[tor-commits] [tor/master] Merge remote-tracking branch 'twstrike/directory-tests'

nickm at torproject.org nickm at torproject.org
Fri Jan 15 16:41:28 UTC 2016


commit 537214d10e79ddd2681bea6b4bb839e8af80315c
Merge: d3e7803 fcd7923
Author: Nick Mathewson <nickm at 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
  };
 +





More information about the tor-commits mailing list