xref: /freebsd/tests/sys/kqueue/libkqueue/read.c (revision cb5fe245b1c7d476e3839126a11ee4305484f7de)
1*cb5fe245SEnji Cooper /*
2*cb5fe245SEnji Cooper  * Copyright (c) 2009 Mark Heily <mark@heily.com>
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
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
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
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
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
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
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
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
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
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
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
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
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