package lib import ( "os" "path/filepath" "runtime" "strings" "testing" ) // loadLocalSchema reads the local config.schema.json for use in tests, // avoiding remote fetches during test execution. func loadLocalSchema(t *testing.T) []byte { t.Helper() _, filename, _, ok := runtime.Caller(0) if !ok { t.Fatal("failed to get current file path") } schemaPath := filepath.Join(filepath.Dir(filename), "..", "..", "config.schema.json") data, err := os.ReadFile(schemaPath) if err != nil { t.Fatalf("failed to read config.schema.json: %v", err) } return data } func TestValidateConfigSchema_ValidConfig(t *testing.T) { // Minimal valid config matching the schema validConfig := `{ "providers": { "openai": { "keys": [ { "name": "default", "value": "sk-test-key", "weight": 1.0, "models": ["gpt-4"] } ] } } }` err := ValidateConfigSchema([]byte(validConfig), loadLocalSchema(t)) if err != nil { t.Errorf("expected valid config to pass validation, got error: %v", err) } } func TestValidateConfigSchema_EmptyObject(t *testing.T) { // Empty object should be valid (all properties are optional) emptyConfig := `{}` err := ValidateConfigSchema([]byte(emptyConfig), loadLocalSchema(t)) if err != nil { t.Errorf("expected empty config to pass validation, got error: %v", err) } } func TestValidateConfigSchema_InvalidJSON(t *testing.T) { invalidJSON := `{invalid json` err := ValidateConfigSchema([]byte(invalidJSON), loadLocalSchema(t)) if err == nil { t.Error("expected invalid JSON to fail validation") } if !strings.Contains(err.Error(), "invalid JSON") { t.Errorf("expected error to mention 'invalid JSON', got: %v", err) } } func TestValidateConfigSchema_InvalidType(t *testing.T) { // client.initial_pool_size should be an integer, not a string invalidConfig := `{ "client": { "initial_pool_size": "not-a-number" } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config with wrong type to fail validation") } } func TestValidateConfigSchema_InvalidEnum(t *testing.T) { // vector_store.type must be one of: weaviate, redis, qdrant, pinecone invalidConfig := `{ "vector_store": { "enabled": true, "type": "invalid-store-type" } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config with invalid enum value to fail validation") } } func TestValidateConfigSchema_MissingRequiredField(t *testing.T) { // governance.budgets items require id, max_limit, and reset_duration invalidConfig := `{ "governance": { "budgets": [ { "id": "budget-1" } ] } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing required fields to fail validation") } } func TestValidateConfigSchema_ValidGovernanceConfig(t *testing.T) { validConfig := `{ "governance": { "budgets": [ { "id": "budget-1", "max_limit": 100.0, "reset_duration": "1d" } ], "virtual_keys": [ { "id": "vk-1", "name": "Test Key", "value": "vk_test123" } ] } }` err := ValidateConfigSchema([]byte(validConfig), loadLocalSchema(t)) if err != nil { t.Errorf("expected valid governance config to pass validation, got error: %v", err) } } func TestValidateConfigSchema_ValidClientConfig(t *testing.T) { // allowed_origins with "*" or URI strings (but not both in same array according to oneOf) validConfig := `{ "client": { "initial_pool_size": 500, "drop_excess_requests": true, "enable_logging": true, "log_retention_days": 30, "allowed_origins": ["https://example.com"] } }` err := ValidateConfigSchema([]byte(validConfig), loadLocalSchema(t)) if err != nil { t.Errorf("expected valid client config to pass validation, got error: %v", err) } } func TestValidateConfigSchema_InvalidMinimum(t *testing.T) { // initial_pool_size has minimum: 1 invalidConfig := `{ "client": { "initial_pool_size": 0 } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config with value below minimum to fail validation") } } // ============================================================================= // Provider Key Required Fields Tests // ============================================================================= func TestValidateConfigSchema_ProviderKey_Valid(t *testing.T) { // Valid provider key with all required fields: name, value, weight validConfig := `{ "providers": { "openai": { "keys": [ { "name": "my-key", "value": "sk-test-key-12345", "weight": 1.0 } ] } } }` err := ValidateConfigSchema([]byte(validConfig), loadLocalSchema(t)) if err != nil { t.Errorf("expected valid provider key config to pass validation, got error: %v", err) } } func TestValidateConfigSchema_ProviderKey_MissingName(t *testing.T) { // Missing required field: name invalidConfig := `{ "providers": { "openai": { "keys": [ { "value": "sk-test-key-12345", "weight": 1.0 } ] } } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'name' in provider key to fail validation") } } func TestValidateConfigSchema_ProviderKey_MissingWeight(t *testing.T) { // Missing required field: weight invalidConfig := `{ "providers": { "openai": { "keys": [ { "name": "my-key", "value": "sk-test-key-12345" } ] } } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'weight' in provider key to fail validation") } } // ============================================================================= // Governance Budget Required Fields Tests // ============================================================================= func TestValidateConfigSchema_Budget_Valid(t *testing.T) { // Valid budget with all required fields: id, max_limit, reset_duration validConfig := `{ "governance": { "budgets": [ { "id": "budget-1", "max_limit": 100.0, "reset_duration": "30d" } ] } }` err := ValidateConfigSchema([]byte(validConfig), loadLocalSchema(t)) if err != nil { t.Errorf("expected valid budget config to pass validation, got error: %v", err) } } func TestValidateConfigSchema_Budget_MissingId(t *testing.T) { // Missing required field: id invalidConfig := `{ "governance": { "budgets": [ { "max_limit": 100.0, "reset_duration": "30d" } ] } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'id' in budget to fail validation") } } func TestValidateConfigSchema_Budget_MissingMaxLimit(t *testing.T) { // Missing required field: max_limit invalidConfig := `{ "governance": { "budgets": [ { "id": "budget-1", "reset_duration": "30d" } ] } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'max_limit' in budget to fail validation") } } func TestValidateConfigSchema_Budget_MissingResetDuration(t *testing.T) { // Missing required field: reset_duration invalidConfig := `{ "governance": { "budgets": [ { "id": "budget-1", "max_limit": 100.0 } ] } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'reset_duration' in budget to fail validation") } } // ============================================================================= // Governance Rate Limit Required Fields Tests // ============================================================================= func TestValidateConfigSchema_RateLimit_Valid(t *testing.T) { // Valid rate limit with required field: id validConfig := `{ "governance": { "rate_limits": [ { "id": "rate-limit-1", "token_max_limit": 10000, "token_reset_duration": "1h" } ] } }` err := ValidateConfigSchema([]byte(validConfig), loadLocalSchema(t)) if err != nil { t.Errorf("expected valid rate limit config to pass validation, got error: %v", err) } } func TestValidateConfigSchema_RateLimit_MissingId(t *testing.T) { // Missing required field: id invalidConfig := `{ "governance": { "rate_limits": [ { "token_max_limit": 10000, "token_reset_duration": "1h" } ] } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'id' in rate limit to fail validation") } } // ============================================================================= // Governance Customer Required Fields Tests // ============================================================================= func TestValidateConfigSchema_Customer_Valid(t *testing.T) { // Valid customer with all required fields: id, name validConfig := `{ "governance": { "customers": [ { "id": "customer-1", "name": "Acme Corp" } ] } }` err := ValidateConfigSchema([]byte(validConfig), loadLocalSchema(t)) if err != nil { t.Errorf("expected valid customer config to pass validation, got error: %v", err) } } func TestValidateConfigSchema_Customer_MissingId(t *testing.T) { // Missing required field: id invalidConfig := `{ "governance": { "customers": [ { "name": "Acme Corp" } ] } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'id' in customer to fail validation") } } func TestValidateConfigSchema_Customer_MissingName(t *testing.T) { // Missing required field: name invalidConfig := `{ "governance": { "customers": [ { "id": "customer-1" } ] } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'name' in customer to fail validation") } } // ============================================================================= // Governance Team Required Fields Tests // ============================================================================= func TestValidateConfigSchema_Team_Valid(t *testing.T) { // Valid team with all required fields: id, name validConfig := `{ "governance": { "teams": [ { "id": "team-1", "name": "Engineering" } ] } }` err := ValidateConfigSchema([]byte(validConfig), loadLocalSchema(t)) if err != nil { t.Errorf("expected valid team config to pass validation, got error: %v", err) } } func TestValidateConfigSchema_Team_MissingId(t *testing.T) { // Missing required field: id invalidConfig := `{ "governance": { "teams": [ { "name": "Engineering" } ] } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'id' in team to fail validation") } } func TestValidateConfigSchema_Team_MissingName(t *testing.T) { // Missing required field: name invalidConfig := `{ "governance": { "teams": [ { "id": "team-1" } ] } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'name' in team to fail validation") } } // ============================================================================= // Governance Virtual Key Required Fields Tests // ============================================================================= func TestValidateConfigSchema_VirtualKey_Valid(t *testing.T) { // Valid virtual key with all required fields: id, name, value validConfig := `{ "governance": { "virtual_keys": [ { "id": "vk-1", "name": "Test Virtual Key", "value": "vk_test_123456" } ] } }` err := ValidateConfigSchema([]byte(validConfig), loadLocalSchema(t)) if err != nil { t.Errorf("expected valid virtual key config to pass validation, got error: %v", err) } } func TestValidateConfigSchema_VirtualKey_MissingId(t *testing.T) { // Missing required field: id invalidConfig := `{ "governance": { "virtual_keys": [ { "name": "Test Virtual Key", "value": "vk_test_123456" } ] } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'id' in virtual key to fail validation") } } func TestValidateConfigSchema_VirtualKey_MissingName(t *testing.T) { // Missing required field: name invalidConfig := `{ "governance": { "virtual_keys": [ { "id": "vk-1", "value": "vk_test_123456" } ] } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'name' in virtual key to fail validation") } } // ============================================================================= // Virtual Key Provider Config Required Fields Tests // ============================================================================= func TestValidateConfigSchema_VirtualKeyProviderConfig_Valid(t *testing.T) { // Valid virtual key provider config with required field: provider validConfig := `{ "governance": { "virtual_keys": [ { "id": "vk-1", "name": "Test Virtual Key", "value": "vk_test_123456", "provider_configs": [ { "provider": "openai" } ] } ] } }` err := ValidateConfigSchema([]byte(validConfig), loadLocalSchema(t)) if err != nil { t.Errorf("expected valid virtual key provider config to pass validation, got error: %v", err) } } func TestValidateConfigSchema_VirtualKeyProviderConfig_MissingProvider(t *testing.T) { // Missing required field: provider invalidConfig := `{ "governance": { "virtual_keys": [ { "id": "vk-1", "name": "Test Virtual Key", "value": "vk_test_123456", "provider_configs": [ { "weight": 1.0 } ] } ] } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'provider' in virtual key provider config to fail validation") } } // ============================================================================= // Virtual Key MCP Config Required Fields Tests // ============================================================================= func TestValidateConfigSchema_VirtualKeyMCPConfig_Valid(t *testing.T) { // Valid virtual key MCP config identifying the MCP client by mcp_client_id (DB form) validConfig := `{ "governance": { "virtual_keys": [ { "id": "vk-1", "name": "Test Virtual Key", "value": "vk_test_123456", "mcp_configs": [ { "mcp_client_id": 1 } ] } ] } }` err := ValidateConfigSchema([]byte(validConfig), loadLocalSchema(t)) if err != nil { t.Errorf("expected valid virtual key MCP config to pass validation, got error: %v", err) } } func TestValidateConfigSchema_VirtualKeyMCPConfig_ValidWithClientName(t *testing.T) { // Valid virtual key MCP config identifying the MCP client by mcp_client_name // (config-file form — resolved to mcp_client_id at startup). Either identifier // alone is sufficient; neither is required at the JSON Schema level. validConfig := `{ "governance": { "virtual_keys": [ { "id": "vk-1", "name": "Test Virtual Key", "value": "vk_test_123456", "mcp_configs": [ { "mcp_client_name": "my-mcp-client", "tools_to_execute": ["tool1"] } ] } ] } }` err := ValidateConfigSchema([]byte(validConfig), loadLocalSchema(t)) if err != nil { t.Errorf("expected virtual key MCP config with mcp_client_name to pass validation, got error: %v", err) } } // ============================================================================= // MCP Client Config Required Fields Tests // ============================================================================= func TestValidateConfigSchema_MCPClientConfig_Valid_Stdio(t *testing.T) { // Valid MCP client config with stdio connection type validConfig := `{ "mcp": { "client_configs": [ { "name": "my-mcp-client", "connection_type": "stdio", "stdio_config": { "command": "/usr/bin/my-tool" } } ] } }` err := ValidateConfigSchema([]byte(validConfig), loadLocalSchema(t)) if err != nil { t.Errorf("expected valid MCP client config (stdio) to pass validation, got error: %v", err) } } func TestValidateConfigSchema_MCPClientConfig_Valid_Sse(t *testing.T) { // Valid MCP client config with sse connection type validConfig := `{ "mcp": { "client_configs": [ { "name": "my-mcp-client", "connection_type": "sse", "connection_string": "http://localhost:8080" } ] } }` err := ValidateConfigSchema([]byte(validConfig), loadLocalSchema(t)) if err != nil { t.Errorf("expected valid MCP client config (sse) to pass validation, got error: %v", err) } } func TestValidateConfigSchema_MCPClientConfig_Valid_Http(t *testing.T) { // Valid MCP client config with http connection type validConfig := `{ "mcp": { "client_configs": [ { "name": "my-mcp-client", "connection_type": "http", "connection_string": "http://localhost:8080" } ] } }` err := ValidateConfigSchema([]byte(validConfig), loadLocalSchema(t)) if err != nil { t.Errorf("expected valid MCP client config (http) to pass validation, got error: %v", err) } } func TestValidateConfigSchema_MCPClientConfig_MissingName(t *testing.T) { // Missing required field: name invalidConfig := `{ "mcp": { "client_configs": [ { "connection_type": "stdio", "stdio_config": { "command": "/usr/bin/my-tool" } } ] } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'name' in MCP client config to fail validation") } } func TestValidateConfigSchema_MCPClientConfig_MissingConnectionType(t *testing.T) { // Missing required field: connection_type invalidConfig := `{ "mcp": { "client_configs": [ { "name": "my-mcp-client", "stdio_config": { "command": "/usr/bin/my-tool" } } ] } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'connection_type' in MCP client config to fail validation") } } func TestValidateConfigSchema_MCPClientConfig_MissingStdioConfig(t *testing.T) { // Missing conditional required field: stdio_config when connection_type is stdio invalidConfig := `{ "mcp": { "client_configs": [ { "name": "my-mcp-client", "connection_type": "stdio" } ] } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'stdio_config' for stdio connection type to fail validation") } } func TestValidateConfigSchema_MCPClientConfig_MissingWebsocketConfig(t *testing.T) { // Missing conditional required field: websocket_config when connection_type is websocket invalidConfig := `{ "mcp": { "client_configs": [ { "name": "my-mcp-client", "connection_type": "websocket" } ] } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'websocket_config' for websocket connection type to fail validation") } } func TestValidateConfigSchema_MCPClientConfig_MissingHttpConfig(t *testing.T) { // Missing conditional required field: http_config when connection_type is http invalidConfig := `{ "mcp": { "client_configs": [ { "name": "my-mcp-client", "connection_type": "http" } ] } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'http_config' for http connection type to fail validation") } } func TestValidateConfigSchema_MCPClientConfig_StdioConfig_MissingCommand(t *testing.T) { // Missing required field in stdio_config: command invalidConfig := `{ "mcp": { "client_configs": [ { "name": "my-mcp-client", "connection_type": "stdio", "stdio_config": { "args": ["--help"] } } ] } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'command' in stdio_config to fail validation") } } func TestValidateConfigSchema_MCPClientConfig_WebsocketConfig_MissingUrl(t *testing.T) { // Missing required field in websocket_config: url invalidConfig := `{ "mcp": { "client_configs": [ { "name": "my-mcp-client", "connection_type": "websocket", "websocket_config": {} } ] } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'url' in websocket_config to fail validation") } } func TestValidateConfigSchema_MCPClientConfig_HttpConfig_MissingUrl(t *testing.T) { // Missing required field in http_config: url invalidConfig := `{ "mcp": { "client_configs": [ { "name": "my-mcp-client", "connection_type": "http", "http_config": {} } ] } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'url' in http_config to fail validation") } } // ============================================================================= // Concurrency Config Required Fields Tests // ============================================================================= func TestValidateConfigSchema_ConcurrencyConfig_Valid(t *testing.T) { // Valid concurrency config with all required fields: concurrency, buffer_size validConfig := `{ "providers": { "openai": { "keys": [ { "name": "my-key", "value": "sk-test-key", "weight": 1.0 } ], "concurrency_and_buffer_size": { "concurrency": 10, "buffer_size": 100 } } } }` err := ValidateConfigSchema([]byte(validConfig), loadLocalSchema(t)) if err != nil { t.Errorf("expected valid concurrency config to pass validation, got error: %v", err) } } func TestValidateConfigSchema_ConcurrencyConfig_MissingConcurrency(t *testing.T) { // Missing required field: concurrency invalidConfig := `{ "providers": { "openai": { "keys": [ { "name": "my-key", "value": "sk-test-key", "weight": 1.0 } ], "concurrency_and_buffer_size": { "buffer_size": 100 } } } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'concurrency' in concurrency config to fail validation") } } func TestValidateConfigSchema_ConcurrencyConfig_MissingBufferSize(t *testing.T) { // Missing required field: buffer_size invalidConfig := `{ "providers": { "openai": { "keys": [ { "name": "my-key", "value": "sk-test-key", "weight": 1.0 } ], "concurrency_and_buffer_size": { "concurrency": 10 } } } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'buffer_size' in concurrency config to fail validation") } } // ============================================================================= // Plugin Required Fields Tests // ============================================================================= func TestValidateConfigSchema_Plugin_Valid(t *testing.T) { // Valid plugin with all required fields: enabled, name, config // Note: telemetry plugin requires config object validConfig := `{ "plugins": [ { "enabled": true, "name": "telemetry", "config": {} } ] }` err := ValidateConfigSchema([]byte(validConfig), loadLocalSchema(t)) if err != nil { t.Errorf("expected valid plugin config to pass validation, got error: %v", err) } } func TestValidateConfigSchema_Plugin_MissingEnabled(t *testing.T) { // Missing required field: enabled invalidConfig := `{ "plugins": [ { "name": "telemetry" } ] }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'enabled' in plugin to fail validation") } } func TestValidateConfigSchema_Plugin_MissingName(t *testing.T) { // Missing required field: name invalidConfig := `{ "plugins": [ { "enabled": true } ] }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'name' in plugin to fail validation") } } // ============================================================================= // Semantic Cache Plugin Config Required Fields Tests // ============================================================================= func TestValidateConfigSchema_SemanticCachePlugin_Valid(t *testing.T) { // Valid semantic cache plugin with provider, embedding model, and dimension. Keys are injected at runtime. validConfig := `{ "plugins": [ { "enabled": true, "name": "semantic_cache", "config": { "provider": "openai", "embedding_model": "text-embedding-3-small", "dimension": 1536 } } ] }` err := ValidateConfigSchema([]byte(validConfig), loadLocalSchema(t)) if err != nil { t.Errorf("expected valid semantic cache plugin config to pass validation, got error: %v", err) } } func TestValidateConfigSchema_SemanticCachePlugin_MissingProvider(t *testing.T) { // Missing required field: provider for semantic mode (dimension > 1) invalidConfig := `{ "plugins": [ { "enabled": true, "name": "semantic_cache", "config": { "dimension": 1536 } } ] }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'provider' in semantic cache plugin to fail validation") } } func TestValidateConfigSchema_SemanticCachePlugin_ProviderWithoutKeys(t *testing.T) { // Keys are not required at schema level for provider-backed config. validConfig := `{ "plugins": [ { "enabled": true, "name": "semantic_cache", "config": { "provider": "openai", "embedding_model": "text-embedding-3-small", "dimension": 1536 } } ] }` err := ValidateConfigSchema([]byte(validConfig), loadLocalSchema(t)) if err != nil { t.Errorf("expected provider-backed semantic cache config without plugin keys to pass validation, got error: %v", err) } } func TestValidateConfigSchema_SemanticCachePlugin_ProviderWithoutEmbeddingModel(t *testing.T) { invalidConfig := `{ "plugins": [ { "enabled": true, "name": "semantic_cache", "config": { "provider": "openai", "dimension": 1536 } } ] }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected provider-backed semantic cache config without embedding_model to fail validation") } } func TestValidateConfigSchema_SemanticCachePlugin_DirectModeValid(t *testing.T) { validConfig := `{ "plugins": [ { "enabled": true, "name": "semantic_cache", "config": { "dimension": 1 } } ] }` err := ValidateConfigSchema([]byte(validConfig), loadLocalSchema(t)) if err != nil { t.Errorf("expected direct-only semantic cache config to pass validation, got error: %v", err) } } func TestValidateConfigSchema_SemanticCachePlugin_DirectModeWithEmbeddingModelInvalid(t *testing.T) { invalidConfig := `{ "plugins": [ { "enabled": true, "name": "semantic_cache", "config": { "dimension": 1, "embedding_model": "text-embedding-3-small" } } ] }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected direct-only semantic cache config with embedding_model to fail validation") } } func TestValidateConfigSchema_SemanticCachePlugin_DimensionOneWithProviderInvalid(t *testing.T) { invalidConfig := `{ "plugins": [ { "enabled": true, "name": "semantic_cache", "config": { "provider": "openai", "embedding_model": "text-embedding-3-small", "dimension": 1 } } ] }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected dimension: 1 with provider in semantic cache plugin to fail validation") } } func TestValidateConfigSchema_SemanticCachePlugin_MissingDimension(t *testing.T) { // Missing required field: dimension invalidConfig := `{ "plugins": [ { "enabled": true, "name": "semantic_cache", "config": { "provider": "openai", "embedding_model": "text-embedding-3-small" } } ] }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'dimension' in semantic cache plugin to fail validation") } } // ============================================================================= // OTEL Plugin Config Required Fields Tests // ============================================================================= func TestValidateConfigSchema_OtelPlugin_Valid(t *testing.T) { // Valid OTEL plugin with all required fields: collector_url, trace_type, protocol validConfig := `{ "plugins": [ { "enabled": true, "name": "otel", "config": { "collector_url": "http://localhost:4318", "trace_type": "genai_extension", "protocol": "http" } } ] }` err := ValidateConfigSchema([]byte(validConfig), loadLocalSchema(t)) if err != nil { t.Errorf("expected valid OTEL plugin config to pass validation, got error: %v", err) } } func TestValidateConfigSchema_OtelPlugin_MissingCollectorUrl(t *testing.T) { // Missing required field: collector_url invalidConfig := `{ "plugins": [ { "enabled": true, "name": "otel", "config": { "trace_type": "genai_extension", "protocol": "http" } } ] }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'collector_url' in OTEL plugin to fail validation") } } func TestValidateConfigSchema_OtelPlugin_MissingTraceType(t *testing.T) { // Missing required field: trace_type invalidConfig := `{ "plugins": [ { "enabled": true, "name": "otel", "config": { "collector_url": "http://localhost:4318", "protocol": "http" } } ] }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'trace_type' in OTEL plugin to fail validation") } } func TestValidateConfigSchema_OtelPlugin_MissingProtocol(t *testing.T) { // Missing required field: protocol invalidConfig := `{ "plugins": [ { "enabled": true, "name": "otel", "config": { "collector_url": "http://localhost:4318", "trace_type": "genai_extension" } } ] }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'protocol' in OTEL plugin to fail validation") } } // ============================================================================= // Maxim Plugin Config Required Fields Tests // ============================================================================= func TestValidateConfigSchema_MaximPlugin_Valid(t *testing.T) { // Valid Maxim plugin with required field: api_key validConfig := `{ "plugins": [ { "enabled": true, "name": "maxim", "config": { "api_key": "maxim-api-key-12345" } } ] }` err := ValidateConfigSchema([]byte(validConfig), loadLocalSchema(t)) if err != nil { t.Errorf("expected valid Maxim plugin config to pass validation, got error: %v", err) } } func TestValidateConfigSchema_MaximPlugin_MissingApiKey(t *testing.T) { // Missing required field: api_key invalidConfig := `{ "plugins": [ { "enabled": true, "name": "maxim", "config": { "log_repo_id": "my-log-repo" } } ] }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'api_key' in Maxim plugin to fail validation") } } // ============================================================================= // Azure Key Config Required Fields Tests // Note: Azure provider uses a special key schema that extends base_key // The azure_key_config is only valid within the azure provider's keys array // ============================================================================= func TestValidateConfigSchema_AzureKeyConfig_MissingEndpoint(t *testing.T) { // Missing required field: endpoint in azure_key_config // This test validates that when azure_key_config is present, endpoint is required invalidConfig := `{ "providers": { "azure": { "keys": [ { "name": "azure-key", "value": "azure-api-key", "weight": 1.0, "azure_key_config": { "api_version": "2024-02-15-preview" } } ] } } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'endpoint' in Azure key config to fail validation") } } func TestValidateConfigSchema_AzureKeyConfig_MissingApiVersion(t *testing.T) { // Missing required field: api_version in azure_key_config invalidConfig := `{ "providers": { "azure": { "keys": [ { "name": "azure-key", "value": "azure-api-key", "weight": 1.0, "azure_key_config": { "endpoint": "https://my-resource.openai.azure.com" } } ] } } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'api_version' in Azure key config to fail validation") } } // ============================================================================= // Vertex Key Config Required Fields Tests // Note: Vertex provider uses a special key schema that extends base_key // ============================================================================= func TestValidateConfigSchema_VertexKeyConfig_MissingProjectId(t *testing.T) { // Missing required field: project_id in vertex_key_config invalidConfig := `{ "providers": { "vertex": { "keys": [ { "name": "vertex-key", "value": "vertex-api-key", "weight": 1.0, "vertex_key_config": { "region": "us-central1" } } ] } } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'project_id' in Vertex key config to fail validation") } } func TestValidateConfigSchema_VertexKeyConfig_MissingRegion(t *testing.T) { // Missing required field: region in vertex_key_config invalidConfig := `{ "providers": { "vertex": { "keys": [ { "name": "vertex-key", "value": "vertex-api-key", "weight": 1.0, "vertex_key_config": { "project_id": "my-gcp-project" } } ] } } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'region' in Vertex key config to fail validation") } } // ============================================================================= // Bedrock Key Config Required Fields Tests // Note: Bedrock provider uses a special key schema that extends base_key // ============================================================================= func TestValidateConfigSchema_BedrockKeyConfig_MissingRegion(t *testing.T) { // Missing required field: region in bedrock_key_config invalidConfig := `{ "providers": { "bedrock": { "keys": [ { "name": "bedrock-key", "value": "bedrock-api-key", "weight": 1.0, "bedrock_key_config": { "access_key": "AKIAIOSFODNN7EXAMPLE" } } ] } } }` err := ValidateConfigSchema([]byte(invalidConfig), loadLocalSchema(t)) if err == nil { t.Error("expected config missing 'region' in Bedrock key config to fail validation") } } // ============================================================================= // Guardrails Config Tests // Note: Guardrails is an enterprise feature. The guardrails_config schema // validation is tested but the detailed rules/providers validation is only // available in the enterprise version. The public schema validates that the // guardrails_config exists but doesn't expose detailed structure. // ============================================================================= // Guardrails tests are skipped for the public schema as guardrails_config // is an enterprise feature with a different schema structure. // Enterprise-specific tests should be added to the enterprise test suite.