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_eq!(g1.is_ok(), true);
110 let g2 = m.clone().try_lock_owned();
111 assert_eq!(g2.is_ok(), false);
112 }
113 let g3 = m.try_lock_owned();
114 assert_eq!(g3.is_ok(), true);
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