Spaces:
Running
Running
File size: 2,311 Bytes
c964813 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | """Replay each contract example in ../contract against a fresh Manager.
Each example lists calls in order, keyed by method name. A call has "args"
(omitted for methods that take none) and either "result" (the expected return
value as JSON; floats are compared to 6 significant figures) or "error" (a
UserError of "kind": "user", whose text contains "message" if given). This
mirrors what @elvis/pyodide's worker sends to the UI.
"""
import json
from pathlib import Path
import pytest
from manager import Manager
CONTRACT_DIR = Path(__file__).parent.parent / "contract"
EXAMPLES = sorted(CONTRACT_DIR.glob("*.json"))
def same(actual, expected) -> bool:
"""Equal JSON values, with floats compared approximately."""
if isinstance(expected, float) or isinstance(actual, float):
return isinstance(actual, (int, float)) and actual == pytest.approx(expected, rel=1e-6, abs=1e-12)
if isinstance(expected, dict):
return isinstance(actual, dict) and actual.keys() == expected.keys() and all(same(actual[k], expected[k]) for k in expected)
if isinstance(expected, list):
return isinstance(actual, list) and len(actual) == len(expected) and all(same(a, e) for a, e in zip(actual, expected))
return actual == expected
@pytest.mark.parametrize("path", EXAMPLES, ids=[p.stem for p in EXAMPLES])
def test_contract_example(path: Path) -> None:
example = json.loads(path.read_text())
manager = Manager()
for method, call in example["calls"].items():
fn = getattr(manager, method)
try:
data = fn(call["args"]) if "args" in call else fn()
except Exception as e:
# The worker treats only UserError as a user error; anything else is a bug
if type(e).__name__ != "UserError":
raise
assert "error" in call, f"{method} raised UserError: {e}"
assert call["error"]["kind"] == "user"
assert call["error"].get("message", "") in str(e)
continue
assert "error" not in call, f"{method} returned {data!r} instead of raising UserError"
# Results must be plain JSON values (no NumPy types) to reach the UI unchanged
actual = json.loads(json.dumps(data))
assert same(actual, call["result"]), f"{method} returned {actual!r}"
|