use std::panic::{AssertUnwindSafe, catch_unwind};
use hegel::generators as gs;
use hegel::{Hegel, Settings, TestCase, Verbosity};
#[hegel::test(
report_multiple_failures = true,
derandomize = true,
test_cases = 500u64,
verbosity = hegel::Verbosity::Quiet,
database = None
)]
#[should_panic(expected = "Property-based test failed with 2 distinct failures.")]
fn test_macro_report_multiple_failures_true_surfaces_both(tc: TestCase) {
let x: i32 = tc.draw(gs::integers::<i32>().min_value(0).max_value(40));
if x > 30 {
panic!("big branch: {}", x);
}
if x < 10 {
panic!("small branch: {}", x);
}
}
#[hegel::test(
report_multiple_failures = false,
derandomize = true,
test_cases = 500u64,
verbosity = hegel::Verbosity::Quiet,
database = None
)]
#[should_panic(expected = "Property test failed: ")]
fn test_macro_report_multiple_failures_false_collapses(tc: TestCase) {
let x: i32 = tc.draw(gs::integers::<i32>().min_value(0).max_value(40));
if x > 30 {
panic!("big branch: {}", x);
}
if x < 10 {
panic!("small branch: {}", x);
}
}
fn run_two_origin_failure(verbosity: Verbosity) -> String {
let result = catch_unwind(AssertUnwindSafe(move || {
Hegel::new(|tc: TestCase| {
let x: i32 = tc.draw(gs::integers::<i32>().min_value(0).max_value(40));
if x > 30 {
panic!("big branch: {}", x);
}
if x < 10 {
panic!("small branch: {}", x);
}
})
.settings(
Settings::new()
.database(None)
.derandomize(true)
.verbosity(verbosity)
.test_cases(500),
)
.run();
}));
let payload = result.expect_err("expected run() to panic with multiple failures");
let msg = payload
.downcast_ref::<&str>()
.map(|s| s.to_string())
.or_else(|| payload.downcast_ref::<String>().cloned())
.unwrap_or_default();
assert!(
msg.starts_with("Property-based test failed with ") && msg.ends_with(" distinct failures."),
"expected multi-failure outer panic, got: {msg:?}"
);
msg
}
#[test]
fn test_multi_failure_panic_with_default_verbosity() {
let _ = run_two_origin_failure(Verbosity::Normal);
}
#[test]
fn test_multi_failure_panic_quiet_suppresses_stderr() {
let _ = run_two_origin_failure(Verbosity::Quiet);
}
#[test]
fn test_report_multiple_failures_false_collapses_to_single_failure_panic() {
let result = catch_unwind(AssertUnwindSafe(move || {
Hegel::new(|tc: TestCase| {
let x: i32 = tc.draw(gs::integers::<i32>().min_value(0).max_value(40));
if x > 30 {
panic!("big branch: {}", x);
}
if x < 10 {
panic!("small branch: {}", x);
}
})
.settings(
Settings::new()
.database(None)
.derandomize(true)
.verbosity(Verbosity::Quiet)
.test_cases(500)
.report_multiple_failures(false),
)
.run();
}));
let payload = result.expect_err("expected run() to panic");
let msg = payload
.downcast_ref::<&str>()
.map(|s| s.to_string())
.or_else(|| payload.downcast_ref::<String>().cloned())
.unwrap_or_default();
assert!(
msg.starts_with("Property test failed: ") && !msg.contains("distinct failures"),
"expected single-failure outer panic (one branch should win), got: {msg:?}"
);
}