package ratelimit_test import ( "testing" "scrabble/gateway/internal/ratelimit" ) // TestTrackerDrain verifies rejections aggregate per (class, key) and that a // drain resets the tracker. func TestTrackerDrain(t *testing.T) { tr := ratelimit.NewTracker() if got := tr.Drain(); got != nil { t.Fatalf("empty tracker drained %v, want nil", got) } tr.Add("user", "u-1") tr.Add("user", "u-1") tr.Add("public", "10.0.0.1") got := map[string]ratelimit.Rejection{} for _, r := range tr.Drain() { got[r.Class+"/"+r.Key] = r } if len(got) != 2 { t.Fatalf("drained %d entries, want 2", len(got)) } if r := got["user/u-1"]; r.Rejected != 2 { t.Errorf("user/u-1 rejected = %d, want 2", r.Rejected) } if r := got["public/10.0.0.1"]; r.Rejected != 1 { t.Errorf("public/10.0.0.1 rejected = %d, want 1", r.Rejected) } if got := tr.Drain(); got != nil { t.Fatalf("second drain = %v, want nil", got) } }