summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml7
-rw-r--r--README.md2
-rw-r--r--src/pty.rs3
-rw-r--r--test/sys/test_aio.rs9
-rw-r--r--test/sys/test_termios.rs46
-rw-r--r--test/sys/test_wait.rs6
-rw-r--r--test/test.rs12
-rw-r--r--test/test_mq.rs54
-rw-r--r--test/test_unistd.rs52
9 files changed, 111 insertions, 80 deletions
diff --git a/.travis.yml b/.travis.yml
index 92234237..935cb1ae 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -64,7 +64,7 @@ matrix:
rust: 1.13.0
- env: TARGET=mipsel-unknown-linux-gnu
rust: 1.13.0
- - env: TARGET=powerpc-unknown-linux-gnu
+ - env: TARGET=powerpc-unknown-linux-gnu DISABLE_TESTS=1
rust: 1.13.0
- env: TARGET=powerpc64-unknown-linux-gnu
rust: 1.13.0
@@ -97,6 +97,11 @@ matrix:
rust: beta
allow_failures:
+ # We allow beta to fail here because a bug might crop up in rust that causes it. We will
+ # however be on the lookout for this and file those bugs with upstream.
+ - env: TARGET=x86_64-unknown-linux-gnu
+ rust: beta
+
# Planning to add these targets, but they can fail for now
- env: TARGET=mips64-unknown-linux-gnuabi64
rust: 1.13.0
diff --git a/README.md b/README.md
index 4ccc4785..2a72e0a8 100644
--- a/README.md
+++ b/README.md
@@ -58,7 +58,6 @@ Tier 1:
* i686-unknown-linux-musl
* mips-unknown-linux-gnu
* mipsel-unknown-linux-gnu
- * powerpc-unknown-linux-gnu
* powerpc64-unknown-linux-gnu
* powerpc64le-unknown-linux-gnu
* x86_64-apple-darwin
@@ -76,6 +75,7 @@ Tier 2:
* i386-apple-ios
* i686-linux-android (requires Rust >= 1.18)
* i686-unknown-freebsd
+ * powerpc-unknown-linux-gnu
* x86_64-apple-ios
* x86_64-linux-android (requires Rust >= 1.18)
* x86_64-unknown-netbsd
diff --git a/src/pty.rs b/src/pty.rs
index fd8ad98e..26c8b500 100644
--- a/src/pty.rs
+++ b/src/pty.rs
@@ -14,7 +14,8 @@ use {Errno, Result, Error, fcntl};
/// Representation of a master/slave pty pair
///
-/// This is returned by `openpty`
+/// This is returned by `openpty`. Note that this type does *not* implement `Drop`, so the user
+/// must manually close the file descriptors.
pub struct OpenptyResult {
pub master: RawFd,
pub slave: RawFd,
diff --git a/test/sys/test_aio.rs b/test/sys/test_aio.rs
index 7945aaf8..7e2bef63 100644
--- a/test/sys/test_aio.rs
+++ b/test/sys/test_aio.rs
@@ -8,7 +8,6 @@ use std::io::{Write, Read, Seek, SeekFrom};
use std::ops::Deref;
use std::os::unix::io::AsRawFd;
use std::rc::Rc;
-use std::sync::Mutex;
use std::sync::atomic::{AtomicBool, Ordering};
use std::{thread, time};
use tempfile::tempfile;
@@ -233,8 +232,6 @@ fn test_write() {
lazy_static! {
pub static ref SIGNALED: AtomicBool = AtomicBool::new(false);
- // protects access to SIGUSR2 handlers, not just SIGNALED
- pub static ref SIGUSR2_MTX: Mutex<()> = Mutex::new(());
}
extern fn sigfunc(_: c_int) {
@@ -246,7 +243,8 @@ extern fn sigfunc(_: c_int) {
#[test]
#[cfg_attr(any(all(target_env = "musl", target_arch = "x86_64"), target_arch = "mips"), ignore)]
fn test_write_sigev_signal() {
- let _ = SIGUSR2_MTX.lock().expect("Mutex got poisoned by another test");
+ #[allow(unused_variables)]
+ let m = ::SIGUSR2_MTX.lock().expect("Mutex got poisoned by another test");
let sa = SigAction::new(SigHandler::Handler(sigfunc),
SA_RESETHAND,
SigSet::empty());
@@ -376,7 +374,8 @@ fn test_lio_listio_nowait() {
#[cfg(not(any(target_os = "ios", target_os = "macos")))]
#[cfg_attr(any(target_arch = "mips", target_env = "musl"), ignore)]
fn test_lio_listio_signal() {
- let _ = SIGUSR2_MTX.lock().expect("Mutex got poisoned by another test");
+ #[allow(unused_variables)]
+ let m = ::SIGUSR2_MTX.lock().expect("Mutex got poisoned by another test");
const INITIAL: &'static [u8] = b"abcdef123456";
const WBUF: &'static [u8] = b"CDEF";
let rbuf = Rc::new(vec![0; 4].into_boxed_slice());
diff --git a/test/sys/test_termios.rs b/test/sys/test_termios.rs
index 308cf62c..c6572052 100644
--- a/test/sys/test_termios.rs
+++ b/test/sys/test_termios.rs
@@ -1,6 +1,7 @@
use std::os::unix::prelude::*;
+use tempfile::tempfile;
-use nix::{Error, fcntl, unistd};
+use nix::{Error, fcntl};
use nix::errno::Errno;
use nix::pty::openpty;
use nix::sys::termios::{self, ECHO, OPOST, OCRNL, Termios, tcgetattr};
@@ -14,22 +15,27 @@ fn write_all(f: RawFd, buf: &[u8]) {
}
}
+// Test tcgetattr on a terminal
#[test]
-fn test_tcgetattr() {
- for fd in 0..5 {
- let termios = termios::tcgetattr(fd);
- match unistd::isatty(fd) {
- // If `fd` is a TTY, tcgetattr must succeed.
- Ok(true) => assert!(termios.is_ok()),
- // If it's an invalid file descriptor, tcgetattr should also return
- // the same error
- Err(Error::Sys(Errno::EBADF)) => {
- assert_eq!(termios.err(), Some(Error::Sys(Errno::EBADF)));
- },
- // Otherwise it should return any error
- _ => assert!(termios.is_err())
- }
- }
+fn test_tcgetattr_pty() {
+ let pty = openpty(None, None).unwrap();
+ assert!(termios::tcgetattr(pty.master).is_ok());
+ close(pty.master).unwrap();
+ close(pty.slave).unwrap();
+}
+// 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(Error::Sys(Errno::ENOTTY)));
+}
+
+// Test tcgetattr on an invalid file descriptor
+#[test]
+fn test_tcgetattr_ebadf() {
+ assert_eq!(termios::tcgetattr(-1).err(),
+ Some(Error::Sys(Errno::EBADF)));
}
// Test modifying output flags
@@ -41,6 +47,8 @@ fn test_output_flags() {
assert!(pty.master > 0);
assert!(pty.slave > 0);
let termios = tcgetattr(pty.master).unwrap();
+ close(pty.master).unwrap();
+ close(pty.slave).unwrap();
termios
};
@@ -64,6 +72,8 @@ fn test_output_flags() {
let mut buf = [0u8; 10];
::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());
}
@@ -76,6 +86,8 @@ fn test_local_flags() {
assert!(pty.master > 0);
assert!(pty.slave > 0);
let termios = tcgetattr(pty.master).unwrap();
+ close(pty.master).unwrap();
+ close(pty.slave).unwrap();
termios
};
@@ -102,6 +114,8 @@ fn test_local_flags() {
// 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, Error::Sys(Errno::EAGAIN));
}
diff --git a/test/sys/test_wait.rs b/test/sys/test_wait.rs
index d8ac94e4..2e28d9e7 100644
--- a/test/sys/test_wait.rs
+++ b/test/sys/test_wait.rs
@@ -6,6 +6,9 @@ use libc::exit;
#[test]
fn test_wait_signal() {
+ #[allow(unused_variables)]
+ let m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
+
match fork() {
Ok(Child) => pause().unwrap_or(()),
Ok(Parent { child }) => {
@@ -19,6 +22,9 @@ fn test_wait_signal() {
#[test]
fn test_wait_exit() {
+ #[allow(unused_variables)]
+ let m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
+
match fork() {
Ok(Child) => unsafe { exit(12); },
Ok(Parent { child }) => {
diff --git a/test/test.rs b/test/test.rs
index 2cf30360..4c81aa2b 100644
--- a/test/test.rs
+++ b/test/test.rs
@@ -25,6 +25,7 @@ mod test_unistd;
use nixtest::assert_size_of;
use std::os::unix::io::RawFd;
+use std::sync::Mutex;
use nix::unistd::read;
/// Helper function analogous to std::io::Read::read_exact, but for `RawFD`s
@@ -37,6 +38,17 @@ fn read_exact(f: RawFd, buf: &mut [u8]) {
}
}
+lazy_static! {
+ /// Any test that changes the process's current working directory must grab
+ /// this mutex
+ pub static ref CWD_MTX: Mutex<()> = Mutex::new(());
+ /// Any test that creates child processes must grab this mutex, regardless
+ /// of what it does with those children.
+ pub static ref FORK_MTX: Mutex<()> = Mutex::new(());
+ /// Any test that registers a SIGUSR2 handler must grab this mutex
+ pub static ref SIGUSR2_MTX: Mutex<()> = Mutex::new(());
+}
+
#[test]
pub fn test_size_of_long() {
// This test is mostly here to ensure that 32bit CI is correctly
diff --git a/test/test_mq.rs b/test/test_mq.rs
index 82a1a388..60f5bd2e 100644
--- a/test/test_mq.rs
+++ b/test/test_mq.rs
@@ -16,43 +16,27 @@ use nix::Error::Sys;
#[test]
fn test_mq_send_and_receive() {
-
const MSG_SIZE: c_long = 32;
let attr = MqAttr::new(0, 10, MSG_SIZE, 0);
- let mq_name_in_parent = &CString::new(b"/a_nix_test_queue".as_ref()).unwrap();
- let mqd_in_parent = mq_open(mq_name_in_parent, O_CREAT | O_WRONLY, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH, Some(&attr)).unwrap();
- let msg_to_send = "msg_1".as_bytes();
-
- mq_send(mqd_in_parent, msg_to_send, 1).unwrap();
-
- let (reader, writer) = pipe().unwrap();
-
- let pid = fork();
- match pid {
- Ok(Child) => {
- let mq_name_in_child = &CString::new(b"/a_nix_test_queue".as_ref()).unwrap();
- let mqd_in_child = mq_open(mq_name_in_child, O_CREAT | O_RDONLY, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH, Some(&attr)).unwrap();
- let mut buf = [0u8; 32];
- let mut prio = 0u32;
- mq_receive(mqd_in_child, &mut buf, &mut prio).unwrap();
- assert!(prio == 1);
- write(writer, &buf).unwrap(); // pipe result to parent process. Otherwise cargo does not report test failures correctly
- mq_close(mqd_in_child).unwrap();
- }
- Ok(Parent { child }) => {
- mq_close(mqd_in_parent).unwrap();
-
- // Wait for the child to exit.
- waitpid(child, None).unwrap();
- // Read 1024 bytes.
- let mut read_buf = [0u8; 32];
- read(reader, &mut read_buf).unwrap();
- let message_str = str::from_utf8(&read_buf).unwrap();
- assert_eq!(&message_str[.. message_str.char_indices().nth(5).unwrap().0], "msg_1");
- },
- // panic, fork should never fail unless there is a serious problem with the OS
- Err(_) => panic!("Error: Fork Failed")
- }
+ let mq_name= &CString::new(b"/a_nix_test_queue".as_ref()).unwrap();
+
+ let mqd0 = mq_open(mq_name, O_CREAT | O_WRONLY,
+ S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH,
+ Some(&attr)).unwrap();
+ let msg_to_send = "msg_1";
+ mq_send(mqd0, msg_to_send.as_bytes(), 1).unwrap();
+
+ let mqd1 = mq_open(mq_name, O_CREAT | O_RDONLY,
+ S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH,
+ Some(&attr)).unwrap();
+ let mut buf = [0u8; 32];
+ let mut prio = 0u32;
+ let len = mq_receive(mqd1, &mut buf, &mut prio).unwrap();
+ assert!(prio == 1);
+
+ mq_close(mqd1).unwrap();
+ mq_close(mqd0).unwrap();
+ assert_eq!(msg_to_send, str::from_utf8(&buf[0..len]).unwrap());
}
diff --git a/test/test_unistd.rs b/test/test_unistd.rs
index 051ea3d1..e6e7b5f2 100644
--- a/test/test_unistd.rs
+++ b/test/test_unistd.rs
@@ -9,16 +9,18 @@ use std::ffi::CString;
use std::fs::File;
use std::io::Write;
use std::os::unix::prelude::*;
-use std::env::current_dir;
use tempfile::tempfile;
use tempdir::TempDir;
use libc::off_t;
+use std::process::exit;
#[test]
fn test_fork_and_waitpid() {
+ #[allow(unused_variables)]
+ let m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
let pid = fork();
match pid {
- Ok(Child) => {} // ignore child here
+ Ok(Child) => exit(0),
Ok(Parent { child }) => {
// assert that child was created and pid > 0
let child_raw: ::libc::pid_t = child.into();
@@ -29,10 +31,10 @@ fn test_fork_and_waitpid() {
Ok(WaitStatus::Exited(pid_t, _)) => assert!(pid_t == child),
// panic, must never happen
- Ok(_) => panic!("Child still alive, should never happen"),
+ s @ Ok(_) => panic!("Child exited {:?}, should never happen", s),
// panic, waitpid should never fail
- Err(_) => panic!("Error: waitpid Failed")
+ Err(s) => panic!("Error: waitpid returned Err({:?}", s)
}
},
@@ -43,9 +45,12 @@ fn test_fork_and_waitpid() {
#[test]
fn test_wait() {
+ // Grab FORK_MTX so wait doesn't reap a different test's child process
+ #[allow(unused_variables)]
+ let m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
let pid = fork();
match pid {
- Ok(Child) => {} // ignore child here
+ Ok(Child) => exit(0),
Ok(Parent { child }) => {
let wait_status = wait();
@@ -100,6 +105,8 @@ macro_rules! execve_test_factory(
($test_name:ident, $syscall:ident, $unix_sh:expr, $android_sh:expr) => (
#[test]
fn $test_name() {
+ #[allow(unused_variables)]
+ let m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
// The `exec`d process will write to `writer`, and we'll read that
// data from `reader`.
let (reader, writer) = pipe().unwrap();
@@ -145,40 +152,43 @@ macro_rules! execve_test_factory(
#[test]
fn test_fchdir() {
+ // fchdir changes the process's cwd
+ #[allow(unused_variables)]
+ let m = ::CWD_MTX.lock().expect("Mutex got poisoned by another test");
+
let tmpdir = TempDir::new("test_fchdir").unwrap();
let tmpdir_path = tmpdir.path().canonicalize().unwrap();
let tmpdir_fd = File::open(&tmpdir_path).unwrap().into_raw_fd();
- let olddir_path = getcwd().unwrap();
- let olddir_fd = File::open(&olddir_path).unwrap().into_raw_fd();
assert!(fchdir(tmpdir_fd).is_ok());
assert_eq!(getcwd().unwrap(), tmpdir_path);
- assert!(fchdir(olddir_fd).is_ok());
- assert_eq!(getcwd().unwrap(), olddir_path);
-
- assert!(close(olddir_fd).is_ok());
assert!(close(tmpdir_fd).is_ok());
}
#[test]
fn test_getcwd() {
- let tmp_dir = TempDir::new("test_getcwd").unwrap();
- assert!(chdir(tmp_dir.path()).is_ok());
- assert_eq!(getcwd().unwrap(), current_dir().unwrap());
-
- // make path 500 chars longer so that buffer doubling in getcwd kicks in.
- // Note: One path cannot be longer than 255 bytes (NAME_MAX)
- // whole path cannot be longer than PATH_MAX (usually 4096 on linux, 1024 on macos)
- let mut inner_tmp_dir = tmp_dir.path().to_path_buf();
+ // chdir changes the process's cwd
+ #[allow(unused_variables)]
+ let m = ::CWD_MTX.lock().expect("Mutex got poisoned by another test");
+
+ let tmpdir = TempDir::new("test_getcwd").unwrap();
+ let tmpdir_path = tmpdir.path().canonicalize().unwrap();
+ assert!(chdir(&tmpdir_path).is_ok());
+ assert_eq!(getcwd().unwrap(), tmpdir_path);
+
+ // make path 500 chars longer so that buffer doubling in getcwd
+ // kicks in. Note: One path cannot be longer than 255 bytes
+ // (NAME_MAX) whole path cannot be longer than PATH_MAX (usually
+ // 4096 on linux, 1024 on macos)
+ let mut inner_tmp_dir = tmpdir_path.to_path_buf();
for _ in 0..5 {
let newdir = iter::repeat("a").take(100).collect::<String>();
- //inner_tmp_dir = inner_tmp_dir.join(newdir).path();
inner_tmp_dir.push(newdir);
assert!(mkdir(inner_tmp_dir.as_path(), stat::S_IRWXU).is_ok());
}
assert!(chdir(inner_tmp_dir.as_path()).is_ok());
- assert_eq!(getcwd().unwrap(), current_dir().unwrap());
+ assert_eq!(getcwd().unwrap(), inner_tmp_dir.as_path());
}
#[test]