Procházet zdrojové kódy

Unit tests for consider_adding_dir_servers() as modified in #15642

Unit tests for the 10 valid combinations of set/NULL config options
DirAuthorities, AlternateBridgeAuthority, AlternateDirAuthority,
and FallbackDir.

Add assertion in consider_adding_dir_servers() for checks in
validate_dir_servers():
"You cannot set both DirAuthority and Alternate*Authority."
teor před 9 roky
rodič
revize
d68bbb0a29

+ 5 - 3
changes/bug-15642-default-fallback-default-dirs

@@ -1,8 +1,10 @@
-  o Minor bugfixes (configuration):
+  o Minor bugfixes (configuration, unit tests):
     - Only add the default fallback directories when the DirAuthorities,
     - Only add the default fallback directories when the DirAuthorities,
       AlternateDirAuthority, and FallbackDir directory config options
       AlternateDirAuthority, and FallbackDir directory config options
       are set to their defaults.
       are set to their defaults.
-      The default fallback directory list is empty, this fix will only
-      change tor's behaviour when it has default fallback directories.
+      The default fallback directory list is currently empty, this fix
+      will only change tor's behaviour when it has default fallback
+      directories.
+      Includes unit tests for consider_adding_dir_servers().
       Fixes bug 15642; bugfix on 90f6071d8dc0 in 0.2.4.7-alpha.
       Fixes bug 15642; bugfix on 90f6071d8dc0 in 0.2.4.7-alpha.
       Patch by "teor".
       Patch by "teor".

+ 13 - 7
src/or/config.c

