package config import ( "log/slog" "net/netip" "testing" "time" ) func TestLoadUsesProductionDefaults(t *testing.T) { clearConfigEnv(t) cfg, err := Load() if err != nil { t.Fatalf("load config: %v", err) } if cfg.Addr != ":8080" { t.Fatalf("got addr %q, want %q", cfg.Addr, ":8080") } if cfg.TrustProxyHeaders { t.Fatal("proxy headers should not be trusted by default") } wantProxy := netip.MustParsePrefix("127.0.0.1/32") if len(cfg.TrustedProxyCIDRs) == 0 || cfg.TrustedProxyCIDRs[0] != wantProxy { t.Fatalf("got trusted proxies %v, want first %v", cfg.TrustedProxyCIDRs, wantProxy) } if cfg.ReadHeaderTimeout != 5*time.Second { t.Fatalf("got read header timeout %s", cfg.ReadHeaderTimeout) } if cfg.LogLevel != slog.LevelInfo { t.Fatalf("got log level %s, want info", cfg.LogLevel) } } func TestLoadParsesEnvironment(t *testing.T) { clearConfigEnv(t) t.Setenv("ADDR", "127.0.0.1:9090") t.Setenv("TRUST_PROXY_HEADERS", "true") t.Setenv("TRUSTED_PROXY_CIDRS", "10.0.0.0/8,192.0.2.10") t.Setenv("READ_HEADER_TIMEOUT", "3s") t.Setenv("READ_TIMEOUT", "4s") t.Setenv("WRITE_TIMEOUT", "5s") t.Setenv("IDLE_TIMEOUT", "30s") t.Setenv("SHUTDOWN_TIMEOUT", "7s") t.Setenv("MAX_HEADER_BYTES", "8192") t.Setenv("LOG_LEVEL", "debug") t.Setenv("LOG_FORMAT", "json") cfg, err := Load() if err != nil { t.Fatalf("load config: %v", err) } if cfg.Addr != "127.0.0.1:9090" { t.Fatalf("got addr %q", cfg.Addr) } if !cfg.TrustProxyHeaders { t.Fatal("expected proxy headers to be trusted") } if got, want := cfg.TrustedProxyCIDRs[1], netip.MustParsePrefix("192.0.2.10/32"); got != want { t.Fatalf("got proxy %v, want %v", got, want) } if cfg.ReadTimeout != 4*time.Second || cfg.WriteTimeout != 5*time.Second { t.Fatalf("got read/write timeouts %s/%s", cfg.ReadTimeout, cfg.WriteTimeout) } if cfg.MaxHeaderBytes != 8192 { t.Fatalf("got max header bytes %d", cfg.MaxHeaderBytes) } if cfg.LogLevel != slog.LevelDebug || cfg.LogFormat != "json" { t.Fatalf("got logging %s/%s", cfg.LogLevel, cfg.LogFormat) } } func TestLoadRejectsInvalidEnvironment(t *testing.T) { tests := map[string]string{ "TRUST_PROXY_HEADERS": "yes-please", "TRUSTED_PROXY_CIDRS": "not-a-cidr", "TRUSTED_PROXY_CIDRS_EMPTY": ",", "READ_TIMEOUT": "forever", "MAX_HEADER_BYTES": "0", "LOG_LEVEL": "verbose", "LOG_FORMAT": "xml", } for name, value := range tests { t.Run(name, func(t *testing.T) { clearConfigEnv(t) envName := name if name == "TRUSTED_PROXY_CIDRS_EMPTY" { envName = "TRUSTED_PROXY_CIDRS" } t.Setenv(envName, value) if _, err := Load(); err == nil { t.Fatal("expected error") } }) } } func clearConfigEnv(t *testing.T) { t.Helper() for _, name := range []string{ "ADDR", "TRUST_PROXY_HEADERS", "TRUSTED_PROXY_CIDRS", "READ_HEADER_TIMEOUT", "READ_TIMEOUT", "WRITE_TIMEOUT", "IDLE_TIMEOUT", "SHUTDOWN_TIMEOUT", "MAX_HEADER_BYTES", "LOG_LEVEL", "LOG_FORMAT", } { t.Setenv(name, "") } }