Files
bifrost/plugins/semanticcache/plugin_no_store_test.go
Beyhan Oğur 880f412e2c first commit
2026-04-26 21:52:23 +03:00

327 lines
12 KiB
Go

package semanticcache
import (
"testing"
"github.com/maximhq/bifrost/core/schemas"
)
// TestCacheNoStoreBasicFunctionality tests that CacheNoStoreKey prevents caching
func TestCacheNoStoreBasicFunctionality(t *testing.T) {
setup := NewTestSetup(t)
defer setup.Cleanup()
testRequest := CreateBasicChatRequest("What is artificial intelligence?", 0.7, 100)
// Test 1: Normal caching (control test)
ctx1 := CreateContextWithCacheKey("test-no-store-control")
t.Log("Making normal request (should be cached)...")
response1, err1 := setup.Client.ChatCompletionRequest(ctx1, testRequest)
if err1 != nil {
return // Test will be skipped by retry function
}
AssertNoCacheHit(t, &schemas.BifrostResponse{ChatResponse: response1}) // Fresh request
WaitForCache(setup.Plugin)
// Verify it got cached
t.Log("Verifying normal caching worked...")
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") // Should be cached
// Test 2: NoStore = true (should not cache)
ctx2 := CreateContextWithCacheKeyAndNoStore("test-no-store-disabled", true)
t.Log("Making request with CacheNoStoreKey=true (should not be cached)...")
response3, err3 := setup.Client.ChatCompletionRequest(ctx2, testRequest)
if err3 != nil {
return // Test will be skipped by retry function
}
AssertNoCacheHit(t, &schemas.BifrostResponse{ChatResponse: response3}) // Fresh request
WaitForCache(setup.Plugin)
// Verify it was NOT cached
t.Log("Verifying no-store request was not cached...")
response4, err4 := setup.Client.ChatCompletionRequest(ctx2, testRequest)
if err4 != nil {
return // Test will be skipped by retry function
}
AssertNoCacheHit(t, &schemas.BifrostResponse{ChatResponse: response4}) // Should still be fresh (not cached)
// Test 3: NoStore = false (should cache normally)
ctx3 := CreateContextWithCacheKeyAndNoStore("test-no-store-enabled", false)
t.Log("Making request with CacheNoStoreKey=false (should be cached)...")
response5, err5 := setup.Client.ChatCompletionRequest(ctx3, testRequest)
if err5 != nil {
return // Test will be skipped by retry function
}
AssertNoCacheHit(t, &schemas.BifrostResponse{ChatResponse: response5}) // Fresh request
WaitForCache(setup.Plugin)
// Verify it got cached
t.Log("Verifying no-store=false request was cached...")
response6, err6 := setup.Client.ChatCompletionRequest(ctx3, testRequest)
if err6 != nil {
t.Fatalf("Sixth request failed: %v", err6)
}
AssertCacheHit(t, &schemas.BifrostResponse{ChatResponse: response6}, "direct") // Should be cached
t.Log("✅ CacheNoStoreKey basic functionality works correctly")
}
// TestCacheNoStoreWithDifferentRequestTypes tests NoStore with various request types
func TestCacheNoStoreWithDifferentRequestTypes(t *testing.T) {
t.Skip("Skipping Embedding Tests")
setup := NewTestSetup(t)
defer setup.Cleanup()
// Test with chat completion
chatRequest := CreateBasicChatRequest("Test no-store with chat", 0.7, 50)
ctx1 := CreateContextWithCacheKeyAndNoStore("test-no-store-chat", true)
t.Log("Testing no-store with chat completion...")
response1, err1 := setup.Client.ChatCompletionRequest(ctx1, chatRequest)
if err1 != nil {
return // Test will be skipped by retry function
}
AssertNoCacheHit(t, &schemas.BifrostResponse{ChatResponse: response1})
WaitForCache(setup.Plugin)
// Verify not cached
response2, err2 := setup.Client.ChatCompletionRequest(ctx1, chatRequest)
if err2 != nil {
return // Test will be skipped by retry function
}
AssertNoCacheHit(t, &schemas.BifrostResponse{ChatResponse: response2}) // Should not be cached
// Test with embedding request
embeddingRequest := CreateEmbeddingRequest([]string{"Test no-store with embeddings"})
ctx2 := CreateContextWithCacheKeyAndNoStore("test-no-store-embedding", true)
t.Log("Testing no-store with embedding request...")
response3, err3 := setup.Client.EmbeddingRequest(ctx2, embeddingRequest)
if err3 != nil {
return // Test will be skipped by retry function
}
AssertNoCacheHit(t, &schemas.BifrostResponse{EmbeddingResponse: response3})
WaitForCache(setup.Plugin)
// Verify not cached
response4, err4 := setup.Client.EmbeddingRequest(ctx2, embeddingRequest)
if err4 != nil {
return // Test will be skipped by retry function
}
AssertNoCacheHit(t, &schemas.BifrostResponse{EmbeddingResponse: response4}) // Should not be cached
t.Log("✅ CacheNoStoreKey works with different request types")
}
// TestCacheNoStoreWithConversationHistory tests NoStore with conversation context
func TestCacheNoStoreWithConversationHistory(t *testing.T) {
setup := NewTestSetup(t)
defer setup.Cleanup()
// Create conversation context
conversation := BuildConversationHistory(
"You are a helpful assistant",
[]string{"Hello", "Hi! How can I help?"},
)
messages := AddUserMessage(conversation, "What is machine learning?")
request := CreateConversationRequest(messages, 0.7, 100)
// Test with no-store enabled
ctx := CreateContextWithCacheKeyAndNoStore("test-no-store-conversation", true)
t.Log("Testing no-store with conversation history...")
response1, err1 := setup.Client.ChatCompletionRequest(ctx, request)
if err1 != nil {
return // Test will be skipped by retry function
}
AssertNoCacheHit(t, &schemas.BifrostResponse{ChatResponse: response1})
WaitForCache(setup.Plugin)
// Verify not cached (same conversation should not hit cache)
response2, err2 := setup.Client.ChatCompletionRequest(ctx, request)
if err2 != nil {
return // Test will be skipped by retry function
}
AssertNoCacheHit(t, &schemas.BifrostResponse{ChatResponse: response2}) // Should not be cached due to no-store
t.Log("✅ CacheNoStoreKey works with conversation history")
}
// TestCacheNoStoreWithCacheTypes tests NoStore interaction with CacheTypeKey
func TestCacheNoStoreWithCacheTypes(t *testing.T) {
setup := NewTestSetup(t)
defer setup.Cleanup()
testRequest := CreateBasicChatRequest("Test no-store with cache types", 0.7, 50)
// Test no-store with direct cache type
ctx1 := CreateContextWithCacheKey("test-no-store-cache-types")
ctx1 = ctx1.WithValue(CacheNoStoreKey, true)
ctx1 = ctx1.WithValue(CacheTypeKey, CacheTypeDirect)
t.Log("Testing no-store with CacheTypeKey=direct...")
response1, err1 := setup.Client.ChatCompletionRequest(ctx1, testRequest)
if err1 != nil {
return // Test will be skipped by retry function
}
AssertNoCacheHit(t, &schemas.BifrostResponse{ChatResponse: response1})
WaitForCache(setup.Plugin)
// Should not be cached
response2, err2 := setup.Client.ChatCompletionRequest(ctx1, testRequest)
if err2 != nil {
return // Test will be skipped by retry function
}
AssertNoCacheHit(t, &schemas.BifrostResponse{ChatResponse: response2}) // No-store should override cache type
// Test no-store with semantic cache type
ctx2 := CreateContextWithCacheKey("test-no-store-cache-types")
ctx2 = ctx2.WithValue(CacheNoStoreKey, true)
ctx2 = ctx2.WithValue(CacheTypeKey, CacheTypeSemantic)
t.Log("Testing no-store with CacheTypeKey=semantic...")
response3, err3 := setup.Client.ChatCompletionRequest(ctx2, testRequest)
if err3 != nil {
return // Test will be skipped by retry function
}
AssertNoCacheHit(t, &schemas.BifrostResponse{ChatResponse: response3})
WaitForCache(setup.Plugin)
// Should not be cached
response4, err4 := setup.Client.ChatCompletionRequest(ctx2, testRequest)
if err4 != nil {
return // Test will be skipped by retry function
}
AssertNoCacheHit(t, &schemas.BifrostResponse{ChatResponse: response4}) // No-store should override cache type
t.Log("✅ CacheNoStoreKey correctly overrides cache type settings")
}
// TestCacheNoStoreErrorHandling tests error scenarios with NoStore
func TestCacheNoStoreErrorHandling(t *testing.T) {
setup := NewTestSetup(t)
defer setup.Cleanup()
testRequest := CreateBasicChatRequest("Test no-store error handling", 0.7, 50)
// Test with invalid no-store value (non-boolean)
ctx1 := CreateContextWithCacheKey("test-no-store-errors")
ctx1 = ctx1.WithValue(CacheNoStoreKey, "invalid")
t.Log("Testing no-store with invalid value (should cache normally)...")
response1, err1 := setup.Client.ChatCompletionRequest(ctx1, testRequest)
if err1 != nil {
return // Test will be skipped by retry function
}
AssertNoCacheHit(t, &schemas.BifrostResponse{ChatResponse: response1})
WaitForCache(setup.Plugin)
// Should be cached (invalid value should be ignored)
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") // Should be cached (invalid value ignored)
// Test with nil value (should cache normally)
ctx2 := CreateContextWithCacheKey("test-no-store-nil")
ctx2 = ctx2.WithValue(CacheNoStoreKey, nil)
t.Log("Testing no-store with nil value (should cache normally)...")
response3, err3 := setup.Client.ChatCompletionRequest(ctx2, testRequest)
if err3 != nil {
return // Test will be skipped by retry function
}
AssertNoCacheHit(t, &schemas.BifrostResponse{ChatResponse: response3})
WaitForCache(setup.Plugin)
// Should be cached (nil should be treated as normal caching)
response4, err4 := setup.Client.ChatCompletionRequest(ctx2, testRequest)
if err4 != nil {
t.Fatalf("Fourth request failed: %v", err4)
}
AssertCacheHit(t, &schemas.BifrostResponse{ChatResponse: response4}, "direct") // Should be cached (nil ignored)
t.Log("✅ CacheNoStoreKey error handling works correctly")
}
// TestCacheNoStoreReadButNoWrite tests that NoStore allows reading cache but prevents writing
func TestCacheNoStoreReadButNoWrite(t *testing.T) {
setup := NewTestSetup(t)
defer setup.Cleanup()
testRequest := CreateBasicChatRequest("Describe Isaac Newton's three laws of motion", 0.7, 50)
// Step 1: Cache a response normally
ctx1 := CreateContextWithCacheKey("test-no-store-read")
t.Log("Caching response normally...")
response1, err1 := setup.Client.ChatCompletionRequest(ctx1, testRequest)
if err1 != nil {
return // Test will be skipped by retry function
}
AssertNoCacheHit(t, &schemas.BifrostResponse{ChatResponse: response1})
WaitForCache(setup.Plugin)
// Step 2: Try to read with no-store enabled (should still read from cache)
ctx2 := CreateContextWithCacheKeyAndNoStore("test-no-store-read", true)
t.Log("Reading with no-store enabled (should still hit cache for reads)...")
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)
}
}
// The current implementation should still read from cache even with no-store
// (no-store only affects writing, not reading)
AssertCacheHit(t, &schemas.BifrostResponse{ChatResponse: response2}, "direct")
// Step 3: Make a semantically similar request with no-store (strong paraphrase for deterministic semantic hit)
newRequest := CreateBasicChatRequest("Describe the three laws of motion by Isaac Newton", 0.7, 50)
t.Log("Making semantically similar request with no-store (should get semantic hit, but not cache response)...")
response3, err3 := setup.Client.ChatCompletionRequest(ctx2, newRequest)
if err3 != nil {
t.Fatalf("Third request failed: %v", err3)
}
// Should get semantic cache hit (no-store allows reads, just prevents writes)
AssertCacheHit(t, &schemas.BifrostResponse{ChatResponse: response3}, "semantic")
WaitForCache(setup.Plugin)
// Step 4: Repeat similar request with no-store (should still get semantic hit)
t.Log("Repeating similar request with no-store (should still get semantic hit)...")
response4, err4 := setup.Client.ChatCompletionRequest(ctx2, newRequest)
if err4 != nil {
t.Fatalf("Fourth request failed: %v", err4)
}
// Should get semantic cache hit again (consistent behavior)
AssertCacheHit(t, &schemas.BifrostResponse{ChatResponse: response4}, "semantic")
t.Log("✅ CacheNoStoreKey allows reading but prevents writing")
}