diff options
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/include.am | 35 | ||||
-rw-r--r-- | src/test/test-memwipe.c | 204 | ||||
-rwxr-xr-x | src/test/test-network.sh | 2 | ||||
-rw-r--r-- | src/test/test.c | 5 | ||||
-rw-r--r-- | src/test/test.h | 2 | ||||
-rw-r--r-- | src/test/test_address.c | 4 | ||||
-rw-r--r-- | src/test/test_buffers.c | 18 | ||||
-rw-r--r-- | src/test/test_cell_queue.c | 16 | ||||
-rw-r--r-- | src/test/test_channel.c | 30 | ||||
-rw-r--r-- | src/test/test_circuitmux.c | 7 | ||||
-rwxr-xr-x | src/test/test_cmdline_args.py | 311 | ||||
-rw-r--r-- | src/test/test_config.c | 10 | ||||
-rw-r--r-- | src/test/test_entrynodes.c | 83 | ||||
-rw-r--r-- | src/test/test_guardfraction.c | 418 | ||||
-rw-r--r-- | src/test/test_helpers.c | 86 | ||||
-rw-r--r-- | src/test/test_helpers.h | 17 | ||||
-rw-r--r-- | src/test/test_hs.c | 80 | ||||
-rw-r--r-- | src/test/test_oom.c | 16 | ||||
-rw-r--r-- | src/test/test_relay.c | 8 | ||||
-rw-r--r-- | src/test/test_status.c | 93 | ||||
-rw-r--r-- | src/test/test_util.c | 91 | ||||
-rw-r--r-- | src/test/test_workqueue.c | 4 | ||||
-rw-r--r-- | src/test/testing_common.c | 7 | ||||
-rwxr-xr-x | src/test/zero_length_keys.sh | 65 |
24 files changed, 921 insertions, 691 deletions
diff --git a/src/test/include.am b/src/test/include.am index 595be0b7c2..c857ec2f89 100644 --- a/src/test/include.am +++ b/src/test/include.am @@ -1,10 +1,11 @@ -TESTS += src/test/test src/test/test-slow +TESTS += src/test/test src/test/test-slow src/test/test-memwipe noinst_PROGRAMS+= src/test/bench if UNITTESTS_ENABLED noinst_PROGRAMS+= \ src/test/test \ src/test/test-slow \ + src/test/test-memwipe \ src/test/test-child \ src/test/test_workqueue endif @@ -40,6 +41,7 @@ src_test_test_SOURCES = \ src/test/test_dir.c \ src/test/test_entryconn.c \ src/test/test_entrynodes.c \ + src/test/test_guardfraction.c \ src/test/test_extorport.c \ src/test/test_hs.c \ src/test/test_introduce.c \ @@ -61,6 +63,7 @@ src_test_test_SOURCES = \ src/test/test_status.c \ src/test/test_threads.c \ src/test/test_util.c \ + src/test/test_helpers.c \ src/test/testing_common.c \ src/ext/tinytest.c @@ -71,10 +74,13 @@ src_test_test_slow_SOURCES = \ src/test/testing_common.c \ src/ext/tinytest.c +src_test_test_memwipe_SOURCES = \ + src/test/test-memwipe.c + src_test_test_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) -src_test_test_CPPFLAGS= $(src_test_AM_CPPFLAGS) +src_test_test_CPPFLAGS= $(src_test_AM_CPPFLAGS) $(TEST_CPPFLAGS) src_test_bench_SOURCES = \ src/test/bench.c @@ -87,7 +93,7 @@ src_test_test_workqueue_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) src_test_test_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \ @TOR_LDFLAGS_libevent@ src_test_test_LDADD = src/or/libtor-testing.a src/common/libor-testing.a \ - src/common/libor-crypto-testing.a $(LIBDONNA) \ + src/common/libor-crypto-testing.a $(LIBDONNA) src/common/libor.a \ src/common/libor-event-testing.a src/trunnel/libor-trunnel-testing.a \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ \ @@ -98,6 +104,11 @@ src_test_test_slow_CFLAGS = $(src_test_test_CFLAGS) src_test_test_slow_LDADD = $(src_test_test_LDADD) src_test_test_slow_LDFLAGS = $(src_test_test_LDFLAGS) +src_test_test_memwipe_CPPFLAGS = $(src_test_test_CPPFLAGS) +src_test_test_memwipe_CFLAGS = $(src_test_test_CFLAGS) +src_test_test_memwipe_LDADD = $(src_test_test_LDADD) +src_test_test_memwipe_LDFLAGS = $(src_test_test_LDFLAGS) + src_test_bench_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \ @TOR_LDFLAGS_libevent@ src_test_bench_LDADD = src/or/libtor.a src/common/libor.a \ @@ -119,10 +130,12 @@ src_test_test_workqueue_LDADD = src/or/libtor-testing.a \ noinst_HEADERS+= \ src/test/fakechans.h \ src/test/test.h \ + src/test/test_helpers.h \ src/test/test_descriptors.inc \ src/test/example_extrainfo.inc \ src/test/failing_routerdescs.inc \ - src/test/ed25519_vectors.inc + src/test/ed25519_vectors.inc \ + src/test/test_descriptors.inc noinst_PROGRAMS+= src/test/test-ntor-cl src_test_test_ntor_cl_SOURCES = src/test/test_ntor_cl.c @@ -136,9 +149,9 @@ src_test_test_ntor_cl_AM_CPPFLAGS = \ NTOR_TEST_DEPS=src/test/test-ntor-cl if COVERAGE_ENABLED -CMDLINE_TEST_TOR = ./src/or/tor-cov +CMDLINE_TEST_TOR = $(top_builddir)/src/or/tor-cov else -CMDLINE_TEST_TOR = ./src/or/tor +CMDLINE_TEST_TOR = $(top_builddir)/src/or/tor endif noinst_PROGRAMS += src/test/test-bt-cl @@ -147,22 +160,20 @@ src_test_test_bt_cl_LDADD = src/common/libor-testing.a \ @TOR_LIB_MATH@ \ @TOR_LIB_WS32@ @TOR_LIB_GDI@ src_test_test_bt_cl_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) -src_test_test_bt_cl_CPPFLAGS= $(src_test_AM_CPPFLAGS) +src_test_test_bt_cl_CPPFLAGS= $(src_test_AM_CPPFLAGS) $(TEST_CPPFLAGS) check-local: $(NTOR_TEST_DEPS) $(CMDLINE_TEST_TOR) if USEPYTHON - $(PYTHON) $(top_srcdir)/src/test/test_cmdline_args.py $(CMDLINE_TEST_TOR) "${top_srcdir}" $(PYTHON) $(top_srcdir)/src/test/ntor_ref.py test-tor $(PYTHON) $(top_srcdir)/src/test/ntor_ref.py self-test - ./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 + $(top_builddir)/src/test/test-bt-cl assert | $(PYTHON) $(top_srcdir)/src/test/bt_test.py + $(top_builddir)/src/test/test-bt-cl crash | $(PYTHON) $(top_srcdir)/src/test/bt_test.py endif - $(top_srcdir)/src/test/zero_length_keys.sh + $(SHELL) $(top_srcdir)/src/test/zero_length_keys.sh EXTRA_DIST += \ src/test/bt_test.py \ src/test/ntor_ref.py \ src/test/slownacl_curve25519.py \ - src/test/test_cmdline_args.py \ src/test/zero_length_keys.sh diff --git a/src/test/test-memwipe.c b/src/test/test-memwipe.c new file mode 100644 index 0000000000..a721a8e728 --- /dev/null +++ b/src/test/test-memwipe.c @@ -0,0 +1,204 @@ +#include <string.h> +#include <stdio.h> +#include <sys/types.h> +#include <stdlib.h> + +#include "crypto.h" +#include "compat.h" + +#undef MIN +#define MIN(a,b) ( ((a)<(b)) ? (a) : (b) ) + +static unsigned fill_a_buffer_memset(void) __attribute__((noinline)); +static unsigned fill_a_buffer_memwipe(void) __attribute__((noinline)); +static unsigned fill_a_buffer_nothing(void) __attribute__((noinline)); +static unsigned fill_heap_buffer_memset(void) __attribute__((noinline)); +static unsigned fill_heap_buffer_memwipe(void) __attribute__((noinline)); +static unsigned fill_heap_buffer_nothing(void) __attribute__((noinline)); +static unsigned check_a_buffer(void) __attribute__((noinline)); + +const char *s = NULL; + +#define FILL_BUFFER_IMPL() \ + unsigned int i; \ + unsigned sum = 0; \ + \ + /* Fill up a 1k buffer with a recognizable pattern. */ \ + for (i = 0; i < 2048; i += strlen(s)) { \ + memcpy(buf+i, s, MIN(strlen(s), 2048-i)); \ + } \ + \ + /* Use the buffer as input to a computation so the above can't get */ \ + /* optimized away. */ \ + for (i = 0; i < 2048; ++i) { \ + sum += (unsigned char)buf[i]; \ + } + +static unsigned +fill_a_buffer_memset(void) +{ + char buf[2048]; + FILL_BUFFER_IMPL() + memset(buf, 0, sizeof(buf)); + return sum; +} + +static unsigned +fill_a_buffer_memwipe(void) +{ + char buf[2048]; + FILL_BUFFER_IMPL() + memwipe(buf, 0, sizeof(buf)); + return sum; +} + +static unsigned +fill_a_buffer_nothing(void) +{ + char buf[2048]; + FILL_BUFFER_IMPL() + return sum; +} + +static INLINE int +vmemeq(volatile char *a, const char *b, size_t n) +{ + while (n--) { + if (*a++ != *b++) + return 0; + } + return 1; +} + +static unsigned +check_a_buffer(void) +{ + unsigned int i; + volatile char buf[1024]; + unsigned sum = 0; + + /* See if this buffer has the string in it. + + YES, THIS DOES INVOKE UNDEFINED BEHAVIOR BY READING FROM AN UNINITIALIZED + BUFFER. + + If you know a better way to figure out whether the compiler eliminated + the memset/memwipe calls or not, please let me know. + */ + for (i = 0; i < sizeof(buf); ++i) { + if (vmemeq(buf+i, s, strlen(s))) + ++sum; + } + + return sum; +} + +static char *heap_buf = NULL; + +static unsigned +fill_heap_buffer_memset(void) +{ + char *buf = heap_buf = malloc(2048); + FILL_BUFFER_IMPL() + memset(buf, 0, 2048); + free(buf); + return sum; +} + +static unsigned +fill_heap_buffer_memwipe(void) +{ + char *buf = heap_buf = malloc(2048); + FILL_BUFFER_IMPL() + memwipe(buf, 0, 2048); + free(buf); + return sum; +} + +static unsigned +fill_heap_buffer_nothing(void) +{ + char *buf = heap_buf = malloc(2048); + FILL_BUFFER_IMPL() + free(buf); + return sum; +} + +static unsigned +check_heap_buffer(void) +{ + unsigned int i; + unsigned sum = 0; + volatile char *buf = heap_buf; + + /* See if this buffer has the string in it. + + YES, THIS DOES INVOKE UNDEFINED BEHAVIOR BY READING FROM A FREED BUFFER. + + If you know a better way to figure out whether the compiler eliminated + the memset/memwipe calls or not, please let me know. + */ + for (i = 0; i < sizeof(buf); ++i) { + if (vmemeq(buf+i, s, strlen(s))) + ++sum; + } + + return sum; +} + +static struct testcase { + const char *name; + unsigned (*fill_fn)(void); + unsigned (*check_fn)(void); +} testcases[] = { + { "nil", fill_a_buffer_nothing, check_a_buffer }, + { "nil-heap", fill_heap_buffer_nothing, check_heap_buffer }, + { "memset", fill_a_buffer_memset, check_a_buffer }, + { "memset-heap", fill_heap_buffer_memset, check_heap_buffer }, + { "memwipe", fill_a_buffer_memwipe, check_a_buffer }, + { "memwipe-heap", fill_heap_buffer_memwipe, check_heap_buffer }, + { NULL, NULL, NULL } +}; + +int +main(int argc, char **argv) +{ + unsigned x, x2; + int i; + int working = 1; + unsigned found[6]; + (void) argc; (void) argv; + + s = "squamous haberdasher gallimaufry"; + + memset(found, 0, sizeof(found)); + + for (i = 0; testcases[i].name; ++i) { + x = testcases[i].fill_fn(); + found[i] = testcases[i].check_fn(); + + x2 = fill_a_buffer_nothing(); + + if (x != x2) { + working = 0; + } + } + + if (!working || !found[0] || !found[1]) { + printf("It appears that this test case may not give you reliable " + "information. Sorry.\n"); + } + + if (!found[2] && !found[3]) { + printf("It appears that memset is good enough on this platform. Good.\n"); + } + + if (found[4] || found[5]) { + printf("ERROR: memwipe does not wipe data!\n"); + return 1; + } else { + printf("OKAY: memwipe seems to work."); + return 0; + } +} + diff --git a/src/test/test-network.sh b/src/test/test-network.sh index be57cafb7f..ccfb5df424 100755 --- a/src/test/test-network.sh +++ b/src/test/test-network.sh @@ -13,7 +13,7 @@ do export TOR_DIR="$2" shift ;; - --flavo?r|--network-flavo?r) + --flavor|--flavour|--network-flavor|--network-flavour) export NETWORK_FLAVOUR="$2" shift ;; diff --git a/src/test/test.c b/src/test/test.c index 78932a4b7a..0524a6978f 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -49,9 +49,6 @@ double fabs(double x); #include "rendcommon.h" #include "test.h" #include "torgzip.h" -#ifdef ENABLE_MEMPOOLS -#include "mempool.h" -#endif #include "memarea.h" #include "onion.h" #include "onion_ntor.h" @@ -1135,6 +1132,7 @@ extern struct testcase_t crypto_tests[]; extern struct testcase_t dir_tests[]; extern struct testcase_t entryconn_tests[]; extern struct testcase_t entrynodes_tests[]; +extern struct testcase_t guardfraction_tests[]; extern struct testcase_t extorport_tests[]; extern struct testcase_t hs_tests[]; extern struct testcase_t introduce_tests[]; @@ -1179,6 +1177,7 @@ struct testgroup_t testgroups[] = { { "dir/md/", microdesc_tests }, { "entryconn/", entryconn_tests }, { "entrynodes/", entrynodes_tests }, + { "guardfraction/", guardfraction_tests }, { "extorport/", extorport_tests }, { "hs/", hs_tests }, { "introduce/", introduce_tests }, diff --git a/src/test/test.h b/src/test/test.h index b8057c59bf..b0c0946ac4 100644 --- a/src/test/test.h +++ b/src/test/test.h @@ -37,7 +37,7 @@ #define test_memeq_hex(expr1, hex) test_mem_op_hex(expr1, OP_EQ, hex) #define tt_double_op(a,op,b) \ - tt_assert_test_type(a,b,#a" "#op" "#b,double,(val1_ op val2_),"%f", \ + tt_assert_test_type(a,b,#a" "#op" "#b,double,(val1_ op val2_),"%g", \ TT_EXIT_TEST_FUNCTION) #ifdef _MSC_VER diff --git a/src/test/test_address.c b/src/test/test_address.c index a69a605873..317b370912 100644 --- a/src/test/test_address.c +++ b/src/test/test_address.c @@ -376,7 +376,7 @@ test_address_ifreq_to_smartlist(void *arg) ifc->ifc_len = sizeof(struct ifreq); ifc->ifc_ifcu.ifcu_req = ifr; - results = ifreq_to_smartlist((struct ifreq *)ifc->ifc_buf,ifc->ifc_len); + results = ifreq_to_smartlist(ifc->ifc_buf,ifc->ifc_len); tt_int_op(smartlist_len(results),==,1); tor_addr = smartlist_get(results, 0); @@ -399,7 +399,7 @@ test_address_ifreq_to_smartlist(void *arg) SMARTLIST_FOREACH(results, tor_addr_t *, t, tor_free(t)); smartlist_free(results); - results = ifreq_to_smartlist((struct ifreq *)ifc->ifc_buf,ifc->ifc_len); + results = ifreq_to_smartlist(ifc->ifc_buf,ifc->ifc_len); tt_int_op(smartlist_len(results),==,2); tor_addr = smartlist_get(results, 0); diff --git a/src/test/test_buffers.c b/src/test/test_buffers.c index 101f448472..0ede8081d8 100644 --- a/src/test/test_buffers.c +++ b/src/test/test_buffers.c @@ -193,7 +193,6 @@ test_buffers_basic(void *arg) buf_free(buf); if (buf2) buf_free(buf2); - buf_shrink_freelists(1); } static void @@ -297,12 +296,9 @@ test_buffer_pullup(void *arg) buf_free(buf); buf = NULL; - buf_shrink_freelists(1); - tt_int_op(buf_get_total_allocation(), OP_EQ, 0); done: buf_free(buf); - buf_shrink_freelists(1); tor_free(stuff); tor_free(tmp); } @@ -370,7 +366,6 @@ test_buffer_copy(void *arg) generic_buffer_free(buf); if (buf2) generic_buffer_free(buf2); - buf_shrink_freelists(1); } static void @@ -445,7 +440,6 @@ 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 @@ -481,20 +475,13 @@ test_buffer_allocation_tracking(void *arg) fetch_from_buf(junk, 4096, buf1); /* drop a 1k chunk... */ tt_int_op(buf_allocation(buf1), OP_EQ, 3*4096); /* now 3 4k chunks */ -#ifdef ENABLE_BUF_FREELISTS - tt_int_op(buf_get_total_allocation(), OP_EQ, 16384); /* that chunk went onto - the freelist. */ -#else tt_int_op(buf_get_total_allocation(), OP_EQ, 12288); /* that chunk was really freed. */ -#endif write_to_buf(junk, 4000, buf2); tt_int_op(buf_allocation(buf2), OP_EQ, 4096); /* another 4k chunk. */ /* - * If we're using freelists, size stays at 16384 because we just pulled a - * chunk from the freelist. If we aren't, we bounce back up to 16384 by - * allocating a new chunk. + * We bounce back up to 16384 by allocating a new chunk. */ tt_int_op(buf_get_total_allocation(), OP_EQ, 16384); write_to_buf(junk, 4000, buf2); @@ -512,17 +499,14 @@ test_buffer_allocation_tracking(void *arg) buf2 = NULL; tt_int_op(buf_get_total_allocation(), OP_LT, 4008000); - buf_shrink_freelists(1); tt_int_op(buf_get_total_allocation(), OP_EQ, buf_allocation(buf1)); buf_free(buf1); buf1 = NULL; - buf_shrink_freelists(1); tt_int_op(buf_get_total_allocation(), OP_EQ, 0); done: buf_free(buf1); buf_free(buf2); - buf_shrink_freelists(1); tor_free(junk); } diff --git a/src/test/test_cell_queue.c b/src/test/test_cell_queue.c index effd316f34..ed34df2ea2 100644 --- a/src/test/test_cell_queue.c +++ b/src/test/test_cell_queue.c @@ -16,10 +16,6 @@ test_cq_manip(void *arg) cell_t cell; (void) arg; -#ifdef ENABLE_MEMPOOLS - init_cell_pool(); -#endif /* ENABLE_MEMPOOLS */ - cell_queue_init(&cq); tt_int_op(cq.n, OP_EQ, 0); @@ -99,10 +95,6 @@ test_cq_manip(void *arg) packed_cell_free(pc_tmp); cell_queue_clear(&cq); - -#ifdef ENABLE_MEMPOOLS - free_cell_pool(); -#endif /* ENABLE_MEMPOOLS */ } static void @@ -114,10 +106,6 @@ test_circuit_n_cells(void *arg) (void)arg; -#ifdef ENABLE_MEMPOOLS - init_cell_pool(); -#endif /* ENABLE_MEMPOOLS */ - pc1 = packed_cell_new(); pc2 = packed_cell_new(); pc3 = packed_cell_new(); @@ -144,10 +132,6 @@ test_circuit_n_cells(void *arg) done: circuit_free(TO_CIRCUIT(or_c)); circuit_free(TO_CIRCUIT(origin_c)); - -#ifdef ENABLE_MEMPOOLS - free_cell_pool(); -#endif /* ENABLE_MEMPOOLS */ } struct testcase_t cell_queue_tests[] = { diff --git a/src/test/test_channel.c b/src/test/test_channel.c index 99633a4026..6cf66493a8 100644 --- a/src/test/test_channel.c +++ b/src/test/test_channel.c @@ -650,10 +650,6 @@ test_channel_flush(void *arg) (void)arg; -#ifdef ENABLE_MEMPOOLS - init_cell_pool(); -#endif /* ENABLE_MEMPOOLS */ - ch = new_fake_channel(); tt_assert(ch); @@ -695,9 +691,6 @@ test_channel_flush(void *arg) done: tor_free(ch); -#ifdef ENABLE_MEMPOOLS - free_cell_pool(); -#endif /* ENABLE_MEMPOOLS */ return; } @@ -715,10 +708,6 @@ test_channel_flushmux(void *arg) (void)arg; -#ifdef ENABLE_MEMPOOLS - init_cell_pool(); -#endif /* ENABLE_MEMPOOLS */ - /* Install mocks we need for this test */ MOCK(channel_flush_from_first_active_circuit, chan_test_channel_flush_from_first_active_circuit_mock); @@ -778,10 +767,6 @@ test_channel_flushmux(void *arg) test_chan_accept_cells = 0; -#ifdef ENABLE_MEMPOOLS - free_cell_pool(); -#endif /* ENABLE_MEMPOOLS */ - return; } @@ -1300,10 +1285,6 @@ test_channel_queue_impossible(void *arg) (void)arg; -#ifdef ENABLE_MEMPOOLS - init_cell_pool(); -#endif /* ENABLE_MEMPOOLS */ - ch = new_fake_channel(); tt_assert(ch); @@ -1430,9 +1411,6 @@ test_channel_queue_impossible(void *arg) done: free_fake_channel(ch); -#ifdef ENABLE_MEMPOOLS - free_cell_pool(); -#endif /* ENABLE_MEMPOOLS */ /* * Doing that meant that we couldn't correctly adjust the queue size @@ -1575,10 +1553,6 @@ test_channel_write(void *arg) (void)arg; -#ifdef ENABLE_MEMPOOLS - init_cell_pool(); -#endif /* ENABLE_MEMPOOLS */ - packed_cell = packed_cell_new(); tt_assert(packed_cell); @@ -1675,10 +1649,6 @@ test_channel_write(void *arg) packed_cell = NULL; tt_assert(test_cells_written == old_count); -#ifdef ENABLE_MEMPOOLS - free_cell_pool(); -#endif /* ENABLE_MEMPOOLS */ - done: free_fake_channel(ch); tor_free(var_cell); diff --git a/src/test/test_circuitmux.c b/src/test/test_circuitmux.c index 2a2a7ba145..6d93731eea 100644 --- a/src/test/test_circuitmux.c +++ b/src/test/test_circuitmux.c @@ -43,9 +43,6 @@ test_cmux_destroy_cell_queue(void *arg) tor_libevent_initialize(&cfg); scheduler_init(); -#ifdef ENABLE_MEMPOOLS - init_cell_pool(); -#endif /* ENABLE_MEMPOOLS */ (void) arg; cmux = circuitmux_alloc(); @@ -82,10 +79,6 @@ test_cmux_destroy_cell_queue(void *arg) circuitmux_free(cmux); channel_free(ch); packed_cell_free(pc); - -#ifdef ENABLE_MEMPOOLS - free_cell_pool(); -#endif /* ENABLE_MEMPOOLS */ } struct testcase_t circuitmux_tests[] = { diff --git a/src/test/test_cmdline_args.py b/src/test/test_cmdline_args.py deleted file mode 100755 index 57641974db..0000000000 --- a/src/test/test_cmdline_args.py +++ /dev/null @@ -1,311 +0,0 @@ -#!/usr/bin/python - -import binascii -import hashlib -import os -import re -import shutil -import subprocess -import sys -import tempfile -import unittest - -TOR = "./src/or/tor" -TOP_SRCDIR = "." - -if len(sys.argv) > 1: - TOR = sys.argv[1] - del sys.argv[1] - -if len(sys.argv) > 1: - TOP_SRCDIR = sys.argv[1] - del sys.argv[1] - -class UnexpectedSuccess(Exception): - pass - -class UnexpectedFailure(Exception): - pass - -if sys.version < '3': - def b2s(b): - return b - def s2b(s): - return s - def NamedTemporaryFile(): - return tempfile.NamedTemporaryFile(delete=False) -else: - def b2s(b): - return str(b, 'ascii') - def s2b(s): - return s.encode('ascii') - def NamedTemporaryFile(): - return tempfile.NamedTemporaryFile(mode="w",delete=False,encoding="ascii") - -def contents(fn): - f = open(fn) - try: - return f.read() - finally: - f.close() - -def run_tor(args, failure=False, stdin=None): - kwargs = {} - if stdin != None: - kwargs['stdin'] = subprocess.PIPE - p = subprocess.Popen([TOR] + args, stdout=subprocess.PIPE, **kwargs) - output, _ = p.communicate(input=stdin) - result = p.poll() - if result and not failure: - raise UnexpectedFailure() - elif not result and failure: - raise UnexpectedSuccess() - return b2s(output.replace('\r\n','\n')) - -def spaceify_fp(fp): - for i in range(0, len(fp), 4): - yield fp[i:i+4] - -def lines(s): - out = s.splitlines() - if out and out[-1] == '': - del out[-1] - return out - -def strip_log_junk(line): - m = re.match(r'([^\[]+\[[a-z]*\] *)(.*)', line) - if not m: - return ""+line - return m.group(2).strip() - -def randstring(entropy_bytes): - s = os.urandom(entropy_bytes) - return b2s(binascii.b2a_hex(s)) - -def findLineContaining(lines, s): - for ln in lines: - if s in ln: - return True - return False - -class CmdlineTests(unittest.TestCase): - - def test_version(self): - out = run_tor(["--version"]) - self.assertTrue(out.startswith("Tor version ")) - self.assertEqual(len(lines(out)), 1) - - def test_quiet(self): - out = run_tor(["--quiet", "--quumblebluffin", "1"], failure=True) - self.assertEqual(out, "") - - def test_help(self): - out = run_tor(["--help"], failure=False) - out2 = run_tor(["-h"], failure=False) - self.assertTrue(out.startswith("Copyright (c) 2001")) - self.assertTrue(out.endswith( - "tor -f <torrc> [args]\n" - "See man page for options, or https://www.torproject.org/ for documentation.\n")) - self.assertTrue(out == out2) - - def test_hush(self): - torrc = NamedTemporaryFile() - torrc.close() - try: - out = run_tor(["--hush", "-f", torrc.name, - "--quumblebluffin", "1"], failure=True) - finally: - os.unlink(torrc.name) - self.assertEqual(len(lines(out)), 2) - ln = [ strip_log_junk(l) for l in lines(out) ] - self.assertEqual(ln[0], "Failed to parse/validate config: Unknown option 'quumblebluffin'. Failing.") - self.assertEqual(ln[1], "Reading config failed--see warnings above.") - - def test_missing_argument(self): - out = run_tor(["--hush", "--hash-password"], failure=True) - self.assertEqual(len(lines(out)), 2) - ln = [ strip_log_junk(l) for l in lines(out) ] - self.assertEqual(ln[0], "Command-line option '--hash-password' with no value. Failing.") - - def test_hash_password(self): - out = run_tor(["--hash-password", "woodwose"]) - result = lines(out)[-1] - self.assertEqual(result[:3], "16:") - self.assertEqual(len(result), 61) - r = binascii.a2b_hex(result[3:]) - self.assertEqual(len(r), 29) - - salt, how, hashed = r[:8], r[8], r[9:] - self.assertEqual(len(hashed), 20) - if type(how) == type("A"): - how = ord(how) - - count = (16 + (how & 15)) << ((how >> 4) + 6) - stuff = salt + s2b("woodwose") - repetitions = count // len(stuff) + 1 - inp = stuff * repetitions - inp = inp[:count] - - self.assertEqual(hashlib.sha1(inp).digest(), hashed) - - def test_digests(self): - main_c = os.path.join(TOP_SRCDIR, "src", "or", "main.c") - - if os.stat(TOR).st_mtime < os.stat(main_c).st_mtime: - self.skipTest(TOR+" not up to date") - out = run_tor(["--digests"]) - main_line = [ l for l in lines(out) if l.endswith("/main.c") or l.endswith(" main.c") ] - digest, name = main_line[0].split() - f = open(main_c, 'rb') - actual = hashlib.sha1(f.read()).hexdigest() - f.close() - self.assertEqual(digest, actual) - - def test_dump_options(self): - default_torrc = NamedTemporaryFile() - torrc = NamedTemporaryFile() - torrc.write("SocksPort 9999") - torrc.close() - default_torrc.write("SafeLogging 0") - default_torrc.close() - out_sh = out_nb = out_fl = None - opts = [ "-f", torrc.name, - "--defaults-torrc", default_torrc.name ] - try: - out_sh = run_tor(["--dump-config", "short"]+opts) - out_nb = run_tor(["--dump-config", "non-builtin"]+opts) - out_fl = run_tor(["--dump-config", "full"]+opts) - out_nr = run_tor(["--dump-config", "bliznert"]+opts, - failure=True) - - out_verif = run_tor(["--verify-config"]+opts) - finally: - os.unlink(torrc.name) - os.unlink(default_torrc.name) - - self.assertEqual(len(lines(out_sh)), 2) - self.assertTrue(lines(out_sh)[0].startswith("DataDirectory ")) - self.assertEqual(lines(out_sh)[1:], - [ "SocksPort 9999" ]) - - self.assertEqual(len(lines(out_nb)), 2) - self.assertEqual(lines(out_nb), - [ "SafeLogging 0", - "SocksPort 9999" ]) - - out_fl = lines(out_fl) - self.assertTrue(len(out_fl) > 100) - self.assertTrue("SocksPort 9999" in out_fl) - self.assertTrue("SafeLogging 0" in out_fl) - self.assertTrue("ClientOnly 0" in out_fl) - - self.assertTrue(out_verif.endswith("Configuration was valid\n")) - - def test_list_fingerprint(self): - tmpdir = tempfile.mkdtemp(prefix='ttca_') - torrc = NamedTemporaryFile() - torrc.write("ORPort 9999\n") - torrc.write("DataDirectory %s\n"%tmpdir) - torrc.write("Nickname tippi") - torrc.close() - opts = ["-f", torrc.name] - try: - out = run_tor(["--list-fingerprint"]+opts) - fp = contents(os.path.join(tmpdir, "fingerprint")) - finally: - os.unlink(torrc.name) - shutil.rmtree(tmpdir) - - out = lines(out) - lastlog = strip_log_junk(out[-2]) - lastline = out[-1] - fp = fp.strip() - nn_fp = fp.split()[0] - space_fp = " ".join(spaceify_fp(fp.split()[1])) - self.assertEqual(lastlog, - "Your Tor server's identity key fingerprint is '%s'"%fp) - self.assertEqual(lastline, "tippi %s"%space_fp) - self.assertEqual(nn_fp, "tippi") - - def test_list_options(self): - out = lines(run_tor(["--list-torrc-options"])) - self.assertTrue(len(out)>100) - self.assertTrue(out[0] <= 'AccountingMax') - self.assertTrue("UseBridges" in out) - self.assertTrue("SocksPort" in out) - - def test_cmdline_args(self): - default_torrc = NamedTemporaryFile() - torrc = NamedTemporaryFile() - contents = ("SocksPort 9999\n" - "SocksPort 9998\n" - "ORPort 9000\n" - "ORPort 9001\n" - "Nickname eleventeen\n" - "ControlPort 9500\n") - torrc.write(contents) - default_torrc.write("") - default_torrc.close() - torrc.close() - out_sh = out_nb = out_fl = None - - opts_stdin = [ "-f", "-", - "--defaults-torrc", default_torrc.name, - "--dump-config", "short" ] - opts = [ "-f", torrc.name, - "--defaults-torrc", default_torrc.name, - "--dump-config", "short" ] - try: - out_0 = run_tor(opts_stdin,stdin=contents) - out_1 = run_tor(opts) - out_2 = run_tor(opts+["+ORPort", "9003", - "SocksPort", "9090", - "/ControlPort", - "/TransPort", - "+ExtORPort", "9005"]) - finally: - os.unlink(torrc.name) - os.unlink(default_torrc.name) - - out_0 = [ l for l in lines(out_0) if not l.startswith("DataDir") ] - out_1 = [ l for l in lines(out_1) if not l.startswith("DataDir") ] - out_2 = [ l for l in lines(out_2) if not l.startswith("DataDir") ] - - self.assertEqual(out_0, - ["ControlPort 9500", - "Nickname eleventeen", - "ORPort 9000", - "ORPort 9001", - "SocksPort 9999", - "SocksPort 9998"]) - - self.assertEqual(out_1, - ["ControlPort 9500", - "Nickname eleventeen", - "ORPort 9000", - "ORPort 9001", - "SocksPort 9999", - "SocksPort 9998"]) - - self.assertEqual(out_2, - ["ExtORPort 9005", - "Nickname eleventeen", - "ORPort 9000", - "ORPort 9001", - "ORPort 9003", - "SocksPort 9090"]) - - def test_missing_torrc(self): - fname = "nonexistent_file_"+randstring(8) - out = run_tor(["-f", fname, "--verify-config"], failure=True) - ln = [ strip_log_junk(l) for l in lines(out) ] - self.assertTrue("Unable to open configuration file" in ln[-2]) - self.assertTrue("Reading config failed" in ln[-1]) - - out = run_tor(["-f", fname, "--verify-config", "--ignore-missing-torrc"]) - ln = [ strip_log_junk(l) for l in lines(out) ] - self.assertTrue(findLineContaining(ln, ", using reasonable defaults")) - self.assertTrue("Configuration was valid" in ln[-1]) - -if __name__ == '__main__': - unittest.main() diff --git a/src/test/test_config.c b/src/test/test_config.c index b63b78e386..0444062722 100644 --- a/src/test/test_config.c +++ b/src/test/test_config.c @@ -1092,7 +1092,7 @@ test_config_resolve_my_address(void *arg) tt_want(retval == 0); tt_want_str_op(method_used,==,"CONFIGURED"); tt_want(hostname_out == NULL); - tt_assert(htonl(resolved_addr) == 0x69803480); + tt_assert(resolved_addr == 0x80348069); tor_free(options->Address); @@ -1117,7 +1117,7 @@ test_config_resolve_my_address(void *arg) tt_want(n_hostname_01010101 == prev_n_hostname_01010101 + 1); tt_want_str_op(method_used,==,"RESOLVED"); tt_want_str_op(hostname_out,==,"www.torproject.org"); - tt_assert(htonl(resolved_addr) == 0x01010101); + tt_assert(resolved_addr == 0x01010101); UNMOCK(tor_lookup_hostname); @@ -1149,7 +1149,7 @@ test_config_resolve_my_address(void *arg) tt_want(n_hostname_01010101 == prev_n_hostname_01010101 + 1); tt_want_str_op(method_used,==,"GETHOSTNAME"); tt_want_str_op(hostname_out,==,"onionrouter!"); - tt_assert(htonl(resolved_addr) == 0x01010101); + tt_assert(resolved_addr == 0x01010101); UNMOCK(tor_gethostname); UNMOCK(tor_lookup_hostname); @@ -1242,7 +1242,7 @@ test_config_resolve_my_address(void *arg) prev_n_get_interface_address + 1); tt_want_str_op(method_used,==,"INTERFACE"); tt_want(hostname_out == NULL); - tt_assert(resolved_addr == ntohl(0x08080808)); + tt_assert(resolved_addr == 0x08080808); UNMOCK(get_interface_address); tor_free(hostname_out); @@ -1297,7 +1297,7 @@ test_config_resolve_my_address(void *arg) tt_want(n_gethostname_replacement == prev_n_gethostname_replacement + 1); tt_want(retval == 0); tt_want_str_op(method_used,==,"INTERFACE"); - tt_assert(htonl(resolved_addr) == 0x09090909); + tt_assert(resolved_addr == 0x09090909); UNMOCK(tor_lookup_hostname); UNMOCK(tor_gethostname); diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c index 19071a1550..17cb9d9329 100644 --- a/src/test/test_entrynodes.c +++ b/src/test/test_entrynodes.c @@ -18,7 +18,7 @@ #include "statefile.h" #include "config.h" -#include "test_descriptors.inc" +#include "test_helpers.h" /* TODO: * choose_random_entry() test with state set. @@ -37,62 +37,6 @@ get_or_state_replacement(void) return dummy_state; } -/* NOP replacement for router_descriptor_is_older_than() */ -static int -router_descriptor_is_older_than_replacement(const routerinfo_t *router, - int seconds) -{ - (void) router; - (void) seconds; - return 0; -} - -/* Number of descriptors contained in test_descriptors.txt. */ -#define NUMBER_OF_DESCRIPTORS 8 - -/** Parse a file containing router descriptors and load them to our - routerlist. This function is used to setup an artificial network - so that we can conduct entry guard tests. */ -static void -setup_fake_routerlist(void) -{ - int retval; - routerlist_t *our_routerlist = NULL; - smartlist_t *our_nodelist = NULL; - - /* Read the file that contains our test descriptors. */ - - /* We need to mock this function otherwise the descriptors will not - accepted as they are too old. */ - MOCK(router_descriptor_is_older_than, - router_descriptor_is_older_than_replacement); - - /* Load all the test descriptors to the routerlist. */ - retval = router_load_routers_from_string(TEST_DESCRIPTORS, - NULL, SAVED_IN_JOURNAL, - NULL, 0, NULL); - tt_int_op(retval, OP_EQ, NUMBER_OF_DESCRIPTORS); - - /* Sanity checking of routerlist and nodelist. */ - our_routerlist = router_get_routerlist(); - tt_int_op(smartlist_len(our_routerlist->routers), OP_EQ, - NUMBER_OF_DESCRIPTORS); - routerlist_assert_ok(our_routerlist); - - our_nodelist = nodelist_get_list(); - tt_int_op(smartlist_len(our_nodelist), OP_EQ, NUMBER_OF_DESCRIPTORS); - - /* Mark all routers as non-guards but up and running! */ - SMARTLIST_FOREACH_BEGIN(our_nodelist, node_t *, node) { - node->is_running = 1; - node->is_valid = 1; - node->is_possible_guard = 0; - } SMARTLIST_FOREACH_END(node); - - done: - UNMOCK(router_descriptor_is_older_than); -} - /* Unittest cleanup function: Cleanup the fake network. */ static int fake_network_cleanup(const struct testcase_t *testcase, void *ptr) @@ -120,7 +64,7 @@ fake_network_setup(const struct testcase_t *testcase) get_or_state_replacement); /* Setup fake routerlist. */ - setup_fake_routerlist(); + helper_setup_fake_routerlist(); /* Return anything but NULL (it's interpreted as test fail) */ return dummy_state; @@ -197,7 +141,7 @@ populate_live_entry_guards_test_helper(int num_needed) /* Walk the nodelist and add all nodes as entry guards. */ our_nodelist = nodelist_get_list(); - tt_int_op(smartlist_len(our_nodelist), OP_EQ, NUMBER_OF_DESCRIPTORS); + tt_int_op(smartlist_len(our_nodelist), OP_EQ, HELPER_NUMBER_OF_DESCRIPTORS); SMARTLIST_FOREACH_BEGIN(our_nodelist, const node_t *, node) { const node_t *node_tmp; @@ -206,7 +150,8 @@ populate_live_entry_guards_test_helper(int num_needed) } SMARTLIST_FOREACH_END(node); /* Make sure the nodes were added as entry guards. */ - tt_int_op(smartlist_len(all_entry_guards), OP_EQ, NUMBER_OF_DESCRIPTORS); + tt_int_op(smartlist_len(all_entry_guards), OP_EQ, + HELPER_NUMBER_OF_DESCRIPTORS); /* Ensure that all the possible entry guards are enough to satisfy us. */ tt_int_op(smartlist_len(all_entry_guards), OP_GE, num_needed); @@ -326,19 +271,6 @@ state_lines_free(smartlist_t *entry_guard_lines) smartlist_free(entry_guard_lines); } -/* Return a statically allocated string representing yesterday's date - * in ISO format. We use it so that state file items are not found to - * be outdated. */ -static const char * -get_yesterday_date_str(void) -{ - static char buf[ISO_TIME_LEN+1]; - - time_t yesterday = time(NULL) - 24*60*60; - format_iso_time(buf, yesterday); - return buf; -} - /* Tests entry_guards_parse_state(). It creates a fake Tor state with a saved entry guard and makes sure that Tor can parse it and creates the right entry node out of it. @@ -647,7 +579,7 @@ test_entry_is_live(void *arg) /* Walk the nodelist and add all nodes as entry guards. */ our_nodelist = nodelist_get_list(); - tt_int_op(smartlist_len(our_nodelist), OP_EQ, NUMBER_OF_DESCRIPTORS); + tt_int_op(smartlist_len(our_nodelist), OP_EQ, HELPER_NUMBER_OF_DESCRIPTORS); SMARTLIST_FOREACH_BEGIN(our_nodelist, const node_t *, node) { const node_t *node_tmp; @@ -659,7 +591,8 @@ test_entry_is_live(void *arg) } SMARTLIST_FOREACH_END(node); /* Make sure the nodes were added as entry guards. */ - tt_int_op(smartlist_len(all_entry_guards), OP_EQ, NUMBER_OF_DESCRIPTORS); + tt_int_op(smartlist_len(all_entry_guards), OP_EQ, + HELPER_NUMBER_OF_DESCRIPTORS); /* Now get a random test entry that we will use for this unit test. */ which_node = 3; /* (chosen by fair dice roll) */ diff --git a/src/test/test_guardfraction.c b/src/test/test_guardfraction.c new file mode 100644 index 0000000000..57063c9085 --- /dev/null +++ b/src/test/test_guardfraction.c @@ -0,0 +1,418 @@ +/* Copyright (c) 2014, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#define DIRSERV_PRIVATE +#define ROUTERPARSE_PRIVATE +#define NETWORKSTATUS_PRIVATE + +#include "orconfig.h" +#include "or.h" +#include "config.h" +#include "dirserv.h" +#include "container.h" +#include "entrynodes.h" +#include "util.h" +#include "routerparse.h" +#include "networkstatus.h" + +#include "test.h" +#include "test_helpers.h" + +/** Generate a vote_routerstatus_t for a router with identity digest + * <b>digest_in_hex</b>. */ +static vote_routerstatus_t * +gen_vote_routerstatus_for_tests(const char *digest_in_hex, int is_guard) +{ + int retval; + vote_routerstatus_t *vrs = NULL; + routerstatus_t *rs; + + vrs = tor_malloc_zero(sizeof(vote_routerstatus_t)); + rs = &vrs->status; + + { /* Useful information for tests */ + char digest_tmp[DIGEST_LEN]; + + /* Guard or not? */ + rs->is_possible_guard = is_guard; + + /* Fill in the fpr */ + tt_int_op(strlen(digest_in_hex), ==, HEX_DIGEST_LEN); + retval = base16_decode(digest_tmp, sizeof(digest_tmp), + digest_in_hex, HEX_DIGEST_LEN); + tt_int_op(retval, ==, 0); + memcpy(rs->identity_digest, digest_tmp, DIGEST_LEN); + } + + { /* Misc info (maybe not used in tests) */ + vrs->version = tor_strdup("0.1.2.14"); + strlcpy(rs->nickname, "router2", sizeof(rs->nickname)); + memset(rs->descriptor_digest, 78, DIGEST_LEN); + rs->addr = 0x99008801; + rs->or_port = 443; + rs->dir_port = 8000; + /* all flags but running cleared */ + rs->is_flagged_running = 1; + vrs->has_measured_bw = 1; + rs->has_bandwidth = 1; + } + + return vrs; + + done: + vote_routerstatus_free(vrs); + + return NULL; +} + +/** Make sure our parsers reject corrupted guardfraction files. */ +static void +test_parse_guardfraction_file_bad(void *arg) +{ + int retval; + char *guardfraction_bad = NULL; + const char *yesterday_date_str = get_yesterday_date_str(); + + (void) arg; + + /* Start parsing all those corrupted guardfraction files! */ + + /* Guardfraction file version is not a number! */ + tor_asprintf(&guardfraction_bad, + "guardfraction-file-version nan\n" + "written-at %s\n" + "n-inputs 420 3\n" + "guard-seen D0EDB47BEAD32D26D0A837F7D5357EC3AD3B8777 100 420\n" + "guard-seen 07B5547026DF3E229806E135CFA8552D56AFBABC 5 420\n", + yesterday_date_str); + + retval = dirserv_read_guardfraction_file_from_str(guardfraction_bad, NULL); + tt_int_op(retval, ==, -1); + tor_free(guardfraction_bad); + + /* This one does not have a date! Parsing should fail. */ + tor_asprintf(&guardfraction_bad, + "guardfraction-file-version 1\n" + "written-at not_date\n" + "n-inputs 420 3\n" + "guard-seen D0EDB47BEAD32D26D0A837F7D5357EC3AD3B8777 100 420\n" + "guard-seen 07B5547026DF3E229806E135CFA8552D56AFBABC 5 420\n"); + + retval = dirserv_read_guardfraction_file_from_str(guardfraction_bad, NULL); + tt_int_op(retval, ==, -1); + tor_free(guardfraction_bad); + + /* This one has an incomplete n-inputs line, but parsing should + still continue. */ + tor_asprintf(&guardfraction_bad, + "guardfraction-file-version 1\n" + "written-at %s\n" + "n-inputs biggie\n" + "guard-seen D0EDB47BEAD32D26D0A837F7D5357EC3AD3B8777 100 420\n" + "guard-seen 07B5547026DF3E229806E135CFA8552D56AFBABC 5 420\n", + yesterday_date_str); + + retval = dirserv_read_guardfraction_file_from_str(guardfraction_bad, NULL); + tt_int_op(retval, ==, 2); + tor_free(guardfraction_bad); + + /* This one does not have a fingerprint in the guard line! */ + tor_asprintf(&guardfraction_bad, + "guardfraction-file-version 1\n" + "written-at %s\n" + "n-inputs 420 3\n" + "guard-seen not_a_fingerprint 100 420\n", + yesterday_date_str); + + retval = dirserv_read_guardfraction_file_from_str(guardfraction_bad, NULL); + tt_int_op(retval, ==, 0); + tor_free(guardfraction_bad); + + /* This one does not even have an integer guardfraction value. */ + tor_asprintf(&guardfraction_bad, + "guardfraction-file-version 1\n" + "written-at %s\n" + "n-inputs 420 3\n" + "guard-seen D0EDB47BEAD32D26D0A837F7D5357EC3AD3B8777 NaN 420\n" + "guard-seen 07B5547026DF3E229806E135CFA8552D56AFBABC 5 420\n", + yesterday_date_str); + + retval = dirserv_read_guardfraction_file_from_str(guardfraction_bad, NULL); + tt_int_op(retval, ==, 1); + tor_free(guardfraction_bad); + + /* This one is not a percentage (not in [0, 100]) */ + tor_asprintf(&guardfraction_bad, + "guardfraction-file-version 1\n" + "written-at %s\n" + "n-inputs 420 3\n" + "guard-seen D0EDB47BEAD32D26D0A837F7D5357EC3AD3B8777 666 420\n" + "guard-seen 07B5547026DF3E229806E135CFA8552D56AFBABC 5 420\n", + yesterday_date_str); + + retval = dirserv_read_guardfraction_file_from_str(guardfraction_bad, NULL); + tt_int_op(retval, ==, 1); + tor_free(guardfraction_bad); + + /* This one is not a percentage either (not in [0, 100]) */ + tor_asprintf(&guardfraction_bad, + "guardfraction-file-version 1\n" + "written-at %s\n" + "n-inputs 420 3\n" + "guard-seen D0EDB47BEAD32D26D0A837F7D5357EC3AD3B8777 -3 420\n", + yesterday_date_str); + + retval = dirserv_read_guardfraction_file_from_str(guardfraction_bad, NULL); + tt_int_op(retval, ==, 0); + + done: + tor_free(guardfraction_bad); +} + +/** Make sure that our test guardfraction file gets parsed properly, and + * its information are applied properly to our routerstatuses. */ +static void +test_parse_guardfraction_file_good(void *arg) +{ + int retval; + vote_routerstatus_t *vrs_guard = NULL; + vote_routerstatus_t *vrs_dummy = NULL; + char *guardfraction_good = NULL; + const char *yesterday_date_str = get_yesterday_date_str(); + smartlist_t *routerstatuses = smartlist_new(); + + /* Some test values that we need to validate later */ + const char fpr_guard[] = "D0EDB47BEAD32D26D0A837F7D5357EC3AD3B8777"; + const char fpr_unlisted[] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; + const int guardfraction_value = 42; + + (void) arg; + + { + /* Populate the smartlist with some fake routerstatuses, so that + after parsing the guardfraction file we can check that their + elements got filled properly. */ + + /* This one is a guard */ + vrs_guard = gen_vote_routerstatus_for_tests(fpr_guard, 1); + tt_assert(vrs_guard); + smartlist_add(routerstatuses, vrs_guard); + + /* This one is a guard but it's not in the guardfraction file */ + vrs_dummy = gen_vote_routerstatus_for_tests(fpr_unlisted, 1); + tt_assert(vrs_dummy); + smartlist_add(routerstatuses, vrs_dummy); + } + + tor_asprintf(&guardfraction_good, + "guardfraction-file-version 1\n" + "written-at %s\n" + "n-inputs 420 3\n" + "guard-seen %s %d 420\n", + yesterday_date_str, + fpr_guard, guardfraction_value); + + /* Read the guardfraction file */ + retval = dirserv_read_guardfraction_file_from_str(guardfraction_good, + routerstatuses); + tt_int_op(retval, ==, 1); + + { /* Test that routerstatus fields got filled properly */ + + /* The guardfraction fields of the guard should be filled. */ + tt_assert(vrs_guard->status.has_guardfraction); + tt_int_op(vrs_guard->status.guardfraction_percentage, + ==, + guardfraction_value); + + /* The guard that was not in the guardfraction file should not have + been touched either. */ + tt_assert(!vrs_dummy->status.has_guardfraction); + } + + done: + vote_routerstatus_free(vrs_guard); + vote_routerstatus_free(vrs_dummy); + smartlist_free(routerstatuses); + tor_free(guardfraction_good); +} + +/** Make sure that the guardfraction bandwidths get calculated properly. */ +static void +test_get_guardfraction_bandwidth(void *arg) +{ + guardfraction_bandwidth_t gf_bw; + const int orig_bw = 1000; + + (void) arg; + + /* A guard with bandwidth 1000 and GuardFraction 0.25, should have + bandwidth 250 as a guard and bandwidth 750 as a non-guard. */ + guard_get_guardfraction_bandwidth(&gf_bw, + orig_bw, 25); + + tt_int_op(gf_bw.guard_bw, ==, 250); + tt_int_op(gf_bw.non_guard_bw, ==, 750); + + /* Also check the 'guard_bw + non_guard_bw == original_bw' + * invariant. */ + tt_int_op(gf_bw.non_guard_bw + gf_bw.guard_bw, ==, orig_bw); + + done: + ; +} + +/** Parse the GuardFraction element of the consensus, and make sure it + * gets parsed correctly. */ +static void +test_parse_guardfraction_consensus(void *arg) +{ + int retval; + or_options_t *options = get_options_mutable(); + + const char *guardfraction_str_good = "GuardFraction=66"; + routerstatus_t rs_good; + routerstatus_t rs_no_guard; + + const char *guardfraction_str_bad1 = "GuardFraction="; /* no value */ + routerstatus_t rs_bad1; + + const char *guardfraction_str_bad2 = "GuardFraction=166"; /* no percentage */ + routerstatus_t rs_bad2; + + (void) arg; + + /* GuardFraction use is currently disabled by default. So we need to + manually enable it. */ + options->UseGuardFraction = 1; + + { /* Properly formatted GuardFraction. Check that it gets applied + correctly. */ + memset(&rs_good, 0, sizeof(routerstatus_t)); + rs_good.is_possible_guard = 1; + + retval = routerstatus_parse_guardfraction(guardfraction_str_good, + NULL, NULL, + &rs_good); + tt_int_op(retval, ==, 0); + tt_assert(rs_good.has_guardfraction); + tt_int_op(rs_good.guardfraction_percentage, ==, 66); + } + + { /* Properly formatted GuardFraction but router is not a + guard. GuardFraction should not get applied. */ + memset(&rs_no_guard, 0, sizeof(routerstatus_t)); + tt_assert(!rs_no_guard.is_possible_guard); + + retval = routerstatus_parse_guardfraction(guardfraction_str_good, + NULL, NULL, + &rs_no_guard); + tt_int_op(retval, ==, 0); + tt_assert(!rs_no_guard.has_guardfraction); + } + + { /* Bad GuardFraction. Function should fail and not apply. */ + memset(&rs_bad1, 0, sizeof(routerstatus_t)); + rs_bad1.is_possible_guard = 1; + + retval = routerstatus_parse_guardfraction(guardfraction_str_bad1, + NULL, NULL, + &rs_bad1); + tt_int_op(retval, ==, -1); + tt_assert(!rs_bad1.has_guardfraction); + } + + { /* Bad GuardFraction. Function should fail and not apply. */ + memset(&rs_bad2, 0, sizeof(routerstatus_t)); + rs_bad2.is_possible_guard = 1; + + retval = routerstatus_parse_guardfraction(guardfraction_str_bad2, + NULL, NULL, + &rs_bad2); + tt_int_op(retval, ==, -1); + tt_assert(!rs_bad2.has_guardfraction); + } + + done: + ; +} + +/** Make sure that we use GuardFraction information when we should, + * according to the torrc option and consensus parameter. */ +static void +test_should_apply_guardfraction(void *arg) +{ + networkstatus_t vote_enabled, vote_disabled, vote_missing; + or_options_t *options = get_options_mutable(); + + (void) arg; + + { /* Fill the votes for later */ + /* This one suggests enabled GuardFraction. */ + memset(&vote_enabled, 0, sizeof(vote_enabled)); + vote_enabled.net_params = smartlist_new(); + smartlist_split_string(vote_enabled.net_params, + "UseGuardFraction=1", NULL, 0, 0); + + /* This one suggests disabled GuardFraction. */ + memset(&vote_disabled, 0, sizeof(vote_disabled)); + vote_disabled.net_params = smartlist_new(); + smartlist_split_string(vote_disabled.net_params, + "UseGuardFraction=0", NULL, 0, 0); + + /* This one doesn't have GuardFraction at all. */ + memset(&vote_missing, 0, sizeof(vote_missing)); + vote_missing.net_params = smartlist_new(); + smartlist_split_string(vote_missing.net_params, + "leon=trout", NULL, 0, 0); + } + + /* If torrc option is set to yes, we should always use + * guardfraction.*/ + options->UseGuardFraction = 1; + tt_int_op(should_apply_guardfraction(&vote_disabled), ==, 1); + + /* If torrc option is set to no, we should never use + * guardfraction.*/ + options->UseGuardFraction = 0; + tt_int_op(should_apply_guardfraction(&vote_enabled), ==, 0); + + /* Now let's test torrc option set to auto. */ + options->UseGuardFraction = -1; + + /* If torrc option is set to auto, and consensus parameter is set to + * yes, we should use guardfraction. */ + tt_int_op(should_apply_guardfraction(&vote_enabled), ==, 1); + + /* If torrc option is set to auto, and consensus parameter is set to + * no, we should use guardfraction. */ + tt_int_op(should_apply_guardfraction(&vote_disabled), ==, 0); + + /* If torrc option is set to auto, and consensus parameter is not + * set, we should fallback to "no". */ + tt_int_op(should_apply_guardfraction(&vote_missing), ==, 0); + + done: + SMARTLIST_FOREACH(vote_enabled.net_params, char *, cp, tor_free(cp)); + SMARTLIST_FOREACH(vote_disabled.net_params, char *, cp, tor_free(cp)); + SMARTLIST_FOREACH(vote_missing.net_params, char *, cp, tor_free(cp)); + smartlist_free(vote_enabled.net_params); + smartlist_free(vote_disabled.net_params); + smartlist_free(vote_missing.net_params); +} + +struct testcase_t guardfraction_tests[] = { + { "parse_guardfraction_file_bad", test_parse_guardfraction_file_bad, + TT_FORK, NULL, NULL }, + { "parse_guardfraction_file_good", test_parse_guardfraction_file_good, + TT_FORK, NULL, NULL }, + { "parse_guardfraction_consensus", test_parse_guardfraction_consensus, + TT_FORK, NULL, NULL }, + { "get_guardfraction_bandwidth", test_get_guardfraction_bandwidth, + TT_FORK, NULL, NULL }, + { "should_apply_guardfraction", test_should_apply_guardfraction, + TT_FORK, NULL, NULL }, + + END_OF_TESTCASES +}; + diff --git a/src/test/test_helpers.c b/src/test/test_helpers.c new file mode 100644 index 0000000000..c3ca0c3554 --- /dev/null +++ b/src/test/test_helpers.c @@ -0,0 +1,86 @@ +/* Copyright (c) 2014, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file test_helpers.c + * \brief Some helper functions to avoid code duplication in unit tests. + */ + +#define ROUTERLIST_PRIVATE +#include "orconfig.h" +#include "or.h" + +#include "routerlist.h" +#include "nodelist.h" + +#include "test.h" +#include "test_helpers.h" + +#include "test_descriptors.inc" + +/* Return a statically allocated string representing yesterday's date + * in ISO format. We use it so that state file items are not found to + * be outdated. */ +const char * +get_yesterday_date_str(void) +{ + static char buf[ISO_TIME_LEN+1]; + + time_t yesterday = time(NULL) - 24*60*60; + format_iso_time(buf, yesterday); + return buf; +} + +/* NOP replacement for router_descriptor_is_older_than() */ +static int +router_descriptor_is_older_than_replacement(const routerinfo_t *router, + int seconds) +{ + (void) router; + (void) seconds; + return 0; +} + +/** Parse a file containing router descriptors and load them to our + routerlist. This function is used to setup an artificial network + so that we can conduct tests on it. */ +void +helper_setup_fake_routerlist(void) +{ + int retval; + routerlist_t *our_routerlist = NULL; + smartlist_t *our_nodelist = NULL; + + /* Read the file that contains our test descriptors. */ + + /* We need to mock this function otherwise the descriptors will not + accepted as they are too old. */ + MOCK(router_descriptor_is_older_than, + router_descriptor_is_older_than_replacement); + + /* Load all the test descriptors to the routerlist. */ + retval = router_load_routers_from_string(TEST_DESCRIPTORS, + NULL, SAVED_IN_JOURNAL, + NULL, 0, NULL); + tt_int_op(retval, ==, HELPER_NUMBER_OF_DESCRIPTORS); + + /* Sanity checking of routerlist and nodelist. */ + our_routerlist = router_get_routerlist(); + tt_int_op(smartlist_len(our_routerlist->routers), ==, + HELPER_NUMBER_OF_DESCRIPTORS); + routerlist_assert_ok(our_routerlist); + + our_nodelist = nodelist_get_list(); + tt_int_op(smartlist_len(our_nodelist), ==, HELPER_NUMBER_OF_DESCRIPTORS); + + /* Mark all routers as non-guards but up and running! */ + SMARTLIST_FOREACH_BEGIN(our_nodelist, node_t *, node) { + node->is_running = 1; + node->is_valid = 1; + node->is_possible_guard = 0; + } SMARTLIST_FOREACH_END(node); + + done: + UNMOCK(router_descriptor_is_older_than); +} + diff --git a/src/test/test_helpers.h b/src/test/test_helpers.h new file mode 100644 index 0000000000..369243b459 --- /dev/null +++ b/src/test/test_helpers.h @@ -0,0 +1,17 @@ +/* Copyright (c) 2014-2015, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#ifndef TOR_TEST_HELPERS_H +#define TOR_TEST_HELPERS_H + +const char *get_yesterday_date_str(void); + +/* Number of descriptors contained in test_descriptors.txt. */ +#define HELPER_NUMBER_OF_DESCRIPTORS 8 + +void helper_setup_fake_routerlist(void); + +extern const char TEST_DESCRIPTORS[]; + +#endif + diff --git a/src/test/test_hs.c b/src/test/test_hs.c index 0246eaf648..67ef646aab 100644 --- a/src/test/test_hs.c +++ b/src/test/test_hs.c @@ -7,9 +7,15 @@ **/ #define CONTROL_PRIVATE +#define CIRCUITBUILD_PRIVATE + #include "or.h" #include "test.h" #include "control.h" +#include "config.h" +#include "routerset.h" +#include "circuitbuild.h" +#include "test_helpers.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" \ @@ -123,9 +129,83 @@ test_hs_desc_event(void *arg) tor_free(received_msg); } +/* Make sure we always pick the right RP, given a well formatted + * Tor2webRendezvousPoints value. */ +static void +test_pick_tor2web_rendezvous_node(void *arg) +{ + or_options_t *options = get_options_mutable(); + const node_t *chosen_rp = NULL; + router_crn_flags_t flags = CRN_NEED_DESC; + int retval, i; + const char *tor2web_rendezvous_str = "test003r"; + + (void) arg; + + /* Setup fake routerlist. */ + helper_setup_fake_routerlist(); + + /* Parse Tor2webRendezvousPoints as a routerset. */ + options->Tor2webRendezvousPoints = routerset_new(); + retval = routerset_parse(options->Tor2webRendezvousPoints, + tor2web_rendezvous_str, + "test_tor2web_rp"); + tt_int_op(retval, >=, 0); + + /* Pick rendezvous point. Make sure the correct one is + picked. Repeat many times to make sure it works properly. */ + for (i = 0; i < 50 ; i++) { + chosen_rp = pick_tor2web_rendezvous_node(flags, options); + tt_assert(chosen_rp); + tt_str_op(chosen_rp->ri->nickname, ==, tor2web_rendezvous_str); + } + + done: + routerset_free(options->Tor2webRendezvousPoints); +} + +/* Make sure we never pick an RP if Tor2webRendezvousPoints doesn't + * correspond to an actual node. */ +static void +test_pick_bad_tor2web_rendezvous_node(void *arg) +{ + or_options_t *options = get_options_mutable(); + const node_t *chosen_rp = NULL; + router_crn_flags_t flags = CRN_NEED_DESC; + int retval, i; + const char *tor2web_rendezvous_str = "dummy"; + + (void) arg; + + /* Setup fake routerlist. */ + helper_setup_fake_routerlist(); + + /* Parse Tor2webRendezvousPoints as a routerset. */ + options->Tor2webRendezvousPoints = routerset_new(); + retval = routerset_parse(options->Tor2webRendezvousPoints, + tor2web_rendezvous_str, + "test_tor2web_rp"); + tt_int_op(retval, >=, 0); + + /* Pick rendezvous point. Since Tor2webRendezvousPoints was set to a + dummy value, we shouldn't find any eligible RPs. */ + for (i = 0; i < 50 ; i++) { + chosen_rp = pick_tor2web_rendezvous_node(flags, options); + tt_assert(!chosen_rp); + } + + done: + routerset_free(options->Tor2webRendezvousPoints); +} + struct testcase_t hs_tests[] = { { "hs_desc_event", test_hs_desc_event, TT_FORK, NULL, NULL }, + { "pick_tor2web_rendezvous_node", test_pick_tor2web_rendezvous_node, TT_FORK, + NULL, NULL }, + { "pick_bad_tor2web_rendezvous_node", + test_pick_bad_tor2web_rendezvous_node, TT_FORK, + NULL, NULL }, END_OF_TESTCASES }; diff --git a/src/test/test_oom.c b/src/test/test_oom.c index 28b4c0435a..41cfcdbd81 100644 --- a/src/test/test_oom.c +++ b/src/test/test_oom.c @@ -13,9 +13,6 @@ #include "compat_libevent.h" #include "connection.h" #include "config.h" -#ifdef ENABLE_MEMPOOLS -#include "mempool.h" -#endif #include "relay.h" #include "test.h" @@ -143,10 +140,6 @@ test_oom_circbuf(void *arg) MOCK(circuit_mark_for_close_, circuit_mark_for_close_dummy_); -#ifdef ENABLE_MEMPOOLS - init_cell_pool(); -#endif /* ENABLE_MEMPOOLS */ - /* Far too low for real life. */ options->MaxMemInQueues = 256*packed_cell_mem_cost(); options->CellStatistics = 0; @@ -164,13 +157,8 @@ test_oom_circbuf(void *arg) tor_gettimeofday_cache_set(&tv); c2 = dummy_or_circuit_new(20, 20); -#ifdef ENABLE_MEMPOOLS - tt_int_op(packed_cell_mem_cost(), OP_EQ, - sizeof(packed_cell_t) + MP_POOL_ITEM_OVERHEAD); -#else tt_int_op(packed_cell_mem_cost(), OP_EQ, sizeof(packed_cell_t)); -#endif /* ENABLE_MEMPOOLS */ tt_int_op(cell_queues_get_total_allocation(), OP_EQ, packed_cell_mem_cost() * 70); tt_int_op(cell_queues_check_size(), OP_EQ, 0); /* We are still not OOM */ @@ -242,10 +230,6 @@ test_oom_streambuf(void *arg) MOCK(circuit_mark_for_close_, circuit_mark_for_close_dummy_); -#ifdef ENABLE_MEMPOOLS - init_cell_pool(); -#endif /* ENABLE_MEMPOOLS */ - /* Far too low for real life. */ options->MaxMemInQueues = 81*packed_cell_mem_cost() + 4096 * 34; options->CellStatistics = 0; diff --git a/src/test/test_relay.c b/src/test/test_relay.c index 2144ef335e..6081956d46 100644 --- a/src/test/test_relay.c +++ b/src/test/test_relay.c @@ -60,11 +60,6 @@ test_relay_append_cell_to_circuit_queue(void *arg) (void)arg; - /* We'll need the cell pool for append_cell_to_circuit_queue() to work */ -#ifdef ENABLE_MEMPOOLS - init_cell_pool(); -#endif /* ENABLE_MEMPOOLS */ - /* Make fake channels to be nchan and pchan for the circuit */ nchan = new_fake_channel(); tt_assert(nchan); @@ -119,9 +114,6 @@ test_relay_append_cell_to_circuit_queue(void *arg) tor_free(orcirc); free_fake_channel(nchan); free_fake_channel(pchan); -#ifdef ENABLE_MEMPOOLS - free_cell_pool(); -#endif /* ENABLE_MEMPOOLS */ return; } diff --git a/src/test/test_status.c b/src/test/test_status.c index aa71aa6a9b..cbc8af188c 100644 --- a/src/test/test_status.c +++ b/src/test/test_status.c @@ -240,7 +240,6 @@ NS(test_main)(void *arg) NS_DECL(double, tls_get_write_overhead_ratio, (void)); NS_DECL(int, we_are_hibernating, (void)); -NS_DECL(const or_options_t *, get_options, (void)); NS_DECL(int, public_server_mode, (const or_options_t *options)); NS_DECL(const routerinfo_t *, router_get_my_routerinfo, (void)); @@ -252,7 +251,6 @@ NS(test_main)(void *arg) NS_MOCK(tls_get_write_overhead_ratio); NS_MOCK(we_are_hibernating); - NS_MOCK(get_options); NS_MOCK(public_server_mode); NS_MOCK(router_get_my_routerinfo); @@ -264,7 +262,6 @@ NS(test_main)(void *arg) done: NS_UNMOCK(tls_get_write_overhead_ratio); NS_UNMOCK(we_are_hibernating); - NS_UNMOCK(get_options); NS_UNMOCK(public_server_mode); NS_UNMOCK(router_get_my_routerinfo); } @@ -281,12 +278,6 @@ NS(we_are_hibernating)(void) return 0; } -static const or_options_t * -NS(get_options)(void) -{ - return NULL; -} - static int NS(public_server_mode)(const or_options_t *options) { @@ -311,7 +302,6 @@ NS(router_get_my_routerinfo)(void) NS_DECL(double, tls_get_write_overhead_ratio, (void)); NS_DECL(int, we_are_hibernating, (void)); -NS_DECL(const or_options_t *, get_options, (void)); NS_DECL(int, public_server_mode, (const or_options_t *options)); NS_DECL(const routerinfo_t *, router_get_my_routerinfo, (void)); NS_DECL(const node_t *, node_get_by_id, (const char *identity_digest)); @@ -331,7 +321,6 @@ NS(test_main)(void *arg) NS_MOCK(tls_get_write_overhead_ratio); NS_MOCK(we_are_hibernating); - NS_MOCK(get_options); NS_MOCK(public_server_mode); NS_MOCK(router_get_my_routerinfo); NS_MOCK(node_get_by_id); @@ -348,12 +337,11 @@ NS(test_main)(void *arg) actual = log_heartbeat(0); tt_int_op(actual, OP_EQ, expected); - tt_int_op(CALLED(logv), OP_EQ, 3); + tt_int_op(CALLED(logv), OP_EQ, 5); done: NS_UNMOCK(tls_get_write_overhead_ratio); NS_UNMOCK(we_are_hibernating); - NS_UNMOCK(get_options); NS_UNMOCK(public_server_mode); NS_UNMOCK(router_get_my_routerinfo); NS_UNMOCK(node_get_by_id); @@ -374,12 +362,6 @@ NS(we_are_hibernating)(void) return 0; } -static const or_options_t * -NS(get_options)(void) -{ - return NULL; -} - static int NS(public_server_mode)(const or_options_t *options) { @@ -433,6 +415,9 @@ NS(logv)(int severity, log_domain_mask_t domain, tt_str_op(va_arg(ap, char *), OP_EQ, ""); /* hibernating */ break; case 2: + tt_int_op(severity, OP_EQ, LOG_INFO); + break; + case 3: tt_int_op(severity, OP_EQ, LOG_NOTICE); tt_int_op(domain, OP_EQ, LD_HEARTBEAT); tt_ptr_op(strstr(funcname, "rep_hist_log_circuit_handshake_stats"), @@ -445,6 +430,12 @@ NS(logv)(int severity, log_domain_mask_t domain, tt_int_op(va_arg(ap, int), OP_EQ, 1); /* handshakes assigned (NTOR) */ tt_int_op(va_arg(ap, int), OP_EQ, 1); /* handshakes requested (NTOR) */ break; + case 4: + tt_int_op(severity, OP_EQ, LOG_NOTICE); + tt_int_op(domain, OP_EQ, LD_HEARTBEAT); + tt_ptr_op(strstr(funcname, "rep_hist_log_link_protocol_counts"), + OP_NE, NULL); + break; default: tt_abort_msg("unexpected call to logv()"); // TODO: prettyprint args break; @@ -472,7 +463,6 @@ NS(server_mode)(const or_options_t *options) NS_DECL(double, tls_get_write_overhead_ratio, (void)); NS_DECL(int, we_are_hibernating, (void)); -NS_DECL(const or_options_t *, get_options, (void)); NS_DECL(int, public_server_mode, (const or_options_t *options)); NS_DECL(long, get_uptime, (void)); NS_DECL(uint64_t, get_bytes_read, (void)); @@ -481,6 +471,8 @@ NS_DECL(void, logv, (int severity, log_domain_mask_t domain, const char *funcname, const char *suffix, const char *format, va_list ap)); NS_DECL(int, server_mode, (const or_options_t *options)); +static int NS(n_msgs) = 0; + static void NS(test_main)(void *arg) { @@ -489,7 +481,6 @@ NS(test_main)(void *arg) NS_MOCK(tls_get_write_overhead_ratio); NS_MOCK(we_are_hibernating); - NS_MOCK(get_options); NS_MOCK(public_server_mode); NS_MOCK(get_uptime); NS_MOCK(get_bytes_read); @@ -503,11 +494,11 @@ NS(test_main)(void *arg) actual = log_heartbeat(0); tt_int_op(actual, OP_EQ, expected); + tt_int_op(NS(n_msgs), OP_EQ, 1); done: NS_UNMOCK(tls_get_write_overhead_ratio); NS_UNMOCK(we_are_hibernating); - NS_UNMOCK(get_options); NS_UNMOCK(public_server_mode); NS_UNMOCK(get_uptime); NS_UNMOCK(get_bytes_read); @@ -528,12 +519,6 @@ NS(we_are_hibernating)(void) return 1; } -static const or_options_t * -NS(get_options)(void) -{ - return NULL; -} - static int NS(public_server_mode)(const or_options_t *options) { @@ -564,6 +549,10 @@ static void NS(logv)(int severity, log_domain_mask_t domain, const char *funcname, const char *suffix, const char *format, va_list ap) { + if (severity == LOG_INFO) + return; + ++NS(n_msgs); + tt_int_op(severity, OP_EQ, LOG_NOTICE); tt_int_op(domain, OP_EQ, LD_HEARTBEAT); tt_ptr_op(strstr(funcname, "log_heartbeat"), OP_NE, NULL); @@ -599,7 +588,6 @@ NS(server_mode)(const or_options_t *options) NS_DECL(double, tls_get_write_overhead_ratio, (void)); NS_DECL(int, we_are_hibernating, (void)); -NS_DECL(const or_options_t *, get_options, (void)); NS_DECL(int, public_server_mode, (const or_options_t *options)); NS_DECL(long, get_uptime, (void)); NS_DECL(uint64_t, get_bytes_read, (void)); @@ -622,7 +610,6 @@ NS(test_main)(void *arg) NS_MOCK(tls_get_write_overhead_ratio); NS_MOCK(we_are_hibernating); - NS_MOCK(get_options); NS_MOCK(public_server_mode); NS_MOCK(get_uptime); NS_MOCK(get_bytes_read); @@ -639,12 +626,11 @@ NS(test_main)(void *arg) actual = log_heartbeat(0); tt_int_op(actual, OP_EQ, expected); - tt_int_op(CALLED(logv), OP_EQ, 2); + tt_int_op(CALLED(logv), OP_EQ, 3); done: NS_UNMOCK(tls_get_write_overhead_ratio); NS_UNMOCK(we_are_hibernating); - NS_UNMOCK(get_options); NS_UNMOCK(public_server_mode); NS_UNMOCK(get_uptime); NS_UNMOCK(get_bytes_read); @@ -669,15 +655,6 @@ NS(we_are_hibernating)(void) return 0; } -static const or_options_t * -NS(get_options)(void) -{ - NS(mock_options) = tor_malloc_zero(sizeof(or_options_t)); - NS(mock_options)->AccountingMax = 0; - - return NS(mock_options); -} - static int NS(public_server_mode)(const or_options_t *options) { @@ -741,6 +718,9 @@ NS(logv)(int severity, log_domain_mask_t domain, OP_NE, NULL); /* end_buf */ tt_str_op(va_arg(ap, char *), OP_EQ, "0:01 hours"); /* remaining */ break; + case 2: + tt_int_op(severity, OP_EQ, LOG_INFO); + break; default: tt_abort_msg("unexpected call to logv()"); // TODO: prettyprint args break; @@ -792,7 +772,6 @@ NS(get_or_state)(void) NS_DECL(double, tls_get_write_overhead_ratio, (void)); NS_DECL(int, we_are_hibernating, (void)); -NS_DECL(const or_options_t *, get_options, (void)); NS_DECL(int, public_server_mode, (const or_options_t *options)); NS_DECL(long, get_uptime, (void)); NS_DECL(uint64_t, get_bytes_read, (void)); @@ -810,7 +789,6 @@ NS(test_main)(void *arg) NS_MOCK(tls_get_write_overhead_ratio); NS_MOCK(we_are_hibernating); - NS_MOCK(get_options); NS_MOCK(public_server_mode); NS_MOCK(get_uptime); NS_MOCK(get_bytes_read); @@ -821,7 +799,7 @@ NS(test_main)(void *arg) log_global_min_severity_ = LOG_DEBUG; stats_n_data_bytes_packaged = RELAY_PAYLOAD_SIZE; - stats_n_data_cells_packaged = 1; + stats_n_data_cells_packaged = 2; expected = 0; actual = log_heartbeat(0); @@ -833,7 +811,6 @@ NS(test_main)(void *arg) stats_n_data_cells_packaged = 0; NS_UNMOCK(tls_get_write_overhead_ratio); NS_UNMOCK(we_are_hibernating); - NS_UNMOCK(get_options); NS_UNMOCK(public_server_mode); NS_UNMOCK(get_uptime); NS_UNMOCK(get_bytes_read); @@ -855,12 +832,6 @@ NS(we_are_hibernating)(void) return 0; } -static const or_options_t * -NS(get_options)(void) -{ - return NULL; -} - static int NS(public_server_mode)(const or_options_t *options) { @@ -913,8 +884,10 @@ NS(logv)(int severity, log_domain_mask_t domain, const char *funcname, tt_ptr_op(strstr(funcname, "log_heartbeat"), OP_NE, NULL); tt_ptr_op(suffix, OP_EQ, NULL); tt_str_op(format, OP_EQ, - "Average packaged cell fullness: %2.3f%%"); - tt_int_op(fabs(va_arg(ap, double) - 100.0) <= DBL_EPSILON, OP_EQ, 1); + "Average packaged cell fullness: %2.3f%%. " + "TLS write overhead: %.f%%"); + tt_double_op(fabs(va_arg(ap, double) - 50.0), <=, DBL_EPSILON); + tt_double_op(fabs(va_arg(ap, double) - 0.0), <=, DBL_EPSILON); break; default: tt_abort_msg("unexpected call to logv()"); // TODO: prettyprint args @@ -951,7 +924,6 @@ NS(accounting_is_enabled)(const or_options_t *options) NS_DECL(double, tls_get_write_overhead_ratio, (void)); NS_DECL(int, we_are_hibernating, (void)); -NS_DECL(const or_options_t *, get_options, (void)); NS_DECL(int, public_server_mode, (const or_options_t *options)); NS_DECL(long, get_uptime, (void)); NS_DECL(uint64_t, get_bytes_read, (void)); @@ -969,7 +941,6 @@ NS(test_main)(void *arg) NS_MOCK(tls_get_write_overhead_ratio); NS_MOCK(we_are_hibernating); - NS_MOCK(get_options); NS_MOCK(public_server_mode); NS_MOCK(get_uptime); NS_MOCK(get_bytes_read); @@ -989,7 +960,6 @@ NS(test_main)(void *arg) done: NS_UNMOCK(tls_get_write_overhead_ratio); NS_UNMOCK(we_are_hibernating); - NS_UNMOCK(get_options); NS_UNMOCK(public_server_mode); NS_UNMOCK(get_uptime); NS_UNMOCK(get_bytes_read); @@ -1011,12 +981,6 @@ NS(we_are_hibernating)(void) return 0; } -static const or_options_t * -NS(get_options)(void) -{ - return NULL; -} - static int NS(public_server_mode)(const or_options_t *options) { @@ -1068,8 +1032,11 @@ NS(logv)(int severity, log_domain_mask_t domain, tt_int_op(domain, OP_EQ, LD_HEARTBEAT); tt_ptr_op(strstr(funcname, "log_heartbeat"), OP_NE, NULL); tt_ptr_op(suffix, OP_EQ, NULL); - tt_str_op(format, OP_EQ, "TLS write overhead: %.f%%"); + tt_str_op(format, OP_EQ, + "Average packaged cell fullness: %2.3f%%. " + "TLS write overhead: %.f%%"); tt_int_op(fabs(va_arg(ap, double) - 100.0) <= DBL_EPSILON, OP_EQ, 1); + tt_double_op(fabs(va_arg(ap, double) - 100.0), <=, DBL_EPSILON); break; default: tt_abort_msg("unexpected call to logv()"); // TODO: prettyprint args diff --git a/src/test/test_util.c b/src/test/test_util.c index e5df5b4494..6a4c3ec072 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -6,15 +6,11 @@ #include "orconfig.h" #define COMPAT_PRIVATE #define CONTROL_PRIVATE -#define MEMPOOL_PRIVATE #define UTIL_PRIVATE #include "or.h" #include "config.h" #include "control.h" #include "test.h" -#ifdef ENABLE_MEMPOOLS -#include "mempool.h" -#endif /* ENABLE_MEMPOOLS */ #include "memarea.h" #include "util_process.h" @@ -2644,69 +2640,6 @@ test_util_path_is_relative(void *arg) ; } -#ifdef ENABLE_MEMPOOLS - -/** Run unittests for memory pool allocator */ -static void -test_util_mempool(void *arg) -{ - mp_pool_t *pool = NULL; - smartlist_t *allocated = NULL; - int i; - - (void)arg; - pool = mp_pool_new(1, 100); - tt_assert(pool); - tt_assert(pool->new_chunk_capacity >= 100); - tt_assert(pool->item_alloc_size >= sizeof(void*)+1); - mp_pool_destroy(pool); - pool = NULL; - - pool = mp_pool_new(241, 2500); - tt_assert(pool); - tt_assert(pool->new_chunk_capacity >= 10); - tt_assert(pool->item_alloc_size >= sizeof(void*)+241); - tt_int_op(pool->item_alloc_size & 0x03,OP_EQ, 0); - tt_assert(pool->new_chunk_capacity < 60); - - allocated = smartlist_new(); - for (i = 0; i < 20000; ++i) { - if (smartlist_len(allocated) < 20 || crypto_rand_int(2)) { - void *m = mp_pool_get(pool); - memset(m, 0x09, 241); - smartlist_add(allocated, m); - //printf("%d: %p\n", i, m); - //mp_pool_assert_ok(pool); - } else { - int idx = crypto_rand_int(smartlist_len(allocated)); - void *m = smartlist_get(allocated, idx); - //printf("%d: free %p\n", i, m); - smartlist_del(allocated, idx); - mp_pool_release(m); - //mp_pool_assert_ok(pool); - } - if (crypto_rand_int(777)==0) - mp_pool_clean(pool, 1, 1); - - if (i % 777) - mp_pool_assert_ok(pool); - } - - done: - if (allocated) { - SMARTLIST_FOREACH(allocated, void *, m, mp_pool_release(m)); - mp_pool_assert_ok(pool); - mp_pool_clean(pool, 0, 0); - mp_pool_assert_ok(pool); - smartlist_free(allocated); - } - - if (pool) - mp_pool_destroy(pool); -} - -#endif /* ENABLE_MEMPOOLS */ - /** Run unittests for memory area allocator */ static void test_util_memarea(void *arg) @@ -4178,26 +4111,6 @@ test_util_laplace(void *arg) ; } -static void -test_util_strclear(void *arg) -{ - static const char *vals[] = { "", "a", "abcdef", "abcdefgh", NULL }; - int i; - char *v = NULL; - (void)arg; - - for (i = 0; vals[i]; ++i) { - size_t n; - v = tor_strdup(vals[i]); - n = strlen(v); - tor_strclear(v); - tt_assert(tor_mem_is_zero(v, n+1)); - tor_free(v); - } - done: - tor_free(v); -} - #define UTIL_LEGACY(name) \ { #name, test_util_ ## name , 0, NULL, NULL } @@ -4405,9 +4318,6 @@ struct testcase_t util_tests[] = { UTIL_LEGACY(pow2), UTIL_LEGACY(gzip), UTIL_LEGACY(datadir), -#ifdef ENABLE_MEMPOOLS - UTIL_LEGACY(mempool), -#endif UTIL_LEGACY(memarea), UTIL_LEGACY(control_formats), UTIL_LEGACY(mmap), @@ -4418,7 +4328,6 @@ struct testcase_t util_tests[] = { UTIL_LEGACY(di_ops), UTIL_TEST(round_to_next_multiple_of, 0), UTIL_TEST(laplace, 0), - UTIL_TEST(strclear, 0), UTIL_TEST(find_str_at_start_of_line, 0), UTIL_TEST(string_is_C_identifier, 0), UTIL_TEST(asprintf, 0), diff --git a/src/test/test_workqueue.c b/src/test/test_workqueue.c index aaff5069be..83f6f3e215 100644 --- a/src/test/test_workqueue.c +++ b/src/test/test_workqueue.c @@ -18,6 +18,8 @@ #include <event.h> #endif +#define MAX_INFLIGHT (1<<16) + static int opt_verbose = 0; static int opt_n_threads = 8; static int opt_n_items = 10000; @@ -348,7 +350,7 @@ main(int argc, char **argv) } if (opt_n_threads < 1 || opt_n_items < 1 || opt_n_inflight < 1 || opt_n_lowwater < 0 || - opt_n_cancel > opt_n_inflight || + opt_n_cancel > opt_n_inflight || opt_n_inflight > MAX_INFLIGHT || opt_ratio_rsa < 0) { help(); return 1; diff --git a/src/test/testing_common.c b/src/test/testing_common.c index d7d6dacee6..403c83bdd2 100644 --- a/src/test/testing_common.c +++ b/src/test/testing_common.c @@ -165,18 +165,21 @@ static crypto_pk_t *pregen_keys[5] = {NULL, NULL, NULL, NULL, NULL}; crypto_pk_t * pk_generate(int idx) { + int res; #ifdef CACHE_GENERATED_KEYS tor_assert(idx < N_PREGEN_KEYS); if (! pregen_keys[idx]) { pregen_keys[idx] = crypto_pk_new(); - tor_assert(!crypto_pk_generate_key(pregen_keys[idx])); + res = crypto_pk_generate_key(pregen_keys[idx]); + tor_assert(!res); } return crypto_pk_dup_key(pregen_keys[idx]); #else crypto_pk_t *result; (void) idx; result = crypto_pk_new(); - tor_assert(!crypto_pk_generate_key(result)); + res = crypto_pk_generate_key(result); + tor_assert(!res); return result; #endif } diff --git a/src/test/zero_length_keys.sh b/src/test/zero_length_keys.sh index 3a99ca1f1d..2fd11d38bd 100755 --- a/src/test/zero_length_keys.sh +++ b/src/test/zero_length_keys.sh @@ -13,10 +13,10 @@ # Check tor does not overwrite existing keys (existing behaviour) # # Exit Statuses: -# -2: test failed - tor did not generate the key files on first run -# -1: a command failed - the test could not be completed # 0: test succeeded - tor regenerated/kept the files # 1: test failed - tor did not regenerate/keep the files +# 2: test failed - tor did not generate the key files on first run +# 3: a command failed - the test could not be completed # if [ $# -lt 1 ]; then @@ -25,33 +25,42 @@ if [ $# -lt 1 ]; then exit $? fi -export DATA_DIR=`mktemp -d -t tor_zero_length_keys.XXXXXX` +DATA_DIR=`mktemp -d -t tor_zero_length_keys.XXXXXX` +if [ -z "$DATA_DIR" ]; then + echo "Failure: mktemp invocation returned empty string" >&2 + exit 3 +fi +if [ ! -d "$DATA_DIR" ]; then + echo "Failure: mktemp invocation result doesn't point to directory" >&2 + exit 3 +fi +trap "rm -rf '$DATA_DIR'" 0 + +touch "$DATA_DIR"/empty_torrc + # DisableNetwork means that the ORPort won't actually be opened. # 'ExitRelay 0' suppresses a warning. -TOR="./src/or/tor --hush --DisableNetwork 1 --ShutdownWaitLength 0 --ORPort 12345 --ExitRelay 0" +TOR="./src/or/tor --hush --DisableNetwork 1 --ShutdownWaitLength 0 --ORPort 12345 --ExitRelay 0 -f $DATA_DIR/empty_torrc" -if [ -s "$DATA_DIR"/keys/secret_id_key -a -s "$DATA_DIR"/keys/secret_onion_key -a -s "$DATA_DIR"/keys/secret_onion_key_ntor ]; then - echo "Failure: Previous tor keys present in tor data directory" - exit -1 +if [ -s "$DATA_DIR"/keys/secret_id_key ] && [ -s "$DATA_DIR"/keys/secret_onion_key ] && + [ -s "$DATA_DIR"/keys/secret_onion_key_ntor ]; then + echo "Failure: Previous tor keys present in tor data directory" >&2 + exit 3 else echo "Generating initial tor keys" - $TOR --DataDirectory "$DATA_DIR" --PidFile "$DATA_DIR"/pid & - TOR_PID=$! - # generate SIGTERM, hopefully after the keys have been regenerated - sleep 5 - kill $TOR_PID - wait $TOR_PID + $TOR --DataDirectory "$DATA_DIR" --list-fingerprint # tor must successfully generate non-zero-length key files - if [ -s "$DATA_DIR"/keys/secret_id_key -a -s "$DATA_DIR"/keys/secret_onion_key -a -s "$DATA_DIR"/keys/secret_onion_key_ntor ]; then + if [ -s "$DATA_DIR"/keys/secret_id_key ] && [ -s "$DATA_DIR"/keys/secret_onion_key ] && + [ -s "$DATA_DIR"/keys/secret_onion_key_ntor ]; then true #echo "tor generated the initial key files" else echo "Failure: tor failed to generate the initial key files" - exit -2 + exit 2 fi fi -#ls -lh "$DATA_DIR"/keys/ || exit -1 +#ls -lh "$DATA_DIR"/keys/ || exit 3 # backup and keep/delete/create zero-length files for the keys @@ -62,31 +71,27 @@ cp -r "$DATA_DIR"/keys "$DATA_DIR"/keys.old # delete keys for -d or -z if [ "$1" != "-e" ]; then FILE_DESC="regenerates deleted" - rm "$DATA_DIR"/keys/secret_id_key || exit -1 - rm "$DATA_DIR"/keys/secret_onion_key || exit -1 - rm "$DATA_DIR"/keys/secret_onion_key_ntor || exit -1 + rm "$DATA_DIR"/keys/secret_id_key || exit 3 + rm "$DATA_DIR"/keys/secret_onion_key || exit 3 + rm "$DATA_DIR"/keys/secret_onion_key_ntor || exit 3 fi # create empty files for -z if [ "$1" = "-z" ]; then FILE_DESC="regenerates zero-length" - touch "$DATA_DIR"/keys/secret_id_key || exit -1 - touch "$DATA_DIR"/keys/secret_onion_key || exit -1 - touch "$DATA_DIR"/keys/secret_onion_key_ntor || exit -1 + touch "$DATA_DIR"/keys/secret_id_key || exit 3 + touch "$DATA_DIR"/keys/secret_onion_key || exit 3 + touch "$DATA_DIR"/keys/secret_onion_key_ntor || exit 3 fi echo "Running tor again to check if it $FILE_DESC keys" -$TOR --DataDirectory "$DATA_DIR" --PidFile "$DATA_DIR"/pid & -TOR_PID=$! -# generate SIGTERM, hopefully after the keys have been regenerated -sleep 5 -kill $TOR_PID -wait $TOR_PID +$TOR --DataDirectory "$DATA_DIR" --list-fingerprint -#ls -lh "$DATA_DIR"/keys/ || exit -1 +#ls -lh "$DATA_DIR"/keys/ || exit 3 # tor must always have non-zero-length key files -if [ -s "$DATA_DIR"/keys/secret_id_key -a -s "$DATA_DIR"/keys/secret_onion_key -a -s "$DATA_DIR"/keys/secret_onion_key_ntor ]; then +if [ -s "$DATA_DIR"/keys/secret_id_key ] && [ -s "$DATA_DIR"/keys/secret_onion_key ] && + [ -s "$DATA_DIR"/keys/secret_onion_key_ntor ]; then # check if the keys are different to the old ones diff -q -r "$DATA_DIR"/keys "$DATA_DIR"/keys.old > /dev/null SAME_KEYS=$? |