Move ssz_generic tests into own file

This commit is contained in:
Paul Hauner 2019-05-14 09:36:25 +10:00
parent 1f6e393ff0
commit 55ff1e0b40
No known key found for this signature in database
GPG Key ID: D362883A9218FCC6
3 changed files with 73 additions and 64 deletions

View File

@ -5,7 +5,10 @@ use ssz::Decode;
use std::fmt::Debug;
use test_decode::TestDecode;
pub use crate::ssz_generic::*;
mod error;
mod ssz_generic;
mod test_decode;
#[derive(Debug, Deserialize)]
@ -20,15 +23,6 @@ pub struct TestDoc<T> {
pub test_cases: Vec<T>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct SszGenericCase {
#[serde(alias = "type")]
pub type_name: String,
pub valid: bool,
pub value: String,
pub ssz: Option<String>,
}
#[derive(Debug, PartialEq, Clone)]
pub struct TestCaseResult<T> {
pub case_index: usize,
@ -40,59 +34,10 @@ pub trait Test<T> {
fn test(&self) -> Vec<TestCaseResult<T>>;
}
impl Test<SszGenericCase> for TestDoc<SszGenericCase> {
fn test(&self) -> Vec<TestCaseResult<SszGenericCase>> {
self.test_cases
.iter()
.enumerate()
.map(|(i, tc)| {
let result = if let Some(ssz) = &tc.ssz {
match tc.type_name.as_ref() {
"uint8" => compare_decoding::<u8>(tc.valid, ssz, &tc.value),
"uint16" => compare_decoding::<u16>(tc.valid, ssz, &tc.value),
"uint32" => compare_decoding::<u32>(tc.valid, ssz, &tc.value),
"uint64" => compare_decoding::<u64>(tc.valid, ssz, &tc.value),
"uint128" => compare_decoding::<U128>(tc.valid, ssz, &tc.value),
"uint256" => compare_decoding::<U256>(tc.valid, ssz, &tc.value),
_ => Err(Error::FailedToParseTest(format!(
"Unknown type: {}",
tc.type_name
))),
}
} else {
// Skip tests that do not have an ssz field.
//
// See: https://github.com/ethereum/eth2.0-specs/issues/1079
Ok(())
};
TestCaseResult {
case_index: i,
case: tc.clone(),
result,
}
})
.collect()
}
}
fn compare_decoding<T>(should_be_ok: bool, ssz: &String, value: &String) -> Result<(), Error>
where
T: Decode + TestDecode + Debug + PartialEq<T>,
{
let ssz = hex::decode(&ssz[2..]).map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?;
let expected = if should_be_ok {
Some(T::test_decode(value)?)
} else {
None
};
let decoded = T::from_ssz_bytes(&ssz);
compare_result(decoded, expected)
}
/// 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<T, E>(result: Result<T, E>, expected: Option<T>) -> Result<(), Error>
where
T: PartialEq<T> + Debug,

View File

@ -0,0 +1,64 @@
use super::*;
#[derive(Debug, Clone, Deserialize)]
pub struct SszGeneric {
#[serde(alias = "type")]
pub type_name: String,
pub valid: bool,
pub value: String,
pub ssz: Option<String>,
}
impl Test<SszGeneric> for TestDoc<SszGeneric> {
fn test(&self) -> Vec<TestCaseResult<SszGeneric>> {
self.test_cases
.iter()
.enumerate()
.map(|(i, tc)| {
let result = if let Some(ssz) = &tc.ssz {
match tc.type_name.as_ref() {
"uint8" => ssz_generic_test::<u8>(tc.valid, ssz, &tc.value),
"uint16" => ssz_generic_test::<u16>(tc.valid, ssz, &tc.value),
"uint32" => ssz_generic_test::<u32>(tc.valid, ssz, &tc.value),
"uint64" => ssz_generic_test::<u64>(tc.valid, ssz, &tc.value),
"uint128" => ssz_generic_test::<U128>(tc.valid, ssz, &tc.value),
"uint256" => ssz_generic_test::<U256>(tc.valid, ssz, &tc.value),
_ => Err(Error::FailedToParseTest(format!(
"Unknown type: {}",
tc.type_name
))),
}
} else {
// Skip tests that do not have an ssz field.
//
// See: https://github.com/ethereum/eth2.0-specs/issues/1079
Ok(())
};
TestCaseResult {
case_index: i,
case: tc.clone(),
result,
}
})
.collect()
}
}
/// Execute a `ssz_generic` test case.
fn ssz_generic_test<T>(should_be_ok: bool, ssz: &String, value: &String) -> Result<(), Error>
where
T: Decode + TestDecode + Debug + PartialEq<T>,
{
let ssz = hex::decode(&ssz[2..]).map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?;
let expected = if should_be_ok {
Some(T::test_decode(value)?)
} else {
None
};
let decoded = T::from_ssz_bytes(&ssz);
compare_result(decoded, expected)
}

View File

@ -19,11 +19,11 @@ fn load_test_case<T: DeserializeOwned>(test_name: &str) -> TestDoc<T> {
#[test]
fn ssz() {
let doc: TestDoc<SszGenericCase> = load_test_case("ssz_generic/uint/uint_bounds.yaml");
let doc: TestDoc<SszGeneric> = load_test_case("ssz_generic/uint/uint_bounds.yaml");
let results = doc.test();
let failures: Vec<&TestCaseResult<SszGenericCase>> =
let failures: Vec<&TestCaseResult<SszGeneric>> =
results.iter().filter(|r| r.result.is_err()).collect();
if !failures.is_empty() {