2 * Copyright (c) 2009 Mark Heily <mark@heily.com>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include <arpa/inet.h>
18 #include <sys/socket.h>
21 static int __thread kqfd;
22 static int __thread sockfd[2];
25 kevent_socket_drain(void)
29 /* Drain the read buffer, then make sure there are no more events. */
30 if (read(sockfd[0], &buf[0], 1) < 1)
35 kevent_socket_fill(void)
37 if (write(sockfd[1], ".", 1) < 1)
43 test_kevent_socket_add(void)
47 kevent_add(kqfd, &kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]);
51 test_kevent_socket_add_without_ev_add(void)
55 /* Try to add a kevent without specifying EV_ADD */
56 EV_SET(&kev, sockfd[0], EVFILT_READ, 0, 0, 0, &sockfd[0]);
57 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) == 0)
58 die("kevent should have failed");
61 test_no_kevents(kqfd);
62 kevent_socket_drain();
64 /* Try to delete a kevent which does not exist */
65 kev.flags = EV_DELETE;
66 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) == 0)
67 die("kevent should have failed");
71 test_kevent_socket_get(void)
75 EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]);
76 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
82 kevent_cmp(&kev, kevent_get(kqfd));
84 kevent_socket_drain();
85 test_no_kevents(kqfd);
87 kev.flags = EV_DELETE;
88 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
93 test_kevent_socket_clear(void)
97 test_no_kevents(kqfd);
98 kevent_socket_drain();
100 EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &sockfd[0]);
101 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
104 kevent_socket_fill();
105 kevent_socket_fill();
107 /* Solaris does not offer a way to get the amount of data pending */
113 kevent_cmp(&kev, kevent_get(kqfd));
115 /* We filled twice, but drain once. Edge-triggered would not generate
118 kevent_socket_drain();
119 test_no_kevents(kqfd);
121 kevent_socket_drain();
122 EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);
123 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
128 test_kevent_socket_disable_and_enable(void)
132 /* Add an event, then disable it. */
133 EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]);
134 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
136 EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DISABLE, 0, 0, &sockfd[0]);
137 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
140 kevent_socket_fill();
141 test_no_kevents(kqfd);
143 /* Re-enable the knote, then see if an event is generated */
144 kev.flags = EV_ENABLE;
145 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
149 kevent_cmp(&kev, kevent_get(kqfd));
151 kevent_socket_drain();
153 kev.flags = EV_DELETE;
154 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
159 test_kevent_socket_del(void)
163 EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);
164 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
167 kevent_socket_fill();
168 test_no_kevents(kqfd);
169 kevent_socket_drain();
173 test_kevent_socket_oneshot(void)
177 /* Re-add the watch and make sure no events are pending */
178 kevent_add(kqfd, &kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &sockfd[0]);
179 test_no_kevents(kqfd);
181 kevent_socket_fill();
183 kevent_cmp(&kev, kevent_get(kqfd));
185 test_no_kevents(kqfd);
187 /* Verify that the event has been deleted */
188 kevent_socket_fill();
189 test_no_kevents(kqfd);
190 kevent_socket_drain();
194 * Test if the data field returns 1 when a listen(2) socket has
195 * a pending connection.
198 test_kevent_socket_listen_backlog(void)
201 struct sockaddr_in sain;
202 socklen_t sa_len = sizeof(sain);
204 const short port = 14973;
207 /* Create a passive socket */
208 memset(&sain, 0, sizeof(sain));
209 sain.sin_family = AF_INET;
210 sain.sin_port = htons(port);
211 if ((srvr = socket(PF_INET, SOCK_STREAM, 0)) < 0) abort();
212 if (setsockopt(srvr, SOL_SOCKET, SO_REUSEADDR,
213 (char *) &one, sizeof(one)) != 0) abort();
214 if (bind(srvr, (struct sockaddr *) &sain, sa_len) < 0) abort();
215 if (listen(srvr, 100) < 0) abort();
217 /* Watch for events on the socket */
218 test_no_kevents(kqfd);
219 kevent_add(kqfd, &kev, srvr, EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, NULL);
220 test_no_kevents(kqfd);
222 /* Simulate a client connecting to the server */
223 sain.sin_family = AF_INET;
224 sain.sin_port = htons(port);
225 sain.sin_addr.s_addr = inet_addr("127.0.0.1");
226 if ((clnt = socket(AF_INET, SOCK_STREAM, 0)) < 0) abort();
227 if (connect(clnt, (struct sockaddr *) &sain, sa_len) < 0) abort();
229 /* Verify that data=1 */
231 kevent_cmp(&kev, kevent_get(kqfd));
232 test_no_kevents(kqfd);
237 test_kevent_socket_dispatch(void)
241 /* Re-add the watch and make sure no events are pending */
242 kevent_add(kqfd, &kev, sockfd[0], EVFILT_READ, EV_ADD | EV_DISPATCH, 0, 0, &sockfd[0]);
243 test_no_kevents(kqfd);
245 /* The event will occur only once, even though EV_CLEAR is not
247 kevent_socket_fill();
249 kevent_cmp(&kev, kevent_get(kqfd));
250 test_no_kevents(kqfd);
252 /* Re-enable the kevent */
253 /* FIXME- is EV_DISPATCH needed when rearming ? */
254 kevent_add(kqfd, &kev, sockfd[0], EVFILT_READ, EV_ENABLE | EV_DISPATCH, 0, 0, &sockfd[0]);
256 kev.flags = EV_ADD | EV_DISPATCH; /* FIXME: may not be portable */
257 kevent_cmp(&kev, kevent_get(kqfd));
258 test_no_kevents(kqfd);
260 /* Since the knote is disabled, the EV_DELETE operation succeeds. */
261 kevent_add(kqfd, &kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);
263 kevent_socket_drain();
265 #endif /* HAVE_EV_DISPATCH */
269 test_kevent_socket_lowat(void)
275 /* Re-add the watch and make sure no events are pending */
276 puts("-- re-adding knote, setting low watermark to 2 bytes");
277 EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, NOTE_LOWAT, 2, &sockfd[0]);
278 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
282 puts("-- checking that one byte does not trigger an event..");
283 kevent_socket_fill();
286 puts("-- checking that two bytes triggers an event..");
287 kevent_socket_fill();
288 if (kevent(kqfd, NULL, 0, &kev, 1, NULL) != 1)
290 KEV_CMP(kev, sockfd[0], EVFILT_READ, 0);
293 kevent_socket_drain();
294 kevent_socket_drain();
299 test_kevent_socket_eof(void)
303 /* Re-add the watch and make sure no events are pending */
304 kevent_add(kqfd, &kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]);
305 test_no_kevents(kqfd);
307 if (close(sockfd[1]) < 0)
311 kevent_cmp(&kev, kevent_get(kqfd));
313 /* Delete the watch */
314 kevent_add(kqfd, &kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);
318 test_evfilt_read(int _kqfd)
320 /* Create a connected pair of full-duplex sockets for testing socket events */
321 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) < 0)
325 test(kevent_socket_add);
326 test(kevent_socket_del);
327 test(kevent_socket_add_without_ev_add);
328 test(kevent_socket_get);
329 test(kevent_socket_disable_and_enable);
330 test(kevent_socket_oneshot);
331 test(kevent_socket_clear);
333 test(kevent_socket_dispatch);
335 test(kevent_socket_listen_backlog);
336 test(kevent_socket_eof);