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}
|