- ErrorMetrics 并发安全测试 - AsyncLogWriter 错误指标真实记录测试 - HTTP Server 超时配置真实验证 - Prometheus 指标 HTTP 端点真实测试 - 日志文件输出真实写入测试
137 lines
2.6 KiB
Go
137 lines
2.6 KiB
Go
package log
|
|
|
|
import (
|
|
"log/slog"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestInitWithConfig_FileOutput_Real(t *testing.T) {
|
|
logDir := t.TempDir()
|
|
logFile := filepath.Join(logDir, "test.log")
|
|
|
|
cfg := Config{
|
|
Level: "info",
|
|
Output: logFile,
|
|
MaxSize: 1, // 1MB
|
|
}
|
|
|
|
// 初始化日志
|
|
InitWithConfig(cfg)
|
|
|
|
// 写入日志
|
|
Info("test message", "key", "value")
|
|
Error("error message", "err", "test error")
|
|
|
|
// 验证文件被创建
|
|
if _, err := os.Stat(logFile); os.IsNotExist(err) {
|
|
t.Fatal("Log file was not created")
|
|
}
|
|
|
|
// 读取文件内容
|
|
content, err := os.ReadFile(logFile)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read log file: %v", err)
|
|
}
|
|
|
|
// 验证内容
|
|
contentStr := string(content)
|
|
if !strings.Contains(contentStr, "test message") {
|
|
t.Error("Log file missing 'test message'")
|
|
}
|
|
if !strings.Contains(contentStr, "key") {
|
|
t.Error("Log file missing 'key' field")
|
|
}
|
|
}
|
|
|
|
func TestSanitizeAttrs_Real(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
key string
|
|
value string
|
|
expected string
|
|
}{
|
|
{
|
|
name: "token should be redacted",
|
|
key: "api_token",
|
|
value: "secret123",
|
|
expected: "[REDACTED]",
|
|
},
|
|
{
|
|
name: "password should be redacted",
|
|
key: "user_password",
|
|
value: "mypassword",
|
|
expected: "[REDACTED]",
|
|
},
|
|
{
|
|
name: "normal key should not be redacted",
|
|
key: "user_name",
|
|
value: "john",
|
|
expected: "john",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
attr := slog.String(tt.key, tt.value)
|
|
sanitized := sanitizeAttrs(nil, attr)
|
|
|
|
if sanitized.Value.String() != tt.expected {
|
|
t.Errorf("sanitizeAttrs() = %q, want %q", sanitized.Value.String(), tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestIsSensitive_Real(t *testing.T) {
|
|
sensitiveKeys := []string{
|
|
"token",
|
|
"password",
|
|
"secret",
|
|
"api_key",
|
|
"private_key",
|
|
}
|
|
|
|
nonSensitiveKeys := []string{
|
|
"name",
|
|
"id",
|
|
"timestamp",
|
|
"message",
|
|
}
|
|
|
|
for _, key := range sensitiveKeys {
|
|
if !IsSensitive(key) {
|
|
t.Errorf("IsSensitive(%q) = false, want true", key)
|
|
}
|
|
}
|
|
|
|
for _, key := range nonSensitiveKeys {
|
|
if IsSensitive(key) {
|
|
t.Errorf("IsSensitive(%q) = true, want false", key)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestParseLevel_Real(t *testing.T) {
|
|
tests := []struct {
|
|
input string
|
|
expected slog.Level
|
|
}{
|
|
{"debug", slog.LevelDebug},
|
|
{"info", slog.LevelInfo},
|
|
{"warn", slog.LevelWarn},
|
|
{"error", slog.LevelError},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.input, func(t *testing.T) {
|
|
level := parseLevel(tt.input)
|
|
if level != tt.expected {
|
|
t.Errorf("parseLevel(%q) = %d, want %d", tt.input, level, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|