Skip to content

Commit

Permalink
Merge pull request #357 from kdarkhan/no-workspace
Browse files Browse the repository at this point in the history
Enable use of cargo-fuzz without a separate workspace
  • Loading branch information
fitzgen authored Jan 12, 2024
2 parents cdd6e41 + 2d04dca commit 56bcbcf
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 13 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ $ cargo install -f cargo-fuzz

Initialize a `cargo fuzz` project for your crate!

### Add `fuzz` directory to `workspace.members` in root `Cargo.toml`

`fuzz` directory can be either a part of an existing workspace (default)
or use an independent workspace. If latter is desired, you can use
`cargo fuzz init --fuzzing-workspace=true`.

### `cargo fuzz add <target>`

Create a new fuzzing target!
Expand Down
4 changes: 4 additions & 0 deletions src/options/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ pub struct Init {
/// Name of the first fuzz target to create
pub target: String,

#[arg(long, value_parser = clap::builder::BoolishValueParser::new(), default_value = "false")]
/// Whether to create a separate workspace for fuzz targets crate
pub fuzzing_workspace: Option<bool>,

#[command(flatten)]
pub fuzz_dir_wrapper: FuzzDirWrapper,
}
Expand Down
8 changes: 6 additions & 2 deletions src/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,11 @@ impl FuzzProject {
let mut cargo = fs::File::create(&cargo_toml)
.with_context(|| format!("failed to create {}", cargo_toml.display()))?;
cargo
.write_fmt(toml_template!(manifest.crate_name, manifest.edition))
.write_fmt(toml_template!(
manifest.crate_name,
manifest.edition,
init.fuzzing_workspace
))
.with_context(|| format!("failed to write to {}", cargo_toml.display()))?;

let gitignore = fuzz_project.join(".gitignore");
Expand Down Expand Up @@ -137,7 +141,7 @@ impl FuzzProject {
.arg(&build.triple);
// we default to release mode unless debug mode is explicitly requested
if !build.dev {
cmd.arg("--release");
cmd.args(["--release", "--config", "profile.release.debug=true"]);
}
if build.verbose {
cmd.arg("--verbose");
Expand Down
21 changes: 12 additions & 9 deletions src/templates.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
macro_rules! toml_template {
($name:expr, $edition:expr) => {
($name:expr, $edition:expr, $fuzzing_workspace:expr) => {
format_args!(
r##"[package]
name = "{name}-fuzz"
Expand All @@ -14,20 +14,22 @@ libfuzzer-sys = "0.4"
[dependencies.{name}]
path = ".."
# Prevent this from interfering with workspaces
[workspace]
members = ["."]
[profile.release]
debug = 1
"##,
{workspace}"##,
name = $name,
edition = if let Some(edition) = &$edition {
format!("edition = \"{}\"\n", edition)
} else {
String::new()
},
workspace = if let Some(true) = $fuzzing_workspace {
r##"
# Use independent workspace for fuzzers
[workspace]
members = ["."]
"##
} else {
""
}
)
};
}
Expand All @@ -41,6 +43,7 @@ name = "{0}"
path = "fuzz_targets/{0}.rs"
test = false
doc = false
bench = false
"#,
$name
)
Expand Down
33 changes: 31 additions & 2 deletions tests/tests/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,35 @@ fn help() {
}

#[test]
fn init() {
fn init_with_workspace() {
let project = project("init").build();
project
.cargo_fuzz()
.arg("init")
.arg("--fuzzing-workspace=true")
.assert()
.success();
assert!(project.fuzz_dir().is_dir());
assert!(project.fuzz_cargo_toml().is_file());
assert!(project.fuzz_targets_dir().is_dir());
assert!(project.fuzz_target_path("fuzz_target_1").is_file());
project
.cargo_fuzz()
.arg("run")
.arg("fuzz_target_1")
.arg("--")
.arg("-runs=1")
.assert()
.success();
}

#[test]
fn init_no_workspace() {
let mut project_builder = project("init_no_workspace");
let project = project_builder.build();
project.cargo_fuzz().arg("init").assert().success();
project_builder.set_workspace_members(&["fuzz"]);

assert!(project.fuzz_dir().is_dir());
assert!(project.fuzz_cargo_toml().is_file());
assert!(project.fuzz_targets_dir().is_dir());
Expand All @@ -28,20 +54,23 @@ fn init() {
.cargo_fuzz()
.arg("run")
.arg("fuzz_target_1")
.arg("--fuzz-dir")
.arg(project.fuzz_dir().to_str().unwrap())
.arg("--")
.arg("-runs=1")
.assert()
.success();
}

#[test]
fn init_with_target() {
fn init_with_target_and_workspace() {
let project = project("init_with_target").build();
project
.cargo_fuzz()
.arg("init")
.arg("-t")
.arg("custom_target_name")
.arg("--fuzzing-workspace=true")
.assert()
.success();
assert!(project.fuzz_dir().is_dir());
Expand Down
20 changes: 20 additions & 0 deletions tests/tests/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,26 @@ impl ProjectBuilder {
self.file(path, body)
}

pub fn set_workspace_members(&mut self, members: &[&str]) -> &mut Self {
let cargo_toml = self.root().join("Cargo.toml");
let manifest = fs::read_to_string(cargo_toml.clone()).unwrap();

let with_members = manifest.replace(
"[workspace]",
&format!(
"[workspace]\nmembers=[{}]",
members
.iter()
.map(|&v| format!("\"{}\"", v))
.collect::<Vec<_>>()
.join(", ")
),
);

fs::write(cargo_toml, with_members).unwrap();
self
}

pub fn file<B: AsRef<Path>>(&mut self, path: B, body: &str) -> &mut Self {
self._file(path.as_ref(), body);
self
Expand Down

0 comments on commit 56bcbcf

Please sign in to comment.