Files

188 lines
5.3 KiB
Go
Raw Permalink Normal View History

2026-09-14 00:14:30 +08:00
package loggerx_test
import (
"context"
"encoding/json"
"os"
"path/filepath"
"strings"
"testing"
"github.com/yuninks/loggerx"
)
func readOne(t *testing.T, dir, file string) string {
t.Helper()
files, _ := filepath.Glob(filepath.Join(dir, "*_"+file))
if len(files) == 0 {
files, _ = filepath.Glob(filepath.Join(dir, file))
}
if len(files) == 0 {
t.Fatalf("没找到 %s", file)
}
b, err := os.ReadFile(files[0])
if err != nil {
t.Fatal(err)
}
return string(b)
}
// 默认(不调用 SetFormat)必须是合法 JSON —— 与 readme 的承诺一致
func TestDefaultFormatIsJSON(t *testing.T) {
dir := t.TempDir()
l := loggerx.NewLogger(context.Background(), loggerx.SetDir(dir))
l.Info(context.Background(), "hello")
if err := l.Close(); err != nil {
t.Fatal(err)
}
line := strings.TrimSpace(readOne(t, dir, "info.log"))
var v map[string]any
if err := json.Unmarshal([]byte(line), &v); err != nil {
t.Fatalf("默认格式不是合法 JSON: %v\n%s", err, line)
}
if v["level"] != "info" {
t.Errorf("level=%v", v["level"])
}
}
// SetFormat(FormatText) 之后输出单行文本,且仍是一行一条
func TestTextFormat(t *testing.T) {
dir := t.TempDir()
l := loggerx.NewLogger(context.Background(),
loggerx.SetDir(dir),
loggerx.SetFormat(loggerx.FormatText),
)
ctx := context.Background()
l.Info(ctx, "hello text")
l.Errorf(ctx, "boom %d", 42)
if err := l.Close(); err != nil {
t.Fatal(err)
}
info := strings.TrimSpace(readOne(t, dir, "info.log"))
if info == "" {
t.Fatal("text 格式没有输出")
}
for _, want := range []string{"level=info", "time=", "file=", "content="} {
if !strings.Contains(info, want) {
t.Errorf("text 输出缺少 %q: %s", want, info)
}
}
if strings.HasPrefix(info, "{") {
t.Errorf("SetFormat(text) 之后不应还是 JSON: %s", info)
}
if strings.Count(info, "\n") != 0 {
t.Errorf("一条日志必须占一行: %q", info)
}
errLine := strings.TrimSpace(readOne(t, dir, "error.log"))
if !strings.Contains(errLine, "level=error") || !strings.Contains(errLine, "42") {
t.Errorf("error 的 text 输出不正确: %s", errLine)
}
}
// 内容里有空格/引号时,text 格式用引号包起来,避免歧义
func TestTextFormatQuotesAmbiguousValues(t *testing.T) {
dir := t.TempDir()
l := loggerx.NewLogger(context.Background(),
loggerx.SetDir(dir),
loggerx.SetFormat(loggerx.FormatText),
)
l.Info(context.Background(), "has space and \"quote\"")
if err := l.Close(); err != nil {
t.Fatal(err)
}
line := strings.TrimSpace(readOne(t, dir, "info.log"))
if !strings.Contains(line, `content="`) {
t.Errorf("含空格/引号的值应当被引号包裹: %s", line)
}
}
// SetFormat 传非法值时应保持默认,而不是切到一个没实现的格式
func TestInvalidFormatKeepsDefault(t *testing.T) {
dir := t.TempDir()
l := loggerx.NewLogger(context.Background(),
loggerx.SetDir(dir),
loggerx.SetFormat(loggerx.Format("yaml")),
)
l.Info(context.Background(), "still-json")
if err := l.Close(); err != nil {
t.Fatal(err)
}
line := strings.TrimSpace(readOne(t, dir, "info.log"))
var v map[string]any
if err := json.Unmarshal([]byte(line), &v); err != nil {
t.Errorf("非法格式值不该改变默认行为: %v\n%s", err, line)
}
}
// SetPrefix 必须真的加上前缀(两种格式都生效)
func TestPrefixApplied(t *testing.T) {
dir := t.TempDir()
l := loggerx.NewLogger(context.Background(),
loggerx.SetDir(dir),
loggerx.SetPrefix("[order-svc] "),
)
l.Info(context.Background(), "with-prefix")
if err := l.Close(); err != nil {
t.Fatal(err)
}
line := readOne(t, dir, "info.log")
if !strings.HasPrefix(line, "[order-svc] ") {
t.Errorf("前缀未生效: %q", line)
}
// 前缀之后仍然要是合法 JSON
body := strings.TrimSpace(strings.TrimPrefix(line, "[order-svc] "))
var v map[string]any
if err := json.Unmarshal([]byte(body), &v); err != nil {
t.Errorf("前缀后的内容不是合法 JSON: %v\n%s", err, body)
}
}
// text 格式 + 前缀 + expandData 组合
func TestTextFormatWithPrefixAndExpand(t *testing.T) {
dir := t.TempDir()
l := loggerx.NewLogger(context.Background(),
loggerx.SetDir(dir),
loggerx.SetFormat(loggerx.FormatText),
loggerx.SetPrefix("P|"),
loggerx.SetExpandData("app", "order"),
)
l.Info(context.Background(), "combo")
if err := l.Close(); err != nil {
t.Fatal(err)
}
line := strings.TrimSpace(readOne(t, dir, "info.log"))
if !strings.HasPrefix(line, "P|level=info") {
t.Errorf("前缀/格式组合输出不正确: %s", line)
}
if !strings.Contains(line, "app=order") {
t.Errorf("expandData 未出现在 text 输出里: %s", line)
}
}
// text 格式下不可序列化的内容也不能丢
func TestTextFormatUnmarshalableContent(t *testing.T) {
dir := t.TempDir()
l := loggerx.NewLogger(context.Background(),
loggerx.SetDir(dir),
loggerx.SetFormat(loggerx.FormatText),
)
l.Info(context.Background(), make(chan int), func() {})
l.Info(context.Background(), "after")
if err := l.Close(); err != nil {
t.Fatal(err)
}
content := readOne(t, dir, "info.log")
lines := strings.Split(strings.TrimSpace(content), "\n")
if len(lines) != 2 {
t.Fatalf("期望 2 行,实际 %d: %q", len(lines), content)
}
for i, line := range lines {
if !strings.Contains(line, "content=") {
t.Errorf("第 %d 行缺少 content: %s", i+1, line)
}
}
}