[tor-commits] [tor/master] test: Add testing module and some unittests for bridges.c.

nickm at torproject.org nickm at torproject.org
Tue Apr 10 19:33:31 UTC 2018


commit c2c5b13e5d8a77eeee36028940175f182fda1ec9
Author: Isis Lovecruft <isis at torproject.org>
Date:   Mon Mar 5 20:43:26 2018 +0000

    test: Add testing module and some unittests for bridges.c.
    
    This roughly doubles our test coverage of the bridges.c module.
    
     * ADD new testing module, .../src/test/test_bridges.c.
     * CHANGE a few function declarations from `static` to `STATIC`.
     * CHANGE one function in transports.c, transport_get_by_name(), to be
       mockable.
     * CLOSES #25425: https://bugs.torproject.org/25425
---
 src/or/bridges.c        |  10 +-
 src/or/bridges.h        |  13 +-
 src/or/transports.c     |   6 +-
 src/or/transports.h     |   5 +-
 src/test/include.am     |   1 +
 src/test/test.c         |   1 +
 src/test/test.h         |   1 +
 src/test/test_bridges.c | 618 ++++++++++++++++++++++++++++++++++++++++++++++++
 8 files changed, 646 insertions(+), 9 deletions(-)

diff --git a/src/or/bridges.c b/src/or/bridges.c
index d88d6c643..4ee355004 100644
--- a/src/or/bridges.c
+++ b/src/or/bridges.c
@@ -11,6 +11,8 @@
  * Bridges are fixed entry nodes, used for censorship circumvention.
  **/
 
+#define TOR_BRIDGES_PRIVATE
+
 #include "or.h"
 #include "bridges.h"
 #include "circuitbuild.h"
@@ -93,7 +95,7 @@ sweep_bridge_list(void)
 }
 
 /** Initialize the bridge list to empty, creating it if needed. */
