test-fs-event.c
Go to the documentation of this file.
1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to
5  * deal in the Software without restriction, including without limitation the
6  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7  * sell copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19  * IN THE SOFTWARE.
20  */
21 
22 #include "uv.h"
23 #include "task.h"
24 
25 #include <string.h>
26 #include <fcntl.h>
27 
28 #if defined(__APPLE__) && !TARGET_OS_IPHONE
29 # include <AvailabilityMacros.h>
30 #endif
31 
32 #ifndef HAVE_KQUEUE
33 # if defined(__APPLE__) || \
34  defined(__DragonFly__) || \
35  defined(__FreeBSD__) || \
36  defined(__FreeBSD_kernel__) || \
37  defined(__OpenBSD__) || \
38  defined(__NetBSD__)
39 # define HAVE_KQUEUE 1
40 # endif
41 #endif
42 
43 #if defined(__arm__)/* Increase the timeout so the test passes on arm CI bots */
44 # define CREATE_TIMEOUT 100
45 #else
46 # define CREATE_TIMEOUT 1
47 #endif
48 
50 static const char file_prefix[] = "fsevent-";
51 static const int fs_event_file_count = 16;
52 #if defined(__APPLE__) || defined(_WIN32)
53 static const char file_prefix_in_subdir[] = "subdir";
54 static int fs_multievent_cb_called;
55 #endif
57 static int timer_cb_called;
58 static int close_cb_called;
59 static int fs_event_created;
60 static int fs_event_removed;
61 static int fs_event_cb_called;
62 #if defined(PATH_MAX)
63 static char fs_event_filename[PATH_MAX];
64 #else
65 static char fs_event_filename[1024];
66 #endif /* defined(PATH_MAX) */
69 
71  const char* filename,
72  int events,
73  int status) {
74  ASSERT(0 && "should never be called");
75 }
76 
77 static void create_dir(const char* name) {
78  int r;
79  uv_fs_t req;
80  r = uv_fs_mkdir(NULL, &req, name, 0755, NULL);
81  ASSERT(r == 0 || r == UV_EEXIST);
83 }
84 
85 static void create_file(const char* name) {
86  int r;
87  uv_file file;
88  uv_fs_t req;
89 
90  r = uv_fs_open(NULL, &req, name, O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR, NULL);
91  ASSERT(r >= 0);
92  file = r;
94  r = uv_fs_close(NULL, &req, file, NULL);
95  ASSERT(r == 0);
97 }
98 
99 static void touch_file(const char* name) {
100  int r;
101  uv_file file;
102  uv_fs_t req;
103  uv_buf_t buf;
104 
105  r = uv_fs_open(NULL, &req, name, O_RDWR, 0, NULL);
106  ASSERT(r >= 0);
107  file = r;
109 
110  buf = uv_buf_init("foo", 4);
111  r = uv_fs_write(NULL, &req, file, &buf, 1, -1, NULL);
112  ASSERT(r >= 0);
114 
115  r = uv_fs_close(NULL, &req, file, NULL);
116  ASSERT(r == 0);
118 }
119 
120 static void close_cb(uv_handle_t* handle) {
121  ASSERT(handle != NULL);
122  close_cb_called++;
123 }
124 
126  const char* path,
127  int events,
128  int status) {
129  ASSERT(0 && "fail_cb called");
130 }
131 
132 static void fs_event_cb_dir(uv_fs_event_t* handle, const char* filename,
133  int events, int status) {
135  ASSERT(handle == &fs_event);
136  ASSERT(status == 0);
137  ASSERT(events == UV_CHANGE);
138  #if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
139  ASSERT(strcmp(filename, "file1") == 0);
140  #else
141  ASSERT(filename == NULL || strcmp(filename, "file1") == 0);
142  #endif
145 }
146 
147 static const char* fs_event_get_filename(int i) {
148  snprintf(fs_event_filename,
149  sizeof(fs_event_filename),
150  "watch_dir/%s%d",
151  file_prefix,
152  i);
153  return fs_event_filename;
154 }
155 
157  /* Make sure we're not attempting to create files we do not intend */
159 
160  /* Create the file */
162 
164  /* Create another file on a different event loop tick. We do it this way
165  * to avoid fs events coalescing into one fs event. */
169  0));
170  }
171 }
172 
174  int r;
175  int i;
176 
177  /* NOTE: handle might be NULL if invoked not as timer callback */
178  if (handle == NULL) {
179  /* Unlink all files */
180  for (i = 0; i < 16; i++) {
181  r = remove(fs_event_get_filename(i));
182  if (handle != NULL)
183  ASSERT(r == 0);
184  }
185  } else {
186  /* Make sure we're not attempting to remove files we do not intend */
188 
189  /* Remove the file */
191 
193  /* Remove another file on a different event loop tick. We do it this way
194  * to avoid fs events coalescing into one fs event. */
196  }
197  }
198 }
199 
201  const char* filename,
202  int events,
203  int status) {
205  ASSERT(handle == &fs_event);
206  ASSERT(status == 0);
207  ASSERT(events == UV_CHANGE || events == UV_RENAME);
208  #if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
209  ASSERT(strncmp(filename, file_prefix, sizeof(file_prefix) - 1) == 0);
210  #else
211  ASSERT(filename == NULL ||
212  strncmp(filename, file_prefix, sizeof(file_prefix) - 1) == 0);
213  #endif
214 
216  /* Once we've processed all create events, delete all files */
218  } else if (fs_event_cb_called == 2 * fs_event_file_count) {
219  /* Once we've processed all create and delete events, stop watching */
222  }
223 }
224 
225 #if defined(__APPLE__) || defined(_WIN32)
226 static const char* fs_event_get_filename_in_subdir(int i) {
227  snprintf(fs_event_filename,
228  sizeof(fs_event_filename),
229  "watch_dir/subdir/%s%d",
230  file_prefix,
231  i);
232  return fs_event_filename;
233 }
234 
235 static void fs_event_create_files_in_subdir(uv_timer_t* handle) {
236  /* Make sure we're not attempting to create files we do not intend */
238 
239  /* Create the file */
240  create_file(fs_event_get_filename_in_subdir(fs_event_created));
241 
243  /* Create another file on a different event loop tick. We do it this way
244  * to avoid fs events coalescing into one fs event. */
245  ASSERT(0 == uv_timer_start(&timer, fs_event_create_files_in_subdir, 1, 0));
246  }
247 }
248 
249 static void fs_event_unlink_files_in_subdir(uv_timer_t* handle) {
250  int r;
251  int i;
252 
253  /* NOTE: handle might be NULL if invoked not as timer callback */
254  if (handle == NULL) {
255  /* Unlink all files */
256  for (i = 0; i < 16; i++) {
257  r = remove(fs_event_get_filename_in_subdir(i));
258  if (handle != NULL)
259  ASSERT(r == 0);
260  }
261  } else {
262  /* Make sure we're not attempting to remove files we do not intend */
264 
265  /* Remove the file */
266  ASSERT(0 == remove(fs_event_get_filename_in_subdir(fs_event_removed)));
267 
269  /* Remove another file on a different event loop tick. We do it this way
270  * to avoid fs events coalescing into one fs event. */
271  ASSERT(0 == uv_timer_start(&timer, fs_event_unlink_files_in_subdir, 1, 0));
272  }
273  }
274 }
275 
276 static void fs_event_cb_dir_multi_file_in_subdir(uv_fs_event_t* handle,
277  const char* filename,
278  int events,
279  int status) {
280 #ifdef _WIN32
281  /* Each file created (or deleted) will cause this callback to be called twice
282  * under Windows: once with the name of the file, and second time with the
283  * name of the directory. We will ignore the callback for the directory
284  * itself. */
285  if (filename && strcmp(filename, file_prefix_in_subdir) == 0)
286  return;
287 #endif
288  /* It may happen that the "subdir" creation event is captured even though
289  * we started watching after its actual creation.
290  */
291  if (strcmp(filename, "subdir") == 0)
292  return;
293 
294  fs_multievent_cb_called++;
295  ASSERT(handle == &fs_event);
296  ASSERT(status == 0);
297  ASSERT(events == UV_CHANGE || events == UV_RENAME);
298  #if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
299  ASSERT(strncmp(filename,
300  file_prefix_in_subdir,
301  sizeof(file_prefix_in_subdir) - 1) == 0);
302  #else
303  ASSERT(filename == NULL ||
304  strncmp(filename,
305  file_prefix_in_subdir,
306  sizeof(file_prefix_in_subdir) - 1) == 0);
307  #endif
308 
310  fs_multievent_cb_called == fs_event_created) {
311  /* Once we've processed all create events, delete all files */
312  ASSERT(0 == uv_timer_start(&timer, fs_event_unlink_files_in_subdir, 1, 0));
313  } else if (fs_multievent_cb_called == 2 * fs_event_file_count) {
314  /* Once we've processed all create and delete events, stop watching */
318  }
319 }
320 #endif
321 
322 static void fs_event_cb_file(uv_fs_event_t* handle, const char* filename,
323  int events, int status) {
325  ASSERT(handle == &fs_event);
326  ASSERT(status == 0);
327  ASSERT(events == UV_CHANGE);
328  #if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
329  ASSERT(strcmp(filename, "file2") == 0);
330  #else
331  ASSERT(filename == NULL || strcmp(filename, "file2") == 0);
332  #endif
335 }
336 
339 
340  ASSERT(timer != NULL);
341  handle = timer->data;
342 
343  uv_close((uv_handle_t*)timer, NULL);
345 }
346 
348  const char* filename, int events, int status) {
351 
352  ASSERT(handle == &fs_event);
353  ASSERT(status == 0);
354  ASSERT(events == UV_CHANGE);
355  #if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
356  ASSERT(strcmp(filename, "watch_file") == 0);
357  #else
358  ASSERT(filename == NULL || strcmp(filename, "watch_file") == 0);
359  #endif
360 
361  /* Regression test for SunOS: touch should generate just one event. */
362  {
363  static uv_timer_t timer;
364  uv_timer_init(handle->loop, &timer);
365  timer.data = handle;
367  }
368 }
369 
371  ++timer_cb_called;
372 
373  if (timer_cb_called == 1) {
374  touch_file("watch_dir/file1");
375  } else {
376  touch_file("watch_dir/file2");
378  }
379 }
380 
382  uv_close((uv_handle_t*)timer, NULL);
383  touch_file("watch_file");
385 }
386 
388  int r;
389 
390  if (timer_cb_exact_called == 0) {
391  touch_file("watch_dir/file.js");
392  } else {
393  uv_close((uv_handle_t*)handle, NULL);
395  ASSERT(r == 0);
396  uv_close((uv_handle_t*) &fs_event, NULL);
397  }
398 
400 }
401 
403  uv_fs_event_t* handles = handle->data;
404  uv_close((uv_handle_t*) (handles + 0), NULL);
405  uv_close((uv_handle_t*) (handles + 1), NULL);
406  uv_close((uv_handle_t*) handle, NULL);
407 }
408 
410  const char* filename,
411  int events,
412  int status) {
413  ASSERT(status == 0);
414 
417 
418  if (fs_event_cb_called == 3) {
420  }
421 }
422 
423 
424 TEST_IMPL(fs_event_watch_dir) {
425 #if defined(NO_FS_EVENTS)
426  RETURN_SKIP(NO_FS_EVENTS);
427 #elif defined(__MVS__)
428  RETURN_SKIP("Directory watching not supported on this platform.");
429 #endif
430 
432  int r;
433 
434  /* Setup */
435  fs_event_unlink_files(NULL);
436  remove("watch_dir/file2");
437  remove("watch_dir/file1");
438  remove("watch_dir/");
439  create_dir("watch_dir");
440 
442  ASSERT(r == 0);
444  ASSERT(r == 0);
445  r = uv_timer_init(loop, &timer);
446  ASSERT(r == 0);
448  ASSERT(r == 0);
449 
451 
453  ASSERT(close_cb_called == 2);
454 
455  /* Cleanup */
456  fs_event_unlink_files(NULL);
457  remove("watch_dir/file2");
458  remove("watch_dir/file1");
459  remove("watch_dir/");
460 
462  return 0;
463 }
464 
465 
466 TEST_IMPL(fs_event_watch_dir_recursive) {
467 #if defined(__APPLE__) || defined(_WIN32)
468  uv_loop_t* loop;
469  int r;
470  uv_fs_event_t fs_event_root;
471 
472  /* Setup */
473  loop = uv_default_loop();
474  fs_event_unlink_files(NULL);
475  remove("watch_dir/file2");
476  remove("watch_dir/file1");
477  remove("watch_dir/subdir");
478  remove("watch_dir/");
479  create_dir("watch_dir");
480  create_dir("watch_dir/subdir");
481 
483  ASSERT(r == 0);
485  fs_event_cb_dir_multi_file_in_subdir,
486  "watch_dir",
488  ASSERT(r == 0);
489  r = uv_timer_init(loop, &timer);
490  ASSERT(r == 0);
491  r = uv_timer_start(&timer, fs_event_create_files_in_subdir, 100, 0);
492  ASSERT(r == 0);
493 
494 #ifndef _WIN32
495  /* Also try to watch the root directory.
496  * This will be noisier, so we're just checking for any couple events to happen. */
497  r = uv_fs_event_init(loop, &fs_event_root);
498  ASSERT(r == 0);
499  r = uv_fs_event_start(&fs_event_root,
501  "/",
503  ASSERT(r == 0);
504 #else
505  fs_event_cb_called += 3;
506  close_cb_called += 1;
507  (void)fs_event_root;
508 #endif
509 
511 
512  ASSERT(fs_multievent_cb_called == fs_event_created + fs_event_removed);
514  ASSERT(close_cb_called == 3);
515 
516  /* Cleanup */
517  fs_event_unlink_files_in_subdir(NULL);
518  remove("watch_dir/file2");
519  remove("watch_dir/file1");
520  remove("watch_dir/subdir");
521  remove("watch_dir/");
522 
524  return 0;
525 #else
526  RETURN_SKIP("Recursive directory watching not supported on this platform.");
527 #endif
528 }
529 
530 #ifdef _WIN32
531 TEST_IMPL(fs_event_watch_dir_short_path) {
532  uv_loop_t* loop;
533  uv_fs_t req;
534  int has_shortnames;
535  int r;
536 
537  /* Setup */
538  loop = uv_default_loop();
539  remove("watch_dir/file1");
540  remove("watch_dir/");
541  create_dir("watch_dir");
542  create_file("watch_dir/file1");
543 
544  /* Newer version of Windows ship with
545  HKLM\SYSTEM\CurrentControlSet\Control\FileSystem\NtfsDisable8dot3NameCreation
546  not equal to 0. So we verify the files we created are addressable by a 8.3
547  short name */
548  has_shortnames = uv_fs_stat(NULL, &req, "watch_~1", NULL) != UV_ENOENT;
549  if (has_shortnames) {
551  ASSERT(r == 0);
552  r = uv_fs_event_start(&fs_event, fs_event_cb_dir, "watch_~1", 0);
553  ASSERT(r == 0);
554  r = uv_timer_init(loop, &timer);
555  ASSERT(r == 0);
556  r = uv_timer_start(&timer, timer_cb_file, 100, 0);
557  ASSERT(r == 0);
558 
560 
562  ASSERT(timer_cb_called == 1);
563  ASSERT(close_cb_called == 1);
564  }
565 
566  /* Cleanup */
567  remove("watch_dir/file1");
568  remove("watch_dir/");
569 
571 
572  if (!has_shortnames)
573  RETURN_SKIP("Was not able to address files with 8.3 short name.");
574 
575  return 0;
576 }
577 #endif
578 
579 
580 TEST_IMPL(fs_event_watch_file) {
581 #if defined(NO_FS_EVENTS)
582  RETURN_SKIP(NO_FS_EVENTS);
583 #endif
584 
586  int r;
587 
588  /* Setup */
589  remove("watch_dir/file2");
590  remove("watch_dir/file1");
591  remove("watch_dir/");
592  create_dir("watch_dir");
593  create_file("watch_dir/file1");
594  create_file("watch_dir/file2");
595 
597  ASSERT(r == 0);
598  r = uv_fs_event_start(&fs_event, fs_event_cb_file, "watch_dir/file2", 0);
599  ASSERT(r == 0);
600  r = uv_timer_init(loop, &timer);
601  ASSERT(r == 0);
602  r = uv_timer_start(&timer, timer_cb_file, 100, 100);
603  ASSERT(r == 0);
604 
606 
608  ASSERT(timer_cb_called == 2);
609  ASSERT(close_cb_called == 2);
610 
611  /* Cleanup */
612  remove("watch_dir/file2");
613  remove("watch_dir/file1");
614  remove("watch_dir/");
615 
617  return 0;
618 }
619 
620 TEST_IMPL(fs_event_watch_file_exact_path) {
621  /*
622  This test watches a file named "file.jsx" and modifies a file named
623  "file.js". The test verifies that no events occur for file.jsx.
624  */
625 
626 #if defined(NO_FS_EVENTS)
627  RETURN_SKIP(NO_FS_EVENTS);
628 #endif
629 
630  uv_loop_t* loop;
631  int r;
632 
633  loop = uv_default_loop();
634 
635  /* Setup */
636  remove("watch_dir/file.js");
637  remove("watch_dir/file.jsx");
638  remove("watch_dir/");
639  create_dir("watch_dir");
640  create_file("watch_dir/file.js");
641  create_file("watch_dir/file.jsx");
642 #if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_12)
643  /* Empirically, FSEvents seems to (reliably) report the preceeding
644  * create_file events prior to macOS 10.11.6 in the subsequent fs_watch
645  * creation, but that behavior hasn't been observed to occur on newer
646  * versions. Give a long delay here to let the system settle before running
647  * the test. */
648  uv_sleep(1100);
650 #endif
651 
653  ASSERT(r == 0);
654  r = uv_fs_event_start(&fs_event, fs_event_fail, "watch_dir/file.jsx", 0);
655  ASSERT(r == 0);
656  r = uv_timer_init(loop, &timer);
657  ASSERT(r == 0);
658  r = uv_timer_start(&timer, timer_cb_exact, 100, 100);
659  ASSERT(r == 0);
661  ASSERT(r == 0);
663 
664  /* Cleanup */
665  remove("watch_dir/file.js");
666  remove("watch_dir/file.jsx");
667  remove("watch_dir/");
668 
670  return 0;
671 }
672 
673 TEST_IMPL(fs_event_watch_file_twice) {
674 #if defined(NO_FS_EVENTS)
675  RETURN_SKIP(NO_FS_EVENTS);
676 #endif
677  const char path[] = "test/fixtures/empty_file";
678  uv_fs_event_t watchers[2];
680  uv_loop_t* loop;
681 
682  loop = uv_default_loop();
683  timer.data = watchers;
684 
685  ASSERT(0 == uv_fs_event_init(loop, watchers + 0));
686  ASSERT(0 == uv_fs_event_start(watchers + 0, fail_cb, path, 0));
687  ASSERT(0 == uv_fs_event_init(loop, watchers + 1));
688  ASSERT(0 == uv_fs_event_start(watchers + 1, fail_cb, path, 0));
689  ASSERT(0 == uv_timer_init(loop, &timer));
692 
694  return 0;
695 }
696 
697 TEST_IMPL(fs_event_watch_file_current_dir) {
698 #if defined(NO_FS_EVENTS)
699  RETURN_SKIP(NO_FS_EVENTS);
700 #endif
702  uv_loop_t* loop;
703  int r;
704 
705  loop = uv_default_loop();
706 
707  /* Setup */
708  remove("watch_file");
709  create_file("watch_file");
710 #if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_12)
711  /* Empirically, kevent seems to (sometimes) report the preceeding
712  * create_file events prior to macOS 10.11.6 in the subsequent fs_event_start
713  * So let the system settle before running the test. */
714  uv_sleep(1100);
716 #endif
717 
719  ASSERT(r == 0);
722  "watch_file",
723  0);
724  ASSERT(r == 0);
725 
726 
727  r = uv_timer_init(loop, &timer);
728  ASSERT(r == 0);
729 
730  r = uv_timer_start(&timer, timer_cb_touch, 1100, 0);
731  ASSERT(r == 0);
732 
735  ASSERT(close_cb_called == 0);
736 
738 
741  ASSERT(close_cb_called == 1);
742 
743  /* Cleanup */
744  remove("watch_file");
745 
747  return 0;
748 }
749 
750 #ifdef _WIN32
751 TEST_IMPL(fs_event_watch_file_root_dir) {
752  uv_loop_t* loop;
753  int r;
754 
755  const char* sys_drive = getenv("SystemDrive");
756  char path[] = "\\\\?\\X:\\bootsect.bak";
757 
758  ASSERT(sys_drive != NULL);
759  strncpy(path + sizeof("\\\\?\\") - 1, sys_drive, 1);
760 
761  loop = uv_default_loop();
762 
764  ASSERT(r == 0);
766  if (r == UV_ENOENT)
767  RETURN_SKIP("bootsect.bak doesn't exist in system root.\n");
768  ASSERT(r == 0);
769 
770  uv_close((uv_handle_t*) &fs_event, NULL);
771 
773  return 0;
774 }
775 #endif
776 
777 TEST_IMPL(fs_event_no_callback_after_close) {
778 #if defined(NO_FS_EVENTS)
779  RETURN_SKIP(NO_FS_EVENTS);
780 #endif
781 
783  int r;
784 
785  /* Setup */
786  remove("watch_dir/file1");
787  remove("watch_dir/");
788  create_dir("watch_dir");
789  create_file("watch_dir/file1");
790 
792  ASSERT(r == 0);
795  "watch_dir/file1",
796  0);
797  ASSERT(r == 0);
798 
799 
801  touch_file("watch_dir/file1");
803 
805  ASSERT(close_cb_called == 1);
806 
807  /* Cleanup */
808  remove("watch_dir/file1");
809  remove("watch_dir/");
810 
812  return 0;
813 }
814 
815 TEST_IMPL(fs_event_no_callback_on_close) {
816 #if defined(NO_FS_EVENTS)
817  RETURN_SKIP(NO_FS_EVENTS);
818 #endif
819 
821  int r;
822 
823  /* Setup */
824  remove("watch_dir/file1");
825  remove("watch_dir/");
826  create_dir("watch_dir");
827  create_file("watch_dir/file1");
828 
830  ASSERT(r == 0);
833  "watch_dir/file1",
834  0);
835  ASSERT(r == 0);
836 
838 
840 
842  ASSERT(close_cb_called == 1);
843 
844  /* Cleanup */
845  remove("watch_dir/file1");
846  remove("watch_dir/");
847 
849  return 0;
850 }
851 
852 
853 static void timer_cb(uv_timer_t* handle) {
854  int r;
855 
856  r = uv_fs_event_init(handle->loop, &fs_event);
857  ASSERT(r == 0);
859  ASSERT(r == 0);
860 
863 }
864 
865 
866 TEST_IMPL(fs_event_immediate_close) {
867 #if defined(NO_FS_EVENTS)
868  RETURN_SKIP(NO_FS_EVENTS);
869 #endif
871  uv_loop_t* loop;
872  int r;
873 
874  loop = uv_default_loop();
875 
876  r = uv_timer_init(loop, &timer);
877  ASSERT(r == 0);
878 
879  r = uv_timer_start(&timer, timer_cb, 1, 0);
880  ASSERT(r == 0);
881 
883 
884  ASSERT(close_cb_called == 2);
885 
887  return 0;
888 }
889 
890 
891 TEST_IMPL(fs_event_close_with_pending_event) {
892 #if defined(NO_FS_EVENTS)
893  RETURN_SKIP(NO_FS_EVENTS);
894 #endif
895  uv_loop_t* loop;
896  int r;
897 
898  loop = uv_default_loop();
899 
900  create_dir("watch_dir");
901  create_file("watch_dir/file");
902 
904  ASSERT(r == 0);
905  r = uv_fs_event_start(&fs_event, fs_event_fail, "watch_dir", 0);
906  ASSERT(r == 0);
907 
908  /* Generate an fs event. */
909  touch_file("watch_dir/file");
910 
912 
914 
915  ASSERT(close_cb_called == 1);
916 
917  /* Clean up */
918  remove("watch_dir/file");
919  remove("watch_dir/");
920 
922  return 0;
923 }
924 
925 TEST_IMPL(fs_event_close_in_callback) {
926 #if defined(NO_FS_EVENTS)
927  RETURN_SKIP(NO_FS_EVENTS);
928 #elif defined(__MVS__)
929  RETURN_SKIP("Directory watching not supported on this platform.");
930 #endif
931  uv_loop_t* loop;
932  int r;
933 
934  loop = uv_default_loop();
935 
936  fs_event_unlink_files(NULL);
937  create_dir("watch_dir");
938 
940  ASSERT(r == 0);
941  r = uv_fs_event_start(&fs_event, fs_event_cb_close, "watch_dir", 0);
942  ASSERT(r == 0);
943 
944  r = uv_timer_init(loop, &timer);
945  ASSERT(r == 0);
947  ASSERT(r == 0);
948 
950 
952 
954 
955  ASSERT(close_cb_called == 2);
957 
958  /* Clean up */
959  fs_event_unlink_files(NULL);
960  remove("watch_dir/");
961 
963  return 0;
964 }
965 
966 TEST_IMPL(fs_event_start_and_close) {
967 #if defined(NO_FS_EVENTS)
968  RETURN_SKIP(NO_FS_EVENTS);
969 #endif
970  uv_loop_t* loop;
971  uv_fs_event_t fs_event1;
972  uv_fs_event_t fs_event2;
973  int r;
974 
975  loop = uv_default_loop();
976 
977  create_dir("watch_dir");
978 
979  r = uv_fs_event_init(loop, &fs_event1);
980  ASSERT(r == 0);
981  r = uv_fs_event_start(&fs_event1, fs_event_cb_dir, "watch_dir", 0);
982  ASSERT(r == 0);
983 
984  r = uv_fs_event_init(loop, &fs_event2);
985  ASSERT(r == 0);
986  r = uv_fs_event_start(&fs_event2, fs_event_cb_dir, "watch_dir", 0);
987  ASSERT(r == 0);
988 
989  uv_close((uv_handle_t*) &fs_event2, close_cb);
990  uv_close((uv_handle_t*) &fs_event1, close_cb);
991 
993 
994  ASSERT(close_cb_called == 2);
995 
996  remove("watch_dir/");
998  return 0;
999 }
1000 
1001 TEST_IMPL(fs_event_getpath) {
1002 #if defined(NO_FS_EVENTS)
1003  RETURN_SKIP(NO_FS_EVENTS);
1004 #endif
1006  unsigned i;
1007  int r;
1008  char buf[1024];
1009  size_t len;
1010  const char* const watch_dir[] = {
1011  "watch_dir",
1012  "watch_dir/",
1013  "watch_dir///",
1014  "watch_dir/subfolder/..",
1015  "watch_dir//subfolder//..//",
1016  };
1017 
1018  create_dir("watch_dir");
1019  create_dir("watch_dir/subfolder");
1020 
1021 
1022  for (i = 0; i < ARRAY_SIZE(watch_dir); i++) {
1024  ASSERT(r == 0);
1025  len = sizeof buf;
1027  ASSERT(r == UV_EINVAL);
1028  r = uv_fs_event_start(&fs_event, fail_cb, watch_dir[i], 0);
1029  ASSERT(r == 0);
1030  len = 0;
1032  ASSERT(r == UV_ENOBUFS);
1033  ASSERT(len < sizeof buf); /* sanity check */
1034  ASSERT(len == strlen(watch_dir[i]) + 1);
1036  ASSERT(r == 0);
1037  ASSERT(len == strlen(watch_dir[i]));
1038  ASSERT(strcmp(buf, watch_dir[i]) == 0);
1040  ASSERT(r == 0);
1042 
1044 
1045  ASSERT(close_cb_called == 1);
1046  close_cb_called = 0;
1047  }
1048 
1049  remove("watch_dir/");
1051  return 0;
1052 }
1053 
1054 #if defined(__APPLE__)
1055 
1056 static int fs_event_error_reported;
1057 
1058 static void fs_event_error_report_cb(uv_fs_event_t* handle,
1059  const char* filename,
1060  int events,
1061  int status) {
1062  if (status != 0)
1063  fs_event_error_reported = status;
1064 }
1065 
1066 static void timer_cb_nop(uv_timer_t* handle) {
1067  ++timer_cb_called;
1069 }
1070 
1071 static void fs_event_error_report_close_cb(uv_handle_t* handle) {
1072  ASSERT(handle != NULL);
1073  close_cb_called++;
1074 
1075  /* handle is allocated on-stack, no need to free it */
1076 }
1077 
1078 
1079 TEST_IMPL(fs_event_error_reporting) {
1080  unsigned int i;
1081  uv_loop_t loops[1024];
1082  uv_fs_event_t events[ARRAY_SIZE(loops)];
1083  uv_loop_t* loop;
1084  uv_fs_event_t* event;
1085 
1086  TEST_FILE_LIMIT(ARRAY_SIZE(loops) * 3);
1087 
1088  remove("watch_dir/");
1089  create_dir("watch_dir");
1090 
1091  /* Create a lot of loops, and start FSEventStream in each of them.
1092  * Eventually, this should create enough streams to make FSEventStreamStart()
1093  * fail.
1094  */
1095  for (i = 0; i < ARRAY_SIZE(loops); i++) {
1096  loop = &loops[i];
1097  ASSERT(0 == uv_loop_init(loop));
1098  event = &events[i];
1099 
1100  timer_cb_called = 0;
1101  close_cb_called = 0;
1102  ASSERT(0 == uv_fs_event_init(loop, event));
1103  ASSERT(0 == uv_fs_event_start(event,
1104  fs_event_error_report_cb,
1105  "watch_dir",
1106  0));
1107  uv_unref((uv_handle_t*) event);
1108 
1109  /* Let loop run for some time */
1110  ASSERT(0 == uv_timer_init(loop, &timer));
1111  ASSERT(0 == uv_timer_start(&timer, timer_cb_nop, 2, 0));
1113  ASSERT(1 == timer_cb_called);
1114  ASSERT(1 == close_cb_called);
1115  if (fs_event_error_reported != 0)
1116  break;
1117  }
1118 
1119  /* At least one loop should fail */
1120  ASSERT(fs_event_error_reported == UV_EMFILE);
1121 
1122  /* Stop and close all events, and destroy loops */
1123  do {
1124  loop = &loops[i];
1125  event = &events[i];
1126 
1127  ASSERT(0 == uv_fs_event_stop(event));
1128  uv_ref((uv_handle_t*) event);
1129  uv_close((uv_handle_t*) event, fs_event_error_report_close_cb);
1130 
1131  close_cb_called = 0;
1133  ASSERT(close_cb_called == 1);
1134 
1136  } while (i-- != 0);
1137 
1138  remove("watch_dir/");
1140  return 0;
1141 }
1142 
1143 #else /* !defined(__APPLE__) */
1144 
1145 TEST_IMPL(fs_event_error_reporting) {
1146  /* No-op, needed only for FSEvents backend */
1147 
1149  return 0;
1150 }
1151 
1152 #endif /* defined(__APPLE__) */
1153 
1154 TEST_IMPL(fs_event_watch_invalid_path) {
1155 #if defined(NO_FS_EVENTS)
1156  RETURN_SKIP(NO_FS_EVENTS);
1157 #endif
1158 
1159  uv_loop_t* loop;
1160  int r;
1161 
1162  loop = uv_default_loop();
1164  ASSERT(r == 0);
1166  ASSERT(r != 0);
1169  ASSERT(r != 0);
1172  return 0;
1173 }
async_greeter_server_with_graceful_shutdown.loop
loop
Definition: async_greeter_server_with_graceful_shutdown.py:59
uv_fs_event_s
Definition: uv.h:1533
filename
const char * filename
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:135
ARRAY_SIZE
#define ARRAY_SIZE(array)
Definition: bloaty.cc:101
uv_fs_open
UV_EXTERN int uv_fs_open(uv_loop_t *loop, uv_fs_t *req, const char *path, int flags, int mode, uv_fs_cb cb)
Definition: unix/fs.c:1812
task.h
touch_file
static void touch_file(const char *name)
Definition: test-fs-event.c:99
file
const grpc_generator::File * file
Definition: python_private_generator.h:38
timer_cb_close_handle
static void timer_cb_close_handle(uv_timer_t *timer)
Definition: test-fs-event.c:337
uv_fs_stat
UV_EXTERN int uv_fs_stat(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_fs_cb cb)
Definition: unix/fs.c:1954
string.h
buf
voidpf void * buf
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
fs_event_filename
static char fs_event_filename[1024]
Definition: test-fs-event.c:65
handles
Definition: test-ipc-send-recv.c:35
fs_event_cb_called
static int fs_event_cb_called
Definition: test-fs-event.c:61
ASSERT
#define ASSERT(expr)
Definition: task.h:102
file
Definition: bloaty/third_party/zlib/examples/gzappend.c:170
status
absl::Status status
Definition: rls.cc:251
setup.name
name
Definition: setup.py:542
check_documentation.path
path
Definition: check_documentation.py:57
uv_run
UV_EXTERN int uv_run(uv_loop_t *, uv_run_mode mode)
Definition: unix/core.c:361
uv_fs_event_stop
UV_EXTERN int uv_fs_event_stop(uv_fs_event_t *handle)
Definition: aix.c:798
fs_event_cb_file
static void fs_event_cb_file(uv_fs_event_t *handle, const char *filename, int events, int status)
Definition: test-fs-event.c:322
close_cb_called
static int close_cb_called
Definition: test-fs-event.c:58
uv_fs_s
Definition: uv.h:1294
uv_fs_mkdir
UV_EXTERN int uv_fs_mkdir(uv_loop_t *loop, uv_fs_t *req, const char *path, int mode, uv_fs_cb cb)
Definition: unix/fs.c:1776
uv_unref
UV_EXTERN void uv_unref(uv_handle_t *)
Definition: uv-common.c:522
uv_close
UV_EXTERN void uv_close(uv_handle_t *handle, uv_close_cb close_cb)
Definition: unix/core.c:112
uv_fs_event_getpath
UV_EXTERN int uv_fs_event_getpath(uv_fs_event_t *handle, char *buffer, size_t *size)
Definition: uv-common.c:562
timer_cb_file
static void timer_cb_file(uv_timer_t *handle)
Definition: test-fs-event.c:370
uv_loop_close
UV_EXTERN int uv_loop_close(uv_loop_t *loop)
Definition: uv-common.c:761
fail_cb
static void fail_cb(uv_fs_event_t *handle, const char *path, int events, int status)
Definition: test-fs-event.c:125
uv_update_time
UV_EXTERN void uv_update_time(uv_loop_t *)
Definition: unix/core.c:413
uv_default_loop
UV_EXTERN uv_loop_t * uv_default_loop(void)
Definition: uv-common.c:733
req
static uv_connect_t req
Definition: test-connection-fail.c:30
timer_cb_exact_called
static int timer_cb_exact_called
Definition: test-fs-event.c:68
fs_event_created
static int fs_event_created
Definition: test-fs-event.c:59
UV_RUN_DEFAULT
@ UV_RUN_DEFAULT
Definition: uv.h:254
fs_event_create_files
static void fs_event_create_files(uv_timer_t *handle)
Definition: test-fs-event.c:156
fs_event_file_count
static const int fs_event_file_count
Definition: test-fs-event.c:51
fs_event_get_filename
static const char * fs_event_get_filename(int i)
Definition: test-fs-event.c:147
uv_is_active
UV_EXTERN int uv_is_active(const uv_handle_t *handle)
Definition: unix/core.c:418
create_dir
static void create_dir(const char *name)
Definition: test-fs-event.c:77
fs_event
static uv_fs_event_t fs_event
Definition: test-fs-event.c:49
timer_cb_watch_twice
static void timer_cb_watch_twice(uv_timer_t *handle)
Definition: test-fs-event.c:402
UV_RENAME
@ UV_RENAME
Definition: uv.h:1528
fs_event_fail
static void fs_event_fail(uv_fs_event_t *handle, const char *filename, int events, int status)
Definition: test-fs-event.c:70
timer_cb_exact
static void timer_cb_exact(uv_timer_t *handle)
Definition: test-fs-event.c:387
uv_loop_init
UV_EXTERN int uv_loop_init(uv_loop_t *loop)
Definition: loop.c:30
uv_sleep
UV_EXTERN void uv_sleep(unsigned int msec)
Definition: unix/core.c:1521
uv_file
int uv_file
Definition: unix.h:126
uv_timer_s
Definition: uv.h:850
fs_event_cb_file_current_dir
static void fs_event_cb_file_current_dir(uv_fs_event_t *handle, const char *filename, int events, int status)
Definition: test-fs-event.c:347
uv_fs_close
UV_EXTERN int uv_fs_close(uv_loop_t *loop, uv_fs_t *req, uv_file file, uv_fs_cb cb)
Definition: unix/fs.c:1651
fs_event_removed
static int fs_event_removed
Definition: test-fs-event.c:60
UV_CHANGE
@ UV_CHANGE
Definition: uv.h:1529
timer
static uv_timer_t timer
Definition: test-fs-event.c:56
close_cb
static void close_cb(uv_handle_t *handle)
Definition: test-fs-event.c:120
uv.h
MAKE_VALGRIND_HAPPY
#define MAKE_VALGRIND_HAPPY()
Definition: task.h:229
TEST_FILE_LIMIT
#define TEST_FILE_LIMIT(num)
Definition: task.h:271
uv_buf_t
Definition: unix.h:121
uv_ref
UV_EXTERN void uv_ref(uv_handle_t *)
Definition: uv-common.c:517
UV_FS_EVENT_RECURSIVE
@ UV_FS_EVENT_RECURSIVE
Definition: uv.h:1607
fs_event_cb_dir
static void fs_event_cb_dir(uv_fs_event_t *handle, const char *filename, int events, int status)
Definition: test-fs-event.c:132
fs_event_unlink_files
static void fs_event_unlink_files(uv_timer_t *handle)
Definition: test-fs-event.c:173
uv_fs_write
UV_EXTERN int uv_fs_write(uv_loop_t *loop, uv_fs_t *req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb)
Definition: unix/fs.c:1995
fs_event_cb_close
static void fs_event_cb_close(uv_fs_event_t *handle, const char *filename, int events, int status)
Definition: test-fs-event.c:409
fix_build_deps.r
r
Definition: fix_build_deps.py:491
fs_event_cb_dir_multi_file
static void fs_event_cb_dir_multi_file(uv_fs_event_t *handle, const char *filename, int events, int status)
Definition: test-fs-event.c:200
file_prefix
static const char file_prefix[]
Definition: test-fs-event.c:50
UV_RUN_ONCE
@ UV_RUN_ONCE
Definition: uv.h:255
uv_buf_init
UV_EXTERN uv_buf_t uv_buf_init(char *base, unsigned int len)
Definition: uv-common.c:157
uv_fs_event_start
UV_EXTERN int uv_fs_event_start(uv_fs_event_t *handle, uv_fs_event_cb cb, const char *path, unsigned int flags)
Definition: aix.c:727
uv_fs_req_cleanup
UV_EXTERN void uv_fs_req_cleanup(uv_fs_t *req)
Definition: unix/fs.c:2024
RETURN_SKIP
#define RETURN_SKIP(explanation)
Definition: task.h:262
CREATE_TIMEOUT
#define CREATE_TIMEOUT
Definition: test-fs-event.c:46
handle
static csh handle
Definition: test_arm_regression.c:16
uv_handle_s
Definition: uv.h:441
timer_cb_called
static int timer_cb_called
Definition: test-fs-event.c:57
uv_timer_start
UV_EXTERN int uv_timer_start(uv_timer_t *handle, uv_timer_cb cb, uint64_t timeout, uint64_t repeat)
Definition: timer.c:66
uv_loop_s
Definition: uv.h:1767
len
int len
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:46
uv_timer_init
UV_EXTERN int uv_timer_init(uv_loop_t *, uv_timer_t *handle)
Definition: timer.c:58
uv_fs_event_init
UV_EXTERN int uv_fs_event_init(uv_loop_t *loop, uv_fs_event_t *handle)
Definition: aix.c:717
timer_cb_touch
static void timer_cb_touch(uv_timer_t *timer)
Definition: test-fs-event.c:381
TEST_IMPL
TEST_IMPL(fs_event_watch_dir)
Definition: test-fs-event.c:424
getenv
#define getenv(ptr)
Definition: ares_private.h:106
timer_cb_touch_called
static int timer_cb_touch_called
Definition: test-fs-event.c:67
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
timer_cb
static void timer_cb(uv_timer_t *handle)
Definition: test-fs-event.c:853
create_file
static void create_file(const char *name)
Definition: test-fs-event.c:85


grpc
Author(s):
autogenerated on Fri May 16 2025 03:00:26