test: ensure that query tests don't rebuild all the time
Beforehand:
```text
❯ env CARGO_LOG=cargo::core::compiler::fingerprint=info cargo test -p query_tests
[2021-07-05T08:52:13Z INFO cargo::core::compiler::fingerprint] stale: changed "/home/mneumann/src/influxdb_iox/query_tests/cases"
[2021-07-05T08:52:13Z INFO cargo::core::compiler::fingerprint] (vs) "/home/mneumann/src/influxdb_iox/target/debug/build/query_tests-0e8f741dfb84437f/output"
[2021-07-05T08:52:13Z INFO cargo::core::compiler::fingerprint] FileTime { seconds: 1625474716, nanos: 436081357 } != FileTime { seconds: 1625474752, nanos: 52625167 }
[2021-07-05T08:52:13Z INFO cargo::core::compiler::fingerprint] fingerprint error for query_tests v0.1.0 (/home/mneumann/src/influxdb_iox/query_tests)/Test/TargetInner { ..: lib_target("query_tests", ["lib"], "/home/mneumann/src/influxdb_iox/query_tests/src/lib.rs", Edition2018) }
[2021-07-05T08:52:13Z INFO cargo::core::compiler::fingerprint] err: current filesystem status shows we're outdated
[2021-07-05T08:52:13Z INFO cargo::core::compiler::fingerprint] fingerprint error for query_tests v0.1.0 (/home/mneumann/src/influxdb_iox/query_tests)/RunCustomBuild/TargetInner { ..: custom_build_target("build-script-build", "/home/mneumann/src/influxdb_iox/query_tests/build.rs", Edition2018) }
[2021-07-05T08:52:13Z INFO cargo::core::compiler::fingerprint] err: current filesystem status shows we're outdated
[2021-07-05T08:52:13Z INFO cargo::core::compiler::fingerprint] fingerprint error for query_tests v0.1.0 (/home/mneumann/src/influxdb_iox/query_tests)/Build/TargetInner { ..: lib_target("query_tests", ["lib"], "/home/mneumann/src/influxdb_iox/query_tests/src/lib.rs", Edition2018) }
[2021-07-05T08:52:13Z INFO cargo::core::compiler::fingerprint] err: current filesystem status shows we're outdated
Compiling query_tests v0.1.0 (/home/mneumann/src/influxdb_iox/query_tests)
```
The issue is that both the input and the test output files are located
under `cases/`. `build.rs` used `cargo:rerun-if-changed=cases` which per
Cargo doc will scan ALL files in that directory. Note that the normal
`exclude` directive in `Cargo.toml` does NOT work, see
https://github.com/rust-lang/cargo/issues/4587 .
So we need to split input and output files into separate directories
(`cases/{in,out}`).
2021-07-05 09:48:50 +00:00
|
|
|
//! Finds all .sql files in `cases/in/` and creates corresponding entries in src/cases.rs
|
2021-06-29 16:09:51 +00:00
|
|
|
//! native Rust types.
|
|
|
|
|
|
|
|
use std::path::{Path, PathBuf};
|
|
|
|
|
|
|
|
type Error = Box<dyn std::error::Error>;
|
|
|
|
type Result<T, E = Error> = std::result::Result<T, E>;
|
|
|
|
|
|
|
|
fn main() -> Result<()> {
|
|
|
|
// crate root
|
|
|
|
let root = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
test: ensure that query tests don't rebuild all the time
Beforehand:
```text
❯ env CARGO_LOG=cargo::core::compiler::fingerprint=info cargo test -p query_tests
[2021-07-05T08:52:13Z INFO cargo::core::compiler::fingerprint] stale: changed "/home/mneumann/src/influxdb_iox/query_tests/cases"
[2021-07-05T08:52:13Z INFO cargo::core::compiler::fingerprint] (vs) "/home/mneumann/src/influxdb_iox/target/debug/build/query_tests-0e8f741dfb84437f/output"
[2021-07-05T08:52:13Z INFO cargo::core::compiler::fingerprint] FileTime { seconds: 1625474716, nanos: 436081357 } != FileTime { seconds: 1625474752, nanos: 52625167 }
[2021-07-05T08:52:13Z INFO cargo::core::compiler::fingerprint] fingerprint error for query_tests v0.1.0 (/home/mneumann/src/influxdb_iox/query_tests)/Test/TargetInner { ..: lib_target("query_tests", ["lib"], "/home/mneumann/src/influxdb_iox/query_tests/src/lib.rs", Edition2018) }
[2021-07-05T08:52:13Z INFO cargo::core::compiler::fingerprint] err: current filesystem status shows we're outdated
[2021-07-05T08:52:13Z INFO cargo::core::compiler::fingerprint] fingerprint error for query_tests v0.1.0 (/home/mneumann/src/influxdb_iox/query_tests)/RunCustomBuild/TargetInner { ..: custom_build_target("build-script-build", "/home/mneumann/src/influxdb_iox/query_tests/build.rs", Edition2018) }
[2021-07-05T08:52:13Z INFO cargo::core::compiler::fingerprint] err: current filesystem status shows we're outdated
[2021-07-05T08:52:13Z INFO cargo::core::compiler::fingerprint] fingerprint error for query_tests v0.1.0 (/home/mneumann/src/influxdb_iox/query_tests)/Build/TargetInner { ..: lib_target("query_tests", ["lib"], "/home/mneumann/src/influxdb_iox/query_tests/src/lib.rs", Edition2018) }
[2021-07-05T08:52:13Z INFO cargo::core::compiler::fingerprint] err: current filesystem status shows we're outdated
Compiling query_tests v0.1.0 (/home/mneumann/src/influxdb_iox/query_tests)
```
The issue is that both the input and the test output files are located
under `cases/`. `build.rs` used `cargo:rerun-if-changed=cases` which per
Cargo doc will scan ALL files in that directory. Note that the normal
`exclude` directive in `Cargo.toml` does NOT work, see
https://github.com/rust-lang/cargo/issues/4587 .
So we need to split input and output files into separate directories
(`cases/{in,out}`).
2021-07-05 09:48:50 +00:00
|
|
|
let cases = root.join("cases").join("in");
|
2021-06-29 16:09:51 +00:00
|
|
|
|
|
|
|
let sql_files = find_sql_files(&cases);
|
|
|
|
|
|
|
|
// Tell cargo to recompile if anything in the cases directory changes
|
|
|
|
println!("cargo:rerun-if-changed={}", cases.display());
|
|
|
|
|
|
|
|
// Now create the generated sql file
|
|
|
|
let output_content = make_cases_rs(&sql_files).join("\n");
|
|
|
|
let output_file = root.join("src").join("cases.rs");
|
2021-07-05 09:49:27 +00:00
|
|
|
write_if_changed(&output_file, &output_content);
|
2021-06-29 16:09:51 +00:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns a sorted list of all files named `.sql` in the specified root directory
|
|
|
|
fn find_sql_files(root: &Path) -> Vec<PathBuf> {
|
|
|
|
let mut sqls: Vec<PathBuf> = root
|
|
|
|
.read_dir()
|
|
|
|
.map_err(|e| format!("can not read root: {:?}: {}", root, e))
|
|
|
|
.unwrap()
|
|
|
|
.map(|dir_ent| {
|
|
|
|
let dir_ent = dir_ent
|
|
|
|
.map_err(|e| format!("can not read directory entry: {}", e))
|
|
|
|
.unwrap();
|
|
|
|
dir_ent.path()
|
|
|
|
})
|
|
|
|
.filter(|p| p.extension() == Some(std::ffi::OsStr::new("sql")))
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
sqls.sort();
|
|
|
|
sqls
|
|
|
|
}
|
|
|
|
|
|
|
|
/// writes out what will be the rust test file that lists out .sqls
|
|
|
|
fn make_cases_rs(sqls: &[PathBuf]) -> Vec<String> {
|
|
|
|
let mut output_lines: Vec<String> = vec![r#"
|
|
|
|
//! This file is auto generated by build.rs
|
|
|
|
//! Do not edit manually --> will result in sadness
|
|
|
|
use std::path::Path;
|
|
|
|
use crate::runner::Runner;"#
|
|
|
|
.into()];
|
|
|
|
|
|
|
|
for sql in sqls {
|
|
|
|
let file_name = sql.file_name().expect("a name").to_string_lossy();
|
|
|
|
|
|
|
|
let test_name = file_name.replace(".", "_");
|
|
|
|
|
|
|
|
output_lines.push(format!(
|
|
|
|
r#"
|
|
|
|
#[tokio::test]
|
|
|
|
// Tests from {:?},
|
|
|
|
async fn test_cases_{}() {{
|
test: ensure that query tests don't rebuild all the time
Beforehand:
```text
❯ env CARGO_LOG=cargo::core::compiler::fingerprint=info cargo test -p query_tests
[2021-07-05T08:52:13Z INFO cargo::core::compiler::fingerprint] stale: changed "/home/mneumann/src/influxdb_iox/query_tests/cases"
[2021-07-05T08:52:13Z INFO cargo::core::compiler::fingerprint] (vs) "/home/mneumann/src/influxdb_iox/target/debug/build/query_tests-0e8f741dfb84437f/output"
[2021-07-05T08:52:13Z INFO cargo::core::compiler::fingerprint] FileTime { seconds: 1625474716, nanos: 436081357 } != FileTime { seconds: 1625474752, nanos: 52625167 }
[2021-07-05T08:52:13Z INFO cargo::core::compiler::fingerprint] fingerprint error for query_tests v0.1.0 (/home/mneumann/src/influxdb_iox/query_tests)/Test/TargetInner { ..: lib_target("query_tests", ["lib"], "/home/mneumann/src/influxdb_iox/query_tests/src/lib.rs", Edition2018) }
[2021-07-05T08:52:13Z INFO cargo::core::compiler::fingerprint] err: current filesystem status shows we're outdated
[2021-07-05T08:52:13Z INFO cargo::core::compiler::fingerprint] fingerprint error for query_tests v0.1.0 (/home/mneumann/src/influxdb_iox/query_tests)/RunCustomBuild/TargetInner { ..: custom_build_target("build-script-build", "/home/mneumann/src/influxdb_iox/query_tests/build.rs", Edition2018) }
[2021-07-05T08:52:13Z INFO cargo::core::compiler::fingerprint] err: current filesystem status shows we're outdated
[2021-07-05T08:52:13Z INFO cargo::core::compiler::fingerprint] fingerprint error for query_tests v0.1.0 (/home/mneumann/src/influxdb_iox/query_tests)/Build/TargetInner { ..: lib_target("query_tests", ["lib"], "/home/mneumann/src/influxdb_iox/query_tests/src/lib.rs", Edition2018) }
[2021-07-05T08:52:13Z INFO cargo::core::compiler::fingerprint] err: current filesystem status shows we're outdated
Compiling query_tests v0.1.0 (/home/mneumann/src/influxdb_iox/query_tests)
```
The issue is that both the input and the test output files are located
under `cases/`. `build.rs` used `cargo:rerun-if-changed=cases` which per
Cargo doc will scan ALL files in that directory. Note that the normal
`exclude` directive in `Cargo.toml` does NOT work, see
https://github.com/rust-lang/cargo/issues/4587 .
So we need to split input and output files into separate directories
(`cases/{in,out}`).
2021-07-05 09:48:50 +00:00
|
|
|
let input_path = Path::new("cases").join("in").join("{}");
|
2021-06-29 16:09:51 +00:00
|
|
|
let mut runner = Runner::new();
|
|
|
|
runner
|
|
|
|
.run(input_path)
|
|
|
|
.await
|
|
|
|
.expect("test failed");
|
|
|
|
runner
|
|
|
|
.flush()
|
|
|
|
.expect("flush worked");
|
|
|
|
}}"#,
|
|
|
|
file_name, test_name, file_name
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
output_lines
|
|
|
|
}
|
2021-07-05 09:49:27 +00:00
|
|
|
|
|
|
|
/// Write content to file if it is different to the current content.
|
|
|
|
///
|
|
|
|
/// This prevents us from touching the file and modifying the `mtime` so that Cargo will re-compile the output `.rs`
|
|
|
|
/// file every time. Also see [`rust-lang/cargo#6529`](https://github.com/rust-lang/cargo/issues/6529).
|
|
|
|
fn write_if_changed(path: &Path, content: &str) {
|
|
|
|
let changed = if !path.exists() {
|
|
|
|
true
|
|
|
|
} else {
|
|
|
|
match std::fs::read_to_string(path) {
|
|
|
|
Ok(old_content) => old_content != content,
|
|
|
|
Err(_) => true,
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
if changed {
|
|
|
|
std::fs::write(path, content)
|
|
|
|
.map_err(|e| format!("Error writing to {:?}: {}", path, e))
|
|
|
|
.unwrap();
|
|
|
|
}
|
|
|
|
}
|