package starlog import ( "path/filepath" "strings" "testing" "time" ) func TestRotateTemplatePathBuilder(t *testing.T) { path := buildRotatePathWithPattern("./logs/app.log", time.Date(2026, 3, 19, 10, 11, 12, 0, time.UTC), "20060102") base := filepath.Base(path) if base != "app.20260319.log" { t.Fatalf("unexpected rotated path: %s", base) } } func TestRotateBySizePolicyShouldRotate(t *testing.T) { p := NewRotateBySizePolicy(1) logger := NewStarlog(nil) logger.SetShowStd(false) logPath := filepath.Join(testBinDir(t), "tpl_size.log") if err := SetLogFile(logPath, logger, false); err != nil { t.Fatalf("SetLogFile failed: %v", err) } defer func() { _ = logger.Close() }() logger.Infoln("x") info, err := GetLogFileInfo(logger) if err != nil { t.Fatalf("GetLogFileInfo failed: %v", err) } if !p.ShouldRotate(info, &Entry{Time: time.Now()}) { t.Fatalf("size policy should rotate when file size threshold reached") } } func TestRotateByTimePolicyShouldRotate(t *testing.T) { p := NewRotateByTimePolicy(time.Second) logger := NewStarlog(nil) logger.SetShowStd(false) logPath := filepath.Join(testBinDir(t), "tpl_time.log") if err := SetLogFile(logPath, logger, false); err != nil { t.Fatalf("SetLogFile failed: %v", err) } defer func() { _ = logger.Close() }() logger.Infoln("time") info, err := GetLogFileInfo(logger) if err != nil { t.Fatalf("GetLogFileInfo failed: %v", err) } base := resolveEntryTime(&Entry{Time: time.Now()}) if p.ShouldRotate(info, &Entry{Time: base}) { t.Fatalf("first check should initialize and not rotate") } if p.ShouldRotate(info, &Entry{Time: base.Add(500 * time.Millisecond)}) { t.Fatalf("within interval should not rotate") } if !p.ShouldRotate(info, &Entry{Time: base.Add(1100 * time.Millisecond)}) { t.Fatalf("after interval should rotate") } } func TestRotateByTimeSizePolicyShouldRotate(t *testing.T) { p := NewRotateByTimeSizePolicy(time.Hour, 1024) logger := NewStarlog(nil) logger.SetShowStd(false) logPath := filepath.Join(testBinDir(t), "tpl_timesize.log") if err := SetLogFile(logPath, logger, false); err != nil { t.Fatalf("SetLogFile failed: %v", err) } defer func() { _ = logger.Close() }() logger.Infoln("small") info, err := GetLogFileInfo(logger) if err != nil { t.Fatalf("GetLogFileInfo failed: %v", err) } base := resolveEntryTime(&Entry{Time: time.Now()}) if p.ShouldRotate(info, &Entry{Time: base}) { t.Fatalf("first check should initialize and not rotate") } if p.ShouldRotate(info, &Entry{Time: base.Add(2 * time.Second)}) { t.Fatalf("before interval and size threshold should not rotate") } p2 := NewRotateByTimeSizePolicy(time.Hour, 1) if !p2.ShouldRotate(info, &Entry{Time: base.Add(3 * time.Second)}) { t.Fatalf("size threshold should rotate for time-size policy") } } func TestStartManagedRotatePolicyAndHelpers(t *testing.T) { logger := NewStarlog(nil) logger.SetShowStd(false) logPath := filepath.Join(testBinDir(t), "tpl_helper.log") if err := SetLogFile(logPath, logger, false); err != nil { t.Fatalf("SetLogFile failed: %v", err) } defer func() { _ = logger.Close() }() defer StopArchive(logger) if err := StartManagedRotatePolicy(logger, nil, 1, RotateManageOptions{}); err == nil { t.Fatalf("nil policy should return error") } if err := StartManagedRotateBySize(logger, 1, 1, RotateManageOptions{Pattern: "tpl_helper.log.*"}); err != nil { t.Fatalf("StartManagedRotateBySize failed: %v", err) } logger.Infoln(strings.Repeat("a", 64)) found := false deadline := time.Now().Add(3 * time.Second) for time.Now().Before(deadline) { matches, _ := filepath.Glob(filepath.Join(filepath.Dir(logPath), "tpl_helper.*.log")) if len(matches) > 0 { found = true break } time.Sleep(100 * time.Millisecond) } if !found { t.Fatalf("managed rotate helper should create backup files") } }