mirror of
https://github.com/elder-plinius/OBLITERATUS.git
synced 2026-08-17 16:37:30 +02:00
337 lines
14 KiB
Python
337 lines
14 KiB
Python
"""Executable contracts for the source-to-test risk map."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import sys
|
|
from copy import deepcopy
|
|
from pathlib import Path
|
|
|
|
from scripts import check_test_risk_map
|
|
|
|
|
|
ROOT = Path(__file__).parents[1]
|
|
|
|
|
|
def _write(path: Path, value: object) -> Path:
|
|
path.write_text(json.dumps(value), encoding="utf-8")
|
|
return path
|
|
|
|
|
|
def test_committed_test_risk_map_is_complete():
|
|
assert check_test_risk_map.validate(
|
|
ROOT / "ci" / "test-risk-map.json",
|
|
ROOT / "ci" / "test-quality-policy.json",
|
|
ROOT / "ci" / "conditional-test-policy.json",
|
|
) == []
|
|
|
|
|
|
def test_risk_map_rejects_duplicate_missing_and_unowned_modules(tmp_path):
|
|
risk = json.loads((ROOT / "ci" / "test-risk-map.json").read_text())
|
|
risk["owner"] = ""
|
|
duplicate = deepcopy(
|
|
next(module for module in risk["modules"] if module["path"] == "obliteratus/cli.py")
|
|
)
|
|
duplicate["required_tests"] = ["tests/missing.py"]
|
|
duplicate["risk_class"] = "unknown"
|
|
risk["modules"].append(duplicate)
|
|
|
|
errors = check_test_risk_map.validate(
|
|
_write(tmp_path / "risk.json", risk),
|
|
ROOT / "ci" / "test-quality-policy.json",
|
|
ROOT / "ci" / "conditional-test-policy.json",
|
|
)
|
|
|
|
assert "test risk map requires a non-empty owner" in errors
|
|
assert "duplicate risk module path: obliteratus/cli.py" in errors
|
|
assert "risk module obliteratus/cli.py has invalid risk_class" in errors
|
|
assert "risk module obliteratus/cli.py maps missing test path: tests/missing.py" in errors
|
|
|
|
|
|
def test_risk_map_rejects_missing_exclusion_and_gate_mapping(tmp_path):
|
|
risk = json.loads((ROOT / "ci" / "test-risk-map.json").read_text())
|
|
risk["modules"] = [
|
|
module for module in risk["modules"] if module["path"] != "obliteratus/remote.py"
|
|
]
|
|
loader = next(
|
|
module for module in risk["modules"] if module["path"] == "obliteratus/models/loader.py"
|
|
)
|
|
loader["conditional_gates"].remove("cuda-runtime")
|
|
|
|
errors = check_test_risk_map.validate(
|
|
_write(tmp_path / "risk.json", risk),
|
|
ROOT / "ci" / "test-quality-policy.json",
|
|
ROOT / "ci" / "conditional-test-policy.json",
|
|
)
|
|
|
|
assert "CPU exclusion is missing from test risk map: obliteratus/remote.py" in errors
|
|
assert "conditional path is missing from test risk map: obliteratus/remote.py" in errors
|
|
assert "risk module obliteratus/models/loader.py is missing conditional gate cuda-runtime" in errors
|
|
|
|
|
|
def test_risk_map_rejects_gate_that_does_not_cover_module(tmp_path):
|
|
risk = json.loads((ROOT / "ci" / "test-risk-map.json").read_text())
|
|
cli = next(module for module in risk["modules"] if module["path"] == "obliteratus/cli.py")
|
|
cli["conditional_gates"] = ["remote-execution", "unknown-gate"]
|
|
|
|
errors = check_test_risk_map.validate(
|
|
_write(tmp_path / "risk.json", risk),
|
|
ROOT / "ci" / "test-quality-policy.json",
|
|
ROOT / "ci" / "conditional-test-policy.json",
|
|
)
|
|
|
|
assert "risk module obliteratus/cli.py is not covered by gate remote-execution" in errors
|
|
assert "risk module obliteratus/cli.py references unknown gate unknown-gate" in errors
|
|
|
|
|
|
def test_risk_map_cannot_drop_critical_cpu_path(tmp_path):
|
|
risk = json.loads((ROOT / "ci" / "test-risk-map.json").read_text())
|
|
risk["modules"] = [
|
|
module for module in risk["modules"] if module["path"] != "obliteratus/cli.py"
|
|
]
|
|
|
|
errors = check_test_risk_map.validate(
|
|
_write(tmp_path / "risk.json", risk),
|
|
ROOT / "ci" / "test-quality-policy.json",
|
|
ROOT / "ci" / "conditional-test-policy.json",
|
|
)
|
|
|
|
assert "critical CPU path is missing from test risk map: obliteratus/cli.py" in errors
|
|
|
|
|
|
def test_contract_inventory_rejects_unmapped_and_multiply_owned_source(tmp_path):
|
|
risk = json.loads((ROOT / "ci" / "test-risk-map.json").read_text())
|
|
risk["source_inventory"]["roots"].append("scripts/check_test_risk_map.py")
|
|
second_surface = risk["contract_surfaces"][1]
|
|
second_surface["paths"].append("app.py")
|
|
|
|
errors = check_test_risk_map.validate(
|
|
_write(tmp_path / "risk.json", risk),
|
|
ROOT / "ci" / "test-quality-policy.json",
|
|
ROOT / "ci" / "conditional-test-policy.json",
|
|
)
|
|
|
|
assert "unmapped production source path: scripts/check_test_risk_map.py" in errors
|
|
assert (
|
|
"production source path has multiple contract owners: "
|
|
"app.py (package-entrypoints, core-pipeline)"
|
|
) in errors
|
|
|
|
|
|
def test_contract_surface_requires_valid_identity_contracts_and_tests(tmp_path):
|
|
risk = json.loads((ROOT / "ci" / "test-risk-map.json").read_text())
|
|
surface = risk["contract_surfaces"][0]
|
|
surface["id"] = "Invalid surface"
|
|
surface["owner"] = ""
|
|
surface["description"] = ""
|
|
surface["contract_types"] = ["package-entrypoint", "invented-contract", {"bad": "type"}]
|
|
surface["required_tests"] = ["tests/missing.py"]
|
|
|
|
errors = check_test_risk_map.validate(
|
|
_write(tmp_path / "risk.json", risk),
|
|
ROOT / "ci" / "test-quality-policy.json",
|
|
ROOT / "ci" / "conditional-test-policy.json",
|
|
)
|
|
|
|
assert "contract surface 0 has invalid id: 'Invalid surface'" in errors
|
|
assert "contract surface index-0 requires a non-empty owner" in errors
|
|
assert "contract surface index-0 requires a non-empty description" in errors
|
|
assert "contract surface index-0 has invalid contract type: 'invented-contract'" in errors
|
|
assert "contract surface index-0 has invalid contract type: {'bad': 'type'}" in errors
|
|
assert "contract surface index-0 maps missing test path: tests/missing.py" in errors
|
|
|
|
|
|
def test_risk_module_must_resolve_to_contract_owner(tmp_path):
|
|
risk = json.loads((ROOT / "ci" / "test-risk-map.json").read_text())
|
|
surface = next(
|
|
item for item in risk["contract_surfaces"] if item["id"] == "public-interface-and-services"
|
|
)
|
|
surface["paths"].remove("obliteratus/cli.py")
|
|
|
|
errors = check_test_risk_map.validate(
|
|
_write(tmp_path / "risk.json", risk),
|
|
ROOT / "ci" / "test-quality-policy.json",
|
|
ROOT / "ci" / "conditional-test-policy.json",
|
|
)
|
|
|
|
assert "unmapped production source path: obliteratus/cli.py" in errors
|
|
assert "risk module is missing a contract owner: obliteratus/cli.py" in errors
|
|
|
|
|
|
def test_risk_map_rejects_legacy_schema_and_invalid_inventory_roots(tmp_path):
|
|
risk = json.loads((ROOT / "ci" / "test-risk-map.json").read_text())
|
|
risk["schema_version"] = 1
|
|
risk["source_inventory"]["roots"] = ["missing-source-root", "/absolute/source.py"]
|
|
risk["source_inventory"]["coverage_roots"] = [
|
|
"obliteratus",
|
|
"obliteratus",
|
|
"missing-coverage-root",
|
|
"/absolute/coverage",
|
|
]
|
|
|
|
errors = check_test_risk_map.validate(
|
|
_write(tmp_path / "risk.json", risk),
|
|
ROOT / "ci" / "test-quality-policy.json",
|
|
ROOT / "ci" / "conditional-test-policy.json",
|
|
)
|
|
|
|
assert "test risk map schema_version must be 2" in errors
|
|
assert "source_inventory root does not exist: missing-source-root" in errors
|
|
assert "source_inventory has invalid root: '/absolute/source.py'" in errors
|
|
assert "test risk map source_inventory has duplicate coverage_roots" in errors
|
|
assert "source_inventory coverage root does not exist: missing-coverage-root" in errors
|
|
assert "source_inventory has invalid coverage root: '/absolute/coverage'" in errors
|
|
|
|
|
|
def test_targeted_risk_module_must_be_inside_measured_coverage_roots(tmp_path):
|
|
risk = json.loads((ROOT / "ci" / "test-risk-map.json").read_text())
|
|
risk["modules"].append(
|
|
{
|
|
"path": "app.py",
|
|
"risk_class": "conditional-runtime",
|
|
"risk": "optional application construction",
|
|
"required_tests": ["tests/conditional/test_operator_ui.py"],
|
|
"conditional_gates": [],
|
|
}
|
|
)
|
|
|
|
errors = check_test_risk_map.validate(
|
|
_write(tmp_path / "risk.json", risk),
|
|
ROOT / "ci" / "test-quality-policy.json",
|
|
ROOT / "ci" / "conditional-test-policy.json",
|
|
)
|
|
|
|
assert "risk module is outside measured coverage roots: app.py" in errors
|
|
|
|
|
|
def test_loader_rejects_unreadable_and_nonobject_documents(tmp_path):
|
|
errors = []
|
|
assert check_test_risk_map._load_object(tmp_path / "missing.json", "fixture", errors) == {}
|
|
assert errors and errors[0].startswith("cannot read fixture:")
|
|
|
|
errors = []
|
|
path = tmp_path / "list.json"
|
|
path.write_text("[]", encoding="utf-8")
|
|
assert check_test_risk_map._load_object(path, "fixture", errors) == {}
|
|
assert errors == ["fixture root must be an object"]
|
|
|
|
|
|
def test_source_inventory_rejects_invalid_shape_duplicates_and_non_python_file(tmp_path):
|
|
risk = json.loads((ROOT / "ci" / "test-risk-map.json").read_text())
|
|
risk["source_inventory"] = {"roots": ["app.py", "app.py", "README.md"]}
|
|
|
|
errors = check_test_risk_map.validate(
|
|
_write(tmp_path / "risk.json", risk),
|
|
ROOT / "ci" / "test-quality-policy.json",
|
|
ROOT / "ci" / "conditional-test-policy.json",
|
|
)
|
|
|
|
assert "test risk map source_inventory has duplicate roots" in errors
|
|
assert "source_inventory root is not Python source: README.md" in errors
|
|
assert any(error.startswith("contract surface ") and "maps source outside inventory" in error for error in errors)
|
|
|
|
risk["source_inventory"] = []
|
|
errors = check_test_risk_map.validate(
|
|
_write(tmp_path / "risk-invalid.json", risk),
|
|
ROOT / "ci" / "test-quality-policy.json",
|
|
ROOT / "ci" / "conditional-test-policy.json",
|
|
)
|
|
assert "test risk map source_inventory must be an object" in errors
|
|
|
|
|
|
def test_contract_surface_rejects_duplicate_and_malformed_fields(tmp_path):
|
|
risk = json.loads((ROOT / "ci" / "test-risk-map.json").read_text())
|
|
first = risk["contract_surfaces"][0]
|
|
second = risk["contract_surfaces"][1]
|
|
second["id"] = first["id"]
|
|
first["contract_types"] = ["public-interface", "public-interface"]
|
|
first["required_tests"] = ["tests/test_cli.py", "tests/test_cli.py", 42]
|
|
first["paths"] = ["app.py", "app.py", 42, "missing.py"]
|
|
|
|
errors = check_test_risk_map.validate(
|
|
_write(tmp_path / "risk.json", risk),
|
|
ROOT / "ci" / "test-quality-policy.json",
|
|
ROOT / "ci" / "conditional-test-policy.json",
|
|
)
|
|
|
|
assert "duplicate contract surface id: package-entrypoints" in errors
|
|
assert "contract surface package-entrypoints has duplicate contract types" in errors
|
|
assert "contract surface package-entrypoints has duplicate test paths" in errors
|
|
assert "contract surface package-entrypoints has invalid test path: 42" in errors
|
|
assert "contract surface package-entrypoints has duplicate source paths" in errors
|
|
assert "contract surface package-entrypoints has invalid source path: 42" in errors
|
|
assert "contract surface package-entrypoints maps source outside inventory: missing.py" in errors
|
|
|
|
|
|
def test_contract_surface_and_module_collections_must_be_nonempty(tmp_path):
|
|
risk = json.loads((ROOT / "ci" / "test-risk-map.json").read_text())
|
|
risk["contract_surfaces"] = []
|
|
risk["modules"] = []
|
|
|
|
errors = check_test_risk_map.validate(
|
|
_write(tmp_path / "risk.json", risk),
|
|
ROOT / "ci" / "test-quality-policy.json",
|
|
ROOT / "ci" / "conditional-test-policy.json",
|
|
)
|
|
|
|
assert "test risk map contract_surfaces must be a non-empty list" in errors
|
|
assert "test risk map modules must be a non-empty list" in errors
|
|
|
|
|
|
def test_risk_modules_reject_malformed_shape_risk_tests_and_gates(tmp_path):
|
|
risk = json.loads((ROOT / "ci" / "test-risk-map.json").read_text())
|
|
original_count = len(risk["modules"])
|
|
malformed = deepcopy(risk["modules"][0])
|
|
malformed["path"] = "obliteratus/cli.py"
|
|
malformed["risk"] = ""
|
|
malformed["required_tests"] = []
|
|
malformed["conditional_gates"] = ["unknown-gate", "unknown-gate", {"bad": "gate"}]
|
|
risk["modules"].extend([None, {}, malformed])
|
|
|
|
errors = check_test_risk_map.validate(
|
|
_write(tmp_path / "risk.json", risk),
|
|
ROOT / "ci" / "test-quality-policy.json",
|
|
ROOT / "ci" / "conditional-test-policy.json",
|
|
)
|
|
|
|
assert f"risk module {original_count} must be an object" in errors
|
|
assert f"risk module {original_count + 1} requires a non-empty path" in errors
|
|
assert "duplicate risk module path: obliteratus/cli.py" in errors
|
|
assert "risk module obliteratus/cli.py requires a non-empty risk" in errors
|
|
assert "risk module obliteratus/cli.py requires at least one test" in errors
|
|
assert "risk module obliteratus/cli.py has duplicate conditional gates" in errors
|
|
assert "risk module obliteratus/cli.py references unknown gate unknown-gate" in errors
|
|
assert "risk module obliteratus/cli.py has invalid conditional gate: {'bad': 'gate'}" in errors
|
|
|
|
|
|
def test_quality_policy_collection_shapes_are_validated(tmp_path):
|
|
risk = ROOT / "ci" / "test-risk-map.json"
|
|
quality = json.loads((ROOT / "ci" / "test-quality-policy.json").read_text())
|
|
quality["mature_cpu_scope"]["exclusions"] = [None]
|
|
quality["critical_cpu_paths"] = "not-a-list"
|
|
|
|
errors = check_test_risk_map.validate(
|
|
risk,
|
|
_write(tmp_path / "quality.json", quality),
|
|
ROOT / "ci" / "conditional-test-policy.json",
|
|
)
|
|
|
|
assert "quality policy exclusion must be an object" in errors
|
|
assert "quality policy critical_cpu_paths must be a list" in errors
|
|
|
|
|
|
def test_main_reports_success_and_failure(tmp_path, monkeypatch, capsys):
|
|
monkeypatch.setattr(sys, "argv", ["check_test_risk_map.py"])
|
|
assert check_test_risk_map.main() == 0
|
|
assert capsys.readouterr().out == "test risk map: valid\n"
|
|
|
|
bad_risk = tmp_path / "bad-risk.json"
|
|
bad_risk.write_text("{}", encoding="utf-8")
|
|
monkeypatch.setattr(
|
|
sys,
|
|
"argv",
|
|
["check_test_risk_map.py", "--risk-map", str(bad_risk)],
|
|
)
|
|
assert check_test_risk_map.main() == 1
|
|
assert "ERROR: test risk map schema_version must be 2" in capsys.readouterr().out
|