1
1
// ignore-windows: Unwind panicking does not currently work on Windows
2
- use std:: panic:: catch_unwind;
2
+ use std:: panic:: { catch_unwind, AssertUnwindSafe } ;
3
3
use std:: cell:: Cell ;
4
4
5
5
thread_local ! {
@@ -18,7 +18,7 @@ impl Drop for DropTester {
18
18
}
19
19
}
20
20
21
- fn do_panic_counter ( ) {
21
+ fn do_panic_counter ( do_panic : impl FnOnce ( usize ) -> ! ) {
22
22
// If this gets leaked, it will be easy to spot
23
23
// in Miri's leak report
24
24
let _string = "LEAKED FROM do_panic_counter" . to_string ( ) ;
@@ -28,35 +28,63 @@ fn do_panic_counter() {
28
28
29
29
// Check for bugs in Miri's panic implementation.
30
30
// 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.
32
32
let old_val = MY_COUNTER . with ( |c| {
33
33
let val = c. get ( ) ;
34
34
c. set ( val + 1 ) ;
35
35
val
36
36
} ) ;
37
- panic ! ( format! ( "Hello from panic: {:?}" , old_val) ) ;
37
+ do_panic ( old_val) ;
38
38
}
39
39
40
40
fn 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| {
42
43
HOOK_CALLED . with ( |h| h. set ( true ) ) ;
44
+ prev ( panic_info)
43
45
} ) ) ;
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 ( || {
45
69
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!" ) ;
57
72
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( ) ) ) ;
61
89
}
62
90
0 commit comments