commit 537214d10e79ddd2681bea6b4bb839e8af80315c Merge: d3e7803 fcd7923 Author: Nick Mathewson nickm@torproject.org Date: Fri Jan 15 11:08:22 2016 -0500
Merge remote-tracking branch 'twstrike/directory-tests'
src/or/directory.c | 28 ++-- src/or/directory.h | 25 ++-- src/test/test_dir.c | 373 ++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 398 insertions(+), 28 deletions(-)
diff --cc src/or/directory.c index 21abfb1,01ed694..e1bdcb0 --- a/src/or/directory.c +++ b/src/or/directory.c @@@ -3666,53 -3456,26 +3666,53 @@@ connection_dir_finished_connecting(dir_ }
/** Decide which download schedule we want to use based on descriptor type - * in <b>dls</b> and whether we are acting as directory <b>server</b>, and - * then return a list of int pointers defining download delays in seconds. - * Helper function for download_status_increment_failure() and - * download_status_reset(). */ + * in <b>dls</b> and <b>options</b>. + * Then return a list of int pointers defining download delays in seconds. + * Helper function for download_status_increment_failure(), + * download_status_reset(), and download_status_increment_attempt(). */ - static const smartlist_t * + STATIC const smartlist_t * -find_dl_schedule_and_len(download_status_t *dls, int server) +find_dl_schedule(download_status_t *dls, const or_options_t *options) { + const int dir_server = dir_server_mode(options); + const int multi_d = networkstatus_consensus_can_use_multiple_directories( + options); + const int we_are_bootstrapping = networkstatus_consensus_is_boostrapping( + time(NULL)); + const int use_fallbacks = networkstatus_consensus_can_use_extra_fallbacks( + options); switch (dls->schedule) { case DL_SCHED_GENERIC: - if (server) - return get_options()->TestingServerDownloadSchedule; - else - return get_options()->TestingClientDownloadSchedule; + if (dir_server) { + return options->TestingServerDownloadSchedule; + } else { + return options->TestingClientDownloadSchedule; + } case DL_SCHED_CONSENSUS: - if (server) - return get_options()->TestingServerConsensusDownloadSchedule; - else - return get_options()->TestingClientConsensusDownloadSchedule; + if (!multi_d) { + return options->TestingServerConsensusDownloadSchedule; + } else { + if (we_are_bootstrapping) { + if (!use_fallbacks) { + /* A bootstrapping client without extra fallback directories */ + return + options->TestingClientBootstrapConsensusAuthorityOnlyDownloadSchedule; + } else if (dls->want_authority) { + /* A bootstrapping client with extra fallback directories, but + * connecting to an authority */ + return + options->TestingClientBootstrapConsensusAuthorityDownloadSchedule; + } else { + /* A bootstrapping client connecting to extra fallback directories + */ + return + options->TestingClientBootstrapConsensusFallbackDownloadSchedule; + } + } else { + return options->TestingClientConsensusDownloadSchedule; + } + } case DL_SCHED_BRIDGE: - return get_options()->TestingBridgeDownloadSchedule; + return options->TestingBridgeDownloadSchedule; default: tor_assert(0); } diff --cc src/or/directory.h index 28442b9,d859df3..c5b5a5a --- a/src/or/directory.h +++ b/src/or/directory.h @@@ -139,14 -129,12 +141,21 @@@ STATIC int purpose_needs_anonymity(uint uint8_t router_purpose); STATIC dirinfo_type_t dir_fetch_type(int dir_purpose, int router_purpose, const char *resource); +STATIC int directory_handle_command_get(dir_connection_t *conn, + const char *headers, + const char *req_body, + size_t req_body_len); +STATIC int connection_dir_would_close_consensus_conn_helper(void); +STATIC int download_status_schedule_get_delay(download_status_t *dls, + const smartlist_t *schedule, + time_t now); ++ + 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); ++STATIC const smartlist_t *find_dl_schedule(download_status_t *dls, ++ const or_options_t *options); #endif
#endif diff --cc src/test/test_dir.c index cf95df5,c888e00..b0ed307 --- a/src/test/test_dir.c +++ b/src/test/test_dir.c @@@ -26,8 -31,10 +31,11 @@@ #include "routerparse.h" #include "routerset.h" #include "test.h" +#include "test_dir_common.h" #include "torcert.h" + #include "relay.h" + + #define NS_MODULE dir
static void test_dir_nicknames(void *arg) @@@ -3264,434 -3527,326 +3296,755 @@@ test_dir_packages(void *arg }
static void +test_dir_download_status_schedule(void *arg) +{ + (void)arg; + download_status_t dls_failure = { 0, 0, 0, DL_SCHED_GENERIC, + DL_WANT_AUTHORITY, + DL_SCHED_INCREMENT_FAILURE }; + download_status_t dls_attempt = { 0, 0, 0, DL_SCHED_CONSENSUS, + DL_WANT_ANY_DIRSERVER, + DL_SCHED_INCREMENT_ATTEMPT}; + download_status_t dls_bridge = { 0, 0, 0, DL_SCHED_BRIDGE, + DL_WANT_AUTHORITY, + DL_SCHED_INCREMENT_FAILURE}; + int increment = -1; + int expected_increment = -1; + time_t current_time = time(NULL); + int delay1 = -1; + int delay2 = -1; + smartlist_t *schedule = smartlist_new(); + + /* Make a dummy schedule */ + smartlist_add(schedule, (void *)&delay1); + smartlist_add(schedule, (void *)&delay2); + + /* check a range of values */ + delay1 = 1000; + increment = download_status_schedule_get_delay(&dls_failure, + schedule, + TIME_MIN); + expected_increment = delay1; + tt_assert(increment == expected_increment); + tt_assert(dls_failure.next_attempt_at == TIME_MIN + expected_increment); + +#if TIME_T_IS_SIGNED + delay1 = INT_MAX; + increment = download_status_schedule_get_delay(&dls_failure, + schedule, + -1); + expected_increment = delay1; + tt_assert(increment == expected_increment); + tt_assert(dls_failure.next_attempt_at == TIME_MAX); +#endif + + delay1 = 0; + increment = download_status_schedule_get_delay(&dls_attempt, + schedule, + 0); + expected_increment = delay1; + tt_assert(increment == expected_increment); + tt_assert(dls_attempt.next_attempt_at == 0 + expected_increment); + + delay1 = 1000; + increment = download_status_schedule_get_delay(&dls_attempt, + schedule, + 1); + expected_increment = delay1; + tt_assert(increment == expected_increment); + tt_assert(dls_attempt.next_attempt_at == 1 + expected_increment); + + delay1 = INT_MAX; + increment = download_status_schedule_get_delay(&dls_bridge, + schedule, + current_time); + expected_increment = delay1; + tt_assert(increment == expected_increment); + tt_assert(dls_bridge.next_attempt_at == TIME_MAX); + + delay1 = 1; + increment = download_status_schedule_get_delay(&dls_bridge, + schedule, + TIME_MAX); + expected_increment = delay1; + tt_assert(increment == expected_increment); + tt_assert(dls_bridge.next_attempt_at == TIME_MAX); + + /* see what happens when we reach the end */ + dls_attempt.n_download_attempts++; + dls_bridge.n_download_failures++; + + delay2 = 100; + increment = download_status_schedule_get_delay(&dls_attempt, + schedule, + current_time); + expected_increment = delay2; + tt_assert(increment == expected_increment); + tt_assert(dls_attempt.next_attempt_at == current_time + delay2); + + delay2 = 1; + increment = download_status_schedule_get_delay(&dls_bridge, + schedule, + current_time); + expected_increment = delay2; + tt_assert(increment == expected_increment); + tt_assert(dls_bridge.next_attempt_at == current_time + delay2); + + /* see what happens when we try to go off the end */ + dls_attempt.n_download_attempts++; + dls_bridge.n_download_failures++; + + delay2 = 5; + increment = download_status_schedule_get_delay(&dls_attempt, + schedule, + current_time); + expected_increment = delay2; + tt_assert(increment == expected_increment); + tt_assert(dls_attempt.next_attempt_at == current_time + delay2); + + delay2 = 17; + increment = download_status_schedule_get_delay(&dls_bridge, + schedule, + current_time); + expected_increment = delay2; + tt_assert(increment == expected_increment); + tt_assert(dls_bridge.next_attempt_at == current_time + delay2); + + /* see what happens when we reach IMPOSSIBLE_TO_DOWNLOAD */ + dls_attempt.n_download_attempts = IMPOSSIBLE_TO_DOWNLOAD; + dls_bridge.n_download_failures = IMPOSSIBLE_TO_DOWNLOAD; + + delay2 = 35; + increment = download_status_schedule_get_delay(&dls_attempt, + schedule, + current_time); + expected_increment = INT_MAX; + tt_assert(increment == expected_increment); + tt_assert(dls_attempt.next_attempt_at == TIME_MAX); + + delay2 = 99; + increment = download_status_schedule_get_delay(&dls_bridge, + schedule, + current_time); + expected_increment = INT_MAX; + tt_assert(increment == expected_increment); + tt_assert(dls_bridge.next_attempt_at == TIME_MAX); + + done: + /* the pointers in schedule are allocated on the stack */ + smartlist_free(schedule); +} + +static void +test_dir_download_status_increment(void *arg) +{ + (void)arg; + download_status_t dls_failure = { 0, 0, 0, DL_SCHED_GENERIC, + DL_WANT_AUTHORITY, + DL_SCHED_INCREMENT_FAILURE }; + download_status_t dls_attempt = { 0, 0, 0, DL_SCHED_BRIDGE, + DL_WANT_ANY_DIRSERVER, + DL_SCHED_INCREMENT_ATTEMPT}; + int delay0 = -1; + int delay1 = -1; + int delay2 = -1; + smartlist_t *schedule = smartlist_new(); + or_options_t test_options; + time_t next_at = TIME_MAX; + time_t current_time = time(NULL); + + /* Provide some values for the schedule */ + delay0 = 10; + delay1 = 99; + delay2 = 20; + + /* Make the schedule */ + smartlist_add(schedule, (void *)&delay0); + smartlist_add(schedule, (void *)&delay1); + smartlist_add(schedule, (void *)&delay2); + + /* Put it in the options */ + mock_options = &test_options; + reset_options(mock_options, &mock_get_options_calls); + mock_options->TestingClientDownloadSchedule = schedule; + mock_options->TestingBridgeDownloadSchedule = schedule; + + MOCK(get_options, mock_get_options); + + /* Check that a failure reset works */ + mock_get_options_calls = 0; + download_status_reset(&dls_failure); + /* we really want to test that it's equal to time(NULL) + delay0, but that's + * an unrealiable test, because time(NULL) might change. */ + tt_assert(download_status_get_next_attempt_at(&dls_failure) + >= current_time + delay0); + tt_assert(download_status_get_next_attempt_at(&dls_failure) + != TIME_MAX); + tt_assert(download_status_get_n_failures(&dls_failure) == 0); + tt_assert(download_status_get_n_attempts(&dls_failure) == 0); + tt_assert(mock_get_options_calls >= 1); + + /* avoid timing inconsistencies */ + dls_failure.next_attempt_at = current_time + delay0; + + /* check that a reset schedule becomes ready at the right time */ + tt_assert(download_status_is_ready(&dls_failure, + current_time + delay0 - 1, + 1) == 0); + tt_assert(download_status_is_ready(&dls_failure, + current_time + delay0, + 1) == 1); + tt_assert(download_status_is_ready(&dls_failure, + current_time + delay0 + 1, + 1) == 1); + + /* Check that a failure increment works */ + mock_get_options_calls = 0; + next_at = download_status_increment_failure(&dls_failure, 404, "test", 0, + current_time); + tt_assert(next_at == current_time + delay1); + tt_assert(download_status_get_n_failures(&dls_failure) == 1); + tt_assert(download_status_get_n_attempts(&dls_failure) == 1); + tt_assert(mock_get_options_calls >= 1); + + /* check that an incremented schedule becomes ready at the right time */ + tt_assert(download_status_is_ready(&dls_failure, + current_time + delay1 - 1, + 1) == 0); + tt_assert(download_status_is_ready(&dls_failure, + current_time + delay1, + 1) == 1); + tt_assert(download_status_is_ready(&dls_failure, + current_time + delay1 + 1, + 1) == 1); + + /* check that a schedule isn't ready if it's had too many failures */ + tt_assert(download_status_is_ready(&dls_failure, + current_time + delay1 + 10, + 0) == 0); + + /* Check that failure increments don't happen on 503 for clients, but that + * attempt increments do. */ + mock_get_options_calls = 0; + next_at = download_status_increment_failure(&dls_failure, 503, "test", 0, + current_time); + tt_assert(next_at == current_time + delay1); + tt_assert(download_status_get_n_failures(&dls_failure) == 1); + tt_assert(download_status_get_n_attempts(&dls_failure) == 2); + tt_assert(mock_get_options_calls >= 1); + + /* Check that failure increments do happen on 503 for servers */ + mock_get_options_calls = 0; + next_at = download_status_increment_failure(&dls_failure, 503, "test", 1, + current_time); + tt_assert(next_at == current_time + delay2); + tt_assert(download_status_get_n_failures(&dls_failure) == 2); + tt_assert(download_status_get_n_attempts(&dls_failure) == 3); + tt_assert(mock_get_options_calls >= 1); + + /* Check what happens when we run off the end of the schedule */ + mock_get_options_calls = 0; + next_at = download_status_increment_failure(&dls_failure, 404, "test", 0, + current_time); + tt_assert(next_at == current_time + delay2); + tt_assert(download_status_get_n_failures(&dls_failure) == 3); + tt_assert(download_status_get_n_attempts(&dls_failure) == 4); + tt_assert(mock_get_options_calls >= 1); + + /* Check what happens when we hit the failure limit */ + mock_get_options_calls = 0; + download_status_mark_impossible(&dls_failure); + next_at = download_status_increment_failure(&dls_failure, 404, "test", 0, + current_time); + tt_assert(next_at == TIME_MAX); + tt_assert(download_status_get_n_failures(&dls_failure) + == IMPOSSIBLE_TO_DOWNLOAD); + tt_assert(download_status_get_n_attempts(&dls_failure) + == IMPOSSIBLE_TO_DOWNLOAD); + tt_assert(mock_get_options_calls >= 1); + + /* Check that a failure reset doesn't reset at the limit */ + mock_get_options_calls = 0; + download_status_reset(&dls_failure); + tt_assert(download_status_get_next_attempt_at(&dls_failure) + == TIME_MAX); + tt_assert(download_status_get_n_failures(&dls_failure) + == IMPOSSIBLE_TO_DOWNLOAD); + tt_assert(download_status_get_n_attempts(&dls_failure) + == IMPOSSIBLE_TO_DOWNLOAD); + tt_assert(mock_get_options_calls == 0); + + /* Check that a failure reset resets just before the limit */ + mock_get_options_calls = 0; + dls_failure.n_download_failures = IMPOSSIBLE_TO_DOWNLOAD - 1; + dls_failure.n_download_attempts = IMPOSSIBLE_TO_DOWNLOAD - 1; + download_status_reset(&dls_failure); + /* we really want to test that it's equal to time(NULL) + delay0, but that's + * an unrealiable test, because time(NULL) might change. */ + tt_assert(download_status_get_next_attempt_at(&dls_failure) + >= current_time + delay0); + tt_assert(download_status_get_next_attempt_at(&dls_failure) + != TIME_MAX); + tt_assert(download_status_get_n_failures(&dls_failure) == 0); + tt_assert(download_status_get_n_attempts(&dls_failure) == 0); + tt_assert(mock_get_options_calls >= 1); + + /* Check that failure increments do happen on attempt-based schedules, + * but that the retry is set at the end of time */ + mock_get_options_calls = 0; + next_at = download_status_increment_failure(&dls_attempt, 404, "test", 0, + current_time); + tt_assert(next_at == TIME_MAX); + tt_assert(download_status_get_n_failures(&dls_attempt) == 1); + tt_assert(download_status_get_n_attempts(&dls_attempt) == 0); + tt_assert(mock_get_options_calls == 0); + + /* Check that an attempt reset works */ + mock_get_options_calls = 0; + download_status_reset(&dls_attempt); + /* we really want to test that it's equal to time(NULL) + delay0, but that's + * an unrealiable test, because time(NULL) might change. */ + tt_assert(download_status_get_next_attempt_at(&dls_attempt) + >= current_time + delay0); + tt_assert(download_status_get_next_attempt_at(&dls_attempt) + != TIME_MAX); + tt_assert(download_status_get_n_failures(&dls_attempt) == 0); + tt_assert(download_status_get_n_attempts(&dls_attempt) == 0); + tt_assert(mock_get_options_calls >= 1); + + /* avoid timing inconsistencies */ + dls_attempt.next_attempt_at = current_time + delay0; + + /* check that a reset schedule becomes ready at the right time */ + tt_assert(download_status_is_ready(&dls_attempt, + current_time + delay0 - 1, + 1) == 0); + tt_assert(download_status_is_ready(&dls_attempt, + current_time + delay0, + 1) == 1); + tt_assert(download_status_is_ready(&dls_attempt, + current_time + delay0 + 1, + 1) == 1); + + /* Check that an attempt increment works */ + mock_get_options_calls = 0; + next_at = download_status_increment_attempt(&dls_attempt, "test", + current_time); + tt_assert(next_at == current_time + delay1); + tt_assert(download_status_get_n_failures(&dls_attempt) == 0); + tt_assert(download_status_get_n_attempts(&dls_attempt) == 1); + tt_assert(mock_get_options_calls >= 1); + + /* check that an incremented schedule becomes ready at the right time */ + tt_assert(download_status_is_ready(&dls_attempt, + current_time + delay1 - 1, + 1) == 0); + tt_assert(download_status_is_ready(&dls_attempt, + current_time + delay1, + 1) == 1); + tt_assert(download_status_is_ready(&dls_attempt, + current_time + delay1 + 1, + 1) == 1); + + /* check that a schedule isn't ready if it's had too many attempts */ + tt_assert(download_status_is_ready(&dls_attempt, + current_time + delay1 + 10, + 0) == 0); + + /* Check what happens when we reach then run off the end of the schedule */ + mock_get_options_calls = 0; + next_at = download_status_increment_attempt(&dls_attempt, "test", + current_time); + tt_assert(next_at == current_time + delay2); + tt_assert(download_status_get_n_failures(&dls_attempt) == 0); + tt_assert(download_status_get_n_attempts(&dls_attempt) == 2); + tt_assert(mock_get_options_calls >= 1); + + mock_get_options_calls = 0; + next_at = download_status_increment_attempt(&dls_attempt, "test", + current_time); + tt_assert(next_at == current_time + delay2); + tt_assert(download_status_get_n_failures(&dls_attempt) == 0); + tt_assert(download_status_get_n_attempts(&dls_attempt) == 3); + tt_assert(mock_get_options_calls >= 1); + + /* Check what happens when we hit the attempt limit */ + mock_get_options_calls = 0; + download_status_mark_impossible(&dls_attempt); + next_at = download_status_increment_attempt(&dls_attempt, "test", + current_time); + tt_assert(next_at == TIME_MAX); + tt_assert(download_status_get_n_failures(&dls_attempt) + == IMPOSSIBLE_TO_DOWNLOAD); + tt_assert(download_status_get_n_attempts(&dls_attempt) + == IMPOSSIBLE_TO_DOWNLOAD); + tt_assert(mock_get_options_calls >= 1); + + /* Check that an attempt reset doesn't reset at the limit */ + mock_get_options_calls = 0; + download_status_reset(&dls_attempt); + tt_assert(download_status_get_next_attempt_at(&dls_attempt) + == TIME_MAX); + tt_assert(download_status_get_n_failures(&dls_attempt) + == IMPOSSIBLE_TO_DOWNLOAD); + tt_assert(download_status_get_n_attempts(&dls_attempt) + == IMPOSSIBLE_TO_DOWNLOAD); + tt_assert(mock_get_options_calls == 0); + + /* Check that an attempt reset resets just before the limit */ + mock_get_options_calls = 0; + dls_attempt.n_download_failures = IMPOSSIBLE_TO_DOWNLOAD - 1; + dls_attempt.n_download_attempts = IMPOSSIBLE_TO_DOWNLOAD - 1; + download_status_reset(&dls_attempt); + /* we really want to test that it's equal to time(NULL) + delay0, but that's + * an unrealiable test, because time(NULL) might change. */ + tt_assert(download_status_get_next_attempt_at(&dls_attempt) + >= current_time + delay0); + tt_assert(download_status_get_next_attempt_at(&dls_attempt) + != TIME_MAX); + tt_assert(download_status_get_n_failures(&dls_attempt) == 0); + tt_assert(download_status_get_n_attempts(&dls_attempt) == 0); + tt_assert(mock_get_options_calls >= 1); + + /* Check that attempt increments don't happen on failure-based schedules, + * and that the attempt is set at the end of time */ + mock_get_options_calls = 0; + next_at = download_status_increment_attempt(&dls_failure, "test", + current_time); + tt_assert(next_at == TIME_MAX); + tt_assert(download_status_get_n_failures(&dls_failure) == 0); + tt_assert(download_status_get_n_attempts(&dls_failure) == 0); + tt_assert(mock_get_options_calls == 0); + + done: + /* the pointers in schedule are allocated on the stack */ + smartlist_free(schedule); + UNMOCK(get_options); + mock_options = NULL; + mock_get_options_calls = 0; +} + ++static void + test_dir_authdir_type_to_string(void *data) + { + (void)data; + char *res; + + tt_str_op(res = authdir_type_to_string(NO_DIRINFO), OP_EQ, + "[Not an authority]"); + tor_free(res); + + tt_str_op(res = authdir_type_to_string(EXTRAINFO_DIRINFO), OP_EQ, + "[Not an authority]"); + tor_free(res); + + tt_str_op(res = authdir_type_to_string(MICRODESC_DIRINFO), OP_EQ, + "[Not an authority]"); + tor_free(res); + + tt_str_op(res = authdir_type_to_string(V3_DIRINFO), OP_EQ, "V3"); + tor_free(res); + + tt_str_op(res = authdir_type_to_string(BRIDGE_DIRINFO), OP_EQ, "Bridge"); + tor_free(res); + + tt_str_op(res = authdir_type_to_string( + V3_DIRINFO | BRIDGE_DIRINFO | EXTRAINFO_DIRINFO), OP_EQ, + "V3, Bridge"); + done: + tor_free(res); + } + + 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); + or_options_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) + { + (void)status; + (void)dir_purpose; + (void)router_purpose; + (void)indirection; + (void)resource; + (void)payload; + (void)payload_len; + (void)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 }
@@@ -3723,8 -3878,13 +4076,16 @@@ struct testcase_t dir_tests[] = DIR(purpose_needs_anonymity, 0), DIR(fetch_type, 0), DIR(packages, 0), + DIR(download_status_schedule, 0), + DIR(download_status_increment, 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 }; +
tor-commits@lists.torproject.org