diff options
author | George Kadianakis <desnacked@riseup.net> | 2020-10-21 14:17:30 +0300 |
---|---|---|
committer | George Kadianakis <desnacked@riseup.net> | 2020-11-03 11:12:17 +0200 |
commit | 131da887d75bd112e668db3c1695ad8cc5a76433 (patch) | |
tree | 9adf7e0cd9bbbd3f5203ade14c661515df460b3a | |
parent | 5c00bee1b1cde4bb77a2e3fa1f5110850ddede6e (diff) | |
download | tor-131da887d75bd112e668db3c1695ad8cc5a76433.tar.gz tor-131da887d75bd112e668db3c1695ad8cc5a76433.zip |
Write unittests for v3 metrics.
-rw-r--r-- | src/feature/stats/rephist.c | 6 | ||||
-rw-r--r-- | src/feature/stats/rephist.h | 11 | ||||
-rw-r--r-- | src/test/hs_test_helpers.c | 19 | ||||
-rw-r--r-- | src/test/hs_test_helpers.h | 4 | ||||
-rw-r--r-- | 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 }; |