diff options
Diffstat (limited to 'src/test/test_dir.c')
-rw-r--r-- | src/test/test_dir.c | 1590 |
1 files changed, 1164 insertions, 426 deletions
diff --git a/src/test/test_dir.c b/src/test/test_dir.c index cdc56acb89..b920655db5 100644 --- a/src/test/test_dir.c +++ b/src/test/test_dir.c @@ -1,12 +1,13 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2016, The Tor Project, Inc. */ + * Copyright (c) 2007-2017, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" #include <math.h> #define CONFIG_PRIVATE +#define CONTROL_PRIVATE #define DIRSERV_PRIVATE #define DIRVOTE_PRIVATE #define ROUTER_PRIVATE @@ -17,12 +18,15 @@ #define RELAY_PRIVATE #include "or.h" +#include "bridges.h" #include "confparse.h" #include "config.h" +#include "control.h" #include "crypto_ed25519.h" #include "directory.h" #include "dirserv.h" #include "dirvote.h" +#include "entrynodes.h" #include "hibernate.h" #include "memarea.h" #include "networkstatus.h" @@ -272,8 +276,8 @@ test_dir_formats(void *arg) tt_int_op(rp1->bandwidthrate,OP_EQ, r1->bandwidthrate); tt_int_op(rp1->bandwidthburst,OP_EQ, r1->bandwidthburst); tt_int_op(rp1->bandwidthcapacity,OP_EQ, r1->bandwidthcapacity); - tt_assert(crypto_pk_cmp_keys(rp1->onion_pkey, pk1) == 0); - tt_assert(crypto_pk_cmp_keys(rp1->identity_pkey, pk2) == 0); + tt_int_op(crypto_pk_cmp_keys(rp1->onion_pkey, pk1), OP_EQ, 0); + tt_int_op(crypto_pk_cmp_keys(rp1->identity_pkey, pk2), OP_EQ, 0); tt_assert(rp1->supports_tunnelled_dir_requests); //tt_assert(rp1->exit_policy == NULL); tor_free(buf); @@ -291,9 +295,9 @@ test_dir_formats(void *arg) strlcat(buf2, "master-key-ed25519 ", sizeof(buf2)); { char k[ED25519_BASE64_LEN+1]; - tt_assert(ed25519_public_to_base64(k, - &r2->cache_info.signing_key_cert->signing_key) - >= 0); + tt_int_op(ed25519_public_to_base64(k, + &r2->cache_info.signing_key_cert->signing_key), + OP_GE, 0); strlcat(buf2, k, sizeof(buf2)); strlcat(buf2, "\n", sizeof(buf2)); } @@ -328,7 +332,7 @@ test_dir_formats(void *arg) ntor_cc = make_ntor_onion_key_crosscert(&r2_onion_keypair, &kp1.pubkey, r2->cache_info.published_on, - MIN_ONION_KEY_LIFETIME, + get_onion_key_lifetime(), &ntor_cc_sign); tt_assert(ntor_cc); base64_encode(cert_buf, sizeof(cert_buf), @@ -389,8 +393,8 @@ test_dir_formats(void *arg) tt_mem_op(rp2->onion_curve25519_pkey->public_key,OP_EQ, r2->onion_curve25519_pkey->public_key, CURVE25519_PUBKEY_LEN); - tt_assert(crypto_pk_cmp_keys(rp2->onion_pkey, pk2) == 0); - tt_assert(crypto_pk_cmp_keys(rp2->identity_pkey, pk1) == 0); + tt_int_op(crypto_pk_cmp_keys(rp2->onion_pkey, pk2), OP_EQ, 0); + tt_int_op(crypto_pk_cmp_keys(rp2->identity_pkey, pk1), OP_EQ, 0); tt_assert(rp2->supports_tunnelled_dir_requests); tt_int_op(smartlist_len(rp2->exit_policy),OP_EQ, 2); @@ -419,7 +423,7 @@ test_dir_formats(void *arg) add_fingerprint_to_dir(buf, fingerprint_list, 0); } -#endif +#endif /* 0 */ dirserv_free_fingerprint_list(); done: @@ -475,34 +479,34 @@ test_dir_routerinfo_parsing(void *arg) routerinfo_free(ri); ri = router_parse_entry_from_string(EX_RI_MINIMAL, NULL, 0, 0, "@purpose bridge\n", NULL); - tt_assert(ri != NULL); + tt_ptr_op(ri, OP_NE, NULL); tt_assert(ri->purpose == ROUTER_PURPOSE_BRIDGE); routerinfo_free(ri); /* bad annotations prepended. */ ri = router_parse_entry_from_string(EX_RI_MINIMAL, NULL, 0, 0, "@purpose\n", NULL); - tt_assert(ri == NULL); + tt_ptr_op(ri, OP_EQ, NULL); /* bad annotations on router. */ ri = router_parse_entry_from_string("@purpose\nrouter x\n", NULL, 0, 1, NULL, NULL); - tt_assert(ri == NULL); + tt_ptr_op(ri, OP_EQ, NULL); /* unwanted annotations on router. */ ri = router_parse_entry_from_string("@purpose foo\nrouter x\n", NULL, 0, 0, NULL, NULL); - tt_assert(ri == NULL); + tt_ptr_op(ri, OP_EQ, NULL); /* No signature. */ ri = router_parse_entry_from_string("router x\n", NULL, 0, 0, NULL, NULL); - tt_assert(ri == NULL); + tt_ptr_op(ri, OP_EQ, NULL); /* Not a router */ routerinfo_free(ri); ri = router_parse_entry_from_string("hello\n", NULL, 0, 0, NULL, NULL); - tt_assert(ri == NULL); + tt_ptr_op(ri, OP_EQ, NULL); CHECK_FAIL(EX_RI_BAD_SIG1, 1); CHECK_FAIL(EX_RI_BAD_SIG2, 1); @@ -629,11 +633,11 @@ test_dir_extrainfo_parsing(void *arg) ADD(EX_EI_ED_MISPLACED_SIG); CHECK_OK(EX_EI_MINIMAL); - tt_assert(!ei->pending_sig); + tt_ptr_op(ei->pending_sig, OP_EQ, NULL); CHECK_OK(EX_EI_MAXIMAL); - tt_assert(!ei->pending_sig); + tt_ptr_op(ei->pending_sig, OP_EQ, NULL); CHECK_OK(EX_EI_GOOD_ED_EI); - tt_assert(!ei->pending_sig); + tt_ptr_op(ei->pending_sig, OP_EQ, NULL); CHECK_FAIL(EX_EI_BAD_SIG1,1); CHECK_FAIL(EX_EI_BAD_SIG2,1); @@ -678,16 +682,16 @@ test_dir_parse_router_list(void *arg) routerinfo_t *ri = NULL; char d[DIGEST_LEN]; - smartlist_add(chunks, tor_strdup(EX_RI_MINIMAL)); // ri 0 - smartlist_add(chunks, tor_strdup(EX_RI_BAD_PORTS)); // bad ri 0 - smartlist_add(chunks, tor_strdup(EX_EI_MAXIMAL)); // ei 0 - smartlist_add(chunks, tor_strdup(EX_EI_BAD_SIG2)); // bad ei -- - smartlist_add(chunks, tor_strdup(EX_EI_BAD_NICKNAME));// bad ei 0 - smartlist_add(chunks, tor_strdup(EX_RI_BAD_SIG1)); // bad ri -- - smartlist_add(chunks, tor_strdup(EX_EI_BAD_PUBLISHED)); // bad ei 1 - smartlist_add(chunks, tor_strdup(EX_RI_MAXIMAL)); // ri 1 - smartlist_add(chunks, tor_strdup(EX_RI_BAD_FAMILY)); // bad ri 1 - smartlist_add(chunks, tor_strdup(EX_EI_MINIMAL)); // ei 1 + smartlist_add_strdup(chunks, EX_RI_MINIMAL); // ri 0 + smartlist_add_strdup(chunks, EX_RI_BAD_PORTS); // bad ri 0 + smartlist_add_strdup(chunks, EX_EI_MAXIMAL); // ei 0 + smartlist_add_strdup(chunks, EX_EI_BAD_SIG2); // bad ei -- + smartlist_add_strdup(chunks, EX_EI_BAD_NICKNAME);// bad ei 0 + smartlist_add_strdup(chunks, EX_RI_BAD_SIG1); // bad ri -- + smartlist_add_strdup(chunks, EX_EI_BAD_PUBLISHED); // bad ei 1 + smartlist_add_strdup(chunks, EX_RI_MAXIMAL); // ri 1 + smartlist_add_strdup(chunks, EX_RI_BAD_FAMILY); // bad ri 1 + smartlist_add_strdup(chunks, EX_EI_MINIMAL); // ei 1 list = smartlist_join_strings(chunks, "", 0, NULL); @@ -812,19 +816,19 @@ test_dir_load_routers(void *arg) #define ADD(str) \ do { \ tt_int_op(0,OP_EQ,router_get_router_hash(str, strlen(str), buf)); \ - smartlist_add(wanted, tor_strdup(hex_str(buf, DIGEST_LEN))); \ + smartlist_add_strdup(wanted, hex_str(buf, DIGEST_LEN)); \ } while (0) MOCK(router_get_dl_status_by_descriptor_digest, mock_router_get_dl_status); update_approx_time(1412510400); - smartlist_add(chunks, tor_strdup(EX_RI_MINIMAL)); - smartlist_add(chunks, tor_strdup(EX_RI_BAD_FINGERPRINT)); - smartlist_add(chunks, tor_strdup(EX_RI_BAD_SIG2)); - smartlist_add(chunks, tor_strdup(EX_RI_MAXIMAL)); - smartlist_add(chunks, tor_strdup(EX_RI_BAD_PORTS)); - smartlist_add(chunks, tor_strdup(EX_RI_BAD_TOKENS)); + smartlist_add_strdup(chunks, EX_RI_MINIMAL); + smartlist_add_strdup(chunks, EX_RI_BAD_FINGERPRINT); + smartlist_add_strdup(chunks, EX_RI_BAD_SIG2); + smartlist_add_strdup(chunks, EX_RI_MAXIMAL); + smartlist_add_strdup(chunks, EX_RI_BAD_PORTS); + smartlist_add_strdup(chunks, EX_RI_BAD_TOKENS); /* not ADDing MINIMIAL */ ADD(EX_RI_MAXIMAL); @@ -909,6 +913,23 @@ mock_get_by_ei_desc_digest(const char *d) } } +static signed_descriptor_t * +mock_ei_get_by_ei_digest(const char *d) +{ + char hex[HEX_DIGEST_LEN+1]; + base16_encode(hex, sizeof(hex), d, DIGEST_LEN); + signed_descriptor_t *sd = &sd_ei_minimal; + + if (!strcmp(hex, "11E0EDF526950739F7769810FCACAB8C882FAEEE")) { + sd->signed_descriptor_body = (char *)EX_EI_MINIMAL; + sd->signed_descriptor_len = sizeof(EX_EI_MINIMAL); + sd->annotations_len = 0; + sd->saved_location = SAVED_NOWHERE; + return sd; + } + return NULL; +} + static smartlist_t *mock_ei_insert_list = NULL; static was_router_added_t mock_ei_insert(routerlist_t *rl, extrainfo_t *ei, int warn_if_incompatible) @@ -932,18 +953,18 @@ test_dir_load_extrainfo(void *arg) #define ADD(str) \ do { \ tt_int_op(0,OP_EQ,router_get_extrainfo_hash(str, strlen(str), buf)); \ - smartlist_add(wanted, tor_strdup(hex_str(buf, DIGEST_LEN))); \ + smartlist_add_strdup(wanted, hex_str(buf, DIGEST_LEN)); \ } while (0) mock_ei_insert_list = smartlist_new(); MOCK(router_get_by_extrainfo_digest, mock_get_by_ei_desc_digest); MOCK(extrainfo_insert, mock_ei_insert); - smartlist_add(chunks, tor_strdup(EX_EI_MINIMAL)); - smartlist_add(chunks, tor_strdup(EX_EI_BAD_NICKNAME)); - smartlist_add(chunks, tor_strdup(EX_EI_MAXIMAL)); - smartlist_add(chunks, tor_strdup(EX_EI_BAD_PUBLISHED)); - smartlist_add(chunks, tor_strdup(EX_EI_BAD_TOKENS)); + smartlist_add_strdup(chunks, EX_EI_MINIMAL); + smartlist_add_strdup(chunks, EX_EI_BAD_NICKNAME); + smartlist_add_strdup(chunks, EX_EI_MAXIMAL); + smartlist_add_strdup(chunks, EX_EI_BAD_PUBLISHED); + smartlist_add_strdup(chunks, EX_EI_BAD_TOKENS); /* not ADDing MINIMIAL */ ADD(EX_EI_MAXIMAL); @@ -998,6 +1019,37 @@ test_dir_load_extrainfo(void *arg) } static void +test_dir_getinfo_extra(void *arg) +{ + int r; + char *answer = NULL; + const char *errmsg = NULL; + + (void)arg; + MOCK(extrainfo_get_by_descriptor_digest, mock_ei_get_by_ei_digest); + r = getinfo_helper_dir(NULL, "extra-info/digest/" + "11E0EDF526950739F7769810FCACAB8C882FAEEE", &answer, + &errmsg); + tt_int_op(0, OP_EQ, r); + tt_ptr_op(NULL, OP_EQ, errmsg); + tt_str_op(answer, OP_EQ, EX_EI_MINIMAL); + tor_free(answer); + + answer = NULL; + r = getinfo_helper_dir(NULL, "extra-info/digest/" + "NOTAVALIDHEXSTRINGNOTAVALIDHEXSTRINGNOTA", &answer, + &errmsg); + tt_int_op(0, OP_EQ, r); + /* getinfo_helper_dir() should maybe return an error here but doesn't */ + tt_ptr_op(NULL, OP_EQ, errmsg); + /* In any case, there should be no answer for an invalid hex string. */ + tt_ptr_op(NULL, OP_EQ, answer); + + done: + UNMOCK(extrainfo_get_by_descriptor_digest); +} + +static void test_dir_versions(void *arg) { tor_version_t ver1; @@ -1064,6 +1116,7 @@ test_dir_versions(void *arg) tt_int_op(0, OP_EQ, ver1.patchlevel); tt_int_op(VER_RELEASE, OP_EQ, ver1.status); tt_str_op("alpha", OP_EQ, ver1.status_tag); + /* Go through the full set of status tags */ tt_int_op(0, OP_EQ, tor_version_parse("2.1.700-alpha", &ver1)); tt_int_op(2, OP_EQ, ver1.major); tt_int_op(1, OP_EQ, ver1.minor); @@ -1078,6 +1131,60 @@ test_dir_versions(void *arg) tt_int_op(0, OP_EQ, ver1.patchlevel); tt_int_op(VER_RELEASE, OP_EQ, ver1.status); tt_str_op("alpha-dev", OP_EQ, ver1.status_tag); + tt_int_op(0, OP_EQ, tor_version_parse("0.2.9.5-rc", &ver1)); + tt_int_op(0, OP_EQ, ver1.major); + tt_int_op(2, OP_EQ, ver1.minor); + tt_int_op(9, OP_EQ, ver1.micro); + tt_int_op(5, OP_EQ, ver1.patchlevel); + tt_int_op(VER_RELEASE, OP_EQ, ver1.status); + tt_str_op("rc", OP_EQ, ver1.status_tag); + tt_int_op(0, OP_EQ, tor_version_parse("0.2.9.6-rc-dev", &ver1)); + tt_int_op(0, OP_EQ, ver1.major); + tt_int_op(2, OP_EQ, ver1.minor); + tt_int_op(9, OP_EQ, ver1.micro); + tt_int_op(6, OP_EQ, ver1.patchlevel); + tt_int_op(VER_RELEASE, OP_EQ, ver1.status); + tt_str_op("rc-dev", OP_EQ, ver1.status_tag); + tt_int_op(0, OP_EQ, tor_version_parse("0.2.9.8", &ver1)); + tt_int_op(0, OP_EQ, ver1.major); + tt_int_op(2, OP_EQ, ver1.minor); + tt_int_op(9, OP_EQ, ver1.micro); + tt_int_op(8, OP_EQ, ver1.patchlevel); + tt_int_op(VER_RELEASE, OP_EQ, ver1.status); + tt_str_op("", OP_EQ, ver1.status_tag); + tt_int_op(0, OP_EQ, tor_version_parse("0.2.9.9-dev", &ver1)); + tt_int_op(0, OP_EQ, ver1.major); + tt_int_op(2, OP_EQ, ver1.minor); + tt_int_op(9, OP_EQ, ver1.micro); + tt_int_op(9, OP_EQ, ver1.patchlevel); + tt_int_op(VER_RELEASE, OP_EQ, ver1.status); + tt_str_op("dev", OP_EQ, ver1.status_tag); + /* In #21450, we fixed an inconsistency in parsing versions > INT32_MAX + * between i386 and x86_64, as we used tor_parse_long, and then cast to int + */ + tt_int_op(0, OP_EQ, tor_version_parse("0.2147483647.0", &ver1)); + tt_int_op(0, OP_EQ, ver1.major); + tt_int_op(2147483647, OP_EQ, ver1.minor); + tt_int_op(0, OP_EQ, ver1.micro); + tt_int_op(0, OP_EQ, ver1.patchlevel); + tt_int_op(VER_RELEASE, OP_EQ, ver1.status); + tt_str_op("", OP_EQ, ver1.status_tag); + tt_int_op(-1, OP_EQ, tor_version_parse("0.2147483648.0", &ver1)); + tt_int_op(-1, OP_EQ, tor_version_parse("0.4294967295.0", &ver1)); + /* In #21278, we reject negative version components */ + tt_int_op(-1, OP_EQ, tor_version_parse("0.-1.0", &ver1)); + tt_int_op(-1, OP_EQ, tor_version_parse("0.-2147483648.0", &ver1)); + tt_int_op(-1, OP_EQ, tor_version_parse("0.-4294967295.0", &ver1)); + /* In #21507, we reject version components with non-numeric prefixes */ + tt_int_op(-1, OP_EQ, tor_version_parse("0.-0.0", &ver1)); + tt_int_op(-1, OP_EQ, tor_version_parse("+1.0.0", &ver1)); + /* use the list in isspace() */ + tt_int_op(-1, OP_EQ, tor_version_parse("0.\t0.0", &ver1)); + tt_int_op(-1, OP_EQ, tor_version_parse("0.\n0.0", &ver1)); + tt_int_op(-1, OP_EQ, tor_version_parse("0.\v0.0", &ver1)); + tt_int_op(-1, OP_EQ, tor_version_parse("0.\f0.0", &ver1)); + tt_int_op(-1, OP_EQ, tor_version_parse("0.\r0.0", &ver1)); + tt_int_op(-1, OP_EQ, tor_version_parse("0. 0.0", &ver1)); #define tt_versionstatus_op(vs1, op, vs2) \ tt_assert_test_type(vs1,vs2,#vs1" "#op" "#vs2,version_status_t, \ @@ -1097,6 +1204,7 @@ test_dir_versions(void *arg) test_v_i_o(VS_RECOMMENDED, "0.0.7rc2", "0.0.7,Tor 0.0.7rc2,Tor 0.0.8"); test_v_i_o(VS_OLD, "0.0.5.0", "0.0.5.1-cvs"); test_v_i_o(VS_NEW_IN_SERIES, "0.0.5.1-cvs", "0.0.5, 0.0.6"); + test_v_i_o(VS_NEW, "0.2.9.9-dev", "0.2.9.9"); /* Not on list, but newer than any in same series. */ test_v_i_o(VS_NEW_IN_SERIES, "0.1.0.3", "Tor 0.1.0.2,Tor 0.0.9.5,Tor 0.1.1.0"); @@ -1135,6 +1243,70 @@ test_dir_versions(void *arg) "Tor 0.2.1.0-dev (r99)")); tt_int_op(1,OP_EQ, tor_version_as_new_as("Tor 0.2.1.1", "Tor 0.2.1.0-dev (r99)")); + /* And git revisions */ + tt_int_op(1,OP_EQ, tor_version_as_new_as( + "Tor 0.2.9.9 (git-56788a2489127072)", + "Tor 0.2.9.9 (git-56788a2489127072)")); + /* a git revision is newer than no git revision */ + tt_int_op(1,OP_EQ, tor_version_as_new_as( + "Tor 0.2.9.9 (git-56788a2489127072)", + "Tor 0.2.9.9")); + /* a longer git revision is newer than a shorter git revision + * this should be true if they prefix-match, but if they don't, they are + * incomparable, because hashes aren't ordered (but we compare their bytes + * anyway) */ + tt_int_op(1,OP_EQ, tor_version_as_new_as( + "Tor 0.2.9.9 (git-56788a2489127072d513cf4baf35a8ff475f3c7b)", + "Tor 0.2.9.9 (git-56788a2489127072)")); + tt_int_op(1,OP_EQ, tor_version_as_new_as( + "Tor 0.2.9.9 (git-0102)", + "Tor 0.2.9.9 (git-03)")); + tt_int_op(1,OP_EQ, tor_version_as_new_as( + "Tor 0.2.9.9 (git-0102)", + "Tor 0.2.9.9 (git-00)")); + tt_int_op(1,OP_EQ, tor_version_as_new_as( + "Tor 0.2.9.9 (git-01)", + "Tor 0.2.9.9 (git-00)")); + tt_int_op(0,OP_EQ, tor_version_as_new_as( + "Tor 0.2.9.9 (git-00)", + "Tor 0.2.9.9 (git-01)")); + /* In #21278, we comapre without integer overflows. + * But since #21450 limits version components to [0, INT32_MAX], it is no + * longer possible to cause an integer overflow in tor_version_compare() */ + tt_int_op(0,OP_EQ, tor_version_as_new_as( + "Tor 0.0.0.0", + "Tor 2147483647.0.0.0")); + tt_int_op(1,OP_EQ, tor_version_as_new_as( + "Tor 2147483647.0.0.0", + "Tor 0.0.0.0")); + /* These versions used to cause an overflow, now they don't parse + * (and authorities reject their descriptors), and log a BUG message */ + setup_full_capture_of_logs(LOG_WARN); + tt_int_op(0,OP_EQ, tor_version_as_new_as( + "Tor 0.0.0.0", + "Tor 0.-2147483648.0.0")); + expect_single_log_msg_containing("unparseable"); + mock_clean_saved_logs(); + tt_int_op(0,OP_EQ, tor_version_as_new_as( + "Tor 0.2147483647.0.0", + "Tor 0.-1.0.0")); + expect_single_log_msg_containing("unparseable"); + mock_clean_saved_logs(); + tt_int_op(0,OP_EQ, tor_version_as_new_as( + "Tor 0.2147483647.0.0", + "Tor 0.-2147483648.0.0")); + expect_single_log_msg_containing("unparseable"); + mock_clean_saved_logs(); + tt_int_op(1,OP_EQ, tor_version_as_new_as( + "Tor 4294967295.0.0.0", + "Tor 0.0.0.0")); + expect_no_log_entry(); + tt_int_op(0,OP_EQ, tor_version_as_new_as( + "Tor 0.4294967295.0.0", + "Tor 0.-4294967295.0.0")); + expect_single_log_msg_containing("unparseable"); + mock_clean_saved_logs(); + teardown_capture_of_logs(); /* Now try git revisions */ tt_int_op(0,OP_EQ, tor_version_parse("0.5.6.7 (git-ff00ff)", &ver1)); @@ -1144,11 +1316,24 @@ test_dir_versions(void *arg) tt_int_op(7,OP_EQ, ver1.patchlevel); tt_int_op(3,OP_EQ, ver1.git_tag_len); tt_mem_op(ver1.git_tag,OP_EQ, "\xff\x00\xff", 3); + /* reject bad hex digits */ tt_int_op(-1,OP_EQ, tor_version_parse("0.5.6.7 (git-ff00xx)", &ver1)); + /* reject odd hex digit count */ tt_int_op(-1,OP_EQ, tor_version_parse("0.5.6.7 (git-ff00fff)", &ver1)); + /* ignore "git " */ tt_int_op(0,OP_EQ, tor_version_parse("0.5.6.7 (git ff00fff)", &ver1)); + /* standard length is 16 hex digits */ + tt_int_op(0,OP_EQ, tor_version_parse("0.5.6.7 (git-0010203040506070)", + &ver1)); + /* length limit is 40 hex digits */ + tt_int_op(0,OP_EQ, tor_version_parse( + "0.5.6.7 (git-000102030405060708090a0b0c0d0e0f10111213)", + &ver1)); + tt_int_op(-1,OP_EQ, tor_version_parse( + "0.5.6.7 (git-000102030405060708090a0b0c0d0e0f1011121314)", + &ver1)); done: - ; + teardown_capture_of_logs(); } /** Run unit tests for directory fp_pair functions. */ @@ -1353,12 +1538,12 @@ test_dir_measured_bw_kb(void *arg) (void)arg; for (i = 0; strcmp(lines_fail[i], "end"); i++) { //fprintf(stderr, "Testing: %s\n", lines_fail[i]); - tt_assert(measured_bw_line_parse(&mbwl, lines_fail[i]) == -1); + tt_int_op(measured_bw_line_parse(&mbwl, lines_fail[i]), OP_EQ, -1); } for (i = 0; strcmp(lines_pass[i], "end"); i++) { //fprintf(stderr, "Testing: %s %d\n", lines_pass[i], TOR_ISSPACE('\n')); - tt_assert(measured_bw_line_parse(&mbwl, lines_pass[i]) == 0); + tt_int_op(measured_bw_line_parse(&mbwl, lines_pass[i]), OP_EQ, 0); tt_assert(mbwl.bw_kb == 1024); tt_assert(strcmp(mbwl.node_hex, "557365204145532d32353620696e73746561642e") == 0); @@ -1493,6 +1678,15 @@ test_dir_param_voting(void *arg) tt_int_op(-8,OP_EQ, networkstatus_get_param(&vote4, "ab", -12, -100, -8)); tt_int_op(0,OP_EQ, networkstatus_get_param(&vote4, "foobar", 0, -100, 8)); + tt_int_op(100,OP_EQ, networkstatus_get_overridable_param( + &vote4, -1, "x-yz", 50, 0, 300)); + tt_int_op(30,OP_EQ, networkstatus_get_overridable_param( + &vote4, 30, "x-yz", 50, 0, 300)); + tt_int_op(0,OP_EQ, networkstatus_get_overridable_param( + &vote4, -101, "foobar", 0, -100, 8)); + tt_int_op(-99,OP_EQ, networkstatus_get_overridable_param( + &vote4, -99, "foobar", 0, -100, 8)); + smartlist_add(votes, &vote1); /* Do the first tests without adding all the other votes, for @@ -1592,7 +1786,7 @@ test_dir_param_voting_lookup(void *arg) dirvote_get_intermediate_param_value(lst, "moomin", -100)); tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_EQ, 1); tt_str_op(smartlist_get(tor_get_captured_bug_log_(), 0), OP_EQ, - "!(n_found > 1)"); + "n_found == 0"); tor_end_capture_bugs_(); /* There is no 'fred=', so that is treated as not existing. */ tt_int_op(-100, OP_EQ, @@ -1680,8 +1874,7 @@ vote_tweaks_for_v3ns(networkstatus_t *v, int voter, time_t now) measured_bw_line_t mbw; memset(mbw.node_id, 33, sizeof(mbw.node_id)); mbw.bw_kb = 1024; - tt_assert(measured_bw_line_apply(&mbw, - v->routerstatus_list) == 1); + tt_int_op(measured_bw_line_apply(&mbw, v->routerstatus_list), OP_EQ, 1); } else if (voter == 2 || voter == 3) { /* Monkey around with the list a bit */ vrs = smartlist_get(v->routerstatus_list, 2); @@ -1797,7 +1990,7 @@ test_consensus_for_v3ns(networkstatus_t *con, time_t now) (void)now; tt_assert(con); - tt_assert(!con->cert); + tt_ptr_op(con->cert, OP_EQ, NULL); tt_int_op(2,OP_EQ, smartlist_len(con->routerstatus_list)); /* There should be two listed routers: one with identity 3, one with * identity 5. */ @@ -1867,13 +2060,260 @@ test_routerstatus_for_v3ns(routerstatus_t *rs, time_t now) /* XXXX check version */ } else { /* Weren't expecting this... */ - tt_assert(0); + tt_abort(); } done: return; } +static void +test_dir_networkstatus_compute_bw_weights_v10(void *arg) +{ + (void) arg; + smartlist_t *chunks = smartlist_new(); + int64_t G, M, E, D, T, weight_scale; + int ret; + weight_scale = 10000; + + /* no case. one or more of the values is 0 */ + G = M = E = D = 0; + T = G + M + E + D; + ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, + weight_scale); + tt_int_op(ret, OP_EQ, 0); + tt_int_op(smartlist_len(chunks), OP_EQ, 0); + + /* case 1 */ + /* XXX dir-spec not followed? See #20272. If it isn't closed, then this is + * testing current behavior, not spec. */ + G = E = 10; + M = D = 1; + T = G + M + E + D; + ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, + weight_scale); + tt_int_op(ret, OP_EQ, 1); + tt_int_op(smartlist_len(chunks), OP_EQ, 1); + tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=3333 " + "Wbe=3000 Wbg=3000 Wbm=10000 Wdb=10000 Web=10000 Wed=3333 Wee=7000 " + "Weg=3333 Wem=7000 Wgb=10000 Wgd=3333 Wgg=7000 Wgm=7000 Wmb=10000 " + "Wmd=3333 Wme=3000 Wmg=3000 Wmm=10000\n"); + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_clear(chunks); + + /* case 2a E scarce */ + M = 100; + G = 20; + E = D = 5; + T = G + M + E + D; + ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, + weight_scale); + tt_int_op(ret, OP_EQ, 1); + tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=0 Wbe=0 " + "Wbg=0 Wbm=10000 Wdb=10000 Web=10000 Wed=10000 Wee=10000 Weg=10000 " + "Wem=10000 Wgb=10000 Wgd=0 Wgg=10000 Wgm=10000 Wmb=10000 Wmd=0 Wme=0 " + "Wmg=0 Wmm=10000\n"); + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_clear(chunks); + + /* case 2a G scarce */ + M = 100; + E = 20; + G = D = 5; + T = G + M + E + D; + ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, + weight_scale); + tt_int_op(ret, OP_EQ, 1); + tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=0 Wbe=0 " + "Wbg=0 Wbm=10000 Wdb=10000 Web=10000 Wed=0 Wee=10000 Weg=0 Wem=10000 " + "Wgb=10000 Wgd=10000 Wgg=10000 Wgm=10000 Wmb=10000 Wmd=0 Wme=0 Wmg=0 " + "Wmm=10000\n"); + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_clear(chunks); + + /* case 2b1 (Wgg=1, Wmd=Wgd) */ + M = 10; + E = 30; + G = 10; + D = 100; + T = G + M + E + D; + ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, + weight_scale); + tt_int_op(ret, OP_EQ, 1); + tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=4000 " + "Wbe=0 Wbg=0 Wbm=10000 Wdb=10000 Web=10000 Wed=2000 Wee=10000 Weg=2000 " + "Wem=10000 Wgb=10000 Wgd=4000 Wgg=10000 Wgm=10000 Wmb=10000 Wmd=4000 " + "Wme=0 Wmg=0 Wmm=10000\n"); + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_clear(chunks); + + /* case 2b2 */ + M = 60; + E = 30; + G = 10; + D = 100; + T = G + M + E + D; + ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, + weight_scale); + tt_int_op(ret, OP_EQ, 1); + tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=666 Wbe=0 " + "Wbg=0 Wbm=10000 Wdb=10000 Web=10000 Wed=3666 Wee=10000 Weg=3666 " + "Wem=10000 Wgb=10000 Wgd=5668 Wgg=10000 Wgm=10000 Wmb=10000 Wmd=666 " + "Wme=0 Wmg=0 Wmm=10000\n"); + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_clear(chunks); + + /* case 2b3 */ + /* XXX I can't get a combination of values that hits this case without error, + * so this just tests that it fails. See #20285. Also see #20284 as 2b3 does + * not follow dir-spec. */ + /* (E < T/3 && G < T/3) && (E+D>=G || G+D>=E) && (M > T/3) */ + M = 80; + E = 30; + G = 30; + D = 30; + T = G + M + E + D; + ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, + weight_scale); + tt_int_op(ret, OP_EQ, 0); + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_clear(chunks); + + /* case 3a G scarce */ + M = 10; + E = 30; + G = 10; + D = 5; + T = G + M + E + D; + ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, + weight_scale); + tt_int_op(ret, OP_EQ, 1); + tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=0 " + "Wbe=3333 Wbg=0 Wbm=10000 Wdb=10000 Web=10000 Wed=0 Wee=6667 Weg=0 " + "Wem=6667 Wgb=10000 Wgd=10000 Wgg=10000 Wgm=10000 Wmb=10000 Wmd=0 " + "Wme=3333 Wmg=0 Wmm=10000\n"); + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_clear(chunks); + + /* case 3a E scarce */ + M = 10; + E = 10; + G = 30; + D = 5; + T = G + M + E + D; + ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, + weight_scale); + tt_int_op(ret, OP_EQ, 1); + tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=0 Wbe=0 " + "Wbg=3333 Wbm=10000 Wdb=10000 Web=10000 Wed=10000 Wee=10000 Weg=10000 " + "Wem=10000 Wgb=10000 Wgd=0 Wgg=6667 Wgm=6667 Wmb=10000 Wmd=0 Wme=0 " + "Wmg=3333 Wmm=10000\n"); + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_clear(chunks); + + /* case 3bg */ + M = 10; + E = 30; + G = 10; + D = 10; + T = G + M + E + D; + ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, + weight_scale); + tt_int_op(ret, OP_EQ, 1); + tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=0 " + "Wbe=3334 Wbg=0 Wbm=10000 Wdb=10000 Web=10000 Wed=0 Wee=6666 Weg=0 " + "Wem=6666 Wgb=10000 Wgd=10000 Wgg=10000 Wgm=10000 Wmb=10000 Wmd=0 " + "Wme=3334 Wmg=0 Wmm=10000\n"); + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_clear(chunks); + + /* case 3be */ + M = 10; + E = 10; + G = 30; + D = 10; + T = G + M + E + D; + ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, + weight_scale); + tt_int_op(ret, OP_EQ, 1); + tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=0 Wbe=0 " + "Wbg=3334 Wbm=10000 Wdb=10000 Web=10000 Wed=10000 Wee=10000 Weg=10000 " + "Wem=10000 Wgb=10000 Wgd=0 Wgg=6666 Wgm=6666 Wmb=10000 Wmd=0 Wme=0 " + "Wmg=3334 Wmm=10000\n"); + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_clear(chunks); + + /* case from 21 Jul 2013 (3be) */ + G = 5483409; + M = 1455379; + E = 980834; + D = 3385803; + T = 11305425; + tt_i64_op(G+M+E+D, OP_EQ, T); + ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, + weight_scale); + tt_assert(ret); + tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=883 Wbe=0 " + "Wbg=3673 Wbm=10000 Wdb=10000 Web=10000 Wed=8233 Wee=10000 Weg=8233 " + "Wem=10000 Wgb=10000 Wgd=883 Wgg=6327 Wgm=6327 Wmb=10000 Wmd=883 Wme=0 " + "Wmg=3673 Wmm=10000\n"); + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_clear(chunks); + + /* case from 04 Oct 2016 (3a E scarce) */ + G=29322240; + M=4721546; + E=1522058; + D=9273571; + T=44839415; + tt_i64_op(G+M+E+D, OP_EQ, T); + ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, + weight_scale); + tt_assert(ret); + tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=0 Wbe=0 " + "Wbg=4194 Wbm=10000 Wdb=10000 Web=10000 Wed=10000 Wee=10000 Weg=10000 " + "Wem=10000 Wgb=10000 Wgd=0 Wgg=5806 Wgm=5806 Wmb=10000 Wmd=0 Wme=0 " + "Wmg=4194 Wmm=10000\n"); + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_clear(chunks); + + /* case from 04 Sep 2013 (2b1) */ + G=3091352; + M=1838837; + E=2109300; + D=2469369; + T=9508858; + tt_i64_op(G+M+E+D, OP_EQ, T); + ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, + weight_scale); + tt_assert(ret); + tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=317 " + "Wbe=5938 Wbg=0 Wbm=10000 Wdb=10000 Web=10000 Wed=9366 Wee=4061 " + "Weg=9366 Wem=4061 Wgb=10000 Wgd=317 Wgg=10000 Wgm=10000 Wmb=10000 " + "Wmd=317 Wme=5938 Wmg=0 Wmm=10000\n"); + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_clear(chunks); + + /* explicitly test initializing weights to 1*/ + G=1; + M=1; + E=1; + D=1; + T=4; + tt_i64_op(G+M+E+D, OP_EQ, T); + ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, + weight_scale); + tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=3333 " + "Wbe=0 Wbg=0 Wbm=10000 Wdb=10000 Web=10000 Wed=3333 Wee=10000 Weg=3333 " + "Wem=10000 Wgb=10000 Wgd=3333 Wgg=10000 Wgm=10000 Wmb=10000 Wmd=3333 " + "Wme=0 Wmg=0 Wmm=10000\n"); + tt_assert(ret); + + done: + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_free(chunks); +} + static authority_cert_t *mock_cert; static authority_cert_t * @@ -2568,7 +3008,7 @@ gen_routerstatus_for_umbw(int idx, time_t now) break; default: /* Shouldn't happen */ - tt_assert(0); + tt_abort(); } if (vrs) { vrs->microdesc = tor_malloc_zero(sizeof(vote_microdesc_hash_t)); @@ -2708,7 +3148,7 @@ test_vrs_for_umbw(vote_routerstatus_t *vrs, int voter, time_t now) tt_int_op(rs->bandwidth_kb,OP_EQ, max_unmeasured_bw_kb / 2); tt_int_op(vrs->measured_bw_kb,OP_EQ, 0); } else { - tt_assert(0); + tt_abort(); } done: @@ -2724,9 +3164,9 @@ test_consensus_for_umbw(networkstatus_t *con, time_t now) (void)now; tt_assert(con); - tt_assert(!con->cert); + tt_ptr_op(con->cert, OP_EQ, NULL); // tt_assert(con->consensus_method >= MIN_METHOD_TO_CLIP_UNMEASURED_BW_KB); - tt_assert(con->consensus_method >= 16); + tt_int_op(con->consensus_method, OP_GE, 16); tt_int_op(4,OP_EQ, smartlist_len(con->routerstatus_list)); /* There should be four listed routers; all voters saw the same in this */ @@ -2823,7 +3263,7 @@ test_routerstatus_for_umbw(routerstatus_t *rs, time_t now) tt_assert(rs->bw_is_unmeasured); } else { /* Weren't expecting this... */ - tt_assert(0); + tt_abort(); } done: @@ -2930,7 +3370,7 @@ mock_get_options(void) static void reset_routerstatus(routerstatus_t *rs, const char *hex_identity_digest, - int32_t ipv4_addr) + uint32_t ipv4_addr) { memset(rs, 0, sizeof(routerstatus_t)); base16_decode(rs->identity_digest, sizeof(rs->identity_digest), @@ -2991,15 +3431,17 @@ test_dir_dirserv_set_routerstatus_testing(void *arg) * Return values are {2, 3, 4} */ /* We want 3 ("*" means match all addresses) */ - tt_assert(routerset_contains_routerstatus(routerset_all, rs_a, 0) == 3); - tt_assert(routerset_contains_routerstatus(routerset_all, rs_b, 0) == 3); + tt_int_op(routerset_contains_routerstatus(routerset_all, rs_a, 0), OP_EQ, 3); + tt_int_op(routerset_contains_routerstatus(routerset_all, rs_b, 0), OP_EQ, 3); /* We want 4 (match id_digest [or nickname]) */ - tt_assert(routerset_contains_routerstatus(routerset_a, rs_a, 0) == 4); - tt_assert(routerset_contains_routerstatus(routerset_a, rs_b, 0) == 0); + tt_int_op(routerset_contains_routerstatus(routerset_a, rs_a, 0), OP_EQ, 4); + tt_int_op(routerset_contains_routerstatus(routerset_a, rs_b, 0), OP_EQ, 0); - tt_assert(routerset_contains_routerstatus(routerset_none, rs_a, 0) == 0); - tt_assert(routerset_contains_routerstatus(routerset_none, rs_b, 0) == 0); + tt_int_op(routerset_contains_routerstatus(routerset_none, rs_a, 0), OP_EQ, + 0); + tt_int_op(routerset_contains_routerstatus(routerset_none, rs_b, 0), OP_EQ, + 0); /* Check that "*" sets flags on all routers: Exit * Check the flags aren't being confused with each other */ @@ -3011,17 +3453,17 @@ test_dir_dirserv_set_routerstatus_testing(void *arg) mock_options->TestingDirAuthVoteExitIsStrict = 0; dirserv_set_routerstatus_testing(rs_a); - tt_assert(mock_get_options_calls == 1); + tt_int_op(mock_get_options_calls, OP_EQ, 1); dirserv_set_routerstatus_testing(rs_b); - tt_assert(mock_get_options_calls == 2); + tt_int_op(mock_get_options_calls, OP_EQ, 2); - tt_assert(rs_a->is_exit == 1); - tt_assert(rs_b->is_exit == 1); + tt_uint_op(rs_a->is_exit, OP_EQ, 1); + tt_uint_op(rs_b->is_exit, OP_EQ, 1); /* Be paranoid - check no other flags are set */ - tt_assert(rs_a->is_possible_guard == 0); - tt_assert(rs_b->is_possible_guard == 0); - tt_assert(rs_a->is_hs_dir == 0); - tt_assert(rs_b->is_hs_dir == 0); + tt_uint_op(rs_a->is_possible_guard, OP_EQ, 0); + tt_uint_op(rs_b->is_possible_guard, OP_EQ, 0); + tt_uint_op(rs_a->is_hs_dir, OP_EQ, 0); + tt_uint_op(rs_b->is_hs_dir, OP_EQ, 0); /* Check that "*" sets flags on all routers: Guard & HSDir * Cover the remaining flags in one test */ @@ -3035,17 +3477,17 @@ test_dir_dirserv_set_routerstatus_testing(void *arg) mock_options->TestingDirAuthVoteHSDirIsStrict = 0; dirserv_set_routerstatus_testing(rs_a); - tt_assert(mock_get_options_calls == 1); + tt_int_op(mock_get_options_calls, OP_EQ, 1); dirserv_set_routerstatus_testing(rs_b); - tt_assert(mock_get_options_calls == 2); + tt_int_op(mock_get_options_calls, OP_EQ, 2); - tt_assert(rs_a->is_possible_guard == 1); - tt_assert(rs_b->is_possible_guard == 1); - tt_assert(rs_a->is_hs_dir == 1); - tt_assert(rs_b->is_hs_dir == 1); + tt_uint_op(rs_a->is_possible_guard, OP_EQ, 1); + tt_uint_op(rs_b->is_possible_guard, OP_EQ, 1); + tt_uint_op(rs_a->is_hs_dir, OP_EQ, 1); + tt_uint_op(rs_b->is_hs_dir, OP_EQ, 1); /* Be paranoid - check exit isn't set */ - tt_assert(rs_a->is_exit == 0); - tt_assert(rs_b->is_exit == 0); + tt_uint_op(rs_a->is_exit, OP_EQ, 0); + tt_uint_op(rs_b->is_exit, OP_EQ, 0); /* Check routerset A sets all flags on router A, * but leaves router B unmodified */ @@ -3061,16 +3503,16 @@ test_dir_dirserv_set_routerstatus_testing(void *arg) mock_options->TestingDirAuthVoteHSDirIsStrict = 0; dirserv_set_routerstatus_testing(rs_a); - tt_assert(mock_get_options_calls == 1); + tt_int_op(mock_get_options_calls, OP_EQ, 1); dirserv_set_routerstatus_testing(rs_b); - tt_assert(mock_get_options_calls == 2); + tt_int_op(mock_get_options_calls, OP_EQ, 2); - tt_assert(rs_a->is_exit == 1); - tt_assert(rs_b->is_exit == 0); - tt_assert(rs_a->is_possible_guard == 1); - tt_assert(rs_b->is_possible_guard == 0); - tt_assert(rs_a->is_hs_dir == 1); - tt_assert(rs_b->is_hs_dir == 0); + tt_uint_op(rs_a->is_exit, OP_EQ, 1); + tt_uint_op(rs_b->is_exit, OP_EQ, 0); + tt_uint_op(rs_a->is_possible_guard, OP_EQ, 1); + tt_uint_op(rs_b->is_possible_guard, OP_EQ, 0); + tt_uint_op(rs_a->is_hs_dir, OP_EQ, 1); + tt_uint_op(rs_b->is_hs_dir, OP_EQ, 0); /* Check routerset A unsets all flags on router B when Strict is set */ reset_options(mock_options, &mock_get_options_calls); @@ -3088,11 +3530,11 @@ test_dir_dirserv_set_routerstatus_testing(void *arg) rs_b->is_hs_dir = 1; dirserv_set_routerstatus_testing(rs_b); - tt_assert(mock_get_options_calls == 1); + tt_int_op(mock_get_options_calls, OP_EQ, 1); - tt_assert(rs_b->is_exit == 0); - tt_assert(rs_b->is_possible_guard == 0); - tt_assert(rs_b->is_hs_dir == 0); + tt_uint_op(rs_b->is_exit, OP_EQ, 0); + tt_uint_op(rs_b->is_possible_guard, OP_EQ, 0); + tt_uint_op(rs_b->is_hs_dir, OP_EQ, 0); /* Check routerset A doesn't modify flags on router B without Strict set */ reset_options(mock_options, &mock_get_options_calls); @@ -3110,11 +3552,11 @@ test_dir_dirserv_set_routerstatus_testing(void *arg) rs_b->is_hs_dir = 1; dirserv_set_routerstatus_testing(rs_b); - tt_assert(mock_get_options_calls == 1); + tt_int_op(mock_get_options_calls, OP_EQ, 1); - tt_assert(rs_b->is_exit == 1); - tt_assert(rs_b->is_possible_guard == 1); - tt_assert(rs_b->is_hs_dir == 1); + tt_uint_op(rs_b->is_exit, OP_EQ, 1); + tt_uint_op(rs_b->is_possible_guard, OP_EQ, 1); + tt_uint_op(rs_b->is_hs_dir, OP_EQ, 1); /* Check the empty routerset zeroes all flags * on routers A & B with Strict set */ @@ -3133,11 +3575,11 @@ test_dir_dirserv_set_routerstatus_testing(void *arg) rs_b->is_hs_dir = 1; dirserv_set_routerstatus_testing(rs_b); - tt_assert(mock_get_options_calls == 1); + tt_int_op(mock_get_options_calls, OP_EQ, 1); - tt_assert(rs_b->is_exit == 0); - tt_assert(rs_b->is_possible_guard == 0); - tt_assert(rs_b->is_hs_dir == 0); + tt_uint_op(rs_b->is_exit, OP_EQ, 0); + tt_uint_op(rs_b->is_possible_guard, OP_EQ, 0); + tt_uint_op(rs_b->is_hs_dir, OP_EQ, 0); /* Check the empty routerset doesn't modify any flags * on A or B without Strict set */ @@ -3157,16 +3599,16 @@ test_dir_dirserv_set_routerstatus_testing(void *arg) rs_b->is_hs_dir = 1; dirserv_set_routerstatus_testing(rs_a); - tt_assert(mock_get_options_calls == 1); + tt_int_op(mock_get_options_calls, OP_EQ, 1); dirserv_set_routerstatus_testing(rs_b); - tt_assert(mock_get_options_calls == 2); + tt_int_op(mock_get_options_calls, OP_EQ, 2); - tt_assert(rs_a->is_exit == 0); - tt_assert(rs_a->is_possible_guard == 0); - tt_assert(rs_a->is_hs_dir == 0); - tt_assert(rs_b->is_exit == 1); - tt_assert(rs_b->is_possible_guard == 1); - tt_assert(rs_b->is_hs_dir == 1); + tt_uint_op(rs_a->is_exit, OP_EQ, 0); + tt_uint_op(rs_a->is_possible_guard, OP_EQ, 0); + tt_uint_op(rs_a->is_hs_dir, OP_EQ, 0); + tt_uint_op(rs_b->is_exit, OP_EQ, 1); + tt_uint_op(rs_b->is_possible_guard, OP_EQ, 1); + tt_uint_op(rs_b->is_hs_dir, OP_EQ, 1); done: tor_free(mock_options); @@ -3222,7 +3664,7 @@ test_dir_http_handling(void *args) "User-Agent: Mozilla/5.0 (Windows;" " U; Windows NT 6.1; en-US; rv:1.9.1.5)\r\n", &url),OP_EQ, -1); - tt_assert(!url); + tt_ptr_op(url, OP_EQ, NULL); /* Bad headers */ tt_int_op(parse_http_url("GET /a/b/c.txt\r\n" @@ -3230,40 +3672,113 @@ test_dir_http_handling(void *args) "User-Agent: Mozilla/5.0 (Windows;" " U; Windows NT 6.1; en-US; rv:1.9.1.5)\r\n", &url),OP_EQ, -1); - tt_assert(!url); + tt_ptr_op(url, OP_EQ, NULL); tt_int_op(parse_http_url("GET /tor/a/b/c.txt", &url),OP_EQ, -1); - tt_assert(!url); + tt_ptr_op(url, OP_EQ, NULL); tt_int_op(parse_http_url("GET /tor/a/b/c.txt HTTP/1.1", &url),OP_EQ, -1); - tt_assert(!url); + tt_ptr_op(url, OP_EQ, NULL); tt_int_op(parse_http_url("GET /tor/a/b/c.txt HTTP/1.1x\r\n", &url), OP_EQ, -1); - tt_assert(!url); + tt_ptr_op(url, OP_EQ, NULL); tt_int_op(parse_http_url("GET /tor/a/b/c.txt HTTP/1.", &url),OP_EQ, -1); - tt_assert(!url); + tt_ptr_op(url, OP_EQ, NULL); tt_int_op(parse_http_url("GET /tor/a/b/c.txt HTTP/1.\r", &url),OP_EQ, -1); - tt_assert(!url); + tt_ptr_op(url, OP_EQ, NULL); done: tor_free(url); } static void -test_dir_purpose_needs_anonymity(void *arg) +test_dir_purpose_needs_anonymity_returns_true_by_default(void *arg) +{ + (void)arg; + + tor_capture_bugs_(1); + setup_full_capture_of_logs(LOG_WARN); + tt_int_op(1, OP_EQ, purpose_needs_anonymity(0, 0, NULL)); + tt_int_op(1, OP_EQ, smartlist_len(tor_get_captured_bug_log_())); + expect_single_log_msg_containing("Called with dir_purpose=0"); + + tor_end_capture_bugs_(); + done: + tor_end_capture_bugs_(); + teardown_capture_of_logs(); +} + +static void +test_dir_purpose_needs_anonymity_returns_true_for_bridges(void *arg) { (void)arg; - tt_int_op(1, ==, purpose_needs_anonymity(0, ROUTER_PURPOSE_BRIDGE)); - tt_int_op(1, ==, purpose_needs_anonymity(0, ROUTER_PURPOSE_GENERAL)); - tt_int_op(0, ==, purpose_needs_anonymity(DIR_PURPOSE_FETCH_MICRODESC, - ROUTER_PURPOSE_GENERAL)); + + tt_int_op(1, OP_EQ, purpose_needs_anonymity(0, ROUTER_PURPOSE_BRIDGE, NULL)); + tt_int_op(1, OP_EQ, purpose_needs_anonymity(0, ROUTER_PURPOSE_BRIDGE, + "foobar")); + tt_int_op(1, OP_EQ, + purpose_needs_anonymity(DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2, + ROUTER_PURPOSE_BRIDGE, NULL)); done: ; } static void +test_dir_purpose_needs_anonymity_returns_false_for_own_bridge_desc(void *arg) +{ + (void)arg; + tt_int_op(0, OP_EQ, purpose_needs_anonymity(DIR_PURPOSE_FETCH_SERVERDESC, + ROUTER_PURPOSE_BRIDGE, + "authority.z")); + done: ; +} + +static void +test_dir_purpose_needs_anonymity_returns_true_for_sensitive_purpose(void *arg) +{ + (void)arg; + + tt_int_op(1, OP_EQ, purpose_needs_anonymity( + DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2, + ROUTER_PURPOSE_GENERAL, NULL)); + tt_int_op(1, OP_EQ, purpose_needs_anonymity( + DIR_PURPOSE_UPLOAD_RENDDESC_V2, 0, NULL)); + tt_int_op(1, OP_EQ, purpose_needs_anonymity( + DIR_PURPOSE_FETCH_RENDDESC_V2, 0, NULL)); + done: ; +} + +static void +test_dir_purpose_needs_anonymity_ret_false_for_non_sensitive_conn(void *arg) +{ + (void)arg; + + tt_int_op(0, OP_EQ, purpose_needs_anonymity(DIR_PURPOSE_UPLOAD_DIR, + ROUTER_PURPOSE_GENERAL, NULL)); + tt_int_op(0, OP_EQ, + purpose_needs_anonymity(DIR_PURPOSE_UPLOAD_VOTE, 0, NULL)); + tt_int_op(0, OP_EQ, + purpose_needs_anonymity(DIR_PURPOSE_UPLOAD_SIGNATURES, 0, NULL)); + tt_int_op(0, OP_EQ, + purpose_needs_anonymity(DIR_PURPOSE_FETCH_STATUS_VOTE, 0, NULL)); + tt_int_op(0, OP_EQ, purpose_needs_anonymity( + DIR_PURPOSE_FETCH_DETACHED_SIGNATURES, 0, NULL)); + tt_int_op(0, OP_EQ, + purpose_needs_anonymity(DIR_PURPOSE_FETCH_CONSENSUS, 0, NULL)); + tt_int_op(0, OP_EQ, + purpose_needs_anonymity(DIR_PURPOSE_FETCH_CERTIFICATE, 0, NULL)); + tt_int_op(0, OP_EQ, + purpose_needs_anonymity(DIR_PURPOSE_FETCH_SERVERDESC, 0, NULL)); + tt_int_op(0, OP_EQ, + purpose_needs_anonymity(DIR_PURPOSE_FETCH_EXTRAINFO, 0, NULL)); + tt_int_op(0, OP_EQ, + purpose_needs_anonymity(DIR_PURPOSE_FETCH_MICRODESC, 0, NULL)); + done: ; +} + +static void test_dir_fetch_type(void *arg) { (void)arg; @@ -3311,9 +3826,9 @@ test_dir_packages(void *arg) (void)arg; #define BAD(s) \ - tt_int_op(0, ==, validate_recommended_package_line(s)); + tt_int_op(0, OP_EQ, validate_recommended_package_line(s)); #define GOOD(s) \ - tt_int_op(1, ==, validate_recommended_package_line(s)); + tt_int_op(1, OP_EQ, validate_recommended_package_line(s)); GOOD("tor 0.2.6.3-alpha " "http://torproject.example.com/dist/tor-0.2.6.3-alpha.tar.gz " "sha256=sssdlkfjdsklfjdskfljasdklfj"); @@ -3430,7 +3945,7 @@ test_dir_packages(void *arg) res = compute_consensus_package_lines(votes); tt_assert(res); - tt_str_op(res, ==, + tt_str_op(res, OP_EQ, "package cbc 99.1.11.1.1 http://example.com/cbc/ cubehash=ahooy sha512=m\n" "package clownshoes 22alpha3 http://quumble.example.com/ blake2=fooz\n" "package clownshoes 22alpha4 http://quumble.example.cam/ blake2=fooa\n" @@ -3602,40 +4117,69 @@ test_dir_download_status_schedule(void *arg) } static void -test_dir_download_status_random_backoff(void *arg) +download_status_random_backoff_helper(int min_delay, int max_delay) { download_status_t dls_random = { 0, 0, 0, DL_SCHED_GENERIC, DL_WANT_AUTHORITY, DL_SCHED_INCREMENT_FAILURE, DL_SCHED_RANDOM_EXPONENTIAL, 0, 0 }; int increment = -1; - int old_increment; + int old_increment = -1; time_t current_time = time(NULL); - const int min_delay = 0; - const int max_delay = 1000000; - - (void)arg; + const int exponent = DIR_DEFAULT_RANDOM_MULTIPLIER + 1; /* Check the random backoff cases */ - old_increment = 0; do { increment = download_status_schedule_get_delay(&dls_random, NULL, min_delay, max_delay, current_time); + + log_debug(LD_DIR, "Min: %d, Max: %d, Inc: %d, Old Inc: %d", + min_delay, max_delay, increment, old_increment); + + /* Regression test for 20534 and friends + * increment must always increase after the first */ + if (dls_random.last_backoff_position > 0 && max_delay > 0) { + /* Always increment the exponential backoff */ + tt_int_op(increment, OP_GE, 1); + } + /* Test */ tt_int_op(increment, OP_GE, min_delay); tt_int_op(increment, OP_LE, max_delay); - tt_int_op(increment, OP_GE, old_increment); - /* We at most quadruple, and maybe add one */ - tt_int_op(increment, OP_LE, 4 * old_increment + 1); + if (dls_random.last_backoff_position == 0) { + /* regression tests for 17750 + * Always use the minimum delay for the first increment */ + tt_int_op(increment, OP_EQ, min_delay); + } else { + /* It's times like these I'd love a good saturating arithmetic + * implementation */ + int min_inc = INT_MAX; + if (old_increment <= INT_MAX - 1) { + min_inc = old_increment + 1; + } + + int max_inc = INT_MAX; + if (old_increment <= (INT_MAX - 1)/exponent) { + max_inc = (exponent * old_increment) + 1; + } + + /* Regression test for 20534 and friends: + * increment must always increase after the first */ + tt_int_op(increment, OP_GE, min_inc); + /* We at most quadruple, and always add one */ + tt_int_op(increment, OP_LE, max_inc); + } /* Advance */ - current_time += increment; ++(dls_random.n_download_attempts); ++(dls_random.n_download_failures); /* Try another maybe */ old_increment = increment; + if (increment >= max_delay) + current_time += increment; + } while (increment < max_delay); done: @@ -3643,6 +4187,27 @@ test_dir_download_status_random_backoff(void *arg) } static void +test_dir_download_status_random_backoff(void *arg) +{ + (void)arg; + + /* Do a standard test */ + download_status_random_backoff_helper(0, 1000000); + /* Regression test for 20534 and friends: + * try tighter bounds */ + download_status_random_backoff_helper(0, 100); + /* regression tests for 17750: initial delay */ + download_status_random_backoff_helper(10, 1000); + download_status_random_backoff_helper(20, 30); + + /* Pathological cases */ + download_status_random_backoff_helper(0, 0); + download_status_random_backoff_helper(1, 1); + download_status_random_backoff_helper(0, INT_MAX); + download_status_random_backoff_helper(INT_MAX/2, INT_MAX); +} + +static void test_dir_download_status_increment(void *arg) { (void)arg; @@ -3654,32 +4219,97 @@ test_dir_download_status_increment(void *arg) DL_WANT_ANY_DIRSERVER, DL_SCHED_INCREMENT_ATTEMPT, DL_SCHED_DETERMINISTIC, 0, 0 }; + download_status_t dls_exp = { 0, 0, 0, DL_SCHED_GENERIC, + DL_WANT_ANY_DIRSERVER, + DL_SCHED_INCREMENT_ATTEMPT, + DL_SCHED_RANDOM_EXPONENTIAL, 0, 0 }; + int no_delay = 0; int delay0 = -1; int delay1 = -1; int delay2 = -1; smartlist_t *schedule = smartlist_new(); + smartlist_t *schedule_no_initial_delay = smartlist_new(); or_options_t test_options; time_t next_at = TIME_MAX; time_t current_time = time(NULL); - /* Provide some values for the schedule */ + /* Provide some values for the schedules */ delay0 = 10; delay1 = 99; delay2 = 20; - /* Make the schedule */ + /* Make the schedules */ smartlist_add(schedule, (void *)&delay0); smartlist_add(schedule, (void *)&delay1); smartlist_add(schedule, (void *)&delay2); + smartlist_add(schedule_no_initial_delay, (void *)&no_delay); + smartlist_add(schedule_no_initial_delay, (void *)&delay1); + smartlist_add(schedule_no_initial_delay, (void *)&delay2); + /* Put it in the options */ mock_options = &test_options; reset_options(mock_options, &mock_get_options_calls); + mock_options->TestingBridgeBootstrapDownloadSchedule = schedule; mock_options->TestingClientDownloadSchedule = schedule; - mock_options->TestingBridgeDownloadSchedule = schedule; MOCK(get_options, mock_get_options); + /* Check that the initial value of the schedule is the first value used, + * whether or not it was reset before being used */ + + /* regression test for 17750: no initial delay */ + mock_options->TestingClientDownloadSchedule = schedule_no_initial_delay; + mock_get_options_calls = 0; + /* we really want to test that it's equal to time(NULL) + delay0, but that's + * an unrealiable test, because time(NULL) might change. */ + tt_assert(download_status_get_next_attempt_at(&dls_failure) + >= current_time + no_delay); + tt_assert(download_status_get_next_attempt_at(&dls_failure) + != TIME_MAX); + tt_int_op(download_status_get_n_failures(&dls_failure), OP_EQ, 0); + tt_int_op(download_status_get_n_attempts(&dls_failure), OP_EQ, 0); + tt_int_op(mock_get_options_calls, OP_GE, 1); + + /* regression test for 17750: initial delay */ + mock_options->TestingClientDownloadSchedule = schedule; + mock_get_options_calls = 0; + /* we really want to test that it's equal to time(NULL) + delay0, but that's + * an unrealiable test, because time(NULL) might change. */ + tt_assert(download_status_get_next_attempt_at(&dls_failure) + >= current_time + delay0); + tt_assert(download_status_get_next_attempt_at(&dls_failure) + != TIME_MAX); + tt_int_op(download_status_get_n_failures(&dls_failure), OP_EQ, 0); + tt_int_op(download_status_get_n_attempts(&dls_failure), OP_EQ, 0); + tt_int_op(mock_get_options_calls, OP_GE, 1); + + /* regression test for 17750: exponential, no initial delay */ + mock_options->TestingClientDownloadSchedule = schedule_no_initial_delay; + mock_get_options_calls = 0; + /* we really want to test that it's equal to time(NULL) + delay0, but that's + * an unrealiable test, because time(NULL) might change. */ + tt_assert(download_status_get_next_attempt_at(&dls_exp) + >= current_time + no_delay); + tt_assert(download_status_get_next_attempt_at(&dls_exp) + != TIME_MAX); + tt_int_op(download_status_get_n_failures(&dls_exp), OP_EQ, 0); + tt_int_op(download_status_get_n_attempts(&dls_exp), OP_EQ, 0); + tt_int_op(mock_get_options_calls, OP_GE, 1); + + /* regression test for 17750: exponential, initial delay */ + mock_options->TestingClientDownloadSchedule = schedule; + mock_get_options_calls = 0; + /* we really want to test that it's equal to time(NULL) + delay0, but that's + * an unrealiable test, because time(NULL) might change. */ + tt_assert(download_status_get_next_attempt_at(&dls_exp) + >= current_time + delay0); + tt_assert(download_status_get_next_attempt_at(&dls_exp) + != TIME_MAX); + tt_int_op(download_status_get_n_failures(&dls_exp), OP_EQ, 0); + tt_int_op(download_status_get_n_attempts(&dls_exp), OP_EQ, 0); + tt_int_op(mock_get_options_calls, OP_GE, 1); + /* Check that a failure reset works */ mock_get_options_calls = 0; download_status_reset(&dls_failure); @@ -3689,76 +4319,76 @@ test_dir_download_status_increment(void *arg) >= current_time + delay0); tt_assert(download_status_get_next_attempt_at(&dls_failure) != TIME_MAX); - tt_assert(download_status_get_n_failures(&dls_failure) == 0); - tt_assert(download_status_get_n_attempts(&dls_failure) == 0); - tt_assert(mock_get_options_calls >= 1); + tt_int_op(download_status_get_n_failures(&dls_failure), OP_EQ, 0); + tt_int_op(download_status_get_n_attempts(&dls_failure), OP_EQ, 0); + tt_int_op(mock_get_options_calls, OP_GE, 1); /* avoid timing inconsistencies */ dls_failure.next_attempt_at = current_time + delay0; /* check that a reset schedule becomes ready at the right time */ - tt_assert(download_status_is_ready(&dls_failure, - current_time + delay0 - 1, - 1) == 0); - tt_assert(download_status_is_ready(&dls_failure, - current_time + delay0, - 1) == 1); - tt_assert(download_status_is_ready(&dls_failure, - current_time + delay0 + 1, - 1) == 1); + tt_int_op(download_status_is_ready(&dls_failure, + current_time + delay0 - 1, 1), + OP_EQ, 0); + tt_int_op(download_status_is_ready(&dls_failure, + current_time + delay0, 1), + OP_EQ, 1); + tt_int_op(download_status_is_ready(&dls_failure, + current_time + delay0 + 1, 1), + OP_EQ, 1); /* Check that a failure increment works */ mock_get_options_calls = 0; next_at = download_status_increment_failure(&dls_failure, 404, "test", 0, current_time); tt_assert(next_at == current_time + delay1); - tt_assert(download_status_get_n_failures(&dls_failure) == 1); - tt_assert(download_status_get_n_attempts(&dls_failure) == 1); - tt_assert(mock_get_options_calls >= 1); + tt_int_op(download_status_get_n_failures(&dls_failure), OP_EQ, 1); + tt_int_op(download_status_get_n_attempts(&dls_failure), OP_EQ, 1); + tt_int_op(mock_get_options_calls, OP_GE, 1); /* check that an incremented schedule becomes ready at the right time */ - tt_assert(download_status_is_ready(&dls_failure, - current_time + delay1 - 1, - 1) == 0); - tt_assert(download_status_is_ready(&dls_failure, - current_time + delay1, - 1) == 1); - tt_assert(download_status_is_ready(&dls_failure, - current_time + delay1 + 1, - 1) == 1); + tt_int_op(download_status_is_ready(&dls_failure, + current_time + delay1 - 1, 1), + OP_EQ, 0); + tt_int_op(download_status_is_ready(&dls_failure, + current_time + delay1, 1), + OP_EQ, 1); + tt_int_op(download_status_is_ready(&dls_failure, + current_time + delay1 + 1, 1), + OP_EQ, 1); /* check that a schedule isn't ready if it's had too many failures */ - tt_assert(download_status_is_ready(&dls_failure, - current_time + delay1 + 10, - 0) == 0); + tt_int_op(download_status_is_ready(&dls_failure, + current_time + delay1 + 10, 0), + OP_EQ, 0); /* Check that failure increments do happen on 503 for clients, and * attempt increments do too. */ mock_get_options_calls = 0; next_at = download_status_increment_failure(&dls_failure, 503, "test", 0, current_time); - tt_i64_op(next_at, ==, current_time + delay2); - tt_int_op(download_status_get_n_failures(&dls_failure), ==, 2); - tt_int_op(download_status_get_n_attempts(&dls_failure), ==, 2); - tt_assert(mock_get_options_calls >= 1); + tt_i64_op(next_at, OP_EQ, current_time + delay2); + tt_int_op(download_status_get_n_failures(&dls_failure), OP_EQ, 2); + tt_int_op(download_status_get_n_attempts(&dls_failure), OP_EQ, 2); + tt_int_op(mock_get_options_calls, OP_GE, 1); /* Check that failure increments do happen on 503 for servers */ mock_get_options_calls = 0; next_at = download_status_increment_failure(&dls_failure, 503, "test", 1, current_time); tt_assert(next_at == current_time + delay2); - tt_assert(download_status_get_n_failures(&dls_failure) == 3); - tt_assert(download_status_get_n_attempts(&dls_failure) == 3); - tt_assert(mock_get_options_calls >= 1); + tt_int_op(download_status_get_n_failures(&dls_failure), OP_EQ, 3); + tt_int_op(download_status_get_n_attempts(&dls_failure), OP_EQ, 3); + tt_int_op(mock_get_options_calls, OP_GE, 1); /* Check what happens when we run off the end of the schedule */ mock_get_options_calls = 0; next_at = download_status_increment_failure(&dls_failure, 404, "test", 0, current_time); tt_assert(next_at == current_time + delay2); - tt_assert(download_status_get_n_failures(&dls_failure) == 4); - tt_assert(download_status_get_n_attempts(&dls_failure) == 4); - tt_assert(mock_get_options_calls >= 1); + tt_int_op(download_status_get_n_failures(&dls_failure), OP_EQ, 4); + tt_int_op(download_status_get_n_attempts(&dls_failure), OP_EQ, 4); + tt_int_op(mock_get_options_calls, OP_GE, 1); /* Check what happens when we hit the failure limit */ mock_get_options_calls = 0; @@ -3766,22 +4396,22 @@ test_dir_download_status_increment(void *arg) next_at = download_status_increment_failure(&dls_failure, 404, "test", 0, current_time); tt_assert(next_at == TIME_MAX); - tt_assert(download_status_get_n_failures(&dls_failure) - == IMPOSSIBLE_TO_DOWNLOAD); - tt_assert(download_status_get_n_attempts(&dls_failure) - == IMPOSSIBLE_TO_DOWNLOAD); - tt_assert(mock_get_options_calls >= 1); + tt_int_op(download_status_get_n_failures(&dls_failure), OP_EQ, + IMPOSSIBLE_TO_DOWNLOAD); + tt_int_op(download_status_get_n_attempts(&dls_failure), OP_EQ, + IMPOSSIBLE_TO_DOWNLOAD); + tt_int_op(mock_get_options_calls, OP_GE, 1); /* Check that a failure reset doesn't reset at the limit */ mock_get_options_calls = 0; download_status_reset(&dls_failure); tt_assert(download_status_get_next_attempt_at(&dls_failure) == TIME_MAX); - tt_assert(download_status_get_n_failures(&dls_failure) - == IMPOSSIBLE_TO_DOWNLOAD); - tt_assert(download_status_get_n_attempts(&dls_failure) - == IMPOSSIBLE_TO_DOWNLOAD); - tt_assert(mock_get_options_calls == 0); + tt_int_op(download_status_get_n_failures(&dls_failure), OP_EQ, + IMPOSSIBLE_TO_DOWNLOAD); + tt_int_op(download_status_get_n_attempts(&dls_failure), OP_EQ, + IMPOSSIBLE_TO_DOWNLOAD); + tt_int_op(mock_get_options_calls, OP_EQ, 0); /* Check that a failure reset resets just before the limit */ mock_get_options_calls = 0; @@ -3794,19 +4424,20 @@ test_dir_download_status_increment(void *arg) >= current_time + delay0); tt_assert(download_status_get_next_attempt_at(&dls_failure) != TIME_MAX); - tt_assert(download_status_get_n_failures(&dls_failure) == 0); - tt_assert(download_status_get_n_attempts(&dls_failure) == 0); - tt_assert(mock_get_options_calls >= 1); + tt_int_op(download_status_get_n_failures(&dls_failure), OP_EQ, 0); + tt_int_op(download_status_get_n_attempts(&dls_failure), OP_EQ, 0); + tt_int_op(mock_get_options_calls, OP_GE, 1); /* Check that failure increments do happen on attempt-based schedules, * but that the retry is set at the end of time */ + mock_options->UseBridges = 1; mock_get_options_calls = 0; next_at = download_status_increment_failure(&dls_attempt, 404, "test", 0, current_time); tt_assert(next_at == TIME_MAX); - tt_assert(download_status_get_n_failures(&dls_attempt) == 1); - tt_assert(download_status_get_n_attempts(&dls_attempt) == 0); - tt_assert(mock_get_options_calls == 0); + tt_int_op(download_status_get_n_failures(&dls_attempt), OP_EQ, 1); + tt_int_op(download_status_get_n_attempts(&dls_attempt), OP_EQ, 0); + tt_int_op(mock_get_options_calls, OP_GE, 1); /* Check that an attempt reset works */ mock_get_options_calls = 0; @@ -3817,65 +4448,65 @@ test_dir_download_status_increment(void *arg) >= current_time + delay0); tt_assert(download_status_get_next_attempt_at(&dls_attempt) != TIME_MAX); - tt_assert(download_status_get_n_failures(&dls_attempt) == 0); - tt_assert(download_status_get_n_attempts(&dls_attempt) == 0); - tt_assert(mock_get_options_calls >= 1); + tt_int_op(download_status_get_n_failures(&dls_attempt), OP_EQ, 0); + tt_int_op(download_status_get_n_attempts(&dls_attempt), OP_EQ, 0); + tt_int_op(mock_get_options_calls, OP_GE, 1); /* avoid timing inconsistencies */ dls_attempt.next_attempt_at = current_time + delay0; /* check that a reset schedule becomes ready at the right time */ - tt_assert(download_status_is_ready(&dls_attempt, - current_time + delay0 - 1, - 1) == 0); - tt_assert(download_status_is_ready(&dls_attempt, - current_time + delay0, - 1) == 1); - tt_assert(download_status_is_ready(&dls_attempt, - current_time + delay0 + 1, - 1) == 1); + tt_int_op(download_status_is_ready(&dls_attempt, + current_time + delay0 - 1, 1), + OP_EQ, 0); + tt_int_op(download_status_is_ready(&dls_attempt, + current_time + delay0, 1), + OP_EQ, 1); + tt_int_op(download_status_is_ready(&dls_attempt, + current_time + delay0 + 1, 1), + OP_EQ, 1); /* Check that an attempt increment works */ mock_get_options_calls = 0; next_at = download_status_increment_attempt(&dls_attempt, "test", current_time); tt_assert(next_at == current_time + delay1); - tt_assert(download_status_get_n_failures(&dls_attempt) == 0); - tt_assert(download_status_get_n_attempts(&dls_attempt) == 1); - tt_assert(mock_get_options_calls >= 1); + tt_int_op(download_status_get_n_failures(&dls_attempt), OP_EQ, 0); + tt_int_op(download_status_get_n_attempts(&dls_attempt), OP_EQ, 1); + tt_int_op(mock_get_options_calls, OP_GE, 1); /* check that an incremented schedule becomes ready at the right time */ - tt_assert(download_status_is_ready(&dls_attempt, - current_time + delay1 - 1, - 1) == 0); - tt_assert(download_status_is_ready(&dls_attempt, - current_time + delay1, - 1) == 1); - tt_assert(download_status_is_ready(&dls_attempt, - current_time + delay1 + 1, - 1) == 1); + tt_int_op(download_status_is_ready(&dls_attempt, + current_time + delay1 - 1, 1), + OP_EQ, 0); + tt_int_op(download_status_is_ready(&dls_attempt, + current_time + delay1, 1), + OP_EQ, 1); + tt_int_op(download_status_is_ready(&dls_attempt, + current_time + delay1 + 1, 1), + OP_EQ, 1); /* check that a schedule isn't ready if it's had too many attempts */ - tt_assert(download_status_is_ready(&dls_attempt, - current_time + delay1 + 10, - 0) == 0); + tt_int_op(download_status_is_ready(&dls_attempt, + current_time + delay1 + 10, 0), + OP_EQ, 0); /* Check what happens when we reach then run off the end of the schedule */ mock_get_options_calls = 0; next_at = download_status_increment_attempt(&dls_attempt, "test", current_time); tt_assert(next_at == current_time + delay2); - tt_assert(download_status_get_n_failures(&dls_attempt) == 0); - tt_assert(download_status_get_n_attempts(&dls_attempt) == 2); - tt_assert(mock_get_options_calls >= 1); + tt_int_op(download_status_get_n_failures(&dls_attempt), OP_EQ, 0); + tt_int_op(download_status_get_n_attempts(&dls_attempt), OP_EQ, 2); + tt_int_op(mock_get_options_calls, OP_GE, 1); mock_get_options_calls = 0; next_at = download_status_increment_attempt(&dls_attempt, "test", current_time); tt_assert(next_at == current_time + delay2); - tt_assert(download_status_get_n_failures(&dls_attempt) == 0); - tt_assert(download_status_get_n_attempts(&dls_attempt) == 3); - tt_assert(mock_get_options_calls >= 1); + tt_int_op(download_status_get_n_failures(&dls_attempt), OP_EQ, 0); + tt_int_op(download_status_get_n_attempts(&dls_attempt), OP_EQ, 3); + tt_int_op(mock_get_options_calls, OP_GE, 1); /* Check what happens when we hit the attempt limit */ mock_get_options_calls = 0; @@ -3883,22 +4514,22 @@ test_dir_download_status_increment(void *arg) next_at = download_status_increment_attempt(&dls_attempt, "test", current_time); tt_assert(next_at == TIME_MAX); - tt_assert(download_status_get_n_failures(&dls_attempt) - == IMPOSSIBLE_TO_DOWNLOAD); - tt_assert(download_status_get_n_attempts(&dls_attempt) - == IMPOSSIBLE_TO_DOWNLOAD); - tt_assert(mock_get_options_calls >= 1); + tt_int_op(download_status_get_n_failures(&dls_attempt), OP_EQ, + IMPOSSIBLE_TO_DOWNLOAD); + tt_int_op(download_status_get_n_attempts(&dls_attempt), OP_EQ, + IMPOSSIBLE_TO_DOWNLOAD); + tt_int_op(mock_get_options_calls, OP_GE, 1); /* Check that an attempt reset doesn't reset at the limit */ mock_get_options_calls = 0; download_status_reset(&dls_attempt); tt_assert(download_status_get_next_attempt_at(&dls_attempt) == TIME_MAX); - tt_assert(download_status_get_n_failures(&dls_attempt) - == IMPOSSIBLE_TO_DOWNLOAD); - tt_assert(download_status_get_n_attempts(&dls_attempt) - == IMPOSSIBLE_TO_DOWNLOAD); - tt_assert(mock_get_options_calls == 0); + tt_int_op(download_status_get_n_failures(&dls_attempt), OP_EQ, + IMPOSSIBLE_TO_DOWNLOAD); + tt_int_op(download_status_get_n_attempts(&dls_attempt), OP_EQ, + IMPOSSIBLE_TO_DOWNLOAD); + tt_int_op(mock_get_options_calls, OP_EQ, 0); /* Check that an attempt reset resets just before the limit */ mock_get_options_calls = 0; @@ -3911,9 +4542,10 @@ test_dir_download_status_increment(void *arg) >= current_time + delay0); tt_assert(download_status_get_next_attempt_at(&dls_attempt) != TIME_MAX); - tt_assert(download_status_get_n_failures(&dls_attempt) == 0); - tt_assert(download_status_get_n_attempts(&dls_attempt) == 0); - tt_assert(mock_get_options_calls >= 1); + tt_int_op(download_status_get_n_failures(&dls_attempt), OP_EQ, 0); + tt_int_op(download_status_get_n_attempts(&dls_attempt), OP_EQ, 0); + tt_int_op(mock_get_options_calls, OP_GE, 1); + mock_options->UseBridges = 0; /* Check that attempt increments don't happen on failure-based schedules, * and that the attempt is set at the end of time */ @@ -3926,13 +4558,14 @@ test_dir_download_status_increment(void *arg) "schedule."); teardown_capture_of_logs(); tt_assert(next_at == TIME_MAX); - tt_assert(download_status_get_n_failures(&dls_failure) == 0); - tt_assert(download_status_get_n_attempts(&dls_failure) == 0); - tt_assert(mock_get_options_calls == 0); + tt_int_op(download_status_get_n_failures(&dls_failure), OP_EQ, 0); + tt_int_op(download_status_get_n_attempts(&dls_failure), OP_EQ, 0); + tt_int_op(mock_get_options_calls, OP_EQ, 0); done: /* the pointers in schedule are allocated on the stack */ smartlist_free(schedule); + smartlist_free(schedule_no_initial_delay); UNMOCK(get_options); mock_options = NULL; mock_get_options_calls = 0; @@ -4035,7 +4668,6 @@ test_dir_should_use_directory_guards(void *data) tt_int_op(should_use_directory_guards(options), OP_EQ, 0); tt_int_op(CALLED(public_server_mode), OP_EQ, 1); - options->UseEntryGuardsAsDirGuards = 1; options->UseEntryGuards = 1; options->DownloadExtraInfo = 0; options->FetchDirInfoEarly = 0; @@ -4049,29 +4681,24 @@ test_dir_should_use_directory_guards(void *data) tt_int_op(CALLED(public_server_mode), OP_EQ, 3); options->UseEntryGuards = 1; - options->UseEntryGuardsAsDirGuards = 0; - tt_int_op(should_use_directory_guards(options), OP_EQ, 0); - tt_int_op(CALLED(public_server_mode), OP_EQ, 4); - options->UseEntryGuardsAsDirGuards = 1; - options->DownloadExtraInfo = 1; tt_int_op(should_use_directory_guards(options), OP_EQ, 0); - tt_int_op(CALLED(public_server_mode), OP_EQ, 5); + tt_int_op(CALLED(public_server_mode), OP_EQ, 4); options->DownloadExtraInfo = 0; options->FetchDirInfoEarly = 1; tt_int_op(should_use_directory_guards(options), OP_EQ, 0); - tt_int_op(CALLED(public_server_mode), OP_EQ, 6); + tt_int_op(CALLED(public_server_mode), OP_EQ, 5); options->FetchDirInfoEarly = 0; options->FetchDirInfoExtraEarly = 1; tt_int_op(should_use_directory_guards(options), OP_EQ, 0); - tt_int_op(CALLED(public_server_mode), OP_EQ, 7); + tt_int_op(CALLED(public_server_mode), OP_EQ, 6); options->FetchDirInfoExtraEarly = 0; options->FetchUselessDescriptors = 1; tt_int_op(should_use_directory_guards(options), OP_EQ, 0); - tt_int_op(CALLED(public_server_mode), OP_EQ, 8); + tt_int_op(CALLED(public_server_mode), OP_EQ, 7); options->FetchUselessDescriptors = 0; done: @@ -4081,14 +4708,7 @@ test_dir_should_use_directory_guards(void *data) } NS_DECL(void, -directory_initiate_command_routerstatus, (const routerstatus_t *status, - uint8_t dir_purpose, - uint8_t router_purpose, - dir_indirection_t indirection, - const char *resource, - const char *payload, - size_t payload_len, - time_t if_modified_since)); +directory_initiate_request, (directory_request_t *req)); static void test_dir_should_not_init_request_to_ourselves(void *data) @@ -4098,7 +4718,7 @@ test_dir_should_not_init_request_to_ourselves(void *data) crypto_pk_t *key = pk_generate(2); (void) data; - NS_MOCK(directory_initiate_command_routerstatus); + NS_MOCK(directory_initiate_request); clear_dir_servers(); routerlist_free_all(); @@ -4113,15 +4733,15 @@ test_dir_should_not_init_request_to_ourselves(void *data) dir_server_add(ourself); directory_get_from_all_authorities(DIR_PURPOSE_FETCH_STATUS_VOTE, 0, NULL); - tt_int_op(CALLED(directory_initiate_command_routerstatus), OP_EQ, 0); + tt_int_op(CALLED(directory_initiate_request), OP_EQ, 0); directory_get_from_all_authorities(DIR_PURPOSE_FETCH_DETACHED_SIGNATURES, 0, NULL); - tt_int_op(CALLED(directory_initiate_command_routerstatus), OP_EQ, 0); + tt_int_op(CALLED(directory_initiate_request), OP_EQ, 0); done: - NS_UNMOCK(directory_initiate_command_routerstatus); + NS_UNMOCK(directory_initiate_request); clear_dir_servers(); routerlist_free_all(); crypto_pk_free(key); @@ -4135,7 +4755,7 @@ test_dir_should_not_init_request_to_dir_auths_without_v3_info(void *data) | MICRODESC_DIRINFO; (void) data; - NS_MOCK(directory_initiate_command_routerstatus); + NS_MOCK(directory_initiate_request); clear_dir_servers(); routerlist_free_all(); @@ -4146,14 +4766,14 @@ test_dir_should_not_init_request_to_dir_auths_without_v3_info(void *data) dir_server_add(ds); directory_get_from_all_authorities(DIR_PURPOSE_FETCH_STATUS_VOTE, 0, NULL); - tt_int_op(CALLED(directory_initiate_command_routerstatus), OP_EQ, 0); + tt_int_op(CALLED(directory_initiate_request), OP_EQ, 0); directory_get_from_all_authorities(DIR_PURPOSE_FETCH_DETACHED_SIGNATURES, 0, NULL); - tt_int_op(CALLED(directory_initiate_command_routerstatus), OP_EQ, 0); + tt_int_op(CALLED(directory_initiate_request), OP_EQ, 0); done: - NS_UNMOCK(directory_initiate_command_routerstatus); + NS_UNMOCK(directory_initiate_request); clear_dir_servers(); routerlist_free_all(); } @@ -4164,7 +4784,7 @@ test_dir_should_init_request_to_dir_auths(void *data) dir_server_t *ds = NULL; (void) data; - NS_MOCK(directory_initiate_command_routerstatus); + NS_MOCK(directory_initiate_request); clear_dir_servers(); routerlist_free_all(); @@ -4175,37 +4795,23 @@ test_dir_should_init_request_to_dir_auths(void *data) dir_server_add(ds); directory_get_from_all_authorities(DIR_PURPOSE_FETCH_STATUS_VOTE, 0, NULL); - tt_int_op(CALLED(directory_initiate_command_routerstatus), OP_EQ, 1); + tt_int_op(CALLED(directory_initiate_request), OP_EQ, 1); directory_get_from_all_authorities(DIR_PURPOSE_FETCH_DETACHED_SIGNATURES, 0, NULL); - tt_int_op(CALLED(directory_initiate_command_routerstatus), OP_EQ, 2); + tt_int_op(CALLED(directory_initiate_request), OP_EQ, 2); done: - NS_UNMOCK(directory_initiate_command_routerstatus); + NS_UNMOCK(directory_initiate_request); clear_dir_servers(); routerlist_free_all(); } void -NS(directory_initiate_command_routerstatus)(const routerstatus_t *status, - uint8_t dir_purpose, - uint8_t router_purpose, - dir_indirection_t indirection, - const char *resource, - const char *payload, - size_t payload_len, - time_t if_modified_since) +NS(directory_initiate_request)(directory_request_t *req) { - (void)status; - (void)dir_purpose; - (void)router_purpose; - (void)indirection; - (void)resource; - (void)payload; - (void)payload_len; - (void)if_modified_since; - CALLED(directory_initiate_command_routerstatus)++; + (void)req; + CALLED(directory_initiate_request)++; } static void @@ -4268,13 +4874,13 @@ mock_get_datadir_fname(const or_options_t *options, * Assert we were called like get_datadir_fname2() or get_datadir_fname(), * since that's all we implement here. */ - tt_assert(options != NULL); - tt_assert(sub1 != NULL); + tt_ptr_op(options, OP_NE, NULL); + tt_ptr_op(sub1, OP_NE, NULL); /* * No particular assertions about sub2, since we could be in the * get_datadir_fname() or get_datadir_fname2() case. */ - tt_assert(suffix == NULL); + tt_ptr_op(suffix, OP_EQ, NULL); /* Just duplicate the basename and return it for this mock */ if (sub2) { @@ -4301,7 +4907,7 @@ mock_unlink_reset(void) static int mock_unlink(const char *path) { - tt_assert(path != NULL); + tt_ptr_op(path, OP_NE, NULL); tor_free(last_unlinked_path); last_unlinked_path = tor_strdup(path); @@ -4330,8 +4936,8 @@ mock_write_str_to_file(const char *path, const char *str, int bin) (void)bin; - tt_assert(path != NULL); - tt_assert(str != NULL); + tt_ptr_op(path, OP_NE, NULL); + tt_ptr_op(str, OP_NE, NULL); len = strlen(str); crypto_digest256((char *)hash, str, len, DIGEST_SHA256); @@ -4457,7 +5063,7 @@ test_dir_dump_unparseable_descriptors(void *data) * Reset the FIFO and check its state */ dump_desc_fifo_cleanup(); - tt_u64_op(len_descs_dumped, ==, 0); + tt_u64_op(len_descs_dumped, OP_EQ, 0); tt_assert(descs_dumped == NULL || smartlist_len(descs_dumped) == 0); /* @@ -4470,21 +5076,21 @@ test_dir_dump_unparseable_descriptors(void *data) /* * Assert things about the FIFO state */ - tt_u64_op(len_descs_dumped, ==, strlen(test_desc_1)); + tt_u64_op(len_descs_dumped, OP_EQ, strlen(test_desc_1)); tt_assert(descs_dumped != NULL && smartlist_len(descs_dumped) == 1); /* * Assert things about the mocks */ - tt_int_op(unlinked_count, ==, 0); - tt_int_op(write_str_count, ==, 1); + tt_int_op(unlinked_count, OP_EQ, 0); + tt_int_op(write_str_count, OP_EQ, 1); tt_mem_op(last_write_str_hash, OP_EQ, test_desc_1_hash, DIGEST_SHA256); /* * Reset the FIFO and check its state */ dump_desc_fifo_cleanup(); - tt_u64_op(len_descs_dumped, ==, 0); + tt_u64_op(len_descs_dumped, OP_EQ, 0); tt_assert(descs_dumped == NULL || smartlist_len(descs_dumped) == 0); /* @@ -4492,8 +5098,8 @@ test_dir_dump_unparseable_descriptors(void *data) */ mock_unlink_reset(); mock_write_str_to_file_reset(); - tt_int_op(unlinked_count, ==, 0); - tt_int_op(write_str_count, ==, 0); + tt_int_op(unlinked_count, OP_EQ, 0); + tt_int_op(write_str_count, OP_EQ, 0); /* * (2) Fire off dump_desc() twice; this still should trigger no cleanup. @@ -4505,14 +5111,14 @@ test_dir_dump_unparseable_descriptors(void *data) /* * Assert things about the FIFO state */ - tt_u64_op(len_descs_dumped, ==, strlen(test_desc_2)); + tt_u64_op(len_descs_dumped, OP_EQ, strlen(test_desc_2)); tt_assert(descs_dumped != NULL && smartlist_len(descs_dumped) == 1); /* * Assert things about the mocks */ - tt_int_op(unlinked_count, ==, 0); - tt_int_op(write_str_count, ==, 1); + tt_int_op(unlinked_count, OP_EQ, 0); + tt_int_op(write_str_count, OP_EQ, 1); tt_mem_op(last_write_str_hash, OP_EQ, test_desc_2_hash, DIGEST_SHA256); /* Second time */ @@ -4521,21 +5127,22 @@ test_dir_dump_unparseable_descriptors(void *data) /* * Assert things about the FIFO state */ - tt_u64_op(len_descs_dumped, ==, strlen(test_desc_2) + strlen(test_desc_3)); + tt_u64_op(len_descs_dumped, OP_EQ, + strlen(test_desc_2) + strlen(test_desc_3)); tt_assert(descs_dumped != NULL && smartlist_len(descs_dumped) == 2); /* * Assert things about the mocks */ - tt_int_op(unlinked_count, ==, 0); - tt_int_op(write_str_count, ==, 2); + tt_int_op(unlinked_count, OP_EQ, 0); + tt_int_op(write_str_count, OP_EQ, 2); tt_mem_op(last_write_str_hash, OP_EQ, test_desc_3_hash, DIGEST_SHA256); /* * Reset the FIFO and check its state */ dump_desc_fifo_cleanup(); - tt_u64_op(len_descs_dumped, ==, 0); + tt_u64_op(len_descs_dumped, OP_EQ, 0); tt_assert(descs_dumped == NULL || smartlist_len(descs_dumped) == 0); /* @@ -4543,8 +5150,8 @@ test_dir_dump_unparseable_descriptors(void *data) */ mock_unlink_reset(); mock_write_str_to_file_reset(); - tt_int_op(unlinked_count, ==, 0); - tt_int_op(write_str_count, ==, 0); + tt_int_op(unlinked_count, OP_EQ, 0); + tt_int_op(write_str_count, OP_EQ, 0); /* * (3) Three calls to dump_desc cause a FIFO cleanup @@ -4556,14 +5163,14 @@ test_dir_dump_unparseable_descriptors(void *data) /* * Assert things about the FIFO state */ - tt_u64_op(len_descs_dumped, ==, strlen(test_desc_4)); + tt_u64_op(len_descs_dumped, OP_EQ, strlen(test_desc_4)); tt_assert(descs_dumped != NULL && smartlist_len(descs_dumped) == 1); /* * Assert things about the mocks */ - tt_int_op(unlinked_count, ==, 0); - tt_int_op(write_str_count, ==, 1); + tt_int_op(unlinked_count, OP_EQ, 0); + tt_int_op(write_str_count, OP_EQ, 1); tt_mem_op(last_write_str_hash, OP_EQ, test_desc_4_hash, DIGEST_SHA256); /* Second time */ @@ -4572,14 +5179,15 @@ test_dir_dump_unparseable_descriptors(void *data) /* * Assert things about the FIFO state */ - tt_u64_op(len_descs_dumped, ==, strlen(test_desc_4) + strlen(test_desc_1)); + tt_u64_op(len_descs_dumped, OP_EQ, + strlen(test_desc_4) + strlen(test_desc_1)); tt_assert(descs_dumped != NULL && smartlist_len(descs_dumped) == 2); /* * Assert things about the mocks */ - tt_int_op(unlinked_count, ==, 0); - tt_int_op(write_str_count, ==, 2); + tt_int_op(unlinked_count, OP_EQ, 0); + tt_int_op(write_str_count, OP_EQ, 2); tt_mem_op(last_write_str_hash, OP_EQ, test_desc_1_hash, DIGEST_SHA256); /* Third time - we should unlink the dump of test_desc_4 here */ @@ -4588,21 +5196,22 @@ test_dir_dump_unparseable_descriptors(void *data) /* * Assert things about the FIFO state */ - tt_u64_op(len_descs_dumped, ==, strlen(test_desc_1) + strlen(test_desc_2)); + tt_u64_op(len_descs_dumped, OP_EQ, + strlen(test_desc_1) + strlen(test_desc_2)); tt_assert(descs_dumped != NULL && smartlist_len(descs_dumped) == 2); /* * Assert things about the mocks */ - tt_int_op(unlinked_count, ==, 1); - tt_int_op(write_str_count, ==, 3); + tt_int_op(unlinked_count, OP_EQ, 1); + tt_int_op(write_str_count, OP_EQ, 3); tt_mem_op(last_write_str_hash, OP_EQ, test_desc_2_hash, DIGEST_SHA256); /* * Reset the FIFO and check its state */ dump_desc_fifo_cleanup(); - tt_u64_op(len_descs_dumped, ==, 0); + tt_u64_op(len_descs_dumped, OP_EQ, 0); tt_assert(descs_dumped == NULL || smartlist_len(descs_dumped) == 0); /* @@ -4610,8 +5219,8 @@ test_dir_dump_unparseable_descriptors(void *data) */ mock_unlink_reset(); mock_write_str_to_file_reset(); - tt_int_op(unlinked_count, ==, 0); - tt_int_op(write_str_count, ==, 0); + tt_int_op(unlinked_count, OP_EQ, 0); + tt_int_op(write_str_count, OP_EQ, 0); /* * (4) But repeating one (A B B) doesn't overflow and cleanup @@ -4623,14 +5232,14 @@ test_dir_dump_unparseable_descriptors(void *data) /* * Assert things about the FIFO state */ - tt_u64_op(len_descs_dumped, ==, strlen(test_desc_3)); + tt_u64_op(len_descs_dumped, OP_EQ, strlen(test_desc_3)); tt_assert(descs_dumped != NULL && smartlist_len(descs_dumped) == 1); /* * Assert things about the mocks */ - tt_int_op(unlinked_count, ==, 0); - tt_int_op(write_str_count, ==, 1); + tt_int_op(unlinked_count, OP_EQ, 0); + tt_int_op(write_str_count, OP_EQ, 1); tt_mem_op(last_write_str_hash, OP_EQ, test_desc_3_hash, DIGEST_SHA256); /* Second time */ @@ -4639,14 +5248,15 @@ test_dir_dump_unparseable_descriptors(void *data) /* * Assert things about the FIFO state */ - tt_u64_op(len_descs_dumped, ==, strlen(test_desc_3) + strlen(test_desc_4)); + tt_u64_op(len_descs_dumped, OP_EQ, + strlen(test_desc_3) + strlen(test_desc_4)); tt_assert(descs_dumped != NULL && smartlist_len(descs_dumped) == 2); /* * Assert things about the mocks */ - tt_int_op(unlinked_count, ==, 0); - tt_int_op(write_str_count, ==, 2); + tt_int_op(unlinked_count, OP_EQ, 0); + tt_int_op(write_str_count, OP_EQ, 2); tt_mem_op(last_write_str_hash, OP_EQ, test_desc_4_hash, DIGEST_SHA256); /* Third time */ @@ -4655,21 +5265,22 @@ test_dir_dump_unparseable_descriptors(void *data) /* * Assert things about the FIFO state */ - tt_u64_op(len_descs_dumped, ==, strlen(test_desc_3) + strlen(test_desc_4)); + tt_u64_op(len_descs_dumped, OP_EQ, + strlen(test_desc_3) + strlen(test_desc_4)); tt_assert(descs_dumped != NULL && smartlist_len(descs_dumped) == 2); /* * Assert things about the mocks */ - tt_int_op(unlinked_count, ==, 0); - tt_int_op(write_str_count, ==, 2); + tt_int_op(unlinked_count, OP_EQ, 0); + tt_int_op(write_str_count, OP_EQ, 2); tt_mem_op(last_write_str_hash, OP_EQ, test_desc_4_hash, DIGEST_SHA256); /* * Reset the FIFO and check its state */ dump_desc_fifo_cleanup(); - tt_u64_op(len_descs_dumped, ==, 0); + tt_u64_op(len_descs_dumped, OP_EQ, 0); tt_assert(descs_dumped == NULL || smartlist_len(descs_dumped) == 0); /* @@ -4677,8 +5288,8 @@ test_dir_dump_unparseable_descriptors(void *data) */ mock_unlink_reset(); mock_write_str_to_file_reset(); - tt_int_op(unlinked_count, ==, 0); - tt_int_op(write_str_count, ==, 0); + tt_int_op(unlinked_count, OP_EQ, 0); + tt_int_op(write_str_count, OP_EQ, 0); /* * (5) Same for the (A B A) repetition @@ -4690,14 +5301,14 @@ test_dir_dump_unparseable_descriptors(void *data) /* * Assert things about the FIFO state */ - tt_u64_op(len_descs_dumped, ==, strlen(test_desc_1)); + tt_u64_op(len_descs_dumped, OP_EQ, strlen(test_desc_1)); tt_assert(descs_dumped != NULL && smartlist_len(descs_dumped) == 1); /* * Assert things about the mocks */ - tt_int_op(unlinked_count, ==, 0); - tt_int_op(write_str_count, ==, 1); + tt_int_op(unlinked_count, OP_EQ, 0); + tt_int_op(write_str_count, OP_EQ, 1); tt_mem_op(last_write_str_hash, OP_EQ, test_desc_1_hash, DIGEST_SHA256); /* Second time */ @@ -4706,14 +5317,15 @@ test_dir_dump_unparseable_descriptors(void *data) /* * Assert things about the FIFO state */ - tt_u64_op(len_descs_dumped, ==, strlen(test_desc_1) + strlen(test_desc_2)); + tt_u64_op(len_descs_dumped, OP_EQ, + strlen(test_desc_1) + strlen(test_desc_2)); tt_assert(descs_dumped != NULL && smartlist_len(descs_dumped) == 2); /* * Assert things about the mocks */ - tt_int_op(unlinked_count, ==, 0); - tt_int_op(write_str_count, ==, 2); + tt_int_op(unlinked_count, OP_EQ, 0); + tt_int_op(write_str_count, OP_EQ, 2); tt_mem_op(last_write_str_hash, OP_EQ, test_desc_2_hash, DIGEST_SHA256); /* Third time */ @@ -4722,21 +5334,22 @@ test_dir_dump_unparseable_descriptors(void *data) /* * Assert things about the FIFO state */ - tt_u64_op(len_descs_dumped, ==, strlen(test_desc_1) + strlen(test_desc_2)); + tt_u64_op(len_descs_dumped, OP_EQ, + strlen(test_desc_1) + strlen(test_desc_2)); tt_assert(descs_dumped != NULL && smartlist_len(descs_dumped) == 2); /* * Assert things about the mocks */ - tt_int_op(unlinked_count, ==, 0); - tt_int_op(write_str_count, ==, 2); + tt_int_op(unlinked_count, OP_EQ, 0); + tt_int_op(write_str_count, OP_EQ, 2); tt_mem_op(last_write_str_hash, OP_EQ, test_desc_2_hash, DIGEST_SHA256); /* * Reset the FIFO and check its state */ dump_desc_fifo_cleanup(); - tt_u64_op(len_descs_dumped, ==, 0); + tt_u64_op(len_descs_dumped, OP_EQ, 0); tt_assert(descs_dumped == NULL || smartlist_len(descs_dumped) == 0); /* @@ -4744,8 +5357,8 @@ test_dir_dump_unparseable_descriptors(void *data) */ mock_unlink_reset(); mock_write_str_to_file_reset(); - tt_int_op(unlinked_count, ==, 0); - tt_int_op(write_str_count, ==, 0); + tt_int_op(unlinked_count, OP_EQ, 0); + tt_int_op(write_str_count, OP_EQ, 0); /* * (6) (A B B C) triggering overflow on C causes A, not B to be unlinked @@ -4757,14 +5370,14 @@ test_dir_dump_unparseable_descriptors(void *data) /* * Assert things about the FIFO state */ - tt_u64_op(len_descs_dumped, ==, strlen(test_desc_3)); + tt_u64_op(len_descs_dumped, OP_EQ, strlen(test_desc_3)); tt_assert(descs_dumped != NULL && smartlist_len(descs_dumped) == 1); /* * Assert things about the mocks */ - tt_int_op(unlinked_count, ==, 0); - tt_int_op(write_str_count, ==, 1); + tt_int_op(unlinked_count, OP_EQ, 0); + tt_int_op(write_str_count, OP_EQ, 1); tt_mem_op(last_write_str_hash, OP_EQ, test_desc_3_hash, DIGEST_SHA256); /* Second time */ @@ -4773,14 +5386,15 @@ test_dir_dump_unparseable_descriptors(void *data) /* * Assert things about the FIFO state */ - tt_u64_op(len_descs_dumped, ==, strlen(test_desc_3) + strlen(test_desc_4)); + tt_u64_op(len_descs_dumped, OP_EQ, + strlen(test_desc_3) + strlen(test_desc_4)); tt_assert(descs_dumped != NULL && smartlist_len(descs_dumped) == 2); /* * Assert things about the mocks */ - tt_int_op(unlinked_count, ==, 0); - tt_int_op(write_str_count, ==, 2); + tt_int_op(unlinked_count, OP_EQ, 0); + tt_int_op(write_str_count, OP_EQ, 2); tt_mem_op(last_write_str_hash, OP_EQ, test_desc_4_hash, DIGEST_SHA256); /* Third time */ @@ -4789,14 +5403,15 @@ test_dir_dump_unparseable_descriptors(void *data) /* * Assert things about the FIFO state */ - tt_u64_op(len_descs_dumped, ==, strlen(test_desc_3) + strlen(test_desc_4)); + tt_u64_op(len_descs_dumped, OP_EQ, + strlen(test_desc_3) + strlen(test_desc_4)); tt_assert(descs_dumped != NULL && smartlist_len(descs_dumped) == 2); /* * Assert things about the mocks */ - tt_int_op(unlinked_count, ==, 0); - tt_int_op(write_str_count, ==, 2); + tt_int_op(unlinked_count, OP_EQ, 0); + tt_int_op(write_str_count, OP_EQ, 2); tt_mem_op(last_write_str_hash, OP_EQ, test_desc_4_hash, DIGEST_SHA256); /* Fourth time - we should unlink the dump of test_desc_3 here */ @@ -4805,21 +5420,22 @@ test_dir_dump_unparseable_descriptors(void *data) /* * Assert things about the FIFO state */ - tt_u64_op(len_descs_dumped, ==, strlen(test_desc_4) + strlen(test_desc_1)); + tt_u64_op(len_descs_dumped, OP_EQ, + strlen(test_desc_4) + strlen(test_desc_1)); tt_assert(descs_dumped != NULL && smartlist_len(descs_dumped) == 2); /* * Assert things about the mocks */ - tt_int_op(unlinked_count, ==, 1); - tt_int_op(write_str_count, ==, 3); + tt_int_op(unlinked_count, OP_EQ, 1); + tt_int_op(write_str_count, OP_EQ, 3); tt_mem_op(last_write_str_hash, OP_EQ, test_desc_1_hash, DIGEST_SHA256); /* * Reset the FIFO and check its state */ dump_desc_fifo_cleanup(); - tt_u64_op(len_descs_dumped, ==, 0); + tt_u64_op(len_descs_dumped, OP_EQ, 0); tt_assert(descs_dumped == NULL || smartlist_len(descs_dumped) == 0); /* @@ -4827,8 +5443,8 @@ test_dir_dump_unparseable_descriptors(void *data) */ mock_unlink_reset(); mock_write_str_to_file_reset(); - tt_int_op(unlinked_count, ==, 0); - tt_int_op(write_str_count, ==, 0); + tt_int_op(unlinked_count, OP_EQ, 0); + tt_int_op(write_str_count, OP_EQ, 0); /* * (7) (A B A C) triggering overflow on C causes B, not A to be unlinked @@ -4840,14 +5456,14 @@ test_dir_dump_unparseable_descriptors(void *data) /* * Assert things about the FIFO state */ - tt_u64_op(len_descs_dumped, ==, strlen(test_desc_2)); + tt_u64_op(len_descs_dumped, OP_EQ, strlen(test_desc_2)); tt_assert(descs_dumped != NULL && smartlist_len(descs_dumped) == 1); /* * Assert things about the mocks */ - tt_int_op(unlinked_count, ==, 0); - tt_int_op(write_str_count, ==, 1); + tt_int_op(unlinked_count, OP_EQ, 0); + tt_int_op(write_str_count, OP_EQ, 1); tt_mem_op(last_write_str_hash, OP_EQ, test_desc_2_hash, DIGEST_SHA256); /* Second time */ @@ -4856,14 +5472,15 @@ test_dir_dump_unparseable_descriptors(void *data) /* * Assert things about the FIFO state */ - tt_u64_op(len_descs_dumped, ==, strlen(test_desc_2) + strlen(test_desc_3)); + tt_u64_op(len_descs_dumped, OP_EQ, + strlen(test_desc_2) + strlen(test_desc_3)); tt_assert(descs_dumped != NULL && smartlist_len(descs_dumped) == 2); /* * Assert things about the mocks */ - tt_int_op(unlinked_count, ==, 0); - tt_int_op(write_str_count, ==, 2); + tt_int_op(unlinked_count, OP_EQ, 0); + tt_int_op(write_str_count, OP_EQ, 2); tt_mem_op(last_write_str_hash, OP_EQ, test_desc_3_hash, DIGEST_SHA256); /* Third time */ @@ -4872,14 +5489,15 @@ test_dir_dump_unparseable_descriptors(void *data) /* * Assert things about the FIFO state */ - tt_u64_op(len_descs_dumped, ==, strlen(test_desc_2) + strlen(test_desc_3)); + tt_u64_op(len_descs_dumped, OP_EQ, + strlen(test_desc_2) + strlen(test_desc_3)); tt_assert(descs_dumped != NULL && smartlist_len(descs_dumped) == 2); /* * Assert things about the mocks */ - tt_int_op(unlinked_count, ==, 0); - tt_int_op(write_str_count, ==, 2); + tt_int_op(unlinked_count, OP_EQ, 0); + tt_int_op(write_str_count, OP_EQ, 2); tt_mem_op(last_write_str_hash, OP_EQ, test_desc_3_hash, DIGEST_SHA256); /* Fourth time - we should unlink the dump of test_desc_3 here */ @@ -4888,21 +5506,22 @@ test_dir_dump_unparseable_descriptors(void *data) /* * Assert things about the FIFO state */ - tt_u64_op(len_descs_dumped, ==, strlen(test_desc_2) + strlen(test_desc_4)); + tt_u64_op(len_descs_dumped, OP_EQ, + strlen(test_desc_2) + strlen(test_desc_4)); tt_assert(descs_dumped != NULL && smartlist_len(descs_dumped) == 2); /* * Assert things about the mocks */ - tt_int_op(unlinked_count, ==, 1); - tt_int_op(write_str_count, ==, 3); + tt_int_op(unlinked_count, OP_EQ, 1); + tt_int_op(write_str_count, OP_EQ, 3); tt_mem_op(last_write_str_hash, OP_EQ, test_desc_4_hash, DIGEST_SHA256); /* * Reset the FIFO and check its state */ dump_desc_fifo_cleanup(); - tt_u64_op(len_descs_dumped, ==, 0); + tt_u64_op(len_descs_dumped, OP_EQ, 0); tt_assert(descs_dumped == NULL || smartlist_len(descs_dumped) == 0); /* @@ -4910,8 +5529,8 @@ test_dir_dump_unparseable_descriptors(void *data) */ mock_unlink_reset(); mock_write_str_to_file_reset(); - tt_int_op(unlinked_count, ==, 0); - tt_int_op(write_str_count, ==, 0); + tt_int_op(unlinked_count, OP_EQ, 0); + tt_int_op(write_str_count, OP_EQ, 0); done: @@ -4958,7 +5577,7 @@ read_file_to_str_mock(const char *filename, int flags, char *result = NULL; /* Insist we got a filename */ - tt_assert(filename != NULL); + tt_ptr_op(filename, OP_NE, NULL); /* We ignore flags */ (void)flags; @@ -5021,53 +5640,53 @@ test_dir_populate_dump_desc_fifo(void *data) reset_read_file_to_str_mock(); /* Check state of unlink mock */ - tt_int_op(unlinked_count, ==, 0); + tt_int_op(unlinked_count, OP_EQ, 0); /* Some cases that should fail before trying to read the file */ ent = dump_desc_populate_one_file(dirname, "bar"); - tt_assert(ent == NULL); - tt_int_op(unlinked_count, ==, 1); - tt_int_op(read_count, ==, 0); - tt_int_op(read_call_count, ==, 0); + tt_ptr_op(ent, OP_EQ, NULL); + tt_int_op(unlinked_count, OP_EQ, 1); + tt_int_op(read_count, OP_EQ, 0); + tt_int_op(read_call_count, OP_EQ, 0); ent = dump_desc_populate_one_file(dirname, "unparseable-desc"); - tt_assert(ent == NULL); - tt_int_op(unlinked_count, ==, 2); - tt_int_op(read_count, ==, 0); - tt_int_op(read_call_count, ==, 0); + tt_ptr_op(ent, OP_EQ, NULL); + tt_int_op(unlinked_count, OP_EQ, 2); + tt_int_op(read_count, OP_EQ, 0); + tt_int_op(read_call_count, OP_EQ, 0); ent = dump_desc_populate_one_file(dirname, "unparseable-desc.baz"); - tt_assert(ent == NULL); - tt_int_op(unlinked_count, ==, 3); - tt_int_op(read_count, ==, 0); - tt_int_op(read_call_count, ==, 0); + tt_ptr_op(ent, OP_EQ, NULL); + tt_int_op(unlinked_count, OP_EQ, 3); + tt_int_op(read_count, OP_EQ, 0); + tt_int_op(read_call_count, OP_EQ, 0); ent = dump_desc_populate_one_file( dirname, "unparseable-desc.08AE85E90461F59E"); - tt_assert(ent == NULL); - tt_int_op(unlinked_count, ==, 4); - tt_int_op(read_count, ==, 0); - tt_int_op(read_call_count, ==, 0); + tt_ptr_op(ent, OP_EQ, NULL); + tt_int_op(unlinked_count, OP_EQ, 4); + tt_int_op(read_count, OP_EQ, 0); + tt_int_op(read_call_count, OP_EQ, 0); ent = dump_desc_populate_one_file( dirname, "unparseable-desc.08AE85E90461F59EDF0981323F3A70D02B55AB54B44B04F" "287D72F7B72F242E85C8CB0EDA8854A99"); - tt_assert(ent == NULL); - tt_int_op(unlinked_count, ==, 5); - tt_int_op(read_count, ==, 0); - tt_int_op(read_call_count, ==, 0); + tt_ptr_op(ent, OP_EQ, NULL); + tt_int_op(unlinked_count, OP_EQ, 5); + tt_int_op(read_count, OP_EQ, 0); + tt_int_op(read_call_count, OP_EQ, 0); /* This is a correct-length digest but base16_decode() will fail */ ent = dump_desc_populate_one_file( dirname, "unparseable-desc.68219B8BGE64B705A6FFC728C069DC596216D60A7D7520C" "D5ECE250D912E686B"); - tt_assert(ent == NULL); - tt_int_op(unlinked_count, ==, 6); - tt_int_op(read_count, ==, 0); - tt_int_op(read_call_count, ==, 0); + tt_ptr_op(ent, OP_EQ, NULL); + tt_int_op(unlinked_count, OP_EQ, 6); + tt_int_op(read_count, OP_EQ, 0); + tt_int_op(read_call_count, OP_EQ, 0); /* This one has a correctly formed filename and should try reading */ @@ -5076,10 +5695,10 @@ test_dir_populate_dump_desc_fifo(void *data) dirname, "unparseable-desc.DF0981323F3A70D02B55AB54B44B04F287D72F7B72F242E" "85C8CB0EDA8854A99"); - tt_assert(ent == NULL); - tt_int_op(unlinked_count, ==, 7); - tt_int_op(read_count, ==, 0); - tt_int_op(read_call_count, ==, 1); + tt_ptr_op(ent, OP_EQ, NULL); + tt_int_op(unlinked_count, OP_EQ, 7); + tt_int_op(read_count, OP_EQ, 0); + tt_int_op(read_call_count, OP_EQ, 1); /* This read will succeed but the digest won't match the file content */ fname = @@ -5092,10 +5711,10 @@ test_dir_populate_dump_desc_fifo(void *data) file_stat.st_mtime = 123456; ent = dump_desc_populate_one_file(dirname, fname); enforce_expected_filename = 0; - tt_assert(ent == NULL); - tt_int_op(unlinked_count, ==, 8); - tt_int_op(read_count, ==, 1); - tt_int_op(read_call_count, ==, 2); + tt_ptr_op(ent, OP_EQ, NULL); + tt_int_op(unlinked_count, OP_EQ, 8); + tt_int_op(read_count, OP_EQ, 1); + tt_int_op(read_call_count, OP_EQ, 2); tor_free(expected_filename); tor_free(file_content); @@ -5108,13 +5727,13 @@ test_dir_populate_dump_desc_fifo(void *data) file_content_len = strlen(file_content); file_stat.st_mtime = 789012; ent = dump_desc_populate_one_file(dirname, fname); - tt_assert(ent != NULL); - tt_int_op(unlinked_count, ==, 8); - tt_int_op(read_count, ==, 2); - tt_int_op(read_call_count, ==, 3); + tt_ptr_op(ent, OP_NE, NULL); + tt_int_op(unlinked_count, OP_EQ, 8); + tt_int_op(read_count, OP_EQ, 2); + tt_int_op(read_call_count, OP_EQ, 3); tt_str_op(ent->filename, OP_EQ, expected_filename); - tt_int_op(ent->len, ==, file_content_len); - tt_int_op(ent->when, ==, file_stat.st_mtime); + tt_int_op(ent->len, OP_EQ, file_content_len); + tt_int_op(ent->when, OP_EQ, file_stat.st_mtime); tor_free(ent->filename); tor_free(ent); tor_free(expected_filename); @@ -5123,9 +5742,9 @@ test_dir_populate_dump_desc_fifo(void *data) * Reset the mocks and check their state */ mock_unlink_reset(); - tt_int_op(unlinked_count, ==, 0); + tt_int_op(unlinked_count, OP_EQ, 0); reset_read_file_to_str_mock(); - tt_int_op(read_count, ==, 0); + tt_int_op(read_count, OP_EQ, 0); done: @@ -5148,9 +5767,9 @@ listdir_mock(const char *dname) (void)dname; l = smartlist_new(); - smartlist_add(l, tor_strdup("foo")); - smartlist_add(l, tor_strdup("bar")); - smartlist_add(l, tor_strdup("baz")); + smartlist_add_strdup(l, "foo"); + smartlist_add_strdup(l, "bar"); + smartlist_add_strdup(l, "baz"); return l; } @@ -5247,9 +5866,17 @@ mock_networkstatus_consensus_can_use_extra_fallbacks( return mock_networkstatus_consensus_can_use_extra_fallbacks_value; } -/* data is a 2 character nul-terminated string. +static int mock_any_bridge_descriptors_known_value = 0; +static int +mock_any_bridge_descriptors_known(void) +{ + return mock_any_bridge_descriptors_known_value; +} + +/* data is a 3 character nul-terminated string. * If data[0] is 'b', set bootstrapping, anything else means not bootstrapping * If data[1] is 'f', set extra fallbacks, anything else means no extra + * If data[2] is 'f', set running bridges, anything else means no extra * fallbacks. */ static void @@ -5257,7 +5884,7 @@ test_dir_find_dl_schedule(void* data) { const char *str = (const char *)data; - tt_assert(strlen(data) == 2); + tt_assert(strlen(data) == 3); if (str[0] == 'b') { mock_networkstatus_consensus_is_bootstrapping_value = 1; @@ -5271,15 +5898,23 @@ test_dir_find_dl_schedule(void* data) mock_networkstatus_consensus_can_use_extra_fallbacks_value = 0; } + if (str[2] == 'r') { + mock_any_bridge_descriptors_known_value = 1; + } else { + mock_any_bridge_descriptors_known_value = 0; + } + MOCK(networkstatus_consensus_is_bootstrapping, mock_networkstatus_consensus_is_bootstrapping); MOCK(networkstatus_consensus_can_use_extra_fallbacks, mock_networkstatus_consensus_can_use_extra_fallbacks); + MOCK(any_bridge_descriptors_known, + mock_any_bridge_descriptors_known); download_status_t dls; smartlist_t server, client, server_cons, client_cons; smartlist_t client_boot_auth_only_cons, client_boot_auth_cons; - smartlist_t client_boot_fallback_cons, bridge; + smartlist_t client_boot_fallback_cons, bridge, bridge_bootstrap; mock_options = tor_malloc(sizeof(or_options_t)); reset_options(mock_options, &mock_get_options_calls); @@ -5296,6 +5931,7 @@ test_dir_find_dl_schedule(void* data) mock_options->ClientBootstrapConsensusFallbackDownloadSchedule = &client_boot_fallback_cons; mock_options->TestingBridgeDownloadSchedule = &bridge; + mock_options->TestingBridgeBootstrapDownloadSchedule = &bridge_bootstrap; dls.schedule = DL_SCHED_GENERIC; /* client */ @@ -5384,11 +6020,17 @@ test_dir_find_dl_schedule(void* data) dls.schedule = DL_SCHED_BRIDGE; /* client */ mock_options->ClientOnly = 1; - tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, &bridge); + mock_options->UseBridges = 1; + if (any_bridge_descriptors_known()) { + tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, &bridge); + } else { + tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, &bridge_bootstrap); + } done: UNMOCK(networkstatus_consensus_is_bootstrapping); UNMOCK(networkstatus_consensus_can_use_extra_fallbacks); + UNMOCK(any_bridge_descriptors_known); UNMOCK(get_options); tor_free(mock_options); mock_options = NULL; @@ -5437,6 +6079,90 @@ test_dir_assumed_flags(void *arg) routerstatus_free(rs); } +static void +test_dir_post_parsing(void *arg) +{ + (void) arg; + + /* Test the version parsing from an HS descriptor publish request. */ + { + const char *end; + const char *prefix = "/tor/hs/"; + int version = parse_hs_version_from_post("/tor/hs//publish", prefix, &end); + tt_int_op(version, OP_EQ, -1); + tt_ptr_op(end, OP_EQ, NULL); + version = parse_hs_version_from_post("/tor/hs/a/publish", prefix, &end); + tt_int_op(version, OP_EQ, -1); + tt_ptr_op(end, OP_EQ, NULL); + version = parse_hs_version_from_post("/tor/hs/3/publish", prefix, &end); + tt_int_op(version, OP_EQ, 3); + tt_str_op(end, OP_EQ, "/publish"); + version = parse_hs_version_from_post("/tor/hs/42/publish", prefix, &end); + tt_int_op(version, OP_EQ, 42); + tt_str_op(end, OP_EQ, "/publish"); + version = parse_hs_version_from_post("/tor/hs/18163/publish",prefix, &end); + tt_int_op(version, OP_EQ, 18163); + tt_str_op(end, OP_EQ, "/publish"); + version = parse_hs_version_from_post("JUNKJUNKJUNK", prefix, &end); + tt_int_op(version, OP_EQ, -1); + tt_ptr_op(end, OP_EQ, NULL); + version = parse_hs_version_from_post("/tor/hs/3/publish", "blah", &end); + tt_int_op(version, OP_EQ, -1); + tt_ptr_op(end, OP_EQ, NULL); + /* Missing the '/' at the end of the prefix. */ + version = parse_hs_version_from_post("/tor/hs/3/publish", "/tor/hs", &end); + tt_int_op(version, OP_EQ, -1); + tt_ptr_op(end, OP_EQ, NULL); + version = parse_hs_version_from_post("/random/blah/tor/hs/3/publish", + prefix, &end); + tt_int_op(version, OP_EQ, -1); + tt_ptr_op(end, OP_EQ, NULL); + version = parse_hs_version_from_post("/tor/hs/3/publish/random/junk", + prefix, &end); + tt_int_op(version, OP_EQ, 3); + tt_str_op(end, OP_EQ, "/publish/random/junk"); + version = parse_hs_version_from_post("/tor/hs/-1/publish", prefix, &end); + tt_int_op(version, OP_EQ, -1); + tt_ptr_op(end, OP_EQ, NULL); + /* INT_MAX */ + version = parse_hs_version_from_post("/tor/hs/2147483647/publish", + prefix, &end); + tt_int_op(version, OP_EQ, INT_MAX); + tt_str_op(end, OP_EQ, "/publish"); + /* INT_MAX + 1*/ + version = parse_hs_version_from_post("/tor/hs/2147483648/publish", + prefix, &end); + tt_int_op(version, OP_EQ, -1); + tt_ptr_op(end, OP_EQ, NULL); + } + + done: + ; +} + +static void +test_dir_platform_str(void *arg) +{ + char platform[256]; + (void)arg; + platform[0] = 0; + get_platform_str(platform, sizeof(platform)); + tt_int_op((int)strlen(platform), OP_GT, 0); + tt_assert(!strcmpstart(platform, "Tor ")); + + tor_version_t ver; + // make sure this is a tor version, a real actual tor version. + tt_int_op(tor_version_parse_platform(platform, &ver, 1), OP_EQ, 1); + + TT_BLATHER(("%d.%d.%d.%d", ver.major, ver.minor, ver.micro, ver.patchlevel)); + + // Handle an example version. + tt_int_op(tor_version_parse_platform( + "Tor 0.3.3.3 (foo) (git-xyzzy) on a potato", &ver, 1), OP_EQ, 1); + done: + ; +} + #define DIR_LEGACY(name) \ { #name, test_dir_ ## name , TT_FORK, NULL, NULL } @@ -5455,6 +6181,7 @@ struct testcase_t dir_tests[] = { DIR(parse_router_list, TT_FORK), DIR(load_routers, TT_FORK), DIR(load_extrainfo, TT_FORK), + DIR(getinfo_extra, 0), DIR_LEGACY(versions), DIR_LEGACY(fp_pairs), DIR(split_fps, 0), @@ -5470,7 +6197,12 @@ struct testcase_t dir_tests[] = { DIR(fmt_control_ns, 0), DIR(dirserv_set_routerstatus_testing, 0), DIR(http_handling, 0), - DIR(purpose_needs_anonymity, 0), + DIR(purpose_needs_anonymity_returns_true_for_bridges, 0), + DIR(purpose_needs_anonymity_returns_false_for_own_bridge_desc, 0), + DIR(purpose_needs_anonymity_returns_true_by_default, 0), + DIR(purpose_needs_anonymity_returns_true_for_sensitive_purpose, 0), + DIR(purpose_needs_anonymity_ret_false_for_non_sensitive_conn, 0), + DIR(post_parsing, 0), DIR(fetch_type, 0), DIR(packages, 0), DIR(download_status_schedule, 0), @@ -5486,11 +6218,17 @@ struct testcase_t dir_tests[] = { DIR(dump_unparseable_descriptors, 0), DIR(populate_dump_desc_fifo, 0), DIR(populate_dump_desc_fifo_2, 0), - DIR_ARG(find_dl_schedule, TT_FORK, "bf"), - DIR_ARG(find_dl_schedule, TT_FORK, "ba"), - DIR_ARG(find_dl_schedule, TT_FORK, "cf"), - DIR_ARG(find_dl_schedule, TT_FORK, "ca"), + DIR_ARG(find_dl_schedule, TT_FORK, "bfd"), + DIR_ARG(find_dl_schedule, TT_FORK, "bad"), + DIR_ARG(find_dl_schedule, TT_FORK, "cfd"), + DIR_ARG(find_dl_schedule, TT_FORK, "cad"), + DIR_ARG(find_dl_schedule, TT_FORK, "bfr"), + DIR_ARG(find_dl_schedule, TT_FORK, "bar"), + DIR_ARG(find_dl_schedule, TT_FORK, "cfr"), + DIR_ARG(find_dl_schedule, TT_FORK, "car"), DIR(assumed_flags, 0), + DIR(networkstatus_compute_bw_weights_v10, 0), + DIR(platform_str, 0), END_OF_TESTCASES }; |