summaryrefslogtreecommitdiffstats
path: root/tests/depfile
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-18 05:39:07 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-18 05:39:07 +0000
commitaf6b8ed095f88f1df2116cdc7a9d44872cfa6074 (patch)
tree1f2df671c1f8033d5ed83f056167a0911f8d2a57 /tests/depfile
parentInitial commit. (diff)
downloadrust-cbindgen-upstream/0.26.0.tar.xz
rust-cbindgen-upstream/0.26.0.zip
Adding upstream version 0.26.0.upstream/0.26.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--tests/depfile.rs108
-rw-r--r--tests/depfile/Readme.md11
-rw-r--r--tests/depfile/cbindgen_test.cmake27
3 files changed, 146 insertions, 0 deletions
diff --git a/tests/depfile.rs b/tests/depfile.rs
new file mode 100644
index 0000000..7d629f3
--- /dev/null
+++ b/tests/depfile.rs
@@ -0,0 +1,108 @@
+use std::fs::read_to_string;
+use std::path::PathBuf;
+use std::process::Command;
+
+static CBINDGEN_PATH: &str = env!("CARGO_BIN_EXE_cbindgen");
+
+fn test_project(project_path: &str) {
+ let mut cmake_cmd = Command::new("cmake");
+ cmake_cmd.arg("--version");
+ cmake_cmd
+ .output()
+ .expect("CMake --version failed - Is CMake installed?");
+
+ let mut cmake_configure = Command::new("cmake");
+ let build_dir = PathBuf::from(project_path).join("build");
+ if build_dir.exists() {
+ std::fs::remove_dir_all(&build_dir).expect("Failed to remove old build directory");
+ }
+ let project_dir = PathBuf::from(project_path);
+
+ let cbindgen_define = format!("-DCBINDGEN_PATH={}", CBINDGEN_PATH);
+ cmake_configure
+ .arg("-S")
+ .arg(project_path)
+ .arg("-B")
+ .arg(&build_dir)
+ .arg(cbindgen_define);
+ let output = cmake_configure.output().expect("Failed to execute process");
+ let stdout_str = String::from_utf8(output.stdout).unwrap();
+ let stderr_str = String::from_utf8(output.stderr).unwrap();
+ assert!(
+ output.status.success(),
+ "Configuring test project failed: stdout: `{}`, stderr: `{}`",
+ stdout_str,
+ stderr_str
+ );
+ let depfile_path = build_dir.join("depfile.d");
+ assert!(
+ !depfile_path.exists(),
+ "depfile should not exist before building"
+ );
+
+ // Do the clean first build
+ let mut cmake_build = Command::new("cmake");
+ cmake_build.arg("--build").arg(&build_dir);
+ let output = cmake_build.output().expect("Failed to execute process");
+ assert!(output.status.success(), "Building test project failed");
+ let out_str = String::from_utf8(output.stdout).unwrap();
+ assert!(
+ out_str.contains("Running cbindgen"),
+ "cbindgen rule did not run. Output: {}",
+ out_str
+ );
+
+ assert!(
+ depfile_path.exists(),
+ "depfile does not exist after building"
+ );
+
+ let expected_dependencies_filepath = PathBuf::from(project_path)
+ .join("expectations")
+ .join("dependencies");
+ assert!(
+ expected_dependencies_filepath.exists(),
+ "Test did not define expected dependencies. Please read the Readme.md"
+ );
+ let expected_deps =
+ read_to_string(expected_dependencies_filepath).expect("Failed to read dependencies");
+ let depinfo = read_to_string(depfile_path).expect("Failed to read dependencies");
+ // Assumes a single rule in the file - all deps are listed to the rhs of the `:`.
+ let actual_deps = depinfo.split(':').collect::<Vec<_>>()[1];
+ // Strip the line breaks.
+ let actual_deps = actual_deps.replace("\\\n", " ");
+ // I don't want to deal with supporting escaped whitespace when splitting at whitespace,
+ // so the tests don't support being run in a directory containing whitespace.
+ assert!(
+ !actual_deps.contains("\\ "),
+ "The tests directory may not contain any whitespace"
+ );
+ let dep_list: Vec<&str> = actual_deps.split_ascii_whitespace().collect();
+ let expected_dep_list: Vec<String> = expected_deps
+ .lines()
+ .map(|dep| project_dir.join(dep).to_str().unwrap().to_string())
+ .collect();
+ assert_eq!(dep_list, expected_dep_list);
+
+ let output = cmake_build.output().expect("Failed to execute process");
+ assert!(output.status.success(), "Building test project failed");
+ let out_str = String::from_utf8(output.stdout).unwrap();
+ assert!(
+ !out_str.contains("Running cbindgen"),
+ "cbindgen rule ran on second build"
+ );
+
+ std::fs::remove_dir_all(build_dir).expect("Failed to remove old build directory");
+}
+
+macro_rules! test_file {
+ ($test_function_name:ident, $name:expr, $file:tt) => {
+ #[test]
+ fn $test_function_name() {
+ test_project($file);
+ }
+ };
+}
+
+// This file is generated by build.rs
+include!(concat!(env!("OUT_DIR"), "/depfile_tests.rs"));
diff --git a/tests/depfile/Readme.md b/tests/depfile/Readme.md
new file mode 100644
index 0000000..d7f8b1a
--- /dev/null
+++ b/tests/depfile/Readme.md
@@ -0,0 +1,11 @@
+This a folder containing tests for `--depfile` parameter.
+Each test is in a subfolder and defines a minimum CMake project,
+which uses cbindgen to generate Rust bindings and the `--depfile`
+parameter to determine when to regenerate.
+The outer test can the build the project, assert that rebuilding does not regenerate the
+bindings, and then assert that touching the files involved does trigger rebuilding.
+
+The test project must contain an `expectations` folder, containing a file `dependencies`.
+This `dependencies` should list all files that should be listed as dependencies in the generated
+depfile. The paths should be relative to the project folder (i.e. to the folder containing
+`expectations`).
diff --git a/tests/depfile/cbindgen_test.cmake b/tests/depfile/cbindgen_test.cmake
new file mode 100644
index 0000000..752c3c3
--- /dev/null
+++ b/tests/depfile/cbindgen_test.cmake
@@ -0,0 +1,27 @@
+# Common code used across the different tests
+
+if(NOT DEFINED CBINDGEN_PATH)
+ message(FATAL_ERROR "Path to cbindgen not specified")
+endif()
+
+# Promote to cache
+set(CBINDGEN_PATH "${CBINDGEN_PATH}" CACHE INTERNAL "")
+
+function(add_cbindgen_command custom_target_name header_destination)
+ # Place the depfile always at the same location, so the outer test framework can locate the file easily
+ set(depfile_destination "${CMAKE_BINARY_DIR}/depfile.d")
+ add_custom_command(
+ OUTPUT
+ "${header_destination}" "${depfile_destination}"
+ COMMAND
+ "${CBINDGEN_PATH}"
+ --output "${header_destination}"
+ --depfile "${depfile_destination}"
+ ${ARGN}
+ DEPFILE "${depfile_destination}"
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+ COMMENT "Running cbindgen"
+ COMMAND_EXPAND_LISTS
+ )
+ add_custom_target("${custom_target_name}" ALL DEPENDS "${header_destination}")
+endfunction() \ No newline at end of file