starlog/archive_test.go

249 lines
7.1 KiB
Go
Raw Normal View History

2024-03-10 15:37:20 +08:00
package starlog
2024-03-10 15:39:05 +08:00
import (
2026-03-19 16:37:57 +08:00
"os"
"path/filepath"
2024-03-10 15:39:05 +08:00
"testing"
"time"
)
2026-03-19 16:37:57 +08:00
type archiveNoop struct {
interval int64
}
func (archive *archiveNoop) ShouldArchiveNow(logger *StarLogger, fullpath string, info os.FileInfo) bool {
return false
}
func (archive *archiveNoop) NextLogFilePath(logger *StarLogger, oldpath string, info os.FileInfo) string {
return oldpath
}
func (archive *archiveNoop) ArchiveLogFilePath(logger *StarLogger, oldpath string, info os.FileInfo) string {
return oldpath
}
func (archive *archiveNoop) Interval() int64 {
return archive.interval
}
func (archive *archiveNoop) HookBeforArchive() func(*StarLogger, string, string, os.FileInfo) error {
return nil
}
func (archive *archiveNoop) HookAfterArchive() func(*StarLogger, string, string, os.FileInfo) error {
return nil
}
func (archive *archiveNoop) DoArchive() func(*StarLogger, string, string, os.FileInfo) error {
return nil
}
func TestArchiveStopCanRestart(t *testing.T) {
logger := NewStarlog(nil)
logger.SetShowStd(false)
logPath := filepath.Join(testBinDir(t), "archive.log")
if err := SetLogFile(logPath, logger, false); err != nil {
t.Fatalf("SetLogFile failed: %v", err)
}
defer Close(logger)
archive := &archiveNoop{interval: 1}
if err := StartArchive(logger, archive); err != nil {
t.Fatalf("StartArchive first run failed: %v", err)
}
if !IsArchiveRun(logger) {
t.Fatalf("archive should be running after StartArchive")
}
StopArchive(logger)
if IsArchiveRun(logger) {
t.Fatalf("archive should be stopped after StopArchive")
}
if err := StartArchive(logger, archive); err != nil {
t.Fatalf("StartArchive second run failed: %v", err)
}
StopArchive(logger)
}
func TestArchiveZeroIntervalDoesNotFail(t *testing.T) {
logger := NewStarlog(nil)
logger.SetShowStd(false)
logPath := filepath.Join(testBinDir(t), "archive_zero.log")
if err := SetLogFile(logPath, logger, false); err != nil {
t.Fatalf("SetLogFile failed: %v", err)
}
defer Close(logger)
archive := &archiveNoop{interval: 0}
if err := StartArchive(logger, archive); err != nil {
t.Fatalf("StartArchive should accept zero interval: %v", err)
}
StopArchive(logger)
}
type rotateWhenNonEmptyPolicy struct{}
func (policy *rotateWhenNonEmptyPolicy) ShouldRotate(info FileInfo, entry *Entry) bool {
return info != nil && info.Size() > 0
}
func (policy *rotateWhenNonEmptyPolicy) NextPath(current string, now time.Time) string {
return current + "." + now.Format("20060102150405.000000") + ".bak"
}
type rotatePreferArchivePathPolicy struct{}
func (policy *rotatePreferArchivePathPolicy) ShouldRotate(info FileInfo, entry *Entry) bool {
return info != nil && info.Size() > 0
}
func (policy *rotatePreferArchivePathPolicy) NextPath(current string, now time.Time) string {
return current + "." + now.Format("20060102150405.000000") + ".next.bak"
}
func (policy *rotatePreferArchivePathPolicy) ArchivePath(current string, now time.Time) string {
return current + "." + now.Format("20060102150405.000000") + ".archive.bak"
}
type rotateArchivePathFallbackPolicy struct{}
func (policy *rotateArchivePathFallbackPolicy) ShouldRotate(info FileInfo, entry *Entry) bool {
return info != nil && info.Size() > 0
}
func (policy *rotateArchivePathFallbackPolicy) NextPath(current string, now time.Time) string {
return current + "." + now.Format("20060102150405.000000") + ".nextonly.bak"
}
func (policy *rotateArchivePathFallbackPolicy) ArchivePath(current string, now time.Time) string {
return ""
}
func TestStartRotatePolicyPrimaryPath(t *testing.T) {
logger := NewStarlog(nil)
logger.SetShowStd(false)
logger.SetShowColor(false)
logPath := filepath.Join(testBinDir(t), "rotate.log")
if err := SetLogFile(logPath, logger, false); err != nil {
t.Fatalf("SetLogFile failed: %v", err)
}
defer Close(logger)
defer StopArchive(logger)
if err := StartRotatePolicy(logger, &rotateWhenNonEmptyPolicy{}, 1); err != nil {
t.Fatalf("StartRotatePolicy failed: %v", err)
}
logger.Infoln("trigger rotate")
var found bool
deadline := time.Now().Add(3 * time.Second)
for time.Now().Before(deadline) {
matches, err := filepath.Glob(logPath + ".*.bak")
if err == nil && len(matches) > 0 {
found = true
break
}
time.Sleep(100 * time.Millisecond)
}
if !found {
t.Fatalf("rotate policy should create archived files")
}
}
func TestStartRotatePolicyPrefersArchivePathProvider(t *testing.T) {
logger := NewStarlog(nil)
logger.SetShowStd(false)
logger.SetShowColor(false)
logPath := filepath.Join(testBinDir(t), "rotate_provider.log")
if err := SetLogFile(logPath, logger, false); err != nil {
t.Fatalf("SetLogFile failed: %v", err)
}
defer Close(logger)
defer StopArchive(logger)
if err := StartRotatePolicy(logger, &rotatePreferArchivePathPolicy{}, 1); err != nil {
t.Fatalf("StartRotatePolicy failed: %v", err)
}
logger.Infoln("trigger rotate with provider")
var foundArchive bool
deadline := time.Now().Add(3 * time.Second)
for time.Now().Before(deadline) {
matches, err := filepath.Glob(logPath + ".*.archive.bak")
if err == nil && len(matches) > 0 {
foundArchive = true
break
}
time.Sleep(100 * time.Millisecond)
}
if !foundArchive {
t.Fatalf("rotate policy should use ArchivePath when provider is implemented")
}
nextMatches, _ := filepath.Glob(logPath + ".*.next.bak")
if len(nextMatches) > 0 {
t.Fatalf("rotate policy should not use NextPath when ArchivePath is available")
}
}
func TestStartRotatePolicyArchivePathProviderFallbackToNextPath(t *testing.T) {
logger := NewStarlog(nil)
logger.SetShowStd(false)
logger.SetShowColor(false)
logPath := filepath.Join(testBinDir(t), "rotate_provider_fallback.log")
if err := SetLogFile(logPath, logger, false); err != nil {
t.Fatalf("SetLogFile failed: %v", err)
}
defer Close(logger)
defer StopArchive(logger)
if err := StartRotatePolicy(logger, &rotateArchivePathFallbackPolicy{}, 1); err != nil {
t.Fatalf("StartRotatePolicy failed: %v", err)
}
logger.Infoln("trigger rotate fallback")
var foundNext bool
deadline := time.Now().Add(3 * time.Second)
for time.Now().Before(deadline) {
matches, err := filepath.Glob(logPath + ".*.nextonly.bak")
if err == nil && len(matches) > 0 {
foundNext = true
break
}
time.Sleep(100 * time.Millisecond)
}
if !foundNext {
t.Fatalf("rotate policy should fallback to NextPath when ArchivePath returns empty")
}
}
func TestArchiveHookBeforeAlias(t *testing.T) {
archive := NewArchiveBySize(1024, 1, "app.log", "app.log.2006", false, nil, nil)
hook := func(*StarLogger, string, string, os.FileInfo) error {
return nil
}
archive.SetHookBeforeArchive(hook)
if archive.HookBeforArchive() == nil || archive.HookBeforeArchive() == nil {
t.Fatalf("both hook getter names should work")
}
}
func TestCloseLogFileClearsManagedWriter(t *testing.T) {
logger := NewStarlog(nil)
logger.SetShowStd(false)
logPath := filepath.Join(testBinDir(t), "close_logfile.log")
if err := SetLogFile(logPath, logger, false); err != nil {
t.Fatalf("SetLogFile failed: %v", err)
}
if err := CloseLogFile(logger); err != nil {
t.Fatalf("CloseLogFile failed: %v", err)
}
if logger.GetWriter() != nil {
t.Fatalf("CloseLogFile should clear managed writer")
2024-03-10 15:39:05 +08:00
}
}