Super User's BSD Cross Reference: /FreeBSD/tests/sys/kqueue/libkqueue/read.c

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

AltStyle によって変換されたページ (->オリジナル) /