diff options
author | teor (Tim Wilson-Brown) <teor2345@gmail.com> | 2015-12-07 17:40:56 +1100 |
---|---|---|
committer | teor (Tim Wilson-Brown) <teor2345@gmail.com> | 2015-12-16 04:02:12 +1100 |
commit | df0c135d62ab1619843f7825ccd5ad697f6afdcb (patch) | |
tree | fda1dea714cad8d2492271bb1dfc3f9a8e3a7d91 /src/test/test_connection.c | |
parent | f3ed5ec0cac4719e249e629760756314d7cfecba (diff) | |
download | tor-df0c135d62ab1619843f7825ccd5ad697f6afdcb.tar.gz tor-df0c135d62ab1619843f7825ccd5ad697f6afdcb.zip |
Prop210: Refactor connection_get_* to produce lists and counts
Diffstat (limited to 'src/test/test_connection.c')
-rw-r--r-- | src/test/test_connection.c | 724 |
1 files changed, 724 insertions, 0 deletions
diff --git a/src/test/test_connection.c b/src/test/test_connection.c new file mode 100644 index 0000000000..2851387917 --- /dev/null +++ b/src/test/test_connection.c @@ -0,0 +1,724 @@ +/* Copyright (c) 2015, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "orconfig.h" + +#define CONNECTION_PRIVATE +#define MAIN_PRIVATE + +#include "or.h" +#include "test.h" + +#include "connection.h" +#include "main.h" +#include "networkstatus.h" +#include "rendcache.h" +#include "directory.h" + +static void test_conn_lookup_addr_helper(const char *address, + int family, + tor_addr_t *addr); + +static void * test_conn_get_basic_setup(const struct testcase_t *tc); +static int test_conn_get_basic_teardown(const struct testcase_t *tc, + void *arg); + +static void * test_conn_get_rend_setup(const struct testcase_t *tc); +static int test_conn_get_rend_teardown(const struct testcase_t *tc, + void *arg); + +static void * test_conn_get_rsrc_setup(const struct testcase_t *tc); +static int test_conn_get_rsrc_teardown(const struct testcase_t *tc, + void *arg); + +/* Arbitrary choice - IPv4 Directory Connection to localhost */ +#define TEST_CONN_TYPE (CONN_TYPE_DIR) +/* We assume every machine has IPv4 localhost, is that ok? */ +#define TEST_CONN_ADDRESS "127.0.0.1" +#define TEST_CONN_PORT (12345) +#define TEST_CONN_ADDRESS_PORT "127.0.0.1:12345" +#define TEST_CONN_FAMILY (AF_INET) +#define TEST_CONN_STATE (DIR_CONN_STATE_MIN_) +#define TEST_CONN_ADDRESS_2 "127.0.0.2" + +#define TEST_CONN_BASIC_PURPOSE (DIR_PURPOSE_MIN_) + +#define TEST_CONN_REND_ADDR "cfs3rltphxxvabci" +#define TEST_CONN_REND_PURPOSE (DIR_PURPOSE_FETCH_RENDDESC_V2) +#define TEST_CONN_REND_PURPOSE_SUCCESSFUL (DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2) +#define TEST_CONN_REND_TYPE_2 (CONN_TYPE_AP) +#define TEST_CONN_REND_ADDR_2 "icbavxxhptlr3sfc" + +#define TEST_CONN_RSRC (networkstatus_get_flavor_name(FLAV_MICRODESC)) +#define TEST_CONN_RSRC_PURPOSE (DIR_PURPOSE_FETCH_CONSENSUS) +#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_FD_INIT 50 +static int mock_connection_connect_sockaddr_called = 0; +static int fake_socket_number = TEST_CONN_FD_INIT; + +static int +mock_connection_connect_sockaddr(connection_t *conn, + const struct sockaddr *sa, + socklen_t sa_len, + const struct sockaddr *bindaddr, + socklen_t bindaddr_len, + int *socket_error) +{ + (void)sa_len; + (void)bindaddr; + (void)bindaddr_len; + + tor_assert(conn); + tor_assert(sa); + tor_assert(socket_error); + + mock_connection_connect_sockaddr_called++; + + conn->s = fake_socket_number++; + tt_assert(SOCKET_OK(conn->s)); + /* We really should call tor_libevent_initialize() here. Because we don't, + * we are relying on other parts of the code not checking if the_event_base + * (and therefore event->ev_base) is NULL. */ + tt_assert(connection_add_connecting(conn) == 0); + + done: + /* Fake "connected" status */ + return 1; +} + +static void +test_conn_lookup_addr_helper(const char *address, int family, tor_addr_t *addr) +{ + int rv = 0; + + tt_assert(addr); + + rv = tor_addr_lookup(address, family, addr); + /* XXXX - should we retry on transient failure? */ + tt_assert(rv == 0); + tt_assert(tor_addr_is_loopback(addr)); + tt_assert(tor_addr_is_v4(addr)); + + return; + + done: + tor_addr_make_null(addr, TEST_CONN_FAMILY); +} + +static void * +test_conn_get_basic_setup(const struct testcase_t *tc) +{ + 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); + 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; + in_progress = connection_connect(conn, TEST_CONN_ADDRESS_PORT, &addr, + TEST_CONN_PORT, &socket_err); + tt_assert(mock_connection_connect_sockaddr_called == 1); + tt_assert(!socket_err); + 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; + assert_connection_ok(conn, time(NULL)); + + UNMOCK(connection_connect_sockaddr); + + return conn; + + /* 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 int +test_conn_get_basic_teardown(const struct testcase_t *tc, void *arg) +{ + (void)tc; + connection_t *conn = arg; + + tt_assert(conn); + assert_connection_ok(conn, time(NULL)); + + /* teardown the connection as fast as possible */ + if (conn->linked_conn) { + assert_connection_ok(conn->linked_conn, time(NULL)); + + /* We didn't call tor_libevent_initialize(), so event_base was NULL, + * so we can't rely on connection_unregister_events() use of event_del(). + */ + if (conn->linked_conn->read_event) { + tor_free(conn->linked_conn->read_event); + conn->linked_conn->read_event = NULL; + } + if (conn->linked_conn->write_event) { + tor_free(conn->linked_conn->write_event); + conn->linked_conn->write_event = NULL; + } + + connection_free(conn->linked_conn); + conn->linked_conn = NULL; + + conn->linked_conn->linked_conn = NULL; + if (!conn->linked_conn->marked_for_close) { + connection_close_immediate(conn->linked_conn); + connection_mark_for_close(conn->linked_conn); + } + } + + /* We didn't set the events up properly, so we can't use event_del() in + * close_closeable_connections() > connection_free() + * > connection_unregister_events() */ + if (conn->read_event) { + tor_free(conn->read_event); + conn->read_event = NULL; + } + if (conn->write_event) { + tor_free(conn->write_event); + conn->write_event = NULL; + } + + if (!conn->marked_for_close) { + connection_close_immediate(conn); + connection_mark_for_close(conn); + } + + close_closeable_connections(); + + /* The unit test will fail if we return 0 */ + return 1; + + /* When conn == NULL, we can't cleanup anything */ + done: + return 0; +} + +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)); + tt_assert(conn); + assert_connection_ok(&conn->base_, time(NULL)); + + rend_cache_init(); + + /* TODO: use directory_initiate_command_rend() to do this - maybe? */ + conn->rend_data = tor_malloc_zero(sizeof(rend_data_t)); + memcpy(conn->rend_data->onion_address, + TEST_CONN_REND_ADDR, + REND_SERVICE_ADDRESS_LEN+1); + conn->rend_data->hsdirs_fp = smartlist_new(); + conn->base_.purpose = TEST_CONN_REND_PURPOSE; + + 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 */ + return NULL; +} + +static int +test_conn_get_rend_teardown(const struct testcase_t *tc, void *arg) +{ + dir_connection_t *conn = DOWNCAST(dir_connection_t, arg); + int rv = 0; + + tt_assert(conn); + assert_connection_ok(&conn->base_, time(NULL)); + + /* avoid a last-ditch attempt to refetch the descriptor */ + conn->base_.purpose = TEST_CONN_REND_PURPOSE_SUCCESSFUL; + + /* connection_free_() cleans up rend_data */ + rv = test_conn_get_basic_teardown(tc, arg); + done: + rend_cache_free_all(); + return rv; +} + +static void * +test_conn_get_rsrc_setup(const struct testcase_t *tc) +{ + dir_connection_t *conn = DOWNCAST(dir_connection_t, + test_conn_get_basic_setup(tc)); + 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; + + 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 */ + return NULL; +} + +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; + + tt_assert(conn); + assert_connection_ok(&conn->base_, time(NULL)); + + /* avoid a last-ditch attempt to refetch the consensus */ + conn->base_.state = TEST_CONN_RSRC_STATE_SUCCESSFUL; + + /* connection_free_() cleans up requested_resource */ + rv = test_conn_get_basic_teardown(tc, arg); + done: + return rv; +} + +static void * +test_conn_download_status_setup(const struct testcase_t *tc) +{ + (void)tc; + + /* Don't return NULL, that causes the test to fail */ + return "ok"; +} + +static int +test_conn_download_status_teardown(const struct testcase_t *tc, void *arg) +{ + (void)arg; + int rv = 0; + + /* Ignore arg, and just loop through the connection array */ + SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) { + if (conn) { + assert_connection_ok(conn, time(NULL)); + + /* connection_free_() cleans up requested_resource */ + rv = test_conn_get_rsrc_teardown(tc, conn); + tt_assert(rv == 1); + } + } SMARTLIST_FOREACH_END(conn); + + done: + return rv; +} + +static dir_connection_t * +test_conn_download_status_add_a_connection(void) +{ + dir_connection_t *conn = DOWNCAST(dir_connection_t, + test_conn_get_rsrc_setup(NULL)); + + tt_assert(conn); + assert_connection_ok(&conn->base_, time(NULL)); + + return conn; + + done: + test_conn_download_status_teardown(NULL, NULL); + return NULL; +} + +static struct testcase_setup_t test_conn_get_basic_st = { + test_conn_get_basic_setup, test_conn_get_basic_teardown +}; + +static struct testcase_setup_t test_conn_get_rend_st = { + test_conn_get_rend_setup, test_conn_get_rend_teardown +}; + +static struct testcase_setup_t test_conn_get_rsrc_st = { + test_conn_get_rsrc_setup, test_conn_get_rsrc_teardown +}; + +static struct testcase_setup_t test_conn_download_status_st = { + test_conn_download_status_setup, test_conn_download_status_teardown +}; + +static void +test_conn_get_basic(void *arg) +{ + connection_t *conn = (connection_t*)arg; + tor_addr_t addr, addr2; + + tt_assert(conn); + assert_connection_ok(conn, time(NULL)); + + test_conn_lookup_addr_helper(TEST_CONN_ADDRESS, TEST_CONN_FAMILY, &addr); + tt_assert(!tor_addr_is_null(&addr)); + test_conn_lookup_addr_helper(TEST_CONN_ADDRESS_2, TEST_CONN_FAMILY, &addr2); + tt_assert(!tor_addr_is_null(&addr2)); + + /* Check that we get this connection back when we search for it by + * its attributes, but get NULL when we supply a different value. */ + + tt_assert(connection_get_by_global_id(conn->global_identifier) == conn); + tt_assert(connection_get_by_global_id(!conn->global_identifier) == NULL); + + tt_assert(connection_get_by_type(conn->type) == conn); + tt_assert(connection_get_by_type(TEST_CONN_TYPE) == conn); + tt_assert(connection_get_by_type(!conn->type) == NULL); + tt_assert(connection_get_by_type(!TEST_CONN_TYPE) == NULL); + + tt_assert(connection_get_by_type_state(conn->type, conn->state) + == conn); + tt_assert(connection_get_by_type_state(TEST_CONN_TYPE, TEST_CONN_STATE) + == conn); + tt_assert(connection_get_by_type_state(!conn->type, !conn->state) + == NULL); + tt_assert(connection_get_by_type_state(!TEST_CONN_TYPE, !TEST_CONN_STATE) + == NULL); + + /* Match on the connection fields themselves */ + tt_assert(connection_get_by_type_addr_port_purpose(conn->type, + &conn->addr, + conn->port, + conn->purpose) + == conn); + /* Match on the original inputs to the connection */ + tt_assert(connection_get_by_type_addr_port_purpose(TEST_CONN_TYPE, + &conn->addr, + conn->port, + conn->purpose) + == conn); + tt_assert(connection_get_by_type_addr_port_purpose(conn->type, + &addr, + conn->port, + conn->purpose) + == conn); + tt_assert(connection_get_by_type_addr_port_purpose(conn->type, + &conn->addr, + TEST_CONN_PORT, + conn->purpose) + == conn); + tt_assert(connection_get_by_type_addr_port_purpose(conn->type, + &conn->addr, + conn->port, + TEST_CONN_BASIC_PURPOSE) + == conn); + tt_assert(connection_get_by_type_addr_port_purpose(TEST_CONN_TYPE, + &addr, + TEST_CONN_PORT, + TEST_CONN_BASIC_PURPOSE) + == conn); + /* Then try each of the not-matching combinations */ + tt_assert(connection_get_by_type_addr_port_purpose(!conn->type, + &conn->addr, + conn->port, + conn->purpose) + == NULL); + tt_assert(connection_get_by_type_addr_port_purpose(conn->type, + &addr2, + conn->port, + conn->purpose) + == NULL); + tt_assert(connection_get_by_type_addr_port_purpose(conn->type, + &conn->addr, + !conn->port, + conn->purpose) + == NULL); + tt_assert(connection_get_by_type_addr_port_purpose(conn->type, + &conn->addr, + conn->port, + !conn->purpose) + == NULL); + /* Then try everything not-matching */ + tt_assert(connection_get_by_type_addr_port_purpose(!conn->type, + &addr2, + !conn->port, + !conn->purpose) + == NULL); + tt_assert(connection_get_by_type_addr_port_purpose(!TEST_CONN_TYPE, + &addr2, + !TEST_CONN_PORT, + !TEST_CONN_BASIC_PURPOSE) + == NULL); + + done: + ; +} + +static void +test_conn_get_rend(void *arg) +{ + dir_connection_t *conn = DOWNCAST(dir_connection_t, arg); + tt_assert(conn); + assert_connection_ok(&conn->base_, time(NULL)); + + tt_assert(connection_get_by_type_state_rendquery( + conn->base_.type, + conn->base_.state, + conn->rend_data->onion_address) + == TO_CONN(conn)); + tt_assert(connection_get_by_type_state_rendquery( + TEST_CONN_TYPE, + TEST_CONN_STATE, + TEST_CONN_REND_ADDR) + == TO_CONN(conn)); + tt_assert(connection_get_by_type_state_rendquery(TEST_CONN_REND_TYPE_2, + !conn->base_.state, + "") + == NULL); + tt_assert(connection_get_by_type_state_rendquery(TEST_CONN_REND_TYPE_2, + !TEST_CONN_STATE, + TEST_CONN_REND_ADDR_2) + == NULL); + + done: + ; +} + +#define sl_is_conn_assert(sl, conn) \ + do { \ + tt_assert(smartlist_len((sl)) == 1); \ + tt_assert(smartlist_get((sl), 0) == (conn)); \ + } while (0) + +#define sl_no_conn_assert(sl) \ + do { \ + tt_assert(smartlist_len((sl)) == 0); \ + } while (0) + +static void +test_conn_get_rsrc(void *arg) +{ + dir_connection_t *conn = DOWNCAST(dir_connection_t, 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), + conn); + sl_is_conn_assert(connection_dir_list_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, + TEST_CONN_RSRC), + conn); + sl_no_conn_assert(connection_dir_list_by_purpose_and_resource( + !conn->base_.purpose, + "")); + sl_no_conn_assert(connection_dir_list_by_purpose_and_resource( + !TEST_CONN_RSRC_PURPOSE, + TEST_CONN_RSRC_2)); + + sl_is_conn_assert(connection_dir_list_by_purpose_resource_and_state( + conn->base_.purpose, + conn->requested_resource, + conn->base_.state), + conn); + sl_is_conn_assert(connection_dir_list_by_purpose_resource_and_state( + TEST_CONN_RSRC_PURPOSE, + TEST_CONN_RSRC, + TEST_CONN_STATE), + conn); + sl_no_conn_assert(connection_dir_list_by_purpose_resource_and_state( + !conn->base_.purpose, + "", + !conn->base_.state)); + sl_no_conn_assert(connection_dir_list_by_purpose_resource_and_state( + !TEST_CONN_RSRC_PURPOSE, + TEST_CONN_RSRC_2, + !TEST_CONN_STATE)); + + tt_assert(connection_dir_count_by_purpose_and_resource( + conn->base_.purpose, + conn->requested_resource) + == 1); + tt_assert(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, + TEST_CONN_RSRC) + == 1); + tt_assert(connection_dir_count_by_purpose_and_resource( + !conn->base_.purpose, + "") + == 0); + tt_assert(connection_dir_count_by_purpose_and_resource( + !TEST_CONN_RSRC_PURPOSE, + TEST_CONN_RSRC_2) + == 0); + + tt_assert(connection_dir_count_by_purpose_resource_and_state( + conn->base_.purpose, + conn->requested_resource, + conn->base_.state) + == 1); + tt_assert(connection_dir_count_by_purpose_resource_and_state( + TEST_CONN_RSRC_PURPOSE, + TEST_CONN_RSRC, + TEST_CONN_STATE) + == 1); + tt_assert(connection_dir_count_by_purpose_resource_and_state( + !conn->base_.purpose, + "", + !conn->base_.state) + == 0); + tt_assert(connection_dir_count_by_purpose_resource_and_state( + !TEST_CONN_RSRC_PURPOSE, + TEST_CONN_RSRC_2, + !TEST_CONN_STATE) + == 0); + + done: + ; +} + +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); + + /* 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); + + /* one connection, no excess, but downloading */ + conn->base_.state = TEST_CONN_DL_STATE; + tt_assert(networkstatus_consensus_has_excess_connections() == 0); + tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 1); + conn->base_.state = TEST_CONN_STATE; + + /* 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); + + /* 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); + 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); + + /* 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); + + /* 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); + + /* 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_boostrapping(time(NULL))); + + tt_assert(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, + TEST_CONN_RSRC) == 3); + tt_assert(connection_dir_close_consensus_conn_if_extra(conn) == -1); + tt_assert(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, + TEST_CONN_RSRC) == 2); + + /* now try closing one that is downloading - it stays open */ + tt_assert(connection_dir_close_consensus_conn_if_extra(conn) == 0); + tt_assert(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, + TEST_CONN_RSRC) == 2); + + /* now try closing all excess connections */ + connection_dir_close_extra_consensus_conns(); + tt_assert(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, + TEST_CONN_RSRC) == 1); + + done: + /* the teardown function removes all the connections */; +} + +#define CONNECTION_TESTCASE(name, fork, setup) \ + { #name, test_conn_##name, fork, &setup, NULL } + +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(func_suffix, TT_FORK, setup_func_pair), + END_OF_TESTCASES +}; + |