1 //! [`std::process::Output`] assertions.
2 
3 use std::borrow::Cow;
4 use std::error::Error;
5 use std::fmt;
6 use std::process;
7 use std::str;
8 
9 use predicates::str::PredicateStrExt;
10 use predicates_tree::CaseTreeExt;
11 
12 use crate::output::output_fmt;
13 use crate::output::DebugBytes;
14 
15 /// Assert the state of an [`Output`].
16 ///
17 /// # Examples
18 ///
19 /// ```rust,no_run
20 /// use assert_cmd::prelude::*;
21 ///
22 /// use std::process::Command;
23 ///
24 /// let mut cmd = Command::cargo_bin("bin_fixture")
25 ///     .unwrap();
26 /// cmd.assert()
27 ///     .success();
28 /// ```
29 ///
30 /// [`Output`]: std::process::Output
31 pub trait OutputAssertExt {
32     /// Wrap with an interface for that provides assertions on the [`Output`].
33     ///
34     /// # Examples
35     ///
36     /// ```rust,no_run
37     /// use assert_cmd::prelude::*;
38     ///
39     /// use std::process::Command;
40     ///
41     /// let mut cmd = Command::cargo_bin("bin_fixture")
42     ///     .unwrap();
43     /// cmd.assert()
44     ///     .success();
45     /// ```
46     ///
47     /// [`Output`]: std::process::Output
assert(self) -> Assert48     fn assert(self) -> Assert;
49 }
50 
51 impl OutputAssertExt for process::Output {
assert(self) -> Assert52     fn assert(self) -> Assert {
53         Assert::new(self)
54     }
55 }
56 
57 impl<'c> OutputAssertExt for &'c mut process::Command {
assert(self) -> Assert58     fn assert(self) -> Assert {
59         let output = match self.output() {
60             Ok(output) => output,
61             Err(err) => {
62                 panic!("Failed to spawn {:?}: {}", self, err);
63             }
64         };
65         Assert::new(output).append_context("command", format!("{:?}", self))
66     }
67 }
68 
69 /// Assert the state of an [`Output`].
70 ///
71 /// Create an `Assert` through the [`OutputAssertExt`] trait.
72 ///
73 /// # Examples
74 ///
75 /// ```rust,no_run
76 /// use assert_cmd::prelude::*;
77 ///
78 /// use std::process::Command;
79 ///
80 /// let mut cmd = Command::cargo_bin("bin_fixture")
81 ///     .unwrap();
82 /// cmd.assert()
83 ///     .success();
84 /// ```
85 ///
86 /// [`Output`]: std::process::Output
87 pub struct Assert {
88     output: process::Output,
89     context: Vec<(&'static str, Box<dyn fmt::Display + Send + Sync>)>,
90 }
91 
92 impl Assert {
93     /// Create an `Assert` for a given [`Output`].
94     ///
95     /// [`Output`]: std::process::Output
new(output: process::Output) -> Self96     pub fn new(output: process::Output) -> Self {
97         Self {
98             output,
99             context: vec![],
100         }
101     }
102 
into_error(self, reason: AssertReason) -> AssertError103     fn into_error(self, reason: AssertReason) -> AssertError {
104         AssertError {
105             assert: self,
106             reason,
107         }
108     }
109 
110     /// Clarify failures with additional context.
111     ///
112     /// # Examples
113     ///
114     /// ```rust,no_run
115     /// use assert_cmd::prelude::*;
116     ///
117     /// use std::process::Command;
118     ///
119     /// Command::cargo_bin("bin_fixture")
120     ///     .unwrap()
121     ///     .assert()
122     ///     .append_context("main", "no args")
123     ///     .success();
124     /// ```
append_context<D>(mut self, name: &'static str, context: D) -> Self where D: fmt::Display + Send + Sync + 'static,125     pub fn append_context<D>(mut self, name: &'static str, context: D) -> Self
126     where
127         D: fmt::Display + Send + Sync + 'static,
128     {
129         self.context.push((name, Box::new(context)));
130         self
131     }
132 
133     /// Access the contained [`Output`].
134     ///
135     /// [`Output`]: std::process::Output
get_output(&self) -> &process::Output136     pub fn get_output(&self) -> &process::Output {
137         &self.output
138     }
139 
140     /// Ensure the command succeeded.
141     ///
142     /// # Examples
143     ///
144     /// ```rust,no_run
145     /// use assert_cmd::prelude::*;
146     ///
147     /// use std::process::Command;
148     ///
149     /// Command::cargo_bin("bin_fixture")
150     ///     .unwrap()
151     ///     .assert()
152     ///     .success();
153     /// ```
154     #[track_caller]
success(self) -> Self155     pub fn success(self) -> Self {
156         self.try_success().unwrap_or_else(AssertError::panic)
157     }
158 
159     /// `try_` variant of [`Assert::success`].
try_success(self) -> AssertResult160     pub fn try_success(self) -> AssertResult {
161         if !self.output.status.success() {
162             let actual_code = self.output.status.code();
163             return Err(self.into_error(AssertReason::UnexpectedFailure { actual_code }));
164         }
165         Ok(self)
166     }
167 
168     /// Ensure the command failed.
169     ///
170     /// # Examples
171     ///
172     /// ```rust,no_run
173     /// use assert_cmd::prelude::*;
174     ///
175     /// use std::process::Command;
176     ///
177     /// Command::cargo_bin("bin_fixture")
178     ///     .unwrap()
179     ///     .env("exit", "1")
180     ///     .assert()
181     ///     .failure();
182     /// ```
183     #[track_caller]
failure(self) -> Self184     pub fn failure(self) -> Self {
185         self.try_failure().unwrap_or_else(AssertError::panic)
186     }
187 
188     /// Variant of [`Assert::failure`] that returns an [`AssertResult`].
try_failure(self) -> AssertResult189     pub fn try_failure(self) -> AssertResult {
190         if self.output.status.success() {
191             return Err(self.into_error(AssertReason::UnexpectedSuccess));
192         }
193         Ok(self)
194     }
195 
196     /// Ensure the command aborted before returning a code.
197     #[track_caller]
interrupted(self) -> Self198     pub fn interrupted(self) -> Self {
199         self.try_interrupted().unwrap_or_else(AssertError::panic)
200     }
201 
202     /// Variant of [`Assert::interrupted`] that returns an [`AssertResult`].
try_interrupted(self) -> AssertResult203     pub fn try_interrupted(self) -> AssertResult {
204         if self.output.status.code().is_some() {
205             return Err(self.into_error(AssertReason::UnexpectedCompletion));
206         }
207         Ok(self)
208     }
209 
210     /// Ensure the command returned the expected code.
211     ///
212     /// This uses [`IntoCodePredicate`] to provide short-hands for common cases.
213     ///
214     /// See [`predicates`] for more predicates.
215     ///
216     /// # Examples
217     ///
218     /// Accepting a predicate:
219     /// ```rust,no_run
220     /// use assert_cmd::prelude::*;
221     ///
222     /// use std::process::Command;
223     /// use predicates::prelude::*;
224     ///
225     /// Command::cargo_bin("bin_fixture")
226     ///     .unwrap()
227     ///     .env("exit", "42")
228     ///     .assert()
229     ///     .code(predicate::eq(42));
230     /// ```
231     ///
232     /// Accepting an exit code:
233     /// ```rust,no_run
234     /// use assert_cmd::prelude::*;
235     ///
236     /// use std::process::Command;
237     ///
238     /// Command::cargo_bin("bin_fixture")
239     ///     .unwrap()
240     ///     .env("exit", "42")
241     ///     .assert()
242     ///     .code(42);
243     /// ```
244     ///
245     /// Accepting multiple exit codes:
246     /// ```rust,no_run
247     /// use assert_cmd::prelude::*;
248     ///
249     /// use std::process::Command;
250     ///
251     /// Command::cargo_bin("bin_fixture")
252     ///     .unwrap()
253     ///     .env("exit", "42")
254     ///     .assert()
255     ///     .code(&[2, 42] as &[i32]);
256     /// ```
257     ///
258     #[track_caller]
code<I, P>(self, pred: I) -> Self where I: IntoCodePredicate<P>, P: predicates_core::Predicate<i32>,259     pub fn code<I, P>(self, pred: I) -> Self
260     where
261         I: IntoCodePredicate<P>,
262         P: predicates_core::Predicate<i32>,
263     {
264         self.try_code(pred).unwrap_or_else(AssertError::panic)
265     }
266 
267     /// Variant of [`Assert::code`] that returns an [`AssertResult`].
try_code<I, P>(self, pred: I) -> AssertResult where I: IntoCodePredicate<P>, P: predicates_core::Predicate<i32>,268     pub fn try_code<I, P>(self, pred: I) -> AssertResult
269     where
270         I: IntoCodePredicate<P>,
271         P: predicates_core::Predicate<i32>,
272     {
273         self.code_impl(&pred.into_code())
274     }
275 
code_impl(self, pred: &dyn predicates_core::Predicate<i32>) -> AssertResult276     fn code_impl(self, pred: &dyn predicates_core::Predicate<i32>) -> AssertResult {
277         let actual_code = if let Some(actual_code) = self.output.status.code() {
278             actual_code
279         } else {
280             return Err(self.into_error(AssertReason::CommandInterrupted));
281         };
282         if let Some(case) = pred.find_case(false, &actual_code) {
283             return Err(self.into_error(AssertReason::UnexpectedReturnCode {
284                 case_tree: CaseTree(case.tree()),
285             }));
286         }
287         Ok(self)
288     }
289 
290     /// Ensure the command wrote the expected data to `stdout`.
291     ///
292     /// This uses [`IntoOutputPredicate`] to provide short-hands for common cases.
293     ///
294     /// See [`predicates`] for more predicates.
295     ///
296     /// # Examples
297     ///
298     /// Accepting a bytes predicate:
299     /// ```rust,no_run
300     /// use assert_cmd::prelude::*;
301     ///
302     /// use std::process::Command;
303     /// use predicates::prelude::*;
304     ///
305     /// Command::cargo_bin("bin_fixture")
306     ///     .unwrap()
307     ///     .env("stdout", "hello")
308     ///     .env("stderr", "world")
309     ///     .assert()
310     ///     .stdout(predicate::eq(b"hello\n" as &[u8]));
311     /// ```
312     ///
313     /// Accepting a `str` predicate:
314     /// ```rust,no_run
315     /// use assert_cmd::prelude::*;
316     ///
317     /// use std::process::Command;
318     /// use predicates::prelude::*;
319     ///
320     /// Command::cargo_bin("bin_fixture")
321     ///     .unwrap()
322     ///     .env("stdout", "hello")
323     ///     .env("stderr", "world")
324     ///     .assert()
325     ///     .stdout(predicate::str::diff("hello\n"));
326     /// ```
327     ///
328     /// Accepting bytes:
329     /// ```rust,no_run
330     /// use assert_cmd::prelude::*;
331     ///
332     /// use std::process::Command;
333     ///
334     /// Command::cargo_bin("bin_fixture")
335     ///     .unwrap()
336     ///     .env("stdout", "hello")
337     ///     .env("stderr", "world")
338     ///     .assert()
339     ///     .stdout(b"hello\n" as &[u8]);
340     /// ```
341     ///
342     /// Accepting a `str`:
343     /// ```rust,no_run
344     /// use assert_cmd::prelude::*;
345     ///
346     /// use std::process::Command;
347     ///
348     /// Command::cargo_bin("bin_fixture")
349     ///     .unwrap()
350     ///     .env("stdout", "hello")
351     ///     .env("stderr", "world")
352     ///     .assert()
353     ///     .stdout("hello\n");
354     /// ```
355     ///
356     #[track_caller]
stdout<I, P>(self, pred: I) -> Self where I: IntoOutputPredicate<P>, P: predicates_core::Predicate<[u8]>,357     pub fn stdout<I, P>(self, pred: I) -> Self
358     where
359         I: IntoOutputPredicate<P>,
360         P: predicates_core::Predicate<[u8]>,
361     {
362         self.try_stdout(pred).unwrap_or_else(AssertError::panic)
363     }
364 
365     /// Variant of [`Assert::stdout`] that returns an [`AssertResult`].
try_stdout<I, P>(self, pred: I) -> AssertResult where I: IntoOutputPredicate<P>, P: predicates_core::Predicate<[u8]>,366     pub fn try_stdout<I, P>(self, pred: I) -> AssertResult
367     where
368         I: IntoOutputPredicate<P>,
369         P: predicates_core::Predicate<[u8]>,
370     {
371         self.stdout_impl(&pred.into_output())
372     }
373 
stdout_impl(self, pred: &dyn predicates_core::Predicate<[u8]>) -> AssertResult374     fn stdout_impl(self, pred: &dyn predicates_core::Predicate<[u8]>) -> AssertResult {
375         {
376             let actual = &self.output.stdout;
377             if let Some(case) = pred.find_case(false, actual) {
378                 return Err(self.into_error(AssertReason::UnexpectedStdout {
379                     case_tree: CaseTree(case.tree()),
380                 }));
381             }
382         }
383         Ok(self)
384     }
385 
386     /// Ensure the command wrote the expected data to `stderr`.
387     ///
388     /// This uses [`IntoOutputPredicate`] to provide short-hands for common cases.
389     ///
390     /// See [`predicates`] for more predicates.
391     ///
392     /// # Examples
393     ///
394     /// Accepting a bytes predicate:
395     /// ```rust,no_run
396     /// use assert_cmd::prelude::*;
397     ///
398     /// use std::process::Command;
399     /// use predicates::prelude::*;
400     ///
401     /// Command::cargo_bin("bin_fixture")
402     ///     .unwrap()
403     ///     .env("stdout", "hello")
404     ///     .env("stderr", "world")
405     ///     .assert()
406     ///     .stderr(predicate::eq(b"world\n" as &[u8]));
407     /// ```
408     ///
409     /// Accepting a `str` predicate:
410     /// ```rust,no_run
411     /// use assert_cmd::prelude::*;
412     ///
413     /// use std::process::Command;
414     /// use predicates::prelude::*;
415     ///
416     /// Command::cargo_bin("bin_fixture")
417     ///     .unwrap()
418     ///     .env("stdout", "hello")
419     ///     .env("stderr", "world")
420     ///     .assert()
421     ///     .stderr(predicate::str::diff("world\n"));
422     /// ```
423     ///
424     /// Accepting bytes:
425     /// ```rust,no_run
426     /// use assert_cmd::prelude::*;
427     ///
428     /// use std::process::Command;
429     ///
430     /// Command::cargo_bin("bin_fixture")
431     ///     .unwrap()
432     ///     .env("stdout", "hello")
433     ///     .env("stderr", "world")
434     ///     .assert()
435     ///     .stderr(b"world\n" as &[u8]);
436     /// ```
437     ///
438     /// Accepting a `str`:
439     /// ```rust,no_run
440     /// use assert_cmd::prelude::*;
441     ///
442     /// use std::process::Command;
443     ///
444     /// Command::cargo_bin("bin_fixture")
445     ///     .unwrap()
446     ///     .env("stdout", "hello")
447     ///     .env("stderr", "world")
448     ///     .assert()
449     ///     .stderr("world\n");
450     /// ```
451     ///
452     #[track_caller]
stderr<I, P>(self, pred: I) -> Self where I: IntoOutputPredicate<P>, P: predicates_core::Predicate<[u8]>,453     pub fn stderr<I, P>(self, pred: I) -> Self
454     where
455         I: IntoOutputPredicate<P>,
456         P: predicates_core::Predicate<[u8]>,
457     {
458         self.try_stderr(pred).unwrap_or_else(AssertError::panic)
459     }
460 
461     /// Variant of [`Assert::stderr`] that returns an [`AssertResult`].
try_stderr<I, P>(self, pred: I) -> AssertResult where I: IntoOutputPredicate<P>, P: predicates_core::Predicate<[u8]>,462     pub fn try_stderr<I, P>(self, pred: I) -> AssertResult
463     where
464         I: IntoOutputPredicate<P>,
465         P: predicates_core::Predicate<[u8]>,
466     {
467         self.stderr_impl(&pred.into_output())
468     }
469 
stderr_impl(self, pred: &dyn predicates_core::Predicate<[u8]>) -> AssertResult470     fn stderr_impl(self, pred: &dyn predicates_core::Predicate<[u8]>) -> AssertResult {
471         {
472             let actual = &self.output.stderr;
473             if let Some(case) = pred.find_case(false, actual) {
474                 return Err(self.into_error(AssertReason::UnexpectedStderr {
475                     case_tree: CaseTree(case.tree()),
476                 }));
477             }
478         }
479         Ok(self)
480     }
481 }
482 
483 impl fmt::Display for Assert {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result484     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
485         let palette = crate::Palette::current();
486         for &(ref name, ref context) in &self.context {
487             writeln!(
488                 f,
489                 "{}=`{}`",
490                 palette.key.paint(name),
491                 palette.value.paint(context)
492             )?;
493         }
494         output_fmt(&self.output, f)
495     }
496 }
497 
498 impl fmt::Debug for Assert {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result499     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
500         f.debug_struct("Assert")
501             .field("output", &self.output)
502             .finish()
503     }
504 }
505 
506 /// Used by [`Assert::code`] to convert `Self` into the needed
507 /// [`predicates_core::Predicate<i32>`].
508 ///
509 /// # Examples
510 ///
511 /// ```rust,no_run
512 /// use assert_cmd::prelude::*;
513 ///
514 /// use std::process::Command;
515 /// use predicates::prelude::*;
516 ///
517 /// Command::cargo_bin("bin_fixture")
518 ///     .unwrap()
519 ///     .env("exit", "42")
520 ///     .assert()
521 ///     .code(predicate::eq(42));
522 ///
523 /// // which can be shortened to:
524 /// Command::cargo_bin("bin_fixture")
525 ///     .unwrap()
526 ///     .env("exit", "42")
527 ///     .assert()
528 ///     .code(42);
529 /// ```
530 pub trait IntoCodePredicate<P>
531 where
532     P: predicates_core::Predicate<i32>,
533 {
534     /// The type of the predicate being returned.
535     type Predicate;
536 
537     /// Convert to a predicate for testing a program's exit code.
into_code(self) -> P538     fn into_code(self) -> P;
539 }
540 
541 impl<P> IntoCodePredicate<P> for P
542 where
543     P: predicates_core::Predicate<i32>,
544 {
545     type Predicate = P;
546 
into_code(self) -> Self::Predicate547     fn into_code(self) -> Self::Predicate {
548         self
549     }
550 }
551 
552 /// Keep `predicates` concrete Predicates out of our public API.
553 /// [predicates_core::Predicate] used by [`IntoCodePredicate`] for code.
554 ///
555 /// # Example
556 ///
557 /// ```rust,no_run
558 /// use assert_cmd::prelude::*;
559 ///
560 /// use std::process::Command;
561 ///
562 /// Command::cargo_bin("bin_fixture")
563 ///     .unwrap()
564 ///     .env("exit", "42")
565 ///     .assert()
566 ///     .code(42);
567 /// ```
568 #[derive(Debug)]
569 pub struct EqCodePredicate(predicates::ord::EqPredicate<i32>);
570 
571 impl EqCodePredicate {
new(value: i32) -> Self572     pub(crate) fn new(value: i32) -> Self {
573         let pred = predicates::ord::eq(value);
574         EqCodePredicate(pred)
575     }
576 }
577 
578 impl predicates_core::reflection::PredicateReflection for EqCodePredicate {
parameters<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a>579     fn parameters<'a>(
580         &'a self,
581     ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a> {
582         self.0.parameters()
583     }
584 
585     /// Nested `Predicate`s of the current `Predicate`.
children<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a>586     fn children<'a>(
587         &'a self,
588     ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a> {
589         self.0.children()
590     }
591 }
592 
593 impl predicates_core::Predicate<i32> for EqCodePredicate {
eval(&self, item: &i32) -> bool594     fn eval(&self, item: &i32) -> bool {
595         self.0.eval(item)
596     }
597 
find_case<'a>( &'a self, expected: bool, variable: &i32, ) -> Option<predicates_core::reflection::Case<'a>>598     fn find_case<'a>(
599         &'a self,
600         expected: bool,
601         variable: &i32,
602     ) -> Option<predicates_core::reflection::Case<'a>> {
603         self.0.find_case(expected, variable)
604     }
605 }
606 
607 impl fmt::Display for EqCodePredicate {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result608     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
609         self.0.fmt(f)
610     }
611 }
612 
613 impl IntoCodePredicate<EqCodePredicate> for i32 {
614     type Predicate = EqCodePredicate;
615 
into_code(self) -> Self::Predicate616     fn into_code(self) -> Self::Predicate {
617         Self::Predicate::new(self)
618     }
619 }
620 
621 /// Keep `predicates` concrete Predicates out of our public API.
622 /// [predicates_core::Predicate] used by [`IntoCodePredicate`] for iterables of codes.
623 ///
624 /// # Example
625 ///
626 /// ```rust,no_run
627 /// use assert_cmd::prelude::*;
628 ///
629 /// use std::process::Command;
630 ///
631 /// Command::cargo_bin("bin_fixture")
632 ///     .unwrap()
633 ///     .env("exit", "42")
634 ///     .assert()
635 ///     .code(&[2, 42] as &[i32]);
636 /// ```
637 #[derive(Debug)]
638 pub struct InCodePredicate(predicates::iter::InPredicate<i32>);
639 
640 impl InCodePredicate {
new<I: IntoIterator<Item = i32>>(value: I) -> Self641     pub(crate) fn new<I: IntoIterator<Item = i32>>(value: I) -> Self {
642         let pred = predicates::iter::in_iter(value);
643         InCodePredicate(pred)
644     }
645 }
646 
647 impl predicates_core::reflection::PredicateReflection for InCodePredicate {
parameters<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a>648     fn parameters<'a>(
649         &'a self,
650     ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a> {
651         self.0.parameters()
652     }
653 
654     /// Nested `Predicate`s of the current `Predicate`.
children<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a>655     fn children<'a>(
656         &'a self,
657     ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a> {
658         self.0.children()
659     }
660 }
661 
662 impl predicates_core::Predicate<i32> for InCodePredicate {
eval(&self, item: &i32) -> bool663     fn eval(&self, item: &i32) -> bool {
664         self.0.eval(item)
665     }
666 
find_case<'a>( &'a self, expected: bool, variable: &i32, ) -> Option<predicates_core::reflection::Case<'a>>667     fn find_case<'a>(
668         &'a self,
669         expected: bool,
670         variable: &i32,
671     ) -> Option<predicates_core::reflection::Case<'a>> {
672         self.0.find_case(expected, variable)
673     }
674 }
675 
676 impl fmt::Display for InCodePredicate {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result677     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
678         self.0.fmt(f)
679     }
680 }
681 
682 impl IntoCodePredicate<InCodePredicate> for Vec<i32> {
683     type Predicate = InCodePredicate;
684 
into_code(self) -> Self::Predicate685     fn into_code(self) -> Self::Predicate {
686         Self::Predicate::new(self)
687     }
688 }
689 
690 impl IntoCodePredicate<InCodePredicate> for &'static [i32] {
691     type Predicate = InCodePredicate;
692 
into_code(self) -> Self::Predicate693     fn into_code(self) -> Self::Predicate {
694         Self::Predicate::new(self.iter().cloned())
695     }
696 }
697 
698 /// Used by [`Assert::stdout`] and [`Assert::stderr`] to convert Self
699 /// into the needed [`predicates_core::Predicate<[u8]>`].
700 ///
701 /// # Examples
702 ///
703 /// ```rust,no_run
704 /// use assert_cmd::prelude::*;
705 ///
706 /// use std::process::Command;
707 /// use predicates::prelude::*;
708 ///
709 /// Command::cargo_bin("bin_fixture")
710 ///     .unwrap()
711 ///     .env("stdout", "hello")
712 ///     .env("stderr", "world")
713 ///     .assert()
714 ///     .stdout(predicate::str::diff("hello\n").from_utf8());
715 ///
716 /// // which can be shortened to:
717 /// Command::cargo_bin("bin_fixture")
718 ///     .unwrap()
719 ///     .env("stdout", "hello")
720 ///     .env("stderr", "world")
721 ///     .assert()
722 ///     .stdout("hello\n");
723 /// ```
724 pub trait IntoOutputPredicate<P>
725 where
726     P: predicates_core::Predicate<[u8]>,
727 {
728     /// The type of the predicate being returned.
729     type Predicate;
730 
731     /// Convert to a predicate for testing a path.
into_output(self) -> P732     fn into_output(self) -> P;
733 }
734 
735 impl<P> IntoOutputPredicate<P> for P
736 where
737     P: predicates_core::Predicate<[u8]>,
738 {
739     type Predicate = P;
740 
into_output(self) -> Self::Predicate741     fn into_output(self) -> Self::Predicate {
742         self
743     }
744 }
745 
746 /// Keep `predicates` concrete Predicates out of our public API.
747 /// [predicates_core::Predicate] used by [`IntoOutputPredicate`] for bytes.
748 ///
749 /// # Example
750 ///
751 /// ```rust,no_run
752 /// use assert_cmd::prelude::*;
753 ///
754 /// use std::process::Command;
755 ///
756 /// Command::cargo_bin("bin_fixture")
757 ///     .unwrap()
758 ///     .env("stdout", "hello")
759 ///     .env("stderr", "world")
760 ///     .assert()
761 ///     .stderr(b"world\n" as &[u8]);
762 /// ```
763 #[derive(Debug)]
764 pub struct BytesContentOutputPredicate(Cow<'static, [u8]>);
765 
766 impl BytesContentOutputPredicate {
new(value: &'static [u8]) -> Self767     pub(crate) fn new(value: &'static [u8]) -> Self {
768         BytesContentOutputPredicate(Cow::from(value))
769     }
770 
from_vec(value: Vec<u8>) -> Self771     pub(crate) fn from_vec(value: Vec<u8>) -> Self {
772         BytesContentOutputPredicate(Cow::from(value))
773     }
774 }
775 
776 impl predicates_core::reflection::PredicateReflection for BytesContentOutputPredicate {}
777 
778 impl predicates_core::Predicate<[u8]> for BytesContentOutputPredicate {
eval(&self, item: &[u8]) -> bool779     fn eval(&self, item: &[u8]) -> bool {
780         self.0.as_ref() == item
781     }
782 
find_case( &self, expected: bool, variable: &[u8], ) -> Option<predicates_core::reflection::Case>783     fn find_case(
784         &self,
785         expected: bool,
786         variable: &[u8],
787     ) -> Option<predicates_core::reflection::Case> {
788         let actual = self.eval(variable);
789         if expected == actual {
790             Some(predicates_core::reflection::Case::new(Some(self), actual))
791         } else {
792             None
793         }
794     }
795 }
796 
797 impl fmt::Display for BytesContentOutputPredicate {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result798     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
799         predicates::ord::eq(self.0.as_ref()).fmt(f)
800     }
801 }
802 
803 impl IntoOutputPredicate<BytesContentOutputPredicate> for Vec<u8> {
804     type Predicate = BytesContentOutputPredicate;
805 
into_output(self) -> Self::Predicate806     fn into_output(self) -> Self::Predicate {
807         Self::Predicate::from_vec(self)
808     }
809 }
810 
811 impl IntoOutputPredicate<BytesContentOutputPredicate> for &'static [u8] {
812     type Predicate = BytesContentOutputPredicate;
813 
into_output(self) -> Self::Predicate814     fn into_output(self) -> Self::Predicate {
815         Self::Predicate::new(self)
816     }
817 }
818 
819 /// Keep `predicates` concrete Predicates out of our public API.
820 /// [predicates_core::Predicate] used by [`IntoOutputPredicate`] for [`str`].
821 ///
822 /// # Example
823 ///
824 /// ```rust,no_run
825 /// use assert_cmd::prelude::*;
826 ///
827 /// use std::process::Command;
828 ///
829 /// Command::cargo_bin("bin_fixture")
830 ///     .unwrap()
831 ///     .env("stdout", "hello")
832 ///     .env("stderr", "world")
833 ///     .assert()
834 ///     .stderr("world\n");
835 /// ```
836 ///
837 /// [`str`]: https://doc.rust-lang.org/std/primitive.str.html
838 #[derive(Debug, Clone)]
839 pub struct StrContentOutputPredicate(
840     predicates::str::Utf8Predicate<predicates::str::DifferencePredicate>,
841 );
842 
843 impl StrContentOutputPredicate {
from_str(value: &'static str) -> Self844     pub(crate) fn from_str(value: &'static str) -> Self {
845         let pred = predicates::str::diff(value).from_utf8();
846         StrContentOutputPredicate(pred)
847     }
848 
from_string(value: String) -> Self849     pub(crate) fn from_string(value: String) -> Self {
850         let pred = predicates::str::diff(value).from_utf8();
851         StrContentOutputPredicate(pred)
852     }
853 }
854 
855 impl predicates_core::reflection::PredicateReflection for StrContentOutputPredicate {
parameters<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a>856     fn parameters<'a>(
857         &'a self,
858     ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a> {
859         self.0.parameters()
860     }
861 
862     /// Nested `Predicate`s of the current `Predicate`.
children<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a>863     fn children<'a>(
864         &'a self,
865     ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a> {
866         self.0.children()
867     }
868 }
869 
870 impl predicates_core::Predicate<[u8]> for StrContentOutputPredicate {
eval(&self, item: &[u8]) -> bool871     fn eval(&self, item: &[u8]) -> bool {
872         self.0.eval(item)
873     }
874 
find_case<'a>( &'a self, expected: bool, variable: &[u8], ) -> Option<predicates_core::reflection::Case<'a>>875     fn find_case<'a>(
876         &'a self,
877         expected: bool,
878         variable: &[u8],
879     ) -> Option<predicates_core::reflection::Case<'a>> {
880         self.0.find_case(expected, variable)
881     }
882 }
883 
884 impl fmt::Display for StrContentOutputPredicate {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result885     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
886         self.0.fmt(f)
887     }
888 }
889 
890 impl IntoOutputPredicate<StrContentOutputPredicate> for String {
891     type Predicate = StrContentOutputPredicate;
892 
into_output(self) -> Self::Predicate893     fn into_output(self) -> Self::Predicate {
894         Self::Predicate::from_string(self)
895     }
896 }
897 
898 impl IntoOutputPredicate<StrContentOutputPredicate> for &'static str {
899     type Predicate = StrContentOutputPredicate;
900 
into_output(self) -> Self::Predicate901     fn into_output(self) -> Self::Predicate {
902         Self::Predicate::from_str(self)
903     }
904 }
905 
906 // Keep `predicates` concrete Predicates out of our public API.
907 /// [predicates_core::Predicate] used by [`IntoOutputPredicate`] for
908 /// [`Predicate<str>`][predicates_core::Predicate].
909 ///
910 /// # Example
911 ///
912 /// ```rust,no_run
913 /// use assert_cmd::prelude::*;
914 ///
915 /// use std::process::Command;
916 /// use predicates::prelude::*;
917 ///
918 /// Command::cargo_bin("bin_fixture")
919 ///     .unwrap()
920 ///     .env("stdout", "hello")
921 ///     .env("stderr", "world")
922 ///     .assert()
923 ///     .stderr(predicate::str::diff("world\n"));
924 /// ```
925 #[derive(Debug, Clone)]
926 pub struct StrOutputPredicate<P: predicates_core::Predicate<str>>(
927     predicates::str::Utf8Predicate<P>,
928 );
929 
930 impl<P> StrOutputPredicate<P>
931 where
932     P: predicates_core::Predicate<str>,
933 {
new(pred: P) -> Self934     pub(crate) fn new(pred: P) -> Self {
935         let pred = pred.from_utf8();
936         StrOutputPredicate(pred)
937     }
938 }
939 
940 impl<P> predicates_core::reflection::PredicateReflection for StrOutputPredicate<P>
941 where
942     P: predicates_core::Predicate<str>,
943 {
parameters<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a>944     fn parameters<'a>(
945         &'a self,
946     ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a> {
947         self.0.parameters()
948     }
949 
950     /// Nested `Predicate`s of the current `Predicate`.
children<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a>951     fn children<'a>(
952         &'a self,
953     ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a> {
954         self.0.children()
955     }
956 }
957 
958 impl<P> predicates_core::Predicate<[u8]> for StrOutputPredicate<P>
959 where
960     P: predicates_core::Predicate<str>,
961 {
eval(&self, item: &[u8]) -> bool962     fn eval(&self, item: &[u8]) -> bool {
963         self.0.eval(item)
964     }
965 
find_case<'a>( &'a self, expected: bool, variable: &[u8], ) -> Option<predicates_core::reflection::Case<'a>>966     fn find_case<'a>(
967         &'a self,
968         expected: bool,
969         variable: &[u8],
970     ) -> Option<predicates_core::reflection::Case<'a>> {
971         self.0.find_case(expected, variable)
972     }
973 }
974 
975 impl<P> fmt::Display for StrOutputPredicate<P>
976 where
977     P: predicates_core::Predicate<str>,
978 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result979     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
980         self.0.fmt(f)
981     }
982 }
983 
984 impl<P> IntoOutputPredicate<StrOutputPredicate<P>> for P
985 where
986     P: predicates_core::Predicate<str>,
987 {
988     type Predicate = StrOutputPredicate<P>;
989 
into_output(self) -> Self::Predicate990     fn into_output(self) -> Self::Predicate {
991         Self::Predicate::new(self)
992     }
993 }
994 
995 /// [`Assert`] represented as a [`Result`].
996 ///
997 /// Produced by the `try_` variants the [`Assert`] methods.
998 ///
999 /// # Example
1000 ///
1001 /// ```rust
1002 /// use assert_cmd::prelude::*;
1003 ///
1004 /// use std::process::Command;
1005 ///
1006 /// let result = Command::new("echo")
1007 ///     .assert()
1008 ///     .try_success();
1009 /// assert!(result.is_ok());
1010 /// ```
1011 ///
1012 /// [`Result`]: std::result::Result
1013 pub type AssertResult = Result<Assert, AssertError>;
1014 
1015 /// [`Assert`] error (see [`AssertResult`]).
1016 #[derive(Debug)]
1017 pub struct AssertError {
1018     assert: Assert,
1019     reason: AssertReason,
1020 }
1021 
1022 #[derive(Debug)]
1023 enum AssertReason {
1024     UnexpectedFailure { actual_code: Option<i32> },
1025     UnexpectedSuccess,
1026     UnexpectedCompletion,
1027     CommandInterrupted,
1028     UnexpectedReturnCode { case_tree: CaseTree },
1029     UnexpectedStdout { case_tree: CaseTree },
1030     UnexpectedStderr { case_tree: CaseTree },
1031 }
1032 
1033 impl AssertError {
1034     #[track_caller]
panic<T>(self) -> T1035     fn panic<T>(self) -> T {
1036         panic!("{}", self)
1037     }
1038 }
1039 
1040 impl Error for AssertError {}
1041 
1042 impl fmt::Display for AssertError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1043     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1044         match &self.reason {
1045             AssertReason::UnexpectedFailure { actual_code } => writeln!(
1046                 f,
1047                 "Unexpected failure.\ncode-{}\nstderr=```{}```",
1048                 actual_code.map_or("<interrupted>".to_owned(), |actual_code| actual_code
1049                     .to_string()),
1050                 DebugBytes::new(&self.assert.output.stderr),
1051             ),
1052             AssertReason::UnexpectedSuccess => {
1053                 writeln!(f, "Unexpected success")
1054             }
1055             AssertReason::UnexpectedCompletion => {
1056                 writeln!(f, "Unexpected completion")
1057             }
1058             AssertReason::CommandInterrupted => {
1059                 writeln!(f, "Command interrupted")
1060             }
1061             AssertReason::UnexpectedReturnCode { case_tree } => {
1062                 writeln!(f, "Unexpected return code, failed {}", case_tree)
1063             }
1064             AssertReason::UnexpectedStdout { case_tree } => {
1065                 writeln!(f, "Unexpected stdout, failed {}", case_tree)
1066             }
1067             AssertReason::UnexpectedStderr { case_tree } => {
1068                 writeln!(f, "Unexpected stderr, failed {}", case_tree)
1069             }
1070         }?;
1071         write!(f, "{}", self.assert)
1072     }
1073 }
1074 
1075 struct CaseTree(predicates_tree::CaseTree);
1076 
1077 impl fmt::Display for CaseTree {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1078     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1079         <predicates_tree::CaseTree as fmt::Display>::fmt(&self.0, f)
1080     }
1081 }
1082 
1083 // Work around `Debug` not being implemented for `predicates_tree::CaseTree`.
1084 impl fmt::Debug for CaseTree {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1085     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1086         <predicates_tree::CaseTree as fmt::Display>::fmt(&self.0, f)
1087     }
1088 }
1089 
1090 #[cfg(test)]
1091 mod test {
1092     use super::*;
1093 
1094     use predicates::prelude::*;
1095 
1096     // Since IntoCodePredicate exists solely for conversion, test it under that scenario to ensure
1097     // it works as expected.
convert_code<I, P>(pred: I) -> P where I: IntoCodePredicate<P>, P: predicates_core::Predicate<i32>,1098     fn convert_code<I, P>(pred: I) -> P
1099     where
1100         I: IntoCodePredicate<P>,
1101         P: predicates_core::Predicate<i32>,
1102     {
1103         pred.into_code()
1104     }
1105 
1106     #[test]
into_code_from_pred()1107     fn into_code_from_pred() {
1108         let pred = convert_code(predicate::eq(10));
1109         assert!(pred.eval(&10));
1110     }
1111 
1112     #[test]
into_code_from_i32()1113     fn into_code_from_i32() {
1114         let pred = convert_code(10);
1115         assert!(pred.eval(&10));
1116     }
1117 
1118     #[test]
into_code_from_vec()1119     fn into_code_from_vec() {
1120         let pred = convert_code(vec![3, 10]);
1121         assert!(pred.eval(&10));
1122     }
1123 
1124     #[test]
into_code_from_array()1125     fn into_code_from_array() {
1126         let pred = convert_code(&[3, 10] as &[i32]);
1127         assert!(pred.eval(&10));
1128     }
1129 
1130     // Since IntoOutputPredicate exists solely for conversion, test it under that scenario to ensure
1131     // it works as expected.
convert_output<I, P>(pred: I) -> P where I: IntoOutputPredicate<P>, P: predicates_core::Predicate<[u8]>,1132     fn convert_output<I, P>(pred: I) -> P
1133     where
1134         I: IntoOutputPredicate<P>,
1135         P: predicates_core::Predicate<[u8]>,
1136     {
1137         pred.into_output()
1138     }
1139 
1140     #[test]
into_output_from_pred()1141     fn into_output_from_pred() {
1142         let pred = convert_output(predicate::eq(b"Hello" as &[u8]));
1143         assert!(pred.eval(b"Hello" as &[u8]));
1144     }
1145 
1146     #[test]
into_output_from_bytes()1147     fn into_output_from_bytes() {
1148         let pred = convert_output(b"Hello" as &[u8]);
1149         assert!(pred.eval(b"Hello" as &[u8]));
1150     }
1151 
1152     #[test]
into_output_from_vec()1153     fn into_output_from_vec() {
1154         let pred = convert_output(vec![b'H', b'e', b'l', b'l', b'o']);
1155         assert!(pred.eval(b"Hello" as &[u8]));
1156     }
1157 
1158     #[test]
into_output_from_str()1159     fn into_output_from_str() {
1160         let pred = convert_output("Hello");
1161         assert!(pred.eval(b"Hello" as &[u8]));
1162     }
1163 }
1164