| //! Tests for the `posix::TTYPort` struct. |
| #![cfg(unix)] |
| |
| extern crate serialport; |
| |
| use std::io::{Read, Write}; |
| use std::os::unix::prelude::*; |
| use std::str; |
| use std::time::Duration; |
| |
| use serialport::{SerialPort, TTYPort}; |
| |
| #[test] |
| fn test_ttyport_pair() { |
| // FIXME: Create a mutex across all tests for using `TTYPort::pair()` as it's not threadsafe |
| let (mut master, mut slave) = TTYPort::pair().expect("Unable to create ptty pair"); |
| master |
| .set_timeout(Duration::from_millis(10)) |
| .expect("Unable to set timeout on the master"); |
| slave |
| .set_timeout(Duration::from_millis(10)) |
| .expect("Unable to set timeout on the slave"); |
| |
| // Test file descriptors. |
| assert!( |
| master.as_raw_fd() > 0, |
| "Invalid file descriptor on master ptty" |
| ); |
| assert!( |
| slave.as_raw_fd() > 0, |
| "Invalid file descriptor on slae ptty" |
| ); |
| assert_ne!( |
| master.as_raw_fd(), |
| slave.as_raw_fd(), |
| "master and slave ptty's share the same file descriptor." |
| ); |
| |
| let msg = "Test Message"; |
| let mut buf = [0u8; 128]; |
| |
| // Write the string on the master |
| let nbytes = master |
| .write(msg.as_bytes()) |
| .expect("Unable to write bytes."); |
| assert_eq!( |
| nbytes, |
| msg.len(), |
| "Write message length differs from sent message." |
| ); |
| |
| // Read it on the slave |
| let nbytes = slave.read(&mut buf).expect("Unable to read bytes."); |
| assert_eq!( |
| nbytes, |
| msg.len(), |
| "Read message length differs from sent message." |
| ); |
| |
| assert_eq!( |
| str::from_utf8(&buf[..nbytes]).unwrap(), |
| msg, |
| "Received message does not match sent" |
| ); |
| } |
| |
| #[test] |
| fn test_ttyport_timeout() { |
| let result = std::sync::Arc::new(std::sync::Mutex::new(None)); |
| let result_thread = result.clone(); |
| |
| std::thread::spawn(move || { |
| // FIXME: Create a mutex across all tests for using `TTYPort::pair()` as it's not threadsafe |
| let (mut master, _slave) = TTYPort::pair().expect("Unable to create ptty pair"); |
| master.set_timeout(Duration::new(1, 0)).unwrap(); |
| |
| let mut buffer = [0u8]; |
| let read_res = master.read(&mut buffer); |
| |
| *result_thread.lock().unwrap() = Some(read_res); |
| }); |
| |
| std::thread::sleep(std::time::Duration::new(2, 0)); |
| |
| let read_res = result.lock().unwrap(); |
| match *read_res { |
| Some(Ok(_)) => panic!("Received data without sending"), |
| Some(Err(ref e)) => assert_eq!(e.kind(), std::io::ErrorKind::TimedOut), |
| None => panic!("Read did not time out"), |
| } |
| } |
| |
| #[test] |
| #[cfg(any(target_os = "ios", target_os = "macos"))] |
| fn test_osx_pty_pair() { |
| #![allow(unused_variables)] |
| let (mut master, slave) = TTYPort::pair().expect("Unable to create ptty pair"); |
| let (output_sink, output_stream) = std::sync::mpsc::sync_channel(1); |
| let name = slave.name().unwrap(); |
| |
| master.write_all("12".as_bytes()).expect(""); |
| |
| let reader_thread = std::thread::spawn(move || { |
| let mut port = TTYPort::open(&serialport::new(&name, 0)).expect("unable to open"); |
| let mut buffer = [0u8; 2]; |
| let amount = port.read_exact(&mut buffer); |
| output_sink |
| .send(String::from_utf8(buffer.to_vec()).expect("buffer not read as valid utf-8")) |
| .expect("unable to send from thread"); |
| }); |
| |
| reader_thread.join().expect("unable to join sink thread"); |
| assert_eq!(output_stream.recv().unwrap(), "12"); |
| } |
| |
| // On Mac this should work (in fact used to in b77768a) but now fails. It's not functionality that |
| // should be required, and the ptys work otherwise. So going to just disable this test instead. |
| #[test] |
| #[cfg_attr(any(target_os = "ios", target_os = "macos"), ignore)] |
| fn test_ttyport_set_standard_baud() { |
| // `master` must be used here as Dropping it causes slave to be deleted by the OS. |
| // TODO: Convert this to a statement-level attribute once |
| // https://github.com/rust-lang/rust/issues/15701 is on stable. |
| // FIXME: Create a mutex across all tests for using `TTYPort::pair()` as it's not threadsafe |
| #![allow(unused_variables)] |
| let (master, mut slave) = TTYPort::pair().expect("Unable to create ptty pair"); |
| |
| slave.set_baud_rate(9600).unwrap(); |
| assert_eq!(slave.baud_rate().unwrap(), 9600); |
| slave.set_baud_rate(57600).unwrap(); |
| assert_eq!(slave.baud_rate().unwrap(), 57600); |
| slave.set_baud_rate(115_200).unwrap(); |
| assert_eq!(slave.baud_rate().unwrap(), 115_200); |
| } |
| |
| // On mac this fails because you can't set nonstandard baud rates for these virtual ports |
| #[test] |
| #[cfg_attr( |
| any( |
| target_os = "ios", |
| all(target_os = "linux", target_env = "musl"), |
| target_os = "macos" |
| ), |
| ignore |
| )] |
| fn test_ttyport_set_nonstandard_baud() { |
| // `master` must be used here as Dropping it causes slave to be deleted by the OS. |
| // TODO: Convert this to a statement-level attribute once |
| // https://github.com/rust-lang/rust/issues/15701 is on stable. |
| // FIXME: Create a mutex across all tests for using `TTYPort::pair()` as it's not threadsafe |
| #![allow(unused_variables)] |
| let (master, mut slave) = TTYPort::pair().expect("Unable to create ptty pair"); |
| |
| slave.set_baud_rate(10000).unwrap(); |
| assert_eq!(slave.baud_rate().unwrap(), 10000); |
| slave.set_baud_rate(60000).unwrap(); |
| assert_eq!(slave.baud_rate().unwrap(), 60000); |
| slave.set_baud_rate(1_200_000).unwrap(); |
| assert_eq!(slave.baud_rate().unwrap(), 1_200_000); |
| } |