chore(xtask): extend CLI options

- It is now possible to pass a custom fuzzing duration and target
- Adds a `coverage install` action
This commit is contained in:
Benoît CORTIER 2023-05-10 10:02:59 -04:00 committed by Benoît Cortier
parent fce63eaf57
commit 368582ec5a
4 changed files with 91 additions and 34 deletions

3
.gitignore vendored
View file

@ -1,6 +1,9 @@
# Build artifacts
/target
# Local cargo root
/.cargo/local_root
# Log files
*.log

View file

@ -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<u32>,
target: Option<String>,
},
ShowHelp,
SvelteRun,
WasmInstall,
@ -61,22 +66,34 @@ pub fn parse_args() -> anyhow::Result<Action> {
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,

View file

@ -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)?,
}

View file

@ -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<u32>, target: Option<String>) -> 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