[tor-commits] [tor/master] Actually make monotonic time functions mockable.

nickm at torproject.org nickm at torproject.org
Thu Jul 21 11:05:00 UTC 2016


commit 2d26b1a54901bff8f508bfebeea3fb471cf36a9d
Author: Nick Mathewson <nickm at torproject.org>
Date:   Thu Jul 21 11:04:22 2016 +0200

    Actually make monotonic time functions mockable.
    
    This is different from making the functions mockable, since
    monotime_t is opaque and so providing mocks for the functions is
    really hard.
---
 src/common/compat_time.c | 108 ++++++++++++++++++++++++++++++++++++++++++++---
 src/common/compat_time.h |   9 ++++
 2 files changed, 112 insertions(+), 5 deletions(-)

diff --git a/src/common/compat_time.c b/src/common/compat_time.c
index b7d69cf..52abfeb 100644
--- a/src/common/compat_time.c
+++ b/src/common/compat_time.c
@@ -118,6 +118,74 @@ tor_gettimeofday(struct timeval *timeval)
 /** True iff monotime_init has been called. */
 static int monotime_initialized = 0;
 
+static monotime_t initialized_at;
+#ifdef MONOTIME_COARSE_FN_IS_DIFFERENT
+static monotime_coarse_t initialized_at_coarse;
+#endif
+
+#ifdef TOR_UNIT_TESTS
+/** True if we are running unit tests and overriding the current monotonic
+ * time.  Note that mocked monotonic time might not be monotonic.
+ */
+static int monotime_mocking_enabled = 0;
+static monotime_t initialized_at_saved;
+
+static int64_t mock_time_nsec = 0;
+#ifdef MONOTIME_COARSE_FN_IS_DIFFERENT
+static int64_t mock_time_nsec_coarse = 0;
+static monotime_coarse_t initialized_at_coarse_saved;
+#endif
+
+void
+monotime_enable_test_mocking(void)
+{
+  if (BUG(monotime_initialized == 0)) {
+    monotime_init();
+  }
+
+  tor_assert_nonfatal(monotime_mocking_enabled == 0);
+  monotime_mocking_enabled = 1;
+  memcpy(&initialized_at_saved,
+         &initialized_at, sizeof(monotime_t));
+  memset(&initialized_at, 0, sizeof(monotime_t));
+#ifdef MONOTIME_COARSE_FN_IS_DIFFERENT
+  memcpy(&initialized_at_coarse_saved,
+         &initialized_at_coarse, sizeof(monotime_coarse_t));
+  memset(&initialized_at_coarse, 0, sizeof(monotime_coarse_t));
+#endif
+}
+
+void
+monotime_disable_test_mocking(void)
+{
+  tor_assert_nonfatal(monotime_mocking_enabled == 1);
+  monotime_mocking_enabled = 0;
+
+  memcpy(&initialized_at,
+         &initialized_at_saved, sizeof(monotime_t));
+#ifdef MONOTIME_COARSE_FN_IS_DIFFERENT
+  memcpy(&initialized_at_coarse,
+         &initialized_at_coarse_saved, sizeof(monotime_coarse_t));
+#endif
+}
+
+void
+monotime_set_mock_time_nsec(int64_t nsec)
+{
+  tor_assert_nonfatal(monotime_mocking_enabled == 1);
+  mock_time_nsec = nsec;
+}
+
+#ifdef MONOTIME_COARSE_FN_IS_DIFFERENT
+void
+monotime_coarse_set_mock_time_nsec(int64_t nsec)
+{
+  tor_assert_nonfatal(monotime_mocking_enabled == 1);
+  mock_time_nsec_coarse = nsec;
+}
+#endif
+#endif
+
 /* "ratchet" functions for monotonic time. */
 
 #if defined(_WIN32) || defined(TOR_UNIT_TESTS)
