summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/sys/mod.rs2
-rw-r--r--test/sys/test_ptrace.rs14
-rw-r--r--test/sys/test_socket.rs39
-rw-r--r--test/sys/test_termios.rs95
-rw-r--r--test/test.rs12
-rw-r--r--test/test_pty.rs27
-rw-r--r--test/test_unistd.rs35
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");