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
|
|
|
}
|
|
|
|
|
}
|