import pytest from mas_conformance import statute_cases, statute_document from mas_core.statute import ( ERROR, WARNING, InheritanceCycle, StatuteInvalid, build_statute, lint, resolve_inheritance, ) CASES = statute_cases() @pytest.mark.parametrize("case", CASES, ids=[c["id"] for c in CASES]) def test_statute_case(case): doc = statute_document(case["file"]) findings = lint(doc, case["host"]) errors = [f for f in findings if f.severity == ERROR] if case["expect"] == "valid": assert not errors, errors build_statute(doc, case["host"]) assert set(case.get("warnings", [])) <= {f.code for f in findings if f.severity == WARNING} else: assert errors and {f.layer for f in errors} == {case["expect"]} assert set(case.get("codes", [])) <= {f.code for f in errors} with pytest.raises(StatuteInvalid) as exc: build_statute(doc, case["host"]) assert exc.value.layer == case["expect"] def test_schema_valid_but_semantically_rejected(): doc = statute_document("semantic-p2-disabled-modes.json") assert not [f for f in lint(doc) if f.layer == "schema"] with pytest.raises(StatuteInvalid): build_statute(doc) def _doc(ns, inherits=None, **over): d = {"mas_version": "0.1", "namespace": ns, "profiles": {"p1": True, "p2": True}, "equivalence": {"local_part_case": "exact", "dot_folding": False}} if inherits: d["inherits"] = inherits d.update(over) return d def url(ns): return f"https://{ns}/.well-known/mas" def test_inheritance_defaults_only(): parent = build_statute(_doc("parent.example", resource_types={"ticket": {"enabled": True}, "invoice": {"enabled": True}}, interaction_modes={"callback": {"enabled": True}}, addresses={"support": {"kind": "function"}})) child = build_statute(_doc("child.example", url("parent.example"), resource_types={"invoice": {"enabled": False}})) merged = resolve_inheritance(child, url("child.example"), lambda u: parent) assert merged.namespace == "child.example" assert merged.resource_type_enabled("ticket") # inherited default assert not merged.resource_type_enabled("invoice") # child overrides assert merged.interaction_mode_enabled("callback") assert "support" not in merged.addresses # registry never inherits assert merged.inherited_from == (url("parent.example"),) @pytest.mark.parametrize("length", [2, 3, 4]) def test_inheritance_cycles(length): names = [f"n{i}.example" for i in range(length)] docs = {url(n): build_statute(_doc(n, url(names[(i + 1) % length]))) for i, n in enumerate(names)} with pytest.raises(InheritanceCycle) as exc: resolve_inheritance(docs[url(names[0])], url(names[0]), docs.__getitem__) assert exc.value.chain[0] == exc.value.chain[-1]