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] |
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] |
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] |
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] |
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] |
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] |
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] |
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] |
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] |
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] |
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] |
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] |
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] |
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] |
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 | |