package config import ( "log/slog" "strings" "testing" "time" ) func TestLoadRequiresDSN(t *testing.T) { t.Setenv("HAMMY_DSN", "") if _, err := Load(); err == nil { t.Fatal("expected an error when HAMMY_DSN is unset") } } func TestLoadDefaults(t *testing.T) { t.Setenv("HAMMY_DSN", "postgres://u:p@localhost/hammy") c, err := Load() if err != nil { t.Fatal(err) } if c.Addr != "127.0.0.1:8080" { t.Errorf("Addr %q, want localhost by default - binding 0.0.0.0 should be deliberate", c.Addr) } if c.MaxConns != 10 { t.Errorf("MaxConns %d, want 10", c.MaxConns) } if c.LogLevel != slog.LevelInfo { t.Errorf("LogLevel %v, want info", c.LogLevel) } if c.RedisAddr != "" { t.Errorf("RedisAddr %q, want empty", c.RedisAddr) } } func TestLoadOverrides(t *testing.T) { t.Setenv("HAMMY_DSN", "postgres://u:p@localhost/hammy") t.Setenv("HAMMY_ADDR", ":9000") t.Setenv("HAMMY_MAX_CONNS", "25") t.Setenv("HAMMY_LOG_LEVEL", "debug") t.Setenv("HAMMY_SHUTDOWN_TIMEOUT", "45s") t.Setenv("HAMMY_REDIS_ADDR", "localhost:6379") c, err := Load() if err != nil { t.Fatal(err) } if c.Addr != ":9000" || c.MaxConns != 25 || c.LogLevel != slog.LevelDebug { t.Errorf("overrides not applied: %+v", c) } if c.ShutdownTimeout != 45*time.Second { t.Errorf("ShutdownTimeout %v, want 45s", c.ShutdownTimeout) } } func TestLoadRejectsBadValues(t *testing.T) { t.Setenv("HAMMY_DSN", "postgres://u:p@localhost/hammy") for _, c := range []struct{ key, val string }{ {"HAMMY_MAX_CONNS", "lots"}, {"HAMMY_LOG_LEVEL", "verbose"}, {"HAMMY_SHUTDOWN_TIMEOUT", "soon"}, } { t.Run(c.key, func(t *testing.T) { t.Setenv(c.key, c.val) if _, err := Load(); err == nil { t.Errorf("%s=%q accepted", c.key, c.val) } }) } } // A DSN in a startup log is a password in a log. func TestRedactedHidesPassword(t *testing.T) { cases := []string{ "postgres://hammy_app:hunter2@192.168.1.127:5432/hammy", "postgresql://hammy_app:p%40ss@localhost/hammy?sslmode=verify-full", } for _, dsn := range cases { c := Config{DSN: dsn, Addr: ":8080", MaxConns: 10} out := c.Redacted() if strings.Contains(out, "hunter2") || strings.Contains(out, "p%40ss") { t.Errorf("password leaked: %s", out) } if !strings.Contains(out, "hammy_app") { t.Errorf("username should survive for diagnosis: %s", out) } } // A DSN with no credentials must not panic or produce nonsense. c := Config{DSN: "postgres:///hammy?host=/var/run/postgresql"} if out := c.Redacted(); strings.Contains(out, "***") && !strings.Contains(out, "(set)") { t.Logf("socket DSN rendered as: %s", out) } }