package config_test import ( "os" "testing" "time" "github.com/libnovel/backend/internal/config" ) func TestLoad_Defaults(t *testing.T) { // Unset all relevant vars so we test pure defaults. unset := []string{ "LOG_LEVEL", "POCKETBASE_URL", "POCKETBASE_ADMIN_EMAIL", "POCKETBASE_ADMIN_PASSWORD", "MINIO_ENDPOINT", "MINIO_PUBLIC_ENDPOINT", "MINIO_ACCESS_KEY", "MINIO_SECRET_KEY", "MINIO_USE_SSL", "MINIO_PUBLIC_USE_SSL", "MINIO_BUCKET_CHAPTERS", "MINIO_BUCKET_AUDIO", "MINIO_BUCKET_AVATARS", "KOKORO_URL", "KOKORO_VOICE", "BACKEND_HTTP_ADDR", "RUNNER_POLL_INTERVAL", "RUNNER_MAX_CONCURRENT_SCRAPE", "RUNNER_MAX_CONCURRENT_AUDIO", "RUNNER_WORKER_ID", "RUNNER_WORKERS", "RUNNER_TIMEOUT", "SCRAPER_PROXY", } for _, k := range unset { t.Setenv(k, "") } cfg := config.Load() if cfg.LogLevel != "info" { t.Errorf("LogLevel: want info, got %q", cfg.LogLevel) } if cfg.PocketBase.URL != "http://localhost:8090" { t.Errorf("PocketBase.URL: want http://localhost:8090, got %q", cfg.PocketBase.URL) } if cfg.MinIO.BucketChapters != "libnovel-chapters" { t.Errorf("MinIO.BucketChapters: want libnovel-chapters, got %q", cfg.MinIO.BucketChapters) } if cfg.MinIO.UseSSL != false { t.Errorf("MinIO.UseSSL: want false, got %v", cfg.MinIO.UseSSL) } if cfg.MinIO.PublicUseSSL != true { t.Errorf("MinIO.PublicUseSSL: want true, got %v", cfg.MinIO.PublicUseSSL) } if cfg.Kokoro.DefaultVoice != "af_bella" { t.Errorf("Kokoro.DefaultVoice: want af_bella, got %q", cfg.Kokoro.DefaultVoice) } if cfg.HTTP.Addr != ":8080" { t.Errorf("HTTP.Addr: want :8080, got %q", cfg.HTTP.Addr) } if cfg.Runner.PollInterval != 30*time.Second { t.Errorf("Runner.PollInterval: want 30s, got %v", cfg.Runner.PollInterval) } if cfg.Runner.MaxConcurrentScrape != 1 { t.Errorf("Runner.MaxConcurrentScrape: want 1, got %d", cfg.Runner.MaxConcurrentScrape) } if cfg.Runner.MaxConcurrentAudio != 1 { t.Errorf("Runner.MaxConcurrentAudio: want 1, got %d", cfg.Runner.MaxConcurrentAudio) } } func TestLoad_EnvOverride(t *testing.T) { t.Setenv("LOG_LEVEL", "debug") t.Setenv("POCKETBASE_URL", "https://pb.libnovel.cc") t.Setenv("MINIO_USE_SSL", "true") t.Setenv("MINIO_PUBLIC_USE_SSL", "false") t.Setenv("RUNNER_POLL_INTERVAL", "1m") t.Setenv("RUNNER_MAX_CONCURRENT_SCRAPE", "5") t.Setenv("RUNNER_WORKER_ID", "homelab-01") t.Setenv("BACKEND_HTTP_ADDR", ":9090") t.Setenv("KOKORO_URL", "https://kokoro.libnovel.cc") cfg := config.Load() if cfg.LogLevel != "debug" { t.Errorf("LogLevel: want debug, got %q", cfg.LogLevel) } if cfg.PocketBase.URL != "https://pb.libnovel.cc" { t.Errorf("PocketBase.URL: want https://pb.libnovel.cc, got %q", cfg.PocketBase.URL) } if !cfg.MinIO.UseSSL { t.Error("MinIO.UseSSL: want true") } if cfg.MinIO.PublicUseSSL { t.Error("MinIO.PublicUseSSL: want false") } if cfg.Runner.PollInterval != time.Minute { t.Errorf("Runner.PollInterval: want 1m, got %v", cfg.Runner.PollInterval) } if cfg.Runner.MaxConcurrentScrape != 5 { t.Errorf("Runner.MaxConcurrentScrape: want 5, got %d", cfg.Runner.MaxConcurrentScrape) } if cfg.Runner.WorkerID != "homelab-01" { t.Errorf("Runner.WorkerID: want homelab-01, got %q", cfg.Runner.WorkerID) } if cfg.HTTP.Addr != ":9090" { t.Errorf("HTTP.Addr: want :9090, got %q", cfg.HTTP.Addr) } if cfg.Kokoro.URL != "https://kokoro.libnovel.cc" { t.Errorf("Kokoro.URL: want https://kokoro.libnovel.cc, got %q", cfg.Kokoro.URL) } } func TestLoad_InvalidInt_FallsToDefault(t *testing.T) { t.Setenv("RUNNER_MAX_CONCURRENT_SCRAPE", "notanumber") cfg := config.Load() if cfg.Runner.MaxConcurrentScrape != 1 { t.Errorf("want default 1, got %d", cfg.Runner.MaxConcurrentScrape) } } func TestLoad_InvalidDuration_FallsToDefault(t *testing.T) { t.Setenv("RUNNER_POLL_INTERVAL", "notaduration") cfg := config.Load() if cfg.Runner.PollInterval != 30*time.Second { t.Errorf("want default 30s, got %v", cfg.Runner.PollInterval) } } func TestLoad_WorkerID_FallsToHostname(t *testing.T) { t.Setenv("RUNNER_WORKER_ID", "") cfg := config.Load() host, _ := os.Hostname() if host != "" && cfg.Runner.WorkerID != host { t.Errorf("want hostname %q, got %q", host, cfg.Runner.WorkerID) } }