2 * Copyright (c) 2009 Mark Heily <mark@heily.com>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 static int __thread kqfd;
20 static int __thread vnode_fd;
21 static char __thread testfile[1024];
24 /* Create an empty file */
30 if ((fd = open(testfile, O_CREAT | O_WRONLY, 0600)) < 0)
40 snprintf(&buf[0], sizeof(buf), "touch %s", testfile);
50 snprintf(&buf[0], sizeof(buf), "echo hi >> %s", testfile);
56 testfile_rename(int step)
60 snprintf(&buf[0], sizeof(buf), "%s.tmp", testfile);
61 /* XXX-FIXME use of 'step' conceals a major memory corruption
62 when the file is renamed twice.
63 To replicate, remove "if step" conditional so
64 two renames occur in this function.
67 if (rename(testfile,buf) != 0)
70 if (rename(buf, testfile) != 0)
76 test_kevent_vnode_add(void)
82 vnode_fd = open(testfile, O_RDWR);
84 err(1, "open of %s", testfile);
86 kevent_add(kqfd, &kev, vnode_fd, EVFILT_VNODE, EV_ADD,
87 NOTE_WRITE | NOTE_ATTRIB | NOTE_RENAME | NOTE_DELETE, 0, NULL);
91 test_kevent_vnode_note_delete(void)
95 kevent_add(kqfd, &kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_DELETE, 0, NULL);
97 if (unlink(testfile) < 0)
100 kevent_cmp(&kev, kevent_get(kqfd));
104 test_kevent_vnode_note_write(void)
108 kevent_add(kqfd, &kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_WRITE, 0, NULL);
112 /* BSD kqueue adds NOTE_EXTEND even though it was not requested */
113 /* BSD kqueue removes EV_ENABLE */
114 kev.flags &= ~EV_ENABLE; // XXX-FIXME compatibility issue
115 kev.fflags |= NOTE_EXTEND; // XXX-FIXME compatibility issue
116 kevent_cmp(&kev, kevent_get(kqfd));
120 test_kevent_vnode_note_attrib(void)
125 kevent_add(kqfd, &kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, NULL);
129 nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL);
132 if (kev.ident != vnode_fd ||
133 kev.filter != EVFILT_VNODE ||
134 kev.fflags != NOTE_ATTRIB)
135 err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)",
136 test_id, (unsigned int)kev.ident, kev.filter, kev.flags);
140 test_kevent_vnode_note_rename(void)
145 kevent_add(kqfd, &kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_RENAME, 0, NULL);
149 nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL);
152 if (kev.ident != vnode_fd ||
153 kev.filter != EVFILT_VNODE ||
154 kev.fflags != NOTE_RENAME)
155 err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)",
156 test_id, (unsigned int)kev.ident, kev.filter, kev.flags);
160 test_no_kevents(kqfd);
164 test_kevent_vnode_del(void)
168 kevent_add(kqfd, &kev, vnode_fd, EVFILT_VNODE, EV_DELETE, 0, 0, NULL);
172 test_kevent_vnode_disable_and_enable(void)
177 test_no_kevents(kqfd);
179 /* Add the watch and immediately disable it */
180 kevent_add(kqfd, &kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, NULL);
181 kev.flags = EV_DISABLE;
182 kevent_update(kqfd, &kev);
184 /* Confirm that the watch is disabled */
186 test_no_kevents(kqfd);
188 /* Re-enable and check again */
189 kev.flags = EV_ENABLE;
190 kevent_update(kqfd, &kev);
192 nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL);
195 if (kev.ident != vnode_fd ||
196 kev.filter != EVFILT_VNODE ||
197 kev.fflags != NOTE_ATTRIB)
198 err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)",
199 test_id, (unsigned int)kev.ident, kev.filter, kev.flags);
204 test_kevent_vnode_dispatch(void)
209 test_no_kevents(kqfd);
211 kevent_add(kqfd, &kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_DISPATCH, NOTE_ATTRIB, 0, NULL);
215 nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL);
218 if (kev.ident != vnode_fd ||
219 kev.filter != EVFILT_VNODE ||
220 kev.fflags != NOTE_ATTRIB)
221 err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)",
222 test_id, (unsigned int)kev.ident, kev.filter, kev.flags);
224 /* Confirm that the watch is disabled automatically */
226 test_no_kevents(kqfd);
228 /* Re-enable the kevent */
229 /* FIXME- is EV_DISPATCH needed when rearming ? */
230 kevent_add(kqfd, &kev, vnode_fd, EVFILT_VNODE, EV_ENABLE | EV_DISPATCH, 0, 0, NULL);
231 kev.flags = EV_ADD | EV_DISPATCH; /* FIXME: may not be portable */
232 kev.fflags = NOTE_ATTRIB;
234 kevent_cmp(&kev, kevent_get(kqfd));
235 test_no_kevents(kqfd);
237 /* Delete the watch */
238 kevent_add(kqfd, &kev, vnode_fd, EVFILT_VNODE, EV_DELETE, NOTE_ATTRIB, 0, NULL);
240 #endif /* HAVE_EV_DISPATCH */
243 test_evfilt_vnode(int _kqfd)
245 snprintf(testfile, sizeof(testfile), "/tmp/kqueue-test%d.tmp",
249 test(kevent_vnode_add);
250 test(kevent_vnode_del);
251 test(kevent_vnode_disable_and_enable);
253 test(kevent_vnode_dispatch);
255 test(kevent_vnode_note_write);
256 test(kevent_vnode_note_attrib);
257 test(kevent_vnode_note_rename);
258 test(kevent_vnode_note_delete);