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