Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow specifying multiple patterns in nargo test #7186

Merged
merged 2 commits into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions compiler/noirc_frontend/src/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ pub struct Context<'file_manager, 'parsed_files> {
pub package_build_path: PathBuf,
}

#[derive(Debug, Copy, Clone)]
pub enum FunctionNameMatch<'a> {
#[derive(Debug)]
pub enum FunctionNameMatch {
Anything,
Exact(&'a str),
Contains(&'a str),
Exact(Vec<String>),
Contains(Vec<String>),
}

impl Context<'_, '_> {
Expand Down Expand Up @@ -175,7 +175,7 @@ impl Context<'_, '_> {
pub fn get_all_test_functions_in_crate_matching(
&self,
crate_id: &CrateId,
pattern: FunctionNameMatch,
pattern: &FunctionNameMatch,
) -> Vec<(String, TestFunction)> {
let interner = &self.def_interner;
let def_map = self.def_map(crate_id).expect("The local crate should be analyzed already");
Expand All @@ -187,10 +187,13 @@ impl Context<'_, '_> {
self.fully_qualified_function_name(crate_id, &test_function.get_id());
match &pattern {
FunctionNameMatch::Anything => Some((fully_qualified_name, test_function)),
FunctionNameMatch::Exact(pattern) => (&fully_qualified_name == pattern)
FunctionNameMatch::Exact(patterns) => patterns
.iter()
.any(|pattern| &fully_qualified_name == pattern)
.then_some((fully_qualified_name, test_function)),
FunctionNameMatch::Contains(pattern) => fully_qualified_name
.contains(pattern)
FunctionNameMatch::Contains(patterns) => patterns
.iter()
.any(|pattern| fully_qualified_name.contains(pattern))
.then_some((fully_qualified_name, test_function)),
}
})
Expand Down
2 changes: 1 addition & 1 deletion tooling/lsp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ fn get_package_tests_in_crate(
let fm = &context.file_manager;
let files = fm.as_file_map();
let tests =
context.get_all_test_functions_in_crate_matching(crate_id, FunctionNameMatch::Anything);
context.get_all_test_functions_in_crate_matching(crate_id, &FunctionNameMatch::Anything);

let package_tests: Vec<_> = tests
.into_iter()
Expand Down
2 changes: 1 addition & 1 deletion tooling/lsp/src/requests/code_lens_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ pub(crate) fn collect_lenses_for_package(
let fm = &context.file_manager;
let files = fm.as_file_map();
let tests =
context.get_all_test_functions_in_crate_matching(&crate_id, FunctionNameMatch::Anything);
context.get_all_test_functions_in_crate_matching(&crate_id, &FunctionNameMatch::Anything);
for (func_name, test_function) in tests {
let location = context.function_meta(&test_function.get_id()).name.location;
let file_id = location.file;
Expand Down
2 changes: 1 addition & 1 deletion tooling/lsp/src/requests/test_run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ fn on_test_run_request_inner(

let test_functions = context.get_all_test_functions_in_crate_matching(
&crate_id,
FunctionNameMatch::Exact(function_name),
&FunctionNameMatch::Exact(vec![function_name.clone()]),
);

let (_, test_function) = test_functions.into_iter().next().ok_or_else(|| {
Expand Down
57 changes: 35 additions & 22 deletions tooling/nargo_cli/src/cli/test_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub(crate) mod formatters;
#[clap(visible_alias = "t")]
pub(crate) struct TestCommand {
/// If given, only tests with names containing this string will be run
test_name: Option<String>,
test_names: Vec<String>,

/// Display output of `println` statements
#[arg(long)]
Expand Down Expand Up @@ -125,15 +125,12 @@ pub(crate) fn run(args: TestCommand, config: NargoConfig) -> Result<(), CliError
insert_all_files_for_workspace_into_file_manager(&workspace, &mut file_manager);
let parsed_files = parse_all(&file_manager);

let pattern = match &args.test_name {
Some(name) => {
if args.exact {
FunctionNameMatch::Exact(name)
} else {
FunctionNameMatch::Contains(name)
}
}
None => FunctionNameMatch::Anything,
let pattern = if args.test_names.is_empty() {
FunctionNameMatch::Anything
} else if args.exact {
FunctionNameMatch::Exact(args.test_names.clone())
} else {
FunctionNameMatch::Contains(args.test_names.clone())
};

let formatter: Box<dyn Formatter> = if let Some(format) = args.format {
Expand Down Expand Up @@ -161,7 +158,7 @@ struct TestRunner<'a> {
parsed_files: &'a ParsedFiles,
workspace: Workspace,
args: &'a TestCommand,
pattern: FunctionNameMatch<'a>,
pattern: FunctionNameMatch,
num_threads: usize,
formatter: Box<dyn Formatter>,
}
Expand All @@ -186,15 +183,31 @@ impl<'a> TestRunner<'a> {

if tests_count == 0 {
match &self.pattern {
FunctionNameMatch::Exact(pattern) => {
return Err(CliError::Generic(format!(
"Found 0 tests matching input '{pattern}'.",
)))
FunctionNameMatch::Exact(patterns) => {
if patterns.len() == 1 {
return Err(CliError::Generic(format!(
"Found 0 tests matching '{}'.",
patterns.first().unwrap()
)));
} else {
return Err(CliError::Generic(format!(
"Found 0 tests matching any of {}.",
patterns.join(", "),
)));
}
}
FunctionNameMatch::Contains(pattern) => {
return Err(CliError::Generic(
format!("Found 0 tests containing '{pattern}'.",),
))
FunctionNameMatch::Contains(patterns) => {
if patterns.len() == 1 {
return Err(CliError::Generic(format!(
"Found 0 tests containing '{}'.",
patterns.first().unwrap()
)));
} else {
return Err(CliError::Generic(format!(
"Found 0 tests containing any of {}.",
patterns.join(", ")
)));
}
}
// If we are running all tests in a crate, having none is not an error
FunctionNameMatch::Anything => {}
Expand Down Expand Up @@ -459,7 +472,7 @@ impl<'a> TestRunner<'a> {
check_crate_and_report_errors(&mut context, crate_id, &self.args.compile_options)?;

Ok(context
.get_all_test_functions_in_crate_matching(&crate_id, self.pattern)
.get_all_test_functions_in_crate_matching(&crate_id, &self.pattern)
.into_iter()
.map(|(test_name, _)| test_name)
.collect())
Expand All @@ -483,8 +496,8 @@ impl<'a> TestRunner<'a> {
check_crate(&mut context, crate_id, &self.args.compile_options)
.expect("Any errors should have occurred when collecting test functions");

let test_functions = context
.get_all_test_functions_in_crate_matching(&crate_id, FunctionNameMatch::Exact(fn_name));
let pattern = FunctionNameMatch::Exact(vec![fn_name.to_string()]);
let test_functions = context.get_all_test_functions_in_crate_matching(&crate_id, &pattern);
let (_, test_function) = test_functions.first().expect("Test function should exist");

let blackbox_solver = S::default();
Expand Down
2 changes: 1 addition & 1 deletion tooling/nargo_cli/src/cli/test_cmd/formatters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ impl Formatter for PrettyFormatter {
}
};

write!(writer, "[{}] Testing {}... ", &test_result.package_name, &test_result.name)?;
write!(writer, "[{}] Testing {} ... ", &test_result.package_name, &test_result.name)?;
writer.flush()?;

match &test_result.status {
Expand Down
4 changes: 2 additions & 2 deletions tooling/nargo_cli/tests/stdlib-tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
impl Options {
pub fn function_name_match(&self) -> FunctionNameMatch {
match self.args.as_slice() {
[_test_name, lib] => FunctionNameMatch::Contains(lib.as_str()),
[_test_name, lib] => FunctionNameMatch::Contains(vec![lib.clone()]),
_ => FunctionNameMatch::Anything,
}
}
Expand All @@ -43,7 +43,7 @@
/// Inlining happens if `inline_cost - retain_cost < aggressiveness` (see `inlining.rs`).
/// NB the CLI uses maximum aggressiveness.
///
/// Even with the same inlining aggressiveness, forcing Brillig can trigger different behaviour.

Check warning on line 46 in tooling/nargo_cli/tests/stdlib-tests.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (behaviour)
#[test_matrix(
[false, true],
[i64::MIN, 0, i64::MAX]
Expand Down Expand Up @@ -78,7 +78,7 @@

let test_functions = context.get_all_test_functions_in_crate_matching(
context.stdlib_crate_id(),
opts.function_name_match(),
&opts.function_name_match(),
);

let test_report: Vec<(String, TestStatus)> = test_functions
Expand Down
Loading