main.c revision 313507
138451Smsmith/* 238451Smsmith * Copyright (c) 2009 Mark Heily <mark@heily.com> 338451Smsmith * 438451Smsmith * Permission to use, copy, modify, and distribute this software for any 538451Smsmith * purpose with or without fee is hereby granted, provided that the above 638451Smsmith * copyright notice and this permission notice appear in all copies. 738451Smsmith * 838451Smsmith * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 938451Smsmith * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1038451Smsmith * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1138451Smsmith * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1238451Smsmith * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1338451Smsmith * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1438451Smsmith * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1538451Smsmith * 1638451Smsmith * $FreeBSD: stable/10/tests/sys/kqueue/libkqueue/main.c 313507 2017-02-10 02:29:09Z ngie $ 1738451Smsmith */ 1838451Smsmith 1938451Smsmith#include <sys/types.h> 2038451Smsmith 2138451Smsmith#include "config.h" 2238451Smsmith#include "common.h" 2338451Smsmith 2438451Smsmithint testnum = 1; 2538451Smsmithchar *cur_test_id = NULL; 2638451Smsmithint kqfd; 2738451Smsmith 2838451Smsmithextern void test_evfilt_read(); 2938451Smsmithextern void test_evfilt_signal(); 3038451Smsmithextern void test_evfilt_vnode(); 3138451Smsmithextern void test_evfilt_timer(); 3238451Smsmithextern void test_evfilt_proc(); 3338451Smsmith#if HAVE_EVFILT_USER 3438451Smsmithextern void test_evfilt_user(); 3538451Smsmith#endif 3638451Smsmith 3738451Smsmith/* Checks if any events are pending, which is an error. */ 3884221Sdillonvoid 3984221Sdillontest_no_kevents(void) 4084221Sdillon{ 4138451Smsmith int nfds; 4238451Smsmith struct timespec timeo; 4338451Smsmith struct kevent kev; 4438451Smsmith 4538451Smsmith puts("confirming that there are no events pending"); 4638451Smsmith memset(&timeo, 0, sizeof(timeo)); 4738451Smsmith nfds = kevent(kqfd, NULL, 0, &kev, 1, &timeo); 4838451Smsmith if (nfds != 0) { 4938451Smsmith puts("\nUnexpected event:"); 5038451Smsmith puts(kevent_to_str(&kev)); 5138451Smsmith errx(1, "%d event(s) pending, but none expected:", nfds); 5238451Smsmith } 5338451Smsmith} 5438451Smsmith 5538451Smsmith/* Retrieve a single kevent */ 5638451Smsmithstruct kevent * 5738451Smsmithkevent_get(int kqfd) 5838451Smsmith{ 5938451Smsmith int nfds; 6038451Smsmith struct kevent *kev; 6138451Smsmith 6238451Smsmith if ((kev = calloc(1, sizeof(*kev))) == NULL) 6338451Smsmith err(1, "out of memory"); 6438451Smsmith 6538451Smsmith nfds = kevent(kqfd, NULL, 0, kev, 1, NULL); 6638451Smsmith if (nfds < 1) 6738451Smsmith err(1, "kevent(2)"); 68330898Skevans 6938451Smsmith return (kev); 7038451Smsmith} 7138451Smsmith 72329100Skevans/* Retrieve a single kevent, specifying a maximum time to wait for it. */ 7338451Smsmithstruct kevent * 7492913Sobrienkevent_get_timeout(int kqfd, int seconds) 7592913Sobrien{ 7692913Sobrien int nfds; 77329100Skevans struct kevent *kev; 7838451Smsmith struct timespec timeout = {seconds, 0}; 7938451Smsmith 8038451Smsmith if ((kev = calloc(1, sizeof(*kev))) == NULL) 8138451Smsmith err(1, "out of memory"); 8238451Smsmith 8338451Smsmith nfds = kevent(kqfd, NULL, 0, kev, 1, &timeout); 8438451Smsmith if (nfds < 0) { 8538451Smsmith err(1, "kevent(2)"); 8638451Smsmith } else if (nfds == 0) { 8738451Smsmith free(kev); 8838451Smsmith kev = NULL; 8938451Smsmith } 9038451Smsmith 9138451Smsmith return (kev); 9238451Smsmith} 9338451Smsmith 9438451Smsmithchar * 9538451Smsmithkevent_fflags_dump(struct kevent *kev) 9638451Smsmith{ 9738451Smsmith char *buf; 9838451Smsmith 9938451Smsmith#define KEVFFL_DUMP(attrib) \ 10038451Smsmith if (kev->fflags & attrib) \ 10138451Smsmith strncat(buf, #attrib" ", 64); 10238451Smsmith 10338451Smsmith if ((buf = calloc(1, 1024)) == NULL) 10438451Smsmith abort(); 10538451Smsmith 10638451Smsmith /* Not every filter has meaningful fflags */ 10738451Smsmith if (kev->filter == EVFILT_PROC) { 10838451Smsmith snprintf(buf, 1024, "fflags = %x (", kev->fflags); 10938451Smsmith KEVFFL_DUMP(NOTE_EXIT); 11038451Smsmith KEVFFL_DUMP(NOTE_FORK); 11138451Smsmith KEVFFL_DUMP(NOTE_EXEC); 11238451Smsmith KEVFFL_DUMP(NOTE_CHILD); 11338451Smsmith KEVFFL_DUMP(NOTE_TRACKERR); 11438451Smsmith KEVFFL_DUMP(NOTE_TRACK); 11538451Smsmith buf[strlen(buf) - 1] = ')'; 11638451Smsmith } else if (kev->filter == EVFILT_VNODE) { 117329100Skevans snprintf(buf, 1024, "fflags = %x (", kev->fflags); 118329100Skevans KEVFFL_DUMP(NOTE_DELETE); 11938451Smsmith KEVFFL_DUMP(NOTE_WRITE); 12038451Smsmith KEVFFL_DUMP(NOTE_EXTEND); 121330898Skevans#if HAVE_NOTE_TRUNCATE 12238451Smsmith KEVFFL_DUMP(NOTE_TRUNCATE); 123346476Skevans#endif 12438451Smsmith KEVFFL_DUMP(NOTE_ATTRIB); 12538451Smsmith KEVFFL_DUMP(NOTE_LINK); 12638451Smsmith KEVFFL_DUMP(NOTE_RENAME); 12738451Smsmith#if HAVE_NOTE_REVOKE 12838451Smsmith KEVFFL_DUMP(NOTE_REVOKE); 12938451Smsmith#endif 130329100Skevans buf[strlen(buf) - 1] = ')'; 131329100Skevans } else { 132329100Skevans snprintf(buf, 1024, "fflags = %x", kev->fflags); 13338451Smsmith } 134329100Skevans 13538451Smsmith return (buf); 13638451Smsmith} 13738451Smsmith 13838451Smsmithchar * 13938451Smsmithkevent_flags_dump(struct kevent *kev) 14038451Smsmith{ 14138451Smsmith char *buf; 142329100Skevans 14338451Smsmith#define KEVFL_DUMP(attrib) \ 14438451Smsmith if (kev->flags & attrib) \ 14538451Smsmith strncat(buf, #attrib" ", 64); 14638451Smsmith 147329100Skevans if ((buf = calloc(1, 1024)) == NULL) 14838451Smsmith abort(); 14938451Smsmith 15038451Smsmith snprintf(buf, 1024, "flags = %d (", kev->flags); 15138451Smsmith KEVFL_DUMP(EV_ADD); 15238451Smsmith KEVFL_DUMP(EV_ENABLE); 15338451Smsmith KEVFL_DUMP(EV_DISABLE); 15438451Smsmith KEVFL_DUMP(EV_DELETE); 15538451Smsmith KEVFL_DUMP(EV_ONESHOT); 15638451Smsmith KEVFL_DUMP(EV_CLEAR); 15738451Smsmith KEVFL_DUMP(EV_EOF); 15838451Smsmith KEVFL_DUMP(EV_ERROR); 15938451Smsmith#if HAVE_EV_DISPATCH 16038451Smsmith KEVFL_DUMP(EV_DISPATCH); 16138451Smsmith#endif 16238451Smsmith#if HAVE_EV_RECEIPT 163330898Skevans KEVFL_DUMP(EV_RECEIPT); 16438451Smsmith#endif 16592913Sobrien buf[strlen(buf) - 1] = ')'; 16692913Sobrien 167332154Skevans return (buf); 168329100Skevans} 16938451Smsmith 17038451Smsmith/* Copied from ../kevent.c kevent_dump() and improved */ 17138451Smsmithconst char * 17238451Smsmithkevent_to_str(struct kevent *kev) 17338451Smsmith{ 17438451Smsmith char buf[512]; 175329100Skevans 176329100Skevans snprintf(&buf[0], sizeof(buf), 17738451Smsmith "[ident=%d, filter=%d, %s, %s, data=%d, udata=%p]", 17838451Smsmith (u_int) kev->ident, 17938451Smsmith kev->filter, 18038451Smsmith kevent_flags_dump(kev), 18138451Smsmith kevent_fflags_dump(kev), 18238451Smsmith (int) kev->data, 183329100Skevans kev->udata); 18438451Smsmith 18538451Smsmith return (strdup(buf)); 18638451Smsmith} 18738451Smsmith 18838451Smsmithvoid 18938451Smsmithkevent_add(int kqfd, struct kevent *kev, 19038451Smsmith uintptr_t ident, 19138451Smsmith short filter, 192329100Skevans u_short flags, 19338451Smsmith u_int fflags, 19438451Smsmith intptr_t data, 19538451Smsmith void *udata) 19638451Smsmith{ 19738451Smsmith EV_SET(kev, ident, filter, flags, fflags, data, NULL); 19838451Smsmith if (kevent(kqfd, kev, 1, NULL, 0, NULL) < 0) { 19938451Smsmith printf("Unable to add the following kevent:\n%s\n", 20038451Smsmith kevent_to_str(kev)); 20138451Smsmith err(1, "kevent(): %s", strerror(errno)); 20238451Smsmith } 20338451Smsmith} 20438451Smsmith 20538451Smsmithvoid 206329100Skevanskevent_cmp(struct kevent *k1, struct kevent *k2) 20738451Smsmith{ 20838451Smsmith/* XXX- 20938451Smsmith Workaround for inconsistent implementation of kevent(2) 21038451Smsmith */ 21138451Smsmith#ifdef __FreeBSD__ 21238451Smsmith if (k1->flags & EV_ADD) 21338451Smsmith k2->flags |= EV_ADD; 21438451Smsmith#endif 21538451Smsmith if (memcmp(k1, k2, sizeof(*k1)) != 0) { 216329100Skevans printf("kevent_cmp: mismatch:\n %s !=\n %s\n", 21738451Smsmith kevent_to_str(k1), kevent_to_str(k2)); 21838451Smsmith abort(); 21938451Smsmith } 22038451Smsmith} 22138451Smsmith 22238451Smsmithvoid 22338451Smsmithtest_begin(const char *func) 22438451Smsmith{ 225329100Skevans if (cur_test_id) 22638451Smsmith free(cur_test_id); 22738451Smsmith cur_test_id = strdup(func); 22838451Smsmith if (!cur_test_id) 22938451Smsmith err(1, "strdup failed"); 23038451Smsmith 23138451Smsmith printf("\n\nTest %d: %s\n", testnum++, func); 23238451Smsmith} 23338451Smsmith 23438451Smsmithvoid 23538451Smsmithsuccess(void) 23638451Smsmith{ 237329100Skevans printf("%-70s %s\n", cur_test_id, "passed"); 23838451Smsmith free(cur_test_id); 23938451Smsmith cur_test_id = NULL; 24038451Smsmith} 24138451Smsmith 24238451Smsmithvoid 24338451Smsmithtest_kqueue(void) 24438451Smsmith{ 24538451Smsmith test_begin("kqueue()"); 24638451Smsmith if ((kqfd = kqueue()) < 0) 247329100Skevans err(1, "kqueue()"); 248329100Skevans test_no_kevents(); 24938451Smsmith success(); 25038451Smsmith} 25138451Smsmith 25238451Smsmithvoid 25338451Smsmithtest_kqueue_close(void) 25438451Smsmith{ 25538451Smsmith test_begin("close(kq)"); 25638451Smsmith if (close(kqfd) < 0) 257329100Skevans err(1, "close()"); 25838451Smsmith success(); 25938451Smsmith} 26038451Smsmith 26138451Smsmithint 26238451Smsmithmain(int argc, char **argv) 26338451Smsmith{ 26438451Smsmith int test_proc = 1; 26538451Smsmith int test_socket = 1; 26638451Smsmith int test_signal = 1; 26738451Smsmith int test_vnode = 1; 26838451Smsmith int test_timer = 1; 26938451Smsmith#ifdef __FreeBSD__ 27038451Smsmith int test_user = 1; 27138451Smsmith#else 27238451Smsmith /* XXX-FIXME temporary */ 27338451Smsmith int test_user = 0; 27438451Smsmith#endif 27538451Smsmith 27638451Smsmith while (argc) { 27738451Smsmith if (strcmp(argv[0], "--no-proc") == 0) 27838451Smsmith test_proc = 0; 27938451Smsmith if (strcmp(argv[0], "--no-socket") == 0) 28038451Smsmith test_socket = 0; 28138451Smsmith if (strcmp(argv[0], "--no-timer") == 0) 28238451Smsmith test_timer = 0; 28338451Smsmith if (strcmp(argv[0], "--no-signal") == 0) 28438451Smsmith test_signal = 0; 28538451Smsmith if (strcmp(argv[0], "--no-vnode") == 0) 28638451Smsmith test_vnode = 0; 28738451Smsmith if (strcmp(argv[0], "--no-user") == 0) 28838451Smsmith test_user = 0; 28938451Smsmith argv++; 29038451Smsmith argc--; 29138451Smsmith } 29238451Smsmith 29338451Smsmith /* 29438451Smsmith * Some tests fork. If output is fully buffered, 29538451Smsmith * the children inherit some buffered data and flush 29638451Smsmith * it when they exit, causing some data to be printed twice. 29738451Smsmith * Use line buffering to avoid this problem. 29838451Smsmith */ 29938451Smsmith setlinebuf(stdout); 30038451Smsmith setlinebuf(stderr); 30138451Smsmith 30238451Smsmith test_kqueue(); 30338451Smsmith test_kqueue_close(); 30438451Smsmith 30538451Smsmith if (test_socket) 306 test_evfilt_read(); 307 if (test_signal) 308 test_evfilt_signal(); 309 if (test_vnode) 310 test_evfilt_vnode(); 311#if HAVE_EVFILT_USER 312 if (test_user) 313 test_evfilt_user(); 314#endif 315 if (test_timer) 316 test_evfilt_timer(); 317 if (test_proc) 318 test_evfilt_proc(); 319 320 printf("\n---\n" 321 "+OK All %d tests completed.\n", testnum - 1); 322 return (0); 323} 324