diff options
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/include.am | 5 | ||||
-rw-r--r-- | src/test/test.c | 19 | ||||
-rw-r--r-- | src/test/test_bt_cl.c | 5 | ||||
-rw-r--r-- | src/test/test_circuitlist.c | 16 | ||||
-rw-r--r-- | src/test/test_config.c | 10 | ||||
-rw-r--r-- | src/test/test_containers.c | 138 | ||||
-rw-r--r-- | src/test/test_descriptors.inc | 305 | ||||
-rw-r--r-- | src/test/test_dir.c | 16 | ||||
-rw-r--r-- | src/test/test_entrynodes.c | 727 | ||||
-rw-r--r-- | src/test/test_logging.c | 2 | ||||
-rw-r--r-- | src/test/test_pt.c | 2 | ||||
-rw-r--r-- | src/test/test_routerset.c | 2118 | ||||
-rw-r--r-- | src/test/test_status.c | 28 | ||||
-rw-r--r-- | src/test/test_util.c | 127 |
14 files changed, 3408 insertions, 110 deletions
diff --git a/src/test/include.am b/src/test/include.am index fba439a616..77c92f12f8 100644 --- a/src/test/include.am +++ b/src/test/include.am @@ -28,6 +28,7 @@ src_test_test_SOURCES = \ src/test/test_cell_queue.c \ src/test/test_data.c \ src/test/test_dir.c \ + src/test/test_entrynodes.c \ src/test/test_extorport.c \ src/test/test_introduce.c \ src/test/test_logging.c \ @@ -45,6 +46,7 @@ src_test_test_SOURCES = \ src/test/test_nodelist.c \ src/test/test_policy.c \ src/test/test_status.c \ + src/test/test_routerset.c \ src/ext/tinytest.c src_test_test_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) @@ -71,7 +73,8 @@ src_test_bench_LDADD = src/or/libtor.a src/common/libor.a \ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ noinst_HEADERS+= \ - src/test/test.h + src/test/test.h \ + src/test/test_descriptors.inc if CURVE25519_ENABLED noinst_PROGRAMS+= src/test/test-ntor-cl diff --git a/src/test/test.c b/src/test/test.c index 8bce9c91f4..e836160bf4 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -43,6 +43,7 @@ long int lround(double x); double fabs(double x); #include "or.h" +#include "backtrace.h" #include "buffers.h" #include "circuitlist.h" #include "circuitstats.h" @@ -106,11 +107,18 @@ setup_directory(void) { char buf[MAX_PATH]; const char *tmp = buf; + const char *extra_backslash = ""; /* If this fails, we're probably screwed anyway */ if (!GetTempPathA(sizeof(buf),buf)) - tmp = "c:\\windows\\temp"; + tmp = "c:\\windows\\temp\\"; + if (strcmpend(tmp, "\\")) { + /* According to MSDN, it should be impossible for GetTempPath to give us + * an answer that doesn't end with \. But let's make sure. */ + extra_backslash = "\\"; + } tor_snprintf(temp_dir, sizeof(temp_dir), - "%s\\tor_test_%d_%s", tmp, (int)getpid(), rnd32); + "%s%stor_test_%d_%s", tmp, extra_backslash, + (int)getpid(), rnd32); r = mkdir(temp_dir); } #else @@ -184,7 +192,7 @@ remove_directory(void) #undef CACHE_GENERATED_KEYS static crypto_pk_t *pregen_keys[5] = {NULL, NULL, NULL, NULL, NULL}; -#define N_PREGEN_KEYS ((int)(sizeof(pregen_keys)/sizeof(pregen_keys[0]))) +#define N_PREGEN_KEYS ARRAY_LENGTH(pregen_keys) /** Generate and return a new keypair for use in unit tests. If we're using * the key cache optimization, we might reuse keys: we only guarantee that @@ -1306,6 +1314,7 @@ extern struct testcase_t circuitmux_tests[]; extern struct testcase_t cell_queue_tests[]; extern struct testcase_t options_tests[]; extern struct testcase_t socks_tests[]; +extern struct testcase_t entrynodes_tests[]; extern struct testcase_t extorport_tests[]; extern struct testcase_t controller_event_tests[]; extern struct testcase_t logging_tests[]; @@ -1315,6 +1324,7 @@ extern struct testcase_t routerkeys_tests[]; extern struct testcase_t oom_tests[]; extern struct testcase_t policy_tests[]; extern struct testcase_t status_tests[]; +extern struct testcase_t routerset_tests[]; static struct testgroup_t testgroups[] = { { "", test_array }, @@ -1337,6 +1347,7 @@ static struct testgroup_t testgroups[] = { { "circuitlist/", circuitlist_tests }, { "circuitmux/", circuitmux_tests }, { "options/", options_tests }, + { "entrynodes/", entrynodes_tests }, { "extorport/", extorport_tests }, { "control/", controller_event_tests }, { "hs/", hs_tests }, @@ -1345,6 +1356,7 @@ static struct testgroup_t testgroups[] = { { "oom/", oom_tests }, { "policy/" , policy_tests }, { "status/" , status_tests }, + { "routerset/" , routerset_tests }, END_OF_GROUPS }; @@ -1370,6 +1382,7 @@ main(int c, const char **v) options = options_new(); tor_threads_init(); init_logging(); + configure_backtrace_handler(get_version()); for (i_out = i = 1; i < c; ++i) { if (!strcmp(v[i], "--warn")) { diff --git a/src/test/test_bt_cl.c b/src/test/test_bt_cl.c index 45ae82fb85..720ccd4627 100644 --- a/src/test/test_bt_cl.c +++ b/src/test/test_bt_cl.c @@ -30,7 +30,12 @@ int crash(int x) { if (crashtype == 0) { +#if defined(__clang_analyzer__) || defined(__COVERITY__) + tor_assert(1 == 0); /* Avert your eyes, clangalyzer and coverity! You + * don't need to see us dereference NULL. */ +#else *(volatile int *)0 = 0; +#endif } else if (crashtype == 1) { tor_assert(1 == 0); } else if (crashtype == -1) { diff --git a/src/test/test_circuitlist.c b/src/test/test_circuitlist.c index b19edd1fd4..53dcab3302 100644 --- a/src/test/test_circuitlist.c +++ b/src/test/test_circuitlist.c @@ -79,9 +79,13 @@ test_clist_maps(void *arg) memset(&cam, 0, sizeof(cam)); memset(&cdm, 0, sizeof(cdm)); - ch1->cmux = (void*)0x1001; - ch2->cmux = (void*)0x1002; - ch3->cmux = (void*)0x1003; + tt_assert(ch1); + tt_assert(ch2); + tt_assert(ch3); + + ch1->cmux = tor_malloc(1); + ch2->cmux = tor_malloc(1); + ch3->cmux = tor_malloc(1); or_c1 = or_circuit_new(100, ch2); tt_assert(or_c1); @@ -156,6 +160,12 @@ test_clist_maps(void *arg) circuit_free(TO_CIRCUIT(or_c1)); if (or_c2) circuit_free(TO_CIRCUIT(or_c2)); + if (ch1) + tor_free(ch1->cmux); + if (ch2) + tor_free(ch2->cmux); + if (ch3) + tor_free(ch3->cmux); tor_free(ch1); tor_free(ch2); tor_free(ch3); diff --git a/src/test/test_config.c b/src/test/test_config.c index 94ac4dca13..b35984f761 100644 --- a/src/test/test_config.c +++ b/src/test/test_config.c @@ -184,7 +184,7 @@ is_private_dir(const char* path) if (r) { return 0; } -#if !defined (_WIN32) || defined (WINCE) +#if !defined (_WIN32) if ((st.st_mode & (S_IFDIR | 0777)) != (S_IFDIR | 0700)) { return 0; } @@ -201,7 +201,7 @@ test_config_check_or_create_data_subdir(void *arg) char *subpath; struct stat st; int r; -#if !defined (_WIN32) || defined (WINCE) +#if !defined (_WIN32) unsigned group_permission; #endif (void)arg; @@ -210,7 +210,7 @@ test_config_check_or_create_data_subdir(void *arg) datadir = options->DataDirectory = tor_strdup(get_fname("datadir-0")); subpath = get_datadir_fname(subdir); -#if defined (_WIN32) && !defined (WINCE) +#if defined (_WIN32) tt_int_op(mkdir(options->DataDirectory), ==, 0); #else tt_int_op(mkdir(options->DataDirectory, 0700), ==, 0); @@ -233,7 +233,7 @@ test_config_check_or_create_data_subdir(void *arg) tt_abort_perror("stat"); } -#if !defined (_WIN32) || defined (WINCE) +#if !defined (_WIN32) group_permission = st.st_mode | 0070; r = chmod(subpath, group_permission); @@ -284,7 +284,7 @@ test_config_write_to_data_subdir(void *arg) datadir = options->DataDirectory = tor_strdup(get_fname("datadir-1")); filepath = get_datadir_fname2(subdir, fname); -#if defined (_WIN32) && !defined (WINCE) +#if defined (_WIN32) tt_int_op(mkdir(options->DataDirectory), ==, 0); #else tt_int_op(mkdir(options->DataDirectory, 0700), ==, 0); diff --git a/src/test/test_containers.c b/src/test/test_containers.c index 067c4c1907..a9f5e727f4 100644 --- a/src/test/test_containers.c +++ b/src/test/test_containers.c @@ -40,38 +40,54 @@ static void test_container_smartlist_basic(void) { smartlist_t *sl; + char *v0 = tor_strdup("v0"); + char *v1 = tor_strdup("v1"); + char *v2 = tor_strdup("v2"); + char *v3 = tor_strdup("v3"); + char *v4 = tor_strdup("v4"); + char *v22 = tor_strdup("v22"); + char *v99 = tor_strdup("v99"); + char *v555 = tor_strdup("v555"); /* XXXX test sort_digests, uniq_strings, uniq_digests */ /* Test smartlist add, del_keeporder, insert, get. */ sl = smartlist_new(); - smartlist_add(sl, (void*)1); - smartlist_add(sl, (void*)2); - smartlist_add(sl, (void*)3); - smartlist_add(sl, (void*)4); + smartlist_add(sl, v1); + smartlist_add(sl, v2); + smartlist_add(sl, v3); + smartlist_add(sl, v4); smartlist_del_keeporder(sl, 1); - smartlist_insert(sl, 1, (void*)22); - smartlist_insert(sl, 0, (void*)0); - smartlist_insert(sl, 5, (void*)555); - test_eq_ptr((void*)0, smartlist_get(sl,0)); - test_eq_ptr((void*)1, smartlist_get(sl,1)); - test_eq_ptr((void*)22, smartlist_get(sl,2)); - test_eq_ptr((void*)3, smartlist_get(sl,3)); - test_eq_ptr((void*)4, smartlist_get(sl,4)); - test_eq_ptr((void*)555, smartlist_get(sl,5)); + smartlist_insert(sl, 1, v22); + smartlist_insert(sl, 0, v0); + smartlist_insert(sl, 5, v555); + test_eq_ptr(v0, smartlist_get(sl,0)); + test_eq_ptr(v1, smartlist_get(sl,1)); + test_eq_ptr(v22, smartlist_get(sl,2)); + test_eq_ptr(v3, smartlist_get(sl,3)); + test_eq_ptr(v4, smartlist_get(sl,4)); + test_eq_ptr(v555, smartlist_get(sl,5)); /* Try deleting in the middle. */ smartlist_del(sl, 1); - test_eq_ptr((void*)555, smartlist_get(sl, 1)); + test_eq_ptr(v555, smartlist_get(sl, 1)); /* Try deleting at the end. */ smartlist_del(sl, 4); test_eq(4, smartlist_len(sl)); /* test isin. */ - test_assert(smartlist_contains(sl, (void*)3)); - test_assert(!smartlist_contains(sl, (void*)99)); + test_assert(smartlist_contains(sl, v3)); + test_assert(!smartlist_contains(sl, v99)); done: smartlist_free(sl); + tor_free(v0); + tor_free(v1); + tor_free(v2); + tor_free(v3); + tor_free(v4); + tor_free(v22); + tor_free(v99); + tor_free(v555); } /** Run unit tests for smartlist-of-strings functionality. */ @@ -717,36 +733,44 @@ test_container_strmap(void) void *v; char *visited = NULL; smartlist_t *found_keys = NULL; + char *v1 = tor_strdup("v1"); + char *v99 = tor_strdup("v99"); + char *v100 = tor_strdup("v100"); + char *v101 = tor_strdup("v101"); + char *v102 = tor_strdup("v102"); + char *v103 = tor_strdup("v103"); + char *v104 = tor_strdup("v104"); + char *v105 = tor_strdup("v105"); map = strmap_new(); test_assert(map); test_eq(strmap_size(map), 0); test_assert(strmap_isempty(map)); - v = strmap_set(map, "K1", (void*)99); + v = strmap_set(map, "K1", v99); test_eq_ptr(v, NULL); test_assert(!strmap_isempty(map)); - v = strmap_set(map, "K2", (void*)101); + v = strmap_set(map, "K2", v101); test_eq_ptr(v, NULL); - v = strmap_set(map, "K1", (void*)100); - test_eq_ptr(v, (void*)99); - test_eq_ptr(strmap_get(map,"K1"), (void*)100); - test_eq_ptr(strmap_get(map,"K2"), (void*)101); + v = strmap_set(map, "K1", v100); + test_eq_ptr(v, v99); + test_eq_ptr(strmap_get(map,"K1"), v100); + test_eq_ptr(strmap_get(map,"K2"), v101); test_eq_ptr(strmap_get(map,"K-not-there"), NULL); strmap_assert_ok(map); v = strmap_remove(map,"K2"); strmap_assert_ok(map); - test_eq_ptr(v, (void*)101); + test_eq_ptr(v, v101); test_eq_ptr(strmap_get(map,"K2"), NULL); test_eq_ptr(strmap_remove(map,"K2"), NULL); - strmap_set(map, "K2", (void*)101); - strmap_set(map, "K3", (void*)102); - strmap_set(map, "K4", (void*)103); + strmap_set(map, "K2", v101); + strmap_set(map, "K3", v102); + strmap_set(map, "K4", v103); test_eq(strmap_size(map), 4); strmap_assert_ok(map); - strmap_set(map, "K5", (void*)104); - strmap_set(map, "K6", (void*)105); + strmap_set(map, "K5", v104); + strmap_set(map, "K6", v105); strmap_assert_ok(map); /* Test iterator. */ @@ -766,7 +790,7 @@ test_container_strmap(void) /* Make sure we removed K2, but not the others. */ test_eq_ptr(strmap_get(map, "K2"), NULL); - test_eq_ptr(strmap_get(map, "K5"), (void*)104); + test_eq_ptr(strmap_get(map, "K5"), v104); /* Make sure we visited everyone once */ smartlist_sort_strings(found_keys); visited = smartlist_join_strings(found_keys, ":", 0, NULL); @@ -779,12 +803,12 @@ test_container_strmap(void) /* Now try some lc functions. */ map = strmap_new(); - strmap_set_lc(map,"Ab.C", (void*)1); - test_eq_ptr(strmap_get(map,"ab.c"), (void*)1); + strmap_set_lc(map,"Ab.C", v1); + test_eq_ptr(strmap_get(map,"ab.c"), v1); strmap_assert_ok(map); - test_eq_ptr(strmap_get_lc(map,"AB.C"), (void*)1); + test_eq_ptr(strmap_get_lc(map,"AB.C"), v1); test_eq_ptr(strmap_get(map,"AB.C"), NULL); - test_eq_ptr(strmap_remove_lc(map,"aB.C"), (void*)1); + test_eq_ptr(strmap_remove_lc(map,"aB.C"), v1); strmap_assert_ok(map); test_eq_ptr(strmap_get_lc(map,"AB.C"), NULL); @@ -796,6 +820,14 @@ test_container_strmap(void) smartlist_free(found_keys); } tor_free(visited); + tor_free(v1); + tor_free(v99); + tor_free(v100); + tor_free(v101); + tor_free(v102); + tor_free(v103); + tor_free(v104); + tor_free(v105); } /** Run unit tests for getting the median of a list. */ @@ -881,6 +913,13 @@ test_container_fp_pair_map(void) void *v; fp_pair_map_iter_t *iter; fp_pair_t k; + char *v99 = tor_strdup("99"); + char *v100 = tor_strdup("v100"); + char *v101 = tor_strdup("v101"); + char *v102 = tor_strdup("v102"); + char *v103 = tor_strdup("v103"); + char *v104 = tor_strdup("v104"); + char *v105 = tor_strdup("v105"); map = fp_pair_map_new(); test_assert(map); @@ -900,31 +939,31 @@ test_container_fp_pair_map(void) memset(fp6.first, 0x61, DIGEST_LEN); memset(fp6.second, 0x62, DIGEST_LEN); - v = fp_pair_map_set(map, &fp1, (void*)99); + v = fp_pair_map_set(map, &fp1, v99); tt_ptr_op(v, ==, NULL); test_assert(!fp_pair_map_isempty(map)); - v = fp_pair_map_set(map, &fp2, (void*)101); + v = fp_pair_map_set(map, &fp2, v101); tt_ptr_op(v, ==, NULL); - v = fp_pair_map_set(map, &fp1, (void*)100); - tt_ptr_op(v, ==, (void*)99); - test_eq_ptr(fp_pair_map_get(map, &fp1), (void*)100); - test_eq_ptr(fp_pair_map_get(map, &fp2), (void*)101); + v = fp_pair_map_set(map, &fp1, v100); + tt_ptr_op(v, ==, v99); + test_eq_ptr(fp_pair_map_get(map, &fp1), v100); + test_eq_ptr(fp_pair_map_get(map, &fp2), v101); test_eq_ptr(fp_pair_map_get(map, &fp3), NULL); fp_pair_map_assert_ok(map); v = fp_pair_map_remove(map, &fp2); fp_pair_map_assert_ok(map); - test_eq_ptr(v, (void*)101); + test_eq_ptr(v, v101); test_eq_ptr(fp_pair_map_get(map, &fp2), NULL); test_eq_ptr(fp_pair_map_remove(map, &fp2), NULL); - fp_pair_map_set(map, &fp2, (void*)101); - fp_pair_map_set(map, &fp3, (void*)102); - fp_pair_map_set(map, &fp4, (void*)103); + fp_pair_map_set(map, &fp2, v101); + fp_pair_map_set(map, &fp3, v102); + fp_pair_map_set(map, &fp4, v103); test_eq(fp_pair_map_size(map), 4); fp_pair_map_assert_ok(map); - fp_pair_map_set(map, &fp5, (void*)104); - fp_pair_map_set(map, &fp6, (void*)105); + fp_pair_map_set(map, &fp5, v104); + fp_pair_map_set(map, &fp6, v105); fp_pair_map_assert_ok(map); /* Test iterator. */ @@ -942,7 +981,7 @@ test_container_fp_pair_map(void) /* Make sure we removed fp2, but not the others. */ test_eq_ptr(fp_pair_map_get(map, &fp2), NULL); - test_eq_ptr(fp_pair_map_get(map, &fp5), (void*)104); + test_eq_ptr(fp_pair_map_get(map, &fp5), v104); fp_pair_map_assert_ok(map); /* Clean up after ourselves. */ @@ -952,6 +991,13 @@ test_container_fp_pair_map(void) done: if (map) fp_pair_map_free(map, NULL); + tor_free(v99); + tor_free(v100); + tor_free(v101); + tor_free(v102); + tor_free(v103); + tor_free(v104); + tor_free(v105); } #define CONTAINER_LEGACY(name) \ diff --git a/src/test/test_descriptors.inc b/src/test/test_descriptors.inc new file mode 100644 index 0000000000..ecbccbd43a --- /dev/null +++ b/src/test/test_descriptors.inc @@ -0,0 +1,305 @@ +const char TEST_DESCRIPTORS[] = +"@uploaded-at 2014-06-08 19:20:11\n" +"@source \"127.0.0.1\"\n" +"router test000a 127.0.0.1 5000 0 7000\n" +"platform Tor 0.2.5.3-alpha-dev on Linux\n" +"protocols Link 1 2 Circuit 1\n" +"published 2014-06-08 19:20:11\n" +"fingerprint C7E7 CCB8 179F 8CC3 7F5C 8A04 2B3A 180B 934B 14BA\n" +"uptime 0\n" +"bandwidth 1073741824 1073741824 0\n" +"extra-info-digest 67A152A4C7686FB07664F872620635F194D76D95\n" +"caches-extra-info\n" +"onion-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBAOuBUIEBARMkkka/TGyaQNgUEDLP0KG7sy6KNQTNOlZHUresPr/vlVjo\n" +"HPpLMfu9M2z18c51YX/muWwY9x4MyQooD56wI4+AqXQcJRwQfQlPn3Ay82uZViA9\n" +"DpBajRieLlKKkl145KjArpD7F5BVsqccvjErgFYXvhhjSrx7BVLnAgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"signing-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBAN6NLnSxWQnFXxqZi5D3b0BMgV6y9NJLGjYQVP+eWtPZWgqyv4zeYsqv\n" +"O9y6c5lvxyUxmNHfoAbe/s8f2Vf3/YaC17asAVSln4ktrr3e9iY74a9RMWHv1Gzk\n" +"3042nMcqj3PEhRN0PoLkcOZNjjmNbaqki6qy9bWWZDNTdo+uI44dAgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"hidden-service-dir\n" +"contact auth0@test.test\n" +"ntor-onion-key pK4bs08ERYN591jj7ca17Rn9Q02TIEfhnjR6hSq+fhU=\n" +"reject *:*\n" +"router-signature\n" +"-----BEGIN SIGNATURE-----\n" +"rx88DuM3Y7tODlHNDDEVzKpwh3csaG1or+T4l2Xs1oq3iHHyPEtB6QTLYrC60trG\n" +"aAPsj3DEowGfjga1b248g2dtic8Ab+0exfjMm1RHXfDam5TXXZU3A0wMyoHjqHuf\n" +"eChGPgFNUvEc+5YtD27qEDcUjcinYztTs7/dzxBT4PE=\n" +"-----END SIGNATURE-----\n" +"@uploaded-at 2014-06-08 19:20:11\n" +"@source \"127.0.0.1\"\n" +"router test001a 127.0.0.1 5001 0 7001\n" +"platform Tor 0.2.5.3-alpha-dev on Linux\n" +"protocols Link 1 2 Circuit 1\n" +"published 2014-06-08 19:20:11\n" +"fingerprint 35DA 711C FC62 F88B C243 DE32 DC0B C28A 3F62 2610\n" +"uptime 0\n" +"bandwidth 1073741824 1073741824 0\n" +"extra-info-digest 9E12278D6CF7608071FE98CE9DCEE48FA264518A\n" +"caches-extra-info\n" +"onion-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBAPbyUrorqoXMW4oezqd307ZGxgobqvQs2nb3TdQyWrwsHtJmS3utdrJS\n" +"xJUZPNHOQ2hrDWW1VvevYqRTGeXGZr9TDZ3+t/gVUttqYRhuzzgEKVAZSsTo5ctO\n" +"QNHnzJ6Xx/w/trhWqPTeJ7R0TCyAbWW7aE3KaKdwvZilRZp/oRUnAgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"signing-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBALwOJ7XZHBnjJEuwF3Os6eashNbTH9YnH8TBZBdKgu3iFJYqDslcMIPX\n" +"gWCJ9apPHyh1+/8OLRWeEYlwoZzgGi0rjm/+BNeOOmJbjfyjk97DuB9/2O5zr1BM\n" +"CvOHqQSzMD+vz1ebvfM039a2mO8lXruUFPZQaFVxk8371XP2khqhAgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"hidden-service-dir\n" +"contact auth1@test.test\n" +"ntor-onion-key t5bI1ksTdigOksMKRHUDwx/34ajEvDN1IpArOxIEWgk=\n" +"reject *:*\n" +"router-signature\n" +"-----BEGIN SIGNATURE-----\n" +"KtMW7A/pzu+np6aKJSy6d7drIb4yjz8SPCo+oQNxj2IqNHJir2O2nWu69xy+K0c1\n" +"RL05KkcDaYzr5hC80FD1H+sTpGYD28SPkQkzPw+0pReSDl93pVXh0rU6Cdcm75FC\n" +"t0UZzDt4TsMuFB0ZYpM3phKcQPpiDG6aR0LskL/YUvY=\n" +"-----END SIGNATURE-----\n" +"@uploaded-at 2014-06-08 19:20:11\n" +"@source \"127.0.0.1\"\n" +"router test004r 127.0.0.1 5004 0 7004\n" +"platform Tor 0.2.5.3-alpha-dev on Linux\n" +"protocols Link 1 2 Circuit 1\n" +"published 2014-06-08 19:20:10\n" +"fingerprint CC6A 48BD 52BD 9A2C 6670 5863 AC31 AE17 6E63 8B02\n" +"uptime 0\n" +"bandwidth 1073741824 1073741824 0\n" +"extra-info-digest B5CC249CEF394B5AFCA0C77FA7D5605615FA487C\n" +"onion-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBAMze36Hupy7HACcF3TMv5mJuZbx3d3cS0WYLl6vTeChBgpS5CEXq6zIu\n" +"d31YmtUcxH6fOjDOudhbnXuoh1nH4CP+LocVHAdlGG1giAm7u8yZudVvVJiIqFgQ\n" +"wVDcWx8LbGCi5P9J/ZPKAIVsSyS7xkOqHjz3VMo/uYLbQCFAwfkdAgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"signing-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBAM/qGP365x6bH+ug7rKVy7V5lC9Ff2Jfk0wlTFIzzwn+DMSG6xDvulKe\n" +"wcIzgGNdQu7qlKlQUif3GPMr0KSS32cRsmoRQJcsm9+lGUK871NyZ8AyrHT+LhyF\n" +"cs718P0iN5yKF2FikNr727kEANCzvC1l9eP4qF5GGzsNtglbJ7bTAgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"hidden-service-dir\n" +"ntor-onion-key a9Pavqnx7DFhMWUO0d17qF9Py8+iie4FnxTHaTgfIXY=\n" +"reject *:25\n" +"reject *:119\n" +"reject *:135-139\n" +"reject *:445\n" +"reject *:563\n" +"reject *:1214\n" +"reject *:4661-4666\n" +"reject *:6346-6429\n" +"reject *:6699\n" +"reject *:6881-6999\n" +"accept *:*\n" +"router-signature\n" +"-----BEGIN SIGNATURE-----\n" +"HVW7kjBgEt+Qdvcrq+NQE1F9B8uV9D38KA2Bp6cYHLWCxL6N4GS8JQqbOEtnqaj7\n" +"Vxrv7uy1Fzb15Zr+1sUVMxNv+LLRfr+JzfETMNYVkYDrNgr1cAAVEQzFWbIziond\n" +"xMFp64yjEW9/I+82lb5GBZEiKdEd4QqWMmQosoYMTM8=\n" +"-----END SIGNATURE-----\n" +"@uploaded-at 2014-06-08 19:20:12\n" +"@source \"127.0.0.1\"\n" +"router test002a 127.0.0.1 5002 0 7002\n" +"platform Tor 0.2.5.3-alpha-dev on Linux\n" +"protocols Link 1 2 Circuit 1\n" +"published 2014-06-08 19:20:11\n" +"fingerprint 29C7 BBB6 C437 32D5 BDF1 5671 F5C5 F1FB 6E36 4B47\n" +"uptime 0\n" +"bandwidth 1073741824 1073741824 0\n" +"extra-info-digest 9BB181EA86E0130680C3CC04AD7DE4C341ADC2C7\n" +"caches-extra-info\n" +"onion-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBALNH19oF8Ajf+djlH/g7L+enFBf5Wwjmf3bPwNKWZ9G+B+Lg8SpfhZiw\n" +"rUqi7h21f45BV/dN05dK6leWD8rj1T9kuM9TKBOEZxIWeq7zbXihyu4XPxP4FNTS\n" +"+0G7BhdP4biALENmeyLhUCZaw5Ic/jFkHT4gV9S0iVZiEDwC9twXAgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"signing-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBALeyQGMQBHgTxpO/i30uHjflTm9MNi3ZBNcOKpvBXWYgY42qTqOZ7Uam\n" +"c5pmZhTLrQ1W8XlGDw8Cl8ktZ0ylodLZyUNajBtJvSFWTb8iwdZsshW6Ahb8TyfI\n" +"Y7MwTlQ/7xw4mj1NEaui6bwGgEZUs18RTqhDrUc2Mcj1Yf61Rq+7AgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"hidden-service-dir\n" +"contact auth2@test.test\n" +"ntor-onion-key ukR41RjtiZ69KO0SrFTvL0LoZK/ZTT01FQWmCXTCUlE=\n" +"reject *:*\n" +"router-signature\n" +"-----BEGIN SIGNATURE-----\n" +"IY2s/RY4tdahrgfGG+vW7lOvpfofoxxSo7guGpSKGxVApiroCQtumoYifnnJ88G2\n" +"K4IbxwEO8pgO8fnz1mibblUWw2vdDNjCifc1wtXJUE+ONA0UcLRlfQ94GbL8h2PG\n" +"72z6i1+NN0QahXMk7MUbzI7bOXTJOiO8e2Zjk9vRnxI=\n" +"-----END SIGNATURE-----\n" +"@uploaded-at 2014-06-08 19:20:12\n" +"@source \"127.0.0.1\"\n" +"router test006r 127.0.0.1 5006 0 7006\n" +"platform Tor 0.2.5.3-alpha-dev on Linux\n" +"protocols Link 1 2 Circuit 1\n" +"published 2014-06-08 19:20:11\n" +"fingerprint 829B 3FAA A42B 605A EB0B F380 8F32 8ED1 73E7 0D25\n" +"uptime 0\n" +"bandwidth 1073741824 1073741824 0\n" +"extra-info-digest 7ECB757002EB9B5838B13AE6F2357A5E585131B8\n" +"onion-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBALsNBChcLVndlS4HNXL3hxBJVgXctATz6yXcJt3bkDB5cjv7Q9fqN3Ue\n" +"j3SI1OUBx4YrLcSLD/hELHVilLrrfbaraAFfAsydlRLjTVcMRx5FFlDd0E7TAadc\n" +"71CkTipNnjwqz1mTRKkEFeepnh/JaFDidY9ER1rMBA5JRyBvqrD9AgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"signing-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBAPgipA8yLj1kqrMlAH7cK7IQEdmqmfNHGXdkYQ+TKtfLh0zeEIvvh9yh\n" +"k+vKHS+HVoHo3tecB9QjJyDyyJTiETXCupSOY+ebG648JADAvv8v1WiE+KBXtjpl\n" +"qgDTrDj5CwGuY6cvQdej5yg1UAVlMMZSg3thL3tCYtQbOq66lAlnAgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"hidden-service-dir\n" +"ntor-onion-key q02F3AQsCX7+zXNpfTqBF8O8lusPhRJpQVxOnBvbOwc=\n" +"reject *:25\n" +"reject *:119\n" +"reject *:135-139\n" +"reject *:445\n" +"reject *:563\n" +"reject *:1214\n" +"reject *:4661-4666\n" +"reject *:6346-6429\n" +"reject *:6699\n" +"reject *:6881-6999\n" +"accept *:*\n" +"router-signature\n" +"-----BEGIN SIGNATURE-----\n" +"L1fdgoN/eXgdzIIXO63W4yGoC9lRozMU+T0Fimhd/XFV8qxeUT83Vgf63vxLUHIb\n" +"D4a80Wj7Pm4y5a766qLGXxlz2FYjCdkp070UpgZneB+VifUlFd/bNAjsiYTstBKM\n" +"EI2L0mhl9d/7KK8vgtadHdX1z1u7QjyF6ccnzhfqeiY=\n" +"-----END SIGNATURE-----\n" +"@uploaded-at 2014-06-08 19:20:12\n" +"@source \"127.0.0.1\"\n" +"router test003r 127.0.0.1 5003 0 7003\n" +"platform Tor 0.2.5.3-alpha-dev on Linux\n" +"protocols Link 1 2 Circuit 1\n" +"published 2014-06-08 19:20:11\n" +"fingerprint 71FD 3A35 F705 8020 D595 B711 D52A 9A0A 99BB B467\n" +"uptime 0\n" +"bandwidth 1073741824 1073741824 0\n" +"extra-info-digest 3796BE0A95B699595445DFD3453CA2074E75BCE8\n" +"onion-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBAL44ctIioIfCYFzMTYNfK5qFAPGGUpsAFmS8pThQEY/tJU14+frJDBrC\n" +"BkLvBs05Bw7xOUb0f2geiYGowBA6028smiq5HzTO7Kaga8vfV7AnANPX+n9cfHCr\n" +"/2cMnKkT/GZzpdk0WbUw5Kc/G1ATIPFQHA8gZAi1fsSIDDn3GRV5AgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"signing-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBALlPo5AI1mVTi+194yOSf40caoFlxSTfXt8KjGVa1dO/bpX7L3noOjYg\n" +"goU4Aqim7BHmBWQDE/tZNTrchFoLQFHi9N4pv/0ND3sY904pzqGpe3FeTuU8P9Jg\n" +"q2w3MeO3GwG8CJf4FOdSkgi8UKkJhOld4g4kViQbrFLXfdFvnT/zAgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"hidden-service-dir\n" +"ntor-onion-key qluYCRrsesOTkavCLnNK6H1ToywyDquCyYeP0h/qol4=\n" +"reject *:25\n" +"reject *:119\n" +"reject *:135-139\n" +"reject *:445\n" +"reject *:563\n" +"reject *:1214\n" +"reject *:4661-4666\n" +"reject *:6346-6429\n" +"reject *:6699\n" +"reject *:6881-6999\n" +"accept *:*\n" +"router-signature\n" +"-----BEGIN SIGNATURE-----\n" +"d09K7rW/OpVzoUpfZXJuJW7a+P4pROCOZTgvDUIy/Nv+EAjcYqv95PlJ8cAMqnn3\n" +"1oQibRmmQwn0OmG5cB8NaZiueaVIRheGzHEM8rndpHn5oFXdFvV7KKjScvfuBbTk\n" +"RYME8XyawRaqsEZnwirDDlZuiZOjdQs8bbGsko3grJE=\n" +"-----END SIGNATURE-----\n" +"@uploaded-at 2014-06-08 19:20:12\n" +"@source \"127.0.0.1\"\n" +"router test005r 127.0.0.1 5005 0 7005\n" +"platform Tor 0.2.5.3-alpha-dev on Linux\n" +"protocols Link 1 2 Circuit 1\n" +"published 2014-06-08 19:20:11\n" +"fingerprint EB6E 42ED E6BF 5EE0 19F5 EFC1 53AD 094C 1327 7B76\n" +"uptime 0\n" +"bandwidth 1073741824 1073741824 0\n" +"extra-info-digest C031EE4E1AE826C1E3C4E21D81C961869E63F5D2\n" +"onion-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBAMd9Fm4KTSjFDzEABPZ1fwBCC2DNgee6nAmlde8FRbCVfcIHRiJyv9YG\n" +"h530yUJal3hBfiWwy/SBA4LDz1flNCEwJm81s3waj4T9c676dAOLPcnOcJM5SbaQ\n" +"hYPDrIZLEZHAk+IoM+avKYYocwCJXwx6WTtsedF0wJBZ9mQAJERJAgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"signing-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBAKT7ldhV43S1CgoER/pU0Rigf0NzcSy25DQJrMRQnNmXnL03Dwuv/Iu7\n" +"dCjgg64odnvSkXHFhkbjGcg8aXikvfbMyZTbsD8NrrP6FS6pfgPgZD9W2TK7QdHI\n" +"QXwx1IYaaJK4nDUNfJhjrclydEdxmHbO1nLG1aS0ypn/G0EBpOSnAgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"hidden-service-dir\n" +"ntor-onion-key umFmyRPA0dIsi0CFYCbGIPe2+OUkyslTkKKDEohjQQg=\n" +"reject *:25\n" +"reject *:119\n" +"reject *:135-139\n" +"reject *:445\n" +"reject *:563\n" +"reject *:1214\n" +"reject *:4661-4666\n" +"reject *:6346-6429\n" +"reject *:6699\n" +"reject *:6881-6999\n" +"accept *:*\n" +"router-signature\n" +"-----BEGIN SIGNATURE-----\n" +"JiXEbqPgDPWEb9DzCYINRXfmvMIc/IRtvshS8Vmmn7DW67TrTLKCEAnisGo92gMA\n" +"bhxGb9G5Mxq/8YqGoqdI2Vp6tfKlz/9AmjHzFAo01y42gafXIdr1oUS2RimA8jfF\n" +"hwfQkbG0FYEsJrH3EUa8sMhcjsEaohK/kgklMR7OgQY=\n" +"-----END SIGNATURE-----\n" +"@uploaded-at 2014-06-08 19:20:12\n" +"@source \"127.0.0.1\"\n" +"router test007r 127.0.0.1 5007 0 7007\n" +"platform Tor 0.2.5.3-alpha-dev on Linux\n" +"protocols Link 1 2 Circuit 1\n" +"published 2014-06-08 19:20:11\n" +"fingerprint DABD 2AAF 8C9F 3B71 7839 9C08 DCD8 CD9D 341D 0002\n" +"uptime 0\n" +"bandwidth 1073741824 1073741824 0\n" +"extra-info-digest F80104A0DFFB4EB429325D41D1F71E5BF8C6C726\n" +"onion-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBAL42fYAriR/JeB/9NpVq5Y5EEHca+ugIpaSdRfbopWDtFjXLEk2jmO5A\n" +"KoAGIkTKDr7e9101x63H+0Nh/7w3uYs/WqTXEH8/1sHwe+0PY2HL0S6qhlOo6X54\n" +"EfK0nDDBAWFOpyiAMHRk8JVikKb56+FVIhCJgi1RIbLIiUQK2/kxAgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"signing-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBAKQj2U5hmB68V6NQBqD8DfIkJjovvM8t6nGfYpkT8ORsROnmgI5mjM38\n" +"cmh5GIjY9RgoOWolLmsWQ4SXtS0FvrPft1M61UMTSHzlrEeuod5KenV7vGlX2TxT\n" +"0DoA5TL9yY7CmxCk8CNRCtN/g7WocgIiP4KCIiEZ4VE6LIb6sxUnAgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"hidden-service-dir\n" +"ntor-onion-key 1UBS8rTlL39u9YxRJWhz+GTG1dS15VRi4au1i5qZOyI=\n" +"reject *:25\n" +"reject *:119\n" +"reject *:135-139\n" +"reject *:445\n" +"reject *:563\n" +"reject *:1214\n" +"reject *:4661-4666\n" +"reject *:6346-6429\n" +"reject *:6699\n" +"reject *:6881-6999\n" +"accept *:*\n" +"router-signature\n" +"-----BEGIN SIGNATURE-----\n" +"m7xHh+XPdLN+qcMLz1dBAEAmcdCFrtdseMHCc0FyAP2kXdayxqe3o2IOOHN++bTH\n" +"Y5iHsZembsIJJ+D/d0YEKWKh42TUWCXBu0Gbfc4OcNuR6PFlTWO2wk7rDT3HOiFr\n" +"pe3wJqZYkLxlBDamROAlMMRe71iag89H/4EulC18opw=\n" +"-----END SIGNATURE-----\n"; diff --git a/src/test/test_dir.c b/src/test/test_dir.c index c03b63be27..71b474d493 100644 --- a/src/test/test_dir.c +++ b/src/test/test_dir.c @@ -736,10 +736,6 @@ test_dir_param_voting(void) /* Do the first tests without adding all the other votes, for * networks without many dirauths. */ - res = dirvote_compute_params(votes, 11, 6); - test_streq(res, "ab=90 abcd=20 cw=50 x-yz=-99"); - tor_free(res); - res = dirvote_compute_params(votes, 12, 2); test_streq(res, ""); tor_free(res); @@ -750,10 +746,6 @@ test_dir_param_voting(void) smartlist_add(votes, &vote2); - res = dirvote_compute_params(votes, 11, 2); - test_streq(res, "ab=27 abcd=20 cw=5 x-yz=-99"); - tor_free(res); - res = dirvote_compute_params(votes, 12, 2); test_streq(res, "ab=27 cw=5 x-yz=-99"); tor_free(res); @@ -768,10 +760,6 @@ test_dir_param_voting(void) smartlist_add(votes, &vote3); - res = dirvote_compute_params(votes, 11, 3); - test_streq(res, "ab=27 abcd=20 c=60 cw=50 x-yz=-9 zzzzz=101"); - tor_free(res); - res = dirvote_compute_params(votes, 12, 3); test_streq(res, "ab=27 abcd=20 cw=50 x-yz=-9"); tor_free(res); @@ -786,10 +774,6 @@ test_dir_param_voting(void) smartlist_add(votes, &vote4); - res = dirvote_compute_params(votes, 11, 4); - test_streq(res, "ab=90 abcd=20 c=1 cw=50 x-yz=-9 zzzzz=101"); - tor_free(res); - res = dirvote_compute_params(votes, 12, 4); test_streq(res, "ab=90 abcd=20 cw=50 x-yz=-9"); tor_free(res); diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c new file mode 100644 index 0000000000..fab82c3446 --- /dev/null +++ b/src/test/test_entrynodes.c @@ -0,0 +1,727 @@ +/* Copyright (c) 2014, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "orconfig.h" + +#define STATEFILE_PRIVATE +#define ENTRYNODES_PRIVATE +#define ROUTERLIST_PRIVATE + +#include "or.h" +#include "test.h" +#include "entrynodes.h" +#include "routerparse.h" +#include "nodelist.h" +#include "util.h" +#include "routerlist.h" +#include "routerset.h" +#include "statefile.h" +#include "config.h" + +#include "test_descriptors.inc" + +/* TODO: + * choose_random_entry() test with state set. + * + * parse_state() tests with more than one guards. + * + * More tests for set_from_config(): Multiple nodes, use fingerprints, + * use country codes. + */ + +/** Dummy Tor state used in unittests. */ +static or_state_t *dummy_state = NULL; +static or_state_t * +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, ==, NUMBER_OF_DESCRIPTORS); + + /* Sanity checking of routerlist and nodelist. */ + our_routerlist = router_get_routerlist(); + tt_int_op(smartlist_len(our_routerlist->routers), ==, NUMBER_OF_DESCRIPTORS); + routerlist_assert_ok(our_routerlist); + + our_nodelist = nodelist_get_list(); + tt_int_op(smartlist_len(our_nodelist), ==, 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) +{ + (void) testcase; + (void) ptr; + + routerlist_free_all(); + nodelist_free_all(); + entry_guards_free_all(); + or_state_free(dummy_state); + + return 1; /* NOP */ +} + +/* Unittest setup function: Setup a fake network. */ +static void * +fake_network_setup(const struct testcase_t *testcase) +{ + (void) testcase; + + /* Setup fake state */ + dummy_state = tor_malloc_zero(sizeof(or_state_t)); + MOCK(get_or_state, + get_or_state_replacement); + + /* Setup fake routerlist. */ + setup_fake_routerlist(); + + /* Return anything but NULL (it's interpreted as test fail) */ + return dummy_state; +} + +/** Test choose_random_entry() with none of our routers being guard nodes. */ +static void +test_choose_random_entry_no_guards(void *arg) +{ + const node_t *chosen_entry = NULL; + + (void) arg; + + /* Try to pick an entry even though none of our routers are guards. */ + chosen_entry = choose_random_entry(NULL); + + /* Unintuitively, we actually pick a random node as our entry, + because router_choose_random_node() relaxes its constraints if it + can't find a proper entry guard. */ + test_assert(chosen_entry); + + done: + ; +} + +/** Test choose_random_entry() with only one of our routers being a + guard node. */ +static void +test_choose_random_entry_one_possible_guard(void *arg) +{ + const node_t *chosen_entry = NULL; + node_t *the_guard = NULL; + smartlist_t *our_nodelist = NULL; + + (void) arg; + + /* Set one of the nodes to be a guard. */ + our_nodelist = nodelist_get_list(); + the_guard = smartlist_get(our_nodelist, 4); /* chosen by fair dice roll */ + the_guard->is_possible_guard = 1; + + /* Pick an entry. Make sure we pick the node we marked as guard. */ + chosen_entry = choose_random_entry(NULL); + tt_ptr_op(chosen_entry, ==, the_guard); + + done: + ; +} + +/** Helper to conduct tests for populate_live_entry_guards(). + + This test adds some entry guards to our list, and then tests + populate_live_entry_guards() to mke sure it filters them correctly. + + <b>num_needed</b> is the number of guard nodes we support. It's + configurable to make sure we function properly with 1 or 3 guard + nodes configured. +*/ +static void +populate_live_entry_guards_test_helper(int num_needed) +{ + smartlist_t *our_nodelist = NULL; + smartlist_t *live_entry_guards = smartlist_new(); + const smartlist_t *all_entry_guards = get_entry_guards(); + or_options_t *options = get_options_mutable(); + int retval; + + /* Set NumEntryGuards to the provided number. */ + options->NumEntryGuards = num_needed; + tt_int_op(num_needed, ==, decide_num_guards(options, 0)); + + /* The global entry guards smartlist should be empty now. */ + tt_int_op(smartlist_len(all_entry_guards), ==, 0); + + /* Walk the nodelist and add all nodes as entry guards. */ + our_nodelist = nodelist_get_list(); + tt_int_op(smartlist_len(our_nodelist), ==, NUMBER_OF_DESCRIPTORS); + + SMARTLIST_FOREACH_BEGIN(our_nodelist, const node_t *, node) { + const node_t *node_tmp; + node_tmp = add_an_entry_guard(node, 0, 1, 0, 0); + test_assert(node_tmp); + } SMARTLIST_FOREACH_END(node); + + /* Make sure the nodes were added as entry guards. */ + tt_int_op(smartlist_len(all_entry_guards), ==, NUMBER_OF_DESCRIPTORS); + + /* Ensure that all the possible entry guards are enough to satisfy us. */ + tt_int_op(smartlist_len(all_entry_guards), >=, num_needed); + + /* Walk the entry guard list for some sanity checking */ + SMARTLIST_FOREACH_BEGIN(all_entry_guards, const entry_guard_t *, entry) { + /* Since we called add_an_entry_guard() with 'for_discovery' being + False, all guards should have made_contact enabled. */ + tt_int_op(entry->made_contact, ==, 1); + + /* Since we don't have a routerstatus, all of the entry guards are + not directory servers. */ + tt_int_op(entry->is_dir_cache, ==, 0); + } SMARTLIST_FOREACH_END(entry); + + /* First, try to get some fast guards. This should fail. */ + retval = populate_live_entry_guards(live_entry_guards, + all_entry_guards, + NULL, + NO_DIRINFO, /* Don't care about DIRINFO*/ + 0, 0, + 1); /* We want fast guard! */ + tt_int_op(retval, ==, 0); + tt_int_op(smartlist_len(live_entry_guards), ==, 0); + + /* Now try to get some stable guards. This should fail too. */ + retval = populate_live_entry_guards(live_entry_guards, + all_entry_guards, + NULL, + NO_DIRINFO, + 0, + 1, /* We want stable guard! */ + 0); + tt_int_op(retval, ==, 0); + tt_int_op(smartlist_len(live_entry_guards), ==, 0); + + /* Now try to get any guard we can find. This should succeed. */ + retval = populate_live_entry_guards(live_entry_guards, + all_entry_guards, + NULL, + NO_DIRINFO, + 0, 0, 0); /* No restrictions! */ + + /* Since we had more than enough guards in 'all_entry_guards', we + should have added 'num_needed' of them to live_entry_guards. + 'retval' should be 1 since we now have enough live entry guards + to pick one. */ + tt_int_op(retval, ==, 1); + tt_int_op(smartlist_len(live_entry_guards), ==, num_needed); + + done: + smartlist_free(live_entry_guards); +} + +/* Test populate_live_entry_guards() for 1 guard node. */ +static void +test_populate_live_entry_guards_1guard(void *arg) +{ + (void) arg; + + populate_live_entry_guards_test_helper(1); +} + +/* Test populate_live_entry_guards() for 3 guard nodes. */ +static void +test_populate_live_entry_guards_3guards(void *arg) +{ + (void) arg; + + populate_live_entry_guards_test_helper(3); +} + +/** Append some EntryGuard lines to the Tor state at <b>state</b>. + + <b>entry_guard_lines</b> is a smartlist containing 2-tuple + smartlists that carry the key and values of the statefile. + As an example: + entry_guard_lines = + (("EntryGuard", "name 67E72FF33D7D41BF11C569646A0A7B4B188340DF DirCache"), + ("EntryGuardDownSince", "2014-06-07 16:02:46 2014-06-07 16:02:46")) +*/ +static void +state_insert_entry_guard_helper(or_state_t *state, + smartlist_t *entry_guard_lines) +{ + config_line_t **next, *line; + + next = &state->EntryGuards; + *next = NULL; + + /* Loop over all the state lines in the smartlist */ + SMARTLIST_FOREACH_BEGIN(entry_guard_lines, const smartlist_t *,state_lines) { + /* Get key and value for each line */ + const char *state_key = smartlist_get(state_lines, 0); + const char *state_value = smartlist_get(state_lines, 1); + + *next = line = tor_malloc_zero(sizeof(config_line_t)); + line->key = tor_strdup(state_key); + tor_asprintf(&line->value, "%s", state_value); + next = &(line->next); + } SMARTLIST_FOREACH_END(state_lines); +} + +/** Free memory occupied by <b>entry_guard_lines</b>. */ +static void +state_lines_free(smartlist_t *entry_guard_lines) +{ + SMARTLIST_FOREACH_BEGIN(entry_guard_lines, smartlist_t *, state_lines) { + char *state_key = smartlist_get(state_lines, 0); + char *state_value = smartlist_get(state_lines, 1); + + tor_free(state_key); + tor_free(state_value); + smartlist_free(state_lines); + } SMARTLIST_FOREACH_END(state_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. +*/ +static void +test_entry_guards_parse_state_simple(void *arg) +{ + or_state_t *state = or_state_new(); + const smartlist_t *all_entry_guards = get_entry_guards(); + smartlist_t *entry_state_lines = smartlist_new(); + char *msg = NULL; + int retval; + + /* Details of our fake guard node */ + const char *nickname = "hagbard"; + const char *fpr = "B29D536DD1752D542E1FBB3C9CE4449D51298212"; + const char *tor_version = "0.2.5.3-alpha-dev"; + const char *added_at = get_yesterday_date_str(); + const char *unlisted_since = "2014-06-08 16:16:50"; + + (void) arg; + + /* The global entry guards smartlist should be empty now. */ + tt_int_op(smartlist_len(all_entry_guards), ==, 0); + + { /* Prepare the state entry */ + + /* Prepare the smartlist to hold the key/value of each line */ + smartlist_t *state_line = smartlist_new(); + smartlist_add_asprintf(state_line, "EntryGuard"); + smartlist_add_asprintf(state_line, "%s %s %s", nickname, fpr, "DirCache"); + smartlist_add(entry_state_lines, state_line); + + state_line = smartlist_new(); + smartlist_add_asprintf(state_line, "EntryGuardAddedBy"); + smartlist_add_asprintf(state_line, "%s %s %s", fpr, tor_version, added_at); + smartlist_add(entry_state_lines, state_line); + + state_line = smartlist_new(); + smartlist_add_asprintf(state_line, "EntryGuardUnlistedSince"); + smartlist_add_asprintf(state_line, "%s", unlisted_since); + smartlist_add(entry_state_lines, state_line); + } + + /* Inject our lines in the state */ + state_insert_entry_guard_helper(state, entry_state_lines); + + /* Parse state */ + retval = entry_guards_parse_state(state, 1, &msg); + tt_int_op(retval, >=, 0); + + /* Test that the guard was registered. + We need to re-get the entry guard list since its pointer was + overwritten in entry_guards_parse_state(). */ + all_entry_guards = get_entry_guards(); + tt_int_op(smartlist_len(all_entry_guards), ==, 1); + + { /* Test the entry guard structure */ + char hex_digest[1024]; + char str_time[1024]; + + const entry_guard_t *e = smartlist_get(all_entry_guards, 0); + tt_str_op(e->nickname, ==, nickname); /* Verify nickname */ + + base16_encode(hex_digest, sizeof(hex_digest), + e->identity, DIGEST_LEN); + tt_str_op(hex_digest, ==, fpr); /* Verify fingerprint */ + + tt_assert(e->is_dir_cache); /* Verify dirness */ + + tt_str_op(e->chosen_by_version, ==, tor_version); /* Verify tor version */ + + tt_assert(e->made_contact); /* All saved guards have been contacted */ + + tt_assert(e->bad_since); /* Verify bad_since timestamp */ + format_iso_time(str_time, e->bad_since); + tt_str_op(str_time, ==, unlisted_since); + + /* The rest should be unset */ + tt_assert(!e->unreachable_since); + tt_assert(!e->can_retry); + tt_assert(!e->path_bias_noticed); + tt_assert(!e->path_bias_warned); + tt_assert(!e->path_bias_extreme); + tt_assert(!e->path_bias_disabled); + tt_assert(!e->path_bias_use_noticed); + tt_assert(!e->path_bias_use_extreme); + tt_assert(!e->last_attempted); + } + + done: + state_lines_free(entry_state_lines); + or_state_free(state); + tor_free(msg); +} + +/** Similar to test_entry_guards_parse_state_simple() but aims to test + the PathBias-related details of the entry guard. */ +static void +test_entry_guards_parse_state_pathbias(void *arg) +{ + or_state_t *state = or_state_new(); + const smartlist_t *all_entry_guards = get_entry_guards(); + char *msg = NULL; + int retval; + smartlist_t *entry_state_lines = smartlist_new(); + + /* Path bias details of the fake guard */ + const double circ_attempts = 9; + const double circ_successes = 8; + const double successful_closed = 4; + const double collapsed = 2; + const double unusable = 0; + const double timeouts = 1; + + (void) arg; + + /* The global entry guards smartlist should be empty now. */ + tt_int_op(smartlist_len(all_entry_guards), ==, 0); + + { /* Prepare the state entry */ + + /* Prepare the smartlist to hold the key/value of each line */ + smartlist_t *state_line = smartlist_new(); + smartlist_add_asprintf(state_line, "EntryGuard"); + smartlist_add_asprintf(state_line, + "givethanks B29D536DD1752D542E1FBB3C9CE4449D51298212 NoDirCache"); + smartlist_add(entry_state_lines, state_line); + + state_line = smartlist_new(); + smartlist_add_asprintf(state_line, "EntryGuardAddedBy"); + smartlist_add_asprintf(state_line, + "B29D536DD1752D542E1FBB3C9CE4449D51298212 0.2.5.3-alpha-dev " + "%s", get_yesterday_date_str()); + smartlist_add(entry_state_lines, state_line); + + state_line = smartlist_new(); + smartlist_add_asprintf(state_line, "EntryGuardUnlistedSince"); + smartlist_add_asprintf(state_line, "2014-06-08 16:16:50"); + smartlist_add(entry_state_lines, state_line); + + state_line = smartlist_new(); + smartlist_add_asprintf(state_line, "EntryGuardPathBias"); + smartlist_add_asprintf(state_line, "%f %f %f %f %f %f", + circ_attempts, circ_successes, successful_closed, + collapsed, unusable, timeouts); + smartlist_add(entry_state_lines, state_line); + } + + /* Inject our lines in the state */ + state_insert_entry_guard_helper(state, entry_state_lines); + + /* Parse state */ + retval = entry_guards_parse_state(state, 1, &msg); + tt_int_op(retval, >=, 0); + + /* Test that the guard was registered */ + all_entry_guards = get_entry_guards(); + tt_int_op(smartlist_len(all_entry_guards), ==, 1); + + { /* Test the path bias of this guard */ + const entry_guard_t *e = smartlist_get(all_entry_guards, 0); + + tt_assert(!e->is_dir_cache); + tt_assert(!e->can_retry); + + /* XXX tt_double_op doesn't support equality. Cast to int for now. */ + tt_int_op((int)e->circ_attempts, ==, (int)circ_attempts); + tt_int_op((int)e->circ_successes, ==, (int)circ_successes); + tt_int_op((int)e->successful_circuits_closed, ==, (int)successful_closed); + tt_int_op((int)e->timeouts, ==, (int)timeouts); + tt_int_op((int)e->collapsed_circuits, ==, (int)collapsed); + tt_int_op((int)e->unusable_circuits, ==, (int)unusable); + } + + done: + or_state_free(state); + state_lines_free(entry_state_lines); + tor_free(msg); +} + +/* Simple test of entry_guards_set_from_config() by specifying a + particular EntryNode and making sure it gets picked. */ +static void +test_entry_guards_set_from_config(void *arg) +{ + or_options_t *options = get_options_mutable(); + const smartlist_t *all_entry_guards = get_entry_guards(); + const char *entrynodes_str = "test003r"; + const node_t *chosen_entry = NULL; + int retval; + + (void) arg; + + /* Prase EntryNodes as a routerset. */ + options->EntryNodes = routerset_new(); + retval = routerset_parse(options->EntryNodes, + entrynodes_str, + "test_entrynodes"); + tt_int_op(retval, >=, 0); + + /* Read nodes from EntryNodes */ + entry_guards_set_from_config(options); + + /* Test that only one guard was added. */ + tt_int_op(smartlist_len(all_entry_guards), ==, 1); + + /* Make sure it was the guard we specified. */ + chosen_entry = choose_random_entry(NULL); + tt_str_op(chosen_entry->ri->nickname, ==, entrynodes_str); + + done: + routerset_free(options->EntryNodes); +} + +static void +test_entry_is_time_to_retry(void *arg) +{ + entry_guard_t *test_guard; + time_t now; + int retval; + (void)arg; + + now = time(NULL); + + test_guard = tor_malloc_zero(sizeof(entry_guard_t)); + + test_guard->last_attempted = now - 10; + test_guard->unreachable_since = now - 1; + + retval = entry_is_time_to_retry(test_guard,now); + tt_int_op(retval,==,1); + + test_guard->unreachable_since = now - (6*60*60 - 1); + test_guard->last_attempted = now - (60*60 + 1); + + retval = entry_is_time_to_retry(test_guard,now); + tt_int_op(retval,==,1); + + test_guard->last_attempted = now - (60*60 - 1); + + retval = entry_is_time_to_retry(test_guard,now); + tt_int_op(retval,==,0); + + test_guard->unreachable_since = now - (6*60*60 + 1); + test_guard->last_attempted = now - (4*60*60 + 1); + + retval = entry_is_time_to_retry(test_guard,now); + tt_int_op(retval,==,1); + + test_guard->unreachable_since = now - (3*24*60*60 - 1); + test_guard->last_attempted = now - (4*60*60 + 1); + + retval = entry_is_time_to_retry(test_guard,now); + tt_int_op(retval,==,1); + + test_guard->unreachable_since = now - (3*24*60*60 + 1); + test_guard->last_attempted = now - (18*60*60 + 1); + + retval = entry_is_time_to_retry(test_guard,now); + tt_int_op(retval,==,1); + + test_guard->unreachable_since = now - (7*24*60*60 - 1); + test_guard->last_attempted = now - (18*60*60 + 1); + + retval = entry_is_time_to_retry(test_guard,now); + tt_int_op(retval,==,1); + + test_guard->last_attempted = now - (18*60*60 - 1); + + retval = entry_is_time_to_retry(test_guard,now); + tt_int_op(retval,==,0); + + test_guard->unreachable_since = now - (7*24*60*60 + 1); + test_guard->last_attempted = now - (36*60*60 + 1); + + retval = entry_is_time_to_retry(test_guard,now); + tt_int_op(retval,==,1); + + test_guard->unreachable_since = now - (7*24*60*60 + 1); + test_guard->last_attempted = now - (36*60*60 + 1); + + retval = entry_is_time_to_retry(test_guard,now); + tt_int_op(retval,==,1); + + done: + tor_free(test_guard); +} + +/** XXX Do some tests that entry_is_live() */ +static void +test_entry_is_live(void *arg) +{ + smartlist_t *our_nodelist = NULL; + const smartlist_t *all_entry_guards = get_entry_guards(); + const node_t *test_node = NULL; + const entry_guard_t *test_entry = NULL; + const char *msg; + int which_node; + + (void) arg; + + /* The global entry guards smartlist should be empty now. */ + tt_int_op(smartlist_len(all_entry_guards), ==, 0); + + /* Walk the nodelist and add all nodes as entry guards. */ + our_nodelist = nodelist_get_list(); + tt_int_op(smartlist_len(our_nodelist), ==, NUMBER_OF_DESCRIPTORS); + + SMARTLIST_FOREACH_BEGIN(our_nodelist, const node_t *, node) { + const node_t *node_tmp; + node_tmp = add_an_entry_guard(node, 0, 1, 0, 0); + test_assert(node_tmp); + + tt_int_op(node->is_stable, ==, 0); + tt_int_op(node->is_fast, ==, 0); + } SMARTLIST_FOREACH_END(node); + + /* Make sure the nodes were added as entry guards. */ + tt_int_op(smartlist_len(all_entry_guards), ==, 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) */ + test_entry = smartlist_get(all_entry_guards, which_node); + + /* Let's do some entry_is_live() tests! */ + + /* Require the node to be stable, but it's not. Should fail. + Also enable 'assume_reachable' because why not. */ + test_node = entry_is_live(test_entry, + ENTRY_NEED_UPTIME | ENTRY_ASSUME_REACHABLE, + &msg); + test_assert(!test_node); + + /* Require the node to be fast, but it's not. Should fail. */ + test_node = entry_is_live(test_entry, + ENTRY_NEED_CAPACITY | ENTRY_ASSUME_REACHABLE, + &msg); + test_assert(!test_node); + + /* Don't impose any restrictions on the node. Should succeed. */ + test_node = entry_is_live(test_entry, 0, &msg); + test_assert(test_node); + tt_ptr_op(test_node, ==, node_get_by_id(test_entry->identity)); + + /* Require descriptor for this node. It has one so it should succeed. */ + test_node = entry_is_live(test_entry, ENTRY_NEED_DESCRIPTOR, &msg); + test_assert(test_node); + tt_ptr_op(test_node, ==, node_get_by_id(test_entry->identity)); + + done: + ; /* XXX */ +} + +static const struct testcase_setup_t fake_network = { + fake_network_setup, fake_network_cleanup +}; + +struct testcase_t entrynodes_tests[] = { + { "entry_is_time_to_retry", test_entry_is_time_to_retry, + TT_FORK, NULL, NULL }, + { "choose_random_entry_no_guards", test_choose_random_entry_no_guards, + TT_FORK, &fake_network, NULL }, + { "choose_random_entry_one_possibleguard", + test_choose_random_entry_one_possible_guard, + TT_FORK, &fake_network, NULL }, + { "populate_live_entry_guards_1guard", + test_populate_live_entry_guards_1guard, + TT_FORK, &fake_network, NULL }, + { "populate_live_entry_guards_3guards", + test_populate_live_entry_guards_3guards, + TT_FORK, &fake_network, NULL }, + { "entry_guards_parse_state_simple", + test_entry_guards_parse_state_simple, + TT_FORK, &fake_network, NULL }, + { "entry_guards_parse_state_pathbias", + test_entry_guards_parse_state_pathbias, + TT_FORK, &fake_network, NULL }, + { "entry_guards_set_from_config", + test_entry_guards_set_from_config, + TT_FORK, &fake_network, NULL }, + { "entry_is_live", + test_entry_is_live, + TT_FORK, &fake_network, NULL }, + END_OF_TESTCASES +}; + diff --git a/src/test/test_logging.c b/src/test/test_logging.c index 7e558f83b1..9f57000bea 100644 --- a/src/test/test_logging.c +++ b/src/test/test_logging.c @@ -89,7 +89,7 @@ test_sigsafe_err(void *arg) init_logging(); mark_logs_temp(); - add_file_log(&include_bug, fn); + add_file_log(&include_bug, fn, 0); tor_log_update_sigsafe_err_fds(); close_temp_logs(); diff --git a/src/test/test_pt.c b/src/test/test_pt.c index f71627df1e..f55c059580 100644 --- a/src/test/test_pt.c +++ b/src/test/test_pt.c @@ -194,7 +194,7 @@ test_pt_protocol(void) managed_proxy_t *mp = tor_malloc_zero(sizeof(managed_proxy_t)); mp->conf_state = PT_PROTO_LAUNCHED; mp->transports = smartlist_new(); - mp->argv = tor_malloc_zero(sizeof(char*)*2); + mp->argv = tor_calloc(sizeof(char *), 2); mp->argv[0] = tor_strdup("<testcase>"); /* various wrong protocol runs: */ diff --git a/src/test/test_routerset.c b/src/test/test_routerset.c new file mode 100644 index 0000000000..0ea1ef2d89 --- /dev/null +++ b/src/test/test_routerset.c @@ -0,0 +1,2118 @@ +#define ROUTERSET_PRIVATE + +#include "or.h" +#include "geoip.h" +#include "routerset.h" +#include "routerparse.h" +#include "policies.h" +#include "nodelist.h" +#include "test.h" + +#define NS_MODULE routerset + +#define NS_SUBMODULE routerset_new + +/* + * Functional (blackbox) test to determine that each member of the routerset + * is non-NULL + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *rs; + (void)arg; + + rs = routerset_new(); + + tt_ptr_op(rs, !=, NULL); + tt_ptr_op(rs->list, !=, NULL); + tt_ptr_op(rs->names, !=, NULL); + tt_ptr_op(rs->digests, !=, NULL); + tt_ptr_op(rs->policies, !=, NULL); + tt_ptr_op(rs->country_names, !=, NULL); + + done: + routerset_free(rs); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE routerset_get_countryname + +/* + * Functional test to strip the braces from a "{xx}" country code string. + */ + +static void +NS(test_main)(void *arg) +{ + const char *input; + char *name; + (void)arg; + + /* strlen(c) < 4 */ + input = "xxx"; + name = routerset_get_countryname(input); + tt_ptr_op(name, ==, NULL); + tor_free(name); + + /* c[0] != '{' */ + input = "xxx}"; + name = routerset_get_countryname(input); + tt_ptr_op(name, ==, NULL); + tor_free(name); + + /* c[3] != '}' */ + input = "{xxx"; + name = routerset_get_countryname(input); + tt_ptr_op(name, ==, NULL); + tor_free(name); + + /* tor_strlower */ + input = "{XX}"; + name = routerset_get_countryname(input); + tt_str_op(name, ==, "xx"); + tor_free(name); + + input = "{xx}"; + name = routerset_get_countryname(input); + tt_str_op(name, ==, "xx"); + done: + tor_free(name); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_refresh_counties, geoip_not_loaded) + +/* + * Structural (whitebox) test for routerset_refresh_counties, when the GeoIP DB + * is not loaded. + */ + +NS_DECL(int, geoip_is_loaded, (sa_family_t family)); +NS_DECL(int, geoip_get_n_countries, (void)); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + (void)arg; + + NS_MOCK(geoip_is_loaded); + NS_MOCK(geoip_get_n_countries); + + routerset_refresh_countries(set); + + tt_ptr_op(set->countries, ==, NULL); + tt_int_op(set->n_countries, ==, 0); + tt_int_op(CALLED(geoip_is_loaded), ==, 1); + tt_int_op(CALLED(geoip_get_n_countries), ==, 0); + + done: + NS_UNMOCK(geoip_is_loaded); + NS_UNMOCK(geoip_get_n_countries); + routerset_free(set); +} + +static int +NS(geoip_is_loaded)(sa_family_t family) +{ + (void)family; + CALLED(geoip_is_loaded)++; + + return 0; +} + +static int +NS(geoip_get_n_countries)(void) +{ + CALLED(geoip_get_n_countries)++; + + return 0; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_refresh_counties, no_countries) + +/* + * Structural test for routerset_refresh_counties, when there are no countries. + */ + +NS_DECL(int, geoip_is_loaded, (sa_family_t family)); +NS_DECL(int, geoip_get_n_countries, (void)); +NS_DECL(country_t, geoip_get_country, (const char *country)); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + (void)arg; + + NS_MOCK(geoip_is_loaded); + NS_MOCK(geoip_get_n_countries); + NS_MOCK(geoip_get_country); + + routerset_refresh_countries(set); + + tt_ptr_op(set->countries, !=, NULL); + tt_int_op(set->n_countries, ==, 1); + tt_int_op((unsigned int)(*set->countries), ==, 0); + tt_int_op(CALLED(geoip_is_loaded), ==, 1); + tt_int_op(CALLED(geoip_get_n_countries), ==, 1); + tt_int_op(CALLED(geoip_get_country), ==, 0); + + done: + NS_UNMOCK(geoip_is_loaded); + NS_UNMOCK(geoip_get_n_countries); + NS_UNMOCK(geoip_get_country); + routerset_free(set); +} + +static int +NS(geoip_is_loaded)(sa_family_t family) +{ + (void)family; + CALLED(geoip_is_loaded)++; + + return 1; +} + +static int +NS(geoip_get_n_countries)(void) +{ + CALLED(geoip_get_n_countries)++; + + return 1; +} + +static country_t +NS(geoip_get_country)(const char *countrycode) +{ + (void)countrycode; + CALLED(geoip_get_country)++; + + return 1; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_refresh_counties, one_valid_country) + +/* + * Structural test for routerset_refresh_counties, with one valid country. + */ + +NS_DECL(int, geoip_is_loaded, (sa_family_t family)); +NS_DECL(int, geoip_get_n_countries, (void)); +NS_DECL(country_t, geoip_get_country, (const char *country)); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + (void)arg; + + NS_MOCK(geoip_is_loaded); + NS_MOCK(geoip_get_n_countries); + NS_MOCK(geoip_get_country); + smartlist_add(set->country_names, tor_strndup("foo", 3)); + + routerset_refresh_countries(set); + + tt_ptr_op(set->countries, !=, NULL); + tt_int_op(set->n_countries, ==, 2); + tt_int_op(CALLED(geoip_is_loaded), ==, 1); + tt_int_op(CALLED(geoip_get_n_countries), ==, 1); + tt_int_op(CALLED(geoip_get_country), ==, 1); + tt_int_op((unsigned int)(*set->countries), !=, 0); + + done: + NS_UNMOCK(geoip_is_loaded); + NS_UNMOCK(geoip_get_n_countries); + NS_UNMOCK(geoip_get_country); + routerset_free(set); +} + +static int +NS(geoip_is_loaded)(sa_family_t family) +{ + (void)family; + CALLED(geoip_is_loaded)++; + + return 1; +} + +static int +NS(geoip_get_n_countries)(void) +{ + CALLED(geoip_get_n_countries)++; + + return 2; +} + +static country_t +NS(geoip_get_country)(const char *countrycode) +{ + (void)countrycode; + CALLED(geoip_get_country)++; + + return 1; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_refresh_counties, one_invalid_country) + +/* + * Structural test for routerset_refresh_counties, with one invalid + * country code.. + */ + +NS_DECL(int, geoip_is_loaded, (sa_family_t family)); +NS_DECL(int, geoip_get_n_countries, (void)); +NS_DECL(country_t, geoip_get_country, (const char *country)); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + (void)arg; + + NS_MOCK(geoip_is_loaded); + NS_MOCK(geoip_get_n_countries); + NS_MOCK(geoip_get_country); + smartlist_add(set->country_names, tor_strndup("foo", 3)); + + routerset_refresh_countries(set); + + tt_ptr_op(set->countries, !=, NULL); + tt_int_op(set->n_countries, ==, 2); + tt_int_op(CALLED(geoip_is_loaded), ==, 1); + tt_int_op(CALLED(geoip_get_n_countries), ==, 1); + tt_int_op(CALLED(geoip_get_country), ==, 1); + tt_int_op((unsigned int)(*set->countries), ==, 0); + + done: + NS_UNMOCK(geoip_is_loaded); + NS_UNMOCK(geoip_get_n_countries); + NS_UNMOCK(geoip_get_country); + routerset_free(set); +} + +static int +NS(geoip_is_loaded)(sa_family_t family) +{ + (void)family; + CALLED(geoip_is_loaded)++; + + return 1; +} + +static int +NS(geoip_get_n_countries)(void) +{ + CALLED(geoip_get_n_countries)++; + + return 2; +} + +static country_t +NS(geoip_get_country)(const char *countrycode) +{ + (void)countrycode; + CALLED(geoip_get_country)++; + + return -1; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_parse, malformed) + +/* + * Functional test, with a malformed string to parse. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + const char *s = "_"; + int r; + (void)arg; + + r = routerset_parse(set, s, ""); + + tt_int_op(r, ==, -1); + + done: + routerset_free(set); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_parse, valid_hexdigest) + +/* + * Functional test for routerset_parse, that routerset_parse returns 0 + * on a valid hexdigest entry. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set; + const char *s; + int r; + (void)arg; + + set = routerset_new(); + s = "$0000000000000000000000000000000000000000"; + r = routerset_parse(set, s, ""); + tt_int_op(r, ==, 0); + tt_int_op(digestmap_isempty(set->digests), !=, 1); + + done: + routerset_free(set); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_parse, valid_nickname) + +/* + * Functional test for routerset_parse, when given a valid nickname as input. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set; + const char *s; + int r; + (void)arg; + + set = routerset_new(); + s = "fred"; + r = routerset_parse(set, s, ""); + tt_int_op(r, ==, 0); + tt_int_op(strmap_isempty(set->names), !=, 1); + + done: + routerset_free(set); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_parse, get_countryname) + +/* + * Functional test for routerset_parse, when given a valid countryname. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set; + const char *s; + int r; + (void)arg; + + set = routerset_new(); + s = "{cc}"; + r = routerset_parse(set, s, ""); + tt_int_op(r, ==, 0); + tt_int_op(smartlist_len(set->country_names), !=, 0); + + done: + routerset_free(set); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_parse, policy) + +/* + * Structural test for routerset_parse, when given a valid policy. + */ + +NS_DECL(addr_policy_t *, router_parse_addr_policy_item_from_string, + (const char *s, int assume_action)); + +addr_policy_t *NS(mock_addr_policy); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set; + const char *s; + int r; + (void)arg; + + NS_MOCK(router_parse_addr_policy_item_from_string); + NS(mock_addr_policy) = tor_malloc_zero(sizeof(addr_policy_t)); + + set = routerset_new(); + s = "*"; + r = routerset_parse(set, s, ""); + tt_int_op(r, ==, 0); + tt_int_op(smartlist_len(set->policies), !=, 0); + tt_int_op(CALLED(router_parse_addr_policy_item_from_string), ==, 1); + + done: + routerset_free(set); +} + +addr_policy_t * +NS(router_parse_addr_policy_item_from_string)(const char *s, int assume_action) +{ + (void)s; + (void)assume_action; + CALLED(router_parse_addr_policy_item_from_string)++; + + return NS(mock_addr_policy); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_union, source_bad) + +/* + * Structural test for routerset_union, when given a bad source argument. + */ + +NS_DECL(smartlist_t *, smartlist_new, (void)); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set, *bad_set; + (void)arg; + + set = routerset_new(); + bad_set = routerset_new(); + smartlist_free(bad_set->list); + bad_set->list = NULL; + + NS_MOCK(smartlist_new); + + routerset_union(set, NULL); + tt_int_op(CALLED(smartlist_new), ==, 0); + + routerset_union(set, bad_set); + tt_int_op(CALLED(smartlist_new), ==, 0); + + done: + NS_UNMOCK(smartlist_new); + routerset_free(set); + + /* Just recreate list, so we can simply use routerset_free. */ + bad_set->list = smartlist_new(); + routerset_free(bad_set); +} + +static smartlist_t * +NS(smartlist_new)(void) +{ + CALLED(smartlist_new)++; + + return NULL; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_union, one) + +/* + * Functional test for routerset_union. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *src = routerset_new(); + routerset_t *tgt; + (void)arg; + + tgt = routerset_new(); + smartlist_add(src->list, tor_strdup("{xx}")); + routerset_union(tgt, src); + + tt_int_op(smartlist_len(tgt->list), !=, 0); + + done: + routerset_free(src); + routerset_free(tgt); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE routerset_is_list + +/* + * Functional tests for routerset_is_list. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set; + addr_policy_t *policy; + int is_list; + (void)arg; + + /* len(set->country_names) == 0, len(set->policies) == 0 */ + set = routerset_new(); + is_list = routerset_is_list(set); + routerset_free(set); + set = NULL; + tt_int_op(is_list, !=, 0); + + /* len(set->country_names) != 0, len(set->policies) == 0 */ + set = routerset_new(); + smartlist_add(set->country_names, tor_strndup("foo", 3)); + is_list = routerset_is_list(set); + routerset_free(set); + set = NULL; + tt_int_op(is_list, ==, 0); + + /* len(set->country_names) == 0, len(set->policies) != 0 */ + set = routerset_new(); + policy = tor_malloc_zero(sizeof(addr_policy_t)); + smartlist_add(set->policies, (void *)policy); + is_list = routerset_is_list(set); + routerset_free(set); + set = NULL; + tt_int_op(is_list, ==, 0); + + /* len(set->country_names) != 0, len(set->policies) != 0 */ + set = routerset_new(); + smartlist_add(set->country_names, tor_strndup("foo", 3)); + policy = tor_malloc_zero(sizeof(addr_policy_t)); + smartlist_add(set->policies, (void *)policy); + is_list = routerset_is_list(set); + routerset_free(set); + set = NULL; + tt_int_op(is_list, ==, 0); + + done: + ; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE routerset_needs_geoip + +/* + * Functional tests for routerset_needs_geoip. + */ + +static void +NS(test_main)(void *arg) +{ + const routerset_t *set; + int needs_geoip; + (void)arg; + + set = NULL; + needs_geoip = routerset_needs_geoip(set); + tt_int_op(needs_geoip, ==, 0); + + set = routerset_new(); + needs_geoip = routerset_needs_geoip(set); + routerset_free((routerset_t *)set); + tt_int_op(needs_geoip, ==, 0); + set = NULL; + + set = routerset_new(); + smartlist_add(set->country_names, tor_strndup("xx", 2)); + needs_geoip = routerset_needs_geoip(set); + routerset_free((routerset_t *)set); + set = NULL; + tt_int_op(needs_geoip, !=, 0); + + done: + ; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE routerset_is_empty + +/* + * Functional tests for routerset_is_empty. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = NULL; + int is_empty; + (void)arg; + + is_empty = routerset_is_empty(set); + tt_int_op(is_empty, !=, 0); + + set = routerset_new(); + is_empty = routerset_is_empty(set); + routerset_free(set); + set = NULL; + tt_int_op(is_empty, !=, 0); + + set = routerset_new(); + smartlist_add(set->list, tor_strdup("{xx}")); + is_empty = routerset_is_empty(set); + routerset_free(set); + set = NULL; + tt_int_op(is_empty, ==, 0); + + done: + ; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_contains, null_set_or_null_set_list) + +/* + * Functional test for routerset_contains, when given a NULL set or the + * set has a NULL list. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = NULL; + int contains; + (void)arg; + + contains = routerset_contains(set, NULL, 0, NULL, NULL, 0); + + tt_int_op(contains, ==, 0); + + set = tor_malloc_zero(sizeof(routerset_t)); + set->list = NULL; + contains = routerset_contains(set, NULL, 0, NULL, NULL, 0); + tor_free(set); + tt_int_op(contains, ==, 0); + + done: + ; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_contains, set_and_null_nickname) + +/* + * Functional test for routerset_contains, when given a valid routerset but a + * NULL nickname. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + char *nickname = NULL; + int contains; + (void)arg; + + contains = routerset_contains(set, NULL, 0, nickname, NULL, 0); + routerset_free(set); + + tt_int_op(contains, ==, 0); + + done: + ; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_contains, set_and_nickname) + +/* + * Functional test for routerset_contains, when given a valid routerset + * and the nickname is in the routerset. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + const char *nickname; + int contains; + (void)arg; + + nickname = "Foo"; /* This tests the lowercase comparison as well. */ + strmap_set_lc(set->names, nickname, (void *)1); + contains = routerset_contains(set, NULL, 0, nickname, NULL, 0); + routerset_free(set); + + tt_int_op(contains, ==, 4); + done: + ; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_contains, set_and_no_nickname) + +/* + * Functional test for routerset_contains, when given a valid routerset + * and the nickname is not in the routerset. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + int contains; + (void)arg; + + strmap_set_lc(set->names, "bar", (void *)1); + contains = routerset_contains(set, NULL, 0, "foo", NULL, 0); + routerset_free(set); + + tt_int_op(contains, ==, 0); + done: + ; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_contains, set_and_digest) + +/* + * Functional test for routerset_contains, when given a valid routerset + * and the digest is contained in the routerset. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + int contains; + (void)arg; + + digestmap_set(set->digests, "foo", (void *)1); + contains = routerset_contains(set, NULL, 0, NULL, "foo", 0); + routerset_free(set); + + tt_int_op(contains, ==, 4); + done: + ; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_contains, set_and_no_digest) + +/* + * Functional test for routerset_contains, when given a valid routerset + * and the digest is not contained in the routerset. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + int contains; + (void)arg; + + digestmap_set(set->digests, "bar", (void *)1); + contains = routerset_contains(set, NULL, 0, NULL, "foo", 0); + routerset_free(set); + + tt_int_op(contains, ==, 0); + done: + ; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_contains, set_and_null_digest) + +/* + * Functional test for routerset_contains, when given a valid routerset + * and the digest is NULL. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + int contains; + (void)arg; + + digestmap_set(set->digests, "bar", (void *)1); + contains = routerset_contains(set, NULL, 0, NULL, NULL, 0); + routerset_free(set); + + tt_int_op(contains, ==, 0); + done: + ; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_contains, set_and_addr) + +/* + * Structural test for routerset_contains, when given a valid routerset + * and the address is rejected by policy. + */ + +NS_DECL(addr_policy_result_t, compare_tor_addr_to_addr_policy, + (const tor_addr_t *addr, uint16_t port, const smartlist_t *policy)); + +static tor_addr_t MOCK_TOR_ADDR; +#define MOCK_TOR_ADDR_PTR (&MOCK_TOR_ADDR) + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + tor_addr_t *addr = MOCK_TOR_ADDR_PTR; + int contains; + (void)arg; + + NS_MOCK(compare_tor_addr_to_addr_policy); + + contains = routerset_contains(set, addr, 0, NULL, NULL, 0); + routerset_free(set); + + tt_int_op(CALLED(compare_tor_addr_to_addr_policy), ==, 1); + tt_int_op(contains, ==, 3); + + done: + ; +} + +addr_policy_result_t +NS(compare_tor_addr_to_addr_policy)(const tor_addr_t *addr, uint16_t port, + const smartlist_t *policy) +{ + (void)port; + (void)policy; + CALLED(compare_tor_addr_to_addr_policy)++; + tt_ptr_op(addr, ==, MOCK_TOR_ADDR_PTR); + return ADDR_POLICY_REJECTED; + + done: + return 0; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_contains, set_and_no_addr) + +/* + * Structural test for routerset_contains, when given a valid routerset + * and the address is not rejected by policy. + */ + +NS_DECL(addr_policy_result_t, compare_tor_addr_to_addr_policy, + (const tor_addr_t *addr, uint16_t port, const smartlist_t *policy)); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + tor_addr_t *addr = MOCK_TOR_ADDR_PTR; + int contains; + (void)arg; + + NS_MOCK(compare_tor_addr_to_addr_policy); + + contains = routerset_contains(set, addr, 0, NULL, NULL, 0); + routerset_free(set); + + tt_int_op(CALLED(compare_tor_addr_to_addr_policy), ==, 1); + tt_int_op(contains, ==, 0); + + done: + ; +} + +addr_policy_result_t +NS(compare_tor_addr_to_addr_policy)(const tor_addr_t *addr, uint16_t port, + const smartlist_t *policy) +{ + (void)port; + (void)policy; + CALLED(compare_tor_addr_to_addr_policy)++; + tt_ptr_op(addr, ==, MOCK_TOR_ADDR_PTR); + + return ADDR_POLICY_ACCEPTED; + + done: + return 0; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_contains, set_and_null_addr) + +/* + * Structural test for routerset_contains, when given a valid routerset + * and the address is NULL. + */ + +NS_DECL(addr_policy_result_t, compare_tor_addr_to_addr_policy, + (const tor_addr_t *addr, uint16_t port, const smartlist_t *policy)); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + int contains; + (void)arg; + + NS_MOCK(compare_tor_addr_to_addr_policy); + + contains = routerset_contains(set, NULL, 0, NULL, NULL, 0); + routerset_free(set); + + tt_int_op(contains, ==, 0); + + done: + ; +} + +addr_policy_result_t +NS(compare_tor_addr_to_addr_policy)(const tor_addr_t *addr, uint16_t port, + const smartlist_t *policy) +{ + (void)port; + (void)policy; + CALLED(compare_tor_addr_to_addr_policy)++; + tt_ptr_op(addr, ==, MOCK_TOR_ADDR_PTR); + + return ADDR_POLICY_ACCEPTED; + + done: + return 0; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_contains, countries_no_geoip) + +/* + * Structural test for routerset_contains, when there is no matching country + * for the address. + */ + +NS_DECL(addr_policy_result_t, compare_tor_addr_to_addr_policy, + (const tor_addr_t *addr, uint16_t port, const smartlist_t *policy)); +NS_DECL(int, geoip_get_country_by_addr, (const tor_addr_t *addr)); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + int contains = 1; + (void)arg; + + NS_MOCK(compare_tor_addr_to_addr_policy); + NS_MOCK(geoip_get_country_by_addr); + + set->countries = bitarray_init_zero(1); + bitarray_set(set->countries, 1); + contains = routerset_contains(set, MOCK_TOR_ADDR_PTR, 0, NULL, NULL, -1); + routerset_free(set); + + tt_int_op(contains, ==, 0); + tt_int_op(CALLED(compare_tor_addr_to_addr_policy), ==, 1); + tt_int_op(CALLED(geoip_get_country_by_addr), ==, 1); + + done: + ; +} + +addr_policy_result_t +NS(compare_tor_addr_to_addr_policy)(const tor_addr_t *addr, uint16_t port, + const smartlist_t *policy) +{ + (void)port; + (void)policy; + CALLED(compare_tor_addr_to_addr_policy)++; + tt_ptr_op(addr, ==, MOCK_TOR_ADDR_PTR); + + done: + return ADDR_POLICY_ACCEPTED; +} + +int +NS(geoip_get_country_by_addr)(const tor_addr_t *addr) +{ + CALLED(geoip_get_country_by_addr)++; + tt_ptr_op(addr, ==, MOCK_TOR_ADDR_PTR); + + done: + return -1; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_contains, countries_geoip) + +/* + * Structural test for routerset_contains, when there a matching country + * for the address. + */ + +NS_DECL(addr_policy_result_t, compare_tor_addr_to_addr_policy, + (const tor_addr_t *addr, uint16_t port, const smartlist_t *policy)); +NS_DECL(int, geoip_get_country_by_addr, (const tor_addr_t *addr)); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + int contains = 1; + (void)arg; + + NS_MOCK(compare_tor_addr_to_addr_policy); + NS_MOCK(geoip_get_country_by_addr); + + set->n_countries = 2; + set->countries = bitarray_init_zero(1); + bitarray_set(set->countries, 1); + contains = routerset_contains(set, MOCK_TOR_ADDR_PTR, 0, NULL, NULL, -1); + routerset_free(set); + + tt_int_op(contains, ==, 2); + tt_int_op(CALLED(compare_tor_addr_to_addr_policy), ==, 1); + tt_int_op(CALLED(geoip_get_country_by_addr), ==, 1); + + done: + ; +} + +addr_policy_result_t +NS(compare_tor_addr_to_addr_policy)(const tor_addr_t *addr, uint16_t port, + const smartlist_t *policy) +{ + (void)port; + (void)policy; + CALLED(compare_tor_addr_to_addr_policy)++; + tt_ptr_op(addr, ==, MOCK_TOR_ADDR_PTR); + + done: + return ADDR_POLICY_ACCEPTED; +} + +int +NS(geoip_get_country_by_addr)(const tor_addr_t *addr) +{ + CALLED(geoip_get_country_by_addr)++; + tt_ptr_op(addr, ==, MOCK_TOR_ADDR_PTR); + + done: + return 1; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_add_unknown_ccs, only_flag_and_no_ccs) + +/* + * Functional test for routerset_add_unknown_ccs, where only_if_some_cc_set + * is set and there are no country names. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + routerset_t **setp = &set; + int r; + (void)arg; + + r = routerset_add_unknown_ccs(setp, 1); + + tt_int_op(r, ==, 0); + + done: + routerset_free(set); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_add_unknown_ccs, creates_set) + +/* + * Functional test for routerset_add_unknown_ccs, where the set argument + * is created if passed in as NULL. + */ + +/* The mock is only used to stop the test from asserting erroneously. */ +NS_DECL(country_t, geoip_get_country, (const char *country)); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = NULL; + routerset_t **setp = &set; + int r; + (void)arg; + + NS_MOCK(geoip_get_country); + + r = routerset_add_unknown_ccs(setp, 0); + + tt_ptr_op(*setp, !=, NULL); + tt_int_op(r, ==, 0); + + done: + if (set != NULL) + routerset_free(set); +} + +country_t +NS(geoip_get_country)(const char *country) +{ + (void)country; + CALLED(geoip_get_country)++; + + return -1; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_add_unknown_ccs, add_unknown) + +/* + * Structural test for routerset_add_unknown_ccs, that the "{??}" + * country code is added to the list. + */ + +NS_DECL(country_t, geoip_get_country, (const char *country)); +NS_DECL(int, geoip_is_loaded, (sa_family_t family)); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + routerset_t **setp = &set; + int r; + (void)arg; + + NS_MOCK(geoip_get_country); + NS_MOCK(geoip_is_loaded); + + r = routerset_add_unknown_ccs(setp, 0); + + tt_int_op(r, ==, 1); + tt_int_op(smartlist_contains_string(set->country_names, "??"), ==, 1); + tt_int_op(smartlist_contains_string(set->list, "{??}"), ==, 1); + + done: + if (set != NULL) + routerset_free(set); +} + +country_t +NS(geoip_get_country)(const char *country) +{ + int arg_is_qq, arg_is_a1; + + CALLED(geoip_get_country)++; + + arg_is_qq = !strcmp(country, "??"); + arg_is_a1 = !strcmp(country, "A1"); + + tt_int_op(arg_is_qq || arg_is_a1, ==, 1); + + if (arg_is_qq) + return 1; + + done: + return -1; +} + +int +NS(geoip_is_loaded)(sa_family_t family) +{ + CALLED(geoip_is_loaded)++; + + tt_int_op(family, ==, AF_INET); + + done: + return 0; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_add_unknown_ccs, add_a1) + +/* + * Structural test for routerset_add_unknown_ccs, that the "{a1}" + * country code is added to the list. + */ + +NS_DECL(country_t, geoip_get_country, (const char *country)); +NS_DECL(int, geoip_is_loaded, (sa_family_t family)); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + routerset_t **setp = &set; + int r; + (void)arg; + + NS_MOCK(geoip_get_country); + NS_MOCK(geoip_is_loaded); + + r = routerset_add_unknown_ccs(setp, 0); + + tt_int_op(r, ==, 1); + tt_int_op(smartlist_contains_string(set->country_names, "a1"), ==, 1); + tt_int_op(smartlist_contains_string(set->list, "{a1}"), ==, 1); + + done: + if (set != NULL) + routerset_free(set); +} + +country_t +NS(geoip_get_country)(const char *country) +{ + int arg_is_qq, arg_is_a1; + + CALLED(geoip_get_country)++; + + arg_is_qq = !strcmp(country, "??"); + arg_is_a1 = !strcmp(country, "A1"); + + tt_int_op(arg_is_qq || arg_is_a1, ==, 1); + + if (arg_is_a1) + return 1; + + done: + return -1; +} + +int +NS(geoip_is_loaded)(sa_family_t family) +{ + CALLED(geoip_is_loaded)++; + + tt_int_op(family, ==, AF_INET); + + done: + return 0; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE routerset_contains_extendinfo + +/* + * Functional test for routerset_contains_extendinfo. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + extend_info_t ei; + int r; + const char *nickname = "foo"; + (void)arg; + + memset(&ei, 0, sizeof(ei)); + strmap_set_lc(set->names, nickname, (void *)1); + strncpy(ei.nickname, nickname, sizeof(ei.nickname) - 1); + ei.nickname[sizeof(ei.nickname) - 1] = '\0'; + + r = routerset_contains_extendinfo(set, &ei); + + tt_int_op(r, ==, 4); + done: + routerset_free(set); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE routerset_contains_router + +/* + * Functional test for routerset_contains_router. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + routerinfo_t ri; + country_t country = 1; + int r; + const char *nickname = "foo"; + (void)arg; + + memset(&ri, 0, sizeof(ri)); + strmap_set_lc(set->names, nickname, (void *)1); + ri.nickname = (char *)nickname; + + r = routerset_contains_router(set, &ri, country); + + tt_int_op(r, ==, 4); + done: + routerset_free(set); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE routerset_contains_routerstatus + +/* + * Functional test for routerset_contains_routerstatus. + */ + +// XXX: This is a bit brief. It only populates and tests the nickname fields +// ie., enough to make the containment check succeed. Perhaps it should do +// a bit more or test a bit more. + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + routerstatus_t rs; + country_t country = 1; + int r; + const char *nickname = "foo"; + (void)arg; + + memset(&rs, 0, sizeof(rs)); + strmap_set_lc(set->names, nickname, (void *)1); + strncpy(rs.nickname, nickname, sizeof(rs.nickname) - 1); + rs.nickname[sizeof(rs.nickname) - 1] = '\0'; + + r = routerset_contains_routerstatus(set, &rs, country); + + tt_int_op(r, ==, 4); + done: + routerset_free(set); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_contains_node, none) + +/* + * Functional test for routerset_contains_node, when the node has no + * routerset or routerinfo. + */ + +node_t NS(mock_node); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + int r; + (void)arg; + + NS(mock_node).ri = NULL; + NS(mock_node).rs = NULL; + + r = routerset_contains_node(set, &NS(mock_node)); + tt_int_op(r, ==, 0); + + done: + routerset_free(set); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_contains_node, routerstatus) + +/* + * Functional test for routerset_contains_node, when the node has a + * routerset and no routerinfo. + */ + +node_t NS(mock_node); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + int r; + const char *nickname = "foo"; + routerstatus_t rs; + (void)arg; + + strmap_set_lc(set->names, nickname, (void *)1); + + strncpy(rs.nickname, nickname, sizeof(rs.nickname) - 1); + rs.nickname[sizeof(rs.nickname) - 1] = '\0'; + NS(mock_node).ri = NULL; + NS(mock_node).rs = &rs; + + r = routerset_contains_node(set, &NS(mock_node)); + + tt_int_op(r, ==, 4); + done: + routerset_free(set); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_contains_node, routerinfo) + +/* + * Functional test for routerset_contains_node, when the node has no + * routerset and a routerinfo. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + int r; + const char *nickname = "foo"; + routerinfo_t ri; + node_t mock_node; + (void)arg; + + strmap_set_lc(set->names, nickname, (void *)1); + + ri.nickname = (char *)nickname; + mock_node.ri = &ri; + mock_node.rs = NULL; + + r = routerset_contains_node(set, &mock_node); + + tt_int_op(r, ==, 4); + done: + routerset_free(set); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_get_all_nodes, no_routerset) + +/* + * Functional test for routerset_get_all_nodes, when routerset is NULL or + * the routerset list is NULL. + */ + +static void +NS(test_main)(void *arg) +{ + smartlist_t *out = smartlist_new(); + routerset_t *set = NULL; + (void)arg; + + tt_int_op(smartlist_len(out), ==, 0); + routerset_get_all_nodes(out, NULL, NULL, 0); + + tt_int_op(smartlist_len(out), ==, 0); + + set = routerset_new(); + smartlist_free(set->list); + routerset_get_all_nodes(out, NULL, NULL, 0); + tt_int_op(smartlist_len(out), ==, 0); + + /* Just recreate list, so we can simply use routerset_free. */ + set->list = smartlist_new(); + + done: + routerset_free(set); + smartlist_free(out); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_get_all_nodes, list_with_no_nodes) + +/* + * Structural test for routerset_get_all_nodes, when the routerset list + * is empty. + */ + +NS_DECL(const node_t *, node_get_by_nickname, + (const char *nickname, int warn_if_unused)); +const char *NS(mock_nickname); + +static void +NS(test_main)(void *arg) +{ + smartlist_t *out = smartlist_new(); + routerset_t *set = routerset_new(); + int out_len; + (void)arg; + + NS_MOCK(node_get_by_nickname); + + NS(mock_nickname) = "foo"; + smartlist_add(set->list, tor_strdup(NS(mock_nickname))); + + routerset_get_all_nodes(out, set, NULL, 0); + out_len = smartlist_len(out); + + smartlist_free(out); + routerset_free(set); + + tt_int_op(out_len, ==, 0); + tt_int_op(CALLED(node_get_by_nickname), ==, 1); + + done: + ; +} + +const node_t * +NS(node_get_by_nickname)(const char *nickname, int warn_if_unused) +{ + CALLED(node_get_by_nickname)++; + tt_str_op(nickname, ==, NS(mock_nickname)); + tt_int_op(warn_if_unused, ==, 1); + + done: + return NULL; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_get_all_nodes, list_flag_not_running) + +/* + * Structural test for routerset_get_all_nodes, with the running_only flag + * is set but the nodes are not running. + */ + +NS_DECL(const node_t *, node_get_by_nickname, + (const char *nickname, int warn_if_unused)); +const char *NS(mock_nickname); +node_t NS(mock_node); + +static void +NS(test_main)(void *arg) +{ + smartlist_t *out = smartlist_new(); + routerset_t *set = routerset_new(); + int out_len; + (void)arg; + + NS_MOCK(node_get_by_nickname); + + NS(mock_node).is_running = 0; + NS(mock_nickname) = "foo"; + smartlist_add(set->list, tor_strdup(NS(mock_nickname))); + + routerset_get_all_nodes(out, set, NULL, 1); + out_len = smartlist_len(out); + + smartlist_free(out); + routerset_free(set); + + tt_int_op(out_len, ==, 0); + tt_int_op(CALLED(node_get_by_nickname), ==, 1); + + done: + ; +} + +const node_t * +NS(node_get_by_nickname)(const char *nickname, int warn_if_unused) +{ + CALLED(node_get_by_nickname)++; + tt_str_op(nickname, ==, NS(mock_nickname)); + tt_int_op(warn_if_unused, ==, 1); + + done: + return &NS(mock_node); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_get_all_nodes, list) + +/* + * Structural test for routerset_get_all_nodes. + */ + +NS_DECL(const node_t *, node_get_by_nickname, + (const char *nickname, int warn_if_unused)); +char *NS(mock_nickname); +node_t NS(mock_node); + +static void +NS(test_main)(void *arg) +{ + smartlist_t *out = smartlist_new(); + routerset_t *set = routerset_new(); + int out_len; + node_t *ent; + (void)arg; + + NS_MOCK(node_get_by_nickname); + + NS(mock_nickname) = tor_strdup("foo"); + smartlist_add(set->list, NS(mock_nickname)); + + routerset_get_all_nodes(out, set, NULL, 0); + out_len = smartlist_len(out); + ent = (node_t *)smartlist_get(out, 0); + + smartlist_free(out); + routerset_free(set); + + tt_int_op(out_len, ==, 1); + tt_ptr_op(ent, ==, &NS(mock_node)); + tt_int_op(CALLED(node_get_by_nickname), ==, 1); + + done: + ; +} + +const node_t * +NS(node_get_by_nickname)(const char *nickname, int warn_if_unused) +{ + CALLED(node_get_by_nickname)++; + tt_str_op(nickname, ==, NS(mock_nickname)); + tt_int_op(warn_if_unused, ==, 1); + + done: + return &NS(mock_node); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_get_all_nodes, nodelist_with_no_nodes) + +/* + * Structural test for routerset_get_all_nodes, when the nodelist has no nodes. + */ + +NS_DECL(smartlist_t *, nodelist_get_list, (void)); + +smartlist_t *NS(mock_smartlist); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + smartlist_t *out = smartlist_new(); + int r; + (void)arg; + + NS_MOCK(nodelist_get_list); + + smartlist_add(set->country_names, tor_strdup("{xx}")); + NS(mock_smartlist) = smartlist_new(); + + routerset_get_all_nodes(out, set, NULL, 1); + r = smartlist_len(out); + routerset_free(set); + smartlist_free(out); + smartlist_free(NS(mock_smartlist)); + + tt_int_op(r, ==, 0); + tt_int_op(CALLED(nodelist_get_list), ==, 1); + + done: + ; +} + +smartlist_t * +NS(nodelist_get_list)(void) +{ + CALLED(nodelist_get_list)++; + + return NS(mock_smartlist); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_get_all_nodes, nodelist_flag_not_running) + +/* + * Structural test for routerset_get_all_nodes, with a non-list routerset + * the running_only flag is set, but the nodes are not running. + */ + +NS_DECL(smartlist_t *, nodelist_get_list, (void)); + +smartlist_t *NS(mock_smartlist); +node_t NS(mock_node); + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + smartlist_t *out = smartlist_new(); + int r; + (void)arg; + + NS_MOCK(nodelist_get_list); + + smartlist_add(set->country_names, tor_strdup("{xx}")); + NS(mock_smartlist) = smartlist_new(); + NS(mock_node).is_running = 0; + smartlist_add(NS(mock_smartlist), (void *)&NS(mock_node)); + + routerset_get_all_nodes(out, set, NULL, 1); + r = smartlist_len(out); + routerset_free(set); + smartlist_free(out); + smartlist_free(NS(mock_smartlist)); + + tt_int_op(r, ==, 0); + tt_int_op(CALLED(nodelist_get_list), ==, 1); + + done: + ; +} + +smartlist_t * +NS(nodelist_get_list)(void) +{ + CALLED(nodelist_get_list)++; + + return NS(mock_smartlist); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE routerset_subtract_nodes + +/* + * Functional test for routerset_subtract_nodes. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = routerset_new(); + smartlist_t *list = smartlist_new(); + const char *nickname = "foo"; + routerinfo_t ri; + node_t mock_node; + (void)arg; + + strmap_set_lc(set->names, nickname, (void *)1); + + ri.nickname = (char *)nickname; + mock_node.rs = NULL; + mock_node.ri = &ri; + smartlist_add(list, (void *)&mock_node); + + tt_int_op(smartlist_len(list), !=, 0); + routerset_subtract_nodes(list, set); + + tt_int_op(smartlist_len(list), ==, 0); + done: + routerset_free(set); + smartlist_free(list); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_subtract_nodes, null_routerset) + +/* + * Functional test for routerset_subtract_nodes, with a NULL routerset. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = NULL; + smartlist_t *list = smartlist_new(); + const char *nickname = "foo"; + routerinfo_t ri; + node_t mock_node; + (void)arg; + + ri.nickname = (char *)nickname; + mock_node.ri = &ri; + smartlist_add(list, (void *)&mock_node); + + tt_int_op(smartlist_len(list), !=, 0); + routerset_subtract_nodes(list, set); + + tt_int_op(smartlist_len(list), !=, 0); + done: + routerset_free(set); + smartlist_free(list); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE routerset_to_string + +/* + * Functional test for routerset_to_string. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *set = NULL; + char *s = NULL; + (void)arg; + + set = NULL; + s = routerset_to_string(set); + tt_str_op(s, ==, ""); + tor_free(s); + + set = routerset_new(); + s = routerset_to_string(set); + tt_str_op(s, ==, ""); + tor_free(s); + routerset_free(set); set = NULL; + + set = routerset_new(); + smartlist_add(set->list, tor_strndup("a", 1)); + s = routerset_to_string(set); + tt_str_op(s, ==, "a"); + tor_free(s); + routerset_free(set); set = NULL; + + set = routerset_new(); + smartlist_add(set->list, tor_strndup("a", 1)); + smartlist_add(set->list, tor_strndup("b", 1)); + s = routerset_to_string(set); + tt_str_op(s, ==, "a,b"); + tor_free(s); + routerset_free(set); set = NULL; + + done: + tor_free(s); + routerset_free((routerset_t *)set); +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_equal, empty_empty) + +/* + * Functional test for routerset_equal, with both routersets empty. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *a = routerset_new(), *b = routerset_new(); + int r; + (void)arg; + + r = routerset_equal(a, b); + routerset_free(a); + routerset_free(b); + + tt_int_op(r, ==, 1); + + done: + ; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_equal, empty_not_empty) + +/* + * Functional test for routerset_equal, with one routersets empty. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *a = routerset_new(), *b = routerset_new(); + int r; + (void)arg; + + smartlist_add(b->list, tor_strdup("{xx}")); + r = routerset_equal(a, b); + routerset_free(a); + routerset_free(b); + + tt_int_op(r, ==, 0); + done: + ; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_equal, differing_lengths) + +/* + * Functional test for routerset_equal, with the routersets having + * differing lengths. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *a = routerset_new(), *b = routerset_new(); + int r; + (void)arg; + + smartlist_add(a->list, tor_strdup("{aa}")); + smartlist_add(b->list, tor_strdup("{b1}")); + smartlist_add(b->list, tor_strdup("{b2}")); + r = routerset_equal(a, b); + routerset_free(a); + routerset_free(b); + + tt_int_op(r, ==, 0); + done: + ; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_equal, unequal) + +/* + * Functional test for routerset_equal, with the routersets being + * different. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *a = routerset_new(), *b = routerset_new(); + int r; + (void)arg; + + smartlist_add(a->list, tor_strdup("foo")); + smartlist_add(b->list, tor_strdup("bar")); + r = routerset_equal(a, b); + routerset_free(a); + routerset_free(b); + + tt_int_op(r, ==, 0); + done: + ; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_equal, equal) + +/* + * Functional test for routerset_equal, with the routersets being + * equal. + */ + +static void +NS(test_main)(void *arg) +{ + routerset_t *a = routerset_new(), *b = routerset_new(); + int r; + (void)arg; + + smartlist_add(a->list, tor_strdup("foo")); + smartlist_add(b->list, tor_strdup("foo")); + r = routerset_equal(a, b); + routerset_free(a); + routerset_free(b); + + tt_int_op(r, ==, 1); + done: + ; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE ASPECT(routerset_free, null_routerset) + +/* + * Structural test for routerset_free, where the routerset is NULL. + */ + +NS_DECL(void, smartlist_free, (smartlist_t *sl)); + +static void +NS(test_main)(void *arg) +{ + (void)arg; + + NS_MOCK(smartlist_free); + + routerset_free(NULL); + + tt_int_op(CALLED(smartlist_free), ==, 0); + + done: + ; +} + +void +NS(smartlist_free)(smartlist_t *s) +{ + (void)s; + CALLED(smartlist_free)++; +} + +#undef NS_SUBMODULE +#define NS_SUBMODULE routerset_free + +/* + * Structural test for routerset_free. + */ + +NS_DECL(void, smartlist_free, (smartlist_t *sl)); +NS_DECL(void, strmap_free,(strmap_t *map, void (*free_val)(void*))); +NS_DECL(void, digestmap_free, (digestmap_t *map, void (*free_val)(void*))); + +static void +NS(test_main)(void *arg) +{ + routerset_t *routerset = routerset_new(); + (void)arg; + + NS_MOCK(smartlist_free); + NS_MOCK(strmap_free); + NS_MOCK(digestmap_free); + + routerset_free(routerset); + + tt_int_op(CALLED(smartlist_free), !=, 0); + tt_int_op(CALLED(strmap_free), !=, 0); + tt_int_op(CALLED(digestmap_free), !=, 0); + + done: + ; +} + +void +NS(smartlist_free)(smartlist_t *s) +{ + CALLED(smartlist_free)++; + smartlist_free__real(s); +} + +void +NS(strmap_free)(strmap_t *map, void (*free_val)(void*)) +{ + CALLED(strmap_free)++; + strmap_free__real(map, free_val); +} + +void +NS(digestmap_free)(digestmap_t *map, void (*free_val)(void*)) +{ + CALLED(digestmap_free)++; + digestmap_free__real(map, free_val); +} + +#undef NS_SUBMODULE + +struct testcase_t routerset_tests[] = { + TEST_CASE(routerset_new), + TEST_CASE(routerset_get_countryname), + TEST_CASE(routerset_is_list), + TEST_CASE(routerset_needs_geoip), + TEST_CASE(routerset_is_empty), + TEST_CASE_ASPECT(routerset_contains, null_set_or_null_set_list), + TEST_CASE_ASPECT(routerset_contains, set_and_nickname), + TEST_CASE_ASPECT(routerset_contains, set_and_null_nickname), + TEST_CASE_ASPECT(routerset_contains, set_and_no_nickname), + TEST_CASE_ASPECT(routerset_contains, set_and_digest), + TEST_CASE_ASPECT(routerset_contains, set_and_no_digest), + TEST_CASE_ASPECT(routerset_contains, set_and_null_digest), + TEST_CASE_ASPECT(routerset_contains, set_and_addr), + TEST_CASE_ASPECT(routerset_contains, set_and_no_addr), + TEST_CASE_ASPECT(routerset_contains, set_and_null_addr), + TEST_CASE_ASPECT(routerset_contains, countries_no_geoip), + TEST_CASE_ASPECT(routerset_contains, countries_geoip), + TEST_CASE_ASPECT(routerset_add_unknown_ccs, only_flag_and_no_ccs), + TEST_CASE_ASPECT(routerset_add_unknown_ccs, creates_set), + TEST_CASE_ASPECT(routerset_add_unknown_ccs, add_unknown), + TEST_CASE_ASPECT(routerset_add_unknown_ccs, add_a1), + TEST_CASE(routerset_contains_extendinfo), + TEST_CASE(routerset_contains_router), + TEST_CASE(routerset_contains_routerstatus), + TEST_CASE_ASPECT(routerset_contains_node, none), + TEST_CASE_ASPECT(routerset_contains_node, routerinfo), + TEST_CASE_ASPECT(routerset_contains_node, routerstatus), + TEST_CASE_ASPECT(routerset_get_all_nodes, no_routerset), + TEST_CASE_ASPECT(routerset_get_all_nodes, list_with_no_nodes), + TEST_CASE_ASPECT(routerset_get_all_nodes, list_flag_not_running), + TEST_CASE_ASPECT(routerset_get_all_nodes, list), + TEST_CASE_ASPECT(routerset_get_all_nodes, nodelist_with_no_nodes), + TEST_CASE_ASPECT(routerset_get_all_nodes, nodelist_flag_not_running), + TEST_CASE_ASPECT(routerset_refresh_counties, geoip_not_loaded), + TEST_CASE_ASPECT(routerset_refresh_counties, no_countries), + TEST_CASE_ASPECT(routerset_refresh_counties, one_valid_country), + TEST_CASE_ASPECT(routerset_refresh_counties, one_invalid_country), + TEST_CASE_ASPECT(routerset_union, source_bad), + TEST_CASE_ASPECT(routerset_union, one), + TEST_CASE_ASPECT(routerset_parse, malformed), + TEST_CASE_ASPECT(routerset_parse, valid_hexdigest), + TEST_CASE_ASPECT(routerset_parse, valid_nickname), + TEST_CASE_ASPECT(routerset_parse, get_countryname), + TEST_CASE_ASPECT(routerset_parse, policy), + TEST_CASE(routerset_subtract_nodes), + TEST_CASE_ASPECT(routerset_subtract_nodes, null_routerset), + TEST_CASE(routerset_to_string), + TEST_CASE_ASPECT(routerset_equal, empty_empty), + TEST_CASE_ASPECT(routerset_equal, empty_not_empty), + TEST_CASE_ASPECT(routerset_equal, differing_lengths), + TEST_CASE_ASPECT(routerset_equal, unequal), + TEST_CASE_ASPECT(routerset_equal, equal), + TEST_CASE_ASPECT(routerset_free, null_routerset), + TEST_CASE(routerset_free), + END_OF_TESTCASES +}; + diff --git a/src/test/test_status.c b/src/test/test_status.c index 46dd473132..8bc0152ffb 100644 --- a/src/test/test_status.c +++ b/src/test/test_status.c @@ -30,27 +30,24 @@ * global circuits. */ -struct global_circuitlist_s mock_global_circuitlist = - TOR_LIST_HEAD_INITIALIZER(global_circuitlist); +static smartlist_t * mock_global_circuitlist = NULL; -NS_DECL(struct global_circuitlist_s *, circuit_get_global_list, (void)); +NS_DECL(smartlist_t *, circuit_get_global_list, (void)); static void NS(test_main)(void *arg) { /* Choose origin_circuit_t wlog. */ origin_circuit_t *mock_circuit1, *mock_circuit2; - circuit_t *circ, *tmp; int expected_circuits = 2, actual_circuits; (void)arg; mock_circuit1 = tor_malloc_zero(sizeof(origin_circuit_t)); mock_circuit2 = tor_malloc_zero(sizeof(origin_circuit_t)); - TOR_LIST_INSERT_HEAD( - &mock_global_circuitlist, TO_CIRCUIT(mock_circuit1), head); - TOR_LIST_INSERT_HEAD( - &mock_global_circuitlist, TO_CIRCUIT(mock_circuit2), head); + mock_global_circuitlist = smartlist_new(); + smartlist_add(mock_global_circuitlist, TO_CIRCUIT(mock_circuit1)); + smartlist_add(mock_global_circuitlist, TO_CIRCUIT(mock_circuit2)); NS_MOCK(circuit_get_global_list); @@ -58,17 +55,18 @@ NS(test_main)(void *arg) tt_assert(expected_circuits == actual_circuits); - done: - TOR_LIST_FOREACH_SAFE( - circ, NS(circuit_get_global_list)(), head, tmp); - tor_free(circ); - NS_UNMOCK(circuit_get_global_list); + done: + tor_free(mock_circuit1); + tor_free(mock_circuit2); + smartlist_free(mock_global_circuitlist); + mock_global_circuitlist = NULL; + NS_UNMOCK(circuit_get_global_list); } -static struct global_circuitlist_s * +static smartlist_t * NS(circuit_get_global_list)(void) { - return &mock_global_circuitlist; + return mock_global_circuitlist; } #undef NS_SUBMODULE diff --git a/src/test/test_util.c b/src/test/test_util.c index 151ec69127..1b7c936fd7 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -87,6 +87,20 @@ test_util_read_file_eof_tiny_limit(void *arg) } static void +test_util_read_file_eof_one_loop_a(void *arg) +{ + (void)arg; + test_util_read_until_eof_impl("tor_test_fifo_1ka", 1024, 1023); +} + +static void +test_util_read_file_eof_one_loop_b(void *arg) +{ + (void)arg; + test_util_read_until_eof_impl("tor_test_fifo_1kb", 1024, 1024); +} + +static void test_util_read_file_eof_two_loops(void *arg) { (void)arg; @@ -98,6 +112,14 @@ test_util_read_file_eof_two_loops(void *arg) } static void +test_util_read_file_eof_two_loops_b(void *arg) +{ + (void)arg; + + test_util_read_until_eof_impl("tor_test_fifo_2kb", 2048, 2048); +} + +static void test_util_read_file_eof_zero_bytes(void *arg) { (void)arg; @@ -1383,12 +1405,6 @@ test_util_threads(void) tv.tv_sec=0; tv.tv_usec=100*1000; #endif -#ifndef TOR_IS_MULTITHREADED - /* Skip this test if we aren't threading. We should be threading most - * everywhere by now. */ - if (1) - return; -#endif thread_test_mutex_ = tor_mutex_new(); thread_test_start1_ = tor_mutex_new(); thread_test_start2_ = tor_mutex_new(); @@ -1493,7 +1509,7 @@ test_util_gzip(void) /* Check whether we can uncompress concatenated, compressed strings. */ tor_free(buf3); - buf2 = tor_realloc(buf2, len1*2); + buf2 = tor_reallocarray(buf2, len1, 2); memcpy(buf2+len1, buf2, len1); test_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1*2, ZLIB_METHOD, 1, LOG_INFO)); @@ -2391,6 +2407,54 @@ test_util_parent_dir(void *ptr) tor_free(cp); } +static void +test_util_ftruncate(void *ptr) +{ + char *buf = NULL; + const char *fname; + int fd = -1; + const char *message = "Hello world"; + const char *message2 = "Hola mundo"; + struct stat st; + + (void) ptr; + + fname = get_fname("ftruncate"); + + fd = tor_open_cloexec(fname, O_WRONLY|O_CREAT, 0600); + tt_int_op(fd, >=, 0); + + /* Make the file be there. */ + tt_int_op(strlen(message), ==, write_all(fd, message, strlen(message), 0)); + tt_int_op((int)tor_fd_getpos(fd), ==, strlen(message)); + tt_int_op(0, ==, fstat(fd, &st)); + tt_int_op((int)st.st_size, ==, strlen(message)); + + /* Truncate and see if it got truncated */ + tt_int_op(0, ==, tor_ftruncate(fd)); + tt_int_op((int)tor_fd_getpos(fd), ==, 0); + tt_int_op(0, ==, fstat(fd, &st)); + tt_int_op((int)st.st_size, ==, 0); + + /* Replace, and see if it got replaced */ + tt_int_op(strlen(message2), ==, + write_all(fd, message2, strlen(message2), 0)); + tt_int_op((int)tor_fd_getpos(fd), ==, strlen(message2)); + tt_int_op(0, ==, fstat(fd, &st)); + tt_int_op((int)st.st_size, ==, strlen(message2)); + + close(fd); + fd = -1; + + buf = read_file_to_str(fname, 0, NULL); + tt_str_op(message2, ==, buf); + + done: + if (fd >= 0) + close(fd); + tor_free(buf); +} + #ifdef _WIN32 static void test_util_load_win_lib(void *ptr) @@ -2453,8 +2517,9 @@ test_util_exit_status(void *ptr) #endif #ifndef _WIN32 -/** Check that fgets waits until a full line, and not return a partial line, on - * a EAGAIN with a non-blocking pipe */ +/* Check that fgets with a non-blocking pipe returns partial lines and sets + * EAGAIN, returns full lines and sets no error, and returns NULL on EOF and + * sets no error */ static void test_util_fgets_eagain(void *ptr) { @@ -2463,17 +2528,19 @@ test_util_fgets_eagain(void *ptr) ssize_t retlen; char *retptr; FILE *test_stream = NULL; - char buf[10]; + char buf[4] = { 0 }; (void)ptr; + errno = 0; + /* Set up a pipe to test on */ retval = pipe(test_pipe); - tt_int_op(retval, >=, 0); + tt_int_op(retval, ==, 0); /* Set up the read-end to be non-blocking */ retval = fcntl(test_pipe[0], F_SETFL, O_NONBLOCK); - tt_int_op(retval, >=, 0); + tt_int_op(retval, ==, 0); /* Open it as a stdio stream */ test_stream = fdopen(test_pipe[0], "r"); @@ -2483,51 +2550,69 @@ test_util_fgets_eagain(void *ptr) retlen = write(test_pipe[1], "A", 1); tt_int_op(retlen, ==, 1); retptr = fgets(buf, sizeof(buf), test_stream); - tt_want(retptr == NULL); tt_int_op(errno, ==, EAGAIN); + tt_ptr_op(retptr, ==, buf); + tt_str_op(buf, ==, "A"); + errno = 0; /* Send in the rest */ retlen = write(test_pipe[1], "B\n", 2); tt_int_op(retlen, ==, 2); retptr = fgets(buf, sizeof(buf), test_stream); + tt_int_op(errno, ==, 0); tt_ptr_op(retptr, ==, buf); - tt_str_op(buf, ==, "AB\n"); + tt_str_op(buf, ==, "B\n"); + errno = 0; /* Send in a full line */ retlen = write(test_pipe[1], "CD\n", 3); tt_int_op(retlen, ==, 3); retptr = fgets(buf, sizeof(buf), test_stream); + tt_int_op(errno, ==, 0); tt_ptr_op(retptr, ==, buf); tt_str_op(buf, ==, "CD\n"); + errno = 0; /* Send in a partial line */ retlen = write(test_pipe[1], "E", 1); tt_int_op(retlen, ==, 1); retptr = fgets(buf, sizeof(buf), test_stream); - tt_ptr_op(retptr, ==, NULL); tt_int_op(errno, ==, EAGAIN); + tt_ptr_op(retptr, ==, buf); + tt_str_op(buf, ==, "E"); + errno = 0; /* Send in the rest */ retlen = write(test_pipe[1], "F\n", 2); tt_int_op(retlen, ==, 2); retptr = fgets(buf, sizeof(buf), test_stream); + tt_int_op(errno, ==, 0); tt_ptr_op(retptr, ==, buf); - tt_str_op(buf, ==, "EF\n"); + tt_str_op(buf, ==, "F\n"); + errno = 0; /* Send in a full line and close */ retlen = write(test_pipe[1], "GH", 2); tt_int_op(retlen, ==, 2); retval = close(test_pipe[1]); - test_pipe[1] = -1; tt_int_op(retval, ==, 0); + test_pipe[1] = -1; retptr = fgets(buf, sizeof(buf), test_stream); + tt_int_op(errno, ==, 0); tt_ptr_op(retptr, ==, buf); tt_str_op(buf, ==, "GH"); + errno = 0; /* Check for EOF */ retptr = fgets(buf, sizeof(buf), test_stream); + tt_int_op(errno, ==, 0); tt_ptr_op(retptr, ==, NULL); - tt_int_op(feof(test_stream), >, 0); + retval = feof(test_stream); + tt_int_op(retval, !=, 0); + errno = 0; + + /* Check that buf is unchanged according to C99 and C11 */ + tt_str_op(buf, ==, "GH"); done: if (test_stream != NULL) @@ -3783,12 +3868,13 @@ struct testcase_t util_tests[] = { UTIL_TEST(asprintf, 0), UTIL_TEST(listdir, 0), UTIL_TEST(parent_dir, 0), + UTIL_TEST(ftruncate, 0), #ifdef _WIN32 UTIL_TEST(load_win_lib, 0), #endif #ifndef _WIN32 UTIL_TEST(exit_status, 0), - UTIL_TEST(fgets_eagain, TT_SKIP), + UTIL_TEST(fgets_eagain, 0), #endif UTIL_TEST(spawn_background_ok, 0), UTIL_TEST(spawn_background_fail, 0), @@ -3806,7 +3892,10 @@ struct testcase_t util_tests[] = { UTIL_TEST(make_environment, 0), UTIL_TEST(set_env_var_in_sl, 0), UTIL_TEST(read_file_eof_tiny_limit, 0), + UTIL_TEST(read_file_eof_one_loop_a, 0), + UTIL_TEST(read_file_eof_one_loop_b, 0), UTIL_TEST(read_file_eof_two_loops, 0), + UTIL_TEST(read_file_eof_two_loops_b, 0), UTIL_TEST(read_file_eof_zero_bytes, 0), UTIL_TEST(write_chunks_to_file, 0), UTIL_TEST(mathlog, 0), |