1use std::panic;
2use std::sync::{Arc, Mutex};
3
4pub fn test_panic<Func: FnOnce() + panic::UnwindSafe>(func: Func) -> Option<String> {
5 static PANIC_MUTEX: Mutex<()> = Mutex::new(());
6
7 {
8 let _guard = PANIC_MUTEX.lock();
9 let panic_file: Arc<Mutex<Option<String>>> = Arc::new(Mutex::new(None));
10
11 let prev_hook = panic::take_hook();
12 {
13 let panic_file = panic_file.clone();
14 panic::set_hook(Box::new(move |panic_info| {
15 let panic_location = panic_info.location().unwrap();
16 panic_file
17 .lock()
18 .unwrap()
19 .clone_from(&Some(panic_location.file().to_string()));
20 }));
21 }
22
23 let result = panic::catch_unwind(func);
24 // Return to the previously set panic hook (maybe default) so that we get nice error
25 // messages in the tests.
26 panic::set_hook(prev_hook);
27
28 if result.is_err() {
29 panic_file.lock().unwrap().clone()
30 } else {
31 None
32 }
33 }
34}
35