Files
tokens-reef/backend/internal/config/config_domain_test.go
User a4eb4d4c3a refactor(config): split config.go into modular files
Split the monolithic config.go (~120KB) into focused modules:
- auth.go: JWT, TOTP, Turnstile, RateLimit configs
- billing.go: Billing and Pricing configs
- database.go: Database and Redis configs
- gateway.go: Gateway and Upstream configs
- gateway_sub.go: Gateway sub-configurations
- ops_and_cache.go: Ops and Cache configs
- platforms.go: Platform-specific configs
- security.go: Security-related configs
- server.go: Server configuration
- config_defaults.go: Default values
- config_defaults_detail.go: Detailed defaults
- config_helpers.go: Helper functions
- config_validate.go: Validation logic
- config_validate_gateway.go: Gateway validation

This improves:
- Code maintainability and readability
- Faster compilation (smaller files)
- Easier navigation and debugging
- Better separation of concerns
2026-04-17 07:22:55 +08:00

202 lines
7.8 KiB
Go

package config
import (
"strings"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
// =============================================================================
// Test: Config Domain Split — Type Definitions & Struct Integrity
// 验证拆分后的 15 个域文件中的所有类型定义正确、字段完整
// =============================================================================
func TestConfigStructIntegrity(t *testing.T) {
t.Parallel()
cfg := Config{}
assert.IsType(t, ServerConfig{}, cfg.Server)
assert.IsType(t, H2CConfig{}, cfg.Server.H2C)
assert.IsType(t, CORSConfig{}, CORSConfig{})
assert.IsType(t, ConcurrencyConfig{}, ConcurrencyConfig{})
assert.IsType(t, SecurityConfig{}, cfg.Security)
assert.IsType(t, URLAllowlistConfig{}, cfg.Security.URLAllowlist)
assert.IsType(t, ResponseHeaderConfig{}, cfg.Security.ResponseHeaders)
assert.IsType(t, CSPConfig{}, cfg.Security.CSP)
assert.IsType(t, ProxyFallbackConfig{}, cfg.Security.ProxyFallback)
assert.IsType(t, ProxyProbeConfig{}, cfg.Security.ProxyProbe)
assert.IsType(t, DatabaseConfig{}, cfg.Database)
assert.IsType(t, RedisConfig{}, cfg.Redis)
assert.IsType(t, JWTConfig{}, cfg.JWT)
assert.IsType(t, TotpConfig{}, cfg.Totp)
assert.IsType(t, TurnstileConfig{}, cfg.Turnstile)
assert.IsType(t, DefaultConfig{}, cfg.Default)
assert.IsType(t, RateLimitConfig{}, cfg.RateLimit)
assert.IsType(t, BillingConfig{}, cfg.Billing)
assert.IsType(t, PricingConfig{}, cfg.Pricing)
assert.IsType(t, GatewayConfig{}, cfg.Gateway)
assert.IsType(t, GatewayOpenAIWSConfig{}, cfg.Gateway.OpenAIWS)
assert.IsType(t, GatewayUsageRecordConfig{}, cfg.Gateway.UsageRecord)
assert.IsType(t, TLSFingerprintConfig{}, cfg.Gateway.TLSFingerprint)
assert.IsType(t, UserMessageQueueConfig{}, cfg.Gateway.UserMessageQueue)
assert.IsType(t, GatewaySchedulingConfig{}, cfg.Gateway.Scheduling)
assert.IsType(t, GatewayOpenAIWSSchedulerScoreWeights{}, cfg.Gateway.OpenAIWS.SchedulerScoreWeights)
assert.IsType(t, SoraConfig{}, cfg.Sora)
assert.IsType(t, GeminiConfig{}, cfg.Gemini)
assert.IsType(t, UpdateConfig{}, cfg.Update)
assert.IsType(t, IdempotencyConfig{}, cfg.Idempotency)
assert.IsType(t, LinuxDoConnectConfig{}, cfg.LinuxDo)
assert.IsType(t, OIDCConnectConfig{}, cfg.OIDC)
assert.IsType(t, OpsConfig{}, cfg.Ops)
assert.IsType(t, LogConfig{}, cfg.Log)
assert.IsType(t, DashboardCacheConfig{}, cfg.Dashboard)
assert.IsType(t, DashboardAggregationConfig{}, cfg.DashboardAgg)
assert.IsType(t, UsageCleanupConfig{}, cfg.UsageCleanup)
assert.IsType(t, ConcurrencyConfig{}, cfg.Concurrency)
assert.IsType(t, TokenRefreshConfig{}, cfg.TokenRefresh)
assert.IsType(t, APIKeyAuthCacheConfig{}, cfg.APIKeyAuth)
assert.IsType(t, SubscriptionCacheConfig{}, cfg.SubscriptionCache)
}
func TestServerConfigDefaults(t *testing.T) {
s := ServerConfig{}
if s.Host != "" { t.Error("Host should default to empty") }
if s.Port != 0 { t.Error("Port should default to 0") }
}
func TestH2CConfigFields(t *testing.T) {
h := H2CConfig{
Enabled: true, MaxConcurrentStreams: 100, IdleTimeout: 75,
MaxReadFrameSize: 1 << 20, MaxUploadBufferPerConnection: 2 << 20,
}
if !h.Enabled { t.Error("Enabled should be true") }
if h.MaxConcurrentStreams != 100 { t.Error("MaxConcurrentStreams mismatch") }
}
func TestSecurityConfigFields(t *testing.T) {
s := SecurityConfig{}
if s.URLAllowlist.Enabled { t.Error("URLAllowlist.Enabled should be false") }
if s.ProxyFallback.AllowDirectOnError { t.Error("AllowDirectOnError should be false") }
if s.ProxyProbe.InsecureSkipVerify { t.Error("InsecureSkipVerify should be false") }
}
func TestDatabaseConfig_DSN(t *testing.T) {
tests := []struct {
name string
cfg DatabaseConfig
check func(DatabaseConfig) string
contains []string
exclude []string
}{
{"no password", DatabaseConfig{Host: "localhost", Port: 5432, User: "u", DBName: "db", SSLMode: "s"},
func(c DatabaseConfig) string { return c.DSN() },
[]string{"host=localhost", "port=5432"}, []string{"password="}},
{"with password", DatabaseConfig{Host: "h", Port: 1, User: "u", Password: "p", DBName: "d", SSLMode: "s"},
func(c DatabaseConfig) string { return c.DSN() },
[]string{"password=p"}, nil},
{"tz default", DatabaseConfig{Host: "h", Port: 1, User: "u", DBName: "d", SSLMode: "s"},
func(c DatabaseConfig) string { return c.DSNWithTimezone("") },
[]string{"TimeZone=Asia/Shanghai"}, nil},
{"tz custom", DatabaseConfig{Host: "h", Port: 1, User: "u", DBName: "d", SSLMode: "s"},
func(c DatabaseConfig) string { return c.DSNWithTimezone("UTC") },
[]string{"TimeZone=UTC"}, nil},
}
for _, tc := range tests {
tc := tc
t.Run(tc.name, func(t *testing.T) {
got := tc.check(tc.cfg)
for _, sub := range tc.contains { assert.Contains(t, got, sub) }
for _, sub := range tc.exclude { assert.NotContains(t, got, sub) }
})
}
}
func TestRedisConfig_Address(t *testing.T) {
r := RedisConfig{Host: "redis.local", Port: 6380}
if r.Address() != "redis.local:6380" { t.Errorf("Address = %q", r.Address()) }
}
func TestJWTConfigFields(t *testing.T) {
j := JWTConfig{Secret: strings.Repeat("x", 32), ExpireHour: 24, RefreshTokenExpireDays: 30}
if j.RefreshTokenExpireDays != 30 { t.Error("RefreshTokenExpireDays mismatch") }
}
func TestTotpConfigFields(t *testing.T) {
tc := TotpConfig{EncryptionKeyConfigured: true}
if !tc.EncryptionKeyConfigured { t.Error("should be true") }
}
func TestGatewayConstants(t *testing.T) {
policies := []string{UsageRecordOverflowPolicyDrop, UsageRecordOverflowPolicySample, UsageRecordOverflowPolicySync}
unique := make(map[string]bool, len(policies))
for _, p := range policies { unique[p] = true }
if len(unique) != len(policies) { t.Error("overflow policies must be unique") }
if UMQModeSerialize == UMQModeThrottle { t.Error("modes must differ") }
strategies := []string{ConnectionPoolIsolationProxy, ConnectionPoolIsolationAccount, ConnectionPoolIsolationAccountProxy}
uniqueS := map[string]bool{}
for _, s := range strategies { uniqueS[s] = true }
if len(uniqueS) != len(strategies) { t.Error("strategies must be unique") }
}
func TestUserMessageQueueConfig_Methods(t *testing.T) {
q := UserMessageQueueConfig{}
if q.WaitTimeout() != 30*time.Second { t.Error("default WaitTimeout should be 30s") }
q.WaitTimeoutMs = 5000
if q.WaitTimeout() != 5*time.Second { t.Error("custom WaitTimeout should be 5s") }
q.Mode = UMQModeThrottle
if q.GetEffectiveMode() != UMQModeThrottle { t.Error("mode should be throttle") }
q.Mode = ""
q.Enabled = true
if q.GetEffectiveMode() != UMQModeSerialize { t.Error("enabled+empty → serialize") }
q.Enabled = false
if q.GetEffectiveMode() != "" { t.Error("disabled+empty → empty") }
}
func TestSoraConfigFields(t *testing.T) {
s := SoraConfig{
Client: SoraClientConfig{BaseURL: "https://sora.example.com"},
Storage: SoraStorageConfig{Type: "local"},
}
if s.Client.BaseURL != "https://sora.example.com" { t.Error("BaseURL mismatch") }
}
func TestGeminiConfigFields(t *testing.T) {
g := GeminiConfig{Quota: GeminiQuotaConfig{Policy: "conservative"}}
if g.Quota.Policy != "conservative" { t.Error("Policy mismatch") }
}
func TestOpsAndCacheConfigFields(t *testing.T) {
lc := LogConfig{Level: "info"}
if lc.Level != "info" { t.Error("Level mismatch") }
r := DashboardAggregationRetentionConfig{UsageLogsDays: 90, UsageBillingDedupDays: 365}
if r.UsageBillingDedupDays < r.UsageLogsDays { t.Error("invariant violation: dedup >= logs") }
}
func TestBillingAndPricingConfig(t *testing.T) {
bc := BillingConfig{CircuitBreaker: CircuitBreakerConfig{Enabled: true}}
if !bc.CircuitBreaker.Enabled { t.Error("should be enabled") }
}
func TestConstants(t *testing.T) {
if RunModeStandard != "standard" { t.Error("RunModeStandard wrong") }
if RunModeSimple != "simple" { t.Error("RunModeSimple wrong") }
if !strings.Contains(DefaultCSPPolicy, "__CSP_NONCE__") { t.Error("CSPPolicy missing nonce placeholder") }
}