96 lines
2.8 KiB
Go
96 lines
2.8 KiB
Go
package routing_test
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"go.uber.org/zap"
|
|
|
|
"github.com/veylant/ia-gateway/internal/routing"
|
|
)
|
|
|
|
func makeRule(name, tenantID string, priority int) routing.RoutingRule {
|
|
return routing.RoutingRule{
|
|
Name: name,
|
|
TenantID: tenantID,
|
|
Priority: priority,
|
|
IsEnabled: true,
|
|
Conditions: []routing.Condition{},
|
|
Action: routing.Action{Provider: "openai"},
|
|
}
|
|
}
|
|
|
|
func TestRuleCache_Get_LoadsFromStore(t *testing.T) {
|
|
store := routing.NewMemStore()
|
|
_, err := store.Create(context.Background(), makeRule("r1", "t1", 100))
|
|
require.NoError(t, err)
|
|
|
|
cache := routing.NewRuleCache(store, 30*time.Second, zap.NewNop())
|
|
rules, err := cache.Get(context.Background(), "t1")
|
|
require.NoError(t, err)
|
|
assert.Len(t, rules, 1)
|
|
assert.Equal(t, "r1", rules[0].Name)
|
|
}
|
|
|
|
func TestRuleCache_Get_ReturnsCachedOnSecondCall(t *testing.T) {
|
|
store := routing.NewMemStore()
|
|
_, err := store.Create(context.Background(), makeRule("r1", "t1", 100))
|
|
require.NoError(t, err)
|
|
|
|
cache := routing.NewRuleCache(store, 30*time.Second, zap.NewNop())
|
|
// First call loads from store
|
|
rules1, err := cache.Get(context.Background(), "t1")
|
|
require.NoError(t, err)
|
|
|
|
// Add another rule to the store — should NOT appear before cache expiry
|
|
_, err = store.Create(context.Background(), makeRule("r2", "t1", 200))
|
|
require.NoError(t, err)
|
|
|
|
rules2, err := cache.Get(context.Background(), "t1")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, len(rules1), len(rules2), "cache should serve stale data within TTL")
|
|
}
|
|
|
|
func TestRuleCache_Invalidate_ForcesReload(t *testing.T) {
|
|
store := routing.NewMemStore()
|
|
_, err := store.Create(context.Background(), makeRule("r1", "t1", 100))
|
|
require.NoError(t, err)
|
|
|
|
cache := routing.NewRuleCache(store, 30*time.Second, zap.NewNop())
|
|
_, err = cache.Get(context.Background(), "t1")
|
|
require.NoError(t, err)
|
|
|
|
// Add a new rule and invalidate
|
|
_, err = store.Create(context.Background(), makeRule("r2", "t1", 200))
|
|
require.NoError(t, err)
|
|
cache.Invalidate("t1")
|
|
|
|
rules, err := cache.Get(context.Background(), "t1")
|
|
require.NoError(t, err)
|
|
assert.Len(t, rules, 2, "after invalidation, new rule should be visible")
|
|
}
|
|
|
|
func TestRuleCache_EmptyTenant_ReturnsEmpty(t *testing.T) {
|
|
store := routing.NewMemStore()
|
|
cache := routing.NewRuleCache(store, 30*time.Second, zap.NewNop())
|
|
|
|
rules, err := cache.Get(context.Background(), "unknown-tenant")
|
|
require.NoError(t, err)
|
|
assert.Empty(t, rules)
|
|
}
|
|
|
|
func TestRuleCache_StartStop_NoRace(t *testing.T) {
|
|
store := routing.NewMemStore()
|
|
cache := routing.NewRuleCache(store, 10*time.Millisecond, zap.NewNop())
|
|
cache.Start()
|
|
// Perform some gets while refresh loop runs
|
|
for i := 0; i < 5; i++ {
|
|
_, _ = cache.Get(context.Background(), "t1")
|
|
time.Sleep(5 * time.Millisecond)
|
|
}
|
|
cache.Stop()
|
|
}
|