97 lines
3.3 KiB
Go
97 lines
3.3 KiB
Go
package bootstrap
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
"sync/atomic"
|
|
"testing"
|
|
|
|
"proxy-pool/internal/config"
|
|
)
|
|
|
|
func TestProductionInfrastructureRejectsInvalidStorageWithoutLeakingURLs(t *testing.T) {
|
|
t.Parallel()
|
|
postgresSecret := "postgres-secret"
|
|
_, err := (&productionInfrastructure{}).Open(context.Background(), &config.Config{
|
|
Admin: config.Listener{Enabled: true},
|
|
Storage: config.Storage{PostgresURL: "postgres://user:" + postgresSecret + "@%zz"},
|
|
})
|
|
if !errors.Is(err, ErrPostgresConfiguration) || strings.Contains(err.Error(), postgresSecret) {
|
|
t.Fatalf("Open(invalid PostgreSQL) error = %v", err)
|
|
}
|
|
|
|
redisSecret := "redis-secret"
|
|
_, err = (&productionInfrastructure{}).Open(context.Background(), &config.Config{
|
|
Distribution: config.Distribution{Listener: config.Listener{Enabled: true}},
|
|
Storage: config.Storage{RedisURL: "redis://user:" + redisSecret + "@%zz"},
|
|
})
|
|
if !errors.Is(err, ErrRedisConfiguration) || strings.Contains(err.Error(), redisSecret) {
|
|
t.Fatalf("Open(invalid Redis) error = %v", err)
|
|
}
|
|
}
|
|
|
|
func TestSelectMetricsReadinessPreservesDistributionWhenAdminStoreFails(t *testing.T) {
|
|
t.Parallel()
|
|
adminCalls := &atomic.Int64{}
|
|
activityCalls := &atomic.Int64{}
|
|
adminReady := readinessFunc(func(context.Context) error {
|
|
adminCalls.Add(1)
|
|
return ErrPostgresUnavailable
|
|
})
|
|
activityReady := readinessFunc(func(context.Context) error {
|
|
activityCalls.Add(1)
|
|
return nil
|
|
})
|
|
selected := selectMetricsReadiness(&config.Config{
|
|
Admin: config.Listener{Enabled: true},
|
|
Distribution: config.Distribution{Listener: config.Listener{Enabled: true}},
|
|
}, adminReady, activityReady)
|
|
if err := selected.Ready(context.Background()); err != nil {
|
|
t.Fatalf("Ready() error = %v", err)
|
|
}
|
|
if adminCalls.Load() != 0 || activityCalls.Load() != 1 {
|
|
t.Fatalf("readiness calls = admin:%d activity:%d", adminCalls.Load(), activityCalls.Load())
|
|
}
|
|
}
|
|
|
|
func TestSelectMetricsReadinessUsesAdminStoresWithoutDistribution(t *testing.T) {
|
|
t.Parallel()
|
|
wantErr := errors.New("admin unavailable")
|
|
selected := selectMetricsReadiness(
|
|
&config.Config{Admin: config.Listener{Enabled: true}},
|
|
readinessFunc(func(context.Context) error { return wantErr }),
|
|
readinessFunc(func(context.Context) error { return nil }),
|
|
)
|
|
if err := selected.Ready(context.Background()); !errors.Is(err, wantErr) {
|
|
t.Fatalf("Ready() error = %v, want %v", err, wantErr)
|
|
}
|
|
}
|
|
|
|
type readinessFunc func(context.Context) error
|
|
|
|
func (function readinessFunc) Ready(ctx context.Context) error { return function(ctx) }
|
|
|
|
func TestProductionRedisSizingUsesConfigurationBounds(t *testing.T) {
|
|
t.Parallel()
|
|
configuration := &config.Config{
|
|
Distribution: config.Distribution{Extraction: config.Extraction{
|
|
MaxCountPerRequest: 100, ReserveForGateway: 5_000,
|
|
}},
|
|
Upstreams: map[string]config.Upstream{
|
|
"provider-a": {Pool: config.Pool{MaxSize: 3_000}},
|
|
"provider-b": {Pool: config.Pool{MaxSize: 2_000}},
|
|
},
|
|
}
|
|
if got := credentialCapacity(configuration); got != 5_000 {
|
|
t.Fatalf("credentialCapacity() = %d, want 5000", got)
|
|
}
|
|
if got := candidateScan(configuration); got != 5_100 {
|
|
t.Fatalf("candidateScan() = %d, want 5100", got)
|
|
}
|
|
configuration.Distribution.Extraction = config.Extraction{MaxCountPerRequest: 1}
|
|
if got := candidateScan(configuration); got != redisMinimumScan {
|
|
t.Fatalf("candidateScan(minimum) = %d, want %d", got, redisMinimumScan)
|
|
}
|
|
}
|