yao/agent/output/message/utils_test.go
Max ef49827faf Refactor message handling for improved streaming and event management
- Updated message structures to replace 'StreamStartData' and 'StreamEndData' with 'EventStreamStartData' and 'EventStreamEndData' for better clarity and consistency.
- Introduced 'EventMessageStartData' and 'EventMessageEndData' to represent individual message lifecycle events, enhancing the granularity of message tracking.
- Refactored the 'streamState' and 'groupTracker' to utilize the new message structures, improving the organization and handling of streaming events.
- Enhanced the context management by integrating an ID generator for unique message identifiers, facilitating better tracking of message sequences.
- Updated documentation and tests to reflect the new message structures and ensure proper functionality across the system.
2025-11-26 18:30:43 +08:00

188 lines
4.1 KiB
Go

package message
import (
"sync"
"testing"
)
func TestIDGenerator(t *testing.T) {
gen := NewIDGenerator()
t.Run("GenerateChunkID", func(t *testing.T) {
id1 := gen.GenerateChunkID()
id2 := gen.GenerateChunkID()
id3 := gen.GenerateChunkID()
if id1 != "C1" {
t.Errorf("Expected C1, got %s", id1)
}
if id2 != "C2" {
t.Errorf("Expected C2, got %s", id2)
}
if id3 != "C3" {
t.Errorf("Expected C3, got %s", id3)
}
})
t.Run("GenerateMessageID", func(t *testing.T) {
gen := NewIDGenerator()
id1 := gen.GenerateMessageID()
id2 := gen.GenerateMessageID()
id3 := gen.GenerateMessageID()
if id1 != "M1" {
t.Errorf("Expected M1, got %s", id1)
}
if id2 != "M2" {
t.Errorf("Expected M2, got %s", id2)
}
if id3 != "M3" {
t.Errorf("Expected M3, got %s", id3)
}
})
t.Run("GenerateBlockID", func(t *testing.T) {
gen := NewIDGenerator()
id1 := gen.GenerateBlockID()
id2 := gen.GenerateBlockID()
id3 := gen.GenerateBlockID()
if id1 != "B1" {
t.Errorf("Expected B1, got %s", id1)
}
if id2 != "B2" {
t.Errorf("Expected B2, got %s", id2)
}
if id3 != "B3" {
t.Errorf("Expected B3, got %s", id3)
}
})
t.Run("GenerateThreadID", func(t *testing.T) {
gen := NewIDGenerator()
id1 := gen.GenerateThreadID()
id2 := gen.GenerateThreadID()
id3 := gen.GenerateThreadID()
if id1 != "T1" {
t.Errorf("Expected T1, got %s", id1)
}
if id2 != "T2" {
t.Errorf("Expected T2, got %s", id2)
}
if id3 != "T3" {
t.Errorf("Expected T3, got %s", id3)
}
})
t.Run("Reset", func(t *testing.T) {
gen := NewIDGenerator()
gen.GenerateChunkID()
gen.GenerateMessageID()
gen.GenerateBlockID()
gen.GenerateThreadID()
gen.Reset()
chunk, message, block, thread := gen.GetCounters()
if chunk != 0 || message != 0 || block != 0 || thread != 0 {
t.Errorf("Expected all counters to be 0 after reset, got chunk=%d, message=%d, block=%d, thread=%d",
chunk, message, block, thread)
}
// Verify IDs start from 1 again
if id := gen.GenerateChunkID(); id != "C1" {
t.Errorf("Expected C1 after reset, got %s", id)
}
if id := gen.GenerateMessageID(); id != "M1" {
t.Errorf("Expected M1 after reset, got %s", id)
}
})
t.Run("ConcurrentAccess", func(t *testing.T) {
gen := NewIDGenerator()
var wg sync.WaitGroup
count := 100
// Test concurrent chunk ID generation
wg.Add(count)
for i := 0; i < count; i++ {
go func() {
defer wg.Done()
gen.GenerateChunkID()
}()
}
wg.Wait()
chunk, _, _, _ := gen.GetCounters()
if chunk != uint64(count) {
t.Errorf("Expected chunk counter to be %d, got %d", count, chunk)
}
})
t.Run("MultipleGenerators", func(t *testing.T) {
gen1 := NewIDGenerator()
gen2 := NewIDGenerator()
id1 := gen1.GenerateMessageID()
id2 := gen2.GenerateMessageID()
// Both should start from M1
if id1 != "M1" || id2 != "M1" {
t.Errorf("Expected both generators to start from M1, got %s and %s", id1, id2)
}
// Advance gen1
gen1.GenerateMessageID()
gen1.GenerateMessageID()
// gen2 should still be at M1
id2_next := gen2.GenerateMessageID()
if id2_next != "M2" {
t.Errorf("Expected gen2 to be at M2, got %s", id2_next)
}
// gen1 should be at M3
id1_next := gen1.GenerateMessageID()
if id1_next != "M4" {
t.Errorf("Expected gen1 to be at M4, got %s", id1_next)
}
})
}
func TestGenerateNanoID(t *testing.T) {
id1 := GenerateNanoID()
id2 := GenerateNanoID()
// NanoID should be 21 characters by default
if len(id1) != 21 {
t.Errorf("Expected NanoID length to be 21, got %d", len(id1))
}
// IDs should be unique
if id1 == id2 {
t.Error("Expected unique NanoIDs, got duplicates")
}
t.Logf("Generated NanoIDs: %s, %s", id1, id2)
}
func TestGenerateCustomID(t *testing.T) {
id1 := GenerateCustomID("msg")
id2 := GenerateCustomID("evt")
// Should have prefix
if len(id1) < 4 || id1[:4] != "msg_" {
t.Errorf("Expected ID to start with 'msg_', got %s", id1)
}
if len(id2) < 4 || id2[:4] != "evt_" {
t.Errorf("Expected ID to start with 'evt_', got %s", id2)
}
// IDs should be unique
if id1 == id2 {
t.Error("Expected unique custom IDs, got duplicates")
}
t.Logf("Generated custom IDs: %s, %s", id1, id2)
}