|
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 /* Tests commented out with XXX are ones that are failing on Linux */
|
|
|
23
|
|
|
24 /*
|
|
|
25 * Purpose of this test is to check semantics of starting and stopping
|
|
|
26 * prepare, check and idle watchers.
|
|
|
27 *
|
|
|
28 * - A watcher must be able to safely stop or close itself;
|
|
|
29 * - Once a watcher is stopped or closed its callback should never be called.
|
|
|
30 * - If a watcher is closed, it is implicitly stopped and its close_cb should
|
|
|
31 * be called exactly once.
|
|
|
32 * - A watcher can safely start and stop other watchers of the same type.
|
|
|
33 * - Prepare and check watchers are called once per event loop iterations.
|
|
|
34 * - All active idle watchers are queued when the event loop has no more work
|
|
|
35 * to do. This is done repeatedly until all idle watchers are inactive.
|
|
|
36 * - If a watcher starts another watcher of the same type its callback is not
|
|
|
37 * immediately queued. For check and prepare watchers, that means that if
|
|
|
38 * a watcher makes another of the same type active, it'll not be called until
|
|
|
39 * the next event loop iteration. For idle. watchers this means that the
|
|
|
40 * newly activated idle watcher might not be queued immediately.
|
|
|
41 * - Prepare, check, idle watchers keep the event loop alive even when they're
|
|
|
42 * not active.
|
|
|
43 *
|
|
|
44 * This is what the test globally does:
|
|
|
45 *
|
|
|
46 * - prepare_1 is always active and counts event loop iterations. It also
|
|
|
47 * creates and starts prepare_2 every other iteration. Finally it verifies
|
|
|
48 * that no idle watchers are active before polling.
|
|
|
49 * - prepare_2 is started by prepare_1 every other iteration. It immediately
|
|
|
50 * stops itself. It verifies that a watcher is not queued immediately
|
|
|
51 * if created by another watcher of the same type.
|
|
|
52 * - There's a check watcher that stops the event loop after a certain number
|
|
|
53 * of iterations. It starts a varying number of idle_1 watchers.
|
|
|
54 * - Idle_1 watchers stop themselves after being called a few times. All idle_1
|
|
|
55 * watchers try to start the idle_2 watcher if it is not already started or
|
|
|
56 * awaiting its close callback.
|
|
|
57 * - The idle_2 watcher always exists but immediately closes itself after
|
|
|
58 * being started by a check_1 watcher. It verifies that a watcher is
|
|
|
59 * implicitly stopped when closed, and that a watcher can close itself
|
|
|
60 * safely.
|
|
|
61 * - There is a repeating timer. It does not keep the event loop alive
|
|
|
62 * (ev_unref) but makes sure that the loop keeps polling the system for
|
|
|
63 * events.
|
|
|
64 */
|
|
|
65
|
|
|
66
|
|
|
67 #include "uv.h"
|
|
|
68 #include "task.h"
|
|
|
69
|
|
|
70 #include <math.h>
|
|
|
71
|
|
|
72
|
|
|
73 #define IDLE_COUNT 7
|
|
|
74 #define ITERATIONS 21
|
|
|
75 #define TIMEOUT 100
|
|
|
76
|
|
|
77
|
|
|
78 static uv_prepare_t prepare_1_handle;
|
|
|
79 static uv_prepare_t prepare_2_handle;
|
|
|
80
|
|
|
81 static uv_check_t check_handle;
|
|
|
82
|
|
|
83 static uv_idle_t idle_1_handles[IDLE_COUNT];
|
|
|
84 static uv_idle_t idle_2_handle;
|
|
|
85
|
|
|
86 static uv_timer_t timer_handle;
|
|
|
87
|
|
|
88
|
|
|
89 static int loop_iteration = 0;
|
|
|
90
|
|
|
91 static int prepare_1_cb_called = 0;
|
|
|
92 static int prepare_1_close_cb_called = 0;
|
|
|
93
|
|
|
94 static int prepare_2_cb_called = 0;
|
|
|
95 static int prepare_2_close_cb_called = 0;
|
|
|
96
|
|
|
97 static int check_cb_called = 0;
|
|
|
98 static int check_close_cb_called = 0;
|
|
|
99
|
|
|
100 static int idle_1_cb_called = 0;
|
|
|
101 static int idle_1_close_cb_called = 0;
|
|
|
102 static int idles_1_active = 0;
|
|
|
103
|
|
|
104 static int idle_2_cb_called = 0;
|
|
|
105 static int idle_2_close_cb_called = 0;
|
|
|
106 static int idle_2_cb_started = 0;
|
|
|
107 static int idle_2_is_active = 0;
|
|
|
108
|
|
|
109
|
|
|
110 static void timer_cb(uv_timer_t* handle) {
|
|
|
111 ASSERT_PTR_EQ(handle, &timer_handle);
|
|
|
112 }
|
|
|
113
|
|
|
114
|
|
|
115 static void idle_2_close_cb(uv_handle_t* handle) {
|
|
|
116 fprintf(stderr, "%s", "IDLE_2_CLOSE_CB\n");
|
|
|
117 fflush(stderr);
|
|
|
118
|
|
|
119 ASSERT_PTR_EQ(handle, (uv_handle_t*)&idle_2_handle);
|
|
|
120
|
|
|
121 ASSERT(idle_2_is_active);
|
|
|
122
|
|
|
123 idle_2_close_cb_called++;
|
|
|
124 idle_2_is_active = 0;
|
|
|
125 }
|
|
|
126
|
|
|
127
|
|
|
128 static void idle_2_cb(uv_idle_t* handle) {
|
|
|
129 fprintf(stderr, "%s", "IDLE_2_CB\n");
|
|
|
130 fflush(stderr);
|
|
|
131
|
|
|
132 ASSERT_PTR_EQ(handle, &idle_2_handle);
|
|
|
133
|
|
|
134 idle_2_cb_called++;
|
|
|
135
|
|
|
136 uv_close((uv_handle_t*)handle, idle_2_close_cb);
|
|
|
137 }
|
|
|
138
|
|
|
139
|
|
|
140 static void idle_1_cb(uv_idle_t* handle) {
|
|
|
141 int r;
|
|
|
142
|
|
|
143 fprintf(stderr, "%s", "IDLE_1_CB\n");
|
|
|
144 fflush(stderr);
|
|
|
145
|
|
|
146 ASSERT_NOT_NULL(handle);
|
|
|
147 ASSERT_GT(idles_1_active, 0);
|
|
|
148
|
|
|
149 /* Init idle_2 and make it active */
|
|
|
150 if (!idle_2_is_active && !uv_is_closing((uv_handle_t*)&idle_2_handle)) {
|
|
|
151 r = uv_idle_init(uv_default_loop(), &idle_2_handle);
|
|
|
152 ASSERT_OK(r);
|
|
|
153 r = uv_idle_start(&idle_2_handle, idle_2_cb);
|
|
|
154 ASSERT_OK(r);
|
|
|
155 idle_2_is_active = 1;
|
|
|
156 idle_2_cb_started++;
|
|
|
157 }
|
|
|
158
|
|
|
159 idle_1_cb_called++;
|
|
|
160
|
|
|
161 if (idle_1_cb_called % 5 == 0) {
|
|
|
162 r = uv_idle_stop((uv_idle_t*)handle);
|
|
|
163 ASSERT_OK(r);
|
|
|
164 idles_1_active--;
|
|
|
165 }
|
|
|
166 }
|
|
|
167
|
|
|
168
|
|
|
169 static void idle_1_close_cb(uv_handle_t* handle) {
|
|
|
170 fprintf(stderr, "%s", "IDLE_1_CLOSE_CB\n");
|
|
|
171 fflush(stderr);
|
|
|
172
|
|
|
173 ASSERT_NOT_NULL(handle);
|
|
|
174
|
|
|
175 idle_1_close_cb_called++;
|
|
|
176 }
|
|
|
177
|
|
|
178
|
|
|
179 static void prepare_1_close_cb(uv_handle_t* handle) {
|
|
|
180 fprintf(stderr, "%s", "PREPARE_1_CLOSE_CB");
|
|
|
181 fflush(stderr);
|
|
|
182 ASSERT_PTR_EQ(handle, (uv_handle_t*)&prepare_1_handle);
|
|
|
183
|
|
|
184 prepare_1_close_cb_called++;
|
|
|
185 }
|
|
|
186
|
|
|
187
|
|
|
188 static void check_close_cb(uv_handle_t* handle) {
|
|
|
189 fprintf(stderr, "%s", "CHECK_CLOSE_CB\n");
|
|
|
190 fflush(stderr);
|
|
|
191 ASSERT_PTR_EQ(handle, (uv_handle_t*)&check_handle);
|
|
|
192
|
|
|
193 check_close_cb_called++;
|
|
|
194 }
|
|
|
195
|
|
|
196
|
|
|
197 static void prepare_2_close_cb(uv_handle_t* handle) {
|
|
|
198 fprintf(stderr, "%s", "PREPARE_2_CLOSE_CB\n");
|
|
|
199 fflush(stderr);
|
|
|
200 ASSERT_PTR_EQ(handle, (uv_handle_t*)&prepare_2_handle);
|
|
|
201
|
|
|
202 prepare_2_close_cb_called++;
|
|
|
203 }
|
|
|
204
|
|
|
205
|
|
|
206 static void check_cb(uv_check_t* handle) {
|
|
|
207 int i, r;
|
|
|
208
|
|
|
209 fprintf(stderr, "%s", "CHECK_CB\n");
|
|
|
210 fflush(stderr);
|
|
|
211 ASSERT_PTR_EQ(handle, &check_handle);
|
|
|
212
|
|
|
213 if (loop_iteration < ITERATIONS) {
|
|
|
214 /* Make some idle watchers active */
|
|
|
215 for (i = 0; i < 1 + (loop_iteration % IDLE_COUNT); i++) {
|
|
|
216 r = uv_idle_start(&idle_1_handles[i], idle_1_cb);
|
|
|
217 ASSERT_OK(r);
|
|
|
218 idles_1_active++;
|
|
|
219 }
|
|
|
220
|
|
|
221 } else {
|
|
|
222 /* End of the test - close all handles */
|
|
|
223 uv_close((uv_handle_t*)&prepare_1_handle, prepare_1_close_cb);
|
|
|
224 uv_close((uv_handle_t*)&check_handle, check_close_cb);
|
|
|
225 uv_close((uv_handle_t*)&prepare_2_handle, prepare_2_close_cb);
|
|
|
226
|
|
|
227 for (i = 0; i < IDLE_COUNT; i++) {
|
|
|
228 uv_close((uv_handle_t*)&idle_1_handles[i], idle_1_close_cb);
|
|
|
229 }
|
|
|
230
|
|
|
231 /* This handle is closed/recreated every time, close it only if it is
|
|
|
232 * active. */
|
|
|
233 if (idle_2_is_active) {
|
|
|
234 uv_close((uv_handle_t*)&idle_2_handle, idle_2_close_cb);
|
|
|
235 }
|
|
|
236 }
|
|
|
237
|
|
|
238 check_cb_called++;
|
|
|
239 }
|
|
|
240
|
|
|
241
|
|
|
242 static void prepare_2_cb(uv_prepare_t* handle) {
|
|
|
243 int r;
|
|
|
244
|
|
|
245 fprintf(stderr, "%s", "PREPARE_2_CB\n");
|
|
|
246 fflush(stderr);
|
|
|
247 ASSERT_PTR_EQ(handle, &prepare_2_handle);
|
|
|
248
|
|
|
249 /* Prepare_2 gets started by prepare_1 when (loop_iteration % 2 == 0), and it
|
|
|
250 * stops itself immediately. A started watcher is not queued until the next
|
|
|
251 * round, so when this callback is made (loop_iteration % 2 == 0) cannot be
|
|
|
252 * true. */
|
|
|
253 ASSERT_NE(0, loop_iteration % 2);
|
|
|
254
|
|
|
255 r = uv_prepare_stop((uv_prepare_t*)handle);
|
|
|
256 ASSERT_OK(r);
|
|
|
257
|
|
|
258 prepare_2_cb_called++;
|
|
|
259 }
|
|
|
260
|
|
|
261
|
|
|
262 static void prepare_1_cb(uv_prepare_t* handle) {
|
|
|
263 int r;
|
|
|
264
|
|
|
265 fprintf(stderr, "%s", "PREPARE_1_CB\n");
|
|
|
266 fflush(stderr);
|
|
|
267 ASSERT_PTR_EQ(handle, &prepare_1_handle);
|
|
|
268
|
|
|
269 if (loop_iteration % 2 == 0) {
|
|
|
270 r = uv_prepare_start(&prepare_2_handle, prepare_2_cb);
|
|
|
271 ASSERT_OK(r);
|
|
|
272 }
|
|
|
273
|
|
|
274 prepare_1_cb_called++;
|
|
|
275 loop_iteration++;
|
|
|
276
|
|
|
277 printf("Loop iteration %d of %d.\n", loop_iteration, ITERATIONS);
|
|
|
278 }
|
|
|
279
|
|
|
280
|
|
|
281 TEST_IMPL(loop_handles) {
|
|
|
282 int i;
|
|
|
283 int r;
|
|
|
284
|
|
|
285 r = uv_prepare_init(uv_default_loop(), &prepare_1_handle);
|
|
|
286 ASSERT_OK(r);
|
|
|
287 r = uv_prepare_start(&prepare_1_handle, prepare_1_cb);
|
|
|
288 ASSERT_OK(r);
|
|
|
289
|
|
|
290 r = uv_check_init(uv_default_loop(), &check_handle);
|
|
|
291 ASSERT_OK(r);
|
|
|
292 r = uv_check_start(&check_handle, check_cb);
|
|
|
293 ASSERT_OK(r);
|
|
|
294
|
|
|
295 /* initialize only, prepare_2 is started by prepare_1_cb */
|
|
|
296 r = uv_prepare_init(uv_default_loop(), &prepare_2_handle);
|
|
|
297 ASSERT_OK(r);
|
|
|
298
|
|
|
299 for (i = 0; i < IDLE_COUNT; i++) {
|
|
|
300 /* initialize only, idle_1 handles are started by check_cb */
|
|
|
301 r = uv_idle_init(uv_default_loop(), &idle_1_handles[i]);
|
|
|
302 ASSERT_OK(r);
|
|
|
303 }
|
|
|
304
|
|
|
305 /* don't init or start idle_2, both is done by idle_1_cb */
|
|
|
306
|
|
|
307 /* The timer callback is there to keep the event loop polling unref it as it
|
|
|
308 * is not supposed to keep the loop alive */
|
|
|
309 r = uv_timer_init(uv_default_loop(), &timer_handle);
|
|
|
310 ASSERT_OK(r);
|
|
|
311 r = uv_timer_start(&timer_handle, timer_cb, TIMEOUT, TIMEOUT);
|
|
|
312 ASSERT_OK(r);
|
|
|
313 uv_unref((uv_handle_t*)&timer_handle);
|
|
|
314
|
|
|
315 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
|
|
316 ASSERT_OK(r);
|
|
|
317
|
|
|
318 ASSERT_EQ(loop_iteration, ITERATIONS);
|
|
|
319
|
|
|
320 ASSERT_EQ(prepare_1_cb_called, ITERATIONS);
|
|
|
321 ASSERT_EQ(1, prepare_1_close_cb_called);
|
|
|
322
|
|
|
323 ASSERT_EQ(prepare_2_cb_called, ITERATIONS / 2);
|
|
|
324 ASSERT_EQ(1, prepare_2_close_cb_called);
|
|
|
325
|
|
|
326 ASSERT_EQ(check_cb_called, ITERATIONS);
|
|
|
327 ASSERT_EQ(1, check_close_cb_called);
|
|
|
328
|
|
|
329 /* idle_1_cb should be called a lot */
|
|
|
330 ASSERT_EQ(idle_1_close_cb_called, IDLE_COUNT);
|
|
|
331
|
|
|
332 ASSERT_EQ(idle_2_close_cb_called, idle_2_cb_started);
|
|
|
333 ASSERT_OK(idle_2_is_active);
|
|
|
334
|
|
|
335 MAKE_VALGRIND_HAPPY(uv_default_loop());
|
|
|
336 return 0;
|
|
|
337 }
|