1#![warn(rust_2018_idioms)]
2#![cfg(feature = "sync")]
3
4#[cfg(all(target_family = "wasm", not(target_os = "wasi")))]
5use wasm_bindgen_test::wasm_bindgen_test as test;
6
7use tokio::sync::Notify;
8use tokio_test::task::spawn;
9use tokio_test::*;
10
11trait AssertSend: Send + Sync {}
12impl AssertSend for Notify {}
13
14#[test]
15fn 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]
24fn 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]
36fn 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]
53fn 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]
71fn 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]
88fn 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]
108fn 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]
142fn 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]
159fn 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]
168fn 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]
180fn 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]
189fn 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]
198fn 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]
212fn 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