From a8a67482bbff8297a96adff65d2fd7029ed998cc Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Fri, 18 Sep 2026 21:36:36 -0400 Subject: refactor: replace economy journal with single-file pending-wager wallet --- internal/game/economy_open_payout_list_test.go | 120 ------------------------- 1 file changed, 120 deletions(-) delete mode 100644 internal/game/economy_open_payout_list_test.go (limited to 'internal/game/economy_open_payout_list_test.go') diff --git a/internal/game/economy_open_payout_list_test.go b/internal/game/economy_open_payout_list_test.go deleted file mode 100644 index a16f73b..0000000 --- a/internal/game/economy_open_payout_list_test.go +++ /dev/null @@ -1,120 +0,0 @@ -package game - -// Regressions for the character-file payout-evidence scheme: an owed payout -// must never be erased because an unrelated credit change coincidentally -// lands on the record's post-payout balance, and a payout whose save became -// durable must never be re-applied (double-paid) just because its settled -// journal marker was lost. - -import ( - "os" - "testing" - - "thehouseoficarus/internal/casino" - "thehouseoficarus/internal/player" -) - -// newEvidenceHarness builds a minimal Game with just the account store and -// economy journal — enough for casinoWallet and recoverEconomy. -func newEvidenceHarness(t *testing.T) (*Game, *player.Player) { - t.Helper() - dir := t.TempDir() - if err := os.MkdirAll(dir+"/players/characters", 0o700); err != nil { - t.Fatal(err) - } - g := &Game{ - Deps: Deps{AccountStore: player.NewAccountStore(dir)}, - Economy: newEconomyJournal(dir), - } - p := player.New("alice") - p.ID = "stable-identity" - p.Credits = 90 - if err := g.AccountStore.SaveCharacter(p); err != nil { - t.Fatal(err) - } - return g, p -} - -// TestRecoveryReappliesPayoutWhenUnrelatedCreditsMaskTheBalance: a payout -// whose save failed leaves an OPEN record at balance 90 (want 110). A later, -// unrelated 20-credit gain brings the durable balance to 110 — the record's -// CreditsAfter. Recovery must read the character-file evidence (absent: the -// save never landed) and re-apply the payout, not settle it as "already -// durable" and silently erase the 20 owed credits. -func TestRecoveryReappliesPayoutWhenUnrelatedCreditsMaskTheBalance(t *testing.T) { - g, p := newEvidenceHarness(t) - - // Force the payout save to fail without touching its journal. - path := g.AccountStore.CharPath(p.Name) - backup := path + ".backup" - if err := os.Rename(path, backup); err != nil { - t.Fatal(err) - } - if err := os.Mkdir(path, 0o700); err != nil { - t.Fatal(err) - } - w := casinoWallet{g: g, p: p} - if err := w.PayCredits(20); err != casino.ErrWalletPersistence { - t.Fatalf("PayCredits error = %v, want ErrWalletPersistence", err) - } - if err := os.Remove(path); err != nil { - t.Fatal(err) - } - if err := os.Rename(backup, path); err != nil { - t.Fatal(err) - } - if p.Credits != 90 { - t.Fatalf("failed payout was paid: credits=%d, want 90", p.Credits) - } - - // The unrelated credit change: a shop sale, a bank withdrawal, anything. - p.Credits += 20 - if err := g.AccountStore.SaveCharacter(p); err != nil { - t.Fatal(err) - } - - g.recoverEconomy() - - loaded, err := g.AccountStore.LoadCharacter(p.Name) - if err != nil { - t.Fatal(err) - } - if loaded.Credits != 130 { - t.Fatalf("balance after recovery = %d, want 130 (owed payout re-applied once)", loaded.Credits) - } - if open := g.Economy.mustLoadOpen(t); len(open) != 0 { - t.Fatalf("records left open after recovery: %+v", open) - } -} - -// TestRecoverySettlesDurablePayoutWithoutReapplying: the payout save landed -// (the character file records the record ID in open_payouts) but the settled -// journal marker was lost in the crash. Recovery must settle from the file -// evidence — re-applying would double-pay the win. -func TestRecoverySettlesDurablePayoutWithoutReapplying(t *testing.T) { - g, p := newEvidenceHarness(t) - - rec, err := g.Economy.start("payout", p, 0, 20, 90, 110, 0, 0) - if err != nil { - t.Fatal(err) - } - // The save landed: balance and evidence both durable. - p.Credits = 110 - p.OpenPayouts = append(p.OpenPayouts, rec.ID) - if err := g.AccountStore.SaveCharacter(p); err != nil { - t.Fatal(err) - } - - g.recoverEconomy() - - loaded, err := g.AccountStore.LoadCharacter(p.Name) - if err != nil { - t.Fatal(err) - } - if loaded.Credits != 110 { - t.Fatalf("balance after recovery = %d, want 110 (durable payout not re-applied)", loaded.Credits) - } - if open := g.Economy.mustLoadOpen(t); len(open) != 0 { - t.Fatalf("records left open after recovery: %+v", open) - } -} -- cgit v1.2.3