"""Unit: `MESSAGE_WHITELIST` — totality and the pinned matrix (phase 06, task 01). The whitelist is the single source of "what is legal when" (PLAN §7 "Accepted when"), imported by the endpoint and never duplicated. These tests pin the whole matrix (a silent edit changes the wire contract) and assert its *totality*: every room state is classified, every classification is a known client type, and every client type is legal in at least one state — so a new `ClientMsgType` that is never whitelisted (or a state that is never classified) fails loudly. """ from __future__ import annotations import pytest from undercooked.server.protocol import CLIENT_MSG_TYPES, MESSAGE_WHITELIST from undercooked.server.room import RoomState pytestmark = pytest.mark.unit #: The pinned matrix — PLAN §7 "Accepted when", one row per room state. EXPECTED_MATRIX: dict[RoomState, frozenset[str]] = { RoomState.LOBBY: frozenset({"hello", "ready", "set_level", "start", "emote", "ping"}), RoomState.COUNTDOWN: frozenset({"hello", "ping"}), RoomState.PLAYING: frozenset({"hello", "input", "emote", "ping"}), RoomState.ROUND_END: frozenset({"hello", "to_lobby", "next_level", "ping"}), RoomState.CLOSED: frozenset({"hello", "ping"}), } def test_the_matrix_is_pinned() -> None: actual = {state: frozenset(types) for state, types in MESSAGE_WHITELIST.items()} assert actual == EXPECTED_MATRIX def test_totality_every_room_state_is_classified() -> None: assert set(MESSAGE_WHITELIST) == set(RoomState) def test_totality_every_whitelisted_type_is_known() -> None: for state, allowed in MESSAGE_WHITELIST.items(): unknown = allowed - CLIENT_MSG_TYPES assert not unknown, f"{state.value}: unknown types {sorted(unknown)}" def test_totality_every_client_type_is_legal_somewhere() -> None: union: set[str] = set() for allowed in MESSAGE_WHITELIST.values(): union |= set(allowed) never = CLIENT_MSG_TYPES - union assert not never, f"client types legal in no state at all: {sorted(never)}" def test_hello_and_ping_are_legal_in_every_state() -> None: for state, allowed in MESSAGE_WHITELIST.items(): assert {"hello", "ping"} <= allowed, ( f"{state.value}: hello (the rejoin handshake) and ping (the " f"keep-alive) must be legal in every state" ) def test_input_is_playing_only() -> None: assert "input" in MESSAGE_WHITELIST[RoomState.PLAYING] for state in (RoomState.LOBBY, RoomState.COUNTDOWN, RoomState.ROUND_END, RoomState.CLOSED): assert "input" not in MESSAGE_WHITELIST[state] def test_the_lobby_verbs_are_lobby_only() -> None: for verb in ("ready", "set_level", "start"): assert verb in MESSAGE_WHITELIST[RoomState.LOBBY] for state in (RoomState.COUNTDOWN, RoomState.PLAYING, RoomState.ROUND_END, RoomState.CLOSED): for verb in ("ready", "set_level", "start"): assert verb not in MESSAGE_WHITELIST[state] def test_emote_is_lobby_and_playing_only() -> None: assert "emote" in MESSAGE_WHITELIST[RoomState.LOBBY] assert "emote" in MESSAGE_WHITELIST[RoomState.PLAYING] for state in (RoomState.COUNTDOWN, RoomState.ROUND_END, RoomState.CLOSED): assert "emote" not in MESSAGE_WHITELIST[state] def test_the_round_end_verbs_are_round_end_only() -> None: for verb in ("to_lobby", "next_level"): assert verb in MESSAGE_WHITELIST[RoomState.ROUND_END] for state in (RoomState.LOBBY, RoomState.COUNTDOWN, RoomState.PLAYING, RoomState.CLOSED): for verb in ("to_lobby", "next_level"): assert verb not in MESSAGE_WHITELIST[state] def test_countdown_accepts_no_gameplay_verb() -> None: # The 3 s countdown is a wall: only the handshake and the keep-alive get # through (a late `ready` or `input` is `wrong_state`). assert MESSAGE_WHITELIST[RoomState.COUNTDOWN] == {"hello", "ping"}