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