aboutsummaryrefslogtreecommitdiff
path: root/internal/game/economy_open_payout_list_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/game/economy_open_payout_list_test.go')
-rw-r--r--internal/game/economy_open_payout_list_test.go120
1 files changed, 0 insertions, 120 deletions
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)
- }
-}