[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