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