package main import ( "testing" "time" ) func TestChatSession_AddMessage(t *testing.T) { cs := &ChatSession{ Buffer: make([]ChatMessage, 0), subscribers: make(map[string]*Subscriber), } cs.AddMessage(ChatMessage{Role: "user", Content: "hello"}) cs.AddMessage(ChatMessage{Role: "assistant", Content: "hi"}) buf := cs.GetBuffer() if len(buf) != 2 { t.Fatalf("buffer len = %d, want 2", len(buf)) } if buf[0].Role != "user" { t.Errorf("buf[0].Role = %q", buf[0].Role) } if buf[1].Content != "hi" { t.Errorf("buf[1].Content = %q", buf[1].Content) } } func TestChatSession_BufferCap(t *testing.T) { cs := &ChatSession{ Buffer: make([]ChatMessage, 0), subscribers: make(map[string]*Subscriber), } for i := 0; i < maxBufferSize+50; i++ { cs.AddMessage(ChatMessage{Role: "user", Content: "msg"}) } buf := cs.GetBuffer() if len(buf) != maxBufferSize { t.Errorf("buffer len = %d, want %d", len(buf), maxBufferSize) } } func TestChatSession_GetBufferIsCopy(t *testing.T) { cs := &ChatSession{ Buffer: make([]ChatMessage, 0), subscribers: make(map[string]*Subscriber), } cs.AddMessage(ChatMessage{Role: "user", Content: "hello"}) buf := cs.GetBuffer() buf[0].Content = "modified" original := cs.GetBuffer() if original[0].Content != "hello" { t.Error("GetBuffer should return a copy") } } func TestChatSession_LastActiveUpdated(t *testing.T) { cs := &ChatSession{ Buffer: make([]ChatMessage, 0), LastActive: time.Now().Add(-1 * time.Hour), subscribers: make(map[string]*Subscriber), } before := cs.LastActive cs.AddMessage(ChatMessage{Role: "user", Content: "hello"}) if !cs.LastActive.After(before) { t.Error("LastActive should be updated") } } func TestChatSession_Subscribe(t *testing.T) { cs := &ChatSession{ Buffer: make([]ChatMessage, 0), subscribers: make(map[string]*Subscriber), } sub := cs.Subscribe("test-1") if sub == nil { t.Fatal("subscriber is nil") } if cs.SubscriberCount() != 1 { t.Errorf("subscriber count = %d, want 1", cs.SubscriberCount()) } // Message should be broadcast go cs.AddMessage(ChatMessage{Role: "user", Content: "hello"}) select { case msg := <-sub.Ch: if msg != "hello" { t.Errorf("got %q, want hello", msg) } case <-time.After(time.Second): t.Fatal("timeout waiting for broadcast") } } func TestChatSession_Unsubscribe(t *testing.T) { cs := &ChatSession{ Buffer: make([]ChatMessage, 0), subscribers: make(map[string]*Subscriber), } cs.Subscribe("test-1") cs.Unsubscribe("test-1") if cs.SubscriberCount() != 0 { t.Errorf("subscriber count = %d, want 0", cs.SubscriberCount()) } } func TestChatSession_MultipleSubscribers(t *testing.T) { cs := &ChatSession{ Buffer: make([]ChatMessage, 0), subscribers: make(map[string]*Subscriber), } sub1 := cs.Subscribe("s1") sub2 := cs.Subscribe("s2") go cs.AddMessage(ChatMessage{Role: "user", Content: "broadcast"}) for _, sub := range []*Subscriber{sub1, sub2} { select { case msg := <-sub.Ch: if msg != "broadcast" { t.Errorf("got %q, want broadcast", msg) } case <-time.After(time.Second): t.Fatal("timeout waiting for broadcast") } } } func TestChatSessionManager_Count(t *testing.T) { csm := NewChatSessionManager() defer csm.Stop() if csm.Count() != 0 { t.Errorf("initial count = %d, want 0", csm.Count()) } } func TestChatSessionManager_Remove(t *testing.T) { csm := NewChatSessionManager() defer csm.Stop() // Remove nonexistent should not panic csm.Remove("nonexistent") }