[Midnightbsd-cvs] src [11972] trunk/tests/sys/kqueue: add kqueue tests

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Sat Jul 28 16:42:59 EDT 2018


Revision: 11972
          http://svnweb.midnightbsd.org/src/?rev=11972
Author:   laffer1
Date:     2018-07-28 16:42:58 -0400 (Sat, 28 Jul 2018)
Log Message:
-----------
add kqueue tests

Added Paths:
-----------
    trunk/tests/sys/kqueue/
    trunk/tests/sys/kqueue/Makefile
    trunk/tests/sys/kqueue/libkqueue/
    trunk/tests/sys/kqueue/libkqueue/Makefile
    trunk/tests/sys/kqueue/libkqueue/Makefile.depend
    trunk/tests/sys/kqueue/libkqueue/common.h
    trunk/tests/sys/kqueue/libkqueue/config.h
    trunk/tests/sys/kqueue/libkqueue/kqueue_test.sh
    trunk/tests/sys/kqueue/libkqueue/main.c
    trunk/tests/sys/kqueue/libkqueue/proc.c
    trunk/tests/sys/kqueue/libkqueue/read.c
    trunk/tests/sys/kqueue/libkqueue/signal.c
    trunk/tests/sys/kqueue/libkqueue/timer.c
    trunk/tests/sys/kqueue/libkqueue/user.c
    trunk/tests/sys/kqueue/libkqueue/vnode.c
    trunk/tests/sys/kqueue/main.c
    trunk/tests/sys/kqueue/read.c

Added: trunk/tests/sys/kqueue/Makefile
===================================================================
--- trunk/tests/sys/kqueue/Makefile	                        (rev 0)
+++ trunk/tests/sys/kqueue/Makefile	2018-07-28 20:42:58 UTC (rev 11972)
@@ -0,0 +1,21 @@
+# $MidnightBSD$
+# $FreeBSD: stable/10/tests/sys/kqueue/Makefile 313508 2017-02-10 02:29:39Z ngie $
+
+TESTSRC=	${SRCTOP}/contrib/netbsd-tests/kernel/kqueue
+
+TESTSDIR=	${TESTSBASE}/sys/kqueue
+BINDIR=		${TESTSDIR}
+
+NETBSD_ATF_TESTS_C=	proc1_test
+# XXX: fails `ke.fflags & NOTE_TRACKERR` invariant
+#NETBSD_ATF_TESTS_C+=	proc2_test
+NETBSD_ATF_TESTS_C+=	proc3_test
+NETBSD_ATF_TESTS_C+=	sig_test
+NETBSD_ATF_TESTS_C+=	vnode_test
+
+WARNS?=		3
+
+TESTS_SUBDIRS+=	libkqueue
+
+.include <netbsd-tests.test.mk>
+.include <bsd.test.mk>


Property changes on: trunk/tests/sys/kqueue/Makefile
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/tests/sys/kqueue/libkqueue/Makefile
===================================================================
--- trunk/tests/sys/kqueue/libkqueue/Makefile	                        (rev 0)
+++ trunk/tests/sys/kqueue/libkqueue/Makefile	2018-07-28 20:42:58 UTC (rev 11972)
@@ -0,0 +1,22 @@
+# $MidnightBSD$
+# $FreeBSD: stable/10/tests/sys/kqueue/libkqueue/Makefile 305467 2016-09-06 08:45:29Z ngie $
+
+TESTSDIR=	${TESTSBASE}/sys/kqueue/libkqueue
+BINDIR=		${TESTSDIR}
+
+# libkqueue and test suite by Mark Heily <mark at heily.com>
+TAP_TESTS_SH=	kqueue_test
+
+PROGS=	kqtest
+
+SRCS.kqtest=		\
+	main.c		\
+	read.c		\
+	timer.c		\
+	vnode.c		\
+	proc.c		\
+	signal.c	\
+	user.c
+WARNS?=	2
+
+.include <bsd.test.mk>


Property changes on: trunk/tests/sys/kqueue/libkqueue/Makefile
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/tests/sys/kqueue/libkqueue/Makefile.depend
===================================================================
--- trunk/tests/sys/kqueue/libkqueue/Makefile.depend	                        (rev 0)
+++ trunk/tests/sys/kqueue/libkqueue/Makefile.depend	2018-07-28 20:42:58 UTC (rev 11972)
@@ -0,0 +1,19 @@
+# $MidnightBSD$
+# $FreeBSD: stable/10/tests/sys/kqueue/libkqueue/Makefile.depend 305467 2016-09-06 08:45:29Z ngie $
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+	gnu/lib/csu \
+	gnu/lib/libgcc \
+	include \
+	include/xlocale \
+	lib/${CSU_DIR} \
+	lib/libc \
+	lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif


Property changes on: trunk/tests/sys/kqueue/libkqueue/Makefile.depend
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/tests/sys/kqueue/libkqueue/common.h
===================================================================
--- trunk/tests/sys/kqueue/libkqueue/common.h	                        (rev 0)
+++ trunk/tests/sys/kqueue/libkqueue/common.h	2018-07-28 20:42:58 UTC (rev 11972)
@@ -0,0 +1,80 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (c) 2009 Mark Heily <mark at heily.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $FreeBSD: stable/10/tests/sys/kqueue/libkqueue/common.h 305467 2016-09-06 08:45:29Z ngie $
+ */
+
+#ifndef _COMMON_H
+#define _COMMON_H
+
+
+#if HAVE_ERR_H
+# include <err.h>
+#else
+# define err(rc,msg,...) do { perror(msg); exit(rc); } while (0)
+# define errx(rc,msg,...) do { puts(msg); exit(rc); } while (0)
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <sys/event.h>
+
+#include "config.h"
+
+extern char *cur_test_id;
+int vnode_fd;
+
+extern const char * kevent_to_str(struct kevent *);
+struct kevent * kevent_get(int);
+struct kevent * kevent_get_timeout(int, int);
+
+
+void kevent_cmp(struct kevent *, struct kevent *);
+
+void
+kevent_add(int kqfd, struct kevent *kev, 
+        uintptr_t ident,
+        short     filter,
+        u_short   flags,
+        u_int     fflags,
+        intptr_t  data,
+        void      *udata);
+
+/* DEPRECATED: */
+#define KEV_CMP(kev,_ident,_filter,_flags) do {                 \
+    if (kev.ident != (_ident) ||                                \
+            kev.filter != (_filter) ||                          \
+            kev.flags != (_flags)) \
+        err(1, "kevent mismatch: got [%d,%d,%d] but expecting [%d,%d,%d]", \
+                (int)_ident, (int)_filter, (int)_flags,\
+                (int)kev.ident, kev.filter, kev.flags);\
+} while (0);
+
+/* Checks if any events are pending, which is an error. */
+extern void test_no_kevents(void);
+
+extern void test_begin(const char *);
+extern void success(void);
+
+#endif  /* _COMMON_H */


Property changes on: trunk/tests/sys/kqueue/libkqueue/common.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/tests/sys/kqueue/libkqueue/config.h
===================================================================
--- trunk/tests/sys/kqueue/libkqueue/config.h	                        (rev 0)
+++ trunk/tests/sys/kqueue/libkqueue/config.h	2018-07-28 20:42:58 UTC (rev 11972)
@@ -0,0 +1,14 @@
+/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/tests/sys/kqueue/libkqueue/config.h 305467 2016-09-06 08:45:29Z ngie $ */
+
+#define HAVE_ERR_H 1
+#define HAVE_SYS_EVENT_H 1
+#define HAVE_EV_DISPATCH 1
+#define HAVE_EV_RECEIPT 1
+#undef HAVE_NOTE_TRUNCATE
+#define HAVE_EVFILT_TIMER 1
+#define HAVE_EVFILT_USER 1
+#define PROGRAM "libkqueue-test"
+#define VERSION "0.1"
+#define TARGET "freebsd"
+#define CFLAGS "-g -O0 -Wall -Werror"


Property changes on: trunk/tests/sys/kqueue/libkqueue/config.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/tests/sys/kqueue/libkqueue/kqueue_test.sh
===================================================================
--- trunk/tests/sys/kqueue/libkqueue/kqueue_test.sh	                        (rev 0)
+++ trunk/tests/sys/kqueue/libkqueue/kqueue_test.sh	2018-07-28 20:42:58 UTC (rev 11972)
@@ -0,0 +1,17 @@
+#!/bin/sh
+# $MidnightBSD$
+
+i=1
+"$(dirname $0)/kqtest" | while read line; do
+	echo $line | grep -q passed
+	if [ $? -eq 0 ]; then
+		echo "ok - $i $line"
+		: $(( i += 1 ))
+	fi
+
+	echo $line | grep -q 'tests completed'
+	if [ $? -eq 0 ]; then
+		echo -n "1.."
+		echo $line | cut -d' ' -f3
+	fi
+done


