prop271: Tests for the highlevel or_state_t encode/decode functions

This commit is contained in:
Nick Mathewson 2016-11-30 12:35:16 -05:00
parent 171981f8a0
commit 79d3e94f8b
3 changed files with 242 additions and 2 deletions

View File

@ -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 /** Return true iff <b>guard</b> is currently "listed" -- that is, it
* appears in the consensus, or as a configured bridge (as * appears in the consensus, or as a configured bridge (as
* appropriate) */ * appropriate) */
static int MOCK_IMPL(STATIC int,
entry_guard_is_listed(guard_selection_t *gs, const entry_guard_t *guard) entry_guard_is_listed,(guard_selection_t *gs, const entry_guard_t *guard))
{ {
if (gs->type == GS_TYPE_BRIDGE) { if (gs->type == GS_TYPE_BRIDGE) {
return NULL != get_bridge_info_for_guard(guard); return NULL != get_bridge_info_for_guard(guard);

View File

@ -498,6 +498,8 @@ STATIC guard_selection_t *guard_selection_new(const char *name,
STATIC guard_selection_t *get_guard_selection_by_name( STATIC guard_selection_t *get_guard_selection_by_name(
const char *name, guard_selection_type_t type, int create_if_absent); const char *name, guard_selection_type_t type, int create_if_absent);
STATIC void guard_selection_free(guard_selection_t *gs); 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, STATIC const char *choose_guard_selection(const or_options_t *options,
const networkstatus_t *ns, const networkstatus_t *ns,
const char *old_selection, const char *old_selection,

View File

@ -14,6 +14,7 @@
#include "bridges.h" #include "bridges.h"
#include "circuitlist.h" #include "circuitlist.h"
#include "config.h" #include "config.h"
#include "confparse.h"
#include "entrynodes.h" #include "entrynodes.h"
#include "nodelist.h" #include "nodelist.h"
#include "networkstatus.h" #include "networkstatus.h"
@ -1247,6 +1248,239 @@ test_entry_guard_parse_from_state_partial_failure(void *arg)
tor_free(mem_op_hex_tmp); 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 static void
test_entry_guard_get_guard_selection_by_name(void *arg) 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 }, test_entry_guard_parse_from_state_failure, 0, NULL, NULL },
{ "parse_from_state_partial_failure", { "parse_from_state_partial_failure",
test_entry_guard_parse_from_state_partial_failure, 0, NULL, NULL }, 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", { "get_guard_selection_by_name",
test_entry_guard_get_guard_selection_by_name, TT_FORK, NULL, NULL }, test_entry_guard_get_guard_selection_by_name, TT_FORK, NULL, NULL },
BFN_TEST(add_single_guard), BFN_TEST(add_single_guard),