[tor-commits] [tor/master] prop271: Tests for the highlevel or_state_t encode/decode functions

nickm at torproject.org nickm at torproject.org
Fri Dec 16 16:26:19 UTC 2016


commit 79d3e94f8b1769ee8d1957cb1d6dd35bd02a7271
Author: Nick Mathewson <nickm at torproject.org>
Date:   Wed Nov 30 12:35:16 2016 -0500

    prop271: Tests for the highlevel or_state_t encode/decode functions
---
 src/or/entrynodes.c        |   4 +-
 src/or/entrynodes.h        |   2 +
 src/test/test_entrynodes.c | 238 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 242 insertions(+), 2 deletions(-)

diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index 9441be4..1f6d562 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -1115,8 +1115,8 @@ remove_guard_from_confirmed_and_primary_lists(guard_selection_t *gs,
 /** Return true iff <b>guard</b> is currently "listed" -- that is, it
  * appears in the consensus, or as a configured bridge (as
  * appropriate) */
-static int
-entry_guard_is_listed(guard_selection_t *gs, const entry_guard_t *guard)
+MOCK_IMPL(STATIC int,
+entry_guard_is_listed,(guard_selection_t *gs, const entry_guard_t *guard))
 {
   if (gs->type == GS_TYPE_BRIDGE) {
     return NULL != get_bridge_info_for_guard(guard);
diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h
index b676172..c05a3e3 100644
--- a/src/or/entrynodes.h
+++ b/src/or/entrynodes.h
@@ -498,6 +498,8 @@ STATIC guard_selection_t *guard_selection_new(const char *name,
 STATIC guard_selection_t *get_guard_selection_by_name(
           const char *name, guard_selection_type_t type, int create_if_absent);
 STATIC void guard_selection_free(guard_selection_t *gs);
+MOCK_DECL(STATIC int, entry_guard_is_listed,
+          (guard_selection_t *gs, const entry_guard_t *guard));
 STATIC const char *choose_guard_selection(const or_options_t *options,
                                           const networkstatus_t *ns,
                                           const char *old_selection,
diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c
index 5360b0e..1fbb8f8 100644
--- a/src/test/test_entrynodes.c
+++ b/src/test/test_entrynodes.c
@@ -14,6 +14,7 @@
 #include "bridges.h"
 #include "circuitlist.h"
 #include "config.h"
+#include "confparse.h"
 #include "entrynodes.h"
 #include "nodelist.h"
 #include "networkstatus.h"
@@ -1247,6 +1248,239 @@ test_entry_guard_parse_from_state_partial_failure(void *arg)
   tor_free(mem_op_hex_tmp);
 }
 
+static int
+mock_entry_guard_is_listed(guard_selection_t *gs, const entry_guard_t *guard)
+{
+  (void)gs;
+  (void)guard;
+  return 1;
+}
+
+static void
+test_entry_guard_parse_from_state_full(void *arg)
+{
+  (void)arg;
+  /* Here's a state I made while testing.  The identities and locations for
+   * the bridges are redacted. */
+  const char STATE[] =
+  "Guard in=default rsa_id=214F44BD5B638E8C817D47FF7C97397790BF0345 "
+    "nickname=TotallyNinja sampled_on=2016-11-12T19:32:49 "
+    "sampled_by=0.3.0.0-alpha-dev "
+    "listed=1\n"
+  "Guard in=default rsa_id=052900AB0EA3ED54BAB84AE8A99E74E8693CE2B2 "
+    "nickname=5OfNovember sampled_on=2016-11-20T04:32:05 "
+    "sampled_by=0.3.0.0-alpha-dev "
+    "listed=1 confirmed_on=2016-11-22T08:13:28 confirmed_idx=0 "
+    "pb_circ_attempts=4.000000 pb_circ_successes=2.000000 "
+    "pb_successful_circuits_closed=2.000000\n"
+  "Guard in=default rsa_id=7B700C0C207EBD0002E00F499BE265519AC3C25A "
+    "nickname=dc6jgk11 sampled_on=2016-11-28T11:50:13 "
+    "sampled_by=0.3.0.0-alpha-dev "
+    "listed=1 confirmed_on=2016-11-24T08:45:30 confirmed_idx=4 "
+    "pb_circ_attempts=5.000000 pb_circ_successes=5.000000 "
+    "pb_successful_circuits_closed=5.000000\n"
+  "Guard in=wobblesome rsa_id=7B700C0C207EBD0002E00F499BE265519AC3C25A "
+    "nickname=dc6jgk11 sampled_on=2016-11-28T11:50:13 "
+    "sampled_by=0.3.0.0-alpha-dev "
+    "listed=1\n"
+  "Guard in=default rsa_id=E9025AD60D86875D5F11548D536CC6AF60F0EF5E "
+    "nickname=maibrunn sampled_on=2016-11-25T22:36:38 "
+    "sampled_by=0.3.0.0-alpha-dev listed=1\n"
+  "Guard in=default rsa_id=DCD30B90BA3A792DA75DC54A327EF353FB84C38E "
+    "nickname=Unnamed sampled_on=2016-11-25T14:34:00 "
+    "sampled_by=0.3.0.0-alpha-dev listed=1\n"
+  "Guard in=bridges rsa_id=8FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E "
+    "bridge_addr=24.1.1.1:443 sampled_on=2016-11-25T06:44:14 "
+    "sampled_by=0.3.0.0-alpha-dev listed=1 "
+    "confirmed_on=2016-11-29T10:36:06 confirmed_idx=0 "
+    "pb_circ_attempts=8.000000 pb_circ_successes=8.000000 "
+    "pb_successful_circuits_closed=13.000000\n"
+  "Guard in=bridges rsa_id=5800000000000000000000000000000000000000 "
+    "bridge_addr=37.218.246.143:28366 "
+    "sampled_on=2016-11-18T15:07:34 sampled_by=0.3.0.0-alpha-dev listed=1\n";
+
+  config_line_t *lines = NULL;
+  or_state_t *state = tor_malloc_zero(sizeof(or_state_t));
+  int r = config_get_lines(STATE, &lines, 0);
+  char *msg = NULL;
+  smartlist_t *text = smartlist_new();
+  char *joined = NULL;
+
+  MOCK(entry_guard_is_listed, mock_entry_guard_is_listed);
+
+  dummy_state = state;
+  MOCK(get_or_state,
+       get_or_state_replacement);
+
+  tt_assert(r == 0);
+  tt_assert(lines);
+
+  state->Guard = lines;
+
+  /* Try it first without setting the result. */
+  r = entry_guards_parse_state(state, 0, &msg);
+  tt_assert(r == 0);
+  guard_selection_t *gs_br =
+    get_guard_selection_by_name("bridges", GS_TYPE_BRIDGE, 0);
+  tt_assert(!gs_br);
+
+  r = entry_guards_parse_state(state, 1, &msg);
+  tt_assert(r == 0);
+  gs_br = get_guard_selection_by_name("bridges", GS_TYPE_BRIDGE, 0);
+  guard_selection_t *gs_df =
+    get_guard_selection_by_name("default", GS_TYPE_NORMAL, 0);
+  guard_selection_t *gs_wb =
+    get_guard_selection_by_name("wobblesome", GS_TYPE_NORMAL, 0);
+
+  tt_assert(gs_br);
+  tt_assert(gs_df);
+  tt_assert(gs_wb);
+
+  tt_int_op(smartlist_len(gs_df->sampled_entry_guards), OP_EQ, 5);
+  tt_int_op(smartlist_len(gs_br->sampled_entry_guards), OP_EQ, 2);
+  tt_int_op(smartlist_len(gs_wb->sampled_entry_guards), OP_EQ, 1);
+
+  /* Try again; make sure it doesn't double-add the guards. */
+  r = entry_guards_parse_state(state, 1, &msg);
+  tt_assert(r == 0);
+  gs_br = get_guard_selection_by_name("bridges", GS_TYPE_BRIDGE, 0);
+  gs_df = get_guard_selection_by_name("default", GS_TYPE_NORMAL, 0);
+  tt_assert(gs_br);
+  tt_assert(gs_df);
+  tt_int_op(smartlist_len(gs_df->sampled_entry_guards), OP_EQ, 5);
+  tt_int_op(smartlist_len(gs_br->sampled_entry_guards), OP_EQ, 2);
+
+  /* Re-encode; it should be the same... almost. */
+  {
+    /* (Make a guard nonpersistent first) */
+    entry_guard_t *g = smartlist_get(gs_df->sampled_entry_guards, 0);
+    g->is_persistent = 0;
+  }
+  config_free_lines(lines);
+  lines = state->Guard = NULL; // to prevent double-free.
+  entry_guards_update_state(state);
+  tt_assert(state->Guard);
+  lines = state->Guard;
+
+  config_line_t *ln;
+  for (ln = lines; ln; ln = ln->next) {
+    smartlist_add_asprintf(text, "%s %s\n",ln->key, ln->value);
+  }
+  joined = smartlist_join_strings(text, "", 0, NULL);
+  tt_str_op(joined, OP_EQ,
+  "Guard in=default rsa_id=052900AB0EA3ED54BAB84AE8A99E74E8693CE2B2 "
+    "nickname=5OfNovember sampled_on=2016-11-20T04:32:05 "
+    "sampled_by=0.3.0.0-alpha-dev "
+    "listed=1 confirmed_on=2016-11-22T08:13:28 confirmed_idx=0 "
+    "pb_circ_attempts=4.000000 pb_circ_successes=2.000000 "
+    "pb_successful_circuits_closed=2.000000\n"
+  "Guard in=default rsa_id=7B700C0C207EBD0002E00F499BE265519AC3C25A "
+    "nickname=dc6jgk11 sampled_on=2016-11-28T11:50:13 "
+    "sampled_by=0.3.0.0-alpha-dev "
+    "listed=1 confirmed_on=2016-11-24T08:45:30 confirmed_idx=1 "
+    "pb_circ_attempts=5.000000 pb_circ_successes=5.000000 "
+    "pb_successful_circuits_closed=5.000000\n"
+  "Guard in=default rsa_id=E9025AD60D86875D5F11548D536CC6AF60F0EF5E "
+    "nickname=maibrunn sampled_on=2016-11-25T22:36:38 "
+    "sampled_by=0.3.0.0-alpha-dev listed=1\n"
+  "Guard in=default rsa_id=DCD30B90BA3A792DA75DC54A327EF353FB84C38E "
+    "nickname=Unnamed sampled_on=2016-11-25T14:34:00 "
+    "sampled_by=0.3.0.0-alpha-dev listed=1\n"
+  "Guard in=wobblesome rsa_id=7B700C0C207EBD0002E00F499BE265519AC3C25A "
+    "nickname=dc6jgk11 sampled_on=2016-11-28T11:50:13 "
+    "sampled_by=0.3.0.0-alpha-dev "
+    "listed=1\n"
+  "Guard in=bridges rsa_id=8FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E "
+    "bridge_addr=24.1.1.1:443 sampled_on=2016-11-25T06:44:14 "
+    "sampled_by=0.3.0.0-alpha-dev listed=1 "
+    "confirmed_on=2016-11-29T10:36:06 confirmed_idx=0 "
+    "pb_circ_attempts=8.000000 pb_circ_successes=8.000000 "
+    "pb_successful_circuits_closed=13.000000\n"
+  "Guard in=bridges rsa_id=5800000000000000000000000000000000000000 "
+    "bridge_addr=37.218.246.143:28366 "
+    "sampled_on=2016-11-18T15:07:34 sampled_by=0.3.0.0-alpha-dev listed=1\n");
+
+ done:
+  config_free_lines(lines);
+  tor_free(state);
+  tor_free(msg);
+  UNMOCK(get_or_state);
+  UNMOCK(entry_guard_is_listed);
+  SMARTLIST_FOREACH(text, char *, cp, tor_free(cp));
+  smartlist_free(text);
+  tor_free(joined);
+}
+
+static void
+test_entry_guard_parse_from_state_broken(void *arg)
+{
+  (void)arg;
+  /* Here's a variation on the previous state. Every line but the first is
+   * busted somehow. */
+  const char STATE[] =
+  /* Okay. */
+  "Guard in=default rsa_id=214F44BD5B638E8C817D47FF7C97397790BF0345 "
+    "nickname=TotallyNinja sampled_on=2016-11-12T19:32:49 "
+    "sampled_by=0.3.0.0-alpha-dev "
+    "listed=1\n"
+  /* No selection listed. */
+  "Guard rsa_id=052900AB0EA3ED54BAB84AE8A99E74E8693CE2B2 "
+    "nickname=5OfNovember sampled_on=2016-11-20T04:32:05 "
+    "sampled_by=0.3.0.0-alpha-dev "
+    "listed=1 confirmed_on=2016-11-22T08:13:28 confirmed_idx=0 "
+    "pb_circ_attempts=4.000000 pb_circ_successes=2.000000 "
+    "pb_successful_circuits_closed=2.000000\n"
+  /* Selection is "legacy"!! */
+  "Guard in=legacy rsa_id=7B700C0C207EBD0002E00F499BE265519AC3C25A "
+    "nickname=dc6jgk11 sampled_on=2016-11-28T11:50:13 "
+    "sampled_by=0.3.0.0-alpha-dev "
+    "listed=1 confirmed_on=2016-11-24T08:45:30 confirmed_idx=4 "
+    "pb_circ_attempts=5.000000 pb_circ_successes=5.000000 "
+    "pb_successful_circuits_closed=5.000000\n";
+
+  config_line_t *lines = NULL;
+  or_state_t *state = tor_malloc_zero(sizeof(or_state_t));
+  int r = config_get_lines(STATE, &lines, 0);
+  char *msg = NULL;
+
+  dummy_state = state;
+  MOCK(get_or_state,
+       get_or_state_replacement);
+
+  tt_assert(r == 0);
+  tt_assert(lines);
+
+  state->Guard = lines;
+
+  /* First, no-set case. we should get an error. */
+  r = entry_guards_parse_state(state, 0, &msg);
+  tt_int_op(r, OP_LT, 0);
+  tt_ptr_op(msg, OP_NE, NULL);
+  /* And we shouldn't have made anything. */
+  guard_selection_t *gs_df =
+    get_guard_selection_by_name("default", GS_TYPE_NORMAL, 0);
+  tt_assert(gs_df == NULL);
+  tor_free(msg);
+
+  /* Now see about the set case (which shouldn't happen IRL) */
+  r = entry_guards_parse_state(state, 1, &msg);
+  tt_int_op(r, OP_LT, 0);
+  tt_ptr_op(msg, OP_NE, NULL);
+  gs_df = get_guard_selection_by_name("default", GS_TYPE_NORMAL, 0);
+  tt_assert(gs_df != NULL);
+  tt_int_op(smartlist_len(gs_df->sampled_entry_guards), OP_EQ, 1);
+  guard_selection_t *gs_legacy =
+    get_guard_selection_by_name("legacy", GS_TYPE_LEGACY, 0);
+  tt_assert(gs_legacy != NULL);
+  tt_int_op(smartlist_len(gs_legacy->chosen_entry_guards), OP_EQ, 0);
+
+ done:
+  config_free_lines(lines);
+  tor_free(state);
+  tor_free(msg);
+  UNMOCK(get_or_state);
+}
+
 static void
 test_entry_guard_get_guard_selection_by_name(void *arg)
 {
@@ -3019,6 +3253,10 @@ struct testcase_t entrynodes_tests[] = {
     test_entry_guard_parse_from_state_failure, 0, NULL, NULL },
   { "parse_from_state_partial_failure",
     test_entry_guard_parse_from_state_partial_failure, 0, NULL, NULL },
+  { "parse_from_state_full",
+    test_entry_guard_parse_from_state_full, TT_FORK, NULL, NULL },
+  { "parse_from_state_broken",
+    test_entry_guard_parse_from_state_broken, TT_FORK, NULL, NULL },
   { "get_guard_selection_by_name",
     test_entry_guard_get_guard_selection_by_name, TT_FORK, NULL, NULL },
   BFN_TEST(add_single_guard),





More information about the tor-commits mailing list