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