Improve efficiency with manual YAML operations
This commit is contained in:
parent
63ee179def
commit
c6fa1602de
@ -16,21 +16,31 @@ pub struct Cases<T> {
|
|||||||
impl<T: YamlDecode> YamlDecode for Cases<T> {
|
impl<T: YamlDecode> YamlDecode for Cases<T> {
|
||||||
/// Decodes a YAML list of test cases
|
/// Decodes a YAML list of test cases
|
||||||
fn yaml_decode(yaml: &String) -> Result<Self, Error> {
|
fn yaml_decode(yaml: &String) -> Result<Self, Error> {
|
||||||
let doc = &YamlLoader::load_from_str(yaml).unwrap()[0];
|
let mut p = 0;
|
||||||
|
let mut elems: Vec<&str> = yaml
|
||||||
|
.match_indices("\n- ")
|
||||||
|
// Skip the `\n` used for matching a new line
|
||||||
|
.map(|(i, _)| i + 1)
|
||||||
|
.map(|i| {
|
||||||
|
let yaml_element = &yaml[p..i];
|
||||||
|
p = i;
|
||||||
|
|
||||||
let mut test_cases: Vec<T> = vec![];
|
yaml_element
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
let mut i = 0;
|
elems.push(&yaml[p..]);
|
||||||
loop {
|
|
||||||
// `is_badvalue` indicates when we have reached the end of the YAML list.
|
|
||||||
if doc[i].is_badvalue() {
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
test_cases.push(T::yaml_decode(&yaml_to_string(&doc[i])).unwrap())
|
|
||||||
}
|
|
||||||
|
|
||||||
i += 1;
|
let test_cases = elems
|
||||||
}
|
.iter()
|
||||||
|
.map(|s| {
|
||||||
|
// Remove the `- ` prefix.
|
||||||
|
let s = &s[2..];
|
||||||
|
// Remove a single level of indenting.
|
||||||
|
s.replace("\n ", "\n")
|
||||||
|
})
|
||||||
|
.map(|s| T::yaml_decode(&s.to_string()).unwrap())
|
||||||
|
.collect();
|
||||||
|
|
||||||
Ok(Self { test_cases })
|
Ok(Self { test_cases })
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ 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::{MainnetEthSpec, MinimalEthSpec};
|
use crate::eth_specs::{MainnetEthSpec, MinimalEthSpec};
|
||||||
use crate::yaml_decode::{extract_yaml_by_key, YamlDecode};
|
use crate::yaml_decode::{extract_yaml_by_key, yaml_split_header_and_cases, 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};
|
||||||
@ -10,7 +10,8 @@ use types::EthSpec;
|
|||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct Doc {
|
pub struct Doc {
|
||||||
pub yaml: String,
|
pub header_yaml: String,
|
||||||
|
pub cases_yaml: String,
|
||||||
pub path: PathBuf,
|
pub path: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,20 +22,26 @@ impl Doc {
|
|||||||
let mut yaml = String::new();
|
let mut yaml = String::new();
|
||||||
file.read_to_string(&mut yaml).unwrap();
|
file.read_to_string(&mut yaml).unwrap();
|
||||||
|
|
||||||
Self { yaml, path }
|
let (header_yaml, cases_yaml) = yaml_split_header_and_cases(yaml.clone());
|
||||||
|
|
||||||
|
Self {
|
||||||
|
header_yaml,
|
||||||
|
cases_yaml,
|
||||||
|
path,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn test_results(&self) -> Vec<CaseResult> {
|
pub fn test_results(&self) -> Vec<CaseResult> {
|
||||||
let header: DocHeader = serde_yaml::from_str(&self.yaml.as_str()).unwrap();
|
let header: DocHeader = serde_yaml::from_str(&self.header_yaml.as_str()).unwrap();
|
||||||
|
|
||||||
match (
|
match (
|
||||||
header.runner.as_ref(),
|
header.runner.as_ref(),
|
||||||
header.handler.as_ref(),
|
header.handler.as_ref(),
|
||||||
header.config.as_ref(),
|
header.config.as_ref(),
|
||||||
) {
|
) {
|
||||||
("ssz", "uint", _) => run_test::<SszGeneric, MainnetEthSpec>(&self.yaml),
|
("ssz", "uint", _) => run_test::<SszGeneric, MainnetEthSpec>(&self),
|
||||||
("ssz", "static", "minimal") => run_test::<SszStatic, MinimalEthSpec>(&self.yaml),
|
("ssz", "static", "minimal") => run_test::<SszStatic, MinimalEthSpec>(&self),
|
||||||
("ssz", "static", "mainnet") => run_test::<SszStatic, MainnetEthSpec>(&self.yaml),
|
("ssz", "static", "mainnet") => run_test::<SszStatic, MainnetEthSpec>(&self),
|
||||||
(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
|
||||||
@ -55,21 +62,21 @@ impl Doc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_test<T, E: EthSpec>(test_doc_yaml: &String) -> Vec<CaseResult>
|
pub fn run_test<T, E: EthSpec>(doc: &Doc) -> Vec<CaseResult>
|
||||||
where
|
where
|
||||||
Cases<T>: EfTest + YamlDecode,
|
Cases<T>: EfTest + YamlDecode,
|
||||||
{
|
{
|
||||||
// Extract only the "test_cases" YAML as a stand-alone string.
|
// Extract only the "test_cases" YAML as a stand-alone string.
|
||||||
let test_cases_yaml = extract_yaml_by_key(test_doc_yaml, "test_cases");
|
//let test_cases_yaml = extract_yaml_by_key(self., "test_cases");
|
||||||
|
|
||||||
// Pass only the "test_cases" YAML string to `yaml_decode`.
|
// Pass only the "test_cases" YAML string to `yaml_decode`.
|
||||||
let test_cases: Cases<T> = Cases::yaml_decode(&test_cases_yaml.to_string()).unwrap();
|
let test_cases: Cases<T> = Cases::yaml_decode(&doc.cases_yaml).unwrap();
|
||||||
|
|
||||||
test_cases.test_results::<E>()
|
test_cases.test_results::<E>()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn print_failures(doc: &Doc, results: &[CaseResult]) {
|
pub fn print_failures(doc: &Doc, results: &[CaseResult]) {
|
||||||
let header: DocHeader = serde_yaml::from_str(&doc.yaml).unwrap();
|
let header: DocHeader = serde_yaml::from_str(&doc.header_yaml).unwrap();
|
||||||
let failures: Vec<&CaseResult> = results.iter().filter(|r| r.result.is_err()).collect();
|
let failures: Vec<&CaseResult> = results.iter().filter(|r| r.result.is_err()).collect();
|
||||||
|
|
||||||
println!("--------------------------------------------------");
|
println!("--------------------------------------------------");
|
||||||
|
@ -22,3 +22,14 @@ pub fn yaml_to_string(yaml: &Yaml) -> String {
|
|||||||
|
|
||||||
out_str
|
out_str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn yaml_split_header_and_cases(mut yaml: String) -> (String, String) {
|
||||||
|
let test_cases_start = yaml.find("\ntest_cases:\n").unwrap();
|
||||||
|
// + 1 to skip the \n we used for matching.
|
||||||
|
let mut test_cases = yaml.split_off(test_cases_start + 1);
|
||||||
|
|
||||||
|
let end_of_first_line = test_cases.find("\n").unwrap();
|
||||||
|
let test_cases = test_cases.split_off(end_of_first_line + 1);
|
||||||
|
|
||||||
|
(yaml, test_cases)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user