From c6fa1602ded1b92ee0a685d8836730d0622d4f73 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Wed, 15 May 2019 17:14:28 +1000 Subject: [PATCH] Improve efficiency with manual YAML operations --- tests/ef_tests/src/cases.rs | 34 ++++++++++++++++--------- tests/ef_tests/src/doc.rs | 29 +++++++++++++-------- tests/ef_tests/src/yaml_decode/utils.rs | 11 ++++++++ 3 files changed, 51 insertions(+), 23 deletions(-) diff --git a/tests/ef_tests/src/cases.rs b/tests/ef_tests/src/cases.rs index 5bb1bdc2fc..90872707d9 100644 --- a/tests/ef_tests/src/cases.rs +++ b/tests/ef_tests/src/cases.rs @@ -16,21 +16,31 @@ pub struct Cases { impl YamlDecode for Cases { /// Decodes a YAML list of test cases fn yaml_decode(yaml: &String) -> Result { - 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 = vec![]; + yaml_element + }) + .collect(); - let mut i = 0; - 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()) - } + elems.push(&yaml[p..]); - 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 }) } diff --git a/tests/ef_tests/src/doc.rs b/tests/ef_tests/src/doc.rs index 1a93c738a7..2898ed3f86 100644 --- a/tests/ef_tests/src/doc.rs +++ b/tests/ef_tests/src/doc.rs @@ -2,7 +2,7 @@ use crate::case_result::CaseResult; use crate::cases::*; use crate::doc_header::DocHeader; 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 serde_derive::Deserialize; use std::{fs::File, io::prelude::*, path::PathBuf}; @@ -10,7 +10,8 @@ use types::EthSpec; #[derive(Debug, Deserialize)] pub struct Doc { - pub yaml: String, + pub header_yaml: String, + pub cases_yaml: String, pub path: PathBuf, } @@ -21,20 +22,26 @@ impl Doc { let mut yaml = String::new(); 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 { - 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 ( header.runner.as_ref(), header.handler.as_ref(), header.config.as_ref(), ) { - ("ssz", "uint", _) => run_test::(&self.yaml), - ("ssz", "static", "minimal") => run_test::(&self.yaml), - ("ssz", "static", "mainnet") => run_test::(&self.yaml), + ("ssz", "uint", _) => run_test::(&self), + ("ssz", "static", "minimal") => run_test::(&self), + ("ssz", "static", "mainnet") => run_test::(&self), (runner, handler, config) => panic!( "No implementation for runner: \"{}\", handler: \"{}\", config: \"{}\"", runner, handler, config @@ -55,21 +62,21 @@ impl Doc { } } -pub fn run_test(test_doc_yaml: &String) -> Vec +pub fn run_test(doc: &Doc) -> Vec where Cases: EfTest + YamlDecode, { // 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`. - let test_cases: Cases = Cases::yaml_decode(&test_cases_yaml.to_string()).unwrap(); + let test_cases: Cases = Cases::yaml_decode(&doc.cases_yaml).unwrap(); test_cases.test_results::() } 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(); println!("--------------------------------------------------"); diff --git a/tests/ef_tests/src/yaml_decode/utils.rs b/tests/ef_tests/src/yaml_decode/utils.rs index ae13ba3b45..9b7d7ef53e 100644 --- a/tests/ef_tests/src/yaml_decode/utils.rs +++ b/tests/ef_tests/src/yaml_decode/utils.rs @@ -22,3 +22,14 @@ pub fn yaml_to_string(yaml: &Yaml) -> String { 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) +}