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
27 #define FIXTURE "testfile"
28
29 static void timer_cb(uv_timer_t* handle);
30 static void close_cb(uv_handle_t* handle);
31 static void poll_cb(uv_fs_poll_t* handle,
32 int status,
33 const uv_stat_t* prev,
34 const uv_stat_t* curr);
35
36 static void poll_cb_fail(uv_fs_poll_t* handle,
37 int status,
38 const uv_stat_t* prev,
39 const uv_stat_t* curr);
40 static void poll_cb_noop(uv_fs_poll_t* handle,
41 int status,
42 const uv_stat_t* prev,
43 const uv_stat_t* curr);
44
45 static uv_fs_poll_t poll_handle;
46 static uv_timer_t timer_handle;
47 static uv_loop_t* loop;
48
49 static int poll_cb_called;
50 static int timer_cb_called;
51 static int close_cb_called;
52
53
touch_file(const char * path)54 static void touch_file(const char* path) {
55 static int count;
56 FILE* fp;
57 int i;
58
59 ASSERT((fp = fopen(FIXTURE, "w+")));
60
61 /* Need to change the file size because the poller may not pick up
62 * sub-second mtime changes.
63 */
64 i = ++count;
65
66 while (i--)
67 fputc('*', fp);
68
69 fclose(fp);
70 }
71
72
close_cb(uv_handle_t * handle)73 static void close_cb(uv_handle_t* handle) {
74 close_cb_called++;
75 }
76
77
timer_cb(uv_timer_t * handle)78 static void timer_cb(uv_timer_t* handle) {
79 touch_file(FIXTURE);
80 timer_cb_called++;
81 }
82
83
poll_cb_fail(uv_fs_poll_t * handle,int status,const uv_stat_t * prev,const uv_stat_t * curr)84 static void poll_cb_fail(uv_fs_poll_t* handle,
85 int status,
86 const uv_stat_t* prev,
87 const uv_stat_t* curr) {
88 ASSERT(0 && "fail_cb called");
89 }
90
poll_cb_noop(uv_fs_poll_t * handle,int status,const uv_stat_t * prev,const uv_stat_t * curr)91 static void poll_cb_noop(uv_fs_poll_t* handle,
92 int status,
93 const uv_stat_t* prev,
94 const uv_stat_t* curr) {
95 }
96
97
poll_cb(uv_fs_poll_t * handle,int status,const uv_stat_t * prev,const uv_stat_t * curr)98 static void poll_cb(uv_fs_poll_t* handle,
99 int status,
100 const uv_stat_t* prev,
101 const uv_stat_t* curr) {
102 uv_stat_t zero_statbuf;
103
104 memset(&zero_statbuf, 0, sizeof(zero_statbuf));
105
106 ASSERT_PTR_EQ(handle, &poll_handle);
107 ASSERT_EQ(1, uv_is_active((uv_handle_t*) handle));
108 ASSERT_NOT_NULL(prev);
109 ASSERT_NOT_NULL(curr);
110
111 switch (poll_cb_called++) {
112 case 0:
113 ASSERT_EQ(status, UV_ENOENT);
114 ASSERT_OK(memcmp(prev, &zero_statbuf, sizeof(zero_statbuf)));
115 ASSERT_OK(memcmp(curr, &zero_statbuf, sizeof(zero_statbuf)));
116 touch_file(FIXTURE);
117 break;
118
119 case 1:
120 ASSERT_OK(status);
121 ASSERT_OK(memcmp(prev, &zero_statbuf, sizeof(zero_statbuf)));
122 ASSERT_NE(0, memcmp(curr, &zero_statbuf, sizeof(zero_statbuf)));
123 ASSERT_OK(uv_timer_start(&timer_handle, timer_cb, 20, 0));
124 break;
125
126 case 2:
127 ASSERT_OK(status);
128 ASSERT_NE(0, memcmp(prev, &zero_statbuf, sizeof(zero_statbuf)));
129 ASSERT_NE(0, memcmp(curr, &zero_statbuf, sizeof(zero_statbuf)));
130 ASSERT_OK(uv_timer_start(&timer_handle, timer_cb, 200, 0));
131 break;
132
133 case 3:
134 ASSERT_OK(status);
135 ASSERT_NE(0, memcmp(prev, &zero_statbuf, sizeof(zero_statbuf)));
136 ASSERT_NE(0, memcmp(curr, &zero_statbuf, sizeof(zero_statbuf)));
137 remove(FIXTURE);
138 break;
139
140 case 4:
141 ASSERT_EQ(status, UV_ENOENT);
142 ASSERT_NE(0, memcmp(prev, &zero_statbuf, sizeof(zero_statbuf)));
143 ASSERT_OK(memcmp(curr, &zero_statbuf, sizeof(zero_statbuf)));
144 uv_close((uv_handle_t*)handle, close_cb);
145 break;
146
147 default:
148 ASSERT(0);
149 }
150 }
151
152
TEST_IMPL(fs_poll)153 TEST_IMPL(fs_poll) {
154 loop = uv_default_loop();
155
156 remove(FIXTURE);
157
158 ASSERT_OK(uv_timer_init(loop, &timer_handle));
159 ASSERT_OK(uv_fs_poll_init(loop, &poll_handle));
160 ASSERT_OK(uv_fs_poll_start(&poll_handle, poll_cb, FIXTURE, 100));
161 ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT));
162
163 ASSERT_EQ(5, poll_cb_called);
164 ASSERT_EQ(2, timer_cb_called);
165 ASSERT_EQ(1, close_cb_called);
166
167 MAKE_VALGRIND_HAPPY(loop);
168 return 0;
169 }
170
171
TEST_IMPL(fs_poll_getpath)172 TEST_IMPL(fs_poll_getpath) {
173 char buf[1024];
174 size_t len;
175 loop = uv_default_loop();
176
177 remove(FIXTURE);
178
179 ASSERT_OK(uv_fs_poll_init(loop, &poll_handle));
180 len = sizeof buf;
181 ASSERT_EQ(UV_EINVAL, uv_fs_poll_getpath(&poll_handle, buf, &len));
182 ASSERT_OK(uv_fs_poll_start(&poll_handle, poll_cb_fail, FIXTURE, 100));
183 len = sizeof buf;
184 ASSERT_OK(uv_fs_poll_getpath(&poll_handle, buf, &len));
185 ASSERT_NE(0, buf[len - 1]);
186 ASSERT_EQ(buf[len], '\0');
187 ASSERT_OK(memcmp(buf, FIXTURE, len));
188
189 uv_close((uv_handle_t*) &poll_handle, close_cb);
190
191 ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT));
192
193 ASSERT_EQ(1, close_cb_called);
194
195 MAKE_VALGRIND_HAPPY(loop);
196 return 0;
197 }
198
199
TEST_IMPL(fs_poll_close_request)200 TEST_IMPL(fs_poll_close_request) {
201 uv_loop_t loop;
202 uv_fs_poll_t poll_handle;
203
204 remove(FIXTURE);
205
206 ASSERT_OK(uv_loop_init(&loop));
207
208 ASSERT_OK(uv_fs_poll_init(&loop, &poll_handle));
209 ASSERT_OK(uv_fs_poll_start(&poll_handle, poll_cb_fail, FIXTURE, 100));
210 uv_close((uv_handle_t*) &poll_handle, close_cb);
211 while (close_cb_called == 0)
212 uv_run(&loop, UV_RUN_ONCE);
213 ASSERT_EQ(1, close_cb_called);
214
215 MAKE_VALGRIND_HAPPY(&loop);
216 return 0;
217 }
218
TEST_IMPL(fs_poll_close_request_multi_start_stop)219 TEST_IMPL(fs_poll_close_request_multi_start_stop) {
220 uv_loop_t loop;
221 uv_fs_poll_t poll_handle;
222 int i;
223
224 remove(FIXTURE);
225
226 ASSERT_OK(uv_loop_init(&loop));
227
228 ASSERT_OK(uv_fs_poll_init(&loop, &poll_handle));
229
230 for (i = 0; i < 10; ++i) {
231 ASSERT_OK(uv_fs_poll_start(&poll_handle, poll_cb_fail, FIXTURE, 100));
232 ASSERT_OK(uv_fs_poll_stop(&poll_handle));
233 }
234 uv_close((uv_handle_t*) &poll_handle, close_cb);
235 while (close_cb_called == 0)
236 uv_run(&loop, UV_RUN_ONCE);
237 ASSERT_EQ(1, close_cb_called);
238
239 MAKE_VALGRIND_HAPPY(&loop);
240 return 0;
241 }
242
TEST_IMPL(fs_poll_close_request_multi_stop_start)243 TEST_IMPL(fs_poll_close_request_multi_stop_start) {
244 uv_loop_t loop;
245 uv_fs_poll_t poll_handle;
246 int i;
247
248 remove(FIXTURE);
249
250 ASSERT_OK(uv_loop_init(&loop));
251
252 ASSERT_OK(uv_fs_poll_init(&loop, &poll_handle));
253
254 for (i = 0; i < 10; ++i) {
255 ASSERT_OK(uv_fs_poll_stop(&poll_handle));
256 ASSERT_OK(uv_fs_poll_start(&poll_handle, poll_cb_fail, FIXTURE, 100));
257 }
258 uv_close((uv_handle_t*) &poll_handle, close_cb);
259 while (close_cb_called == 0)
260 uv_run(&loop, UV_RUN_ONCE);
261 ASSERT_EQ(1, close_cb_called);
262
263 MAKE_VALGRIND_HAPPY(&loop);
264 return 0;
265 }
266
TEST_IMPL(fs_poll_close_request_stop_when_active)267 TEST_IMPL(fs_poll_close_request_stop_when_active) {
268 /* Regression test for https://github.com/libuv/libuv/issues/2287. */
269 uv_loop_t loop;
270 uv_fs_poll_t poll_handle;
271
272 remove(FIXTURE);
273
274 ASSERT_OK(uv_loop_init(&loop));
275
276 /* Set up all handles. */
277 ASSERT_OK(uv_fs_poll_init(&loop, &poll_handle));
278 ASSERT_OK(uv_fs_poll_start(&poll_handle, poll_cb_noop, FIXTURE, 100));
279 uv_run(&loop, UV_RUN_ONCE);
280
281 /* Close the timer handle, and do not crash. */
282 ASSERT_OK(uv_fs_poll_stop(&poll_handle));
283 uv_run(&loop, UV_RUN_ONCE);
284
285 /* Clean up after the test. */
286 uv_close((uv_handle_t*) &poll_handle, close_cb);
287 uv_run(&loop, UV_RUN_ONCE);
288 ASSERT_EQ(1, close_cb_called);
289
290 MAKE_VALGRIND_HAPPY(&loop);
291 return 0;
292 }
293