diff --git a/tests/ef_tests/src/lib.rs b/tests/ef_tests/src/lib.rs index 4e58bdb86..4eb06dd9a 100644 --- a/tests/ef_tests/src/lib.rs +++ b/tests/ef_tests/src/lib.rs @@ -6,73 +6,14 @@ use std::fmt::Debug; use test_decode::TestDecode; pub use crate::error::*; -pub use crate::ssz_generic::*; +pub use crate::test_case_result::*; +pub use crate::test_doc::*; +pub use crate::test_doc_cases::*; +pub use crate::test_doc_header::*; mod error; -mod ssz_generic; -mod ssz_static; +mod test_case_result; mod test_decode; - -#[derive(Debug, Deserialize)] -pub struct TestDoc { - pub title: String, - pub summary: String, - pub forks_timeline: String, - pub forks: Vec, - pub config: String, - pub runner: String, - pub handler: String, - pub test_cases: Vec, -} - -#[derive(Debug, PartialEq, Clone)] -pub struct TestCaseResult { - pub case_index: usize, - pub case: T, - pub result: Result<(), Error>, -} - -pub trait Test { - fn test(&self) -> Vec>; -} - -/// Compares `result` with `expected`. -/// -/// If `expected.is_none()` then `result` is expected to be `Err`. Otherwise, `T` in `result` and -/// `expected` must be equal. -fn compare_result(result: Result, expected: Option) -> Result<(), Error> -where - T: PartialEq + 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!( - "Got {:?} expected {:?}", - e, expected - ))), - // Fail: The test produced a result when it should have failed (fail). - (Ok(result), None) => Err(Error::DidntFail(format!("Got {:?}", result))), - // 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!( - "Got {:?} expected {:?}", - result, expected - ))) - } - } - } -} - -#[cfg(test)] -mod tests { - #[test] - fn it_works() { - assert_eq!(2 + 2, 4); - } -} +mod test_doc; +mod test_doc_cases; +mod test_doc_header; diff --git a/tests/ef_tests/src/test_case_result.rs b/tests/ef_tests/src/test_case_result.rs new file mode 100644 index 000000000..f16036922 --- /dev/null +++ b/tests/ef_tests/src/test_case_result.rs @@ -0,0 +1,55 @@ +use super::*; + +#[derive(Debug, PartialEq, Clone)] +pub struct TestCaseResult { + pub case_index: usize, + pub desc: String, + pub result: Result<(), Error>, +} + +impl TestCaseResult { + pub fn new(case_index: usize, case: &T, result: Result<(), Error>) -> Self { + TestCaseResult { + case_index, + desc: format!("{:?}", case), + result, + } + } +} + +pub trait Test { + fn test(&self) -> Vec; +} + +/// Compares `result` with `expected`. +/// +/// If `expected.is_none()` then `result` is expected to be `Err`. Otherwise, `T` in `result` and +/// `expected` must be equal. +pub fn compare_result(result: Result, expected: Option) -> Result<(), Error> +where + T: PartialEq + 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!( + "Got {:?} expected {:?}", + e, expected + ))), + // Fail: The test produced a result when it should have failed (fail). + (Ok(result), None) => Err(Error::DidntFail(format!("Got {:?}", result))), + // 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!( + "Got {:?} expected {:?}", + result, expected + ))) + } + } + } +} diff --git a/tests/ef_tests/src/test_doc.rs b/tests/ef_tests/src/test_doc.rs new file mode 100644 index 000000000..7417fc280 --- /dev/null +++ b/tests/ef_tests/src/test_doc.rs @@ -0,0 +1,51 @@ +use super::*; +use std::{fs::File, io::prelude::*, path::PathBuf}; + +#[derive(Debug, Deserialize)] +pub struct TestDoc { + pub yaml: String, +} + +impl TestDoc { + fn new(path: PathBuf) -> Self { + let mut file = File::open(path).unwrap(); + + let mut yaml = String::new(); + file.read_to_string(&mut yaml).unwrap(); + + Self { yaml } + } + + pub fn get_test_results(path: PathBuf) -> Vec { + let doc = Self::new(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 + ), + } + } + + pub fn assert_tests_pass(path: PathBuf) { + let results = Self::get_test_results(path); + + let failures: Vec<&TestCaseResult> = results.iter().filter(|r| r.result.is_err()).collect(); + + if !failures.is_empty() { + panic!("{:?}", failures); + } + } +} + +pub fn run_test(test_doc_yaml: &String) -> Vec +where + TestDocCases: Test + serde::de::DeserializeOwned, +{ + let doc: TestDocCases = serde_yaml::from_str(&test_doc_yaml.as_str()).unwrap(); + + doc.test() +} diff --git a/tests/ef_tests/src/test_doc_cases.rs b/tests/ef_tests/src/test_doc_cases.rs new file mode 100644 index 000000000..b46668925 --- /dev/null +++ b/tests/ef_tests/src/test_doc_cases.rs @@ -0,0 +1,11 @@ +use super::*; + +mod ssz_generic; +// mod ssz_static; + +pub use ssz_generic::*; + +#[derive(Debug, Deserialize)] +pub struct TestDocCases { + pub test_cases: Vec, +} diff --git a/tests/ef_tests/src/ssz_generic.rs b/tests/ef_tests/src/test_doc_cases/ssz_generic.rs similarity index 88% rename from tests/ef_tests/src/ssz_generic.rs rename to tests/ef_tests/src/test_doc_cases/ssz_generic.rs index fbd307169..b99c6f005 100644 --- a/tests/ef_tests/src/ssz_generic.rs +++ b/tests/ef_tests/src/test_doc_cases/ssz_generic.rs @@ -9,8 +9,8 @@ pub struct SszGeneric { pub ssz: Option, } -impl Test for TestDoc { - fn test(&self) -> Vec> { +impl Test for TestDocCases { + fn test(&self) -> Vec { self.test_cases .iter() .enumerate() @@ -35,11 +35,7 @@ impl Test for TestDoc { Ok(()) }; - TestCaseResult { - case_index: i, - case: tc.clone(), - result, - } + TestCaseResult::new(i, tc, result) }) .collect() } diff --git a/tests/ef_tests/src/ssz_static.rs b/tests/ef_tests/src/test_doc_cases/ssz_static.rs similarity index 100% rename from tests/ef_tests/src/ssz_static.rs rename to tests/ef_tests/src/test_doc_cases/ssz_static.rs diff --git a/tests/ef_tests/src/test_doc_header.rs b/tests/ef_tests/src/test_doc_header.rs new file mode 100644 index 000000000..f605e85bb --- /dev/null +++ b/tests/ef_tests/src/test_doc_header.rs @@ -0,0 +1,12 @@ +use super::*; + +#[derive(Debug, Deserialize)] +pub struct TestDocHeader { + pub title: String, + pub summary: String, + pub forks_timeline: String, + pub forks: Vec, + pub config: String, + pub runner: String, + pub handler: String, +} diff --git a/tests/ef_tests/tests/tests.rs b/tests/ef_tests/tests/tests.rs index f27aacf06..2bcd29dab 100644 --- a/tests/ef_tests/tests/tests.rs +++ b/tests/ef_tests/tests/tests.rs @@ -2,6 +2,7 @@ use ef_tests::*; use serde::de::DeserializeOwned; use std::{fs::File, io::prelude::*, path::PathBuf}; +/* fn load_test_case(test_name: &str) -> TestDoc { let mut file = { let mut file_path_buf = PathBuf::from(env!("CARGO_MANIFEST_DIR")); @@ -23,10 +24,34 @@ fn ssz_generic() { let results = doc.test(); - 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() { panic!("{:?}", failures); } } +*/ + +fn test_file(trailing_path: &str) -> PathBuf { + let mut file_path_buf = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + file_path_buf.push(format!("eth2.0-spec-tests/tests/{}", trailing_path)); + + file_path_buf +} + +mod ssz_generic { + use super::*; + + fn ssz_generic_file(file: &str) -> PathBuf { + let mut path = test_file("ssz_generic"); + path.push(file); + dbg!(&path); + + path + } + + #[test] + fn uint_bounds() { + TestDoc::assert_tests_pass(ssz_generic_file("uint/uint_bounds.yaml")); + } +}