]> git.lizzy.rs Git - rust.git/blob - library/std/src/sync/mutex/tests.rs
Rollup merge of #107391 - notriddle:notriddle/copy-path-button, r=GuillaumeGomez
[rust.git] / library / std / src / sync / mutex / tests.rs
1 use crate::sync::atomic::{AtomicUsize, Ordering};
2 use crate::sync::mpsc::channel;
3 use crate::sync::{Arc, Condvar, Mutex};
4 use crate::thread;
5
6 struct Packet<T>(Arc<(Mutex<T>, Condvar)>);
7
8 #[derive(Eq, PartialEq, Debug)]
9 struct NonCopy(i32);
10
11 #[test]
12 fn smoke() {
13     let m = Mutex::new(());
14     drop(m.lock().unwrap());
15     drop(m.lock().unwrap());
16 }
17
18 #[test]
19 fn lots_and_lots() {
20     const J: u32 = 1000;
21     const K: u32 = 3;
22
23     let m = Arc::new(Mutex::new(0));
24
25     fn inc(m: &Mutex<u32>) {
26         for _ in 0..J {
27             *m.lock().unwrap() += 1;
28         }
29     }
30
31     let (tx, rx) = channel();
32     for _ in 0..K {
33         let tx2 = tx.clone();
34         let m2 = m.clone();
35         thread::spawn(move || {
36             inc(&m2);
37             tx2.send(()).unwrap();
38         });
39         let tx2 = tx.clone();
40         let m2 = m.clone();
41         thread::spawn(move || {
42             inc(&m2);
43             tx2.send(()).unwrap();
44         });
45     }
46
47     drop(tx);
48     for _ in 0..2 * K {
49         rx.recv().unwrap();
50     }
51     assert_eq!(*m.lock().unwrap(), J * K * 2);
52 }
53
54 #[test]
55 fn try_lock() {
56     let m = Mutex::new(());
57     *m.try_lock().unwrap() = ();
58 }
59
60 #[test]
61 fn test_into_inner() {
62     let m = Mutex::new(NonCopy(10));
63     assert_eq!(m.into_inner().unwrap(), NonCopy(10));
64 }
65
66 #[test]
67 fn test_into_inner_drop() {
68     struct Foo(Arc<AtomicUsize>);
69     impl Drop for Foo {
70         fn drop(&mut self) {
71             self.0.fetch_add(1, Ordering::SeqCst);
72         }
73     }
74     let num_drops = Arc::new(AtomicUsize::new(0));
75     let m = Mutex::new(Foo(num_drops.clone()));
76     assert_eq!(num_drops.load(Ordering::SeqCst), 0);
77     {
78         let _inner = m.into_inner().unwrap();
79         assert_eq!(num_drops.load(Ordering::SeqCst), 0);
80     }
81     assert_eq!(num_drops.load(Ordering::SeqCst), 1);
82 }
83
84 #[test]
85 fn test_into_inner_poison() {
86     let m = Arc::new(Mutex::new(NonCopy(10)));
87     let m2 = m.clone();
88     let _ = thread::spawn(move || {
89         let _lock = m2.lock().unwrap();
90         panic!("test panic in inner thread to poison mutex");
91     })
92     .join();
93
94     assert!(m.is_poisoned());
95     match Arc::try_unwrap(m).unwrap().into_inner() {
96         Err(e) => assert_eq!(e.into_inner(), NonCopy(10)),
97         Ok(x) => panic!("into_inner of poisoned Mutex is Ok: {x:?}"),
98     }
99 }
100
101 #[test]
102 fn test_get_mut() {
103     let mut m = Mutex::new(NonCopy(10));
104     *m.get_mut().unwrap() = NonCopy(20);
105     assert_eq!(m.into_inner().unwrap(), NonCopy(20));
106 }
107
108 #[test]
109 fn test_get_mut_poison() {
110     let m = Arc::new(Mutex::new(NonCopy(10)));
111     let m2 = m.clone();
112     let _ = thread::spawn(move || {
113         let _lock = m2.lock().unwrap();
114         panic!("test panic in inner thread to poison mutex");
115     })
116     .join();
117
118     assert!(m.is_poisoned());
119     match Arc::try_unwrap(m).unwrap().get_mut() {
120         Err(e) => assert_eq!(*e.into_inner(), NonCopy(10)),
121         Ok(x) => panic!("get_mut of poisoned Mutex is Ok: {x:?}"),
122     }
123 }
124
125 #[test]
126 fn test_mutex_arc_condvar() {
127     let packet = Packet(Arc::new((Mutex::new(false), Condvar::new())));
128     let packet2 = Packet(packet.0.clone());
129     let (tx, rx) = channel();
130     let _t = thread::spawn(move || {
131         // wait until parent gets in
132         rx.recv().unwrap();
133         let &(ref lock, ref cvar) = &*packet2.0;
134         let mut lock = lock.lock().unwrap();
135         *lock = true;
136         cvar.notify_one();
137     });
138
139     let &(ref lock, ref cvar) = &*packet.0;
140     let mut lock = lock.lock().unwrap();
141     tx.send(()).unwrap();
142     assert!(!*lock);
143     while !*lock {
144         lock = cvar.wait(lock).unwrap();
145     }
146 }
147
148 #[test]
149 fn test_arc_condvar_poison() {
150     let packet = Packet(Arc::new((Mutex::new(1), Condvar::new())));
151     let packet2 = Packet(packet.0.clone());
152     let (tx, rx) = channel();
153
154     let _t = thread::spawn(move || -> () {
155         rx.recv().unwrap();
156         let &(ref lock, ref cvar) = &*packet2.0;
157         let _g = lock.lock().unwrap();
158         cvar.notify_one();
159         // Parent should fail when it wakes up.
160         panic!();
161     });
162
163     let &(ref lock, ref cvar) = &*packet.0;
164     let mut lock = lock.lock().unwrap();
165     tx.send(()).unwrap();
166     while *lock == 1 {
167         match cvar.wait(lock) {
168             Ok(l) => {
169                 lock = l;
170                 assert_eq!(*lock, 1);
171             }
172             Err(..) => break,
173         }
174     }
175 }
176
177 #[test]
178 fn test_mutex_arc_poison() {
179     let arc = Arc::new(Mutex::new(1));
180     assert!(!arc.is_poisoned());
181     let arc2 = arc.clone();
182     let _ = thread::spawn(move || {
183         let lock = arc2.lock().unwrap();
184         assert_eq!(*lock, 2); // deliberate assertion failure to poison the mutex
185     })
186     .join();
187     assert!(arc.lock().is_err());
188     assert!(arc.is_poisoned());
189 }
190
191 #[test]
192 fn test_mutex_arc_nested() {
193     // Tests nested mutexes and access
194     // to underlying data.
195     let arc = Arc::new(Mutex::new(1));
196     let arc2 = Arc::new(Mutex::new(arc));
197     let (tx, rx) = channel();
198     let _t = thread::spawn(move || {
199         let lock = arc2.lock().unwrap();
200         let lock2 = lock.lock().unwrap();
201         assert_eq!(*lock2, 1);
202         tx.send(()).unwrap();
203     });
204     rx.recv().unwrap();
205 }
206
207 #[test]
208 fn test_mutex_arc_access_in_unwind() {
209     let arc = Arc::new(Mutex::new(1));
210     let arc2 = arc.clone();
211     let _ = thread::spawn(move || -> () {
212         struct Unwinder {
213             i: Arc<Mutex<i32>>,
214         }
215         impl Drop for Unwinder {
216             fn drop(&mut self) {
217                 *self.i.lock().unwrap() += 1;
218             }
219         }
220         let _u = Unwinder { i: arc2 };
221         panic!();
222     })
223     .join();
224     let lock = arc.lock().unwrap();
225     assert_eq!(*lock, 2);
226 }
227
228 #[test]
229 fn test_mutex_unsized() {
230     let mutex: &Mutex<[i32]> = &Mutex::new([1, 2, 3]);
231     {
232         let b = &mut *mutex.lock().unwrap();
233         b[0] = 4;
234         b[2] = 5;
235     }
236     let comp: &[i32] = &[4, 2, 5];
237     assert_eq!(&*mutex.lock().unwrap(), comp);
238 }