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