Skip to content

Commit

Permalink
fix(assert): Change set_stdin to clarify intent
Browse files Browse the repository at this point in the history
While the documentation for `set_stdin` and `with_stdin` is clear, we
can't expect everyone to read the documentation closely.  This attempts
to make the API harder to misuse so users can be more successful.

BREAKING CHANGE: `Assert::set_cmd` and `Assert::set_stdin` have been
replaced with `Assert::append_context`.

Fixes #29
  • Loading branch information
epage committed Jul 27, 2018
1 parent b6e0f7e commit 624a798
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 44 deletions.
45 changes: 20 additions & 25 deletions src/assert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::str;
use predicates;
use predicates::str::PredicateStrExt;

use cmd::dump_buffer;
use errors::dump_buffer;
use errors::output_fmt;

/// Assert the state of an `Output`.
Expand Down Expand Up @@ -51,7 +51,7 @@ impl OutputAssertExt for process::Output {
impl<'c> OutputAssertExt for &'c mut process::Command {
fn assert(self) -> Assert {
let output = self.output().unwrap();
Assert::new(output).set_cmd(format!("{:?}", self))
Assert::new(output).append_context("command", format!("{:?}", self))
}
}

Expand All @@ -71,32 +71,26 @@ impl<'c> OutputAssertExt for &'c mut process::Command {
/// .assert()
/// .success();
/// ```
#[derive(Debug)]
pub struct Assert {
output: process::Output,
cmd: Option<String>,
stdin: Option<Vec<u8>>,
context: Vec<(&'static str, Box<fmt::Display>)>,
}

impl Assert {
/// Create an `Assert` for a given `Output`.
pub fn new(output: process::Output) -> Self {
Self {
output,
cmd: None,
stdin: None,
context: vec![],
}
}

/// Add the command line for additional context.
pub fn set_cmd(mut self, cmd: String) -> Self {
self.cmd = Some(cmd);
self
}

/// Add the `stdn` for additional context.
pub fn set_stdin(mut self, stdin: Vec<u8>) -> Self {
self.stdin = Some(stdin);
/// Clarify failures with additional context.
pub fn append_context<D>(mut self, name: &'static str, context: D) -> Self
where
D: fmt::Display + 'static,
{
self.context.push((name, Box::new(context)));
self
}

Expand Down Expand Up @@ -298,20 +292,21 @@ impl Assert {

impl fmt::Display for Assert {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(ref cmd) = self.cmd {
writeln!(f, "command=`{}`", cmd)?;
}
if let Some(ref stdin) = self.stdin {
if let Ok(stdin) = str::from_utf8(stdin) {
writeln!(f, "stdin=```{}```", stdin)?;
} else {
writeln!(f, "stdin=```{:?}```", stdin)?;
}
for &(ref name, ref context) in &self.context {
writeln!(f, "{}=`{}`", name, context)?;
}
output_fmt(&self.output, f)
}
}

impl fmt::Debug for Assert {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Assert")
.field("output", &self.output)
.finish()
}
}

/// Used by `Assert::code` to convert `Self` into the needed `Predicate<i32>`.
///
/// # Examples
Expand Down
10 changes: 1 addition & 9 deletions src/cmd.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::process;
use std::str;

use errors::dump_buffer;
use errors::OutputError;
use errors::OutputResult;

Expand Down Expand Up @@ -116,11 +116,3 @@ impl<'c> OutputOkExt for &'c mut process::Command {
}
}
}

pub(crate) fn dump_buffer(buffer: &[u8]) -> String {
if let Ok(buffer) = str::from_utf8(buffer) {
buffer.to_string()
} else {
format!("{:?}", buffer)
}
}
45 changes: 38 additions & 7 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,16 +162,47 @@ pub(crate) fn output_fmt(output: &process::Output, f: &mut fmt::Formatter) -> fm
} else {
writeln!(f, "code=<interrupted>")?;
}
if let Ok(stdout) = str::from_utf8(&output.stdout) {
writeln!(f, "stdout=```{}```", stdout)?;

write!(f, "stdout=```")?;
write_buffer(&output.stdout, f)?;
writeln!(f, "```")?;

write!(f, "stderr=```")?;
write_buffer(&output.stderr, f)?;
writeln!(f, "```")?;

Ok(())
}

pub(crate) fn dump_buffer(buffer: &[u8]) -> String {
if let Ok(buffer) = str::from_utf8(buffer) {
buffer.to_string()
} else {
writeln!(f, "stdout=```{:?}```", output.stdout)?;
format!("{:?}", buffer)
}
if let Ok(stderr) = str::from_utf8(&output.stderr) {
writeln!(f, "stderr=```{}```", stderr)?;
}

pub(crate) fn write_buffer(buffer: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
if let Ok(buffer) = str::from_utf8(buffer) {
write!(f, "{}", buffer)
} else {
writeln!(f, "stderr=```{:?}```", output.stderr)?;
write!(f, "{:?}", buffer)
}
}

#[derive(Debug)]
pub(crate) struct DebugBuffer {
buffer: Vec<u8>,
}

impl DebugBuffer {
pub(crate) fn new(buffer: Vec<u8>) -> Self {
DebugBuffer { buffer }
}
}

Ok(())
impl fmt::Display for DebugBuffer {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write_buffer(&self.buffer, f)
}
}
7 changes: 4 additions & 3 deletions src/stdin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ use std::process;

use assert::Assert;
use assert::OutputAssertExt;
use cmd::dump_buffer;
use cmd::OutputOkExt;
use errors::dump_buffer;
use errors::DebugBuffer;
use errors::OutputError;
use errors::OutputResult;

Expand Down Expand Up @@ -189,7 +190,7 @@ impl<'c> OutputAssertExt for &'c mut StdInCommand<'c> {
fn assert(self) -> Assert {
let output = self.output().unwrap();
Assert::new(output)
.set_cmd(format!("{:?}", self.cmd))
.set_stdin(self.stdin.clone())
.append_context("command", format!("{:?}", self.cmd))
.append_context("stdin", DebugBuffer::new(self.stdin.clone()))
}
}

0 comments on commit 624a798

Please sign in to comment.