proxy-pool/internal/domain/proxy/proxy_test.go

130 lines
3.1 KiB
Go

package proxy
import (
"sync"
"sync/atomic"
"testing"
"time"
)
func TestUniqueKeyIncludesCredentialVersionButNotPassword(t *testing.T) {
p := Proxy{
Scheme: SchemeHTTP,
Host: "EXAMPLE.COM",
Port: 8080,
Username: "alice",
CredentialVersion: "v2",
SecretRef: "secret-password",
}
got := p.UniqueKey()
want := "http|example.com|8080|alice|v2"
if got != want {
t.Fatalf("UniqueKey() = %q, want %q", got, want)
}
if contains(got, p.SecretRef) {
t.Fatal("unique key leaked the proxy password reference")
}
}
func TestEffectiveExpiryPrecedence(t *testing.T) {
now := time.Date(2026, 7, 28, 10, 0, 0, 0, time.UTC)
explicit := now.Add(90 * time.Second)
tests := []struct {
name string
expiresAt *time.Time
response time.Duration
configured time.Duration
want *time.Time
}{
{name: "explicit timestamp", expiresAt: &explicit, response: 2 * time.Minute, configured: 3 * time.Minute, want: &explicit},
{name: "response ttl", response: 2 * time.Minute, configured: 3 * time.Minute, want: timePtr(now.Add(2 * time.Minute))},
{name: "configured ttl", configured: 3 * time.Minute, want: timePtr(now.Add(3 * time.Minute))},
{name: "non expiring"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := EffectiveExpiry(now, tt.expiresAt, tt.response, tt.configured)
if !equalTimePtr(got, tt.want) {
t.Fatalf("EffectiveExpiry() = %v, want %v", got, tt.want)
}
})
}
}
func TestStateMachineRejectsIllegalTransition(t *testing.T) {
p := Proxy{State: StateFetched}
if err := p.Transition(StateChecking); err != nil {
t.Fatalf("FETCHED -> CHECKING: %v", err)
}
if err := p.Transition(StateAvailable); err != nil {
t.Fatalf("CHECKING -> AVAILABLE: %v", err)
}
if err := p.Transition(StateFetched); err == nil {
t.Fatal("AVAILABLE -> FETCHED must be rejected")
}
}
func TestCapacityNeverOversubscribes(t *testing.T) {
capacity := NewCapacity(8)
var acquired atomic.Int64
var peak atomic.Int64
var wg sync.WaitGroup
for range 1000 {
wg.Add(1)
go func() {
defer wg.Done()
reservation, ok := capacity.Reserve()
if !ok {
return
}
active := acquired.Add(1)
for {
old := peak.Load()
if active <= old || peak.CompareAndSwap(old, active) {
break
}
}
if err := reservation.Commit(); err != nil {
t.Errorf("Commit(): %v", err)
}
acquired.Add(-1)
if err := reservation.Release(); err != nil {
t.Errorf("Release(): %v", err)
}
}()
}
wg.Wait()
if peak.Load() > 8 {
t.Fatalf("peak reservations = %d, exceeds 8", peak.Load())
}
if got := capacity.Active(); got != 0 {
t.Fatalf("active = %d, want 0", got)
}
if got := capacity.Reserved(); got != 0 {
t.Fatalf("reserved = %d, want 0", got)
}
}
func contains(s, part string) bool {
for i := 0; i+len(part) <= len(s); i++ {
if s[i:i+len(part)] == part {
return true
}
}
return false
}
func timePtr(value time.Time) *time.Time { return &value }
func equalTimePtr(a, b *time.Time) bool {
if a == nil || b == nil {
return a == b
}
return a.Equal(*b)
}