1 #![warn(rust_2018_idioms)]
2 #![cfg(feature = "full")]
3 
4 use tokio::sync::Mutex;
5 use tokio::time::{interval, timeout};
6 use tokio_test::task::spawn;
7 use tokio_test::{assert_pending, assert_ready};
8 
9 use std::sync::Arc;
10 use std::time::Duration;
11 
12 #[test]
straight_execution()13 fn straight_execution() {
14     let l = Mutex::new(100);
15 
16     {
17         let mut t = spawn(l.lock());
18         let mut g = assert_ready!(t.poll());
19         assert_eq!(&*g, &100);
20         *g = 99;
21     }
22     {
23         let mut t = spawn(l.lock());
24         let mut g = assert_ready!(t.poll());
25         assert_eq!(&*g, &99);
26         *g = 98;
27     }
28     {
29         let mut t = spawn(l.lock());
30         let g = assert_ready!(t.poll());
31         assert_eq!(&*g, &98);
32     }
33 }
34 
35 #[test]
readiness()36 fn readiness() {
37     let l1 = Arc::new(Mutex::new(100));
38     let l2 = Arc::clone(&l1);
39     let mut t1 = spawn(l1.lock());
40     let mut t2 = spawn(l2.lock());
41 
42     let g = assert_ready!(t1.poll());
43 
44     // We can't now acquire the lease since it's already held in g
45     assert_pending!(t2.poll());
46 
47     // But once g unlocks, we can acquire it
48     drop(g);
49     assert!(t2.is_woken());
50     assert_ready!(t2.poll());
51 }
52 
53 /*
54 #[test]
55 #[ignore]
56 fn lock() {
57     let mut lock = Mutex::new(false);
58 
59     let mut lock2 = lock.clone();
60     std::thread::spawn(move || {
61         let l = lock2.lock();
62         pin_mut!(l);
63 
64         let mut task = MockTask::new();
65         let mut g = assert_ready!(task.poll(&mut l));
66         std::thread::sleep(std::time::Duration::from_millis(500));
67         *g = true;
68         drop(g);
69     });
70 
71     std::thread::sleep(std::time::Duration::from_millis(50));
72     let mut task = MockTask::new();
73     let l = lock.lock();
74     pin_mut!(l);
75 
76     assert_pending!(task.poll(&mut l));
77 
78     std::thread::sleep(std::time::Duration::from_millis(500));
79     assert!(task.is_woken());
80     let result = assert_ready!(task.poll(&mut l));
81     assert!(*result);
82 }
83 */
84 
85 #[tokio::test]
86 /// Ensure a mutex is unlocked if a future holding the lock
87 /// is aborted prematurely.
aborted_future_1()88 async fn aborted_future_1() {
89     let m1: Arc<Mutex<usize>> = Arc::new(Mutex::new(0));
90     {
91         let m2 = m1.clone();
92         // Try to lock mutex in a future that is aborted prematurely
93         timeout(Duration::from_millis(1u64), async move {
94             let iv = interval(Duration::from_millis(1000));
95             tokio::pin!(iv);
96             m2.lock().await;
97             iv.as_mut().tick().await;
98             iv.as_mut().tick().await;
99         })
100         .await
101         .unwrap_err();
102     }
103     // This should succeed as there is no lock left for the mutex.
104     timeout(Duration::from_millis(1u64), async move {
105         m1.lock().await;
106     })
107     .await
108     .expect("Mutex is locked");
109 }
110 
111 #[tokio::test]
112 /// This test is similar to `aborted_future_1` but this time the
113 /// aborted future is waiting for the lock.
aborted_future_2()114 async fn aborted_future_2() {
115     let m1: Arc<Mutex<usize>> = Arc::new(Mutex::new(0));
116     {
117         // Lock mutex
118         let _lock = m1.lock().await;
119         {
120             let m2 = m1.clone();
121             // Try to lock mutex in a future that is aborted prematurely
122             timeout(Duration::from_millis(1u64), async move {
123                 m2.lock().await;
124             })
125             .await
126             .unwrap_err();
127         }
128     }
129     // This should succeed as there is no lock left for the mutex.
130     timeout(Duration::from_millis(1u64), async move {
131         m1.lock().await;
132     })
133     .await
134     .expect("Mutex is locked");
135 }
136 
137 #[test]
try_lock()138 fn try_lock() {
139     let m: Mutex<usize> = Mutex::new(0);
140     {
141         let g1 = m.try_lock();
142         assert!(g1.is_ok());
143         let g2 = m.try_lock();
144         assert!(!g2.is_ok());
145     }
146     let g3 = m.try_lock();
147     assert!(g3.is_ok());
148 }
149 
150 #[tokio::test]
debug_format()151 async fn debug_format() {
152     let s = "debug";
153     let m = Mutex::new(s.to_string());
154     assert_eq!(format!("{:?}", s), format!("{:?}", m.lock().await));
155 }
156 
157 #[tokio::test]
mutex_debug()158 async fn mutex_debug() {
159     let s = "data";
160     let m = Mutex::new(s.to_string());
161     assert_eq!(format!("{:?}", m), r#"Mutex { data: "data" }"#);
162     let _guard = m.lock().await;
163     assert_eq!(format!("{:?}", m), r#"Mutex { data: <locked> }"#)
164 }
165