From 4eb11e2419cd1b3ea2d8e54513ec4011346a2c88 Mon Sep 17 00:00:00 2001 From: Felix Date: Sat, 20 Jun 2026 00:25:55 +0200 Subject: [PATCH] Export empty CSV columns for reference command parameters Fixes #852 --- src/export/csv.rs | 17 ++++++++++++++--- tests/integration_tests.rs | 23 +++++++++++++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/export/csv.rs b/src/export/csv.rs index a0cf8aa7d..4123cc828 100644 --- a/src/export/csv.rs +++ b/src/export/csv.rs @@ -21,6 +21,7 @@ impl Exporter for CsvExporter { ) -> Result> { let mut writer = WriterBuilder::new().from_writer(vec![]); + let mut num_params = 0; { let mut headers: Vec> = [ // The list of times and exit codes cannot be exported to the CSV file - omit them. @@ -29,7 +30,11 @@ impl Exporter for CsvExporter { .iter() .map(|x| Cow::Borrowed(x.as_bytes())) .collect(); - if let Some(res) = results.first() { + + // Use param column names from the first non-reference command + let non_ref = results.iter().find(|res| !res.parameters.is_empty()); + if let Some(res) = non_ref { + num_params = res.parameters.len(); for param_name in res.parameters.keys() { headers.push(Cow::Owned(format!("parameter_{param_name}").into_bytes())); } @@ -50,8 +55,14 @@ impl Exporter for CsvExporter { ] { fields.push(Cow::Owned(f.to_string().into_bytes())) } - for v in res.parameters.values() { - fields.push(Cow::Borrowed(v.as_bytes())) + if res.parameters.is_empty() && num_params > 0 { + // Reference command, insert an empty column for each param + let mut empties = vec![Cow::Borrowed("".as_bytes()); num_params]; + fields.append(&mut empties); + } else { + for v in res.parameters.values() { + fields.push(Cow::Borrowed(v.as_bytes())) + } } writer.write_record(fields)?; } diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index 2de3a5049..d21aaa6a7 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -705,6 +705,29 @@ fn speed_comparison_sort_order() { )); } +// Regression test for https://github.com/sharkdp/hyperfine/issues/852 +#[test] +fn csv_export_reference_command_with_parameters() { + hyperfine_debug() + .arg("--style=none") + .arg("--runs=1") + .arg("--reference=sleep 1") + .arg("--parameter-scan") + .arg("secs") + .arg("2") + .arg("3") + .arg("--export-csv") + .arg("-") + .arg("sleep {secs}") + .assert() + .success() + .stdout(predicate::str::starts_with( + r#" +command,mean,stddev,median,user,system,min,max,parameter_secs +sleep 1,1,0,1,0,0,1,1,"#, // Ends in empty value + )); +} + #[cfg(windows)] #[test] fn windows_quote_args() {