diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/sys/mod.rs | 2 | ||||
-rw-r--r-- | test/sys/test_ptrace.rs | 14 | ||||
-rw-r--r-- | test/sys/test_socket.rs | 39 | ||||
-rw-r--r-- | test/sys/test_termios.rs | 95 | ||||
-rw-r--r-- | test/test.rs | 12 | ||||
-rw-r--r-- | test/test_pty.rs | 27 | ||||
-rw-r--r-- | test/test_unistd.rs | 35 |
7 files changed, 187 insertions, 37 deletions
diff --git a/test/sys/mod.rs b/test/sys/mod.rs index e93b0d28..4edb6af0 100644 --- a/test/sys/mod.rs +++ b/test/sys/mod.rs @@ -13,3 +13,5 @@ mod test_uio; #[cfg(target_os = "linux")] mod test_epoll; mod test_pthread; +#[cfg(any(target_os = "linux", target_os = "android"))] +mod test_ptrace; diff --git a/test/sys/test_ptrace.rs b/test/sys/test_ptrace.rs new file mode 100644 index 00000000..6318495a --- /dev/null +++ b/test/sys/test_ptrace.rs @@ -0,0 +1,14 @@ +use nix::Error; +use nix::errno::*; +use nix::unistd::*; +use nix::sys::ptrace::*; +use nix::sys::ptrace::ptrace::*; +use std::ptr; + +#[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 + let err = ptrace(PTRACE_ATTACH, getpid(), ptr::null_mut(), ptr::null_mut()).unwrap_err(); + assert!(err == Error::Sys(Errno::EPERM) || err == Error::Sys(Errno::ENOSYS)); +} diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs index b5465aa0..9f9c9bf0 100644 --- a/test/sys/test_socket.rs +++ b/test/sys/test_socket.rs @@ -131,7 +131,7 @@ pub fn test_scm_rights() { panic!("unexpected cmsg"); } } - assert_eq!(msg.flags & (MSG_TRUNC | MSG_CTRUNC), MsgFlags::empty()); + assert!(!msg.flags.intersects(MSG_TRUNC | MSG_CTRUNC)); close(fd2).unwrap(); } @@ -145,6 +145,43 @@ pub fn test_scm_rights() { close(w).unwrap(); } +// Verify `sendmsg` builds a valid `msghdr` when passing an empty +// `cmsgs` argument. This should result in a msghdr with a nullptr +// msg_control field and a msg_controllen of 0 when calling into the +// raw `sendmsg`. +#[test] +pub fn test_sendmsg_empty_cmsgs() { + use nix::sys::uio::IoVec; + use nix::unistd::close; + use nix::sys::socket::{socketpair, sendmsg, recvmsg, + AddressFamily, SockType, SockFlag, + CmsgSpace, MsgFlags, + MSG_TRUNC, MSG_CTRUNC}; + + let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, 0, + SockFlag::empty()) + .unwrap(); + + { + let iov = [IoVec::from_slice(b"hello")]; + assert_eq!(sendmsg(fd1, &iov, &[], MsgFlags::empty(), None).unwrap(), 5); + close(fd1).unwrap(); + } + + { + let mut buf = [0u8; 5]; + let iov = [IoVec::from_mut_slice(&mut buf[..])]; + let mut cmsgspace: CmsgSpace<[RawFd; 1]> = CmsgSpace::new(); + let msg = recvmsg(fd2, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap(); + + for _ in msg.cmsgs() { + panic!("unexpected cmsg"); + } + assert!(!msg.flags.intersects(MSG_TRUNC | MSG_CTRUNC)); + close(fd2).unwrap(); + } +} + // Test creating and using named unix domain sockets #[test] pub fn test_unixdomain() { diff --git a/test/sys/test_termios.rs b/test/sys/test_termios.rs index a41304d7..308cf62c 100644 --- a/test/sys/test_termios.rs +++ b/test/sys/test_termios.rs @@ -1,6 +1,18 @@ +use std::os::unix::prelude::*; + +use nix::{Error, fcntl, unistd}; use nix::errno::Errno; -use nix::sys::termios; -use nix::{Error, unistd}; +use nix::pty::openpty; +use nix::sys::termios::{self, ECHO, OPOST, OCRNL, Termios, 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] fn test_tcgetattr() { @@ -19,3 +31,82 @@ fn test_tcgetattr() { } } } + +// Test modifying output flags +#[test] +fn test_output_flags() { + // 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.master).unwrap(); + termios + }; + + // Make sure postprocessing '\r' isn't specified by default or this test is useless. + assert!(!termios.output_flags.contains(OPOST | OCRNL)); + + // Specify that '\r' characters should be transformed to '\n' + // OPOST is specified to enable post-processing + termios.output_flags.insert(OPOST | 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]; + ::read_exact(pty.slave, &mut buf); + let transformed_string = "foofoofoo\n"; + assert_eq!(&buf, transformed_string.as_bytes()); +} + +// Test modifying local flags +#[test] +fn test_local_flags() { + // 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.master).unwrap(); + termios + }; + + // Make sure echo is specified by default or this test is useless. + assert!(termios.local_flags.contains(ECHO)); + + // Disable local echo + termios.local_flags.remove(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(flags).unwrap() | fcntl::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(); + assert_eq!(read, Error::Sys(Errno::EAGAIN)); +} + +#[test] +fn test_cfmakeraw() { + let mut termios = unsafe { Termios::default_uninit() }; + termios::cfmakeraw(&mut termios); +} diff --git a/test/test.rs b/test/test.rs index e2f5a024..2cf30360 100644 --- a/test/test.rs +++ b/test/test.rs @@ -24,6 +24,18 @@ mod test_stat; mod test_unistd; use nixtest::assert_size_of; +use std::os::unix::io::RawFd; +use nix::unistd::read; + +/// Helper function analogous to std::io::Read::read_exact, but for `RawFD`s +fn read_exact(f: RawFd, buf: &mut [u8]) { + let mut len = 0; + while len < buf.len() { + // get_mut would be better than split_at_mut, but it requires nightly + let (_, remaining) = buf.split_at_mut(len); + len += read(f, remaining).unwrap(); + } +} #[test] pub fn test_size_of_long() { diff --git a/test/test_pty.rs b/test/test_pty.rs index b1c2d630..53e94724 100644 --- a/test/test_pty.rs +++ b/test/test_pty.rs @@ -5,17 +5,7 @@ use nix::fcntl::{O_RDWR, open}; use nix::pty::*; use nix::sys::stat; use nix::sys::termios::*; -use nix::unistd::{read, write, close}; - -/// Helper function analogous to std::io::Read::read_exact, but for `RawFD`s -fn read_exact(f: RawFd, buf: &mut [u8]) { - let mut len = 0; - while len < buf.len() { - // get_mut would be better than split_at_mut, but it requires nightly - let (_, remaining) = buf.split_at_mut(len); - len += read(f, remaining).unwrap(); - } -} +use nix::unistd::{write, close}; /// Test equivalence of `ptsname` and `ptsname_r` #[test] @@ -115,21 +105,21 @@ fn test_openpty() { let string = "foofoofoo\n"; let mut buf = [0u8; 10]; write(pty.master, string.as_bytes()).unwrap(); - read_exact(pty.slave, &mut buf); + ::read_exact(pty.slave, &mut buf); assert_eq!(&buf, string.as_bytes()); // Read the echo as well let echoed_string = "foofoofoo\r\n"; let mut buf = [0u8; 11]; - read_exact(pty.master, &mut buf); + ::read_exact(pty.master, &mut buf); assert_eq!(&buf, echoed_string.as_bytes()); let string2 = "barbarbarbar\n"; let echoed_string2 = "barbarbarbar\r\n"; let mut buf = [0u8; 14]; write(pty.slave, string2.as_bytes()).unwrap(); - read_exact(pty.master, &mut buf); + ::read_exact(pty.master, &mut buf); assert_eq!(&buf, echoed_string2.as_bytes()); @@ -149,7 +139,8 @@ fn test_openpty_with_termios() { close(pty.slave).unwrap(); termios }; - termios.c_oflag &= !ONLCR; + // Make sure newlines are not transformed so the data is preserved when sent. + termios.output_flags.remove(ONLCR); let pty = openpty(None, &termios).unwrap(); // Must be valid file descriptors @@ -160,20 +151,20 @@ fn test_openpty_with_termios() { let string = "foofoofoo\n"; let mut buf = [0u8; 10]; write(pty.master, string.as_bytes()).unwrap(); - read_exact(pty.slave, &mut buf); + ::read_exact(pty.slave, &mut buf); assert_eq!(&buf, string.as_bytes()); // read the echo as well let echoed_string = "foofoofoo\n"; - read_exact(pty.master, &mut buf); + ::read_exact(pty.master, &mut buf); assert_eq!(&buf, echoed_string.as_bytes()); let string2 = "barbarbarbar\n"; let echoed_string2 = "barbarbarbar\n"; let mut buf = [0u8; 13]; write(pty.slave, string2.as_bytes()).unwrap(); - read_exact(pty.master, &mut buf); + ::read_exact(pty.master, &mut buf); assert_eq!(&buf, echoed_string2.as_bytes()); diff --git a/test/test_unistd.rs b/test/test_unistd.rs index 82c6aa68..051ea3d1 100644 --- a/test/test_unistd.rs +++ b/test/test_unistd.rs @@ -7,7 +7,7 @@ use nix::sys::stat; use std::iter; use std::ffi::CString; use std::fs::File; -use std::io::{Write, Read}; +use std::io::Write; use std::os::unix::prelude::*; use std::env::current_dir; use tempfile::tempfile; @@ -21,7 +21,8 @@ fn test_fork_and_waitpid() { Ok(Child) => {} // ignore child here Ok(Parent { child }) => { // assert that child was created and pid > 0 - assert!(child > 0); + let child_raw: ::libc::pid_t = child.into(); + assert!(child_raw > 0); let wait_status = waitpid(child, None); match wait_status { // assert that waitpid returned correct status and the pid is the one of the child @@ -78,8 +79,8 @@ fn test_mkstemp() { #[test] fn test_getpid() { - let pid = getpid(); - let ppid = getppid(); + let pid: ::libc::pid_t = getpid().into(); + let ppid: ::libc::pid_t = getppid().into(); assert!(pid > 0); assert!(ppid > 0); } @@ -90,7 +91,7 @@ mod linux_android { #[test] fn test_gettid() { - let tid = gettid(); + let tid: ::libc::pid_t = gettid().into(); assert!(tid > 0); } } @@ -184,16 +185,17 @@ fn test_getcwd() { fn test_lseek() { const CONTENTS: &'static [u8] = b"abcdef123456"; let mut tmp = tempfile().unwrap(); - tmp.write(CONTENTS).unwrap(); + tmp.write_all(CONTENTS).unwrap(); + let tmpfd = tmp.into_raw_fd(); let offset: off_t = 5; - lseek(tmp.as_raw_fd(), offset, Whence::SeekSet).unwrap(); + lseek(tmpfd, offset, Whence::SeekSet).unwrap(); - let mut buf = String::new(); - tmp.read_to_string(&mut buf).unwrap(); - assert_eq!(b"f123456", buf.as_bytes()); + let mut buf = [0u8; 7]; + ::read_exact(tmpfd, &mut buf); + assert_eq!(b"f123456", &buf); - close(tmp.as_raw_fd()).unwrap(); + close(tmpfd).unwrap(); } #[cfg(any(target_os = "linux", target_os = "android"))] @@ -202,14 +204,15 @@ fn test_lseek64() { const CONTENTS: &'static [u8] = b"abcdef123456"; let mut tmp = tempfile().unwrap(); tmp.write(CONTENTS).unwrap(); + let tmpfd = tmp.into_raw_fd(); - lseek64(tmp.as_raw_fd(), 5, Whence::SeekSet).unwrap(); + lseek64(tmpfd, 5, Whence::SeekSet).unwrap(); - let mut buf = String::new(); - tmp.read_to_string(&mut buf).unwrap(); - assert_eq!(b"f123456", buf.as_bytes()); + let mut buf = [0u8; 7]; + ::read_exact(tmpfd, &mut buf); + assert_eq!(b"f123456", &buf); - close(tmp.as_raw_fd()).unwrap(); + close(tmpfd).unwrap(); } execve_test_factory!(test_execve, execve, b"/bin/sh", b"/system/bin/sh"); |