1 #![allow(deprecated)]
2 
3 extern crate mio;
4 extern crate bytes;
5 extern crate net2;
6 
7 #[macro_use]
8 extern crate log;
9 extern crate env_logger;
10 extern crate iovec;
11 extern crate slab;
12 extern crate tempdir;
13 
14 #[cfg(target_os = "fuchsia")]
15 extern crate fuchsia_zircon as zircon;
16 
17 pub use ports::localhost;
18 
19 mod test_custom_evented;
20 mod test_close_on_drop;
21 mod test_double_register;
22 mod test_echo_server;
23 mod test_local_addr_ready;
24 mod test_multicast;
25 mod test_oneshot;
26 mod test_poll;
27 mod test_register_deregister;
28 mod test_register_multiple_event_loops;
29 mod test_reregister_without_poll;
30 mod test_smoke;
31 mod test_tcp;
32 mod test_tcp_level;
33 mod test_tcp_shutdown;
34 mod test_udp_level;
35 mod test_udp_socket;
36 mod test_write_then_drop;
37 
38 #[cfg(feature = "with-deprecated")]
39 mod test_notify;
40 #[cfg(feature = "with-deprecated")]
41 mod test_poll_channel;
42 #[cfg(feature = "with-deprecated")]
43 mod test_tick;
44 
45 // The following tests are for deprecated features. Only run these tests on
46 // platforms that were supported from before the features were deprecated
47 #[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
48 #[cfg(feature = "with-deprecated")]
49 mod test_battery;
50 
51 #[cfg(any(target_os = "macos", target_os = "linux"))]
52 #[cfg(feature = "with-deprecated")]
53 mod test_unix_echo_server;
54 #[cfg(any(target_os = "macos", target_os = "linux"))]
55 #[cfg(feature = "with-deprecated")]
56 mod test_unix_pass_fd;
57 #[cfg(any(target_os = "macos", target_os = "linux"))]
58 #[cfg(feature = "with-deprecated")]
59 mod test_uds_shutdown;
60 #[cfg(any(target_os = "macos", target_os = "linux"))]
61 #[cfg(feature = "with-deprecated")]
62 mod test_subprocess_pipe;
63 #[cfg(any(target_os = "macos", target_os = "linux"))]
64 #[cfg(feature = "with-deprecated")]
65 mod test_broken_pipe;
66 
67 #[cfg(any(target_os = "fuchsia"))]
68 mod test_fuchsia_handles;
69 
70 use bytes::{Buf, MutBuf};
71 use std::io::{self, Read, Write};
72 use std::time::Duration;
73 use mio::{Events, Poll};
74 use mio::event::Event;
75 
76 pub trait TryRead {
try_read_buf<B: MutBuf>(&mut self, buf: &mut B) -> io::Result<Option<usize>> where Self : Sized77     fn try_read_buf<B: MutBuf>(&mut self, buf: &mut B) -> io::Result<Option<usize>>
78         where Self : Sized
79     {
80         // Reads the length of the slice supplied by buf.mut_bytes into the buffer
81         // This is not guaranteed to consume an entire datagram or segment.
82         // If your protocol is msg based (instead of continuous stream) you should
83         // ensure that your buffer is large enough to hold an entire segment (1532 bytes if not jumbo
84         // frames)
85         let res = self.try_read(unsafe { buf.mut_bytes() });
86 
87         if let Ok(Some(cnt)) = res {
88             unsafe { buf.advance(cnt); }
89         }
90 
91         res
92     }
93 
try_read(&mut self, buf: &mut [u8]) -> io::Result<Option<usize>>94     fn try_read(&mut self, buf: &mut [u8]) -> io::Result<Option<usize>>;
95 }
96 
97 pub trait TryWrite {
try_write_buf<B: Buf>(&mut self, buf: &mut B) -> io::Result<Option<usize>> where Self : Sized98     fn try_write_buf<B: Buf>(&mut self, buf: &mut B) -> io::Result<Option<usize>>
99         where Self : Sized
100     {
101         let res = self.try_write(buf.bytes());
102 
103         if let Ok(Some(cnt)) = res {
104             buf.advance(cnt);
105         }
106 
107         res
108     }
109 
try_write(&mut self, buf: &[u8]) -> io::Result<Option<usize>>110     fn try_write(&mut self, buf: &[u8]) -> io::Result<Option<usize>>;
111 }
112 
113 impl<T: Read> TryRead for T {
try_read(&mut self, dst: &mut [u8]) -> io::Result<Option<usize>>114     fn try_read(&mut self, dst: &mut [u8]) -> io::Result<Option<usize>> {
115         self.read(dst).map_non_block()
116     }
117 }
118 
119 impl<T: Write> TryWrite for T {
try_write(&mut self, src: &[u8]) -> io::Result<Option<usize>>120     fn try_write(&mut self, src: &[u8]) -> io::Result<Option<usize>> {
121         self.write(src).map_non_block()
122     }
123 }
124 
125 /*
126  *
127  * ===== Helpers =====
128  *
129  */
130 
131 /// A helper trait to provide the map_non_block function on Results.
132 trait MapNonBlock<T> {
133     /// Maps a `Result<T>` to a `Result<Option<T>>` by converting
134     /// operation-would-block errors into `Ok(None)`.
map_non_block(self) -> io::Result<Option<T>>135     fn map_non_block(self) -> io::Result<Option<T>>;
136 }
137 
138 impl<T> MapNonBlock<T> for io::Result<T> {
map_non_block(self) -> io::Result<Option<T>>139     fn map_non_block(self) -> io::Result<Option<T>> {
140         use std::io::ErrorKind::WouldBlock;
141 
142         match self {
143             Ok(value) => Ok(Some(value)),
144             Err(err) => {
145                 if let WouldBlock = err.kind() {
146                     Ok(None)
147                 } else {
148                     Err(err)
149                 }
150             }
151         }
152     }
153 }
154 
155 mod ports {
156     use std::net::SocketAddr;
157     use std::str::FromStr;
158     use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
159     use std::sync::atomic::Ordering::SeqCst;
160 
161     // Helper for getting a unique port for the task run
162     // TODO: Reuse ports to not spam the system
163     static mut NEXT_PORT: AtomicUsize = ATOMIC_USIZE_INIT;
164     const FIRST_PORT: usize = 18080;
165 
next_port() -> usize166     fn next_port() -> usize {
167         unsafe {
168             // If the atomic was never used, set it to the initial port
169             NEXT_PORT.compare_and_swap(0, FIRST_PORT, SeqCst);
170 
171             // Get and increment the port list
172             NEXT_PORT.fetch_add(1, SeqCst)
173         }
174     }
175 
localhost() -> SocketAddr176     pub fn localhost() -> SocketAddr {
177         let s = format!("127.0.0.1:{}", next_port());
178         FromStr::from_str(&s).unwrap()
179     }
180 }
181 
sleep_ms(ms: u64)182 pub fn sleep_ms(ms: u64) {
183     use std::thread;
184     thread::sleep(Duration::from_millis(ms));
185 }
186 
expect_events(poll: &Poll, event_buffer: &mut Events, poll_try_count: usize, mut expected: Vec<Event>)187 pub fn expect_events(poll: &Poll,
188                      event_buffer: &mut Events,
189                      poll_try_count: usize,
190                      mut expected: Vec<Event>)
191 {
192     const MS: u64 = 1_000;
193 
194     for _ in 0..poll_try_count {
195         poll.poll(event_buffer, Some(Duration::from_millis(MS))).unwrap();
196         for event in event_buffer.iter() {
197             let pos_opt = match expected.iter().position(|exp_event| {
198                 (event.token() == exp_event.token()) &&
199                 event.readiness().contains(exp_event.readiness())
200             }) {
201                 Some(x) => Some(x),
202                 None => None,
203             };
204             if let Some(pos) = pos_opt { expected.remove(pos); }
205         }
206 
207         if expected.is_empty() {
208             break;
209         }
210     }
211 
212     assert!(expected.is_empty(), "The following expected events were not found: {:?}", expected);
213 }
214 
215