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: stable/10/tests/sys/kqueue/libkqueue/read.c 305467 2016-09-06 08:45:29Z ngie $
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
127295786Smarkj    /*
128295786Smarkj     * Write to the socket before adding the event. This way we can verify that
129295786Smarkj     * enabling a triggered kevent causes the event to be returned immediately.
130295786Smarkj     */
131295786Smarkj    kevent_socket_fill();
132295786Smarkj
133295786Smarkj    /* Add a disabled event. */
134295786Smarkj    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_DISABLE, 0, 0, &sockfd[0]);
135200483Srwatson    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
136200483Srwatson        err(1, "%s", test_id);
137200483Srwatson
138200483Srwatson    test_no_kevents();
139200483Srwatson
140200483Srwatson    /* Re-enable the knote, then see if an event is generated */
141200483Srwatson    kev.flags = EV_ENABLE;
142200483Srwatson    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
143200483Srwatson        err(1, "%s", test_id);
144200483Srwatson    kev.flags = EV_ADD;
145200483Srwatson    kev.data = 1;
146200483Srwatson    kevent_cmp(&kev, kevent_get(kqfd));
147200483Srwatson
148200483Srwatson    kevent_socket_drain();
149200483Srwatson
150200483Srwatson    kev.flags = EV_DELETE;
151200483Srwatson    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
152200483Srwatson        err(1, "%s", test_id);
153200483Srwatson
154200483Srwatson    success();
155200483Srwatson}
156200483Srwatson
157200483Srwatsonvoid
158200483Srwatsontest_kevent_socket_del(void)
159200483Srwatson{
160200483Srwatson    const char *test_id = "kevent(EVFILT_READ, EV_DELETE)";
161200483Srwatson    struct kevent kev;
162200483Srwatson
163200483Srwatson    test_begin(test_id);
164200483Srwatson
165200483Srwatson    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);
166200483Srwatson    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
167200483Srwatson        err(1, "%s", test_id);
168200483Srwatson
169200483Srwatson    kevent_socket_fill();
170200483Srwatson    test_no_kevents();
171200483Srwatson    kevent_socket_drain();
172200483Srwatson
173200483Srwatson    success();
174200483Srwatson}
175200483Srwatson
176200483Srwatsonvoid
177200483Srwatsontest_kevent_socket_oneshot(void)
178200483Srwatson{
179200483Srwatson    const char *test_id = "kevent(EVFILT_READ, EV_ONESHOT)";
180200483Srwatson    struct kevent kev;
181200483Srwatson
182200483Srwatson    test_begin(test_id);
183200483Srwatson
184200483Srwatson    /* Re-add the watch and make sure no events are pending */
185200483Srwatson    puts("-- re-adding knote");
186200483Srwatson    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &sockfd[0]);
187200483Srwatson    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
188200483Srwatson        err(1, "%s", test_id);
189200483Srwatson    test_no_kevents();
190200483Srwatson
191200483Srwatson    puts("-- getting one event");
192200483Srwatson    kevent_socket_fill();
193200483Srwatson    kev.data = 1;
194200483Srwatson    kevent_cmp(&kev, kevent_get(kqfd));
195200483Srwatson
196200483Srwatson    puts("-- checking knote disabled");
197200483Srwatson    test_no_kevents();
198200483Srwatson
199200483Srwatson    /* Try to delete the knote, it should already be deleted */
200200483Srwatson    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);
201200483Srwatson    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) == 0)
202200483Srwatson        err(1, "%s", test_id);
203200483Srwatson
204200483Srwatson    kevent_socket_drain();
205200483Srwatson
206200483Srwatson    success();
207200483Srwatson}
208200483Srwatson
209200483Srwatson
210200483Srwatson#if HAVE_EV_DISPATCH
211200483Srwatsonvoid
212200483Srwatsontest_kevent_socket_dispatch(void)
213200483Srwatson{
214200483Srwatson    const char *test_id = "kevent(EVFILT_READ, EV_DISPATCH)";
215200483Srwatson
216200483Srwatson    test_begin(test_id);
217200483Srwatson
218200483Srwatson    struct kevent kev;
219200483Srwatson
220200483Srwatson    /* Re-add the watch and make sure no events are pending */
221200483Srwatson    puts("-- re-adding knote");
222200483Srwatson    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_DISPATCH, 0, 0, &sockfd[0]);
223200483Srwatson    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
224200483Srwatson        err(1, "%s", test_id);
225200483Srwatson    test_no_kevents();
226200483Srwatson
227200483Srwatson    /* The event will occur only once, even though EV_CLEAR is not
228200483Srwatson       specified. */
229200483Srwatson    kevent_socket_fill();
230200483Srwatson    kev.data = 1;
231200483Srwatson    kevent_cmp(&kev, kevent_get(kqfd));
232200483Srwatson    test_no_kevents();
233200483Srwatson
234200483Srwatson    /* Since the knote is disabled, the EV_DELETE operation succeeds. */
235200483Srwatson    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);
236200483Srwatson    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
237200483Srwatson        err(1, "%s", test_id);
238200483Srwatson
239200483Srwatson    kevent_socket_drain();
240200483Srwatson
241200483Srwatson    success();
242200483Srwatson}
243200483Srwatson#endif  /* HAVE_EV_DISPATCH */
244200483Srwatson
245200483Srwatson#if BROKEN
246200483Srwatsonvoid
247200483Srwatsontest_kevent_socket_lowat(void)
248200483Srwatson{
249200483Srwatson    const char *test_id = "kevent(EVFILT_READ, NOTE_LOWAT)";
250200483Srwatson    struct kevent kev;
251200483Srwatson
252200483Srwatson    test_begin(test_id);
253200483Srwatson
254200483Srwatson    /* Re-add the watch and make sure no events are pending */
255200483Srwatson    puts("-- re-adding knote, setting low watermark to 2 bytes");
256200483Srwatson    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, NOTE_LOWAT, 2, &sockfd[0]);
257200483Srwatson    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
258200483Srwatson        err(1, "%s", test_id);
259200483Srwatson    test_no_kevents();
260200483Srwatson
261200483Srwatson    puts("-- checking that one byte does not trigger an event..");
262200483Srwatson    kevent_socket_fill();
263200483Srwatson    test_no_kevents();
264200483Srwatson
265200483Srwatson    puts("-- checking that two bytes triggers an event..");
266200483Srwatson    kevent_socket_fill();
267200483Srwatson    if (kevent(kqfd, NULL, 0, &kev, 1, NULL) != 1)
268200483Srwatson        err(1, "%s", test_id);
269200483Srwatson    KEV_CMP(kev, sockfd[0], EVFILT_READ, 0);
270200483Srwatson    test_no_kevents();
271200483Srwatson
272200483Srwatson    kevent_socket_drain();
273200483Srwatson    kevent_socket_drain();
274200483Srwatson
275200483Srwatson    success();
276200483Srwatson}
277200483Srwatson#endif
278200483Srwatson
279200483Srwatsonvoid
280200483Srwatsontest_kevent_socket_eof(void)
281200483Srwatson{
282200483Srwatson    const char *test_id = "kevent(EVFILT_READ, EV_EOF)";
283200483Srwatson    struct kevent kev;
284200483Srwatson
285200483Srwatson    test_begin(test_id);
286200483Srwatson
287200483Srwatson    /* Re-add the watch and make sure no events are pending */
288200483Srwatson    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]);
289200483Srwatson    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
290200483Srwatson        err(1, "%s", test_id);
291200483Srwatson    test_no_kevents();
292200483Srwatson
293200483Srwatson    if (close(sockfd[1]) < 0)
294200483Srwatson        err(1, "close(2)");
295200483Srwatson
296200483Srwatson    kev.flags |= EV_EOF;
297200483Srwatson    kevent_cmp(&kev, kevent_get(kqfd));
298200483Srwatson
299200483Srwatson    /* Delete the watch */
300200483Srwatson    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);
301200483Srwatson    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
302200483Srwatson        err(1, "%s", test_id);
303200483Srwatson
304200483Srwatson    success();
305200483Srwatson}
306200483Srwatson
307200483Srwatsonvoid
308200483Srwatsontest_evfilt_read()
309200483Srwatson{
310200483Srwatson    /* Create a connected pair of full-duplex sockets for testing socket events */
311200483Srwatson    if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) < 0)
312200483Srwatson        abort();
313200483Srwatson
314200483Srwatson    kqfd = kqueue();
315200483Srwatson    test_kevent_socket_add();
316200483Srwatson    test_kevent_socket_del();
317200483Srwatson    test_kevent_socket_get();
318200483Srwatson    test_kevent_socket_disable_and_enable();
319200483Srwatson    test_kevent_socket_oneshot();
320200483Srwatson    test_kevent_socket_clear();
321200483Srwatson#if HAVE_EV_DISPATCH
322200483Srwatson    test_kevent_socket_dispatch();
323200483Srwatson#endif
324200483Srwatson    test_kevent_socket_eof();
325200483Srwatson    close(kqfd);
326200483Srwatson}
327