Skip to content
Open
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
10 changes: 4 additions & 6 deletions bin/cargo-bolero/src/build_clusterfuzz.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{list::List, project::Project};
use crate::list::List;
use anyhow::{Context, Result};
use std::{
collections::{hash_map::DefaultHasher, HashMap},
Expand All @@ -12,7 +12,7 @@ use structopt::StructOpt;
#[derive(Debug, StructOpt)]
pub struct BuildClusterfuzz {
#[structopt(flatten)]
project: Project,
list: List,
}

impl BuildClusterfuzz {
Expand All @@ -34,9 +34,7 @@ impl BuildClusterfuzz {
);

// Figure out the list of fuzz targets, grouped by which test executable they use
let targets = List::new(self.project.clone())
.list()
.context("listing fuzz targets")?;
let targets = self.list.list().context("listing fuzz targets")?;
let mut targets_per_exe = HashMap::new();
for t in targets {
targets_per_exe
Expand All @@ -54,7 +52,7 @@ impl BuildClusterfuzz {
let dir = PathBuf::from(format!("{}-{:x}", list_bin, hash));

let fuzz_exe =
crate::libfuzzer::build(self.project.clone(), tests[0].test_name.clone())
crate::libfuzzer::build(self.list.project().clone(), tests[0].test_name.clone())
.context("building to-be-fuzzed executable")?;
// .cargo extension is not an ALLOWED_FUZZ_TARGET_EXTENSIONS for clusterfuzz, so it doesn’t get picked up as a fuzzer
let fuzz_bin = format!("{}.cargo", fuzz_exe.file_name().unwrap().to_string_lossy());
Expand Down
16 changes: 5 additions & 11 deletions bin/cargo-bolero/src/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,16 @@ pub struct List {
}

impl List {
pub fn new(project: Project) -> Self {
Self { project }
pub fn project(&self) -> &Project {
&self.project
}

pub fn list(&self) -> Result<Vec<TestTarget>> {
let mut build_command = self.cmd("test", &[], None)?;
build_command.arg("--no-run");
let build_command = self.cmd("test", false, &["--no-run"], &[], None)?;
exec(build_command)?;

let output = self
.cmd("test", &[], None)?
.arg("--no-fail-fast")
.arg("--")
.arg("--nocapture")
.env("CARGO_BOLERO_SELECT", "all")
.output()?;
let mut cmd = self.cmd("test", true, &["--no-fail-fast"], &[], None)?;
let output = cmd.env("CARGO_BOLERO_SELECT", "all").output()?;
// ignore the status in case any tests failed

TestTarget::all_from_stdout(&output.stdout)
Expand Down
69 changes: 62 additions & 7 deletions bin/cargo-bolero/src/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ pub struct Project {
#[structopt(short, long)]
package: Option<String>,

/// Whether to run tests for the whole workspace
#[structopt(long)]
workspace: bool,

/// Path to Cargo.toml
#[structopt(long)]
manifest_path: Option<String>,
Expand All @@ -60,6 +64,14 @@ pub struct Project {
/// Fake using a nightly toolchain while using the default toolchain by using RUSTC_BOOTSTRAP
#[structopt(long)]
rustc_bootstrap: bool,

/// Use cargo nextest instead of cargo test
#[structopt(long)]
use_nextest: bool,

/// Set a specific nextest profile, eg. to set a one second timeout for listing fuzzers
#[structopt(long)]
nextest_profile: Option<String>,
}

impl Project {
Expand All @@ -86,11 +98,38 @@ impl Project {
}
}

pub fn cmd(&self, call: &str, flags: &[&str], fuzzer: Option<&str>) -> Result<Command> {
pub fn cmd(
&self,
call: &str,
no_capture: bool,
cargoflags: &[&str],
rustflags: &[&str],
fuzzer: Option<&str>,
) -> Result<Command> {
let mut cmd = self.cargo();

cmd.arg(call).arg("--target").arg(&self.target);
cmd.arg("--profile").arg(&self.profile);
let use_nextest = self.use_nextest && call == "test";

if use_nextest {
cmd.arg("nextest").arg("run");
} else {
cmd.arg(call);
}

cmd.arg("--target").arg(&self.target);

if use_nextest {
cmd.arg("--cargo-profile").arg(&self.profile);
if let Some(nextest_profile) = &self.nextest_profile {
cmd.arg("--profile").arg(nextest_profile);
}
} else {
anyhow::ensure!(
self.nextest_profile.is_none(),
"Requested nextest profile without using nextest"
);
cmd.arg("--profile").arg(&self.profile);
}

if self.no_default_features {
cmd.arg("--no-default-features");
Expand All @@ -104,6 +143,10 @@ impl Project {
cmd.arg("--features").arg(value);
}

if self.workspace {
cmd.arg("--workspace");
}

if let Some(value) = self.package.as_ref() {
cmd.arg("--package").arg(value);
}
Expand All @@ -113,13 +156,13 @@ impl Project {
}

if let Some(fuzzer) = fuzzer {
let rustflags = self.rustflags("RUSTFLAGS", flags)?;
let final_rustflags = self.rustflags("RUSTFLAGS", rustflags)?;

if let Some(value) = self.target_dir.as_ref() {
cmd.arg("--target-dir").arg(value);
} else {
let mut hasher = DefaultHasher::new();
rustflags.hash(&mut hasher);
final_rustflags.hash(&mut hasher);
cmd.arg("--target-dir")
.arg(format!("target/fuzz/build_{:x}", hasher.finish()));
}
Expand All @@ -128,11 +171,23 @@ impl Project {
cmd.arg("-Zbuild-std");
}

cmd.env("RUSTFLAGS", rustflags)
.env("RUSTDOCFLAGS", self.rustflags("RUSTDOCFLAGS", flags)?)
cmd.env("RUSTFLAGS", final_rustflags)
.env("RUSTDOCFLAGS", self.rustflags("RUSTDOCFLAGS", rustflags)?)
.env("BOLERO_FUZZER", fuzzer);
}

for f in cargoflags {
cmd.arg(f);
}

if no_capture {
if use_nextest {
cmd.arg("--no-capture");
} else {
cmd.arg("--").arg("--nocapture");
}
}

Ok(cmd)
}

Expand Down
4 changes: 2 additions & 2 deletions bin/cargo-bolero/src/selection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ impl Selection {
}

pub fn test_target(&self, flags: &[&str], fuzzer: &str) -> Result<TestTarget> {
let mut build_command = self.cmd("test", flags, Some(fuzzer))?;
let mut build_command = self.cmd("test", false, &[], flags, Some(fuzzer))?;
build_command
.arg(&self.test)
.arg("--no-run")
.arg("--")
.arg("--exact");
exec(build_command)?;

let mut output_command = self.cmd("test", flags, Some(fuzzer))?;
let mut output_command = self.cmd("test", false, &[], flags, Some(fuzzer))?;
output_command
.arg(&self.test)
.arg("--")
Expand Down
Loading