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

Commit b386d23

Browse files
committed
Refactor output assertions
1 parent 434303a commit b386d23

File tree

2 files changed

+107
-79
lines changed

2 files changed

+107
-79
lines changed

src/lib.rs

Lines changed: 16 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -108,17 +108,17 @@ extern crate difference;
108108
#[macro_use] extern crate error_chain;
109109
extern crate rustc_serialize;
110110

111-
use std::process::{Command, Output};
112-
use std::fmt;
113-
114-
use difference::Changeset;
111+
use std::process::Command;
115112

116113
mod errors;
117114
use errors::*;
118115

119116
#[macro_use] mod macros;
120117
pub use macros::flatten_escaped_string;
121118

119+
mod output;
120+
use output::{OutputAssertion, StdErr, StdOut};
121+
122122
mod diff;
123123

124124
/// Assertions for a specific command.
@@ -127,38 +127,8 @@ pub struct Assert {
127127
cmd: Vec<String>,
128128
expect_success: Option<bool>,
129129
expect_exit_code: Option<i32>,
130-
expect_stdout: Option<OutputAssertion>,
131-
expect_stderr: Option<OutputAssertion>,
132-
}
133-
134-
#[derive(Debug)]
135-
struct OutputAssertion {
136-
expect: String,
137-
fuzzy: bool,
138-
}
139-
140-
#[derive(Debug, Copy, Clone)]
141-
enum OutputType {
142-
StdOut,
143-
StdErr,
144-
}
145-
146-
impl OutputType {
147-
fn select<'a>(&self, o: &'a Output) -> &'a [u8] {
148-
match *self {
149-
OutputType::StdOut => &o.stdout,
150-
OutputType::StdErr => &o.stderr,
151-
}
152-
}
153-
}
154-
155-
impl fmt::Display for OutputType {
156-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
157-
match *self {
158-
OutputType::StdOut => write!(f, "stdout"),
159-
OutputType::StdErr => write!(f, "stderr"),
160-
}
161-
}
130+
expect_stdout: Option<OutputAssertion<StdOut>>,
131+
expect_stderr: Option<OutputAssertion<StdErr>>,
162132
}
163133

164134
impl std::default::Default for Assert {
@@ -318,6 +288,7 @@ impl Assert {
318288
self.expect_stdout = Some(OutputAssertion {
319289
expect: output.into(),
320290
fuzzy: true,
291+
kind: StdOut,
321292
});
322293
self
323294
}
@@ -337,6 +308,7 @@ impl Assert {
337308
self.expect_stdout = Some(OutputAssertion {
338309
expect: output.into(),
339310
fuzzy: false,
311+
kind: StdOut,
340312
});
341313
self
342314
}
@@ -358,6 +330,7 @@ impl Assert {
358330
self.expect_stderr = Some(OutputAssertion {
359331
expect: output.into(),
360332
fuzzy: true,
333+
kind: StdErr,
361334
});
362335
self
363336
}
@@ -379,6 +352,7 @@ impl Assert {
379352
self.expect_stderr = Some(OutputAssertion {
380353
expect: output.into(),
381354
fuzzy: false,
355+
kind: StdErr,
382356
});
383357
self
384358
}
@@ -421,52 +395,15 @@ impl Assert {
421395
));
422396
}
423397

