Improve ef_tests, pass all ssz_static tests

This commit is contained in:
Paul Hauner 2019-05-15 15:08:48 +10:00
parent 0af4cfa711
commit 4aa6d57abe
No known key found for this signature in database
GPG Key ID: 5E2CFF9B75FA63DF
5 changed files with 67 additions and 54 deletions

View File

@ -11,10 +11,13 @@ fake_crypto = ["bls/fake_crypto"]
bls = { path = "../../eth2/utils/bls" } bls = { path = "../../eth2/utils/bls" }
ethereum-types = "0.5" ethereum-types = "0.5"
hex = "0.3" hex = "0.3"
rayon = "1.0"
serde = "1.0" serde = "1.0"
serde_derive = "1.0" serde_derive = "1.0"
serde_yaml = "0.8" serde_yaml = "0.8"
ssz = { path = "../../eth2/utils/ssz" } ssz = { path = "../../eth2/utils/ssz" }
tree_hash = { path = "../../eth2/utils/tree_hash" } tree_hash = { path = "../../eth2/utils/tree_hash" }
cached_tree_hash = { path = "../../eth2/utils/cached_tree_hash" }
types = { path = "../../eth2/types" } types = { path = "../../eth2/types" }
walkdir = "2"
yaml-rust = { git = "https://github.com/sigp/yaml-rust", branch = "escape_all_str"} yaml-rust = { git = "https://github.com/sigp/yaml-rust", branch = "escape_all_str"}

View File

