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]
straight_execution()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]
readiness()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 #[cfg_attr(miri, ignore)]
aborted_future_1()63 async fn aborted_future_1() {
64 use std::time::Duration;
65 use tokio::time::{interval, timeout};
66
67 let m1: Arc<Mutex<usize>> = Arc::new(Mutex::new(0));
68 {
69 let m2 = m1.clone();
70 // Try to lock mutex in a future that is aborted prematurely
71 timeout(Duration::from_millis(1u64), async move {
72 let iv = interval(Duration::from_millis(1000));
73 tokio::pin!(iv);
74 m2.lock_owned().await;
75 iv.as_mut().tick().await;
76 iv.as_mut().tick().await;
77 })
78 .await
79 .unwrap_err();
80 }
81 // This should succeed as there is no lock left for the mutex.
82 timeout(Duration::from_millis(1u64), async move {
83 m1.lock_owned().await;
84 })
85 .await
86 .expect("Mutex is locked");
87 }
88
89 /// This test is similar to `aborted_future_1` but this time the
90 /// aborted future is waiting for the lock.
91 #[tokio::test]
92 #[cfg(feature = "full")]
aborted_future_2()93 async fn aborted_future_2() {
94 use std::time::Duration;
95 use tokio::time::timeout;
96
97 let m1: Arc<Mutex<usize>> = Arc::new(Mutex::new(0));
98 {
99 // Lock mutex
100 let _lock = m1.clone().lock_owned().await;
101 {
102 let m2 = m1.clone();
103 // Try to lock mutex in a future that is aborted prematurely
104 timeout(Duration::from_millis(1u64), async move {
105 m2.lock_owned().await;
106 })
107 .await
108 .unwrap_err();
109 }
110 }
111 // This should succeed as there is no lock left for the mutex.
112 timeout(Duration::from_millis(1u64), async move {
113 m1.lock_owned().await;
114 })
115 .await
116 .expect("Mutex is locked");
117 }
118
119 #[test]
try_lock_owned()120 fn try_lock_owned() {
121 let m: Arc<Mutex<usize>> = Arc::new(Mutex::new(0));
122 {
123 let g1 = m.clone().try_lock_owned();
124 assert!(g1.is_ok());
125 let g2 = m.clone().try_lock_owned();
126 assert!(g2.is_err());
127 }
128 let g3 = m.try_lock_owned();
129 assert!(g3.is_ok());
130 }
131
132 #[maybe_tokio_test]
debug_format()133 async fn debug_format() {
134 let s = "debug";
135 let m = Arc::new(Mutex::new(s.to_string()));
136 assert_eq!(format!("{s:?}"), format!("{:?}", m.lock_owned().await));
137 }
138