aboutsummaryrefslogtreecommitdiff
path: root/internal/game/casino_forfeit_regression_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/game/casino_forfeit_regression_test.go')
-rw-r--r--internal/game/casino_forfeit_regression_test.go61
1 files changed, 61 insertions, 0 deletions
diff --git a/internal/game/casino_forfeit_regression_test.go b/internal/game/casino_forfeit_regression_test.go
new file mode 100644
index 0000000..9ad8016
--- /dev/null
+++ b/internal/game/casino_forfeit_regression_test.go
@@ -0,0 +1,61 @@
+package game
+
+// Disconnect-forfeit regressions: a player who disconnects mid-round
+// forfeits the committed stake, so startup recovery must NOT refund it; a
+// stake left outstanding by a genuine crash still is.
+
+import (
+ "testing"
+
+ "thehouseoficarus/internal/casino"
+)
+
+// TestDisconnectForfeitsMachineStake: disconnecting mid-spin forfeits the
+// stake (the machine frees the seat immediately); recovery must not refund
+// it on the next startup.
+func TestDisconnectForfeitsMachineStake(t *testing.T) {
+ h := newHarness(t)
+ h.seedAccount("alice", "pw", false)
+ p := h.seedCharacter("alice", "alice")
+ h.g.RunOnOwner(func() {
+ p.Credits = 100
+ h.g.Casino.JoinMachine(1, casino.MachineConfig{ID: "slots", Game: casino.GameSlots, SpinTicks: 50}, "alice")
+ h.g.Casino.SetMachineBet(1, "slots", "alice", 10, casinoWallet{g: h.g, p: p})
+ // The disconnect path forfeits the in-flight spin.
+ h.g.Casino.MarkDisconnected("alice")
+ })
+ h.barrier()
+
+ restarted := harnessFromDir(t, h.dir)
+ loaded, err := restarted.g.AccountStore.LoadCharacter("alice")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if loaded.Credits != 90 {
+ t.Fatalf("credits after forfeited spin = %d, want 90 (disconnect forfeits)", loaded.Credits)
+ }
+}
+
+// TestDisconnectForfeitsBlackjackStake: same policy at a table: the seat
+// frees up and the stake is not refunded by recovery.
+func TestDisconnectForfeitsBlackjackStake(t *testing.T) {
+ h := newHarness(t)
+ h.seedAccount("alice", "pw", false)
+ p := h.seedCharacter("alice", "alice")
+ h.g.RunOnOwner(func() {
+ p.Credits = 100
+ h.g.Casino.Join(1, casino.TableConfig{ID: "bj", Game: casino.GameBlackjack, MaxPlayers: 2}, "alice")
+ h.g.Casino.Bet(1, "bj", "alice", "", 10, casinoWallet{g: h.g, p: p})
+ h.g.Casino.MarkDisconnected("alice")
+ })
+ h.barrier()
+
+ restarted := harnessFromDir(t, h.dir)
+ loaded, err := restarted.g.AccountStore.LoadCharacter("alice")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if loaded.Credits != 90 {
+ t.Fatalf("credits after forfeited hand = %d, want 90 (disconnect forfeits)", loaded.Credits)
+ }
+}