package config import ( "log/slog" "os" "path/filepath" "strings" "testing" ) func TestNewLogger_Invalid(t *testing.T) { if _, _, err := NewLogger(LoggingConfig{Format: "xml"}); err == nil { t.Error("expected error for format xml") } if _, _, err := NewLogger(LoggingConfig{Level: "loud"}); err == nil { t.Error("expected error for level loud") } } func TestNewLogger_Levels(t *testing.T) { for _, tt := range []struct { in string want slog.Level }{{"", slog.LevelInfo}, {"debug", slog.LevelDebug}, {"INFO", slog.LevelInfo}, {"warn", slog.LevelWarn}, {"warning", slog.LevelWarn}, {"error", slog.LevelError}} { got, err := parseLogLevel(tt.in) if err != nil || got != tt.want { t.Errorf("parseLogLevel(%q) = %v, %v; want %v", tt.in, got, err, tt.want) } } } // Rotation: after the file is renamed away, Reopen must create a fresh file at // the configured path and subsequent writes must land there. func TestLogWriter_Reopen(t *testing.T) { dir := t.TempDir() path := filepath.Join(dir, "app.log") w, err := newLogWriter(path) if err != nil { t.Fatal(err) } defer w.Close() if _, err := w.Write([]byte("one\n")); err != nil { t.Fatal(err) } rotated := filepath.Join(dir, "app.log.0") if err := os.Rename(path, rotated); err != nil { t.Fatal(err) } if err := w.Reopen(); err != nil { t.Fatalf("Reopen: %v", err) } if _, err := w.Write([]byte("two\n")); err != nil { t.Fatal(err) } old, _ := os.ReadFile(rotated) fresh, _ := os.ReadFile(path) if strings.TrimSpace(string(old)) != "one" || strings.TrimSpace(string(fresh)) != "two" { t.Errorf("rotated=%q fresh=%q", old, fresh) } } func TestLogWriter_StderrReopenIsNoop(t *testing.T) { w, err := newLogWriter("stderr") if err != nil { t.Fatal(err) } if err := w.Reopen(); err != nil { t.Errorf("Reopen on stderr: %v", err) } if err := w.Close(); err != nil { t.Errorf("Close on stderr: %v", err) } }