]>
git.proxmox.com Git - mirror_frr.git/blob - tests/lib/test_timer_correctness.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Test program to verify that scheduled timers are executed in the
6 * Copyright (C) 2013 by Open Source Routing.
7 * Copyright (C) 2013 by Internet Systems Consortium, Inc. ("ISC")
9 * This file is part of Quagga
21 #define SCHEDULE_TIMERS 800
22 #define REMOVE_TIMERS 200
24 #define TIMESTR_LEN strlen("4294967296.999999")
26 struct thread_master
*master
;
28 static size_t log_buf_len
;
29 static size_t log_buf_pos
;
32 static size_t expected_buf_len
;
33 static size_t expected_buf_pos
;
34 static char *expected_buf
;
36 static struct prng
*prng
;
38 static struct thread
**timers
;
40 static int timers_pending
;
42 static void terminate_test(void)
46 if (strcmp(log_buf
, expected_buf
)) {
48 "Expected output and received output differ.\n");
49 fprintf(stderr
, "---Expected output: ---\n%s", expected_buf
);
50 fprintf(stderr
, "---Actual output: ---\n%s", log_buf
);
53 printf("Expected output and actual output match.\n");
57 thread_master_free(master
);
58 XFREE(MTYPE_TMP
, log_buf
);
59 XFREE(MTYPE_TMP
, expected_buf
);
61 XFREE(MTYPE_TMP
, timers
);
66 static void timer_func(struct thread
*thread
)
70 rv
= snprintf(log_buf
+ log_buf_pos
, log_buf_len
- log_buf_pos
, "%s\n",
74 assert(log_buf_pos
< log_buf_len
);
75 XFREE(MTYPE_TMP
, thread
->arg
);
82 static int cmp_timeval(const void *a
, const void *b
)
84 const struct timeval
*ta
= *(struct timeval
* const *)a
;
85 const struct timeval
*tb
= *(struct timeval
* const *)b
;
87 if (timercmp(ta
, tb
, <))
89 if (timercmp(ta
, tb
, >))
94 int main(int argc
, char **argv
)
98 struct timeval
**alarms
;
100 master
= thread_master_create(NULL
);
102 log_buf_len
= SCHEDULE_TIMERS
* (TIMESTR_LEN
+ 1) + 1;
104 log_buf
= XMALLOC(MTYPE_TMP
, log_buf_len
);
106 expected_buf_len
= SCHEDULE_TIMERS
* (TIMESTR_LEN
+ 1) + 1;
107 expected_buf_pos
= 0;
108 expected_buf
= XMALLOC(MTYPE_TMP
, expected_buf_len
);
112 timers
= XCALLOC(MTYPE_TMP
, SCHEDULE_TIMERS
* sizeof(*timers
));
114 for (i
= 0; i
< SCHEDULE_TIMERS
; i
++) {
119 /* Schedule timers to expire in 0..5 seconds */
120 interval_msec
= prng_rand(prng
) % 5000;
121 arg
= XMALLOC(MTYPE_TMP
, TIMESTR_LEN
+ 1);
122 thread_add_timer_msec(master
, timer_func
, arg
, interval_msec
,
124 ret
= snprintf(arg
, TIMESTR_LEN
+ 1, "%lld.%06lld",
125 (long long)timers
[i
]->u
.sands
.tv_sec
,
126 (long long)timers
[i
]->u
.sands
.tv_usec
);
128 assert((size_t)ret
< TIMESTR_LEN
+ 1);
132 for (i
= 0; i
< REMOVE_TIMERS
; i
++) {
135 index
= prng_rand(prng
) % SCHEDULE_TIMERS
;
139 XFREE(MTYPE_TMP
, timers
[index
]->arg
);
140 thread_cancel(&timers
[index
]);
144 /* We create an array of pointers to the alarm times and sort
145 * that array. That sorted array is used to generate a string
146 * representing the expected "output" of the timers when they
149 alarms
= XCALLOC(MTYPE_TMP
, timers_pending
* sizeof(*alarms
));
150 for (i
= 0; i
< SCHEDULE_TIMERS
; i
++) {
153 alarms
[j
++] = &timers
[i
]->u
.sands
;
155 qsort(alarms
, j
, sizeof(*alarms
), cmp_timeval
);
156 for (i
= 0; i
< j
; i
++) {
159 ret
= snprintf(expected_buf
+ expected_buf_pos
,
160 expected_buf_len
- expected_buf_pos
,
161 "%lld.%06lld\n", (long long)alarms
[i
]->tv_sec
,
162 (long long)alarms
[i
]->tv_usec
);
164 expected_buf_pos
+= ret
;
165 assert(expected_buf_pos
< expected_buf_len
);
167 XFREE(MTYPE_TMP
, alarms
);
169 while (thread_fetch(master
, &t
))