| package semanticcache |
|
|
| import ( |
| "testing" |
|
|
| "github.com/maximhq/bifrost/core/schemas" |
| ) |
|
|
| |
| func TestCrossCacheTypeAccessibility(t *testing.T) { |
| setup := NewTestSetup(t) |
| defer setup.Cleanup() |
|
|
| testRequest := CreateBasicChatRequest("What is artificial intelligence?", 0.7, 100) |
|
|
| |
| ctx1 := CreateContextWithCacheKey("test-cross-cache-access") |
| t.Log("Caching with default behavior (both direct + semantic)...") |
| response1, err1 := setup.Client.ChatCompletionRequest(ctx1, testRequest) |
| if err1 != nil { |
| return |
| } |
| AssertNoCacheHit(t, &schemas.BifrostResponse{ChatResponse: response1}) |
|
|
| WaitForCache(setup.Plugin) |
|
|
| |
| ctx2 := CreateContextWithCacheKeyAndType("test-cross-cache-access", CacheTypeDirect) |
| t.Log("Retrieving with CacheTypeKey=direct...") |
| response2, err2 := setup.Client.ChatCompletionRequest(ctx2, testRequest) |
| if err2 != nil { |
| if err2.Error != nil { |
| t.Fatalf("Second request failed: %v", err2.Error.Message) |
| } else { |
| t.Fatalf("Second request failed: %v", err2) |
| } |
| } |
| AssertCacheHit(t, &schemas.BifrostResponse{ChatResponse: response2}, "direct") |
|
|
| |
| ctx3 := CreateContextWithCacheKeyAndType("test-cross-cache-access", CacheTypeSemantic) |
| t.Log("Retrieving with CacheTypeKey=semantic...") |
| response3, err3 := setup.Client.ChatCompletionRequest(ctx3, testRequest) |
| if err3 != nil { |
| t.Fatalf("Third request failed: %v", err3) |
| } |
| AssertCacheHit(t, &schemas.BifrostResponse{ChatResponse: response3}, "semantic") |
|
|
| t.Log("✅ Entries cached with default behavior are accessible via both cache types") |
| } |
|
|
| |
| func TestCacheTypeIsolation(t *testing.T) { |
| setup := NewTestSetup(t) |
| defer setup.Cleanup() |
|
|
| testRequest := CreateBasicChatRequest("Define blockchain technology", 0.7, 100) |
|
|
| |
| clearTestKeysWithStore(t, setup.Store) |
|
|
| |
| ctx1 := CreateContextWithCacheKeyAndType("test-cache-isolation", CacheTypeDirect) |
| t.Log("Caching with CacheTypeKey=direct only...") |
| response1, err1 := setup.Client.ChatCompletionRequest(ctx1, testRequest) |
| if err1 != nil { |
| return |
| } |
| AssertNoCacheHit(t, &schemas.BifrostResponse{ChatResponse: response1}) |
|
|
| WaitForCache(setup.Plugin) |
|
|
| |
| ctx2 := CreateContextWithCacheKeyAndType("test-cache-isolation", CacheTypeSemantic) |
| t.Log("Retrieving same request with CacheTypeKey=semantic (should miss)...") |
| response2, err2 := setup.Client.ChatCompletionRequest(ctx2, testRequest) |
| if err2 != nil { |
| return |
| } |
| AssertNoCacheHit(t, &schemas.BifrostResponse{ChatResponse: response2}) |
|
|
| WaitForCache(setup.Plugin) |
|
|
| |
| t.Log("Retrieving with CacheTypeKey=direct (should hit)...") |
| response3, err3 := setup.Client.ChatCompletionRequest(ctx1, testRequest) |
| if err3 != nil { |
| t.Fatalf("Third request failed: %v", err3) |
| } |
| AssertCacheHit(t, &schemas.BifrostResponse{ChatResponse: response3}, "direct") |
|
|
| |
| ctx4 := CreateContextWithCacheKey("test-cache-isolation") |
| t.Log("Retrieving with default behavior (should find direct cache)...") |
| response4, err4 := setup.Client.ChatCompletionRequest(ctx4, testRequest) |
| if err4 != nil { |
| t.Fatalf("Fourth request failed: %v", err4) |
| } |
| AssertCacheHit(t, &schemas.BifrostResponse{ChatResponse: response4}, "direct") |
|
|
| t.Log("✅ Cache type isolation works correctly") |
| } |
|
|
| |
| func TestCacheTypeFallbackBehavior(t *testing.T) { |
| setup := NewTestSetup(t) |
| defer setup.Cleanup() |
|
|
| |
| originalRequest := CreateBasicChatRequest("Explain machine learning", 0.7, 100) |
| ctx1 := CreateContextWithCacheKey("test-fallback-behavior") |
|
|
| t.Log("Caching with default behavior...") |
| response1, err1 := setup.Client.ChatCompletionRequest(ctx1, originalRequest) |
| if err1 != nil { |
| return |
| } |
| AssertNoCacheHit(t, &schemas.BifrostResponse{ChatResponse: response1}) |
|
|
| WaitForCache(setup.Plugin) |
|
|
| |
| similarRequest := CreateBasicChatRequest("Explain machine learning concepts", 0.7, 100) |
| ctx2 := CreateContextWithCacheKeyAndType("test-fallback-behavior", CacheTypeDirect) |
|
|
| t.Log("Testing similar request with CacheTypeKey=direct (should miss, make request, cache without embeddings)...") |
| response2, err2 := setup.Client.ChatCompletionRequest(ctx2, similarRequest) |
| if err2 != nil { |
| return |
| } |
| AssertNoCacheHit(t, &schemas.BifrostResponse{ChatResponse: response2}) |
|
|
| WaitForCache(setup.Plugin) |
|
|
| |
| ctx3 := CreateContextWithCacheKeyAndType("test-fallback-behavior", CacheTypeSemantic) |
|
|
| t.Log("Testing similar request with CacheTypeKey=semantic (should find semantic match from step 1)...") |
| response3, err3 := setup.Client.ChatCompletionRequest(ctx3, similarRequest) |
| if err3 != nil { |
| t.Fatalf("Third request failed: %v", err3) |
| } |
|
|
| |
| if response3.ExtraFields.CacheDebug != nil && response3.ExtraFields.CacheDebug.CacheHit { |
| AssertCacheHit(t, &schemas.BifrostResponse{ChatResponse: response3}, "semantic") |
| t.Log("✅ Semantic search found similar entry from step 1") |
| } else { |
| AssertNoCacheHit(t, &schemas.BifrostResponse{ChatResponse: response3}) |
| t.Log("ℹ️ No semantic match found (threshold may be too high or semantic similarity low)") |
| } |
|
|
| |
| |
| differentSimilarRequest := CreateBasicChatRequest("Explain the basics of machine learning", 0.7, 100) |
| ctx4 := CreateContextWithCacheKey("test-fallback-behavior") |
|
|
| t.Log("Testing different similar request with default behavior (direct miss -> semantic fallback)...") |
| response4, err4 := setup.Client.ChatCompletionRequest(ctx4, differentSimilarRequest) |
| if err4 != nil { |
| t.Fatalf("Fourth request failed: %v", err4) |
| } |
|
|
| |
| if response4.ExtraFields.CacheDebug != nil && response4.ExtraFields.CacheDebug.CacheHit { |
| AssertCacheHit(t, &schemas.BifrostResponse{ChatResponse: response4}, "semantic") |
| t.Log("✅ Default behavior found semantic fallback") |
| } else { |
| AssertNoCacheHit(t, &schemas.BifrostResponse{ChatResponse: response4}) |
| t.Log("ℹ️ No fallback match found") |
| } |
|
|
| t.Log("✅ Cache type fallback behavior verified") |
| } |
|
|
| |
| func TestMultipleCacheEntriesPriority(t *testing.T) { |
| setup := NewTestSetup(t) |
| defer setup.Cleanup() |
|
|
| testRequest := CreateBasicChatRequest("What is deep learning?", 0.7, 100) |
|
|
| |
| ctx1 := CreateContextWithCacheKey("test-cache-priority") |
| t.Log("Creating cache entry with default behavior...") |
| response1, err1 := setup.Client.ChatCompletionRequest(ctx1, testRequest) |
| if err1 != nil { |
| return |
| } |
| AssertNoCacheHit(t, &schemas.BifrostResponse{ChatResponse: response1}) |
| originalContent := *response1.Choices[0].Message.Content.ContentStr |
|
|
| WaitForCache(setup.Plugin) |
|
|
| |
| t.Log("Verifying cache hit with default behavior...") |
| response2, err2 := setup.Client.ChatCompletionRequest(ctx1, testRequest) |
| if err2 != nil { |
| if err2.Error != nil { |
| t.Fatalf("Second request failed: %v", err2.Error.Message) |
| } else { |
| t.Fatalf("Second request failed: %v", err2) |
| } |
| } |
| AssertCacheHit(t, &schemas.BifrostResponse{ChatResponse: response2}, "direct") |
| cachedContent := *response2.Choices[0].Message.Content.ContentStr |
|
|
| |
| if originalContent != cachedContent { |
| t.Errorf("Cache content mismatch:\nOriginal: %s\nCached: %s", originalContent, cachedContent) |
| } |
|
|
| |
| ctx2 := CreateContextWithCacheKeyAndType("test-cache-priority", CacheTypeDirect) |
| t.Log("Accessing with CacheTypeKey=direct...") |
| response3, err3 := setup.Client.ChatCompletionRequest(ctx2, testRequest) |
| if err3 != nil { |
| t.Fatalf("Third request failed: %v", err3) |
| } |
| AssertCacheHit(t, &schemas.BifrostResponse{ChatResponse: response3}, "direct") |
|
|
| |
| ctx3 := CreateContextWithCacheKeyAndType("test-cache-priority", CacheTypeSemantic) |
| t.Log("Accessing with CacheTypeKey=semantic...") |
| response4, err4 := setup.Client.ChatCompletionRequest(ctx3, testRequest) |
| if err4 != nil { |
| t.Fatalf("Fourth request failed: %v", err4) |
| } |
| AssertCacheHit(t, &schemas.BifrostResponse{ChatResponse: response4}, "semantic") |
|
|
| t.Log("✅ Multiple cache entries accessible correctly") |
| } |
|
|
| |
| func TestCrossCacheTypeWithDifferentParameters(t *testing.T) { |
| setup := NewTestSetup(t) |
| defer setup.Cleanup() |
|
|
| baseMessage := "Explain quantum computing" |
|
|
| |
| request1 := CreateBasicChatRequest(baseMessage, 0.7, 100) |
| ctx1 := CreateContextWithCacheKey("test-cross-cache-params") |
|
|
| t.Log("Caching with temp=0.7, max_tokens=100...") |
| response1, err1 := setup.Client.ChatCompletionRequest(ctx1, request1) |
| if err1 != nil { |
| return |
| } |
| AssertNoCacheHit(t, &schemas.BifrostResponse{ChatResponse: response1}) |
|
|
| WaitForCache(setup.Plugin) |
|
|
| |
| ctx2 := CreateContextWithCacheKeyAndType("test-cross-cache-params", CacheTypeDirect) |
| t.Log("Retrieving same parameters with CacheTypeKey=direct...") |
| response2, err2 := setup.Client.ChatCompletionRequest(ctx2, request1) |
| if err2 != nil { |
| if err2.Error != nil { |
| t.Fatalf("Second request failed: %v", err2.Error.Message) |
| } else { |
| t.Fatalf("Second request failed: %v", err2) |
| } |
| } |
| AssertCacheHit(t, &schemas.BifrostResponse{ChatResponse: response2}, "direct") |
|
|
| |
| request3 := CreateBasicChatRequest(baseMessage, 0.5, 200) |
| t.Log("Testing different parameters (should miss)...") |
| response3, err3 := setup.Client.ChatCompletionRequest(ctx2, request3) |
| if err3 != nil { |
| return |
| } |
| AssertNoCacheHit(t, &schemas.BifrostResponse{ChatResponse: response3}) |
|
|
| |
| ctx4 := CreateContextWithCacheKeyAndType("test-cross-cache-params", CacheTypeSemantic) |
| similarRequest := CreateBasicChatRequest("Can you explain quantum computing", 0.5, 200) |
|
|
| t.Log("Testing semantic search with different params and similar message...") |
| response4, err4 := setup.Client.ChatCompletionRequest(ctx4, similarRequest) |
| if err4 != nil { |
| return |
| } |
| |
| AssertNoCacheHit(t, &schemas.BifrostResponse{ChatResponse: response4}) |
|
|
| t.Log("✅ Cross-cache-type parameter handling works correctly") |
| } |
|
|
| |
| func TestCacheTypeErrorHandling(t *testing.T) { |
| setup := NewTestSetup(t) |
| defer setup.Cleanup() |
|
|
| testRequest := CreateBasicChatRequest("Test error handling", 0.7, 50) |
|
|
| |
| ctx1 := CreateContextWithCacheKey("test-cache-error-handling") |
| ctx1 = ctx1.WithValue(CacheTypeKey, "invalid_cache_type") |
|
|
| t.Log("Testing invalid cache type (should fallback to default behavior)...") |
| response1, err1 := setup.Client.ChatCompletionRequest(ctx1, testRequest) |
| if err1 != nil { |
| return |
| } |
| AssertNoCacheHit(t, &schemas.BifrostResponse{ChatResponse: response1}) |
|
|
| WaitForCache(setup.Plugin) |
|
|
| |
| ctx2 := CreateContextWithCacheKey("test-cache-error-handling") |
| ctx2 = ctx2.WithValue(CacheTypeKey, nil) |
|
|
| t.Log("Testing nil cache type (should use default behavior)...") |
| response2, err2 := setup.Client.ChatCompletionRequest(ctx2, testRequest) |
| if err2 != nil { |
| if err2.Error != nil { |
| t.Fatalf("Second request failed: %v", err2.Error.Message) |
| } else { |
| t.Fatalf("Second request failed: %v", err2) |
| } |
| } |
| AssertCacheHit(t, &schemas.BifrostResponse{ChatResponse: response2}, "direct") |
|
|
| t.Log("✅ Cache type error handling works correctly") |
| } |
|
|