88//! Here's a trivial example:
99//!
1010//! ```rust
11- //! extern crate assert_cli;
11+ //! # extern crate assert_cli;
12+ //!
1213//! assert_cli::assert_cli_output("echo", &["42"], "42").unwrap();
1314//! ```
1415//!
1516//! And here is one that will fail:
1617//!
1718//! ```rust,should_panic
18- //! extern crate assert_cli;
1919//! assert_cli::assert_cli_output("echo", &["42"], "1337").unwrap();
2020//! ```
2121//!
2525//! -1337
2626//! +42
2727//! ```
28+ //!
29+ //! Alternatively, you can use the `assert_cli!` macro:
30+ //!
31+ //! ```rust,ignore
32+ //! assert_cli!("echo 42" => Success, "42").unwrap();
33+ //! ```
34+ //!
35+ //! Make sure to include the crate as `#[macro_use] extern crate assert_cli;`.
36+
2837
2938#![ cfg_attr( feature = "dev" , feature( plugin) ) ]
3039#![ cfg_attr( feature = "dev" , plugin( clippy) ) ]
@@ -48,22 +57,22 @@ use cli_error::CliError;
4857/// To test that
4958///
5059/// ```sh
51- /// ls -n1 src/
60+ /// bash -c $BLACK_BOX
5261/// ```
5362///
5463/// returns
5564///
5665/// ```plain
57- /// cli_error.rs
58- /// diff.rs
59- /// lib.rs
66+ /// Launch sequence initiated.
6067/// ```
6168///
6269/// you would call it like this:
6370///
64- /// ```rust,no_run
71+ /// ```rust
6572/// # extern crate assert_cli;
66- /// assert_cli::assert_cli_output("ls", &["-n1", "src/"], "cli_error.rs\ndiff.rs\nlib.rs");
73+ /// # const BLACK_BOX: &'static str = r#"function test_helper() {\
74+ /// # echo "Launch sequence initiated."; return 0; }; test_helper"#;
75+ /// assert_cli::assert_cli_output("bash", &["-c", BLACK_BOX], "Launch sequence initiated.");
6776/// ```
6877pub fn assert_cli_output < S > ( cmd : & str , args : & [ S ] , expected_output : & str ) -> Result < ( ) , Box < Error > >
6978 where S : AsRef < OsStr >
@@ -75,7 +84,7 @@ pub fn assert_cli_output<S>(cmd: &str, args: &[S], expected_output: &str) -> Res
7584
7685 call. and_then ( |output| {
7786 if !output. status . success ( ) {
78- return Err ( From :: from ( CliError :: NoSuccess ( output) ) ) ;
87+ return Err ( From :: from ( CliError :: WrongExitCode ( output) ) ) ;
7988 }
8089
8190 let stdout = String :: from_utf8_lossy ( & output. stdout ) ;
@@ -90,3 +99,83 @@ pub fn assert_cli_output<S>(cmd: &str, args: &[S], expected_output: &str) -> Res
9099 } )
91100 . map_err ( From :: from)
92101}
102+
103+ /// Assert a CLI call that fails the expected `stderr` output and error code.
104+ ///
105+ /// To test that
106+ ///
107+ /// ```sh
108+ /// bash -c $BLACK_BOX
109+ /// ```
110+ ///
111+ /// fails with an exit code of `42` after printing this to `stderr`
112+ ///
113+ /// ```plain
114+ /// error no 42!
115+ /// ```
116+ ///
117+ /// you would call it like this:
118+ ///
119+ /// ```rust
120+ /// # extern crate assert_cli;
121+ /// # const BLACK_BOX: &'static str = r#"function test_helper() {\
122+ /// # >&2 echo "error no 42!"; return 42; }; test_helper"#;
123+ /// assert_cli::assert_cli_output_error("bash", &["-c", BLACK_BOX], Some(42), "error no 42!");
124+ /// ```
125+ pub fn assert_cli_output_error < S > ( cmd : & str ,
126+ args : & [ S ] ,
127+ error_code : Option < i32 > ,
128+ expected_output : & str )
129+ -> Result < ( ) , Box < Error > >
130+ where S : AsRef < OsStr >
131+ {
132+ let call: Result < Output , Box < Error > > = Command :: new ( cmd)
133+ . args ( args)
134+ . output ( )
135+ . map_err ( From :: from) ;
136+
137+ call. and_then ( |output| {
138+ if output. status . success ( ) {
139+ return Err ( From :: from ( CliError :: WrongExitCode ( output) ) ) ;
140+ }
141+
142+ match ( error_code, output. status . code ( ) ) {
143+ ( Some ( a) , Some ( b) ) if a != b =>
144+ return Err ( From :: from ( CliError :: WrongExitCode ( output) ) ) ,
145+ _ => { }
146+ }
147+
148+ let stdout = String :: from_utf8_lossy ( & output. stderr ) ;
149+ let ( distance, changes) = difference:: diff ( expected_output. trim ( ) ,
150+ & stdout. trim ( ) ,
151+ "\n " ) ;
152+ if distance > 0 {
153+ return Err ( From :: from ( CliError :: OutputMissmatch ( changes) ) ) ;
154+ }
155+
156+ Ok ( ( ) )
157+ } )
158+ . map_err ( From :: from)
159+ }
160+
161+ /// The `assert_cli!` macro combines the functionality of the other functions in this crate in one
162+ /// short macro.
163+ ///
164+ /// ```rust,ignore
165+ /// assert_cli!("echo 42" => Success, "42").unwrap();
166+ /// assert_cli!("exit 11" => Error 11, "").unwrap();
167+ /// ```
168+ ///
169+ /// Make sure to include the crate as `#[macro_use] extern crate assert_cli;`.
170+ #[ macro_export]
171+ macro_rules! assert_cli {
172+ ( $cmd: expr, $args: expr => Success , $output: expr) => { {
173+ $crate:: assert_cli_output( $cmd, $args, $output)
174+ } } ;
175+ ( $cmd: expr, $args: expr => Error , $output: expr) => { {
176+ $crate:: assert_cli_output_error( $cmd, $args, None , $output)
177+ } } ;
178+ ( $cmd: expr, $args: expr => Error $err: expr, $output: expr) => { {
179+ $crate:: assert_cli_output_error( $cmd, $args, Some ( $err) , $output)
180+ } } ;
181+ }
0 commit comments