diff --git a/src/backend/tests/test_vision_boundary.py b/src/backend/tests/test_vision_boundary.py new file mode 100644 index 0000000..b230fa0 --- /dev/null +++ b/src/backend/tests/test_vision_boundary.py @@ -0,0 +1,44 @@ +"""Il server non importa VisionSuite, e questo lo verifica. + +Senza qualcuno che lo controlli, il confine si perde in silenzio: basta un +import comodo perché l'immagine dell'API torni da cinque gigabyte e il motivo +per cui il worker esiste svanisca senza che nessuna prova diventi rossa. +""" +import ast +from pathlib import Path + +BACKEND = Path(__file__).resolve().parents[1] +FORBIDDEN = {"visionsuite", "pm2d", "dxf_compare", "Acquire", "torch"} + + +def _imported_roots(source: Path) -> set[str]: + tree = ast.parse(source.read_text(encoding="utf-8"), filename=str(source)) + roots: set[str] = set() + for node in ast.walk(tree): + if isinstance(node, ast.Import): + roots.update(alias.name.split(".")[0] for alias in node.names) + elif isinstance(node, ast.ImportFrom) and node.module and node.level == 0: + roots.add(node.module.split(".")[0]) + return roots + + +def test_the_server_never_imports_visionsuite(): + offenders = [] + for source in BACKEND.rglob("*.py"): + if "tests" in source.parts or "migrations" in source.parts: + continue + forbidden = _imported_roots(source) & FORBIDDEN + if forbidden: + offenders.append(f"{source.relative_to(BACKEND)}: {sorted(forbidden)}") + + assert offenders == [], ( + "il server deve restare cieco alla visione; usa il worker via HTTP:\n" + + "\n".join(offenders) + ) + + +def test_the_submodule_is_pinned(): + """Server e stazione devono montare lo stesso commit: qui c'è la fonte.""" + gitmodules = Path(__file__).resolve().parents[3] / ".gitmodules" + assert gitmodules.exists(), "vendor/visionsuite non è un sottomodulo" + assert "vendor/visionsuite" in gitmodules.read_text(encoding="utf-8")