From b2666d700c71f1e459b8322b3be2b64470eb0d3e Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Wed, 22 May 2019 18:00:21 +1000 Subject: [PATCH] Implemented detailed state eqs in ef_tests --- eth2/types/src/beacon_state.rs | 17 ++++++- tests/ef_tests/Cargo.toml | 1 + tests/ef_tests/src/case_result.rs | 51 +++++++++++++++++++ .../ef_tests/src/cases/operations_deposit.rs | 8 +-- 4 files changed, 73 insertions(+), 4 deletions(-) diff --git a/eth2/types/src/beacon_state.rs b/eth2/types/src/beacon_state.rs index a9e6c648eb..00b756c1a0 100644 --- a/eth2/types/src/beacon_state.rs +++ b/eth2/types/src/beacon_state.rs @@ -762,6 +762,16 @@ impl BeaconState { Ok(()) } + /// Drop all caches on the state. + pub fn drop_all_caches(&mut self) { + self.drop_committee_cache(RelativeEpoch::Previous); + self.drop_committee_cache(RelativeEpoch::Current); + self.drop_committee_cache(RelativeEpoch::Next); + self.drop_pubkey_cache(); + self.drop_tree_hash_cache(); + self.exit_cache = ExitCache::default(); + } + /// Build an epoch cache, unless it is has already been built. pub fn build_committee_cache( &mut self, @@ -824,7 +834,7 @@ impl BeaconState { } /// Drops the cache, leaving it in an uninitialized state. - fn drop_cache(&mut self, relative_epoch: RelativeEpoch) { + fn drop_committee_cache(&mut self, relative_epoch: RelativeEpoch) { self.committee_caches[Self::cache_index(relative_epoch)] = CommitteeCache::default(); } @@ -887,6 +897,11 @@ impl BeaconState { .and_then(|b| Ok(Hash256::from_slice(b))) .map_err(Into::into) } + + /// Completely drops the tree hash cache, replacing it with a new, empty cache. + pub fn drop_tree_hash_cache(&mut self) { + self.tree_hash_cache = TreeHashCache::default() + } } impl From for Error { diff --git a/tests/ef_tests/Cargo.toml b/tests/ef_tests/Cargo.toml index 10a0cc7b65..fdba1bcb39 100644 --- a/tests/ef_tests/Cargo.toml +++ b/tests/ef_tests/Cargo.toml @@ -9,6 +9,7 @@ fake_crypto = ["bls/fake_crypto"] [dependencies] bls = { path = "../../eth2/utils/bls" } +compare_fields = { path = "../../eth2/utils/compare_fields" } ethereum-types = "0.5" hex = "0.3" rayon = "1.0" diff --git a/tests/ef_tests/src/case_result.rs b/tests/ef_tests/src/case_result.rs index 2bf9813c60..b58cb7702c 100644 --- a/tests/ef_tests/src/case_result.rs +++ b/tests/ef_tests/src/case_result.rs @@ -1,5 +1,7 @@ use super::*; +use compare_fields::CompareFields; use std::fmt::Debug; +use types::BeaconState; pub const MAX_VALUE_STRING_LEN: usize = 500; @@ -20,6 +22,55 @@ impl CaseResult { } } +/// Same as `compare_result_detailed`, however it drops the caches on both states before +/// comparison. +pub fn compare_beacon_state_results_without_caches( + result: &mut Result, E>, + expected: &mut Option>, +) -> 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( + result: &Result, + expected: &Option, +) -> Result<(), Error> +where + T: PartialEq + Debug + CompareFields, + E: Debug, +{ + match (result, expected) { + (Ok(result), Some(expected)) => { + let mismatching_fields: Vec = expected + .compare_fields(result) + .into_iter() + .filter(|c| !c.equal) + .map(|c| c.field_name) + .collect(); + + if !mismatching_fields.is_empty() { + Err(Error::NotEqual(format!( + "Result mismatch. Fields not equal: {:?}", + mismatching_fields + ))) + } else { + Ok(()) + } + } + _ => compare_result(result, expected), + } +} + /// Compares `result` with `expected`. /// /// If `expected.is_none()` then `result` is expected to be `Err`. Otherwise, `T` in `result` and diff --git a/tests/ef_tests/src/cases/operations_deposit.rs b/tests/ef_tests/src/cases/operations_deposit.rs index fb2364961d..6645e28c83 100644 --- a/tests/ef_tests/src/cases/operations_deposit.rs +++ b/tests/ef_tests/src/cases/operations_deposit.rs @@ -1,5 +1,5 @@ use super::*; -use crate::case_result::compare_result; +use crate::case_result::compare_beacon_state_results_without_caches; use serde_derive::Deserialize; use state_processing::per_block_processing::process_deposits; use types::{BeaconState, Deposit, EthSpec}; @@ -24,9 +24,11 @@ impl Case for OperationsDeposit { fn result(&self) -> Result<(), Error> { let mut state = self.pre.clone(); let deposit = self.deposit.clone(); + let mut expected = self.post.clone(); - let result = process_deposits(&mut state, &[deposit], &E::spec()).and_then(|_| Ok(state)); + let mut result = + process_deposits(&mut state, &[deposit], &E::spec()).and_then(|_| Ok(state)); - compare_result(&result, &self.post) + compare_beacon_state_results_without_caches(&mut result, &mut expected) } }