//go:build mysql package mysql import ( "errors" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gorm.io/gorm" "nex/backend/internal/config" ) func TestConstraint_ForeignKeyEnforced(t *testing.T) { db := SetupMySQLTestDB(t) model := config.Model{ ID: "test-model-id", ProviderID: "non-existent-provider", ModelName: "gpt-4", Enabled: true, } err := db.Create(&model).Error assert.Error(t, err, "创建 model 时 provider_id 不存在应失败") assert.Contains(t, err.Error(), "foreign key constraint", "错误应为外键约束错误") } func TestConstraint_CascadeDelete(t *testing.T) { db := SetupMySQLTestDB(t) provider := config.Provider{ ID: "test-provider-cascade", Name: "Test Provider", APIKey: "test-key", BaseURL: "https://test.com", Enabled: true, } err := db.Create(&provider).Error require.NoError(t, err, "创建 provider 应成功") model := config.Model{ ID: "test-model-cascade", ProviderID: provider.ID, ModelName: "gpt-4", Enabled: true, } err = db.Create(&model).Error require.NoError(t, err, "创建 model 应成功") err = db.Delete(&provider).Error require.NoError(t, err, "删除 provider 应成功") var count int64 err = db.Model(&config.Model{}).Where("provider_id = ?", provider.ID).Count(&count).Error require.NoError(t, err) assert.Equal(t, int64(0), count, "删除 provider 后其 models 应被级联删除") } func TestConstraint_UniqueProviderModel(t *testing.T) { db := SetupMySQLTestDB(t) provider := config.Provider{ ID: "test-provider-unique", Name: "Test Provider", APIKey: "test-key", BaseURL: "https://test.com", Enabled: true, } err := db.Create(&provider).Error require.NoError(t, err, "创建 provider 应成功") model1 := config.Model{ ID: "test-model-unique-1", ProviderID: provider.ID, ModelName: "gpt-4", Enabled: true, } err = db.Create(&model1).Error require.NoError(t, err, "创建第一个 model 应成功") model2 := config.Model{ ID: "test-model-unique-2", ProviderID: provider.ID, ModelName: "gpt-4", Enabled: true, } err = db.Create(&model2).Error assert.Error(t, err, "创建相同 (provider_id, model_name) 的 model 应失败") assert.True(t, errors.Is(err, gorm.ErrDuplicatedKey) || (err != nil && (err.Error() == "Error 1062" || containsDuplicateError(err.Error()))), "错误应为唯一约束错误") } func TestConstraint_UniqueUsageStats(t *testing.T) { db := SetupMySQLTestDB(t) today := time.Now().Format("2006-01-02") todayTime, _ := time.Parse("2006-01-02", today) providerID := "test-provider-unique-stats" stats1 := config.UsageStats{ ProviderID: providerID, ModelName: "gpt-4", RequestCount: 10, Date: todayTime, } err := db.Create(&stats1).Error require.NoError(t, err, "创建第一个 usage_stats 应成功") stats2 := config.UsageStats{ ProviderID: providerID, ModelName: "gpt-4", RequestCount: 20, Date: todayTime, } err = db.Create(&stats2).Error assert.Error(t, err, "创建相同 (provider_id, model_name, date) 的 usage_stats 应失败") assert.True(t, errors.Is(err, gorm.ErrDuplicatedKey) || (err != nil && (err.Error() == "Error 1062" || containsDuplicateError(err.Error()))), "错误应为唯一约束错误") } func containsDuplicateError(errStr string) bool { return len(errStr) > 0 && (errStr[0:8] == "Error 10" || errStr[0:5] == "Dupli") }