11use environment:: Environment ;
22use error_chain:: ChainedError ;
33use errors:: * ;
4- use output:: { OutputAssertion , OutputKind } ;
4+ use output:: { Content , Output , OutputKind , OutputPredicate } ;
55use std:: default;
66use std:: ffi:: { OsStr , OsString } ;
77use std:: io:: Write ;
@@ -18,8 +18,8 @@ pub struct Assert {
1818 current_dir : Option < PathBuf > ,
1919 expect_success : Option < bool > ,
2020 expect_exit_code : Option < i32 > ,
21- expect_output : Vec < OutputAssertion > ,
22- stdin_contents : Option < String > ,
21+ expect_output : Vec < OutputPredicate > ,
22+ stdin_contents : Option < Vec < u8 > > ,
2323}
2424
2525impl default:: Default for Assert {
@@ -118,8 +118,8 @@ impl Assert {
118118 /// .stdout().contains("42")
119119 /// .unwrap();
120120 /// ```
121- pub fn stdin ( mut self , contents : & str ) -> Self {
122- self . stdin_contents = Some ( String :: from ( contents) ) ;
121+ pub fn stdin < S : Into < Vec < u8 > > > ( mut self , contents : S ) -> Self {
122+ self . stdin_contents = Some ( contents. into ( ) ) ;
123123 self
124124 }
125125
@@ -289,7 +289,6 @@ impl Assert {
289289 OutputAssertionBuilder {
290290 assertion : self ,
291291 kind : OutputKind :: StdOut ,
292- expected_result : true ,
293292 }
294293 }
295294
@@ -310,7 +309,6 @@ impl Assert {
310309 OutputAssertionBuilder {
311310 assertion : self ,
312311 kind : OutputKind :: StdErr ,
313- expected_result : true ,
314312 }
315313 }
316314
@@ -327,10 +325,10 @@ impl Assert {
327325 /// assert!(test.is_ok());
328326 /// ```
329327 pub fn execute ( self ) -> Result < ( ) > {
330- let cmd = & self . cmd [ 0 ] ;
328+ let bin = & self . cmd [ 0 ] ;
331329
332330 let args: Vec < _ > = self . cmd . iter ( ) . skip ( 1 ) . collect ( ) ;
333- let mut command = Command :: new ( cmd ) ;
331+ let mut command = Command :: new ( bin ) ;
334332 let command = command
335333 . stdin ( Stdio :: piped ( ) )
336334 . stdout ( Stdio :: piped ( ) )
@@ -353,38 +351,34 @@ impl Assert {
353351 . stdin
354352 . as_mut ( )
355353 . expect ( "Couldn't get mut ref to command stdin" )
356- . write_all ( contents. as_bytes ( ) ) ?;
354+ . write_all ( contents) ?;
357355 }
358356 let output = spawned. wait_with_output ( ) ?;
359357
360358 if let Some ( expect_success) = self . expect_success {
361359 if expect_success != output. status . success ( ) {
362360 let out = String :: from_utf8_lossy ( & output. stdout ) . to_string ( ) ;
363361 let err = String :: from_utf8_lossy ( & output. stderr ) . to_string ( ) ;
364- bail ! ( ErrorKind :: StatusMismatch (
365- self . cmd. clone( ) ,
366- expect_success,
367- out,
368- err,
369- ) ) ;
362+ let err: Error = ErrorKind :: StatusMismatch ( expect_success, out, err) . into ( ) ;
363+ bail ! ( err. chain_err( || ErrorKind :: AssertionFailed ( self . cmd. clone( ) ) ) ) ;
370364 }
371365 }
372366
373367 if self . expect_exit_code . is_some ( ) && self . expect_exit_code != output. status . code ( ) {
374368 let out = String :: from_utf8_lossy ( & output. stdout ) . to_string ( ) ;
375369 let err = String :: from_utf8_lossy ( & output. stderr ) . to_string ( ) ;
376- bail ! ( ErrorKind :: ExitCodeMismatch (
377- self . cmd. clone( ) ,
378- self . expect_exit_code,
379- output. status. code( ) ,
380- out,
381- err,
382- ) ) ;
370+ let err: Error =
371+ ErrorKind :: ExitCodeMismatch ( self . expect_exit_code , output. status . code ( ) , out, err)
372+ . into ( ) ;
373+ bail ! ( err. chain_err( || ErrorKind :: AssertionFailed ( self . cmd. clone( ) ) ) ) ;
383374 }
384375
385376 self . expect_output
386377 . iter ( )
387- . map ( |a| a. execute ( & output, & self . cmd ) )
378+ . map ( |a| {
379+ a. verify ( & output)
380+ . chain_err ( || ErrorKind :: AssertionFailed ( self . cmd . clone ( ) ) )
381+ } )
388382 . collect :: < Result < Vec < ( ) > > > ( ) ?;
389383
390384 Ok ( ( ) )
@@ -414,98 +408,96 @@ impl Assert {
414408pub struct OutputAssertionBuilder {
415409 assertion : Assert ,
416410 kind : OutputKind ,
417- expected_result : bool ,
418411}
419412
420413impl OutputAssertionBuilder {
421- /// Negate the assertion predicate
414+ /// Expect the command's output to **contain** `output`.
422415 ///
423416 /// # Examples
424417 ///
425418 /// ```rust
426419 /// extern crate assert_cli;
427420 ///
428421 /// assert_cli::Assert::command(&["echo", "42"])
429- /// .stdout().not(). contains("73 ")
422+ /// .stdout().contains("42 ")
430423 /// .unwrap();
431424 /// ```
432- // No clippy, we don't want to implement std::ops::Not :)
433- #[ cfg_attr( feature = "cargo-clippy" , allow( should_implement_trait) ) ]
434- pub fn not ( mut self ) -> Self {
435- self . expected_result = !self . expected_result ;
436- self
425+ pub fn contains < O : Into < Content > > ( mut self , output : O ) -> Assert {
426+ let pred = OutputPredicate :: new ( self . kind , Output :: contains ( output) ) ;
427+ self . assertion . expect_output . push ( pred) ;
428+ self . assertion
437429 }
438430
439- /// Expect the command's output to **contain** `output`.
431+ /// Expect the command to output **exactly** this `output`.
440432 ///
441433 /// # Examples
442434 ///
443435 /// ```rust
444436 /// extern crate assert_cli;
445437 ///
446438 /// assert_cli::Assert::command(&["echo", "42"])
447- /// .stdout().contains ("42")
439+ /// .stdout().is ("42")
448440 /// .unwrap();
449441 /// ```
450- pub fn contains < O : Into < String > > ( mut self , output : O ) -> Assert {
451- self . assertion . expect_output . push ( OutputAssertion {
452- expect : output. into ( ) ,
453- fuzzy : true ,
454- expected_result : self . expected_result ,
455- kind : self . kind ,
456- } ) ;
442+ pub fn is < O : Into < Content > > ( mut self , output : O ) -> Assert {
443+ let pred = OutputPredicate :: new ( self . kind , Output :: is ( output) ) ;
444+ self . assertion . expect_output . push ( pred) ;
457445 self . assertion
458446 }
459447
460- /// Expect the command to output **exactly** this `output`.
448+ /// Expect the command's output to not **contain** `output`.
461449 ///
462450 /// # Examples
463451 ///
464452 /// ```rust
465453 /// extern crate assert_cli;
466454 ///
467455 /// assert_cli::Assert::command(&["echo", "42"])
468- /// .stdout().is("42 ")
456+ /// .stdout().doesnt_contain("73 ")
469457 /// .unwrap();
470458 /// ```
471- pub fn is < O : Into < String > > ( mut self , output : O ) -> Assert {
472- self . assertion . expect_output . push ( OutputAssertion {
473- expect : output. into ( ) ,
474- fuzzy : false ,
475- expected_result : self . expected_result ,
476- kind : self . kind ,
477- } ) ;
459+ pub fn doesnt_contain < O : Into < Content > > ( mut self , output : O ) -> Assert {
460+ let pred = OutputPredicate :: new ( self . kind , Output :: doesnt_contain ( output) ) ;
461+ self . assertion . expect_output . push ( pred) ;
478462 self . assertion
479463 }
480464
481- /// Expect the command's output to not **contain** `output`.
465+ /// Expect the command to output to not be **exactly** this `output`.
482466 ///
483467 /// # Examples
484468 ///
485469 /// ```rust
486470 /// extern crate assert_cli;
487471 ///
488472 /// assert_cli::Assert::command(&["echo", "42"])
489- /// .stdout().doesnt_contain ("73")
473+ /// .stdout().isnt ("73")
490474 /// .unwrap();
491475 /// ```
492- pub fn doesnt_contain < O : Into < String > > ( self , output : O ) -> Assert {
493- self . not ( ) . contains ( output)
476+ pub fn isnt < O : Into < Content > > ( mut self , output : O ) -> Assert {
477+ let pred = OutputPredicate :: new ( self . kind , Output :: isnt ( output) ) ;
478+ self . assertion . expect_output . push ( pred) ;
479+ self . assertion
494480 }
495481
496- /// Expect the command to output to not be **exactly** this `output` .
482+ /// Expect the command output to satisfy the given predicate .
497483 ///
498484 /// # Examples
499485 ///
500486 /// ```rust
501487 /// extern crate assert_cli;
502488 ///
503- /// assert_cli::Assert::command(&["echo", "42"])
504- /// .stdout().isnt("73 ")
489+ /// assert_cli::Assert::command(&["echo", "-n", " 42"])
490+ /// .stdout().satisfies(|x| x.len() == 2, "bad length ")
505491 /// .unwrap();
506492 /// ```
507- pub fn isnt < O : Into < String > > ( self , output : O ) -> Assert {
508- self . not ( ) . is ( output)
493+ pub fn satisfies < F , M > ( mut self , pred : F , msg : M ) -> Assert
494+ where
495+ F : ' static + Fn ( & str ) -> bool ,
496+ M : Into < String > ,
497+ {
498+ let pred = OutputPredicate :: new ( self . kind , Output :: satisfies ( pred, msg) ) ;
499+ self . assertion . expect_output . push ( pred) ;
500+ self . assertion
509501 }
510502}
511503
@@ -522,7 +514,11 @@ mod test {
522514 fn take_ownership ( ) {
523515 let x = Environment :: inherit ( ) ;
524516
525- command ( ) . with_env ( x. clone ( ) ) . with_env ( & x) . with_env ( x) ;
517+ command ( )
518+ . with_env ( x. clone ( ) )
519+ . with_env ( & x)
520+ . with_env ( x)
521+ . unwrap ( ) ;
526522 }
527523
528524 #[ test]
@@ -564,8 +560,7 @@ mod test {
564560 command ( )
565561 . with_env ( y)
566562 . stdout ( )
567- . not ( )
568- . contains ( "key=value" )
563+ . doesnt_contain ( "key=value" )
569564 . execute ( )
570565 . unwrap ( ) ;
571566 }
0 commit comments