334 lines
7.2 KiB
Go
334 lines
7.2 KiB
Go
package pubsub
|
|
|
|
import (
|
|
"net"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
type mockConn struct {
|
|
data []byte
|
|
pos int
|
|
}
|
|
|
|
func (m *mockConn) Read(b []byte) (n int, err error) {
|
|
if m.pos >= len(m.data) {
|
|
return 0, nil
|
|
}
|
|
n = copy(b, m.data[m.pos:])
|
|
m.pos += n
|
|
return n, nil
|
|
}
|
|
|
|
func (m *mockConn) Write(b []byte) (n int, err error) {
|
|
m.data = append(m.data, b...)
|
|
return len(b), nil
|
|
}
|
|
|
|
func (m *mockConn) Close() error { return nil }
|
|
func (m *mockConn) LocalAddr() net.Addr { return nil }
|
|
func (m *mockConn) RemoteAddr() net.Addr { return nil }
|
|
func (m *mockConn) SetDeadline(time.Time) error { return nil }
|
|
func (m *mockConn) SetReadDeadline(time.Time) error { return nil }
|
|
func (m *mockConn) SetWriteDeadline(time.Time) error { return nil }
|
|
|
|
func NewMockClient() *Client {
|
|
return NewClient(&mockConn{data: []byte{}})
|
|
}
|
|
|
|
func TestNewHub(t *testing.T) {
|
|
hub := NewHub()
|
|
if hub == nil {
|
|
t.Fatal("NewHub() returned nil")
|
|
}
|
|
if hub.subs == nil {
|
|
t.Error("hub.subs is nil")
|
|
}
|
|
}
|
|
|
|
func TestHubSubscribe(t *testing.T) {
|
|
hub := NewHub()
|
|
client := NewMockClient()
|
|
|
|
// Subscribe to a channel
|
|
ok := hub.Subscribe(client, "news")
|
|
if !ok {
|
|
t.Error("Subscribe() returned false for new subscription")
|
|
}
|
|
|
|
// Check subscriber count
|
|
count := hub.ChannelCount("news")
|
|
if count != 1 {
|
|
t.Errorf("ChannelCount() = %d, want 1", count)
|
|
}
|
|
|
|
// Duplicate subscription should return false
|
|
ok = hub.Subscribe(client, "news")
|
|
if ok {
|
|
t.Error("Subscribe() should return false for duplicate subscription")
|
|
}
|
|
}
|
|
|
|
func TestHubUnsubscribe(t *testing.T) {
|
|
hub := NewHub()
|
|
client := NewMockClient()
|
|
|
|
hub.Subscribe(client, "news")
|
|
|
|
ok := hub.Unsubscribe(client, "news")
|
|
if !ok {
|
|
t.Error("Unsubscribe() returned false")
|
|
}
|
|
|
|
count := hub.ChannelCount("news")
|
|
if count != 0 {
|
|
t.Errorf("ChannelCount() = %d, want 0", count)
|
|
}
|
|
}
|
|
|
|
func TestHubUnsubscribeNotSubscribed(t *testing.T) {
|
|
hub := NewHub()
|
|
client := NewMockClient()
|
|
|
|
ok := hub.Unsubscribe(client, "nonexistent")
|
|
if ok {
|
|
t.Error("Unsubscribe() should return false for non-subscribed channel")
|
|
}
|
|
}
|
|
|
|
func TestHubUnsubscribeAll(t *testing.T) {
|
|
hub := NewHub()
|
|
client := NewMockClient()
|
|
|
|
hub.Subscribe(client, "news")
|
|
hub.Subscribe(client, "sports")
|
|
hub.Subscribe(client, "weather")
|
|
|
|
hub.UnsubscribeAll(client)
|
|
|
|
if hub.ChannelCount("news") != 0 {
|
|
t.Error("news channel should be empty")
|
|
}
|
|
if hub.ChannelCount("sports") != 0 {
|
|
t.Error("sports channel should be empty")
|
|
}
|
|
if hub.ChannelCount("weather") != 0 {
|
|
t.Error("weather channel should be empty")
|
|
}
|
|
}
|
|
|
|
func TestHubPublish(t *testing.T) {
|
|
hub := NewHub()
|
|
client1 := NewMockClient()
|
|
client2 := NewMockClient()
|
|
|
|
hub.Subscribe(client1, "news")
|
|
hub.Subscribe(client2, "news")
|
|
|
|
count := hub.Publish("news", []byte("Hello"))
|
|
if count != 2 {
|
|
t.Errorf("Publish() = %d, want 2", count)
|
|
}
|
|
}
|
|
|
|
func TestHubPublishEmptyChannel(t *testing.T) {
|
|
hub := NewHub()
|
|
|
|
count := hub.Publish("empty", []byte("Hello"))
|
|
if count != 0 {
|
|
t.Errorf("Publish() to empty channel = %d, want 0", count)
|
|
}
|
|
}
|
|
|
|
func TestHubChannelCount(t *testing.T) {
|
|
hub := NewHub()
|
|
client := NewMockClient()
|
|
|
|
if hub.ChannelCount("news") != 0 {
|
|
t.Error("new channel should have 0 subscribers")
|
|
}
|
|
|
|
hub.Subscribe(client, "news")
|
|
if hub.ChannelCount("news") != 1 {
|
|
t.Errorf("ChannelCount() = %d, want 1", hub.ChannelCount("news"))
|
|
}
|
|
|
|
hub.Subscribe(client, "news") // duplicate
|
|
if hub.ChannelCount("news") != 1 {
|
|
t.Errorf("ChannelCount() after duplicate = %d, want 1", hub.ChannelCount("news"))
|
|
}
|
|
}
|
|
|
|
func TestHubTotalChannels(t *testing.T) {
|
|
hub := NewHub()
|
|
client := NewMockClient()
|
|
|
|
if hub.TotalChannels() != 0 {
|
|
t.Errorf("TotalChannels() = %d, want 0", hub.TotalChannels())
|
|
}
|
|
|
|
hub.Subscribe(client, "news")
|
|
hub.Subscribe(client, "sports")
|
|
|
|
if hub.TotalChannels() != 2 {
|
|
t.Errorf("TotalChannels() = %d, want 2", hub.TotalChannels())
|
|
}
|
|
}
|
|
|
|
func TestHubChannelList(t *testing.T) {
|
|
hub := NewHub()
|
|
client := NewMockClient()
|
|
|
|
channels := hub.ChannelList("")
|
|
if len(channels) != 0 {
|
|
t.Errorf("Empty hub ChannelList() length = %d, want 0", len(channels))
|
|
}
|
|
|
|
hub.Subscribe(client, "news")
|
|
hub.Subscribe(client, "sports")
|
|
|
|
channels = hub.ChannelList("")
|
|
if len(channels) != 2 {
|
|
t.Errorf("ChannelList() length = %d, want 2", len(channels))
|
|
}
|
|
}
|
|
|
|
func TestHubMultipleClients(t *testing.T) {
|
|
hub := NewHub()
|
|
client1 := NewMockClient()
|
|
client2 := NewMockClient()
|
|
client3 := NewMockClient()
|
|
|
|
hub.Subscribe(client1, "news")
|
|
hub.Subscribe(client2, "news")
|
|
hub.Subscribe(client3, "news")
|
|
|
|
count := hub.ChannelCount("news")
|
|
if count != 3 {
|
|
t.Errorf("ChannelCount() = %d, want 3", count)
|
|
}
|
|
}
|
|
|
|
func TestHubChannelCleanup(t *testing.T) {
|
|
hub := NewHub()
|
|
client := NewMockClient()
|
|
|
|
hub.Subscribe(client, "temp")
|
|
if hub.ChannelCount("temp") != 1 {
|
|
t.Error("Channel should exist")
|
|
}
|
|
|
|
hub.Unsubscribe(client, "temp")
|
|
if hub.ChannelCount("temp") != 0 {
|
|
t.Error("Channel should be cleaned up")
|
|
}
|
|
|
|
channels := hub.ChannelList("")
|
|
for _, ch := range channels {
|
|
if ch == "temp" {
|
|
t.Error("Channel should not be in list after cleanup")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestNewClient(t *testing.T) {
|
|
conn := &mockConn{data: []byte{}}
|
|
client := NewClient(conn)
|
|
if client == nil {
|
|
t.Fatal("NewClient() returned nil")
|
|
}
|
|
if client.subscribed == nil {
|
|
t.Error("client.subscribed is nil")
|
|
}
|
|
}
|
|
|
|
func TestClientAddSubscription(t *testing.T) {
|
|
client := NewMockClient()
|
|
|
|
client.AddSubscription("news")
|
|
if client.SubsCount() != 1 {
|
|
t.Errorf("SubsCount() = %d, want 1", client.SubsCount())
|
|
}
|
|
|
|
client.AddSubscription("sports")
|
|
if client.SubsCount() != 2 {
|
|
t.Errorf("SubsCount() = %d, want 2", client.SubsCount())
|
|
}
|
|
}
|
|
|
|
func TestClientRemoveSubscription(t *testing.T) {
|
|
client := NewMockClient()
|
|
|
|
client.AddSubscription("news")
|
|
client.AddSubscription("sports")
|
|
client.RemoveSubscription("news")
|
|
|
|
if client.SubsCount() != 1 {
|
|
t.Errorf("SubsCount() = %d, want 1", client.SubsCount())
|
|
}
|
|
}
|
|
|
|
func TestClientGetChannels(t *testing.T) {
|
|
client := NewMockClient()
|
|
|
|
client.AddSubscription("news")
|
|
client.AddSubscription("sports")
|
|
|
|
channels := client.GetChannels()
|
|
if len(channels) != 2 {
|
|
t.Errorf("GetChannels() length = %d, want 2", len(channels))
|
|
}
|
|
|
|
found := make(map[string]bool)
|
|
for _, ch := range channels {
|
|
found[ch] = true
|
|
}
|
|
if !found["news"] || !found["sports"] {
|
|
t.Error("GetChannels() missing expected channels")
|
|
}
|
|
}
|
|
|
|
func TestClientGetChannelsReturnsCopy(t *testing.T) {
|
|
client := NewMockClient()
|
|
client.AddSubscription("news")
|
|
|
|
channels := client.GetChannels()
|
|
channels[0] = "modified"
|
|
|
|
channels2 := client.GetChannels()
|
|
if channels2[0] == "modified" {
|
|
t.Error("GetChannels() should return a copy, not modify original")
|
|
}
|
|
}
|
|
|
|
func TestClientSubsCount(t *testing.T) {
|
|
client := NewMockClient()
|
|
|
|
if client.SubsCount() != 0 {
|
|
t.Errorf("Initial SubsCount() = %d, want 0", client.SubsCount())
|
|
}
|
|
|
|
client.AddSubscription("news")
|
|
if client.SubsCount() != 1 {
|
|
t.Errorf("SubsCount() = %d, want 1", client.SubsCount())
|
|
}
|
|
}
|
|
|
|
func TestConcurrentSubscribe(t *testing.T) {
|
|
hub := NewHub()
|
|
client := NewMockClient()
|
|
|
|
done := make(chan bool)
|
|
go func() {
|
|
hub.Subscribe(client, "channel1")
|
|
done <- true
|
|
}()
|
|
|
|
hub.Subscribe(client, "channel2")
|
|
<-done
|
|
|
|
if hub.TotalChannels() != 2 {
|
|
t.Errorf("TotalChannels() = %d, want 2", hub.TotalChannels())
|
|
}
|
|
}
|