aboutsummaryrefslogtreecommitdiff
path: root/internal/casino/credits_test.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-09-15 15:35:52 -0400
committerhistoria <[not public]>2026-09-15 15:35:52 -0400
commit0b0b25222b3131ada79ff78c28eb8bf07d977deb (patch)
tree2ceaef5203595044f66a8f00064cd8e017f8f48d /internal/casino/credits_test.go
parent396c3facb8287b9a34076cae8f3d7b300d366d99 (diff)
downloadthehouseoficarus-0b0b25222b3131ada79ff78c28eb8bf07d977deb.tar.gz
feat: single-owner game state, transactional lifecycle, durable money on server stop
Diffstat (limited to 'internal/casino/credits_test.go')
-rw-r--r--internal/casino/credits_test.go74
1 files changed, 74 insertions, 0 deletions
diff --git a/internal/casino/credits_test.go b/internal/casino/credits_test.go
new file mode 100644
index 0000000..4094d72
--- /dev/null
+++ b/internal/casino/credits_test.go
@@ -0,0 +1,74 @@
+package casino
+
+import (
+ "testing"
+)
+
+func TestAddCreditsChecked(t *testing.T) {
+ sum, err := AddCredits(5, 7)
+ if err != nil || sum != 12 {
+ t.Fatalf("AddCredits(5,7) = %d, %v", sum, err)
+ }
+ if sum, err := AddCredits(MaxCredits, 1); err == nil || sum != MaxCredits {
+ t.Fatalf("overflow add: %d, %v", sum, err)
+ }
+ if _, err := AddCredits(MaxCredits, -1); err == nil {
+ t.Fatal("negative add must be rejected")
+ }
+}
+
+func TestMulPayoutBoundsAndConverts(t *testing.T) {
+ payout, err := MulPayout(10, 1.5)
+ if err != nil || payout != 15 {
+ t.Fatalf("MulPayout(10,1.5) = %d, %v", payout, err)
+ }
+ // Floor conversion: 10 * 0.333 = 3.33 -> 3.
+ if payout, _ := MulPayout(10, 0.333); payout != 3 {
+ t.Fatalf("floor conversion: %d", payout)
+ }
+ if payout, err := MulPayout(MaxCredits, 2); err == nil || payout != MaxCredits {
+ t.Fatalf("overflow payout: %d, %v", payout, err)
+ }
+ if payout, err := MulPayout(MaxCredits, 0.5); err != nil || payout != MaxCredits/2 {
+ t.Fatalf("half of max: %d, %v", payout, err)
+ }
+ for _, bad := range []float64{-1, inf(), nan()} {
+ if payout, err := MulPayout(10, bad); err == nil || payout != 0 {
+ t.Fatalf("multiplier %v accepted: %d, %v", bad, payout, err)
+ }
+ }
+ if payout, _ := MulPayout(0, 2); payout != 0 {
+ t.Fatalf("zero-amount payout = %d", payout)
+ }
+}
+
+func TestWalletErrorMessages(t *testing.T) {
+ if got := walletErrorMessage(ErrInsufficientFunds, "Custom short balance."); got != "Custom short balance." {
+ t.Fatalf("insufficient funds rendering: %q", got)
+ }
+ if got := walletErrorMessage(ErrWalletPersistence); !errContains(got, "persistence failure") || errContains(got, "insufficient") {
+ t.Fatalf("persistence rendering must be distinct: %q", got)
+ }
+ if got := walletErrorMessage(ErrInsufficientFunds); got == "" {
+ t.Fatal("default message missing")
+ }
+}
+
+func inf() float64 {
+ var max float64 = 1e308
+ return max * 10
+}
+func nan() float64 { return inf() - inf() }
+
+func errContains(value, fragment string) bool {
+ return len(value) >= len(fragment) && (value == fragment || len(fragment) == 0 || indexOf(value, fragment) >= 0)
+}
+
+func indexOf(haystack, needle string) int {
+ for i := 0; i+len(needle) <= len(haystack); i++ {
+ if haystack[i:i+len(needle)] == needle {
+ return i
+ }
+ }
+ return -1
+}