1 #![warn(rust_2018_idioms)]
2 #![cfg(feature = "full")]
3 
4 use tokio::sync::Notify;
5 use tokio_test::task::spawn;
6 use tokio_test::*;
7 
8 trait AssertSend: Send + Sync {}
9 impl AssertSend for Notify {}
10 
11 #[test]
notify_notified_one()12 fn notify_notified_one() {
13     let notify = Notify::new();
14     let mut notified = spawn(async { notify.notified().await });
15 
16     notify.notify_one();
17     assert_ready!(notified.poll());
18 }
19 
20 #[test]
notified_one_notify()21 fn notified_one_notify() {
22     let notify = Notify::new();
23     let mut notified = spawn(async { notify.notified().await });
24 
25     assert_pending!(notified.poll());
26 
27     notify.notify_one();
28     assert!(notified.is_woken());
29     assert_ready!(notified.poll());
30 }
31 
32 #[test]
notified_multi_notify()33 fn notified_multi_notify() {
34     let notify = Notify::new();
35     let mut notified1 = spawn(async { notify.notified().await });
36     let mut notified2 = spawn(async { notify.notified().await });
37 
38     assert_pending!(notified1.poll());
39     assert_pending!(notified2.poll());
40 
41     notify.notify_one();
42     assert!(notified1.is_woken());
43     assert!(!notified2.is_woken());
44 
45     assert_ready!(notified1.poll());
46     assert_pending!(notified2.poll());
47 }
48 
49 #[test]
notify_notified_multi()50 fn notify_notified_multi() {
51     let notify = Notify::new();
52 
53     notify.notify_one();
54 
55     let mut notified1 = spawn(async { notify.notified().await });
56     let mut notified2 = spawn(async { notify.notified().await });
57 
58     assert_ready!(notified1.poll());
59     assert_pending!(notified2.poll());
60 
61     notify.notify_one();
62 
63     assert!(notified2.is_woken());
64     assert_ready!(notified2.poll());
65 }
66 
67 #[test]
notified_drop_notified_notify()68 fn notified_drop_notified_notify() {
69     let notify = Notify::new();
70     let mut notified1 = spawn(async { notify.notified().await });
71     let mut notified2 = spawn(async { notify.notified().await });
72 
73     assert_pending!(notified1.poll());
74 
75     drop(notified1);
76 
77     assert_pending!(notified2.poll());
78 
79     notify.notify_one();
80     assert!(notified2.is_woken());
81     assert_ready!(notified2.poll());
82 }
83 
84 #[test]
notified_multi_notify_drop_one()85 fn notified_multi_notify_drop_one() {
86     let notify = Notify::new();
87     let mut notified1 = spawn(async { notify.notified().await });
88     let mut notified2 = spawn(async { notify.notified().await });
89 
90     assert_pending!(notified1.poll());
91     assert_pending!(notified2.poll());
92 
93     notify.notify_one();
94 
95     assert!(notified1.is_woken());
96     assert!(!notified2.is_woken());
97 
98     drop(notified1);
99 
100     assert!(notified2.is_woken());
101     assert_ready!(notified2.poll());
102 }
103 
104 #[test]
notify_in_drop_after_wake()105 fn notify_in_drop_after_wake() {
106     use futures::task::ArcWake;
107     use std::future::Future;
108     use std::sync::Arc;
109 
110     let notify = Arc::new(Notify::new());
111 
112     struct NotifyOnDrop(Arc<Notify>);
113 
114     impl ArcWake for NotifyOnDrop {
115         fn wake_by_ref(_arc_self: &Arc<Self>) {}
116     }
117 
118     impl Drop for NotifyOnDrop {
119         fn drop(&mut self) {
120             self.0.notify_waiters();
121         }
122     }
123 
124     let mut fut = Box::pin(async {
125         notify.notified().await;
126     });
127 
128     {
129         let waker = futures::task::waker(Arc::new(NotifyOnDrop(notify.clone())));
130         let mut cx = std::task::Context::from_waker(&waker);
131         assert!(fut.as_mut().poll(&mut cx).is_pending());
132     }
133 
134     // Now, notifying **should not** deadlock
135     notify.notify_waiters();
136 }
137 
138 #[test]
notify_one_after_dropped_all()139 fn notify_one_after_dropped_all() {
140     let notify = Notify::new();
141     let mut notified1 = spawn(async { notify.notified().await });
142 
143     assert_pending!(notified1.poll());
144 
145     notify.notify_waiters();
146     notify.notify_one();
147 
148     drop(notified1);
149 
150     let mut notified2 = spawn(async { notify.notified().await });
151 
152     assert_ready!(notified2.poll());
153 }
154