package casino import "testing" // Regression: the blackjack action window may only restart when a new turn // is actually prompted. Rejected actions must never extend the deadline, and // each successive player must receive a full window. func TestBlackjackActionWindowBoundaries(t *testing.T) { table := newBlackjackTable(1, TableConfig{ID: "blackjack", Game: GameBlackjack, Blackjack: BlackjackConfig{ActionTicks: 3}}, newTestRand()) for _, name := range []string{"alice", "bob", "carol"} { table.players.add(name, &blackjackPlayer{ Participant: Participant{Name: name, Connected: true, HasBet: true, Wallet: &testWallet{credits: 100}}, hands: []*blackjackHand{{bet: 10, cards: []card{{rank: "10"}, {rank: "6"}}}}, }) } table.dealer.cards = []card{{rank: "10"}, {rank: "7"}} table.beginPlay() table.prompt() // Alice burns one tick, then submits an invalid action and one she cannot // take (surrender disabled by default). Neither may reset her window. table.tick() table.action("alice", "invalid") table.action("alice", "surrender") if table.timer.clock != 1 { t.Fatalf("rejected actions extended or reset the deadline: timer=%+v", table.timer) } // Two more ticks expire her window; the timeout advances to Bob. table.tick() table.tick() if table.activeName() != "bob" { t.Fatalf("timeout did not advance to bob: active=%s", table.activeName()) } if table.timer.clock != 0 { t.Fatalf("bob did not receive a fresh action window: timer=%+v", table.timer) } // Bob must survive two ticks and time out on the third. table.tick() table.tick() if table.activeName() != "bob" { t.Fatalf("bob timed out early: active=%s", table.activeName()) } table.tick() if table.activeName() != "carol" { t.Fatalf("bob did not time out after his window: active=%s", table.activeName()) } }