//! [`std::process::Output`] assertions. use std::borrow::Cow; use std::error::Error; use std::fmt; use std::process; use std::str; #[cfg(feature = "color")] use anstream::panic; use predicates::str::PredicateStrExt; use predicates_tree::CaseTreeExt; use crate::output::DebugBytes; use crate::output::output_fmt; /// Assert the state of an [`Output`]. /// /// # Examples /// /// ```rust,no_run /// use assert_cmd::prelude::*; /// /// use std::process::Command; /// /// let mut cmd = Command::cargo_bin("bin_fixture") /// .unwrap(); /// cmd.assert() /// .success(); /// ``` /// /// [`Output`]: std::process::Output pub trait OutputAssertExt { /// Wrap with an interface for that provides assertions on the [`Output`]. /// /// # Examples /// /// ```rust,no_run /// use assert_cmd::prelude::*; /// /// use std::process::Command; /// /// let mut cmd = Command::cargo_bin("bin_fixture") /// .unwrap(); /// cmd.assert() /// .success(); /// ``` /// /// [`Output`]: std::process::Output #[must_use] fn assert(self) -> Assert; } impl OutputAssertExt for process::Output { fn assert(self) -> Assert { Assert::new(self) } } impl OutputAssertExt for &mut process::Command { #[track_caller] fn assert(self) -> Assert { let output = match self.output() { Ok(output) => output, Err(err) => { panic!("Failed to spawn {self:?}: {err}"); } }; Assert::new(output).append_context("command", format!("{self:?}")) } } /// Assert the state of an [`Output`]. /// /// Create an `Assert` through the [`OutputAssertExt`] trait. /// /// # Examples /// /// ```rust,no_run /// use assert_cmd::prelude::*; /// /// use std::process::Command; /// /// let mut cmd = Command::cargo_bin("bin_fixture") /// .unwrap(); /// cmd.assert() /// .success(); /// ``` /// /// [`Output`]: std::process::Output pub struct Assert { output: process::Output, context: Vec<(&'static str, Box)>, } impl Assert { /// Create an `Assert` for a given [`Output`]. /// /// [`Output`]: std::process::Output #[must_use] pub fn new(output: process::Output) -> Self { Self { output, context: vec![], } } fn into_error(self, reason: AssertReason) -> AssertError { AssertError { assert: self, reason, } } /// Clarify failures with additional context. /// /// # Examples /// /// ```rust,no_run /// use assert_cmd::prelude::*; /// /// use std::process::Command; /// /// Command::cargo_bin("bin_fixture") /// .unwrap() /// .assert() /// .append_context("main", "no args") /// .success(); /// ``` #[must_use] pub fn append_context(mut self, name: &'static str, context: D) -> Self where D: fmt::Display + Send + Sync + 'static, { self.context.push((name, Box::new(context))); self } /// Access the contained [`Output`]. /// /// [`Output`]: std::process::Output pub fn get_output(&self) -> &process::Output { &self.output } /// Ensure the command succeeded. /// /// # Examples /// /// ```rust,no_run /// use assert_cmd::prelude::*; /// /// use std::process::Command; /// /// Command::cargo_bin("bin_fixture") /// .unwrap() /// .assert() /// .success(); /// ``` #[track_caller] pub fn success(self) -> Self { match self.try_success() { Ok(v) => v, // Called manually so `#[track_caller]` is effective. Err(e) => e.panic(), } } /// `try_` variant of [`Assert::success`]. pub fn try_success(self) -> AssertResult { if !self.output.status.success() { let actual_code = self.output.status.code(); return Err(self.into_error(AssertReason::UnexpectedFailure { actual_code })); } Ok(self) } /// Ensure the command failed. /// /// # Examples /// /// ```rust,no_run /// use assert_cmd::prelude::*; /// /// use std::process::Command; /// /// Command::cargo_bin("bin_fixture") /// .unwrap() /// .env("exit", "1") /// .assert() /// .failure(); /// ``` #[track_caller] pub fn failure(self) -> Self { match self.try_failure() { Ok(v) => v, // Called manually so `#[track_caller]` is effective. Err(e) => e.panic(), } } /// Variant of [`Assert::failure`] that returns an [`AssertResult`]. pub fn try_failure(self) -> AssertResult { if self.output.status.success() { return Err(self.into_error(AssertReason::UnexpectedSuccess)); } Ok(self) } /// Ensure the command aborted before returning a code. #[track_caller] pub fn interrupted(self) -> Self { match self.try_interrupted() { Ok(v) => v, // Called manually so `#[track_caller]` is effective. Err(e) => e.panic(), } } /// Variant of [`Assert::interrupted`] that returns an [`AssertResult`]. pub fn try_interrupted(self) -> AssertResult { if self.output.status.code().is_some() { return Err(self.into_error(AssertReason::UnexpectedCompletion)); } Ok(self) } /// Ensure the command returned the expected code. /// /// This uses [`IntoCodePredicate`] to provide short-hands for common cases. /// /// See [`predicates`] for more predicates. /// /// # Examples /// /// Accepting a predicate: /// ```rust,no_run /// use assert_cmd::prelude::*; /// /// use std::process::Command; /// use predicates::prelude::*; /// /// Command::cargo_bin("bin_fixture") /// .unwrap() /// .env("exit", "42") /// .assert() /// .code(predicate::eq(42)); /// ``` /// /// Accepting an exit code: /// ```rust,no_run /// use assert_cmd::prelude::*; /// /// use std::process::Command; /// /// Command::cargo_bin("bin_fixture") /// .unwrap() /// .env("exit", "42") /// .assert() /// .code(42); /// ``` /// /// Accepting multiple exit codes: /// ```rust,no_run /// use assert_cmd::prelude::*; /// /// use std::process::Command; /// /// Command::cargo_bin("bin_fixture") /// .unwrap() /// .env("exit", "42") /// .assert() /// .code(&[2, 42] as &[i32]); /// ``` /// #[track_caller] pub fn code(self, pred: I) -> Self where I: IntoCodePredicate

