Files
tokens-reef/backend/internal/config/config_domain_test.go
pham 0e057904e6
Some checks failed
CI / test (push) Has been cancelled
CI / golangci-lint (push) Has been cancelled
Security Scan / backend-security (push) Has been cancelled
Security Scan / frontend-security (push) Has been cancelled
refactor: 彻底移除 Sora 视频生成模块(全栈清理)
## 后端变更
- 删除 21 个 sora_*.go 服务文件(service/handler/repository/routes)
- 删除 Sora 相关 migration 文件(046/047/063/090)
- 清理 config 中的 sora_* 配置项和平台常量
- 清理 wire 依赖注入中的 Sora 组件
- 修复 wire_gen.go 语法错误(缺少逗号和闭合括号)
- 移除 go.mod 中的 go-sora2api 依赖
- 更新 ent schema usage_log.go 注释

## 前端变更
- 删除 SoraView、SoraAdminView 及 8 个 Sora 子组件
- 删除 sora API 层和路由配置
- 清理 UserEditModal 中的 Sora 存储配额 UI
- 清理 types/index.ts 中 Sora 相关类型定义
- 清理 stores/app.ts 默认配置
- 清理 i18n 翻译文件 en.ts/zh.ts (~110 行)
- 更新相关测试文件

## 文档更新
- README.md / README_CN.md / README_JA.md: 移除 Sora 状态说明和配置段落
- PROJECT_DIFF.md: 移除 Sora 相关差异描述

## 验证结果
-  Go 编译通过 (go build ./...)
-  TypeScript 类型检查通过 (vue-tsc --noEmit)
-  后端测试全通过 (0 failures)
-  前端测试全通过 (59 files, 329 tests, 0 failures)
-  前端生产构建成功 (23.81s)
2026-05-10 14:15:45 +08:00

193 lines
7.5 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, 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 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") }
}