Property changes on: trunk/tests/sys/kqueue/libkqueue/kqueue_test.sh
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/tests/sys/kqueue/libkqueue/main.c
===================================================================
--- trunk/tests/sys/kqueue/libkqueue/main.c	                        (rev 0)
+++ trunk/tests/sys/kqueue/libkqueue/main.c	2018-07-28 20:42:58 UTC (rev 11972)
@@ -0,0 +1,324 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (c) 2009 Mark Heily <mark at heily.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $FreeBSD: stable/10/tests/sys/kqueue/libkqueue/main.c 313507 2017-02-10 02:29:09Z ngie $
+ */
+
+#include <sys/types.h>
+
+#include "config.h"
+#include "common.h"
+
+int testnum = 1;
+char *cur_test_id = NULL;
+int kqfd;
+
+extern void test_evfilt_read();
+extern void test_evfilt_signal();
+extern void test_evfilt_vnode();
+extern void test_evfilt_timer();
+extern void test_evfilt_proc();
+#if HAVE_EVFILT_USER
+extern void test_evfilt_user();
+#endif
+
+/* Checks if any events are pending, which is an error. */
+void 
+test_no_kevents(void)
+{
+    int nfds;
+    struct timespec timeo;
+    struct kevent kev;
+
+    puts("confirming that there are no events pending");
+    memset(&timeo, 0, sizeof(timeo));
+    nfds = kevent(kqfd, NULL, 0, &kev, 1, &timeo);
+    if (nfds != 0) {
+        puts("\nUnexpected event:");
+        puts(kevent_to_str(&kev));
+        errx(1, "%d event(s) pending, but none expected:", nfds);
+    }
+}
+
+/* Retrieve a single kevent */
+struct kevent *
+kevent_get(int kqfd)
+{
+    int nfds;
+    struct kevent *kev;
+
+    if ((kev = calloc(1, sizeof(*kev))) == NULL)
+	err(1, "out of memory");
+    
+    nfds = kevent(kqfd, NULL, 0, kev, 1, NULL);
+    if (nfds < 1)
+        err(1, "kevent(2)");
+
+    return (kev);
+}
+
+/* Retrieve a single kevent, specifying a maximum time to wait for it. */
+struct kevent *
+kevent_get_timeout(int kqfd, int seconds)
+{
+    int nfds;
+    struct kevent *kev;
+    struct timespec timeout = {seconds, 0};
+
+    if ((kev = calloc(1, sizeof(*kev))) == NULL)
+	err(1, "out of memory");
+    
+    nfds = kevent(kqfd, NULL, 0, kev, 1, &timeout);
+    if (nfds < 0) {
+        err(1, "kevent(2)");
+    } else if (nfds == 0) {
+        free(kev);
+        kev = NULL;
+    }
+
+    return (kev);
+}
+
+char *
+kevent_fflags_dump(struct kevent *kev)
+{
+    char *buf;
+
+#define KEVFFL_DUMP(attrib) \
+    if (kev->fflags & attrib) \
+	strncat(buf, #attrib" ", 64);
+
+    if ((buf = calloc(1, 1024)) == NULL)
+	abort();
+
+    /* Not every filter has meaningful fflags */
+    if (kev->filter == EVFILT_PROC) {
+        snprintf(buf, 1024, "fflags = %x (", kev->fflags);
+        KEVFFL_DUMP(NOTE_EXIT);
+        KEVFFL_DUMP(NOTE_FORK);
+        KEVFFL_DUMP(NOTE_EXEC);
+        KEVFFL_DUMP(NOTE_CHILD);
+        KEVFFL_DUMP(NOTE_TRACKERR);
+        KEVFFL_DUMP(NOTE_TRACK);
+        buf[strlen(buf) - 1] = ')';
+    } else if (kev->filter == EVFILT_VNODE) {
+        snprintf(buf, 1024, "fflags = %x (", kev->fflags);
+        KEVFFL_DUMP(NOTE_DELETE);
+        KEVFFL_DUMP(NOTE_WRITE);
+        KEVFFL_DUMP(NOTE_EXTEND);
+#if HAVE_NOTE_TRUNCATE
+        KEVFFL_DUMP(NOTE_TRUNCATE);
+#endif
+        KEVFFL_DUMP(NOTE_ATTRIB);
+        KEVFFL_DUMP(NOTE_LINK);
+        KEVFFL_DUMP(NOTE_RENAME);
+#if HAVE_NOTE_REVOKE
+        KEVFFL_DUMP(NOTE_REVOKE);
+#endif
+        buf[strlen(buf) - 1] = ')';
+    } else {
+    	snprintf(buf, 1024, "fflags = %x", kev->fflags);
+    }
+
+    return (buf);
+}
+
+char *
+kevent_flags_dump(struct kevent *kev)
+{
+    char *buf;
+
+#define KEVFL_DUMP(attrib) \
+    if (kev->flags & attrib) \
+	strncat(buf, #attrib" ", 64);
+
+    if ((buf = calloc(1, 1024)) == NULL)
+	abort();
+
+    snprintf(buf, 1024, "flags = %d (", kev->flags);
+    KEVFL_DUMP(EV_ADD);
+    KEVFL_DUMP(EV_ENABLE);
+    KEVFL_DUMP(EV_DISABLE);
+    KEVFL_DUMP(EV_DELETE);
+    KEVFL_DUMP(EV_ONESHOT);
+    KEVFL_DUMP(EV_CLEAR);
+    KEVFL_DUMP(EV_EOF);
+    KEVFL_DUMP(EV_ERROR);
+#if HAVE_EV_DISPATCH
+    KEVFL_DUMP(EV_DISPATCH);
+#endif
+#if HAVE_EV_RECEIPT
+    KEVFL_DUMP(EV_RECEIPT);
+#endif
+    buf[strlen(buf) - 1] = ')';
+
+    return (buf);
+}
+
+/* Copied from ../kevent.c kevent_dump() and improved */
+const char *
+kevent_to_str(struct kevent *kev)
+{
+    char buf[512];
+
+    snprintf(&buf[0], sizeof(buf), 
+            "[ident=%d, filter=%d, %s, %s, data=%d, udata=%p]",
+            (u_int) kev->ident,
+            kev->filter,
+            kevent_flags_dump(kev),
+            kevent_fflags_dump(kev),
+            (int) kev->data,
+            kev->udata);
+
+    return (strdup(buf));
+}
+
+void
+kevent_add(int kqfd, struct kevent *kev, 
+        uintptr_t ident,
+        short     filter,
+        u_short   flags,
+        u_int     fflags,
+        intptr_t  data,
+        void      *udata)
+{
+    EV_SET(kev, ident, filter, flags, fflags, data, NULL);    
+    if (kevent(kqfd, kev, 1, NULL, 0, NULL) < 0) {
+        printf("Unable to add the following kevent:\n%s\n",
+                kevent_to_str(kev));
+        err(1, "kevent(): %s", strerror(errno));
+    }
+}
+
+void
+kevent_cmp(struct kevent *k1, struct kevent *k2)
+{
+/* XXX-
+   Workaround for inconsistent implementation of kevent(2) 
+ */
+#ifdef __FreeBSD__
+    if (k1->flags & EV_ADD)
+        k2->flags |= EV_ADD;
+#endif
+    if (memcmp(k1, k2, sizeof(*k1)) != 0) {
+        printf("kevent_cmp: mismatch:\n  %s !=\n  %s\n", 
+              kevent_to_str(k1), kevent_to_str(k2));
+        abort();
+    }
+}
+
+void
+test_begin(const char *func)
+{
+    if (cur_test_id)
+        free(cur_test_id);
+    cur_test_id = strdup(func);
+    if (!cur_test_id)
+        err(1, "strdup failed");
+
+    printf("\n\nTest %d: %s\n", testnum++, func);
+}
+
+void
+success(void)
+{
+    printf("%-70s %s\n", cur_test_id, "passed");
+    free(cur_test_id);
+    cur_test_id = NULL;
+}
+
+void
+test_kqueue(void)
+{
+    test_begin("kqueue()");
+    if ((kqfd = kqueue()) < 0)
+        err(1, "kqueue()");
+    test_no_kevents();
+    success();
+}
+
+void
+test_kqueue_close(void)
+{
+    test_begin("close(kq)");
+    if (close(kqfd) < 0)
+        err(1, "close()");
+    success();
+}
+
+int 
+main(int argc, char **argv)
+{
+    int test_proc = 1;
+    int test_socket = 1;
+    int test_signal = 1;
+    int test_vnode = 1;
+    int test_timer = 1;
+#ifdef __FreeBSD__
+    int test_user = 1;
+#else
+    /* XXX-FIXME temporary */
+    int test_user = 0;
+#endif
+
+    while (argc) {
+        if (strcmp(argv[0], "--no-proc") == 0)
+            test_proc = 0;
+        if (strcmp(argv[0], "--no-socket") == 0)
+            test_socket = 0;
+        if (strcmp(argv[0], "--no-timer") == 0)
+            test_timer = 0;
+        if (strcmp(argv[0], "--no-signal") == 0)
+            test_signal = 0;
+        if (strcmp(argv[0], "--no-vnode") == 0)
+            test_vnode = 0;
+        if (strcmp(argv[0], "--no-user") == 0)
+            test_user = 0;
+        argv++;
+        argc--;
+    }
+
+    /*
+     * Some tests fork.  If output is fully buffered,
+     * the children inherit some buffered data and flush
+     * it when they exit, causing some data to be printed twice.
+     * Use line buffering to avoid this problem.
+     */
+    setlinebuf(stdout);
+    setlinebuf(stderr);
+
+    test_kqueue();
+    test_kqueue_close();
+
+    if (test_socket) 
+        test_evfilt_read();
+    if (test_signal) 
+        test_evfilt_signal();
+    if (test_vnode) 
+        test_evfilt_vnode();
+#if HAVE_EVFILT_USER
+    if (test_user) 
+        test_evfilt_user();
+#endif
+    if (test_timer) 
+        test_evfilt_timer();
+    if (test_proc) 
+        test_evfilt_proc();
+
+    printf("\n---\n"
+            "+OK All %d tests completed.\n", testnum - 1);
+    return (0);
+}


Property changes on: trunk/tests/sys/kqueue/libkqueue/main.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/tests/sys/kqueue/libkqueue/proc.c
===================================================================
--- trunk/tests/sys/kqueue/libkqueue/proc.c	                        (rev 0)
+++ trunk/tests/sys/kqueue/libkqueue/proc.c	2018-07-28 20:42:58 UTC (rev 11972)
@@ -0,0 +1,424 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (c) 2009 Mark Heily <mark at heily.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $FreeBSD: stable/10/tests/sys/kqueue/libkqueue/proc.c 305467 2016-09-06 08:45:29Z ngie $
+ */
+
+#include <sys/stat.h>
+
+#include <err.h>
+
+#include "config.h"
+#include "common.h"
+
+static int sigusr1_caught = 0;
+
+int kqfd;
+
+static void
+sig_handler(int signum)
+{
+    sigusr1_caught = 1;
+}
+
+static void
+add_and_delete(void)
+{
+    struct kevent kev;
+    pid_t pid;
+
+    /* Create a child that waits to be killed and then exits */
+    pid = fork();
+    if (pid == 0) {
+        struct stat s;
+        if (fstat(kqfd, &s) != -1)
+            errx(1, "kqueue inherited across fork! (%s() at %s:%d)",
+	        __func__, __FILE__, __LINE__);
+
+        pause();
+        exit(2);
+    }
+    printf(" -- child created (pid %d)\n", (int) pid);
+
+    test_begin("kevent(EVFILT_PROC, EV_ADD)");
+
+    test_no_kevents();
+    kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_ADD, 0, 0, NULL);
+    test_no_kevents();
+
+    success();
+
+    test_begin("kevent(EVFILT_PROC, EV_DELETE)");
+
+    sleep(1);
+    test_no_kevents();
+    kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_DELETE, 0, 0, NULL);
+    if (kill(pid, SIGKILL) < 0)
+        err(1, "kill");
+    sleep(1);
+    test_no_kevents();
+
+    success();
+
+}
+
+static void
+proc_track(int sleep_time)
+{
+    char test_id[64];
+    struct kevent kev;
+    pid_t pid;
+    int pipe_fd[2];
+    ssize_t result;
+
+    snprintf(test_id, sizeof(test_id),
+             "kevent(EVFILT_PROC, NOTE_TRACK); sleep %d", sleep_time);
+    test_begin(test_id);
+    test_no_kevents();
+
+    if (pipe(pipe_fd)) {
+        err(1, "pipe (parent) failed! (%s() at %s:%d)",
+            __func__, __FILE__, __LINE__);
+    }
+
+    /* Create a child to track. */
+    pid = fork();
+    if (pid == 0) { /* Child */
+        pid_t grandchild = -1;
+
+        /*
+         * Give the parent a chance to start tracking us.
+         */
+        result = read(pipe_fd[1], test_id, 1);
+        if (result != 1) {
+            err(1, "read from pipe in child failed! (ret %zd) (%s() at %s:%d)",
+                result, __func__, __FILE__, __LINE__);
+        }
+
+        /*
+         * Spawn a grandchild that will immediately exit. If the kernel has bug
+         * 180385, the parent will see a kevent with both NOTE_CHILD and
+         * NOTE_EXIT. If that bug is fixed, it will see two separate kevents
+         * for those notes. Note that this triggers the conditions for
+         * detecting the bug quite reliably on a 1 CPU system (or if the test
+         * process is restricted to a single CPU), but may not trigger it on a
+         * multi-CPU system.
+         */
+        grandchild = fork();
+        if (grandchild == 0) { /* Grandchild */
+            if (sleep_time) sleep(sleep_time);
+            exit(1);
+        } else if (grandchild == -1) { /* Error */
+            err(1, "fork (grandchild) failed! (%s() at %s:%d)",
+                __func__, __FILE__, __LINE__);
+        } else { /* Child (Grandchild Parent) */
+            printf(" -- grandchild created (pid %d)\n", (int) grandchild);
+        }
+        if (sleep_time) sleep(sleep_time);
+        exit(0);
+    } else if (pid == -1) { /* Error */
+        err(1, "fork (child) failed! (%s() at %s:%d)",
+            __func__, __FILE__, __LINE__);
+    }
+    
+    printf(" -- child created (pid %d)\n", (int) pid);
+
+    kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_ADD | EV_ENABLE,
+               NOTE_TRACK | NOTE_EXEC | NOTE_EXIT | NOTE_FORK,
+               0, NULL);
+
+    printf(" -- tracking child (pid %d)\n", (int) pid);
+
+    /* Now that we're tracking the child, tell it to proceed. */
+    result = write(pipe_fd[0], test_id, 1);
+    if (result != 1) {
+        err(1, "write to pipe in parent failed! (ret %zd) (%s() at %s:%d)",
+            result, __func__, __FILE__, __LINE__);
+    }
+
+    /*
+     * Several events should be received:
+     *  - NOTE_FORK (from child)
+     *  - NOTE_CHILD (from grandchild)
+     *  - NOTE_EXIT (from grandchild)
+     *  - NOTE_EXIT (from child)
+     *
+     * The NOTE_FORK and NOTE_EXIT from the child could be combined into a
+     * single event, but the NOTE_CHILD and NOTE_EXIT from the grandchild must
+     * not be combined.
+     *
+     * The loop continues until no events are received within a 5 second
+     * period, at which point it is assumed that no more will be coming. The
+     * loop is deliberately designed to attempt to get events even after all
+     * the expected ones are received in case some spurious events are
+     * generated as well as the expected ones.
+     */
+    {
+        int child_exit = 0;
+        int child_fork = 0;
+        int gchild_exit = 0;
+        int gchild_note = 0;
+        pid_t gchild_pid = -1;
+        int done = 0;
+        
+        while (!done)
+        {
+            int handled = 0;
+            struct kevent *kevp;
+
+            kevp = kevent_get_timeout(kqfd, 5);
+            if (kevp == NULL) {
+                done = 1;
+            } else {
+                printf(" -- Received kevent: %s\n", kevent_to_str(kevp));
+            
+                if ((kevp->fflags & NOTE_CHILD) && (kevp->fflags & NOTE_EXIT)) {
+                    errx(1, "NOTE_CHILD and NOTE_EXIT in same kevent: %s", kevent_to_str(kevp));
+                }
+            
+                if (kevp->fflags & NOTE_CHILD) {
+                    if (kevp->data == pid) {
+                        if (!gchild_note) {
+                            ++gchild_note;
+                            gchild_pid = kevp->ident;
+                            ++handled;
+                        } else {
+                            errx(1, "Spurious NOTE_CHILD: %s", kevent_to_str(kevp));
+                        }
+                    }
+                }
+
+                if (kevp->fflags & NOTE_EXIT) {
+                    if ((kevp->ident == pid) && (!child_exit)) {
+                        ++child_exit;
+                        ++handled;
+                    } else if ((kevp->ident == gchild_pid) && (!gchild_exit)) {
+                        ++gchild_exit;
+                        ++handled;
+                    } else {
+                        errx(1, "Spurious NOTE_EXIT: %s", kevent_to_str(kevp));
+                    }
+                }
+
+                if (kevp->fflags & NOTE_FORK) {
+                    if ((kevp->ident == pid) && (!child_fork)) {
+                        ++child_fork;
+                        ++handled;
+                    } else {
+                        errx(1, "Spurious NOTE_FORK: %s", kevent_to_str(kevp));
+                    }
+                }
+
+                if (!handled) {
+                    errx(1, "Spurious kevent: %s", kevent_to_str(kevp));
+                }
+
+                free(kevp);
+            }
+        }
+        
+        /* Make sure all expected events were received. */
+        if (child_exit && child_fork && gchild_exit && gchild_note) {
+            printf(" -- Received all expected events.\n");
+        } else {
+            errx(1, "Did not receive all expected events.");
+        }
+    }
+
+    success();
+}
+
+#ifdef TODO
+static void
+event_trigger(void)
+{
+    struct kevent kev;
+    pid_t pid;
+
+    test_begin("kevent(EVFILT_PROC, wait)");
+
+    /* Create a child that waits to be killed and then exits */
+    pid = fork();
+    if (pid == 0) {
+        pause();
+        printf(" -- child caught signal, exiting\n");
+        exit(2);
+    }
+    printf(" -- child created (pid %d)\n", (int) pid);
+
+    test_no_kevents();
+    kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_ADD, 0, 0, NULL);
+
+    /* Cause the child to exit, then retrieve the event */
+    printf(" -- killing process %d\n", (int) pid);
+    if (kill(pid, SIGUSR1) < 0)
+        err(1, "kill");
+    kevent_cmp(&kev, kevent_get(kqfd));
+    test_no_kevents();
+
+    success();
+}
+
+void
+test_kevent_signal_disable(void)
+{
+    const char *test_id = "kevent(EVFILT_SIGNAL, EV_DISABLE)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DISABLE, 0, 0, NULL);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    /* Block SIGUSR1, then send it to ourselves */
+    sigset_t mask;
+    sigemptyset(&mask);
+    sigaddset(&mask, SIGUSR1);
+    if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
+        err(1, "sigprocmask");
+    if (kill(getpid(), SIGKILL) < 0)
+        err(1, "kill");
+
+    test_no_kevents();
+
+    success();
+}
+
+void
+test_kevent_signal_enable(void)
+{
+    const char *test_id = "kevent(EVFILT_SIGNAL, EV_ENABLE)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ENABLE, 0, 0, NULL);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    /* Block SIGUSR1, then send it to ourselves */
+    sigset_t mask;
+    sigemptyset(&mask);
+    sigaddset(&mask, SIGUSR1);
+    if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
+        err(1, "sigprocmask");
+    if (kill(getpid(), SIGUSR1) < 0)
+        err(1, "kill");
+
+    kev.flags = EV_ADD | EV_CLEAR;
+#if LIBKQUEUE
+    kev.data = 1; /* WORKAROUND */
+#else
+    kev.data = 2; // one extra time from test_kevent_signal_disable()
+#endif
+    kevent_cmp(&kev, kevent_get(kqfd));
+
+    /* Delete the watch */
+    kev.flags = EV_DELETE;
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    success();
+}
+
+void
+test_kevent_signal_del(void)
+{
+    const char *test_id = "kevent(EVFILT_SIGNAL, EV_DELETE)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    /* Delete the kevent */
+    EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DELETE, 0, 0, NULL);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    /* Block SIGUSR1, then send it to ourselves */
+    sigset_t mask;
+    sigemptyset(&mask);
+    sigaddset(&mask, SIGUSR1);
+    if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
+        err(1, "sigprocmask");
+    if (kill(getpid(), SIGUSR1) < 0)
+        err(1, "kill");
+
+    test_no_kevents();
+    success();
+}
+
+void
+test_kevent_signal_oneshot(void)
+{
+    const char *test_id = "kevent(EVFILT_SIGNAL, EV_ONESHOT)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_ONESHOT, 0, 0, NULL);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    /* Block SIGUSR1, then send it to ourselves */
+    sigset_t mask;
+    sigemptyset(&mask);
+    sigaddset(&mask, SIGUSR1);
+    if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
+        err(1, "sigprocmask");
+    if (kill(getpid(), SIGUSR1) < 0)
+        err(1, "kill");
+
+    kev.flags |= EV_CLEAR;
+    kev.data = 1;
+    kevent_cmp(&kev, kevent_get(kqfd));
+
+    /* Send another one and make sure we get no events */
+    if (kill(getpid(), SIGUSR1) < 0)
+        err(1, "kill");
+    test_no_kevents();
+
+    success();
+}
+#endif
+
+void
+test_evfilt_proc()
+{
+    kqfd = kqueue();
+
+    signal(SIGUSR1, sig_handler);
+
+    add_and_delete();
+    proc_track(0); /* Run without sleeping before children exit. */
+    proc_track(1); /* Sleep a bit in the children before exiting. */
+
+#if TODO
+    event_trigger();
+#endif
+
+    signal(SIGUSR1, SIG_DFL);
+
+#if TODO
+    test_kevent_signal_add();
+    test_kevent_signal_del();
+    test_kevent_signal_get();
+    test_kevent_signal_disable();
+    test_kevent_signal_enable();
+    test_kevent_signal_oneshot();
+#endif
+    close(kqfd);
+}


