From 5c288b0ac9eda29f6ea676c22c13f2047822c108 Mon Sep 17 00:00:00 2001 From: lovasoa Date: Sun, 23 Aug 2026 09:47:58 +0200 Subject: [PATCH] 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//` 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. --- tests/sql_test_files/README.md | 11 ++++- .../mssql/variable_mssql_contains.sql} | 0 .../mssql/variable_unicode.sql} | 0 .../mysql/variable_limit_offset.sql} | 0 .../sqlite/set_multiple_rows.sql} | 0 tests/sql_test_files/mod.rs | 41 ++++++++++++++++--- 6 files changed, 46 insertions(+), 6 deletions(-) rename tests/sql_test_files/data/{variable_mssql_contains_noduckdb_nogeneric_nomysql_nooracle_nopostgres_nosnowflake_nosqlite.sql => database-specific/mssql/variable_mssql_contains.sql} (100%) rename tests/sql_test_files/data/{variable_unicode_noduckdb_nogeneric_nomysql_nooracle_nopostgres_nosnowflake_nosqlite.sql => database-specific/mssql/variable_unicode.sql} (100%) rename tests/sql_test_files/data/{variable_limit_offset_noduckdb_nogeneric_nomssql_nooracle_nopostgres_nosnowflake_nosqlite.sql => database-specific/mysql/variable_limit_offset.sql} (100%) rename tests/sql_test_files/data/{set_multiple_rows_noduckdb_nogeneric_nomssql_nomysql_nooracle_nopostgres_nosnowflake.sql => database-specific/sqlite/set_multiple_rows.sql} (100%) diff --git a/tests/sql_test_files/README.md b/tests/sql_test_files/README.md index f28b3722..6e23b124 100644 --- a/tests/sql_test_files/README.md +++ b/tests/sql_test_files/README.md @@ -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. \ No newline at end of file +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. \ No newline at end of file diff --git a/tests/sql_test_files/data/variable_mssql_contains_noduckdb_nogeneric_nomysql_nooracle_nopostgres_nosnowflake_nosqlite.sql b/tests/sql_test_files/data/database-specific/mssql/variable_mssql_contains.sql similarity index 100% rename from tests/sql_test_files/data/variable_mssql_contains_noduckdb_nogeneric_nomysql_nooracle_nopostgres_nosnowflake_nosqlite.sql rename to tests/sql_test_files/data/database-specific/mssql/variable_mssql_contains.sql diff --git a/tests/sql_test_files/data/variable_unicode_noduckdb_nogeneric_nomysql_nooracle_nopostgres_nosnowflake_nosqlite.sql b/tests/sql_test_files/data/database-specific/mssql/variable_unicode.sql similarity index 100% rename from tests/sql_test_files/data/variable_unicode_noduckdb_nogeneric_nomysql_nooracle_nopostgres_nosnowflake_nosqlite.sql rename to tests/sql_test_files/data/database-specific/mssql/variable_unicode.sql diff --git a/tests/sql_test_files/data/variable_limit_offset_noduckdb_nogeneric_nomssql_nooracle_nopostgres_nosnowflake_nosqlite.sql b/tests/sql_test_files/data/database-specific/mysql/variable_limit_offset.sql similarity index 100% rename from tests/sql_test_files/data/variable_limit_offset_noduckdb_nogeneric_nomssql_nooracle_nopostgres_nosnowflake_nosqlite.sql rename to tests/sql_test_files/data/database-specific/mysql/variable_limit_offset.sql diff --git a/tests/sql_test_files/data/set_multiple_rows_noduckdb_nogeneric_nomssql_nomysql_nooracle_nopostgres_nosnowflake.sql b/tests/sql_test_files/data/database-specific/sqlite/set_multiple_rows.sql similarity index 100% rename from tests/sql_test_files/data/set_multiple_rows_noduckdb_nogeneric_nomssql_nomysql_nooracle_nopostgres_nosnowflake.sql rename to tests/sql_test_files/data/database-specific/sqlite/set_multiple_rows.sql diff --git a/tests/sql_test_files/mod.rs b/tests/sql_test_files/mod.rs index 3335f967..915cc0cc 100644 --- a/tests/sql_test_files/mod.rs +++ b/tests/sql_test_files/mod.rs @@ -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//`. +/// 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, + test_files: Vec, +) { + 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 { tests } +fn get_database_specific_test_cases(db_type: &str) -> Vec { + 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) -> String { + format!("{:?}", app_data.db.info.database_type).to_lowercase() +} + fn read_sql_tests_in_dir(dir: &str, format: SqlTestFormat) -> Vec { - 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;