xref: /libuv/test/test-loop-handles.c (revision 011a1ac1)
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 
timer_cb(uv_timer_t * handle)110 static void timer_cb(uv_timer_t* handle) {
111   ASSERT_PTR_EQ(handle, &timer_handle);
112 }
113 
114 
idle_2_close_cb(uv_handle_t * handle)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 
idle_2_cb(uv_idle_t * handle)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 
idle_1_cb(uv_idle_t * handle)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 
idle_1_close_cb(uv_handle_t * handle)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 
prepare_1_close_cb(uv_handle_t * handle)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 
check_close_cb(uv_handle_t * handle)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 
prepare_2_close_cb(uv_handle_t * handle)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 
check_cb(uv_check_t * handle)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 
prepare_2_cb(uv_prepare_t * handle)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 
prepare_1_cb(uv_prepare_t * handle)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 
TEST_IMPL(loop_handles)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 }
338