1*cb5fe245SEnji Cooper /*
2*cb5fe245SEnji Cooper * Copyright (c) 2009 Mark Heily <[email protected]>
3*cb5fe245SEnji Cooper *
4*cb5fe245SEnji Cooper * Permission to use, copy, modify, and distribute this software for any
5*cb5fe245SEnji Cooper * purpose with or without fee is hereby granted, provided that the above
6*cb5fe245SEnji Cooper * copyright notice and this permission notice appear in all copies.
7*cb5fe245SEnji Cooper *
8*cb5fe245SEnji Cooper * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9*cb5fe245SEnji Cooper * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10*cb5fe245SEnji Cooper * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11*cb5fe245SEnji Cooper * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12*cb5fe245SEnji Cooper * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13*cb5fe245SEnji Cooper * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14*cb5fe245SEnji Cooper * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15*cb5fe245SEnji Cooper *
16*cb5fe245SEnji Cooper * $FreeBSD$
17*cb5fe245SEnji Cooper */
18*cb5fe245SEnji Cooper
19*cb5fe245SEnji Cooper #include "common.h"
20*cb5fe245SEnji Cooper
21*cb5fe245SEnji Cooper int kqfd;
22*cb5fe245SEnji Cooper int sockfd[2];
23*cb5fe245SEnji Cooper
24*cb5fe245SEnji Cooper static void
kevent_socket_drain(void)25*cb5fe245SEnji Cooper kevent_socket_drain(void)
26*cb5fe245SEnji Cooper {
27*cb5fe245SEnji Cooper char buf[1];
28*cb5fe245SEnji Cooper
29*cb5fe245SEnji Cooper /* Drain the read buffer, then make sure there are no more events. */
30*cb5fe245SEnji Cooper puts("draining the read buffer");
31*cb5fe245SEnji Cooper if (read(sockfd[0], &buf[0], 1) < 1)
32*cb5fe245SEnji Cooper err(1, "read(2)");
33*cb5fe245SEnji Cooper }
34*cb5fe245SEnji Cooper
35*cb5fe245SEnji Cooper static void
kevent_socket_fill(void)36*cb5fe245SEnji Cooper kevent_socket_fill(void)
37*cb5fe245SEnji Cooper {
38*cb5fe245SEnji Cooper puts("filling the read buffer");
39*cb5fe245SEnji Cooper if (write(sockfd[1], ".", 1) < 1)
40*cb5fe245SEnji Cooper err(1, "write(2)");
41*cb5fe245SEnji Cooper }
42*cb5fe245SEnji Cooper
43*cb5fe245SEnji Cooper
44*cb5fe245SEnji Cooper void
test_kevent_socket_add(void)45*cb5fe245SEnji Cooper test_kevent_socket_add(void)
46*cb5fe245SEnji Cooper {
47*cb5fe245SEnji Cooper const char *test_id = "kevent(EVFILT_READ, EV_ADD)";
48*cb5fe245SEnji Cooper struct kevent kev;
49*cb5fe245SEnji Cooper
50*cb5fe245SEnji Cooper test_begin(test_id);
51*cb5fe245SEnji Cooper EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]);
52*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
53*cb5fe245SEnji Cooper err(1, "%s", test_id);
54*cb5fe245SEnji Cooper
55*cb5fe245SEnji Cooper success();
56*cb5fe245SEnji Cooper }
57*cb5fe245SEnji Cooper
58*cb5fe245SEnji Cooper void
test_kevent_socket_get(void)59*cb5fe245SEnji Cooper test_kevent_socket_get(void)
60*cb5fe245SEnji Cooper {
61*cb5fe245SEnji Cooper const char *test_id = "kevent(EVFILT_READ) wait";
62*cb5fe245SEnji Cooper struct kevent kev;
63*cb5fe245SEnji Cooper
64*cb5fe245SEnji Cooper test_begin(test_id);
65*cb5fe245SEnji Cooper
66*cb5fe245SEnji Cooper EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]);
67*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
68*cb5fe245SEnji Cooper err(1, "%s", test_id);
69*cb5fe245SEnji Cooper
70*cb5fe245SEnji Cooper kevent_socket_fill();
71*cb5fe245SEnji Cooper
72*cb5fe245SEnji Cooper kev.data = 1;
73*cb5fe245SEnji Cooper kevent_cmp(&kev, kevent_get(kqfd));
74*cb5fe245SEnji Cooper
75*cb5fe245SEnji Cooper kevent_socket_drain();
76*cb5fe245SEnji Cooper test_no_kevents();
77*cb5fe245SEnji Cooper
78*cb5fe245SEnji Cooper kev.flags = EV_DELETE;
79*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
80*cb5fe245SEnji Cooper err(1, "%s", test_id);
81*cb5fe245SEnji Cooper
82*cb5fe245SEnji Cooper success();
83*cb5fe245SEnji Cooper }
84*cb5fe245SEnji Cooper
85*cb5fe245SEnji Cooper void
test_kevent_socket_clear(void)86*cb5fe245SEnji Cooper test_kevent_socket_clear(void)
87*cb5fe245SEnji Cooper {
88*cb5fe245SEnji Cooper const char *test_id = "kevent(EVFILT_READ, EV_CLEAR)";
89*cb5fe245SEnji Cooper struct kevent kev;
90*cb5fe245SEnji Cooper
91*cb5fe245SEnji Cooper test_begin(test_id);
92*cb5fe245SEnji Cooper
93*cb5fe245SEnji Cooper test_no_kevents();
94*cb5fe245SEnji Cooper
95*cb5fe245SEnji Cooper EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &sockfd[0]);
96*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
97*cb5fe245SEnji Cooper err(1, "%s", test_id);
98*cb5fe245SEnji Cooper
99*cb5fe245SEnji Cooper kevent_socket_fill();
100*cb5fe245SEnji Cooper kevent_socket_fill();
101*cb5fe245SEnji Cooper
102*cb5fe245SEnji Cooper kev.data = 2;
103*cb5fe245SEnji Cooper kevent_cmp(&kev, kevent_get(kqfd));
104*cb5fe245SEnji Cooper
105*cb5fe245SEnji Cooper /* We filled twice, but drain once. Edge-triggered would not generate
106*cb5fe245SEnji Cooper additional events.
107*cb5fe245SEnji Cooper */
108*cb5fe245SEnji Cooper kevent_socket_drain();
109*cb5fe245SEnji Cooper test_no_kevents();
110*cb5fe245SEnji Cooper
111*cb5fe245SEnji Cooper kevent_socket_drain();
112*cb5fe245SEnji Cooper EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);
113*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
114*cb5fe245SEnji Cooper err(1, "%s", test_id);
115*cb5fe245SEnji Cooper
116*cb5fe245SEnji Cooper success();
117*cb5fe245SEnji Cooper }
118*cb5fe245SEnji Cooper
119*cb5fe245SEnji Cooper void
test_kevent_socket_disable_and_enable(void)120*cb5fe245SEnji Cooper test_kevent_socket_disable_and_enable(void)
121*cb5fe245SEnji Cooper {
122*cb5fe245SEnji Cooper const char *test_id = "kevent(EVFILT_READ, EV_DISABLE)";
123*cb5fe245SEnji Cooper struct kevent kev;
124*cb5fe245SEnji Cooper
125*cb5fe245SEnji Cooper test_begin(test_id);
126*cb5fe245SEnji Cooper
127*cb5fe245SEnji Cooper /*
128*cb5fe245SEnji Cooper * Write to the socket before adding the event. This way we can verify that
129*cb5fe245SEnji Cooper * enabling a triggered kevent causes the event to be returned immediately.
130*cb5fe245SEnji Cooper */
131*cb5fe245SEnji Cooper kevent_socket_fill();
132*cb5fe245SEnji Cooper
133*cb5fe245SEnji Cooper /* Add a disabled event. */
134*cb5fe245SEnji Cooper EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_DISABLE, 0, 0, &sockfd[0]);
135*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
136*cb5fe245SEnji Cooper err(1, "%s", test_id);
137*cb5fe245SEnji Cooper
138*cb5fe245SEnji Cooper test_no_kevents();
139*cb5fe245SEnji Cooper
140*cb5fe245SEnji Cooper /* Re-enable the knote, then see if an event is generated */
141*cb5fe245SEnji Cooper kev.flags = EV_ENABLE;
142*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
143*cb5fe245SEnji Cooper err(1, "%s", test_id);
144*cb5fe245SEnji Cooper kev.flags = EV_ADD;
145*cb5fe245SEnji Cooper kev.data = 1;
146*cb5fe245SEnji Cooper kevent_cmp(&kev, kevent_get(kqfd));
147*cb5fe245SEnji Cooper
148*cb5fe245SEnji Cooper kevent_socket_drain();
149*cb5fe245SEnji Cooper
150*cb5fe245SEnji Cooper kev.flags = EV_DELETE;
151*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
152*cb5fe245SEnji Cooper err(1, "%s", test_id);
153*cb5fe245SEnji Cooper
154*cb5fe245SEnji Cooper success();
155*cb5fe245SEnji Cooper }
156*cb5fe245SEnji Cooper
157*cb5fe245SEnji Cooper void
test_kevent_socket_del(void)158*cb5fe245SEnji Cooper test_kevent_socket_del(void)
159*cb5fe245SEnji Cooper {
160*cb5fe245SEnji Cooper const char *test_id = "kevent(EVFILT_READ, EV_DELETE)";
161*cb5fe245SEnji Cooper struct kevent kev;
162*cb5fe245SEnji Cooper
163*cb5fe245SEnji Cooper test_begin(test_id);
164*cb5fe245SEnji Cooper
165*cb5fe245SEnji Cooper EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);
166*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
167*cb5fe245SEnji Cooper err(1, "%s", test_id);
168*cb5fe245SEnji Cooper
169*cb5fe245SEnji Cooper kevent_socket_fill();
170*cb5fe245SEnji Cooper test_no_kevents();
171*cb5fe245SEnji Cooper kevent_socket_drain();
172*cb5fe245SEnji Cooper
173*cb5fe245SEnji Cooper success();
174*cb5fe245SEnji Cooper }
175*cb5fe245SEnji Cooper
176*cb5fe245SEnji Cooper void
test_kevent_socket_oneshot(void)177*cb5fe245SEnji Cooper test_kevent_socket_oneshot(void)
178*cb5fe245SEnji Cooper {
179*cb5fe245SEnji Cooper const char *test_id = "kevent(EVFILT_READ, EV_ONESHOT)";
180*cb5fe245SEnji Cooper struct kevent kev;
181*cb5fe245SEnji Cooper
182*cb5fe245SEnji Cooper test_begin(test_id);
183*cb5fe245SEnji Cooper
184*cb5fe245SEnji Cooper /* Re-add the watch and make sure no events are pending */
185*cb5fe245SEnji Cooper puts("-- re-adding knote");
186*cb5fe245SEnji Cooper EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &sockfd[0]);
187*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
188*cb5fe245SEnji Cooper err(1, "%s", test_id);
189*cb5fe245SEnji Cooper test_no_kevents();
190*cb5fe245SEnji Cooper
191*cb5fe245SEnji Cooper puts("-- getting one event");
192*cb5fe245SEnji Cooper kevent_socket_fill();
193*cb5fe245SEnji Cooper kev.data = 1;
194*cb5fe245SEnji Cooper kevent_cmp(&kev, kevent_get(kqfd));
195*cb5fe245SEnji Cooper
196*cb5fe245SEnji Cooper puts("-- checking knote disabled");
197*cb5fe245SEnji Cooper test_no_kevents();
198*cb5fe245SEnji Cooper
199*cb5fe245SEnji Cooper /* Try to delete the knote, it should already be deleted */
200*cb5fe245SEnji Cooper EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);
201*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) == 0)
202*cb5fe245SEnji Cooper err(1, "%s", test_id);
203*cb5fe245SEnji Cooper
204*cb5fe245SEnji Cooper kevent_socket_drain();
205*cb5fe245SEnji Cooper
206*cb5fe245SEnji Cooper success();
207*cb5fe245SEnji Cooper }
208*cb5fe245SEnji Cooper
209*cb5fe245SEnji Cooper
210*cb5fe245SEnji Cooper #if HAVE_EV_DISPATCH
211*cb5fe245SEnji Cooper void
test_kevent_socket_dispatch(void)212*cb5fe245SEnji Cooper test_kevent_socket_dispatch(void)
213*cb5fe245SEnji Cooper {
214*cb5fe245SEnji Cooper const char *test_id = "kevent(EVFILT_READ, EV_DISPATCH)";
215*cb5fe245SEnji Cooper
216*cb5fe245SEnji Cooper test_begin(test_id);
217*cb5fe245SEnji Cooper
218*cb5fe245SEnji Cooper struct kevent kev;
219*cb5fe245SEnji Cooper
220*cb5fe245SEnji Cooper /* Re-add the watch and make sure no events are pending */
221*cb5fe245SEnji Cooper puts("-- re-adding knote");
222*cb5fe245SEnji Cooper EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_DISPATCH, 0, 0, &sockfd[0]);
223*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
224*cb5fe245SEnji Cooper err(1, "%s", test_id);
225*cb5fe245SEnji Cooper test_no_kevents();
226*cb5fe245SEnji Cooper
227*cb5fe245SEnji Cooper /* The event will occur only once, even though EV_CLEAR is not
228*cb5fe245SEnji Cooper specified. */
229*cb5fe245SEnji Cooper kevent_socket_fill();
230*cb5fe245SEnji Cooper kev.data = 1;
231*cb5fe245SEnji Cooper kevent_cmp(&kev, kevent_get(kqfd));
232*cb5fe245SEnji Cooper test_no_kevents();
233*cb5fe245SEnji Cooper
234*cb5fe245SEnji Cooper /* Since the knote is disabled, the EV_DELETE operation succeeds. */
235*cb5fe245SEnji Cooper EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);
236*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
237*cb5fe245SEnji Cooper err(1, "%s", test_id);
238*cb5fe245SEnji Cooper
239*cb5fe245SEnji Cooper kevent_socket_drain();
240*cb5fe245SEnji Cooper
241*cb5fe245SEnji Cooper success();
242*cb5fe245SEnji Cooper }
243*cb5fe245SEnji Cooper #endif /* HAVE_EV_DISPATCH */
244*cb5fe245SEnji Cooper
245*cb5fe245SEnji Cooper #if BROKEN
246*cb5fe245SEnji Cooper void
test_kevent_socket_lowat(void)247*cb5fe245SEnji Cooper test_kevent_socket_lowat(void)
248*cb5fe245SEnji Cooper {
249*cb5fe245SEnji Cooper const char *test_id = "kevent(EVFILT_READ, NOTE_LOWAT)";
250*cb5fe245SEnji Cooper struct kevent kev;
251*cb5fe245SEnji Cooper
252*cb5fe245SEnji Cooper test_begin(test_id);
253*cb5fe245SEnji Cooper
254*cb5fe245SEnji Cooper /* Re-add the watch and make sure no events are pending */
255*cb5fe245SEnji Cooper puts("-- re-adding knote, setting low watermark to 2 bytes");
256*cb5fe245SEnji Cooper EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, NOTE_LOWAT, 2, &sockfd[0]);
257*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
258*cb5fe245SEnji Cooper err(1, "%s", test_id);
259*cb5fe245SEnji Cooper test_no_kevents();
260*cb5fe245SEnji Cooper
261*cb5fe245SEnji Cooper puts("-- checking that one byte does not trigger an event..");
262*cb5fe245SEnji Cooper kevent_socket_fill();
263*cb5fe245SEnji Cooper test_no_kevents();
264*cb5fe245SEnji Cooper
265*cb5fe245SEnji Cooper puts("-- checking that two bytes triggers an event..");
266*cb5fe245SEnji Cooper kevent_socket_fill();
267*cb5fe245SEnji Cooper if (kevent(kqfd, NULL, 0, &kev, 1, NULL) != 1)
268*cb5fe245SEnji Cooper err(1, "%s", test_id);
269*cb5fe245SEnji Cooper KEV_CMP(kev, sockfd[0], EVFILT_READ, 0);
270*cb5fe245SEnji Cooper test_no_kevents();
271*cb5fe245SEnji Cooper
272*cb5fe245SEnji Cooper kevent_socket_drain();
273*cb5fe245SEnji Cooper kevent_socket_drain();
274*cb5fe245SEnji Cooper
275*cb5fe245SEnji Cooper success();
276*cb5fe245SEnji Cooper }
277*cb5fe245SEnji Cooper #endif
278*cb5fe245SEnji Cooper
279*cb5fe245SEnji Cooper void
test_kevent_socket_eof(void)280*cb5fe245SEnji Cooper test_kevent_socket_eof(void)
281*cb5fe245SEnji Cooper {
282*cb5fe245SEnji Cooper const char *test_id = "kevent(EVFILT_READ, EV_EOF)";
283*cb5fe245SEnji Cooper struct kevent kev;
284*cb5fe245SEnji Cooper
285*cb5fe245SEnji Cooper test_begin(test_id);
286*cb5fe245SEnji Cooper
287*cb5fe245SEnji Cooper /* Re-add the watch and make sure no events are pending */
288*cb5fe245SEnji Cooper EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]);
289*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
290*cb5fe245SEnji Cooper err(1, "%s", test_id);
291*cb5fe245SEnji Cooper test_no_kevents();
292*cb5fe245SEnji Cooper
293*cb5fe245SEnji Cooper if (close(sockfd[1]) < 0)
294*cb5fe245SEnji Cooper err(1, "close(2)");
295*cb5fe245SEnji Cooper
296*cb5fe245SEnji Cooper kev.flags |= EV_EOF;
297*cb5fe245SEnji Cooper kevent_cmp(&kev, kevent_get(kqfd));
298*cb5fe245SEnji Cooper
299*cb5fe245SEnji Cooper /* Delete the watch */
300*cb5fe245SEnji Cooper EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);
301*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
302*cb5fe245SEnji Cooper err(1, "%s", test_id);
303*cb5fe245SEnji Cooper
304*cb5fe245SEnji Cooper success();
305*cb5fe245SEnji Cooper }
306*cb5fe245SEnji Cooper
307*cb5fe245SEnji Cooper void
test_evfilt_read()308*cb5fe245SEnji Cooper test_evfilt_read()
309*cb5fe245SEnji Cooper {
310*cb5fe245SEnji Cooper /* Create a connected pair of full-duplex sockets for testing socket events */
311*cb5fe245SEnji Cooper if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) < 0)
312*cb5fe245SEnji Cooper abort();
313*cb5fe245SEnji Cooper
314*cb5fe245SEnji Cooper kqfd = kqueue();
315*cb5fe245SEnji Cooper test_kevent_socket_add();
316*cb5fe245SEnji Cooper test_kevent_socket_del();
317*cb5fe245SEnji Cooper test_kevent_socket_get();
318*cb5fe245SEnji Cooper test_kevent_socket_disable_and_enable();
319*cb5fe245SEnji Cooper test_kevent_socket_oneshot();
320*cb5fe245SEnji Cooper test_kevent_socket_clear();
321*cb5fe245SEnji Cooper #if HAVE_EV_DISPATCH
322*cb5fe245SEnji Cooper test_kevent_socket_dispatch();
323*cb5fe245SEnji Cooper #endif
324*cb5fe245SEnji Cooper test_kevent_socket_eof();
325*cb5fe245SEnji Cooper close(kqfd);
326*cb5fe245SEnji Cooper }
327