Scert/backend/internal/logging/logging_test.go

151 lines
4.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package logging
import (
"log/slog"
"os"
"path/filepath"
"runtime"
"strconv"
"strings"
"testing"
"time"
)
func TestLoggerWritesJSONAndUsesRestrictedPermissions(t *testing.T) {
dir := t.TempDir()
logger, err := New(dir, slog.LevelInfo)
if err != nil {
t.Fatalf("初始化日志失败:%v", err)
}
logger.Info("复审日志", "component", "test")
if err := logger.Close(); err != nil {
t.Fatalf("关闭日志失败:%v", err)
}
path := filepath.Join(dir, "scert.log")
data, err := os.ReadFile(path)
if err != nil {
t.Fatalf("读取日志失败:%v", err)
}
text := string(data)
if !strings.Contains(text, `"msg":"复审日志"`) || !strings.Contains(text, `"component":"test"`) {
t.Fatalf("日志内容不正确:%s", text)
}
if runtime.GOOS != "windows" {
info, err := os.Stat(path)
if err != nil {
t.Fatalf("读取日志权限失败:%v", err)
}
if info.Mode().Perm() != 0o600 {
t.Fatalf("日志文件权限不正确:%o", info.Mode().Perm())
}
}
}
func TestDailyFileWriterRotatesCapsAndRemovesExpiredLogs(t *testing.T) {
directory := t.TempDir()
now := time.Date(2026, 8, 31, 8, 0, 0, 0, time.Local)
oldPath := filepath.Join(directory, "scert-20260701.log")
if err := os.WriteFile(oldPath, []byte("old"), 0o600); err != nil {
t.Fatalf("写入过期日志失败:%v", err)
}
oldTime := now.AddDate(0, 0, -60)
if err := os.Chtimes(oldPath, oldTime, oldTime); err != nil {
t.Fatalf("设置过期日志时间失败:%v", err)
}
writer, err := newDailyFileWriterWithOptions(directory, 32, 30, func() time.Time { return now })
if err != nil {
t.Fatalf("初始化日志轮转器失败:%v", err)
}
if _, err := writer.Write([]byte("first-day-entry\n")); err != nil {
t.Fatalf("写入首日日志失败:%v", err)
}
if _, err := os.Stat(oldPath); !os.IsNotExist(err) {
t.Fatalf("过期日志未被清理:%v", err)
}
now = now.Add(24 * time.Hour)
if _, err := writer.Write([]byte("second-day-entry\n")); err != nil {
t.Fatalf("写入次日日志失败:%v", err)
}
rotatedPath := filepath.Join(directory, "scert-20260831.log")
if data, err := os.ReadFile(rotatedPath); err != nil || !strings.Contains(string(data), "first-day-entry") {
t.Fatalf("首日日志未正确轮转:data=%q err=%v", data, err)
}
activePath := filepath.Join(directory, "scert.log")
before, err := os.Stat(activePath)
if err != nil {
t.Fatalf("读取活动日志状态失败:%v", err)
}
large := strings.Repeat("x", 64)
if written, err := writer.Write([]byte(large)); err != nil || written != len(large) {
t.Fatalf("超过容量的日志写入结果不正确:written=%d err=%v", written, err)
}
after, err := os.Stat(activePath)
if err != nil {
t.Fatalf("再次读取活动日志状态失败:%v", err)
}
if before.Size() != after.Size() || after.Size() > 32 {
t.Fatalf("活动日志超过每日容量上限:before=%s after=%s", strconv.FormatInt(before.Size(), 10), strconv.FormatInt(after.Size(), 10))
}
if err := writer.Close(); err != nil {
t.Fatalf("关闭日志轮转器失败:%v", err)
}
}
func TestDailyFileWriterRejectsSymlink(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("Windows 普通用户环境通常无法创建符号链接")
}
directory := t.TempDir()
target := filepath.Join(directory, "target.log")
if err := os.WriteFile(target, []byte("target"), 0o600); err != nil {
t.Fatal(err)
}
if err := os.Symlink(target, filepath.Join(directory, "scert.log")); err != nil {
t.Fatal(err)
}
if _, err := newDailyFileWriter(directory); err == nil {
t.Fatal("活动日志是符号链接时应拒绝启动")
}
}
func TestDailyFileWriterKeepsDailyCapAfterRestart(t *testing.T) {
directory := t.TempDir()
now := time.Now()
activePath := filepath.Join(directory, "scert.log")
writer, err := newDailyFileWriterWithOptions(directory, 16, 30, func() time.Time { return now })
if err != nil {
t.Fatalf("初始化日志轮转器失败:%v", err)
}
if _, err := writer.Write([]byte("1234567890123456")); err != nil {
t.Fatalf("写满每日日志容量失败:%v", err)
}
if err := writer.Close(); err != nil {
t.Fatalf("关闭日志轮转器失败:%v", err)
}
restarted, err := newDailyFileWriterWithOptions(directory, 16, 30, func() time.Time { return now })
if err != nil {
t.Fatalf("重启日志轮转器失败:%v", err)
}
if _, err := restarted.Write([]byte("should-not-be-written")); err != nil {
t.Fatalf("容量用尽后写入结果错误:%v", err)
}
if err := restarted.Close(); err != nil {
t.Fatalf("再次关闭日志轮转器失败:%v", err)
}
info, err := os.Stat(activePath)
if err != nil {
t.Fatalf("读取活动日志状态失败:%v", err)
}
if info.Size() != 16 {
t.Fatalf("服务重启后每日日志容量被绕过:%d", info.Size())
}
if _, err := os.Stat(filepath.Join(directory, "scert-"+logDay(now)+".log")); !os.IsNotExist(err) {
t.Fatalf("同日重启不应轮转活动日志:%v", err)
}
}