From d5e860e3dca8cd9159e17555541262c828d05976 Mon Sep 17 00:00:00 2001 From: Reinaldo de Souza Jr Date: Mon, 7 Sep 2015 14:04:51 -0500 Subject: [PATCH] Add tests for src/or/directory.c --- src/or/directory.c | 28 ++-- src/or/directory.h | 24 ++- src/test/test_dir.c | 348 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 372 insertions(+), 28 deletions(-) diff --git a/src/or/directory.c b/src/or/directory.c index 9461606f1b..01ed69452a 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -143,7 +143,7 @@ purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose) /** Return a newly allocated string describing auth. Only describes * authority features. */ -static char * +STATIC char * authdir_type_to_string(dirinfo_type_t auth) { char *result; @@ -162,7 +162,7 @@ authdir_type_to_string(dirinfo_type_t auth) } /** Return a string describing a given directory connection purpose. */ -static const char * +STATIC const char * dir_conn_purpose_to_string(int purpose) { switch (purpose) @@ -370,7 +370,7 @@ directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose, /** Return true iff, according to the values in options, we should be * using directory guards for direct downloads of directory information. */ -static int +STATIC int should_use_directory_guards(const or_options_t *options) { /* Public (non-bridge) servers never use directory guards. */ @@ -666,15 +666,15 @@ directory_initiate_command_routerstatus_rend(const routerstatus_t *status, * When fetching a rendezvous descriptor, resource is the service ID we * want to fetch. */ -void -directory_initiate_command_routerstatus(const routerstatus_t *status, - uint8_t dir_purpose, - uint8_t router_purpose, - dir_indirection_t indirection, - const char *resource, - const char *payload, - size_t payload_len, - time_t if_modified_since) +MOCK_IMPL(void, directory_initiate_command_routerstatus, + (const routerstatus_t *status, + uint8_t dir_purpose, + uint8_t router_purpose, + dir_indirection_t indirection, + const char *resource, + const char *payload, + size_t payload_len, + time_t if_modified_since)) { directory_initiate_command_routerstatus_rend(status, dir_purpose, router_purpose, @@ -2593,7 +2593,7 @@ client_likes_consensus(networkstatus_t *v, const char *want_url) /** Return the compression level we should use for sending a compressed * response of size n_bytes. */ -static zlib_compression_level_t +STATIC zlib_compression_level_t choose_compression_level(ssize_t n_bytes) { if (! have_been_under_memory_pressure()) { @@ -3460,7 +3460,7 @@ connection_dir_finished_connecting(dir_connection_t *conn) * then return a list of int pointers defining download delays in seconds. * Helper function for download_status_increment_failure() and * download_status_reset(). */ -static const smartlist_t * +STATIC const smartlist_t * find_dl_schedule_and_len(download_status_t *dls, int server) { switch (dls->schedule) { diff --git a/src/or/directory.h b/src/or/directory.h index 4899eb5c8c..d859df3061 100644 --- a/src/or/directory.h +++ b/src/or/directory.h @@ -37,14 +37,16 @@ typedef enum { DIRIND_ANON_DIRPORT, } dir_indirection_t; -void directory_initiate_command_routerstatus(const routerstatus_t *status, - uint8_t dir_purpose, - uint8_t router_purpose, - dir_indirection_t indirection, - const char *resource, - const char *payload, - size_t payload_len, - time_t if_modified_since); +MOCK_DECL(void, directory_initiate_command_routerstatus, + (const routerstatus_t *status, + uint8_t dir_purpose, + uint8_t router_purpose, + dir_indirection_t indirection, + const char *resource, + const char *payload, + size_t payload_len, + time_t if_modified_since)); + void directory_initiate_command_routerstatus_rend(const routerstatus_t *status, uint8_t dir_purpose, uint8_t router_purpose, @@ -127,6 +129,12 @@ STATIC int purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose); STATIC dirinfo_type_t dir_fetch_type(int dir_purpose, int router_purpose, const char *resource); +STATIC char* authdir_type_to_string(dirinfo_type_t auth); +STATIC const char * dir_conn_purpose_to_string(int purpose); +STATIC int should_use_directory_guards(const or_options_t *options); +STATIC zlib_compression_level_t choose_compression_level(ssize_t n_bytes); +STATIC const smartlist_t * find_dl_schedule_and_len(download_status_t *dls, + int server); #endif #endif diff --git a/src/test/test_dir.c b/src/test/test_dir.c index 855746e749..9be7e0de6b 100644 --- a/src/test/test_dir.c +++ b/src/test/test_dir.c @@ -12,6 +12,8 @@ #define ROUTERLIST_PRIVATE #define HIBERNATE_PRIVATE #define NETWORKSTATUS_PRIVATE +#define RELAY_PRIVATE + #include "or.h" #include "config.h" #include "crypto_ed25519.h" @@ -27,6 +29,9 @@ #include "routerset.h" #include "test.h" #include "torcert.h" +#include "relay.h" + +#define NS_MODULE dir static void test_dir_nicknames(void *arg) @@ -3340,12 +3345,33 @@ static void test_dir_fetch_type(void *arg) { (void)arg; - tt_assert(dir_fetch_type(DIR_PURPOSE_FETCH_MICRODESC, ROUTER_PURPOSE_GENERAL, - NULL) == MICRODESC_DIRINFO); - tt_assert(dir_fetch_type(DIR_PURPOSE_FETCH_SERVERDESC, ROUTER_PURPOSE_BRIDGE, - NULL) == BRIDGE_DIRINFO); - tt_assert(dir_fetch_type(DIR_PURPOSE_FETCH_CONSENSUS, ROUTER_PURPOSE_GENERAL, - "microdesc") == (V3_DIRINFO | MICRODESC_DIRINFO)); + tt_int_op(dir_fetch_type(DIR_PURPOSE_FETCH_EXTRAINFO, ROUTER_PURPOSE_BRIDGE, + NULL), OP_EQ, EXTRAINFO_DIRINFO | BRIDGE_DIRINFO); + tt_int_op(dir_fetch_type(DIR_PURPOSE_FETCH_EXTRAINFO, ROUTER_PURPOSE_GENERAL, + NULL), OP_EQ, EXTRAINFO_DIRINFO | V3_DIRINFO); + + tt_int_op(dir_fetch_type(DIR_PURPOSE_FETCH_SERVERDESC, ROUTER_PURPOSE_BRIDGE, + NULL), OP_EQ, BRIDGE_DIRINFO); + tt_int_op(dir_fetch_type(DIR_PURPOSE_FETCH_SERVERDESC, + ROUTER_PURPOSE_GENERAL, NULL), OP_EQ, V3_DIRINFO); + + tt_int_op(dir_fetch_type(DIR_PURPOSE_FETCH_STATUS_VOTE, + ROUTER_PURPOSE_GENERAL, NULL), OP_EQ, V3_DIRINFO); + tt_int_op(dir_fetch_type(DIR_PURPOSE_FETCH_DETACHED_SIGNATURES, + ROUTER_PURPOSE_GENERAL, NULL), OP_EQ, V3_DIRINFO); + tt_int_op(dir_fetch_type(DIR_PURPOSE_FETCH_CERTIFICATE, + ROUTER_PURPOSE_GENERAL, NULL), OP_EQ, V3_DIRINFO); + + tt_int_op(dir_fetch_type(DIR_PURPOSE_FETCH_CONSENSUS, ROUTER_PURPOSE_GENERAL, + "microdesc"), OP_EQ, V3_DIRINFO|MICRODESC_DIRINFO); + tt_int_op(dir_fetch_type(DIR_PURPOSE_FETCH_CONSENSUS, ROUTER_PURPOSE_GENERAL, + NULL), OP_EQ, V3_DIRINFO); + + tt_int_op(dir_fetch_type(DIR_PURPOSE_FETCH_MICRODESC, ROUTER_PURPOSE_GENERAL, + NULL), OP_EQ, MICRODESC_DIRINFO); + + tt_int_op(dir_fetch_type(DIR_PURPOSE_FETCH_RENDDESC_V2, + ROUTER_PURPOSE_GENERAL, NULL), OP_EQ, NO_DIRINFO); done: ; } @@ -3494,6 +3520,308 @@ test_dir_packages(void *arg) tor_free(res); } +static void +test_dir_authdir_type_to_string(void *data) +{ + (void)data; + + tt_str_op(authdir_type_to_string(NO_DIRINFO), OP_EQ, + "[Not an authority]"); + tt_str_op(authdir_type_to_string(EXTRAINFO_DIRINFO), OP_EQ, + "[Not an authority]"); + tt_str_op(authdir_type_to_string(MICRODESC_DIRINFO), OP_EQ, + "[Not an authority]"); + + tt_str_op(authdir_type_to_string(V3_DIRINFO), OP_EQ, "V3"); + tt_str_op(authdir_type_to_string(BRIDGE_DIRINFO), OP_EQ, "Bridge"); + tt_str_op(authdir_type_to_string( + V3_DIRINFO | BRIDGE_DIRINFO | EXTRAINFO_DIRINFO), OP_EQ, + "V3, Bridge"); + done: ; +} + +static void +test_dir_conn_purpose_to_string(void *data) +{ + (void)data; + +#define EXPECT_CONN_PURPOSE(purpose, expected) \ + tt_str_op(dir_conn_purpose_to_string(purpose), OP_EQ, expected); + + EXPECT_CONN_PURPOSE(DIR_PURPOSE_UPLOAD_DIR, "server descriptor upload"); + EXPECT_CONN_PURPOSE(DIR_PURPOSE_UPLOAD_VOTE, "server vote upload"); + EXPECT_CONN_PURPOSE(DIR_PURPOSE_UPLOAD_SIGNATURES, + "consensus signature upload"); + EXPECT_CONN_PURPOSE(DIR_PURPOSE_FETCH_SERVERDESC, "server descriptor fetch"); + EXPECT_CONN_PURPOSE(DIR_PURPOSE_FETCH_EXTRAINFO, "extra-info fetch"); + EXPECT_CONN_PURPOSE(DIR_PURPOSE_FETCH_CONSENSUS, + "consensus network-status fetch"); + EXPECT_CONN_PURPOSE(DIR_PURPOSE_FETCH_CERTIFICATE, "authority cert fetch"); + EXPECT_CONN_PURPOSE(DIR_PURPOSE_FETCH_STATUS_VOTE, "status vote fetch"); + EXPECT_CONN_PURPOSE(DIR_PURPOSE_FETCH_DETACHED_SIGNATURES, + "consensus signature fetch"); + EXPECT_CONN_PURPOSE(DIR_PURPOSE_FETCH_RENDDESC_V2, + "hidden-service v2 descriptor fetch"); + EXPECT_CONN_PURPOSE(DIR_PURPOSE_UPLOAD_RENDDESC_V2, + "hidden-service v2 descriptor upload"); + EXPECT_CONN_PURPOSE(DIR_PURPOSE_FETCH_MICRODESC, "microdescriptor fetch"); + EXPECT_CONN_PURPOSE(1024, "(unknown)"); + + done: ; +} + +NS_DECL(int, +public_server_mode, (const or_options_t *options)); + +static int +NS(public_server_mode)(const or_options_t *options) +{ + (void)options; + + if (CALLED(public_server_mode)++ == 0) { + return 1; + } + + return 0; +} + +static void +test_dir_should_use_directory_guards(void *data) +{ + or_options_t *options; + char *errmsg = NULL; + (void)data; + + NS_MOCK(public_server_mode); + + options = options_new(); + options_init(options); + + tt_int_op(should_use_directory_guards(options), OP_EQ, 0); + tt_int_op(CALLED(public_server_mode), OP_EQ, 1); + + options->UseEntryGuardsAsDirGuards = 1; + options->UseEntryGuards = 1; + options->DownloadExtraInfo = 0; + options->FetchDirInfoEarly = 0; + options->FetchDirInfoExtraEarly = 0; + options->FetchUselessDescriptors = 0; + tt_int_op(should_use_directory_guards(options), OP_EQ, 1); + tt_int_op(CALLED(public_server_mode), OP_EQ, 2); + + options->UseEntryGuards = 0; + tt_int_op(should_use_directory_guards(options), OP_EQ, 0); + tt_int_op(CALLED(public_server_mode), OP_EQ, 3); + options->UseEntryGuards = 1; + + options->UseEntryGuardsAsDirGuards = 0; + tt_int_op(should_use_directory_guards(options), OP_EQ, 0); + tt_int_op(CALLED(public_server_mode), OP_EQ, 4); + options->UseEntryGuardsAsDirGuards = 1; + + options->DownloadExtraInfo = 1; + tt_int_op(should_use_directory_guards(options), OP_EQ, 0); + tt_int_op(CALLED(public_server_mode), OP_EQ, 5); + options->DownloadExtraInfo = 0; + + options->FetchDirInfoEarly = 1; + tt_int_op(should_use_directory_guards(options), OP_EQ, 0); + tt_int_op(CALLED(public_server_mode), OP_EQ, 6); + options->FetchDirInfoEarly = 0; + + options->FetchDirInfoExtraEarly = 1; + tt_int_op(should_use_directory_guards(options), OP_EQ, 0); + tt_int_op(CALLED(public_server_mode), OP_EQ, 7); + options->FetchDirInfoExtraEarly = 0; + + options->FetchUselessDescriptors = 1; + tt_int_op(should_use_directory_guards(options), OP_EQ, 0); + tt_int_op(CALLED(public_server_mode), OP_EQ, 8); + options->FetchUselessDescriptors = 0; + + done: + NS_UNMOCK(public_server_mode); + tor_free(options); + tor_free(errmsg); +} + +NS_DECL(void, +directory_initiate_command_routerstatus, (const routerstatus_t *status, + uint8_t dir_purpose, + uint8_t router_purpose, + dir_indirection_t indirection, + const char *resource, + const char *payload, + size_t payload_len, + time_t if_modified_since)); + +static void +test_dir_should_not_init_request_to_ourselves(void *data) +{ + char digest[DIGEST_LEN]; + dir_server_t *ourself = NULL; + crypto_pk_t *key = pk_generate(2); + (void) data; + + NS_MOCK(directory_initiate_command_routerstatus); + + clear_dir_servers(); + routerlist_free_all(); + + set_server_identity_key(key); + crypto_pk_get_digest(key, (char*) &digest); + ourself = trusted_dir_server_new("ourself", "127.0.0.1", 9059, 9060, digest, + NULL, V3_DIRINFO, 1.0); + + tt_assert(ourself); + dir_server_add(ourself); + + directory_get_from_all_authorities(DIR_PURPOSE_FETCH_STATUS_VOTE, 0, NULL); + tt_int_op(CALLED(directory_initiate_command_routerstatus), OP_EQ, 0); + + directory_get_from_all_authorities(DIR_PURPOSE_FETCH_DETACHED_SIGNATURES, 0, + NULL); + + tt_int_op(CALLED(directory_initiate_command_routerstatus), OP_EQ, 0); + + done: + NS_UNMOCK(directory_initiate_command_routerstatus); + clear_dir_servers(); + routerlist_free_all(); + crypto_pk_free(key); +} + +static void +test_dir_should_not_init_request_to_dir_auths_without_v3_info(void *data) +{ + dir_server_t *ds = NULL; + dirinfo_type_t dirinfo_type = BRIDGE_DIRINFO | EXTRAINFO_DIRINFO \ + | MICRODESC_DIRINFO; + (void) data; + + NS_MOCK(directory_initiate_command_routerstatus); + + clear_dir_servers(); + routerlist_free_all(); + + ds = trusted_dir_server_new("ds", "10.0.0.1", 9059, 9060, + "12345678901234567890", NULL, dirinfo_type, 1.0); + tt_assert(ds); + dir_server_add(ds); + + directory_get_from_all_authorities(DIR_PURPOSE_FETCH_STATUS_VOTE, 0, NULL); + tt_int_op(CALLED(directory_initiate_command_routerstatus), OP_EQ, 0); + + directory_get_from_all_authorities(DIR_PURPOSE_FETCH_DETACHED_SIGNATURES, 0, + NULL); + tt_int_op(CALLED(directory_initiate_command_routerstatus), OP_EQ, 0); + + done: + NS_UNMOCK(directory_initiate_command_routerstatus); + clear_dir_servers(); + routerlist_free_all(); +} + +static void +test_dir_should_init_request_to_dir_auths(void *data) +{ + dir_server_t *ds = NULL; + (void) data; + + NS_MOCK(directory_initiate_command_routerstatus); + + clear_dir_servers(); + routerlist_free_all(); + + ds = trusted_dir_server_new("ds", "10.0.0.1", 9059, 9060, + "12345678901234567890", NULL, V3_DIRINFO, 1.0); + tt_assert(ds); + dir_server_add(ds); + + directory_get_from_all_authorities(DIR_PURPOSE_FETCH_STATUS_VOTE, 0, NULL); + tt_int_op(CALLED(directory_initiate_command_routerstatus), OP_EQ, 1); + + directory_get_from_all_authorities(DIR_PURPOSE_FETCH_DETACHED_SIGNATURES, 0, + NULL); + tt_int_op(CALLED(directory_initiate_command_routerstatus), OP_EQ, 2); + + done: + NS_UNMOCK(directory_initiate_command_routerstatus); + clear_dir_servers(); + routerlist_free_all(); +} + +void +NS(directory_initiate_command_routerstatus)(const routerstatus_t *status, + uint8_t dir_purpose, + uint8_t router_purpose, + dir_indirection_t indirection, + const char *resource, + const char *payload, + size_t payload_len, + time_t if_modified_since) +{ + CALLED(directory_initiate_command_routerstatus)++; +} + +static void +test_dir_choose_compression_level(void* data) +{ + (void)data; + + /* It starts under_memory_pressure */ + tt_int_op(have_been_under_memory_pressure(), OP_EQ, 1); + + tt_assert(HIGH_COMPRESSION == choose_compression_level(-1)); + tt_assert(LOW_COMPRESSION == choose_compression_level(1024-1)); + tt_assert(MEDIUM_COMPRESSION == choose_compression_level(2048-1)); + tt_assert(HIGH_COMPRESSION == choose_compression_level(2048)); + + /* Reset under_memory_pressure timer */ + cell_queues_check_size(); + tt_int_op(have_been_under_memory_pressure(), OP_EQ, 0); + + tt_assert(HIGH_COMPRESSION == choose_compression_level(-1)); + tt_assert(HIGH_COMPRESSION == choose_compression_level(1024-1)); + tt_assert(HIGH_COMPRESSION == choose_compression_level(2048-1)); + tt_assert(HIGH_COMPRESSION == choose_compression_level(2048)); + + done: ; +} + +static void +test_dir_find_dl_schedule_and_len(void* data) +{ + download_status_t dls; + smartlist_t server, client, server_cons, client_cons, bridge; + (void)data; + + mock_options = malloc(sizeof(or_options_t)); + reset_options(mock_options, &mock_get_options_calls); + MOCK(get_options, mock_get_options); + + mock_options->TestingServerDownloadSchedule = &server; + mock_options->TestingClientDownloadSchedule = &client; + mock_options->TestingServerConsensusDownloadSchedule = &server_cons; + mock_options->TestingClientConsensusDownloadSchedule = &client_cons; + mock_options->TestingBridgeDownloadSchedule = &bridge; + + dls.schedule = DL_SCHED_GENERIC; + tt_ptr_op(find_dl_schedule_and_len(&dls, 0), OP_EQ, &client); + tt_ptr_op(find_dl_schedule_and_len(&dls, 1), OP_EQ, &server); + + dls.schedule = DL_SCHED_CONSENSUS; + tt_ptr_op(find_dl_schedule_and_len(&dls, 0), OP_EQ, &client_cons); + tt_ptr_op(find_dl_schedule_and_len(&dls, 1), OP_EQ, &server_cons); + + dls.schedule = DL_SCHED_BRIDGE; + tt_ptr_op(find_dl_schedule_and_len(&dls, 0), OP_EQ, &bridge); + tt_ptr_op(find_dl_schedule_and_len(&dls, 1), OP_EQ, &bridge); + + done: + UNMOCK(get_options); +} + #define DIR_LEGACY(name) \ { #name, test_dir_ ## name , TT_FORK, NULL, NULL } @@ -3525,6 +3853,14 @@ struct testcase_t dir_tests[] = { DIR(purpose_needs_anonymity, 0), DIR(fetch_type, 0), DIR(packages, 0), + DIR(authdir_type_to_string, 0), + DIR(conn_purpose_to_string, 0), + DIR(should_use_directory_guards, 0), + DIR(should_not_init_request_to_ourselves, TT_FORK), + DIR(should_not_init_request_to_dir_auths_without_v3_info, 0), + DIR(should_init_request_to_dir_auths, 0), + DIR(choose_compression_level, 0), + DIR(find_dl_schedule_and_len, 0), END_OF_TESTCASES };