Property changes on: trunk/tests/sys/kqueue/libkqueue/proc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/tests/sys/kqueue/libkqueue/read.c
===================================================================
--- trunk/tests/sys/kqueue/libkqueue/read.c	                        (rev 0)
+++ trunk/tests/sys/kqueue/libkqueue/read.c	2018-07-28 20:42:58 UTC (rev 11972)
@@ -0,0 +1,327 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (c) 2009 Mark Heily <mark at heily.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $FreeBSD: stable/10/tests/sys/kqueue/libkqueue/read.c 305467 2016-09-06 08:45:29Z ngie $
+ */
+
+#include "common.h"
+
+int kqfd;
+int sockfd[2];
+
+static void
+kevent_socket_drain(void)
+{
+    char buf[1];
+
+    /* Drain the read buffer, then make sure there are no more events. */
+    puts("draining the read buffer");
+    if (read(sockfd[0], &buf[0], 1) < 1)
+        err(1, "read(2)");
+}
+
+static void
+kevent_socket_fill(void)
+{
+  puts("filling the read buffer");
+    if (write(sockfd[1], ".", 1) < 1)
+        err(1, "write(2)");
+}
+
+
+void
+test_kevent_socket_add(void)
+{
+    const char *test_id = "kevent(EVFILT_READ, EV_ADD)";
+    struct kevent kev;
+
+    test_begin(test_id);
+    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    success();
+}
+
+void
+test_kevent_socket_get(void)
+{
+    const char *test_id = "kevent(EVFILT_READ) wait";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    kevent_socket_fill();
+
+    kev.data = 1;
+    kevent_cmp(&kev, kevent_get(kqfd));
+
+    kevent_socket_drain();
+    test_no_kevents();
+
+    kev.flags = EV_DELETE;
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    success();
+}
+
+void
+test_kevent_socket_clear(void)
+{
+    const char *test_id = "kevent(EVFILT_READ, EV_CLEAR)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    test_no_kevents();
+
+    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &sockfd[0]);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    kevent_socket_fill();
+    kevent_socket_fill();
+
+    kev.data = 2;
+    kevent_cmp(&kev, kevent_get(kqfd)); 
+
+    /* We filled twice, but drain once. Edge-triggered would not generate
+       additional events.
+     */
+    kevent_socket_drain();
+    test_no_kevents();
+
+    kevent_socket_drain();
+    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    success();
+}
+
+void
+test_kevent_socket_disable_and_enable(void)
+{
+    const char *test_id = "kevent(EVFILT_READ, EV_DISABLE)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    /*
+     * Write to the socket before adding the event. This way we can verify that
+     * enabling a triggered kevent causes the event to be returned immediately.
+     */
+    kevent_socket_fill();
+
+    /* Add a disabled event. */
+    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_DISABLE, 0, 0, &sockfd[0]);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    test_no_kevents();
+
+    /* Re-enable the knote, then see if an event is generated */
+    kev.flags = EV_ENABLE;
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+    kev.flags = EV_ADD;
+    kev.data = 1;
+    kevent_cmp(&kev, kevent_get(kqfd));
+
+    kevent_socket_drain();
+
+    kev.flags = EV_DELETE;
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    success();
+}
+
+void
+test_kevent_socket_del(void)
+{
+    const char *test_id = "kevent(EVFILT_READ, EV_DELETE)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    kevent_socket_fill();
+    test_no_kevents();
+    kevent_socket_drain();
+
+    success();
+}
+
+void
+test_kevent_socket_oneshot(void)
+{
+    const char *test_id = "kevent(EVFILT_READ, EV_ONESHOT)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    /* Re-add the watch and make sure no events are pending */
+    puts("-- re-adding knote");
+    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &sockfd[0]);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+    test_no_kevents();
+
+    puts("-- getting one event");
+    kevent_socket_fill();
+    kev.data = 1;
+    kevent_cmp(&kev, kevent_get(kqfd));
+
+    puts("-- checking knote disabled");
+    test_no_kevents();
+
+    /* Try to delete the knote, it should already be deleted */
+    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) == 0)
+        err(1, "%s", test_id);
+
+    kevent_socket_drain();
+
+    success();
+}
+
+
+#if HAVE_EV_DISPATCH
+void
+test_kevent_socket_dispatch(void)
+{
+    const char *test_id = "kevent(EVFILT_READ, EV_DISPATCH)";
+
+    test_begin(test_id);
+
+    struct kevent kev;
+
+    /* Re-add the watch and make sure no events are pending */
+    puts("-- re-adding knote");
+    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_DISPATCH, 0, 0, &sockfd[0]);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+    test_no_kevents();
+
+    /* The event will occur only once, even though EV_CLEAR is not
+       specified. */
+    kevent_socket_fill();
+    kev.data = 1;
+    kevent_cmp(&kev, kevent_get(kqfd));
+    test_no_kevents();
+
+    /* Since the knote is disabled, the EV_DELETE operation succeeds. */
+    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    kevent_socket_drain();
+
+    success();
+}
+#endif  /* HAVE_EV_DISPATCH */
+
+#if BROKEN
+void
+test_kevent_socket_lowat(void)
+{
+    const char *test_id = "kevent(EVFILT_READ, NOTE_LOWAT)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    /* Re-add the watch and make sure no events are pending */
+    puts("-- re-adding knote, setting low watermark to 2 bytes");
+    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, NOTE_LOWAT, 2, &sockfd[0]);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+    test_no_kevents();
+
+    puts("-- checking that one byte does not trigger an event..");
+    kevent_socket_fill();
+    test_no_kevents();
+
+    puts("-- checking that two bytes triggers an event..");
+    kevent_socket_fill();
+    if (kevent(kqfd, NULL, 0, &kev, 1, NULL) != 1)
+        err(1, "%s", test_id);
+    KEV_CMP(kev, sockfd[0], EVFILT_READ, 0);
+    test_no_kevents();
+
+    kevent_socket_drain();
+    kevent_socket_drain();
+
+    success();
+}
+#endif
+
+void
+test_kevent_socket_eof(void)
+{
+    const char *test_id = "kevent(EVFILT_READ, EV_EOF)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    /* Re-add the watch and make sure no events are pending */
+    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+    test_no_kevents();
+
+    if (close(sockfd[1]) < 0)
+        err(1, "close(2)");
+
+    kev.flags |= EV_EOF;
+    kevent_cmp(&kev, kevent_get(kqfd));
+
+    /* Delete the watch */
+    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    success();
+}
+
+void
+test_evfilt_read()
+{
+    /* Create a connected pair of full-duplex sockets for testing socket events */
+    if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) < 0) 
+        abort();
+
+    kqfd = kqueue();
+    test_kevent_socket_add();
+    test_kevent_socket_del();
+    test_kevent_socket_get();
+    test_kevent_socket_disable_and_enable();
+    test_kevent_socket_oneshot();
+    test_kevent_socket_clear();
+#if HAVE_EV_DISPATCH
+    test_kevent_socket_dispatch();
+#endif
+    test_kevent_socket_eof();
+    close(kqfd);
+}


