Skip to content

Commit

Permalink
Improve matcher API
Browse files Browse the repository at this point in the history
  • Loading branch information
carllerche committed Apr 1, 2014
1 parent 4c7d882 commit 634495e
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 82 deletions.
57 changes: 20 additions & 37 deletions src/hamcrest/core.rs
@@ -1,55 +1,38 @@
use std::result::Result;

pub fn assert_that<T: Clone, U: Matcher<T> + SelfDescribing>(actual: &T, matcher: U) {
if !matcher.matches(actual) {
let mut desc = Description::new();

desc
.append_text("\nExpected: ")
.append_description_of(&matcher as &SelfDescribing)
.append_text("\n but: ");
pub type MatchResult = Result<(), ~str>;

matcher.describe_mismatch(actual, &mut desc);

fail!("{}", desc.to_str());
}
pub fn success() -> MatchResult {
Ok(())
}

pub struct Description {
msg: ~str
}

impl Description {
pub fn new() -> Description {
Description { msg: ~"" }
pub fn expect(predicate: bool, msg: ~str) -> MatchResult {
if predicate {
success()
}

pub fn append_text<'r>(&'r mut self, item: &str) -> &'r mut Description {
self.msg = self.msg + item;
self
}

pub fn append_description_of<'r>(&'r mut self, item: &SelfDescribing) -> &'r mut Description {
item.describe_to(self);
self
else {
Err(msg)
}
}

pub fn to_str<'r>(&'r self) -> &'r str {
self.msg.as_slice()
pub fn assert_that<T: Clone, U: Matcher<T> + SelfDescribing>(actual: &T, matcher: U) {
match matcher.matches(actual) {
Ok(_) => return,
Err(mismatch) => {
let expected = matcher.describe();
fail!("\nExpected: {}\n but: {}", expected, mismatch);
}
}
}

pub trait SelfDescribing {

fn describe_to(&self, desc: &mut Description) {
desc.append_text(format!("{:?}", self));
fn describe(&self) -> ~str {
format!("{:?}", self)
}

}

pub trait Matcher<T> : SelfDescribing + Clone {
fn matches(&self, actual: &T) -> bool;

fn describe_mismatch(&self, _: &T, desc: &mut Description) {
desc.append_text(format!("was {:?}", self));
}
fn matches(&self, actual: &T) -> MatchResult;
}
6 changes: 3 additions & 3 deletions src/hamcrest/lib.rs
@@ -1,7 +1,7 @@
#[crate_id = "hamcrest"];
#[crate_type = "lib"];
#![crate_id = "hamcrest"]
#![crate_type = "lib"]

pub use core::{assert_that,Matcher,Description,SelfDescribing};
pub use core::{assert_that,expect,success,Matcher,MatchResult,SelfDescribing};
pub use matchers::is::{is,is_not};
pub use matchers::equal_to::equal_to;
pub use matchers::existing_path::{existing_path,existing_file,existing_dir};
Expand Down
19 changes: 10 additions & 9 deletions src/hamcrest/matchers/equal_to.rs
@@ -1,24 +1,25 @@
use std::fmt::Show;
use core::{Matcher,SelfDescribing,Description};
use {success,Matcher,MatchResult,SelfDescribing};

#[deriving(Clone)]
pub struct EqualTo<T> {
expected: T
}

impl<T : Show> SelfDescribing for EqualTo<T> {
fn describe_to(&self, desc: &mut Description) {
desc.append_text(format!("{}", self.expected));
fn describe(&self) -> ~str {
format!("{}", self.expected)
}
}

impl<T : Eq + Clone + Show> Matcher<T> for EqualTo<T> {
fn matches(&self, actual: &T) -> bool {
self.expected.eq(actual)
}

fn describe_mismatch(&self, actual: &T, desc: &mut Description) {
desc.append_text(format!("was {}", actual));
fn matches(&self, actual: &T) -> MatchResult {
if self.expected.eq(actual) {
success()
}
else {
Err(format!("was {}", actual))
}
}
}

Expand Down
33 changes: 16 additions & 17 deletions src/hamcrest/matchers/existing_path.rs
@@ -1,4 +1,4 @@
use core::{Matcher,SelfDescribing,Description};
use {success,expect,Matcher,MatchResult,SelfDescribing};

#[deriving(Clone,Eq)]
pub enum PathType {
Expand All @@ -12,27 +12,26 @@ pub struct ExistingPath {
path_type: PathType
}

impl SelfDescribing for ExistingPath {
fn describe_to(&self, desc: &mut Description) {
desc.append_text("an existing file");
impl ExistingPath {
fn match_path_type(&self, actual: &Path) -> MatchResult {
match self.path_type {
File => expect(actual.is_file(), format!("`{}` was not a file", actual.display())),
Dir => expect(actual.is_dir(), format!("`{}` was not a dir", actual.display())),
_ => success()
}
}
}

impl Matcher<Path> for ExistingPath {
fn matches(&self, actual: &Path) -> bool {
if !actual.exists() {
return false;
}

match self.path_type {
File => actual.is_file(),
Dir => actual.is_dir(),
AnyType => true
}
impl SelfDescribing for ExistingPath {
fn describe(&self) -> ~str {
~"an existing file"
}
}

fn describe_mismatch(&self, actual: &Path, desc: &mut Description) {
desc.append_text(format!("`{}` was missing", actual.display()));
impl Matcher<Path> for ExistingPath {
fn matches(&self, actual: &Path) -> MatchResult {
expect(actual.exists(), format!("{} was missing", actual.display()))
.and(self.match_path_type(actual))
}
}

Expand Down
27 changes: 11 additions & 16 deletions src/hamcrest/matchers/is.rs
@@ -1,24 +1,20 @@
use super::super::core::{Matcher,SelfDescribing,Description};
use {Matcher,MatchResult,SelfDescribing};

#[deriving(Clone,Eq)]
pub struct Is<T, M> {
matcher: M
}

impl<T, M : Matcher<T>> SelfDescribing for Is<T, M> {
fn describe_to(&self, desc: &mut Description) {
self.matcher.describe_to(desc);
fn describe(&self) -> ~str {
self.matcher.describe()
}
}

impl<T : Clone, M : Matcher<T>> Matcher<T> for Is<T, M> {
fn matches(&self, actual: &T) -> bool {
fn matches(&self, actual: &T) -> MatchResult {
self.matcher.matches(actual)
}

fn describe_mismatch(&self, actual: &T, desc: &mut Description) {
self.matcher.describe_mismatch(actual, desc);
}
}

pub fn is<T, M: Matcher<T>>(matcher: M) -> Is<T, M> {
Expand All @@ -31,18 +27,17 @@ pub struct IsNot<T, M> {
}

impl<T, M : Matcher<T>> SelfDescribing for IsNot<T, M> {
fn describe_to(&self, desc: &mut Description) {
self.matcher.describe_to(desc);
fn describe(&self) -> ~str {
self.matcher.describe()
}
}

impl<T : Clone, M : Matcher<T>> Matcher<T> for IsNot<T, M> {
fn matches(&self, actual: &T) -> bool {
!self.matcher.matches(actual)
}

fn describe_mismatch(&self, actual: &T, desc: &mut Description) {
self.matcher.describe_mismatch(actual, desc);
fn matches(&self, actual: &T) -> MatchResult {
match self.matcher.matches(actual) {
Ok(_) => Err(~"matched"),
Err(_) => Ok(())
}
}
}

Expand Down

0 comments on commit 634495e

Please sign in to comment.