1 /**************************************************************************
2 *
3 * Copyright (C) 2009 Andreas.Fink (Andreas.Fink85@gmail.com)
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License version 2
7 * as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 **************************************************************************/
17
18 #include <time.h>
19 #include <sys/time.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23
24 #include "colors.h"
25 #include "timer.h"
26 #include "test.h"
27
28 bool warnings_for_timers = true;
29 bool debug_timers = false;
30 #define MOCK_ORIGIN 1000000
31
32 // All active timers
33 static GList *timers = NULL;
34
35 long long get_time_ms();
36
default_timers()37 void default_timers()
38 {
39 timers = NULL;
40 }
41
cleanup_timers()42 void cleanup_timers()
43 {
44 if (debug_timers)
45 fprintf(stderr, "tint2: timers: %s\n", __FUNCTION__);
46 g_list_free(timers);
47 timers = NULL;
48 }
49
init_timer(Timer * timer,const char * name)50 void init_timer(Timer *timer, const char *name)
51 {
52 if (debug_timers)
53 fprintf(stderr, "tint2: timers: %s: %s, %p\n", __FUNCTION__, name, (void *)timer);
54 bzero(timer, sizeof(*timer));
55 strncpy(timer->name_, name, sizeof(timer->name_));
56 if (!g_list_find(timers, timer)) {
57 timers = g_list_append(timers, timer);
58 }
59 }
60
destroy_timer(Timer * timer)61 void destroy_timer(Timer *timer)
62 {
63 if (warnings_for_timers && !g_list_find(timers, timer)) {
64 fprintf(stderr, RED "tint2: Attempt to destroy nonexisting timer: %s" RESET "\n", timer->name_);
65 return;
66 }
67 if (debug_timers)
68 fprintf(stderr, "tint2: timers: %s: %s, %p\n", __FUNCTION__, timer->name_, (void *)timer);
69 timers = g_list_remove(timers, timer);
70 }
71
change_timer(Timer * timer,bool enabled,int delay_ms,int period_ms,TimerCallback * callback,void * arg)72 void change_timer(Timer *timer, bool enabled, int delay_ms, int period_ms, TimerCallback *callback, void *arg)
73 {
74 if (!g_list_find(timers, timer)) {
75 fprintf(stderr, RED "tint2: Attempt to change unknown timer" RESET "\n");
76 init_timer(timer, "unknown");
77 }
78 timer->enabled_ = enabled;
79 timer->expiration_time_ms_ = get_time_ms() + delay_ms;
80 timer->period_ms_ = period_ms;
81 timer->callback_ = callback;
82 timer->arg_ = arg;
83 if (debug_timers)
84 fprintf(stderr,
85 "tint2: timers: %s: %s, %p: %s, expires %lld, period %d\n",
86 __FUNCTION__,
87 timer->name_,
88 (void *)timer,
89 timer->enabled_ ? "on" : "off",
90 timer->expiration_time_ms_,
91 timer->period_ms_);
92 }
93
stop_timer(Timer * timer)94 void stop_timer(Timer *timer)
95 {
96 change_timer(timer, false, 0, 0, NULL, NULL);
97 }
98
get_duration_to_next_timer_expiration()99 struct timeval *get_duration_to_next_timer_expiration()
100 {
101 static struct timeval result = {0, 0};
102 long long min_expiration_time = -1;
103 Timer *next_timer = NULL;
104 for (GList *it = timers; it; it = it->next) {
105 Timer *timer = (Timer *)it->data;
106 if (!timer->enabled_)
107 continue;
108 if (min_expiration_time < 0 || timer->expiration_time_ms_ < min_expiration_time) {
109 min_expiration_time = timer->expiration_time_ms_;
110 next_timer = timer;
111 }
112 }
113 if (min_expiration_time < 0) {
114 if (debug_timers)
115 fprintf(stderr,
116 "tint2: timers: %s: no active timer\n",
117 __FUNCTION__);
118 return NULL;
119 }
120 long long now = get_time_ms();
121 long long duration = min_expiration_time - now;
122 if (debug_timers)
123 fprintf(stderr,
124 "tint2: timers: %s: t=%lld, %lld to next timer: %s, %p: %s, expires %lld, period %d\n",
125 __FUNCTION__,
126 now,
127 duration,
128 next_timer->name_,
129 (void *)next_timer,
130 next_timer->enabled_ ? "on" : "off",
131 next_timer->expiration_time_ms_,
132 next_timer->period_ms_);
133 result.tv_sec = duration / 1000;
134 result.tv_usec = 1000 * (duration - result.tv_sec);
135 return &result;
136 }
137
handle_expired_timers()138 void handle_expired_timers()
139 {
140 long long now = get_time_ms();
141 bool expired_timers = false;
142 for (GList *it = timers; it; it = it->next) {
143 Timer *timer = (Timer *)it->data;
144 if (timer->enabled_ && timer->callback_ && timer->expiration_time_ms_ <= now)
145 expired_timers = true;
146 }
147 if (!expired_timers)
148 return;
149
150 // We make a copy of the timer list, as the callbacks may create new timers,
151 // which we don't want to trigger in this event loop iteration,
152 // to prevent infinite loops.
153 GList *current_timers = g_list_copy(timers);
154
155 // Mark all timers as not handled.
156 // This is to ensure not triggering a timer more than once per event loop iteration,
157 // in case it is modified from a callback.
158 for (GList *it = current_timers; it; it = it->next) {
159 Timer *timer = (Timer *)it->data;
160 timer->handled_ = false;
161 }
162
163 bool triggered;
164 do {
165 triggered = false;
166 for (GList *it = current_timers; it; it = it->next) {
167 Timer *timer = (Timer *)it->data;
168 // Check that it is still registered.
169 if (!g_list_find(timers, timer))
170 continue;
171 if (!timer->enabled_ || timer->handled_ || !timer->callback_ || timer->expiration_time_ms_ > now)
172 continue;
173 timer->handled_ = true;
174 if (timer->period_ms_ == 0) {
175 // One shot timer, turn it off.
176 timer->enabled_ = false;
177 } else {
178 // Periodic timer, reschedule.
179 timer->expiration_time_ms_ = now + timer->period_ms_;
180 }
181 if (debug_timers)
182 fprintf(stderr,
183 "tint2: timers: %s: t=%lld, triggering %s, %p: %s, expires %lld, period %d\n",
184 __FUNCTION__,
185 now,
186 timer->name_,
187 (void *)timer,
188 timer->enabled_ ? "on" : "off",
189 timer->expiration_time_ms_,
190 timer->period_ms_);
191 timer->callback_(timer->arg_);
192 // The callback may have modified timers, so start from scratch
193 triggered = true;
194 break;
195 }
196 } while (triggered);
197
198 g_list_free(current_timers);
199 }
200
201 // Time helper functions
202
203 static struct timespec mock_time = {0, 0};
set_mock_time(struct timespec * tp)204 void set_mock_time(struct timespec *tp)
205 {
206 mock_time = *tp;
207 if (debug_timers)
208 fprintf(stderr,
209 "tint2: timers: %s: t=%lld\n",
210 __FUNCTION__,
211 get_time_ms());
212 }
213
set_mock_time_ms(u_int64_t ms)214 void set_mock_time_ms(u_int64_t ms)
215 {
216 struct timespec t;
217 t.tv_sec = ms / 1000;
218 t.tv_nsec = (ms % 1000) * 1000 * 1000;
219 set_mock_time(&t);
220 }
221
gettime(struct timespec * tp)222 int gettime(struct timespec *tp)
223 {
224 if (mock_time.tv_sec || mock_time.tv_nsec) {
225 *tp = mock_time;
226 return 0;
227 }
228 // CLOCK_BOOTTIME under Linux is the same as CLOCK_MONOTONIC under *BSD.
229 #ifdef CLOCK_BOOTTIME
230 return clock_gettime(CLOCK_BOOTTIME, tp);
231 #else
232 return clock_gettime(CLOCK_MONOTONIC, tp);
233 #endif
234 }
235
compare_timespecs(const struct timespec * t1,const struct timespec * t2)236 gint compare_timespecs(const struct timespec *t1, const struct timespec *t2)
237 {
238 if (t1->tv_sec < t2->tv_sec)
239 return -1;
240 else if (t1->tv_sec == t2->tv_sec) {
241 if (t1->tv_nsec < t2->tv_nsec)
242 return -1;
243 else if (t1->tv_nsec == t2->tv_nsec)
244 return 0;
245 else
246 return 1;
247 } else
248 return 1;
249 }
250
add_msec_to_timespec(struct timespec ts,int msec)251 struct timespec add_msec_to_timespec(struct timespec ts, int msec)
252 {
253 ts.tv_sec += msec / 1000;
254 ts.tv_nsec += (msec % 1000) * 1000000;
255 if (ts.tv_nsec >= 1000000000) { // 10^9
256 ts.tv_sec++;
257 ts.tv_nsec -= 1000000000;
258 }
259 return ts;
260 }
261
262 static double profiling_get_time_old_time = 0;
263
get_time()264 double get_time()
265 {
266 struct timespec cur_time;
267 gettime(&cur_time);
268 return cur_time.tv_sec + cur_time.tv_nsec * 1.0e-9;
269 }
270
get_time_ms()271 long long get_time_ms()
272 {
273 struct timespec cur_time;
274 gettime(&cur_time);
275 return cur_time.tv_sec * 1000LL + cur_time.tv_nsec / 1000000LL;
276 }
277
profiling_get_time()278 double profiling_get_time()
279 {
280 double t = get_time();
281 if (profiling_get_time_old_time <= 0)
282 profiling_get_time_old_time = t;
283 double delta = t - profiling_get_time_old_time;
284 profiling_get_time_old_time = t;
285 return delta;
286 }
287
288 ///////////////////////////////////////////////////////////////////////////////
289 // Tests start here
290
timeval_to_ms(struct timeval * v)291 static int64_t timeval_to_ms(struct timeval *v)
292 {
293 if (!v)
294 return -1;
295 return (int64_t)(v->tv_sec * 1000 + v->tv_usec / 1000);
296 }
297
trigger_callback(void * arg)298 static void trigger_callback(void *arg)
299 {
300 int *triggered = (int *)arg;
301 *triggered += 1;
302 }
303
304 typedef struct {
305 Timer *timer;
306 int triggered;
307 bool stop;
308 bool change;
309 int change_value_ms;
310 int change_interval_ms;
311 bool add;
312 int add_value_ms;
313 int add_interval_ms;
314 bool stop_other;
315 bool change_other;
316 int change_other_value_ms;
317 int change_other_interval_ms;
318 Timer *other;
319 } TimeoutContainer;
320
container_callback(void * arg)321 static void container_callback(void *arg)
322 {
323 TimeoutContainer *container = (TimeoutContainer *)arg;
324 container->triggered += 1;
325 if (container->stop)
326 stop_timer(container->timer);
327 else if (container->change) {
328 change_timer(container->timer,
329 true,
330 container->change_value_ms,
331 container->change_interval_ms,
332 container_callback,
333 arg);
334 if (container->change_interval_ms)
335 container->change = false;
336 }
337 if (container->add) {
338 Timer *timer = calloc(1, sizeof(Timer));
339 init_timer(timer, "container_callback");
340 change_timer(timer, true, container->add_value_ms, container->add_interval_ms, container_callback, arg);
341 container->add = false;
342 }
343 if (container->stop_other)
344 stop_timer(container->other);
345 else if (container->change_other) {
346 change_timer(container->other,
347 true,
348 container->change_other_value_ms,
349 container->change_other_interval_ms,
350 container_callback,
351 arg);
352 container->change_other = false;
353 }
354 }
355
TEST(mock_time)356 TEST(mock_time)
357 {
358 struct timespec t1 = {1000, 2};
359 struct timespec t2 = {0, 0};
360 struct timespec t3 = {2000, 3};
361 int ret;
362 set_mock_time(&t1);
363 ret = gettime(&t2);
364 ASSERT_EQUAL(ret, 0);
365 ASSERT_EQUAL(t1.tv_sec, t2.tv_sec);
366 ASSERT_EQUAL(t1.tv_nsec, t2.tv_nsec);
367
368 set_mock_time(&t3);
369 ret = gettime(&t2);
370 ASSERT_EQUAL(ret, 0);
371 ASSERT_EQUAL(t3.tv_sec, t2.tv_sec);
372 ASSERT_EQUAL(t3.tv_nsec, t2.tv_nsec);
373 }
374
TEST(mock_time_ms)375 TEST(mock_time_ms)
376 {
377 struct timespec t1 = {1000, 2 * 1000 * 1000};
378 struct timespec t2 = {0, 0};
379 struct timespec t3 = {2000, 3 * 1000 * 1000};
380 int ret;
381 set_mock_time_ms(1000 * 1000 + 2);
382 ret = gettime(&t2);
383 ASSERT_EQUAL(ret, 0);
384 ASSERT_EQUAL(t1.tv_sec, t2.tv_sec);
385 ASSERT_EQUAL(t1.tv_nsec, t2.tv_nsec);
386
387 set_mock_time_ms(2000 * 1000 + 3);
388 ret = gettime(&t2);
389 ASSERT_EQUAL(ret, 0);
390 ASSERT_EQUAL(t3.tv_sec, t2.tv_sec);
391 ASSERT_EQUAL(t3.tv_nsec, t2.tv_nsec);
392 }
393
TEST(change_timer_simple)394 TEST(change_timer_simple)
395 {
396 u_int64_t origin = MOCK_ORIGIN;
397 int triggered = 0;
398 Timer timer;
399 init_timer(&timer, __FUNCTION__);
400
401 set_mock_time_ms(origin + 0);
402 change_timer(&timer, true, 200, 0, trigger_callback, &triggered);
403 handle_expired_timers();
404 ASSERT_EQUAL(triggered, 0);
405
406 set_mock_time_ms(origin + 100);
407 handle_expired_timers();
408 ASSERT_EQUAL(triggered, 0);
409
410 set_mock_time_ms(origin + 190);
411 handle_expired_timers();
412 ASSERT_EQUAL(triggered, 0);
413
414 set_mock_time_ms(origin + 200);
415 handle_expired_timers();
416 ASSERT_EQUAL(triggered, 1);
417
418 set_mock_time_ms(origin + 300);
419 handle_expired_timers();
420 ASSERT_EQUAL(triggered, 1);
421
422 set_mock_time_ms(origin + 500);
423 handle_expired_timers();
424 ASSERT_EQUAL(triggered, 1);
425 }
426
TEST(change_timer_simple_two)427 TEST(change_timer_simple_two)
428 {
429 u_int64_t origin = MOCK_ORIGIN;
430 int triggered = 0;
431 Timer t1;
432 init_timer(&t1, "t1");
433 Timer t2;
434 init_timer(&t2, "t2");
435
436 set_mock_time_ms(origin + 0);
437 change_timer(&t1, true, 100, 0, trigger_callback, &triggered);
438 change_timer(&t2, true, 200, 0, trigger_callback, &triggered);
439 handle_expired_timers();
440 ASSERT_EQUAL(triggered, 0);
441
442 set_mock_time_ms(origin + 50);
443 handle_expired_timers();
444 ASSERT_EQUAL(triggered, 0);
445
446 set_mock_time_ms(origin + 100);
447 handle_expired_timers();
448 ASSERT_EQUAL(triggered, 1);
449
450 set_mock_time_ms(origin + 190);
451 handle_expired_timers();
452 ASSERT_EQUAL(triggered, 1);
453
454 set_mock_time_ms(origin + 200);
455 handle_expired_timers();
456 ASSERT_EQUAL(triggered, 2);
457
458 set_mock_time_ms(origin + 300);
459 handle_expired_timers();
460 ASSERT_EQUAL(triggered, 2);
461
462 set_mock_time_ms(origin + 500);
463 handle_expired_timers();
464 ASSERT_EQUAL(triggered, 2);
465 }
466
TEST(change_timer_simple_two_reversed)467 TEST(change_timer_simple_two_reversed)
468 {
469 u_int64_t origin = MOCK_ORIGIN;
470 int triggered = 0;
471 Timer t1;
472 init_timer(&t1, "t1");
473 Timer t2;
474 init_timer(&t2, "t2");
475
476 set_mock_time_ms(origin + 0);
477 change_timer(&t1, true, 200, 0, trigger_callback, &triggered);
478 change_timer(&t2, true, 100, 0, trigger_callback, &triggered);
479 handle_expired_timers();
480 ASSERT_EQUAL(triggered, 0);
481
482 set_mock_time_ms(origin + 50);
483 handle_expired_timers();
484 ASSERT_EQUAL(triggered, 0);
485
486 set_mock_time_ms(origin + 100);
487 handle_expired_timers();
488 ASSERT_EQUAL(triggered, 1);
489
490 set_mock_time_ms(origin + 190);
491 handle_expired_timers();
492 ASSERT_EQUAL(triggered, 1);
493
494 set_mock_time_ms(origin + 200);
495 handle_expired_timers();
496 ASSERT_EQUAL(triggered, 2);
497
498 set_mock_time_ms(origin + 300);
499 handle_expired_timers();
500 ASSERT_EQUAL(triggered, 2);
501
502 set_mock_time_ms(origin + 500);
503 handle_expired_timers();
504 ASSERT_EQUAL(triggered, 2);
505 }
506
TEST(change_timer_simple_two_overlap)507 TEST(change_timer_simple_two_overlap)
508 {
509 u_int64_t origin = MOCK_ORIGIN;
510 int triggered = 0;
511 Timer t1;
512 init_timer(&t1, "t1");
513 Timer t2;
514 init_timer(&t2, "t2");
515
516 set_mock_time_ms(origin + 0);
517 change_timer(&t1, true, 100, 0, trigger_callback, &triggered);
518 change_timer(&t2, true, 100, 0, trigger_callback, &triggered);
519 handle_expired_timers();
520 ASSERT_EQUAL(triggered, 0);
521
522 set_mock_time_ms(origin + 50);
523 handle_expired_timers();
524 ASSERT_EQUAL(triggered, 0);
525
526 set_mock_time_ms(origin + 100);
527 handle_expired_timers();
528 ASSERT_EQUAL(triggered, 2);
529
530 set_mock_time_ms(origin + 200);
531 handle_expired_timers();
532 ASSERT_EQUAL(triggered, 2);
533
534 set_mock_time_ms(origin + 300);
535 handle_expired_timers();
536 ASSERT_EQUAL(triggered, 2);
537 }
538
TEST(change_timer_simple_inside_callback)539 TEST(change_timer_simple_inside_callback)
540 {
541 u_int64_t origin = MOCK_ORIGIN;
542 TimeoutContainer container;
543 bzero(&container, sizeof(container));
544 Timer timer;
545 init_timer(&timer, __FUNCTION__);
546
547 set_mock_time_ms(origin + 0);
548
549 container.add = true;
550 container.add_value_ms = 100;
551 container.timer = &timer;
552 change_timer(container.timer, true, 200, 0, container_callback, &container);
553 handle_expired_timers();
554 ASSERT_EQUAL(container.triggered, 0);
555
556 set_mock_time_ms(origin + 100);
557 handle_expired_timers();
558 ASSERT_EQUAL(container.triggered, 0);
559
560 set_mock_time_ms(origin + 200);
561 handle_expired_timers();
562 ASSERT_EQUAL(container.triggered, 1);
563
564 set_mock_time_ms(origin + 250);
565 handle_expired_timers();
566 ASSERT_EQUAL(container.triggered, 1);
567
568 set_mock_time_ms(origin + 300);
569 handle_expired_timers();
570 ASSERT_EQUAL(container.triggered, 2);
571
572 set_mock_time_ms(origin + 500);
573 handle_expired_timers();
574 ASSERT_EQUAL(container.triggered, 2);
575 }
576
TEST(change_timer_multi)577 TEST(change_timer_multi)
578 {
579 u_int64_t origin = MOCK_ORIGIN;
580 int triggered = 0;
581 Timer timer;
582 init_timer(&timer, __FUNCTION__);
583
584 set_mock_time_ms(origin + 0);
585 change_timer(&timer, true, 200, 100, trigger_callback, &triggered);
586 handle_expired_timers();
587 ASSERT_EQUAL(triggered, 0);
588
589 set_mock_time_ms(origin + 50);
590 handle_expired_timers();
591 ASSERT_EQUAL(triggered, 0);
592
593 set_mock_time_ms(origin + 150);
594 handle_expired_timers();
595 ASSERT_EQUAL(triggered, 0);
596
597 set_mock_time_ms(origin + 200);
598 handle_expired_timers();
599 ASSERT_EQUAL(triggered, 1);
600
601 set_mock_time_ms(origin + 250);
602 handle_expired_timers();
603 ASSERT_EQUAL(triggered, 1);
604
605 set_mock_time_ms(origin + 300);
606 handle_expired_timers();
607 ASSERT_EQUAL(triggered, 2);
608
609 set_mock_time_ms(origin + 400);
610 handle_expired_timers();
611 ASSERT_EQUAL(triggered, 3);
612
613 set_mock_time_ms(origin + 500);
614 handle_expired_timers();
615 ASSERT_EQUAL(triggered, 4);
616 }
617
TEST(change_timer_multi_two)618 TEST(change_timer_multi_two)
619 {
620 u_int64_t origin = MOCK_ORIGIN;
621 int triggered = 0;
622 Timer t1;
623 init_timer(&t1, "t1");
624 Timer t2;
625 init_timer(&t2, "t2");
626
627 set_mock_time_ms(origin + 0);
628 change_timer(&t1, true, 100, 100, trigger_callback, &triggered);
629 change_timer(&t2, true, 200, 200, trigger_callback, &triggered);
630 handle_expired_timers();
631 ASSERT_EQUAL(triggered, 0);
632
633 set_mock_time_ms(origin + 50);
634 handle_expired_timers();
635 ASSERT_EQUAL(triggered, 0);
636
637 set_mock_time_ms(origin + 100);
638 handle_expired_timers();
639 ASSERT_EQUAL(triggered, 1);
640
641 set_mock_time_ms(origin + 200);
642 handle_expired_timers();
643 ASSERT_EQUAL(triggered, 3);
644
645 set_mock_time_ms(origin + 300);
646 handle_expired_timers();
647 ASSERT_EQUAL(triggered, 4);
648
649 set_mock_time_ms(origin + 400);
650 handle_expired_timers();
651 ASSERT_EQUAL(triggered, 6);
652 }
653
TEST(change_timer_multi_two_overlap)654 TEST(change_timer_multi_two_overlap)
655 {
656 u_int64_t origin = MOCK_ORIGIN;
657 int triggered = 0;
658 Timer t1;
659 init_timer(&t1, "t1");
660 Timer t2;
661 init_timer(&t2, "t2");
662
663 set_mock_time_ms(origin + 0);
664 change_timer(&t1, true, 100, 100, trigger_callback, &triggered);
665 change_timer(&t2, true, 100, 100, trigger_callback, &triggered);
666 handle_expired_timers();
667 ASSERT_EQUAL(triggered, 0);
668
669 set_mock_time_ms(origin + 50);
670 handle_expired_timers();
671 ASSERT_EQUAL(triggered, 0);
672
673 set_mock_time_ms(origin + 100);
674 handle_expired_timers();
675 ASSERT_EQUAL(triggered, 2);
676
677 set_mock_time_ms(origin + 150);
678 handle_expired_timers();
679 ASSERT_EQUAL(triggered, 2);
680
681 set_mock_time_ms(origin + 200);
682 handle_expired_timers();
683 ASSERT_EQUAL(triggered, 4);
684
685 set_mock_time_ms(origin + 300);
686 handle_expired_timers();
687 ASSERT_EQUAL(triggered, 6);
688
689 set_mock_time_ms(origin + 400);
690 handle_expired_timers();
691 ASSERT_EQUAL(triggered, 8);
692 }
693
TEST(change_timer_simple_multi_two)694 TEST(change_timer_simple_multi_two)
695 {
696 u_int64_t origin = MOCK_ORIGIN;
697 int triggered = 0;
698 Timer t1;
699 init_timer(&t1, "t1");
700 Timer t2;
701 init_timer(&t2, "t2");
702
703 set_mock_time_ms(origin + 0);
704 change_timer(&t1, true, 100, 100, trigger_callback, &triggered);
705 change_timer(&t2, true, 200, 0, trigger_callback, &triggered);
706 handle_expired_timers();
707 ASSERT_EQUAL(triggered, 0);
708
709 set_mock_time_ms(origin + 50);
710 handle_expired_timers();
711 ASSERT_EQUAL(triggered, 0);
712
713 set_mock_time_ms(origin + 100);
714 handle_expired_timers();
715 ASSERT_EQUAL(triggered, 1);
716
717 set_mock_time_ms(origin + 150);
718 handle_expired_timers();
719 ASSERT_EQUAL(triggered, 1);
720
721 set_mock_time_ms(origin + 200);
722 handle_expired_timers();
723 ASSERT_EQUAL(triggered, 3);
724
725 set_mock_time_ms(origin + 300);
726 handle_expired_timers();
727 ASSERT_EQUAL(triggered, 4);
728
729 set_mock_time_ms(origin + 400);
730 handle_expired_timers();
731 ASSERT_EQUAL(triggered, 5);
732 }
733
TEST(change_timer_simple_multi_two_overlap)734 TEST(change_timer_simple_multi_two_overlap)
735 {
736 u_int64_t origin = MOCK_ORIGIN;
737 int triggered = 0;
738 Timer t1;
739 init_timer(&t1, "t1");
740 Timer t2;
741 init_timer(&t2, "t2");
742
743 set_mock_time_ms(origin + 0);
744 change_timer(&t1, true, 100, 100, trigger_callback, &triggered);
745 change_timer(&t2, true, 100, 0, trigger_callback, &triggered);
746 handle_expired_timers();
747 ASSERT_EQUAL(triggered, 0);
748
749 set_mock_time_ms(origin + 50);
750 handle_expired_timers();
751 ASSERT_EQUAL(triggered, 0);
752
753 set_mock_time_ms(origin + 100);
754 handle_expired_timers();
755 ASSERT_EQUAL(triggered, 2);
756
757 set_mock_time_ms(origin + 150);
758 handle_expired_timers();
759 ASSERT_EQUAL(triggered, 2);
760
761 set_mock_time_ms(origin + 200);
762 handle_expired_timers();
763 ASSERT_EQUAL(triggered, 3);
764
765 set_mock_time_ms(origin + 300);
766 handle_expired_timers();
767 ASSERT_EQUAL(triggered, 4);
768
769 set_mock_time_ms(origin + 400);
770 handle_expired_timers();
771 ASSERT_EQUAL(triggered, 5);
772 }
773
TEST(stop_timer_simple_two)774 TEST(stop_timer_simple_two)
775 {
776 u_int64_t origin = MOCK_ORIGIN;
777 int triggered = 0;
778 Timer t1;
779 init_timer(&t1, "t1");
780 Timer t2;
781 init_timer(&t2, "t2");
782
783 set_mock_time_ms(origin + 0);
784 change_timer(&t1, true, 100, 0, trigger_callback, &triggered);
785 change_timer(&t2, true, 200, 0, trigger_callback, &triggered);
786 handle_expired_timers();
787 ASSERT_EQUAL(triggered, 0);
788
789 set_mock_time_ms(origin + 50);
790 handle_expired_timers();
791 ASSERT_EQUAL(triggered, 0);
792
793 stop_timer(&t1);
794
795 set_mock_time_ms(origin + 100);
796 handle_expired_timers();
797 ASSERT_EQUAL(triggered, 0);
798
799 set_mock_time_ms(origin + 190);
800 handle_expired_timers();
801 ASSERT_EQUAL(triggered, 0);
802
803 set_mock_time_ms(origin + 200);
804 handle_expired_timers();
805 ASSERT_EQUAL(triggered, 1);
806
807 set_mock_time_ms(origin + 300);
808 handle_expired_timers();
809 ASSERT_EQUAL(triggered, 1);
810
811 set_mock_time_ms(origin + 500);
812 handle_expired_timers();
813 ASSERT_EQUAL(triggered, 1);
814 }
815
TEST(stop_timer_simple_two_reversed)816 TEST(stop_timer_simple_two_reversed)
817 {
818 u_int64_t origin = MOCK_ORIGIN;
819 int triggered = 0;
820 Timer t1;
821 init_timer(&t1, "t1");
822 Timer t2;
823 init_timer(&t2, "t2");
824
825 set_mock_time_ms(origin + 0);
826 change_timer(&t1, true, 100, 0, trigger_callback, &triggered);
827 change_timer(&t2, true, 200, 0, trigger_callback, &triggered);
828 handle_expired_timers();
829 ASSERT_EQUAL(triggered, 0);
830
831 set_mock_time_ms(origin + 50);
832 handle_expired_timers();
833 ASSERT_EQUAL(triggered, 0);
834
835 stop_timer(&t2);
836
837 set_mock_time_ms(origin + 100);
838 handle_expired_timers();
839 ASSERT_EQUAL(triggered, 1);
840
841 set_mock_time_ms(origin + 190);
842 handle_expired_timers();
843 ASSERT_EQUAL(triggered, 1);
844
845 set_mock_time_ms(origin + 200);
846 handle_expired_timers();
847 ASSERT_EQUAL(triggered, 1);
848
849 set_mock_time_ms(origin + 300);
850 handle_expired_timers();
851 ASSERT_EQUAL(triggered, 1);
852
853 set_mock_time_ms(origin + 500);
854 handle_expired_timers();
855 ASSERT_EQUAL(triggered, 1);
856 }
857
TEST(stop_timer_simple_inside_callback)858 TEST(stop_timer_simple_inside_callback)
859 {
860 u_int64_t origin = MOCK_ORIGIN;
861 TimeoutContainer container;
862 bzero(&container, sizeof(container));
863 Timer t1;
864 init_timer(&t1, "t1");
865
866 set_mock_time_ms(origin + 0);
867
868 container.stop = true;
869 container.timer = &t1;
870 change_timer(&t1, true, 200, 0, container_callback, &container);
871 handle_expired_timers();
872 ASSERT_EQUAL(container.triggered, 0);
873
874 set_mock_time_ms(origin + 100);
875 handle_expired_timers();
876 ASSERT_EQUAL(container.triggered, 0);
877
878 set_mock_time_ms(origin + 200);
879 handle_expired_timers();
880 ASSERT_EQUAL(container.triggered, 1);
881
882 set_mock_time_ms(origin + 250);
883 handle_expired_timers();
884 ASSERT_EQUAL(container.triggered, 1);
885
886 set_mock_time_ms(origin + 300);
887 handle_expired_timers();
888 ASSERT_EQUAL(container.triggered, 1);
889
890 set_mock_time_ms(origin + 500);
891 handle_expired_timers();
892 ASSERT_EQUAL(container.triggered, 1);
893 }
894
TEST(stop_timer_simple_other_inside_callback)895 TEST(stop_timer_simple_other_inside_callback)
896 {
897 u_int64_t origin = MOCK_ORIGIN;
898 TimeoutContainer container;
899 bzero(&container, sizeof(container));
900 Timer t1;
901 init_timer(&t1, "t1");
902 Timer t2;
903 init_timer(&t1, "t2");
904 int triggered_other = 0;
905
906 set_mock_time_ms(origin + 0);
907
908 container.stop_other = true;
909 container.timer = &t1;
910 change_timer(&t1, true, 100, 0, container_callback, &container);
911 container.other = &t2;
912 change_timer(&t2, true, 200, 0, trigger_callback, &triggered_other);
913 handle_expired_timers();
914 ASSERT_EQUAL(container.triggered, 0);
915 ASSERT_EQUAL(triggered_other, 0);
916
917 set_mock_time_ms(origin + 100);
918 handle_expired_timers();
919 ASSERT_EQUAL(container.triggered, 1);
920 ASSERT_EQUAL(triggered_other, 0);
921
922 set_mock_time_ms(origin + 200);
923 handle_expired_timers();
924 ASSERT_EQUAL(container.triggered, 1);
925 ASSERT_EQUAL(triggered_other, 0);
926
927 set_mock_time_ms(origin + 300);
928 handle_expired_timers();
929 ASSERT_EQUAL(container.triggered, 1);
930 ASSERT_EQUAL(triggered_other, 0);
931 }
932
TEST(stop_timer_multi)933 TEST(stop_timer_multi)
934 {
935 u_int64_t origin = MOCK_ORIGIN;
936 int triggered = 0;
937 Timer t1;
938 init_timer(&t1, "t1");
939
940 set_mock_time_ms(origin + 0);
941 change_timer(&t1, true, 100, 100, trigger_callback, &triggered);
942 handle_expired_timers();
943 ASSERT_EQUAL(triggered, 0);
944
945 set_mock_time_ms(origin + 50);
946 handle_expired_timers();
947 ASSERT_EQUAL(triggered, 0);
948
949 set_mock_time_ms(origin + 100);
950 handle_expired_timers();
951 ASSERT_EQUAL(triggered, 1);
952
953 set_mock_time_ms(origin + 150);
954 handle_expired_timers();
955 ASSERT_EQUAL(triggered, 1);
956
957 set_mock_time_ms(origin + 200);
958 handle_expired_timers();
959 ASSERT_EQUAL(triggered, 2);
960
961 stop_timer(&t1);
962
963 set_mock_time_ms(origin + 300);
964 handle_expired_timers();
965 ASSERT_EQUAL(triggered, 2);
966
967 set_mock_time_ms(origin + 400);
968 handle_expired_timers();
969 ASSERT_EQUAL(triggered, 2);
970 }
971
TEST(stop_timer_multi_two)972 TEST(stop_timer_multi_two)
973 {
974 u_int64_t origin = MOCK_ORIGIN;
975 int triggered = 0;
976 Timer t1;
977 init_timer(&t1, "t1");
978 Timer t2;
979 init_timer(&t2, "t2");
980
981 set_mock_time_ms(origin + 0);
982 change_timer(&t1, true, 100, 100, trigger_callback, &triggered);
983 change_timer(&t2, true, 100, 100, trigger_callback, &triggered);
984 handle_expired_timers();
985 ASSERT_EQUAL(triggered, 0);
986
987 set_mock_time_ms(origin + 50);
988 handle_expired_timers();
989 ASSERT_EQUAL(triggered, 0);
990
991 set_mock_time_ms(origin + 100);
992 handle_expired_timers();
993 ASSERT_EQUAL(triggered, 2);
994
995 set_mock_time_ms(origin + 150);
996 handle_expired_timers();
997 ASSERT_EQUAL(triggered, 2);
998
999 set_mock_time_ms(origin + 200);
1000 handle_expired_timers();
1001 ASSERT_EQUAL(triggered, 4);
1002
1003 stop_timer(&t1);
1004
1005 set_mock_time_ms(origin + 300);
1006 handle_expired_timers();
1007 ASSERT_EQUAL(triggered, 5);
1008
1009 set_mock_time_ms(origin + 400);
1010 handle_expired_timers();
1011 ASSERT_EQUAL(triggered, 6);
1012 }
1013
TEST(stop_timer_multi_inside_callback)1014 TEST(stop_timer_multi_inside_callback)
1015 {
1016 u_int64_t origin = MOCK_ORIGIN;
1017 TimeoutContainer container;
1018 bzero(&container, sizeof(container));
1019 Timer t1;
1020 init_timer(&t1, "t1");
1021
1022 set_mock_time_ms(origin + 0);
1023
1024 container.stop = true;
1025 container.timer = &t1;
1026 change_timer(&t1, true, 100, 100, container_callback, &container);
1027 handle_expired_timers();
1028 ASSERT_EQUAL(container.triggered, 0);
1029
1030 set_mock_time_ms(origin + 50);
1031 handle_expired_timers();
1032 ASSERT_EQUAL(container.triggered, 0);
1033
1034 set_mock_time_ms(origin + 100);
1035 handle_expired_timers();
1036 ASSERT_EQUAL(container.triggered, 1);
1037
1038 set_mock_time_ms(origin + 150);
1039 handle_expired_timers();
1040 ASSERT_EQUAL(container.triggered, 1);
1041
1042 set_mock_time_ms(origin + 200);
1043 handle_expired_timers();
1044 ASSERT_EQUAL(container.triggered, 1);
1045
1046 set_mock_time_ms(origin + 300);
1047 handle_expired_timers();
1048 ASSERT_EQUAL(container.triggered, 1);
1049 }
1050
TEST(stop_timer_multi_other_inside_callback)1051 TEST(stop_timer_multi_other_inside_callback)
1052 {
1053 u_int64_t origin = MOCK_ORIGIN;
1054 TimeoutContainer container;
1055 bzero(&container, sizeof(container));
1056 Timer t1;
1057 init_timer(&t1, "t1");
1058 Timer t2;
1059 init_timer(&t2, "t2");
1060 int triggered_other = 0;
1061
1062 set_mock_time_ms(origin + 0);
1063
1064 container.stop_other = true;
1065 container.timer = &t1;
1066 change_timer(&t1, true, 100, 100, container_callback, &container);
1067 container.other = &t2;
1068 change_timer(&t2, true, 200, 10, trigger_callback, &triggered_other);
1069 handle_expired_timers();
1070 ASSERT_EQUAL(container.triggered, 0);
1071 ASSERT_EQUAL(triggered_other, 0);
1072
1073 set_mock_time_ms(origin + 100);
1074 handle_expired_timers();
1075 ASSERT_EQUAL(container.triggered, 1);
1076 ASSERT_EQUAL(triggered_other, 0);
1077
1078 set_mock_time_ms(origin + 200);
1079 handle_expired_timers();
1080 ASSERT_EQUAL(container.triggered, 2);
1081 ASSERT_EQUAL(triggered_other, 0);
1082
1083 set_mock_time_ms(origin + 300);
1084 handle_expired_timers();
1085 ASSERT_EQUAL(container.triggered, 3);
1086 ASSERT_EQUAL(triggered_other, 0);
1087 }
1088
TEST(change_timer_simple_again)1089 TEST(change_timer_simple_again)
1090 {
1091 u_int64_t origin = MOCK_ORIGIN;
1092 int triggered = 0;
1093 Timer t1;
1094 init_timer(&t1, "t1");
1095
1096 set_mock_time_ms(origin + 0);
1097 change_timer(&t1, true, 200, 0, trigger_callback, &triggered);
1098 handle_expired_timers();
1099 ASSERT_EQUAL(triggered, 0);
1100
1101 set_mock_time_ms(origin + 100);
1102 handle_expired_timers();
1103 ASSERT_EQUAL(triggered, 0);
1104
1105 change_timer(&t1, true, 200, 0, trigger_callback, &triggered);
1106
1107 set_mock_time_ms(origin + 200);
1108 handle_expired_timers();
1109 ASSERT_EQUAL(triggered, 0);
1110
1111 set_mock_time_ms(origin + 250);
1112 handle_expired_timers();
1113 ASSERT_EQUAL(triggered, 0);
1114
1115 set_mock_time_ms(origin + 300);
1116 handle_expired_timers();
1117 ASSERT_EQUAL(triggered, 1);
1118
1119 set_mock_time_ms(origin + 500);
1120 handle_expired_timers();
1121 ASSERT_EQUAL(triggered, 1);
1122 }
1123
TEST(change_timer_simple_two_again)1124 TEST(change_timer_simple_two_again)
1125 {
1126 u_int64_t origin = MOCK_ORIGIN;
1127 int triggered = 0;
1128 Timer t1;
1129 init_timer(&t1, "t1");
1130 Timer t2;
1131 init_timer(&t2, "t2");
1132
1133 set_mock_time_ms(origin + 0);
1134 change_timer(&t1, true, 200, 0, trigger_callback, &triggered);
1135 change_timer(&t2, true, 250, 0, trigger_callback, &triggered);
1136 handle_expired_timers();
1137 ASSERT_EQUAL(triggered, 0);
1138
1139 set_mock_time_ms(origin + 100);
1140 handle_expired_timers();
1141 ASSERT_EQUAL(triggered, 0);
1142
1143 change_timer(&t1, true, 200, 0, trigger_callback, &triggered);
1144
1145 set_mock_time_ms(origin + 200);
1146 handle_expired_timers();
1147 ASSERT_EQUAL(triggered, 0);
1148
1149 set_mock_time_ms(origin + 250);
1150 handle_expired_timers();
1151 ASSERT_EQUAL(triggered, 1);
1152
1153 set_mock_time_ms(origin + 300);
1154 handle_expired_timers();
1155 ASSERT_EQUAL(triggered, 2);
1156
1157 set_mock_time_ms(origin + 500);
1158 handle_expired_timers();
1159 ASSERT_EQUAL(triggered, 2);
1160 }
1161
TEST(change_timer_simple_inside_callback_again)1162 TEST(change_timer_simple_inside_callback_again)
1163 {
1164 u_int64_t origin = MOCK_ORIGIN;
1165 TimeoutContainer container;
1166 bzero(&container, sizeof(container));
1167 Timer t1;
1168 init_timer(&t1, "t1");
1169
1170 set_mock_time_ms(origin + 0);
1171
1172 container.change = true;
1173 container.change_value_ms = 100;
1174 container.timer = &t1;
1175 change_timer(&t1, true, 200, 0, container_callback, &container);
1176 handle_expired_timers();
1177 ASSERT_EQUAL(container.triggered, 0);
1178
1179 set_mock_time_ms(origin + 100);
1180 handle_expired_timers();
1181 ASSERT_EQUAL(container.triggered, 0);
1182
1183 set_mock_time_ms(origin + 200);
1184 handle_expired_timers();
1185 ASSERT_EQUAL(container.triggered, 1);
1186
1187 set_mock_time_ms(origin + 250);
1188 handle_expired_timers();
1189 ASSERT_EQUAL(container.triggered, 1);
1190
1191 set_mock_time_ms(origin + 300);
1192 handle_expired_timers();
1193 ASSERT_EQUAL(container.triggered, 2);
1194
1195 set_mock_time_ms(origin + 350);
1196 handle_expired_timers();
1197 ASSERT_EQUAL(container.triggered, 2);
1198
1199 set_mock_time_ms(origin + 400);
1200 handle_expired_timers();
1201 ASSERT_EQUAL(container.triggered, 3);
1202 }
1203
TEST(change_timer_simple_other_inside_callback)1204 TEST(change_timer_simple_other_inside_callback)
1205 {
1206 u_int64_t origin = MOCK_ORIGIN;
1207 TimeoutContainer container;
1208 bzero(&container, sizeof(container));
1209 Timer t1;
1210 init_timer(&t1, "t1");
1211 Timer t2;
1212 init_timer(&t2, "t2");
1213 int triggered_other = 0;
1214
1215 set_mock_time_ms(origin + 0);
1216
1217 container.change_other = true;
1218 container.change_other_value_ms = 100;
1219 container.timer = &t1;
1220 change_timer(&t1, true, 100, 0, container_callback, &container);
1221 container.other = &t2;
1222 change_timer(&t2, true, 1000, 0, trigger_callback, &triggered_other);
1223 handle_expired_timers();
1224 ASSERT_EQUAL(container.triggered, 0);
1225 ASSERT_EQUAL(triggered_other, 0);
1226
1227 set_mock_time_ms(origin + 100);
1228 handle_expired_timers();
1229 ASSERT_EQUAL(container.triggered, 1);
1230 ASSERT_EQUAL(triggered_other, 0);
1231
1232 set_mock_time_ms(origin + 200);
1233 handle_expired_timers();
1234 ASSERT_EQUAL(container.triggered, 2);
1235 ASSERT_EQUAL(triggered_other, 0);
1236
1237 set_mock_time_ms(origin + 300);
1238 handle_expired_timers();
1239 ASSERT_EQUAL(container.triggered, 2);
1240 ASSERT_EQUAL(triggered_other, 0);
1241 }
1242
TEST(add_change_two_timer_simple_inside_callback)1243 TEST(add_change_two_timer_simple_inside_callback)
1244 {
1245 u_int64_t origin = MOCK_ORIGIN;
1246 TimeoutContainer container;
1247 bzero(&container, sizeof(container));
1248 Timer t1;
1249 init_timer(&t1, "t1");
1250
1251 set_mock_time_ms(origin + 0);
1252
1253 container.add = true;
1254 container.add_value_ms = 100;
1255 container.change = true;
1256 container.change_value_ms = 100;
1257 container.timer = &t1;
1258 change_timer(&t1, true, 200, 0, container_callback, &container);
1259 handle_expired_timers();
1260 ASSERT_EQUAL(container.triggered, 0);
1261
1262 set_mock_time_ms(origin + 100);
1263 handle_expired_timers();
1264 ASSERT_EQUAL(container.triggered, 0);
1265
1266 set_mock_time_ms(origin + 200);
1267 handle_expired_timers();
1268 ASSERT_EQUAL(container.triggered, 1);
1269
1270 // Now we have two running timers, one changing itself to expire after 100 ms when triggered,
1271 // the other firing once after 100 ms
1272 set_mock_time_ms(origin + 250);
1273 handle_expired_timers();
1274 ASSERT_EQUAL(container.triggered, 1);
1275
1276 set_mock_time_ms(origin + 300);
1277 handle_expired_timers();
1278 ASSERT_EQUAL(container.triggered, 3);
1279
1280 set_mock_time_ms(origin + 350);
1281 handle_expired_timers();
1282 ASSERT_EQUAL(container.triggered, 3);
1283
1284 set_mock_time_ms(origin + 400);
1285 handle_expired_timers();
1286 ASSERT_EQUAL(container.triggered, 4);
1287 }
1288
TEST(change_timer_multi_again)1289 TEST(change_timer_multi_again)
1290 {
1291 u_int64_t origin = MOCK_ORIGIN;
1292 int triggered = 0;
1293 Timer t1;
1294 init_timer(&t1, "t1");
1295
1296 set_mock_time_ms(origin + 0);
1297 change_timer(&t1, true, 100, 50, trigger_callback, &triggered);
1298 handle_expired_timers();
1299 ASSERT_EQUAL(triggered, 0);
1300
1301 set_mock_time_ms(origin + 100);
1302 handle_expired_timers();
1303 ASSERT_EQUAL(triggered, 1);
1304
1305 set_mock_time_ms(origin + 150);
1306 handle_expired_timers();
1307 ASSERT_EQUAL(triggered, 2);
1308
1309 set_mock_time_ms(origin + 200);
1310 handle_expired_timers();
1311 ASSERT_EQUAL(triggered, 3);
1312
1313 change_timer(&t1, true, 100, 100, trigger_callback, &triggered);
1314
1315 set_mock_time_ms(origin + 250);
1316 handle_expired_timers();
1317 ASSERT_EQUAL(triggered, 3);
1318
1319 set_mock_time_ms(origin + 300);
1320 handle_expired_timers();
1321 ASSERT_EQUAL(triggered, 4);
1322
1323 set_mock_time_ms(origin + 350);
1324 handle_expired_timers();
1325 ASSERT_EQUAL(triggered, 4);
1326
1327 set_mock_time_ms(origin + 400);
1328 handle_expired_timers();
1329 ASSERT_EQUAL(triggered, 5);
1330 }
1331
TEST(change_timer_simple_multi)1332 TEST(change_timer_simple_multi)
1333 {
1334 u_int64_t origin = MOCK_ORIGIN;
1335 int triggered = 0;
1336 Timer t1;
1337 init_timer(&t1, "t1");
1338
1339 set_mock_time_ms(origin + 0);
1340 change_timer(&t1, true, 100, 0, trigger_callback, &triggered);
1341 handle_expired_timers();
1342 ASSERT_EQUAL(triggered, 0);
1343
1344 set_mock_time_ms(origin + 50);
1345 handle_expired_timers();
1346 ASSERT_EQUAL(triggered, 0);
1347
1348 change_timer(&t1, true, 100, 100, trigger_callback, &triggered);
1349
1350 set_mock_time_ms(origin + 100);
1351 handle_expired_timers();
1352 ASSERT_EQUAL(triggered, 0);
1353
1354 set_mock_time_ms(origin + 150);
1355 handle_expired_timers();
1356 ASSERT_EQUAL(triggered, 1);
1357
1358 set_mock_time_ms(origin + 200);
1359 handle_expired_timers();
1360 ASSERT_EQUAL(triggered, 1);
1361
1362 set_mock_time_ms(origin + 250);
1363 handle_expired_timers();
1364 ASSERT_EQUAL(triggered, 2);
1365
1366 change_timer(&t1, true, 50, 0, trigger_callback, &triggered);
1367
1368 set_mock_time_ms(origin + 300);
1369 handle_expired_timers();
1370 ASSERT_EQUAL(triggered, 3);
1371
1372 set_mock_time_ms(origin + 350);
1373 handle_expired_timers();
1374 ASSERT_EQUAL(triggered, 3);
1375
1376 set_mock_time_ms(origin + 400);
1377 handle_expired_timers();
1378 ASSERT_EQUAL(triggered, 3);
1379 }
1380
TEST(change_timer_multi_inside_callback)1381 TEST(change_timer_multi_inside_callback)
1382 {
1383 u_int64_t origin = MOCK_ORIGIN;
1384 TimeoutContainer container;
1385 bzero(&container, sizeof(container));
1386 Timer t1;
1387 init_timer(&t1, "t1");
1388
1389 set_mock_time_ms(origin + 0);
1390
1391 container.change = true;
1392 container.change_value_ms = 100;
1393 container.change_interval_ms = 100;
1394 container.timer = &t1;
1395 change_timer(&t1, true, 200, 200, container_callback, &container);
1396 handle_expired_timers();
1397 ASSERT_EQUAL(container.triggered, 0);
1398
1399 set_mock_time_ms(origin + 100);
1400 handle_expired_timers();
1401 ASSERT_EQUAL(container.triggered, 0);
1402
1403 set_mock_time_ms(origin + 200);
1404 handle_expired_timers();
1405 ASSERT_EQUAL(container.triggered, 1);
1406
1407 set_mock_time_ms(origin + 250);
1408 handle_expired_timers();
1409 ASSERT_EQUAL(container.triggered, 1);
1410
1411 set_mock_time_ms(origin + 300);
1412 handle_expired_timers();
1413 ASSERT_EQUAL(container.triggered, 2);
1414
1415 set_mock_time_ms(origin + 350);
1416 handle_expired_timers();
1417 ASSERT_EQUAL(container.triggered, 2);
1418
1419 set_mock_time_ms(origin + 400);
1420 handle_expired_timers();
1421 ASSERT_EQUAL(container.triggered, 3);
1422 }
1423
TEST(change_timer_multi_other_inside_callback)1424 TEST(change_timer_multi_other_inside_callback)
1425 {
1426 u_int64_t origin = MOCK_ORIGIN;
1427 TimeoutContainer container;
1428 bzero(&container, sizeof(container));
1429 Timer t1;
1430 init_timer(&t1, "t1");
1431 Timer t2;
1432 init_timer(&t2, "t2");
1433 int triggered_other = 0;
1434
1435 set_mock_time_ms(origin + 0);
1436
1437 container.change_other = true;
1438 container.change_other_value_ms = 100;
1439 container.change_other_interval_ms = 100;
1440 container.timer = &t1;
1441 change_timer(&t1, true, 100, 0, container_callback, &container);
1442 container.other = &t2;
1443 change_timer(&t2, true, 1000, 0, trigger_callback, &triggered_other);
1444 handle_expired_timers();
1445 ASSERT_EQUAL(container.triggered, 0);
1446 ASSERT_EQUAL(triggered_other, 0);
1447
1448 set_mock_time_ms(origin + 100);
1449 handle_expired_timers();
1450 ASSERT_EQUAL(container.triggered, 1);
1451 ASSERT_EQUAL(triggered_other, 0);
1452
1453 set_mock_time_ms(origin + 200);
1454 handle_expired_timers();
1455 ASSERT_EQUAL(container.triggered, 2);
1456 ASSERT_EQUAL(triggered_other, 0);
1457
1458 set_mock_time_ms(origin + 300);
1459 handle_expired_timers();
1460 ASSERT_EQUAL(container.triggered, 3);
1461 ASSERT_EQUAL(triggered_other, 0);
1462 }
1463
TEST(add_change_two_timer_multi_inside_callback)1464 TEST(add_change_two_timer_multi_inside_callback)
1465 {
1466 u_int64_t origin = MOCK_ORIGIN;
1467 TimeoutContainer container;
1468 bzero(&container, sizeof(container));
1469 Timer t1;
1470 init_timer(&t1, "t1");
1471
1472 set_mock_time_ms(origin + 0);
1473
1474 container.add = true;
1475 container.add_value_ms = 100;
1476 container.add_interval_ms = 100;
1477 container.change = true;
1478 container.change_value_ms = 100;
1479 container.change_interval_ms = 100;
1480 container.timer = &t1;
1481 change_timer(&t1, true, 200, 200, container_callback, &container);
1482 handle_expired_timers();
1483 ASSERT_EQUAL(container.triggered, 0);
1484
1485 set_mock_time_ms(origin + 100);
1486 handle_expired_timers();
1487 ASSERT_EQUAL(container.triggered, 0);
1488
1489 set_mock_time_ms(origin + 200);
1490 handle_expired_timers();
1491 ASSERT_EQUAL(container.triggered, 1);
1492
1493 // Now we have two running timers, one changing itself to expire after 100 ms when triggered,
1494 // the other firing once after 100 ms
1495 set_mock_time_ms(origin + 250);
1496 handle_expired_timers();
1497 ASSERT_EQUAL(container.triggered, 1);
1498
1499 set_mock_time_ms(origin + 300);
1500 handle_expired_timers();
1501 ASSERT_EQUAL(container.triggered, 3);
1502
1503 set_mock_time_ms(origin + 350);
1504 handle_expired_timers();
1505 ASSERT_EQUAL(container.triggered, 3);
1506
1507 set_mock_time_ms(origin + 400);
1508 handle_expired_timers();
1509 ASSERT_EQUAL(container.triggered, 5);
1510 }
1511
TEST(get_duration_to_next_timer_expiration_simple)1512 TEST(get_duration_to_next_timer_expiration_simple)
1513 {
1514 u_int64_t origin = MOCK_ORIGIN;
1515 int triggered = 0;
1516 Timer t1;
1517 init_timer(&t1, "t1");
1518
1519 set_mock_time_ms(origin + 0);
1520 change_timer(&t1, true, 200, 0, trigger_callback, &triggered);
1521 handle_expired_timers();
1522 ASSERT_EQUAL(triggered, 0);
1523 ASSERT_EQUAL(timeval_to_ms(get_duration_to_next_timer_expiration()), 200);
1524
1525 set_mock_time_ms(origin + 100);
1526 handle_expired_timers();
1527 ASSERT_EQUAL(triggered, 0);
1528 ASSERT_EQUAL(timeval_to_ms(get_duration_to_next_timer_expiration()), 100);
1529
1530 change_timer(&t1, true, 200, 0, trigger_callback, &triggered);
1531 ASSERT_EQUAL(timeval_to_ms(get_duration_to_next_timer_expiration()), 200);
1532
1533 set_mock_time_ms(origin + 200);
1534 handle_expired_timers();
1535 ASSERT_EQUAL(triggered, 0);
1536 ASSERT_EQUAL(timeval_to_ms(get_duration_to_next_timer_expiration()), 100);
1537
1538 set_mock_time_ms(origin + 250);
1539 handle_expired_timers();
1540 ASSERT_EQUAL(triggered, 0);
1541 ASSERT_EQUAL(timeval_to_ms(get_duration_to_next_timer_expiration()), 50);
1542
1543 set_mock_time_ms(origin + 300);
1544 handle_expired_timers();
1545 ASSERT_EQUAL(triggered, 1);
1546 ASSERT_EQUAL(timeval_to_ms(get_duration_to_next_timer_expiration()), -1);
1547
1548 set_mock_time_ms(origin + 500);
1549 handle_expired_timers();
1550 ASSERT_EQUAL(triggered, 1);
1551 ASSERT_EQUAL(timeval_to_ms(get_duration_to_next_timer_expiration()), -1);
1552 }
1553
TEST(get_duration_to_next_timer_expiration_multi)1554 TEST(get_duration_to_next_timer_expiration_multi)
1555 {
1556 u_int64_t origin = MOCK_ORIGIN;
1557 int triggered = 0;
1558 Timer t1;
1559 init_timer(&t1, "t1");
1560
1561 set_mock_time_ms(origin + 0);
1562 change_timer(&t1, true, 100, 200, trigger_callback, &triggered);
1563 handle_expired_timers();
1564 ASSERT_EQUAL(triggered, 0);
1565 ASSERT_EQUAL(timeval_to_ms(get_duration_to_next_timer_expiration()), 100);
1566
1567 set_mock_time_ms(origin + 50);
1568 handle_expired_timers();
1569 ASSERT_EQUAL(triggered, 0);
1570 ASSERT_EQUAL(timeval_to_ms(get_duration_to_next_timer_expiration()), 50);
1571
1572 set_mock_time_ms(origin + 100);
1573 handle_expired_timers();
1574 ASSERT_EQUAL(triggered, 1);
1575 ASSERT_EQUAL(timeval_to_ms(get_duration_to_next_timer_expiration()), 200);
1576
1577 set_mock_time_ms(origin + 200);
1578 handle_expired_timers();
1579 ASSERT_EQUAL(triggered, 1);
1580 ASSERT_EQUAL(timeval_to_ms(get_duration_to_next_timer_expiration()), 100);
1581
1582 set_mock_time_ms(origin + 300);
1583 handle_expired_timers();
1584 ASSERT_EQUAL(triggered, 2);
1585 ASSERT_EQUAL(timeval_to_ms(get_duration_to_next_timer_expiration()), 200);
1586
1587 change_timer(&t1, true, 100, 0, trigger_callback, &triggered);
1588 handle_expired_timers();
1589 ASSERT_EQUAL(triggered, 2);
1590 ASSERT_EQUAL(timeval_to_ms(get_duration_to_next_timer_expiration()), 100);
1591
1592 change_timer(&t1, true, 100, 300, trigger_callback, &triggered);
1593 handle_expired_timers();
1594 ASSERT_EQUAL(triggered, 2);
1595 ASSERT_EQUAL(timeval_to_ms(get_duration_to_next_timer_expiration()), 100);
1596
1597 set_mock_time_ms(origin + 400);
1598 handle_expired_timers();
1599 ASSERT_EQUAL(triggered, 3);
1600 ASSERT_EQUAL(timeval_to_ms(get_duration_to_next_timer_expiration()), 300);
1601
1602 set_mock_time_ms(origin + 700);
1603 handle_expired_timers();
1604 ASSERT_EQUAL(triggered, 4);
1605 ASSERT_EQUAL(timeval_to_ms(get_duration_to_next_timer_expiration()), 300);
1606 }
1607
TEST(get_duration_to_next_timer_expiration_simple_multi)1608 TEST(get_duration_to_next_timer_expiration_simple_multi)
1609 {
1610 u_int64_t origin = MOCK_ORIGIN;
1611 Timer t1;
1612 init_timer(&t1, "t1");
1613 Timer t2;
1614 init_timer(&t2, "t2");
1615 int triggered = 0;
1616
1617 set_mock_time_ms(origin + 0);
1618 change_timer(&t1, true, 100, 0, trigger_callback, &triggered);
1619 change_timer(&t2, true, 200, 50, trigger_callback, &triggered);
1620 handle_expired_timers();
1621 ASSERT_EQUAL(triggered, 0);
1622 ASSERT_EQUAL(timeval_to_ms(get_duration_to_next_timer_expiration()), 100);
1623
1624 set_mock_time_ms(origin + 50);
1625 handle_expired_timers();
1626 ASSERT_EQUAL(triggered, 0);
1627 ASSERT_EQUAL(timeval_to_ms(get_duration_to_next_timer_expiration()), 50);
1628
1629 set_mock_time_ms(origin + 100);
1630 handle_expired_timers();
1631 ASSERT_EQUAL(triggered, 1);
1632 ASSERT_EQUAL(timeval_to_ms(get_duration_to_next_timer_expiration()), 100);
1633
1634 set_mock_time_ms(origin + 150);
1635 handle_expired_timers();
1636 ASSERT_EQUAL(triggered, 1);
1637 ASSERT_EQUAL(timeval_to_ms(get_duration_to_next_timer_expiration()), 50);
1638
1639 set_mock_time_ms(origin + 200);
1640 handle_expired_timers();
1641 ASSERT_EQUAL(triggered, 2);
1642 ASSERT_EQUAL(timeval_to_ms(get_duration_to_next_timer_expiration()), 50);
1643
1644 change_timer(&t1, true, 10, 0, trigger_callback, &triggered);
1645 handle_expired_timers();
1646 ASSERT_EQUAL(triggered, 2);
1647 ASSERT_EQUAL(timeval_to_ms(get_duration_to_next_timer_expiration()), 10);
1648
1649 set_mock_time_ms(origin + 210);
1650 handle_expired_timers();
1651 ASSERT_EQUAL(triggered, 3);
1652 ASSERT_EQUAL(timeval_to_ms(get_duration_to_next_timer_expiration()), 40);
1653 }
1654
TEST(cleanup_timers_simple)1655 TEST(cleanup_timers_simple)
1656 {
1657 u_int64_t origin = MOCK_ORIGIN;
1658 int triggered = 0;
1659 Timer t1;
1660 init_timer(&t1, "t1");
1661 Timer t2;
1662 init_timer(&t1, "t2");
1663 Timer t3;
1664 init_timer(&t1, "t3");
1665
1666 set_mock_time_ms(origin + 0);
1667 change_timer(&t1, true, 100, 0, trigger_callback, &triggered);
1668 change_timer(&t2, true, 200, 0, trigger_callback, &triggered);
1669 change_timer(&t3, true, 300, 0, trigger_callback, &triggered);
1670 handle_expired_timers();
1671 ASSERT_EQUAL(triggered, 0);
1672
1673 set_mock_time_ms(origin + 50);
1674 handle_expired_timers();
1675 ASSERT_EQUAL(triggered, 0);
1676
1677 set_mock_time_ms(origin + 100);
1678 handle_expired_timers();
1679 ASSERT_EQUAL(triggered, 1);
1680
1681 set_mock_time_ms(origin + 150);
1682 handle_expired_timers();
1683 ASSERT_EQUAL(triggered, 1);
1684
1685 cleanup_timers();
1686 ASSERT_EQUAL(timeval_to_ms(get_duration_to_next_timer_expiration()), -1);
1687
1688 set_mock_time_ms(origin + 200);
1689 handle_expired_timers();
1690 ASSERT_EQUAL(triggered, 1);
1691
1692 set_mock_time_ms(origin + 300);
1693 handle_expired_timers();
1694 ASSERT_EQUAL(triggered, 1);
1695
1696 set_mock_time_ms(origin + 500);
1697 handle_expired_timers();
1698 ASSERT_EQUAL(triggered, 1);
1699 }
1700