starlog/rotate_manage_test.go

150 lines
4.3 KiB
Go
Raw Normal View History

2026-03-19 16:37:57 +08:00
package starlog
import (
"os"
"path/filepath"
"strconv"
"testing"
"time"
)
func writeFileWithModTime(t *testing.T, path string, modTime time.Time) {
t.Helper()
if err := os.WriteFile(path, []byte("x"), 0644); err != nil {
t.Fatalf("write file failed: %v", err)
}
if err := os.Chtimes(path, modTime, modTime); err != nil {
t.Fatalf("set mod time failed: %v", err)
}
}
func TestApplyRotateManageOptionsCompress(t *testing.T) {
dir := testBinDir(t)
current := filepath.Join(dir, "app.log")
archive := filepath.Join(dir, "app.log.1")
writeFileWithModTime(t, current, time.Now())
writeFileWithModTime(t, archive, time.Now())
if err := ApplyRotateManageOptions(archive, current, RotateManageOptions{
Compress: true,
Pattern: "app.log.*",
}); err != nil {
t.Fatalf("ApplyRotateManageOptions compress failed: %v", err)
}
if _, err := os.Stat(archive + ".gz"); err != nil {
t.Fatalf("compressed file should exist: %v", err)
}
if _, err := os.Stat(archive); !os.IsNotExist(err) {
t.Fatalf("original archive file should be removed after compression")
}
}
func TestApplyRotateManageOptionsMaxBackups(t *testing.T) {
dir := testBinDir(t)
current := filepath.Join(dir, "app.log")
writeFileWithModTime(t, current, time.Now())
baseTime := time.Now().Add(-4 * time.Hour)
for i := 1; i <= 4; i++ {
path := filepath.Join(dir, "app.log."+strconv.Itoa(i))
writeFileWithModTime(t, path, baseTime.Add(time.Duration(i)*time.Hour))
}
if err := ApplyRotateManageOptions(filepath.Join(dir, "app.log.4"), current, RotateManageOptions{
MaxBackups: 2,
Pattern: "app.log.*",
}); err != nil {
t.Fatalf("ApplyRotateManageOptions max backups failed: %v", err)
}
matches, err := filepath.Glob(filepath.Join(dir, "app.log.*"))
if err != nil {
t.Fatalf("glob failed: %v", err)
}
if len(matches) != 2 {
t.Fatalf("should keep only 2 backup files, got %d (%v)", len(matches), matches)
}
}
func TestApplyRotateManageOptionsMaxAge(t *testing.T) {
dir := testBinDir(t)
current := filepath.Join(dir, "app.log")
oldBackup := filepath.Join(dir, "app.log.old")
newBackup := filepath.Join(dir, "app.log.new")
writeFileWithModTime(t, current, time.Now())
writeFileWithModTime(t, oldBackup, time.Now().Add(-4*time.Hour))
writeFileWithModTime(t, newBackup, time.Now().Add(-10*time.Minute))
if err := ApplyRotateManageOptions(newBackup, current, RotateManageOptions{
MaxAge: time.Hour,
Pattern: "app.log.*",
}); err != nil {
t.Fatalf("ApplyRotateManageOptions max age failed: %v", err)
}
if _, err := os.Stat(oldBackup); !os.IsNotExist(err) {
t.Fatalf("old backup should be removed by max age")
}
if _, err := os.Stat(newBackup); err != nil {
t.Fatalf("new backup should be kept: %v", err)
}
}
func TestWithRotateManageOptionsKeepsPreviousHook(t *testing.T) {
archive := NewRotatePolicyArchive(&rotateWhenNonEmptyPolicy{}, 1)
var called bool
archive.SetHookAfterArchive(func(*StarLogger, string, string, os.FileInfo) error {
called = true
return nil
})
WithRotateManageOptions(archive, RotateManageOptions{})
dir := testBinDir(t)
current := filepath.Join(dir, "app.log")
archived := filepath.Join(dir, "app.log.1")
writeFileWithModTime(t, current, time.Now())
writeFileWithModTime(t, archived, time.Now())
hook := archive.HookAfterArchive()
if hook == nil {
t.Fatalf("hook after archive should not be nil")
}
if err := hook(nil, archived, current, nil); err != nil {
t.Fatalf("hook execution failed: %v", err)
}
if !called {
t.Fatalf("previous hook should still run after wrapping")
}
}
func TestIsManagedBackupNameDefaultSafeMatch(t *testing.T) {
base := "app.log"
stem := "app"
tests := []struct {
name string
matched bool
}{
{name: "app.log.20260318", matched: true},
{name: "app.log-1", matched: true},
{name: "app.log.1.gz", matched: true},
{name: "app.log.bak", matched: true},
{name: "app_20260318.log", matched: true},
{name: "app.log.current", matched: false},
{name: "app.log.backup", matched: false},
{name: "app-config.log", matched: false},
{name: "other.log.1", matched: false},
}
for _, tc := range tests {
matched, err := isManagedBackupName(tc.name, base, stem, "")
if err != nil {
t.Fatalf("isManagedBackupName(%q) returned err: %v", tc.name, err)
}
if matched != tc.matched {
t.Fatalf("isManagedBackupName(%q)=%v, want %v", tc.name, matched, tc.matched)
}
}
}