diff --git a/src/hyperfine/benchmark.rs b/src/hyperfine/benchmark.rs index ff94bf7..4271366 100644 --- a/src/hyperfine/benchmark.rs +++ b/src/hyperfine/benchmark.rs @@ -6,7 +6,7 @@ use ansi_term::Colour::{Cyan, Green, Purple, White, Yellow}; use statistical::{mean, standard_deviation}; use hyperfine::internal::{get_progress_bar, max, min, HyperfineOptions, Second, Warnings, - MIN_EXECUTION_TIME}; + MIN_EXECUTION_TIME, CmdFailureAction}; use hyperfine::format::{format_duration, format_duration_unit, Unit}; /// Results from timing a single shell command @@ -30,7 +30,7 @@ impl TimingResult { /// Run the given shell command and measure the execution time pub fn time_shell_command( shell_cmd: &str, - ignore_failure: bool, + failure_action: CmdFailureAction, shell_spawning_time: Option, ) -> io::Result { let start = Instant::now(); @@ -43,7 +43,7 @@ pub fn time_shell_command( .stderr(Stdio::null()) .status()?; - if !ignore_failure && !status.success() { + if failure_action == CmdFailureAction::RaiseError && !status.success() { return Err(io::Error::new( io::ErrorKind::Other, "Command terminated with non-zero exit code. \ @@ -80,7 +80,7 @@ pub fn mean_shell_spawning_time() -> io::Result { let mut times: Vec = vec![]; for _ in 0..COUNT { // Just run the shell without any command - let res = time_shell_command("", false, None); + let res = time_shell_command("", CmdFailureAction::RaiseError, None); match res { Err(_) => { @@ -124,7 +124,7 @@ pub fn run_benchmark( let bar = get_progress_bar(options.warmup_count, "Performing warmup runs"); for _ in 0..options.warmup_count { - let _ = time_shell_command(cmd, options.ignore_failure, None)?; + let _ = time_shell_command(cmd, options.failure_action, None)?; bar.inc(1); } bar.finish_and_clear(); @@ -136,13 +136,13 @@ pub fn run_benchmark( // Run init / cleanup command let run_preparation_command = || { if let Some(ref preparation_command) = options.preparation_command { - let _ = time_shell_command(preparation_command, options.ignore_failure, None); + let _ = time_shell_command(preparation_command, options.failure_action, None); } }; run_preparation_command(); // Initial timing run - let res = time_shell_command(cmd, options.ignore_failure, Some(shell_spawning_time))?; + let res = time_shell_command(cmd, options.failure_action, Some(shell_spawning_time))?; // Determine number of benchmark runs let runs_in_min_time = @@ -173,7 +173,7 @@ pub fn run_benchmark( }; bar.set_message(&msg); - let res = time_shell_command(cmd, options.ignore_failure, Some(shell_spawning_time))?; + let res = time_shell_command(cmd, options.failure_action, Some(shell_spawning_time))?; execution_times.push(res.execution_time); all_succeeded = all_succeeded && res.success; diff --git a/src/hyperfine/internal.rs b/src/hyperfine/internal.rs index be3d446..7f1355d 100644 --- a/src/hyperfine/internal.rs +++ b/src/hyperfine/internal.rs @@ -8,6 +8,16 @@ pub type Second = f64; /// Threshold for warning about fast execution time pub const MIN_EXECUTION_TIME: Second = 5e-3; +/// Action to take when an executed command fails. +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum CmdFailureAction { + /// Exit with an error message + RaiseError, + + /// Simply ignore the non-zero exit code + Ignore, +} + /// A set of options for hyperfine pub struct HyperfineOptions { /// Number of warmup runs @@ -20,7 +30,7 @@ pub struct HyperfineOptions { pub min_time_sec: Second, /// Whether or not to ignore non-zero exit codes - pub ignore_failure: bool, + pub failure_action: CmdFailureAction, /// Command to run before each timing run pub preparation_command: Option, @@ -32,7 +42,7 @@ impl Default for HyperfineOptions { warmup_count: 0, min_runs: 10, min_time_sec: 3.0, - ignore_failure: false, + failure_action: CmdFailureAction::RaiseError, preparation_command: None, } } diff --git a/src/main.rs b/src/main.rs index deee960..439bf22 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,7 +13,7 @@ use clap::{App, AppSettings, Arg}; mod hyperfine; -use hyperfine::internal::HyperfineOptions; +use hyperfine::internal::{HyperfineOptions, CmdFailureAction}; use hyperfine::benchmark::{mean_shell_spawning_time, run_benchmark}; /// Print error message to stderr and terminate @@ -109,7 +109,9 @@ fn main() { options.preparation_command = matches.value_of("prepare").map(String::from); - options.ignore_failure = matches.is_present("ignore-failure"); + if matches.is_present("ignore-failure") { + options.failure_action = CmdFailureAction::Ignore; + } let commands = matches.values_of("command").unwrap().collect(); let res = run(&commands, &options);