|
160
|
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 static uv_fs_event_t fs_event;
|
|
|
33 static const char file_prefix[] = "fsevent-";
|
|
|
34 static const int fs_event_file_count = 16;
|
|
|
35 #if (defined(__APPLE__) && !defined(__TSAN__)) || defined(_WIN32)
|
|
|
36 static const char file_prefix_in_subdir[] = "subdir";
|
|
|
37 static int fs_multievent_cb_called;
|
|
|
38 #endif
|
|
|
39 static uv_timer_t timer;
|
|
|
40 static int timer_cb_called;
|
|
|
41 static int close_cb_called;
|
|
|
42 static int fs_event_created;
|
|
|
43 static int fs_event_removed;
|
|
|
44 static int fs_event_cb_called;
|
|
|
45 #if defined(PATH_MAX)
|
|
|
46 static char fs_event_filename[PATH_MAX];
|
|
|
47 #else
|
|
|
48 static char fs_event_filename[1024];
|
|
|
49 #endif /* defined(PATH_MAX) */
|
|
|
50 static int timer_cb_touch_called;
|
|
|
51 static int timer_cb_exact_called;
|
|
|
52
|
|
|
53 static void fs_event_fail(uv_fs_event_t* handle,
|
|
|
54 const char* filename,
|
|
|
55 int events,
|
|
|
56 int status) {
|
|
|
57 ASSERT(0 && "should never be called");
|
|
|
58 }
|
|
|
59
|
|
|
60 static void create_dir(const char* name) {
|
|
|
61 int r;
|
|
|
62 uv_fs_t req;
|
|
|
63 r = uv_fs_mkdir(NULL, &req, name, 0755, NULL);
|
|
|
64 ASSERT(r == 0 || r == UV_EEXIST);
|
|
|
65 uv_fs_req_cleanup(&req);
|
|
|
66 }
|
|
|
67
|
|
|
68 static void create_file(const char* name) {
|
|
|
69 int r;
|
|
|
70 uv_file file;
|
|
|
71 uv_fs_t req;
|
|
|
72
|
|
|
73 r = uv_fs_open(NULL, &req, name, UV_FS_O_WRONLY | UV_FS_O_CREAT,
|
|
|
74 S_IWUSR | S_IRUSR,
|
|
|
75 NULL);
|
|
|
76 ASSERT_GE(r, 0);
|
|
|
77 file = r;
|
|
|
78 uv_fs_req_cleanup(&req);
|
|
|
79 r = uv_fs_close(NULL, &req, file, NULL);
|
|
|
80 ASSERT_OK(r);
|
|
|
81 uv_fs_req_cleanup(&req);
|
|
|
82 }
|
|
|
83
|
|
|
84 static int delete_dir(const char* name) {
|
|
|
85 int r;
|
|
|
86 uv_fs_t req;
|
|
|
87 r = uv_fs_rmdir(NULL, &req, name, NULL);
|
|
|
88 uv_fs_req_cleanup(&req);
|
|
|
89 return r;
|
|
|
90 }
|
|
|
91
|
|
|
92 static int delete_file(const char* name) {
|
|
|
93 int r;
|
|
|
94 uv_fs_t req;
|
|
|
95 r = uv_fs_unlink(NULL, &req, name, NULL);
|
|
|
96 uv_fs_req_cleanup(&req);
|
|
|
97 return r;
|
|
|
98 }
|
|
|
99
|
|
|
100 static void touch_file(const char* name) {
|
|
|
101 int r;
|
|
|
102 uv_file file;
|
|
|
103 uv_fs_t req;
|
|
|
104 uv_buf_t buf;
|
|
|
105
|
|
|
106 r = uv_fs_open(NULL, &req, name, UV_FS_O_RDWR, 0, NULL);
|
|
|
107 ASSERT_GE(r, 0);
|
|
|
108 file = r;
|
|
|
109 uv_fs_req_cleanup(&req);
|
|
|
110
|
|
|
111 buf = uv_buf_init("foo", 4);
|
|
|
112 r = uv_fs_write(NULL, &req, file, &buf, 1, -1, NULL);
|
|
|
113 ASSERT_GE(r, 0);
|
|
|
114 uv_fs_req_cleanup(&req);
|
|
|
115
|
|
|
116 r = uv_fs_close(NULL, &req, file, NULL);
|
|
|
117 ASSERT_OK(r);
|
|
|
118 uv_fs_req_cleanup(&req);
|
|
|
119 }
|
|
|
120
|
|
|
121 static void close_cb(uv_handle_t* handle) {
|
|
|
122 ASSERT_NOT_NULL(handle);
|
|
|
123 close_cb_called++;
|
|
|
124 }
|
|
|
125
|
|
|
126 static void fail_cb(uv_fs_event_t* handle,
|
|
|
127 const char* path,
|
|
|
128 int events,
|
|
|
129 int status) {
|
|
|
130 ASSERT(0 && "fail_cb called");
|
|
|
131 }
|
|
|
132
|
|
|
133 static void fs_event_cb_dir(uv_fs_event_t* handle, const char* filename,
|
|
|
134 int events, int status) {
|
|
|
135 ++fs_event_cb_called;
|
|
|
136 ASSERT_PTR_EQ(handle, &fs_event);
|
|
|
137 ASSERT_OK(status);
|
|
|
138 ASSERT_EQ(events, UV_CHANGE);
|
|
|
139 #if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
|
|
|
140 ASSERT_OK(strcmp(filename, "file1"));
|
|
|
141 #else
|
|
|
142 ASSERT(filename == NULL || strcmp(filename, "file1") == 0);
|
|
|
143 #endif
|
|
|
144 ASSERT_OK(uv_fs_event_stop(handle));
|
|
|
145 uv_close((uv_handle_t*)handle, close_cb);
|
|
|
146 }
|
|
|
147
|
|
|
148 static void fs_event_cb_del_dir(uv_fs_event_t* handle,
|
|
|
149 const char* filename,
|
|
|
150 int events,
|
|
|
151 int status) {
|
|
|
152 ++fs_event_cb_called;
|
|
|
153 ASSERT_PTR_EQ(handle, &fs_event);
|
|
|
154 ASSERT_OK(status);
|
|
|
155 ASSERT(events == UV_CHANGE || events == UV_RENAME);
|
|
|
156 /* There is a bug in the FreeBSD kernel where the filename is sometimes NULL.
|
|
|
157 * Refs: https://github.com/libuv/libuv/issues/4606
|
|
|
158 */
|
|
|
159 #if defined(__FreeBSD__)
|
|
|
160 ASSERT(filename == NULL || strcmp(filename, "watch_del_dir") == 0);
|
|
|
161 #else
|
|
|
162 ASSERT_OK(strcmp(filename, "watch_del_dir"));
|
|
|
163 #endif
|
|
|
164 ASSERT_OK(uv_fs_event_stop(handle));
|
|
|
165 uv_close((uv_handle_t*)handle, close_cb);
|
|
|
166 }
|
|
|
167
|
|
|
168 static const char* fs_event_get_filename(int i) {
|
|
|
169 snprintf(fs_event_filename,
|
|
|
170 sizeof(fs_event_filename),
|
|
|
171 "watch_dir/%s%d",
|
|
|
172 file_prefix,
|
|
|
173 i);
|
|
|
174 return fs_event_filename;
|
|
|
175 }
|
|
|
176
|
|
|
177 static void fs_event_create_files(uv_timer_t* handle) {
|
|
|
178 /* Make sure we're not attempting to create files we do not intend */
|
|
|
179 ASSERT_LT(fs_event_created, fs_event_file_count);
|
|
|
180
|
|
|
181 /* Create the file */
|
|
|
182 create_file(fs_event_get_filename(fs_event_created));
|
|
|
183
|
|
|
184 if (++fs_event_created < fs_event_file_count) {
|
|
|
185 /* Create another file on a different event loop tick. We do it this way
|
|
|
186 * to avoid fs events coalescing into one fs event. */
|
|
|
187 ASSERT_OK(uv_timer_start(&timer, fs_event_create_files, 100, 0));
|
|
|
188 }
|
|
|
189 }
|
|
|
190
|
|
|
191 static void fs_event_del_dir(uv_timer_t* handle) {
|
|
|
192 int r;
|
|
|
193
|
|
|
194 r = delete_dir("watch_del_dir");
|
|
|
195 ASSERT_OK(r);
|
|
|
196
|
|
|
197 uv_close((uv_handle_t*)handle, close_cb);
|
|
|
198 }
|
|
|
199
|
|
|
200 static void fs_event_unlink_files(uv_timer_t* handle) {
|
|
|
201 int r;
|
|
|
202 int i;
|
|
|
203
|
|
|
204 /* NOTE: handle might be NULL if invoked not as timer callback */
|
|
|
205 if (handle == NULL) {
|
|
|
206 /* Unlink all files */
|
|
|
207 for (i = 0; i < 16; i++) {
|
|
|
208 r = delete_file(fs_event_get_filename(i));
|
|
|
209 if (handle != NULL)
|
|
|
210 ASSERT_OK(r);
|
|
|
211 }
|
|
|
212 } else {
|
|
|
213 /* Make sure we're not attempting to remove files we do not intend */
|
|
|
214 ASSERT_LT(fs_event_removed, fs_event_file_count);
|
|
|
215
|
|
|
216 /* Remove the file */
|
|
|
217 ASSERT_OK(delete_file(fs_event_get_filename(fs_event_removed)));
|
|
|
218
|
|
|
219 if (++fs_event_removed < fs_event_file_count) {
|
|
|
220 /* Remove another file on a different event loop tick. We do it this way
|
|
|
221 * to avoid fs events coalescing into one fs event. */
|
|
|
222 ASSERT_OK(uv_timer_start(&timer, fs_event_unlink_files, 1, 0));
|
|
|
223 }
|
|
|
224 }
|
|
|
225 }
|
|
|
226
|
|
|
227 static void fs_event_cb_dir_multi_file(uv_fs_event_t* handle,
|
|
|
228 const char* filename,
|
|
|
229 int events,
|
|
|
230 int status) {
|
|
|
231 fs_event_cb_called++;
|
|
|
232 ASSERT_PTR_EQ(handle, &fs_event);
|
|
|
233 ASSERT_OK(status);
|
|
|
234 ASSERT(events == UV_CHANGE || events == UV_RENAME);
|
|
|
235 #if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
|
|
|
236 ASSERT_NOT_NULL(filename);
|
|
|
237 ASSERT_MEM_EQ(filename, file_prefix, sizeof(file_prefix) - 1);
|
|
|
238 #else
|
|
|
239 if (filename != NULL)
|
|
|
240 ASSERT_MEM_EQ(filename, file_prefix, sizeof(file_prefix) - 1);
|
|
|
241 #endif
|
|
|
242
|
|
|
243 if (fs_event_created + fs_event_removed == fs_event_file_count) {
|
|
|
244 /* Once we've processed all create events, delete all files */
|
|
|
245 ASSERT_OK(uv_timer_start(&timer, fs_event_unlink_files, 1, 0));
|
|
|
246 } else if (fs_event_cb_called == 2 * fs_event_file_count) {
|
|
|
247 /* Once we've processed all create and delete events, stop watching */
|
|
|
248 uv_close((uv_handle_t*) &timer, close_cb);
|
|
|
249 uv_close((uv_handle_t*) handle, close_cb);
|
|
|
250 }
|
|
|
251 }
|
|
|
252
|
|
|
253 #if (defined(__APPLE__) && !defined(__TSAN__)) || defined(_WIN32)
|
|
|
254 static const char* fs_event_get_filename_in_subdir(int i) {
|
|
|
255 snprintf(fs_event_filename,
|
|
|
256 sizeof(fs_event_filename),
|
|
|
257 "watch_dir/subdir/%s%d",
|
|
|
258 file_prefix,
|
|
|
259 i);
|
|
|
260 return fs_event_filename;
|
|
|
261 }
|
|
|
262
|
|
|
263 static void fs_event_create_files_in_subdir(uv_timer_t* handle) {
|
|
|
264 /* Make sure we're not attempting to create files we do not intend */
|
|
|
265 ASSERT_LT(fs_event_created, fs_event_file_count);
|
|
|
266
|
|
|
267 /* Create the file */
|
|
|
268 create_file(fs_event_get_filename_in_subdir(fs_event_created));
|
|
|
269
|
|
|
270 if (++fs_event_created < fs_event_file_count) {
|
|
|
271 /* Create another file on a different event loop tick. We do it this way
|
|
|
272 * to avoid fs events coalescing into one fs event. */
|
|
|
273 ASSERT_OK(uv_timer_start(&timer, fs_event_create_files_in_subdir, 100, 0));
|
|
|
274 }
|
|
|
275 }
|
|
|
276
|
|
|
277 static void fs_event_unlink_files_in_subdir(uv_timer_t* handle) {
|
|
|
278 int r;
|
|
|
279 int i;
|
|
|
280
|
|
|
281 /* NOTE: handle might be NULL if invoked not as timer callback */
|
|
|
282 if (handle == NULL) {
|
|
|
283 /* Unlink all files */
|
|
|
284 for (i = 0; i < 16; i++) {
|
|
|
285 r = delete_file(fs_event_get_filename_in_subdir(i));
|
|
|
286 if (handle != NULL)
|
|
|
287 ASSERT_OK(r);
|
|
|
288 }
|
|
|
289 } else {
|
|
|
290 /* Make sure we're not attempting to remove files we do not intend */
|
|
|
291 ASSERT_LT(fs_event_removed, fs_event_file_count);
|
|
|
292
|
|
|
293 /* Remove the file */
|
|
|
294 ASSERT_OK(delete_file(fs_event_get_filename_in_subdir(fs_event_removed)));
|
|
|
295
|
|
|
296 if (++fs_event_removed < fs_event_file_count) {
|
|
|
297 /* Remove another file on a different event loop tick. We do it this way
|
|
|
298 * to avoid fs events coalescing into one fs event. */
|
|
|
299 ASSERT_OK(uv_timer_start(&timer,
|
|
|
300 fs_event_unlink_files_in_subdir,
|
|
|
301 1,
|
|
|
302 0));
|
|
|
303 }
|
|
|
304 }
|
|
|
305 }
|
|
|
306
|
|
|
307 static void fs_event_cb_dir_multi_file_in_subdir(uv_fs_event_t* handle,
|
|
|
308 const char* filename,
|
|
|
309 int events,
|
|
|
310 int status) {
|
|
|
311 #ifdef _WIN32
|
|
|
312 /* Each file created (or deleted) will cause this callback to be called twice
|
|
|
313 * under Windows: once with the name of the file, and second time with the
|
|
|
314 * name of the directory. We will ignore the callback for the directory
|
|
|
315 * itself. */
|
|
|
316 if (filename && strcmp(filename, file_prefix_in_subdir) == 0)
|
|
|
317 return;
|
|
|
318 #endif
|
|
|
319 /* It may happen that the "subdir" creation event is captured even though
|
|
|
320 * we started watching after its actual creation.
|
|
|
321 */
|
|
|
322 if (strcmp(filename, "subdir") == 0)
|
|
|
323 return;
|
|
|
324
|
|
|
325 fs_multievent_cb_called++;
|
|
|
326 ASSERT_PTR_EQ(handle, &fs_event);
|
|
|
327 ASSERT_OK(status);
|
|
|
328 ASSERT(events == UV_CHANGE || events == UV_RENAME);
|
|
|
329 #if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
|
|
|
330 ASSERT_OK(strncmp(filename,
|
|
|
331 file_prefix_in_subdir,
|
|
|
332 sizeof(file_prefix_in_subdir) - 1));
|
|
|
333 #else
|
|
|
334 ASSERT_NE(filename == NULL ||
|
|
|
335 strncmp(filename,
|
|
|
336 file_prefix_in_subdir,
|
|
|
337 sizeof(file_prefix_in_subdir) - 1) == 0, 0);
|
|
|
338 #endif
|
|
|
339
|
|
|
340 if (fs_event_created == fs_event_file_count &&
|
|
|
341 fs_multievent_cb_called == fs_event_created) {
|
|
|
342 /* Once we've processed all create events, delete all files */
|
|
|
343 ASSERT_OK(uv_timer_start(&timer,
|
|
|
344 fs_event_unlink_files_in_subdir,
|
|
|
345 1,
|
|
|
346 0));
|
|
|
347 } else if (fs_multievent_cb_called == 2 * fs_event_file_count) {
|
|
|
348 /* Once we've processed all create and delete events, stop watching */
|
|
|
349 ASSERT_EQ(fs_event_removed, fs_event_file_count);
|
|
|
350 uv_close((uv_handle_t*) &timer, close_cb);
|
|
|
351 uv_close((uv_handle_t*) handle, close_cb);
|
|
|
352 }
|
|
|
353 }
|
|
|
354 #endif
|
|
|
355
|
|
|
356 static void fs_event_cb_file(uv_fs_event_t* handle, const char* filename,
|
|
|
357 int events, int status) {
|
|
|
358 ++fs_event_cb_called;
|
|
|
359 ASSERT_PTR_EQ(handle, &fs_event);
|
|
|
360 ASSERT_OK(status);
|
|
|
361 ASSERT_EQ(events, UV_CHANGE);
|
|
|
362 #if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
|
|
|
363 ASSERT_OK(strcmp(filename, "file2"));
|
|
|
364 #else
|
|
|
365 ASSERT(filename == NULL || strcmp(filename, "file2") == 0);
|
|
|
366 #endif
|
|
|
367 ASSERT_OK(uv_fs_event_stop(handle));
|
|
|
368 uv_close((uv_handle_t*)handle, close_cb);
|
|
|
369 }
|
|
|
370
|
|
|
371 static void fs_event_cb_file_current_dir(uv_fs_event_t* handle,
|
|
|
372 const char* filename, int events, int status) {
|
|
|
373 ++fs_event_cb_called;
|
|
|
374
|
|
|
375 ASSERT_PTR_EQ(handle, &fs_event);
|
|
|
376 ASSERT_OK(status);
|
|
|
377 ASSERT_EQ(events, UV_CHANGE);
|
|
|
378 #if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
|
|
|
379 ASSERT_OK(strcmp(filename, "watch_file"));
|
|
|
380 #else
|
|
|
381 ASSERT(filename == NULL || strcmp(filename, "watch_file") == 0);
|
|
|
382 #endif
|
|
|
383
|
|
|
384 uv_close((uv_handle_t*)handle, close_cb);
|
|
|
385 }
|
|
|
386
|
|
|
387 static void timer_cb_file(uv_timer_t* handle) {
|
|
|
388 ++timer_cb_called;
|
|
|
389
|
|
|
390 if (timer_cb_called == 1) {
|
|
|
391 touch_file("watch_dir/file1");
|
|
|
392 } else {
|
|
|
393 touch_file("watch_dir/file2");
|
|
|
394 uv_close((uv_handle_t*)handle, close_cb);
|
|
|
395 }
|
|
|
396 }
|
|
|
397
|
|
|
398 static void timer_cb_touch(uv_timer_t* timer) {
|
|
|
399 uv_close((uv_handle_t*)timer, NULL);
|
|
|
400 touch_file((char*) timer->data);
|
|
|
401 timer_cb_touch_called++;
|
|
|
402 }
|
|
|
403
|
|
|
404 static void timer_cb_exact(uv_timer_t* handle) {
|
|
|
405 int r;
|
|
|
406
|
|
|
407 if (timer_cb_exact_called == 0) {
|
|
|
408 touch_file("watch_dir/file.js");
|
|
|
409 } else {
|
|
|
410 uv_close((uv_handle_t*)handle, NULL);
|
|
|
411 r = uv_fs_event_stop(&fs_event);
|
|
|
412 ASSERT_OK(r);
|
|
|
413 uv_close((uv_handle_t*) &fs_event, NULL);
|
|
|
414 }
|
|
|
415
|
|
|
416 ++timer_cb_exact_called;
|
|
|
417 }
|
|
|
418
|
|
|
419 static void timer_cb_watch_twice(uv_timer_t* handle) {
|
|
|
420 uv_fs_event_t* handles = handle->data;
|
|
|
421 uv_close((uv_handle_t*) (handles + 0), NULL);
|
|
|
422 uv_close((uv_handle_t*) (handles + 1), NULL);
|
|
|
423 uv_close((uv_handle_t*) handle, NULL);
|
|
|
424 }
|
|
|
425
|
|
|
426 static void fs_event_cb_close(uv_fs_event_t* handle,
|
|
|
427 const char* filename,
|
|
|
428 int events,
|
|
|
429 int status) {
|
|
|
430 ASSERT_OK(status);
|
|
|
431
|
|
|
432 ASSERT_LT(fs_event_cb_called, 3);
|
|
|
433 ++fs_event_cb_called;
|
|
|
434
|
|
|
435 if (fs_event_cb_called == 3) {
|
|
|
436 uv_close((uv_handle_t*) handle, close_cb);
|
|
|
437 }
|
|
|
438 }
|
|
|
439
|
|
|
440
|
|
|
441 TEST_IMPL(fs_event_watch_dir) {
|
|
|
442 #if defined(NO_FS_EVENTS)
|
|
|
443 RETURN_SKIP(NO_FS_EVENTS);
|
|
|
444 #elif defined(__MVS__)
|
|
|
445 RETURN_SKIP("Directory watching not supported on this platform.");
|
|
|
446 #elif defined(__APPLE__) && defined(__TSAN__)
|
|
|
447 RETURN_SKIP("Times out under TSAN.");
|
|
|
448 #endif
|
|
|
449
|
|
|
450 uv_loop_t* loop = uv_default_loop();
|
|
|
451 int r;
|
|
|
452
|
|
|
453 /* Setup */
|
|
|
454 fs_event_unlink_files(NULL);
|
|
|
455 delete_file("watch_dir/file2");
|
|
|
456 delete_file("watch_dir/file1");
|
|
|
457 delete_dir("watch_dir/");
|
|
|
458 create_dir("watch_dir");
|
|
|
459
|
|
|
460 r = uv_fs_event_init(loop, &fs_event);
|
|
|
461 ASSERT_OK(r);
|
|
|
462 r = uv_fs_event_start(&fs_event, fs_event_cb_dir_multi_file, "watch_dir", 0);
|
|
|
463 ASSERT_OK(r);
|
|
|
464 r = uv_timer_init(loop, &timer);
|
|
|
465 ASSERT_OK(r);
|
|
|
466 r = uv_timer_start(&timer, fs_event_create_files, 100, 0);
|
|
|
467 ASSERT_OK(r);
|
|
|
468
|
|
|
469 uv_run(loop, UV_RUN_DEFAULT);
|
|
|
470
|
|
|
471 ASSERT_EQ(fs_event_cb_called, fs_event_created + fs_event_removed);
|
|
|
472 ASSERT_EQ(2, close_cb_called);
|
|
|
473
|
|
|
474 /* Cleanup */
|
|
|
475 fs_event_unlink_files(NULL);
|
|
|
476 delete_file("watch_dir/file2");
|
|
|
477 delete_file("watch_dir/file1");
|
|
|
478 delete_dir("watch_dir/");
|
|
|
479
|
|
|
480 MAKE_VALGRIND_HAPPY(loop);
|
|
|
481 return 0;
|
|
|
482 }
|
|
|
483
|
|
|
484 TEST_IMPL(fs_event_watch_delete_dir) {
|
|
|
485 #if defined(NO_FS_EVENTS)
|
|
|
486 RETURN_SKIP(NO_FS_EVENTS);
|
|
|
487 #elif defined(__MVS__)
|
|
|
488 RETURN_SKIP("Directory watching not supported on this platform.");
|
|
|
489 #elif defined(__APPLE__) && defined(__TSAN__)
|
|
|
490 RETURN_SKIP("Times out under TSAN.");
|
|
|
491 #endif
|
|
|
492
|
|
|
493 uv_loop_t* loop = uv_default_loop();
|
|
|
494 int r;
|
|
|
495
|
|
|
496 /* Setup */
|
|
|
497 fs_event_unlink_files(NULL);
|
|
|
498 delete_dir("watch_del_dir/");
|
|
|
499 create_dir("watch_del_dir");
|
|
|
500
|
|
|
501 r = uv_fs_event_init(loop, &fs_event);
|
|
|
502 ASSERT_OK(r);
|
|
|
503 r = uv_fs_event_start(&fs_event, fs_event_cb_del_dir, "watch_del_dir", 0);
|
|
|
504 ASSERT_OK(r);
|
|
|
505 r = uv_timer_init(loop, &timer);
|
|
|
506 ASSERT_OK(r);
|
|
|
507 r = uv_timer_start(&timer, fs_event_del_dir, 100, 0);
|
|
|
508 ASSERT_OK(r);
|
|
|
509
|
|
|
510 uv_run(loop, UV_RUN_DEFAULT);
|
|
|
511
|
|
|
512 ASSERT_EQ(1, fs_event_cb_called);
|
|
|
513 ASSERT_EQ(2, close_cb_called);
|
|
|
514
|
|
|
515 /* Cleanup */
|
|
|
516 fs_event_unlink_files(NULL);
|
|
|
517
|
|
|
518 MAKE_VALGRIND_HAPPY(loop);
|
|
|
519 return 0;
|
|
|
520 }
|
|
|
521
|
|
|
522
|
|
|
523 TEST_IMPL(fs_event_watch_dir_recursive) {
|
|
|
524 #if defined(__APPLE__) && defined(__TSAN__)
|
|
|
525 RETURN_SKIP("Times out under TSAN.");
|
|
|
526 #elif defined(__APPLE__) || defined(_WIN32)
|
|
|
527 uv_loop_t* loop;
|
|
|
528 int r;
|
|
|
529 uv_fs_event_t fs_event_root;
|
|
|
530
|
|
|
531 /* Setup */
|
|
|
532 loop = uv_default_loop();
|
|
|
533 fs_event_unlink_files(NULL);
|
|
|
534 delete_file("watch_dir/file2");
|
|
|
535 delete_file("watch_dir/file1");
|
|
|
536 delete_dir("watch_dir/subdir");
|
|
|
537 delete_dir("watch_dir/");
|
|
|
538 create_dir("watch_dir");
|
|
|
539 create_dir("watch_dir/subdir");
|
|
|
540
|
|
|
541 r = uv_fs_event_init(loop, &fs_event);
|
|
|
542 ASSERT_OK(r);
|
|
|
543 r = uv_fs_event_start(&fs_event,
|
|
|
544 fs_event_cb_dir_multi_file_in_subdir,
|
|
|
545 "watch_dir",
|
|
|
546 UV_FS_EVENT_RECURSIVE);
|
|
|
547 ASSERT_OK(r);
|
|
|
548 r = uv_timer_init(loop, &timer);
|
|
|
549 ASSERT_OK(r);
|
|
|
550 r = uv_timer_start(&timer, fs_event_create_files_in_subdir, 100, 0);
|
|
|
551 ASSERT_OK(r);
|
|
|
552
|
|
|
553 #ifndef _WIN32
|
|
|
554 /* Also try to watch the root directory.
|
|
|
555 * This will be noisier, so we're just checking for any couple events to happen. */
|
|
|
556 r = uv_fs_event_init(loop, &fs_event_root);
|
|
|
557 ASSERT_OK(r);
|
|
|
558 r = uv_fs_event_start(&fs_event_root,
|
|
|
559 fs_event_cb_close,
|
|
|
560 "/",
|
|
|
561 UV_FS_EVENT_RECURSIVE);
|
|
|
562 ASSERT_OK(r);
|
|
|
563 #else
|
|
|
564 fs_event_cb_called += 3;
|
|
|
565 close_cb_called += 1;
|
|
|
566 (void)fs_event_root;
|
|
|
567 #endif
|
|
|
568
|
|
|
569 uv_run(loop, UV_RUN_DEFAULT);
|
|
|
570
|
|
|
571 ASSERT_EQ(fs_multievent_cb_called, fs_event_created + fs_event_removed);
|
|
|
572 ASSERT_EQ(3, fs_event_cb_called);
|
|
|
573 ASSERT_EQ(3, close_cb_called);
|
|
|
574
|
|
|
575 /* Cleanup */
|
|
|
576 fs_event_unlink_files_in_subdir(NULL);
|
|
|
577 delete_file("watch_dir/file2");
|
|
|
578 delete_file("watch_dir/file1");
|
|
|
579 delete_dir("watch_dir/subdir");
|
|
|
580 delete_dir("watch_dir/");
|
|
|
581
|
|
|
582 MAKE_VALGRIND_HAPPY(loop);
|
|
|
583 return 0;
|
|
|
584 #else
|
|
|
585 RETURN_SKIP("Recursive directory watching not supported on this platform.");
|
|
|
586 #endif
|
|
|
587 }
|
|
|
588
|
|
|
589 #ifdef _WIN32
|
|
|
590 TEST_IMPL(fs_event_watch_dir_short_path) {
|
|
|
591 uv_loop_t* loop;
|
|
|
592 uv_fs_t req;
|
|
|
593 int has_shortnames;
|
|
|
594 int r;
|
|
|
595
|
|
|
596 /* Setup */
|
|
|
597 loop = uv_default_loop();
|
|
|
598 delete_file("watch_dir/file1");
|
|
|
599 delete_dir("watch_dir/");
|
|
|
600 create_dir("watch_dir");
|
|
|
601 create_file("watch_dir/file1");
|
|
|
602
|
|
|
603 /* Newer version of Windows ship with
|
|
|
604 HKLM\SYSTEM\CurrentControlSet\Control\FileSystem\NtfsDisable8dot3NameCreation
|
|
|
605 not equal to 0. So we verify the files we created are addressable by a 8.3
|
|
|
606 short name */
|
|
|
607 has_shortnames = uv_fs_stat(NULL, &req, "watch_~1", NULL) != UV_ENOENT;
|
|
|
608 if (has_shortnames) {
|
|
|
609 r = uv_fs_event_init(loop, &fs_event);
|
|
|
610 ASSERT_OK(r);
|
|
|
611 r = uv_fs_event_start(&fs_event, fs_event_cb_dir, "watch_~1", 0);
|
|
|
612 ASSERT_OK(r);
|
|
|
613 r = uv_timer_init(loop, &timer);
|
|
|
614 ASSERT_OK(r);
|
|
|
615 r = uv_timer_start(&timer, timer_cb_file, 100, 0);
|
|
|
616 ASSERT_OK(r);
|
|
|
617
|
|
|
618 uv_run(loop, UV_RUN_DEFAULT);
|
|
|
619
|
|
|
620 ASSERT_EQ(1, fs_event_cb_called);
|
|
|
621 ASSERT_EQ(1, timer_cb_called);
|
|
|
622 ASSERT_EQ(1, close_cb_called);
|
|
|
623 }
|
|
|
624
|
|
|
625 /* Cleanup */
|
|
|
626 delete_file("watch_dir/file1");
|
|
|
627 delete_dir("watch_dir/");
|
|
|
628
|
|
|
629 MAKE_VALGRIND_HAPPY(loop);
|
|
|
630
|
|
|
631 if (!has_shortnames)
|
|
|
632 RETURN_SKIP("Was not able to address files with 8.3 short name.");
|
|
|
633
|
|
|
634 return 0;
|
|
|
635 }
|
|
|
636 #endif
|
|
|
637
|
|
|
638
|
|
|
639 TEST_IMPL(fs_event_watch_file) {
|
|
|
640 #if defined(NO_FS_EVENTS)
|
|
|
641 RETURN_SKIP(NO_FS_EVENTS);
|
|
|
642 #endif
|
|
|
643
|
|
|
644 uv_loop_t* loop = uv_default_loop();
|
|
|
645 int r;
|
|
|
646
|
|
|
647 /* Setup */
|
|
|
648 delete_file("watch_dir/file2");
|
|
|
649 delete_file("watch_dir/file1");
|
|
|
650 delete_dir("watch_dir/");
|
|
|
651 create_dir("watch_dir");
|
|
|
652 create_file("watch_dir/file1");
|
|
|
653 create_file("watch_dir/file2");
|
|
|
654
|
|
|
655 r = uv_fs_event_init(loop, &fs_event);
|
|
|
656 ASSERT_OK(r);
|
|
|
657 r = uv_fs_event_start(&fs_event, fs_event_cb_file, "watch_dir/file2", 0);
|
|
|
658 ASSERT_OK(r);
|
|
|
659 r = uv_timer_init(loop, &timer);
|
|
|
660 ASSERT_OK(r);
|
|
|
661 r = uv_timer_start(&timer, timer_cb_file, 100, 100);
|
|
|
662 ASSERT_OK(r);
|
|
|
663
|
|
|
664 uv_run(loop, UV_RUN_DEFAULT);
|
|
|
665
|
|
|
666 ASSERT_EQ(1, fs_event_cb_called);
|
|
|
667 ASSERT_EQ(2, timer_cb_called);
|
|
|
668 ASSERT_EQ(2, close_cb_called);
|
|
|
669
|
|
|
670 /* Cleanup */
|
|
|
671 delete_file("watch_dir/file2");
|
|
|
672 delete_file("watch_dir/file1");
|
|
|
673 delete_dir("watch_dir/");
|
|
|
674
|
|
|
675 MAKE_VALGRIND_HAPPY(loop);
|
|
|
676 return 0;
|
|
|
677 }
|
|
|
678
|
|
|
679 TEST_IMPL(fs_event_watch_file_exact_path) {
|
|
|
680 /*
|
|
|
681 This test watches a file named "file.jsx" and modifies a file named
|
|
|
682 "file.js". The test verifies that no events occur for file.jsx.
|
|
|
683 */
|
|
|
684
|
|
|
685 #if defined(NO_FS_EVENTS)
|
|
|
686 RETURN_SKIP(NO_FS_EVENTS);
|
|
|
687 #endif
|
|
|
688
|
|
|
689 uv_loop_t* loop;
|
|
|
690 int r;
|
|
|
691
|
|
|
692 loop = uv_default_loop();
|
|
|
693
|
|
|
694 /* Setup */
|
|
|
695 delete_file("watch_dir/file.js");
|
|
|
696 delete_file("watch_dir/file.jsx");
|
|
|
697 delete_dir("watch_dir/");
|
|
|
698 create_dir("watch_dir");
|
|
|
699 create_file("watch_dir/file.js");
|
|
|
700 create_file("watch_dir/file.jsx");
|
|
|
701 #if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_12)
|
|
|
702 /* Empirically, FSEvents seems to (reliably) report the preceding
|
|
|
703 * create_file events prior to macOS 10.11.6 in the subsequent fs_watch
|
|
|
704 * creation, but that behavior hasn't been observed to occur on newer
|
|
|
705 * versions. Give a long delay here to let the system settle before running
|
|
|
706 * the test. */
|
|
|
707 uv_sleep(1100);
|
|
|
708 uv_update_time(loop);
|
|
|
709 #endif
|
|
|
710
|
|
|
711 r = uv_fs_event_init(loop, &fs_event);
|
|
|
712 ASSERT_OK(r);
|
|
|
713 r = uv_fs_event_start(&fs_event, fs_event_fail, "watch_dir/file.jsx", 0);
|
|
|
714 ASSERT_OK(r);
|
|
|
715 r = uv_timer_init(loop, &timer);
|
|
|
716 ASSERT_OK(r);
|
|
|
717 r = uv_timer_start(&timer, timer_cb_exact, 100, 100);
|
|
|
718 ASSERT_OK(r);
|
|
|
719 r = uv_run(loop, UV_RUN_DEFAULT);
|
|
|
720 ASSERT_OK(r);
|
|
|
721 ASSERT_EQ(2, timer_cb_exact_called);
|
|
|
722
|
|
|
723 /* Cleanup */
|
|
|
724 delete_file("watch_dir/file.js");
|
|
|
725 delete_file("watch_dir/file.jsx");
|
|
|
726 delete_dir("watch_dir/");
|
|
|
727
|
|
|
728 MAKE_VALGRIND_HAPPY(loop);
|
|
|
729 return 0;
|
|
|
730 }
|
|
|
731
|
|
|
732 TEST_IMPL(fs_event_watch_file_twice) {
|
|
|
733 #if defined(NO_FS_EVENTS)
|
|
|
734 RETURN_SKIP(NO_FS_EVENTS);
|
|
|
735 #endif
|
|
|
736 const char path[] = "test/fixtures/empty_file";
|
|
|
737 uv_fs_event_t watchers[2];
|
|
|
738 uv_timer_t timer;
|
|
|
739 uv_loop_t* loop;
|
|
|
740
|
|
|
741 loop = uv_default_loop();
|
|
|
742 timer.data = watchers;
|
|
|
743
|
|
|
744 ASSERT_OK(uv_fs_event_init(loop, watchers + 0));
|
|
|
745 ASSERT_OK(uv_fs_event_start(watchers + 0, fail_cb, path, 0));
|
|
|
746 ASSERT_OK(uv_fs_event_init(loop, watchers + 1));
|
|
|
747 ASSERT_OK(uv_fs_event_start(watchers + 1, fail_cb, path, 0));
|
|
|
748 ASSERT_OK(uv_timer_init(loop, &timer));
|
|
|
749 ASSERT_OK(uv_timer_start(&timer, timer_cb_watch_twice, 10, 0));
|
|
|
750 ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT));
|
|
|
751
|
|
|
752 MAKE_VALGRIND_HAPPY(loop);
|
|
|
753 return 0;
|
|
|
754 }
|
|
|
755
|
|
|
756 TEST_IMPL(fs_event_watch_file_current_dir) {
|
|
|
757 #if defined(NO_FS_EVENTS)
|
|
|
758 RETURN_SKIP(NO_FS_EVENTS);
|
|
|
759 #endif
|
|
|
760 uv_timer_t timer;
|
|
|
761 uv_loop_t* loop;
|
|
|
762 int r;
|
|
|
763
|
|
|
764 loop = uv_default_loop();
|
|
|
765
|
|
|
766 /* Setup */
|
|
|
767 delete_file("watch_file");
|
|
|
768 create_file("watch_file");
|
|
|
769 #if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_12)
|
|
|
770 /* Empirically, kevent seems to (sometimes) report the preceding
|
|
|
771 * create_file events prior to macOS 10.11.6 in the subsequent fs_event_start
|
|
|
772 * So let the system settle before running the test. */
|
|
|
773 uv_sleep(1100);
|
|
|
774 uv_update_time(loop);
|
|
|
775 #endif
|
|
|
776
|
|
|
777 r = uv_fs_event_init(loop, &fs_event);
|
|
|
778 ASSERT_OK(r);
|
|
|
779 r = uv_fs_event_start(&fs_event,
|
|
|
780 fs_event_cb_file_current_dir,
|
|
|
781 "watch_file",
|
|
|
782 0);
|
|
|
783 ASSERT_OK(r);
|
|
|
784
|
|
|
785
|
|
|
786 r = uv_timer_init(loop, &timer);
|
|
|
787 ASSERT_OK(r);
|
|
|
788
|
|
|
789 timer.data = "watch_file";
|
|
|
790 r = uv_timer_start(&timer, timer_cb_touch, 1100, 0);
|
|
|
791 ASSERT_OK(r);
|
|
|
792
|
|
|
793 ASSERT_OK(timer_cb_touch_called);
|
|
|
794 ASSERT_OK(fs_event_cb_called);
|
|
|
795 ASSERT_OK(close_cb_called);
|
|
|
796
|
|
|
797 uv_run(loop, UV_RUN_DEFAULT);
|
|
|
798
|
|
|
799 ASSERT_EQ(1, timer_cb_touch_called);
|
|
|
800 /* FSEvents on macOS sometimes sends one change event, sometimes two. */
|
|
|
801 ASSERT_NE(0, fs_event_cb_called);
|
|
|
802 ASSERT_EQ(1, close_cb_called);
|
|
|
803
|
|
|
804 /* Cleanup */
|
|
|
805 delete_file("watch_file");
|
|
|
806
|
|
|
807 MAKE_VALGRIND_HAPPY(loop);
|
|
|
808 return 0;
|
|
|
809 }
|
|
|
810
|
|
|
811 #ifdef _WIN32
|
|
|
812 TEST_IMPL(fs_event_watch_file_root_dir) {
|
|
|
813 uv_loop_t* loop;
|
|
|
814 int r;
|
|
|
815
|
|
|
816 const char* sys_drive = getenv("SystemDrive");
|
|
|
817 char path[] = "\\\\?\\X:\\bootsect.bak";
|
|
|
818
|
|
|
819 ASSERT_NOT_NULL(sys_drive);
|
|
|
820 strncpy(path + sizeof("\\\\?\\") - 1, sys_drive, 1);
|
|
|
821
|
|
|
822 loop = uv_default_loop();
|
|
|
823
|
|
|
824 r = uv_fs_event_init(loop, &fs_event);
|
|
|
825 ASSERT_OK(r);
|
|
|
826 r = uv_fs_event_start(&fs_event, fail_cb, path, 0);
|
|
|
827 if (r == UV_ENOENT)
|
|
|
828 RETURN_SKIP("bootsect.bak doesn't exist in system root.\n");
|
|
|
829 ASSERT_OK(r);
|
|
|
830
|
|
|
831 uv_close((uv_handle_t*) &fs_event, NULL);
|
|
|
832
|
|
|
833 MAKE_VALGRIND_HAPPY(loop);
|
|
|
834 return 0;
|
|
|
835 }
|
|
|
836 #endif
|
|
|
837
|
|
|
838 TEST_IMPL(fs_event_no_callback_after_close) {
|
|
|
839 #if defined(NO_FS_EVENTS)
|
|
|
840 RETURN_SKIP(NO_FS_EVENTS);
|
|
|
841 #endif
|
|
|
842
|
|
|
843 uv_loop_t* loop = uv_default_loop();
|
|
|
844 int r;
|
|
|
845
|
|
|
846 /* Setup */
|
|
|
847 delete_file("watch_dir/file1");
|
|
|
848 delete_dir("watch_dir/");
|
|
|
849 create_dir("watch_dir");
|
|
|
850 create_file("watch_dir/file1");
|
|
|
851
|
|
|
852 r = uv_fs_event_init(loop, &fs_event);
|
|
|
853 ASSERT_OK(r);
|
|
|
854 r = uv_fs_event_start(&fs_event,
|
|
|
855 fs_event_cb_file,
|
|
|
856 "watch_dir/file1",
|
|
|
857 0);
|
|
|
858 ASSERT_OK(r);
|
|
|
859
|
|
|
860
|
|
|
861 uv_close((uv_handle_t*)&fs_event, close_cb);
|
|
|
862 touch_file("watch_dir/file1");
|
|
|
863 uv_run(loop, UV_RUN_DEFAULT);
|
|
|
864
|
|
|
865 ASSERT_OK(fs_event_cb_called);
|
|
|
866 ASSERT_EQ(1, close_cb_called);
|
|
|
867
|
|
|
868 /* Cleanup */
|
|
|
869 delete_file("watch_dir/file1");
|
|
|
870 delete_dir("watch_dir/");
|
|
|
871
|
|
|
872 MAKE_VALGRIND_HAPPY(loop);
|
|
|
873 return 0;
|
|
|
874 }
|
|
|
875
|
|
|
876 TEST_IMPL(fs_event_no_callback_on_close) {
|
|
|
877 #if defined(NO_FS_EVENTS)
|
|
|
878 RETURN_SKIP(NO_FS_EVENTS);
|
|
|
879 #endif
|
|
|
880
|
|
|
881 uv_loop_t* loop = uv_default_loop();
|
|
|
882 int r;
|
|
|
883
|
|
|
884 /* Setup */
|
|
|
885 delete_file("watch_dir/file1");
|
|
|
886 delete_dir("watch_dir/");
|
|
|
887 create_dir("watch_dir");
|
|
|
888 create_file("watch_dir/file1");
|
|
|
889
|
|
|
890 r = uv_fs_event_init(loop, &fs_event);
|
|
|
891 ASSERT_OK(r);
|
|
|
892 r = uv_fs_event_start(&fs_event,
|
|
|
893 fs_event_cb_file,
|
|
|
894 "watch_dir/file1",
|
|
|
895 0);
|
|
|
896 ASSERT_OK(r);
|
|
|
897
|
|
|
898 uv_close((uv_handle_t*)&fs_event, close_cb);
|
|
|
899
|
|
|
900 uv_run(loop, UV_RUN_DEFAULT);
|
|
|
901
|
|
|
902 ASSERT_OK(fs_event_cb_called);
|
|
|
903 ASSERT_EQ(1, close_cb_called);
|
|
|
904
|
|
|
905 /* Cleanup */
|
|
|
906 delete_file("watch_dir/file1");
|
|
|
907 delete_dir("watch_dir/");
|
|
|
908
|
|
|
909 MAKE_VALGRIND_HAPPY(loop);
|
|
|
910 return 0;
|
|
|
911 }
|
|
|
912
|
|
|
913
|
|
|
914 static void timer_cb(uv_timer_t* handle) {
|
|
|
915 int r;
|
|
|
916
|
|
|
917 r = uv_fs_event_init(handle->loop, &fs_event);
|
|
|
918 ASSERT_OK(r);
|
|
|
919 r = uv_fs_event_start(&fs_event, fs_event_fail, ".", 0);
|
|
|
920 ASSERT_OK(r);
|
|
|
921
|
|
|
922 uv_close((uv_handle_t*)&fs_event, close_cb);
|
|
|
923 uv_close((uv_handle_t*)handle, close_cb);
|
|
|
924 }
|
|
|
925
|
|
|
926
|
|
|
927 TEST_IMPL(fs_event_immediate_close) {
|
|
|
928 #if defined(NO_FS_EVENTS)
|
|
|
929 RETURN_SKIP(NO_FS_EVENTS);
|
|
|
930 #endif
|
|
|
931 uv_timer_t timer;
|
|
|
932 uv_loop_t* loop;
|
|
|
933 int r;
|
|
|
934
|
|
|
935 loop = uv_default_loop();
|
|
|
936
|
|
|
937 r = uv_timer_init(loop, &timer);
|
|
|
938 ASSERT_OK(r);
|
|
|
939
|
|
|
940 r = uv_timer_start(&timer, timer_cb, 1, 0);
|
|
|
941 ASSERT_OK(r);
|
|
|
942
|
|
|
943 uv_run(loop, UV_RUN_DEFAULT);
|
|
|
944
|
|
|
945 ASSERT_EQ(2, close_cb_called);
|
|
|
946
|
|
|
947 MAKE_VALGRIND_HAPPY(loop);
|
|
|
948 return 0;
|
|
|
949 }
|
|
|
950
|
|
|
951
|
|
|
952 TEST_IMPL(fs_event_close_with_pending_event) {
|
|
|
953 #if defined(NO_FS_EVENTS)
|
|
|
954 RETURN_SKIP(NO_FS_EVENTS);
|
|
|
955 #endif
|
|
|
956 uv_loop_t* loop;
|
|
|
957 int r;
|
|
|
958
|
|
|
959 loop = uv_default_loop();
|
|
|
960
|
|
|
961 create_dir("watch_dir");
|
|
|
962 create_file("watch_dir/file");
|
|
|
963
|
|
|
964 r = uv_fs_event_init(loop, &fs_event);
|
|
|
965 ASSERT_OK(r);
|
|
|
966 r = uv_fs_event_start(&fs_event, fs_event_fail, "watch_dir", 0);
|
|
|
967 ASSERT_OK(r);
|
|
|
968
|
|
|
969 /* Generate an fs event. */
|
|
|
970 touch_file("watch_dir/file");
|
|
|
971
|
|
|
972 uv_close((uv_handle_t*)&fs_event, close_cb);
|
|
|
973
|
|
|
974 uv_run(loop, UV_RUN_DEFAULT);
|
|
|
975
|
|
|
976 ASSERT_EQ(1, close_cb_called);
|
|
|
977
|
|
|
978 /* Clean up */
|
|
|
979 delete_file("watch_dir/file");
|
|
|
980 delete_dir("watch_dir/");
|
|
|
981
|
|
|
982 MAKE_VALGRIND_HAPPY(loop);
|
|
|
983 return 0;
|
|
|
984 }
|
|
|
985
|
|
|
986 TEST_IMPL(fs_event_close_with_pending_delete_event) {
|
|
|
987 #if defined(NO_FS_EVENTS)
|
|
|
988 RETURN_SKIP(NO_FS_EVENTS);
|
|
|
989 #endif
|
|
|
990 uv_loop_t* loop;
|
|
|
991 int r;
|
|
|
992
|
|
|
993 loop = uv_default_loop();
|
|
|
994
|
|
|
995 create_dir("watch_dir");
|
|
|
996 create_file("watch_dir/file");
|
|
|
997
|
|
|
998 r = uv_fs_event_init(loop, &fs_event);
|
|
|
999 ASSERT_OK(r);
|
|
|
1000 r = uv_fs_event_start(&fs_event, fs_event_fail, "watch_dir/file", 0);
|
|
|
1001 ASSERT_OK(r);
|
|
|
1002
|
|
|
1003 /* Generate an fs event. */
|
|
|
1004 delete_file("watch_dir/file");
|
|
|
1005
|
|
|
1006 /* Allow time for the remove event to propagate to the pending list. */
|
|
|
1007 /* XXX - perhaps just for __sun? */
|
|
|
1008 uv_sleep(1100);
|
|
|
1009 uv_update_time(loop);
|
|
|
1010
|
|
|
1011 uv_close((uv_handle_t*)&fs_event, close_cb);
|
|
|
1012
|
|
|
1013 uv_run(loop, UV_RUN_DEFAULT);
|
|
|
1014
|
|
|
1015 ASSERT_EQ(1, close_cb_called);
|
|
|
1016
|
|
|
1017 /* Clean up */
|
|
|
1018 delete_dir("watch_dir/");
|
|
|
1019
|
|
|
1020 MAKE_VALGRIND_HAPPY(loop);
|
|
|
1021 return 0;
|
|
|
1022 }
|
|
|
1023
|
|
|
1024 TEST_IMPL(fs_event_close_in_callback) {
|
|
|
1025 #if defined(NO_FS_EVENTS)
|
|
|
1026 RETURN_SKIP(NO_FS_EVENTS);
|
|
|
1027 #elif defined(__MVS__)
|
|
|
1028 RETURN_SKIP("Directory watching not supported on this platform.");
|
|
|
1029 #elif defined(__APPLE__) && defined(__TSAN__)
|
|
|
1030 RETURN_SKIP("Times out under TSAN.");
|
|
|
1031 #endif
|
|
|
1032 uv_loop_t* loop;
|
|
|
1033 int r;
|
|
|
1034
|
|
|
1035 loop = uv_default_loop();
|
|
|
1036
|
|
|
1037 fs_event_unlink_files(NULL);
|
|
|
1038 create_dir("watch_dir");
|
|
|
1039
|
|
|
1040 r = uv_fs_event_init(loop, &fs_event);
|
|
|
1041 ASSERT_OK(r);
|
|
|
1042 r = uv_fs_event_start(&fs_event, fs_event_cb_close, "watch_dir", 0);
|
|
|
1043 ASSERT_OK(r);
|
|
|
1044
|
|
|
1045 r = uv_timer_init(loop, &timer);
|
|
|
1046 ASSERT_OK(r);
|
|
|
1047 r = uv_timer_start(&timer, fs_event_create_files, 100, 0);
|
|
|
1048 ASSERT_OK(r);
|
|
|
1049
|
|
|
1050 uv_run(loop, UV_RUN_DEFAULT);
|
|
|
1051
|
|
|
1052 uv_close((uv_handle_t*)&timer, close_cb);
|
|
|
1053
|
|
|
1054 uv_run(loop, UV_RUN_ONCE);
|
|
|
1055
|
|
|
1056 ASSERT_EQ(2, close_cb_called);
|
|
|
1057 ASSERT_EQ(3, fs_event_cb_called);
|
|
|
1058
|
|
|
1059 /* Clean up */
|
|
|
1060 fs_event_unlink_files(NULL);
|
|
|
1061 delete_dir("watch_dir/");
|
|
|
1062
|
|
|
1063 MAKE_VALGRIND_HAPPY(loop);
|
|
|
1064 return 0;
|
|
|
1065 }
|
|
|
1066
|
|
|
1067 TEST_IMPL(fs_event_start_and_close) {
|
|
|
1068 #if defined(NO_FS_EVENTS)
|
|
|
1069 RETURN_SKIP(NO_FS_EVENTS);
|
|
|
1070 #endif
|
|
|
1071 uv_loop_t* loop;
|
|
|
1072 uv_fs_event_t fs_event1;
|
|
|
1073 uv_fs_event_t fs_event2;
|
|
|
1074 int r;
|
|
|
1075
|
|
|
1076 loop = uv_default_loop();
|
|
|
1077
|
|
|
1078 create_dir("watch_dir");
|
|
|
1079
|
|
|
1080 r = uv_fs_event_init(loop, &fs_event1);
|
|
|
1081 ASSERT_OK(r);
|
|
|
1082 r = uv_fs_event_start(&fs_event1, fs_event_cb_dir, "watch_dir", 0);
|
|
|
1083 ASSERT_OK(r);
|
|
|
1084
|
|
|
1085 r = uv_fs_event_init(loop, &fs_event2);
|
|
|
1086 ASSERT_OK(r);
|
|
|
1087 r = uv_fs_event_start(&fs_event2, fs_event_cb_dir, "watch_dir", 0);
|
|
|
1088 ASSERT_OK(r);
|
|
|
1089
|
|
|
1090 uv_close((uv_handle_t*) &fs_event2, close_cb);
|
|
|
1091 uv_close((uv_handle_t*) &fs_event1, close_cb);
|
|
|
1092
|
|
|
1093 uv_run(loop, UV_RUN_DEFAULT);
|
|
|
1094
|
|
|
1095 ASSERT_EQ(2, close_cb_called);
|
|
|
1096
|
|
|
1097 delete_dir("watch_dir/");
|
|
|
1098 MAKE_VALGRIND_HAPPY(loop);
|
|
|
1099 return 0;
|
|
|
1100 }
|
|
|
1101
|
|
|
1102 TEST_IMPL(fs_event_getpath) {
|
|
|
1103 #if defined(NO_FS_EVENTS)
|
|
|
1104 RETURN_SKIP(NO_FS_EVENTS);
|
|
|
1105 #endif
|
|
|
1106 uv_loop_t* loop = uv_default_loop();
|
|
|
1107 unsigned i;
|
|
|
1108 int r;
|
|
|
1109 char buf[1024];
|
|
|
1110 size_t len;
|
|
|
1111 const char* const watch_dir[] = {
|
|
|
1112 "watch_dir",
|
|
|
1113 "watch_dir/",
|
|
|
1114 "watch_dir///",
|
|
|
1115 "watch_dir/subfolder/..",
|
|
|
1116 "watch_dir//subfolder//..//",
|
|
|
1117 };
|
|
|
1118
|
|
|
1119 create_dir("watch_dir");
|
|
|
1120 create_dir("watch_dir/subfolder");
|
|
|
1121
|
|
|
1122
|
|
|
1123 for (i = 0; i < ARRAY_SIZE(watch_dir); i++) {
|
|
|
1124 r = uv_fs_event_init(loop, &fs_event);
|
|
|
1125 ASSERT_OK(r);
|
|
|
1126 len = sizeof buf;
|
|
|
1127 r = uv_fs_event_getpath(&fs_event, buf, &len);
|
|
|
1128 ASSERT_EQ(r, UV_EINVAL);
|
|
|
1129 r = uv_fs_event_start(&fs_event, fail_cb, watch_dir[i], 0);
|
|
|
1130 ASSERT_OK(r);
|
|
|
1131 len = 1;
|
|
|
1132 r = uv_fs_event_getpath(&fs_event, buf, &len);
|
|
|
1133 ASSERT_EQ(r, UV_ENOBUFS);
|
|
|
1134 ASSERT_LT(len, sizeof buf); /* sanity check */
|
|
|
1135 ASSERT_EQ(len, strlen(watch_dir[i]) + 1);
|
|
|
1136 r = uv_fs_event_getpath(&fs_event, buf, &len);
|
|
|
1137 ASSERT_OK(r);
|
|
|
1138 ASSERT_EQ(len, strlen(watch_dir[i]));
|
|
|
1139 ASSERT(strcmp(buf, watch_dir[i]) == 0);
|
|
|
1140 r = uv_fs_event_stop(&fs_event);
|
|
|
1141 ASSERT_OK(r);
|
|
|
1142 uv_close((uv_handle_t*) &fs_event, close_cb);
|
|
|
1143
|
|
|
1144 uv_run(loop, UV_RUN_DEFAULT);
|
|
|
1145
|
|
|
1146 ASSERT_EQ(1, close_cb_called);
|
|
|
1147 close_cb_called = 0;
|
|
|
1148 }
|
|
|
1149
|
|
|
1150 delete_dir("watch_dir/");
|
|
|
1151 MAKE_VALGRIND_HAPPY(loop);
|
|
|
1152 return 0;
|
|
|
1153 }
|
|
|
1154
|
|
|
1155 TEST_IMPL(fs_event_watch_invalid_path) {
|
|
|
1156 #if defined(NO_FS_EVENTS)
|
|
|
1157 RETURN_SKIP(NO_FS_EVENTS);
|
|
|
1158 #endif
|
|
|
1159
|
|
|
1160 uv_loop_t* loop;
|
|
|
1161 int r;
|
|
|
1162
|
|
|
1163 loop = uv_default_loop();
|
|
|
1164 r = uv_fs_event_init(loop, &fs_event);
|
|
|
1165 ASSERT_OK(r);
|
|
|
1166 r = uv_fs_event_start(&fs_event, fs_event_cb_file, "<:;", 0);
|
|
|
1167 ASSERT(r);
|
|
|
1168 ASSERT_OK(uv_is_active((uv_handle_t*) &fs_event));
|
|
|
1169 r = uv_fs_event_start(&fs_event, fs_event_cb_file, "", 0);
|
|
|
1170 ASSERT(r);
|
|
|
1171 ASSERT_OK(uv_is_active((uv_handle_t*) &fs_event));
|
|
|
1172 MAKE_VALGRIND_HAPPY(loop);
|
|
|
1173 return 0;
|
|
|
1174 }
|
|
|
1175
|
|
|
1176 static int fs_event_cb_stop_calls;
|
|
|
1177
|
|
|
1178 static void fs_event_cb_stop(uv_fs_event_t* handle, const char* path,
|
|
|
1179 int events, int status) {
|
|
|
1180 uv_fs_event_stop(handle);
|
|
|
1181 fs_event_cb_stop_calls++;
|
|
|
1182 }
|
|
|
1183
|
|
|
1184 TEST_IMPL(fs_event_stop_in_cb) {
|
|
|
1185 uv_fs_event_t fs;
|
|
|
1186 uv_timer_t timer;
|
|
|
1187 char path[] = "fs_event_stop_in_cb.txt";
|
|
|
1188
|
|
|
1189 #if defined(NO_FS_EVENTS)
|
|
|
1190 RETURN_SKIP(NO_FS_EVENTS);
|
|
|
1191 #endif
|
|
|
1192
|
|
|
1193 delete_file(path);
|
|
|
1194 create_file(path);
|
|
|
1195
|
|
|
1196 ASSERT_OK(uv_fs_event_init(uv_default_loop(), &fs));
|
|
|
1197 ASSERT_OK(uv_fs_event_start(&fs, fs_event_cb_stop, path, 0));
|
|
|
1198
|
|
|
1199 /* Note: timer_cb_touch() closes the handle. */
|
|
|
1200 timer.data = path;
|
|
|
1201 ASSERT_OK(uv_timer_init(uv_default_loop(), &timer));
|
|
|
1202 ASSERT_OK(uv_timer_start(&timer, timer_cb_touch, 100, 0));
|
|
|
1203
|
|
|
1204 ASSERT_OK(fs_event_cb_stop_calls);
|
|
|
1205 ASSERT_OK(timer_cb_touch_called);
|
|
|
1206
|
|
|
1207 ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT));
|
|
|
1208
|
|
|
1209 ASSERT_EQ(1, fs_event_cb_stop_calls);
|
|
|
1210 ASSERT_EQ(1, timer_cb_touch_called);
|
|
|
1211
|
|
|
1212 uv_close((uv_handle_t*) &fs, NULL);
|
|
|
1213 ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT));
|
|
|
1214 ASSERT_EQ(1, fs_event_cb_stop_calls);
|
|
|
1215
|
|
|
1216 delete_file(path);
|
|
|
1217
|
|
|
1218 MAKE_VALGRIND_HAPPY(uv_default_loop());
|
|
|
1219 return 0;
|
|
|
1220 }
|