1 #![warn(rust_2018_idioms)]
2 #![cfg(feature = "sync")]
3 
4 #[cfg(all(target_family = "wasm", not(target_os = "wasi")))]
5 use wasm_bindgen_test::wasm_bindgen_test as test;
6 
7 use tokio::sync::Notify;
8 use tokio_test::task::spawn;
9 use tokio_test::*;
10 
11 #[allow(unused)]
12 trait AssertSend: Send + Sync {}
13 impl AssertSend for Notify {}
14 
15 #[test]
notify_notified_one()16 fn notify_notified_one() {
17     let notify = Notify::new();
18     let mut notified = spawn(async { notify.notified().await });
19 
20     notify.notify_one();
21     assert_ready!(notified.poll());
22 }
23 
24 #[test]
notify_multi_notified_one()25 fn notify_multi_notified_one() {
26     let notify = Notify::new();
27     let mut notified1 = spawn(async { notify.notified().await });
28     let mut notified2 = spawn(async { notify.notified().await });
29 
30     // add two waiters into the queue
31     assert_pending!(notified1.poll());
32     assert_pending!(notified2.poll());
33 
34     // should wakeup the first one
35     notify.notify_one();
36     assert_ready!(notified1.poll());
37     assert_pending!(notified2.poll());
38 }
39 
40 #[test]
notify_multi_notified_last()41 fn notify_multi_notified_last() {
42     let notify = Notify::new();
43     let mut notified1 = spawn(async { notify.notified().await });
44     let mut notified2 = spawn(async { notify.notified().await });
45 
46     // add two waiters into the queue
47     assert_pending!(notified1.poll());
48     assert_pending!(notified2.poll());
49 
50     // should wakeup the last one
51     notify.notify_last();
52     assert_pending!(notified1.poll());
53     assert_ready!(notified2.poll());
54 }
55 
56 #[test]
notified_one_notify()57 fn notified_one_notify() {
58     let notify = Notify::new();
59     let mut notified = spawn(async { notify.notified().await });
60 
61     assert_pending!(notified.poll());
62 
63     notify.notify_one();
64     assert!(notified.is_woken());
65     assert_ready!(notified.poll());
66 }
67 
68 #[test]
notified_multi_notify()69 fn notified_multi_notify() {
70     let notify = Notify::new();
71     let mut notified1 = spawn(async { notify.notified().await });
72     let mut notified2 = spawn(async { notify.notified().await });
73 
74     assert_pending!(notified1.poll());
75     assert_pending!(notified2.poll());
76 
77     notify.notify_one();
78     assert!(notified1.is_woken());
79     assert!(!notified2.is_woken());
80 
81     assert_ready!(notified1.poll());
82     assert_pending!(notified2.poll());
83 }
84 
85 #[test]
notify_notified_multi()86 fn notify_notified_multi() {
87     let notify = Notify::new();
88 
89     notify.notify_one();
90 
91     let mut notified1 = spawn(async { notify.notified().await });
92     let mut notified2 = spawn(async { notify.notified().await });
93 
94     assert_ready!(notified1.poll());
95     assert_pending!(notified2.poll());
96 
97     notify.notify_one();
98 
99     assert!(notified2.is_woken());
100     assert_ready!(notified2.poll());
101 }
102 
103 #[test]
notified_drop_notified_notify()104 fn notified_drop_notified_notify() {
105     let notify = Notify::new();
106     let mut notified1 = spawn(async { notify.notified().await });
107     let mut notified2 = spawn(async { notify.notified().await });
108 
109     assert_pending!(notified1.poll());
110 
111     drop(notified1);
112 
113     assert_pending!(notified2.poll());
114 
115     notify.notify_one();
116     assert!(notified2.is_woken());
117     assert_ready!(notified2.poll());
118 }
119 
120 #[test]
notified_multi_notify_drop_one()121 fn notified_multi_notify_drop_one() {
122     let notify = Notify::new();
123     let mut notified1 = spawn(async { notify.notified().await });
124     let mut notified2 = spawn(async { notify.notified().await });
125 
126     assert_pending!(notified1.poll());
127     assert_pending!(notified2.poll());
128 
129     notify.notify_one();
130 
131     assert!(notified1.is_woken());
132     assert!(!notified2.is_woken());
133 
134     drop(notified1);
135 
136     assert!(notified2.is_woken());
137     assert_ready!(notified2.poll());
138 }
139 
140 #[test]
notified_multi_notify_one_drop()141 fn notified_multi_notify_one_drop() {
142     let notify = Notify::new();
143     let mut notified1 = spawn(async { notify.notified().await });
144     let mut notified2 = spawn(async { notify.notified().await });
145     let mut notified3 = spawn(async { notify.notified().await });
146 
147     // add waiters by order of poll execution
148     assert_pending!(notified1.poll());
149     assert_pending!(notified2.poll());
150     assert_pending!(notified3.poll());
151 
152     // by default fifo
153     notify.notify_one();
154 
155     drop(notified1);
156 
157     // next waiter should be the one to be to woken up
158     assert_ready!(notified2.poll());
159     assert_pending!(notified3.poll());
160 }
161 
162 #[test]
notified_multi_notify_last_drop()163 fn notified_multi_notify_last_drop() {
164     let notify = Notify::new();
165     let mut notified1 = spawn(async { notify.notified().await });
166     let mut notified2 = spawn(async { notify.notified().await });
167     let mut notified3 = spawn(async { notify.notified().await });
168 
169     // add waiters by order of poll execution
170     assert_pending!(notified1.poll());
171     assert_pending!(notified2.poll());
172     assert_pending!(notified3.poll());
173 
174     notify.notify_last();
175 
176     drop(notified3);
177 
178     // latest waiter added should be the one to woken up
179     assert_ready!(notified2.poll());
180     assert_pending!(notified1.poll());
181 }
182 
183 #[test]
notify_in_drop_after_wake()184 fn notify_in_drop_after_wake() {
185     use futures::task::ArcWake;
186     use std::future::Future;
187     use std::sync::Arc;
188 
189     let notify = Arc::new(Notify::new());
190 
191     struct NotifyOnDrop(Arc<Notify>);
192 
193     impl ArcWake for NotifyOnDrop {
194         fn wake_by_ref(_arc_self: &Arc<Self>) {}
195     }
196 
197     impl Drop for NotifyOnDrop {
198         fn drop(&mut self) {
199             self.0.notify_waiters();
200         }
201     }
202 
203     let mut fut = Box::pin(async {
204         notify.notified().await;
205     });
206 
207     {
208         let waker = futures::task::waker(Arc::new(NotifyOnDrop(notify.clone())));
209         let mut cx = std::task::Context::from_waker(&waker);
210         assert!(fut.as_mut().poll(&mut cx).is_pending());
211     }
212 
213     // Now, notifying **should not** deadlock
214     notify.notify_waiters();
215 }
216 
217 #[test]
notify_one_after_dropped_all()218 fn notify_one_after_dropped_all() {
219     let notify = Notify::new();
220     let mut notified1 = spawn(async { notify.notified().await });
221 
222     assert_pending!(notified1.poll());
223 
224     notify.notify_waiters();
225     notify.notify_one();
226 
227     drop(notified1);
228 
229     let mut notified2 = spawn(async { notify.notified().await });
230 
231     assert_ready!(notified2.poll());
232 }
233 
234 #[test]
test_notify_one_not_enabled()235 fn test_notify_one_not_enabled() {
236     let notify = Notify::new();
237     let mut future = spawn(notify.notified());
238 
239     notify.notify_one();
240     assert_ready!(future.poll());
241 }
242 
243 #[test]
test_notify_one_after_enable()244 fn test_notify_one_after_enable() {
245     let notify = Notify::new();
246     let mut future = spawn(notify.notified());
247 
248     future.enter(|_, fut| assert!(!fut.enable()));
249 
250     notify.notify_one();
251     assert_ready!(future.poll());
252     future.enter(|_, fut| assert!(fut.enable()));
253 }
254 
255 #[test]
test_poll_after_enable()256 fn test_poll_after_enable() {
257     let notify = Notify::new();
258     let mut future = spawn(notify.notified());
259 
260     future.enter(|_, fut| assert!(!fut.enable()));
261     assert_pending!(future.poll());
262 }
263 
264 #[test]
test_enable_after_poll()265 fn test_enable_after_poll() {
266     let notify = Notify::new();
267     let mut future = spawn(notify.notified());
268 
269     assert_pending!(future.poll());
270     future.enter(|_, fut| assert!(!fut.enable()));
271 }
272 
273 #[test]
test_enable_consumes_permit()274 fn test_enable_consumes_permit() {
275     let notify = Notify::new();
276 
277     // Add a permit.
278     notify.notify_one();
279 
280     let mut future1 = spawn(notify.notified());
281     future1.enter(|_, fut| assert!(fut.enable()));
282 
283     let mut future2 = spawn(notify.notified());
284     future2.enter(|_, fut| assert!(!fut.enable()));
285 }
286 
287 #[test]
test_waker_update()288 fn test_waker_update() {
289     use futures::task::noop_waker;
290     use std::future::Future;
291     use std::task::Context;
292 
293     let notify = Notify::new();
294     let mut future = spawn(notify.notified());
295 
296     let noop = noop_waker();
297     future.enter(|_, fut| assert_pending!(fut.poll(&mut Context::from_waker(&noop))));
298 
299     assert_pending!(future.poll());
300     notify.notify_one();
301 
302     assert!(future.is_woken());
303 }
304