Property changes on: trunk/tests/sys/kqueue/libkqueue/read.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/tests/sys/kqueue/libkqueue/signal.c
===================================================================
--- trunk/tests/sys/kqueue/libkqueue/signal.c	                        (rev 0)
+++ trunk/tests/sys/kqueue/libkqueue/signal.c	2018-07-28 20:42:58 UTC (rev 11972)
@@ -0,0 +1,200 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (c) 2009 Mark Heily <mark at heily.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $FreeBSD: stable/10/tests/sys/kqueue/libkqueue/signal.c 305467 2016-09-06 08:45:29Z ngie $
+ */
+
+#include "common.h"
+
+int kqfd;
+
+void
+test_kevent_signal_add(void)
+{
+    const char *test_id = "kevent(EVFILT_SIGNAL, EV_ADD)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    success();
+}
+
+void
+test_kevent_signal_get(void)
+{
+    const char *test_id = "kevent(EVFILT_SIGNAL, wait)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);    
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    /* Block SIGUSR1, then send it to ourselves */
+    sigset_t mask;
+    sigemptyset(&mask);
+    sigaddset(&mask, SIGUSR1);
+    if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
+        err(1, "sigprocmask");
+    if (kill(getpid(), SIGUSR1) < 0)
+        err(1, "kill");
+
+    kev.flags |= EV_CLEAR;
+    kev.data = 1;
+    kevent_cmp(&kev, kevent_get(kqfd));
+
+    success();
+}
+
+void
+test_kevent_signal_disable(void)
+{
+    const char *test_id = "kevent(EVFILT_SIGNAL, EV_DISABLE)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DISABLE, 0, 0, NULL);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    /* Block SIGUSR1, then send it to ourselves */
+    sigset_t mask;
+    sigemptyset(&mask);
+    sigaddset(&mask, SIGUSR1);
+    if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
+        err(1, "sigprocmask");
+    if (kill(getpid(), SIGUSR1) < 0)
+        err(1, "kill");
+
+    test_no_kevents();
+
+    success();
+}
+
+void
+test_kevent_signal_enable(void)
+{
+    const char *test_id = "kevent(EVFILT_SIGNAL, EV_ENABLE)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ENABLE, 0, 0, NULL);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    /* Block SIGUSR1, then send it to ourselves */
+    sigset_t mask;
+    sigemptyset(&mask);
+    sigaddset(&mask, SIGUSR1);
+    if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
+        err(1, "sigprocmask");
+    if (kill(getpid(), SIGUSR1) < 0)
+        err(1, "kill");
+
+    kev.flags = EV_ADD | EV_CLEAR;
+#if LIBKQUEUE
+    kev.data = 1; /* WORKAROUND */
+#else
+    kev.data = 2; // one extra time from test_kevent_signal_disable()
+#endif
+    kevent_cmp(&kev, kevent_get(kqfd));
+
+    /* Delete the watch */
+    kev.flags = EV_DELETE;
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    success();
+}
+
+void
+test_kevent_signal_del(void)
+{
+    const char *test_id = "kevent(EVFILT_SIGNAL, EV_DELETE)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    /* Delete the kevent */
+    EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DELETE, 0, 0, NULL);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    /* Block SIGUSR1, then send it to ourselves */
+    sigset_t mask;
+    sigemptyset(&mask);
+    sigaddset(&mask, SIGUSR1);
+    if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
+        err(1, "sigprocmask");
+    if (kill(getpid(), SIGUSR1) < 0)
+        err(1, "kill");
+
+    test_no_kevents();
+    success();
+}
+
+void
+test_kevent_signal_oneshot(void)
+{
+    const char *test_id = "kevent(EVFILT_SIGNAL, EV_ONESHOT)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_ONESHOT, 0, 0, NULL);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    /* Block SIGUSR1, then send it to ourselves */
+    sigset_t mask;
+    sigemptyset(&mask);
+    sigaddset(&mask, SIGUSR1);
+    if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
+        err(1, "sigprocmask");
+    if (kill(getpid(), SIGUSR1) < 0)
+        err(1, "kill");
+
+    kev.flags |= EV_CLEAR;
+    kev.data = 1;
+    kevent_cmp(&kev, kevent_get(kqfd));
+
+    /* Send another one and make sure we get no events */
+    if (kill(getpid(), SIGUSR1) < 0)
+        err(1, "kill");
+    test_no_kevents();
+
+    success();
+}
+
+void
+test_evfilt_signal()
+{
+	kqfd = kqueue();
+        test_kevent_signal_add();
+        test_kevent_signal_del();
+        test_kevent_signal_get();
+        test_kevent_signal_disable();
+        test_kevent_signal_enable();
+        test_kevent_signal_oneshot();
+	close(kqfd);
+}


