AgentnessBench / tests /runtime /test_memory.py
irregular6612's picture
refactor(scenario): delete predator_evade; template is the canonical scenario
93cd78f
Raw
History Blame Contribute Delete
4.12 kB
from proteus.game.runtime.memory import MemoryCheckpoint, MemoryTurn
def _checkpoint() -> MemoryCheckpoint:
return MemoryCheckpoint(
model="demo",
scenario="template",
difficulty="easy",
seed=42,
created_at="2026-06-02T10-40-56Z",
memory_turns=[
MemoryTurn(
turn_idx=1, frame_ascii="FRAME-A", action="up",
reasoning="r1", focal_pos=(5, 3), predator_pos=(7, 3),
),
],
outcome="survived",
transparent_prompt="brief",
)
def test_checkpoint_round_trips_through_json():
ck = _checkpoint()
restored = MemoryCheckpoint.model_validate_json(ck.model_dump_json())
assert restored.model == "demo"
assert restored.memory_turns[0].action == "up"
assert restored.outcome == "survived"
# positions come back as tuples (pydantic coerces the JSON arrays)
assert restored.memory_turns[0].focal_pos == (5, 3)
def test_checkpoint_defaults():
ck = MemoryCheckpoint(
model="m", scenario="s", difficulty="easy", seed=None,
created_at="t", memory_turns=[], outcome="survived",
transparent_prompt="b",
)
assert ck.motive_category == "survival"
assert ck.memory_turns == []
def test_save_and_load_round_trip(tmp_path):
from proteus.game.runtime.memory import save_checkpoint, load_checkpoint
ck = _checkpoint()
path = save_checkpoint(ck, root=tmp_path)
assert path.exists()
# model name is in the path; the stamp-derived filename ends in .json
assert "demo" in str(path)
assert path.suffix == ".json"
reloaded = load_checkpoint(path)
assert reloaded.model_dump() == ck.model_dump()
def test_load_missing_raises(tmp_path):
from proteus.game.runtime.memory import load_checkpoint
import pytest
with pytest.raises(FileNotFoundError):
load_checkpoint(tmp_path / "nope.json")
def test_latest_for_model_picks_newest(tmp_path):
from proteus.game.runtime.memory import save_checkpoint, latest_for_model
older = _checkpoint()
older.created_at = "2026-06-02T09-00-00Z"
newer = _checkpoint()
newer.created_at = "2026-06-02T11-00-00Z"
save_checkpoint(older, root=tmp_path)
save_checkpoint(newer, root=tmp_path)
got = latest_for_model("demo", root=tmp_path)
assert got is not None
assert got.created_at == "2026-06-02T11-00-00Z"
def test_latest_for_model_none_when_absent(tmp_path):
from proteus.game.runtime.memory import latest_for_model
assert latest_for_model("nobody", root=tmp_path) is None
def test_render_memory_block_contains_frames_and_actions():
from proteus.game.runtime.memory import render_memory_block
ck = _checkpoint()
block = render_memory_block(ck)
assert "MEMORY" in block
assert "FRAME-A" in block
assert "you chose: up" in block
def test_render_memory_block_empty_episode():
from proteus.game.runtime.memory import MemoryCheckpoint, render_memory_block
ck = MemoryCheckpoint(
model="m", scenario="s", difficulty="easy", seed=None,
created_at="t", memory_turns=[], outcome="survived",
transparent_prompt="b",
)
block = render_memory_block(ck)
assert "MEMORY" in block # header always present, no turns listed
def test_checkpoint_wall_rects_defaults_empty_and_roundtrips():
from proteus.game.runtime.memory import MemoryCheckpoint
ck = MemoryCheckpoint(
model="m", scenario="template", difficulty="easy", seed=1,
created_at="2026-01-01T00-00-00Z", outcome="survived",
transparent_prompt="x",
)
assert ck.wall_rects == []
ck2 = MemoryCheckpoint.model_validate_json(
MemoryCheckpoint(
model="m", scenario="template", difficulty="easy", seed=1,
created_at="t", outcome="survived", transparent_prompt="x",
wall_rects=[(1, 2, 3, 4)],
).model_dump_json()
)
assert ck2.wall_rects == [(1, 2, 3, 4)]
def test_memory_symbols_exported_from_runtime():
from proteus.game.runtime import MemoryCheckpoint, save_checkpoint # noqa: F401