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
26static int once_cb_called = 0;
27static int once_close_cb_called = 0;
28static int repeat_cb_called = 0;
29static int repeat_close_cb_called = 0;
30static int order_cb_called = 0;
31static uint64_t start_time;
32static uv_timer_t tiny_timer;
33static uv_timer_t huge_timer1;
34static uv_timer_t huge_timer2;
35
36
37static void once_close_cb(uv_handle_t* handle) {
38 printf("ONCE_CLOSE_CB\n");
39
40 ASSERT(handle != NULL);
41 ASSERT(0 == uv_is_active(handle));
42
43 once_close_cb_called++;
44}
45
46
47static void once_cb(uv_timer_t* handle) {
48 printf("ONCE_CB %d\n", once_cb_called);
49
50 ASSERT(handle != NULL);
51 ASSERT(0 == uv_is_active((uv_handle_t*) handle));
52
53 once_cb_called++;
54
55 uv_close((uv_handle_t*)handle, once_close_cb);
56
57 /* Just call this randomly for the code coverage. */
58 uv_update_time(uv_default_loop());
59}
60
61
62static void repeat_close_cb(uv_handle_t* handle) {
63 printf("REPEAT_CLOSE_CB\n");
64
65 ASSERT(handle != NULL);
66
67 repeat_close_cb_called++;
68}
69
70
71static void repeat_cb(uv_timer_t* handle) {
72 printf("REPEAT_CB\n");
73
74 ASSERT(handle != NULL);
75 ASSERT(1 == uv_is_active((uv_handle_t*) handle));
76
77 repeat_cb_called++;
78
79 if (repeat_cb_called == 5) {
80 uv_close((uv_handle_t*)handle, repeat_close_cb);
81 }
82}
83
84
85static void never_cb(uv_timer_t* handle) {
86 FATAL("never_cb should never be called");
87}
88
89
90TEST_IMPL(timer) {
91 uv_timer_t once_timers[10];
92 uv_timer_t *once;
93 uv_timer_t repeat, never;
94 unsigned int i;
95 int r;
96
97 start_time = uv_now(uv_default_loop());
98 ASSERT(0 < start_time);
99
100 /* Let 10 timers time out in 500 ms total. */
101 for (i = 0; i < ARRAY_SIZE(once_timers); i++) {
102 once = once_timers + i;
103 r = uv_timer_init(uv_default_loop(), once);
104 ASSERT(r == 0);
105 r = uv_timer_start(once, once_cb, i * 50, 0);
106 ASSERT(r == 0);
107 }
108
109 /* The 11th timer is a repeating timer that runs 4 times */
110 r = uv_timer_init(uv_default_loop(), &repeat);
111 ASSERT(r == 0);
112 r = uv_timer_start(&repeat, repeat_cb, 100, 100);
113 ASSERT(r == 0);
114
115 /* The 12th timer should not do anything. */
116 r = uv_timer_init(uv_default_loop(), &never);
117 ASSERT(r == 0);
118 r = uv_timer_start(&never, never_cb, 100, 100);
119 ASSERT(r == 0);
120 r = uv_timer_stop(&never);
121 ASSERT(r == 0);
122 uv_unref((uv_handle_t*)&never);
123
124 uv_run(uv_default_loop(), UV_RUN_DEFAULT);
125
126 ASSERT(once_cb_called == 10);
127 ASSERT(once_close_cb_called == 10);
128 printf("repeat_cb_called %d\n", repeat_cb_called);
129 ASSERT(repeat_cb_called == 5);
130 ASSERT(repeat_close_cb_called == 1);
131
132 ASSERT(500 <= uv_now(uv_default_loop()) - start_time);
133
134 MAKE_VALGRIND_HAPPY();
135 return 0;
136}
137
138
139TEST_IMPL(timer_start_twice) {
140 uv_timer_t once;
141 int r;
142
143 r = uv_timer_init(uv_default_loop(), &once);
144 ASSERT(r == 0);
145 r = uv_timer_start(&once, never_cb, 86400 * 1000, 0);
146 ASSERT(r == 0);
147 r = uv_timer_start(&once, once_cb, 10, 0);
148 ASSERT(r == 0);
149 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
150 ASSERT(r == 0);
151
152 ASSERT(once_cb_called == 1);
153
154 MAKE_VALGRIND_HAPPY();
155 return 0;
156}
157
158
159TEST_IMPL(timer_init) {
160 uv_timer_t handle;
161
162 ASSERT(0 == uv_timer_init(uv_default_loop(), &handle));
163 ASSERT(0 == uv_timer_get_repeat(&handle));
164 ASSERT(0 == uv_is_active((uv_handle_t*) &handle));
165
166 MAKE_VALGRIND_HAPPY();
167 return 0;
168}
169
170
171static void order_cb_a(uv_timer_t *handle) {
172 ASSERT(order_cb_called++ == *(int*)handle->data);
173}
174
175
176static void order_cb_b(uv_timer_t *handle) {
177 ASSERT(order_cb_called++ == *(int*)handle->data);
178}
179
180
181TEST_IMPL(timer_order) {
182 int first;
183 int second;
184 uv_timer_t handle_a;
185 uv_timer_t handle_b;
186
187 first = 0;
188 second = 1;
189 ASSERT(0 == uv_timer_init(uv_default_loop(), &handle_a));
190 ASSERT(0 == uv_timer_init(uv_default_loop(), &handle_b));
191
192 /* Test for starting handle_a then handle_b */
193 handle_a.data = &first;
194 ASSERT(0 == uv_timer_start(&handle_a, order_cb_a, 0, 0));
195 handle_b.data = &second;
196 ASSERT(0 == uv_timer_start(&handle_b, order_cb_b, 0, 0));
197 ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
198
199 ASSERT(order_cb_called == 2);
200
201 ASSERT(0 == uv_timer_stop(&handle_a));
202 ASSERT(0 == uv_timer_stop(&handle_b));
203
204 /* Test for starting handle_b then handle_a */
205 order_cb_called = 0;
206 handle_b.data = &first;
207 ASSERT(0 == uv_timer_start(&handle_b, order_cb_b, 0, 0));
208
209 handle_a.data = &second;
210 ASSERT(0 == uv_timer_start(&handle_a, order_cb_a, 0, 0));
211 ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
212
213 ASSERT(order_cb_called == 2);
214
215 MAKE_VALGRIND_HAPPY();
216 return 0;
217}
218
219
220static void tiny_timer_cb(uv_timer_t* handle) {
221 ASSERT(handle == &tiny_timer);
222 uv_close((uv_handle_t*) &tiny_timer, NULL);
223 uv_close((uv_handle_t*) &huge_timer1, NULL);
224 uv_close((uv_handle_t*) &huge_timer2, NULL);
225}
226
227
228TEST_IMPL(timer_huge_timeout) {
229 ASSERT(0 == uv_timer_init(uv_default_loop(), &tiny_timer));
230 ASSERT(0 == uv_timer_init(uv_default_loop(), &huge_timer1));
231 ASSERT(0 == uv_timer_init(uv_default_loop(), &huge_timer2));
232 ASSERT(0 == uv_timer_start(&tiny_timer, tiny_timer_cb, 1, 0));
233 ASSERT(0 == uv_timer_start(&huge_timer1, tiny_timer_cb, 0xffffffffffffLL, 0));
234 ASSERT(0 == uv_timer_start(&huge_timer2, tiny_timer_cb, (uint64_t) -1, 0));
235 ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
236 MAKE_VALGRIND_HAPPY();
237 return 0;
238}
239
240
241static void huge_repeat_cb(uv_timer_t* handle) {
242 static int ncalls;
243
244 if (ncalls == 0)
245 ASSERT(handle == &huge_timer1);
246 else
247 ASSERT(handle == &tiny_timer);
248
249 if (++ncalls == 10) {
250 uv_close((uv_handle_t*) &tiny_timer, NULL);
251 uv_close((uv_handle_t*) &huge_timer1, NULL);
252 }
253}
254
255
256TEST_IMPL(timer_huge_repeat) {
257 ASSERT(0 == uv_timer_init(uv_default_loop(), &tiny_timer));
258 ASSERT(0 == uv_timer_init(uv_default_loop(), &huge_timer1));
259 ASSERT(0 == uv_timer_start(&tiny_timer, huge_repeat_cb, 2, 2));
260 ASSERT(0 == uv_timer_start(&huge_timer1, huge_repeat_cb, 1, (uint64_t) -1));
261 ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
262 MAKE_VALGRIND_HAPPY();
263 return 0;
264}
265
266
267static unsigned int timer_run_once_timer_cb_called;
268
269
270static void timer_run_once_timer_cb(uv_timer_t* handle) {
271 timer_run_once_timer_cb_called++;
272}
273
274
275TEST_IMPL(timer_run_once) {
276 uv_timer_t timer_handle;
277
278 ASSERT(0 == uv_timer_init(uv_default_loop(), &timer_handle));
279 ASSERT(0 == uv_timer_start(&timer_handle, timer_run_once_timer_cb, 0, 0));
280 ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE));
281 ASSERT(1 == timer_run_once_timer_cb_called);
282
283 ASSERT(0 == uv_timer_start(&timer_handle, timer_run_once_timer_cb, 1, 0));
284 ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE));
285 ASSERT(2 == timer_run_once_timer_cb_called);
286
287 uv_close((uv_handle_t*) &timer_handle, NULL);
288 ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE));
289
290 MAKE_VALGRIND_HAPPY();
291 return 0;
292}
293
294
295TEST_IMPL(timer_null_callback) {
296 uv_timer_t handle;
297
298 ASSERT(0 == uv_timer_init(uv_default_loop(), &handle));
299 ASSERT(UV_EINVAL == uv_timer_start(&handle, NULL, 100, 100));
300
301 MAKE_VALGRIND_HAPPY();
302 return 0;
303}
304
305
306static uint64_t timer_early_check_expected_time;
307
308
309static void timer_early_check_cb(uv_timer_t* handle) {
310 uint64_t hrtime = uv_hrtime() / 1000000;
311 ASSERT(hrtime >= timer_early_check_expected_time);
312}
313
314
315TEST_IMPL(timer_early_check) {
316 uv_timer_t timer_handle;
317 const uint64_t timeout_ms = 10;
318
319 timer_early_check_expected_time = uv_now(uv_default_loop()) + timeout_ms;
320
321 ASSERT(0 == uv_timer_init(uv_default_loop(), &timer_handle));
322 ASSERT(0 == uv_timer_start(&timer_handle, timer_early_check_cb, timeout_ms, 0));
323 ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
324
325 uv_close((uv_handle_t*) &timer_handle, NULL);
326 ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
327
328 MAKE_VALGRIND_HAPPY();
329 return 0;
330}
331