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 | #[cfg (all(target_family = "wasm" , not(target_os = "wasi" )))] |
7 | use wasm_bindgen_test::wasm_bindgen_test as maybe_tokio_test; |
8 | |
9 | #[cfg (not(all(target_family = "wasm" , not(target_os = "wasi" ))))] |
10 | use tokio::test as maybe_tokio_test ; |
11 | |
12 | use tokio::sync::Mutex; |
13 | use tokio_test::task::spawn; |
14 | use tokio_test::{assert_pending, assert_ready}; |
15 | |
16 | use std::sync::Arc; |
17 | |
18 | #[test] |
19 | fn straight_execution() { |
20 | let l = Arc::new(Mutex::new(100)); |
21 | |
22 | { |
23 | let mut t = spawn(l.clone().lock_owned()); |
24 | let mut g = assert_ready!(t.poll()); |
25 | assert_eq!(&*g, &100); |
26 | *g = 99; |
27 | } |
28 | { |
29 | let mut t = spawn(l.clone().lock_owned()); |
30 | let mut g = assert_ready!(t.poll()); |
31 | assert_eq!(&*g, &99); |
32 | *g = 98; |
33 | } |
34 | { |
35 | let mut t = spawn(l.lock_owned()); |
36 | let g = assert_ready!(t.poll()); |
37 | assert_eq!(&*g, &98); |
38 | } |
39 | } |
40 | |
41 | #[test] |
42 | fn readiness() { |
43 | let l = Arc::new(Mutex::new(100)); |
44 | let mut t1 = spawn(l.clone().lock_owned()); |
45 | let mut t2 = spawn(l.lock_owned()); |
46 | |
47 | let g = assert_ready!(t1.poll()); |
48 | |
49 | // We can't now acquire the lease since it's already held in g |
50 | assert_pending!(t2.poll()); |
51 | |
52 | // But once g unlocks, we can acquire it |
53 | drop(g); |
54 | assert!(t2.is_woken()); |
55 | assert_ready!(t2.poll()); |
56 | } |
57 | |
58 | /// Ensure a mutex is unlocked if a future holding the lock |
59 | /// is aborted prematurely. |
60 | #[tokio::test ] |
61 | #[cfg (feature = "full" )] |
62 | async fn aborted_future_1() { |
63 | use std::time::Duration; |
64 | use tokio::time::{interval, timeout}; |
65 | |
66 | let m1: Arc<Mutex<usize>> = Arc::new(Mutex::new(0)); |
67 | { |
68 | let m2 = m1.clone(); |
69 | // Try to lock mutex in a future that is aborted prematurely |
70 | timeout(Duration::from_millis(1u64), async move { |
71 | let iv = interval(Duration::from_millis(1000)); |
72 | tokio::pin!(iv); |
73 | m2.lock_owned().await; |
74 | iv.as_mut().tick().await; |
75 | iv.as_mut().tick().await; |
76 | }) |
77 | .await |
78 | .unwrap_err(); |
79 | } |
80 | // This should succeed as there is no lock left for the mutex. |
81 | timeout(Duration::from_millis(1u64), async move { |
82 | m1.lock_owned().await; |
83 | }) |
84 | .await |
85 | .expect("Mutex is locked" ); |
86 | } |
87 | |
88 | /// This test is similar to `aborted_future_1` but this time the |
89 | /// aborted future is waiting for the lock. |
90 | #[tokio::test ] |
91 | #[cfg (feature = "full" )] |
92 | async fn aborted_future_2() { |
93 | use std::time::Duration; |
94 | use tokio::time::timeout; |
95 | |
96 | let m1: Arc<Mutex<usize>> = Arc::new(Mutex::new(0)); |
97 | { |
98 | // Lock mutex |
99 | let _lock = m1.clone().lock_owned().await; |
100 | { |
101 | let m2 = m1.clone(); |
102 | // Try to lock mutex in a future that is aborted prematurely |
103 | timeout(Duration::from_millis(1u64), async move { |
104 | m2.lock_owned().await; |
105 | }) |
106 | .await |
107 | .unwrap_err(); |
108 | } |
109 | } |
110 | // This should succeed as there is no lock left for the mutex. |
111 | timeout(Duration::from_millis(1u64), async move { |
112 | m1.lock_owned().await; |
113 | }) |
114 | .await |
115 | .expect("Mutex is locked" ); |
116 | } |
117 | |
118 | #[test] |
119 | fn try_lock_owned() { |
120 | let m: Arc<Mutex<usize>> = Arc::new(Mutex::new(0)); |
121 | { |
122 | let g1 = m.clone().try_lock_owned(); |
123 | assert!(g1.is_ok()); |
124 | let g2 = m.clone().try_lock_owned(); |
125 | assert!(g2.is_err()); |
126 | } |
127 | let g3 = m.try_lock_owned(); |
128 | assert!(g3.is_ok()); |
129 | } |
130 | |
131 | #[maybe_tokio_test ] |
132 | async fn debug_format() { |
133 | let s = "debug" ; |
134 | let m = Arc::new(Mutex::new(s.to_string())); |
135 | assert_eq!(format!("{:?}" , s), format!("{:?}" , m.lock_owned().await)); |
136 | } |
137 | |