diff options
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/bench.c | 5 | ||||
-rw-r--r-- | src/test/include.am | 10 | ||||
-rw-r--r-- | src/test/test.c | 52 | ||||
-rw-r--r-- | src/test/test.h | 12 | ||||
-rw-r--r-- | src/test/test_addr.c | 37 | ||||
-rw-r--r-- | src/test/test_buffers.c | 264 | ||||
-rw-r--r-- | src/test/test_circuitlist.c | 6 | ||||
-rw-r--r-- | src/test/test_config.c | 19 | ||||
-rw-r--r-- | src/test/test_crypto.c | 149 | ||||
-rw-r--r-- | src/test/test_dir.c | 14 | ||||
-rw-r--r-- | src/test/test_extorport.c | 4 | ||||
-rw-r--r-- | src/test/test_hs.c | 70 | ||||
-rw-r--r-- | src/test/test_nodelist.c | 71 | ||||
-rw-r--r-- | src/test/test_oom.c | 348 | ||||
-rw-r--r-- | src/test/test_router.c | 37 | ||||
-rw-r--r-- | src/test/test_routerkeys.c | 84 | ||||
-rw-r--r-- | src/test/test_util.c | 11 |
17 files changed, 1068 insertions, 125 deletions
diff --git a/src/test/bench.c b/src/test/bench.c index e650569a75..c9cc101b72 100644 --- a/src/test/bench.c +++ b/src/test/bench.c @@ -438,6 +438,10 @@ bench_ecdh_impl(int nid, const char *name) ssize_t slen_a, slen_b; EC_KEY *dh_a = EC_KEY_new_by_curve_name(nid); EC_KEY *dh_b = EC_KEY_new_by_curve_name(nid); + if (!dh_a || !dh_b) { + puts("Skipping. (No implementation?)"); + return; + } EC_KEY_generate_key(dh_a); EC_KEY_generate_key(dh_b); @@ -540,6 +544,7 @@ main(int argc, const char **argv) reset_perftime(); crypto_seed_rng(1); + crypto_init_siphash_key(); options = options_new(); init_logging(); options->command = CMD_RUN_UNITTESTS; diff --git a/src/test/include.am b/src/test/include.am index b338cbe3e6..c6743a19b0 100644 --- a/src/test/include.am +++ b/src/test/include.am @@ -32,14 +32,16 @@ src_test_test_SOURCES = \ src/test/test_introduce.c \ src/test/test_logging.c \ src/test/test_microdesc.c \ + src/test/test_oom.c \ src/test/test_options.c \ src/test/test_pt.c \ src/test/test_replay.c \ + src/test/test_routerkeys.c \ src/test/test_socks.c \ src/test/test_util.c \ src/test/test_config.c \ src/test/test_hs.c \ - src/test/test_router.c \ + src/test/test_nodelist.c \ src/ext/tinytest.c src_test_test_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) @@ -108,3 +110,9 @@ endif ./src/test/test-bt-cl assert | $(PYTHON) $(top_srcdir)/src/test/bt_test.py ./src/test/test-bt-cl crash | $(PYTHON) $(top_srcdir)/src/test/bt_test.py endif + +EXTRA_DIST += \ + src/test/bt_test.py \ + src/test/ntor_ref.py \ + src/test/slownacl_curve25519.py \ + src/test/test_cmdline_args.py diff --git a/src/test/test.c b/src/test/test.c index 8b2a5ad67d..0ba5da3672 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -638,7 +638,7 @@ test_policy_summary_helper(const char *policy_str, line.value = (char *)policy_str; line.next = NULL; - r = policies_parse_exit_policy(&line, &policy, 1, 0, NULL, 1); + r = policies_parse_exit_policy(&line, &policy, 1, 0, 0, 1); test_eq(r, 0); summary = policy_summarize(policy, AF_INET); @@ -671,6 +671,7 @@ test_policies(void) config_line_t line; smartlist_t *sm = NULL; char *policy_str = NULL; + short_policy_t *short_parsed = NULL; policy = smartlist_new(); @@ -695,7 +696,7 @@ test_policies(void) test_assert(ADDR_POLICY_REJECTED == compare_tor_addr_to_addr_policy(&tar, 2, policy)); - test_assert(0 == policies_parse_exit_policy(NULL, &policy2, 1, 1, NULL, 1)); + test_assert(0 == policies_parse_exit_policy(NULL, &policy2, 1, 1, 0, 1)); test_assert(policy2); policy3 = smartlist_new(); @@ -782,7 +783,7 @@ test_policies(void) line.key = (char*)"foo"; line.value = (char*)"accept *:80,reject private:*,reject *:*"; line.next = NULL; - test_assert(0 == policies_parse_exit_policy(&line, &policy, 1, 0, NULL, 1)); + test_assert(0 == policies_parse_exit_policy(&line, &policy, 1, 0, 0, 1)); test_assert(policy); //test_streq(policy->string, "accept *:80"); //test_streq(policy->next->string, "reject *:*"); @@ -858,19 +859,24 @@ test_policies(void) test_short_policy_parse("reject ,1-10,,,,30-40", "reject 1-10,30-40"); /* Try parsing various broken short policies */ - tt_ptr_op(NULL, ==, parse_short_policy("accept 200-199")); - tt_ptr_op(NULL, ==, parse_short_policy("")); - tt_ptr_op(NULL, ==, parse_short_policy("rejekt 1,2,3")); - tt_ptr_op(NULL, ==, parse_short_policy("reject ")); - tt_ptr_op(NULL, ==, parse_short_policy("reject")); - tt_ptr_op(NULL, ==, parse_short_policy("rej")); - tt_ptr_op(NULL, ==, parse_short_policy("accept 2,3,100000")); - tt_ptr_op(NULL, ==, parse_short_policy("accept 2,3x,4")); - tt_ptr_op(NULL, ==, parse_short_policy("accept 2,3x,4")); - tt_ptr_op(NULL, ==, parse_short_policy("accept 2-")); - tt_ptr_op(NULL, ==, parse_short_policy("accept 2-x")); - tt_ptr_op(NULL, ==, parse_short_policy("accept 1-,3")); - tt_ptr_op(NULL, ==, parse_short_policy("accept 1-,3")); +#define TT_BAD_SHORT_POLICY(s) \ + do { \ + tt_ptr_op(NULL, ==, (short_parsed = parse_short_policy((s)))); \ + } while (0) + TT_BAD_SHORT_POLICY("accept 200-199"); + TT_BAD_SHORT_POLICY(""); + TT_BAD_SHORT_POLICY("rejekt 1,2,3"); + TT_BAD_SHORT_POLICY("reject "); + TT_BAD_SHORT_POLICY("reject"); + TT_BAD_SHORT_POLICY("rej"); + TT_BAD_SHORT_POLICY("accept 2,3,100000"); + TT_BAD_SHORT_POLICY("accept 2,3x,4"); + TT_BAD_SHORT_POLICY("accept 2,3x,4"); + TT_BAD_SHORT_POLICY("accept 2-"); + TT_BAD_SHORT_POLICY("accept 2-x"); + TT_BAD_SHORT_POLICY("accept 1-,3"); + TT_BAD_SHORT_POLICY("accept 1-,3"); + /* Test a too-long policy. */ { int i; @@ -883,8 +889,9 @@ test_policies(void) policy = smartlist_join_strings(chunks, "", 0, NULL); SMARTLIST_FOREACH(chunks, char *, ch, tor_free(ch)); smartlist_free(chunks); - tt_ptr_op(NULL, ==, parse_short_policy(policy));/* shouldn't be accepted */ - tor_free(policy); /* could leak. */ + short_parsed = parse_short_policy(policy);/* shouldn't be accepted */ + tor_free(policy); + tt_ptr_op(NULL, ==, short_parsed); } /* truncation ports */ @@ -925,6 +932,7 @@ test_policies(void) SMARTLIST_FOREACH(sm, char *, s, tor_free(s)); smartlist_free(sm); } + short_policy_free(short_parsed); } /** Test encoding and parsing of rendezvous service descriptors. */ @@ -1626,7 +1634,9 @@ extern struct testcase_t controller_event_tests[]; extern struct testcase_t logging_tests[]; extern struct testcase_t backtrace_tests[]; extern struct testcase_t hs_tests[]; -extern struct testcase_t router_tests[]; +extern struct testcase_t nodelist_tests[]; +extern struct testcase_t routerkeys_tests[]; +extern struct testcase_t oom_tests[]; static struct testgroup_t testgroups[] = { { "", test_array }, @@ -1651,7 +1661,9 @@ static struct testgroup_t testgroups[] = { { "extorport/", extorport_tests }, { "control/", controller_event_tests }, { "hs/", hs_tests }, - { "router/", router_tests }, + { "nodelist/", nodelist_tests }, + { "routerkeys/", routerkeys_tests }, + { "oom/", oom_tests }, END_OF_GROUPS }; diff --git a/src/test/test.h b/src/test/test.h index a89b558e5a..ba82f52add 100644 --- a/src/test/test.h +++ b/src/test/test.h @@ -36,17 +36,7 @@ #define test_strneq(expr1, expr2) tt_str_op((expr1), !=, (expr2)) #define test_mem_op(expr1, op, expr2, len) \ - tt_assert_test_fmt_type(expr1,expr2,#expr1" "#op" "#expr2, \ - const char *, \ - (memcmp(val1_, val2_, len) op 0), \ - char *, "%s", \ - { size_t printlen = (len)*2+1; \ - print_ = tor_malloc(printlen); \ - base16_encode(print_, printlen, value_, \ - (len)); }, \ - { tor_free(print_); }, \ - TT_EXIT_TEST_FUNCTION \ - ); + tt_mem_op((expr1), op, (expr2), (len)) #define test_memeq(expr1, expr2, len) test_mem_op((expr1), ==, (expr2), len) #define test_memneq(expr1, expr2, len) test_mem_op((expr1), !=, (expr2), len) diff --git a/src/test/test_addr.c b/src/test/test_addr.c index 829697b1e8..1c2a90e1ec 100644 --- a/src/test/test_addr.c +++ b/src/test/test_addr.c @@ -898,7 +898,7 @@ test_addr_sockaddr_to_str(void *arg) struct sockaddr_in6 sin6; struct sockaddr_storage ss; #ifdef HAVE_SYS_UN_H - struct sockaddr_un sun; + struct sockaddr_un s_un; #endif #define CHECK(sa, s) do { \ v = tor_sockaddr_to_str((const struct sockaddr*) &(sa)); \ @@ -918,10 +918,10 @@ test_addr_sockaddr_to_str(void *arg) CHECK(sin, "127.128.128.1:1234"); #ifdef HAVE_SYS_UN_H - memset(&sun,0,sizeof(sun)); - sun.sun_family = AF_UNIX; - strlcpy(sun.sun_path, "/here/is/a/path", sizeof(sun.sun_path)); - CHECK(sun, "unix:/here/is/a/path"); + memset(&s_un,0,sizeof(s_un)); + s_un.sun_family = AF_UNIX; + strlcpy(s_un.sun_path, "/here/is/a/path", sizeof(s_un.sun_path)); + CHECK(s_un, "unix:/here/is/a/path"); #endif memset(&sin6,0,sizeof(sin6)); @@ -970,6 +970,32 @@ test_addr_is_loopback(void *data) ; } +static void +test_addr_make_null(void *data) +{ + tor_addr_t *addr = tor_malloc(sizeof(*addr)); + tor_addr_t *zeros = tor_malloc_zero(sizeof(*addr)); + char buf[TOR_ADDR_BUF_LEN]; + (void) data; + /* Ensure that before tor_addr_make_null, addr != 0's */ + memset(addr, 1, sizeof(*addr)); + tt_int_op(memcmp(addr, zeros, sizeof(*addr)), !=, 0); + /* Test with AF == AF_INET */ + zeros->family = AF_INET; + tor_addr_make_null(addr, AF_INET); + tt_int_op(memcmp(addr, zeros, sizeof(*addr)), ==, 0); + tt_str_op(tor_addr_to_str(buf, addr, sizeof(buf), 0), ==, "0.0.0.0"); + /* Test with AF == AF_INET6 */ + memset(addr, 1, sizeof(*addr)); + zeros->family = AF_INET6; + tor_addr_make_null(addr, AF_INET6); + tt_int_op(memcmp(addr, zeros, sizeof(*addr)), ==, 0); + tt_str_op(tor_addr_to_str(buf, addr, sizeof(buf), 0), ==, "::"); + done: + tor_free(addr); + tor_free(zeros); +} + #define ADDR_LEGACY(name) \ { #name, legacy_test_helper, 0, &legacy_setup, test_addr_ ## name } @@ -982,6 +1008,7 @@ struct testcase_t addr_tests[] = { { "dup_ip", test_addr_dup_ip, 0, NULL, NULL }, { "sockaddr_to_str", test_addr_sockaddr_to_str, 0, NULL, NULL }, { "is_loopback", test_addr_is_loopback, 0, NULL, NULL }, + { "make_null", test_addr_make_null, 0, NULL, NULL }, END_OF_TESTCASES }; diff --git a/src/test/test_buffers.c b/src/test/test_buffers.c index a009faa0be..6dd7715936 100644 --- a/src/test/test_buffers.c +++ b/src/test/test_buffers.c @@ -193,7 +193,120 @@ test_buffers_basic(void *arg) buf_free(buf); if (buf2) buf_free(buf2); + buf_shrink_freelists(1); } + +static void +test_buffer_pullup(void *arg) +{ + buf_t *buf; + char *stuff, *tmp; + const char *cp; + size_t sz; + (void)arg; + stuff = tor_malloc(16384); + tmp = tor_malloc(16384); + + /* Note: this test doesn't check the nulterminate argument to buf_pullup, + since nothing actually uses it. We should remove it some time. */ + + buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */ + + tt_assert(buf); + tt_int_op(buf_get_default_chunk_size(buf), ==, 4096); + + tt_int_op(buf_get_total_allocation(), ==, 0); + + /* There are a bunch of cases for pullup. One is the trivial case. Let's + mess around with an empty buffer. */ + buf_pullup(buf, 16, 1); + buf_get_first_chunk_data(buf, &cp, &sz); + tt_ptr_op(cp, ==, NULL); + tt_ptr_op(sz, ==, 0); + + /* Let's make sure nothing got allocated */ + tt_int_op(buf_get_total_allocation(), ==, 0); + + /* Case 1: everything puts into the first chunk with some moving. */ + + /* Let's add some data. */ + crypto_rand(stuff, 16384); + write_to_buf(stuff, 3000, buf); + write_to_buf(stuff+3000, 3000, buf); + buf_get_first_chunk_data(buf, &cp, &sz); + tt_ptr_op(cp, !=, NULL); + tt_int_op(sz, <=, 4096); + + /* Make room for 3000 bytes in the first chunk, so that the pullup-move code + * can get tested. */ + tt_int_op(fetch_from_buf(tmp, 3000, buf), ==, 3000); + test_memeq(tmp, stuff, 3000); + buf_pullup(buf, 2048, 0); + assert_buf_ok(buf); + buf_get_first_chunk_data(buf, &cp, &sz); + tt_ptr_op(cp, !=, NULL); + tt_int_op(sz, >=, 2048); + test_memeq(cp, stuff+3000, 2048); + tt_int_op(3000, ==, buf_datalen(buf)); + tt_int_op(fetch_from_buf(tmp, 3000, buf), ==, 0); + test_memeq(tmp, stuff+3000, 2048); + + buf_free(buf); + + /* Now try the large-chunk case. */ + buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */ + write_to_buf(stuff, 4000, buf); + write_to_buf(stuff+4000, 4000, buf); + write_to_buf(stuff+8000, 4000, buf); + write_to_buf(stuff+12000, 4000, buf); + tt_int_op(buf_datalen(buf), ==, 16000); + buf_get_first_chunk_data(buf, &cp, &sz); + tt_ptr_op(cp, !=, NULL); + tt_int_op(sz, <=, 4096); + + buf_pullup(buf, 12500, 0); + assert_buf_ok(buf); + buf_get_first_chunk_data(buf, &cp, &sz); + tt_ptr_op(cp, !=, NULL); + tt_int_op(sz, >=, 12500); + test_memeq(cp, stuff, 12500); + tt_int_op(buf_datalen(buf), ==, 16000); + + fetch_from_buf(tmp, 12400, buf); + test_memeq(tmp, stuff, 12400); + tt_int_op(buf_datalen(buf), ==, 3600); + fetch_from_buf(tmp, 3500, buf); + test_memeq(tmp, stuff+12400, 3500); + fetch_from_buf(tmp, 100, buf); + test_memeq(tmp, stuff+15900, 10); + + buf_free(buf); + + /* Make sure that the pull-up-whole-buffer case works */ + buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */ + write_to_buf(stuff, 4000, buf); + write_to_buf(stuff+4000, 4000, buf); + fetch_from_buf(tmp, 100, buf); /* dump 100 bytes from first chunk */ + buf_pullup(buf, 16000, 0); /* Way too much. */ + assert_buf_ok(buf); + buf_get_first_chunk_data(buf, &cp, &sz); + tt_ptr_op(cp, !=, NULL); + tt_int_op(sz, ==, 7900); + test_memeq(cp, stuff+100, 7900); + + buf_free(buf); + buf = NULL; + + buf_shrink_freelists(1); + + tt_int_op(buf_get_total_allocation(), ==, 0); + done: + buf_free(buf); + buf_shrink_freelists(1); + tor_free(stuff); + tor_free(tmp); +} + static void test_buffer_copy(void *arg) { @@ -257,6 +370,7 @@ test_buffer_copy(void *arg) generic_buffer_free(buf); if (buf2) generic_buffer_free(buf2); + buf_shrink_freelists(1); } static void @@ -331,12 +445,156 @@ test_buffer_ext_or_cmd(void *arg) ext_or_cmd_free(cmd); generic_buffer_free(buf); tor_free(tmp); + buf_shrink_freelists(1); +} + +static void +test_buffer_allocation_tracking(void *arg) +{ + char *junk = tor_malloc(16384); + buf_t *buf1 = NULL, *buf2 = NULL; + int i; + + (void)arg; + + crypto_rand(junk, 16384); + tt_int_op(buf_get_total_allocation(), ==, 0); + + buf1 = buf_new(); + tt_assert(buf1); + buf2 = buf_new(); + tt_assert(buf2); + + tt_int_op(buf_allocation(buf1), ==, 0); + tt_int_op(buf_get_total_allocation(), ==, 0); + + write_to_buf(junk, 4000, buf1); + write_to_buf(junk, 4000, buf1); + write_to_buf(junk, 4000, buf1); + write_to_buf(junk, 4000, buf1); + tt_int_op(buf_allocation(buf1), ==, 16384); + fetch_from_buf(junk, 100, buf1); + tt_int_op(buf_allocation(buf1), ==, 16384); /* still 4 4k chunks */ + + tt_int_op(buf_get_total_allocation(), ==, 16384); + + fetch_from_buf(junk, 4096, buf1); /* drop a 1k chunk... */ + tt_int_op(buf_allocation(buf1), ==, 3*4096); /* now 3 4k chunks */ + + tt_int_op(buf_get_total_allocation(), ==, 16384); /* that chunk went onto + the freelist. */ + + write_to_buf(junk, 4000, buf2); + tt_int_op(buf_allocation(buf2), ==, 4096); /* another 4k chunk. */ + tt_int_op(buf_get_total_allocation(), ==, 16384); /* that chunk came from + the freelist. */ + write_to_buf(junk, 4000, buf2); + tt_int_op(buf_allocation(buf2), ==, 8192); /* another 4k chunk. */ + tt_int_op(buf_get_total_allocation(), ==, 5*4096); /* that chunk was new. */ + + /* Make a really huge buffer */ + for (i = 0; i < 1000; ++i) { + write_to_buf(junk, 4000, buf2); + } + tt_int_op(buf_allocation(buf2), >=, 4008000); + tt_int_op(buf_get_total_allocation(), >=, 4008000); + buf_free(buf2); + buf2 = NULL; + + tt_int_op(buf_get_total_allocation(), <, 4008000); + buf_shrink_freelists(1); + tt_int_op(buf_get_total_allocation(), ==, buf_allocation(buf1)); + buf_free(buf1); + buf1 = NULL; + buf_shrink_freelists(1); + tt_int_op(buf_get_total_allocation(), ==, 0); + + done: + buf_free(buf1); + buf_free(buf2); + buf_shrink_freelists(1); +} + +static void +test_buffer_time_tracking(void *arg) +{ + buf_t *buf=NULL, *buf2=NULL; + struct timeval tv0; + const time_t START = 1389288246; + const uint32_t START_MSEC = (uint32_t) ((uint64_t)START * 1000); + int i; + char tmp[4096]; + (void)arg; + + crypto_rand(tmp, sizeof(tmp)); + + tv0.tv_sec = START; + tv0.tv_usec = 0; + + buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */ + tt_assert(buf); + + /* Empty buffer means the timestamp is 0. */ + tt_int_op(0, ==, buf_get_oldest_chunk_timestamp(buf, START_MSEC)); + tt_int_op(0, ==, buf_get_oldest_chunk_timestamp(buf, START_MSEC+1000)); + + tor_gettimeofday_cache_set(&tv0); + write_to_buf("ABCDEFG", 7, buf); + tt_int_op(1000, ==, buf_get_oldest_chunk_timestamp(buf, START_MSEC+1000)); + + buf2 = buf_copy(buf); + tt_assert(buf2); + tt_int_op(1234, ==, buf_get_oldest_chunk_timestamp(buf2, START_MSEC+1234)); + + /* Now add more bytes; enough to overflow the first chunk. */ + tv0.tv_usec += 123 * 1000; + tor_gettimeofday_cache_set(&tv0); + for (i = 0; i < 600; ++i) + write_to_buf("ABCDEFG", 7, buf); + tt_int_op(4207, ==, buf_datalen(buf)); + + /* The oldest bytes are still in the front. */ + tt_int_op(2000, ==, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2000)); + + /* Once those bytes are dropped, the chunk is still on the first + * timestamp. */ + fetch_from_buf(tmp, 100, buf); + tt_int_op(2000, ==, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2000)); + + /* But once we discard the whole first chunk, we get the data in the second + * chunk. */ + fetch_from_buf(tmp, 4000, buf); + tt_int_op(107, ==, buf_datalen(buf)); + tt_int_op(2000, ==, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2123)); + + /* This time we'll be grabbing a chunk from the freelist, and making sure + its time gets updated */ + tv0.tv_sec += 5; + tv0.tv_usec = 617*1000; + tor_gettimeofday_cache_set(&tv0); + for (i = 0; i < 600; ++i) + write_to_buf("ABCDEFG", 7, buf); + tt_int_op(4307, ==, buf_datalen(buf)); + + tt_int_op(2000, ==, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2123)); + fetch_from_buf(tmp, 4000, buf); + fetch_from_buf(tmp, 306, buf); + tt_int_op(0, ==, buf_get_oldest_chunk_timestamp(buf, START_MSEC+5617)); + tt_int_op(383, ==, buf_get_oldest_chunk_timestamp(buf, START_MSEC+6000)); + + done: + buf_free(buf); + buf_free(buf2); } struct testcase_t buffer_tests[] = { - { "basic", test_buffers_basic, 0, NULL, NULL }, - { "copy", test_buffer_copy, 0, NULL, NULL }, - { "ext_or_cmd", test_buffer_ext_or_cmd, 0, NULL, NULL }, + { "basic", test_buffers_basic, TT_FORK, NULL, NULL }, + { "copy", test_buffer_copy, TT_FORK, NULL, NULL }, + { "pullup", test_buffer_pullup, TT_FORK, NULL, NULL }, + { "ext_or_cmd", test_buffer_ext_or_cmd, TT_FORK, NULL, NULL }, + { "allocation_tracking", test_buffer_allocation_tracking, TT_FORK, + NULL, NULL }, + { "time_tracking", test_buffer_time_tracking, TT_FORK, NULL, NULL }, END_OF_TESTCASES }; diff --git a/src/test/test_circuitlist.c b/src/test/test_circuitlist.c index 720b407659..54aa51d3c7 100644 --- a/src/test/test_circuitlist.c +++ b/src/test/test_circuitlist.c @@ -150,13 +150,13 @@ test_clist_maps(void *arg) tt_assert(! circuit_id_in_use_on_channel(100, ch1)); done: - tor_free(ch1); - tor_free(ch2); - tor_free(ch3); if (or_c1) circuit_free(TO_CIRCUIT(or_c1)); if (or_c2) circuit_free(TO_CIRCUIT(or_c2)); + tor_free(ch1); + tor_free(ch2); + tor_free(ch3); UNMOCK(circuitmux_attach_circuit); UNMOCK(circuitmux_detach_circuit); } diff --git a/src/test/test_config.c b/src/test/test_config.c index 6a285db6e3..3a1e6cb78a 100644 --- a/src/test/test_config.c +++ b/src/test/test_config.c @@ -221,12 +221,17 @@ test_config_check_or_create_data_subdir(void *arg) // and is private to the user. test_assert(!check_or_create_data_subdir(subdir)); + r = stat(subpath, &st); + if (r) { + tt_abort_perror("stat"); + } + #if !defined (_WIN32) || defined (WINCE) group_permission = st.st_mode | 0070; r = chmod(subpath, group_permission); if (r) { - test_fail_msg("Changing permissions for the subdirectory failed."); + tt_abort_perror("chmod"); } // If the directory exists, but its mode is too permissive @@ -247,6 +252,7 @@ test_config_write_to_data_subdir(void *arg) { or_options_t* options = get_options_mutable(); char *datadir = options->DataDirectory = tor_strdup(get_fname("datadir-1")); + char *cp = NULL; const char* subdir = "test_stats"; const char* fname = "test_file"; const char* str = @@ -280,17 +286,22 @@ test_config_write_to_data_subdir(void *arg) // Content of file after write attempt should be // equal to the original string. test_assert(!write_to_data_subdir(subdir, fname, str, NULL)); - test_streq(read_file_to_str(filepath, 0, NULL), str); + cp = read_file_to_str(filepath, 0, NULL); + test_streq(cp, str); + tor_free(cp); // A second write operation should overwrite the old content. test_assert(!write_to_data_subdir(subdir, fname, str, NULL)); - test_streq(read_file_to_str(filepath, 0, NULL), str); + cp = read_file_to_str(filepath, 0, NULL); + test_streq(cp, str); + tor_free(cp); done: (void) unlink(filepath); rmdir(options->DataDirectory); tor_free(datadir); tor_free(filepath); + tor_free(cp); } /* Test helper function: Make sure that a bridge line gets parsed @@ -358,6 +369,8 @@ static void bad_bridge_line_test(const char *string) { bridge_line_t *bridge_line = parse_bridge_line(string); + if (bridge_line) + TT_FAIL(("%s was supposed to fail, but it didn't.", string)); test_assert(!bridge_line); done: diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c index 22adc6cc34..1fda334760 100644 --- a/src/test/test_crypto.c +++ b/src/test/test_crypto.c @@ -9,6 +9,7 @@ #include "test.h" #include "aes.h" #include "util.h" +#include "siphash.h" #ifdef CURVE25519_ENABLED #include "crypto_curve25519.h" #endif @@ -508,6 +509,56 @@ test_crypto_pk(void) tor_free(encoded); } +static void +test_crypto_pk_fingerprints(void *arg) +{ + crypto_pk_t *pk = NULL; + char encoded[512]; + char d[DIGEST_LEN], d2[DIGEST_LEN]; + char fingerprint[FINGERPRINT_LEN+1]; + int n; + unsigned i; + char *mem_op_hex_tmp=NULL; + + (void)arg; + + pk = pk_generate(1); + tt_assert(pk); + n = crypto_pk_asn1_encode(pk, encoded, sizeof(encoded)); + tt_int_op(n, >, 0); + tt_int_op(n, >, 128); + tt_int_op(n, <, 256); + + /* Is digest as expected? */ + crypto_digest(d, encoded, n); + tt_int_op(0, ==, crypto_pk_get_digest(pk, d2)); + test_memeq(d, d2, DIGEST_LEN); + + /* Is fingerprint right? */ + tt_int_op(0, ==, crypto_pk_get_fingerprint(pk, fingerprint, 0)); + tt_int_op(strlen(fingerprint), ==, DIGEST_LEN * 2); + test_memeq_hex(d, fingerprint); + + /* Are spaces right? */ + tt_int_op(0, ==, crypto_pk_get_fingerprint(pk, fingerprint, 1)); + for (i = 4; i < strlen(fingerprint); i += 5) { + tt_int_op(fingerprint[i], ==, ' '); + } + tor_strstrip(fingerprint, " "); + tt_int_op(strlen(fingerprint), ==, DIGEST_LEN * 2); + test_memeq_hex(d, fingerprint); + + /* Now hash again and check crypto_pk_get_hashed_fingerprint. */ + crypto_digest(d2, d, sizeof(d)); + tt_int_op(0, ==, crypto_pk_get_hashed_fingerprint(pk, fingerprint)); + tt_int_op(strlen(fingerprint), ==, DIGEST_LEN * 2); + test_memeq_hex(d2, fingerprint); + + done: + crypto_pk_free(pk); + tor_free(mem_op_hex_tmp); +} + /** Sanity check for crypto pk digests */ static void test_crypto_digests(void) @@ -1111,6 +1162,102 @@ test_crypto_curve25519_persist(void *arg) #endif +static void +test_crypto_siphash(void *arg) +{ + /* From the reference implementation, taking + k = 00 01 02 ... 0f + and in = 00; 00 01; 00 01 02; ... + */ + const uint8_t VECTORS[64][8] = + { + { 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, }, + { 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, }, + { 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, }, + { 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, }, + { 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, }, + { 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, }, + { 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, }, + { 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, }, + { 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, }, + { 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, }, + { 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, }, + { 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, }, + { 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, }, + { 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, }, + { 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, }, + { 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, }, + { 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, }, + { 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, }, + { 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, }, + { 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, }, + { 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, }, + { 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, }, + { 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, }, + { 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, }, + { 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, }, + { 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, }, + { 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, }, + { 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, }, + { 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, }, + { 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, }, + { 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, }, + { 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, }, + { 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, }, + { 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, }, + { 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, }, + { 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, }, + { 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, }, + { 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, }, + { 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, }, + { 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, }, + { 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, }, + { 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, }, + { 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, }, + { 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, }, + { 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, }, + { 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, }, + { 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, }, + { 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, }, + { 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, }, + { 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, }, + { 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, }, + { 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, }, + { 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, }, + { 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, }, + { 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, }, + { 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, }, + { 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, }, + { 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, }, + { 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, }, + { 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, }, + { 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, }, + { 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, }, + { 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, }, + { 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, } + }; + + const struct sipkey K = { U64_LITERAL(0x0706050403020100), + U64_LITERAL(0x0f0e0d0c0b0a0908) }; + uint8_t input[64]; + int i, j; + + (void)arg; + + for (i = 0; i < 64; ++i) + input[i] = i; + + for (i = 0; i < 64; ++i) { + uint64_t r = siphash24(input, i, &K); + for (j = 0; j < 8; ++j) { + tt_int_op( (r >> (j*8)) & 0xff, ==, VECTORS[i][j]); + } + } + + done: + ; +} + static void * pass_data_setup_fn(const struct testcase_t *testcase) { @@ -1137,6 +1284,7 @@ struct testcase_t crypto_tests[] = { { "aes_EVP", test_crypto_aes, TT_FORK, &pass_data, (void*)"evp" }, CRYPTO_LEGACY(sha), CRYPTO_LEGACY(pk), + { "pk_fingerprints", test_crypto_pk_fingerprints, TT_FORK, NULL, NULL }, CRYPTO_LEGACY(digests), CRYPTO_LEGACY(dh), CRYPTO_LEGACY(s2k), @@ -1152,6 +1300,7 @@ struct testcase_t crypto_tests[] = { { "curve25519_encode", test_crypto_curve25519_encode, 0, NULL, NULL }, { "curve25519_persist", test_crypto_curve25519_persist, 0, NULL, NULL }, #endif + { "siphash", test_crypto_siphash, 0, NULL, NULL }, END_OF_TESTCASES }; diff --git a/src/test/test_dir.c b/src/test/test_dir.c index 7c625ce7dd..9e01bdbd48 100644 --- a/src/test/test_dir.c +++ b/src/test/test_dir.c @@ -97,7 +97,6 @@ test_dir_formats(void) get_platform_str(platform, sizeof(platform)); r1 = tor_malloc_zero(sizeof(routerinfo_t)); - r1->address = tor_strdup("18.244.0.1"); r1->addr = 0xc0a80001u; /* 192.168.0.1 */ r1->cache_info.published_on = 0; r1->or_port = 9000; @@ -124,7 +123,6 @@ test_dir_formats(void) ex2->maskbits = 8; ex2->prt_min = ex2->prt_max = 24; r2 = tor_malloc_zero(sizeof(routerinfo_t)); - r2->address = tor_strdup("1.1.1.1"); r2->addr = 0x0a030201u; /* 10.3.2.1 */ r2->platform = tor_strdup(platform); r2->cache_info.published_on = 5; @@ -153,7 +151,7 @@ test_dir_formats(void) tor_free(options->ContactInfo); test_assert(buf); - strlcpy(buf2, "router Magri 18.244.0.1 9000 0 9003\n" + strlcpy(buf2, "router Magri 192.168.0.1 9000 0 9003\n" "or-address [1:2:3:4::]:9999\n" "platform Tor "VERSION" on ", sizeof(buf2)); strlcat(buf2, get_uname(), sizeof(buf2)); @@ -187,7 +185,7 @@ test_dir_formats(void) cp = buf; rp1 = router_parse_entry_from_string((const char*)cp,NULL,1,0,NULL); test_assert(rp1); - test_streq(rp1->address, r1->address); + test_eq(rp1->addr, r1->addr); test_eq(rp1->or_port, r1->or_port); //test_eq(rp1->dir_port, r1->dir_port); test_eq(rp1->bandwidthrate, r1->bandwidthrate); @@ -198,7 +196,7 @@ test_dir_formats(void) //test_assert(rp1->exit_policy == NULL); strlcpy(buf2, - "router Fred 1.1.1.1 9005 0 0\n" + "router Fred 10.3.2.1 9005 0 0\n" "platform Tor "VERSION" on ", sizeof(buf2)); strlcat(buf2, get_uname(), sizeof(buf2)); strlcat(buf2, "\n" @@ -231,7 +229,7 @@ test_dir_formats(void) cp = buf; rp2 = router_parse_entry_from_string((const char*)cp,NULL,1,0,NULL); test_assert(rp2); - test_streq(rp2->address, r2->address); + test_eq(rp2->addr, r2->addr); test_eq(rp2->or_port, r2->or_port); test_eq(rp2->dir_port, r2->dir_port); test_eq(rp2->bandwidthrate, r2->bandwidthrate); @@ -1230,7 +1228,8 @@ test_a_networkstatus( vote_routerstatus_t *vrs; routerstatus_t *rs; int idx, n_rs, n_vrs; - char *v1_text=NULL, *v2_text=NULL, *v3_text=NULL, *consensus_text=NULL, *cp; + char *v1_text=NULL, *v2_text=NULL, *v3_text=NULL, *consensus_text=NULL, + *cp=NULL; smartlist_t *votes = smartlist_new(); /* For generating the two other consensuses. */ @@ -1648,6 +1647,7 @@ test_a_networkstatus( } done: + tor_free(cp); smartlist_free(votes); tor_free(v1_text); tor_free(v2_text); diff --git a/src/test/test_extorport.c b/src/test/test_extorport.c index 7e38ba57dc..b34f5e38de 100644 --- a/src/test/test_extorport.c +++ b/src/test/test_extorport.c @@ -363,10 +363,12 @@ test_ext_or_cookie_auth_testvec(void *arg) } static void -ignore_bootstrap_problem(const char *warn, int reason) +ignore_bootstrap_problem(const char *warn, int reason, + const or_connection_t *conn) { (void)warn; (void)reason; + (void)conn; } static int is_reading = 1; diff --git a/src/test/test_hs.c b/src/test/test_hs.c index a9e6644397..99ef7dd570 100644 --- a/src/test/test_hs.c +++ b/src/test/test_hs.c @@ -11,6 +11,17 @@ #include "test.h" #include "control.h" +/* mock ID digest and longname for node that's in nodelist */ +#define HSDIR_EXIST_ID "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" \ + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" +#define STR_HSDIR_EXIST_LONGNAME \ + "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=TestDir" +/* mock ID digest and longname for node that's not in nodelist */ +#define HSDIR_NONE_EXIST_ID "\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB" \ + "\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB" +#define STR_HSDIR_NONE_EXIST_LONGNAME \ + "$BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" + /* Helper global variable for hidden service descriptor event test. * It's used as a pointer to dynamically created message buffer in * send_control_event_string_replacement function, which mocks @@ -25,13 +36,23 @@ static void send_control_event_string_replacement(uint16_t event, event_format_t which, const char *msg) { - int msg_len; - (void) event; (void) which; - msg_len = strlen(msg); - received_msg = tor_malloc_zero(msg_len+1); - strncpy(received_msg, msg, msg_len); + tor_free(received_msg); + received_msg = tor_strdup(msg); +} + +/** Mock function for node_describe_longname_by_id, it returns either + * STR_HSDIR_EXIST_LONGNAME or STR_HSDIR_NONE_EXIST_LONGNAME + */ +static const char * +node_describe_longname_by_id_replacement(const char *id_digest) +{ + if (!strcmp(id_digest, HSDIR_EXIST_ID)) { + return STR_HSDIR_EXIST_LONGNAME; + } else { + return STR_HSDIR_NONE_EXIST_LONGNAME; + } } /** Make sure each hidden service descriptor async event generation @@ -42,8 +63,6 @@ static void test_hs_desc_event(void *arg) { #define STR_HS_ADDR "ajhb7kljbiru65qo" - #define STR_HS_DIR_LONGNAME \ - "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=TestDir at 1.2.3.4" #define STR_HS_ID "b3oeducbhjmbqmgw2i3jtz4fekkrinwj" rend_data_t rend_query; @@ -52,6 +71,8 @@ test_hs_desc_event(void *arg) (void) arg; MOCK(send_control_event_string, send_control_event_string_replacement); + MOCK(node_describe_longname_by_id, + node_describe_longname_by_id_replacement); /* setup rend_query struct */ strncpy(rend_query.onion_address, STR_HS_ADDR, @@ -59,52 +80,45 @@ test_hs_desc_event(void *arg) rend_query.auth_type = 0; /* test request event */ - control_event_hs_descriptor_requested(&rend_query, STR_HS_DIR_LONGNAME, + control_event_hs_descriptor_requested(&rend_query, HSDIR_EXIST_ID, STR_HS_ID); - expected_msg = - "650 HS_DESC REQUESTED "STR_HS_ADDR" NO_AUTH "STR_HS_DIR_LONGNAME\ - " "STR_HS_ID"\r\n"; + expected_msg = "650 HS_DESC REQUESTED "STR_HS_ADDR" NO_AUTH "\ + STR_HSDIR_EXIST_LONGNAME" "STR_HS_ID"\r\n"; test_assert(received_msg); test_streq(received_msg, expected_msg); tor_free(received_msg); - received_msg = NULL; /* test received event */ rend_query.auth_type = 1; - control_event_hs_descriptor_received(&rend_query, STR_HS_DIR_LONGNAME); - expected_msg = - "650 HS_DESC RECEIVED "STR_HS_ADDR" BASIC_AUTH "STR_HS_DIR_LONGNAME"\r\n"; + control_event_hs_descriptor_received(&rend_query, HSDIR_EXIST_ID); + expected_msg = "650 HS_DESC RECEIVED "STR_HS_ADDR" BASIC_AUTH "\ + STR_HSDIR_EXIST_LONGNAME"\r\n"; test_assert(received_msg); test_streq(received_msg, expected_msg); tor_free(received_msg); - received_msg = NULL; /* test failed event */ rend_query.auth_type = 2; - control_event_hs_descriptor_failed(&rend_query, STR_HS_DIR_LONGNAME); - expected_msg = - "650 HS_DESC FAILED "STR_HS_ADDR" STEALTH_AUTH "STR_HS_DIR_LONGNAME"\r\n"; + control_event_hs_descriptor_failed(&rend_query, HSDIR_NONE_EXIST_ID); + expected_msg = "650 HS_DESC FAILED "STR_HS_ADDR" STEALTH_AUTH "\ + STR_HSDIR_NONE_EXIST_LONGNAME"\r\n"; test_assert(received_msg); test_streq(received_msg, expected_msg); tor_free(received_msg); - received_msg = NULL; /* test invalid auth type */ rend_query.auth_type = 999; - control_event_hs_descriptor_failed(&rend_query, STR_HS_DIR_LONGNAME); - expected_msg = - "650 HS_DESC FAILED "STR_HS_ADDR" UNKNOWN "STR_HS_DIR_LONGNAME"\r\n"; + control_event_hs_descriptor_failed(&rend_query, HSDIR_EXIST_ID); + expected_msg = "650 HS_DESC FAILED "STR_HS_ADDR" UNKNOWN "\ + STR_HSDIR_EXIST_LONGNAME"\r\n"; test_assert(received_msg); test_streq(received_msg, expected_msg); tor_free(received_msg); - received_msg = NULL; done: UNMOCK(send_control_event_string); - if (received_msg) { - tor_free(received_msg); - received_msg = NULL; - } + UNMOCK(node_describe_longname_by_id); + tor_free(received_msg); } struct testcase_t hs_tests[] = { diff --git a/src/test/test_nodelist.c b/src/test/test_nodelist.c new file mode 100644 index 0000000000..600e6a89d4 --- /dev/null +++ b/src/test/test_nodelist.c @@ -0,0 +1,71 @@ +/* Copyright (c) 2007-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file test_nodelist.c + * \brief Unit tests for nodelist related functions. + **/ + +#include "or.h" +#include "nodelist.h" +#include "test.h" + +/** Tese the case when node_get_by_id() returns NULL, + * node_get_verbose_nickname_by_id should return the base 16 encoding + * of the id. + */ +static void +test_nodelist_node_get_verbose_nickname_by_id_null_node(void *arg) +{ + char vname[MAX_VERBOSE_NICKNAME_LEN+1]; + const char ID[] = "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"; + (void) arg; + + /* make sure node_get_by_id returns NULL */ + test_assert(!node_get_by_id(ID)); + node_get_verbose_nickname_by_id(ID, vname); + test_streq(vname, "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); + done: + return; +} + +/** For routers without named flag, get_verbose_nickname should return + * "Fingerprint~Nickname" + */ +static void +test_nodelist_node_get_verbose_nickname_not_named(void *arg) +{ + node_t mock_node; + routerstatus_t mock_rs; + + char vname[MAX_VERBOSE_NICKNAME_LEN+1]; + + (void) arg; + + memset(&mock_node, 0, sizeof(node_t)); + memset(&mock_rs, 0, sizeof(routerstatus_t)); + + /* verbose nickname should use ~ instead of = for unnamed routers */ + strlcpy(mock_rs.nickname, "TestOR", sizeof(mock_rs.nickname)); + mock_node.rs = &mock_rs; + memcpy(mock_node.identity, + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA", + DIGEST_LEN); + node_get_verbose_nickname(&mock_node, vname); + test_streq(vname, "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~TestOR"); + + done: + return; +} + +#define NODE(name, flags) \ + { #name, test_nodelist_##name, (flags), NULL, NULL } + +struct testcase_t nodelist_tests[] = { + NODE(node_get_verbose_nickname_by_id_null_node, TT_FORK), + NODE(node_get_verbose_nickname_not_named, TT_FORK), + END_OF_TESTCASES +}; + diff --git a/src/test/test_oom.c b/src/test/test_oom.c new file mode 100644 index 0000000000..cc6e532358 --- /dev/null +++ b/src/test/test_oom.c @@ -0,0 +1,348 @@ +/* Copyright (c) 2014, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/* Unit tests for OOM handling logic */ + +#define RELAY_PRIVATE +#define BUFFERS_PRIVATE +#define CIRCUITLIST_PRIVATE +#include "or.h" +#include "buffers.h" +#include "circuitlist.h" +#include "compat_libevent.h" +#include "connection.h" +#include "config.h" +#include "mempool.h" +#include "relay.h" +#include "test.h" + +/* small replacement mock for circuit_mark_for_close_ to avoid doing all + * the other bookkeeping that comes with marking circuits. */ +static void +circuit_mark_for_close_dummy_(circuit_t *circ, int reason, int line, + const char *file) +{ + (void) reason; + if (circ->marked_for_close) { + TT_FAIL(("Circuit already marked for close at %s:%d, but we are marking " + "it again at %s:%d", + circ->marked_for_close_file, (int)circ->marked_for_close, + file, line)); + } + + circ->marked_for_close = line; + circ->marked_for_close_file = file; +} + +static circuit_t * +dummy_or_circuit_new(int n_p_cells, int n_n_cells) +{ + or_circuit_t *circ = or_circuit_new(0, NULL); + int i; + cell_t cell; + + for (i=0; i < n_p_cells; ++i) { + crypto_rand((void*)&cell, sizeof(cell)); + cell_queue_append_packed_copy(TO_CIRCUIT(circ), &circ->p_chan_cells, + 0, &cell, 1, 0); + } + + for (i=0; i < n_n_cells; ++i) { + crypto_rand((void*)&cell, sizeof(cell)); + cell_queue_append_packed_copy(TO_CIRCUIT(circ), + &TO_CIRCUIT(circ)->n_chan_cells, + 1, &cell, 1, 0); + } + + TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_OR; + return TO_CIRCUIT(circ); +} + +static circuit_t * +dummy_origin_circuit_new(int n_cells) +{ + origin_circuit_t *circ = origin_circuit_new(); + int i; + cell_t cell; + + for (i=0; i < n_cells; ++i) { + crypto_rand((void*)&cell, sizeof(cell)); + cell_queue_append_packed_copy(TO_CIRCUIT(circ), + &TO_CIRCUIT(circ)->n_chan_cells, + 1, &cell, 1, 0); + } + + TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_C_GENERAL; + return TO_CIRCUIT(circ); +} + +static void +add_bytes_to_buf(generic_buffer_t *buf, size_t n_bytes) +{ + char b[3000]; + + while (n_bytes) { + size_t this_add = n_bytes > sizeof(buf) ? sizeof(buf) : n_bytes; + crypto_rand(b, sizeof(b)); + generic_buffer_add(buf, b, this_add); + n_bytes -= this_add; + } +} + +static edge_connection_t * +dummy_edge_conn_new(circuit_t *circ, + int type, size_t in_bytes, size_t out_bytes) +{ + edge_connection_t *conn; + + if (type == CONN_TYPE_EXIT) + conn = edge_connection_new(type, AF_INET); + else + conn = ENTRY_TO_EDGE_CONN(entry_connection_new(type, AF_INET)); + + /* We add these bytes directly to the buffers, to avoid all the + * edge connection read/write machinery. */ + add_bytes_to_buf(TO_CONN(conn)->inbuf, in_bytes); + add_bytes_to_buf(TO_CONN(conn)->outbuf, out_bytes); + + conn->on_circuit = circ; + if (type == CONN_TYPE_EXIT) { + or_circuit_t *oc = TO_OR_CIRCUIT(circ); + conn->next_stream = oc->n_streams; + oc->n_streams = conn; + } else { + origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(circ); + conn->next_stream = oc->p_streams; + oc->p_streams = conn; + } + + return conn; +} + +/** Run unit tests for buffers.c */ +static void +test_oom_circbuf(void *arg) +{ + or_options_t *options = get_options_mutable(); + circuit_t *c1 = NULL, *c2 = NULL, *c3 = NULL, *c4 = NULL; + struct timeval tv = { 1389631048, 0 }; + + (void) arg; + + MOCK(circuit_mark_for_close_, circuit_mark_for_close_dummy_); + init_cell_pool(); + + /* Far too low for real life. */ + options->MaxMemInQueues = 256*packed_cell_mem_cost(); + options->CellStatistics = 0; + + tt_int_op(cell_queues_check_size(), ==, 0); /* We don't start out OOM. */ + tt_int_op(cell_queues_get_total_allocation(), ==, 0); + tt_int_op(buf_get_total_allocation(), ==, 0); + + /* Now we're going to fake up some circuits and get them added to the global + circuit list. */ + tv.tv_usec = 0; + tor_gettimeofday_cache_set(&tv); + c1 = dummy_origin_circuit_new(30); + tv.tv_usec = 10*1000; + tor_gettimeofday_cache_set(&tv); + c2 = dummy_or_circuit_new(20, 20); + + tt_int_op(packed_cell_mem_cost(), ==, + sizeof(packed_cell_t) + MP_POOL_ITEM_OVERHEAD); + tt_int_op(cell_queues_get_total_allocation(), ==, + packed_cell_mem_cost() * 70); + tt_int_op(cell_queues_check_size(), ==, 0); /* We are still not OOM */ + + tv.tv_usec = 20*1000; + tor_gettimeofday_cache_set(&tv); + c3 = dummy_or_circuit_new(100, 85); + tt_int_op(cell_queues_check_size(), ==, 0); /* We are still not OOM */ + tt_int_op(cell_queues_get_total_allocation(), ==, + packed_cell_mem_cost() * 255); + + tv.tv_usec = 30*1000; + tor_gettimeofday_cache_set(&tv); + /* Adding this cell will trigger our OOM handler. */ + c4 = dummy_or_circuit_new(2, 0); + + tt_int_op(cell_queues_get_total_allocation(), ==, + packed_cell_mem_cost() * 257); + + tt_int_op(cell_queues_check_size(), ==, 1); /* We are now OOM */ + + tt_assert(c1->marked_for_close); + tt_assert(! c2->marked_for_close); + tt_assert(! c3->marked_for_close); + tt_assert(! c4->marked_for_close); + + tt_int_op(cell_queues_get_total_allocation(), ==, + packed_cell_mem_cost() * (257 - 30)); + + circuit_free(c1); + tv.tv_usec = 0; + tor_gettimeofday_cache_set(&tv); /* go back in time */ + c1 = dummy_or_circuit_new(90, 0); + + tv.tv_usec = 40*1000; /* go back to the future */ + tor_gettimeofday_cache_set(&tv); + + tt_int_op(cell_queues_check_size(), ==, 1); /* We are now OOM */ + + tt_assert(c1->marked_for_close); + tt_assert(! c2->marked_for_close); + tt_assert(! c3->marked_for_close); + tt_assert(! c4->marked_for_close); + + tt_int_op(cell_queues_get_total_allocation(), ==, + packed_cell_mem_cost() * (257 - 30)); + + done: + circuit_free(c1); + circuit_free(c2); + circuit_free(c3); + circuit_free(c4); + + UNMOCK(circuit_mark_for_close_); +} + +/** Run unit tests for buffers.c */ +static void +test_oom_streambuf(void *arg) +{ + or_options_t *options = get_options_mutable(); + circuit_t *c1 = NULL, *c2 = NULL, *c3 = NULL, *c4 = NULL, *c5 = NULL; + struct timeval tv = { 1389641159, 0 }; + uint32_t tvms; + int i; + + (void) arg; + + MOCK(circuit_mark_for_close_, circuit_mark_for_close_dummy_); + init_cell_pool(); + + /* Far too low for real life. */ + options->MaxMemInQueues = 81*packed_cell_mem_cost() + 4096 * 34; + options->CellStatistics = 0; + + tt_int_op(cell_queues_check_size(), ==, 0); /* We don't start out OOM. */ + tt_int_op(cell_queues_get_total_allocation(), ==, 0); + tt_int_op(buf_get_total_allocation(), ==, 0); + + /* Start all circuits with a bit of data queued in cells */ + tv.tv_usec = 500*1000; /* go halfway into the second. */ + tor_gettimeofday_cache_set(&tv); + c1 = dummy_or_circuit_new(10,10); + tv.tv_usec = 510*1000; + tor_gettimeofday_cache_set(&tv); + c2 = dummy_origin_circuit_new(20); + tv.tv_usec = 520*1000; + tor_gettimeofday_cache_set(&tv); + c3 = dummy_or_circuit_new(20,20); + tv.tv_usec = 530*1000; + tor_gettimeofday_cache_set(&tv); + c4 = dummy_or_circuit_new(0,0); + tt_int_op(cell_queues_get_total_allocation(), ==, + packed_cell_mem_cost() * 80); + + tv.tv_usec = 600*1000; + tor_gettimeofday_cache_set(&tv); + + /* Add some connections to c1...c4. */ + for (i = 0; i < 4; ++i) { + edge_connection_t *ec; + /* link it to a circuit */ + tv.tv_usec += 10*1000; + tor_gettimeofday_cache_set(&tv); + ec = dummy_edge_conn_new(c1, CONN_TYPE_EXIT, 1000, 1000); + tt_assert(ec); + tv.tv_usec += 10*1000; + tor_gettimeofday_cache_set(&tv); + ec = dummy_edge_conn_new(c2, CONN_TYPE_AP, 1000, 1000); + tt_assert(ec); + tv.tv_usec += 10*1000; + tor_gettimeofday_cache_set(&tv); + ec = dummy_edge_conn_new(c4, CONN_TYPE_EXIT, 1000, 1000); /* Yes, 4 twice*/ + tt_assert(ec); + tv.tv_usec += 10*1000; + tor_gettimeofday_cache_set(&tv); + ec = dummy_edge_conn_new(c4, CONN_TYPE_EXIT, 1000, 1000); + tt_assert(ec); + } + + tv.tv_sec += 1; + tv.tv_usec = 0; + tvms = (uint32_t) tv_to_msec(&tv); + + tt_int_op(circuit_max_queued_cell_age(c1, tvms), ==, 500); + tt_int_op(circuit_max_queued_cell_age(c2, tvms), ==, 490); + tt_int_op(circuit_max_queued_cell_age(c3, tvms), ==, 480); + tt_int_op(circuit_max_queued_cell_age(c4, tvms), ==, 0); + + tt_int_op(circuit_max_queued_data_age(c1, tvms), ==, 390); + tt_int_op(circuit_max_queued_data_age(c2, tvms), ==, 380); + tt_int_op(circuit_max_queued_data_age(c3, tvms), ==, 0); + tt_int_op(circuit_max_queued_data_age(c4, tvms), ==, 370); + + tt_int_op(circuit_max_queued_item_age(c1, tvms), ==, 500); + tt_int_op(circuit_max_queued_item_age(c2, tvms), ==, 490); + tt_int_op(circuit_max_queued_item_age(c3, tvms), ==, 480); + tt_int_op(circuit_max_queued_item_age(c4, tvms), ==, 370); + + tt_int_op(cell_queues_get_total_allocation(), ==, + packed_cell_mem_cost() * 80); + tt_int_op(buf_get_total_allocation(), ==, 4096*16*2); + + /* Now give c4 a very old buffer of modest size */ + { + edge_connection_t *ec; + tv.tv_sec -= 1; + tv.tv_usec = 0; + tor_gettimeofday_cache_set(&tv); + ec = dummy_edge_conn_new(c4, CONN_TYPE_EXIT, 1000, 1000); + tt_assert(ec); + } + tt_int_op(buf_get_total_allocation(), ==, 4096*17*2); + tt_int_op(circuit_max_queued_item_age(c4, tvms), ==, 1000); + + tt_int_op(cell_queues_check_size(), ==, 0); + + /* And run over the limit. */ + tv.tv_usec = 800*1000; + tor_gettimeofday_cache_set(&tv); + c5 = dummy_or_circuit_new(0,5); + + tt_int_op(cell_queues_get_total_allocation(), ==, + packed_cell_mem_cost() * 85); + tt_int_op(buf_get_total_allocation(), ==, 4096*17*2); + + tt_int_op(cell_queues_check_size(), ==, 1); /* We are now OOM */ + + /* C4 should have died. */ + tt_assert(! c1->marked_for_close); + tt_assert(! c2->marked_for_close); + tt_assert(! c3->marked_for_close); + tt_assert(c4->marked_for_close); + tt_assert(! c5->marked_for_close); + + tt_int_op(cell_queues_get_total_allocation(), ==, + packed_cell_mem_cost() * 85); + tt_int_op(buf_get_total_allocation(), ==, 4096*8*2); + + done: + circuit_free(c1); + circuit_free(c2); + circuit_free(c3); + circuit_free(c4); + circuit_free(c5); + + UNMOCK(circuit_mark_for_close_); +} + +struct testcase_t oom_tests[] = { + { "circbuf", test_oom_circbuf, TT_FORK, NULL, NULL }, + { "streambuf", test_oom_streambuf, TT_FORK, NULL, NULL }, + END_OF_TESTCASES +}; + diff --git a/src/test/test_router.c b/src/test/test_router.c deleted file mode 100644 index 5e816564d9..0000000000 --- a/src/test/test_router.c +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright (c) 2007-2013, The Tor Project, Inc. */ -/* See LICENSE for licensing information */ - -/** - * \file test_router.c - * \brief Unit tests for router related functions. - **/ - -#include "or.h" -#include "nodelist.h" -#include "router.h" -#include "test.h" - -/** Tese the case when node_get_by_id() returns NULL, node_describe_by_id - * should return the base 16 encoding of the id. - */ -static void -test_node_describe_by_id_null_node(void *arg) -{ - const char ID[] = "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"; - (void) arg; - - /* make sure node_get_by_id returns NULL */ - test_assert(!node_get_by_id(ID)); - test_streq(node_describe_by_id(ID), - "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); - done: - return; -} - -struct testcase_t router_tests[] = { - { "node_get_by_id_null_node", test_node_describe_by_id_null_node, TT_FORK, - NULL, NULL }, - END_OF_TESTCASES -}; - diff --git a/src/test/test_routerkeys.c b/src/test/test_routerkeys.c new file mode 100644 index 0000000000..1c8174b065 --- /dev/null +++ b/src/test/test_routerkeys.c @@ -0,0 +1,84 @@ +/* Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "orconfig.h" +#define ROUTER_PRIVATE +#include "or.h" +#include "config.h" +#include "router.h" +#include "util.h" +#include "crypto.h" + +#include "test.h" + +static void +test_routerkeys_write_fingerprint(void *arg) +{ + crypto_pk_t *key = pk_generate(2); + or_options_t *options = get_options_mutable(); + const char *ddir = get_fname("write_fingerprint"); + char *cp = NULL, *cp2 = NULL; + char fp[FINGERPRINT_LEN+1]; + + (void)arg; + + tt_assert(key); + + options->ORPort_set = 1; /* So that we can get the server ID key */ + options->DataDirectory = tor_strdup(ddir); + options->Nickname = tor_strdup("haflinger"); + set_server_identity_key(key); + set_client_identity_key(crypto_pk_dup_key(key)); + + tt_int_op(0, ==, check_private_dir(ddir, CPD_CREATE, NULL)); + tt_int_op(crypto_pk_cmp_keys(get_server_identity_key(),key),==,0); + + /* Write fingerprint file */ + tt_int_op(0, ==, router_write_fingerprint(0)); + cp = read_file_to_str(get_fname("write_fingerprint/fingerprint"), + 0, NULL); + crypto_pk_get_fingerprint(key, fp, 0); + tor_asprintf(&cp2, "haflinger %s\n", fp); + tt_str_op(cp, ==, cp2); + tor_free(cp); + tor_free(cp2); + + /* Write hashed-fingerprint file */ + tt_int_op(0, ==, router_write_fingerprint(1)); + cp = read_file_to_str(get_fname("write_fingerprint/hashed-fingerprint"), + 0, NULL); + crypto_pk_get_hashed_fingerprint(key, fp); + tor_asprintf(&cp2, "haflinger %s\n", fp); + tt_str_op(cp, ==, cp2); + tor_free(cp); + tor_free(cp2); + + /* Replace outdated file */ + write_str_to_file(get_fname("write_fingerprint/hashed-fingerprint"), + "junk goes here", 0); + tt_int_op(0, ==, router_write_fingerprint(1)); + cp = read_file_to_str(get_fname("write_fingerprint/hashed-fingerprint"), + 0, NULL); + crypto_pk_get_hashed_fingerprint(key, fp); + tor_asprintf(&cp2, "haflinger %s\n", fp); + tt_str_op(cp, ==, cp2); + tor_free(cp); + tor_free(cp2); + + done: + crypto_pk_free(key); + set_client_identity_key(NULL); + tor_free(cp); + tor_free(cp2); +} + +#define TEST(name, flags) \ + { #name , test_routerkeys_ ## name, (flags), NULL, NULL } + +struct testcase_t routerkeys_tests[] = { + TEST(write_fingerprint, TT_FORK), + END_OF_TESTCASES +}; + diff --git a/src/test/test_util.c b/src/test/test_util.c index 9104088c90..a471b8eb19 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -1577,14 +1577,14 @@ test_util_mmap(void) test_eq(mapping->size, strlen("Short file.")); test_streq(mapping->data, "Short file."); #ifdef _WIN32 - tor_munmap_file(mapping); + tt_int_op(0, ==, tor_munmap_file(mapping)); mapping = NULL; test_assert(unlink(fname1) == 0); #else /* make sure we can unlink. */ test_assert(unlink(fname1) == 0); test_streq(mapping->data, "Short file."); - tor_munmap_file(mapping); + tt_int_op(0, ==, tor_munmap_file(mapping)); mapping = NULL; #endif @@ -1605,7 +1605,7 @@ test_util_mmap(void) test_assert(mapping); test_eq(mapping->size, buflen); test_memeq(mapping->data, buf, buflen); - tor_munmap_file(mapping); + tt_int_op(0, ==, tor_munmap_file(mapping)); mapping = NULL; /* Now try a big aligned file. */ @@ -1614,7 +1614,7 @@ test_util_mmap(void) test_assert(mapping); test_eq(mapping->size, 16384); test_memeq(mapping->data, buf, 16384); - tor_munmap_file(mapping); + tt_int_op(0, ==, tor_munmap_file(mapping)); mapping = NULL; done: @@ -1627,8 +1627,7 @@ test_util_mmap(void) tor_free(fname3); tor_free(buf); - if (mapping) - tor_munmap_file(mapping); + tor_munmap_file(mapping); } /** Run unit tests for escaping/unescaping data for use by controllers. */ |