#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]
#![deny(missing_docs)]
extern crate ansi_term;
extern crate difference;
use std::process::{Command, Output};
use std::error::Error;
use std::ffi::OsStr;
mod cli_error;
mod diff;
use cli_error::CliError;
pub fn assert_cli<S>(cmd: &str, args: &[S]) -> Result<(), Box<Error>>
where S: AsRef<OsStr>
{
let call: Result<Output, Box<Error>> = Command::new(cmd)
.args(args)
.output()
.map_err(From::from);
call.and_then(|output| {
if !output.status.success() {
return Err(From::from(CliError::WrongExitCode(output)));
}
Ok(())
})
.map_err(From::from)
}
pub fn assert_cli_output<S>(cmd: &str, args: &[S], expected_output: &str) -> Result<(), Box<Error>>
where S: AsRef<OsStr>
{
let call: Result<Output, Box<Error>> = Command::new(cmd)
.args(args)
.output()
.map_err(From::from);
call.and_then(|output| {
if !output.status.success() {
return Err(From::from(CliError::WrongExitCode(output)));
}
let stdout = String::from_utf8_lossy(&output.stdout);
let (distance, changes) = difference::diff(expected_output.trim(),
&stdout.trim(),
"\n");
if distance > 0 {
return Err(From::from(CliError::OutputMissmatch(changes)));
}
Ok(())
})
.map_err(From::from)
}
pub fn assert_cli_error<S>(cmd: &str,
args: &[S],
error_code: Option<i32>)
-> Result<(), Box<Error>>
where S: AsRef<OsStr>
{
let call: Result<Output, Box<Error>> = Command::new(cmd)
.args(args)
.output()
.map_err(From::from);
call.and_then(|output| {
if output.status.success() {
return Err(From::from(CliError::WrongExitCode(output)));
}
match (error_code, output.status.code()) {
(Some(a), Some(b)) if a != b =>
return Err(From::from(CliError::WrongExitCode(output))),
_ => {}
}
Ok(())
})
.map_err(From::from)
}
pub fn assert_cli_output_error<S>(cmd: &str,
args: &[S],
error_code: Option<i32>,
expected_output: &str)
-> Result<(), Box<Error>>
where S: AsRef<OsStr>
{
let call: Result<Output, Box<Error>> = Command::new(cmd)
.args(args)
.output()
.map_err(From::from);
call.and_then(|output| {
if output.status.success() {
return Err(From::from(CliError::WrongExitCode(output)));
}
match (error_code, output.status.code()) {
(Some(a), Some(b)) if a != b =>
return Err(From::from(CliError::WrongExitCode(output))),
_ => {}
}
let stdout = String::from_utf8_lossy(&output.stderr);
let (distance, changes) = difference::diff(expected_output.trim(),
&stdout.trim(),
"\n");
if distance > 0 {
return Err(From::from(CliError::OutputMissmatch(changes)));
}
Ok(())
})
.map_err(From::from)
}
#[macro_export]
macro_rules! assert_cli {
($cmd:expr, $args:expr => Success) => {{
$crate::assert_cli($cmd, $args)
}};
($cmd:expr, $args:expr => Success, $output:expr) => {{
$crate::assert_cli_output($cmd, $args, $output)
}};
($cmd:expr, $args:expr => Error, $output:expr) => {{
$crate::assert_cli_output_error($cmd, $args, None, $output)
}};
($cmd:expr, $args:expr => Error $err:expr, $output:expr) => {{
$crate::assert_cli_output_error($cmd, $args, Some($err), $output)
}};
($cmd:expr, $args:expr => Error) => {{
$crate::assert_cli_error($cmd, $args, None)
}};
($cmd:expr, $args:expr => Error $err:expr) => {{
$crate::assert_cli_error($cmd, $args, Some($err))
}};
}