- 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.
188 lines
4.1 KiB
Go
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)
|
|
}
|