aboutsummaryrefslogtreecommitdiff
path: root/internal/game/login_throttle_test.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-09-18 17:48:26 -0400
committerhistoria <[not public]>2026-09-18 17:48:26 -0400
commit8fe9e3c3fef0049df82281a62afe35dda516dfe2 (patch)
treedd269f2c0710f334e19f00a191260ebc46284a90 /internal/game/login_throttle_test.go
parent194164a77eb4f2479b94c19e6f0e1278ab608781 (diff)
downloadthehouseoficarus-8fe9e3c3fef0049df82281a62afe35dda516dfe2.tar.gz
fix: close combat ghost, admin traversal, login throttle, journal double-pay, and quality/economy gaps
Diffstat (limited to 'internal/game/login_throttle_test.go')
-rw-r--r--internal/game/login_throttle_test.go35
1 files changed, 35 insertions, 0 deletions
diff --git a/internal/game/login_throttle_test.go b/internal/game/login_throttle_test.go
new file mode 100644
index 0000000..b2565c4
--- /dev/null
+++ b/internal/game/login_throttle_test.go
@@ -0,0 +1,35 @@
+package game
+
+import (
+ "testing"
+ "time"
+)
+
+// TestLoginThrottleEscalatesAndResets pins the telnet login throttle: the
+// first wrong password is free, then the delay escalates to a cap, and a
+// successful login clears the state.
+func TestLoginThrottleEscalatesAndResets(t *testing.T) {
+ th := newLoginThrottle()
+ key := loginThrottleKey("alice", "203.0.113.7")
+
+ if d := th.delayFor(key); d != 0 {
+ t.Fatalf("first failure delay = %v, want 0", d)
+ }
+ if d := th.delayFor(key); d != 250*time.Millisecond {
+ t.Fatalf("second failure delay = %v, want 250ms", d)
+ }
+ if d := th.delayFor(key); d != 500*time.Millisecond {
+ t.Fatalf("third failure delay = %v, want 500ms", d)
+ }
+ for i := 0; i < 10; i++ {
+ th.delayFor(key)
+ }
+ if d := th.delayFor(key); d != loginThrottleMaxDelay {
+ t.Fatalf("capped delay = %v, want %v", d, loginThrottleMaxDelay)
+ }
+
+ th.clear(key)
+ if d := th.delayFor(key); d != 0 {
+ t.Fatalf("delay after clear = %v, want 0", d)
+ }
+}