savinmax 03f379c73c refactor(hub): introduce room types and update Hub struct
- Add client struct with conn and room fields
- Add broadcastMsg struct with room and data fields
- Change Hub.clients to Hub.rooms map[string]map[*websocket.Conn]bool
- Add Hub.connRoom map[*websocket.Conn]string for reverse lookup
- Change broadcast channel type to chan broadcastMsg
- Change register channel type to chan client
- Update New() to initialize rooms and connRoom maps
- Update ClientCount() to use len(h.connRoom)
- Add RoomCount() method
- Update Run() loop for room-segmented register/unregister/broadcast
- Update HandleWebSocket to extract room from query param
- Backward compatible: clients without ?room use default empty room
- Update TestNew to verify rooms and connRoom maps initialized
- Add TestRoomCount to verify initial room count is 0
- Fix TestBroadcastChannel to use broadcastMsg type

All existing unit and integration tests pass (16 hub tests + 21 other).

🤖 Assisted by the code-assist SOP
2026-06-13 13:09:25 +02:00

88 lines
1.6 KiB
Go

package hub
import (
"bytes"
"testing"
"time"
"websocket-relay/internal/logging"
)
func newTestLogger() *logging.Logger {
return logging.NewLogger("debug", &bytes.Buffer{})
}
func TestNew(t *testing.T) {
h := New(newTestLogger())
if h == nil {
t.Fatal("New returned nil")
}
if h.rooms == nil {
t.Error("rooms map not initialized")
}
if h.connRoom == nil {
t.Error("connRoom map not initialized")
}
if h.broadcast == nil {
t.Error("broadcast channel not initialized")
}
if h.stop == nil {
t.Error("stop channel not initialized")
}
}
func TestClientCount(t *testing.T) {
h := New(newTestLogger())
go h.Run()
defer h.Shutdown()
if count := h.ClientCount(); count != 0 {
t.Errorf("Expected 0 clients, got %d", count)
}
}
func TestRoomCount(t *testing.T) {
h := New(newTestLogger())
go h.Run()
defer h.Shutdown()
if count := h.RoomCount(); count != 0 {
t.Errorf("Expected 0 rooms, got %d", count)
}
}
func TestBroadcastChannel(t *testing.T) {
h := New(newTestLogger())
go h.Run()
defer h.Shutdown()
select {
case h.broadcast <- broadcastMsg{room: "", data: []byte("test")}:
// Channel is working
case <-time.After(100 * time.Millisecond):
t.Error("broadcast channel blocked")
}
}
func TestShutdown(t *testing.T) {
h := New(newTestLogger())
done := make(chan struct{})
go func() {
h.Run()
close(done)
}()
// Ensure Run is processing before shutdown
time.Sleep(10 * time.Millisecond)
h.Shutdown()
select {
case <-done:
// Hub.Run() returned successfully
case <-time.After(1 * time.Second):
t.Fatal("Hub.Run() did not return after Shutdown")
}
}