package aether import "testing" func TestMatchNamespacePattern(t *testing.T) { tests := []struct { name string pattern string namespace string expected bool }{ // Exact matches {"exact match", "tenant-a", "tenant-a", true}, {"exact mismatch", "tenant-a", "tenant-b", false}, {"exact match with dots", "prod.tenant.a", "prod.tenant.a", true}, {"exact mismatch with dots", "prod.tenant.a", "prod.tenant.b", false}, // Empty cases {"empty pattern", "", "tenant-a", false}, {"empty namespace exact", "tenant-a", "", false}, {"empty namespace catch-all", ">", "", false}, {"both empty", "", "", false}, // Single wildcard (*) - matches one token (NATS semantics: tokens are dot-separated) {"star matches any single token", "*", "tenant-a", true}, {"star matches any single token 2", "*", "anything", true}, {"star does not match multi-token", "*", "prod.tenant", false}, {"prefix with star", "prod.*", "prod.tenant", true}, {"prefix with star 2", "prod.*", "prod.orders", true}, {"prefix with star no match extra tokens", "prod.*", "prod.tenant.orders", false}, {"prefix with star no match wrong prefix", "prod.*", "staging.tenant", false}, {"middle wildcard", "prod.*.orders", "prod.tenant.orders", true}, {"middle wildcard no match", "prod.*.orders", "prod.tenant.events", false}, {"multiple stars", "*.tenant.*", "prod.tenant.orders", true}, {"multiple stars 2", "*.*.orders", "prod.tenant.orders", true}, {"multiple stars no match", "*.*.orders", "prod.orders", false}, // Multi-token wildcard (>) - matches one or more tokens {"greater matches one", ">", "tenant", true}, {"greater matches multi", ">", "prod.tenant.orders", true}, {"prefix greater", "prod.>", "prod.tenant", true}, {"prefix greater multi", "prod.>", "prod.tenant.orders.items", true}, {"prefix greater no match different prefix", "prod.>", "staging.tenant", false}, {"prefix greater requires at least one", "prod.>", "prod", false}, {"deep prefix greater", "prod.tenant.>", "prod.tenant.orders", true}, // Combined wildcards {"star then greater", "*.>", "prod.tenant", true}, {"star then greater multi", "*.>", "prod.tenant.orders", true}, {"star then greater no match single", "*.>", "prod", false}, // Edge cases {"trailing dot in pattern", "tenant.", "tenant.", true}, {"just dots", "..", "..", true}, {"star at end", "prod.tenant.*", "prod.tenant.a", true}, {"star at end no match", "prod.tenant.*", "prod.other.a", false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := MatchNamespacePattern(tt.pattern, tt.namespace) if result != tt.expected { t.Errorf("MatchNamespacePattern(%q, %q) = %v, want %v", tt.pattern, tt.namespace, result, tt.expected) } }) } } func TestIsWildcardPattern(t *testing.T) { tests := []struct { pattern string expected bool }{ {"tenant-a", false}, {"prod.tenant.orders", false}, {"*", true}, {"prod.*", true}, {"*.orders", true}, {">", true}, {"prod.>", true}, {"*.>", true}, {"prod.*.orders", true}, } for _, tt := range tests { t.Run(tt.pattern, func(t *testing.T) { result := IsWildcardPattern(tt.pattern) if result != tt.expected { t.Errorf("IsWildcardPattern(%q) = %v, want %v", tt.pattern, result, tt.expected) } }) } } func BenchmarkMatchNamespacePattern(b *testing.B) { benchmarks := []struct { name string pattern string namespace string }{ {"exact", "tenant-a", "tenant-a"}, {"star", "*", "tenant-a"}, {"prefix_star", "prod.*", "prod.tenant"}, {"greater", ">", "prod.tenant.orders"}, {"complex", "prod.*.>", "prod.tenant.orders.items"}, } for _, bm := range benchmarks { b.Run(bm.name, func(b *testing.B) { for i := 0; i < b.N; i++ { MatchNamespacePattern(bm.pattern, bm.namespace) } }) } } func TestMatchActorPattern(t *testing.T) { tests := []struct { name string pattern string actorID string expected bool }{ // Empty cases {"empty pattern", "", "actor-123", false}, {"empty actorID", "actor-*", "", false}, {"both empty", "", "", false}, // Exact matches (no dots) {"exact match", "actor-123", "actor-123", true}, {"exact mismatch", "actor-123", "actor-456", false}, // Suffix wildcard with * (simple, no dots) {"prefix with star", "order-*", "order-123", true}, {"prefix with star 2", "order-*", "order-456-xyz", true}, {"prefix with star mismatch", "order-*", "user-123", false}, {"star alone", "*", "anything", true}, // Suffix wildcard with > (simple, no dots) {"prefix with greater", "order->", "order-123", true}, {"greater alone", ">", "anything", true}, // Dot-separated actor IDs (uses MatchNamespacePattern) {"dotted exact match", "order.us.123", "order.us.123", true}, {"dotted exact mismatch", "order.us.123", "order.eu.123", false}, {"dotted star", "order.*", "order.123", true}, {"dotted star deep", "order.*.*", "order.us.123", true}, {"dotted greater", "order.>", "order.us.123.456", true}, {"dotted star mismatch depth", "order.*", "order.us.123", false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := MatchActorPattern(tt.pattern, tt.actorID) if result != tt.expected { t.Errorf("MatchActorPattern(%q, %q) = %v, want %v", tt.pattern, tt.actorID, result, tt.expected) } }) } } func TestSubscriptionFilter_IsEmpty(t *testing.T) { tests := []struct { name string filter *SubscriptionFilter expected bool }{ {"nil fields", &SubscriptionFilter{}, true}, {"empty slice", &SubscriptionFilter{EventTypes: []string{}}, true}, {"has event types", &SubscriptionFilter{EventTypes: []string{"OrderPlaced"}}, false}, {"has actor pattern", &SubscriptionFilter{ActorPattern: "order-*"}, false}, {"has both", &SubscriptionFilter{EventTypes: []string{"OrderPlaced"}, ActorPattern: "order-*"}, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := tt.filter.IsEmpty() if result != tt.expected { t.Errorf("SubscriptionFilter.IsEmpty() = %v, want %v", result, tt.expected) } }) } } func TestSubscriptionFilter_Matches(t *testing.T) { tests := []struct { name string filter *SubscriptionFilter event *Event expected bool }{ // Nil event {"nil event", &SubscriptionFilter{}, nil, false}, // Empty filter matches all {"empty filter", &SubscriptionFilter{}, &Event{EventType: "Test", ActorID: "actor-1"}, true}, // Event type filtering {"event type match", &SubscriptionFilter{EventTypes: []string{"OrderPlaced"}}, &Event{EventType: "OrderPlaced", ActorID: "order-1"}, true}, {"event type mismatch", &SubscriptionFilter{EventTypes: []string{"OrderPlaced"}}, &Event{EventType: "OrderShipped", ActorID: "order-1"}, false}, {"event type multiple match first", &SubscriptionFilter{EventTypes: []string{"OrderPlaced", "OrderShipped"}}, &Event{EventType: "OrderPlaced", ActorID: "order-1"}, true}, {"event type multiple match second", &SubscriptionFilter{EventTypes: []string{"OrderPlaced", "OrderShipped"}}, &Event{EventType: "OrderShipped", ActorID: "order-1"}, true}, {"event type multiple no match", &SubscriptionFilter{EventTypes: []string{"OrderPlaced", "OrderShipped"}}, &Event{EventType: "OrderCancelled", ActorID: "order-1"}, false}, // Actor pattern filtering {"actor pattern exact match", &SubscriptionFilter{ActorPattern: "order-123"}, &Event{EventType: "Test", ActorID: "order-123"}, true}, {"actor pattern exact mismatch", &SubscriptionFilter{ActorPattern: "order-123"}, &Event{EventType: "Test", ActorID: "order-456"}, false}, {"actor pattern wildcard match", &SubscriptionFilter{ActorPattern: "order-*"}, &Event{EventType: "Test", ActorID: "order-123"}, true}, {"actor pattern wildcard mismatch", &SubscriptionFilter{ActorPattern: "order-*"}, &Event{EventType: "Test", ActorID: "user-123"}, false}, // Combined filters (AND logic) {"combined both match", &SubscriptionFilter{EventTypes: []string{"OrderPlaced"}, ActorPattern: "order-*"}, &Event{EventType: "OrderPlaced", ActorID: "order-123"}, true}, {"combined event matches actor does not", &SubscriptionFilter{EventTypes: []string{"OrderPlaced"}, ActorPattern: "order-*"}, &Event{EventType: "OrderPlaced", ActorID: "user-123"}, false}, {"combined actor matches event does not", &SubscriptionFilter{EventTypes: []string{"OrderPlaced"}, ActorPattern: "order-*"}, &Event{EventType: "OrderShipped", ActorID: "order-123"}, false}, {"combined neither matches", &SubscriptionFilter{EventTypes: []string{"OrderPlaced"}, ActorPattern: "order-*"}, &Event{EventType: "OrderShipped", ActorID: "user-123"}, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := tt.filter.Matches(tt.event) if result != tt.expected { t.Errorf("SubscriptionFilter.Matches() = %v, want %v", result, tt.expected) } }) } }