Files
adaptive-multi-protocol-gat…/tests/test_route_manifest.py

176 lines
6.3 KiB
Python

import contextlib
import io
import json
import subprocess
import sys
import tempfile
import unittest
from pathlib import Path
from ampg.capabilities import IDENTITY_ADAPTERS, INTERACTION_TIERS, PAYMENT_ADAPTERS
from ampg.cli import main
from ampg.metadata import (
IDENTITY_ADAPTERS as METADATA_IDENTITY_ADAPTERS,
INTERACTION_TIERS as METADATA_INTERACTION_TIERS,
PAYMENT_ADAPTERS as METADATA_PAYMENT_ADAPTERS,
)
from ampg.route_manifest import (
route_manifest_schema_json,
validate_route_manifest,
)
ROOT = Path(__file__).resolve().parents[1]
class RouteManifestTest(unittest.TestCase):
def test_example_route_manifest_is_valid(self):
data = json.loads((ROOT / "examples/route-manifest.json").read_text(encoding="utf-8"))
self.assertEqual([], validate_route_manifest(data))
def test_route_catalog_generator_matches_example_manifest(self):
with tempfile.TemporaryDirectory() as tmp:
output = Path(tmp) / "route-manifest.json"
result = subprocess.run(
[
sys.executable,
"tools/generate_route_manifest.py",
"examples/route-catalog.json",
str(output),
],
cwd=ROOT,
check=False,
capture_output=True,
text=True,
)
self.assertEqual("", result.stderr)
self.assertEqual(0, result.returncode)
self.assertEqual(
(ROOT / "examples/route-manifest.json").read_text(encoding="utf-8"),
output.read_text(encoding="utf-8"),
)
check_result = subprocess.run(
[
sys.executable,
"tools/generate_route_manifest.py",
"examples/route-catalog.json",
str(output),
"--check",
],
cwd=ROOT,
check=False,
capture_output=True,
text=True,
)
self.assertEqual("", check_result.stderr)
self.assertEqual(0, check_result.returncode)
def test_invalid_route_manifest_reports_all_contract_issues(self):
issues = validate_route_manifest(
{
"schema": "wrong",
"default_tier": "magic",
"deny_routes": ["admin/*"],
"extra": True,
"routes": [
{
"match": "play/*",
"tier": "paid",
"identity": "cookie-ish",
"payments": "coin",
"realtime": "yes",
"public_allowed": "no",
"extra": True,
},
[],
],
}
)
by_path = {issue.path: issue for issue in issues}
self.assertEqual("unknown-field", by_path["$.extra"].code)
self.assertEqual("schema", by_path["$.schema"].code)
self.assertEqual("enum", by_path["$.default_tier"].code)
self.assertEqual("pattern", by_path["$.deny_routes[0]"].code)
self.assertEqual("unknown-field", by_path["$.routes[0].extra"].code)
self.assertEqual("pattern", by_path["$.routes[0].match"].code)
self.assertEqual("enum", by_path["$.routes[0].tier"].code)
self.assertEqual("enum", by_path["$.routes[0].identity"].code)
self.assertEqual("enum", by_path["$.routes[0].payments"].code)
self.assertEqual("type", by_path["$.routes[0].realtime"].code)
self.assertEqual("type", by_path["$.routes[0].public_allowed"].code)
self.assertEqual("type", by_path["$.routes[1]"].code)
def test_route_manifest_validate_cli(self):
stdout = io.StringIO()
with contextlib.redirect_stdout(stdout):
status = main(["route-manifest", "validate", "examples/route-manifest.json"])
self.assertEqual(0, status)
self.assertIn("schema=ampg.route-manifest.v1 routes=4 status=ok", stdout.getvalue())
def test_route_manifest_validate_cli_reports_issues(self):
with tempfile.TemporaryDirectory() as tmp:
path = Path(tmp) / "routes.json"
path.write_text(
json.dumps(
{
"schema": "ampg.route-manifest.v1",
"routes": [{"match": "play/*", "tier": "paid"}],
}
),
encoding="utf-8",
)
stdout = io.StringIO()
with contextlib.redirect_stdout(stdout):
status = main(["route-manifest", "validate", str(path)])
output = stdout.getvalue()
self.assertEqual(1, status)
self.assertIn("json_path=$.routes[0].match code=pattern", output)
self.assertIn("json_path=$.routes[0].tier code=enum", output)
self.assertIn("status=fail issues=2", output)
def test_route_manifest_schema_file_matches_generated_schema(self):
schema_path = ROOT / "schemas/ampg.route-manifest.v1.schema.json"
self.assertEqual(
route_manifest_schema_json(),
schema_path.read_text(encoding="utf-8"),
)
def test_route_manifest_schema_cli_can_write_schema(self):
with tempfile.TemporaryDirectory() as tmp:
path = Path(tmp) / "schema.json"
stdout = io.StringIO()
with contextlib.redirect_stdout(stdout):
status = main(["route-manifest", "schema", "--output", str(path)])
self.assertEqual(0, status)
self.assertEqual(route_manifest_schema_json(), path.read_text(encoding="utf-8"))
self.assertIn(f"AMPG_ROUTE_MANIFEST_SCHEMA path={path}", stdout.getvalue())
def test_capability_constants_match_generated_metadata(self):
self.assertEqual(
tuple(tier.name for tier in METADATA_INTERACTION_TIERS),
INTERACTION_TIERS,
)
self.assertEqual(
tuple(adapter.name for adapter in METADATA_IDENTITY_ADAPTERS),
IDENTITY_ADAPTERS,
)
self.assertEqual(
tuple(adapter.name for adapter in METADATA_PAYMENT_ADAPTERS),
PAYMENT_ADAPTERS,
)
if __name__ == "__main__":
unittest.main()