use crate::expectation_list::ExpectationList;
use crate::{CheckResult, Expectation, ExpectationBuilder};
use std::fmt::Debug;
pub struct OwnedExpectations<'e, T: Debug> {
value: Option<T>,
expectations: ExpectationList<'e, T>,
}
impl<'e, T: Debug> OwnedExpectations<'e, T> {
pub fn new(value: T) -> Self {
Self {
expectations: ExpectationList::new(),
value: Some(value),
}
}
pub fn check_result(mut self) -> (T, CheckResult) {
let value = self
.value
.take()
.expect("Check can only be called once, hence value must be Some");
let result = self.expectations.check(&value);
(value, result)
}
pub fn check(self) -> T {
let (value, result) = self.check_result();
if let CheckResult::Fail(message) = result {
panic!("{}", message);
}
value
}
}
impl<'e, T: Debug + 'e> ExpectationBuilder<'e> for OwnedExpectations<'e, T> {
type Value = T;
fn to_pass(mut self, expectation: impl Expectation<T> + 'e) -> Self {
self.expectations.push(expectation);
self
}
}
impl<'e, T: Debug> Drop for OwnedExpectations<'e, T> {
fn drop(&mut self) {
if let Some(value) = self.value.take()
&& let CheckResult::Fail(message) = self.expectations.check(&value)
{
panic!("{}", message);
}
}
}
pub struct RefExpectations<'e, T: Debug> {
value: &'e T,
expectations: ExpectationList<'e, T>,
}
impl<'e, T: Debug> RefExpectations<'e, T> {
pub fn new(value: &'e T) -> Self {
Self {
expectations: ExpectationList::new(),
value,
}
}
pub fn check(self) {
drop(self)
}
}
impl<'e, T: Debug + 'e> ExpectationBuilder<'e> for RefExpectations<'e, T> {
type Value = T;
fn to_pass(mut self, expectation: impl Expectation<T> + 'e) -> Self {
self.expectations.push(expectation);
self
}
}
impl<'e, T: Debug> Drop for RefExpectations<'e, T> {
fn drop(&mut self) {
if let CheckResult::Fail(message) = self.expectations.check(self.value) {
panic!("{}", message);
}
}
}
#[cfg(test)]
mod tests {
use crate::expectations::{BooleanExpectations, PredicateExpectation};
use crate::tests::TestExpectation;
use crate::{CheckResult, ExpectationBuilder, expect, expect_ref};
#[test]
pub fn that_assert_runs_an_expectation() {
let (expectation, expected) = TestExpectation::new(CheckResult::Pass);
let expectations = expect(true).to_pass(expectation);
expectations.check();
assert!(*expected.lock().unwrap());
}
#[test]
pub fn that_check_returns_the_value() {
let value = vec![1, 2, 3];
let returned = expect(value).check();
assert_eq!(returned, vec![1, 2, 3]);
}
#[test]
pub fn that_assert_works_on_references() {
let (expectation, _) = TestExpectation::new(CheckResult::Pass);
let value = true;
expect_ref(&value).to_pass(expectation);
}
#[test]
pub fn that_check_runs_all_expectations() {
let (expectation1, expected1) = TestExpectation::new(CheckResult::Pass);
let (expectation2, expected2) = TestExpectation::new(CheckResult::Pass);
let expectations = expect(true).to_pass(expectation1).to_pass(expectation2);
expectations.check();
assert!(*expected1.lock().unwrap());
assert!(*expected2.lock().unwrap());
}
#[test]
#[should_panic]
pub fn that_failure_panics() {
let (expectation, _) = TestExpectation::new(CheckResult::Fail("message".to_owned()));
let expectations = expect(true).to_pass(expectation);
expectations.check();
}
#[test]
pub fn that_check_result_returns_value_and_result() {
let (expectation, _) = TestExpectation::new(CheckResult::Fail("message".to_owned()));
let expectations = expect(true).to_pass(expectation);
let (value, result) = expectations.check_result();
expect(value).to_be_true();
expect(result).to_pass(PredicateExpectation::new(
(),
|actual, _| matches!(actual, CheckResult::Fail(_)),
|actual, _| format!("Expected CheckResult::Fail, but was {:?}", actual),
));
}
}