Deleted Added
full compact
main.c (288683) main.c (295012)
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 *
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: head/tests/sys/kqueue/main.c 223845 2011-07-07 18:07:03Z jonathan $
16 * $FreeBSD: head/tests/sys/kqueue/main.c 295012 2016-01-28 20:24:15Z vangyzen $
17 */
18
19#include <sys/types.h>
20
21#include "config.h"
22#include "common.h"
23
24int testnum = 1;
25char *cur_test_id = NULL;
26int kqfd;
27
28extern void test_evfilt_read();
29extern void test_evfilt_signal();
30extern void test_evfilt_vnode();
31extern void test_evfilt_timer();
32extern void test_evfilt_proc();
33#if HAVE_EVFILT_USER
34extern void test_evfilt_user();
35#endif
36
37/* Checks if any events are pending, which is an error. */
38void
39test_no_kevents(void)
40{
41 int nfds;
42 struct timespec timeo;
43 struct kevent kev;
44
45 puts("confirming that there are no events pending");
46 memset(&timeo, 0, sizeof(timeo));
47 nfds = kevent(kqfd, NULL, 0, &kev, 1, &timeo);
48 if (nfds != 0) {
49 puts("\nUnexpected event:");
50 puts(kevent_to_str(&kev));
51 errx(1, "%d event(s) pending, but none expected:", nfds);
52 }
53}
54
55/* Retrieve a single kevent */
56struct kevent *
57kevent_get(int kqfd)
58{
59 int nfds;
60 struct kevent *kev;
61
62 if ((kev = calloc(1, sizeof(*kev))) == NULL)
63 err(1, "out of memory");
64
65 nfds = kevent(kqfd, NULL, 0, kev, 1, NULL);
66 if (nfds < 1)
67 err(1, "kevent(2)");
68
69 return (kev);
70}
71
17 */
18
19#include <sys/types.h>
20
21#include "config.h"
22#include "common.h"
23
24int testnum = 1;
25char *cur_test_id = NULL;
26int kqfd;
27
28extern void test_evfilt_read();
29extern void test_evfilt_signal();
30extern void test_evfilt_vnode();
31extern void test_evfilt_timer();
32extern void test_evfilt_proc();
33#if HAVE_EVFILT_USER
34extern void test_evfilt_user();
35#endif
36
37/* Checks if any events are pending, which is an error. */
38void
39test_no_kevents(void)
40{
41 int nfds;
42 struct timespec timeo;
43 struct kevent kev;
44
45 puts("confirming that there are no events pending");
46 memset(&timeo, 0, sizeof(timeo));
47 nfds = kevent(kqfd, NULL, 0, &kev, 1, &timeo);
48 if (nfds != 0) {
49 puts("\nUnexpected event:");
50 puts(kevent_to_str(&kev));
51 errx(1, "%d event(s) pending, but none expected:", nfds);
52 }
53}
54
55/* Retrieve a single kevent */
56struct kevent *
57kevent_get(int kqfd)
58{
59 int nfds;
60 struct kevent *kev;
61
62 if ((kev = calloc(1, sizeof(*kev))) == NULL)
63 err(1, "out of memory");
64
65 nfds = kevent(kqfd, NULL, 0, kev, 1, NULL);
66 if (nfds < 1)
67 err(1, "kevent(2)");
68
69 return (kev);
70}
71
72/* Retrieve a single kevent, specifying a maximum time to wait for it. */
73struct kevent *
74kevent_get_timeout(int kqfd, int seconds)
75{
76 int nfds;
77 struct kevent *kev;
78 struct timespec timeout = {seconds, 0};
79
80 if ((kev = calloc(1, sizeof(*kev))) == NULL)
81 err(1, "out of memory");
82
83 nfds = kevent(kqfd, NULL, 0, kev, 1, &timeout);
84 if (nfds < 0) {
85 err(1, "kevent(2)");
86 } else if (nfds == 0) {
87 free(kev);
88 kev = NULL;
89 }
90
91 return (kev);
92}
93
72char *
73kevent_fflags_dump(struct kevent *kev)
74{
75 char *buf;
76
77#define KEVFFL_DUMP(attrib) \
78 if (kev->fflags & attrib) \
79 strncat(buf, #attrib" ", 64);
80
81 if ((buf = calloc(1, 1024)) == NULL)
82 abort();
83
84 /* Not every filter has meaningful fflags */
94char *
95kevent_fflags_dump(struct kevent *kev)
96{
97 char *buf;
98
99#define KEVFFL_DUMP(attrib) \
100 if (kev->fflags & attrib) \
101 strncat(buf, #attrib" ", 64);
102
103 if ((buf = calloc(1, 1024)) == NULL)
104 abort();
105
106 /* Not every filter has meaningful fflags */
85 if (kev->filter != EVFILT_VNODE) {
86 snprintf(buf, 1024, "fflags = %d", kev->fflags);
87 return (buf);
88 }
89
90 snprintf(buf, 1024, "fflags = %d (", kev->fflags);
91 KEVFFL_DUMP(NOTE_DELETE);
92 KEVFFL_DUMP(NOTE_WRITE);
93 KEVFFL_DUMP(NOTE_EXTEND);
107 if (kev->filter == EVFILT_PROC) {
108 snprintf(buf, 1024, "fflags = %x (", kev->fflags);
109 KEVFFL_DUMP(NOTE_EXIT);
110 KEVFFL_DUMP(NOTE_FORK);
111 KEVFFL_DUMP(NOTE_EXEC);
112 KEVFFL_DUMP(NOTE_CHILD);
113 KEVFFL_DUMP(NOTE_TRACKERR);
114 KEVFFL_DUMP(NOTE_TRACK);
115 buf[strlen(buf) - 1] = ')';
116 } else if (kev->filter == EVFILT_PROCDESC) {
117 snprintf(buf, 1024, "fflags = %x (", kev->fflags);
118 KEVFFL_DUMP(NOTE_EXIT);
119 KEVFFL_DUMP(NOTE_FORK);
120 KEVFFL_DUMP(NOTE_EXEC);
121 buf[strlen(buf) - 1] = ')';
122 } else if (kev->filter == EVFILT_VNODE) {
123 snprintf(buf, 1024, "fflags = %x (", kev->fflags);
124 KEVFFL_DUMP(NOTE_DELETE);
125 KEVFFL_DUMP(NOTE_WRITE);
126 KEVFFL_DUMP(NOTE_EXTEND);
94#if HAVE_NOTE_TRUNCATE
127#if HAVE_NOTE_TRUNCATE
95 KEVFFL_DUMP(NOTE_TRUNCATE);
128 KEVFFL_DUMP(NOTE_TRUNCATE);
96#endif
129#endif
97 KEVFFL_DUMP(NOTE_ATTRIB);
98 KEVFFL_DUMP(NOTE_LINK);
99 KEVFFL_DUMP(NOTE_RENAME);
130 KEVFFL_DUMP(NOTE_ATTRIB);
131 KEVFFL_DUMP(NOTE_LINK);
132 KEVFFL_DUMP(NOTE_RENAME);
100#if HAVE_NOTE_REVOKE
133#if HAVE_NOTE_REVOKE
101 KEVFFL_DUMP(NOTE_REVOKE);
134 KEVFFL_DUMP(NOTE_REVOKE);
102#endif
135#endif
103 buf[strlen(buf) - 1] = ')';
136 buf[strlen(buf) - 1] = ')';
137 } else {
138 snprintf(buf, 1024, "fflags = %x", kev->fflags);
139 }
104
105 return (buf);
106}
107
108char *
109kevent_flags_dump(struct kevent *kev)
110{
111 char *buf;
112
113#define KEVFL_DUMP(attrib) \
114 if (kev->flags & attrib) \
115 strncat(buf, #attrib" ", 64);
116
117 if ((buf = calloc(1, 1024)) == NULL)
118 abort();
119
120 snprintf(buf, 1024, "flags = %d (", kev->flags);
121 KEVFL_DUMP(EV_ADD);
122 KEVFL_DUMP(EV_ENABLE);
123 KEVFL_DUMP(EV_DISABLE);
124 KEVFL_DUMP(EV_DELETE);
125 KEVFL_DUMP(EV_ONESHOT);
126 KEVFL_DUMP(EV_CLEAR);
127 KEVFL_DUMP(EV_EOF);
128 KEVFL_DUMP(EV_ERROR);
129#if HAVE_EV_DISPATCH
130 KEVFL_DUMP(EV_DISPATCH);
131#endif
132#if HAVE_EV_RECEIPT
133 KEVFL_DUMP(EV_RECEIPT);
134#endif
135 buf[strlen(buf) - 1] = ')';
136
137 return (buf);
138}
139
140/* Copied from ../kevent.c kevent_dump() and improved */
141const char *
142kevent_to_str(struct kevent *kev)
143{
144 char buf[512];
145
146 snprintf(&buf[0], sizeof(buf),
147 "[ident=%d, filter=%d, %s, %s, data=%d, udata=%p]",
148 (u_int) kev->ident,
149 kev->filter,
150 kevent_flags_dump(kev),
151 kevent_fflags_dump(kev),
152 (int) kev->data,
153 kev->udata);
154
155 return (strdup(buf));
156}
157
158void
159kevent_add(int kqfd, struct kevent *kev,
160 uintptr_t ident,
161 short filter,
162 u_short flags,
163 u_int fflags,
164 intptr_t data,
165 void *udata)
166{
167 EV_SET(kev, ident, filter, flags, fflags, data, NULL);
168 if (kevent(kqfd, kev, 1, NULL, 0, NULL) < 0) {
169 printf("Unable to add the following kevent:\n%s\n",
170 kevent_to_str(kev));
171 err(1, "kevent(): %s", strerror(errno));
172 }
173}
174
175void
176kevent_cmp(struct kevent *k1, struct kevent *k2)
177{
178/* XXX-
179 Workaround for inconsistent implementation of kevent(2)
180 */
181#ifdef __FreeBSD__
182 if (k1->flags & EV_ADD)
183 k2->flags |= EV_ADD;
184#endif
185 if (memcmp(k1, k2, sizeof(*k1)) != 0) {
186 printf("kevent_cmp: mismatch:\n %s !=\n %s\n",
187 kevent_to_str(k1), kevent_to_str(k2));
188 abort();
189 }
190}
191
192void
193test_begin(const char *func)
194{
195 if (cur_test_id)
196 free(cur_test_id);
197 cur_test_id = strdup(func);
198 if (!cur_test_id)
199 err(1, "strdup failed");
200
201 printf("\n\nTest %d: %s\n", testnum++, func);
202}
203
204void
205success(void)
206{
207 printf("%-70s %s\n", cur_test_id, "passed");
208 free(cur_test_id);
209 cur_test_id = NULL;
210}
211
212void
213test_kqueue(void)
214{
215 test_begin("kqueue()");
216 if ((kqfd = kqueue()) < 0)
217 err(1, "kqueue()");
218 test_no_kevents();
219 success();
220}
221
222void
223test_kqueue_close(void)
224{
225 test_begin("close(kq)");
226 if (close(kqfd) < 0)
227 err(1, "close()");
228 success();
229}
230
231int
232main(int argc, char **argv)
233{
234 int test_proc = 1;
235 int test_socket = 1;
236 int test_signal = 1;
237 int test_vnode = 1;
238 int test_timer = 1;
239#ifdef __FreeBSD__
240 int test_user = 1;
241#else
242 /* XXX-FIXME temporary */
243 int test_user = 0;
244#endif
245
246 while (argc) {
247 if (strcmp(argv[0], "--no-proc") == 0)
248 test_proc = 0;
249 if (strcmp(argv[0], "--no-socket") == 0)
250 test_socket = 0;
251 if (strcmp(argv[0], "--no-timer") == 0)
252 test_timer = 0;
253 if (strcmp(argv[0], "--no-signal") == 0)
254 test_signal = 0;
255 if (strcmp(argv[0], "--no-vnode") == 0)
256 test_vnode = 0;
257 if (strcmp(argv[0], "--no-user") == 0)
258 test_user = 0;
259 argv++;
260 argc--;
261 }
262
140
141 return (buf);
142}
143
144char *
145kevent_flags_dump(struct kevent *kev)
146{
147 char *buf;
148
149#define KEVFL_DUMP(attrib) \
150 if (kev->flags & attrib) \
151 strncat(buf, #attrib" ", 64);
152
153 if ((buf = calloc(1, 1024)) == NULL)
154 abort();
155
156 snprintf(buf, 1024, "flags = %d (", kev->flags);
157 KEVFL_DUMP(EV_ADD);
158 KEVFL_DUMP(EV_ENABLE);
159 KEVFL_DUMP(EV_DISABLE);
160 KEVFL_DUMP(EV_DELETE);
161 KEVFL_DUMP(EV_ONESHOT);
162 KEVFL_DUMP(EV_CLEAR);
163 KEVFL_DUMP(EV_EOF);
164 KEVFL_DUMP(EV_ERROR);
165#if HAVE_EV_DISPATCH
166 KEVFL_DUMP(EV_DISPATCH);
167#endif
168#if HAVE_EV_RECEIPT
169 KEVFL_DUMP(EV_RECEIPT);
170#endif
171 buf[strlen(buf) - 1] = ')';
172
173 return (buf);
174}
175
176/* Copied from ../kevent.c kevent_dump() and improved */
177const char *
178kevent_to_str(struct kevent *kev)
179{
180 char buf[512];
181
182 snprintf(&buf[0], sizeof(buf),
183 "[ident=%d, filter=%d, %s, %s, data=%d, udata=%p]",
184 (u_int) kev->ident,
185 kev->filter,
186 kevent_flags_dump(kev),
187 kevent_fflags_dump(kev),
188 (int) kev->data,
189 kev->udata);
190
191 return (strdup(buf));
192}
193
194void
195kevent_add(int kqfd, struct kevent *kev,
196 uintptr_t ident,
197 short filter,
198 u_short flags,
199 u_int fflags,
200 intptr_t data,
201 void *udata)
202{
203 EV_SET(kev, ident, filter, flags, fflags, data, NULL);
204 if (kevent(kqfd, kev, 1, NULL, 0, NULL) < 0) {
205 printf("Unable to add the following kevent:\n%s\n",
206 kevent_to_str(kev));
207 err(1, "kevent(): %s", strerror(errno));
208 }
209}
210
211void
212kevent_cmp(struct kevent *k1, struct kevent *k2)
213{
214/* XXX-
215 Workaround for inconsistent implementation of kevent(2)
216 */
217#ifdef __FreeBSD__
218 if (k1->flags & EV_ADD)
219 k2->flags |= EV_ADD;
220#endif
221 if (memcmp(k1, k2, sizeof(*k1)) != 0) {
222 printf("kevent_cmp: mismatch:\n %s !=\n %s\n",
223 kevent_to_str(k1), kevent_to_str(k2));
224 abort();
225 }
226}
227
228void
229test_begin(const char *func)
230{
231 if (cur_test_id)
232 free(cur_test_id);
233 cur_test_id = strdup(func);
234 if (!cur_test_id)
235 err(1, "strdup failed");
236
237 printf("\n\nTest %d: %s\n", testnum++, func);
238}
239
240void
241success(void)
242{
243 printf("%-70s %s\n", cur_test_id, "passed");
244 free(cur_test_id);
245 cur_test_id = NULL;
246}
247
248void
249test_kqueue(void)
250{
251 test_begin("kqueue()");
252 if ((kqfd = kqueue()) < 0)
253 err(1, "kqueue()");
254 test_no_kevents();
255 success();
256}
257
258void
259test_kqueue_close(void)
260{
261 test_begin("close(kq)");
262 if (close(kqfd) < 0)
263 err(1, "close()");
264 success();
265}
266
267int
268main(int argc, char **argv)
269{
270 int test_proc = 1;
271 int test_socket = 1;
272 int test_signal = 1;
273 int test_vnode = 1;
274 int test_timer = 1;
275#ifdef __FreeBSD__
276 int test_user = 1;
277#else
278 /* XXX-FIXME temporary */
279 int test_user = 0;
280#endif
281
282 while (argc) {
283 if (strcmp(argv[0], "--no-proc") == 0)
284 test_proc = 0;
285 if (strcmp(argv[0], "--no-socket") == 0)
286 test_socket = 0;
287 if (strcmp(argv[0], "--no-timer") == 0)
288 test_timer = 0;
289 if (strcmp(argv[0], "--no-signal") == 0)
290 test_signal = 0;
291 if (strcmp(argv[0], "--no-vnode") == 0)
292 test_vnode = 0;
293 if (strcmp(argv[0], "--no-user") == 0)
294 test_user = 0;
295 argv++;
296 argc--;
297 }
298
299 /*
300 * Some tests fork. If output is fully buffered,
301 * the children inherit some buffered data and flush
302 * it when they exit, causing some data to be printed twice.
303 * Use line buffering to avoid this problem.
304 */
305 setlinebuf(stdout);
306 setlinebuf(stderr);
307
263 test_kqueue();
264 test_kqueue_close();
265
266 if (test_socket)
267 test_evfilt_read();
268 if (test_signal)
269 test_evfilt_signal();
270 if (test_vnode)
271 test_evfilt_vnode();
272#if HAVE_EVFILT_USER
273 if (test_user)
274 test_evfilt_user();
275#endif
276 if (test_timer)
277 test_evfilt_timer();
278 if (test_proc)
279 test_evfilt_proc();
280
281 printf("\n---\n"
282 "+OK All %d tests completed.\n", testnum - 1);
283 return (0);
284}
308 test_kqueue();
309 test_kqueue_close();
310
311 if (test_socket)
312 test_evfilt_read();
313 if (test_signal)
314 test_evfilt_signal();
315 if (test_vnode)
316 test_evfilt_vnode();
317#if HAVE_EVFILT_USER
318 if (test_user)
319 test_evfilt_user();
320#endif
321 if (test_timer)
322 test_evfilt_timer();
323 if (test_proc)
324 test_evfilt_proc();
325
326 printf("\n---\n"
327 "+OK All %d tests completed.\n", testnum - 1);
328 return (0);
329}