]>
Commit | Line | Data |
---|---|---|
1b1a35ee XL |
1 | use crate::io::ErrorKind; |
2 | use crate::net::test::{next_test_ip4, next_test_ip6}; | |
3 | use crate::net::*; | |
4 | use crate::sync::mpsc::channel; | |
1b1a35ee XL |
5 | use crate::thread; |
6 | use crate::time::{Duration, Instant}; | |
7 | ||
8 | fn each_ip(f: &mut dyn FnMut(SocketAddr, SocketAddr)) { | |
9 | f(next_test_ip4(), next_test_ip4()); | |
10 | f(next_test_ip6(), next_test_ip6()); | |
11 | } | |
12 | ||
13 | macro_rules! t { | |
14 | ($e:expr) => { | |
15 | match $e { | |
16 | Ok(t) => t, | |
17 | Err(e) => panic!("received error for `{}`: {}", stringify!($e), e), | |
18 | } | |
19 | }; | |
20 | } | |
21 | ||
22 | #[test] | |
23 | fn bind_error() { | |
24 | match UdpSocket::bind("1.1.1.1:9999") { | |
25 | Ok(..) => panic!(), | |
26 | Err(e) => assert_eq!(e.kind(), ErrorKind::AddrNotAvailable), | |
27 | } | |
28 | } | |
29 | ||
30 | #[test] | |
31 | fn socket_smoke_test_ip4() { | |
32 | each_ip(&mut |server_ip, client_ip| { | |
33 | let (tx1, rx1) = channel(); | |
34 | let (tx2, rx2) = channel(); | |
35 | ||
36 | let _t = thread::spawn(move || { | |
37 | let client = t!(UdpSocket::bind(&client_ip)); | |
38 | rx1.recv().unwrap(); | |
39 | t!(client.send_to(&[99], &server_ip)); | |
40 | tx2.send(()).unwrap(); | |
41 | }); | |
42 | ||
43 | let server = t!(UdpSocket::bind(&server_ip)); | |
44 | tx1.send(()).unwrap(); | |
45 | let mut buf = [0]; | |
46 | let (nread, src) = t!(server.recv_from(&mut buf)); | |
47 | assert_eq!(nread, 1); | |
48 | assert_eq!(buf[0], 99); | |
49 | assert_eq!(src, client_ip); | |
50 | rx2.recv().unwrap(); | |
51 | }) | |
52 | } | |
53 | ||
54 | #[test] | |
55 | fn socket_name() { | |
56 | each_ip(&mut |addr, _| { | |
57 | let server = t!(UdpSocket::bind(&addr)); | |
58 | assert_eq!(addr, t!(server.local_addr())); | |
59 | }) | |
60 | } | |
61 | ||
62 | #[test] | |
63 | fn socket_peer() { | |
64 | each_ip(&mut |addr1, addr2| { | |
65 | let server = t!(UdpSocket::bind(&addr1)); | |
66 | assert_eq!(server.peer_addr().unwrap_err().kind(), ErrorKind::NotConnected); | |
67 | t!(server.connect(&addr2)); | |
68 | assert_eq!(addr2, t!(server.peer_addr())); | |
69 | }) | |
70 | } | |
71 | ||
72 | #[test] | |
73 | fn udp_clone_smoke() { | |
74 | each_ip(&mut |addr1, addr2| { | |
75 | let sock1 = t!(UdpSocket::bind(&addr1)); | |
76 | let sock2 = t!(UdpSocket::bind(&addr2)); | |
77 | ||
78 | let _t = thread::spawn(move || { | |
79 | let mut buf = [0, 0]; | |
80 | assert_eq!(sock2.recv_from(&mut buf).unwrap(), (1, addr1)); | |
81 | assert_eq!(buf[0], 1); | |
82 | t!(sock2.send_to(&[2], &addr1)); | |
83 | }); | |
84 | ||
85 | let sock3 = t!(sock1.try_clone()); | |
86 | ||
87 | let (tx1, rx1) = channel(); | |
88 | let (tx2, rx2) = channel(); | |
89 | let _t = thread::spawn(move || { | |
90 | rx1.recv().unwrap(); | |
91 | t!(sock3.send_to(&[1], &addr2)); | |
92 | tx2.send(()).unwrap(); | |
93 | }); | |
94 | tx1.send(()).unwrap(); | |
95 | let mut buf = [0, 0]; | |
96 | assert_eq!(sock1.recv_from(&mut buf).unwrap(), (1, addr2)); | |
97 | rx2.recv().unwrap(); | |
98 | }) | |
99 | } | |
100 | ||
101 | #[test] | |
102 | fn udp_clone_two_read() { | |
103 | each_ip(&mut |addr1, addr2| { | |
104 | let sock1 = t!(UdpSocket::bind(&addr1)); | |
105 | let sock2 = t!(UdpSocket::bind(&addr2)); | |
106 | let (tx1, rx) = channel(); | |
107 | let tx2 = tx1.clone(); | |
108 | ||
109 | let _t = thread::spawn(move || { | |
110 | t!(sock2.send_to(&[1], &addr1)); | |
111 | rx.recv().unwrap(); | |
112 | t!(sock2.send_to(&[2], &addr1)); | |
113 | rx.recv().unwrap(); | |
114 | }); | |
115 | ||
116 | let sock3 = t!(sock1.try_clone()); | |
117 | ||
118 | let (done, rx) = channel(); | |
119 | let _t = thread::spawn(move || { | |
120 | let mut buf = [0, 0]; | |
121 | t!(sock3.recv_from(&mut buf)); | |
122 | tx2.send(()).unwrap(); | |
123 | done.send(()).unwrap(); | |
124 | }); | |
125 | let mut buf = [0, 0]; | |
126 | t!(sock1.recv_from(&mut buf)); | |
127 | tx1.send(()).unwrap(); | |
128 | ||
129 | rx.recv().unwrap(); | |
130 | }) | |
131 | } | |
132 | ||
133 | #[test] | |
134 | fn udp_clone_two_write() { | |
135 | each_ip(&mut |addr1, addr2| { | |
136 | let sock1 = t!(UdpSocket::bind(&addr1)); | |
137 | let sock2 = t!(UdpSocket::bind(&addr2)); | |
138 | ||
139 | let (tx, rx) = channel(); | |
140 | let (serv_tx, serv_rx) = channel(); | |
141 | ||
142 | let _t = thread::spawn(move || { | |
143 | let mut buf = [0, 1]; | |
144 | rx.recv().unwrap(); | |
145 | t!(sock2.recv_from(&mut buf)); | |
146 | serv_tx.send(()).unwrap(); | |
147 | }); | |
148 | ||
149 | let sock3 = t!(sock1.try_clone()); | |
150 | ||
151 | let (done, rx) = channel(); | |
152 | let tx2 = tx.clone(); | |
153 | let _t = thread::spawn(move || { | |
29967ef6 XL |
154 | if sock3.send_to(&[1], &addr2).is_ok() { |
155 | let _ = tx2.send(()); | |
1b1a35ee XL |
156 | } |
157 | done.send(()).unwrap(); | |
158 | }); | |
29967ef6 XL |
159 | if sock1.send_to(&[2], &addr2).is_ok() { |
160 | let _ = tx.send(()); | |
1b1a35ee XL |
161 | } |
162 | drop(tx); | |
163 | ||
164 | rx.recv().unwrap(); | |
165 | serv_rx.recv().unwrap(); | |
166 | }) | |
167 | } | |
168 | ||
169 | #[test] | |
170 | fn debug() { | |
171 | let name = if cfg!(windows) { "socket" } else { "fd" }; | |
172 | let socket_addr = next_test_ip4(); | |
173 | ||
174 | let udpsock = t!(UdpSocket::bind(&socket_addr)); | |
94222f64 | 175 | let udpsock_inner = udpsock.0.socket().as_raw(); |
1b1a35ee XL |
176 | let compare = format!("UdpSocket {{ addr: {:?}, {}: {:?} }}", socket_addr, name, udpsock_inner); |
177 | assert_eq!(format!("{:?}", udpsock), compare); | |
178 | } | |
179 | ||
180 | // FIXME: re-enabled openbsd/netbsd tests once their socket timeout code | |
181 | // no longer has rounding errors. | |
182 | // VxWorks ignores SO_SNDTIMEO. | |
183 | #[cfg_attr(any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks"), ignore)] | |
184 | #[test] | |
185 | fn timeouts() { | |
186 | let addr = next_test_ip4(); | |
187 | ||
188 | let stream = t!(UdpSocket::bind(&addr)); | |
189 | let dur = Duration::new(15410, 0); | |
190 | ||
191 | assert_eq!(None, t!(stream.read_timeout())); | |
192 | ||
193 | t!(stream.set_read_timeout(Some(dur))); | |
194 | assert_eq!(Some(dur), t!(stream.read_timeout())); | |
195 | ||
196 | assert_eq!(None, t!(stream.write_timeout())); | |
197 | ||
198 | t!(stream.set_write_timeout(Some(dur))); | |
199 | assert_eq!(Some(dur), t!(stream.write_timeout())); | |
200 | ||
201 | t!(stream.set_read_timeout(None)); | |
202 | assert_eq!(None, t!(stream.read_timeout())); | |
203 | ||
204 | t!(stream.set_write_timeout(None)); | |
205 | assert_eq!(None, t!(stream.write_timeout())); | |
206 | } | |
207 | ||
208 | #[test] | |
209 | fn test_read_timeout() { | |
210 | let addr = next_test_ip4(); | |
211 | ||
212 | let stream = t!(UdpSocket::bind(&addr)); | |
213 | t!(stream.set_read_timeout(Some(Duration::from_millis(1000)))); | |
214 | ||
215 | let mut buf = [0; 10]; | |
216 | ||
217 | let start = Instant::now(); | |
218 | loop { | |
219 | let kind = stream.recv_from(&mut buf).err().expect("expected error").kind(); | |
220 | if kind != ErrorKind::Interrupted { | |
221 | assert!( | |
222 | kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut, | |
223 | "unexpected_error: {:?}", | |
224 | kind | |
225 | ); | |
226 | break; | |
227 | } | |
228 | } | |
229 | assert!(start.elapsed() > Duration::from_millis(400)); | |
230 | } | |
231 | ||
232 | #[test] | |
233 | fn test_read_with_timeout() { | |
234 | let addr = next_test_ip4(); | |
235 | ||
236 | let stream = t!(UdpSocket::bind(&addr)); | |
237 | t!(stream.set_read_timeout(Some(Duration::from_millis(1000)))); | |
238 | ||
239 | t!(stream.send_to(b"hello world", &addr)); | |
240 | ||
241 | let mut buf = [0; 11]; | |
242 | t!(stream.recv_from(&mut buf)); | |
243 | assert_eq!(b"hello world", &buf[..]); | |
244 | ||
245 | let start = Instant::now(); | |
246 | loop { | |
247 | let kind = stream.recv_from(&mut buf).err().expect("expected error").kind(); | |
248 | if kind != ErrorKind::Interrupted { | |
249 | assert!( | |
250 | kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut, | |
251 | "unexpected_error: {:?}", | |
252 | kind | |
253 | ); | |
254 | break; | |
255 | } | |
256 | } | |
257 | assert!(start.elapsed() > Duration::from_millis(400)); | |
258 | } | |
259 | ||
260 | // Ensure the `set_read_timeout` and `set_write_timeout` calls return errors | |
261 | // when passed zero Durations | |
262 | #[test] | |
263 | fn test_timeout_zero_duration() { | |
264 | let addr = next_test_ip4(); | |
265 | ||
266 | let socket = t!(UdpSocket::bind(&addr)); | |
267 | ||
268 | let result = socket.set_write_timeout(Some(Duration::new(0, 0))); | |
269 | let err = result.unwrap_err(); | |
270 | assert_eq!(err.kind(), ErrorKind::InvalidInput); | |
271 | ||
272 | let result = socket.set_read_timeout(Some(Duration::new(0, 0))); | |
273 | let err = result.unwrap_err(); | |
274 | assert_eq!(err.kind(), ErrorKind::InvalidInput); | |
275 | } | |
276 | ||
277 | #[test] | |
278 | fn connect_send_recv() { | |
279 | let addr = next_test_ip4(); | |
280 | ||
281 | let socket = t!(UdpSocket::bind(&addr)); | |
282 | t!(socket.connect(addr)); | |
283 | ||
284 | t!(socket.send(b"hello world")); | |
285 | ||
286 | let mut buf = [0; 11]; | |
287 | t!(socket.recv(&mut buf)); | |
288 | assert_eq!(b"hello world", &buf[..]); | |
289 | } | |
290 | ||
291 | #[test] | |
292 | fn connect_send_peek_recv() { | |
293 | each_ip(&mut |addr, _| { | |
294 | let socket = t!(UdpSocket::bind(&addr)); | |
295 | t!(socket.connect(addr)); | |
296 | ||
297 | t!(socket.send(b"hello world")); | |
298 | ||
299 | for _ in 1..3 { | |
300 | let mut buf = [0; 11]; | |
301 | let size = t!(socket.peek(&mut buf)); | |
302 | assert_eq!(b"hello world", &buf[..]); | |
303 | assert_eq!(size, 11); | |
304 | } | |
305 | ||
306 | let mut buf = [0; 11]; | |
307 | let size = t!(socket.recv(&mut buf)); | |
308 | assert_eq!(b"hello world", &buf[..]); | |
309 | assert_eq!(size, 11); | |
310 | }) | |
311 | } | |
312 | ||
313 | #[test] | |
314 | fn peek_from() { | |
315 | each_ip(&mut |addr, _| { | |
316 | let socket = t!(UdpSocket::bind(&addr)); | |
317 | t!(socket.send_to(b"hello world", &addr)); | |
318 | ||
319 | for _ in 1..3 { | |
320 | let mut buf = [0; 11]; | |
321 | let (size, _) = t!(socket.peek_from(&mut buf)); | |
322 | assert_eq!(b"hello world", &buf[..]); | |
323 | assert_eq!(size, 11); | |
324 | } | |
325 | ||
326 | let mut buf = [0; 11]; | |
327 | let (size, _) = t!(socket.recv_from(&mut buf)); | |
328 | assert_eq!(b"hello world", &buf[..]); | |
329 | assert_eq!(size, 11); | |
330 | }) | |
331 | } | |
332 | ||
333 | #[test] | |
334 | fn ttl() { | |
335 | let ttl = 100; | |
336 | ||
337 | let addr = next_test_ip4(); | |
338 | ||
339 | let stream = t!(UdpSocket::bind(&addr)); | |
340 | ||
341 | t!(stream.set_ttl(ttl)); | |
342 | assert_eq!(ttl, t!(stream.ttl())); | |
343 | } | |
344 | ||
345 | #[test] | |
346 | fn set_nonblocking() { | |
347 | each_ip(&mut |addr, _| { | |
348 | let socket = t!(UdpSocket::bind(&addr)); | |
349 | ||
350 | t!(socket.set_nonblocking(true)); | |
351 | t!(socket.set_nonblocking(false)); | |
352 | ||
353 | t!(socket.connect(addr)); | |
354 | ||
355 | t!(socket.set_nonblocking(false)); | |
356 | t!(socket.set_nonblocking(true)); | |
357 | ||
358 | let mut buf = [0]; | |
359 | match socket.recv(&mut buf) { | |
360 | Ok(_) => panic!("expected error"), | |
361 | Err(ref e) if e.kind() == ErrorKind::WouldBlock => {} | |
362 | Err(e) => panic!("unexpected error {}", e), | |
363 | } | |
364 | }) | |
365 | } |