Allow for decode ssz_static tests
This commit is contained in:
parent
97be6b52cc
commit
523caf52d6
@ -12,3 +12,4 @@ serde_derive = "1.0"
|
|||||||
serde_yaml = "0.8"
|
serde_yaml = "0.8"
|
||||||
ssz = { path = "../../eth2/utils/ssz" }
|
ssz = { path = "../../eth2/utils/ssz" }
|
||||||
types = { path = "../../eth2/types" }
|
types = { path = "../../eth2/types" }
|
||||||
|
yaml-rust = "0.4"
|
||||||
|
@ -10,6 +10,7 @@ pub use crate::test_case_result::*;
|
|||||||
pub use crate::test_doc::*;
|
pub use crate::test_doc::*;
|
||||||
pub use crate::test_doc_cases::*;
|
pub use crate::test_doc_cases::*;
|
||||||
pub use crate::test_doc_header::*;
|
pub use crate::test_doc_header::*;
|
||||||
|
pub use crate::yaml_utils::*;
|
||||||
|
|
||||||
mod error;
|
mod error;
|
||||||
mod test_case_result;
|
mod test_case_result;
|
||||||
@ -17,3 +18,4 @@ mod test_decode;
|
|||||||
mod test_doc;
|
mod test_doc;
|
||||||
mod test_doc_cases;
|
mod test_doc_cases;
|
||||||
mod test_doc_header;
|
mod test_doc_header;
|
||||||
|
mod yaml_utils;
|
||||||
|
@ -24,7 +24,7 @@ impl_via_parse!(u16);
|
|||||||
impl_via_parse!(u32);
|
impl_via_parse!(u32);
|
||||||
impl_via_parse!(u64);
|
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.
|
/// hex, so we use `from_dec_str` instead.
|
||||||
macro_rules! impl_via_from_dec_str {
|
macro_rules! impl_via_from_dec_str {
|
||||||
($ty: ty) => {
|
($ty: ty) => {
|
||||||
|
@ -7,7 +7,7 @@ pub struct TestDoc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TestDoc {
|
impl TestDoc {
|
||||||
fn new(path: PathBuf) -> Self {
|
fn from_path(path: PathBuf) -> Self {
|
||||||
let mut file = File::open(path).unwrap();
|
let mut file = File::open(path).unwrap();
|
||||||
|
|
||||||
let mut yaml = String::new();
|
let mut yaml = String::new();
|
||||||
@ -17,15 +17,20 @@ impl TestDoc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_test_results(path: PathBuf) -> Vec<TestCaseResult> {
|
pub fn get_test_results(path: PathBuf) -> Vec<TestCaseResult> {
|
||||||
let doc = Self::new(path);
|
let doc = Self::from_path(path);
|
||||||
|
|
||||||
let header: TestDocHeader = serde_yaml::from_str(&doc.yaml.as_str()).unwrap();
|
let header: TestDocHeader = serde_yaml::from_str(&doc.yaml.as_str()).unwrap();
|
||||||
|
|
||||||
match (header.runner.as_ref(), header.handler.as_ref()) {
|
match (
|
||||||
("ssz", "uint") => run_test::<SszGeneric>(&doc.yaml),
|
header.runner.as_ref(),
|
||||||
(runner, handler) => panic!(
|
header.handler.as_ref(),
|
||||||
"No implementation for runner {} handler {}",
|
header.config.as_ref(),
|
||||||
runner, handler
|
) {
|
||||||
|
("ssz", "uint", _) => run_test::<SszGeneric>(&doc.yaml),
|
||||||
|
("ssz", "static", "minimal") => run_test::<SszStatic>(&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();
|
let failures: Vec<&TestCaseResult> = results.iter().filter(|r| r.result.is_err()).collect();
|
||||||
|
|
||||||
if !failures.is_empty() {
|
if !failures.is_empty() {
|
||||||
panic!("{:?}", failures);
|
for f in failures {
|
||||||
|
dbg!(&f.case_index);
|
||||||
|
dbg!(&f.result);
|
||||||
|
}
|
||||||
|
panic!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_test<T>(test_doc_yaml: &String) -> Vec<TestCaseResult>
|
pub fn run_test<T>(test_doc_yaml: &String) -> Vec<TestCaseResult>
|
||||||
where
|
where
|
||||||
TestDocCases<T>: Test + serde::de::DeserializeOwned,
|
TestDocCases<T>: Test + serde::de::DeserializeOwned + TestDecode,
|
||||||
{
|
{
|
||||||
let doc: TestDocCases<T> = 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<T> =
|
||||||
|
TestDocCases::test_decode(&test_cases_yaml.to_string()).unwrap();
|
||||||
|
|
||||||
|
test_cases.test()
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,35 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
use yaml_rust::YamlLoader;
|
||||||
|
|
||||||
mod ssz_generic;
|
mod ssz_generic;
|
||||||
// mod ssz_static;
|
mod ssz_static;
|
||||||
|
|
||||||
pub use ssz_generic::*;
|
pub use ssz_generic::*;
|
||||||
|
pub use ssz_static::*;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct TestDocCases<T> {
|
pub struct TestDocCases<T> {
|
||||||
pub test_cases: Vec<T>,
|
pub test_cases: Vec<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: TestDecode> TestDecode for TestDocCases<T> {
|
||||||
|
/// Decodes a YAML list of test cases
|
||||||
|
fn test_decode(yaml: &String) -> Result<Self, Error> {
|
||||||
|
let doc = &YamlLoader::load_from_str(yaml).unwrap()[0];
|
||||||
|
|
||||||
|
let mut test_cases: Vec<T> = 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 })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -9,6 +9,12 @@ pub struct SszGeneric {
|
|||||||
pub ssz: Option<String>,
|
pub ssz: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TestDecode for SszGeneric {
|
||||||
|
fn test_decode(yaml: &String) -> Result<Self, Error> {
|
||||||
|
Ok(serde_yaml::from_str(&yaml.as_str()).unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Test for TestDocCases<SszGeneric> {
|
impl Test for TestDocCases<SszGeneric> {
|
||||||
fn test(&self) -> Vec<TestCaseResult> {
|
fn test(&self) -> Vec<TestCaseResult> {
|
||||||
self.test_cases
|
self.test_cases
|
||||||
|
@ -1,49 +1,73 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
use serde::de::{Deserialize, Deserializer};
|
||||||
use types::Fork;
|
use types::Fork;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
pub struct SszStatic {
|
pub struct SszStatic {
|
||||||
pub type_name: String,
|
pub type_name: String,
|
||||||
pub value: String,
|
|
||||||
pub serialized: String,
|
pub serialized: String,
|
||||||
pub root: String,
|
pub root: String,
|
||||||
|
#[serde(skip)]
|
||||||
|
pub raw_yaml: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Test<SszStatic> for TestDoc<SszStatic> {
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
fn test(&self) -> Vec<TestCaseResult<SszStatic>> {
|
pub struct Value<T> {
|
||||||
|
value: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestDecode for SszStatic {
|
||||||
|
fn test_decode(yaml: &String) -> Result<Self, Error> {
|
||||||
|
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<T: serde::de::DeserializeOwned>(&self) -> Result<T, Error> {
|
||||||
|
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<SszStatic> {
|
||||||
|
fn test(&self) -> Vec<TestCaseResult> {
|
||||||
self.test_cases
|
self.test_cases
|
||||||
.iter()
|
.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() {
|
||||||
"Fork" => ssz_static_test::<Fork>(&tc.value, &tc.serialized, &tc.root),
|
"Fork" => ssz_static_test::<Fork>(tc),
|
||||||
_ => Err(Error::FailedToParseTest(format!(
|
_ => Err(Error::FailedToParseTest(format!(
|
||||||
"Unknown type: {}",
|
"Unknown type: {}",
|
||||||
tc.type_name
|
tc.type_name
|
||||||
))),
|
))),
|
||||||
};
|
};
|
||||||
|
|
||||||
TestCaseResult {
|
TestCaseResult::new(i, tc, result)
|
||||||
case_index: i,
|
|
||||||
case: tc.clone(),
|
|
||||||
result,
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Execute a `ssz_generic` test case.
|
fn ssz_static_test<T>(tc: &SszStatic) -> Result<(), Error>
|
||||||
fn ssz_static_test<T>(value: &String, serialized: &String, root: &String) -> Result<(), Error>
|
|
||||||
where
|
where
|
||||||
T: Decode + TestDecode + Debug + PartialEq<T>,
|
T: Decode + TestDecode + Debug + PartialEq<T> + serde::de::DeserializeOwned,
|
||||||
{
|
{
|
||||||
let ssz =
|
let ssz = hex::decode(&tc.serialized[2..])
|
||||||
hex::decode(&serialized[2..]).map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?;
|
.map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?;
|
||||||
|
|
||||||
let expected = T::test_decode(value)?;
|
let expected = tc.value::<T>()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
|
||||||
|
/*
|
||||||
let decoded = T::from_ssz_bytes(&ssz);
|
let decoded = T::from_ssz_bytes(&ssz);
|
||||||
|
|
||||||
compare_result(decoded, Some(expected))
|
compare_result(decoded, Some(expected))
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
23
tests/ef_tests/src/yaml_utils.rs
Normal file
23
tests/ef_tests/src/yaml_utils.rs
Normal file
@ -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
|
||||||
|
}
|
@ -34,3 +34,20 @@ mod ssz_generic {
|
|||||||
TestDoc::assert_tests_pass(ssz_generic_file("uint/uint_wrong_length.yaml"));
|
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"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user