lighthouse/tests/ef_tests/src/case_result.rs

118 lines
3.6 KiB
Rust
Raw Normal View History

2019-05-14 01:13:28 +00:00
use super::*;
use compare_fields::{CompareFields, Comparison, FieldComparison};
2019-05-15 01:41:25 +00:00
use std::fmt::Debug;
use types::BeaconState;
2019-05-14 01:13:28 +00:00
2019-05-22 06:46:50 +00:00
pub const MAX_VALUE_STRING_LEN: usize = 500;
2019-05-14 01:13:28 +00:00
#[derive(Debug, PartialEq, Clone)]
2019-05-15 01:27:22 +00:00
pub struct CaseResult {
2019-05-14 01:13:28 +00:00
pub case_index: usize,
pub desc: String,
pub result: Result<(), Error>,
}
2019-05-15 01:27:22 +00:00
impl CaseResult {
2019-05-23 06:55:50 +00:00
pub fn new(case_index: usize, case: &impl Case, result: Result<(), Error>) -> Self {
2019-05-15 01:27:22 +00:00
CaseResult {
2019-05-14 01:13:28 +00:00
case_index,
2019-05-23 06:55:50 +00:00
desc: case.description(),
2019-05-14 01:13:28 +00:00
result,
}
}
}
/// Same as `compare_result_detailed`, however it drops the caches on both states before
/// comparison.
pub fn compare_beacon_state_results_without_caches<T: EthSpec, E: Debug>(
result: &mut Result<BeaconState<T>, E>,
expected: &mut Option<BeaconState<T>>,
) -> Result<(), Error> {
match (result.as_mut(), expected.as_mut()) {
(Ok(ref mut result), Some(ref mut expected)) => {
result.drop_all_caches();
expected.drop_all_caches();
}
_ => (),
};
compare_result_detailed(&result, &expected)
}
/// Same as `compare_result`, however utilizes the `CompareFields` trait to give a list of
/// mismatching fields when `Ok(result) != Some(expected)`.
pub fn compare_result_detailed<T, E>(
result: &Result<T, E>,
expected: &Option<T>,
) -> Result<(), Error>
where
T: PartialEq<T> + Debug + CompareFields,
E: Debug,
{
match (result, expected) {
(Ok(result), Some(expected)) => {
let mut mismatching_fields: Vec<Comparison> = expected
.compare_fields(result)
.into_iter()
// Filter all out all fields that are equal.
.filter(Comparison::not_equal)
.collect();
mismatching_fields
.iter_mut()
.for_each(|f| f.retain_children(FieldComparison::not_equal));
if !mismatching_fields.is_empty() {
Err(Error::NotEqual(format!(
2019-05-23 06:55:50 +00:00
"Fields not equal (a = expected, b = result): {:#?}",
mismatching_fields
)))
} else {
Ok(())
}
}
_ => compare_result(result, expected),
}
}
2019-05-14 01:13:28 +00:00
/// Compares `result` with `expected`.
///
/// If `expected.is_none()` then `result` is expected to be `Err`. Otherwise, `T` in `result` and
/// `expected` must be equal.
2019-05-14 23:50:05 +00:00
pub fn compare_result<T, E>(result: &Result<T, E>, expected: &Option<T>) -> Result<(), Error>
2019-05-14 01:13:28 +00:00
where
T: PartialEq<T> + Debug,
E: Debug,
{
match (result, expected) {
// Pass: The should have failed and did fail.
(Err(_), None) => Ok(()),
// Fail: The test failed when it should have produced a result (fail).
(Err(e), Some(expected)) => Err(Error::NotEqual(format!(
2019-05-22 06:46:50 +00:00
"Got {:?} | Expected {:?}",
e,
fmt_val(expected)
2019-05-14 01:13:28 +00:00
))),
// Fail: The test produced a result when it should have failed (fail).
2019-05-22 06:46:50 +00:00
(Ok(result), None) => Err(Error::DidntFail(format!("Got {:?}", fmt_val(result)))),
2019-05-14 01:13:28 +00:00
// Potential Pass: The test should have produced a result, and it did.
(Ok(result), Some(expected)) => {
if result == expected {
Ok(())
} else {
Err(Error::NotEqual(format!(
2019-05-22 06:46:50 +00:00
"Got {:?} | Expected {:?}",
fmt_val(result),
fmt_val(expected)
2019-05-14 01:13:28 +00:00
)))
}
}
}
}
2019-05-22 06:46:50 +00:00
fn fmt_val<T: Debug>(val: T) -> String {
let mut string = format!("{:?}", val);
string.truncate(MAX_VALUE_STRING_LEN);
string
}