summaryrefslogtreecommitdiff
path: root/test/sys/test_termios.rs
diff options
context:
space:
mode:
authorBryant Mairs <bryant@mai.rs>2017-02-27 13:20:58 -0800
committerBryant Mairs <bryant@mai.rs>2017-07-10 20:49:40 -0700
commite3529352e9bfb337c8ccdbfbfa660d23df247cf9 (patch)
tree512df7b19210aba0e37abc2a8132c6a5078138a9 /test/sys/test_termios.rs
parent30d820fe6ffdd50ab9fe4b5ed52467e0ff632928 (diff)
downloadnix-e3529352e9bfb337c8ccdbfbfa660d23df247cf9.zip
Use libc types for termios
This also removes the incorrect TCSASOFT definition as an enum type because it's actually a bitfield.
Diffstat (limited to 'test/sys/test_termios.rs')
-rw-r--r--test/sys/test_termios.rs89
1 files changed, 87 insertions, 2 deletions
diff --git a/test/sys/test_termios.rs b/test/sys/test_termios.rs
index a41304d7..0a2d1855 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, 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,76 @@ 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));
+}