-static void
+STATIC void
 clear_bridge_list(void)
 {
   if (!bridge_list)
@@ -156,7 +158,7 @@ bridge_get_addr_port(const bridge_info_t *bridge)
  * bridge with no known digest whose address matches any of the
  * tor_addr_port_t's in <b>orports</b>, return that bridge.  Else return
  * NULL. */
-static bridge_info_t *
+STATIC bridge_info_t *
 get_configured_bridge_by_orports_digest(const char *digest,
                                         const smartlist_t *orports)
 {
@@ -350,7 +352,7 @@ bridge_has_digest(const bridge_info_t *bridge, const char *digest)
  * existing bridge with the same address and port, and warn the user as
  * appropriate.
  */
-static void
+STATIC void
 bridge_resolve_conflicts(const tor_addr_t *addr, uint16_t port,
                          const char *digest, const char *transport_name)
 {
@@ -472,7 +474,7 @@ bridge_add_from_config(bridge_line_t *bridge_line)
 }
 
 /** If <b>digest</b> is one of our known bridges, return it. */
-bridge_info_t *
+STATIC bridge_info_t *
 find_bridge_by_digest(const char *digest)
 {
   if (! bridge_list)
diff --git a/src/or/bridges.h b/src/or/bridges.h
index 54a625025..3108eb555 100644
--- a/src/or/bridges.h
+++ b/src/or/bridges.h
@@ -20,7 +20,6 @@ typedef struct bridge_info_t bridge_info_t;
 void mark_bridge_list(void);
 void sweep_bridge_list(void);
 const smartlist_t *bridge_list_get(void);
-bridge_info_t *find_bridge_by_digest(const char *digest);
 const uint8_t *bridge_get_rsa_id_digest(const bridge_info_t *bridge);
 const tor_addr_port_t * bridge_get_addr_port(const bridge_info_t *bridge);
 bridge_info_t *get_configured_bridge_by_addr_port_digest(
@@ -65,5 +64,17 @@ MOCK_DECL(download_status_t *, get_bridge_dl_status_by_id,
 
 void bridges_free_all(void);
 
+#ifdef TOR_BRIDGES_PRIVATE
+STATIC void clear_bridge_list(void);
+STATIC bridge_info_t *find_bridge_by_digest(const char *digest);
+STATIC bridge_info_t *get_configured_bridge_by_orports_digest(
+                                                  const char *digest,
+                                                  const smartlist_t *orports);
+STATIC void bridge_resolve_conflicts(const tor_addr_t *addr,
+                                     uint16_t port,
+                                     const char *digest,
+                                     const char *transport_name);
+#endif /* defined(TOR_BRIDGES_PRIVATE) */
+
 #endif /* !defined(TOR_BRIDGES_H) */
 
diff --git a/src/or/transports.c b/src/or/transports.c
index b08dcd161..fb6c29de7 100644
--- a/src/or/transports.c
+++ b/src/or/transports.c
@@ -135,7 +135,7 @@ static smartlist_t *transport_list = NULL;
 /** Returns a transport_t struct for a transport proxy supporting the
     protocol <b>name</b> listening at <b>addr</b>:<b>port</b> using
     SOCKS version <b>socks_ver</b>. */
-static transport_t *
+STATIC transport_t *
 transport_new(const tor_addr_t *addr, uint16_t port,
               const char *name, int socks_ver,
               const char *extra_info_args)
@@ -222,8 +222,8 @@ transport_copy(const transport_t *transport)
 
 /** Returns the transport in our transport list that has the name <b>name</b>.
  *  Else returns NULL. */
-transport_t *
-transport_get_by_name(const char *name)
+MOCK_IMPL(transport_t *,
+transport_get_by_name,(const char *name))
 {
   tor_assert(name);
 
diff --git a/src/or/transports.h b/src/or/transports.h
index 1b2786472..022b926a0 100644
--- a/src/or/transports.h
+++ b/src/or/transports.h
@@ -38,7 +38,7 @@ MOCK_DECL(int, transport_add_from_config,
 void transport_free_(transport_t *transport);
 #define transport_free(tr) FREE_AND_NULL(transport_t, transport_free_, (tr))
 
-transport_t *transport_get_by_name(const char *name);
+MOCK_DECL(transport_t*, transport_get_by_name, (const char *name));
 
 MOCK_DECL(void, pt_kickstart_proxy,
           (const smartlist_t *transport_list, char **proxy_argv,
@@ -113,6 +113,9 @@ typedef struct {
   smartlist_t *transports;
 } managed_proxy_t;
 
+STATIC transport_t *transport_new(const tor_addr_t *addr, uint16_t port,
+                                  const char *name, int socks_ver,
+                                  const char *extra_info_args);
 STATIC int parse_cmethod_line(const char *line, managed_proxy_t *mp);
 STATIC int parse_smethod_line(const char *line, managed_proxy_t *mp);
 
diff --git a/src/test/include.am b/src/test/include.am
index 1a49367c6..7a3d05661 100644
--- a/src/test/include.am
+++ b/src/test/include.am
@@ -88,6 +88,7 @@ src_test_test_SOURCES = \
 	src/test/test_addr.c \
 	src/test/test_address.c \
 	src/test/test_address_set.c \
+	src/test/test_bridges.c \
 	src/test/test_buffers.c \
 	src/test/test_cell_formats.c \
 	src/test/test_cell_queue.c \
diff --git a/src/test/test.c b/src/test/test.c
index 2712de4ed..c9c646890 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -1185,6 +1185,7 @@ struct testgroup_t testgroups[] = {
   { "addr/", addr_tests },
   { "address/", address_tests },
   { "address_set/", address_set_tests },
+  { "bridges/", bridges_tests },
   { "buffer/", buffer_tests },
   { "cellfmt/", cell_format_tests },
   { "cellqueue/", cell_queue_tests },
diff --git a/src/test/test.h b/src/test/test.h
index 26139fc5f..91c8d3ebd 100644
--- a/src/test/test.h
+++ b/src/test/test.h
@@ -178,6 +178,7 @@ extern struct testcase_t accounting_tests[];
 extern struct testcase_t addr_tests[];
 extern struct testcase_t address_tests[];
 extern struct testcase_t address_set_tests[];
+extern struct testcase_t bridges_tests[];
 extern struct testcase_t buffer_tests[];
 extern struct testcase_t cell_format_tests[];
 extern struct testcase_t cell_queue_tests[];
diff --git a/src/test/test_bridges.c b/src/test/test_bridges.c
new file mode 100644
index 000000000..aada363d9
--- /dev/null
+++ b/src/test/test_bridges.c
@@ -0,0 +1,618 @@
+/* Copyright (c) 2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information     */
+
+/**
+ * \file test_bridges.c
+ * \brief Unittests for code in src/or/bridges.c
+ **/
+
+#define TOR_BRIDGES_PRIVATE
+#define PT_PRIVATE /* Only needed for the mock_* items below */
+
+#include <stdbool.h>
+
+#include "or.h"
+#include "address.h"
+#include "bridges.h"
+#include "config.h"
+#include "container.h"
+#include "transports.h"
+#include "util.h"
+
+/* Test suite stuff */
+#include "test.h"
+
+/**
+ * A mocked transport_t, constructed via mock_transport_get_by_name().
+ */
+static transport_t *mock_transport = NULL;
+
+/**
+ * Mock transport_get_by_name() to simply return a transport_t for the
+ * transport name that was input to it.
+ */
+static transport_t *
+mock_transport_get_by_name(const char *name)
+{
+  tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
+  uint16_t port = 9999;
+  int socksv = 9;
+  char *args = tor_strdup("foo=bar");
+
+  if (!mock_transport) {
+    tor_addr_parse(addr, "99.99.99.99");
+    mock_transport = transport_new(addr, port, name, socksv, args);
+  }
+
+  tor_free(addr);
+  tor_free(args);
+
+  return mock_transport;
+}
+
+#undef PT_PRIVATE /* defined(PT_PRIVATE) */
+
+/**
+ * Test helper: Add a variety of bridges to our global bridgelist.
+ */
+static void
+helper_add_bridges_to_bridgelist(void *arg)
+{
+  /* Note: the two bridges which do not have specified fingerprints will be
+   * internally stored as both having the same fingerprint of all-zero bytes.
+   */
+
+  (void)arg;
+  char *bridge0 = tor_strdup("6.6.6.6:6666");
+  char *bridge1 = tor_strdup("6.6.6.7:6667 "
+                             "A10C4F666D27364036B562823E5830BC448E046A");
+  char *bridge2 = tor_strdup("obfs4 198.245.60.51:443 "
+                             "752CF7825B3B9EA6A98C83AC41F7099D67007EA5 "
+                  "cert=xpmQtKUqQ/6v5X7ijgYE/f03+l2/EuQ1dexjyUhh16wQlu/"
+                             "cpXUGalmhDIlhuiQPNEKmKw iat-mode=0");
+  char *bridge3 = tor_strdup("banana 5.5.5.5:5555 "
+                             "9D6AE1BD4FDF39721CE908966E79E16F9BFCCF2F");
+  char *bridge4 = tor_strdup("obfs4 1.2.3.4:1234 "
+                             "foo=abcdefghijklmnopqrstuvwxyz");
+  char *bridge5 = tor_strdup("apple 4.4.4.4:4444 "
+                             "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA "
+                             "foo=abcdefghijklmnopqrstuvwxyz");
+
+  mark_bridge_list();
+
+#define ADD_BRIDGE(bridge)                                          \
+  bridge_line_t *bridge_line_ ##bridge = parse_bridge_line(bridge); \
+  if (!bridge_line_ ##bridge) {                                     \
+    printf("Unparseable bridge line: '%s'", #bridge);               \
+  } else {                                                          \
+    bridge_add_from_config(bridge_line_ ##bridge);                  \
+  }                                                                 \
+  tor_free(bridge);
+
+  ADD_BRIDGE(bridge0);
+  ADD_BRIDGE(bridge1);
+  ADD_BRIDGE(bridge2);
+  ADD_BRIDGE(bridge3);
+  ADD_BRIDGE(bridge4);
+  ADD_BRIDGE(bridge5);
+#undef ADD_BRIDGES
+
+  sweep_bridge_list();
+}
+
+/**
+ * Make sure our test helper works too.
+ */
+static void
+test_bridges_helper_func_add_bridges_to_bridgelist(void *arg)
+{
+  helper_add_bridges_to_bridgelist(arg);
+  tt_int_op(0, OP_EQ, 0);
+
+ done:
+  mark_bridge_list();
+  sweep_bridge_list();
+}
+
+/**
+ * Calling bridge_list_get() should create a new bridgelist if we
+ * didn't have one before.
+ */
+static void
+test_bridges_bridge_list_get_creates_new_bridgelist(void *arg)
+{
+  const smartlist_t *bridgelist = bridge_list_get();
+
+  (void)arg;
+
+  tt_ptr_op(bridgelist, OP_NE, NULL);
+
+ done:
+  return;
+}
+
+/**
+ * Calling clear_bridge_list() should remove all bridges from the bridgelist.
+ */
+static void
+test_bridges_clear_bridge_list(void *arg)
+{
+  const smartlist_t *bridgelist;
+  const smartlist_t *bridgelist_after;
+  const bridge_info_t *bridge;
+  const bridge_info_t *bridge_after;
+
+  helper_add_bridges_to_bridgelist(arg);
+  bridgelist = bridge_list_get();
+  tt_ptr_op(bridgelist, OP_NE, NULL);
+
+  bridge = smartlist_get(bridgelist, 0);
+  tt_ptr_op(bridge, OP_NE, NULL);
+
+  clear_bridge_list();
+  bridgelist_after = bridge_list_get();
+  tt_ptr_op(bridgelist_after, OP_NE, NULL);
+
+  bridge_after = smartlist_get(bridgelist, 0);
+  // There now shouldn't be a first bridge
+  tt_ptr_op(bridge_after, OP_EQ, NULL);
+
+ done:
+  return;
+}
+
+/**
+ * Calling bridge_get_addrport() should give me the address and port
+ * of the bridge.  In this case, we sort the smartlist of bridges on
+ * fingerprints and choose the first one.
+ */
+static void
+test_bridges_bridge_get_addrport(void *arg)
+{
+  smartlist_t *bridgelist;
+  const bridge_info_t *bridge;
+  const tor_addr_port_t *addrport;
+
+  helper_add_bridges_to_bridgelist(arg);
+  bridgelist = (smartlist_t*)bridge_list_get();
+  tt_ptr_op(bridgelist, OP_NE, NULL);
+
+  // This should be the bridge at 6.6.6.6:6666 with fingerprint
+  // 0000000000000000000000000000000000000000
+  bridge = smartlist_get(bridgelist, 0);
+  tt_ptr_op(bridge, OP_NE, NULL);
+
+  addrport = bridge_get_addr_port(bridge);
+  tt_int_op(addrport->port, OP_EQ, 6666);
+
+ done:
+  mark_bridge_list();
+  sweep_bridge_list();
+}
+
+/**
+ * Calling get_configured_bridge_by_orports_digest() with two
+ * configured bridge orports and an invalid digest should return the
+ * bridge of the first addrport in the list.
+ */
+static void
+test_bridges_get_configured_bridge_by_orports_digest(void *arg)
+{
+  smartlist_t *orports = NULL;
+  const smartlist_t *bridgelist;
+  const bridge_info_t *bridge1;
+  const bridge_info_t *bridge2;
+  const bridge_info_t *ret;
+  tor_addr_port_t *addrport1;
+  tor_addr_port_t *addrport2;
+  const char *digest;
+
+  helper_add_bridges_to_bridgelist(arg);
+  bridgelist = bridge_list_get();
+  tt_ptr_op(bridgelist, OP_NE, NULL);
+
+  // This should be the bridge at 6.6.6.6:6666 with fingerprint
+  // 0000000000000000000000000000000000000000
+  bridge1 = smartlist_get(bridgelist, 0);
+  tt_ptr_op(bridge1, OP_NE, NULL);
+  // This should be the bridge at 6.6.6.7:6667 with fingerprint
+  // A10C4F666D27364036B562823E5830BC448E046A
+  bridge2 = smartlist_get(bridgelist, 1);
+  tt_ptr_op(bridge2, OP_NE, NULL);
+
+  addrport1 = (tor_addr_port_t*)bridge_get_addr_port(bridge1);
+  tt_int_op(addrport1->port, OP_EQ, 6666);
+  addrport2 = (tor_addr_port_t*)bridge_get_addr_port(bridge2);
+  tt_int_op(addrport2->port, OP_EQ, 6667);
+
+  orports = smartlist_new();
+  smartlist_add(orports, addrport1);
+  smartlist_add(orports, addrport2);
+
+  digest = "zzzzzzzzzzzzzzzz";
+
+  ret = get_configured_bridge_by_orports_digest(digest, orports);
+  tt_ptr_op(ret, OP_NE, NULL);
+
+  tt_mem_op(addrport1, OP_EQ, bridge_get_addr_port(ret), sizeof(ret));
+
+ done:
+  smartlist_free(orports);
+
+  mark_bridge_list();
+  sweep_bridge_list();
+}
+
+/**
+ * Calling get_configured_bridge_by_addr_port_digest() with a digest that we do
+ * have and an addr:port pair we don't should return the bridge for that
+ * digest.
+ */
+static void
+test_bridges_get_configured_bridge_by_addr_port_digest_digest_only(void *arg)
+{
+  char digest[DIGEST_LEN];
+  bridge_info_t *bridge;
+  const char fingerprint[HEX_DIGEST_LEN] =
+    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+  tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
+  char ret_addr[16];
+  uint16_t port = 11111;
+  int ret;
+
+  helper_add_bridges_to_bridgelist(arg);
+
+  // We don't actually have a bridge with this addr:port pair
+  base16_decode(digest, DIGEST_LEN, fingerprint, HEX_DIGEST_LEN);
+  ret = tor_addr_parse(addr, "111.111.111.111");
+  tt_int_op(ret, OP_EQ, 2); // it returns the address family on success
+
+  bridge = get_configured_bridge_by_addr_port_digest(addr, port, digest);
+  tt_ptr_op(bridge, OP_NE, NULL);
+
+  tor_addr_to_str(ret_addr, &bridge_get_addr_port(bridge)->addr, 16, 0);
+  tt_str_op("4.4.4.4", OP_EQ, ret_addr);
+
+ done:
+  tor_free(addr);
+
+  mark_bridge_list();
+  sweep_bridge_list();
+}
+
+/**
+ * Calling get_configured_bridge_by_addr_port_digest() with only an
+ * addr:port (i.e. digest set to NULL) should return the bridge for
+ * that digest when there is such a bridge.
+ */
+static void
+test_bridges_get_configured_bridge_by_addr_port_digest_address_only(void *arg)
+{
+  bridge_info_t *bridge;
+  tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
+  char ret_addr[16];
+  uint16_t port = 6666;
+  int ret;
+
+  helper_add_bridges_to_bridgelist(arg);
+
+  ret = tor_addr_parse(addr, "6.6.6.6");
+  tt_int_op(ret, OP_EQ, 2); // it returns the address family on success
+
+  bridge = get_configured_bridge_by_addr_port_digest(addr, port, NULL);
+  tt_ptr_op(bridge, OP_NE, NULL);
+
+  tor_addr_to_str(ret_addr, &bridge_get_addr_port(bridge)->addr, 16, 0);
+  tt_str_op("6.6.6.6", OP_EQ, ret_addr);
+
+ done:
+  tor_free(addr);
+
+  mark_bridge_list();
+  sweep_bridge_list();
+}
+
+/**
+ * Calling get_configured_bridge_by_exact_addr_port_digest() with a digest that
+ * we do have, and an addr:port pair we don't have, should return NULL.
+ */
+static void
+test_bridges_get_configured_bridge_by_exact_addr_port_digest_donly(void *arg)
+{
+  char digest[DIGEST_LEN];
+  bridge_info_t *bridge;
+  const char fingerprint[HEX_DIGEST_LEN] =
+    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+  tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
+  uint16_t port = 11111;
+  int ret;
+
+  helper_add_bridges_to_bridgelist(arg);
+
+  // We don't actually have a bridge with this addr:port pair
+  base16_decode(digest, DIGEST_LEN, fingerprint, HEX_DIGEST_LEN);
+  ret = tor_addr_parse(addr, "111.111.111.111");
+  tt_int_op(ret, OP_EQ, 2); // it returns the address family on success
+
+  bridge = get_configured_bridge_by_exact_addr_port_digest(addr, port, digest);
+  tt_ptr_op(bridge, OP_EQ, NULL);
+
+ done:
+  tor_free(addr);
+
+  mark_bridge_list();
+  sweep_bridge_list();
+}
+
+/**
+ * Calling get_configured_bridge_by_exact_addr_port_digest() with a digest that
+ * we do have, and an addr:port pair we do have, should return the bridge.
+ */
+static void
+test_bridges_get_configured_bridge_by_exact_addr_port_digest_both(void *arg)
+{
+  char digest[DIGEST_LEN];
+  bridge_info_t *bridge;
+  const char fingerprint[HEX_DIGEST_LEN] =
+    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+  tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
+  uint16_t port = 4444;
+  char ret_addr[16];
+  int ret;
+
+  helper_add_bridges_to_bridgelist(arg);
+
+  base16_decode(digest, DIGEST_LEN, fingerprint, HEX_DIGEST_LEN);
+  ret = tor_addr_parse(addr, "4.4.4.4");
+  tt_int_op(ret, OP_EQ, 2); // it returns the address family on success
+
+  bridge = get_configured_bridge_by_exact_addr_port_digest(addr, port, digest);
+  tt_ptr_op(bridge, OP_NE, NULL);
+
+  tor_addr_to_str(ret_addr, &bridge_get_addr_port(bridge)->addr, 16, 0);
+  tt_str_op("4.4.4.4", OP_EQ, ret_addr);
+
+ done:
+  tor_free(addr);
+
+  mark_bridge_list();
+  sweep_bridge_list();
+}
+
+/**
+ * Calling get_configured_bridge_by_exact_addr_port_digest() with no digest,
+ * and an addr:port pair we do have, should return the bridge.
+ */
+static void
+test_bridges_get_configured_bridge_by_exact_addr_port_digest_aonly(void *arg)
+{
+  bridge_info_t *bridge;
+  tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
+  uint16_t port = 4444;
+  char ret_addr[16];
+  int ret;
+
+  helper_add_bridges_to_bridgelist(arg);
+
+  ret = tor_addr_parse(addr, "4.4.4.4");
+  tt_int_op(ret, OP_EQ, 2); // it returns the address family on success
+
+  bridge = get_configured_bridge_by_exact_addr_port_digest(addr, port, NULL);
+  tt_ptr_op(bridge, OP_NE, NULL);
+
+  tor_addr_to_str(ret_addr, &bridge_get_addr_port(bridge)->addr, 16, 0);
+  tt_str_op("4.4.4.4", OP_EQ, ret_addr);
+
+ done:
+  tor_free(addr);
+
+  mark_bridge_list();
+  sweep_bridge_list();
+}
+
+/**
+ * Calling find_bridge_by_digest() when we have a bridge with a known
+ * identity digest should return the bridge's information.
+ */
+static void
+test_bridges_find_bridge_by_digest_known(void *arg)
+{
+  char digest1[DIGEST_LEN];
+  bridge_info_t *bridge;
+  const char fingerprint[HEX_DIGEST_LEN] =
+    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+
+  helper_add_bridges_to_bridgelist(arg);
+
+  base16_decode(digest1, DIGEST_LEN, fingerprint, HEX_DIGEST_LEN);
+  bridge = find_bridge_by_digest(digest1);
+
+  tt_ptr_op(bridge, OP_NE, NULL);
+
+  /* We have to call bridge_get_rsa_id_digest() here because the bridge_info_t
+   * struct is opaquely defined in bridges.h. */
+  const uint8_t *digest2 = bridge_get_rsa_id_digest(bridge);
+
+  tt_mem_op((char*)digest2, OP_EQ, digest1, DIGEST_LEN);
+
+ done:
+  mark_bridge_list();
+  sweep_bridge_list();
+}
+
+/**
+ * Calling find_bridge_by_digest() when we do NOT have a bridge with that
+ * identity digest should return NULL.
+ */
+static void
+test_bridges_find_bridge_by_digest_unknown(void *arg)
+{
+  const char *fingerprint = "cccccccccccccccccccccccccccccccccccccccc";
+  bridge_info_t *bridge;
+
+  helper_add_bridges_to_bridgelist(arg);
+
+  bridge = find_bridge_by_digest(fingerprint);
+
+  tt_ptr_op(bridge, OP_EQ, NULL);
+
+ done:
+  mark_bridge_list();
+  sweep_bridge_list();
+}
+
+/**
+ * Calling bridge_resolve_conflicts() with an identical bridge to one we've
+ * already configure should mark the pre-configured bridge for removal.
+ */
+static void
+test_bridges_bridge_resolve_conflicts(void *arg)
+{
+  tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
+  uint16_t port = 4444;
+  const char *digest = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
+  const char *transport = "apple";
+  int ret;
+
+  helper_add_bridges_to_bridgelist(arg);
+
+  ret = tor_addr_parse(addr, "4.4.4.4");
+  tt_int_op(ret, OP_EQ, 2); // it returns the address family on success
+
+  bridge_resolve_conflicts((const tor_addr_t*)addr, port, digest, transport);
+
+  /* The bridge should now be marked for removal, and removed when we sweep the
+   * bridge_list */
+  sweep_bridge_list();
+  ret = addr_is_a_configured_bridge((const tor_addr_t*)addr, port, digest);
+  tt_int_op(ret, OP_EQ, 0);
+
+ done:
+  tor_free(addr);
+
+  mark_bridge_list();
+  sweep_bridge_list();
+}
+
+/**
+ * Calling transport_is_needed() with a transport we do need ("obfs4") and a
+ * bogus transport that we don't need should return 1 and 0, respectively.
+ */
+static void
+test_bridges_transport_is_needed(void *arg)
+{
+  int ret;
+
+  helper_add_bridges_to_bridgelist(arg);
+
+  ret = transport_is_needed("obfs4");
+  tt_int_op(ret, OP_EQ, 1);
+
+  ret = transport_is_needed("apowefjaoewpaief");
+  tt_int_op(ret, OP_EQ, 0);
+
+ done:
+  mark_bridge_list();
+  sweep_bridge_list();
+}
+
+/**
+ * Calling get_transport_by_bridge_addrport() with the address and port of a
+ * configured bridge which uses a pluggable transport when there is no global
+ * transport_list should return -1 and the transport_t should be NULL.
+ */
+static void
+test_bridges_get_transport_by_bridge_addrport_no_ptlist(void *arg)
+{
+  transport_t *transport = NULL;
+  tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
+  uint16_t port = 1234;
+  int ret;
+
+  helper_add_bridges_to_bridgelist(arg);
+
+  ret = tor_addr_parse(addr, "1.2.3.4");
+  tt_int_op(ret, OP_EQ, 2); // it returns the address family on success?
+
+  /* This will fail because the global transport_list has nothing in it, and so
+   * transport_get_by_name() has nothing to return, even the the bridge *did*
+   * say it had an obfs4 transport.
+   */
+  ret = get_transport_by_bridge_addrport((const tor_addr_t*)addr, port,
+                                         (const transport_t**)&transport);
+  tt_int_op(ret, OP_EQ, -1); // returns -1 on failure
+  tt_ptr_op(transport, OP_EQ, NULL);
+
+ done:
+  tor_free(addr);
+
+  mark_bridge_list();
+  sweep_bridge_list();
+}
+
+#define PT_PRIVATE
+
+/**
+ * Calling get_transport_by_bridge_addrport() with the address and port of a
+ * configured bridge which uses a pluggable transport should return 0 and set
+ * appropriate transport_t.
+ */
+static void
+test_bridges_get_transport_by_bridge_addrport(void *arg)
+{
+  transport_t *transport = NULL;
+  tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
+  uint16_t port = 1234;
+  int ret;
+
+  helper_add_bridges_to_bridgelist(arg);
+  mark_transport_list(); // Also initialise our transport_list
+
+  ret = tor_addr_parse(addr, "1.2.3.4");
+  tt_int_op(ret, OP_EQ, 2); // it returns the address family on success?
+
+  /* After we mock transport_get_by_name() to return a bogus transport_t with
+   * the name it was asked for, the call should succeed.
+   */
+  MOCK(transport_get_by_name, mock_transport_get_by_name);
+  ret = get_transport_by_bridge_addrport((const tor_addr_t*)addr, port,
+                                         (const transport_t**)&transport);
+  tt_int_op(ret, OP_EQ, 0); // returns 0 on success
+  tt_ptr_op(transport, OP_NE, NULL);
+  tt_str_op(transport->name, OP_EQ, "obfs4");
+
+ done:
+  UNMOCK(transport_get_by_name);
+
+  tor_free(addr);
+  transport_free(transport);
+
+  mark_bridge_list();
+  sweep_bridge_list();
+}
+
+#undef PT_PRIVATE /* defined(PT_PRIVATE) */
+
+#define B_TEST(name, flags) \
+  { #name, test_bridges_ ##name, (flags), NULL, NULL }
+
+struct testcase_t bridges_tests[] = {
+  B_TEST(helper_func_add_bridges_to_bridgelist, 0),
+  B_TEST(bridge_list_get_creates_new_bridgelist, 0),
+  B_TEST(clear_bridge_list, 0),
+  B_TEST(bridge_get_addrport, 0),
+  B_TEST(get_configured_bridge_by_orports_digest, 0),
+  B_TEST(get_configured_bridge_by_addr_port_digest_digest_only, 0),
+  B_TEST(get_configured_bridge_by_addr_port_digest_address_only, 0),
+  B_TEST(get_configured_bridge_by_exact_addr_port_digest_donly, 0),
+  B_TEST(get_configured_bridge_by_exact_addr_port_digest_both, 0),
+  B_TEST(get_configured_bridge_by_exact_addr_port_digest_aonly, 0),
+  B_TEST(find_bridge_by_digest_known, 0),
+  B_TEST(find_bridge_by_digest_unknown, 0),
+  B_TEST(bridge_resolve_conflicts, 0),
+  B_TEST(get_transport_by_bridge_addrport_no_ptlist, 0),
+  B_TEST(get_transport_by_bridge_addrport, 0),
+  B_TEST(transport_is_needed, 0),
+  END_OF_TESTCASES
+};
+





More information about the tor-commits mailing list