14 * Test cases for events triggered by manipulating a target directory
15 * content. Using EVFILT_VNODE filter on the target directory descriptor.
19 static const char *dir_target = "foo";
20 static const char *dir_inside1 = "foo/bar1";
21 static const char *dir_inside2 = "foo/bar2";
22 static const char *dir_outside = "bar";
23 static const char *file_inside1 = "foo/baz1";
24 static const char *file_inside2 = "foo/baz2";
25 static const char *file_outside = "qux";
26 static const struct timespec ts = {0, 0};
28 static int target = -1;
30 int init_target(void);
31 int init_kqueue(void);
32 int create_file(const char *);
38 if (mkdir(dir_target, S_IRWXU) < 0) {
41 target = open(dir_target, O_RDONLY, 0);
48 struct kevent eventlist[1];
54 EV_SET(&eventlist[0], (uintptr_t)target, EVFILT_VNODE,
55 EV_ADD | EV_ONESHOT, NOTE_DELETE |
56 NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB |
57 NOTE_LINK | NOTE_RENAME | NOTE_REVOKE, 0, 0);
58 return kevent(kq, eventlist, 1, NULL, 0, NULL);
62 create_file(const char *file)
66 fd = open(file, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
76 (void)unlink(file_inside1);
77 (void)unlink(file_inside2);
78 (void)unlink(file_outside);
79 (void)rmdir(dir_inside1);
80 (void)rmdir(dir_inside2);
81 (void)rmdir(dir_outside);
82 (void)rmdir(dir_target);
87 ATF_TC_WITH_CLEANUP(dir_no_note_link_create_file_in);
88 ATF_TC_HEAD(dir_no_note_link_create_file_in, tc)
90 atf_tc_set_md_var(tc, "descr", "This test case ensures "
91 "that kevent(2) does not return NOTE_LINK for the directory "
92 "'foo' if a file 'foo/baz' is created.");
94 ATF_TC_BODY(dir_no_note_link_create_file_in, tc)
96 struct kevent changelist[1];
98 ATF_REQUIRE(init_target() != -1);
99 ATF_REQUIRE(init_kqueue() != -1);
101 ATF_REQUIRE(create_file(file_inside1) != -1);
102 ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
103 ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, 0);
105 ATF_TC_CLEANUP(dir_no_note_link_create_file_in, tc)
110 ATF_TC_WITH_CLEANUP(dir_no_note_link_delete_file_in);
111 ATF_TC_HEAD(dir_no_note_link_delete_file_in, tc)
113 atf_tc_set_md_var(tc, "descr", "This test case ensures "
114 "that kevent(2) does not return NOTE_LINK for the directory "
115 "'foo' if a file 'foo/baz' is deleted.");
117 ATF_TC_BODY(dir_no_note_link_delete_file_in, tc)
119 struct kevent changelist[1];
121 ATF_REQUIRE(init_target() != -1);
122 ATF_REQUIRE(create_file(file_inside1) != -1);
123 ATF_REQUIRE(init_kqueue() != -1);
125 ATF_REQUIRE(unlink(file_inside1) != -1);
126 ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
127 ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, 0);
129 ATF_TC_CLEANUP(dir_no_note_link_delete_file_in, tc)
134 ATF_TC_WITH_CLEANUP(dir_no_note_link_mv_dir_within);
135 ATF_TC_HEAD(dir_no_note_link_mv_dir_within, tc)
137 atf_tc_set_md_var(tc, "descr", "This test case ensures "
138 "that kevent(2) does not return NOTE_LINK for the directory "
139 "'foo' if a directory 'foo/bar' is renamed to 'foo/baz'.");
141 ATF_TC_BODY(dir_no_note_link_mv_dir_within, tc)
143 struct kevent changelist[1];
145 ATF_REQUIRE(init_target() != -1);
146 ATF_REQUIRE(mkdir(dir_inside1, S_IRWXU) != -1);
147 ATF_REQUIRE(init_kqueue() != -1);
149 ATF_REQUIRE(rename(dir_inside1, dir_inside2) != -1);
150 ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
151 ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, 0);
153 ATF_TC_CLEANUP(dir_no_note_link_mv_dir_within, tc)
158 ATF_TC_WITH_CLEANUP(dir_no_note_link_mv_file_within);
159 ATF_TC_HEAD(dir_no_note_link_mv_file_within, tc)
161 atf_tc_set_md_var(tc, "descr", "This test case ensures "
162 "that kevent(2) does not return NOTE_LINK for the directory "
163 "'foo' if a file 'foo/baz' is renamed to 'foo/qux'.");
165 ATF_TC_BODY(dir_no_note_link_mv_file_within, tc)
167 struct kevent changelist[1];
169 ATF_REQUIRE(init_target() != -1);
170 ATF_REQUIRE(create_file(file_inside1) != -1);
171 ATF_REQUIRE(init_kqueue() != -1);
173 ATF_REQUIRE(rename(file_inside1, file_inside2) != -1);
174 ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
175 ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, 0);
177 ATF_TC_CLEANUP(dir_no_note_link_mv_file_within, tc)
182 ATF_TC_WITH_CLEANUP(dir_note_link_create_dir_in);
183 ATF_TC_HEAD(dir_note_link_create_dir_in, tc)
185 atf_tc_set_md_var(tc, "descr", "This test case ensures "
186 "that kevent(2) returns NOTE_LINK for the directory "
187 "'foo' if a directory 'foo/bar' is created.");
189 ATF_TC_BODY(dir_note_link_create_dir_in, tc)
191 struct kevent changelist[1];
193 ATF_REQUIRE(init_target() != -1);
194 ATF_REQUIRE(init_kqueue() != -1);
196 ATF_REQUIRE(mkdir(dir_inside1, S_IRWXU) != -1);
197 ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
198 ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, NOTE_LINK);
200 ATF_TC_CLEANUP(dir_note_link_create_dir_in, tc)
205 ATF_TC_WITH_CLEANUP(dir_note_link_delete_dir_in);
206 ATF_TC_HEAD(dir_note_link_delete_dir_in, tc)
208 atf_tc_set_md_var(tc, "descr", "This test case ensures "
209 "that kevent(2) returns NOTE_LINK for the directory "
210 "'foo' if a directory 'foo/bar' is deleted.");
212 ATF_TC_BODY(dir_note_link_delete_dir_in, tc)
214 struct kevent changelist[1];
216 ATF_REQUIRE(init_target() != -1);
217 ATF_REQUIRE(mkdir(dir_inside1, S_IRWXU) != -1);
218 ATF_REQUIRE(init_kqueue() != -1);
220 ATF_REQUIRE(rmdir(dir_inside1) != -1);
221 ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
222 ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, NOTE_LINK);
224 ATF_TC_CLEANUP(dir_note_link_delete_dir_in, tc)
229 ATF_TC_WITH_CLEANUP(dir_note_link_mv_dir_in);
230 ATF_TC_HEAD(dir_note_link_mv_dir_in, tc)
232 atf_tc_set_md_var(tc, "descr", "This test case ensures "
233 "that kevent(2) returns NOTE_LINK for the directory "
234 "'foo' if a directory 'bar' is renamed to 'foo/bar'.");
236 ATF_TC_BODY(dir_note_link_mv_dir_in, tc)
238 struct kevent changelist[1];
240 ATF_REQUIRE(init_target() != -1);
241 ATF_REQUIRE(mkdir(dir_outside, S_IRWXU) != -1);
242 ATF_REQUIRE(init_kqueue() != -1);
244 ATF_REQUIRE(rename(dir_outside, dir_inside1) != -1);
245 ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
246 ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, NOTE_LINK);
248 ATF_TC_CLEANUP(dir_note_link_mv_dir_in, tc)
253 ATF_TC_WITH_CLEANUP(dir_note_link_mv_dir_out);
254 ATF_TC_HEAD(dir_note_link_mv_dir_out, tc)
256 atf_tc_set_md_var(tc, "descr", "This test case ensures "
257 "that kevent(2) returns NOTE_LINK for the directory "
258 "'foo' if a directory 'foo/bar' is renamed to 'bar'.");
260 ATF_TC_BODY(dir_note_link_mv_dir_out, tc)
262 struct kevent changelist[1];
264 ATF_REQUIRE(init_target() != -1);
265 ATF_REQUIRE(mkdir(dir_inside1, S_IRWXU) != -1);
266 ATF_REQUIRE(init_kqueue() != -1);
268 ATF_REQUIRE(rename(dir_inside1, dir_outside) != -1);
269 ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
270 ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, NOTE_LINK);
272 ATF_TC_CLEANUP(dir_note_link_mv_dir_out, tc)
277 ATF_TC_WITH_CLEANUP(dir_note_write_create_dir_in);
278 ATF_TC_HEAD(dir_note_write_create_dir_in, tc)
280 atf_tc_set_md_var(tc, "descr", "This test case ensures "
281 "that kevent(2) returns NOTE_WRITE for the directory "
282 "'foo' if a directory 'foo/bar' is created.");
284 ATF_TC_BODY(dir_note_write_create_dir_in, tc)
286 struct kevent changelist[1];
288 ATF_REQUIRE(init_target() != -1);
289 ATF_REQUIRE(init_kqueue() != -1);
291 ATF_REQUIRE(mkdir(dir_inside1, S_IRWXU) != -1);
292 ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
293 ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
295 ATF_TC_CLEANUP(dir_note_write_create_dir_in, tc)
300 ATF_TC_WITH_CLEANUP(dir_note_write_create_file_in);
301 ATF_TC_HEAD(dir_note_write_create_file_in, tc)
303 atf_tc_set_md_var(tc, "descr", "This test case ensures "
304 "that kevent(2) returns NOTE_WRITE for the directory "
305 "'foo' if a file 'foo/baz' is created.");
307 ATF_TC_BODY(dir_note_write_create_file_in, tc)
309 struct kevent changelist[1];
311 ATF_REQUIRE(init_target() != -1);
312 ATF_REQUIRE(init_kqueue() != -1);
314 ATF_REQUIRE(create_file(file_inside1) != -1);
315 ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
316 ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
318 ATF_TC_CLEANUP(dir_note_write_create_file_in, tc)
323 ATF_TC_WITH_CLEANUP(dir_note_write_delete_dir_in);
324 ATF_TC_HEAD(dir_note_write_delete_dir_in, tc)
326 atf_tc_set_md_var(tc, "descr", "This test case ensures "
327 "that kevent(2) returns NOTE_WRITE for the directory "
328 "'foo' if a directory 'foo/bar' is deleted.");
330 ATF_TC_BODY(dir_note_write_delete_dir_in, tc)
332 struct kevent changelist[1];
334 ATF_REQUIRE(init_target() != -1);
335 ATF_REQUIRE(mkdir(dir_inside1, S_IRWXU) != -1);
336 ATF_REQUIRE(init_kqueue() != -1);
338 ATF_REQUIRE(rmdir(dir_inside1) != -1);
339 ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
340 ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
342 ATF_TC_CLEANUP(dir_note_write_delete_dir_in, tc)
347 ATF_TC_WITH_CLEANUP(dir_note_write_delete_file_in);
348 ATF_TC_HEAD(dir_note_write_delete_file_in, tc)
350 atf_tc_set_md_var(tc, "descr", "This test case ensures "
351 "that kevent(2) returns NOTE_WRITE for the directory "
352 "'foo' if a file 'foo/baz' is deleted.");
354 ATF_TC_BODY(dir_note_write_delete_file_in, tc)
356 struct kevent changelist[1];
358 ATF_REQUIRE(init_target() != -1);
359 ATF_REQUIRE(create_file(file_inside1) != -1);
360 ATF_REQUIRE(init_kqueue() != -1);
362 ATF_REQUIRE(unlink(file_inside1) != -1);
363 ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
364 ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
366 ATF_TC_CLEANUP(dir_note_write_delete_file_in, tc)
371 ATF_TC_WITH_CLEANUP(dir_note_write_mv_dir_in);
372 ATF_TC_HEAD(dir_note_write_mv_dir_in, tc)
374 atf_tc_set_md_var(tc, "descr", "This test case ensures "
375 "that kevent(2) returns NOTE_WRITE for the directory "
376 "'foo' if a directory 'bar' is renamed to 'foo/bar'.");
378 ATF_TC_BODY(dir_note_write_mv_dir_in, tc)
380 struct kevent changelist[1];
382 ATF_REQUIRE(init_target() != -1);
383 ATF_REQUIRE(mkdir(dir_outside, S_IRWXU) != -1);
384 ATF_REQUIRE(init_kqueue() != -1);
386 ATF_REQUIRE(rename(dir_outside, dir_inside1) != -1);
387 ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
388 ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
390 ATF_TC_CLEANUP(dir_note_write_mv_dir_in, tc)
395 ATF_TC_WITH_CLEANUP(dir_note_write_mv_dir_out);
396 ATF_TC_HEAD(dir_note_write_mv_dir_out, tc)
398 atf_tc_set_md_var(tc, "descr", "This test case ensures "
399 "that kevent(2) returns NOTE_WRITE for the directory "
400 "'foo' if a directory 'foo/bar' is renamed to 'bar'.");
402 ATF_TC_BODY(dir_note_write_mv_dir_out, tc)
404 struct kevent changelist[1];
406 ATF_REQUIRE(init_target() != -1);
407 ATF_REQUIRE(mkdir(dir_inside1, S_IRWXU) != -1);
408 ATF_REQUIRE(init_kqueue() != -1);
410 ATF_REQUIRE(rename(dir_inside1, dir_outside) != -1);
411 ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
412 ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
414 ATF_TC_CLEANUP(dir_note_write_mv_dir_out, tc)
419 ATF_TC_WITH_CLEANUP(dir_note_write_mv_dir_within);
420 ATF_TC_HEAD(dir_note_write_mv_dir_within, tc)
422 atf_tc_set_md_var(tc, "descr", "This test case ensures "
423 "that kevent(2) returns NOTE_WRITE for the directory "
424 "'foo' if a directory 'foo/bar' is renamed to 'foo/baz'.");
426 ATF_TC_BODY(dir_note_write_mv_dir_within, tc)
428 struct kevent changelist[1];
430 ATF_REQUIRE(init_target() != -1);
431 ATF_REQUIRE(mkdir(dir_inside1, S_IRWXU) != -1);
432 ATF_REQUIRE(init_kqueue() != -1);
434 ATF_REQUIRE(rename(dir_inside1, dir_inside2) != -1);
435 ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
436 ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
438 ATF_TC_CLEANUP(dir_note_write_mv_dir_within, tc)
443 ATF_TC_WITH_CLEANUP(dir_note_write_mv_file_in);
444 ATF_TC_HEAD(dir_note_write_mv_file_in, tc)
446 atf_tc_set_md_var(tc, "descr", "This test case ensures "
447 "that kevent(2) returns NOTE_WRITE for the directory "
448 "'foo' if a file 'qux' is renamed to 'foo/baz'.");
450 ATF_TC_BODY(dir_note_write_mv_file_in, tc)
452 struct kevent changelist[1];
454 ATF_REQUIRE(init_target() != -1);
455 ATF_REQUIRE(create_file(file_outside) != -1);
456 ATF_REQUIRE(init_kqueue() != -1);
458 ATF_REQUIRE(rename(file_outside, file_inside1) != -1);
459 ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
460 ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
462 ATF_TC_CLEANUP(dir_note_write_mv_file_in, tc)
467 ATF_TC_WITH_CLEANUP(dir_note_write_mv_file_out);
468 ATF_TC_HEAD(dir_note_write_mv_file_out, tc)
470 atf_tc_set_md_var(tc, "descr", "This test case ensures "
471 "that kevent(2) returns NOTE_WRITE for the directory "
472 "'foo' if a file 'foo/baz' is renamed to 'qux'.");
474 ATF_TC_BODY(dir_note_write_mv_file_out, tc)
476 struct kevent changelist[1];
478 ATF_REQUIRE(init_target() != -1);
479 ATF_REQUIRE(create_file(file_inside1) != -1);
480 ATF_REQUIRE(init_kqueue() != -1);
482 ATF_REQUIRE(rename(file_inside1, file_outside) != -1);
483 ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
484 ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
486 ATF_TC_CLEANUP(dir_note_write_mv_file_out, tc)
491 ATF_TC_WITH_CLEANUP(dir_note_write_mv_file_within);
492 ATF_TC_HEAD(dir_note_write_mv_file_within, tc)
494 atf_tc_set_md_var(tc, "descr", "This test case ensures "
495 "that kevent(2) returns NOTE_WRITE for the directory "
496 "'foo' if a file 'foo/baz' is renamed to 'foo/qux'.");
498 ATF_TC_BODY(dir_note_write_mv_file_within, tc)
500 struct kevent changelist[1];
502 ATF_REQUIRE(init_target() != -1);
503 ATF_REQUIRE(create_file(file_inside1) != -1);
504 ATF_REQUIRE(init_kqueue() != -1);
506 ATF_REQUIRE(rename(file_inside1, file_inside2) != -1);
507 ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
508 ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
510 ATF_TC_CLEANUP(dir_note_write_mv_file_within, tc)
517 ATF_TP_ADD_TC(tp, dir_no_note_link_create_file_in);
518 ATF_TP_ADD_TC(tp, dir_no_note_link_delete_file_in);
519 ATF_TP_ADD_TC(tp, dir_no_note_link_mv_dir_within);
520 ATF_TP_ADD_TC(tp, dir_no_note_link_mv_file_within);
521 ATF_TP_ADD_TC(tp, dir_note_link_create_dir_in);
522 ATF_TP_ADD_TC(tp, dir_note_link_delete_dir_in);
523 ATF_TP_ADD_TC(tp, dir_note_link_mv_dir_in);
524 ATF_TP_ADD_TC(tp, dir_note_link_mv_dir_out);
525 ATF_TP_ADD_TC(tp, dir_note_write_create_dir_in);
526 ATF_TP_ADD_TC(tp, dir_note_write_create_file_in);
527 ATF_TP_ADD_TC(tp, dir_note_write_delete_dir_in);
528 ATF_TP_ADD_TC(tp, dir_note_write_delete_file_in);
529 ATF_TP_ADD_TC(tp, dir_note_write_mv_dir_in);
530 ATF_TP_ADD_TC(tp, dir_note_write_mv_dir_out);
531 ATF_TP_ADD_TC(tp, dir_note_write_mv_dir_within);
532 ATF_TP_ADD_TC(tp, dir_note_write_mv_file_in);
533 ATF_TP_ADD_TC(tp, dir_note_write_mv_file_out);
534 ATF_TP_ADD_TC(tp, dir_note_write_mv_file_within);
535 return atf_no_error();