use super::super::test_helpers::{EnvVarGuard, dummy_test_fn, eevdf_entry, lock_env};
use super::super::topo::TopoOverride;
use super::*;
fn count_sidecars_by_prefix(dir: &std::path::Path, prefix: &str) -> usize {
std::fs::read_dir(dir)
.expect("sidecar dir must exist for lookup")
.filter_map(|e| e.ok().map(|e| e.path()))
.filter(|p| {
p.file_name()
.and_then(|n| n.to_str())
.is_some_and(|n| n.starts_with(prefix) && n.ends_with(".ktstr.json"))
})
.count()
}
#[test]
fn run_ktstr_test_inner_invalid_entry_name_fails_validation() {
let entry = KtstrTestEntry {
name: "bad/name",
func: dummy_test_fn,
auto_repro: false,
..KtstrTestEntry::DEFAULT
};
let err = run_ktstr_test_inner(&entry, None).unwrap_err();
let msg = format!("{err:#}");
assert!(
msg.contains("KtstrTestEntry validation"),
"the .context() wrapper must ride the chain, got: {msg}",
);
assert!(
msg.contains("must not contain path separators"),
"the validate diagnostic must surface as the chain root, got: {msg}",
);
}
#[test]
fn run_ktstr_test_inner_empty_entry_name_fails_validation() {
let entry = KtstrTestEntry {
name: "",
func: dummy_test_fn,
auto_repro: false,
..KtstrTestEntry::DEFAULT
};
let err = run_ktstr_test_inner(&entry, None).unwrap_err();
let msg = format!("{err:#}");
assert!(
msg.contains("KtstrTestEntry validation"),
"the validation .context() wrapper must ride the chain, got: {msg}",
);
assert!(
msg.contains("must be non-empty"),
"the empty-name validate diagnostic must surface, got: {msg}",
);
}
#[test]
fn run_ktstr_test_inner_invalid_topo_override_fails_validation() {
let entry = eevdf_entry("__inner_bad_topo__");
let topo = TopoOverride {
numa_nodes: 1,
llcs: 1,
cores: 2,
threads: 1,
memory_mib: 0,
};
let err = run_ktstr_test_inner(&entry, Some(&topo)).unwrap_err();
let msg = format!("{err:#}");
assert!(
msg.contains("TopoOverride validation"),
"the topo-gate .context() wrapper must ride the chain, got: {msg}",
);
assert!(
msg.contains("memory_mib must be > 0"),
"the zero-memory TopoOverride diagnostic must surface, got: {msg}",
);
}
#[test]
fn run_ktstr_test_inner_skips_perf_test_under_no_perf_mode() {
let _lock = lock_env();
let sidecar_tmp = tempfile::TempDir::new().expect("sidecar tempdir");
let _env_sidecar = EnvVarGuard::set(crate::KTSTR_SIDECAR_DIR_ENV, sidecar_tmp.path());
let _env_no_perf = EnvVarGuard::set(crate::KTSTR_NO_PERF_MODE_ENV, "1");
let _env_perf_only = EnvVarGuard::remove(crate::KTSTR_PERF_ONLY_ENV);
let entry = KtstrTestEntry {
name: "__inner_no_perf_skip__",
func: dummy_test_fn,
auto_repro: false,
performance_mode: true,
..KtstrTestEntry::DEFAULT
};
let result = run_ktstr_test_inner(&entry, None)
.expect("the no-perf-mode skip arm must return Ok(skip), not Err");
assert!(
result.is_skip(),
"performance_mode under KTSTR_NO_PERF_MODE must yield a SKIP AssertResult",
);
let rendered = result
.skip_details()
.map(|d| d.message.as_str())
.collect::<Vec<_>>()
.join("\n");
assert!(
rendered.contains("requires performance_mode but --no-perf-mode or KTSTR_NO_PERF_MODE"),
"the skip AssertResult must carry the canonical no-perf-mode REASON, got: {rendered}",
);
assert_eq!(
count_sidecars_by_prefix(sidecar_tmp.path(), "__inner_no_perf_skip__-"),
1,
"record_skip_sidecar must write exactly one skip sidecar into the override dir",
);
}
#[test]
fn run_ktstr_test_inner_skips_non_perf_test_under_perf_only() {
let _lock = lock_env();
let sidecar_tmp = tempfile::TempDir::new().expect("sidecar tempdir");
let _env_sidecar = EnvVarGuard::set(crate::KTSTR_SIDECAR_DIR_ENV, sidecar_tmp.path());
let _env_perf_only = EnvVarGuard::set(crate::KTSTR_PERF_ONLY_ENV, "1");
let _env_no_perf = EnvVarGuard::remove(crate::KTSTR_NO_PERF_MODE_ENV);
let entry = eevdf_entry("__inner_perf_only_skip__");
let result = run_ktstr_test_inner(&entry, None)
.expect("the perf-only skip arm must return Ok(skip), not Err");
assert!(
result.is_skip(),
"a non-perf entry under KTSTR_PERF_ONLY must yield a SKIP AssertResult",
);
let rendered = result
.skip_details()
.map(|d| d.message.as_str())
.collect::<Vec<_>>()
.join("\n");
assert!(
rendered.contains("KTSTR_PERF_ONLY is active and this test is not a performance_mode test"),
"the skip AssertResult must carry the canonical perf-only REASON, got: {rendered}",
);
assert_eq!(
count_sidecars_by_prefix(sidecar_tmp.path(), "__inner_perf_only_skip__-"),
1,
"record_skip_sidecar must write exactly one skip sidecar into the override dir",
);
}