Property changes on: trunk/tests/sys/kqueue/libkqueue/signal.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/tests/sys/kqueue/libkqueue/timer.c
===================================================================
--- trunk/tests/sys/kqueue/libkqueue/timer.c	                        (rev 0)
+++ trunk/tests/sys/kqueue/libkqueue/timer.c	2018-07-28 20:42:58 UTC (rev 11972)
@@ -0,0 +1,179 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (c) 2009 Mark Heily <mark at heily.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $FreeBSD: stable/10/tests/sys/kqueue/libkqueue/timer.c 305467 2016-09-06 08:45:29Z ngie $
+ */
+
+#include "common.h"
+
+int kqfd;
+
+void
+test_kevent_timer_add(void)
+{
+    const char *test_id = "kevent(EVFILT_TIMER, EV_ADD)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    EV_SET(&kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000, NULL);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    success();
+}
+
+void
+test_kevent_timer_del(void)
+{
+    const char *test_id = "kevent(EVFILT_TIMER, EV_DELETE)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    EV_SET(&kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, NULL);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    test_no_kevents();
+
+    success();
+}
+
+void
+test_kevent_timer_get(void)
+{
+    const char *test_id = "kevent(EVFILT_TIMER, wait)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    EV_SET(&kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000, NULL);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    kev.flags |= EV_CLEAR;
+    kev.data = 1; 
+    kevent_cmp(&kev, kevent_get(kqfd));
+
+    EV_SET(&kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, NULL);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    success();
+}
+
+static void
+test_oneshot(void)
+{
+    const char *test_id = "kevent(EVFILT_TIMER, EV_ONESHOT)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    test_no_kevents();
+
+    EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 500,NULL);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    /* Retrieve the event */
+    kev.flags = EV_ADD | EV_CLEAR | EV_ONESHOT;
+    kev.data = 1; 
+    kevent_cmp(&kev, kevent_get(kqfd));
+
+    /* Check if the event occurs again */
+    sleep(3);
+    test_no_kevents();
+
+
+    success();
+}
+
+static void
+test_periodic(void)
+{
+    const char *test_id = "kevent(EVFILT_TIMER, periodic)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    test_no_kevents();
+
+    EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD, 0, 1000,NULL);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    /* Retrieve the event */
+    kev.flags = EV_ADD | EV_CLEAR;
+    kev.data = 1; 
+    kevent_cmp(&kev, kevent_get(kqfd));
+
+    /* Check if the event occurs again */
+    sleep(1);
+    kevent_cmp(&kev, kevent_get(kqfd));
+
+    /* Delete the event */
+    kev.flags = EV_DELETE;
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    success();
+}
+
+static void
+disable_and_enable(void)
+{
+    const char *test_id = "kevent(EVFILT_TIMER, EV_DISABLE and EV_ENABLE)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    test_no_kevents();
+
+    /* Add the watch and immediately disable it */
+    EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 2000,NULL);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+    kev.flags = EV_DISABLE;
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+    test_no_kevents();
+
+    /* Re-enable and check again */
+    kev.flags = EV_ENABLE;
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    kev.flags = EV_ADD | EV_CLEAR | EV_ONESHOT;
+    kev.data = 1; 
+    kevent_cmp(&kev, kevent_get(kqfd));
+
+    success();
+}
+
+void
+test_evfilt_timer()
+{
+	kqfd = kqueue();
+    test_kevent_timer_add();
+    test_kevent_timer_del();
+    test_kevent_timer_get();
+    test_oneshot();
+    test_periodic();
+    disable_and_enable();
+	close(kqfd);
+}


