package lobby import "testing" // TestNextStatusFromSnapshot covers the pure status-mapping function // that drives `OnRuntimeSnapshot`'s lifecycle transitions. The Phase // 25 contribution is the `running → paused` branch on // `engine_unreachable` / `generation_failed`: the order handler relies // on the `paused` game status to reject late submits with // `turn_already_closed`. func TestNextStatusFromSnapshot(t *testing.T) { t.Parallel() tests := []struct { name string currentStatus string runtimeStatus string wantStatus string wantTransit bool }{ { name: "starting then running flips to running", currentStatus: GameStatusStarting, runtimeStatus: "running", wantStatus: GameStatusRunning, wantTransit: true, }, { name: "running on running snapshot does not transit", currentStatus: GameStatusRunning, runtimeStatus: "running", wantStatus: GameStatusRunning, wantTransit: false, }, { name: "starting then engine_unreachable flips to start_failed", currentStatus: GameStatusStarting, runtimeStatus: "engine_unreachable", wantStatus: GameStatusStartFailed, wantTransit: true, }, { name: "starting then generation_failed flips to start_failed", currentStatus: GameStatusStarting, runtimeStatus: "generation_failed", wantStatus: GameStatusStartFailed, wantTransit: true, }, { name: "running then engine_unreachable flips to paused", currentStatus: GameStatusRunning, runtimeStatus: "engine_unreachable", wantStatus: GameStatusPaused, wantTransit: true, }, { name: "running then generation_failed flips to paused", currentStatus: GameStatusRunning, runtimeStatus: "generation_failed", wantStatus: GameStatusPaused, wantTransit: true, }, { name: "paused stays paused on repeated failed snapshot", currentStatus: GameStatusPaused, runtimeStatus: "generation_failed", wantStatus: GameStatusPaused, wantTransit: false, }, { name: "starting then start_failed flips to start_failed", currentStatus: GameStatusStarting, runtimeStatus: "start_failed", wantStatus: GameStatusStartFailed, wantTransit: true, }, { name: "running ignores start_failed", currentStatus: GameStatusRunning, runtimeStatus: "start_failed", wantStatus: GameStatusRunning, wantTransit: false, }, { name: "running on finished flips to finished", currentStatus: GameStatusRunning, runtimeStatus: "finished", wantStatus: GameStatusFinished, wantTransit: true, }, { name: "finished stays finished on finished snapshot", currentStatus: GameStatusFinished, runtimeStatus: "finished", wantStatus: GameStatusFinished, wantTransit: false, }, { name: "cancelled stays cancelled on finished snapshot", currentStatus: GameStatusCancelled, runtimeStatus: "finished", wantStatus: GameStatusCancelled, wantTransit: false, }, { name: "paused on stopped snapshot flips to finished", currentStatus: GameStatusPaused, runtimeStatus: "stopped", wantStatus: GameStatusFinished, wantTransit: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { t.Parallel() got, transit := nextStatusFromSnapshot(tt.currentStatus, RuntimeSnapshot{ RuntimeStatus: tt.runtimeStatus, }) if got != tt.wantStatus { t.Errorf("status = %q, want %q", got, tt.wantStatus) } if transit != tt.wantTransit { t.Errorf("transit = %v, want %v", transit, tt.wantTransit) } }) } }