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]