1 //! [`std::process::Output`] assertions. 2 3 use std::borrow::Cow; 4 use std::error::Error; 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::output_fmt; 13 use crate::output::DebugBytes; 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`]: std::process::Output 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`]: std::process::Output 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 = match self.output() { 60 Ok(output) => output, 61 Err(err) => { 62 panic!("Failed to spawn {:?}: {}", self, err); 63 } 64 }; 65 Assert::new(output).append_context("command", format!("{:?}", self)) 66 } 67 } 68 69 /// [`Assert`] represented as a [`Result`]. 70 /// 71 /// Produced by the `try_` variants the [`Assert`] methods. 72 /// 73 /// # Example 74 /// 75 /// ```rust 76 /// use assert_cmd::prelude::*; 77 /// 78 /// use std::process::Command; 79 /// 80 /// let result = Command::new("echo") 81 /// .assert() 82 /// .try_success(); 83 /// assert!(result.is_ok()); 84 /// ``` 85 /// 86 /// [`Result`]: std::result::Result 87 pub type AssertResult = Result<Assert, AssertError>; 88 89 /// [`Assert`] error (see [`AssertResult`]). 90 #[derive(Debug)] 91 pub struct AssertError { 92 assert: Assert, 93 reason: AssertReason, 94 } 95 96 #[derive(Debug)] 97 enum AssertReason { 98 UnexpectedFailure { actual_code: Option<i32> }, 99 UnexpectedSuccess, 100 UnexpectedCompletion, 101 CommandInterrupted, 102 UnexpectedReturnCode { case_tree: CaseTree }, 103 UnexpectedStdout { case_tree: CaseTree }, 104 UnexpectedStderr { case_tree: CaseTree }, 105 } 106 107 struct CaseTree(predicates_tree::CaseTree); 108 109 impl fmt::Display for CaseTree { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result110 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 111 <predicates_tree::CaseTree as fmt::Display>::fmt(&self.0, f) 112 } 113 } 114 115 // Work around `Debug` not being implemented for `predicates_tree::CaseTree`. 116 impl fmt::Debug for CaseTree { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result117 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 118 <predicates_tree::CaseTree as fmt::Display>::fmt(&self.0, f) 119 } 120 } 121 122 impl AssertError { panic<T>(self) -> T123 fn panic<T>(self) -> T { 124 panic!("{}", self.to_string()) 125 } 126 } 127 128 impl Error for AssertError {} 129 130 impl fmt::Display for AssertError { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result131 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 132 match &self.reason { 133 AssertReason::UnexpectedFailure { actual_code } => writeln!( 134 f, 135 "Unexpected failure.\ncode-{}\nstderr=```{}```", 136 actual_code.map_or("<interrupted>".to_owned(), |actual_code| actual_code 137 .to_string()), 138 DebugBytes::new(&self.assert.output.stderr), 139 ), 140 AssertReason::UnexpectedSuccess => { 141 writeln!(f, "Unexpected success") 142 } 143 AssertReason::UnexpectedCompletion => { 144 writeln!(f, "Unexpected completion") 145 } 146 AssertReason::CommandInterrupted => { 147 writeln!(f, "Command interrupted") 148 } 149 AssertReason::UnexpectedReturnCode { case_tree } => { 150 writeln!(f, "Unexpected return code, failed {}", case_tree) 151 } 152 AssertReason::UnexpectedStdout { case_tree } => { 153 writeln!(f, "Unexpected stdout, failed {}", case_tree) 154 } 155 AssertReason::UnexpectedStderr { case_tree } => { 156 writeln!(f, "Unexpected stderr, failed {}", case_tree) 157 } 158 }?; 159 write!(f, "{}", self.assert) 160 } 161 } 162 163 /// Assert the state of an [`Output`]. 164 /// 165 /// Create an `Assert` through the [`OutputAssertExt`] trait. 166 /// 167 /// # Examples 168 /// 169 /// ```rust,no_run 170 /// use assert_cmd::prelude::*; 171 /// 172 /// use std::process::Command; 173 /// 174 /// let mut cmd = Command::cargo_bin("bin_fixture") 175 /// .unwrap(); 176 /// cmd.assert() 177 /// .success(); 178 /// ``` 179 /// 180 /// [`Output`]: std::process::Output 181 pub struct Assert { 182 output: process::Output, 183 context: Vec<(&'static str, Box<dyn fmt::Display>)>, 184 } 185 186 impl Assert { 187 /// Create an `Assert` for a given [`Output`]. 188 /// 189 /// [`Output`]: std::process::Output new(output: process::Output) -> Self190 pub fn new(output: process::Output) -> Self { 191 Self { 192 output, 193 context: vec![], 194 } 195 } 196 into_error(self, reason: AssertReason) -> AssertError197 fn into_error(self, reason: AssertReason) -> AssertError { 198 AssertError { 199 assert: self, 200 reason, 201 } 202 } 203 204 /// Clarify failures with additional context. 205 /// 206 /// # Examples 207 /// 208 /// ```rust,no_run 209 /// use assert_cmd::prelude::*; 210 /// 211 /// use std::process::Command; 212 /// 213 /// Command::cargo_bin("bin_fixture") 214 /// .unwrap() 215 /// .assert() 216 /// .append_context("main", "no args") 217 /// .success(); 218 /// ``` append_context<D>(mut self, name: &'static str, context: D) -> Self where D: fmt::Display + 'static,219 pub fn append_context<D>(mut self, name: &'static str, context: D) -> Self 220 where 221 D: fmt::Display + 'static, 222 { 223 self.context.push((name, Box::new(context))); 224 self 225 } 226 227 /// Access the contained [`Output`]. 228 /// 229 /// [`Output`]: std::process::Output get_output(&self) -> &process::Output230 pub fn get_output(&self) -> &process::Output { 231 &self.output 232 } 233 234 /// Ensure the command succeeded. 235 /// 236 /// # Examples 237 /// 238 /// ```rust,no_run 239 /// use assert_cmd::prelude::*; 240 /// 241 /// use std::process::Command; 242 /// 243 /// Command::cargo_bin("bin_fixture") 244 /// .unwrap() 245 /// .assert() 246 /// .success(); 247 /// ``` success(self) -> Self248 pub fn success(self) -> Self { 249 self.try_success().unwrap_or_else(AssertError::panic) 250 } 251 252 /// `try_` variant of [`Assert::success`]. try_success(self) -> AssertResult253 pub fn try_success(self) -> AssertResult { 254 if !self.output.status.success() { 255 let actual_code = self.output.status.code(); 256 return Err(self.into_error(AssertReason::UnexpectedFailure { actual_code })); 257 } 258 Ok(self) 259 } 260 261 /// Ensure the command failed. 262 /// 263 /// # Examples 264 /// 265 /// ```rust,no_run 266 /// use assert_cmd::prelude::*; 267 /// 268 /// use std::process::Command; 269 /// 270 /// Command::cargo_bin("bin_fixture") 271 /// .unwrap() 272 /// .env("exit", "1") 273 /// .assert() 274 /// .failure(); 275 /// ``` failure(self) -> Self276 pub fn failure(self) -> Self { 277 self.try_failure().unwrap_or_else(AssertError::panic) 278 } 279 280 /// Variant of [`Assert::failure`] that returns an [`AssertResult`]. try_failure(self) -> AssertResult281 pub fn try_failure(self) -> AssertResult { 282 if self.output.status.success() { 283 return Err(self.into_error(AssertReason::UnexpectedSuccess)); 284 } 285 Ok(self) 286 } 287 288 /// Ensure the command aborted before returning a code. interrupted(self) -> Self289 pub fn interrupted(self) -> Self { 290 self.try_interrupted().unwrap_or_else(AssertError::panic) 291 } 292 293 /// Variant of [`Assert::interrupted`] that returns an [`AssertResult`]. try_interrupted(self) -> AssertResult294 pub fn try_interrupted(self) -> AssertResult { 295 if self.output.status.code().is_some() { 296 return Err(self.into_error(AssertReason::UnexpectedCompletion)); 297 } 298 Ok(self) 299 } 300 301 /// Ensure the command returned the expected code. 302 /// 303 /// This uses [`IntoCodePredicate`] to provide short-hands for common cases. 304 /// 305 /// See [`predicates`] for more predicates. 306 /// 307 /// # Examples 308 /// 309 /// Accepting a predicate: 310 /// ```rust,no_run 311 /// use assert_cmd::prelude::*; 312 /// 313 /// use std::process::Command; 314 /// use predicates::prelude::*; 315 /// 316 /// Command::cargo_bin("bin_fixture") 317 /// .unwrap() 318 /// .env("exit", "42") 319 /// .assert() 320 /// .code(predicate::eq(42)); 321 /// ``` 322 /// 323 /// Accepting an exit code: 324 /// ```rust,no_run 325 /// use assert_cmd::prelude::*; 326 /// 327 /// use std::process::Command; 328 /// 329 /// Command::cargo_bin("bin_fixture") 330 /// .unwrap() 331 /// .env("exit", "42") 332 /// .assert() 333 /// .code(42); 334 /// ``` 335 /// 336 /// Accepting multiple exit codes: 337 /// ```rust,no_run 338 /// use assert_cmd::prelude::*; 339 /// 340 /// use std::process::Command; 341 /// 342 /// Command::cargo_bin("bin_fixture") 343 /// .unwrap() 344 /// .env("exit", "42") 345 /// .assert() 346 /// .code(&[2, 42] as &[i32]); 347 /// ``` 348 /// code<I, P>(self, pred: I) -> Self where I: IntoCodePredicate<P>, P: predicates_core::Predicate<i32>,349 pub fn code<I, P>(self, pred: I) -> Self 350 where 351 I: IntoCodePredicate<P>, 352 P: predicates_core::Predicate<i32>, 353 { 354 self.try_code(pred).unwrap_or_else(AssertError::panic) 355 } 356 357 /// Variant of [`Assert::code`] that returns an [`AssertResult`]. try_code<I, P>(self, pred: I) -> AssertResult where I: IntoCodePredicate<P>, P: predicates_core::Predicate<i32>,358 pub fn try_code<I, P>(self, pred: I) -> AssertResult 359 where 360 I: IntoCodePredicate<P>, 361 P: predicates_core::Predicate<i32>, 362 { 363 self.code_impl(&pred.into_code()) 364 } 365 code_impl(self, pred: &dyn predicates_core::Predicate<i32>) -> AssertResult366 fn code_impl(self, pred: &dyn predicates_core::Predicate<i32>) -> AssertResult { 367 let actual_code = if let Some(actual_code) = self.output.status.code() { 368 actual_code 369 } else { 370 return Err(self.into_error(AssertReason::CommandInterrupted)); 371 }; 372 if let Some(case) = pred.find_case(false, &actual_code) { 373 return Err(self.into_error(AssertReason::UnexpectedReturnCode { 374 case_tree: CaseTree(case.tree()), 375 })); 376 } 377 Ok(self) 378 } 379 380 /// Ensure the command wrote the expected data to `stdout`. 381 /// 382 /// This uses [`IntoOutputPredicate`] to provide short-hands for common cases. 383 /// 384 /// See [`predicates`] for more predicates. 385 /// 386 /// # Examples 387 /// 388 /// Accepting a bytes predicate: 389 /// ```rust,no_run 390 /// use assert_cmd::prelude::*; 391 /// 392 /// use std::process::Command; 393 /// use predicates::prelude::*; 394 /// 395 /// Command::cargo_bin("bin_fixture") 396 /// .unwrap() 397 /// .env("stdout", "hello") 398 /// .env("stderr", "world") 399 /// .assert() 400 /// .stdout(predicate::eq(b"hello\n" as &[u8])); 401 /// ``` 402 /// 403 /// Accepting a `str` predicate: 404 /// ```rust,no_run 405 /// use assert_cmd::prelude::*; 406 /// 407 /// use std::process::Command; 408 /// use predicates::prelude::*; 409 /// 410 /// Command::cargo_bin("bin_fixture") 411 /// .unwrap() 412 /// .env("stdout", "hello") 413 /// .env("stderr", "world") 414 /// .assert() 415 /// .stdout(predicate::str::diff("hello\n")); 416 /// ``` 417 /// 418 /// Accepting bytes: 419 /// ```rust,no_run 420 /// use assert_cmd::prelude::*; 421 /// 422 /// use std::process::Command; 423 /// 424 /// Command::cargo_bin("bin_fixture") 425 /// .unwrap() 426 /// .env("stdout", "hello") 427 /// .env("stderr", "world") 428 /// .assert() 429 /// .stdout(b"hello\n" as &[u8]); 430 /// ``` 431 /// 432 /// Accepting a `str`: 433 /// ```rust,no_run 434 /// use assert_cmd::prelude::*; 435 /// 436 /// use std::process::Command; 437 /// 438 /// Command::cargo_bin("bin_fixture") 439 /// .unwrap() 440 /// .env("stdout", "hello") 441 /// .env("stderr", "world") 442 /// .assert() 443 /// .stdout("hello\n"); 444 /// ``` 445 /// stdout<I, P>(self, pred: I) -> Self where I: IntoOutputPredicate<P>, P: predicates_core::Predicate<[u8]>,446 pub fn stdout<I, P>(self, pred: I) -> Self 447 where 448 I: IntoOutputPredicate<P>, 449 P: predicates_core::Predicate<[u8]>, 450 { 451 self.try_stdout(pred).unwrap_or_else(AssertError::panic) 452 } 453 454 /// Variant of [`Assert::stdout`] that returns an [`AssertResult`]. try_stdout<I, P>(self, pred: I) -> AssertResult where I: IntoOutputPredicate<P>, P: predicates_core::Predicate<[u8]>,455 pub fn try_stdout<I, P>(self, pred: I) -> AssertResult 456 where 457 I: IntoOutputPredicate<P>, 458 P: predicates_core::Predicate<[u8]>, 459 { 460 self.stdout_impl(&pred.into_output()) 461 } 462 stdout_impl(self, pred: &dyn predicates_core::Predicate<[u8]>) -> AssertResult463 fn stdout_impl(self, pred: &dyn predicates_core::Predicate<[u8]>) -> AssertResult { 464 { 465 let actual = &self.output.stdout; 466 if let Some(case) = pred.find_case(false, &actual) { 467 return Err(self.into_error(AssertReason::UnexpectedStdout { 468 case_tree: CaseTree(case.tree()), 469 })); 470 } 471 } 472 Ok(self) 473 } 474 475 /// Ensure the command wrote the expected data to `stderr`. 476 /// 477 /// This uses [`IntoOutputPredicate`] to provide short-hands for common cases. 478 /// 479 /// See [`predicates`] for more predicates. 480 /// 481 /// # Examples 482 /// 483 /// Accepting a bytes predicate: 484 /// ```rust,no_run 485 /// use assert_cmd::prelude::*; 486 /// 487 /// use std::process::Command; 488 /// use predicates::prelude::*; 489 /// 490 /// Command::cargo_bin("bin_fixture") 491 /// .unwrap() 492 /// .env("stdout", "hello") 493 /// .env("stderr", "world") 494 /// .assert() 495 /// .stderr(predicate::eq(b"world\n" as &[u8])); 496 /// ``` 497 /// 498 /// Accepting a `str` predicate: 499 /// ```rust,no_run 500 /// use assert_cmd::prelude::*; 501 /// 502 /// use std::process::Command; 503 /// use predicates::prelude::*; 504 /// 505 /// Command::cargo_bin("bin_fixture") 506 /// .unwrap() 507 /// .env("stdout", "hello") 508 /// .env("stderr", "world") 509 /// .assert() 510 /// .stderr(predicate::str::diff("world\n")); 511 /// ``` 512 /// 513 /// Accepting bytes: 514 /// ```rust,no_run 515 /// use assert_cmd::prelude::*; 516 /// 517 /// use std::process::Command; 518 /// 519 /// Command::cargo_bin("bin_fixture") 520 /// .unwrap() 521 /// .env("stdout", "hello") 522 /// .env("stderr", "world") 523 /// .assert() 524 /// .stderr(b"world\n" as &[u8]); 525 /// ``` 526 /// 527 /// Accepting a `str`: 528 /// ```rust,no_run 529 /// use assert_cmd::prelude::*; 530 /// 531 /// use std::process::Command; 532 /// 533 /// Command::cargo_bin("bin_fixture") 534 /// .unwrap() 535 /// .env("stdout", "hello") 536 /// .env("stderr", "world") 537 /// .assert() 538 /// .stderr("world\n"); 539 /// ``` 540 /// stderr<I, P>(self, pred: I) -> Self where I: IntoOutputPredicate<P>, P: predicates_core::Predicate<[u8]>,541 pub fn stderr<I, P>(self, pred: I) -> Self 542 where 543 I: IntoOutputPredicate<P>, 544 P: predicates_core::Predicate<[u8]>, 545 { 546 self.try_stderr(pred).unwrap_or_else(AssertError::panic) 547 } 548 549 /// Variant of [`Assert::stderr`] that returns an [`AssertResult`]. try_stderr<I, P>(self, pred: I) -> AssertResult where I: IntoOutputPredicate<P>, P: predicates_core::Predicate<[u8]>,550 pub fn try_stderr<I, P>(self, pred: I) -> AssertResult 551 where 552 I: IntoOutputPredicate<P>, 553 P: predicates_core::Predicate<[u8]>, 554 { 555 self.stderr_impl(&pred.into_output()) 556 } 557 stderr_impl(self, pred: &dyn predicates_core::Predicate<[u8]>) -> AssertResult558 fn stderr_impl(self, pred: &dyn predicates_core::Predicate<[u8]>) -> AssertResult { 559 { 560 let actual = &self.output.stderr; 561 if let Some(case) = pred.find_case(false, &actual) { 562 return Err(self.into_error(AssertReason::UnexpectedStderr { 563 case_tree: CaseTree(case.tree()), 564 })); 565 } 566 } 567 Ok(self) 568 } 569 } 570 571 impl fmt::Display for Assert { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result572 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 573 for &(ref name, ref context) in &self.context { 574 writeln!(f, "{}=`{}`", name, context)?; 575 } 576 output_fmt(&self.output, f) 577 } 578 } 579 580 impl fmt::Debug for Assert { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result581 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 582 f.debug_struct("Assert") 583 .field("output", &self.output) 584 .finish() 585 } 586 } 587 588 /// Used by [`Assert::code`] to convert `Self` into the needed 589 /// [`predicates_core::Predicate<i32>`]. 590 /// 591 /// # Examples 592 /// 593 /// ```rust,no_run 594 /// use assert_cmd::prelude::*; 595 /// 596 /// use std::process::Command; 597 /// use predicates::prelude::*; 598 /// 599 /// Command::cargo_bin("bin_fixture") 600 /// .unwrap() 601 /// .env("exit", "42") 602 /// .assert() 603 /// .code(predicate::eq(42)); 604 /// 605 /// // which can be shortened to: 606 /// Command::cargo_bin("bin_fixture") 607 /// .unwrap() 608 /// .env("exit", "42") 609 /// .assert() 610 /// .code(42); 611 /// ``` 612 pub trait IntoCodePredicate<P> 613 where 614 P: predicates_core::Predicate<i32>, 615 { 616 /// The type of the predicate being returned. 617 type Predicate; 618 619 /// Convert to a predicate for testing a program's exit code. into_code(self) -> P620 fn into_code(self) -> P; 621 } 622 623 impl<P> IntoCodePredicate<P> for P 624 where 625 P: predicates_core::Predicate<i32>, 626 { 627 type Predicate = P; 628 into_code(self) -> Self::Predicate629 fn into_code(self) -> Self::Predicate { 630 self 631 } 632 } 633 634 /// Keep `predicates` concrete Predicates out of our public API. 635 /// [predicates_core::Predicate] used by [`IntoCodePredicate`] for code. 636 /// 637 /// # Example 638 /// 639 /// ```rust,no_run 640 /// use assert_cmd::prelude::*; 641 /// 642 /// use std::process::Command; 643 /// 644 /// Command::cargo_bin("bin_fixture") 645 /// .unwrap() 646 /// .env("exit", "42") 647 /// .assert() 648 /// .code(42); 649 /// ``` 650 #[derive(Debug)] 651 pub struct EqCodePredicate(predicates::ord::EqPredicate<i32>); 652 653 impl EqCodePredicate { new(value: i32) -> Self654 pub(crate) fn new(value: i32) -> Self { 655 let pred = predicates::ord::eq(value); 656 EqCodePredicate(pred) 657 } 658 } 659 660 impl predicates_core::reflection::PredicateReflection for EqCodePredicate { parameters<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a>661 fn parameters<'a>( 662 &'a self, 663 ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a> { 664 self.0.parameters() 665 } 666 667 /// Nested `Predicate`s of the current `Predicate`. children<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a>668 fn children<'a>( 669 &'a self, 670 ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a> { 671 self.0.children() 672 } 673 } 674 675 impl predicates_core::Predicate<i32> for EqCodePredicate { eval(&self, item: &i32) -> bool676 fn eval(&self, item: &i32) -> bool { 677 self.0.eval(item) 678 } 679 find_case<'a>( &'a self, expected: bool, variable: &i32, ) -> Option<predicates_core::reflection::Case<'a>>680 fn find_case<'a>( 681 &'a self, 682 expected: bool, 683 variable: &i32, 684 ) -> Option<predicates_core::reflection::Case<'a>> { 685 self.0.find_case(expected, variable) 686 } 687 } 688 689 impl fmt::Display for EqCodePredicate { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result690 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 691 self.0.fmt(f) 692 } 693 } 694 695 impl IntoCodePredicate<EqCodePredicate> for i32 { 696 type Predicate = EqCodePredicate; 697 into_code(self) -> Self::Predicate698 fn into_code(self) -> Self::Predicate { 699 Self::Predicate::new(self) 700 } 701 } 702 703 /// Keep `predicates` concrete Predicates out of our public API. 704 /// [predicates_core::Predicate] used by [`IntoCodePredicate`] for iterables of codes. 705 /// 706 /// # Example 707 /// 708 /// ```rust,no_run 709 /// use assert_cmd::prelude::*; 710 /// 711 /// use std::process::Command; 712 /// 713 /// Command::cargo_bin("bin_fixture") 714 /// .unwrap() 715 /// .env("exit", "42") 716 /// .assert() 717 /// .code(&[2, 42] as &[i32]); 718 /// ``` 719 #[derive(Debug)] 720 pub struct InCodePredicate(predicates::iter::InPredicate<i32>); 721 722 impl InCodePredicate { new<I: IntoIterator<Item = i32>>(value: I) -> Self723 pub(crate) fn new<I: IntoIterator<Item = i32>>(value: I) -> Self { 724 let pred = predicates::iter::in_iter(value); 725 InCodePredicate(pred) 726 } 727 } 728 729 impl predicates_core::reflection::PredicateReflection for InCodePredicate { parameters<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a>730 fn parameters<'a>( 731 &'a self, 732 ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a> { 733 self.0.parameters() 734 } 735 736 /// Nested `Predicate`s of the current `Predicate`. children<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a>737 fn children<'a>( 738 &'a self, 739 ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a> { 740 self.0.children() 741 } 742 } 743 744 impl predicates_core::Predicate<i32> for InCodePredicate { eval(&self, item: &i32) -> bool745 fn eval(&self, item: &i32) -> bool { 746 self.0.eval(item) 747 } 748 find_case<'a>( &'a self, expected: bool, variable: &i32, ) -> Option<predicates_core::reflection::Case<'a>>749 fn find_case<'a>( 750 &'a self, 751 expected: bool, 752 variable: &i32, 753 ) -> Option<predicates_core::reflection::Case<'a>> { 754 self.0.find_case(expected, variable) 755 } 756 } 757 758 impl fmt::Display for InCodePredicate { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result759 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 760 self.0.fmt(f) 761 } 762 } 763 764 impl IntoCodePredicate<InCodePredicate> for Vec<i32> { 765 type Predicate = InCodePredicate; 766 into_code(self) -> Self::Predicate767 fn into_code(self) -> Self::Predicate { 768 Self::Predicate::new(self) 769 } 770 } 771 772 impl IntoCodePredicate<InCodePredicate> for &'static [i32] { 773 type Predicate = InCodePredicate; 774 into_code(self) -> Self::Predicate775 fn into_code(self) -> Self::Predicate { 776 Self::Predicate::new(self.iter().cloned()) 777 } 778 } 779 780 /// Used by [`Assert::stdout`] and [`Assert::stderr`] to convert Self 781 /// into the needed [`predicates_core::Predicate<[u8]>`]. 782 /// 783 /// # Examples 784 /// 785 /// ```rust,no_run 786 /// use assert_cmd::prelude::*; 787 /// 788 /// use std::process::Command; 789 /// use predicates::prelude::*; 790 /// 791 /// Command::cargo_bin("bin_fixture") 792 /// .unwrap() 793 /// .env("stdout", "hello") 794 /// .env("stderr", "world") 795 /// .assert() 796 /// .stdout(predicate::str::diff("hello\n").from_utf8()); 797 /// 798 /// // which can be shortened to: 799 /// Command::cargo_bin("bin_fixture") 800 /// .unwrap() 801 /// .env("stdout", "hello") 802 /// .env("stderr", "world") 803 /// .assert() 804 /// .stdout("hello\n"); 805 /// ``` 806 pub trait IntoOutputPredicate<P> 807 where 808 P: predicates_core::Predicate<[u8]>, 809 { 810 /// The type of the predicate being returned. 811 type Predicate; 812 813 /// Convert to a predicate for testing a path. into_output(self) -> P814 fn into_output(self) -> P; 815 } 816 817 impl<P> IntoOutputPredicate<P> for P 818 where 819 P: predicates_core::Predicate<[u8]>, 820 { 821 type Predicate = P; 822 into_output(self) -> Self::Predicate823 fn into_output(self) -> Self::Predicate { 824 self 825 } 826 } 827 828 /// Keep `predicates` concrete Predicates out of our public API. 829 /// [predicates_core::Predicate] used by [`IntoOutputPredicate`] for bytes. 830 /// 831 /// # Example 832 /// 833 /// ```rust,no_run 834 /// use assert_cmd::prelude::*; 835 /// 836 /// use std::process::Command; 837 /// 838 /// Command::cargo_bin("bin_fixture") 839 /// .unwrap() 840 /// .env("stdout", "hello") 841 /// .env("stderr", "world") 842 /// .assert() 843 /// .stderr(b"world\n" as &[u8]); 844 /// ``` 845 #[derive(Debug)] 846 pub struct BytesContentOutputPredicate(Cow<'static, [u8]>); 847 848 impl BytesContentOutputPredicate { new(value: &'static [u8]) -> Self849 pub(crate) fn new(value: &'static [u8]) -> Self { 850 BytesContentOutputPredicate(Cow::from(value)) 851 } 852 from_vec(value: Vec<u8>) -> Self853 pub(crate) fn from_vec(value: Vec<u8>) -> Self { 854 BytesContentOutputPredicate(Cow::from(value)) 855 } 856 } 857 858 impl predicates_core::reflection::PredicateReflection for BytesContentOutputPredicate {} 859 860 impl predicates_core::Predicate<[u8]> for BytesContentOutputPredicate { eval(&self, item: &[u8]) -> bool861 fn eval(&self, item: &[u8]) -> bool { 862 self.0.as_ref() == item 863 } 864 find_case( &self, expected: bool, variable: &[u8], ) -> Option<predicates_core::reflection::Case>865 fn find_case( 866 &self, 867 expected: bool, 868 variable: &[u8], 869 ) -> Option<predicates_core::reflection::Case> { 870 let actual = self.eval(variable); 871 if expected == actual { 872 Some(predicates_core::reflection::Case::new(Some(self), actual)) 873 } else { 874 None 875 } 876 } 877 } 878 879 impl fmt::Display for BytesContentOutputPredicate { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result880 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 881 predicates::ord::eq(self.0.as_ref()).fmt(f) 882 } 883 } 884 885 impl IntoOutputPredicate<BytesContentOutputPredicate> for Vec<u8> { 886 type Predicate = BytesContentOutputPredicate; 887 into_output(self) -> Self::Predicate888 fn into_output(self) -> Self::Predicate { 889 Self::Predicate::from_vec(self) 890 } 891 } 892 893 impl IntoOutputPredicate<BytesContentOutputPredicate> for &'static [u8] { 894 type Predicate = BytesContentOutputPredicate; 895 into_output(self) -> Self::Predicate896 fn into_output(self) -> Self::Predicate { 897 Self::Predicate::new(self) 898 } 899 } 900 901 /// Keep `predicates` concrete Predicates out of our public API. 902 /// [predicates_core::Predicate] used by [`IntoOutputPredicate`] for [`str`]. 903 /// 904 /// # Example 905 /// 906 /// ```rust,no_run 907 /// use assert_cmd::prelude::*; 908 /// 909 /// use std::process::Command; 910 /// 911 /// Command::cargo_bin("bin_fixture") 912 /// .unwrap() 913 /// .env("stdout", "hello") 914 /// .env("stderr", "world") 915 /// .assert() 916 /// .stderr("world\n"); 917 /// ``` 918 /// 919 /// [`str`]: https://doc.rust-lang.org/std/primitive.str.html 920 #[derive(Debug, Clone)] 921 pub struct StrContentOutputPredicate( 922 predicates::str::Utf8Predicate<predicates::str::DifferencePredicate>, 923 ); 924 925 impl StrContentOutputPredicate { from_str(value: &'static str) -> Self926 pub(crate) fn from_str(value: &'static str) -> Self { 927 let pred = predicates::str::diff(value).from_utf8(); 928 StrContentOutputPredicate(pred) 929 } 930 from_string(value: String) -> Self931 pub(crate) fn from_string(value: String) -> Self { 932 let pred = predicates::str::diff(value).from_utf8(); 933 StrContentOutputPredicate(pred) 934 } 935 } 936 937 impl predicates_core::reflection::PredicateReflection for StrContentOutputPredicate { parameters<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a>938 fn parameters<'a>( 939 &'a self, 940 ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a> { 941 self.0.parameters() 942 } 943 944 /// Nested `Predicate`s of the current `Predicate`. children<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a>945 fn children<'a>( 946 &'a self, 947 ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a> { 948 self.0.children() 949 } 950 } 951 952 impl predicates_core::Predicate<[u8]> for StrContentOutputPredicate { eval(&self, item: &[u8]) -> bool953 fn eval(&self, item: &[u8]) -> bool { 954 self.0.eval(item) 955 } 956 find_case<'a>( &'a self, expected: bool, variable: &[u8], ) -> Option<predicates_core::reflection::Case<'a>>957 fn find_case<'a>( 958 &'a self, 959 expected: bool, 960 variable: &[u8], 961 ) -> Option<predicates_core::reflection::Case<'a>> { 962 self.0.find_case(expected, variable) 963 } 964 } 965 966 impl fmt::Display for StrContentOutputPredicate { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result967 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 968 self.0.fmt(f) 969 } 970 } 971 972 impl IntoOutputPredicate<StrContentOutputPredicate> for String { 973 type Predicate = StrContentOutputPredicate; 974 into_output(self) -> Self::Predicate975 fn into_output(self) -> Self::Predicate { 976 Self::Predicate::from_string(self) 977 } 978 } 979 980 impl IntoOutputPredicate<StrContentOutputPredicate> for &'static str { 981 type Predicate = StrContentOutputPredicate; 982 into_output(self) -> Self::Predicate983 fn into_output(self) -> Self::Predicate { 984 Self::Predicate::from_str(self) 985 } 986 } 987 988 // Keep `predicates` concrete Predicates out of our public API. 989 /// [predicates_core::Predicate] used by [`IntoOutputPredicate`] for 990 /// [`Predicate<str>`][predicates_core::Predicate]. 991 /// 992 /// # Example 993 /// 994 /// ```rust,no_run 995 /// use assert_cmd::prelude::*; 996 /// 997 /// use std::process::Command; 998 /// use predicates::prelude::*; 999 /// 1000 /// Command::cargo_bin("bin_fixture") 1001 /// .unwrap() 1002 /// .env("stdout", "hello") 1003 /// .env("stderr", "world") 1004 /// .assert() 1005 /// .stderr(predicate::str::diff("world\n")); 1006 /// ``` 1007 #[derive(Debug, Clone)] 1008 pub struct StrOutputPredicate<P: predicates_core::Predicate<str>>( 1009 predicates::str::Utf8Predicate<P>, 1010 ); 1011 1012 impl<P> StrOutputPredicate<P> 1013 where 1014 P: predicates_core::Predicate<str>, 1015 { new(pred: P) -> Self1016 pub(crate) fn new(pred: P) -> Self { 1017 let pred = pred.from_utf8(); 1018 StrOutputPredicate(pred) 1019 } 1020 } 1021 1022 impl<P> predicates_core::reflection::PredicateReflection for StrOutputPredicate<P> 1023 where 1024 P: predicates_core::Predicate<str>, 1025 { parameters<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a>1026 fn parameters<'a>( 1027 &'a self, 1028 ) -> Box<dyn Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a> { 1029 self.0.parameters() 1030 } 1031 1032 /// Nested `Predicate`s of the current `Predicate`. children<'a>( &'a self, ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a>1033 fn children<'a>( 1034 &'a self, 1035 ) -> Box<dyn Iterator<Item = predicates_core::reflection::Child<'a>> + 'a> { 1036 self.0.children() 1037 } 1038 } 1039 1040 impl<P> predicates_core::Predicate<[u8]> for StrOutputPredicate<P> 1041 where 1042 P: predicates_core::Predicate<str>, 1043 { eval(&self, item: &[u8]) -> bool1044 fn eval(&self, item: &[u8]) -> bool { 1045 self.0.eval(item) 1046 } 1047 find_case<'a>( &'a self, expected: bool, variable: &[u8], ) -> Option<predicates_core::reflection::Case<'a>>1048 fn find_case<'a>( 1049 &'a self, 1050 expected: bool, 1051 variable: &[u8], 1052 ) -> Option<predicates_core::reflection::Case<'a>> { 1053 self.0.find_case(expected, variable) 1054 } 1055 } 1056 1057 impl<P> fmt::Display for StrOutputPredicate<P> 1058 where 1059 P: predicates_core::Predicate<str>, 1060 { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1061 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1062 self.0.fmt(f) 1063 } 1064 } 1065 1066 impl<P> IntoOutputPredicate<StrOutputPredicate<P>> for P 1067 where 1068 P: predicates_core::Predicate<str>, 1069 { 1070 type Predicate = StrOutputPredicate<P>; 1071 into_output(self) -> Self::Predicate1072 fn into_output(self) -> Self::Predicate { 1073 Self::Predicate::new(self) 1074 } 1075 } 1076 1077 #[cfg(test)] 1078 mod test { 1079 use super::*; 1080 1081 use predicates::prelude::*; 1082 1083 // Since IntoCodePredicate exists solely for conversion, test it under that scenario to ensure 1084 // it works as expected. convert_code<I, P>(pred: I) -> P where I: IntoCodePredicate<P>, P: predicates_core::Predicate<i32>,1085 fn convert_code<I, P>(pred: I) -> P 1086 where 1087 I: IntoCodePredicate<P>, 1088 P: predicates_core::Predicate<i32>, 1089 { 1090 pred.into_code() 1091 } 1092 1093 #[test] into_code_from_pred()1094 fn into_code_from_pred() { 1095 let pred = convert_code(predicate::eq(10)); 1096 assert!(pred.eval(&10)); 1097 } 1098 1099 #[test] into_code_from_i32()1100 fn into_code_from_i32() { 1101 let pred = convert_code(10); 1102 assert!(pred.eval(&10)); 1103 } 1104 1105 #[test] into_code_from_vec()1106 fn into_code_from_vec() { 1107 let pred = convert_code(vec![3, 10]); 1108 assert!(pred.eval(&10)); 1109 } 1110 1111 #[test] into_code_from_array()1112 fn into_code_from_array() { 1113 let pred = convert_code(&[3, 10] as &[i32]); 1114 assert!(pred.eval(&10)); 1115 } 1116 1117 // Since IntoOutputPredicate exists solely for conversion, test it under that scenario to ensure 1118 // it works as expected. convert_output<I, P>(pred: I) -> P where I: IntoOutputPredicate<P>, P: predicates_core::Predicate<[u8]>,1119 fn convert_output<I, P>(pred: I) -> P 1120 where 1121 I: IntoOutputPredicate<P>, 1122 P: predicates_core::Predicate<[u8]>, 1123 { 1124 pred.into_output() 1125 } 1126 1127 #[test] into_output_from_pred()1128 fn into_output_from_pred() { 1129 let pred = convert_output(predicate::eq(b"Hello" as &[u8])); 1130 assert!(pred.eval(b"Hello" as &[u8])); 1131 } 1132 1133 #[test] into_output_from_bytes()1134 fn into_output_from_bytes() { 1135 let pred = convert_output(b"Hello" as &[u8]); 1136 assert!(pred.eval(b"Hello" as &[u8])); 1137 } 1138 1139 #[test] into_output_from_vec()1140 fn into_output_from_vec() { 1141 let pred = convert_output(vec![b'H', b'e', b'l', b'l', b'o']); 1142 assert!(pred.eval(b"Hello" as &[u8])); 1143 } 1144 1145 #[test] into_output_from_str()1146 fn into_output_from_str() { 1147 let pred = convert_output("Hello"); 1148 assert!(pred.eval(b"Hello" as &[u8])); 1149 } 1150 } 1151