diff options
| author | historia <[not public]> | 2026-09-18 21:36:36 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-09-18 21:36:36 -0400 |
| commit | a8a67482bbff8297a96adff65d2fd7029ed998cc (patch) | |
| tree | e84f8ba636c8f2edb4d2ff8b45d7cff7298fa7cc /internal/game/economy_rollback_regression_test.go | |
| parent | ff04d26ce90d6b411a04a2fb59f7c24ceefb161f (diff) | |
| download | thehouseoficarus-a8a67482bbff8297a96adff65d2fd7029ed998cc.tar.gz | |
refactor: replace economy journal with single-file pending-wager wallet
Diffstat (limited to 'internal/game/economy_rollback_regression_test.go')
| -rw-r--r-- | internal/game/economy_rollback_regression_test.go | 89 |
1 files changed, 0 insertions, 89 deletions
diff --git a/internal/game/economy_rollback_regression_test.go b/internal/game/economy_rollback_regression_test.go deleted file mode 100644 index bceb351..0000000 --- a/internal/game/economy_rollback_regression_test.go +++ /dev/null @@ -1,89 +0,0 @@ -package game - -// Rollback-failure regressions for the durable money journal. When a journal -// append fails, the invariant was historically "append failed means no record -// bytes remain". A failed rollback (the truncate, or the sync that makes it -// durable) breaks that invariant: the record can survive while the caller -// believes the append failed. The wallet's journal-unavailable payout fallback -// must then still record the attempted record's ID as open-payout evidence, or -// recovery re-applies the surviving payout and pays the player twice. - -import ( - "encoding/json" - "errors" - "os" - "path/filepath" - "testing" -) - -// TestAppendRollbackFailureIsUncertain: /dev/full accepts the open but fails -// the write with ENOSPC and the rollback truncate with EINVAL, so the append -// must report that the record MAY have survived. -func TestAppendRollbackFailureIsUncertain(t *testing.T) { - if _, err := os.Stat("/dev/full"); err != nil { - t.Skipf("/dev/full is not available: %v", err) - } - j := newEconomyJournal(t.TempDir()) - j.path = "/dev/full" - - err := j.append(economyRecord{ID: "uncertain", Kind: "payout", Status: "open"}) - if !errors.Is(err, errJournalAppendUncertain) { - t.Fatalf("append rollback failure = %v, want errJournalAppendUncertain", err) - } -} - -// TestFallbackPayoutRecordsEvidenceForSurvivingRecord: a payout whose journal -// append fails and whose rollback cannot be proven must leave open-payout -// evidence in the character file. A surviving record is then settled from that -// evidence at the next startup instead of being re-applied. -func TestFallbackPayoutRecordsEvidenceForSurvivingRecord(t *testing.T) { - g, p := newEvidenceHarness(t) - - // Break the journal append: point it at its own directory, which cannot - // be opened for append or truncation. The wallet takes the file-only - // fallback. - journalPath := g.Economy.path - g.Economy.path = filepath.Dir(journalPath) - w := casinoWallet{g: g, p: p} - if err := w.PayCredits(20); err != nil { - t.Fatalf("fallback payout failed: %v", err) - } - if p.Credits != 110 { - t.Fatalf("fallback payout not applied: credits=%d, want 110", p.Credits) - } - if len(p.OpenPayouts) != 1 { - t.Fatalf("fallback payout recorded %d open-payout evidence IDs, want 1: %v", - len(p.OpenPayouts), p.OpenPayouts) - } - id := p.OpenPayouts[0] - - // Simulate the failed append having survived in the journal (the exact - // state a failed rollback produces). Recovery must use the file evidence - // and settle it, not re-apply it. - g.Economy.path = journalPath - rec := economyRecord{ - ID: id, Player: p.Name, PlayerID: p.ID, Kind: "payout", Tracked: true, - Credit: 20, Status: "open", CreditsBefore: 90, CreditsAfter: 110, - } - line, err := json.Marshal(rec) - if err != nil { - t.Fatal(err) - } - if err := os.WriteFile(journalPath, append(line, '\n'), 0o600); 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 (surviving payout settled from evidence, not re-applied)", - loaded.Credits) - } - if open := g.Economy.mustLoadOpen(t); len(open) != 0 { - t.Fatalf("records left open after recovery: %+v", open) - } -} |
