From 10e474f4886bd599a2ff4168209dc566f3024258 Mon Sep 17 00:00:00 2001 From: Amaan Qureshi Date: Sat, 7 Sep 2024 20:15:57 -0400 Subject: [PATCH] feat!: remove `filter` flag from commands in favor of `include` and `exclude` --- cli/src/fuzz/mod.rs | 36 +++++++++++++++++++++++++++--------- cli/src/main.rs | 30 ++++++++++++++++-------------- cli/src/test.rs | 5 +---- cli/src/tests/corpus_test.rs | 36 ++++++++++++++++++++++++------------ 4 files changed, 68 insertions(+), 39 deletions(-) diff --git a/cli/src/fuzz/mod.rs b/cli/src/fuzz/mod.rs index 0fdde6e9..028215e4 100644 --- a/cli/src/fuzz/mod.rs +++ b/cli/src/fuzz/mod.rs @@ -27,7 +27,8 @@ lazy_static! { pub static ref LOG_ENABLED: bool = env::var("TREE_SITTER_LOG").is_ok(); pub static ref LOG_GRAPH_ENABLED: bool = env::var("TREE_SITTER_LOG_GRAPHS").is_ok(); pub static ref LANGUAGE_FILTER: Option = env::var("TREE_SITTER_LANGUAGE").ok(); - pub static ref EXAMPLE_FILTER: Option = regex_env_var("TREE_SITTER_EXAMPLE"); + pub static ref EXAMPLE_INCLUDE: Option = regex_env_var("TREE_SITTER_EXAMPLE_INCLUDE"); + pub static ref EXAMPLE_EXCLUDE: Option = regex_env_var("TREE_SITTER_EXAMPLE_EXCLUDE"); pub static ref START_SEED: usize = new_seed(); pub static ref EDIT_COUNT: usize = int_env_var("TREE_SITTER_EDITS").unwrap_or(3); pub static ref ITERATION_COUNT: usize = int_env_var("TREE_SITTER_ITERATIONS").unwrap_or(10); @@ -41,6 +42,7 @@ fn regex_env_var(name: &'static str) -> Option { env::var(name).ok().and_then(|e| Regex::new(&e).ok()) } +#[must_use] pub fn new_seed() -> usize { int_env_var("TREE_SITTER_SEED").unwrap_or_else(|| { let mut rng = rand::thread_rng(); @@ -53,7 +55,8 @@ pub struct FuzzOptions { pub subdir: Option, pub edits: usize, pub iterations: usize, - pub filter: Option, + pub include: Option, + pub exclude: Option, pub log_graphs: bool, pub log: bool, } @@ -106,7 +109,11 @@ pub fn fuzz_language_corpus( } TestEntry::Example { .. } => unreachable!(), } - let tests = flatten_tests(main_tests, options.filter.as_ref()); + let tests = flatten_tests( + main_tests, + options.include.as_ref(), + options.exclude.as_ref(), + ); let mut skipped = options.skipped.as_ref().map(|x| { x.iter() @@ -294,10 +301,16 @@ pub struct FlattenedTest { pub template_delimiters: Option<(&'static str, &'static str)>, } -pub fn flatten_tests(test: TestEntry, filter: Option<&Regex>) -> Vec { +#[must_use] +pub fn flatten_tests( + test: TestEntry, + include: Option<&Regex>, + exclude: Option<&Regex>, +) -> Vec { fn helper( test: TestEntry, - filter: Option<&Regex>, + include: Option<&Regex>, + exclude: Option<&Regex>, is_root: bool, prefix: &str, result: &mut Vec, @@ -315,8 +328,13 @@ pub fn flatten_tests(test: TestEntry, filter: Option<&Regex>) -> Vec) -> Vec, #[arg( long, short, @@ -267,8 +261,18 @@ struct Fuzz { pub edits: Option, #[arg(long, short, help = "Number of fuzzing iterations to run per test")] pub iterations: Option, - #[arg(long, short, help = "Regex pattern to filter tests")] - pub filter: Option, + #[arg( + long, + short, + help = "Only fuzz corpus test cases whose name matches the given regex" + )] + pub include: Option, + #[arg( + long, + short, + help = "Only fuzz corpus test cases whose name does not match the given regex" + )] + pub exclude: Option, #[arg(long, help = "Enable logging of graphs and input")] pub log_graphs: bool, #[arg(long, short, help = "Enable parser logging")] @@ -489,9 +493,9 @@ fn run() -> Result<()> { } Commands::Build(build_options) => { + let grammar_path = current_dir.join(build_options.path.as_deref().unwrap_or_default()); + if build_options.wasm { - let grammar_path = - current_dir.join(build_options.path.as_deref().unwrap_or_default()); let output_path = build_options.output.map(|path| current_dir.join(path)); let root_path = lookup_package_json_for_path(&grammar_path.join("package.json")) .map(|(p, _)| p.parent().unwrap().to_path_buf())?; @@ -504,8 +508,6 @@ fn run() -> Result<()> { build_options.docker, )?; } else { - let grammar_path = - current_dir.join(build_options.path.as_deref().unwrap_or_default()); let output_path = if let Some(ref path) = build_options.output { let path = Path::new(path); if path.is_absolute() { @@ -711,7 +713,6 @@ fn run() -> Result<()> { path: test_corpus_dir, debug: test_options.debug, debug_graph: test_options.debug_graph, - filter: test_options.filter.as_deref(), include: test_options.include, exclude: test_options.exclude, update: test_options.update, @@ -770,7 +771,8 @@ fn run() -> Result<()> { subdir: fuzz_options.subdir, edits: fuzz_options.edits.unwrap_or(*EDIT_COUNT), iterations: fuzz_options.iterations.unwrap_or(*ITERATION_COUNT), - filter: fuzz_options.filter, + include: fuzz_options.include, + exclude: fuzz_options.exclude, log_graphs: fuzz_options.log_graphs || *LOG_GRAPH_ENABLED, log: fuzz_options.log || *LOG_ENABLED, }; diff --git a/cli/src/test.rs b/cli/src/test.rs index fedffd95..dbff512e 100644 --- a/cli/src/test.rs +++ b/cli/src/test.rs @@ -99,7 +99,6 @@ pub struct TestOptions<'a> { pub path: PathBuf, pub debug: bool, pub debug_graph: bool, - pub filter: Option<&'a str>, pub include: Option, pub exclude: Option, pub update: bool, @@ -530,9 +529,7 @@ fn run_tests( let mut skipped_tests = 0; let matches_filter = |name: &str, opts: &TestOptions| { - if let Some(filter) = opts.filter { - name.contains(filter) - } else if let Some(include) = &opts.include { + if let Some(include) = &opts.include { include.is_match(name) } else if let Some(exclude) = &opts.exclude { !exclude.is_match(name) diff --git a/cli/src/tests/corpus_test.rs b/cli/src/tests/corpus_test.rs index ffa328e2..f81d7543 100644 --- a/cli/src/tests/corpus_test.rs +++ b/cli/src/tests/corpus_test.rs @@ -11,8 +11,8 @@ use crate::{ edits::{get_random_edit, invert_edit}, flatten_tests, new_seed, random::Rand, - EDIT_COUNT, EXAMPLE_FILTER, ITERATION_COUNT, LANGUAGE_FILTER, LOG_GRAPH_ENABLED, - START_SEED, + EDIT_COUNT, EXAMPLE_EXCLUDE, EXAMPLE_INCLUDE, ITERATION_COUNT, LANGUAGE_FILTER, + LOG_GRAPH_ENABLED, START_SEED, }, generate, parse::perform_edit, @@ -130,15 +130,27 @@ pub fn test_language_corpus( let main_tests = parse_tests(&corpus_dir).unwrap(); let error_tests = parse_tests(&error_corpus_file).unwrap_or_default(); let template_tests = parse_tests(&template_corpus_file).unwrap_or_default(); - let mut tests = flatten_tests(main_tests, EXAMPLE_FILTER.as_ref()); - tests.extend(flatten_tests(error_tests, EXAMPLE_FILTER.as_ref())); + let mut tests = flatten_tests( + main_tests, + EXAMPLE_INCLUDE.as_ref(), + EXAMPLE_EXCLUDE.as_ref(), + ); + tests.extend(flatten_tests( + error_tests, + EXAMPLE_INCLUDE.as_ref(), + EXAMPLE_EXCLUDE.as_ref(), + )); tests.extend( - flatten_tests(template_tests, EXAMPLE_FILTER.as_ref()) - .into_iter() - .map(|mut t| { - t.template_delimiters = Some(("<%", "%>")); - t - }), + flatten_tests( + template_tests, + EXAMPLE_INCLUDE.as_ref(), + EXAMPLE_EXCLUDE.as_ref(), + ) + .into_iter() + .map(|mut t| { + t.template_delimiters = Some(("<%", "%>")); + t + }), ); tests.retain(|t| t.languages[0].is_empty() || t.languages.contains(&Box::from(language_dir))); @@ -345,7 +357,7 @@ fn test_feature_corpus_files() { let generate_result = generate::generate_parser_for_grammar(&grammar_json); if error_message_path.exists() { - if EXAMPLE_FILTER.is_some() { + if EXAMPLE_INCLUDE.is_some() || EXAMPLE_EXCLUDE.is_some() { continue; } @@ -377,7 +389,7 @@ fn test_feature_corpus_files() { let c_code = generate_result.unwrap().1; let language = get_test_language(language_name, &c_code, Some(&test_path)); let test = parse_tests(&corpus_path).unwrap(); - let tests = flatten_tests(test, EXAMPLE_FILTER.as_ref()); + let tests = flatten_tests(test, EXAMPLE_INCLUDE.as_ref(), EXAMPLE_EXCLUDE.as_ref()); if !tests.is_empty() { eprintln!("test language: {language_name:?}");