aboutsummaryrefslogtreecommitdiff
path: root/internal/game/economy_recovery_regression_test.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-09-16 14:09:22 -0400
committerhistoria <[not public]>2026-09-16 14:09:22 -0400
commit2f34e75f27e5f99cfc1c5f8eaf6ab4ff2fddb1d9 (patch)
treec50388fe639286bda1b1999ca6c2c972d03eb3a5 /internal/game/economy_recovery_regression_test.go
parentc054b27f628f23fecc505b9e09e78721738f3c4e (diff)
downloadthehouseoficarus-2f34e75f27e5f99cfc1c5f8eaf6ab4ff2fddb1d9.tar.gz
fix: reserved-loot pickup, credit pickup, payout recovery, and slot stake/bonus shutdown handling
Diffstat (limited to 'internal/game/economy_recovery_regression_test.go')
-rw-r--r--internal/game/economy_recovery_regression_test.go56
1 files changed, 56 insertions, 0 deletions
diff --git a/internal/game/economy_recovery_regression_test.go b/internal/game/economy_recovery_regression_test.go
index 1bb3293..241b235 100644
--- a/internal/game/economy_recovery_regression_test.go
+++ b/internal/game/economy_recovery_regression_test.go
@@ -479,3 +479,59 @@ func TestCapBlockedPayoutIsJournaled(t *testing.T) {
t.Fatalf("recovery mutated a capped balance: %d", loaded.Credits)
}
}
+
+// TestRecoveryReappliesPartiallyPaidIdenticalPayouts: two identical payout
+// records were open and an earlier recovery run re-applied (and settled)
+// only the FIRST before crashing again — the second save failed transiently
+// (see TestRecoverySaveFailureRetriesOnNextStartup for the single-record
+// case). The next recovery must NOT settle the remaining record as
+// "already durable" merely because the balance now sits at its
+// post-payout checkpoint: the settled sibling explains that balance, and
+// the open record is still owed.
+func TestRecoveryReappliesPartiallyPaidIdenticalPayouts(t *testing.T) {
+ h := newHarness(t)
+ h.seedAccount("alice", "pw", false)
+ p := h.seedCharacter("alice", "alice")
+ h.g.RunOnOwner(func() {
+ p.Credits = 90
+ if err := h.g.AccountStore.SaveCharacter(p); err != nil {
+ t.Error(err)
+ return
+ }
+ // Two identical owed payouts were journaled against balance 90.
+ if _, err := h.g.Economy.start("payout", p, 0, 20, 90, 110, 0, 0); err != nil {
+ t.Error(err)
+ return
+ }
+ second, err := h.g.Economy.start("payout", p, 0, 20, 90, 110, 0, 0)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ // Simulate the prior recovery run: the first record was re-applied
+ // and settled durably; the second's save failed transiently.
+ if err := h.g.payCreditsDurable(p, 20); err != nil {
+ t.Error(err)
+ return
+ }
+ first := h.g.Economy.loadOpen()[0]
+ if first.ID == second.ID {
+ t.Fatal("setup: expected two distinct records")
+ }
+ h.g.Economy.settle(first)
+ // Recovery over this state: the remaining owed payout must be
+ // re-applied, never settled as "already durable".
+ h.g.recoverEconomy()
+ loaded, err := h.g.AccountStore.LoadCharacter("alice")
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if loaded.Credits != 130 {
+ t.Errorf("recovered balance = %d, want 130 (remaining owed payout re-applied)", loaded.Credits)
+ }
+ if open := h.g.Economy.loadOpen(); len(open) != 0 {
+ t.Errorf("records left open after recovery: %+v", open)
+ }
+ })
+}