package config import ( "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestLoadFromEnvUsesDefaults(t *testing.T) { t.Setenv(redisAddrEnvVar, "127.0.0.1:6379") cfg, err := LoadFromEnv() require.NoError(t, err) defaults := DefaultConfig() assert.Equal(t, defaults.ShutdownTimeout, cfg.ShutdownTimeout) assert.Equal(t, defaults.Logging.Level, cfg.Logging.Level) assert.Equal(t, defaults.PublicHTTP, cfg.PublicHTTP) assert.Equal(t, defaults.InternalHTTP, cfg.InternalHTTP) assert.Equal(t, "127.0.0.1:6379", cfg.Redis.Addr) assert.Equal(t, defaults.Redis.DB, cfg.Redis.DB) assert.Equal(t, defaults.Redis.OperationTimeout, cfg.Redis.OperationTimeout) assert.Equal(t, defaults.UserService, cfg.UserService) assert.Equal(t, defaults.MailService, cfg.MailService) assert.Equal(t, defaults.Telemetry.ServiceName, cfg.Telemetry.ServiceName) assert.Equal(t, defaults.Telemetry.TracesExporter, cfg.Telemetry.TracesExporter) assert.Equal(t, defaults.Telemetry.MetricsExporter, cfg.Telemetry.MetricsExporter) assert.False(t, cfg.Telemetry.StdoutTracesEnabled) assert.False(t, cfg.Telemetry.StdoutMetricsEnabled) } func TestLoadFromEnvAppliesOverrides(t *testing.T) { t.Setenv(shutdownTimeoutEnvVar, "9s") t.Setenv(logLevelEnvVar, "debug") t.Setenv(publicHTTPAddrEnvVar, "127.0.0.1:18080") t.Setenv(internalHTTPAddrEnvVar, "127.0.0.1:18081") t.Setenv(redisAddrEnvVar, "127.0.0.1:6380") t.Setenv(redisUsernameEnvVar, "alice") t.Setenv(redisPasswordEnvVar, "secret") t.Setenv(redisDBEnvVar, "3") t.Setenv(redisTLSEnabledEnvVar, "true") t.Setenv(redisOperationTimeoutEnvVar, "750ms") t.Setenv(userServiceModeEnvVar, "rest") t.Setenv(userServiceBaseURLEnvVar, "http://127.0.0.1:19090") t.Setenv(userServiceRequestTimeoutEnvVar, "900ms") t.Setenv(mailServiceModeEnvVar, "rest") t.Setenv(mailServiceBaseURLEnvVar, "http://127.0.0.1:19091") t.Setenv(mailServiceRequestTimeoutEnvVar, "950ms") t.Setenv(otelServiceNameEnvVar, "custom-authsession") t.Setenv(otelTracesExporterEnvVar, "otlp") t.Setenv(otelMetricsExporterEnvVar, "otlp") t.Setenv(otelExporterOTLPProtocolEnvVar, "grpc") t.Setenv(otelStdoutTracesEnabledEnvVar, "true") t.Setenv(otelStdoutMetricsEnabledEnvVar, "true") cfg, err := LoadFromEnv() require.NoError(t, err) assert.Equal(t, 9*time.Second, cfg.ShutdownTimeout) assert.Equal(t, "debug", cfg.Logging.Level) assert.Equal(t, "127.0.0.1:18080", cfg.PublicHTTP.Addr) assert.Equal(t, "127.0.0.1:18081", cfg.InternalHTTP.Addr) assert.Equal(t, "127.0.0.1:6380", cfg.Redis.Addr) assert.Equal(t, "alice", cfg.Redis.Username) assert.Equal(t, "secret", cfg.Redis.Password) assert.Equal(t, 3, cfg.Redis.DB) assert.True(t, cfg.Redis.TLSEnabled) assert.Equal(t, 750*time.Millisecond, cfg.Redis.OperationTimeout) assert.Equal(t, UserServiceConfig{ Mode: "rest", BaseURL: "http://127.0.0.1:19090", RequestTimeout: 900 * time.Millisecond, }, cfg.UserService) assert.Equal(t, MailServiceConfig{ Mode: "rest", BaseURL: "http://127.0.0.1:19091", RequestTimeout: 950 * time.Millisecond, }, cfg.MailService) assert.Equal(t, "custom-authsession", cfg.Telemetry.ServiceName) assert.Equal(t, "otlp", cfg.Telemetry.TracesExporter) assert.Equal(t, "otlp", cfg.Telemetry.MetricsExporter) assert.Equal(t, "grpc", cfg.Telemetry.TracesProtocol) assert.Equal(t, "grpc", cfg.Telemetry.MetricsProtocol) assert.True(t, cfg.Telemetry.StdoutTracesEnabled) assert.True(t, cfg.Telemetry.StdoutMetricsEnabled) } func TestLoadFromEnvRejectsInvalidValues(t *testing.T) { tests := []struct { name string envName string envVal string }{ {name: "invalid duration", envName: shutdownTimeoutEnvVar, envVal: "later"}, {name: "invalid bool", envName: otelStdoutTracesEnabledEnvVar, envVal: "sometimes"}, {name: "invalid log level", envName: logLevelEnvVar, envVal: "verbose"}, {name: "invalid traces protocol", envName: otelExporterOTLPTracesProtocolEnvVar, envVal: "udp"}, {name: "invalid user service mode", envName: userServiceModeEnvVar, envVal: "grpc"}, {name: "invalid user service timeout", envName: userServiceRequestTimeoutEnvVar, envVal: "never"}, {name: "invalid mail service mode", envName: mailServiceModeEnvVar, envVal: "grpc"}, {name: "invalid mail service timeout", envName: mailServiceRequestTimeoutEnvVar, envVal: "never"}, } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { t.Setenv(redisAddrEnvVar, "127.0.0.1:6379") t.Setenv(tt.envName, tt.envVal) if tt.envName == otelExporterOTLPTracesProtocolEnvVar { t.Setenv(otelTracesExporterEnvVar, "otlp") } _, err := LoadFromEnv() require.Error(t, err) assert.Contains(t, err.Error(), tt.envName) }) } } func TestLoadFromEnvRejectsInvalidRESTUserServiceConfiguration(t *testing.T) { t.Setenv(redisAddrEnvVar, "127.0.0.1:6379") t.Setenv(userServiceModeEnvVar, "rest") t.Run("missing base url", func(t *testing.T) { _, err := LoadFromEnv() require.Error(t, err) assert.Contains(t, err.Error(), userServiceBaseURLEnvVar) }) t.Run("non positive timeout", func(t *testing.T) { t.Setenv(userServiceBaseURLEnvVar, "http://127.0.0.1:19090") t.Setenv(userServiceRequestTimeoutEnvVar, "0s") _, err := LoadFromEnv() require.Error(t, err) assert.Contains(t, err.Error(), userServiceRequestTimeoutEnvVar) }) } func TestLoadFromEnvRejectsInvalidRESTMailServiceConfiguration(t *testing.T) { t.Setenv(redisAddrEnvVar, "127.0.0.1:6379") t.Setenv(mailServiceModeEnvVar, "rest") t.Run("missing base url", func(t *testing.T) { _, err := LoadFromEnv() require.Error(t, err) assert.Contains(t, err.Error(), mailServiceBaseURLEnvVar) }) t.Run("non positive timeout", func(t *testing.T) { t.Setenv(mailServiceBaseURLEnvVar, "http://127.0.0.1:19091") t.Setenv(mailServiceRequestTimeoutEnvVar, "0s") _, err := LoadFromEnv() require.Error(t, err) assert.Contains(t, err.Error(), mailServiceRequestTimeoutEnvVar) }) }