use errors::{Error, ErrorKind, FromError};
use mutator::Mutator;
use std::mem::replace;
pub trait LazyMatcher: Sized {
type Ret;
fn test(self) -> Result<Self::Ret, Error>;
}
pub struct SimpleMatcher<Ret> {
result: Result<Ret, Error>,
}
pub type SimpleAssert<Ret> = LazyAssertion<SimpleMatcher<Ret>>;
fn matched<Ret>(result: Result<Ret, Error>) -> SimpleAssert<Ret> {
SimpleMatcher { result: result }.into()
}
impl<Ret> From<Ret> for LazyAssertion<SimpleMatcher<Ret>> {
fn from(ret: Ret) -> Self {
matched(Ok(ret))
}
}
impl<Ret> FromError for LazyAssertion<SimpleMatcher<Ret>> {
fn from_err(err: ErrorKind, got: String) -> Self {
matched(Err(Error {
got: got,
kind: err,
}))
.into()
}
}
impl<Ret> LazyMatcher for SimpleMatcher<Ret> {
type Ret = Ret;
fn test(self) -> Result<Self::Ret, Error> {
self.result
}
}
pub struct LazyAssertion<M: LazyMatcher> {
matcher: Option<M>,
}
impl<M: LazyMatcher> Mutator<M> for LazyAssertion<M> {
fn mutate<F>(mut self, op: F) -> Self
where F: FnOnce(&mut M)
{
match self.matcher {
Some(ref mut matcher) => op(matcher),
None => panic!("must: cannot call chaining method after assertion"),
}
self
}
}
impl<M: LazyMatcher> Drop for LazyAssertion<M> {
fn drop(&mut self) {
match replace(&mut self.matcher, None) {
None => {
trace!("Assertion.drop() called, but test is already done");
return;
}
Some(matcher) => {
trace!("running matcher.test() on drop");
match matcher.test() {
Ok(..) => return,
Err(err) => panic!("{}", err),
}
}
}
}
}
impl<M: LazyMatcher> From<M> for LazyAssertion<M> {
fn from(matcher: M) -> Self {
LazyAssertion { matcher: Some(matcher) }
}
}
impl<M: LazyMatcher> LazyAssertion<M> {
pub fn and<F, R>(self, op: F) -> LazyAssertion<R>
where F: FnOnce(M::Ret) -> LazyAssertion<R>,
R: LazyMatcher
{
trace!("Assertion.and() is called");
match self.into_result() {
Ok(val) => op(val).into(),
Err(err) => panic!("{}", err),
}
}
pub fn or<F>(self, f: F)
where F: FnOnce(&Error)
{
trace!("Assertion.or() is called");
match self.into_result() {
Ok(..) => return,
Err(err) => {
f(&err);
panic!("User provided function did not panicked.\n {}", err)
}
}
}
pub fn take(self) -> M::Ret {
trace!("Assertion.take() is called");
match self.into_result() {
Ok(val) => val,
Err(err) => panic!("{}", err),
}
}
pub fn into_result(mut self) -> Result<M::Ret, Error> {
match replace(&mut self.matcher, None) {
Some(matcher) => matcher.test(),
None => panic!("must: Called into_result() twice (how did you do that?)"),
}
}
}