ouroboros/tests/test_domain_report.py
Anton Razzhigaev 98ca8a13d5 Retire completed campaign artifacts and keep repository reports explicit
Remove completed campaign records, one-time adoption/transplant machinery and
incidental line floors. Keep current contracts and generated inventories with
their readers, and direct optional domain reports to stdout or an explicit file.
Document continuing-purpose review in the existing handbook and checklists.

No version bump; ordinary release gates and runtime behavior are preserved.

Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
2026-09-18 01:07:51 +03:00

102 lines
3.6 KiB
Python

"""The optional graph report writes only to the requested output surface."""
from __future__ import annotations
import os
import pathlib
import shutil
import subprocess
import sys
import pytest
pytestmark = pytest.mark.serial # Real Git and Python subprocesses.
REPO = pathlib.Path(__file__).resolve().parents[1]
@pytest.fixture
def report_repo(tmp_path):
root = tmp_path / "repo"
(root / "scripts").mkdir(parents=True)
(root / "ouroboros").mkdir()
for name in ("domain_report.py", "domain_graph.py"):
shutil.copyfile(REPO / "scripts" / name, root / "scripts" / name)
(root / "ouroboros/a.py").write_text("import ouroboros.b\n", encoding="utf-8")
(root / "ouroboros/b.py").write_text("import ouroboros.a\n", encoding="utf-8")
(root / "ouroboros/domains.toml").write_text(
'[domains]\nD01 = "Первый"\nD02 = "Second"\n'
'[modules]\n"ouroboros/a.py" = "D01"\n"ouroboros/b.py" = "D02"\n',
encoding="utf-8",
)
for args in (
["init"],
["add", "."],
["-c", "user.name=Test", "-c", "user.email=test@example.invalid",
"-c", "commit.gpgsign=false", "commit", "-m", "fixture"],
):
subprocess.run(["git", *args], cwd=root, check=True, capture_output=True,
encoding="utf-8")
return root
def _files(root):
return {
path.relative_to(root): path.read_bytes()
for path in root.rglob("*")
if path.is_file() and ".git" not in path.relative_to(root).parts
}
def _run(root, *args):
# The report's UTF-8 output must also survive a non-UTF-8 host default.
return subprocess.run(
[sys.executable, "-B", str(root / "scripts/domain_report.py"), *args],
cwd=root, capture_output=True, encoding="utf-8",
env={**os.environ, "PYTHONIOENCODING": "ascii"},
)
def _assert_report(text):
assert text.startswith("# Domain quotient report (report-only)\n")
assert "Generated by `scripts/domain_report.py`" in text
assert "analyzed-inputs content fingerprint: sha256" in text
assert "`ouroboros/a.py` → `ouroboros/b.py` (line 1)" in text
assert "D01 — Первый" in text
assert text.endswith("\n") and not text.endswith("\n\n")
assert "\nstrict:" not in text and "\n cycle:" not in text
def test_report_defaults_to_stdout_without_repository_writes(report_repo):
before = _files(report_repo)
result = _run(report_repo)
assert result.returncode == 0, result.stderr
_assert_report(result.stdout)
assert "strict: 2 module edges, 2 domain edges, 1 cycle groups" in result.stderr
assert "cycle: D01 ⇄ D02" in result.stderr
assert _files(report_repo) == before
def test_report_writes_only_to_explicit_output(report_repo, tmp_path):
before = _files(report_repo)
output = tmp_path / "reports" / "graph.md"
result = _run(report_repo, "--output", str(output))
assert result.returncode == 0, result.stderr
assert result.stdout == ""
_assert_report(output.read_text(encoding="utf-8"))
assert f"wrote {output}" in result.stderr
assert "strict: 2 module edges" in result.stderr
assert _files(report_repo) == before
@pytest.mark.parametrize("broken", ["manifest", "source"])
def test_untrustworthy_inputs_return_two_without_a_report(report_repo, broken):
if broken == "manifest":
(report_repo / "ouroboros/domains.toml").unlink()
else:
(report_repo / "ouroboros/a.py").write_text("def (\n", encoding="utf-8")
result = _run(report_repo)
assert result.returncode == 2, result.stderr
assert result.stdout == ""
assert ("missing manifest:" if broken == "manifest" else "cannot parse:") in result.stderr