"""Run the shared JAV-ID fixture corpus against rc-jav.py. Exits non-zero if any fixture case fails. No third-party dependencies. Usage: python fixtures/run.py """ from __future__ import annotations import importlib.util import json import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[1] FIXTURES = Path(__file__).resolve().parent # rc-jav.py now imports from the `rcjav/` package at ROOT, so the parent dir # must be on sys.path before we exec it. if str(ROOT) not in sys.path: sys.path.insert(0, str(ROOT)) # Synthesized module name avoids collision with the real `rcjav` package # directory (rc-jav.py now imports from it). SPEC = importlib.util.spec_from_file_location("rcjav_script", ROOT / "rc-jav.py") RCJAV = importlib.util.module_from_spec(SPEC) sys.modules[SPEC.name] = RCJAV SPEC.loader.exec_module(RCJAV) def _load(name: str) -> dict: with (FIXTURES / name).open("r", encoding="utf-8") as f: return json.load(f) def _run(label: str, cases: list[dict], fn) -> tuple[int, int]: passed = 0 failed = 0 for case in cases: got = fn(case["input"]) if got == case["expected"]: passed += 1 else: failed += 1 print(f" FAIL [{label}] {case['name']!r}") print(f" input = {case['input']!r}") print(f" expected = {case['expected']!r}") print(f" got = {got!r}") return passed, failed def main() -> int: total_passed = 0 total_failed = 0 for filename, fn_name, fn in [ ("filename-extraction.json", "extract_id", RCJAV.extract_id), ("shared-normalization.json", "normalize_id", RCJAV.normalize_id), ]: doc = _load(filename) cases = doc.get("cases", []) print(f"\n{filename} -> rcjav.{fn_name} ({len(cases)} cases)") p, f = _run(filename, cases, fn) total_passed += p total_failed += f print(f" {p} passed | {f} failed") print() if total_failed: print(f"FAILED: {total_failed} of {total_passed + total_failed} cases") return 1 print(f"OK: all {total_passed} cases passed") return 0 if __name__ == "__main__": sys.exit(main())