package loggerx_test import ( "context" "fmt" "os" "path/filepath" "strings" "sync" "testing" "github.com/yuninks/loggerx" ) func readAllLogs(t *testing.T, dir string) string { t.Helper() var sb strings.Builder files, _ := filepath.Glob(filepath.Join(dir, "*.log")) for _, f := range files { b, err := os.ReadFile(f) if err != nil { t.Fatalf("读取 %s: %v", f, err) } sb.Write(b) } return sb.String() } // 写入量远超异步队列容量(1000)时的行为 func TestAsyncQueueOverflow(t *testing.T) { dir := t.TempDir() l := loggerx.NewLogger(context.Background(), loggerx.SetDir(dir), loggerx.SetWriteAsync()) const n = 5000 done := make(chan struct{}) go func() { defer close(done) for i := 0; i < n; i++ { l.Infof(context.Background(), "OVF-%d", i) } }() // 等写完,再关闭 <-done if err := l.Close(); err != nil { t.Fatalf("Close: %v", err) } content := readAllLogs(t, dir) missing := 0 for i := 0; i < n; i++ { if !strings.Contains(content, fmt.Sprintf(`OVF-%d"`, i)) { missing++ } } t.Logf("写入 %d 条,落盘缺失 %d 条,文件字节=%d", n, missing, len(content)) if missing > 0 { t.Errorf("队列溢出场景丢日志 %d 条", missing) } } // 超过队列容量且「边写边关闭」:不能永久阻塞 func TestAsyncOverflowConcurrentClose(t *testing.T) { dir := t.TempDir() l := loggerx.NewLogger(context.Background(), loggerx.SetDir(dir), loggerx.SetWriteAsync()) const n = 5000 var wg sync.WaitGroup wg.Add(1) go func() { defer wg.Done() for i := 0; i < n; i++ { l.Infof(context.Background(), "CLOSE-%d", i) } }() // 写一半就关 closeDone := make(chan error, 1) go func() { closeDone <- l.Close() }() waitWrite := make(chan struct{}) go func() { wg.Wait(); close(waitWrite) }() // 两者都必须在合理时间内结束,否则就是死锁 for i := 0; i < 2; i++ { select { case err := <-closeDone: if err != nil { t.Errorf("Close 返回错误: %v", err) } closeDone = nil case <-waitWrite: waitWrite = nil } if closeDone == nil && waitWrite == nil { break } } if closeDone != nil || waitWrite != nil { t.Fatal("写入或 Close 卡死(死锁)") } }