use client_core::mysql_executor::{MySqlConfig, MySqlExecutor};
use sqlx::mysql::MySqlPoolOptions;
use std::path::Path;
const TEST_DB: &str = "executor_integration_test";
#[tokio::test]
async fn test_mysql_executor_integration() {
println!("🔧 1. 设置测试环境...");
let cargo_manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
let compose_path_buf = Path::new(&cargo_manifest_dir).join("fixtures/docker-compose.yml");
let compose_path = compose_path_buf.to_str().unwrap();
let env_path_buf = Path::new(&cargo_manifest_dir).join("fixtures/.env");
let env_path = env_path_buf.to_str().unwrap();
println!("🔧 2. 获取 MySQL 配置...");
let config = MySqlConfig::for_container(Some(compose_path), Some(env_path))
.await
.expect("无法从容器获取 MySQL 配置");
println!("🔧 2.1. 使用 root 用户确保测试用户拥有权限...");
let mut root_config = config.clone();
root_config.user = "root".to_string();
root_config.password = "root".to_string();
let root_executor = MySqlExecutor::new(root_config);
let grant_sql = format!("GRANT ALL PRIVILEGES ON *.* TO '{}'@'%'", &config.user);
root_executor
.execute_single(&grant_sql)
.await
.expect("使用 root 用户授权失败");
let flush_sql = "FLUSH PRIVILEGES";
root_executor
.execute_single(flush_sql)
.await
.expect("刷新权限失败");
println!("✅ 权限已自动授予。");
let executor = MySqlExecutor::new(config.clone());
println!("🧹 3. 清理并创建测试数据库 '{TEST_DB}'...");
let drop_db_sql = format!("DROP DATABASE IF EXISTS `{TEST_DB}`");
executor.execute_single(&drop_db_sql).await.ok();
let create_db_sql = format!("CREATE DATABASE `{TEST_DB}`");
executor
.execute_single(&create_db_sql)
.await
.expect("创建测试数据库失败");
println!("🔧 4. 在 '{TEST_DB}' 数据库中执行 SQL 脚本...");
let sql_script = format!(
"USE `{TEST_DB}`;
{SQL_CREATE_TABLE}\n{SQL_ADD_COLUMN_AND_INDEX}\n{SQL_INSERT_DATA}\n{SQL_DROP_INDEX_AND_COLUMN}"
);
executor
.execute_diff_sql(&sql_script)
.await
.expect("执行 SQL 脚本失败");
println!("🔧 5. 连接数据库并验证结果...");
let db_url = format!(
"mysql://{}:{}@{}:{}/{}",
config.user, config.password, config.host, config.port, TEST_DB
);
let pool = MySqlPoolOptions::new()
.max_connections(1)
.connect(&db_url)
.await
.expect("无法连接到测试数据库");
let columns: Vec<(String,)> = sqlx::query_as("SHOW COLUMNS FROM users WHERE Field = 'status'")
.fetch_all(&pool)
.await
.expect("查询表结构失败");
assert!(columns.is_empty(), "'status' 列未被成功删除");
let indexes: Vec<(String,)> =
sqlx::query_as("SHOW INDEX FROM users WHERE Key_name = 'idx_email'")
.fetch_all(&pool)
.await
.expect("查询索引失败");
assert!(indexes.is_empty(), "'idx_email' 索引未被成功删除");
let count: (i64,) = sqlx::query_as("SELECT COUNT(*) FROM users")
.fetch_one(&pool)
.await
.expect("查询数据失败");
assert_eq!(count.0, 1, "数据插入验证失败");
println!("✅ 集成测试成功!");
}
const SQL_CREATE_TABLE: &str = r#"
CREATE TABLE `users` (
`id` bigint NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
"#;
const SQL_ADD_COLUMN_AND_INDEX: &str = r#"
ALTER TABLE `users`
ADD COLUMN `email` varchar(100) NOT NULL AFTER `username`,
ADD COLUMN `status` tinyint(1) DEFAULT 1,
ADD INDEX `idx_email` (`email`);
"#;
const SQL_INSERT_DATA: &str = r#"
INSERT INTO `users` (username, email, status) VALUES ('test_user', 'test@example.com', 1);
"#;
const SQL_DROP_INDEX_AND_COLUMN: &str = r#"
ALTER TABLE `users`
DROP INDEX `idx_email`,
DROP COLUMN `status`;
"#;