Move database-specific SQL tests into per-database subdirectories

Restructure tests so files that only work on a single database engine
are
organized under `database-specific/<engine>/` instead of using long
`_no...`
suffixes. Add a dedicated test that runs these files only when the
current
database matches, and simplify the generic test runner by extracting
shared
execution logic.
This commit is contained in:
lovasoa
2026-08-23 09:47:58 +02:00
parent 08988a9c64
commit 5c288b0ac9
6 changed files with 46 additions and 6 deletions
+10 -1
View File
@@ -15,4 +15,13 @@ and the rest of the file name. Files may include `nosqlite`, `nomssql`,
Files that only validate data-processing functions should live here. They must
return rows with an `actual` column plus either `expected` (exact match) or
`expected_contains` (substring match). Tests in this directory are fetched as
JSON and validated row by row.
JSON and validated row by row.
### `data/database-specific/`
Files that only work on a single database engine (because they use
engine-specific SQL syntax) live in a subdirectory named after that database
(`sqlite`, `postgres`, `mysql`, `mssql`, `oracle`, `duckdb`, `snowflake`,
`generic`). They are run by a separate test, only when the current database
matches. Unlike the other directories, their file names do not need `_no...`
suffixes to exclude incompatible backends.
+36 -5
View File
@@ -8,14 +8,32 @@ use tokio::task::JoinHandle;
#[actix_web::test]
async fn run_all_sql_test_files() {
let app_data = crate::common::make_app_data().await;
let test_files = get_sql_test_cases();
run_sql_test_cases(&app_data, get_sql_test_cases()).await;
}
/// Runs the SQL test files in `database-specific/<current database>/`.
/// These files use syntax that only works on a single database engine, so they
/// cannot be part of the generic `run_all_sql_test_files` test.
#[actix_web::test]
async fn run_database_specific_sql_test_files() {
let app_data = crate::common::make_app_data().await;
let db_type = database_type_name(&app_data);
run_sql_test_cases(&app_data, get_database_specific_test_cases(&db_type)).await;
}
async fn run_sql_test_cases(
app_data: &actix_web::web::Data<AppState>,
test_files: Vec<SqlTestCase>,
) {
if test_files.is_empty() {
return;
}
let (shutdown_tx, shutdown_rx) = oneshot::channel();
let (echo_handle, port) = crate::common::start_echo_server(shutdown_rx);
wait_for_echo_server(port).await;
for test_file in test_files {
run_sql_test(&test_file, &app_data, &echo_handle, port).await;
run_sql_test(&test_file, app_data, &echo_handle, port).await;
}
let _ = shutdown_tx.send(());
@@ -63,9 +81,22 @@ fn get_sql_test_cases() -> Vec<SqlTestCase> {
tests
}
fn get_database_specific_test_cases(db_type: &str) -> Vec<SqlTestCase> {
read_sql_tests_in_dir(
&format!("tests/sql_test_files/data/database-specific/{db_type}"),
SqlTestFormat::Json,
)
}
fn database_type_name(app_data: &actix_web::web::Data<AppState>) -> String {
format!("{:?}", app_data.db.info.database_type).to_lowercase()
}
fn read_sql_tests_in_dir(dir: &str, format: SqlTestFormat) -> Vec<SqlTestCase> {
std::fs::read_dir(dir)
.unwrap()
let Ok(entries) = std::fs::read_dir(dir) else {
return Vec::new(); // no tests in this directory (e.g. no database-specific tests for this database)
};
entries
.filter_map(|e| {
let path = e.ok()?.path();
if path.is_dir() || path.extension()? != "sql" {
@@ -86,7 +117,7 @@ async fn run_sql_test(
let test_file_path = test_file.to_string_lossy().replace('\\', "/");
let stem = test_file.file_stem().unwrap().to_str().unwrap();
let db_type = format!("{:?}", app_data.db.info.database_type).to_lowercase();
let db_type = database_type_name(app_data);
if stem.contains(&format!("_no{db_type}")) {
println!("Skipped {}: {}", test_file.display(), db_type);
return;