- 新增 backend/tests/mysql/ 目录,包含 Docker Compose 配置和测试文件 - 新增 Makefile 命令: test-mysql, test-mysql-up, test-mysql-down, test-mysql-quick - 使用 build tag 控制测试启用,默认不运行 - 测试覆盖: 迁移正确性、外键约束、UNIQUE 约束、并发写入 - 发现 statsRepo.Record 存在并发 bug(检查-然后-操作竞态条件)
127 lines
4.0 KiB
Go
127 lines
4.0 KiB
Go
//go:build mysql
|
|
|
|
package mysql
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestMigration_TablesExist(t *testing.T) {
|
|
db := SetupMySQLTestDB(t)
|
|
|
|
var tables []string
|
|
err := db.Raw("SHOW TABLES").Scan(&tables).Error
|
|
require.NoError(t, err)
|
|
|
|
expectedTables := []string{"providers", "models", "usage_stats"}
|
|
for _, expected := range expectedTables {
|
|
assert.Contains(t, tables, expected, "表 %s 应存在", expected)
|
|
}
|
|
}
|
|
|
|
func TestMigration_TableColumns(t *testing.T) {
|
|
db := SetupMySQLTestDB(t)
|
|
|
|
t.Run("providers 表字段", func(t *testing.T) {
|
|
var columns []struct {
|
|
Field string
|
|
Type string
|
|
Null string
|
|
}
|
|
err := db.Raw("SHOW COLUMNS FROM providers").Scan(&columns).Error
|
|
require.NoError(t, err)
|
|
|
|
columnMap := make(map[string]string)
|
|
for _, col := range columns {
|
|
columnMap[col.Field] = col.Type
|
|
}
|
|
|
|
assert.Contains(t, columnMap["id"], "varchar", "id 应为 VARCHAR 类型")
|
|
assert.Contains(t, columnMap["name"], "varchar", "name 应为 VARCHAR 类型")
|
|
assert.Contains(t, columnMap["api_key"], "varchar", "api_key 应为 VARCHAR 类型")
|
|
assert.Contains(t, columnMap["base_url"], "varchar", "base_url 应为 VARCHAR 类型")
|
|
assert.Contains(t, columnMap["protocol"], "varchar", "protocol 应为 VARCHAR 类型")
|
|
assert.Contains(t, columnMap["enabled"], "tinyint", "enabled 应为 TINYINT (BOOLEAN) 类型")
|
|
assert.Contains(t, columnMap["created_at"], "datetime", "created_at 应为 DATETIME 类型")
|
|
assert.Contains(t, columnMap["updated_at"], "datetime", "updated_at 应为 DATETIME 类型")
|
|
})
|
|
|
|
t.Run("models 表字段", func(t *testing.T) {
|
|
var columns []struct {
|
|
Field string
|
|
Type string
|
|
}
|
|
err := db.Raw("SHOW COLUMNS FROM models").Scan(&columns).Error
|
|
require.NoError(t, err)
|
|
|
|
columnMap := make(map[string]string)
|
|
for _, col := range columns {
|
|
columnMap[col.Field] = col.Type
|
|
}
|
|
|
|
assert.Contains(t, columnMap["id"], "varchar", "id 应为 VARCHAR 类型")
|
|
assert.Contains(t, columnMap["provider_id"], "varchar", "provider_id 应为 VARCHAR 类型")
|
|
assert.Contains(t, columnMap["model_name"], "varchar", "model_name 应为 VARCHAR 类型")
|
|
assert.Contains(t, columnMap["enabled"], "tinyint", "enabled 应为 TINYINT (BOOLEAN) 类型")
|
|
assert.Contains(t, columnMap["created_at"], "datetime", "created_at 应为 DATETIME 类型")
|
|
})
|
|
|
|
t.Run("usage_stats 表字段", func(t *testing.T) {
|
|
var columns []struct {
|
|
Field string
|
|
Type string
|
|
}
|
|
err := db.Raw("SHOW COLUMNS FROM usage_stats").Scan(&columns).Error
|
|
require.NoError(t, err)
|
|
|
|
columnMap := make(map[string]string)
|
|
for _, col := range columns {
|
|
columnMap[col.Field] = col.Type
|
|
}
|
|
|
|
assert.Contains(t, columnMap["id"], "int", "id 应为 INT 类型")
|
|
assert.Contains(t, columnMap["provider_id"], "varchar", "provider_id 应为 VARCHAR 类型")
|
|
assert.Contains(t, columnMap["model_name"], "varchar", "model_name 应为 VARCHAR 类型")
|
|
assert.Contains(t, columnMap["request_count"], "int", "request_count 应为 INT 类型")
|
|
assert.Contains(t, columnMap["date"], "date", "date 应为 DATE 类型")
|
|
})
|
|
}
|
|
|
|
func TestMigration_IndexesExist(t *testing.T) {
|
|
db := SetupMySQLTestDB(t)
|
|
|
|
t.Run("models 表索引", func(t *testing.T) {
|
|
var indexes []struct {
|
|
KeyName string
|
|
}
|
|
err := db.Raw("SHOW INDEX FROM models").Scan(&indexes).Error
|
|
require.NoError(t, err)
|
|
|
|
indexMap := make(map[string]bool)
|
|
for _, idx := range indexes {
|
|
indexMap[idx.KeyName] = true
|
|
}
|
|
|
|
assert.True(t, indexMap["idx_models_provider_id"], "idx_models_provider_id 索引应存在")
|
|
assert.True(t, indexMap["idx_models_model_name"], "idx_models_model_name 索引应存在")
|
|
})
|
|
|
|
t.Run("usage_stats 表索引", func(t *testing.T) {
|
|
var indexes []struct {
|
|
KeyName string
|
|
}
|
|
err := db.Raw("SHOW INDEX FROM usage_stats").Scan(&indexes).Error
|
|
require.NoError(t, err)
|
|
|
|
indexMap := make(map[string]bool)
|
|
for _, idx := range indexes {
|
|
indexMap[idx.KeyName] = true
|
|
}
|
|
|
|
assert.True(t, indexMap["idx_usage_stats_provider_model_date"], "idx_usage_stats_provider_model_date 索引应存在")
|
|
})
|
|
}
|