a3f746b11dc80dd32bd7badf5f9786acf6426a89
[rust-lightning] / lightning / src / sync / test_lockorder_checks.rs
1 use crate::sync::debug_sync::{RwLock, Mutex};
2
3 use super::{LockHeldState, LockTestExt};
4
5 use std::sync::Arc;
6 use std::thread;
7
8 #[test]
9 #[should_panic]
10 #[cfg(not(feature = "backtrace"))]
11 fn recursive_lock_fail() {
12         let mutex = Mutex::new(());
13         let _a = mutex.lock().unwrap();
14         let _b = mutex.lock().unwrap();
15 }
16
17 #[test]
18 fn recursive_read() {
19         let lock = RwLock::new(());
20         let _a = lock.read().unwrap();
21         let _b = lock.read().unwrap();
22 }
23
24 #[test]
25 #[should_panic]
26 fn lockorder_fail() {
27         let a = Mutex::new(());
28         let b = Mutex::new(());
29         {
30                 let _a = a.lock().unwrap();
31                 let _b = b.lock().unwrap();
32         }
33         {
34                 let _b = b.lock().unwrap();
35                 let _a = a.lock().unwrap();
36         }
37 }
38
39 #[test]
40 #[should_panic]
41 fn write_lockorder_fail() {
42         let a = RwLock::new(());
43         let b = RwLock::new(());
44         {
45                 let _a = a.write().unwrap();
46                 let _b = b.write().unwrap();
47         }
48         {
49                 let _b = b.write().unwrap();
50                 let _a = a.write().unwrap();
51         }
52 }
53
54 #[test]
55 #[should_panic]
56 fn read_lockorder_fail() {
57         let a = RwLock::new(());
58         let b = RwLock::new(());
59         {
60                 let _a = a.read().unwrap();
61                 let _b = b.read().unwrap();
62         }
63         {
64                 let _b = b.read().unwrap();
65                 let _a = a.read().unwrap();
66         }
67 }
68
69 #[test]
70 fn read_recursive_no_lockorder() {
71         // Like the above, but note that no lockorder is implied when we recursively read-lock a
72         // RwLock, causing this to pass just fine.
73         let a = RwLock::new(());
74         let b = RwLock::new(());
75         let _outer = a.read().unwrap();
76         {
77                 let _a = a.read().unwrap();
78                 let _b = b.read().unwrap();
79         }
80         {
81                 let _b = b.read().unwrap();
82                 let _a = a.read().unwrap();
83         }
84 }
85
86 #[test]
87 #[should_panic]
88 fn read_write_lockorder_fail() {
89         let a = RwLock::new(());
90         let b = RwLock::new(());
91         {
92                 let _a = a.write().unwrap();
93                 let _b = b.read().unwrap();
94         }
95         {
96                 let _b = b.read().unwrap();
97                 let _a = a.write().unwrap();
98         }
99 }
100
101 #[test]
102 fn test_thread_locked_state() {
103         let mtx = Arc::new(Mutex::new(()));
104         let mtx_ref = Arc::clone(&mtx);
105         assert_eq!(mtx.held_by_thread(), LockHeldState::NotHeldByThread);
106
107         let lck = mtx.lock().unwrap();
108         assert_eq!(mtx.held_by_thread(), LockHeldState::HeldByThread);
109
110         let thrd = std::thread::spawn(move || {
111                 assert_eq!(mtx_ref.held_by_thread(), LockHeldState::NotHeldByThread);
112         });
113         thrd.join().unwrap();
114         assert_eq!(mtx.held_by_thread(), LockHeldState::HeldByThread);
115
116         std::mem::drop(lck);
117         assert_eq!(mtx.held_by_thread(), LockHeldState::NotHeldByThread);
118 }