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