@ -1,5 +1,7 @@
use super::*; use super::*;
use crate::case_result::compare_result; use crate::case_result::compare_result;
use cached_tree_hash::{CachedTreeHash, TreeHashCache};
use rayon::prelude::*;
use serde_derive::Deserialize; use serde_derive::Deserialize;
use ssz::Decode; use ssz::Decode;
use std::fmt::Debug; use std::fmt::Debug;
@ -48,7 +50,7 @@ impl SszStatic {
impl EfTest for Cases<SszStatic> { impl EfTest for Cases<SszStatic> {
fn test_results<E: EthSpec>(&self) -> Vec<CaseResult> { fn test_results<E: EthSpec>(&self) -> Vec<CaseResult> {
self.test_cases self.test_cases
.iter() .par_iter()
.enumerate() .enumerate()
.map(|(i, tc)| { .map(|(i, tc)| {
let result = match tc.type_name.as_ref() { let result = match tc.type_name.as_ref() {
@ -88,7 +90,7 @@ impl EfTest for Cases<SszStatic> {
fn ssz_static_test<T>(tc: &SszStatic) -> Result<(), Error> fn ssz_static_test<T>(tc: &SszStatic) -> Result<(), Error>
where where
T: Decode + Debug + PartialEq<T> + serde::de::DeserializeOwned + TreeHash, T: Decode + Debug + PartialEq<T> + serde::de::DeserializeOwned + TreeHash + CachedTreeHash,
{ {
// Verify we can decode SSZ in the same way we can decode YAML. // Verify we can decode SSZ in the same way we can decode YAML.
let ssz = hex::decode(&tc.serialized[2..]) let ssz = hex::decode(&tc.serialized[2..])
@ -97,12 +99,18 @@ where
let decode_result = T::from_ssz_bytes(&ssz); let decode_result = T::from_ssz_bytes(&ssz);
compare_result(&decode_result, &Some(expected))?; compare_result(&decode_result, &Some(expected))?;
// Verify the tree hash root is identical to the decoded struct. // Verify the TreeHash root of the decoded struct matches the test.
let root_bytes = let decoded = decode_result.unwrap();
let expected_root =
&hex::decode(&tc.root[2..]).map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?; &hex::decode(&tc.root[2..]).map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?;
let expected_root = Hash256::from_slice(&root_bytes); let expected_root = Hash256::from_slice(&expected_root);
let root = Hash256::from_slice(&decode_result.unwrap().tree_hash_root()); let tree_hash_root = Hash256::from_slice(&decoded.tree_hash_root());
compare_result::<Hash256, Error>(&Ok(root), &Some(expected_root))?; compare_result::<Hash256, Error>(&Ok(tree_hash_root), &Some(expected_root))?;
// Verify a _new_ CachedTreeHash root of the decoded struct matches the test.
let cache = TreeHashCache::new(&decoded).unwrap();
let cached_tree_hash_root = Hash256::from_slice(cache.tree_hash_root().unwrap());
compare_result::<Hash256, Error>(&Ok(cached_tree_hash_root), &Some(expected_root))?;
Ok(()) Ok(())
} }

View File

@ -1,12 +1,12 @@
use crate::case_result::CaseResult; use crate::case_result::CaseResult;
use crate::cases::*; use crate::cases::*;
use crate::doc_header::DocHeader; use crate::doc_header::DocHeader;
use crate::eth_specs::MinimalEthSpec; use crate::eth_specs::{MainnetEthSpec, MinimalEthSpec};
use crate::yaml_decode::{extract_yaml_by_key, YamlDecode}; use crate::yaml_decode::{extract_yaml_by_key, YamlDecode};
use crate::EfTest; use crate::EfTest;
use serde_derive::Deserialize; use serde_derive::Deserialize;
use std::{fs::File, io::prelude::*, path::PathBuf}; use std::{fs::File, io::prelude::*, path::PathBuf};
use types::{EthSpec, FoundationEthSpec}; use types::EthSpec;
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub struct Doc { pub struct Doc {
@ -32,8 +32,9 @@ impl Doc {
header.handler.as_ref(), header.handler.as_ref(),
header.config.as_ref(), header.config.as_ref(),
) { ) {
("ssz", "uint", _) => run_test::<SszGeneric, FoundationEthSpec>(&self.yaml), ("ssz", "uint", _) => run_test::<SszGeneric, MainnetEthSpec>(&self.yaml),
("ssz", "static", "minimal") => run_test::<SszStatic, MinimalEthSpec>(&self.yaml), ("ssz", "static", "minimal") => run_test::<SszStatic, MinimalEthSpec>(&self.yaml),
("ssz", "static", "mainnet") => run_test::<SszStatic, MainnetEthSpec>(&self.yaml),
(runner, handler, config) => panic!( (runner, handler, config) => panic!(
"No implementation for runner: \"{}\", handler: \"{}\", config: \"{}\"", "No implementation for runner: \"{}\", handler: \"{}\", config: \"{}\"",
runner, handler, config runner, handler, config
@ -48,6 +49,8 @@ impl Doc {
if results.iter().any(|r| r.result.is_err()) { if results.iter().any(|r| r.result.is_err()) {
print_failures(&doc, &results); print_failures(&doc, &results);
panic!("Tests failed (see above)"); panic!("Tests failed (see above)");
} else {
println!("Passed {} tests in {:?}", results.len(), doc.path);
} }
} }
} }

View File

@ -1,5 +1,8 @@
use types::{EthSpec, typenum::{U64, U8}, ChainSpec, FewValidatorsEthSpec}; use serde_derive::{Deserialize, Serialize};
use serde_derive::{Serialize, Deserialize}; use types::{
typenum::{U64, U8},
ChainSpec, EthSpec, FewValidatorsEthSpec, FoundationEthSpec,
};
/// "Minimal" testing specification, as defined here: /// "Minimal" testing specification, as defined here:
/// ///
@ -21,3 +24,5 @@ impl EthSpec for MinimalEthSpec {
FewValidatorsEthSpec::spec() FewValidatorsEthSpec::spec()
} }
} }
pub type MainnetEthSpec = FoundationEthSpec;

View File

@ -1,51 +1,45 @@
use ef_tests::*; use ef_tests::*;
use rayon::prelude::*;
use std::path::PathBuf; use std::path::PathBuf;
use walkdir::WalkDir;
fn test_file(trailing_path: &str) -> PathBuf { fn yaml_files_in_test_dir(dir: &str) -> Vec<PathBuf> {
let mut file_path_buf = PathBuf::from(env!("CARGO_MANIFEST_DIR")); let mut base_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
file_path_buf.push(format!("eth2.0-spec-tests/tests/{}", trailing_path)); base_path.push("eth2.0-spec-tests");
base_path.push("tests");
base_path.push(dir);
file_path_buf WalkDir::new(base_path)
.into_iter()
.filter_map(|e| e.ok())
.filter_map(|entry| {
if entry.file_type().is_file() {
match entry.file_name().to_str() {
Some(f) if f.ends_with(".yaml") => Some(entry.path().to_path_buf()),
Some(f) if f.ends_with(".yml") => Some(entry.path().to_path_buf()),
_ => None,
}
} else {
None
}
})
.collect()
} }
mod ssz_generic { #[test]
use super::*; fn ssz_generic() {
yaml_files_in_test_dir("ssz_generic")
fn ssz_generic_file(file: &str) -> PathBuf { .into_par_iter()
let mut path = test_file("ssz_generic"); .for_each(|file| {
path.push(file); Doc::assert_tests_pass(file);
});
path
}
#[test]
fn uint_bounds() {
Doc::assert_tests_pass(ssz_generic_file("uint/uint_bounds.yaml"));
}
#[test]
fn uint_random() {
Doc::assert_tests_pass(ssz_generic_file("uint/uint_random.yaml"));
}
#[test]
fn uint_wrong_length() {
Doc::assert_tests_pass(ssz_generic_file("uint/uint_wrong_length.yaml"));
}
} }
mod ssz_static { #[test]
use super::*; fn ssz_static() {
yaml_files_in_test_dir("ssz_static")
fn ssz_generic_file(file: &str) -> PathBuf { .into_par_iter()
let mut path = test_file("ssz_static"); .for_each(|file| {
path.push(file); Doc::assert_tests_pass(file);
});
path
}
#[test]
fn minimal_nil() {
Doc::assert_tests_pass(ssz_generic_file("core/ssz_minimal_nil.yaml"));
}
} }