mirror of
https://github.com/bitechdev/ResolveSpec.git
synced 2026-01-10 05:04:25 +00:00
Updated to websockspec
This commit is contained in:
434
pkg/websocketspec/subscription_test.go
Normal file
434
pkg/websocketspec/subscription_test.go
Normal file
@@ -0,0 +1,434 @@
|
||||
package websocketspec
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/bitechdev/ResolveSpec/pkg/common"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestNewSubscriptionManager(t *testing.T) {
|
||||
sm := NewSubscriptionManager()
|
||||
assert.NotNil(t, sm)
|
||||
assert.NotNil(t, sm.subscriptions)
|
||||
assert.NotNil(t, sm.entitySubscriptions)
|
||||
assert.Equal(t, 0, sm.Count())
|
||||
}
|
||||
|
||||
func TestSubscriptionManager_Subscribe(t *testing.T) {
|
||||
sm := NewSubscriptionManager()
|
||||
|
||||
// Create a subscription
|
||||
sub := sm.Subscribe("sub-1", "conn-1", "public", "users", nil)
|
||||
|
||||
assert.NotNil(t, sub)
|
||||
assert.Equal(t, "sub-1", sub.ID)
|
||||
assert.Equal(t, "conn-1", sub.ConnectionID)
|
||||
assert.Equal(t, "public", sub.Schema)
|
||||
assert.Equal(t, "users", sub.Entity)
|
||||
assert.True(t, sub.Active)
|
||||
assert.Equal(t, 1, sm.Count())
|
||||
}
|
||||
|
||||
func TestSubscriptionManager_Subscribe_WithOptions(t *testing.T) {
|
||||
sm := NewSubscriptionManager()
|
||||
|
||||
options := &common.RequestOptions{
|
||||
Filters: []common.FilterOption{
|
||||
{Column: "status", Operator: "eq", Value: "active"},
|
||||
},
|
||||
}
|
||||
|
||||
sub := sm.Subscribe("sub-1", "conn-1", "public", "users", options)
|
||||
|
||||
assert.NotNil(t, sub)
|
||||
assert.NotNil(t, sub.Options)
|
||||
assert.Len(t, sub.Options.Filters, 1)
|
||||
assert.Equal(t, "status", sub.Options.Filters[0].Column)
|
||||
}
|
||||
|
||||
func TestSubscriptionManager_Subscribe_MultipleSubscriptions(t *testing.T) {
|
||||
sm := NewSubscriptionManager()
|
||||
|
||||
sub1 := sm.Subscribe("sub-1", "conn-1", "public", "users", nil)
|
||||
sub2 := sm.Subscribe("sub-2", "conn-1", "public", "posts", nil)
|
||||
sub3 := sm.Subscribe("sub-3", "conn-2", "public", "users", nil)
|
||||
|
||||
assert.NotNil(t, sub1)
|
||||
assert.NotNil(t, sub2)
|
||||
assert.NotNil(t, sub3)
|
||||
assert.Equal(t, 3, sm.Count())
|
||||
}
|
||||
|
||||
func TestSubscriptionManager_Unsubscribe(t *testing.T) {
|
||||
sm := NewSubscriptionManager()
|
||||
|
||||
sm.Subscribe("sub-1", "conn-1", "public", "users", nil)
|
||||
assert.Equal(t, 1, sm.Count())
|
||||
|
||||
// Unsubscribe
|
||||
ok := sm.Unsubscribe("sub-1")
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, 0, sm.Count())
|
||||
}
|
||||
|
||||
func TestSubscriptionManager_Unsubscribe_NonExistent(t *testing.T) {
|
||||
sm := NewSubscriptionManager()
|
||||
|
||||
ok := sm.Unsubscribe("non-existent")
|
||||
assert.False(t, ok)
|
||||
}
|
||||
|
||||
func TestSubscriptionManager_Unsubscribe_MultipleSubscriptions(t *testing.T) {
|
||||
sm := NewSubscriptionManager()
|
||||
|
||||
sm.Subscribe("sub-1", "conn-1", "public", "users", nil)
|
||||
sm.Subscribe("sub-2", "conn-1", "public", "posts", nil)
|
||||
sm.Subscribe("sub-3", "conn-2", "public", "users", nil)
|
||||
assert.Equal(t, 3, sm.Count())
|
||||
|
||||
// Unsubscribe one
|
||||
ok := sm.Unsubscribe("sub-2")
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, 2, sm.Count())
|
||||
|
||||
// Verify the right subscription was removed
|
||||
_, exists := sm.GetSubscription("sub-2")
|
||||
assert.False(t, exists)
|
||||
|
||||
_, exists = sm.GetSubscription("sub-1")
|
||||
assert.True(t, exists)
|
||||
|
||||
_, exists = sm.GetSubscription("sub-3")
|
||||
assert.True(t, exists)
|
||||
}
|
||||
|
||||
func TestSubscriptionManager_GetSubscription(t *testing.T) {
|
||||
sm := NewSubscriptionManager()
|
||||
|
||||
sm.Subscribe("sub-1", "conn-1", "public", "users", nil)
|
||||
|
||||
// Get existing subscription
|
||||
sub, exists := sm.GetSubscription("sub-1")
|
||||
assert.True(t, exists)
|
||||
assert.NotNil(t, sub)
|
||||
assert.Equal(t, "sub-1", sub.ID)
|
||||
}
|
||||
|
||||
func TestSubscriptionManager_GetSubscription_NonExistent(t *testing.T) {
|
||||
sm := NewSubscriptionManager()
|
||||
|
||||
sub, exists := sm.GetSubscription("non-existent")
|
||||
assert.False(t, exists)
|
||||
assert.Nil(t, sub)
|
||||
}
|
||||
|
||||
func TestSubscriptionManager_GetSubscriptionsByEntity(t *testing.T) {
|
||||
sm := NewSubscriptionManager()
|
||||
|
||||
sm.Subscribe("sub-1", "conn-1", "public", "users", nil)
|
||||
sm.Subscribe("sub-2", "conn-2", "public", "users", nil)
|
||||
sm.Subscribe("sub-3", "conn-1", "public", "posts", nil)
|
||||
|
||||
// Get subscriptions for users entity
|
||||
subs := sm.GetSubscriptionsByEntity("public", "users")
|
||||
assert.Len(t, subs, 2)
|
||||
|
||||
// Verify subscription IDs
|
||||
ids := make([]string, len(subs))
|
||||
for i, sub := range subs {
|
||||
ids[i] = sub.ID
|
||||
}
|
||||
assert.Contains(t, ids, "sub-1")
|
||||
assert.Contains(t, ids, "sub-2")
|
||||
}
|
||||
|
||||
func TestSubscriptionManager_GetSubscriptionsByEntity_NoSchema(t *testing.T) {
|
||||
sm := NewSubscriptionManager()
|
||||
|
||||
sm.Subscribe("sub-1", "conn-1", "", "users", nil)
|
||||
sm.Subscribe("sub-2", "conn-2", "", "users", nil)
|
||||
|
||||
// Get subscriptions without schema
|
||||
subs := sm.GetSubscriptionsByEntity("", "users")
|
||||
assert.Len(t, subs, 2)
|
||||
}
|
||||
|
||||
func TestSubscriptionManager_GetSubscriptionsByEntity_NoResults(t *testing.T) {
|
||||
sm := NewSubscriptionManager()
|
||||
|
||||
sm.Subscribe("sub-1", "conn-1", "public", "users", nil)
|
||||
|
||||
// Get subscriptions for non-existent entity
|
||||
subs := sm.GetSubscriptionsByEntity("public", "posts")
|
||||
assert.Nil(t, subs)
|
||||
}
|
||||
|
||||
func TestSubscriptionManager_GetSubscriptionsByConnection(t *testing.T) {
|
||||
sm := NewSubscriptionManager()
|
||||
|
||||
sm.Subscribe("sub-1", "conn-1", "public", "users", nil)
|
||||
sm.Subscribe("sub-2", "conn-1", "public", "posts", nil)
|
||||
sm.Subscribe("sub-3", "conn-2", "public", "users", nil)
|
||||
|
||||
// Get subscriptions for connection 1
|
||||
subs := sm.GetSubscriptionsByConnection("conn-1")
|
||||
assert.Len(t, subs, 2)
|
||||
|
||||
// Verify subscription IDs
|
||||
ids := make([]string, len(subs))
|
||||
for i, sub := range subs {
|
||||
ids[i] = sub.ID
|
||||
}
|
||||
assert.Contains(t, ids, "sub-1")
|
||||
assert.Contains(t, ids, "sub-2")
|
||||
}
|
||||
|
||||
func TestSubscriptionManager_GetSubscriptionsByConnection_NoResults(t *testing.T) {
|
||||
sm := NewSubscriptionManager()
|
||||
|
||||
sm.Subscribe("sub-1", "conn-1", "public", "users", nil)
|
||||
|
||||
// Get subscriptions for non-existent connection
|
||||
subs := sm.GetSubscriptionsByConnection("conn-2")
|
||||
assert.Empty(t, subs)
|
||||
}
|
||||
|
||||
func TestSubscriptionManager_Count(t *testing.T) {
|
||||
sm := NewSubscriptionManager()
|
||||
|
||||
assert.Equal(t, 0, sm.Count())
|
||||
|
||||
sm.Subscribe("sub-1", "conn-1", "public", "users", nil)
|
||||
assert.Equal(t, 1, sm.Count())
|
||||
|
||||
sm.Subscribe("sub-2", "conn-1", "public", "posts", nil)
|
||||
assert.Equal(t, 2, sm.Count())
|
||||
|
||||
sm.Unsubscribe("sub-1")
|
||||
assert.Equal(t, 1, sm.Count())
|
||||
|
||||
sm.Unsubscribe("sub-2")
|
||||
assert.Equal(t, 0, sm.Count())
|
||||
}
|
||||
|
||||
func TestSubscriptionManager_CountForEntity(t *testing.T) {
|
||||
sm := NewSubscriptionManager()
|
||||
|
||||
sm.Subscribe("sub-1", "conn-1", "public", "users", nil)
|
||||
sm.Subscribe("sub-2", "conn-2", "public", "users", nil)
|
||||
sm.Subscribe("sub-3", "conn-1", "public", "posts", nil)
|
||||
|
||||
assert.Equal(t, 2, sm.CountForEntity("public", "users"))
|
||||
assert.Equal(t, 1, sm.CountForEntity("public", "posts"))
|
||||
assert.Equal(t, 0, sm.CountForEntity("public", "orders"))
|
||||
}
|
||||
|
||||
func TestSubscriptionManager_UnsubscribeUpdatesEntityIndex(t *testing.T) {
|
||||
sm := NewSubscriptionManager()
|
||||
|
||||
sm.Subscribe("sub-1", "conn-1", "public", "users", nil)
|
||||
sm.Subscribe("sub-2", "conn-2", "public", "users", nil)
|
||||
assert.Equal(t, 2, sm.CountForEntity("public", "users"))
|
||||
|
||||
// Unsubscribe one
|
||||
sm.Unsubscribe("sub-1")
|
||||
assert.Equal(t, 1, sm.CountForEntity("public", "users"))
|
||||
|
||||
// Unsubscribe the other
|
||||
sm.Unsubscribe("sub-2")
|
||||
assert.Equal(t, 0, sm.CountForEntity("public", "users"))
|
||||
}
|
||||
|
||||
func TestSubscription_MatchesFilters_NoFilters(t *testing.T) {
|
||||
sub := &Subscription{
|
||||
ID: "sub-1",
|
||||
ConnectionID: "conn-1",
|
||||
Schema: "public",
|
||||
Entity: "users",
|
||||
Options: nil,
|
||||
Active: true,
|
||||
}
|
||||
|
||||
data := map[string]interface{}{
|
||||
"id": 1,
|
||||
"name": "John",
|
||||
"status": "active",
|
||||
}
|
||||
|
||||
// Should match when no filters are specified
|
||||
assert.True(t, sub.MatchesFilters(data))
|
||||
}
|
||||
|
||||
func TestSubscription_MatchesFilters_WithFilters(t *testing.T) {
|
||||
sub := &Subscription{
|
||||
ID: "sub-1",
|
||||
ConnectionID: "conn-1",
|
||||
Schema: "public",
|
||||
Entity: "users",
|
||||
Options: &common.RequestOptions{
|
||||
Filters: []common.FilterOption{
|
||||
{Column: "status", Operator: "eq", Value: "active"},
|
||||
},
|
||||
},
|
||||
Active: true,
|
||||
}
|
||||
|
||||
data := map[string]interface{}{
|
||||
"id": 1,
|
||||
"name": "John",
|
||||
"status": "active",
|
||||
}
|
||||
|
||||
// Current implementation returns true for all data
|
||||
// This test documents the expected behavior
|
||||
assert.True(t, sub.MatchesFilters(data))
|
||||
}
|
||||
|
||||
func TestSubscription_MatchesFilters_EmptyFiltersArray(t *testing.T) {
|
||||
sub := &Subscription{
|
||||
ID: "sub-1",
|
||||
ConnectionID: "conn-1",
|
||||
Schema: "public",
|
||||
Entity: "users",
|
||||
Options: &common.RequestOptions{
|
||||
Filters: []common.FilterOption{},
|
||||
},
|
||||
Active: true,
|
||||
}
|
||||
|
||||
data := map[string]interface{}{
|
||||
"id": 1,
|
||||
"name": "John",
|
||||
}
|
||||
|
||||
// Should match when filters array is empty
|
||||
assert.True(t, sub.MatchesFilters(data))
|
||||
}
|
||||
|
||||
func TestMakeEntityKey(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
schema string
|
||||
entity string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "With schema",
|
||||
schema: "public",
|
||||
entity: "users",
|
||||
expected: "public.users",
|
||||
},
|
||||
{
|
||||
name: "Without schema",
|
||||
schema: "",
|
||||
entity: "users",
|
||||
expected: "users",
|
||||
},
|
||||
{
|
||||
name: "Different schema",
|
||||
schema: "custom",
|
||||
entity: "posts",
|
||||
expected: "custom.posts",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := makeEntityKey(tt.schema, tt.entity)
|
||||
assert.Equal(t, tt.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSubscriptionManager_ConcurrentOperations(t *testing.T) {
|
||||
sm := NewSubscriptionManager()
|
||||
|
||||
// This test verifies that concurrent operations don't cause race conditions
|
||||
// Run with: go test -race
|
||||
|
||||
done := make(chan bool)
|
||||
|
||||
// Goroutine 1: Subscribe
|
||||
go func() {
|
||||
for i := 0; i < 100; i++ {
|
||||
sm.Subscribe("sub-"+string(rune(i)), "conn-1", "public", "users", nil)
|
||||
}
|
||||
done <- true
|
||||
}()
|
||||
|
||||
// Goroutine 2: Get subscriptions
|
||||
go func() {
|
||||
for i := 0; i < 100; i++ {
|
||||
sm.GetSubscriptionsByEntity("public", "users")
|
||||
}
|
||||
done <- true
|
||||
}()
|
||||
|
||||
// Goroutine 3: Count
|
||||
go func() {
|
||||
for i := 0; i < 100; i++ {
|
||||
sm.Count()
|
||||
}
|
||||
done <- true
|
||||
}()
|
||||
|
||||
// Wait for all goroutines
|
||||
<-done
|
||||
<-done
|
||||
<-done
|
||||
}
|
||||
|
||||
func TestSubscriptionManager_CompleteLifecycle(t *testing.T) {
|
||||
sm := NewSubscriptionManager()
|
||||
|
||||
// Create subscriptions
|
||||
options := &common.RequestOptions{
|
||||
Filters: []common.FilterOption{
|
||||
{Column: "status", Operator: "eq", Value: "active"},
|
||||
},
|
||||
}
|
||||
|
||||
sub1 := sm.Subscribe("sub-1", "conn-1", "public", "users", options)
|
||||
require.NotNil(t, sub1)
|
||||
assert.Equal(t, 1, sm.Count())
|
||||
|
||||
sub2 := sm.Subscribe("sub-2", "conn-1", "public", "posts", nil)
|
||||
require.NotNil(t, sub2)
|
||||
assert.Equal(t, 2, sm.Count())
|
||||
|
||||
// Get by entity
|
||||
userSubs := sm.GetSubscriptionsByEntity("public", "users")
|
||||
assert.Len(t, userSubs, 1)
|
||||
assert.Equal(t, "sub-1", userSubs[0].ID)
|
||||
|
||||
// Get by connection
|
||||
connSubs := sm.GetSubscriptionsByConnection("conn-1")
|
||||
assert.Len(t, connSubs, 2)
|
||||
|
||||
// Get specific subscription
|
||||
sub, exists := sm.GetSubscription("sub-1")
|
||||
assert.True(t, exists)
|
||||
assert.Equal(t, "sub-1", sub.ID)
|
||||
assert.NotNil(t, sub.Options)
|
||||
|
||||
// Count by entity
|
||||
assert.Equal(t, 1, sm.CountForEntity("public", "users"))
|
||||
assert.Equal(t, 1, sm.CountForEntity("public", "posts"))
|
||||
|
||||
// Unsubscribe
|
||||
ok := sm.Unsubscribe("sub-1")
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, 1, sm.Count())
|
||||
assert.Equal(t, 0, sm.CountForEntity("public", "users"))
|
||||
|
||||
// Verify subscription is gone
|
||||
_, exists = sm.GetSubscription("sub-1")
|
||||
assert.False(t, exists)
|
||||
|
||||
// Unsubscribe second subscription
|
||||
ok = sm.Unsubscribe("sub-2")
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, 0, sm.Count())
|
||||
}
|
||||
Reference in New Issue
Block a user