From 368582ec5ade8be2a31a8e90f99f5750d792239c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20CORTIER?= Date: Wed, 10 May 2023 10:02:59 -0400 Subject: [PATCH] chore(xtask): extend CLI options - It is now possible to pass a custom fuzzing duration and target - Adds a `coverage install` action --- .gitignore | 3 +++ xtask/src/cli.rs | 61 +++++++++++++++++++++++++++++----------------- xtask/src/main.rs | 7 +++--- xtask/src/tasks.rs | 54 +++++++++++++++++++++++++++++++++------- 4 files changed, 91 insertions(+), 34 deletions(-) diff --git a/.gitignore b/.gitignore index 05146457..92351b60 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ # Build artifacts /target +# Local cargo root +/.cargo/local_root + # Log files *.log diff --git a/xtask/src/cli.rs b/xtask/src/cli.rs index cf6e8019..64378a87 100644 --- a/xtask/src/cli.rs +++ b/xtask/src/cli.rs @@ -8,21 +8,22 @@ FLAGS: -h, --help Prints help information TASKS: - check [all] Runs all checks - check fmt Checks formatting - check lints Checks lints - check tests Runs tests - check wasm Ensures wasm module is compatible for the web - ci Runs all checks required on CI - clean Clean workspace - coverage Generate code-coverage data using tests and fuzz targets - fuzz corpus-fetch Minify fuzzing corpus - fuzz corpus-min Minify fuzzing corpus - fuzz corpus-push Minify fuzzing corpus - fuzz install Install dependencies required for fuzzing - fuzz run Fuzz all targets for a few seconds - svelte-run Runs SvelteKit-based standalone Web Client - wasm install Install dependencies required to build the wasm target + check [all] Runs all checks + check fmt Checks formatting + check lints Checks lints + check tests Runs tests + check wasm Ensures wasm module is compatible for the web + ci Runs all checks required on CI + clean Clean workspace + coverage install Install dependencies required to generate the coverage report + coverage report Generate code-coverage data using tests and fuzz targets + fuzz corpus-fetch Minify fuzzing corpus + fuzz corpus-min Minify fuzzing corpus + fuzz corpus-push Minify fuzzing corpus + fuzz install Install dependencies required for fuzzing + fuzz run [--duration] [--target] Fuzz a specific target if any or all targets for a limited duration (default is 5s) + svelte-run Runs SvelteKit-based standalone Web Client + wasm install Install dependencies required to build the wasm target "; pub fn print_help() { @@ -36,12 +37,16 @@ pub enum Action { CheckTests, CheckWasm, Clean, - Coverage, + CoverageInstall, + CoverageReport, FuzzCorpusFetch, FuzzCorpusMin, FuzzCorpusPush, FuzzInstall, - FuzzRun, // TODO: add option to choose the target and run duration so we can optimize CI further + FuzzRun { + duration: Option, + target: Option, + }, ShowHelp, SvelteRun, WasmInstall, @@ -61,22 +66,34 @@ pub fn parse_args() -> anyhow::Result { Some("lints") => Action::CheckLints, Some("tests") => Action::CheckTests, Some("wasm") => Action::CheckWasm, - Some(_) => anyhow::bail!("Unknown check action"), + Some(_) => anyhow::bail!("unknown check action"), }, Some("clean") => Action::Clean, - Some("coverage") => Action::Coverage, + Some("coverage") => match args.subcommand()?.as_deref() { + Some("install") => Action::CoverageInstall, + Some("report") => Action::CoverageReport, + Some(_) => anyhow::bail!("unknown coverage action"), + None => Action::ShowHelp, + }, Some("fuzz") => match args.subcommand()?.as_deref() { Some("corpus-fetch") => Action::FuzzCorpusFetch, Some("corpus-min") => Action::FuzzCorpusMin, Some("corpus-push") => Action::FuzzCorpusPush, - Some("run") | None => Action::FuzzRun, + Some("run") => Action::FuzzRun { + duration: args.opt_value_from_str("--duration")?, + target: args.opt_value_from_str("--target")?, + }, + None => Action::FuzzRun { + duration: None, + target: None, + }, Some("install") => Action::FuzzInstall, - Some(_) => anyhow::bail!("Unknown fuzz action"), + Some(_) => anyhow::bail!("unknown fuzz action"), }, Some("svelte-run") => Action::SvelteRun, Some("wasm") => match args.subcommand()?.as_deref() { Some("install") => Action::WasmInstall, - Some(_) => anyhow::bail!("Unknown wasm action"), + Some(_) => anyhow::bail!("unknown wasm action"), None => Action::ShowHelp, }, None | Some(_) => Action::ShowHelp, diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 0e7edcd7..ba97f6b0 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -28,19 +28,20 @@ fn main() -> anyhow::Result<()> { tasks::run_tests(&sh)?; tasks::check_lints(&sh)?; tasks::check_wasm(&sh)?; - tasks::fuzz_run(&sh)?; + tasks::fuzz_run(&sh, None, None)?; } Action::CheckFmt => tasks::check_formatting(&sh)?, Action::CheckLints => tasks::check_lints(&sh)?, Action::CheckTests => tasks::run_tests(&sh)?, Action::CheckWasm => tasks::check_wasm(&sh)?, Action::Clean => tasks::clean_workspace(&sh)?, - Action::Coverage => tasks::report_code_coverage(&sh)?, + Action::CoverageInstall => tasks::coverage_install(&sh)?, + Action::CoverageReport => tasks::coverage_report(&sh)?, Action::FuzzCorpusFetch => tasks::fuzz_corpus_fetch(&sh)?, Action::FuzzCorpusMin => tasks::fuzz_corpus_minify(&sh)?, Action::FuzzCorpusPush => tasks::fuzz_corpus_push(&sh)?, Action::FuzzInstall => tasks::fuzz_install(&sh)?, - Action::FuzzRun => tasks::fuzz_run(&sh)?, + Action::FuzzRun { duration, target } => tasks::fuzz_run(&sh, duration, target)?, Action::SvelteRun => tasks::svelte_run(&sh)?, Action::WasmInstall => tasks::wasm_install(&sh)?, } diff --git a/xtask/src/tasks.rs b/xtask/src/tasks.rs index ced3eb19..f0fe279a 100644 --- a/xtask/src/tasks.rs +++ b/xtask/src/tasks.rs @@ -5,7 +5,8 @@ use crate::section::Section; const CARGO: &str = env!("CARGO"); const CARGO_FUZZ_VERSION: &str = "0.11.2"; -const LOCAL_CARGO_ROOT: &str = "./target/local_root/"; +const GRCOV_VERSION: &str = "0.8.18"; +const LOCAL_CARGO_ROOT: &str = ".cargo/local_root/"; const WASM_PACKAGES: &[&str] = &["ironrdp-web"]; const FUZZ_TARGETS: &[&str] = &["pdu_decoding", "rle_decompression", "bitmap_stream"]; @@ -65,15 +66,24 @@ pub fn check_wasm(sh: &Shell) -> anyhow::Result<()> { Ok(()) } -pub fn fuzz_run(sh: &Shell) -> anyhow::Result<()> { +pub fn fuzz_run(sh: &Shell, duration: Option, target: Option) -> anyhow::Result<()> { let _s = Section::new("FUZZ-RUN"); let _guard = sh.push_dir("./fuzz"); - for target in FUZZ_TARGETS { + let duration = duration.unwrap_or(5).to_string(); + let target_from_user = target.as_deref().map(|value| [value]); + + let targets = if let Some(targets) = &target_from_user { + targets + } else { + FUZZ_TARGETS + }; + + for target in targets { cmd!( sh, - "../target/local_root/bin/cargo-fuzz run {target} -- -max_total_time=5s" + "../{LOCAL_CARGO_ROOT}/bin/cargo-fuzz run {target} -- -max_total_time={duration}" ) .env("RUSTUP_TOOLCHAIN", "nightly") .run()?; @@ -90,7 +100,9 @@ pub fn fuzz_corpus_minify(sh: &Shell) -> anyhow::Result<()> { let _guard = sh.push_dir("./fuzz"); for target in FUZZ_TARGETS { - cmd!(sh, "rustup run nightly cargo fuzz cmin {target}").run()?; + cmd!(sh, "../{LOCAL_CARGO_ROOT}/bin/cargo-fuzz cmin {target}") + .env("RUSTUP_TOOLCHAIN", "nightly") + .run()?; } Ok(()) @@ -163,8 +175,30 @@ pub fn svelte_run(sh: &Shell) -> anyhow::Result<()> { Ok(()) } -pub fn report_code_coverage(sh: &Shell) -> anyhow::Result<()> { - let _s = Section::new("COVERAGE"); +pub fn coverage_install(sh: &Shell) -> anyhow::Result<()> { + let _s = Section::new("COVERAGE-INSTALL"); + + cmd!(sh, "rustup install nightly --profile=minimal").run()?; + cmd!(sh, "rustup component add --toolchain nightly llvm-tools-preview").run()?; + cmd!(sh, "rustup component add llvm-tools-preview").run()?; + + cmd!( + sh, + "{CARGO} install --debug --locked --root {LOCAL_CARGO_ROOT} cargo-fuzz@{CARGO_FUZZ_VERSION}" + ) + .run()?; + + cmd!( + sh, + "{CARGO} install --debug --locked --root {LOCAL_CARGO_ROOT} grcov@{GRCOV_VERSION}" + ) + .run()?; + + Ok(()) +} + +pub fn coverage_report(sh: &Shell) -> anyhow::Result<()> { + let _s = Section::new("COVERAGE-REPORT"); println!("Remove leftovers"); sh.remove_path("./fuzz/coverage/")?; @@ -180,7 +214,9 @@ pub fn report_code_coverage(sh: &Shell) -> anyhow::Result<()> { cmd!(sh, "{CARGO} clean").run()?; for target in FUZZ_TARGETS { - cmd!(sh, "rustup run nightly cargo fuzz coverage {target}").run()?; + cmd!(sh, "../{LOCAL_CARGO_ROOT}/bin/cargo-fuzz coverage {target}") + .env("RUSTUP_TOOLCHAIN", "nightly") + .run()?; } cmd!(sh, "cp -r ./target ../coverage/binaries/").run()?; @@ -204,7 +240,7 @@ pub fn report_code_coverage(sh: &Shell) -> anyhow::Result<()> { cmd!( sh, - "grcov . ./fuzz + "./{LOCAL_CARGO_ROOT}/bin/grcov . ./fuzz --source-dir . --binary-path ./coverage/binaries/ --output-type html