From ade5005853c17b3ae5923c194680442e0f86db4d Mon Sep 17 00:00:00 2001 From: Ola Bini Date: Tue, 15 Sep 2015 16:21:50 +0200 Subject: [PATCH 1/2] Add tests for the rend cache --- src/or/rendcache.c | 37 +- src/or/rendcache.h | 17 +- src/or/routerlist.c | 5 +- src/or/routerlist.h | 3 +- src/test/include.am | 2 + src/test/rend_test_helpers.c | 65 ++ src/test/rend_test_helpers.h | 12 + src/test/test.c | 3 +- src/test/test_rendcache.c | 1178 ++++++++++++++++++++++++++++++++++ 9 files changed, 1296 insertions(+), 26 deletions(-) create mode 100644 src/test/rend_test_helpers.c create mode 100644 src/test/rend_test_helpers.h create mode 100644 src/test/test_rendcache.c diff --git a/src/or/rendcache.c b/src/or/rendcache.c index 542d322c79..800cc2446b 100644 --- a/src/or/rendcache.c +++ b/src/or/rendcache.c @@ -3,9 +3,10 @@ /** * \file rendcache.c - * \brief Hidden service desriptor cache. + * \brief Hidden service descriptor cache. **/ +#define RENDCACHE_PRIVATE #include "rendcache.h" #include "config.h" @@ -15,11 +16,11 @@ /** Map from service id (as generated by rend_get_service_id) to * rend_cache_entry_t. */ -static strmap_t *rend_cache = NULL; +STATIC strmap_t *rend_cache = NULL; /** Map from descriptor id to rend_cache_entry_t; only for hidden service * directories. */ -static digestmap_t *rend_cache_v2_dir = NULL; +STATIC digestmap_t *rend_cache_v2_dir = NULL; /** (Client side only) Map from service id to rend_cache_failure_t. This * cache is used to track intro point(IP) failures so we know when to keep @@ -46,10 +47,10 @@ static digestmap_t *rend_cache_v2_dir = NULL; * This scheme allows us to not realy on the descriptor's timestamp (which * is rounded down to the hour) to know if we have a newer descriptor. We * only rely on the usability of intro points from an internal state. */ -static strmap_t *rend_cache_failure = NULL; +STATIC strmap_t *rend_cache_failure = NULL; /** DOCDOC */ -static size_t rend_cache_total_allocation = 0; +STATIC size_t rend_cache_total_allocation = 0; /** Initializes the service descriptor cache. */ @@ -62,7 +63,7 @@ rend_cache_init(void) } /** Return the approximate number of bytes needed to hold e. */ -static size_t +STATIC size_t rend_cache_entry_allocation(const rend_cache_entry_t *e) { if (!e) @@ -80,7 +81,7 @@ rend_cache_get_total_allocation(void) } /** Decrement the total bytes attributed to the rendezvous cache by n. */ -static void +STATIC void rend_cache_decrement_allocation(size_t n) { static int have_underflowed = 0; @@ -97,7 +98,7 @@ rend_cache_decrement_allocation(size_t n) } /** Increase the total bytes attributed to the rendezvous cache by n. */ -static void +STATIC void rend_cache_increment_allocation(size_t n) { static int have_overflowed = 0; @@ -113,7 +114,7 @@ rend_cache_increment_allocation(size_t n) } /** Helper: free a rend cache failure intro object. */ -static void +STATIC void rend_cache_failure_intro_entry_free(rend_cache_failure_intro_t *entry) { if (entry == NULL) { @@ -124,7 +125,7 @@ rend_cache_failure_intro_entry_free(rend_cache_failure_intro_t *entry) /** Allocate a rend cache failure intro object and return it. failure * is set into the object. This function can not fail. */ -static rend_cache_failure_intro_t * +STATIC rend_cache_failure_intro_t * rend_cache_failure_intro_entry_new(rend_intro_point_failure_t failure) { rend_cache_failure_intro_t *entry = tor_malloc(sizeof(*entry)); @@ -134,7 +135,7 @@ rend_cache_failure_intro_entry_new(rend_intro_point_failure_t failure) } /** Helper: free a rend cache failure object. */ -static void +STATIC void rend_cache_failure_entry_free(rend_cache_failure_t *entry) { if (entry == NULL) { @@ -160,7 +161,7 @@ rend_cache_failure_entry_free_(void *entry) /** Allocate a rend cache failure object and return it. This function can * not fail. */ -static rend_cache_failure_t * +STATIC rend_cache_failure_t * rend_cache_failure_entry_new(void) { rend_cache_failure_t *entry = tor_malloc(sizeof(*entry)); @@ -170,7 +171,7 @@ rend_cache_failure_entry_new(void) /** Remove failure cache entry for the service ID in the given descriptor * desc. */ -static void +STATIC void rend_cache_failure_remove(rend_service_descriptor_t *desc) { char service_id[REND_SERVICE_ID_LEN_BASE32 + 1]; @@ -190,7 +191,7 @@ rend_cache_failure_remove(rend_service_descriptor_t *desc) } /** Helper: free storage held by a single service descriptor cache entry. */ -static void +STATIC void rend_cache_entry_free(rend_cache_entry_t *e) { if (!e) @@ -304,7 +305,7 @@ rend_cache_failure_purge(void) * identity and service ID service_id. If found, the intro * failure is set in intro_entry else it stays untouched. Return 1 * iff found else 0. */ -static int +STATIC int cache_failure_intro_lookup(const uint8_t *identity, const char *service_id, rend_cache_failure_intro_t **intro_entry) { @@ -348,7 +349,7 @@ cache_failure_intro_dup(const rend_cache_failure_intro_t *entry) /** Add an intro point failure to the failure cache using the relay * identity and service ID service_id. Record the * failure in that object. */ -static void +STATIC void cache_failure_intro_add(const uint8_t *identity, const char *service_id, rend_intro_point_failure_t failure) { @@ -372,7 +373,7 @@ cache_failure_intro_add(const uint8_t *identity, const char *service_id, * descriptor and kept into the failure cache. Then, each intro points that * are NOT in the descriptor but in the failure cache for the given * service_id are removed from the failure cache. */ -static void +STATIC void validate_intro_point_failure(const rend_service_descriptor_t *desc, const char *service_id) { @@ -652,7 +653,6 @@ rend_cache_store_v2_desc_as_dir(const char *desc) log_info(LD_REND, "Successfully stored service descriptor with desc ID " "'%s' and len %d.", safe_str(desc_id_base32), (int)encoded_size); - /* Statistics: Note down this potentially new HS. */ if (options->HiddenServiceStatistics) { rep_hist_stored_maybe_new_hs(e->parsed->pk); @@ -887,4 +887,3 @@ rend_cache_store_v2_desc_as_client(const char *desc, tor_free(intro_content); return retval; } - diff --git a/src/or/rendcache.h b/src/or/rendcache.h index 0512058054..8ba1f6ffde 100644 --- a/src/or/rendcache.h +++ b/src/or/rendcache.h @@ -76,5 +76,20 @@ void rend_cache_intro_failure_note(rend_intro_point_failure_t failure, const char *service_id); void rend_cache_failure_purge(void); -#endif /* TOR_RENDCACHE_H */ +#ifdef RENDCACHE_PRIVATE +STATIC size_t rend_cache_entry_allocation(const rend_cache_entry_t *e); +STATIC void rend_cache_entry_free(rend_cache_entry_t *e); +STATIC void rend_cache_failure_intro_entry_free(rend_cache_failure_intro_t *entry); +STATIC void rend_cache_failure_entry_free(rend_cache_failure_t *entry); +STATIC int cache_failure_intro_lookup(const uint8_t *identity, const char *service_id, rend_cache_failure_intro_t **intro_entry); +STATIC void rend_cache_decrement_allocation(size_t n); +STATIC void rend_cache_increment_allocation(size_t n); +STATIC rend_cache_failure_intro_t *rend_cache_failure_intro_entry_new(rend_intro_point_failure_t failure); +STATIC rend_cache_failure_t *rend_cache_failure_entry_new(void); +STATIC void rend_cache_failure_remove(rend_service_descriptor_t *desc); +STATIC void cache_failure_intro_add(const uint8_t *identity, const char *service_id, rend_intro_point_failure_t failure); +STATIC void validate_intro_point_failure(const rend_service_descriptor_t *desc, const char *service_id); +#endif + +#endif /* TOR_RENDCACHE_H */ diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 8bd80391bc..93dc2fe9d2 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -5184,8 +5184,8 @@ hid_serv_acting_as_directory(void) /** Return true if this node is responsible for storing the descriptor ID * in query and false otherwise. */ -int -hid_serv_responsible_for_desc_id(const char *query) +MOCK_IMPL(int, hid_serv_responsible_for_desc_id, + (const char *query)) { const routerinfo_t *me; routerstatus_t *last_rs; @@ -5208,4 +5208,3 @@ hid_serv_responsible_for_desc_id(const char *query) smartlist_free(responsible); return result; } - diff --git a/src/or/routerlist.h b/src/or/routerlist.h index 200533fe91..ec09f234a5 100644 --- a/src/or/routerlist.h +++ b/src/or/routerlist.h @@ -201,7 +201,7 @@ void refresh_all_country_info(void); int hid_serv_get_responsible_directories(smartlist_t *responsible_dirs, const char *id); int hid_serv_acting_as_directory(void); -int hid_serv_responsible_for_desc_id(const char *id); +MOCK_DECL(int, hid_serv_responsible_for_desc_id, (const char *id)); void list_pending_microdesc_downloads(digest256map_t *result); void launch_descriptor_downloads(int purpose, @@ -243,4 +243,3 @@ MOCK_DECL(STATIC void, initiate_descriptor_downloads, #endif #endif - diff --git a/src/test/include.am b/src/test/include.am index f7c0204832..a9ad57022f 100644 --- a/src/test/include.am +++ b/src/test/include.am @@ -51,6 +51,7 @@ src_test_AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \ # matters a lot there, and is quite hard to debug if you forget to do it. src_test_test_SOURCES = \ + src/test/rend_test_helpers.c \ src/test/test.c \ src/test/test_accounting.c \ src/test/test_addr.c \ @@ -87,6 +88,7 @@ src_test_test_SOURCES = \ src/test/test_pt.c \ src/test/test_relay.c \ src/test/test_relaycell.c \ + src/test/test_rendcache.c \ src/test/test_replay.c \ src/test/test_routerkeys.c \ src/test/test_routerlist.c \ diff --git a/src/test/rend_test_helpers.c b/src/test/rend_test_helpers.c new file mode 100644 index 0000000000..06e40a0153 --- /dev/null +++ b/src/test/rend_test_helpers.c @@ -0,0 +1,65 @@ +#include "rend_test_helpers.h" + +#include "test.h" +#include "rendcommon.h" + +/** TODO: Description */ +void +generate_desc(int time_diff, rend_encoded_v2_service_descriptor_t **desc, char **service_id, int intro_points) +{ + rend_service_descriptor_t *generated = NULL; + smartlist_t *descs = smartlist_new(); + time_t now; + + now = time(NULL) + time_diff; + create_descriptor(&generated, service_id, intro_points); + generated->timestamp = now; + + rend_encode_v2_descriptors(descs, generated, now, 0, REND_NO_AUTH, NULL, NULL); + *desc = ((rend_encoded_v2_service_descriptor_t *)smartlist_get(descs, 0)); + + smartlist_free(descs); + rend_service_descriptor_free(generated); +} + + +/** TODO: Description */ +void +create_descriptor(rend_service_descriptor_t **generated, char **service_id, int intro_points) +{ + crypto_pk_t *pk1 = NULL; + crypto_pk_t *pk2 = NULL; + int i; + + *service_id = tor_malloc(REND_SERVICE_ID_LEN_BASE32+1); + pk1 = pk_generate(0); + pk2 = pk_generate(1); + + *generated = tor_malloc_zero(sizeof(rend_service_descriptor_t)); + (*generated)->pk = crypto_pk_dup_key(pk1); + rend_get_service_id((*generated)->pk, *service_id); + + (*generated)->version = 2; + (*generated)->protocols = 42; + (*generated)->intro_nodes = smartlist_new(); + + for (i = 0; i < intro_points; i++) { + rend_intro_point_t *intro = tor_malloc_zero(sizeof(rend_intro_point_t)); + crypto_pk_t *okey = pk_generate(2 + i); + intro->extend_info = tor_malloc_zero(sizeof(extend_info_t)); + intro->extend_info->onion_key = okey; + crypto_pk_get_digest(intro->extend_info->onion_key, + intro->extend_info->identity_digest); + intro->extend_info->nickname[0] = '$'; + base16_encode(intro->extend_info->nickname + 1, + sizeof(intro->extend_info->nickname) - 1, + intro->extend_info->identity_digest, DIGEST_LEN); + tor_addr_from_ipv4h(&intro->extend_info->addr, crypto_rand_int(65536)); + intro->extend_info->port = 1 + crypto_rand_int(65535); + intro->intro_key = crypto_pk_dup_key(pk2); + smartlist_add((*generated)->intro_nodes, intro); + } + + crypto_pk_free(pk1); + crypto_pk_free(pk2); +} diff --git a/src/test/rend_test_helpers.h b/src/test/rend_test_helpers.h new file mode 100644 index 0000000000..00a17be692 --- /dev/null +++ b/src/test/rend_test_helpers.h @@ -0,0 +1,12 @@ +/* Copyright (c) 2014-2015, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "or.h" + +#ifndef TOR_REND_TEST_HELPERS_H +#define TOR_REND_TEST_HELPERS_H + +void generate_desc(int time_diff, rend_encoded_v2_service_descriptor_t **desc, char **service_id, int intro_points); +void create_descriptor(rend_service_descriptor_t **generated, char **service_id, int intro_points); + +#endif diff --git a/src/test/test.c b/src/test/test.c index e10e260266..773764cade 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -1148,6 +1148,7 @@ extern struct testcase_t policy_tests[]; extern struct testcase_t pt_tests[]; extern struct testcase_t relay_tests[]; extern struct testcase_t relaycell_tests[]; +extern struct testcase_t rend_cache_tests[]; extern struct testcase_t replaycache_tests[]; extern struct testcase_t router_tests[]; extern struct testcase_t routerkeys_tests[]; @@ -1195,6 +1196,7 @@ struct testgroup_t testgroups[] = { { "pt/", pt_tests }, { "relay/" , relay_tests }, { "relaycell/", relaycell_tests }, + { "rend_cache/", rend_cache_tests }, { "replaycache/", replaycache_tests }, { "routerkeys/", routerkeys_tests }, { "routerlist/", routerlist_tests }, @@ -1208,4 +1210,3 @@ struct testgroup_t testgroups[] = { { "dns/", dns_tests }, END_OF_GROUPS }; - diff --git a/src/test/test_rendcache.c b/src/test/test_rendcache.c new file mode 100644 index 0000000000..a005e66cb7 --- /dev/null +++ b/src/test/test_rendcache.c @@ -0,0 +1,1178 @@ +/* Copyright (c) 2010-2015, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "orconfig.h" +#include "or.h" + +#include "test.h" +#define RENDCACHE_PRIVATE +#include "rendcache.h" +#include "router.h" +#include "routerlist.h" +#include "config.h" +#include +#include "rend_test_helpers.h" + +#define NS_MODULE rend_cache + +static const int RECENT_TIME = -10; +static const int TIME_IN_THE_PAST = -(REND_CACHE_MAX_AGE + REND_CACHE_MAX_SKEW + 10); +static const int TIME_IN_THE_FUTURE = REND_CACHE_MAX_SKEW + 10; + +extern strmap_t *rend_cache; +extern digestmap_t *rend_cache_v2_dir; +extern strmap_t *rend_cache_failure; +extern size_t rend_cache_total_allocation; + +static rend_data_t +mock_rend_data(char *onion_address) +{ + rend_data_t rend_query; + + memset(&rend_query, 0, sizeof(rend_query)); + strncpy(rend_query.onion_address, onion_address, REND_SERVICE_ID_LEN_BASE32+1); + rend_query.auth_type = REND_NO_AUTH; + rend_query.hsdirs_fp = smartlist_new(); + smartlist_add(rend_query.hsdirs_fp, tor_memdup("aaaaaaaaaaaaaaaaaaaaaaaa", DIGEST_LEN)); + + return rend_query; +} + +static void +test_rend_cache_lookup_entry(void *data) +{ + int ret; + rend_data_t mock_rend_query; + char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1]; + rend_cache_entry_t *entry = NULL; + rend_encoded_v2_service_descriptor_t *desc_holder = NULL; + char *service_id = NULL; + (void)data; + + rend_cache_init(); + + generate_desc(RECENT_TIME, &desc_holder, &service_id, 3); + + + ret = rend_cache_lookup_entry("abababababababab", 0, NULL); + tt_int_op(ret, OP_EQ, -ENOENT); + + ret = rend_cache_lookup_entry("invalid query", 2, NULL); + tt_int_op(ret, OP_EQ, -EINVAL); + + ret = rend_cache_lookup_entry("abababababababab", 2, NULL); + tt_int_op(ret, OP_EQ, -ENOENT); + + ret = rend_cache_lookup_entry("abababababababab", 4224, NULL); + tt_int_op(ret, OP_EQ, -ENOENT); + + mock_rend_query = mock_rend_data(service_id); + base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); + rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, &mock_rend_query, NULL); + + ret = rend_cache_lookup_entry(service_id, 2, NULL); + tt_int_op(ret, OP_EQ, 0); + + ret = rend_cache_lookup_entry(service_id, 2, &entry); + tt_assert(entry); + tt_int_op(entry->len, OP_EQ, strlen(desc_holder->desc_str)); + tt_str_op(entry->desc, OP_EQ, desc_holder->desc_str); + + done: + tor_free(desc_holder); + tor_free(entry); + tor_free(service_id); +} + +static void +test_rend_cache_store_v2_desc_as_client(void *data) +{ + rend_cache_store_status_t ret; + rend_data_t mock_rend_query; + char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1]; + rend_cache_entry_t *entry = NULL; + rend_encoded_v2_service_descriptor_t *desc_holder = NULL; + char *service_id = NULL; + char client_cookie[REND_DESC_COOKIE_LEN]; + (void)data; + + rend_cache_init(); + + generate_desc(RECENT_TIME, &desc_holder, &service_id, 3); + + // Test success + mock_rend_query = mock_rend_data(service_id); + base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); + ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, &mock_rend_query, &entry); + + tt_int_op(ret, OP_EQ, RCS_OKAY); + tt_assert(entry); + tt_int_op(entry->len, OP_EQ, strlen(desc_holder->desc_str)); + tt_str_op(entry->desc, OP_EQ, desc_holder->desc_str); + + // Test various failure modes + + // TODO: a too long desc_id_base32 argument crashes the function + /* ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, "3TOOLONG3TOOLONG3TOOLONG3TOOLONG3TOOLONG3TOOLONG", &mock_rend_query, NULL); */ + /* tt_int_op(ret, OP_EQ, RCS_BADDESC); */ + + // Test bad base32 failure + // This causes an assertion failure if we're running with assertions. But when doing coverage, we can test it. +#ifdef TOR_COVERAGE + ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, "!xqunszqnaolrrfmtzgaki7mxelgvkj", &mock_rend_query, NULL); + tt_int_op(ret, OP_EQ, RCS_BADDESC); +#endif + + // Test invalid descriptor + ret = rend_cache_store_v2_desc_as_client("invalid descriptor", "3xqunszqnaolrrfmtzgaki7mxelgvkje", &mock_rend_query, NULL); + tt_int_op(ret, OP_EQ, RCS_BADDESC); + + // TODO: it doesn't seem to be possible to test invalid service ID condition. + // that means it is likely not possible to have that condition without earlier conditions failing first (such as signature checking of the desc) + + // Test mismatch between service ID and onion address + rend_cache_init(); + strncpy(mock_rend_query.onion_address, "abc", REND_SERVICE_ID_LEN_BASE32+1); + ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, &mock_rend_query, NULL); + tt_int_op(ret, OP_EQ, RCS_BADDESC); + + // Test incorrect descriptor ID + rend_cache_init(); + mock_rend_query = mock_rend_data(service_id); + desc_id_base32[0]++; + ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, &mock_rend_query, NULL); + tt_int_op(ret, OP_EQ, RCS_BADDESC); + desc_id_base32[0]--; + + // Test too old descriptor + rend_cache_init(); + tor_free(desc_holder); + tor_free(service_id); + + generate_desc(TIME_IN_THE_PAST, &desc_holder, &service_id, 3); + mock_rend_query = mock_rend_data(service_id); + base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); + + ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, &mock_rend_query, NULL); + tt_int_op(ret, OP_EQ, RCS_BADDESC); + + // Test too new descriptor (in the future) + rend_cache_init(); + tor_free(desc_holder); + tor_free(service_id); + + generate_desc(TIME_IN_THE_FUTURE, &desc_holder, &service_id, 3); + mock_rend_query = mock_rend_data(service_id); + base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); + + ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, &mock_rend_query, NULL); + tt_int_op(ret, OP_EQ, RCS_BADDESC); + + // Test when a descriptor is already in the cache + rend_cache_init(); + tor_free(desc_holder); + tor_free(service_id); + tor_free(entry); + + generate_desc(RECENT_TIME, &desc_holder, &service_id, 3); + mock_rend_query = mock_rend_data(service_id); + base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); + + rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, &mock_rend_query, NULL); + ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, &mock_rend_query, NULL); + tt_int_op(ret, OP_EQ, RCS_OKAY); + + ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, &mock_rend_query, &entry); + tt_int_op(ret, OP_EQ, RCS_OKAY); + tt_assert(entry); + + // Test unsuccessful decrypting of introduction points + rend_cache_init(); + tor_free(desc_holder); + tor_free(service_id); + + generate_desc(RECENT_TIME, &desc_holder, &service_id, 3); + mock_rend_query = mock_rend_data(service_id); + mock_rend_query.auth_type = REND_BASIC_AUTH; + client_cookie[0] = 'A'; + memcpy(mock_rend_query.descriptor_cookie, client_cookie, REND_DESC_COOKIE_LEN); + base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); + ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, &mock_rend_query, NULL); + tt_int_op(ret, OP_EQ, RCS_OKAY); + + // Test successful run when we have REND_BASIC_AUTH but not cookie + rend_cache_init(); + tor_free(desc_holder); + tor_free(service_id); + + generate_desc(RECENT_TIME, &desc_holder, &service_id, 3); + mock_rend_query = mock_rend_data(service_id); + mock_rend_query.auth_type = REND_BASIC_AUTH; + base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); + ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, &mock_rend_query, NULL); + tt_int_op(ret, OP_EQ, RCS_OKAY); + + // Test when we have no introduction points + rend_cache_init(); + tor_free(desc_holder); + tor_free(service_id); + + generate_desc(RECENT_TIME, &desc_holder, &service_id, 0); + mock_rend_query = mock_rend_data(service_id); + base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); + ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, &mock_rend_query, NULL); + tt_int_op(ret, OP_EQ, RCS_BADDESC); + + // Test when we have too many intro points + rend_cache_init(); + tor_free(desc_holder); + tor_free(service_id); + + generate_desc(RECENT_TIME, &desc_holder, &service_id, MAX_INTRO_POINTS+1); + mock_rend_query = mock_rend_data(service_id); + base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); + ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, &mock_rend_query, NULL); + tt_int_op(ret, OP_EQ, RCS_BADDESC); + + done: + rend_encoded_v2_service_descriptor_free(desc_holder); + tor_free(entry); + tor_free(service_id); +} + +static void +test_rend_cache_store_v2_desc_as_client_with_different_time(void *data) +{ + rend_cache_store_status_t ret; + rend_data_t mock_rend_query; + char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1]; + rend_service_descriptor_t *generated = NULL; + smartlist_t *descs = smartlist_new(); + time_t t; + char *service_id = NULL; + rend_encoded_v2_service_descriptor_t *desc_holder_newer; + rend_encoded_v2_service_descriptor_t *desc_holder_older; + + t = time(NULL); + + create_descriptor(&generated, &service_id, 3); + + generated->timestamp = t + RECENT_TIME; + rend_encode_v2_descriptors(descs, generated, t + RECENT_TIME, 0, REND_NO_AUTH, NULL, NULL); + desc_holder_newer = ((rend_encoded_v2_service_descriptor_t *)smartlist_get(descs, 0)); + + smartlist_free(descs); + descs = smartlist_new(); + + generated->timestamp = (t + RECENT_TIME) - 20; + rend_encode_v2_descriptors(descs, generated, t + RECENT_TIME, 0, REND_NO_AUTH, NULL, NULL); + desc_holder_older = ((rend_encoded_v2_service_descriptor_t *)smartlist_get(descs, 0)); + + (void)data; + rend_cache_init(); + + // Test when a descriptor is already in the cache and it is newer than the one we submit + mock_rend_query = mock_rend_data(service_id); + base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder_newer->desc_id, DIGEST_LEN); + rend_cache_store_v2_desc_as_client(desc_holder_newer->desc_str, desc_id_base32, &mock_rend_query, NULL); + ret = rend_cache_store_v2_desc_as_client(desc_holder_older->desc_str, desc_id_base32, &mock_rend_query, NULL); + tt_int_op(ret, OP_EQ, RCS_OKAY); + + // Test when an old descriptor is in the cache and we submit a newer one + rend_cache_init(); + rend_cache_store_v2_desc_as_client(desc_holder_older->desc_str, desc_id_base32, &mock_rend_query, NULL); + ret = rend_cache_store_v2_desc_as_client(desc_holder_newer->desc_str, desc_id_base32, &mock_rend_query, NULL); + tt_int_op(ret, OP_EQ, RCS_OKAY); + + done: + rend_encoded_v2_service_descriptor_free(desc_holder_newer); + rend_encoded_v2_service_descriptor_free(desc_holder_older); + smartlist_free(descs); + rend_service_descriptor_free(generated); + tor_free(service_id); +} + + +#define NS_SUBMODULE lookup_v2_desc_as_dir +NS_DECL(const routerinfo_t *, router_get_my_routerinfo, (void)); +NS_DECL(int, hid_serv_responsible_for_desc_id, (const char *id)); + +static routerinfo_t *mock_routerinfo; +static int hid_serv_responsible_for_desc_id_response; + +static const routerinfo_t * +NS(router_get_my_routerinfo)(void) +{ + if(!mock_routerinfo) { + mock_routerinfo = tor_malloc(sizeof(routerinfo_t)); + } + + return mock_routerinfo; +} + +static int +NS(hid_serv_responsible_for_desc_id)(const char *id) +{ + return hid_serv_responsible_for_desc_id_response; +} + +static void +test_rend_cache_lookup_v2_desc_as_dir(void *data) +{ + int ret; + char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1]; + rend_encoded_v2_service_descriptor_t *desc_holder = NULL; + char *service_id = NULL; + const char *ret_desc = NULL; + + (void)data; + + NS_MOCK(router_get_my_routerinfo); + NS_MOCK(hid_serv_responsible_for_desc_id); + + rend_cache_init(); + + // Test invalid base32 + ret = rend_cache_lookup_v2_desc_as_dir("!bababababababab", NULL); + tt_int_op(ret, OP_EQ, -1); + + // Test non-existent descriptor but well formed + ret = rend_cache_lookup_v2_desc_as_dir("3xqunszqnaolrrfmtzgaki7mxelgvkje", NULL); + tt_int_op(ret, OP_EQ, 0); + + // Test existing descriptor + hid_serv_responsible_for_desc_id_response = 1; + generate_desc(RECENT_TIME, &desc_holder, &service_id, 3); + rend_cache_store_v2_desc_as_dir(desc_holder->desc_str); + base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); + ret = rend_cache_lookup_v2_desc_as_dir(desc_id_base32, &ret_desc); + tt_int_op(ret, OP_EQ, 1); + tt_assert(ret_desc); + + done: + NS_UNMOCK(router_get_my_routerinfo); + NS_UNMOCK(hid_serv_responsible_for_desc_id); + tor_free(mock_routerinfo); +} + +#undef NS_SUBMODULE + +#define NS_SUBMODULE store_v2_desc_as_dir +NS_DECL(const routerinfo_t *, router_get_my_routerinfo, (void)); +NS_DECL(int, hid_serv_responsible_for_desc_id, (const char *id)); + +static routerinfo_t *mock_routerinfo; +static int hid_serv_responsible_for_desc_id_response; + +static const routerinfo_t * +NS(router_get_my_routerinfo)(void) +{ + return mock_routerinfo; +} + +static int +NS(hid_serv_responsible_for_desc_id)(const char *id) +{ + return hid_serv_responsible_for_desc_id_response; +} + +static void +test_rend_cache_store_v2_desc_as_dir(void *data) +{ + (void)data; + rend_cache_store_status_t ret; + rend_encoded_v2_service_descriptor_t *desc_holder = NULL; + char *service_id = NULL; + + NS_MOCK(router_get_my_routerinfo); + NS_MOCK(hid_serv_responsible_for_desc_id); + + rend_cache_init(); + + // Test when we are not an HS dir + mock_routerinfo = NULL; + ret = rend_cache_store_v2_desc_as_dir(""); + tt_int_op(ret, OP_EQ, RCS_NOTDIR); + + // Test when we can't parse the descriptor + mock_routerinfo = tor_malloc(sizeof(routerinfo_t)); + hid_serv_responsible_for_desc_id_response = 1; + ret = rend_cache_store_v2_desc_as_dir("unparseable"); + tt_int_op(ret, OP_EQ, RCS_BADDESC); + + // Test when we are not responsible for an HS + hid_serv_responsible_for_desc_id_response = 0; + generate_desc(RECENT_TIME, &desc_holder, &service_id, 3); + ret = rend_cache_store_v2_desc_as_dir(desc_holder->desc_str); + tt_int_op(ret, OP_EQ, RCS_OKAY); + + // Test when we have an old descriptor + hid_serv_responsible_for_desc_id_response = 1; + generate_desc(TIME_IN_THE_PAST, &desc_holder, &service_id, 3); + ret = rend_cache_store_v2_desc_as_dir(desc_holder->desc_str); + tt_int_op(ret, OP_EQ, RCS_OKAY); + + // Test when we have a descriptor in the future + generate_desc(TIME_IN_THE_FUTURE, &desc_holder, &service_id, 3); + ret = rend_cache_store_v2_desc_as_dir(desc_holder->desc_str); + tt_int_op(ret, OP_EQ, RCS_OKAY); + + // Test when two descriptors + generate_desc(TIME_IN_THE_FUTURE, &desc_holder, &service_id, 3); + ret = rend_cache_store_v2_desc_as_dir(desc_holder->desc_str); + tt_int_op(ret, OP_EQ, RCS_OKAY); + + // Test when asking for hidden service statistics HiddenServiceStatistics + rend_cache_purge(); + generate_desc(RECENT_TIME, &desc_holder, &service_id, 3); + get_options_mutable()->HiddenServiceStatistics = 1; + ret = rend_cache_store_v2_desc_as_dir(desc_holder->desc_str); + tt_int_op(ret, OP_EQ, RCS_OKAY); + + done: + NS_UNMOCK(router_get_my_routerinfo); + NS_UNMOCK(hid_serv_responsible_for_desc_id); + tor_free(desc_holder); + tor_free(service_id); +} + +static void +test_rend_cache_store_v2_desc_as_dir_with_different_time(void *data) +{ + (void)data; + + rend_cache_store_status_t ret; + rend_service_descriptor_t *generated = NULL; + smartlist_t *descs = smartlist_new(); + time_t t; + char *service_id = NULL; + rend_encoded_v2_service_descriptor_t *desc_holder_newer; + rend_encoded_v2_service_descriptor_t *desc_holder_older; + + NS_MOCK(router_get_my_routerinfo); + NS_MOCK(hid_serv_responsible_for_desc_id); + + rend_cache_init(); + + t = time(NULL); + + create_descriptor(&generated, &service_id, 3); + generated->timestamp = t + RECENT_TIME; + rend_encode_v2_descriptors(descs, generated, t + RECENT_TIME, 0, REND_NO_AUTH, NULL, NULL); + desc_holder_newer = ((rend_encoded_v2_service_descriptor_t *)smartlist_get(descs, 0)); + + smartlist_free(descs); + descs = smartlist_new(); + + generated->timestamp = (t + RECENT_TIME) - 20; + rend_encode_v2_descriptors(descs, generated, t + RECENT_TIME, 0, REND_NO_AUTH, NULL, NULL); + desc_holder_older = ((rend_encoded_v2_service_descriptor_t *)smartlist_get(descs, 0)); + + // Test when we have a newer descriptor stored + mock_routerinfo = tor_malloc(sizeof(routerinfo_t)); + hid_serv_responsible_for_desc_id_response = 1; + rend_cache_store_v2_desc_as_dir(desc_holder_newer->desc_str); + ret = rend_cache_store_v2_desc_as_dir(desc_holder_older->desc_str); + tt_int_op(ret, OP_EQ, RCS_OKAY); + + // Test when we have an old descriptor stored + rend_cache_purge(); + rend_cache_store_v2_desc_as_dir(desc_holder_older->desc_str); + ret = rend_cache_store_v2_desc_as_dir(desc_holder_newer->desc_str); + tt_int_op(ret, OP_EQ, RCS_OKAY); + + done: + NS_UNMOCK(router_get_my_routerinfo); + NS_UNMOCK(hid_serv_responsible_for_desc_id); +} + +static void +test_rend_cache_store_v2_desc_as_dir_with_different_content(void *data) +{ + (void)data; + + rend_cache_store_status_t ret; + rend_service_descriptor_t *generated = NULL; + smartlist_t *descs = smartlist_new(); + time_t t; + char *service_id = NULL; + rend_encoded_v2_service_descriptor_t *desc_holder_one; + rend_encoded_v2_service_descriptor_t *desc_holder_two; + + NS_MOCK(router_get_my_routerinfo); + NS_MOCK(hid_serv_responsible_for_desc_id); + + rend_cache_init(); + + t = time(NULL); + + create_descriptor(&generated, &service_id, 3); + generated->timestamp = t + RECENT_TIME; + rend_encode_v2_descriptors(descs, generated, t + RECENT_TIME, 0, REND_NO_AUTH, NULL, NULL); + desc_holder_one = ((rend_encoded_v2_service_descriptor_t *)smartlist_get(descs, 0)); + + smartlist_free(descs); + descs = smartlist_new(); + + generated->timestamp = t + RECENT_TIME; + generated->protocols = 41; + rend_encode_v2_descriptors(descs, generated, t + RECENT_TIME, 0, REND_NO_AUTH, NULL, NULL); + desc_holder_two = ((rend_encoded_v2_service_descriptor_t *)smartlist_get(descs, 0)); + + // Test when we have another descriptor stored, with a different descriptor + mock_routerinfo = tor_malloc(sizeof(routerinfo_t)); + hid_serv_responsible_for_desc_id_response = 1; + rend_cache_store_v2_desc_as_dir(desc_holder_one->desc_str); + ret = rend_cache_store_v2_desc_as_dir(desc_holder_two->desc_str); + tt_int_op(ret, OP_EQ, RCS_OKAY); + + done: + NS_UNMOCK(router_get_my_routerinfo); + NS_UNMOCK(hid_serv_responsible_for_desc_id); +} + + +#undef NS_SUBMODULE + +static void +test_rend_cache_init(void *data) +{ + (void)data; + + tt_assert_msg(!rend_cache, "rend_cache should be NULL when starting"); + tt_assert_msg(!rend_cache_v2_dir, "rend_cache_v2_dir should be NULL when starting"); + tt_assert_msg(!rend_cache_failure, "rend_cache_failure should be NULL when starting"); + + rend_cache_init(); + + tt_assert_msg(rend_cache, "rend_cache should not be NULL after initing"); + tt_assert_msg(rend_cache_v2_dir, "rend_cache_v2_dir should not be NULL after initing"); + tt_assert_msg(rend_cache_failure, "rend_cache_failure should not be NULL after initing"); + + tt_int_op(strmap_size(rend_cache), OP_EQ, 0); + tt_int_op(digestmap_size(rend_cache_v2_dir), OP_EQ, 0); + tt_int_op(strmap_size(rend_cache_failure), OP_EQ, 0); + + done: + (void)0; +} + +static void +test_rend_cache_decrement_allocation(void *data) +{ + (void)data; + + // Test when the cache has enough allocations + rend_cache_total_allocation = 10; + rend_cache_decrement_allocation(3); + tt_int_op(rend_cache_total_allocation, OP_EQ, 7); + + // Test when there are not enough allocations + rend_cache_total_allocation = 1; + rend_cache_decrement_allocation(2); + tt_int_op(rend_cache_total_allocation, OP_EQ, 0); + + // And again + rend_cache_decrement_allocation(2); + tt_int_op(rend_cache_total_allocation, OP_EQ, 0); + + done: + (void)0; +} + +static void +test_rend_cache_increment_allocation(void *data) +{ + (void)data; + + // Test when the cache is not overflowing + rend_cache_total_allocation = 5; + rend_cache_increment_allocation(3); + tt_int_op(rend_cache_total_allocation, OP_EQ, 8); + + // Test when there are too many allocations + rend_cache_total_allocation = SIZE_MAX-1; + rend_cache_increment_allocation(2); + tt_int_op(rend_cache_total_allocation, OP_EQ, SIZE_MAX); + + // And again + rend_cache_increment_allocation(2); + tt_int_op(rend_cache_total_allocation, OP_EQ, SIZE_MAX); + + done: + (void)0; +} + + +static void +test_rend_cache_failure_intro_entry_new(void *data) +{ + time_t now; + rend_cache_failure_intro_t *entry; + rend_intro_point_failure_t failure; + + (void)data; + + failure = INTRO_POINT_FAILURE_TIMEOUT; + now = time(NULL); + entry = rend_cache_failure_intro_entry_new(failure); + + tt_int_op(entry->failure_type, OP_EQ, INTRO_POINT_FAILURE_TIMEOUT); + tt_int_op(entry->created_ts, OP_GE, now-5); + tt_int_op(entry->created_ts, OP_LE, now+5); + + done: + tor_free(entry); +} + +static void +test_rend_cache_failure_intro_lookup(void *data) +{ + (void)data; + int ret; + rend_cache_failure_t *failure; + rend_cache_failure_intro_t *ip; + rend_cache_failure_intro_t *entry; + + rend_cache_init(); + + failure = rend_cache_failure_entry_new(); + ip = rend_cache_failure_intro_entry_new(INTRO_POINT_FAILURE_TIMEOUT); + digestmap_set(failure->intro_failures, "ip1", ip); + strmap_set_lc(rend_cache_failure, "foo1", failure); + + // Test not found + ret = cache_failure_intro_lookup((const uint8_t *)"foo1", "foo2", NULL); + tt_int_op(ret, OP_EQ, 0); + + // Test found with no intro failures in it + ret = cache_failure_intro_lookup((const uint8_t *)"ip2", "foo1", NULL); + tt_int_op(ret, OP_EQ, 0); + + // Test found + ret = cache_failure_intro_lookup((const uint8_t *)"ip1", "foo1", NULL); + tt_int_op(ret, OP_EQ, 1); + + // Test found and asking for entry + cache_failure_intro_lookup((const uint8_t *)"ip1", "foo1", &entry); + tt_assert(entry); + tt_assert(entry == ip); + + done: + rend_cache_purge(); +} + +static void +test_rend_cache_clean(void *data) +{ + rend_cache_entry_t *one, *two; + rend_service_descriptor_t *desc_one, *desc_two; + strmap_iter_t *iter = NULL; + const char *key; + void *val; + + (void)data; + + rend_cache_init(); + + // Test with empty rendcache + rend_cache_clean(time(NULL)); + tt_int_op(strmap_size(rend_cache), OP_EQ, 0); + + // Test with two old entries + one = tor_malloc_zero(sizeof(rend_cache_entry_t)); + two = tor_malloc_zero(sizeof(rend_cache_entry_t)); + desc_one = tor_malloc_zero(sizeof(rend_service_descriptor_t)); + desc_two = tor_malloc_zero(sizeof(rend_service_descriptor_t)); + one->parsed = desc_one; + two->parsed = desc_two; + + desc_one->timestamp = time(NULL) + TIME_IN_THE_PAST; + desc_two->timestamp = (time(NULL) + TIME_IN_THE_PAST) - 10; + desc_one->pk = pk_generate(0); + desc_two->pk = pk_generate(1); + + strmap_set_lc(rend_cache, "foo1", one); + strmap_set_lc(rend_cache, "foo2", two); + + rend_cache_clean(time(NULL)); + tt_int_op(strmap_size(rend_cache), OP_EQ, 0); + + // Test with one old entry and one newer entry + one = tor_malloc_zero(sizeof(rend_cache_entry_t)); + two = tor_malloc_zero(sizeof(rend_cache_entry_t)); + desc_one = tor_malloc_zero(sizeof(rend_service_descriptor_t)); + desc_two = tor_malloc_zero(sizeof(rend_service_descriptor_t)); + one->parsed = desc_one; + two->parsed = desc_two; + + desc_one->timestamp = (time(NULL) + TIME_IN_THE_PAST) - 10; + desc_two->timestamp = time(NULL) - 100; + desc_one->pk = pk_generate(0); + desc_two->pk = pk_generate(1); + + strmap_set_lc(rend_cache, "foo1", one); + strmap_set_lc(rend_cache, "foo2", two); + + rend_cache_clean(time(NULL)); + tt_int_op(strmap_size(rend_cache), OP_EQ, 1); + + iter = strmap_iter_init(rend_cache); + strmap_iter_get(iter, &key, &val); + tt_str_op(key, OP_EQ, "foo2"); + + done: + (void)1; +} + +static void +test_rend_cache_failure_entry_new(void *data) +{ + rend_cache_failure_t *failure; + + (void)data; + + failure = rend_cache_failure_entry_new(); + tt_assert(failure); + tt_int_op(digestmap_size(failure->intro_failures), OP_EQ, 0); + + done: + tor_free(failure); +} + +static void +test_rend_cache_failure_entry_free(void *data) +{ + (void)data; + + // Test that it can deal with a NULL argument + rend_cache_failure_entry_free(NULL); + + /* done: */ + /* (void)0; */ +} + +static void +test_rend_cache_failure_clean(void *data) +{ + rend_cache_failure_t *failure; + rend_cache_failure_intro_t *ip_one, *ip_two; + + (void)data; + + rend_cache_init(); + + // Test with empty failure cache + rend_cache_failure_clean(time(NULL)); + tt_int_op(strmap_size(rend_cache_failure), OP_EQ, 0); + + // Test with one empty failure entry + failure = rend_cache_failure_entry_new(); + strmap_set_lc(rend_cache_failure, "foo1", failure); + rend_cache_failure_clean(time(NULL)); + tt_int_op(strmap_size(rend_cache_failure), OP_EQ, 0); + + // Test with one new intro point + failure = rend_cache_failure_entry_new(); + ip_one = rend_cache_failure_intro_entry_new(INTRO_POINT_FAILURE_TIMEOUT); + digestmap_set(failure->intro_failures, "ip1", ip_one); + strmap_set_lc(rend_cache_failure, "foo1", failure); + rend_cache_failure_clean(time(NULL)); + tt_int_op(strmap_size(rend_cache_failure), OP_EQ, 1); + + // Test with one old intro point + rend_cache_failure_purge(); + failure = rend_cache_failure_entry_new(); + ip_one = rend_cache_failure_intro_entry_new(INTRO_POINT_FAILURE_TIMEOUT); + ip_one->created_ts = time(NULL) - 7*60; + digestmap_set(failure->intro_failures, "ip1", ip_one); + strmap_set_lc(rend_cache_failure, "foo1", failure); + rend_cache_failure_clean(time(NULL)); + tt_int_op(strmap_size(rend_cache_failure), OP_EQ, 0); + + + // Test with one old intro point and one new one + rend_cache_failure_purge(); + failure = rend_cache_failure_entry_new(); + ip_one = rend_cache_failure_intro_entry_new(INTRO_POINT_FAILURE_TIMEOUT); + ip_one->created_ts = time(NULL) - 7*60; + digestmap_set(failure->intro_failures, "ip1", ip_one); + ip_two = rend_cache_failure_intro_entry_new(INTRO_POINT_FAILURE_TIMEOUT); + ip_two->created_ts = time(NULL) - 2*60; + digestmap_set(failure->intro_failures, "ip2", ip_two); + strmap_set_lc(rend_cache_failure, "foo1", failure); + rend_cache_failure_clean(time(NULL)); + tt_int_op(strmap_size(rend_cache_failure), OP_EQ, 1); + tt_int_op(digestmap_size(failure->intro_failures), OP_EQ, 1); + + done: + (void)0; +} + + +static void +test_rend_cache_failure_remove(void *data) +{ + rend_service_descriptor_t *desc; + (void)data; + + rend_cache_init(); + + // Test that it deals well with a NULL desc + rend_cache_failure_remove(NULL); + + // Test a descriptor that isn't in the cache + desc = tor_malloc_zero(sizeof(rend_service_descriptor_t)); + desc->pk = pk_generate(0); + rend_cache_failure_remove(desc); + + // There seems to not exist any way of getting rend_cache_failure_remove() to fail because of a problem with rend_get_service_id from here + + /* done: */ + /* (void)0; */ +} + +static void +test_rend_cache_free_all(void *data) +{ + rend_cache_failure_t *failure; + rend_cache_entry_t *one; + rend_service_descriptor_t *desc_one; + + (void)data; + + rend_cache_init(); + + failure = rend_cache_failure_entry_new(); + strmap_set_lc(rend_cache_failure, "foo1", failure); + + one = tor_malloc_zero(sizeof(rend_cache_entry_t)); + desc_one = tor_malloc_zero(sizeof(rend_service_descriptor_t)); + one->parsed = desc_one; + desc_one->timestamp = time(NULL) + TIME_IN_THE_PAST; + desc_one->pk = pk_generate(0); + strmap_set_lc(rend_cache, "foo1", one); + + rend_cache_free_all(); + + tt_assert(!rend_cache); + tt_assert(!rend_cache_v2_dir); + tt_assert(!rend_cache_failure); + tt_assert(!rend_cache_total_allocation); + + done: + (void)0; +} + + +static void +test_rend_cache_entry_free(void *data) +{ + (void)data; + rend_cache_entry_t *e; + + // Handles NULL correctly + rend_cache_entry_free(NULL); + + // Handles NULL descriptor correctly + e = tor_malloc_zero(sizeof(rend_cache_entry_t)); + rend_cache_entry_free(e); + + // Handles non-NULL descriptor correctly + e = tor_malloc_zero(sizeof(rend_cache_entry_t)); + e->desc = (char *)malloc(10); + rend_cache_entry_free(e); + + /* done: */ + /* (void)0; */ +} + + +static void +test_rend_cache_purge(void *data) +{ + strmap_t *our_rend_cache; + + (void)data; + + // Deals with a NULL rend_cache + rend_cache_purge(); + tt_assert(rend_cache); + tt_int_op(strmap_size(rend_cache), OP_EQ, 0); + + // Deals with existing rend_cache + rend_cache_init(); + + our_rend_cache = rend_cache; + rend_cache_purge(); + tt_assert(rend_cache); + tt_assert(rend_cache == our_rend_cache); + + done: + (void)0; +} + +static void +test_rend_cache_failure_intro_add(void *data) +{ + (void)data; + rend_cache_failure_t *fail_entry; + rend_cache_failure_intro_t *entry; + + rend_cache_init(); + + // Adds non-existing entry + cache_failure_intro_add((const uint8_t *)"foo1", "foo2", INTRO_POINT_FAILURE_TIMEOUT); + fail_entry = strmap_get_lc(rend_cache_failure, "foo2"); + tt_assert(fail_entry); + tt_int_op(digestmap_size(fail_entry->intro_failures), OP_EQ, 1); + entry = digestmap_get(fail_entry->intro_failures, "foo1"); + tt_assert(entry); + + // Adds existing entry + cache_failure_intro_add((const uint8_t *)"foo1", "foo2", INTRO_POINT_FAILURE_TIMEOUT); + fail_entry = strmap_get_lc(rend_cache_failure, "foo2"); + tt_assert(fail_entry); + tt_int_op(digestmap_size(fail_entry->intro_failures), OP_EQ, 1); + entry = digestmap_get(fail_entry->intro_failures, "foo1"); + tt_assert(entry); + + done: + rend_cache_purge(); +} + + +static void +test_rend_cache_intro_failure_note(void *data) +{ + (void)data; + rend_cache_failure_t *fail_entry; + rend_cache_failure_intro_t *entry; + + // Test not found + rend_cache_intro_failure_note(INTRO_POINT_FAILURE_TIMEOUT,(const uint8_t *)"foo1", "foo2"); + fail_entry = strmap_get_lc(rend_cache_failure, "foo2"); + tt_assert(fail_entry); + tt_int_op(digestmap_size(fail_entry->intro_failures), OP_EQ, 1); + entry = digestmap_get(fail_entry->intro_failures, "foo1"); + tt_assert(entry); + tt_int_op(entry->failure_type, OP_EQ, INTRO_POINT_FAILURE_TIMEOUT); + + // Test found + rend_cache_intro_failure_note(INTRO_POINT_FAILURE_UNREACHABLE,(const uint8_t *)"foo1", "foo2"); + tt_int_op(entry->failure_type, OP_EQ, INTRO_POINT_FAILURE_UNREACHABLE); + + done: + rend_cache_purge(); +} + +#define NS_SUBMODULE clean_v2_descs_as_dir +NS_DECL(int, hid_serv_responsible_for_desc_id, (const char *id)); + +static int hid_serv_responsible_for_desc_id_response; + +static int +NS(hid_serv_responsible_for_desc_id)(const char *id) +{ + return hid_serv_responsible_for_desc_id_response; +} + + +static void +test_rend_cache_clean_v2_descs_as_dir(void *data) +{ + rend_cache_entry_t *e; + time_t now; + rend_service_descriptor_t *desc; + now = time(NULL); + + (void)data; + + NS_MOCK(hid_serv_responsible_for_desc_id); + rend_cache_init(); + + // Test running with an empty cache + rend_cache_clean_v2_descs_as_dir(now, 0); + tt_int_op(digestmap_size(rend_cache_v2_dir), OP_EQ, 0); + + // Test with only one new entry + e = tor_malloc_zero(sizeof(rend_cache_entry_t)); + e->last_served = now; + desc = tor_malloc_zero(sizeof(rend_service_descriptor_t)); + desc->timestamp = now; + desc->pk = pk_generate(0); + e->parsed = desc; + digestmap_set(rend_cache_v2_dir, "abcde", e); + + hid_serv_responsible_for_desc_id_response = 1; + rend_cache_clean_v2_descs_as_dir(now, 0); + tt_int_op(digestmap_size(rend_cache_v2_dir), OP_EQ, 1); + + // Test with one old entry + desc->timestamp = now - (REND_CACHE_MAX_AGE + REND_CACHE_MAX_SKEW + 1000); + rend_cache_clean_v2_descs_as_dir(now, 0); + tt_int_op(digestmap_size(rend_cache_v2_dir), OP_EQ, 0); + + // Test with one entry that is not under the responsibility of this hidden service + e = tor_malloc_zero(sizeof(rend_cache_entry_t)); + e->last_served = now; + desc = tor_malloc_zero(sizeof(rend_service_descriptor_t)); + desc->timestamp = now; + desc->pk = pk_generate(0); + e->parsed = desc; + digestmap_set(rend_cache_v2_dir, "abcde", e); + + hid_serv_responsible_for_desc_id_response = 0; + rend_cache_clean_v2_descs_as_dir(now, 0); + tt_int_op(digestmap_size(rend_cache_v2_dir), OP_EQ, 0); + + // Test with one entry that has an old last served + e = tor_malloc_zero(sizeof(rend_cache_entry_t)); + e->last_served = now - (REND_CACHE_MAX_AGE + REND_CACHE_MAX_SKEW + 1000); + desc = tor_malloc_zero(sizeof(rend_service_descriptor_t)); + desc->timestamp = now; + desc->pk = pk_generate(0); + e->parsed = desc; + digestmap_set(rend_cache_v2_dir, "abcde", e); + + hid_serv_responsible_for_desc_id_response = 1; + rend_cache_clean_v2_descs_as_dir(now, 0); + tt_int_op(digestmap_size(rend_cache_v2_dir), OP_EQ, 0); + + // Test a run through asking for a large force_remove + e = tor_malloc_zero(sizeof(rend_cache_entry_t)); + e->last_served = now; + desc = tor_malloc_zero(sizeof(rend_service_descriptor_t)); + desc->timestamp = now; + desc->pk = pk_generate(0); + e->parsed = desc; + digestmap_set(rend_cache_v2_dir, "abcde", e); + + hid_serv_responsible_for_desc_id_response = 1; + rend_cache_clean_v2_descs_as_dir(now, 20000); + tt_int_op(digestmap_size(rend_cache_v2_dir), OP_EQ, 1); + + + + done: + NS_UNMOCK(hid_serv_responsible_for_desc_id); + rend_cache_purge(); +} + +#undef NS_SUBMODULE + + +static void +test_rend_cache_entry_allocation(void *data) +{ + (void)data; + + int ret; + rend_cache_entry_t *e; + + // Handles a null argument + ret = rend_cache_entry_allocation(NULL); + tt_int_op(ret, OP_EQ, 0); + + // Handles a non-null argument + e = tor_malloc_zero(sizeof(rend_cache_entry_t)); + ret = rend_cache_entry_allocation(e); + tt_int_op(ret, OP_EQ, 88); + + done: + (void)0; +} + +static void +test_rend_cache_failure_intro_entry_free(void *data) +{ + (void)data; + rend_cache_failure_intro_t *entry; + + // Handles a null argument + rend_cache_failure_intro_entry_free(NULL); + + // Handles a non-null argument + entry = rend_cache_failure_intro_entry_new(INTRO_POINT_FAILURE_TIMEOUT); + rend_cache_failure_intro_entry_free(entry); +} + + +static void +test_rend_cache_failure_purge(void *data) +{ + (void)data; + + // Handles a null failure cache + rend_cache_failure = NULL; + + rend_cache_failure_purge(); + + tt_int_op(strmap_size(rend_cache_failure), OP_EQ, 0); + + done: + (void)0; +} + +static void +test_rend_cache_validate_intro_point_failure(void *data) +{ + (void)data; + rend_service_descriptor_t *desc = NULL; + char *service_id = NULL; + rend_intro_point_t *intro = NULL; + const uint8_t *identity = NULL; + rend_cache_failure_t *failure; + rend_cache_failure_intro_t *ip; + + rend_cache_init(); + + create_descriptor(&desc, &service_id, 3); + desc->timestamp = time(NULL) + RECENT_TIME; + + intro = (rend_intro_point_t *)smartlist_get(desc->intro_nodes, 0); + identity = (uint8_t *) intro->extend_info->identity_digest; + + failure = rend_cache_failure_entry_new(); + ip = rend_cache_failure_intro_entry_new(INTRO_POINT_FAILURE_TIMEOUT); + digestmap_set(failure->intro_failures, (char *)identity, ip); + strmap_set_lc(rend_cache_failure, service_id, failure); + + // Test when we have an intro point in our cache + validate_intro_point_failure(desc, service_id); + tt_int_op(smartlist_len(desc->intro_nodes), OP_EQ, 2); + + done: + rend_cache_purge(); +} + +struct testcase_t rend_cache_tests[] = { + { "init", test_rend_cache_init, 0, NULL, NULL }, + { "decrement_allocation", test_rend_cache_decrement_allocation, 0, NULL, NULL }, + { "increment_allocation", test_rend_cache_increment_allocation, 0, NULL, NULL }, + { "clean", test_rend_cache_clean, TT_FORK, NULL, NULL }, + { "clean_v2_descs_as_dir", test_rend_cache_clean_v2_descs_as_dir, 0, NULL, NULL }, + { "entry_allocation", test_rend_cache_entry_allocation, 0, NULL, NULL }, + { "entry_free", test_rend_cache_entry_free, 0, NULL, NULL }, + { "failure_intro_entry_free", test_rend_cache_failure_intro_entry_free, 0, NULL, NULL }, + { "free_all", test_rend_cache_free_all, 0, NULL, NULL }, + { "purge", test_rend_cache_purge, 0, NULL, NULL }, + { "failure_clean", test_rend_cache_failure_clean, 0, NULL, NULL }, + { "failure_entry_new", test_rend_cache_failure_entry_new, 0, NULL, NULL }, + { "failure_entry_free", test_rend_cache_failure_entry_free, 0, NULL, NULL }, + { "failure_intro_add", test_rend_cache_failure_intro_add, 0, NULL, NULL }, + { "failure_intro_entry_new", test_rend_cache_failure_intro_entry_new, 0, NULL, NULL }, + { "failure_intro_lookup", test_rend_cache_failure_intro_lookup, 0, NULL, NULL }, + { "failure_purge", test_rend_cache_failure_purge, 0, NULL, NULL }, + { "failure_remove", test_rend_cache_failure_remove, 0, NULL, NULL }, + { "intro_failure_note", test_rend_cache_intro_failure_note, 0, NULL, NULL }, + { "lookup", test_rend_cache_lookup_entry, 0, NULL, NULL }, + { "lookup_v2_desc_as_dir", test_rend_cache_lookup_v2_desc_as_dir, 0, NULL, NULL }, + { "store_v2_desc_as_client", test_rend_cache_store_v2_desc_as_client, 0, NULL, NULL }, + { "store_v2_desc_as_client_with_different_time", test_rend_cache_store_v2_desc_as_client_with_different_time, 0, NULL, NULL }, + { "store_v2_desc_as_dir", test_rend_cache_store_v2_desc_as_dir, 0, NULL, NULL }, + { "store_v2_desc_as_dir_with_different_time", test_rend_cache_store_v2_desc_as_dir_with_different_time, 0, NULL, NULL }, + { "store_v2_desc_as_dir_with_different_content", test_rend_cache_store_v2_desc_as_dir_with_different_content, 0, NULL, NULL }, + { "validate_intro_point_failure", test_rend_cache_validate_intro_point_failure, 0, NULL, NULL }, + END_OF_TESTCASES +}; From 70de8d4bf86c430969bb314ba8590c00ce4dd374 Mon Sep 17 00:00:00 2001 From: Ola Bini Date: Mon, 5 Oct 2015 14:31:10 -0500 Subject: [PATCH 2/2] Fix spaces and other smaller issues --- src/or/rendcache.h | 20 ++- src/test/rend_test_helpers.c | 10 +- src/test/rend_test_helpers.h | 6 +- src/test/test_rendcache.c | 263 ++++++++++++++++++++++------------- 4 files changed, 193 insertions(+), 106 deletions(-) diff --git a/src/or/rendcache.h b/src/or/rendcache.h index 8ba1f6ffde..4f55240750 100644 --- a/src/or/rendcache.h +++ b/src/or/rendcache.h @@ -76,20 +76,28 @@ void rend_cache_intro_failure_note(rend_intro_point_failure_t failure, const char *service_id); void rend_cache_failure_purge(void); - #ifdef RENDCACHE_PRIVATE + STATIC size_t rend_cache_entry_allocation(const rend_cache_entry_t *e); STATIC void rend_cache_entry_free(rend_cache_entry_t *e); -STATIC void rend_cache_failure_intro_entry_free(rend_cache_failure_intro_t *entry); +STATIC void rend_cache_failure_intro_entry_free(rend_cache_failure_intro_t + *entry); STATIC void rend_cache_failure_entry_free(rend_cache_failure_t *entry); -STATIC int cache_failure_intro_lookup(const uint8_t *identity, const char *service_id, rend_cache_failure_intro_t **intro_entry); +STATIC int cache_failure_intro_lookup(const uint8_t *identity, + const char *service_id, + rend_cache_failure_intro_t + **intro_entry); STATIC void rend_cache_decrement_allocation(size_t n); STATIC void rend_cache_increment_allocation(size_t n); -STATIC rend_cache_failure_intro_t *rend_cache_failure_intro_entry_new(rend_intro_point_failure_t failure); +STATIC rend_cache_failure_intro_t *rend_cache_failure_intro_entry_new( + rend_intro_point_failure_t failure); STATIC rend_cache_failure_t *rend_cache_failure_entry_new(void); STATIC void rend_cache_failure_remove(rend_service_descriptor_t *desc); -STATIC void cache_failure_intro_add(const uint8_t *identity, const char *service_id, rend_intro_point_failure_t failure); -STATIC void validate_intro_point_failure(const rend_service_descriptor_t *desc, const char *service_id); +STATIC void cache_failure_intro_add(const uint8_t *identity, + const char *service_id, + rend_intro_point_failure_t failure); +STATIC void validate_intro_point_failure(const rend_service_descriptor_t *desc, + const char *service_id); #endif #endif /* TOR_RENDCACHE_H */ diff --git a/src/test/rend_test_helpers.c b/src/test/rend_test_helpers.c index 06e40a0153..615ef7bd38 100644 --- a/src/test/rend_test_helpers.c +++ b/src/test/rend_test_helpers.c @@ -5,7 +5,8 @@ /** TODO: Description */ void -generate_desc(int time_diff, rend_encoded_v2_service_descriptor_t **desc, char **service_id, int intro_points) +generate_desc(int time_diff, rend_encoded_v2_service_descriptor_t **desc, + char **service_id, int intro_points) { rend_service_descriptor_t *generated = NULL; smartlist_t *descs = smartlist_new(); @@ -15,17 +16,18 @@ generate_desc(int time_diff, rend_encoded_v2_service_descriptor_t **desc, char * create_descriptor(&generated, service_id, intro_points); generated->timestamp = now; - rend_encode_v2_descriptors(descs, generated, now, 0, REND_NO_AUTH, NULL, NULL); + rend_encode_v2_descriptors(descs, generated, now, 0, REND_NO_AUTH, NULL, + NULL); *desc = ((rend_encoded_v2_service_descriptor_t *)smartlist_get(descs, 0)); smartlist_free(descs); rend_service_descriptor_free(generated); } - /** TODO: Description */ void -create_descriptor(rend_service_descriptor_t **generated, char **service_id, int intro_points) +create_descriptor(rend_service_descriptor_t **generated, char **service_id, + int intro_points) { crypto_pk_t *pk1 = NULL; crypto_pk_t *pk2 = NULL; diff --git a/src/test/rend_test_helpers.h b/src/test/rend_test_helpers.h index 00a17be692..4305c1578b 100644 --- a/src/test/rend_test_helpers.h +++ b/src/test/rend_test_helpers.h @@ -6,7 +6,9 @@ #ifndef TOR_REND_TEST_HELPERS_H #define TOR_REND_TEST_HELPERS_H -void generate_desc(int time_diff, rend_encoded_v2_service_descriptor_t **desc, char **service_id, int intro_points); -void create_descriptor(rend_service_descriptor_t **generated, char **service_id, int intro_points); +void generate_desc(int time_diff, rend_encoded_v2_service_descriptor_t **desc, + char **service_id, int intro_points); +void create_descriptor(rend_service_descriptor_t **generated, + char **service_id, int intro_points); #endif diff --git a/src/test/test_rendcache.c b/src/test/test_rendcache.c index a005e66cb7..1213d548ac 100644 --- a/src/test/test_rendcache.c +++ b/src/test/test_rendcache.c @@ -16,7 +16,8 @@ #define NS_MODULE rend_cache static const int RECENT_TIME = -10; -static const int TIME_IN_THE_PAST = -(REND_CACHE_MAX_AGE + REND_CACHE_MAX_SKEW + 10); +static const int TIME_IN_THE_PAST = -(REND_CACHE_MAX_AGE + \ + REND_CACHE_MAX_SKEW + 10); static const int TIME_IN_THE_FUTURE = REND_CACHE_MAX_SKEW + 10; extern strmap_t *rend_cache; @@ -30,10 +31,12 @@ mock_rend_data(char *onion_address) rend_data_t rend_query; memset(&rend_query, 0, sizeof(rend_query)); - strncpy(rend_query.onion_address, onion_address, REND_SERVICE_ID_LEN_BASE32+1); + strncpy(rend_query.onion_address, onion_address, + REND_SERVICE_ID_LEN_BASE32+1); rend_query.auth_type = REND_NO_AUTH; rend_query.hsdirs_fp = smartlist_new(); - smartlist_add(rend_query.hsdirs_fp, tor_memdup("aaaaaaaaaaaaaaaaaaaaaaaa", DIGEST_LEN)); + smartlist_add(rend_query.hsdirs_fp, tor_memdup("aaaaaaaaaaaaaaaaaaaaaaaa", + DIGEST_LEN)); return rend_query; } @@ -53,7 +56,6 @@ test_rend_cache_lookup_entry(void *data) generate_desc(RECENT_TIME, &desc_holder, &service_id, 3); - ret = rend_cache_lookup_entry("abababababababab", 0, NULL); tt_int_op(ret, OP_EQ, -ENOENT); @@ -67,8 +69,10 @@ test_rend_cache_lookup_entry(void *data) tt_int_op(ret, OP_EQ, -ENOENT); mock_rend_query = mock_rend_data(service_id); - base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); - rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, &mock_rend_query, NULL); + base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, + DIGEST_LEN); + rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, + &mock_rend_query, NULL); ret = rend_cache_lookup_entry(service_id, 2, NULL); tt_int_op(ret, OP_EQ, 0); @@ -102,8 +106,11 @@ test_rend_cache_store_v2_desc_as_client(void *data) // Test success mock_rend_query = mock_rend_data(service_id); - base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); - ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, &mock_rend_query, &entry); + base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, + DIGEST_LEN); + ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, + desc_id_base32, &mock_rend_query, + &entry); tt_int_op(ret, OP_EQ, RCS_OKAY); tt_assert(entry); @@ -113,34 +120,45 @@ test_rend_cache_store_v2_desc_as_client(void *data) // Test various failure modes // TODO: a too long desc_id_base32 argument crashes the function - /* ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, "3TOOLONG3TOOLONG3TOOLONG3TOOLONG3TOOLONG3TOOLONG", &mock_rend_query, NULL); */ + /* ret = rend_cache_store_v2_desc_as_client( */ + /* desc_holder->desc_str, */ + /* "3TOOLONG3TOOLONG3TOOLONG3TOOLONG3TOOLONG3TOOLONG", */ + /* &mock_rend_query, NULL); */ /* tt_int_op(ret, OP_EQ, RCS_BADDESC); */ // Test bad base32 failure - // This causes an assertion failure if we're running with assertions. But when doing coverage, we can test it. + // This causes an assertion failure if we're running with assertions. + // But when doing coverage, we can test it. #ifdef TOR_COVERAGE - ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, "!xqunszqnaolrrfmtzgaki7mxelgvkj", &mock_rend_query, NULL); + ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, + "!xqunszqnaolrrfmtzgaki7mxelgvkj", &mock_rend_query, NULL); tt_int_op(ret, OP_EQ, RCS_BADDESC); #endif // Test invalid descriptor - ret = rend_cache_store_v2_desc_as_client("invalid descriptor", "3xqunszqnaolrrfmtzgaki7mxelgvkje", &mock_rend_query, NULL); + ret = rend_cache_store_v2_desc_as_client("invalid descriptor", + "3xqunszqnaolrrfmtzgaki7mxelgvkje", &mock_rend_query, NULL); tt_int_op(ret, OP_EQ, RCS_BADDESC); // TODO: it doesn't seem to be possible to test invalid service ID condition. - // that means it is likely not possible to have that condition without earlier conditions failing first (such as signature checking of the desc) + // that means it is likely not possible to have that condition without + // earlier conditions failing first (such as signature checking of the desc) // Test mismatch between service ID and onion address rend_cache_init(); strncpy(mock_rend_query.onion_address, "abc", REND_SERVICE_ID_LEN_BASE32+1); - ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, &mock_rend_query, NULL); + ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, + desc_id_base32, + &mock_rend_query, NULL); tt_int_op(ret, OP_EQ, RCS_BADDESC); // Test incorrect descriptor ID rend_cache_init(); mock_rend_query = mock_rend_data(service_id); desc_id_base32[0]++; - ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, &mock_rend_query, NULL); + ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, + desc_id_base32, &mock_rend_query, + NULL); tt_int_op(ret, OP_EQ, RCS_BADDESC); desc_id_base32[0]--; @@ -151,9 +169,12 @@ test_rend_cache_store_v2_desc_as_client(void *data) generate_desc(TIME_IN_THE_PAST, &desc_holder, &service_id, 3); mock_rend_query = mock_rend_data(service_id); - base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); + base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, + DIGEST_LEN); - ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, &mock_rend_query, NULL); + ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, + desc_id_base32, + &mock_rend_query, NULL); tt_int_op(ret, OP_EQ, RCS_BADDESC); // Test too new descriptor (in the future) @@ -163,9 +184,12 @@ test_rend_cache_store_v2_desc_as_client(void *data) generate_desc(TIME_IN_THE_FUTURE, &desc_holder, &service_id, 3); mock_rend_query = mock_rend_data(service_id); - base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); + base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, + DIGEST_LEN); - ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, &mock_rend_query, NULL); + ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, + desc_id_base32, &mock_rend_query, + NULL); tt_int_op(ret, OP_EQ, RCS_BADDESC); // Test when a descriptor is already in the cache @@ -176,13 +200,19 @@ test_rend_cache_store_v2_desc_as_client(void *data) generate_desc(RECENT_TIME, &desc_holder, &service_id, 3); mock_rend_query = mock_rend_data(service_id); - base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); + base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, + DIGEST_LEN); - rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, &mock_rend_query, NULL); - ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, &mock_rend_query, NULL); + rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, + &mock_rend_query, NULL); + ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, + desc_id_base32, &mock_rend_query, + NULL); tt_int_op(ret, OP_EQ, RCS_OKAY); - ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, &mock_rend_query, &entry); + ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, + desc_id_base32, &mock_rend_query, + &entry); tt_int_op(ret, OP_EQ, RCS_OKAY); tt_assert(entry); @@ -195,9 +225,13 @@ test_rend_cache_store_v2_desc_as_client(void *data) mock_rend_query = mock_rend_data(service_id); mock_rend_query.auth_type = REND_BASIC_AUTH; client_cookie[0] = 'A'; - memcpy(mock_rend_query.descriptor_cookie, client_cookie, REND_DESC_COOKIE_LEN); - base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); - ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, &mock_rend_query, NULL); + memcpy(mock_rend_query.descriptor_cookie, client_cookie, + REND_DESC_COOKIE_LEN); + base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, + DIGEST_LEN); + ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, + desc_id_base32, &mock_rend_query, + NULL); tt_int_op(ret, OP_EQ, RCS_OKAY); // Test successful run when we have REND_BASIC_AUTH but not cookie @@ -208,8 +242,11 @@ test_rend_cache_store_v2_desc_as_client(void *data) generate_desc(RECENT_TIME, &desc_holder, &service_id, 3); mock_rend_query = mock_rend_data(service_id); mock_rend_query.auth_type = REND_BASIC_AUTH; - base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); - ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, &mock_rend_query, NULL); + base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, + DIGEST_LEN); + ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, + desc_id_base32, &mock_rend_query, + NULL); tt_int_op(ret, OP_EQ, RCS_OKAY); // Test when we have no introduction points @@ -219,8 +256,11 @@ test_rend_cache_store_v2_desc_as_client(void *data) generate_desc(RECENT_TIME, &desc_holder, &service_id, 0); mock_rend_query = mock_rend_data(service_id); - base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); - ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, &mock_rend_query, NULL); + base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, + DIGEST_LEN); + ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, + desc_id_base32, &mock_rend_query, + NULL); tt_int_op(ret, OP_EQ, RCS_BADDESC); // Test when we have too many intro points @@ -230,8 +270,11 @@ test_rend_cache_store_v2_desc_as_client(void *data) generate_desc(RECENT_TIME, &desc_holder, &service_id, MAX_INTRO_POINTS+1); mock_rend_query = mock_rend_data(service_id); - base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); - ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, &mock_rend_query, NULL); + base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, + DIGEST_LEN); + ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, + desc_id_base32, &mock_rend_query, + NULL); tt_int_op(ret, OP_EQ, RCS_BADDESC); done: @@ -258,30 +301,42 @@ test_rend_cache_store_v2_desc_as_client_with_different_time(void *data) create_descriptor(&generated, &service_id, 3); generated->timestamp = t + RECENT_TIME; - rend_encode_v2_descriptors(descs, generated, t + RECENT_TIME, 0, REND_NO_AUTH, NULL, NULL); - desc_holder_newer = ((rend_encoded_v2_service_descriptor_t *)smartlist_get(descs, 0)); + rend_encode_v2_descriptors(descs, generated, t + RECENT_TIME, 0, + REND_NO_AUTH, NULL, NULL); + desc_holder_newer = ((rend_encoded_v2_service_descriptor_t *) + smartlist_get(descs, 0)); smartlist_free(descs); descs = smartlist_new(); generated->timestamp = (t + RECENT_TIME) - 20; - rend_encode_v2_descriptors(descs, generated, t + RECENT_TIME, 0, REND_NO_AUTH, NULL, NULL); - desc_holder_older = ((rend_encoded_v2_service_descriptor_t *)smartlist_get(descs, 0)); + rend_encode_v2_descriptors(descs, generated, t + RECENT_TIME, 0, + REND_NO_AUTH, NULL, NULL); + desc_holder_older = ((rend_encoded_v2_service_descriptor_t *) + smartlist_get(descs, 0)); (void)data; rend_cache_init(); - // Test when a descriptor is already in the cache and it is newer than the one we submit + // Test when a descriptor is already in the cache and it is newer than the + // one we submit mock_rend_query = mock_rend_data(service_id); - base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder_newer->desc_id, DIGEST_LEN); - rend_cache_store_v2_desc_as_client(desc_holder_newer->desc_str, desc_id_base32, &mock_rend_query, NULL); - ret = rend_cache_store_v2_desc_as_client(desc_holder_older->desc_str, desc_id_base32, &mock_rend_query, NULL); + base32_encode(desc_id_base32, sizeof(desc_id_base32), + desc_holder_newer->desc_id, DIGEST_LEN); + rend_cache_store_v2_desc_as_client(desc_holder_newer->desc_str, + desc_id_base32, &mock_rend_query, NULL); + ret = rend_cache_store_v2_desc_as_client(desc_holder_older->desc_str, + desc_id_base32, &mock_rend_query, + NULL); tt_int_op(ret, OP_EQ, RCS_OKAY); // Test when an old descriptor is in the cache and we submit a newer one rend_cache_init(); - rend_cache_store_v2_desc_as_client(desc_holder_older->desc_str, desc_id_base32, &mock_rend_query, NULL); - ret = rend_cache_store_v2_desc_as_client(desc_holder_newer->desc_str, desc_id_base32, &mock_rend_query, NULL); + rend_cache_store_v2_desc_as_client(desc_holder_older->desc_str, + desc_id_base32, &mock_rend_query, NULL); + ret = rend_cache_store_v2_desc_as_client(desc_holder_newer->desc_str, + desc_id_base32, &mock_rend_query, + NULL); tt_int_op(ret, OP_EQ, RCS_OKAY); done: @@ -292,7 +347,6 @@ test_rend_cache_store_v2_desc_as_client_with_different_time(void *data) tor_free(service_id); } - #define NS_SUBMODULE lookup_v2_desc_as_dir NS_DECL(const routerinfo_t *, router_get_my_routerinfo, (void)); NS_DECL(int, hid_serv_responsible_for_desc_id, (const char *id)); @@ -303,7 +357,7 @@ static int hid_serv_responsible_for_desc_id_response; static const routerinfo_t * NS(router_get_my_routerinfo)(void) { - if(!mock_routerinfo) { + if (!mock_routerinfo) { mock_routerinfo = tor_malloc(sizeof(routerinfo_t)); } @@ -313,6 +367,7 @@ NS(router_get_my_routerinfo)(void) static int NS(hid_serv_responsible_for_desc_id)(const char *id) { + (void)id; return hid_serv_responsible_for_desc_id_response; } @@ -337,14 +392,16 @@ test_rend_cache_lookup_v2_desc_as_dir(void *data) tt_int_op(ret, OP_EQ, -1); // Test non-existent descriptor but well formed - ret = rend_cache_lookup_v2_desc_as_dir("3xqunszqnaolrrfmtzgaki7mxelgvkje", NULL); + ret = rend_cache_lookup_v2_desc_as_dir("3xqunszqnaolrrfmtzgaki7mxelgvkje", + NULL); tt_int_op(ret, OP_EQ, 0); // Test existing descriptor hid_serv_responsible_for_desc_id_response = 1; generate_desc(RECENT_TIME, &desc_holder, &service_id, 3); rend_cache_store_v2_desc_as_dir(desc_holder->desc_str); - base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); + base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, + DIGEST_LEN); ret = rend_cache_lookup_v2_desc_as_dir(desc_id_base32, &ret_desc); tt_int_op(ret, OP_EQ, 1); tt_assert(ret_desc); @@ -361,9 +418,6 @@ test_rend_cache_lookup_v2_desc_as_dir(void *data) NS_DECL(const routerinfo_t *, router_get_my_routerinfo, (void)); NS_DECL(int, hid_serv_responsible_for_desc_id, (const char *id)); -static routerinfo_t *mock_routerinfo; -static int hid_serv_responsible_for_desc_id_response; - static const routerinfo_t * NS(router_get_my_routerinfo)(void) { @@ -373,6 +427,7 @@ NS(router_get_my_routerinfo)(void) static int NS(hid_serv_responsible_for_desc_id)(const char *id) { + (void)id; return hid_serv_responsible_for_desc_id_response; } @@ -458,15 +513,19 @@ test_rend_cache_store_v2_desc_as_dir_with_different_time(void *data) create_descriptor(&generated, &service_id, 3); generated->timestamp = t + RECENT_TIME; - rend_encode_v2_descriptors(descs, generated, t + RECENT_TIME, 0, REND_NO_AUTH, NULL, NULL); - desc_holder_newer = ((rend_encoded_v2_service_descriptor_t *)smartlist_get(descs, 0)); + rend_encode_v2_descriptors(descs, generated, t + RECENT_TIME, 0, + REND_NO_AUTH, NULL, NULL); + desc_holder_newer = ((rend_encoded_v2_service_descriptor_t *) + smartlist_get(descs, 0)); smartlist_free(descs); descs = smartlist_new(); generated->timestamp = (t + RECENT_TIME) - 20; - rend_encode_v2_descriptors(descs, generated, t + RECENT_TIME, 0, REND_NO_AUTH, NULL, NULL); - desc_holder_older = ((rend_encoded_v2_service_descriptor_t *)smartlist_get(descs, 0)); + rend_encode_v2_descriptors(descs, generated, t + RECENT_TIME, 0, + REND_NO_AUTH, NULL, NULL); + desc_holder_older = ((rend_encoded_v2_service_descriptor_t *) + smartlist_get(descs, 0)); // Test when we have a newer descriptor stored mock_routerinfo = tor_malloc(sizeof(routerinfo_t)); @@ -508,16 +567,20 @@ test_rend_cache_store_v2_desc_as_dir_with_different_content(void *data) create_descriptor(&generated, &service_id, 3); generated->timestamp = t + RECENT_TIME; - rend_encode_v2_descriptors(descs, generated, t + RECENT_TIME, 0, REND_NO_AUTH, NULL, NULL); - desc_holder_one = ((rend_encoded_v2_service_descriptor_t *)smartlist_get(descs, 0)); + rend_encode_v2_descriptors(descs, generated, t + RECENT_TIME, 0, + REND_NO_AUTH, NULL, NULL); + desc_holder_one = ((rend_encoded_v2_service_descriptor_t *) + smartlist_get(descs, 0)); smartlist_free(descs); descs = smartlist_new(); generated->timestamp = t + RECENT_TIME; generated->protocols = 41; - rend_encode_v2_descriptors(descs, generated, t + RECENT_TIME, 0, REND_NO_AUTH, NULL, NULL); - desc_holder_two = ((rend_encoded_v2_service_descriptor_t *)smartlist_get(descs, 0)); + rend_encode_v2_descriptors(descs, generated, t + RECENT_TIME, 0, + REND_NO_AUTH, NULL, NULL); + desc_holder_two = ((rend_encoded_v2_service_descriptor_t *) + smartlist_get(descs, 0)); // Test when we have another descriptor stored, with a different descriptor mock_routerinfo = tor_malloc(sizeof(routerinfo_t)); @@ -531,7 +594,6 @@ test_rend_cache_store_v2_desc_as_dir_with_different_content(void *data) NS_UNMOCK(hid_serv_responsible_for_desc_id); } - #undef NS_SUBMODULE static void @@ -540,14 +602,18 @@ test_rend_cache_init(void *data) (void)data; tt_assert_msg(!rend_cache, "rend_cache should be NULL when starting"); - tt_assert_msg(!rend_cache_v2_dir, "rend_cache_v2_dir should be NULL when starting"); - tt_assert_msg(!rend_cache_failure, "rend_cache_failure should be NULL when starting"); + tt_assert_msg(!rend_cache_v2_dir, "rend_cache_v2_dir should be NULL " + "when starting"); + tt_assert_msg(!rend_cache_failure, "rend_cache_failure should be NULL when " + "starting"); rend_cache_init(); tt_assert_msg(rend_cache, "rend_cache should not be NULL after initing"); - tt_assert_msg(rend_cache_v2_dir, "rend_cache_v2_dir should not be NULL after initing"); - tt_assert_msg(rend_cache_failure, "rend_cache_failure should not be NULL after initing"); + tt_assert_msg(rend_cache_v2_dir, "rend_cache_v2_dir should not be NULL " + "after initing"); + tt_assert_msg(rend_cache_failure, "rend_cache_failure should not be NULL " + "after initing"); tt_int_op(strmap_size(rend_cache), OP_EQ, 0); tt_int_op(digestmap_size(rend_cache_v2_dir), OP_EQ, 0); @@ -603,7 +669,6 @@ test_rend_cache_increment_allocation(void *data) (void)0; } - static void test_rend_cache_failure_intro_entry_new(void *data) { @@ -790,7 +855,6 @@ test_rend_cache_failure_clean(void *data) rend_cache_failure_clean(time(NULL)); tt_int_op(strmap_size(rend_cache_failure), OP_EQ, 0); - // Test with one old intro point and one new one rend_cache_failure_purge(); failure = rend_cache_failure_entry_new(); @@ -809,7 +873,6 @@ test_rend_cache_failure_clean(void *data) (void)0; } - static void test_rend_cache_failure_remove(void *data) { @@ -826,7 +889,8 @@ test_rend_cache_failure_remove(void *data) desc->pk = pk_generate(0); rend_cache_failure_remove(desc); - // There seems to not exist any way of getting rend_cache_failure_remove() to fail because of a problem with rend_get_service_id from here + // There seems to not exist any way of getting rend_cache_failure_remove() + // to fail because of a problem with rend_get_service_id from here /* done: */ /* (void)0; */ @@ -864,7 +928,6 @@ test_rend_cache_free_all(void *data) (void)0; } - static void test_rend_cache_entry_free(void *data) { @@ -887,7 +950,6 @@ test_rend_cache_entry_free(void *data) /* (void)0; */ } - static void test_rend_cache_purge(void *data) { @@ -922,7 +984,8 @@ test_rend_cache_failure_intro_add(void *data) rend_cache_init(); // Adds non-existing entry - cache_failure_intro_add((const uint8_t *)"foo1", "foo2", INTRO_POINT_FAILURE_TIMEOUT); + cache_failure_intro_add((const uint8_t *)"foo1", "foo2", + INTRO_POINT_FAILURE_TIMEOUT); fail_entry = strmap_get_lc(rend_cache_failure, "foo2"); tt_assert(fail_entry); tt_int_op(digestmap_size(fail_entry->intro_failures), OP_EQ, 1); @@ -930,7 +993,8 @@ test_rend_cache_failure_intro_add(void *data) tt_assert(entry); // Adds existing entry - cache_failure_intro_add((const uint8_t *)"foo1", "foo2", INTRO_POINT_FAILURE_TIMEOUT); + cache_failure_intro_add((const uint8_t *)"foo1", "foo2", + INTRO_POINT_FAILURE_TIMEOUT); fail_entry = strmap_get_lc(rend_cache_failure, "foo2"); tt_assert(fail_entry); tt_int_op(digestmap_size(fail_entry->intro_failures), OP_EQ, 1); @@ -941,7 +1005,6 @@ test_rend_cache_failure_intro_add(void *data) rend_cache_purge(); } - static void test_rend_cache_intro_failure_note(void *data) { @@ -950,7 +1013,8 @@ test_rend_cache_intro_failure_note(void *data) rend_cache_failure_intro_t *entry; // Test not found - rend_cache_intro_failure_note(INTRO_POINT_FAILURE_TIMEOUT,(const uint8_t *)"foo1", "foo2"); + rend_cache_intro_failure_note(INTRO_POINT_FAILURE_TIMEOUT, + (const uint8_t *)"foo1", "foo2"); fail_entry = strmap_get_lc(rend_cache_failure, "foo2"); tt_assert(fail_entry); tt_int_op(digestmap_size(fail_entry->intro_failures), OP_EQ, 1); @@ -959,7 +1023,8 @@ test_rend_cache_intro_failure_note(void *data) tt_int_op(entry->failure_type, OP_EQ, INTRO_POINT_FAILURE_TIMEOUT); // Test found - rend_cache_intro_failure_note(INTRO_POINT_FAILURE_UNREACHABLE,(const uint8_t *)"foo1", "foo2"); + rend_cache_intro_failure_note(INTRO_POINT_FAILURE_UNREACHABLE, + (const uint8_t *)"foo1", "foo2"); tt_int_op(entry->failure_type, OP_EQ, INTRO_POINT_FAILURE_UNREACHABLE); done: @@ -969,15 +1034,13 @@ test_rend_cache_intro_failure_note(void *data) #define NS_SUBMODULE clean_v2_descs_as_dir NS_DECL(int, hid_serv_responsible_for_desc_id, (const char *id)); -static int hid_serv_responsible_for_desc_id_response; - static int NS(hid_serv_responsible_for_desc_id)(const char *id) { + (void)id; return hid_serv_responsible_for_desc_id_response; } - static void test_rend_cache_clean_v2_descs_as_dir(void *data) { @@ -1013,7 +1076,8 @@ test_rend_cache_clean_v2_descs_as_dir(void *data) rend_cache_clean_v2_descs_as_dir(now, 0); tt_int_op(digestmap_size(rend_cache_v2_dir), OP_EQ, 0); - // Test with one entry that is not under the responsibility of this hidden service + // Test with one entry that is not under the responsibility of this + // hidden service e = tor_malloc_zero(sizeof(rend_cache_entry_t)); e->last_served = now; desc = tor_malloc_zero(sizeof(rend_service_descriptor_t)); @@ -1052,8 +1116,6 @@ test_rend_cache_clean_v2_descs_as_dir(void *data) rend_cache_clean_v2_descs_as_dir(now, 20000); tt_int_op(digestmap_size(rend_cache_v2_dir), OP_EQ, 1); - - done: NS_UNMOCK(hid_serv_responsible_for_desc_id); rend_cache_purge(); @@ -1061,7 +1123,6 @@ test_rend_cache_clean_v2_descs_as_dir(void *data) #undef NS_SUBMODULE - static void test_rend_cache_entry_allocation(void *data) { @@ -1097,7 +1158,6 @@ test_rend_cache_failure_intro_entry_free(void *data) rend_cache_failure_intro_entry_free(entry); } - static void test_rend_cache_failure_purge(void *data) { @@ -1148,31 +1208,46 @@ test_rend_cache_validate_intro_point_failure(void *data) struct testcase_t rend_cache_tests[] = { { "init", test_rend_cache_init, 0, NULL, NULL }, - { "decrement_allocation", test_rend_cache_decrement_allocation, 0, NULL, NULL }, - { "increment_allocation", test_rend_cache_increment_allocation, 0, NULL, NULL }, + { "decrement_allocation", test_rend_cache_decrement_allocation, 0, + NULL, NULL }, + { "increment_allocation", test_rend_cache_increment_allocation, 0, + NULL, NULL }, { "clean", test_rend_cache_clean, TT_FORK, NULL, NULL }, - { "clean_v2_descs_as_dir", test_rend_cache_clean_v2_descs_as_dir, 0, NULL, NULL }, + { "clean_v2_descs_as_dir", test_rend_cache_clean_v2_descs_as_dir, 0, + NULL, NULL }, { "entry_allocation", test_rend_cache_entry_allocation, 0, NULL, NULL }, { "entry_free", test_rend_cache_entry_free, 0, NULL, NULL }, - { "failure_intro_entry_free", test_rend_cache_failure_intro_entry_free, 0, NULL, NULL }, + { "failure_intro_entry_free", test_rend_cache_failure_intro_entry_free, 0, + NULL, NULL }, { "free_all", test_rend_cache_free_all, 0, NULL, NULL }, { "purge", test_rend_cache_purge, 0, NULL, NULL }, { "failure_clean", test_rend_cache_failure_clean, 0, NULL, NULL }, { "failure_entry_new", test_rend_cache_failure_entry_new, 0, NULL, NULL }, { "failure_entry_free", test_rend_cache_failure_entry_free, 0, NULL, NULL }, { "failure_intro_add", test_rend_cache_failure_intro_add, 0, NULL, NULL }, - { "failure_intro_entry_new", test_rend_cache_failure_intro_entry_new, 0, NULL, NULL }, - { "failure_intro_lookup", test_rend_cache_failure_intro_lookup, 0, NULL, NULL }, + { "failure_intro_entry_new", test_rend_cache_failure_intro_entry_new, 0, + NULL, NULL }, + { "failure_intro_lookup", test_rend_cache_failure_intro_lookup, 0, + NULL, NULL }, { "failure_purge", test_rend_cache_failure_purge, 0, NULL, NULL }, { "failure_remove", test_rend_cache_failure_remove, 0, NULL, NULL }, { "intro_failure_note", test_rend_cache_intro_failure_note, 0, NULL, NULL }, { "lookup", test_rend_cache_lookup_entry, 0, NULL, NULL }, - { "lookup_v2_desc_as_dir", test_rend_cache_lookup_v2_desc_as_dir, 0, NULL, NULL }, - { "store_v2_desc_as_client", test_rend_cache_store_v2_desc_as_client, 0, NULL, NULL }, - { "store_v2_desc_as_client_with_different_time", test_rend_cache_store_v2_desc_as_client_with_different_time, 0, NULL, NULL }, - { "store_v2_desc_as_dir", test_rend_cache_store_v2_desc_as_dir, 0, NULL, NULL }, - { "store_v2_desc_as_dir_with_different_time", test_rend_cache_store_v2_desc_as_dir_with_different_time, 0, NULL, NULL }, - { "store_v2_desc_as_dir_with_different_content", test_rend_cache_store_v2_desc_as_dir_with_different_content, 0, NULL, NULL }, - { "validate_intro_point_failure", test_rend_cache_validate_intro_point_failure, 0, NULL, NULL }, + { "lookup_v2_desc_as_dir", test_rend_cache_lookup_v2_desc_as_dir, 0, + NULL, NULL }, + { "store_v2_desc_as_client", test_rend_cache_store_v2_desc_as_client, 0, + NULL, NULL }, + { "store_v2_desc_as_client_with_different_time", + test_rend_cache_store_v2_desc_as_client_with_different_time, 0, + NULL, NULL }, + { "store_v2_desc_as_dir", test_rend_cache_store_v2_desc_as_dir, 0, + NULL, NULL }, + { "store_v2_desc_as_dir_with_different_time", + test_rend_cache_store_v2_desc_as_dir_with_different_time, 0, NULL, NULL }, + { "store_v2_desc_as_dir_with_different_content", + test_rend_cache_store_v2_desc_as_dir_with_different_content, 0, + NULL, NULL }, + { "validate_intro_point_failure", + test_rend_cache_validate_intro_point_failure, 0, NULL, NULL }, END_OF_TESTCASES };