mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-11 05:33:47 +01:00
Test coverage for timers.
This commit is contained in:
parent
10fd4535c2
commit
11a09778d6
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user