1 | #[macro_use ] |
2 | extern crate cfg_if; |
3 | #[cfg_attr (not(any(target_os = "redox" , target_os = "haiku" )), macro_use)] |
4 | extern crate nix; |
5 | |
6 | mod common; |
7 | mod sys; |
8 | #[cfg (not(target_os = "redox" ))] |
9 | mod test_dir; |
10 | mod test_fcntl; |
11 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
12 | mod test_kmod; |
13 | #[cfg (any( |
14 | target_os = "dragonfly" , |
15 | target_os = "freebsd" , |
16 | target_os = "fushsia" , |
17 | target_os = "linux" , |
18 | target_os = "netbsd" |
19 | ))] |
20 | mod test_mq; |
21 | #[cfg (not(target_os = "redox" ))] |
22 | mod test_net; |
23 | mod test_nix_path; |
24 | #[cfg (target_os = "freebsd" )] |
25 | mod test_nmount; |
26 | mod test_poll; |
27 | #[cfg (not(any( |
28 | target_os = "redox" , |
29 | target_os = "fuchsia" , |
30 | target_os = "haiku" |
31 | )))] |
32 | mod test_pty; |
33 | mod test_resource; |
34 | #[cfg (any( |
35 | target_os = "android" , |
36 | target_os = "dragonfly" , |
37 | all(target_os = "freebsd" , fbsd14), |
38 | target_os = "linux" |
39 | ))] |
40 | mod test_sched; |
41 | #[cfg (any( |
42 | target_os = "android" , |
43 | target_os = "dragonfly" , |
44 | target_os = "freebsd" , |
45 | target_os = "ios" , |
46 | target_os = "linux" , |
47 | target_os = "macos" |
48 | ))] |
49 | mod test_sendfile; |
50 | mod test_stat; |
51 | mod test_time; |
52 | #[cfg (all( |
53 | any( |
54 | target_os = "freebsd" , |
55 | target_os = "illumos" , |
56 | target_os = "linux" , |
57 | target_os = "netbsd" |
58 | ), |
59 | feature = "time" , |
60 | feature = "signal" |
61 | ))] |
62 | mod test_timer; |
63 | mod test_unistd; |
64 | |
65 | use nix::unistd::{chdir, getcwd, read}; |
66 | use parking_lot::{Mutex, RwLock, RwLockWriteGuard}; |
67 | use std::os::unix::io::{AsFd, AsRawFd}; |
68 | use std::path::PathBuf; |
69 | |
70 | /// Helper function analogous to `std::io::Read::read_exact`, but for `Fd`s |
71 | fn read_exact<Fd: AsFd>(f: Fd, buf: &mut [u8]) { |
72 | let mut len = 0; |
73 | while len < buf.len() { |
74 | // get_mut would be better than split_at_mut, but it requires nightly |
75 | let (_, remaining) = buf.split_at_mut(len); |
76 | len += read(f.as_fd().as_raw_fd(), remaining).unwrap(); |
77 | } |
78 | } |
79 | |
80 | /// Any test that creates child processes must grab this mutex, regardless |
81 | /// of what it does with those children. |
82 | pub static FORK_MTX: std::sync::Mutex<()> = std::sync::Mutex::new(()); |
83 | /// Any test that changes the process's current working directory must grab |
84 | /// the RwLock exclusively. Any process that cares about the current |
85 | /// working directory must grab it shared. |
86 | pub static CWD_LOCK: RwLock<()> = RwLock::new(()); |
87 | /// Any test that changes the process's supplementary groups must grab this |
88 | /// mutex |
89 | pub static GROUPS_MTX: Mutex<()> = Mutex::new(()); |
90 | /// Any tests that loads or unloads kernel modules must grab this mutex |
91 | pub static KMOD_MTX: Mutex<()> = Mutex::new(()); |
92 | /// Any test that calls ptsname(3) must grab this mutex. |
93 | pub static PTSNAME_MTX: Mutex<()> = Mutex::new(()); |
94 | /// Any test that alters signal handling must grab this mutex. |
95 | pub static SIGNAL_MTX: Mutex<()> = Mutex::new(()); |
96 | |
97 | /// RAII object that restores a test's original directory on drop |
98 | struct DirRestore<'a> { |
99 | d: PathBuf, |
100 | _g: RwLockWriteGuard<'a, ()>, |
101 | } |
102 | |
103 | impl<'a> DirRestore<'a> { |
104 | fn new() -> Self { |
105 | let guard = crate::CWD_LOCK.write(); |
106 | DirRestore { |
107 | _g: guard, |
108 | d: getcwd().unwrap(), |
109 | } |
110 | } |
111 | } |
112 | |
113 | impl<'a> Drop for DirRestore<'a> { |
114 | fn drop(&mut self) { |
115 | let r = chdir(&self.d); |
116 | if std::thread::panicking() { |
117 | r.unwrap(); |
118 | } |
119 | } |
120 | } |
121 | |