tor/src/test/test_routerlist.c
teor (Tim Wilson-Brown) e72cbf7a4e Choose directory servers by IPv4/IPv6 preferences
Add unit tests, refactor pick_directory functions.
2016-01-29 07:13:57 +11:00

179 lines
5.3 KiB
C

/* Copyright (c) 2014, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define ROUTERLIST_PRIVATE
#include "or.h"
#include "routerlist.h"
#include "directory.h"
#include "connection.h"
#include "test.h"
/* 4 digests + 3 sep + pre + post + NULL */
static char output[4*BASE64_DIGEST256_LEN+3+2+2+1];
static void
mock_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
const char *resource, int pds_flags,
download_want_authority_t want_authority)
{
(void)dir_purpose;
(void)router_purpose;
(void)pds_flags;
(void)want_authority;
tt_assert(resource);
strlcpy(output, resource, sizeof(output));
done:
;
}
static void
test_routerlist_initiate_descriptor_downloads(void *arg)
{
const char *prose = "unhurried and wise, we perceive.";
smartlist_t *digests = smartlist_new();
(void)arg;
for (int i = 0; i < 20; i++) {
smartlist_add(digests, (char*)prose);
}
MOCK(directory_get_from_dirserver, mock_get_from_dirserver);
initiate_descriptor_downloads(NULL, DIR_PURPOSE_FETCH_MICRODESC,
digests, 3, 7, 0);
UNMOCK(directory_get_from_dirserver);
tt_str_op(output, OP_EQ, "d/"
"dW5odXJyaWVkIGFuZCB3aXNlLCB3ZSBwZXJjZWl2ZS4-"
"dW5odXJyaWVkIGFuZCB3aXNlLCB3ZSBwZXJjZWl2ZS4-"
"dW5odXJyaWVkIGFuZCB3aXNlLCB3ZSBwZXJjZWl2ZS4-"
"dW5odXJyaWVkIGFuZCB3aXNlLCB3ZSBwZXJjZWl2ZS4"
".z");
done:
smartlist_free(digests);
}
static int count = 0;
static void
mock_initiate_descriptor_downloads(const routerstatus_t *source,
int purpose, smartlist_t *digests,
int lo, int hi, int pds_flags)
{
(void)source;
(void)purpose;
(void)digests;
(void)pds_flags;
(void)hi;
(void)lo;
count += 1;
}
static void
test_routerlist_launch_descriptor_downloads(void *arg)
{
smartlist_t *downloadable = smartlist_new();
time_t now = time(NULL);
char *cp;
(void)arg;
for (int i = 0; i < 100; i++) {
cp = tor_malloc(DIGEST256_LEN);
tt_assert(cp);
crypto_rand(cp, DIGEST256_LEN);
smartlist_add(downloadable, cp);
}
MOCK(initiate_descriptor_downloads, mock_initiate_descriptor_downloads);
launch_descriptor_downloads(DIR_PURPOSE_FETCH_MICRODESC, downloadable,
NULL, now);
tt_int_op(3, ==, count);
UNMOCK(initiate_descriptor_downloads);
done:
SMARTLIST_FOREACH(downloadable, char *, cp1, tor_free(cp1));
smartlist_free(downloadable);
}
connection_t *mocked_connection = NULL;
/* Mock connection_get_by_type_addr_port_purpose by returning
* mocked_connection. */
static connection_t *
mock_connection_get_by_type_addr_port_purpose(int type,
const tor_addr_t *addr,
uint16_t port, int purpose)
{
(void)type;
(void)addr;
(void)port;
(void)purpose;
return mocked_connection;
}
#define TEST_ADDR_STR "127.0.0.1"
#define TEST_DIR_PORT 12345
static void
test_routerlist_router_is_already_dir_fetching(void *arg)
{
(void)arg;
tor_addr_port_t test_ap, null_addr_ap, zero_port_ap;
/* Setup */
tor_addr_parse(&test_ap.addr, TEST_ADDR_STR);
test_ap.port = TEST_DIR_PORT;
tor_addr_make_null(&null_addr_ap.addr, AF_INET6);
null_addr_ap.port = TEST_DIR_PORT;
tor_addr_parse(&zero_port_ap.addr, TEST_ADDR_STR);
zero_port_ap.port = 0;
MOCK(connection_get_by_type_addr_port_purpose,
mock_connection_get_by_type_addr_port_purpose);
/* Test that we never get 1 from a NULL connection */
mocked_connection = NULL;
tt_assert(router_is_already_dir_fetching(&test_ap, 1, 1) == 0);
tt_assert(router_is_already_dir_fetching(&test_ap, 1, 0) == 0);
tt_assert(router_is_already_dir_fetching(&test_ap, 0, 1) == 0);
/* We always expect 0 in these cases */
tt_assert(router_is_already_dir_fetching(&test_ap, 0, 0) == 0);
tt_assert(router_is_already_dir_fetching(NULL, 1, 1) == 0);
tt_assert(router_is_already_dir_fetching(&null_addr_ap, 1, 1) == 0);
tt_assert(router_is_already_dir_fetching(&zero_port_ap, 1, 1) == 0);
/* Test that we get 1 with a connection in the appropriate circumstances */
mocked_connection = connection_new(CONN_TYPE_DIR, AF_INET);
tt_assert(router_is_already_dir_fetching(&test_ap, 1, 1) == 1);
tt_assert(router_is_already_dir_fetching(&test_ap, 1, 0) == 1);
tt_assert(router_is_already_dir_fetching(&test_ap, 0, 1) == 1);
/* Test that we get 0 even with a connection in the appropriate
* circumstances */
tt_assert(router_is_already_dir_fetching(&test_ap, 0, 0) == 0);
tt_assert(router_is_already_dir_fetching(NULL, 1, 1) == 0);
tt_assert(router_is_already_dir_fetching(&null_addr_ap, 1, 1) == 0);
tt_assert(router_is_already_dir_fetching(&zero_port_ap, 1, 1) == 0);
done:
/* If a connection is never set up, connection_free chokes on it. */
buf_free(mocked_connection->inbuf);
buf_free(mocked_connection->outbuf);
tor_free(mocked_connection);
UNMOCK(connection_get_by_type_addr_port_purpose);
}
#undef TEST_ADDR_STR
#undef TEST_DIR_PORT
#define NODE(name, flags) \
{ #name, test_routerlist_##name, (flags), NULL, NULL }
struct testcase_t routerlist_tests[] = {
NODE(initiate_descriptor_downloads, 0),
NODE(launch_descriptor_downloads, 0),
NODE(router_is_already_dir_fetching, TT_FORK),
END_OF_TESTCASES
};