1 | use crate::sync::AtomicWaker; |
2 | use tokio_test::task; |
3 | |
4 | use std::task::Waker; |
5 | |
6 | trait AssertSend: Send {} |
7 | trait AssertSync: Sync {} |
8 | |
9 | impl AssertSend for AtomicWaker {} |
10 | impl AssertSync for AtomicWaker {} |
11 | |
12 | impl AssertSend for Waker {} |
13 | impl AssertSync for Waker {} |
14 | |
15 | #[cfg (all(target_family = "wasm" , not(target_os = "wasi" )))] |
16 | use wasm_bindgen_test::wasm_bindgen_test as test; |
17 | |
18 | #[test] |
19 | fn basic_usage() { |
20 | let mut waker = task::spawn(AtomicWaker::new()); |
21 | |
22 | waker.enter(|cx, waker| waker.register_by_ref(cx.waker())); |
23 | waker.wake(); |
24 | |
25 | assert!(waker.is_woken()); |
26 | } |
27 | |
28 | #[test] |
29 | fn wake_without_register() { |
30 | let mut waker = task::spawn(AtomicWaker::new()); |
31 | waker.wake(); |
32 | |
33 | // Registering should not result in a notification |
34 | waker.enter(|cx, waker| waker.register_by_ref(cx.waker())); |
35 | |
36 | assert!(!waker.is_woken()); |
37 | } |
38 | |
39 | #[cfg (panic = "unwind" )] |
40 | #[test] |
41 | #[cfg (not(target_family = "wasm" ))] // wasm currently doesn't support unwinding |
42 | fn atomic_waker_panic_safe() { |
43 | use std::panic; |
44 | use std::ptr; |
45 | use std::task::{RawWaker, RawWakerVTable, Waker}; |
46 | |
47 | static PANICKING_VTABLE: RawWakerVTable = RawWakerVTable::new( |
48 | |_| panic!("clone" ), |
49 | |_| unimplemented!("wake" ), |
50 | |_| unimplemented!("wake_by_ref" ), |
51 | |_| (), |
52 | ); |
53 | |
54 | static NONPANICKING_VTABLE: RawWakerVTable = RawWakerVTable::new( |
55 | |_| RawWaker::new(ptr::null(), &NONPANICKING_VTABLE), |
56 | |_| unimplemented!("wake" ), |
57 | |_| unimplemented!("wake_by_ref" ), |
58 | |_| (), |
59 | ); |
60 | |
61 | let panicking = unsafe { Waker::from_raw(RawWaker::new(ptr::null(), &PANICKING_VTABLE)) }; |
62 | let nonpanicking = unsafe { Waker::from_raw(RawWaker::new(ptr::null(), &NONPANICKING_VTABLE)) }; |
63 | |
64 | let atomic_waker = AtomicWaker::new(); |
65 | |
66 | let panicking = panic::AssertUnwindSafe(&panicking); |
67 | |
68 | let result = panic::catch_unwind(|| { |
69 | let panic::AssertUnwindSafe(panicking) = panicking; |
70 | atomic_waker.register_by_ref(panicking); |
71 | }); |
72 | |
73 | assert!(result.is_err()); |
74 | assert!(atomic_waker.take_waker().is_none()); |
75 | |
76 | atomic_waker.register_by_ref(&nonpanicking); |
77 | assert!(atomic_waker.take_waker().is_some()); |
78 | } |
79 | |