feat!: remove filter flag from commands in favor of include and exclude
This commit is contained in:
parent
5e46fef0d7
commit
10e474f488
4 changed files with 68 additions and 39 deletions
|
|
@ -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<String> = env::var("TREE_SITTER_LANGUAGE").ok();
|
||||
pub static ref EXAMPLE_FILTER: Option<Regex> = regex_env_var("TREE_SITTER_EXAMPLE");
|
||||
pub static ref EXAMPLE_INCLUDE: Option<Regex> = regex_env_var("TREE_SITTER_EXAMPLE_INCLUDE");
|
||||
pub static ref EXAMPLE_EXCLUDE: Option<Regex> = 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<Regex> {
|
|||
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<String>,
|
||||
pub edits: usize,
|
||||
pub iterations: usize,
|
||||
pub filter: Option<Regex>,
|
||||
pub include: Option<Regex>,
|
||||
pub exclude: Option<Regex>,
|
||||
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<FlattenedTest> {
|
||||
#[must_use]
|
||||
pub fn flatten_tests(
|
||||
test: TestEntry,
|
||||
include: Option<&Regex>,
|
||||
exclude: Option<&Regex>,
|
||||
) -> Vec<FlattenedTest> {
|
||||
fn helper(
|
||||
test: TestEntry,
|
||||
filter: Option<&Regex>,
|
||||
include: Option<&Regex>,
|
||||
exclude: Option<&Regex>,
|
||||
is_root: bool,
|
||||
prefix: &str,
|
||||
result: &mut Vec<FlattenedTest>,
|
||||
|
|
@ -315,8 +328,13 @@ pub fn flatten_tests(test: TestEntry, filter: Option<&Regex>) -> Vec<FlattenedTe
|
|||
name.insert_str(0, " - ");
|
||||
name.insert_str(0, prefix);
|
||||
}
|
||||
if let Some(filter) = filter {
|
||||
if filter.find(&name).is_none() {
|
||||
|
||||
if let Some(include) = include {
|
||||
if !include.is_match(&name) {
|
||||
return;
|
||||
}
|
||||
} else if let Some(exclude) = exclude {
|
||||
if exclude.is_match(&name) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -338,12 +356,12 @@ pub fn flatten_tests(test: TestEntry, filter: Option<&Regex>) -> Vec<FlattenedTe
|
|||
name.insert_str(0, prefix);
|
||||
}
|
||||
for child in children {
|
||||
helper(child, filter, false, &name, result);
|
||||
helper(child, include, exclude, false, &name, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut result = Vec::new();
|
||||
helper(test, filter, true, "", &mut result);
|
||||
helper(test, include, exclude, true, "", &mut result);
|
||||
result
|
||||
}
|
||||
|
|
|
|||
|
|
@ -206,12 +206,6 @@ struct Parse {
|
|||
#[derive(Args)]
|
||||
#[command(about = "Run a parser's tests", alias = "t")]
|
||||
struct Test {
|
||||
#[arg(
|
||||
long,
|
||||
short,
|
||||
help = "Only run corpus test cases whose name includes the given string"
|
||||
)]
|
||||
pub filter: Option<String>,
|
||||
#[arg(
|
||||
long,
|
||||
short,
|
||||
|
|
@ -267,8 +261,18 @@ struct Fuzz {
|
|||
pub edits: Option<usize>,
|
||||
#[arg(long, short, help = "Number of fuzzing iterations to run per test")]
|
||||
pub iterations: Option<usize>,
|
||||
#[arg(long, short, help = "Regex pattern to filter tests")]
|
||||
pub filter: Option<Regex>,
|
||||
#[arg(
|
||||
long,
|
||||
short,
|
||||
help = "Only fuzz corpus test cases whose name matches the given regex"
|
||||
)]
|
||||
pub include: Option<Regex>,
|
||||
#[arg(
|
||||
long,
|
||||
short,
|
||||
help = "Only fuzz corpus test cases whose name does not match the given regex"
|
||||
)]
|
||||
pub exclude: Option<Regex>,
|
||||
#[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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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<Regex>,
|
||||
pub exclude: Option<Regex>,
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -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:?}");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue