[tor-commits] [tor/master] Fix unit tests on systems without IPv4 or localhost addresses

nickm at torproject.org nickm at torproject.org
Thu Nov 19 16:19:38 UTC 2015


commit 71fd66c8668ae35847fa8868cc34b5a575fa1fea
Author: teor (Tim Wilson-Brown) <teor2345 at gmail.com>
Date:   Wed Nov 18 23:25:21 2015 +1100

    Fix unit tests on systems without IPv4 or localhost addresses
    
    Make unit tests pass on IPv6-only systems, and systems without
    localhost addresses (like some FreeBSD jails).
    
    Fixes:
    * get_if_addrs_ifaddrs: systems without localhost
    * get_if_addrs_ioctl: only works on IPv4 systems
    * socket: check IPv4 and IPv6, skip on EPROTONOSUPPORT
    * socketpair_ersatz: uses IPv4, skip on EPROTONOSUPPORT
    
    Fixes bug #17632; bugfix on unit tests in 0.2.7.3-rc.
    c464a367728d was a partial fix for this issue in #17255;
    it was released in unit tests in 0.2.7.4-rc.
    
    Patch by "teor".
---
 changes/bug17632-no-ipv4-no-localhost |    7 ++++
 src/test/test_address.c               |   65 +++++++++++++++++++++++++++++----
 src/test/test_util.c                  |   37 +++++++++++++++----
 3 files changed, 94 insertions(+), 15 deletions(-)

diff --git a/changes/bug17632-no-ipv4-no-localhost b/changes/bug17632-no-ipv4-no-localhost
new file mode 100644
index 0000000..0462207
--- /dev/null
+++ b/changes/bug17632-no-ipv4-no-localhost
@@ -0,0 +1,7 @@
+  o Minor bugfix (unit tests):
+    - Make unit tests pass on IPv6-only systems, and systems without
+      localhost addresses (like some FreeBSD jails).
+      Fixes bug #17632; bugfix on unit tests in 0.2.7.3-rc.
+      c464a367728d was a partial fix for this issue in #17255;
+      it was released in unit tests in 0.2.7.4-rc.
+      Patch by "teor".
diff --git a/src/test/test_address.c b/src/test/test_address.c
index 7368b05..9f3d81c 100644
--- a/src/test/test_address.c
+++ b/src/test/test_address.c
@@ -119,6 +119,21 @@ smartlist_contains_internal_tor_addr(smartlist_t *smartlist)
 }
 
 /** Return 1 iff <b>smartlist</b> contains a tor_addr_t structure
+ * that is NULL or the null tor_addr_t. Otherwise, return 0.
+ */
+static int
+smartlist_contains_null_tor_addr(smartlist_t *smartlist)
+{
+  SMARTLIST_FOREACH_BEGIN(smartlist, tor_addr_t *, tor_addr) {
+    if (tor_addr == NULL || tor_addr_is_null(tor_addr)) {
+      return 1;
+    }
+  } SMARTLIST_FOREACH_END(tor_addr);
+
+  return 0;
+}
+
+/** Return 1 iff <b>smartlist</b> contains a tor_addr_t structure
  * that is an IPv4 address. Otherwise, return 0.
  */
 static int
@@ -268,8 +283,18 @@ test_address_get_if_addrs_ifaddrs(void *arg)
 
   results = get_interface_addresses_ifaddrs(LOG_ERR);
 
-  tt_int_op(smartlist_len(results),>=,1);
-  tt_assert(smartlist_contains_localhost_tor_addr(results));
+  tt_assert(results);
+  /* Some FreeBSD jails don't have localhost IP address. Instead, they only
+   * have the address assigned to the jail (whatever that may be).
+   * And a jail without a network connection might not have any addresses at
+   * all. */
+  tt_assert(!smartlist_contains_null_tor_addr(results));
+
+  /* If there are addresses, they must be IPv4 or IPv6 */
+  if (smartlist_len(results) > 0) {
+    tt_assert(smartlist_contains_ipv4_tor_addr(results)
+              || smartlist_contains_ipv6_tor_addr(results));
+  }
 
   done:
   SMARTLIST_FOREACH(results, tor_addr_t *, t, tor_free(t));
@@ -293,6 +318,13 @@ test_address_get_if_addrs_win32(void *arg)
 
   tt_int_op(smartlist_len(results),>=,1);
   tt_assert(smartlist_contains_localhost_tor_addr(results));
+  tt_assert(!smartlist_contains_null_tor_addr(results));
+
+  /* If there are addresses, they must be IPv4 or IPv6 */
+  if (smartlist_len(results) > 0) {
+    tt_assert(smartlist_contains_ipv4_tor_addr(results)
+              || smartlist_contains_ipv6_tor_addr(results));
+  }
 
   done:
   SMARTLIST_FOREACH(results, tor_addr_t *, t, tor_free(t));
@@ -481,10 +513,24 @@ test_address_get_if_addrs_ioctl(void *arg)
 
   result = get_interface_addresses_ioctl(LOG_ERR);
 
+  /* On an IPv6-only system, this will fail and return NULL
   tt_assert(result);
-  tt_int_op(smartlist_len(result),>=,1);
+  */
 
-  tt_assert(smartlist_contains_localhost_tor_addr(result));
+  /* Some FreeBSD jails don't have localhost IP address. Instead, they only
+   * have the address assigned to the jail (whatever that may be).
+   * And a jail without a network connection might not have any addresses at
+   * all. */
+  if (result) {
+    tt_assert(!smartlist_contains_null_tor_addr(result));
+
+    /* If there are addresses, they must be IPv4 or IPv6.
+     * (AIX supports IPv6 from SIOCGIFCONF.) */
+    if (smartlist_len(result) > 0) {
+      tt_assert(smartlist_contains_ipv4_tor_addr(result)
+                || smartlist_contains_ipv6_tor_addr(result));
+    }
+  }
 
   done:
   if (result) {
@@ -696,12 +742,13 @@ test_address_get_if_addrs_list_internal(void *arg)
   tt_assert(!smartlist_contains_localhost_tor_addr(results));
   tt_assert(!smartlist_contains_multicast_tor_addr(results));
   /* The list may or may not contain internal addresses */
+  tt_assert(!smartlist_contains_null_tor_addr(results));
 
-  /* Allow unit tests to pass on IPv6-only machines */
+  /* if there are any addresses, they must be IPv4 */
   if (smartlist_len(results) > 0) {
-    tt_assert(smartlist_contains_ipv4_tor_addr(results)
-              || smartlist_contains_ipv6_tor_addr(results));
+    tt_assert(smartlist_contains_ipv4_tor_addr(results));
   }
+  tt_assert(!smartlist_contains_ipv6_tor_addr(results));
 
  done:
   free_interface_address_list(results);
@@ -724,6 +771,7 @@ test_address_get_if_addrs_list_no_internal(void *arg)
   tt_assert(!smartlist_contains_localhost_tor_addr(results));
   tt_assert(!smartlist_contains_multicast_tor_addr(results));
   tt_assert(!smartlist_contains_internal_tor_addr(results));
+  tt_assert(!smartlist_contains_null_tor_addr(results));
 
   /* if there are any addresses, they must be IPv4 */
   if (smartlist_len(results) > 0) {
@@ -752,6 +800,7 @@ test_address_get_if_addrs6_list_internal(void *arg)
   tt_assert(!smartlist_contains_localhost_tor_addr(results));
   tt_assert(!smartlist_contains_multicast_tor_addr(results));
   /* The list may or may not contain internal addresses */
+  tt_assert(!smartlist_contains_null_tor_addr(results));
 
   /* if there are any addresses, they must be IPv6 */
   tt_assert(!smartlist_contains_ipv4_tor_addr(results));
@@ -780,7 +829,9 @@ test_address_get_if_addrs6_list_no_internal(void *arg)
   tt_assert(!smartlist_contains_localhost_tor_addr(results));
   tt_assert(!smartlist_contains_multicast_tor_addr(results));
   tt_assert(!smartlist_contains_internal_tor_addr(results));
+  tt_assert(!smartlist_contains_null_tor_addr(results));
 
+  /* if there are any addresses, they must be IPv6 */
   tt_assert(!smartlist_contains_ipv4_tor_addr(results));
   if (smartlist_len(results) > 0) {
     tt_assert(smartlist_contains_ipv6_tor_addr(results));
diff --git a/src/test/test_util.c b/src/test/test_util.c
index 208186c..187cb23 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -4342,9 +4342,14 @@ fd_is_nonblocking(tor_socket_t fd)
 }
 #endif
 
+#define ERRNO_IS_EPROTO(e)    (e == SOCK_ERRNO(EPROTONOSUPPORT))
+#define SOCK_ERR_IS_EPROTO(s) ERRNO_IS_EPROTO(tor_socket_errno(s))
+
+/* Test for tor_open_socket*, using IPv4 or IPv6 depending on arg. */
 static void
 test_util_socket(void *arg)
 {
+  const int domain = !strcmp(arg, "4") ? AF_INET : AF_INET6;
   tor_socket_t fd1 = TOR_INVALID_SOCKET;
   tor_socket_t fd2 = TOR_INVALID_SOCKET;
   tor_socket_t fd3 = TOR_INVALID_SOCKET;
@@ -4355,15 +4360,19 @@ test_util_socket(void *arg)
 
   (void)arg;
 
-  fd1 = tor_open_socket_with_extensions(AF_INET, SOCK_STREAM, 0, 0, 0);
-  fd2 = tor_open_socket_with_extensions(AF_INET, SOCK_STREAM, 0, 0, 1);
+  fd1 = tor_open_socket_with_extensions(domain, SOCK_STREAM, 0, 0, 0);
+  if (SOCK_ERR_IS_EPROTO(fd1)) {
+    /* Assume we're on an IPv4-only or IPv6-only system, and give up now. */
+    goto done;
+  }
+  fd2 = tor_open_socket_with_extensions(domain, SOCK_STREAM, 0, 0, 1);
   tt_assert(SOCKET_OK(fd1));
   tt_assert(SOCKET_OK(fd2));
   tt_int_op(get_n_open_sockets(), OP_EQ, n + 2);
-  //fd3 = tor_open_socket_with_extensions(AF_INET, SOCK_STREAM, 0, 1, 0);
-  //fd4 = tor_open_socket_with_extensions(AF_INET, SOCK_STREAM, 0, 1, 1);
-  fd3 = tor_open_socket(AF_INET, SOCK_STREAM, 0);
-  fd4 = tor_open_socket_nonblocking(AF_INET, SOCK_STREAM, 0);
+  //fd3 = tor_open_socket_with_extensions(domain, SOCK_STREAM, 0, 1, 0);
+  //fd4 = tor_open_socket_with_extensions(domain, SOCK_STREAM, 0, 1, 1);
+  fd3 = tor_open_socket(domain, SOCK_STREAM, 0);
+  fd4 = tor_open_socket_nonblocking(domain, SOCK_STREAM, 0);
   tt_assert(SOCKET_OK(fd3));
   tt_assert(SOCKET_OK(fd4));
   tt_int_op(get_n_open_sockets(), OP_EQ, n + 4);
@@ -4412,8 +4421,15 @@ test_util_socketpair(void *arg)
   int n = get_n_open_sockets();
   tor_socket_t fds[2] = {TOR_INVALID_SOCKET, TOR_INVALID_SOCKET};
   const int family = AF_UNIX;
+  int socketpair_result = 0;
 
-  tt_int_op(0, OP_EQ, tor_socketpair_fn(family, SOCK_STREAM, 0, fds));
+  socketpair_result = tor_socketpair_fn(family, SOCK_STREAM, 0, fds);
+  if (ersatz && ERRNO_IS_EPROTO(-socketpair_result)) {
+    /* Assume we're on an IPv6-only system, and give up now.
+     * (tor_ersatz_socketpair uses IPv4.) */
+    goto done;
+  }
+  tt_int_op(0, OP_EQ, socketpair_result);
   tt_assert(SOCKET_OK(fds[0]));
   tt_assert(SOCKET_OK(fds[1]));
   tt_int_op(get_n_open_sockets(), OP_EQ, n + 2);
@@ -4433,6 +4449,8 @@ test_util_socketpair(void *arg)
     tor_close_socket(fds[1]);
 }
 
+#undef SOCKET_EPROTO
+
 static void
 test_util_max_mem(void *arg)
 {
@@ -4636,7 +4654,10 @@ struct testcase_t util_tests[] = {
   UTIL_TEST(write_chunks_to_file, 0),
   UTIL_TEST(mathlog, 0),
   UTIL_TEST(weak_random, 0),
-  UTIL_TEST(socket, TT_FORK),
+  { "socket_ipv4", test_util_socket, TT_FORK, &passthrough_setup,
+    (void*)"4" },
+  { "socket_ipv6", test_util_socket, TT_FORK,
+    &passthrough_setup, (void*)"6" },
   { "socketpair", test_util_socketpair, TT_FORK, &passthrough_setup,
     (void*)"0" },
   { "socketpair_ersatz", test_util_socketpair, TT_FORK,





More information about the tor-commits mailing list