[tor-commits] [tor/master] Write unittests for v3 metrics.

dgoulet at torproject.org dgoulet at torproject.org
Tue Nov 17 15:49:48 UTC 2020


commit 131da887d75bd112e668db3c1695ad8cc5a76433
Author: George Kadianakis <desnacked at riseup.net>
Date:   Wed Oct 21 14:17:30 2020 +0300

    Write unittests for v3 metrics.
---
 src/feature/stats/rephist.c |   6 +--
 src/feature/stats/rephist.h |  11 ++--
 src/test/hs_test_helpers.c  |  19 +++++--
 src/test/hs_test_helpers.h  |   4 ++
 src/test/test_stats.c       | 124 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 152 insertions(+), 12 deletions(-)

diff --git a/src/feature/stats/rephist.c b/src/feature/stats/rephist.c
index 24712707ca..ada19b447a 100644
--- a/src/feature/stats/rephist.c
+++ b/src/feature/stats/rephist.c
@@ -1871,8 +1871,8 @@ rep_hist_reset_hs_v3_stats(time_t now)
  *  on the real network) and hence we don't want to collect statistics if it's
  *  not yet the time to do so.
  */
-static bool
-should_collect_v3_stats(void)
+MOCK_IMPL(STATIC bool,
+should_collect_v3_stats,(void))
 {
   return start_of_hs_v3_stats_interval <= approx_time();
 }
@@ -1973,7 +1973,7 @@ rep_hist_hs_stats_term(void)
 
 /** Allocate and return a string containing hidden service stats that
  *  are meant to be placed in the extra-info descriptor. */
