ca98703538
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FYqwNMyPUHeTbFWg83GQq6
50 lines
1.7 KiB
Python
50 lines
1.7 KiB
Python
import pytest
|
|
|
|
from leanbench.schema import KIND_FACT, KIND_OBJECT, Fact, Goal, Role, Simplex
|
|
|
|
|
|
def test_simplex_needs_two_roles():
|
|
only = Role("n", KIND_OBJECT)
|
|
with pytest.raises(ValueError, match="at least 2"):
|
|
Simplex("solo", {"n": only})
|
|
two = Simplex("pair", {"n": only, "h": Role("h", KIND_FACT)})
|
|
assert [r.name for r in two.by_kind(KIND_FACT)] == ["h"]
|
|
|
|
|
|
def test_validation_runs_in_init_not_a_dead_post_init():
|
|
# The archived prototype defined __post_init__ beside a hand-written __init__,
|
|
# so its minimum-role check never executed. Guard against that regression.
|
|
with pytest.raises(ValueError):
|
|
Simplex("empty", {})
|
|
|
|
|
|
def test_constrained_role_rejects_values_outside_choices():
|
|
role = Role("parity", KIND_OBJECT, choices=["even", "odd"])
|
|
assert role.is_constrained()
|
|
assert role.validate_value("even")
|
|
with pytest.raises(ValueError, match="not allowed"):
|
|
role.check_value("prime")
|
|
assert Role("free", KIND_OBJECT).validate_value(object())
|
|
|
|
|
|
def test_simplices_nest_and_walk_flattens():
|
|
inner = Simplex("inner", {"a": Role("a"), "b": Role("b")})
|
|
outer = Simplex("outer", {"inner": inner, "c": Role("c")})
|
|
assert sorted(r.name for r in outer.walk()) == ["a", "b", "c"]
|
|
assert outer.as_dict()["roles"]["inner"]["roles"]["a"]["name"] == "a"
|
|
|
|
|
|
def test_unknown_kind_and_empty_name_are_rejected():
|
|
with pytest.raises(ValueError):
|
|
Role("x", "banana")
|
|
with pytest.raises(ValueError):
|
|
Role("")
|
|
|
|
|
|
def test_states():
|
|
role = Role("n")
|
|
assert not Goal(role).is_resolved()
|
|
assert Fact(role, 3).is_resolved()
|
|
with pytest.raises(ValueError):
|
|
Fact(role, None)
|