Finish adding generated parser test generation.
This commit is contained in:
parent
024baf2064
commit
9c43e28f32
8
build.rs
8
build.rs
@ -9,10 +9,8 @@ fn main() -> std::io::Result<()> {
|
||||
let out_dir_path = Path::new(&out_dir);
|
||||
let parser_tests_dir = out_dir_path.join("src").join("parser").join("tests");
|
||||
fs::create_dir_all(&parser_tests_dir)?;
|
||||
let files = generate_test_files(Path::new("src/parser/tests"))?;
|
||||
for parser_test_file in &files {
|
||||
let file_path = parser_tests_dir.join(&parser_test_file.file_name);
|
||||
fs::write(file_path, &parser_test_file.contents)?;
|
||||
}
|
||||
let test_suites_file = generate_test_files(Path::new("src/parser/tests"))?;
|
||||
let file_path = parser_tests_dir.join(&test_suites_file.file_name);
|
||||
fs::write(file_path, &test_suites_file.contents)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -5,14 +5,13 @@ use std::path::Path;
|
||||
use std::{fs, io};
|
||||
use syn::File;
|
||||
|
||||
pub struct ParserTestFile {
|
||||
pub struct ParserTestSuitesFile {
|
||||
pub file_name: String,
|
||||
pub contents: String,
|
||||
}
|
||||
|
||||
pub fn generate_test_files(tests_dir: &Path) -> io::Result<Vec<ParserTestFile>> {
|
||||
let mut files: Vec<ParserTestFile> = vec![];
|
||||
let mut test_module_names: Vec<String> = vec![];
|
||||
pub fn generate_test_files(tests_dir: &Path) -> io::Result<ParserTestSuitesFile> {
|
||||
let mut test_suites: Vec<TokenStream> = vec![];
|
||||
|
||||
// generate test file for each sub dir
|
||||
for sub_dir in fs::read_dir(tests_dir)? {
|
||||
@ -21,7 +20,6 @@ pub fn generate_test_files(tests_dir: &Path) -> io::Result<Vec<ParserTestFile>>
|
||||
if sub_dir_path.is_dir() {
|
||||
let sub_dir_file_name = sub_dir.file_name();
|
||||
let sub_dir_string = sub_dir_file_name.to_string_lossy();
|
||||
test_module_names.push(sub_dir_string.to_string());
|
||||
|
||||
let sub_dir_pascal = sub_dir_string.to_case(Case::Pascal);
|
||||
let rule_ident = format_ident!("{}", sub_dir_pascal);
|
||||
@ -45,71 +43,30 @@ pub fn generate_test_files(tests_dir: &Path) -> io::Result<Vec<ParserTestFile>>
|
||||
}
|
||||
|
||||
let tests_mod_ident = format_ident!("{}_tests", sub_dir.file_name().to_string_lossy());
|
||||
let test_file_contents = quote! {
|
||||
#[cfg(test)]
|
||||
let test_suite = quote! {
|
||||
mod #tests_mod_ident {
|
||||
use crate::parser::Rule;
|
||||
use crate::parser::tests::parses_to;
|
||||
use super::*;
|
||||
|
||||
#(#tests)*
|
||||
}
|
||||
};
|
||||
let parsed: File = syn::parse2(test_file_contents).unwrap();
|
||||
let contents = prettyplease::unparse(&parsed);
|
||||
|
||||
let file_name = sub_dir.file_name().to_string_lossy().to_string() + ".rs";
|
||||
files.push(ParserTestFile {
|
||||
file_name,
|
||||
contents,
|
||||
})
|
||||
test_suites.push(test_suite);
|
||||
} else {
|
||||
println!("Warning: not a directory: {:?}", sub_dir_path);
|
||||
}
|
||||
}
|
||||
|
||||
let test_mod_statements = test_module_names
|
||||
.iter()
|
||||
.map(|name| format_ident!("{}", name))
|
||||
.map(|module_ident| quote! { mod #module_ident; })
|
||||
.collect::<Vec<_>>();
|
||||
// generate main test_suites file
|
||||
let test_suites = quote! {
|
||||
use super::*;
|
||||
|
||||
// generate main mod.rs file
|
||||
let main_mod = quote! {
|
||||
use crate::parser::DeimosParser;
|
||||
use crate::parser::Rule;
|
||||
use pest_derive::Parser;
|
||||
|
||||
#(#test_mod_statements)*
|
||||
|
||||
pub(crate) fn parses_to(rule: Rule, input: &str) {
|
||||
let parse_result = DeimosParser::parse(rule, input);
|
||||
if let Err(e) = parse_result {
|
||||
panic!("Parsing failed.\n{}", e);
|
||||
} else {
|
||||
let mut pairs = parse_result.unwrap();
|
||||
if input.trim() != pairs.as_str().trim() {
|
||||
panic!(
|
||||
"Parsing did not consume entire input. Consumed only:\n{}",
|
||||
pairs.as_str().trim()
|
||||
);
|
||||
}
|
||||
let first = pairs.next().unwrap();
|
||||
if rule != pair.as_rule() {
|
||||
panic!(
|
||||
"Expected {} but found {:?}.",
|
||||
stringify!(rule),
|
||||
pair.as_rule()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
#(#test_suites)*
|
||||
};
|
||||
let mod_file_parsed: File = syn::parse2(main_mod).unwrap();
|
||||
let mod_file_contents = prettyplease::unparse(&mod_file_parsed);
|
||||
files.push(ParserTestFile {
|
||||
file_name: String::from("mod.rs"),
|
||||
contents: mod_file_contents,
|
||||
});
|
||||
let test_suites_file: File = syn::parse2(test_suites).unwrap();
|
||||
let test_suites_file_contents = prettyplease::unparse(&test_suites_file);
|
||||
|
||||
Ok(files)
|
||||
Ok(ParserTestSuitesFile {
|
||||
file_name: String::from("test_suites.rs"),
|
||||
contents: test_suites_file_contents,
|
||||
})
|
||||
}
|
||||
|
||||
@ -45,6 +45,10 @@ mod deimos_parser_tests {
|
||||
}
|
||||
}
|
||||
|
||||
mod generated_tests {
|
||||
include!(concat!(env!("OUT_DIR"), "/src/parser/tests/test_suites.rs"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hex_int() {
|
||||
parses_to(Rule::IntLiteral, "0x1234abcd");
|
||||
|
||||
Loading…
Reference in New Issue
Block a user