package server import ( "context" "testing" "github.com/maximhq/bifrost/core/schemas" "github.com/maximhq/bifrost/framework/configstore" "github.com/maximhq/bifrost/transports/bifrost-http/lib" ) // TestConfig is a sample config struct for testing type TestConfig struct { Name string `json:"name"` Enabled bool `json:"enabled"` Count int `json:"count"` } type updateStatusOnlyConfigStore struct { configstore.ConfigStore calls []schemas.KeyStatus } type noopTestLogger struct{} func (noopTestLogger) Debug(string, ...any) {} func (noopTestLogger) Info(string, ...any) {} func (noopTestLogger) Warn(string, ...any) {} func (noopTestLogger) Error(string, ...any) {} func (noopTestLogger) Fatal(string, ...any) {} func (noopTestLogger) SetLevel(schemas.LogLevel) {} func (noopTestLogger) SetOutputType(schemas.LoggerOutputType) {} func (noopTestLogger) LogHTTPRequest(schemas.LogLevel, string) schemas.LogEventBuilder { return schemas.NoopLogEvent } func (s *updateStatusOnlyConfigStore) UpdateStatus(ctx context.Context, provider schemas.ModelProvider, keyID string, status, errorMsg string) error { s.calls = append(s.calls, schemas.KeyStatus{ Provider: provider, KeyID: keyID, Status: schemas.KeyStatusType(status), Error: &schemas.BifrostError{Error: &schemas.ErrorField{Message: errorMsg}}, }) return nil } func TestUpdateKeyStatus_KeylessProviderUpdatesProviderStatusInMemory(t *testing.T) { prevLogger := logger logger = noopTestLogger{} defer func() { logger = prevLogger }() store := &updateStatusOnlyConfigStore{} server := &BifrostHTTPServer{ Config: &lib.Config{ ConfigStore: store, Providers: map[schemas.ModelProvider]configstore.ProviderConfig{ "mock-openai": { CustomProviderConfig: &schemas.CustomProviderConfig{IsKeyLess: true}, Status: "unknown", }, }, }, } server.updateKeyStatus(context.Background(), []schemas.KeyStatus{{ Provider: "mock-openai", KeyID: "", Status: schemas.KeyStatusListModelsFailed, Error: &schemas.BifrostError{Error: &schemas.ErrorField{Message: "preview missing model"}}, }}) provider := server.Config.Providers["mock-openai"] if provider.Status != string(schemas.KeyStatusListModelsFailed) { t.Fatalf("expected provider status %q, got %q", schemas.KeyStatusListModelsFailed, provider.Status) } if provider.Description != "preview missing model" { t.Fatalf("expected provider description to be updated, got %q", provider.Description) } if len(store.calls) != 1 { t.Fatalf("expected one status update call, got %d", len(store.calls)) } if store.calls[0].Provider != "mock-openai" || store.calls[0].KeyID != "" { t.Fatalf("expected provider-level status update, got provider=%q keyID=%q", store.calls[0].Provider, store.calls[0].KeyID) } } func TestUpdateKeyStatus_EmptyKeyIDDoesNotOverwriteKeyedProviderStatus(t *testing.T) { prevLogger := logger logger = noopTestLogger{} defer func() { logger = prevLogger }() store := &updateStatusOnlyConfigStore{} server := &BifrostHTTPServer{ Config: &lib.Config{ ConfigStore: store, Providers: map[schemas.ModelProvider]configstore.ProviderConfig{ "openai": { Keys: []schemas.Key{{ID: "key-1"}}, Status: "healthy", }, }, }, } server.updateKeyStatus(context.Background(), []schemas.KeyStatus{{ Provider: "openai", KeyID: "", Status: schemas.KeyStatusListModelsFailed, Error: &schemas.BifrostError{Error: &schemas.ErrorField{Message: "malformed status"}}, }}) provider := server.Config.Providers["openai"] if provider.Status != "healthy" { t.Fatalf("expected keyed provider status to remain unchanged, got %q", provider.Status) } if provider.Description != "" { t.Fatalf("expected keyed provider description to remain unchanged, got %q", provider.Description) } if len(store.calls) != 1 { t.Fatalf("expected one status update call, got %d", len(store.calls)) } if store.calls[0].Provider != "openai" || store.calls[0].KeyID != "" { t.Fatalf("expected DB status update to retain empty key ID, got provider=%q keyID=%q", store.calls[0].Provider, store.calls[0].KeyID) } } func TestMarshalPluginConfig_WithPointerType(t *testing.T) { // Test case 1: source is already *T expected := &TestConfig{ Name: "test-plugin", Enabled: true, Count: 42, } result, err := MarshalPluginConfig[TestConfig](expected) if err != nil { t.Fatalf("Expected no error, got: %v", err) } if result != expected { t.Errorf("Expected same pointer, got different pointer") } if result.Name != expected.Name { t.Errorf("Expected Name=%s, got %s", expected.Name, result.Name) } if result.Enabled != expected.Enabled { t.Errorf("Expected Enabled=%v, got %v", expected.Enabled, result.Enabled) } if result.Count != expected.Count { t.Errorf("Expected Count=%d, got %d", expected.Count, result.Count) } } func TestMarshalPluginConfig_WithMap(t *testing.T) { // Test case 2: source is map[string]any configMap := map[string]any{ "name": "test-plugin", "enabled": true, "count": 42, } result, err := MarshalPluginConfig[TestConfig](configMap) if err != nil { t.Fatalf("Expected no error, got: %v", err) } if result == nil { t.Fatal("Expected non-nil result") } if result.Name != "test-plugin" { t.Errorf("Expected Name=test-plugin, got %s", result.Name) } if result.Enabled != true { t.Errorf("Expected Enabled=true, got %v", result.Enabled) } if result.Count != 42 { t.Errorf("Expected Count=42, got %d", result.Count) } } func TestMarshalPluginConfig_WithString(t *testing.T) { // Test case 3: source is string (JSON) configStr := `{"name":"test-plugin","enabled":true,"count":42}` result, err := MarshalPluginConfig[TestConfig](configStr) if err != nil { t.Fatalf("Expected no error, got: %v", err) } if result == nil { t.Fatal("Expected non-nil result") } if result.Name != "test-plugin" { t.Errorf("Expected Name=test-plugin, got %s", result.Name) } if result.Enabled != true { t.Errorf("Expected Enabled=true, got %v", result.Enabled) } if result.Count != 42 { t.Errorf("Expected Count=42, got %d", result.Count) } } func TestMarshalPluginConfig_WithInvalidType(t *testing.T) { // Test case 4: source is invalid type (should return error) invalidSource := 12345 result, err := MarshalPluginConfig[TestConfig](invalidSource) if err == nil { t.Fatal("Expected error for invalid type, got nil") } if result != nil { t.Errorf("Expected nil result for invalid type, got %v", result) } expectedError := "invalid config type" if err.Error() != expectedError { t.Errorf("Expected error message '%s', got '%s'", expectedError, err.Error()) } } func TestMarshalPluginConfig_WithInvalidJSONString(t *testing.T) { // Test case 5: source is string but invalid JSON invalidJSON := `{"name":"test-plugin","enabled":true,count:42}` // missing quotes around count result, err := MarshalPluginConfig[TestConfig](invalidJSON) if err == nil { t.Fatal("Expected error for invalid JSON, got nil") } if result != nil { t.Errorf("Expected nil result for invalid JSON, got %v", result) } } func TestMarshalPluginConfig_WithInvalidMapData(t *testing.T) { // Test case 6: source is map but contains invalid data types configMap := map[string]any{ "name": "test-plugin", "enabled": "not-a-boolean", // wrong type "count": 42, } result, err := MarshalPluginConfig[TestConfig](configMap) if err == nil { t.Fatal("Expected error for invalid map data, got nil") } if result != nil { t.Errorf("Expected nil result for invalid map data, got %v", result) } } func TestMarshalPluginConfig_WithEmptyMap(t *testing.T) { // Test case 7: source is empty map (should work, return zero values) configMap := map[string]any{} result, err := MarshalPluginConfig[TestConfig](configMap) if err != nil { t.Fatalf("Expected no error for empty map, got: %v", err) } if result == nil { t.Fatal("Expected non-nil result") } // All fields should have zero values if result.Name != "" { t.Errorf("Expected empty Name, got %s", result.Name) } if result.Enabled != false { t.Errorf("Expected Enabled=false, got %v", result.Enabled) } if result.Count != 0 { t.Errorf("Expected Count=0, got %d", result.Count) } } func TestMarshalPluginConfig_WithEmptyString(t *testing.T) { // Test case 8: source is empty string (should fail as invalid JSON) configStr := "" result, err := MarshalPluginConfig[TestConfig](configStr) if err == nil { t.Fatal("Expected error for empty string, got nil") } if result != nil { t.Errorf("Expected nil result for empty string, got %v", result) } } func TestMarshalPluginConfig_WithNil(t *testing.T) { // Test case 9: source is nil (should return error as invalid type) result, err := MarshalPluginConfig[TestConfig](nil) if err == nil { t.Fatal("Expected error for nil source, got nil") } if result != nil { t.Errorf("Expected nil result for nil source, got %v", result) } } // Benchmark tests func BenchmarkMarshalPluginConfig_WithPointerType(b *testing.B) { config := &TestConfig{ Name: "test-plugin", Enabled: true, Count: 42, } b.ResetTimer() for i := 0; i < b.N; i++ { _, _ = MarshalPluginConfig[TestConfig](config) } } func BenchmarkMarshalPluginConfig_WithMap(b *testing.B) { configMap := map[string]any{ "name": "test-plugin", "enabled": true, "count": 42, } b.ResetTimer() for i := 0; i < b.N; i++ { _, _ = MarshalPluginConfig[TestConfig](configMap) } } func BenchmarkMarshalPluginConfig_WithString(b *testing.B) { configStr := `{"name":"test-plugin","enabled":true,"count":42}` b.ResetTimer() for i := 0; i < b.N; i++ { _, _ = MarshalPluginConfig[TestConfig](configStr) } } // Complex config for additional testing type ComplexConfig struct { Settings map[string]string `json:"settings"` Tags []string `json:"tags"` Metadata map[string]any `json:"metadata"` Nested *TestConfig `json:"nested"` } func TestMarshalPluginConfig_WithComplexType(t *testing.T) { // Test with a more complex nested structure configMap := map[string]any{ "settings": map[string]any{ "key1": "value1", "key2": "value2", }, "tags": []any{"tag1", "tag2", "tag3"}, "metadata": map[string]any{ "version": "1.0.0", "author": "test", }, "nested": map[string]any{ "name": "nested-config", "enabled": true, "count": 10, }, } result, err := MarshalPluginConfig[ComplexConfig](configMap) if err != nil { t.Fatalf("Expected no error, got: %v", err) } if result == nil { t.Fatal("Expected non-nil result") } if len(result.Settings) != 2 { t.Errorf("Expected 2 settings, got %d", len(result.Settings)) } if len(result.Tags) != 3 { t.Errorf("Expected 3 tags, got %d", len(result.Tags)) } if result.Nested == nil { t.Fatal("Expected non-nil nested config") } if result.Nested.Name != "nested-config" { t.Errorf("Expected nested name=nested-config, got %s", result.Nested.Name) } }