1#[macro_use] 2extern crate cfg_if; 3#[cfg_attr(not(any(target_os = "redox", target_os = "haiku")), macro_use)] 4extern crate nix; 5#[macro_use] 6extern crate lazy_static; 7 8mod common; 9mod sys; 10#[cfg(not(target_os = "redox"))] 11mod test_dir; 12mod test_fcntl; 13#[cfg(any(target_os = "android", target_os = "linux"))] 14mod 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))] 22mod test_mq; 23#[cfg(not(target_os = "redox"))] 24mod test_net; 25mod test_nix_path; 26#[cfg(target_os = "freebsd")] 27mod test_nmount; 28mod test_poll; 29#[cfg(not(any( 30 target_os = "redox", 31 target_os = "fuchsia", 32 target_os = "haiku" 33)))] 34mod test_pty; 35mod test_resource; 36#[cfg(any( 37 target_os = "android", 38 target_os = "dragonfly", 39 all(target_os = "freebsd", fbsd14), 40 target_os = "linux" 41))] 42mod 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))] 51mod test_sendfile; 52mod test_stat; 53mod 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))] 64mod test_timer; 65mod test_unistd; 66 67use nix::unistd::{chdir, getcwd, read}; 68use parking_lot::{Mutex, RwLock, RwLockWriteGuard}; 69use std::os::unix::io::RawFd; 70use std::path::PathBuf; 71 72/// Helper function analogous to `std::io::Read::read_exact`, but for `RawFD`s 73fn 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 82lazy_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 102struct DirRestore<'a> { 103 d: PathBuf, 104 _g: RwLockWriteGuard<'a, ()>, 105} 106 107impl<'a> DirRestore<'a> { 108 fn new() -> Self { 109 let guard = crate::CWD_LOCK.write(); 110 DirRestore { 111 _g: guard, 112 d: getcwd().unwrap(), 113 } 114 } 115} 116 117impl<'a> Drop for DirRestore<'a> { 118 fn drop(&mut self) { 119 let r = chdir(&self.d); 120 if std::thread::panicking() { 121 r.unwrap(); 122 } 123 } 124} 125