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