• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 mod config;
2 
3 use config::{hw_config, HardwareConfig};
4 use rstest::rstest;
5 use serialport::*;
6 use std::io::Read;
7 use std::thread;
8 use std::time::{Duration, Instant};
9 
10 #[rstest]
11 #[case(1, Vec::from(b"abcdef"))]
12 #[case(
13     20,
14     Vec::from(b"0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~")
15 )]
16 #[cfg_attr(feature = "ignore-hardware-tests", ignore)]
test_read_returns_available_data_before_timeout( hw_config: HardwareConfig, #[case] chunk_size: usize, #[case] message: Vec<u8>, )17 fn test_read_returns_available_data_before_timeout(
18     hw_config: HardwareConfig,
19     #[case] chunk_size: usize,
20     #[case] message: Vec<u8>,
21 ) {
22     let send_period = Duration::from_millis(500);
23     let receive_timeout = Duration::from_millis(3000);
24     let marign = Duration::from_millis(100);
25 
26     let mut sender = serialport::new(hw_config.port_1, 115200).open().unwrap();
27     let mut receiver = serialport::new(hw_config.port_2, 115200)
28         .timeout(receive_timeout)
29         .open()
30         .unwrap();
31 
32     sender.clear(ClearBuffer::All).unwrap();
33     receiver.clear(ClearBuffer::All).unwrap();
34 
35     let expected_message = message.clone();
36     let receiver_thread = thread::spawn(move || {
37         let chunk_timeout = send_period + marign;
38         assert!(receiver.timeout() > 3 * chunk_timeout);
39 
40         let mut received_message = Vec::with_capacity(expected_message.len());
41 
42         loop {
43             let chunk_start = Instant::now();
44             let expected_chunk_until = chunk_start + chunk_timeout;
45 
46             let mut buffer = [0u8; 1024];
47             assert!(buffer.len() > expected_message.len());
48 
49             // Try to read more data than we are expecting and expect some data to be available
50             // after the send period (plus some margin).
51             match receiver.read(&mut buffer) {
52                 Ok(read) => {
53                     assert!(expected_chunk_until > Instant::now());
54                     assert!(read > 0);
55                     println!(
56                         "receive: {} bytes after waiting {} ms",
57                         read,
58                         (Instant::now() - chunk_start).as_millis()
59                     );
60                     received_message.extend_from_slice(&buffer[..read]);
61                 }
62                 e => panic!("unexpected error {:?}", e),
63             }
64 
65             if received_message.len() >= expected_message.len() {
66                 break;
67             }
68         }
69 
70         assert_eq!(expected_message, received_message);
71     });
72 
73     let sender_thread = thread::spawn(move || {
74         let mut next = Instant::now();
75 
76         for chunk in message.chunks(chunk_size) {
77             sender.write_all(chunk).unwrap();
78             sender.flush().unwrap();
79 
80             println!("send: {} bytes", chunk.len());
81 
82             next += send_period;
83             thread::sleep(next - Instant::now());
84         }
85     });
86 
87     sender_thread.join().unwrap();
88     receiver_thread.join().unwrap();
89 }
90 
91 #[rstest]
92 #[case(b"a")]
93 #[case(b"0123456789")]
94 #[case(b"0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~")]
95 #[cfg_attr(feature = "ignore-hardware-tests", ignore)]
test_timeout_zero(hw_config: HardwareConfig, #[case] message: &[u8])96 fn test_timeout_zero(hw_config: HardwareConfig, #[case] message: &[u8]) {
97     let timeout = Duration::ZERO;
98     let margin = Duration::from_millis(100);
99 
100     let mut sender = serialport::new(hw_config.port_1, 115200).open().unwrap();
101     let mut receiver = serialport::new(hw_config.port_2, 115200)
102         .timeout(timeout)
103         .open()
104         .unwrap();
105     let mut buffer: [u8; 1024] = [0xff; 1024];
106 
107     sender.clear(ClearBuffer::All).unwrap();
108     receiver.clear(ClearBuffer::All).unwrap();
109 
110     sender.write_all(message).unwrap();
111     sender.flush().unwrap();
112     let flushed_at = Instant::now();
113 
114     let expected_until = flushed_at + timeout + margin;
115     let mut timeouts = 0usize;
116 
117     loop {
118         match receiver.read(&mut buffer) {
119             Ok(read) => {
120                 assert!(read > 0);
121                 println!(
122                     "read: {} bytes of {} after {} timeouts/{} ms",
123                     read,
124                     message.len(),
125                     timeouts,
126                     (Instant::now() - flushed_at).as_millis()
127                 );
128                 assert_eq!(message[..read], buffer[..read]);
129                 break;
130             }
131             Err(e) => {
132                 assert_eq!(e.kind(), std::io::ErrorKind::TimedOut);
133                 timeouts += 1;
134             }
135         }
136 
137         assert!(expected_until > Instant::now());
138     }
139 }
140 
141 #[rstest]
142 #[case(Duration::from_millis(10))]
143 #[case(Duration::from_millis(100))]
144 #[case(Duration::from_millis(1000))]
145 #[cfg_attr(feature = "ignore-hardware-tests", ignore)]
test_timeout_greater_zero(hw_config: HardwareConfig, #[case] timeout: Duration)146 fn test_timeout_greater_zero(hw_config: HardwareConfig, #[case] timeout: Duration) {
147     let margin = Duration::from_millis(100);
148 
149     let mut sender = serialport::new(hw_config.port_1, 115200).open().unwrap();
150     let mut receiver = serialport::new(hw_config.port_2, 115200)
151         .timeout(timeout)
152         .open()
153         .unwrap();
154 
155     let message =
156         b"0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
157     let mut buffer: [u8; 1024] = [0xff; 1024];
158 
159     sender.clear(ClearBuffer::All).unwrap();
160     receiver.clear(ClearBuffer::All).unwrap();
161 
162     sender.write_all(message).unwrap();
163     sender.flush().unwrap();
164 
165     let flushed_at = Instant::now();
166 
167     let read = receiver.read(&mut buffer).unwrap();
168     let read_at = Instant::now();
169 
170     println!(
171         "read: {} bytes of {} after {} ms",
172         read,
173         message.len(),
174         (Instant::now() - flushed_at).as_millis()
175     );
176 
177     assert!(read > 0);
178     assert!(flushed_at + timeout + margin > read_at);
179     assert_eq!(buffer[..read], message[..read]);
180 }
181 
182 /// Checks that reading data with a timeout of `Duration::MAX` returns some data and no error. It
183 /// does not check the actual timeout for obvious reason.
184 #[rstest]
185 #[cfg_attr(feature = "ignore-hardware-tests", ignore)]
test_timeout_max(hw_config: HardwareConfig)186 fn test_timeout_max(hw_config: HardwareConfig) {
187     let sleep = Duration::from_millis(3000);
188     let margin = Duration::from_millis(500);
189     let mut sender = serialport::new(hw_config.port_1, 115200).open().unwrap();
190     let mut receiver = serialport::new(hw_config.port_2, 115200)
191         .timeout(Duration::MAX)
192         .open()
193         .unwrap();
194 
195     let message =
196         b"0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
197     let mut buffer: [u8; 1024] = [0xff; 1024];
198 
199     sender.clear(ClearBuffer::All).unwrap();
200     receiver.clear(ClearBuffer::All).unwrap();
201 
202     let started_at = Instant::now();
203 
204     let sender_thread = thread::spawn(move || {
205         thread::sleep(sleep);
206 
207         sender.write_all(message).unwrap();
208         sender.flush().unwrap();
209     });
210 
211     let read = receiver.read(&mut buffer).unwrap();
212     let read_at = Instant::now();
213 
214     println!(
215         "read: {} bytes of {} after {} ms",
216         read,
217         message.len(),
218         (Instant::now() - started_at).as_millis()
219     );
220 
221     assert!(read > 0);
222     assert!(read_at > started_at + sleep);
223     assert!(read_at < started_at + sleep + margin);
224     assert_eq!(buffer[..read], message[..read]);
225 
226     sender_thread.join().unwrap();
227 }
228