Browse Source

Test coverage for timers.

Nick Mathewson 8 years ago
parent
commit
11a09778d6
2 changed files with 39 additions and 10 deletions
  1. 4 2
      src/common/timers.c
  2. 35 8
      src/test/test-timers.c

+ 4 - 2
src/common/timers.c

@@ -186,14 +186,16 @@ libevent_timer_callback(evutil_socket_t fd, short what, void *arg)
 void
 timers_initialize(void)
 {
-  if (global_timeouts)
-    return;
+  if (BUG(global_timeouts))
+    return; // LCOV_EXCL_LINE
 
   timeout_error_t err;
   global_timeouts = timeouts_open(0, &err);
   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));
     tor_assert(0);
+    // LCOV_EXCL_STOP
   }
 
   struct event *timer_event;

+ 35 - 8
src/test/test-timers.c

@@ -21,12 +21,15 @@
 
 #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
@@ -39,7 +42,7 @@ timer_cb(tor_timer_t *t, void *arg, const struct timeval *now)
   timersub(now, &fire_at[idx], &difference[idx]);
   ++n_fired;
   // 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());
   }
 }
@@ -55,6 +58,7 @@ main(int argc, char **argv)
   timers_initialize();
 
   int i;
+  int ret;
   struct timeval now;
   tor_gettimeofday(&now);
   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_usec = crypto_rand_int_range(0,1000000);
     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);
+    ++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);
 
   uint64_t total_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) {
+    if (is_disabled[i]) {
+      tor_assert(fired[i] == 0);
+      continue;
+    }
     tor_assert(fired[i] == 1);
     uint64_t diff = difference[i].tv_usec + difference[i].tv_sec * 1000000;
     total_difference += 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",
          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 stddev = sqrt(mean_sq - sq_mean);
   printf("standard deviation: %lf usec\n", stddev);
@@ -89,13 +108,21 @@ main(int argc, char **argv)
   if (mean_diff > 500*1000 || stddev > 500*1000) {
     printf("Either your system is under ridiculous load, or the "
            "timer backend is broken.\n");
-    return 1;
+    ret = 1;
   } else if (mean_diff > 2000 || stddev > 2000) {
     printf("Either your system is a bit slow or the "
            "timer backend is odd.\n");
-    return 0;
+    ret = 0;
   } else {
     printf("Looks good enough.\n");
+    ret = 0;
+  }
+
+  timer_free(NULL);
+
+  for (i = 0; i < N_TIMERS; ++i) {
+    timer_free(timers[i]);
   }
-  return 0;
+  timers_shutdown();
+  return ret;
 }