]> git.saurik.com Git - apple/xnu.git/blob - tests/kqueue_file_tests.c
xnu-6153.141.1.tar.gz
[apple/xnu.git] / tests / kqueue_file_tests.c
1 #include <string.h>
2 #include <errno.h>
3 #include <pwd.h>
4 #include <stdarg.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <unistd.h>
8 #include <fcntl.h>
9 #include <pthread.h>
10 #include <poll.h>
11 #include <sys/types.h>
12 #include <sys/event.h>
13 #include <sys/time.h>
14 #include <sys/stat.h>
15 #include <sys/mman.h>
16 #include <sys/param.h>
17 #include <sys/mount.h>
18 #include <sys/xattr.h>
19 #include <sys/file.h>
20
21 #include <TargetConditionals.h>
22 #include <darwintest.h>
23
24 T_GLOBAL_META(
25 T_META_NAMESPACE("xnu.kevent")
26 );
27
28 #define PDIR "/tmp"
29 #define DIR1 PDIR "/dir1"
30 #define DOTDOT ".."
31 #define DIR2 PDIR "/dir2"
32 #define FILE1 PDIR "/file1"
33 #define FILE2 PDIR "/file2"
34
35 #define KEY "somekey"
36 #define VAL "someval"
37
38 #define NOSLEEP 0
39 #define SLEEP 1
40 #define NO_EVENT 0
41 #define YES_EVENT 1
42
43
44 #define OUTPUT_LEVEL 0
45 #define RESULT_LEVEL 3
46
47 #define TEST_STRING "Some text!!! Yes indeed, some of that very structure which has passed on man's knowledge for generations."
48 #define HELLO_WORLD "Hello, World!"
49 #define USLEEP_TIME 5000
50 #define WAIT_TIME (4l)
51 #define LENGTHEN_SIZE 500
52 #define FIFO_SPACE 8192 /* FIFOS have 8K of buffer space */
53
54 /*
55 * These two variables are the non local memory for holding the return
56 * values from functions with which pthread_create is called.
57 */
58 int thread_status;
59 int fifo_read_fd;
60
61 /*
62 * Types of actions for setup, cleanup, and execution of tests
63 */
64 typedef enum {CREAT, MKDIR, READ, WRITE, WRITEFD, FILLFD, UNLINK, LSKEE, RMDIR, MKFIFO, LENGTHEN, TRUNC,
65 SYMLINK, CHMOD, CHOWN, EXCHANGEDATA, RENAME, LSEEK, OPEN, MMAP, NOTHING,
66 SETXATTR, UTIMES, STAT, HARDLINK, REVOKE, FUNLOCK} action_id_t;
67
68 /*
69 * Directs an action as mentioned above
70 */
71 typedef struct _action {
72 int act_dosleep;
73 action_id_t act_id;
74 void *act_args[5];
75 int act_fd;
76 } action_t;
77
78 /*
79 * A test case. Specifies setup, an event to look for, an action to take to
80 * cause (or not cause) that event, and cleanup.
81 */
82 typedef struct _test {
83 char *t_testname;
84
85 /* Is this test an expected failure? */
86 int t_known_failure;
87
88 /* Is this test behaving non-deterministically? */
89 int t_nondeterministic;
90
91 /* Test kevent() or poll() */
92 int t_is_poll_test;
93
94 /* Actions for setting up test */
95 int t_n_prep_actions;
96 action_t t_prep_actions[5];
97
98 /* Actions for cleaning up test */
99 int t_n_cleanup_actions;
100 action_t t_cleanup_actions[5];
101
102 /* Action for thred to take while we wait */
103 action_t t_helpthreadact;
104
105 /* File to look for event on */
106 char *t_watchfile; /* set event ident IN TEST (can't know fd beforehand)*/
107 int t_file_is_fifo;/* FIFOs are handled in a special manner */
108
109 /* Different parameters for poll() vs kevent() */
110 union {
111 struct kevent tu_kev;
112 short tu_pollevents;
113 } t_union;
114
115 /* Do we expect results? */
116 int t_want_event;
117
118 /* Not always used--how much data should we find (EVFILT_{READ,WRITE}) */
119 int t_nbytes;
120
121 /* Hacks for FILT_READ and pipes */
122 int t_read_to_end_first; /* Consume all data in file before waiting for event */
123 int t_write_some_data; /* Write some data to file before waiting for event (FIFO hack) */
124 int t_extra_sleep_hack; /* Sleep before waiting, to let a fifo fill up with data */
125 } test_t;
126
127 char *
128 get_action_name(action_id_t a)
129 {
130 switch (a) {
131 case CREAT:
132 return "CREAT";
133 case MKDIR:
134 return "MKDIR";
135 case READ:
136 return "READ";
137 case WRITE:
138 return "WRITE";
139 case WRITEFD:
140 return "WRITEFD";
141 case FILLFD:
142 return "FILLFD";
143 case UNLINK:
144 return "UNLINK";
145 case LSKEE:
146 return "LSKEE";
147 case RMDIR:
148 return "RMDIR";
149 case MKFIFO:
150 return "MKFIFO";
151 case LENGTHEN:
152 return "LENGTHEN";
153 case TRUNC:
154 return "TRUNC";
155 case SYMLINK:
156 return "SYMLINK";
157 case CHMOD:
158 return "CHMOD";
159 case CHOWN:
160 return "CHOWN";
161 case EXCHANGEDATA:
162 return "EXCHANGEDATA";
163 case RENAME:
164 return "RENAME";
165 case LSEEK:
166 return "LSEEK";
167 case OPEN:
168 return "OPEN";
169 case MMAP:
170 return "MMAP";
171 case NOTHING:
172 return "NOTHING";
173 case SETXATTR:
174 return "SETXATTR";
175 case UTIMES:
176 return "UTIMES";
177 case STAT:
178 return "STAT";
179 case HARDLINK:
180 return "HARDLINK";
181 case REVOKE:
182 return "REVOKE";
183 case FUNLOCK:
184 return "FUNLOCK";
185 }
186 return "Unknown";
187 }
188 /*
189 * Initialize an action struct. Whether to sleep, what action to take,
190 * and arguments for that action.
191 */
192 void
193 init_action(action_t *act, int sleep, action_id_t call, int nargs, ...)
194 {
195 int i;
196 va_list ap;
197 va_start(ap, nargs);
198 act->act_dosleep = sleep;
199 act->act_id = call;
200
201 for (i = 0; i < nargs; i++) {
202 act->act_args[i] = va_arg(ap, void*);
203 }
204
205 va_end(ap);
206 }
207
208 /*
209 * Opening a fifo is complicated: need to open both sides at once
210 */
211 void *
212 open_fifo_readside(void *arg)
213 {
214 if ((fifo_read_fd = open((char*)arg, O_RDONLY)) == -1) {
215 T_LOG("open(%s, O_RDONLY) failed: %d (%s)\n", arg, errno, strerror(errno));
216 }
217 return &fifo_read_fd;
218 }
219
220 /*
221 * Open a fifo, setting read and write descriptors. Return 0 for success, -1 for failure.
222 * Only set FD args upon success; they will be unmodified on failure.
223 */
224 int
225 open_fifo(const char *path, int *readfd, int *writefd)
226 {
227 pthread_t thread;
228 int waitres;
229 int res;
230 int *tmpreadfd, tmpwritefd;
231
232 fifo_read_fd = -1;
233 res = pthread_create(&thread, 0, open_fifo_readside, (void*)path);
234 if (res == 0) {
235 if ((tmpwritefd = open(path, O_WRONLY)) == -1) {
236 T_LOG("open(%s, O_WRONLY) failed: %d (%s)\n", path, errno, strerror(errno));
237 return -1;
238 }
239 waitres = pthread_join(thread, (void**) &tmpreadfd);
240
241 fcntl(tmpwritefd, F_SETFL, O_WRONLY | O_NONBLOCK);
242
243 if ((waitres == 0) && (tmpwritefd >= 0) && (*tmpreadfd >= 0)) {
244 *readfd = *tmpreadfd;
245 *writefd = tmpwritefd;
246 } else {
247 res = -1;
248 }
249 }
250
251 return res;
252 }
253
254 /*
255 * Just concatenate a directory and a filename, sticking a "/" betwixt them
256 */
257 void
258 makepath(char *buf, const char *dir, const char *file)
259 {
260 strcpy(buf, dir);
261 strcat(buf, "/");
262 strcat(buf, file);
263 }
264
265
266 /* Execute a prep, cleanup, or test action; specific tricky notes below.
267 *
268 * CREAT: comes to life and given length 1
269 * READ: try to read one char
270 * WRITE: try to write TEST_STRING to file
271 * LENGTHEN: make longer by LENGTHEN_SIZE
272 * MMAP: mmap first 20 bytes of file, write HELLO_WORLD in
273 * SETXATTR: set the KEY attribute to value VAL
274 * WRITEFD: instead of opening fresh, take an FD in the action struct (FIFOs)
275 * FILLFD: write a file until you can no longer. for filling FIFOS.
276 *
277 * * Several of these have hard-coded sizes.
278 */
279 void*
280 execute_action(void *actionptr)
281 {
282 action_t *act = (action_t*)actionptr;
283 void **args = act->act_args;
284 char c;
285 int res = -1, tmpfd, tmpfd2;
286 static int lastfd;
287 void *addr;
288 struct timeval tv;
289 struct stat sstat;
290
291 T_LOG("Beginning action of type %d: %s\n", act->act_id, get_action_name(act->act_id));
292
293 /* Let other thread get into kevent() sleep */
294 if (SLEEP == act->act_dosleep) {
295 usleep(USLEEP_TIME);
296 }
297 switch (act->act_id) {
298 case NOTHING:
299 res = 0;
300 break;
301 case CREAT:
302 if ((tmpfd = creat((char*)args[0], 0755)) == -1) {
303 T_LOG("creat() failed on \"%s\": %d (%s)\n", args[0], errno, strerror(errno));
304 res = -1;
305 break;
306 }
307 ftruncate(tmpfd, 1); /* So that mmap() doesn't fool us */
308 close(tmpfd);
309 res = 0;
310 break;
311 case MKDIR:
312 res = mkdir((char*)args[0], 0755);
313 break;
314 case READ:
315 if ((tmpfd = open((char*)args[0], O_RDONLY)) == -1) {
316 T_LOG("open(%s, O_RDONLY) failed: %d (%s)\n", args[0], errno, strerror(errno));
317 res = -1;
318 break;
319 }
320 res = read(tmpfd, &c, 1);
321 res = (res == 1 ? 0 : -1);
322 close(tmpfd);
323 break;
324 case WRITE:
325 if ((tmpfd = open((char*)args[0], O_RDWR)) == -1) {
326 T_LOG("open(%s, O_RDWR) failed: %d (%s)\n", args[0], errno, strerror(errno));
327 res = -1;
328 break;
329 }
330 res = write(tmpfd, TEST_STRING, strlen(TEST_STRING));
331 if (res == strlen(TEST_STRING)) {
332 res = 0;
333 } else {
334 res = -1;
335 }
336 close(tmpfd);
337 break;
338 case WRITEFD:
339 res = write((int)act->act_fd, TEST_STRING, strlen(TEST_STRING));
340 if (res == strlen(TEST_STRING)) {
341 res = 0;
342 } else {
343 res = -1;
344 }
345 break;
346 case FILLFD:
347 while (write((int)act->act_fd, "a", 1) > 0) {
348 ;
349 }
350 res = 0;
351 break;
352 case UNLINK:
353 res = unlink((char*)args[0]);
354 break;
355 case LSEEK:
356 res = lseek((int)act->act_fd, (int)args[0], SEEK_SET);
357 res = (res == (int)args[0] ? 0 : -1);
358 break;
359 case RMDIR:
360 res = rmdir((char*)args[0]);
361 break;
362 case MKFIFO:
363 res = mkfifo((char*)args[0], 0755);
364 break;
365 case LENGTHEN:
366 res = truncate((char*)args[0], LENGTHEN_SIZE);
367 break;
368 case TRUNC:
369 res = truncate((char*)args[0], 0);
370 break;
371 case SYMLINK:
372 res = symlink((char*)args[0], (char*)args[1]);
373 break;
374 case CHMOD:
375 res = chmod((char*)args[0], (int)args[1]);
376 break;
377 case CHOWN:
378 /* path, uid, gid */
379 res = chown((char*)args[0], (int) args[1], (int) args[2]);
380 break;
381 case EXCHANGEDATA:
382 res = exchangedata((char*)args[0], (char*)args[1], 0);
383 break;
384 case RENAME:
385 res = rename((char*)args[0], (char*)args[1]);
386 break;
387 case OPEN:
388 if ((tmpfd = open((char*)args[0], O_RDONLY | O_CREAT)) == -1) {
389 T_LOG("open(%s, O_RDONLY | O_CREAT) failed: %d (%s)\n", args[0], errno, strerror(errno));
390 res = -1;
391 break;
392 }
393 res = close(tmpfd);
394 break;
395 case MMAP:
396 /* It had best already exist with nonzero size */
397 if ((tmpfd = open((char*)args[0], O_RDWR)) == -1) {
398 T_LOG("open(%s, O_RDWR) failed: %d (%s)\n", args[0], errno, strerror(errno));
399 res = -1;
400 break;
401 }
402 addr = mmap(0, 20, PROT_WRITE | PROT_READ, MAP_FILE | MAP_SHARED, tmpfd, 0);
403 if (addr != ((void*)-1)) {
404 res = 0;
405 if ((int)args[1]) {
406 strcpy((char*)addr, HELLO_WORLD);
407 msync(addr, 20, MS_SYNC);
408 }
409 }
410 close(tmpfd);
411 munmap(addr, 20);
412 break;
413 case SETXATTR:
414 res = setxattr((char*)args[0], KEY, (void*)VAL, strlen(VAL),
415 0, 0);
416 break;
417 case UTIMES:
418 tv.tv_sec = time(NULL);
419 tv.tv_usec = 0;
420 res = utimes((char*)args[0], &tv);
421 break;
422 case STAT:
423 res = lstat((char*)args[0], &sstat);
424 break;
425 case HARDLINK:
426 res = link((char*)args[0], (char*)args[1]);
427 break;
428 case REVOKE:
429 if ((tmpfd = open((char*)args[0], O_RDONLY)) == -1) {
430 T_LOG("open(%s, O_RDONLY) failed: %d (%s)\n", args[0], errno, strerror(errno));
431 res = -1;
432 break;
433 }
434 res = revoke((char*)args[0]);
435 close(tmpfd);
436 break;
437 case FUNLOCK:
438 if ((tmpfd = open((char*)args[0], O_RDONLY)) == -1) {
439 T_LOG("open(%s, O_RDONLY) failed: %d (%s)\n", args[0], errno, strerror(errno));
440 res = -1;
441 break;
442 }
443 if ((res = flock(tmpfd, LOCK_EX)) == -1) {
444 T_LOG("flock() LOCK_EX failed: %d (%s)\n", errno, strerror(errno));
445 close(tmpfd);
446 break;
447 }
448 if ((res = flock(tmpfd, LOCK_UN)) == -1) {
449 T_LOG("flock() LOCK_UN failed: %d (%s)\n", errno, strerror(errno));
450 close(tmpfd);
451 break;
452 }
453 close(tmpfd);
454 break;
455 default:
456 res = -1;
457 break;
458 }
459
460 thread_status = res;
461 return &thread_status;
462 }
463
464 /*
465 * Read until the end of a file, for EVFILT_READ purposes (considers file position)
466 */
467 void
468 read_to_end(int fd)
469 {
470 char buf[50];
471 while (read(fd, buf, sizeof(buf)) > 0) {
472 ;
473 }
474 }
475
476 /*
477 * Helper for setup and cleanup; just execute every action in an array
478 * of actions. "failout" parameter indicates whether to stop if one fails.
479 */
480 int
481 execute_action_list(action_t *actions, int nactions, int failout)
482 {
483 int i, res;
484 for (i = 0, res = 0; (0 == res || (!failout)) && (i < nactions); i++) {
485 T_LOG("Starting prep action %d\n", i);
486 res = *((int *) execute_action(&(actions[i])));
487 if (res != 0) {
488 T_LOG("Action list failed on step %d. res = %d errno = %d (%s)\n", i, res,
489 errno, strerror(errno));
490 } else {
491 T_LOG("Action list work succeeded on step %d.\n", i);
492 }
493 }
494
495 return res;
496 }
497
498 /*
499 * Execute a full test, return success value.
500 */
501 int
502 execute_test(test_t *test)
503 {
504 int i, kqfd, filefd = -1, res2, res, cnt, writefd = -1;
505 int retval = -1;
506 pthread_t thr;
507 struct kevent evlist;
508 struct timespec ts = {WAIT_TIME, 0l};
509 int *status;
510
511 memset(&evlist, 0, sizeof(evlist));
512
513 T_LOG("[BEGIN] %s\n", test->t_testname);
514
515 T_LOG(test->t_want_event ? "Expecting an event.\n" : "Not expecting events.\n");
516
517 res = execute_action_list(test->t_prep_actions, test->t_n_prep_actions, 1);
518
519 /* If prep succeeded */
520 if (0 == res) {
521 /* Create kqueue for kqueue tests*/
522 if (!test->t_is_poll_test) {
523 if ((kqfd = kqueue()) == -1) {
524 T_LOG("kqueue() failed: %d (%s)\n", errno, strerror(errno));
525 }
526 }
527
528 if ((test->t_is_poll_test) || kqfd >= 0) {
529 /* Open the file we're to monitor. Fifos get special handling */
530 if (test->t_file_is_fifo) {
531 filefd = -1;
532 open_fifo(test->t_watchfile, &filefd, &writefd);
533 } else {
534 if ((filefd = open(test->t_watchfile, O_RDONLY | O_SYMLINK)) == -1) {
535 T_LOG("open() of watchfile %s failed: %d (%s)\n", test->t_watchfile,
536 errno, strerror(errno));
537 }
538 }
539
540 if (filefd >= 0) {
541 T_LOG("Opened file to monitor.\n");
542
543 /*
544 * Fill in the fd to monitor once you know it
545 * If it's a fifo test, then the helper is definitely going to want the write end.
546 */
547 test->t_helpthreadact.act_fd = (writefd >= 0 ? writefd : filefd);
548
549 if (test->t_read_to_end_first) {
550 read_to_end(filefd);
551 } else if (test->t_write_some_data) {
552 action_t dowr;
553 init_action(&dowr, NOSLEEP, WRITEFD, 0);
554 dowr.act_fd = writefd;
555 (void)execute_action(&dowr);
556 }
557
558 /* Helper modifies the file that we're listening on (sleeps first, in general) */
559 thread_status = 0;
560 res = pthread_create(&thr, NULL, execute_action, (void*) &test->t_helpthreadact);
561 if (0 == res) {
562 T_LOG("Created helper thread.\n");
563
564 /* This is ugly business to hack on filling up a FIFO */
565 if (test->t_extra_sleep_hack) {
566 usleep(USLEEP_TIME);
567 }
568
569 if (test->t_is_poll_test) {
570 struct pollfd pl;
571 pl.fd = filefd;
572 pl.events = test->t_union.tu_pollevents;
573 cnt = poll(&pl, 1, WAIT_TIME);
574 T_LOG("Finished poll() call.\n");
575 if ((cnt < 0)) {
576 T_LOG("error is in errno, %s\n", strerror(errno));
577 res = cnt;
578 }
579 } else {
580 test->t_union.tu_kev.ident = filefd;
581 cnt = kevent(kqfd, &test->t_union.tu_kev, 1, &evlist, 1, &ts);
582 T_LOG("Finished kevent() call.\n");
583
584 if ((cnt < 0) || (evlist.flags & EV_ERROR)) {
585 T_LOG("kevent() call failed.\n");
586 if (cnt < 0) {
587 T_LOG("error is in errno, %s\n", strerror(errno));
588 } else {
589 T_LOG("error is in data, %s\n", strerror(evlist.data));
590 }
591 res = cnt;
592 }
593 }
594
595 /* Success only if you've succeeded to this point AND joined AND other thread is happy*/
596 status = NULL;
597 res2 = pthread_join(thr, (void **)&status);
598 if (res2 != 0) {
599 T_LOG("Couldn't join helper thread: %d (%s).\n", res2,
600 strerror(res2));
601 } else if (*status) {
602 T_LOG("Helper action had result %d\n", *status);
603 }
604 res = ((res == 0) && (res2 == 0) && (*status == 0)) ? 0 : -1;
605 } else {
606 T_LOG("Couldn't start thread: %d (%s).\n", res, strerror(res));
607 }
608
609 close(filefd);
610 if (test->t_file_is_fifo) {
611 close(writefd);
612 }
613 } else {
614 T_LOG("Couldn't open test file %s to monitor: %d (%s)\n", test->t_watchfile);
615 res = -1;
616 }
617 if (!test->t_is_poll_test) {
618 close(kqfd);
619 }
620 } else {
621 T_LOG("Couldn't open kqueue.\n");
622 res = -1;
623 }
624 }
625
626 /* Cleanup work */
627 execute_action_list(test->t_cleanup_actions, test->t_n_cleanup_actions, 0);
628
629 /* Success if nothing failed and we either received or did not receive event,
630 * as expected
631 */
632 if (0 == res) {
633 T_LOG(cnt > 0 ? "Got an event.\n" : "Did not get an event.\n");
634 if (((cnt > 0) && (test->t_want_event)) || ((cnt == 0) && (!test->t_want_event))) {
635 if ((!test->t_is_poll_test) && (test->t_union.tu_kev.filter == EVFILT_READ || test->t_union.tu_kev.filter == EVFILT_WRITE)
636 && (test->t_nbytes) && (test->t_nbytes != evlist.data)) {
637 T_LOG("Read wrong number of bytes available. Wanted %d, got %d\n", test->t_nbytes, evlist.data);
638 retval = -1;
639 } else {
640 retval = 0;
641 }
642 } else {
643 T_LOG("Got unexpected event or lack thereof.\n");
644 retval = -1;
645 }
646 } else {
647 T_LOG("Failed to execute test. res = %d\n", res);
648 retval = -1;
649 }
650
651 if (test->t_nondeterministic) {
652 T_LOG("XXX non-deterministic test result = %d (%s)\n", retval,
653 (retval == 0) ? "pass" : "fail");
654 T_MAYFAIL;
655 } else {
656 if (test->t_known_failure) {
657 // Signal to harness that this test is expected to fail.
658 T_EXPECTFAIL;
659 }
660 }
661
662 if (retval == 0) {
663 T_PASS("%s", test->t_testname);
664 } else {
665 T_FAIL("%s", test->t_testname);
666 }
667
668 T_LOG("Test %s done with result %d.\n", test->t_testname, retval);
669 return retval;
670 }
671
672
673
674 void
675 init_test_common(test_t *tst, char *testname, char *watchfile, int nprep, int nclean, int event, int want, int ispoll)
676 {
677 memset(tst, 0, sizeof(test_t));
678 tst->t_testname = testname;
679 tst->t_known_failure = 0;
680 tst->t_nondeterministic = 0;
681 tst->t_watchfile = watchfile;
682 tst->t_n_prep_actions = nprep;
683 tst->t_n_cleanup_actions = nclean;
684 tst->t_want_event = (want > 0);
685
686 if (ispoll) {
687 tst->t_is_poll_test = 1;
688 tst->t_union.tu_pollevents = (short)event;
689 } else {
690 /* Can do this because filter is negative, notes are positive */
691 if (event == EVFILT_READ || event == EVFILT_WRITE) {
692 EV_SET(&tst->t_union.tu_kev, 0, event, EV_ADD | EV_ENABLE, 0, 0, NULL);
693 tst->t_nbytes = want;
694 } else {
695 EV_SET(&tst->t_union.tu_kev, 0, EVFILT_VNODE, EV_ADD | EV_ENABLE, event, 0, NULL);
696 }
697 }
698 }
699
700 /*
701 * Initialize a test case, not including its actions. Meaning: a name for it, what filename to watch,
702 * counts of prep and cleanup actions, what event to watch for, and whether you want an event/how many bytes read.
703 *
704 * "want" does double duty as whether you want an event and how many bytes you might want to read
705 * "event" is either an event flag (e.g. NOTE_WRITE) or EVFILT_READ
706 */
707 void
708 init_test(test_t *tst, char *testname, char *watchfile, int nprep, int nclean, int event, int want)
709 {
710 init_test_common(tst, testname, watchfile, nprep, nclean, event, want, 0);
711 }
712
713 /*
714 * Same as above, but for a poll() test
715 */
716 void
717 init_poll_test(test_t *tst, char *testname, char *watchfile, int nprep, int nclean, int event, int want)
718 {
719 init_test_common(tst, testname, watchfile, nprep, nclean, event, want, 1);
720 }
721
722 void
723 run_note_delete_tests()
724 {
725 test_t test;
726
727 init_test(&test, "1.1.2: unlink a file", FILE1, 1, 0, NOTE_DELETE, YES_EVENT);
728 test.t_nondeterministic = 1;
729 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
730 init_action(&test.t_helpthreadact, SLEEP, UNLINK, 2, (void*)FILE1, NULL);
731 execute_test(&test);
732
733 init_test(&test, "1.1.3: rmdir a dir", DIR1, 1, 0, NOTE_DELETE, YES_EVENT);
734 test.t_nondeterministic = 1;
735 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
736 init_action(&test.t_helpthreadact, SLEEP, RMDIR, 2, (void*)DIR1, NULL);
737 execute_test(&test);
738
739 init_test(&test, "1.1.4: rename one file over another", FILE2, 2, 1, NOTE_DELETE, YES_EVENT);
740 test.t_nondeterministic = 1;
741 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
742 init_action(&(test.t_prep_actions[1]), NOSLEEP, CREAT, 2, (void*)FILE2, (void*)NULL);
743 init_action(&test.t_helpthreadact, SLEEP, RENAME, 2, (void*)FILE1, (void*)FILE2);
744 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE2, NULL);
745 execute_test(&test);
746
747 init_test(&test, "1.1.5: rename one dir over another", DIR2, 2, 1, NOTE_DELETE, YES_EVENT);
748 test.t_nondeterministic = 1;
749 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
750 init_action(&(test.t_prep_actions[1]), NOSLEEP, MKDIR, 2, (void*)DIR2, (void*)NULL);
751 init_action(&test.t_helpthreadact, SLEEP, RENAME, 2, (void*)DIR1, (void*)DIR2);
752 init_action(&test.t_cleanup_actions[0], NOSLEEP, RMDIR, 2, (void*)DIR2, NULL);
753 execute_test(&test);
754
755 /* Do FIFO stuff here */
756 init_test(&test, "1.1.6: make a fifo, unlink it", FILE1, 1, 0, NOTE_DELETE, YES_EVENT);
757 test.t_file_is_fifo = 1;
758 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKFIFO, 2, (void*)FILE1, (void*)NULL);
759 init_action(&test.t_helpthreadact, SLEEP, UNLINK, 1, (void*)FILE1);
760 execute_test(&test);
761
762 init_test(&test, "1.1.7: rename a file over a fifo", FILE1, 2, 1, NOTE_DELETE, YES_EVENT);
763 test.t_nondeterministic = 1;
764 test.t_file_is_fifo = 1;
765 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKFIFO, 2, (void*)FILE1, (void*)NULL);
766 init_action(&(test.t_prep_actions[1]), NOSLEEP, CREAT, 2, (void*)FILE2, (void*)NULL);
767 init_action(&test.t_helpthreadact, SLEEP, RENAME, 2, (void*)FILE2, (void*)FILE1);
768 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, NULL);
769 execute_test(&test);
770
771 init_test(&test, "1.1.8: unlink a symlink to a file", FILE2, 2, 1, NOTE_DELETE, YES_EVENT);
772 test.t_nondeterministic = 1;
773 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
774 init_action(&(test.t_prep_actions[1]), NOSLEEP, SYMLINK, 2, (void*)FILE1, (void*)FILE2);
775 init_action(&test.t_helpthreadact, SLEEP, UNLINK, 2, (void*)FILE2, NULL);
776 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, NULL);
777 execute_test(&test);
778
779 /* ================= */
780
781 init_test(&test, "1.2.1: Straight-up rename file", FILE1, 1, 1, NOTE_DELETE, NO_EVENT);
782 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
783 init_action(&test.t_helpthreadact, SLEEP, RENAME, 2, (void*)FILE1, (void*)FILE2);
784 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE2, (void*)NULL);
785 execute_test(&test);
786
787 init_test(&test, "1.2.2: Straight-up rename dir", DIR1, 1, 1, NOTE_DELETE, NO_EVENT);
788 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
789 init_action(&test.t_helpthreadact, SLEEP, RENAME, 2, (void*)DIR1, (void*)DIR2);
790 init_action(&test.t_cleanup_actions[0], NOSLEEP, RMDIR, 2, (void*)DIR2, (void*)NULL);
791 execute_test(&test);
792
793 init_test(&test, "1.2.3: Null action on file", FILE1, 1, 1, NOTE_DELETE, NO_EVENT);
794 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
795 init_action(&test.t_helpthreadact, SLEEP, NOTHING, 2, NULL, NULL); /* The null action */
796 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, (void*)NULL);
797 execute_test(&test);
798
799 init_test(&test, "1.2.4: Rename one file over another: watch the file that lives", FILE1, 2, 1, NOTE_DELETE, NO_EVENT);
800 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
801 init_action(&(test.t_prep_actions[1]), NOSLEEP, CREAT, 2, (void*)FILE2, (void*)NULL);
802 init_action(&test.t_helpthreadact, SLEEP, RENAME, 2, (void*)FILE1, (void*)FILE2);
803 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE2, NULL);
804 execute_test(&test);
805
806 init_test(&test, "1.2.5: Rename one dir over another, watch the dir that lives", DIR1, 2, 1, NOTE_DELETE, NO_EVENT);
807 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
808 init_action(&(test.t_prep_actions[1]), NOSLEEP, MKDIR, 2, (void*)DIR2, (void*)NULL);
809 init_action(&test.t_helpthreadact, SLEEP, RENAME, 2, (void*)DIR1, (void*)DIR2);
810 init_action(&test.t_cleanup_actions[0], NOSLEEP, RMDIR, 2, (void*)DIR2, NULL);
811 }
812
813 static bool
814 path_on_apfs(const char *path)
815 {
816 struct statfs sfs = {};
817 T_QUIET; T_ASSERT_POSIX_SUCCESS(statfs(path, &sfs), NULL);
818 return memcmp(&sfs.f_fstypename[0], "apfs", strlen("apfs")) == 0;
819 }
820
821 void
822 run_note_write_tests()
823 {
824 char pathbuf[50];
825 char otherpathbuf[50];
826
827 test_t test;
828
829 init_test(&test, "2.1.1: Straight-up write to a file", FILE1, 1, 1, NOTE_WRITE, YES_EVENT);
830 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
831 init_action(&test.t_helpthreadact, SLEEP, WRITE, 2, (void*)FILE1, NULL);
832 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, (void*)NULL);
833 execute_test(&test);
834
835
836 makepath(pathbuf, DIR1, FILE1);
837 init_test(&test, "2.1.2: creat() file inside a dir", DIR1, 1, 2, NOTE_WRITE, YES_EVENT);
838 test.t_known_failure = 1;
839 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
840 init_action(&test.t_helpthreadact, SLEEP, CREAT, 2, (void*)pathbuf, NULL);
841 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)pathbuf, (void*)NULL);
842 init_action(&test.t_cleanup_actions[1], NOSLEEP, RMDIR, 2, (void*)DIR1, (void*)NULL);
843 execute_test(&test);
844
845 makepath(pathbuf, DIR1, FILE1);
846 init_test(&test, "2.1.3: open() file inside a dir", DIR1, 1, 2, NOTE_WRITE, YES_EVENT);
847 test.t_known_failure = 1;
848 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
849 init_action(&test.t_helpthreadact, SLEEP, OPEN, 2, (void*)pathbuf, NULL);
850 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)pathbuf, (void*)NULL);
851 init_action(&test.t_cleanup_actions[1], NOSLEEP, RMDIR, 2, (void*)DIR1, (void*)NULL);
852 execute_test(&test);
853
854 makepath(pathbuf, DIR1, FILE1);
855 init_test(&test, "2.1.4: unlink a file from a dir", DIR1, 2, 1, NOTE_WRITE, YES_EVENT);
856 test.t_known_failure = 1;
857 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
858 init_action(&(test.t_prep_actions[1]), NOSLEEP, CREAT, 2, (void*)pathbuf, (void*)NULL);
859 init_action(&test.t_helpthreadact, SLEEP, UNLINK, 2, (void*)pathbuf, NULL);
860 init_action(&test.t_cleanup_actions[0], NOSLEEP, RMDIR, 2, (void*)DIR1, (void*)NULL);
861 execute_test(&test);
862
863 makepath(pathbuf, DIR1, FILE1);
864 makepath(otherpathbuf, DIR1, FILE2);
865 init_test(&test, "2.1.5: rename a file in a dir", DIR1, 2, 2, NOTE_WRITE, YES_EVENT);
866 test.t_known_failure = 1;
867 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
868 init_action(&(test.t_prep_actions[1]), NOSLEEP, CREAT, 2, (void*)pathbuf, (void*)NULL);
869 init_action(&test.t_helpthreadact, SLEEP, RENAME, 2, (void*)pathbuf, (void*)otherpathbuf);
870 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)otherpathbuf, (void*)NULL);
871 init_action(&test.t_cleanup_actions[1], NOSLEEP, RMDIR, 2, (void*)DIR1, (void*)NULL);
872 execute_test(&test);
873
874 makepath(pathbuf, DIR1, FILE1);
875 init_test(&test, "2.1.6: rename a file to outside of a dir", DIR1, 2, 2, NOTE_WRITE, YES_EVENT);
876 test.t_known_failure = 1;
877 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
878 init_action(&(test.t_prep_actions[1]), NOSLEEP, CREAT, 2, (void*)pathbuf, (void*)NULL);
879 init_action(&test.t_helpthreadact, SLEEP, RENAME, 2, (void*)pathbuf, (void*)FILE1);
880 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, (void*)NULL);
881 init_action(&test.t_cleanup_actions[1], NOSLEEP, RMDIR, 2, (void*)DIR1, (void*)NULL);
882 execute_test(&test);
883
884 makepath(pathbuf, DIR1, FILE1);
885 init_test(&test, "2.1.7: rename a file into a dir", DIR1, 2, 2, NOTE_WRITE, YES_EVENT);
886 test.t_known_failure = 1;
887 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
888 init_action(&(test.t_prep_actions[1]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
889 init_action(&test.t_helpthreadact, SLEEP, RENAME, 2, (void*)FILE1, (void*)pathbuf);
890 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)pathbuf, (void*)NULL);
891 init_action(&test.t_cleanup_actions[1], NOSLEEP, RMDIR, 2, (void*)DIR1, (void*)NULL);
892 execute_test(&test);
893
894 makepath(pathbuf, DIR1, FILE1);
895 init_test(&test, "2.1.9: unlink a fifo from a dir", DIR1, 2, 1, NOTE_WRITE, YES_EVENT);
896 test.t_known_failure = 1;
897 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
898 init_action(&(test.t_prep_actions[1]), NOSLEEP, MKFIFO, 2, (void*)pathbuf, (void*)NULL);
899 init_action(&test.t_helpthreadact, SLEEP, UNLINK, 2, (void*)pathbuf, NULL);
900 init_action(&test.t_cleanup_actions[0], NOSLEEP, RMDIR, 2, (void*)DIR1, (void*)NULL);
901 execute_test(&test);
902
903 makepath(pathbuf, DIR1, FILE1);
904 init_test(&test, "2.1.10: make symlink in a dir", DIR1, 1, 2, NOTE_WRITE, YES_EVENT);
905 test.t_known_failure = 1;
906 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
907 init_action(&test.t_helpthreadact, SLEEP, SYMLINK, 2, (void*)DOTDOT, (void*)pathbuf);
908 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)pathbuf, (void*)NULL);
909 init_action(&test.t_cleanup_actions[1], NOSLEEP, RMDIR, 2, (void*)DIR1, (void*)NULL);
910 execute_test(&test);
911
912 init_test(&test, "2.1.12: write to a FIFO", FILE1, 1, 1, NOTE_WRITE, YES_EVENT);
913 test.t_known_failure = 1;
914 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKFIFO, 2, (void*)FILE1, (void*)NULL);
915 test.t_file_is_fifo = 1;
916 init_action(&test.t_helpthreadact, SLEEP, WRITEFD, 0);
917 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, (void*)NULL);
918 execute_test(&test);
919
920
921 makepath(pathbuf, DIR1, FILE1);
922 init_test(&test, "2.1.13: delete a symlink in a dir", DIR1, 2, 1, NOTE_WRITE, YES_EVENT);
923 test.t_known_failure = 1;
924 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
925 init_action(&(test.t_prep_actions[1]), NOSLEEP, SYMLINK, 2, (void*)DOTDOT, (void*)pathbuf);
926 init_action(&test.t_helpthreadact, SLEEP, UNLINK, 2, (void*)pathbuf, (void*)FILE1);
927 init_action(&test.t_cleanup_actions[0], NOSLEEP, RMDIR, 2, (void*)DIR1, (void*)NULL);
928 execute_test(&test);
929
930 /* exchangedata is not supported on APFS volumes */
931 if (!path_on_apfs(PDIR)) {
932 /* This actually should not generate an event, though it's in this section */
933 makepath(pathbuf, DIR1, FILE1);
934 makepath(otherpathbuf, DIR1, FILE2);
935 init_test(&test, "2.1.14: exchangedata two files in a dir", DIR1, 3, 3, NOTE_WRITE, NO_EVENT);
936 test.t_known_failure = 1;
937 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
938 init_action(&(test.t_prep_actions[1]), NOSLEEP, CREAT, 2, (void*)pathbuf, (void*)NULL);
939 init_action(&(test.t_prep_actions[2]), NOSLEEP, CREAT, 2, (void*)otherpathbuf, (void*)NULL);
940 init_action(&test.t_helpthreadact, SLEEP, EXCHANGEDATA, 2, (void*)pathbuf, (void*)otherpathbuf);
941 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)pathbuf, (void*)NULL);
942 init_action(&test.t_cleanup_actions[1], NOSLEEP, UNLINK, 2, (void*)otherpathbuf, (void*)NULL);
943 init_action(&test.t_cleanup_actions[2], NOSLEEP, RMDIR, 2, (void*)DIR1, (void*)NULL);
944 execute_test(&test);
945 }
946
947 init_test(&test, "2.1.15: Change a file with mmap()", FILE1, 1, 1, NOTE_WRITE, YES_EVENT);
948 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
949 init_action(&test.t_helpthreadact, SLEEP, MMAP, 2, (void*)FILE1, (void*)1); /* 1 -> "modify it"*/
950 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, (void*)NULL);
951 execute_test(&test);
952
953 /*================= no-event tests ==================*/
954 init_test(&test, "2.2.1: just open and close existing file", FILE1, 1, 1, NOTE_WRITE, NO_EVENT);
955 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
956 init_action(&test.t_helpthreadact, SLEEP, OPEN, 2, (void*)FILE1, NULL);
957 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, (void*)NULL);
958 execute_test(&test);
959
960 init_test(&test, "2.2.2: read from existing file", FILE1, 1, 1, NOTE_WRITE, NO_EVENT);
961 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
962 init_action(&test.t_helpthreadact, SLEEP, READ, 2, (void*)FILE1, NULL);
963 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, (void*)NULL);
964 execute_test(&test);
965
966 init_test(&test, "2.2.3: rename existing file", FILE1, 1, 1, NOTE_WRITE, NO_EVENT);
967 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
968 init_action(&test.t_helpthreadact, SLEEP, RENAME, 2, (void*)FILE1, (void*)FILE2);
969 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE2, (void*)NULL);
970 execute_test(&test);
971
972 init_test(&test, "2.2.4: just open and close dir", DIR1, 1, 1, NOTE_WRITE, NO_EVENT);
973 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
974 init_action(&test.t_helpthreadact, SLEEP, OPEN, 2, (void*)DIR1, (void*)NULL);
975 init_action(&test.t_cleanup_actions[0], NOSLEEP, RMDIR, 2, (void*)DIR1, (void*)NULL);
976 execute_test(&test);
977
978 /* There are no tests 2.2.5 or 2.2.6 */
979
980 init_test(&test, "2.2.7: rename a dir", DIR1, 1, 1, NOTE_WRITE, NO_EVENT);
981 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
982 init_action(&test.t_helpthreadact, SLEEP, RENAME, 2, (void*)DIR1, (void*)DIR2);
983 init_action(&test.t_cleanup_actions[0], NOSLEEP, RMDIR, 2, (void*)DIR2, (void*)NULL);
984 execute_test(&test);
985
986 init_test(&test, "2.2.8: rename a fifo", FILE1, 1, 1, NOTE_WRITE, NO_EVENT);
987 test.t_file_is_fifo = 1;
988 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKFIFO, 2, (void*)FILE1, (void*)NULL);
989 init_action(&test.t_helpthreadact, SLEEP, RENAME, 2, (void*)FILE1, (void*)FILE2);
990 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE2, (void*)NULL);
991 execute_test(&test);
992
993 init_test(&test, "2.2.9: unlink a fifo", FILE1, 1, 0, NOTE_WRITE, NO_EVENT);
994 test.t_file_is_fifo = 1;
995 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKFIFO, 2, (void*)FILE1, (void*)NULL);
996 init_action(&test.t_helpthreadact, SLEEP, UNLINK, 1, (void*)FILE1);
997 execute_test(&test);
998
999 init_test(&test, "2.2.10: chmod a file", FILE1, 1, 1, NOTE_WRITE, NO_EVENT);
1000 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1001 init_action(&test.t_helpthreadact, SLEEP, CHMOD, 2, (void*)FILE1, (void*)0700);
1002 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, (void*)NULL);
1003 execute_test(&test);
1004
1005 struct passwd *pwd = getpwnam("local");
1006
1007 if (pwd != NULL) {
1008 init_test(&test, "2.2.11: chown a file", FILE1, 2, 1, NOTE_WRITE, NO_EVENT);
1009 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1010 init_action(&test.t_prep_actions[1], NOSLEEP, CHOWN, 3, (void*)FILE1, (void*)pwd->pw_uid, (void*)pwd->pw_gid);
1011 init_action(&test.t_helpthreadact, SLEEP, CHOWN, 3, (void*)FILE1, (void*)getuid(), (void*)getgid());
1012 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, (void*)NULL);
1013 execute_test(&test);
1014 }
1015
1016 init_test(&test, "2.2.12: chmod a dir", DIR1, 1, 1, NOTE_WRITE, NO_EVENT);
1017 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1018 init_action(&test.t_helpthreadact, SLEEP, CHMOD, 2, (void*)DIR1, (void*)0700);
1019 init_action(&test.t_cleanup_actions[0], NOSLEEP, RMDIR, 2, (void*)DIR1, (void*)NULL);
1020 execute_test(&test);
1021
1022 if (pwd != NULL) {
1023 init_test(&test, "2.2.13: chown a dir", DIR1, 2, 1, NOTE_WRITE, NO_EVENT);
1024 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1025 init_action(&test.t_prep_actions[1], NOSLEEP, CHOWN, 3, (void*)DIR1, (void*)pwd->pw_uid, (void*)pwd->pw_gid);
1026 init_action(&test.t_helpthreadact, SLEEP, CHOWN, 3, (void*)DIR1, (void*)getuid(), (void*)getgid());
1027 init_action(&test.t_cleanup_actions[0], NOSLEEP, RMDIR, 2, (void*)DIR1, (void*)NULL);
1028 execute_test(&test);
1029 }
1030
1031 T_LOG("MMAP will never give a notification on HFS.\n");
1032 init_test(&test, "2.1.14: mmap() a file but do not change it", FILE1, 1, 1, NOTE_WRITE, NO_EVENT);
1033 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1034 init_action(&test.t_helpthreadact, SLEEP, MMAP, 2, (void*)FILE1, (void*)0);
1035 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, (void*)NULL);
1036 execute_test(&test);
1037 }
1038
1039 void
1040 run_note_extend_tests()
1041 {
1042 test_t test;
1043 char pathbuf[50];
1044
1045 T_LOG("THESE TESTS MAY FAIL ON HFS\n");
1046
1047 init_test(&test, "3.1.1: write beyond the end of a file", FILE1, 1, 1, NOTE_EXTEND, YES_EVENT);
1048 test.t_nondeterministic = 1;
1049 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1050 init_action(&test.t_helpthreadact, SLEEP, WRITE, 2, (void*)FILE1, (void*)NULL);
1051 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, (void*)NULL);
1052 execute_test(&test);
1053
1054 /*
1055 * We won't concern ourselves with lengthening directories: commenting these out
1056 *
1057 *
1058 * makepath(pathbuf, DIR1, FILE1);
1059 * init_test(&test, "3.1.2: add a file to a directory with creat()", DIR1, 1, 2, NOTE_EXTEND, YES_EVENT);
1060 * init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1061 * init_action(&test.t_helpthreadact, SLEEP, CREAT, 2, (void*)pathbuf, (void*)NULL);
1062 * init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)pathbuf, (void*)NULL);
1063 * init_action(&test.t_cleanup_actions[1], NOSLEEP, RMDIR, 2, (void*)DIR1, (void*)NULL);
1064 * execute_test(&test);
1065 *
1066 * makepath(pathbuf, DIR1, FILE1);
1067 * init_test(&test, "3.1.3: add a file to a directory with open()", DIR1, 1, 2, NOTE_EXTEND, YES_EVENT);
1068 * init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1069 * init_action(&test.t_helpthreadact, SLEEP, CREAT, 2, (void*)pathbuf, (void*)NULL);
1070 * init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)pathbuf, (void*)NULL);
1071 * init_action(&test.t_cleanup_actions[1], NOSLEEP, RMDIR, 2, (void*)DIR1, (void*)NULL);
1072 * execute_test(&test);
1073 *
1074 * makepath(pathbuf, DIR1, FILE1);
1075 * init_test(&test, "3.1.4: add a file to a directory with rename()", DIR1, 2, 2, NOTE_EXTEND, YES_EVENT);
1076 * init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1077 * init_action(&(test.t_prep_actions[1]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1078 * init_action(&test.t_helpthreadact, SLEEP, RENAME, 2, (void*)FILE1, (void*)pathbuf);
1079 * init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)pathbuf, (void*)NULL);
1080 * init_action(&test.t_cleanup_actions[1], NOSLEEP, RMDIR, 2, (void*)DIR1, (void*)NULL);
1081 * execute_test(&test);
1082 */
1083
1084 /* 3.1.5: a placeholder for a potential kernel test */
1085 /*
1086 * makepath(pathbuf, DIR1, DIR2);
1087 * init_test(&test, "3.1.6: add a file to a directory with mkdir()", DIR1, 1, 2, NOTE_EXTEND, YES_EVENT);
1088 * init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1089 * init_action(&test.t_helpthreadact, SLEEP, MKDIR, 2, (void*)pathbuf, (void*)NULL);
1090 * init_action(&test.t_cleanup_actions[0], NOSLEEP, RMDIR, 2, (void*)pathbuf, (void*)NULL);
1091 * init_action(&test.t_cleanup_actions[1], NOSLEEP, RMDIR, 2, (void*)DIR1, (void*)NULL);
1092 * execute_test(&test);
1093 */
1094 init_test(&test, "3.1.7: lengthen a file with truncate()", FILE1, 1, 1, NOTE_EXTEND, YES_EVENT);
1095 test.t_nondeterministic = 1;
1096 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1097 init_action(&test.t_helpthreadact, SLEEP, LENGTHEN, 2, FILE1, (void*)NULL);
1098 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, (void*)NULL);
1099 execute_test(&test);
1100
1101
1102 /** ========== NO EVENT SECTION ============== **/
1103 init_test(&test, "3.2.1: setxattr() a file", FILE1, 1, 1, NOTE_EXTEND, NO_EVENT);
1104 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1105 init_action(&test.t_helpthreadact, SLEEP, SETXATTR, 2, FILE1, (void*)NULL);
1106 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, (void*)NULL);
1107 execute_test(&test);
1108
1109 init_test(&test, "3.2.2: chmod a file", FILE1, 1, 1, NOTE_EXTEND, NO_EVENT);
1110 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1111 init_action(&test.t_helpthreadact, SLEEP, CHMOD, 2, (void*)FILE1, (void*)0700);
1112 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, (void*)NULL);
1113 execute_test(&test);
1114
1115 struct passwd *pwd = getpwnam("local");
1116 if (pwd != NULL) {
1117 init_test(&test, "3.2.3: chown a file", FILE1, 2, 1, NOTE_EXTEND, NO_EVENT);
1118 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1119 init_action(&test.t_prep_actions[1], NOSLEEP, CHOWN, 3, (void*)FILE1, (void*)pwd->pw_uid, (void*)pwd->pw_gid);
1120 init_action(&test.t_helpthreadact, SLEEP, CHOWN, 3, (void*)FILE1, (void*)getuid(), (void*)getgid());
1121 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, (void*)NULL);
1122 execute_test(&test);
1123 } else {
1124 T_LOG("Couldn't getpwnam for user \"local\"\n");
1125 }
1126
1127 init_test(&test, "3.2.4: chmod a dir", DIR1, 1, 1, NOTE_EXTEND, NO_EVENT);
1128 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1129 init_action(&test.t_helpthreadact, SLEEP, CHMOD, 2, (void*)DIR1, (void*)0700);
1130 init_action(&test.t_cleanup_actions[0], NOSLEEP, RMDIR, 2, (void*)DIR1, (void*)NULL);
1131 execute_test(&test);
1132
1133 if (pwd != NULL) {
1134 init_test(&test, "3.2.5: chown a dir", DIR1, 2, 1, NOTE_EXTEND, NO_EVENT);
1135 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1136 init_action(&test.t_prep_actions[1], NOSLEEP, CHOWN, 3, (void*)DIR1, (void*)pwd->pw_uid, (void*)pwd->pw_gid);
1137 init_action(&test.t_helpthreadact, SLEEP, CHOWN, 3, (void*)DIR1, (void*)getuid(), (void*)getgid());
1138 init_action(&test.t_cleanup_actions[0], NOSLEEP, RMDIR, 2, (void*)DIR1, (void*)NULL);
1139 execute_test(&test);
1140 }
1141
1142 init_test(&test, "3.2.6: TRUNC a file with truncate()", FILE1, 1, 1, NOTE_EXTEND, NO_EVENT);
1143 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1144 init_action(&test.t_helpthreadact, SLEEP, TRUNC, 2, FILE1, (void*)NULL);
1145 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, (void*)NULL);
1146 execute_test(&test);
1147 }
1148
1149 void
1150 run_note_attrib_tests()
1151 {
1152 test_t test;
1153 char pathbuf[50];
1154
1155 init_test(&test, "4.1.1: chmod a file", FILE1, 1, 1, NOTE_ATTRIB, YES_EVENT);
1156 test.t_nondeterministic = 1;
1157 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1158 init_action(&test.t_helpthreadact, SLEEP, CHMOD, 2, FILE1, (void*)0700);
1159 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, (void*)NULL);
1160 execute_test(&test);
1161
1162 struct passwd *pwd = getpwnam("local");
1163 if (pwd != NULL) {
1164 init_test(&test, "4.1.2: chown a file", FILE1, 2, 1, NOTE_ATTRIB, YES_EVENT);
1165 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1166 init_action(&(test.t_prep_actions[1]), NOSLEEP, CHOWN, 3, (void*)FILE1, (void*)pwd->pw_uid, (void*)pwd->pw_gid);
1167 init_action(&test.t_helpthreadact, SLEEP, CHOWN, 3, FILE1, (void*)getuid(), (void*)pwd->pw_gid);
1168 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, (void*)NULL);
1169 execute_test(&test);
1170 }
1171
1172 init_test(&test, "4.1.3: chmod a dir", DIR1, 1, 1, NOTE_ATTRIB, YES_EVENT);
1173 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1174 init_action(&(test.t_helpthreadact), SLEEP, CHMOD, 2, (void*)DIR1, (void*)0700);
1175 init_action(&test.t_cleanup_actions[0], NOSLEEP, RMDIR, 2, (void*)DIR1, (void*)NULL);
1176 execute_test(&test);
1177
1178 if (pwd != NULL) {
1179 init_test(&test, "4.1.4: chown a dir", DIR1, 2, 1, NOTE_ATTRIB, YES_EVENT);
1180 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1181 init_action(&(test.t_prep_actions[1]), NOSLEEP, CHOWN, 3, (void*)DIR1, (void*) pwd->pw_uid, (void*)pwd->pw_gid);
1182 init_action(&test.t_helpthreadact, SLEEP, CHOWN, 3, DIR1, (void*)getuid(), (void*)getgid());
1183 init_action(&test.t_cleanup_actions[0], NOSLEEP, RMDIR, 2, (void*)DIR1, (void*)NULL);
1184 execute_test(&test);
1185 }
1186
1187 init_test(&test, "4.1.5: setxattr on a file", FILE1, 1, 1, NOTE_ATTRIB, YES_EVENT);
1188 test.t_nondeterministic = 1;
1189 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1190 init_action(&test.t_helpthreadact, SLEEP, SETXATTR, 2, (void*)FILE1, (void*)NULL);
1191 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, (void*)NULL);
1192 execute_test(&test);
1193
1194 init_test(&test, "4.1.6: setxattr on a dir", DIR1, 1, 1, NOTE_ATTRIB, YES_EVENT);
1195 test.t_nondeterministic = 1;
1196 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1197 init_action(&test.t_helpthreadact, SLEEP, SETXATTR, 2, (void*)DIR1, (void*)NULL);
1198 init_action(&test.t_cleanup_actions[0], NOSLEEP, RMDIR, 2, (void*)DIR1, (void*)NULL);
1199 execute_test(&test);
1200
1201 /* exchangedata is not supported on APFS volumes */
1202 if (!path_on_apfs(PDIR)) {
1203 init_test(&test, "4.1.7: exchangedata", FILE1, 2, 2, NOTE_ATTRIB, YES_EVENT);
1204 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1205 init_action(&(test.t_prep_actions[1]), NOSLEEP, CREAT, 2, (void*)FILE2, (void*)NULL);
1206 init_action(&test.t_helpthreadact, SLEEP, EXCHANGEDATA, 2, (void*)FILE1, (void*)FILE2);
1207 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, (void*)NULL);
1208 init_action(&test.t_cleanup_actions[1], NOSLEEP, UNLINK, 2, (void*)FILE2, (void*)NULL);
1209 execute_test(&test);
1210 }
1211
1212 init_test(&test, "4.1.8: utimes on a file", FILE1, 1, 1, NOTE_ATTRIB, YES_EVENT);
1213 test.t_nondeterministic = 1;
1214 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1215 init_action(&test.t_helpthreadact, SLEEP, UTIMES, 2, (void*)FILE1, (void*)NULL);
1216 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, (void*)NULL);
1217 execute_test(&test);
1218
1219 init_test(&test, "4.1.9: utimes on a dir", DIR1, 1, 1, NOTE_ATTRIB, YES_EVENT);
1220 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1221 init_action(&test.t_helpthreadact, SLEEP, UTIMES, 2, (void*)DIR1, (void*)NULL);
1222 init_action(&test.t_cleanup_actions[0], NOSLEEP, RMDIR, 2, (void*)DIR1, (void*)NULL);
1223 execute_test(&test);
1224
1225
1226 /* ====== NO EVENT TESTS ========== */
1227
1228 init_test(&test, "4.2.1: rename a file", FILE1, 1, 1, NOTE_ATTRIB, NO_EVENT);
1229 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1230 init_action(&test.t_helpthreadact, SLEEP, RENAME, 2, (void*)FILE1, (void*)FILE2);
1231 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE2, NULL);
1232 execute_test(&test);
1233
1234 init_test(&test, "4.2.2: open (do not change) a file", FILE1, 1, 1, NOTE_ATTRIB, NO_EVENT);
1235 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1236 init_action(&test.t_helpthreadact, SLEEP, OPEN, 2, (void*)FILE1, NULL);
1237 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, NULL);
1238 execute_test(&test);
1239
1240 init_test(&test, "4.2.3: stat a file", FILE1, 1, 1, NOTE_ATTRIB, NO_EVENT);
1241 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1242 init_action(&test.t_helpthreadact, SLEEP, STAT, 2, (void*)FILE1, NULL);
1243 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, NULL);
1244 execute_test(&test);
1245
1246 init_test(&test, "4.2.4: unlink a file", FILE1, 1, 0, NOTE_ATTRIB, NO_EVENT);
1247 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1248 init_action(&test.t_helpthreadact, SLEEP, UNLINK, 2, (void*)FILE1, NULL);
1249 execute_test(&test);
1250
1251 init_test(&test, "4.2.5: write to a file", FILE1, 1, 1, NOTE_ATTRIB, NO_EVENT);
1252 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1253 init_action(&test.t_helpthreadact, SLEEP, WRITE, 2, (void*)FILE1, (void*)NULL);
1254 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, (void*)NULL);
1255 execute_test(&test);
1256
1257 T_LOG("EXPECT SPURIOUS NOTE_ATTRIB EVENTS FROM DIRECTORY OPERATIONS on HFS.\n");
1258 init_test(&test, "4.2.6: add a file to a directory with creat()", DIR1, 1, 2, NOTE_ATTRIB, NO_EVENT);
1259 test.t_known_failure = 1;
1260 makepath(pathbuf, DIR1, FILE1);
1261 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1262 init_action(&test.t_helpthreadact, SLEEP, CREAT, 2, (void*)pathbuf, (void*)NULL);
1263 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)pathbuf, (void*)NULL);
1264 init_action(&test.t_cleanup_actions[1], NOSLEEP, RMDIR, 2, (void*)DIR1, (void*)NULL);
1265 execute_test(&test);
1266
1267 init_test(&test, "4.2.7: mkdir in a dir", DIR1, 1, 2, NOTE_ATTRIB, NO_EVENT);
1268 test.t_known_failure = 1;
1269 makepath(pathbuf, DIR1, DIR2);
1270 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1271 init_action(&test.t_helpthreadact, SLEEP, MKDIR, 2, (void*)pathbuf, (void*)NULL);
1272 init_action(&test.t_cleanup_actions[0], NOSLEEP, RMDIR, 2, (void*)pathbuf, (void*)NULL);
1273 init_action(&test.t_cleanup_actions[1], NOSLEEP, RMDIR, 2, (void*)DIR1, (void*)NULL);
1274 execute_test(&test);
1275
1276 init_test(&test, "4.2.8: add a symlink to a directory", DIR1, 1, 2, NOTE_ATTRIB, NO_EVENT);
1277 test.t_known_failure = 1;
1278 makepath(pathbuf, DIR1, FILE1);
1279 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1280 init_action(&test.t_helpthreadact, SLEEP, SYMLINK, 2, (void*)DOTDOT, (void*)pathbuf);
1281 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)pathbuf, (void*)NULL);
1282 init_action(&test.t_cleanup_actions[1], NOSLEEP, RMDIR, 2, (void*)DIR1, (void*)NULL);
1283 execute_test(&test);
1284
1285 init_test(&test, "4.2.9: rename into a dir()", DIR1, 2, 2, NOTE_ATTRIB, NO_EVENT);
1286 test.t_known_failure = 1;
1287 makepath(pathbuf, DIR1, FILE1);
1288 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1289 init_action(&(test.t_prep_actions[1]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1290 init_action(&test.t_helpthreadact, SLEEP, RENAME, 2, (void*)FILE1, (void*)pathbuf);
1291 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)pathbuf, (void*)NULL);
1292 init_action(&test.t_cleanup_actions[1], NOSLEEP, RMDIR, 2, (void*)DIR1, (void*)NULL);
1293 execute_test(&test);
1294
1295 init_test(&test, "4.2.10: unlink() file from dir", DIR1, 2, 1, NOTE_ATTRIB, NO_EVENT);
1296 test.t_known_failure = 1;
1297 makepath(pathbuf, DIR1, FILE1);
1298 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1299 init_action(&(test.t_prep_actions[1]), NOSLEEP, CREAT, 2, (void*)pathbuf, (void*)NULL);
1300 init_action(&test.t_helpthreadact, SLEEP, UNLINK, 2, (void*)pathbuf, (void*)NULL);
1301 init_action(&test.t_cleanup_actions[0], NOSLEEP, RMDIR, 2, (void*)DIR1, (void*)NULL);
1302 execute_test(&test);
1303
1304 init_test(&test, "4.2.11: mkfifo in a directory", DIR1, 1, 2, NOTE_ATTRIB, NO_EVENT);
1305 test.t_known_failure = 1;
1306 makepath(pathbuf, DIR1, FILE1);
1307 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1308 init_action(&test.t_helpthreadact, SLEEP, MKFIFO, 1, (void*)pathbuf);
1309 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)pathbuf, (void*)NULL);
1310 init_action(&test.t_cleanup_actions[1], NOSLEEP, RMDIR, 2, (void*)DIR1, (void*)NULL);
1311 execute_test(&test);
1312 }
1313
1314
1315 void
1316 run_note_link_tests()
1317 {
1318 test_t test;
1319 char pathbuf[50];
1320 char otherpathbuf[50];
1321
1322 T_LOG("HFS DOES NOT HANDLE UNLINK CORRECTLY...\n");
1323 init_test(&test, "5.1.1: unlink() a file", FILE1, 1, 0, NOTE_LINK, YES_EVENT);
1324 test.t_nondeterministic = 1;
1325 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1326 init_action(&test.t_helpthreadact, SLEEP, UNLINK, 2, (void*)FILE1, (void*)NULL);
1327 execute_test(&test);
1328
1329
1330 init_test(&test, "5.1.1.5: link A to B, watch A, remove B", FILE1, 2, 1, NOTE_LINK, YES_EVENT);
1331 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1332 init_action(&(test.t_prep_actions[1]), NOSLEEP, HARDLINK, 2, (void*)FILE1, (void*)FILE2);
1333 init_action(&test.t_helpthreadact, SLEEP, UNLINK, 2, (void*)FILE2, (void*)NULL);
1334 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, NULL);
1335 execute_test(&test);
1336
1337 init_test(&test, "5.1.2: link() to a file", FILE1, 1, 2, NOTE_LINK, YES_EVENT);
1338 #if TARGET_OS_WATCH
1339 test.t_nondeterministic = 1;
1340 #endif
1341 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1342 init_action(&test.t_helpthreadact, SLEEP, HARDLINK, 2, (void*)FILE1, (void*)FILE2);
1343 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, NULL);
1344 init_action(&test.t_cleanup_actions[1], NOSLEEP, UNLINK, 2, (void*)FILE2, NULL);
1345 execute_test(&test);
1346
1347 makepath(pathbuf, DIR1, DIR2);
1348 init_test(&test, "5.1.3: make one dir in another", DIR1, 1, 2, NOTE_LINK, YES_EVENT);
1349 test.t_known_failure = 1;
1350 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1351 init_action(&test.t_helpthreadact, SLEEP, MKDIR, 2, (void*)pathbuf, (void*)NULL);
1352 init_action(&test.t_cleanup_actions[0], NOSLEEP, RMDIR, 2, (void*)pathbuf, NULL);
1353 init_action(&test.t_cleanup_actions[1], NOSLEEP, RMDIR, 2, (void*)DIR1, NULL);
1354 execute_test(&test);
1355
1356 makepath(pathbuf, DIR1, DIR2);
1357 init_test(&test, "5.1.4: rmdir a dir from within another", DIR1, 2, 1, NOTE_LINK, YES_EVENT);
1358 test.t_known_failure = 1;
1359 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1360 init_action(&(test.t_prep_actions[1]), NOSLEEP, MKDIR, 2, (void*)pathbuf, (void*)NULL);
1361 init_action(&test.t_helpthreadact, SLEEP, RMDIR, 2, (void*)pathbuf, (void*)NULL);
1362 init_action(&test.t_cleanup_actions[0], NOSLEEP, RMDIR, 2, (void*)DIR1, NULL);
1363 execute_test(&test);
1364
1365 makepath(pathbuf, DIR1, DIR2);
1366 makepath(otherpathbuf, DIR1, DIR1);
1367 init_test(&test, "5.1.5: rename dir A over dir B inside dir C", DIR1, 3, 2, NOTE_LINK, YES_EVENT);
1368 test.t_known_failure = 1;
1369 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1370 init_action(&(test.t_prep_actions[1]), NOSLEEP, MKDIR, 2, (void*)pathbuf, (void*)NULL);
1371 init_action(&(test.t_prep_actions[2]), NOSLEEP, MKDIR, 2, (void*)otherpathbuf, (void*)NULL);
1372 init_action(&test.t_helpthreadact, SLEEP, RENAME, 2, (void*)pathbuf, (void*)otherpathbuf);
1373 init_action(&test.t_cleanup_actions[0], NOSLEEP, RMDIR, 2, (void*)otherpathbuf, NULL);
1374 init_action(&test.t_cleanup_actions[1], NOSLEEP, RMDIR, 2, (void*)DIR1, NULL);
1375 execute_test(&test);
1376
1377 T_LOG("HFS bypasses hfs_makenode to create in target, so misses knote.\n");
1378 makepath(pathbuf, DIR1, DIR2);
1379 init_test(&test, "5.1.6: rename one dir into another", DIR1, 2, 2, NOTE_LINK, YES_EVENT);
1380 test.t_known_failure = 1;
1381 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1382 init_action(&(test.t_prep_actions[1]), NOSLEEP, MKDIR, 2, (void*)DIR2, (void*)NULL);
1383 init_action(&test.t_helpthreadact, SLEEP, RENAME, 2, (void*)DIR2, (void*)pathbuf);
1384 init_action(&test.t_cleanup_actions[0], NOSLEEP, RMDIR, 2, (void*)pathbuf, NULL);
1385 init_action(&test.t_cleanup_actions[1], NOSLEEP, RMDIR, 2, (void*)DIR1, NULL);
1386 execute_test(&test);
1387
1388 T_LOG("HFS bypasses hfs_removedir to remove from source, so misses knote.\n");
1389 makepath(pathbuf, DIR1, DIR2);
1390 init_test(&test, "5.1.7: rename one dir out of another", DIR1, 2, 2, NOTE_LINK, YES_EVENT);
1391 test.t_known_failure = 1;
1392 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1393 init_action(&(test.t_prep_actions[1]), NOSLEEP, MKDIR, 2, (void*)pathbuf, (void*)NULL);
1394 init_action(&test.t_helpthreadact, SLEEP, RENAME, 2, (void*)pathbuf, (void*)DIR2);
1395 init_action(&test.t_cleanup_actions[0], NOSLEEP, RMDIR, 2, (void*)DIR2, NULL);
1396 init_action(&test.t_cleanup_actions[1], NOSLEEP, RMDIR, 2, (void*)DIR1, NULL);
1397 execute_test(&test);
1398
1399 init_test(&test, "5.1.8: rmdir a dir", DIR1, 1, 0, NOTE_LINK, YES_EVENT);
1400 test.t_nondeterministic = 1;
1401 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1402 init_action(&test.t_helpthreadact, SLEEP, RMDIR, 2, (void*)DIR1, (void*)NULL);
1403 execute_test(&test);
1404
1405 /* ============= NO EVENT SECTION ============== */
1406 makepath(pathbuf, DIR1, FILE1);
1407 init_test(&test, "5.2.1: make a file in a dir", DIR1, 1, 2, NOTE_LINK, NO_EVENT);
1408 test.t_known_failure = 1;
1409 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1410 init_action(&test.t_helpthreadact, SLEEP, CREAT, 2, (void*)pathbuf, (void*)NULL);
1411 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)pathbuf, NULL);
1412 init_action(&test.t_cleanup_actions[1], NOSLEEP, RMDIR, 2, (void*)DIR1, NULL);
1413 execute_test(&test);
1414
1415 makepath(pathbuf, DIR1, FILE1);
1416 init_test(&test, "5.2.2: unlink a file in a dir", DIR1, 2, 1, NOTE_LINK, NO_EVENT);
1417 test.t_known_failure = 1;
1418 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1419 init_action(&(test.t_prep_actions[1]), NOSLEEP, CREAT, 2, (void*)pathbuf, (void*)NULL);
1420 init_action(&test.t_helpthreadact, SLEEP, UNLINK, 2, (void*)pathbuf, (void*)NULL);
1421 init_action(&test.t_cleanup_actions[0], NOSLEEP, RMDIR, 2, (void*)DIR1, NULL);
1422 execute_test(&test);
1423
1424 makepath(pathbuf, DIR1, FILE1);
1425 makepath(otherpathbuf, DIR1, FILE2);
1426 init_test(&test, "5.2.3: rename a file within a dir", DIR1, 2, 2, NOTE_LINK, NO_EVENT);
1427 test.t_known_failure = 1;
1428 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1429 init_action(&(test.t_prep_actions[1]), NOSLEEP, CREAT, 2, (void*)pathbuf, (void*)NULL);
1430 init_action(&test.t_helpthreadact, SLEEP, RENAME, 2, (void*)pathbuf, (void*)otherpathbuf);
1431 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)otherpathbuf, NULL);
1432 init_action(&test.t_cleanup_actions[1], NOSLEEP, RMDIR, 2, (void*)DIR1, NULL);
1433 execute_test(&test);
1434
1435 makepath(pathbuf, DIR1, FILE1);
1436 init_test(&test, "5.2.4: rename a file into a dir", DIR1, 2, 2, NOTE_LINK, NO_EVENT);
1437 test.t_known_failure = 1;
1438 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1439 init_action(&(test.t_prep_actions[1]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1440 init_action(&test.t_helpthreadact, SLEEP, RENAME, 2, (void*)FILE1, (void*)pathbuf);
1441 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)pathbuf, NULL);
1442 init_action(&test.t_cleanup_actions[1], NOSLEEP, RMDIR, 2, (void*)DIR1, NULL);
1443 execute_test(&test);
1444
1445 makepath(pathbuf, DIR1, FILE1);
1446 init_test(&test, "5.2.5: make a symlink in a dir", DIR1, 1, 2, NOTE_LINK, NO_EVENT);
1447 test.t_known_failure = 1;
1448 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1449 init_action(&test.t_helpthreadact, SLEEP, SYMLINK, 2, (void*)DOTDOT, (void*)pathbuf);
1450 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)pathbuf, NULL);
1451 init_action(&test.t_cleanup_actions[1], NOSLEEP, RMDIR, 2, (void*)DIR1, NULL);
1452 execute_test(&test);
1453
1454 init_test(&test, "5.2.6: make a symlink to a dir", DIR1, 1, 2, NOTE_LINK, NO_EVENT);
1455 test.t_known_failure = 1;
1456 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1457 init_action(&test.t_helpthreadact, SLEEP, SYMLINK, 2, (void*)DIR1, (void*)FILE1);
1458 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, NULL);
1459 init_action(&test.t_cleanup_actions[1], NOSLEEP, RMDIR, 2, (void*)DIR1, NULL);
1460 execute_test(&test);
1461
1462 init_test(&test, "5.2.7: make a symlink to a file", FILE1, 1, 2, NOTE_LINK, NO_EVENT);
1463 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1464 init_action(&test.t_helpthreadact, SLEEP, SYMLINK, 2, (void*)FILE1, (void*)FILE2);
1465 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE2, NULL);
1466 init_action(&test.t_cleanup_actions[1], NOSLEEP, UNLINK, 2, (void*)FILE1, NULL);
1467 execute_test(&test);
1468 }
1469
1470 void
1471 run_note_rename_tests()
1472 {
1473 test_t test;
1474
1475 init_test(&test, "6.1.1: rename a file", FILE1, 1, 1, NOTE_RENAME, YES_EVENT);
1476 test.t_nondeterministic = 1;
1477 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1478 init_action(&test.t_helpthreadact, SLEEP, RENAME, 2, (void*)FILE1, (void*)FILE2);
1479 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE2, NULL);
1480 execute_test(&test);
1481
1482 init_test(&test, "6.1.2: rename a dir", DIR1, 1, 1, NOTE_RENAME, YES_EVENT);
1483 test.t_nondeterministic = 1;
1484 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1485 init_action(&test.t_helpthreadact, SLEEP, RENAME, 2, (void*)DIR1, (void*)DIR2);
1486 init_action(&test.t_cleanup_actions[0], NOSLEEP, RMDIR, 2, (void*)DIR2, NULL);
1487 execute_test(&test);
1488
1489 init_test(&test, "6.1.3: rename one file over another", FILE1, 2, 1, NOTE_RENAME, YES_EVENT);
1490 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1491 init_action(&(test.t_prep_actions[1]), NOSLEEP, CREAT, 2, (void*)FILE2, (void*)NULL);
1492 init_action(&test.t_helpthreadact, SLEEP, RENAME, 2, (void*)FILE1, (void*)FILE2);
1493 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE2, NULL);
1494 execute_test(&test);
1495
1496 init_test(&test, "6.1.4: rename one dir over another", DIR1, 2, 1, NOTE_RENAME, YES_EVENT);
1497 test.t_nondeterministic = 1;
1498 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1499 init_action(&(test.t_prep_actions[1]), NOSLEEP, MKDIR, 2, (void*)DIR2, (void*)NULL);
1500 init_action(&test.t_helpthreadact, SLEEP, RENAME, 2, (void*)DIR1, (void*)DIR2);
1501 init_action(&test.t_cleanup_actions[0], NOSLEEP, RMDIR, 2, (void*)DIR2, NULL);
1502 execute_test(&test);
1503
1504 /* ========= NO EVENT SECTION =========== */
1505
1506 init_test(&test, "6.2.1: unlink a file", FILE1, 1, 0, NOTE_RENAME, NO_EVENT);
1507 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1508 init_action(&test.t_helpthreadact, SLEEP, UNLINK, 2, (void*)FILE1, NULL);
1509 execute_test(&test);
1510
1511 init_test(&test, "6.2.2: rmdir a dir", DIR1, 1, 0, NOTE_RENAME, NO_EVENT);
1512 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1513 init_action(&test.t_helpthreadact, SLEEP, RMDIR, 2, (void*)DIR1, NULL);
1514 execute_test(&test);
1515
1516 init_test(&test, "6.2.3: link() to a file", FILE1, 1, 2, NOTE_RENAME, NO_EVENT);
1517 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1518 init_action(&test.t_helpthreadact, SLEEP, HARDLINK, 2, (void*)FILE1, (void*)FILE2);
1519 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, NULL);
1520 init_action(&test.t_cleanup_actions[1], NOSLEEP, UNLINK, 2, (void*)FILE2, NULL);
1521 execute_test(&test);
1522
1523 init_test(&test, "6.2.4: rename one file over another: watch deceased",
1524 FILE2, 2, 1, NOTE_RENAME, NO_EVENT);
1525 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1526 init_action(&(test.t_prep_actions[1]), NOSLEEP, CREAT, 2, (void*)FILE2, (void*)NULL);
1527 init_action(&test.t_helpthreadact, SLEEP, RENAME, 2, (void*)FILE1, (void*)FILE2);
1528 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE2, NULL);
1529 execute_test(&test);
1530
1531 init_test(&test, "6.2.5: rename one dir over another: watch deceased",
1532 DIR2, 2, 1, NOTE_RENAME, NO_EVENT);
1533 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1534 init_action(&(test.t_prep_actions[1]), NOSLEEP, MKDIR, 2, (void*)DIR2, (void*)NULL);
1535 init_action(&test.t_helpthreadact, SLEEP, RENAME, 2, (void*)DIR1, (void*)DIR2);
1536 init_action(&test.t_cleanup_actions[0], NOSLEEP, RMDIR, 2, (void*)DIR2, NULL);
1537 execute_test(&test);
1538
1539 init_test(&test, "6.2.6: rename a file to itself", FILE1, 1, 1, NOTE_RENAME, NO_EVENT);
1540 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1541 init_action(&test.t_helpthreadact, SLEEP, RENAME, 2, (void*)FILE1, (void*)FILE1);
1542 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, NULL);
1543 execute_test(&test);
1544
1545 init_test(&test, "6.2.7: rename a dir to itself", DIR1, 1, 1, NOTE_RENAME, NO_EVENT);
1546 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKDIR, 2, (void*)DIR1, (void*)NULL);
1547 init_action(&test.t_helpthreadact, SLEEP, RENAME, 2, (void*)DIR1, (void*)DIR1);
1548 init_action(&test.t_cleanup_actions[0], NOSLEEP, RMDIR, 2, (void*)DIR1, NULL);
1549 execute_test(&test);
1550 }
1551
1552 void
1553 run_note_revoke_tests()
1554 {
1555 test_t test;
1556 init_test(&test, "7.1.1: revoke file", FILE1, 1, 1, NOTE_REVOKE, YES_EVENT);
1557 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 1, (void*)FILE1);
1558 init_action(&test.t_helpthreadact, SLEEP, REVOKE, 1, (void*)FILE1);
1559 init_action(&(test.t_cleanup_actions[0]), NOSLEEP, UNLINK, 1, (void*)FILE1);
1560 execute_test(&test);
1561
1562 init_test(&test, "7.2.1: delete file", FILE1, 1, 0, NOTE_REVOKE, NO_EVENT);
1563 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 1, (void*)FILE1);
1564 init_action(&test.t_helpthreadact, SLEEP, UNLINK, 1, (void*)FILE1);
1565 execute_test(&test);
1566 }
1567
1568
1569 void
1570 run_evfilt_read_tests()
1571 {
1572 test_t test;
1573 init_test(&test, "8.1.1: how much data in file of length LENGTHEN_SIZE?", FILE1, 2, 1, EVFILT_READ, LENGTHEN_SIZE);
1574 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void*)NULL);
1575 init_action(&(test.t_prep_actions[1]), NOSLEEP, LENGTHEN, 2, (void*)FILE1, (void*)NULL);
1576 init_action(&test.t_helpthreadact, SLEEP, NOTHING, 0);
1577 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, NULL);
1578 execute_test(&test);
1579
1580 init_test(&test, "8.1.2: block, then write to file", FILE1, 2, 1, EVFILT_READ, strlen(TEST_STRING));
1581 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 1, (void*)FILE1);
1582 init_action(&(test.t_prep_actions[1]), NOSLEEP, TRUNC, 1, (void*)FILE1);
1583 init_action(&test.t_helpthreadact, SLEEP, WRITE, 1, (void*)FILE1);
1584 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, NULL);
1585 execute_test(&test);
1586
1587 init_test(&test, "8.1.3: block, then extend", FILE1, 2, 1, EVFILT_READ, LENGTHEN_SIZE);
1588 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 1, (void*)FILE1);
1589 init_action(&(test.t_prep_actions[1]), NOSLEEP, TRUNC, 1, (void*)FILE1);
1590 init_action(&test.t_helpthreadact, SLEEP, LENGTHEN, 1, (void*)FILE1);
1591 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, NULL);
1592 execute_test(&test);
1593
1594 init_test(&test, "8.1.4: block, then seek to beginning", FILE1, 2, 1, EVFILT_READ, strlen(TEST_STRING));
1595 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 1, (void*)FILE1);
1596 init_action(&(test.t_prep_actions[1]), NOSLEEP, WRITE, 1, (void*)FILE1);
1597 test.t_read_to_end_first = 1; /* hack means that we've gotten to EOF before we block */
1598 init_action(&test.t_helpthreadact, SLEEP, LSEEK, 1, (void*)0);
1599 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, NULL);
1600 execute_test(&test);
1601
1602
1603 init_test(&test, "8.1.5: block, then write to fifo", FILE1, 1, 1, EVFILT_READ, strlen(TEST_STRING));
1604 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKFIFO, 1, (void*)FILE1);
1605 test.t_file_is_fifo = 1;
1606 init_action(&test.t_helpthreadact, SLEEP, WRITE, 1, (void*)FILE1);
1607 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, NULL);
1608 execute_test(&test);
1609
1610 /* No result section... */
1611 init_test(&test, "8.2.1: just rename", FILE1, 2, 1, EVFILT_READ, NO_EVENT);
1612 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 1, (void*)FILE1);
1613 init_action(&(test.t_prep_actions[1]), NOSLEEP, TRUNC, 1, (void*)FILE1);
1614 init_action(&test.t_helpthreadact, SLEEP, RENAME, 2, (void*)FILE1, (void*)FILE2);
1615 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE2, NULL);
1616 execute_test(&test);
1617
1618 init_test(&test, "8.2.2: delete file", FILE1, 2, 0, EVFILT_READ, NO_EVENT);
1619 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 1, (void*)FILE1);
1620 init_action(&(test.t_prep_actions[1]), NOSLEEP, TRUNC, 1, (void*)FILE1);
1621 init_action(&test.t_helpthreadact, SLEEP, UNLINK, 1, (void*)FILE1);
1622 execute_test(&test);
1623
1624 init_test(&test, "8.2.3: write to beginning", FILE1, 2, 1, EVFILT_READ, NO_EVENT);
1625 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 1, (void*)FILE1);
1626 init_action(&(test.t_prep_actions[1]), NOSLEEP, WRITE, 1, (void*)FILE1);
1627 test.t_read_to_end_first = 1; /* hack means that we've gotten to EOF before we block */
1628 init_action(&test.t_helpthreadact, SLEEP, WRITE, 1, (void*)FILE1);
1629 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 1, (void*)FILE1);
1630 execute_test(&test);
1631
1632 init_test(&test, "8.1.4: block, then seek to current location", FILE1, 2, 1, EVFILT_READ, 0);
1633 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 1, (void*)FILE1);
1634 init_action(&(test.t_prep_actions[1]), NOSLEEP, WRITE, 1, (void*)FILE1);
1635 test.t_read_to_end_first = 1; /* hack means that we've gotten to EOF before we block */
1636 init_action(&test.t_helpthreadact, SLEEP, LSEEK, 1, (void*)strlen(TEST_STRING));
1637 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, NULL);
1638 execute_test(&test);
1639
1640 init_test(&test, "8.2.5: trying to read from empty fifo", FILE1, 1, 1, EVFILT_READ, 0);
1641 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKFIFO, 1, (void*)FILE1);
1642 test.t_file_is_fifo = 1;
1643 init_action(&test.t_helpthreadact, SLEEP, NOTHING, 1, (void*)0);
1644 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, NULL);
1645 execute_test(&test);
1646 }
1647
1648
1649
1650 void*
1651 read_from_fd(void *arg)
1652 {
1653 char buf[50];
1654 int fd = (int) arg;
1655 usleep(USLEEP_TIME);
1656 return (void*) read(fd, buf, sizeof(buf));
1657 }
1658
1659 void*
1660 write_to_fd(void *arg)
1661 {
1662 char buf[50];
1663 int fd = (int) arg;
1664 usleep(USLEEP_TIME);
1665 return (void*) write(fd, buf, sizeof(buf));
1666 }
1667
1668 /*
1669 * We don't (in principle) support EVFILT_WRITE for vnodes; thusly, no tests here
1670 */
1671 void
1672 run_evfilt_write_tests()
1673 {
1674 test_t test;
1675 init_test(&test, "9.1.1: how much space in empty fifo?", FILE1, 1, 1, EVFILT_WRITE, FIFO_SPACE);
1676 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKFIFO, 1, (void*)FILE1, (void*)NULL);
1677 test.t_file_is_fifo = 1;
1678 init_action(&test.t_helpthreadact, SLEEP, NOTHING, 0);
1679 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, NULL);
1680 execute_test(&test);
1681
1682 init_test(&test, "9.1.2: how much space in slightly written fifo?", FILE1, 1, 1, EVFILT_WRITE, FIFO_SPACE - strlen(TEST_STRING));
1683 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKFIFO, 1, (void*)FILE1, (void*)NULL);
1684 test.t_file_is_fifo = 1;
1685 test.t_write_some_data = 1;
1686 init_action(&(test.t_helpthreadact), NOSLEEP, NOTHING, 0);
1687 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, NULL);
1688 execute_test(&test);
1689
1690 init_test(&test, "9.2.1: how much space in a full fifo?", FILE1, 1, 1, EVFILT_WRITE, 0);
1691 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKFIFO, 1, (void*)FILE1, (void*)NULL);
1692 test.t_nondeterministic = 1;
1693 test.t_file_is_fifo = 1;
1694 test.t_extra_sleep_hack = 1;
1695 init_action(&(test.t_helpthreadact), NOSLEEP, FILLFD, 1, (void*)FILE1, (void*)NULL);
1696 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, NULL);
1697 execute_test(&test);
1698 }
1699
1700 void
1701 run_poll_tests()
1702 {
1703 test_t test;
1704 init_poll_test(&test, "10.1.1: does poll say I can write a regular file?", FILE1, 1, 1, POLLWRNORM, 1);
1705 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 1, (void*)FILE1, (void*)NULL);
1706 init_action(&test.t_helpthreadact, SLEEP, NOTHING, 0);
1707 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, NULL);
1708 execute_test(&test);
1709
1710 init_poll_test(&test, "10.1.2: does poll say I can write an empty FIFO?", FILE1, 1, 1, POLLWRNORM, 1);
1711 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKFIFO, 1, (void*)FILE1, (void*)NULL);
1712 test.t_file_is_fifo = 1;
1713 init_action(&test.t_helpthreadact, SLEEP, NOTHING, 0);
1714 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, NULL);
1715 execute_test(&test);
1716
1717 init_poll_test(&test, "10.1.3: does poll say I can read a nonempty FIFO?", FILE1, 1, 1, POLLRDNORM, 1);
1718 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKFIFO, 1, (void*)FILE1, (void*)NULL);
1719 test.t_file_is_fifo = 1;
1720 test.t_write_some_data = 1;
1721 init_action(&test.t_helpthreadact, SLEEP, NOTHING, 0);
1722 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, NULL);
1723 execute_test(&test);
1724
1725 init_poll_test(&test, "10.1.4: does poll say I can read a nonempty regular file?", FILE1, 2, 1, POLLRDNORM, 1);
1726 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 1, (void*)FILE1, (void*)NULL);
1727 init_action(&(test.t_prep_actions[1]), NOSLEEP, LENGTHEN, 1, (void*)FILE1, (void*)NULL);
1728 init_action(&test.t_helpthreadact, SLEEP, NOTHING, 0);
1729 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, NULL);
1730 execute_test(&test);
1731
1732 init_poll_test(&test, "10.1.5: does poll say I can read an empty file?", FILE1, 1, 1, POLLRDNORM, 1);
1733 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 1, (void*)FILE1, (void*)NULL);
1734 init_action(&test.t_helpthreadact, SLEEP, NOTHING, 0);
1735 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, NULL);
1736 execute_test(&test);
1737
1738
1739
1740
1741 init_poll_test(&test, "10.2.2: does poll say I can read an empty FIFO?", FILE1, 1, 1, POLLRDNORM, 0);
1742 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKFIFO, 1, (void*)FILE1, (void*)NULL);
1743 test.t_file_is_fifo = 1;
1744 init_action(&test.t_helpthreadact, SLEEP, NOTHING, 0);
1745 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, NULL);
1746 execute_test(&test);
1747
1748 init_poll_test(&test, "10.2.3: does poll say I can write a full FIFO?", FILE1, 1, 1, POLLWRNORM, 0);
1749 init_action(&(test.t_prep_actions[0]), NOSLEEP, MKFIFO, 1, (void*)FILE1, (void*)NULL);
1750 test.t_nondeterministic = 1;
1751 test.t_file_is_fifo = 1;
1752 test.t_extra_sleep_hack = 1;
1753 init_action(&(test.t_helpthreadact), NOSLEEP, FILLFD, 1, (void*)FILE1, (void*)NULL);
1754 init_action(&test.t_cleanup_actions[0], NOSLEEP, UNLINK, 2, (void*)FILE1, NULL);
1755 test.t_known_failure = 1;
1756 execute_test(&test);
1757 }
1758
1759 void
1760 run_note_funlock_tests()
1761 {
1762 test_t test;
1763 init_test(&test, "11.1.1: unlock file", FILE1, 1, 1, NOTE_FUNLOCK, YES_EVENT);
1764 test.t_nondeterministic = 1;
1765 init_action(&(test.t_prep_actions[0]), NOSLEEP, CREAT, 2, (void*)FILE1, (void *)NULL);
1766 init_action(&test.t_helpthreadact, SLEEP, FUNLOCK, 2, (void*)FILE1, (void *)NULL);
1767 init_action(&(test.t_cleanup_actions[0]), NOSLEEP, UNLINK, 2, (void*)FILE1, (void *)NULL);
1768 execute_test(&test);
1769 }
1770
1771 void
1772 run_all_tests()
1773 {
1774 run_note_delete_tests();
1775 run_note_write_tests();
1776 run_note_extend_tests();
1777 run_note_attrib_tests();
1778 run_note_link_tests();
1779 run_note_rename_tests();
1780 #if 0
1781 run_note_revoke_tests(); /* Can no longer revoke a regular file--need an unmount test */
1782 #endif /* 0 */
1783 run_evfilt_read_tests();
1784 run_evfilt_write_tests();
1785 run_poll_tests();
1786 run_note_funlock_tests();
1787 }
1788
1789 T_DECL(kqueue_file_tests,
1790 "Tests assorted kqueue operations for file-related events")
1791 {
1792 char *which = NULL;
1793 if (argc > 1) {
1794 which = argv[1];
1795 }
1796
1797 T_SETUPBEGIN;
1798 rmdir(DIR1);
1799 rmdir(DIR2);
1800 T_SETUPEND;
1801
1802 if ((!which) || (strcmp(which, "all") == 0)) {
1803 run_all_tests();
1804 } else if (strcmp(which, "delete") == 0) {
1805 run_note_delete_tests();
1806 } else if (strcmp(which, "write") == 0) {
1807 run_note_write_tests();
1808 } else if (strcmp(which, "extend") == 0) {
1809 run_note_extend_tests();
1810 } else if (strcmp(which, "attrib") == 0) {
1811 run_note_attrib_tests();
1812 } else if (strcmp(which, "link") == 0) {
1813 run_note_link_tests();
1814 } else if (strcmp(which, "rename") == 0) {
1815 run_note_rename_tests();
1816 } else if (strcmp(which, "revoke") == 0) {
1817 run_note_revoke_tests();
1818 } else if (strcmp(which, "evfiltread") == 0) {
1819 run_evfilt_read_tests();
1820 } else if (strcmp(which, "evfiltwrite") == 0) {
1821 run_evfilt_write_tests();
1822 } else if (strcmp(which, "poll") == 0) {
1823 run_poll_tests();
1824 } else if (strcmp(which, "funlock") == 0) {
1825 run_note_funlock_tests();
1826 } else {
1827 fprintf(stderr, "Valid options are:\n\tdelete, write, extend, "
1828 "attrib, link, rename, revoke, evfiltread, "
1829 "fifo, all, evfiltwrite, funlock<none>\n");
1830 exit(1);
1831 }
1832 }