11// ignore-windows: Unwind panicking does not currently work on Windows
2- use std:: panic:: catch_unwind;
2+ use std:: panic:: { catch_unwind, AssertUnwindSafe } ;
33use std:: cell:: Cell ;
44
55thread_local ! {
@@ -18,7 +18,7 @@ impl Drop for DropTester {
1818 }
1919}
2020
21- fn do_panic_counter ( ) {
21+ fn do_panic_counter ( do_panic : impl FnOnce ( usize ) -> ! ) {
2222 // If this gets leaked, it will be easy to spot
2323 // in Miri's leak report
2424 let _string = "LEAKED FROM do_panic_counter" . to_string ( ) ;
@@ -28,35 +28,62 @@ fn do_panic_counter() {
2828
2929 // Check for bugs in Miri's panic implementation.
3030 // If do_panic_counter() somehow gets called more than once,
31- // we'll generate a different panic message
31+ // we'll generate a different panic message and stderr will differ.
3232 let old_val = MY_COUNTER . with ( |c| {
3333 let val = c. get ( ) ;
3434 c. set ( val + 1 ) ;
3535 val
3636 } ) ;
37- panic ! ( format! ( "Hello from panic: {:?}" , old_val) ) ;
37+ do_panic ( old_val) ;
3838}
3939
4040fn main ( ) {
41- std:: panic:: set_hook ( Box :: new ( |_panic_info| {
41+ let prev = std:: panic:: take_hook ( ) ;
42+ std:: panic:: set_hook ( Box :: new ( move |panic_info| {
4243 HOOK_CALLED . with ( |h| h. set ( true ) ) ;
44+ prev ( panic_info)
4345 } ) ) ;
44- let res = catch_unwind ( || {
46+
47+ test ( |_old_val| panic ! ( "Hello from panic: std" ) ) ;
48+ test ( |old_val| panic ! ( format!( "Hello from panic: {:?}" , old_val) ) ) ;
49+ test ( |old_val| panic ! ( "Hello from panic: {:?}" , old_val) ) ;
50+ // FIXME https://github.com/rust-lang/miri/issues/1071
51+ //test(|_old_val| core::panic!("Hello from panic: core"));
52+ //test(|old_val| core::panic!(&format!("Hello from panic: {:?}", old_val)));
53+ //test(|old_val| core::panic!("Hello from panic: {:?}", old_val));
54+
55+ // Cleanup: reset to default hook.
56+ drop ( std:: panic:: take_hook ( ) ) ;
57+
58+ eprintln ! ( "Success!" ) ; // Make sure we get this in stderr
59+ }
60+
61+ fn test ( do_panic : impl FnOnce ( usize ) -> !) {
62+ // Reset test flags.
63+ DROPPED . with ( |c| c. set ( false ) ) ;
64+ HOOK_CALLED . with ( |c| c. set ( false ) ) ;
65+
66+ // Cause and catch a panic.
67+ let res = catch_unwind ( AssertUnwindSafe ( || {
4568 let _string = "LEAKED FROM CLOSURE" . to_string ( ) ;
46- do_panic_counter ( )
47- } ) ;
48- let expected: Box < String > = Box :: new ( "Hello from panic: 0" . to_string ( ) ) ;
49- let actual = res. expect_err ( "do_panic() did not panic!" )
50- . downcast :: < String > ( ) . expect ( "Failed to cast to string!" ) ;
51-
52- assert_eq ! ( expected, actual) ;
53- DROPPED . with ( |c| {
54- // This should have been set to 'true' by DropTester
55- assert ! ( c. get( ) ) ;
56- } ) ;
69+ do_panic_counter ( do_panic)
70+ } ) ) . expect_err ( "do_panic() did not panic!" ) ;
5771
58- HOOK_CALLED . with ( |h| {
59- assert ! ( h. get( ) ) ;
60- } ) ;
72+ // See if we can extract panic message.
73+ match res. downcast :: < String > ( ) {
74+ Ok ( s) => {
75+ eprintln ! ( "Caught panic message (String): {}" , s) ;
76+ }
77+ Err ( res) =>
78+ if let Ok ( s) = res. downcast :: < & str > ( ) {
79+ eprintln ! ( "Caught panic message (&str): {}" , s) ;
80+ } else {
81+ eprintln ! ( "Failed get caught panic message." ) ;
82+ }
83+ }
84+
85+ // Test flags.
86+ assert ! ( DROPPED . with( |c| c. get( ) ) ) ;
87+ assert ! ( HOOK_CALLED . with( |c| c. get( ) ) ) ;
6188}
6289
0 commit comments