summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/common/mod.rs6
-rw-r--r--test/sys/mod.rs2
-rw-r--r--test/sys/test_mman.rs14
-rw-r--r--test/sys/test_ptrace.rs16
-rw-r--r--test/sys/test_socket.rs246
-rw-r--r--test/sys/test_sockopt.rs64
-rw-r--r--test/sys/test_uio.rs6
-rw-r--r--test/sys/test_wait.rs2
-rw-r--r--test/test_fcntl.rs10
-rw-r--r--test/test_kmod/mod.rs16
-rw-r--r--test/test_mq.rs12
-rw-r--r--test/test_poll.rs8
-rw-r--r--test/test_unistd.rs4
13 files changed, 331 insertions, 75 deletions
diff --git a/test/common/mod.rs b/test/common/mod.rs
index cdc32582..84a0b4fa 100644
--- a/test/common/mod.rs
+++ b/test/common/mod.rs
@@ -14,19 +14,19 @@ use cfg_if::cfg_if;
cfg_if! {
if #[cfg(any(target_os = "android", target_os = "linux"))] {
#[macro_export] macro_rules! require_capability {
- ($capname:ident) => {
+ ($name:expr, $capname:ident) => {
use ::caps::{Capability, CapSet, has_cap};
if !has_cap(None, CapSet::Effective, Capability::$capname)
.unwrap()
{
- skip!("Insufficient capabilities. Skipping test.");
+ skip!("{} requires capability {}. Skipping test.", $name, Capability::$capname);
}
}
}
} else if #[cfg(not(target_os = "redox"))] {
#[macro_export] macro_rules! require_capability {
- ($capname:ident) => {}
+ ($name:expr, $capname:ident) => {}
}
}
}
diff --git a/test/sys/mod.rs b/test/sys/mod.rs
index 4f5316ff..14b03784 100644
--- a/test/sys/mod.rs
+++ b/test/sys/mod.rs
@@ -41,5 +41,5 @@ mod test_pthread;
target_os = "netbsd",
target_os = "openbsd"))]
mod test_ptrace;
-#[cfg(target_os = "linux")]
+#[cfg(any(target_os = "android", target_os = "linux"))]
mod test_timerfd;
diff --git a/test/sys/test_mman.rs b/test/sys/test_mman.rs
index 152fff69..4d140948 100644
--- a/test/sys/test_mman.rs
+++ b/test/sys/test_mman.rs
@@ -20,7 +20,7 @@ fn test_mmap_anonymous() {
}
#[test]
-#[cfg(target_os = "linux")]
+#[cfg(any(target_os = "linux", target_os = "netbsd"))]
fn test_mremap_grow() {
const ONE_K : size_t = 1024;
let slice : &mut[u8] = unsafe {
@@ -35,9 +35,14 @@ fn test_mremap_grow() {
assert_eq !(slice[ONE_K - 1], 0xFF);
let slice : &mut[u8] = unsafe {
+ #[cfg(target_os = "linux")]
let mem = mremap(slice.as_mut_ptr() as * mut c_void, ONE_K, 10 * ONE_K,
MRemapFlags::MREMAP_MAYMOVE, None)
.unwrap();
+ #[cfg(target_os = "netbsd")]
+ let mem = mremap(slice.as_mut_ptr() as * mut c_void, ONE_K, 10 * ONE_K,
+ MRemapFlags::MAP_REMAPDUP, None)
+ .unwrap();
std::slice::from_raw_parts_mut(mem as * mut u8, 10 * ONE_K)
};
@@ -51,7 +56,7 @@ fn test_mremap_grow() {
}
#[test]
-#[cfg(target_os = "linux")]
+#[cfg(any(target_os = "linux", target_os = "netbsd"))]
fn test_mremap_shrink() {
const ONE_K : size_t = 1024;
let slice : &mut[u8] = unsafe {
@@ -66,11 +71,16 @@ fn test_mremap_shrink() {
assert_eq !(slice[ONE_K - 1], 0xFF);
let slice : &mut[u8] = unsafe {
+ #[cfg(target_os = "linux")]
let mem = mremap(slice.as_mut_ptr() as * mut c_void, 10 * ONE_K, ONE_K,
MRemapFlags::empty(), None)
.unwrap();
// Since we didn't supply MREMAP_MAYMOVE, the address should be the
// same.
+ #[cfg(target_os = "linux")]
+ let mem = mremap(slice.as_mut_ptr() as * mut c_void, 10 * ONE_K, ONE_K,
+ MRemapFlags::MAP_FIXED), None)
+ .unwrap();
assert_eq !(mem, slice.as_mut_ptr() as * mut c_void);
std::slice::from_raw_parts_mut(mem as * mut u8, ONE_K)
};
diff --git a/test/sys/test_ptrace.rs b/test/sys/test_ptrace.rs
index ceb39b9b..1c72e7c2 100644
--- a/test/sys/test_ptrace.rs
+++ b/test/sys/test_ptrace.rs
@@ -13,7 +13,7 @@ use crate::*;
fn test_ptrace() {
// Just make sure ptrace can be called at all, for now.
// FIXME: qemu-user doesn't implement ptrace on all arches, so permit ENOSYS
- require_capability!(CAP_SYS_PTRACE);
+ require_capability!("test_ptrace", CAP_SYS_PTRACE);
let err = ptrace::attach(getpid()).unwrap_err();
assert!(err == Errno::EPERM || err == Errno::EINVAL ||
err == Errno::ENOSYS);
@@ -23,7 +23,7 @@ fn test_ptrace() {
#[test]
#[cfg(any(target_os = "android", target_os = "linux"))]
fn test_ptrace_setoptions() {
- require_capability!(CAP_SYS_PTRACE);
+ require_capability!("test_ptrace_setoptions", CAP_SYS_PTRACE);
let err = ptrace::setoptions(getpid(), Options::PTRACE_O_TRACESYSGOOD).unwrap_err();
assert!(err != Errno::EOPNOTSUPP);
}
@@ -32,7 +32,7 @@ fn test_ptrace_setoptions() {
#[test]
#[cfg(any(target_os = "android", target_os = "linux"))]
fn test_ptrace_getevent() {
- require_capability!(CAP_SYS_PTRACE);
+ require_capability!("test_ptrace_getevent", CAP_SYS_PTRACE);
let err = ptrace::getevent(getpid()).unwrap_err();
assert!(err != Errno::EOPNOTSUPP);
}
@@ -41,7 +41,7 @@ fn test_ptrace_getevent() {
#[test]
#[cfg(any(target_os = "android", target_os = "linux"))]
fn test_ptrace_getsiginfo() {
- require_capability!(CAP_SYS_PTRACE);
+ require_capability!("test_ptrace_getsiginfo", CAP_SYS_PTRACE);
if let Err(Errno::EOPNOTSUPP) = ptrace::getsiginfo(getpid()) {
panic!("ptrace_getsiginfo returns Errno::EOPNOTSUPP!");
}
@@ -51,7 +51,7 @@ fn test_ptrace_getsiginfo() {
#[test]
#[cfg(any(target_os = "android", target_os = "linux"))]
fn test_ptrace_setsiginfo() {
- require_capability!(CAP_SYS_PTRACE);
+ require_capability!("test_ptrace_setsiginfo", CAP_SYS_PTRACE);
let siginfo = unsafe { mem::zeroed() };
if let Err(Errno::EOPNOTSUPP) = ptrace::setsiginfo(getpid(), &siginfo) {
panic!("ptrace_setsiginfo returns Errno::EOPNOTSUPP!");
@@ -67,7 +67,7 @@ fn test_ptrace_cont() {
use nix::unistd::fork;
use nix::unistd::ForkResult::*;
- require_capability!(CAP_SYS_PTRACE);
+ require_capability!("test_ptrace_cont", CAP_SYS_PTRACE);
let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
@@ -125,7 +125,7 @@ fn test_ptrace_interrupt() {
use std::thread::sleep;
use std::time::Duration;
- require_capability!(CAP_SYS_PTRACE);
+ require_capability!("test_ptrace_interrupt", CAP_SYS_PTRACE);
let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
@@ -171,7 +171,7 @@ fn test_ptrace_syscall() {
use nix::unistd::getpid;
use nix::unistd::ForkResult::*;
- require_capability!(CAP_SYS_PTRACE);
+ require_capability!("test_ptrace_syscall", CAP_SYS_PTRACE);
let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs
index 2e548c3d..6b998cb6 100644
--- a/test/sys/test_socket.rs
+++ b/test/sys/test_socket.rs
@@ -287,9 +287,9 @@ mod recvfrom {
use nix::sys::socket::sockopt::{UdpGroSegment, UdpGsoSegment};
#[test]
- // Disable the test on emulated platforms because it fails in Cirrus-CI. Lack of QEMU
- // support is suspected.
- #[cfg_attr(not(any(target_arch = "x86_64", target_arch="i686")), ignore)]
+ // Disable the test under emulation because it fails in Cirrus-CI. Lack
+ // of QEMU support is suspected.
+ #[cfg_attr(qemu, ignore)]
pub fn gso() {
require_kernel_version!(udp_offload::gso, ">= 4.18");
@@ -341,9 +341,9 @@ mod recvfrom {
}
#[test]
- // Disable the test on emulated platforms because it fails in Cirrus-CI. Lack of QEMU
- // support is suspected.
- #[cfg_attr(not(any(target_arch = "x86_64", target_arch="i686")), ignore)]
+ // Disable the test on emulated platforms because it fails in Cirrus-CI.
+ // Lack of QEMU support is suspected.
+ #[cfg_attr(qemu, ignore)]
pub fn gro() {
require_kernel_version!(udp_offload::gro, ">= 5.3");
@@ -582,7 +582,7 @@ pub fn test_recvmsg_ebadf() {
// Disable the test on emulated platforms due to a bug in QEMU versions <
// 2.12.0. https://bugs.launchpad.net/qemu/+bug/1701808
-#[cfg_attr(not(any(target_arch = "x86_64", target_arch="i686")), ignore)]
+#[cfg_attr(qemu, ignore)]
#[test]
pub fn test_scm_rights() {
use nix::sys::uio::IoVec;
@@ -636,8 +636,8 @@ pub fn test_scm_rights() {
}
// Disable the test on emulated platforms due to not enabled support of AF_ALG in QEMU from rust cross
-#[cfg_attr(not(any(target_arch = "x86_64", target_arch = "i686")), ignore)]
#[cfg(any(target_os = "linux", target_os= "android"))]
+#[cfg_attr(qemu, ignore)]
#[test]
pub fn test_af_alg_cipher() {
use libc;
@@ -704,12 +704,14 @@ pub fn test_af_alg_cipher() {
assert_eq!(decrypted, payload);
}
-// Disable the test on emulated platforms due to not enabled support of AF_ALG in QEMU from rust cross
-#[cfg_attr(not(any(target_arch = "x86_64", target_arch = "i686")), ignore)]
+// Disable the test on emulated platforms due to not enabled support of AF_ALG
+// in QEMU from rust cross
#[cfg(any(target_os = "linux", target_os= "android"))]
+#[cfg_attr(qemu, ignore)]
#[test]
pub fn test_af_alg_aead() {
use libc::{ALG_OP_DECRYPT, ALG_OP_ENCRYPT};
+ use nix::fcntl::{fcntl, FcntlArg, OFlag};
use nix::sys::uio::IoVec;
use nix::unistd::{read, close};
use nix::sys::socket::{socket, sendmsg, bind, accept, setsockopt,
@@ -788,6 +790,11 @@ pub fn test_af_alg_aead() {
// allocate buffer for decrypted data
let mut decrypted = vec![0u8; payload_len + (assoc_size as usize) + auth_size];
+ // Starting with kernel 4.9, the interface changed slightly such that the
+ // authentication tag memory is only needed in the output buffer for encryption
+ // and in the input buffer for decryption.
+ // Do not block on read, as we may have fewer bytes than buffer size
+ fcntl(session_socket,FcntlArg::F_SETFL(OFlag::O_NONBLOCK)).expect("fcntl non_blocking");
let num_bytes = read(session_socket, &mut decrypted).expect("read decrypt");
assert!(num_bytes >= payload_len + (assoc_size as usize));
@@ -909,7 +916,7 @@ pub fn test_sendmsg_ipv6packetinfo() {
/// Tests that passing multiple fds using a single `ControlMessage` works.
// Disable the test on emulated platforms due to a bug in QEMU versions <
// 2.12.0. https://bugs.launchpad.net/qemu/+bug/1701808
-#[cfg_attr(not(any(target_arch = "x86_64", target_arch="i686")), ignore)]
+#[cfg_attr(qemu, ignore)]
#[test]
fn test_scm_rights_single_cmsg_multiple_fds() {
use std::os::unix::net::UnixDatagram;
@@ -1056,9 +1063,9 @@ fn test_scm_credentials() {
/// Ensure that we can send `SCM_CREDENTIALS` and `SCM_RIGHTS` with a single
/// `sendmsg` call.
#[cfg(any(target_os = "android", target_os = "linux"))]
-// qemu's handling of multiple cmsgs is bugged, ignore tests on non-x86
+// qemu's handling of multiple cmsgs is bugged, ignore tests under emulation
// see https://bugs.launchpad.net/qemu/+bug/1781280
-#[cfg_attr(not(any(target_arch = "x86_64", target_arch = "x86")), ignore)]
+#[cfg_attr(qemu, ignore)]
#[test]
fn test_scm_credentials_and_rights() {
use libc;
@@ -1070,9 +1077,9 @@ fn test_scm_credentials_and_rights() {
/// Ensure that passing a an oversized control message buffer to recvmsg
/// still works.
#[cfg(any(target_os = "android", target_os = "linux"))]
-// qemu's handling of multiple cmsgs is bugged, ignore tests on non-x86
+// qemu's handling of multiple cmsgs is bugged, ignore tests under emulation
// see https://bugs.launchpad.net/qemu/+bug/1781280
-#[cfg_attr(not(any(target_arch = "x86_64", target_arch = "x86")), ignore)]
+#[cfg_attr(qemu, ignore)]
#[test]
fn test_too_large_cmsgspace() {
let space = vec![0u8; 1024];
@@ -1261,10 +1268,13 @@ fn loopback_address(family: AddressFamily) -> Option<nix::ifaddrs::InterfaceAddr
target_os = "netbsd",
))]
// qemu doesn't seem to be emulating this correctly in these architectures
-#[cfg_attr(any(
- target_arch = "mips",
- target_arch = "mips64",
- target_arch = "powerpc64",
+#[cfg_attr(all(
+ qemu,
+ any(
+ target_arch = "mips",
+ target_arch = "mips64",
+ target_arch = "powerpc64",
+ )
), ignore)]
#[test]
pub fn test_recv_ipv4pktinfo() {
@@ -1351,10 +1361,13 @@ pub fn test_recv_ipv4pktinfo() {
target_os = "openbsd",
))]
// qemu doesn't seem to be emulating this correctly in these architectures
-#[cfg_attr(any(
- target_arch = "mips",
- target_arch = "mips64",
- target_arch = "powerpc64",
+#[cfg_attr(all(
+ qemu,
+ any(
+ target_arch = "mips",
+ target_arch = "mips64",
+ target_arch = "powerpc64",
+ )
), ignore)]
#[test]
pub fn test_recvif() {
@@ -1462,10 +1475,13 @@ pub fn test_recvif() {
target_os = "openbsd",
))]
// qemu doesn't seem to be emulating this correctly in these architectures
-#[cfg_attr(any(
- target_arch = "mips",
- target_arch = "mips64",
- target_arch = "powerpc64",
+#[cfg_attr(all(
+ qemu,
+ any(
+ target_arch = "mips",
+ target_arch = "mips64",
+ target_arch = "powerpc64",
+ )
), ignore)]
#[test]
pub fn test_recv_ipv6pktinfo() {
@@ -1543,6 +1559,7 @@ pub fn test_recv_ipv6pktinfo() {
}
#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg_attr(graviton, ignore = "Not supported by the CI environment")]
#[test]
pub fn test_vsock() {
use libc;
@@ -1587,9 +1604,9 @@ pub fn test_vsock() {
thr.join().unwrap();
}
-// Disable the test on emulated platforms because it fails in Cirrus-CI. Lack of QEMU
-// support is suspected.
-#[cfg_attr(not(any(target_arch = "x86_64")), ignore)]
+// Disable the test on emulated platforms because it fails in Cirrus-CI. Lack
+// of QEMU support is suspected.
+#[cfg_attr(qemu, ignore)]
#[cfg(all(target_os = "linux"))]
#[test]
fn test_recvmsg_timestampns() {
@@ -1638,9 +1655,9 @@ fn test_recvmsg_timestampns() {
nix::unistd::close(in_socket).unwrap();
}
-// Disable the test on emulated platforms because it fails in Cirrus-CI. Lack of QEMU
-// support is suspected.
-#[cfg_attr(not(any(target_arch = "x86_64")), ignore)]
+// Disable the test on emulated platforms because it fails in Cirrus-CI. Lack
+// of QEMU support is suspected.
+#[cfg_attr(qemu, ignore)]
#[cfg(all(target_os = "linux"))]
#[test]
fn test_recvmmsg_timestampns() {
@@ -1695,9 +1712,9 @@ fn test_recvmmsg_timestampns() {
nix::unistd::close(in_socket).unwrap();
}
-// Disable the test on emulated platforms because it fails in Cirrus-CI. Lack of QEMU
-// support is suspected.
-#[cfg_attr(not(any(target_arch = "x86_64")), ignore)]
+// Disable the test on emulated platforms because it fails in Cirrus-CI. Lack
+// of QEMU support is suspected.
+#[cfg_attr(qemu, ignore)]
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
#[test]
fn test_recvmsg_rxq_ovfl() {
@@ -1777,3 +1794,160 @@ fn test_recvmsg_rxq_ovfl() {
nix::unistd::close(in_socket).unwrap();
nix::unistd::close(out_socket).unwrap();
}
+
+#[cfg(any(
+ target_os = "linux",
+ target_os = "android",
+))]
+mod linux_errqueue {
+ use nix::sys::socket::*;
+ use super::{FromStr, SocketAddr};
+
+ // Send a UDP datagram to a bogus destination address and observe an ICMP error (v4).
+ //
+ // Disable the test on QEMU because QEMU emulation of IP_RECVERR is broken (as documented on PR
+ // #1514).
+ #[cfg_attr(qemu, ignore)]
+ #[test]
+ fn test_recverr_v4() {
+ #[repr(u8)]
+ enum IcmpTypes {
+ DestUnreach = 3, // ICMP_DEST_UNREACH
+ }
+ #[repr(u8)]
+ enum IcmpUnreachCodes {
+ PortUnreach = 3, // ICMP_PORT_UNREACH
+ }
+
+ test_recverr_impl::<sockaddr_in, _, _>(
+ "127.0.0.1:6800",
+ AddressFamily::Inet,
+ sockopt::Ipv4RecvErr,
+ libc::SO_EE_ORIGIN_ICMP,
+ IcmpTypes::DestUnreach as u8,
+ IcmpUnreachCodes::PortUnreach as u8,
+ // Closure handles protocol-specific testing and returns generic sock_extended_err for
+ // protocol-independent test impl.
+ |cmsg| {
+ if let ControlMessageOwned::Ipv4RecvErr(ext_err, err_addr) = cmsg {
+ if let Some(origin) = err_addr {
+ // Validate that our network error originated from 127.0.0.1:0.
+ assert_eq!(origin.sin_family, AddressFamily::Inet as _);
+ assert_eq!(Ipv4Addr(origin.sin_addr), Ipv4Addr::new(127, 0, 0, 1));
+ assert_eq!(origin.sin_port, 0);
+ } else {
+ panic!("Expected some error origin");
+ }
+ return *ext_err
+ } else {
+ panic!("Unexpected control message {:?}", cmsg);
+ }
+ },
+ )
+ }
+
+ // Essentially the same test as v4.
+ //
+ // Disable the test on QEMU because QEMU emulation of IPV6_RECVERR is broken (as documented on
+ // PR #1514).
+ #[cfg_attr(qemu, ignore)]
+ #[test]
+ fn test_recverr_v6() {
+ #[repr(u8)]
+ enum IcmpV6Types {
+ DestUnreach = 1, // ICMPV6_DEST_UNREACH
+ }
+ #[repr(u8)]
+ enum IcmpV6UnreachCodes {
+ PortUnreach = 4, // ICMPV6_PORT_UNREACH
+ }
+
+ test_recverr_impl::<sockaddr_in6, _, _>(
+ "[::1]:6801",
+ AddressFamily::Inet6,
+ sockopt::Ipv6RecvErr,
+ libc::SO_EE_ORIGIN_ICMP6,
+ IcmpV6Types::DestUnreach as u8,
+ IcmpV6UnreachCodes::PortUnreach as u8,
+ // Closure handles protocol-specific testing and returns generic sock_extended_err for
+ // protocol-independent test impl.
+ |cmsg| {
+ if let ControlMessageOwned::Ipv6RecvErr(ext_err, err_addr) = cmsg {
+ if let Some(origin) = err_addr {
+ // Validate that our network error originated from localhost:0.
+ assert_eq!(origin.sin6_family, AddressFamily::Inet6 as _);
+ assert_eq!(
+ Ipv6Addr(origin.sin6_addr),
+ Ipv6Addr::from_std(&"::1".parse().unwrap()),
+ );
+ assert_eq!(origin.sin6_port, 0);
+ } else {
+ panic!("Expected some error origin");
+ }
+ return *ext_err
+ } else {
+ panic!("Unexpected control message {:?}", cmsg);
+ }
+ },
+ )
+ }
+
+ fn test_recverr_impl<SA, OPT, TESTF>(sa: &str,
+ af: AddressFamily,
+ opt: OPT,
+ ee_origin: u8,
+ ee_type: u8,
+ ee_code: u8,
+ testf: TESTF)
+ where
+ OPT: SetSockOpt<Val = bool>,
+ TESTF: FnOnce(&ControlMessageOwned) -> libc::sock_extended_err,
+ {
+ use nix::errno::Errno;
+ use nix::sys::uio::IoVec;
+
+ const MESSAGE_CONTENTS: &str = "ABCDEF";
+
+ let sock_addr = {
+ let std_sa = SocketAddr::from_str(sa).unwrap();
+ let inet_addr = InetAddr::from_std(&std_sa);
+ SockAddr::new_inet(inet_addr)
+ };
+ let sock = socket(af, SockType::Datagram, SockFlag::SOCK_CLOEXEC, None).unwrap();
+ setsockopt(sock, opt, &true).unwrap();
+ if let Err(e) = sendto(sock, MESSAGE_CONTENTS.as_bytes(), &sock_addr, MsgFlags::empty()) {
+ assert_eq!(e, Errno::EADDRNOTAVAIL);
+ println!("{:?} not available, skipping test.", af);
+ return;
+ }
+
+ let mut buf = [0u8; 8];
+ let iovec = [IoVec::from_mut_slice(&mut buf)];
+ let mut cspace = cmsg_space!(libc::sock_extended_err, SA);
+
+ let msg = recvmsg(sock, &iovec, Some(&mut cspace), MsgFlags::MSG_ERRQUEUE).unwrap();
+ // The sent message / destination associated with the error is returned:
+ assert_eq!(msg.bytes, MESSAGE_CONTENTS.as_bytes().len());
+ assert_eq!(&buf[..msg.bytes], MESSAGE_CONTENTS.as_bytes());
+ // recvmsg(2): "The original destination address of the datagram that caused the error is
+ // supplied via msg_name;" however, this is not literally true. E.g., an earlier version
+ // of this test used 0.0.0.0 (::0) as the destination address, which was mutated into
+ // 127.0.0.1 (::1).
+ assert_eq!(msg.address, Some(sock_addr));
+
+ // Check for expected control message.
+ let ext_err = match msg.cmsgs().next() {
+ Some(cmsg) => testf(&cmsg),
+ None => panic!("No control message"),
+ };
+
+ assert_eq!(ext_err.ee_errno, libc::ECONNREFUSED as u32);
+ assert_eq!(ext_err.ee_origin, ee_origin);
+ // ip(7): ee_type and ee_code are set from the type and code fields of the ICMP (ICMPv6)
+ // header.
+ assert_eq!(ext_err.ee_type, ee_type);
+ assert_eq!(ext_err.ee_code, ee_code);
+ // ip(7): ee_info contains the discovered MTU for EMSGSIZE errors.
+ assert_eq!(ext_err.ee_info, 0);
+ }
+}
diff --git a/test/sys/test_sockopt.rs b/test/sys/test_sockopt.rs
index 4d2d7e51..01920fd4 100644
--- a/test/sys/test_sockopt.rs
+++ b/test/sys/test_sockopt.rs
@@ -49,7 +49,7 @@ pub fn test_local_peercred_stream() {
fn is_so_mark_functional() {
use nix::sys::socket::sockopt;
- require_capability!(CAP_NET_ADMIN);
+ require_capability!("is_so_mark_functional", CAP_NET_ADMIN);
let s = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap();
setsockopt(s, sockopt::Mark, &1337).unwrap();
@@ -70,6 +70,57 @@ fn test_so_buf() {
assert!(actual >= bufsize);
}
+#[test]
+fn test_so_tcp_maxseg() {
+ use std::net::SocketAddr;
+ use std::str::FromStr;
+ use nix::sys::socket::{accept, bind, connect, listen, InetAddr, SockAddr};
+ use nix::unistd::{close, write};
+
+ let std_sa = SocketAddr::from_str("127.0.0.1:4001").unwrap();
+ let inet_addr = InetAddr::from_std(&std_sa);
+ let sock_addr = SockAddr::new_inet(inet_addr);
+
+ let rsock = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), SockProtocol::Tcp)
+ .unwrap();
+ bind(rsock, &sock_addr).unwrap();
+ listen(rsock, 10).unwrap();
+ let initial = getsockopt(rsock, sockopt::TcpMaxSeg).unwrap();
+ // Initial MSS is expected to be 536 (https://tools.ietf.org/html/rfc879#section-1) but some
+ // platforms keep it even lower. This might fail if you've tuned your initial MSS to be larger
+ // than 700
+ cfg_if! {
+ if #[cfg(any(target_os = "android", target_os = "linux"))] {
+ let segsize: u32 = 873;
+ assert!(initial < segsize);
+ setsockopt(rsock, sockopt::TcpMaxSeg, &segsize).unwrap();
+ } else {
+ assert!(initial < 700);
+ }
+ }
+
+ // Connect and check the MSS that was advertised
+ let ssock = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), SockProtocol::Tcp)
+ .unwrap();
+ connect(ssock, &sock_addr).unwrap();
+ let rsess = accept(rsock).unwrap();
+ write(rsess, b"hello").unwrap();
+ let actual = getsockopt(ssock, sockopt::TcpMaxSeg).unwrap();
+ // Actual max segment size takes header lengths into account, max IPv4 options (60 bytes) + max
+ // TCP options (40 bytes) are subtracted from the requested maximum as a lower boundary.
+ cfg_if! {
+ if #[cfg(any(target_os = "android", target_os = "linux"))] {
+ assert!((segsize - 100) <= actual);
+ assert!(actual <= segsize);
+ } else {
+ assert!(initial < actual);
+ assert!(536 < actual);
+ }
+ }
+ close(rsock).unwrap();
+ close(ssock).unwrap();
+}
+
// The CI doesn't supported getsockopt and setsockopt on emulated processors.
// It's beleived that a QEMU issue, the tests run ok on a fully emulated system.
// Current CI just run the binary with QEMU but the Kernel remains the same as the host.
@@ -135,3 +186,14 @@ fn test_so_tcp_keepalive() {
assert_eq!(getsockopt(fd, sockopt::TcpKeepInterval).unwrap(), x + 1);
}
}
+
+#[test]
+#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
+fn test_ttl_opts() {
+ let fd4 = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), None).unwrap();
+ setsockopt(fd4, sockopt::Ipv4Ttl, &1)
+ .expect("setting ipv4ttl on an inet socket should succeed");
+ let fd6 = socket(AddressFamily::Inet6, SockType::Datagram, SockFlag::empty(), None).unwrap();
+ setsockopt(fd6, sockopt::Ipv6Ttl, &1)
+ .expect("setting ipv6ttl on an inet6 socket should succeed");
+}
diff --git a/test/sys/test_uio.rs b/test/sys/test_uio.rs
index 9dd4f01d..8f8ba5e4 100644
--- a/test/sys/test_uio.rs
+++ b/test/sys/test_uio.rs
@@ -205,15 +205,15 @@ fn test_preadv() {
#[test]
#[cfg(target_os = "linux")]
-// FIXME: qemu-user doesn't implement process_vm_readv/writev on most arches
-#[cfg_attr(not(any(target_arch = "x86", target_arch = "x86_64")), ignore)]
+// qemu-user doesn't implement process_vm_readv/writev on most arches
+#[cfg_attr(qemu, ignore)]
fn test_process_vm_readv() {
use nix::unistd::ForkResult::*;
use nix::sys::signal::*;
use nix::sys::wait::*;
use crate::*;
- require_capability!(CAP_SYS_PTRACE);
+ require_capability!("test_process_vm_readv", CAP_SYS_PTRACE);
let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
// Pre-allocate memory in the child, since allocation isn't safe
diff --git a/test/sys/test_wait.rs b/test/sys/test_wait.rs
index 2d26fb8e..4a5b9661 100644
--- a/test/sys/test_wait.rs
+++ b/test/sys/test_wait.rs
@@ -96,7 +96,7 @@ mod ptrace {
#[test]
fn test_wait_ptrace() {
- require_capability!(CAP_SYS_PTRACE);
+ require_capability!("test_wait_ptrace", CAP_SYS_PTRACE);
let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
match unsafe{fork()}.expect("Error: Fork Failed") {
diff --git a/test/test_fcntl.rs b/test/test_fcntl.rs
index e74a8598..c19a1b0a 100644
--- a/test/test_fcntl.rs
+++ b/test/test_fcntl.rs
@@ -236,14 +236,8 @@ mod linux_android {
/// The from_offset should be updated by the call to reflect
/// the 3 bytes read (6).
#[test]
- // QEMU does not support copy_file_range. Skip platforms that use QEMU in CI
- #[cfg_attr(all(target_os = "linux", any(
- target_arch = "aarch64",
- target_arch = "arm",
- target_arch = "mips",
- target_arch = "mips64",
- target_arch = "powerpc64"
- )), ignore)]
+ // QEMU does not support copy_file_range. Skip under qemu
+ #[cfg_attr(qemu, ignore)]
fn test_copy_file_range() {
const CONTENTS: &[u8] = b"foobarbaz";
diff --git a/test/test_kmod/mod.rs b/test/test_kmod/mod.rs
index 76263305..e53e7a9e 100644
--- a/test/test_kmod/mod.rs
+++ b/test/test_kmod/mod.rs
@@ -41,7 +41,7 @@ use std::io::Read;
#[test]
fn test_finit_and_delete_module() {
- require_capability!(CAP_SYS_MODULE);
+ require_capability!("test_finit_and_delete_module", CAP_SYS_MODULE);
let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
@@ -58,8 +58,8 @@ fn test_finit_and_delete_module() {
}
#[test]
-fn test_finit_and_delete_modul_with_params() {
- require_capability!(CAP_SYS_MODULE);
+fn test_finit_and_delete_module_with_params() {
+ require_capability!("test_finit_and_delete_module_with_params", CAP_SYS_MODULE);
let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
@@ -80,7 +80,7 @@ fn test_finit_and_delete_modul_with_params() {
#[test]
fn test_init_and_delete_module() {
- require_capability!(CAP_SYS_MODULE);
+ require_capability!("test_init_and_delete_module", CAP_SYS_MODULE);
let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
@@ -100,7 +100,7 @@ fn test_init_and_delete_module() {
#[test]
fn test_init_and_delete_module_with_params() {
- require_capability!(CAP_SYS_MODULE);
+ require_capability!("test_init_and_delete_module_with_params", CAP_SYS_MODULE);
let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
@@ -121,7 +121,7 @@ fn test_init_and_delete_module_with_params() {
#[test]
fn test_finit_module_invalid() {
- require_capability!(CAP_SYS_MODULE);
+ require_capability!("test_finit_module_invalid", CAP_SYS_MODULE);
let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
@@ -135,7 +135,7 @@ fn test_finit_module_invalid() {
#[test]
fn test_finit_module_twice_and_delete_module() {
- require_capability!(CAP_SYS_MODULE);
+ require_capability!("test_finit_module_twice_and_delete_module", CAP_SYS_MODULE);
let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
@@ -157,7 +157,7 @@ fn test_finit_module_twice_and_delete_module() {
#[test]
fn test_delete_module_not_loaded() {
- require_capability!(CAP_SYS_MODULE);
+ require_capability!("test_delete_module_not_loaded", CAP_SYS_MODULE);
let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
diff --git a/test/test_mq.rs b/test/test_mq.rs
index d0826923..430df5dd 100644
--- a/test/test_mq.rs
+++ b/test/test_mq.rs
@@ -60,7 +60,11 @@ fn test_mq_getattr() {
// FIXME: Fix failures for mips in QEMU
#[test]
#[cfg(not(any(target_os = "netbsd")))]
-#[cfg_attr(any(target_arch = "mips", target_arch = "mips64"), ignore)]
+#[cfg_attr(all(
+ qemu,
+ any(target_arch = "mips", target_arch = "mips64")
+ ), ignore
+)]
fn test_mq_setattr() {
use nix::mqueue::{mq_getattr, mq_setattr};
const MSG_SIZE: mq_attr_member_t = 32;
@@ -97,7 +101,11 @@ fn test_mq_setattr() {
// FIXME: Fix failures for mips in QEMU
#[test]
#[cfg(not(any(target_os = "netbsd")))]
-#[cfg_attr(any(target_arch = "mips", target_arch = "mips64"), ignore)]
+#[cfg_attr(all(
+ qemu,
+ any(target_arch = "mips", target_arch = "mips64")
+ ), ignore
+)]
fn test_mq_set_nonblocking() {
use nix::mqueue::{mq_getattr, mq_set_nonblock, mq_remove_nonblock};
const MSG_SIZE: mq_attr_member_t = 32;
diff --git a/test/test_poll.rs b/test/test_poll.rs
index 0395512b..ee89c4a0 100644
--- a/test/test_poll.rs
+++ b/test/test_poll.rs
@@ -64,3 +64,11 @@ fn test_ppoll() {
assert_eq!(nfds, 1);
assert!(fds[0].revents().unwrap().contains(PollFlags::POLLIN));
}
+
+#[test]
+fn test_pollfd_fd() {
+ use std::os::unix::io::AsRawFd;
+
+ let pfd = PollFd::new(0x1234, PollFlags::empty());
+ assert_eq!(pfd.as_raw_fd(), 0x1234);
+}
diff --git a/test/test_unistd.rs b/test/test_unistd.rs
index 37e7a9b3..cb23ba75 100644
--- a/test/test_unistd.rs
+++ b/test/test_unistd.rs
@@ -549,7 +549,7 @@ cfg_if!{
if #[cfg(any(target_os = "android", target_os = "linux"))] {
macro_rules! require_acct{
() => {
- require_capability!(CAP_SYS_PACCT);
+ require_capability!("test_acct", CAP_SYS_PACCT);
}
}
} else if #[cfg(target_os = "freebsd")] {
@@ -1040,7 +1040,7 @@ fn test_user_into_passwd() {
fn test_setfsuid() {
use std::os::unix::fs::PermissionsExt;
use std::{fs, io, thread};
- require_capability!(CAP_SETUID);
+ require_capability!("test_setfsuid", CAP_SETUID);
// get the UID of the "nobody" user
let nobody = User::from_name("nobody").unwrap().unwrap();