#[cfg(test)]
pub mod tests {
use serde_json::Value;
use std::process::Command;
fn run_all_guards_json(features: &str, report: &str) -> Value {
let output = Command::new("cargo")
.env("HOTPATH_OUTPUT_FORMAT", "json")
.env("HOTPATH_REPORT", report)
.env("HOTPATH_METRICS_SERVER_OFF", "true")
.args([
"run",
"-p",
"test-smol-async",
"--example",
"all_guards",
"--features",
features,
])
.output()
.expect("Failed to execute command");
assert!(
output.status.success(),
"Process did not exit successfully.\n\nstderr:\n{}",
String::from_utf8_lossy(&output.stderr)
);
let stdout = String::from_utf8_lossy(&output.stdout);
serde_json::from_str(stdout.lines().last().expect("No JSON output line"))
.expect("Failed to parse JSON report")
}
fn assert_functions_present(report: &Value) {
let functions = report["functions_timing"]["data"]
.as_array()
.expect("Expected functions_timing.data array");
let expected = [
"all_guards::sync_plain",
"all_guards::sync_log",
"all_guards::async_plain",
"all_guards::async_log",
"all_guards::async_future",
"all_guards::async_future_log",
];
for name in expected {
let entry = functions
.iter()
.find(|f| f["name"].as_str() == Some(name))
.unwrap_or_else(|| panic!("Expected {name} in functions_timing"));
assert_eq!(
entry["calls"].as_u64(),
Some(3),
"Expected 3 calls for {name}"
);
}
}
fn assert_futures_present(report: &Value) {
let futures = report["futures"]["data"]
.as_array()
.expect("Expected futures.data array");
let with_future = ["all_guards::async_future", "all_guards::async_future_log"];
for source in with_future {
let entry = futures
.iter()
.find(|f| f["source"].as_str() == Some(source))
.unwrap_or_else(|| panic!("Expected future entry for {source}"));
assert_eq!(
entry["call_count"].as_u64(),
Some(3),
"Expected 3 calls for {source}"
);
}
let without_future = ["all_guards::async_plain", "all_guards::async_log"];
for source in without_future {
assert!(
futures.iter().all(|f| f["source"].as_str() != Some(source)),
"Did not expect future entry for {source}"
);
}
}
#[test]
fn test_measure_impl_guards_example_runs() {
let output = Command::new("cargo")
.env("HOTPATH_OUTPUT_FORMAT", "none")
.args([
"run",
"-p",
"test-smol-async",
"--example",
"all_guards",
"--features",
"hotpath,hotpath-alloc",
])
.output()
.expect("Failed to execute command");
assert!(
output.status.success(),
"Process did not exit successfully.\n\nstderr:\n{}",
String::from_utf8_lossy(&output.stderr)
);
}
#[test]
fn test_measure_impl_guards_json_hotpath() {
let report = run_all_guards_json("hotpath", "functions-timing,futures");
assert_functions_present(&report);
assert_futures_present(&report);
}
#[test]
fn test_measure_impl_guards_json_hotpath_alloc() {
let report = run_all_guards_json(
"hotpath,hotpath-alloc",
"functions-timing,functions-alloc,futures",
);
assert_functions_present(&report);
assert_futures_present(&report);
let functions_alloc = report["functions_alloc"]["data"]
.as_array()
.expect("Expected functions_alloc.data array");
let expected = [
"all_guards::sync_plain",
"all_guards::sync_log",
"all_guards::async_plain",
"all_guards::async_log",
"all_guards::async_future",
"all_guards::async_future_log",
];
for name in expected {
functions_alloc
.iter()
.find(|f| f["name"].as_str() == Some(name))
.unwrap_or_else(|| panic!("Expected {name} in functions_alloc"));
}
}
}