@@ -223,6 +291,13 @@ monotime_init_internal(void)
 void
 monotime_get(monotime_t *out)
 {
+#ifdef TOR_UNIT_TESTS
+  if (monotime_mocking_enabled) {
+    out->abstime_ = (mock_time_nsec * mach_time_info.denom)
+      / mach_time_info.numer;
+    return;
+  }
+#endif
   out->abstime_ = mach_absolute_time();
 }
 
@@ -254,6 +329,13 @@ monotime_init_internal(void)
 void
 monotime_get(monotime_t *out)
 {
+#ifdef TOR_UNIT_TESTS
+  if (monotime_mocking_enabled) {
+    out->ts_.tv_sec = mock_time_nsec / ONE_BILLION;
+    out->ts_.tv_nsec = mock_time_nsec % ONE_BILLION;
+    return;
+  }
+#endif
   int r = clock_gettime(CLOCK_MONOTONIC, &out->ts_);
   tor_assert(r == 0);
 }
@@ -262,6 +344,13 @@ monotime_get(monotime_t *out)
 void
 monotime_coarse_get(monotime_coarse_t *out)
 {
+#ifdef TOR_UNIT_TESTS
+  if (monotime_mocking_enabled) {
+    out->ts_.tv_sec = mock_time_nsec_coarse / ONE_BILLION;
+    out->ts_.tv_nsec = mock_time_nsec_coarse % ONE_BILLION;
+    return;
+  }
+#endif
   int r = clock_gettime(CLOCK_MONOTONIC_COARSE, &out->ts_);
   tor_assert(r == 0);
 }
@@ -323,6 +412,13 @@ monotime_get(monotime_t *out)
     monotime_init();
   }
 
+#ifdef TOR_UNIT_TESTS
+  if (monotime_mocking_enabled) {
+    out->pcount_ = (mock_time_nsec * ticks_per_second) / ONE_BILLION;
+    return;
+  }
+#endif
+
   /* Alas, QueryPerformanceCounter is not always monotonic: see bug list at
 
     https://www.python.org/dev/peps/pep-0418/#windows-queryperformancecounter
@@ -340,6 +436,13 @@ monotime_get(monotime_t *out)
 void
 monotime_coarse_get(monotime_coarse_t *out)
 {
+#ifdef TOR_UNIT_TESTS
+  if (monotime_mocking_enabled) {
+    out->tick_count_ = mock_time_nsec_coarse / ONE_MILLION;
+    return;
+  }
+#endif
+
   if (GetTickCount64_fn) {
     out->tick_count_ = (int64_t)GetTickCount64_fn();
   } else {
@@ -424,11 +527,6 @@ monotime_diff_nsec(const monotime_t *start,
 #error "No way to implement monotonic timers."
 #endif
 
-static monotime_t initialized_at;
-#ifdef MONOTIME_COARSE_FN_IS_DIFFERENT
-static monotime_coarse_t initialized_at_coarse;
-#endif
-
 /**
  * Initialize the monotonic timer subsystem. Must be called before any
  * monotonic timer functions. This function is idempotent.
diff --git a/src/common/compat_time.h b/src/common/compat_time.h
index 8d61bc2..de6994f 100644
--- a/src/common/compat_time.h
+++ b/src/common/compat_time.h
@@ -130,6 +130,15 @@ void tor_gettimeofday(struct timeval *timeval);
 
 #ifdef TOR_UNIT_TESTS
 void tor_sleep_msec(int msec);
+
+void monotime_enable_test_mocking(void);
+void monotime_disable_test_mocking(void);
+void monotime_set_mock_time_nsec(int64_t);
+#if defined(MONOTIME_COARSE_FN_IS_DIFFERENT)
+void monotime_coarse_set_mock_time_nsec(int64_t);
+#else
+#define monotime_coarse_set_mock_time_nsec monotime_set_mock_time_nsec
+#endif
 #endif
 
 #ifdef COMPAT_TIME_PRIVATE





More information about the tor-commits mailing list