|
1 |
| -use std::io::Write; |
| 1 | +use std::fs::File; |
| 2 | +use std::io::{Read, Write}; |
2 | 3 | use std::path::Path;
|
3 | 4 | use std::os::unix::prelude::*;
|
4 | 5 | use tempfile::tempfile;
|
@@ -95,29 +96,68 @@ fn test_ptsname_unique() {
|
95 | 96 | assert!(slave_name1 != slave_name2);
|
96 | 97 | }
|
97 | 98 |
|
98 |
| -/// Test opening a master/slave PTTY pair |
99 |
| -/// |
100 |
| -/// This is a single larger test because much of these functions aren't useful by themselves. So for |
101 |
| -/// this test we perform the basic act of getting a file handle for a connect master/slave PTTY |
102 |
| -/// pair. |
103 |
| -#[test] |
104 |
| -fn test_open_ptty_pair() { |
| 99 | +/// Common setup for testing PTTY pairs |
| 100 | +fn open_ptty_pair() -> (PtyMaster, File) { |
105 | 101 | let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
|
106 | 102 |
|
107 | 103 | // Open a new PTTY master
|
108 |
| - let master_fd = posix_openpt(OFlag::O_RDWR).expect("posix_openpt failed"); |
109 |
| - assert!(master_fd.as_raw_fd() > 0); |
| 104 | + let master = posix_openpt(OFlag::O_RDWR).expect("posix_openpt failed"); |
110 | 105 |
|
111 | 106 | // Allow a slave to be generated for it
|
112 |
| - grantpt(&master_fd).expect("grantpt failed"); |
113 |
| - unlockpt(&master_fd).expect("unlockpt failed"); |
| 107 | + grantpt(&master).expect("grantpt failed"); |
| 108 | + unlockpt(&master).expect("unlockpt failed"); |
114 | 109 |
|
115 | 110 | // Get the name of the slave
|
116 |
| - let slave_name = unsafe { ptsname(&master_fd) }.expect("ptsname failed"); |
| 111 | + let slave_name = unsafe { ptsname(&master) }.expect("ptsname failed"); |
117 | 112 |
|
118 | 113 | // Open the slave device
|
119 | 114 | let slave_fd = open(Path::new(&slave_name), OFlag::O_RDWR, stat::Mode::empty()).unwrap();
|
120 |
| - assert!(slave_fd > 0); |
| 115 | + let slave = unsafe { File::from_raw_fd(slave_fd) }; |
| 116 | + |
| 117 | + (master, slave) |
| 118 | +} |
| 119 | + |
| 120 | +/// Test opening a master/slave PTTY pair |
| 121 | +/// |
| 122 | +/// This uses a common `open_ptty_pair` because much of these functions aren't useful by |
| 123 | +/// themselves. So for this test we perform the basic act of getting a file handle for a |
| 124 | +/// master/slave PTTY pair, then just sanity-check the raw values. |
| 125 | +#[test] |
| 126 | +fn test_open_ptty_pair() { |
| 127 | + let (master, slave) = open_ptty_pair(); |
| 128 | + assert!(master.as_raw_fd() > 0); |
| 129 | + assert!(slave.as_raw_fd() > 0); |
| 130 | +} |
| 131 | + |
| 132 | +/// Put the terminal in raw mode. |
| 133 | +fn make_raw(fd: RawFd) { |
| 134 | + let mut termios = tcgetattr(fd).unwrap(); |
| 135 | + cfmakeraw(&mut termios); |
| 136 | + tcsetattr(fd, SetArg::TCSANOW, &termios).unwrap(); |
| 137 | +} |
| 138 | + |
| 139 | +/// Test `io::Read` on the PTTY master |
| 140 | +#[test] |
| 141 | +fn test_read_ptty_pair() { |
| 142 | + let (mut master, mut slave) = open_ptty_pair(); |
| 143 | + make_raw(slave.as_raw_fd()); |
| 144 | + |
| 145 | + let mut buf = [0u8; 5]; |
| 146 | + slave.write_all(b"hello").unwrap(); |
| 147 | + master.read_exact(&mut buf).unwrap(); |
| 148 | + assert_eq!(&buf, b"hello"); |
| 149 | +} |
| 150 | + |
| 151 | +/// Test `io::Write` on the PTTY master |
| 152 | +#[test] |
| 153 | +fn test_write_ptty_pair() { |
| 154 | + let (mut master, mut slave) = open_ptty_pair(); |
| 155 | + make_raw(slave.as_raw_fd()); |
| 156 | + |
| 157 | + let mut buf = [0u8; 5]; |
| 158 | + master.write_all(b"adios").unwrap(); |
| 159 | + slave.read_exact(&mut buf).unwrap(); |
| 160 | + assert_eq!(&buf, b"adios"); |
121 | 161 | }
|
122 | 162 |
|
123 | 163 | #[test]
|
|
0 commit comments