Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
47
third-party/vendor/nix-0.24.3/test/sys/mod.rs
vendored
Normal file
47
third-party/vendor/nix-0.24.3/test/sys/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
mod test_signal;
|
||||
|
||||
// NOTE: DragonFly lacks a kernel-level implementation of Posix AIO as of
|
||||
// this writing. There is an user-level implementation, but whether aio
|
||||
// works or not heavily depends on which pthread implementation is chosen
|
||||
// by the user at link time. For this reason we do not want to run aio test
|
||||
// cases on DragonFly.
|
||||
#[cfg(any(target_os = "freebsd",
|
||||
target_os = "ios",
|
||||
all(target_os = "linux", not(target_env = "uclibc")),
|
||||
target_os = "macos",
|
||||
target_os = "netbsd"))]
|
||||
mod test_aio;
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
mod test_mman;
|
||||
#[cfg(target_os = "linux")]
|
||||
mod test_signalfd;
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
mod test_socket;
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
mod test_sockopt;
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
mod test_select;
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
mod test_sysinfo;
|
||||
#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
|
||||
mod test_termios;
|
||||
#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
|
||||
mod test_ioctl;
|
||||
mod test_wait;
|
||||
mod test_uio;
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
mod test_epoll;
|
||||
#[cfg(target_os = "linux")]
|
||||
mod test_inotify;
|
||||
mod test_pthread;
|
||||
#[cfg(any(target_os = "android",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "linux",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd"))]
|
||||
mod test_ptrace;
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
mod test_timerfd;
|
||||
620
third-party/vendor/nix-0.24.3/test/sys/test_aio.rs
vendored
Normal file
620
third-party/vendor/nix-0.24.3/test/sys/test_aio.rs
vendored
Normal file
|
|
@ -0,0 +1,620 @@
|
|||
use libc::{c_int, c_void};
|
||||
use nix::Result;
|
||||
use nix::errno::*;
|
||||
use nix::sys::aio::*;
|
||||
use nix::sys::signal::{SaFlags, SigAction, sigaction, SigevNotify, SigHandler, Signal, SigSet};
|
||||
use nix::sys::time::{TimeSpec, TimeValLike};
|
||||
use std::io::{Write, Read, Seek, SeekFrom};
|
||||
use std::ops::Deref;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::pin::Pin;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::{thread, time};
|
||||
use tempfile::tempfile;
|
||||
|
||||
// Helper that polls an AioCb for completion or error
|
||||
fn poll_aio(aiocb: &mut Pin<Box<AioCb>>) -> Result<()> {
|
||||
loop {
|
||||
let err = aiocb.error();
|
||||
if err != Err(Errno::EINPROGRESS) { return err; };
|
||||
thread::sleep(time::Duration::from_millis(10));
|
||||
}
|
||||
}
|
||||
|
||||
// Helper that polls a component of an LioCb for completion or error
|
||||
#[cfg(not(any(target_os = "ios", target_os = "macos")))]
|
||||
fn poll_lio(liocb: &mut LioCb, i: usize) -> Result<()> {
|
||||
loop {
|
||||
let err = liocb.error(i);
|
||||
if err != Err(Errno::EINPROGRESS) { return err; };
|
||||
thread::sleep(time::Duration::from_millis(10));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_accessors() {
|
||||
let mut rbuf = vec![0; 4];
|
||||
let aiocb = AioCb::from_mut_slice( 1001,
|
||||
2, //offset
|
||||
&mut rbuf,
|
||||
42, //priority
|
||||
SigevNotify::SigevSignal {
|
||||
signal: Signal::SIGUSR2,
|
||||
si_value: 99
|
||||
},
|
||||
LioOpcode::LIO_NOP);
|
||||
assert_eq!(1001, aiocb.fd());
|
||||
assert_eq!(Some(LioOpcode::LIO_NOP), aiocb.lio_opcode());
|
||||
assert_eq!(4, aiocb.nbytes());
|
||||
assert_eq!(2, aiocb.offset());
|
||||
assert_eq!(42, aiocb.priority());
|
||||
let sev = aiocb.sigevent().sigevent();
|
||||
assert_eq!(Signal::SIGUSR2 as i32, sev.sigev_signo);
|
||||
assert_eq!(99, sev.sigev_value.sival_ptr as i64);
|
||||
}
|
||||
|
||||
// Tests AioCb.cancel. We aren't trying to test the OS's implementation, only
|
||||
// our bindings. So it's sufficient to check that AioCb.cancel returned any
|
||||
// AioCancelStat value.
|
||||
#[test]
|
||||
#[cfg_attr(target_env = "musl", ignore)]
|
||||
fn test_cancel() {
|
||||
let wbuf: &[u8] = b"CDEF";
|
||||
|
||||
let f = tempfile().unwrap();
|
||||
let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
|
||||
0, //offset
|
||||
wbuf,
|
||||
0, //priority
|
||||
SigevNotify::SigevNone,
|
||||
LioOpcode::LIO_NOP);
|
||||
aiocb.write().unwrap();
|
||||
let err = aiocb.error();
|
||||
assert!(err == Ok(()) || err == Err(Errno::EINPROGRESS));
|
||||
|
||||
let cancelstat = aiocb.cancel();
|
||||
assert!(cancelstat.is_ok());
|
||||
|
||||
// Wait for aiocb to complete, but don't care whether it succeeded
|
||||
let _ = poll_aio(&mut aiocb);
|
||||
let _ = aiocb.aio_return();
|
||||
}
|
||||
|
||||
// Tests using aio_cancel_all for all outstanding IOs.
|
||||
#[test]
|
||||
#[cfg_attr(target_env = "musl", ignore)]
|
||||
fn test_aio_cancel_all() {
|
||||
let wbuf: &[u8] = b"CDEF";
|
||||
|
||||
let f = tempfile().unwrap();
|
||||
let mut aiocb = AioCb::from_slice(f.as_raw_fd(),
|
||||
0, //offset
|
||||
wbuf,
|
||||
0, //priority
|
||||
SigevNotify::SigevNone,
|
||||
LioOpcode::LIO_NOP);
|
||||
aiocb.write().unwrap();
|
||||
let err = aiocb.error();
|
||||
assert!(err == Ok(()) || err == Err(Errno::EINPROGRESS));
|
||||
|
||||
let cancelstat = aio_cancel_all(f.as_raw_fd());
|
||||
assert!(cancelstat.is_ok());
|
||||
|
||||
// Wait for aiocb to complete, but don't care whether it succeeded
|
||||
let _ = poll_aio(&mut aiocb);
|
||||
let _ = aiocb.aio_return();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
|
||||
fn test_fsync() {
|
||||
const INITIAL: &[u8] = b"abcdef123456";
|
||||
let mut f = tempfile().unwrap();
|
||||
f.write_all(INITIAL).unwrap();
|
||||
let mut aiocb = AioCb::from_fd( f.as_raw_fd(),
|
||||
0, //priority
|
||||
SigevNotify::SigevNone);
|
||||
let err = aiocb.fsync(AioFsyncMode::O_SYNC);
|
||||
assert!(err.is_ok());
|
||||
poll_aio(&mut aiocb).unwrap();
|
||||
aiocb.aio_return().unwrap();
|
||||
}
|
||||
|
||||
/// `AioCb::fsync` should not modify the `AioCb` object if `libc::aio_fsync` returns
|
||||
/// an error
|
||||
// Skip on Linux, because Linux's AIO implementation can't detect errors
|
||||
// synchronously
|
||||
#[test]
|
||||
#[cfg(any(target_os = "freebsd", target_os = "macos"))]
|
||||
fn test_fsync_error() {
|
||||
use std::mem;
|
||||
|
||||
const INITIAL: &[u8] = b"abcdef123456";
|
||||
// Create an invalid AioFsyncMode
|
||||
let mode = unsafe { mem::transmute(666) };
|
||||
let mut f = tempfile().unwrap();
|
||||
f.write_all(INITIAL).unwrap();
|
||||
let mut aiocb = AioCb::from_fd( f.as_raw_fd(),
|
||||
0, //priority
|
||||
SigevNotify::SigevNone);
|
||||
let err = aiocb.fsync(mode);
|
||||
assert!(err.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
// On Cirrus on Linux, this test fails due to a glibc bug.
|
||||
// https://github.com/nix-rust/nix/issues/1099
|
||||
#[cfg_attr(target_os = "linux", ignore)]
|
||||
// On Cirrus, aio_suspend is failing with EINVAL
|
||||
// https://github.com/nix-rust/nix/issues/1361
|
||||
#[cfg_attr(target_os = "macos", ignore)]
|
||||
fn test_aio_suspend() {
|
||||
const INITIAL: &[u8] = b"abcdef123456";
|
||||
const WBUF: &[u8] = b"CDEFG";
|
||||
let timeout = TimeSpec::seconds(10);
|
||||
let mut rbuf = vec![0; 4];
|
||||
let rlen = rbuf.len();
|
||||
let mut f = tempfile().unwrap();
|
||||
f.write_all(INITIAL).unwrap();
|
||||
|
||||
let mut wcb = AioCb::from_slice( f.as_raw_fd(),
|
||||
2, //offset
|
||||
WBUF,
|
||||
0, //priority
|
||||
SigevNotify::SigevNone,
|
||||
LioOpcode::LIO_WRITE);
|
||||
|
||||
let mut rcb = AioCb::from_mut_slice( f.as_raw_fd(),
|
||||
8, //offset
|
||||
&mut rbuf,
|
||||
0, //priority
|
||||
SigevNotify::SigevNone,
|
||||
LioOpcode::LIO_READ);
|
||||
wcb.write().unwrap();
|
||||
rcb.read().unwrap();
|
||||
loop {
|
||||
{
|
||||
let cbbuf = [wcb.as_ref(), rcb.as_ref()];
|
||||
let r = aio_suspend(&cbbuf[..], Some(timeout));
|
||||
match r {
|
||||
Err(Errno::EINTR) => continue,
|
||||
Err(e) => panic!("aio_suspend returned {:?}", e),
|
||||
Ok(_) => ()
|
||||
};
|
||||
}
|
||||
if rcb.error() != Err(Errno::EINPROGRESS) &&
|
||||
wcb.error() != Err(Errno::EINPROGRESS) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(wcb.aio_return().unwrap() as usize, WBUF.len());
|
||||
assert_eq!(rcb.aio_return().unwrap() as usize, rlen);
|
||||
}
|
||||
|
||||
// Test a simple aio operation with no completion notification. We must poll
|
||||
// for completion
|
||||
#[test]
|
||||
#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
|
||||
fn test_read() {
|
||||
const INITIAL: &[u8] = b"abcdef123456";
|
||||
let mut rbuf = vec![0; 4];
|
||||
const EXPECT: &[u8] = b"cdef";
|
||||
let mut f = tempfile().unwrap();
|
||||
f.write_all(INITIAL).unwrap();
|
||||
{
|
||||
let mut aiocb = AioCb::from_mut_slice( f.as_raw_fd(),
|
||||
2, //offset
|
||||
&mut rbuf,
|
||||
0, //priority
|
||||
SigevNotify::SigevNone,
|
||||
LioOpcode::LIO_NOP);
|
||||
aiocb.read().unwrap();
|
||||
|
||||
let err = poll_aio(&mut aiocb);
|
||||
assert_eq!(err, Ok(()));
|
||||
assert_eq!(aiocb.aio_return().unwrap() as usize, EXPECT.len());
|
||||
}
|
||||
|
||||
assert_eq!(EXPECT, rbuf.deref().deref());
|
||||
}
|
||||
|
||||
/// `AioCb::read` should not modify the `AioCb` object if `libc::aio_read`
|
||||
/// returns an error
|
||||
// Skip on Linux, because Linux's AIO implementation can't detect errors
|
||||
// synchronously
|
||||
#[test]
|
||||
#[cfg(any(target_os = "freebsd", target_os = "macos"))]
|
||||
fn test_read_error() {
|
||||
const INITIAL: &[u8] = b"abcdef123456";
|
||||
let mut rbuf = vec![0; 4];
|
||||
let mut f = tempfile().unwrap();
|
||||
f.write_all(INITIAL).unwrap();
|
||||
let mut aiocb = AioCb::from_mut_slice( f.as_raw_fd(),
|
||||
-1, //an invalid offset
|
||||
&mut rbuf,
|
||||
0, //priority
|
||||
SigevNotify::SigevNone,
|
||||
LioOpcode::LIO_NOP);
|
||||
assert!(aiocb.read().is_err());
|
||||
}
|
||||
|
||||
// Tests from_mut_slice
|
||||
#[test]
|
||||
#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
|
||||
fn test_read_into_mut_slice() {
|
||||
const INITIAL: &[u8] = b"abcdef123456";
|
||||
let mut rbuf = vec![0; 4];
|
||||
const EXPECT: &[u8] = b"cdef";
|
||||
let mut f = tempfile().unwrap();
|
||||
f.write_all(INITIAL).unwrap();
|
||||
{
|
||||
let mut aiocb = AioCb::from_mut_slice( f.as_raw_fd(),
|
||||
2, //offset
|
||||
&mut rbuf,
|
||||
0, //priority
|
||||
SigevNotify::SigevNone,
|
||||
LioOpcode::LIO_NOP);
|
||||
aiocb.read().unwrap();
|
||||
|
||||
let err = poll_aio(&mut aiocb);
|
||||
assert_eq!(err, Ok(()));
|
||||
assert_eq!(aiocb.aio_return().unwrap() as usize, EXPECT.len());
|
||||
}
|
||||
|
||||
assert_eq!(rbuf, EXPECT);
|
||||
}
|
||||
|
||||
// Tests from_ptr
|
||||
#[test]
|
||||
#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
|
||||
fn test_read_into_pointer() {
|
||||
const INITIAL: &[u8] = b"abcdef123456";
|
||||
let mut rbuf = vec![0; 4];
|
||||
const EXPECT: &[u8] = b"cdef";
|
||||
let mut f = tempfile().unwrap();
|
||||
f.write_all(INITIAL).unwrap();
|
||||
{
|
||||
// Safety: ok because rbuf lives until after poll_aio
|
||||
let mut aiocb = unsafe {
|
||||
AioCb::from_mut_ptr( f.as_raw_fd(),
|
||||
2, //offset
|
||||
rbuf.as_mut_ptr() as *mut c_void,
|
||||
rbuf.len(),
|
||||
0, //priority
|
||||
SigevNotify::SigevNone,
|
||||
LioOpcode::LIO_NOP)
|
||||
};
|
||||
aiocb.read().unwrap();
|
||||
|
||||
let err = poll_aio(&mut aiocb);
|
||||
assert_eq!(err, Ok(()));
|
||||
assert_eq!(aiocb.aio_return().unwrap() as usize, EXPECT.len());
|
||||
}
|
||||
|
||||
assert_eq!(rbuf, EXPECT);
|
||||
}
|
||||
|
||||
// Test reading into an immutable buffer. It should fail
|
||||
// FIXME: This test fails to panic on Linux/musl
|
||||
#[test]
|
||||
#[should_panic(expected = "Can't read into an immutable buffer")]
|
||||
#[cfg_attr(target_env = "musl", ignore)]
|
||||
fn test_read_immutable_buffer() {
|
||||
let rbuf: &[u8] = b"CDEF";
|
||||
let f = tempfile().unwrap();
|
||||
let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
|
||||
2, //offset
|
||||
rbuf,
|
||||
0, //priority
|
||||
SigevNotify::SigevNone,
|
||||
LioOpcode::LIO_NOP);
|
||||
aiocb.read().unwrap();
|
||||
}
|
||||
|
||||
|
||||
// Test a simple aio operation with no completion notification. We must poll
|
||||
// for completion. Unlike test_aio_read, this test uses AioCb::from_slice
|
||||
#[test]
|
||||
#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
|
||||
fn test_write() {
|
||||
const INITIAL: &[u8] = b"abcdef123456";
|
||||
let wbuf = "CDEF".to_string().into_bytes();
|
||||
let mut rbuf = Vec::new();
|
||||
const EXPECT: &[u8] = b"abCDEF123456";
|
||||
|
||||
let mut f = tempfile().unwrap();
|
||||
f.write_all(INITIAL).unwrap();
|
||||
let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
|
||||
2, //offset
|
||||
&wbuf,
|
||||
0, //priority
|
||||
SigevNotify::SigevNone,
|
||||
LioOpcode::LIO_NOP);
|
||||
aiocb.write().unwrap();
|
||||
|
||||
let err = poll_aio(&mut aiocb);
|
||||
assert_eq!(err, Ok(()));
|
||||
assert_eq!(aiocb.aio_return().unwrap() as usize, wbuf.len());
|
||||
|
||||
f.seek(SeekFrom::Start(0)).unwrap();
|
||||
let len = f.read_to_end(&mut rbuf).unwrap();
|
||||
assert_eq!(len, EXPECT.len());
|
||||
assert_eq!(rbuf, EXPECT);
|
||||
}
|
||||
|
||||
// Tests `AioCb::from_ptr`
|
||||
#[test]
|
||||
#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
|
||||
fn test_write_from_pointer() {
|
||||
const INITIAL: &[u8] = b"abcdef123456";
|
||||
let wbuf = "CDEF".to_string().into_bytes();
|
||||
let mut rbuf = Vec::new();
|
||||
const EXPECT: &[u8] = b"abCDEF123456";
|
||||
|
||||
let mut f = tempfile().unwrap();
|
||||
f.write_all(INITIAL).unwrap();
|
||||
// Safety: ok because aiocb outlives poll_aio
|
||||
let mut aiocb = unsafe {
|
||||
AioCb::from_ptr( f.as_raw_fd(),
|
||||
2, //offset
|
||||
wbuf.as_ptr() as *const c_void,
|
||||
wbuf.len(),
|
||||
0, //priority
|
||||
SigevNotify::SigevNone,
|
||||
LioOpcode::LIO_NOP)
|
||||
};
|
||||
aiocb.write().unwrap();
|
||||
|
||||
let err = poll_aio(&mut aiocb);
|
||||
assert_eq!(err, Ok(()));
|
||||
assert_eq!(aiocb.aio_return().unwrap() as usize, wbuf.len());
|
||||
|
||||
f.seek(SeekFrom::Start(0)).unwrap();
|
||||
let len = f.read_to_end(&mut rbuf).unwrap();
|
||||
assert_eq!(len, EXPECT.len());
|
||||
assert_eq!(rbuf, EXPECT);
|
||||
}
|
||||
|
||||
/// `AioCb::write` should not modify the `AioCb` object if `libc::aio_write`
|
||||
/// returns an error
|
||||
// Skip on Linux, because Linux's AIO implementation can't detect errors
|
||||
// synchronously
|
||||
#[test]
|
||||
#[cfg(any(target_os = "freebsd", target_os = "macos"))]
|
||||
fn test_write_error() {
|
||||
let wbuf = "CDEF".to_string().into_bytes();
|
||||
let mut aiocb = AioCb::from_slice( 666, // An invalid file descriptor
|
||||
0, //offset
|
||||
&wbuf,
|
||||
0, //priority
|
||||
SigevNotify::SigevNone,
|
||||
LioOpcode::LIO_NOP);
|
||||
assert!(aiocb.write().is_err());
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref SIGNALED: AtomicBool = AtomicBool::new(false);
|
||||
}
|
||||
|
||||
extern fn sigfunc(_: c_int) {
|
||||
SIGNALED.store(true, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
// Test an aio operation with completion delivered by a signal
|
||||
// FIXME: This test is ignored on mips because of failures in qemu in CI
|
||||
#[test]
|
||||
#[cfg_attr(any(all(target_env = "musl", target_arch = "x86_64"), target_arch = "mips", target_arch = "mips64"), ignore)]
|
||||
fn test_write_sigev_signal() {
|
||||
let _m = crate::SIGNAL_MTX.lock();
|
||||
let sa = SigAction::new(SigHandler::Handler(sigfunc),
|
||||
SaFlags::SA_RESETHAND,
|
||||
SigSet::empty());
|
||||
SIGNALED.store(false, Ordering::Relaxed);
|
||||
unsafe { sigaction(Signal::SIGUSR2, &sa) }.unwrap();
|
||||
|
||||
const INITIAL: &[u8] = b"abcdef123456";
|
||||
const WBUF: &[u8] = b"CDEF";
|
||||
let mut rbuf = Vec::new();
|
||||
const EXPECT: &[u8] = b"abCDEF123456";
|
||||
|
||||
let mut f = tempfile().unwrap();
|
||||
f.write_all(INITIAL).unwrap();
|
||||
let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
|
||||
2, //offset
|
||||
WBUF,
|
||||
0, //priority
|
||||
SigevNotify::SigevSignal {
|
||||
signal: Signal::SIGUSR2,
|
||||
si_value: 0 //TODO: validate in sigfunc
|
||||
},
|
||||
LioOpcode::LIO_NOP);
|
||||
aiocb.write().unwrap();
|
||||
while !SIGNALED.load(Ordering::Relaxed) {
|
||||
thread::sleep(time::Duration::from_millis(10));
|
||||
}
|
||||
|
||||
assert_eq!(aiocb.aio_return().unwrap() as usize, WBUF.len());
|
||||
f.seek(SeekFrom::Start(0)).unwrap();
|
||||
let len = f.read_to_end(&mut rbuf).unwrap();
|
||||
assert_eq!(len, EXPECT.len());
|
||||
assert_eq!(rbuf, EXPECT);
|
||||
}
|
||||
|
||||
// Test LioCb::listio with LIO_WAIT, so all AIO ops should be complete by the
|
||||
// time listio returns.
|
||||
#[test]
|
||||
#[cfg(not(any(target_os = "ios", target_os = "macos")))]
|
||||
#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
|
||||
fn test_liocb_listio_wait() {
|
||||
const INITIAL: &[u8] = b"abcdef123456";
|
||||
const WBUF: &[u8] = b"CDEF";
|
||||
let mut rbuf = vec![0; 4];
|
||||
let rlen = rbuf.len();
|
||||
let mut rbuf2 = Vec::new();
|
||||
const EXPECT: &[u8] = b"abCDEF123456";
|
||||
let mut f = tempfile().unwrap();
|
||||
|
||||
f.write_all(INITIAL).unwrap();
|
||||
|
||||
{
|
||||
let mut liocb = LioCbBuilder::with_capacity(2)
|
||||
.emplace_slice(
|
||||
f.as_raw_fd(),
|
||||
2, //offset
|
||||
WBUF,
|
||||
0, //priority
|
||||
SigevNotify::SigevNone,
|
||||
LioOpcode::LIO_WRITE
|
||||
).emplace_mut_slice(
|
||||
f.as_raw_fd(),
|
||||
8, //offset
|
||||
&mut rbuf,
|
||||
0, //priority
|
||||
SigevNotify::SigevNone,
|
||||
LioOpcode::LIO_READ
|
||||
).finish();
|
||||
let err = liocb.listio(LioMode::LIO_WAIT, SigevNotify::SigevNone);
|
||||
err.expect("lio_listio");
|
||||
|
||||
assert_eq!(liocb.aio_return(0).unwrap() as usize, WBUF.len());
|
||||
assert_eq!(liocb.aio_return(1).unwrap() as usize, rlen);
|
||||
}
|
||||
assert_eq!(rbuf.deref().deref(), b"3456");
|
||||
|
||||
f.seek(SeekFrom::Start(0)).unwrap();
|
||||
let len = f.read_to_end(&mut rbuf2).unwrap();
|
||||
assert_eq!(len, EXPECT.len());
|
||||
assert_eq!(rbuf2, EXPECT);
|
||||
}
|
||||
|
||||
// Test LioCb::listio with LIO_NOWAIT and no SigEvent, so we must use some other
|
||||
// mechanism to check for the individual AioCb's completion.
|
||||
#[test]
|
||||
#[cfg(not(any(target_os = "ios", target_os = "macos")))]
|
||||
#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
|
||||
fn test_liocb_listio_nowait() {
|
||||
const INITIAL: &[u8] = b"abcdef123456";
|
||||
const WBUF: &[u8] = b"CDEF";
|
||||
let mut rbuf = vec![0; 4];
|
||||
let rlen = rbuf.len();
|
||||
let mut rbuf2 = Vec::new();
|
||||
const EXPECT: &[u8] = b"abCDEF123456";
|
||||
let mut f = tempfile().unwrap();
|
||||
|
||||
f.write_all(INITIAL).unwrap();
|
||||
|
||||
{
|
||||
let mut liocb = LioCbBuilder::with_capacity(2)
|
||||
.emplace_slice(
|
||||
f.as_raw_fd(),
|
||||
2, //offset
|
||||
WBUF,
|
||||
0, //priority
|
||||
SigevNotify::SigevNone,
|
||||
LioOpcode::LIO_WRITE
|
||||
).emplace_mut_slice(
|
||||
f.as_raw_fd(),
|
||||
8, //offset
|
||||
&mut rbuf,
|
||||
0, //priority
|
||||
SigevNotify::SigevNone,
|
||||
LioOpcode::LIO_READ
|
||||
).finish();
|
||||
let err = liocb.listio(LioMode::LIO_NOWAIT, SigevNotify::SigevNone);
|
||||
err.expect("lio_listio");
|
||||
|
||||
poll_lio(&mut liocb, 0).unwrap();
|
||||
poll_lio(&mut liocb, 1).unwrap();
|
||||
assert_eq!(liocb.aio_return(0).unwrap() as usize, WBUF.len());
|
||||
assert_eq!(liocb.aio_return(1).unwrap() as usize, rlen);
|
||||
}
|
||||
assert_eq!(rbuf.deref().deref(), b"3456");
|
||||
|
||||
f.seek(SeekFrom::Start(0)).unwrap();
|
||||
let len = f.read_to_end(&mut rbuf2).unwrap();
|
||||
assert_eq!(len, EXPECT.len());
|
||||
assert_eq!(rbuf2, EXPECT);
|
||||
}
|
||||
|
||||
// Test LioCb::listio with LIO_NOWAIT and a SigEvent to indicate when all
|
||||
// AioCb's are complete.
|
||||
// FIXME: This test is ignored on mips/mips64 because of failures in qemu in CI.
|
||||
#[test]
|
||||
#[cfg(not(any(target_os = "ios", target_os = "macos")))]
|
||||
#[cfg_attr(any(target_arch = "mips", target_arch = "mips64", target_env = "musl"), ignore)]
|
||||
fn test_liocb_listio_signal() {
|
||||
let _m = crate::SIGNAL_MTX.lock();
|
||||
const INITIAL: &[u8] = b"abcdef123456";
|
||||
const WBUF: &[u8] = b"CDEF";
|
||||
let mut rbuf = vec![0; 4];
|
||||
let rlen = rbuf.len();
|
||||
let mut rbuf2 = Vec::new();
|
||||
const EXPECT: &[u8] = b"abCDEF123456";
|
||||
let mut f = tempfile().unwrap();
|
||||
let sa = SigAction::new(SigHandler::Handler(sigfunc),
|
||||
SaFlags::SA_RESETHAND,
|
||||
SigSet::empty());
|
||||
let sigev_notify = SigevNotify::SigevSignal { signal: Signal::SIGUSR2,
|
||||
si_value: 0 };
|
||||
|
||||
f.write_all(INITIAL).unwrap();
|
||||
|
||||
{
|
||||
let mut liocb = LioCbBuilder::with_capacity(2)
|
||||
.emplace_slice(
|
||||
f.as_raw_fd(),
|
||||
2, //offset
|
||||
WBUF,
|
||||
0, //priority
|
||||
SigevNotify::SigevNone,
|
||||
LioOpcode::LIO_WRITE
|
||||
).emplace_mut_slice(
|
||||
f.as_raw_fd(),
|
||||
8, //offset
|
||||
&mut rbuf,
|
||||
0, //priority
|
||||
SigevNotify::SigevNone,
|
||||
LioOpcode::LIO_READ
|
||||
).finish();
|
||||
SIGNALED.store(false, Ordering::Relaxed);
|
||||
unsafe { sigaction(Signal::SIGUSR2, &sa) }.unwrap();
|
||||
let err = liocb.listio(LioMode::LIO_NOWAIT, sigev_notify);
|
||||
err.expect("lio_listio");
|
||||
while !SIGNALED.load(Ordering::Relaxed) {
|
||||
thread::sleep(time::Duration::from_millis(10));
|
||||
}
|
||||
|
||||
assert_eq!(liocb.aio_return(0).unwrap() as usize, WBUF.len());
|
||||
assert_eq!(liocb.aio_return(1).unwrap() as usize, rlen);
|
||||
}
|
||||
assert_eq!(rbuf.deref().deref(), b"3456");
|
||||
|
||||
f.seek(SeekFrom::Start(0)).unwrap();
|
||||
let len = f.read_to_end(&mut rbuf2).unwrap();
|
||||
assert_eq!(len, EXPECT.len());
|
||||
assert_eq!(rbuf2, EXPECT);
|
||||
}
|
||||
|
||||
// Try to use LioCb::listio to read into an immutable buffer. It should fail
|
||||
// FIXME: This test fails to panic on Linux/musl
|
||||
#[test]
|
||||
#[cfg(not(any(target_os = "ios", target_os = "macos")))]
|
||||
#[should_panic(expected = "Can't read into an immutable buffer")]
|
||||
#[cfg_attr(target_env = "musl", ignore)]
|
||||
fn test_liocb_listio_read_immutable() {
|
||||
let rbuf: &[u8] = b"abcd";
|
||||
let f = tempfile().unwrap();
|
||||
|
||||
|
||||
let mut liocb = LioCbBuilder::with_capacity(1)
|
||||
.emplace_slice(
|
||||
f.as_raw_fd(),
|
||||
2, //offset
|
||||
rbuf,
|
||||
0, //priority
|
||||
SigevNotify::SigevNone,
|
||||
LioOpcode::LIO_READ
|
||||
).finish();
|
||||
let _ = liocb.listio(LioMode::LIO_NOWAIT, SigevNotify::SigevNone);
|
||||
}
|
||||
30
third-party/vendor/nix-0.24.3/test/sys/test_aio_drop.rs
vendored
Normal file
30
third-party/vendor/nix-0.24.3/test/sys/test_aio_drop.rs
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// Test dropping an AioCb that hasn't yet finished.
|
||||
// This must happen in its own process, because on OSX this test seems to hose
|
||||
// the AIO subsystem and causes subsequent tests to fail
|
||||
#[test]
|
||||
#[should_panic(expected = "Dropped an in-progress AioCb")]
|
||||
#[cfg(all(not(target_env = "musl"),
|
||||
not(target_env = "uclibc"),
|
||||
any(target_os = "linux",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd")))]
|
||||
fn test_drop() {
|
||||
use nix::sys::aio::*;
|
||||
use nix::sys::signal::*;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use tempfile::tempfile;
|
||||
|
||||
const WBUF: &[u8] = b"CDEF";
|
||||
|
||||
let f = tempfile().unwrap();
|
||||
f.set_len(6).unwrap();
|
||||
let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
|
||||
2, //offset
|
||||
WBUF,
|
||||
0, //priority
|
||||
SigevNotify::SigevNone,
|
||||
LioOpcode::LIO_NOP);
|
||||
aiocb.write().unwrap();
|
||||
}
|
||||
23
third-party/vendor/nix-0.24.3/test/sys/test_epoll.rs
vendored
Normal file
23
third-party/vendor/nix-0.24.3/test/sys/test_epoll.rs
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
use nix::sys::epoll::{EpollCreateFlags, EpollFlags, EpollOp, EpollEvent};
|
||||
use nix::sys::epoll::{epoll_create1, epoll_ctl};
|
||||
use nix::errno::Errno;
|
||||
|
||||
#[test]
|
||||
pub fn test_epoll_errno() {
|
||||
let efd = epoll_create1(EpollCreateFlags::empty()).unwrap();
|
||||
let result = epoll_ctl(efd, EpollOp::EpollCtlDel, 1, None);
|
||||
assert!(result.is_err());
|
||||
assert_eq!(result.unwrap_err(), Errno::ENOENT);
|
||||
|
||||
let result = epoll_ctl(efd, EpollOp::EpollCtlAdd, 1, None);
|
||||
assert!(result.is_err());
|
||||
assert_eq!(result.unwrap_err(), Errno::EINVAL);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_epoll_ctl() {
|
||||
let efd = epoll_create1(EpollCreateFlags::empty()).unwrap();
|
||||
let mut event = EpollEvent::new(EpollFlags::EPOLLIN | EpollFlags::EPOLLERR, 1);
|
||||
epoll_ctl(efd, EpollOp::EpollCtlAdd, 1, &mut event).unwrap();
|
||||
epoll_ctl(efd, EpollOp::EpollCtlDel, 1, None).unwrap();
|
||||
}
|
||||
63
third-party/vendor/nix-0.24.3/test/sys/test_inotify.rs
vendored
Normal file
63
third-party/vendor/nix-0.24.3/test/sys/test_inotify.rs
vendored
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
use nix::sys::inotify::{AddWatchFlags,InitFlags,Inotify};
|
||||
use nix::errno::Errno;
|
||||
use std::ffi::OsString;
|
||||
use std::fs::{rename, File};
|
||||
|
||||
#[test]
|
||||
pub fn test_inotify() {
|
||||
let instance = Inotify::init(InitFlags::IN_NONBLOCK)
|
||||
.unwrap();
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
|
||||
instance.add_watch(tempdir.path(), AddWatchFlags::IN_ALL_EVENTS).unwrap();
|
||||
|
||||
let events = instance.read_events();
|
||||
assert_eq!(events.unwrap_err(), Errno::EAGAIN);
|
||||
|
||||
File::create(tempdir.path().join("test")).unwrap();
|
||||
|
||||
let events = instance.read_events().unwrap();
|
||||
assert_eq!(events[0].name, Some(OsString::from("test")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_inotify_multi_events() {
|
||||
let instance = Inotify::init(InitFlags::IN_NONBLOCK)
|
||||
.unwrap();
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
|
||||
instance.add_watch(tempdir.path(), AddWatchFlags::IN_ALL_EVENTS).unwrap();
|
||||
|
||||
let events = instance.read_events();
|
||||
assert_eq!(events.unwrap_err(), Errno::EAGAIN);
|
||||
|
||||
File::create(tempdir.path().join("test")).unwrap();
|
||||
rename(tempdir.path().join("test"), tempdir.path().join("test2")).unwrap();
|
||||
|
||||
// Now there should be 5 events in queue:
|
||||
// - IN_CREATE on test
|
||||
// - IN_OPEN on test
|
||||
// - IN_CLOSE_WRITE on test
|
||||
// - IN_MOVED_FROM on test with a cookie
|
||||
// - IN_MOVED_TO on test2 with the same cookie
|
||||
|
||||
let events = instance.read_events().unwrap();
|
||||
assert_eq!(events.len(), 5);
|
||||
|
||||
assert_eq!(events[0].mask, AddWatchFlags::IN_CREATE);
|
||||
assert_eq!(events[0].name, Some(OsString::from("test")));
|
||||
|
||||
assert_eq!(events[1].mask, AddWatchFlags::IN_OPEN);
|
||||
assert_eq!(events[1].name, Some(OsString::from("test")));
|
||||
|
||||
assert_eq!(events[2].mask, AddWatchFlags::IN_CLOSE_WRITE);
|
||||
assert_eq!(events[2].name, Some(OsString::from("test")));
|
||||
|
||||
assert_eq!(events[3].mask, AddWatchFlags::IN_MOVED_FROM);
|
||||
assert_eq!(events[3].name, Some(OsString::from("test")));
|
||||
|
||||
assert_eq!(events[4].mask, AddWatchFlags::IN_MOVED_TO);
|
||||
assert_eq!(events[4].name, Some(OsString::from("test2")));
|
||||
|
||||
assert_eq!(events[3].cookie, events[4].cookie);
|
||||
}
|
||||
345
third-party/vendor/nix-0.24.3/test/sys/test_ioctl.rs
vendored
Normal file
345
third-party/vendor/nix-0.24.3/test/sys/test_ioctl.rs
vendored
Normal file
|
|
@ -0,0 +1,345 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
// Simple tests to ensure macro generated fns compile
|
||||
ioctl_none_bad!(do_bad, 0x1234);
|
||||
ioctl_read_bad!(do_bad_read, 0x1234, u16);
|
||||
ioctl_write_int_bad!(do_bad_write_int, 0x1234);
|
||||
ioctl_write_ptr_bad!(do_bad_write_ptr, 0x1234, u8);
|
||||
ioctl_readwrite_bad!(do_bad_readwrite, 0x1234, u32);
|
||||
ioctl_none!(do_none, 0, 0);
|
||||
ioctl_read!(read_test, 0, 0, u32);
|
||||
ioctl_write_int!(write_ptr_int, 0, 0);
|
||||
ioctl_write_ptr!(write_ptr_u8, 0, 0, u8);
|
||||
ioctl_write_ptr!(write_ptr_u32, 0, 0, u32);
|
||||
ioctl_write_ptr!(write_ptr_u64, 0, 0, u64);
|
||||
ioctl_readwrite!(readwrite_test, 0, 0, u64);
|
||||
ioctl_read_buf!(readbuf_test, 0, 0, u32);
|
||||
const SPI_IOC_MAGIC: u8 = b'k';
|
||||
const SPI_IOC_MESSAGE: u8 = 0;
|
||||
ioctl_write_buf!(writebuf_test_consts, SPI_IOC_MAGIC, SPI_IOC_MESSAGE, u8);
|
||||
ioctl_write_buf!(writebuf_test_u8, 0, 0, u8);
|
||||
ioctl_write_buf!(writebuf_test_u32, 0, 0, u32);
|
||||
ioctl_write_buf!(writebuf_test_u64, 0, 0, u64);
|
||||
ioctl_readwrite_buf!(readwritebuf_test, 0, 0, u32);
|
||||
|
||||
// See C code for source of values for op calculations (does NOT work for mips/powerpc):
|
||||
// https://gist.github.com/posborne/83ea6880770a1aef332e
|
||||
//
|
||||
// TODO: Need a way to compute these constants at test time. Using precomputed
|
||||
// values is fragile and needs to be maintained.
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
mod linux {
|
||||
// The cast is not unnecessary on all platforms.
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
#[test]
|
||||
fn test_op_none() {
|
||||
if cfg!(any(target_arch = "mips", target_arch = "mips64", target_arch="powerpc", target_arch="powerpc64")){
|
||||
assert_eq!(request_code_none!(b'q', 10) as u32, 0x2000_710A);
|
||||
assert_eq!(request_code_none!(b'a', 255) as u32, 0x2000_61FF);
|
||||
} else {
|
||||
assert_eq!(request_code_none!(b'q', 10) as u32, 0x0000_710A);
|
||||
assert_eq!(request_code_none!(b'a', 255) as u32, 0x0000_61FF);
|
||||
}
|
||||
}
|
||||
|
||||
// The cast is not unnecessary on all platforms.
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
#[test]
|
||||
fn test_op_write() {
|
||||
if cfg!(any(target_arch = "mips", target_arch = "mips64", target_arch="powerpc", target_arch="powerpc64")){
|
||||
assert_eq!(request_code_write!(b'z', 10, 1) as u32, 0x8001_7A0A);
|
||||
assert_eq!(request_code_write!(b'z', 10, 512) as u32, 0x8200_7A0A);
|
||||
} else {
|
||||
assert_eq!(request_code_write!(b'z', 10, 1) as u32, 0x4001_7A0A);
|
||||
assert_eq!(request_code_write!(b'z', 10, 512) as u32, 0x4200_7A0A);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
#[test]
|
||||
fn test_op_write_64() {
|
||||
if cfg!(any(target_arch = "mips64", target_arch="powerpc64")){
|
||||
assert_eq!(request_code_write!(b'z', 10, 1u64 << 32) as u32,
|
||||
0x8000_7A0A);
|
||||
} else {
|
||||
assert_eq!(request_code_write!(b'z', 10, 1u64 << 32) as u32,
|
||||
0x4000_7A0A);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// The cast is not unnecessary on all platforms.
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
#[test]
|
||||
fn test_op_read() {
|
||||
if cfg!(any(target_arch = "mips", target_arch = "mips64", target_arch="powerpc", target_arch="powerpc64")){
|
||||
assert_eq!(request_code_read!(b'z', 10, 1) as u32, 0x4001_7A0A);
|
||||
assert_eq!(request_code_read!(b'z', 10, 512) as u32, 0x4200_7A0A);
|
||||
} else {
|
||||
assert_eq!(request_code_read!(b'z', 10, 1) as u32, 0x8001_7A0A);
|
||||
assert_eq!(request_code_read!(b'z', 10, 512) as u32, 0x8200_7A0A);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
#[test]
|
||||
fn test_op_read_64() {
|
||||
if cfg!(any(target_arch = "mips64", target_arch="powerpc64")){
|
||||
assert_eq!(request_code_read!(b'z', 10, 1u64 << 32) as u32,
|
||||
0x4000_7A0A);
|
||||
} else {
|
||||
assert_eq!(request_code_read!(b'z', 10, 1u64 << 32) as u32,
|
||||
0x8000_7A0A);
|
||||
}
|
||||
}
|
||||
|
||||
// The cast is not unnecessary on all platforms.
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
#[test]
|
||||
fn test_op_read_write() {
|
||||
assert_eq!(request_code_readwrite!(b'z', 10, 1) as u32, 0xC001_7A0A);
|
||||
assert_eq!(request_code_readwrite!(b'z', 10, 512) as u32, 0xC200_7A0A);
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
#[test]
|
||||
fn test_op_read_write_64() {
|
||||
assert_eq!(request_code_readwrite!(b'z', 10, 1u64 << 32) as u32,
|
||||
0xC000_7A0A);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd"))]
|
||||
mod bsd {
|
||||
#[test]
|
||||
fn test_op_none() {
|
||||
assert_eq!(request_code_none!(b'q', 10), 0x2000_710A);
|
||||
assert_eq!(request_code_none!(b'a', 255), 0x2000_61FF);
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
|
||||
#[test]
|
||||
fn test_op_write_int() {
|
||||
assert_eq!(request_code_write_int!(b'v', 4), 0x2004_7604);
|
||||
assert_eq!(request_code_write_int!(b'p', 2), 0x2004_7002);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_op_write() {
|
||||
assert_eq!(request_code_write!(b'z', 10, 1), 0x8001_7A0A);
|
||||
assert_eq!(request_code_write!(b'z', 10, 512), 0x8200_7A0A);
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
#[test]
|
||||
fn test_op_write_64() {
|
||||
assert_eq!(request_code_write!(b'z', 10, 1u64 << 32), 0x8000_7A0A);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_op_read() {
|
||||
assert_eq!(request_code_read!(b'z', 10, 1), 0x4001_7A0A);
|
||||
assert_eq!(request_code_read!(b'z', 10, 512), 0x4200_7A0A);
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
#[test]
|
||||
fn test_op_read_64() {
|
||||
assert_eq!(request_code_read!(b'z', 10, 1u64 << 32), 0x4000_7A0A);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_op_read_write() {
|
||||
assert_eq!(request_code_readwrite!(b'z', 10, 1), 0xC001_7A0A);
|
||||
assert_eq!(request_code_readwrite!(b'z', 10, 512), 0xC200_7A0A);
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
#[test]
|
||||
fn test_op_read_write_64() {
|
||||
assert_eq!(request_code_readwrite!(b'z', 10, 1u64 << 32), 0xC000_7A0A);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
mod linux_ioctls {
|
||||
use std::mem;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
|
||||
use tempfile::tempfile;
|
||||
use libc::{TCGETS, TCSBRK, TCSETS, TIOCNXCL, termios};
|
||||
|
||||
use nix::errno::Errno;
|
||||
|
||||
ioctl_none_bad!(tiocnxcl, TIOCNXCL);
|
||||
#[test]
|
||||
fn test_ioctl_none_bad() {
|
||||
let file = tempfile().unwrap();
|
||||
let res = unsafe { tiocnxcl(file.as_raw_fd()) };
|
||||
assert_eq!(res, Err(Errno::ENOTTY));
|
||||
}
|
||||
|
||||
ioctl_read_bad!(tcgets, TCGETS, termios);
|
||||
#[test]
|
||||
fn test_ioctl_read_bad() {
|
||||
let file = tempfile().unwrap();
|
||||
let mut termios = unsafe { mem::zeroed() };
|
||||
let res = unsafe { tcgets(file.as_raw_fd(), &mut termios) };
|
||||
assert_eq!(res, Err(Errno::ENOTTY));
|
||||
}
|
||||
|
||||
ioctl_write_int_bad!(tcsbrk, TCSBRK);
|
||||
#[test]
|
||||
fn test_ioctl_write_int_bad() {
|
||||
let file = tempfile().unwrap();
|
||||
let res = unsafe { tcsbrk(file.as_raw_fd(), 0) };
|
||||
assert_eq!(res, Err(Errno::ENOTTY));
|
||||
}
|
||||
|
||||
ioctl_write_ptr_bad!(tcsets, TCSETS, termios);
|
||||
#[test]
|
||||
fn test_ioctl_write_ptr_bad() {
|
||||
let file = tempfile().unwrap();
|
||||
let termios: termios = unsafe { mem::zeroed() };
|
||||
let res = unsafe { tcsets(file.as_raw_fd(), &termios) };
|
||||
assert_eq!(res, Err(Errno::ENOTTY));
|
||||
}
|
||||
|
||||
// FIXME: Find a suitable example for `ioctl_readwrite_bad`
|
||||
|
||||
// From linux/videodev2.h
|
||||
ioctl_none!(log_status, b'V', 70);
|
||||
#[test]
|
||||
fn test_ioctl_none() {
|
||||
let file = tempfile().unwrap();
|
||||
let res = unsafe { log_status(file.as_raw_fd()) };
|
||||
assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS));
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct v4l2_audio {
|
||||
index: u32,
|
||||
name: [u8; 32],
|
||||
capability: u32,
|
||||
mode: u32,
|
||||
reserved: [u32; 2],
|
||||
}
|
||||
|
||||
// From linux/videodev2.h
|
||||
ioctl_write_ptr!(s_audio, b'V', 34, v4l2_audio);
|
||||
#[test]
|
||||
fn test_ioctl_write_ptr() {
|
||||
let file = tempfile().unwrap();
|
||||
let data: v4l2_audio = unsafe { mem::zeroed() };
|
||||
let res = unsafe { s_audio(file.as_raw_fd(), &data) };
|
||||
assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS));
|
||||
}
|
||||
|
||||
// From linux/net/bluetooth/hci_sock.h
|
||||
const HCI_IOC_MAGIC: u8 = b'H';
|
||||
const HCI_IOC_HCIDEVUP: u8 = 201;
|
||||
ioctl_write_int!(hcidevup, HCI_IOC_MAGIC, HCI_IOC_HCIDEVUP);
|
||||
#[test]
|
||||
fn test_ioctl_write_int() {
|
||||
let file = tempfile().unwrap();
|
||||
let res = unsafe { hcidevup(file.as_raw_fd(), 0) };
|
||||
assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS));
|
||||
}
|
||||
|
||||
// From linux/videodev2.h
|
||||
ioctl_read!(g_audio, b'V', 33, v4l2_audio);
|
||||
#[test]
|
||||
fn test_ioctl_read() {
|
||||
let file = tempfile().unwrap();
|
||||
let mut data: v4l2_audio = unsafe { mem::zeroed() };
|
||||
let res = unsafe { g_audio(file.as_raw_fd(), &mut data) };
|
||||
assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS));
|
||||
}
|
||||
|
||||
// From linux/videodev2.h
|
||||
ioctl_readwrite!(enum_audio, b'V', 65, v4l2_audio);
|
||||
#[test]
|
||||
fn test_ioctl_readwrite() {
|
||||
let file = tempfile().unwrap();
|
||||
let mut data: v4l2_audio = unsafe { mem::zeroed() };
|
||||
let res = unsafe { enum_audio(file.as_raw_fd(), &mut data) };
|
||||
assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS));
|
||||
}
|
||||
|
||||
// FIXME: Find a suitable example for `ioctl_read_buf`.
|
||||
|
||||
#[repr(C)]
|
||||
pub struct spi_ioc_transfer {
|
||||
tx_buf: u64,
|
||||
rx_buf: u64,
|
||||
len: u32,
|
||||
speed_hz: u32,
|
||||
delay_usecs: u16,
|
||||
bits_per_word: u8,
|
||||
cs_change: u8,
|
||||
tx_nbits: u8,
|
||||
rx_nbits: u8,
|
||||
pad: u16,
|
||||
}
|
||||
|
||||
// From linux/spi/spidev.h
|
||||
ioctl_write_buf!(spi_ioc_message, super::SPI_IOC_MAGIC, super::SPI_IOC_MESSAGE, spi_ioc_transfer);
|
||||
#[test]
|
||||
fn test_ioctl_write_buf() {
|
||||
let file = tempfile().unwrap();
|
||||
let data: [spi_ioc_transfer; 4] = unsafe { mem::zeroed() };
|
||||
let res = unsafe { spi_ioc_message(file.as_raw_fd(), &data[..]) };
|
||||
assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS));
|
||||
}
|
||||
|
||||
// FIXME: Find a suitable example for `ioctl_readwrite_buf`.
|
||||
}
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
mod freebsd_ioctls {
|
||||
use std::mem;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
|
||||
use tempfile::tempfile;
|
||||
use libc::termios;
|
||||
|
||||
use nix::errno::Errno;
|
||||
|
||||
// From sys/sys/ttycom.h
|
||||
const TTY_IOC_MAGIC: u8 = b't';
|
||||
const TTY_IOC_TYPE_NXCL: u8 = 14;
|
||||
const TTY_IOC_TYPE_GETA: u8 = 19;
|
||||
const TTY_IOC_TYPE_SETA: u8 = 20;
|
||||
|
||||
ioctl_none!(tiocnxcl, TTY_IOC_MAGIC, TTY_IOC_TYPE_NXCL);
|
||||
#[test]
|
||||
fn test_ioctl_none() {
|
||||
let file = tempfile().unwrap();
|
||||
let res = unsafe { tiocnxcl(file.as_raw_fd()) };
|
||||
assert_eq!(res, Err(Errno::ENOTTY));
|
||||
}
|
||||
|
||||
ioctl_read!(tiocgeta, TTY_IOC_MAGIC, TTY_IOC_TYPE_GETA, termios);
|
||||
#[test]
|
||||
fn test_ioctl_read() {
|
||||
let file = tempfile().unwrap();
|
||||
let mut termios = unsafe { mem::zeroed() };
|
||||
let res = unsafe { tiocgeta(file.as_raw_fd(), &mut termios) };
|
||||
assert_eq!(res, Err(Errno::ENOTTY));
|
||||
}
|
||||
|
||||
ioctl_write_ptr!(tiocseta, TTY_IOC_MAGIC, TTY_IOC_TYPE_SETA, termios);
|
||||
#[test]
|
||||
fn test_ioctl_write_ptr() {
|
||||
let file = tempfile().unwrap();
|
||||
let termios: termios = unsafe { mem::zeroed() };
|
||||
let res = unsafe { tiocseta(file.as_raw_fd(), &termios) };
|
||||
assert_eq!(res, Err(Errno::ENOTTY));
|
||||
}
|
||||
}
|
||||
106
third-party/vendor/nix-0.24.3/test/sys/test_lio_listio_resubmit.rs
vendored
Normal file
106
third-party/vendor/nix-0.24.3/test/sys/test_lio_listio_resubmit.rs
vendored
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
// vim: tw=80
|
||||
|
||||
// Annoyingly, Cargo is unable to conditionally build an entire test binary. So
|
||||
// we must disable the test here rather than in Cargo.toml
|
||||
#![cfg(target_os = "freebsd")]
|
||||
|
||||
use nix::errno::*;
|
||||
use nix::libc::off_t;
|
||||
use nix::sys::aio::*;
|
||||
use nix::sys::signal::SigevNotify;
|
||||
use nix::unistd::{SysconfVar, sysconf};
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::{thread, time};
|
||||
use sysctl::CtlValue;
|
||||
use tempfile::tempfile;
|
||||
|
||||
const BYTES_PER_OP: usize = 512;
|
||||
|
||||
/// Attempt to collect final status for all of `liocb`'s operations, freeing
|
||||
/// system resources
|
||||
fn finish_liocb(liocb: &mut LioCb) {
|
||||
for j in 0..liocb.len() {
|
||||
loop {
|
||||
let e = liocb.error(j);
|
||||
match e {
|
||||
Ok(()) => break,
|
||||
Err(Errno::EINPROGRESS) =>
|
||||
thread::sleep(time::Duration::from_millis(10)),
|
||||
Err(x) => panic!("aio_error({:?})", x)
|
||||
}
|
||||
}
|
||||
assert_eq!(liocb.aio_return(j).unwrap(), BYTES_PER_OP as isize);
|
||||
}
|
||||
}
|
||||
|
||||
// Deliberately exceed system resource limits, causing lio_listio to return EIO.
|
||||
// This test must run in its own process since it deliberately uses all AIO
|
||||
// resources. ATM it is only enabled on FreeBSD, because I don't know how to
|
||||
// check system AIO limits on other operating systems.
|
||||
#[test]
|
||||
fn test_lio_listio_resubmit() {
|
||||
let mut resubmit_count = 0;
|
||||
|
||||
// Lookup system resource limits
|
||||
let alm = sysconf(SysconfVar::AIO_LISTIO_MAX)
|
||||
.expect("sysconf").unwrap() as usize;
|
||||
let maqpp = if let CtlValue::Int(x) = sysctl::value(
|
||||
"vfs.aio.max_aio_queue_per_proc").unwrap(){
|
||||
x as usize
|
||||
} else {
|
||||
panic!("unknown sysctl");
|
||||
};
|
||||
|
||||
// Find lio_listio sizes that satisfy the AIO_LISTIO_MAX constraint and also
|
||||
// result in a final lio_listio call that can only partially be queued
|
||||
let target_ops = maqpp + alm / 2;
|
||||
let num_listios = (target_ops + alm - 3) / (alm - 2);
|
||||
let ops_per_listio = (target_ops + num_listios - 1) / num_listios;
|
||||
assert!((num_listios - 1) * ops_per_listio < maqpp,
|
||||
"the last lio_listio won't make any progress; fix the algorithm");
|
||||
println!("Using {:?} LioCbs of {:?} operations apiece", num_listios,
|
||||
ops_per_listio);
|
||||
|
||||
let f = tempfile().unwrap();
|
||||
let buffer_set = (0..num_listios).map(|_| {
|
||||
(0..ops_per_listio).map(|_| {
|
||||
vec![0u8; BYTES_PER_OP]
|
||||
}).collect::<Vec<_>>()
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
let mut liocbs = (0..num_listios).map(|i| {
|
||||
let mut builder = LioCbBuilder::with_capacity(ops_per_listio);
|
||||
for j in 0..ops_per_listio {
|
||||
let offset = (BYTES_PER_OP * (i * ops_per_listio + j)) as off_t;
|
||||
builder = builder.emplace_slice(f.as_raw_fd(),
|
||||
offset,
|
||||
&buffer_set[i][j][..],
|
||||
0, //priority
|
||||
SigevNotify::SigevNone,
|
||||
LioOpcode::LIO_WRITE);
|
||||
}
|
||||
let mut liocb = builder.finish();
|
||||
let mut err = liocb.listio(LioMode::LIO_NOWAIT, SigevNotify::SigevNone);
|
||||
while err == Err(Errno::EIO) ||
|
||||
err == Err(Errno::EAGAIN) ||
|
||||
err == Err(Errno::EINTR) {
|
||||
//
|
||||
thread::sleep(time::Duration::from_millis(10));
|
||||
resubmit_count += 1;
|
||||
err = liocb.listio_resubmit(LioMode::LIO_NOWAIT,
|
||||
SigevNotify::SigevNone);
|
||||
}
|
||||
liocb
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
// Ensure that every AioCb completed
|
||||
for liocb in liocbs.iter_mut() {
|
||||
finish_liocb(liocb);
|
||||
}
|
||||
|
||||
if resubmit_count > 0 {
|
||||
println!("Resubmitted {:?} times, test passed", resubmit_count);
|
||||
} else {
|
||||
println!("Never resubmitted. Test ambiguous");
|
||||
}
|
||||
}
|
||||
87
third-party/vendor/nix-0.24.3/test/sys/test_mman.rs
vendored
Normal file
87
third-party/vendor/nix-0.24.3/test/sys/test_mman.rs
vendored
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
use nix::sys::mman::{mmap, MapFlags, ProtFlags};
|
||||
|
||||
#[test]
|
||||
fn test_mmap_anonymous() {
|
||||
unsafe {
|
||||
let ptr = mmap(std::ptr::null_mut(), 1,
|
||||
ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
|
||||
MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS, -1, 0)
|
||||
.unwrap() as *mut u8;
|
||||
assert_eq !(*ptr, 0x00u8);
|
||||
*ptr = 0xffu8;
|
||||
assert_eq !(*ptr, 0xffu8);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(target_os = "linux", target_os = "netbsd"))]
|
||||
fn test_mremap_grow() {
|
||||
use nix::sys::mman::{mremap, MRemapFlags};
|
||||
use nix::libc::{c_void, size_t};
|
||||
|
||||
const ONE_K : size_t = 1024;
|
||||
let slice : &mut[u8] = unsafe {
|
||||
let mem = mmap(std::ptr::null_mut(), ONE_K,
|
||||
ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
|
||||
MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE, -1, 0)
|
||||
.unwrap();
|
||||
std::slice::from_raw_parts_mut(mem as * mut u8, ONE_K)
|
||||
};
|
||||
assert_eq !(slice[ONE_K - 1], 0x00);
|
||||
slice[ONE_K - 1] = 0xFF;
|
||||
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)
|
||||
};
|
||||
|
||||
// The first KB should still have the old data in it.
|
||||
assert_eq !(slice[ONE_K - 1], 0xFF);
|
||||
|
||||
// The additional range should be zero-init'd and accessible.
|
||||
assert_eq !(slice[10 * ONE_K - 1], 0x00);
|
||||
slice[10 * ONE_K - 1] = 0xFF;
|
||||
assert_eq !(slice[10 * ONE_K - 1], 0xFF);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(target_os = "linux", target_os = "netbsd"))]
|
||||
// Segfaults for unknown reasons under QEMU for 32-bit targets
|
||||
#[cfg_attr(all(target_pointer_width = "32", qemu), ignore)]
|
||||
fn test_mremap_shrink() {
|
||||
use nix::sys::mman::{mremap, MRemapFlags};
|
||||
use nix::libc::{c_void, size_t};
|
||||
|
||||
const ONE_K : size_t = 1024;
|
||||
let slice : &mut[u8] = unsafe {
|
||||
let mem = mmap(std::ptr::null_mut(), 10 * ONE_K,
|
||||
ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
|
||||
MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE, -1, 0)
|
||||
.unwrap();
|
||||
std::slice::from_raw_parts_mut(mem as * mut u8, ONE_K)
|
||||
};
|
||||
assert_eq !(slice[ONE_K - 1], 0x00);
|
||||
slice[ONE_K - 1] = 0xFF;
|
||||
assert_eq !(slice[ONE_K - 1], 0xFF);
|
||||
|
||||
let slice : &mut[u8] = unsafe {
|
||||
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.
|
||||
assert_eq !(mem, slice.as_mut_ptr() as * mut c_void);
|
||||
std::slice::from_raw_parts_mut(mem as * mut u8, ONE_K)
|
||||
};
|
||||
|
||||
// The first KB should still be accessible and have the old data in it.
|
||||
assert_eq !(slice[ONE_K - 1], 0xFF);
|
||||
}
|
||||
22
third-party/vendor/nix-0.24.3/test/sys/test_pthread.rs
vendored
Normal file
22
third-party/vendor/nix-0.24.3/test/sys/test_pthread.rs
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
use nix::sys::pthread::*;
|
||||
|
||||
#[cfg(any(target_env = "musl", target_os = "redox"))]
|
||||
#[test]
|
||||
fn test_pthread_self() {
|
||||
let tid = pthread_self();
|
||||
assert!(tid != ::std::ptr::null_mut());
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_env = "musl", target_os = "redox")))]
|
||||
#[test]
|
||||
fn test_pthread_self() {
|
||||
let tid = pthread_self();
|
||||
assert!(tid != 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
fn test_pthread_kill_none() {
|
||||
pthread_kill(pthread_self(), None)
|
||||
.expect("Should be able to send signal to my thread.");
|
||||
}
|
||||
219
third-party/vendor/nix-0.24.3/test/sys/test_ptrace.rs
vendored
Normal file
219
third-party/vendor/nix-0.24.3/test/sys/test_ptrace.rs
vendored
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
use nix::errno::Errno;
|
||||
use nix::unistd::getpid;
|
||||
use nix::sys::ptrace;
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
use nix::sys::ptrace::Options;
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
use std::mem;
|
||||
|
||||
use crate::*;
|
||||
|
||||
#[test]
|
||||
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!("test_ptrace", CAP_SYS_PTRACE);
|
||||
let err = ptrace::attach(getpid()).unwrap_err();
|
||||
assert!(err == Errno::EPERM || err == Errno::EINVAL ||
|
||||
err == Errno::ENOSYS);
|
||||
}
|
||||
|
||||
// Just make sure ptrace_setoptions can be called at all, for now.
|
||||
#[test]
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
fn test_ptrace_setoptions() {
|
||||
require_capability!("test_ptrace_setoptions", CAP_SYS_PTRACE);
|
||||
let err = ptrace::setoptions(getpid(), Options::PTRACE_O_TRACESYSGOOD).unwrap_err();
|
||||
assert!(err != Errno::EOPNOTSUPP);
|
||||
}
|
||||
|
||||
// Just make sure ptrace_getevent can be called at all, for now.
|
||||
#[test]
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
fn test_ptrace_getevent() {
|
||||
require_capability!("test_ptrace_getevent", CAP_SYS_PTRACE);
|
||||
let err = ptrace::getevent(getpid()).unwrap_err();
|
||||
assert!(err != Errno::EOPNOTSUPP);
|
||||
}
|
||||
|
||||
// Just make sure ptrace_getsiginfo can be called at all, for now.
|
||||
#[test]
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
fn test_ptrace_getsiginfo() {
|
||||
require_capability!("test_ptrace_getsiginfo", CAP_SYS_PTRACE);
|
||||
if let Err(Errno::EOPNOTSUPP) = ptrace::getsiginfo(getpid()) {
|
||||
panic!("ptrace_getsiginfo returns Errno::EOPNOTSUPP!");
|
||||
}
|
||||
}
|
||||
|
||||
// Just make sure ptrace_setsiginfo can be called at all, for now.
|
||||
#[test]
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
fn test_ptrace_setsiginfo() {
|
||||
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!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_ptrace_cont() {
|
||||
use nix::sys::ptrace;
|
||||
use nix::sys::signal::{raise, Signal};
|
||||
use nix::sys::wait::{waitpid, WaitPidFlag, WaitStatus};
|
||||
use nix::unistd::fork;
|
||||
use nix::unistd::ForkResult::*;
|
||||
|
||||
require_capability!("test_ptrace_cont", CAP_SYS_PTRACE);
|
||||
|
||||
let _m = crate::FORK_MTX.lock();
|
||||
|
||||
// FIXME: qemu-user doesn't implement ptrace on all architectures
|
||||
// and returns ENOSYS in this case.
|
||||
// We (ab)use this behavior to detect the affected platforms
|
||||
// and skip the test then.
|
||||
// On valid platforms the ptrace call should return Errno::EPERM, this
|
||||
// is already tested by `test_ptrace`.
|
||||
let err = ptrace::attach(getpid()).unwrap_err();
|
||||
if err == Errno::ENOSYS {
|
||||
return;
|
||||
}
|
||||
|
||||
match unsafe{fork()}.expect("Error: Fork Failed") {
|
||||
Child => {
|
||||
ptrace::traceme().unwrap();
|
||||
// As recommended by ptrace(2), raise SIGTRAP to pause the child
|
||||
// until the parent is ready to continue
|
||||
loop {
|
||||
raise(Signal::SIGTRAP).unwrap();
|
||||
}
|
||||
|
||||
},
|
||||
Parent { child } => {
|
||||
assert_eq!(waitpid(child, None), Ok(WaitStatus::Stopped(child, Signal::SIGTRAP)));
|
||||
ptrace::cont(child, None).unwrap();
|
||||
assert_eq!(waitpid(child, None), Ok(WaitStatus::Stopped(child, Signal::SIGTRAP)));
|
||||
ptrace::cont(child, Some(Signal::SIGKILL)).unwrap();
|
||||
match waitpid(child, None) {
|
||||
Ok(WaitStatus::Signaled(pid, Signal::SIGKILL, _)) if pid == child => {
|
||||
// FIXME It's been observed on some systems (apple) the
|
||||
// tracee may not be killed but remain as a zombie process
|
||||
// affecting other wait based tests. Add an extra kill just
|
||||
// to make sure there are no zombies.
|
||||
let _ = waitpid(child, Some(WaitPidFlag::WNOHANG));
|
||||
while ptrace::cont(child, Some(Signal::SIGKILL)).is_ok() {
|
||||
let _ = waitpid(child, Some(WaitPidFlag::WNOHANG));
|
||||
}
|
||||
}
|
||||
_ => panic!("The process should have been killed"),
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[test]
|
||||
fn test_ptrace_interrupt() {
|
||||
use nix::sys::ptrace;
|
||||
use nix::sys::signal::Signal;
|
||||
use nix::sys::wait::{waitpid, WaitPidFlag, WaitStatus};
|
||||
use nix::unistd::fork;
|
||||
use nix::unistd::ForkResult::*;
|
||||
use std::thread::sleep;
|
||||
use std::time::Duration;
|
||||
|
||||
require_capability!("test_ptrace_interrupt", CAP_SYS_PTRACE);
|
||||
|
||||
let _m = crate::FORK_MTX.lock();
|
||||
|
||||
match unsafe{fork()}.expect("Error: Fork Failed") {
|
||||
Child => {
|
||||
loop {
|
||||
sleep(Duration::from_millis(1000));
|
||||
}
|
||||
|
||||
},
|
||||
Parent { child } => {
|
||||
ptrace::seize(child, ptrace::Options::PTRACE_O_TRACESYSGOOD).unwrap();
|
||||
ptrace::interrupt(child).unwrap();
|
||||
assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceEvent(child, Signal::SIGTRAP, 128)));
|
||||
ptrace::syscall(child, None).unwrap();
|
||||
assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceSyscall(child)));
|
||||
ptrace::detach(child, Some(Signal::SIGKILL)).unwrap();
|
||||
match waitpid(child, None) {
|
||||
Ok(WaitStatus::Signaled(pid, Signal::SIGKILL, _)) if pid == child => {
|
||||
let _ = waitpid(child, Some(WaitPidFlag::WNOHANG));
|
||||
while ptrace::cont(child, Some(Signal::SIGKILL)).is_ok() {
|
||||
let _ = waitpid(child, Some(WaitPidFlag::WNOHANG));
|
||||
}
|
||||
}
|
||||
_ => panic!("The process should have been killed"),
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// ptrace::{setoptions, getregs} are only available in these platforms
|
||||
#[cfg(all(target_os = "linux",
|
||||
any(target_arch = "x86_64",
|
||||
target_arch = "x86"),
|
||||
target_env = "gnu"))]
|
||||
#[test]
|
||||
fn test_ptrace_syscall() {
|
||||
use nix::sys::signal::kill;
|
||||
use nix::sys::ptrace;
|
||||
use nix::sys::signal::Signal;
|
||||
use nix::sys::wait::{waitpid, WaitStatus};
|
||||
use nix::unistd::fork;
|
||||
use nix::unistd::getpid;
|
||||
use nix::unistd::ForkResult::*;
|
||||
|
||||
require_capability!("test_ptrace_syscall", CAP_SYS_PTRACE);
|
||||
|
||||
let _m = crate::FORK_MTX.lock();
|
||||
|
||||
match unsafe{fork()}.expect("Error: Fork Failed") {
|
||||
Child => {
|
||||
ptrace::traceme().unwrap();
|
||||
// first sigstop until parent is ready to continue
|
||||
let pid = getpid();
|
||||
kill(pid, Signal::SIGSTOP).unwrap();
|
||||
kill(pid, Signal::SIGTERM).unwrap();
|
||||
unsafe { ::libc::_exit(0); }
|
||||
},
|
||||
|
||||
Parent { child } => {
|
||||
assert_eq!(waitpid(child, None), Ok(WaitStatus::Stopped(child, Signal::SIGSTOP)));
|
||||
|
||||
// set this option to recognize syscall-stops
|
||||
ptrace::setoptions(child, ptrace::Options::PTRACE_O_TRACESYSGOOD).unwrap();
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
let get_syscall_id = || ptrace::getregs(child).unwrap().orig_rax as libc::c_long;
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
let get_syscall_id = || ptrace::getregs(child).unwrap().orig_eax as libc::c_long;
|
||||
|
||||
// kill entry
|
||||
ptrace::syscall(child, None).unwrap();
|
||||
assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceSyscall(child)));
|
||||
assert_eq!(get_syscall_id(), ::libc::SYS_kill);
|
||||
|
||||
// kill exit
|
||||
ptrace::syscall(child, None).unwrap();
|
||||
assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceSyscall(child)));
|
||||
assert_eq!(get_syscall_id(), ::libc::SYS_kill);
|
||||
|
||||
// receive signal
|
||||
ptrace::syscall(child, None).unwrap();
|
||||
assert_eq!(waitpid(child, None), Ok(WaitStatus::Stopped(child, Signal::SIGTERM)));
|
||||
|
||||
// inject signal
|
||||
ptrace::syscall(child, Signal::SIGTERM).unwrap();
|
||||
assert_eq!(waitpid(child, None), Ok(WaitStatus::Signaled(child, Signal::SIGTERM, false)));
|
||||
},
|
||||
}
|
||||
}
|
||||
80
third-party/vendor/nix-0.24.3/test/sys/test_select.rs
vendored
Normal file
80
third-party/vendor/nix-0.24.3/test/sys/test_select.rs
vendored
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
use nix::sys::select::*;
|
||||
use nix::unistd::{pipe, write};
|
||||
use nix::sys::signal::SigSet;
|
||||
use nix::sys::time::{TimeSpec, TimeValLike};
|
||||
|
||||
#[test]
|
||||
pub fn test_pselect() {
|
||||
let _mtx = crate::SIGNAL_MTX.lock();
|
||||
|
||||
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);
|
||||
fd_set.insert(r2);
|
||||
|
||||
let timeout = TimeSpec::seconds(10);
|
||||
let sigmask = SigSet::empty();
|
||||
assert_eq!(
|
||||
1,
|
||||
pselect(None, &mut fd_set, None, None, &timeout, &sigmask).unwrap()
|
||||
);
|
||||
assert!(fd_set.contains(r1));
|
||||
assert!(!fd_set.contains(r2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_pselect_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);
|
||||
fd_set.insert(r2);
|
||||
|
||||
let timeout = TimeSpec::seconds(10);
|
||||
assert_eq!(
|
||||
1,
|
||||
pselect(
|
||||
::std::cmp::max(r1, r2) + 1,
|
||||
&mut fd_set,
|
||||
None,
|
||||
None,
|
||||
&timeout,
|
||||
None
|
||||
).unwrap()
|
||||
);
|
||||
assert!(fd_set.contains(r1));
|
||||
assert!(!fd_set.contains(r2));
|
||||
}
|
||||
|
||||
macro_rules! generate_fdset_bad_fd_tests {
|
||||
($fd:expr, $($method:ident),* $(,)?) => {
|
||||
$(
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn $method() {
|
||||
FdSet::new().$method($fd);
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
mod test_fdset_negative_fd {
|
||||
use super::*;
|
||||
generate_fdset_bad_fd_tests!(-1, insert, remove, contains);
|
||||
}
|
||||
|
||||
mod test_fdset_too_large_fd {
|
||||
use super::*;
|
||||
use std::convert::TryInto;
|
||||
generate_fdset_bad_fd_tests!(
|
||||
FD_SETSIZE.try_into().unwrap(),
|
||||
insert,
|
||||
remove,
|
||||
contains,
|
||||
);
|
||||
}
|
||||
121
third-party/vendor/nix-0.24.3/test/sys/test_signal.rs
vendored
Normal file
121
third-party/vendor/nix-0.24.3/test/sys/test_signal.rs
vendored
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
#[cfg(not(target_os = "redox"))]
|
||||
use nix::errno::Errno;
|
||||
use nix::sys::signal::*;
|
||||
use nix::unistd::*;
|
||||
use std::convert::TryFrom;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
#[test]
|
||||
fn test_kill_none() {
|
||||
kill(getpid(), None).expect("Should be able to send signal to myself.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_os = "fuchsia"))]
|
||||
fn test_killpg_none() {
|
||||
killpg(getpgrp(), None)
|
||||
.expect("Should be able to send signal to my process group.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_old_sigaction_flags() {
|
||||
let _m = crate::SIGNAL_MTX.lock();
|
||||
|
||||
extern "C" fn handler(_: ::libc::c_int) {}
|
||||
let act = SigAction::new(
|
||||
SigHandler::Handler(handler),
|
||||
SaFlags::empty(),
|
||||
SigSet::empty(),
|
||||
);
|
||||
let oact = unsafe { sigaction(SIGINT, &act) }.unwrap();
|
||||
let _flags = oact.flags();
|
||||
let oact = unsafe { sigaction(SIGINT, &act) }.unwrap();
|
||||
let _flags = oact.flags();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sigprocmask_noop() {
|
||||
sigprocmask(SigmaskHow::SIG_BLOCK, None, None)
|
||||
.expect("this should be an effective noop");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sigprocmask() {
|
||||
let _m = crate::SIGNAL_MTX.lock();
|
||||
|
||||
// This needs to be a signal that rust doesn't use in the test harness.
|
||||
const SIGNAL: Signal = Signal::SIGCHLD;
|
||||
|
||||
let mut old_signal_set = SigSet::empty();
|
||||
sigprocmask(SigmaskHow::SIG_BLOCK, None, Some(&mut old_signal_set))
|
||||
.expect("expect to be able to retrieve old signals");
|
||||
|
||||
// Make sure the old set doesn't contain the signal, otherwise the following
|
||||
// test don't make sense.
|
||||
assert!(!old_signal_set.contains(SIGNAL),
|
||||
"the {:?} signal is already blocked, please change to a \
|
||||
different one", SIGNAL);
|
||||
|
||||
// Now block the signal.
|
||||
let mut signal_set = SigSet::empty();
|
||||
signal_set.add(SIGNAL);
|
||||
sigprocmask(SigmaskHow::SIG_BLOCK, Some(&signal_set), None)
|
||||
.expect("expect to be able to block signals");
|
||||
|
||||
// And test it again, to make sure the change was effective.
|
||||
old_signal_set.clear();
|
||||
sigprocmask(SigmaskHow::SIG_BLOCK, None, Some(&mut old_signal_set))
|
||||
.expect("expect to be able to retrieve old signals");
|
||||
assert!(old_signal_set.contains(SIGNAL),
|
||||
"expected the {:?} to be blocked", SIGNAL);
|
||||
|
||||
// Reset the signal.
|
||||
sigprocmask(SigmaskHow::SIG_UNBLOCK, Some(&signal_set), None)
|
||||
.expect("expect to be able to block signals");
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref SIGNALED: AtomicBool = AtomicBool::new(false);
|
||||
}
|
||||
|
||||
extern fn test_sigaction_handler(signal: libc::c_int) {
|
||||
let signal = Signal::try_from(signal).unwrap();
|
||||
SIGNALED.store(signal == Signal::SIGINT, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
extern fn test_sigaction_action(_: libc::c_int, _: *mut libc::siginfo_t, _: *mut libc::c_void) {}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
fn test_signal_sigaction() {
|
||||
let _m = crate::SIGNAL_MTX.lock();
|
||||
|
||||
let action_handler = SigHandler::SigAction(test_sigaction_action);
|
||||
assert_eq!(unsafe { signal(Signal::SIGINT, action_handler) }.unwrap_err(), Errno::ENOTSUP);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_signal() {
|
||||
let _m = crate::SIGNAL_MTX.lock();
|
||||
|
||||
unsafe { signal(Signal::SIGINT, SigHandler::SigIgn) }.unwrap();
|
||||
raise(Signal::SIGINT).unwrap();
|
||||
assert_eq!(unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(), SigHandler::SigIgn);
|
||||
|
||||
let handler = SigHandler::Handler(test_sigaction_handler);
|
||||
assert_eq!(unsafe { signal(Signal::SIGINT, handler) }.unwrap(), SigHandler::SigDfl);
|
||||
raise(Signal::SIGINT).unwrap();
|
||||
assert!(SIGNALED.load(Ordering::Relaxed));
|
||||
|
||||
#[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
|
||||
assert_eq!(unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(), handler);
|
||||
|
||||
// System V based OSes (e.g. illumos and Solaris) always resets the
|
||||
// disposition to SIG_DFL prior to calling the signal handler
|
||||
#[cfg(any(target_os = "illumos", target_os = "solaris"))]
|
||||
assert_eq!(unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(), SigHandler::SigDfl);
|
||||
|
||||
// Restore default signal handler
|
||||
unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap();
|
||||
}
|
||||
27
third-party/vendor/nix-0.24.3/test/sys/test_signalfd.rs
vendored
Normal file
27
third-party/vendor/nix-0.24.3/test/sys/test_signalfd.rs
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
use std::convert::TryFrom;
|
||||
|
||||
#[test]
|
||||
fn test_signalfd() {
|
||||
use nix::sys::signalfd::SignalFd;
|
||||
use nix::sys::signal::{self, raise, Signal, SigSet};
|
||||
|
||||
// Grab the mutex for altering signals so we don't interfere with other tests.
|
||||
let _m = crate::SIGNAL_MTX.lock();
|
||||
|
||||
// Block the SIGUSR1 signal from automatic processing for this thread
|
||||
let mut mask = SigSet::empty();
|
||||
mask.add(signal::SIGUSR1);
|
||||
mask.thread_block().unwrap();
|
||||
|
||||
let mut fd = SignalFd::new(&mask).unwrap();
|
||||
|
||||
// Send a SIGUSR1 signal to the current process. Note that this uses `raise` instead of `kill`
|
||||
// because `kill` with `getpid` isn't correct during multi-threaded execution like during a
|
||||
// cargo test session. Instead use `raise` which does the correct thing by default.
|
||||
raise(signal::SIGUSR1).expect("Error: raise(SIGUSR1) failed");
|
||||
|
||||
// And now catch that same signal.
|
||||
let res = fd.read_signal().unwrap().unwrap();
|
||||
let signo = Signal::try_from(res.ssi_signo as i32).unwrap();
|
||||
assert_eq!(signo, signal::SIGUSR1);
|
||||
}
|
||||
2064
third-party/vendor/nix-0.24.3/test/sys/test_socket.rs
vendored
Normal file
2064
third-party/vendor/nix-0.24.3/test/sys/test_socket.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
264
third-party/vendor/nix-0.24.3/test/sys/test_sockopt.rs
vendored
Normal file
264
third-party/vendor/nix-0.24.3/test/sys/test_sockopt.rs
vendored
Normal file
|
|
@ -0,0 +1,264 @@
|
|||
use rand::{thread_rng, Rng};
|
||||
use nix::sys::socket::{socket, sockopt, getsockopt, setsockopt, AddressFamily, SockType, SockFlag, SockProtocol};
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
use crate::*;
|
||||
|
||||
// NB: FreeBSD supports LOCAL_PEERCRED for SOCK_SEQPACKET, but OSX does not.
|
||||
#[cfg(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
))]
|
||||
#[test]
|
||||
pub fn test_local_peercred_seqpacket() {
|
||||
use nix::{
|
||||
unistd::{Gid, Uid},
|
||||
sys::socket::socketpair
|
||||
};
|
||||
|
||||
let (fd1, _fd2) = socketpair(AddressFamily::Unix, SockType::SeqPacket, None,
|
||||
SockFlag::empty()).unwrap();
|
||||
let xucred = getsockopt(fd1, sockopt::LocalPeerCred).unwrap();
|
||||
assert_eq!(xucred.version(), 0);
|
||||
assert_eq!(Uid::from_raw(xucred.uid()), Uid::current());
|
||||
assert_eq!(Gid::from_raw(xucred.groups()[0]), Gid::current());
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "macos",
|
||||
target_os = "ios"
|
||||
))]
|
||||
#[test]
|
||||
pub fn test_local_peercred_stream() {
|
||||
use nix::{
|
||||
unistd::{Gid, Uid},
|
||||
sys::socket::socketpair
|
||||
};
|
||||
|
||||
let (fd1, _fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None,
|
||||
SockFlag::empty()).unwrap();
|
||||
let xucred = getsockopt(fd1, sockopt::LocalPeerCred).unwrap();
|
||||
assert_eq!(xucred.version(), 0);
|
||||
assert_eq!(Uid::from_raw(xucred.uid()), Uid::current());
|
||||
assert_eq!(Gid::from_raw(xucred.groups()[0]), Gid::current());
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[test]
|
||||
fn is_so_mark_functional() {
|
||||
use nix::sys::socket::sockopt;
|
||||
|
||||
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();
|
||||
let mark = getsockopt(s, sockopt::Mark).unwrap();
|
||||
assert_eq!(mark, 1337);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_so_buf() {
|
||||
let fd = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), SockProtocol::Udp)
|
||||
.unwrap();
|
||||
let bufsize: usize = thread_rng().gen_range(4096..131_072);
|
||||
setsockopt(fd, sockopt::SndBuf, &bufsize).unwrap();
|
||||
let actual = getsockopt(fd, sockopt::SndBuf).unwrap();
|
||||
assert!(actual >= bufsize);
|
||||
setsockopt(fd, sockopt::RcvBuf, &bufsize).unwrap();
|
||||
let actual = getsockopt(fd, sockopt::RcvBuf).unwrap();
|
||||
assert!(actual >= bufsize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_so_tcp_maxseg() {
|
||||
use std::net::SocketAddrV4;
|
||||
use std::str::FromStr;
|
||||
use nix::sys::socket::{accept, bind, connect, listen, SockaddrIn};
|
||||
use nix::unistd::{close, write};
|
||||
|
||||
let std_sa = SocketAddrV4::from_str("127.0.0.1:4001").unwrap();
|
||||
let sock_addr = SockaddrIn::from(std_sa);
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_so_type() {
|
||||
let sockfd = socket(
|
||||
AddressFamily::Inet,
|
||||
SockType::Stream,
|
||||
SockFlag::empty(),
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(Ok(SockType::Stream), getsockopt(sockfd, sockopt::SockType));
|
||||
}
|
||||
|
||||
/// getsockopt(_, sockopt::SockType) should gracefully handle unknown socket
|
||||
/// types. Regression test for https://github.com/nix-rust/nix/issues/1819
|
||||
#[cfg(any(target_os = "android", target_os = "linux",))]
|
||||
#[test]
|
||||
fn test_so_type_unknown() {
|
||||
use nix::errno::Errno;
|
||||
|
||||
require_capability!("test_so_type", CAP_NET_RAW);
|
||||
let sockfd = unsafe { libc::socket(libc::AF_PACKET, libc::SOCK_PACKET, 0) };
|
||||
assert!(sockfd >= 0, "Error opening socket: {}", nix::Error::last());
|
||||
|
||||
assert_eq!(Err(Errno::EINVAL), getsockopt(sockfd, sockopt::SockType));
|
||||
}
|
||||
|
||||
// The CI doesn't supported getsockopt and setsockopt on emulated processors.
|
||||
// It's believed 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.
|
||||
// So the syscall doesn't work properly unless the kernel is also emulated.
|
||||
#[test]
|
||||
#[cfg(all(
|
||||
any(target_arch = "x86", target_arch = "x86_64"),
|
||||
any(target_os = "freebsd", target_os = "linux")
|
||||
))]
|
||||
fn test_tcp_congestion() {
|
||||
use std::ffi::OsString;
|
||||
|
||||
let fd = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap();
|
||||
|
||||
let val = getsockopt(fd, sockopt::TcpCongestion).unwrap();
|
||||
setsockopt(fd, sockopt::TcpCongestion, &val).unwrap();
|
||||
|
||||
setsockopt(fd, sockopt::TcpCongestion, &OsString::from("tcp_congestion_does_not_exist")).unwrap_err();
|
||||
|
||||
assert_eq!(
|
||||
getsockopt(fd, sockopt::TcpCongestion).unwrap(),
|
||||
val
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
fn test_bindtodevice() {
|
||||
skip_if_not_root!("test_bindtodevice");
|
||||
|
||||
let fd = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap();
|
||||
|
||||
let val = getsockopt(fd, sockopt::BindToDevice).unwrap();
|
||||
setsockopt(fd, sockopt::BindToDevice, &val).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
getsockopt(fd, sockopt::BindToDevice).unwrap(),
|
||||
val
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_so_tcp_keepalive() {
|
||||
let fd = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), SockProtocol::Tcp).unwrap();
|
||||
setsockopt(fd, sockopt::KeepAlive, &true).unwrap();
|
||||
assert!(getsockopt(fd, sockopt::KeepAlive).unwrap());
|
||||
|
||||
#[cfg(any(target_os = "android",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "linux",
|
||||
target_os = "nacl"))] {
|
||||
let x = getsockopt(fd, sockopt::TcpKeepIdle).unwrap();
|
||||
setsockopt(fd, sockopt::TcpKeepIdle, &(x + 1)).unwrap();
|
||||
assert_eq!(getsockopt(fd, sockopt::TcpKeepIdle).unwrap(), x + 1);
|
||||
|
||||
let x = getsockopt(fd, sockopt::TcpKeepCount).unwrap();
|
||||
setsockopt(fd, sockopt::TcpKeepCount, &(x + 1)).unwrap();
|
||||
assert_eq!(getsockopt(fd, sockopt::TcpKeepCount).unwrap(), x + 1);
|
||||
|
||||
let x = getsockopt(fd, sockopt::TcpKeepInterval).unwrap();
|
||||
setsockopt(fd, sockopt::TcpKeepInterval, &(x + 1)).unwrap();
|
||||
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");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(target_os = "ios", target_os = "macos"))]
|
||||
fn test_dontfrag_opts() {
|
||||
let fd4 = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), SockProtocol::Tcp).unwrap();
|
||||
setsockopt(fd4, sockopt::IpDontFrag, &true)
|
||||
.expect("setting IP_DONTFRAG on an inet stream socket should succeed");
|
||||
setsockopt(fd4, sockopt::IpDontFrag, &false)
|
||||
.expect("unsetting IP_DONTFRAG on an inet stream socket should succeed");
|
||||
let fd4d = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), None).unwrap();
|
||||
setsockopt(fd4d, sockopt::IpDontFrag, &true)
|
||||
.expect("setting IP_DONTFRAG on an inet datagram socket should succeed");
|
||||
setsockopt(fd4d, sockopt::IpDontFrag, &false)
|
||||
.expect("unsetting IP_DONTFRAG on an inet datagram socket should succeed");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "ios",
|
||||
target_os = "linux",
|
||||
target_os = "macos",
|
||||
)
|
||||
)]
|
||||
// Disable the test under emulation because it fails in Cirrus-CI. Lack
|
||||
// of QEMU support is suspected.
|
||||
#[cfg_attr(qemu, ignore)]
|
||||
fn test_v6dontfrag_opts() {
|
||||
let fd6 = socket(AddressFamily::Inet6, SockType::Stream, SockFlag::empty(), SockProtocol::Tcp).unwrap();
|
||||
setsockopt(fd6, sockopt::Ipv6DontFrag, &true)
|
||||
.expect("setting IPV6_DONTFRAG on an inet6 stream socket should succeed");
|
||||
setsockopt(fd6, sockopt::Ipv6DontFrag, &false)
|
||||
.expect("unsetting IPV6_DONTFRAG on an inet6 stream socket should succeed");
|
||||
let fd6d = socket(AddressFamily::Inet6, SockType::Datagram, SockFlag::empty(), None).unwrap();
|
||||
setsockopt(fd6d, sockopt::Ipv6DontFrag, &true)
|
||||
.expect("setting IPV6_DONTFRAG on an inet6 datagram socket should succeed");
|
||||
setsockopt(fd6d, sockopt::Ipv6DontFrag, &false)
|
||||
.expect("unsetting IPV6_DONTFRAG on an inet6 datagram socket should succeed");
|
||||
}
|
||||
29
third-party/vendor/nix-0.24.3/test/sys/test_stat.rs
vendored
Normal file
29
third-party/vendor/nix-0.24.3/test/sys/test_stat.rs
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// The conversion is not useless on all platforms.
|
||||
#[allow(clippy::useless_conversion)]
|
||||
#[cfg(target_os = "freebsd")]
|
||||
#[test]
|
||||
fn test_chflags() {
|
||||
use nix::{
|
||||
sys::stat::{fstat, FileFlag},
|
||||
unistd::chflags,
|
||||
};
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use tempfile::NamedTempFile;
|
||||
|
||||
let f = NamedTempFile::new().unwrap();
|
||||
|
||||
let initial = FileFlag::from_bits_truncate(
|
||||
fstat(f.as_raw_fd()).unwrap().st_flags.into(),
|
||||
);
|
||||
// UF_OFFLINE is preserved by all FreeBSD file systems, but not interpreted
|
||||
// in any way, so it's handy for testing.
|
||||
let commanded = initial ^ FileFlag::UF_OFFLINE;
|
||||
|
||||
chflags(f.path(), commanded).unwrap();
|
||||
|
||||
let changed = FileFlag::from_bits_truncate(
|
||||
fstat(f.as_raw_fd()).unwrap().st_flags.into(),
|
||||
);
|
||||
|
||||
assert_eq!(commanded, changed);
|
||||
}
|
||||
18
third-party/vendor/nix-0.24.3/test/sys/test_sysinfo.rs
vendored
Normal file
18
third-party/vendor/nix-0.24.3/test/sys/test_sysinfo.rs
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
use nix::sys::sysinfo::*;
|
||||
|
||||
#[test]
|
||||
fn sysinfo_works() {
|
||||
let info = sysinfo().unwrap();
|
||||
|
||||
let (l1, l5, l15) = info.load_average();
|
||||
assert!(l1 >= 0.0);
|
||||
assert!(l5 >= 0.0);
|
||||
assert!(l15 >= 0.0);
|
||||
|
||||
info.uptime(); // just test Duration construction
|
||||
|
||||
assert!(info.swap_free() <= info.swap_total(),
|
||||
"more swap available than installed (free: {}, total: {})",
|
||||
info.swap_free(),
|
||||
info.swap_total());
|
||||
}
|
||||
130
third-party/vendor/nix-0.24.3/test/sys/test_termios.rs
vendored
Normal file
130
third-party/vendor/nix-0.24.3/test/sys/test_termios.rs
vendored
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
use std::os::unix::prelude::*;
|
||||
use tempfile::tempfile;
|
||||
|
||||
use nix::fcntl;
|
||||
use nix::errno::Errno;
|
||||
use nix::pty::openpty;
|
||||
use nix::sys::termios::{self, LocalFlags, OutputFlags, tcgetattr};
|
||||
use nix::unistd::{read, write, close};
|
||||
|
||||
/// Helper function analogous to `std::io::Write::write_all`, but for `RawFd`s
|
||||
fn write_all(f: RawFd, buf: &[u8]) {
|
||||
let mut len = 0;
|
||||
while len < buf.len() {
|
||||
len += write(f, &buf[len..]).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
// Test tcgetattr on a terminal
|
||||
#[test]
|
||||
fn test_tcgetattr_pty() {
|
||||
// openpty uses ptname(3) internally
|
||||
let _m = crate::PTSNAME_MTX.lock();
|
||||
|
||||
let pty = openpty(None, None).expect("openpty failed");
|
||||
assert!(termios::tcgetattr(pty.slave).is_ok());
|
||||
close(pty.master).expect("closing the master failed");
|
||||
close(pty.slave).expect("closing the slave failed");
|
||||
}
|
||||
|
||||
// Test tcgetattr on something that isn't a terminal
|
||||
#[test]
|
||||
fn test_tcgetattr_enotty() {
|
||||
let file = tempfile().unwrap();
|
||||
assert_eq!(termios::tcgetattr(file.as_raw_fd()).err(),
|
||||
Some(Errno::ENOTTY));
|
||||
}
|
||||
|
||||
// Test tcgetattr on an invalid file descriptor
|
||||
#[test]
|
||||
fn test_tcgetattr_ebadf() {
|
||||
assert_eq!(termios::tcgetattr(-1).err(),
|
||||
Some(Errno::EBADF));
|
||||
}
|
||||
|
||||
// Test modifying output flags
|
||||
#[test]
|
||||
fn test_output_flags() {
|
||||
// openpty uses ptname(3) internally
|
||||
let _m = crate::PTSNAME_MTX.lock();
|
||||
|
||||
// Open one pty to get attributes for the second one
|
||||
let mut termios = {
|
||||
let pty = openpty(None, None).expect("openpty failed");
|
||||
assert!(pty.master > 0);
|
||||
assert!(pty.slave > 0);
|
||||
let termios = tcgetattr(pty.slave).expect("tcgetattr failed");
|
||||
close(pty.master).unwrap();
|
||||
close(pty.slave).unwrap();
|
||||
termios
|
||||
};
|
||||
|
||||
// Make sure postprocessing '\r' isn't specified by default or this test is useless.
|
||||
assert!(!termios.output_flags.contains(OutputFlags::OPOST | OutputFlags::OCRNL));
|
||||
|
||||
// Specify that '\r' characters should be transformed to '\n'
|
||||
// OPOST is specified to enable post-processing
|
||||
termios.output_flags.insert(OutputFlags::OPOST | OutputFlags::OCRNL);
|
||||
|
||||
// Open a pty
|
||||
let pty = openpty(None, &termios).unwrap();
|
||||
assert!(pty.master > 0);
|
||||
assert!(pty.slave > 0);
|
||||
|
||||
// Write into the master
|
||||
let string = "foofoofoo\r";
|
||||
write_all(pty.master, string.as_bytes());
|
||||
|
||||
// Read from the slave verifying that the output has been properly transformed
|
||||
let mut buf = [0u8; 10];
|
||||
crate::read_exact(pty.slave, &mut buf);
|
||||
let transformed_string = "foofoofoo\n";
|
||||
close(pty.master).unwrap();
|
||||
close(pty.slave).unwrap();
|
||||
assert_eq!(&buf, transformed_string.as_bytes());
|
||||
}
|
||||
|
||||
// Test modifying local flags
|
||||
#[test]
|
||||
fn test_local_flags() {
|
||||
// openpty uses ptname(3) internally
|
||||
let _m = crate::PTSNAME_MTX.lock();
|
||||
|
||||
// Open one pty to get attributes for the second one
|
||||
let mut termios = {
|
||||
let pty = openpty(None, None).unwrap();
|
||||
assert!(pty.master > 0);
|
||||
assert!(pty.slave > 0);
|
||||
let termios = tcgetattr(pty.slave).unwrap();
|
||||
close(pty.master).unwrap();
|
||||
close(pty.slave).unwrap();
|
||||
termios
|
||||
};
|
||||
|
||||
// Make sure echo is specified by default or this test is useless.
|
||||
assert!(termios.local_flags.contains(LocalFlags::ECHO));
|
||||
|
||||
// Disable local echo
|
||||
termios.local_flags.remove(LocalFlags::ECHO);
|
||||
|
||||
// Open a new pty with our modified termios settings
|
||||
let pty = openpty(None, &termios).unwrap();
|
||||
assert!(pty.master > 0);
|
||||
assert!(pty.slave > 0);
|
||||
|
||||
// Set the master is in nonblocking mode or reading will never return.
|
||||
let flags = fcntl::fcntl(pty.master, fcntl::F_GETFL).unwrap();
|
||||
let new_flags = fcntl::OFlag::from_bits_truncate(flags) | fcntl::OFlag::O_NONBLOCK;
|
||||
fcntl::fcntl(pty.master, fcntl::F_SETFL(new_flags)).unwrap();
|
||||
|
||||
// Write into the master
|
||||
let string = "foofoofoo\r";
|
||||
write_all(pty.master, string.as_bytes());
|
||||
|
||||
// Try to read from the master, which should not have anything as echoing was disabled.
|
||||
let mut buf = [0u8; 10];
|
||||
let read = read(pty.master, &mut buf).unwrap_err();
|
||||
close(pty.master).unwrap();
|
||||
close(pty.slave).unwrap();
|
||||
assert_eq!(read, Errno::EAGAIN);
|
||||
}
|
||||
61
third-party/vendor/nix-0.24.3/test/sys/test_timerfd.rs
vendored
Normal file
61
third-party/vendor/nix-0.24.3/test/sys/test_timerfd.rs
vendored
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
use nix::sys::time::{TimeSpec, TimeValLike};
|
||||
use nix::sys::timerfd::{ClockId, Expiration, TimerFd, TimerFlags, TimerSetTimeFlags};
|
||||
use std::time::Instant;
|
||||
|
||||
#[test]
|
||||
pub fn test_timerfd_oneshot() {
|
||||
let timer = TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty()).unwrap();
|
||||
|
||||
let before = Instant::now();
|
||||
|
||||
timer
|
||||
.set(
|
||||
Expiration::OneShot(TimeSpec::seconds(1)),
|
||||
TimerSetTimeFlags::empty(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
timer.wait().unwrap();
|
||||
|
||||
let millis = before.elapsed().as_millis();
|
||||
assert!(millis > 900);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_timerfd_interval() {
|
||||
let timer = TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty()).unwrap();
|
||||
|
||||
let before = Instant::now();
|
||||
timer
|
||||
.set(
|
||||
Expiration::IntervalDelayed(TimeSpec::seconds(1), TimeSpec::seconds(2)),
|
||||
TimerSetTimeFlags::empty(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
timer.wait().unwrap();
|
||||
|
||||
let start_delay = before.elapsed().as_millis();
|
||||
assert!(start_delay > 900);
|
||||
|
||||
timer.wait().unwrap();
|
||||
|
||||
let interval_delay = before.elapsed().as_millis();
|
||||
assert!(interval_delay > 2900);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_timerfd_unset() {
|
||||
let timer = TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty()).unwrap();
|
||||
|
||||
timer
|
||||
.set(
|
||||
Expiration::OneShot(TimeSpec::seconds(1)),
|
||||
TimerSetTimeFlags::empty(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
timer.unset().unwrap();
|
||||
|
||||
assert!(timer.get().unwrap().is_none());
|
||||
}
|
||||
259
third-party/vendor/nix-0.24.3/test/sys/test_uio.rs
vendored
Normal file
259
third-party/vendor/nix-0.24.3/test/sys/test_uio.rs
vendored
Normal file
|
|
@ -0,0 +1,259 @@
|
|||
use nix::sys::uio::*;
|
||||
use nix::unistd::*;
|
||||
use rand::{thread_rng, Rng};
|
||||
use rand::distributions::Alphanumeric;
|
||||
use std::{cmp, iter};
|
||||
use std::fs::{OpenOptions};
|
||||
use std::io::IoSlice;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
use std::io::IoSliceMut;
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
use tempfile::tempfile;
|
||||
use tempfile::tempdir;
|
||||
|
||||
#[test]
|
||||
fn test_writev() {
|
||||
let mut to_write = Vec::with_capacity(16 * 128);
|
||||
for _ in 0..16 {
|
||||
let s: String = thread_rng()
|
||||
.sample_iter(&Alphanumeric)
|
||||
.map(char::from)
|
||||
.take(128)
|
||||
.collect();
|
||||
let b = s.as_bytes();
|
||||
to_write.extend(b.iter().cloned());
|
||||
}
|
||||
// Allocate and fill iovecs
|
||||
let mut iovecs = Vec::new();
|
||||
let mut consumed = 0;
|
||||
while consumed < to_write.len() {
|
||||
let left = to_write.len() - consumed;
|
||||
let slice_len = if left <= 64 { left } else { thread_rng().gen_range(64..cmp::min(256, left)) };
|
||||
let b = &to_write[consumed..consumed+slice_len];
|
||||
iovecs.push(IoSlice::new(b));
|
||||
consumed += slice_len;
|
||||
}
|
||||
let pipe_res = pipe();
|
||||
assert!(pipe_res.is_ok());
|
||||
let (reader, writer) = pipe_res.ok().unwrap();
|
||||
// FileDesc will close its filedesc (reader).
|
||||
let mut read_buf: Vec<u8> = iter::repeat(0u8).take(128 * 16).collect();
|
||||
// Blocking io, should write all data.
|
||||
let write_res = writev(writer, &iovecs);
|
||||
// Successful write
|
||||
assert!(write_res.is_ok());
|
||||
let written = write_res.ok().unwrap();
|
||||
// Check whether we written all data
|
||||
assert_eq!(to_write.len(), written);
|
||||
let read_res = read(reader, &mut read_buf[..]);
|
||||
// Successful read
|
||||
assert!(read_res.is_ok());
|
||||
let read = read_res.ok().unwrap();
|
||||
// Check we have read as much as we written
|
||||
assert_eq!(read, written);
|
||||
// Check equality of written and read data
|
||||
assert_eq!(&to_write, &read_buf);
|
||||
let close_res = close(writer);
|
||||
assert!(close_res.is_ok());
|
||||
let close_res = close(reader);
|
||||
assert!(close_res.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
fn test_readv() {
|
||||
let s:String = thread_rng()
|
||||
.sample_iter(&Alphanumeric)
|
||||
.map(char::from)
|
||||
.take(128)
|
||||
.collect();
|
||||
let to_write = s.as_bytes().to_vec();
|
||||
let mut storage = Vec::new();
|
||||
let mut allocated = 0;
|
||||
while allocated < to_write.len() {
|
||||
let left = to_write.len() - allocated;
|
||||
let vec_len = if left <= 64 { left } else { thread_rng().gen_range(64..cmp::min(256, left)) };
|
||||
let v: Vec<u8> = iter::repeat(0u8).take(vec_len).collect();
|
||||
storage.push(v);
|
||||
allocated += vec_len;
|
||||
}
|
||||
let mut iovecs = Vec::with_capacity(storage.len());
|
||||
for v in &mut storage {
|
||||
iovecs.push(IoSliceMut::new(&mut v[..]));
|
||||
}
|
||||
let pipe_res = pipe();
|
||||
assert!(pipe_res.is_ok());
|
||||
let (reader, writer) = pipe_res.ok().unwrap();
|
||||
// Blocking io, should write all data.
|
||||
let write_res = write(writer, &to_write);
|
||||
// Successful write
|
||||
assert!(write_res.is_ok());
|
||||
let read_res = readv(reader, &mut iovecs[..]);
|
||||
assert!(read_res.is_ok());
|
||||
let read = read_res.ok().unwrap();
|
||||
// Check whether we've read all data
|
||||
assert_eq!(to_write.len(), read);
|
||||
// Cccumulate data from iovecs
|
||||
let mut read_buf = Vec::with_capacity(to_write.len());
|
||||
for iovec in &iovecs {
|
||||
read_buf.extend(iovec.iter().cloned());
|
||||
}
|
||||
// Check whether iovecs contain all written data
|
||||
assert_eq!(read_buf.len(), to_write.len());
|
||||
// Check equality of written and read data
|
||||
assert_eq!(&read_buf, &to_write);
|
||||
let close_res = close(reader);
|
||||
assert!(close_res.is_ok());
|
||||
let close_res = close(writer);
|
||||
assert!(close_res.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
fn test_pwrite() {
|
||||
use std::io::Read;
|
||||
|
||||
let mut file = tempfile().unwrap();
|
||||
let buf = [1u8;8];
|
||||
assert_eq!(Ok(8), pwrite(file.as_raw_fd(), &buf, 8));
|
||||
let mut file_content = Vec::new();
|
||||
file.read_to_end(&mut file_content).unwrap();
|
||||
let mut expected = vec![0u8;8];
|
||||
expected.extend(vec![1;8]);
|
||||
assert_eq!(file_content, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pread() {
|
||||
use std::io::Write;
|
||||
|
||||
let tempdir = tempdir().unwrap();
|
||||
|
||||
let path = tempdir.path().join("pread_test_file");
|
||||
let mut file = OpenOptions::new().write(true).read(true).create(true)
|
||||
.truncate(true).open(path).unwrap();
|
||||
let file_content: Vec<u8> = (0..64).collect();
|
||||
file.write_all(&file_content).unwrap();
|
||||
|
||||
let mut buf = [0u8;16];
|
||||
assert_eq!(Ok(16), pread(file.as_raw_fd(), &mut buf, 16));
|
||||
let expected: Vec<_> = (16..32).collect();
|
||||
assert_eq!(&buf[..], &expected[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
fn test_pwritev() {
|
||||
use std::io::Read;
|
||||
|
||||
let to_write: Vec<u8> = (0..128).collect();
|
||||
let expected: Vec<u8> = [vec![0;100], to_write.clone()].concat();
|
||||
|
||||
let iovecs = [
|
||||
IoSlice::new(&to_write[0..17]),
|
||||
IoSlice::new(&to_write[17..64]),
|
||||
IoSlice::new(&to_write[64..128]),
|
||||
];
|
||||
|
||||
let tempdir = tempdir().unwrap();
|
||||
|
||||
// pwritev them into a temporary file
|
||||
let path = tempdir.path().join("pwritev_test_file");
|
||||
let mut file = OpenOptions::new().write(true).read(true).create(true)
|
||||
.truncate(true).open(path).unwrap();
|
||||
|
||||
let written = pwritev(file.as_raw_fd(), &iovecs, 100).ok().unwrap();
|
||||
assert_eq!(written, to_write.len());
|
||||
|
||||
// Read the data back and make sure it matches
|
||||
let mut contents = Vec::new();
|
||||
file.read_to_end(&mut contents).unwrap();
|
||||
assert_eq!(contents, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
fn test_preadv() {
|
||||
use std::io::Write;
|
||||
|
||||
let to_write: Vec<u8> = (0..200).collect();
|
||||
let expected: Vec<u8> = (100..200).collect();
|
||||
|
||||
let tempdir = tempdir().unwrap();
|
||||
|
||||
let path = tempdir.path().join("preadv_test_file");
|
||||
|
||||
let mut file = OpenOptions::new().read(true).write(true).create(true)
|
||||
.truncate(true).open(path).unwrap();
|
||||
file.write_all(&to_write).unwrap();
|
||||
|
||||
let mut buffers: Vec<Vec<u8>> = vec![
|
||||
vec![0; 24],
|
||||
vec![0; 1],
|
||||
vec![0; 75],
|
||||
];
|
||||
|
||||
{
|
||||
// Borrow the buffers into IoVecs and preadv into them
|
||||
let mut iovecs: Vec<_> = buffers.iter_mut().map(
|
||||
|buf| IoSliceMut::new(&mut buf[..])).collect();
|
||||
assert_eq!(Ok(100), preadv(file.as_raw_fd(), &mut iovecs, 100));
|
||||
}
|
||||
|
||||
let all = buffers.concat();
|
||||
assert_eq!(all, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(target_os = "linux", not(target_env = "uclibc")))] // uclibc doesn't implement process_vm_readv
|
||||
// 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!("test_process_vm_readv", CAP_SYS_PTRACE);
|
||||
let _m = crate::FORK_MTX.lock();
|
||||
|
||||
// Pre-allocate memory in the child, since allocation isn't safe
|
||||
// post-fork (~= async-signal-safe)
|
||||
let mut vector = vec![1u8, 2, 3, 4, 5];
|
||||
|
||||
let (r, w) = pipe().unwrap();
|
||||
match unsafe{fork()}.expect("Error: Fork Failed") {
|
||||
Parent { child } => {
|
||||
close(w).unwrap();
|
||||
// wait for child
|
||||
read(r, &mut [0u8]).unwrap();
|
||||
close(r).unwrap();
|
||||
|
||||
let ptr = vector.as_ptr() as usize;
|
||||
let remote_iov = RemoteIoVec { base: ptr, len: 5 };
|
||||
let mut buf = vec![0u8; 5];
|
||||
|
||||
let ret = process_vm_readv(child,
|
||||
&mut [IoSliceMut::new(&mut buf)],
|
||||
&[remote_iov]);
|
||||
|
||||
kill(child, SIGTERM).unwrap();
|
||||
waitpid(child, None).unwrap();
|
||||
|
||||
assert_eq!(Ok(5), ret);
|
||||
assert_eq!(20u8, buf.iter().sum());
|
||||
},
|
||||
Child => {
|
||||
let _ = close(r);
|
||||
for i in &mut vector {
|
||||
*i += 1;
|
||||
}
|
||||
let _ = write(w, b"\0");
|
||||
let _ = close(w);
|
||||
loop { pause(); }
|
||||
},
|
||||
}
|
||||
}
|
||||
221
third-party/vendor/nix-0.24.3/test/sys/test_wait.rs
vendored
Normal file
221
third-party/vendor/nix-0.24.3/test/sys/test_wait.rs
vendored
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
use nix::errno::Errno;
|
||||
use nix::unistd::*;
|
||||
use nix::unistd::ForkResult::*;
|
||||
use nix::sys::signal::*;
|
||||
use nix::sys::wait::*;
|
||||
use libc::_exit;
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
fn test_wait_signal() {
|
||||
let _m = crate::FORK_MTX.lock();
|
||||
|
||||
// Safe: The child only calls `pause` and/or `_exit`, which are async-signal-safe.
|
||||
match unsafe{fork()}.expect("Error: Fork Failed") {
|
||||
Child => {
|
||||
pause();
|
||||
unsafe { _exit(123) }
|
||||
},
|
||||
Parent { child } => {
|
||||
kill(child, Some(SIGKILL)).expect("Error: Kill Failed");
|
||||
assert_eq!(waitpid(child, None), Ok(WaitStatus::Signaled(child, SIGKILL, false)));
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
all(target_os = "linux", not(target_env = "uclibc")),
|
||||
))]
|
||||
#[cfg(not(any(target_arch = "mips", target_arch = "mips64")))]
|
||||
fn test_waitid_signal() {
|
||||
let _m = crate::FORK_MTX.lock();
|
||||
|
||||
// Safe: The child only calls `pause` and/or `_exit`, which are async-signal-safe.
|
||||
match unsafe{fork()}.expect("Error: Fork Failed") {
|
||||
Child => {
|
||||
pause();
|
||||
unsafe { _exit(123) }
|
||||
},
|
||||
Parent { child } => {
|
||||
kill(child, Some(SIGKILL)).expect("Error: Kill Failed");
|
||||
assert_eq!(
|
||||
waitid(Id::Pid(child), WaitPidFlag::WEXITED),
|
||||
Ok(WaitStatus::Signaled(child, SIGKILL, false)),
|
||||
);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wait_exit() {
|
||||
let _m = crate::FORK_MTX.lock();
|
||||
|
||||
// Safe: Child only calls `_exit`, which is async-signal-safe.
|
||||
match unsafe{fork()}.expect("Error: Fork Failed") {
|
||||
Child => unsafe { _exit(12); },
|
||||
Parent { child } => {
|
||||
assert_eq!(waitpid(child, None), Ok(WaitStatus::Exited(child, 12)));
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
all(target_os = "linux", not(target_env = "uclibc")),
|
||||
))]
|
||||
#[cfg(not(any(target_arch = "mips", target_arch = "mips64")))]
|
||||
fn test_waitid_exit() {
|
||||
let _m = crate::FORK_MTX.lock();
|
||||
|
||||
// Safe: Child only calls `_exit`, which is async-signal-safe.
|
||||
match unsafe{fork()}.expect("Error: Fork Failed") {
|
||||
Child => unsafe { _exit(12); },
|
||||
Parent { child } => {
|
||||
assert_eq!(
|
||||
waitid(Id::Pid(child), WaitPidFlag::WEXITED),
|
||||
Ok(WaitStatus::Exited(child, 12)),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_waitstatus_from_raw() {
|
||||
let pid = Pid::from_raw(1);
|
||||
assert_eq!(WaitStatus::from_raw(pid, 0x0002), Ok(WaitStatus::Signaled(pid, Signal::SIGINT, false)));
|
||||
assert_eq!(WaitStatus::from_raw(pid, 0x0200), Ok(WaitStatus::Exited(pid, 2)));
|
||||
assert_eq!(WaitStatus::from_raw(pid, 0x7f7f), Err(Errno::EINVAL));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_waitstatus_pid() {
|
||||
let _m = crate::FORK_MTX.lock();
|
||||
|
||||
match unsafe{fork()}.unwrap() {
|
||||
Child => unsafe { _exit(0) },
|
||||
Parent { child } => {
|
||||
let status = waitpid(child, None).unwrap();
|
||||
assert_eq!(status.pid(), Some(child));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
all(target_os = "linux", not(target_env = "uclibc")),
|
||||
))]
|
||||
fn test_waitid_pid() {
|
||||
let _m = crate::FORK_MTX.lock();
|
||||
|
||||
match unsafe { fork() }.unwrap() {
|
||||
Child => unsafe { _exit(0) },
|
||||
Parent { child } => {
|
||||
let status = waitid(Id::Pid(child), WaitPidFlag::WEXITED).unwrap();
|
||||
assert_eq!(status.pid(), Some(child));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
// FIXME: qemu-user doesn't implement ptrace on most arches
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
mod ptrace {
|
||||
use nix::sys::ptrace::{self, Options, Event};
|
||||
use nix::sys::signal::*;
|
||||
use nix::sys::wait::*;
|
||||
use nix::unistd::*;
|
||||
use nix::unistd::ForkResult::*;
|
||||
use libc::_exit;
|
||||
use crate::*;
|
||||
|
||||
fn ptrace_child() -> ! {
|
||||
ptrace::traceme().unwrap();
|
||||
// As recommended by ptrace(2), raise SIGTRAP to pause the child
|
||||
// until the parent is ready to continue
|
||||
raise(SIGTRAP).unwrap();
|
||||
unsafe { _exit(0) }
|
||||
}
|
||||
|
||||
fn ptrace_wait_parent(child: Pid) {
|
||||
// Wait for the raised SIGTRAP
|
||||
assert_eq!(waitpid(child, None), Ok(WaitStatus::Stopped(child, SIGTRAP)));
|
||||
// We want to test a syscall stop and a PTRACE_EVENT stop
|
||||
assert!(ptrace::setoptions(child, Options::PTRACE_O_TRACESYSGOOD | Options::PTRACE_O_TRACEEXIT).is_ok());
|
||||
|
||||
// First, stop on the next system call, which will be exit()
|
||||
assert!(ptrace::syscall(child, None).is_ok());
|
||||
assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceSyscall(child)));
|
||||
// Then get the ptrace event for the process exiting
|
||||
assert!(ptrace::cont(child, None).is_ok());
|
||||
assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceEvent(child, SIGTRAP, Event::PTRACE_EVENT_EXIT as i32)));
|
||||
// Finally get the normal wait() result, now that the process has exited
|
||||
assert!(ptrace::cont(child, None).is_ok());
|
||||
assert_eq!(waitpid(child, None), Ok(WaitStatus::Exited(child, 0)));
|
||||
}
|
||||
|
||||
#[cfg(not(target_env = "uclibc"))]
|
||||
fn ptrace_waitid_parent(child: Pid) {
|
||||
// Wait for the raised SIGTRAP
|
||||
//
|
||||
// Unlike waitpid(), waitid() can distinguish trap events from regular
|
||||
// stop events, so unlike ptrace_wait_parent(), we get a PtraceEvent here
|
||||
assert_eq!(
|
||||
waitid(Id::Pid(child), WaitPidFlag::WEXITED),
|
||||
Ok(WaitStatus::PtraceEvent(child, SIGTRAP, 0)),
|
||||
);
|
||||
// We want to test a syscall stop and a PTRACE_EVENT stop
|
||||
assert!(ptrace::setoptions(child, Options::PTRACE_O_TRACESYSGOOD | Options::PTRACE_O_TRACEEXIT).is_ok());
|
||||
|
||||
// First, stop on the next system call, which will be exit()
|
||||
assert!(ptrace::syscall(child, None).is_ok());
|
||||
assert_eq!(
|
||||
waitid(Id::Pid(child), WaitPidFlag::WEXITED),
|
||||
Ok(WaitStatus::PtraceSyscall(child)),
|
||||
);
|
||||
// Then get the ptrace event for the process exiting
|
||||
assert!(ptrace::cont(child, None).is_ok());
|
||||
assert_eq!(
|
||||
waitid(Id::Pid(child), WaitPidFlag::WEXITED),
|
||||
Ok(WaitStatus::PtraceEvent(child, SIGTRAP, Event::PTRACE_EVENT_EXIT as i32)),
|
||||
);
|
||||
// Finally get the normal wait() result, now that the process has exited
|
||||
assert!(ptrace::cont(child, None).is_ok());
|
||||
assert_eq!(
|
||||
waitid(Id::Pid(child), WaitPidFlag::WEXITED),
|
||||
Ok(WaitStatus::Exited(child, 0)),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wait_ptrace() {
|
||||
require_capability!("test_wait_ptrace", CAP_SYS_PTRACE);
|
||||
let _m = crate::FORK_MTX.lock();
|
||||
|
||||
match unsafe{fork()}.expect("Error: Fork Failed") {
|
||||
Child => ptrace_child(),
|
||||
Parent { child } => ptrace_wait_parent(child),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_env = "uclibc"))]
|
||||
fn test_waitid_ptrace() {
|
||||
require_capability!("test_waitid_ptrace", CAP_SYS_PTRACE);
|
||||
let _m = crate::FORK_MTX.lock();
|
||||
|
||||
match unsafe{fork()}.expect("Error: Fork Failed") {
|
||||
Child => ptrace_child(),
|
||||
Parent { child } => ptrace_waitid_parent(child),
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue