• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 trait AssertSend: Send + Sync {}
12 impl AssertSend for Notify {}
13 
14 #[test]
notify_notified_one()15 fn notify_notified_one() {
16     let notify = Notify::new();
17     let mut notified = spawn(async { notify.notified().await });
18 
19     notify.notify_one();
20     assert_ready!(notified.poll());
21 }
22 
23 #[test]
notified_one_notify()24 fn notified_one_notify() {
25     let notify = Notify::new();
26     let mut notified = spawn(async { notify.notified().await });
27 
28     assert_pending!(notified.poll());
29 
30     notify.notify_one();
31     assert!(notified.is_woken());
32     assert_ready!(notified.poll());
33 }
34 
35 #[test]
notified_multi_notify()36 fn notified_multi_notify() {
37     let notify = Notify::new();
38     let mut notified1 = spawn(async { notify.notified().await });
39     let mut notified2 = spawn(async { notify.notified().await });
40 
41     assert_pending!(notified1.poll());
42     assert_pending!(notified2.poll());
43 
44     notify.notify_one();
45     assert!(notified1.is_woken());
46     assert!(!notified2.is_woken());
47 
48     assert_ready!(notified1.poll());
49     assert_pending!(notified2.poll());
50 }
51 
52 #[test]
notify_notified_multi()53 fn notify_notified_multi() {
54     let notify = Notify::new();
55 
56     notify.notify_one();
57 
58     let mut notified1 = spawn(async { notify.notified().await });
59     let mut notified2 = spawn(async { notify.notified().await });
60 
61     assert_ready!(notified1.poll());
62     assert_pending!(notified2.poll());
63 
64     notify.notify_one();
65 
66     assert!(notified2.is_woken());
67     assert_ready!(notified2.poll());
68 }
69 
70 #[test]
notified_drop_notified_notify()71 fn notified_drop_notified_notify() {
72     let notify = Notify::new();
73     let mut notified1 = spawn(async { notify.notified().await });
74     let mut notified2 = spawn(async { notify.notified().await });
75 
76     assert_pending!(notified1.poll());
77 
78     drop(notified1);
79 
80     assert_pending!(notified2.poll());
81 
82     notify.notify_one();
83     assert!(notified2.is_woken());
84     assert_ready!(notified2.poll());
85 }
86 
87 #[test]
notified_multi_notify_drop_one()88 fn notified_multi_notify_drop_one() {
89     let notify = Notify::new();
90     let mut notified1 = spawn(async { notify.notified().await });
91     let mut notified2 = spawn(async { notify.notified().await });
92 
93     assert_pending!(notified1.poll());
94     assert_pending!(notified2.poll());
95 
96     notify.notify_one();
97 
98     assert!(notified1.is_woken());
99     assert!(!notified2.is_woken());
100 
101     drop(notified1);
102 
103     assert!(notified2.is_woken());
104     assert_ready!(notified2.poll());
105 }
106 
107 #[test]
notify_in_drop_after_wake()108 fn notify_in_drop_after_wake() {
109     use futures::task::ArcWake;
110     use std::future::Future;
111     use std::sync::Arc;
112 
113     let notify = Arc::new(Notify::new());
114 
115     struct NotifyOnDrop(Arc<Notify>);
116 
117     impl ArcWake for NotifyOnDrop {
118         fn wake_by_ref(_arc_self: &Arc<Self>) {}
119     }
120 
121     impl Drop for NotifyOnDrop {
122         fn drop(&mut self) {
123             self.0.notify_waiters();
124         }
125     }
126 
127     let mut fut = Box::pin(async {
128         notify.notified().await;
129     });
130 
131     {
132         let waker = futures::task::waker(Arc::new(NotifyOnDrop(notify.clone())));
133         let mut cx = std::task::Context::from_waker(&waker);
134         assert!(fut.as_mut().poll(&mut cx).is_pending());
135     }
136 
137     // Now, notifying **should not** deadlock
138     notify.notify_waiters();
139 }
140 
141 #[test]
notify_one_after_dropped_all()142 fn notify_one_after_dropped_all() {
143     let notify = Notify::new();
144     let mut notified1 = spawn(async { notify.notified().await });
145 
146     assert_pending!(notified1.poll());
147 
148     notify.notify_waiters();
149     notify.notify_one();
150 
151     drop(notified1);
152 
153     let mut notified2 = spawn(async { notify.notified().await });
154 
155     assert_ready!(notified2.poll());
156 }
157 
158 #[test]
test_notify_one_not_enabled()159 fn test_notify_one_not_enabled() {
160     let notify = Notify::new();
161     let mut future = spawn(notify.notified());
162 
163     notify.notify_one();
164     assert_ready!(future.poll());
165 }
166 
167 #[test]
test_notify_one_after_enable()168 fn test_notify_one_after_enable() {
169     let notify = Notify::new();
170     let mut future = spawn(notify.notified());
171 
172     future.enter(|_, fut| assert!(!fut.enable()));
173 
174     notify.notify_one();
175     assert_ready!(future.poll());
176     future.enter(|_, fut| assert!(fut.enable()));
177 }
178 
179 #[test]
test_poll_after_enable()180 fn test_poll_after_enable() {
181     let notify = Notify::new();
182     let mut future = spawn(notify.notified());
183 
184     future.enter(|_, fut| assert!(!fut.enable()));
185     assert_pending!(future.poll());
186 }
187 
188 #[test]
test_enable_after_poll()189 fn test_enable_after_poll() {
190     let notify = Notify::new();
191     let mut future = spawn(notify.notified());
192 
193     assert_pending!(future.poll());
194     future.enter(|_, fut| assert!(!fut.enable()));
195 }
196 
197 #[test]
test_enable_consumes_permit()198 fn test_enable_consumes_permit() {
199     let notify = Notify::new();
200 
201     // Add a permit.
202     notify.notify_one();
203 
204     let mut future1 = spawn(notify.notified());
205     future1.enter(|_, fut| assert!(fut.enable()));
206 
207     let mut future2 = spawn(notify.notified());
208     future2.enter(|_, fut| assert!(!fut.enable()));
209 }
210 
211 #[test]
test_waker_update()212 fn test_waker_update() {
213     use futures::task::noop_waker;
214     use std::future::Future;
215     use std::task::Context;
216 
217     let notify = Notify::new();
218     let mut future = spawn(notify.notified());
219 
220     let noop = noop_waker();
221     future.enter(|_, fut| assert_pending!(fut.poll(&mut Context::from_waker(&noop))));
222 
223     assert_pending!(future.poll());
224     notify.notify_one();
225 
226     assert!(future.is_woken());
227 }
228