#![deny(deprecated)] use maybe_unwind::maybe_unwind; use std::{panic::PanicInfo, sync::Once}; fn ensure_set_hook() { fn test_hook(info: &PanicInfo) { maybe_unwind::capture_panic_info(info); } static SET_HOOK: Once = Once::new(); SET_HOOK.call_once(|| { std::panic::set_hook(Box::new(test_hook)); }); } #[test] fn never_unwind() { ensure_set_hook(); assert!(maybe_unwind(|| "foo").is_ok()); } #[allow(unreachable_code)] #[test] fn has_unwind() { ensure_set_hook(); let unwind = maybe_unwind(|| { panic!("bar"); "foo" }) .unwrap_err(); assert_eq!(unwind.payload_str(), "bar"); assert!(unwind .location() .map_or(false, |loc| loc.file().contains(file!()))); } #[test] #[should_panic(expected = "explicit panic")] fn without_wrapper() { ensure_set_hook(); panic!("explicit panic"); } #[allow(unreachable_code)] #[test] fn nested1() { ensure_set_hook(); let res = maybe_unwind(|| { maybe_unwind(|| { panic!("bar"); "baz" }) }); let res = res.unwrap(); let unwind = res.unwrap_err(); assert_eq!(unwind.payload_str(), "bar"); } #[allow(unreachable_code)] #[test] fn nested2() { ensure_set_hook(); let res = maybe_unwind(|| { let _ = maybe_unwind(|| { panic!("bar"); "baz" }); panic!("foo"); }); let unwind = res.unwrap_err(); assert_eq!(unwind.payload_str(), "foo"); } #[cfg(feature = "futures")] mod futures { use super::ensure_set_hook; use futures_executor::block_on; use maybe_unwind::FutureMaybeUnwindExt as _; #[test] fn never_unwind() { ensure_set_hook(); block_on(async { assert!(async { "foo" }.maybe_unwind().await.is_ok()); }) } #[allow(unreachable_code)] #[test] fn has_unwind() { ensure_set_hook(); block_on(async { let unwind = async { panic!("bar"); "foo" } .maybe_unwind() .await .unwrap_err(); assert_eq!(unwind.payload_str(), "bar"); assert!(unwind .location() .map_or(false, |loc| loc.file().contains(file!()))); }) } #[allow(unreachable_code)] #[test] fn nested1() { ensure_set_hook(); block_on(async { let res = async { async { panic!("bar"); "baz" } .maybe_unwind() .await } .maybe_unwind() .await; let res = res.unwrap(); let unwind = res.unwrap_err(); assert_eq!(unwind.payload_str(), "bar"); }) } #[allow(unreachable_code)] #[test] fn nested2() { ensure_set_hook(); block_on(async { let res = async { let _ = async { panic!("bar"); "baz" } .maybe_unwind() .await; panic!("foo"); } .maybe_unwind() .await; let unwind = res.unwrap_err(); assert_eq!(unwind.payload_str(), "foo"); }) } }