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,63 @@ 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+ test ( |_old_val| panic ! ( 1337 ) ) ;
51+ // FIXME https://github.com/rust-lang/miri/issues/1071
52+ //test(|_old_val| core::panic!("Hello from panic: core"));
53+ //test(|old_val| core::panic!(&format!("Hello from panic: {:?}", old_val)));
54+ //test(|old_val| core::panic!("Hello from panic: {:?}", old_val));
55+
56+ // Cleanup: reset to default hook.
57+ drop ( std:: panic:: take_hook ( ) ) ;
58+
59+ eprintln ! ( "Success!" ) ; // Make sure we get this in stderr
60+ }
61+
62+ fn test ( do_panic : impl FnOnce ( usize ) -> !) {
63+ // Reset test flags.
64+ DROPPED . with ( |c| c. set ( false ) ) ;
65+ HOOK_CALLED . with ( |c| c. set ( false ) ) ;
66+
67+ // Cause and catch a panic.
68+ let res = catch_unwind ( AssertUnwindSafe ( || {
4569 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- } ) ;
70+ do_panic_counter ( do_panic)
71+ } ) ) . expect_err ( "do_panic() did not panic!" ) ;
5772
58- HOOK_CALLED . with ( |h| {
59- assert ! ( h. get( ) ) ;
60- } ) ;
73+ // See if we can extract panic message.
74+ match res. downcast :: < String > ( ) {
75+ Ok ( s) => {
76+ eprintln ! ( "Caught panic message (String): {}" , s) ;
77+ }
78+ Err ( res) =>
79+ if let Ok ( s) = res. downcast :: < & str > ( ) {
80+ eprintln ! ( "Caught panic message (&str): {}" , s) ;
81+ } else {
82+ eprintln ! ( "Failed get caught panic message." ) ;
83+ }
84+ }
85+
86+ // Test flags.
87+ assert ! ( DROPPED . with( |c| c. get( ) ) ) ;
88+ assert ! ( HOOK_CALLED . with( |c| c. get( ) ) ) ;
6189}
6290
0 commit comments