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