[tor-commits] [tor/master] test: Add unit test for prune_services_on_reload()

nickm at torproject.org nickm at torproject.org
Fri Jan 13 21:48:24 UTC 2017


commit 2d1fa58fb442122a64cdef9be1d18e8f53067038
Author: David Goulet <dgoulet at torproject.org>
Date:   Wed Dec 21 15:00:02 2016 -0500

    test: Add unit test for prune_services_on_reload()
    
    Signed-off-by: David Goulet <dgoulet at torproject.org>
---
 src/or/rendservice.c |   2 +-
 src/or/rendservice.h |   3 ++
 src/test/test_hs.c   | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 127 insertions(+), 1 deletion(-)

diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index a4e6452..2d94bb8 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -545,7 +545,7 @@ rend_service_check_dir_and_add(smartlist_t *service_list,
 /* If this is a reload and there were hidden services configured before,
  * keep the introduction points that are still needed and close the
  * other ones. */
-static void
+STATIC void
 prune_services_on_reload(smartlist_t *old_service_list,
                          smartlist_t *new_service_list)
 {
diff --git a/src/or/rendservice.h b/src/or/rendservice.h
index 4e6b9a2..3bfac0b 100644
--- a/src/or/rendservice.h
+++ b/src/or/rendservice.h
@@ -132,6 +132,9 @@ STATIC int rend_service_poison_new_single_onion_dir(
 STATIC ssize_t encode_establish_intro_cell_legacy(char *cell_body_out,
                                                   crypto_pk_t *intro_key,
                                                   char *rend_circ_nonce);
+STATIC void prune_services_on_reload(smartlist_t *old_service_list,
+                                     smartlist_t *new_service_list);
+
 #endif
 
 int num_rend_services(void);
diff --git a/src/test/test_hs.c b/src/test/test_hs.c
index ac9788c..fbaabe9 100644
--- a/src/test/test_hs.c
+++ b/src/test/test_hs.c
@@ -787,6 +787,126 @@ test_single_onion_poisoning(void *arg)
   tor_free(mock_options->DataDirectory);
 }
 
+static rend_service_t *
+helper_create_rend_service(const char *path)
+{
+  rend_service_t *s = tor_malloc_zero(sizeof(rend_service_t));
+  s->ports = smartlist_new();
+  s->intro_nodes = smartlist_new();
+  s->expiring_nodes = smartlist_new();
+  if (path) {
+    s->directory = tor_strdup(path);
+  }
+  return s;
+}
+
+static void
+test_prune_services_on_reload(void *arg)
+{
+  smartlist_t *new = smartlist_new(), *old = smartlist_new();
+  /* Non ephemeral service. */
+  rend_service_t *s1 = helper_create_rend_service("SomePath");
+  /* Create a non ephemeral service with the _same_ path as so we can test the
+   * transfer of introduction point between the same services on reload. */
+  rend_service_t *s2 = helper_create_rend_service(s1->directory);
+  /* Ephemeral service (directory is NULL). */
+  rend_service_t *e1 = helper_create_rend_service(NULL);
+  rend_service_t *e2 = helper_create_rend_service(NULL);
+
+  (void) arg;
+
+  {
+    /* Add both services to the old list. */
+    smartlist_add(old, s1);
+    smartlist_add(old, e1);
+    /* Only put the non ephemeral in the new list. */
+    smartlist_add(new, s1);
+    prune_services_on_reload(old, new);
+    /* We expect that the ephemeral one is in the new list but removed from
+     * the old one. */
+    tt_int_op(smartlist_len(old), OP_EQ, 1);
+    tt_assert(smartlist_get(old, 0) == s1);
+    tt_int_op(smartlist_len(new), OP_EQ, 2);
+    tt_assert(smartlist_get(new, 0) == s1);
+    tt_assert(smartlist_get(new, 1) == e1);
+    /* Cleanup for next test. */
+    smartlist_clear(new);
+    smartlist_clear(old);
+  }
+
+  {
+    /* This test will make sure that only the ephemeral service is kept if the
+     * new list is empty. The old list should contain only the non ephemeral
+     * one. */
+    smartlist_add(old, s1);
+    smartlist_add(old, e1);
+    prune_services_on_reload(old, new);
+    tt_int_op(smartlist_len(old), OP_EQ, 1);
+    tt_assert(smartlist_get(old, 0) == s1);
+    tt_int_op(smartlist_len(new), OP_EQ, 1);
+    tt_assert(smartlist_get(new, 0) == e1);
+    /* Cleanup for next test. */
+    smartlist_clear(new);
+    smartlist_clear(old);
+  }
+
+  {
+    /* This test makes sure that the new list stays the same even from the old
+     * list being completely different. */
+    smartlist_add(new, s1);
+    smartlist_add(new, e1);
+    prune_services_on_reload(old, new);
+    tt_int_op(smartlist_len(old), OP_EQ, 0);
+    tt_int_op(smartlist_len(new), OP_EQ, 2);
+    tt_assert(smartlist_get(new, 0) == s1);
+    tt_assert(smartlist_get(new, 1) == e1);
+    /* Cleanup for next test. */
+    smartlist_clear(new);
+  }
+
+  {
+    rend_intro_point_t ip1;
+    /* This IP should be found in the s2 service after pruning. */
+    smartlist_add(s1->intro_nodes, &ip1);
+    /* Setup our list. */
+    smartlist_add(old, s1);
+    smartlist_add(new, s2);
+    prune_services_on_reload(old, new);
+    tt_int_op(smartlist_len(old), OP_EQ, 1);
+    /* Intro nodes have been moved to the s2 in theory so it must be empty. */
+    tt_int_op(smartlist_len(s1->intro_nodes), OP_EQ, 0);
+    tt_int_op(smartlist_len(new), OP_EQ, 1);
+    rend_service_t *elem = smartlist_get(new, 0);
+    tt_assert(elem);
+    tt_assert(elem == s2);
+    tt_int_op(smartlist_len(elem->intro_nodes), OP_EQ, 1);
+    tt_assert(smartlist_get(elem->intro_nodes, 0) == &ip1);
+    smartlist_clear(s1->intro_nodes);
+    smartlist_clear(s2->intro_nodes);
+    /* Cleanup for next test. */
+    smartlist_clear(new);
+    smartlist_clear(old);
+  }
+
+  {
+    /* Test two ephemeral services. */
+    smartlist_add(old, e1);
+    smartlist_add(old, e2);
+    prune_services_on_reload(old, new);
+    /* Check if they've all been transfered. */
+    tt_int_op(smartlist_len(old), OP_EQ, 0);
+    tt_int_op(smartlist_len(new), OP_EQ, 2);
+  }
+
+ done:
+  rend_service_free(s1);
+  rend_service_free(s2);
+  rend_service_free(e1);
+  rend_service_free(e2);
+  smartlist_free(new);
+  smartlist_free(old);
+}
+
 struct testcase_t hs_tests[] = {
   { "hs_rend_data", test_hs_rend_data, TT_FORK,
     NULL, NULL },
@@ -807,6 +927,9 @@ struct testcase_t hs_tests[] = {
     TT_FORK, &passthrough_setup, (void*)(CREATE_HS_DIR2) },
   { "single_onion_poisoning_create_dir_both", test_single_onion_poisoning,
     TT_FORK, &passthrough_setup, (void*)(CREATE_HS_DIR1 | CREATE_HS_DIR2) },
+  { "prune_services_on_reload", test_prune_services_on_reload, TT_FORK,
+    NULL, NULL },
+
   END_OF_TESTCASES
 };
 





More information about the tor-commits mailing list