fix: 修复keys速率限制未自动重置额度的bug
This commit is contained in:
245
backend/internal/service/api_key_rate_limit_test.go
Normal file
245
backend/internal/service/api_key_rate_limit_test.go
Normal file
@@ -0,0 +1,245 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestIsWindowExpired(t *testing.T) {
|
||||
now := time.Now()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
start *time.Time
|
||||
duration time.Duration
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "nil window start",
|
||||
start: nil,
|
||||
duration: RateLimitWindow5h,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "active window (started 1h ago, 5h window)",
|
||||
start: rateLimitTimePtr(now.Add(-1 * time.Hour)),
|
||||
duration: RateLimitWindow5h,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "expired window (started 6h ago, 5h window)",
|
||||
start: rateLimitTimePtr(now.Add(-6 * time.Hour)),
|
||||
duration: RateLimitWindow5h,
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "exactly at boundary (started 5h ago, 5h window)",
|
||||
start: rateLimitTimePtr(now.Add(-5 * time.Hour)),
|
||||
duration: RateLimitWindow5h,
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "active 1d window (started 12h ago)",
|
||||
start: rateLimitTimePtr(now.Add(-12 * time.Hour)),
|
||||
duration: RateLimitWindow1d,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "expired 1d window (started 25h ago)",
|
||||
start: rateLimitTimePtr(now.Add(-25 * time.Hour)),
|
||||
duration: RateLimitWindow1d,
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "active 7d window (started 3d ago)",
|
||||
start: rateLimitTimePtr(now.Add(-3 * 24 * time.Hour)),
|
||||
duration: RateLimitWindow7d,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "expired 7d window (started 8d ago)",
|
||||
start: rateLimitTimePtr(now.Add(-8 * 24 * time.Hour)),
|
||||
duration: RateLimitWindow7d,
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := IsWindowExpired(tt.start, tt.duration)
|
||||
if got != tt.want {
|
||||
t.Errorf("IsWindowExpired() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAPIKey_EffectiveUsage(t *testing.T) {
|
||||
now := time.Now()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
key APIKey
|
||||
want5h float64
|
||||
want1d float64
|
||||
want7d float64
|
||||
}{
|
||||
{
|
||||
name: "all windows active",
|
||||
key: APIKey{
|
||||
Usage5h: 5.0,
|
||||
Usage1d: 10.0,
|
||||
Usage7d: 50.0,
|
||||
Window5hStart: rateLimitTimePtr(now.Add(-1 * time.Hour)),
|
||||
Window1dStart: rateLimitTimePtr(now.Add(-12 * time.Hour)),
|
||||
Window7dStart: rateLimitTimePtr(now.Add(-3 * 24 * time.Hour)),
|
||||
},
|
||||
want5h: 5.0,
|
||||
want1d: 10.0,
|
||||
want7d: 50.0,
|
||||
},
|
||||
{
|
||||
name: "all windows expired",
|
||||
key: APIKey{
|
||||
Usage5h: 5.0,
|
||||
Usage1d: 10.0,
|
||||
Usage7d: 50.0,
|
||||
Window5hStart: rateLimitTimePtr(now.Add(-6 * time.Hour)),
|
||||
Window1dStart: rateLimitTimePtr(now.Add(-25 * time.Hour)),
|
||||
Window7dStart: rateLimitTimePtr(now.Add(-8 * 24 * time.Hour)),
|
||||
},
|
||||
want5h: 0,
|
||||
want1d: 0,
|
||||
want7d: 0,
|
||||
},
|
||||
{
|
||||
name: "nil window starts return raw usage",
|
||||
key: APIKey{
|
||||
Usage5h: 5.0,
|
||||
Usage1d: 10.0,
|
||||
Usage7d: 50.0,
|
||||
Window5hStart: nil,
|
||||
Window1dStart: nil,
|
||||
Window7dStart: nil,
|
||||
},
|
||||
want5h: 5.0,
|
||||
want1d: 10.0,
|
||||
want7d: 50.0,
|
||||
},
|
||||
{
|
||||
name: "mixed: 5h expired, 1d active, 7d nil",
|
||||
key: APIKey{
|
||||
Usage5h: 5.0,
|
||||
Usage1d: 10.0,
|
||||
Usage7d: 50.0,
|
||||
Window5hStart: rateLimitTimePtr(now.Add(-6 * time.Hour)),
|
||||
Window1dStart: rateLimitTimePtr(now.Add(-12 * time.Hour)),
|
||||
Window7dStart: nil,
|
||||
},
|
||||
want5h: 0,
|
||||
want1d: 10.0,
|
||||
want7d: 50.0,
|
||||
},
|
||||
{
|
||||
name: "zero usage with active windows",
|
||||
key: APIKey{
|
||||
Usage5h: 0,
|
||||
Usage1d: 0,
|
||||
Usage7d: 0,
|
||||
Window5hStart: rateLimitTimePtr(now.Add(-1 * time.Hour)),
|
||||
Window1dStart: rateLimitTimePtr(now.Add(-1 * time.Hour)),
|
||||
Window7dStart: rateLimitTimePtr(now.Add(-1 * time.Hour)),
|
||||
},
|
||||
want5h: 0,
|
||||
want1d: 0,
|
||||
want7d: 0,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := tt.key.EffectiveUsage5h(); got != tt.want5h {
|
||||
t.Errorf("EffectiveUsage5h() = %v, want %v", got, tt.want5h)
|
||||
}
|
||||
if got := tt.key.EffectiveUsage1d(); got != tt.want1d {
|
||||
t.Errorf("EffectiveUsage1d() = %v, want %v", got, tt.want1d)
|
||||
}
|
||||
if got := tt.key.EffectiveUsage7d(); got != tt.want7d {
|
||||
t.Errorf("EffectiveUsage7d() = %v, want %v", got, tt.want7d)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAPIKeyRateLimitData_EffectiveUsage(t *testing.T) {
|
||||
now := time.Now()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
data APIKeyRateLimitData
|
||||
want5h float64
|
||||
want1d float64
|
||||
want7d float64
|
||||
}{
|
||||
{
|
||||
name: "all windows active",
|
||||
data: APIKeyRateLimitData{
|
||||
Usage5h: 3.0,
|
||||
Usage1d: 8.0,
|
||||
Usage7d: 40.0,
|
||||
Window5hStart: rateLimitTimePtr(now.Add(-2 * time.Hour)),
|
||||
Window1dStart: rateLimitTimePtr(now.Add(-10 * time.Hour)),
|
||||
Window7dStart: rateLimitTimePtr(now.Add(-2 * 24 * time.Hour)),
|
||||
},
|
||||
want5h: 3.0,
|
||||
want1d: 8.0,
|
||||
want7d: 40.0,
|
||||
},
|
||||
{
|
||||
name: "all windows expired",
|
||||
data: APIKeyRateLimitData{
|
||||
Usage5h: 3.0,
|
||||
Usage1d: 8.0,
|
||||
Usage7d: 40.0,
|
||||
Window5hStart: rateLimitTimePtr(now.Add(-10 * time.Hour)),
|
||||
Window1dStart: rateLimitTimePtr(now.Add(-48 * time.Hour)),
|
||||
Window7dStart: rateLimitTimePtr(now.Add(-10 * 24 * time.Hour)),
|
||||
},
|
||||
want5h: 0,
|
||||
want1d: 0,
|
||||
want7d: 0,
|
||||
},
|
||||
{
|
||||
name: "nil window starts return raw usage",
|
||||
data: APIKeyRateLimitData{
|
||||
Usage5h: 3.0,
|
||||
Usage1d: 8.0,
|
||||
Usage7d: 40.0,
|
||||
Window5hStart: nil,
|
||||
Window1dStart: nil,
|
||||
Window7dStart: nil,
|
||||
},
|
||||
want5h: 3.0,
|
||||
want1d: 8.0,
|
||||
want7d: 40.0,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := tt.data.EffectiveUsage5h(); got != tt.want5h {
|
||||
t.Errorf("EffectiveUsage5h() = %v, want %v", got, tt.want5h)
|
||||
}
|
||||
if got := tt.data.EffectiveUsage1d(); got != tt.want1d {
|
||||
t.Errorf("EffectiveUsage1d() = %v, want %v", got, tt.want1d)
|
||||
}
|
||||
if got := tt.data.EffectiveUsage7d(); got != tt.want7d {
|
||||
t.Errorf("EffectiveUsage7d() = %v, want %v", got, tt.want7d)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func rateLimitTimePtr(t time.Time) *time.Time {
|
||||
return &t
|
||||
}
|
||||
Reference in New Issue
Block a user