pyrtan / sourcev0.14.0 · main

pyrtan / tests / test_conformance.py

2,530 bytes · last changed 2026-10-28 in Merge main (the console as a hub of its own, dates in our own words) into identity

1"""Both runtimes read the same tree and say the same thing, read the same
2sentence the same way, and (the hub in a browser) answer the same requests
3the same way a service does.
4
5The vectors are what Python says; node runs pyrtan.js over them. The
6vectors file is regenerated here and compared, so it cannot drift from
7the examples or the runtime without this test saying so.
8"""
9
10import importlib.util
11import json
12import shutil
13import subprocess
14import sys
15from pathlib import Path
16
17import pytest
18
19ROOT = Path(__file__).resolve().parent.parent
20sys.path.insert(0, str(ROOT / "tests" / "conformance"))
21
22from make_vectors import build # noqa: E402
23
24VECTORS = ROOT / "tests" / "conformance" / "vectors.json"
25
26
27def test_vectors_are_current():
28 fresh = json.dumps(build(), indent=1, ensure_ascii=False, sort_keys=True) + "\n"
29 assert VECTORS.read_text(encoding="utf-8") == fresh, "tests/conformance/vectors.json is stale: run `uv run python tests/conformance/make_vectors.py`"
30
31
32@pytest.mark.skipif(shutil.which("node") is None, reason="node is not installed")
33def test_javascript_runtime_agrees_with_python():
34 run = subprocess.run(["node", str(ROOT / "tests" / "conformance" / "run.cjs")], capture_output=True, text=True, cwd=str(ROOT))
35 assert run.returncode == 0, run.stdout + run.stderr
36 v = json.loads(VECTORS.read_text())
37 total = sum(len(v[k]) for k in ("runs", "readings", "nlp", "proposals", "hub"))
38 assert f"{total}/{total} agree" in run.stdout
39
40
41# ---------------------------------------------------------------- identity.js and identity.py
42
43IDENTITY_VECTORS = ROOT / "tests" / "conformance" / "identity.json"
44needs_crypto = pytest.mark.skipif(importlib.util.find_spec("cryptography") is None, reason="needs pyrtan[identity]")
45
46
47@needs_crypto
48def test_identity_vectors_are_current():
49 from make_identity_vectors import build as build_identity
50 fresh = json.dumps(build_identity(), indent=1, ensure_ascii=False, sort_keys=True) + "\n"
51 assert IDENTITY_VECTORS.read_text(encoding="utf-8") == fresh, "tests/conformance/identity.json is stale: run `uv run python tests/conformance/make_identity_vectors.py`"
52
53
54@pytest.mark.skipif(shutil.which("node") is None, reason="node is not installed")
55def test_console_identity_agrees_with_python():
56 run = subprocess.run(["node", str(ROOT / "tests" / "conformance" / "identity.cjs")], capture_output=True, text=True, cwd=str(ROOT))
57 assert run.returncode == 0, run.stdout + run.stderr
58 assert " agree" in run.stdout and "DIFF" not in run.stdout