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