package config import ( "os" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func clearEnv(t *testing.T) { t.Helper() for _, key := range []string{ "APP_ENV", "TEMPORAL_HOSTPORT", "TEMPORAL_NAMESPACE", "TEMPORAL_TLS_CERT", "TEMPORAL_TLS_KEY", "TEMPORAL_TASK_QUEUE", "TEMPORAL_WORKER_COUNT", "MEMORY_SERVICE_URL", "MEMORY_SERVICE_JWT_TOKEN", "LOCAL_LLM_BASE_URL", "ANTHROPIC_API_KEY", "LLM_AUTH_TOKEN", "LOG_LEVEL", "KUBERNETES_SERVICE_HOST", } { os.Unsetenv(key) } } func TestLoadConfigDefaults(t *testing.T) { clearEnv(t) cfg, err := LoadConfig() require.NoError(t, err) assert.Equal(t, EnvDev, cfg.Env) assert.Equal(t, "127.0.0.1:7233", cfg.Temporal.HostPort) assert.Equal(t, "poimen-harness", cfg.Temporal.Namespace) assert.Equal(t, "poimen-taskqueue", cfg.Temporal.TaskQueue) assert.Equal(t, 10, cfg.Temporal.WorkerCount) assert.Equal(t, "info", cfg.LogLevel) } func TestLoadConfigFromEnv(t *testing.T) { clearEnv(t) os.Setenv("APP_ENV", "staging") os.Setenv("TEMPORAL_HOSTPORT", "temporal:7233") os.Setenv("TEMPORAL_NAMESPACE", "test-ns") os.Setenv("TEMPORAL_TASK_QUEUE", "test-queue") os.Setenv("TEMPORAL_WORKER_COUNT", "5") os.Setenv("MEMORY_SERVICE_URL", "http://memory:8080") os.Setenv("ANTHROPIC_API_KEY", "sk-test") os.Setenv("LOG_LEVEL", "debug") cfg, err := LoadConfig() require.NoError(t, err) assert.Equal(t, EnvStaging, cfg.Env) assert.Equal(t, "temporal:7233", cfg.Temporal.HostPort) assert.Equal(t, "test-ns", cfg.Temporal.Namespace) assert.Equal(t, "test-queue", cfg.Temporal.TaskQueue) assert.Equal(t, 5, cfg.Temporal.WorkerCount) assert.Equal(t, "http://memory:8080", cfg.MemoryService.URL) assert.Equal(t, "sk-test", cfg.LLM.AnthropicKey) assert.Equal(t, "debug", cfg.LogLevel) } func TestValidateTLSMismatch(t *testing.T) { clearEnv(t) os.Setenv("TEMPORAL_TLS_CERT", "/tmp/cert.pem") // Missing TLS_KEY _, err := LoadConfig() assert.Error(t, err) assert.Contains(t, err.Error(), "TEMPORAL_TLS_CERT and TEMPORAL_TLS_KEY must both be set") } func TestValidateTLSFileNotFound(t *testing.T) { clearEnv(t) os.Setenv("TEMPORAL_TLS_CERT", "/nonexistent/cert.pem") os.Setenv("TEMPORAL_TLS_KEY", "/nonexistent/key.pem") _, err := LoadConfig() assert.Error(t, err) assert.Contains(t, err.Error(), "not found") } func TestValidateProdRequiresLLMKey(t *testing.T) { clearEnv(t) os.Setenv("APP_ENV", "prod") _, err := LoadConfig() assert.Error(t, err) assert.Contains(t, err.Error(), "prod requires ANTHROPIC_API_KEY or LLM_AUTH_TOKEN") } func TestValidateProdWithAnthropicKey(t *testing.T) { clearEnv(t) os.Setenv("APP_ENV", "prod") os.Setenv("ANTHROPIC_API_KEY", "sk-prod") cfg, err := LoadConfig() require.NoError(t, err) assert.True(t, cfg.IsProd()) assert.False(t, cfg.IsDevOrStaging()) } func TestValidateProdWithAuthToken(t *testing.T) { clearEnv(t) os.Setenv("APP_ENV", "prod") os.Setenv("LLM_AUTH_TOKEN", "token-prod") cfg, err := LoadConfig() require.NoError(t, err) assert.True(t, cfg.IsProd()) } func TestParseEnv(t *testing.T) { assert.Equal(t, EnvDev, parseEnv("dev")) assert.Equal(t, EnvDev, parseEnv("unknown")) assert.Equal(t, EnvStaging, parseEnv("staging")) assert.Equal(t, EnvStaging, parseEnv("stage")) assert.Equal(t, EnvProd, parseEnv("prod")) assert.Equal(t, EnvProd, parseEnv("production")) } func TestDefaultTemporalHostInCluster(t *testing.T) { clearEnv(t) os.Setenv("KUBERNETES_SERVICE_HOST", "10.0.0.1") cfg, err := LoadConfig() require.NoError(t, err) assert.Equal(t, "temporal-frontend.temporal.svc.cluster.local:7233", cfg.Temporal.HostPort) } func TestAddDefaultPort(t *testing.T) { assert.Equal(t, "host:7233", addDefaultPort("host")) assert.Equal(t, "host:9090", addDefaultPort("host:9090")) } func TestGetEnvIntOrDefault(t *testing.T) { clearEnv(t) assert.Equal(t, 10, getEnvIntOrDefault("TEMPORAL_WORKER_COUNT", 10)) os.Setenv("TEMPORAL_WORKER_COUNT", "abc") assert.Equal(t, 10, getEnvIntOrDefault("TEMPORAL_WORKER_COUNT", 10)) os.Setenv("TEMPORAL_WORKER_COUNT", "20") assert.Equal(t, 20, getEnvIntOrDefault("TEMPORAL_WORKER_COUNT", 10)) }