mail-address-semantics/mas_conformance/runner.py

51 lines
1.6 KiB
Python
Raw Normal View History

"""Run the conformance corpus against mas_core. Used by `mas test` and pytest."""
from __future__ import annotations
from dataclasses import dataclass, field
from mas_core.parser import MasSyntaxError, parse_for_profile
from . import address_fixtures, property_fixtures
@dataclass
class Report:
passed: int = 0
failures: list = field(default_factory=list)
@property
def ok(self) -> bool:
return not self.failures
def check_address_fixture(f: dict):
"""Return None on pass, else a failure description."""
try:
got = parse_for_profile(f["local_part"], f["profile"])
except MasSyntaxError as e:
if f["valid"]:
return f"unexpected invalid ({e.code}: {e})"
if "error" in f and f["error"] != e.code and f["id"].startswith("prop-"):
return f"wrong error code: expected {f['error']}, got {e.code}"
return None
if not f["valid"]:
return f"expected invalid, parsed as {got.to_fixture_dict()}"
if got.to_fixture_dict() != f["parsed"]:
return f"parse mismatch: got {got.to_fixture_dict()}, expected {f['parsed']}"
for key in ("required_profile", "generator_allowed", "base"):
if key in f and got.to_dict()[key] != f[key]:
return f"{key} mismatch: got {got.to_dict()[key]!r}, expected {f[key]!r}"
return None
def run_parser_corpus() -> Report:
report = Report()
for f in address_fixtures() + property_fixtures():
problem = check_address_fixture(f)
if problem:
report.failures.append((f["id"], f["local_part"], problem))
else:
report.passed += 1
return report