diff options
Diffstat (limited to 'src/test')
-rwxr-xr-x | src/test/test_bt.sh | 1 | ||||
-rw-r--r-- | src/test/test_connection.c | 411 | ||||
-rw-r--r-- | src/test/test_crypto.c | 30 | ||||
-rw-r--r-- | src/test/test_crypto_slow.c | 15 | ||||
-rw-r--r-- | src/test/test_dir.c | 208 | ||||
-rw-r--r-- | src/test/test_dir_handle_get.c | 14 | ||||
-rw-r--r-- | src/test/test_microdesc.c | 2 | ||||
-rw-r--r-- | src/test/test_policy.c | 3 | ||||
-rw-r--r-- | src/test/test_routerlist.c | 48 | ||||
-rw-r--r-- | src/test/test_util.c | 15 | ||||
-rw-r--r-- | src/test/testing_common.c | 3 |
11 files changed, 539 insertions, 211 deletions
diff --git a/src/test/test_bt.sh b/src/test/test_bt.sh index 83fa3ff24b..fe1781659d 100755 --- a/src/test/test_bt.sh +++ b/src/test/test_bt.sh @@ -3,6 +3,7 @@ exitcode=0 +export ASAN_OPTIONS="handle_segv=0:allow_user_segv_handler=1" "${builddir:-.}/src/test/test-bt-cl" backtraces || exit $? "${builddir:-.}/src/test/test-bt-cl" assert 2>&1 | "${PYTHON:-python}" "${abs_top_srcdir:-.}/src/test/bt_test.py" || exitcode="$?" "${builddir:-.}/src/test/test-bt-cl" crash 2>&1 | "${PYTHON:-python}" "${abs_top_srcdir:-.}/src/test/bt_test.py" || exitcode="$?" diff --git a/src/test/test_connection.c b/src/test/test_connection.c index 6f7aef879c..bf95b0b59f 100644 --- a/src/test/test_connection.c +++ b/src/test/test_connection.c @@ -11,6 +11,7 @@ #include "connection.h" #include "main.h" +#include "microdesc.h" #include "networkstatus.h" #include "rendcache.h" #include "directory.h" @@ -54,7 +55,11 @@ static int test_conn_get_rsrc_teardown(const struct testcase_t *tc, #define TEST_CONN_RSRC_STATE_SUCCESSFUL (DIR_CONN_STATE_CLIENT_FINISHED) #define TEST_CONN_RSRC_2 (networkstatus_get_flavor_name(FLAV_NS)) -#define TEST_CONN_DL_STATE (DIR_CONN_STATE_CLIENT_SENDING) +#define TEST_CONN_DL_STATE (DIR_CONN_STATE_CLIENT_READING) + +/* see AP_CONN_STATE_IS_UNATTACHED() */ +#define TEST_CONN_UNATTACHED_STATE (AP_CONN_STATE_CIRCUIT_WAIT) +#define TEST_CONN_ATTACHED_STATE (AP_CONN_STATE_CONNECT_WAIT) #define TEST_CONN_FD_INIT 50 static int mock_connection_connect_sockaddr_called = 0; @@ -109,27 +114,25 @@ test_conn_lookup_addr_helper(const char *address, int family, tor_addr_t *addr) tor_addr_make_null(addr, TEST_CONN_FAMILY); } -static void * -test_conn_get_basic_setup(const struct testcase_t *tc) +static connection_t * +test_conn_get_connection(uint8_t state, uint8_t type, uint8_t purpose) { connection_t *conn = NULL; tor_addr_t addr; int socket_err = 0; int in_progress = 0; - (void)tc; MOCK(connection_connect_sockaddr, mock_connection_connect_sockaddr); init_connection_lists(); - conn = connection_new(TEST_CONN_TYPE, TEST_CONN_FAMILY); + conn = connection_new(type, TEST_CONN_FAMILY); tt_assert(conn); test_conn_lookup_addr_helper(TEST_CONN_ADDRESS, TEST_CONN_FAMILY, &addr); tt_assert(!tor_addr_is_null(&addr)); - /* XXXX - connection_connect doesn't set these, should it? */ tor_addr_copy_tight(&conn->addr, &addr); conn->port = TEST_CONN_PORT; mock_connection_connect_sockaddr_called = 0; @@ -140,8 +143,8 @@ test_conn_get_basic_setup(const struct testcase_t *tc) tt_assert(in_progress == 0 || in_progress == 1); /* fake some of the attributes so the connection looks OK */ - conn->state = TEST_CONN_STATE; - conn->purpose = TEST_CONN_BASIC_PURPOSE; + conn->state = state; + conn->purpose = purpose; assert_connection_ok(conn, time(NULL)); UNMOCK(connection_connect_sockaddr); @@ -151,12 +154,17 @@ test_conn_get_basic_setup(const struct testcase_t *tc) /* On failure */ done: UNMOCK(connection_connect_sockaddr); - test_conn_get_basic_teardown(tc, conn); - - /* Returning NULL causes the unit test to fail */ return NULL; } +static void * +test_conn_get_basic_setup(const struct testcase_t *tc) +{ + (void)tc; + return test_conn_get_connection(TEST_CONN_STATE, TEST_CONN_TYPE, + TEST_CONN_BASIC_PURPOSE); +} + static int test_conn_get_basic_teardown(const struct testcase_t *tc, void *arg) { @@ -186,9 +194,8 @@ test_conn_get_basic_teardown(const struct testcase_t *tc, void *arg) connection_close_immediate(conn->linked_conn); connection_mark_for_close(conn->linked_conn); } - conn->linked_conn->linked_conn = NULL; - connection_free(conn->linked_conn); - conn->linked_conn = NULL; + + close_closeable_connections(); } /* We didn't set the events up properly, so we can't use event_del() in @@ -222,7 +229,10 @@ static void * test_conn_get_rend_setup(const struct testcase_t *tc) { dir_connection_t *conn = DOWNCAST(dir_connection_t, - test_conn_get_basic_setup(tc)); + test_conn_get_connection( + TEST_CONN_STATE, + TEST_CONN_TYPE, + TEST_CONN_REND_PURPOSE)); tt_assert(conn); assert_connection_ok(&conn->base_, time(NULL)); @@ -235,7 +245,6 @@ test_conn_get_rend_setup(const struct testcase_t *tc) TEST_CONN_REND_ADDR, REND_SERVICE_ID_LEN_BASE32+1); conn->rend_data->hsdirs_fp = smartlist_new(); - conn->base_.purpose = TEST_CONN_REND_PURPOSE; assert_connection_ok(&conn->base_, time(NULL)); return conn; @@ -266,42 +275,64 @@ test_conn_get_rend_teardown(const struct testcase_t *tc, void *arg) return rv; } -static void * -test_conn_get_rsrc_setup(const struct testcase_t *tc) +static dir_connection_t * +test_conn_download_status_add_a_connection(const char *resource) { dir_connection_t *conn = DOWNCAST(dir_connection_t, - test_conn_get_basic_setup(tc)); + test_conn_get_connection( + TEST_CONN_STATE, + TEST_CONN_TYPE, + TEST_CONN_RSRC_PURPOSE)); + tt_assert(conn); assert_connection_ok(&conn->base_, time(NULL)); - /* TODO: use the canonical function to do this - maybe? */ - conn->requested_resource = tor_strdup(TEST_CONN_RSRC); - conn->base_.purpose = TEST_CONN_RSRC_PURPOSE; + /* Replace the existing resource with the one we want */ + if (resource) { + if (conn->requested_resource) { + tor_free(conn->requested_resource); + } + conn->requested_resource = tor_strdup(resource); + assert_connection_ok(&conn->base_, time(NULL)); + } - assert_connection_ok(&conn->base_, time(NULL)); return conn; - /* On failure */ done: - test_conn_get_rend_teardown(tc, conn); - /* Returning NULL causes the unit test to fail */ + test_conn_get_rsrc_teardown(NULL, conn); return NULL; } +static void * +test_conn_get_rsrc_setup(const struct testcase_t *tc) +{ + (void)tc; + return test_conn_download_status_add_a_connection(TEST_CONN_RSRC); +} + static int test_conn_get_rsrc_teardown(const struct testcase_t *tc, void *arg) { - dir_connection_t *conn = DOWNCAST(dir_connection_t, arg); int rv = 0; + connection_t *conn = (connection_t *)arg; tt_assert(conn); - assert_connection_ok(&conn->base_, time(NULL)); + assert_connection_ok(conn, time(NULL)); + + if (conn->type == CONN_TYPE_DIR) { + dir_connection_t *dir_conn = DOWNCAST(dir_connection_t, arg); + + tt_assert(dir_conn); + assert_connection_ok(&dir_conn->base_, time(NULL)); - /* avoid a last-ditch attempt to refetch the consensus */ - conn->base_.state = TEST_CONN_RSRC_STATE_SUCCESSFUL; + /* avoid a last-ditch attempt to refetch the consensus */ + dir_conn->base_.state = TEST_CONN_RSRC_STATE_SUCCESSFUL; + assert_connection_ok(&dir_conn->base_, time(NULL)); + } /* connection_free_() cleans up requested_resource */ - rv = test_conn_get_basic_teardown(tc, arg); + rv = test_conn_get_basic_teardown(tc, conn); + done: return rv; } @@ -336,14 +367,30 @@ test_conn_download_status_teardown(const struct testcase_t *tc, void *arg) return rv; } -static dir_connection_t * -test_conn_download_status_add_a_connection(void) +/* Like connection_ap_make_link(), but does much less */ +static connection_t * +test_conn_get_linked_connection(connection_t *l_conn, uint8_t state) { - dir_connection_t *conn = DOWNCAST(dir_connection_t, - test_conn_get_rsrc_setup(NULL)); + tt_assert(l_conn); + assert_connection_ok(l_conn, time(NULL)); + + /* AP connections don't seem to have purposes */ + connection_t *conn = test_conn_get_connection(state, CONN_TYPE_AP, + 0); tt_assert(conn); - assert_connection_ok(&conn->base_, time(NULL)); + assert_connection_ok(conn, time(NULL)); + + conn->linked = 1; + l_conn->linked = 1; + conn->linked_conn = l_conn; + l_conn->linked_conn = conn; + /* we never opened a real socket, so we can just overwrite it */ + conn->s = TOR_INVALID_SOCKET; + l_conn->s = TOR_INVALID_SOCKET; + + assert_connection_ok(conn, time(NULL)); + assert_connection_ok(l_conn, time(NULL)); return conn; @@ -524,44 +571,6 @@ test_conn_get_rsrc(void *arg) tt_assert(conn); assert_connection_ok(&conn->base_, time(NULL)); - tt_assert(connection_dir_get_by_purpose_and_resource( - conn->base_.purpose, - conn->requested_resource) - == conn); - tt_assert(connection_dir_get_by_purpose_and_resource( - TEST_CONN_RSRC_PURPOSE, - TEST_CONN_RSRC) - == conn); - tt_assert(connection_dir_get_by_purpose_and_resource( - !conn->base_.purpose, - "") - == NULL); - tt_assert(connection_dir_get_by_purpose_and_resource( - !TEST_CONN_RSRC_PURPOSE, - TEST_CONN_RSRC_2) - == NULL); - - tt_assert(connection_dir_get_by_purpose_resource_and_state( - conn->base_.purpose, - conn->requested_resource, - conn->base_.state) - == conn); - tt_assert(connection_dir_get_by_purpose_resource_and_state( - TEST_CONN_RSRC_PURPOSE, - TEST_CONN_RSRC, - TEST_CONN_STATE) - == conn); - tt_assert(connection_dir_get_by_purpose_resource_and_state( - !conn->base_.purpose, - "", - !conn->base_.state) - == NULL); - tt_assert(connection_dir_get_by_purpose_resource_and_state( - !TEST_CONN_RSRC_PURPOSE, - TEST_CONN_RSRC_2, - !TEST_CONN_STATE) - == NULL); - sl_is_conn_assert(connection_dir_list_by_purpose_and_resource( conn->base_.purpose, conn->requested_resource), @@ -641,120 +650,208 @@ test_conn_get_rsrc(void *arg) static void test_conn_download_status(void *arg) { - (void)arg; dir_connection_t *conn = NULL; dir_connection_t *conn2 = NULL; - dir_connection_t *conn3 = NULL; - - /* no connections, no excess, not downloading */ - tt_assert(networkstatus_consensus_has_excess_connections() == 0); - tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 0); - tt_assert(connection_dir_avoid_extra_connection_for_purpose( - TEST_CONN_RSRC_PURPOSE) == 0); - - /* one connection, no excess, not downloading */ - conn = test_conn_download_status_add_a_connection(); - tt_assert(networkstatus_consensus_has_excess_connections() == 0); - tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 0); - tt_assert(connection_dir_avoid_extra_connection_for_purpose( - TEST_CONN_RSRC_PURPOSE) == 0); - - /* one connection, no excess, but downloading */ + dir_connection_t *conn4 = NULL; + connection_t *ap_conn = NULL; + + consensus_flavor_t usable_flavor = (consensus_flavor_t)arg; + + /* The "other flavor" trick only works if there are two flavors */ + tor_assert(N_CONSENSUS_FLAVORS == 2); + consensus_flavor_t other_flavor = ((usable_flavor == FLAV_NS) + ? FLAV_MICRODESC + : FLAV_NS); + const char *res = networkstatus_get_flavor_name(usable_flavor); + const char *other_res = networkstatus_get_flavor_name(other_flavor); + + /* no connections */ + tt_assert(networkstatus_consensus_is_already_downloading(res) == 0); + tt_assert(networkstatus_consensus_is_already_downloading(other_res) == 0); + tt_assert(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, + res) == 0); + tt_assert(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, + other_res) == 0); + + /* one connection, not downloading */ + conn = test_conn_download_status_add_a_connection(res); + tt_assert(networkstatus_consensus_is_already_downloading(res) == 0); + tt_assert(networkstatus_consensus_is_already_downloading(other_res) == 0); + tt_assert(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, + res) == 1); + tt_assert(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, + other_res) == 0); + + /* one connection, downloading but not linked (not possible on a client, + * but possible on a relay) */ conn->base_.state = TEST_CONN_DL_STATE; - tt_assert(networkstatus_consensus_has_excess_connections() == 0); - tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 1); - tt_assert(connection_dir_avoid_extra_connection_for_purpose( - TEST_CONN_RSRC_PURPOSE) == 1); - conn->base_.state = TEST_CONN_STATE; + tt_assert(networkstatus_consensus_is_already_downloading(res) == 0); + tt_assert(networkstatus_consensus_is_already_downloading(other_res) == 0); + tt_assert(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, + res) == 1); + tt_assert(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, + other_res) == 0); - /* two connections, excess, but not downloading */ - conn2 = test_conn_download_status_add_a_connection(); - tt_assert(networkstatus_consensus_has_excess_connections() == 1); - tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 0); - tt_assert(connection_dir_avoid_extra_connection_for_purpose( - TEST_CONN_RSRC_PURPOSE) == 0); + /* one connection, downloading and linked, but not yet attached */ + ap_conn = test_conn_get_linked_connection(TO_CONN(conn), + TEST_CONN_UNATTACHED_STATE); + tt_assert(networkstatus_consensus_is_already_downloading(res) == 0); + tt_assert(networkstatus_consensus_is_already_downloading(other_res) == 0); + tt_assert(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, + res) == 1); + tt_assert(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, + other_res) == 0); - /* two connections, excess, downloading */ - conn2->base_.state = TEST_CONN_DL_STATE; - tt_assert(networkstatus_consensus_has_excess_connections() == 1); - tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 1); - tt_assert(connection_dir_avoid_extra_connection_for_purpose( - TEST_CONN_RSRC_PURPOSE) == 1); - conn2->base_.state = TEST_CONN_STATE; - - /* more connections, excess, but not downloading */ - conn3 = test_conn_download_status_add_a_connection(); - tt_assert(networkstatus_consensus_has_excess_connections() == 1); - tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 0); - tt_assert(connection_dir_avoid_extra_connection_for_purpose( - TEST_CONN_RSRC_PURPOSE) == 0); - - /* more connections, excess, downloading */ - conn3->base_.state = TEST_CONN_DL_STATE; - tt_assert(networkstatus_consensus_has_excess_connections() == 1); - tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 1); - tt_assert(connection_dir_avoid_extra_connection_for_purpose( - TEST_CONN_RSRC_PURPOSE) == 1); - - /* more connections, more downloading */ - conn2->base_.state = TEST_CONN_DL_STATE; - tt_assert(networkstatus_consensus_has_excess_connections() == 1); - tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 1); - tt_assert(connection_dir_avoid_extra_connection_for_purpose( - TEST_CONN_RSRC_PURPOSE) == 1); + /* one connection, downloading and linked and attached */ + ap_conn->state = TEST_CONN_ATTACHED_STATE; + tt_assert(networkstatus_consensus_is_already_downloading(res) == 1); + tt_assert(networkstatus_consensus_is_already_downloading(other_res) == 0); + tt_assert(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, + res) == 1); + tt_assert(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, + other_res) == 0); + + /* one connection, linked and attached but not downloading */ + conn->base_.state = TEST_CONN_STATE; + tt_assert(networkstatus_consensus_is_already_downloading(res) == 0); + tt_assert(networkstatus_consensus_is_already_downloading(other_res) == 0); + tt_assert(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, + res) == 1); + tt_assert(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, + other_res) == 0); - /* now try closing the one that isn't downloading: - * these tests won't work unless tor thinks it is bootstrapping */ - tt_assert(networkstatus_consensus_is_bootstrapping(time(NULL))); + /* two connections, both not downloading */ + conn2 = test_conn_download_status_add_a_connection(res); + tt_assert(networkstatus_consensus_is_already_downloading(res) == 0); + tt_assert(networkstatus_consensus_is_already_downloading(other_res) == 0); + tt_assert(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, + res) == 2); + tt_assert(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, + other_res) == 0); + /* two connections, one downloading */ + conn->base_.state = TEST_CONN_DL_STATE; + tt_assert(networkstatus_consensus_is_already_downloading(res) == 1); + tt_assert(networkstatus_consensus_is_already_downloading(other_res) == 0); + tt_assert(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, + res) == 2); + tt_assert(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, + other_res) == 0); + conn->base_.state = TEST_CONN_STATE; + + /* more connections, all not downloading */ + /* ignore the return value, it's free'd using the connection list */ + (void)test_conn_download_status_add_a_connection(res); + tt_assert(networkstatus_consensus_is_already_downloading(res) == 0); + tt_assert(networkstatus_consensus_is_already_downloading(other_res) == 0); tt_assert(connection_dir_count_by_purpose_and_resource( TEST_CONN_RSRC_PURPOSE, - TEST_CONN_RSRC) == 3); - tt_assert(connection_dir_avoid_extra_connection_for_purpose( - TEST_CONN_RSRC_PURPOSE) == 1); - tt_assert(connection_dir_close_consensus_conn_if_extra(conn) == -1); + res) == 3); tt_assert(connection_dir_count_by_purpose_and_resource( TEST_CONN_RSRC_PURPOSE, - TEST_CONN_RSRC) == 2); - tt_assert(connection_dir_avoid_extra_connection_for_purpose( - TEST_CONN_RSRC_PURPOSE) == 1); + other_res) == 0); - /* now try closing one that is already closed - nothing happens */ - tt_assert(connection_dir_close_consensus_conn_if_extra(conn) == 0); + /* more connections, one downloading */ + conn->base_.state = TEST_CONN_DL_STATE; + tt_assert(networkstatus_consensus_is_already_downloading(res) == 1); + tt_assert(networkstatus_consensus_is_already_downloading(other_res) == 0); tt_assert(connection_dir_count_by_purpose_and_resource( TEST_CONN_RSRC_PURPOSE, - TEST_CONN_RSRC) == 2); - tt_assert(connection_dir_avoid_extra_connection_for_purpose( - TEST_CONN_RSRC_PURPOSE) == 1); + res) == 3); + tt_assert(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, + other_res) == 0); - /* now try closing one that is downloading - it stays open */ - tt_assert(connection_dir_close_consensus_conn_if_extra(conn2) == 0); + /* more connections, two downloading (should never happen, but needs + * to be tested for completeness) */ + conn2->base_.state = TEST_CONN_DL_STATE; + /* ignore the return value, it's free'd using the connection list */ + (void)test_conn_get_linked_connection(TO_CONN(conn2), + TEST_CONN_ATTACHED_STATE); + tt_assert(networkstatus_consensus_is_already_downloading(res) == 1); + tt_assert(networkstatus_consensus_is_already_downloading(other_res) == 0); + tt_assert(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, + res) == 3); tt_assert(connection_dir_count_by_purpose_and_resource( TEST_CONN_RSRC_PURPOSE, - TEST_CONN_RSRC) == 2); - tt_assert(connection_dir_avoid_extra_connection_for_purpose( - TEST_CONN_RSRC_PURPOSE) == 1); + other_res) == 0); + conn->base_.state = TEST_CONN_STATE; - /* now try closing all excess connections */ - connection_dir_close_extra_consensus_conns(); + /* more connections, a different one downloading */ + tt_assert(networkstatus_consensus_is_already_downloading(res) == 1); + tt_assert(networkstatus_consensus_is_already_downloading(other_res) == 0); + tt_assert(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, + res) == 3); tt_assert(connection_dir_count_by_purpose_and_resource( TEST_CONN_RSRC_PURPOSE, - TEST_CONN_RSRC) == 1); - tt_assert(connection_dir_avoid_extra_connection_for_purpose( - TEST_CONN_RSRC_PURPOSE) == 1); + other_res) == 0); + + /* a connection for the other flavor (could happen if a client is set to + * cache directory documents), one preferred flavor downloading + */ + conn4 = test_conn_download_status_add_a_connection(other_res); + tt_assert(networkstatus_consensus_is_already_downloading(res) == 1); + tt_assert(networkstatus_consensus_is_already_downloading(other_res) == 0); + tt_assert(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, + res) == 3); + tt_assert(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, + other_res) == 1); + + /* a connection for the other flavor (could happen if a client is set to + * cache directory documents), both flavors downloading + */ + conn4->base_.state = TEST_CONN_DL_STATE; + /* ignore the return value, it's free'd using the connection list */ + (void)test_conn_get_linked_connection(TO_CONN(conn4), + TEST_CONN_ATTACHED_STATE); + tt_assert(networkstatus_consensus_is_already_downloading(res) == 1); + tt_assert(networkstatus_consensus_is_already_downloading(other_res) == 1); + tt_assert(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, + res) == 3); + tt_assert(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, + other_res) == 1); done: - /* the teardown function removes all the connections */; + /* the teardown function removes all the connections in the global list*/; } #define CONNECTION_TESTCASE(name, fork, setup) \ { #name, test_conn_##name, fork, &setup, NULL } +/* where arg is an expression (constant, varaible, compound expression) */ +#define CONNECTION_TESTCASE_ARG(name, fork, setup, arg) \ + { #name "_" #arg, test_conn_##name, fork, &setup, (void *)arg } + struct testcase_t connection_tests[] = { CONNECTION_TESTCASE(get_basic, TT_FORK, test_conn_get_basic_st), CONNECTION_TESTCASE(get_rend, TT_FORK, test_conn_get_rend_st), CONNECTION_TESTCASE(get_rsrc, TT_FORK, test_conn_get_rsrc_st), - CONNECTION_TESTCASE(download_status, TT_FORK, test_conn_download_status_st), + CONNECTION_TESTCASE_ARG(download_status, TT_FORK, + test_conn_download_status_st, FLAV_MICRODESC), + CONNECTION_TESTCASE_ARG(download_status, TT_FORK, + test_conn_download_status_st, FLAV_NS), //CONNECTION_TESTCASE(func_suffix, TT_FORK, setup_func_pair), END_OF_TESTCASES }; diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c index e981eac602..e6b250a677 100644 --- a/src/test/test_crypto.c +++ b/src/test/test_crypto.c @@ -126,7 +126,7 @@ test_crypto_dh(void *arg) s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH_BYTES, s1, 50); tt_int_op(-1, OP_EQ, s1len); - memset(p1, 0xff, sizeof(DH_BYTES)), /* 2^1024-1 */ + memset(p1, 0xff, DH_BYTES), /* 2^1024-1 */ s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH_BYTES, s1, 50); tt_int_op(-1, OP_EQ, s1len); } @@ -548,6 +548,7 @@ test_crypto_aes_ctr_testvec(void *arg) done: tor_free(mem_op_hex_tmp); + crypto_cipher_free(c); } /** Run unit tests for our SHA-1 functionality */ @@ -1322,6 +1323,29 @@ test_crypto_pk_base64(void *arg) tor_free(encoded); } +#ifdef HAVE_TRUNCATE +#define do_truncate truncate +#else +static int +do_truncate(const char *fname, size_t len) +{ + struct stat st; + char *bytes; + + bytes = read_file_to_str(fname, RFTS_BIN, &st); + if (!bytes) + return -1; + /* This cast isn't so great, but it should be safe given the actual files + * and lengths we're using. */ + if (st.st_size < (off_t)len) + len = MIN(len, (size_t)st.st_size); + + int r = write_bytes_to_file(fname, bytes, len, 1); + tor_free(bytes); + return r; +} +#endif + /** Sanity check for crypto pk digests */ static void test_crypto_digests(void *arg) @@ -2664,8 +2688,8 @@ test_crypto_ed25519_storage(void *arg) tor_free(tag); /* whitebox test: truncated keys. */ - tt_int_op(0, ==, truncate(fname_1, 40)); - tt_int_op(0, ==, truncate(fname_2, 40)); + tt_int_op(0, ==, do_truncate(fname_1, 40)); + tt_int_op(0, ==, do_truncate(fname_2, 40)); tt_int_op(-1, OP_EQ, ed25519_pubkey_read_from_file(&pub, &tag, fname_2)); tt_ptr_op(tag, OP_EQ, NULL); tor_free(tag); diff --git a/src/test/test_crypto_slow.c b/src/test/test_crypto_slow.c index 9b39199cd0..6f3e40e0ab 100644 --- a/src/test/test_crypto_slow.c +++ b/src/test/test_crypto_slow.c @@ -10,7 +10,8 @@ #include "crypto_s2k.h" #include "crypto_pwbox.h" -#if defined(HAVE_LIBSCRYPT_H) +#if defined(HAVE_LIBSCRYPT_H) && defined(HAVE_LIBSCRYPT_SCRYPT) +#define HAVE_LIBSCRYPT #include <libscrypt.h> #endif @@ -129,7 +130,7 @@ test_crypto_s2k_general(void *arg) } } -#if defined(HAVE_LIBSCRYPT_H) && defined(HAVE_EVP_PBE_SCRYPT) +#if defined(HAVE_LIBSCRYPT) && defined(HAVE_EVP_PBE_SCRYPT) static void test_libscrypt_eq_openssl(void *arg) { @@ -276,7 +277,7 @@ test_crypto_s2k_errors(void *arg) buf, sizeof(buf), "ABC", 3)); /* Truncated output */ -#ifdef HAVE_LIBSCRYPT_H +#ifdef HAVE_LIBSCRYPT tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_new(buf, 50, &sz, "ABC", 3, 0)); tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_new(buf, 50, &sz, @@ -287,7 +288,7 @@ test_crypto_s2k_errors(void *arg) tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_new(buf, 29, &sz, "ABC", 3, S2K_FLAG_NO_SCRYPT)); -#ifdef HAVE_LIBSCRYPT_H +#ifdef HAVE_LIBSCRYPT tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_make_specifier(buf, 18, 0)); tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_make_specifier(buf, 18, S2K_FLAG_LOW_MEM)); @@ -308,7 +309,7 @@ test_crypto_s2k_errors(void *arg) secret_to_key_derivekey(buf2, sizeof(buf2), buf, 18, "ABC", 3)); -#ifdef HAVE_LIBSCRYPT_H +#ifdef HAVE_LIBSCRYPT /* It's a bad scrypt buffer if N would overflow uint64 */ memset(buf, 0, sizeof(buf)); buf[0] = 2; /* scrypt */ @@ -329,7 +330,7 @@ test_crypto_scrypt_vectors(void *arg) uint8_t spec[64], out[64]; (void)arg; -#ifndef HAVE_LIBSCRYPT_H +#ifndef HAVE_LIBSCRYPT if (1) tt_skip(); #endif @@ -507,7 +508,7 @@ test_crypto_pwbox(void *arg) struct testcase_t slow_crypto_tests[] = { CRYPTO_LEGACY(s2k_rfc2440), -#ifdef HAVE_LIBSCRYPT_H +#ifdef HAVE_LIBSCRYPT { "s2k_scrypt", test_crypto_s2k_general, 0, &passthrough_setup, (void*)"scrypt" }, { "s2k_scrypt_low", test_crypto_s2k_general, 0, &passthrough_setup, diff --git a/src/test/test_dir.c b/src/test/test_dir.c index 747c4c4aa3..bddbe9f18e 100644 --- a/src/test/test_dir.c +++ b/src/test/test_dir.c @@ -85,6 +85,15 @@ test_dir_nicknames(void *arg) ; } +static smartlist_t *mocked_configured_ports = NULL; + +/** Returns mocked_configured_ports */ +static const smartlist_t * +mock_get_configured_ports(void) +{ + return mocked_configured_ports; +} + /** Run unit tests for router descriptor generation logic. */ static void test_dir_formats(void *arg) @@ -104,6 +113,7 @@ test_dir_formats(void *arg) or_options_t *options = get_options_mutable(); const addr_policy_t *p; time_t now = time(NULL); + port_cfg_t orport, dirport; (void)arg; pk1 = pk_generate(0); @@ -150,15 +160,15 @@ test_dir_formats(void *arg) ed25519_secret_key_from_seed(&kp2.seckey, (const uint8_t*)"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); ed25519_public_key_generate(&kp2.pubkey, &kp2.seckey); - r2->signing_key_cert = tor_cert_create(&kp1, + r2->cache_info.signing_key_cert = tor_cert_create(&kp1, CERT_TYPE_ID_SIGNING, &kp2.pubkey, now, 86400, CERT_FLAG_INCLUDE_SIGNING_KEY); char cert_buf[256]; base64_encode(cert_buf, sizeof(cert_buf), - (const char*)r2->signing_key_cert->encoded, - r2->signing_key_cert->encoded_len, + (const char*)r2->cache_info.signing_key_cert->encoded, + r2->cache_info.signing_key_cert->encoded_len, BASE64_ENCODE_MULTILINE); r2->platform = tor_strdup(platform); r2->cache_info.published_on = 5; @@ -185,9 +195,31 @@ test_dir_formats(void *arg) /* XXXX025 router_dump_to_string should really take this from ri.*/ options->ContactInfo = tor_strdup("Magri White " "<magri@elsewhere.example.com>"); + /* Skip reachability checks for DirPort and tunnelled-dir-server */ + options->AssumeReachable = 1; + + /* Fake just enough of an ORPort and DirPort to get by */ + MOCK(get_configured_ports, mock_get_configured_ports); + mocked_configured_ports = smartlist_new(); + + memset(&orport, 0, sizeof(orport)); + orport.type = CONN_TYPE_OR_LISTENER; + orport.addr.family = AF_INET; + orport.port = 9000; + smartlist_add(mocked_configured_ports, &orport); + + memset(&dirport, 0, sizeof(dirport)); + dirport.type = CONN_TYPE_DIR_LISTENER; + dirport.addr.family = AF_INET; + dirport.port = 9003; + smartlist_add(mocked_configured_ports, &dirport); buf = router_dump_router_to_string(r1, pk2, NULL, NULL, NULL); + UNMOCK(get_configured_ports); + smartlist_free(mocked_configured_ports); + mocked_configured_ports = NULL; + tor_free(options->ContactInfo); tt_assert(buf); @@ -247,7 +279,8 @@ test_dir_formats(void *arg) strlcat(buf2, "master-key-ed25519 ", sizeof(buf2)); { char k[ED25519_BASE64_LEN+1]; - tt_assert(ed25519_public_to_base64(k, &r2->signing_key_cert->signing_key) + tt_assert(ed25519_public_to_base64(k, + &r2->cache_info.signing_key_cert->signing_key) >= 0); strlcat(buf2, k, sizeof(buf2)); strlcat(buf2, "\n", sizeof(buf2)); @@ -308,6 +341,16 @@ test_dir_formats(void *arg) strlcat(buf2, "tunnelled-dir-server\n", sizeof(buf2)); strlcat(buf2, "router-sig-ed25519 ", sizeof(buf2)); + /* Fake just enough of an ORPort to get by */ + MOCK(get_configured_ports, mock_get_configured_ports); + mocked_configured_ports = smartlist_new(); + + memset(&orport, 0, sizeof(orport)); + orport.type = CONN_TYPE_OR_LISTENER; + orport.addr.family = AF_INET; + orport.port = 9005; + smartlist_add(mocked_configured_ports, &orport); + buf = router_dump_router_to_string(r2, pk1, pk2, &r2_onion_keypair, &kp2); tt_assert(buf); buf[strlen(buf2)] = '\0'; /* Don't compare the sig; it's never the same @@ -318,6 +361,10 @@ test_dir_formats(void *arg) buf = router_dump_router_to_string(r2, pk1, NULL, NULL, NULL); + UNMOCK(get_configured_ports); + smartlist_free(mocked_configured_ports); + mocked_configured_ports = NULL; + /* Reset for later */ cp = buf; rp2 = router_parse_entry_from_string((const char*)cp,NULL,1,0,NULL,NULL); @@ -3996,12 +4043,56 @@ test_dir_choose_compression_level(void* data) done: ; } +static int mock_networkstatus_consensus_is_bootstrapping_value = 0; +static int +mock_networkstatus_consensus_is_bootstrapping(time_t now) +{ + (void)now; + return mock_networkstatus_consensus_is_bootstrapping_value; +} + +static int mock_networkstatus_consensus_can_use_extra_fallbacks_value = 0; +static int +mock_networkstatus_consensus_can_use_extra_fallbacks( + const or_options_t *options) +{ + (void)options; + return mock_networkstatus_consensus_can_use_extra_fallbacks_value; +} + +/* data is a 2 character nul-terminated string. + * If data[0] is 'b', set bootstrapping, anything else means not bootstrapping + * If data[1] is 'f', set extra fallbacks, anything else means no extra + * fallbacks. + */ static void test_dir_find_dl_schedule(void* data) { + const char *str = (const char *)data; + + tt_assert(strlen(data) == 2); + + if (str[0] == 'b') { + mock_networkstatus_consensus_is_bootstrapping_value = 1; + } else { + mock_networkstatus_consensus_is_bootstrapping_value = 0; + } + + if (str[1] == 'f') { + mock_networkstatus_consensus_can_use_extra_fallbacks_value = 1; + } else { + mock_networkstatus_consensus_can_use_extra_fallbacks_value = 0; + } + + MOCK(networkstatus_consensus_is_bootstrapping, + mock_networkstatus_consensus_is_bootstrapping); + MOCK(networkstatus_consensus_can_use_extra_fallbacks, + mock_networkstatus_consensus_can_use_extra_fallbacks); + download_status_t dls; - smartlist_t server, client, server_cons, client_cons, bridge; - (void)data; + smartlist_t server, client, server_cons, client_cons; + smartlist_t client_boot_auth_only_cons, client_boot_auth_cons; + smartlist_t client_boot_fallback_cons, bridge; mock_options = malloc(sizeof(or_options_t)); reset_options(mock_options, &mock_get_options_calls); @@ -4011,43 +4102,121 @@ test_dir_find_dl_schedule(void* data) mock_options->TestingClientDownloadSchedule = &client; mock_options->TestingServerConsensusDownloadSchedule = &server_cons; mock_options->TestingClientConsensusDownloadSchedule = &client_cons; + mock_options->ClientBootstrapConsensusAuthorityOnlyDownloadSchedule = + &client_boot_auth_only_cons; + mock_options->ClientBootstrapConsensusAuthorityDownloadSchedule = + &client_boot_auth_cons; + mock_options->ClientBootstrapConsensusFallbackDownloadSchedule = + &client_boot_fallback_cons; mock_options->TestingBridgeDownloadSchedule = &bridge; dls.schedule = DL_SCHED_GENERIC; + /* client */ mock_options->ClientOnly = 1; tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, &client); mock_options->ClientOnly = 0; + + /* dir mode */ mock_options->DirPort_set = 1; - mock_options->ORPort_set = 1; mock_options->DirCache = 1; tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, &server); + mock_options->DirPort_set = 0; + mock_options->DirCache = 0; -#if 0 dls.schedule = DL_SCHED_CONSENSUS; - mock_options->ClientOnly = 1; - mock_options->DirCache = 0; - tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, &client_cons); - mock_options->ClientOnly = 0; - mock_options->DirCache = 1; + /* public server mode */ + mock_options->ORPort_set = 1; tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, &server_cons); -#endif + mock_options->ORPort_set = 0; + + /* client and bridge modes */ + if (networkstatus_consensus_is_bootstrapping(time(NULL))) { + if (networkstatus_consensus_can_use_extra_fallbacks(mock_options)) { + dls.want_authority = 1; + /* client */ + mock_options->ClientOnly = 1; + tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, + &client_boot_auth_cons); + mock_options->ClientOnly = 0; + + /* bridge relay */ + mock_options->ORPort_set = 1; + mock_options->BridgeRelay = 1; + tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, + &client_boot_auth_cons); + mock_options->ORPort_set = 0; + mock_options->BridgeRelay = 0; + + dls.want_authority = 0; + /* client */ + mock_options->ClientOnly = 1; + tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, + &client_boot_fallback_cons); + mock_options->ClientOnly = 0; + + /* bridge relay */ + mock_options->ORPort_set = 1; + mock_options->BridgeRelay = 1; + tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, + &client_boot_fallback_cons); + mock_options->ORPort_set = 0; + mock_options->BridgeRelay = 0; + + } else { + /* dls.want_authority is ignored */ + /* client */ + mock_options->ClientOnly = 1; + tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, + &client_boot_auth_only_cons); + mock_options->ClientOnly = 0; + + /* bridge relay */ + mock_options->ORPort_set = 1; + mock_options->BridgeRelay = 1; + tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, + &client_boot_auth_only_cons); + mock_options->ORPort_set = 0; + mock_options->BridgeRelay = 0; + } + } else { + /* client */ + mock_options->ClientOnly = 1; + tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, + &client_cons); + mock_options->ClientOnly = 0; + + /* bridge relay */ + mock_options->ORPort_set = 1; + mock_options->BridgeRelay = 1; + tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, + &client_cons); + mock_options->ORPort_set = 0; + mock_options->BridgeRelay = 0; + } dls.schedule = DL_SCHED_BRIDGE; + /* client */ mock_options->ClientOnly = 1; tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, &bridge); - mock_options->ClientOnly = 0; - tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, &bridge); done: + UNMOCK(networkstatus_consensus_is_bootstrapping); + UNMOCK(networkstatus_consensus_can_use_extra_fallbacks); UNMOCK(get_options); + free(mock_options); + mock_options = NULL; } -#define DIR_LEGACY(name) \ +#define DIR_LEGACY(name) \ { #name, test_dir_ ## name , TT_FORK, NULL, NULL } #define DIR(name,flags) \ { #name, test_dir_##name, (flags), NULL, NULL } +/* where arg is a string constant */ +#define DIR_ARG(name,flags,arg) \ + { #name "_" arg, test_dir_##name, (flags), &passthrough_setup, (void*) arg } + struct testcase_t dir_tests[] = { DIR_LEGACY(nicknames), DIR_LEGACY(formats), @@ -4082,7 +4251,10 @@ struct testcase_t dir_tests[] = { DIR(should_not_init_request_to_dir_auths_without_v3_info, 0), DIR(should_init_request_to_dir_auths, 0), DIR(choose_compression_level, 0), - DIR(find_dl_schedule, 0), + DIR_ARG(find_dl_schedule, TT_FORK, "bf"), + DIR_ARG(find_dl_schedule, TT_FORK, "ba"), + DIR_ARG(find_dl_schedule, TT_FORK, "cf"), + DIR_ARG(find_dl_schedule, TT_FORK, "ca"), END_OF_TESTCASES }; diff --git a/src/test/test_dir_handle_get.c b/src/test/test_dir_handle_get.c index 05657ca452..1416b389aa 100644 --- a/src/test/test_dir_handle_get.c +++ b/src/test/test_dir_handle_get.c @@ -1237,7 +1237,7 @@ test_dir_handle_get_server_keys_all(void* data) base16_decode(ds->v3_identity_digest, DIGEST_LEN, TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN); tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE, - TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1)); + TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1, NULL)); conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR)); @@ -1396,7 +1396,7 @@ test_dir_handle_get_server_keys_fp(void* data) TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN); tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE, - TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1)); + TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1, NULL)); conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR)); char req[71]; @@ -1468,7 +1468,7 @@ test_dir_handle_get_server_keys_sk(void* data) routerlist_free_all(); tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE, - TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1)); + TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1, NULL)); conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR)); char req[71]; @@ -1550,7 +1550,7 @@ test_dir_handle_get_server_keys_fpsk(void* data) dir_server_add(ds); tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE, - TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1)); + TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1, NULL)); conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR)); @@ -1606,7 +1606,7 @@ test_dir_handle_get_server_keys_busy(void* data) dir_server_add(ds); tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE, - TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1)); + TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1, NULL)); MOCK(get_options, mock_get_options); MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock); @@ -2344,7 +2344,7 @@ test_dir_handle_get_status_vote_next_authority(void* data) base16_decode(ds->v3_identity_digest, DIGEST_LEN, TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN); tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE, - TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1)); + TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1, NULL)); init_mock_options(); mock_options->AuthoritativeDir = 1; @@ -2423,7 +2423,7 @@ test_dir_handle_get_status_vote_current_authority(void* data) TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN); tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE, - TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1)); + TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1, NULL)); init_mock_options(); mock_options->AuthoritativeDir = 1; diff --git a/src/test/test_microdesc.c b/src/test/test_microdesc.c index 7db819a622..581f58b45f 100644 --- a/src/test/test_microdesc.c +++ b/src/test/test_microdesc.c @@ -483,7 +483,7 @@ test_md_generate(void *arg) md = dirvote_create_microdescriptor(ri, 21); tt_str_op(md->body, ==, test_md2_21); tt_assert(ed25519_pubkey_eq(md->ed25519_identity_pkey, - &ri->signing_key_cert->signing_key)); + &ri->cache_info.signing_key_cert->signing_key)); done: microdesc_free(md); diff --git a/src/test/test_policy.c b/src/test/test_policy.c index 48e82551e3..a939ebf54f 100644 --- a/src/test/test_policy.c +++ b/src/test/test_policy.c @@ -716,10 +716,9 @@ test_policies_reject_exit_address(void *arg) } static smartlist_t *test_configured_ports = NULL; -const smartlist_t *mock_get_configured_ports(void); /** Returns test_configured_ports */ -const smartlist_t * +static const smartlist_t * mock_get_configured_ports(void) { return test_configured_ports; diff --git a/src/test/test_routerlist.c b/src/test/test_routerlist.c index 497606920d..2cffa6e801 100644 --- a/src/test/test_routerlist.c +++ b/src/test/test_routerlist.c @@ -15,6 +15,7 @@ #include "container.h" #include "directory.h" #include "dirvote.h" +#include "microdesc.h" #include "networkstatus.h" #include "nodelist.h" #include "policies.h" @@ -190,6 +191,14 @@ construct_consensus(char **consensus_text_md) crypto_pk_free(sign_skey_leg); } +static int mock_usable_consensus_flavor_value = FLAV_NS; + +static int +mock_usable_consensus_flavor(void) +{ + return mock_usable_consensus_flavor_value; +} + static void test_router_pick_directory_server_impl(void *arg) { @@ -209,6 +218,22 @@ test_router_pick_directory_server_impl(void *arg) (void)arg; + MOCK(usable_consensus_flavor, mock_usable_consensus_flavor); + + /* With no consensus, we must be bootstrapping, regardless of time or flavor + */ + mock_usable_consensus_flavor_value = FLAV_NS; + tt_assert(networkstatus_consensus_is_bootstrapping(now)); + tt_assert(networkstatus_consensus_is_bootstrapping(now + 2000)); + tt_assert(networkstatus_consensus_is_bootstrapping(now + 2*24*60*60)); + tt_assert(networkstatus_consensus_is_bootstrapping(now - 2*24*60*60)); + + mock_usable_consensus_flavor_value = FLAV_MICRODESC; + tt_assert(networkstatus_consensus_is_bootstrapping(now)); + tt_assert(networkstatus_consensus_is_bootstrapping(now + 2000)); + tt_assert(networkstatus_consensus_is_bootstrapping(now + 2*24*60*60)); + tt_assert(networkstatus_consensus_is_bootstrapping(now - 2*24*60*60)); + /* No consensus available, fail early */ rs = router_pick_directory_server_impl(V3_DIRINFO, (const int) 0, NULL); tt_assert(rs == NULL); @@ -223,6 +248,28 @@ test_router_pick_directory_server_impl(void *arg) tt_int_op(smartlist_len(con_md->routerstatus_list), ==, 3); tt_assert(!networkstatus_set_current_consensus_from_ns(con_md, "microdesc")); + + /* If the consensus time or flavor doesn't match, we are still + * bootstrapping */ + mock_usable_consensus_flavor_value = FLAV_NS; + tt_assert(networkstatus_consensus_is_bootstrapping(now)); + tt_assert(networkstatus_consensus_is_bootstrapping(now + 2000)); + tt_assert(networkstatus_consensus_is_bootstrapping(now + 2*24*60*60)); + tt_assert(networkstatus_consensus_is_bootstrapping(now - 2*24*60*60)); + + /* With a valid consensus for the current time and flavor, we stop + * bootstrapping, even if we have no certificates */ + mock_usable_consensus_flavor_value = FLAV_MICRODESC; + tt_assert(!networkstatus_consensus_is_bootstrapping(now + 2000)); + tt_assert(!networkstatus_consensus_is_bootstrapping(con_md->valid_after)); + tt_assert(!networkstatus_consensus_is_bootstrapping(con_md->valid_until)); + tt_assert(!networkstatus_consensus_is_bootstrapping(con_md->valid_until + + 24*60*60)); + /* These times are outside the test validity period */ + tt_assert(networkstatus_consensus_is_bootstrapping(now)); + tt_assert(networkstatus_consensus_is_bootstrapping(now + 2*24*60*60)); + tt_assert(networkstatus_consensus_is_bootstrapping(now - 2*24*60*60)); + nodelist_set_consensus(con_md); nodelist_assert_ok(); @@ -362,6 +409,7 @@ test_router_pick_directory_server_impl(void *arg) node_router1->rs->last_dir_503_at = 0; done: + UNMOCK(usable_consensus_flavor); if (router1_id) tor_free(router1_id); if (router2_id) diff --git a/src/test/test_util.c b/src/test/test_util.c index a8802068a3..2726c31fe8 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -4223,21 +4223,6 @@ test_util_round_to_next_multiple_of(void *arg) tt_u64_op(round_uint64_to_next_multiple_of(UINT64_MAX,2), ==, UINT64_MAX); - tt_i64_op(round_int64_to_next_multiple_of(0,1), ==, 0); - tt_i64_op(round_int64_to_next_multiple_of(0,7), ==, 0); - - tt_i64_op(round_int64_to_next_multiple_of(99,1), ==, 99); - tt_i64_op(round_int64_to_next_multiple_of(99,7), ==, 105); - tt_i64_op(round_int64_to_next_multiple_of(99,9), ==, 99); - - tt_i64_op(round_int64_to_next_multiple_of(-99,1), ==, -99); - tt_i64_op(round_int64_to_next_multiple_of(-99,7), ==, -98); - tt_i64_op(round_int64_to_next_multiple_of(-99,9), ==, -99); - - tt_i64_op(round_int64_to_next_multiple_of(INT64_MIN,2), ==, INT64_MIN); - tt_i64_op(round_int64_to_next_multiple_of(INT64_MAX,2), ==, - INT64_MAX); - tt_int_op(round_uint32_to_next_multiple_of(0,1), ==, 0); tt_int_op(round_uint32_to_next_multiple_of(0,7), ==, 0); diff --git a/src/test/testing_common.c b/src/test/testing_common.c index aeb1fa794d..39c3d02ab1 100644 --- a/src/test/testing_common.c +++ b/src/test/testing_common.c @@ -242,6 +242,8 @@ main(int c, const char **v) options = options_new(); tor_threads_init(); + network_init(); + struct tor_libevent_cfg cfg; memset(&cfg, 0, sizeof(cfg)); tor_libevent_initialize(&cfg); @@ -284,7 +286,6 @@ main(int c, const char **v) return 1; } rep_hist_init(); - network_init(); setup_directory(); options_init(options); options->DataDirectory = tor_strdup(temp_dir); |