bf1798479d
PATH_RE gains .md. The false-positive walk across all four repos found one: an audit document cited by app-catalog's REUSE.md, hidden by the evidence-copy exclusion — excluded trees are now walked for .md documents only, so a .go evidence copy there still never satisfies a citation. The KNOWN HOLE decoy now expects a conviction. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
217 lines
10 KiB
Python
217 lines
10 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""Fixture tests for scripts/reuse_refs_check.py — one per row of its resolution table, plus the
|
|
kill condition.
|
|
|
|
Run: python3 scripts/test_reuse_refs_check.py
|
|
|
|
THE ONE THAT MATTERS is test_absent_path_fails (Scenario E). The 2026-08-02 change taught the
|
|
checker to resolve suffixes and sibling repos, which turned 13 findings green in one step. A
|
|
checker made green by being made BLIND is a failure this project has shipped before, so the
|
|
ability to still fail is pinned here, and the assertion is on the EXIT CODE — the effect — not on
|
|
the summary text, which the checker can print without having decided anything.
|
|
"""
|
|
import importlib.util
|
|
import io
|
|
import os
|
|
import shutil
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
|
|
SCRIPT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "reuse_refs_check.py")
|
|
|
|
|
|
def load_checker():
|
|
"""Fresh module per test — the checker keeps a global failure count and an index cache."""
|
|
spec = importlib.util.spec_from_file_location("reuse_refs_check_under_test", SCRIPT)
|
|
mod = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(mod)
|
|
return mod
|
|
|
|
|
|
def write(path, text=""):
|
|
d = os.path.dirname(path)
|
|
if d and not os.path.isdir(d):
|
|
os.makedirs(d)
|
|
with io.open(path, "w", encoding="utf-8") as f:
|
|
f.write(text)
|
|
|
|
|
|
class ReuseRefsCheckTest(unittest.TestCase):
|
|
|
|
def setUp(self):
|
|
self.tmp = tempfile.mkdtemp(prefix="reuse-refs-")
|
|
self.root = os.path.join(self.tmp, "myrepo")
|
|
write(os.path.join(self.root, ".git"), "gitdir: elsewhere\n")
|
|
|
|
def tearDown(self):
|
|
shutil.rmtree(self.tmp, ignore_errors=True)
|
|
|
|
# ── harness ──────────────────────────────────────────────────────────────────
|
|
def run_check(self, *roots):
|
|
"""Returns (exit_code, stdout). Exit code is the assertion that counts."""
|
|
mod = load_checker()
|
|
buf = io.StringIO()
|
|
real = sys.stdout
|
|
sys.stdout = buf
|
|
try:
|
|
rc = mod.main(list(roots) or [self.root])
|
|
finally:
|
|
sys.stdout = real
|
|
return rc, buf.getvalue()
|
|
|
|
def reuse(self, body):
|
|
write(os.path.join(self.root, "REUSE.md"), body)
|
|
|
|
def sibling(self, name):
|
|
p = os.path.join(self.tmp, name)
|
|
write(os.path.join(p, ".git"), "gitdir: elsewhere\n")
|
|
return p
|
|
|
|
# ── row 1: exact ─────────────────────────────────────────────────────────────
|
|
def test_exact_match_is_silent_and_passes(self):
|
|
write(os.path.join(self.root, "a", "b.go"), "package a\n")
|
|
self.reuse("see `a/b.go` for the thing\n")
|
|
rc, out = self.run_check()
|
|
self.assertEqual(rc, 0, out)
|
|
self.assertIn("exact 1", out)
|
|
self.assertNotIn("note [", out) # an exact hit prints no note
|
|
|
|
# ── row 2: suffix ────────────────────────────────────────────────────────────
|
|
def test_package_shorthand_resolves_by_suffix(self):
|
|
write(os.path.join(self.root, "controller", "internal", "pkg", "x.go"), "package pkg\n")
|
|
self.reuse("see `pkg/x.go`\n")
|
|
rc, out = self.run_check()
|
|
self.assertEqual(rc, 0, out)
|
|
self.assertIn("resolved by suffix", out)
|
|
self.assertIn("controller/internal/pkg/x.go", out)
|
|
self.assertIn("suffix 1", out)
|
|
|
|
# ── row 3: ambiguous — real citation, imprecise shorthand; NOT a failure ─────
|
|
def test_two_suffix_matches_are_ambiguous_not_fatal(self):
|
|
write(os.path.join(self.root, "one", "pkg", "x.go"), "package pkg\n")
|
|
write(os.path.join(self.root, "two", "pkg", "x.go"), "package pkg\n")
|
|
self.reuse("see `pkg/x.go`\n")
|
|
rc, out = self.run_check()
|
|
self.assertEqual(rc, 0, out)
|
|
self.assertIn("AMBIGUOUS", out)
|
|
self.assertIn("one/pkg/x.go", out)
|
|
self.assertIn("two/pkg/x.go", out)
|
|
self.assertIn("ambiguous 1", out)
|
|
|
|
# ── row 4: cross-repo, by suffix in a sibling ────────────────────────────────
|
|
def test_sibling_repo_resolution(self):
|
|
sib = self.sibling("otherrepo")
|
|
write(os.path.join(sib, "hub", "internal", "wgsync", "reconciler.go"), "package wgsync\n")
|
|
self.reuse("see `wgsync/reconciler.go`\n")
|
|
rc, out = self.run_check()
|
|
self.assertEqual(rc, 0, out)
|
|
self.assertIn("cross-repo", out)
|
|
self.assertIn("otherrepo", out)
|
|
self.assertIn("cross-repo 1", out)
|
|
|
|
# ── row 4b: cross-repo where the token CARRIES the sibling's repo name ───────
|
|
def test_sibling_repo_name_prefixed_token(self):
|
|
sib = self.sibling("felhom.eu")
|
|
write(os.path.join(sib, "scripts", "site_gates.py"), "# gate\n")
|
|
self.reuse("run `felhom.eu/scripts/site_gates.py`\n")
|
|
rc, out = self.run_check()
|
|
self.assertEqual(rc, 0, out)
|
|
self.assertIn("cross-repo", out)
|
|
|
|
def test_non_git_sibling_is_not_searched(self):
|
|
plain = os.path.join(self.tmp, "notarepo") # no .git — not a repo, must not resolve
|
|
write(os.path.join(plain, "pkg", "x.go"), "package pkg\n")
|
|
self.reuse("see `pkg/x.go`\n")
|
|
rc, out = self.run_check()
|
|
self.assertNotEqual(rc, 0, out)
|
|
|
|
# ── row 5: THE KILL CONDITION (Scenario E) ──────────────────────────────────
|
|
def test_absent_path_fails(self):
|
|
write(os.path.join(self.root, "internal", "present.go"), "package internal\n")
|
|
self.reuse("line one\nsee `internal/definitely_absent_xyz.go`\n")
|
|
rc, out = self.run_check()
|
|
self.assertNotEqual(rc, 0, "a citation that exists NOWHERE must fail:\n" + out)
|
|
self.assertIn("definitely_absent_xyz.go", out)
|
|
self.assertIn("line 2", out) # names the line
|
|
self.assertIn("FAILED 1", out)
|
|
|
|
def test_failure_lists_every_resolution_attempted(self):
|
|
"""CLAUDE.md standing rule: a 'not found' claim must name what was tried."""
|
|
self.sibling("otherrepo")
|
|
self.reuse("see `internal/definitely_absent_xyz.go`\n")
|
|
rc, out = self.run_check()
|
|
self.assertNotEqual(rc, 0, out)
|
|
self.assertIn("tried: repo-relative myrepo/internal/definitely_absent_xyz.go", out)
|
|
self.assertIn("tried: suffix search over", out)
|
|
self.assertIn("tried: sibling otherrepo", out)
|
|
|
|
# ── evidence trees are not the file ─────────────────────────────────────────
|
|
def test_evidence_copy_does_not_satisfy_a_citation(self):
|
|
write(os.path.join(self.root, "documentation", "audits", "pkg", "x.go"), "package pkg\n")
|
|
write(os.path.join(self.root, "documentation", "tests", "pkg", "y.go"), "package pkg\n")
|
|
self.reuse("see `pkg/x.go` and `pkg/y.go`\n")
|
|
rc, out = self.run_check()
|
|
self.assertNotEqual(rc, 0, "an audits/ or documentation/tests/ copy must NOT resolve:\n" + out)
|
|
self.assertIn("FAILED 2", out)
|
|
|
|
# ── R-422: document citations are checked ───────────────────────────────────
|
|
def test_absent_md_citation_fails(self):
|
|
"""The measured hole: a rotted .md citation passed because .md was not a checked extension."""
|
|
self.reuse("see `documentation/architecture/99-does-not-exist.md`\n")
|
|
rc, out = self.run_check()
|
|
self.assertNotEqual(rc, 0, "a .md citation that exists nowhere must fail:\n" + out)
|
|
self.assertIn("99-does-not-exist.md", out)
|
|
|
|
def test_md_citation_resolves_including_under_audits(self):
|
|
"""An audit DOCUMENT is the cited thing, not an evidence copy — it must resolve (the one false
|
|
positive the 2026-10-05 walk found, in app-catalog's REUSE.md)."""
|
|
write(os.path.join(self.root, "documentation", "architecture", "05-hub.md"), "# x\n")
|
|
write(os.path.join(self.root, "documentation", "audits", "SPIKE-x.md"), "# y\n")
|
|
self.reuse("see `documentation/architecture/05-hub.md` and `documentation/audits/SPIKE-x.md`\n")
|
|
rc, out = self.run_check()
|
|
self.assertEqual(rc, 0, out)
|
|
|
|
def test_audits_still_hide_code_copies_when_docs_are_indexed(self):
|
|
"""Indexing .md under audits/ must not let a .go evidence copy there resolve."""
|
|
write(os.path.join(self.root, "documentation", "audits", "pkg", "x.go"), "package pkg\n")
|
|
write(os.path.join(self.root, "documentation", "audits", "pkg", "notes.md"), "# n\n")
|
|
self.reuse("see `pkg/x.go`\n")
|
|
rc, out = self.run_check()
|
|
self.assertNotEqual(rc, 0, out)
|
|
|
|
# ── a clone in isolation must still check itself ────────────────────────────
|
|
def test_no_siblings_is_not_a_failure(self):
|
|
write(os.path.join(self.root, "a", "b.go"), "package a\n")
|
|
self.reuse("see `a/b.go`\n")
|
|
rc, out = self.run_check()
|
|
self.assertEqual(rc, 0, out)
|
|
self.assertIn("siblings searched: none", out)
|
|
|
|
def test_missing_reuse_md_fails(self):
|
|
rc, out = self.run_check()
|
|
self.assertNotEqual(rc, 0, out)
|
|
self.assertIn("no REUSE.md", out)
|
|
|
|
# ── globs stay conventions, not refs ────────────────────────────────────────
|
|
def test_glob_is_not_a_citation(self):
|
|
self.reuse("the gates are `scripts/*.py`\n")
|
|
rc, out = self.run_check()
|
|
self.assertEqual(rc, 0, out)
|
|
self.assertIn("0 cited paths", out)
|
|
|
|
# ── no args → usage, exit 2 ─────────────────────────────────────────────────
|
|
def test_no_args_is_usage_exit_2(self):
|
|
mod = load_checker()
|
|
buf, real = io.StringIO(), sys.stdout
|
|
sys.stdout = buf
|
|
try:
|
|
rc = mod.main([])
|
|
finally:
|
|
sys.stdout = real
|
|
self.assertEqual(rc, 2)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main(verbosity=2)
|