1 //! [`std::process::Output`] assertions.
2 
3 use std::borrow::Cow;
4 use std::fmt;
5 use std::process;
6 use std::str;
7 
8 use predicates::str::PredicateStrExt;
9 use predicates_tree::CaseTreeExt;
10 
11 use crate::output::output_fmt;
12 use crate::output::DebugBytes;
13 
14 /// Assert the state of an [`Output`].
15 ///
16 /// # Examples
17 ///
18 /// ```rust,no_run
19 /// use assert_cmd::prelude::*;
20 ///
21 /// use std::process::Command;
22 ///
23 /// let mut cmd = Command::cargo_bin("bin_fixture")
24 ///     .unwrap();
25 /// cmd.assert()
26 ///     .success();
27 /// ```
28 ///
29 /// [`Output`]: std::process::Output
30 pub trait OutputAssertExt {
31     /// Wrap with an interface for that provides assertions on the [`Output`].
32     ///
33     /// # Examples
34     ///
35     /// ```rust,no_run
36     /// use assert_cmd::prelude::*;
37     ///
38     /// use std::process::Command;
39     ///
40     /// let mut cmd = Command::cargo_bin("bin_fixture")
41     ///     .unwrap();
42     /// cmd.assert()
43     ///     .success();
44     /// ```
45     ///
46     /// [`Output`]: std::process::Output
assert(self) -> Assert47     fn assert(self) -> Assert;
48 }
49 
50 impl OutputAssertExt for process::Output {
assert(self) -> Assert51     fn assert(self) -> Assert {
52         Assert::new(self)
53     }
54 }
55 
56 impl<'c> OutputAssertExt for &'c mut process::Command {
assert(self) -> Assert57     fn assert(self) -> Assert {
58         let output = match self.output() {
59             Ok(output) => output,
60             Err(err) => {
61                 panic!("Failed to spawn {:?}: {}", self, err);
62             }
63         };
64         Assert::new(output).append_context("command", format!("{:?}", self))
65     }
66 }
67 
68 /// Assert the state of an [`Output`].
69 ///
70 /// Create an `Assert` through the [`OutputAssertExt`] trait.
71 ///
72 /// # Examples
73 ///
74 /// ```rust,no_run
75 /// use assert_cmd::prelude::*;
76 ///
77 /// use std::process::Command;
78 ///
79 /// let mut cmd = Command::cargo_bin("bin_fixture")
80 ///     .unwrap();
81 /// cmd.assert()
82 ///     .success();
83 /// ```
84 ///
85 /// [`Output`]: std::process::Output
86 pub struct Assert {
87     output: process::Output,
88     context: Vec<(&'static str, Box<dyn fmt::Display>)>,
89 }
90 
91 impl Assert {
92     /// Create an `Assert` for a given [`Output`].
93     ///
94     /// [`Output`]: std::process::Output
new(output: process::Output) -> Self95     pub fn new(output: process::Output) -> Self {
96         Self {
97             output,
98             context: vec![],
99         }
100     }
101 
102     /// Clarify failures with additional context.
103     ///
104     /// # Examples
105     ///
106     /// ```rust,no_run
107     /// use assert_cmd::prelude::*;
108     ///
109     /// use std::process::Command;
110     ///
111     /// Command::cargo_bin("bin_fixture")
112     ///     .unwrap()
113     ///     .assert()
114     ///     .append_context("main", "no args")
115     ///     .success();
116     /// ```
append_context<D>(mut self, name: &'static str, context: D) -> Self where D: fmt::Display + 'static,117     pub fn append_context<D>(mut self, name: &'static str, context: D) -> Self
118     where
119         D: fmt::Display + 'static,
120     {
121         self.context.push((name, Box::new(context)));
122         self
123     }
124 
125     /// Access the contained [`Output`].
126     ///
127     /// [`Output`]: std::process::Output
get_output(&self) -> &process::Output128     pub fn get_output(&self) -> &process::Output {
129         &self.output
130     }
131 
132     /// Ensure the command succeeded.
133     ///
134     /// # Examples
135     ///
136     /// ```rust,no_run
137     /// use assert_cmd::prelude::*;
138     ///
139     /// use std::process::Command;
140     ///
141     /// Command::cargo_bin("bin_fixture")
142     ///     .unwrap()
143     ///     .assert()
144     ///     .success();
145     /// ```
success(self) -> Self146     pub fn success(self) -> Self {
147         if !self.output.status.success() {
148             let actual_code = self.output.status.code().unwrap_or_else(|| {
149                 panic!(
150                     "Unexpected failure.\ncode=<interrupted>\nstderr=```{}```\n{}",
151                     DebugBytes::new(&self.output.stderr),
152                     self
153                 )
154             });
155             panic!(
156                 "Unexpected failure.\ncode-{}\nstderr=```{}```\n{}",
157                 actual_code,
158                 DebugBytes::new(&self.output.stderr),
159                 self
160             );
161         }
162         self
163     }
164 
165     /// Ensure the command failed.
166     ///
167     /// # Examples
168     ///
169     /// ```rust,no_run
170     /// use assert_cmd::prelude::*;
171     ///
172     /// use std::process::Command;
173     ///
174     /// Command::cargo_bin("bin_fixture")
175     ///     .unwrap()
176     ///     .env("exit", "1")
177     ///     .assert()
178     ///     .failure();
179     /// ```
failure(self) -> Self180     pub fn failure(self) -> Self {
181         if self.output.status.success() {
182             panic!("Unexpected success\n{}", self);
183         }
184         self
185     }
186 
187     /// Ensure the command aborted before returning a code.
interrupted(self) -> Self188     pub fn interrupted(self) -> Self {
189         if self.output.status.code().is_some() {
190             panic!("Unexpected completion\n{}", self);
191         }
192         self
193     }
194 
195     /// Ensure the command returned the expected code.
196     ///
197     /// This uses [`IntoCodePredicate`] to provide short-hands for common cases.
198     ///
199     /// See [`predicates`] for more predicates.
200     ///
201     /// # Examples
202     ///
203     /// Accepting a predicate:
204     /// ```rust,no_run
205     /// use assert_cmd::prelude::*;
206     ///
207     /// use std::process::Command;
208     /// use predicates::prelude::*;
209     ///
210     /// Command::cargo_bin("bin_fixture")
211     ///     .unwrap()
212     ///     .env("exit", "42")
213     ///     .assert()
214     ///     .code(predicate::eq(42));
215     /// ```
216     ///
217     /// Accepting an exit code:
218     /// ```rust,no_run
219     /// use assert_cmd::prelude::*;
220     ///
221     /// use std::process::Command;
222     ///
223     /// Command::cargo_bin("bin_fixture")
224     ///     .unwrap()
225     ///     .env("exit", "42")
226     ///     .assert()
227     ///     .code(42);
228     /// ```
229     ///
230     /// Accepting multiple exit codes:
231     /// ```rust,no_run
232     /// use assert_cmd::prelude::*;
233     ///
234     /// use std::process::Command;
235     ///
236     /// Command::cargo_bin("bin_fixture")
237     ///     .unwrap()
238     ///     .env("exit", "42")
239     ///     .assert()
240     ///     .code(&[2, 42] as &[i32]);
241     /// ```
242     ///
code<I, P>(self, pred: I) -> Self where I: IntoCodePredicate<P>, P: predicates_core::Predicate<i32>,243     pub fn code<I, P>(self, pred: I) -> Self
244     where
245         I: IntoCodePredicate<P>,
246         P: predicates_core::Predicate<i32>,
247     {
248         self.code_impl(&pred.into_code())
249     }
250 
code_impl(self, pred: &dyn predicates_core::Predicate<i32>) -> Self251     fn code_impl(self, pred: &dyn predicates_core::Predicate<i32>) -> Self {
252         let actual_code = self
253             .output
254             .status
255             .code()
256             .unwrap_or_else(|| panic!("Command interrupted\n{}", self));
257         if let Some(case) = pred.find_case(false, &actual_code) {
258             panic!("Unexpected return code, failed {}\n{}", case.tree(), self);
259         }
260         self
261     }
262 
263     /// Ensure the command wrote the expected data to `stdout`.
264     ///
265     /// This uses [`IntoOutputPredicate`] to provide short-hands for common cases.
266     ///
267     /// See [`predicates`] for more predicates.
268     ///
269     /// # Examples
270     ///
271     /// Accepting a bytes predicate:
272     /// ```rust,no_run
273     /// use assert_cmd::prelude::*;
274     ///
275     /// use std::process::Command;
276     /// use predicates::prelude::*;
277     ///
278     /// Command::cargo_bin("bin_fixture")
279     ///     .unwrap()
280     ///     .env("stdout", "hello")
281     ///     .env("stderr", "world")
282     ///     .assert()
283     ///     .stdout(predicate::eq(b"hello\n" as &[u8]));
284     /// ```
285     ///
286     /// Accepting a `str` predicate:
287     /// ```rust,no_run
288     /// use assert_cmd::prelude::*;
289     ///
290     /// use std::process::Command;
291     /// use predicates::prelude::*;
292     ///
293     /// Command::cargo_bin("bin_fixture")
294     ///     .unwrap()
295     ///     .env("stdout", "hello")
296     ///     .env("stderr", "world")
297     ///     .assert()
298     ///     .stdout(predicate::str::diff("hello\n"));
299     /// ```
300     ///
301     /// Accepting bytes:
302     /// ```rust,no_run
303     /// use assert_cmd::prelude::*;
304     ///
305     /// use std::process::Command;
306     ///
307     /// Command::cargo_bin("bin_fixture")
308     ///     .unwrap()
309     ///     .env("stdout", "hello")
310     ///     .env("stderr", "world")
311     ///     .assert()
312     ///     .stdout(b"hello\n" as &[u8]);
313     /// ```
314     ///
315     /// Accepting a `str`:
316     /// ```rust,no_run
317     /// use assert_cmd::prelude::*;
318     ///
319     /// use std::process::Command;
320     ///
321     /// Command::cargo_bin("bin_fixture")
322     ///     .unwrap()
323     ///     .env("stdout", "hello")
324     ///     .env("stderr", "world")
325     ///     .assert()
326     ///     .stdout("hello\n");
327     /// ```
328     ///
stdout<I, P>(self, pred: I) -> Self where I: IntoOutputPredicate<P>, P: predicates_core::Predicate<[u8]>,329     pub fn stdout<I, P>(self, pred: I) -> Self
330     where
331         I: IntoOutputPredicate<P>,
332         P: predicates_core::Predicate<[u8]>,
333     {
334         self.stdout_impl(&pred.into_output())
335     }
336 
stdout_impl(self, pred: &dyn predicates_core::Predicate<[u8]>) -> Self337     fn stdout_impl(self, pred: &dyn predicates_core::Predicate<[u8]>) -> Self {
338         {
339             let actual = &self.output.stdout;
340             if let Some(case) = pred.find_case(false, &actual) {
341                 panic!("Unexpected stdout, failed {}\n{}", case.tree(), self);
342             }
343         }
344         self
345     }
346 
347     /// Ensure the command wrote the expected data to `stderr`.
348     ///
349     /// This uses [`IntoOutputPredicate`] to provide short-hands for common cases.
350     ///
351     /// See [`predicates`] for more predicates.
352     ///
353     /// # Examples
354     ///
355     /// Accepting a bytes predicate:
356     /// ```rust,no_run
357     /// use assert_cmd::prelude::*;
358     ///
359     /// use std::process::Command;
360     /// use predicates::prelude::*;
361     ///
362     /// Command::cargo_bin("bin_fixture")
363     ///     .unwrap()
364     ///     .env("stdout", "hello")
365     ///     .env("stderr", "world")
366     ///     .assert()
367     ///     .stderr(predicate::eq(b"world\n" as &[u8]));
368     /// ```
369     ///
370     /// Accepting a `str` predicate:
371     /// ```rust,no_run
372     /// use assert_cmd::prelude::*;
373     ///
374     /// use std::process::Command;
375     /// use predicates::prelude::*;
376     ///
377     /// Command::cargo_bin("bin_fixture")
378     ///     .unwrap()
379     ///     .env("stdout", "hello")
380     ///     .env("stderr", "world")
381     ///     .assert()
382     ///     .stderr(predicate::str::diff("world\n"));
383     /// ```
384     ///
385     /// Accepting bytes:
386     /// ```rust,no_run
387     /// use assert_cmd::prelude::*;
388     ///
389     /// use std::process::Command;
390     ///
391     /// Command::cargo_bin("bin_fixture")
392     ///     .unwrap()
393     ///     .env("stdout", "hello")
394     ///     .env("stderr", "world")
395     ///     .assert()
396     ///     .stderr(b"world\n" as &[u8]);
397     /// ```
398     ///
399     /// Accepting a `str`:
400     /// ```rust,no_run
401     /// use assert_cmd::prelude::*;
402     ///
403     /// use std::process::Command;
404     ///
405     /// Command::cargo_bin("bin_fixture")
406     ///     .unwrap()
407     ///     .env("stdout", "hello")
408     ///     .env("stderr", "world")
409     ///     .assert()
410     ///     .stderr("world\n");
411     /// ```
412     ///
stderr<I, P>(self, pred: I) -> Self where I: IntoOutputPredicate<P>, P: predicates_core::Predicate<[u8]>,413     pub fn stderr<I, P>(self, pred: I) -> Self
414     where
415         I: IntoOutputPredicate<P>,
416         P: predicates_core::Predicate<[u8]>,
417     {
418         self.stderr_impl(&pred.into_output())
419     }
420 
stderr_impl(self, pred: &dyn predicates_core::Predicate<[u8]>) -> Self421     fn stderr_impl(self, pred: &dyn predicates_core::Predicate<[u8]>) -> Self {
422         {
423             let actual = &self.output.stderr;
424             if let Some(case) = pred.find_case(false, &actual) {
425                 panic!("Unexpected stderr, failed {}\n\n{}", case.tree(), self);
426             }
427         }
428         self
429     }
430 }
431 
432 impl fmt::Display for Assert {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result433     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
434         for &(ref name, ref context) in &self.context {
435             writeln!(f, "{}=`{}`", name, context)?;
436         }
437         output_fmt(&self.output, f)
438     }
439 }
440 
441 impl fmt::Debug for Assert {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result442     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
443         f.debug_struct("Assert")
444             .field("output", &self.output)
445             .finish()
446     }
447 }
448 
449 /// Used by [`Assert::code`] to convert `Self` into the needed
450 /// [`predicates_core::Predicate<i32>`].
451 ///
452 /// # Examples
453 ///
454 /// ```rust,no_run
455 /// use assert_cmd::prelude::*;
456 ///
457 /// use std::process::Command;
458 /// use predicates::prelude::*;
459 ///
460 /// Command::cargo_bin("bin_fixture")
461 ///     .unwrap()
462 ///     .env("exit", "42")
463 ///     .assert()
464 ///     .code(predicate::eq(42));
465 ///
466 /// // which can be shortened to:
467 /// Command::cargo_bin("bin_fixture")
468 ///     .unwrap()
469 ///     .env("exit", "42")
470 ///     .assert()
471 ///     .code(42);
472 /// ```
473 pub trait IntoCodePredicate<P>
474 where
475     P: predicates_core::Predicate<i32>,
476 {
477     /// The type of the predicate being returned.
478     type Predicate;
479 
480     /// Convert to a predicate for testing a program's exit code.
into_code(self) -> P481     fn into_code(self) -> P;
482 }
483 
484 impl<P> IntoCodePredicate<P> for P
485 where
486     P: predicates_core::Predicate<i32>,
487 {
488     type Predicate = P;
489 
into_code(self) -> Self::Predicate490     fn into_code(self) -> Self::Predicate {
491         self
492     }
493 }
494 
495 /// Keep `predicates` concrete Predicates out of our public API.
496 /// [predicates_core::Predicate] used by [`IntoCodePredicate`] for code.
497 ///
498 /// # Example
499 ///
500 /// ```rust,no_run
501 /// use assert_cmd::prelude::*;
502 ///
503 /// use std::process::Command;
504 ///
505 /// Command::cargo_bin("bin_fixture")
506 ///     .unwrap()
507 ///     .env("exit", "42")
508 ///     .assert()
509 ///     .code(42);
510 /// ```
511 #[derive(Debug)]
512 pub struct EqCodePredicate(predicates::ord::EqPredicate<i32>);
513 
514 impl EqCodePredicate {
new(value: i32) -> Self515     pub(crate) fn new(value: i32) -> Self {
516         let pred = predicates::ord::eq(value);
517         EqCodePredicate(pred)
518     }
519 }
520 
521 impl predicates_core::reflection::PredicateReflection for EqCodePredicate {
parameters<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a>522     fn parameters<'a>(
523         &'a self,
524     ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a> {
525         self.0.parameters()
526     }
527 
528     /// Nested `Predicate`s of the current `Predicate`.
children<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a>529     fn children<'a>(
530         &'a self,
531     ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a> {
532         self.0.children()
533     }
534 }
535 
536 impl predicates_core::Predicate<i32> for EqCodePredicate {
eval(&self, item: &i32) -> bool537     fn eval(&self, item: &i32) -> bool {
538         self.0.eval(item)
539     }
540 
find_case<'a>( &'a self, expected: bool, variable: &i32, ) -> Option<predicates_core::reflection::Case<'a>>541     fn find_case<'a>(
542         &'a self,
543         expected: bool,
544         variable: &i32,
545     ) -> Option<predicates_core::reflection::Case<'a>> {
546         self.0.find_case(expected, variable)
547     }
548 }
549 
550 impl fmt::Display for EqCodePredicate {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result551     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
552         self.0.fmt(f)
553     }
554 }
555 
556 impl IntoCodePredicate<EqCodePredicate> for i32 {
557     type Predicate = EqCodePredicate;
558 
into_code(self) -> Self::Predicate559     fn into_code(self) -> Self::Predicate {
560         Self::Predicate::new(self)
561     }
562 }
563 
564 /// Keep `predicates` concrete Predicates out of our public API.
565 /// [predicates_core::Predicate] used by [`IntoCodePredicate`] for iterables of codes.
566 ///
567 /// # Example
568 ///
569 /// ```rust,no_run
570 /// use assert_cmd::prelude::*;
571 ///
572 /// use std::process::Command;
573 ///
574 /// Command::cargo_bin("bin_fixture")
575 ///     .unwrap()
576 ///     .env("exit", "42")
577 ///     .assert()
578 ///     .code(&[2, 42] as &[i32]);
579 /// ```
580 #[derive(Debug)]
581 pub struct InCodePredicate(predicates::iter::InPredicate<i32>);
582 
583 impl InCodePredicate {
new<I: IntoIterator<Item = i32>>(value: I) -> Self584     pub(crate) fn new<I: IntoIterator<Item = i32>>(value: I) -> Self {
585         let pred = predicates::iter::in_iter(value);
586         InCodePredicate(pred)
587     }
588 }
589 
590 impl predicates_core::reflection::PredicateReflection for InCodePredicate {
parameters<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a>591     fn parameters<'a>(
592         &'a self,
593     ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a> {
594         self.0.parameters()
595     }
596 
597     /// Nested `Predicate`s of the current `Predicate`.
children<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a>598     fn children<'a>(
599         &'a self,
600     ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a> {
601         self.0.children()
602     }
603 }
604 
605 impl predicates_core::Predicate<i32> for InCodePredicate {
eval(&self, item: &i32) -> bool606     fn eval(&self, item: &i32) -> bool {
607         self.0.eval(item)
608     }
609 
find_case<'a>( &'a self, expected: bool, variable: &i32, ) -> Option<predicates_core::reflection::Case<'a>>610     fn find_case<'a>(
611         &'a self,
612         expected: bool,
613         variable: &i32,
614     ) -> Option<predicates_core::reflection::Case<'a>> {
615         self.0.find_case(expected, variable)
616     }
617 }
618 
619 impl fmt::Display for InCodePredicate {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result620     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
621         self.0.fmt(f)
622     }
623 }
624 
625 impl IntoCodePredicate<InCodePredicate> for Vec<i32> {
626     type Predicate = InCodePredicate;
627 
into_code(self) -> Self::Predicate628     fn into_code(self) -> Self::Predicate {
629         Self::Predicate::new(self)
630     }
631 }
632 
633 impl IntoCodePredicate<InCodePredicate> for &'static [i32] {
634     type Predicate = InCodePredicate;
635 
into_code(self) -> Self::Predicate636     fn into_code(self) -> Self::Predicate {
637         Self::Predicate::new(self.iter().cloned())
638     }
639 }
640 
641 /// Used by [`Assert::stdout`] and [`Assert::stderr`] to convert Self
642 /// into the needed [`predicates_core::Predicate<[u8]>`].
643 ///
644 /// # Examples
645 ///
646 /// ```rust,no_run
647 /// use assert_cmd::prelude::*;
648 ///
649 /// use std::process::Command;
650 /// use predicates::prelude::*;
651 ///
652 /// Command::cargo_bin("bin_fixture")
653 ///     .unwrap()
654 ///     .env("stdout", "hello")
655 ///     .env("stderr", "world")
656 ///     .assert()
657 ///     .stdout(predicate::str::diff("hello\n").from_utf8());
658 ///
659 /// // which can be shortened to:
660 /// Command::cargo_bin("bin_fixture")
661 ///     .unwrap()
662 ///     .env("stdout", "hello")
663 ///     .env("stderr", "world")
664 ///     .assert()
665 ///     .stdout("hello\n");
666 /// ```
667 pub trait IntoOutputPredicate<P>
668 where
669     P: predicates_core::Predicate<[u8]>,
670 {
671     /// The type of the predicate being returned.
672     type Predicate;
673 
674     /// Convert to a predicate for testing a path.
into_output(self) -> P675     fn into_output(self) -> P;
676 }
677 
678 impl<P> IntoOutputPredicate<P> for P
679 where
680     P: predicates_core::Predicate<[u8]>,
681 {
682     type Predicate = P;
683 
into_output(self) -> Self::Predicate684     fn into_output(self) -> Self::Predicate {
685         self
686     }
687 }
688 
689 /// Keep `predicates` concrete Predicates out of our public API.
690 /// [predicates_core::Predicate] used by [`IntoOutputPredicate`] for bytes.
691 ///
692 /// # Example
693 ///
694 /// ```rust,no_run
695 /// use assert_cmd::prelude::*;
696 ///
697 /// use std::process::Command;
698 ///
699 /// Command::cargo_bin("bin_fixture")
700 ///     .unwrap()
701 ///     .env("stdout", "hello")
702 ///     .env("stderr", "world")
703 ///     .assert()
704 ///     .stderr(b"world\n" as &[u8]);
705 /// ```
706 #[derive(Debug)]
707 pub struct BytesContentOutputPredicate(Cow<'static, [u8]>);
708 
709 impl BytesContentOutputPredicate {
new(value: &'static [u8]) -> Self710     pub(crate) fn new(value: &'static [u8]) -> Self {
711         BytesContentOutputPredicate(Cow::from(value))
712     }
713 
from_vec(value: Vec<u8>) -> Self714     pub(crate) fn from_vec(value: Vec<u8>) -> Self {
715         BytesContentOutputPredicate(Cow::from(value))
716     }
717 }
718 
719 impl predicates_core::reflection::PredicateReflection for BytesContentOutputPredicate {}
720 
721 impl predicates_core::Predicate<[u8]> for BytesContentOutputPredicate {
eval(&self, item: &[u8]) -> bool722     fn eval(&self, item: &[u8]) -> bool {
723         self.0.as_ref() == item
724     }
725 
find_case( &self, expected: bool, variable: &[u8], ) -> Option<predicates_core::reflection::Case>726     fn find_case(
727         &self,
728         expected: bool,
729         variable: &[u8],
730     ) -> Option<predicates_core::reflection::Case> {
731         let actual = self.eval(variable);
732         if expected == actual {
733             Some(predicates_core::reflection::Case::new(Some(self), actual))
734         } else {
735             None
736         }
737     }
738 }
739 
740 impl fmt::Display for BytesContentOutputPredicate {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result741     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
742         predicates::ord::eq(self.0.as_ref()).fmt(f)
743     }
744 }
745 
746 impl IntoOutputPredicate<BytesContentOutputPredicate> for Vec<u8> {
747     type Predicate = BytesContentOutputPredicate;
748 
into_output(self) -> Self::Predicate749     fn into_output(self) -> Self::Predicate {
750         Self::Predicate::from_vec(self)
751     }
752 }
753 
754 impl IntoOutputPredicate<BytesContentOutputPredicate> for &'static [u8] {
755     type Predicate = BytesContentOutputPredicate;
756 
into_output(self) -> Self::Predicate757     fn into_output(self) -> Self::Predicate {
758         Self::Predicate::new(self)
759     }
760 }
761 
762 /// Keep `predicates` concrete Predicates out of our public API.
763 /// [predicates_core::Predicate] used by [`IntoOutputPredicate`] for [`str`].
764 ///
765 /// # Example
766 ///
767 /// ```rust,no_run
768 /// use assert_cmd::prelude::*;
769 ///
770 /// use std::process::Command;
771 ///
772 /// Command::cargo_bin("bin_fixture")
773 ///     .unwrap()
774 ///     .env("stdout", "hello")
775 ///     .env("stderr", "world")
776 ///     .assert()
777 ///     .stderr("world\n");
778 /// ```
779 ///
780 /// [`str`]: https://doc.rust-lang.org/std/primitive.str.html
781 #[derive(Debug, Clone)]
782 pub struct StrContentOutputPredicate(
783     predicates::str::Utf8Predicate<predicates::str::DifferencePredicate>,
784 );
785 
786 impl StrContentOutputPredicate {
from_str(value: &'static str) -> Self787     pub(crate) fn from_str(value: &'static str) -> Self {
788         let pred = predicates::str::diff(value).from_utf8();
789         StrContentOutputPredicate(pred)
790     }
791 
from_string(value: String) -> Self792     pub(crate) fn from_string(value: String) -> Self {
793         let pred = predicates::str::diff(value).from_utf8();
794         StrContentOutputPredicate(pred)
795     }
796 }
797 
798 impl predicates_core::reflection::PredicateReflection for StrContentOutputPredicate {
parameters<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a>799     fn parameters<'a>(
800         &'a self,
801     ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a> {
802         self.0.parameters()
803     }
804 
805     /// Nested `Predicate`s of the current `Predicate`.
children<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a>806     fn children<'a>(
807         &'a self,
808     ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a> {
809         self.0.children()
810     }
811 }
812 
813 impl predicates_core::Predicate<[u8]> for StrContentOutputPredicate {
eval(&self, item: &[u8]) -> bool814     fn eval(&self, item: &[u8]) -> bool {
815         self.0.eval(item)
816     }
817 
find_case<'a>( &'a self, expected: bool, variable: &[u8], ) -> Option<predicates_core::reflection::Case<'a>>818     fn find_case<'a>(
819         &'a self,
820         expected: bool,
821         variable: &[u8],
822     ) -> Option<predicates_core::reflection::Case<'a>> {
823         self.0.find_case(expected, variable)
824     }
825 }
826 
827 impl fmt::Display for StrContentOutputPredicate {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result828     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
829         self.0.fmt(f)
830     }
831 }
832 
833 impl IntoOutputPredicate<StrContentOutputPredicate> for String {
834     type Predicate = StrContentOutputPredicate;
835 
into_output(self) -> Self::Predicate836     fn into_output(self) -> Self::Predicate {
837         Self::Predicate::from_string(self)
838     }
839 }
840 
841 impl IntoOutputPredicate<StrContentOutputPredicate> for &'static str {
842     type Predicate = StrContentOutputPredicate;
843 
into_output(self) -> Self::Predicate844     fn into_output(self) -> Self::Predicate {
845         Self::Predicate::from_str(self)
846     }
847 }
848 
849 // Keep `predicates` concrete Predicates out of our public API.
850 /// [predicates_core::Predicate] used by [`IntoOutputPredicate`] for
851 /// [`Predicate<str>`][predicates_core::Predicate].
852 ///
853 /// # Example
854 ///
855 /// ```rust,no_run
856 /// use assert_cmd::prelude::*;
857 ///
858 /// use std::process::Command;
859 /// use predicates::prelude::*;
860 ///
861 /// Command::cargo_bin("bin_fixture")
862 ///     .unwrap()
863 ///     .env("stdout", "hello")
864 ///     .env("stderr", "world")
865 ///     .assert()
866 ///     .stderr(predicate::str::diff("world\n"));
867 /// ```
868 #[derive(Debug, Clone)]
869 pub struct StrOutputPredicate<P: predicates_core::Predicate<str>>(
870     predicates::str::Utf8Predicate<P>,
871 );
872 
873 impl<P> StrOutputPredicate<P>
874 where
875     P: predicates_core::Predicate<str>,
876 {
new(pred: P) -> Self877     pub(crate) fn new(pred: P) -> Self {
878         let pred = pred.from_utf8();
879         StrOutputPredicate(pred)
880     }
881 }
882 
883 impl<P> predicates_core::reflection::PredicateReflection for StrOutputPredicate<P>
884 where
885     P: predicates_core::Predicate<str>,
886 {
parameters<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a>887     fn parameters<'a>(
888         &'a self,
889     ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a> {
890         self.0.parameters()
891     }
892 
893     /// Nested `Predicate`s of the current `Predicate`.
children<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a>894     fn children<'a>(
895         &'a self,
896     ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a> {
897         self.0.children()
898     }
899 }
900 
901 impl<P> predicates_core::Predicate<[u8]> for StrOutputPredicate<P>
902 where
903     P: predicates_core::Predicate<str>,
904 {
eval(&self, item: &[u8]) -> bool905     fn eval(&self, item: &[u8]) -> bool {
906         self.0.eval(item)
907     }
908 
find_case<'a>( &'a self, expected: bool, variable: &[u8], ) -> Option<predicates_core::reflection::Case<'a>>909     fn find_case<'a>(
910         &'a self,
911         expected: bool,
912         variable: &[u8],
913     ) -> Option<predicates_core::reflection::Case<'a>> {
914         self.0.find_case(expected, variable)
915     }
916 }
917 
918 impl<P> fmt::Display for StrOutputPredicate<P>
919 where
920     P: predicates_core::Predicate<str>,
921 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result922     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
923         self.0.fmt(f)
924     }
925 }
926 
927 impl<P> IntoOutputPredicate<StrOutputPredicate<P>> for P
928 where
929     P: predicates_core::Predicate<str>,
930 {
931     type Predicate = StrOutputPredicate<P>;
932 
into_output(self) -> Self::Predicate933     fn into_output(self) -> Self::Predicate {
934         Self::Predicate::new(self)
935     }
936 }
937 
938 #[cfg(test)]
939 mod test {
940     use super::*;
941 
942     use predicates::prelude::*;
943 
944     // Since IntoCodePredicate exists solely for conversion, test it under that scenario to ensure
945     // it works as expected.
convert_code<I, P>(pred: I) -> P where I: IntoCodePredicate<P>, P: predicates_core::Predicate<i32>,946     fn convert_code<I, P>(pred: I) -> P
947     where
948         I: IntoCodePredicate<P>,
949         P: predicates_core::Predicate<i32>,
950     {
951         pred.into_code()
952     }
953 
954     #[test]
into_code_from_pred()955     fn into_code_from_pred() {
956         let pred = convert_code(predicate::eq(10));
957         assert!(pred.eval(&10));
958     }
959 
960     #[test]
into_code_from_i32()961     fn into_code_from_i32() {
962         let pred = convert_code(10);
963         assert!(pred.eval(&10));
964     }
965 
966     #[test]
into_code_from_vec()967     fn into_code_from_vec() {
968         let pred = convert_code(vec![3, 10]);
969         assert!(pred.eval(&10));
970     }
971 
972     #[test]
into_code_from_array()973     fn into_code_from_array() {
974         let pred = convert_code(&[3, 10] as &[i32]);
975         assert!(pred.eval(&10));
976     }
977 
978     // Since IntoOutputPredicate exists solely for conversion, test it under that scenario to ensure
979     // it works as expected.
convert_output<I, P>(pred: I) -> P where I: IntoOutputPredicate<P>, P: predicates_core::Predicate<[u8]>,980     fn convert_output<I, P>(pred: I) -> P
981     where
982         I: IntoOutputPredicate<P>,
983         P: predicates_core::Predicate<[u8]>,
984     {
985         pred.into_output()
986     }
987 
988     #[test]
into_output_from_pred()989     fn into_output_from_pred() {
990         let pred = convert_output(predicate::eq(b"Hello" as &[u8]));
991         assert!(pred.eval(b"Hello" as &[u8]));
992     }
993 
994     #[test]
into_output_from_bytes()995     fn into_output_from_bytes() {
996         let pred = convert_output(b"Hello" as &[u8]);
997         assert!(pred.eval(b"Hello" as &[u8]));
998     }
999 
1000     #[test]
into_output_from_vec()1001     fn into_output_from_vec() {
1002         let pred = convert_output(vec![b'H', b'e', b'l', b'l', b'o']);
1003         assert!(pred.eval(b"Hello" as &[u8]));
1004     }
1005 
1006     #[test]
into_output_from_str()1007     fn into_output_from_str() {
1008         let pred = convert_output("Hello");
1009         assert!(pred.eval(b"Hello" as &[u8]));
1010     }
1011 }
1012