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         for &(ref name, ref context) in &self.context {
486             writeln!(f, "{}=`{}`", name, context)?;
487         }
488         output_fmt(&self.output, f)
489     }
490 }
491 
492 impl fmt::Debug for Assert {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result493     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
494         f.debug_struct("Assert")
495             .field("output", &self.output)
496             .finish()
497     }
498 }
499 
500 /// Used by [`Assert::code`] to convert `Self` into the needed
501 /// [`predicates_core::Predicate<i32>`].
502 ///
503 /// # Examples
504 ///
505 /// ```rust,no_run
506 /// use assert_cmd::prelude::*;
507 ///
508 /// use std::process::Command;
509 /// use predicates::prelude::*;
510 ///
511 /// Command::cargo_bin("bin_fixture")
512 ///     .unwrap()
513 ///     .env("exit", "42")
514 ///     .assert()
515 ///     .code(predicate::eq(42));
516 ///
517 /// // which can be shortened to:
518 /// Command::cargo_bin("bin_fixture")
519 ///     .unwrap()
520 ///     .env("exit", "42")
521 ///     .assert()
522 ///     .code(42);
523 /// ```
524 pub trait IntoCodePredicate<P>
525 where
526     P: predicates_core::Predicate<i32>,
527 {
528     /// The type of the predicate being returned.
529     type Predicate;
530 
531     /// Convert to a predicate for testing a program's exit code.
into_code(self) -> P532     fn into_code(self) -> P;
533 }
534 
535 impl<P> IntoCodePredicate<P> for P
536 where
537     P: predicates_core::Predicate<i32>,
538 {
539     type Predicate = P;
540 
into_code(self) -> Self::Predicate541     fn into_code(self) -> Self::Predicate {
542         self
543     }
544 }
545 
546 /// Keep `predicates` concrete Predicates out of our public API.
547 /// [predicates_core::Predicate] used by [`IntoCodePredicate`] for code.
548 ///
549 /// # Example
550 ///
551 /// ```rust,no_run
552 /// use assert_cmd::prelude::*;
553 ///
554 /// use std::process::Command;
555 ///
556 /// Command::cargo_bin("bin_fixture")
557 ///     .unwrap()
558 ///     .env("exit", "42")
559 ///     .assert()
560 ///     .code(42);
561 /// ```
562 #[derive(Debug)]
563 pub struct EqCodePredicate(predicates::ord::EqPredicate<i32>);
564 
565 impl EqCodePredicate {
new(value: i32) -> Self566     pub(crate) fn new(value: i32) -> Self {
567         let pred = predicates::ord::eq(value);
568         EqCodePredicate(pred)
569     }
570 }
571 
572 impl predicates_core::reflection::PredicateReflection for EqCodePredicate {
parameters<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a>573     fn parameters<'a>(
574         &'a self,
575     ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a> {
576         self.0.parameters()
577     }
578 
579     /// Nested `Predicate`s of the current `Predicate`.
children<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a>580     fn children<'a>(
581         &'a self,
582     ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a> {
583         self.0.children()
584     }
585 }
586 
587 impl predicates_core::Predicate<i32> for EqCodePredicate {
eval(&self, item: &i32) -> bool588     fn eval(&self, item: &i32) -> bool {
589         self.0.eval(item)
590     }
591 
find_case<'a>( &'a self, expected: bool, variable: &i32, ) -> Option<predicates_core::reflection::Case<'a>>592     fn find_case<'a>(
593         &'a self,
594         expected: bool,
595         variable: &i32,
596     ) -> Option<predicates_core::reflection::Case<'a>> {
597         self.0.find_case(expected, variable)
598     }
599 }
600 
601 impl fmt::Display for EqCodePredicate {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result602     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
603         self.0.fmt(f)
604     }
605 }
606 
607 impl IntoCodePredicate<EqCodePredicate> for i32 {
608     type Predicate = EqCodePredicate;
609 
into_code(self) -> Self::Predicate610     fn into_code(self) -> Self::Predicate {
611         Self::Predicate::new(self)
612     }
613 }
614 
615 /// Keep `predicates` concrete Predicates out of our public API.
616 /// [predicates_core::Predicate] used by [`IntoCodePredicate`] for iterables of codes.
617 ///
618 /// # Example
619 ///
620 /// ```rust,no_run
621 /// use assert_cmd::prelude::*;
622 ///
623 /// use std::process::Command;
624 ///
625 /// Command::cargo_bin("bin_fixture")
626 ///     .unwrap()
627 ///     .env("exit", "42")
628 ///     .assert()
629 ///     .code(&[2, 42] as &[i32]);
630 /// ```
631 #[derive(Debug)]
632 pub struct InCodePredicate(predicates::iter::InPredicate<i32>);
633 
634 impl InCodePredicate {
new<I: IntoIterator<Item = i32>>(value: I) -> Self635     pub(crate) fn new<I: IntoIterator<Item = i32>>(value: I) -> Self {
636         let pred = predicates::iter::in_iter(value);
637         InCodePredicate(pred)
638     }
639 }
640 
641 impl predicates_core::reflection::PredicateReflection for InCodePredicate {
parameters<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a>642     fn parameters<'a>(
643         &'a self,
644     ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a> {
645         self.0.parameters()
646     }
647 
648     /// Nested `Predicate`s of the current `Predicate`.
children<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a>649     fn children<'a>(
650         &'a self,
651     ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a> {
652         self.0.children()
653     }
654 }
655 
656 impl predicates_core::Predicate<i32> for InCodePredicate {
eval(&self, item: &i32) -> bool657     fn eval(&self, item: &i32) -> bool {
658         self.0.eval(item)
659     }
660 
find_case<'a>( &'a self, expected: bool, variable: &i32, ) -> Option<predicates_core::reflection::Case<'a>>661     fn find_case<'a>(
662         &'a self,
663         expected: bool,
664         variable: &i32,
665     ) -> Option<predicates_core::reflection::Case<'a>> {
666         self.0.find_case(expected, variable)
667     }
668 }
669 
670 impl fmt::Display for InCodePredicate {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result671     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
672         self.0.fmt(f)
673     }
674 }
675 
676 impl IntoCodePredicate<InCodePredicate> for Vec<i32> {
677     type Predicate = InCodePredicate;
678 
into_code(self) -> Self::Predicate679     fn into_code(self) -> Self::Predicate {
680         Self::Predicate::new(self)
681     }
682 }
683 
684 impl IntoCodePredicate<InCodePredicate> for &'static [i32] {
685     type Predicate = InCodePredicate;
686 
into_code(self) -> Self::Predicate687     fn into_code(self) -> Self::Predicate {
688         Self::Predicate::new(self.iter().cloned())
689     }
690 }
691 
692 /// Used by [`Assert::stdout`] and [`Assert::stderr`] to convert Self
693 /// into the needed [`predicates_core::Predicate<[u8]>`].
694 ///
695 /// # Examples
696 ///
697 /// ```rust,no_run
698 /// use assert_cmd::prelude::*;
699 ///
700 /// use std::process::Command;
701 /// use predicates::prelude::*;
702 ///
703 /// Command::cargo_bin("bin_fixture")
704 ///     .unwrap()
705 ///     .env("stdout", "hello")
706 ///     .env("stderr", "world")
707 ///     .assert()
708 ///     .stdout(predicate::str::diff("hello\n").from_utf8());
709 ///
710 /// // which can be shortened to:
711 /// Command::cargo_bin("bin_fixture")
712 ///     .unwrap()
713 ///     .env("stdout", "hello")
714 ///     .env("stderr", "world")
715 ///     .assert()
716 ///     .stdout("hello\n");
717 /// ```
718 pub trait IntoOutputPredicate<P>
719 where
720     P: predicates_core::Predicate<[u8]>,
721 {
722     /// The type of the predicate being returned.
723     type Predicate;
724 
725     /// Convert to a predicate for testing a path.
into_output(self) -> P726     fn into_output(self) -> P;
727 }
728 
729 impl<P> IntoOutputPredicate<P> for P
730 where
731     P: predicates_core::Predicate<[u8]>,
732 {
733     type Predicate = P;
734 
into_output(self) -> Self::Predicate735     fn into_output(self) -> Self::Predicate {
736         self
737     }
738 }
739 
740 /// Keep `predicates` concrete Predicates out of our public API.
741 /// [predicates_core::Predicate] used by [`IntoOutputPredicate`] for bytes.
742 ///
743 /// # Example
744 ///
745 /// ```rust,no_run
746 /// use assert_cmd::prelude::*;
747 ///
748 /// use std::process::Command;
749 ///
750 /// Command::cargo_bin("bin_fixture")
751 ///     .unwrap()
752 ///     .env("stdout", "hello")
753 ///     .env("stderr", "world")
754 ///     .assert()
755 ///     .stderr(b"world\n" as &[u8]);
756 /// ```
757 #[derive(Debug)]
758 pub struct BytesContentOutputPredicate(Cow<'static, [u8]>);
759 
760 impl BytesContentOutputPredicate {
new(value: &'static [u8]) -> Self761     pub(crate) fn new(value: &'static [u8]) -> Self {
762         BytesContentOutputPredicate(Cow::from(value))
763     }
764 
from_vec(value: Vec<u8>) -> Self765     pub(crate) fn from_vec(value: Vec<u8>) -> Self {
766         BytesContentOutputPredicate(Cow::from(value))
767     }
768 }
769 
770 impl predicates_core::reflection::PredicateReflection for BytesContentOutputPredicate {}
771 
772 impl predicates_core::Predicate<[u8]> for BytesContentOutputPredicate {
eval(&self, item: &[u8]) -> bool773     fn eval(&self, item: &[u8]) -> bool {
774         self.0.as_ref() == item
775     }
776 
find_case( &self, expected: bool, variable: &[u8], ) -> Option<predicates_core::reflection::Case>777     fn find_case(
778         &self,
779         expected: bool,
780         variable: &[u8],
781     ) -> Option<predicates_core::reflection::Case> {
782         let actual = self.eval(variable);
783         if expected == actual {
784             Some(predicates_core::reflection::Case::new(Some(self), actual))
785         } else {
786             None
787         }
788     }
789 }
790 
791 impl fmt::Display for BytesContentOutputPredicate {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result792     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
793         predicates::ord::eq(self.0.as_ref()).fmt(f)
794     }
795 }
796 
797 impl IntoOutputPredicate<BytesContentOutputPredicate> for Vec<u8> {
798     type Predicate = BytesContentOutputPredicate;
799 
into_output(self) -> Self::Predicate800     fn into_output(self) -> Self::Predicate {
801         Self::Predicate::from_vec(self)
802     }
803 }
804 
805 impl IntoOutputPredicate<BytesContentOutputPredicate> for &'static [u8] {
806     type Predicate = BytesContentOutputPredicate;
807 
into_output(self) -> Self::Predicate808     fn into_output(self) -> Self::Predicate {
809         Self::Predicate::new(self)
810     }
811 }
812 
813 /// Keep `predicates` concrete Predicates out of our public API.
814 /// [predicates_core::Predicate] used by [`IntoOutputPredicate`] for [`str`].
815 ///
816 /// # Example
817 ///
818 /// ```rust,no_run
819 /// use assert_cmd::prelude::*;
820 ///
821 /// use std::process::Command;
822 ///
823 /// Command::cargo_bin("bin_fixture")
824 ///     .unwrap()
825 ///     .env("stdout", "hello")
826 ///     .env("stderr", "world")
827 ///     .assert()
828 ///     .stderr("world\n");
829 /// ```
830 ///
831 /// [`str`]: https://doc.rust-lang.org/std/primitive.str.html
832 #[derive(Debug, Clone)]
833 pub struct StrContentOutputPredicate(
834     predicates::str::Utf8Predicate<predicates::str::DifferencePredicate>,
835 );
836 
837 impl StrContentOutputPredicate {
from_str(value: &'static str) -> Self838     pub(crate) fn from_str(value: &'static str) -> Self {
839         let pred = predicates::str::diff(value).from_utf8();
840         StrContentOutputPredicate(pred)
841     }
842 
from_string(value: String) -> Self843     pub(crate) fn from_string(value: String) -> Self {
844         let pred = predicates::str::diff(value).from_utf8();
845         StrContentOutputPredicate(pred)
846     }
847 }
848 
849 impl predicates_core::reflection::PredicateReflection for StrContentOutputPredicate {
parameters<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a>850     fn parameters<'a>(
851         &'a self,
852     ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a> {
853         self.0.parameters()
854     }
855 
856     /// Nested `Predicate`s of the current `Predicate`.
children<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a>857     fn children<'a>(
858         &'a self,
859     ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a> {
860         self.0.children()
861     }
862 }
863 
864 impl predicates_core::Predicate<[u8]> for StrContentOutputPredicate {
eval(&self, item: &[u8]) -> bool865     fn eval(&self, item: &[u8]) -> bool {
866         self.0.eval(item)
867     }
868 
find_case<'a>( &'a self, expected: bool, variable: &[u8], ) -> Option<predicates_core::reflection::Case<'a>>869     fn find_case<'a>(
870         &'a self,
871         expected: bool,
872         variable: &[u8],
873     ) -> Option<predicates_core::reflection::Case<'a>> {
874         self.0.find_case(expected, variable)
875     }
876 }
877 
878 impl fmt::Display for StrContentOutputPredicate {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result879     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
880         self.0.fmt(f)
881     }
882 }
883 
884 impl IntoOutputPredicate<StrContentOutputPredicate> for String {
885     type Predicate = StrContentOutputPredicate;
886 
into_output(self) -> Self::Predicate887     fn into_output(self) -> Self::Predicate {
888         Self::Predicate::from_string(self)
889     }
890 }
891 
892 impl IntoOutputPredicate<StrContentOutputPredicate> for &'static str {
893     type Predicate = StrContentOutputPredicate;
894 
into_output(self) -> Self::Predicate895     fn into_output(self) -> Self::Predicate {
896         Self::Predicate::from_str(self)
897     }
898 }
899 
900 // Keep `predicates` concrete Predicates out of our public API.
901 /// [predicates_core::Predicate] used by [`IntoOutputPredicate`] for
902 /// [`Predicate<str>`][predicates_core::Predicate].
903 ///
904 /// # Example
905 ///
906 /// ```rust,no_run
907 /// use assert_cmd::prelude::*;
908 ///
909 /// use std::process::Command;
910 /// use predicates::prelude::*;
911 ///
912 /// Command::cargo_bin("bin_fixture")
913 ///     .unwrap()
914 ///     .env("stdout", "hello")
915 ///     .env("stderr", "world")
916 ///     .assert()
917 ///     .stderr(predicate::str::diff("world\n"));
918 /// ```
919 #[derive(Debug, Clone)]
920 pub struct StrOutputPredicate<P: predicates_core::Predicate<str>>(
921     predicates::str::Utf8Predicate<P>,
922 );
923 
924 impl<P> StrOutputPredicate<P>
925 where
926     P: predicates_core::Predicate<str>,
927 {
new(pred: P) -> Self928     pub(crate) fn new(pred: P) -> Self {
929         let pred = pred.from_utf8();
930         StrOutputPredicate(pred)
931     }
932 }
933 
934 impl<P> predicates_core::reflection::PredicateReflection for StrOutputPredicate<P>
935 where
936     P: predicates_core::Predicate<str>,
937 {
parameters<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a>938     fn parameters<'a>(
939         &'a self,
940     ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a> {
941         self.0.parameters()
942     }
943 
944     /// Nested `Predicate`s of the current `Predicate`.
children<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a>945     fn children<'a>(
946         &'a self,
947     ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a> {
948         self.0.children()
949     }
950 }
951 
952 impl<P> predicates_core::Predicate<[u8]> for StrOutputPredicate<P>
953 where
954     P: predicates_core::Predicate<str>,
955 {
eval(&self, item: &[u8]) -> bool956     fn eval(&self, item: &[u8]) -> bool {
957         self.0.eval(item)
958     }
959 
find_case<'a>( &'a self, expected: bool, variable: &[u8], ) -> Option<predicates_core::reflection::Case<'a>>960     fn find_case<'a>(
961         &'a self,
962         expected: bool,
963         variable: &[u8],
964     ) -> Option<predicates_core::reflection::Case<'a>> {
965         self.0.find_case(expected, variable)
966     }
967 }
968 
969 impl<P> fmt::Display for StrOutputPredicate<P>
970 where
971     P: predicates_core::Predicate<str>,
972 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result973     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
974         self.0.fmt(f)
975     }
976 }
977 
978 impl<P> IntoOutputPredicate<StrOutputPredicate<P>> for P
979 where
980     P: predicates_core::Predicate<str>,
981 {
982     type Predicate = StrOutputPredicate<P>;
983 
into_output(self) -> Self::Predicate984     fn into_output(self) -> Self::Predicate {
985         Self::Predicate::new(self)
986     }
987 }
988 
989 /// [`Assert`] represented as a [`Result`].
990 ///
991 /// Produced by the `try_` variants the [`Assert`] methods.
992 ///
993 /// # Example
994 ///
995 /// ```rust
996 /// use assert_cmd::prelude::*;
997 ///
998 /// use std::process::Command;
999 ///
1000 /// let result = Command::new("echo")
1001 ///     .assert()
1002 ///     .try_success();
1003 /// assert!(result.is_ok());
1004 /// ```
1005 ///
1006 /// [`Result`]: std::result::Result
1007 pub type AssertResult = Result<Assert, AssertError>;
1008 
1009 /// [`Assert`] error (see [`AssertResult`]).
1010 #[derive(Debug)]
1011 pub struct AssertError {
1012     assert: Assert,
1013     reason: AssertReason,
1014 }
1015 
1016 #[derive(Debug)]
1017 enum AssertReason {
1018     UnexpectedFailure { actual_code: Option<i32> },
1019     UnexpectedSuccess,
1020     UnexpectedCompletion,
1021     CommandInterrupted,
1022     UnexpectedReturnCode { case_tree: CaseTree },
1023     UnexpectedStdout { case_tree: CaseTree },
1024     UnexpectedStderr { case_tree: CaseTree },
1025 }
1026 
1027 impl AssertError {
1028     #[track_caller]
panic<T>(self) -> T1029     fn panic<T>(self) -> T {
1030         panic!("{}", self)
1031     }
1032 }
1033 
1034 impl Error for AssertError {}
1035 
1036 impl fmt::Display for AssertError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1037     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1038         match &self.reason {
1039             AssertReason::UnexpectedFailure { actual_code } => writeln!(
1040                 f,
1041                 "Unexpected failure.\ncode-{}\nstderr=```{}```",
1042                 actual_code.map_or("<interrupted>".to_owned(), |actual_code| actual_code
1043                     .to_string()),
1044                 DebugBytes::new(&self.assert.output.stderr),
1045             ),
1046             AssertReason::UnexpectedSuccess => {
1047                 writeln!(f, "Unexpected success")
1048             }
1049             AssertReason::UnexpectedCompletion => {
1050                 writeln!(f, "Unexpected completion")
1051             }
1052             AssertReason::CommandInterrupted => {
1053                 writeln!(f, "Command interrupted")
1054             }
1055             AssertReason::UnexpectedReturnCode { case_tree } => {
1056                 writeln!(f, "Unexpected return code, failed {}", case_tree)
1057             }
1058             AssertReason::UnexpectedStdout { case_tree } => {
1059                 writeln!(f, "Unexpected stdout, failed {}", case_tree)
1060             }
1061             AssertReason::UnexpectedStderr { case_tree } => {
1062                 writeln!(f, "Unexpected stderr, failed {}", case_tree)
1063             }
1064         }?;
1065         write!(f, "{}", self.assert)
1066     }
1067 }
1068 
1069 struct CaseTree(predicates_tree::CaseTree);
1070 
1071 impl fmt::Display for CaseTree {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1072     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1073         <predicates_tree::CaseTree as fmt::Display>::fmt(&self.0, f)
1074     }
1075 }
1076 
1077 // Work around `Debug` not being implemented for `predicates_tree::CaseTree`.
1078 impl fmt::Debug for CaseTree {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1079     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1080         <predicates_tree::CaseTree as fmt::Display>::fmt(&self.0, f)
1081     }
1082 }
1083 
1084 #[cfg(test)]
1085 mod test {
1086     use super::*;
1087 
1088     use predicates::prelude::*;
1089 
1090     // Since IntoCodePredicate exists solely for conversion, test it under that scenario to ensure
1091     // it works as expected.
convert_code<I, P>(pred: I) -> P where I: IntoCodePredicate<P>, P: predicates_core::Predicate<i32>,1092     fn convert_code<I, P>(pred: I) -> P
1093     where
1094         I: IntoCodePredicate<P>,
1095         P: predicates_core::Predicate<i32>,
1096     {
1097         pred.into_code()
1098     }
1099 
1100     #[test]
into_code_from_pred()1101     fn into_code_from_pred() {
1102         let pred = convert_code(predicate::eq(10));
1103         assert!(pred.eval(&10));
1104     }
1105 
1106     #[test]
into_code_from_i32()1107     fn into_code_from_i32() {
1108         let pred = convert_code(10);
1109         assert!(pred.eval(&10));
1110     }
1111 
1112     #[test]
into_code_from_vec()1113     fn into_code_from_vec() {
1114         let pred = convert_code(vec![3, 10]);
1115         assert!(pred.eval(&10));
1116     }
1117 
1118     #[test]
into_code_from_array()1119     fn into_code_from_array() {
1120         let pred = convert_code(&[3, 10] as &[i32]);
1121         assert!(pred.eval(&10));
1122     }
1123 
1124     // Since IntoOutputPredicate exists solely for conversion, test it under that scenario to ensure
1125     // it works as expected.
convert_output<I, P>(pred: I) -> P where I: IntoOutputPredicate<P>, P: predicates_core::Predicate<[u8]>,1126     fn convert_output<I, P>(pred: I) -> P
1127     where
1128         I: IntoOutputPredicate<P>,
1129         P: predicates_core::Predicate<[u8]>,
1130     {
1131         pred.into_output()
1132     }
1133 
1134     #[test]
into_output_from_pred()1135     fn into_output_from_pred() {
1136         let pred = convert_output(predicate::eq(b"Hello" as &[u8]));
1137         assert!(pred.eval(b"Hello" as &[u8]));
1138     }
1139 
1140     #[test]
into_output_from_bytes()1141     fn into_output_from_bytes() {
1142         let pred = convert_output(b"Hello" as &[u8]);
1143         assert!(pred.eval(b"Hello" as &[u8]));
1144     }
1145 
1146     #[test]
into_output_from_vec()1147     fn into_output_from_vec() {
1148         let pred = convert_output(vec![b'H', b'e', b'l', b'l', b'o']);
1149         assert!(pred.eval(b"Hello" as &[u8]));
1150     }
1151 
1152     #[test]
into_output_from_str()1153     fn into_output_from_str() {
1154         let pred = convert_output("Hello");
1155         assert!(pred.eval(b"Hello" as &[u8]));
1156     }
1157 }
1158