Cover JSON exports with integration snapshots

This commit is contained in:
David Peter committed 2026-10-05 20:42:13 +02:00
1 parent cb021e64b9
commit eedec07812
6 files changed
+557 -264

No files matched your search

+54 -80
View File
@@ -24,6 +24,17 @@ fn snapshot_settings() -> insta::Settings {
settings
}
fn json_snapshot_settings() -> insta::Settings {
let mut settings = snapshot_settings();
for field in ["hyperfine_version", "start_time", "os", "architecture"] {
settings.add_filter(
&format!(r#"("{field}": ")[^"]+(")"#),
format!(r#"${{1}}[{field}]$2"#),
);
}
settings
}
#[test]
fn runs_successfully() {
hyperfine()
@@ -42,86 +53,6 @@ fn one_run_is_supported() {
.success();
}
#[test]
fn json_includes_name_only_when_different() {
for (args, expected) in [
(vec!["sleep 0.01"], vec![("sleep 0.01", None)]),
(
vec!["--command-name=example", "sleep 0.01"],
vec![("sleep 0.01", Some("example"))],
),
(
vec!["--command-name=sleep 0.01", "sleep 0.01"],
vec![("sleep 0.01", None)],
),
(
vec![
"-L",
"delay",
"0.01,0.02",
"--command-name=delay {delay}",
"sleep {delay}",
],
vec![
("sleep 0.01", Some("delay 0.01")),
("sleep 0.02", Some("delay 0.02")),
],
),
(
vec![
"-L",
"delay",
"0.01,0.02",
"--command-name=sleep {delay}",
"sleep {delay}",
],
vec![("sleep 0.01", None), ("sleep 0.02", None)],
),
] {
let output = hyperfine_debug()
.args(["--runs=1", "--style=none", "--export-json=-"])
.args(args)
.output()
.unwrap();
assert!(output.status.success());
let export: serde_json::Value = serde_json::from_slice(&output.stdout).unwrap();
let results = export["results"].as_array().unwrap();
assert_eq!(results.len(), expected.len());
for (result, (command, name)) in results.iter().zip(expected) {
assert_eq!(result["command"], command);
assert!(result.get("command_raw").is_none());
assert_eq!(
result.get("name"),
name.map(serde_json::Value::from).as_ref()
);
}
}
}
#[test]
fn json_memory_availability_matches_platform() {
let output = hyperfine_raw_command()
.args([
"--runs=1",
"--style=none",
"--export-json=-",
"echo benchmark",
])
.output()
.unwrap();
assert!(output.status.success());
let export: serde_json::Value = serde_json::from_slice(&output.stdout).unwrap();
let measurement = &export["results"][0]["measurements"][0];
let memory = measurement.get("memory_peak_resident");
if cfg!(windows) {
assert!(memory.is_none(), "unavailable memory must be omitted");
} else {
let memory = memory.expect("Unix memory measurement must be present");
assert_eq!(memory["unit"], "byte");
assert!(memory["value"].as_f64().unwrap() >= 0.0);
}
}
/// Regression test: hyperfine must not panic when writing to a closed
/// stdout pipe (e.g. `hyperfine ... | head -n 1` or a downstream process
/// that terminates early). A `BrokenPipe` error should result in a quiet
@@ -1353,3 +1284,46 @@ fn hyperfine_iteration_env_var_in_prepare_and_conclude_commands() {
]
);
}
#[test]
fn json_export_basic() {
let _settings = json_snapshot_settings().bind_to_scope();
assert_cmd_snapshot!(hyperfine_debug().args([
"--style=none",
"--export-json=-",
"--runs=2",
"--warmup=1",
"--reference-name=one second",
"--reference=sleep 1",
"--command-name=sleep 2",
"sleep 2",
]));
}
#[test]
fn json_export_single_run() {
// Make sure that the standard deviation is set to `null`
let _settings = json_snapshot_settings().bind_to_scope();
assert_cmd_snapshot!(hyperfine_debug().args([
"--style=none",
"--export-json=-",
"--runs=1",
"sleep 1",
]));
}
#[test]
fn json_export_parameterized_with_reference() {
let _settings = json_snapshot_settings().bind_to_scope();
assert_cmd_snapshot!(hyperfine_debug().args([
"--style=none",
"--export-json=-",
"--runs=2",
"-L",
"duration",
"1,2",
"--command-name=sleep for {duration} seconds",
"--reference=sleep for 2 seconds",
"sleep {duration}",
]));
}
@@ -0,0 +1,199 @@
---
source: tests/integration_tests.rs
info:
program: hyperfine
args:
- "--debug-mode"
- "--style=none"
- "--export-json=-"
- "--runs=2"
- "--warmup=1"
- "--reference-name=one second"
- "--reference=sleep 1"
- "--command-name=sleep 2"
- sleep 2
---
success: true
exit_code: 0
----- stdout -----
{
"schema_version": 2,
"metadata": {
"hyperfine_version": "[hyperfine_version]",
"start_time": "[start_time]",
"platform": {
"os": "[os]",
"architecture": "[architecture]"
}
},
"results": [
{
"command": "sleep 1",
"name": "one second",
"measurements": [
{
"time_wall_clock": {
"value": 1.0,
"unit": "second"
},
"time_user": {
"value": 0.0,
"unit": "second"
},
"time_system": {
"value": 0.0,
"unit": "second"
},
"memory_peak_resident": {
"value": 0.0,
"unit": "byte"
},
"exit_code": 0
},
{
"time_wall_clock": {
"value": 1.0,
"unit": "second"
},
"time_user": {
"value": 0.0,
"unit": "second"
},
"time_system": {
"value": 0.0,
"unit": "second"
},
"memory_peak_resident": {
"value": 0.0,
"unit": "byte"
},
"exit_code": 0
}
],
"is_reference": true,
"summary": {
"time_wall_clock": {
"unit": "second",
"count": 2,
"mean": 1.0,
"stddev": 0.0,
"median": 1.0,
"min": 1.0,
"max": 1.0
},
"time_user": {
"unit": "second",
"count": 2,
"mean": 0.0,
"stddev": 0.0,
"median": 0.0,
"min": 0.0,
"max": 0.0
},
"time_system": {
"unit": "second",
"count": 2,
"mean": 0.0,
"stddev": 0.0,
"median": 0.0,
"min": 0.0,
"max": 0.0
},
"memory_peak_resident": {
"unit": "byte",
"count": 2,
"mean": 0.0,
"stddev": 0.0,
"median": 0.0,
"min": 0.0,
"max": 0.0
}
}
},
{
"command": "sleep 2",
"measurements": [
{
"time_wall_clock": {
"value": 2.0,
"unit": "second"
},
"time_user": {
"value": 0.0,
"unit": "second"
},
"time_system": {
"value": 0.0,
"unit": "second"
},
"memory_peak_resident": {
"value": 0.0,
"unit": "byte"
},
"exit_code": 0
},
{
"time_wall_clock": {
"value": 2.0,
"unit": "second"
},
"time_user": {
"value": 0.0,
"unit": "second"
},
"time_system": {
"value": 0.0,
"unit": "second"
},
"memory_peak_resident": {
"value": 0.0,
"unit": "byte"
},
"exit_code": 0
}
],
"summary": {
"time_wall_clock": {
"unit": "second",
"count": 2,
"mean": 2.0,
"stddev": 0.0,
"median": 2.0,
"min": 2.0,
"max": 2.0
},
"time_user": {
"unit": "second",
"count": 2,
"mean": 0.0,
"stddev": 0.0,
"median": 0.0,
"min": 0.0,
"max": 0.0
},
"time_system": {
"unit": "second",
"count": 2,
"mean": 0.0,
"stddev": 0.0,
"median": 0.0,
"min": 0.0,
"max": 0.0
},
"memory_peak_resident": {
"unit": "byte",
"count": 2,
"mean": 0.0,
"stddev": 0.0,
"median": 0.0,
"min": 0.0,
"max": 0.0
}
}
}
]
}
----- stderr -----
@@ -0,0 +1,211 @@
---
source: tests/integration_tests.rs
info:
program: hyperfine
args:
- "--debug-mode"
- "--style=none"
- "--export-json=-"
- "--runs=2"
- "-L"
- duration
- "1,2"
- "--command-name=sleep for {duration} seconds"
- "--reference=sleep for 2 seconds"
- "sleep {duration}"
---
success: true
exit_code: 0
----- stdout -----
{
"schema_version": 2,
"metadata": {
"hyperfine_version": "[hyperfine_version]",
"start_time": "[start_time]",
"platform": {
"os": "[os]",
"architecture": "[architecture]"
}
},
"results": [
{
"command": "sleep 1",
"name": "sleep for 1 seconds",
"measurements": [
{
"time_wall_clock": {
"value": 1.0,
"unit": "second"
},
"time_user": {
"value": 0.0,
"unit": "second"
},
"time_system": {
"value": 0.0,
"unit": "second"
},
"memory_peak_resident": {
"value": 0.0,
"unit": "byte"
},
"exit_code": 0
},
{
"time_wall_clock": {
"value": 1.0,
"unit": "second"
},
"time_user": {
"value": 0.0,
"unit": "second"
},
"time_system": {
"value": 0.0,
"unit": "second"
},
"memory_peak_resident": {
"value": 0.0,
"unit": "byte"
},
"exit_code": 0
}
],
"parameters": {
"duration": {
"value": "1"
}
},
"summary": {
"time_wall_clock": {
"unit": "second",
"count": 2,
"mean": 1.0,
"stddev": 0.0,
"median": 1.0,
"min": 1.0,
"max": 1.0
},
"time_user": {
"unit": "second",
"count": 2,
"mean": 0.0,
"stddev": 0.0,
"median": 0.0,
"min": 0.0,
"max": 0.0
},
"time_system": {
"unit": "second",
"count": 2,
"mean": 0.0,
"stddev": 0.0,
"median": 0.0,
"min": 0.0,
"max": 0.0
},
"memory_peak_resident": {
"unit": "byte",
"count": 2,
"mean": 0.0,
"stddev": 0.0,
"median": 0.0,
"min": 0.0,
"max": 0.0
}
}
},
{
"command": "sleep 2",
"name": "sleep for 2 seconds",
"measurements": [
{
"time_wall_clock": {
"value": 2.0,
"unit": "second"
},
"time_user": {
"value": 0.0,
"unit": "second"
},
"time_system": {
"value": 0.0,
"unit": "second"
},
"memory_peak_resident": {
"value": 0.0,
"unit": "byte"
},
"exit_code": 0
},
{
"time_wall_clock": {
"value": 2.0,
"unit": "second"
},
"time_user": {
"value": 0.0,
"unit": "second"
},
"time_system": {
"value": 0.0,
"unit": "second"
},
"memory_peak_resident": {
"value": 0.0,
"unit": "byte"
},
"exit_code": 0
}
],
"parameters": {
"duration": {
"value": "2"
}
},
"is_reference": true,
"summary": {
"time_wall_clock": {
"unit": "second",
"count": 2,
"mean": 2.0,
"stddev": 0.0,
"median": 2.0,
"min": 2.0,
"max": 2.0
},
"time_user": {
"unit": "second",
"count": 2,
"mean": 0.0,
"stddev": 0.0,
"median": 0.0,
"min": 0.0,
"max": 0.0
},
"time_system": {
"unit": "second",
"count": 2,
"mean": 0.0,
"stddev": 0.0,
"median": 0.0,
"min": 0.0,
"max": 0.0
},
"memory_peak_resident": {
"unit": "byte",
"count": 2,
"mean": 0.0,
"stddev": 0.0,
"median": 0.0,
"min": 0.0,
"max": 0.0
}
}
}
]
}
----- stderr -----
@@ -0,0 +1,93 @@
---
source: tests/integration_tests.rs
info:
program: hyperfine
args:
- "--debug-mode"
- "--style=none"
- "--export-json=-"
- "--runs=1"
- sleep 1
---
success: true
exit_code: 0
----- stdout -----
{
"schema_version": 2,
"metadata": {
"hyperfine_version": "[hyperfine_version]",
"start_time": "[start_time]",
"platform": {
"os": "[os]",
"architecture": "[architecture]"
}
},
"results": [
{
"command": "sleep 1",
"measurements": [
{
"time_wall_clock": {
"value": 1.0,
"unit": "second"
},
"time_user": {
"value": 0.0,
"unit": "second"
},
"time_system": {
"value": 0.0,
"unit": "second"
},
"memory_peak_resident": {
"value": 0.0,
"unit": "byte"
},
"exit_code": 0
}
],
"summary": {
"time_wall_clock": {
"unit": "second",
"count": 1,
"mean": 1.0,
"stddev": null,
"median": 1.0,
"min": 1.0,
"max": 1.0
},
"time_user": {
"unit": "second",
"count": 1,
"mean": 0.0,
"stddev": null,
"median": 0.0,
"min": 0.0,
"max": 0.0
},
"time_system": {
"unit": "second",
"count": 1,
"mean": 0.0,
"stddev": null,
"median": 0.0,
"min": 0.0,
"max": 0.0
},
"memory_peak_resident": {
"unit": "byte",
"count": 1,
"mean": 0.0,
"stddev": null,
"median": 0.0,
"min": 0.0,
"max": 0.0
}
}
}
]
}
----- stderr -----