1 //! Tests for the `posix::TTYPort` struct.
2 #![cfg(unix)]
3
4 extern crate serialport;
5
6 use std::io::{Read, Write};
7 use std::os::unix::prelude::*;
8 use std::str;
9 use std::time::Duration;
10
11 use serialport::{SerialPort, TTYPort};
12
13 #[test]
test_ttyport_pair()14 fn test_ttyport_pair() {
15 // FIXME: Create a mutex across all tests for using `TTYPort::pair()` as it's not threadsafe
16 let (mut master, mut slave) = TTYPort::pair().expect("Unable to create ptty pair");
17 master
18 .set_timeout(Duration::from_millis(10))
19 .expect("Unable to set timeout on the master");
20 slave
21 .set_timeout(Duration::from_millis(10))
22 .expect("Unable to set timeout on the slave");
23
24 // Test file descriptors.
25 assert!(
26 master.as_raw_fd() > 0,
27 "Invalid file descriptor on master ptty"
28 );
29 assert!(
30 slave.as_raw_fd() > 0,
31 "Invalid file descriptor on slae ptty"
32 );
33 assert_ne!(
34 master.as_raw_fd(),
35 slave.as_raw_fd(),
36 "master and slave ptty's share the same file descriptor."
37 );
38
39 let msg = "Test Message";
40 let mut buf = [0u8; 128];
41
42 // Write the string on the master
43 let nbytes = master
44 .write(msg.as_bytes())
45 .expect("Unable to write bytes.");
46 assert_eq!(
47 nbytes,
48 msg.len(),
49 "Write message length differs from sent message."
50 );
51
52 // Read it on the slave
53 let nbytes = slave.read(&mut buf).expect("Unable to read bytes.");
54 assert_eq!(
55 nbytes,
56 msg.len(),
57 "Read message length differs from sent message."
58 );
59
60 assert_eq!(
61 str::from_utf8(&buf[..nbytes]).unwrap(),
62 msg,
63 "Received message does not match sent"
64 );
65 }
66
67 #[test]
test_ttyport_timeout()68 fn test_ttyport_timeout() {
69 let result = std::sync::Arc::new(std::sync::Mutex::new(None));
70 let result_thread = result.clone();
71
72 std::thread::spawn(move || {
73 // FIXME: Create a mutex across all tests for using `TTYPort::pair()` as it's not threadsafe
74 let (mut master, _slave) = TTYPort::pair().expect("Unable to create ptty pair");
75 master.set_timeout(Duration::new(1, 0)).unwrap();
76
77 let mut buffer = [0u8];
78 let read_res = master.read(&mut buffer);
79
80 *result_thread.lock().unwrap() = Some(read_res);
81 });
82
83 std::thread::sleep(std::time::Duration::new(2, 0));
84
85 let read_res = result.lock().unwrap();
86 match *read_res {
87 Some(Ok(_)) => panic!("Received data without sending"),
88 Some(Err(ref e)) => assert_eq!(e.kind(), std::io::ErrorKind::TimedOut),
89 None => panic!("Read did not time out"),
90 }
91 }
92
93 #[test]
94 #[cfg(any(target_os = "ios", target_os = "macos"))]
test_osx_pty_pair()95 fn test_osx_pty_pair() {
96 #![allow(unused_variables)]
97 let (mut master, slave) = TTYPort::pair().expect("Unable to create ptty pair");
98 let (output_sink, output_stream) = std::sync::mpsc::sync_channel(1);
99 let name = slave.name().unwrap();
100
101 master.write_all("12".as_bytes()).expect("");
102
103 let reader_thread = std::thread::spawn(move || {
104 let mut port = TTYPort::open(&serialport::new(&name, 0)).expect("unable to open");
105 let mut buffer = [0u8; 2];
106 let amount = port.read_exact(&mut buffer);
107 output_sink
108 .send(String::from_utf8(buffer.to_vec()).expect("buffer not read as valid utf-8"))
109 .expect("unable to send from thread");
110 });
111
112 reader_thread.join().expect("unable to join sink thread");
113 assert_eq!(output_stream.recv().unwrap(), "12");
114 }
115
116 // On Mac this should work (in fact used to in b77768a) but now fails. It's not functionality that
117 // should be required, and the ptys work otherwise. So going to just disable this test instead.
118 #[test]
119 #[cfg_attr(any(target_os = "ios", target_os = "macos"), ignore)]
test_ttyport_set_standard_baud()120 fn test_ttyport_set_standard_baud() {
121 // `master` must be used here as Dropping it causes slave to be deleted by the OS.
122 // TODO: Convert this to a statement-level attribute once
123 // https://github.com/rust-lang/rust/issues/15701 is on stable.
124 // FIXME: Create a mutex across all tests for using `TTYPort::pair()` as it's not threadsafe
125 #![allow(unused_variables)]
126 let (master, mut slave) = TTYPort::pair().expect("Unable to create ptty pair");
127
128 slave.set_baud_rate(9600).unwrap();
129 assert_eq!(slave.baud_rate().unwrap(), 9600);
130 slave.set_baud_rate(57600).unwrap();
131 assert_eq!(slave.baud_rate().unwrap(), 57600);
132 slave.set_baud_rate(115_200).unwrap();
133 assert_eq!(slave.baud_rate().unwrap(), 115_200);
134 }
135
136 // On mac this fails because you can't set nonstandard baud rates for these virtual ports
137 #[test]
138 #[cfg_attr(
139 any(
140 target_os = "ios",
141 all(target_os = "linux", target_env = "musl"),
142 target_os = "macos"
143 ),
144 ignore
145 )]
test_ttyport_set_nonstandard_baud()146 fn test_ttyport_set_nonstandard_baud() {
147 // `master` must be used here as Dropping it causes slave to be deleted by the OS.
148 // TODO: Convert this to a statement-level attribute once
149 // https://github.com/rust-lang/rust/issues/15701 is on stable.
150 // FIXME: Create a mutex across all tests for using `TTYPort::pair()` as it's not threadsafe
151 #![allow(unused_variables)]
152 let (master, mut slave) = TTYPort::pair().expect("Unable to create ptty pair");
153
154 slave.set_baud_rate(10000).unwrap();
155 assert_eq!(slave.baud_rate().unwrap(), 10000);
156 slave.set_baud_rate(60000).unwrap();
157 assert_eq!(slave.baud_rate().unwrap(), 60000);
158 slave.set_baud_rate(1_200_000).unwrap();
159 assert_eq!(slave.baud_rate().unwrap(), 1_200_000);
160 }
161