import importlib.util from pathlib import Path import tempfile import unittest ROOT = Path(__file__).resolve().parents[2] spec = importlib.util.spec_from_file_location("room_server", ROOT / "tools/room_controller/server.py") server = importlib.util.module_from_spec(spec) spec.loader.exec_module(server) class RoomTests(unittest.TestCase): def setUp(self): self.now = 100 self.room = server.Room(":memory:", lambda: self.now) self.poll() def tearDown(self): self.room.db.close() def poll(self, reports=None, boot="boot1"): return self.room.poll(dict(cabinet="cabinet_01", protocol=1, boot=boot, reports=reports or [])) def ready(self): self.room.operator("prepare") command = self.poll()["commands"][0] self.assertEqual(self.room.state["phase"], "preparing") self.poll([dict(kind="ack", id=command["id"], session=command["session"], ok=True)]) self.assertEqual(self.room.state["phase"], "ready") def event(self, name, event_id): return dict(kind="event", event=name, id=event_id, session=self.room.state["session"]) def test_ready_then_win_queues_one_reward(self): self.ready() self.poll([self.event("started", "1"), self.event("won", "2")]) reward = self.poll()["commands"] self.assertEqual(len(reward), 1) self.assertEqual(reward[0]["type"], "reward") self.poll([self.event("won", "2"), self.event("won", "3")]) self.assertEqual(len(self.poll()["commands"]), 1) def test_stale_session_cannot_reward_after_reset(self): self.ready() self.poll([self.event("started", "1")]) old_win = self.event("won", "2") self.room.operator("reset") self.poll([old_win]) self.assertEqual(self.room.state["reward"], "not requested") def test_offline_and_expiry(self): self.now += 5 self.assertFalse(self.room.snapshot()["online"]) with self.assertRaises(ValueError): self.room.operator("prepare") self.poll() self.room.operator("prepare") self.now += 16 self.assertEqual(self.poll()["commands"], []) self.assertEqual(self.room.state["phase"], "needs_prepare") def test_new_agent_boot_requires_prepare(self): self.ready() self.poll(boot="boot2") self.assertEqual(self.room.state["session"], "") self.assertEqual(self.room.state["phase"], "needs_prepare") def test_persistence(self): with tempfile.TemporaryDirectory() as temp: path = Path(temp) / "room.db" room = server.Room(path, lambda: self.now) room.poll(dict(cabinet="cabinet_01", protocol=1, boot="a")) room.operator("prepare") session = room.state["session"] room.db.close() restored = server.Room(path, lambda: self.now) self.assertEqual(restored.state["session"], session) self.assertFalse(restored.online()) restored.db.close() if __name__ == "__main__": unittest.main()