Skip to content
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
2 changes: 1 addition & 1 deletion tooling/nargo/src/ops/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub use self::fuzz::{
FuzzExecutionConfig, FuzzFolderConfig, FuzzingRunStatus, run_fuzzing_harness,
};
pub use self::test::{
TestStatus, check_expected_failure_message, fuzz_test, run_or_fuzz_test, run_test,
FuzzConfig, TestStatus, check_expected_failure_message, fuzz_test, run_or_fuzz_test, run_test,
test_status_program_compile_fail, test_status_program_compile_pass,
};

Expand Down
39 changes: 33 additions & 6 deletions tooling/nargo/src/ops/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,20 @@ impl TestStatus {
}
}

pub struct FuzzConfig {
pub folder_config: FuzzFolderConfig,
}

/// Runs a test function. This will either run the test or fuzz it, depending on whether the function has arguments.
#[allow(clippy::too_many_arguments)]
pub fn run_or_fuzz_test<'a, W, B, F, E>(
blackbox_solver: &B,
context: &mut Context,
test_function: &TestFunction,
output: W,
package_name: String,
config: &CompileOptions,
fuzz_config: FuzzConfig,
build_foreign_call_executor: F,
) -> TestStatus
where
Expand All @@ -69,6 +75,7 @@ where
test_function,
package_name,
config,
fuzz_config,
build_foreign_call_executor,
)
} else {
Expand Down Expand Up @@ -186,6 +193,7 @@ pub fn fuzz_test<'a, B, F, E>(
test_function: &TestFunction,
package_name: String,
config: &CompileOptions,
fuzz_config: FuzzConfig,
build_foreign_call_executor: F,
) -> TestStatus
where
Expand All @@ -199,6 +207,7 @@ where
test_function,
package_name,
config,
fuzz_config,
build_foreign_call_executor,
),
Err(err) => test_status_program_compile_fail(err, test_function),
Expand All @@ -210,6 +219,7 @@ fn fuzz_test_impl<'a, B, F, E>(
test_function: &TestFunction,
package_name: String,
config: &CompileOptions,
fuzz_config: FuzzConfig,
build_foreign_call_executor: F,
) -> TestStatus
where
Expand All @@ -227,14 +237,26 @@ where
let location = test_function.location;
let fuzzing_harness = FuzzingHarness { id, scope, location };

let corpus_dir = tempfile::tempdir().expect("Couldn't create temporary directory");
let fuzzing_failure_dir = tempfile::tempdir().expect("Couldn't create temporary directory");
let mut temporary_dirs_to_delete = Vec::new();

let mut config_or_temporary_dir = |dir: Option<String>| match dir {
Some(ref dir) => PathBuf::from(dir),
None => {
let corpus_dir = tempfile::tempdir().expect("Couldn't create temporary directory");
let corpus_dir = corpus_dir.into_path();
temporary_dirs_to_delete.push(corpus_dir.clone());
corpus_dir
}
};

let corpus_dir = config_or_temporary_dir(fuzz_config.folder_config.corpus_dir);
let fuzzing_failure_dir =
config_or_temporary_dir(fuzz_config.folder_config.fuzzing_failure_dir);

// TODO: allow configuring this. See https://github.com/noir-lang/noir/issues/8214
let fuzz_folder_config = FuzzFolderConfig {
corpus_dir: Some(corpus_dir.path().to_string_lossy().to_string()),
minimized_corpus_dir: None,
fuzzing_failure_dir: Some(fuzzing_failure_dir.path().to_string_lossy().to_string()),
corpus_dir: Some(corpus_dir.to_string_lossy().to_string()),
fuzzing_failure_dir: Some(fuzzing_failure_dir.to_string_lossy().to_string()),
minimized_corpus_dir: fuzz_config.folder_config.minimized_corpus_dir,
};
// TODO: allow configuring this. See https://github.com/noir-lang/noir/issues/8214
let fuzz_execution_config =
Expand All @@ -253,6 +275,11 @@ where
build_foreign_call_executor,
);

for temporary_dir_to_delete in temporary_dirs_to_delete {
// Not a big deal if we can't delete a temporary directory
let _ = std::fs::remove_dir_all(temporary_dir_to_delete);
}

match fuzz_result {
FuzzingRunStatus::ExecutionPass | FuzzingRunStatus::MinimizationPass => TestStatus::Pass,
FuzzingRunStatus::CorpusFailure { message } => {
Expand Down
24 changes: 23 additions & 1 deletion tooling/nargo_cli/src/cli/test_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ use clap::Args;
use fm::FileManager;
use formatters::{Formatter, JsonFormatter, PrettyFormatter, TerseFormatter};
use nargo::{
FuzzFolderConfig,
foreign_calls::DefaultForeignCallBuilder,
insert_all_files_for_workspace_into_file_manager,
ops::{TestStatus, check_crate_and_report_errors},
ops::{FuzzConfig, TestStatus, check_crate_and_report_errors},
package::Package,
parse_all, prepare_package,
workspace::Workspace,
Expand Down Expand Up @@ -79,6 +80,18 @@ pub(crate) struct TestCommand {
/// Only run fuzz tests (tests that have arguments)
#[clap(long, conflicts_with("no_fuzz"))]
only_fuzz: bool,

/// If given, load/store fuzzer corpus from this folder
#[arg(long)]
corpus_dir: Option<String>,

/// If given, perform corpus minimization instead of fuzzing and store results in the given folder
#[arg(long)]
minimized_corpus_dir: Option<String>,

/// If given, store the failing input in the given folder
#[arg(long)]
fuzzing_failure_dir: Option<String>,
}

impl WorkspaceCommand for TestCommand {
Expand Down Expand Up @@ -542,13 +555,22 @@ impl<'a> TestRunner<'a> {
let blackbox_solver = S::default();
let mut output_buffer = Vec::new();

let fuzz_config = FuzzConfig {
folder_config: FuzzFolderConfig {
corpus_dir: self.args.corpus_dir.clone(),
minimized_corpus_dir: self.args.minimized_corpus_dir.clone(),
fuzzing_failure_dir: self.args.fuzzing_failure_dir.clone(),
},
};

let test_status = nargo::ops::run_or_fuzz_test(
&blackbox_solver,
&mut context,
test_function,
&mut output_buffer,
package_name.clone(),
&self.args.compile_options,
fuzz_config,
|output, base| {
DefaultForeignCallBuilder {
output,
Expand Down
Loading