Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/tests/kernel/kqueue PR/48958: rudolf: EVFILT_VNODE filter mi...



details:   https://anonhg.NetBSD.org/src/rev/0cf2728e7a2f
branches:  trunk
changeset: 805709:0cf2728e7a2f
user:      christos <christos%NetBSD.org@localhost>
date:      Wed Jan 14 22:22:14 2015 +0000

description:
PR/48958: rudolf: EVFILT_VNODE filter miscounting hardlinks (add test)

diffstat:

 tests/kernel/kqueue/t_vnode.c |  533 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 533 insertions(+), 0 deletions(-)

diffs (truncated from 537 to 300 lines):

diff -r 874e17ae9117 -r 0cf2728e7a2f tests/kernel/kqueue/t_vnode.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/kernel/kqueue/t_vnode.c     Wed Jan 14 22:22:14 2015 +0000
@@ -0,0 +1,533 @@
+#include <sys/event.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <atf-c.h>
+
+/*
+ * Test cases for events triggered by manipulating a target directory
+ * content.  Using EVFILT_VNODE filter on the target directory descriptor.
+ *
+ */
+
+static const char *dir_target = "foo";
+static const char *dir_inside1 = "foo/bar1";
+static const char *dir_inside2 = "foo/bar2";
+static const char *dir_outside = "bar";
+static const char *file_inside1 = "foo/baz1";
+static const char *file_inside2 = "foo/baz2";
+static const char *file_outside = "qux";
+static const struct timespec ts = {0, 0};
+static int kq = -1;
+static int target = -1;
+
+int init_target(void);
+int init_kqueue(void);
+int create_file(const char *);
+void cleanup(void);
+
+int
+init_target(void)
+{
+       if (mkdir(dir_target, S_IRWXU) < 0) {
+               return -1;
+       }
+       target = open(dir_target, O_RDONLY, 0);
+       return target;
+}
+
+int
+init_kqueue(void)
+{
+       struct kevent eventlist[1];
+
+       kq = kqueue();
+       if (kq < 0) {
+               return -1;
+       }
+       EV_SET(&eventlist[0], (uintptr_t)target, EVFILT_VNODE,
+               EV_ADD | EV_ONESHOT, NOTE_DELETE |
+               NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB |
+               NOTE_LINK | NOTE_RENAME | NOTE_REVOKE, 0, 0);
+       return kevent(kq, eventlist, 1, NULL, 0, NULL);
+}
+
+int
+create_file(const char *file)
+{
+       int fd;
+
+       fd = open(file, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
+       if (fd < 0) {
+               return -1;
+       }
+       return close(fd);
+}
+
+void
+cleanup(void)
+{
+       (void)unlink(file_inside1);
+       (void)unlink(file_inside2);
+       (void)unlink(file_outside);
+       (void)rmdir(dir_inside1);
+       (void)rmdir(dir_inside2);
+       (void)rmdir(dir_outside);
+       (void)rmdir(dir_target);
+       (void)close(kq);
+       (void)close(target);
+}
+
+ATF_TC_WITH_CLEANUP(dir_no_note_link_create_file_in);
+ATF_TC_HEAD(dir_no_note_link_create_file_in, tc)
+{
+       atf_tc_set_md_var(tc, "descr", "This test case ensures "
+               "that kevent(2) does not return NOTE_LINK for the directory "
+               "'foo' if a file 'foo/baz' is created.");
+}
+ATF_TC_BODY(dir_no_note_link_create_file_in, tc)
+{
+       struct kevent changelist[1];
+
+       ATF_REQUIRE(init_target() != -1);
+       ATF_REQUIRE(init_kqueue() != -1);
+
+       ATF_REQUIRE(create_file(file_inside1) != -1);
+       ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
+       ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, 0);
+}
+ATF_TC_CLEANUP(dir_no_note_link_create_file_in, tc)
+{
+       cleanup();
+}
+
+ATF_TC_WITH_CLEANUP(dir_no_note_link_delete_file_in);
+ATF_TC_HEAD(dir_no_note_link_delete_file_in, tc)
+{
+       atf_tc_set_md_var(tc, "descr", "This test case ensures "
+               "that kevent(2) does not return NOTE_LINK for the directory "
+               "'foo' if a file 'foo/baz' is deleted.");
+}
+ATF_TC_BODY(dir_no_note_link_delete_file_in, tc)
+{
+       struct kevent changelist[1];
+
+       ATF_REQUIRE(init_target() != -1);
+       ATF_REQUIRE(create_file(file_inside1) != -1);
+       ATF_REQUIRE(init_kqueue() != -1);
+
+       ATF_REQUIRE(unlink(file_inside1) != -1);
+       ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
+       ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, 0);
+}
+ATF_TC_CLEANUP(dir_no_note_link_delete_file_in, tc)
+{
+       cleanup();
+}
+
+ATF_TC_WITH_CLEANUP(dir_no_note_link_mv_dir_within);
+ATF_TC_HEAD(dir_no_note_link_mv_dir_within, tc)
+{
+       atf_tc_set_md_var(tc, "descr", "This test case ensures "
+               "that kevent(2) does not return NOTE_LINK for the directory "
+               "'foo' if a directory 'foo/bar' is renamed to 'foo/baz'.");
+}
+ATF_TC_BODY(dir_no_note_link_mv_dir_within, tc)
+{
+       struct kevent changelist[1];
+
+       ATF_REQUIRE(init_target() != -1);
+       ATF_REQUIRE(mkdir(dir_inside1, S_IRWXU) != -1);
+       ATF_REQUIRE(init_kqueue() != -1);
+
+       ATF_REQUIRE(rename(dir_inside1, dir_inside2) != -1);
+       ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
+       ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, 0);
+}
+ATF_TC_CLEANUP(dir_no_note_link_mv_dir_within, tc)
+{
+       cleanup();
+}
+
+ATF_TC_WITH_CLEANUP(dir_no_note_link_mv_file_within);
+ATF_TC_HEAD(dir_no_note_link_mv_file_within, tc)
+{
+       atf_tc_set_md_var(tc, "descr", "This test case ensures "
+               "that kevent(2) does not return NOTE_LINK for the directory "
+               "'foo' if a file 'foo/baz' is renamed to 'foo/qux'.");
+}
+ATF_TC_BODY(dir_no_note_link_mv_file_within, tc)
+{
+       struct kevent changelist[1];
+
+       ATF_REQUIRE(init_target() != -1);
+       ATF_REQUIRE(create_file(file_inside1) != -1);
+       ATF_REQUIRE(init_kqueue() != -1);
+
+       ATF_REQUIRE(rename(file_inside1, file_inside2) != -1);
+       ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
+       ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, 0);
+}
+ATF_TC_CLEANUP(dir_no_note_link_mv_file_within, tc)
+{
+       cleanup();
+}
+
+ATF_TC_WITH_CLEANUP(dir_note_link_create_dir_in);
+ATF_TC_HEAD(dir_note_link_create_dir_in, tc)
+{
+       atf_tc_set_md_var(tc, "descr", "This test case ensures "
+               "that kevent(2) returns NOTE_LINK for the directory "
+               "'foo' if a directory 'foo/bar' is created.");
+}
+ATF_TC_BODY(dir_note_link_create_dir_in, tc)
+{
+       struct kevent changelist[1];
+
+       ATF_REQUIRE(init_target() != -1);
+       ATF_REQUIRE(init_kqueue() != -1);
+
+       ATF_REQUIRE(mkdir(dir_inside1, S_IRWXU) != -1);
+       ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
+       ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, NOTE_LINK);
+}
+ATF_TC_CLEANUP(dir_note_link_create_dir_in, tc)
+{
+       cleanup();
+}
+
+ATF_TC_WITH_CLEANUP(dir_note_link_delete_dir_in);
+ATF_TC_HEAD(dir_note_link_delete_dir_in, tc)
+{
+       atf_tc_set_md_var(tc, "descr", "This test case ensures "
+               "that kevent(2) returns NOTE_LINK for the directory "
+               "'foo' if a directory 'foo/bar' is deleted.");
+}
+ATF_TC_BODY(dir_note_link_delete_dir_in, tc)
+{
+       struct kevent changelist[1];
+
+       ATF_REQUIRE(init_target() != -1);
+       ATF_REQUIRE(mkdir(dir_inside1, S_IRWXU) != -1);
+       ATF_REQUIRE(init_kqueue() != -1);
+
+       ATF_REQUIRE(rmdir(dir_inside1) != -1);
+       ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
+       ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, NOTE_LINK);
+}
+ATF_TC_CLEANUP(dir_note_link_delete_dir_in, tc)
+{
+       cleanup();
+}
+
+ATF_TC_WITH_CLEANUP(dir_note_link_mv_dir_in);
+ATF_TC_HEAD(dir_note_link_mv_dir_in, tc)
+{
+       atf_tc_set_md_var(tc, "descr", "This test case ensures "
+               "that kevent(2) returns NOTE_LINK for the directory "
+               "'foo' if a directory 'bar' is renamed to 'foo/bar'.");
+}
+ATF_TC_BODY(dir_note_link_mv_dir_in, tc)
+{
+       struct kevent changelist[1];
+
+       ATF_REQUIRE(init_target() != -1);
+       ATF_REQUIRE(mkdir(dir_outside, S_IRWXU) != -1);
+       ATF_REQUIRE(init_kqueue() != -1);
+
+       ATF_REQUIRE(rename(dir_outside, dir_inside1) != -1);
+       ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
+       ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, NOTE_LINK);
+}
+ATF_TC_CLEANUP(dir_note_link_mv_dir_in, tc)
+{
+       cleanup();
+}
+
+ATF_TC_WITH_CLEANUP(dir_note_link_mv_dir_out);
+ATF_TC_HEAD(dir_note_link_mv_dir_out, tc)
+{
+       atf_tc_set_md_var(tc, "descr", "This test case ensures "
+               "that kevent(2) returns NOTE_LINK for the directory "
+               "'foo' if a directory 'foo/bar' is renamed to 'bar'.");
+}
+ATF_TC_BODY(dir_note_link_mv_dir_out, tc)
+{
+       struct kevent changelist[1];
+
+       ATF_REQUIRE(init_target() != -1);
+       ATF_REQUIRE(mkdir(dir_inside1, S_IRWXU) != -1);
+       ATF_REQUIRE(init_kqueue() != -1);
+
+       ATF_REQUIRE(rename(dir_inside1, dir_outside) != -1);
+       ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
+       ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, NOTE_LINK);
+}
+ATF_TC_CLEANUP(dir_note_link_mv_dir_out, tc)
+{
+       cleanup();
+}
+
+ATF_TC_WITH_CLEANUP(dir_note_write_create_dir_in);
+ATF_TC_HEAD(dir_note_write_create_dir_in, tc)
+{
+       atf_tc_set_md_var(tc, "descr", "This test case ensures "
+               "that kevent(2) returns NOTE_WRITE for the directory "
+               "'foo' if a directory 'foo/bar' is created.");
+}
+ATF_TC_BODY(dir_note_write_create_dir_in, tc)
+{
+       struct kevent changelist[1];
+
+       ATF_REQUIRE(init_target() != -1);
+       ATF_REQUIRE(init_kqueue() != -1);
+
+       ATF_REQUIRE(mkdir(dir_inside1, S_IRWXU) != -1);
+       ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
+       ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
+}
+ATF_TC_CLEANUP(dir_note_write_create_dir_in, tc)
+{
+       cleanup();
+}
+



Home | Main Index | Thread Index | Old Index