mod common;
use std::panic::{AssertUnwindSafe, catch_unwind};
use common::project::TempRustProject;
use hegel::generators as gs;
use hegel::{Hegel, Settings, TestCase, Verbosity};
fn run_property_panicking_with(msg: &'static str) -> String {
let result = catch_unwind(AssertUnwindSafe(|| {
Hegel::new(move |tc: TestCase| {
tc.draw(gs::booleans());
panic!("{}", msg);
})
.settings(
Settings::new()
.database(None)
.derandomize(true)
.test_cases(10)
.verbosity(Verbosity::Quiet),
)
.run();
}));
let payload = result.expect_err("a panicking property must fail its run");
payload
.downcast_ref::<String>()
.cloned()
.or_else(|| payload.downcast_ref::<&str>().map(|s| s.to_string()))
.unwrap_or_default()
}
#[test]
fn user_panic_matching_assume_sentinel_is_a_failure() {
assert_eq!(
run_property_panicking_with("__HEGEL_ASSUME_FAIL"),
"__HEGEL_ASSUME_FAIL"
);
}
#[test]
fn user_panic_matching_stop_test_sentinel_is_a_failure() {
assert_eq!(
run_property_panicking_with("__HEGEL_STOP_TEST"),
"__HEGEL_STOP_TEST"
);
}
#[test]
fn user_panic_matching_loop_done_sentinel_is_a_failure() {
assert_eq!(
run_property_panicking_with("__HEGEL_LOOP_DONE"),
"__HEGEL_LOOP_DONE"
);
}
#[test]
fn user_panic_matching_invalid_argument_prefix_is_a_failure() {
assert_eq!(
run_property_panicking_with("__HEGEL_INVALID_ARGUMENT: boom"),
"__HEGEL_INVALID_ARGUMENT: boom"
);
}
const THREADED_REJECTS_CODE: &str = r#"
use hegel::{Hegel, HealthCheck, Settings};
use hegel::generators as gs;
fn main() {
Hegel::new(|tc| {
let worker = tc.clone();
let result = std::thread::spawn(move || {
let keep: bool = worker.draw(gs::booleans());
// Rejecting on the worker thread raises the control-flow unwind
// *there*, not on the thread the lifecycle's hook protects.
worker.assume(keep);
})
.join();
if let Err(payload) = result {
std::panic::resume_unwind(payload);
}
})
.settings(
Settings::new()
.database(None)
.derandomize(true)
.test_cases(20)
.suppress_health_check(HealthCheck::all()),
)
.run();
}
"#;
#[test]
fn worker_thread_rejections_print_no_panic_noise() {
let output = TempRustProject::new()
.main_file(THREADED_REJECTS_CODE)
.cargo_run(&[]);
assert!(
!output.stderr.contains("panicked"),
"worker-thread rejections must not reach any panic hook, got:\n{}",
output.stderr
);
}