Test coverage for timers.

This commit is contained in:
Nick Mathewson 2016-04-15 09:31:18 -04:00
parent 10fd4535c2
commit 11a09778d6
2 changed files with 39 additions and 10 deletions

View File

@ -186,14 +186,16 @@ libevent_timer_callback(evutil_socket_t fd, short what, void *arg)
void void
timers_initialize(void) timers_initialize(void)
{ {
if (global_timeouts) if (BUG(global_timeouts))
return; return; // LCOV_EXCL_LINE
timeout_error_t err; timeout_error_t err;
global_timeouts = timeouts_open(0, &err); global_timeouts = timeouts_open(0, &err);
if (!global_timeouts) { if (!global_timeouts) {
// LCOV_EXCL_START -- this can only fail on malloc failure.
log_err(LD_BUG, "Unable to open timer backend: %s", strerror(err)); log_err(LD_BUG, "Unable to open timer backend: %s", strerror(err));
tor_assert(0); tor_assert(0);
// LCOV_EXCL_STOP
} }
struct event *timer_event; struct event *timer_event;

View File

@ -21,12 +21,15 @@
#define N_TIMERS 1000 #define N_TIMERS 1000
#define MAX_DURATION 30 #define MAX_DURATION 30
#define N_DISABLE 5
static struct timeval fire_at[N_TIMERS] = {{0,0}}; static struct timeval fire_at[N_TIMERS] = {{0,0}};
static int is_disabled[N_TIMERS] = {0};
static int fired[N_TIMERS] = {0}; static int fired[N_TIMERS] = {0};
static struct timeval difference[N_TIMERS] = {{0,0}}; static struct timeval difference[N_TIMERS] = {{0,0}};
static tor_timer_t *timers[N_TIMERS] = {NULL}; static tor_timer_t *timers[N_TIMERS] = {NULL};
static int n_active_timers = 0;
static int n_fired = 0; static int n_fired = 0;
static void static void
@ -39,7 +42,7 @@ timer_cb(tor_timer_t *t, void *arg, const struct timeval *now)
timersub(now, &fire_at[idx], &difference[idx]); timersub(now, &fire_at[idx], &difference[idx]);
++n_fired; ++n_fired;
// printf("%d / %d\n",n_fired, N_TIMERS); // printf("%d / %d\n",n_fired, N_TIMERS);
if (n_fired == N_TIMERS) { if (n_fired == n_active_timers) {
event_base_loopbreak(tor_libevent_get_base()); event_base_loopbreak(tor_libevent_get_base());
} }
} }
@ -55,6 +58,7 @@ main(int argc, char **argv)
timers_initialize(); timers_initialize();
int i; int i;
int ret;
struct timeval now; struct timeval now;
tor_gettimeofday(&now); tor_gettimeofday(&now);
for (i = 0; i < N_TIMERS; ++i) { for (i = 0; i < N_TIMERS; ++i) {
@ -62,26 +66,41 @@ main(int argc, char **argv)
delay.tv_sec = crypto_rand_int_range(0,MAX_DURATION); delay.tv_sec = crypto_rand_int_range(0,MAX_DURATION);
delay.tv_usec = crypto_rand_int_range(0,1000000); delay.tv_usec = crypto_rand_int_range(0,1000000);
timeradd(&now, &delay, &fire_at[i]); timeradd(&now, &delay, &fire_at[i]);
timers[i] = timer_new(timer_cb, &timers[i], 0); timers[i] = timer_new(timer_cb, &timers[i]);
timer_schedule(timers[i], &delay); timer_schedule(timers[i], &delay);
++n_active_timers;
}
/* Disable some; we'll make sure they don't trigger. */
for (i = 0; i < N_DISABLE; ++i) {
int idx = crypto_rand_int_range(0, N_TIMERS);
if (is_disabled[idx])
continue;
is_disabled[idx] = 1;
timer_disable(timers[idx]);
--n_active_timers;
} }
event_base_loop(tor_libevent_get_base(), 0); event_base_loop(tor_libevent_get_base(), 0);
uint64_t total_difference = 0; uint64_t total_difference = 0;
uint64_t total_square_difference = 0; uint64_t total_square_difference = 0;
tor_assert(n_fired == N_TIMERS); tor_assert(n_fired == n_active_timers);
for (i = 0; i < N_TIMERS; ++i) { for (i = 0; i < N_TIMERS; ++i) {
if (is_disabled[i]) {
tor_assert(fired[i] == 0);
continue;
}
tor_assert(fired[i] == 1); tor_assert(fired[i] == 1);
uint64_t diff = difference[i].tv_usec + difference[i].tv_sec * 1000000; uint64_t diff = difference[i].tv_usec + difference[i].tv_sec * 1000000;
total_difference += diff; total_difference += diff;
total_square_difference += diff*diff; total_square_difference += diff*diff;
} }
const uint64_t mean_diff = total_difference / N_TIMERS; const uint64_t mean_diff = total_difference / n_active_timers;
printf("mean difference: "U64_FORMAT" usec\n", printf("mean difference: "U64_FORMAT" usec\n",
U64_PRINTF_ARG(mean_diff)); U64_PRINTF_ARG(mean_diff));
const double mean_sq = ((double)total_square_difference) / N_TIMERS; const double mean_sq = ((double)total_square_difference)/ n_active_timers;
const double sq_mean = mean_diff * mean_diff; const double sq_mean = mean_diff * mean_diff;
const double stddev = sqrt(mean_sq - sq_mean); const double stddev = sqrt(mean_sq - sq_mean);
printf("standard deviation: %lf usec\n", stddev); printf("standard deviation: %lf usec\n", stddev);
@ -89,13 +108,21 @@ main(int argc, char **argv)
if (mean_diff > 500*1000 || stddev > 500*1000) { if (mean_diff > 500*1000 || stddev > 500*1000) {
printf("Either your system is under ridiculous load, or the " printf("Either your system is under ridiculous load, or the "
"timer backend is broken.\n"); "timer backend is broken.\n");
return 1; ret = 1;
} else if (mean_diff > 2000 || stddev > 2000) { } else if (mean_diff > 2000 || stddev > 2000) {
printf("Either your system is a bit slow or the " printf("Either your system is a bit slow or the "
"timer backend is odd.\n"); "timer backend is odd.\n");
return 0; ret = 0;
} else { } else {
printf("Looks good enough.\n"); printf("Looks good enough.\n");
ret = 0;
} }
return 0;
timer_free(NULL);
for (i = 0; i < N_TIMERS; ++i) {
timer_free(timers[i]);
}
timers_shutdown();
return ret;
} }