mirror of
https://github.com/bitechdev/ResolveSpec.git
synced 2026-01-07 04:14:26 +00:00
feature: mqtt support
This commit is contained in:
256
pkg/mqttspec/client_test.go
Normal file
256
pkg/mqttspec/client_test.go
Normal file
@@ -0,0 +1,256 @@
|
||||
package mqttspec
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNewClient(t *testing.T) {
|
||||
client := NewClient("client-123", "user@example.com", nil)
|
||||
|
||||
assert.Equal(t, "client-123", client.ID)
|
||||
assert.Equal(t, "user@example.com", client.Username)
|
||||
assert.NotNil(t, client.subscriptions)
|
||||
assert.NotNil(t, client.metadata)
|
||||
assert.NotNil(t, client.ctx)
|
||||
assert.NotNil(t, client.cancel)
|
||||
}
|
||||
|
||||
func TestClient_Metadata(t *testing.T) {
|
||||
client := NewClient("client-123", "user", nil)
|
||||
|
||||
// Set metadata
|
||||
client.SetMetadata("user_id", 456)
|
||||
client.SetMetadata("tenant_id", "tenant-abc")
|
||||
client.SetMetadata("roles", []string{"admin", "user"})
|
||||
|
||||
// Get metadata
|
||||
userID, exists := client.GetMetadata("user_id")
|
||||
assert.True(t, exists)
|
||||
assert.Equal(t, 456, userID)
|
||||
|
||||
tenantID, exists := client.GetMetadata("tenant_id")
|
||||
assert.True(t, exists)
|
||||
assert.Equal(t, "tenant-abc", tenantID)
|
||||
|
||||
roles, exists := client.GetMetadata("roles")
|
||||
assert.True(t, exists)
|
||||
assert.Equal(t, []string{"admin", "user"}, roles)
|
||||
|
||||
// Non-existent key
|
||||
_, exists = client.GetMetadata("nonexistent")
|
||||
assert.False(t, exists)
|
||||
}
|
||||
|
||||
func TestClient_Subscriptions(t *testing.T) {
|
||||
client := NewClient("client-123", "user", nil)
|
||||
|
||||
// Create mock subscription
|
||||
sub := &Subscription{
|
||||
ID: "sub-1",
|
||||
ConnectionID: "client-123",
|
||||
Schema: "public",
|
||||
Entity: "users",
|
||||
Active: true,
|
||||
}
|
||||
|
||||
// Add subscription
|
||||
client.AddSubscription(sub)
|
||||
|
||||
// Get subscription
|
||||
retrieved, exists := client.GetSubscription("sub-1")
|
||||
assert.True(t, exists)
|
||||
assert.Equal(t, "sub-1", retrieved.ID)
|
||||
|
||||
// Remove subscription
|
||||
client.RemoveSubscription("sub-1")
|
||||
|
||||
// Verify removed
|
||||
_, exists = client.GetSubscription("sub-1")
|
||||
assert.False(t, exists)
|
||||
}
|
||||
|
||||
func TestClient_Close(t *testing.T) {
|
||||
client := NewClient("client-123", "user", nil)
|
||||
|
||||
// Add some subscriptions
|
||||
client.AddSubscription(&Subscription{ID: "sub-1"})
|
||||
client.AddSubscription(&Subscription{ID: "sub-2"})
|
||||
|
||||
// Close client
|
||||
client.Close()
|
||||
|
||||
// Verify subscriptions cleared
|
||||
client.subMu.RLock()
|
||||
assert.Empty(t, client.subscriptions)
|
||||
client.subMu.RUnlock()
|
||||
|
||||
// Verify context cancelled
|
||||
select {
|
||||
case <-client.ctx.Done():
|
||||
// Context was cancelled
|
||||
default:
|
||||
t.Fatal("Context should be cancelled after Close()")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewClientManager(t *testing.T) {
|
||||
cm := NewClientManager(context.Background())
|
||||
|
||||
assert.NotNil(t, cm)
|
||||
assert.NotNil(t, cm.clients)
|
||||
assert.Equal(t, 0, cm.Count())
|
||||
}
|
||||
|
||||
func TestClientManager_Register(t *testing.T) {
|
||||
cm := NewClientManager(context.Background())
|
||||
defer cm.Shutdown()
|
||||
|
||||
client := cm.Register("client-1", "user@example.com", nil)
|
||||
|
||||
assert.NotNil(t, client)
|
||||
assert.Equal(t, "client-1", client.ID)
|
||||
assert.Equal(t, "user@example.com", client.Username)
|
||||
assert.Equal(t, 1, cm.Count())
|
||||
}
|
||||
|
||||
func TestClientManager_Unregister(t *testing.T) {
|
||||
cm := NewClientManager(context.Background())
|
||||
defer cm.Shutdown()
|
||||
|
||||
cm.Register("client-1", "user1", nil)
|
||||
assert.Equal(t, 1, cm.Count())
|
||||
|
||||
cm.Unregister("client-1")
|
||||
assert.Equal(t, 0, cm.Count())
|
||||
}
|
||||
|
||||
func TestClientManager_GetClient(t *testing.T) {
|
||||
cm := NewClientManager(context.Background())
|
||||
defer cm.Shutdown()
|
||||
|
||||
cm.Register("client-1", "user1", nil)
|
||||
|
||||
// Get existing client
|
||||
client, exists := cm.GetClient("client-1")
|
||||
assert.True(t, exists)
|
||||
assert.NotNil(t, client)
|
||||
assert.Equal(t, "client-1", client.ID)
|
||||
|
||||
// Get non-existent client
|
||||
_, exists = cm.GetClient("nonexistent")
|
||||
assert.False(t, exists)
|
||||
}
|
||||
|
||||
func TestClientManager_MultipleClients(t *testing.T) {
|
||||
cm := NewClientManager(context.Background())
|
||||
defer cm.Shutdown()
|
||||
|
||||
cm.Register("client-1", "user1", nil)
|
||||
cm.Register("client-2", "user2", nil)
|
||||
cm.Register("client-3", "user3", nil)
|
||||
|
||||
assert.Equal(t, 3, cm.Count())
|
||||
|
||||
cm.Unregister("client-2")
|
||||
assert.Equal(t, 2, cm.Count())
|
||||
|
||||
// Verify correct client was removed
|
||||
_, exists := cm.GetClient("client-2")
|
||||
assert.False(t, exists)
|
||||
|
||||
_, exists = cm.GetClient("client-1")
|
||||
assert.True(t, exists)
|
||||
|
||||
_, exists = cm.GetClient("client-3")
|
||||
assert.True(t, exists)
|
||||
}
|
||||
|
||||
func TestClientManager_Shutdown(t *testing.T) {
|
||||
cm := NewClientManager(context.Background())
|
||||
|
||||
cm.Register("client-1", "user1", nil)
|
||||
cm.Register("client-2", "user2", nil)
|
||||
assert.Equal(t, 2, cm.Count())
|
||||
|
||||
cm.Shutdown()
|
||||
|
||||
// All clients should be removed
|
||||
assert.Equal(t, 0, cm.Count())
|
||||
|
||||
// Context should be cancelled
|
||||
select {
|
||||
case <-cm.ctx.Done():
|
||||
// Context was cancelled
|
||||
default:
|
||||
t.Fatal("Context should be cancelled after Shutdown()")
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientManager_ConcurrentOperations(t *testing.T) {
|
||||
cm := NewClientManager(context.Background())
|
||||
defer cm.Shutdown()
|
||||
|
||||
// This test verifies that concurrent operations don't cause race conditions
|
||||
// Run with: go test -race
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
// Goroutine 1: Register clients
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for i := 0; i < 100; i++ {
|
||||
cm.Register("client-"+string(rune(i)), "user", nil)
|
||||
}
|
||||
}()
|
||||
|
||||
// Goroutine 2: Get clients
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for i := 0; i < 100; i++ {
|
||||
cm.GetClient("client-" + string(rune(i)))
|
||||
}
|
||||
}()
|
||||
|
||||
// Goroutine 3: Count
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for i := 0; i < 100; i++ {
|
||||
cm.Count()
|
||||
}
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func TestClient_ConcurrentMetadata(t *testing.T) {
|
||||
client := NewClient("client-123", "user", nil)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
// Concurrent writes
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for i := 0; i < 100; i++ {
|
||||
client.SetMetadata("key1", i)
|
||||
}
|
||||
}()
|
||||
|
||||
// Concurrent reads
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for i := 0; i < 100; i++ {
|
||||
client.GetMetadata("key1")
|
||||
}
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
}
|
||||
Reference in New Issue
Block a user