mirror of
https://github.com/elder-plinius/OBLITERATUS.git
synced 2026-08-17 16:37:30 +02:00
test: enforce Wave A quality lock
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Validate the source-to-test risk map and conditional coverage graph."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
|
||||
RISK_CLASSES = {"cpu-contract", "mixed-runtime", "conditional-runtime"}
|
||||
|
||||
|
||||
def _load_object(path: Path, label: str, errors: list[str]) -> dict[str, Any]:
|
||||
try:
|
||||
value = json.loads(path.read_text(encoding="utf-8"))
|
||||
except (OSError, json.JSONDecodeError) as exc:
|
||||
errors.append(f"cannot read {label}: {exc}")
|
||||
return {}
|
||||
if not isinstance(value, dict):
|
||||
errors.append(f"{label} root must be an object")
|
||||
return {}
|
||||
return value
|
||||
|
||||
|
||||
def validate(risk_path: Path, quality_path: Path, conditional_path: Path) -> list[str]:
|
||||
"""Return structural and cross-policy failures for the risk map."""
|
||||
|
||||
errors: list[str] = []
|
||||
risk = _load_object(risk_path, "test risk map", errors)
|
||||
quality = _load_object(quality_path, "quality policy", errors)
|
||||
conditional = _load_object(conditional_path, "conditional policy", errors)
|
||||
if errors:
|
||||
return errors
|
||||
|
||||
if risk.get("schema_version") != 1:
|
||||
errors.append("test risk map schema_version must be 1")
|
||||
if not isinstance(risk.get("owner"), str) or not risk["owner"].strip():
|
||||
errors.append("test risk map requires a non-empty owner")
|
||||
|
||||
gates = conditional.get("gates")
|
||||
gate_by_id = {
|
||||
gate.get("id"): gate
|
||||
for gate in gates if isinstance(gate, dict) and isinstance(gate.get("id"), str)
|
||||
} if isinstance(gates, list) else {}
|
||||
|
||||
modules = risk.get("modules")
|
||||
if not isinstance(modules, list) or not modules:
|
||||
return errors + ["test risk map modules must be a non-empty list"]
|
||||
|
||||
module_by_path: dict[str, dict[str, Any]] = {}
|
||||
for index, module in enumerate(modules):
|
||||
label = f"risk module {index}"
|
||||
if not isinstance(module, dict):
|
||||
errors.append(f"{label} must be an object")
|
||||
continue
|
||||
path = module.get("path")
|
||||
if not isinstance(path, str) or not path:
|
||||
errors.append(f"{label} requires a non-empty path")
|
||||
continue
|
||||
if path in module_by_path:
|
||||
errors.append(f"duplicate risk module path: {path}")
|
||||
module_by_path[path] = module
|
||||
if not Path(path).is_file():
|
||||
errors.append(f"risk module maps missing source path: {path}")
|
||||
if module.get("risk_class") not in RISK_CLASSES:
|
||||
errors.append(f"risk module {path} has invalid risk_class")
|
||||
if not isinstance(module.get("risk"), str) or not module["risk"].strip():
|
||||
errors.append(f"risk module {path} requires a non-empty risk")
|
||||
|
||||
tests = module.get("required_tests")
|
||||
if not isinstance(tests, list) or not tests:
|
||||
errors.append(f"risk module {path} requires at least one test")
|
||||
else:
|
||||
for test_path in tests:
|
||||
if not isinstance(test_path, str) or not test_path.startswith("tests/"):
|
||||
errors.append(f"risk module {path} has invalid test path: {test_path!r}")
|
||||
elif not Path(test_path).is_file():
|
||||
errors.append(f"risk module {path} maps missing test path: {test_path}")
|
||||
|
||||
module_gates = module.get("conditional_gates")
|
||||
if not isinstance(module_gates, list):
|
||||
errors.append(f"risk module {path} conditional_gates must be a list")
|
||||
continue
|
||||
if len(module_gates) != len(set(module_gates)):
|
||||
errors.append(f"risk module {path} has duplicate conditional gates")
|
||||
for gate_id in module_gates:
|
||||
gate = gate_by_id.get(gate_id)
|
||||
if gate is None:
|
||||
errors.append(f"risk module {path} references unknown gate {gate_id}")
|
||||
elif path not in gate.get("coverage_paths", []):
|
||||
errors.append(f"risk module {path} is not covered by gate {gate_id}")
|
||||
|
||||
exclusions = quality.get("mature_cpu_scope", {}).get("exclusions", [])
|
||||
if not isinstance(exclusions, list):
|
||||
errors.append("quality policy exclusions must be a list")
|
||||
exclusions = []
|
||||
for exclusion in exclusions:
|
||||
if not isinstance(exclusion, dict):
|
||||
errors.append("quality policy exclusion must be an object")
|
||||
continue
|
||||
path = exclusion.get("path")
|
||||
gate_id = exclusion.get("conditional_gate")
|
||||
module = module_by_path.get(path)
|
||||
if module is None:
|
||||
errors.append(f"CPU exclusion is missing from test risk map: {path}")
|
||||
elif gate_id not in module.get("conditional_gates", []):
|
||||
errors.append(f"CPU exclusion {path} is missing conditional gate {gate_id}")
|
||||
|
||||
critical_paths = quality.get("critical_cpu_paths", [])
|
||||
if not isinstance(critical_paths, list):
|
||||
errors.append("quality policy critical_cpu_paths must be a list")
|
||||
critical_paths = []
|
||||
for path in critical_paths:
|
||||
if path not in module_by_path:
|
||||
errors.append(f"critical CPU path is missing from test risk map: {path}")
|
||||
|
||||
for gate_id, gate in gate_by_id.items():
|
||||
for path in gate.get("coverage_paths", []):
|
||||
module = module_by_path.get(path)
|
||||
if module is None:
|
||||
errors.append(f"conditional path is missing from test risk map: {path}")
|
||||
elif gate_id not in module.get("conditional_gates", []):
|
||||
errors.append(f"risk module {path} is missing conditional gate {gate_id}")
|
||||
return errors
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--risk-map", type=Path, default=Path("ci/test-risk-map.json"))
|
||||
parser.add_argument("--quality", type=Path, default=Path("ci/test-quality-policy.json"))
|
||||
parser.add_argument(
|
||||
"--conditional",
|
||||
type=Path,
|
||||
default=Path("ci/conditional-test-policy.json"),
|
||||
)
|
||||
args = parser.parse_args()
|
||||
errors = validate(args.risk_map, args.quality, args.conditional)
|
||||
if errors:
|
||||
for error in errors:
|
||||
print(f"ERROR: {error}")
|
||||
return 1
|
||||
print("test risk map: valid")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user