From 523caf52d68db66963fd2b1dcf98b677a0e18edb Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 14 May 2019 15:08:42 +1000 Subject: [PATCH] Allow for decode ssz_static tests --- tests/ef_tests/Cargo.toml | 1 + tests/ef_tests/src/lib.rs | 2 + tests/ef_tests/src/test_decode.rs | 2 +- tests/ef_tests/src/test_doc.rs | 34 ++++++++---- tests/ef_tests/src/test_doc_cases.rs | 26 ++++++++- .../src/test_doc_cases/ssz_generic.rs | 6 +++ .../ef_tests/src/test_doc_cases/ssz_static.rs | 54 +++++++++++++------ tests/ef_tests/src/yaml_utils.rs | 23 ++++++++ tests/ef_tests/tests/tests.rs | 17 ++++++ 9 files changed, 137 insertions(+), 28 deletions(-) create mode 100644 tests/ef_tests/src/yaml_utils.rs diff --git a/tests/ef_tests/Cargo.toml b/tests/ef_tests/Cargo.toml index 638b0ecfd8..5535f19561 100644 --- a/tests/ef_tests/Cargo.toml +++ b/tests/ef_tests/Cargo.toml @@ -12,3 +12,4 @@ serde_derive = "1.0" serde_yaml = "0.8" ssz = { path = "../../eth2/utils/ssz" } types = { path = "../../eth2/types" } +yaml-rust = "0.4" diff --git a/tests/ef_tests/src/lib.rs b/tests/ef_tests/src/lib.rs index 4eb06dd9a0..56aaaec92a 100644 --- a/tests/ef_tests/src/lib.rs +++ b/tests/ef_tests/src/lib.rs @@ -10,6 +10,7 @@ pub use crate::test_case_result::*; pub use crate::test_doc::*; pub use crate::test_doc_cases::*; pub use crate::test_doc_header::*; +pub use crate::yaml_utils::*; mod error; mod test_case_result; @@ -17,3 +18,4 @@ mod test_decode; mod test_doc; mod test_doc_cases; mod test_doc_header; +mod yaml_utils; diff --git a/tests/ef_tests/src/test_decode.rs b/tests/ef_tests/src/test_decode.rs index 6003968fc0..4ba25c1a8f 100644 --- a/tests/ef_tests/src/test_decode.rs +++ b/tests/ef_tests/src/test_decode.rs @@ -24,7 +24,7 @@ impl_via_parse!(u16); impl_via_parse!(u32); impl_via_parse!(u64); -/// Some `ethereum-types` methods have a `str::FromStr` implementation that expects `0x`-prefixed +/// Some `ethereum-types` methods have a `str::FromStr` implementation that expects `0x`-prefixed: /// hex, so we use `from_dec_str` instead. macro_rules! impl_via_from_dec_str { ($ty: ty) => { diff --git a/tests/ef_tests/src/test_doc.rs b/tests/ef_tests/src/test_doc.rs index 7417fc280e..46769d29b9 100644 --- a/tests/ef_tests/src/test_doc.rs +++ b/tests/ef_tests/src/test_doc.rs @@ -7,7 +7,7 @@ pub struct TestDoc { } impl TestDoc { - fn new(path: PathBuf) -> Self { + fn from_path(path: PathBuf) -> Self { let mut file = File::open(path).unwrap(); let mut yaml = String::new(); @@ -17,15 +17,20 @@ impl TestDoc { } pub fn get_test_results(path: PathBuf) -> Vec { - let doc = Self::new(path); + let doc = Self::from_path(path); let header: TestDocHeader = serde_yaml::from_str(&doc.yaml.as_str()).unwrap(); - match (header.runner.as_ref(), header.handler.as_ref()) { - ("ssz", "uint") => run_test::(&doc.yaml), - (runner, handler) => panic!( - "No implementation for runner {} handler {}", - runner, handler + match ( + header.runner.as_ref(), + header.handler.as_ref(), + header.config.as_ref(), + ) { + ("ssz", "uint", _) => run_test::(&doc.yaml), + ("ssz", "static", "minimal") => run_test::(&doc.yaml), + (runner, handler, config) => panic!( + "No implementation for runner: \"{}\", handler: \"{}\", config: \"{}\"", + runner, handler, config ), } } @@ -36,16 +41,23 @@ impl TestDoc { let failures: Vec<&TestCaseResult> = results.iter().filter(|r| r.result.is_err()).collect(); if !failures.is_empty() { - panic!("{:?}", failures); + for f in failures { + dbg!(&f.case_index); + dbg!(&f.result); + } + panic!() } } } pub fn run_test(test_doc_yaml: &String) -> Vec where - TestDocCases: Test + serde::de::DeserializeOwned, + TestDocCases: Test + serde::de::DeserializeOwned + TestDecode, { - let doc: TestDocCases = serde_yaml::from_str(&test_doc_yaml.as_str()).unwrap(); + let test_cases_yaml = extract_yaml_by_key(test_doc_yaml, "test_cases"); - doc.test() + let test_cases: TestDocCases = + TestDocCases::test_decode(&test_cases_yaml.to_string()).unwrap(); + + test_cases.test() } diff --git a/tests/ef_tests/src/test_doc_cases.rs b/tests/ef_tests/src/test_doc_cases.rs index b466689256..45c24146cd 100644 --- a/tests/ef_tests/src/test_doc_cases.rs +++ b/tests/ef_tests/src/test_doc_cases.rs @@ -1,11 +1,35 @@ use super::*; +use yaml_rust::YamlLoader; mod ssz_generic; -// mod ssz_static; +mod ssz_static; pub use ssz_generic::*; +pub use ssz_static::*; #[derive(Debug, Deserialize)] pub struct TestDocCases { pub test_cases: Vec, } + +impl TestDecode for TestDocCases { + /// Decodes a YAML list of test cases + fn test_decode(yaml: &String) -> Result { + let doc = &YamlLoader::load_from_str(yaml).unwrap()[0]; + + let mut test_cases: Vec = vec![]; + + let mut i = 0; + loop { + if doc[i].is_badvalue() { + break; + } else { + test_cases.push(T::test_decode(&yaml_to_string(&doc[i])).unwrap()) + } + + i += 1; + } + + Ok(Self { test_cases }) + } +} diff --git a/tests/ef_tests/src/test_doc_cases/ssz_generic.rs b/tests/ef_tests/src/test_doc_cases/ssz_generic.rs index d2bccbdd58..da932df53f 100644 --- a/tests/ef_tests/src/test_doc_cases/ssz_generic.rs +++ b/tests/ef_tests/src/test_doc_cases/ssz_generic.rs @@ -9,6 +9,12 @@ pub struct SszGeneric { pub ssz: Option, } +impl TestDecode for SszGeneric { + fn test_decode(yaml: &String) -> Result { + Ok(serde_yaml::from_str(&yaml.as_str()).unwrap()) + } +} + impl Test for TestDocCases { fn test(&self) -> Vec { self.test_cases diff --git a/tests/ef_tests/src/test_doc_cases/ssz_static.rs b/tests/ef_tests/src/test_doc_cases/ssz_static.rs index 6c0d3f9e1d..8367f4c8ec 100644 --- a/tests/ef_tests/src/test_doc_cases/ssz_static.rs +++ b/tests/ef_tests/src/test_doc_cases/ssz_static.rs @@ -1,49 +1,73 @@ use super::*; +use serde::de::{Deserialize, Deserializer}; use types::Fork; #[derive(Debug, Clone, Deserialize)] pub struct SszStatic { pub type_name: String, - pub value: String, pub serialized: String, pub root: String, + #[serde(skip)] + pub raw_yaml: String, } -impl Test for TestDoc { - fn test(&self) -> Vec> { +#[derive(Debug, Clone, Deserialize)] +pub struct Value { + value: T, +} + +impl TestDecode for SszStatic { + fn test_decode(yaml: &String) -> Result { + let mut ssz_static: SszStatic = serde_yaml::from_str(&yaml.as_str()).unwrap(); + + ssz_static.raw_yaml = yaml.clone(); + + Ok(ssz_static) + } +} + +impl SszStatic { + fn value(&self) -> Result { + serde_yaml::from_str(&self.raw_yaml.as_str()).map_err(|e| { + Error::FailedToParseTest(format!("Unable to parse {} YAML: {:?}", self.type_name, e)) + }) + } +} + +impl Test for TestDocCases { + fn test(&self) -> Vec { self.test_cases .iter() .enumerate() .map(|(i, tc)| { let result = match tc.type_name.as_ref() { - "Fork" => ssz_static_test::(&tc.value, &tc.serialized, &tc.root), + "Fork" => ssz_static_test::(tc), _ => Err(Error::FailedToParseTest(format!( "Unknown type: {}", tc.type_name ))), }; - TestCaseResult { - case_index: i, - case: tc.clone(), - result, - } + TestCaseResult::new(i, tc, result) }) .collect() } } -/// Execute a `ssz_generic` test case. -fn ssz_static_test(value: &String, serialized: &String, root: &String) -> Result<(), Error> +fn ssz_static_test(tc: &SszStatic) -> Result<(), Error> where - T: Decode + TestDecode + Debug + PartialEq, + T: Decode + TestDecode + Debug + PartialEq + serde::de::DeserializeOwned, { - let ssz = - hex::decode(&serialized[2..]).map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?; + let ssz = hex::decode(&tc.serialized[2..]) + .map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?; - let expected = T::test_decode(value)?; + let expected = tc.value::()?; + Ok(()) + + /* let decoded = T::from_ssz_bytes(&ssz); compare_result(decoded, Some(expected)) + */ } diff --git a/tests/ef_tests/src/yaml_utils.rs b/tests/ef_tests/src/yaml_utils.rs new file mode 100644 index 0000000000..2e379a2779 --- /dev/null +++ b/tests/ef_tests/src/yaml_utils.rs @@ -0,0 +1,23 @@ +use yaml_rust::{Yaml, YamlEmitter, YamlLoader}; + +pub fn extract_yaml_by_key(yaml: &str, key: &str) -> String { + let doc = &YamlLoader::load_from_str(yaml).unwrap()[0]; + let subsection = &doc[key]; + + yaml_to_string(subsection) +} + +pub fn extract_yaml_by_index(yaml: &str, index: usize) -> String { + let doc = &YamlLoader::load_from_str(yaml).unwrap()[0]; + let subsection = &doc[index]; + + yaml_to_string(subsection) +} + +pub fn yaml_to_string(yaml: &Yaml) -> String { + let mut out_str = String::new(); + let mut emitter = YamlEmitter::new(&mut out_str); + emitter.dump(yaml).unwrap(); + + out_str +} diff --git a/tests/ef_tests/tests/tests.rs b/tests/ef_tests/tests/tests.rs index dd7e7d9d10..70966dc901 100644 --- a/tests/ef_tests/tests/tests.rs +++ b/tests/ef_tests/tests/tests.rs @@ -34,3 +34,20 @@ mod ssz_generic { TestDoc::assert_tests_pass(ssz_generic_file("uint/uint_wrong_length.yaml")); } } + +mod ssz_static { + use super::*; + + fn ssz_generic_file(file: &str) -> PathBuf { + let mut path = test_file("ssz_static"); + path.push(file); + dbg!(&path); + + path + } + + #[test] + fn minimal_nil() { + TestDoc::assert_tests_pass(ssz_generic_file("core/ssz_minimal_nil.yaml")); + } +}