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