use std::fs;
use std::path::PathBuf;
use std::sync::atomic::{AtomicU64, Ordering};
use super::*;
static COUNTER: AtomicU64 = AtomicU64::new(0);
fn temp_root() -> PathBuf {
let n = COUNTER.fetch_add(1, Ordering::Relaxed);
std::env::temp_dir().join(format!("nam-coverage-{}-{n}", std::process::id()))
}
fn crit_log() -> &'static str {
"Benchmarking RT_A: Warming up for 1.0000 s\n\
Benchmarking RT_A: Collecting 100 samples\n\
Benchmarking RT_B: Warming up for 1.0000 s\n\
Benchmarking RT_C: Warming up for 1.0000 s\n"
}
#[test]
fn tests_long_f24_cases_are_mirrored() {
let crit = temp_root();
for id in ["RT_A", "RT_B"] {
fs::create_dir_all(crit.join(id).join("ci-baseline")).unwrap();
}
let missing = missing_baseline_coverage(crit_log(), &crit, "ci-baseline").unwrap();
assert_eq!(missing, vec!["RT_C".to_string()]);
assert_eq!(executed_bench_ids(crit_log()), ["RT_A", "RT_B", "RT_C"]);
fs::create_dir_all(crit.join("RT_C").join("ci-baseline")).unwrap();
assert_eq!(
missing_baseline_coverage(crit_log(), &crit, "ci-baseline").unwrap(),
Vec::<String>::new()
);
assert_eq!(
missing_baseline_coverage(
"garbage log with no criterion lines\n",
&crit,
"ci-baseline"
),
Err(BaselineCoverageGap)
);
assert_eq!(
missing_baseline_coverage("", &crit, "ci-baseline"),
Err(BaselineCoverageGap)
);
}
#[test]
fn sed_requires_prefix_and_colon() {
let log = "Warming up for 1.0000 s\n\
Benchmarking RT_A without a colon\n\
Benchmarking RT_B: Collecting 100 samples\n";
assert_eq!(executed_bench_ids(log), ["RT_B"]);
}
#[test]
fn id_capture_stops_at_first_colon_and_is_raw() {
let log = "Benchmarking RT_X_1:2:3: more\nBenchmarking RT_A : x\n";
assert_eq!(executed_bench_ids(log), ["RT_A ", "RT_X_1"]);
}
#[test]
fn ids_are_deduplicated_and_sorted() {
let log =
"Benchmarking RT_C: a\nBenchmarking RT_A: b\nBenchmarking RT_C: c\nBenchmarking RT_B: d\n";
assert_eq!(executed_bench_ids(log), ["RT_A", "RT_B", "RT_C"]);
}
#[test]
fn missing_list_preserves_sorted_order() {
let crit = temp_root();
fs::create_dir_all(crit.join("RT_B").join("ci-baseline")).unwrap();
let missing = missing_baseline_coverage(crit_log(), &crit, "ci-baseline").unwrap();
assert_eq!(missing, ["RT_A", "RT_C"]);
}
#[test]
fn custom_baseline_name_is_used() {
let crit = temp_root();
fs::create_dir_all(crit.join("RT_A").join("ci-baseline")).unwrap();
fs::create_dir_all(crit.join("RT_A").join("nightly")).unwrap();
fs::create_dir_all(crit.join("RT_B").join("nightly")).unwrap();
let missing = missing_baseline_coverage(crit_log(), &crit, "nightly").unwrap();
assert_eq!(missing, ["RT_C"]);
}
#[test]
fn a_file_named_like_the_series_is_not_coverage() {
let crit = temp_root();
fs::create_dir_all(crit.join("RT_A")).unwrap();
fs::write(crit.join("RT_A").join("ci-baseline"), "not a dir").unwrap();
fs::create_dir_all(crit.join("RT_B").join("ci-baseline")).unwrap();
let missing = missing_baseline_coverage(crit_log(), &crit, "ci-baseline").unwrap();
assert_eq!(missing, ["RT_A", "RT_C"]);
}
#[test]
fn empty_id_captures_are_dropped_like_bash_word_splitting() {
let only_empty = "Benchmarking : no id\n";
assert_eq!(executed_bench_ids(only_empty), [""]);
assert_eq!(
missing_baseline_coverage(only_empty, &temp_root(), "ci-baseline"),
Err(BaselineCoverageGap)
);
let crit = temp_root();
fs::create_dir_all(crit.join("RT_A").join("ci-baseline")).unwrap();
let mixed = "Benchmarking : no id\nBenchmarking RT_A: ok\nBenchmarking : also empty\n";
assert_eq!(
missing_baseline_coverage(mixed, &crit, "ci-baseline").unwrap(),
Vec::<String>::new(),
"empty captures must not be listed as missing"
);
}