@@ -545,8 +545,6 @@ static char *get_bindaddr_from_transport_listen_line(const char *line,
 static int parse_dir_authority_line(const char *line,
 static int parse_dir_authority_line(const char *line,
                                  dirinfo_type_t required_type,
                                  dirinfo_type_t required_type,
                                  int validate_only);
                                  int validate_only);
-static int parse_dir_fallback_line(const char *line,
-                                   int validate_only);
 static void port_cfg_free(port_cfg_t *port);
 static void port_cfg_free(port_cfg_t *port);
 static int parse_ports(or_options_t *options, int validate_only,
 static int parse_ports(or_options_t *options, int validate_only,
                               char **msg_out, int *n_ports_out);
                               char **msg_out, int *n_ports_out);
@@ -891,8 +889,8 @@ add_default_trusted_dir_authorities(dirinfo_type_t type)
 
 
 /** Add the default fallback directory servers into the fallback directory
 /** Add the default fallback directory servers into the fallback directory
  * server list. */
  * server list. */
-static void
-add_default_fallback_dir_servers(void)
+MOCK_IMPL(void,
+add_default_fallback_dir_servers,(void))
 {
 {
   int i;
   int i;
   const char *fallback[] = {
   const char *fallback[] = {
@@ -961,7 +959,7 @@ validate_dir_servers(or_options_t *options, or_options_t *old_options)
 /** Look at all the config options and assign new dir authorities
 /** Look at all the config options and assign new dir authorities
  * as appropriate.
  * as appropriate.
  */
  */
-static int
+int
 consider_adding_dir_servers(const or_options_t *options,
 consider_adding_dir_servers(const or_options_t *options,
                             const or_options_t *old_options)
                             const or_options_t *old_options)
 {
 {
@@ -979,6 +977,13 @@ consider_adding_dir_servers(const or_options_t *options,
   if (!need_to_update)
   if (!need_to_update)
     return 0; /* all done */
     return 0; /* all done */
 
 
+  /* "You cannot set both DirAuthority and Alternate*Authority."
+   * Checking that this restriction holds allows us to simplify
+   * the unit tests. */
+  tor_assert(!(options->DirAuthorities &&
+               (options->AlternateDirAuthority
+                || options->AlternateBridgeAuthority)));
+
   /* Start from a clean slate. */
   /* Start from a clean slate. */
   clear_dir_servers();
   clear_dir_servers();
 
 
@@ -993,8 +998,9 @@ consider_adding_dir_servers(const or_options_t *options,
       /* Only add the default fallback directories when the DirAuthorities,
       /* Only add the default fallback directories when the DirAuthorities,
        * AlternateDirAuthority, and FallbackDir directory config options
        * AlternateDirAuthority, and FallbackDir directory config options
        * are set to their defaults. */
        * are set to their defaults. */
-      if (!options->FallbackDir)
+      if (!options->FallbackDir) {
         add_default_fallback_dir_servers();
         add_default_fallback_dir_servers();
+      }
     }
     }
     /* if type == NO_DIRINFO, we don't want to add any of the
     /* if type == NO_DIRINFO, we don't want to add any of the
      * default authorities, because we've replaced them all */
      * default authorities, because we've replaced them all */
@@ -5500,7 +5506,7 @@ parse_dir_authority_line(const char *line, dirinfo_type_t required_type,
  * <b>validate_only</b> is 0, and the line is well-formed, then add the
  * <b>validate_only</b> is 0, and the line is well-formed, then add the
  * dirserver described in the line as a fallback directory. Return 0 on
  * dirserver described in the line as a fallback directory. Return 0 on
  * success, or -1 if the line isn't well-formed or if we can't add it. */
  * success, or -1 if the line isn't well-formed or if we can't add it. */
-static int
+int
 parse_dir_fallback_line(const char *line,
 parse_dir_fallback_line(const char *line,
                         int validate_only)
                         int validate_only)
 {
 {

+ 6 - 0
src/or/config.h

@@ -144,6 +144,12 @@ STATIC int options_validate(or_options_t *old_options,
 STATIC int parse_transport_line(const or_options_t *options,
 STATIC int parse_transport_line(const or_options_t *options,
                                 const char *line, int validate_only,
                                 const char *line, int validate_only,
                                 int server);
                                 int server);
+STATIC int consider_adding_dir_servers(const or_options_t *options,
+                                       const or_options_t *old_options);
+MOCK_DECL(STATIC void, add_default_fallback_dir_servers, (void));
+STATIC int
+parse_dir_fallback_line(const char *line,
+                        int validate_only);
 #endif
 #endif
 
 
 #endif
 #endif

+ 1769 - 2
src/test/test_config.c

@@ -17,6 +17,7 @@
 #include "address.h"
 #include "address.h"
 #include "entrynodes.h"
 #include "entrynodes.h"
 #include "transports.h"
 #include "transports.h"
+#include "routerlist.h"
 
 
 static void
 static void
 test_config_addressmap(void *arg)
 test_config_addressmap(void *arg)
@@ -1036,7 +1037,7 @@ static int n_get_interface_address6_failure = 0;
 
 
 /**
 /**
  * This mock function is meant to replace get_interface_addres6().
  * This mock function is meant to replace get_interface_addres6().
- * It will pretent to fail by return -1.
+ * It will pretend to fail by return -1.
  * <b>n_get_interface_address6_failure</b> is incremented by one
  * <b>n_get_interface_address6_failure</b> is incremented by one
  * every time this function is called and <b>last_address6_family</b>
  * every time this function is called and <b>last_address6_family</b>
  * is assigned the value of <b>family</b> argument.
  * is assigned the value of <b>family</b> argument.
@@ -1405,7 +1406,7 @@ test_config_resolve_my_address(void *arg)
 
 
   /* CASE 12:
   /* CASE 12:
    * Suppose the following happens:
    * Suppose the following happens:
-   *   1. options->Address is NULL AND options->DirAuthorities is 1.
+   *   1. options->Address is NULL AND options->DirAuthorities is non-NULL
    *   2. tor_gethostname() succeeds in getting hostname of a machine ...
    *   2. tor_gethostname() succeeds in getting hostname of a machine ...
    *   3. ... which is successfully parsed by tor_inet_aton() ...
    *   3. ... which is successfully parsed by tor_inet_aton() ...
    *   4. into IPv4 address that tor_addr_is_inernal() considers to be
    *   4. into IPv4 address that tor_addr_is_inernal() considers to be
@@ -1443,10 +1444,1776 @@ test_config_resolve_my_address(void *arg)
   UNMOCK(tor_gethostname);
   UNMOCK(tor_gethostname);
 }
 }
 
 
+static int n_add_default_fallback_dir_servers_known_default = 0;
+
+/**
+ * This mock function is meant to replace add_default_fallback_dir_servers().
+ * It will parse and add one known default fallback dir server,
+ * which has a dir_port of 99.
+ * <b>n_add_default_fallback_dir_servers_known_default</b> is incremented by
+ * one every time this function is called.
+ */
+static void
+add_default_fallback_dir_servers_known_default(void)
+{
+  int i;
+  const char *fallback[] = {
+    "127.0.0.1:60099 orport=9009 "
+    "id=0923456789012345678901234567890123456789",
+    NULL
+  };
+  for (i=0; fallback[i]; i++) {
+    if (parse_dir_fallback_line(fallback[i], 0)<0) {
+      log_err(LD_BUG, "Couldn't parse internal FallbackDir line %s",
+              fallback[i]);
+    }
+  }
+  n_add_default_fallback_dir_servers_known_default++;
+}
+
+static void
+test_config_adding_dir_servers(void *arg)
+{
+  (void)arg;
+
+  /* allocate options */
+  or_options_t *options = tor_malloc(sizeof(or_options_t));
+
+  /* Allocate and populate configuration lines:
+   *
+   * Use the same format as the hard-coded directories in
+   * add_default_trusted_dir_authorities().
+   * Zeroing the structure has the same effect as initialising to:
+   * { NULL, NULL, NULL, CONFIG_LINE_NORMAL, 0};
+   */
+  config_line_t *test_dir_authority = tor_malloc(sizeof(config_line_t));
+  memset(test_dir_authority, 0, sizeof(config_line_t));
+  test_dir_authority->key = tor_strdup("DirAuthority");
+  test_dir_authority->value = tor_strdup(
+    "D0 orport=9000 "
+    "v3ident=0023456789012345678901234567890123456789 "
+    "127.0.0.1:60090 0123 4567 8901 2345 6789 0123 4567 8901 2345 6789"
+    );
+
+  config_line_t *test_alt_bridge_authority = tor_malloc(sizeof(config_line_t));
+  memset(test_alt_bridge_authority, 0, sizeof(config_line_t));
+  test_alt_bridge_authority->key = tor_strdup("AlternateBridgeAuthority");
+  test_alt_bridge_authority->value = tor_strdup(
+    "B1 orport=9001 bridge "
+    "127.0.0.1:60091 1123 4567 8901 2345 6789 0123 4567 8901 2345 6789"
+    );
+
+  config_line_t *test_alt_dir_authority = tor_malloc(sizeof(config_line_t));
+  memset(test_alt_dir_authority, 0, sizeof(config_line_t));
+  test_alt_dir_authority->key = tor_strdup("AlternateDirAuthority");
+  test_alt_dir_authority->value = tor_strdup(
+    "A2 orport=9002 "
+    "v3ident=0223456789012345678901234567890123456789 "
+    "127.0.0.1:60092 2123 4567 8901 2345 6789 0123 4567 8901 2345 6789"
+    );
+
+  /* Use the format specified in the manual page */
+  config_line_t *test_fallback_directory = tor_malloc(sizeof(config_line_t));
+  memset(test_fallback_directory, 0, sizeof(config_line_t));
+  test_fallback_directory->key = tor_strdup("FallbackDir");
+  test_fallback_directory->value = tor_strdup(
+    "127.0.0.1:60093 orport=9003 id=0323456789012345678901234567890123456789"
+    );
+
+  /* We need to know if add_default_fallback_dir_servers is called,
+   * so we use a version of add_default_fallback_dir_servers that adds
+   * one known default fallback directory.
+   * There doesn't appear to be any need to test it unmocked. */
+  MOCK(add_default_fallback_dir_servers,
+       add_default_fallback_dir_servers_known_default);
+
+  /* There are 16 different cases, covering each combination of set/NULL for:
+   * DirAuthorities, AlternateBridgeAuthority, AlternateDirAuthority &
+   * FallbackDir.
+   * But validate_dir_servers() ensures that:
+   *   "You cannot set both DirAuthority and Alternate*Authority."
+   * This reduces the number of cases to 10.
+   *
+   * Let's count these cases using binary, with 1 meaning set & 0 meaning NULL
+   * So 1001 or case 9 is:
+   *   DirAuthorities set,
+   *   AlternateBridgeAuthority NULL,
+   *   AlternateDirAuthority NULL
+   *   FallbackDir set
+   * The valid cases are cases 0-9 counting using this method, as every case
+   * greater than or equal to 10 = 1010 is invalid.
+   *
+   * After #15642 - Disable default fallback dirs when any custom dirs set
+   *
+   * 1. Outcome: Use Set Directory Authorities
+   *   - No Default Authorities
+   *   - Use AlternateBridgeAuthority, AlternateDirAuthority, and FallbackDir
+   *     if they are set
+   *   Cases expected to yield this outcome:
+   *     8 & 9 (the 2 valid cases where DirAuthorities is set)
+   *     6 & 7 (the 2 cases where DirAuthorities is NULL, and
+   *           AlternateBridgeAuthority and AlternateDirAuthority are both set)
+   *
+   * 2. Outcome: Use Set Bridge Authority
+   *  - Use Default Non-Bridge Directory Authorities
+   *  - Use FallbackDir if it is set, otherwise use default FallbackDir
+   *  Cases expected to yield this outcome:
+   *    4 & 5 (the 2 cases where DirAuthorities is NULL,
+   *           AlternateBridgeAuthority is set, and
+   *           AlternateDirAuthority is NULL)
+   *
+   * 3. Outcome: Use Set Alternate Directory Authority
+   *  - Use Default Bridge Authorities
+   *  - Use FallbackDir if it is set, otherwise No Default Fallback Directories
+   *  Cases expected to yield this outcome:
+   *    2 & 3 (the 2 cases where DirAuthorities and AlternateBridgeAuthority
+   *           are both NULL, but AlternateDirAuthority is set)
+   *
+   * 4. Outcome: Use Set Custom Fallback Directory
+   *  - Use Default Bridge & Directory Authorities
+   *  Cases expected to yield this outcome:
+   *    1 (DirAuthorities, AlternateBridgeAuthority and AlternateDirAuthority
+   *       are all NULL, but FallbackDir is set)
+   *
+   * 5. Outcome: Use All Defaults
+   *  - Use Default Bridge & Directory Authorities, and
+   *    Default Fallback Directories
+   *  Cases expected to yield this outcome:
+   *    0 (DirAuthorities, AlternateBridgeAuthority, AlternateDirAuthority
+   *       and FallbackDir are all NULL)
+   *
+   * Before #15642 but after #13163 - Stop using default authorities when both
+   * Alternate Dir and Bridge Authority are set
+   * (#13163 was committed in 0.2.6 as c1dd43d823c7)
+   *
+   * The behaviour is different in the following cases
+   * where FallbackDir is NULL:
+   *  2, 6, 8
+   *
+   * In these cases, the Default Fallback Directories are applied, even when
+   * DirAuthorities or AlternateDirAuthority are set.
+   *
+   * However, as the list of default fallback directories is currently empty,
+   * this change doesn't modify any user-visible behaviour.
+   */
+
+  /*
+   * Find out how many default Bridge, Non-Bridge and Fallback Directories
+   * are hard-coded into this build.
+   * This code makes some assumptions about the implementation.
+   * If they are wrong, one or more of cases 0-5 could fail.
+   */
+  int n_default_alt_bridge_authority = 0;
+  int n_default_alt_dir_authority = 0;
+  int n_default_fallback_dir = 0;
+#define n_default_authorities ((n_default_alt_bridge_authority) \
+                               + (n_default_alt_dir_authority))
+
+  /* Pre-Count Number of Authorities of Each Type
+   * Use 0000: No Directory Authorities or Fallback Directories Set
+   */
+  {
+    /* clear fallback dirs counter */
+    n_add_default_fallback_dir_servers_known_default = 0;
+
+    /* clear options*/
+    memset(options, 0, sizeof(or_options_t));
+
+    /* clear any previous dir servers:
+     consider_adding_dir_servers() should do this anyway */
+    clear_dir_servers();
+
+    /* assign options: 0000 */
+    options->DirAuthorities = NULL;
+    options->AlternateBridgeAuthority = NULL;
+    options->AlternateDirAuthority = NULL;
+    options->FallbackDir = NULL;
+
+    /* parse options - ensure we always update by passing NULL old_options */
+    consider_adding_dir_servers(options, NULL);
+
+    /* check outcome */
+
+    /* we must have added the default fallback dirs */
+    tt_assert(n_add_default_fallback_dir_servers_known_default == 1);
+
+    {
+      /* fallback_dir_servers */
+      const smartlist_t *fallback_servers = router_get_fallback_dir_servers();
+
+      /* Count Bridge Authorities */
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if it's a bridge auth */
+                        n_default_alt_bridge_authority +=
+                        ((ds->is_authority && (ds->type & BRIDGE_DIRINFO)) ?
+                         1 : 0)
+                        );
+      /* If we have no default bridge authority, something has gone wrong */
+      tt_assert(n_default_alt_bridge_authority >= 1);
+
+      /* Count v3 Authorities */
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment found counter if it's a v3 auth */
+                        n_default_alt_dir_authority +=
+                        ((ds->is_authority && (ds->type & V3_DIRINFO)) ?
+                         1 : 0)
+                        );
+      /* If we have no default authorities, something has gone really wrong */
+      tt_assert(n_default_alt_dir_authority >= 1);
+
+      /* Calculate Fallback Directory Count */
+      n_default_fallback_dir = (smartlist_len(fallback_servers) -
+                                n_default_alt_bridge_authority -
+                                n_default_alt_dir_authority);
+      /* If we have a negative count, something has gone really wrong */
+      tt_assert(n_default_fallback_dir >= 0);
+    }
+  }
+
+  /*
+   * 1. Outcome: Use Set Directory Authorities
+   *   - No Default Authorities
+   *   - Use AlternateBridgeAuthority, AlternateDirAuthority, and FallbackDir
+   *     if they are set
+   *   Cases expected to yield this outcome:
+   *     8 & 9 (the 2 valid cases where DirAuthorities is set)
+   *     6 & 7 (the 2 cases where DirAuthorities is NULL, and
+   *           AlternateBridgeAuthority and AlternateDirAuthority are both set)
+   */
+
+  /* Case 9: 1001 - DirAuthorities Set, AlternateBridgeAuthority Not Set,
+     AlternateDirAuthority Not Set, FallbackDir Set */
+  {
+    /* clear fallback dirs counter */
+    n_add_default_fallback_dir_servers_known_default = 0;
+
+    /* clear options*/
+    memset(options, 0, sizeof(or_options_t));
+
+    /* clear any previous dir servers:
+     consider_adding_dir_servers() should do this anyway */
+    clear_dir_servers();
+
+    /* assign options: 1001 */
+    options->DirAuthorities = test_dir_authority;
+    options->AlternateBridgeAuthority = NULL;
+    options->AlternateDirAuthority = NULL;
+    options->FallbackDir = test_fallback_directory;
+
+    /* parse options - ensure we always update by passing NULL old_options */
+    consider_adding_dir_servers(options, NULL);
+
+    /* check outcome */
+
+    /* we must not have added the default fallback dirs */
+    tt_assert(n_add_default_fallback_dir_servers_known_default == 0);
+
+    {
+      /* trusted_dir_servers */
+      const smartlist_t *dir_servers = router_get_trusted_dir_servers();
+      /* D0, (No B1), (No A2) */
+      tt_assert(smartlist_len(dir_servers) == 1);
+
+      /* DirAuthority - D0 - dir_port: 60090 */
+      int found_D0 = 0;
+      SMARTLIST_FOREACH(dir_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_D0 +=
+                        (ds->dir_port == 60090 ?
+                         1 : 0)
+                        );
+      tt_assert(found_D0 == 1);
+
+      /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */
+      int found_B1 = 0;
+      SMARTLIST_FOREACH(dir_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_B1 +=
+                        (ds->dir_port == 60091 ?
+                         1 : 0)
+                        );
+      tt_assert(found_B1 == 0);
+
+      /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */
+      int found_A2 = 0;
+      SMARTLIST_FOREACH(dir_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_A2 +=
+                        (ds->dir_port == 60092 ?
+                         1 : 0)
+                        );
+      tt_assert(found_A2 == 0);
+    }
+
+    {
+      /* fallback_dir_servers */
+      const smartlist_t *fallback_servers = router_get_fallback_dir_servers();
+      /* D0, (No B1), (No A2), Custom Fallback */
+      tt_assert(smartlist_len(fallback_servers) == 2);
+
+      /* DirAuthority - D0 - dir_port: 60090 */
+      int found_D0 = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_D0 +=
+                        (ds->dir_port == 60090 ?
+                         1 : 0)
+                        );
+      tt_assert(found_D0 == 1);
+
+      /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */
+      int found_B1 = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_B1 +=
+                        (ds->dir_port == 60091 ?
+                         1 : 0)
+                        );
+      tt_assert(found_B1 == 0);
+
+      /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */
+      int found_A2 = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_A2 +=
+                        (ds->dir_port == 60092 ?
+                         1 : 0)
+                        );
+      tt_assert(found_A2 == 0);
+
+      /* Custom FallbackDir - No Nickname - dir_port: 60093 */
+      int found_non_default_fallback = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_non_default_fallback +=
+                        (ds->dir_port == 60093 ?
+                         1 : 0)
+                        );
+      tt_assert(found_non_default_fallback == 1);
+
+      /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */
+      int found_default_fallback = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_default_fallback +=
+                        (ds->dir_port == 60099 ?
+                         1 : 0)
+                        );
+      tt_assert(found_default_fallback == 0);
+    }
+  }
+
+  /* Case 8: 1000 - DirAuthorities Set, Others Not Set */
+  {
+    /* clear fallback dirs counter */
+    n_add_default_fallback_dir_servers_known_default = 0;
+
+    /* clear options*/
+    memset(options, 0, sizeof(or_options_t));
+
+    /* clear any previous dir servers:
+     consider_adding_dir_servers() should do this anyway */
+    clear_dir_servers();
+
+    /* assign options: 1000 */
+    options->DirAuthorities = test_dir_authority;
+    options->AlternateBridgeAuthority = NULL;
+    options->AlternateDirAuthority = NULL;
+    options->FallbackDir = NULL;
+
+    /* parse options - ensure we always update by passing NULL old_options */
+    consider_adding_dir_servers(options, NULL);
+
+    /* check outcome */
+
+    /* we must not have added the default fallback dirs */
+    tt_assert(n_add_default_fallback_dir_servers_known_default == 0);
+
+    {
+      /* trusted_dir_servers */
+      const smartlist_t *dir_servers = router_get_trusted_dir_servers();
+      /* D0, (No B1), (No A2) */
+      tt_assert(smartlist_len(dir_servers) == 1);
+
+      /* DirAuthority - D0 - dir_port: 60090 */
+      int found_D0 = 0;
+      SMARTLIST_FOREACH(dir_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_D0 +=
+                        (ds->dir_port == 60090 ?
+                         1 : 0)
+                        );
+      tt_assert(found_D0 == 1);
+
+      /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */
+      int found_B1 = 0;
+      SMARTLIST_FOREACH(dir_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_B1 +=
+                        (ds->dir_port == 60091 ?
+                         1 : 0)
+                        );
+      tt_assert(found_B1 == 0);
+
+      /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */
+      int found_A2 = 0;
+      SMARTLIST_FOREACH(dir_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_A2 +=
+                        (ds->dir_port == 60092 ?
+                         1 : 0)
+                        );
+      tt_assert(found_A2 == 0);
+    }
+
+    {
+      /* fallback_dir_servers */
+      const smartlist_t *fallback_servers = router_get_fallback_dir_servers();
+      /* D0, (No B1), (No A2), (No Fallback) */
+      tt_assert(smartlist_len(fallback_servers) == 1);
+
+      /* DirAuthority - D0 - dir_port: 60090 */
+      int found_D0 = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_D0 +=
+                        (ds->dir_port == 60090 ?
+                         1 : 0)
+                        );
+      tt_assert(found_D0 == 1);
+
+      /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */
+      int found_B1 = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_B1 +=
+                        (ds->dir_port == 60091 ?
+                         1 : 0)
+                        );
+      tt_assert(found_B1 == 0);
+
+      /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */
+      int found_A2 = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_A2 +=
+                        (ds->dir_port == 60092 ?
+                         1 : 0)
+                        );
+      tt_assert(found_A2 == 0);
+
+      /* (No Custom FallbackDir) - No Nickname - dir_port: 60093 */
+      int found_non_default_fallback = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_non_default_fallback +=
+                        (ds->dir_port == 60093 ?
+                         1 : 0)
+                        );
+      tt_assert(found_non_default_fallback == 0);
+
+      /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */
+      int found_default_fallback = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_default_fallback +=
+                        (ds->dir_port == 60099 ?
+                         1 : 0)
+                        );
+      tt_assert(found_default_fallback == 0);
+    }
+  }
+
+  /* Case 7: 0111 - DirAuthorities Not Set, Others Set */
+  {
+    /* clear fallback dirs counter */
+    n_add_default_fallback_dir_servers_known_default = 0;
+
+    /* clear options*/
+    memset(options, 0, sizeof(or_options_t));
+
+    /* clear any previous dir servers:
+     consider_adding_dir_servers() should do this anyway */
+    clear_dir_servers();
+
+    /* assign options: 0111 */
+    options->DirAuthorities = NULL;
+    options->AlternateBridgeAuthority = test_alt_bridge_authority;
+    options->AlternateDirAuthority = test_alt_dir_authority;
+    options->FallbackDir = test_fallback_directory;
+
+    /* parse options - ensure we always update by passing NULL old_options */
+    consider_adding_dir_servers(options, NULL);
+
+    /* check outcome */
+
+    /* we must not have added the default fallback dirs */
+    tt_assert(n_add_default_fallback_dir_servers_known_default == 0);
+
+    {
+      /* trusted_dir_servers */
+      const smartlist_t *dir_servers = router_get_trusted_dir_servers();
+      /* (No D0), B1, A2 */
+      tt_assert(smartlist_len(dir_servers) == 2);
+
+      /* (No DirAuthority) - D0 - dir_port: 60090 */
+      int found_D0 = 0;
+      SMARTLIST_FOREACH(dir_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_D0 +=
+                        (ds->dir_port == 60090 ?
+                         1 : 0)
+                        );
+      tt_assert(found_D0 == 0);
+
+      /* AlternateBridgeAuthority - B1 - dir_port: 60091 */
+      int found_B1 = 0;
+      SMARTLIST_FOREACH(dir_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_B1 +=
+                        (ds->dir_port == 60091 ?
+                         1 : 0)
+                        );
+      tt_assert(found_B1 == 1);
+
+      /* AlternateDirAuthority - A2 - dir_port: 60092 */
+      int found_A2 = 0;
+      SMARTLIST_FOREACH(dir_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_A2 +=
+                        (ds->dir_port == 60092 ?
+                         1 : 0)
+                        );
+      tt_assert(found_A2 == 1);
+    }
+
+    {
+      /* fallback_dir_servers */
+      const smartlist_t *fallback_servers = router_get_fallback_dir_servers();
+      /* (No D0), B1, A2, Custom Fallback */
+      tt_assert(smartlist_len(fallback_servers) == 3);
+
+      /* (No DirAuthority) - D0 - dir_port: 60090 */
+      int found_D0 = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_D0 +=
+                        (ds->dir_port == 60090 ?
+                         1 : 0)
+                        );
+      tt_assert(found_D0 == 0);
+
+      /* AlternateBridgeAuthority - B1 - dir_port: 60091 */
+      int found_B1 = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_B1 +=
+                        (ds->dir_port == 60091 ?
+                         1 : 0)
+                        );
+      tt_assert(found_B1 == 1);
+
+      /* AlternateDirAuthority - A2 - dir_port: 60092 */
+      int found_A2 = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_A2 +=
+                        (ds->dir_port == 60092 ?
+                         1 : 0)
+                        );
+      tt_assert(found_A2 == 1);
+
+      /* Custom FallbackDir - No Nickname - dir_port: 60093 */
+      int found_non_default_fallback = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_non_default_fallback +=
+                        (ds->dir_port == 60093 ?
+                         1 : 0)
+                        );
+      tt_assert(found_non_default_fallback == 1);
+
+      /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */
+      int found_default_fallback = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_default_fallback +=
+                        (ds->dir_port == 60099 ?
+                         1 : 0)
+                        );
+      tt_assert(found_default_fallback == 0);
+    }
+  }
+
+  /* Case 6: 0110 - DirAuthorities Not Set, AlternateBridgeAuthority &
+     AlternateDirAuthority Set, FallbackDir Not Set */
+  {
+    /* clear fallback dirs counter */
+    n_add_default_fallback_dir_servers_known_default = 0;
+
+    /* clear options*/
+    memset(options, 0, sizeof(or_options_t));
+
+    /* clear any previous dir servers:
+     consider_adding_dir_servers() should do this anyway */
+    clear_dir_servers();
+
+    /* assign options: 0110 */
+    options->DirAuthorities = NULL;
+    options->AlternateBridgeAuthority = test_alt_bridge_authority;
+    options->AlternateDirAuthority = test_alt_dir_authority;
+    options->FallbackDir = NULL;
+
+    /* parse options - ensure we always update by passing NULL old_options */
+    consider_adding_dir_servers(options, NULL);
+
+    /* check outcome */
+
+    /* we must not have added the default fallback dirs */
+    tt_assert(n_add_default_fallback_dir_servers_known_default == 0);
+
+    {
+      /* trusted_dir_servers */
+      const smartlist_t *dir_servers = router_get_trusted_dir_servers();
+      /* (No D0), B1, A2 */
+      tt_assert(smartlist_len(dir_servers) == 2);
+
+      /* (No DirAuthority) - D0 - dir_port: 60090 */
+      int found_D0 = 0;
+      SMARTLIST_FOREACH(dir_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_D0 +=
+                        (ds->dir_port == 60090 ?
+                         1 : 0)
+                        );
+      tt_assert(found_D0 == 0);
+
+      /* AlternateBridgeAuthority - B1 - dir_port: 60091 */
+      int found_B1 = 0;
+      SMARTLIST_FOREACH(dir_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_B1 +=
+                        (ds->dir_port == 60091 ?
+                         1 : 0)
+                        );
+      tt_assert(found_B1 == 1);
+
+      /* AlternateDirAuthority - A2 - dir_port: 60092 */
+      int found_A2 = 0;
+      SMARTLIST_FOREACH(dir_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_A2 +=
+                        (ds->dir_port == 60092 ?
+                         1 : 0)
+                        );
+      tt_assert(found_A2 == 1);
+    }
+
+    {
+      /* fallback_dir_servers */
+      const smartlist_t *fallback_servers = router_get_fallback_dir_servers();
+      /* (No D0), B1, A2, (No Fallback) */
+      tt_assert(smartlist_len(fallback_servers) == 2);
+
+      /* (No DirAuthority) - D0 - dir_port: 60090 */
+      int found_D0 = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_D0 +=
+                        (ds->dir_port == 60090 ?
+                         1 : 0)
+                        );
+      tt_assert(found_D0 == 0);
+
+      /* AlternateBridgeAuthority - B1 - dir_port: 60091 */
+      int found_B1 = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_B1 +=
+                        (ds->dir_port == 60091 ?
+                         1 : 0)
+                        );
+      tt_assert(found_B1 == 1);
+
+      /* AlternateDirAuthority - A2 - dir_port: 60092 */
+      int found_A2 = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_A2 +=
+                        (ds->dir_port == 60092 ?
+                         1 : 0)
+                        );
+      tt_assert(found_A2 == 1);
+
+      /* (No Custom FallbackDir) - No Nickname - dir_port: 60093 */
+      int found_non_default_fallback = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_non_default_fallback +=
+                        (ds->dir_port == 60093 ?
+                         1 : 0)
+                        );
+      tt_assert(found_non_default_fallback == 0);
+
+      /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */
+      int found_default_fallback = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_default_fallback +=
+                        (ds->dir_port == 60099 ?
+                         1 : 0)
+                        );
+      tt_assert(found_default_fallback == 0);
+    }
+  }
+
+  /*
+   2. Outcome: Use Set Bridge Authority
+     - Use Default Non-Bridge Directory Authorities
+     - Use FallbackDir if it is set, otherwise use default FallbackDir
+     Cases expected to yield this outcome:
+       4 & 5 (the 2 cases where DirAuthorities is NULL,
+              AlternateBridgeAuthority is set, and
+              AlternateDirAuthority is NULL)
+  */
+
+  /* Case 5: 0101 - DirAuthorities Not Set, AlternateBridgeAuthority Set,
+     AlternateDirAuthority Not Set, FallbackDir Set */
+  {
+    /* clear fallback dirs counter */
+    n_add_default_fallback_dir_servers_known_default = 0;
+
+    /* clear options*/
+    memset(options, 0, sizeof(or_options_t));
+
+    /* clear any previous dir servers:
+     consider_adding_dir_servers() should do this anyway */
+    clear_dir_servers();
+
+    /* assign options: 0101 */
+    options->DirAuthorities = NULL;
+    options->AlternateBridgeAuthority = test_alt_bridge_authority;
+    options->AlternateDirAuthority = NULL;
+    options->FallbackDir = test_fallback_directory;
+
+    /* parse options - ensure we always update by passing NULL old_options */
+    consider_adding_dir_servers(options, NULL);
+
+    /* check outcome */
+
+    /* we must not have added the default fallback dirs */
+    tt_assert(n_add_default_fallback_dir_servers_known_default == 0);
+
+    {
+      /* trusted_dir_servers */
+      const smartlist_t *dir_servers = router_get_trusted_dir_servers();
+      /* (No D0), B1, (No A2), Default v3 Non-Bridge Authorities */
+      tt_assert(smartlist_len(dir_servers) == 1 + n_default_alt_dir_authority);
+
+      /* (No DirAuthorities) - D0 - dir_port: 60090 */
+      int found_D0 = 0;
+      SMARTLIST_FOREACH(dir_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_D0 +=
+                        (ds->dir_port == 60090 ?
+                         1 : 0)
+                        );
+      tt_assert(found_D0 == 0);
+
+      /* AlternateBridgeAuthority - B1 - dir_port: 60091 */
+      int found_B1 = 0;
+      SMARTLIST_FOREACH(dir_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_B1 +=
+                        (ds->dir_port == 60091 ?
+                         1 : 0)
+                        );
+      tt_assert(found_B1 == 1);
+
+      /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */
+      int found_A2 = 0;
+      SMARTLIST_FOREACH(dir_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_A2 +=
+                        (ds->dir_port == 60092 ?
+                         1 : 0)
+                        );
+      tt_assert(found_A2 == 0);
+
+      /* There's no easy way of checking that we have included all the
+       * default v3 non-Bridge directory authorities, so let's assume that
+       * if the total count above is correct, we have the right ones.
+       */
+    }
+
+    {
+      /* fallback_dir_servers */
+      const smartlist_t *fallback_servers = router_get_fallback_dir_servers();
+      /* (No D0), B1, (No A2), Default v3 Non-Bridge Authorities,
+       * Custom Fallback */
+      tt_assert(smartlist_len(fallback_servers) ==
+                2 + n_default_alt_dir_authority);
+
+      /* (No DirAuthorities) - D0 - dir_port: 60090 */
+      int found_D0 = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_D0 +=
+                        (ds->dir_port == 60090 ?
+                         1 : 0)
+                        );
+      tt_assert(found_D0 == 0);
+
+      /* AlternateBridgeAuthority - B1 - dir_port: 60091 */
+      int found_B1 = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_B1 +=
+                        (ds->dir_port == 60091 ?
+                         1 : 0)
+                        );
+      tt_assert(found_B1 == 1);
+
+      /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */
+      int found_A2 = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_A2 +=
+                        (ds->dir_port == 60092 ?
+                         1 : 0)
+                        );
+      tt_assert(found_A2 == 0);
+
+      /* Custom FallbackDir - No Nickname - dir_port: 60093 */
+      int found_non_default_fallback = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_non_default_fallback +=
+                        (ds->dir_port == 60093 ?
+                         1 : 0)
+                        );
+      tt_assert(found_non_default_fallback == 1);
+
+      /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */
+      int found_default_fallback = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_default_fallback +=
+                        (ds->dir_port == 60099 ?
+                         1 : 0)
+                        );
+      tt_assert(found_default_fallback == 0);
+
+      /* There's no easy way of checking that we have included all the
+       * default v3 non-Bridge directory authorities, so let's assume that
+       * if the total count above is correct, we have the right ones.
+       */
+    }
+  }
+
+  /* Case 4: 0100 - DirAuthorities Not Set, AlternateBridgeAuthority Set,
+   AlternateDirAuthority & FallbackDir Not Set */
+  {
+    /* clear fallback dirs counter */
+    n_add_default_fallback_dir_servers_known_default = 0;
+
+    /* clear options*/
+    memset(options, 0, sizeof(or_options_t));
+
+    /* clear any previous dir servers:
+     consider_adding_dir_servers() should do this anyway */
+    clear_dir_servers();
+
+    /* assign options: 0100 */
+    options->DirAuthorities = NULL;
+    options->AlternateBridgeAuthority = test_alt_bridge_authority;
+    options->AlternateDirAuthority = NULL;
+    options->FallbackDir = NULL;
+
+    /* parse options - ensure we always update by passing NULL old_options */
+    consider_adding_dir_servers(options, NULL);
+
+    /* check outcome */
+
+    /* we must have added the default fallback dirs */
+    tt_assert(n_add_default_fallback_dir_servers_known_default == 1);
+
+    {
+      /* trusted_dir_servers */
+      const smartlist_t *dir_servers = router_get_trusted_dir_servers();
+      /* (No D0), B1, (No A2), Default v3 Non-Bridge Authorities */
+      tt_assert(smartlist_len(dir_servers) == 1 + n_default_alt_dir_authority);
+
+      /* (No DirAuthorities) - D0 - dir_port: 60090 */
+      int found_D0 = 0;
+      SMARTLIST_FOREACH(dir_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_D0 +=
+                        (ds->dir_port == 60090 ?
+                         1 : 0)
+                        );
+      tt_assert(found_D0 == 0);
+
+      /* AlternateBridgeAuthority - B1 - dir_port: 60091 */
+      int found_B1 = 0;
+      SMARTLIST_FOREACH(dir_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_B1 +=
+                        (ds->dir_port == 60091 ?
+                         1 : 0)
+                        );
+      tt_assert(found_B1 == 1);
+
+      /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */
+      int found_A2 = 0;
+      SMARTLIST_FOREACH(dir_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_A2 +=
+                        (ds->dir_port == 60092 ?
+                         1 : 0)
+                        );
+      tt_assert(found_A2 == 0);
+
+      /* There's no easy way of checking that we have included all the
+       * default v3 non-Bridge directory authorities, so let's assume that
+       * if the total count above is correct, we have the right ones.
+       */
+    }
+
+    {
+      /* fallback_dir_servers */
+      const smartlist_t *fallback_servers = router_get_fallback_dir_servers();
+      /* (No D0), B1, (No A2), Default v3 Non-Bridge Authorities,
+       * Default Fallback */
+      tt_assert(smartlist_len(fallback_servers) ==
+                2 + n_default_alt_dir_authority);
+
+      /* (No DirAuthorities) - D0 - dir_port: 60090 */
+      int found_D0 = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_D0 +=
+                        (ds->dir_port == 60090 ?
+                         1 : 0)
+                        );
+      tt_assert(found_D0 == 0);
+
+      /* AlternateBridgeAuthority - B1 - dir_port: 60091 */
+      int found_B1 = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_B1 +=
+                        (ds->dir_port == 60091 ?
+                         1 : 0)
+                        );
+      tt_assert(found_B1 == 1);
+
+      /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */
+      int found_A2 = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_A2 +=
+                        (ds->dir_port == 60092 ?
+                         1 : 0)
+                        );
+      tt_assert(found_A2 == 0);
+
+      /* (No Custom FallbackDir) - No Nickname - dir_port: 60093 */
+      int found_non_default_fallback = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_non_default_fallback +=
+                        (ds->dir_port == 60093 ?
+                         1 : 0)
+                        );
+      tt_assert(found_non_default_fallback == 0);
+
+      /* Default FallbackDir - No Nickname - dir_port: 60099 */
+      int found_default_fallback = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_default_fallback +=
+                        (ds->dir_port == 60099 ?
+                         1 : 0)
+                        );
+      tt_assert(found_default_fallback == 1);
+
+      /* There's no easy way of checking that we have included all the
+       * default v3 non-Bridge directory authorities, so let's assume that
+       * if the total count above is correct, we have the right ones.
+       */
+    }
+  }
+
+  /*
+   3. Outcome: Use Set Alternate Directory Authority
+     - Use Default Bridge Authorities
+     - Use FallbackDir if it is set, otherwise No Default Fallback Directories
+     Cases expected to yield this outcome:
+       2 & 3 (the 2 cases where DirAuthorities and AlternateBridgeAuthority
+              are both NULL, but AlternateDirAuthority is set)
+  */
+
+  /* Case 3: 0011 - DirAuthorities & AlternateBridgeAuthority Not Set,
+     AlternateDirAuthority & FallbackDir Set */
+  {
+    /* clear fallback dirs counter */
+    n_add_default_fallback_dir_servers_known_default = 0;
+
+    /* clear options*/
+    memset(options, 0, sizeof(or_options_t));
+
+    /* clear any previous dir servers:
+     consider_adding_dir_servers() should do this anyway */
+    clear_dir_servers();
+
+    /* assign options: 0011 */
+    options->DirAuthorities = NULL;
+    options->AlternateBridgeAuthority = NULL;
+    options->AlternateDirAuthority = test_alt_dir_authority;
+    options->FallbackDir = test_fallback_directory;
+
+    /* parse options - ensure we always update by passing NULL old_options */
+    consider_adding_dir_servers(options, NULL);
+
+    /* check outcome */
+
+    /* we must not have added the default fallback dirs */
+    tt_assert(n_add_default_fallback_dir_servers_known_default == 0);
+
+    {
+      /* trusted_dir_servers */
+      const smartlist_t *dir_servers = router_get_trusted_dir_servers();
+      /* (No D0), (No B1), Default Bridge Authorities, A2 */
+      tt_assert(smartlist_len(dir_servers) ==
+                1 + n_default_alt_bridge_authority);
+
+      /* (No DirAuthorities) - D0 - dir_port: 60090 */
+      int found_D0 = 0;
+      SMARTLIST_FOREACH(dir_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_D0 +=
+                        (ds->dir_port == 60090 ?
+                         1 : 0)
+                        );
+      tt_assert(found_D0 == 0);
+
+      /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */
+      int found_B1 = 0;
+      SMARTLIST_FOREACH(dir_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_B1 +=
+                        (ds->dir_port == 60091 ?
+                         1 : 0)
+                        );
+      tt_assert(found_B1 == 0);
+
+      /* AlternateDirAuthority - A2 - dir_port: 60092 */
+      int found_A2 = 0;
+      SMARTLIST_FOREACH(dir_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_A2 +=
+                        (ds->dir_port == 60092 ?
+                         1 : 0)
+                        );
+      tt_assert(found_A2 == 1);
+
+      /* There's no easy way of checking that we have included all the
+       * default Bridge authorities (except for hard-coding tonga's details),
+       * so let's assume that if the total count above is correct,
+       * we have the right ones.
+       */
+    }
+
+    {
+      /* fallback_dir_servers */
+      const smartlist_t *fallback_servers = router_get_fallback_dir_servers();
+      /* (No D0), (No B1), Default Bridge Authorities, A2,
+       * Custom Fallback Directory, (No Default Fallback Directories) */
+      tt_assert(smartlist_len(fallback_servers) ==
+                2 + n_default_alt_bridge_authority);
+
+      /* (No DirAuthorities) - D0 - dir_port: 60090 */
+      int found_D0 = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_D0 +=
+                        (ds->dir_port == 60090 ?
+                         1 : 0)
+                        );
+      tt_assert(found_D0 == 0);
+
+      /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */
+      int found_B1 = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_B1 +=
+                        (ds->dir_port == 60091 ?
+                         1 : 0)
+                        );
+      tt_assert(found_B1 == 0);
+
+      /* AlternateDirAuthority - A2 - dir_port: 60092 */
+      int found_A2 = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_A2 +=
+                        (ds->dir_port == 60092 ?
+                         1 : 0)
+                        );
+      tt_assert(found_A2 == 1);
+
+      /* Custom FallbackDir - No Nickname - dir_port: 60093 */
+      int found_non_default_fallback = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_non_default_fallback +=
+                        (ds->dir_port == 60093 ?
+                         1 : 0)
+                        );
+      tt_assert(found_non_default_fallback == 1);
+
+      /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */
+      int found_default_fallback = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_default_fallback +=
+                        (ds->dir_port == 60099 ?
+                         1 : 0)
+                        );
+      tt_assert(found_default_fallback == 0);
+
+      /* There's no easy way of checking that we have included all the
+       * default Bridge authorities (except for hard-coding tonga's details),
+       * so let's assume that if the total count above is correct,
+       * we have the right ones.
+       */
+    }
+  }
+
+  /* Case 2: 0010 - DirAuthorities & AlternateBridgeAuthority Not Set,
+   AlternateDirAuthority Set, FallbackDir Not Set */
+  {
+    /* clear fallback dirs counter */
+    n_add_default_fallback_dir_servers_known_default = 0;
+
+    /* clear options*/
+    memset(options, 0, sizeof(or_options_t));
+
+    /* clear any previous dir servers:
+     consider_adding_dir_servers() should do this anyway */
+    clear_dir_servers();
+
+    /* assign options: 0010 */
+    options->DirAuthorities = NULL;
+    options->AlternateBridgeAuthority = NULL;
+    options->AlternateDirAuthority = test_alt_dir_authority;
+    options->FallbackDir = NULL;
+
+    /* parse options - ensure we always update by passing NULL old_options */
+    consider_adding_dir_servers(options, NULL);
+
+    /* check outcome */
+
+    /* we must not have added the default fallback dirs */
+    tt_assert(n_add_default_fallback_dir_servers_known_default == 0);
+
+    {
+      /* trusted_dir_servers */
+      const smartlist_t *dir_servers = router_get_trusted_dir_servers();
+      /* (No D0), (No B1), Default Bridge Authorities, A2,
+       * No Default or Custom Fallback Directories */
+      tt_assert(smartlist_len(dir_servers) ==
+                1 + n_default_alt_bridge_authority);
+
+      /* (No DirAuthorities) - D0 - dir_port: 60090 */
+      int found_D0 = 0;
+      SMARTLIST_FOREACH(dir_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_D0 +=
+                        (ds->dir_port == 60090 ?
+                         1 : 0)
+                        );
+      tt_assert(found_D0 == 0);
+
+      /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */
+      int found_B1 = 0;
+      SMARTLIST_FOREACH(dir_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_B1 +=
+                        (ds->dir_port == 60091 ?
+                         1 : 0)
+                        );
+      tt_assert(found_B1 == 0);
+
+      /* AlternateDirAuthority - A2 - dir_port: 60092 */
+      int found_A2 = 0;
+      SMARTLIST_FOREACH(dir_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_A2 +=
+                        (ds->dir_port == 60092 ?
+                         1 : 0)
+                        );
+      tt_assert(found_A2 == 1);
+
+      /* There's no easy way of checking that we have included all the
+       * default Bridge authorities (except for hard-coding tonga's details),
+       * so let's assume that if the total count above is correct,
+       * we have the right ones.
+       */
+    }
+
+    {
+      /* fallback_dir_servers */
+      const smartlist_t *fallback_servers = router_get_fallback_dir_servers();
+      /* (No D0), (No B1), Default Bridge Authorities, A2,
+       * No Custom or Default Fallback Directories */
+      tt_assert(smartlist_len(fallback_servers) ==
+                1 + n_default_alt_bridge_authority);
+
+      /* (No DirAuthorities) - D0 - dir_port: 60090 */
+      int found_D0 = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_D0 +=
+                        (ds->dir_port == 60090 ?
+                         1 : 0)
+                        );
+      tt_assert(found_D0 == 0);
+
+      /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */
+      int found_B1 = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_B1 +=
+                        (ds->dir_port == 60091 ?
+                         1 : 0)
+                        );
+      tt_assert(found_B1 == 0);
+
+      /* AlternateDirAuthority - A2 - dir_port: 60092 */
+      int found_A2 = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_A2 +=
+                        (ds->dir_port == 60092 ?
+                         1 : 0)
+                        );
+      tt_assert(found_A2 == 1);
+
+      /* (No Custom FallbackDir) - No Nickname - dir_port: 60093 */
+      int found_non_default_fallback = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_non_default_fallback +=
+                        (ds->dir_port == 60093 ?
+                         1 : 0)
+                        );
+      tt_assert(found_non_default_fallback == 0);
+
+      /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */
+      int found_default_fallback = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_default_fallback +=
+                        (ds->dir_port == 60099 ?
+                         1 : 0)
+                        );
+      tt_assert(found_default_fallback == 0);
+
+      /* There's no easy way of checking that we have included all the
+       * default Bridge authorities (except for hard-coding tonga's details),
+       * so let's assume that if the total count above is correct,
+       * we have the right ones.
+       */
+    }
+  }
+
+  /*
+   4. Outcome: Use Set Custom Fallback Directory
+     - Use Default Bridge & Directory Authorities
+     Cases expected to yield this outcome:
+       1 (DirAuthorities, AlternateBridgeAuthority and AlternateDirAuthority
+          are all NULL, but FallbackDir is set)
+  */
+
+  /* Case 1: 0001 - DirAuthorities, AlternateBridgeAuthority
+    & AlternateDirAuthority Not Set, FallbackDir Set */
+  {
+    /* clear fallback dirs counter */
+    n_add_default_fallback_dir_servers_known_default = 0;
+
+    /* clear options*/
+    memset(options, 0, sizeof(or_options_t));
+
+    /* clear any previous dir servers:
+     consider_adding_dir_servers() should do this anyway */
+    clear_dir_servers();
+
+    /* assign options: 0001 */
+    options->DirAuthorities = NULL;
+    options->AlternateBridgeAuthority = NULL;
+    options->AlternateDirAuthority = NULL;
+    options->FallbackDir = test_fallback_directory;
+
+    /* parse options - ensure we always update by passing NULL old_options */
+    consider_adding_dir_servers(options, NULL);
+
+    /* check outcome */
+
+    /* we must not have added the default fallback dirs */
+    tt_assert(n_add_default_fallback_dir_servers_known_default == 0);
+
+    {
+      /* trusted_dir_servers */
+      const smartlist_t *dir_servers = router_get_trusted_dir_servers();
+      /* (No D0), (No B1), Default Bridge Authorities,
+       * (No A2), Default v3 Directory Authorities */
+      tt_assert(smartlist_len(dir_servers) == n_default_authorities);
+
+      /* (No DirAuthorities) - D0 - dir_port: 60090 */
+      int found_D0 = 0;
+      SMARTLIST_FOREACH(dir_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_D0 +=
+                        (ds->dir_port == 60090 ?
+                         1 : 0)
+                        );
+      tt_assert(found_D0 == 0);
+
+      /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */
+      int found_B1 = 0;
+      SMARTLIST_FOREACH(dir_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_B1 +=
+                        (ds->dir_port == 60091 ?
+                         1 : 0)
+                        );
+      tt_assert(found_B1 == 0);
+
+      /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */
+      int found_A2 = 0;
+      SMARTLIST_FOREACH(dir_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_A2 +=
+                        (ds->dir_port == 60092 ?
+                         1 : 0)
+                        );
+      tt_assert(found_A2 == 0);
+
+      /* There's no easy way of checking that we have included all the
+       * default Bridge & V3 Directory authorities, so let's assume that
+       * if the total count above is correct, we have the right ones.
+       */
+    }
+
+    {
+      /* fallback_dir_servers */
+      const smartlist_t *fallback_servers = router_get_fallback_dir_servers();
+      /* (No D0), (No B1), Default Bridge Authorities,
+       * (No A2), Default v3 Directory Authorities,
+       * Custom Fallback Directory, (No Default Fallback Directories) */
+      tt_assert(smartlist_len(fallback_servers) ==
+                1 + n_default_authorities);
+
+      /* (No DirAuthorities) - D0 - dir_port: 60090 */
+      int found_D0 = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_D0 +=
+                        (ds->dir_port == 60090 ?
+                         1 : 0)
+                        );
+      tt_assert(found_D0 == 0);
+
+      /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */
+      int found_B1 = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_B1 +=
+                        (ds->dir_port == 60091 ?
+                         1 : 0)
+                        );
+      tt_assert(found_B1 == 0);
+
+      /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */
+      int found_A2 = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_A2 +=
+                        (ds->dir_port == 60092 ?
+                         1 : 0)
+                        );
+      tt_assert(found_A2 == 0);
+
+      /* Custom FallbackDir - No Nickname - dir_port: 60093 */
+      int found_non_default_fallback = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_non_default_fallback +=
+                        (ds->dir_port == 60093 ?
+                         1 : 0)
+                        );
+      tt_assert(found_non_default_fallback == 1);
+
+      /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */
+      int found_default_fallback = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_default_fallback +=
+                        (ds->dir_port == 60099 ?
+                         1 : 0)
+                        );
+      tt_assert(found_default_fallback == 0);
+
+      /* There's no easy way of checking that we have included all the
+       * default Bridge & V3 Directory authorities, so let's assume that
+       * if the total count above is correct, we have the right ones.
+       */
+    }
+  }
+
+  /*
+   5. Outcome: Use All Defaults
+     - Use Default Bridge & Directory Authorities, Default Fallback Directories
+     Cases expected to yield this outcome:
+       0 (DirAuthorities, AlternateBridgeAuthority, AlternateDirAuthority
+          and FallbackDir are all NULL)
+  */
+
+  /* Case 0: 0000 - All Not Set */
+  {
+    /* clear fallback dirs counter */
+    n_add_default_fallback_dir_servers_known_default = 0;
+
+    /* clear options*/
+    memset(options, 0, sizeof(or_options_t));
+
+    /* clear any previous dir servers:
+     consider_adding_dir_servers() should do this anyway */
+    clear_dir_servers();
+
+    /* assign options: 0001 */
+    options->DirAuthorities = NULL;
+    options->AlternateBridgeAuthority = NULL;
+    options->AlternateDirAuthority = NULL;
+    options->FallbackDir = NULL;
+
+    /* parse options - ensure we always update by passing NULL old_options */
+    consider_adding_dir_servers(options, NULL);
+
+    /* check outcome */
+
+    /* we must have added the default fallback dirs */
+    tt_assert(n_add_default_fallback_dir_servers_known_default == 1);
+
+    {
+      /* trusted_dir_servers */
+      const smartlist_t *dir_servers = router_get_trusted_dir_servers();
+      /* (No D0), (No B1), Default Bridge Authorities,
+       * (No A2), Default v3 Directory Authorities */
+      tt_assert(smartlist_len(dir_servers) == n_default_authorities);
+
+      /* (No DirAuthorities) - D0 - dir_port: 60090 */
+      int found_D0 = 0;
+      SMARTLIST_FOREACH(dir_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_D0 +=
+                        (ds->dir_port == 60090 ?
+                         1 : 0)
+                        );
+      tt_assert(found_D0 == 0);
+
+      /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */
+      int found_B1 = 0;
+      SMARTLIST_FOREACH(dir_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_B1 +=
+                        (ds->dir_port == 60091 ?
+                         1 : 0)
+                        );
+      tt_assert(found_B1 == 0);
+
+      /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */
+      int found_A2 = 0;
+      SMARTLIST_FOREACH(dir_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_A2 +=
+                        (ds->dir_port == 60092 ?
+                         1 : 0)
+                        );
+      tt_assert(found_A2 == 0);
+
+      /* There's no easy way of checking that we have included all the
+       * default Bridge & V3 Directory authorities, so let's assume that
+       * if the total count above is correct, we have the right ones.
+       */
+    }
+
+    {
+      /* fallback_dir_servers */
+      const smartlist_t *fallback_servers = router_get_fallback_dir_servers();
+      /* (No D0), (No B1), Default Bridge Authorities,
+       * (No A2), Default v3 Directory Authorities,
+       * (No Custom Fallback Directory), Default Fallback Directories */
+      tt_assert(smartlist_len(fallback_servers) ==
+                n_default_authorities + n_default_fallback_dir);
+
+      /* (No DirAuthorities) - D0 - dir_port: 60090 */
+      int found_D0 = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_D0 +=
+                        (ds->dir_port == 60090 ?
+                         1 : 0)
+                        );
+      tt_assert(found_D0 == 0);
+
+      /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */
+      int found_B1 = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_B1 +=
+                        (ds->dir_port == 60091 ?
+                         1 : 0)
+                        );
+      tt_assert(found_B1 == 0);
+
+      /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */
+      int found_A2 = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_A2 +=
+                        (ds->dir_port == 60092 ?
+                         1 : 0)
+                        );
+      tt_assert(found_A2 == 0);
+
+      /* Custom FallbackDir - No Nickname - dir_port: 60093 */
+      int found_non_default_fallback = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_non_default_fallback +=
+                        (ds->dir_port == 60093 ?
+                         1 : 0)
+                        );
+      tt_assert(found_non_default_fallback == 0);
+
+      /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */
+      int found_default_fallback = 0;
+      SMARTLIST_FOREACH(fallback_servers,
+                        dir_server_t *,
+                        ds,
+                        /* increment the found counter if dir_port matches */
+                        found_default_fallback +=
+                        (ds->dir_port == 60099 ?
+                         1 : 0)
+                        );
+      tt_assert(found_default_fallback == 1);
+
+      /* There's no easy way of checking that we have included all the
+       * default Bridge & V3 Directory authorities, and the default
+       * Fallback Directories, so let's assume that if the total count
+       * above is correct, we have the right ones.
+       */
+    }
+  }
+
+  done:
+  clear_dir_servers();
+
+  tor_free(test_dir_authority->key);
+  tor_free(test_dir_authority->value);
+  tor_free(test_dir_authority);
+
+  tor_free(test_alt_dir_authority->key);
+  tor_free(test_alt_dir_authority->value);
+  tor_free(test_alt_dir_authority);
+
+  tor_free(test_alt_bridge_authority->key);
+  tor_free(test_alt_bridge_authority->value);
+  tor_free(test_alt_bridge_authority);
+
+  tor_free(test_fallback_directory->key);
+  tor_free(test_fallback_directory->value);
+  tor_free(test_fallback_directory);
+
+  options->DirAuthorities = NULL;
+  options->AlternateBridgeAuthority = NULL;
+  options->AlternateDirAuthority = NULL;
+  options->FallbackDir = NULL;
+  or_options_free(options);
+
+  UNMOCK(add_default_fallback_dir_servers);
+}
+
 #define CONFIG_TEST(name, flags)                          \
 #define CONFIG_TEST(name, flags)                          \
   { #name, test_config_ ## name, flags, NULL, NULL }
   { #name, test_config_ ## name, flags, NULL, NULL }
 
 
 struct testcase_t config_tests[] = {
 struct testcase_t config_tests[] = {
+  CONFIG_TEST(adding_dir_servers, TT_FORK),
   CONFIG_TEST(resolve_my_address, TT_FORK),
   CONFIG_TEST(resolve_my_address, TT_FORK),
   CONFIG_TEST(addressmap, 0),
   CONFIG_TEST(addressmap, 0),
   CONFIG_TEST(parse_bridge_line, 0),
   CONFIG_TEST(parse_bridge_line, 0),