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_eq!(g1.is_ok(), true);
143 let g2 = m.try_lock();
144 assert_eq!(g2.is_ok(), false);
145 }
146 let g3 = m.try_lock();
147 assert_eq!(g3.is_ok(), true);
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