1 #![warn(rust_2018_idioms)]
2 #![cfg(all(feature = "full", not(target_os = "wasi")))]
3 #![cfg(panic = "unwind")]
4 
5 use std::{error::Error, sync::Arc};
6 use tokio::{
7     runtime::{Builder, Runtime},
8     sync::{broadcast, mpsc, oneshot, Mutex, RwLock, Semaphore},
9 };
10 
11 mod support {
12     pub mod panic;
13 }
14 use support::panic::test_panic;
15 
16 #[test]
broadcast_channel_panic_caller() -> Result<(), Box<dyn Error>>17 fn broadcast_channel_panic_caller() -> Result<(), Box<dyn Error>> {
18     let panic_location_file = test_panic(|| {
19         let (_, _) = broadcast::channel::<u32>(0);
20     });
21 
22     // The panic location should be in this file
23     assert_eq!(&panic_location_file.unwrap(), file!());
24 
25     Ok(())
26 }
27 
28 #[test]
mutex_blocking_lock_panic_caller() -> Result<(), Box<dyn Error>>29 fn mutex_blocking_lock_panic_caller() -> Result<(), Box<dyn Error>> {
30     let panic_location_file = test_panic(|| {
31         let rt = current_thread();
32         rt.block_on(async {
33             let mutex = Mutex::new(5_u32);
34             let _g = mutex.blocking_lock();
35         });
36     });
37 
38     // The panic location should be in this file
39     assert_eq!(&panic_location_file.unwrap(), file!());
40 
41     Ok(())
42 }
43 
44 #[test]
oneshot_blocking_recv_panic_caller() -> Result<(), Box<dyn Error>>45 fn oneshot_blocking_recv_panic_caller() -> Result<(), Box<dyn Error>> {
46     let panic_location_file = test_panic(|| {
47         let rt = current_thread();
48         rt.block_on(async {
49             let (_tx, rx) = oneshot::channel::<u8>();
50             let _ = rx.blocking_recv();
51         });
52     });
53 
54     // The panic location should be in this file
55     assert_eq!(&panic_location_file.unwrap(), file!());
56 
57     Ok(())
58 }
59 
60 #[test]
rwlock_with_max_readers_panic_caller() -> Result<(), Box<dyn Error>>61 fn rwlock_with_max_readers_panic_caller() -> Result<(), Box<dyn Error>> {
62     let panic_location_file = test_panic(|| {
63         let _ = RwLock::<u8>::with_max_readers(0, (u32::MAX >> 3) + 1);
64     });
65 
66     // The panic location should be in this file
67     assert_eq!(&panic_location_file.unwrap(), file!());
68 
69     Ok(())
70 }
71 
72 #[test]
rwlock_blocking_read_panic_caller() -> Result<(), Box<dyn Error>>73 fn rwlock_blocking_read_panic_caller() -> Result<(), Box<dyn Error>> {
74     let panic_location_file = test_panic(|| {
75         let rt = current_thread();
76         rt.block_on(async {
77             let lock = RwLock::<u8>::new(0);
78             let _ = lock.blocking_read();
79         });
80     });
81 
82     // The panic location should be in this file
83     assert_eq!(&panic_location_file.unwrap(), file!());
84 
85     Ok(())
86 }
87 
88 #[test]
rwlock_blocking_write_panic_caller() -> Result<(), Box<dyn Error>>89 fn rwlock_blocking_write_panic_caller() -> Result<(), Box<dyn Error>> {
90     let panic_location_file = test_panic(|| {
91         let rt = current_thread();
92         rt.block_on(async {
93             let lock = RwLock::<u8>::new(0);
94             let _ = lock.blocking_write();
95         });
96     });
97 
98     // The panic location should be in this file
99     assert_eq!(&panic_location_file.unwrap(), file!());
100 
101     Ok(())
102 }
103 
104 #[test]
mpsc_bounded_channel_panic_caller() -> Result<(), Box<dyn Error>>105 fn mpsc_bounded_channel_panic_caller() -> Result<(), Box<dyn Error>> {
106     let panic_location_file = test_panic(|| {
107         let (_, _) = mpsc::channel::<u8>(0);
108     });
109 
110     // The panic location should be in this file
111     assert_eq!(&panic_location_file.unwrap(), file!());
112 
113     Ok(())
114 }
115 
116 #[test]
mpsc_bounded_receiver_blocking_recv_panic_caller() -> Result<(), Box<dyn Error>>117 fn mpsc_bounded_receiver_blocking_recv_panic_caller() -> Result<(), Box<dyn Error>> {
118     let panic_location_file = test_panic(|| {
119         let rt = current_thread();
120         let (_tx, mut rx) = mpsc::channel::<u8>(1);
121         rt.block_on(async {
122             let _ = rx.blocking_recv();
123         });
124     });
125 
126     // The panic location should be in this file
127     assert_eq!(&panic_location_file.unwrap(), file!());
128 
129     Ok(())
130 }
131 
132 #[test]
mpsc_bounded_receiver_blocking_recv_many_panic_caller() -> Result<(), Box<dyn Error>>133 fn mpsc_bounded_receiver_blocking_recv_many_panic_caller() -> Result<(), Box<dyn Error>> {
134     let panic_location_file = test_panic(|| {
135         let rt = current_thread();
136         let (_tx, mut rx) = mpsc::channel::<u8>(1);
137         rt.block_on(async {
138             let _ = rx.blocking_recv();
139         });
140     });
141 
142     // The panic location should be in this file
143     assert_eq!(&panic_location_file.unwrap(), file!());
144 
145     Ok(())
146 }
147 
148 #[test]
mpsc_bounded_sender_blocking_send_panic_caller() -> Result<(), Box<dyn Error>>149 fn mpsc_bounded_sender_blocking_send_panic_caller() -> Result<(), Box<dyn Error>> {
150     let panic_location_file = test_panic(|| {
151         let rt = current_thread();
152         let (tx, _rx) = mpsc::channel::<u8>(1);
153         rt.block_on(async {
154             let _ = tx.blocking_send(3);
155         });
156     });
157 
158     // The panic location should be in this file
159     assert_eq!(&panic_location_file.unwrap(), file!());
160 
161     Ok(())
162 }
163 
164 #[test]
mpsc_unbounded_receiver_blocking_recv_panic_caller() -> Result<(), Box<dyn Error>>165 fn mpsc_unbounded_receiver_blocking_recv_panic_caller() -> Result<(), Box<dyn Error>> {
166     let panic_location_file = test_panic(|| {
167         let rt = current_thread();
168         let (_tx, mut rx) = mpsc::unbounded_channel::<u8>();
169         rt.block_on(async {
170             let _ = rx.blocking_recv();
171         });
172     });
173 
174     // The panic location should be in this file
175     assert_eq!(&panic_location_file.unwrap(), file!());
176 
177     Ok(())
178 }
179 
180 #[test]
mpsc_unbounded_receiver_blocking_recv_many_panic_caller() -> Result<(), Box<dyn Error>>181 fn mpsc_unbounded_receiver_blocking_recv_many_panic_caller() -> Result<(), Box<dyn Error>> {
182     let panic_location_file = test_panic(|| {
183         let rt = current_thread();
184         let (_tx, mut rx) = mpsc::unbounded_channel::<u8>();
185         let mut vec = vec![];
186         rt.block_on(async {
187             let _ = rx.blocking_recv_many(&mut vec, 1);
188         });
189     });
190 
191     // The panic location should be in this file
192     assert_eq!(&panic_location_file.unwrap(), file!());
193 
194     Ok(())
195 }
196 
197 #[test]
semaphore_merge_unrelated_owned_permits() -> Result<(), Box<dyn Error>>198 fn semaphore_merge_unrelated_owned_permits() -> Result<(), Box<dyn Error>> {
199     let panic_location_file = test_panic(|| {
200         let sem1 = Arc::new(Semaphore::new(42));
201         let sem2 = Arc::new(Semaphore::new(42));
202         let mut p1 = sem1.try_acquire_owned().unwrap();
203         let p2 = sem2.try_acquire_owned().unwrap();
204         p1.merge(p2);
205     });
206 
207     // The panic location should be in this file
208     assert_eq!(&panic_location_file.unwrap(), file!());
209 
210     Ok(())
211 }
212 
213 #[test]
semaphore_merge_unrelated_permits() -> Result<(), Box<dyn Error>>214 fn semaphore_merge_unrelated_permits() -> Result<(), Box<dyn Error>> {
215     let panic_location_file = test_panic(|| {
216         let sem1 = Semaphore::new(42);
217         let sem2 = Semaphore::new(42);
218         let mut p1 = sem1.try_acquire().unwrap();
219         let p2 = sem2.try_acquire().unwrap();
220         p1.merge(p2);
221     });
222 
223     // The panic location should be in this file
224     assert_eq!(&panic_location_file.unwrap(), file!());
225 
226     Ok(())
227 }
228 
current_thread() -> Runtime229 fn current_thread() -> Runtime {
230     Builder::new_current_thread().enable_all().build().unwrap()
231 }
232