mail-address-semantics/tests/test_statute.py
tegwick 59815701c1 Implement MAS v0.1 reference experiment (MAS-WP-0002 M0-M8, M9 first pass)
- mas_core: P2-maximal parser with required_profile, generator, statute
  schema + semantic lint + defaults-only inheritance, exact-host discovery
  with typed failures and same-origin redirects, pure policy resolver
- mas_conformance: vendored spec fixtures (drift-tested) + property and
  statute cases
- mas CLI: parse / explain / discover / lint-statute / test
- mas-gateway: generic mail -> MAS event -> HTTP (MTA pipe + webhook)
- examples: static great-service.example statute, reference ticket service
- docs/experiment-review.md: first-pass findings; live MTA test still open

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 623586@bnt-lap001
Assistant-Session: 10b30928-5b3b-4c11-9934-5ecca07367d8
2026-10-08 00:24:43 +02:00

77 lines
2.9 KiB
Python

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]