opnsense-src/tests/sys/kqueue/vnode.c
Julio Merino f2ee07cfdc Make use of Kyua's work directories.
Change the vnode tests to use the current directory when creating temporary
files, which we can assume is a volatile work directory, and then make the
kqueue_test.sh driver _not_ abandon the directory created by Kyua.

This makes the various kqueue tests independent of each other, and ensures
the temporary file is cleaned up on failure.

Problem spotted by asomers@ when reviewing D4254.
2016-08-25 10:28:47 +00:00

266 lines
7.4 KiB
C

/*
* Copyright (c) 2009 Mark Heily <mark@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$
*/
#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);
}