Refuse recursive read locks in lockorder testing
[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 #[should_panic]
19 #[cfg(not(feature = "backtrace"))]
20 fn recursive_read() {
21         let lock = RwLock::new(());
22         let _a = lock.read().unwrap();
23         let _b = lock.read().unwrap();
24 }
25
26 #[test]
27 #[should_panic]
28 fn lockorder_fail() {
29         let a = Mutex::new(());
30         let b = Mutex::new(());
31         {
32                 let _a = a.lock().unwrap();
33                 let _b = b.lock().unwrap();
34         }
35         {
36                 let _b = b.lock().unwrap();
37                 let _a = a.lock().unwrap();
38         }
39 }
40
41 #[test]
42 #[should_panic]
43 fn write_lockorder_fail() {
44         let a = RwLock::new(());
45         let b = RwLock::new(());
46         {
47                 let _a = a.write().unwrap();
48                 let _b = b.write().unwrap();
49         }
50         {
51                 let _b = b.write().unwrap();
52                 let _a = a.write().unwrap();
53         }
54 }
55
56 #[test]
57 #[should_panic]
58 fn read_lockorder_fail() {
59         let a = RwLock::new(());
60         let b = RwLock::new(());
61         {
62                 let _a = a.read().unwrap();
63                 let _b = b.read().unwrap();
64         }
65         {
66                 let _b = b.read().unwrap();
67                 let _a = a.read().unwrap();
68         }
69 }
70
71 #[test]
72 #[should_panic]
73 fn read_write_lockorder_fail() {
74         let a = RwLock::new(());
75         let b = RwLock::new(());
76         {
77                 let _a = a.write().unwrap();
78                 let _b = b.read().unwrap();
79         }
80         {
81                 let _b = b.read().unwrap();
82                 let _a = a.write().unwrap();
83         }
84 }
85
86 #[test]
87 fn test_thread_locked_state() {
88         let mtx = Arc::new(Mutex::new(()));
89         let mtx_ref = Arc::clone(&mtx);
90         assert_eq!(mtx.held_by_thread(), LockHeldState::NotHeldByThread);
91
92         let lck = mtx.lock().unwrap();
93         assert_eq!(mtx.held_by_thread(), LockHeldState::HeldByThread);
94
95         let thrd = std::thread::spawn(move || {
96                 assert_eq!(mtx_ref.held_by_thread(), LockHeldState::NotHeldByThread);
97         });
98         thrd.join().unwrap();
99         assert_eq!(mtx.held_by_thread(), LockHeldState::HeldByThread);
100
101         std::mem::drop(lck);
102         assert_eq!(mtx.held_by_thread(), LockHeldState::NotHeldByThread);
103 }