package repository import ( "database/sql" "fmt" "os" "strings" "testing" "cmautobuy/admin/config" ) // TestMySQLMigrate_真实MySQL8 只在显式提供隔离测试库时运行。 // 库名必须以 _test 结尾,防止测试清理误碰生产库。 func TestMySQLMigrate_真实MySQL8(t *testing.T) { if os.Getenv("CMAUTOBUY_MYSQL_TEST") != "1" { t.Skip("未启用真实 MySQL 8 集成测试") } cfg, err := config.LoadDatabaseFromEnv() if err != nil { t.Fatal(err) } if !strings.HasSuffix(cfg.Name, "_test") { t.Fatalf("拒绝清理非测试数据库 %q:库名必须以 _test 结尾", cfg.Name) } db, err := OpenMySQL(cfg) if err != nil { t.Fatal(err) } defer db.Close() cleanMySQLTestSchema(t, db) defer cleanMySQLTestSchema(t, db) if err := MigrateMySQL(db); err != nil { t.Fatalf("首次建立 MySQL schema 失败: %v", err) } if err := MigrateMySQL(db); err != nil { t.Fatalf("重复迁移应该无副作用: %v", err) } var version int if err := db.QueryRow(`SELECT MAX(version) FROM schema_migrations`).Scan(&version); err != nil { t.Fatal(err) } if version != mysqlSchemaVersion { t.Fatalf("schema 版本=%d,期望 %d", version, mysqlSchemaVersion) } } func cleanMySQLTestSchema(t *testing.T, db *sql.DB) { t.Helper() rows, err := db.Query(`SELECT table_name FROM information_schema.tables WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE'`) if err != nil { t.Fatal(err) } var tables []string for rows.Next() { var table string if err := rows.Scan(&table); err != nil { rows.Close() t.Fatal(err) } tables = append(tables, table) } if err := rows.Close(); err != nil { t.Fatal(err) } if _, err := db.Exec(`SET FOREIGN_KEY_CHECKS = 0`); err != nil { t.Fatal(err) } defer db.Exec(`SET FOREIGN_KEY_CHECKS = 1`) for _, table := range tables { // 表名只来自当前 _test 数据库的 information_schema,并对反引号转义。 quoted := "`" + strings.ReplaceAll(table, "`", "``") + "`" if _, err := db.Exec("DROP TABLE " + quoted); err != nil { t.Fatal(fmt.Errorf("清理 MySQL 测试表 %s 失败: %w", table, err)) } } }