mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-13 00:14:33 +00:00
Apply Go 1.21+ min/max builtins and improved switch pattern matching across test files and utilities. No functional changes.
109 lines
3.0 KiB
Go
109 lines
3.0 KiB
Go
package gateway
|
|
|
|
import (
|
|
"testing"
|
|
)
|
|
|
|
// TestRateLimiter_DisabledWhenZeroRPM verifies that rpm=0 means always-allow.
|
|
func TestRateLimiter_DisabledWhenZeroRPM(t *testing.T) {
|
|
rl := NewRateLimiter(0, 5)
|
|
if rl.Enabled() {
|
|
t.Fatal("expected disabled when rpm=0")
|
|
}
|
|
for range 100 {
|
|
if !rl.Allow("key") {
|
|
t.Fatal("expected allow when disabled")
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestRateLimiter_DisabledWhenNegativeRPM verifies that rpm<0 means always-allow.
|
|
func TestRateLimiter_DisabledWhenNegativeRPM(t *testing.T) {
|
|
rl := NewRateLimiter(-1, 5)
|
|
if rl.Enabled() {
|
|
t.Fatal("expected disabled when rpm<0")
|
|
}
|
|
if !rl.Allow("key") {
|
|
t.Fatal("expected allow when disabled")
|
|
}
|
|
}
|
|
|
|
// TestRateLimiter_EnabledWhenPositiveRPM verifies Enabled() returns true for rpm>0.
|
|
func TestRateLimiter_EnabledWhenPositiveRPM(t *testing.T) {
|
|
rl := NewRateLimiter(60, 5)
|
|
if !rl.Enabled() {
|
|
t.Fatal("expected enabled when rpm>0")
|
|
}
|
|
}
|
|
|
|
// TestRateLimiter_BurstAllowed verifies that up to burst requests pass immediately.
|
|
func TestRateLimiter_BurstAllowed(t *testing.T) {
|
|
burst := 3
|
|
// 1 RPM so refill is negligible during burst; burst=3 so first 3 should pass.
|
|
rl := NewRateLimiter(1, burst)
|
|
key := "test-burst"
|
|
allowed := 0
|
|
for range burst {
|
|
if rl.Allow(key) {
|
|
allowed++
|
|
}
|
|
}
|
|
if allowed != burst {
|
|
t.Errorf("expected %d burst-allowed requests, got %d", burst, allowed)
|
|
}
|
|
}
|
|
|
|
// TestRateLimiter_BlocksAfterBurst verifies that requests beyond burst are blocked.
|
|
func TestRateLimiter_BlocksAfterBurst(t *testing.T) {
|
|
// 1 RPM, burst=2 → 2 tokens available, 3rd request in same instant is blocked.
|
|
rl := NewRateLimiter(1, 2)
|
|
key := "test-block"
|
|
// Drain the burst
|
|
rl.Allow(key)
|
|
rl.Allow(key)
|
|
// Next request should be rate-limited
|
|
if rl.Allow(key) {
|
|
t.Error("expected request to be rate-limited after burst exhausted")
|
|
}
|
|
}
|
|
|
|
// TestRateLimiter_PerKeyIsolation verifies that different keys have independent limiters.
|
|
func TestRateLimiter_PerKeyIsolation(t *testing.T) {
|
|
// Very small RPM with burst=1 so each key gets exactly 1 request before blocking.
|
|
rl := NewRateLimiter(1, 1)
|
|
key1, key2 := "user1", "user2"
|
|
|
|
// Both keys should pass their first request.
|
|
if !rl.Allow(key1) {
|
|
t.Error("key1 first request should be allowed")
|
|
}
|
|
if !rl.Allow(key2) {
|
|
t.Error("key2 first request should be allowed (independent from key1)")
|
|
}
|
|
|
|
// Both should now be blocked.
|
|
if rl.Allow(key1) {
|
|
t.Error("key1 second request should be rate-limited")
|
|
}
|
|
if rl.Allow(key2) {
|
|
t.Error("key2 second request should be rate-limited")
|
|
}
|
|
}
|
|
|
|
// TestRateLimiter_DefaultBurstWhenZero verifies that burst<=0 defaults to 5.
|
|
func TestRateLimiter_DefaultBurstWhenZero(t *testing.T) {
|
|
// burst=0 → default to 5; rpm=600 so refill is fast but we test burst size
|
|
rl := NewRateLimiter(600, 0)
|
|
key := "burst-default"
|
|
// Should be able to consume at least 5 tokens from the default burst.
|
|
allowed := 0
|
|
for range 5 {
|
|
if rl.Allow(key) {
|
|
allowed++
|
|
}
|
|
}
|
|
if allowed < 5 {
|
|
t.Errorf("expected at least 5 burst requests with default burst, got %d", allowed)
|
|
}
|
|
}
|