96 lines
2.7 KiB
Go
96 lines
2.7 KiB
Go
package runtimelog
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.pcux.cn/xuans/Smail/utils/logpolicy"
|
|
)
|
|
|
|
func TestRuntimeLogCompressionAndExactRetention(t *testing.T) {
|
|
root := t.TempDir()
|
|
w, err := New(root)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer w.Close()
|
|
now := time.Date(2026, 9, 8, 12, 0, 0, 0, time.UTC)
|
|
cutoff := logpolicy.Cutoff(now)
|
|
w.now = func() time.Time { return cutoff }
|
|
for _, at := range []time.Time{cutoff.Add(-time.Hour), cutoff, cutoff.Add(time.Hour), now.Add(-8 * 24 * time.Hour), now} {
|
|
if err := w.WriteAt(at, "sample\nsecond line"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
w.now = func() time.Time { return now }
|
|
ctx := context.Background()
|
|
if err := w.Maintain(ctx, now); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
files, err := w.Files()
|
|
if err != nil || len(files) != 3 {
|
|
t.Fatalf("files: %+v %v", files, err)
|
|
}
|
|
name := prefix + cutoff.Format("2006-01-02") + ".log.gz"
|
|
page, err := w.Read(ctx, name, 0, 100)
|
|
if err != nil || len(page.Lines) != 2 {
|
|
t.Fatalf("boundary: %+v %v", page, err)
|
|
}
|
|
if !strings.Contains(page.Lines[0], `\n`) {
|
|
t.Fatal("multiline event split")
|
|
}
|
|
// 压缩后仍须逐条裁剪,不能按整个归档日期删除有效记录。
|
|
now = now.Add(30 * time.Minute)
|
|
if err := w.Maintain(ctx, now); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
page, err = w.Read(ctx, name, 0, 100)
|
|
if err != nil || len(page.Lines) != 1 {
|
|
t.Fatalf("compressed boundary: %+v %v", page, err)
|
|
}
|
|
now = now.Add(24 * time.Hour)
|
|
if err := w.Maintain(ctx, now); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := w.root.Stat(name); !os.IsNotExist(err) {
|
|
t.Fatalf("expired archive still exists: %v", err)
|
|
}
|
|
if _, err := w.Read(ctx, "../config/config.json", 0, 100); err == nil {
|
|
t.Fatal("path traversal accepted")
|
|
}
|
|
if err := w.Maintain(ctx, now); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestRuntimeLogCorruptionAndUnknownFilesArePreserved(t *testing.T) {
|
|
root := t.TempDir()
|
|
w, err := New(root)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer w.Close()
|
|
now := time.Now().UTC()
|
|
w.now = func() time.Time { return now }
|
|
directory := filepath.Join(root, "log", "运行日志")
|
|
name := prefix + now.Add(-40*24*time.Hour).Format("2006-01-02") + ".log.gz"
|
|
if err := os.WriteFile(filepath.Join(directory, name), []byte("broken"), 0600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(filepath.Join(directory, "manual.log"), []byte("keep"), 0600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := w.Maintain(context.Background(), now); err == nil {
|
|
t.Fatal("corruption not reported")
|
|
}
|
|
for _, file := range []string{name, "manual.log"} {
|
|
if _, err := os.Stat(filepath.Join(directory, file)); err != nil {
|
|
t.Fatal("unmanaged or damaged evidence deleted")
|
|
}
|
|
}
|
|
}
|