424-
self.assert_output(OutputType::StdOut, &output)?;
425-
self.assert_output(OutputType::StdErr, &output)?;
426-
427-
Ok(())
428-
}
429-
430-
/// Perform the appropriate output assertion.
431-
fn assert_output(&self, output_type: OutputType, output: &Output) -> Result<()> {
432-
let observed = String::from_utf8_lossy(output_type.select(output));
433-
match *self.expect_output(output_type) {
434-
Some(OutputAssertion {
435-
expect: ref expected_output,
436-
fuzzy: true,
437-
}) if !observed.contains(expected_output) => {
438-
bail!(ErrorKind::OutputMismatch(
439-
output_type.to_string(),
440-
self.cmd.clone(),
441-
expected_output.clone(),
442-
observed.into(),
443-
));
444-
},
445-
Some(OutputAssertion {
446-
expect: ref expected_output,
447-
fuzzy: false,
448-
}) => {
449-
let differences = Changeset::new(expected_output.trim(), observed.trim(), "\n");
450-
if differences.distance > 0 {
451-
let nice_diff = diff::render(&differences)?;
452-
bail!(ErrorKind::ExactOutputMismatch(
453-
output_type.to_string(),
454-
self.cmd.clone(),
455-
nice_diff
456-
));
457-
}
458-
},
459-
_ => {},
398+
if let Some(ouput_assertion) = self.expect_stdout {
399+
ouput_assertion.execute(&output)?;
460400
}
461-
Ok(())
462-
}
463401

464-
/// Return a reference to the appropriate output assertion.
465-
fn expect_output(&self, output_type: OutputType) -> &Option<OutputAssertion> {
466-
match output_type {
467-
OutputType::StdOut => &self.expect_stdout,
468-
OutputType::StdErr => &self.expect_stderr,
402+
if let Some(ouput_assertion) = self.expect_stderr {
403+
ouput_assertion.execute(&output)?;
469404
}
405+
406+
Ok(())
470407
}
471408

472409
/// Execute the command, check the assertions, and panic when they fail.

src/output.rs

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
use std::fmt;
2+
use std::process::Output;
3+
4+
use difference::Changeset;
5+
6+
use errors::*;
7+
use diff;
8+
9+
#[derive(Debug, Clone)]
10+
pub struct OutputAssertion<T> {
11+
pub expect: String,
12+
pub fuzzy: bool,
13+
pub kind: T,
14+
}
15+
16+
impl<T: OutputType> OutputAssertion<T> {
17+
fn matches_fuzzy(&self, got: &str) -> Result<()> {
18+
if !got.contains(&self.expect) {
19+
bail!(ErrorKind::OutputMismatch(
20+
self.kind.to_string(),
21+
vec!["Foo".to_string()],
22+
self.expect.clone(),
23+
got.into(),
24+
));
25+
}
26+
27+
Ok(())
28+
}
29+
30+
fn matches_exact(&self, got: &str) -> Result<()> {
31+
let differences = Changeset::new(self.expect.trim(), got.trim(), "\n");
32+
33+
if differences.distance > 0 {
34+
let nice_diff = diff::render(&differences)?;
35+
bail!(ErrorKind::ExactOutputMismatch(
36+
self.kind.to_string(),
37+
vec!["Foo".to_string()],
38+
nice_diff
39+
));
40+
}
41+
42+
Ok(())
43+
}
44+
45+
pub fn execute(&self, output: &Output) -> Result<()> {
46+
let observed = String::from_utf8_lossy(self.kind.select(output));
47+
48+
if self.fuzzy {
49+
self.matches_fuzzy(&observed)
50+
} else {
51+
self.matches_exact(&observed)
52+
}
53+
}
54+
}
55+
56+
57+
pub trait OutputType: fmt::Display {
58+
fn select<'a>(&self, o: &'a Output) -> &'a [u8];
59+
}
60+
61+
62+
#[derive(Debug, Clone, Copy)]
63+
pub struct StdOut;
64+
65+
impl fmt::Display for StdOut {
66+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
67+
write!(f, "stdout")
68+
}
69+
}
70+
71+
impl OutputType for StdOut {
72+
fn select<'a>(&self, o: &'a Output) -> &'a [u8] {
73+
&o.stdout
74+
}
75+
}
76+
77+
78+
#[derive(Debug, Clone, Copy)]
79+
pub struct StdErr;
80+
81+
impl fmt::Display for StdErr {
82+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
83+
write!(f, "stderr")
84+
}
85+
}
86+
87+
impl OutputType for StdErr {
88+
fn select<'a>(&self, o: &'a Output) -> &'a [u8] {
89+
&o.stderr
90+
}
91+
}

0 commit comments

Comments
 (0)