1200483Srwatson/*
2200483Srwatson * Copyright (c) 2009 Mark Heily <mark@heily.com>
3200483Srwatson *
4200483Srwatson * Permission to use, copy, modify, and distribute this software for any
5200483Srwatson * purpose with or without fee is hereby granted, provided that the above
6200483Srwatson * copyright notice and this permission notice appear in all copies.
7200483Srwatson *
8200483Srwatson * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9200483Srwatson * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10200483Srwatson * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11200483Srwatson * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12200483Srwatson * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13200483Srwatson * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14200483Srwatson * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15200483Srwatson *
16200483Srwatson * $FreeBSD$
17200483Srwatson */
18200483Srwatson
19200483Srwatson#include "common.h"
20200483Srwatson
21200483Srwatsonint kqfd;
22200483Srwatsonint sockfd[2];
23200483Srwatson
24200483Srwatsonstatic void
25200483Srwatsonkevent_socket_drain(void)
26200483Srwatson{
27200483Srwatson    char buf[1];
28200483Srwatson
29200483Srwatson    /* Drain the read buffer, then make sure there are no more events. */
30200483Srwatson    puts("draining the read buffer");
31200483Srwatson    if (read(sockfd[0], &buf[0], 1) < 1)
32200483Srwatson        err(1, "read(2)");
33200483Srwatson}
34200483Srwatson
35200483Srwatsonstatic void
36200483Srwatsonkevent_socket_fill(void)
37200483Srwatson{
38200483Srwatson  puts("filling the read buffer");
39200483Srwatson    if (write(sockfd[1], ".", 1) < 1)
40200483Srwatson        err(1, "write(2)");
41200483Srwatson}
42200483Srwatson
43200483Srwatson
44200483Srwatsonvoid
45200483Srwatsontest_kevent_socket_add(void)
46200483Srwatson{
47200483Srwatson    const char *test_id = "kevent(EVFILT_READ, EV_ADD)";
48200483Srwatson    struct kevent kev;
49200483Srwatson
50200483Srwatson    test_begin(test_id);
51200483Srwatson    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]);
52200483Srwatson    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
53200483Srwatson        err(1, "%s", test_id);
54200483Srwatson
55200483Srwatson    success();
56200483Srwatson}
57200483Srwatson
58200483Srwatsonvoid
59200483Srwatsontest_kevent_socket_get(void)
60200483Srwatson{
61200483Srwatson    const char *test_id = "kevent(EVFILT_READ) wait";
62200483Srwatson    struct kevent kev;
63200483Srwatson
64200483Srwatson    test_begin(test_id);
65200483Srwatson
66200483Srwatson    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]);
67200483Srwatson    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
68200483Srwatson        err(1, "%s", test_id);
69200483Srwatson
70200483Srwatson    kevent_socket_fill();
71200483Srwatson
72200483Srwatson    kev.data = 1;
73200483Srwatson    kevent_cmp(&kev, kevent_get(kqfd));
74200483Srwatson
75200483Srwatson    kevent_socket_drain();
76200483Srwatson    test_no_kevents();
77200483Srwatson
78200483Srwatson    kev.flags = EV_DELETE;
79200483Srwatson    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
80200483Srwatson        err(1, "%s", test_id);
81200483Srwatson
82200483Srwatson    success();
83200483Srwatson}
84200483Srwatson
85200483Srwatsonvoid
86200483Srwatsontest_kevent_socket_clear(void)
87200483Srwatson{
88200483Srwatson    const char *test_id = "kevent(EVFILT_READ, EV_CLEAR)";
89200483Srwatson    struct kevent kev;
90200483Srwatson
91200483Srwatson    test_begin(test_id);
92200483Srwatson
93200483Srwatson    test_no_kevents();
94200483Srwatson
95200483Srwatson    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &sockfd[0]);
96200483Srwatson    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
97200483Srwatson        err(1, "%s", test_id);
98200483Srwatson
99200483Srwatson    kevent_socket_fill();
100200483Srwatson    kevent_socket_fill();
101200483Srwatson
102200483Srwatson    kev.data = 2;
103200483Srwatson    kevent_cmp(&kev, kevent_get(kqfd));
104200483Srwatson
105200483Srwatson    /* We filled twice, but drain once. Edge-triggered would not generate
106200483Srwatson       additional events.
107200483Srwatson     */
108200483Srwatson    kevent_socket_drain();
109200483Srwatson    test_no_kevents();
110200483Srwatson
111200483Srwatson    kevent_socket_drain();
112200483Srwatson    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);
113200483Srwatson    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
114200483Srwatson        err(1, "%s", test_id);
115200483Srwatson
116200483Srwatson    success();
117200483Srwatson}
118200483Srwatson
119200483Srwatsonvoid
120200483Srwatsontest_kevent_socket_disable_and_enable(void)
121200483Srwatson{
122200483Srwatson    const char *test_id = "kevent(EVFILT_READ, EV_DISABLE)";
123200483Srwatson    struct kevent kev;
124200483Srwatson
125200483Srwatson    test_begin(test_id);
126200483Srwatson
127200483Srwatson    /* Add an event, then disable it. */
128200483Srwatson    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]);
129200483Srwatson    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
130200483Srwatson        err(1, "%s", test_id);
131200483Srwatson    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DISABLE, 0, 0, &sockfd[0]);
132200483Srwatson    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
133200483Srwatson        err(1, "%s", test_id);
134200483Srwatson
135200483Srwatson    kevent_socket_fill();
136200483Srwatson    test_no_kevents();
137200483Srwatson
138200483Srwatson    /* Re-enable the knote, then see if an event is generated */
139200483Srwatson    kev.flags = EV_ENABLE;
140200483Srwatson    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
141200483Srwatson        err(1, "%s", test_id);
142200483Srwatson    kev.flags = EV_ADD;
143200483Srwatson    kev.data = 1;
144200483Srwatson    kevent_cmp(&kev, kevent_get(kqfd));
145200483Srwatson
146200483Srwatson    kevent_socket_drain();
147200483Srwatson
148200483Srwatson    kev.flags = EV_DELETE;
149200483Srwatson    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
150200483Srwatson        err(1, "%s", test_id);
151200483Srwatson
152200483Srwatson    success();
153200483Srwatson}
154200483Srwatson
155200483Srwatsonvoid
156200483Srwatsontest_kevent_socket_del(void)
157200483Srwatson{
158200483Srwatson    const char *test_id = "kevent(EVFILT_READ, EV_DELETE)";
159200483Srwatson    struct kevent kev;
160200483Srwatson
161200483Srwatson    test_begin(test_id);
162200483Srwatson
163200483Srwatson    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);
164200483Srwatson    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
165200483Srwatson        err(1, "%s", test_id);
166200483Srwatson
167200483Srwatson    kevent_socket_fill();
168200483Srwatson    test_no_kevents();
169200483Srwatson    kevent_socket_drain();
170200483Srwatson
171200483Srwatson    success();
172200483Srwatson}
173200483Srwatson
174200483Srwatsonvoid
175200483Srwatsontest_kevent_socket_oneshot(void)
176200483Srwatson{
177200483Srwatson    const char *test_id = "kevent(EVFILT_READ, EV_ONESHOT)";
178200483Srwatson    struct kevent kev;
179200483Srwatson
180200483Srwatson    test_begin(test_id);
181200483Srwatson
182200483Srwatson    /* Re-add the watch and make sure no events are pending */
183200483Srwatson    puts("-- re-adding knote");
184200483Srwatson    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &sockfd[0]);
185200483Srwatson    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
186200483Srwatson        err(1, "%s", test_id);
187200483Srwatson    test_no_kevents();
188200483Srwatson
189200483Srwatson    puts("-- getting one event");
190200483Srwatson    kevent_socket_fill();
191200483Srwatson    kev.data = 1;
192200483Srwatson    kevent_cmp(&kev, kevent_get(kqfd));
193200483Srwatson
194200483Srwatson    puts("-- checking knote disabled");
195200483Srwatson    test_no_kevents();
196200483Srwatson
197200483Srwatson    /* Try to delete the knote, it should already be deleted */
198200483Srwatson    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);
199200483Srwatson    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) == 0)
200200483Srwatson        err(1, "%s", test_id);
201200483Srwatson
202200483Srwatson    kevent_socket_drain();
203200483Srwatson
204200483Srwatson    success();
205200483Srwatson}
206200483Srwatson
207200483Srwatson
208200483Srwatson#if HAVE_EV_DISPATCH
209200483Srwatsonvoid
210200483Srwatsontest_kevent_socket_dispatch(void)
211200483Srwatson{
212200483Srwatson    const char *test_id = "kevent(EVFILT_READ, EV_DISPATCH)";
213200483Srwatson
214200483Srwatson    test_begin(test_id);
215200483Srwatson
216200483Srwatson    struct kevent kev;
217200483Srwatson
218200483Srwatson    /* Re-add the watch and make sure no events are pending */
219200483Srwatson    puts("-- re-adding knote");
220200483Srwatson    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_DISPATCH, 0, 0, &sockfd[0]);
221200483Srwatson    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
222200483Srwatson        err(1, "%s", test_id);
223200483Srwatson    test_no_kevents();
224200483Srwatson
225200483Srwatson    /* The event will occur only once, even though EV_CLEAR is not
226200483Srwatson       specified. */
227200483Srwatson    kevent_socket_fill();
228200483Srwatson    kev.data = 1;
229200483Srwatson    kevent_cmp(&kev, kevent_get(kqfd));
230200483Srwatson    test_no_kevents();
231200483Srwatson
232200483Srwatson    /* Since the knote is disabled, the EV_DELETE operation succeeds. */
233200483Srwatson    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);
234200483Srwatson    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
235200483Srwatson        err(1, "%s", test_id);
236200483Srwatson
237200483Srwatson    kevent_socket_drain();
238200483Srwatson
239200483Srwatson    success();
240200483Srwatson}
241200483Srwatson#endif  /* HAVE_EV_DISPATCH */
242200483Srwatson
243200483Srwatson#if BROKEN
244200483Srwatsonvoid
245200483Srwatsontest_kevent_socket_lowat(void)
246200483Srwatson{
247200483Srwatson    const char *test_id = "kevent(EVFILT_READ, NOTE_LOWAT)";
248200483Srwatson    struct kevent kev;
249200483Srwatson
250200483Srwatson    test_begin(test_id);
251200483Srwatson
252200483Srwatson    /* Re-add the watch and make sure no events are pending */
253200483Srwatson    puts("-- re-adding knote, setting low watermark to 2 bytes");
254200483Srwatson    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, NOTE_LOWAT, 2, &sockfd[0]);
255200483Srwatson    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
256200483Srwatson        err(1, "%s", test_id);
257200483Srwatson    test_no_kevents();
258200483Srwatson
259200483Srwatson    puts("-- checking that one byte does not trigger an event..");
260200483Srwatson    kevent_socket_fill();
261200483Srwatson    test_no_kevents();
262200483Srwatson
263200483Srwatson    puts("-- checking that two bytes triggers an event..");
264200483Srwatson    kevent_socket_fill();
265200483Srwatson    if (kevent(kqfd, NULL, 0, &kev, 1, NULL) != 1)
266200483Srwatson        err(1, "%s", test_id);
267200483Srwatson    KEV_CMP(kev, sockfd[0], EVFILT_READ, 0);
268200483Srwatson    test_no_kevents();
269200483Srwatson
270200483Srwatson    kevent_socket_drain();
271200483Srwatson    kevent_socket_drain();
272200483Srwatson
273200483Srwatson    success();
274200483Srwatson}
275200483Srwatson#endif
276200483Srwatson
277200483Srwatsonvoid
278200483Srwatsontest_kevent_socket_eof(void)
279200483Srwatson{
280200483Srwatson    const char *test_id = "kevent(EVFILT_READ, EV_EOF)";
281200483Srwatson    struct kevent kev;
282200483Srwatson
283200483Srwatson    test_begin(test_id);
284200483Srwatson
285200483Srwatson    /* Re-add the watch and make sure no events are pending */
286200483Srwatson    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]);
287200483Srwatson    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
288200483Srwatson        err(1, "%s", test_id);
289200483Srwatson    test_no_kevents();
290200483Srwatson
291200483Srwatson    if (close(sockfd[1]) < 0)
292200483Srwatson        err(1, "close(2)");
293200483Srwatson
294200483Srwatson    kev.flags |= EV_EOF;
295200483Srwatson    kevent_cmp(&kev, kevent_get(kqfd));
296200483Srwatson
297200483Srwatson    /* Delete the watch */
298200483Srwatson    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);
299200483Srwatson    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
300200483Srwatson        err(1, "%s", test_id);
301200483Srwatson
302200483Srwatson    success();
303200483Srwatson}
304200483Srwatson
305200483Srwatsonvoid
306200483Srwatsontest_evfilt_read()
307200483Srwatson{
308200483Srwatson    /* Create a connected pair of full-duplex sockets for testing socket events */
309200483Srwatson    if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) < 0)
310200483Srwatson        abort();
311200483Srwatson
312200483Srwatson    kqfd = kqueue();
313200483Srwatson    test_kevent_socket_add();
314200483Srwatson    test_kevent_socket_del();
315200483Srwatson    test_kevent_socket_get();
316200483Srwatson    test_kevent_socket_disable_and_enable();
317200483Srwatson    test_kevent_socket_oneshot();
318200483Srwatson    test_kevent_socket_clear();
319200483Srwatson#if HAVE_EV_DISPATCH
320200483Srwatson    test_kevent_socket_dispatch();
321200483Srwatson#endif
322200483Srwatson    test_kevent_socket_eof();
323200483Srwatson    close(kqfd);
324200483Srwatson}
325