use std::os::unix::io::AsFd;
use tempfile::tempfile;
use nix::errno::Errno;
use nix::fcntl;
use nix::pty::openpty;
use nix::sys::termios::{self, tcgetattr, BaudRate, LocalFlags, OutputFlags};
use nix::unistd::{read, write};
fn write_all<Fd: AsFd>(f: Fd, buf: &[u8]) {
let mut len = 0;
while len < buf.len() {
len += write(f.as_fd(), &buf[len..]).unwrap();
}
}
#[test]
fn test_baudrate_try_from() {
assert_eq!(Ok(BaudRate::B0), BaudRate::try_from(libc::B0));
#[cfg(not(target_os = "haiku"))]
BaudRate::try_from(999999999).expect_err("assertion failed");
#[cfg(target_os = "haiku")]
BaudRate::try_from(99).expect_err("assertion failed");
}
#[test]
fn test_tcgetattr_pty() {
let _m = crate::PTSNAME_MTX.lock();
let pty = openpty(None, None).expect("openpty failed");
termios::tcgetattr(&pty.slave).unwrap();
}
#[test]
fn test_tcgetattr_enotty() {
let file = tempfile().unwrap();
assert_eq!(termios::tcgetattr(&file).err(), Some(Errno::ENOTTY));
}
#[test]
fn test_output_flags() {
let _m = crate::PTSNAME_MTX.lock();
let mut termios = {
let pty = openpty(None, None).expect("openpty failed");
tcgetattr(&pty.slave).expect("tcgetattr failed")
};
assert!(!termios
.output_flags
.contains(OutputFlags::OPOST | OutputFlags::OCRNL));
termios
.output_flags
.insert(OutputFlags::OPOST | OutputFlags::OCRNL);
let pty = openpty(None, &termios).unwrap();
let string = "foofoofoo\r";
write_all(&pty.master, string.as_bytes());
let mut buf = [0u8; 10];
crate::read_exact(&pty.slave, &mut buf);
let transformed_string = "foofoofoo\n";
assert_eq!(&buf, transformed_string.as_bytes());
}
#[test]
#[cfg(not(target_os = "solaris"))]
fn test_local_flags() {
let _m = crate::PTSNAME_MTX.lock();
let mut termios = {
let pty = openpty(None, None).unwrap();
tcgetattr(&pty.slave).unwrap()
};
assert!(termios.local_flags.contains(LocalFlags::ECHO));
termios.local_flags.remove(LocalFlags::ECHO);
let pty = openpty(None, &termios).unwrap();
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.as_fd(), fcntl::F_SETFL(new_flags)).unwrap();
let string = "foofoofoo\r";
write_all(&pty.master, string.as_bytes());
let mut buf = [0u8; 10];
let read = read(&pty.master, &mut buf).unwrap_err();
assert_eq!(read, Errno::EAGAIN);
}