Property changes on: trunk/tests/sys/kqueue/libkqueue/timer.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/tests/sys/kqueue/libkqueue/user.c
===================================================================
--- trunk/tests/sys/kqueue/libkqueue/user.c	                        (rev 0)
+++ trunk/tests/sys/kqueue/libkqueue/user.c	2018-07-28 20:42:58 UTC (rev 11972)
@@ -0,0 +1,130 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (c) 2009 Mark Heily <mark at heily.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $FreeBSD: stable/10/tests/sys/kqueue/libkqueue/user.c 305467 2016-09-06 08:45:29Z ngie $
+ */
+
+#include "common.h"
+
+int kqfd;
+
+static void
+add_and_delete(void)
+{
+    const char *test_id = "kevent(EVFILT_USER, EV_ADD and EV_DELETE)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_ADD, 0, 0, NULL);
+    test_no_kevents();
+
+    kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_DELETE, 0, 0, NULL);
+    test_no_kevents();
+
+    success();
+}
+
+static void
+event_wait(void)
+{
+    const char *test_id = "kevent(EVFILT_USER, wait)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    test_no_kevents();
+
+    /* Add the event, and then trigger it */
+    kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_ADD | EV_CLEAR, 0, 0, NULL);    
+    kevent_add(kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL);    
+
+    kev.fflags &= ~NOTE_FFCTRLMASK;
+    kev.fflags &= ~NOTE_TRIGGER;
+    kev.flags = EV_CLEAR;
+    kevent_cmp(&kev, kevent_get(kqfd));
+
+    test_no_kevents();
+
+    success();
+}
+
+static void
+disable_and_enable(void)
+{
+    const char *test_id = "kevent(EVFILT_USER, EV_DISABLE and EV_ENABLE)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    test_no_kevents();
+
+    kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_ADD, 0, 0, NULL); 
+    kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_DISABLE, 0, 0, NULL); 
+
+    /* Trigger the event, but since it is disabled, nothing will happen. */
+    kevent_add(kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); 
+    test_no_kevents();
+
+    kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_ENABLE, 0, 0, NULL); 
+    kevent_add(kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); 
+
+    kev.flags = EV_CLEAR;
+    kev.fflags &= ~NOTE_FFCTRLMASK;
+    kev.fflags &= ~NOTE_TRIGGER;
+    kevent_cmp(&kev, kevent_get(kqfd));
+
+    success();
+}
+
+static void
+oneshot(void)
+{
+    const char *test_id = "kevent(EVFILT_USER, EV_ONESHOT)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    test_no_kevents();
+
+    kevent_add(kqfd, &kev, 2, EVFILT_USER, EV_ADD | EV_ONESHOT, 0, 0, NULL);
+
+    puts("  -- event 1");
+    kevent_add(kqfd, &kev, 2, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL);    
+
+    kev.flags = EV_ONESHOT;
+    kev.fflags &= ~NOTE_FFCTRLMASK;
+    kev.fflags &= ~NOTE_TRIGGER;
+    kevent_cmp(&kev, kevent_get(kqfd));
+
+    test_no_kevents();
+
+    success();
+}
+
+void
+test_evfilt_user()
+{
+	kqfd = kqueue();
+
+    add_and_delete();
+    event_wait();
+    disable_and_enable();
+    oneshot();
+    /* TODO: try different fflags operations */
+
+	close(kqfd);
+}


Property changes on: trunk/tests/sys/kqueue/libkqueue/user.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/tests/sys/kqueue/libkqueue/vnode.c
===================================================================
--- trunk/tests/sys/kqueue/libkqueue/vnode.c	                        (rev 0)
+++ trunk/tests/sys/kqueue/libkqueue/vnode.c	2018-07-28 20:42:58 UTC (rev 11972)
@@ -0,0 +1,267 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (c) 2009 Mark Heily <mark at heily.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $FreeBSD: stable/10/tests/sys/kqueue/libkqueue/vnode.c 305467 2016-09-06 08:45:29Z ngie $
+ */
+
+#include "common.h"
+
+int kqfd;
+int vnode_fd;
+
+void
+test_kevent_vnode_add(void)
+{
+    const char *test_id = "kevent(EVFILT_VNODE, EV_ADD)";
+    const char *testfile = "./kqueue-test.tmp";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    system("touch ./kqueue-test.tmp");
+    vnode_fd = open(testfile, O_RDONLY);
+    if (vnode_fd < 0)
+        err(1, "open of %s", testfile);
+    else
+        printf("vnode_fd = %d\n", vnode_fd);
+
+    EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD, 
+            NOTE_WRITE | NOTE_ATTRIB | NOTE_RENAME | NOTE_DELETE, 0, NULL);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    success();
+}
+
+void
+test_kevent_vnode_note_delete(void)
+{
+    const char *test_id = "kevent(EVFILT_VNODE, NOTE_DELETE)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_DELETE, 0, NULL);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    if (unlink("./kqueue-test.tmp") < 0)
+        err(1, "unlink");
+
+    kevent_cmp(&kev, kevent_get(kqfd));
+
+    success();
+}
+
+void
+test_kevent_vnode_note_write(void)
+{
+    const char *test_id = "kevent(EVFILT_VNODE, NOTE_WRITE)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_WRITE, 0, NULL);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    if (system("echo hello >> ./kqueue-test.tmp") < 0)
+        err(1, "system");
+
+    /* BSD kqueue adds NOTE_EXTEND even though it was not requested */
+    /* BSD kqueue removes EV_ENABLE */
+    kev.flags &= ~EV_ENABLE; // XXX-FIXME compatibility issue
+    kev.fflags |= NOTE_EXTEND; // XXX-FIXME compatibility issue
+    kevent_cmp(&kev, kevent_get(kqfd));
+
+    success();
+}
+
+void
+test_kevent_vnode_note_attrib(void)
+{
+    const char *test_id = "kevent(EVFILT_VNODE, NOTE_ATTRIB)";
+    struct kevent kev;
+    int nfds;
+
+    test_begin(test_id);
+
+    EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, NULL);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    if (system("touch ./kqueue-test.tmp") < 0)
+        err(1, "system");
+
+    nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL);
+    if (nfds < 1)
+        err(1, "%s", test_id);
+    if (kev.ident != vnode_fd ||
+            kev.filter != EVFILT_VNODE || 
+            kev.fflags != NOTE_ATTRIB)
+        err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", 
+                test_id, (unsigned int)kev.ident, kev.filter, kev.flags);
+
+    success();
+}
+
+void
+test_kevent_vnode_note_rename(void)
+{
+    const char *test_id = "kevent(EVFILT_VNODE, NOTE_RENAME)";
+    struct kevent kev;
+    int nfds;
+
+    test_begin(test_id);
+
+    EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_RENAME, 0, NULL);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    if (system("mv ./kqueue-test.tmp ./kqueue-test2.tmp") < 0)
+        err(1, "system");
+
+    nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL);
+    if (nfds < 1)
+        err(1, "%s", test_id);
+    if (kev.ident != vnode_fd ||
+            kev.filter != EVFILT_VNODE || 
+            kev.fflags != NOTE_RENAME)
+        err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", 
+                test_id, (unsigned int)kev.ident, kev.filter, kev.flags);
+
+    if (system("mv ./kqueue-test2.tmp ./kqueue-test.tmp") < 0)
+        err(1, "system");
+
+    success();
+}
+
+void
+test_kevent_vnode_del(void)
+{
+    const char *test_id = "kevent(EVFILT_VNODE, EV_DELETE)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_DELETE, 0, 0, NULL);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    success();
+}
+
+void
+test_kevent_vnode_disable_and_enable(void)
+{
+    const char *test_id = "kevent(EVFILT_VNODE, EV_DISABLE and EV_ENABLE)";
+    struct kevent kev;
+    int nfds;
+
+    test_begin(test_id);
+
+    test_no_kevents();
+
+    /* Add the watch and immediately disable it */
+    EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, NULL);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+    kev.flags = EV_DISABLE;
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    /* Confirm that the watch is disabled */
+    if (system("touch ./kqueue-test.tmp") < 0)
+        err(1, "system");
+    test_no_kevents();
+
+    /* Re-enable and check again */
+    kev.flags = EV_ENABLE;
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+    if (system("touch ./kqueue-test.tmp") < 0)
+        err(1, "system");
+    nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL);
+    if (nfds < 1)
+        err(1, "%s", test_id);
+    if (kev.ident != vnode_fd ||
+            kev.filter != EVFILT_VNODE || 
+            kev.fflags != NOTE_ATTRIB)
+        err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", 
+                test_id, (unsigned int)kev.ident, kev.filter, kev.flags);
+
+    success();
+}
+
+#if HAVE_EV_DISPATCH
+void
+test_kevent_vnode_dispatch(void)
+{
+    const char *test_id = "kevent(EVFILT_VNODE, EV_DISPATCH)";
+    struct kevent kev;
+    int nfds;
+
+    test_begin(test_id);
+
+    test_no_kevents();
+
+    EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_DISPATCH, NOTE_ATTRIB, 0, NULL);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    if (system("touch ./kqueue-test.tmp") < 0)
+        err(1, "system");
+
+    nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL);
+    if (nfds < 1)
+        err(1, "%s", test_id);
+    if (kev.ident != vnode_fd ||
+            kev.filter != EVFILT_VNODE || 
+            kev.fflags != NOTE_ATTRIB)
+        err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", 
+                test_id, (unsigned int)kev.ident, kev.filter, kev.flags);
+
+    /* Confirm that the watch is disabled automatically */
+    puts("-- checking that watch is disabled");
+    if (system("touch ./kqueue-test.tmp") < 0)
+        err(1, "system");
+    test_no_kevents();
+
+    /* Delete the watch */
+    EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_DELETE, NOTE_ATTRIB, 0, NULL);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "remove watch failed: %s", test_id);
+
+    success();
+}
+#endif 	/* HAVE_EV_DISPATCH */
+
+void
+test_evfilt_vnode()
+{
+	kqfd = kqueue();
+        test_kevent_vnode_add();
+        test_kevent_vnode_del();
+        test_kevent_vnode_disable_and_enable();
+#if HAVE_EV_DISPATCH
+        test_kevent_vnode_dispatch();
+#endif
+        test_kevent_vnode_note_write();
+        test_kevent_vnode_note_attrib();
+        test_kevent_vnode_note_rename();
+        test_kevent_vnode_note_delete();
+	close(kqfd);
+}


