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