Skip to content
This repository has been archived by the owner on Dec 29, 2021. It is now read-only.

Commit

Permalink
Refactor Output Traits into Enum
Browse files Browse the repository at this point in the history
This simplifies the logic for generically adding new assertions at the
cost of an match statement for each output assertion executed.
  • Loading branch information
epage committed Sep 14, 2017
1 parent 57245da commit c25b46b
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 63 deletions.
48 changes: 21 additions & 27 deletions src/assert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::path::PathBuf;
use std::vec::Vec;

use errors::*;
use output::{OutputAssertion, StdErr, StdOut};
use output::{OutputAssertion, OutputKind};

/// Assertions for a specific command.
#[derive(Debug)]
Expand All @@ -13,8 +13,7 @@ pub struct Assert {
current_dir: Option<PathBuf>,
expect_success: Option<bool>,
expect_exit_code: Option<i32>,
expect_stdout: Vec<OutputAssertion<StdOut>>,
expect_stderr: Vec<OutputAssertion<StdErr>>,
expect_output: Vec<OutputAssertion>,
}

impl default::Default for Assert {
Expand All @@ -28,8 +27,7 @@ impl default::Default for Assert {
current_dir: None,
expect_success: Some(true),
expect_exit_code: None,
expect_stdout: vec![],
expect_stderr: vec![],
expect_output: vec![],
}
}
}
Expand Down Expand Up @@ -190,11 +188,11 @@ impl Assert {
/// .unwrap();
/// ```
pub fn prints<O: Into<String>>(mut self, output: O) -> Self {
self.expect_stdout.push(OutputAssertion {
self.expect_output.push(OutputAssertion {
expect: output.into(),
fuzzy: true,
expected_result: true,
kind: StdOut,
kind: OutputKind::StdOut,
});
self
}
Expand All @@ -211,11 +209,11 @@ impl Assert {
/// .unwrap();
/// ```
pub fn prints_exactly<O: Into<String>>(mut self, output: O) -> Self {
self.expect_stdout.push(OutputAssertion {
self.expect_output.push(OutputAssertion {
expect: output.into(),
fuzzy: false,
expected_result: true,
kind: StdOut,
kind: OutputKind::StdOut,
});
self
}
Expand All @@ -234,11 +232,11 @@ impl Assert {
/// .unwrap();
/// ```
pub fn prints_error<O: Into<String>>(mut self, output: O) -> Self {
self.expect_stderr.push(OutputAssertion {
self.expect_output.push(OutputAssertion {
expect: output.into(),
fuzzy: true,
expected_result: true,
kind: StdErr,
kind: OutputKind::StdErr,
});
self
}
Expand All @@ -257,11 +255,11 @@ impl Assert {
/// .unwrap();
/// ```
pub fn prints_error_exactly<O: Into<String>>(mut self, output: O) -> Self {
self.expect_stderr.push(OutputAssertion {
self.expect_output.push(OutputAssertion {
expect: output.into(),
fuzzy: false,
expected_result: true,
kind: StdErr,
kind: OutputKind::StdErr,
});
self
}
Expand All @@ -279,11 +277,11 @@ impl Assert {
/// .unwrap();
/// ```
pub fn doesnt_print<O: Into<String>>(mut self, output: O) -> Self {
self.expect_stdout.push(OutputAssertion {
self.expect_output.push(OutputAssertion {
expect: output.into(),
fuzzy: true,
expected_result: false,
kind: StdOut,
kind: OutputKind::StdOut,
});
self
}
Expand All @@ -301,11 +299,11 @@ impl Assert {
/// .unwrap();
/// ```
pub fn doesnt_print_exactly<O: Into<String>>(mut self, output: O) -> Self {
self.expect_stdout.push(OutputAssertion {
self.expect_output.push(OutputAssertion {
expect: output.into(),
fuzzy: false,
expected_result: false,
kind: StdOut,
kind: OutputKind::StdOut,
});
self
}
Expand All @@ -325,11 +323,11 @@ impl Assert {
/// .unwrap();
/// ```
pub fn doesnt_print_error<O: Into<String>>(mut self, output: O) -> Self {
self.expect_stderr.push(OutputAssertion {
self.expect_output.push(OutputAssertion {
expect: output.into(),
fuzzy: true,
expected_result: false,
kind: StdErr,
kind: OutputKind::StdErr,
});
self
}
Expand All @@ -349,11 +347,11 @@ impl Assert {
/// .unwrap();
/// ```
pub fn doesnt_print_error_exactly<O: Into<String>>(mut self, output: O) -> Self {
self.expect_stderr.push(OutputAssertion {
self.expect_output.push(OutputAssertion {
expect: output.into(),
fuzzy: false,
expected_result: false,
kind: StdErr,
kind: OutputKind::StdErr,
});
self
}
Expand Down Expand Up @@ -399,13 +397,9 @@ impl Assert {
));
}

self.expect_stdout
self.expect_output
.iter()
.map(|a| a.execute(&output).map_err(|e| ErrorKind::StdoutMismatch(self.cmd.clone(), e).into()))
.collect::<Result<Vec<()>>>()?;
self.expect_stderr
.iter()
.map(|a| a.execute(&output).map_err(|e| ErrorKind::StderrMismatch(self.cmd.clone(), e).into()))
.map(|a| a.execute(&output, &self.cmd))
.collect::<Result<Vec<()>>>()?;

Ok(())
Expand Down
57 changes: 21 additions & 36 deletions src/output.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use std::fmt;
use std::process::Output;

use difference::Changeset;
Expand All @@ -8,14 +7,14 @@ pub use self::errors::{Error, ErrorKind};
use diff;

#[derive(Debug, Clone)]
pub struct OutputAssertion<T> {
pub struct OutputAssertion {
pub expect: String,
pub fuzzy: bool,
pub expected_result: bool,
pub kind: T,
pub kind: OutputKind,
}

impl<T: OutputType> OutputAssertion<T> {
impl OutputAssertion {
fn matches_fuzzy(&self, got: &str) -> Result<()> {
let result = got.contains(&self.expect);
if result != self.expected_result {
Expand Down Expand Up @@ -45,51 +44,37 @@ impl<T: OutputType> OutputAssertion<T> {
Ok(())
}

pub fn execute(&self, output: &Output) -> Result<()> {
pub fn execute(&self, output: &Output, cmd: &[String]) -> super::errors::Result<()> {
let observed = String::from_utf8_lossy(self.kind.select(output));

if self.fuzzy {
let result = if self.fuzzy {
self.matches_fuzzy(&observed)
} else {
self.matches_exact(&observed)
}
};
result.map_err(|e| self.kind.map_err(e, cmd))
}
}


pub trait OutputType: fmt::Display {
fn select<'a>(&self, o: &'a Output) -> &'a [u8];
}


#[derive(Debug, Clone, Copy)]
pub struct StdOut;

impl fmt::Display for StdOut {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "stdout")
}
}

impl OutputType for StdOut {
fn select<'a>(&self, o: &'a Output) -> &'a [u8] {
&o.stdout
}
pub enum OutputKind {
StdOut,
StdErr,
}


#[derive(Debug, Clone, Copy)]
pub struct StdErr;

impl fmt::Display for StdErr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "stderr")
impl OutputKind {
pub fn select<'a>(self, o: &'a Output) -> &'a [u8] {
match self {
OutputKind::StdOut => &o.stdout,
OutputKind::StdErr => &o.stderr,
}
}
}

impl OutputType for StdErr {
fn select<'a>(&self, o: &'a Output) -> &'a [u8] {
&o.stderr
pub fn map_err(self, e: Error, cmd: &[String]) -> super::errors::Error {
match self {
OutputKind::StdOut => super::errors::ErrorKind::StdoutMismatch(cmd.to_vec(), e).into(),
OutputKind::StdErr => super::errors::ErrorKind::StderrMismatch(cmd.to_vec(), e).into(),
}
}
}

Expand Down

0 comments on commit c25b46b

Please sign in to comment.