diff options
Diffstat (limited to 'vendor/nix/test/test_pty.rs')
-rw-r--r-- | vendor/nix/test/test_pty.rs | 313 |
1 files changed, 0 insertions, 313 deletions
diff --git a/vendor/nix/test/test_pty.rs b/vendor/nix/test/test_pty.rs deleted file mode 100644 index 5c27e2d63..000000000 --- a/vendor/nix/test/test_pty.rs +++ /dev/null @@ -1,313 +0,0 @@ -use std::fs::File; -use std::io::{Read, Write}; -use std::os::unix::prelude::*; -use std::path::Path; -use tempfile::tempfile; - -use libc::{_exit, STDOUT_FILENO}; -use nix::fcntl::{open, OFlag}; -use nix::pty::*; -use nix::sys::stat; -use nix::sys::termios::*; -use nix::unistd::{close, pause, write}; - -/// Regression test for Issue #659 -/// This is the correct way to explicitly close a `PtyMaster` -#[test] -fn test_explicit_close() { - let mut f = { - let m = posix_openpt(OFlag::O_RDWR).unwrap(); - close(m.into_raw_fd()).unwrap(); - tempfile().unwrap() - }; - // This should work. But if there's been a double close, then it will - // return EBADF - f.write_all(b"whatever").unwrap(); -} - -/// Test equivalence of `ptsname` and `ptsname_r` -#[test] -#[cfg(any(target_os = "android", target_os = "linux"))] -fn test_ptsname_equivalence() { - let _m = crate::PTSNAME_MTX.lock(); - - // Open a new PTTY master - let master_fd = posix_openpt(OFlag::O_RDWR).unwrap(); - assert!(master_fd.as_raw_fd() > 0); - - // Get the name of the slave - let slave_name = unsafe { ptsname(&master_fd) }.unwrap(); - let slave_name_r = ptsname_r(&master_fd).unwrap(); - assert_eq!(slave_name, slave_name_r); -} - -/// Test data copying of `ptsname` -// TODO need to run in a subprocess, since ptsname is non-reentrant -#[test] -#[cfg(any(target_os = "android", target_os = "linux"))] -fn test_ptsname_copy() { - let _m = crate::PTSNAME_MTX.lock(); - - // Open a new PTTY master - let master_fd = posix_openpt(OFlag::O_RDWR).unwrap(); - assert!(master_fd.as_raw_fd() > 0); - - // Get the name of the slave - let slave_name1 = unsafe { ptsname(&master_fd) }.unwrap(); - let slave_name2 = unsafe { ptsname(&master_fd) }.unwrap(); - assert_eq!(slave_name1, slave_name2); - // Also make sure that the string was actually copied and they point to different parts of - // memory. - assert_ne!(slave_name1.as_ptr(), slave_name2.as_ptr()); -} - -/// Test data copying of `ptsname_r` -#[test] -#[cfg(any(target_os = "android", target_os = "linux"))] -fn test_ptsname_r_copy() { - // Open a new PTTY master - let master_fd = posix_openpt(OFlag::O_RDWR).unwrap(); - assert!(master_fd.as_raw_fd() > 0); - - // Get the name of the slave - let slave_name1 = ptsname_r(&master_fd).unwrap(); - let slave_name2 = ptsname_r(&master_fd).unwrap(); - assert_eq!(slave_name1, slave_name2); - assert_ne!(slave_name1.as_ptr(), slave_name2.as_ptr()); -} - -/// Test that `ptsname` returns different names for different devices -#[test] -#[cfg(any(target_os = "android", target_os = "linux"))] -fn test_ptsname_unique() { - let _m = crate::PTSNAME_MTX.lock(); - - // Open a new PTTY master - let master1_fd = posix_openpt(OFlag::O_RDWR).unwrap(); - assert!(master1_fd.as_raw_fd() > 0); - - // Open a second PTTY master - let master2_fd = posix_openpt(OFlag::O_RDWR).unwrap(); - assert!(master2_fd.as_raw_fd() > 0); - - // Get the name of the slave - let slave_name1 = unsafe { ptsname(&master1_fd) }.unwrap(); - let slave_name2 = unsafe { ptsname(&master2_fd) }.unwrap(); - assert_ne!(slave_name1, slave_name2); -} - -/// Common setup for testing PTTY pairs -fn open_ptty_pair() -> (PtyMaster, File) { - let _m = crate::PTSNAME_MTX.lock(); - - // Open a new PTTY master - let master = posix_openpt(OFlag::O_RDWR).expect("posix_openpt failed"); - - // Allow a slave to be generated for it - grantpt(&master).expect("grantpt failed"); - unlockpt(&master).expect("unlockpt failed"); - - // Get the name of the slave - let slave_name = unsafe { ptsname(&master) }.expect("ptsname failed"); - - // Open the slave device - let slave_fd = - open(Path::new(&slave_name), OFlag::O_RDWR, stat::Mode::empty()) - .unwrap(); - - #[cfg(target_os = "illumos")] - // TODO: rewrite using ioctl! - #[allow(clippy::comparison_chain)] - { - use libc::{ioctl, I_FIND, I_PUSH}; - - // On illumos systems, as per pts(7D), one must push STREAMS modules - // after opening a device path returned from ptsname(). - let ptem = b"ptem\0"; - let ldterm = b"ldterm\0"; - let r = unsafe { ioctl(slave_fd, I_FIND, ldterm.as_ptr()) }; - if r < 0 { - panic!("I_FIND failure"); - } else if r == 0 { - if unsafe { ioctl(slave_fd, I_PUSH, ptem.as_ptr()) } < 0 { - panic!("I_PUSH ptem failure"); - } - if unsafe { ioctl(slave_fd, I_PUSH, ldterm.as_ptr()) } < 0 { - panic!("I_PUSH ldterm failure"); - } - } - } - - let slave = unsafe { File::from_raw_fd(slave_fd) }; - - (master, slave) -} - -/// Test opening a master/slave PTTY pair -/// -/// This uses a common `open_ptty_pair` because much of these functions aren't useful by -/// themselves. So for this test we perform the basic act of getting a file handle for a -/// master/slave PTTY pair, then just sanity-check the raw values. -#[test] -fn test_open_ptty_pair() { - let (master, slave) = open_ptty_pair(); - assert!(master.as_raw_fd() > 0); - assert!(slave.as_raw_fd() > 0); -} - -/// Put the terminal in raw mode. -fn make_raw(fd: RawFd) { - let mut termios = tcgetattr(fd).unwrap(); - cfmakeraw(&mut termios); - tcsetattr(fd, SetArg::TCSANOW, &termios).unwrap(); -} - -/// Test `io::Read` on the PTTY master -#[test] -fn test_read_ptty_pair() { - let (mut master, mut slave) = open_ptty_pair(); - make_raw(slave.as_raw_fd()); - - let mut buf = [0u8; 5]; - slave.write_all(b"hello").unwrap(); - master.read_exact(&mut buf).unwrap(); - assert_eq!(&buf, b"hello"); - - let mut master = &master; - slave.write_all(b"hello").unwrap(); - master.read_exact(&mut buf).unwrap(); - assert_eq!(&buf, b"hello"); -} - -/// Test `io::Write` on the PTTY master -#[test] -fn test_write_ptty_pair() { - let (mut master, mut slave) = open_ptty_pair(); - make_raw(slave.as_raw_fd()); - - let mut buf = [0u8; 5]; - master.write_all(b"adios").unwrap(); - slave.read_exact(&mut buf).unwrap(); - assert_eq!(&buf, b"adios"); - - let mut master = &master; - master.write_all(b"adios").unwrap(); - slave.read_exact(&mut buf).unwrap(); - assert_eq!(&buf, b"adios"); -} - -#[test] -fn test_openpty() { - // openpty uses ptname(3) internally - let _m = crate::PTSNAME_MTX.lock(); - - let pty = openpty(None, None).unwrap(); - assert!(pty.master > 0); - assert!(pty.slave > 0); - - // Writing to one should be readable on the other one - let string = "foofoofoo\n"; - let mut buf = [0u8; 10]; - write(pty.master, string.as_bytes()).unwrap(); - crate::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]; - crate::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(); - crate::read_exact(pty.master, &mut buf); - - assert_eq!(&buf, echoed_string2.as_bytes()); - - close(pty.master).unwrap(); - close(pty.slave).unwrap(); -} - -#[test] -fn test_openpty_with_termios() { - // 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 newlines are not transformed so the data is preserved when sent. - termios.output_flags.remove(OutputFlags::ONLCR); - - let pty = openpty(None, &termios).unwrap(); - // Must be valid file descriptors - assert!(pty.master > 0); - assert!(pty.slave > 0); - - // Writing to one should be readable on the other one - let string = "foofoofoo\n"; - let mut buf = [0u8; 10]; - write(pty.master, string.as_bytes()).unwrap(); - crate::read_exact(pty.slave, &mut buf); - - assert_eq!(&buf, string.as_bytes()); - - // read the echo as well - let echoed_string = "foofoofoo\n"; - crate::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(); - crate::read_exact(pty.master, &mut buf); - - assert_eq!(&buf, echoed_string2.as_bytes()); - - close(pty.master).unwrap(); - close(pty.slave).unwrap(); -} - -#[test] -fn test_forkpty() { - use nix::sys::signal::*; - use nix::sys::wait::wait; - use nix::unistd::ForkResult::*; - // forkpty calls openpty which uses ptname(3) internally. - let _m0 = crate::PTSNAME_MTX.lock(); - // forkpty spawns a child process - let _m1 = crate::FORK_MTX.lock(); - - let string = "naninani\n"; - let echoed_string = "naninani\r\n"; - let pty = unsafe { forkpty(None, None).unwrap() }; - match pty.fork_result { - Child => { - write(STDOUT_FILENO, string.as_bytes()).unwrap(); - pause(); // we need the child to stay alive until the parent calls read - unsafe { - _exit(0); - } - } - Parent { child } => { - let mut buf = [0u8; 10]; - assert!(child.as_raw() > 0); - crate::read_exact(pty.master, &mut buf); - kill(child, SIGTERM).unwrap(); - wait().unwrap(); // keep other tests using generic wait from getting our child - assert_eq!(&buf, echoed_string.as_bytes()); - close(pty.master).unwrap(); - } - } -} |