, P: predicates_core::Predicate, { match self.try_code(pred) { Ok(v) => v, // Called manually so `#[track_caller]` is effective. Err(e) => e.panic(), } } /// Variant of [`Assert::code`] that returns an [`AssertResult`]. pub fn try_code(self, pred: I) -> AssertResult where I: IntoCodePredicate

, P: predicates_core::Predicate, { self.code_impl(&pred.into_code()) } fn code_impl(self, pred: &dyn predicates_core::Predicate) -> AssertResult { let actual_code = if let Some(actual_code) = self.output.status.code() { actual_code } else { return Err(self.into_error(AssertReason::CommandInterrupted)); }; if let Some(case) = pred.find_case(false, &actual_code) { return Err(self.into_error(AssertReason::UnexpectedReturnCode { case_tree: CaseTree(case.tree()), })); } Ok(self) } /// Ensure the command wrote the expected data to `stdout`. /// /// This uses [`IntoOutputPredicate`] to provide short-hands for common cases. /// /// See [`predicates`] for more predicates. /// /// # Examples /// /// Accepting a bytes predicate: /// ```rust,no_run /// use assert_cmd::prelude::*; /// /// use std::process::Command; /// use predicates::prelude::*; /// /// Command::cargo_bin("bin_fixture") /// .unwrap() /// .env("stdout", "hello") /// .env("stderr", "world") /// .assert() /// .stdout(predicate::eq(b"hello\n" as &[u8])); /// ``` /// /// Accepting a `str` predicate: /// ```rust,no_run /// use assert_cmd::prelude::*; /// /// use std::process::Command; /// use predicates::prelude::*; /// /// Command::cargo_bin("bin_fixture") /// .unwrap() /// .env("stdout", "hello") /// .env("stderr", "world") /// .assert() /// .stdout(predicate::str::diff("hello\n")); /// ``` /// /// Accepting bytes: /// ```rust,no_run /// use assert_cmd::prelude::*; /// /// use std::process::Command; /// /// Command::cargo_bin("bin_fixture") /// .unwrap() /// .env("stdout", "hello") /// .env("stderr", "world") /// .assert() /// .stdout(b"hello\n" as &[u8]); /// ``` /// /// Accepting a `str`: /// ```rust,no_run /// use assert_cmd::prelude::*; /// /// use std::process::Command; /// /// Command::cargo_bin("bin_fixture") /// .unwrap() /// .env("stdout", "hello") /// .env("stderr", "world") /// .assert() /// .stdout("hello\n"); /// ``` /// #[track_caller] pub fn stdout(self, pred: I) -> Self where I: IntoOutputPredicate

, P: predicates_core::Predicate<[u8]>, { match self.try_stdout(pred) { Ok(v) => v, // Called manually so `#[track_caller]` is effective. Err(e) => e.panic(), } } /// Variant of [`Assert::stdout`] that returns an [`AssertResult`]. pub fn try_stdout(self, pred: I) -> AssertResult where I: IntoOutputPredicate

, P: predicates_core::Predicate<[u8]>, { self.stdout_impl(&pred.into_output()) } fn stdout_impl(self, pred: &dyn predicates_core::Predicate<[u8]>) -> AssertResult { { let actual = &self.output.stdout; if let Some(case) = pred.find_case(false, actual) { return Err(self.into_error(AssertReason::UnexpectedStdout { case_tree: CaseTree(case.tree()), })); } } Ok(self) } /// Ensure the command wrote the expected data to `stderr`. /// /// This uses [`IntoOutputPredicate`] to provide short-hands for common cases. /// /// See [`predicates`] for more predicates. /// /// # Examples /// /// Accepting a bytes predicate: /// ```rust,no_run /// use assert_cmd::prelude::*; /// /// use std::process::Command; /// use predicates::prelude::*; /// /// Command::cargo_bin("bin_fixture") /// .unwrap() /// .env("stdout", "hello") /// .env("stderr", "world") /// .assert() /// .stderr(predicate::eq(b"world\n" as &[u8])); /// ``` /// /// Accepting a `str` predicate: /// ```rust,no_run /// use assert_cmd::prelude::*; /// /// use std::process::Command; /// use predicates::prelude::*; /// /// Command::cargo_bin("bin_fixture") /// .unwrap() /// .env("stdout", "hello") /// .env("stderr", "world") /// .assert() /// .stderr(predicate::str::diff("world\n")); /// ``` /// /// Accepting bytes: /// ```rust,no_run /// use assert_cmd::prelude::*; /// /// use std::process::Command; /// /// Command::cargo_bin("bin_fixture") /// .unwrap() /// .env("stdout", "hello") /// .env("stderr", "world") /// .assert() /// .stderr(b"world\n" as &[u8]); /// ``` /// /// Accepting a `str`: /// ```rust,no_run /// use assert_cmd::prelude::*; /// /// use std::process::Command; /// /// Command::cargo_bin("bin_fixture") /// .unwrap() /// .env("stdout", "hello") /// .env("stderr", "world") /// .assert() /// .stderr("world\n"); /// ``` /// #[track_caller] pub fn stderr(self, pred: I) -> Self where I: IntoOutputPredicate

, P: predicates_core::Predicate<[u8]>, { match self.try_stderr(pred) { Ok(v) => v, // Called manually so `#[track_caller]` is effective. Err(e) => e.panic(), } } /// Variant of [`Assert::stderr`] that returns an [`AssertResult`]. pub fn try_stderr(self, pred: I) -> AssertResult where I: IntoOutputPredicate

, P: predicates_core::Predicate<[u8]>, { self.stderr_impl(&pred.into_output()) } fn stderr_impl(self, pred: &dyn predicates_core::Predicate<[u8]>) -> AssertResult { { let actual = &self.output.stderr; if let Some(case) = pred.find_case(false, actual) { return Err(self.into_error(AssertReason::UnexpectedStderr { case_tree: CaseTree(case.tree()), })); } } Ok(self) } } impl fmt::Display for Assert { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let palette = crate::Palette::color(); for (name, context) in &self.context { writeln!(f, "{:#}=`{:#}`", palette.key(name), palette.value(context))?; } output_fmt(&self.output, f) } } impl fmt::Debug for Assert { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Assert") .field("output", &self.output) .finish() } } /// Used by [`Assert::code`] to convert `Self` into the needed /// [`predicates_core::Predicate`]. /// /// # Examples /// /// ```rust,no_run /// use assert_cmd::prelude::*; /// /// use std::process::Command; /// use predicates::prelude::*; /// /// Command::cargo_bin("bin_fixture") /// .unwrap() /// .env("exit", "42") /// .assert() /// .code(predicate::eq(42)); /// /// // which can be shortened to: /// Command::cargo_bin("bin_fixture") /// .unwrap() /// .env("exit", "42") /// .assert() /// .code(42); /// ``` pub trait IntoCodePredicate

where P: predicates_core::Predicate, { /// The type of the predicate being returned. type Predicate; /// Convert to a predicate for testing a program's exit code. fn into_code(self) -> P; } impl

IntoCodePredicate

for P where P: predicates_core::Predicate, { type Predicate = P; fn into_code(self) -> Self::Predicate { self } } /// Keep `predicates` concrete Predicates out of our public API. /// [`predicates_core::Predicate`] used by [`IntoCodePredicate`] for code. /// /// # Example /// /// ```rust,no_run /// use assert_cmd::prelude::*; /// /// use std::process::Command; /// /// Command::cargo_bin("bin_fixture") /// .unwrap() /// .env("exit", "42") /// .assert() /// .code(42); /// ``` #[derive(Debug)] pub struct EqCodePredicate(predicates::ord::EqPredicate); impl EqCodePredicate { pub(crate) fn new(value: i32) -> Self { let pred = predicates::ord::eq(value); Self(pred) } } impl predicates_core::reflection::PredicateReflection for EqCodePredicate { fn parameters<'a>( &'a self, ) -> Box> + 'a> { self.0.parameters() } /// Nested `Predicate`s of the current `Predicate`. fn children<'a>( &'a self, ) -> Box> + 'a> { self.0.children() } } impl predicates_core::Predicate for EqCodePredicate { fn eval(&self, item: &i32) -> bool { self.0.eval(item) } fn find_case<'a>( &'a self, expected: bool, variable: &i32, ) -> Option> { self.0.find_case(expected, variable) } } impl fmt::Display for EqCodePredicate { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.0.fmt(f) } } impl IntoCodePredicate for i32 { type Predicate = EqCodePredicate; fn into_code(self) -> Self::Predicate { Self::Predicate::new(self) } } /// Keep `predicates` concrete Predicates out of our public API. /// [`predicates_core::Predicate`] used by [`IntoCodePredicate`] for iterables of codes. /// /// # Example /// /// ```rust,no_run /// use assert_cmd::prelude::*; /// /// use std::process::Command; /// /// Command::cargo_bin("bin_fixture") /// .unwrap() /// .env("exit", "42") /// .assert() /// .code(&[2, 42] as &[i32]); /// ``` #[derive(Debug)] pub struct InCodePredicate(predicates::iter::InPredicate); impl InCodePredicate { pub(crate) fn new>(value: I) -> Self { let pred = predicates::iter::in_iter(value); Self(pred) } } impl predicates_core::reflection::PredicateReflection for InCodePredicate { fn parameters<'a>( &'a self, ) -> Box> + 'a> { self.0.parameters() } /// Nested `Predicate`s of the current `Predicate`. fn children<'a>( &'a self, ) -> Box> + 'a> { self.0.children() } } impl predicates_core::Predicate for InCodePredicate { fn eval(&self, item: &i32) -> bool { self.0.eval(item) } fn find_case<'a>( &'a self, expected: bool, variable: &i32, ) -> Option> { self.0.find_case(expected, variable) } } impl fmt::Display for InCodePredicate { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.0.fmt(f) } } impl IntoCodePredicate for Vec { type Predicate = InCodePredicate; fn into_code(self) -> Self::Predicate { Self::Predicate::new(self) } } impl IntoCodePredicate for &'static [i32] { type Predicate = InCodePredicate; fn into_code(self) -> Self::Predicate { Self::Predicate::new(self.iter().cloned()) } } /// Used by [`Assert::stdout`] and [`Assert::stderr`] to convert Self /// into the needed [`predicates_core::Predicate<[u8]>`]. /// /// # Examples /// /// ```rust,no_run /// use assert_cmd::prelude::*; /// /// use std::process::Command; /// use predicates::prelude::*; /// /// Command::cargo_bin("bin_fixture") /// .unwrap() /// .env("stdout", "hello") /// .env("stderr", "world") /// .assert() /// .stdout(predicate::str::diff("hello\n").from_utf8()); /// /// // which can be shortened to: /// Command::cargo_bin("bin_fixture") /// .unwrap() /// .env("stdout", "hello") /// .env("stderr", "world") /// .assert() /// .stdout("hello\n"); /// ``` pub trait IntoOutputPredicate

where P: predicates_core::Predicate<[u8]>, { /// The type of the predicate being returned. type Predicate; /// Convert to a predicate for testing a path. fn into_output(self) -> P; } impl

IntoOutputPredicate

for P where P: predicates_core::Predicate<[u8]>, { type Predicate = P; fn into_output(self) -> Self::Predicate { self } } /// Keep `predicates` concrete Predicates out of our public API. /// [`predicates_core::Predicate`] used by [`IntoOutputPredicate`] for bytes. /// /// # Example /// /// ```rust,no_run /// use assert_cmd::prelude::*; /// /// use std::process::Command; /// /// Command::cargo_bin("bin_fixture") /// .unwrap() /// .env("stdout", "hello") /// .env("stderr", "world") /// .assert() /// .stderr(b"world\n" as &[u8]); /// ``` #[derive(Debug)] pub struct BytesContentOutputPredicate(Cow<'static, [u8]>); impl BytesContentOutputPredicate { pub(crate) fn new(value: &'static [u8]) -> Self { Self(Cow::from(value)) } pub(crate) fn from_vec(value: Vec) -> Self { Self(Cow::from(value)) } } impl predicates_core::reflection::PredicateReflection for BytesContentOutputPredicate {} impl predicates_core::Predicate<[u8]> for BytesContentOutputPredicate { fn eval(&self, item: &[u8]) -> bool { self.0.as_ref() == item } fn find_case( &self, expected: bool, variable: &[u8], ) -> Option> { let actual = self.eval(variable); if expected == actual { Some(predicates_core::reflection::Case::new(Some(self), actual)) } else { None } } } impl fmt::Display for BytesContentOutputPredicate { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { predicates::ord::eq(self.0.as_ref()).fmt(f) } } impl IntoOutputPredicate for Vec { type Predicate = BytesContentOutputPredicate; fn into_output(self) -> Self::Predicate { Self::Predicate::from_vec(self) } } impl IntoOutputPredicate for &'static [u8] { type Predicate = BytesContentOutputPredicate; fn into_output(self) -> Self::Predicate { Self::Predicate::new(self) } } /// Keep `predicates` concrete Predicates out of our public API. /// [`predicates_core::Predicate`] used by [`IntoOutputPredicate`] for [`str`]. /// /// # Example /// /// ```rust,no_run /// use assert_cmd::prelude::*; /// /// use std::process::Command; /// /// Command::cargo_bin("bin_fixture") /// .unwrap() /// .env("stdout", "hello") /// .env("stderr", "world") /// .assert() /// .stderr("world\n"); /// ``` /// /// [`str`]: https://doc.rust-lang.org/std/primitive.str.html #[derive(Debug, Clone)] pub struct StrContentOutputPredicate( predicates::str::Utf8Predicate, ); impl StrContentOutputPredicate { pub(crate) fn from_str(value: &'static str) -> Self { let pred = predicates::str::diff(value).from_utf8(); Self(pred) } pub(crate) fn from_string(value: String) -> Self { let pred = predicates::str::diff(value).from_utf8(); Self(pred) } } impl predicates_core::reflection::PredicateReflection for StrContentOutputPredicate { fn parameters<'a>( &'a self, ) -> Box> + 'a> { self.0.parameters() } /// Nested `Predicate`s of the current `Predicate`. fn children<'a>( &'a self, ) -> Box> + 'a> { self.0.children() } } impl predicates_core::Predicate<[u8]> for StrContentOutputPredicate { fn eval(&self, item: &[u8]) -> bool { self.0.eval(item) } fn find_case<'a>( &'a self, expected: bool, variable: &[u8], ) -> Option> { self.0.find_case(expected, variable) } } impl fmt::Display for StrContentOutputPredicate { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.0.fmt(f) } } impl IntoOutputPredicate for String { type Predicate = StrContentOutputPredicate; fn into_output(self) -> Self::Predicate { Self::Predicate::from_string(self) } } impl IntoOutputPredicate for &'static str { type Predicate = StrContentOutputPredicate; fn into_output(self) -> Self::Predicate { Self::Predicate::from_str(self) } } // Keep `predicates` concrete Predicates out of our public API. /// [`predicates_core::Predicate`] used by [`IntoOutputPredicate`] for /// [`Predicate`][predicates_core::Predicate]. /// /// # Example /// /// ```rust,no_run /// use assert_cmd::prelude::*; /// /// use std::process::Command; /// use predicates::prelude::*; /// /// Command::cargo_bin("bin_fixture") /// .unwrap() /// .env("stdout", "hello") /// .env("stderr", "world") /// .assert() /// .stderr(predicate::str::diff("world\n")); /// ``` #[derive(Debug, Clone)] pub struct StrOutputPredicate>( predicates::str::Utf8Predicate

, ); impl

StrOutputPredicate

where P: predicates_core::Predicate, { pub(crate) fn new(pred: P) -> Self { let pred = pred.from_utf8(); Self(pred) } } impl

predicates_core::reflection::PredicateReflection for StrOutputPredicate

where P: predicates_core::Predicate, { fn parameters<'a>( &'a self, ) -> Box> + 'a> { self.0.parameters() } /// Nested `Predicate`s of the current `Predicate`. fn children<'a>( &'a self, ) -> Box> + 'a> { self.0.children() } } impl

predicates_core::Predicate<[u8]> for StrOutputPredicate

where P: predicates_core::Predicate, { fn eval(&self, item: &[u8]) -> bool { self.0.eval(item) } fn find_case<'a>( &'a self, expected: bool, variable: &[u8], ) -> Option> { self.0.find_case(expected, variable) } } impl

fmt::Display for StrOutputPredicate

where P: predicates_core::Predicate, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.0.fmt(f) } } impl

IntoOutputPredicate> for P where P: predicates_core::Predicate, { type Predicate = StrOutputPredicate

; fn into_output(self) -> Self::Predicate { Self::Predicate::new(self) } } /// [`Assert`] represented as a [`Result`]. /// /// Produced by the `try_` variants the [`Assert`] methods. /// /// # Example /// /// ```rust /// use assert_cmd::prelude::*; /// /// use std::process::Command; /// /// let result = Command::new("echo") /// .assert() /// .try_success(); /// assert!(result.is_ok()); /// ``` /// /// [`Result`]: std::result::Result pub type AssertResult = Result; /// [`Assert`] error (see [`AssertResult`]). #[derive(Debug)] pub struct AssertError { assert: Assert, reason: AssertReason, } #[derive(Debug)] enum AssertReason { UnexpectedFailure { actual_code: Option }, UnexpectedSuccess, UnexpectedCompletion, CommandInterrupted, UnexpectedReturnCode { case_tree: CaseTree }, UnexpectedStdout { case_tree: CaseTree }, UnexpectedStderr { case_tree: CaseTree }, } impl AssertError { #[track_caller] fn panic(self) -> T { panic!("{}", self) } /// Returns the [`Assert`] wrapped into the [`Result`] produced by /// the `try_` variants of the [`Assert`] methods. /// /// # Examples /// /// ```rust,no_run /// use assert_cmd::prelude::*; /// /// use std::process::Command; /// use predicates::prelude::*; /// /// let result = Command::new("echo") /// .assert(); /// /// match result.try_success() { /// Ok(assert) => { /// assert.stdout(predicate::eq(b"Success\n" as &[u8])); /// } /// Err(err) => { /// err.assert().stdout(predicate::eq(b"Err but some specific output you might want to check\n" as &[u8])); /// } /// } /// ``` pub fn assert(self) -> Assert { self.assert } } impl Error for AssertError {} impl fmt::Display for AssertError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match &self.reason { AssertReason::UnexpectedFailure { actual_code } => writeln!( f, "Unexpected failure.\ncode={}\nstderr=```{}```", actual_code .map(|actual_code| actual_code.to_string()) .unwrap_or_else(|| "".to_owned()), DebugBytes::new(&self.assert.output.stderr), ), AssertReason::UnexpectedSuccess => { writeln!(f, "Unexpected success") } AssertReason::UnexpectedCompletion => { writeln!(f, "Unexpected completion") } AssertReason::CommandInterrupted => { writeln!(f, "Command interrupted") } AssertReason::UnexpectedReturnCode { case_tree } => { writeln!(f, "Unexpected return code, failed {case_tree}") } AssertReason::UnexpectedStdout { case_tree } => { writeln!(f, "Unexpected stdout, failed {case_tree}") } AssertReason::UnexpectedStderr { case_tree } => { writeln!(f, "Unexpected stderr, failed {case_tree}") } }?; write!(f, "{}", self.assert) } } struct CaseTree(predicates_tree::CaseTree); impl fmt::Display for CaseTree { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { ::fmt(&self.0, f) } } // Work around `Debug` not being implemented for `predicates_tree::CaseTree`. impl fmt::Debug for CaseTree { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { ::fmt(&self.0, f) } } #[cfg(test)] mod test { use super::*; use predicates::prelude::*; // Since IntoCodePredicate exists solely for conversion, test it under that scenario to ensure // it works as expected. fn convert_code(pred: I) -> P where I: IntoCodePredicate

, P: Predicate, { pred.into_code() } #[test] fn into_code_from_pred() { let pred = convert_code(predicate::eq(10)); assert!(pred.eval(&10)); } #[test] fn into_code_from_i32() { let pred = convert_code(10); assert!(pred.eval(&10)); } #[test] fn into_code_from_vec() { let pred = convert_code(vec![3, 10]); assert!(pred.eval(&10)); } #[test] fn into_code_from_array() { let pred = convert_code(&[3, 10] as &[i32]); assert!(pred.eval(&10)); } // Since IntoOutputPredicate exists solely for conversion, test it under that scenario to ensure // it works as expected. fn convert_output(pred: I) -> P where I: IntoOutputPredicate

, P: Predicate<[u8]>, { pred.into_output() } #[test] fn into_output_from_pred() { let pred = convert_output(predicate::eq(b"Hello" as &[u8])); assert!(pred.eval(b"Hello" as &[u8])); } #[test] fn into_output_from_bytes() { let pred = convert_output(b"Hello" as &[u8]); assert!(pred.eval(b"Hello" as &[u8])); } #[test] fn into_output_from_vec() { let pred = convert_output(vec![b'H', b'e', b'l', b'l', b'o']); assert!(pred.eval(b"Hello" as &[u8])); } #[test] fn into_output_from_str() { let pred = convert_output("Hello"); assert!(pred.eval(b"Hello" as &[u8])); } }