fn required() -> bool {
std::env::var("HAL_TEST_REQUIRE_CUDA").as_deref() == Ok("1")
}
fn decide(satisfied: bool, require: bool, what: &str, why: &str) -> bool {
if satisfied {
return true;
}
assert!(
!require,
"HAL_TEST_REQUIRE_CUDA=1 but {what} would have skipped while \
reporting success: {why}"
);
false
}
pub(crate) fn cuda_available_or_skip(what: &str) -> bool {
let why = "no libcudart (a supported soname missing from cuda.rs's probe \
list, or LD_LIBRARY_PATH does not reach the runtime)";
let run = decide(edgefirst_tensor::is_cuda_available(), required(), what, why);
if !run {
crate::test_support::report_skip(&format!("{what}: {why}"));
}
run
}
pub(crate) fn require_or_skip(satisfied: bool, what: &str, why: &str) -> bool {
let run = decide(satisfied, required(), what, why);
if !run {
crate::test_support::report_skip(&format!("{what}: {why}"));
}
run
}
#[cfg(test)]
mod tests {
use super::decide;
#[test]
fn satisfied_and_required_runs() {
assert!(decide(true, true, "what", "why"));
}
#[test]
fn satisfied_and_not_required_runs() {
assert!(decide(true, false, "what", "why"));
}
#[test]
fn unsatisfied_and_not_required_is_an_ordinary_skip() {
assert!(!decide(false, false, "what", "why"));
}
#[test]
fn unsatisfied_and_required_panics_naming_the_opt_in_what_and_why() {
let prev_hook = std::panic::take_hook();
std::panic::set_hook(Box::new(|_| {}));
let caught = std::panic::catch_unwind(|| decide(false, true, "probe", "some reason"));
std::panic::set_hook(prev_hook);
let payload = caught.expect_err("a required-but-absent precondition must panic, not skip");
let message = payload
.downcast_ref::<String>()
.map(String::as_str)
.or_else(|| payload.downcast_ref::<&str>().copied())
.expect("panic payload should be a string");
assert!(
message.contains("HAL_TEST_REQUIRE_CUDA=1"),
"panic message must name the opt-in: {message}"
);
assert!(
message.contains("probe"),
"panic message must name the caller: {message}"
);
assert!(
message.contains("some reason"),
"panic message must name the reason: {message}"
);
}
}