bldr/util/logfile/prune_test.go
Rama master · réplica de lectura del repositorio original.
package logfile
import (
"os"
"path/filepath"
"testing"
"time"
)
// writeFile writes name under dir with mtime set to mtime. It fails the
// test on any I/O error.
func writeFile(t *testing.T, dir, name string, mtime time.Time) string {
// Write the log fixture in the requested directory.
t.Helper()
path := filepath.Join(dir, name)
if err := os.WriteFile(path, []byte("entry\n"), 0o644); err != nil {
t.Fatalf("write %s: %v", path, err)
}
// Set the log fixture age for retention checks.
if err := os.Chtimes(path, mtime, mtime); err != nil {
t.Fatalf("chtimes %s: %v", path, err)
}
return path
}
func TestPruneOldLogs_DeletesAged(t *testing.T) {
// Create the log directory and retention cutoff.
dir := t.TempDir()
now := time.Date(2026, 5, 4, 12, 0, 0, 0, time.UTC)
maxAge := 7 * 24 * time.Hour
// Write expired, recent, and unrelated file fixtures.
old := writeFile(t, dir, "20260101-000000.log", now.Add(-30*24*time.Hour))
young := writeFile(t, dir, "20260503-000000.log", now.Add(-24*time.Hour))
nonLog := writeFile(t, dir, "old.txt", now.Add(-30*24*time.Hour))
// Prune files older than the retention cutoff.
removed, err := PruneOldLogs(dir, maxAge, 0, now)
if err != nil {
t.Fatalf("PruneOldLogs: %v", err)
}
// Verify pruning removes only the expired log.
if removed != 1 {
t.Errorf("removed = %d, want 1", removed)
}
if _, err := os.Stat(old); !os.IsNotExist(err) {
t.Errorf("old log should be removed: stat err = %v", err)
}
if _, err := os.Stat(young); err != nil {
t.Errorf("young log should remain: %v", err)
}
if _, err := os.Stat(nonLog); err != nil {
t.Errorf("non-.log file should remain: %v", err)
}
}
func TestPruneOldLogs_KeepsAtCutoff(t *testing.T) {
// Create the log directory and retention cutoff.
dir := t.TempDir()
now := time.Date(2026, 5, 4, 12, 0, 0, 0, time.UTC)
maxAge := 7 * 24 * time.Hour
// File whose mtime is exactly at the cutoff is kept (Before is strict).
atCutoff := writeFile(t, dir, "edge.log", now.Add(-maxAge))
// Prune the log whose age equals the retention cutoff.
removed, err := PruneOldLogs(dir, maxAge, 0, now)
if err != nil {
t.Fatalf("PruneOldLogs: %v", err)
}
// Verify the log at the exact cutoff remains.
if removed != 0 {
t.Errorf("removed = %d, want 0 at cutoff", removed)
}
if _, err := os.Stat(atCutoff); err != nil {
t.Errorf("at-cutoff log should remain: %v", err)
}
}
func TestPruneOldLogs_NonExistentDir(t *testing.T) {
dir := filepath.Join(t.TempDir(), "missing")
removed, err := PruneOldLogs(dir, time.Hour, 0, time.Now())
if err != nil {
t.Errorf("non-existent dir should be no-op, got err = %v", err)
}
if removed != 0 {
t.Errorf("removed = %d, want 0", removed)
}
}
func TestPruneOldLogs_SkipsSubdirs(t *testing.T) {
// Create the log directory and retention cutoff.
dir := t.TempDir()
now := time.Date(2026, 5, 4, 12, 0, 0, 0, time.UTC)
maxAge := 7 * 24 * time.Hour
// Create an aged directory with a log filename.
subdir := filepath.Join(dir, "old.log")
if err := os.Mkdir(subdir, 0o755); err != nil {
t.Fatalf("mkdir: %v", err)
}
if err := os.Chtimes(subdir, now.Add(-30*24*time.Hour), now.Add(-30*24*time.Hour)); err != nil {
t.Fatalf("chtimes subdir: %v", err)
}
// Prune the directory containing the aged subdirectory.
removed, err := PruneOldLogs(dir, maxAge, 0, now)
if err != nil {
t.Fatalf("PruneOldLogs: %v", err)
}
// Verify pruning preserves the subdirectory.
if removed != 0 {
t.Errorf("removed = %d, want 0", removed)
}
if _, err := os.Stat(subdir); err != nil {
t.Errorf("subdir named *.log should remain: %v", err)
}
}
func TestPruneOldLogs_EmptyDir(t *testing.T) {
dir := t.TempDir()
removed, err := PruneOldLogs(dir, time.Hour, 0, time.Now())
if err != nil {
t.Errorf("empty dir: err = %v", err)
}
if removed != 0 {
t.Errorf("removed = %d, want 0", removed)
}
}
func TestPruneOldLogs_KeepsNewest(t *testing.T) {
// Create the log directory and reference time.
dir := t.TempDir()
now := time.Date(2026, 5, 4, 12, 0, 0, 0, time.UTC)
// Write logs in increasing modification-time order.
oldest := writeFile(t, dir, "20260504-080000.log", now.Add(-4*time.Hour))
older := writeFile(t, dir, "20260504-090000.log", now.Add(-3*time.Hour))
newer := writeFile(t, dir, "20260504-100000.log", now.Add(-2*time.Hour))
newest := writeFile(t, dir, "20260504-110000.log", now.Add(-time.Hour))
// Prune the log directory to its two newest files.
removed, err := PruneOldLogs(dir, 7*24*time.Hour, 2, now)
if err != nil {
t.Fatalf("PruneOldLogs: %v", err)
}
// Verify pruning removed the older logs and retained the newest pair.
if removed != 2 {
t.Errorf("removed = %d, want 2", removed)
}
for _, path := range []string{oldest, older} {
if _, err := os.Stat(path); !os.IsNotExist(err) {
t.Errorf("%s should be removed, stat err = %v", path, err)
}
}
for _, path := range []string{newer, newest} {
if _, err := os.Stat(path); err != nil {
t.Errorf("%s should be kept: %v", path, err)
}
}
}