[tor-commits] [tor/master] Adding comprehensive test cases for resolve_my_address.

nickm at torproject.org nickm at torproject.org
Mon Dec 29 15:02:16 UTC 2014


commit 28217b969eec213e7eb01bc8382fb1236eb4bbdd
Author: rl1987 <rl1987 at sdf.lonestar.org>
Date:   Mon Apr 28 23:20:58 2014 +0300

    Adding comprehensive test cases for resolve_my_address.
    
    Also, improve comments on resolve_my_address to explain what it
    actually does.
---
 src/common/address.c   |    8 +-
 src/common/address.h   |    5 +-
 src/common/compat.c    |   20 +-
 src/common/compat.h    |    3 +-
 src/or/config.c        |   36 ++-
 src/test/test_config.c |  569 ++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 628 insertions(+), 13 deletions(-)

diff --git a/src/common/address.c b/src/common/address.c
index e5930de..c9b5cf4 100644
--- a/src/common/address.c
+++ b/src/common/address.c
@@ -1354,8 +1354,8 @@ tor_addr_is_multicast(const tor_addr_t *a)
  * connects to the Internet.  This address should only be used in checking
  * whether our address has changed.  Return 0 on success, -1 on failure.
  */
-int
-get_interface_address6(int severity, sa_family_t family, tor_addr_t *addr)
+MOCK_IMPL(int,
+get_interface_address6,(int severity, sa_family_t family, tor_addr_t *addr))
 {
   /* XXX really, this function should yield a smartlist of addresses. */
   smartlist_t *addrs;
@@ -1684,8 +1684,8 @@ tor_dup_ip(uint32_t addr)
  * checking whether our address has changed.  Return 0 on success, -1 on
  * failure.
  */
-int
-get_interface_address(int severity, uint32_t *addr)
+MOCK_IMPL(int,
+get_interface_address,(int severity, uint32_t *addr))
 {
   tor_addr_t local_addr;
   int r;
diff --git a/src/common/address.h b/src/common/address.h
index 8dc63b7..ecb7adc 100644
--- a/src/common/address.h
+++ b/src/common/address.h
@@ -148,7 +148,8 @@ char *tor_dup_addr(const tor_addr_t *addr) ATTR_MALLOC;
 const char *fmt_addr_impl(const tor_addr_t *addr, int decorate);
 const char *fmt_addrport(const tor_addr_t *addr, uint16_t port);
 const char * fmt_addr32(uint32_t addr);
-int get_interface_address6(int severity, sa_family_t family, tor_addr_t *addr);
+MOCK_DECL(int,get_interface_address6,(int severity, sa_family_t family,
+tor_addr_t *addr));
 
 /** Flag to specify how to do a comparison between addresses.  In an "exact"
  * comparison, addresses are equivalent only if they are in the same family
@@ -225,7 +226,7 @@ int addr_mask_get_bits(uint32_t mask);
 #define INET_NTOA_BUF_LEN 16
 int tor_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len);
 char *tor_dup_ip(uint32_t addr) ATTR_MALLOC;
-int get_interface_address(int severity, uint32_t *addr);
+MOCK_DECL(int,get_interface_address,(int severity, uint32_t *addr));
 
 tor_addr_port_t *tor_addr_port_new(const tor_addr_t *addr, uint16_t port);
 
diff --git a/src/common/compat.c b/src/common/compat.c
index 470e860..9b040f1 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -2061,9 +2061,20 @@ get_environment(void)
 #endif
 }
 
+/** Get name of current host and write it to <b>name</b> array, whose
+ * length is specified by <b>namelen</b> argument. Return 0 upon
+ * successfull completion; otherwise return return -1. (Currently,
+ * this function is merely a mockable wrapper for POSIX gethostname().)
+ */
+MOCK_IMPL(int,
+tor_gethostname,(char *name, size_t namelen))
+{
+   return gethostname(name,namelen);
+}
+
 /** Set *addr to the IP address (in dotted-quad notation) stored in *str.
- * Return 1 on success, 0 if *str is badly formatted.  (Like inet_aton(str,addr),
- * but works on Windows and Solaris.)
+ * Return 1 on success, 0 if *str is badly formatted.
+ * (Like inet_aton(str,addr), but works on Windows and Solaris.)
  */
 int
 tor_inet_aton(const char *str, struct in_addr* addr)
@@ -2281,8 +2292,9 @@ tor_inet_pton(int af, const char *src, void *dst)
  * (This function exists because standard windows gethostbyname
  * doesn't treat raw IP addresses properly.)
  */
-int
-tor_lookup_hostname(const char *name, uint32_t *addr)
+
+MOCK_IMPL(int,
+tor_lookup_hostname,(const char *name, uint32_t *addr))
 {
   tor_addr_t myaddr;
   int ret;
diff --git a/src/common/compat.h b/src/common/compat.h
index 9a381fb..4e614c0 100644
--- a/src/common/compat.h
+++ b/src/common/compat.h
@@ -537,10 +537,11 @@ struct sockaddr_in6 {
 };
 #endif
 
+MOCK_DECL(int,tor_gethostname,(char *name, size_t namelen));
 int tor_inet_aton(const char *cp, struct in_addr *addr) ATTR_NONNULL((1,2));
 const char *tor_inet_ntop(int af, const void *src, char *dst, size_t len);
 int tor_inet_pton(int af, const char *src, void *dst);
-int tor_lookup_hostname(const char *name, uint32_t *addr) ATTR_NONNULL((1,2));
+MOCK_DECL(int,tor_lookup_hostname,(const char *name, uint32_t *addr));
 int set_socket_nonblocking(tor_socket_t socket);
 int tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2]);
 int network_init(void);
diff --git a/src/or/config.c b/src/or/config.c
index a5407dd..e0a2460 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -11,6 +11,7 @@
 
 #define CONFIG_PRIVATE
 #include "or.h"
+#include "compat.h"
 #include "addressmap.h"
 #include "channel.h"
 #include "circuitbuild.h"
@@ -2051,7 +2052,33 @@ get_last_resolved_addr(void)
 }
 
 /**
- * Use <b>options-\>Address</b> to guess our public IP address.
+ * Attempt getting our non-local (as judged by tor_addr_is_internal()
+ * function) IP address using following techniques, listed in
+ * order from best (most desirable, try first) to worst (least
+ * desirable, try if everything else fails).
+ *
+ * First, attempt using <b>options-\>Address</b> to get our
+ * non-local IP address.
+ *
+ * If <b>options-\>Address</b> represents a non-local IP address,
+ * consider it ours.
+ *
+ * If <b>options-\>Address</b> is a DNS name that resolves to
+ * a non-local IP address, consider this IP address ours.
+ *
+ * If <b>options-\>Address</b> is NULL, fall back to getting local
+ * hostname and using it in above-described ways to try and
+ * get our IP address.
+ *
+ * In case local hostname cannot be resolved to a non-local IP
+ * address, try getting an IP address of network interface
+ * in hopes it will be non-local one.
+ *
+ * Fail if one or more of the following is true:
+ *   - DNS name in <b>options-\>Address</b> cannot be resolved.
+ *   - <b>options-\>Address</b> is a local host address.
+ *   - Attempt to getting local hostname fails.
+ *   - Attempt to getting network interface address fails.
  *
  * Return 0 if all is well, or -1 if we can't find a suitable
  * public IP address.
@@ -2060,6 +2087,11 @@ get_last_resolved_addr(void)
  *   - Put our public IP address (in host order) into *<b>addr_out</b>.
  *   - If <b>method_out</b> is non-NULL, set *<b>method_out</b> to a static
  *     string describing how we arrived at our answer.
+ *      - "CONFIGURED" - parsed from IP address string in
+ *        <b>options-\>Address</b>
+ *      - "RESOLVED" - resolved from DNS name in <b>options-\>Address</b>
+ *      - "GETHOSTNAME" - resolved from a local hostname.
+ *      - "INTERFACE" - retrieved from a network interface.
  *   - If <b>hostname_out</b> is non-NULL, and we resolved a hostname to
  *     get our address, set *<b>hostname_out</b> to a newly allocated string
  *     holding that hostname. (If we didn't get our address by resolving a
@@ -2098,7 +2130,7 @@ resolve_my_address(int warn_severity, const or_options_t *options,
     explicit_ip = 0; /* it's implicit */
     explicit_hostname = 0; /* it's implicit */
 
-    if (gethostname(hostname, sizeof(hostname)) < 0) {
+    if (tor_gethostname(hostname, sizeof(hostname)) < 0) {
       log_fn(warn_severity, LD_NET,"Error obtaining local hostname");
       return -1;
     }
diff --git a/src/test/test_config.c b/src/test/test_config.c
index dbb5079..fa68129 100644
--- a/src/test/test_config.c
+++ b/src/test/test_config.c
@@ -578,10 +578,579 @@ test_config_fix_my_family(void *arg)
     or_options_free(defaults);
 }
 
+static int n_hostname_01010101 = 0;
+
+/** This mock function is meant to replace tor_lookup_hostname().
+ * It answers with 1.1.1.1 as IP adddress that resulted from lookup.
+ * This function increments <b>n_hostname_01010101</b> counter by one
+ * every time it is called.
+ */
+static int
+tor_lookup_hostname_01010101(const char *name, uint32_t *addr)
+{
+  n_hostname_01010101++;
+
+  if (name && addr) {
+    *addr = ntohl(0x01010101);
+  }
+
+  return 0;
+}
+
+static int n_hostname_localhost = 0;
+
+/** This mock function is meant to replace tor_lookup_hostname().
+ * It answers with 127.0.0.1 as IP adddress that resulted from lookup.
+ * This function increments <b>n_hostname_localhost</b> counter by one
+ * every time it is called.
+ */
+static int
+tor_lookup_hostname_localhost(const char *name, uint32_t *addr)
+{
+  n_hostname_localhost++;
+
+  if (name && addr) {
+    *addr = 0x7f000001;
+  }
+
+  return 0;
+}
+
+static int n_hostname_failure = 0;
+
+/** This mock function is meant to replace tor_lookup_hostname().
+ * It pretends to fail by returning -1 to caller. Also, this function
+ * increments <b>n_hostname_failure</b> every time it is called.
+ */
+static int
+tor_lookup_hostname_failure(const char *name, uint32_t *addr)
+{
+  (void)name;
+  (void)addr;
+
+  n_hostname_failure++;
+
+  return -1;
+}
+
+static int n_gethostname_replacement = 0;
+
+/** This mock function is meant to replace tor_gethostname(). It
+ * responds with string "onionrouter" as hostname. This function
+ * increments <b>n_gethostname_replacement</b> by one every time
+ * it is called.
+ */
+static int
+tor_gethostname_replacement(char *name, size_t namelen)
+{
+  n_gethostname_replacement++;
+
+  if (name && namelen) {
+    strlcpy(name,"onionrouter",namelen);
+  }
+
+  return 0;
+}
+
+static int n_gethostname_localhost = 0;
+
+/** This mock function is meant to replace tor_gethostname(). It
+ * responds with string "127.0.0.1" as hostname. This function
+ * increments <b>n_gethostname_localhost</b> by one every time
+ * it is called.
+ */
+static int
+tor_gethostname_localhost(char *name, size_t namelen)
+{
+  n_gethostname_localhost++;
+
+  if (name && namelen) {
+    strlcpy(name,"127.0.0.1",namelen);
+  }
+
+  return 0;
+}
+
+static int n_gethostname_failure = 0;
+
+/** This mock function is meant to replace tor_gethostname.
+ * It pretends to fail by returning -1. This function increments
+ * <b>n_gethostname_failure</b> by one every time it is called.
+ */
+static int
+tor_gethostname_failure(char *name, size_t namelen)
+{
+  n_gethostname_failure++;
+
+  return -1;
+}
+
+static int n_get_interface_address = 0;
+
+/** This mock function is meant to replace get_interface_address().
+ * It answers with address 8.8.8.8. This function increments
+ * <b>n_get_interface_address</b> by one every time it is called.
+ */
+static int
+get_interface_address_08080808(int severity, uint32_t *addr)
+{
+  (void)severity;
+
+  n_get_interface_address++;
+
+  if (addr) {
+    *addr = ntohl(0x08080808);
+  }
+
+  return 0;
+}
+
+static int n_get_interface_address6 = 0;
+static sa_family_t last_address6_family;
+
+/** This mock function is meant to replace get_interface_address6().
+ * It answers with IP address 9.9.9.9 iff both of the following are true:
+ *  - <b>family</b> is AF_INET
+ *  - <b>addr</b> pointer is not NULL.
+ * This function increments <b>n_get_interface_address6</b> by one every
+ * time it is called.
+ */
+static int
+get_interface_address6_replacement(int severity, sa_family_t family,
+                                   tor_addr_t *addr)
+{
+  (void)severity;
+
+  last_address6_family = family;
+  n_get_interface_address6++;
+
+  if ((family != AF_INET) || !addr) {
+    return -1;
+  }
+
+  tor_addr_from_ipv4h(addr,0x09090909);
+
+  return 0;
+}
+
+static int n_get_interface_address_failure = 0;
+
+/**
+ * This mock function is meant to replace get_interface_address().
+ * It pretends to fail getting interface address by returning -1.
+ * <b>n_get_interface_address_failure</b> is incremented by one
+ * every time this function is called.
+ */
+static int
+get_interface_address_failure(int severity, uint32_t *addr)
+{
+  (void)severity;
+  (void)addr;
+
+  n_get_interface_address_failure++;
+
+  return -1;
+}
+
+static int n_get_interface_address6_failure = 0;
+
+/**
+ * This mock function is meant to replace get_interface_addres6().
+ * It will pretent to fail by return -1.
+ * <b>n_get_interface_address6_failure</b> is incremented by one
+ * every time this function is called and <b>last_address6_family</b>
+ * is assigned the value of <b>family</b> argument.
+ */
+static int
+get_interface_address6_failure(int severity, sa_family_t family,
+                               tor_addr_t *addr)
+{
+   n_get_interface_address6_failure++;
+   last_address6_family = family;
+
+   return -1;
+}
+
+static void
+test_config_resolve_my_address(void *arg)
+{
+  (void)arg;
+
+  or_options_t *options;
+  uint32_t resolved_addr;
+  const char *method_used;
+  char *hostname_out;
+  int retval;
+  int prev_n_hostname_01010101;
+  int prev_n_hostname_localhost;
+  int prev_n_hostname_failure;
+  int prev_n_gethostname_replacement;
+  int prev_n_gethostname_failure;
+  int prev_n_gethostname_localhost;
+  int prev_n_get_interface_address;
+  int prev_n_get_interface_address_failure;
+  int prev_n_get_interface_address6;
+  int prev_n_get_interface_address6_failure;
+
+  options = options_new();
+
+  options_init(options);
+
+ /*
+  * CASE 1:
+  * If options->Address is a valid IPv4 address string, we want
+  * the corresponding address to be parsed and returned.
+  */
+
+  options->Address = tor_strdup("128.52.128.105");
+
+  retval = resolve_my_address(LOG_NOTICE,options,&resolved_addr,
+                              &method_used,&hostname_out);
+
+  tt_want(retval == 0);
+  tt_want_str_op(method_used,==,"CONFIGURED");
+  tt_want(hostname_out == NULL);
+  tt_assert(htonl(resolved_addr) == 0x69803480);
+
+  tor_free(options->Address);
+
+/*
+ * CASE 2:
+ * If options->Address is a valid DNS address, we want resolve_my_address()
+ * function to ask tor_lookup_hostname() for help with resolving it
+ * and return the address that was resolved (in host order).
+ */
+
+  MOCK(tor_lookup_hostname,tor_lookup_hostname_01010101);
+
+  tor_free(options->Address);
+  options->Address = tor_strdup("www.torproject.org");
+
+  prev_n_hostname_01010101 = n_hostname_01010101;
+
+  retval = resolve_my_address(LOG_NOTICE,options,&resolved_addr,
+                              &method_used,&hostname_out);
+
+  tt_want(retval == 0);
+  tt_want(n_hostname_01010101 == prev_n_hostname_01010101 + 1);
+  tt_want_str_op(method_used,==,"RESOLVED");
+  tt_want_str_op(hostname_out,==,"www.torproject.org");
+  tt_assert(htonl(resolved_addr) == 0x01010101);
+
+  UNMOCK(tor_lookup_hostname);
+
+  tor_free(options->Address);
+
+/*
+ * CASE 3:
+ * Given that options->Address is NULL, we want resolve_my_address()
+ * to try and use tor_gethostname() to get hostname AND use
+ * tor_lookup_hostname() to get IP address.
+ */
+
+  resolved_addr = 0;
+  tor_free(options->Address);
+  options->Address = NULL;
+
+  MOCK(tor_gethostname,tor_gethostname_replacement);
+  MOCK(tor_lookup_hostname,tor_lookup_hostname_01010101);
+
+  prev_n_gethostname_replacement = n_gethostname_replacement;
+  prev_n_hostname_01010101 = n_hostname_01010101;
+
+  retval = resolve_my_address(LOG_NOTICE,options,&resolved_addr,
+                              &method_used,&hostname_out);
+
+  tt_want(retval == 0);
+  tt_want(n_gethostname_replacement == prev_n_gethostname_replacement + 1);
+  tt_want(n_hostname_01010101 == prev_n_hostname_01010101 + 1);
+  tt_want_str_op(method_used,==,"GETHOSTNAME");
+  tt_want_str_op(hostname_out,==,"onionrouter");
+  tt_assert(htonl(resolved_addr) == 0x01010101);
+
+  UNMOCK(tor_gethostname);
+  UNMOCK(tor_lookup_hostname);
+
+/*
+ * CASE 4:
+ * Given that options->Address is a local host address, we want
+ * resolve_my_address() function to fail.
+ */
+
+  resolved_addr = 0;
+  tor_free(options->Address);
+  options->Address = tor_strdup("127.0.0.1");
+
+  retval = resolve_my_address(LOG_NOTICE,options,&resolved_addr,
+                              &method_used,&hostname_out);
+
+  tt_want(resolved_addr == 0);
+  tt_assert(retval == -1);
+
+  tor_free(options->Address);
+
+/*
+ * CASE 5:
+ * We want resolve_my_address() to fail if DNS address in options->Address
+ * cannot be resolved.
+ */
+
+  MOCK(tor_lookup_hostname,tor_lookup_hostname_failure);
+
+  prev_n_hostname_failure = n_hostname_failure;
+
+  tor_free(options->Address);
+  options->Address = tor_strdup("www.tor-project.org");
+
+  retval = resolve_my_address(LOG_NOTICE,options,&resolved_addr,
+                              &method_used,&hostname_out);
+
+  tt_want(n_hostname_failure == prev_n_hostname_failure + 1);
+  tt_assert(retval == -1);
+
+  UNMOCK(tor_lookup_hostname);
+
+  tor_free(options->Address);
+  options->Address = NULL;
+
+/*
+ * CASE 6:
+ * If options->Address is NULL AND gettting local hostname fails, we want
+ * resolve_my_address() to fail as well.
+ */
+
+  MOCK(tor_gethostname,tor_gethostname_failure);
+
+  prev_n_gethostname_failure = n_gethostname_failure;
+
+  retval = resolve_my_address(LOG_NOTICE,options,&resolved_addr,
+                              &method_used,&hostname_out);
+
+  tt_want(n_gethostname_failure == prev_n_gethostname_failure + 1);
+  tt_assert(retval == -1);
+
+  UNMOCK(tor_gethostname);
+
+/*
+ * CASE 7:
+ * We want resolve_my_address() to try and get network interface address via
+ * get_interface_address() if hostname returned by tor_gethostname() cannot be
+ * resolved into IP address.
+ */
+
+  MOCK(tor_gethostname,tor_gethostname_replacement);
+  MOCK(get_interface_address,get_interface_address_08080808);
+
+  prev_n_gethostname_replacement = n_gethostname_replacement;
+  prev_n_get_interface_address = n_get_interface_address;
+
+  retval = resolve_my_address(LOG_NOTICE,options,&resolved_addr,
+                              &method_used,&hostname_out);
+
+  tt_want(retval == 0);
+  tt_want(n_gethostname_replacement == prev_n_gethostname_replacement + 1);
+  tt_want(n_get_interface_address == prev_n_get_interface_address + 1);
+  tt_want_str_op(method_used,==,"INTERFACE");
+  tt_want(hostname_out == NULL);
+  tt_assert(resolved_addr == ntohl(0x08080808));
+
+  UNMOCK(get_interface_address);
+
+/*
+ * CASE 8:
+ * Suppose options->Address is NULL AND hostname returned by tor_gethostname()
+ * is unresolvable. We want resolve_my_address to fail if
+ * get_interface_address() fails.
+ */
+
+  MOCK(get_interface_address,get_interface_address_failure);
+
+  prev_n_get_interface_address_failure = n_get_interface_address_failure;
+  prev_n_gethostname_replacement = n_gethostname_replacement;
+
+  retval = resolve_my_address(LOG_NOTICE,options,&resolved_addr,
+                              &method_used,&hostname_out);
+
+  tt_want(n_get_interface_address_failure ==
+          prev_n_get_interface_address_failure + 1);
+  tt_want(n_gethostname_replacement ==
+          prev_n_gethostname_replacement + 1);
+  tt_assert(retval == -1);
+
+  UNMOCK(get_interface_address);
+
+/*
+ * CASE 9:
+ * Given that options->Address is NULL AND tor_lookup_hostname()
+ * fails AND hostname returned by gethostname() resolves
+ * to local IP address, we want resolve_my_address() function to
+ * call get_interface_address6(.,AF_INET,.) and return IP address
+ * the latter function has found.
+ */
+
+  MOCK(tor_lookup_hostname,tor_lookup_hostname_failure);
+  MOCK(tor_gethostname,tor_gethostname_replacement);
+  MOCK(get_interface_address6,get_interface_address6_replacement);
+
+  prev_n_gethostname_replacement = n_gethostname_replacement;
+  prev_n_hostname_failure = n_hostname_failure;
+  prev_n_get_interface_address6 = n_get_interface_address6;
+
+  retval = resolve_my_address(LOG_NOTICE,options,&resolved_addr,
+                              &method_used,&hostname_out);
+
+  tt_want(last_address6_family == AF_INET);
+  tt_want(n_get_interface_address6 == prev_n_get_interface_address6 + 1);
+  tt_want(n_hostname_failure == prev_n_hostname_failure + 1);
+  tt_want(n_gethostname_replacement == prev_n_gethostname_replacement + 1);
+  tt_want(retval == 0);
+  tt_want_str_op(method_used,==,"INTERFACE");
+  tt_assert(htonl(resolved_addr) == 0x09090909);
+
+  UNMOCK(tor_lookup_hostname);
+  UNMOCK(tor_gethostname);
+  UNMOCK(get_interface_address6);
+
+  /*
+   * CASE 10: We want resolve_my_address() to fail if all of the following
+   * are true:
+   *   1. options->Address is not NULL
+   *   2. ... but it cannot be converted to struct in_addr by
+   *      tor_inet_aton()
+   *   3. ... and tor_lookup_hostname() fails to resolve the
+   *      options->Address
+   */
+
+  MOCK(tor_lookup_hostname,tor_lookup_hostname_failure);
+
+  prev_n_hostname_failure = n_hostname_failure;
+
+  tor_free(options->Address);
+  options->Address = tor_strdup("some_hostname");
+
+  retval = resolve_my_address(LOG_NOTICE, options, &resolved_addr,
+                              &method_used,&hostname_out);
+
+  tt_want(n_hostname_failure == prev_n_hostname_failure + 1);
+  tt_assert(retval == -1);
+
+  UNMOCK(tor_gethostname);
+  UNMOCK(tor_lookup_hostname);
+
+  /*
+   * CASE 11:
+   * Suppose the following sequence of events:
+   *   1. options->Address is NULL
+   *   2. tor_gethostname() succeeds to get hostname of machine Tor
+   *      if running on.
+   *   3. Hostname from previous step cannot be converted to
+   *      address by using tor_inet_aton() function.
+   *   4. However, tor_lookup_hostname() succeds in resolving the
+   *      hostname from step 2.
+   *   5. Unfortunately, tor_addr_is_internal() deems this address
+   *      to be internal.
+   *   6. get_interface_address6(.,AF_INET,.) returns non-internal
+   *      IPv4
+   *
+   *   We want resolve_my_addr() to succeed with method "INTERFACE"
+   *   and address from step 6.
+   */
+
+  tor_free(options->Address);
+  options->Address = NULL;
+
+  MOCK(tor_gethostname,tor_gethostname_replacement);
+  MOCK(tor_lookup_hostname,tor_lookup_hostname_localhost);
+  MOCK(get_interface_address6,get_interface_address6_replacement);
+
+  prev_n_gethostname_replacement = n_gethostname_replacement;
+  prev_n_hostname_localhost = n_hostname_localhost;
+  prev_n_get_interface_address6 = n_get_interface_address6;
+
+  retval = resolve_my_address(LOG_DEBUG, options, &resolved_addr,
+                              &method_used,&hostname_out);
+
+  tt_want(n_gethostname_replacement == prev_n_gethostname_replacement + 1);
+  tt_want(n_hostname_localhost == prev_n_hostname_localhost + 1);
+  tt_want(n_get_interface_address6 == prev_n_get_interface_address6 + 1);
+
+  tt_str_op(method_used,==,"INTERFACE");
+  tt_assert(!hostname_out);
+  tt_assert(retval == 0);
+
+  /*
+   * CASE 11b:
+   *   1-5 as above.
+   *   6. get_interface_address6() fails.
+   *
+   *   In this subcase, we want resolve_my_address() to fail.
+   */
+
+  UNMOCK(get_interface_address6);
+  MOCK(get_interface_address6,get_interface_address6_failure);
+
+  prev_n_gethostname_replacement = n_gethostname_replacement;
+  prev_n_hostname_localhost = n_hostname_localhost;
+  prev_n_get_interface_address6_failure = n_get_interface_address6_failure;
+
+  retval = resolve_my_address(LOG_DEBUG, options, &resolved_addr,
+                              &method_used,&hostname_out);
+
+  tt_want(n_gethostname_replacement == prev_n_gethostname_replacement + 1);
+  tt_want(n_hostname_localhost == prev_n_hostname_localhost + 1);
+  tt_want(n_get_interface_address6_failure ==
+          prev_n_get_interface_address6_failure + 1);
+
+  tt_assert(retval == -1);
+
+  UNMOCK(tor_gethostname);
+  UNMOCK(tor_lookup_hostname);
+  UNMOCK(get_interface_address6);
+
+  /* CASE 12:
+   * Suppose the following happens:
+   *   1. options->Address is NULL AND options->DirAuthorities is 1.
+   *   2. tor_gethostname() succeeds in getting hostname of a machine ...
+   *   3. ... which is successfully parsed by tor_inet_aton() ...
+   *   4. into IPv4 address that tor_addr_is_inernal() considers to be
+   *      internal.
+   *
+   *  In this case, we want resolve_my_address() to fail.
+   */
+
+  tor_free(options->Address);
+  options->Address = NULL;
+  options->DirAuthorities = tor_malloc_zero(sizeof(config_line_t));
+
+  MOCK(tor_gethostname,tor_gethostname_localhost);
+
+  prev_n_gethostname_localhost = n_gethostname_localhost;
+
+  retval = resolve_my_address(LOG_DEBUG, options, &resolved_addr,
+                              &method_used,&hostname_out);
+
+  tt_want(n_gethostname_localhost == prev_n_gethostname_localhost + 1);
+  tt_assert(retval == -1);
+
+  UNMOCK(tor_gethostname);
+
+  done:
+  tor_free(options->Address);
+  tor_free(options->DirAuthorities);
+  or_options_free(options);
+
+  UNMOCK(tor_gethostname);
+  UNMOCK(tor_lookup_hostname);
+  UNMOCK(get_interface_address);
+  UNMOCK(get_interface_address6);
+  UNMOCK(tor_gethostname);
+}
+
 #define CONFIG_TEST(name, flags)                          \
   { #name, test_config_ ## name, flags, NULL, NULL }
 
 struct testcase_t config_tests[] = {
+  CONFIG_TEST(resolve_my_address, TT_FORK),
   CONFIG_TEST(addressmap, 0),
   CONFIG_TEST(parse_bridge_line, 0),
   CONFIG_TEST(parse_transport_options_line, 0),





More information about the tor-commits mailing list