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