]> git.proxmox.com Git - rustc.git/blame - library/std/src/net/tcp/tests.rs
New upstream version 1.61.0+dfsg1
[rustc.git] / library / std / src / net / tcp / tests.rs
CommitLineData
1b1a35ee
XL
1use crate::fmt;
2use crate::io::prelude::*;
3use crate::io::{ErrorKind, IoSlice, IoSliceMut};
4use crate::net::test::{next_test_ip4, next_test_ip6};
5use crate::net::*;
6use crate::sync::mpsc::channel;
7use crate::thread;
8use crate::time::{Duration, Instant};
9
10fn each_ip(f: &mut dyn FnMut(SocketAddr)) {
11 f(next_test_ip4());
12 f(next_test_ip6());
13}
14
15macro_rules! t {
16 ($e:expr) => {
17 match $e {
18 Ok(t) => t,
19 Err(e) => panic!("received error for `{}`: {}", stringify!($e), e),
20 }
21 };
22}
23
24#[test]
25fn bind_error() {
26 match TcpListener::bind("1.1.1.1:9999") {
27 Ok(..) => panic!(),
28 Err(e) => assert_eq!(e.kind(), ErrorKind::AddrNotAvailable),
29 }
30}
31
32#[test]
33fn connect_error() {
34 match TcpStream::connect("0.0.0.0:1") {
35 Ok(..) => panic!(),
36 Err(e) => assert!(
37 e.kind() == ErrorKind::ConnectionRefused
38 || e.kind() == ErrorKind::InvalidInput
39 || e.kind() == ErrorKind::AddrInUse
40 || e.kind() == ErrorKind::AddrNotAvailable,
41 "bad error: {} {:?}",
42 e,
43 e.kind()
44 ),
45 }
46}
47
48#[test]
49fn listen_localhost() {
50 let socket_addr = next_test_ip4();
51 let listener = t!(TcpListener::bind(&socket_addr));
52
53 let _t = thread::spawn(move || {
54 let mut stream = t!(TcpStream::connect(&("localhost", socket_addr.port())));
55 t!(stream.write(&[144]));
56 });
57
58 let mut stream = t!(listener.accept()).0;
59 let mut buf = [0];
60 t!(stream.read(&mut buf));
61 assert!(buf[0] == 144);
62}
63
64#[test]
65fn connect_loopback() {
66 each_ip(&mut |addr| {
67 let acceptor = t!(TcpListener::bind(&addr));
68
69 let _t = thread::spawn(move || {
70 let host = match addr {
71 SocketAddr::V4(..) => "127.0.0.1",
72 SocketAddr::V6(..) => "::1",
73 };
74 let mut stream = t!(TcpStream::connect(&(host, addr.port())));
75 t!(stream.write(&[66]));
76 });
77
78 let mut stream = t!(acceptor.accept()).0;
79 let mut buf = [0];
80 t!(stream.read(&mut buf));
81 assert!(buf[0] == 66);
82 })
83}
84
85#[test]
86fn smoke_test() {
87 each_ip(&mut |addr| {
88 let acceptor = t!(TcpListener::bind(&addr));
89
90 let (tx, rx) = channel();
91 let _t = thread::spawn(move || {
92 let mut stream = t!(TcpStream::connect(&addr));
93 t!(stream.write(&[99]));
94 tx.send(t!(stream.local_addr())).unwrap();
95 });
96
97 let (mut stream, addr) = t!(acceptor.accept());
98 let mut buf = [0];
99 t!(stream.read(&mut buf));
100 assert!(buf[0] == 99);
101 assert_eq!(addr, t!(rx.recv()));
102 })
103}
104
105#[test]
106fn read_eof() {
107 each_ip(&mut |addr| {
108 let acceptor = t!(TcpListener::bind(&addr));
109
110 let _t = thread::spawn(move || {
111 let _stream = t!(TcpStream::connect(&addr));
112 // Close
113 });
114
115 let mut stream = t!(acceptor.accept()).0;
116 let mut buf = [0];
117 let nread = t!(stream.read(&mut buf));
118 assert_eq!(nread, 0);
119 let nread = t!(stream.read(&mut buf));
120 assert_eq!(nread, 0);
121 })
122}
123
124#[test]
125fn write_close() {
126 each_ip(&mut |addr| {
127 let acceptor = t!(TcpListener::bind(&addr));
128
129 let (tx, rx) = channel();
130 let _t = thread::spawn(move || {
131 drop(t!(TcpStream::connect(&addr)));
132 tx.send(()).unwrap();
133 });
134
135 let mut stream = t!(acceptor.accept()).0;
136 rx.recv().unwrap();
137 let buf = [0];
138 match stream.write(&buf) {
139 Ok(..) => {}
140 Err(e) => {
141 assert!(
142 e.kind() == ErrorKind::ConnectionReset
143 || e.kind() == ErrorKind::BrokenPipe
144 || e.kind() == ErrorKind::ConnectionAborted,
5e7ed085 145 "unknown error: {e}"
1b1a35ee
XL
146 );
147 }
148 }
149 })
150}
151
152#[test]
153fn multiple_connect_serial() {
154 each_ip(&mut |addr| {
155 let max = 10;
156 let acceptor = t!(TcpListener::bind(&addr));
157
158 let _t = thread::spawn(move || {
159 for _ in 0..max {
160 let mut stream = t!(TcpStream::connect(&addr));
161 t!(stream.write(&[99]));
162 }
163 });
164
165 for stream in acceptor.incoming().take(max) {
166 let mut stream = t!(stream);
167 let mut buf = [0];
168 t!(stream.read(&mut buf));
169 assert_eq!(buf[0], 99);
170 }
171 })
172}
173
174#[test]
175fn multiple_connect_interleaved_greedy_schedule() {
176 const MAX: usize = 10;
177 each_ip(&mut |addr| {
178 let acceptor = t!(TcpListener::bind(&addr));
179
180 let _t = thread::spawn(move || {
181 let acceptor = acceptor;
182 for (i, stream) in acceptor.incoming().enumerate().take(MAX) {
183 // Start another thread to handle the connection
184 let _t = thread::spawn(move || {
185 let mut stream = t!(stream);
186 let mut buf = [0];
187 t!(stream.read(&mut buf));
188 assert!(buf[0] == i as u8);
189 });
190 }
191 });
192
193 connect(0, addr);
194 });
195
196 fn connect(i: usize, addr: SocketAddr) {
197 if i == MAX {
198 return;
199 }
200
201 let t = thread::spawn(move || {
202 let mut stream = t!(TcpStream::connect(&addr));
203 // Connect again before writing
204 connect(i + 1, addr);
205 t!(stream.write(&[i as u8]));
206 });
207 t.join().ok().expect("thread panicked");
208 }
209}
210
211#[test]
212fn multiple_connect_interleaved_lazy_schedule() {
213 const MAX: usize = 10;
214 each_ip(&mut |addr| {
215 let acceptor = t!(TcpListener::bind(&addr));
216
217 let _t = thread::spawn(move || {
218 for stream in acceptor.incoming().take(MAX) {
219 // Start another thread to handle the connection
220 let _t = thread::spawn(move || {
221 let mut stream = t!(stream);
222 let mut buf = [0];
223 t!(stream.read(&mut buf));
224 assert!(buf[0] == 99);
225 });
226 }
227 });
228
229 connect(0, addr);
230 });
231
232 fn connect(i: usize, addr: SocketAddr) {
233 if i == MAX {
234 return;
235 }
236
237 let t = thread::spawn(move || {
238 let mut stream = t!(TcpStream::connect(&addr));
239 connect(i + 1, addr);
240 t!(stream.write(&[99]));
241 });
242 t.join().ok().expect("thread panicked");
243 }
244}
245
246#[test]
247fn socket_and_peer_name() {
248 each_ip(&mut |addr| {
249 let listener = t!(TcpListener::bind(&addr));
250 let so_name = t!(listener.local_addr());
251 assert_eq!(addr, so_name);
252 let _t = thread::spawn(move || {
253 t!(listener.accept());
254 });
255
256 let stream = t!(TcpStream::connect(&addr));
257 assert_eq!(addr, t!(stream.peer_addr()));
258 })
259}
260
261#[test]
262fn partial_read() {
263 each_ip(&mut |addr| {
264 let (tx, rx) = channel();
265 let srv = t!(TcpListener::bind(&addr));
266 let _t = thread::spawn(move || {
267 let mut cl = t!(srv.accept()).0;
268 cl.write(&[10]).unwrap();
269 let mut b = [0];
270 t!(cl.read(&mut b));
271 tx.send(()).unwrap();
272 });
273
274 let mut c = t!(TcpStream::connect(&addr));
275 let mut b = [0; 10];
276 assert_eq!(c.read(&mut b).unwrap(), 1);
277 t!(c.write(&[1]));
278 rx.recv().unwrap();
279 })
280}
281
282#[test]
283fn read_vectored() {
284 each_ip(&mut |addr| {
285 let srv = t!(TcpListener::bind(&addr));
286 let mut s1 = t!(TcpStream::connect(&addr));
287 let mut s2 = t!(srv.accept()).0;
288
289 let len = s1.write(&[10, 11, 12]).unwrap();
290 assert_eq!(len, 3);
291
292 let mut a = [];
293 let mut b = [0];
294 let mut c = [0; 3];
295 let len = t!(s2.read_vectored(&mut [
296 IoSliceMut::new(&mut a),
297 IoSliceMut::new(&mut b),
298 IoSliceMut::new(&mut c)
299 ],));
300 assert!(len > 0);
301 assert_eq!(b, [10]);
302 // some implementations don't support readv, so we may only fill the first buffer
303 assert!(len == 1 || c == [11, 12, 0]);
304 })
305}
306
307#[test]
308fn write_vectored() {
309 each_ip(&mut |addr| {
310 let srv = t!(TcpListener::bind(&addr));
311 let mut s1 = t!(TcpStream::connect(&addr));
312 let mut s2 = t!(srv.accept()).0;
313
314 let a = [];
315 let b = [10];
316 let c = [11, 12];
317 t!(s1.write_vectored(&[IoSlice::new(&a), IoSlice::new(&b), IoSlice::new(&c)]));
318
319 let mut buf = [0; 4];
320 let len = t!(s2.read(&mut buf));
321 // some implementations don't support writev, so we may only write the first buffer
322 if len == 1 {
323 assert_eq!(buf, [10, 0, 0, 0]);
324 } else {
325 assert_eq!(len, 3);
326 assert_eq!(buf, [10, 11, 12, 0]);
327 }
328 })
329}
330
331#[test]
332fn double_bind() {
333 each_ip(&mut |addr| {
334 let listener1 = t!(TcpListener::bind(&addr));
335 match TcpListener::bind(&addr) {
336 Ok(listener2) => panic!(
337 "This system (perhaps due to options set by TcpListener::bind) \
338 permits double binding: {:?} and {:?}",
339 listener1, listener2
340 ),
341 Err(e) => {
342 assert!(
343 e.kind() == ErrorKind::ConnectionRefused
136023e0 344 || e.kind() == ErrorKind::Uncategorized
1b1a35ee
XL
345 || e.kind() == ErrorKind::AddrInUse,
346 "unknown error: {} {:?}",
347 e,
348 e.kind()
349 );
350 }
351 }
352 })
353}
354
355#[test]
356fn tcp_clone_smoke() {
357 each_ip(&mut |addr| {
358 let acceptor = t!(TcpListener::bind(&addr));
359
360 let _t = thread::spawn(move || {
361 let mut s = t!(TcpStream::connect(&addr));
362 let mut buf = [0, 0];
363 assert_eq!(s.read(&mut buf).unwrap(), 1);
364 assert_eq!(buf[0], 1);
365 t!(s.write(&[2]));
366 });
367
368 let mut s1 = t!(acceptor.accept()).0;
369 let s2 = t!(s1.try_clone());
370
371 let (tx1, rx1) = channel();
372 let (tx2, rx2) = channel();
373 let _t = thread::spawn(move || {
374 let mut s2 = s2;
375 rx1.recv().unwrap();
376 t!(s2.write(&[1]));
377 tx2.send(()).unwrap();
378 });
379 tx1.send(()).unwrap();
380 let mut buf = [0, 0];
381 assert_eq!(s1.read(&mut buf).unwrap(), 1);
382 rx2.recv().unwrap();
383 })
384}
385
386#[test]
387fn tcp_clone_two_read() {
388 each_ip(&mut |addr| {
389 let acceptor = t!(TcpListener::bind(&addr));
390 let (tx1, rx) = channel();
391 let tx2 = tx1.clone();
392
393 let _t = thread::spawn(move || {
394 let mut s = t!(TcpStream::connect(&addr));
395 t!(s.write(&[1]));
396 rx.recv().unwrap();
397 t!(s.write(&[2]));
398 rx.recv().unwrap();
399 });
400
401 let mut s1 = t!(acceptor.accept()).0;
402 let s2 = t!(s1.try_clone());
403
404 let (done, rx) = channel();
405 let _t = thread::spawn(move || {
406 let mut s2 = s2;
407 let mut buf = [0, 0];
408 t!(s2.read(&mut buf));
409 tx2.send(()).unwrap();
410 done.send(()).unwrap();
411 });
412 let mut buf = [0, 0];
413 t!(s1.read(&mut buf));
414 tx1.send(()).unwrap();
415
416 rx.recv().unwrap();
417 })
418}
419
420#[test]
421fn tcp_clone_two_write() {
422 each_ip(&mut |addr| {
423 let acceptor = t!(TcpListener::bind(&addr));
424
425 let _t = thread::spawn(move || {
426 let mut s = t!(TcpStream::connect(&addr));
427 let mut buf = [0, 1];
428 t!(s.read(&mut buf));
429 t!(s.read(&mut buf));
430 });
431
432 let mut s1 = t!(acceptor.accept()).0;
433 let s2 = t!(s1.try_clone());
434
435 let (done, rx) = channel();
436 let _t = thread::spawn(move || {
437 let mut s2 = s2;
438 t!(s2.write(&[1]));
439 done.send(()).unwrap();
440 });
441 t!(s1.write(&[2]));
442
443 rx.recv().unwrap();
444 })
445}
446
447#[test]
448// FIXME: https://github.com/fortanix/rust-sgx/issues/110
449#[cfg_attr(target_env = "sgx", ignore)]
450fn shutdown_smoke() {
451 each_ip(&mut |addr| {
452 let a = t!(TcpListener::bind(&addr));
453 let _t = thread::spawn(move || {
454 let mut c = t!(a.accept()).0;
455 let mut b = [0];
456 assert_eq!(c.read(&mut b).unwrap(), 0);
457 t!(c.write(&[1]));
458 });
459
460 let mut s = t!(TcpStream::connect(&addr));
461 t!(s.shutdown(Shutdown::Write));
462 assert!(s.write(&[1]).is_err());
463 let mut b = [0, 0];
464 assert_eq!(t!(s.read(&mut b)), 1);
465 assert_eq!(b[0], 1);
466 })
467}
468
469#[test]
470// FIXME: https://github.com/fortanix/rust-sgx/issues/110
471#[cfg_attr(target_env = "sgx", ignore)]
472fn close_readwrite_smoke() {
473 each_ip(&mut |addr| {
474 let a = t!(TcpListener::bind(&addr));
475 let (tx, rx) = channel::<()>();
476 let _t = thread::spawn(move || {
477 let _s = t!(a.accept());
478 let _ = rx.recv();
479 });
480
481 let mut b = [0];
482 let mut s = t!(TcpStream::connect(&addr));
483 let mut s2 = t!(s.try_clone());
484
485 // closing should prevent reads/writes
486 t!(s.shutdown(Shutdown::Write));
487 assert!(s.write(&[0]).is_err());
488 t!(s.shutdown(Shutdown::Read));
489 assert_eq!(s.read(&mut b).unwrap(), 0);
490
491 // closing should affect previous handles
492 assert!(s2.write(&[0]).is_err());
493 assert_eq!(s2.read(&mut b).unwrap(), 0);
494
495 // closing should affect new handles
496 let mut s3 = t!(s.try_clone());
497 assert!(s3.write(&[0]).is_err());
498 assert_eq!(s3.read(&mut b).unwrap(), 0);
499
500 // make sure these don't die
501 let _ = s2.shutdown(Shutdown::Read);
502 let _ = s2.shutdown(Shutdown::Write);
503 let _ = s3.shutdown(Shutdown::Read);
504 let _ = s3.shutdown(Shutdown::Write);
505 drop(tx);
506 })
507}
508
509#[test]
5e7ed085 510#[cfg_attr(target_env = "sgx", ignore)]
1b1a35ee
XL
511fn close_read_wakes_up() {
512 each_ip(&mut |addr| {
513 let a = t!(TcpListener::bind(&addr));
514 let (tx1, rx) = channel::<()>();
515 let _t = thread::spawn(move || {
516 let _s = t!(a.accept());
517 let _ = rx.recv();
518 });
519
520 let s = t!(TcpStream::connect(&addr));
521 let s2 = t!(s.try_clone());
522 let (tx, rx) = channel();
523 let _t = thread::spawn(move || {
524 let mut s2 = s2;
525 assert_eq!(t!(s2.read(&mut [0])), 0);
526 tx.send(()).unwrap();
527 });
528 // this should wake up the child thread
529 t!(s.shutdown(Shutdown::Read));
530
531 // this test will never finish if the child doesn't wake up
532 rx.recv().unwrap();
533 drop(tx1);
534 })
535}
536
537#[test]
538fn clone_while_reading() {
539 each_ip(&mut |addr| {
540 let accept = t!(TcpListener::bind(&addr));
541
542 // Enqueue a thread to write to a socket
543 let (tx, rx) = channel();
544 let (txdone, rxdone) = channel();
545 let txdone2 = txdone.clone();
546 let _t = thread::spawn(move || {
547 let mut tcp = t!(TcpStream::connect(&addr));
548 rx.recv().unwrap();
549 t!(tcp.write(&[0]));
550 txdone2.send(()).unwrap();
551 });
552
553 // Spawn off a reading clone
554 let tcp = t!(accept.accept()).0;
555 let tcp2 = t!(tcp.try_clone());
556 let txdone3 = txdone.clone();
557 let _t = thread::spawn(move || {
558 let mut tcp2 = tcp2;
559 t!(tcp2.read(&mut [0]));
560 txdone3.send(()).unwrap();
561 });
562
563 // Try to ensure that the reading clone is indeed reading
564 for _ in 0..50 {
565 thread::yield_now();
566 }
567
568 // clone the handle again while it's reading, then let it finish the
569 // read.
570 let _ = t!(tcp.try_clone());
571 tx.send(()).unwrap();
572 rxdone.recv().unwrap();
573 rxdone.recv().unwrap();
574 })
575}
576
577#[test]
578fn clone_accept_smoke() {
579 each_ip(&mut |addr| {
580 let a = t!(TcpListener::bind(&addr));
581 let a2 = t!(a.try_clone());
582
583 let _t = thread::spawn(move || {
584 let _ = TcpStream::connect(&addr);
585 });
586 let _t = thread::spawn(move || {
587 let _ = TcpStream::connect(&addr);
588 });
589
590 t!(a.accept());
591 t!(a2.accept());
592 })
593}
594
595#[test]
596fn clone_accept_concurrent() {
597 each_ip(&mut |addr| {
598 let a = t!(TcpListener::bind(&addr));
599 let a2 = t!(a.try_clone());
600
601 let (tx, rx) = channel();
602 let tx2 = tx.clone();
603
604 let _t = thread::spawn(move || {
605 tx.send(t!(a.accept())).unwrap();
606 });
607 let _t = thread::spawn(move || {
608 tx2.send(t!(a2.accept())).unwrap();
609 });
610
611 let _t = thread::spawn(move || {
612 let _ = TcpStream::connect(&addr);
613 });
614 let _t = thread::spawn(move || {
615 let _ = TcpStream::connect(&addr);
616 });
617
618 rx.recv().unwrap();
619 rx.recv().unwrap();
620 })
621}
622
623#[test]
624fn debug() {
625 #[cfg(not(target_env = "sgx"))]
626 fn render_socket_addr<'a>(addr: &'a SocketAddr) -> impl fmt::Debug + 'a {
627 addr
628 }
629 #[cfg(target_env = "sgx")]
630 fn render_socket_addr<'a>(addr: &'a SocketAddr) -> impl fmt::Debug + 'a {
631 addr.to_string()
632 }
633
634 #[cfg(target_env = "sgx")]
635 use crate::os::fortanix_sgx::io::AsRawFd;
636 #[cfg(unix)]
637 use crate::os::unix::io::AsRawFd;
638 #[cfg(not(windows))]
639 fn render_inner(addr: &dyn AsRawFd) -> impl fmt::Debug {
640 addr.as_raw_fd()
641 }
642 #[cfg(windows)]
643 fn render_inner(addr: &dyn crate::os::windows::io::AsRawSocket) -> impl fmt::Debug {
644 addr.as_raw_socket()
645 }
646
647 let inner_name = if cfg!(windows) { "socket" } else { "fd" };
648 let socket_addr = next_test_ip4();
649
650 let listener = t!(TcpListener::bind(&socket_addr));
651 let compare = format!(
652 "TcpListener {{ addr: {:?}, {}: {:?} }}",
653 render_socket_addr(&socket_addr),
654 inner_name,
655 render_inner(&listener)
656 );
5e7ed085 657 assert_eq!(format!("{listener:?}"), compare);
1b1a35ee
XL
658
659 let stream = t!(TcpStream::connect(&("localhost", socket_addr.port())));
660 let compare = format!(
661 "TcpStream {{ addr: {:?}, peer: {:?}, {}: {:?} }}",
662 render_socket_addr(&stream.local_addr().unwrap()),
663 render_socket_addr(&stream.peer_addr().unwrap()),
664 inner_name,
665 render_inner(&stream)
666 );
5e7ed085 667 assert_eq!(format!("{stream:?}"), compare);
1b1a35ee
XL
668}
669
670// FIXME: re-enabled openbsd tests once their socket timeout code
671// no longer has rounding errors.
672// VxWorks ignores SO_SNDTIMEO.
673#[cfg_attr(any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks"), ignore)]
674#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
675#[test]
676fn timeouts() {
677 let addr = next_test_ip4();
678 let listener = t!(TcpListener::bind(&addr));
679
680 let stream = t!(TcpStream::connect(&("localhost", addr.port())));
681 let dur = Duration::new(15410, 0);
682
683 assert_eq!(None, t!(stream.read_timeout()));
684
685 t!(stream.set_read_timeout(Some(dur)));
686 assert_eq!(Some(dur), t!(stream.read_timeout()));
687
688 assert_eq!(None, t!(stream.write_timeout()));
689
690 t!(stream.set_write_timeout(Some(dur)));
691 assert_eq!(Some(dur), t!(stream.write_timeout()));
692
693 t!(stream.set_read_timeout(None));
694 assert_eq!(None, t!(stream.read_timeout()));
695
696 t!(stream.set_write_timeout(None));
697 assert_eq!(None, t!(stream.write_timeout()));
698 drop(listener);
699}
700
701#[test]
702#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
703fn test_read_timeout() {
704 let addr = next_test_ip4();
705 let listener = t!(TcpListener::bind(&addr));
706
707 let mut stream = t!(TcpStream::connect(&("localhost", addr.port())));
708 t!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
709
710 let mut buf = [0; 10];
711 let start = Instant::now();
712 let kind = stream.read_exact(&mut buf).err().expect("expected error").kind();
713 assert!(
714 kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut,
715 "unexpected_error: {:?}",
716 kind
717 );
718 assert!(start.elapsed() > Duration::from_millis(400));
719 drop(listener);
720}
721
722#[test]
723#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
724fn test_read_with_timeout() {
725 let addr = next_test_ip4();
726 let listener = t!(TcpListener::bind(&addr));
727
728 let mut stream = t!(TcpStream::connect(&("localhost", addr.port())));
729 t!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
730
731 let mut other_end = t!(listener.accept()).0;
732 t!(other_end.write_all(b"hello world"));
733
734 let mut buf = [0; 11];
735 t!(stream.read(&mut buf));
736 assert_eq!(b"hello world", &buf[..]);
737
738 let start = Instant::now();
739 let kind = stream.read_exact(&mut buf).err().expect("expected error").kind();
740 assert!(
741 kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut,
742 "unexpected_error: {:?}",
743 kind
744 );
745 assert!(start.elapsed() > Duration::from_millis(400));
746 drop(listener);
747}
748
749// Ensure the `set_read_timeout` and `set_write_timeout` calls return errors
750// when passed zero Durations
751#[test]
752fn test_timeout_zero_duration() {
753 let addr = next_test_ip4();
754
755 let listener = t!(TcpListener::bind(&addr));
756 let stream = t!(TcpStream::connect(&addr));
757
758 let result = stream.set_write_timeout(Some(Duration::new(0, 0)));
759 let err = result.unwrap_err();
760 assert_eq!(err.kind(), ErrorKind::InvalidInput);
761
762 let result = stream.set_read_timeout(Some(Duration::new(0, 0)));
763 let err = result.unwrap_err();
764 assert_eq!(err.kind(), ErrorKind::InvalidInput);
765
766 drop(listener);
767}
768
94222f64
XL
769#[test]
770#[cfg_attr(target_env = "sgx", ignore)]
771fn linger() {
772 let addr = next_test_ip4();
773 let _listener = t!(TcpListener::bind(&addr));
774
775 let stream = t!(TcpStream::connect(&("localhost", addr.port())));
776
777 assert_eq!(None, t!(stream.linger()));
778 t!(stream.set_linger(Some(Duration::from_secs(1))));
779 assert_eq!(Some(Duration::from_secs(1)), t!(stream.linger()));
780 t!(stream.set_linger(None));
781 assert_eq!(None, t!(stream.linger()));
782}
783
1b1a35ee
XL
784#[test]
785#[cfg_attr(target_env = "sgx", ignore)]
786fn nodelay() {
787 let addr = next_test_ip4();
788 let _listener = t!(TcpListener::bind(&addr));
789
790 let stream = t!(TcpStream::connect(&("localhost", addr.port())));
791
792 assert_eq!(false, t!(stream.nodelay()));
793 t!(stream.set_nodelay(true));
794 assert_eq!(true, t!(stream.nodelay()));
795 t!(stream.set_nodelay(false));
796 assert_eq!(false, t!(stream.nodelay()));
797}
798
799#[test]
800#[cfg_attr(target_env = "sgx", ignore)]
801fn ttl() {
802 let ttl = 100;
803
804 let addr = next_test_ip4();
805 let listener = t!(TcpListener::bind(&addr));
806
807 t!(listener.set_ttl(ttl));
808 assert_eq!(ttl, t!(listener.ttl()));
809
810 let stream = t!(TcpStream::connect(&("localhost", addr.port())));
811
812 t!(stream.set_ttl(ttl));
813 assert_eq!(ttl, t!(stream.ttl()));
814}
815
816#[test]
817#[cfg_attr(target_env = "sgx", ignore)]
818fn set_nonblocking() {
819 let addr = next_test_ip4();
820 let listener = t!(TcpListener::bind(&addr));
821
822 t!(listener.set_nonblocking(true));
823 t!(listener.set_nonblocking(false));
824
825 let mut stream = t!(TcpStream::connect(&("localhost", addr.port())));
826
827 t!(stream.set_nonblocking(false));
828 t!(stream.set_nonblocking(true));
829
830 let mut buf = [0];
831 match stream.read(&mut buf) {
832 Ok(_) => panic!("expected error"),
833 Err(ref e) if e.kind() == ErrorKind::WouldBlock => {}
5e7ed085 834 Err(e) => panic!("unexpected error {e}"),
1b1a35ee
XL
835 }
836}
837
838#[test]
839#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
840fn peek() {
841 each_ip(&mut |addr| {
842 let (txdone, rxdone) = channel();
843
844 let srv = t!(TcpListener::bind(&addr));
845 let _t = thread::spawn(move || {
846 let mut cl = t!(srv.accept()).0;
847 cl.write(&[1, 3, 3, 7]).unwrap();
848 t!(rxdone.recv());
849 });
850
851 let mut c = t!(TcpStream::connect(&addr));
852 let mut b = [0; 10];
853 for _ in 1..3 {
854 let len = c.peek(&mut b).unwrap();
855 assert_eq!(len, 4);
856 }
857 let len = c.read(&mut b).unwrap();
858 assert_eq!(len, 4);
859
860 t!(c.set_nonblocking(true));
861 match c.peek(&mut b) {
862 Ok(_) => panic!("expected error"),
863 Err(ref e) if e.kind() == ErrorKind::WouldBlock => {}
5e7ed085 864 Err(e) => panic!("unexpected error {e}"),
1b1a35ee
XL
865 }
866 t!(txdone.send(()));
867 })
868}
869
870#[test]
871#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
872fn connect_timeout_valid() {
873 let listener = TcpListener::bind("127.0.0.1:0").unwrap();
874 let addr = listener.local_addr().unwrap();
875 TcpStream::connect_timeout(&addr, Duration::from_secs(2)).unwrap();
876}