diff options
Diffstat (limited to 'tests/timer')
| -rw-r--r-- | tests/timer/Makefile.am | 7 | ||||
| -rw-r--r-- | tests/timer/timer_test.c | 191 | ||||
| -rw-r--r-- | tests/timer/timer_test.ok | 2 |
3 files changed, 200 insertions, 0 deletions
diff --git a/tests/timer/Makefile.am b/tests/timer/Makefile.am new file mode 100644 index 00000000..062d81b3 --- /dev/null +++ b/tests/timer/Makefile.am @@ -0,0 +1,7 @@ +INCLUDES = $(all_includes) -I$(top_srcdir)/include +noinst_PROGRAMS = timer_test +EXTRA_DIST = timer_test.ok + +timer_test_SOURCES = timer_test.c +timer_test_LDADD = $(top_builddir)/src/libosmocore.la + diff --git a/tests/timer/timer_test.c b/tests/timer/timer_test.c new file mode 100644 index 00000000..61079bd9 --- /dev/null +++ b/tests/timer/timer_test.c @@ -0,0 +1,191 @@ +/* + * (C) 2008 by Holger Hans Peter Freyther <zecke@selfish.org> + * (C) 2011 by Harald Welte <laforge@gnumonks.org> + * All Rights Reserved + * + * Authors: Holger Hans Peter Freyther <zecke@selfish.org> + * Pablo Neira Ayuso <pablo@gnumonks.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <signal.h> +#include <getopt.h> + +#include <osmocom/core/talloc.h> +#include <osmocom/core/timer.h> +#include <osmocom/core/select.h> +#include <osmocom/core/linuxlist.h> + +#include "../../config.h" + +static void main_timer_fired(void *data); +static void secondary_timer_fired(void *data); + +static unsigned int main_timer_step = 0; +static struct osmo_timer_list main_timer = { + .cb = main_timer_fired, + .data = &main_timer_step, +}; + +static LLIST_HEAD(timer_test_list); + +struct test_timer { + struct llist_head head; + struct osmo_timer_list timer; + struct timeval start; + struct timeval stop; +}; + +/* number of test steps. We add fact(steps) timers in the whole test. */ +#define MAIN_TIMER_NSTEPS 16 + +/* time between two steps, in secs. */ +#define TIME_BETWEEN_STEPS 1 + +/* timer imprecision that we accept for this test: 10 milliseconds. */ +#define TIMER_PRES_SECS 0 +#define TIMER_PRES_USECS 20000 + +static int timer_nsteps = MAIN_TIMER_NSTEPS; +static unsigned int expired_timers = 0; +static unsigned int total_timers = 0; +static unsigned int too_late = 0; + +static void main_timer_fired(void *data) +{ + unsigned int *step = data; + unsigned int add_in_this_step; + int i; + + if (*step == timer_nsteps) { + fprintf(stderr, "Main timer has finished, please, " + "wait a bit for the final report.\n"); + return; + } + /* add 2^step pair of timers per step. */ + add_in_this_step = (1 << *step); + + for (i=0; i<add_in_this_step; i++) { + struct test_timer *v; + + v = talloc_zero(NULL, struct test_timer); + if (v == NULL) { + fprintf(stderr, "timer_test: OOM!\n"); + return; + } + gettimeofday(&v->start, NULL); + v->timer.cb = secondary_timer_fired; + v->timer.data = v; + unsigned int seconds = (random() % 10) + 1; + v->stop.tv_sec = v->start.tv_sec + seconds; + osmo_timer_schedule(&v->timer, seconds, 0); + llist_add(&v->head, &timer_test_list); + } + fprintf(stderr, "added %d timers in step %u (expired=%u)\n", + add_in_this_step, *step, expired_timers); + total_timers += add_in_this_step; + osmo_timer_schedule(&main_timer, TIME_BETWEEN_STEPS, 0); + (*step)++; +} + +static void secondary_timer_fired(void *data) +{ + struct test_timer *v = data, *this, *tmp; + struct timeval current, res, precision = { 1, 0 }; + + gettimeofday(¤t, NULL); + + timersub(¤t, &v->stop, &res); + if (timercmp(&res, &precision, >)) { + fprintf(stderr, "ERROR: timer %p has expired too late!\n", + v->timer); + too_late++; + } + + llist_del(&v->head); + talloc_free(data); + expired_timers++; + if (expired_timers == total_timers) { + fprintf(stdout, "test over: added=%u expired=%u too_late=%u \n", + total_timers, expired_timers, too_late); + exit(EXIT_SUCCESS); + } + + /* randomly (10%) deletion of timers. */ + llist_for_each_entry_safe(this, tmp, &timer_test_list, head) { + if ((random() % 100) < 10) { + osmo_timer_del(&this->timer); + llist_del(&this->head); + talloc_free(this); + expired_timers++; + } + } +} + +static void alarm_handler(int signum) +{ + fprintf(stderr, "ERROR: We took too long to run the timer test, " + "something seems broken, aborting.\n"); + exit(EXIT_FAILURE); +} + +int main(int argc, char *argv[]) +{ + int c; + + if (signal(SIGALRM, alarm_handler) == SIG_ERR) { + perror("cannot register signal handler"); + exit(EXIT_FAILURE); + } + + while ((c = getopt_long(argc, argv, "s:", NULL, NULL)) != -1) { + switch(c) { + case 's': + timer_nsteps = atoi(optarg); + if (timer_nsteps <= 0) { + fprintf(stderr, "%s: steps must be > 0\n", + argv[0]); + exit(EXIT_FAILURE); + } + break; + default: + exit(EXIT_FAILURE); + } + } + + fprintf(stdout, "Running timer test for %u steps, accepting " + "imprecision of %u.%.6u seconds\n", + timer_nsteps, TIMER_PRES_SECS, TIMER_PRES_USECS); + + osmo_timer_schedule(&main_timer, 1, 0); + + /* if the test takes too long, we may consider that the timer scheduler + * has hung. We set some maximum wait time which is the double of the + * maximum timeout randomly set (10 seconds, worst case) plus the + * number of steps (since some of them are reset each step). */ + alarm(2 * (10 + timer_nsteps)); + +#ifdef HAVE_SYS_SELECT_H + while (1) { + osmo_select_main(0); + } +#else + fprintf(stdout, "Select not supported on this platform!\n"); +#endif +} diff --git a/tests/timer/timer_test.ok b/tests/timer/timer_test.ok new file mode 100644 index 00000000..1bb382ee --- /dev/null +++ b/tests/timer/timer_test.ok @@ -0,0 +1,2 @@ +Running timer test for 5 steps, accepting imprecision of 0.020000 seconds +test over: added=31 expired=31 too_late=0 |
