Files
ai-ops/internal/config/config_test.go
2026-05-12 17:48:22 +08:00

137 lines
3.3 KiB
Go

package config
import (
"os"
"path/filepath"
"strings"
"testing"
)
func TestLoadReadsConfigAndBuildsDSN(t *testing.T) {
dir := t.TempDir()
path := filepath.Join(dir, "config.yaml")
content := []byte(`server:
port: 19090
mode: production
jwt_secret: "0123456789abcdef0123456789abcdef"
metrics_auth: "metrics-api-key-123456"
database:
host: db
port: 15432
user: user
password: pass
dbname: aiops
sslmode: require
pool_size: 7
redis:
host: redis
port: 16379
password: redispass
db: 2
metrics:
prometheus_url: http://prom
retention_days: 14
`)
if err := os.WriteFile(path, content, 0o600); err != nil {
t.Fatal(err)
}
cfg, err := Load(path)
if err != nil {
t.Fatal(err)
}
if cfg.Server.Port != 19090 || cfg.Database.Host != "db" || cfg.Redis.DB != 2 || cfg.Metrics.RetentionDays != 14 {
t.Fatalf("unexpected config: %+v", cfg)
}
dsn := cfg.Database.DSN()
for _, want := range []string{"host=db", "port=15432", "user=user", "password=pass", "dbname=aiops", "sslmode=require", "pool_max_conns=7"} {
if !strings.Contains(dsn, want) {
t.Fatalf("dsn %q missing %q", dsn, want)
}
}
}
func TestLoadAppliesDefaultsAndSpringDatasourceCompatibility(t *testing.T) {
t.Setenv("SPRING_DATASOURCE_URL", "spring-host")
path := filepath.Join(t.TempDir(), "empty.yaml")
if err := os.WriteFile(path, []byte("{}\n"), 0o600); err != nil {
t.Fatal(err)
}
cfg, err := Load(path)
if err != nil {
t.Fatal(err)
}
if cfg.Server.Port != 8080 || cfg.Database.Port != 5432 || cfg.Redis.Port != 6379 || cfg.Metrics.RetentionDays != 7 {
t.Fatalf("defaults not applied: %+v", cfg)
}
if cfg.Database.Host != "spring-host" {
t.Fatalf("spring datasource compatibility not applied: %s", cfg.Database.Host)
}
}
func TestLoadReturnsErrorForMalformedConfig(t *testing.T) {
path := filepath.Join(t.TempDir(), "bad.yaml")
if err := os.WriteFile(path, []byte("server: ["), 0o600); err != nil {
t.Fatal(err)
}
if _, err := Load(path); err == nil {
t.Fatal("expected malformed config error")
}
}
func TestLoadRejectsWeakProductionSecrets(t *testing.T) {
path := filepath.Join(t.TempDir(), "config.yaml")
content := []byte(`server:
mode: production
jwt_secret: short
metrics_auth: short
database:
host: db
port: 5432
user: aiops
password: aiops123
dbname: ai_ops
pool_size: 1
metrics:
retention_days: 7
`)
if err := os.WriteFile(path, content, 0o600); err != nil {
t.Fatal(err)
}
_, err := Load(path)
if err == nil || !strings.Contains(err.Error(), "jwt_secret") {
t.Fatalf("expected weak jwt secret error, got %v", err)
}
}
func TestLoadAppliesExplicitEnvironmentOverrides(t *testing.T) {
path := filepath.Join(t.TempDir(), "config.yaml")
content := []byte(`server:
mode: production
jwt_secret: "0123456789abcdef0123456789abcdef"
metrics_auth: "metrics-api-key-123456"
database:
host: db
port: 5432
user: aiops
password: aiops123
dbname: ai_ops
pool_size: 1
metrics:
retention_days: 7
`)
if err := os.WriteFile(path, content, 0o600); err != nil {
t.Fatal(err)
}
t.Setenv("AI_OPS_DATABASE_PASSWORD", "override-pass")
t.Setenv("AI_OPS_SERVER_METRICS_AUTH", "override-metrics-key")
cfg, err := Load(path)
if err != nil {
t.Fatal(err)
}
if cfg.Database.Password != "override-pass" || cfg.Server.MetricsAuth != "override-metrics-key" {
t.Fatalf("env overrides not applied: %+v", cfg)
}
}