Files
felhom-controller/controller/scripts/test_controller_gates.py
T
admin 55868cb3e0
gates / gates (push) Successful in 46s
The decoy suite is a gate of the full run (R-1116); no code change
controller/scripts/test_gate_decoys.py is now controller_gates.py's `gate-decoys` row: blocking, full run only
(~22 s, 53 cases, and it edits real files in the tree for a moment, so never the hook). Declared in its own
COVERS; test_controller_gates.py pins it. Red-proved: debug-routes/comment flipped to expect accept ->
CONVICTED: gate-decoys; restored, green. gates.md's "--fast is all of them" corrected.

Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-17 11:01:40 +02:00

85 lines
3.9 KiB
Python

# -*- coding: utf-8 -*-
"""Seam test for scripts/controller_gates.py.
Run from controller/: python3 scripts/test_controller_gates.py
WHY THIS EXISTS. An entry point is a seam by definition: a runner that LISTS a gate but never
executes it is inert and fully green, and this project has shipped an inert seam four times. So
the assertion is on each member gate's OWN distinctive stdout — never on the runner's summary
line, which the runner can print without ever calling anything — plus the exit code, which is a
runner's actual effect.
Red-proofed 2026-08-02: replacing run_gate's body with `return 0` (the inert runner) turns
test_every_member_gate_actually_ran red while the summary still prints "all controller gates OK".
"""
import os
import subprocess
import sys
import unittest
SCRIPTS = os.path.dirname(os.path.abspath(__file__))
CTRL = os.path.dirname(SCRIPTS)
ENTRY = os.path.join(SCRIPTS, "controller_gates.py")
# (label, a substring only THAT gate can print)
FINGERPRINTS = [
("template-id", "integrity gate OK — every JS element-ID reference"),
("emoji", "emoji gate OK"),
("native-confirm", "native-confirm gate OK"),
("offbox-rename", "offbox rename gate OK"),
("app-row-dedup", "app_row_dedup_gate: OK"),
("mojibake", "mojibake_gate: OK"),
("docker-v", "docker -v gate OK"),
("debug-routes", "debug route gate OK"),
("reuse-refs", "cited paths — exact"),
("minagent-header", "minagent header gate OK"),
]
class ControllerGatesTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
p = subprocess.run([sys.executable, ENTRY, "--fast"], cwd=CTRL,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
cls.rc = p.returncode
cls.out = p.stdout.decode("utf-8", "replace")
def test_exit_code_is_zero(self):
self.assertEqual(self.rc, 0, self.out)
def test_every_member_gate_actually_ran(self):
for label, fingerprint in FINGERPRINTS:
self.assertIn(fingerprint, self.out,
"gate %r is listed but its own output never appeared — an inert runner "
"prints the summary without calling anything:\n%s" % (label, self.out))
def test_shared_reuse_checker_is_not_copied_into_this_repo(self):
"""It lives in felhom.eu/scripts/ and is invoked across the workspace. A copy here would
recreate exactly the drift it exists to detect."""
self.assertFalse(os.path.exists(os.path.join(SCRIPTS, "reuse_refs_check.py")),
"reuse_refs_check.py must NOT be copied into this repo")
def test_decoy_suite_is_a_blocking_full_run_gate(self):
"""R-1116: the decoy suite is a gate of the FULL run (blocking), and --fast names it as skipped.
Not --fast: ~22 s, and it edits real files in this tree for a moment (a hook would race other sessions)."""
sys.path.insert(0, SCRIPTS)
import controller_gates as mod
rows = [g for g in mod.GATES if g[0] == "gate-decoys"]
self.assertEqual(len(rows), 1, "gate-decoys is not registered exactly once")
_label, path, _args, fast, blocking = rows[0]
self.assertEqual(os.path.basename(path), "test_gate_decoys.py")
self.assertFalse(fast, "gate-decoys must not be --fast")
self.assertTrue(blocking, "a decoy that stops convicting must fail the run")
self.assertEqual([g[0] for g in mod.GATES if not g[3]], ["gate-decoys"])
self.assertIn("--fast SKIPPED (deliberate periodic runs, never in a hook): gate-decoys", self.out)
def test_unknown_argument_is_rejected(self):
p = subprocess.run([sys.executable, ENTRY, "--nope"], cwd=CTRL,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
self.assertEqual(p.returncode, 2, p.stdout.decode("utf-8", "replace"))
if __name__ == "__main__":
unittest.main(verbosity=2)