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 | |
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 | |
73 | static void close_cb(uv_handle_t* handle) { |
74 | close_cb_called++; |
75 | } |
76 | |
77 | |
78 | static void timer_cb(uv_timer_t* handle) { |
79 | touch_file(FIXTURE); |
80 | timer_cb_called++; |
81 | } |
82 | |
83 | |
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 | |
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 | |
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(handle == &poll_handle); |
107 | ASSERT(1 == uv_is_active((uv_handle_t*) handle)); |
108 | ASSERT(prev != NULL); |
109 | ASSERT(curr != NULL); |
110 | |
111 | switch (poll_cb_called++) { |
112 | case 0: |
113 | ASSERT(status == UV_ENOENT); |
114 | ASSERT(0 == memcmp(prev, &zero_statbuf, sizeof(zero_statbuf))); |
115 | ASSERT(0 == memcmp(curr, &zero_statbuf, sizeof(zero_statbuf))); |
116 | touch_file(FIXTURE); |
117 | break; |
118 | |
119 | case 1: |
120 | ASSERT(status == 0); |
121 | ASSERT(0 == memcmp(prev, &zero_statbuf, sizeof(zero_statbuf))); |
122 | ASSERT(0 != memcmp(curr, &zero_statbuf, sizeof(zero_statbuf))); |
123 | ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 20, 0)); |
124 | break; |
125 | |
126 | case 2: |
127 | ASSERT(status == 0); |
128 | ASSERT(0 != memcmp(prev, &zero_statbuf, sizeof(zero_statbuf))); |
129 | ASSERT(0 != memcmp(curr, &zero_statbuf, sizeof(zero_statbuf))); |
130 | ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 200, 0)); |
131 | break; |
132 | |
133 | case 3: |
134 | ASSERT(status == 0); |
135 | ASSERT(0 != memcmp(prev, &zero_statbuf, sizeof(zero_statbuf))); |
136 | ASSERT(0 != memcmp(curr, &zero_statbuf, sizeof(zero_statbuf))); |
137 | remove(FIXTURE); |
138 | break; |
139 | |
140 | case 4: |
141 | ASSERT(status == UV_ENOENT); |
142 | ASSERT(0 != memcmp(prev, &zero_statbuf, sizeof(zero_statbuf))); |
143 | ASSERT(0 == 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 | |
153 | TEST_IMPL(fs_poll) { |
154 | loop = uv_default_loop(); |
155 | |
156 | remove(FIXTURE); |
157 | |
158 | ASSERT(0 == uv_timer_init(loop, &timer_handle)); |
159 | ASSERT(0 == uv_fs_poll_init(loop, &poll_handle)); |
160 | ASSERT(0 == uv_fs_poll_start(&poll_handle, poll_cb, FIXTURE, 100)); |
161 | ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); |
162 | |
163 | ASSERT(poll_cb_called == 5); |
164 | ASSERT(timer_cb_called == 2); |
165 | ASSERT(close_cb_called == 1); |
166 | |
167 | MAKE_VALGRIND_HAPPY(); |
168 | return 0; |
169 | } |
170 | |
171 | |
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(0 == uv_fs_poll_init(loop, &poll_handle)); |
180 | len = sizeof buf; |
181 | ASSERT(UV_EINVAL == uv_fs_poll_getpath(&poll_handle, buf, &len)); |
182 | ASSERT(0 == uv_fs_poll_start(&poll_handle, poll_cb_fail, FIXTURE, 100)); |
183 | len = sizeof buf; |
184 | ASSERT(0 == uv_fs_poll_getpath(&poll_handle, buf, &len)); |
185 | ASSERT(buf[len - 1] != 0); |
186 | ASSERT(buf[len] == '\0'); |
187 | ASSERT(0 == memcmp(buf, FIXTURE, len)); |
188 | |
189 | uv_close((uv_handle_t*) &poll_handle, close_cb); |
190 | |
191 | ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); |
192 | |
193 | ASSERT(close_cb_called == 1); |
194 | |
195 | MAKE_VALGRIND_HAPPY(); |
196 | return 0; |
197 | } |
198 | |
199 | |
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(0 == uv_loop_init(&loop)); |
207 | |
208 | ASSERT(0 == uv_fs_poll_init(&loop, &poll_handle)); |
209 | ASSERT(0 == 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(close_cb_called == 1); |
214 | |
215 | ASSERT(0 == uv_loop_close(&loop)); |
216 | |
217 | MAKE_VALGRIND_HAPPY(); |
218 | return 0; |
219 | } |
220 | |
221 | TEST_IMPL(fs_poll_close_request_multi_start_stop) { |
222 | uv_loop_t loop; |
223 | uv_fs_poll_t poll_handle; |
224 | int i; |
225 | |
226 | remove(FIXTURE); |
227 | |
228 | ASSERT(0 == uv_loop_init(&loop)); |
229 | |
230 | ASSERT(0 == uv_fs_poll_init(&loop, &poll_handle)); |
231 | |
232 | for (i = 0; i < 10; ++i) { |
233 | ASSERT(0 == uv_fs_poll_start(&poll_handle, poll_cb_fail, FIXTURE, 100)); |
234 | ASSERT(0 == uv_fs_poll_stop(&poll_handle)); |
235 | } |
236 | uv_close((uv_handle_t*) &poll_handle, close_cb); |
237 | while (close_cb_called == 0) |
238 | uv_run(&loop, UV_RUN_ONCE); |
239 | ASSERT(close_cb_called == 1); |
240 | |
241 | ASSERT(0 == uv_loop_close(&loop)); |
242 | |
243 | MAKE_VALGRIND_HAPPY(); |
244 | return 0; |
245 | } |
246 | |
247 | TEST_IMPL(fs_poll_close_request_multi_stop_start) { |
248 | uv_loop_t loop; |
249 | uv_fs_poll_t poll_handle; |
250 | int i; |
251 | |
252 | remove(FIXTURE); |
253 | |
254 | ASSERT(0 == uv_loop_init(&loop)); |
255 | |
256 | ASSERT(0 == uv_fs_poll_init(&loop, &poll_handle)); |
257 | |
258 | for (i = 0; i < 10; ++i) { |
259 | ASSERT(0 == uv_fs_poll_stop(&poll_handle)); |
260 | ASSERT(0 == uv_fs_poll_start(&poll_handle, poll_cb_fail, FIXTURE, 100)); |
261 | } |
262 | uv_close((uv_handle_t*) &poll_handle, close_cb); |
263 | while (close_cb_called == 0) |
264 | uv_run(&loop, UV_RUN_ONCE); |
265 | ASSERT(close_cb_called == 1); |
266 | |
267 | ASSERT(0 == uv_loop_close(&loop)); |
268 | |
269 | MAKE_VALGRIND_HAPPY(); |
270 | return 0; |
271 | } |
272 | |
273 | TEST_IMPL(fs_poll_close_request_stop_when_active) { |
274 | /* Regression test for https://github.com/libuv/libuv/issues/2287. */ |
275 | uv_loop_t loop; |
276 | uv_fs_poll_t poll_handle; |
277 | |
278 | remove(FIXTURE); |
279 | |
280 | ASSERT(0 == uv_loop_init(&loop)); |
281 | |
282 | /* Set up all handles. */ |
283 | ASSERT(0 == uv_fs_poll_init(&loop, &poll_handle)); |
284 | ASSERT(0 == uv_fs_poll_start(&poll_handle, poll_cb_noop, FIXTURE, 100)); |
285 | uv_run(&loop, UV_RUN_ONCE); |
286 | |
287 | /* Close the timer handle, and do not crash. */ |
288 | ASSERT(0 == uv_fs_poll_stop(&poll_handle)); |
289 | uv_run(&loop, UV_RUN_ONCE); |
290 | |
291 | /* Clean up after the test. */ |
292 | uv_close((uv_handle_t*) &poll_handle, close_cb); |
293 | uv_run(&loop, UV_RUN_ONCE); |
294 | ASSERT(close_cb_called == 1); |
295 | |
296 | ASSERT(0 == uv_loop_close(&loop)); |
297 | |
298 | MAKE_VALGRIND_HAPPY(); |
299 | return 0; |
300 | } |
301 | |