185 lines
7.8 KiB
Go
185 lines
7.8 KiB
Go
package latencylog
|
|
|
|
import (
|
|
"bufio"
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"reflect"
|
|
"testing"
|
|
|
|
"omnisocketgo/cmd/internal/protocol"
|
|
)
|
|
|
|
func TestSummarizeEventsComputesLatencyMetrics(t *testing.T) {
|
|
events := []Event{
|
|
{TsUnixNano: 100, Event: EventAAppPrepBegin, MessageType: protocol.MessageTypeText, MessageID: 1, From: "peer-a", To: "peer-b"},
|
|
{TsUnixNano: 120, Event: EventATXSched, MessageType: protocol.MessageTypeText, MessageID: 1, From: "peer-a", To: "peer-b"},
|
|
{TsUnixNano: 140, Event: EventATXSoftware, MessageType: protocol.MessageTypeText, MessageID: 1, From: "peer-a", To: "peer-b"},
|
|
{TsUnixNano: 180, Event: EventBRXSoftware, MessageType: protocol.MessageTypeText, MessageID: 1, From: "peer-a", To: "peer-b"},
|
|
{TsUnixNano: 220, Event: EventBAppRecv, MessageType: protocol.MessageTypeText, MessageID: 1, From: "peer-a", To: "peer-b"},
|
|
{TsUnixNano: 230, Event: EventBPersistBegin, MessageType: protocol.MessageTypeText, MessageID: 1, From: "peer-a", To: "peer-b"},
|
|
{TsUnixNano: 260, Event: EventBPersistEnd, MessageType: protocol.MessageTypeText, MessageID: 1, From: "peer-a", To: "peer-b"},
|
|
}
|
|
|
|
summaries := SummarizeEvents(events)
|
|
if len(summaries) != 1 {
|
|
t.Fatalf("summary count = %d, want 1", len(summaries))
|
|
}
|
|
|
|
summary := summaries[0]
|
|
if got := ptrValue(summary.AProcessingLatencyNS); got != 20 {
|
|
t.Fatalf("AProcessingLatencyNS = %d, want 20", got)
|
|
}
|
|
if got := ptrValue(summary.AQueueLatencyNS); got != 20 {
|
|
t.Fatalf("AQueueLatencyNS = %d, want 20", got)
|
|
}
|
|
if got := ptrValue(summary.ABTransportPropagationNS); got != 80 {
|
|
t.Fatalf("ABTransportPropagationNS = %d, want 80", got)
|
|
}
|
|
if got := ptrValue(summary.BKernelReceivePathLatencyNS); got != 40 {
|
|
t.Fatalf("BKernelReceivePathLatencyNS = %d, want 40", got)
|
|
}
|
|
if got := ptrValue(summary.BProcessingLatencyNS); got != 40 {
|
|
t.Fatalf("BProcessingLatencyNS = %d, want 40", got)
|
|
}
|
|
if got := ptrValue(summary.EndToEndLatencyNS); got != 160 {
|
|
t.Fatalf("EndToEndLatencyNS = %d, want 160", got)
|
|
}
|
|
if got := summary.Timestamps[EventBRXSoftware]; got != 180 {
|
|
t.Fatalf("timestamps[%q] = %d, want 180", EventBRXSoftware, got)
|
|
}
|
|
if len(summary.MissingTimestamps) != 0 {
|
|
t.Fatalf("MissingTimestamps = %v, want empty", summary.MissingTimestamps)
|
|
}
|
|
}
|
|
|
|
func TestSummarizeEventsComputesApproxRTTByPairingReverseMessages(t *testing.T) {
|
|
events := []Event{
|
|
{TsUnixNano: 100, Event: EventAAppPrepBegin, MessageType: protocol.MessageTypeText, MessageID: 1, From: "peer-a", To: "peer-b"},
|
|
{TsUnixNano: 110, Event: EventATXSoftware, MessageType: protocol.MessageTypeText, MessageID: 1, From: "peer-a", To: "peer-b"},
|
|
{TsUnixNano: 180, Event: EventBAppRecv, MessageType: protocol.MessageTypeText, MessageID: 1, From: "peer-a", To: "peer-b"},
|
|
{TsUnixNano: 120, Event: EventAAppPrepBegin, MessageType: protocol.MessageTypeText, MessageID: 2, From: "peer-a", To: "peer-b"},
|
|
{TsUnixNano: 140, Event: EventATXSoftware, MessageType: protocol.MessageTypeText, MessageID: 2, From: "peer-a", To: "peer-b"},
|
|
{TsUnixNano: 190, Event: EventBAppRecv, MessageType: protocol.MessageTypeText, MessageID: 2, From: "peer-a", To: "peer-b"},
|
|
{TsUnixNano: 200, Event: EventAAppPrepBegin, MessageType: protocol.MessageTypeText, MessageID: 11, From: "peer-b", To: "peer-a"},
|
|
{TsUnixNano: 210, Event: EventATXSoftware, MessageType: protocol.MessageTypeText, MessageID: 11, From: "peer-b", To: "peer-a"},
|
|
{TsUnixNano: 260, Event: EventBAppRecv, MessageType: protocol.MessageTypeText, MessageID: 11, From: "peer-b", To: "peer-a"},
|
|
{TsUnixNano: 220, Event: EventAAppPrepBegin, MessageType: protocol.MessageTypeText, MessageID: 12, From: "peer-b", To: "peer-a"},
|
|
{TsUnixNano: 230, Event: EventATXSoftware, MessageType: protocol.MessageTypeText, MessageID: 12, From: "peer-b", To: "peer-a"},
|
|
{TsUnixNano: 310, Event: EventBAppRecv, MessageType: protocol.MessageTypeText, MessageID: 12, From: "peer-b", To: "peer-a"},
|
|
}
|
|
|
|
summaries := SummarizeEvents(events)
|
|
if len(summaries) != 4 {
|
|
t.Fatalf("summary count = %d, want 4", len(summaries))
|
|
}
|
|
|
|
gotByMessageID := make(map[uint64]Summary, len(summaries))
|
|
for _, summary := range summaries {
|
|
gotByMessageID[summary.MessageID] = summary
|
|
}
|
|
|
|
if got := ptrValue(gotByMessageID[1].ApproxRTTNS); got != 150 {
|
|
t.Fatalf("message 1 ApproxRTTNS = %d, want 150", got)
|
|
}
|
|
if got := ptrValue(gotByMessageID[2].ApproxRTTNS); got != 170 {
|
|
t.Fatalf("message 2 ApproxRTTNS = %d, want 170", got)
|
|
}
|
|
if gotByMessageID[11].ApproxRTTNS != nil {
|
|
t.Fatalf("message 11 ApproxRTTNS = %d, want nil", ptrValue(gotByMessageID[11].ApproxRTTNS))
|
|
}
|
|
if gotByMessageID[12].ApproxRTTNS != nil {
|
|
t.Fatalf("message 12 ApproxRTTNS = %d, want nil", ptrValue(gotByMessageID[12].ApproxRTTNS))
|
|
}
|
|
}
|
|
|
|
func TestSummarizeEventsReportsMissingTimestamps(t *testing.T) {
|
|
events := []Event{
|
|
{TsUnixNano: 100, Event: EventAAppPrepBegin, MessageType: protocol.MessageTypeText, MessageID: 2, From: "peer-a", To: "peer-b"},
|
|
{TsUnixNano: 240, Event: EventBPersistEnd, MessageType: protocol.MessageTypeText, MessageID: 2, From: "peer-a", To: "peer-b"},
|
|
}
|
|
|
|
summaries := SummarizeEvents(events)
|
|
if len(summaries) != 1 {
|
|
t.Fatalf("summary count = %d, want 1", len(summaries))
|
|
}
|
|
|
|
wantMissing := []string{EventATXSched, EventATXSoftware, EventBRXSoftware, EventBAppRecv}
|
|
if !reflect.DeepEqual(summaries[0].MissingTimestamps, wantMissing) {
|
|
t.Fatalf("MissingTimestamps = %v, want %v", summaries[0].MissingTimestamps, wantMissing)
|
|
}
|
|
if summaries[0].AProcessingLatencyNS != nil {
|
|
t.Fatalf("AProcessingLatencyNS = %v, want nil", ptrValue(summaries[0].AProcessingLatencyNS))
|
|
}
|
|
if summaries[0].EndToEndLatencyNS == nil {
|
|
t.Fatal("EndToEndLatencyNS = nil, want non-nil because endpoints are present")
|
|
}
|
|
}
|
|
|
|
func TestLoadAndWriteSummaryFiles(t *testing.T) {
|
|
rawPath := filepath.Join(t.TempDir(), "raw.jsonl")
|
|
rawLogger, err := NewJSONLLogger(rawPath)
|
|
if err != nil {
|
|
t.Fatalf("NewJSONLLogger() error = %v", err)
|
|
}
|
|
t.Cleanup(func() {
|
|
_ = rawLogger.Close()
|
|
})
|
|
|
|
for _, event := range []Event{
|
|
{TsUnixNano: 100, Event: EventAAppPrepBegin, MessageType: protocol.MessageTypeText, MessageID: 3, From: "peer-a", To: "peer-b"},
|
|
{TsUnixNano: 120, Event: EventATXSched, MessageType: protocol.MessageTypeText, MessageID: 3, From: "peer-a", To: "peer-b"},
|
|
{TsUnixNano: 140, Event: EventATXSoftware, MessageType: protocol.MessageTypeText, MessageID: 3, From: "peer-a", To: "peer-b"},
|
|
{TsUnixNano: 180, Event: EventBRXSoftware, MessageType: protocol.MessageTypeText, MessageID: 3, From: "peer-a", To: "peer-b"},
|
|
{TsUnixNano: 220, Event: EventBAppRecv, MessageType: protocol.MessageTypeText, MessageID: 3, From: "peer-a", To: "peer-b"},
|
|
{TsUnixNano: 260, Event: EventBPersistEnd, MessageType: protocol.MessageTypeText, MessageID: 3, From: "peer-a", To: "peer-b"},
|
|
} {
|
|
if err := rawLogger.LogEvent(event); err != nil {
|
|
t.Fatalf("LogEvent() error = %v", err)
|
|
}
|
|
}
|
|
|
|
events, err := LoadEventsFromFile(rawPath)
|
|
if err != nil {
|
|
t.Fatalf("LoadEventsFromFile() error = %v", err)
|
|
}
|
|
|
|
summaryPath := filepath.Join(t.TempDir(), "summary.jsonl")
|
|
if err := WriteSummariesJSONL(summaryPath, SummarizeEvents(events)); err != nil {
|
|
t.Fatalf("WriteSummariesJSONL() error = %v", err)
|
|
}
|
|
|
|
file, err := os.Open(summaryPath)
|
|
if err != nil {
|
|
t.Fatalf("os.Open() error = %v", err)
|
|
}
|
|
defer file.Close()
|
|
|
|
scanner := bufio.NewScanner(file)
|
|
if !scanner.Scan() {
|
|
t.Fatal("expected one summary line, got none")
|
|
}
|
|
|
|
var summary Summary
|
|
if err := json.Unmarshal(scanner.Bytes(), &summary); err != nil {
|
|
t.Fatalf("json.Unmarshal() error = %v", err)
|
|
}
|
|
if summary.MessageID != 3 {
|
|
t.Fatalf("MessageID = %d, want 3", summary.MessageID)
|
|
}
|
|
if got := ptrValue(summary.BKernelReceivePathLatencyNS); got != 40 {
|
|
t.Fatalf("BKernelReceivePathLatencyNS = %d, want 40", got)
|
|
}
|
|
if got := ptrValue(summary.EndToEndLatencyNS); got != 160 {
|
|
t.Fatalf("EndToEndLatencyNS = %d, want 160", got)
|
|
}
|
|
}
|
|
|
|
func ptrValue(value *int64) int64 {
|
|
if value == nil {
|
|
return 0
|
|
}
|
|
return *value
|
|
}
|