mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-10 16:04:04 +00:00
73 lines
1.7 KiB
Go
73 lines
1.7 KiB
Go
package allocator
|
|
|
|
import (
|
|
"errors"
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestFixedWindowBudgetLimitsEachRegionAndResets(t *testing.T) {
|
|
now := time.Unix(1000, 0).UTC()
|
|
budget, err := NewFixedWindowBudget(2, time.Minute)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for i := 0; i < 2; i++ {
|
|
if err := budget.Allow("EU", now); err != nil {
|
|
t.Fatalf("EU attempt %d: %v", i, err)
|
|
}
|
|
}
|
|
if err := budget.Allow("EU", now); !errors.Is(err, ErrAllocationBudgetExceeded) {
|
|
t.Fatalf("third EU attempt = %v, want budget error", err)
|
|
}
|
|
if err := budget.Allow("NA", now); err != nil {
|
|
t.Fatalf("NA should have an independent budget: %v", err)
|
|
}
|
|
if err := budget.Allow("EU", now.Add(time.Minute)); err != nil {
|
|
t.Fatalf("EU after window: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestFixedWindowBudgetIsAtomicUnderConcurrentAttempts(t *testing.T) {
|
|
budget, err := NewFixedWindowBudget(7, time.Minute)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
now := time.Unix(1000, 0).UTC()
|
|
var wg sync.WaitGroup
|
|
var mu sync.Mutex
|
|
allowed := 0
|
|
for i := 0; i < 64; i++ {
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
if budget.Allow("EU", now) == nil {
|
|
mu.Lock()
|
|
allowed++
|
|
mu.Unlock()
|
|
}
|
|
}()
|
|
}
|
|
wg.Wait()
|
|
if allowed != 7 {
|
|
t.Fatalf("allowed=%d, want exactly 7", allowed)
|
|
}
|
|
}
|
|
|
|
func TestFixedWindowBudgetRejectsInvalidConfigurationAndInput(t *testing.T) {
|
|
if _, err := NewFixedWindowBudget(0, time.Minute); err == nil {
|
|
t.Fatal("zero limit accepted")
|
|
}
|
|
if _, err := NewFixedWindowBudget(1, 0); err == nil {
|
|
t.Fatal("zero window accepted")
|
|
}
|
|
budget, _ := NewFixedWindowBudget(1, time.Minute)
|
|
if err := budget.Allow("APAC", time.Unix(1000, 0)); err == nil {
|
|
t.Fatal("unknown region accepted")
|
|
}
|
|
if err := budget.Allow("EU", time.Time{}); err == nil {
|
|
t.Fatal("zero time accepted")
|
|
}
|
|
}
|