Files
story/internal/config/config_test.go
T

233 lines
8.3 KiB
Go
Raw Normal View History

2026-08-26 06:41:07 +08:00
package config
import (
"os"
"path/filepath"
"strings"
"testing"
)
func TestLoadUsesServicePortDefaults(t *testing.T) {
t.Setenv("HTTP_ADDR", "")
t.Setenv("APP_ENV", "test")
tests := map[string]string{
"api": "0.0.0.0:58080",
"callbacks": "0.0.0.0:58081",
"worker": "0.0.0.0:58082",
}
for service, expected := range tests {
cfg, err := Load(service)
if err != nil {
t.Fatalf("Load(%s) returned error: %v", service, err)
}
if cfg.HTTPAddr != expected {
t.Fatalf("Load(%s).HTTPAddr = %s, want %s", service, cfg.HTTPAddr, expected)
}
}
}
2026-08-26 10:51:33 +08:00
func TestLoadAllowsTracingExporterToBeDisabled(t *testing.T) {
t.Setenv("OTEL_EXPORTER_OTLP_ENDPOINT", "")
cfg, err := Load("api")
if err != nil {
t.Fatal(err)
}
if cfg.OTLPEndpoint != "" {
t.Fatalf("OTLPEndpoint = %q, want disabled exporter", cfg.OTLPEndpoint)
}
}
2026-08-26 06:41:07 +08:00
func TestLoadRejectsInvalidDuration(t *testing.T) {
t.Setenv("DEPENDENCY_TIMEOUT", "soon")
if _, err := Load("api"); err == nil {
t.Fatal("Load should reject an invalid duration")
}
}
func TestLoadReadsSecretsFromAbsoluteFiles(t *testing.T) {
secret := strings.Repeat("k", 40)
path := filepath.Join(t.TempDir(), "ark-api-key")
if err := os.WriteFile(path, []byte(secret+"\n"), 0o600); err != nil {
t.Fatal(err)
}
t.Setenv("ARK_API_KEY", "")
t.Setenv("ARK_API_KEY_FILE", path)
databaseURL := "postgres://voice:secret@db.example.com:5432/voice?sslmode=verify-full"
databasePath := filepath.Join(t.TempDir(), "database-url")
if err := os.WriteFile(databasePath, []byte(databaseURL+"\r\n"), 0o600); err != nil {
t.Fatal(err)
}
t.Setenv("DATABASE_URL", "")
t.Setenv("DATABASE_URL_FILE", databasePath)
cfg, err := Load("worker")
if err != nil {
t.Fatal(err)
}
if cfg.ArkAPIKey != secret {
t.Fatalf("secret file value was not loaded")
}
if cfg.DatabaseURL != databaseURL {
t.Fatalf("database URL file value was not loaded")
}
}
func TestLoadRejectsAmbiguousSecretSources(t *testing.T) {
path := filepath.Join(t.TempDir(), "redis-password")
if err := os.WriteFile(path, []byte(strings.Repeat("r", 40)), 0o600); err != nil {
t.Fatal(err)
}
t.Setenv("REDIS_PASSWORD", strings.Repeat("x", 40))
t.Setenv("REDIS_PASSWORD_FILE", path)
if _, err := Load("api"); err == nil || !strings.Contains(err.Error(), "cannot both") {
t.Fatalf("Load() error=%v, want ambiguous secret source rejection", err)
}
}
func TestValidateRejectsUnknownEnvironment(t *testing.T) {
cfg, err := Load("api")
if err != nil {
t.Fatalf("unexpected load error: %v", err)
}
cfg.Environment = "production-ish"
if err := cfg.Validate(); err == nil {
t.Fatal("Validate should reject an unknown environment")
}
}
func TestProductionRejectsLocalDefaults(t *testing.T) {
cfg, err := Load("api")
if err != nil {
t.Fatalf("unexpected load error: %v", err)
}
cfg.Environment = EnvironmentProd
if err := cfg.Validate(); err == nil || !strings.Contains(err.Error(), "HTTPS") {
t.Fatalf("Validate() error = %v, want HTTPS production gate", err)
}
}
func TestProductionAPIAcceptsHardenedConfiguration(t *testing.T) {
cfg, err := Load("api")
if err != nil {
t.Fatalf("unexpected load error: %v", err)
}
cfg.Environment = EnvironmentProd
cfg.DatabaseURL = "postgres://voice:secret@postgres.example.internal:5432/voice?sslmode=verify-full"
cfg.RedisPassword = strings.Repeat("r", 40)
cfg.AuthIssuerURL = "https://identity.example.com/realms/voice"
cfg.AuthJWKSURL = "https://identity.example.com/realms/voice/certs"
cfg.DeviceLocalSecret = strings.Repeat("d", 40)
cfg.DeviceSecretDirectory = t.TempDir()
cfg.RTCTokenSecret = strings.Repeat("t", 40)
cfg.RTCTokenIssuer = "volcengine"
cfg.RTCAppKey = strings.Repeat("v", 40)
cfg.CursorSigningSecret = strings.Repeat("c", 40)
cfg.ShareTokenSecret = strings.Repeat("h", 40)
cfg.RTCAppID = "661e7ae5543cf00000000000"
cfg.ObjectStoreEndpoint = "objects.internal.example.com:9000"
cfg.ObjectStorePublic = "objects.example.com"
cfg.ObjectStoreAccessKey = strings.Repeat("a", 40)
cfg.ObjectStoreSecretKey = strings.Repeat("s", 40)
cfg.ObjectStoreSecure = true
2026-08-26 10:26:06 +08:00
cfg.ObjectStorePublicSecure = true
2026-08-26 06:41:07 +08:00
cfg.EmbeddingProvider = "ark"
cfg.ArkBaseURL = "https://ark.cn-beijing.volces.com/api/v3"
cfg.ArkAPIKey = strings.Repeat("k", 40)
cfg.ArkEmbeddingModel = "doubao-production-embedding"
if err := cfg.Validate(); err != nil {
t.Fatalf("Validate() returned error for hardened production config: %v", err)
}
}
func TestProductionRejectsReusedSigningSecrets(t *testing.T) {
cfg, err := Load("api")
if err != nil {
t.Fatalf("unexpected load error: %v", err)
}
cfg.Environment = EnvironmentProd
cfg.DatabaseURL = "postgres://voice:secret@postgres.example.internal:5432/voice?sslmode=require"
cfg.RedisPassword = strings.Repeat("r", 40)
cfg.AuthIssuerURL = "https://identity.example.com/realms/voice"
cfg.AuthJWKSURL = "https://identity.example.com/realms/voice/certs"
cfg.DeviceLocalSecret = strings.Repeat("x", 40)
cfg.DeviceSecretDirectory = t.TempDir()
cfg.RTCTokenSecret = strings.Repeat("x", 40)
cfg.RTCTokenIssuer = "volcengine"
cfg.RTCAppKey = strings.Repeat("v", 40)
cfg.CursorSigningSecret = strings.Repeat("x", 40)
cfg.ShareTokenSecret = strings.Repeat("x", 40)
cfg.RTCAppID = "661e7ae5543cf00000000000"
cfg.ObjectStoreEndpoint = "objects.internal.example.com:9000"
cfg.ObjectStorePublic = "objects.example.com"
cfg.ObjectStoreAccessKey = strings.Repeat("a", 40)
cfg.ObjectStoreSecretKey = strings.Repeat("s", 40)
cfg.ObjectStoreSecure = true
2026-08-26 10:26:06 +08:00
cfg.ObjectStorePublicSecure = true
2026-08-26 06:41:07 +08:00
cfg.EmbeddingProvider = "ark"
cfg.ArkBaseURL = "https://ark.cn-beijing.volces.com/api/v3"
cfg.ArkAPIKey = strings.Repeat("k", 40)
cfg.ArkEmbeddingModel = "doubao-production-embedding"
if err := cfg.Validate(); err == nil || !strings.Contains(err.Error(), "distinct") {
t.Fatalf("Validate() error = %v, want distinct-secret gate", err)
}
}
func TestProductionWorkerRequiresRealArkContentGenerator(t *testing.T) {
cfg, err := Load("worker")
if err != nil {
t.Fatalf("unexpected load error: %v", err)
}
cfg.Environment = EnvironmentProd
cfg.DatabaseURL = "postgres://voice:secret@postgres.example.internal:5432/voice?sslmode=verify-full"
cfg.RedisPassword = strings.Repeat("r", 40)
cfg.AuthIssuerURL = "https://identity.example.com/realms/voice"
cfg.AuthJWKSURL = "https://identity.example.com/realms/voice/certs"
cfg.VoiceProvider = "volcengine"
cfg.VolcRTCBaseURL = "https://rtc.volcengineapi.com"
cfg.VolcAccessKeyID = strings.Repeat("a", 40)
cfg.VolcSecretAccessKey = strings.Repeat("v", 40)
cfg.VolcRTCRegion = "cn-north-1"
cfg.VolcRTCAPIVersion = "2024-12-01"
cfg.VolcVoiceChatTemplate = "/run/secrets/voice-chat-template.json"
cfg.RTCAppID = "661e7ae5543cf00000000000"
cfg.ObjectStoreEndpoint = "objects.internal.example.com:9000"
cfg.ObjectStorePublic = "objects.example.com"
cfg.ObjectStoreAccessKey = strings.Repeat("a", 40)
cfg.ObjectStoreSecretKey = strings.Repeat("s", 40)
cfg.ObjectStoreSecure = true
2026-08-26 10:26:06 +08:00
cfg.ObjectStorePublicSecure = true
2026-08-26 06:41:07 +08:00
if err = cfg.Validate(); err == nil || !strings.Contains(err.Error(), "content generation") {
t.Fatalf("Validate() error=%v, want local content generator production gate", err)
}
cfg.ContentGenerator = "ark"
cfg.ArkBaseURL = "https://ark.cn-beijing.volces.com/api/v3"
cfg.ArkAPIKey = strings.Repeat("k", 40)
cfg.ArkContentModel = "doubao-production-model"
cfg.ContentSafetyProvider = "managed_http"
cfg.ContentSafetyEndpoint = "https://content-safety.example.com/v1/classify"
cfg.ContentSafetyAPIKey = strings.Repeat("p", 40)
cfg.ContentSafetyPolicyRef = "elder-story-production-v1"
cfg.EmbeddingProvider = "ark"
cfg.ArkEmbeddingModel = "doubao-production-embedding"
if err = cfg.Validate(); err != nil {
t.Fatalf("Validate() rejected production Ark worker: %v", err)
}
}
func TestWorkerManagedContentSafetyConfiguration(t *testing.T) {
cfg, err := Load("worker")
if err != nil {
t.Fatal(err)
}
cfg.ContentSafetyProvider = "managed_http"
if err = cfg.Validate(); err == nil || !strings.Contains(err.Error(), "content safety") {
t.Fatalf("Validate() error=%v, want incomplete managed content safety rejection", err)
}
cfg.ContentSafetyEndpoint = "http://127.0.0.1:18080/v1/classify"
cfg.ContentSafetyAPIKey = strings.Repeat("s", 40)
cfg.ContentSafetyPolicyRef = "local-contract-test-v1"
if err = cfg.Validate(); err != nil {
t.Fatalf("Validate() rejected complete non-production managed content safety config: %v", err)
}
}