From b3a290ce81873bb266457c6ea7f6d94124ba8ed5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Lehmann?= Date: Wed, 24 Jan 2024 11:38:29 +0100 Subject: [PATCH] feat: add cargo runner support in order to work with cross don't run the mod_example test when using cross it depends on escargot also supporting cross, which it doesn't at this time document the runner configuration usage and how to not change anything to run with cross close: #139 --- README.md | 8 +++++--- build.rs | 16 ++++++++++++++++ src/cargo.rs | 26 +++++++++++++++++++++++++- tests/cargo.rs | 27 ++++++++++++++++++--------- 4 files changed, 64 insertions(+), 13 deletions(-) create mode 100644 build.rs diff --git a/README.md b/README.md index cbee4dd..f8cde96 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ Other crates that might be useful in testing command line programs. * [`assert_fs`][assert_fs] for filesystem fixtures and assertions. * or [tempfile][tempfile] for scratchpad directories. * [dir-diff][dir-diff] for testing file side-effects. +* [cross][cross] for cross-platform testing. [escargot]: http://docs.rs/escargot [rexpect]: https://crates.io/crates/rexpect @@ -41,6 +42,7 @@ Other crates that might be useful in testing command line programs. [duct]: https://crates.io/crates/duct [assert_fs]: https://crates.io/crates/assert_fs [commandspec]: https://crates.io/crates/commandspec +[cross]: https://github.com/cross-rs/cross ## License @@ -58,13 +60,13 @@ fitzgen > > bravo bravo WG-cli -passcod +passcod > Running commands and dealing with output can be complex in many many ways, so assert_cmd smoothing that is excellent, very much welcome, and improves ergonomics significantly. -volks73 +volks73 > I have used [assert_cmd] in other projects and I am extremely pleased with it -coreyja +coreyja > [assert_cmd] pretty much IS my testing strategy so far, though my app under test is pretty small. > > This library has made it really easy to add some test coverage to my project, even when I am just learning how to write Rust! diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..8b7b65a --- /dev/null +++ b/build.rs @@ -0,0 +1,16 @@ +use std::env; +use std::fs; +use std::io::Write; +use std::path; + +fn main() { + println!("cargo:rerun-if-changed=build.rs"); + + // env::ARCH doesn't include full triplet, and AFAIK there isn't a nicer way of getting the full triplet + // (see lib.rs for the rest of this hack) + let out = path::PathBuf::from(env::var_os("OUT_DIR").expect("run within cargo")) + .join("current_target.txt"); + let default_target = env::var("TARGET").expect("run as cargo build script"); + let mut file = fs::File::create(out).unwrap(); + file.write_all(default_target.as_bytes()).unwrap(); +} diff --git a/src/cargo.rs b/src/cargo.rs index b1e5ec3..6200b35 100644 --- a/src/cargo.rs +++ b/src/cargo.rs @@ -89,6 +89,12 @@ where /// /// See the [`cargo` module documentation][crate::cargo] for caveats and workarounds. /// + /// The [`Command`] created with this method may run the binary through a runner, as configured + /// in the `CARGO_TARGET__RUNNER` environment variable. This is useful for running + /// binaries that can't be launched directly, such as cross-compiled binaries. When using + /// this method with [cross](https://github.com/cross-rs/cross), no extra configuration is + /// needed. + /// /// # Examples /// /// ```rust,no_run @@ -132,12 +138,27 @@ impl CommandCargoExt for process::Command { pub(crate) fn cargo_bin_cmd>(name: S) -> Result { let path = cargo_bin(name); if path.is_file() { - Ok(process::Command::new(path)) + if let Some(runner) = cargo_runner() { + let mut cmd = process::Command::new(&runner[0]); + cmd.args(&runner[1..]).arg(path); + Ok(cmd) + } else { + Ok(process::Command::new(path)) + } } else { Err(CargoError::with_cause(NotFoundError { path })) } } +pub(crate) fn cargo_runner() -> Option> { + let runner_env = format!( + "CARGO_TARGET_{}_RUNNER", + CURRENT_TARGET.replace('-', "_").to_uppercase() + ); + let runner = std::env::var(runner_env).ok()?; + Some(runner.split(' ').map(str::to_string).collect()) +} + /// Error when finding crate binary. #[derive(Debug)] pub struct CargoError { @@ -206,3 +227,6 @@ fn cargo_bin_str(name: &str) -> path::PathBuf { .map(|p| p.into()) .unwrap_or_else(|| target_dir().join(format!("{}{}", name, env::consts::EXE_SUFFIX))) } + +/// The current process' target triplet. +const CURRENT_TARGET: &str = include_str!(concat!(env!("OUT_DIR"), "/current_target.txt")); diff --git a/tests/cargo.rs b/tests/cargo.rs index 02ba3dc..26c2492 100644 --- a/tests/cargo.rs +++ b/tests/cargo.rs @@ -2,6 +2,7 @@ use std::process; use std::process::Command; use assert_cmd::prelude::*; +use escargot::CURRENT_TARGET; #[test] fn cargo_binary() { @@ -19,15 +20,23 @@ fn cargo_binary_with_empty_env() { #[test] fn mod_example() { - let bin_under_test = escargot::CargoBuild::new() - .bin("bin_fixture") - .current_release() - .current_target() - .run() - .unwrap(); - let mut cmd = bin_under_test.command(); - let output = cmd.unwrap(); - println!("{:?}", output); + let runner_env = format!( + "CARGO_TARGET_{}_RUNNER", + CURRENT_TARGET.replace('-', "_").to_uppercase() + ); + if std::env::var(runner_env).is_ok() { + // not running this test on cross because escargot doesn't support the cargo target runner yet + } else { + let bin_under_test = escargot::CargoBuild::new() + .bin("bin_fixture") + .current_release() + .current_target() + .run() + .unwrap(); + let mut cmd = bin_under_test.command(); + let output = cmd.unwrap(); + println!("{:?}", output); + } } #[test]