-static char *
+STATIC char *
 rep_hist_format_hs_v2_stats(time_t now)
 {
   char t[ISO_TIME_LEN+1];
diff --git a/src/feature/stats/rephist.h b/src/feature/stats/rephist.h
index 3bb4f996a2..b2a4a5048d 100644
--- a/src/feature/stats/rephist.h
+++ b/src/feature/stats/rephist.h
@@ -117,6 +117,9 @@ typedef struct hs_v3_stats_t {
 
 STATIC char *rep_hist_format_hs_v2_stats(time_t now);
 STATIC char *rep_hist_format_hs_v3_stats(time_t now);
+
+MOCK_DECL(STATIC bool, should_collect_v3_stats,(void));
+
 #endif /* defined(REPHIST_PRIVATE) */
 
 /**
@@ -145,10 +148,10 @@ void rep_hist_prep_published_padding_counts(time_t now);
 void rep_hist_padding_count_timers(uint64_t num_timers);
 
 #ifdef TOR_UNIT_TESTS
-typedef struct hs_v2_stats_t hs_v2_stats_t;
-const hs_v2_stats_t *rep_hist_get_hs_v2_stats(void);
-typedef struct hs_v3_stats_t hs_v3_stats_t;
-const hs_v3_stats_t *rep_hist_get_hs_v3_stats(void);
+struct hs_v2_stats_t;
+const struct hs_v2_stats_t *rep_hist_get_hs_v2_stats(void);
+struct hs_v3_stats_t;
+const struct hs_v3_stats_t *rep_hist_get_hs_v3_stats(void);
 #endif
 
 #endif /* !defined(TOR_REPHIST_H) */
diff --git a/src/test/hs_test_helpers.c b/src/test/hs_test_helpers.c
index e9aafa4760..e1ecf9fe56 100644
--- a/src/test/hs_test_helpers.c
+++ b/src/test/hs_test_helpers.c
@@ -134,7 +134,8 @@ hs_helper_build_intro_point(const ed25519_keypair_t *signing_kp, time_t now,
  * points are added. */
 static hs_descriptor_t *
 hs_helper_build_hs_desc_impl(unsigned int no_ip,
-                             const ed25519_keypair_t *signing_kp)
+                             const ed25519_keypair_t *signing_kp,
+                             uint64_t rev_counter)
 {
   int ret;
   int i;
@@ -161,7 +162,7 @@ hs_helper_build_hs_desc_impl(unsigned int no_ip,
                     &signing_kp->pubkey, now, 3600,
                     CERT_FLAG_INCLUDE_SIGNING_KEY);
   tt_assert(desc->plaintext_data.signing_key_cert);
-  desc->plaintext_data.revision_counter = 42;
+  desc->plaintext_data.revision_counter = rev_counter;
   desc->plaintext_data.lifetime_sec = 3 * 60 * 60;
 
   hs_get_subcredential(&signing_kp->pubkey, &blinded_kp.pubkey,
@@ -226,18 +227,26 @@ hs_helper_get_subcred_from_identity_keypair(ed25519_keypair_t *signing_kp,
                        subcred_out);
 }
 
+/* Build a descriptor with a specific rev counter. */
+hs_descriptor_t *
+hs_helper_build_hs_desc_with_rev_counter(const ed25519_keypair_t *signing_kp,
+                                         uint64_t revision_counter)
+{
+  return hs_helper_build_hs_desc_impl(0, signing_kp, revision_counter);
+}
+
 /* Build a descriptor with introduction points. */
 hs_descriptor_t *
 hs_helper_build_hs_desc_with_ip(const ed25519_keypair_t *signing_kp)
 {
-  return hs_helper_build_hs_desc_impl(0, signing_kp);
+  return hs_helper_build_hs_desc_impl(0, signing_kp, 42);
 }
 
 /* Build a descriptor without any introduction points. */
 hs_descriptor_t *
 hs_helper_build_hs_desc_no_ip(const ed25519_keypair_t *signing_kp)
 {
-  return hs_helper_build_hs_desc_impl(1, signing_kp);
+  return hs_helper_build_hs_desc_impl(1, signing_kp, 42);
 }
 
 hs_descriptor_t *
@@ -247,7 +256,7 @@ hs_helper_build_hs_desc_with_client_auth(
                         const ed25519_keypair_t *signing_kp)
 {
   curve25519_keypair_t auth_ephemeral_kp;
-  hs_descriptor_t *desc = hs_helper_build_hs_desc_impl(0, signing_kp);
+  hs_descriptor_t *desc = hs_helper_build_hs_desc_impl(0, signing_kp, 42);
   hs_desc_authorized_client_t *desc_client;
 
   /* The number of client authorized auth has tobe a multiple of
diff --git a/src/test/hs_test_helpers.h b/src/test/hs_test_helpers.h
index 23d11f2a4a..e22295b660 100644
--- a/src/test/hs_test_helpers.h
+++ b/src/test/hs_test_helpers.h
@@ -17,6 +17,10 @@ hs_descriptor_t *hs_helper_build_hs_desc_no_ip(
                                  const ed25519_keypair_t *signing_kp);
 hs_descriptor_t *hs_helper_build_hs_desc_with_ip(
                                  const ed25519_keypair_t *signing_kp);
+hs_descriptor_t *
+hs_helper_build_hs_desc_with_rev_counter(const ed25519_keypair_t *signing_kp,
+                                         uint64_t revision_counter);
+
 hs_descriptor_t *hs_helper_build_hs_desc_with_client_auth(
                                  const uint8_t *descriptor_cookie,
                                  const curve25519_public_key_t *client_pk,
diff --git a/src/test/test_stats.c b/src/test/test_stats.c
index b6849b0b6d..3ddc3bb31c 100644
--- a/src/test/test_stats.c
+++ b/src/test/test_stats.c
@@ -12,6 +12,8 @@
 #include "lib/crypt_ops/crypto_rand.h"
 #include "app/config/or_state_st.h"
 #include "test/rng_test_helpers.h"
+#include "feature/hs/hs_cache.h"
+#include "test/hs_test_helpers.h"
 
 #include <stdio.h>
 
@@ -31,6 +33,7 @@
 #define MAINLOOP_PRIVATE
 #define STATEFILE_PRIVATE
 #define BWHIST_PRIVATE
+#define REPHIST_PRIVATE
 
 #include "core/or/or.h"
 #include "lib/err/backtrace.h"
@@ -493,6 +496,126 @@ test_get_bandwidth_lines(void *arg)
   bwhist_free_all();
 }
 
+static bool
+mock_should_collect_v3_stats(void)
+{
+  return true;
+}
+
+/* Test v3 metrics */
+static void
+test_rephist_v3_onions(void *arg)
+{
+  int ret;
+
+  char *stats_string = NULL;
+  char *desc1_str = NULL;
+  ed25519_keypair_t signing_kp1;
+  hs_descriptor_t *desc1 = NULL;
+
+  const hs_v3_stats_t *hs_v3_stats = NULL;
+
+  (void) arg;
+
+  MOCK(should_collect_v3_stats, mock_should_collect_v3_stats);
+
+  get_options_mutable()->HiddenServiceStatistics = 1;
+
+  /* Initialize the subsystems */
+  hs_cache_init();
+  rep_hist_hs_stats_init(0);
+  update_approx_time(10101010101);
+
+  /* HS stats should be zero here */
+  hs_v3_stats = rep_hist_get_hs_v3_stats();
+  tt_int_op(digestmap_size(hs_v3_stats->v3_onions_seen_this_period), OP_EQ, 0);
+
+  /* Generate a valid descriptor */
+  ret = ed25519_keypair_generate(&signing_kp1, 0);
+  tt_int_op(ret, OP_EQ, 0);
+  desc1 = hs_helper_build_hs_desc_with_rev_counter(&signing_kp1, 42);
+  tt_assert(desc1);
+  ret = hs_desc_encode_descriptor(desc1, &signing_kp1, NULL, &desc1_str);
+  tt_int_op(ret, OP_EQ, 0);
+
+  /* Store descriptor and check that stats got updated */
+  ret = hs_cache_store_as_dir(desc1_str);
+  tt_int_op(ret, OP_EQ, 0);
+  hs_v3_stats = rep_hist_get_hs_v3_stats();
+  tt_int_op(digestmap_size(hs_v3_stats->v3_onions_seen_this_period), OP_EQ, 1);
+
+  /* cleanup */
+  hs_descriptor_free(desc1);
+  tor_free(desc1_str);
+
+  /* Generate another valid descriptor */
+  ret = ed25519_keypair_generate(&signing_kp1, 0);
+  tt_int_op(ret, OP_EQ, 0);
+  desc1 = hs_helper_build_hs_desc_with_rev_counter(&signing_kp1, 42);
+  tt_assert(desc1);
+  ret = hs_desc_encode_descriptor(desc1, &signing_kp1, NULL, &desc1_str);
+  tt_int_op(ret, OP_EQ, 0);
+
+  /* Store descriptor and check that stats are updated */
+  ret = hs_cache_store_as_dir(desc1_str);
+  tt_int_op(ret, OP_EQ, 0);
+  hs_v3_stats = rep_hist_get_hs_v3_stats();
+  tt_int_op(digestmap_size(hs_v3_stats->v3_onions_seen_this_period), OP_EQ, 2);
+
+  /* Check that storing the same descriptor twice does not work */
+  ret = hs_cache_store_as_dir(desc1_str);
+  tt_int_op(ret, OP_EQ, -1);
+
+  /* cleanup */
+  hs_descriptor_free(desc1);
+  tor_free(desc1_str);
+
+  /* Create a descriptor with the same identity key but diff rev counter and
+     same blinded key */
+  desc1 = hs_helper_build_hs_desc_with_rev_counter(&signing_kp1, 43);
+  tt_assert(desc1);
+  ret = hs_desc_encode_descriptor(desc1, &signing_kp1, NULL, &desc1_str);
+  tt_int_op(ret, OP_EQ, 0);
+
+  /* Store descriptor and check that stats are updated */
+  ret = hs_cache_store_as_dir(desc1_str);
+  tt_int_op(ret, OP_EQ, 0);
+  tt_int_op(digestmap_size(hs_v3_stats->v3_onions_seen_this_period), OP_EQ, 2);
+
+  /* cleanup */
+  hs_descriptor_free(desc1);
+  tor_free(desc1_str);
+
+  /* Now let's skip to four days forward so that the blinded key rolls
+     forward */
+  update_approx_time(approx_time() + 345600);
+
+  /* Now create a descriptor with the same identity key but diff rev counter
+     and different blinded key */
+  desc1 = hs_helper_build_hs_desc_with_rev_counter(&signing_kp1, 44);
+  tt_assert(desc1);
+  ret = hs_desc_encode_descriptor(desc1, &signing_kp1, NULL, &desc1_str);
+  tt_int_op(ret, OP_EQ, 0);
+
+  /* Store descriptor and check that stats are updated */
+  ret = hs_cache_store_as_dir(desc1_str);
+  tt_int_op(ret, OP_EQ, 0);
+  tt_int_op(digestmap_size(hs_v3_stats->v3_onions_seen_this_period), OP_EQ, 3);
+
+  /* cleanup */
+  hs_descriptor_free(desc1);
+  tor_free(desc1_str);
+
+  /* Because of differential privacy we can't actually check the stat value,
+     but let's just check that it's formatted correctly. */
+  stats_string = rep_hist_format_hs_v3_stats(approx_time(), true);
+  tt_assert(strstr(stats_string, "hidserv-dir-v3-onions-seen"));
+
+ done:
+  UNMOCK(should_collect_v3_stats);
+  tor_free(stats_string);
+}
+
 #define ENT(name)                                                       \
   { #name, test_ ## name , 0, NULL, NULL }
 #define FORK(name)                                                      \
@@ -506,6 +629,7 @@ struct testcase_t stats_tests[] = {
   FORK(add_obs),
   FORK(fill_bandwidth_history),
   FORK(get_bandwidth_lines),
+  FORK(rephist_v3_onions),
 
   END_OF_TESTCASES
 };





More information about the tor-commits mailing list