// Package messages benchmarks protobuf encoding/decoding of all message types. // // Run with: // //go test -bench=. -benchmem -count=5 ./messages/... | tee bench.txt //# optional: go install golang.org/x/perf/cmd/benchstat@latest && benchstat bench.txt package messages import ( "testing" "time" "google.golang.org/protobuf/proto" pb "git.daviestechlabs.io/daviestechlabs/handler-base/gen/messagespb" ) // ──────────────────────────────────────────────────────────────────────────── // Test fixtures — proto message constructors // ──────────────────────────────────────────────────────────────────────────── func chatRequestProto() *pb.ChatRequest { return &pb.ChatRequest{ RequestId: "req-abc-123", UserId: "user-42", Message: "What is the capital of France?", Premium: true, EnableRag: true, EnableReranker: true, TopK: 10, Collection: "documents", SystemPrompt: "You are a helpful assistant.", ResponseSubject: "ai.chat.response.req-abc-123", } } func voiceResponseProto() *pb.VoiceResponse { return &pb.VoiceResponse{ RequestId: "vr-001", Response: "The capital of France is Paris.", Audio: make([]byte, 16384), Transcription: "What is the capital of France?", } } func ttsChunkProto() *pb.TTSAudioChunk { return &pb.TTSAudioChunk{ SessionId: "tts-sess-99", ChunkIndex: 3, TotalChunks: 12, Audio: make([]byte, 32768), IsLast: false, Timestamp: time.Now().Unix(), SampleRate: 24000, } } // ──────────────────────────────────────────────────────────────────────────── // Wire-size comparison (run once, printed by TestWireSize) // ──────────────────────────────────────────────────────────────────────────── func TestWireSize(t *testing.T) { tests := []struct { name string protoMsg proto.Message }{ {"ChatRequest", chatRequestProto()}, {"VoiceResponse", voiceResponseProto()}, {"TTSAudioChunk", ttsChunkProto()}, } for _, tt := range tests { protoBytes, _ := proto.Marshal(tt.protoMsg) t.Logf("%-16s proto=%5d B", tt.name, len(protoBytes)) } } // ──────────────────────────────────────────────────────────────────────────── // Encode benchmarks // ──────────────────────────────────────────────────────────────────────────── func BenchmarkEncode_ChatRequest(b *testing.B) { data := chatRequestProto() b.ResetTimer() for b.Loop() { _, _ = proto.Marshal(data) } } func BenchmarkEncode_VoiceResponse(b *testing.B) { data := voiceResponseProto() b.ResetTimer() for b.Loop() { _, _ = proto.Marshal(data) } } func BenchmarkEncode_TTSChunk(b *testing.B) { data := ttsChunkProto() b.ResetTimer() for b.Loop() { _, _ = proto.Marshal(data) } } // ──────────────────────────────────────────────────────────────────────────── // Decode benchmarks // ──────────────────────────────────────────────────────────────────────────── func BenchmarkDecode_ChatRequest(b *testing.B) { encoded, _ := proto.Marshal(chatRequestProto()) b.ResetTimer() for b.Loop() { var m pb.ChatRequest _ = proto.Unmarshal(encoded, &m) } } func BenchmarkDecode_VoiceResponse(b *testing.B) { encoded, _ := proto.Marshal(voiceResponseProto()) b.ResetTimer() for b.Loop() { var m pb.VoiceResponse _ = proto.Unmarshal(encoded, &m) } } func BenchmarkDecode_TTSChunk(b *testing.B) { encoded, _ := proto.Marshal(ttsChunkProto()) b.ResetTimer() for b.Loop() { var m pb.TTSAudioChunk _ = proto.Unmarshal(encoded, &m) } } // ──────────────────────────────────────────────────────────────────────────── // Roundtrip benchmarks (encode + decode) // ──────────────────────────────────────────────────────────────────────────── func BenchmarkRoundtrip_ChatRequest(b *testing.B) { data := chatRequestProto() b.ResetTimer() for b.Loop() { enc, _ := proto.Marshal(data) var dec pb.ChatRequest _ = proto.Unmarshal(enc, &dec) } } // ──────────────────────────────────────────────────────────────────────────── // Correctness tests — verify proto roundtrip // ──────────────────────────────────────────────────────────────────────────── func TestRoundtrip_ChatRequest(t *testing.T) { orig := chatRequestProto() data, err := proto.Marshal(orig) if err != nil { t.Fatal(err) } var dec pb.ChatRequest if err := proto.Unmarshal(data, &dec); err != nil { t.Fatal(err) } if dec.GetRequestId() != orig.GetRequestId() { t.Errorf("RequestId = %q, want %q", dec.GetRequestId(), orig.GetRequestId()) } if dec.GetMessage() != orig.GetMessage() { t.Errorf("Message = %q, want %q", dec.GetMessage(), orig.GetMessage()) } if dec.GetTopK() != orig.GetTopK() { t.Errorf("TopK = %d, want %d", dec.GetTopK(), orig.GetTopK()) } if dec.GetPremium() != orig.GetPremium() { t.Errorf("Premium = %v, want %v", dec.GetPremium(), orig.GetPremium()) } if EffectiveQuery(&dec) != orig.GetMessage() { t.Errorf("EffectiveQuery() = %q, want %q", EffectiveQuery(&dec), orig.GetMessage()) } } func TestRoundtrip_VoiceResponse(t *testing.T) { orig := voiceResponseProto() data, err := proto.Marshal(orig) if err != nil { t.Fatal(err) } var dec pb.VoiceResponse if err := proto.Unmarshal(data, &dec); err != nil { t.Fatal(err) } if dec.GetRequestId() != orig.GetRequestId() { t.Errorf("RequestId mismatch") } if len(dec.GetAudio()) != len(orig.GetAudio()) { t.Errorf("Audio len = %d, want %d", len(dec.GetAudio()), len(orig.GetAudio())) } if dec.GetTranscription() != orig.GetTranscription() { t.Errorf("Transcription mismatch") } } func TestRoundtrip_TTSAudioChunk(t *testing.T) { orig := ttsChunkProto() data, err := proto.Marshal(orig) if err != nil { t.Fatal(err) } var dec pb.TTSAudioChunk if err := proto.Unmarshal(data, &dec); err != nil { t.Fatal(err) } if dec.GetSessionId() != orig.GetSessionId() { t.Errorf("SessionId mismatch") } if dec.GetChunkIndex() != orig.GetChunkIndex() { t.Errorf("ChunkIndex = %d, want %d", dec.GetChunkIndex(), orig.GetChunkIndex()) } if len(dec.GetAudio()) != len(orig.GetAudio()) { t.Errorf("Audio len = %d, want %d", len(dec.GetAudio()), len(orig.GetAudio())) } if dec.GetSampleRate() != orig.GetSampleRate() { t.Errorf("SampleRate = %d, want %d", dec.GetSampleRate(), orig.GetSampleRate()) } } func TestRoundtrip_PipelineTrigger(t *testing.T) { orig := &pb.PipelineTrigger{ RequestId: "pip-001", Pipeline: "document-ingestion", Parameters: map[string]string{"source": "s3://bucket/data"}, } data, err := proto.Marshal(orig) if err != nil { t.Fatal(err) } var dec pb.PipelineTrigger if err := proto.Unmarshal(data, &dec); err != nil { t.Fatal(err) } if dec.GetPipeline() != orig.GetPipeline() { t.Errorf("Pipeline = %q, want %q", dec.GetPipeline(), orig.GetPipeline()) } if dec.GetParameters()["source"] != orig.GetParameters()["source"] { t.Errorf("Parameters[source] mismatch") } } func TestRoundtrip_STTTranscription(t *testing.T) { orig := &pb.STTTranscription{ SessionId: "stt-001", Transcript: "hello world", Sequence: 5, IsPartial: false, IsFinal: true, Timestamp: time.Now().Unix(), SpeakerId: "speaker-1", HasVoiceActivity: true, State: "listening", } data, err := proto.Marshal(orig) if err != nil { t.Fatal(err) } var dec pb.STTTranscription if err := proto.Unmarshal(data, &dec); err != nil { t.Fatal(err) } if dec.GetTranscript() != orig.GetTranscript() { t.Errorf("Transcript = %q, want %q", dec.GetTranscript(), orig.GetTranscript()) } if dec.GetIsFinal() != orig.GetIsFinal() { t.Error("IsFinal mismatch") } } func TestRoundtrip_ErrorResponse(t *testing.T) { orig := &pb.ErrorResponse{Error: true, Message: "something broke", Type: "InternalError"} data, err := proto.Marshal(orig) if err != nil { t.Fatal(err) } var dec pb.ErrorResponse if err := proto.Unmarshal(data, &dec); err != nil { t.Fatal(err) } if !dec.GetError() || dec.GetMessage() != "something broke" || dec.GetType() != "InternalError" { t.Errorf("ErrorResponse roundtrip mismatch: %+v", &dec) } } func TestEffectiveQuery_MessageSet(t *testing.T) { req := &pb.ChatRequest{Message: "hello", Query: "world"} if got := EffectiveQuery(req); got != "hello" { t.Errorf("EffectiveQuery() = %q, want %q", got, "hello") } } func TestEffectiveQuery_FallbackToQuery(t *testing.T) { req := &pb.ChatRequest{Query: "world"} if got := EffectiveQuery(req); got != "world" { t.Errorf("EffectiveQuery() = %q, want %q", got, "world") } } func TestTimestamp(t *testing.T) { ts := Timestamp() now := time.Now().Unix() if ts < now-1 || ts > now+1 { t.Errorf("Timestamp() = %d, expected ~%d", ts, now) } }