aboutsummaryrefslogtreecommitdiff
path: root/src/test/test-timers.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/test-timers.c')
-rw-r--r--src/test/test-timers.c134
1 files changed, 134 insertions, 0 deletions
diff --git a/src/test/test-timers.c b/src/test/test-timers.c
new file mode 100644
index 0000000000..0196ec1fef
--- /dev/null
+++ b/src/test/test-timers.c
@@ -0,0 +1,134 @@
+/* Copyright 2016, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef HAVE_EVENT2_EVENT_H
+#include <event2/event.h>
+#else
+#include <event.h>
+#endif
+
+#include "compat.h"
+#include "compat_libevent.h"
+#include "crypto.h"
+#include "timers.h"
+#include "util.h"
+
+#define N_TIMERS 1000
+#define MAX_DURATION 30
+#define N_DISABLE 5
+
+static struct timeval fire_at[N_TIMERS] = { {0,0} };
+static int is_disabled[N_TIMERS] = {0};
+static int fired[N_TIMERS] = {0};
+static struct timeval difference[N_TIMERS] = { {0,0} };
+static tor_timer_t *timers[N_TIMERS] = {NULL};
+
+static int n_active_timers = 0;
+static int n_fired = 0;
+
+static void
+timer_cb(tor_timer_t *t, void *arg, const struct timeval *now)
+{
+ tor_timer_t **t_ptr = arg;
+ tor_assert(*t_ptr == t);
+ int idx = (int) (t_ptr - timers);
+ ++fired[idx];
+ timersub(now, &fire_at[idx], &difference[idx]);
+ ++n_fired;
+ // printf("%d / %d\n",n_fired, N_TIMERS);
+ if (n_fired == n_active_timers) {
+ event_base_loopbreak(tor_libevent_get_base());
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ (void)argc;
+ (void)argv;
+ tor_libevent_cfg cfg;
+ memset(&cfg, 0, sizeof(cfg));
+ tor_libevent_initialize(&cfg);
+ timers_initialize();
+
+ int i;
+ int ret;
+ struct timeval now;
+ tor_gettimeofday(&now);
+ for (i = 0; i < N_TIMERS; ++i) {
+ struct timeval delay;
+ delay.tv_sec = crypto_rand_int_range(0,MAX_DURATION);
+ delay.tv_usec = crypto_rand_int_range(0,1000000);
+ timeradd(&now, &delay, &fire_at[i]);
+ timers[i] = timer_new(timer_cb, &timers[i]);
+ 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);
+
+ int64_t total_difference = 0;
+ uint64_t total_square_difference = 0;
+ tor_assert(n_fired == n_active_timers);
+ for (i = 0; i < N_TIMERS; ++i) {
+ if (is_disabled[i]) {
+ tor_assert(fired[i] == 0);
+ continue;
+ }
+ tor_assert(fired[i] == 1);
+ int64_t diff = difference[i].tv_usec + difference[i].tv_sec * 1000000;
+ total_difference += diff;
+ total_square_difference += diff*diff;
+ }
+ const int64_t mean_diff = total_difference / n_active_timers;
+ printf("mean difference: "U64_FORMAT" usec\n",
+ U64_PRINTF_ARG(mean_diff));
+
+ const double mean_sq = ((double)total_square_difference)/ n_active_timers;
+ const double sq_mean = mean_diff * mean_diff;
+ const double stddev = sqrt(mean_sq - sq_mean);
+ printf("standard deviation: %lf usec\n", stddev);
+
+#define MAX_DIFF_USEC (500*1000)
+#define MAX_STDDEV_USEC (500*1000)
+#define ODD_DIFF_USEC (2000)
+#define ODD_STDDEV_USEC (2000)
+
+ if (mean_diff < 0 || mean_diff > MAX_DIFF_USEC || stddev > MAX_STDDEV_USEC) {
+ printf("Either your system is under ridiculous load, or the "
+ "timer backend is broken.\n");
+ ret = 1;
+ } else if (mean_diff > ODD_DIFF_USEC || stddev > ODD_STDDEV_USEC) {
+ printf("Either your system is a bit slow or the "
+ "timer backend is odd.\n");
+ ret = 0;
+ } else {
+ printf("Looks good enough.\n");
+ ret = 0;
+ }
+
+ timer_free(NULL);
+
+ for (i = 0; i < N_TIMERS; ++i) {
+ timer_free(timers[i]);
+ }
+ timers_shutdown();
+ return ret;
+}
+