97 lines
2.7 KiB
Go
97 lines
2.7 KiB
Go
|
|
package starlog
|
||
|
|
|
||
|
|
import (
|
||
|
|
"errors"
|
||
|
|
"path/filepath"
|
||
|
|
"strings"
|
||
|
|
"testing"
|
||
|
|
"time"
|
||
|
|
)
|
||
|
|
|
||
|
|
func waitForRotate(t *testing.T, timeout time.Duration, cond func() bool, reason string) {
|
||
|
|
t.Helper()
|
||
|
|
deadline := time.Now().Add(timeout)
|
||
|
|
for time.Now().Before(deadline) {
|
||
|
|
if cond() {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
time.Sleep(10 * time.Millisecond)
|
||
|
|
}
|
||
|
|
t.Fatalf("timeout waiting for condition: %s", reason)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestNewRotatePolicySinkNilPolicy(t *testing.T) {
|
||
|
|
sink, err := NewRotatePolicySink(filepath.Join(testBinDir(t), "a.log"), true, nil, time.Second)
|
||
|
|
if err == nil {
|
||
|
|
t.Fatalf("expected error for nil rotate policy")
|
||
|
|
}
|
||
|
|
if sink != nil {
|
||
|
|
t.Fatalf("sink should be nil when create fails")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestManagedRotateBySizeSinkCreatesBackups(t *testing.T) {
|
||
|
|
path := filepath.Join(testBinDir(t), "route.log")
|
||
|
|
sink, err := NewManagedRotateBySizeSink(path, true, 64, 5*time.Millisecond, RotateManageOptions{
|
||
|
|
MaxBackups: 10,
|
||
|
|
Pattern: "route.*.log",
|
||
|
|
})
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("create sink failed: %v", err)
|
||
|
|
}
|
||
|
|
defer sink.Close()
|
||
|
|
|
||
|
|
for idx := 0; idx < 40; idx++ {
|
||
|
|
if err = sink.Write([]byte(strings.Repeat("x", 16))); err != nil {
|
||
|
|
t.Fatalf("sink write failed: %v", err)
|
||
|
|
}
|
||
|
|
time.Sleep(3 * time.Millisecond)
|
||
|
|
}
|
||
|
|
|
||
|
|
waitForRotate(t, 2*time.Second, func() bool {
|
||
|
|
matches, _ := filepath.Glob(filepath.Join(filepath.Dir(path), "route.*.log"))
|
||
|
|
return len(matches) > 0
|
||
|
|
}, "rotating sink backups")
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestRotatingFileSinkClose(t *testing.T) {
|
||
|
|
path := filepath.Join(testBinDir(t), "close.log")
|
||
|
|
sink, err := NewRotateBySizeSink(path, true, 1024, time.Second)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("create sink failed: %v", err)
|
||
|
|
}
|
||
|
|
if err = sink.Close(); err != nil {
|
||
|
|
t.Fatalf("close failed: %v", err)
|
||
|
|
}
|
||
|
|
if err = sink.Write([]byte("after-close")); !errors.Is(err, ErrRotatingFileSinkClosed) {
|
||
|
|
t.Fatalf("write after close should return ErrRotatingFileSinkClosed, got %v", err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestRotatingFileSinkPrefersArchivePathProvider(t *testing.T) {
|
||
|
|
path := filepath.Join(testBinDir(t), "sink_provider.log")
|
||
|
|
sink, err := NewRotatePolicySink(path, true, &rotatePreferArchivePathPolicy{}, 5*time.Millisecond)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("create sink failed: %v", err)
|
||
|
|
}
|
||
|
|
defer sink.Close()
|
||
|
|
|
||
|
|
if err = sink.Write([]byte("first")); err != nil {
|
||
|
|
t.Fatalf("first write failed: %v", err)
|
||
|
|
}
|
||
|
|
time.Sleep(10 * time.Millisecond)
|
||
|
|
if err = sink.Write([]byte("second")); err != nil {
|
||
|
|
t.Fatalf("second write failed: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
waitForRotate(t, 2*time.Second, func() bool {
|
||
|
|
matches, _ := filepath.Glob(path + ".*.archive.bak")
|
||
|
|
return len(matches) > 0
|
||
|
|
}, "rotating sink archive path provider")
|
||
|
|
|
||
|
|
nextMatches, _ := filepath.Glob(path + ".*.next.bak")
|
||
|
|
if len(nextMatches) > 0 {
|
||
|
|
t.Fatalf("rotating sink should not use NextPath when ArchivePath is available")
|
||
|
|
}
|
||
|
|
}
|