1 use nix::sys::select::*;
2 use nix::sys::signal::SigSet;
3 use nix::sys::time::{TimeSpec, TimeVal, TimeValLike};
4 use nix::unistd::{pipe, write};
5 use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
6
7 #[test]
test_pselect()8 pub fn test_pselect() {
9 let _mtx = crate::SIGNAL_MTX.lock();
10
11 let (r1, w1) = pipe().unwrap();
12 write(&w1, b"hi!").unwrap();
13 let (r2, _w2) = pipe().unwrap();
14
15 let mut fd_set = FdSet::new();
16 fd_set.insert(r1.as_fd());
17 fd_set.insert(r2.as_fd());
18
19 let timeout = TimeSpec::seconds(10);
20 let sigmask = SigSet::empty();
21 assert_eq!(
22 1,
23 pselect(None, &mut fd_set, None, None, &timeout, &sigmask).unwrap()
24 );
25 assert!(fd_set.contains(r1.as_fd()));
26 assert!(!fd_set.contains(r2.as_fd()));
27 }
28
29 #[test]
test_pselect_nfds2()30 pub fn test_pselect_nfds2() {
31 let (r1, w1) = pipe().unwrap();
32 write(&w1, b"hi!").unwrap();
33 let (r2, _w2) = pipe().unwrap();
34
35 let mut fd_set = FdSet::new();
36 fd_set.insert(r1.as_fd());
37 fd_set.insert(r2.as_fd());
38
39 let timeout = TimeSpec::seconds(10);
40 assert_eq!(
41 1,
42 pselect(
43 std::cmp::max(r1.as_raw_fd(), r2.as_raw_fd()) + 1,
44 &mut fd_set,
45 None,
46 None,
47 &timeout,
48 None
49 )
50 .unwrap()
51 );
52 assert!(fd_set.contains(r1.as_fd()));
53 assert!(!fd_set.contains(r2.as_fd()));
54 }
55
56 macro_rules! generate_fdset_bad_fd_tests {
57 ($fd:expr, $($method:ident),* $(,)?) => {
58 $(
59 #[test]
60 #[should_panic]
61 fn $method() {
62 let bad_fd = unsafe{BorrowedFd::borrow_raw($fd)};
63 FdSet::new().$method(bad_fd);
64 }
65 )*
66 }
67 }
68
69 mod test_fdset_too_large_fd {
70 use super::*;
71 generate_fdset_bad_fd_tests!(
72 FD_SETSIZE.try_into().unwrap(),
73 insert,
74 remove,
75 contains,
76 );
77 }
78
79 #[test]
fdset_insert()80 fn fdset_insert() {
81 let mut fd_set = FdSet::new();
82
83 for i in 0..FD_SETSIZE {
84 let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) };
85 assert!(!fd_set.contains(borrowed_i));
86 }
87
88 let fd_seven = unsafe { BorrowedFd::borrow_raw(7) };
89 fd_set.insert(fd_seven);
90
91 assert!(fd_set.contains(fd_seven));
92 }
93
94 #[test]
fdset_remove()95 fn fdset_remove() {
96 let mut fd_set = FdSet::new();
97
98 for i in 0..FD_SETSIZE {
99 let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) };
100 assert!(!fd_set.contains(borrowed_i));
101 }
102
103 let fd_seven = unsafe { BorrowedFd::borrow_raw(7) };
104 fd_set.insert(fd_seven);
105 fd_set.remove(fd_seven);
106
107 for i in 0..FD_SETSIZE {
108 let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) };
109 assert!(!fd_set.contains(borrowed_i));
110 }
111 }
112
113 #[test]
114 #[allow(non_snake_case)]
fdset_clear()115 fn fdset_clear() {
116 let mut fd_set = FdSet::new();
117 let fd_one = unsafe { BorrowedFd::borrow_raw(1) };
118 let fd_FD_SETSIZE_divided_by_two =
119 unsafe { BorrowedFd::borrow_raw((FD_SETSIZE / 2) as RawFd) };
120 let fd_FD_SETSIZE_minus_one =
121 unsafe { BorrowedFd::borrow_raw((FD_SETSIZE - 1) as RawFd) };
122 fd_set.insert(fd_one);
123 fd_set.insert(fd_FD_SETSIZE_divided_by_two);
124 fd_set.insert(fd_FD_SETSIZE_minus_one);
125
126 fd_set.clear();
127
128 for i in 0..FD_SETSIZE {
129 let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) };
130 assert!(!fd_set.contains(borrowed_i));
131 }
132 }
133
134 #[test]
fdset_highest()135 fn fdset_highest() {
136 let mut set = FdSet::new();
137 assert_eq!(
138 set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()),
139 None
140 );
141 let fd_zero = unsafe { BorrowedFd::borrow_raw(0) };
142 let fd_ninety = unsafe { BorrowedFd::borrow_raw(90) };
143 set.insert(fd_zero);
144 assert_eq!(
145 set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()),
146 Some(0)
147 );
148 set.insert(fd_ninety);
149 assert_eq!(
150 set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()),
151 Some(90)
152 );
153 set.remove(fd_zero);
154 assert_eq!(
155 set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()),
156 Some(90)
157 );
158 set.remove(fd_ninety);
159 assert_eq!(
160 set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()),
161 None
162 );
163
164 let fd_four = unsafe { BorrowedFd::borrow_raw(4) };
165 let fd_five = unsafe { BorrowedFd::borrow_raw(5) };
166 let fd_seven = unsafe { BorrowedFd::borrow_raw(7) };
167 set.insert(fd_four);
168 set.insert(fd_five);
169 set.insert(fd_seven);
170 assert_eq!(
171 set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()),
172 Some(7)
173 );
174 }
175
176 #[test]
fdset_fds()177 fn fdset_fds() {
178 let mut set = FdSet::new();
179 let fd_zero = unsafe { BorrowedFd::borrow_raw(0) };
180 let fd_ninety = unsafe { BorrowedFd::borrow_raw(90) };
181 assert_eq!(
182 set.fds(None)
183 .map(|borrowed_fd| borrowed_fd.as_raw_fd())
184 .collect::<Vec<_>>(),
185 vec![]
186 );
187 set.insert(fd_zero);
188 assert_eq!(
189 set.fds(None)
190 .map(|borrowed_fd| borrowed_fd.as_raw_fd())
191 .collect::<Vec<_>>(),
192 vec![0]
193 );
194 set.insert(fd_ninety);
195 assert_eq!(
196 set.fds(None)
197 .map(|borrowed_fd| borrowed_fd.as_raw_fd())
198 .collect::<Vec<_>>(),
199 vec![0, 90]
200 );
201
202 // highest limit
203 assert_eq!(
204 set.fds(Some(89))
205 .map(|borrowed_fd| borrowed_fd.as_raw_fd())
206 .collect::<Vec<_>>(),
207 vec![0]
208 );
209 assert_eq!(
210 set.fds(Some(90))
211 .map(|borrowed_fd| borrowed_fd.as_raw_fd())
212 .collect::<Vec<_>>(),
213 vec![0, 90]
214 );
215 }
216
217 #[test]
test_select()218 fn test_select() {
219 let (r1, w1) = pipe().unwrap();
220 let (r2, _w2) = pipe().unwrap();
221
222 write(&w1, b"hi!").unwrap();
223 let mut fd_set = FdSet::new();
224 fd_set.insert(r1.as_fd());
225 fd_set.insert(r2.as_fd());
226
227 let mut timeout = TimeVal::seconds(10);
228 assert_eq!(
229 1,
230 select(None, &mut fd_set, None, None, &mut timeout).unwrap()
231 );
232 assert!(fd_set.contains(r1.as_fd()));
233 assert!(!fd_set.contains(r2.as_fd()));
234 }
235
236 #[test]
test_select_nfds()237 fn test_select_nfds() {
238 let (r1, w1) = pipe().unwrap();
239 let (r2, _w2) = pipe().unwrap();
240
241 write(&w1, b"hi!").unwrap();
242 let mut fd_set = FdSet::new();
243 fd_set.insert(r1.as_fd());
244 fd_set.insert(r2.as_fd());
245
246 let mut timeout = TimeVal::seconds(10);
247 {
248 assert_eq!(
249 1,
250 select(
251 Some(
252 fd_set
253 .highest()
254 .map(|borrowed_fd| borrowed_fd.as_raw_fd())
255 .unwrap()
256 + 1
257 ),
258 &mut fd_set,
259 None,
260 None,
261 &mut timeout
262 )
263 .unwrap()
264 );
265 }
266 assert!(fd_set.contains(r1.as_fd()));
267 assert!(!fd_set.contains(r2.as_fd()));
268 }
269
270 #[test]
test_select_nfds2()271 fn test_select_nfds2() {
272 let (r1, w1) = pipe().unwrap();
273 write(&w1, b"hi!").unwrap();
274 let (r2, _w2) = pipe().unwrap();
275 let mut fd_set = FdSet::new();
276 fd_set.insert(r1.as_fd());
277 fd_set.insert(r2.as_fd());
278
279 let mut timeout = TimeVal::seconds(10);
280 assert_eq!(
281 1,
282 select(
283 std::cmp::max(r1.as_raw_fd(), r2.as_raw_fd()) + 1,
284 &mut fd_set,
285 None,
286 None,
287 &mut timeout
288 )
289 .unwrap()
290 );
291 assert!(fd_set.contains(r1.as_fd()));
292 assert!(!fd_set.contains(r2.as_fd()));
293 }
294