diff --git a/Cargo.toml b/Cargo.toml index 39b38b9..db2f366 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,9 @@ categories = ["development-tools::testing"] keywords = ["cli", "testing", "assert"] build = "build.rs" +[[bin]] +name = "assert_fixture" + [dependencies] colored = "1.5" difference = "1.0" diff --git a/src/assert.rs b/src/assert.rs index 74e45c0..cb545cc 100644 --- a/src/assert.rs +++ b/src/assert.rs @@ -1,4 +1,5 @@ use environment::Environment; +use error_chain::ChainedError; use errors::*; use output::{OutputAssertion, OutputKind}; use std::default; @@ -7,6 +8,20 @@ use std::path::PathBuf; use std::process::{Command, Stdio}; use std::vec::Vec; +fn find_cargo() -> String { + let which_cargo = Command::new("which").arg("cargo") + .output().expect("Cannot exectute `which` to find `cargo`."); + + if !which_cargo.status.success() { + panic!("Could not find `cargo` command"); + } + + String::from_utf8(which_cargo.stdout) + .expect("Path to `cargo` is not UTF-8. This is currently unsupported by assert_cli.") + .trim() + .to_string() +} + /// Assertions for a specific command. #[derive(Debug)] pub struct Assert { @@ -24,11 +39,13 @@ impl default::Default for Assert { /// /// Defaults to asserting _successful_ execution. fn default() -> Self { + let cargo_path = find_cargo(); + let args = vec!["run", "--quiet", "--"] + .into_iter() + .map(String::from); + Assert { - cmd: vec!["cargo", "run", "--"] - .into_iter() - .map(String::from) - .collect(), + cmd: vec![cargo_path].into_iter().chain(args).collect(), env: Environment::inherit(), current_dir: None, expect_success: Some(true), @@ -51,11 +68,13 @@ impl Assert { /// /// Defaults to asserting _successful_ execution. pub fn cargo_binary(name: &str) -> Self { + let cargo_path = find_cargo(); + let args = vec!["run", "--quiet", "--bin", name, "--"] + .into_iter() + .map(String::from); + Assert { - cmd: vec!["cargo", "run", "--bin", name, "--"] - .into_iter() - .map(String::from) - .collect(), + cmd: vec![cargo_path].into_iter().chain(args).collect(), ..Self::default() } } @@ -308,7 +327,9 @@ impl Assert { None => command, }; - let mut spawned = command.spawn()?; + let mut spawned = command + .spawn() + .chain_err(|| ErrorKind::SpawnFailed(self.cmd.clone()))?; if let Some(ref contents) = self.stdin_contents { spawned @@ -365,7 +386,7 @@ impl Assert { /// ``` pub fn unwrap(self) { if let Err(err) = self.execute() { - panic!("{}", err); + panic!("{}", err.display_chain()); } } } diff --git a/src/bin/assert_fixture.rs b/src/bin/assert_fixture.rs new file mode 100644 index 0000000..f22ba0c --- /dev/null +++ b/src/bin/assert_fixture.rs @@ -0,0 +1,31 @@ +#[macro_use] +extern crate error_chain; + +use std::env; +use std::process; + +error_chain! { + foreign_links { + Env(env::VarError); + ParseInt(std::num::ParseIntError); + } +} + +fn run() -> Result<()> { + if let Ok(text) = env::var("stdout") { + println!("{}", text); + } + if let Ok(text) = env::var("stderr") { + eprintln!("{}", text); + } + + let code = env::var("exit") + .ok() + .map(|v| v.parse::()) + .map_or(Ok(None), |r| r.map(Some)) + .chain_err(|| "Invalid exit code")? + .unwrap_or(0); + process::exit(code); +} + +quick_main!(run); diff --git a/src/errors.rs b/src/errors.rs index af9ab5e..ab0f7b1 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -6,6 +6,14 @@ error_chain! { Fmt(::std::fmt::Error); } errors { + SpawnFailed(cmd: Vec) { + description("Spawn failed") + display( + "{}: (command `{}` failed to run)", + ERROR_PREFIX, + cmd.join(" "), + ) + } StatusMismatch(cmd: Vec, expected: bool, out: String, err: String) { description("Wrong status") display( diff --git a/tests/cargo.rs b/tests/cargo.rs new file mode 100644 index 0000000..405532d --- /dev/null +++ b/tests/cargo.rs @@ -0,0 +1,35 @@ +extern crate assert_cli; + +#[test] +fn main_binary() { + assert_cli::Assert::main_binary() + .with_env(assert_cli::Environment::inherit().insert("stdout", "42")) + .stdout() + .is("42") + .stderr() + .is("") + .unwrap(); +} + +#[test] +fn cargo_binary() { + assert_cli::Assert::cargo_binary("assert_fixture") + .with_env(assert_cli::Environment::inherit().insert("stdout", "42")) + .stdout() + .is("42") + .stderr() + .is("") + .unwrap(); +} + + +#[test] +fn works_with_empty_env() { + assert_cli::Assert::main_binary() + .with_env(assert_cli::Environment::empty()) + .unwrap(); + + assert_cli::Assert::cargo_binary("assert_fixture") + .with_env(assert_cli::Environment::empty()) + .unwrap(); +}