diff --git a/CONVENTIONS.md b/CONVENTIONS.md index 540cdce666..d71a3d17dd 100644 --- a/CONVENTIONS.md +++ b/CONVENTIONS.md @@ -124,3 +124,10 @@ cases, it will be the version of the next release. And a user-friendly note should be added. Normally, there should be a new interface that will replace the old one, so a note should be something like: "`` should be used instead". + +## Where to put a test + +If you want to add a test for a feature that is in `xxx.rs`, then the test should +be put in the corresponding `test_xxx.rs` file unless you cannot do this, e.g., +the test involves private stuff and thus cannot be added outside of Nix, then +it is allowed to leave the test in `xxx.rs`. diff --git a/src/sys/aio.rs b/src/sys/aio.rs index fbf5b27695..e3c44db654 100644 --- a/src/sys/aio.rs +++ b/src/sys/aio.rs @@ -1191,56 +1191,3 @@ pub fn lio_listio( }) .map(drop) } - -#[cfg(test)] -mod t { - use super::*; - - /// aio_suspend relies on casting Rust Aio* struct pointers to libc::aiocb - /// pointers. This test ensures that such casts are valid. - #[test] - fn casting() { - let sev = SigevNotify::SigevNone; - let aiof = AioFsync::new(666, AioFsyncMode::O_SYNC, 0, sev); - assert_eq!( - aiof.as_ref() as *const libc::aiocb, - &aiof as *const AioFsync as *const libc::aiocb - ); - - let mut rbuf = []; - let aior = AioRead::new(666, 0, &mut rbuf, 0, sev); - assert_eq!( - aior.as_ref() as *const libc::aiocb, - &aior as *const AioRead as *const libc::aiocb - ); - - let wbuf = []; - let aiow = AioWrite::new(666, 0, &wbuf, 0, sev); - assert_eq!( - aiow.as_ref() as *const libc::aiocb, - &aiow as *const AioWrite as *const libc::aiocb - ); - } - - #[cfg(target_os = "freebsd")] - #[test] - fn casting_vectored() { - let sev = SigevNotify::SigevNone; - - let mut rbuf = []; - let mut rbufs = [IoSliceMut::new(&mut rbuf)]; - let aiorv = AioReadv::new(666, 0, &mut rbufs[..], 0, sev); - assert_eq!( - aiorv.as_ref() as *const libc::aiocb, - &aiorv as *const AioReadv as *const libc::aiocb - ); - - let wbuf = []; - let wbufs = [IoSlice::new(&wbuf)]; - let aiowv = AioWritev::new(666, 0, &wbufs, 0, sev); - assert_eq!( - aiowv.as_ref() as *const libc::aiocb, - &aiowv as *const AioWritev as *const libc::aiocb - ); - } -} diff --git a/src/sys/event.rs b/src/sys/event.rs index d30896aaeb..968c5a4ae2 100644 --- a/src/sys/event.rs +++ b/src/sys/event.rs @@ -441,42 +441,3 @@ pub fn ev_set( ev.kevent.data = 0; ev.kevent.udata = udata as type_of_udata; } - -#[test] -fn test_struct_kevent() { - use std::mem; - - let udata: intptr_t = 12345; - - let actual = KEvent::new( - 0xdead_beef, - EventFilter::EVFILT_READ, - EventFlag::EV_ONESHOT | EventFlag::EV_ADD, - FilterFlag::NOTE_CHILD | FilterFlag::NOTE_EXIT, - 0x1337, - udata, - ); - assert_eq!(0xdead_beef, actual.ident()); - let filter = actual.kevent.filter; - assert_eq!(libc::EVFILT_READ, filter); - assert_eq!(libc::EV_ONESHOT | libc::EV_ADD, actual.flags().bits()); - assert_eq!(libc::NOTE_CHILD | libc::NOTE_EXIT, actual.fflags().bits()); - assert_eq!(0x1337, actual.data()); - assert_eq!(udata as type_of_udata, actual.udata() as type_of_udata); - assert_eq!(mem::size_of::(), mem::size_of::()); -} - -#[test] -fn test_kevent_filter() { - let udata: intptr_t = 12345; - - let actual = KEvent::new( - 0xdead_beef, - EventFilter::EVFILT_READ, - EventFlag::EV_ONESHOT | EventFlag::EV_ADD, - FilterFlag::NOTE_CHILD | FilterFlag::NOTE_EXIT, - 0x1337, - udata, - ); - assert_eq!(EventFilter::EVFILT_READ, actual.filter().unwrap()); -} diff --git a/src/sys/resource.rs b/src/sys/resource.rs index f57db47944..71315072d4 100644 --- a/src/sys/resource.rs +++ b/src/sys/resource.rs @@ -396,28 +396,3 @@ pub fn getrusage(who: UsageWho) -> Result { Errno::result(res).map(|_| Usage(rusage.assume_init())) } } - -#[cfg(test)] -mod test { - use super::{getrusage, UsageWho}; - - #[test] - pub fn test_self_cpu_time() { - // Make sure some CPU time is used. - let mut numbers: Vec = (1..1_000_000).collect(); - numbers.iter_mut().for_each(|item| *item *= 2); - - // FIXME: this is here to help ensure the compiler does not optimize the whole - // thing away. Replace the assert with test::black_box once stabilized. - assert_eq!(numbers[100..200].iter().sum::(), 30_100); - - let usage = getrusage(UsageWho::RUSAGE_SELF) - .expect("Failed to call getrusage for SELF"); - let rusage = usage.as_ref(); - - let user = usage.user_time(); - assert!(user.tv_sec() > 0 || user.tv_usec() > 0); - assert_eq!(user.tv_sec(), rusage.ru_utime.tv_sec); - assert_eq!(user.tv_usec(), rusage.ru_utime.tv_usec); - } -} diff --git a/src/sys/select.rs b/src/sys/select.rs index ea0c41d4be..64a8e258cf 100644 --- a/src/sys/select.rs +++ b/src/sys/select.rs @@ -317,227 +317,3 @@ where Errno::result(res) } } - -#[cfg(test)] -mod tests { - use super::*; - use crate::sys::time::{TimeVal, TimeValLike}; - use crate::unistd::{pipe, write}; - use std::os::unix::io::{AsFd, RawFd}; - - #[test] - fn fdset_insert() { - let mut fd_set = FdSet::new(); - - for i in 0..FD_SETSIZE { - let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) }; - assert!(!fd_set.contains(borrowed_i)); - } - - let fd_seven = unsafe { BorrowedFd::borrow_raw(7) }; - fd_set.insert(fd_seven); - - assert!(fd_set.contains(fd_seven)); - } - - #[test] - fn fdset_remove() { - let mut fd_set = FdSet::new(); - - for i in 0..FD_SETSIZE { - let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) }; - assert!(!fd_set.contains(borrowed_i)); - } - - let fd_seven = unsafe { BorrowedFd::borrow_raw(7) }; - fd_set.insert(fd_seven); - fd_set.remove(fd_seven); - - for i in 0..FD_SETSIZE { - let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) }; - assert!(!fd_set.contains(borrowed_i)); - } - } - - #[test] - #[allow(non_snake_case)] - fn fdset_clear() { - let mut fd_set = FdSet::new(); - let fd_one = unsafe { BorrowedFd::borrow_raw(1) }; - let fd_FD_SETSIZE_divided_by_two = - unsafe { BorrowedFd::borrow_raw((FD_SETSIZE / 2) as RawFd) }; - let fd_FD_SETSIZE_minus_one = - unsafe { BorrowedFd::borrow_raw((FD_SETSIZE - 1) as RawFd) }; - fd_set.insert(fd_one); - fd_set.insert(fd_FD_SETSIZE_divided_by_two); - fd_set.insert(fd_FD_SETSIZE_minus_one); - - fd_set.clear(); - - for i in 0..FD_SETSIZE { - let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) }; - assert!(!fd_set.contains(borrowed_i)); - } - } - - #[test] - fn fdset_highest() { - let mut set = FdSet::new(); - assert_eq!( - set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()), - None - ); - let fd_zero = unsafe { BorrowedFd::borrow_raw(0) }; - let fd_ninety = unsafe { BorrowedFd::borrow_raw(90) }; - set.insert(fd_zero); - assert_eq!( - set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()), - Some(0) - ); - set.insert(fd_ninety); - assert_eq!( - set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()), - Some(90) - ); - set.remove(fd_zero); - assert_eq!( - set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()), - Some(90) - ); - set.remove(fd_ninety); - assert_eq!( - set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()), - None - ); - - let fd_four = unsafe { BorrowedFd::borrow_raw(4) }; - let fd_five = unsafe { BorrowedFd::borrow_raw(5) }; - let fd_seven = unsafe { BorrowedFd::borrow_raw(7) }; - set.insert(fd_four); - set.insert(fd_five); - set.insert(fd_seven); - assert_eq!( - set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()), - Some(7) - ); - } - - #[test] - fn fdset_fds() { - let mut set = FdSet::new(); - let fd_zero = unsafe { BorrowedFd::borrow_raw(0) }; - let fd_ninety = unsafe { BorrowedFd::borrow_raw(90) }; - assert_eq!( - set.fds(None) - .map(|borrowed_fd| borrowed_fd.as_raw_fd()) - .collect::>(), - vec![] - ); - set.insert(fd_zero); - assert_eq!( - set.fds(None) - .map(|borrowed_fd| borrowed_fd.as_raw_fd()) - .collect::>(), - vec![0] - ); - set.insert(fd_ninety); - assert_eq!( - set.fds(None) - .map(|borrowed_fd| borrowed_fd.as_raw_fd()) - .collect::>(), - vec![0, 90] - ); - - // highest limit - assert_eq!( - set.fds(Some(89)) - .map(|borrowed_fd| borrowed_fd.as_raw_fd()) - .collect::>(), - vec![0] - ); - assert_eq!( - set.fds(Some(90)) - .map(|borrowed_fd| borrowed_fd.as_raw_fd()) - .collect::>(), - vec![0, 90] - ); - } - - #[test] - fn test_select() { - let (r1, w1) = pipe().unwrap(); - let (r2, _w2) = pipe().unwrap(); - - write(&w1, b"hi!").unwrap(); - let mut fd_set = FdSet::new(); - fd_set.insert(r1.as_fd()); - fd_set.insert(r2.as_fd()); - - let mut timeout = TimeVal::seconds(10); - assert_eq!( - 1, - select(None, &mut fd_set, None, None, &mut timeout).unwrap() - ); - assert!(fd_set.contains(r1.as_fd())); - assert!(!fd_set.contains(r2.as_fd())); - } - - #[test] - fn test_select_nfds() { - let (r1, w1) = pipe().unwrap(); - let (r2, _w2) = pipe().unwrap(); - - write(&w1, b"hi!").unwrap(); - let mut fd_set = FdSet::new(); - fd_set.insert(r1.as_fd()); - fd_set.insert(r2.as_fd()); - - let mut timeout = TimeVal::seconds(10); - { - assert_eq!( - 1, - select( - Some( - fd_set - .highest() - .map(|borrowed_fd| borrowed_fd.as_raw_fd()) - .unwrap() - + 1 - ), - &mut fd_set, - None, - None, - &mut timeout - ) - .unwrap() - ); - } - assert!(fd_set.contains(r1.as_fd())); - assert!(!fd_set.contains(r2.as_fd())); - } - - #[test] - fn test_select_nfds2() { - let (r1, w1) = pipe().unwrap(); - write(&w1, b"hi!").unwrap(); - let (r2, _w2) = pipe().unwrap(); - let mut fd_set = FdSet::new(); - fd_set.insert(r1.as_fd()); - fd_set.insert(r2.as_fd()); - - let mut timeout = TimeVal::seconds(10); - assert_eq!( - 1, - select( - std::cmp::max(r1.as_raw_fd(), r2.as_raw_fd()) + 1, - &mut fd_set, - None, - None, - &mut timeout - ) - .unwrap() - ); - assert!(fd_set.contains(r1.as_fd())); - assert!(!fd_set.contains(r2.as_fd())); - } -} diff --git a/src/sys/signal.rs b/src/sys/signal.rs index 10f1de85b0..efa11a134b 100644 --- a/src/sys/signal.rs +++ b/src/sys/signal.rs @@ -1379,271 +1379,3 @@ mod sigevent { } } } - -#[cfg(test)] -mod tests { - use super::*; - #[cfg(not(target_os = "redox"))] - use std::thread; - - #[test] - fn test_contains() { - let mut mask = SigSet::empty(); - mask.add(SIGUSR1); - - assert!(mask.contains(SIGUSR1)); - assert!(!mask.contains(SIGUSR2)); - - let all = SigSet::all(); - assert!(all.contains(SIGUSR1)); - assert!(all.contains(SIGUSR2)); - } - - #[test] - fn test_clear() { - let mut set = SigSet::all(); - set.clear(); - for signal in Signal::iterator() { - assert!(!set.contains(signal)); - } - } - - #[test] - fn test_from_str_round_trips() { - for signal in Signal::iterator() { - assert_eq!(signal.as_ref().parse::().unwrap(), signal); - assert_eq!(signal.to_string().parse::().unwrap(), signal); - } - } - - #[test] - fn test_from_str_invalid_value() { - let errval = Err(Errno::EINVAL); - assert_eq!("NOSIGNAL".parse::(), errval); - assert_eq!("kill".parse::(), errval); - assert_eq!("9".parse::(), errval); - } - - #[test] - fn test_extend() { - let mut one_signal = SigSet::empty(); - one_signal.add(SIGUSR1); - - let mut two_signals = SigSet::empty(); - two_signals.add(SIGUSR2); - two_signals.extend(&one_signal); - - assert!(two_signals.contains(SIGUSR1)); - assert!(two_signals.contains(SIGUSR2)); - } - - #[test] - #[cfg(not(target_os = "redox"))] - fn test_thread_signal_set_mask() { - thread::spawn(|| { - let prev_mask = SigSet::thread_get_mask() - .expect("Failed to get existing signal mask!"); - - let mut test_mask = prev_mask; - test_mask.add(SIGUSR1); - - test_mask.thread_set_mask().expect("assertion failed"); - let new_mask = - SigSet::thread_get_mask().expect("Failed to get new mask!"); - - assert!(new_mask.contains(SIGUSR1)); - assert!(!new_mask.contains(SIGUSR2)); - - prev_mask - .thread_set_mask() - .expect("Failed to revert signal mask!"); - }) - .join() - .unwrap(); - } - - #[test] - #[cfg(not(target_os = "redox"))] - fn test_thread_signal_block() { - thread::spawn(|| { - let mut mask = SigSet::empty(); - mask.add(SIGUSR1); - - mask.thread_block().expect("assertion failed"); - - assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1)); - }) - .join() - .unwrap(); - } - - #[test] - #[cfg(not(target_os = "redox"))] - fn test_thread_signal_unblock() { - thread::spawn(|| { - let mut mask = SigSet::empty(); - mask.add(SIGUSR1); - - mask.thread_unblock().expect("assertion failed"); - - assert!(!SigSet::thread_get_mask().unwrap().contains(SIGUSR1)); - }) - .join() - .unwrap(); - } - - #[test] - #[cfg(not(target_os = "redox"))] - fn test_thread_signal_swap() { - thread::spawn(|| { - let mut mask = SigSet::empty(); - mask.add(SIGUSR1); - mask.thread_block().unwrap(); - - assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1)); - - let mut mask2 = SigSet::empty(); - mask2.add(SIGUSR2); - - let oldmask = - mask2.thread_swap_mask(SigmaskHow::SIG_SETMASK).unwrap(); - - assert!(oldmask.contains(SIGUSR1)); - assert!(!oldmask.contains(SIGUSR2)); - - assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR2)); - }) - .join() - .unwrap(); - } - - #[test] - fn test_from_and_into_iterator() { - let sigset = SigSet::from_iter(vec![Signal::SIGUSR1, Signal::SIGUSR2]); - let signals = sigset.into_iter().collect::>(); - assert_eq!(signals, [Signal::SIGUSR1, Signal::SIGUSR2]); - } - - #[test] - #[cfg(not(target_os = "redox"))] - fn test_sigaction() { - thread::spawn(|| { - extern "C" fn test_sigaction_handler(_: libc::c_int) {} - extern "C" fn test_sigaction_action( - _: libc::c_int, - _: *mut libc::siginfo_t, - _: *mut libc::c_void, - ) { - } - - let handler_sig = SigHandler::Handler(test_sigaction_handler); - - let flags = - SaFlags::SA_ONSTACK | SaFlags::SA_RESTART | SaFlags::SA_SIGINFO; - - let mut mask = SigSet::empty(); - mask.add(SIGUSR1); - - let action_sig = SigAction::new(handler_sig, flags, mask); - - assert_eq!( - action_sig.flags(), - SaFlags::SA_ONSTACK | SaFlags::SA_RESTART - ); - assert_eq!(action_sig.handler(), handler_sig); - - mask = action_sig.mask(); - assert!(mask.contains(SIGUSR1)); - assert!(!mask.contains(SIGUSR2)); - - let handler_act = SigHandler::SigAction(test_sigaction_action); - let action_act = SigAction::new(handler_act, flags, mask); - assert_eq!(action_act.handler(), handler_act); - - let action_dfl = SigAction::new(SigHandler::SigDfl, flags, mask); - assert_eq!(action_dfl.handler(), SigHandler::SigDfl); - - let action_ign = SigAction::new(SigHandler::SigIgn, flags, mask); - assert_eq!(action_ign.handler(), SigHandler::SigIgn); - }) - .join() - .unwrap(); - } - - #[test] - #[cfg(not(target_os = "redox"))] - fn test_sigwait() { - thread::spawn(|| { - let mut mask = SigSet::empty(); - mask.add(SIGUSR1); - mask.add(SIGUSR2); - mask.thread_block().unwrap(); - - raise(SIGUSR1).unwrap(); - assert_eq!(mask.wait().unwrap(), SIGUSR1); - }) - .join() - .unwrap(); - } - - #[test] - fn test_from_sigset_t_unchecked() { - let src_set = SigSet::empty(); - let set = unsafe { SigSet::from_sigset_t_unchecked(src_set.sigset) }; - - for signal in Signal::iterator() { - assert!(!set.contains(signal)); - } - - let src_set = SigSet::all(); - let set = unsafe { SigSet::from_sigset_t_unchecked(src_set.sigset) }; - - for signal in Signal::iterator() { - assert!(set.contains(signal)); - } - } - - #[test] - fn test_eq_empty() { - let set0 = SigSet::empty(); - let set1 = SigSet::empty(); - assert_eq!(set0, set1); - } - - #[test] - fn test_eq_all() { - let set0 = SigSet::all(); - let set1 = SigSet::all(); - assert_eq!(set0, set1); - } - - #[test] - fn test_hash_empty() { - use std::collections::hash_map::DefaultHasher; - - let set0 = SigSet::empty(); - let mut h0 = DefaultHasher::new(); - set0.hash(&mut h0); - - let set1 = SigSet::empty(); - let mut h1 = DefaultHasher::new(); - set1.hash(&mut h1); - - assert_eq!(h0.finish(), h1.finish()); - } - - #[test] - fn test_hash_all() { - use std::collections::hash_map::DefaultHasher; - - let set0 = SigSet::all(); - let mut h0 = DefaultHasher::new(); - set0.hash(&mut h0); - - let set1 = SigSet::all(); - let mut h1 = DefaultHasher::new(); - set1.hash(&mut h1); - - assert_eq!(h0.finish(), h1.finish()); - } -} diff --git a/src/sys/signalfd.rs b/src/sys/signalfd.rs index aefc89bc73..ccba774d1a 100644 --- a/src/sys/signalfd.rs +++ b/src/sys/signalfd.rs @@ -155,34 +155,3 @@ impl Iterator for SignalFd { } } } - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn create_signalfd() { - let mask = SigSet::empty(); - SignalFd::new(&mask).unwrap(); - } - - #[test] - fn create_signalfd_with_opts() { - let mask = SigSet::empty(); - SignalFd::with_flags( - &mask, - SfdFlags::SFD_CLOEXEC | SfdFlags::SFD_NONBLOCK, - ) - .unwrap(); - } - - #[test] - fn read_empty_signalfd() { - let mask = SigSet::empty(); - let mut fd = - SignalFd::with_flags(&mask, SfdFlags::SFD_NONBLOCK).unwrap(); - - let res = fd.read_signal(); - assert!(res.unwrap().is_none()); - } -} diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index 8556c7d46d..dfc37db745 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -1774,108 +1774,6 @@ impl<'a> Iterator for IoSliceIterator<'a> { } } -// test contains both recvmmsg and timestaping which is linux only -// there are existing tests for recvmmsg only in tests/ -#[cfg(target_os = "linux")] -#[cfg(test)] -mod test { - use crate::sys::socket::{AddressFamily, ControlMessageOwned}; - use crate::*; - use std::str::FromStr; - use std::os::unix::io::AsRawFd; - - #[cfg_attr(qemu, ignore)] - #[test] - fn test_recvmm2() -> crate::Result<()> { - use crate::sys::socket::{ - sendmsg, setsockopt, socket, sockopt::Timestamping, MsgFlags, SockFlag, SockType, - SockaddrIn, TimestampingFlag, - }; - use std::io::{IoSlice, IoSliceMut}; - - let sock_addr = SockaddrIn::from_str("127.0.0.1:6790").unwrap(); - - let ssock = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - )?; - - let rsock = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::SOCK_NONBLOCK, - None, - )?; - - crate::sys::socket::bind(rsock.as_raw_fd(), &sock_addr)?; - - setsockopt(&rsock, Timestamping, &TimestampingFlag::all())?; - - let sbuf = (0..400).map(|i| i as u8).collect::>(); - - let mut recv_buf = vec![0; 1024]; - - let mut recv_iovs = Vec::new(); - let mut pkt_iovs = Vec::new(); - - for (ix, chunk) in recv_buf.chunks_mut(256).enumerate() { - pkt_iovs.push(IoSliceMut::new(chunk)); - if ix % 2 == 1 { - recv_iovs.push(pkt_iovs); - pkt_iovs = Vec::new(); - } - } - drop(pkt_iovs); - - let flags = MsgFlags::empty(); - let iov1 = [IoSlice::new(&sbuf)]; - - let cmsg = cmsg_space!(crate::sys::socket::Timestamps); - sendmsg(ssock.as_raw_fd(), &iov1, &[], flags, Some(&sock_addr)).unwrap(); - - let mut data = super::MultiHeaders::<()>::preallocate(recv_iovs.len(), Some(cmsg)); - - let t = sys::time::TimeSpec::from_duration(std::time::Duration::from_secs(10)); - - let recv = super::recvmmsg(rsock.as_raw_fd(), &mut data, recv_iovs.iter_mut(), flags, Some(t))?; - - for rmsg in recv { - #[cfg(not(any(qemu, target_arch = "aarch64")))] - let mut saw_time = false; - let mut recvd = 0; - for cmsg in rmsg.cmsgs() { - if let ControlMessageOwned::ScmTimestampsns(timestamps) = cmsg { - let ts = timestamps.system; - - let sys_time = - crate::time::clock_gettime(crate::time::ClockId::CLOCK_REALTIME)?; - let diff = if ts > sys_time { - ts - sys_time - } else { - sys_time - ts - }; - assert!(std::time::Duration::from(diff).as_secs() < 60); - #[cfg(not(any(qemu, target_arch = "aarch64")))] - { - saw_time = true; - } - } - } - - #[cfg(not(any(qemu, target_arch = "aarch64")))] - assert!(saw_time); - - for iov in rmsg.iovs() { - recvd += iov.len(); - } - assert_eq!(recvd, 400); - } - - Ok(()) - } -} unsafe fn read_mhdr<'a, 'i, S>( mhdr: msghdr, r: isize, @@ -2364,23 +2262,3 @@ pub fn shutdown(df: RawFd, how: Shutdown) -> Result<()> { } } -#[cfg(test)] -mod tests { - #[cfg(not(target_os = "redox"))] - #[test] - fn can_use_cmsg_space() { - let _ = cmsg_space!(u8); - } - - #[cfg(not(any(linux_android, target_os = "redox", target_os = "haiku")))] - #[test] - fn can_open_routing_socket() { - let _ = super::socket( - super::AddressFamily::Route, - super::SockType::Raw, - super::SockFlag::empty(), - None, - ) - .expect("Failed to open routing socket"); - } -} diff --git a/src/sys/socket/sockopt.rs b/src/sys/socket/sockopt.rs index cbc7beca34..6ce57c6f96 100644 --- a/src/sys/socket/sockopt.rs +++ b/src/sys/socket/sockopt.rs @@ -1403,72 +1403,3 @@ impl<'a> Set<'a, OsString> for SetOsString<'a> { } } -#[cfg(test)] -mod test { - #[cfg(linux_android)] - #[test] - fn can_get_peercred_on_unix_socket() { - use super::super::*; - - let (a, b) = socketpair( - AddressFamily::Unix, - SockType::Stream, - None, - SockFlag::empty(), - ) - .unwrap(); - let a_cred = getsockopt(&a, super::PeerCredentials).unwrap(); - let b_cred = getsockopt(&b, super::PeerCredentials).unwrap(); - assert_eq!(a_cred, b_cred); - assert_ne!(a_cred.pid(), 0); - } - - #[test] - fn is_socket_type_unix() { - use super::super::*; - - let (a, _b) = socketpair( - AddressFamily::Unix, - SockType::Stream, - None, - SockFlag::empty(), - ) - .unwrap(); - let a_type = getsockopt(&a, super::SockType).unwrap(); - assert_eq!(a_type, SockType::Stream); - } - - #[test] - fn is_socket_type_dgram() { - use super::super::*; - - let s = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .unwrap(); - let s_type = getsockopt(&s, super::SockType).unwrap(); - assert_eq!(s_type, SockType::Datagram); - } - - #[cfg(any(target_os = "freebsd", target_os = "linux"))] - #[test] - fn can_get_listen_on_tcp_socket() { - use super::super::*; - - let s = socket( - AddressFamily::Inet, - SockType::Stream, - SockFlag::empty(), - None, - ) - .unwrap(); - let s_listening = getsockopt(&s, super::AcceptConn).unwrap(); - assert!(!s_listening); - listen(&s, 10).unwrap(); - let s_listening2 = getsockopt(&s, super::AcceptConn).unwrap(); - assert!(s_listening2); - } -} diff --git a/src/sys/statfs.rs b/src/sys/statfs.rs index 377e303e99..d4335cf388 100644 --- a/src/sys/statfs.rs +++ b/src/sys/statfs.rs @@ -657,107 +657,3 @@ pub fn fstatfs(fd: Fd) -> Result { .map(|_| Statfs(stat.assume_init())) } } - -#[cfg(test)] -mod test { - use std::fs::File; - - use crate::sys::statfs::*; - use crate::sys::statvfs::*; - use std::path::Path; - - #[test] - fn statfs_call() { - check_statfs("/tmp"); - check_statfs("/dev"); - check_statfs("/run"); - check_statfs("/"); - } - - #[test] - fn fstatfs_call() { - check_fstatfs("/tmp"); - check_fstatfs("/dev"); - check_fstatfs("/run"); - check_fstatfs("/"); - } - - fn check_fstatfs(path: &str) { - if !Path::new(path).exists() { - return; - } - let vfs = statvfs(path.as_bytes()).unwrap(); - let file = File::open(path).unwrap(); - let fs = fstatfs(&file).unwrap(); - assert_fs_equals(fs, vfs); - } - - fn check_statfs(path: &str) { - if !Path::new(path).exists() { - return; - } - let vfs = statvfs(path.as_bytes()).unwrap(); - let fs = statfs(path.as_bytes()).unwrap(); - assert_fs_equals(fs, vfs); - } - - // The cast is not unnecessary on all platforms. - #[allow(clippy::unnecessary_cast)] - fn assert_fs_equals(fs: Statfs, vfs: Statvfs) { - assert_eq!(fs.files() as u64, vfs.files() as u64); - assert_eq!(fs.blocks() as u64, vfs.blocks() as u64); - assert_eq!(fs.block_size() as u64, vfs.fragment_size() as u64); - } - - // This test is ignored because files_free/blocks_free can change after statvfs call and before - // statfs call. - #[test] - #[ignore] - fn statfs_call_strict() { - check_statfs_strict("/tmp"); - check_statfs_strict("/dev"); - check_statfs_strict("/run"); - check_statfs_strict("/"); - } - - // This test is ignored because files_free/blocks_free can change after statvfs call and before - // fstatfs call. - #[test] - #[ignore] - fn fstatfs_call_strict() { - check_fstatfs_strict("/tmp"); - check_fstatfs_strict("/dev"); - check_fstatfs_strict("/run"); - check_fstatfs_strict("/"); - } - - fn check_fstatfs_strict(path: &str) { - if !Path::new(path).exists() { - return; - } - let vfs = statvfs(path.as_bytes()); - let file = File::open(path).unwrap(); - let fs = fstatfs(&file); - assert_fs_equals_strict(fs.unwrap(), vfs.unwrap()) - } - - fn check_statfs_strict(path: &str) { - if !Path::new(path).exists() { - return; - } - let vfs = statvfs(path.as_bytes()); - let fs = statfs(path.as_bytes()); - assert_fs_equals_strict(fs.unwrap(), vfs.unwrap()) - } - - // The cast is not unnecessary on all platforms. - #[allow(clippy::unnecessary_cast)] - fn assert_fs_equals_strict(fs: Statfs, vfs: Statvfs) { - assert_eq!(fs.files_free() as u64, vfs.files_free() as u64); - assert_eq!(fs.blocks_free() as u64, vfs.blocks_free() as u64); - assert_eq!(fs.blocks_available() as u64, vfs.blocks_available() as u64); - assert_eq!(fs.files() as u64, vfs.files() as u64); - assert_eq!(fs.blocks() as u64, vfs.blocks() as u64); - assert_eq!(fs.block_size() as u64, vfs.fragment_size() as u64); - } -} diff --git a/src/sys/statvfs.rs b/src/sys/statvfs.rs index 72f38ab7ab..7de326200e 100644 --- a/src/sys/statvfs.rs +++ b/src/sys/statvfs.rs @@ -148,20 +148,3 @@ pub fn fstatvfs(fd: Fd) -> Result { .map(|_| Statvfs(stat.assume_init())) } } - -#[cfg(test)] -mod test { - use crate::sys::statvfs::*; - use std::fs::File; - - #[test] - fn statvfs_call() { - statvfs(&b"/"[..]).unwrap(); - } - - #[test] - fn fstatvfs_call() { - let root = File::open("/").unwrap(); - fstatvfs(&root).unwrap(); - } -} diff --git a/src/sys/termios.rs b/src/sys/termios.rs index 57b42254ea..e006c2f1b0 100644 --- a/src/sys/termios.rs +++ b/src/sys/termios.rs @@ -923,18 +923,3 @@ pub fn tcgetsid(fd: Fd) -> Result { Errno::result(res).map(Pid::from_raw) } } - -#[cfg(test)] -mod test { - use super::*; - use std::convert::TryFrom; - - #[test] - fn try_from() { - assert_eq!(Ok(BaudRate::B0), BaudRate::try_from(libc::B0)); - #[cfg(not(target_os = "haiku"))] - BaudRate::try_from(999999999).expect_err("assertion failed"); - #[cfg(target_os = "haiku")] - BaudRate::try_from(99).expect_err("assertion failed"); - } -} diff --git a/src/sys/time.rs b/src/sys/time.rs index a63a03dc88..b19dee91a0 100644 --- a/src/sys/time.rs +++ b/src/sys/time.rs @@ -718,101 +718,3 @@ fn mod_floor_64(this: i64, other: i64) -> i64 { fn div_rem_64(this: i64, other: i64) -> (i64, i64) { (this / other, this % other) } - -#[cfg(test)] -mod test { - use super::{TimeSpec, TimeVal, TimeValLike}; - use std::time::Duration; - - #[test] - pub fn test_timespec() { - assert_ne!(TimeSpec::seconds(1), TimeSpec::zero()); - assert_eq!( - TimeSpec::seconds(1) + TimeSpec::seconds(2), - TimeSpec::seconds(3) - ); - assert_eq!( - TimeSpec::minutes(3) + TimeSpec::seconds(2), - TimeSpec::seconds(182) - ); - } - - #[test] - pub fn test_timespec_from() { - let duration = Duration::new(123, 123_456_789); - let timespec = TimeSpec::nanoseconds(123_123_456_789); - - assert_eq!(TimeSpec::from(duration), timespec); - assert_eq!(Duration::from(timespec), duration); - } - - #[test] - pub fn test_timespec_neg() { - let a = TimeSpec::seconds(1) + TimeSpec::nanoseconds(123); - let b = TimeSpec::seconds(-1) + TimeSpec::nanoseconds(-123); - - assert_eq!(a, -b); - } - - #[test] - pub fn test_timespec_ord() { - assert_eq!(TimeSpec::seconds(1), TimeSpec::nanoseconds(1_000_000_000)); - assert!(TimeSpec::seconds(1) < TimeSpec::nanoseconds(1_000_000_001)); - assert!(TimeSpec::seconds(1) > TimeSpec::nanoseconds(999_999_999)); - assert!(TimeSpec::seconds(-1) < TimeSpec::nanoseconds(-999_999_999)); - assert!(TimeSpec::seconds(-1) > TimeSpec::nanoseconds(-1_000_000_001)); - } - - #[test] - pub fn test_timespec_fmt() { - assert_eq!(TimeSpec::zero().to_string(), "0 seconds"); - assert_eq!(TimeSpec::seconds(42).to_string(), "42 seconds"); - assert_eq!(TimeSpec::milliseconds(42).to_string(), "0.042 seconds"); - assert_eq!(TimeSpec::microseconds(42).to_string(), "0.000042 seconds"); - assert_eq!( - TimeSpec::nanoseconds(42).to_string(), - "0.000000042 seconds" - ); - assert_eq!(TimeSpec::seconds(-86401).to_string(), "-86401 seconds"); - } - - #[test] - pub fn test_timeval() { - assert_ne!(TimeVal::seconds(1), TimeVal::zero()); - assert_eq!( - TimeVal::seconds(1) + TimeVal::seconds(2), - TimeVal::seconds(3) - ); - assert_eq!( - TimeVal::minutes(3) + TimeVal::seconds(2), - TimeVal::seconds(182) - ); - } - - #[test] - pub fn test_timeval_ord() { - assert_eq!(TimeVal::seconds(1), TimeVal::microseconds(1_000_000)); - assert!(TimeVal::seconds(1) < TimeVal::microseconds(1_000_001)); - assert!(TimeVal::seconds(1) > TimeVal::microseconds(999_999)); - assert!(TimeVal::seconds(-1) < TimeVal::microseconds(-999_999)); - assert!(TimeVal::seconds(-1) > TimeVal::microseconds(-1_000_001)); - } - - #[test] - pub fn test_timeval_neg() { - let a = TimeVal::seconds(1) + TimeVal::microseconds(123); - let b = TimeVal::seconds(-1) + TimeVal::microseconds(-123); - - assert_eq!(a, -b); - } - - #[test] - pub fn test_timeval_fmt() { - assert_eq!(TimeVal::zero().to_string(), "0 seconds"); - assert_eq!(TimeVal::seconds(42).to_string(), "42 seconds"); - assert_eq!(TimeVal::milliseconds(42).to_string(), "0.042 seconds"); - assert_eq!(TimeVal::microseconds(42).to_string(), "0.000042 seconds"); - assert_eq!(TimeVal::nanoseconds(1402).to_string(), "0.000001 seconds"); - assert_eq!(TimeVal::seconds(-86401).to_string(), "-86401 seconds"); - } -} diff --git a/src/sys/utsname.rs b/src/sys/utsname.rs index f07067b5b1..cf4e6cc738 100644 --- a/src/sys/utsname.rs +++ b/src/sys/utsname.rs @@ -62,24 +62,3 @@ fn cast_and_trim(slice: &[c_char]) -> &OsStr { OsStr::from_bytes(bytes) } - -#[cfg(test)] -mod test { - #[cfg(target_os = "linux")] - #[test] - pub fn test_uname_linux() { - assert_eq!(super::uname().unwrap().sysname(), "Linux"); - } - - #[cfg(apple_targets)] - #[test] - pub fn test_uname_darwin() { - assert_eq!(super::uname().unwrap().sysname(), "Darwin"); - } - - #[cfg(target_os = "freebsd")] - #[test] - pub fn test_uname_freebsd() { - assert_eq!(super::uname().unwrap().sysname(), "FreeBSD"); - } -} diff --git a/test/sys/mod.rs b/test/sys/mod.rs index 3a6707ba1d..fb3f6be0e5 100644 --- a/test/sys/mod.rs +++ b/test/sys/mod.rs @@ -53,3 +53,32 @@ mod test_pthread; mod test_ptrace; #[cfg(linux_android)] mod test_timerfd; + +#[cfg(all( + any( + target_os = "freebsd", + solarish, + target_os = "linux", + target_os = "netbsd" + ), + feature = "time", + feature = "signal" +))] +mod test_timer; + +#[cfg(bsd)] +mod test_event; +mod test_statvfs; +mod test_time; +mod test_utsname; + +#[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "openbsd"))] +mod test_statfs; + +#[cfg(not(any( + target_os = "redox", + target_os = "fuchsia", + solarish, + target_os = "haiku" +)))] +mod test_resource; diff --git a/test/sys/test_aio.rs b/test/sys/test_aio.rs index e8eb818024..323a36364a 100644 --- a/test/sys/test_aio.rs +++ b/test/sys/test_aio.rs @@ -624,3 +624,53 @@ fn test_aio_suspend() { assert_eq!(wcb.as_mut().aio_return().unwrap(), WBUF.len()); assert_eq!(rcb.as_mut().aio_return().unwrap(), rlen); } + +/// aio_suspend relies on casting Rust Aio* struct pointers to libc::aiocb +/// pointers. This test ensures that such casts are valid. +#[test] +fn casting() { + let sev = SigevNotify::SigevNone; + let aiof = AioFsync::new(666, AioFsyncMode::O_SYNC, 0, sev); + assert_eq!( + aiof.as_ref() as *const libc::aiocb, + &aiof as *const AioFsync as *const libc::aiocb + ); + + let mut rbuf = []; + let aior = AioRead::new(666, 0, &mut rbuf, 0, sev); + assert_eq!( + aior.as_ref() as *const libc::aiocb, + &aior as *const AioRead as *const libc::aiocb + ); + + let wbuf = []; + let aiow = AioWrite::new(666, 0, &wbuf, 0, sev); + assert_eq!( + aiow.as_ref() as *const libc::aiocb, + &aiow as *const AioWrite as *const libc::aiocb + ); +} + +#[cfg(target_os = "freebsd")] +#[test] +fn casting_vectored() { + use std::io::{IoSlice, IoSliceMut}; + + let sev = SigevNotify::SigevNone; + + let mut rbuf = []; + let mut rbufs = [IoSliceMut::new(&mut rbuf)]; + let aiorv = AioReadv::new(666, 0, &mut rbufs[..], 0, sev); + assert_eq!( + aiorv.as_ref() as *const libc::aiocb, + &aiorv as *const AioReadv as *const libc::aiocb + ); + + let wbuf = []; + let wbufs = [IoSlice::new(&wbuf)]; + let aiowv = AioWritev::new(666, 0, &wbufs, 0, sev); + assert_eq!( + aiowv.as_ref() as *const libc::aiocb, + &aiowv as *const AioWritev as *const libc::aiocb + ); +} diff --git a/test/sys/test_event.rs b/test/sys/test_event.rs new file mode 100644 index 0000000000..a10b1e5d12 --- /dev/null +++ b/test/sys/test_event.rs @@ -0,0 +1,41 @@ +use libc::intptr_t; +use nix::sys::event::{EventFilter, EventFlag, FilterFlag, KEvent}; + +#[test] +fn test_struct_kevent() { + use std::mem; + + let udata: intptr_t = 12345; + let data: intptr_t = 0x1337; + + let actual = KEvent::new( + 0xdead_beef, + EventFilter::EVFILT_READ, + EventFlag::EV_ONESHOT | EventFlag::EV_ADD, + FilterFlag::NOTE_CHILD | FilterFlag::NOTE_EXIT, + data, + udata, + ); + assert_eq!(0xdead_beef, actual.ident()); + assert_eq!(EventFilter::EVFILT_READ, actual.filter().unwrap()); + assert_eq!(libc::EV_ONESHOT | libc::EV_ADD, actual.flags().bits()); + assert_eq!(libc::NOTE_CHILD | libc::NOTE_EXIT, actual.fflags().bits()); + assert_eq!(data, actual.data()); + assert_eq!(udata, actual.udata()); + assert_eq!(mem::size_of::(), mem::size_of::()); +} + +#[test] +fn test_kevent_filter() { + let udata: intptr_t = 12345; + + let actual = KEvent::new( + 0xdead_beef, + EventFilter::EVFILT_READ, + EventFlag::EV_ONESHOT | EventFlag::EV_ADD, + FilterFlag::NOTE_CHILD | FilterFlag::NOTE_EXIT, + 0x1337, + udata, + ); + assert_eq!(EventFilter::EVFILT_READ, actual.filter().unwrap()); +} diff --git a/test/test_resource.rs b/test/sys/test_resource.rs similarity index 56% rename from test/test_resource.rs rename to test/sys/test_resource.rs index beae01c4c8..8b12a9495b 100644 --- a/test/test_resource.rs +++ b/test/sys/test_resource.rs @@ -1,10 +1,5 @@ -#[cfg(not(any( - target_os = "redox", - target_os = "fuchsia", - solarish, - target_os = "haiku" -)))] use nix::sys::resource::{getrlimit, setrlimit, Resource}; +use nix::sys::resource::{getrusage, UsageWho}; /// Tests the RLIMIT_NOFILE functionality of getrlimit(), where the resource RLIMIT_NOFILE refers /// to the maximum file descriptor number that can be opened by the process (aka the maximum number @@ -15,12 +10,6 @@ use nix::sys::resource::{getrlimit, setrlimit, Resource}; /// to put the new soft limit in effect, and then getrlimit() once more to ensure the limits have /// been updated. #[test] -#[cfg(not(any( - target_os = "redox", - target_os = "fuchsia", - solarish, - target_os = "haiku" -)))] pub fn test_resource_limits_nofile() { let (mut soft_limit, hard_limit) = getrlimit(Resource::RLIMIT_NOFILE).unwrap(); @@ -32,3 +21,23 @@ pub fn test_resource_limits_nofile() { let (new_soft_limit, _) = getrlimit(Resource::RLIMIT_NOFILE).unwrap(); assert_eq!(new_soft_limit, soft_limit); } + +#[test] +pub fn test_self_cpu_time() { + // Make sure some CPU time is used. + let mut numbers: Vec = (1..1_000_000).collect(); + numbers.iter_mut().for_each(|item| *item *= 2); + + // FIXME: this is here to help ensure the compiler does not optimize the whole + // thing away. Replace the assert with test::black_box once stabilized. + assert_eq!(numbers[100..200].iter().sum::(), 30_100); + + let usage = getrusage(UsageWho::RUSAGE_SELF) + .expect("Failed to call getrusage for SELF"); + let rusage = usage.as_ref(); + + let user = usage.user_time(); + assert!(user.tv_sec() > 0 || user.tv_usec() > 0); + assert_eq!(user.tv_sec(), rusage.ru_utime.tv_sec); + assert_eq!(user.tv_usec(), rusage.ru_utime.tv_usec); +} diff --git a/test/sys/test_select.rs b/test/sys/test_select.rs index 111e444d49..746c6b6966 100644 --- a/test/sys/test_select.rs +++ b/test/sys/test_select.rs @@ -1,8 +1,8 @@ use nix::sys::select::*; use nix::sys::signal::SigSet; -use nix::sys::time::{TimeSpec, TimeValLike}; +use nix::sys::time::{TimeSpec, TimeVal, TimeValLike}; use nix::unistd::{pipe, write}; -use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd}; +use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd}; #[test] pub fn test_pselect() { @@ -76,3 +76,219 @@ mod test_fdset_too_large_fd { contains, ); } + +#[test] +fn fdset_insert() { + let mut fd_set = FdSet::new(); + + for i in 0..FD_SETSIZE { + let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) }; + assert!(!fd_set.contains(borrowed_i)); + } + + let fd_seven = unsafe { BorrowedFd::borrow_raw(7) }; + fd_set.insert(fd_seven); + + assert!(fd_set.contains(fd_seven)); +} + +#[test] +fn fdset_remove() { + let mut fd_set = FdSet::new(); + + for i in 0..FD_SETSIZE { + let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) }; + assert!(!fd_set.contains(borrowed_i)); + } + + let fd_seven = unsafe { BorrowedFd::borrow_raw(7) }; + fd_set.insert(fd_seven); + fd_set.remove(fd_seven); + + for i in 0..FD_SETSIZE { + let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) }; + assert!(!fd_set.contains(borrowed_i)); + } +} + +#[test] +#[allow(non_snake_case)] +fn fdset_clear() { + let mut fd_set = FdSet::new(); + let fd_one = unsafe { BorrowedFd::borrow_raw(1) }; + let fd_FD_SETSIZE_divided_by_two = + unsafe { BorrowedFd::borrow_raw((FD_SETSIZE / 2) as RawFd) }; + let fd_FD_SETSIZE_minus_one = + unsafe { BorrowedFd::borrow_raw((FD_SETSIZE - 1) as RawFd) }; + fd_set.insert(fd_one); + fd_set.insert(fd_FD_SETSIZE_divided_by_two); + fd_set.insert(fd_FD_SETSIZE_minus_one); + + fd_set.clear(); + + for i in 0..FD_SETSIZE { + let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) }; + assert!(!fd_set.contains(borrowed_i)); + } +} + +#[test] +fn fdset_highest() { + let mut set = FdSet::new(); + assert_eq!( + set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()), + None + ); + let fd_zero = unsafe { BorrowedFd::borrow_raw(0) }; + let fd_ninety = unsafe { BorrowedFd::borrow_raw(90) }; + set.insert(fd_zero); + assert_eq!( + set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()), + Some(0) + ); + set.insert(fd_ninety); + assert_eq!( + set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()), + Some(90) + ); + set.remove(fd_zero); + assert_eq!( + set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()), + Some(90) + ); + set.remove(fd_ninety); + assert_eq!( + set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()), + None + ); + + let fd_four = unsafe { BorrowedFd::borrow_raw(4) }; + let fd_five = unsafe { BorrowedFd::borrow_raw(5) }; + let fd_seven = unsafe { BorrowedFd::borrow_raw(7) }; + set.insert(fd_four); + set.insert(fd_five); + set.insert(fd_seven); + assert_eq!( + set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()), + Some(7) + ); +} + +#[test] +fn fdset_fds() { + let mut set = FdSet::new(); + let fd_zero = unsafe { BorrowedFd::borrow_raw(0) }; + let fd_ninety = unsafe { BorrowedFd::borrow_raw(90) }; + assert_eq!( + set.fds(None) + .map(|borrowed_fd| borrowed_fd.as_raw_fd()) + .collect::>(), + vec![] + ); + set.insert(fd_zero); + assert_eq!( + set.fds(None) + .map(|borrowed_fd| borrowed_fd.as_raw_fd()) + .collect::>(), + vec![0] + ); + set.insert(fd_ninety); + assert_eq!( + set.fds(None) + .map(|borrowed_fd| borrowed_fd.as_raw_fd()) + .collect::>(), + vec![0, 90] + ); + + // highest limit + assert_eq!( + set.fds(Some(89)) + .map(|borrowed_fd| borrowed_fd.as_raw_fd()) + .collect::>(), + vec![0] + ); + assert_eq!( + set.fds(Some(90)) + .map(|borrowed_fd| borrowed_fd.as_raw_fd()) + .collect::>(), + vec![0, 90] + ); +} + +#[test] +fn test_select() { + let (r1, w1) = pipe().unwrap(); + let (r2, _w2) = pipe().unwrap(); + + write(&w1, b"hi!").unwrap(); + let mut fd_set = FdSet::new(); + fd_set.insert(r1.as_fd()); + fd_set.insert(r2.as_fd()); + + let mut timeout = TimeVal::seconds(10); + assert_eq!( + 1, + select(None, &mut fd_set, None, None, &mut timeout).unwrap() + ); + assert!(fd_set.contains(r1.as_fd())); + assert!(!fd_set.contains(r2.as_fd())); +} + +#[test] +fn test_select_nfds() { + let (r1, w1) = pipe().unwrap(); + let (r2, _w2) = pipe().unwrap(); + + write(&w1, b"hi!").unwrap(); + let mut fd_set = FdSet::new(); + fd_set.insert(r1.as_fd()); + fd_set.insert(r2.as_fd()); + + let mut timeout = TimeVal::seconds(10); + { + assert_eq!( + 1, + select( + Some( + fd_set + .highest() + .map(|borrowed_fd| borrowed_fd.as_raw_fd()) + .unwrap() + + 1 + ), + &mut fd_set, + None, + None, + &mut timeout + ) + .unwrap() + ); + } + assert!(fd_set.contains(r1.as_fd())); + assert!(!fd_set.contains(r2.as_fd())); +} + +#[test] +fn test_select_nfds2() { + let (r1, w1) = pipe().unwrap(); + write(&w1, b"hi!").unwrap(); + let (r2, _w2) = pipe().unwrap(); + let mut fd_set = FdSet::new(); + fd_set.insert(r1.as_fd()); + fd_set.insert(r2.as_fd()); + + let mut timeout = TimeVal::seconds(10); + assert_eq!( + 1, + select( + std::cmp::max(r1.as_raw_fd(), r2.as_raw_fd()) + 1, + &mut fd_set, + None, + None, + &mut timeout + ) + .unwrap() + ); + assert!(fd_set.contains(r1.as_fd())); + assert!(!fd_set.contains(r2.as_fd())); +} diff --git a/test/sys/test_signal.rs b/test/sys/test_signal.rs index bf201ab800..eb6347d5b0 100644 --- a/test/sys/test_signal.rs +++ b/test/sys/test_signal.rs @@ -1,9 +1,11 @@ -#[cfg(not(target_os = "redox"))] use nix::errno::Errno; use nix::sys::signal::*; use nix::unistd::*; use std::convert::TryFrom; +use std::hash::{Hash, Hasher}; use std::sync::atomic::{AtomicBool, Ordering}; +#[cfg(not(target_os = "redox"))] +use std::thread; #[test] fn test_kill_none() { @@ -141,3 +143,263 @@ fn test_signal() { // Restore default signal handler unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(); } + +#[test] +fn test_contains() { + let mut mask = SigSet::empty(); + mask.add(SIGUSR1); + + assert!(mask.contains(SIGUSR1)); + assert!(!mask.contains(SIGUSR2)); + + let all = SigSet::all(); + assert!(all.contains(SIGUSR1)); + assert!(all.contains(SIGUSR2)); +} + +#[test] +fn test_clear() { + let mut set = SigSet::all(); + set.clear(); + for signal in Signal::iterator() { + assert!(!set.contains(signal)); + } +} + +#[test] +fn test_from_str_round_trips() { + for signal in Signal::iterator() { + assert_eq!(signal.as_ref().parse::().unwrap(), signal); + assert_eq!(signal.to_string().parse::().unwrap(), signal); + } +} + +#[test] +fn test_from_str_invalid_value() { + let errval = Err(Errno::EINVAL); + assert_eq!("NOSIGNAL".parse::(), errval); + assert_eq!("kill".parse::(), errval); + assert_eq!("9".parse::(), errval); +} + +#[test] +fn test_extend() { + let mut one_signal = SigSet::empty(); + one_signal.add(SIGUSR1); + + let mut two_signals = SigSet::empty(); + two_signals.add(SIGUSR2); + two_signals.extend(&one_signal); + + assert!(two_signals.contains(SIGUSR1)); + assert!(two_signals.contains(SIGUSR2)); +} + +#[test] +#[cfg(not(target_os = "redox"))] +fn test_thread_signal_set_mask() { + thread::spawn(|| { + let prev_mask = SigSet::thread_get_mask() + .expect("Failed to get existing signal mask!"); + + let mut test_mask = prev_mask; + test_mask.add(SIGUSR1); + + test_mask.thread_set_mask().expect("assertion failed"); + let new_mask = + SigSet::thread_get_mask().expect("Failed to get new mask!"); + + assert!(new_mask.contains(SIGUSR1)); + assert!(!new_mask.contains(SIGUSR2)); + + prev_mask + .thread_set_mask() + .expect("Failed to revert signal mask!"); + }) + .join() + .unwrap(); +} + +#[test] +#[cfg(not(target_os = "redox"))] +fn test_thread_signal_block() { + thread::spawn(|| { + let mut mask = SigSet::empty(); + mask.add(SIGUSR1); + + mask.thread_block().expect("assertion failed"); + + assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1)); + }) + .join() + .unwrap(); +} + +#[test] +#[cfg(not(target_os = "redox"))] +fn test_thread_signal_unblock() { + thread::spawn(|| { + let mut mask = SigSet::empty(); + mask.add(SIGUSR1); + + mask.thread_unblock().expect("assertion failed"); + + assert!(!SigSet::thread_get_mask().unwrap().contains(SIGUSR1)); + }) + .join() + .unwrap(); +} + +#[test] +#[cfg(not(target_os = "redox"))] +fn test_thread_signal_swap() { + thread::spawn(|| { + let mut mask = SigSet::empty(); + mask.add(SIGUSR1); + mask.thread_block().unwrap(); + + assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1)); + + let mut mask2 = SigSet::empty(); + mask2.add(SIGUSR2); + + let oldmask = mask2.thread_swap_mask(SigmaskHow::SIG_SETMASK).unwrap(); + + assert!(oldmask.contains(SIGUSR1)); + assert!(!oldmask.contains(SIGUSR2)); + + assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR2)); + }) + .join() + .unwrap(); +} + +#[test] +fn test_from_and_into_iterator() { + let sigset = SigSet::from_iter(vec![Signal::SIGUSR1, Signal::SIGUSR2]); + let signals = sigset.into_iter().collect::>(); + assert_eq!(signals, [Signal::SIGUSR1, Signal::SIGUSR2]); +} + +#[test] +#[cfg(not(target_os = "redox"))] +fn test_sigaction() { + thread::spawn(|| { + extern "C" fn test_sigaction_handler(_: libc::c_int) {} + extern "C" fn test_sigaction_action( + _: libc::c_int, + _: *mut libc::siginfo_t, + _: *mut libc::c_void, + ) { + } + + let handler_sig = SigHandler::Handler(test_sigaction_handler); + + let flags = + SaFlags::SA_ONSTACK | SaFlags::SA_RESTART | SaFlags::SA_SIGINFO; + + let mut mask = SigSet::empty(); + mask.add(SIGUSR1); + + let action_sig = SigAction::new(handler_sig, flags, mask); + + assert_eq!( + action_sig.flags(), + SaFlags::SA_ONSTACK | SaFlags::SA_RESTART + ); + assert_eq!(action_sig.handler(), handler_sig); + + mask = action_sig.mask(); + assert!(mask.contains(SIGUSR1)); + assert!(!mask.contains(SIGUSR2)); + + let handler_act = SigHandler::SigAction(test_sigaction_action); + let action_act = SigAction::new(handler_act, flags, mask); + assert_eq!(action_act.handler(), handler_act); + + let action_dfl = SigAction::new(SigHandler::SigDfl, flags, mask); + assert_eq!(action_dfl.handler(), SigHandler::SigDfl); + + let action_ign = SigAction::new(SigHandler::SigIgn, flags, mask); + assert_eq!(action_ign.handler(), SigHandler::SigIgn); + }) + .join() + .unwrap(); +} + +#[test] +#[cfg(not(target_os = "redox"))] +fn test_sigwait() { + thread::spawn(|| { + let mut mask = SigSet::empty(); + mask.add(SIGUSR1); + mask.add(SIGUSR2); + mask.thread_block().unwrap(); + + raise(SIGUSR1).unwrap(); + assert_eq!(mask.wait().unwrap(), SIGUSR1); + }) + .join() + .unwrap(); +} + +#[test] +fn test_from_sigset_t_unchecked() { + let src_set = SigSet::empty(); + let set = unsafe { SigSet::from_sigset_t_unchecked(*src_set.as_ref()) }; + + for signal in Signal::iterator() { + assert!(!set.contains(signal)); + } + + let src_set = SigSet::all(); + let set = unsafe { SigSet::from_sigset_t_unchecked(*src_set.as_ref()) }; + + for signal in Signal::iterator() { + assert!(set.contains(signal)); + } +} + +#[test] +fn test_eq_empty() { + let set0 = SigSet::empty(); + let set1 = SigSet::empty(); + assert_eq!(set0, set1); +} + +#[test] +fn test_eq_all() { + let set0 = SigSet::all(); + let set1 = SigSet::all(); + assert_eq!(set0, set1); +} + +#[test] +fn test_hash_empty() { + use std::collections::hash_map::DefaultHasher; + + let set0 = SigSet::empty(); + let mut h0 = DefaultHasher::new(); + set0.hash(&mut h0); + + let set1 = SigSet::empty(); + let mut h1 = DefaultHasher::new(); + set1.hash(&mut h1); + + assert_eq!(h0.finish(), h1.finish()); +} + +#[test] +fn test_hash_all() { + use std::collections::hash_map::DefaultHasher; + + let set0 = SigSet::all(); + let mut h0 = DefaultHasher::new(); + set0.hash(&mut h0); + + let set1 = SigSet::all(); + let mut h1 = DefaultHasher::new(); + set1.hash(&mut h1); + + assert_eq!(h0.finish(), h1.finish()); +} diff --git a/test/sys/test_signalfd.rs b/test/sys/test_signalfd.rs index 6a279d1832..4e0971aba7 100644 --- a/test/sys/test_signalfd.rs +++ b/test/sys/test_signalfd.rs @@ -1,5 +1,39 @@ use std::convert::TryFrom; +#[test] +fn create_signalfd() { + use nix::sys::{signal::SigSet, signalfd::SignalFd}; + + let mask = SigSet::empty(); + SignalFd::new(&mask).unwrap(); +} + +#[test] +fn create_signalfd_with_opts() { + use nix::sys::{ + signal::SigSet, + signalfd::{SfdFlags, SignalFd}, + }; + + let mask = SigSet::empty(); + SignalFd::with_flags(&mask, SfdFlags::SFD_CLOEXEC | SfdFlags::SFD_NONBLOCK) + .unwrap(); +} + +#[test] +fn read_empty_signalfd() { + use nix::sys::{ + signal::SigSet, + signalfd::{SfdFlags, SignalFd}, + }; + + let mask = SigSet::empty(); + let mut fd = SignalFd::with_flags(&mask, SfdFlags::SFD_NONBLOCK).unwrap(); + + let res = fd.read_signal(); + assert!(res.unwrap().is_none()); +} + #[test] fn test_signalfd() { use nix::sys::signal::{self, raise, SigSet, Signal}; diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs index 736fae1937..504ad44fde 100644 --- a/test/sys/test_socket.rs +++ b/test/sys/test_socket.rs @@ -2791,3 +2791,127 @@ fn test_icmp_protocol() { sendto(owned_fd.as_raw_fd(), &packet, &dest_addr, MsgFlags::empty()) .unwrap(); } + +// test contains both recvmmsg and timestaping which is linux only +// there are existing tests for recvmmsg only in tests/ +#[cfg_attr(qemu, ignore)] +#[cfg(target_os = "linux")] +#[test] +fn test_recvmm2() -> nix::Result<()> { + use nix::sys::{ + socket::{ + bind, recvmmsg, sendmsg, setsockopt, socket, sockopt::Timestamping, + AddressFamily, ControlMessageOwned, MsgFlags, MultiHeaders, + SockFlag, SockType, SockaddrIn, TimestampingFlag, Timestamps, + }, + time::TimeSpec, + }; + use std::io::{IoSlice, IoSliceMut}; + use std::os::unix::io::AsRawFd; + use std::str::FromStr; + + let sock_addr = SockaddrIn::from_str("127.0.0.1:6790").unwrap(); + + let ssock = socket( + AddressFamily::Inet, + SockType::Datagram, + SockFlag::empty(), + None, + )?; + + let rsock = socket( + AddressFamily::Inet, + SockType::Datagram, + SockFlag::SOCK_NONBLOCK, + None, + )?; + + bind(rsock.as_raw_fd(), &sock_addr)?; + + setsockopt(&rsock, Timestamping, &TimestampingFlag::all())?; + + let sbuf = (0..400).map(|i| i as u8).collect::>(); + + let mut recv_buf = vec![0; 1024]; + + let mut recv_iovs = Vec::new(); + let mut pkt_iovs = Vec::new(); + + for (ix, chunk) in recv_buf.chunks_mut(256).enumerate() { + pkt_iovs.push(IoSliceMut::new(chunk)); + if ix % 2 == 1 { + recv_iovs.push(pkt_iovs); + pkt_iovs = Vec::new(); + } + } + drop(pkt_iovs); + + let flags = MsgFlags::empty(); + let iov1 = [IoSlice::new(&sbuf)]; + + let cmsg = cmsg_space!(Timestamps); + sendmsg(ssock.as_raw_fd(), &iov1, &[], flags, Some(&sock_addr)).unwrap(); + + let mut data = MultiHeaders::<()>::preallocate(recv_iovs.len(), Some(cmsg)); + + let t = TimeSpec::from_duration(std::time::Duration::from_secs(10)); + + let recv = recvmmsg( + rsock.as_raw_fd(), + &mut data, + recv_iovs.iter_mut(), + flags, + Some(t), + )?; + + for rmsg in recv { + #[cfg(not(any(qemu, target_arch = "aarch64")))] + let mut saw_time = false; + let mut recvd = 0; + for cmsg in rmsg.cmsgs() { + if let ControlMessageOwned::ScmTimestampsns(timestamps) = cmsg { + let ts = timestamps.system; + + let sys_time = nix::time::clock_gettime( + nix::time::ClockId::CLOCK_REALTIME, + )?; + let diff = if ts > sys_time { + ts - sys_time + } else { + sys_time - ts + }; + assert!(std::time::Duration::from(diff).as_secs() < 60); + #[cfg(not(any(qemu, target_arch = "aarch64")))] + { + saw_time = true; + } + } + } + + #[cfg(not(any(qemu, target_arch = "aarch64")))] + assert!(saw_time); + + for iov in rmsg.iovs() { + recvd += iov.len(); + } + assert_eq!(recvd, 400); + } + + Ok(()) +} + +#[cfg(not(target_os = "redox"))] +#[test] +fn can_use_cmsg_space() { + let _ = cmsg_space!(u8); +} + +#[cfg(not(any(linux_android, target_os = "redox", target_os = "haiku")))] +#[test] +fn can_open_routing_socket() { + use nix::sys::socket::{socket, AddressFamily, SockFlag, SockType}; + + let _ = + socket(AddressFamily::Route, SockType::Raw, SockFlag::empty(), None) + .expect("Failed to open routing socket"); +} diff --git a/test/sys/test_sockopt.rs b/test/sys/test_sockopt.rs index d7e00e3b1b..876df7a56d 100644 --- a/test/sys/test_sockopt.rs +++ b/test/sys/test_sockopt.rs @@ -636,3 +636,74 @@ fn test_tcp_fast_open_connect() { "getting TCP_FASTOPEN_CONNECT on an inet stream socket should succeed", )); } + +#[cfg(linux_android)] +#[test] +fn can_get_peercred_on_unix_socket() { + use nix::sys::socket::{socketpair, sockopt, SockFlag, SockType}; + + let (a, b) = socketpair( + AddressFamily::Unix, + SockType::Stream, + None, + SockFlag::empty(), + ) + .unwrap(); + let a_cred = getsockopt(&a, sockopt::PeerCredentials).unwrap(); + let b_cred = getsockopt(&b, sockopt::PeerCredentials).unwrap(); + assert_eq!(a_cred, b_cred); + assert_ne!(a_cred.pid(), 0); +} + +#[test] +fn is_socket_type_unix() { + use nix::sys::socket::{socketpair, sockopt, SockFlag, SockType}; + + let (a, _b) = socketpair( + AddressFamily::Unix, + SockType::Stream, + None, + SockFlag::empty(), + ) + .unwrap(); + let a_type = getsockopt(&a, sockopt::SockType).unwrap(); + assert_eq!(a_type, SockType::Stream); +} + +#[test] +fn is_socket_type_dgram() { + use nix::sys::socket::{ + getsockopt, sockopt, AddressFamily, SockFlag, SockType, + }; + + let s = socket( + AddressFamily::Inet, + SockType::Datagram, + SockFlag::empty(), + None, + ) + .unwrap(); + let s_type = getsockopt(&s, sockopt::SockType).unwrap(); + assert_eq!(s_type, SockType::Datagram); +} + +#[cfg(any(target_os = "freebsd", target_os = "linux"))] +#[test] +fn can_get_listen_on_tcp_socket() { + use nix::sys::socket::{ + getsockopt, listen, socket, sockopt, AddressFamily, SockFlag, SockType, + }; + + let s = socket( + AddressFamily::Inet, + SockType::Stream, + SockFlag::empty(), + None, + ) + .unwrap(); + let s_listening = getsockopt(&s, sockopt::AcceptConn).unwrap(); + assert!(!s_listening); + listen(&s, 10).unwrap(); + let s_listening2 = getsockopt(&s, sockopt::AcceptConn).unwrap(); + assert!(s_listening2); +} diff --git a/test/sys/test_statfs.rs b/test/sys/test_statfs.rs new file mode 100644 index 0000000000..66b3f2ce96 --- /dev/null +++ b/test/sys/test_statfs.rs @@ -0,0 +1,99 @@ +use nix::sys::statfs::*; +use nix::sys::statvfs::*; +use std::fs::File; +use std::path::Path; + +fn check_fstatfs(path: &str) { + if !Path::new(path).exists() { + return; + } + let vfs = statvfs(path.as_bytes()).unwrap(); + let file = File::open(path).unwrap(); + let fs = fstatfs(&file).unwrap(); + assert_fs_equals(fs, vfs); +} + +fn check_statfs(path: &str) { + if !Path::new(path).exists() { + return; + } + let vfs = statvfs(path.as_bytes()).unwrap(); + let fs = statfs(path.as_bytes()).unwrap(); + assert_fs_equals(fs, vfs); +} + +fn check_fstatfs_strict(path: &str) { + if !Path::new(path).exists() { + return; + } + let vfs = statvfs(path.as_bytes()); + let file = File::open(path).unwrap(); + let fs = fstatfs(&file); + assert_fs_equals_strict(fs.unwrap(), vfs.unwrap()) +} + +fn check_statfs_strict(path: &str) { + if !Path::new(path).exists() { + return; + } + let vfs = statvfs(path.as_bytes()); + let fs = statfs(path.as_bytes()); + assert_fs_equals_strict(fs.unwrap(), vfs.unwrap()) +} + +// The cast is not unnecessary on all platforms. +#[allow(clippy::unnecessary_cast)] +fn assert_fs_equals(fs: Statfs, vfs: Statvfs) { + assert_eq!(fs.files() as u64, vfs.files() as u64); + assert_eq!(fs.blocks() as u64, vfs.blocks() as u64); + assert_eq!(fs.block_size() as u64, vfs.fragment_size() as u64); +} + +#[test] +fn statfs_call() { + check_statfs("/tmp"); + check_statfs("/dev"); + check_statfs("/run"); + check_statfs("/"); +} + +#[test] +fn fstatfs_call() { + check_fstatfs("/tmp"); + check_fstatfs("/dev"); + check_fstatfs("/run"); + check_fstatfs("/"); +} + +// This test is ignored because files_free/blocks_free can change after statvfs call and before +// statfs call. +#[test] +#[ignore] +fn statfs_call_strict() { + check_statfs_strict("/tmp"); + check_statfs_strict("/dev"); + check_statfs_strict("/run"); + check_statfs_strict("/"); +} + +// This test is ignored because files_free/blocks_free can change after statvfs call and before +// fstatfs call. +#[test] +#[ignore] +fn fstatfs_call_strict() { + check_fstatfs_strict("/tmp"); + check_fstatfs_strict("/dev"); + check_fstatfs_strict("/run"); + check_fstatfs_strict("/"); +} + +// The cast is not unnecessary on all platforms. +#[allow(clippy::unnecessary_cast)] +fn assert_fs_equals_strict(fs: Statfs, vfs: Statvfs) { + assert_eq!(fs.files_free() as u64, vfs.files_free() as u64); + assert_eq!(fs.blocks_free() as u64, vfs.blocks_free() as u64); + assert_eq!(fs.blocks_available() as u64, vfs.blocks_available() as u64); + assert_eq!(fs.files() as u64, vfs.files() as u64); + assert_eq!(fs.blocks() as u64, vfs.blocks() as u64); + assert_eq!(fs.block_size() as u64, vfs.fragment_size() as u64); +} diff --git a/test/sys/test_statvfs.rs b/test/sys/test_statvfs.rs new file mode 100644 index 0000000000..5c80965253 --- /dev/null +++ b/test/sys/test_statvfs.rs @@ -0,0 +1,13 @@ +use nix::sys::statvfs::*; +use std::fs::File; + +#[test] +fn statvfs_call() { + statvfs(&b"/"[..]).unwrap(); +} + +#[test] +fn fstatvfs_call() { + let root = File::open("/").unwrap(); + fstatvfs(&root).unwrap(); +} diff --git a/test/sys/test_termios.rs b/test/sys/test_termios.rs index 21bb8c61ef..72399cf6a5 100644 --- a/test/sys/test_termios.rs +++ b/test/sys/test_termios.rs @@ -1,10 +1,11 @@ +use std::convert::TryFrom; use std::os::unix::io::{AsFd, AsRawFd}; use tempfile::tempfile; use nix::errno::Errno; use nix::fcntl; use nix::pty::openpty; -use nix::sys::termios::{self, tcgetattr, LocalFlags, OutputFlags}; +use nix::sys::termios::{self, tcgetattr, BaudRate, LocalFlags, OutputFlags}; use nix::unistd::{read, write}; /// Helper function analogous to `std::io::Write::write_all`, but for `Fd`s @@ -15,6 +16,15 @@ fn write_all(f: Fd, buf: &[u8]) { } } +#[test] +fn test_baudrate_try_from() { + assert_eq!(Ok(BaudRate::B0), BaudRate::try_from(libc::B0)); + #[cfg(not(target_os = "haiku"))] + BaudRate::try_from(999999999).expect_err("assertion failed"); + #[cfg(target_os = "haiku")] + BaudRate::try_from(99).expect_err("assertion failed"); +} + // Test tcgetattr on a terminal #[test] fn test_tcgetattr_pty() { diff --git a/test/sys/test_time.rs b/test/sys/test_time.rs new file mode 100644 index 0000000000..0510225a92 --- /dev/null +++ b/test/sys/test_time.rs @@ -0,0 +1,91 @@ +use nix::sys::time::{TimeSpec, TimeVal, TimeValLike}; +use std::time::Duration; + +#[test] +pub fn test_timespec() { + assert_ne!(TimeSpec::seconds(1), TimeSpec::zero()); + assert_eq!( + TimeSpec::seconds(1) + TimeSpec::seconds(2), + TimeSpec::seconds(3) + ); + assert_eq!( + TimeSpec::minutes(3) + TimeSpec::seconds(2), + TimeSpec::seconds(182) + ); +} + +#[test] +pub fn test_timespec_from() { + let duration = Duration::new(123, 123_456_789); + let timespec = TimeSpec::nanoseconds(123_123_456_789); + + assert_eq!(TimeSpec::from(duration), timespec); + assert_eq!(Duration::from(timespec), duration); +} + +#[test] +pub fn test_timespec_neg() { + let a = TimeSpec::seconds(1) + TimeSpec::nanoseconds(123); + let b = TimeSpec::seconds(-1) + TimeSpec::nanoseconds(-123); + + assert_eq!(a, -b); +} + +#[test] +pub fn test_timespec_ord() { + assert_eq!(TimeSpec::seconds(1), TimeSpec::nanoseconds(1_000_000_000)); + assert!(TimeSpec::seconds(1) < TimeSpec::nanoseconds(1_000_000_001)); + assert!(TimeSpec::seconds(1) > TimeSpec::nanoseconds(999_999_999)); + assert!(TimeSpec::seconds(-1) < TimeSpec::nanoseconds(-999_999_999)); + assert!(TimeSpec::seconds(-1) > TimeSpec::nanoseconds(-1_000_000_001)); +} + +#[test] +pub fn test_timespec_fmt() { + assert_eq!(TimeSpec::zero().to_string(), "0 seconds"); + assert_eq!(TimeSpec::seconds(42).to_string(), "42 seconds"); + assert_eq!(TimeSpec::milliseconds(42).to_string(), "0.042 seconds"); + assert_eq!(TimeSpec::microseconds(42).to_string(), "0.000042 seconds"); + assert_eq!(TimeSpec::nanoseconds(42).to_string(), "0.000000042 seconds"); + assert_eq!(TimeSpec::seconds(-86401).to_string(), "-86401 seconds"); +} + +#[test] +pub fn test_timeval() { + assert_ne!(TimeVal::seconds(1), TimeVal::zero()); + assert_eq!( + TimeVal::seconds(1) + TimeVal::seconds(2), + TimeVal::seconds(3) + ); + assert_eq!( + TimeVal::minutes(3) + TimeVal::seconds(2), + TimeVal::seconds(182) + ); +} + +#[test] +pub fn test_timeval_ord() { + assert_eq!(TimeVal::seconds(1), TimeVal::microseconds(1_000_000)); + assert!(TimeVal::seconds(1) < TimeVal::microseconds(1_000_001)); + assert!(TimeVal::seconds(1) > TimeVal::microseconds(999_999)); + assert!(TimeVal::seconds(-1) < TimeVal::microseconds(-999_999)); + assert!(TimeVal::seconds(-1) > TimeVal::microseconds(-1_000_001)); +} + +#[test] +pub fn test_timeval_neg() { + let a = TimeVal::seconds(1) + TimeVal::microseconds(123); + let b = TimeVal::seconds(-1) + TimeVal::microseconds(-123); + + assert_eq!(a, -b); +} + +#[test] +pub fn test_timeval_fmt() { + assert_eq!(TimeVal::zero().to_string(), "0 seconds"); + assert_eq!(TimeVal::seconds(42).to_string(), "42 seconds"); + assert_eq!(TimeVal::milliseconds(42).to_string(), "0.042 seconds"); + assert_eq!(TimeVal::microseconds(42).to_string(), "0.000042 seconds"); + assert_eq!(TimeVal::nanoseconds(1402).to_string(), "0.000001 seconds"); + assert_eq!(TimeVal::seconds(-86401).to_string(), "-86401 seconds"); +} diff --git a/test/test_timer.rs b/test/sys/test_timer.rs similarity index 100% rename from test/test_timer.rs rename to test/sys/test_timer.rs diff --git a/test/sys/test_utsname.rs b/test/sys/test_utsname.rs new file mode 100644 index 0000000000..8f84ac074f --- /dev/null +++ b/test/sys/test_utsname.rs @@ -0,0 +1,17 @@ +#[cfg(target_os = "linux")] +#[test] +pub fn test_uname_linux() { + assert_eq!(nix::sys::utsname::uname().unwrap().sysname(), "Linux"); +} + +#[cfg(apple_targets)] +#[test] +pub fn test_uname_darwin() { + assert_eq!(nix::sys::utsname::uname().unwrap().sysname(), "Darwin"); +} + +#[cfg(target_os = "freebsd")] +#[test] +pub fn test_uname_freebsd() { + assert_eq!(nix::sys::utsname::uname().unwrap().sysname(), "FreeBSD"); +} diff --git a/test/test.rs b/test/test.rs index fc6b4b3e32..205ae3329c 100644 --- a/test/test.rs +++ b/test/test.rs @@ -29,7 +29,6 @@ mod test_poll; target_os = "haiku" )))] mod test_pty; -mod test_resource; #[cfg(any( linux_android, target_os = "dragonfly", @@ -40,17 +39,6 @@ mod test_sched; mod test_sendfile; mod test_stat; mod test_time; -#[cfg(all( - any( - target_os = "freebsd", - solarish, - target_os = "linux", - target_os = "netbsd" - ), - feature = "time", - feature = "signal" -))] -mod test_timer; mod test_unistd; use nix::unistd::{chdir, getcwd, read};