package ratelimit_test import ( "testing" "time" "scrabble/gateway/internal/ratelimit" ) func TestAllowEnforcesBurst(t *testing.T) { l := ratelimit.New() p := ratelimit.PerMinute(60, 3) // 1/s, burst 3 allowed := 0 for i := 0; i < 5; i++ { if l.Allow("ip:1.2.3.4", p) { allowed++ } } if allowed != 3 { t.Fatalf("allowed %d of 5, want 3 (burst)", allowed) } } func TestAllowIsolatesKeys(t *testing.T) { l := ratelimit.New() p := ratelimit.PerMinute(60, 1) if !l.Allow("user:a", p) { t.Fatal("first key should be allowed") } if !l.Allow("user:b", p) { t.Fatal("a different key must have its own bucket") } if l.Allow("user:a", p) { t.Fatal("the first key's bucket should now be empty") } } func TestPerWindow(t *testing.T) { // 5 events per 10 minutes, burst 2: the third immediate call is denied. p := ratelimit.Per(5, 10*time.Minute, 2) l := ratelimit.New() got := []bool{l.Allow("email:x", p), l.Allow("email:x", p), l.Allow("email:x", p)} if !got[0] || !got[1] || got[2] { t.Fatalf("per-window burst = %v, want [true true false]", got) } }