Skip to content
This repository was archived by the owner on Dec 29, 2021. It is now read-only.
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit f0260d5

Browse files
committedOct 16, 2015
Merge pull request #1 from killercup/feature/err-and-macro
Assert CLI Error
2 parents c7cc61f + f5ad27a commit f0260d5

File tree

5 files changed

+135
-14
lines changed

5 files changed

+135
-14
lines changed
 

‎Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ dev = ["clippy"]
1616
[dependencies]
1717
ansi_term = "0.6.3"
1818
difference = "0.4.0"
19-
clippy = {version = "0.0.19", optional = true}
19+
clippy = {version = "0.0.21", optional = true}

‎Readme.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@ extern crate assert_cli;
2525
assert_cli::assert_cli_output("echo", &["42"], "42").unwrap();
2626
```
2727

28+
Or if you'd rather use the macro:
29+
30+
```rust,ignore
31+
#[macro_use] extern crate assert_cli;
32+
assert_cli!("echo", &["42"] => Success, "42").unwrap();
33+
assert_cli!("black-box", &["--special"] => Error 42, "error no 42\n").unwrap()
34+
```
35+
2836
And here is one that will fail:
2937

3038
```rust,should_panic

‎src/cli_error.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::process::Output;
66
use difference::Difference;
77

88
pub enum CliError {
9-
NoSuccess(Output),
9+
WrongExitCode(Output),
1010
OutputMissmatch(Vec<Difference>),
1111
}
1212

@@ -19,8 +19,8 @@ impl fmt::Display for CliError {
1919
impl fmt::Debug for CliError {
2020
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2121
match *self {
22-
CliError::NoSuccess(ref output) => write!(f,
23-
"Non-success error code {code:?} with this stderr:\n{stderr}",
22+
CliError::WrongExitCode(ref output) => write!(f,
23+
"Unexpected error code {code:?} with this stderr:\n{stderr}",
2424
code = output.status.code(),
2525
stderr = String::from_utf8_lossy(&output.stderr)),
2626
CliError::OutputMissmatch(ref diff) => {
@@ -37,7 +37,7 @@ impl fmt::Debug for CliError {
3737
impl Error for CliError {
3838
fn description(&self) -> &str {
3939
match *self {
40-
CliError::NoSuccess(_) => "Command return non-success error code.",
40+
CliError::WrongExitCode(_) => "Command return unexpected error code.",
4141
CliError::OutputMissmatch(_) => "Command output was not as expected.",
4242
}
4343
}

‎src/lib.rs

Lines changed: 98 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
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
//!
@@ -25,6 +25,15 @@
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
/// ```
6877
pub 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+
}

‎tests/macro.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#[macro_use]
2+
extern crate assert_cli;
3+
4+
fn test_helper(exit_code: i32, output: &str) -> Vec<String> {
5+
vec!["-c".into(),
6+
format!(r#"function test_helper() {{ >&2 echo $1; return {}; }}; test_helper "{}""#,
7+
exit_code,
8+
output)]
9+
}
10+
11+
#[test]
12+
fn assert_success() {
13+
assert_cli!("echo", &["42"] => Success, "42").unwrap();
14+
assert!(assert_cli!("echo", &["1"] => Success, "42").is_err());
15+
}
16+
17+
#[test]
18+
fn assert_failure() {
19+
assert_cli!("bash", &test_helper(66, "sorry, my bad") => Error, "sorry, my bad").unwrap();
20+
assert_cli!("bash", &test_helper(42, "error no 42") => Error 42, "error no 42").unwrap();
21+
22+
assert!(assert_cli!("echo", &["good"] => Error, "").is_err());
23+
assert!(assert_cli!("echo", &["good"] => Error 11, "").is_err());
24+
}

0 commit comments

Comments
 (0)
This repository has been archived.