package latencylog import ( "bufio" "encoding/json" "os" "path/filepath" "sync" "testing" "omnisocketgo/cmd/internal/protocol" ) func TestJSONLLoggerWritesOneEventPerLine(t *testing.T) { path := filepath.Join(t.TempDir(), "latency.jsonl") logger, err := NewJSONLLogger(path) if err != nil { t.Fatalf("NewJSONLLogger() error = %v", err) } t.Cleanup(func() { _ = logger.Close() }) event := Event{ TsUnixNano: 123, NodeRole: NodeRolePeer, NodeID: "peer-a", Event: EventAAppPrepBegin, MessageType: protocol.MessageTypeText, MessageID: 1, From: "peer-a", To: "peer-b", BodySize: 5, } if err := logger.LogEvent(event); err != nil { t.Fatalf("LogEvent() error = %v", err) } file, err := os.Open(path) if err != nil { t.Fatalf("os.Open() error = %v", err) } defer file.Close() scanner := bufio.NewScanner(file) if !scanner.Scan() { t.Fatal("expected one JSONL line, got none") } var got Event if err := json.Unmarshal(scanner.Bytes(), &got); err != nil { t.Fatalf("json.Unmarshal() error = %v", err) } if got != event { t.Fatalf("event mismatch: got %+v want %+v", got, event) } if scanner.Scan() { t.Fatal("expected exactly one JSONL line") } if err := scanner.Err(); err != nil { t.Fatalf("scanner.Err() = %v", err) } } func TestJSONLLoggerHandlesConcurrentWrites(t *testing.T) { path := filepath.Join(t.TempDir(), "latency.jsonl") logger, err := NewJSONLLogger(path) if err != nil { t.Fatalf("NewJSONLLogger() error = %v", err) } t.Cleanup(func() { _ = logger.Close() }) const total = 32 var wg sync.WaitGroup for i := 0; i < total; i++ { i := i wg.Add(1) go func() { defer wg.Done() err := logger.LogEvent(Event{ TsUnixNano: int64(i + 1), NodeRole: NodeRoleServer, NodeID: protocol.ServerPeerID, Event: EventBAppRecv, MessageType: protocol.MessageTypeFile, MessageID: uint64(i + 1), From: "peer-a", To: "peer-b", FileName: "payload.bin", BodySize: 3, }) if err != nil { t.Errorf("LogEvent() error = %v", err) } }() } wg.Wait() file, err := os.Open(path) if err != nil { t.Fatalf("os.Open() error = %v", err) } defer file.Close() scanner := bufio.NewScanner(file) var count int seen := make(map[uint64]bool, total) for scanner.Scan() { var event Event if err := json.Unmarshal(scanner.Bytes(), &event); err != nil { t.Fatalf("json.Unmarshal() error = %v", err) } count++ seen[event.MessageID] = true } if err := scanner.Err(); err != nil { t.Fatalf("scanner.Err() = %v", err) } if count != total { t.Fatalf("line count = %d, want %d", count, total) } if len(seen) != total { t.Fatalf("unique message count = %d, want %d", len(seen), total) } }