Property changes on: trunk/tests/sys/kqueue/libkqueue/vnode.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/tests/sys/kqueue/main.c
===================================================================
--- trunk/tests/sys/kqueue/main.c	                        (rev 0)
+++ trunk/tests/sys/kqueue/main.c	2018-07-28 20:42:58 UTC (rev 11972)
@@ -0,0 +1,324 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (c) 2009 Mark Heily <mark at heily.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $FreeBSD: stable/10/tests/sys/kqueue/main.c 297977 2016-04-14 17:14:11Z vangyzen $
+ */
+
+#include <sys/types.h>
+
+#include "config.h"
+#include "common.h"
+
+int testnum = 1;
+char *cur_test_id = NULL;
+int kqfd;
+
+extern void test_evfilt_read();
+extern void test_evfilt_signal();
+extern void test_evfilt_vnode();
+extern void test_evfilt_timer();
+extern void test_evfilt_proc();
+#if HAVE_EVFILT_USER
+extern void test_evfilt_user();
+#endif
+
+/* Checks if any events are pending, which is an error. */
+void 
+test_no_kevents(void)
+{
+    int nfds;
+    struct timespec timeo;
+    struct kevent kev;
+
+    puts("confirming that there are no events pending");
+    memset(&timeo, 0, sizeof(timeo));
+    nfds = kevent(kqfd, NULL, 0, &kev, 1, &timeo);
+    if (nfds != 0) {
+        puts("\nUnexpected event:");
+        puts(kevent_to_str(&kev));
+        errx(1, "%d event(s) pending, but none expected:", nfds);
+    }
+}
+
+/* Retrieve a single kevent */
+struct kevent *
+kevent_get(int kqfd)
+{
+    int nfds;
+    struct kevent *kev;
+
+    if ((kev = calloc(1, sizeof(*kev))) == NULL)
+	err(1, "out of memory");
+    
+    nfds = kevent(kqfd, NULL, 0, kev, 1, NULL);
+    if (nfds < 1)
+        err(1, "kevent(2)");
+
+    return (kev);
+}
+
+/* Retrieve a single kevent, specifying a maximum time to wait for it. */
+struct kevent *
+kevent_get_timeout(int kqfd, int seconds)
+{
+    int nfds;
+    struct kevent *kev;
+    struct timespec timeout = {seconds, 0};
+
+    if ((kev = calloc(1, sizeof(*kev))) == NULL)
+	err(1, "out of memory");
+    
+    nfds = kevent(kqfd, NULL, 0, kev, 1, &timeout);
+    if (nfds < 0) {
+        err(1, "kevent(2)");
+    } else if (nfds == 0) {
+        free(kev);
+        kev = NULL;
+    }
+
+    return (kev);
+}
+
+char *
+kevent_fflags_dump(struct kevent *kev)
+{
+    char *buf;
+
+#define KEVFFL_DUMP(attrib) \
+    if (kev->fflags & attrib) \
+	strncat(buf, #attrib" ", 64);
+
+    if ((buf = calloc(1, 1024)) == NULL)
+	abort();
+
+    /* Not every filter has meaningful fflags */
+    if (kev->filter == EVFILT_PROC) {
+        snprintf(buf, 1024, "fflags = %x (", kev->fflags);
+        KEVFFL_DUMP(NOTE_EXIT);
+        KEVFFL_DUMP(NOTE_FORK);
+        KEVFFL_DUMP(NOTE_EXEC);
+        KEVFFL_DUMP(NOTE_CHILD);
+        KEVFFL_DUMP(NOTE_TRACKERR);
+        KEVFFL_DUMP(NOTE_TRACK);
+        buf[strlen(buf) - 1] = ')';
+    } else if (kev->filter == EVFILT_VNODE) {
+        snprintf(buf, 1024, "fflags = %x (", kev->fflags);
+        KEVFFL_DUMP(NOTE_DELETE);
+        KEVFFL_DUMP(NOTE_WRITE);
+        KEVFFL_DUMP(NOTE_EXTEND);
+#if HAVE_NOTE_TRUNCATE
+        KEVFFL_DUMP(NOTE_TRUNCATE);
+#endif
+        KEVFFL_DUMP(NOTE_ATTRIB);
+        KEVFFL_DUMP(NOTE_LINK);
+        KEVFFL_DUMP(NOTE_RENAME);
+#if HAVE_NOTE_REVOKE
+        KEVFFL_DUMP(NOTE_REVOKE);
+#endif
+        buf[strlen(buf) - 1] = ')';
+    } else {
+    	snprintf(buf, 1024, "fflags = %x", kev->fflags);
+    }
+
+    return (buf);
+}
+
+char *
+kevent_flags_dump(struct kevent *kev)
+{
+    char *buf;
+
+#define KEVFL_DUMP(attrib) \
+    if (kev->flags & attrib) \
+	strncat(buf, #attrib" ", 64);
+
+    if ((buf = calloc(1, 1024)) == NULL)
+	abort();
+
+    snprintf(buf, 1024, "flags = %d (", kev->flags);
+    KEVFL_DUMP(EV_ADD);
+    KEVFL_DUMP(EV_ENABLE);
+    KEVFL_DUMP(EV_DISABLE);
+    KEVFL_DUMP(EV_DELETE);
+    KEVFL_DUMP(EV_ONESHOT);
+    KEVFL_DUMP(EV_CLEAR);
+    KEVFL_DUMP(EV_EOF);
+    KEVFL_DUMP(EV_ERROR);
+#if HAVE_EV_DISPATCH
+    KEVFL_DUMP(EV_DISPATCH);
+#endif
+#if HAVE_EV_RECEIPT
+    KEVFL_DUMP(EV_RECEIPT);
+#endif
+    buf[strlen(buf) - 1] = ')';
+
+    return (buf);
+}
+
+/* Copied from ../kevent.c kevent_dump() and improved */
+const char *
+kevent_to_str(struct kevent *kev)
+{
+    char buf[512];
+
+    snprintf(&buf[0], sizeof(buf), 
+            "[ident=%d, filter=%d, %s, %s, data=%d, udata=%p]",
+            (u_int) kev->ident,
+            kev->filter,
+            kevent_flags_dump(kev),
+            kevent_fflags_dump(kev),
+            (int) kev->data,
+            kev->udata);
+
+    return (strdup(buf));
+}
+
+void
+kevent_add(int kqfd, struct kevent *kev, 
+        uintptr_t ident,
+        short     filter,
+        u_short   flags,
+        u_int     fflags,
+        intptr_t  data,
+        void      *udata)
+{
+    EV_SET(kev, ident, filter, flags, fflags, data, NULL);    
+    if (kevent(kqfd, kev, 1, NULL, 0, NULL) < 0) {
+        printf("Unable to add the following kevent:\n%s\n",
+                kevent_to_str(kev));
+        err(1, "kevent(): %s", strerror(errno));
+    }
+}
+
+void
+kevent_cmp(struct kevent *k1, struct kevent *k2)
+{
+/* XXX-
+   Workaround for inconsistent implementation of kevent(2) 
+ */
+#ifdef __FreeBSD__
+    if (k1->flags & EV_ADD)
+        k2->flags |= EV_ADD;
+#endif
+    if (memcmp(k1, k2, sizeof(*k1)) != 0) {
+        printf("kevent_cmp: mismatch:\n  %s !=\n  %s\n", 
+              kevent_to_str(k1), kevent_to_str(k2));
+        abort();
+    }
+}
+
+void
+test_begin(const char *func)
+{
+    if (cur_test_id)
+        free(cur_test_id);
+    cur_test_id = strdup(func);
+    if (!cur_test_id)
+        err(1, "strdup failed");
+
+    printf("\n\nTest %d: %s\n", testnum++, func);
+}
+
+void
+success(void)
+{
+    printf("%-70s %s\n", cur_test_id, "passed");
+    free(cur_test_id);
+    cur_test_id = NULL;
+}
+
+void
+test_kqueue(void)
+{
+    test_begin("kqueue()");
+    if ((kqfd = kqueue()) < 0)
+        err(1, "kqueue()");
+    test_no_kevents();
+    success();
+}
+
+void
+test_kqueue_close(void)
+{
+    test_begin("close(kq)");
+    if (close(kqfd) < 0)
+        err(1, "close()");
+    success();
+}
+
+int 
+main(int argc, char **argv)
+{
+    int test_proc = 1;
+    int test_socket = 1;
+    int test_signal = 1;
+    int test_vnode = 1;
+    int test_timer = 1;
+#ifdef __FreeBSD__
+    int test_user = 1;
+#else
+    /* XXX-FIXME temporary */
+    int test_user = 0;
+#endif
+
+    while (argc) {
+        if (strcmp(argv[0], "--no-proc") == 0)
+            test_proc = 0;
+        if (strcmp(argv[0], "--no-socket") == 0)
+            test_socket = 0;
+        if (strcmp(argv[0], "--no-timer") == 0)
+            test_timer = 0;
+        if (strcmp(argv[0], "--no-signal") == 0)
+            test_signal = 0;
+        if (strcmp(argv[0], "--no-vnode") == 0)
+            test_vnode = 0;
+        if (strcmp(argv[0], "--no-user") == 0)
+            test_user = 0;
+        argv++;
+        argc--;
+    }
+
+    /*
+     * Some tests fork.  If output is fully buffered,
+     * the children inherit some buffered data and flush
+     * it when they exit, causing some data to be printed twice.
+     * Use line buffering to avoid this problem.
+     */
+    setlinebuf(stdout);
+    setlinebuf(stderr);
+
+    test_kqueue();
+    test_kqueue_close();
+
+    if (test_socket) 
+        test_evfilt_read();
+    if (test_signal) 
+        test_evfilt_signal();
+    if (test_vnode) 
+        test_evfilt_vnode();
+#if HAVE_EVFILT_USER
+    if (test_user) 
+        test_evfilt_user();
+#endif
+    if (test_timer) 
+        test_evfilt_timer();
+    if (test_proc) 
+        test_evfilt_proc();
+
+    printf("\n---\n"
+            "+OK All %d tests completed.\n", testnum - 1);
+    return (0);
+}


Property changes on: trunk/tests/sys/kqueue/main.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/tests/sys/kqueue/read.c
===================================================================
--- trunk/tests/sys/kqueue/read.c	                        (rev 0)
+++ trunk/tests/sys/kqueue/read.c	2018-07-28 20:42:58 UTC (rev 11972)
@@ -0,0 +1,325 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (c) 2009 Mark Heily <mark at heily.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $FreeBSD: stable/10/tests/sys/kqueue/read.c 200483 2009-12-13 20:27:46Z rwatson $
+ */
+
+#include "common.h"
+
+int kqfd;
+int sockfd[2];
+
+static void
+kevent_socket_drain(void)
+{
+    char buf[1];
+
+    /* Drain the read buffer, then make sure there are no more events. */
+    puts("draining the read buffer");
+    if (read(sockfd[0], &buf[0], 1) < 1)
+        err(1, "read(2)");
+}
+
+static void
+kevent_socket_fill(void)
+{
+  puts("filling the read buffer");
+    if (write(sockfd[1], ".", 1) < 1)
+        err(1, "write(2)");
+}
+
+
+void
+test_kevent_socket_add(void)
+{
+    const char *test_id = "kevent(EVFILT_READ, EV_ADD)";
+    struct kevent kev;
+
+    test_begin(test_id);
+    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    success();
+}
+
+void
+test_kevent_socket_get(void)
+{
+    const char *test_id = "kevent(EVFILT_READ) wait";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    kevent_socket_fill();
+
+    kev.data = 1;
+    kevent_cmp(&kev, kevent_get(kqfd));
+
+    kevent_socket_drain();
+    test_no_kevents();
+
+    kev.flags = EV_DELETE;
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    success();
+}
+
+void
+test_kevent_socket_clear(void)
+{
+    const char *test_id = "kevent(EVFILT_READ, EV_CLEAR)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    test_no_kevents();
+
+    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &sockfd[0]);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    kevent_socket_fill();
+    kevent_socket_fill();
+
+    kev.data = 2;
+    kevent_cmp(&kev, kevent_get(kqfd)); 
+
+    /* We filled twice, but drain once. Edge-triggered would not generate
+       additional events.
+     */
+    kevent_socket_drain();
+    test_no_kevents();
+
+    kevent_socket_drain();
+    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    success();
+}
+
+void
+test_kevent_socket_disable_and_enable(void)
+{
+    const char *test_id = "kevent(EVFILT_READ, EV_DISABLE)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    /* Add an event, then disable it. */
+    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DISABLE, 0, 0, &sockfd[0]);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    kevent_socket_fill();
+    test_no_kevents();
+
+    /* Re-enable the knote, then see if an event is generated */
+    kev.flags = EV_ENABLE;
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+    kev.flags = EV_ADD;
+    kev.data = 1;
+    kevent_cmp(&kev, kevent_get(kqfd));
+
+    kevent_socket_drain();
+
+    kev.flags = EV_DELETE;
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    success();
+}
+
+void
+test_kevent_socket_del(void)
+{
+    const char *test_id = "kevent(EVFILT_READ, EV_DELETE)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    kevent_socket_fill();
+    test_no_kevents();
+    kevent_socket_drain();
+
+    success();
+}
+
+void
+test_kevent_socket_oneshot(void)
+{
+    const char *test_id = "kevent(EVFILT_READ, EV_ONESHOT)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    /* Re-add the watch and make sure no events are pending */
+    puts("-- re-adding knote");
+    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &sockfd[0]);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+    test_no_kevents();
+
+    puts("-- getting one event");
+    kevent_socket_fill();
+    kev.data = 1;
+    kevent_cmp(&kev, kevent_get(kqfd));
+
+    puts("-- checking knote disabled");
+    test_no_kevents();
+
+    /* Try to delete the knote, it should already be deleted */
+    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) == 0)
+        err(1, "%s", test_id);
+
+    kevent_socket_drain();
+
+    success();
+}
+
+
+#if HAVE_EV_DISPATCH
+void
+test_kevent_socket_dispatch(void)
+{
+    const char *test_id = "kevent(EVFILT_READ, EV_DISPATCH)";
+
+    test_begin(test_id);
+
+    struct kevent kev;
+
+    /* Re-add the watch and make sure no events are pending */
+    puts("-- re-adding knote");
+    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_DISPATCH, 0, 0, &sockfd[0]);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+    test_no_kevents();
+
+    /* The event will occur only once, even though EV_CLEAR is not
+       specified. */
+    kevent_socket_fill();
+    kev.data = 1;
+    kevent_cmp(&kev, kevent_get(kqfd));
+    test_no_kevents();
+
+    /* Since the knote is disabled, the EV_DELETE operation succeeds. */
+    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    kevent_socket_drain();
+
+    success();
+}
+#endif  /* HAVE_EV_DISPATCH */
+
+#if BROKEN
+void
+test_kevent_socket_lowat(void)
+{
+    const char *test_id = "kevent(EVFILT_READ, NOTE_LOWAT)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    /* Re-add the watch and make sure no events are pending */
+    puts("-- re-adding knote, setting low watermark to 2 bytes");
+    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, NOTE_LOWAT, 2, &sockfd[0]);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+    test_no_kevents();
+
+    puts("-- checking that one byte does not trigger an event..");
+    kevent_socket_fill();
+    test_no_kevents();
+
+    puts("-- checking that two bytes triggers an event..");
+    kevent_socket_fill();
+    if (kevent(kqfd, NULL, 0, &kev, 1, NULL) != 1)
+        err(1, "%s", test_id);
+    KEV_CMP(kev, sockfd[0], EVFILT_READ, 0);
+    test_no_kevents();
+
+    kevent_socket_drain();
+    kevent_socket_drain();
+
+    success();
+}
+#endif
+
+void
+test_kevent_socket_eof(void)
+{
+    const char *test_id = "kevent(EVFILT_READ, EV_EOF)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    /* Re-add the watch and make sure no events are pending */
+    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+    test_no_kevents();
+
+    if (close(sockfd[1]) < 0)
+        err(1, "close(2)");
+
+    kev.flags |= EV_EOF;
+    kevent_cmp(&kev, kevent_get(kqfd));
+
+    /* Delete the watch */
+    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+
+    success();
+}
+
+void
+test_evfilt_read()
+{
+    /* Create a connected pair of full-duplex sockets for testing socket events */
+    if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) < 0) 
+        abort();
+
+    kqfd = kqueue();
+    test_kevent_socket_add();
+    test_kevent_socket_del();
+    test_kevent_socket_get();
+    test_kevent_socket_disable_and_enable();
+    test_kevent_socket_oneshot();
+    test_kevent_socket_clear();
+#if HAVE_EV_DISPATCH
+    test_kevent_socket_dispatch();
+#endif
+    test_kevent_socket_eof();
+    close(kqfd);
+}


Property changes on: trunk/tests/sys/kqueue/read.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property


More information about the Midnightbsd-cvs mailing list