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