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