使用空白标识符忽略测试辅助函数中 Close、ReadFrom、Set 等返回值, 与主代码风格保持一致。 Co-Authored-By: Claude <noreply@anthropic.com>
186 lines
4.1 KiB
Go
186 lines
4.1 KiB
Go
package logging
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/rs/zerolog"
|
|
"github.com/valyala/fasthttp"
|
|
"rua.plus/lolly/internal/config"
|
|
)
|
|
|
|
func TestParseLevel(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
expected zerolog.Level
|
|
}{
|
|
{
|
|
name: "debug level",
|
|
input: "debug",
|
|
expected: zerolog.DebugLevel,
|
|
},
|
|
{
|
|
name: "info level",
|
|
input: "info",
|
|
expected: zerolog.InfoLevel,
|
|
},
|
|
{
|
|
name: "warn level",
|
|
input: "warn",
|
|
expected: zerolog.WarnLevel,
|
|
},
|
|
{
|
|
name: "error level",
|
|
input: "error",
|
|
expected: zerolog.ErrorLevel,
|
|
},
|
|
{
|
|
name: "unknown level defaults to info",
|
|
input: "unknown",
|
|
expected: zerolog.InfoLevel,
|
|
},
|
|
{
|
|
name: "empty string defaults to info",
|
|
input: "",
|
|
expected: zerolog.InfoLevel,
|
|
},
|
|
{
|
|
name: "uppercase DEBUG now works",
|
|
input: "DEBUG",
|
|
expected: zerolog.DebugLevel,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := parseLevel(tt.input)
|
|
if result != tt.expected {
|
|
t.Errorf("parseLevel(%q) = %v, want %v", tt.input, result, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNewLogger(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
cfg *config.LoggingConfig
|
|
}{
|
|
{"nil config", nil},
|
|
{"empty paths", &config.LoggingConfig{}},
|
|
{"with access format", &config.LoggingConfig{Access: config.AccessLogConfig{Format: "json"}}},
|
|
{"with error level", &config.LoggingConfig{Error: config.ErrorLogConfig{Level: "debug"}}},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
logger := New(tt.cfg)
|
|
if logger == nil {
|
|
t.Error("Expected non-nil Logger")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestLoggerWithFile(t *testing.T) {
|
|
tmpDir := t.TempDir()
|
|
accessPath := filepath.Join(tmpDir, "access.log")
|
|
errorPath := filepath.Join(tmpDir, "error.log")
|
|
|
|
cfg := &config.LoggingConfig{
|
|
Access: config.AccessLogConfig{Path: accessPath, Format: "json"},
|
|
Error: config.ErrorLogConfig{Path: errorPath, Level: "info"},
|
|
}
|
|
|
|
logger := New(cfg)
|
|
|
|
ctx := &fasthttp.RequestCtx{}
|
|
ctx.Request.SetRequestURI("/test")
|
|
ctx.Request.Header.SetMethod("GET")
|
|
|
|
logger.LogAccess(ctx, 200, 10, 100*time.Millisecond)
|
|
logger.Error().Str("test", "value").Msg("test error")
|
|
_ = logger.Close()
|
|
|
|
if _, err := os.Stat(accessPath); os.IsNotExist(err) {
|
|
t.Error("Expected access log file to be created")
|
|
}
|
|
}
|
|
|
|
func TestGetOutput(t *testing.T) {
|
|
if getOutput("") != os.Stdout {
|
|
t.Error("Expected stdout for empty path")
|
|
}
|
|
if getOutput("stderr") != os.Stderr {
|
|
t.Error("Expected stderr for 'stderr' path")
|
|
}
|
|
|
|
tmpFile := filepath.Join(t.TempDir(), "test.log")
|
|
out := getOutput(tmpFile)
|
|
if out == nil {
|
|
t.Error("Expected non-nil writer for file path")
|
|
}
|
|
}
|
|
|
|
func TestLoggerNginxFormat(t *testing.T) {
|
|
old := os.Stdout
|
|
r, w, _ := os.Pipe()
|
|
os.Stdout = w
|
|
|
|
logger := New(&config.LoggingConfig{Access: config.AccessLogConfig{Format: "json"}})
|
|
|
|
ctx := &fasthttp.RequestCtx{}
|
|
ctx.Request.SetRequestURI("/api/users?id=123")
|
|
ctx.Request.Header.SetMethod("POST")
|
|
ctx.Request.Header.Set("User-Agent", "test-agent")
|
|
ctx.Request.Header.Set("Referer", "http://example.com/")
|
|
|
|
logger.LogAccess(ctx, 201, 512, 250*time.Millisecond)
|
|
|
|
_ = w.Close()
|
|
os.Stdout = old
|
|
|
|
var buf bytes.Buffer
|
|
_, _ = io.Copy(&buf, r)
|
|
|
|
output := buf.String()
|
|
expectedFields := []string{"request", "status", "body_bytes_sent", "request_time", "remote_addr"}
|
|
|
|
for _, field := range expectedFields {
|
|
if !strings.Contains(output, field) {
|
|
t.Errorf("Expected output to contain '%s'", field)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLoggerDebug(t *testing.T) {
|
|
old := os.Stdout
|
|
r, w, _ := os.Pipe()
|
|
os.Stdout = w
|
|
|
|
logger := New(&config.LoggingConfig{Error: config.ErrorLogConfig{Level: "debug"}})
|
|
|
|
logger.Debug().Msg("debug message")
|
|
logger.Info().Msg("info message")
|
|
|
|
_ = w.Close()
|
|
os.Stdout = old
|
|
|
|
var buf bytes.Buffer
|
|
_, _ = io.Copy(&buf, r)
|
|
|
|
output := buf.String()
|
|
if !strings.Contains(output, "debug message") {
|
|
t.Error("Expected debug message to be logged")
|
|
}
|
|
if !strings.Contains(output, "info message") {
|
|
t.Error("Expected info message to be logged")
|
|
}
|
|
}
|