diff options
Diffstat (limited to 'src/test')
100 files changed, 11654 insertions, 3899 deletions
diff --git a/src/test/bench.c b/src/test/bench.c index a44dc94a61..b7b123eee2 100644 --- a/src/test/bench.c +++ b/src/test/bench.c @@ -58,7 +58,7 @@ perftime(void) return timespec_to_nsec(&ts) - nanostart; } -#else +#else /* !(defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID)) */ static struct timeval tv_start = { 0, 0 }; static void reset_perftime(void) @@ -73,7 +73,7 @@ perftime(void) timersub(&now, &tv_start, &out); return ((uint64_t)out.tv_sec)*1000000000 + out.tv_usec*1000; } -#endif +#endif /* defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID) */ #define NANOCOUNT(start,end,iters) \ ( ((double)((end)-(start))) / (iters) ) @@ -200,6 +200,7 @@ bench_onion_ntor_impl(void) curve25519_public_key_generate(&keypair2.pubkey, &keypair2.seckey); dimap_add_entry(&keymap, keypair1.pubkey.public_key, &keypair1); dimap_add_entry(&keymap, keypair2.pubkey.public_key, &keypair2); + crypto_rand((char *)nodeid, sizeof(nodeid)); reset_perftime(); start = perftime(); diff --git a/src/test/ed25519_exts_ref.py b/src/test/ed25519_exts_ref.py index af5010415e..f84d3002d3 100644 --- a/src/test/ed25519_exts_ref.py +++ b/src/test/ed25519_exts_ref.py @@ -32,8 +32,7 @@ def curve25519ToEd25519(c, sign): return encodepoint([x,y]) def blindESK(esk, param): - h = H("Derive temporary signing key" + param) - mult = 2**(b-2) + sum(2**i * bit(h,i) for i in range(3,b-2)) + mult = 2**(b-2) + sum(2**i * bit(param,i) for i in range(3,b-2)) s = decodeint(esk[:32]) s_prime = (s * mult) % ell k = esk[32:] @@ -42,8 +41,7 @@ def blindESK(esk, param): return encodeint(s_prime) + k_prime def blindPK(pk, param): - h = H("Derive temporary signing key" + param) - mult = 2**(b-2) + sum(2**i * bit(h,i) for i in range(3,b-2)) + mult = 2**(b-2) + sum(2**i * bit(param,i) for i in range(3,b-2)) P = decodepoint(pk) return encodepoint(scalarmult(P, mult)) @@ -69,6 +67,11 @@ def signatureWithESK(m,h,pk): def newSK(): return os.urandom(32) +def random_scalar(entropy_f): # 0..L-1 inclusive + # reduce the bias to a safe level by generating 256 extra bits + oversized = int(binascii.hexlify(entropy_f(32+32)), 16) + return oversized % ell + # ------------------------------------------------------------ MSG = "This is extremely silly. But it is also incredibly serious business!" @@ -126,6 +129,31 @@ class SelfTest(unittest.TestCase): self._testSignatures(besk, bpk) + def testIdentity(self): + # Base point: + # B is the unique point (x, 4/5) \in E for which x is positive + By = 4 * inv(5) + Bx = xrecover(By) + B = [Bx % q,By % q] + + # Get identity E by doing: E = l*B, where l is the group order + identity = scalarmult(B, ell) + + # Get identity E by doing: E = l*A, where A is a random point + sk = newSK() + pk = decodepoint(publickey(sk)) + identity2 = scalarmult(pk, ell) + + # Check that identities match + assert(identity == identity2) + # Check that identity is the point (0,1) + assert(identity == [0L,1L]) + + # Check identity element: a*E = E, where a is a random scalar + scalar = random_scalar(os.urandom) + result = scalarmult(identity, scalar) + assert(result == identity == identity2) + # ------------------------------------------------------------ # From pprint.pprint([ binascii.b2a_hex(os.urandom(32)) for _ in xrange(8) ]) diff --git a/src/test/ed25519_vectors.inc b/src/test/ed25519_vectors.inc index 760bafb971..60c863beba 100644 --- a/src/test/ed25519_vectors.inc +++ b/src/test/ed25519_vectors.inc @@ -91,21 +91,21 @@ static const char *ED25519_BLINDING_PARAMS[] = { * blinding parameter. */ static const char *ED25519_BLINDED_SECRET_KEYS[] = { - "014e83abadb2ca9a27e0ffe23920333d817729f48700e97656ec2823d694050e171d43" + "293c3acff4e902f6f63ddc5d5caa2a57e771db4f24de65d4c28df3232f47fa01171d43" "f24e3f53e70ec7ac280044ac77d4942dee5d6807118a59bdf3ee647e89", - "fad8cca0b4335847795288b1452508752b253e64e6c7c78d4a02dbbd7d46aa0eb8ceff" + "38b88f9f9440358da544504ee152fb475528f7c51c285bd1c68b14ade8e29a07b8ceff" "20dfcf53eb52b891fc078c934efbf0353af7242e7dc51bb32a093afa29", - "116eb0ae0a4a91763365bdf86db427b00862db448487808788cc339ac10e5e089217f5" + "4d03ce16a3f3249846aac9de0a0075061495c3b027248eeee47da4ddbaf9e0049217f5" "2e92797462bd890fc274672e05c98f2c82970d640084781334aae0f940", - "bd1fbb0ee5acddc4adbcf5f33e95d9445f40326ce579fdd764a24483a9ccb20f509ece" + "51d7db01aaa0d937a9fd7c8c7381445a14d8fa61f43347af5460d7cd8fda9904509ece" "e77082ce088f7c19d5a00e955eeef8df6fa41686abc1030c2d76807733", - "237f5345cefe8573ce9fa7e216381a1172796c9e3f70668ab503b1352952530fb57b95" + "1f76cab834e222bd2546efa7e073425680ab88df186ff41327d3e40770129b00b57b95" "a440570659a440a3e4771465022a8e67af86bdf2d0990c54e7bb87ff9a", - "ba8ff23bc4ad2b739e1ccffc9fbc7837053ea81cdfdb15073f56411cfbae1d0ec492fc" + "c23588c23ee76093419d07b27c6df5922a03ac58f96c53671456a7d1bdbf560ec492fc" "87d5ec2a1b185ca5a40541fdef0b1e128fd5c2380c888bfa924711bcab", - "0fa68f969de038c7a90a4a74ee6167c77582006f2dedecc1956501ba6b6fb10391b476" + "3ed249c6932d076e1a2f6916975914b14e8c739da00992358b8f37d3e790650691b476" "8f8e556d78f4bdcb9a13b6f6066fe81d3134ae965dc48cd0785b3af2b8", - "deaa3456d1c21944d5dcd361a646858c6cf9336b0a6851d925717eb1ae186902053d9c" + "288cbfd923cb286d48c084555b5bdd06c05e92fb81acdb45271367f57515380e053d9c" "00c81e1331c06ab50087be8cfc7dc11691b132614474f1aa9c2503cccd", }; @@ -115,14 +115,14 @@ static const char *ED25519_BLINDED_SECRET_KEYS[] = { * blinding parameter. */ static const char *ED25519_BLINDED_PUBLIC_KEYS[] = { - "722d6da6348e618967ef782e71061e27163a8b35f21856475d9d2023f65b6495", - "1dffa0586da6cbfcff2024eedf4fc6c818242d9a82dbbe635d6da1b975a1160d", - "5ed81f98fed5a6acda4ea6da2c34fab0ab359d950c510c256473f1f33ff438b4", - "6e6f92a54fb282120c46d9603df41135f025bc1f58f283809d04be96aeb04040", - "cda236f28edc4c7e02d18007b8dab49d669265b0f7aefb1824d7cc8e73a2cd63", - "367b03b17b67ca7329b89a520bdab91782402a41cd67264e34b5541a4b3f875b", - "8d486b03ac4e3b486b7a1d563706c7fdac75aee789a7cf6f22789eedeff61a31", - "9f297ff0aa2ceda91c5ab1b6446f12533d145940de6d850dc323417afde0cb78", + "1fc1fa4465bd9d4956fdbdc9d3acb3c7019bb8d5606b951c2e1dfe0b42eaeb41", + "1cbbd4a88ce8f165447f159d9f628ada18674158c4f7c5ead44ce8eb0fa6eb7e", + "c5419ad133ffde7e0ac882055d942f582054132b092de377d587435722deb028", + "3e08d0dc291066272e313014bfac4d39ad84aa93c038478a58011f431648105f", + "59381f06acb6bf1389ba305f70874eed3e0f2ab57cdb7bc69ed59a9b8899ff4d", + "2b946a484344eb1c17c89dd8b04196a84f3b7222c876a07a4cece85f676f87d9", + "c6b585129b135f8769df2eba987e76e089e80ba3a2a6729134d3b28008ac098e", + "0eefdc795b59cabbc194c6174e34ba9451e8355108520554ec285acabebb34ac", }; /** diff --git a/src/test/fuzz/dict/hsdescv3 b/src/test/fuzz/dict/hsdescv3 new file mode 100644 index 0000000000..84e8db578a --- /dev/null +++ b/src/test/fuzz/dict/hsdescv3 @@ -0,0 +1,6 @@ +"hs-descriptor" +"descriptor-lifetime" +"descriptor-signing-key-cert" +"revision-counter" +"superencrypted" +"signature" diff --git a/src/test/fuzz/fuzz_hsdescv3.c b/src/test/fuzz/fuzz_hsdescv3.c new file mode 100644 index 0000000000..428774e330 --- /dev/null +++ b/src/test/fuzz/fuzz_hsdescv3.c @@ -0,0 +1,99 @@ +/* Copyright (c) 2017, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#define ROUTERPARSE_PRIVATE +#define HS_DESCRIPTOR_PRIVATE + +#include "or.h" +#include "ed25519_cert.h" /* Trunnel interface. */ +#include "crypto_ed25519.h" +#include "hs_descriptor.h" +#include "routerparse.h" +#include "util.h" + +#include "fuzzing.h" + +static void +mock_dump_desc__nodump(const char *desc, const char *type) +{ + (void)desc; + (void)type; +} + +static int +mock_rsa_ed25519_crosscert_check(const uint8_t *crosscert, + const size_t crosscert_len, + const crypto_pk_t *rsa_id_key, + const ed25519_public_key_t *master_key, + const time_t reject_if_expired_before) +{ + (void) crosscert; + (void) crosscert_len; + (void) rsa_id_key; + (void) master_key; + (void) reject_if_expired_before; + return 0; +} + +static size_t +mock_decrypt_desc_layer(const hs_descriptor_t *desc, + const uint8_t *encrypted_blob, + size_t encrypted_blob_size, + int is_superencrypted_layer, + char **decrypted_out) +{ + (void)is_superencrypted_layer; + (void)desc; + const size_t overhead = HS_DESC_ENCRYPTED_SALT_LEN + DIGEST256_LEN; + if (encrypted_blob_size < overhead) + return 0; + *decrypted_out = tor_memdup_nulterm( + encrypted_blob + HS_DESC_ENCRYPTED_SALT_LEN, + encrypted_blob_size - overhead); + size_t result = strlen(*decrypted_out); + if (result) { + return result; + } else { + tor_free(*decrypted_out); + return 0; + } +} + +int +fuzz_init(void) +{ + disable_signature_checking(); + MOCK(dump_desc, mock_dump_desc__nodump); + MOCK(rsa_ed25519_crosscert_check, mock_rsa_ed25519_crosscert_check); + MOCK(decrypt_desc_layer, mock_decrypt_desc_layer); + ed25519_init(); + return 0; +} + +int +fuzz_cleanup(void) +{ + return 0; +} + +int +fuzz_main(const uint8_t *data, size_t sz) +{ + hs_descriptor_t *desc = NULL; + uint8_t subcredential[DIGEST256_LEN]; + + char *fuzzing_data = tor_memdup_nulterm(data, sz); + memset(subcredential, 'A', sizeof(subcredential)); + + hs_desc_decode_descriptor(fuzzing_data, subcredential, &desc); + if (desc) { + log_debug(LD_GENERAL, "Decoding okay"); + hs_descriptor_free(desc); + } else { + log_debug(LD_GENERAL, "Decoding failed"); + } + + tor_free(fuzzing_data); + return 0; +} + diff --git a/src/test/fuzz/fuzz_http_connect.c b/src/test/fuzz/fuzz_http_connect.c new file mode 100644 index 0000000000..dc674070b2 --- /dev/null +++ b/src/test/fuzz/fuzz_http_connect.c @@ -0,0 +1,106 @@ +/* Copyright (c) 2016-2017, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "orconfig.h" + +#define BUFFERS_PRIVATE +#define CONNECTION_EDGE_PRIVATE + +#include "or.h" +#include "backtrace.h" +#include "buffers.h" +#include "config.h" +#include "connection.h" +#include "connection_edge.h" +#include "proto_socks.h" +#include "torlog.h" + +#include "fuzzing.h" + +static void +mock_connection_write_to_buf_impl_(const char *string, size_t len, + connection_t *conn, int compressed) +{ + log_debug(LD_GENERAL, "%sResponse:\n%u\nConnection: %p\n%s\n", + compressed ? "Compressed " : "", (unsigned)len, conn, string); +} + +static void +mock_connection_mark_unattached_ap_(entry_connection_t *conn, int endreason, + int line, const char *file) +{ + (void)conn; + (void)endreason; + (void)line; + (void)file; +} + +static int +mock_connection_ap_rewrite_and_attach_if_allowed(entry_connection_t *conn, + origin_circuit_t *circ, + crypt_path_t *cpath) +{ + (void)conn; + (void)circ; + (void)cpath; + return 0; +} + +int +fuzz_init(void) +{ + /* Set up fake response handler */ + MOCK(connection_write_to_buf_impl_, mock_connection_write_to_buf_impl_); + /* Set up the fake handler functions */ + MOCK(connection_mark_unattached_ap_, mock_connection_mark_unattached_ap_); + MOCK(connection_ap_rewrite_and_attach_if_allowed, + mock_connection_ap_rewrite_and_attach_if_allowed); + + return 0; +} + +int +fuzz_cleanup(void) +{ + UNMOCK(connection_write_to_buf_impl_); + UNMOCK(connection_mark_unattached_ap_); + UNMOCK(connection_ap_rewrite_and_attach_if_allowed); + return 0; +} + +int +fuzz_main(const uint8_t *stdin_buf, size_t data_size) +{ + entry_connection_t conn; + + /* Set up the fake connection */ + memset(&conn, 0, sizeof(conn)); + conn.edge_.base_.type = CONN_TYPE_AP; + conn.edge_.base_.state = AP_CONN_STATE_HTTP_CONNECT_WAIT; + conn.socks_request = tor_malloc_zero(sizeof(socks_request_t)); + conn.socks_request->listener_type = CONN_TYPE_AP_HTTP_CONNECT_LISTENER; + + conn.edge_.base_.inbuf = buf_new_with_data((char*)stdin_buf, data_size); + if (!conn.edge_.base_.inbuf) { + log_debug(LD_GENERAL, "Zero-Length-Input\n"); + goto done; + } + + /* Parse the headers */ + int rv = connection_ap_process_http_connect(&conn); + + /* TODO: check the output is correctly parsed based on the input */ + + log_debug(LD_GENERAL, "Result:\n%d\n", rv); + + goto done; + + done: + /* Reset. */ + socks_request_free(conn.socks_request); + buf_free(conn.edge_.base_.inbuf); + conn.edge_.base_.inbuf = NULL; + + return 0; +} + diff --git a/src/test/fuzz/fuzzing_common.c b/src/test/fuzz/fuzzing_common.c index 7aee92df63..1e98eb6c85 100644 --- a/src/test/fuzz/fuzzing_common.c +++ b/src/test/fuzz/fuzzing_common.c @@ -28,8 +28,9 @@ mock_crypto_pk_public_checksig__nocheck(const crypto_pk_t *env, char *to, (void)fromlen; /* We could look at from[0..fromlen-1] ... */ tor_assert(tolen >= crypto_pk_keysize(env)); - memset(to, 0x01, 20); - return 20; + size_t siglen = MIN(20, crypto_pk_keysize(env)); + memset(to, 0x01, siglen); + return (int)siglen; } static int @@ -107,7 +108,7 @@ global_init(void) configure_backtrace_handler(get_version()); /* set up the options. */ - mock_options = tor_malloc(sizeof(or_options_t)); + mock_options = tor_malloc_zero(sizeof(or_options_t)); MOCK(get_options, mock_get_options); /* Make BUG() and nonfatal asserts crash */ diff --git a/src/test/fuzz/include.am b/src/test/fuzz/include.am index 2961dab56f..cd16dc05be 100644 --- a/src/test/fuzz/include.am +++ b/src/test/fuzz/include.am @@ -15,13 +15,13 @@ FUZZING_LIBS = \ src/common/libor-ctime-testing.a \ src/common/libor-event-testing.a \ src/trunnel/libor-trunnel-testing.a \ + $(rust_ldadd) \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \ - @TOR_LIBEVENT_LIBS@ \ - @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ \ + @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \ + @TOR_LIB_WS32@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ @CURVE25519_LIBS@ \ @TOR_SYSTEMD_LIBS@ \ @TOR_LZMA_LIBS@ \ - @TOR_ZSTD_LIBS@ \ - $(rust_ldadd) + @TOR_ZSTD_LIBS@ oss-fuzz-prereqs: \ src/or/libtor-testing.a \ @@ -94,6 +94,14 @@ src_test_fuzz_fuzz_hsdescv2_CFLAGS = $(FUZZING_CFLAGS) src_test_fuzz_fuzz_hsdescv2_LDFLAGS = $(FUZZING_LDFLAG) src_test_fuzz_fuzz_hsdescv2_LDADD = $(FUZZING_LIBS) +src_test_fuzz_fuzz_hsdescv3_SOURCES = \ + src/test/fuzz/fuzzing_common.c \ + src/test/fuzz/fuzz_hsdescv3.c +src_test_fuzz_fuzz_hsdescv3_CPPFLAGS = $(FUZZING_CPPFLAGS) +src_test_fuzz_fuzz_hsdescv3_CFLAGS = $(FUZZING_CFLAGS) +src_test_fuzz_fuzz_hsdescv3_LDFLAGS = $(FUZZING_LDFLAG) +src_test_fuzz_fuzz_hsdescv3_LDADD = $(FUZZING_LIBS) + src_test_fuzz_fuzz_http_SOURCES = \ src/test/fuzz/fuzzing_common.c \ src/test/fuzz/fuzz_http.c @@ -102,6 +110,14 @@ src_test_fuzz_fuzz_http_CFLAGS = $(FUZZING_CFLAGS) src_test_fuzz_fuzz_http_LDFLAGS = $(FUZZING_LDFLAG) src_test_fuzz_fuzz_http_LDADD = $(FUZZING_LIBS) +src_test_fuzz_fuzz_http_connect_SOURCES = \ + src/test/fuzz/fuzzing_common.c \ + src/test/fuzz/fuzz_http_connect.c +src_test_fuzz_fuzz_http_connect_CPPFLAGS = $(FUZZING_CPPFLAGS) +src_test_fuzz_fuzz_http_connect_CFLAGS = $(FUZZING_CFLAGS) +src_test_fuzz_fuzz_http_connect_LDFLAGS = $(FUZZING_LDFLAG) +src_test_fuzz_fuzz_http_connect_LDADD = $(FUZZING_LIBS) + src_test_fuzz_fuzz_iptsv2_SOURCES = \ src/test/fuzz/fuzzing_common.c \ src/test/fuzz/fuzz_iptsv2.c @@ -133,7 +149,9 @@ FUZZERS = \ src/test/fuzz/fuzz-diff-apply \ src/test/fuzz/fuzz-extrainfo \ src/test/fuzz/fuzz-hsdescv2 \ + src/test/fuzz/fuzz-hsdescv3 \ src/test/fuzz/fuzz-http \ + src/test/fuzz/fuzz-http-connect \ src/test/fuzz/fuzz-iptsv2 \ src/test/fuzz/fuzz-microdesc \ src/test/fuzz/fuzz-vrs @@ -183,6 +201,13 @@ src_test_fuzz_lf_fuzz_hsdescv2_CFLAGS = $(LIBFUZZER_CFLAGS) src_test_fuzz_lf_fuzz_hsdescv2_LDFLAGS = $(LIBFUZZER_LDFLAG) src_test_fuzz_lf_fuzz_hsdescv2_LDADD = $(LIBFUZZER_LIBS) +src_test_fuzz_lf_fuzz_hsdescv3_SOURCES = \ + $(src_test_fuzz_fuzz_hsdescv3_SOURCES) +src_test_fuzz_lf_fuzz_hsdescv3_CPPFLAGS = $(LIBFUZZER_CPPFLAGS) +src_test_fuzz_lf_fuzz_hsdescv3_CFLAGS = $(LIBFUZZER_CFLAGS) +src_test_fuzz_lf_fuzz_hsdescv3_LDFLAGS = $(LIBFUZZER_LDFLAG) +src_test_fuzz_lf_fuzz_hsdescv3_LDADD = $(LIBFUZZER_LIBS) + src_test_fuzz_lf_fuzz_http_SOURCES = \ $(src_test_fuzz_fuzz_http_SOURCES) src_test_fuzz_lf_fuzz_http_CPPFLAGS = $(LIBFUZZER_CPPFLAGS) @@ -190,6 +215,13 @@ src_test_fuzz_lf_fuzz_http_CFLAGS = $(LIBFUZZER_CFLAGS) src_test_fuzz_lf_fuzz_http_LDFLAGS = $(LIBFUZZER_LDFLAG) src_test_fuzz_lf_fuzz_http_LDADD = $(LIBFUZZER_LIBS) +src_test_fuzz_lf_fuzz_http_connect_SOURCES = \ + $(src_test_fuzz_fuzz_http_connect_SOURCES) +src_test_fuzz_lf_fuzz_http_connect_CPPFLAGS = $(LIBFUZZER_CPPFLAGS) +src_test_fuzz_lf_fuzz_http_connect_CFLAGS = $(LIBFUZZER_CFLAGS) +src_test_fuzz_lf_fuzz_http_connect_LDFLAGS = $(LIBFUZZER_LDFLAG) +src_test_fuzz_lf_fuzz_http_connect_LDADD = $(LIBFUZZER_LIBS) + src_test_fuzz_lf_fuzz_iptsv2_SOURCES = \ $(src_test_fuzz_fuzz_iptsv2_SOURCES) src_test_fuzz_lf_fuzz_iptsv2_CPPFLAGS = $(LIBFUZZER_CPPFLAGS) @@ -218,7 +250,9 @@ LIBFUZZER_FUZZERS = \ src/test/fuzz/lf-fuzz-diff-apply \ src/test/fuzz/lf-fuzz-extrainfo \ src/test/fuzz/lf-fuzz-hsdescv2 \ + src/test/fuzz/lf-fuzz-hsdescv3 \ src/test/fuzz/lf-fuzz-http \ + src/test/fuzz/lf-fuzz-http-connect \ src/test/fuzz/lf-fuzz-iptsv2 \ src/test/fuzz/lf-fuzz-microdesc \ src/test/fuzz/lf-fuzz-vrs @@ -260,11 +294,21 @@ src_test_fuzz_liboss_fuzz_hsdescv2_a_SOURCES = \ src_test_fuzz_liboss_fuzz_hsdescv2_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS) src_test_fuzz_liboss_fuzz_hsdescv2_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS) +src_test_fuzz_liboss_fuzz_hsdescv3_a_SOURCES = \ + $(src_test_fuzz_fuzz_hsdescv3_SOURCES) +src_test_fuzz_liboss_fuzz_hsdescv3_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS) +src_test_fuzz_liboss_fuzz_hsdescv3_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS) + src_test_fuzz_liboss_fuzz_http_a_SOURCES = \ $(src_test_fuzz_fuzz_http_SOURCES) src_test_fuzz_liboss_fuzz_http_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS) src_test_fuzz_liboss_fuzz_http_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS) +src_test_fuzz_liboss_fuzz_http_connect_a_SOURCES = \ + $(src_test_fuzz_fuzz_http_connect_SOURCES) +src_test_fuzz_liboss_fuzz_http_connect_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS) +src_test_fuzz_liboss_fuzz_http_connect_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS) + src_test_fuzz_liboss_fuzz_iptsv2_a_SOURCES = \ $(src_test_fuzz_fuzz_iptsv2_SOURCES) src_test_fuzz_liboss_fuzz_iptsv2_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS) @@ -287,7 +331,9 @@ OSS_FUZZ_FUZZERS = \ src/test/fuzz/liboss-fuzz-diff-apply.a \ src/test/fuzz/liboss-fuzz-extrainfo.a \ src/test/fuzz/liboss-fuzz-hsdescv2.a \ + src/test/fuzz/liboss-fuzz-hsdescv3.a \ src/test/fuzz/liboss-fuzz-http.a \ + src/test/fuzz/liboss-fuzz-http-connect.a \ src/test/fuzz/liboss-fuzz-iptsv2.a \ src/test/fuzz/liboss-fuzz-microdesc.a \ src/test/fuzz/liboss-fuzz-vrs.a diff --git a/src/test/hs_build_address.py b/src/test/hs_build_address.py new file mode 100644 index 0000000000..7ff22c3a9a --- /dev/null +++ b/src/test/hs_build_address.py @@ -0,0 +1,38 @@ +import sys +import hashlib +import struct +import base64 + +# Python 3.6+, the SHA3 is available in hashlib natively. Else this requires +# the pysha3 package (pip install pysha3). +if sys.version_info < (3, 6): + import sha3 + +# Test vector to make sure the right sha3 version will be used. pysha3 < 1.0 +# used the old Keccak implementation. During the finalization of SHA3, NIST +# changed the delimiter suffix from 0x01 to 0x06. The Keccak sponge function +# stayed the same. pysha3 1.0 provides the previous Keccak hash, too. +TEST_VALUE = "e167f68d6563d75bb25f3aa49c29ef612d41352dc00606de7cbd630bb2665f51" +if TEST_VALUE != sha3.sha3_256(b"Hello World").hexdigest(): + print("pysha3 version is < 1.0. Please install from:") + print("https://github.com/tiran/pysha3https://github.com/tiran/pysha3") + sys.exit(1) + +# Checksum is built like so: +# CHECKSUM = SHA3(".onion checksum" || PUBKEY || VERSION) +PREFIX = ".onion checksum".encode() +# 32 bytes ed25519 pubkey from first test vector of +# https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-02#section-6 +PUBKEY = "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a".decode('hex') +# Version 3 is proposal224 +VERSION = 3 + +data = struct.pack('15s32sb', PREFIX, PUBKEY, VERSION) +checksum = hashlib.sha3_256(data).digest() + +# Onion address is built like so: +# onion_address = base32(PUBKEY || CHECKSUM || VERSION) + ".onion" +address = struct.pack('!32s2sb', PUBKEY, checksum, VERSION) +onion_addr = base64.b32encode(address).decode().lower() + +print("%s" % (onion_addr)) diff --git a/src/test/hs_indexes.py b/src/test/hs_indexes.py new file mode 100644 index 0000000000..af0b81f8de --- /dev/null +++ b/src/test/hs_indexes.py @@ -0,0 +1,70 @@ +# +# The hidden service subsystem has two type of index. The first type is a +# value that each node in the network gets assigned to using their identity +# key which is their position in the hashring. (hs_build_hsdir_index()). +# +# The second type is a value that both the client and service computes to +# store/fetch the descriptor on the hashring. (hs_build_hs_index()). +# + +import sys +import hashlib +import struct +import base64 + +# Python 3.6+, the SHA3 is available in hashlib natively. Else this requires +# the pysha3 package (pip install pysha3). +if sys.version_info < (3, 6): + import sha3 + # Test vector to make sure the right sha3 version will be used. pysha3 < 1.0 + # used the old Keccak implementation. During the finalization of SHA3, NIST + # changed the delimiter suffix from 0x01 to 0x06. The Keccak sponge function + # stayed the same. pysha3 1.0 provides the previous Keccak hash, too. + TEST_VALUE = "e167f68d6563d75bb25f3aa49c29ef612d41352dc00606de7cbd630bb2665f51" + if TEST_VALUE != sha3.sha3_256(b"Hello World").hexdigest(): + print("pysha3 version is < 1.0. Please install from:") + print("https://github.com/tiran/pysha3https://github.com/tiran/pysha3") + sys.exit(1) + +# The first index we'll build is the position index in the hashring that is +# constructed by the hs_build_hsdir_index() function. Construction is: +# SHA3-256("node-idx" | node_identity | +# shared_random_value | INT_8(period_length) | INT_8(period_num) ) + +PREFIX = "node-idx".encode() +# 32 bytes ed25519 pubkey. +IDENTITY = ("\x42" * 32).encode() +# SRV is 32 bytes. +SRV = ("\x43" * 32).encode() +# Time period length is a 8 bytes value. +PERIOD_LEN = 1440 +# Period number is a 8 bytes value. +PERIOD_NUM = 42 + +data = struct.pack('!8s32s32sQQ', PREFIX, IDENTITY, SRV, PERIOD_NUM, + PERIOD_LEN) +hsdir_index = hashlib.sha3_256(data).hexdigest() + +print("[hs_build_hsdir_index] %s" % (hsdir_index)) + +# The second index we'll build is where the HS stores and the client fetches +# the descriptor on the hashring. It is constructed by the hs_build_hs_index() +# function and the construction is: +# SHA3-256("store-at-idx" | blinded_public_key | +# INT_8(replicanum) | INT_8(period_num) | INT_8(period_length) ) + +PREFIX = "store-at-idx".encode() +# 32 bytes ed25519 pubkey. +PUBKEY = ("\x42" * 32).encode() +# Replica number is a 8 bytes value. +REPLICA_NUM = 1 +# Time period length is a 8 bytes value. +PERIOD_LEN = 1440 +# Period number is a 8 bytes value. +PERIOD_NUM = 42 + +data = struct.pack('!12s32sQQQ', PREFIX, PUBKEY, REPLICA_NUM, PERIOD_LEN, + PERIOD_NUM) +hs_index = hashlib.sha3_256(data).hexdigest() + +print("[hs_build_hs_index] %s" % (hs_index)) diff --git a/src/test/hs_ntor_ref.py b/src/test/hs_ntor_ref.py index 2ed9324e1f..542b02d2e0 100644 --- a/src/test/hs_ntor_ref.py +++ b/src/test/hs_ntor_ref.py @@ -234,8 +234,11 @@ Utilities for communicating with the little-t-tor ntor wrapper to conduct the integration tests """ -PROG = b"./src/test/test-hs-ntor-cl" -enhex=lambda s: binascii.b2a_hex(s) +PROG = "./src/test/test-hs-ntor-cl" +if sys.version_info[0] >= 3: + enhex=lambda s: binascii.b2a_hex(s).decode("ascii") +else: + enhex=lambda s: binascii.b2a_hex(s) dehex=lambda s: binascii.a2b_hex(s.strip()) def tor_client1(intro_auth_pubkey_str, intro_enc_pubkey, diff --git a/src/test/hs_test_helpers.c b/src/test/hs_test_helpers.c index 3f0d6a9413..5c1b9123d8 100644 --- a/src/test/hs_test_helpers.c +++ b/src/test/hs_test_helpers.c @@ -6,6 +6,7 @@ #include "test.h" #include "torcert.h" +#include "hs_common.h" #include "hs_test_helpers.h" hs_desc_intro_point_t * @@ -15,31 +16,31 @@ hs_helper_build_intro_point(const ed25519_keypair_t *signing_kp, time_t now, int ret; ed25519_keypair_t auth_kp; hs_desc_intro_point_t *intro_point = NULL; - hs_desc_intro_point_t *ip = tor_malloc_zero(sizeof(*ip)); - ip->link_specifiers = smartlist_new(); + hs_desc_intro_point_t *ip = hs_desc_intro_point_new(); + /* For a usable intro point we need at least two link specifiers: One legacy + * keyid and one ipv4 */ { - hs_desc_link_specifier_t *ls = tor_malloc_zero(sizeof(*ls)); - if (legacy) { - ls->type = LS_LEGACY_ID; - memcpy(ls->u.legacy_id, "0299F268FCA9D55CD157976D39AE92B4B455B3A8", - DIGEST_LEN); - } else { - ls->u.ap.port = 9001; - int family = tor_addr_parse(&ls->u.ap.addr, addr); - switch (family) { - case AF_INET: - ls->type = LS_IPV4; + hs_desc_link_specifier_t *ls_legacy = tor_malloc_zero(sizeof(*ls_legacy)); + hs_desc_link_specifier_t *ls_v4 = tor_malloc_zero(sizeof(*ls_v4)); + ls_legacy->type = LS_LEGACY_ID; + memcpy(ls_legacy->u.legacy_id, "0299F268FCA9D55CD157976D39AE92B4B455B3A8", + DIGEST_LEN); + ls_v4->u.ap.port = 9001; + int family = tor_addr_parse(&ls_v4->u.ap.addr, addr); + switch (family) { + case AF_INET: + ls_v4->type = LS_IPV4; break; case AF_INET6: - ls->type = LS_IPV6; + ls_v4->type = LS_IPV6; break; default: /* Stop the test, not suppose to have an error. */ tt_int_op(family, OP_EQ, AF_INET); - } } - smartlist_add(ip->link_specifiers, ls); + smartlist_add(ip->link_specifiers, ls_legacy); + smartlist_add(ip->link_specifiers, ls_v4); } ret = ed25519_keypair_generate(&auth_kp, 0); @@ -85,6 +86,9 @@ hs_helper_build_intro_point(const ed25519_keypair_t *signing_kp, time_t now, intro_point = ip; done: + if (intro_point == NULL) + tor_free(ip); + return intro_point; } @@ -94,8 +98,7 @@ static hs_descriptor_t * hs_helper_build_hs_desc_impl(unsigned int no_ip, const ed25519_keypair_t *signing_kp) { - int ret; - time_t now = time(NULL); + time_t now = approx_time(); ed25519_keypair_t blinded_kp; hs_descriptor_t *descp = NULL, *desc = tor_malloc_zero(sizeof(*desc)); @@ -105,8 +108,9 @@ hs_helper_build_hs_desc_impl(unsigned int no_ip, memcpy(&desc->plaintext_data.signing_pubkey, &signing_kp->pubkey, sizeof(ed25519_public_key_t)); - ret = ed25519_keypair_generate(&blinded_kp, 0); - tt_int_op(ret, ==, 0); + uint64_t current_time_period = hs_get_time_period_num(0); + hs_build_blinded_keypair(signing_kp, NULL, 0, + current_time_period, &blinded_kp); /* Copy only the public key into the descriptor. */ memcpy(&desc->plaintext_data.blinded_pubkey, &blinded_kp.pubkey, sizeof(ed25519_public_key_t)); @@ -119,6 +123,9 @@ hs_helper_build_hs_desc_impl(unsigned int no_ip, desc->plaintext_data.revision_counter = 42; desc->plaintext_data.lifetime_sec = 3 * 60 * 60; + hs_get_subcredential(&signing_kp->pubkey, &blinded_kp.pubkey, + desc->subcredential); + /* Setup encrypted data section. */ desc->encrypted_data.create2_ntor = 1; desc->encrypted_data.intro_auth_types = smartlist_new(); @@ -134,14 +141,32 @@ hs_helper_build_hs_desc_impl(unsigned int no_ip, smartlist_add(desc->encrypted_data.intro_points, hs_helper_build_intro_point(signing_kp, now, "3.2.1.4", 1)); smartlist_add(desc->encrypted_data.intro_points, - hs_helper_build_intro_point(signing_kp, now, "", 1)); + hs_helper_build_intro_point(signing_kp, now, "5.6.7.8", 1)); } descp = desc; done: + if (descp == NULL) + tor_free(desc); + return descp; } +/** Helper function to get the HS subcredential using the identity keypair of + * an HS. Used to decrypt descriptors in unittests. */ +void +hs_helper_get_subcred_from_identity_keypair(ed25519_keypair_t *signing_kp, + uint8_t *subcred_out) +{ + ed25519_keypair_t blinded_kp; + uint64_t current_time_period = hs_get_time_period_num(approx_time()); + hs_build_blinded_keypair(signing_kp, NULL, 0, + current_time_period, &blinded_kp); + + hs_get_subcredential(&signing_kp->pubkey, &blinded_kp.pubkey, + subcred_out); +} + /* Build a descriptor with introduction points. */ hs_descriptor_t * hs_helper_build_hs_desc_with_ip(const ed25519_keypair_t *signing_kp) diff --git a/src/test/hs_test_helpers.h b/src/test/hs_test_helpers.h index a7fedab136..b1b0490f05 100644 --- a/src/test/hs_test_helpers.h +++ b/src/test/hs_test_helpers.h @@ -17,6 +17,9 @@ hs_descriptor_t *hs_helper_build_hs_desc_with_ip( const ed25519_keypair_t *signing_kp); void hs_helper_desc_equal(const hs_descriptor_t *desc1, const hs_descriptor_t *desc2); +void +hs_helper_get_subcred_from_identity_keypair(ed25519_keypair_t *signing_kp, + uint8_t *subcred_out); -#endif /* TOR_HS_TEST_HELPERS_H */ +#endif /* !defined(TOR_HS_TEST_HELPERS_H) */ diff --git a/src/test/include.am b/src/test/include.am index 723b4964e1..230845a1ed 100644 --- a/src/test/include.am +++ b/src/test/include.am @@ -34,16 +34,20 @@ endif TESTS += src/test/test src/test/test-slow src/test/test-memwipe \ src/test/test_workqueue \ src/test/test_keygen.sh \ + src/test/test_key_expiration.sh \ src/test/test-timers \ $(TESTSCRIPTS) # These flavors are run using automake's test-driver and test-network.sh -TEST_CHUTNEY_FLAVORS = basic-min bridges-min hs-min single-onion +TEST_CHUTNEY_FLAVORS = basic-min bridges-min hs-v2-min hs-v3-min \ + single-onion-v23 # only run if we can ping6 ::1 (localhost) -TEST_CHUTNEY_FLAVORS_IPV6 = bridges+ipv6-min ipv6-exit-min hs-ipv6 \ - single-onion-ipv6 +# IPv6-only v3 single onion services don't work yet, so we don't test the +# single-onion-v23-ipv6-md flavor +TEST_CHUTNEY_FLAVORS_IPV6 = bridges+ipv6-min ipv6-exit-min hs-v23-ipv6-md \ + single-onion-ipv6-md # only run if we can find a stable (or simply another) version of tor -TEST_CHUTNEY_FLAVORS_MIXED = mixed +TEST_CHUTNEY_FLAVORS_MIXED = mixed+hs-v23 ### This is a lovely feature, but it requires automake >= 1.12, and Tor ### doesn't require that yet. @@ -116,7 +120,12 @@ src_test_test_SOURCES = \ src/test/test_guardfraction.c \ src/test/test_extorport.c \ src/test/test_hs.c \ + src/test/test_hs_common.c \ + src/test/test_hs_config.c \ + src/test/test_hs_cell.c \ + src/test/test_hs_ntor.c \ src/test/test_hs_service.c \ + src/test/test_hs_client.c \ src/test/test_hs_intropoint.c \ src/test/test_handles.c \ src/test/test_hs_cache.c \ @@ -132,6 +141,8 @@ src_test_test_SOURCES = \ src/test/test_options.c \ src/test/test_policy.c \ src/test/test_procmon.c \ + src/test/test_proto_http.c \ + src/test/test_proto_misc.c \ src/test/test_protover.c \ src/test/test_pt.c \ src/test/test_pubsub.c \ @@ -139,6 +150,7 @@ src_test_test_SOURCES = \ src/test/test_relaycell.c \ src/test/test_rendcache.c \ src/test/test_replay.c \ + src/test/test_router.c \ src/test/test_routerkeys.c \ src/test/test_routerlist.c \ src/test/test_routerset.c \ @@ -193,9 +205,10 @@ src_test_test_switch_id_LDFLAGS = @TOR_LDFLAGS_zlib@ src_test_test_switch_id_LDADD = \ src/common/libor-testing.a \ src/common/libor-ctime-testing.a \ + $(rust_ldadd) \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \ - @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ \ - $(rust_ldadd) + @TOR_LIB_WS32@ @TOR_LIB_USERENV@ \ + @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ src_test_test_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \ @TOR_LDFLAGS_libevent@ @@ -208,10 +221,11 @@ src_test_test_LDADD = src/or/libtor-testing.a \ src/common/libor-event-testing.a \ src/trunnel/libor-trunnel-testing.a \ src/trace/libor-trace.a \ + $(rust_ldadd) \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \ - @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ \ - @TOR_SYSTEMD_LIBS@ @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ \ - $(rust_ldadd) + @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ + @CURVE25519_LIBS@ \ + @TOR_SYSTEMD_LIBS@ @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ src_test_test_slow_CPPFLAGS = $(src_test_test_CPPFLAGS) src_test_test_slow_CFLAGS = $(src_test_test_CFLAGS) @@ -233,10 +247,11 @@ src_test_bench_LDADD = src/or/libtor.a src/common/libor.a \ src/common/libor-crypto.a $(LIBKECCAK_TINY) $(LIBDONNA) \ src/common/libor-event.a src/trunnel/libor-trunnel.a \ src/trace/libor-trace.a \ + $(rust_ldadd) \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \ - @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ \ - @TOR_SYSTEMD_LIBS@ @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ \ - $(rust_ldadd) + @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ + @CURVE25519_LIBS@ \ + @TOR_SYSTEMD_LIBS@ @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ src_test_test_workqueue_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \ @TOR_LDFLAGS_libevent@ @@ -246,10 +261,11 @@ src_test_test_workqueue_LDADD = src/or/libtor-testing.a \ src/common/libor-crypto-testing.a $(LIBKECCAK_TINY) $(LIBDONNA) \ src/common/libor-event-testing.a \ src/trace/libor-trace.a \ + $(rust_ldadd) \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \ - @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ \ - @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ \ - $(rust_ldadd) + @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ + @CURVE25519_LIBS@ \ + @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ src_test_test_timers_CPPFLAGS = $(src_test_test_CPPFLAGS) src_test_test_timers_CFLAGS = $(src_test_test_CFLAGS) @@ -258,10 +274,11 @@ src_test_test_timers_LDADD = \ src/common/libor-ctime-testing.a \ src/common/libor-event-testing.a \ src/common/libor-crypto-testing.a $(LIBKECCAK_TINY) $(LIBDONNA) \ + $(rust_ldadd) \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \ - @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ \ - @TOR_LZMA_LIBS@ \ - $(rust_ldadd) + @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ + @CURVE25519_LIBS@ \ + @TOR_LZMA_LIBS@ src_test_test_timers_LDFLAGS = $(src_test_test_LDFLAGS) noinst_HEADERS+= \ @@ -272,6 +289,7 @@ noinst_HEADERS+= \ src/test/test.h \ src/test/test_helpers.h \ src/test/test_dir_common.h \ + src/test/test_connection.h \ src/test/test_descriptors.inc \ src/test/example_extrainfo.inc \ src/test/failing_routerdescs.inc \ @@ -288,10 +306,10 @@ src_test_test_ntor_cl_LDADD = src/or/libtor.a src/common/libor.a \ src/common/libor-ctime.a \ src/common/libor-crypto.a $(LIBKECCAK_TINY) $(LIBDONNA) \ src/trace/libor-trace.a \ + $(rust_ldadd) \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \ - @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ \ - @TOR_LZMA_LIBS@ \ - $(rust_ldadd) + @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ + @CURVE25519_LIBS@ @TOR_LZMA_LIBS@ src_test_test_ntor_cl_AM_CPPFLAGS = \ -I"$(top_srcdir)/src/or" @@ -311,9 +329,9 @@ src_test_test_bt_cl_SOURCES = src/test/test_bt_cl.c src_test_test_bt_cl_LDADD = src/common/libor-testing.a \ src/common/libor-ctime-testing.a \ src/trace/libor-trace.a \ + $(rust_ldadd) \ @TOR_LIB_MATH@ \ - @TOR_LIB_WS32@ @TOR_LIB_GDI@ \ - $(rust_ldadd) + @TOR_LIB_WS32@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ src_test_test_bt_cl_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) src_test_test_bt_cl_CPPFLAGS= $(src_test_AM_CPPFLAGS) $(TEST_CPPFLAGS) @@ -321,10 +339,13 @@ EXTRA_DIST += \ src/test/bt_test.py \ src/test/ntor_ref.py \ src/test/hs_ntor_ref.py \ + src/test/hs_build_address.py \ + src/test/hs_indexes.py \ src/test/fuzz_static_testcases.sh \ src/test/slownacl_curve25519.py \ src/test/zero_length_keys.sh \ src/test/test_keygen.sh \ + src/test/test_key_expiration.sh \ src/test/test_zero_length_keys.sh \ src/test/test_ntor.sh src/test/test_hs_ntor.sh src/test/test_bt.sh \ src/test/test-network.sh \ diff --git a/src/test/log_test_helpers.h b/src/test/log_test_helpers.h index f7798c0249..70c584eb37 100644 --- a/src/test/log_test_helpers.h +++ b/src/test/log_test_helpers.h @@ -101,5 +101,5 @@ void mock_dump_saved_logs(void); assert_log_predicate(!mock_saved_log_has_entry(), \ "expected log to not contain entries"); -#endif +#endif /* !defined(TOR_LOG_TEST_HELPERS_H) */ diff --git a/src/test/ntor_ref.py b/src/test/ntor_ref.py index c753588f97..51f218f512 100755 --- a/src/test/ntor_ref.py +++ b/src/test/ntor_ref.py @@ -336,13 +336,16 @@ def test_tor(): Call the test-ntor-cl command-line program to make sure we can interoperate with Tor's ntor program """ - enhex=lambda s: binascii.b2a_hex(s) + if sys.version_info[0] >= 3: + enhex=lambda s: binascii.b2a_hex(s).decode("ascii") + else: + enhex=lambda s: binascii.b2a_hex(s) dehex=lambda s: binascii.a2b_hex(s.strip()) - PROG = b"./src/test/test-ntor-cl" + PROG = "./src/test/test-ntor-cl" def tor_client1(node_id, pubkey_B): " returns (msg, state) " - p = subprocess.Popen([PROG, b"client1", enhex(node_id), + p = subprocess.Popen([PROG, "client1", enhex(node_id), enhex(pubkey_B.serialize())], stdout=subprocess.PIPE) return map(dehex, p.stdout.readlines()) diff --git a/src/test/rend_test_helpers.c b/src/test/rend_test_helpers.c index f7880046fb..095bfecf21 100644 --- a/src/test/rend_test_helpers.c +++ b/src/test/rend_test_helpers.c @@ -71,3 +71,19 @@ create_descriptor(rend_service_descriptor_t **generated, char **service_id, crypto_pk_free(pk2); } +rend_data_t * +mock_rend_data(const char *onion_address) +{ + rend_data_v2_t *v2_data = tor_malloc_zero(sizeof(*v2_data)); + rend_data_t *rend_query = &v2_data->base_; + rend_query->version = 2; + + strlcpy(v2_data->onion_address, onion_address, + sizeof(v2_data->onion_address)); + v2_data->auth_type = REND_NO_AUTH; + rend_query->hsdirs_fp = smartlist_new(); + smartlist_add(rend_query->hsdirs_fp, tor_memdup("aaaaaaaaaaaaaaaaaaaaaaaa", + DIGEST_LEN)); + return rend_query; +} + diff --git a/src/test/rend_test_helpers.h b/src/test/rend_test_helpers.h index 486adba436..abf4324988 100644 --- a/src/test/rend_test_helpers.h +++ b/src/test/rend_test_helpers.h @@ -10,6 +10,7 @@ void generate_desc(int time_diff, rend_encoded_v2_service_descriptor_t **desc, char **service_id, int intro_points); void create_descriptor(rend_service_descriptor_t **generated, char **service_id, int intro_points); +rend_data_t *mock_rend_data(const char *onion_address); -#endif +#endif /* !defined(TOR_REND_TEST_HELPERS_H) */ diff --git a/src/test/test-child.c b/src/test/test-child.c index f0bdb3ea26..f78a829107 100644 --- a/src/test/test-child.c +++ b/src/test/test-child.c @@ -8,7 +8,7 @@ #include <windows.h> #else #include <unistd.h> -#endif +#endif /* defined(_WIN32) */ #include <string.h> #ifdef _WIN32 diff --git a/src/test/test.c b/src/test/test.c index 911ef0c24e..383bc00002 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -20,7 +20,7 @@ #include <direct.h> #else #include <dirent.h> -#endif +#endif /* defined(_WIN32) */ /* These macros pull in declarations for some functions and structures that * are typically file-private. */ @@ -142,7 +142,8 @@ test_bad_onion_handshake(void *arg) /* Server: Case 1: the encrypted data is degenerate. */ memset(junk_buf, 0, sizeof(junk_buf)); - crypto_pk_public_hybrid_encrypt(pk, junk_buf2, TAP_ONIONSKIN_CHALLENGE_LEN, + crypto_pk_obsolete_public_hybrid_encrypt(pk, + junk_buf2, TAP_ONIONSKIN_CHALLENGE_LEN, junk_buf, DH_KEY_LEN, PK_PKCS1_OAEP_PADDING, 1); tt_int_op(-1, OP_EQ, onion_skin_TAP_server_handshake(junk_buf2, pk, NULL, @@ -408,11 +409,11 @@ test_circuit_timeout(void *arg) } while (fabs(circuit_build_times_cdf(&initial, timeout0) - circuit_build_times_cdf(&initial, timeout1)) > 0.02); - tt_assert(estimate.total_build_times <= CBT_NCIRCUITS_TO_OBSERVE); + tt_int_op(estimate.total_build_times, OP_LE, CBT_NCIRCUITS_TO_OBSERVE); circuit_build_times_update_state(&estimate, state); circuit_build_times_free_timeouts(&final); - tt_assert(circuit_build_times_parse_state(&final, state) == 0); + tt_int_op(circuit_build_times_parse_state(&final, state), OP_EQ, 0); circuit_build_times_update_alpha(&final); timeout2 = circuit_build_times_calculate_timeout(&final, @@ -490,7 +491,7 @@ test_circuit_timeout(void *arg) } } - tt_assert(estimate.liveness.after_firsthop_idx == 0); + tt_int_op(estimate.liveness.after_firsthop_idx, OP_EQ, 0); tt_assert(final.liveness.after_firsthop_idx == CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT-1); @@ -533,25 +534,8 @@ test_rend_fns(void *arg) size_t intro_points_size; size_t encoded_size; int i; - char address1[] = "fooaddress.onion"; - char address2[] = "aaaaaaaaaaaaaaaa.onion"; - char address3[] = "fooaddress.exit"; - char address4[] = "www.torproject.org"; - char address5[] = "foo.abcdefghijklmnop.onion"; - char address6[] = "foo.bar.abcdefghijklmnop.onion"; - char address7[] = ".abcdefghijklmnop.onion"; (void)arg; - tt_assert(BAD_HOSTNAME == parse_extended_hostname(address1)); - tt_assert(ONION_HOSTNAME == parse_extended_hostname(address2)); - tt_str_op(address2,OP_EQ, "aaaaaaaaaaaaaaaa"); - tt_assert(EXIT_HOSTNAME == parse_extended_hostname(address3)); - tt_assert(NORMAL_HOSTNAME == parse_extended_hostname(address4)); - tt_assert(ONION_HOSTNAME == parse_extended_hostname(address5)); - tt_str_op(address5,OP_EQ, "abcdefghijklmnop"); - tt_assert(ONION_HOSTNAME == parse_extended_hostname(address6)); - tt_str_op(address6,OP_EQ, "abcdefghijklmnop"); - tt_assert(BAD_HOSTNAME == parse_extended_hostname(address7)); /* Initialize the service cache. */ rend_cache_init(); @@ -587,20 +571,21 @@ test_rend_fns(void *arg) intro->intro_key = crypto_pk_dup_key(pk2); smartlist_add(generated->intro_nodes, intro); } - tt_assert(rend_encode_v2_descriptors(descs, generated, now, 0, - REND_NO_AUTH, NULL, NULL) > 0); - tt_assert(rend_compute_v2_desc_id(computed_desc_id, service_id_base32, - NULL, now, 0) == 0); + int rv = rend_encode_v2_descriptors(descs, generated, now, 0, + REND_NO_AUTH, NULL, NULL); + tt_int_op(rv, OP_GT, 0); + rv = rend_compute_v2_desc_id(computed_desc_id, service_id_base32, NULL, + now, 0); + tt_int_op(rv, OP_EQ, 0); tt_mem_op(((rend_encoded_v2_service_descriptor_t *) smartlist_get(descs, 0))->desc_id, OP_EQ, computed_desc_id, DIGEST_LEN); - tt_assert(rend_parse_v2_service_descriptor(&parsed, parsed_desc_id, - &intro_points_encrypted, - &intro_points_size, - &encoded_size, - &next_desc, - ((rend_encoded_v2_service_descriptor_t *) - smartlist_get(descs, 0))->desc_str, 1) == 0); + rv = rend_parse_v2_service_descriptor(&parsed, parsed_desc_id, + &intro_points_encrypted, &intro_points_size, &encoded_size, + &next_desc, + ((rend_encoded_v2_service_descriptor_t *)smartlist_get(descs, 0)) + ->desc_str, 1); + tt_int_op(rv, OP_EQ, 0); tt_assert(parsed); tt_mem_op(((rend_encoded_v2_service_descriptor_t *) smartlist_get(descs, 0))->desc_id,OP_EQ, parsed_desc_id, DIGEST_LEN); @@ -802,7 +787,7 @@ test_geoip(void *arg) /* Start testing bridge statistics by making sure that we don't output * bridge stats without initializing them. */ s = geoip_format_bridge_stats(now + 86400); - tt_assert(!s); + tt_ptr_op(s, OP_EQ, NULL); /* Initialize stats and generate the bridge-stats history string out of * the connecting clients added above. */ @@ -816,7 +801,7 @@ test_geoip(void *arg) * string anymore. */ geoip_bridge_stats_term(); s = geoip_format_bridge_stats(now + 86400); - tt_assert(!s); + tt_ptr_op(s, OP_EQ, NULL); /* Stop being a bridge and start being a directory mirror that gathers * directory request statistics. */ @@ -830,7 +815,7 @@ test_geoip(void *arg) SET_TEST_ADDRESS(100); geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now); s = geoip_format_dirreq_stats(now + 86400); - tt_assert(!s); + tt_ptr_op(s, OP_EQ, NULL); /* Initialize stats, note one connecting client, and generate the * dirreq-stats history string. */ @@ -847,7 +832,7 @@ test_geoip(void *arg) SET_TEST_ADDRESS(101); geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now); s = geoip_format_dirreq_stats(now + 86400); - tt_assert(!s); + tt_ptr_op(s, OP_EQ, NULL); /* Re-start stats, add a connecting client, reset stats, and make sure * that we get an all empty history string. */ @@ -883,7 +868,7 @@ test_geoip(void *arg) SET_TEST_ADDRESS(100); geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now); s = geoip_format_entry_stats(now + 86400); - tt_assert(!s); + tt_ptr_op(s, OP_EQ, NULL); /* Initialize stats, note one connecting client, and generate the * entry-stats history string. */ @@ -900,7 +885,7 @@ test_geoip(void *arg) SET_TEST_ADDRESS(101); geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now); s = geoip_format_entry_stats(now + 86400); - tt_assert(!s); + tt_ptr_op(s, OP_EQ, NULL); /* Re-start stats, add a connecting client, reset stats, and make sure * that we get an all empty history string. */ @@ -1029,7 +1014,7 @@ test_stats(void *arg) rep_hist_note_exit_stream_opened(80); rep_hist_note_exit_bytes(80, 100, 10000); s = rep_hist_format_exit_stats(now + 86400); - tt_assert(!s); + tt_ptr_op(s, OP_EQ, NULL); /* Initialize stats, note some streams and bytes, and generate history * string. */ @@ -1067,7 +1052,7 @@ test_stats(void *arg) rep_hist_exit_stats_term(); rep_hist_note_exit_bytes(80, 100, 10000); s = rep_hist_format_exit_stats(now + 86400); - tt_assert(!s); + tt_ptr_op(s, OP_EQ, NULL); /* Re-start stats, add some bytes, reset stats, and see what history we * get when observing no streams or bytes at all. */ @@ -1086,7 +1071,7 @@ test_stats(void *arg) * conn stats without initializing them. */ rep_hist_note_or_conn_bytes(1, 20, 400, now); s = rep_hist_format_conn_stats(now + 86400); - tt_assert(!s); + tt_ptr_op(s, OP_EQ, NULL); /* Initialize stats, note bytes, and generate history string. */ rep_hist_conn_stats_init(now); @@ -1103,7 +1088,7 @@ test_stats(void *arg) rep_hist_conn_stats_term(); rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15); s = rep_hist_format_conn_stats(now + 86400); - tt_assert(!s); + tt_ptr_op(s, OP_EQ, NULL); /* Re-start stats, add some bytes, reset stats, and see what history we * get when observing no bytes at all. */ @@ -1121,7 +1106,7 @@ test_stats(void *arg) * stats without initializing them. */ rep_hist_add_buffer_stats(2.0, 2.0, 20); s = rep_hist_format_buffer_stats(now + 86400); - tt_assert(!s); + tt_ptr_op(s, OP_EQ, NULL); /* Initialize stats, add statistics for a single circuit, and generate * the history string. */ @@ -1156,7 +1141,7 @@ test_stats(void *arg) rep_hist_buffer_stats_term(); rep_hist_add_buffer_stats(2.0, 2.0, 20); s = rep_hist_format_buffer_stats(now + 86400); - tt_assert(!s); + tt_ptr_op(s, OP_EQ, NULL); /* Re-start stats, add statistics for one circuit, reset stats, and make * sure that the history has all zeros. */ @@ -1233,8 +1218,13 @@ struct testgroup_t testgroups[] = { { "extorport/", extorport_tests }, { "legacy_hs/", hs_tests }, { "hs_cache/", hs_cache }, + { "hs_cell/", hs_cell_tests }, + { "hs_common/", hs_common_tests }, + { "hs_config/", hs_config_tests }, { "hs_descriptor/", hs_descriptor }, + { "hs_ntor/", hs_ntor_tests }, { "hs_service/", hs_service_tests }, + { "hs_client/", hs_client_tests }, { "hs_intropoint/", hs_intropoint_tests }, { "introduce/", introduce_tests }, { "keypin/", keypin_tests }, @@ -1245,12 +1235,15 @@ struct testgroup_t testgroups[] = { { "options/", options_tests }, { "policy/" , policy_tests }, { "procmon/", procmon_tests }, + { "proto/http/", proto_http_tests }, + { "proto/misc/", proto_misc_tests }, { "protover/", protover_tests }, { "pt/", pt_tests }, { "relay/" , relay_tests }, { "relaycell/", relaycell_tests }, { "rend_cache/", rend_cache_tests }, { "replaycache/", replaycache_tests }, + { "router/", router_tests }, { "routerkeys/", routerkeys_tests }, { "routerlist/", routerlist_tests }, { "routerset/" , routerset_tests }, diff --git a/src/test/test.h b/src/test/test.h index ea1b16adee..3c12d2b673 100644 --- a/src/test/test.h +++ b/src/test/test.h @@ -45,8 +45,8 @@ * you're doing. */ #define tt_double_eq(a,b) \ STMT_BEGIN \ - tt_double_op((a), >=, (b)); \ - tt_double_op((a), <=, (b)); \ + tt_double_op((a), OP_GE, (b)); \ + tt_double_op((a), OP_LE, (b)); \ STMT_END #ifdef _MSC_VER @@ -55,7 +55,7 @@ #else #define U64_PRINTF_TYPE unsigned long long #define I64_PRINTF_TYPE long long -#endif +#endif /* defined(_MSC_VER) */ #define tt_size_op(a,op,b) \ tt_assert_test_fmt_type(a,b,#a" "#op" "#b,size_t,(val1_ op val2_), \ @@ -209,8 +209,13 @@ extern struct testcase_t guardfraction_tests[]; extern struct testcase_t extorport_tests[]; extern struct testcase_t hs_tests[]; extern struct testcase_t hs_cache[]; +extern struct testcase_t hs_cell_tests[]; +extern struct testcase_t hs_common_tests[]; +extern struct testcase_t hs_config_tests[]; extern struct testcase_t hs_descriptor[]; +extern struct testcase_t hs_ntor_tests[]; extern struct testcase_t hs_service_tests[]; +extern struct testcase_t hs_client_tests[]; extern struct testcase_t hs_intropoint_tests[]; extern struct testcase_t introduce_tests[]; extern struct testcase_t keypin_tests[]; @@ -223,6 +228,8 @@ extern struct testcase_t oos_tests[]; extern struct testcase_t options_tests[]; extern struct testcase_t policy_tests[]; extern struct testcase_t procmon_tests[]; +extern struct testcase_t proto_http_tests[]; +extern struct testcase_t proto_misc_tests[]; extern struct testcase_t protover_tests[]; extern struct testcase_t pubsub_tests[]; extern struct testcase_t pt_tests[]; @@ -266,5 +273,5 @@ extern const char AUTHORITY_SIGNKEY_3[]; extern const char AUTHORITY_SIGNKEY_C_DIGEST[]; extern const char AUTHORITY_SIGNKEY_C_DIGEST256[]; -#endif +#endif /* !defined(TOR_TEST_H) */ diff --git a/src/test/test_addr.c b/src/test/test_addr.c index 2f591bdfe7..e1a40b7e60 100644 --- a/src/test/test_addr.c +++ b/src/test/test_addr.c @@ -451,10 +451,10 @@ test_addr_ip6_helpers(void *arg) "::ffff:6.0.0.0"); /* XXXX wrong. */ tor_addr_parse_mask_ports("[::ffff:2.3.4.5]", 0, &t1, NULL, NULL, NULL); tor_addr_parse_mask_ports("2.3.4.5", 0, &t2, NULL, NULL, NULL); - tt_assert(tor_addr_compare(&t1, &t2, CMP_SEMANTIC) == 0); + tt_int_op(tor_addr_compare(&t1, &t2, CMP_SEMANTIC), OP_EQ, 0); tor_addr_parse_mask_ports("[::ffff:2.3.4.4]", 0, &t1, NULL, NULL, NULL); tor_addr_parse_mask_ports("2.3.4.5", 0, &t2, NULL, NULL, NULL); - tt_assert(tor_addr_compare(&t1, &t2, CMP_SEMANTIC) < 0); + tt_int_op(tor_addr_compare(&t1, &t2, CMP_SEMANTIC), OP_LT, 0); /* test compare_masked */ test_addr_compare_masked("ffff::", OP_EQ, "ffff::0", 128); @@ -637,7 +637,7 @@ test_addr_ip6_helpers(void *arg) /* Try some long addresses. */ r=tor_addr_parse_mask_ports("[ffff:1111:1111:1111:1111:1111:1111:1111]", 0, &t1, NULL, NULL, NULL); - tt_assert(r == AF_INET6); + tt_int_op(r, OP_EQ, AF_INET6); r=tor_addr_parse_mask_ports("[ffff:1111:1111:1111:1111:1111:1111:11111]", 0, &t1, NULL, NULL, NULL); tt_int_op(r, OP_EQ, -1); @@ -686,38 +686,38 @@ test_addr_ip6_helpers(void *arg) tt_int_op(r, OP_EQ, -1); r=tor_addr_parse_mask_ports("*6",0,&t1, &mask, NULL, NULL); tt_int_op(r, OP_EQ, -1); - tt_assert(r == -1); + tt_int_op(r, OP_EQ, -1); /* Try a mask with a wildcard. */ r=tor_addr_parse_mask_ports("*/16",0,&t1, &mask, NULL, NULL); - tt_assert(r == -1); + tt_int_op(r, OP_EQ, -1); r=tor_addr_parse_mask_ports("*4/16",TAPMP_EXTENDED_STAR, &t1, &mask, NULL, NULL); - tt_assert(r == -1); + tt_int_op(r, OP_EQ, -1); r=tor_addr_parse_mask_ports("*6/30",TAPMP_EXTENDED_STAR, &t1, &mask, NULL, NULL); - tt_assert(r == -1); + tt_int_op(r, OP_EQ, -1); /* Basic mask tests*/ r=tor_addr_parse_mask_ports("1.1.2.2/31",0,&t1, &mask, NULL, NULL); - tt_assert(r == AF_INET); + tt_int_op(r, OP_EQ, AF_INET); tt_int_op(mask,OP_EQ,31); tt_int_op(tor_addr_family(&t1),OP_EQ,AF_INET); tt_int_op(tor_addr_to_ipv4h(&t1),OP_EQ,0x01010202); r=tor_addr_parse_mask_ports("3.4.16.032:1-2",0,&t1, &mask, &port1, &port2); - tt_assert(r == AF_INET); + tt_int_op(r, OP_EQ, AF_INET); tt_int_op(mask,OP_EQ,32); tt_int_op(tor_addr_family(&t1),OP_EQ,AF_INET); tt_int_op(tor_addr_to_ipv4h(&t1),OP_EQ,0x03041020); - tt_assert(port1 == 1); - tt_assert(port2 == 2); + tt_uint_op(port1, OP_EQ, 1); + tt_uint_op(port2, OP_EQ, 2); r=tor_addr_parse_mask_ports("1.1.2.3/255.255.128.0",0,&t1, &mask,NULL,NULL); - tt_assert(r == AF_INET); + tt_int_op(r, OP_EQ, AF_INET); tt_int_op(mask,OP_EQ,17); tt_int_op(tor_addr_family(&t1),OP_EQ,AF_INET); tt_int_op(tor_addr_to_ipv4h(&t1),OP_EQ,0x01010203); r=tor_addr_parse_mask_ports("[efef::]/112",0,&t1, &mask, &port1, &port2); - tt_assert(r == AF_INET6); - tt_assert(port1 == 1); - tt_assert(port2 == 65535); + tt_int_op(r, OP_EQ, AF_INET6); + tt_uint_op(port1, OP_EQ, 1); + tt_uint_op(port2, OP_EQ, 65535); /* Try regular wildcard behavior without TAPMP_EXTENDED_STAR */ r=tor_addr_parse_mask_ports("*:80-443",0,&t1,&mask,&port1,&port2); tt_int_op(r,OP_EQ,AF_INET); /* Old users of this always get inet */ @@ -752,15 +752,17 @@ test_addr_ip6_helpers(void *arg) tt_int_op(port2,OP_EQ,65535); /* make sure inet address lengths >= max */ - tt_assert(INET_NTOA_BUF_LEN >= sizeof("255.255.255.255")); - tt_assert(TOR_ADDR_BUF_LEN >= - sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")); + tt_int_op(INET_NTOA_BUF_LEN, OP_GE, sizeof("255.255.255.255")); + tt_int_op(TOR_ADDR_BUF_LEN, OP_GE, + sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")); tt_assert(sizeof(tor_addr_t) >= sizeof(struct in6_addr)); /* get interface addresses */ r = get_interface_address6(LOG_DEBUG, AF_INET, &t1); + tt_int_op(r, OP_LE, 0); // "it worked or it didn't" i = get_interface_address6(LOG_DEBUG, AF_INET6, &t2); + tt_int_op(i, OP_LE, 0); // "it worked or it didn't" TT_BLATHER(("v4 address: %s (family=%d)", fmt_addr(&t1), tor_addr_family(&t1))); @@ -1010,7 +1012,7 @@ test_addr_sockaddr_to_str(void *arg) s_un.sun_family = AF_UNIX; strlcpy(s_un.sun_path, "/here/is/a/path", sizeof(s_un.sun_path)); CHECK(s_un, "unix:/here/is/a/path"); -#endif +#endif /* defined(HAVE_SYS_UN_H) */ memset(&sin6,0,sizeof(sin6)); sin6.sin6_family = AF_INET6; diff --git a/src/test/test_address.c b/src/test/test_address.c index 50a0574522..f36ff6998b 100644 --- a/src/test/test_address.c +++ b/src/test/test_address.c @@ -21,7 +21,7 @@ #include <sys/ioctl.h> #endif #include <net/if.h> -#endif +#endif /* defined(HAVE_IFCONF_TO_SMARTLIST) */ #include "or.h" #include "address.h" @@ -224,7 +224,7 @@ test_address_ifaddrs_to_smartlist(void *arg) smartlist = ifaddrs_to_smartlist(ifa, AF_UNSPEC); tt_assert(smartlist); - tt_assert(smartlist_len(smartlist) == 3); + tt_int_op(smartlist_len(smartlist), OP_EQ, 3); sockaddr_to_check = tor_malloc(sizeof(struct sockaddr_in6)); @@ -233,7 +233,7 @@ test_address_ifaddrs_to_smartlist(void *arg) tor_addr_to_sockaddr(tor_addr,0,sockaddr_to_check, sizeof(struct sockaddr_in)); - tt_int_op(addr_len,==,sizeof(struct sockaddr_in)); + tt_int_op(addr_len,OP_EQ,sizeof(struct sockaddr_in)); tt_assert(sockaddr_in_are_equal((struct sockaddr_in *)sockaddr_to_check, ipv4_sockaddr_local)); @@ -242,7 +242,7 @@ test_address_ifaddrs_to_smartlist(void *arg) tor_addr_to_sockaddr(tor_addr,0,sockaddr_to_check, sizeof(struct sockaddr_in)); - tt_int_op(addr_len,==,sizeof(struct sockaddr_in)); + tt_int_op(addr_len,OP_EQ,sizeof(struct sockaddr_in)); tt_assert(sockaddr_in_are_equal((struct sockaddr_in *)sockaddr_to_check, ipv4_sockaddr_remote)); @@ -251,7 +251,7 @@ test_address_ifaddrs_to_smartlist(void *arg) tor_addr_to_sockaddr(tor_addr,0,sockaddr_to_check, sizeof(struct sockaddr_in6)); - tt_int_op(addr_len,==,sizeof(struct sockaddr_in6)); + tt_int_op(addr_len,OP_EQ,sizeof(struct sockaddr_in6)); tt_assert(sockaddr_in6_are_equal((struct sockaddr_in6*)sockaddr_to_check, ipv6_sockaddr)); @@ -305,7 +305,7 @@ test_address_get_if_addrs_ifaddrs(void *arg) return; } -#endif +#endif /* defined(HAVE_IFADDRS_TO_SMARTLIST) */ #ifdef HAVE_IP_ADAPTER_TO_SMARTLIST @@ -319,7 +319,7 @@ test_address_get_if_addrs_win32(void *arg) results = get_interface_addresses_win32(LOG_ERR, AF_UNSPEC); - tt_int_op(smartlist_len(results),>=,1); + tt_int_op(smartlist_len(results),OP_GE,1); tt_assert(smartlist_contains_localhost_tor_addr(results)); tt_assert(!smartlist_contains_null_tor_addr(results)); @@ -384,7 +384,7 @@ test_address_ip_adapter_addresses_to_smartlist(void *arg) result = ip_adapter_addresses_to_smartlist(addrs1); tt_assert(result); - tt_assert(smartlist_len(result) == 3); + tt_int_op(smartlist_len(result), OP_EQ, 3); tor_addr = smartlist_get(result,0); @@ -421,7 +421,7 @@ test_address_ip_adapter_addresses_to_smartlist(void *arg) tor_free(sockaddr_to_check); return; } -#endif +#endif /* defined(HAVE_IP_ADAPTER_TO_SMARTLIST) */ #ifdef HAVE_IFCONF_TO_SMARTLIST @@ -456,14 +456,14 @@ test_address_ifreq_to_smartlist(void *arg) ifc->ifc_ifcu.ifcu_req = ifr; results = ifreq_to_smartlist(ifc->ifc_buf,ifc->ifc_len); - tt_int_op(smartlist_len(results),==,1); + tt_int_op(smartlist_len(results),OP_EQ,1); tor_addr = smartlist_get(results, 0); addr_len = tor_addr_to_sockaddr(tor_addr,0,(struct sockaddr *)sockaddr_to_check, sizeof(struct sockaddr_in)); - tt_int_op(addr_len,==,sizeof(struct sockaddr_in)); + tt_int_op(addr_len,OP_EQ,sizeof(struct sockaddr_in)); tt_assert(sockaddr_in_are_equal(sockaddr,sockaddr_to_check)); ifr = tor_realloc(ifr,2*sizeof(struct ifreq)); @@ -479,14 +479,14 @@ test_address_ifreq_to_smartlist(void *arg) smartlist_free(results); results = ifreq_to_smartlist(ifc->ifc_buf,ifc->ifc_len); - tt_int_op(smartlist_len(results),==,2); + tt_int_op(smartlist_len(results),OP_EQ,2); tor_addr = smartlist_get(results, 0); addr_len = tor_addr_to_sockaddr(tor_addr,0,(struct sockaddr *)sockaddr_to_check, sizeof(struct sockaddr_in)); - tt_int_op(addr_len,==,sizeof(struct sockaddr_in)); + tt_int_op(addr_len,OP_EQ,sizeof(struct sockaddr_in)); tt_assert(sockaddr_in_are_equal(sockaddr,sockaddr_to_check)); tor_addr = smartlist_get(results, 1); @@ -494,7 +494,7 @@ test_address_ifreq_to_smartlist(void *arg) tor_addr_to_sockaddr(tor_addr,0,(struct sockaddr *)sockaddr_to_check, sizeof(struct sockaddr_in)); - tt_int_op(addr_len,==,sizeof(struct sockaddr_in)); + tt_int_op(addr_len,OP_EQ,sizeof(struct sockaddr_in)); tt_assert(sockaddr_in_are_equal(sockaddr_eth1,sockaddr_to_check)); done: @@ -543,7 +543,7 @@ test_address_get_if_addrs_ioctl(void *arg) return; } -#endif +#endif /* defined(HAVE_IFCONF_TO_SMARTLIST) */ #define FAKE_SOCKET_FD (42) @@ -633,7 +633,7 @@ test_address_udp_socket_trick_whitebox(void *arg) get_interface_address6_via_udp_socket_hack(LOG_DEBUG, AF_INET, addr_from_hack); - tt_int_op(hack_retval,==,0); + tt_int_op(hack_retval,OP_EQ,0); tt_assert(tor_addr_eq_ipv4h(addr_from_hack, 0x1720f676)); /* Now, lets do an IPv6 case. */ @@ -648,7 +648,7 @@ test_address_udp_socket_trick_whitebox(void *arg) get_interface_address6_via_udp_socket_hack(LOG_DEBUG, AF_INET6, addr_from_hack); - tt_int_op(hack_retval,==,0); + tt_int_op(hack_retval,OP_EQ,0); tor_addr_to_sockaddr(addr_from_hack,0,(struct sockaddr *)ipv6_to_check, sizeof(struct sockaddr_in6)); @@ -693,7 +693,7 @@ test_address_udp_socket_trick_blackbox(void *arg) AF_INET, &addr4_to_check); - tt_int_op(retval,==,retval_reference); + tt_int_op(retval,OP_EQ,retval_reference); tt_assert( (retval == -1 && retval_reference == -1) || (tor_addr_compare(&addr4,&addr4_to_check,CMP_EXACT) == 0) ); @@ -702,11 +702,11 @@ test_address_udp_socket_trick_blackbox(void *arg) AF_INET6, &addr6_to_check); - tt_int_op(retval,==,retval_reference); + tt_int_op(retval,OP_EQ,retval_reference); tt_assert( (retval == -1 && retval_reference == -1) || (tor_addr_compare(&addr6,&addr6_to_check,CMP_EXACT) == 0) ); -#else +#else /* !(0) */ /* Both of the blackbox test cases fail horribly if: * * The host has no external addreses. * * There are multiple interfaces with either AF_INET or AF_INET6. @@ -721,7 +721,7 @@ test_address_udp_socket_trick_blackbox(void *arg) (void)addr6_to_check; (void)addr6; (void) retval_reference; -#endif +#endif /* 0 */ /* When family is neither AF_INET nor AF_INET6, we want _hack to * fail and return -1. @@ -730,7 +730,7 @@ test_address_udp_socket_trick_blackbox(void *arg) retval = get_interface_address6_via_udp_socket_hack(LOG_DEBUG, AF_INET+AF_INET6,&addr4); - tt_assert(retval == -1); + tt_int_op(retval, OP_EQ, -1); done: return; @@ -745,11 +745,11 @@ test_address_get_if_addrs_list_internal(void *arg) results = get_interface_address_list(LOG_ERR, 1); - tt_assert(results != NULL); + tt_ptr_op(results, OP_NE, NULL); /* When the network is down, a system might not have any non-local * non-multicast addresseses, not even internal ones. * Unit tests shouldn't fail because of this. */ - tt_int_op(smartlist_len(results),>=,0); + tt_int_op(smartlist_len(results),OP_GE,0); tt_assert(!smartlist_contains_localhost_tor_addr(results)); tt_assert(!smartlist_contains_multicast_tor_addr(results)); @@ -776,9 +776,9 @@ test_address_get_if_addrs_list_no_internal(void *arg) results = get_interface_address_list(LOG_ERR, 0); - tt_assert(results != NULL); + tt_ptr_op(results, OP_NE, NULL); /* Work even on systems with only internal IPv4 addresses */ - tt_int_op(smartlist_len(results),>=,0); + tt_int_op(smartlist_len(results),OP_GE,0); tt_assert(!smartlist_contains_localhost_tor_addr(results)); tt_assert(!smartlist_contains_multicast_tor_addr(results)); @@ -818,9 +818,9 @@ test_address_get_if_addrs6_list_internal(void *arg) } teardown_capture_of_logs(); - tt_assert(results != NULL); + tt_ptr_op(results, OP_NE, NULL); /* Work even on systems without IPv6 interfaces */ - tt_int_op(smartlist_len(results),>=,0); + tt_int_op(smartlist_len(results),OP_GE,0); tt_assert(!smartlist_contains_localhost_tor_addr(results)); tt_assert(!smartlist_contains_multicast_tor_addr(results)); @@ -861,9 +861,9 @@ test_address_get_if_addrs6_list_no_internal(void *arg) } teardown_capture_of_logs(); - tt_assert(results != NULL); + tt_ptr_op(results, OP_NE, NULL); /* Work even on systems without IPv6 interfaces */ - tt_int_op(smartlist_len(results),>=,0); + tt_int_op(smartlist_len(results),OP_GE,0); tt_assert(!smartlist_contains_localhost_tor_addr(results)); tt_assert(!smartlist_contains_multicast_tor_addr(results)); @@ -927,18 +927,18 @@ test_address_get_if_addrs_internal_fail(void *arg) mock_get_interface_address6_via_udp_socket_hack_fail); results1 = get_interface_address6_list(LOG_ERR, AF_INET6, 1); - tt_assert(results1 != NULL); - tt_int_op(smartlist_len(results1),==,0); + tt_ptr_op(results1, OP_NE, NULL); + tt_int_op(smartlist_len(results1),OP_EQ,0); results2 = get_interface_address_list(LOG_ERR, 1); - tt_assert(results2 != NULL); - tt_int_op(smartlist_len(results2),==,0); + tt_ptr_op(results2, OP_NE, NULL); + tt_int_op(smartlist_len(results2),OP_EQ,0); rv = get_interface_address6(LOG_ERR, AF_INET6, &ipv6_addr); - tt_assert(rv == -1); + tt_int_op(rv, OP_EQ, -1); rv = get_interface_address(LOG_ERR, &ipv4h_addr); - tt_assert(rv == -1); + tt_int_op(rv, OP_EQ, -1); done: UNMOCK(get_interface_addresses_raw); @@ -961,12 +961,12 @@ test_address_get_if_addrs_no_internal_fail(void *arg) mock_get_interface_address6_via_udp_socket_hack_fail); results1 = get_interface_address6_list(LOG_ERR, AF_INET6, 0); - tt_assert(results1 != NULL); - tt_int_op(smartlist_len(results1),==,0); + tt_ptr_op(results1, OP_NE, NULL); + tt_int_op(smartlist_len(results1),OP_EQ,0); results2 = get_interface_address_list(LOG_ERR, 0); - tt_assert(results2 != NULL); - tt_int_op(smartlist_len(results2),==,0); + tt_ptr_op(results2, OP_NE, NULL); + tt_int_op(smartlist_len(results2),OP_EQ,0); done: UNMOCK(get_interface_addresses_raw); diff --git a/src/test/test_bt_cl.c b/src/test/test_bt_cl.c index ed588ecc5b..b5c8d7cf9e 100644 --- a/src/test/test_bt_cl.c +++ b/src/test/test_bt_cl.c @@ -38,7 +38,7 @@ crash(int x) * don't need to see us dereference NULL. */ #else *(volatile int *)0 = 0; -#endif +#endif /* defined(__clang_analyzer__) || defined(__COVERITY__) */ } else if (crashtype == 1) { tor_assert(1 == 0); } else if (crashtype == -1) { diff --git a/src/test/test_buffers.c b/src/test/test_buffers.c index 07114a8571..9f4e19bc5f 100644 --- a/src/test/test_buffers.c +++ b/src/test/test_buffers.c @@ -4,9 +4,12 @@ /* See LICENSE for licensing information */ #define BUFFERS_PRIVATE +#define PROTO_HTTP_PRIVATE #include "or.h" #include "buffers.h" -#include "ext_orport.h" +#include "buffers_tls.h" +#include "proto_http.h" +#include "proto_socks.h" #include "test.h" /** Run unit tests for buffers.c */ @@ -38,15 +41,15 @@ test_buffers_basic(void *arg) for (j=0;j<256;++j) { str[j] = (char)j; } - write_to_buf(str, 256, buf); - write_to_buf(str, 256, buf); + buf_add(buf, str, 256); + buf_add(buf, str, 256); tt_int_op(buf_datalen(buf),OP_EQ, 512); - fetch_from_buf(str2, 200, buf); + buf_get_bytes(buf, str2, 200); tt_mem_op(str,OP_EQ, str2, 200); tt_int_op(buf_datalen(buf),OP_EQ, 312); memset(str2, 0, sizeof(str2)); - fetch_from_buf(str2, 256, buf); + buf_get_bytes(buf, str2, 256); tt_mem_op(str+200,OP_EQ, str2, 56); tt_mem_op(str,OP_EQ, str2+56, 200); tt_int_op(buf_datalen(buf),OP_EQ, 56); @@ -54,16 +57,16 @@ test_buffers_basic(void *arg) /* Okay, now we should be 512 bytes into the 4096-byte buffer. If we add * another 3584 bytes, we hit the end. */ for (j=0;j<15;++j) { - write_to_buf(str, 256, buf); + buf_add(buf, str, 256); } - assert_buf_ok(buf); + buf_assert_ok(buf); tt_int_op(buf_datalen(buf),OP_EQ, 3896); - fetch_from_buf(str2, 56, buf); + buf_get_bytes(buf, str2, 56); tt_int_op(buf_datalen(buf),OP_EQ, 3840); tt_mem_op(str+200,OP_EQ, str2, 56); for (j=0;j<15;++j) { memset(str2, 0, sizeof(str2)); - fetch_from_buf(str2, 256, buf); + buf_get_bytes(buf, str2, 256); tt_mem_op(str,OP_EQ, str2, 256); } tt_int_op(buf_datalen(buf),OP_EQ, 0); @@ -73,38 +76,38 @@ test_buffers_basic(void *arg) /* Okay, now make sure growing can work. */ buf = buf_new_with_capacity(16); //test_eq(buf_capacity(buf), 16); - write_to_buf(str+1, 255, buf); + buf_add(buf, str+1, 255); //test_eq(buf_capacity(buf), 256); - fetch_from_buf(str2, 254, buf); + buf_get_bytes(buf, str2, 254); tt_mem_op(str+1,OP_EQ, str2, 254); //test_eq(buf_capacity(buf), 256); - assert_buf_ok(buf); - write_to_buf(str, 32, buf); + buf_assert_ok(buf); + buf_add(buf, str, 32); //test_eq(buf_capacity(buf), 256); - assert_buf_ok(buf); - write_to_buf(str, 256, buf); - assert_buf_ok(buf); + buf_assert_ok(buf); + buf_add(buf, str, 256); + buf_assert_ok(buf); //test_eq(buf_capacity(buf), 512); tt_int_op(buf_datalen(buf),OP_EQ, 33+256); - fetch_from_buf(str2, 33, buf); + buf_get_bytes(buf, str2, 33); tt_int_op(*str2,OP_EQ, str[255]); tt_mem_op(str2+1,OP_EQ, str, 32); //test_eq(buf_capacity(buf), 512); tt_int_op(buf_datalen(buf),OP_EQ, 256); - fetch_from_buf(str2, 256, buf); + buf_get_bytes(buf, str2, 256); tt_mem_op(str,OP_EQ, str2, 256); /* now try shrinking: case 1. */ buf_free(buf); buf = buf_new_with_capacity(33668); for (j=0;j<67;++j) { - write_to_buf(str,255, buf); + buf_add(buf, str,255); } //test_eq(buf_capacity(buf), 33668); tt_int_op(buf_datalen(buf),OP_EQ, 17085); for (j=0; j < 40; ++j) { - fetch_from_buf(str2, 255,buf); + buf_get_bytes(buf, str2, 255); tt_mem_op(str2,OP_EQ, str, 255); } @@ -112,18 +115,18 @@ test_buffers_basic(void *arg) buf_free(buf); buf = buf_new_with_capacity(33668); for (j=0;j<67;++j) { - write_to_buf(str,255, buf); + buf_add(buf, str, 255); } for (j=0; j < 20; ++j) { - fetch_from_buf(str2, 255,buf); + buf_get_bytes(buf, str2, 255); tt_mem_op(str2,OP_EQ, str, 255); } for (j=0;j<80;++j) { - write_to_buf(str,255, buf); + buf_add(buf, str, 255); } //test_eq(buf_capacity(buf),33668); for (j=0; j < 120; ++j) { - fetch_from_buf(str2, 255,buf); + buf_get_bytes(buf, str2, 255); tt_mem_op(str2,OP_EQ, str, 255); } @@ -132,27 +135,27 @@ test_buffers_basic(void *arg) buf = buf_new_with_capacity(4096); buf2 = buf_new_with_capacity(4096); for (j=0;j<100;++j) - write_to_buf(str, 255, buf); + buf_add(buf, str, 255); tt_int_op(buf_datalen(buf),OP_EQ, 25500); for (j=0;j<100;++j) { r = 10; - move_buf_to_buf(buf2, buf, &r); + buf_move_to_buf(buf2, buf, &r); tt_int_op(r,OP_EQ, 0); } tt_int_op(buf_datalen(buf),OP_EQ, 24500); tt_int_op(buf_datalen(buf2),OP_EQ, 1000); for (j=0;j<3;++j) { - fetch_from_buf(str2, 255, buf2); + buf_get_bytes(buf2, str2, 255); tt_mem_op(str2,OP_EQ, str, 255); } r = 8192; /*big move*/ - move_buf_to_buf(buf2, buf, &r); + buf_move_to_buf(buf2, buf, &r); tt_int_op(r,OP_EQ, 0); r = 30000; /* incomplete move */ - move_buf_to_buf(buf2, buf, &r); + buf_move_to_buf(buf2, buf, &r); tt_int_op(r,OP_EQ, 13692); for (j=0;j<97;++j) { - fetch_from_buf(str2, 255, buf2); + buf_get_bytes(buf2, str2, 255); tt_mem_op(str2,OP_EQ, str, 255); } buf_free(buf); @@ -162,7 +165,7 @@ test_buffers_basic(void *arg) buf = buf_new_with_capacity(5); cp = "Testing. This is a moderately long Testing string."; for (j = 0; cp[j]; j++) - write_to_buf(cp+j, 1, buf); + buf_add(buf, cp+j, 1); tt_int_op(0,OP_EQ, buf_find_string_offset(buf, "Testing", 7)); tt_int_op(1,OP_EQ, buf_find_string_offset(buf, "esting", 6)); tt_int_op(1,OP_EQ, buf_find_string_offset(buf, "est", 3)); @@ -180,7 +183,7 @@ test_buffers_basic(void *arg) { char *mem = tor_malloc_zero(65536); buf = buf_new(); - write_to_buf(mem, 65536, buf); + buf_add(buf, mem, 65536); tor_free(mem); tt_int_op(buf_datalen(buf), OP_EQ, 65536); @@ -215,8 +218,7 @@ test_buffer_pullup(void *arg) /* There are a bunch of cases for pullup. One is the trivial case. Let's mess around with an empty buffer. */ - buf_pullup(buf, 16); - buf_get_first_chunk_data(buf, &cp, &sz); + buf_pullup(buf, 16, &cp, &sz); tt_ptr_op(cp, OP_EQ, NULL); tt_uint_op(sz, OP_EQ, 0); @@ -227,65 +229,62 @@ test_buffer_pullup(void *arg) /* Let's add some data. */ crypto_rand(stuff, 16384); - write_to_buf(stuff, 3000, buf); - write_to_buf(stuff+3000, 3000, buf); - buf_get_first_chunk_data(buf, &cp, &sz); + buf_add(buf, stuff, 3000); + buf_add(buf, stuff+3000, 3000); + buf_pullup(buf, 0, &cp, &sz); tt_ptr_op(cp, OP_NE, NULL); tt_int_op(sz, OP_LE, 4096); /* Make room for 3000 bytes in the first chunk, so that the pullup-move code * can get tested. */ - tt_int_op(fetch_from_buf(tmp, 3000, buf), OP_EQ, 3000); + tt_int_op(buf_get_bytes(buf, tmp, 3000), OP_EQ, 3000); tt_mem_op(tmp,OP_EQ, stuff, 3000); - buf_pullup(buf, 2048); - assert_buf_ok(buf); - buf_get_first_chunk_data(buf, &cp, &sz); + buf_pullup(buf, 2048, &cp, &sz); + buf_assert_ok(buf); tt_ptr_op(cp, OP_NE, NULL); tt_int_op(sz, OP_GE, 2048); tt_mem_op(cp,OP_EQ, stuff+3000, 2048); tt_int_op(3000, OP_EQ, buf_datalen(buf)); - tt_int_op(fetch_from_buf(tmp, 3000, buf), OP_EQ, 0); + tt_int_op(buf_get_bytes(buf, tmp, 3000), OP_EQ, 0); tt_mem_op(tmp,OP_EQ, stuff+3000, 2048); buf_free(buf); /* Now try the large-chunk case. */ buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */ - write_to_buf(stuff, 4000, buf); - write_to_buf(stuff+4000, 4000, buf); - write_to_buf(stuff+8000, 4000, buf); - write_to_buf(stuff+12000, 4000, buf); + buf_add(buf, stuff, 4000); + buf_add(buf, stuff+4000, 4000); + buf_add(buf, stuff+8000, 4000); + buf_add(buf, stuff+12000, 4000); tt_int_op(buf_datalen(buf), OP_EQ, 16000); - buf_get_first_chunk_data(buf, &cp, &sz); + buf_pullup(buf, 0, &cp, &sz); tt_ptr_op(cp, OP_NE, NULL); tt_int_op(sz, OP_LE, 4096); - buf_pullup(buf, 12500); - assert_buf_ok(buf); - buf_get_first_chunk_data(buf, &cp, &sz); + buf_pullup(buf, 12500, &cp, &sz); + buf_assert_ok(buf); tt_ptr_op(cp, OP_NE, NULL); tt_int_op(sz, OP_GE, 12500); tt_mem_op(cp,OP_EQ, stuff, 12500); tt_int_op(buf_datalen(buf), OP_EQ, 16000); - fetch_from_buf(tmp, 12400, buf); + buf_get_bytes(buf, tmp, 12400); tt_mem_op(tmp,OP_EQ, stuff, 12400); tt_int_op(buf_datalen(buf), OP_EQ, 3600); - fetch_from_buf(tmp, 3500, buf); + buf_get_bytes(buf, tmp, 3500); tt_mem_op(tmp,OP_EQ, stuff+12400, 3500); - fetch_from_buf(tmp, 100, buf); + buf_get_bytes(buf, tmp, 100); tt_mem_op(tmp,OP_EQ, stuff+15900, 10); buf_free(buf); /* Make sure that the pull-up-whole-buffer case works */ buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */ - write_to_buf(stuff, 4000, buf); - write_to_buf(stuff+4000, 4000, buf); - fetch_from_buf(tmp, 100, buf); /* dump 100 bytes from first chunk */ - buf_pullup(buf, 16000); /* Way too much. */ - assert_buf_ok(buf); - buf_get_first_chunk_data(buf, &cp, &sz); + buf_add(buf, stuff, 4000); + buf_add(buf, stuff+4000, 4000); + buf_get_bytes(buf, tmp, 100); /* dump 100 bytes from first chunk */ + buf_pullup(buf, 16000, &cp, &sz); + buf_assert_ok(buf); tt_ptr_op(cp, OP_NE, NULL); tt_int_op(sz, OP_EQ, 7900); tt_mem_op(cp,OP_EQ, stuff+100, 7900); @@ -321,23 +320,23 @@ test_buffer_copy(void *arg) /* Now try with a short buffer. */ s = "And now comes an act of enormous enormance!"; len = strlen(s); - write_to_buf(s, len, buf); + buf_add(buf, s, len); tt_int_op(len, OP_EQ, buf_datalen(buf)); /* Add junk to buf2 so we can test replacing.*/ - write_to_buf("BLARG", 5, buf2); + buf_add(buf2, "BLARG", 5); tt_int_op(0, OP_EQ, buf_set_to_copy(&buf2, buf)); tt_int_op(len, OP_EQ, buf_datalen(buf2)); - fetch_from_buf(b, len, buf2); + buf_get_bytes(buf2, b, len); tt_mem_op(b, OP_EQ, s, len); /* Now free buf2 and retry so we can test allocating */ buf_free(buf2); buf2 = NULL; tt_int_op(0, OP_EQ, buf_set_to_copy(&buf2, buf)); tt_int_op(len, OP_EQ, buf_datalen(buf2)); - fetch_from_buf(b, len, buf2); + buf_get_bytes(buf2, b, len); tt_mem_op(b, OP_EQ, s, len); /* Clear buf for next test */ - fetch_from_buf(b, len, buf); + buf_get_bytes(buf, b, len); tt_int_op(buf_datalen(buf),OP_EQ,0); /* Okay, now let's try a bigger buffer. */ @@ -347,13 +346,13 @@ test_buffer_copy(void *arg) len = strlen(s); for (i = 0; i < 256; ++i) { b[0]=i; - write_to_buf(b, 1, buf); - write_to_buf(s, len, buf); + buf_add(buf, b, 1); + buf_add(buf, s, len); } tt_int_op(0, OP_EQ, buf_set_to_copy(&buf2, buf)); tt_int_op(buf_datalen(buf2), OP_EQ, buf_datalen(buf)); for (i = 0; i < 256; ++i) { - fetch_from_buf(b, len+1, buf2); + buf_get_bytes(buf2, b, len+1); tt_int_op((unsigned char)b[0],OP_EQ,i); tt_mem_op(b+1, OP_EQ, s, len); } @@ -366,79 +365,6 @@ test_buffer_copy(void *arg) } static void -test_buffer_ext_or_cmd(void *arg) -{ - ext_or_cmd_t *cmd = NULL; - buf_t *buf = buf_new(); - char *tmp = NULL; - (void) arg; - - /* Empty -- should give "not there. */ - tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd)); - tt_ptr_op(NULL, OP_EQ, cmd); - - /* Three bytes: shouldn't work. */ - write_to_buf("\x00\x20\x00", 3, buf); - tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd)); - tt_ptr_op(NULL, OP_EQ, cmd); - tt_int_op(3, OP_EQ, buf_datalen(buf)); - - /* 0020 0000: That's a nil command. It should work. */ - write_to_buf("\x00", 1, buf); - tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd)); - tt_ptr_op(NULL, OP_NE, cmd); - tt_int_op(0x20, OP_EQ, cmd->cmd); - tt_int_op(0, OP_EQ, cmd->len); - tt_int_op(0, OP_EQ, buf_datalen(buf)); - ext_or_cmd_free(cmd); - cmd = NULL; - - /* Now try a length-6 command with one byte missing. */ - write_to_buf("\x10\x21\x00\x06""abcde", 9, buf); - tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd)); - tt_ptr_op(NULL, OP_EQ, cmd); - write_to_buf("f", 1, buf); - tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd)); - tt_ptr_op(NULL, OP_NE, cmd); - tt_int_op(0x1021, OP_EQ, cmd->cmd); - tt_int_op(6, OP_EQ, cmd->len); - tt_mem_op("abcdef", OP_EQ, cmd->body, 6); - tt_int_op(0, OP_EQ, buf_datalen(buf)); - ext_or_cmd_free(cmd); - cmd = NULL; - - /* Now try a length-10 command with 4 extra bytes. */ - write_to_buf("\xff\xff\x00\x0aloremipsum\x10\x00\xff\xff", 18, buf); - tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd)); - tt_ptr_op(NULL, OP_NE, cmd); - tt_int_op(0xffff, OP_EQ, cmd->cmd); - tt_int_op(10, OP_EQ, cmd->len); - tt_mem_op("loremipsum", OP_EQ, cmd->body, 10); - tt_int_op(4, OP_EQ, buf_datalen(buf)); - ext_or_cmd_free(cmd); - cmd = NULL; - - /* Finally, let's try a maximum-length command. We already have the header - * waiting. */ - tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd)); - tmp = tor_malloc_zero(65535); - write_to_buf(tmp, 65535, buf); - tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd)); - tt_ptr_op(NULL, OP_NE, cmd); - tt_int_op(0x1000, OP_EQ, cmd->cmd); - tt_int_op(0xffff, OP_EQ, cmd->len); - tt_mem_op(tmp, OP_EQ, cmd->body, 65535); - tt_int_op(0, OP_EQ, buf_datalen(buf)); - ext_or_cmd_free(cmd); - cmd = NULL; - - done: - ext_or_cmd_free(cmd); - buf_free(buf); - tor_free(tmp); -} - -static void test_buffer_allocation_tracking(void *arg) { char *junk = tor_malloc(16384); @@ -458,36 +384,36 @@ test_buffer_allocation_tracking(void *arg) tt_int_op(buf_allocation(buf1), OP_EQ, 0); tt_int_op(buf_get_total_allocation(), OP_EQ, 0); - write_to_buf(junk, 4000, buf1); - write_to_buf(junk, 4000, buf1); - write_to_buf(junk, 4000, buf1); - write_to_buf(junk, 4000, buf1); + buf_add(buf1, junk, 4000); + buf_add(buf1, junk, 4000); + buf_add(buf1, junk, 4000); + buf_add(buf1, junk, 4000); tt_int_op(buf_allocation(buf1), OP_EQ, 16384); - fetch_from_buf(junk, 100, buf1); + buf_get_bytes(buf1, junk, 100); tt_int_op(buf_allocation(buf1), OP_EQ, 16384); /* still 4 4k chunks */ tt_int_op(buf_get_total_allocation(), OP_EQ, 16384); - fetch_from_buf(junk, 4096, buf1); /* drop a 1k chunk... */ + buf_get_bytes(buf1, junk, 4096); /* drop a 1k chunk... */ tt_int_op(buf_allocation(buf1), OP_EQ, 3*4096); /* now 3 4k chunks */ tt_int_op(buf_get_total_allocation(), OP_EQ, 12288); /* that chunk was really freed. */ - write_to_buf(junk, 4000, buf2); + buf_add(buf2, junk, 4000); tt_int_op(buf_allocation(buf2), OP_EQ, 4096); /* another 4k chunk. */ /* * We bounce back up to 16384 by allocating a new chunk. */ tt_int_op(buf_get_total_allocation(), OP_EQ, 16384); - write_to_buf(junk, 4000, buf2); + buf_add(buf2, junk, 4000); tt_int_op(buf_allocation(buf2), OP_EQ, 8192); /* another 4k chunk. */ tt_int_op(buf_get_total_allocation(), OP_EQ, 5*4096); /* that chunk was new. */ /* Make a really huge buffer */ for (i = 0; i < 1000; ++i) { - write_to_buf(junk, 4000, buf2); + buf_add(buf2, junk, 4000); } tt_int_op(buf_allocation(buf2), OP_GE, 4008000); tt_int_op(buf_get_total_allocation(), OP_GE, 4008000); @@ -530,7 +456,7 @@ test_buffer_time_tracking(void *arg) tt_int_op(0, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC)); tt_int_op(0, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+1000)); - write_to_buf("ABCDEFG", 7, buf); + buf_add(buf, "ABCDEFG", 7); tt_int_op(1000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+1000)); buf2 = buf_copy(buf); @@ -541,7 +467,7 @@ test_buffer_time_tracking(void *arg) /* Now add more bytes; enough to overflow the first chunk. */ monotime_coarse_set_mock_time_nsec(START_NSEC + 123 * (uint64_t)1000000); for (i = 0; i < 600; ++i) - write_to_buf("ABCDEFG", 7, buf); + buf_add(buf, "ABCDEFG", 7); tt_int_op(4207, OP_EQ, buf_datalen(buf)); /* The oldest bytes are still in the front. */ @@ -549,12 +475,12 @@ test_buffer_time_tracking(void *arg) /* Once those bytes are dropped, the chunk is still on the first * timestamp. */ - fetch_from_buf(tmp, 100, buf); + buf_get_bytes(buf, tmp, 100); tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2000)); /* But once we discard the whole first chunk, we get the data in the second * chunk. */ - fetch_from_buf(tmp, 4000, buf); + buf_get_bytes(buf, tmp, 4000); tt_int_op(107, OP_EQ, buf_datalen(buf)); tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2123)); @@ -562,12 +488,12 @@ test_buffer_time_tracking(void *arg) its time gets updated */ monotime_coarse_set_mock_time_nsec(START_NSEC + 5617 * (uint64_t)1000000); for (i = 0; i < 600; ++i) - write_to_buf("ABCDEFG", 7, buf); + buf_add(buf, "ABCDEFG", 7); tt_int_op(4307, OP_EQ, buf_datalen(buf)); tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2123)); - fetch_from_buf(tmp, 4000, buf); - fetch_from_buf(tmp, 306, buf); + buf_get_bytes(buf, tmp, 4000); + buf_get_bytes(buf, tmp, 306); tt_int_op(0, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+5617)); tt_int_op(383, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+6000)); @@ -593,23 +519,23 @@ test_buffers_compress_fin_at_chunk_end_impl(compress_method_t method, sz = buf_get_default_chunk_size(buf); msg = tor_malloc_zero(sz); - write_to_buf(msg, 1, buf); + buf_add(buf, msg, 1); tt_assert(buf->head); /* Fill up the chunk so the compression stuff won't fit in one chunk. */ tt_uint_op(buf->head->memlen, OP_LT, sz); headerjunk = buf->head->memlen - 7; - write_to_buf(msg, headerjunk-1, buf); + buf_add(buf, msg, headerjunk-1); tt_uint_op(buf->head->datalen, OP_EQ, headerjunk); tt_uint_op(buf_datalen(buf), OP_EQ, headerjunk); /* Write an empty string, with finalization on. */ compress_state = tor_compress_new(1, method, level); - tt_int_op(write_to_buf_compress(buf, compress_state, "", 0, 1), OP_EQ, 0); + tt_int_op(buf_add_compress(buf, compress_state, "", 0, 1), OP_EQ, 0); in_len = buf_datalen(buf); contents = tor_malloc(in_len); - tt_int_op(fetch_from_buf(contents, in_len, buf), OP_EQ, 0); + tt_int_op(buf_get_bytes(buf, contents, in_len), OP_EQ, 0); if (method == NO_METHOD) { tt_uint_op(in_len, OP_EQ, headerjunk); @@ -652,23 +578,23 @@ test_buffers_compress_impl(compress_method_t method, msg = tor_malloc(512); crypto_rand(msg, 512); - tt_int_op(write_to_buf_compress(buf, compress_state, + tt_int_op(buf_add_compress(buf, compress_state, msg, 128, 0), OP_EQ, 0); - tt_int_op(write_to_buf_compress(buf, compress_state, + tt_int_op(buf_add_compress(buf, compress_state, msg+128, 128, 0), OP_EQ, 0); - tt_int_op(write_to_buf_compress(buf, compress_state, + tt_int_op(buf_add_compress(buf, compress_state, msg+256, 256, 0), OP_EQ, 0); done = !finalize_with_nil; - tt_int_op(write_to_buf_compress(buf, compress_state, + tt_int_op(buf_add_compress(buf, compress_state, "all done", 9, done), OP_EQ, 0); if (finalize_with_nil) { - tt_int_op(write_to_buf_compress(buf, compress_state, "", 0, 1), OP_EQ, 0); + tt_int_op(buf_add_compress(buf, compress_state, "", 0, 1), OP_EQ, 0); } in_len = buf_datalen(buf); contents = tor_malloc(in_len); - tt_int_op(fetch_from_buf(contents, in_len, buf), OP_EQ, 0); + tt_int_op(buf_get_bytes(buf, contents, in_len), OP_EQ, 0); tt_int_op(0, OP_EQ, tor_uncompress(&expanded, &out_len, contents, in_len, @@ -762,11 +688,11 @@ test_buffers_tls_read_mocked(void *arg) buf = buf_new(); next_reply_val[0] = 1024; - tt_int_op(128, ==, read_to_buf_tls(NULL, 128, buf)); + tt_int_op(128, OP_EQ, buf_read_from_tls(buf, NULL, 128)); next_reply_val[0] = 5000; next_reply_val[1] = 5000; - tt_int_op(6000, ==, read_to_buf_tls(NULL, 6000, buf)); + tt_int_op(6000, OP_EQ, buf_read_from_tls(buf, NULL, 6000)); done: UNMOCK(tor_tls_read); @@ -780,17 +706,17 @@ test_buffers_chunk_size(void *arg) (void)arg; const int min = 256; const int max = 65536; - tt_uint_op(preferred_chunk_size(3), OP_EQ, min); - tt_uint_op(preferred_chunk_size(25), OP_EQ, min); - tt_uint_op(preferred_chunk_size(0), OP_EQ, min); - tt_uint_op(preferred_chunk_size(256), OP_EQ, 512); - tt_uint_op(preferred_chunk_size(65400), OP_EQ, max); + tt_uint_op(buf_preferred_chunk_size(3), OP_EQ, min); + tt_uint_op(buf_preferred_chunk_size(25), OP_EQ, min); + tt_uint_op(buf_preferred_chunk_size(0), OP_EQ, min); + tt_uint_op(buf_preferred_chunk_size(256), OP_EQ, 512); + tt_uint_op(buf_preferred_chunk_size(65400), OP_EQ, max); /* Here, we're implicitly saying that the chunk header overhead is * between 1 and 100 bytes. 24..48 would probably be more accurate. */ - tt_uint_op(preferred_chunk_size(65536), OP_GT, 65536); - tt_uint_op(preferred_chunk_size(65536), OP_LT, 65536+100); - tt_uint_op(preferred_chunk_size(165536), OP_GT, 165536); - tt_uint_op(preferred_chunk_size(165536), OP_LT, 165536+100); + tt_uint_op(buf_preferred_chunk_size(65536), OP_GT, 65536); + tt_uint_op(buf_preferred_chunk_size(65536), OP_LT, 65536+100); + tt_uint_op(buf_preferred_chunk_size(165536), OP_GT, 165536); + tt_uint_op(buf_preferred_chunk_size(165536), OP_LT, 165536+100); done: ; } @@ -831,18 +757,44 @@ test_buffers_find_contentlen(void *arg) r = buf_http_find_content_length(tmp, headerlen, &sz); tor_free(tmp); log_debug(LD_DIR, "%d: %s", i, escaped(results[i].headers)); - tt_int_op(r, ==, results[i].r); - tt_int_op(sz, ==, results[i].contentlen); + tt_int_op(r, OP_EQ, results[i].r); + tt_int_op(sz, OP_EQ, results[i].contentlen); } done: ; } +static void +test_buffer_peek_startswith(void *arg) +{ + (void)arg; + buf_t *buf; + buf = buf_new(); + tt_ptr_op(buf, OP_NE, NULL); + + tt_assert(buf_peek_startswith(buf, "")); + tt_assert(! buf_peek_startswith(buf, "X")); + + buf_add(buf, "Tor", 3); + + tt_assert(buf_peek_startswith(buf, "")); + tt_assert(buf_peek_startswith(buf, "T")); + tt_assert(buf_peek_startswith(buf, "To")); + tt_assert(buf_peek_startswith(buf, "Tor")); + tt_assert(! buf_peek_startswith(buf, "Top")); + tt_assert(! buf_peek_startswith(buf, "For")); + tt_assert(! buf_peek_startswith(buf, "Tork")); + tt_assert(! buf_peek_startswith(buf, "Torpor")); + + done: + buf_free(buf); +} + struct testcase_t buffer_tests[] = { { "basic", test_buffers_basic, TT_FORK, NULL, NULL }, { "copy", test_buffer_copy, TT_FORK, NULL, NULL }, { "pullup", test_buffer_pullup, TT_FORK, NULL, NULL }, - { "ext_or_cmd", test_buffer_ext_or_cmd, TT_FORK, NULL, NULL }, + { "startswith", test_buffer_peek_startswith, 0, NULL, NULL }, { "allocation_tracking", test_buffer_allocation_tracking, TT_FORK, NULL, NULL }, { "time_tracking", test_buffer_time_tracking, TT_FORK, NULL, NULL }, diff --git a/src/test/test_channel.c b/src/test/test_channel.c index f5999b8e67..023c2950c9 100644 --- a/src/test/test_channel.c +++ b/src/test/test_channel.c @@ -86,7 +86,7 @@ channel_note_destroy_not_pending_mock(channel_t *ch, static const char * chan_test_describe_transport(channel_t *ch) { - tt_assert(ch != NULL); + tt_ptr_op(ch, OP_NE, NULL); done: return "Fake channel for unit tests"; @@ -100,7 +100,7 @@ chan_test_describe_transport(channel_t *ch) static void chan_test_channel_dump_statistics_mock(channel_t *chan, int severity) { - tt_assert(chan != NULL); + tt_ptr_op(chan, OP_NE, NULL); (void)severity; @@ -125,7 +125,7 @@ chan_test_channel_flush_from_first_active_circuit_mock(channel_t *chan, int result = 0, c = 0; packed_cell_t *cell = NULL; - tt_assert(chan != NULL); + tt_ptr_op(chan, OP_NE, NULL); if (test_target_cmux != NULL && test_target_cmux == chan->cmux) { while (c <= max && test_cmux_cells > 0) { @@ -154,7 +154,7 @@ chan_test_circuitmux_num_cells_mock(circuitmux_t *cmux) { unsigned int result = 0; - tt_assert(cmux != NULL); + tt_ptr_op(cmux, OP_NE, NULL); if (cmux != NULL) { if (cmux == test_target_cmux) { result = test_cmux_cells; @@ -193,7 +193,7 @@ chan_test_cell_handler(channel_t *ch, static void chan_test_dumpstats(channel_t *ch, int severity) { - tt_assert(ch != NULL); + tt_ptr_op(ch, OP_NE, NULL); (void)severity; @@ -268,7 +268,7 @@ static const char * chan_test_get_remote_descr(channel_t *ch, int flags) { tt_assert(ch); - tt_int_op(flags & ~(GRD_FLAG_ORIGINAL | GRD_FLAG_ADDR_ONLY), ==, 0); + tt_int_op(flags & ~(GRD_FLAG_ORIGINAL | GRD_FLAG_ADDR_ONLY), OP_EQ, 0); done: return "Fake channel for unit tests; no real endpoint"; @@ -286,7 +286,7 @@ chan_test_get_overhead_estimate(channel_t *ch) static int chan_test_is_canonical(channel_t *ch, int req) { - tt_assert(ch != NULL); + tt_ptr_op(ch, OP_NE, NULL); tt_assert(req == 0 || req == 1); done: @@ -380,7 +380,7 @@ chan_test_write_var_cell(channel_t *ch, var_cell_t *var_cell) void make_fake_cell(cell_t *c) { - tt_assert(c != NULL); + tt_ptr_op(c, OP_NE, NULL); c->circ_id = 1; c->command = CELL_RELAY; @@ -397,7 +397,7 @@ make_fake_cell(cell_t *c) void make_fake_var_cell(var_cell_t *c) { - tt_assert(c != NULL); + tt_ptr_op(c, OP_NE, NULL); c->circ_id = 1; c->command = CELL_VERSIONS; @@ -552,24 +552,24 @@ test_channel_dumpstats(void *arg) channel_dumpstats(LOG_DEBUG); /* Assert that we hit the mock */ - tt_int_op(dump_statistics_mock_matches, ==, 1); + tt_int_op(dump_statistics_mock_matches, OP_EQ, 1); /* Close the channel */ channel_mark_for_close(ch); - tt_int_op(ch->state, ==, CHANNEL_STATE_CLOSING); + tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSING); chan_test_finish_close(ch); - tt_int_op(ch->state, ==, CHANNEL_STATE_CLOSED); + tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSED); /* Try again and hit the finished channel */ channel_dumpstats(LOG_DEBUG); - tt_int_op(dump_statistics_mock_matches, ==, 2); + tt_int_op(dump_statistics_mock_matches, OP_EQ, 2); channel_run_cleanup(); ch = NULL; /* Now we should hit nothing */ channel_dumpstats(LOG_DEBUG); - tt_int_op(dump_statistics_mock_matches, ==, 2); + tt_int_op(dump_statistics_mock_matches, OP_EQ, 2); /* Unmock */ UNMOCK(channel_dump_statistics); @@ -594,7 +594,7 @@ test_channel_dumpstats(void *arg) old_count = test_cells_written; channel_write_cell(ch, cell); cell = NULL; - tt_int_op(test_cells_written, ==, old_count + 1); + tt_int_op(test_cells_written, OP_EQ, old_count + 1); tt_assert(ch->n_bytes_xmitted > 0); tt_assert(ch->n_cells_xmitted > 0); @@ -602,14 +602,15 @@ test_channel_dumpstats(void *arg) channel_set_cell_handlers(ch, chan_test_cell_handler, chan_test_var_cell_handler); - tt_ptr_op(channel_get_cell_handler(ch), ==, chan_test_cell_handler); - tt_ptr_op(channel_get_var_cell_handler(ch), ==, chan_test_var_cell_handler); + tt_ptr_op(channel_get_cell_handler(ch), OP_EQ, chan_test_cell_handler); + tt_ptr_op(channel_get_var_cell_handler(ch), OP_EQ, + chan_test_var_cell_handler); cell = tor_malloc_zero(sizeof(cell_t)); make_fake_cell(cell); old_count = test_chan_fixed_cells_recved; channel_queue_cell(ch, cell); tor_free(cell); - tt_int_op(test_chan_fixed_cells_recved, ==, old_count + 1); + tt_int_op(test_chan_fixed_cells_recved, OP_EQ, old_count + 1); tt_assert(ch->n_bytes_recved > 0); tt_assert(ch->n_cells_recved > 0); @@ -619,13 +620,13 @@ test_channel_dumpstats(void *arg) ch->is_canonical = chan_test_is_canonical; old_count = test_dumpstats_calls; channel_dump_statistics(ch, LOG_DEBUG); - tt_int_op(test_dumpstats_calls, ==, old_count + 1); + tt_int_op(test_dumpstats_calls, OP_EQ, old_count + 1); /* Close the channel */ channel_mark_for_close(ch); - tt_int_op(ch->state, ==, CHANNEL_STATE_CLOSING); + tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSING); chan_test_finish_close(ch); - tt_int_op(ch->state, ==, CHANNEL_STATE_CLOSED); + tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSED); channel_run_cleanup(); ch = NULL; @@ -664,21 +665,21 @@ test_channel_flush(void *arg) make_fake_cell(cell); channel_write_cell(ch, cell); /* It should be queued, so assert that we didn't write it */ - tt_int_op(test_cells_written, ==, init_count); + tt_int_op(test_cells_written, OP_EQ, init_count); /* Queue a var cell */ v_cell = tor_malloc_zero(sizeof(var_cell_t) + CELL_PAYLOAD_SIZE); make_fake_var_cell(v_cell); channel_write_var_cell(ch, v_cell); /* It should be queued, so assert that we didn't write it */ - tt_int_op(test_cells_written, ==, init_count); + tt_int_op(test_cells_written, OP_EQ, init_count); /* Try a packed cell now */ p_cell = packed_cell_new(); tt_assert(p_cell); channel_write_packed_cell(ch, p_cell); /* It should be queued, so assert that we didn't write it */ - tt_int_op(test_cells_written, ==, init_count); + tt_int_op(test_cells_written, OP_EQ, init_count); /* Now allow writes through again */ test_chan_accept_cells = 1; @@ -687,7 +688,7 @@ test_channel_flush(void *arg) channel_flush_cells(ch); /* All three should have gone through */ - tt_int_op(test_cells_written, ==, init_count + 3); + tt_int_op(test_cells_written, OP_EQ, init_count + 3); done: tor_free(ch); @@ -728,9 +729,9 @@ test_channel_flushmux(void *arg) result = channel_flush_some_cells(ch, 1); - tt_int_op(result, ==, 1); - tt_int_op(test_cells_written, ==, old_count + 1); - tt_int_op(test_cmux_cells, ==, 0); + tt_int_op(result, OP_EQ, 1); + tt_int_op(test_cells_written, OP_EQ, old_count + 1); + tt_int_op(test_cmux_cells, OP_EQ, 0); /* Now try it without accepting to force them into the queue */ test_chan_accept_cells = 0; @@ -740,19 +741,19 @@ test_channel_flushmux(void *arg) result = channel_flush_some_cells(ch, 1); /* We should not have actually flushed any */ - tt_int_op(result, ==, 0); - tt_int_op(test_cells_written, ==, old_count + 1); + tt_int_op(result, OP_EQ, 0); + tt_int_op(test_cells_written, OP_EQ, old_count + 1); /* But we should have gotten to the fake cellgen loop */ - tt_int_op(test_cmux_cells, ==, 0); + tt_int_op(test_cmux_cells, OP_EQ, 0); /* ...and we should have a queued cell */ q_len_after = chan_cell_queue_len(&(ch->outgoing_queue)); - tt_int_op(q_len_after, ==, q_len_before + 1); + tt_int_op(q_len_after, OP_EQ, q_len_before + 1); /* Now accept cells again and drain the queue */ test_chan_accept_cells = 1; channel_flush_cells(ch); - tt_int_op(test_cells_written, ==, old_count + 2); - tt_int_op(chan_cell_queue_len(&(ch->outgoing_queue)), ==, 0); + tt_int_op(test_cells_written, OP_EQ, old_count + 2); + tt_int_op(chan_cell_queue_len(&(ch->outgoing_queue)), OP_EQ, 0); test_target_cmux = NULL; test_cmux_cells = 0; @@ -803,16 +804,17 @@ test_channel_incoming(void *arg) chan_test_cell_handler, chan_test_var_cell_handler); /* Test cell handler getters */ - tt_ptr_op(channel_get_cell_handler(ch), ==, chan_test_cell_handler); - tt_ptr_op(channel_get_var_cell_handler(ch), ==, chan_test_var_cell_handler); + tt_ptr_op(channel_get_cell_handler(ch), OP_EQ, chan_test_cell_handler); + tt_ptr_op(channel_get_var_cell_handler(ch), OP_EQ, + chan_test_var_cell_handler); /* Try to register it */ channel_register(ch); tt_assert(ch->registered); /* Open it */ - channel_change_state(ch, CHANNEL_STATE_OPEN); - tt_int_op(ch->state, ==, CHANNEL_STATE_OPEN); + channel_change_state_open(ch); + tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_OPEN); /* Receive a fixed cell */ cell = tor_malloc_zero(sizeof(cell_t)); @@ -820,7 +822,7 @@ test_channel_incoming(void *arg) old_count = test_chan_fixed_cells_recved; channel_queue_cell(ch, cell); tor_free(cell); - tt_int_op(test_chan_fixed_cells_recved, ==, old_count + 1); + tt_int_op(test_chan_fixed_cells_recved, OP_EQ, old_count + 1); /* Receive a variable-size cell */ var_cell = tor_malloc_zero(sizeof(var_cell_t) + CELL_PAYLOAD_SIZE); @@ -828,13 +830,13 @@ test_channel_incoming(void *arg) old_count = test_chan_var_cells_recved; channel_queue_var_cell(ch, var_cell); tor_free(cell); - tt_int_op(test_chan_var_cells_recved, ==, old_count + 1); + tt_int_op(test_chan_var_cells_recved, OP_EQ, old_count + 1); /* Close it */ channel_mark_for_close(ch); - tt_int_op(ch->state, ==, CHANNEL_STATE_CLOSING); + tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSING); chan_test_finish_close(ch); - tt_int_op(ch->state, ==, CHANNEL_STATE_CLOSED); + tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSED); channel_run_cleanup(); ch = NULL; @@ -896,13 +898,13 @@ test_channel_lifecycle(void *arg) make_fake_cell(cell); old_count = test_cells_written; channel_write_cell(ch1, cell); - tt_int_op(old_count, ==, test_cells_written); + tt_int_op(old_count, OP_EQ, test_cells_written); /* Move it to OPEN and flush */ - channel_change_state(ch1, CHANNEL_STATE_OPEN); + channel_change_state_open(ch1); /* Queue should drain */ - tt_int_op(old_count + 1, ==, test_cells_written); + tt_int_op(old_count + 1, OP_EQ, test_cells_written); /* Get another one */ ch2 = new_fake_channel(); @@ -915,41 +917,42 @@ test_channel_lifecycle(void *arg) tt_assert(ch2->registered); /* Check counters */ - tt_int_op(test_doesnt_want_writes_count, ==, init_doesnt_want_writes_count); - tt_int_op(test_releases_count, ==, init_releases_count); + tt_int_op(test_doesnt_want_writes_count, OP_EQ, + init_doesnt_want_writes_count); + tt_int_op(test_releases_count, OP_EQ, init_releases_count); /* Move ch1 to MAINT */ channel_change_state(ch1, CHANNEL_STATE_MAINT); - tt_int_op(test_doesnt_want_writes_count, ==, + tt_int_op(test_doesnt_want_writes_count, OP_EQ, init_doesnt_want_writes_count + 1); - tt_int_op(test_releases_count, ==, init_releases_count); + tt_int_op(test_releases_count, OP_EQ, init_releases_count); /* Move ch2 to OPEN */ - channel_change_state(ch2, CHANNEL_STATE_OPEN); - tt_int_op(test_doesnt_want_writes_count, ==, + channel_change_state_open(ch2); + tt_int_op(test_doesnt_want_writes_count, OP_EQ, init_doesnt_want_writes_count + 1); - tt_int_op(test_releases_count, ==, init_releases_count); + tt_int_op(test_releases_count, OP_EQ, init_releases_count); /* Move ch1 back to OPEN */ - channel_change_state(ch1, CHANNEL_STATE_OPEN); - tt_int_op(test_doesnt_want_writes_count, ==, + channel_change_state_open(ch1); + tt_int_op(test_doesnt_want_writes_count, OP_EQ, init_doesnt_want_writes_count + 1); - tt_int_op(test_releases_count, ==, init_releases_count); + tt_int_op(test_releases_count, OP_EQ, init_releases_count); /* Mark ch2 for close */ channel_mark_for_close(ch2); - tt_int_op(ch2->state, ==, CHANNEL_STATE_CLOSING); - tt_int_op(test_doesnt_want_writes_count, ==, + tt_int_op(ch2->state, OP_EQ, CHANNEL_STATE_CLOSING); + tt_int_op(test_doesnt_want_writes_count, OP_EQ, init_doesnt_want_writes_count + 1); - tt_int_op(test_releases_count, ==, init_releases_count + 1); + tt_int_op(test_releases_count, OP_EQ, init_releases_count + 1); /* Shut down channels */ channel_free_all(); ch1 = ch2 = NULL; - tt_int_op(test_doesnt_want_writes_count, ==, + tt_int_op(test_doesnt_want_writes_count, OP_EQ, init_doesnt_want_writes_count + 1); /* channel_free() calls scheduler_release_channel() */ - tt_int_op(test_releases_count, ==, init_releases_count + 4); + tt_int_op(test_releases_count, OP_EQ, init_releases_count + 4); done: free_fake_channel(ch1); @@ -1001,11 +1004,11 @@ test_channel_lifecycle_2(void *arg) /* Try to close it */ channel_mark_for_close(ch); - tt_int_op(ch->state, ==, CHANNEL_STATE_CLOSING); + tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSING); /* Finish closing it */ chan_test_finish_close(ch); - tt_int_op(ch->state, ==, CHANNEL_STATE_CLOSED); + tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSED); channel_run_cleanup(); ch = NULL; @@ -1018,13 +1021,13 @@ test_channel_lifecycle_2(void *arg) tt_assert(ch->registered); /* Finish opening it */ - channel_change_state(ch, CHANNEL_STATE_OPEN); + channel_change_state_open(ch); /* Error exit from lower layer */ chan_test_error(ch); - tt_int_op(ch->state, ==, CHANNEL_STATE_CLOSING); + tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSING); chan_test_finish_close(ch); - tt_int_op(ch->state, ==, CHANNEL_STATE_ERROR); + tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_ERROR); channel_run_cleanup(); ch = NULL; @@ -1037,20 +1040,20 @@ test_channel_lifecycle_2(void *arg) tt_assert(ch->registered); /* Finish opening it */ - channel_change_state(ch, CHANNEL_STATE_OPEN); - tt_int_op(ch->state, ==, CHANNEL_STATE_OPEN); + channel_change_state_open(ch); + tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_OPEN); /* Go to maintenance state */ channel_change_state(ch, CHANNEL_STATE_MAINT); - tt_int_op(ch->state, ==, CHANNEL_STATE_MAINT); + tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_MAINT); /* Lower layer close */ channel_mark_for_close(ch); - tt_int_op(ch->state, ==, CHANNEL_STATE_CLOSING); + tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSING); /* Finish */ chan_test_finish_close(ch); - tt_int_op(ch->state, ==, CHANNEL_STATE_CLOSED); + tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSED); channel_run_cleanup(); ch = NULL; @@ -1066,20 +1069,20 @@ test_channel_lifecycle_2(void *arg) tt_assert(ch->registered); /* Finish opening it */ - channel_change_state(ch, CHANNEL_STATE_OPEN); - tt_int_op(ch->state, ==, CHANNEL_STATE_OPEN); + channel_change_state_open(ch); + tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_OPEN); /* Go to maintenance state */ channel_change_state(ch, CHANNEL_STATE_MAINT); - tt_int_op(ch->state, ==, CHANNEL_STATE_MAINT); + tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_MAINT); /* Lower layer close */ channel_close_from_lower_layer(ch); - tt_int_op(ch->state, ==, CHANNEL_STATE_CLOSING); + tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSING); /* Finish */ chan_test_finish_close(ch); - tt_int_op(ch->state, ==, CHANNEL_STATE_CLOSED); + tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSED); channel_run_cleanup(); ch = NULL; @@ -1092,20 +1095,20 @@ test_channel_lifecycle_2(void *arg) tt_assert(ch->registered); /* Finish opening it */ - channel_change_state(ch, CHANNEL_STATE_OPEN); - tt_int_op(ch->state, ==, CHANNEL_STATE_OPEN); + channel_change_state_open(ch); + tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_OPEN); /* Go to maintenance state */ channel_change_state(ch, CHANNEL_STATE_MAINT); - tt_int_op(ch->state, ==, CHANNEL_STATE_MAINT); + tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_MAINT); /* Lower layer close */ chan_test_error(ch); - tt_int_op(ch->state, ==, CHANNEL_STATE_CLOSING); + tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSING); /* Finish */ chan_test_finish_close(ch); - tt_int_op(ch->state, ==, CHANNEL_STATE_ERROR); + tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_ERROR); channel_run_cleanup(); ch = NULL; @@ -1142,11 +1145,11 @@ test_channel_multi(void *arg) /* Initial queue size update */ channel_update_xmit_queue_size(ch1); - tt_u64_op(ch1->bytes_queued_for_xmit, ==, 0); + tt_u64_op(ch1->bytes_queued_for_xmit, OP_EQ, 0); channel_update_xmit_queue_size(ch2); - tt_u64_op(ch2->bytes_queued_for_xmit, ==, 0); + tt_u64_op(ch2->bytes_queued_for_xmit, OP_EQ, 0); global_queue_estimate = channel_get_global_queue_estimate(); - tt_u64_op(global_queue_estimate, ==, 0); + tt_u64_op(global_queue_estimate, OP_EQ, 0); /* Queue some cells, check queue estimates */ cell = tor_malloc_zero(sizeof(cell_t)); @@ -1159,10 +1162,10 @@ test_channel_multi(void *arg) channel_update_xmit_queue_size(ch1); channel_update_xmit_queue_size(ch2); - tt_u64_op(ch1->bytes_queued_for_xmit, ==, 0); - tt_u64_op(ch2->bytes_queued_for_xmit, ==, 0); + tt_u64_op(ch1->bytes_queued_for_xmit, OP_EQ, 0); + tt_u64_op(ch2->bytes_queued_for_xmit, OP_EQ, 0); global_queue_estimate = channel_get_global_queue_estimate(); - tt_u64_op(global_queue_estimate, ==, 0); + tt_u64_op(global_queue_estimate, OP_EQ, 0); /* Stop accepting cells at lower layer */ test_chan_accept_cells = 0; @@ -1173,18 +1176,18 @@ test_channel_multi(void *arg) channel_write_cell(ch1, cell); channel_update_xmit_queue_size(ch1); - tt_u64_op(ch1->bytes_queued_for_xmit, ==, 512); + tt_u64_op(ch1->bytes_queued_for_xmit, OP_EQ, 512); global_queue_estimate = channel_get_global_queue_estimate(); - tt_u64_op(global_queue_estimate, ==, 512); + tt_u64_op(global_queue_estimate, OP_EQ, 512); cell = tor_malloc_zero(sizeof(cell_t)); make_fake_cell(cell); channel_write_cell(ch2, cell); channel_update_xmit_queue_size(ch2); - tt_u64_op(ch2->bytes_queued_for_xmit, ==, 512); + tt_u64_op(ch2->bytes_queued_for_xmit, OP_EQ, 512); global_queue_estimate = channel_get_global_queue_estimate(); - tt_u64_op(global_queue_estimate, ==, 1024); + tt_u64_op(global_queue_estimate, OP_EQ, 1024); /* Allow cells through again */ test_chan_accept_cells = 1; @@ -1195,10 +1198,10 @@ test_channel_multi(void *arg) /* Update and check queue sizes */ channel_update_xmit_queue_size(ch1); channel_update_xmit_queue_size(ch2); - tt_u64_op(ch1->bytes_queued_for_xmit, ==, 512); - tt_u64_op(ch2->bytes_queued_for_xmit, ==, 0); + tt_u64_op(ch1->bytes_queued_for_xmit, OP_EQ, 512); + tt_u64_op(ch2->bytes_queued_for_xmit, OP_EQ, 0); global_queue_estimate = channel_get_global_queue_estimate(); - tt_u64_op(global_queue_estimate, ==, 512); + tt_u64_op(global_queue_estimate, OP_EQ, 512); /* Flush chan 1 */ channel_flush_cells(ch1); @@ -1206,10 +1209,10 @@ test_channel_multi(void *arg) /* Update and check queue sizes */ channel_update_xmit_queue_size(ch1); channel_update_xmit_queue_size(ch2); - tt_u64_op(ch1->bytes_queued_for_xmit, ==, 0); - tt_u64_op(ch2->bytes_queued_for_xmit, ==, 0); + tt_u64_op(ch1->bytes_queued_for_xmit, OP_EQ, 0); + tt_u64_op(ch2->bytes_queued_for_xmit, OP_EQ, 0); global_queue_estimate = channel_get_global_queue_estimate(); - tt_u64_op(global_queue_estimate, ==, 0); + tt_u64_op(global_queue_estimate, OP_EQ, 0); /* Now block again */ test_chan_accept_cells = 0; @@ -1227,10 +1230,10 @@ test_channel_multi(void *arg) /* Check the estimates */ channel_update_xmit_queue_size(ch1); channel_update_xmit_queue_size(ch2); - tt_u64_op(ch1->bytes_queued_for_xmit, ==, 512); - tt_u64_op(ch2->bytes_queued_for_xmit, ==, 512); + tt_u64_op(ch1->bytes_queued_for_xmit, OP_EQ, 512); + tt_u64_op(ch2->bytes_queued_for_xmit, OP_EQ, 512); global_queue_estimate = channel_get_global_queue_estimate(); - tt_u64_op(global_queue_estimate, ==, 1024); + tt_u64_op(global_queue_estimate, OP_EQ, 1024); /* Now close channel 2; it should be subtracted from the global queue */ MOCK(scheduler_release_channel, scheduler_release_channel_mock); @@ -1238,7 +1241,7 @@ test_channel_multi(void *arg) UNMOCK(scheduler_release_channel); global_queue_estimate = channel_get_global_queue_estimate(); - tt_u64_op(global_queue_estimate, ==, 512); + tt_u64_op(global_queue_estimate, OP_EQ, 512); /* * Since the fake channels aren't registered, channel_free_all() can't @@ -1249,7 +1252,7 @@ test_channel_multi(void *arg) UNMOCK(scheduler_release_channel); global_queue_estimate = channel_get_global_queue_estimate(); - tt_u64_op(global_queue_estimate, ==, 0); + tt_u64_op(global_queue_estimate, OP_EQ, 0); /* Now free everything */ MOCK(scheduler_release_channel, scheduler_release_channel_mock); @@ -1297,7 +1300,7 @@ test_channel_queue_impossible(void *arg) old_count = test_cells_written; /* Assert that the queue is initially empty */ - tt_int_op(chan_cell_queue_len(&(ch->outgoing_queue)), ==, 0); + tt_int_op(chan_cell_queue_len(&(ch->outgoing_queue)), OP_EQ, 0); /* Get a fresh cell and write it to the channel*/ cell = tor_malloc_zero(sizeof(cell_t)); @@ -1306,11 +1309,11 @@ test_channel_queue_impossible(void *arg) channel_write_cell(ch, cell); /* Now it should be queued */ - tt_int_op(chan_cell_queue_len(&(ch->outgoing_queue)), ==, 1); + tt_int_op(chan_cell_queue_len(&(ch->outgoing_queue)), OP_EQ, 1); q = TOR_SIMPLEQ_FIRST(&(ch->outgoing_queue)); tt_assert(q); if (q) { - tt_int_op(q->type, ==, CELL_QUEUE_FIXED); + tt_int_op(q->type, OP_EQ, CELL_QUEUE_FIXED); tt_assert((uintptr_t)q->u.fixed.cell == cellintptr); } /* Do perverse things to it */ @@ -1322,9 +1325,9 @@ test_channel_queue_impossible(void *arg) * gets thrown away properly. */ test_chan_accept_cells = 1; - channel_change_state(ch, CHANNEL_STATE_OPEN); + channel_change_state_open(ch); tt_assert(test_cells_written == old_count); - tt_int_op(chan_cell_queue_len(&(ch->outgoing_queue)), ==, 0); + tt_int_op(chan_cell_queue_len(&(ch->outgoing_queue)), OP_EQ, 0); /* Same thing but for a var_cell */ @@ -1336,11 +1339,11 @@ test_channel_queue_impossible(void *arg) channel_write_var_cell(ch, var_cell); /* Check that it's queued */ - tt_int_op(chan_cell_queue_len(&(ch->outgoing_queue)), ==, 1); + tt_int_op(chan_cell_queue_len(&(ch->outgoing_queue)), OP_EQ, 1); q = TOR_SIMPLEQ_FIRST(&(ch->outgoing_queue)); tt_assert(q); if (q) { - tt_int_op(q->type, ==, CELL_QUEUE_VAR); + tt_int_op(q->type, OP_EQ, CELL_QUEUE_VAR); tt_assert((uintptr_t)q->u.var.var_cell == cellintptr); } @@ -1350,9 +1353,9 @@ test_channel_queue_impossible(void *arg) /* Let it drain and check that the bad entry is discarded */ test_chan_accept_cells = 1; - channel_change_state(ch, CHANNEL_STATE_OPEN); + channel_change_state_open(ch); tt_assert(test_cells_written == old_count); - tt_int_op(chan_cell_queue_len(&(ch->outgoing_queue)), ==, 0); + tt_int_op(chan_cell_queue_len(&(ch->outgoing_queue)), OP_EQ, 0); /* Same thing with a packed_cell */ @@ -1364,11 +1367,11 @@ test_channel_queue_impossible(void *arg) channel_write_packed_cell(ch, packed_cell); /* Check that it's queued */ - tt_int_op(chan_cell_queue_len(&(ch->outgoing_queue)), ==, 1); + tt_int_op(chan_cell_queue_len(&(ch->outgoing_queue)), OP_EQ, 1); q = TOR_SIMPLEQ_FIRST(&(ch->outgoing_queue)); tt_assert(q); if (q) { - tt_int_op(q->type, ==, CELL_QUEUE_PACKED); + tt_int_op(q->type, OP_EQ, CELL_QUEUE_PACKED); tt_assert((uintptr_t)q->u.packed.packed_cell == cellintptr); } @@ -1378,9 +1381,9 @@ test_channel_queue_impossible(void *arg) /* Let it drain and check that the bad entry is discarded */ test_chan_accept_cells = 1; - channel_change_state(ch, CHANNEL_STATE_OPEN); + channel_change_state_open(ch); tt_assert(test_cells_written == old_count); - tt_int_op(chan_cell_queue_len(&(ch->outgoing_queue)), ==, 0); + tt_int_op(chan_cell_queue_len(&(ch->outgoing_queue)), OP_EQ, 0); /* Unknown cell type case */ test_chan_accept_cells = 0; @@ -1391,11 +1394,11 @@ test_channel_queue_impossible(void *arg) channel_write_cell(ch, cell); /* Check that it's queued */ - tt_int_op(chan_cell_queue_len(&(ch->outgoing_queue)), ==, 1); + tt_int_op(chan_cell_queue_len(&(ch->outgoing_queue)), OP_EQ, 1); q = TOR_SIMPLEQ_FIRST(&(ch->outgoing_queue)); tt_assert(q); if (q) { - tt_int_op(q->type, ==, CELL_QUEUE_FIXED); + tt_int_op(q->type, OP_EQ, CELL_QUEUE_FIXED); tt_assert((uintptr_t)q->u.fixed.cell == cellintptr); } /* Clobber it, including the queue entry type */ @@ -1406,11 +1409,11 @@ test_channel_queue_impossible(void *arg) /* Let it drain and check that the bad entry is discarded */ test_chan_accept_cells = 1; tor_capture_bugs_(1); - channel_change_state(ch, CHANNEL_STATE_OPEN); + channel_change_state_open(ch); tt_assert(test_cells_written == old_count); - tt_int_op(chan_cell_queue_len(&(ch->outgoing_queue)), ==, 0); + tt_int_op(chan_cell_queue_len(&(ch->outgoing_queue)), OP_EQ, 0); - tt_int_op(smartlist_len(tor_get_captured_bug_log_()), ==, 1); + tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_EQ, 1); tor_end_capture_bugs_(); done: @@ -1455,16 +1458,16 @@ test_channel_queue_incoming(void *arg) ch->cmux = circuitmux_alloc(); /* Test cell handler getters */ - tt_ptr_op(channel_get_cell_handler(ch), ==, NULL); - tt_ptr_op(channel_get_var_cell_handler(ch), ==, NULL); + tt_ptr_op(channel_get_cell_handler(ch), OP_EQ, NULL); + tt_ptr_op(channel_get_var_cell_handler(ch), OP_EQ, NULL); /* Try to register it */ channel_register(ch); tt_assert(ch->registered); /* Open it */ - channel_change_state(ch, CHANNEL_STATE_OPEN); - tt_int_op(ch->state, ==, CHANNEL_STATE_OPEN); + channel_change_state_open(ch); + tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_OPEN); /* Assert that the incoming queue is empty */ tt_assert(TOR_SIMPLEQ_EMPTY(&(ch->incoming_queue))); @@ -1475,7 +1478,7 @@ test_channel_queue_incoming(void *arg) channel_queue_cell(ch, cell); /* Assert that the incoming queue has one entry */ - tt_int_op(chan_cell_queue_len(&(ch->incoming_queue)), ==, 1); + tt_int_op(chan_cell_queue_len(&(ch->incoming_queue)), OP_EQ, 1); /* Queue an incoming var cell */ var_cell = tor_malloc_zero(sizeof(var_cell_t) + CELL_PAYLOAD_SIZE); @@ -1483,7 +1486,7 @@ test_channel_queue_incoming(void *arg) channel_queue_var_cell(ch, var_cell); /* Assert that the incoming queue has two entries */ - tt_int_op(chan_cell_queue_len(&(ch->incoming_queue)), ==, 2); + tt_int_op(chan_cell_queue_len(&(ch->incoming_queue)), OP_EQ, 2); /* * Install cell handlers; this will drain the queue, so save the old @@ -1494,12 +1497,13 @@ test_channel_queue_incoming(void *arg) channel_set_cell_handlers(ch, chan_test_cell_handler, chan_test_var_cell_handler); - tt_ptr_op(channel_get_cell_handler(ch), ==, chan_test_cell_handler); - tt_ptr_op(channel_get_var_cell_handler(ch), ==, chan_test_var_cell_handler); + tt_ptr_op(channel_get_cell_handler(ch), OP_EQ, chan_test_cell_handler); + tt_ptr_op(channel_get_var_cell_handler(ch), OP_EQ, + chan_test_var_cell_handler); /* Assert cells were received */ - tt_int_op(test_chan_fixed_cells_recved, ==, old_fixed_count + 1); - tt_int_op(test_chan_var_cells_recved, ==, old_var_count + 1); + tt_int_op(test_chan_fixed_cells_recved, OP_EQ, old_fixed_count + 1); + tt_int_op(test_chan_var_cells_recved, OP_EQ, old_var_count + 1); /* * Assert that the pointers are different from the cells we allocated; @@ -1508,17 +1512,17 @@ test_channel_queue_incoming(void *arg) * delivery. These pointers will have already been freed by the time * we get here, so don't dereference them. */ - tt_ptr_op(test_chan_last_seen_fixed_cell_ptr, !=, cell); - tt_ptr_op(test_chan_last_seen_var_cell_ptr, !=, var_cell); + tt_ptr_op(test_chan_last_seen_fixed_cell_ptr, OP_NE, cell); + tt_ptr_op(test_chan_last_seen_var_cell_ptr, OP_NE, var_cell); /* Assert queue is now empty */ tt_assert(TOR_SIMPLEQ_EMPTY(&(ch->incoming_queue))); /* Close it; this contains an assertion that the incoming queue is empty */ channel_mark_for_close(ch); - tt_int_op(ch->state, ==, CHANNEL_STATE_CLOSING); + tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSING); chan_test_finish_close(ch); - tt_int_op(ch->state, ==, CHANNEL_STATE_CLOSED); + tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSED); channel_run_cleanup(); ch = NULL; @@ -1548,14 +1552,14 @@ test_channel_queue_size(void *arg) /* Initial queue size update */ channel_update_xmit_queue_size(ch); - tt_u64_op(ch->bytes_queued_for_xmit, ==, 0); + tt_u64_op(ch->bytes_queued_for_xmit, OP_EQ, 0); global_queue_estimate = channel_get_global_queue_estimate(); - tt_u64_op(global_queue_estimate, ==, 0); + tt_u64_op(global_queue_estimate, OP_EQ, 0); /* Test the call-through to our fake lower layer */ n = channel_num_cells_writeable(ch); /* chan_test_num_cells_writeable() always returns 32 */ - tt_int_op(n, ==, 32); + tt_int_op(n, OP_EQ, 32); /* * Now we queue some cells and check that channel_num_cells_writeable() @@ -1574,72 +1578,73 @@ test_channel_queue_size(void *arg) old_count = test_cells_written; channel_write_cell(ch, cell); /* Assert that it got queued, not written through, correctly */ - tt_int_op(test_cells_written, ==, old_count); + tt_int_op(test_cells_written, OP_EQ, old_count); /* Now check chan_test_num_cells_writeable() again */ n = channel_num_cells_writeable(ch); - tt_int_op(n, ==, 0); /* Should return 0 since we're in CHANNEL_STATE_MAINT */ + /* Should return 0 since we're in CHANNEL_STATE_MAINT */ + tt_int_op(n, OP_EQ, 0); /* Update queue size estimates */ channel_update_xmit_queue_size(ch); /* One cell, times an overhead factor of 1.0 */ - tt_u64_op(ch->bytes_queued_for_xmit, ==, 512); + tt_u64_op(ch->bytes_queued_for_xmit, OP_EQ, 512); /* Try a different overhead factor */ test_overhead_estimate = 0.5; /* This one should be ignored since it's below 1.0 */ channel_update_xmit_queue_size(ch); - tt_u64_op(ch->bytes_queued_for_xmit, ==, 512); + tt_u64_op(ch->bytes_queued_for_xmit, OP_EQ, 512); /* Now try a larger one */ test_overhead_estimate = 2.0; channel_update_xmit_queue_size(ch); - tt_u64_op(ch->bytes_queued_for_xmit, ==, 1024); + tt_u64_op(ch->bytes_queued_for_xmit, OP_EQ, 1024); /* Go back to 1.0 */ test_overhead_estimate = 1.0; channel_update_xmit_queue_size(ch); - tt_u64_op(ch->bytes_queued_for_xmit, ==, 512); + tt_u64_op(ch->bytes_queued_for_xmit, OP_EQ, 512); /* Check the global estimate too */ global_queue_estimate = channel_get_global_queue_estimate(); - tt_u64_op(global_queue_estimate, ==, 512); + tt_u64_op(global_queue_estimate, OP_EQ, 512); /* Go to open */ old_count = test_cells_written; - channel_change_state(ch, CHANNEL_STATE_OPEN); + channel_change_state_open(ch); /* * It should try to write, but we aren't accepting cells right now, so * it'll requeue */ - tt_int_op(test_cells_written, ==, old_count); + tt_int_op(test_cells_written, OP_EQ, old_count); /* Check the queue size again */ channel_update_xmit_queue_size(ch); - tt_u64_op(ch->bytes_queued_for_xmit, ==, 512); + tt_u64_op(ch->bytes_queued_for_xmit, OP_EQ, 512); global_queue_estimate = channel_get_global_queue_estimate(); - tt_u64_op(global_queue_estimate, ==, 512); + tt_u64_op(global_queue_estimate, OP_EQ, 512); /* * Now the cell is in the queue, and we're open, so we should get 31 * writeable cells. */ n = channel_num_cells_writeable(ch); - tt_int_op(n, ==, 31); + tt_int_op(n, OP_EQ, 31); /* Accept cells again */ test_chan_accept_cells = 1; /* ...and re-process the queue */ old_count = test_cells_written; channel_flush_cells(ch); - tt_int_op(test_cells_written, ==, old_count + 1); + tt_int_op(test_cells_written, OP_EQ, old_count + 1); /* Should have 32 writeable now */ n = channel_num_cells_writeable(ch); - tt_int_op(n, ==, 32); + tt_int_op(n, OP_EQ, 32); /* Should have queue size estimate of zero */ channel_update_xmit_queue_size(ch); - tt_u64_op(ch->bytes_queued_for_xmit, ==, 0); + tt_u64_op(ch->bytes_queued_for_xmit, OP_EQ, 0); global_queue_estimate = channel_get_global_queue_estimate(); - tt_u64_op(global_queue_estimate, ==, 0); + tt_u64_op(global_queue_estimate, OP_EQ, 0); /* Okay, now we're done with this one */ MOCK(scheduler_release_channel, scheduler_release_channel_mock); @@ -1706,7 +1711,7 @@ test_channel_write(void *arg) * gets drained from the queue. */ test_chan_accept_cells = 1; - channel_change_state(ch, CHANNEL_STATE_OPEN); + channel_change_state_open(ch); tt_assert(test_cells_written == old_count + 1); /* @@ -1780,7 +1785,7 @@ test_channel_id_map(void *arg) ed25519_public_key_t ed_zero; memset(&ed_zero, 0, sizeof(ed_zero)); - tt_assert(sizeof(rsa_id[0]) == DIGEST_LEN); // Do I remember C? + tt_int_op(DIGEST_LEN, OP_EQ, sizeof(rsa_id[0])); // Do I remember C? for (i = 0; i < N_CHAN; ++i) { crypto_rand(rsa_id[i], DIGEST_LEN); @@ -1822,7 +1827,7 @@ test_channel_id_map(void *arg) ch = channel_next_with_rsa_identity(ch); tt_assert(ch == chan[2] || ch == chan[4] || ch == chan[5]); ch = channel_next_with_rsa_identity(ch); - tt_assert(ch == NULL); + tt_ptr_op(ch, OP_EQ, NULL); /* As above, but with zero Ed25519 ID (meaning "any ID") */ tt_ptr_op(chan[0], OP_EQ, @@ -1838,7 +1843,7 @@ test_channel_id_map(void *arg) ch = channel_next_with_rsa_identity(ch); tt_assert(ch == chan[2] || ch == chan[4] || ch == chan[5]); ch = channel_next_with_rsa_identity(ch); - tt_assert(ch == NULL); + tt_ptr_op(ch, OP_EQ, NULL); /* Lookup nonexistent RSA identity */ tt_ptr_op(NULL, OP_EQ, diff --git a/src/test/test_channelpadding.c b/src/test/test_channelpadding.c index d54c9cc52c..391ead3c72 100644 --- a/src/test/test_channelpadding.c +++ b/src/test/test_channelpadding.c @@ -193,7 +193,8 @@ static void setup_mock_network(void) { routerstatus_t *relay; - connection_array = smartlist_new(); + if (!connection_array) + connection_array = smartlist_new(); relay1_relay2 = (channel_t*)new_fake_channeltls(2); relay1_relay2->write_cell = mock_channel_write_cell_relay1; @@ -280,7 +281,8 @@ test_channelpadding_timers(void *arg) tor_libevent_postfork(); - connection_array = smartlist_new(); + if (!connection_array) + connection_array = smartlist_new(); monotime_init(); monotime_enable_test_mocking(); @@ -570,7 +572,8 @@ test_channelpadding_consensus(void *arg) monotime_coarse_set_mock_time_nsec(1); timers_initialize(); - connection_array = smartlist_new(); + if (!connection_array) + connection_array = smartlist_new(); chan = (channel_t*)new_fake_channeltls(0); channel_timestamp_active(chan); @@ -677,6 +680,7 @@ test_channelpadding_consensus(void *arg) memcpy(relay->identity_digest, ((channel_tls_t *)chan)->conn->identity_digest, DIGEST_LEN); smartlist_add(current_md_consensus->routerstatus_list, relay); + relay = NULL; /* Prevent double-free */ tried_to_write_cell = 0; decision = channelpadding_decide_to_pad_channel(chan); @@ -745,6 +749,8 @@ test_channelpadding_consensus(void *arg) tt_i64_op(val, OP_LE, 24*60*60*2); done: + tor_free(relay); + free_mock_consensus(); free_fake_channeltls((channel_tls_t*)chan); smartlist_free(connection_array); @@ -928,7 +934,8 @@ test_channelpadding_decide_to_pad_channel(void *arg) */ channel_t *chan; int64_t new_time; - connection_array = smartlist_new(); + if (!connection_array) + connection_array = smartlist_new(); (void)arg; tor_libevent_postfork(); diff --git a/src/test/test_channeltls.c b/src/test/test_channeltls.c index 96c5eba9a5..94f1893cae 100644 --- a/src/test/test_channeltls.c +++ b/src/test/test_channeltls.c @@ -72,7 +72,7 @@ test_channeltls_create(void *arg) /* Try connecting */ ch = channel_tls_connect(&test_addr, 567, test_digest, NULL); - tt_assert(ch != NULL); + tt_ptr_op(ch, OP_NE, NULL); done: if (ch) { @@ -121,7 +121,7 @@ test_channeltls_num_bytes_queued(void *arg) /* Try connecting */ ch = channel_tls_connect(&test_addr, 567, test_digest, NULL); - tt_assert(ch != NULL); + tt_ptr_op(ch, OP_NE, NULL); /* * Next, we have to test ch->num_bytes_queued, which is @@ -132,7 +132,7 @@ test_channeltls_num_bytes_queued(void *arg) tt_assert(ch->num_bytes_queued != NULL); tlschan = BASE_CHAN_TO_TLS(ch); - tt_assert(tlschan != NULL); + tt_ptr_op(tlschan, OP_NE, NULL); if (TO_CONN(tlschan->conn)->outbuf == NULL) { /* We need an outbuf to make sure buf_datalen() gets called */ fake_outbuf = 1; @@ -142,7 +142,7 @@ test_channeltls_num_bytes_queued(void *arg) tlschan_buf_datalen_mock_size = 1024; MOCK(buf_datalen, tlschan_buf_datalen_mock); len = ch->num_bytes_queued(ch); - tt_int_op(len, ==, tlschan_buf_datalen_mock_size); + tt_int_op(len, OP_EQ, tlschan_buf_datalen_mock_size); /* * We also cover num_cells_writeable here; since wide_circ_ids = 0 on * the fake tlschans, cell_network_size returns 512, and so with @@ -151,7 +151,7 @@ test_channeltls_num_bytes_queued(void *arg) * - 2 cells. */ n = ch->num_cells_writeable(ch); - tt_int_op(n, ==, CEIL_DIV(OR_CONN_HIGHWATER, 512) - 2); + tt_int_op(n, OP_EQ, CEIL_DIV(OR_CONN_HIGHWATER, 512) - 2); UNMOCK(buf_datalen); tlschan_buf_datalen_mock_target = NULL; tlschan_buf_datalen_mock_size = 0; @@ -206,11 +206,11 @@ test_channeltls_overhead_estimate(void *arg) /* Try connecting */ ch = channel_tls_connect(&test_addr, 567, test_digest, NULL); - tt_assert(ch != NULL); + tt_ptr_op(ch, OP_NE, NULL); /* First case: silly low ratios should get clamped to 1.0 */ tlschan = BASE_CHAN_TO_TLS(ch); - tt_assert(tlschan != NULL); + tt_ptr_op(tlschan, OP_NE, NULL); tlschan->conn->bytes_xmitted = 128; tlschan->conn->bytes_xmitted_by_tls = 64; r = ch->get_overhead_estimate(ch); @@ -273,10 +273,10 @@ tlschan_connection_or_connect_mock(const tor_addr_t *addr, or_connection_t *result = NULL; (void) ed_id; // XXXX Not yet used. - tt_assert(addr != NULL); - tt_assert(port != 0); - tt_assert(digest != NULL); - tt_assert(tlschan != NULL); + tt_ptr_op(addr, OP_NE, NULL); + tt_uint_op(port, OP_NE, 0); + tt_ptr_op(digest, OP_NE, NULL); + tt_ptr_op(tlschan, OP_NE, NULL); /* Make a fake orconn */ result = tor_malloc_zero(sizeof(*result)); @@ -301,11 +301,11 @@ tlschan_fake_close_method(channel_t *chan) { channel_tls_t *tlschan = NULL; - tt_assert(chan != NULL); - tt_int_op(chan->magic, ==, TLS_CHAN_MAGIC); + tt_ptr_op(chan, OP_NE, NULL); + tt_int_op(chan->magic, OP_EQ, TLS_CHAN_MAGIC); tlschan = BASE_CHAN_TO_TLS(chan); - tt_assert(tlschan != NULL); + tt_ptr_op(tlschan, OP_NE, NULL); /* Just free the fake orconn */ tor_free(tlschan->conn->base_.address); @@ -320,7 +320,7 @@ tlschan_fake_close_method(channel_t *chan) static int tlschan_is_local_addr_mock(const tor_addr_t *addr) { - tt_assert(addr != NULL); + tt_ptr_op(addr, OP_NE, NULL); done: return tlschan_local; diff --git a/src/test/test_checkdir.c b/src/test/test_checkdir.c index 38f3360b61..bf6a8376b3 100644 --- a/src/test/test_checkdir.c +++ b/src/test/test_checkdir.c @@ -20,7 +20,7 @@ #define umask(mask) ((void)0) #else #define tt_int_op_nowin(a,op,b) tt_int_op((a),op,(b)) -#endif +#endif /* defined(_WIN32) */ /** Run unit tests for private dir permission enforcement logic. */ static void diff --git a/src/test/test_circuitlist.c b/src/test/test_circuitlist.c index 344ab27921..f622704ec5 100644 --- a/src/test/test_circuitlist.c +++ b/src/test/test_circuitlist.c @@ -180,6 +180,7 @@ static void test_rend_token_maps(void *arg) { or_circuit_t *c1, *c2, *c3, *c4; + origin_circuit_t *c5; const uint8_t tok1[REND_TOKEN_LEN] = "The cat can't tell y"; const uint8_t tok2[REND_TOKEN_LEN] = "ou its name, and it "; const uint8_t tok3[REND_TOKEN_LEN] = "doesn't really care."; @@ -194,6 +195,7 @@ test_rend_token_maps(void *arg) c2 = or_circuit_new(0, NULL); c3 = or_circuit_new(0, NULL); c4 = or_circuit_new(0, NULL); + c5 = origin_circuit_new(); /* Make sure we really filled up the tok* variables */ tt_int_op(tok1[REND_TOKEN_LEN-1], OP_EQ, 'y'); @@ -264,6 +266,13 @@ test_rend_token_maps(void *arg) tt_ptr_op(TO_CIRCUIT(c4)->hs_token, OP_EQ, NULL); tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok3)); + /* Now let's do a check for the client-side rend circuitmap */ + c5->base_.purpose = CIRCUIT_PURPOSE_C_ESTABLISH_REND; + hs_circuitmap_register_rend_circ_client_side(c5, tok1); + + tt_ptr_op(c5, OP_EQ, hs_circuitmap_get_rend_circ_client_side(tok1)); + tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_client_side(tok2)); + done: if (c1) circuit_free(TO_CIRCUIT(c1)); @@ -273,6 +282,8 @@ test_rend_token_maps(void *arg) circuit_free(TO_CIRCUIT(c3)); if (c4) circuit_free(TO_CIRCUIT(c4)); + if (c5) + circuit_free(TO_CIRCUIT(c5)); } static void diff --git a/src/test/test_circuitmux.c b/src/test/test_circuitmux.c index 99abdbc685..854f725054 100644 --- a/src/test/test_circuitmux.c +++ b/src/test/test_circuitmux.c @@ -49,8 +49,8 @@ test_cmux_destroy_cell_queue(void *arg) ch->wide_circ_ids = 1; circ = circuitmux_get_first_active_circuit(cmux, &cq); - tt_assert(!circ); - tt_assert(!cq); + tt_ptr_op(circ, OP_EQ, NULL); + tt_ptr_op(cq, OP_EQ, NULL); circuitmux_append_destroy_cell(ch, cmux, 100, 10); circuitmux_append_destroy_cell(ch, cmux, 190, 6); @@ -59,7 +59,7 @@ test_cmux_destroy_cell_queue(void *arg) tt_int_op(circuitmux_num_cells(cmux), OP_EQ, 3); circ = circuitmux_get_first_active_circuit(cmux, &cq); - tt_assert(!circ); + tt_ptr_op(circ, OP_EQ, NULL); tt_assert(cq); tt_int_op(cq->n, OP_EQ, 3); diff --git a/src/test/test_circuituse.c b/src/test/test_circuituse.c index 5cc9fe571e..df1b43807f 100644 --- a/src/test/test_circuituse.c +++ b/src/test/test_circuituse.c @@ -22,7 +22,7 @@ test_circuit_is_available_for_use_ret_false_when_marked_for_close(void *arg) circuit_t *circ = tor_malloc(sizeof(circuit_t)); circ->marked_for_close = 1; - tt_int_op(0, ==, circuit_is_available_for_use(circ)); + tt_int_op(0, OP_EQ, circuit_is_available_for_use(circ)); done: tor_free(circ); @@ -36,7 +36,7 @@ test_circuit_is_available_for_use_ret_false_when_timestamp_dirty(void *arg) circuit_t *circ = tor_malloc(sizeof(circuit_t)); circ->timestamp_dirty = 1; - tt_int_op(0, ==, circuit_is_available_for_use(circ)); + tt_int_op(0, OP_EQ, circuit_is_available_for_use(circ)); done: tor_free(circ); @@ -50,7 +50,7 @@ test_circuit_is_available_for_use_ret_false_for_non_general_purpose(void *arg) circuit_t *circ = tor_malloc(sizeof(circuit_t)); circ->purpose = CIRCUIT_PURPOSE_REND_POINT_WAITING; - tt_int_op(0, ==, circuit_is_available_for_use(circ)); + tt_int_op(0, OP_EQ, circuit_is_available_for_use(circ)); done: tor_free(circ); @@ -64,7 +64,7 @@ test_circuit_is_available_for_use_ret_false_for_non_general_origin(void *arg) circuit_t *circ = tor_malloc(sizeof(circuit_t)); circ->purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT; - tt_int_op(0, ==, circuit_is_available_for_use(circ)); + tt_int_op(0, OP_EQ, circuit_is_available_for_use(circ)); done: tor_free(circ); @@ -78,7 +78,7 @@ test_circuit_is_available_for_use_ret_false_for_non_origin_purpose(void *arg) circuit_t *circ = tor_malloc(sizeof(circuit_t)); circ->purpose = CIRCUIT_PURPOSE_OR; - tt_int_op(0, ==, circuit_is_available_for_use(circ)); + tt_int_op(0, OP_EQ, circuit_is_available_for_use(circ)); done: tor_free(circ); @@ -92,7 +92,7 @@ test_circuit_is_available_for_use_ret_false_unusable_for_new_conns(void *arg) circuit_t *circ = dummy_origin_circuit_new(30); mark_circuit_unusable_for_new_conns(TO_ORIGIN_CIRCUIT(circ)); - tt_int_op(0, ==, circuit_is_available_for_use(circ)); + tt_int_op(0, OP_EQ, circuit_is_available_for_use(circ)); done: circuit_free(circ); @@ -108,7 +108,7 @@ test_circuit_is_available_for_use_returns_false_for_onehop_tunnel(void *arg) oc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t)); oc->build_state->onehop_tunnel = 1; - tt_int_op(0, ==, circuit_is_available_for_use(circ)); + tt_int_op(0, OP_EQ, circuit_is_available_for_use(circ)); done: circuit_free(circ); @@ -124,7 +124,7 @@ test_circuit_is_available_for_use_returns_true_for_clean_circuit(void *arg) oc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t)); oc->build_state->onehop_tunnel = 0; - tt_int_op(1, ==, circuit_is_available_for_use(circ)); + tt_int_op(1, OP_EQ, circuit_is_available_for_use(circ)); done: circuit_free(circ); @@ -165,7 +165,8 @@ test_needs_exit_circuits_ret_false_for_predicted_ports_and_path(void *arg) int needs_capacity = 0; time_t now = time(NULL); - tt_int_op(0, ==, needs_exit_circuits(now, &needs_uptime, &needs_capacity)); + tt_int_op(0, OP_EQ, + needs_exit_circuits(now, &needs_uptime, &needs_capacity)); done: UNMOCK(circuit_all_predicted_ports_handled); @@ -183,7 +184,8 @@ test_needs_exit_circuits_ret_false_for_non_exit_consensus_path(void *arg) MOCK(router_have_consensus_path, mock_router_have_unknown_consensus_path); time_t now = time(NULL); - tt_int_op(0, ==, needs_exit_circuits(now, &needs_uptime, &needs_capacity)); + tt_int_op(0, OP_EQ, + needs_exit_circuits(now, &needs_uptime, &needs_capacity)); done: UNMOCK(circuit_all_predicted_ports_handled); @@ -202,7 +204,8 @@ test_needs_exit_circuits_ret_true_for_predicted_ports_and_path(void *arg) MOCK(router_have_consensus_path, mock_router_have_exit_consensus_path); time_t now = time(NULL); - tt_int_op(1, ==, needs_exit_circuits(now, &needs_uptime, &needs_capacity)); + tt_int_op(1, OP_EQ, + needs_exit_circuits(now, &needs_uptime, &needs_capacity)); done: UNMOCK(circuit_all_predicted_ports_handled); @@ -214,7 +217,7 @@ test_needs_circuits_for_build_ret_false_consensus_path_unknown(void *arg) { (void)arg; MOCK(router_have_consensus_path, mock_router_have_unknown_consensus_path); - tt_int_op(0, ==, needs_circuits_for_build(0)); + tt_int_op(0, OP_EQ, needs_circuits_for_build(0)); done: ; } @@ -223,7 +226,7 @@ test_needs_circuits_for_build_ret_false_if_num_less_than_max(void *arg) { (void)arg; MOCK(router_have_consensus_path, mock_router_have_exit_consensus_path); - tt_int_op(0, ==, needs_circuits_for_build(13)); + tt_int_op(0, OP_EQ, needs_circuits_for_build(13)); done: UNMOCK(router_have_consensus_path); } @@ -233,7 +236,7 @@ test_needs_circuits_for_build_returns_true_when_more_are_needed(void *arg) { (void)arg; MOCK(router_have_consensus_path, mock_router_have_exit_consensus_path); - tt_int_op(1, ==, needs_circuits_for_build(0)); + tt_int_op(1, OP_EQ, needs_circuits_for_build(0)); done: UNMOCK(router_have_consensus_path); } diff --git a/src/test/test_config.c b/src/test/test_config.c index beaab00f73..e7380c1d14 100644 --- a/src/test/test_config.c +++ b/src/test/test_config.c @@ -279,7 +279,7 @@ test_config_check_or_create_data_subdir(void *arg) tt_assert(!is_private_dir(subpath)); tt_assert(!check_or_create_data_subdir(subdir)); tt_assert(is_private_dir(subpath)); -#endif +#endif /* !defined (_WIN32) */ done: rmdir(subpath); @@ -368,12 +368,12 @@ good_bridge_line_test(const char *string, const char *test_addrport, /* If we were asked to validate a digest, but we did not get a digest after parsing, we failed. */ if (test_digest && tor_digest_is_zero(bridge_line->digest)) - tt_assert(0); + tt_abort(); /* If we were not asked to validate a digest, and we got a digest after parsing, we failed again. */ if (!test_digest && !tor_digest_is_zero(bridge_line->digest)) - tt_assert(0); + tt_abort(); /* If we were asked to validate a digest, and we got a digest after parsing, make sure it's correct. */ @@ -387,17 +387,17 @@ good_bridge_line_test(const char *string, const char *test_addrport, /* If we were asked to validate a transport name, make sure tha it matches with the transport name that was parsed. */ if (test_transport && !bridge_line->transport_name) - tt_assert(0); + tt_abort(); if (!test_transport && bridge_line->transport_name) - tt_assert(0); + tt_abort(); if (test_transport) tt_str_op(test_transport,OP_EQ, bridge_line->transport_name); /* Validate the SOCKS argument smartlist. */ if (test_socks_args && !bridge_line->socks_args) - tt_assert(0); + tt_abort(); if (!test_socks_args && bridge_line->socks_args) - tt_assert(0); + tt_abort(); if (test_socks_args) tt_assert(smartlist_strings_eq(test_socks_args, bridge_line->socks_args)); @@ -415,7 +415,7 @@ bad_bridge_line_test(const char *string) bridge_line_t *bridge_line = parse_bridge_line(string); if (bridge_line) TT_FAIL(("%s was supposed to fail, but it didn't.", string)); - tt_assert(!bridge_line); + tt_ptr_op(bridge_line, OP_EQ, NULL); done: bridge_line_free(bridge_line); @@ -523,18 +523,18 @@ test_config_parse_transport_options_line(void *arg) { /* too small line */ options_sl = get_options_from_transport_options_line("valley", NULL); - tt_assert(!options_sl); + tt_ptr_op(options_sl, OP_EQ, NULL); } { /* no k=v values */ options_sl = get_options_from_transport_options_line("hit it!", NULL); - tt_assert(!options_sl); + tt_ptr_op(options_sl, OP_EQ, NULL); } { /* correct line, but wrong transport specified */ options_sl = get_options_from_transport_options_line("trebuchet k=v", "rook"); - tt_assert(!options_sl); + tt_ptr_op(options_sl, OP_EQ, NULL); } { /* correct -- no transport specified */ @@ -658,84 +658,85 @@ test_config_parse_transport_plugin_line(void *arg) /* Bad transport lines - too short */ r = parse_transport_line(options, "bad", 1, 0); - tt_assert(r < 0); + tt_int_op(r, OP_LT, 0); r = parse_transport_line(options, "bad", 1, 1); - tt_assert(r < 0); + tt_int_op(r, OP_LT, 0); r = parse_transport_line(options, "bad bad", 1, 0); - tt_assert(r < 0); + tt_int_op(r, OP_LT, 0); r = parse_transport_line(options, "bad bad", 1, 1); - tt_assert(r < 0); + tt_int_op(r, OP_LT, 0); /* Test transport list parsing */ r = parse_transport_line(options, "transport_1 exec /usr/bin/fake-transport", 1, 0); - tt_assert(r == 0); + tt_int_op(r, OP_EQ, 0); r = parse_transport_line(options, "transport_1 exec /usr/bin/fake-transport", 1, 1); - tt_assert(r == 0); + tt_int_op(r, OP_EQ, 0); r = parse_transport_line(options, "transport_1,transport_2 exec /usr/bin/fake-transport", 1, 0); - tt_assert(r == 0); + tt_int_op(r, OP_EQ, 0); r = parse_transport_line(options, "transport_1,transport_2 exec /usr/bin/fake-transport", 1, 1); - tt_assert(r == 0); + tt_int_op(r, OP_EQ, 0); /* Bad transport identifiers */ r = parse_transport_line(options, "transport_* exec /usr/bin/fake-transport", 1, 0); - tt_assert(r < 0); + tt_int_op(r, OP_LT, 0); r = parse_transport_line(options, "transport_* exec /usr/bin/fake-transport", 1, 1); - tt_assert(r < 0); + tt_int_op(r, OP_LT, 0); /* Check SOCKS cases for client transport */ r = parse_transport_line(options, "transport_1 socks4 1.2.3.4:567", 1, 0); - tt_assert(r == 0); + tt_int_op(r, OP_EQ, 0); r = parse_transport_line(options, "transport_1 socks5 1.2.3.4:567", 1, 0); - tt_assert(r == 0); + tt_int_op(r, OP_EQ, 0); /* Proxy case for server transport */ r = parse_transport_line(options, "transport_1 proxy 1.2.3.4:567", 1, 1); - tt_assert(r == 0); + tt_int_op(r, OP_EQ, 0); /* Multiple-transport error exit */ r = parse_transport_line(options, "transport_1,transport_2 socks5 1.2.3.4:567", 1, 0); - tt_assert(r < 0); + tt_int_op(r, OP_LT, 0); r = parse_transport_line(options, "transport_1,transport_2 proxy 1.2.3.4:567", 1, 1); + tt_int_op(r, OP_LT, 0); /* No port error exit */ r = parse_transport_line(options, "transport_1 socks5 1.2.3.4", 1, 0); - tt_assert(r < 0); + tt_int_op(r, OP_LT, 0); r = parse_transport_line(options, "transport_1 proxy 1.2.3.4", 1, 1); - tt_assert(r < 0); + tt_int_op(r, OP_LT, 0); /* Unparsable address error exit */ r = parse_transport_line(options, "transport_1 socks5 1.2.3:6x7", 1, 0); - tt_assert(r < 0); + tt_int_op(r, OP_LT, 0); r = parse_transport_line(options, "transport_1 proxy 1.2.3:6x7", 1, 1); - tt_assert(r < 0); + tt_int_op(r, OP_LT, 0); /* "Strange {Client|Server}TransportPlugin field" error exit */ r = parse_transport_line(options, "transport_1 foo bar", 1, 0); - tt_assert(r < 0); + tt_int_op(r, OP_LT, 0); r = parse_transport_line(options, "transport_1 foo bar", 1, 1); - tt_assert(r < 0); + tt_int_op(r, OP_LT, 0); /* No sandbox mode error exit */ tmp = options->Sandbox; options->Sandbox = 1; r = parse_transport_line(options, "transport_1 exec /usr/bin/fake-transport", 1, 0); - tt_assert(r < 0); + tt_int_op(r, OP_LT, 0); r = parse_transport_line(options, "transport_1 exec /usr/bin/fake-transport", 1, 1); - tt_assert(r < 0); + tt_int_op(r, OP_LT, 0); options->Sandbox = tmp; /* @@ -747,7 +748,7 @@ test_config_parse_transport_plugin_line(void *arg) pt_kickstart_proxy_mock_call_count; r = parse_transport_line(options, "transport_1 exec /usr/bin/fake-transport", 0, 1); - tt_assert(r == 0); + tt_int_op(r, OP_EQ, 0); tt_assert(pt_kickstart_proxy_mock_call_count == old_pt_kickstart_proxy_mock_call_count + 1); UNMOCK(pt_kickstart_proxy); @@ -755,7 +756,7 @@ test_config_parse_transport_plugin_line(void *arg) /* This one hits a log line in the !validate_only case only */ r = parse_transport_line(options, "transport_1 proxy 1.2.3.4:567", 0, 1); - tt_assert(r == 0); + tt_int_op(r, OP_EQ, 0); /* Check mocked client transport cases */ MOCK(pt_kickstart_proxy, pt_kickstart_proxy_mock); @@ -773,7 +774,7 @@ test_config_parse_transport_plugin_line(void *arg) r = parse_transport_line(options, "transport_1 exec /usr/bin/fake-transport", 0, 0); /* Should have succeeded */ - tt_assert(r == 0); + tt_int_op(r, OP_EQ, 0); /* transport_is_needed() should have been called */ tt_assert(transport_is_needed_mock_call_count == old_transport_is_needed_mock_call_count + 1); @@ -797,7 +798,7 @@ test_config_parse_transport_plugin_line(void *arg) r = parse_transport_line(options, "transport_1 exec /usr/bin/fake-transport", 0, 0); /* Should have succeeded */ - tt_assert(r == 0); + tt_int_op(r, OP_EQ, 0); /* * transport_is_needed() and pt_kickstart_proxy() should have been * called. @@ -821,7 +822,7 @@ test_config_parse_transport_plugin_line(void *arg) r = parse_transport_line(options, "transport_1 socks5 1.2.3.4:567", 0, 0); /* Should have succeeded */ - tt_assert(r == 0); + tt_int_op(r, OP_EQ, 0); /* * transport_is_needed() and transport_add_from_config() should have * been called. @@ -1139,7 +1140,7 @@ test_config_resolve_my_address(void *arg) &method_used,&hostname_out); tt_want(retval == 0); - tt_want_str_op(method_used,==,"CONFIGURED"); + tt_want_str_op(method_used,OP_EQ,"CONFIGURED"); tt_want(hostname_out == NULL); tt_assert(resolved_addr == 0x80348069); @@ -1164,8 +1165,8 @@ test_config_resolve_my_address(void *arg) tt_want(retval == 0); tt_want(n_hostname_01010101 == prev_n_hostname_01010101 + 1); - tt_want_str_op(method_used,==,"RESOLVED"); - tt_want_str_op(hostname_out,==,"www.torproject.org"); + tt_want_str_op(method_used,OP_EQ,"RESOLVED"); + tt_want_str_op(hostname_out,OP_EQ,"www.torproject.org"); tt_assert(resolved_addr == 0x01010101); UNMOCK(tor_lookup_hostname); @@ -1196,8 +1197,8 @@ test_config_resolve_my_address(void *arg) tt_want(retval == 0); tt_want(n_gethostname_replacement == prev_n_gethostname_replacement + 1); tt_want(n_hostname_01010101 == prev_n_hostname_01010101 + 1); - tt_want_str_op(method_used,==,"GETHOSTNAME"); - tt_want_str_op(hostname_out,==,"onionrouter!"); + tt_want_str_op(method_used,OP_EQ,"GETHOSTNAME"); + tt_want_str_op(hostname_out,OP_EQ,"onionrouter!"); tt_assert(resolved_addr == 0x01010101); UNMOCK(tor_gethostname); @@ -1219,7 +1220,7 @@ test_config_resolve_my_address(void *arg) &method_used,&hostname_out); tt_want(resolved_addr == 0); - tt_assert(retval == -1); + tt_int_op(retval, OP_EQ, -1); tor_free(options->Address); tor_free(hostname_out); @@ -1241,7 +1242,7 @@ test_config_resolve_my_address(void *arg) &method_used,&hostname_out); tt_want(n_hostname_failure == prev_n_hostname_failure + 1); - tt_assert(retval == -1); + tt_int_op(retval, OP_EQ, -1); UNMOCK(tor_lookup_hostname); @@ -1262,7 +1263,7 @@ test_config_resolve_my_address(void *arg) &method_used,&hostname_out); tt_want(n_gethostname_failure == prev_n_gethostname_failure + 1); - tt_assert(retval == -1); + tt_int_op(retval, OP_EQ, -1); UNMOCK(tor_gethostname); tor_free(hostname_out); @@ -1285,11 +1286,11 @@ test_config_resolve_my_address(void *arg) &method_used,&hostname_out); tt_want(retval == 0); - tt_want_int_op(n_gethostname_replacement, ==, + tt_want_int_op(n_gethostname_replacement, OP_EQ, prev_n_gethostname_replacement + 1); - tt_want_int_op(n_get_interface_address, ==, + tt_want_int_op(n_get_interface_address, OP_EQ, prev_n_get_interface_address + 1); - tt_want_str_op(method_used,==,"INTERFACE"); + tt_want_str_op(method_used,OP_EQ,"INTERFACE"); tt_want(hostname_out == NULL); tt_assert(resolved_addr == 0x08080808); @@ -1315,7 +1316,7 @@ test_config_resolve_my_address(void *arg) prev_n_get_interface_address_failure + 1); tt_want(n_gethostname_replacement == prev_n_gethostname_replacement + 1); - tt_assert(retval == -1); + tt_int_op(retval, OP_EQ, -1); UNMOCK(get_interface_address); tor_free(hostname_out); @@ -1345,7 +1346,7 @@ test_config_resolve_my_address(void *arg) tt_want(n_hostname_failure == prev_n_hostname_failure + 1); tt_want(n_gethostname_replacement == prev_n_gethostname_replacement + 1); tt_want(retval == 0); - tt_want_str_op(method_used,==,"INTERFACE"); + tt_want_str_op(method_used,OP_EQ,"INTERFACE"); tt_assert(resolved_addr == 0x09090909); UNMOCK(tor_lookup_hostname); @@ -1375,7 +1376,7 @@ test_config_resolve_my_address(void *arg) &method_used,&hostname_out); tt_want(n_hostname_failure == prev_n_hostname_failure + 1); - tt_assert(retval == -1); + tt_int_op(retval, OP_EQ, -1); UNMOCK(tor_gethostname); UNMOCK(tor_lookup_hostname); @@ -1419,9 +1420,9 @@ test_config_resolve_my_address(void *arg) tt_want(n_hostname_localhost == prev_n_hostname_localhost + 1); tt_want(n_get_interface_address6 == prev_n_get_interface_address6 + 1); - tt_str_op(method_used,==,"INTERFACE"); - tt_assert(!hostname_out); - tt_assert(retval == 0); + tt_str_op(method_used,OP_EQ,"INTERFACE"); + tt_ptr_op(hostname_out, OP_EQ, NULL); + tt_int_op(retval, OP_EQ, 0); /* * CASE 11b: @@ -1446,7 +1447,7 @@ test_config_resolve_my_address(void *arg) tt_want(n_get_interface_address6_failure == prev_n_get_interface_address6_failure + 1); - tt_assert(retval == -1); + tt_int_op(retval, OP_EQ, -1); UNMOCK(tor_gethostname); UNMOCK(tor_lookup_hostname); @@ -1475,7 +1476,7 @@ test_config_resolve_my_address(void *arg) &method_used,&hostname_out); tt_want(n_gethostname_localhost == prev_n_gethostname_localhost + 1); - tt_assert(retval == -1); + tt_int_op(retval, OP_EQ, -1); UNMOCK(tor_gethostname); @@ -1510,18 +1511,18 @@ test_config_adding_trusted_dir_server(void *arg) NULL, V3_DIRINFO, 1.0); tt_assert(ds); dir_server_add(ds); - tt_assert(get_n_authorities(V3_DIRINFO) == 1); - tt_assert(smartlist_len(router_get_fallback_dir_servers()) == 1); + tt_int_op(get_n_authorities(V3_DIRINFO), OP_EQ, 1); + tt_int_op(smartlist_len(router_get_fallback_dir_servers()), OP_EQ, 1); /* create a trusted ds with an IPv6 address and port */ rv = tor_addr_port_parse(LOG_WARN, "[::1]:9061", &ipv6.addr, &ipv6.port, -1); - tt_assert(rv == 0); + tt_int_op(rv, OP_EQ, 0); ds = trusted_dir_server_new("ds", "127.0.0.1", 9059, 9060, &ipv6, digest, NULL, V3_DIRINFO, 1.0); tt_assert(ds); dir_server_add(ds); - tt_assert(get_n_authorities(V3_DIRINFO) == 2); - tt_assert(smartlist_len(router_get_fallback_dir_servers()) == 2); + tt_int_op(get_n_authorities(V3_DIRINFO), OP_EQ, 2); + tt_int_op(smartlist_len(router_get_fallback_dir_servers()), OP_EQ, 2); done: clear_dir_servers(); @@ -1543,21 +1544,21 @@ test_config_adding_fallback_dir_server(void *arg) routerlist_free_all(); rv = tor_addr_parse(&ipv4, "127.0.0.1"); - tt_assert(rv == AF_INET); + tt_int_op(rv, OP_EQ, AF_INET); /* create a trusted ds without an IPv6 address and port */ ds = fallback_dir_server_new(&ipv4, 9059, 9060, NULL, digest, 1.0); tt_assert(ds); dir_server_add(ds); - tt_assert(smartlist_len(router_get_fallback_dir_servers()) == 1); + tt_int_op(smartlist_len(router_get_fallback_dir_servers()), OP_EQ, 1); /* create a trusted ds with an IPv6 address and port */ rv = tor_addr_port_parse(LOG_WARN, "[::1]:9061", &ipv6.addr, &ipv6.port, -1); - tt_assert(rv == 0); + tt_int_op(rv, OP_EQ, 0); ds = fallback_dir_server_new(&ipv4, 9059, 9060, &ipv6, digest, 1.0); tt_assert(ds); dir_server_add(ds); - tt_assert(smartlist_len(router_get_fallback_dir_servers()) == 2); + tt_int_op(smartlist_len(router_get_fallback_dir_servers()), OP_EQ, 2); done: clear_dir_servers(); @@ -1588,14 +1589,14 @@ test_config_parsing_trusted_dir_server(void *arg) rv = parse_dir_authority_line(TEST_DIR_AUTH_LINE_START TEST_DIR_AUTH_LINE_END, V3_DIRINFO, 1); - tt_assert(rv == 0); + tt_int_op(rv, OP_EQ, 0); /* parse a trusted dir server with an IPv6 address and port */ rv = parse_dir_authority_line(TEST_DIR_AUTH_LINE_START TEST_DIR_AUTH_IPV6_FLAG TEST_DIR_AUTH_LINE_END, V3_DIRINFO, 1); - tt_assert(rv == 0); + tt_int_op(rv, OP_EQ, 0); /* Since we are only validating, there is no cleanup. */ done: @@ -1623,13 +1624,13 @@ test_config_parsing_fallback_dir_server(void *arg) /* parse a trusted dir server without an IPv6 address and port */ rv = parse_dir_fallback_line(TEST_DIR_FALLBACK_LINE, 1); - tt_assert(rv == 0); + tt_int_op(rv, OP_EQ, 0); /* parse a trusted dir server with an IPv6 address and port */ rv = parse_dir_fallback_line(TEST_DIR_FALLBACK_LINE TEST_DIR_FALLBACK_IPV6_FLAG, 1); - tt_assert(rv == 0); + tt_int_op(rv, OP_EQ, 0); /* Since we are only validating, there is no cleanup. */ done: @@ -1649,8 +1650,8 @@ test_config_adding_default_trusted_dir_servers(void *arg) /* Assume we only have one bridge authority */ add_default_trusted_dir_authorities(BRIDGE_DIRINFO); - tt_assert(get_n_authorities(BRIDGE_DIRINFO) == 1); - tt_assert(smartlist_len(router_get_fallback_dir_servers()) == 1); + tt_int_op(get_n_authorities(BRIDGE_DIRINFO), OP_EQ, 1); + tt_int_op(smartlist_len(router_get_fallback_dir_servers()), OP_EQ, 1); /* Assume we have eight V3 authorities */ add_default_trusted_dir_authorities(V3_DIRINFO); @@ -1838,7 +1839,7 @@ test_config_adding_dir_servers(void *arg) /* check outcome */ /* we must have added the default fallback dirs */ - tt_assert(n_add_default_fallback_dir_servers_known_default == 1); + tt_int_op(n_add_default_fallback_dir_servers_known_default, OP_EQ, 1); /* we have more fallbacks than just the authorities */ tt_assert(networkstatus_consensus_can_use_extra_fallbacks(options) == 1); @@ -1857,7 +1858,7 @@ test_config_adding_dir_servers(void *arg) 1 : 0) ); /* If we have no default bridge authority, something has gone wrong */ - tt_assert(n_default_alt_bridge_authority >= 1); + tt_int_op(n_default_alt_bridge_authority, OP_GE, 1); /* Count v3 Authorities */ SMARTLIST_FOREACH(fallback_servers, @@ -1869,7 +1870,7 @@ test_config_adding_dir_servers(void *arg) 1 : 0) ); /* If we have no default authorities, something has gone really wrong */ - tt_assert(n_default_alt_dir_authority >= 1); + tt_int_op(n_default_alt_dir_authority, OP_GE, 1); /* Calculate Fallback Directory Count */ n_default_fallback_dir = (smartlist_len(fallback_servers) - @@ -1879,7 +1880,7 @@ test_config_adding_dir_servers(void *arg) * or some authorities aren't being added as fallback directories. * (networkstatus_consensus_can_use_extra_fallbacks depends on all * authorities being fallback directories.) */ - tt_assert(n_default_fallback_dir >= 0); + tt_int_op(n_default_fallback_dir, OP_GE, 0); } } @@ -1920,7 +1921,7 @@ test_config_adding_dir_servers(void *arg) /* check outcome */ /* we must not have added the default fallback dirs */ - tt_assert(n_add_default_fallback_dir_servers_known_default == 0); + tt_int_op(n_add_default_fallback_dir_servers_known_default, OP_EQ, 0); /* we have more fallbacks than just the authorities */ tt_assert(networkstatus_consensus_can_use_extra_fallbacks(options) == 1); @@ -1929,7 +1930,7 @@ test_config_adding_dir_servers(void *arg) /* trusted_dir_servers */ const smartlist_t *dir_servers = router_get_trusted_dir_servers(); /* D0, (No B1), (No A2) */ - tt_assert(smartlist_len(dir_servers) == 1); + tt_int_op(smartlist_len(dir_servers), OP_EQ, 1); /* DirAuthority - D0 - dir_port: 60090 */ int found_D0 = 0; @@ -1941,7 +1942,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60090 ? 1 : 0) ); - tt_assert(found_D0 == 1); + tt_int_op(found_D0, OP_EQ, 1); /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ int found_B1 = 0; @@ -1953,7 +1954,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60091 ? 1 : 0) ); - tt_assert(found_B1 == 0); + tt_int_op(found_B1, OP_EQ, 0); /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ int found_A2 = 0; @@ -1965,14 +1966,14 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60092 ? 1 : 0) ); - tt_assert(found_A2 == 0); + tt_int_op(found_A2, OP_EQ, 0); } { /* fallback_dir_servers */ const smartlist_t *fallback_servers = router_get_fallback_dir_servers(); /* D0, (No B1), (No A2), Custom Fallback */ - tt_assert(smartlist_len(fallback_servers) == 2); + tt_int_op(smartlist_len(fallback_servers), OP_EQ, 2); /* DirAuthority - D0 - dir_port: 60090 */ int found_D0 = 0; @@ -1984,7 +1985,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60090 ? 1 : 0) ); - tt_assert(found_D0 == 1); + tt_int_op(found_D0, OP_EQ, 1); /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ int found_B1 = 0; @@ -1996,7 +1997,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60091 ? 1 : 0) ); - tt_assert(found_B1 == 0); + tt_int_op(found_B1, OP_EQ, 0); /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ int found_A2 = 0; @@ -2008,7 +2009,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60092 ? 1 : 0) ); - tt_assert(found_A2 == 0); + tt_int_op(found_A2, OP_EQ, 0); /* Custom FallbackDir - No Nickname - dir_port: 60093 */ int found_non_default_fallback = 0; @@ -2020,7 +2021,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60093 ? 1 : 0) ); - tt_assert(found_non_default_fallback == 1); + tt_int_op(found_non_default_fallback, OP_EQ, 1); /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */ int found_default_fallback = 0; @@ -2032,7 +2033,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60099 ? 1 : 0) ); - tt_assert(found_default_fallback == 0); + tt_int_op(found_default_fallback, OP_EQ, 0); } } @@ -2061,7 +2062,7 @@ test_config_adding_dir_servers(void *arg) /* check outcome */ /* we must not have added the default fallback dirs */ - tt_assert(n_add_default_fallback_dir_servers_known_default == 0); + tt_int_op(n_add_default_fallback_dir_servers_known_default, OP_EQ, 0); /* we just have the authorities */ tt_assert(networkstatus_consensus_can_use_extra_fallbacks(options) == 0); @@ -2070,7 +2071,7 @@ test_config_adding_dir_servers(void *arg) /* trusted_dir_servers */ const smartlist_t *dir_servers = router_get_trusted_dir_servers(); /* D0, (No B1), (No A2) */ - tt_assert(smartlist_len(dir_servers) == 1); + tt_int_op(smartlist_len(dir_servers), OP_EQ, 1); /* DirAuthority - D0 - dir_port: 60090 */ int found_D0 = 0; @@ -2082,7 +2083,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60090 ? 1 : 0) ); - tt_assert(found_D0 == 1); + tt_int_op(found_D0, OP_EQ, 1); /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ int found_B1 = 0; @@ -2094,7 +2095,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60091 ? 1 : 0) ); - tt_assert(found_B1 == 0); + tt_int_op(found_B1, OP_EQ, 0); /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ int found_A2 = 0; @@ -2106,14 +2107,14 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60092 ? 1 : 0) ); - tt_assert(found_A2 == 0); + tt_int_op(found_A2, OP_EQ, 0); } { /* fallback_dir_servers */ const smartlist_t *fallback_servers = router_get_fallback_dir_servers(); /* D0, (No B1), (No A2), (No Fallback) */ - tt_assert(smartlist_len(fallback_servers) == 1); + tt_int_op(smartlist_len(fallback_servers), OP_EQ, 1); /* DirAuthority - D0 - dir_port: 60090 */ int found_D0 = 0; @@ -2125,7 +2126,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60090 ? 1 : 0) ); - tt_assert(found_D0 == 1); + tt_int_op(found_D0, OP_EQ, 1); /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ int found_B1 = 0; @@ -2137,7 +2138,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60091 ? 1 : 0) ); - tt_assert(found_B1 == 0); + tt_int_op(found_B1, OP_EQ, 0); /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ int found_A2 = 0; @@ -2149,7 +2150,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60092 ? 1 : 0) ); - tt_assert(found_A2 == 0); + tt_int_op(found_A2, OP_EQ, 0); /* (No Custom FallbackDir) - No Nickname - dir_port: 60093 */ int found_non_default_fallback = 0; @@ -2161,7 +2162,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60093 ? 1 : 0) ); - tt_assert(found_non_default_fallback == 0); + tt_int_op(found_non_default_fallback, OP_EQ, 0); /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */ int found_default_fallback = 0; @@ -2173,7 +2174,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60099 ? 1 : 0) ); - tt_assert(found_default_fallback == 0); + tt_int_op(found_default_fallback, OP_EQ, 0); } } @@ -2202,7 +2203,7 @@ test_config_adding_dir_servers(void *arg) /* check outcome */ /* we must not have added the default fallback dirs */ - tt_assert(n_add_default_fallback_dir_servers_known_default == 0); + tt_int_op(n_add_default_fallback_dir_servers_known_default, OP_EQ, 0); /* we have more fallbacks than just the authorities */ tt_assert(networkstatus_consensus_can_use_extra_fallbacks(options) == 1); @@ -2211,7 +2212,7 @@ test_config_adding_dir_servers(void *arg) /* trusted_dir_servers */ const smartlist_t *dir_servers = router_get_trusted_dir_servers(); /* (No D0), B1, A2 */ - tt_assert(smartlist_len(dir_servers) == 2); + tt_int_op(smartlist_len(dir_servers), OP_EQ, 2); /* (No DirAuthority) - D0 - dir_port: 60090 */ int found_D0 = 0; @@ -2223,7 +2224,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60090 ? 1 : 0) ); - tt_assert(found_D0 == 0); + tt_int_op(found_D0, OP_EQ, 0); /* AlternateBridgeAuthority - B1 - dir_port: 60091 */ int found_B1 = 0; @@ -2235,7 +2236,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60091 ? 1 : 0) ); - tt_assert(found_B1 == 1); + tt_int_op(found_B1, OP_EQ, 1); /* AlternateDirAuthority - A2 - dir_port: 60092 */ int found_A2 = 0; @@ -2247,14 +2248,14 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60092 ? 1 : 0) ); - tt_assert(found_A2 == 1); + tt_int_op(found_A2, OP_EQ, 1); } { /* fallback_dir_servers */ const smartlist_t *fallback_servers = router_get_fallback_dir_servers(); /* (No D0), B1, A2, Custom Fallback */ - tt_assert(smartlist_len(fallback_servers) == 3); + tt_int_op(smartlist_len(fallback_servers), OP_EQ, 3); /* (No DirAuthority) - D0 - dir_port: 60090 */ int found_D0 = 0; @@ -2266,7 +2267,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60090 ? 1 : 0) ); - tt_assert(found_D0 == 0); + tt_int_op(found_D0, OP_EQ, 0); /* AlternateBridgeAuthority - B1 - dir_port: 60091 */ int found_B1 = 0; @@ -2278,7 +2279,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60091 ? 1 : 0) ); - tt_assert(found_B1 == 1); + tt_int_op(found_B1, OP_EQ, 1); /* AlternateDirAuthority - A2 - dir_port: 60092 */ int found_A2 = 0; @@ -2290,7 +2291,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60092 ? 1 : 0) ); - tt_assert(found_A2 == 1); + tt_int_op(found_A2, OP_EQ, 1); /* Custom FallbackDir - No Nickname - dir_port: 60093 */ int found_non_default_fallback = 0; @@ -2302,7 +2303,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60093 ? 1 : 0) ); - tt_assert(found_non_default_fallback == 1); + tt_int_op(found_non_default_fallback, OP_EQ, 1); /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */ int found_default_fallback = 0; @@ -2314,7 +2315,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60099 ? 1 : 0) ); - tt_assert(found_default_fallback == 0); + tt_int_op(found_default_fallback, OP_EQ, 0); } } @@ -2344,7 +2345,7 @@ test_config_adding_dir_servers(void *arg) /* check outcome */ /* we must not have added the default fallback dirs */ - tt_assert(n_add_default_fallback_dir_servers_known_default == 0); + tt_int_op(n_add_default_fallback_dir_servers_known_default, OP_EQ, 0); /* we have more fallbacks than just the authorities */ tt_assert(networkstatus_consensus_can_use_extra_fallbacks(options) == 0); @@ -2353,7 +2354,7 @@ test_config_adding_dir_servers(void *arg) /* trusted_dir_servers */ const smartlist_t *dir_servers = router_get_trusted_dir_servers(); /* (No D0), B1, A2 */ - tt_assert(smartlist_len(dir_servers) == 2); + tt_int_op(smartlist_len(dir_servers), OP_EQ, 2); /* (No DirAuthority) - D0 - dir_port: 60090 */ int found_D0 = 0; @@ -2365,7 +2366,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60090 ? 1 : 0) ); - tt_assert(found_D0 == 0); + tt_int_op(found_D0, OP_EQ, 0); /* AlternateBridgeAuthority - B1 - dir_port: 60091 */ int found_B1 = 0; @@ -2377,7 +2378,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60091 ? 1 : 0) ); - tt_assert(found_B1 == 1); + tt_int_op(found_B1, OP_EQ, 1); /* AlternateDirAuthority - A2 - dir_port: 60092 */ int found_A2 = 0; @@ -2389,14 +2390,14 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60092 ? 1 : 0) ); - tt_assert(found_A2 == 1); + tt_int_op(found_A2, OP_EQ, 1); } { /* fallback_dir_servers */ const smartlist_t *fallback_servers = router_get_fallback_dir_servers(); /* (No D0), B1, A2, (No Fallback) */ - tt_assert(smartlist_len(fallback_servers) == 2); + tt_int_op(smartlist_len(fallback_servers), OP_EQ, 2); /* (No DirAuthority) - D0 - dir_port: 60090 */ int found_D0 = 0; @@ -2408,7 +2409,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60090 ? 1 : 0) ); - tt_assert(found_D0 == 0); + tt_int_op(found_D0, OP_EQ, 0); /* AlternateBridgeAuthority - B1 - dir_port: 60091 */ int found_B1 = 0; @@ -2420,7 +2421,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60091 ? 1 : 0) ); - tt_assert(found_B1 == 1); + tt_int_op(found_B1, OP_EQ, 1); /* AlternateDirAuthority - A2 - dir_port: 60092 */ int found_A2 = 0; @@ -2432,7 +2433,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60092 ? 1 : 0) ); - tt_assert(found_A2 == 1); + tt_int_op(found_A2, OP_EQ, 1); /* (No Custom FallbackDir) - No Nickname - dir_port: 60093 */ int found_non_default_fallback = 0; @@ -2444,7 +2445,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60093 ? 1 : 0) ); - tt_assert(found_non_default_fallback == 0); + tt_int_op(found_non_default_fallback, OP_EQ, 0); /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */ int found_default_fallback = 0; @@ -2456,7 +2457,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60099 ? 1 : 0) ); - tt_assert(found_default_fallback == 0); + tt_int_op(found_default_fallback, OP_EQ, 0); } } @@ -2496,7 +2497,7 @@ test_config_adding_dir_servers(void *arg) /* check outcome */ /* we must not have added the default fallback dirs */ - tt_assert(n_add_default_fallback_dir_servers_known_default == 0); + tt_int_op(n_add_default_fallback_dir_servers_known_default, OP_EQ, 0); /* we have more fallbacks than just the authorities */ tt_assert(networkstatus_consensus_can_use_extra_fallbacks(options) == 1); @@ -2517,7 +2518,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60090 ? 1 : 0) ); - tt_assert(found_D0 == 0); + tt_int_op(found_D0, OP_EQ, 0); /* AlternateBridgeAuthority - B1 - dir_port: 60091 */ int found_B1 = 0; @@ -2529,7 +2530,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60091 ? 1 : 0) ); - tt_assert(found_B1 == 1); + tt_int_op(found_B1, OP_EQ, 1); /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ int found_A2 = 0; @@ -2541,7 +2542,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60092 ? 1 : 0) ); - tt_assert(found_A2 == 0); + tt_int_op(found_A2, OP_EQ, 0); /* There's no easy way of checking that we have included all the * default v3 non-Bridge directory authorities, so let's assume that @@ -2567,7 +2568,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60090 ? 1 : 0) ); - tt_assert(found_D0 == 0); + tt_int_op(found_D0, OP_EQ, 0); /* AlternateBridgeAuthority - B1 - dir_port: 60091 */ int found_B1 = 0; @@ -2579,7 +2580,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60091 ? 1 : 0) ); - tt_assert(found_B1 == 1); + tt_int_op(found_B1, OP_EQ, 1); /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ int found_A2 = 0; @@ -2591,7 +2592,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60092 ? 1 : 0) ); - tt_assert(found_A2 == 0); + tt_int_op(found_A2, OP_EQ, 0); /* Custom FallbackDir - No Nickname - dir_port: 60093 */ int found_non_default_fallback = 0; @@ -2603,7 +2604,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60093 ? 1 : 0) ); - tt_assert(found_non_default_fallback == 1); + tt_int_op(found_non_default_fallback, OP_EQ, 1); /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */ int found_default_fallback = 0; @@ -2615,7 +2616,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60099 ? 1 : 0) ); - tt_assert(found_default_fallback == 0); + tt_int_op(found_default_fallback, OP_EQ, 0); /* There's no easy way of checking that we have included all the * default v3 non-Bridge directory authorities, so let's assume that @@ -2650,7 +2651,7 @@ test_config_adding_dir_servers(void *arg) /* check outcome */ /* we must have added the default fallback dirs */ - tt_assert(n_add_default_fallback_dir_servers_known_default == 1); + tt_int_op(n_add_default_fallback_dir_servers_known_default, OP_EQ, 1); /* we have more fallbacks than just the authorities */ tt_assert(networkstatus_consensus_can_use_extra_fallbacks(options) == 1); @@ -2671,7 +2672,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60090 ? 1 : 0) ); - tt_assert(found_D0 == 0); + tt_int_op(found_D0, OP_EQ, 0); /* AlternateBridgeAuthority - B1 - dir_port: 60091 */ int found_B1 = 0; @@ -2683,7 +2684,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60091 ? 1 : 0) ); - tt_assert(found_B1 == 1); + tt_int_op(found_B1, OP_EQ, 1); /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ int found_A2 = 0; @@ -2695,7 +2696,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60092 ? 1 : 0) ); - tt_assert(found_A2 == 0); + tt_int_op(found_A2, OP_EQ, 0); /* There's no easy way of checking that we have included all the * default v3 non-Bridge directory authorities, so let's assume that @@ -2721,7 +2722,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60090 ? 1 : 0) ); - tt_assert(found_D0 == 0); + tt_int_op(found_D0, OP_EQ, 0); /* AlternateBridgeAuthority - B1 - dir_port: 60091 */ int found_B1 = 0; @@ -2733,7 +2734,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60091 ? 1 : 0) ); - tt_assert(found_B1 == 1); + tt_int_op(found_B1, OP_EQ, 1); /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ int found_A2 = 0; @@ -2745,7 +2746,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60092 ? 1 : 0) ); - tt_assert(found_A2 == 0); + tt_int_op(found_A2, OP_EQ, 0); /* (No Custom FallbackDir) - No Nickname - dir_port: 60093 */ int found_non_default_fallback = 0; @@ -2757,7 +2758,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60093 ? 1 : 0) ); - tt_assert(found_non_default_fallback == 0); + tt_int_op(found_non_default_fallback, OP_EQ, 0); /* Default FallbackDir - No Nickname - dir_port: 60099 */ int found_default_fallback = 0; @@ -2769,7 +2770,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60099 ? 1 : 0) ); - tt_assert(found_default_fallback == 1); + tt_int_op(found_default_fallback, OP_EQ, 1); /* There's no easy way of checking that we have included all the * default v3 non-Bridge directory authorities, so let's assume that @@ -2813,7 +2814,7 @@ test_config_adding_dir_servers(void *arg) /* check outcome */ /* we must not have added the default fallback dirs */ - tt_assert(n_add_default_fallback_dir_servers_known_default == 0); + tt_int_op(n_add_default_fallback_dir_servers_known_default, OP_EQ, 0); /* we have more fallbacks than just the authorities */ tt_assert(networkstatus_consensus_can_use_extra_fallbacks(options) == 1); @@ -2835,7 +2836,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60090 ? 1 : 0) ); - tt_assert(found_D0 == 0); + tt_int_op(found_D0, OP_EQ, 0); /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ int found_B1 = 0; @@ -2847,7 +2848,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60091 ? 1 : 0) ); - tt_assert(found_B1 == 0); + tt_int_op(found_B1, OP_EQ, 0); /* AlternateDirAuthority - A2 - dir_port: 60092 */ int found_A2 = 0; @@ -2859,7 +2860,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60092 ? 1 : 0) ); - tt_assert(found_A2 == 1); + tt_int_op(found_A2, OP_EQ, 1); /* There's no easy way of checking that we have included all the * default Bridge authorities (except for hard-coding tonga's details), @@ -2886,7 +2887,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60090 ? 1 : 0) ); - tt_assert(found_D0 == 0); + tt_int_op(found_D0, OP_EQ, 0); /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ int found_B1 = 0; @@ -2898,7 +2899,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60091 ? 1 : 0) ); - tt_assert(found_B1 == 0); + tt_int_op(found_B1, OP_EQ, 0); /* AlternateDirAuthority - A2 - dir_port: 60092 */ int found_A2 = 0; @@ -2910,7 +2911,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60092 ? 1 : 0) ); - tt_assert(found_A2 == 1); + tt_int_op(found_A2, OP_EQ, 1); /* Custom FallbackDir - No Nickname - dir_port: 60093 */ int found_non_default_fallback = 0; @@ -2922,7 +2923,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60093 ? 1 : 0) ); - tt_assert(found_non_default_fallback == 1); + tt_int_op(found_non_default_fallback, OP_EQ, 1); /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */ int found_default_fallback = 0; @@ -2934,7 +2935,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60099 ? 1 : 0) ); - tt_assert(found_default_fallback == 0); + tt_int_op(found_default_fallback, OP_EQ, 0); /* There's no easy way of checking that we have included all the * default Bridge authorities (except for hard-coding tonga's details), @@ -2970,7 +2971,7 @@ test_config_adding_dir_servers(void *arg) /* check outcome */ /* we must not have added the default fallback dirs */ - tt_assert(n_add_default_fallback_dir_servers_known_default == 0); + tt_int_op(n_add_default_fallback_dir_servers_known_default, OP_EQ, 0); /* we just have the authorities */ tt_assert(networkstatus_consensus_can_use_extra_fallbacks(options) == 0); @@ -2993,7 +2994,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60090 ? 1 : 0) ); - tt_assert(found_D0 == 0); + tt_int_op(found_D0, OP_EQ, 0); /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ int found_B1 = 0; @@ -3005,7 +3006,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60091 ? 1 : 0) ); - tt_assert(found_B1 == 0); + tt_int_op(found_B1, OP_EQ, 0); /* AlternateDirAuthority - A2 - dir_port: 60092 */ int found_A2 = 0; @@ -3017,7 +3018,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60092 ? 1 : 0) ); - tt_assert(found_A2 == 1); + tt_int_op(found_A2, OP_EQ, 1); /* There's no easy way of checking that we have included all the * default Bridge authorities (except for hard-coding tonga's details), @@ -3044,7 +3045,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60090 ? 1 : 0) ); - tt_assert(found_D0 == 0); + tt_int_op(found_D0, OP_EQ, 0); /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ int found_B1 = 0; @@ -3056,7 +3057,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60091 ? 1 : 0) ); - tt_assert(found_B1 == 0); + tt_int_op(found_B1, OP_EQ, 0); /* AlternateDirAuthority - A2 - dir_port: 60092 */ int found_A2 = 0; @@ -3068,7 +3069,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60092 ? 1 : 0) ); - tt_assert(found_A2 == 1); + tt_int_op(found_A2, OP_EQ, 1); /* (No Custom FallbackDir) - No Nickname - dir_port: 60093 */ int found_non_default_fallback = 0; @@ -3080,7 +3081,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60093 ? 1 : 0) ); - tt_assert(found_non_default_fallback == 0); + tt_int_op(found_non_default_fallback, OP_EQ, 0); /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */ int found_default_fallback = 0; @@ -3092,7 +3093,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60099 ? 1 : 0) ); - tt_assert(found_default_fallback == 0); + tt_int_op(found_default_fallback, OP_EQ, 0); /* There's no easy way of checking that we have included all the * default Bridge authorities (except for hard-coding tonga's details), @@ -3136,7 +3137,7 @@ test_config_adding_dir_servers(void *arg) /* check outcome */ /* we must not have added the default fallback dirs */ - tt_assert(n_add_default_fallback_dir_servers_known_default == 0); + tt_int_op(n_add_default_fallback_dir_servers_known_default, OP_EQ, 0); /* we have more fallbacks than just the authorities */ tt_assert(networkstatus_consensus_can_use_extra_fallbacks(options) == 1); @@ -3158,7 +3159,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60090 ? 1 : 0) ); - tt_assert(found_D0 == 0); + tt_int_op(found_D0, OP_EQ, 0); /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ int found_B1 = 0; @@ -3170,7 +3171,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60091 ? 1 : 0) ); - tt_assert(found_B1 == 0); + tt_int_op(found_B1, OP_EQ, 0); /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ int found_A2 = 0; @@ -3182,7 +3183,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60092 ? 1 : 0) ); - tt_assert(found_A2 == 0); + tt_int_op(found_A2, OP_EQ, 0); /* There's no easy way of checking that we have included all the * default Bridge & V3 Directory authorities, so let's assume that @@ -3209,7 +3210,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60090 ? 1 : 0) ); - tt_assert(found_D0 == 0); + tt_int_op(found_D0, OP_EQ, 0); /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ int found_B1 = 0; @@ -3221,7 +3222,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60091 ? 1 : 0) ); - tt_assert(found_B1 == 0); + tt_int_op(found_B1, OP_EQ, 0); /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ int found_A2 = 0; @@ -3233,7 +3234,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60092 ? 1 : 0) ); - tt_assert(found_A2 == 0); + tt_int_op(found_A2, OP_EQ, 0); /* Custom FallbackDir - No Nickname - dir_port: 60093 */ int found_non_default_fallback = 0; @@ -3245,7 +3246,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60093 ? 1 : 0) ); - tt_assert(found_non_default_fallback == 1); + tt_int_op(found_non_default_fallback, OP_EQ, 1); /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */ int found_default_fallback = 0; @@ -3257,7 +3258,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60099 ? 1 : 0) ); - tt_assert(found_default_fallback == 0); + tt_int_op(found_default_fallback, OP_EQ, 0); /* There's no easy way of checking that we have included all the * default Bridge & V3 Directory authorities, so let's assume that @@ -3299,7 +3300,7 @@ test_config_adding_dir_servers(void *arg) /* check outcome */ /* we must have added the default fallback dirs */ - tt_assert(n_add_default_fallback_dir_servers_known_default == 1); + tt_int_op(n_add_default_fallback_dir_servers_known_default, OP_EQ, 1); /* we have more fallbacks than just the authorities */ tt_assert(networkstatus_consensus_can_use_extra_fallbacks(options) == 1); @@ -3321,7 +3322,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60090 ? 1 : 0) ); - tt_assert(found_D0 == 0); + tt_int_op(found_D0, OP_EQ, 0); /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ int found_B1 = 0; @@ -3333,7 +3334,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60091 ? 1 : 0) ); - tt_assert(found_B1 == 0); + tt_int_op(found_B1, OP_EQ, 0); /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ int found_A2 = 0; @@ -3345,7 +3346,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60092 ? 1 : 0) ); - tt_assert(found_A2 == 0); + tt_int_op(found_A2, OP_EQ, 0); /* There's no easy way of checking that we have included all the * default Bridge & V3 Directory authorities, so let's assume that @@ -3372,7 +3373,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60090 ? 1 : 0) ); - tt_assert(found_D0 == 0); + tt_int_op(found_D0, OP_EQ, 0); /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ int found_B1 = 0; @@ -3384,7 +3385,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60091 ? 1 : 0) ); - tt_assert(found_B1 == 0); + tt_int_op(found_B1, OP_EQ, 0); /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ int found_A2 = 0; @@ -3396,7 +3397,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60092 ? 1 : 0) ); - tt_assert(found_A2 == 0); + tt_int_op(found_A2, OP_EQ, 0); /* Custom FallbackDir - No Nickname - dir_port: 60093 */ int found_non_default_fallback = 0; @@ -3408,7 +3409,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60093 ? 1 : 0) ); - tt_assert(found_non_default_fallback == 0); + tt_int_op(found_non_default_fallback, OP_EQ, 0); /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */ int found_default_fallback = 0; @@ -3420,7 +3421,7 @@ test_config_adding_dir_servers(void *arg) (ds->dir_port == 60099 ? 1 : 0) ); - tt_assert(found_default_fallback == 1); + tt_int_op(found_default_fallback, OP_EQ, 1); /* There's no easy way of checking that we have included all the * default Bridge & V3 Directory authorities, and the default @@ -3477,7 +3478,7 @@ test_config_default_dir_servers(void *arg) opts = NULL; /* assume a release will never go out with less than 7 authorities */ - tt_assert(trusted_count >= 7); + tt_int_op(trusted_count, OP_GE, 7); /* if we disable the default fallbacks, there must not be any extra */ tt_assert(fallback_count == trusted_count); @@ -3490,7 +3491,7 @@ test_config_default_dir_servers(void *arg) opts = NULL; /* assume a release will never go out with less than 7 authorities */ - tt_assert(trusted_count >= 7); + tt_int_op(trusted_count, OP_GE, 7); /* XX/teor - allow for default fallbacks to be added without breaking * the unit tests. Set a minimum fallback count once the list is stable. */ tt_assert(fallback_count >= trusted_count); @@ -3559,18 +3560,18 @@ test_config_directory_fetch(void *arg) options->ClientOnly = 1; tt_assert(server_mode(options) == 0); tt_assert(public_server_mode(options) == 0); - tt_assert(directory_fetches_from_authorities(options) == 0); - tt_assert(networkstatus_consensus_can_use_multiple_directories(options) - == 1); + tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 0); + tt_int_op(networkstatus_consensus_can_use_multiple_directories(options), + OP_EQ, 1); /* Bridge Clients can use multiple directory mirrors for bootstrap */ memset(options, 0, sizeof(or_options_t)); options->UseBridges = 1; tt_assert(server_mode(options) == 0); tt_assert(public_server_mode(options) == 0); - tt_assert(directory_fetches_from_authorities(options) == 0); - tt_assert(networkstatus_consensus_can_use_multiple_directories(options) - == 1); + tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 0); + tt_int_op(networkstatus_consensus_can_use_multiple_directories(options), + OP_EQ, 1); /* Bridge Relays (Bridges) must act like clients, and use multiple * directory mirrors for bootstrap */ @@ -3579,9 +3580,9 @@ test_config_directory_fetch(void *arg) options->ORPort_set = 1; tt_assert(server_mode(options) == 1); tt_assert(public_server_mode(options) == 0); - tt_assert(directory_fetches_from_authorities(options) == 0); - tt_assert(networkstatus_consensus_can_use_multiple_directories(options) - == 1); + tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 0); + tt_int_op(networkstatus_consensus_can_use_multiple_directories(options), + OP_EQ, 1); /* Clients set to FetchDirInfoEarly must fetch it from the authorities, * but can use multiple authorities for bootstrap */ @@ -3589,9 +3590,9 @@ test_config_directory_fetch(void *arg) options->FetchDirInfoEarly = 1; tt_assert(server_mode(options) == 0); tt_assert(public_server_mode(options) == 0); - tt_assert(directory_fetches_from_authorities(options) == 1); - tt_assert(networkstatus_consensus_can_use_multiple_directories(options) - == 1); + tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 1); + tt_int_op(networkstatus_consensus_can_use_multiple_directories(options), + OP_EQ, 1); /* OR servers only fetch the consensus from the authorities when they don't * know their own address, but never use multiple directories for bootstrap @@ -3602,16 +3603,16 @@ test_config_directory_fetch(void *arg) mock_router_pick_published_address_result = -1; tt_assert(server_mode(options) == 1); tt_assert(public_server_mode(options) == 1); - tt_assert(directory_fetches_from_authorities(options) == 1); - tt_assert(networkstatus_consensus_can_use_multiple_directories(options) - == 0); + tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 1); + tt_int_op(networkstatus_consensus_can_use_multiple_directories(options), + OP_EQ, 0); mock_router_pick_published_address_result = 0; tt_assert(server_mode(options) == 1); tt_assert(public_server_mode(options) == 1); - tt_assert(directory_fetches_from_authorities(options) == 0); - tt_assert(networkstatus_consensus_can_use_multiple_directories(options) - == 0); + tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 0); + tt_int_op(networkstatus_consensus_can_use_multiple_directories(options), + OP_EQ, 0); /* Exit OR servers only fetch the consensus from the authorities when they * refuse unknown exits, but never use multiple directories for bootstrap @@ -3629,17 +3630,17 @@ test_config_directory_fetch(void *arg) options->RefuseUnknownExits = 1; tt_assert(server_mode(options) == 1); tt_assert(public_server_mode(options) == 1); - tt_assert(directory_fetches_from_authorities(options) == 1); - tt_assert(networkstatus_consensus_can_use_multiple_directories(options) - == 0); + tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 1); + tt_int_op(networkstatus_consensus_can_use_multiple_directories(options), + OP_EQ, 0); options->RefuseUnknownExits = 0; mock_router_pick_published_address_result = 0; tt_assert(server_mode(options) == 1); tt_assert(public_server_mode(options) == 1); - tt_assert(directory_fetches_from_authorities(options) == 0); - tt_assert(networkstatus_consensus_can_use_multiple_directories(options) - == 0); + tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 0); + tt_int_op(networkstatus_consensus_can_use_multiple_directories(options), + OP_EQ, 0); /* Dir servers fetch the consensus from the authorities, unless they are not * advertising themselves (hibernating) or have no routerinfo or are not @@ -3658,26 +3659,26 @@ test_config_directory_fetch(void *arg) mock_router_get_my_routerinfo_result = &routerinfo; tt_assert(server_mode(options) == 1); tt_assert(public_server_mode(options) == 1); - tt_assert(directory_fetches_from_authorities(options) == 1); - tt_assert(networkstatus_consensus_can_use_multiple_directories(options) - == 0); + tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 1); + tt_int_op(networkstatus_consensus_can_use_multiple_directories(options), + OP_EQ, 0); mock_advertised_server_mode_result = 0; routerinfo.dir_port = 1; mock_router_get_my_routerinfo_result = &routerinfo; tt_assert(server_mode(options) == 1); tt_assert(public_server_mode(options) == 1); - tt_assert(directory_fetches_from_authorities(options) == 0); - tt_assert(networkstatus_consensus_can_use_multiple_directories(options) - == 0); + tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 0); + tt_int_op(networkstatus_consensus_can_use_multiple_directories(options), + OP_EQ, 0); mock_advertised_server_mode_result = 1; mock_router_get_my_routerinfo_result = NULL; tt_assert(server_mode(options) == 1); tt_assert(public_server_mode(options) == 1); - tt_assert(directory_fetches_from_authorities(options) == 0); - tt_assert(networkstatus_consensus_can_use_multiple_directories(options) - == 0); + tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 0); + tt_int_op(networkstatus_consensus_can_use_multiple_directories(options), + OP_EQ, 0); mock_advertised_server_mode_result = 1; routerinfo.dir_port = 0; @@ -3685,9 +3686,9 @@ test_config_directory_fetch(void *arg) mock_router_get_my_routerinfo_result = &routerinfo; tt_assert(server_mode(options) == 1); tt_assert(public_server_mode(options) == 1); - tt_assert(directory_fetches_from_authorities(options) == 0); - tt_assert(networkstatus_consensus_can_use_multiple_directories(options) - == 0); + tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 0); + tt_int_op(networkstatus_consensus_can_use_multiple_directories(options), + OP_EQ, 0); mock_advertised_server_mode_result = 1; routerinfo.dir_port = 1; @@ -3695,9 +3696,9 @@ test_config_directory_fetch(void *arg) mock_router_get_my_routerinfo_result = &routerinfo; tt_assert(server_mode(options) == 1); tt_assert(public_server_mode(options) == 1); - tt_assert(directory_fetches_from_authorities(options) == 1); - tt_assert(networkstatus_consensus_can_use_multiple_directories(options) - == 0); + tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 1); + tt_int_op(networkstatus_consensus_can_use_multiple_directories(options), + OP_EQ, 0); done: tor_free(options); @@ -3744,119 +3745,119 @@ test_config_port_cfg_line_extract_addrport(void *arg) tt_int_op(port_cfg_line_extract_addrport("", &a, &unixy, &rest), OP_EQ, 0); tt_int_op(unixy, OP_EQ, 0); - tt_str_op(a, OP_EQ, "");; + tt_str_op(a, OP_EQ, ""); tt_str_op(rest, OP_EQ, ""); tor_free(a); tt_int_op(port_cfg_line_extract_addrport("hello", &a, &unixy, &rest), OP_EQ, 0); tt_int_op(unixy, OP_EQ, 0); - tt_str_op(a, OP_EQ, "hello");; + tt_str_op(a, OP_EQ, "hello"); tt_str_op(rest, OP_EQ, ""); tor_free(a); tt_int_op(port_cfg_line_extract_addrport(" flipperwalt gersplut", &a, &unixy, &rest), OP_EQ, 0); tt_int_op(unixy, OP_EQ, 0); - tt_str_op(a, OP_EQ, "flipperwalt");; + tt_str_op(a, OP_EQ, "flipperwalt"); tt_str_op(rest, OP_EQ, "gersplut"); tor_free(a); tt_int_op(port_cfg_line_extract_addrport(" flipperwalt \t gersplut", &a, &unixy, &rest), OP_EQ, 0); tt_int_op(unixy, OP_EQ, 0); - tt_str_op(a, OP_EQ, "flipperwalt");; + tt_str_op(a, OP_EQ, "flipperwalt"); tt_str_op(rest, OP_EQ, "gersplut"); tor_free(a); tt_int_op(port_cfg_line_extract_addrport("flipperwalt \t gersplut", &a, &unixy, &rest), OP_EQ, 0); tt_int_op(unixy, OP_EQ, 0); - tt_str_op(a, OP_EQ, "flipperwalt");; + tt_str_op(a, OP_EQ, "flipperwalt"); tt_str_op(rest, OP_EQ, "gersplut"); tor_free(a); tt_int_op(port_cfg_line_extract_addrport("unix:flipperwalt \t gersplut", &a, &unixy, &rest), OP_EQ, 0); tt_int_op(unixy, OP_EQ, 1); - tt_str_op(a, OP_EQ, "flipperwalt");; + tt_str_op(a, OP_EQ, "flipperwalt"); tt_str_op(rest, OP_EQ, "gersplut"); tor_free(a); tt_int_op(port_cfg_line_extract_addrport("lolol", &a, &unixy, &rest), OP_EQ, 0); tt_int_op(unixy, OP_EQ, 0); - tt_str_op(a, OP_EQ, "lolol");; + tt_str_op(a, OP_EQ, "lolol"); tt_str_op(rest, OP_EQ, ""); tor_free(a); tt_int_op(port_cfg_line_extract_addrport("unix:lolol", &a, &unixy, &rest), OP_EQ, 0); tt_int_op(unixy, OP_EQ, 1); - tt_str_op(a, OP_EQ, "lolol");; + tt_str_op(a, OP_EQ, "lolol"); tt_str_op(rest, OP_EQ, ""); tor_free(a); tt_int_op(port_cfg_line_extract_addrport("unix:lolol ", &a, &unixy, &rest), OP_EQ, 0); tt_int_op(unixy, OP_EQ, 1); - tt_str_op(a, OP_EQ, "lolol");; + tt_str_op(a, OP_EQ, "lolol"); tt_str_op(rest, OP_EQ, ""); tor_free(a); tt_int_op(port_cfg_line_extract_addrport(" unix:lolol", &a, &unixy, &rest), OP_EQ, 0); tt_int_op(unixy, OP_EQ, 1); - tt_str_op(a, OP_EQ, "lolol");; + tt_str_op(a, OP_EQ, "lolol"); tt_str_op(rest, OP_EQ, ""); tor_free(a); tt_int_op(port_cfg_line_extract_addrport("foobar:lolol", &a, &unixy, &rest), OP_EQ, 0); tt_int_op(unixy, OP_EQ, 0); - tt_str_op(a, OP_EQ, "foobar:lolol");; + tt_str_op(a, OP_EQ, "foobar:lolol"); tt_str_op(rest, OP_EQ, ""); tor_free(a); tt_int_op(port_cfg_line_extract_addrport(":lolol", &a, &unixy, &rest), OP_EQ, 0); tt_int_op(unixy, OP_EQ, 0); - tt_str_op(a, OP_EQ, ":lolol");; + tt_str_op(a, OP_EQ, ":lolol"); tt_str_op(rest, OP_EQ, ""); tor_free(a); tt_int_op(port_cfg_line_extract_addrport("unix:\"lolol\"", &a, &unixy, &rest), OP_EQ, 0); tt_int_op(unixy, OP_EQ, 1); - tt_str_op(a, OP_EQ, "lolol");; + tt_str_op(a, OP_EQ, "lolol"); tt_str_op(rest, OP_EQ, ""); tor_free(a); tt_int_op(port_cfg_line_extract_addrport("unix:\"lolol\" ", &a, &unixy, &rest), OP_EQ, 0); tt_int_op(unixy, OP_EQ, 1); - tt_str_op(a, OP_EQ, "lolol");; + tt_str_op(a, OP_EQ, "lolol"); tt_str_op(rest, OP_EQ, ""); tor_free(a); tt_int_op(port_cfg_line_extract_addrport("unix:\"lolol\" foo ", &a, &unixy, &rest), OP_EQ, 0); tt_int_op(unixy, OP_EQ, 1); - tt_str_op(a, OP_EQ, "lolol");; + tt_str_op(a, OP_EQ, "lolol"); tt_str_op(rest, OP_EQ, "foo "); tor_free(a); tt_int_op(port_cfg_line_extract_addrport("unix:\"lol ol\" foo ", &a, &unixy, &rest), OP_EQ, 0); tt_int_op(unixy, OP_EQ, 1); - tt_str_op(a, OP_EQ, "lol ol");; + tt_str_op(a, OP_EQ, "lol ol"); tt_str_op(rest, OP_EQ, "foo "); tor_free(a); tt_int_op(port_cfg_line_extract_addrport("unix:\"lol\\\" ol\" foo ", &a, &unixy, &rest), OP_EQ, 0); tt_int_op(unixy, OP_EQ, 1); - tt_str_op(a, OP_EQ, "lol\" ol");; + tt_str_op(a, OP_EQ, "lol\" ol"); tt_str_op(rest, OP_EQ, "foo "); tor_free(a); @@ -4002,9 +4003,9 @@ test_config_parse_port_config__ports__ports_given(void *data) tt_int_op(port_cfg->entry_cfg.dns_request, OP_EQ, 1); tt_int_op(port_cfg->entry_cfg.ipv4_traffic, OP_EQ, 1); tt_int_op(port_cfg->entry_cfg.onion_traffic, OP_EQ, 1); - tt_int_op(port_cfg->entry_cfg.cache_ipv4_answers, OP_EQ, 1); + tt_int_op(port_cfg->entry_cfg.cache_ipv4_answers, OP_EQ, 0); tt_int_op(port_cfg->entry_cfg.prefer_ipv6_virtaddr, OP_EQ, 1); -#endif +#endif /* defined(_WIN32) */ // Test failure if we have no ipv4 and no ipv6 and no onion (DNS only) config_free_lines(config_port_invalid); config_port_invalid = NULL; @@ -4076,7 +4077,7 @@ test_config_parse_port_config__ports__ports_given(void *data) tt_int_op(port_cfg->entry_cfg.ipv4_traffic, OP_EQ, 0); tt_int_op(port_cfg->entry_cfg.ipv6_traffic, OP_EQ, 0); tt_int_op(port_cfg->entry_cfg.onion_traffic, OP_EQ, 1); -#endif +#endif /* defined(_WIN32) */ // Test success with quoted unix: address. config_free_lines(config_port_valid); config_port_valid = NULL; @@ -4098,7 +4099,7 @@ test_config_parse_port_config__ports__ports_given(void *data) tt_int_op(port_cfg->entry_cfg.ipv4_traffic, OP_EQ, 0); tt_int_op(port_cfg->entry_cfg.ipv6_traffic, OP_EQ, 0); tt_int_op(port_cfg->entry_cfg.onion_traffic, OP_EQ, 1); -#endif +#endif /* defined(_WIN32) */ // Test failure with broken quoted unix: address. config_free_lines(config_port_valid); config_port_valid = NULL; @@ -4143,7 +4144,7 @@ test_config_parse_port_config__ports__ports_given(void *data) tt_int_op(port_cfg->entry_cfg.ipv4_traffic, OP_EQ, 0); tt_int_op(port_cfg->entry_cfg.ipv6_traffic, OP_EQ, 0); tt_int_op(port_cfg->entry_cfg.onion_traffic, OP_EQ, 1); -#endif +#endif /* defined(_WIN32) */ // Test success with no ipv4 but take ipv6 config_free_lines(config_port_valid); config_port_valid = NULL; @@ -4162,7 +4163,7 @@ test_config_parse_port_config__ports__ports_given(void *data) port_cfg = (port_cfg_t *)smartlist_get(slout, 0); tt_int_op(port_cfg->entry_cfg.ipv4_traffic, OP_EQ, 0); tt_int_op(port_cfg->entry_cfg.ipv6_traffic, OP_EQ, 1); -#endif +#endif /* defined(_WIN32) */ // Test success with both ipv4 and ipv6 config_free_lines(config_port_valid); config_port_valid = NULL; @@ -4181,7 +4182,7 @@ test_config_parse_port_config__ports__ports_given(void *data) port_cfg = (port_cfg_t *)smartlist_get(slout, 0); tt_int_op(port_cfg->entry_cfg.ipv4_traffic, OP_EQ, 1); tt_int_op(port_cfg->entry_cfg.ipv6_traffic, OP_EQ, 1); -#endif +#endif /* defined(_WIN32) */ // Test failure if we specify world writable for an IP Port config_free_lines(config_port_invalid); config_port_invalid = NULL; @@ -4345,7 +4346,7 @@ test_config_parse_port_config__ports__ports_given(void *data) tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); port_cfg = (port_cfg_t *)smartlist_get(slout, 0); - tt_int_op(port_cfg->entry_cfg.cache_ipv4_answers, OP_EQ, 1); + tt_int_op(port_cfg->entry_cfg.cache_ipv4_answers, OP_EQ, 0); tt_int_op(port_cfg->entry_cfg.cache_ipv6_answers, OP_EQ, 1); // Test success with no cache ipv4 DNS @@ -4645,7 +4646,7 @@ test_config_parse_port_config__ports__ports_given(void *data) tt_int_op(smartlist_len(slout), OP_EQ, 1); port_cfg = (port_cfg_t *)smartlist_get(slout, 0); tt_int_op(port_cfg->is_group_writable, OP_EQ, 1); -#endif +#endif /* defined(_WIN32) */ done: if (slout) @@ -4816,6 +4817,7 @@ test_config_include_limit(void *data) (void)data; config_line_t *result = NULL; + char *torrc_path = NULL; char *dir = tor_strdup(get_fname("test_include_limit")); tt_ptr_op(dir, OP_NE, NULL); @@ -4825,8 +4827,7 @@ test_config_include_limit(void *data) tt_int_op(mkdir(dir, 0700), OP_EQ, 0); #endif - char torrc_path[PATH_MAX+1]; - tor_snprintf(torrc_path, sizeof(torrc_path), "%s"PATH_SEPARATOR"torrc", dir); + tor_asprintf(&torrc_path, "%s"PATH_SEPARATOR"torrc", dir); char torrc_contents[1000]; tor_snprintf(torrc_contents, sizeof(torrc_contents), "%%include %s", torrc_path); @@ -4837,6 +4838,7 @@ test_config_include_limit(void *data) done: config_free_lines(result); + tor_free(torrc_path); tor_free(dir); } @@ -4847,6 +4849,7 @@ test_config_include_does_not_exist(void *data) config_line_t *result = NULL; char *dir = tor_strdup(get_fname("test_include_does_not_exist")); + char *missing_path = NULL; tt_ptr_op(dir, OP_NE, NULL); #ifdef _WIN32 @@ -4855,9 +4858,7 @@ test_config_include_does_not_exist(void *data) tt_int_op(mkdir(dir, 0700), OP_EQ, 0); #endif - char missing_path[PATH_MAX+1]; - tor_snprintf(missing_path, sizeof(missing_path), "%s"PATH_SEPARATOR"missing", - dir); + tor_asprintf(&missing_path, "%s"PATH_SEPARATOR"missing", dir); char torrc_contents[1000]; tor_snprintf(torrc_contents, sizeof(torrc_contents), "%%include %s", missing_path); @@ -4868,6 +4869,7 @@ test_config_include_does_not_exist(void *data) done: config_free_lines(result); tor_free(dir); + tor_free(missing_path); } static void @@ -4877,6 +4879,7 @@ test_config_include_error_in_included_file(void *data) config_line_t *result = NULL; char *dir = tor_strdup(get_fname("test_error_in_included_file")); + char *invalid_path = NULL; tt_ptr_op(dir, OP_NE, NULL); #ifdef _WIN32 @@ -4885,9 +4888,7 @@ test_config_include_error_in_included_file(void *data) tt_int_op(mkdir(dir, 0700), OP_EQ, 0); #endif - char invalid_path[PATH_MAX+1]; - tor_snprintf(invalid_path, sizeof(invalid_path), "%s"PATH_SEPARATOR"invalid", - dir); + tor_asprintf(&invalid_path, "%s"PATH_SEPARATOR"invalid", dir); tt_int_op(write_str_to_file(invalid_path, "unclosed \"", 0), OP_EQ, 0); char torrc_contents[1000]; @@ -4900,6 +4901,7 @@ test_config_include_error_in_included_file(void *data) done: config_free_lines(result); tor_free(dir); + tor_free(invalid_path); } static void @@ -4908,6 +4910,8 @@ test_config_include_empty_file_folder(void *data) (void)data; config_line_t *result = NULL; + char *folder_path = NULL; + char *file_path = NULL; char *dir = tor_strdup(get_fname("test_include_empty_file_folder")); tt_ptr_op(dir, OP_NE, NULL); @@ -4917,17 +4921,13 @@ test_config_include_empty_file_folder(void *data) tt_int_op(mkdir(dir, 0700), OP_EQ, 0); #endif - char folder_path[PATH_MAX+1]; - tor_snprintf(folder_path, sizeof(folder_path), "%s"PATH_SEPARATOR"empty_dir", - dir); + tor_asprintf(&folder_path, "%s"PATH_SEPARATOR"empty_dir", dir); #ifdef _WIN32 tt_int_op(mkdir(folder_path), OP_EQ, 0); #else tt_int_op(mkdir(folder_path, 0700), OP_EQ, 0); #endif - char file_path[PATH_MAX+1]; - tor_snprintf(file_path, sizeof(file_path), "%s"PATH_SEPARATOR"empty_file", - dir); + tor_asprintf(&file_path, "%s"PATH_SEPARATOR"empty_file", dir); tt_int_op(write_str_to_file(file_path, "", 0), OP_EQ, 0); char torrc_contents[1000]; @@ -4944,15 +4944,57 @@ test_config_include_empty_file_folder(void *data) done: config_free_lines(result); + tor_free(folder_path); + tor_free(file_path); tor_free(dir); } +#ifndef _WIN32 +static void +test_config_include_no_permission(void *data) +{ + (void)data; + config_line_t *result = NULL; + + char *folder_path = NULL; + char *dir = NULL; + if (geteuid() == 0) + tt_skip(); + + dir = tor_strdup(get_fname("test_include_forbidden_folder")); + tt_ptr_op(dir, OP_NE, NULL); + + tt_int_op(mkdir(dir, 0700), OP_EQ, 0); + + tor_asprintf(&folder_path, "%s"PATH_SEPARATOR"forbidden_dir", dir); + tt_int_op(mkdir(folder_path, 0100), OP_EQ, 0); + + char torrc_contents[1000]; + tor_snprintf(torrc_contents, sizeof(torrc_contents), + "%%include %s\n", + folder_path); + + int include_used; + tt_int_op(config_get_lines_include(torrc_contents, &result, 0,&include_used), + OP_EQ, -1); + tt_ptr_op(result, OP_EQ, NULL); + + done: + config_free_lines(result); + tor_free(folder_path); + if (dir) + chmod(dir, 0700); + tor_free(dir); +} +#endif + static void test_config_include_recursion_before_after(void *data) { (void)data; config_line_t *result = NULL; + char *torrc_path = NULL; char *dir = tor_strdup(get_fname("test_include_recursion_before_after")); tt_ptr_op(dir, OP_NE, NULL); @@ -4962,8 +5004,7 @@ test_config_include_recursion_before_after(void *data) tt_int_op(mkdir(dir, 0700), OP_EQ, 0); #endif - char torrc_path[PATH_MAX+1]; - tor_snprintf(torrc_path, sizeof(torrc_path), "%s"PATH_SEPARATOR"torrc", dir); + tor_asprintf(&torrc_path, "%s"PATH_SEPARATOR"torrc", dir); char file_contents[1000]; const int limit = MAX_INCLUDE_RECURSION_LEVEL; @@ -4982,9 +5023,10 @@ test_config_include_recursion_before_after(void *data) } if (i > 1) { - char file_path[PATH_MAX+1]; - tor_snprintf(file_path, sizeof(file_path), "%s%d", torrc_path, i); + char *file_path = NULL; + tor_asprintf(&file_path, "%s%d", torrc_path, i); tt_int_op(write_str_to_file(file_path, file_contents, 0), OP_EQ, 0); + tor_free(file_path); } } @@ -5008,6 +5050,7 @@ test_config_include_recursion_before_after(void *data) done: config_free_lines(result); tor_free(dir); + tor_free(torrc_path); } static void @@ -5016,6 +5059,7 @@ test_config_include_recursion_after_only(void *data) (void)data; config_line_t *result = NULL; + char *torrc_path = NULL; char *dir = tor_strdup(get_fname("test_include_recursion_after_only")); tt_ptr_op(dir, OP_NE, NULL); @@ -5025,8 +5069,7 @@ test_config_include_recursion_after_only(void *data) tt_int_op(mkdir(dir, 0700), OP_EQ, 0); #endif - char torrc_path[PATH_MAX+1]; - tor_snprintf(torrc_path, sizeof(torrc_path), "%s"PATH_SEPARATOR"torrc", dir); + tor_asprintf(&torrc_path, "%s"PATH_SEPARATOR"torrc", dir); char file_contents[1000]; const int limit = MAX_INCLUDE_RECURSION_LEVEL; @@ -5045,9 +5088,10 @@ test_config_include_recursion_after_only(void *data) } if (i > 1) { - char file_path[PATH_MAX+1]; - tor_snprintf(file_path, sizeof(file_path), "%s%d", torrc_path, i); + char *file_path = NULL; + tor_asprintf(&file_path, "%s%d", torrc_path, i); tt_int_op(write_str_to_file(file_path, file_contents, 0), OP_EQ, 0); + tor_free(file_path); } } @@ -5071,6 +5115,7 @@ test_config_include_recursion_after_only(void *data) done: config_free_lines(result); tor_free(dir); + tor_free(torrc_path); } static void @@ -5079,6 +5124,9 @@ test_config_include_folder_order(void *data) (void)data; config_line_t *result = NULL; + char *torrcd = NULL; + char *path = NULL; + char *path2 = NULL; char *dir = tor_strdup(get_fname("test_include_folder_order")); tt_ptr_op(dir, OP_NE, NULL); @@ -5088,8 +5136,7 @@ test_config_include_folder_order(void *data) tt_int_op(mkdir(dir, 0700), OP_EQ, 0); #endif - char torrcd[PATH_MAX+1]; - tor_snprintf(torrcd, sizeof(torrcd), "%s"PATH_SEPARATOR"%s", dir, "torrc.d"); + tor_asprintf(&torrcd, "%s"PATH_SEPARATOR"%s", dir, "torrc.d"); #ifdef _WIN32 tt_int_op(mkdir(torrcd), OP_EQ, 0); @@ -5098,9 +5145,7 @@ test_config_include_folder_order(void *data) #endif // test that files in subfolders are ignored - char path[PATH_MAX+1]; - tor_snprintf(path, sizeof(path), "%s"PATH_SEPARATOR"%s", torrcd, - "subfolder"); + tor_asprintf(&path, "%s"PATH_SEPARATOR"%s", torrcd, "subfolder"); #ifdef _WIN32 tt_int_op(mkdir(path), OP_EQ, 0); @@ -5108,27 +5153,31 @@ test_config_include_folder_order(void *data) tt_int_op(mkdir(path, 0700), OP_EQ, 0); #endif - char path2[PATH_MAX+1]; - tor_snprintf(path2, sizeof(path2), "%s"PATH_SEPARATOR"%s", path, - "01_ignore"); + tor_asprintf(&path2, "%s"PATH_SEPARATOR"%s", path, "01_ignore"); tt_int_op(write_str_to_file(path2, "ShouldNotSee 1\n", 0), OP_EQ, 0); + tor_free(path); // test that files starting with . are ignored - tor_snprintf(path, sizeof(path), "%s"PATH_SEPARATOR"%s", torrcd, ".dot"); + tor_asprintf(&path, "%s"PATH_SEPARATOR"%s", torrcd, ".dot"); tt_int_op(write_str_to_file(path, "ShouldNotSee 2\n", 0), OP_EQ, 0); + tor_free(path); // test file order - tor_snprintf(path, sizeof(path), "%s"PATH_SEPARATOR"%s", torrcd, "01_1st"); + tor_asprintf(&path, "%s"PATH_SEPARATOR"%s", torrcd, "01_1st"); tt_int_op(write_str_to_file(path, "Test 1\n", 0), OP_EQ, 0); + tor_free(path); - tor_snprintf(path, sizeof(path), "%s"PATH_SEPARATOR"%s", torrcd, "02_2nd"); + tor_asprintf(&path, "%s"PATH_SEPARATOR"%s", torrcd, "02_2nd"); tt_int_op(write_str_to_file(path, "Test 2\n", 0), OP_EQ, 0); + tor_free(path); - tor_snprintf(path, sizeof(path), "%s"PATH_SEPARATOR"%s", torrcd, "aa_3rd"); + tor_asprintf(&path, "%s"PATH_SEPARATOR"%s", torrcd, "aa_3rd"); tt_int_op(write_str_to_file(path, "Test 3\n", 0), OP_EQ, 0); + tor_free(path); - tor_snprintf(path, sizeof(path), "%s"PATH_SEPARATOR"%s", torrcd, "ab_4th"); + tor_asprintf(&path, "%s"PATH_SEPARATOR"%s", torrcd, "ab_4th"); tt_int_op(write_str_to_file(path, "Test 4\n", 0), OP_EQ, 0); + tor_free(path); char torrc_contents[1000]; tor_snprintf(torrc_contents, sizeof(torrc_contents), @@ -5154,6 +5203,9 @@ test_config_include_folder_order(void *data) done: config_free_lines(result); + tor_free(torrcd); + tor_free(path); + tor_free(path2); tor_free(dir); } @@ -5285,6 +5337,7 @@ test_config_include_flag_torrc_only(void *data) (void)data; char *errmsg = NULL; + char *path = NULL; char *dir = tor_strdup(get_fname("test_include_flag_torrc_only")); tt_ptr_op(dir, OP_NE, NULL); @@ -5294,8 +5347,7 @@ test_config_include_flag_torrc_only(void *data) tt_int_op(mkdir(dir, 0700), OP_EQ, 0); #endif - char path[PATH_MAX+1]; - tor_snprintf(path, sizeof(path), "%s"PATH_SEPARATOR"%s", dir, "dummy"); + tor_asprintf(&path, "%s"PATH_SEPARATOR"%s", dir, "dummy"); tt_int_op(write_str_to_file(path, "\n", 0), OP_EQ, 0); char conf_empty[1000]; @@ -5315,6 +5367,7 @@ test_config_include_flag_torrc_only(void *data) done: tor_free(errmsg); + tor_free(path); tor_free(dir); } @@ -5324,6 +5377,7 @@ test_config_include_flag_defaults_only(void *data) (void)data; char *errmsg = NULL; + char *path = NULL; char *dir = tor_strdup(get_fname("test_include_flag_defaults_only")); tt_ptr_op(dir, OP_NE, NULL); @@ -5333,8 +5387,7 @@ test_config_include_flag_defaults_only(void *data) tt_int_op(mkdir(dir, 0700), OP_EQ, 0); #endif - char path[PATH_MAX+1]; - tor_snprintf(path, sizeof(path), "%s"PATH_SEPARATOR"%s", dir, "dummy"); + tor_asprintf(&path, "%s"PATH_SEPARATOR"%s", dir, "dummy"); tt_int_op(write_str_to_file(path, "\n", 0), OP_EQ, 0); char conf_empty[1000]; @@ -5354,9 +5407,115 @@ test_config_include_flag_defaults_only(void *data) done: tor_free(errmsg); + tor_free(path); tor_free(dir); } +static void +test_config_dup_and_filter(void *arg) +{ + (void)arg; + /* Test normal input. */ + config_line_t *line = NULL; + config_line_append(&line, "abc", "def"); + config_line_append(&line, "ghi", "jkl"); + config_line_append(&line, "ABCD", "mno"); + + config_line_t *line_dup = config_lines_dup_and_filter(line, "aBc"); + tt_ptr_op(line_dup, OP_NE, NULL); + tt_ptr_op(line_dup->next, OP_NE, NULL); + tt_ptr_op(line_dup->next->next, OP_EQ, NULL); + + tt_str_op(line_dup->key, OP_EQ, "abc"); + tt_str_op(line_dup->value, OP_EQ, "def"); + tt_str_op(line_dup->next->key, OP_EQ, "ABCD"); + tt_str_op(line_dup->next->value, OP_EQ, "mno"); + + /* empty output */ + config_free_lines(line_dup); + line_dup = config_lines_dup_and_filter(line, "skdjfsdkljf"); + tt_ptr_op(line_dup, OP_EQ, NULL); + + /* empty input */ + config_free_lines(line_dup); + line_dup = config_lines_dup_and_filter(NULL, "abc"); + tt_ptr_op(line_dup, OP_EQ, NULL); + + done: + config_free_lines(line); + config_free_lines(line_dup); +} + +/* If we're not configured to be a bridge, but we set + * BridgeDistribution, then options_validate () should return -1. */ +static void +test_config_check_bridge_distribution_setting_not_a_bridge(void *arg) +{ + or_options_t* options = get_options_mutable(); + or_options_t* old_options = options; + or_options_t* default_options = options; + char* message = NULL; + int ret; + + (void)arg; + + options->BridgeRelay = 0; + options->BridgeDistribution = (char*)("https"); + + ret = options_validate(old_options, options, default_options, 0, &message); + + tt_int_op(ret, OP_EQ, -1); + tt_str_op(message, OP_EQ, "You set BridgeDistribution, but you " + "didn't set BridgeRelay!"); + done: + tor_free(message); + options->BridgeDistribution = NULL; +} + +/* If the BridgeDistribution setting was valid, 0 should be returned. */ +static void +test_config_check_bridge_distribution_setting_valid(void *arg) +{ + int ret = check_bridge_distribution_setting("https"); + + (void)arg; + + tt_int_op(ret, OP_EQ, 0); + done: + return; +} + +/* If the BridgeDistribution setting was invalid, -1 should be returned. */ +static void +test_config_check_bridge_distribution_setting_invalid(void *arg) +{ + int ret = check_bridge_distribution_setting("hyphens-are-allowed"); + + (void)arg; + + tt_int_op(ret, OP_EQ, 0); + + ret = check_bridge_distribution_setting("asterisks*are*forbidden"); + + tt_int_op(ret, OP_EQ, -1); + done: + return; +} + +/* If the BridgeDistribution setting was unrecognised, a warning should be + * logged and 0 should be returned. */ +static void +test_config_check_bridge_distribution_setting_unrecognised(void *arg) +{ + int ret = check_bridge_distribution_setting("unicorn"); + + (void)arg; + + tt_int_op(ret, OP_EQ, 0); + done: + return; +} + #define CONFIG_TEST(name, flags) \ { #name, test_config_ ## name, flags, NULL, NULL } @@ -5387,6 +5546,9 @@ struct testcase_t config_tests[] = { CONFIG_TEST(include_does_not_exist, 0), CONFIG_TEST(include_error_in_included_file, 0), CONFIG_TEST(include_empty_file_folder, 0), +#ifndef _WIN32 + CONFIG_TEST(include_no_permission, 0), +#endif CONFIG_TEST(include_recursion_before_after, 0), CONFIG_TEST(include_recursion_after_only, 0), CONFIG_TEST(include_folder_order, 0), @@ -5396,6 +5558,11 @@ struct testcase_t config_tests[] = { CONFIG_TEST(include_flag_both_without, TT_FORK), CONFIG_TEST(include_flag_torrc_only, TT_FORK), CONFIG_TEST(include_flag_defaults_only, TT_FORK), + CONFIG_TEST(dup_and_filter, 0), + CONFIG_TEST(check_bridge_distribution_setting_not_a_bridge, TT_FORK), + CONFIG_TEST(check_bridge_distribution_setting_valid, 0), + CONFIG_TEST(check_bridge_distribution_setting_invalid, 0), + CONFIG_TEST(check_bridge_distribution_setting_unrecognised, 0), END_OF_TESTCASES }; diff --git a/src/test/test_connection.c b/src/test/test_connection.c index 7e5193b203..314b90cfda 100644 --- a/src/test/test_connection.c +++ b/src/test/test_connection.c @@ -17,9 +17,8 @@ #include "rendcache.h" #include "directory.h" -static void test_conn_lookup_addr_helper(const char *address, - int family, - tor_addr_t *addr); +#include "test_connection.h" +#include "test_helpers.h" static void * test_conn_get_basic_setup(const struct testcase_t *tc); static int test_conn_get_basic_teardown(const struct testcase_t *tc, @@ -62,48 +61,7 @@ static int test_conn_get_rsrc_teardown(const struct testcase_t *tc, #define TEST_CONN_UNATTACHED_STATE (AP_CONN_STATE_CIRCUIT_WAIT) #define TEST_CONN_ATTACHED_STATE (AP_CONN_STATE_CONNECT_WAIT) -#define TEST_CONN_FD_INIT 50 -static int mock_connection_connect_sockaddr_called = 0; -static int fake_socket_number = TEST_CONN_FD_INIT; - -static int -mock_connection_connect_sockaddr(connection_t *conn, - const struct sockaddr *sa, - socklen_t sa_len, - const struct sockaddr *bindaddr, - socklen_t bindaddr_len, - int *socket_error) -{ - (void)sa_len; - (void)bindaddr; - (void)bindaddr_len; - - tor_assert(conn); - tor_assert(sa); - tor_assert(socket_error); - - mock_connection_connect_sockaddr_called++; - - conn->s = fake_socket_number++; - tt_assert(SOCKET_OK(conn->s)); - /* We really should call tor_libevent_initialize() here. Because we don't, - * we are relying on other parts of the code not checking if the_event_base - * (and therefore event->ev_base) is NULL. */ - tt_assert(connection_add_connecting(conn) == 0); - - done: - /* Fake "connected" status */ - return 1; -} - -static int -fake_close_socket(evutil_socket_t sock) -{ - (void)sock; - return 0; -} - -static void +void test_conn_lookup_addr_helper(const char *address, int family, tor_addr_t *addr) { int rv = 0; @@ -112,7 +70,7 @@ test_conn_lookup_addr_helper(const char *address, int family, tor_addr_t *addr) rv = tor_addr_lookup(address, family, addr); /* XXXX - should we retry on transient failure? */ - tt_assert(rv == 0); + tt_int_op(rv, OP_EQ, 0); tt_assert(tor_addr_is_loopback(addr)); tt_assert(tor_addr_is_v4(addr)); @@ -122,51 +80,6 @@ test_conn_lookup_addr_helper(const char *address, int family, tor_addr_t *addr) tor_addr_make_null(addr, TEST_CONN_FAMILY); } -static connection_t * -test_conn_get_connection(uint8_t state, uint8_t type, uint8_t purpose) -{ - connection_t *conn = NULL; - tor_addr_t addr; - int socket_err = 0; - int in_progress = 0; - - MOCK(connection_connect_sockaddr, - mock_connection_connect_sockaddr); - MOCK(tor_close_socket, fake_close_socket); - - init_connection_lists(); - - conn = connection_new(type, TEST_CONN_FAMILY); - tt_assert(conn); - - test_conn_lookup_addr_helper(TEST_CONN_ADDRESS, TEST_CONN_FAMILY, &addr); - tt_assert(!tor_addr_is_null(&addr)); - - tor_addr_copy_tight(&conn->addr, &addr); - conn->port = TEST_CONN_PORT; - mock_connection_connect_sockaddr_called = 0; - in_progress = connection_connect(conn, TEST_CONN_ADDRESS_PORT, &addr, - TEST_CONN_PORT, &socket_err); - tt_assert(mock_connection_connect_sockaddr_called == 1); - tt_assert(!socket_err); - tt_assert(in_progress == 0 || in_progress == 1); - - /* fake some of the attributes so the connection looks OK */ - conn->state = state; - conn->purpose = purpose; - assert_connection_ok(conn, time(NULL)); - - UNMOCK(connection_connect_sockaddr); - UNMOCK(tor_close_socket); - return conn; - - /* On failure */ - done: - UNMOCK(connection_connect_sockaddr); - UNMOCK(tor_close_socket); - return NULL; -} - static void * test_conn_get_basic_setup(const struct testcase_t *tc) { @@ -379,7 +292,7 @@ test_conn_download_status_teardown(const struct testcase_t *tc, void *arg) /* connection_free_() cleans up requested_resource */ rv = test_conn_get_rsrc_teardown(tc, conn); - tt_assert(rv == 1); + tt_int_op(rv, OP_EQ, 1); } } SMARTLIST_FOREACH_END(conn); @@ -453,12 +366,13 @@ test_conn_get_basic(void *arg) * its attributes, but get NULL when we supply a different value. */ tt_assert(connection_get_by_global_id(conn->global_identifier) == conn); - tt_assert(connection_get_by_global_id(!conn->global_identifier) == NULL); + tt_ptr_op(connection_get_by_global_id(!conn->global_identifier), OP_EQ, + NULL); tt_assert(connection_get_by_type(conn->type) == conn); tt_assert(connection_get_by_type(TEST_CONN_TYPE) == conn); - tt_assert(connection_get_by_type(!conn->type) == NULL); - tt_assert(connection_get_by_type(!TEST_CONN_TYPE) == NULL); + tt_ptr_op(connection_get_by_type(!conn->type), OP_EQ, NULL); + tt_ptr_op(connection_get_by_type(!TEST_CONN_TYPE), OP_EQ, NULL); tt_assert(connection_get_by_type_state(conn->type, conn->state) == conn); @@ -572,7 +486,7 @@ test_conn_get_rend(void *arg) #define sl_is_conn_assert(sl_input, conn) \ do { \ the_sl = (sl_input); \ - tt_assert(smartlist_len((the_sl)) == 1); \ + tt_int_op(smartlist_len((the_sl)), OP_EQ, 1); \ tt_assert(smartlist_get((the_sl), 0) == (conn)); \ smartlist_free(the_sl); the_sl = NULL; \ } while (0) @@ -580,7 +494,7 @@ test_conn_get_rend(void *arg) #define sl_no_conn_assert(sl_input) \ do { \ the_sl = (sl_input); \ - tt_assert(smartlist_len((the_sl)) == 0); \ + tt_int_op(smartlist_len((the_sl)), OP_EQ, 0); \ smartlist_free(the_sl); the_sl = NULL; \ } while (0) @@ -626,43 +540,32 @@ test_conn_get_rsrc(void *arg) TEST_CONN_RSRC_2, !TEST_CONN_STATE)); - tt_assert(connection_dir_count_by_purpose_and_resource( - conn->base_.purpose, - conn->requested_resource) - == 1); - tt_assert(connection_dir_count_by_purpose_and_resource( - TEST_CONN_RSRC_PURPOSE, - TEST_CONN_RSRC) - == 1); - tt_assert(connection_dir_count_by_purpose_and_resource( - !conn->base_.purpose, - "") - == 0); - tt_assert(connection_dir_count_by_purpose_and_resource( - !TEST_CONN_RSRC_PURPOSE, - TEST_CONN_RSRC_2) - == 0); - - tt_assert(connection_dir_count_by_purpose_resource_and_state( - conn->base_.purpose, - conn->requested_resource, - conn->base_.state) - == 1); - tt_assert(connection_dir_count_by_purpose_resource_and_state( - TEST_CONN_RSRC_PURPOSE, - TEST_CONN_RSRC, - TEST_CONN_STATE) - == 1); - tt_assert(connection_dir_count_by_purpose_resource_and_state( - !conn->base_.purpose, - "", - !conn->base_.state) - == 0); - tt_assert(connection_dir_count_by_purpose_resource_and_state( - !TEST_CONN_RSRC_PURPOSE, - TEST_CONN_RSRC_2, - !TEST_CONN_STATE) - == 0); + tt_int_op(connection_dir_count_by_purpose_and_resource( + conn->base_.purpose, conn->requested_resource), + OP_EQ, 1); + tt_int_op(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, TEST_CONN_RSRC), + OP_EQ, 1); + tt_int_op(connection_dir_count_by_purpose_and_resource( + !conn->base_.purpose, ""), + OP_EQ, 0); + tt_int_op(connection_dir_count_by_purpose_and_resource( + !TEST_CONN_RSRC_PURPOSE, TEST_CONN_RSRC_2), + OP_EQ, 0); + + tt_int_op(connection_dir_count_by_purpose_resource_and_state( + conn->base_.purpose, conn->requested_resource, + conn->base_.state), + OP_EQ, 1); + tt_int_op(connection_dir_count_by_purpose_resource_and_state( + TEST_CONN_RSRC_PURPOSE, TEST_CONN_RSRC, TEST_CONN_STATE), + OP_EQ, 1); + tt_int_op(connection_dir_count_by_purpose_resource_and_state( + !conn->base_.purpose, "", !conn->base_.state), + OP_EQ, 0); + tt_int_op(connection_dir_count_by_purpose_resource_and_state( + !TEST_CONN_RSRC_PURPOSE, TEST_CONN_RSRC_2, !TEST_CONN_STATE), + OP_EQ, 0); done: smartlist_free(the_sl); @@ -688,117 +591,127 @@ test_conn_download_status(void *arg) const char *other_res = networkstatus_get_flavor_name(other_flavor); /* no connections */ - tt_assert(networkstatus_consensus_is_already_downloading(res) == 0); - tt_assert(networkstatus_consensus_is_already_downloading(other_res) == 0); - tt_assert(connection_dir_count_by_purpose_and_resource( - TEST_CONN_RSRC_PURPOSE, - res) == 0); - tt_assert(connection_dir_count_by_purpose_and_resource( - TEST_CONN_RSRC_PURPOSE, - other_res) == 0); + tt_int_op(networkstatus_consensus_is_already_downloading(res), OP_EQ, 0); + tt_int_op(networkstatus_consensus_is_already_downloading(other_res), OP_EQ, + 0); + tt_int_op(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, res), + OP_EQ, 0); + tt_int_op(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, other_res), + OP_EQ, 0); /* one connection, not downloading */ conn = test_conn_download_status_add_a_connection(res); - tt_assert(networkstatus_consensus_is_already_downloading(res) == 0); - tt_assert(networkstatus_consensus_is_already_downloading(other_res) == 0); - tt_assert(connection_dir_count_by_purpose_and_resource( - TEST_CONN_RSRC_PURPOSE, - res) == 1); - tt_assert(connection_dir_count_by_purpose_and_resource( - TEST_CONN_RSRC_PURPOSE, - other_res) == 0); + tt_int_op(networkstatus_consensus_is_already_downloading(res), OP_EQ, 0); + tt_int_op(networkstatus_consensus_is_already_downloading(other_res), OP_EQ, + 0); + tt_int_op(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, res), + OP_EQ, 1); + tt_int_op(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, other_res), + OP_EQ, 0); /* one connection, downloading but not linked (not possible on a client, * but possible on a relay) */ conn->base_.state = TEST_CONN_DL_STATE; - tt_assert(networkstatus_consensus_is_already_downloading(res) == 0); - tt_assert(networkstatus_consensus_is_already_downloading(other_res) == 0); - tt_assert(connection_dir_count_by_purpose_and_resource( - TEST_CONN_RSRC_PURPOSE, - res) == 1); - tt_assert(connection_dir_count_by_purpose_and_resource( - TEST_CONN_RSRC_PURPOSE, - other_res) == 0); + tt_int_op(networkstatus_consensus_is_already_downloading(res), OP_EQ, 0); + tt_int_op(networkstatus_consensus_is_already_downloading(other_res), OP_EQ, + 0); + tt_int_op(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, res), + OP_EQ, 1); + tt_int_op(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, other_res), + OP_EQ, 0); /* one connection, downloading and linked, but not yet attached */ ap_conn = test_conn_get_linked_connection(TO_CONN(conn), TEST_CONN_UNATTACHED_STATE); - tt_assert(networkstatus_consensus_is_already_downloading(res) == 0); - tt_assert(networkstatus_consensus_is_already_downloading(other_res) == 0); - tt_assert(connection_dir_count_by_purpose_and_resource( - TEST_CONN_RSRC_PURPOSE, - res) == 1); - tt_assert(connection_dir_count_by_purpose_and_resource( - TEST_CONN_RSRC_PURPOSE, - other_res) == 0); + tt_int_op(networkstatus_consensus_is_already_downloading(res), OP_EQ, 0); + tt_int_op(networkstatus_consensus_is_already_downloading(other_res), OP_EQ, + 0); + tt_int_op(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, res), + OP_EQ, 1); + tt_int_op(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, other_res), + OP_EQ, 0); /* one connection, downloading and linked and attached */ ap_conn->state = TEST_CONN_ATTACHED_STATE; - tt_assert(networkstatus_consensus_is_already_downloading(res) == 1); - tt_assert(networkstatus_consensus_is_already_downloading(other_res) == 0); - tt_assert(connection_dir_count_by_purpose_and_resource( - TEST_CONN_RSRC_PURPOSE, - res) == 1); - tt_assert(connection_dir_count_by_purpose_and_resource( - TEST_CONN_RSRC_PURPOSE, - other_res) == 0); + tt_int_op(networkstatus_consensus_is_already_downloading(res), OP_EQ, 1); + tt_int_op(networkstatus_consensus_is_already_downloading(other_res), OP_EQ, + 0); + tt_int_op(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, res), + OP_EQ, 1); + tt_int_op(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, other_res), + OP_EQ, 0); /* one connection, linked and attached but not downloading */ conn->base_.state = TEST_CONN_STATE; - tt_assert(networkstatus_consensus_is_already_downloading(res) == 0); - tt_assert(networkstatus_consensus_is_already_downloading(other_res) == 0); - tt_assert(connection_dir_count_by_purpose_and_resource( - TEST_CONN_RSRC_PURPOSE, - res) == 1); - tt_assert(connection_dir_count_by_purpose_and_resource( - TEST_CONN_RSRC_PURPOSE, - other_res) == 0); + tt_int_op(networkstatus_consensus_is_already_downloading(res), OP_EQ, 0); + tt_int_op(networkstatus_consensus_is_already_downloading(other_res), OP_EQ, + 0); + tt_int_op(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, res), + OP_EQ, 1); + tt_int_op(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, other_res), + OP_EQ, 0); /* two connections, both not downloading */ conn2 = test_conn_download_status_add_a_connection(res); - tt_assert(networkstatus_consensus_is_already_downloading(res) == 0); - tt_assert(networkstatus_consensus_is_already_downloading(other_res) == 0); - tt_assert(connection_dir_count_by_purpose_and_resource( - TEST_CONN_RSRC_PURPOSE, - res) == 2); - tt_assert(connection_dir_count_by_purpose_and_resource( - TEST_CONN_RSRC_PURPOSE, - other_res) == 0); + tt_int_op(networkstatus_consensus_is_already_downloading(res), OP_EQ, 0); + tt_int_op(networkstatus_consensus_is_already_downloading(other_res), OP_EQ, + 0); + tt_int_op(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, res), + OP_EQ, 2); + tt_int_op(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, other_res), + OP_EQ, 0); /* two connections, one downloading */ conn->base_.state = TEST_CONN_DL_STATE; - tt_assert(networkstatus_consensus_is_already_downloading(res) == 1); - tt_assert(networkstatus_consensus_is_already_downloading(other_res) == 0); - tt_assert(connection_dir_count_by_purpose_and_resource( - TEST_CONN_RSRC_PURPOSE, - res) == 2); - tt_assert(connection_dir_count_by_purpose_and_resource( - TEST_CONN_RSRC_PURPOSE, - other_res) == 0); + tt_int_op(networkstatus_consensus_is_already_downloading(res), OP_EQ, 1); + tt_int_op(networkstatus_consensus_is_already_downloading(other_res), OP_EQ, + 0); + tt_int_op(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, res), + OP_EQ, 2); + tt_int_op(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, other_res), + OP_EQ, 0); conn->base_.state = TEST_CONN_STATE; /* more connections, all not downloading */ /* ignore the return value, it's free'd using the connection list */ (void)test_conn_download_status_add_a_connection(res); - tt_assert(networkstatus_consensus_is_already_downloading(res) == 0); - tt_assert(networkstatus_consensus_is_already_downloading(other_res) == 0); - tt_assert(connection_dir_count_by_purpose_and_resource( - TEST_CONN_RSRC_PURPOSE, - res) == 3); - tt_assert(connection_dir_count_by_purpose_and_resource( - TEST_CONN_RSRC_PURPOSE, - other_res) == 0); + tt_int_op(networkstatus_consensus_is_already_downloading(res), OP_EQ, 0); + tt_int_op(networkstatus_consensus_is_already_downloading(other_res), OP_EQ, + 0); + tt_int_op(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, res), + OP_EQ, 3); + tt_int_op(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, other_res), + OP_EQ, 0); /* more connections, one downloading */ conn->base_.state = TEST_CONN_DL_STATE; - tt_assert(networkstatus_consensus_is_already_downloading(res) == 1); - tt_assert(networkstatus_consensus_is_already_downloading(other_res) == 0); - tt_assert(connection_dir_count_by_purpose_and_resource( - TEST_CONN_RSRC_PURPOSE, - res) == 3); - tt_assert(connection_dir_count_by_purpose_and_resource( - TEST_CONN_RSRC_PURPOSE, - other_res) == 0); + tt_int_op(networkstatus_consensus_is_already_downloading(res), OP_EQ, 1); + tt_int_op(networkstatus_consensus_is_already_downloading(other_res), OP_EQ, + 0); + tt_int_op(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, res), + OP_EQ, 3); + tt_int_op(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, other_res), + OP_EQ, 0); /* more connections, two downloading (should never happen, but needs * to be tested for completeness) */ @@ -806,38 +719,41 @@ test_conn_download_status(void *arg) /* ignore the return value, it's free'd using the connection list */ (void)test_conn_get_linked_connection(TO_CONN(conn2), TEST_CONN_ATTACHED_STATE); - tt_assert(networkstatus_consensus_is_already_downloading(res) == 1); - tt_assert(networkstatus_consensus_is_already_downloading(other_res) == 0); - tt_assert(connection_dir_count_by_purpose_and_resource( - TEST_CONN_RSRC_PURPOSE, - res) == 3); - tt_assert(connection_dir_count_by_purpose_and_resource( - TEST_CONN_RSRC_PURPOSE, - other_res) == 0); + tt_int_op(networkstatus_consensus_is_already_downloading(res), OP_EQ, 1); + tt_int_op(networkstatus_consensus_is_already_downloading(other_res), OP_EQ, + 0); + tt_int_op(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, res), + OP_EQ, 3); + tt_int_op(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, other_res), + OP_EQ, 0); conn->base_.state = TEST_CONN_STATE; /* more connections, a different one downloading */ - tt_assert(networkstatus_consensus_is_already_downloading(res) == 1); - tt_assert(networkstatus_consensus_is_already_downloading(other_res) == 0); - tt_assert(connection_dir_count_by_purpose_and_resource( - TEST_CONN_RSRC_PURPOSE, - res) == 3); - tt_assert(connection_dir_count_by_purpose_and_resource( - TEST_CONN_RSRC_PURPOSE, - other_res) == 0); + tt_int_op(networkstatus_consensus_is_already_downloading(res), OP_EQ, 1); + tt_int_op(networkstatus_consensus_is_already_downloading(other_res), OP_EQ, + 0); + tt_int_op(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, res), + OP_EQ, 3); + tt_int_op(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, other_res), + OP_EQ, 0); /* a connection for the other flavor (could happen if a client is set to * cache directory documents), one preferred flavor downloading */ conn4 = test_conn_download_status_add_a_connection(other_res); - tt_assert(networkstatus_consensus_is_already_downloading(res) == 1); - tt_assert(networkstatus_consensus_is_already_downloading(other_res) == 0); - tt_assert(connection_dir_count_by_purpose_and_resource( - TEST_CONN_RSRC_PURPOSE, - res) == 3); - tt_assert(connection_dir_count_by_purpose_and_resource( - TEST_CONN_RSRC_PURPOSE, - other_res) == 1); + tt_int_op(networkstatus_consensus_is_already_downloading(res), OP_EQ, 1); + tt_int_op(networkstatus_consensus_is_already_downloading(other_res), OP_EQ, + 0); + tt_int_op(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, res), + OP_EQ, 3); + tt_int_op(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, other_res), + OP_EQ, 1); /* a connection for the other flavor (could happen if a client is set to * cache directory documents), both flavors downloading @@ -846,14 +762,15 @@ test_conn_download_status(void *arg) /* ignore the return value, it's free'd using the connection list */ (void)test_conn_get_linked_connection(TO_CONN(conn4), TEST_CONN_ATTACHED_STATE); - tt_assert(networkstatus_consensus_is_already_downloading(res) == 1); - tt_assert(networkstatus_consensus_is_already_downloading(other_res) == 1); - tt_assert(connection_dir_count_by_purpose_and_resource( - TEST_CONN_RSRC_PURPOSE, - res) == 3); - tt_assert(connection_dir_count_by_purpose_and_resource( - TEST_CONN_RSRC_PURPOSE, - other_res) == 1); + tt_int_op(networkstatus_consensus_is_already_downloading(res), OP_EQ, 1); + tt_int_op(networkstatus_consensus_is_already_downloading(other_res), OP_EQ, + 1); + tt_int_op(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, res), + OP_EQ, 3); + tt_int_op(connection_dir_count_by_purpose_and_resource( + TEST_CONN_RSRC_PURPOSE, other_res), + OP_EQ, 1); done: /* the teardown function removes all the connections in the global list*/; diff --git a/src/test/test_connection.h b/src/test/test_connection.h new file mode 100644 index 0000000000..392783b53b --- /dev/null +++ b/src/test/test_connection.h @@ -0,0 +1,13 @@ +/* Copyright (c) 2014-2017, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** Some constants used by test_connection and helpers */ +#define TEST_CONN_FAMILY (AF_INET) +#define TEST_CONN_ADDRESS "127.0.0.1" +#define TEST_CONN_PORT (12345) +#define TEST_CONN_ADDRESS_PORT "127.0.0.1:12345" +#define TEST_CONN_FD_INIT 50 + +void test_conn_lookup_addr_helper(const char *address, + int family, tor_addr_t *addr); + diff --git a/src/test/test_conscache.c b/src/test/test_conscache.c index aee1ba8a06..ddb1bc53c1 100644 --- a/src/test/test_conscache.c +++ b/src/test/test_conscache.c @@ -200,7 +200,7 @@ test_conscache_cleanup(void *arg) tt_assert(e_tmp); tt_assert(consensus_cache_entry_is_mapped(e_tmp)); e_tmp = consensus_cache_find_first(cache, "index", "7"); - tt_assert(e_tmp == NULL); // not found because pending deletion. + tt_ptr_op(e_tmp, OP_EQ, NULL); // not found because pending deletion. /* Delete the pending-deletion items. */ consensus_cache_delete_pending(cache, 0); @@ -212,9 +212,9 @@ test_conscache_cleanup(void *arg) tt_int_op(n, OP_EQ, 20 - 2); /* 1 entry was deleted; 1 is not-found. */ } e_tmp = consensus_cache_find_first(cache, "index", "7"); // refcnt == 1... - tt_assert(e_tmp == NULL); // so deleted. + tt_ptr_op(e_tmp, OP_EQ, NULL); // so deleted. e_tmp = consensus_cache_find_first(cache, "index", "14"); // refcnt == 2 - tt_assert(e_tmp == NULL); // not deleted; but not found. + tt_ptr_op(e_tmp, OP_EQ, NULL); // not deleted; but not found. /* Now do lazy unmapping. */ // should do nothing. diff --git a/src/test/test_consdiff.c b/src/test/test_consdiff.c index 7cf8d6ba2b..fda3a7f186 100644 --- a/src/test/test_consdiff.c +++ b/src/test/test_consdiff.c @@ -19,28 +19,29 @@ test_consdiff_smartlist_slice(void *arg) { smartlist_t *sl = smartlist_new(); smartlist_slice_t *sls; + int items[6] = {0,0,0,0,0,0}; /* Create a regular smartlist. */ (void)arg; - smartlist_add(sl, (void*)1); - smartlist_add(sl, (void*)2); - smartlist_add(sl, (void*)3); - smartlist_add(sl, (void*)4); - smartlist_add(sl, (void*)5); + smartlist_add(sl, &items[1]); + smartlist_add(sl, &items[2]); + smartlist_add(sl, &items[3]); + smartlist_add(sl, &items[4]); + smartlist_add(sl, &items[5]); /* See if the slice was done correctly. */ sls = smartlist_slice(sl, 2, 5); tt_ptr_op(sl, OP_EQ, sls->list); - tt_ptr_op((void*)3, OP_EQ, smartlist_get(sls->list, sls->offset)); - tt_ptr_op((void*)5, OP_EQ, + tt_ptr_op(&items[3], OP_EQ, smartlist_get(sls->list, sls->offset)); + tt_ptr_op(&items[5], OP_EQ, smartlist_get(sls->list, sls->offset + (sls->len-1))); tor_free(sls); /* See that using -1 as the end does get to the last element. */ sls = smartlist_slice(sl, 2, -1); tt_ptr_op(sl, OP_EQ, sls->list); - tt_ptr_op((void*)3, OP_EQ, smartlist_get(sls->list, sls->offset)); - tt_ptr_op((void*)5, OP_EQ, + tt_ptr_op(&items[3], OP_EQ, smartlist_get(sls->list, sls->offset)); + tt_ptr_op(&items[5], OP_EQ, smartlist_get(sls->list, sls->offset + (sls->len-1))); done: @@ -1107,7 +1108,7 @@ test_consdiff_apply_diff(void *arg) tt_ptr_op(NULL, OP_EQ, cons2); expect_log_msg_containing("Could not compute digests of the consensus " "resulting from applying a consensus diff."); -#endif +#endif /* 0 */ /* Very simple test, only to see that nothing errors. */ smartlist_clear(diff); diff --git a/src/test/test_consdiffmgr.c b/src/test/test_consdiffmgr.c index 963a6e427a..80d3f943ab 100644 --- a/src/test/test_consdiffmgr.c +++ b/src/test/test_consdiffmgr.c @@ -230,7 +230,7 @@ test_consdiffmgr_init_failure(void *arg) done: tor_end_capture_bugs_(); } -#endif +#endif /* 0 */ static void test_consdiffmgr_sha3_helper(void *arg) @@ -325,8 +325,8 @@ test_consdiffmgr_add(void *arg) tt_mem_op(body, OP_EQ, "quux", 4); /* Try looking up another entry, but fail */ - tt_assert(NULL == cdm_cache_lookup_consensus(FLAV_MICRODESC, now-60)); - tt_assert(NULL == cdm_cache_lookup_consensus(FLAV_NS, now-61)); + tt_ptr_op(cdm_cache_lookup_consensus(FLAV_MICRODESC, now - 60), OP_EQ, NULL); + tt_ptr_op(cdm_cache_lookup_consensus(FLAV_NS, now - 61), OP_EQ, NULL); done: networkstatus_vote_free(ns_tmp); diff --git a/src/test/test_containers.c b/src/test/test_containers.c index 54484a2a91..c4dba73750 100644 --- a/src/test/test_containers.c +++ b/src/test/test_containers.c @@ -510,22 +510,22 @@ test_container_smartlist_pos(void *arg) smartlist_add_strdup(sl, "function"); /* Test string_pos */ - tt_int_op(smartlist_string_pos(NULL, "Fred"), ==, -1); - tt_int_op(smartlist_string_pos(sl, "Fred"), ==, -1); - tt_int_op(smartlist_string_pos(sl, "This"), ==, 0); - tt_int_op(smartlist_string_pos(sl, "a"), ==, 2); - tt_int_op(smartlist_string_pos(sl, "function"), ==, 6); + tt_int_op(smartlist_string_pos(NULL, "Fred"), OP_EQ, -1); + tt_int_op(smartlist_string_pos(sl, "Fred"), OP_EQ, -1); + tt_int_op(smartlist_string_pos(sl, "This"), OP_EQ, 0); + tt_int_op(smartlist_string_pos(sl, "a"), OP_EQ, 2); + tt_int_op(smartlist_string_pos(sl, "function"), OP_EQ, 6); /* Test pos */ - tt_int_op(smartlist_pos(NULL, "Fred"), ==, -1); - tt_int_op(smartlist_pos(sl, "Fred"), ==, -1); - tt_int_op(smartlist_pos(sl, "This"), ==, -1); - tt_int_op(smartlist_pos(sl, "a"), ==, -1); - tt_int_op(smartlist_pos(sl, "function"), ==, -1); - tt_int_op(smartlist_pos(sl, smartlist_get(sl,0)), ==, 0); - tt_int_op(smartlist_pos(sl, smartlist_get(sl,2)), ==, 2); - tt_int_op(smartlist_pos(sl, smartlist_get(sl,5)), ==, 5); - tt_int_op(smartlist_pos(sl, smartlist_get(sl,6)), ==, 6); + tt_int_op(smartlist_pos(NULL, "Fred"), OP_EQ, -1); + tt_int_op(smartlist_pos(sl, "Fred"), OP_EQ, -1); + tt_int_op(smartlist_pos(sl, "This"), OP_EQ, -1); + tt_int_op(smartlist_pos(sl, "a"), OP_EQ, -1); + tt_int_op(smartlist_pos(sl, "function"), OP_EQ, -1); + tt_int_op(smartlist_pos(sl, smartlist_get(sl,0)), OP_EQ, 0); + tt_int_op(smartlist_pos(sl, smartlist_get(sl,2)), OP_EQ, 2); + tt_int_op(smartlist_pos(sl, smartlist_get(sl,5)), OP_EQ, 5); + tt_int_op(smartlist_pos(sl, smartlist_get(sl,6)), OP_EQ, 6); done: SMARTLIST_FOREACH(sl, char *, str, tor_free(str)); @@ -681,7 +681,7 @@ test_container_pqueue(void *arg) { smartlist_t *sl = smartlist_new(); int (*cmp)(const void *, const void*); - const int offset = STRUCT_OFFSET(pq_entry_t, idx); + const int offset = offsetof(pq_entry_t, idx); #define ENTRY(s) pq_entry_t s = { #s, -1 } ENTRY(cows); ENTRY(zebras); @@ -990,13 +990,13 @@ test_container_order_functions(void *arg) tt_assert(15 == median_time(times, 5)); int32_t int32s[] = { -5, -10, -50, 100 }; - tt_int_op(-5, ==, median_int32(int32s, 1)); - tt_int_op(-10, ==, median_int32(int32s, 2)); - tt_int_op(-10, ==, median_int32(int32s, 3)); - tt_int_op(-10, ==, median_int32(int32s, 4)); + tt_int_op(-5, OP_EQ, median_int32(int32s, 1)); + tt_int_op(-10, OP_EQ, median_int32(int32s, 2)); + tt_int_op(-10, OP_EQ, median_int32(int32s, 3)); + tt_int_op(-10, OP_EQ, median_int32(int32s, 4)); long longs[] = { -30, 30, 100, -100, 7 }; - tt_int_op(7, ==, find_nth_long(longs, 5, 2)); + tt_int_op(7, OP_EQ, find_nth_long(longs, 5, 2)); done: ; @@ -1106,7 +1106,7 @@ test_container_fp_pair_map(void *arg) tt_int_op(fp_pair_map_size(map),OP_EQ, 4); fp_pair_map_assert_ok(map); fp_pair_map_set(map, &fp5, v104); - fp_pair_map_set(map, &fp6, v105); + fp_pair_map_set_by_digests(map, fp6.first, fp6.second, v105); fp_pair_map_assert_ok(map); /* Test iterator. */ @@ -1124,7 +1124,8 @@ test_container_fp_pair_map(void *arg) /* Make sure we removed fp2, but not the others. */ tt_ptr_op(fp_pair_map_get(map, &fp2),OP_EQ, NULL); - tt_ptr_op(fp_pair_map_get(map, &fp5),OP_EQ, v104); + tt_ptr_op(fp_pair_map_get_by_digests(map, fp5.first, fp5.second), + OP_EQ, v104); fp_pair_map_assert_ok(map); /* Clean up after ourselves. */ @@ -1153,31 +1154,31 @@ test_container_smartlist_most_frequent(void *arg) const char *cp; cp = smartlist_get_most_frequent_string_(sl, &count); - tt_int_op(count, ==, 0); - tt_ptr_op(cp, ==, NULL); + tt_int_op(count, OP_EQ, 0); + tt_ptr_op(cp, OP_EQ, NULL); /* String must be sorted before we call get_most_frequent */ smartlist_split_string(sl, "abc:def:ghi", ":", 0, 0); cp = smartlist_get_most_frequent_string_(sl, &count); - tt_int_op(count, ==, 1); - tt_str_op(cp, ==, "ghi"); /* Ties broken in favor of later element */ + tt_int_op(count, OP_EQ, 1); + tt_str_op(cp, OP_EQ, "ghi"); /* Ties broken in favor of later element */ smartlist_split_string(sl, "def:ghi", ":", 0, 0); smartlist_sort_strings(sl); cp = smartlist_get_most_frequent_string_(sl, &count); - tt_int_op(count, ==, 2); - tt_ptr_op(cp, !=, NULL); - tt_str_op(cp, ==, "ghi"); /* Ties broken in favor of later element */ + tt_int_op(count, OP_EQ, 2); + tt_ptr_op(cp, OP_NE, NULL); + tt_str_op(cp, OP_EQ, "ghi"); /* Ties broken in favor of later element */ smartlist_split_string(sl, "def:abc:qwop", ":", 0, 0); smartlist_sort_strings(sl); cp = smartlist_get_most_frequent_string_(sl, &count); - tt_int_op(count, ==, 3); - tt_ptr_op(cp, !=, NULL); - tt_str_op(cp, ==, "def"); /* No tie */ + tt_int_op(count, OP_EQ, 3); + tt_ptr_op(cp, OP_NE, NULL); + tt_str_op(cp, OP_EQ, "def"); /* No tie */ done: SMARTLIST_FOREACH(sl, char *, str, tor_free(str)); @@ -1206,7 +1207,7 @@ test_container_smartlist_sort_ptrs(void *arg) smartlist_shuffle(sl); smartlist_sort_pointers(sl); for (j = 0; j < ARRAY_LENGTH(arrayptrs); ++j) { - tt_ptr_op(smartlist_get(sl, j), ==, arrayptrs[j]); + tt_ptr_op(smartlist_get(sl, j), OP_EQ, arrayptrs[j]); } } @@ -1232,11 +1233,11 @@ test_container_smartlist_strings_eq(void *arg) } while (0) /* Both NULL, so equal */ - tt_int_op(1, ==, smartlist_strings_eq(NULL, NULL)); + tt_int_op(1, OP_EQ, smartlist_strings_eq(NULL, NULL)); /* One NULL, not equal. */ - tt_int_op(0, ==, smartlist_strings_eq(NULL, sl1)); - tt_int_op(0, ==, smartlist_strings_eq(sl1, NULL)); + tt_int_op(0, OP_EQ, smartlist_strings_eq(NULL, sl1)); + tt_int_op(0, OP_EQ, smartlist_strings_eq(sl1, NULL)); /* Both empty, both equal. */ EQ_SHOULD_SAY("", "", 1); diff --git a/src/test/test_controller.c b/src/test/test_controller.c index 592f91a988..472fcb8c53 100644 --- a/src/test/test_controller.c +++ b/src/test/test_controller.c @@ -31,7 +31,7 @@ test_add_onion_helper_keyarg(void *arg) tt_assert(pk); tt_str_op(key_new_alg, OP_EQ, "RSA1024"); tt_assert(key_new_blob); - tt_assert(!err_msg); + tt_ptr_op(err_msg, OP_EQ, NULL); /* Test "BEST" key generation (Assumes BEST = RSA1024). */ crypto_pk_free(pk); @@ -41,7 +41,7 @@ test_add_onion_helper_keyarg(void *arg) tt_assert(pk); tt_str_op(key_new_alg, OP_EQ, "RSA1024"); tt_assert(key_new_blob); - tt_assert(!err_msg); + tt_ptr_op(err_msg, OP_EQ, NULL); /* Test discarding the private key. */ crypto_pk_free(pk); @@ -49,17 +49,17 @@ test_add_onion_helper_keyarg(void *arg) pk = add_onion_helper_keyarg("NEW:BEST", 1, &key_new_alg, &key_new_blob, &err_msg); tt_assert(pk); - tt_assert(!key_new_alg); - tt_assert(!key_new_blob); - tt_assert(!err_msg); + tt_ptr_op(key_new_alg, OP_EQ, NULL); + tt_ptr_op(key_new_blob, OP_EQ, NULL); + tt_ptr_op(err_msg, OP_EQ, NULL); /* Test generating a invalid key type. */ crypto_pk_free(pk); pk = add_onion_helper_keyarg("NEW:RSA512", 0, &key_new_alg, &key_new_blob, &err_msg); - tt_assert(!pk); - tt_assert(!key_new_alg); - tt_assert(!key_new_blob); + tt_ptr_op(pk, OP_EQ, NULL); + tt_ptr_op(key_new_alg, OP_EQ, NULL); + tt_ptr_op(key_new_blob, OP_EQ, NULL); tt_assert(err_msg); /* Test loading a RSA1024 key. */ @@ -70,10 +70,10 @@ test_add_onion_helper_keyarg(void *arg) pk2 = add_onion_helper_keyarg(arg_str, 0, &key_new_alg, &key_new_blob, &err_msg); tt_assert(pk2); - tt_assert(!key_new_alg); - tt_assert(!key_new_blob); - tt_assert(!err_msg); - tt_assert(crypto_pk_cmp_keys(pk, pk2) == 0); + tt_ptr_op(key_new_alg, OP_EQ, NULL); + tt_ptr_op(key_new_blob, OP_EQ, NULL); + tt_ptr_op(err_msg, OP_EQ, NULL); + tt_int_op(crypto_pk_cmp_keys(pk, pk2), OP_EQ, 0); /* Test loading a invalid key type. */ tor_free(arg_str); @@ -81,9 +81,9 @@ test_add_onion_helper_keyarg(void *arg) tor_asprintf(&arg_str, "RSA512:%s", encoded); pk = add_onion_helper_keyarg(arg_str, 0, &key_new_alg, &key_new_blob, &err_msg); - tt_assert(!pk); - tt_assert(!key_new_alg); - tt_assert(!key_new_blob); + tt_ptr_op(pk, OP_EQ, NULL); + tt_ptr_op(key_new_alg, OP_EQ, NULL); + tt_ptr_op(key_new_blob, OP_EQ, NULL); tt_assert(err_msg); /* Test loading a invalid key. */ @@ -94,9 +94,9 @@ test_add_onion_helper_keyarg(void *arg) tor_asprintf(&arg_str, "RSA1024:%s", encoded); pk = add_onion_helper_keyarg(arg_str, 0, &key_new_alg, &key_new_blob, &err_msg); - tt_assert(!pk); - tt_assert(!key_new_alg); - tt_assert(!key_new_blob); + tt_ptr_op(pk, OP_EQ, NULL); + tt_ptr_op(key_new_alg, OP_EQ, NULL); + tt_ptr_op(key_new_blob, OP_EQ, NULL); tt_assert(err_msg); done: @@ -123,13 +123,13 @@ test_getinfo_helper_onion(void *arg) /* successfully get an empty answer */ rt = getinfo_helper_onions(&dummy, "onions/current", &answer, &errmsg); - tt_assert(rt == 0); + tt_int_op(rt, OP_EQ, 0); tt_str_op(answer, OP_EQ, ""); tor_free(answer); /* successfully get an empty answer */ rt = getinfo_helper_onions(&dummy, "onions/detached", &answer, &errmsg); - tt_assert(rt == 0); + tt_int_op(rt, OP_EQ, 0); tt_str_op(answer, OP_EQ, ""); tor_free(answer); @@ -138,7 +138,7 @@ test_getinfo_helper_onion(void *arg) dummy.ephemeral_onion_services = smartlist_new(); smartlist_add(dummy.ephemeral_onion_services, service_id); rt = getinfo_helper_onions(&dummy, "onions/current", &answer, &errmsg); - tt_assert(rt == 0); + tt_int_op(rt, OP_EQ, 0); tt_str_op(answer, OP_EQ, "dummy_onion_id"); done: @@ -159,25 +159,25 @@ test_rend_service_parse_port_config(void *arg) /* Test "VIRTPORT" only. */ cfg = rend_service_parse_port_config("80", sep, &err_msg); tt_assert(cfg); - tt_assert(!err_msg); + tt_ptr_op(err_msg, OP_EQ, NULL); /* Test "VIRTPORT,TARGET" (Target is port). */ rend_service_port_config_free(cfg); cfg = rend_service_parse_port_config("80,8080", sep, &err_msg); tt_assert(cfg); - tt_assert(!err_msg); + tt_ptr_op(err_msg, OP_EQ, NULL); /* Test "VIRTPORT,TARGET" (Target is IPv4:port). */ rend_service_port_config_free(cfg); cfg = rend_service_parse_port_config("80,192.0.2.1:8080", sep, &err_msg); tt_assert(cfg); - tt_assert(!err_msg); + tt_ptr_op(err_msg, OP_EQ, NULL); /* Test "VIRTPORT,TARGET" (Target is IPv6:port). */ rend_service_port_config_free(cfg); cfg = rend_service_parse_port_config("80,[2001:db8::1]:8080", sep, &err_msg); tt_assert(cfg); - tt_assert(!err_msg); + tt_ptr_op(err_msg, OP_EQ, NULL); rend_service_port_config_free(cfg); cfg = NULL; @@ -186,13 +186,13 @@ test_rend_service_parse_port_config(void *arg) /* Test empty config. */ rend_service_port_config_free(cfg); cfg = rend_service_parse_port_config("", sep, &err_msg); - tt_assert(!cfg); + tt_ptr_op(cfg, OP_EQ, NULL); tt_assert(err_msg); /* Test invalid port. */ tor_free(err_msg); cfg = rend_service_parse_port_config("90001", sep, &err_msg); - tt_assert(!cfg); + tt_ptr_op(cfg, OP_EQ, NULL); tt_assert(err_msg); tor_free(err_msg); @@ -204,7 +204,7 @@ test_rend_service_parse_port_config(void *arg) cfg = rend_service_parse_port_config("100 unix:\"/tmp/foo bar\"", " ", &err_msg); tt_assert(cfg); - tt_assert(!err_msg); + tt_ptr_op(err_msg, OP_EQ, NULL); rend_service_port_config_free(cfg); cfg = NULL; @@ -213,14 +213,14 @@ test_rend_service_parse_port_config(void *arg) cfg = rend_service_parse_port_config("100 unix:\"/tmp/foo bar\"", " ", &err_msg); tt_assert(cfg); - tt_assert(!err_msg); + tt_ptr_op(err_msg, OP_EQ, NULL); rend_service_port_config_free(cfg); cfg = NULL; /* quoted unix port, missing end quote */ cfg = rend_service_parse_port_config("100 unix:\"/tmp/foo bar", " ", &err_msg); - tt_assert(!cfg); + tt_ptr_op(cfg, OP_EQ, NULL); tt_str_op(err_msg, OP_EQ, "Couldn't process address <unix:\"/tmp/foo bar> " "from hidden service configuration"); tor_free(err_msg); @@ -230,7 +230,7 @@ test_rend_service_parse_port_config(void *arg) cfg = rend_service_parse_port_config("100 foo!!.example.com:9000", " ", &err_msg); UNMOCK(tor_addr_lookup); - tt_assert(!cfg); + tt_ptr_op(cfg, OP_EQ, NULL); tt_str_op(err_msg, OP_EQ, "Unparseable address in hidden service port " "configuration."); tor_free(err_msg); @@ -238,7 +238,7 @@ test_rend_service_parse_port_config(void *arg) /* bogus port port */ cfg = rend_service_parse_port_config("100 99999", " ", &err_msg); - tt_assert(!cfg); + tt_ptr_op(cfg, OP_EQ, NULL); tt_str_op(err_msg, OP_EQ, "Unparseable or out-of-range port \"99999\" " "in hidden service port configuration."); tor_free(err_msg); @@ -261,7 +261,7 @@ test_add_onion_helper_clientauth(void *arg) client = add_onion_helper_clientauth("alice", &created, &err_msg); tt_assert(client); tt_assert(created); - tt_assert(!err_msg); + tt_ptr_op(err_msg, OP_EQ, NULL); rend_authorized_client_free(client); /* Test "ClientName:Blob" */ @@ -269,26 +269,26 @@ test_add_onion_helper_clientauth(void *arg) &created, &err_msg); tt_assert(client); tt_assert(!created); - tt_assert(!err_msg); + tt_ptr_op(err_msg, OP_EQ, NULL); rend_authorized_client_free(client); /* Test invalid client names */ client = add_onion_helper_clientauth("no*asterisks*allowed", &created, &err_msg); - tt_assert(!client); + tt_ptr_op(client, OP_EQ, NULL); tt_assert(err_msg); tor_free(err_msg); /* Test invalid auth cookie */ client = add_onion_helper_clientauth("alice:12345", &created, &err_msg); - tt_assert(!client); + tt_ptr_op(client, OP_EQ, NULL); tt_assert(err_msg); tor_free(err_msg); /* Test invalid syntax */ client = add_onion_helper_clientauth(":475hGBHPlq7Mc0cRZitK/B", &created, &err_msg); - tt_assert(!client); + tt_ptr_op(client, OP_EQ, NULL); tt_assert(err_msg); tor_free(err_msg); @@ -544,7 +544,7 @@ cert_dl_status_def_for_auth_mock(const char *digest) download_status_t *dl = NULL; char digest_str[HEX_DIGEST_LEN+1]; - tt_assert(digest != NULL); + tt_ptr_op(digest, OP_NE, NULL); base16_encode(digest_str, HEX_DIGEST_LEN + 1, digest, DIGEST_LEN); digest_str[HEX_DIGEST_LEN] = '\0'; @@ -568,7 +568,7 @@ cert_dl_status_sks_for_auth_id_mock(const char *digest) char *tmp; int len; - tt_assert(digest != NULL); + tt_ptr_op(digest, OP_NE, NULL); base16_encode(digest_str, HEX_DIGEST_LEN + 1, digest, DIGEST_LEN); digest_str[HEX_DIGEST_LEN] = '\0'; @@ -622,11 +622,11 @@ cert_dl_status_fp_sk_mock(const char *fp_digest, const char *sk_digest) * dl status we want. */ - tt_assert(fp_digest != NULL); + tt_ptr_op(fp_digest, OP_NE, NULL); base16_encode(fp_digest_str, HEX_DIGEST_LEN + 1, fp_digest, DIGEST_LEN); fp_digest_str[HEX_DIGEST_LEN] = '\0'; - tt_assert(sk_digest != NULL); + tt_ptr_op(sk_digest, OP_NE, NULL); base16_encode(sk_digest_str, HEX_DIGEST_LEN + 1, sk_digest, DIGEST_LEN); sk_digest_str[HEX_DIGEST_LEN] = '\0'; @@ -706,7 +706,7 @@ descbr_get_dl_by_digest_mock(const char *digest) char digest_str[HEX_DIGEST_LEN+1]; if (!disable_descbr) { - tt_assert(digest != NULL); + tt_ptr_op(digest, OP_NE, NULL); base16_encode(digest_str, HEX_DIGEST_LEN + 1, digest, DIGEST_LEN); digest_str[HEX_DIGEST_LEN] = '\0'; @@ -773,7 +773,7 @@ test_download_status_consensus(void *arg) /* Check that the unknown prefix case works; no mocks needed yet */ getinfo_helper_downloads(&dummy, "downloads/foo", &answer, &errmsg); - tt_assert(answer == NULL); + tt_ptr_op(answer, OP_EQ, NULL); tt_str_op(errmsg, OP_EQ, "Unknown download status query"); setup_ns_mocks(); @@ -788,8 +788,8 @@ test_download_status_consensus(void *arg) sizeof(download_status_t)); getinfo_helper_downloads(&dummy, "downloads/networkstatus/ns", &answer, &errmsg); - tt_assert(answer != NULL); - tt_assert(errmsg == NULL); + tt_ptr_op(answer, OP_NE, NULL); + tt_ptr_op(errmsg, OP_EQ, NULL); tt_str_op(answer, OP_EQ, dls_sample_1_str); tor_free(answer); errmsg = NULL; @@ -799,8 +799,8 @@ test_download_status_consensus(void *arg) sizeof(download_status_t)); getinfo_helper_downloads(&dummy, "downloads/networkstatus/microdesc", &answer, &errmsg); - tt_assert(answer != NULL); - tt_assert(errmsg == NULL); + tt_ptr_op(answer, OP_NE, NULL); + tt_ptr_op(errmsg, OP_EQ, NULL); tt_str_op(answer, OP_EQ, dls_sample_2_str); tor_free(answer); errmsg = NULL; @@ -810,8 +810,8 @@ test_download_status_consensus(void *arg) sizeof(download_status_t)); getinfo_helper_downloads(&dummy, "downloads/networkstatus/ns/bootstrap", &answer, &errmsg); - tt_assert(answer != NULL); - tt_assert(errmsg == NULL); + tt_ptr_op(answer, OP_NE, NULL); + tt_ptr_op(errmsg, OP_EQ, NULL); tt_str_op(answer, OP_EQ, dls_sample_3_str); tor_free(answer); errmsg = NULL; @@ -822,8 +822,8 @@ test_download_status_consensus(void *arg) getinfo_helper_downloads(&dummy, "downloads/networkstatus/microdesc/bootstrap", &answer, &errmsg); - tt_assert(answer != NULL); - tt_assert(errmsg == NULL); + tt_ptr_op(answer, OP_NE, NULL); + tt_ptr_op(errmsg, OP_EQ, NULL); tt_str_op(answer, OP_EQ, dls_sample_4_str); tor_free(answer); errmsg = NULL; @@ -834,8 +834,8 @@ test_download_status_consensus(void *arg) getinfo_helper_downloads(&dummy, "downloads/networkstatus/ns/running", &answer, &errmsg); - tt_assert(answer != NULL); - tt_assert(errmsg == NULL); + tt_ptr_op(answer, OP_NE, NULL); + tt_ptr_op(errmsg, OP_EQ, NULL); tt_str_op(answer, OP_EQ, dls_sample_5_str); tor_free(answer); errmsg = NULL; @@ -846,8 +846,8 @@ test_download_status_consensus(void *arg) getinfo_helper_downloads(&dummy, "downloads/networkstatus/microdesc/running", &answer, &errmsg); - tt_assert(answer != NULL); - tt_assert(errmsg == NULL); + tt_ptr_op(answer, OP_NE, NULL); + tt_ptr_op(errmsg, OP_EQ, NULL); tt_str_op(answer, OP_EQ, dls_sample_6_str); tor_free(answer); errmsg = NULL; @@ -855,8 +855,8 @@ test_download_status_consensus(void *arg) /* Now check the error case */ getinfo_helper_downloads(&dummy, "downloads/networkstatus/foo", &answer, &errmsg); - tt_assert(answer == NULL); - tt_assert(errmsg != NULL); + tt_ptr_op(answer, OP_EQ, NULL); + tt_ptr_op(errmsg, OP_NE, NULL); tt_str_op(errmsg, OP_EQ, "Unknown flavor"); errmsg = NULL; @@ -890,8 +890,8 @@ test_download_status_cert(void *arg) getinfo_helper_downloads(&dummy, "downloads/cert/fps", &answer, &errmsg); - tt_assert(answer != NULL); - tt_assert(errmsg == NULL); + tt_ptr_op(answer, OP_NE, NULL); + tt_ptr_op(errmsg, OP_EQ, NULL); tt_str_op(answer, OP_EQ, auth_id_digest_expected_list); tor_free(answer); errmsg = NULL; @@ -900,10 +900,10 @@ test_download_status_cert(void *arg) memcpy(&auth_def_cert_download_status_1, &dls_sample_1, sizeof(download_status_t)); tor_asprintf(&question, "downloads/cert/fp/%s", auth_id_digest_1_str); - tt_assert(question != NULL); + tt_ptr_op(question, OP_NE, NULL); getinfo_helper_downloads(&dummy, question, &answer, &errmsg); - tt_assert(answer != NULL); - tt_assert(errmsg == NULL); + tt_ptr_op(answer, OP_NE, NULL); + tt_ptr_op(errmsg, OP_EQ, NULL); tt_str_op(answer, OP_EQ, dls_sample_1_str); tor_free(question); tor_free(answer); @@ -913,10 +913,10 @@ test_download_status_cert(void *arg) memcpy(&auth_def_cert_download_status_2, &dls_sample_2, sizeof(download_status_t)); tor_asprintf(&question, "downloads/cert/fp/%s", auth_id_digest_2_str); - tt_assert(question != NULL); + tt_ptr_op(question, OP_NE, NULL); getinfo_helper_downloads(&dummy, question, &answer, &errmsg); - tt_assert(answer != NULL); - tt_assert(errmsg == NULL); + tt_ptr_op(answer, OP_NE, NULL); + tt_ptr_op(errmsg, OP_EQ, NULL); tt_str_op(answer, OP_EQ, dls_sample_2_str); tor_free(question); tor_free(answer); @@ -924,10 +924,10 @@ test_download_status_cert(void *arg) /* Case 4 - list of signing key digests for 1st auth id */ tor_asprintf(&question, "downloads/cert/fp/%s/sks", auth_id_digest_1_str); - tt_assert(question != NULL); + tt_ptr_op(question, OP_NE, NULL); getinfo_helper_downloads(&dummy, question, &answer, &errmsg); - tt_assert(answer != NULL); - tt_assert(errmsg == NULL); + tt_ptr_op(answer, OP_NE, NULL); + tt_ptr_op(errmsg, OP_EQ, NULL); tt_str_op(answer, OP_EQ, auth_1_sk_digest_expected_list); tor_free(question); tor_free(answer); @@ -935,10 +935,10 @@ test_download_status_cert(void *arg) /* Case 5 - list of signing key digests for 2nd auth id */ tor_asprintf(&question, "downloads/cert/fp/%s/sks", auth_id_digest_2_str); - tt_assert(question != NULL); + tt_ptr_op(question, OP_NE, NULL); getinfo_helper_downloads(&dummy, question, &answer, &errmsg); - tt_assert(answer != NULL); - tt_assert(errmsg == NULL); + tt_ptr_op(answer, OP_NE, NULL); + tt_ptr_op(errmsg, OP_EQ, NULL); tt_str_op(answer, OP_EQ, auth_2_sk_digest_expected_list); tor_free(question); tor_free(answer); @@ -949,10 +949,10 @@ test_download_status_cert(void *arg) sizeof(download_status_t)); tor_asprintf(&question, "downloads/cert/fp/%s/%s", auth_id_digest_1_str, auth_1_sk_1_str); - tt_assert(question != NULL); + tt_ptr_op(question, OP_NE, NULL); getinfo_helper_downloads(&dummy, question, &answer, &errmsg); - tt_assert(answer != NULL); - tt_assert(errmsg == NULL); + tt_ptr_op(answer, OP_NE, NULL); + tt_ptr_op(errmsg, OP_EQ, NULL); tt_str_op(answer, OP_EQ, dls_sample_3_str); tor_free(question); tor_free(answer); @@ -963,10 +963,10 @@ test_download_status_cert(void *arg) sizeof(download_status_t)); tor_asprintf(&question, "downloads/cert/fp/%s/%s", auth_id_digest_1_str, auth_1_sk_2_str); - tt_assert(question != NULL); + tt_ptr_op(question, OP_NE, NULL); getinfo_helper_downloads(&dummy, question, &answer, &errmsg); - tt_assert(answer != NULL); - tt_assert(errmsg == NULL); + tt_ptr_op(answer, OP_NE, NULL); + tt_ptr_op(errmsg, OP_EQ, NULL); tt_str_op(answer, OP_EQ, dls_sample_4_str); tor_free(question); tor_free(answer); @@ -977,10 +977,10 @@ test_download_status_cert(void *arg) sizeof(download_status_t)); tor_asprintf(&question, "downloads/cert/fp/%s/%s", auth_id_digest_2_str, auth_2_sk_1_str); - tt_assert(question != NULL); + tt_ptr_op(question, OP_NE, NULL); getinfo_helper_downloads(&dummy, question, &answer, &errmsg); - tt_assert(answer != NULL); - tt_assert(errmsg == NULL); + tt_ptr_op(answer, OP_NE, NULL); + tt_ptr_op(errmsg, OP_EQ, NULL); tt_str_op(answer, OP_EQ, dls_sample_5_str); tor_free(question); tor_free(answer); @@ -991,10 +991,10 @@ test_download_status_cert(void *arg) sizeof(download_status_t)); tor_asprintf(&question, "downloads/cert/fp/%s/%s", auth_id_digest_2_str, auth_2_sk_2_str); - tt_assert(question != NULL); + tt_ptr_op(question, OP_NE, NULL); getinfo_helper_downloads(&dummy, question, &answer, &errmsg); - tt_assert(answer != NULL); - tt_assert(errmsg == NULL); + tt_ptr_op(answer, OP_NE, NULL); + tt_ptr_op(errmsg, OP_EQ, NULL); tt_str_op(answer, OP_EQ, dls_sample_6_str); tor_free(question); tor_free(answer); @@ -1005,8 +1005,8 @@ test_download_status_cert(void *arg) /* Case 1 - query is garbage after downloads/cert/ part */ getinfo_helper_downloads(&dummy, "downloads/cert/blahdeblah", &answer, &errmsg); - tt_assert(answer == NULL); - tt_assert(errmsg != NULL); + tt_ptr_op(answer, OP_EQ, NULL); + tt_ptr_op(errmsg, OP_NE, NULL); tt_str_op(errmsg, OP_EQ, "Unknown certificate download status query"); errmsg = NULL; @@ -1016,8 +1016,8 @@ test_download_status_cert(void *arg) */ getinfo_helper_downloads(&dummy, "downloads/cert/fp/2B1D36D32B2942406", &answer, &errmsg); - tt_assert(answer == NULL); - tt_assert(errmsg != NULL); + tt_ptr_op(answer, OP_EQ, NULL); + tt_ptr_op(errmsg, OP_NE, NULL); tt_str_op(errmsg, OP_EQ, "That didn't look like a digest"); errmsg = NULL; @@ -1028,8 +1028,8 @@ test_download_status_cert(void *arg) getinfo_helper_downloads(&dummy, "downloads/cert/fp/82F52AF55D250115FE44D3GC81D49643241D56A1", &answer, &errmsg); - tt_assert(answer == NULL); - tt_assert(errmsg != NULL); + tt_ptr_op(answer, OP_EQ, NULL); + tt_ptr_op(errmsg, OP_NE, NULL); tt_str_op(errmsg, OP_EQ, "That didn't look like a digest"); errmsg = NULL; @@ -1040,8 +1040,8 @@ test_download_status_cert(void *arg) getinfo_helper_downloads(&dummy, "downloads/cert/fp/AC4F23B5745BDD2A77997B85B1FD85D05C2E0F61", &answer, &errmsg); - tt_assert(answer == NULL); - tt_assert(errmsg != NULL); + tt_ptr_op(answer, OP_EQ, NULL); + tt_ptr_op(errmsg, OP_NE, NULL); tt_str_op(errmsg, OP_EQ, "Failed to get download status for this authority identity digest"); errmsg = NULL; @@ -1053,8 +1053,8 @@ test_download_status_cert(void *arg) getinfo_helper_downloads(&dummy, "downloads/cert/fp/82F52AF55D250115FE44D3GC81D49643241D56A1/blah", &answer, &errmsg); - tt_assert(answer == NULL); - tt_assert(errmsg != NULL); + tt_ptr_op(answer, OP_EQ, NULL); + tt_ptr_op(errmsg, OP_NE, NULL); tt_str_op(errmsg, OP_EQ, "That didn't look like an identity digest"); errmsg = NULL; @@ -1065,8 +1065,8 @@ test_download_status_cert(void *arg) getinfo_helper_downloads(&dummy, "downloads/cert/fp/82F52AF55D25/blah", &answer, &errmsg); - tt_assert(answer == NULL); - tt_assert(errmsg != NULL); + tt_ptr_op(answer, OP_EQ, NULL); + tt_ptr_op(errmsg, OP_NE, NULL); tt_str_op(errmsg, OP_EQ, "That didn't look like an identity digest"); errmsg = NULL; @@ -1077,8 +1077,8 @@ test_download_status_cert(void *arg) getinfo_helper_downloads(&dummy, "downloads/cert/fp/AC4F23B5745BDD2A77997B85B1FD85D05C2E0F61/sks", &answer, &errmsg); - tt_assert(answer == NULL); - tt_assert(errmsg != NULL); + tt_ptr_op(answer, OP_EQ, NULL); + tt_ptr_op(errmsg, OP_NE, NULL); tt_str_op(errmsg, OP_EQ, "Failed to get list of signing key digests for this authority " "identity digest"); @@ -1092,8 +1092,8 @@ test_download_status_cert(void *arg) "downloads/cert/fp/AC4F23B5745BDD2A77997B85B1FD85D05C2E0F61/" "82F52AF55D250115FE44D3GC81D49643241D56A1", &answer, &errmsg); - tt_assert(answer == NULL); - tt_assert(errmsg != NULL); + tt_ptr_op(answer, OP_EQ, NULL); + tt_ptr_op(errmsg, OP_NE, NULL); tt_str_op(errmsg, OP_EQ, "That didn't look like a signing key digest"); errmsg = NULL; @@ -1105,8 +1105,8 @@ test_download_status_cert(void *arg) "downloads/cert/fp/AC4F23B5745BDD2A77997B85B1FD85D05C2E0F61/" "82F52AF55D250115FE44D", &answer, &errmsg); - tt_assert(answer == NULL); - tt_assert(errmsg != NULL); + tt_ptr_op(answer, OP_EQ, NULL); + tt_ptr_op(errmsg, OP_NE, NULL); tt_str_op(errmsg, OP_EQ, "That didn't look like a signing key digest"); errmsg = NULL; @@ -1118,8 +1118,8 @@ test_download_status_cert(void *arg) "downloads/cert/fp/C6B05DF332F74DB9A13498EE3BBC7AA2F69FCB45/" "3A214FC21AE25B012C2ECCB5F4EC8A3602D0545D", &answer, &errmsg); - tt_assert(answer == NULL); - tt_assert(errmsg != NULL); + tt_ptr_op(answer, OP_EQ, NULL); + tt_ptr_op(errmsg, OP_NE, NULL); tt_str_op(errmsg, OP_EQ, "Failed to get download status for this identity/" "signing key digest pair"); @@ -1133,8 +1133,8 @@ test_download_status_cert(void *arg) "downloads/cert/fp/63CDD326DFEF0CA020BDD3FEB45A3286FE13A061/" "3A214FC21AE25B012C2ECCB5F4EC8A3602D0545D", &answer, &errmsg); - tt_assert(answer == NULL); - tt_assert(errmsg != NULL); + tt_ptr_op(answer, OP_EQ, NULL); + tt_ptr_op(errmsg, OP_NE, NULL); tt_str_op(errmsg, OP_EQ, "Failed to get download status for this identity/" "signing key digest pair"); @@ -1148,8 +1148,8 @@ test_download_status_cert(void *arg) "downloads/cert/fp/63CDD326DFEF0CA020BDD3FEB45A3286FE13A061/" "9451B8F1B10952384EB58B5F230C0BB701626C9B", &answer, &errmsg); - tt_assert(answer == NULL); - tt_assert(errmsg != NULL); + tt_ptr_op(answer, OP_EQ, NULL); + tt_ptr_op(errmsg, OP_NE, NULL); tt_str_op(errmsg, OP_EQ, "Failed to get download status for this identity/" "signing key digest pair"); @@ -1185,8 +1185,8 @@ test_download_status_desc(void *arg) getinfo_helper_downloads(&dummy, "downloads/desc/descs", &answer, &errmsg); - tt_assert(answer != NULL); - tt_assert(errmsg == NULL); + tt_ptr_op(answer, OP_NE, NULL); + tt_ptr_op(errmsg, OP_EQ, NULL); tt_str_op(answer, OP_EQ, descbr_expected_list); tor_free(answer); errmsg = NULL; @@ -1195,10 +1195,10 @@ test_download_status_desc(void *arg) memcpy(&descbr_digest_1_dl, &dls_sample_1, sizeof(download_status_t)); tor_asprintf(&question, "downloads/desc/%s", descbr_digest_1_str); - tt_assert(question != NULL); + tt_ptr_op(question, OP_NE, NULL); getinfo_helper_downloads(&dummy, question, &answer, &errmsg); - tt_assert(answer != NULL); - tt_assert(errmsg == NULL); + tt_ptr_op(answer, OP_NE, NULL); + tt_ptr_op(errmsg, OP_EQ, NULL); tt_str_op(answer, OP_EQ, dls_sample_1_str); tor_free(question); tor_free(answer); @@ -1208,10 +1208,10 @@ test_download_status_desc(void *arg) memcpy(&descbr_digest_2_dl, &dls_sample_2, sizeof(download_status_t)); tor_asprintf(&question, "downloads/desc/%s", descbr_digest_2_str); - tt_assert(question != NULL); + tt_ptr_op(question, OP_NE, NULL); getinfo_helper_downloads(&dummy, question, &answer, &errmsg); - tt_assert(answer != NULL); - tt_assert(errmsg == NULL); + tt_ptr_op(answer, OP_NE, NULL); + tt_ptr_op(errmsg, OP_EQ, NULL); tt_str_op(answer, OP_EQ, dls_sample_2_str); tor_free(question); tor_free(answer); @@ -1222,8 +1222,8 @@ test_download_status_desc(void *arg) /* Case 1 - non-digest-length garbage after downloads/desc */ getinfo_helper_downloads(&dummy, "downloads/desc/blahdeblah", &answer, &errmsg); - tt_assert(answer == NULL); - tt_assert(errmsg != NULL); + tt_ptr_op(answer, OP_EQ, NULL); + tt_ptr_op(errmsg, OP_NE, NULL); tt_str_op(errmsg, OP_EQ, "Unknown router descriptor download status query"); errmsg = NULL; @@ -1232,8 +1232,8 @@ test_download_status_desc(void *arg) &dummy, "downloads/desc/774EC52FD9A5B80A6FACZE536616E8022E3470AG", &answer, &errmsg); - tt_assert(answer == NULL); - tt_assert(errmsg != NULL); + tt_ptr_op(answer, OP_EQ, NULL); + tt_ptr_op(errmsg, OP_NE, NULL); tt_str_op(errmsg, OP_EQ, "That didn't look like a digest"); errmsg = NULL; @@ -1242,8 +1242,8 @@ test_download_status_desc(void *arg) &dummy, "downloads/desc/B05B46135B0B2C04EBE1DD6A6AE4B12D7CD2226A", &answer, &errmsg); - tt_assert(answer == NULL); - tt_assert(errmsg != NULL); + tt_ptr_op(answer, OP_EQ, NULL); + tt_ptr_op(errmsg, OP_NE, NULL); tt_str_op(errmsg, OP_EQ, "No such descriptor digest found"); errmsg = NULL; @@ -1252,8 +1252,8 @@ test_download_status_desc(void *arg) getinfo_helper_downloads(&dummy, "downloads/desc/descs", &answer, &errmsg); - tt_assert(answer == NULL); - tt_assert(errmsg != NULL); + tt_ptr_op(answer, OP_EQ, NULL); + tt_ptr_op(errmsg, OP_NE, NULL); tt_str_op(errmsg, OP_EQ, "We don't seem to have a networkstatus-flavored consensus"); errmsg = NULL; @@ -1289,8 +1289,8 @@ test_download_status_bridge(void *arg) getinfo_helper_downloads(&dummy, "downloads/bridge/bridges", &answer, &errmsg); - tt_assert(answer != NULL); - tt_assert(errmsg == NULL); + tt_ptr_op(answer, OP_NE, NULL); + tt_ptr_op(errmsg, OP_EQ, NULL); tt_str_op(answer, OP_EQ, descbr_expected_list); tor_free(answer); errmsg = NULL; @@ -1299,10 +1299,10 @@ test_download_status_bridge(void *arg) memcpy(&descbr_digest_1_dl, &dls_sample_3, sizeof(download_status_t)); tor_asprintf(&question, "downloads/bridge/%s", descbr_digest_1_str); - tt_assert(question != NULL); + tt_ptr_op(question, OP_NE, NULL); getinfo_helper_downloads(&dummy, question, &answer, &errmsg); - tt_assert(answer != NULL); - tt_assert(errmsg == NULL); + tt_ptr_op(answer, OP_NE, NULL); + tt_ptr_op(errmsg, OP_EQ, NULL); tt_str_op(answer, OP_EQ, dls_sample_3_str); tor_free(question); tor_free(answer); @@ -1312,10 +1312,10 @@ test_download_status_bridge(void *arg) memcpy(&descbr_digest_2_dl, &dls_sample_4, sizeof(download_status_t)); tor_asprintf(&question, "downloads/bridge/%s", descbr_digest_2_str); - tt_assert(question != NULL); + tt_ptr_op(question, OP_NE, NULL); getinfo_helper_downloads(&dummy, question, &answer, &errmsg); - tt_assert(answer != NULL); - tt_assert(errmsg == NULL); + tt_ptr_op(answer, OP_NE, NULL); + tt_ptr_op(errmsg, OP_EQ, NULL); tt_str_op(answer, OP_EQ, dls_sample_4_str); tor_free(question); tor_free(answer); @@ -1326,8 +1326,8 @@ test_download_status_bridge(void *arg) /* Case 1 - non-digest-length garbage after downloads/bridge */ getinfo_helper_downloads(&dummy, "downloads/bridge/blahdeblah", &answer, &errmsg); - tt_assert(answer == NULL); - tt_assert(errmsg != NULL); + tt_ptr_op(answer, OP_EQ, NULL); + tt_ptr_op(errmsg, OP_NE, NULL); tt_str_op(errmsg, OP_EQ, "Unknown bridge descriptor download status query"); errmsg = NULL; @@ -1336,8 +1336,8 @@ test_download_status_bridge(void *arg) &dummy, "downloads/bridge/774EC52FD9A5B80A6FACZE536616E8022E3470AG", &answer, &errmsg); - tt_assert(answer == NULL); - tt_assert(errmsg != NULL); + tt_ptr_op(answer, OP_EQ, NULL); + tt_ptr_op(errmsg, OP_NE, NULL); tt_str_op(errmsg, OP_EQ, "That didn't look like a digest"); errmsg = NULL; @@ -1346,8 +1346,8 @@ test_download_status_bridge(void *arg) &dummy, "downloads/bridge/B05B46135B0B2C04EBE1DD6A6AE4B12D7CD2226A", &answer, &errmsg); - tt_assert(answer == NULL); - tt_assert(errmsg != NULL); + tt_ptr_op(answer, OP_EQ, NULL); + tt_ptr_op(errmsg, OP_NE, NULL); tt_str_op(errmsg, OP_EQ, "No such bridge identity digest found"); errmsg = NULL; @@ -1356,8 +1356,8 @@ test_download_status_bridge(void *arg) getinfo_helper_downloads(&dummy, "downloads/bridge/bridges", &answer, &errmsg); - tt_assert(answer == NULL); - tt_assert(errmsg != NULL); + tt_ptr_op(answer, OP_EQ, NULL); + tt_ptr_op(errmsg, OP_NE, NULL); tt_str_op(errmsg, OP_EQ, "We don't seem to be using bridges"); errmsg = NULL; disable_descbr = 0; diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c index 75cd30ebb5..83d97f2867 100644 --- a/src/test/test_crypto.c +++ b/src/test/test_crypto.c @@ -1139,7 +1139,7 @@ test_crypto_mac_sha3(void *arg) result = crypto_digest256(hmac_manual, all, all_len, DIGEST_SHA3_256); tor_free(key_msg_concat); tor_free(all); - tt_int_op(result, ==, 0); + tt_int_op(result, OP_EQ, 0); } /* Now compare the two results */ @@ -1208,12 +1208,12 @@ test_crypto_pk(void *arg) tt_assert(! crypto_pk_write_private_key_to_filename(pk1, get_fname("pkey1"))); /* failing case for read: can't read. */ - tt_assert(crypto_pk_read_private_key_from_filename(pk2, - get_fname("xyzzy")) < 0); + tt_int_op(crypto_pk_read_private_key_from_filename(pk2, get_fname("xyzzy")), + OP_LT, 0); write_str_to_file(get_fname("xyzzy"), "foobar", 6); /* Failing case for read: no key. */ - tt_assert(crypto_pk_read_private_key_from_filename(pk2, - get_fname("xyzzy")) < 0); + tt_int_op(crypto_pk_read_private_key_from_filename(pk2, get_fname("xyzzy")), + OP_LT, 0); tt_assert(! crypto_pk_read_private_key_from_filename(pk2, get_fname("pkey1"))); tt_int_op(15,OP_EQ, @@ -1245,17 +1245,17 @@ test_crypto_pk(void *arg) i = crypto_pk_asn1_encode(pk1, data1, 1024); tt_int_op(i, OP_GT, 0); pk2 = crypto_pk_asn1_decode(data1, i); - tt_assert(crypto_pk_cmp_keys(pk1,pk2) == 0); + tt_int_op(crypto_pk_cmp_keys(pk1, pk2), OP_EQ, 0); /* Try with hybrid encryption wrappers. */ crypto_rand(data1, 1024); for (i = 85; i < 140; ++i) { memset(data2,0,1024); memset(data3,0,1024); - len = crypto_pk_public_hybrid_encrypt(pk1,data2,sizeof(data2), + len = crypto_pk_obsolete_public_hybrid_encrypt(pk1,data2,sizeof(data2), data1,i,PK_PKCS1_OAEP_PADDING,0); tt_int_op(len, OP_GE, 0); - len = crypto_pk_private_hybrid_decrypt(pk1,data3,sizeof(data3), + len = crypto_pk_obsolete_private_hybrid_decrypt(pk1,data3,sizeof(data3), data2,len,PK_PKCS1_OAEP_PADDING,1); tt_int_op(len,OP_EQ, i); tt_mem_op(data1,OP_EQ, data3,i); @@ -1264,9 +1264,9 @@ test_crypto_pk(void *arg) /* Try copy_full */ crypto_pk_free(pk2); pk2 = crypto_pk_copy_full(pk1); - tt_assert(pk2 != NULL); + tt_ptr_op(pk2, OP_NE, NULL); tt_ptr_op(pk1, OP_NE, pk2); - tt_assert(crypto_pk_cmp_keys(pk1,pk2) == 0); + tt_int_op(crypto_pk_cmp_keys(pk1, pk2), OP_EQ, 0); done: if (pk1) @@ -1344,17 +1344,17 @@ test_crypto_pk_base64(void *arg) /* Test decoding a valid key. */ pk2 = crypto_pk_base64_decode(encoded, strlen(encoded)); tt_assert(pk2); - tt_assert(crypto_pk_cmp_keys(pk1,pk2) == 0); + tt_int_op(crypto_pk_cmp_keys(pk1, pk2), OP_EQ, 0); crypto_pk_free(pk2); /* Test decoding a invalid key (not Base64). */ static const char *invalid_b64 = "The key is in another castle!"; pk2 = crypto_pk_base64_decode(invalid_b64, strlen(invalid_b64)); - tt_assert(!pk2); + tt_ptr_op(pk2, OP_EQ, NULL); /* Test decoding a truncated Base64 blob. */ pk2 = crypto_pk_base64_decode(encoded, strlen(encoded)/2); - tt_assert(!pk2); + tt_ptr_op(pk2, OP_EQ, NULL); done: crypto_pk_free(pk1); @@ -1423,7 +1423,7 @@ do_truncate(const char *fname, size_t len) tor_free(bytes); return r; } -#endif +#endif /* defined(HAVE_TRUNCATE) */ /** Sanity check for crypto pk digests */ static void @@ -1446,6 +1446,7 @@ test_crypto_digests(void *arg) AUTHORITY_SIGNKEY_A_DIGEST, HEX_DIGEST_LEN); r = crypto_pk_get_common_digests(k, &pkey_digests); + tt_int_op(r, OP_EQ, 0); tt_mem_op(hex_str(pkey_digests.d[DIGEST_SHA1], DIGEST_LEN),OP_EQ, AUTHORITY_SIGNKEY_A_DIGEST, HEX_DIGEST_LEN); @@ -1535,7 +1536,7 @@ test_crypto_formats(void *arg) tt_mem_op(data1,OP_EQ, data3, DIGEST_LEN); tt_int_op(99,OP_EQ, data3[DIGEST_LEN+1]); - tt_assert(digest_from_base64(data3, "###") < 0); + tt_int_op(digest_from_base64(data3, "###"), OP_LT, 0); /* Encoding SHA256 */ crypto_rand(data2, DIGEST256_LEN); @@ -1946,7 +1947,7 @@ test_crypto_curve25519_impl(void *arg) "e0544770bc7de853b38f9100489e3e79"; const char e1e2k_expected[] = "cd6e8269104eb5aaee886bd2071fba88" "bd13861475516bc2cd2b6e005e805064"; -#else +#else /* !(defined(SLOW_CURVE25519_TEST)) */ const int loop_max=200; const char e1_expected[] = "bc7112cde03f97ef7008cad1bdc56be3" "c6a1037d74cceb3712e9206871dcf654"; @@ -1954,7 +1955,7 @@ test_crypto_curve25519_impl(void *arg) "8e3ee1a63c7d14274ea5d4c67f065467"; const char e1e2k_expected[] = "7ddb98bd89025d2347776b33901b3e7e" "c0ee98cb2257a4545c0cfb2ca3e1812b"; -#endif +#endif /* defined(SLOW_CURVE25519_TEST) */ unsigned char e1k[32]; unsigned char e2k[32]; @@ -2210,6 +2211,9 @@ test_crypto_ed25519_simple(void *arg) tt_int_op(0, OP_EQ, ed25519_public_key_generate(&pub1, &sec1)); tt_int_op(0, OP_EQ, ed25519_public_key_generate(&pub2, &sec1)); + tt_int_op(ed25519_validate_pubkey(&pub1), OP_EQ, 0); + tt_int_op(ed25519_validate_pubkey(&pub2), OP_EQ, 0); + tt_mem_op(pub1.pubkey, OP_EQ, pub2.pubkey, sizeof(pub1.pubkey)); tt_assert(ed25519_pubkey_eq(&pub1, &pub2)); tt_assert(ed25519_pubkey_eq(&pub1, &pub1)); @@ -2581,6 +2585,39 @@ test_crypto_ed25519_blinding(void *arg) ; } +/** Test that our blinding functions will fail if we pass them bad pubkeys */ +static void +test_crypto_ed25519_blinding_fail(void *arg) +{ + int retval; + uint8_t param[32] = {2}; + ed25519_public_key_t pub; + ed25519_public_key_t pub_blinded; + + (void)arg; + + /* This point is not on the curve: the blind routines should fail */ + const char badkey[] = + "e19c65de75c68cf3b7643ea732ba9eb1a3d20d6d57ba223c2ece1df66feb5af0"; + retval = base16_decode((char*)pub.pubkey, sizeof(pub.pubkey), + badkey, strlen(badkey)); + tt_int_op(retval, OP_EQ, sizeof(pub.pubkey)); + retval = ed25519_public_blind(&pub_blinded, &pub, param); + tt_int_op(retval, OP_EQ, -1); + + /* This point is legit: blind routines should be happy */ + const char goodkey[] = + "4ba2e44760dff4c559ef3c38768c1c14a8a54740c782c8d70803e9d6e3ad8794"; + retval = base16_decode((char*)pub.pubkey, sizeof(pub.pubkey), + goodkey, strlen(goodkey)); + tt_int_op(retval, OP_EQ, sizeof(pub.pubkey)); + retval = ed25519_public_blind(&pub_blinded, &pub, param); + tt_int_op(retval, OP_EQ, 0); + + done: + ; +} + static void test_crypto_ed25519_testvectors(void *arg) { @@ -2598,6 +2635,8 @@ test_crypto_ed25519_testvectors(void *arg) ed25519_signature_t sig; int sign; + memset(&curvekp, 0xd0, sizeof(curvekp)); + #define DECODE(p,s) base16_decode((char*)(p),sizeof(p),(s),strlen(s)) #define EQ(a,h) test_memeq_hex((const char*)(a), (h)) @@ -2679,8 +2718,8 @@ test_crypto_ed25519_storage(void *arg) tor_free(tag); /* whitebox test: truncated keys. */ - tt_int_op(0, ==, do_truncate(fname_1, 40)); - tt_int_op(0, ==, do_truncate(fname_2, 40)); + tt_int_op(0, OP_EQ, do_truncate(fname_1, 40)); + tt_int_op(0, OP_EQ, do_truncate(fname_2, 40)); tt_int_op(-1, OP_EQ, ed25519_pubkey_read_from_file(&pub, &tag, fname_2)); tt_ptr_op(tag, OP_EQ, NULL); tor_free(tag); @@ -2872,6 +2911,67 @@ crypto_rand_check_failure_mode_predict(void) #undef FAILURE_MODE_BUFFER_SIZE +/** Test that our ed25519 validation function rejects evil public keys and + * accepts good ones. */ +static void +test_crypto_ed25519_validation(void *arg) +{ + (void) arg; + + int retval; + ed25519_public_key_t pub1; + + /* See https://lists.torproject.org/pipermail/tor-dev/2017-April/012230.html + for a list of points with torsion components in ed25519. */ + + { /* Point with torsion component (order 8l) */ + const char badkey[] = + "300ef2e64e588e1df55b48e4da0416ffb64cc85d5b00af6463d5cc6c2b1c185e"; + retval = base16_decode((char*)pub1.pubkey, sizeof(pub1.pubkey), + badkey, strlen(badkey)); + tt_int_op(retval, OP_EQ, sizeof(pub1.pubkey)); + tt_int_op(ed25519_validate_pubkey(&pub1), OP_EQ, -1); + } + + { /* Point with torsion component (order 4l) */ + const char badkey[] = + "f43e3a046db8749164c6e69b193f1e942c7452e7d888736f40b98093d814d5e7"; + retval = base16_decode((char*)pub1.pubkey, sizeof(pub1.pubkey), + badkey, strlen(badkey)); + tt_int_op(retval, OP_EQ, sizeof(pub1.pubkey)); + tt_int_op(ed25519_validate_pubkey(&pub1), OP_EQ, -1); + } + + { /* Point with torsion component (order 2l) */ + const char badkey[] = + "c9fff3af0471c28e33e98c2043e44f779d0427b1e37c521a6bddc011ed1869af"; + retval = base16_decode((char*)pub1.pubkey, sizeof(pub1.pubkey), + badkey, strlen(badkey)); + tt_int_op(retval, OP_EQ, sizeof(pub1.pubkey)); + tt_int_op(ed25519_validate_pubkey(&pub1), OP_EQ, -1); + } + + { /* This point is not even on the curve */ + const char badkey[] = + "e19c65de75c68cf3b7643ea732ba9eb1a3d20d6d57ba223c2ece1df66feb5af0"; + retval = base16_decode((char*)pub1.pubkey, sizeof(pub1.pubkey), + badkey, strlen(badkey)); + tt_int_op(retval, OP_EQ, sizeof(pub1.pubkey)); + tt_int_op(ed25519_validate_pubkey(&pub1), OP_EQ, -1); + } + + { /* This one is a good key */ + const char goodkey[] = + "4ba2e44760dff4c559ef3c38768c1c14a8a54740c782c8d70803e9d6e3ad8794"; + retval = base16_decode((char*)pub1.pubkey, sizeof(pub1.pubkey), + goodkey, strlen(goodkey)); + tt_int_op(retval, OP_EQ, sizeof(pub1.pubkey)); + tt_int_op(ed25519_validate_pubkey(&pub1), OP_EQ, 0); + } + + done: ; +} + static void test_crypto_failure_modes(void *arg) { @@ -2879,17 +2979,17 @@ test_crypto_failure_modes(void *arg) (void)arg; rv = crypto_early_init(); - tt_assert(rv == 0); + tt_int_op(rv, OP_EQ, 0); /* Check random works */ rv = crypto_rand_check_failure_mode_zero(); - tt_assert(rv == 0); + tt_int_op(rv, OP_EQ, 0); rv = crypto_rand_check_failure_mode_identical(); - tt_assert(rv == 0); + tt_int_op(rv, OP_EQ, 0); rv = crypto_rand_check_failure_mode_predict(); - tt_assert(rv == 0); + tt_int_op(rv, OP_EQ, 0); done: ; @@ -2958,7 +3058,9 @@ struct testcase_t crypto_tests[] = { ED25519_TEST(encode, 0), ED25519_TEST(convert, 0), ED25519_TEST(blinding, 0), + ED25519_TEST(blinding_fail, 0), ED25519_TEST(testvectors, 0), + ED25519_TEST(validation, 0), { "ed25519_storage", test_crypto_ed25519_storage, 0, NULL, NULL }, { "siphash", test_crypto_siphash, 0, NULL, NULL }, { "failure_modes", test_crypto_failure_modes, TT_FORK, NULL, NULL }, diff --git a/src/test/test_crypto_openssl.c b/src/test/test_crypto_openssl.c index 3d7d2b4639..090cb4242b 100644 --- a/src/test/test_crypto_openssl.c +++ b/src/test/test_crypto_openssl.c @@ -26,7 +26,7 @@ test_crypto_rng_engine(void *arg) memset(&dummy_method, 0, sizeof(dummy_method)); /* We should be a no-op if we're already on RAND_OpenSSL */ - tt_int_op(0, ==, crypto_force_rand_ssleay()); + tt_int_op(0, OP_EQ, crypto_force_rand_ssleay()); tt_assert(RAND_get_rand_method() == RAND_OpenSSL()); /* We should correct the method if it's a dummy. */ @@ -34,11 +34,11 @@ test_crypto_rng_engine(void *arg) #ifdef LIBRESSL_VERSION_NUMBER /* On libressl, you can't override the RNG. */ tt_assert(RAND_get_rand_method() == RAND_OpenSSL()); - tt_int_op(0, ==, crypto_force_rand_ssleay()); + tt_int_op(0, OP_EQ, crypto_force_rand_ssleay()); #else tt_assert(RAND_get_rand_method() == &dummy_method); - tt_int_op(1, ==, crypto_force_rand_ssleay()); -#endif + tt_int_op(1, OP_EQ, crypto_force_rand_ssleay()); +#endif /* defined(LIBRESSL_VERSION_NUMBER) */ tt_assert(RAND_get_rand_method() == RAND_OpenSSL()); /* Make sure we aren't calling dummy_method */ diff --git a/src/test/test_crypto_slow.c b/src/test/test_crypto_slow.c index 75c6ba9aaa..2afb71ff5a 100644 --- a/src/test/test_crypto_slow.c +++ b/src/test/test_crypto_slow.c @@ -164,10 +164,10 @@ test_libscrypt_eq_openssl(void *arg) EVP_PBE_scrypt((const char *)"", 0, (const unsigned char *)"", 0, N, r, p, maxmem, buf2, dk_len); - tt_int_op(libscrypt_retval, ==, 0); - tt_int_op(openssl_retval, ==, 1); + tt_int_op(libscrypt_retval, OP_EQ, 0); + tt_int_op(openssl_retval, OP_EQ, 1); - tt_mem_op(buf1, ==, buf2, 64); + tt_mem_op(buf1, OP_EQ, buf2, 64); memset(buf1,0,64); memset(buf2,0,64); @@ -185,10 +185,10 @@ test_libscrypt_eq_openssl(void *arg) (const unsigned char *)"NaCl", strlen("NaCl"), N, r, p, maxmem, buf2, dk_len); - tt_int_op(libscrypt_retval, ==, 0); - tt_int_op(openssl_retval, ==, 1); + tt_int_op(libscrypt_retval, OP_EQ, 0); + tt_int_op(openssl_retval, OP_EQ, 1); - tt_mem_op(buf1, ==, buf2, 64); + tt_mem_op(buf1, OP_EQ, buf2, 64); memset(buf1,0,64); memset(buf2,0,64); @@ -210,10 +210,10 @@ test_libscrypt_eq_openssl(void *arg) strlen("SodiumChloride"), N, r, p, maxmem, buf2, dk_len); - tt_int_op(libscrypt_retval, ==, 0); - tt_int_op(openssl_retval, ==, 1); + tt_int_op(libscrypt_retval, OP_EQ, 0); + tt_int_op(openssl_retval, OP_EQ, 1); - tt_mem_op(buf1, ==, buf2, 64); + tt_mem_op(buf1, OP_EQ, buf2, 64); memset(buf1,0,64); memset(buf2,0,64); @@ -234,15 +234,15 @@ test_libscrypt_eq_openssl(void *arg) strlen("SodiumChloride"), N, r, p, maxmem, buf2, dk_len); - tt_int_op(libscrypt_retval, ==, 0); - tt_int_op(openssl_retval, ==, 1); + tt_int_op(libscrypt_retval, OP_EQ, 0); + tt_int_op(openssl_retval, OP_EQ, 1); - tt_mem_op(buf1, ==, buf2, 64); + tt_mem_op(buf1, OP_EQ, buf2, 64); done: return; } -#endif +#endif /* defined(HAVE_LIBSCRYPT) && defined(HAVE_EVP_PBE_SCRYPT) */ static void test_crypto_s2k_errors(void *arg) @@ -283,7 +283,7 @@ test_crypto_s2k_errors(void *arg) "ABC", 3, 0)); tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_new(buf, 50, &sz, "ABC", 3, S2K_FLAG_LOW_MEM)); -#endif +#endif /* defined(HAVE_LIBSCRYPT) */ tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_new(buf, 37, &sz, "ABC", 3, S2K_FLAG_USE_PBKDF2)); tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_new(buf, 29, &sz, @@ -318,7 +318,7 @@ test_crypto_s2k_errors(void *arg) tt_int_op(S2K_BAD_PARAMS, OP_EQ, secret_to_key_derivekey(buf2, sizeof(buf2), buf, 19, "ABC", 3)); -#endif +#endif /* defined(HAVE_LIBSCRYPT) */ done: ; @@ -516,7 +516,7 @@ test_crypto_ed25519_fuzz_donna(void *arg) unsigned i; (void)arg; - tt_assert(sizeof(msg) == iters); + tt_uint_op(iters, OP_EQ, sizeof(msg)); crypto_rand((char*) msg, sizeof(msg)); /* Fuzz Ed25519-donna vs ref10, alternating the implementation used to @@ -600,7 +600,7 @@ struct testcase_t slow_crypto_tests[] = { #ifdef HAVE_EVP_PBE_SCRYPT { "libscrypt_eq_openssl", test_libscrypt_eq_openssl, 0, NULL, NULL }, #endif -#endif +#endif /* defined(HAVE_LIBSCRYPT) */ { "s2k_pbkdf2", test_crypto_s2k_general, 0, &passthrough_setup, (void*)"pbkdf2" }, { "s2k_rfc2440_general", test_crypto_s2k_general, 0, &passthrough_setup, diff --git a/src/test/test_dir.c b/src/test/test_dir.c index 1ead6d78c2..b21ce5048c 100644 --- a/src/test/test_dir.c +++ b/src/test/test_dir.c @@ -18,6 +18,7 @@ #define RELAY_PRIVATE #include "or.h" +#include "bridges.h" #include "confparse.h" #include "config.h" #include "control.h" @@ -275,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); @@ -294,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)); } @@ -392,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); @@ -422,7 +423,7 @@ test_dir_formats(void *arg) add_fingerprint_to_dir(buf, fingerprint_list, 0); } -#endif +#endif /* 0 */ dirserv_free_fingerprint_list(); done: @@ -478,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); @@ -632,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); @@ -1537,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); @@ -1804,7 +1805,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, @@ -1892,8 +1893,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); @@ -2009,7 +2009,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. */ @@ -2079,7 +2079,7 @@ test_routerstatus_for_v3ns(routerstatus_t *rs, time_t now) /* XXXX check version */ } else { /* Weren't expecting this... */ - tt_assert(0); + tt_abort(); } done: @@ -2271,6 +2271,7 @@ test_dir_networkstatus_compute_bw_weights_v10(void *arg) 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 " @@ -2287,6 +2288,7 @@ test_dir_networkstatus_compute_bw_weights_v10(void *arg) 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 " @@ -2303,6 +2305,7 @@ test_dir_networkstatus_compute_bw_weights_v10(void *arg) 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 " @@ -2323,6 +2326,7 @@ test_dir_networkstatus_compute_bw_weights_v10(void *arg) "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)); @@ -2394,6 +2398,7 @@ test_a_networkstatus( sign_skey_2 = crypto_pk_new(); sign_skey_3 = crypto_pk_new(); sign_skey_leg1 = pk_generate(4); + dirvote_recalculate_timing(get_options(), now); sr_state_init(0, 0); tt_assert(!crypto_pk_read_private_key_from_string(sign_skey_1, @@ -3023,7 +3028,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)); @@ -3163,7 +3168,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: @@ -3179,9 +3184,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 */ @@ -3278,7 +3283,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: @@ -3385,7 +3390,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), @@ -3446,15 +3451,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 */ @@ -3466,17 +3473,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 */ @@ -3490,17 +3497,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 */ @@ -3516,16 +3523,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); @@ -3543,11 +3550,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); @@ -3565,11 +3572,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 */ @@ -3588,11 +3595,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 */ @@ -3612,16 +3619,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); @@ -3677,7 +3684,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" @@ -3685,23 +3692,23 @@ 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); @@ -3714,8 +3721,8 @@ test_dir_purpose_needs_anonymity_returns_true_by_default(void *arg) tor_capture_bugs_(1); setup_full_capture_of_logs(LOG_WARN); - tt_int_op(1, ==, purpose_needs_anonymity(0, 0, NULL)); - tt_int_op(1, ==, smartlist_len(tor_get_captured_bug_log_())); + 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_(); @@ -3729,11 +3736,12 @@ test_dir_purpose_needs_anonymity_returns_true_for_bridges(void *arg) { (void)arg; - tt_int_op(1, ==, purpose_needs_anonymity(0, ROUTER_PURPOSE_BRIDGE, NULL)); - tt_int_op(1, ==, purpose_needs_anonymity(0, ROUTER_PURPOSE_BRIDGE, + 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, ==, purpose_needs_anonymity(DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2, - ROUTER_PURPOSE_BRIDGE, NULL)); + tt_int_op(1, OP_EQ, + purpose_needs_anonymity(DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2, + ROUTER_PURPOSE_BRIDGE, NULL)); done: ; } @@ -3741,7 +3749,7 @@ static void test_dir_purpose_needs_anonymity_returns_false_for_own_bridge_desc(void *arg) { (void)arg; - tt_int_op(0, ==, purpose_needs_anonymity(DIR_PURPOSE_FETCH_SERVERDESC, + tt_int_op(0, OP_EQ, purpose_needs_anonymity(DIR_PURPOSE_FETCH_SERVERDESC, ROUTER_PURPOSE_BRIDGE, "authority.z")); done: ; @@ -3752,12 +3760,12 @@ test_dir_purpose_needs_anonymity_returns_true_for_sensitive_purpose(void *arg) { (void)arg; - tt_int_op(1, ==, purpose_needs_anonymity( + tt_int_op(1, OP_EQ, purpose_needs_anonymity( DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2, ROUTER_PURPOSE_GENERAL, NULL)); - tt_int_op(1, ==, purpose_needs_anonymity( + tt_int_op(1, OP_EQ, purpose_needs_anonymity( DIR_PURPOSE_UPLOAD_RENDDESC_V2, 0, NULL)); - tt_int_op(1, ==, purpose_needs_anonymity( + tt_int_op(1, OP_EQ, purpose_needs_anonymity( DIR_PURPOSE_FETCH_RENDDESC_V2, 0, NULL)); done: ; } @@ -3767,24 +3775,25 @@ test_dir_purpose_needs_anonymity_ret_false_for_non_sensitive_conn(void *arg) { (void)arg; - tt_int_op(0, ==, purpose_needs_anonymity(DIR_PURPOSE_UPLOAD_DIR, + tt_int_op(0, OP_EQ, purpose_needs_anonymity(DIR_PURPOSE_UPLOAD_DIR, ROUTER_PURPOSE_GENERAL, NULL)); - tt_int_op(0, ==, purpose_needs_anonymity(DIR_PURPOSE_UPLOAD_VOTE, 0, NULL)); - tt_int_op(0, ==, + 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, ==, + tt_int_op(0, OP_EQ, purpose_needs_anonymity(DIR_PURPOSE_FETCH_STATUS_VOTE, 0, NULL)); - tt_int_op(0, ==, purpose_needs_anonymity( + tt_int_op(0, OP_EQ, purpose_needs_anonymity( DIR_PURPOSE_FETCH_DETACHED_SIGNATURES, 0, NULL)); - tt_int_op(0, ==, + tt_int_op(0, OP_EQ, purpose_needs_anonymity(DIR_PURPOSE_FETCH_CONSENSUS, 0, NULL)); - tt_int_op(0, ==, + tt_int_op(0, OP_EQ, purpose_needs_anonymity(DIR_PURPOSE_FETCH_CERTIFICATE, 0, NULL)); - tt_int_op(0, ==, + tt_int_op(0, OP_EQ, purpose_needs_anonymity(DIR_PURPOSE_FETCH_SERVERDESC, 0, NULL)); - tt_int_op(0, ==, + tt_int_op(0, OP_EQ, purpose_needs_anonymity(DIR_PURPOSE_FETCH_EXTRAINFO, 0, NULL)); - tt_int_op(0, ==, + tt_int_op(0, OP_EQ, purpose_needs_anonymity(DIR_PURPOSE_FETCH_MICRODESC, 0, NULL)); done: ; } @@ -3837,9 +3846,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"); @@ -3956,7 +3965,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" @@ -4128,47 +4137,105 @@ 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; /* Check the random backoff cases */ - old_increment = 0; + int n_attempts = 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); /* Advance */ - current_time += increment; - ++(dls_random.n_download_attempts); - ++(dls_random.n_download_failures); + if (dls_random.n_download_attempts < IMPOSSIBLE_TO_DOWNLOAD - 1) { + ++(dls_random.n_download_attempts); + ++(dls_random.n_download_failures); + } /* Try another maybe */ old_increment = increment; - } while (increment < max_delay); + } while (increment < max_delay && ++n_attempts < 1000); done: return; } 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_random_backoff_ranges(void *arg) +{ + (void)arg; + int lo, hi; + next_random_exponential_delay_range(&lo, &hi, 0, 10); + tt_int_op(lo, OP_EQ, 10); + tt_int_op(hi, OP_EQ, 11); + + next_random_exponential_delay_range(&lo, &hi, 6, 10); + tt_int_op(lo, OP_EQ, 10); + tt_int_op(hi, OP_EQ, 6*3); + + next_random_exponential_delay_range(&lo, &hi, 13, 10); + tt_int_op(lo, OP_EQ, 10); + tt_int_op(hi, OP_EQ, 13 * 3); + + next_random_exponential_delay_range(&lo, &hi, 37, 10); + tt_int_op(lo, OP_EQ, 10); + tt_int_op(hi, OP_EQ, 111); + + next_random_exponential_delay_range(&lo, &hi, 123, 10); + tt_int_op(lo, OP_EQ, 10); + tt_int_op(hi, OP_EQ, 369); + + next_random_exponential_delay_range(&lo, &hi, INT_MAX-5, 10); + tt_int_op(lo, OP_EQ, 10); + tt_int_op(hi, OP_EQ, INT_MAX); + done: + ; +} + +static void test_dir_download_status_increment(void *arg) { (void)arg; @@ -4180,32 +4247,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); @@ -4215,76 +4347,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; @@ -4292,22 +4424,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; @@ -4320,19 +4452,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; @@ -4343,65 +4476,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; @@ -4409,22 +4542,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; @@ -4437,9 +4570,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 */ @@ -4452,13 +4586,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; @@ -4767,13 +4902,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) { @@ -4800,7 +4935,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); @@ -4829,8 +4964,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); @@ -4956,7 +5091,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); /* @@ -4969,21 +5104,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); /* @@ -4991,8 +5126,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. @@ -5004,14 +5139,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 */ @@ -5020,21 +5155,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); /* @@ -5042,8 +5178,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 @@ -5055,14 +5191,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 */ @@ -5071,14 +5207,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 */ @@ -5087,21 +5224,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); /* @@ -5109,8 +5247,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 @@ -5122,14 +5260,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 */ @@ -5138,14 +5276,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 */ @@ -5154,21 +5293,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); /* @@ -5176,8 +5316,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 @@ -5189,14 +5329,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 */ @@ -5205,14 +5345,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 */ @@ -5221,21 +5362,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); /* @@ -5243,8 +5385,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 @@ -5256,14 +5398,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 */ @@ -5272,14 +5414,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 */ @@ -5288,14 +5431,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 */ @@ -5304,21 +5448,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); /* @@ -5326,8 +5471,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 @@ -5339,14 +5484,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 */ @@ -5355,14 +5500,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 */ @@ -5371,14 +5517,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 */ @@ -5387,21 +5534,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); /* @@ -5409,8 +5557,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: @@ -5457,7 +5605,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; @@ -5520,53 +5668,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 */ @@ -5575,10 +5723,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 = @@ -5591,10 +5739,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); @@ -5607,13 +5755,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); @@ -5622,9 +5770,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: @@ -5746,9 +5894,18 @@ 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_num_bridges_usable_value = 0; +static int +mock_num_bridges_usable(int use_maybe_reachable) +{ + (void)use_maybe_reachable; + return mock_num_bridges_usable_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 @@ -5756,7 +5913,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; @@ -5770,15 +5927,24 @@ test_dir_find_dl_schedule(void* data) mock_networkstatus_consensus_can_use_extra_fallbacks_value = 0; } + if (str[2] == 'r') { + /* Any positive, non-zero value should work */ + mock_num_bridges_usable_value = 2; + } else { + mock_num_bridges_usable_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(num_bridges_usable, + mock_num_bridges_usable); 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); @@ -5795,6 +5961,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 */ @@ -5883,11 +6050,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 (num_bridges_usable(0) > 0) { + 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(num_bridges_usable); UNMOCK(get_options); tor_free(mock_options); mock_options = NULL; @@ -5997,6 +6170,29 @@ test_dir_post_parsing(void *arg) ; } +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 } @@ -6042,7 +6238,8 @@ struct testcase_t dir_tests[] = { DIR(packages, 0), DIR(download_status_schedule, 0), DIR(download_status_random_backoff, 0), - DIR(download_status_increment, 0), + DIR(download_status_random_backoff_ranges, 0), + DIR(download_status_increment, TT_FORK), DIR(authdir_type_to_string, 0), DIR(conn_purpose_to_string, 0), DIR(should_use_directory_guards, 0), @@ -6053,12 +6250,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 }; diff --git a/src/test/test_dir_common.c b/src/test/test_dir_common.c index fca70249bd..fdf43533a8 100644 --- a/src/test/test_dir_common.c +++ b/src/test/test_dir_common.c @@ -146,7 +146,7 @@ dir_common_gen_routerstatus_for_v3ns(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)); diff --git a/src/test/test_dir_handle_get.c b/src/test/test_dir_handle_get.c index 75fe6249ad..fe26657ad8 100644 --- a/src/test/test_dir_handle_get.c +++ b/src/test/test_dir_handle_get.c @@ -28,6 +28,7 @@ #include "entrynodes.h" #include "routerparse.h" #include "networkstatus.h" +#include "proto_http.h" #include "geoip.h" #include "dirserv.h" #include "dirvote.h" @@ -38,7 +39,7 @@ #include <direct.h> #else #include <dirent.h> -#endif +#endif /* defined(_WIN32) */ #ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS DISABLE_GCC_WARNING(overlength-strings) @@ -869,7 +870,7 @@ test_dir_handle_get_server_descriptors_authority(void* data) mock_routerinfo->cache_info.signed_descriptor_body = tor_strdup(TEST_DESCRIPTOR); mock_routerinfo->cache_info.signed_descriptor_len = - strlen(TEST_DESCRIPTOR) - annotation_len;; + strlen(TEST_DESCRIPTOR) - annotation_len; mock_routerinfo->cache_info.annotations_len = annotation_len; mock_routerinfo->cache_info.published_on = time(NULL); @@ -1794,7 +1795,7 @@ status_vote_current_consensus_ns_test(char **header, char **body, dirserv_set_cached_consensus_networkstatus(NETWORK_STATUS, "ns", &digests, sha3, time(NULL)); -#endif +#endif /* 0 */ networkstatus_t *ns = tor_malloc_zero(sizeof(networkstatus_t)); ns->type = NS_TYPE_CONSENSUS; ns->flavor = FLAV_NS; diff --git a/src/test/test_dns.c b/src/test/test_dns.c index 6a8e92cb47..19dcb02931 100644 --- a/src/test/test_dns.c +++ b/src/test/test_dns.c @@ -18,9 +18,9 @@ NS(test_main)(void *arg) uint32_t ttl_mid = MIN_DNS_TTL_AT_EXIT / 2 + MAX_DNS_TTL_AT_EXIT / 2; - tt_int_op(dns_clip_ttl(MIN_DNS_TTL_AT_EXIT - 1),==,MIN_DNS_TTL_AT_EXIT); - tt_int_op(dns_clip_ttl(ttl_mid),==,MAX_DNS_TTL_AT_EXIT); - tt_int_op(dns_clip_ttl(MAX_DNS_TTL_AT_EXIT + 1),==,MAX_DNS_TTL_AT_EXIT); + tt_int_op(dns_clip_ttl(MIN_DNS_TTL_AT_EXIT - 1),OP_EQ,MIN_DNS_TTL_AT_EXIT); + tt_int_op(dns_clip_ttl(ttl_mid),OP_EQ,MAX_DNS_TTL_AT_EXIT); + tt_int_op(dns_clip_ttl(MAX_DNS_TTL_AT_EXIT + 1),OP_EQ,MAX_DNS_TTL_AT_EXIT); done: return; @@ -172,10 +172,10 @@ NS(test_main)(void *arg) retval = dns_resolve(exitconn); - tt_int_op(retval,==,1); - tt_str_op(resolved_name,==,last_resolved_hostname); + tt_int_op(retval,OP_EQ,1); + tt_str_op(resolved_name,OP_EQ,last_resolved_hostname); tt_assert(conn_for_resolved_cell == exitconn); - tt_int_op(n_send_resolved_hostname_cell_replacement,==, + tt_int_op(n_send_resolved_hostname_cell_replacement,OP_EQ, prev_n_send_resolved_hostname_cell_replacement + 1); tt_assert(exitconn->on_circuit == NULL); @@ -201,12 +201,12 @@ NS(test_main)(void *arg) retval = dns_resolve(exitconn); - tt_int_op(retval,==,1); + tt_int_op(retval,OP_EQ,1); tt_assert(conn_for_resolved_cell == exitconn); - tt_int_op(n_send_resolved_cell_replacement,==, + tt_int_op(n_send_resolved_cell_replacement,OP_EQ, prev_n_send_resolved_cell_replacement + 1); tt_assert(last_resolved == fake_resolved); - tt_int_op(last_answer_type,==,0xff); + tt_int_op(last_answer_type,OP_EQ,0xff); tt_assert(exitconn->on_circuit == NULL); /* CASE 3: The purpose of exit connection is not EXIT_PURPOSE_RESOLVE @@ -229,12 +229,12 @@ NS(test_main)(void *arg) retval = dns_resolve(exitconn); - tt_int_op(retval,==,1); + tt_int_op(retval,OP_EQ,1); tt_assert(on_circuit->n_streams == exitconn); tt_assert(exitconn->next_stream == nextconn); - tt_int_op(prev_n_send_resolved_cell_replacement,==, + tt_int_op(prev_n_send_resolved_cell_replacement,OP_EQ, n_send_resolved_cell_replacement); - tt_int_op(prev_n_send_resolved_hostname_cell_replacement,==, + tt_int_op(prev_n_send_resolved_hostname_cell_replacement,OP_EQ, n_send_resolved_hostname_cell_replacement); /* CASE 4: _impl returns 0. @@ -253,8 +253,8 @@ NS(test_main)(void *arg) retval = dns_resolve(exitconn); - tt_int_op(retval,==,0); - tt_int_op(exitconn->base_.state,==,EXIT_CONN_STATE_RESOLVING); + tt_int_op(retval,OP_EQ,0); + tt_int_op(exitconn->base_.state,OP_EQ,EXIT_CONN_STATE_RESOLVING); tt_assert(on_circuit->resolving_streams == exitconn); tt_assert(exitconn->next_stream == nextconn); @@ -278,12 +278,12 @@ NS(test_main)(void *arg) retval = dns_resolve(exitconn); - tt_int_op(retval,==,-1); - tt_int_op(n_send_resolved_cell_replacement,==, + tt_int_op(retval,OP_EQ,-1); + tt_int_op(n_send_resolved_cell_replacement,OP_EQ, prev_n_send_resolved_cell_replacement + 1); - tt_int_op(last_answer_type,==,RESOLVED_TYPE_ERROR); - tt_int_op(n_dns_cancel_pending_resolve_replacement,==,1); - tt_int_op(n_connection_free,==,prev_n_connection_free + 1); + tt_int_op(last_answer_type,OP_EQ,RESOLVED_TYPE_ERROR); + tt_int_op(n_dns_cancel_pending_resolve_replacement,OP_EQ,1); + tt_int_op(n_connection_free,OP_EQ,prev_n_connection_free + 1); tt_assert(last_freed_conn == TO_CONN(exitconn)); done: @@ -351,9 +351,9 @@ NS(test_main)(void *arg) resolved_addr = &(exitconn->base_.addr); - tt_int_op(retval,==,1); + tt_int_op(retval,OP_EQ,1); tt_assert(tor_addr_eq(resolved_addr, (const tor_addr_t *)&addr_to_compare)); - tt_int_op(exitconn->address_ttl,==,DEFAULT_DNS_TTL); + tt_int_op(exitconn->address_ttl,OP_EQ,DEFAULT_DNS_TTL); done: tor_free(on_circ); @@ -393,7 +393,7 @@ NS(test_main)(void *arg) retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending, NULL); - tt_int_op(retval,==,-1); + tt_int_op(retval,OP_EQ,-1); done: tor_free(TO_CONN(exitconn)->address); @@ -436,7 +436,7 @@ NS(test_main)(void *arg) retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending, NULL); - tt_int_op(retval,==,-1); + tt_int_op(retval,OP_EQ,-1); done: NS_UNMOCK(router_my_exit_policy_is_reject_star); @@ -478,7 +478,7 @@ NS(test_main)(void *arg) retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending, NULL); - tt_int_op(retval,==,-1); + tt_int_op(retval,OP_EQ,-1); tor_free(TO_CONN(exitconn)->address); @@ -488,7 +488,7 @@ NS(test_main)(void *arg) retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending, NULL); - tt_int_op(retval,==,-1); + tt_int_op(retval,OP_EQ,-1); done: NS_UNMOCK(router_my_exit_policy_is_reject_star); @@ -546,8 +546,8 @@ NS(test_main)(void *arg) retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending, NULL); - tt_int_op(retval,==,0); - tt_int_op(made_pending,==,1); + tt_int_op(retval,OP_EQ,0); + tt_int_op(made_pending,OP_EQ,1); pending_conn = cache_entry->pending_connections; @@ -628,8 +628,8 @@ NS(test_main)(void *arg) retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending, &resolve_out); - tt_int_op(retval,==,0); - tt_int_op(made_pending,==,0); + tt_int_op(retval,OP_EQ,0); + tt_int_op(made_pending,OP_EQ,0); tt_assert(resolve_out == cache_entry); tt_assert(last_exitconn == exitconn); @@ -699,8 +699,8 @@ NS(test_main)(void *arg) retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending, NULL); - tt_int_op(retval,==,0); - tt_int_op(made_pending,==,1); + tt_int_op(retval,OP_EQ,0); + tt_int_op(made_pending,OP_EQ,1); cache_entry = dns_get_cache_entry(&query); @@ -712,7 +712,7 @@ NS(test_main)(void *arg) tt_assert(pending_conn->conn == exitconn); tt_assert(last_launched_resolve == cache_entry); - tt_str_op(cache_entry->address,==,TO_CONN(exitconn)->address); + tt_str_op(cache_entry->address,OP_EQ,TO_CONN(exitconn)->address); done: NS_UNMOCK(router_my_exit_policy_is_reject_star); diff --git a/src/test/test_entryconn.c b/src/test/test_entryconn.c index 12a631630b..c29b1a7126 100644 --- a/src/test/test_entryconn.c +++ b/src/test/test_entryconn.c @@ -14,6 +14,10 @@ #include "confparse.h" #include "connection.h" #include "connection_edge.h" +#include "nodelist.h" + +#include "hs_cache.h" +#include "rendcache.h" static void * entryconn_rewrite_setup(const struct testcase_t *tc) @@ -72,7 +76,6 @@ test_entryconn_rewrite_bad_dotexit(void *arg) entry_connection_t *ec = arg; rewrite_result_t rr; - get_options_mutable()->AllowDotExit = 0; tt_assert(ec->socks_request); strlcpy(ec->socks_request->address, "www.TORproject.org.foo.exit", sizeof(ec->socks_request->address)); @@ -282,7 +285,7 @@ test_entryconn_rewrite_automap_reverse(void *arg) done: connection_free_(ENTRY_TO_CONN(ec2)); } -#endif +#endif /* 0 */ /* Rewrite because of cached DNS entry. */ static void @@ -476,7 +479,7 @@ test_entryconn_rewrite_reject_internal_reverse(void *arg) ; } -/* Rewrite into .exit because of virtual address mapping */ +/* Rewrite into .exit because of virtual address mapping. */ static void test_entryconn_rewrite_automap_exit(void *arg) { @@ -487,43 +490,21 @@ test_entryconn_rewrite_automap_exit(void *arg) ec2 = entry_connection_new(CONN_TYPE_AP, AF_INET); - get_options_mutable()->AutomapHostsOnResolve = 1; - get_options_mutable()->AllowDotExit = 1; smartlist_add_strdup(get_options_mutable()->AutomapHostsSuffixes, ".EXIT"); parse_virtual_addr_network("127.1.0.0/16", AF_INET, 0, &msg); - /* Automap this on resolve. */ + /* Try to automap this on resolve. */ strlcpy(ec->socks_request->address, "website.example.exit", sizeof(ec->socks_request->address)); ec->socks_request->command = SOCKS_COMMAND_RESOLVE; connection_ap_handshake_rewrite(ec, &rr); - tt_int_op(rr.automap, OP_EQ, 1); - tt_int_op(rr.should_close, OP_EQ, 0); - tt_int_op(rr.end_reason, OP_EQ, 0); - tt_i64_op(rr.map_expires, OP_EQ, TIME_MAX); - tt_int_op(rr.exit_source, OP_EQ, ADDRMAPSRC_NONE); - tt_str_op(rr.orig_address, OP_EQ, "website.example.exit"); - tt_str_op(ec->original_dest_address, OP_EQ, "website.example.exit"); - - tt_assert(!strcmpstart(ec->socks_request->address,"127.1.")); - - /* Connect to it and make sure we get the original address back. */ - strlcpy(ec2->socks_request->address, ec->socks_request->address, - sizeof(ec2->socks_request->address)); - - ec2->socks_request->command = SOCKS_COMMAND_CONNECT; - connection_ap_handshake_rewrite(ec2, &rr); - + /* Make sure it isn't allowed -- there is no longer an AllowDotExit + * option. */ tt_int_op(rr.automap, OP_EQ, 0); - tt_int_op(rr.should_close, OP_EQ, 0); - tt_int_op(rr.end_reason, OP_EQ, 0); - tt_i64_op(rr.map_expires, OP_EQ, TIME_MAX); - tt_int_op(rr.exit_source, OP_EQ, ADDRMAPSRC_AUTOMAP); - tt_str_op(rr.orig_address, OP_EQ, ec->socks_request->address); - tt_str_op(ec2->original_dest_address, OP_EQ, ec->socks_request->address); - tt_str_op(ec2->socks_request->address, OP_EQ, "website.example.exit"); + tt_int_op(rr.should_close, OP_EQ, 1); + tt_int_op(rr.end_reason, OP_EQ, END_STREAM_REASON_TORPROTOCOL); done: connection_free_(ENTRY_TO_CONN(ec2)); @@ -573,7 +554,6 @@ test_entryconn_rewrite_mapaddress_automap_onion(void *arg) ec4 = entry_connection_new(CONN_TYPE_AP, AF_INET); get_options_mutable()->AutomapHostsOnResolve = 1; - get_options_mutable()->AllowDotExit = 1; smartlist_add_strdup(get_options_mutable()->AutomapHostsSuffixes, ".onion"); parse_virtual_addr_network("192.168.0.0/16", AF_INET, 0, &msg); @@ -743,6 +723,88 @@ test_entryconn_rewrite_mapaddress_automap_onion4(void *arg) test_entryconn_rewrite_mapaddress_automap_onion_common(arg, 0, 1); } +/** Test that rewrite functions can handle v2 addresses */ +static void +test_entryconn_rewrite_onion_v2(void *arg) +{ + int retval; + entry_connection_t *conn = arg; + + (void) arg; + + rend_cache_init(); + + /* Make a SOCKS request */ + conn->socks_request->command = SOCKS_COMMAND_CONNECT; + strlcpy(conn->socks_request->address, + "pqeed46efnwmfuid.onion", + sizeof(conn->socks_request->address)); + + /* Make an onion connection using the SOCKS request */ + conn->entry_cfg.onion_traffic = 1; + ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_SOCKS_WAIT; + tt_assert(!ENTRY_TO_EDGE_CONN(conn)->rend_data); + + /* Handle SOCKS and rewrite! */ + retval = connection_ap_handshake_rewrite_and_attach(conn, NULL, NULL); + tt_int_op(retval, OP_EQ, 0); + + /* Check connection state after rewrite */ + tt_int_op(ENTRY_TO_CONN(conn)->state, OP_EQ, AP_CONN_STATE_RENDDESC_WAIT); + /* check that the address got rewritten */ + tt_str_op(conn->socks_request->address, OP_EQ, + "pqeed46efnwmfuid"); + /* check that HS information got attached to the connection */ + tt_assert(ENTRY_TO_EDGE_CONN(conn)->rend_data); + tt_assert(!ENTRY_TO_EDGE_CONN(conn)->hs_ident); + + done: + rend_cache_free_all(); + /* 'conn' is cleaned by handler */ +} + +/** Test that rewrite functions can handle v3 onion addresses */ +static void +test_entryconn_rewrite_onion_v3(void *arg) +{ + int retval; + entry_connection_t *conn = arg; + + (void) arg; + + hs_cache_init(); + + /* Make a SOCKS request */ + conn->socks_request->command = SOCKS_COMMAND_CONNECT; + strlcpy(conn->socks_request->address, + "git.25njqamcweflpvkl73j4szahhihoc4xt3ktcgjnpaingr5yhkenl5sid.onion", + sizeof(conn->socks_request->address)); + + /* Make an onion connection using the SOCKS request */ + conn->entry_cfg.onion_traffic = 1; + ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_SOCKS_WAIT; + tt_assert(!ENTRY_TO_EDGE_CONN(conn)->rend_data); + tt_assert(!ENTRY_TO_EDGE_CONN(conn)->hs_ident); + + /* Handle SOCKS and rewrite! */ + retval = connection_ap_handshake_rewrite_and_attach(conn, NULL, NULL); + tt_int_op(retval, OP_EQ, 0); + + /* Check connection state after rewrite. It should be in waiting for + * descriptor state. */ + tt_int_op(ENTRY_TO_CONN(conn)->state, OP_EQ, AP_CONN_STATE_RENDDESC_WAIT); + /* check that the address got rewritten */ + tt_str_op(conn->socks_request->address, OP_EQ, + "25njqamcweflpvkl73j4szahhihoc4xt3ktcgjnpaingr5yhkenl5sid"); + /* check that HS information got attached to the connection */ + tt_assert(ENTRY_TO_EDGE_CONN(conn)->hs_ident); + tt_assert(!ENTRY_TO_EDGE_CONN(conn)->rend_data); + + done: + hs_free_all(); + /* 'conn' is cleaned by handler */ +} + #define REWRITE(name) \ { #name, test_entryconn_##name, TT_FORK, &test_rewrite_setup, NULL } @@ -763,6 +825,8 @@ struct testcase_t entryconn_tests[] = { REWRITE(rewrite_mapaddress_automap_onion2), REWRITE(rewrite_mapaddress_automap_onion3), REWRITE(rewrite_mapaddress_automap_onion4), + REWRITE(rewrite_onion_v2), + REWRITE(rewrite_onion_v3), END_OF_TESTCASES }; diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c index 2162e338d2..7d85b09e03 100644 --- a/src/test/test_entrynodes.c +++ b/src/test/test_entrynodes.c @@ -7,6 +7,7 @@ #define STATEFILE_PRIVATE #define ENTRYNODES_PRIVATE #define ROUTERLIST_PRIVATE +#define DIRECTORY_PRIVATE #include "or.h" #include "test.h" @@ -15,6 +16,7 @@ #include "circuitlist.h" #include "config.h" #include "confparse.h" +#include "directory.h" #include "entrynodes.h" #include "nodelist.h" #include "networkstatus.h" @@ -129,6 +131,14 @@ big_fake_network_setup(const struct testcase_t *testcase) n->rs->has_bandwidth = 1; n->rs->bandwidth_kb = 30; + /* Make a random nickname for each node */ + { + char nickname_binary[8]; + crypto_rand(nickname_binary, sizeof(nickname_binary)); + base64_encode(n->rs->nickname, sizeof(n->rs->nickname), + nickname_binary, sizeof(nickname_binary), 0); + } + /* Call half of the nodes a possible guard. */ if (i % 2 == 0) { n->is_possible_guard = 1; @@ -455,29 +465,29 @@ test_entry_guard_parse_from_state_failure(void *arg) /* no selection */ eg = entry_guard_parse_from_state( "rsa_id=596f75206d6179206e656564206120686f626270"); - tt_assert(! eg); + tt_ptr_op(eg, OP_EQ, NULL); /* no RSA ID. */ eg = entry_guard_parse_from_state("in=default nickname=Fred"); - tt_assert(! eg); + tt_ptr_op(eg, OP_EQ, NULL); /* Bad RSA ID: bad character. */ eg = entry_guard_parse_from_state( "in=default " "rsa_id=596f75206d6179206e656564206120686f62627q"); - tt_assert(! eg); + tt_ptr_op(eg, OP_EQ, NULL); /* Bad RSA ID: too long.*/ eg = entry_guard_parse_from_state( "in=default " "rsa_id=596f75206d6179206e656564206120686f6262703"); - tt_assert(! eg); + tt_ptr_op(eg, OP_EQ, NULL); /* Bad RSA ID: too short.*/ eg = entry_guard_parse_from_state( "in=default " "rsa_id=596f75206d6179206e65656420612"); - tt_assert(! eg); + tt_ptr_op(eg, OP_EQ, NULL); done: entry_guard_free(eg); @@ -595,20 +605,20 @@ test_entry_guard_parse_from_state_full(void *arg) MOCK(get_or_state, get_or_state_replacement); - tt_assert(r == 0); + tt_int_op(r, OP_EQ, 0); tt_assert(lines); state->Guard = lines; /* Try it first without setting the result. */ r = entry_guards_parse_state(state, 0, &msg); - tt_assert(r == 0); + tt_int_op(r, OP_EQ, 0); guard_selection_t *gs_br = get_guard_selection_by_name("bridges", GS_TYPE_BRIDGE, 0); - tt_assert(!gs_br); + tt_ptr_op(gs_br, OP_EQ, NULL); r = entry_guards_parse_state(state, 1, &msg); - tt_assert(r == 0); + tt_int_op(r, OP_EQ, 0); gs_br = get_guard_selection_by_name("bridges", GS_TYPE_BRIDGE, 0); guard_selection_t *gs_df = get_guard_selection_by_name("default", GS_TYPE_NORMAL, 0); @@ -625,7 +635,7 @@ test_entry_guard_parse_from_state_full(void *arg) /* Try again; make sure it doesn't double-add the guards. */ r = entry_guards_parse_state(state, 1, &msg); - tt_assert(r == 0); + tt_int_op(r, OP_EQ, 0); gs_br = get_guard_selection_by_name("bridges", GS_TYPE_BRIDGE, 0); gs_df = get_guard_selection_by_name("default", GS_TYPE_NORMAL, 0); tt_assert(gs_br); @@ -730,7 +740,7 @@ test_entry_guard_parse_from_state_broken(void *arg) MOCK(get_or_state, get_or_state_replacement); - tt_assert(r == 0); + tt_int_op(r, OP_EQ, 0); tt_assert(lines); state->Guard = lines; @@ -742,7 +752,7 @@ test_entry_guard_parse_from_state_broken(void *arg) /* And we shouldn't have made anything. */ guard_selection_t *gs_df = get_guard_selection_by_name("default", GS_TYPE_NORMAL, 0); - tt_assert(gs_df == NULL); + tt_ptr_op(gs_df, OP_EQ, NULL); tor_free(msg); /* Now see about the set case (which shouldn't happen IRL) */ @@ -750,7 +760,7 @@ test_entry_guard_parse_from_state_broken(void *arg) tt_int_op(r, OP_LT, 0); tt_ptr_op(msg, OP_NE, NULL); gs_df = get_guard_selection_by_name("default", GS_TYPE_NORMAL, 0); - tt_assert(gs_df != NULL); + tt_ptr_op(gs_df, OP_NE, NULL); tt_int_op(smartlist_len(gs_df->sampled_entry_guards), OP_EQ, 1); done: @@ -767,26 +777,26 @@ test_entry_guard_get_guard_selection_by_name(void *arg) guard_selection_t *gs1, *gs2, *gs3; gs1 = get_guard_selection_by_name("unlikely", GS_TYPE_NORMAL, 0); - tt_assert(gs1 == NULL); + tt_ptr_op(gs1, OP_EQ, NULL); gs1 = get_guard_selection_by_name("unlikely", GS_TYPE_NORMAL, 1); - tt_assert(gs1 != NULL); + tt_ptr_op(gs1, OP_NE, NULL); gs2 = get_guard_selection_by_name("unlikely", GS_TYPE_NORMAL, 1); tt_assert(gs2 == gs1); gs2 = get_guard_selection_by_name("unlikely", GS_TYPE_NORMAL, 0); tt_assert(gs2 == gs1); gs2 = get_guard_selection_by_name("implausible", GS_TYPE_NORMAL, 0); - tt_assert(gs2 == NULL); + tt_ptr_op(gs2, OP_EQ, NULL); gs2 = get_guard_selection_by_name("implausible", GS_TYPE_NORMAL, 1); - tt_assert(gs2 != NULL); + tt_ptr_op(gs2, OP_NE, NULL); tt_assert(gs2 != gs1); gs3 = get_guard_selection_by_name("implausible", GS_TYPE_NORMAL, 0); tt_assert(gs3 == gs2); gs3 = get_guard_selection_by_name("default", GS_TYPE_NORMAL, 0); - tt_assert(gs3 == NULL); + tt_ptr_op(gs3, OP_EQ, NULL); gs3 = get_guard_selection_by_name("default", GS_TYPE_NORMAL, 1); - tt_assert(gs3 != NULL); + tt_ptr_op(gs3, OP_NE, NULL); tt_assert(gs3 != gs2); tt_assert(gs3 != gs1); tt_assert(gs3 == get_guard_selection_info()); @@ -847,16 +857,16 @@ test_entry_guard_add_single_guard(void *arg) tt_i64_op(g1->sampled_on_date, OP_GE, now - 12*86400); tt_i64_op(g1->sampled_on_date, OP_LE, now); tt_str_op(g1->sampled_by_version, OP_EQ, VERSION); - tt_assert(g1->currently_listed == 1); + tt_uint_op(g1->currently_listed, OP_EQ, 1); tt_i64_op(g1->confirmed_on_date, OP_EQ, 0); tt_int_op(g1->confirmed_idx, OP_EQ, -1); tt_int_op(g1->last_tried_to_connect, OP_EQ, 0); tt_uint_op(g1->is_reachable, OP_EQ, GUARD_REACHABLE_MAYBE); tt_i64_op(g1->failing_since, OP_EQ, 0); - tt_assert(g1->is_filtered_guard == 1); - tt_assert(g1->is_usable_filtered_guard == 1); - tt_assert(g1->is_primary == 0); - tt_assert(g1->extra_state_fields == NULL); + tt_uint_op(g1->is_filtered_guard, OP_EQ, 1); + tt_uint_op(g1->is_usable_filtered_guard, OP_EQ, 1); + tt_uint_op(g1->is_primary, OP_EQ, 0); + tt_ptr_op(g1->extra_state_fields, OP_EQ, NULL); /* Make sure it got added. */ tt_int_op(1, OP_EQ, smartlist_len(gs->sampled_entry_guards)); @@ -886,16 +896,16 @@ test_entry_guard_node_filter(void *arg) g[i] = entry_guard_add_to_sample(gs, n[i]); // everything starts out filtered-in - tt_assert(g[i]->is_filtered_guard == 1); - tt_assert(g[i]->is_usable_filtered_guard == 1); + tt_uint_op(g[i]->is_filtered_guard, OP_EQ, 1); + tt_uint_op(g[i]->is_usable_filtered_guard, OP_EQ, 1); } tt_int_op(num_reachable_filtered_guards(gs, NULL), OP_EQ, NUM); /* Make sure refiltering doesn't hurt */ entry_guards_update_filtered_sets(gs); for (i = 0; i < NUM; ++i) { - tt_assert(g[i]->is_filtered_guard == 1); - tt_assert(g[i]->is_usable_filtered_guard == 1); + tt_uint_op(g[i]->is_filtered_guard, OP_EQ, 1); + tt_uint_op(g[i]->is_usable_filtered_guard, OP_EQ, 1); } tt_int_op(num_reachable_filtered_guards(gs, NULL), OP_EQ, NUM); @@ -917,6 +927,7 @@ test_entry_guard_node_filter(void *arg) routerset_parse(get_options_mutable()->ExcludeNodes, "144.144.0.0/16", ""); /* 4: Bridge. */ + get_options_mutable()->UseBridges = 1; sweep_bridge_list(); bl = tor_malloc_zero(sizeof(bridge_line_t)); tor_addr_from_ipv4h(&bl->addr, n[4]->rs->addr); @@ -924,6 +935,7 @@ test_entry_guard_node_filter(void *arg) memcpy(bl->digest, n[4]->identity, 20); bridge_add_from_config(bl); bl = NULL; // prevent free. + get_options_mutable()->UseBridges = 0; /* 5: Unreachable. This stays in the filter, but isn't in usable-filtered */ g[5]->last_tried_to_connect = approx_time(); // prevent retry. @@ -948,8 +960,8 @@ test_entry_guard_node_filter(void *arg) }); entry_guards_update_filtered_sets(gs); for (i = 0; i < NUM; ++i) { - tt_assert(g[i]->is_filtered_guard == 0); - tt_assert(g[i]->is_usable_filtered_guard == 0); + tt_uint_op(g[i]->is_filtered_guard, OP_EQ, 0); + tt_uint_op(g[i]->is_usable_filtered_guard, OP_EQ, 0); } tt_int_op(num_reachable_filtered_guards(gs, NULL), OP_EQ, 0); @@ -992,7 +1004,7 @@ test_entry_guard_expand_sample(void *arg) // Nothing became unusable/unfiltered, so a subsequent expand should // make no changes. guard = entry_guards_expand_sample(gs); - tt_assert(! guard); // no guard was added. + tt_ptr_op(guard, OP_EQ, NULL); // no guard was added. tt_int_op(DFLT_MIN_FILTERED_SAMPLE_SIZE, OP_EQ, num_reachable_filtered_guards(gs, NULL)); @@ -1016,7 +1028,7 @@ test_entry_guard_expand_sample(void *arg) // Still idempotent. guard = entry_guards_expand_sample(gs); - tt_assert(! guard); // no guard was added. + tt_ptr_op(guard, OP_EQ, NULL); // no guard was added. tt_int_op(DFLT_MIN_FILTERED_SAMPLE_SIZE, OP_EQ, num_reachable_filtered_guards(gs, NULL)); @@ -1526,7 +1538,7 @@ test_entry_guard_retry_unreachable(void *arg) entry_guards_expand_sample(gs); /* Let's say that we have two guards, and they're down. */ - time_t start = approx_time();; + time_t start = approx_time(); entry_guard_t *g1 = smartlist_get(gs->sampled_entry_guards, 0); entry_guard_t *g2 = smartlist_get(gs->sampled_entry_guards, 1); entry_guard_t *g3 = smartlist_get(gs->sampled_entry_guards, 2); @@ -1643,6 +1655,27 @@ test_entry_guard_manage_primary(void *arg) tt_ptr_op(g, OP_EQ, smartlist_get(prev_guards, g_sl_idx)); }); + /* Do some dirinfo checks */ + { + /* Check that we have all required dirinfo for the primaries (that's done + * in big_fake_network_setup()) */ + char *dir_info_str = + guard_selection_get_err_str_if_dir_info_missing(gs, 0, 0, 0); + tt_assert(!dir_info_str); + + /* Now artificially remove the first primary's descriptor and re-check */ + entry_guard_t *first_primary; + first_primary = smartlist_get(gs->primary_entry_guards, 0); + /* Change the first primary's identity digest so that the mocked functions + * can't find its descriptor */ + memset(first_primary->identity, 9, sizeof(first_primary->identity)); + dir_info_str =guard_selection_get_err_str_if_dir_info_missing(gs, 1, 2, 3); + tt_str_op(dir_info_str, OP_EQ, + "We're missing descriptors for 1/2 of our primary entry guards " + "(total microdescriptors: 2/3)."); + tor_free(dir_info_str); + } + done: guard_selection_free(gs); smartlist_free(prev_guards); @@ -1702,6 +1735,7 @@ test_entry_guard_select_for_circuit_no_confirmed(void *arg) /* Simpler cases: no gaurds are confirmed yet. */ (void)arg; guard_selection_t *gs = guard_selection_new("default", GS_TYPE_NORMAL); + entry_guard_restriction_t *rst = NULL; /* simple starting configuration */ entry_guards_update_primary(gs); @@ -1713,7 +1747,7 @@ test_entry_guard_select_for_circuit_no_confirmed(void *arg) tt_assert(g); tt_assert(g->is_primary); tt_int_op(g->confirmed_idx, OP_EQ, -1); - tt_assert(g->is_pending == 0); // primary implies non-pending. + tt_uint_op(g->is_pending, OP_EQ, 0); // primary implies non-pending. tt_uint_op(state, OP_EQ, GUARD_CIRC_STATE_USABLE_ON_COMPLETION); tt_i64_op(g->last_tried_to_connect, OP_EQ, approx_time()); @@ -1733,7 +1767,7 @@ test_entry_guard_select_for_circuit_no_confirmed(void *arg) tt_assert(g2); tt_assert(g2->is_primary); tt_int_op(g2->confirmed_idx, OP_EQ, -1); - tt_assert(g2->is_pending == 0); // primary implies non-pending. + tt_uint_op(g2->is_pending, OP_EQ, 0); // primary implies non-pending. tt_uint_op(state, OP_EQ, GUARD_CIRC_STATE_USABLE_ON_COMPLETION); tt_i64_op(g2->last_tried_to_connect, OP_EQ, approx_time()); @@ -1761,7 +1795,7 @@ test_entry_guard_select_for_circuit_no_confirmed(void *arg) tt_assert(g2); tt_assert(!g2->is_primary); tt_int_op(g2->confirmed_idx, OP_EQ, -1); - tt_assert(g2->is_pending == 1); + tt_uint_op(g2->is_pending, OP_EQ, 1); tt_uint_op(state, OP_EQ, GUARD_CIRC_STATE_USABLE_IF_NO_BETTER_GUARD); tt_i64_op(g2->last_tried_to_connect, OP_EQ, approx_time()); tt_int_op(g2->is_reachable, OP_EQ, GUARD_REACHABLE_MAYBE); @@ -1783,14 +1817,13 @@ test_entry_guard_select_for_circuit_no_confirmed(void *arg) tt_ptr_op(g2, OP_EQ, g); /* But if we impose a restriction, we don't get the same guard */ - entry_guard_restriction_t rst; - memset(&rst, 0, sizeof(rst)); - memcpy(rst.exclude_id, g->identity, DIGEST_LEN); - g2 = select_entry_guard_for_circuit(gs, GUARD_USAGE_TRAFFIC, &rst, &state); + rst = guard_create_exit_restriction((uint8_t*)g->identity); + g2 = select_entry_guard_for_circuit(gs, GUARD_USAGE_TRAFFIC, rst, &state); tt_ptr_op(g2, OP_NE, g); done: guard_selection_free(gs); + entry_guard_restriction_free(rst); } static void @@ -1800,6 +1833,7 @@ test_entry_guard_select_for_circuit_confirmed(void *arg) guards, we use a confirmed guard. */ (void)arg; int i; + entry_guard_restriction_t *rst = NULL; guard_selection_t *gs = guard_selection_new("default", GS_TYPE_NORMAL); const int N_CONFIRMED = 10; @@ -1819,7 +1853,7 @@ test_entry_guard_select_for_circuit_confirmed(void *arg) tt_assert(g); tt_assert(g->is_primary); tt_int_op(g->confirmed_idx, OP_EQ, 0); - tt_assert(g->is_pending == 0); // primary implies non-pending. + tt_uint_op(g->is_pending, OP_EQ, 0); // primary implies non-pending. tt_uint_op(state, OP_EQ, GUARD_CIRC_STATE_USABLE_ON_COMPLETION); tt_i64_op(g->last_tried_to_connect, OP_EQ, approx_time()); tt_ptr_op(g, OP_EQ, smartlist_get(gs->primary_entry_guards, 0)); @@ -1860,10 +1894,8 @@ test_entry_guard_select_for_circuit_confirmed(void *arg) get_options_mutable()->EnforceDistinctSubnets = 0; g = smartlist_get(gs->confirmed_entry_guards, smartlist_len(gs->primary_entry_guards)+2); - entry_guard_restriction_t rst; - memset(&rst, 0, sizeof(rst)); - memcpy(rst.exclude_id, g->identity, DIGEST_LEN); - g2 = select_entry_guard_for_circuit(gs, GUARD_USAGE_TRAFFIC, &rst, &state); + rst = guard_create_exit_restriction((uint8_t*)g->identity); + g2 = select_entry_guard_for_circuit(gs, GUARD_USAGE_TRAFFIC, rst, &state); tt_ptr_op(g2, OP_NE, NULL); tt_ptr_op(g2, OP_NE, g); tt_int_op(g2->confirmed_idx, OP_EQ, @@ -1889,13 +1921,13 @@ test_entry_guard_select_for_circuit_confirmed(void *arg) // Regression test for bug 22753/TROVE-2017-006. get_options_mutable()->EnforceDistinctSubnets = 1; g = smartlist_get(gs->confirmed_entry_guards, 0); - memset(&rst, 0, sizeof(rst)); - memcpy(rst.exclude_id, g->identity, DIGEST_LEN); - g2 = select_entry_guard_for_circuit(gs, GUARD_USAGE_TRAFFIC, &rst, &state); + memcpy(rst->exclude_id, g->identity, DIGEST_LEN); + g2 = select_entry_guard_for_circuit(gs, GUARD_USAGE_TRAFFIC, rst, &state); tt_ptr_op(g2, OP_EQ, NULL); done: guard_selection_free(gs); + entry_guard_restriction_free(rst); } static void @@ -1919,7 +1951,7 @@ test_entry_guard_select_for_circuit_highlevel_primary(void *arg) int r = entry_guard_pick_for_circuit(gs, GUARD_USAGE_TRAFFIC, NULL, &node, &guard); - tt_assert(r == 0); + tt_int_op(r, OP_EQ, 0); tt_assert(node); tt_assert(guard); tt_int_op(guard->state, OP_EQ, GUARD_CIRC_STATE_USABLE_ON_COMPLETION); @@ -1951,7 +1983,7 @@ test_entry_guard_select_for_circuit_highlevel_primary(void *arg) update_approx_time(start+35); r = entry_guard_pick_for_circuit(gs, GUARD_USAGE_TRAFFIC, NULL, &node, &guard); - tt_assert(r == 0); + tt_int_op(r, OP_EQ, 0); tt_assert(node); tt_assert(guard); tt_int_op(guard->state, OP_EQ, GUARD_CIRC_STATE_USABLE_ON_COMPLETION); @@ -1987,7 +2019,7 @@ test_entry_guard_select_for_circuit_highlevel_primary(void *arg) update_approx_time(start+60); r = entry_guard_pick_for_circuit(gs, GUARD_USAGE_TRAFFIC, NULL, &node, &guard); - tt_assert(r == 0); + tt_int_op(r, OP_EQ, 0); tt_assert(node); tt_assert(guard); tt_int_op(guard->state, OP_EQ, GUARD_CIRC_STATE_USABLE_ON_COMPLETION); @@ -2042,7 +2074,7 @@ test_entry_guard_select_for_circuit_highlevel_confirm_other(void *arg) &node, &guard); tt_assert(node); tt_assert(guard); - tt_assert(r == 0); + tt_int_op(r, OP_EQ, 0); tt_int_op(guard->state, OP_EQ, GUARD_CIRC_STATE_USABLE_ON_COMPLETION); entry_guard_failed(&guard); circuit_guard_state_free(guard); @@ -2056,7 +2088,7 @@ test_entry_guard_select_for_circuit_highlevel_confirm_other(void *arg) &node, &guard); tt_assert(node); tt_assert(guard); - tt_assert(r == 0); + tt_int_op(r, OP_EQ, 0); entry_guard_t *g = entry_guard_handle_get(guard->guard); tt_assert(g); tt_int_op(guard->state, OP_EQ, GUARD_CIRC_STATE_USABLE_IF_NO_BETTER_GUARD); @@ -2108,7 +2140,7 @@ test_entry_guard_select_for_circuit_highlevel_primary_retry(void *arg) &node, &guard); tt_assert(node); tt_assert(guard); - tt_assert(r == 0); + tt_int_op(r, OP_EQ, 0); tt_int_op(guard->state, OP_EQ, GUARD_CIRC_STATE_USABLE_ON_COMPLETION); g = entry_guard_handle_get(guard->guard); make_guard_confirmed(gs, g); @@ -2125,7 +2157,7 @@ test_entry_guard_select_for_circuit_highlevel_primary_retry(void *arg) &node, &guard); tt_assert(node); tt_assert(guard); - tt_assert(r == 0); + tt_int_op(r, OP_EQ, 0); tt_int_op(guard->state, OP_EQ, GUARD_CIRC_STATE_USABLE_IF_NO_BETTER_GUARD); g = entry_guard_handle_get(guard->guard); tt_int_op(g->is_primary, OP_EQ, 0); @@ -2151,7 +2183,7 @@ test_entry_guard_select_for_circuit_highlevel_primary_retry(void *arg) /* Have a circuit to a primary guard succeed. */ r = entry_guard_pick_for_circuit(gs, GUARD_USAGE_TRAFFIC, NULL, &node, &guard2); - tt_assert(r == 0); + tt_int_op(r, OP_EQ, 0); tt_int_op(guard2->state, OP_EQ, GUARD_CIRC_STATE_USABLE_ON_COMPLETION); u = entry_guard_succeeded(&guard2); tt_assert(u == GUARD_USABLE_NOW); @@ -2200,7 +2232,7 @@ test_entry_guard_select_and_cancel(void *arg) &node, &guard); tt_assert(node); tt_assert(guard); - tt_assert(r == 0); + tt_int_op(r, OP_EQ, 0); tt_int_op(guard->state, OP_EQ, GUARD_CIRC_STATE_USABLE_IF_NO_BETTER_GUARD); g = entry_guard_handle_get(guard->guard); tt_int_op(g->is_primary, OP_EQ, 0); @@ -2208,7 +2240,7 @@ test_entry_guard_select_and_cancel(void *arg) /* Whoops! We should never have asked for this guard. Cancel the request! */ entry_guard_cancel(&guard); - tt_assert(guard == NULL); + tt_ptr_op(guard, OP_EQ, NULL); tt_int_op(g->is_primary, OP_EQ, 0); tt_int_op(g->is_pending, OP_EQ, 0); @@ -2476,9 +2508,7 @@ test_entry_guard_upgrade_not_blocked_by_restricted_circ_complete(void *arg) /* Once more, let circ1 become complete. But this time, we'll claim * that circ2 was restricted to not use the same guard as circ1. */ data->guard2_state->restrictions = - tor_malloc_zero(sizeof(entry_guard_restriction_t)); - memcpy(data->guard2_state->restrictions->exclude_id, - data->guard1->identity, DIGEST_LEN); + guard_create_exit_restriction((uint8_t*)data->guard1->identity); smartlist_t *result = smartlist_new(); int r; @@ -2587,9 +2617,7 @@ test_entry_guard_upgrade_not_blocked_by_restricted_circ_pending(void *arg) } data->guard2_state->restrictions = - tor_malloc_zero(sizeof(entry_guard_restriction_t)); - memcpy(data->guard2_state->restrictions->exclude_id, - data->guard1->identity, DIGEST_LEN); + guard_create_exit_restriction((uint8_t*)data->guard1->identity); smartlist_t *result = smartlist_new(); int r; @@ -2657,6 +2685,114 @@ test_enty_guard_should_expire_waiting(void *arg) tor_free(fake_state); } +static void +mock_directory_initiate_request(directory_request_t *req) +{ + if (req->guard_state) { + circuit_guard_state_free(req->guard_state); + } +} + +static networkstatus_t *mock_ns_val = NULL; +static networkstatus_t * +mock_ns_get_by_flavor(consensus_flavor_t f) +{ + (void)f; + return mock_ns_val; +} + +/** Test that when we fetch microdescriptors we skip guards that have + * previously failed to serve us needed microdescriptors. */ +static void +test_entry_guard_outdated_dirserver_exclusion(void *arg) +{ + int retval; + response_handler_args_t *args = NULL; + dir_connection_t *conn = NULL; + (void) arg; + + /* Test prep: Make a new guard selection */ + guard_selection_t *gs = get_guard_selection_by_name("default", + GS_TYPE_NORMAL, 1); + + /* ... we want to use entry guards */ + or_options_t *options = get_options_mutable(); + options->UseEntryGuards = 1; + options->UseBridges = 0; + + /* ... prepare some md digests we want to download in the future */ + smartlist_t *digests = smartlist_new(); + const char *prose = "unhurried and wise, we perceive."; + for (int i = 0; i < 20; i++) { + smartlist_add(digests, (char*)prose); + } + + tt_int_op(smartlist_len(digests), OP_EQ, 20); + + /* ... now mock some functions */ + mock_ns_val = tor_malloc_zero(sizeof(networkstatus_t)); + MOCK(networkstatus_get_latest_consensus_by_flavor, mock_ns_get_by_flavor); + MOCK(directory_initiate_request, mock_directory_initiate_request); + + /* Test logic: + * 0. Create a proper guard set and primary guard list. + * 1. Pretend to fail microdescriptor fetches from all the primary guards. + * 2. Order another microdescriptor fetch and make sure that primary guards + * get skipped since they failed previous fetches. + */ + + { /* Setup primary guard list */ + int i; + entry_guards_update_primary(gs); + for (i = 0; i < DFLT_N_PRIMARY_GUARDS; ++i) { + entry_guard_t *guard = smartlist_get(gs->sampled_entry_guards, i); + make_guard_confirmed(gs, guard); + } + entry_guards_update_primary(gs); + } + + { + /* Fail microdesc fetches with all the primary guards */ + args = tor_malloc_zero(sizeof(response_handler_args_t)); + args->status_code = 404; + args->reason = NULL; + args->body = NULL; + args->body_len = 0; + + conn = tor_malloc_zero(sizeof(dir_connection_t)); + conn->requested_resource = tor_strdup("d/jlinblackorigami"); + conn->base_.purpose = DIR_PURPOSE_FETCH_MICRODESC; + + /* Pretend to fail fetches with all primary guards */ + SMARTLIST_FOREACH_BEGIN(gs->primary_entry_guards,const entry_guard_t *,g) { + memcpy(conn->identity_digest, g->identity, DIGEST_LEN); + + retval = handle_response_fetch_microdesc(conn, args); + tt_int_op(retval, OP_EQ, 0); + } SMARTLIST_FOREACH_END(g); + } + + { + /* Now order the final md download */ + setup_full_capture_of_logs(LOG_INFO); + initiate_descriptor_downloads(NULL, DIR_PURPOSE_FETCH_MICRODESC, + digests, 3, 7, 0); + + /* ... and check that because we failed to fetch microdescs from all our + * primaries, we didnt end up selecting a primary for fetching dir info */ + expect_log_msg_containing("No primary or confirmed guards available."); + teardown_capture_of_logs(); + } + + done: + smartlist_free(digests); + tor_free(args); + if (conn) { + tor_free(conn->requested_resource); + tor_free(conn); + } +} + static const struct testcase_setup_t big_fake_network = { big_fake_network_setup, big_fake_network_cleanup }; @@ -2717,6 +2853,7 @@ struct testcase_t entrynodes_tests[] = { BFN_TEST(select_for_circuit_highlevel_primary_retry), BFN_TEST(select_and_cancel), BFN_TEST(drop_guards), + BFN_TEST(outdated_dirserver_exclusion), UPGRADE_TEST(upgrade_a_circuit, "c1-done c2-done"), UPGRADE_TEST(upgrade_blocked_by_live_primary_guards, "c1-done c2-done"), diff --git a/src/test/test_extorport.c b/src/test/test_extorport.c index fc9f27a5ac..e18deb2700 100644 --- a/src/test/test_extorport.c +++ b/src/test/test_extorport.c @@ -78,7 +78,7 @@ connection_write_to_buf_impl_replacement(const char *string, size_t len, tor_assert(string); tor_assert(conn); - write_to_buf(string, len, conn->outbuf); + buf_add(conn->outbuf, string, len); } static char * @@ -89,7 +89,7 @@ buf_get_contents(buf_t *buf, size_t *sz_out) if (*sz_out >= ULONG_MAX) return NULL; /* C'mon, really? */ out = tor_malloc(*sz_out + 1); - if (fetch_from_buf(out, (unsigned long)*sz_out, buf) != 0) { + if (buf_get_bytes(buf, out, (unsigned long)*sz_out) != 0) { tor_free(out); return NULL; } @@ -399,14 +399,14 @@ handshake_start(or_connection_t *conn, int receiving) #define WRITE(s,n) \ do { \ - write_to_buf((s), (n), TO_CONN(conn)->inbuf); \ + buf_add(TO_CONN(conn)->inbuf, (s), (n)); \ } while (0) #define CONTAINS(s,n) \ do { \ tt_int_op((n), OP_LE, sizeof(b)); \ tt_int_op(buf_datalen(TO_CONN(conn)->outbuf), OP_EQ, (n)); \ if ((n)) { \ - fetch_from_buf(b, (n), TO_CONN(conn)->outbuf); \ + buf_get_bytes(TO_CONN(conn)->outbuf, b, (n)); \ tt_mem_op(b, OP_EQ, (s), (n)); \ } \ } while (0) @@ -497,14 +497,14 @@ test_ext_or_handshake(void *arg) "te road There is always another ", 64); /* Send the wrong response. */ WRITE("not with a bang but a whimper...", 32); - MOCK(control_event_bootstrap_problem, ignore_bootstrap_problem); + MOCK(control_event_bootstrap_prob_or, ignore_bootstrap_problem); tt_int_op(-1, OP_EQ, connection_ext_or_process_inbuf(conn)); CONTAINS("\x00", 1); tt_assert(TO_CONN(conn)->marked_for_close); /* XXXX Hold-open-until-flushed. */ close_closeable_connections(); conn = NULL; - UNMOCK(control_event_bootstrap_problem); + UNMOCK(control_event_bootstrap_prob_or); MOCK(connection_start_reading, note_read_started); MOCK(connection_stop_reading, note_read_stopped); @@ -552,26 +552,26 @@ test_ext_or_handshake(void *arg) do_ext_or_handshake(conn); /* USERADDR command with an extra NUL byte */ WRITE("\x00\x01\x00\x0d""1.2.3.4:5678\x00", 17); - MOCK(control_event_bootstrap_problem, ignore_bootstrap_problem); + MOCK(control_event_bootstrap_prob_or, ignore_bootstrap_problem); tt_int_op(-1, OP_EQ, connection_ext_or_process_inbuf(conn)); CONTAINS("", 0); tt_assert(TO_CONN(conn)->marked_for_close); close_closeable_connections(); conn = NULL; - UNMOCK(control_event_bootstrap_problem); + UNMOCK(control_event_bootstrap_prob_or); /* Now fail the TRANSPORT command. */ conn = or_connection_new(CONN_TYPE_EXT_OR, AF_INET); do_ext_or_handshake(conn); /* TRANSPORT command with an extra NUL byte */ WRITE("\x00\x02\x00\x08""rfc1149\x00", 12); - MOCK(control_event_bootstrap_problem, ignore_bootstrap_problem); + MOCK(control_event_bootstrap_prob_or, ignore_bootstrap_problem); tt_int_op(-1, OP_EQ, connection_ext_or_process_inbuf(conn)); CONTAINS("", 0); tt_assert(TO_CONN(conn)->marked_for_close); close_closeable_connections(); conn = NULL; - UNMOCK(control_event_bootstrap_problem); + UNMOCK(control_event_bootstrap_prob_or); /* Now fail the TRANSPORT command. */ conn = or_connection_new(CONN_TYPE_EXT_OR, AF_INET); @@ -579,13 +579,13 @@ test_ext_or_handshake(void *arg) /* TRANSPORT command with transport name with symbols (not a C-identifier) */ WRITE("\x00\x02\x00\x07""rf*1149", 11); - MOCK(control_event_bootstrap_problem, ignore_bootstrap_problem); + MOCK(control_event_bootstrap_prob_or, ignore_bootstrap_problem); tt_int_op(-1, OP_EQ, connection_ext_or_process_inbuf(conn)); CONTAINS("", 0); tt_assert(TO_CONN(conn)->marked_for_close); close_closeable_connections(); conn = NULL; - UNMOCK(control_event_bootstrap_problem); + UNMOCK(control_event_bootstrap_prob_or); done: UNMOCK(connection_write_to_buf_impl_); diff --git a/src/test/test_guardfraction.c b/src/test/test_guardfraction.c index 56006f3cc3..51ca8f08ec 100644 --- a/src/test/test_guardfraction.c +++ b/src/test/test_guardfraction.c @@ -38,10 +38,10 @@ gen_vote_routerstatus_for_tests(const char *digest_in_hex, int is_guard) rs->is_possible_guard = is_guard; /* Fill in the fpr */ - tt_int_op(strlen(digest_in_hex), ==, HEX_DIGEST_LEN); + tt_int_op(strlen(digest_in_hex), OP_EQ, HEX_DIGEST_LEN); retval = base16_decode(digest_tmp, sizeof(digest_tmp), digest_in_hex, HEX_DIGEST_LEN); - tt_int_op(retval, ==, sizeof(digest_tmp)); + tt_int_op(retval, OP_EQ, sizeof(digest_tmp)); memcpy(rs->identity_digest, digest_tmp, DIGEST_LEN); } @@ -88,7 +88,7 @@ test_parse_guardfraction_file_bad(void *arg) yesterday_date_str); retval = dirserv_read_guardfraction_file_from_str(guardfraction_bad, NULL); - tt_int_op(retval, ==, -1); + tt_int_op(retval, OP_EQ, -1); tor_free(guardfraction_bad); /* This one does not have a date! Parsing should fail. */ @@ -100,7 +100,7 @@ test_parse_guardfraction_file_bad(void *arg) "guard-seen 07B5547026DF3E229806E135CFA8552D56AFBABC 5 420\n"); retval = dirserv_read_guardfraction_file_from_str(guardfraction_bad, NULL); - tt_int_op(retval, ==, -1); + tt_int_op(retval, OP_EQ, -1); tor_free(guardfraction_bad); /* This one has an incomplete n-inputs line, but parsing should @@ -114,7 +114,7 @@ test_parse_guardfraction_file_bad(void *arg) yesterday_date_str); retval = dirserv_read_guardfraction_file_from_str(guardfraction_bad, NULL); - tt_int_op(retval, ==, 2); + tt_int_op(retval, OP_EQ, 2); tor_free(guardfraction_bad); /* This one does not have a fingerprint in the guard line! */ @@ -126,7 +126,7 @@ test_parse_guardfraction_file_bad(void *arg) yesterday_date_str); retval = dirserv_read_guardfraction_file_from_str(guardfraction_bad, NULL); - tt_int_op(retval, ==, 0); + tt_int_op(retval, OP_EQ, 0); tor_free(guardfraction_bad); /* This one does not even have an integer guardfraction value. */ @@ -139,7 +139,7 @@ test_parse_guardfraction_file_bad(void *arg) yesterday_date_str); retval = dirserv_read_guardfraction_file_from_str(guardfraction_bad, NULL); - tt_int_op(retval, ==, 1); + tt_int_op(retval, OP_EQ, 1); tor_free(guardfraction_bad); /* This one is not a percentage (not in [0, 100]) */ @@ -152,7 +152,7 @@ test_parse_guardfraction_file_bad(void *arg) yesterday_date_str); retval = dirserv_read_guardfraction_file_from_str(guardfraction_bad, NULL); - tt_int_op(retval, ==, 1); + tt_int_op(retval, OP_EQ, 1); tor_free(guardfraction_bad); /* This one is not a percentage either (not in [0, 100]) */ @@ -164,7 +164,7 @@ test_parse_guardfraction_file_bad(void *arg) yesterday_date_str); retval = dirserv_read_guardfraction_file_from_str(guardfraction_bad, NULL); - tt_int_op(retval, ==, 0); + tt_int_op(retval, OP_EQ, 0); done: tor_free(guardfraction_bad); @@ -216,14 +216,14 @@ test_parse_guardfraction_file_good(void *arg) /* Read the guardfraction file */ retval = dirserv_read_guardfraction_file_from_str(guardfraction_good, routerstatuses); - tt_int_op(retval, ==, 1); + tt_int_op(retval, OP_EQ, 1); { /* Test that routerstatus fields got filled properly */ /* The guardfraction fields of the guard should be filled. */ tt_assert(vrs_guard->status.has_guardfraction); tt_int_op(vrs_guard->status.guardfraction_percentage, - ==, + OP_EQ, guardfraction_value); /* The guard that was not in the guardfraction file should not have @@ -252,12 +252,12 @@ test_get_guardfraction_bandwidth(void *arg) guard_get_guardfraction_bandwidth(&gf_bw, orig_bw, 25); - tt_int_op(gf_bw.guard_bw, ==, 250); - tt_int_op(gf_bw.non_guard_bw, ==, 750); + tt_int_op(gf_bw.guard_bw, OP_EQ, 250); + tt_int_op(gf_bw.non_guard_bw, OP_EQ, 750); /* Also check the 'guard_bw + non_guard_bw == original_bw' * invariant. */ - tt_int_op(gf_bw.non_guard_bw + gf_bw.guard_bw, ==, orig_bw); + tt_int_op(gf_bw.non_guard_bw + gf_bw.guard_bw, OP_EQ, orig_bw); done: ; @@ -295,9 +295,9 @@ test_parse_guardfraction_consensus(void *arg) retval = routerstatus_parse_guardfraction(guardfraction_str_good, NULL, NULL, &rs_good); - tt_int_op(retval, ==, 0); + tt_int_op(retval, OP_EQ, 0); tt_assert(rs_good.has_guardfraction); - tt_int_op(rs_good.guardfraction_percentage, ==, 66); + tt_int_op(rs_good.guardfraction_percentage, OP_EQ, 66); } { /* Properly formatted GuardFraction but router is not a @@ -309,7 +309,7 @@ test_parse_guardfraction_consensus(void *arg) retval = routerstatus_parse_guardfraction(guardfraction_str_good, NULL, NULL, &rs_no_guard); - tt_int_op(retval, ==, 0); + tt_int_op(retval, OP_EQ, 0); tt_assert(!rs_no_guard.has_guardfraction); expect_single_log_msg_containing("Got GuardFraction for non-guard . " "This is not supposed to happen."); @@ -323,7 +323,7 @@ test_parse_guardfraction_consensus(void *arg) retval = routerstatus_parse_guardfraction(guardfraction_str_bad1, NULL, NULL, &rs_bad1); - tt_int_op(retval, ==, -1); + tt_int_op(retval, OP_EQ, -1); tt_assert(!rs_bad1.has_guardfraction); } @@ -334,7 +334,7 @@ test_parse_guardfraction_consensus(void *arg) retval = routerstatus_parse_guardfraction(guardfraction_str_bad2, NULL, NULL, &rs_bad2); - tt_int_op(retval, ==, -1); + tt_int_op(retval, OP_EQ, -1); tt_assert(!rs_bad2.has_guardfraction); } @@ -375,27 +375,27 @@ test_should_apply_guardfraction(void *arg) /* If torrc option is set to yes, we should always use * guardfraction.*/ options->UseGuardFraction = 1; - tt_int_op(should_apply_guardfraction(&vote_disabled), ==, 1); + tt_int_op(should_apply_guardfraction(&vote_disabled), OP_EQ, 1); /* If torrc option is set to no, we should never use * guardfraction.*/ options->UseGuardFraction = 0; - tt_int_op(should_apply_guardfraction(&vote_enabled), ==, 0); + tt_int_op(should_apply_guardfraction(&vote_enabled), OP_EQ, 0); /* Now let's test torrc option set to auto. */ options->UseGuardFraction = -1; /* If torrc option is set to auto, and consensus parameter is set to * yes, we should use guardfraction. */ - tt_int_op(should_apply_guardfraction(&vote_enabled), ==, 1); + tt_int_op(should_apply_guardfraction(&vote_enabled), OP_EQ, 1); /* If torrc option is set to auto, and consensus parameter is set to * no, we should use guardfraction. */ - tt_int_op(should_apply_guardfraction(&vote_disabled), ==, 0); + tt_int_op(should_apply_guardfraction(&vote_disabled), OP_EQ, 0); /* If torrc option is set to auto, and consensus parameter is not * set, we should fallback to "no". */ - tt_int_op(should_apply_guardfraction(&vote_missing), ==, 0); + tt_int_op(should_apply_guardfraction(&vote_missing), OP_EQ, 0); done: SMARTLIST_FOREACH(vote_enabled.net_params, char *, cp, tor_free(cp)); diff --git a/src/test/test_helpers.c b/src/test/test_helpers.c index 9fada5a675..0da9cf64d0 100644 --- a/src/test/test_helpers.c +++ b/src/test/test_helpers.c @@ -7,16 +7,25 @@ */ #define ROUTERLIST_PRIVATE +#define CONFIG_PRIVATE +#define CONNECTION_PRIVATE +#define MAIN_PRIVATE + #include "orconfig.h" #include "or.h" +#include "buffers.h" +#include "config.h" +#include "confparse.h" +#include "connection.h" +#include "main.h" +#include "nodelist.h" #include "relay.h" #include "routerlist.h" -#include "nodelist.h" -#include "buffers.h" #include "test.h" #include "test_helpers.h" +#include "test_connection.h" #ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS DISABLE_GCC_WARNING(overlength-strings) @@ -74,16 +83,16 @@ helper_setup_fake_routerlist(void) retval = router_load_routers_from_string(TEST_DESCRIPTORS, NULL, SAVED_IN_JOURNAL, NULL, 0, NULL); - tt_int_op(retval, ==, HELPER_NUMBER_OF_DESCRIPTORS); + tt_int_op(retval, OP_EQ, HELPER_NUMBER_OF_DESCRIPTORS); /* Sanity checking of routerlist and nodelist. */ our_routerlist = router_get_routerlist(); - tt_int_op(smartlist_len(our_routerlist->routers), ==, + tt_int_op(smartlist_len(our_routerlist->routers), OP_EQ, HELPER_NUMBER_OF_DESCRIPTORS); routerlist_assert_ok(our_routerlist); our_nodelist = nodelist_get_list(); - tt_int_op(smartlist_len(our_nodelist), ==, HELPER_NUMBER_OF_DESCRIPTORS); + tt_int_op(smartlist_len(our_nodelist), OP_EQ, HELPER_NUMBER_OF_DESCRIPTORS); /* Mark all routers as non-guards but up and running! */ SMARTLIST_FOREACH_BEGIN(our_nodelist, node_t *, node) { @@ -105,7 +114,7 @@ connection_write_to_buf_mock(const char *string, size_t len, tor_assert(string); tor_assert(conn); - write_to_buf(string, len, conn->outbuf); + buf_add(conn->outbuf, string, len); } /* Set up a fake origin circuit with the specified number of cells, @@ -143,3 +152,128 @@ mock_tor_addr_lookup__fail_on_bad_addrs(const char *name, return tor_addr_lookup__real(name, family, out); } +/*********** Helper funcs for making new connections/streams *****************/ + +/* Helper for test_conn_get_connection() */ +static int +fake_close_socket(evutil_socket_t sock) +{ + (void)sock; + return 0; +} + +static int mock_connection_connect_sockaddr_called = 0; +static int fake_socket_number = TEST_CONN_FD_INIT; + +/* Helper for test_conn_get_connection() */ +static int +mock_connection_connect_sockaddr(connection_t *conn, + const struct sockaddr *sa, + socklen_t sa_len, + const struct sockaddr *bindaddr, + socklen_t bindaddr_len, + int *socket_error) +{ + (void)sa_len; + (void)bindaddr; + (void)bindaddr_len; + + tor_assert(conn); + tor_assert(sa); + tor_assert(socket_error); + + mock_connection_connect_sockaddr_called++; + + conn->s = fake_socket_number++; + tt_assert(SOCKET_OK(conn->s)); + /* We really should call tor_libevent_initialize() here. Because we don't, + * we are relying on other parts of the code not checking if the_event_base + * (and therefore event->ev_base) is NULL. */ + tt_int_op(connection_add_connecting(conn), OP_EQ, 0); + + done: + /* Fake "connected" status */ + return 1; +} + +/** Create and return a new connection/stream */ +connection_t * +test_conn_get_connection(uint8_t state, uint8_t type, uint8_t purpose) +{ + connection_t *conn = NULL; + tor_addr_t addr; + int socket_err = 0; + int in_progress = 0; + + MOCK(connection_connect_sockaddr, + mock_connection_connect_sockaddr); + MOCK(tor_close_socket, fake_close_socket); + + init_connection_lists(); + + conn = connection_new(type, TEST_CONN_FAMILY); + tt_assert(conn); + + test_conn_lookup_addr_helper(TEST_CONN_ADDRESS, TEST_CONN_FAMILY, &addr); + tt_assert(!tor_addr_is_null(&addr)); + + tor_addr_copy_tight(&conn->addr, &addr); + conn->port = TEST_CONN_PORT; + mock_connection_connect_sockaddr_called = 0; + in_progress = connection_connect(conn, TEST_CONN_ADDRESS_PORT, &addr, + TEST_CONN_PORT, &socket_err); + tt_int_op(mock_connection_connect_sockaddr_called, OP_EQ, 1); + tt_assert(!socket_err); + tt_assert(in_progress == 0 || in_progress == 1); + + /* fake some of the attributes so the connection looks OK */ + conn->state = state; + conn->purpose = purpose; + assert_connection_ok(conn, time(NULL)); + + UNMOCK(connection_connect_sockaddr); + UNMOCK(tor_close_socket); + return conn; + + /* On failure */ + done: + UNMOCK(connection_connect_sockaddr); + UNMOCK(tor_close_socket); + return NULL; +} + +/* Helper function to parse a set of torrc options in a text format and return + * a newly allocated or_options_t object containing the configuration. On + * error, NULL is returned indicating that the conf couldn't be parsed + * properly. */ +or_options_t * +helper_parse_options(const char *conf) +{ + int ret = 0; + char *msg = NULL; + or_options_t *opt = NULL; + config_line_t *line = NULL; + + /* Kind of pointless to call this with a NULL value. */ + tt_assert(conf); + + opt = options_new(); + tt_assert(opt); + ret = config_get_lines(conf, &line, 1); + if (ret != 0) { + goto done; + } + ret = config_assign(&options_format, opt, line, 0, &msg); + if (ret != 0) { + goto done; + } + + done: + config_free_lines(line); + if (ret != 0) { + or_options_free(opt); + opt = NULL; + } + return opt; +} + diff --git a/src/test/test_helpers.h b/src/test/test_helpers.h index 4621631cc1..9bc8553257 100644 --- a/src/test/test_helpers.h +++ b/src/test/test_helpers.h @@ -1,9 +1,11 @@ -/* Copyright (c) 2014-2017, The Tor Project, Inc. */ +/* Copyright (c) 2017, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #ifndef TOR_TEST_HELPERS_H #define TOR_TEST_HELPERS_H +#include "or.h" + const char *get_yesterday_date_str(void); circuit_t * dummy_origin_circuit_new(int num_cells); @@ -20,7 +22,11 @@ void connection_write_to_buf_mock(const char *string, size_t len, int mock_tor_addr_lookup__fail_on_bad_addrs(const char *name, uint16_t family, tor_addr_t *out); +connection_t *test_conn_get_connection(uint8_t state, + uint8_t type, uint8_t purpose); +or_options_t *helper_parse_options(const char *conf); + extern const char TEST_DESCRIPTORS[]; -#endif +#endif /* !defined(TOR_TEST_HELPERS_H) */ diff --git a/src/test/test_hs.c b/src/test/test_hs.c index 5aae6c5b97..09db176df8 100644 --- a/src/test/test_hs.c +++ b/src/test/test_hs.c @@ -8,7 +8,9 @@ #define CONTROL_PRIVATE #define CIRCUITBUILD_PRIVATE +#define RENDCOMMON_PRIVATE #define RENDSERVICE_PRIVATE +#define HS_SERVICE_PRIVATE #include "or.h" #include "test.h" @@ -32,8 +34,9 @@ #define STR_HSDIR_NONE_EXIST_LONGNAME \ "$BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" -/* DuckDuckGo descriptor as an example. */ -static const char *hs_desc_content = "\ +/* DuckDuckGo descriptor as an example. This one has extra "\r" at the end so + * the control port is happy. */ +static const char *hs_desc_content_control = "\ rendezvous-service-descriptor g5ojobzupf275beh5ra72uyhb3dkpxwg\r\n\ version 2\r\n\ permanent-key\r\n\ @@ -94,6 +97,68 @@ PcftsZf2ztN0sbNCtPgDL3d0PqvxY3iHTQAI8EbaGq/IAJUZ8U4y963dD5+Bn6JQ\r\n\ myE3ctmh0vy5+QxSiRjmQBkuEpCyks7LvWvHYrhnmcg=\r\n\ -----END SIGNATURE-----"; +/* DuckDuckGo descriptor as an example. */ +static const char *hs_desc_content = "\ +rendezvous-service-descriptor g5ojobzupf275beh5ra72uyhb3dkpxwg\n\ +version 2\n\ +permanent-key\n\ +-----BEGIN RSA PUBLIC KEY-----\n\ +MIGJAoGBAJ/SzzgrXPxTlFrKVhXh3buCWv2QfcNgncUpDpKouLn3AtPH5Ocys0jE\n\ +aZSKdvaiQ62md2gOwj4x61cFNdi05tdQjS+2thHKEm/KsB9BGLSLBNJYY356bupg\n\ +I5gQozM65ENelfxYlysBjJ52xSDBd8C4f/p9umdzaaaCmzXG/nhzAgMBAAE=\n\ +-----END RSA PUBLIC KEY-----\n\ +secret-id-part anmjoxxwiupreyajjt5yasimfmwcnxlf\n\ +publication-time 2015-03-11 19:00:00\n\ +protocol-versions 2,3\n\ +introduction-points\n\ +-----BEGIN MESSAGE-----\n\ +aW50cm9kdWN0aW9uLXBvaW50IDd1bnd4cmg2dG5kNGh6eWt1Z3EzaGZzdHduc2ll\n\ +cmhyCmlwLWFkZHJlc3MgMTg4LjEzOC4xMjEuMTE4Cm9uaW9uLXBvcnQgOTAwMQpv\n\ +bmlvbi1rZXkKLS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JR0pBb0dC\n\ +QUxGRVVyeVpDbk9ROEhURmV5cDVjMTRObWVqL1BhekFLTTBxRENTNElKUWh0Y3g1\n\ +NXpRSFdOVWIKQ2hHZ0JqR1RjV3ZGRnA0N3FkdGF6WUZhVXE2c0lQKzVqeWZ5b0Q4\n\ +UmJ1bzBwQmFWclJjMmNhYUptWWM0RDh6Vgpuby9sZnhzOVVaQnZ1cWY4eHIrMDB2\n\ +S0JJNmFSMlA2OE1WeDhrMExqcUpUU2RKOE9idm9yQWdNQkFBRT0KLS0tLS1FTkQg\n\ +UlNBIFBVQkxJQyBLRVktLS0tLQpzZXJ2aWNlLWtleQotLS0tLUJFR0lOIFJTQSBQ\n\ +VUJMSUMgS0VZLS0tLS0KTUlHSkFvR0JBTnJHb0ozeTlHNXQzN2F2ekI1cTlwN1hG\n\ +VUplRUVYMUNOaExnWmJXWGJhVk5OcXpoZFhyL0xTUQppM1Z6dW5OaUs3cndUVnE2\n\ +K2QyZ1lRckhMMmIvMXBBY3ZKWjJiNSs0bTRRc0NibFpjRENXTktRbHJnRWN5WXRJ\n\ +CkdscXJTbFFEaXA0ZnNrUFMvNDVkWTI0QmJsQ3NGU1k3RzVLVkxJck4zZFpGbmJr\n\ +NEZIS1hBZ01CQUFFPQotLS0tLUVORCBSU0EgUFVCTElDIEtFWS0tLS0tCmludHJv\n\ +ZHVjdGlvbi1wb2ludCBiNGM3enlxNXNheGZzN2prNXFibG1wN3I1b3pwdHRvagpp\n\ +cC1hZGRyZXNzIDEwOS4xNjkuNDUuMjI2Cm9uaW9uLXBvcnQgOTAwMQpvbmlvbi1r\n\ +ZXkKLS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JR0pBb0dCQU8xSXpw\n\ +WFFUTUY3RXZUb1NEUXpzVnZiRVFRQUQrcGZ6NzczMVRXZzVaUEJZY1EyUkRaeVp4\n\ +OEQKNUVQSU1FeUE1RE83cGd0ak5LaXJvYXJGMC8yempjMkRXTUlSaXZyU29YUWVZ\n\ +ZXlMM1pzKzFIajJhMDlCdkYxZAp6MEswblRFdVhoNVR5V3lyMHdsbGI1SFBnTlI0\n\ +MS9oYkprZzkwZitPVCtIeGhKL1duUml2QWdNQkFBRT0KLS0tLS1FTkQgUlNBIFBV\n\ +QkxJQyBLRVktLS0tLQpzZXJ2aWNlLWtleQotLS0tLUJFR0lOIFJTQSBQVUJMSUMg\n\ +S0VZLS0tLS0KTUlHSkFvR0JBSzNWZEJ2ajFtQllLL3JrcHNwcm9Ub0llNUtHVmth\n\ +QkxvMW1tK1I2YUVJek1VZFE1SjkwNGtyRwpCd3k5NC8rV0lGNFpGYXh5Z2phejl1\n\ +N2pKY1k3ZGJhd1pFeG1hYXFCRlRwL2h2ZG9rcHQ4a1ByRVk4OTJPRHJ1CmJORUox\n\ +N1FPSmVMTVZZZk5Kcjl4TWZCQ3JQai8zOGh2RUdrbWVRNmRVWElvbVFNaUJGOVRB\n\ +Z01CQUFFPQotLS0tLUVORCBSU0EgUFVCTElDIEtFWS0tLS0tCmludHJvZHVjdGlv\n\ +bi1wb2ludCBhdjVtcWl0Y2Q3cjJkandsYmN0c2Jlc2R3eGt0ZWtvegppcC1hZGRy\n\ +ZXNzIDE0NC43Ni44LjczCm9uaW9uLXBvcnQgNDQzCm9uaW9uLWtleQotLS0tLUJF\n\ +R0lOIFJTQSBQVUJMSUMgS0VZLS0tLS0KTUlHSkFvR0JBTzVweVZzQmpZQmNmMXBE\n\ +dklHUlpmWXUzQ05nNldka0ZLMGlvdTBXTGZtejZRVDN0NWhzd3cyVwpjejlHMXhx\n\ +MmN0Nkd6VWkrNnVkTDlITTRVOUdHTi9BbW8wRG9GV1hKWHpBQkFXd2YyMVdsd1lW\n\ +eFJQMHRydi9WCkN6UDkzcHc5OG5vSmdGUGRUZ05iMjdKYmVUZENLVFBrTEtscXFt\n\ +b3NveUN2RitRa25vUS9BZ01CQUFFPQotLS0tLUVORCBSU0EgUFVCTElDIEtFWS0t\n\ +LS0tCnNlcnZpY2Uta2V5Ci0tLS0tQkVHSU4gUlNBIFBVQkxJQyBLRVktLS0tLQpN\n\ +SUdKQW9HQkFMVjNKSmtWN3lTNU9jc1lHMHNFYzFQOTVRclFRR3ZzbGJ6Wi9zRGxl\n\ +RlpKYXFSOUYvYjRUVERNClNGcFMxcU1GbldkZDgxVmRGMEdYRmN2WVpLamRJdHU2\n\ +SndBaTRJeEhxeXZtdTRKdUxrcXNaTEFLaXRLVkx4eGsKeERlMjlDNzRWMmJrOTRJ\n\ +MEgybTNKS2tzTHVwc3VxWWRVUmhOVXN0SElKZmgyZmNIalF0bEFnTUJBQUU9Ci0t\n\ +LS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0KCg==\n\ +-----END MESSAGE-----\n\ +signature\n\ +-----BEGIN SIGNATURE-----\n\ +d4OuCE5OLAOnRB6cQN6WyMEmg/BHem144Vec+eYgeWoKwx3MxXFplUjFxgnMlmwN\n\ +PcftsZf2ztN0sbNCtPgDL3d0PqvxY3iHTQAI8EbaGq/IAJUZ8U4y963dD5+Bn6JQ\n\ +myE3ctmh0vy5+QxSiRjmQBkuEpCyks7LvWvHYrhnmcg=\n\ +-----END SIGNATURE-----"; + /* Helper global variable for hidden service descriptor event test. * It's used as a pointer to dynamically created message buffer in * send_control_event_string_replacement function, which mocks @@ -125,6 +190,30 @@ node_describe_longname_by_id_replacement(const char *id_digest) } } +/** Test that we can parse a hardcoded v2 HS desc. */ +static void +test_hs_parse_static_v2_desc(void *arg) +{ + int ret; + rend_encoded_v2_service_descriptor_t desc; + + (void) arg; + + /* Test an obviously not parseable string */ + desc.desc_str = tor_strdup("ceci n'est pas un HS descriptor"); + ret = rend_desc_v2_is_parsable(&desc); + tor_free(desc.desc_str); + tt_int_op(ret, OP_EQ, 0); + + /* Test an actual descriptor */ + desc.desc_str = tor_strdup(hs_desc_content); + ret = rend_desc_v2_is_parsable(&desc); + tor_free(desc.desc_str); + tt_int_op(ret, OP_EQ, 1); + + done: ; +} + /** Make sure each hidden service descriptor async event generation * * function generates the message in expected format. @@ -161,7 +250,7 @@ test_hs_desc_event(void *arg) ret = rend_compute_v2_desc_id(rend_query.descriptor_id[0], rend_query.onion_address, NULL, 0, 0); - tt_int_op(ret, ==, 0); + tt_int_op(ret, OP_EQ, 0); base32_encode(desc_id_base32, sizeof(desc_id_base32), rend_query.descriptor_id[0], DIGEST_LEN); /* Make sure rend_compute_v2_desc_id works properly. */ @@ -235,10 +324,10 @@ test_hs_desc_event(void *arg) /* test valid content. */ control_event_hs_descriptor_content(rend_query.onion_address, STR_HS_CONTENT_DESC_ID, HSDIR_EXIST_ID, - hs_desc_content); + hs_desc_content_control); tor_asprintf(&exp_msg, "650+HS_DESC_CONTENT " STR_HS_ADDR " "\ STR_HS_CONTENT_DESC_ID " " STR_HSDIR_EXIST_LONGNAME\ - "\r\n%s\r\n.\r\n650 OK\r\n", hs_desc_content); + "\r\n%s\r\n.\r\n650 OK\r\n", hs_desc_content_control); tt_assert(received_msg); tt_str_op(received_msg, OP_EQ, exp_msg); @@ -274,14 +363,14 @@ test_pick_tor2web_rendezvous_node(void *arg) retval = routerset_parse(options->Tor2webRendezvousPoints, tor2web_rendezvous_str, "test_tor2web_rp"); - tt_int_op(retval, >=, 0); + tt_int_op(retval, OP_GE, 0); /* Pick rendezvous point. Make sure the correct one is picked. Repeat many times to make sure it works properly. */ for (i = 0; i < 50 ; i++) { chosen_rp = pick_tor2web_rendezvous_node(flags, options); tt_assert(chosen_rp); - tt_str_op(chosen_rp->ri->nickname, ==, tor2web_rendezvous_str); + tt_str_op(chosen_rp->ri->nickname, OP_EQ, tor2web_rendezvous_str); } done: @@ -309,13 +398,13 @@ test_pick_bad_tor2web_rendezvous_node(void *arg) retval = routerset_parse(options->Tor2webRendezvousPoints, tor2web_rendezvous_str, "test_tor2web_rp"); - tt_int_op(retval, >=, 0); + tt_int_op(retval, OP_GE, 0); /* Pick rendezvous point. Since Tor2webRendezvousPoints was set to a dummy value, we shouldn't find any eligible RPs. */ for (i = 0; i < 50 ; i++) { chosen_rp = pick_tor2web_rendezvous_node(flags, options); - tt_assert(!chosen_rp); + tt_ptr_op(chosen_rp, OP_EQ, NULL); } done: @@ -346,30 +435,30 @@ test_hs_rend_data(void *arg) REND_NO_AUTH); tt_assert(client); rend_data_v2_t *client_v2 = TO_REND_DATA_V2(client); - tt_int_op(client_v2->auth_type, ==, REND_NO_AUTH); + tt_int_op(client_v2->auth_type, OP_EQ, REND_NO_AUTH); tt_str_op(client_v2->onion_address, OP_EQ, STR_HS_ADDR); tt_mem_op(client_v2->desc_id_fetch, OP_EQ, desc_id, sizeof(desc_id)); tt_mem_op(client_v2->descriptor_cookie, OP_EQ, client_cookie, sizeof(client_cookie)); tt_assert(client->hsdirs_fp); - tt_int_op(smartlist_len(client->hsdirs_fp), ==, 0); + tt_int_op(smartlist_len(client->hsdirs_fp), OP_EQ, 0); for (rep = 0; rep < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; rep++) { int ret = rend_compute_v2_desc_id(desc_id, client_v2->onion_address, client_v2->descriptor_cookie, now, rep); /* That shouldn't never fail. */ - tt_int_op(ret, ==, 0); + tt_int_op(ret, OP_EQ, 0); tt_mem_op(client_v2->descriptor_id[rep], OP_EQ, desc_id, sizeof(desc_id)); } /* The rest should be zeroed because this is a client request. */ - tt_int_op(tor_digest_is_zero(client_v2->rend_pk_digest), ==, 1); - tt_int_op(tor_digest_is_zero(client->rend_cookie), ==, 1); + tt_int_op(tor_digest_is_zero(client_v2->rend_pk_digest), OP_EQ, 1); + tt_int_op(tor_digest_is_zero(client->rend_cookie), OP_EQ, 1); /* Test dup(). */ client_dup = rend_data_dup(client); tt_assert(client_dup); rend_data_v2_t *client_dup_v2 = TO_REND_DATA_V2(client_dup); - tt_int_op(client_dup_v2->auth_type, ==, client_v2->auth_type); + tt_int_op(client_dup_v2->auth_type, OP_EQ, client_v2->auth_type); tt_str_op(client_dup_v2->onion_address, OP_EQ, client_v2->onion_address); tt_mem_op(client_dup_v2->desc_id_fetch, OP_EQ, client_v2->desc_id_fetch, sizeof(client_dup_v2->desc_id_fetch)); @@ -378,14 +467,14 @@ test_hs_rend_data(void *arg) sizeof(client_dup_v2->descriptor_cookie)); tt_assert(client_dup->hsdirs_fp); - tt_int_op(smartlist_len(client_dup->hsdirs_fp), ==, 0); + tt_int_op(smartlist_len(client_dup->hsdirs_fp), OP_EQ, 0); for (rep = 0; rep < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; rep++) { tt_mem_op(client_dup_v2->descriptor_id[rep], OP_EQ, client_v2->descriptor_id[rep], DIGEST_LEN); } /* The rest should be zeroed because this is a client request. */ - tt_int_op(tor_digest_is_zero(client_dup_v2->rend_pk_digest), ==, 1); - tt_int_op(tor_digest_is_zero(client_dup->rend_cookie), ==, 1); + tt_int_op(tor_digest_is_zero(client_dup_v2->rend_pk_digest), OP_EQ, 1); + tt_int_op(tor_digest_is_zero(client_dup->rend_cookie), OP_EQ, 1); rend_data_free(client); client = NULL; rend_data_free(client_dup); @@ -401,19 +490,19 @@ test_hs_rend_data(void *arg) client = rend_data_client_create(NULL, desc_id, NULL, REND_BASIC_AUTH); tt_assert(client); client_v2 = TO_REND_DATA_V2(client); - tt_int_op(client_v2->auth_type, ==, REND_BASIC_AUTH); - tt_int_op(strlen(client_v2->onion_address), ==, 0); + tt_int_op(client_v2->auth_type, OP_EQ, REND_BASIC_AUTH); + tt_int_op(strlen(client_v2->onion_address), OP_EQ, 0); tt_mem_op(client_v2->desc_id_fetch, OP_EQ, desc_id, sizeof(desc_id)); tt_int_op(tor_mem_is_zero(client_v2->descriptor_cookie, - sizeof(client_v2->descriptor_cookie)), ==, 1); + sizeof(client_v2->descriptor_cookie)), OP_EQ, 1); tt_assert(client->hsdirs_fp); - tt_int_op(smartlist_len(client->hsdirs_fp), ==, 0); + tt_int_op(smartlist_len(client->hsdirs_fp), OP_EQ, 0); for (rep = 0; rep < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; rep++) { - tt_int_op(tor_digest_is_zero(client_v2->descriptor_id[rep]), ==, 1); + tt_int_op(tor_digest_is_zero(client_v2->descriptor_id[rep]), OP_EQ, 1); } /* The rest should be zeroed because this is a client request. */ - tt_int_op(tor_digest_is_zero(client_v2->rend_pk_digest), ==, 1); - tt_int_op(tor_digest_is_zero(client->rend_cookie), ==, 1); + tt_int_op(tor_digest_is_zero(client_v2->rend_pk_digest), OP_EQ, 1); + tt_int_op(tor_digest_is_zero(client->rend_cookie), OP_EQ, 1); rend_data_free(client); client = NULL; @@ -427,38 +516,38 @@ test_hs_rend_data(void *arg) rend_cookie, REND_NO_AUTH); tt_assert(service); rend_data_v2_t *service_v2 = TO_REND_DATA_V2(service); - tt_int_op(service_v2->auth_type, ==, REND_NO_AUTH); + tt_int_op(service_v2->auth_type, OP_EQ, REND_NO_AUTH); tt_str_op(service_v2->onion_address, OP_EQ, STR_HS_ADDR); tt_mem_op(service_v2->rend_pk_digest, OP_EQ, rend_pk_digest, sizeof(rend_pk_digest)); tt_mem_op(service->rend_cookie, OP_EQ, rend_cookie, sizeof(rend_cookie)); tt_assert(service->hsdirs_fp); - tt_int_op(smartlist_len(service->hsdirs_fp), ==, 0); + tt_int_op(smartlist_len(service->hsdirs_fp), OP_EQ, 0); for (rep = 0; rep < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; rep++) { - tt_int_op(tor_digest_is_zero(service_v2->descriptor_id[rep]), ==, 1); + tt_int_op(tor_digest_is_zero(service_v2->descriptor_id[rep]), OP_EQ, 1); } /* The rest should be zeroed because this is a service request. */ - tt_int_op(tor_digest_is_zero(service_v2->descriptor_cookie), ==, 1); - tt_int_op(tor_digest_is_zero(service_v2->desc_id_fetch), ==, 1); + tt_int_op(tor_digest_is_zero(service_v2->descriptor_cookie), OP_EQ, 1); + tt_int_op(tor_digest_is_zero(service_v2->desc_id_fetch), OP_EQ, 1); /* Test dup(). */ service_dup = rend_data_dup(service); rend_data_v2_t *service_dup_v2 = TO_REND_DATA_V2(service_dup); tt_assert(service_dup); - tt_int_op(service_dup_v2->auth_type, ==, service_v2->auth_type); + tt_int_op(service_dup_v2->auth_type, OP_EQ, service_v2->auth_type); tt_str_op(service_dup_v2->onion_address, OP_EQ, service_v2->onion_address); tt_mem_op(service_dup_v2->rend_pk_digest, OP_EQ, service_v2->rend_pk_digest, sizeof(service_dup_v2->rend_pk_digest)); tt_mem_op(service_dup->rend_cookie, OP_EQ, service->rend_cookie, sizeof(service_dup->rend_cookie)); tt_assert(service_dup->hsdirs_fp); - tt_int_op(smartlist_len(service_dup->hsdirs_fp), ==, 0); + tt_int_op(smartlist_len(service_dup->hsdirs_fp), OP_EQ, 0); for (rep = 0; rep < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; rep++) { - tt_int_op(tor_digest_is_zero(service_dup_v2->descriptor_id[rep]), ==, 1); + tt_assert(tor_digest_is_zero(service_dup_v2->descriptor_id[rep])); } /* The rest should be zeroed because this is a service request. */ - tt_int_op(tor_digest_is_zero(service_dup_v2->descriptor_cookie), ==, 1); - tt_int_op(tor_digest_is_zero(service_dup_v2->desc_id_fetch), ==, 1); + tt_int_op(tor_digest_is_zero(service_dup_v2->descriptor_cookie), OP_EQ, 1); + tt_int_op(tor_digest_is_zero(service_dup_v2->desc_id_fetch), OP_EQ, 1); done: rend_data_free(service); @@ -476,10 +565,10 @@ test_hs_auth_cookies(void *arg) #define TEST_COOKIE_ENCODED_STEALTH "YWJjZGVmZ2hpamtsbW5vcB" #define TEST_COOKIE_ENCODED_INVALID "YWJjZGVmZ2hpamtsbW5vcD" - char *encoded_cookie; + char *encoded_cookie = NULL; uint8_t raw_cookie[REND_DESC_COOKIE_LEN]; rend_auth_type_t auth_type; - char *err_msg; + char *err_msg = NULL; int re; (void)arg; @@ -497,7 +586,7 @@ test_hs_auth_cookies(void *arg) re = rend_auth_decode_cookie(TEST_COOKIE_ENCODED, raw_cookie, &auth_type, &err_msg); tt_assert(!re); - tt_assert(!err_msg); + tt_ptr_op(err_msg, OP_EQ, NULL); tt_mem_op(raw_cookie, OP_EQ, TEST_COOKIE_RAW, REND_DESC_COOKIE_LEN); tt_int_op(auth_type, OP_EQ, REND_BASIC_AUTH); memset(raw_cookie, 0, sizeof(raw_cookie)); @@ -505,7 +594,7 @@ test_hs_auth_cookies(void *arg) re = rend_auth_decode_cookie(TEST_COOKIE_ENCODED_STEALTH, raw_cookie, &auth_type, &err_msg); tt_assert(!re); - tt_assert(!err_msg); + tt_ptr_op(err_msg, OP_EQ, NULL); tt_mem_op(raw_cookie, OP_EQ, TEST_COOKIE_RAW, REND_DESC_COOKIE_LEN); tt_int_op(auth_type, OP_EQ, REND_STEALTH_AUTH); memset(raw_cookie, 0, sizeof(raw_cookie)); @@ -514,7 +603,7 @@ test_hs_auth_cookies(void *arg) re = rend_auth_decode_cookie(TEST_COOKIE_ENCODED "==", raw_cookie, NULL, &err_msg); tt_assert(!re); - tt_assert(!err_msg); + tt_ptr_op(err_msg, OP_EQ, NULL); tt_mem_op(raw_cookie, OP_EQ, TEST_COOKIE_RAW, REND_DESC_COOKIE_LEN); /* Decoding with an unknown type should fail */ @@ -525,6 +614,9 @@ test_hs_auth_cookies(void *arg) tor_free(err_msg); done: + tor_free(encoded_cookie); + tor_free(err_msg); + return; } @@ -574,31 +666,22 @@ test_single_onion_poisoning(void *arg) char *poison_path = NULL; char *err_msg = NULL; - /* No services, no service to verify, no problem! */ - mock_options->HiddenServiceSingleHopMode = 0; - mock_options->HiddenServiceNonAnonymousMode = 0; - ret = rend_config_services(mock_options, 1); - tt_assert(ret == 0); - - /* Either way, no problem. */ mock_options->HiddenServiceSingleHopMode = 1; mock_options->HiddenServiceNonAnonymousMode = 1; - ret = rend_config_services(mock_options, 1); - tt_assert(ret == 0); /* Create the data directory, and, if the correct bit in arg is set, * create a directory for that service. * The data directory is required for the lockfile, which is used when * loading keys. */ ret = check_private_dir(mock_options->DataDirectory, CPD_CREATE, NULL); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); if (create_dir_mask & CREATE_HS_DIR1) { ret = check_private_dir(dir1, CPD_CREATE, NULL); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); } if (create_dir_mask & CREATE_HS_DIR2) { ret = check_private_dir(dir2, CPD_CREATE, NULL); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); } service_1->directory = dir1; @@ -611,190 +694,194 @@ test_single_onion_poisoning(void *arg) rend_service_port_config_t *port1 = rend_service_parse_port_config("80", " ", &err_msg); tt_assert(port1); - tt_assert(!err_msg); + tt_ptr_op(err_msg, OP_EQ, NULL); smartlist_add(service_1->ports, port1); rend_service_port_config_t *port2 = rend_service_parse_port_config("90", " ", &err_msg); /* Add port to service 2 */ tt_assert(port2); - tt_assert(!err_msg); + tt_ptr_op(err_msg, OP_EQ, NULL); smartlist_add(service_2->ports, port2); /* No services, a service to verify, no problem! */ mock_options->HiddenServiceSingleHopMode = 0; mock_options->HiddenServiceNonAnonymousMode = 0; ret = rend_service_verify_single_onion_poison(service_1, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); ret = rend_service_verify_single_onion_poison(service_2, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); /* Either way, no problem. */ mock_options->HiddenServiceSingleHopMode = 1; mock_options->HiddenServiceNonAnonymousMode = 1; ret = rend_service_verify_single_onion_poison(service_1, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); ret = rend_service_verify_single_onion_poison(service_2, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); /* Add the first service */ - ret = rend_service_check_dir_and_add(services, mock_options, service_1, 0); - tt_assert(ret == 0); + ret = hs_check_service_private_dir(mock_options->User, service_1->directory, + service_1->dir_group_readable, 1); + tt_int_op(ret, OP_EQ, 0); + smartlist_add(services, service_1); /* But don't add the second service yet. */ /* Service directories, but no previous keys, no problem! */ mock_options->HiddenServiceSingleHopMode = 0; mock_options->HiddenServiceNonAnonymousMode = 0; ret = rend_service_verify_single_onion_poison(service_1, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); ret = rend_service_verify_single_onion_poison(service_2, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); /* Either way, no problem. */ mock_options->HiddenServiceSingleHopMode = 1; mock_options->HiddenServiceNonAnonymousMode = 1; ret = rend_service_verify_single_onion_poison(service_1, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); ret = rend_service_verify_single_onion_poison(service_2, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); /* Poison! Poison! Poison! * This can only be done in HiddenServiceSingleHopMode. */ mock_options->HiddenServiceSingleHopMode = 1; mock_options->HiddenServiceNonAnonymousMode = 1; ret = rend_service_poison_new_single_onion_dir(service_1, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); /* Poisoning twice is a no-op. */ ret = rend_service_poison_new_single_onion_dir(service_1, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); /* Poisoned service directories, but no previous keys, no problem! */ mock_options->HiddenServiceSingleHopMode = 0; mock_options->HiddenServiceNonAnonymousMode = 0; ret = rend_service_verify_single_onion_poison(service_1, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); ret = rend_service_verify_single_onion_poison(service_2, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); /* Either way, no problem. */ mock_options->HiddenServiceSingleHopMode = 1; mock_options->HiddenServiceNonAnonymousMode = 1; ret = rend_service_verify_single_onion_poison(service_1, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); ret = rend_service_verify_single_onion_poison(service_2, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); /* Now add some keys, and we'll have a problem. */ ret = rend_service_load_all_keys(services); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); /* Poisoned service directories with previous keys are not allowed. */ mock_options->HiddenServiceSingleHopMode = 0; mock_options->HiddenServiceNonAnonymousMode = 0; ret = rend_service_verify_single_onion_poison(service_1, mock_options); - tt_assert(ret < 0); + tt_int_op(ret, OP_LT, 0); ret = rend_service_verify_single_onion_poison(service_2, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); /* But they are allowed if we're in non-anonymous mode. */ mock_options->HiddenServiceSingleHopMode = 1; mock_options->HiddenServiceNonAnonymousMode = 1; ret = rend_service_verify_single_onion_poison(service_1, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); ret = rend_service_verify_single_onion_poison(service_2, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); /* Re-poisoning directories with existing keys is a no-op, because * directories with existing keys are ignored. */ mock_options->HiddenServiceSingleHopMode = 1; mock_options->HiddenServiceNonAnonymousMode = 1; ret = rend_service_poison_new_single_onion_dir(service_1, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); /* And it keeps the poison. */ ret = rend_service_verify_single_onion_poison(service_1, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); ret = rend_service_verify_single_onion_poison(service_2, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); /* Now add the second service: it has no key and no poison file */ - ret = rend_service_check_dir_and_add(services, mock_options, service_2, 0); - tt_assert(ret == 0); + ret = hs_check_service_private_dir(mock_options->User, service_2->directory, + service_2->dir_group_readable, 1); + tt_int_op(ret, OP_EQ, 0); + smartlist_add(services, service_2); /* A new service, and an existing poisoned service. Not ok. */ mock_options->HiddenServiceSingleHopMode = 0; mock_options->HiddenServiceNonAnonymousMode = 0; ret = rend_service_verify_single_onion_poison(service_1, mock_options); - tt_assert(ret < 0); + tt_int_op(ret, OP_LT, 0); ret = rend_service_verify_single_onion_poison(service_2, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); /* But ok to add in non-anonymous mode. */ mock_options->HiddenServiceSingleHopMode = 1; mock_options->HiddenServiceNonAnonymousMode = 1; ret = rend_service_verify_single_onion_poison(service_1, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); ret = rend_service_verify_single_onion_poison(service_2, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); /* Now remove the poisoning from the first service, and we have the opposite * problem. */ poison_path = rend_service_sos_poison_path(service_1); tt_assert(poison_path); ret = unlink(poison_path); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); /* Unpoisoned service directories with previous keys are ok, as are empty * directories. */ mock_options->HiddenServiceSingleHopMode = 0; mock_options->HiddenServiceNonAnonymousMode = 0; ret = rend_service_verify_single_onion_poison(service_1, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); ret = rend_service_verify_single_onion_poison(service_2, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); /* But the existing unpoisoned key is not ok in non-anonymous mode, even if * there is an empty service. */ mock_options->HiddenServiceSingleHopMode = 1; mock_options->HiddenServiceNonAnonymousMode = 1; ret = rend_service_verify_single_onion_poison(service_1, mock_options); - tt_assert(ret < 0); + tt_int_op(ret, OP_LT, 0); ret = rend_service_verify_single_onion_poison(service_2, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); /* Poisoning directories with existing keys is a no-op, because directories * with existing keys are ignored. But the new directory should poison. */ mock_options->HiddenServiceSingleHopMode = 1; mock_options->HiddenServiceNonAnonymousMode = 1; ret = rend_service_poison_new_single_onion_dir(service_1, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); ret = rend_service_poison_new_single_onion_dir(service_2, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); /* And the old directory remains unpoisoned. */ ret = rend_service_verify_single_onion_poison(service_1, mock_options); - tt_assert(ret < 0); + tt_int_op(ret, OP_LT, 0); ret = rend_service_verify_single_onion_poison(service_2, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); /* And the new directory should be ignored, because it has no key. */ mock_options->HiddenServiceSingleHopMode = 0; mock_options->HiddenServiceNonAnonymousMode = 0; ret = rend_service_verify_single_onion_poison(service_1, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); ret = rend_service_verify_single_onion_poison(service_2, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); /* Re-poisoning directories without existing keys is a no-op. */ mock_options->HiddenServiceSingleHopMode = 1; mock_options->HiddenServiceNonAnonymousMode = 1; ret = rend_service_poison_new_single_onion_dir(service_1, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); ret = rend_service_poison_new_single_onion_dir(service_2, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); /* And the old directory remains unpoisoned. */ ret = rend_service_verify_single_onion_poison(service_1, mock_options); - tt_assert(ret < 0); + tt_int_op(ret, OP_LT, 0); ret = rend_service_verify_single_onion_poison(service_2, mock_options); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); done: /* The test harness deletes the directories at exit */ @@ -942,6 +1029,8 @@ test_prune_services_on_reload(void *arg) struct testcase_t hs_tests[] = { { "hs_rend_data", test_hs_rend_data, TT_FORK, NULL, NULL }, + { "hs_parse_static_v2_desc", test_hs_parse_static_v2_desc, TT_FORK, + NULL, NULL }, { "hs_desc_event", test_hs_desc_event, TT_FORK, NULL, NULL }, { "pick_tor2web_rendezvous_node", test_pick_tor2web_rendezvous_node, TT_FORK, diff --git a/src/test/test_hs_cache.c b/src/test/test_hs_cache.c index 40f50b322a..91b13be862 100644 --- a/src/test/test_hs_cache.c +++ b/src/test/test_hs_cache.c @@ -7,13 +7,16 @@ */ #define CONNECTION_PRIVATE +#define DIRECTORY_PRIVATE #define HS_CACHE_PRIVATE #include "ed25519_cert.h" #include "hs_cache.h" #include "rendcache.h" #include "directory.h" +#include "networkstatus.h" #include "connection.h" +#include "proto_http.h" #include "hs_test_helpers.h" #include "test_helpers.h" @@ -54,7 +57,7 @@ test_directory(void *arg) init_test(); /* Generate a valid descriptor with normal values. */ ret = ed25519_keypair_generate(&signing_kp1, 0); - tt_int_op(ret, ==, 0); + tt_int_op(ret, OP_EQ, 0); desc1 = hs_helper_build_hs_desc_with_ip(&signing_kp1); tt_assert(desc1); ret = hs_desc_encode_descriptor(desc1, &signing_kp1, &desc1_str); @@ -78,7 +81,7 @@ test_directory(void *arg) /* Tell our OOM to run and to at least remove a byte which will result in * removing the descriptor from our cache. */ oom_size = hs_cache_handle_oom(time(NULL), 1); - tt_int_op(oom_size, >=, 1); + tt_int_op(oom_size, OP_GE, 1); ret = hs_cache_lookup_as_dir(3, helper_get_hsdir_query(desc1), NULL); tt_int_op(ret, OP_EQ, 0); } @@ -87,7 +90,7 @@ test_directory(void *arg) { ed25519_keypair_t signing_kp_zero; ret = ed25519_keypair_generate(&signing_kp_zero, 0); - tt_int_op(ret, ==, 0); + tt_int_op(ret, OP_EQ, 0); hs_descriptor_t *desc_zero_lifetime; desc_zero_lifetime = hs_helper_build_hs_desc_with_ip(&signing_kp_zero); tt_assert(desc_zero_lifetime); @@ -115,7 +118,7 @@ test_directory(void *arg) tt_int_op(ret, OP_EQ, 0); /* Cleanup our entire cache. */ oom_size = hs_cache_handle_oom(time(NULL), 1); - tt_int_op(oom_size, >=, 1); + tt_int_op(oom_size, OP_GE, 1); hs_descriptor_free(desc_zero_lifetime); tor_free(desc_zero_lifetime_str); } @@ -177,7 +180,7 @@ test_clean_as_dir(void *arg) /* Generate a valid descriptor with values. */ ret = ed25519_keypair_generate(&signing_kp1, 0); - tt_int_op(ret, ==, 0); + tt_int_op(ret, OP_EQ, 0); desc1 = hs_helper_build_hs_desc_with_ip(&signing_kp1); tt_assert(desc1); ret = hs_desc_encode_descriptor(desc1, &signing_kp1, &desc1_str); @@ -187,21 +190,21 @@ test_clean_as_dir(void *arg) /* With the lifetime being 3 hours, a cleanup shouldn't remove it. */ ret = cache_clean_v3_as_dir(now, 0); - tt_int_op(ret, ==, 0); + tt_int_op(ret, OP_EQ, 0); /* Should be present after clean up. */ ret = hs_cache_lookup_as_dir(3, helper_get_hsdir_query(desc1), NULL); tt_int_op(ret, OP_EQ, 1); /* Set a cutoff 100 seconds in the past. It should not remove the entry * since the entry is still recent enough. */ ret = cache_clean_v3_as_dir(now, now - 100); - tt_int_op(ret, ==, 0); + tt_int_op(ret, OP_EQ, 0); /* Should be present after clean up. */ ret = hs_cache_lookup_as_dir(3, helper_get_hsdir_query(desc1), NULL); tt_int_op(ret, OP_EQ, 1); /* Set a cutoff of 100 seconds in the future. It should remove the entry * that we've just added since it's not too old for the cutoff. */ ret = cache_clean_v3_as_dir(now, now + 100); - tt_int_op(ret, >, 0); + tt_int_op(ret, OP_GT, 0); /* Shouldn't be present after clean up. */ ret = hs_cache_lookup_as_dir(3, helper_get_hsdir_query(desc1), NULL); tt_int_op(ret, OP_EQ, 0); @@ -231,7 +234,7 @@ helper_fetch_desc_from_hsdir(const ed25519_public_key_t *blinded_key) retval = ed25519_public_to_base64(hsdir_cache_key, blinded_key); - tt_int_op(retval, ==, 0); + tt_int_op(retval, OP_EQ, 0); tor_asprintf(&hsdir_query_str, GET("/tor/hs/3/%s"), hsdir_cache_key); } @@ -290,7 +293,7 @@ test_upload_and_download_hs_desc(void *arg) { ed25519_keypair_t signing_kp; retval = ed25519_keypair_generate(&signing_kp, 0); - tt_int_op(retval, ==, 0); + tt_int_op(retval, OP_EQ, 0); published_desc = hs_helper_build_hs_desc_with_ip(&signing_kp); tt_assert(published_desc); retval = hs_desc_encode_descriptor(published_desc, &signing_kp, @@ -301,7 +304,7 @@ test_upload_and_download_hs_desc(void *arg) /* Publish descriptor to the HSDir */ { retval = handle_post_hs_descriptor("/tor/hs/3/publish",published_desc_str); - tt_int_op(retval, ==, 200); + tt_int_op(retval, OP_EQ, 200); } /* Simulate a fetch of the previously published descriptor */ @@ -342,6 +345,7 @@ test_hsdir_revision_counter_check(void *arg) hs_descriptor_t *published_desc = NULL; char *published_desc_str = NULL; + uint8_t subcredential[DIGEST256_LEN]; char *received_desc_str = NULL; hs_descriptor_t *received_desc = NULL; @@ -353,7 +357,7 @@ test_hsdir_revision_counter_check(void *arg) /* Generate a valid descriptor with normal values. */ { retval = ed25519_keypair_generate(&signing_kp, 0); - tt_int_op(retval, ==, 0); + tt_int_op(retval, OP_EQ, 0); published_desc = hs_helper_build_hs_desc_with_ip(&signing_kp); tt_assert(published_desc); retval = hs_desc_encode_descriptor(published_desc, &signing_kp, @@ -364,13 +368,13 @@ test_hsdir_revision_counter_check(void *arg) /* Publish descriptor to the HSDir */ { retval = handle_post_hs_descriptor("/tor/hs/3/publish",published_desc_str); - tt_int_op(retval, ==, 200); + tt_int_op(retval, OP_EQ, 200); } /* Try publishing again with the same revision counter: Should fail. */ { retval = handle_post_hs_descriptor("/tor/hs/3/publish",published_desc_str); - tt_int_op(retval, ==, 400); + tt_int_op(retval, OP_EQ, 400); } /* Fetch the published descriptor and validate the revision counter. */ @@ -378,14 +382,16 @@ test_hsdir_revision_counter_check(void *arg) const ed25519_public_key_t *blinded_key; blinded_key = &published_desc->plaintext_data.blinded_pubkey; + hs_get_subcredential(&signing_kp.pubkey, blinded_key, subcredential); received_desc_str = helper_fetch_desc_from_hsdir(blinded_key); - retval = hs_desc_decode_descriptor(received_desc_str,NULL, &received_desc); - tt_int_op(retval, ==, 0); + retval = hs_desc_decode_descriptor(received_desc_str, + subcredential, &received_desc); + tt_int_op(retval, OP_EQ, 0); tt_assert(received_desc); /* Check that the revision counter is correct */ - tt_u64_op(received_desc->plaintext_data.revision_counter, ==, 42); + tt_u64_op(received_desc->plaintext_data.revision_counter, OP_EQ, 42); hs_descriptor_free(received_desc); received_desc = NULL; @@ -401,7 +407,7 @@ test_hsdir_revision_counter_check(void *arg) tt_int_op(retval, OP_EQ, 0); retval = handle_post_hs_descriptor("/tor/hs/3/publish",published_desc_str); - tt_int_op(retval, ==, 200); + tt_int_op(retval, OP_EQ, 200); } /* Again, fetch the published descriptor and perform the revision counter @@ -412,12 +418,13 @@ test_hsdir_revision_counter_check(void *arg) blinded_key = &published_desc->plaintext_data.blinded_pubkey; received_desc_str = helper_fetch_desc_from_hsdir(blinded_key); - retval = hs_desc_decode_descriptor(received_desc_str,NULL, &received_desc); - tt_int_op(retval, ==, 0); + retval = hs_desc_decode_descriptor(received_desc_str, + subcredential, &received_desc); + tt_int_op(retval, OP_EQ, 0); tt_assert(received_desc); /* Check that the revision counter is the latest */ - tt_u64_op(received_desc->plaintext_data.revision_counter, ==, 1313); + tt_u64_op(received_desc->plaintext_data.revision_counter, OP_EQ, 1313); } done: @@ -427,6 +434,115 @@ test_hsdir_revision_counter_check(void *arg) tor_free(published_desc_str); } +static networkstatus_t mock_ns; + +static networkstatus_t * +mock_networkstatus_get_live_consensus(time_t now) +{ + (void) now; + return &mock_ns; +} + +/** Test that we can store HS descriptors in the client HS cache. */ +static void +test_client_cache(void *arg) +{ + int retval; + ed25519_keypair_t signing_kp; + hs_descriptor_t *published_desc = NULL; + char *published_desc_str = NULL; + uint8_t wanted_subcredential[DIGEST256_LEN]; + response_handler_args_t *args = NULL; + dir_connection_t *conn = NULL; + + (void) arg; + + /* Initialize HSDir cache subsystem */ + init_test(); + + MOCK(networkstatus_get_live_consensus, + mock_networkstatus_get_live_consensus); + + /* Set consensus time */ + parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC", + &mock_ns.valid_after); + parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC", + &mock_ns.fresh_until); + parse_rfc1123_time("Sat, 26 Oct 1985 16:00:00 UTC", + &mock_ns.valid_until); + + /* Generate a valid descriptor with normal values. */ + { + retval = ed25519_keypair_generate(&signing_kp, 0); + tt_int_op(retval, OP_EQ, 0); + published_desc = hs_helper_build_hs_desc_with_ip(&signing_kp); + tt_assert(published_desc); + retval = hs_desc_encode_descriptor(published_desc, &signing_kp, + &published_desc_str); + tt_int_op(retval, OP_EQ, 0); + memcpy(wanted_subcredential, published_desc->subcredential, DIGEST256_LEN); + tt_assert(!tor_mem_is_zero((char*)wanted_subcredential, DIGEST256_LEN)); + } + + /* Test handle_response_fetch_hsdesc_v3() */ + { + args = tor_malloc_zero(sizeof(response_handler_args_t)); + args->status_code = 200; + args->reason = NULL; + args->body = published_desc_str; + args->body_len = strlen(published_desc_str); + + conn = tor_malloc_zero(sizeof(dir_connection_t)); + conn->hs_ident = tor_malloc_zero(sizeof(hs_ident_dir_conn_t)); + ed25519_pubkey_copy(&conn->hs_ident->identity_pk, &signing_kp.pubkey); + } + + /* store the descriptor! */ + retval = handle_response_fetch_hsdesc_v3(conn, args); + tt_int_op(retval, == , 0); + + /* Progress time a bit and attempt to clean cache: our desc should not be + * cleaned since we still in the same TP. */ + { + parse_rfc1123_time("Sat, 27 Oct 1985 02:00:00 UTC", + &mock_ns.valid_after); + parse_rfc1123_time("Sat, 27 Oct 1985 03:00:00 UTC", + &mock_ns.fresh_until); + parse_rfc1123_time("Sat, 27 Oct 1985 05:00:00 UTC", + &mock_ns.valid_until); + + /* fetch the descriptor and make sure it's there */ + const hs_descriptor_t *cached_desc = NULL; + cached_desc = hs_cache_lookup_as_client(&signing_kp.pubkey); + tt_assert(cached_desc); + tt_mem_op(cached_desc->subcredential, OP_EQ, wanted_subcredential, + DIGEST256_LEN); + } + + /* Progress time to next TP and check that desc was cleaned */ + { + parse_rfc1123_time("Sat, 27 Oct 1985 12:00:00 UTC", + &mock_ns.valid_after); + parse_rfc1123_time("Sat, 27 Oct 1985 13:00:00 UTC", + &mock_ns.fresh_until); + parse_rfc1123_time("Sat, 27 Oct 1985 15:00:00 UTC", + &mock_ns.valid_until); + + const hs_descriptor_t *cached_desc = NULL; + cached_desc = hs_cache_lookup_as_client(&signing_kp.pubkey); + tt_assert(!cached_desc); + } + + done: + tor_free(args); + hs_descriptor_free(published_desc); + tor_free(published_desc_str); + if (conn) { + tor_free(conn->hs_ident); + tor_free(conn); + } +} + struct testcase_t hs_cache[] = { /* Encoding tests. */ { "directory", test_directory, TT_FORK, @@ -437,6 +553,8 @@ struct testcase_t hs_cache[] = { NULL, NULL }, { "upload_and_download_hs_desc", test_upload_and_download_hs_desc, TT_FORK, NULL, NULL }, + { "client_cache", test_client_cache, TT_FORK, + NULL, NULL }, END_OF_TESTCASES }; diff --git a/src/test/test_hs_cell.c b/src/test/test_hs_cell.c new file mode 100644 index 0000000000..1b3c788a67 --- /dev/null +++ b/src/test/test_hs_cell.c @@ -0,0 +1,130 @@ +/* Copyright (c) 2017, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file test_hs_cell.c + * \brief Test hidden service cell functionality. + */ + +#define HS_INTROPOINT_PRIVATE +#define HS_SERVICE_PRIVATE + +#include "test.h" +#include "test_helpers.h" +#include "log_test_helpers.h" + +#include "crypto_ed25519.h" +#include "hs_cell.h" +#include "hs_intropoint.h" +#include "hs_service.h" + +/* Trunnel. */ +#include "hs/cell_establish_intro.h" + +/** We simulate the creation of an outgoing ESTABLISH_INTRO cell, and then we + * parse it from the receiver side. */ +static void +test_gen_establish_intro_cell(void *arg) +{ + (void) arg; + ssize_t ret; + char circ_nonce[DIGEST_LEN] = {0}; + uint8_t buf[RELAY_PAYLOAD_SIZE]; + trn_cell_establish_intro_t *cell_in = NULL; + + crypto_rand(circ_nonce, sizeof(circ_nonce)); + + /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we + attempt to parse it. */ + { + /* We only need the auth key pair here. */ + hs_service_intro_point_t *ip = service_intro_point_new(NULL, 0); + /* Auth key pair is generated in the constructor so we are all set for + * using this IP object. */ + ret = hs_cell_build_establish_intro(circ_nonce, ip, buf); + service_intro_point_free(ip); + tt_u64_op(ret, OP_GT, 0); + } + + /* Check the contents of the cell */ + { + /* First byte is the auth key type: make sure its correct */ + tt_int_op(buf[0], OP_EQ, HS_INTRO_AUTH_KEY_TYPE_ED25519); + /* Next two bytes is auth key len */ + tt_int_op(ntohs(get_uint16(buf+1)), OP_EQ, ED25519_PUBKEY_LEN); + /* Skip to the number of extensions: no extensions */ + tt_int_op(buf[35], OP_EQ, 0); + /* Skip to the sig len. Make sure it's the size of an ed25519 sig */ + tt_int_op(ntohs(get_uint16(buf+35+1+32)), OP_EQ, ED25519_SIG_LEN); + } + + /* Parse it as the receiver */ + { + ret = trn_cell_establish_intro_parse(&cell_in, buf, sizeof(buf)); + tt_u64_op(ret, OP_GT, 0); + + ret = verify_establish_intro_cell(cell_in, + (const uint8_t *) circ_nonce, + sizeof(circ_nonce)); + tt_u64_op(ret, OP_EQ, 0); + } + + done: + trn_cell_establish_intro_free(cell_in); +} + +/* Mocked ed25519_sign_prefixed() function that always fails :) */ +static int +mock_ed25519_sign_prefixed(ed25519_signature_t *signature_out, + const uint8_t *msg, size_t msg_len, + const char *prefix_str, + const ed25519_keypair_t *keypair) { + (void) signature_out; + (void) msg; + (void) msg_len; + (void) prefix_str; + (void) keypair; + return -1; +} + +/** We simulate a failure to create an ESTABLISH_INTRO cell */ +static void +test_gen_establish_intro_cell_bad(void *arg) +{ + (void) arg; + ssize_t cell_len = 0; + trn_cell_establish_intro_t *cell = NULL; + char circ_nonce[DIGEST_LEN] = {0}; + hs_service_intro_point_t *ip = NULL; + + MOCK(ed25519_sign_prefixed, mock_ed25519_sign_prefixed); + + crypto_rand(circ_nonce, sizeof(circ_nonce)); + + setup_full_capture_of_logs(LOG_WARN); + /* Easiest way to make that function fail is to mock the + ed25519_sign_prefixed() function and make it fail. */ + cell = trn_cell_establish_intro_new(); + tt_assert(cell); + ip = service_intro_point_new(NULL, 0); + cell_len = hs_cell_build_establish_intro(circ_nonce, ip, NULL); + service_intro_point_free(ip); + expect_log_msg_containing("Unable to make signature for " + "ESTABLISH_INTRO cell."); + teardown_capture_of_logs(); + tt_i64_op(cell_len, OP_EQ, -1); + + done: + trn_cell_establish_intro_free(cell); + UNMOCK(ed25519_sign_prefixed); +} + +struct testcase_t hs_cell_tests[] = { + { "gen_establish_intro_cell", test_gen_establish_intro_cell, TT_FORK, + NULL, NULL }, + { "gen_establish_intro_cell_bad", test_gen_establish_intro_cell_bad, TT_FORK, + NULL, NULL }, + + END_OF_TESTCASES +}; + diff --git a/src/test/test_hs_client.c b/src/test/test_hs_client.c new file mode 100644 index 0000000000..750920fac0 --- /dev/null +++ b/src/test/test_hs_client.c @@ -0,0 +1,599 @@ +/* Copyright (c) 2016-2017, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file test_hs_client.c + * \brief Test prop224 HS client functionality. + */ + +#define CRYPTO_PRIVATE +#define MAIN_PRIVATE +#define HS_CLIENT_PRIVATE +#define TOR_CHANNEL_INTERNAL_ +#define CIRCUITBUILD_PRIVATE +#define CIRCUITLIST_PRIVATE +#define CONNECTION_PRIVATE + +#include "test.h" +#include "test_helpers.h" +#include "log_test_helpers.h" +#include "rend_test_helpers.h" +#include "hs_test_helpers.h" + +#include "config.h" +#include "crypto.h" +#include "channeltls.h" +#include "main.h" +#include "nodelist.h" +#include "routerset.h" + +#include "hs_circuit.h" +#include "hs_client.h" +#include "hs_ident.h" +#include "hs_cache.h" +#include "circuitlist.h" +#include "circuitbuild.h" +#include "connection.h" +#include "connection_edge.h" +#include "networkstatus.h" + +static int +mock_connection_ap_handshake_send_begin(entry_connection_t *ap_conn) +{ + (void) ap_conn; + return 0; +} + +static networkstatus_t mock_ns; + +/* Always return NULL. */ +static networkstatus_t * +mock_networkstatus_get_live_consensus_false(time_t now) +{ + (void) now; + return NULL; +} + +static networkstatus_t * +mock_networkstatus_get_live_consensus(time_t now) +{ + (void) now; + return &mock_ns; +} + +/* Test helper function: Setup a circuit and a stream with the same hidden + * service destination, and put them in <b>circ_out</b> and + * <b>conn_out</b>. Make the stream wait for circuits to be established to the + * hidden service. */ +static int +helper_get_circ_and_stream_for_test(origin_circuit_t **circ_out, + connection_t **conn_out, + int is_legacy) +{ + int retval; + channel_tls_t *n_chan=NULL; + rend_data_t *conn_rend_data = NULL; + origin_circuit_t *or_circ = NULL; + connection_t *conn = NULL; + ed25519_public_key_t service_pk; + + /* Make a dummy connection stream and make it wait for our circuit */ + conn = test_conn_get_connection(AP_CONN_STATE_CIRCUIT_WAIT, + CONN_TYPE_AP /* ??? */, + 0); + if (is_legacy) { + /* Legacy: Setup rend_data of stream */ + char service_id[REND_SERVICE_ID_LEN_BASE32+1] = {0}; + TO_EDGE_CONN(conn)->rend_data = mock_rend_data(service_id); + conn_rend_data = TO_EDGE_CONN(conn)->rend_data; + } else { + /* prop224: Setup hs conn identifier on the stream */ + ed25519_secret_key_t sk; + tt_int_op(0, OP_EQ, ed25519_secret_key_generate(&sk, 0)); + tt_int_op(0, OP_EQ, ed25519_public_key_generate(&service_pk, &sk)); + + /* Setup hs_conn_identifier of stream */ + TO_EDGE_CONN(conn)->hs_ident = hs_ident_edge_conn_new(&service_pk); + } + + /* Make it wait for circuit */ + connection_ap_mark_as_pending_circuit(TO_ENTRY_CONN(conn)); + + /* This is needed to silence a BUG warning from + connection_edge_update_circuit_isolation() */ + TO_ENTRY_CONN(conn)->original_dest_address = + tor_strdup(TO_ENTRY_CONN(conn)->socks_request->address); + + /****************************************************/ + + /* Now make dummy circuit */ + or_circ = origin_circuit_new(); + + or_circ->base_.purpose = CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED; + + or_circ->build_state = tor_malloc_zero(sizeof(cpath_build_state_t)); + or_circ->build_state->is_internal = 1; + + if (is_legacy) { + /* Legacy: Setup rend data and final cpath */ + or_circ->build_state->pending_final_cpath = + tor_malloc_zero(sizeof(crypt_path_t)); + or_circ->build_state->pending_final_cpath->magic = CRYPT_PATH_MAGIC; + or_circ->build_state->pending_final_cpath->rend_dh_handshake_state = + crypto_dh_new(DH_TYPE_REND); + tt_assert( + or_circ->build_state->pending_final_cpath->rend_dh_handshake_state); + retval = crypto_dh_generate_public( + or_circ->build_state->pending_final_cpath->rend_dh_handshake_state); + tt_int_op(retval, OP_EQ, 0); + or_circ->rend_data = rend_data_dup(conn_rend_data); + } else { + /* prop224: Setup hs ident on the circuit */ + or_circ->hs_ident = hs_ident_circuit_new(&service_pk, + HS_IDENT_CIRCUIT_RENDEZVOUS); + } + + TO_CIRCUIT(or_circ)->state = CIRCUIT_STATE_OPEN; + + /* fake n_chan */ + n_chan = tor_malloc_zero(sizeof(channel_tls_t)); + n_chan->base_.global_identifier = 1; + or_circ->base_.n_chan = &(n_chan->base_); + + *circ_out = or_circ; + *conn_out = conn; + + return 0; + + done: + /* something failed */ + return -1; +} + +/* Test: Ensure that setting up legacy e2e rendezvous circuits works + * correctly. */ +static void +test_e2e_rend_circuit_setup_legacy(void *arg) +{ + ssize_t retval; + origin_circuit_t *or_circ = NULL; + connection_t *conn = NULL; + + (void) arg; + + /** In this test we create a v2 legacy HS stream and a circuit with the same + * hidden service destination. We make the stream wait for circuits to be + * established to the hidden service, and then we complete the circuit using + * the hs_circuit_setup_e2e_rend_circ_legacy_client() function. We then + * check that the end-to-end cpath was setup correctly and that the stream + * was attached to the circuit as expected. */ + + MOCK(connection_ap_handshake_send_begin, + mock_connection_ap_handshake_send_begin); + + /* Setup */ + retval = helper_get_circ_and_stream_for_test( &or_circ, &conn, 1); + tt_int_op(retval, OP_EQ, 0); + tt_assert(or_circ); + tt_assert(conn); + + /* Check number of hops */ + retval = cpath_get_n_hops(&or_circ->cpath); + tt_int_op(retval, OP_EQ, 0); + + /* Check that our stream is not attached on any circuits */ + tt_ptr_op(TO_EDGE_CONN(conn)->on_circuit, OP_EQ, NULL); + + /********************************************** */ + + /* Make a good RENDEZVOUS1 cell body because it needs to pass key exchange + * digest verification... */ + uint8_t rend_cell_body[DH_KEY_LEN+DIGEST_LEN] = {2}; + { + char keys[DIGEST_LEN+CPATH_KEY_MATERIAL_LEN]; + crypto_dh_t *dh_state = + or_circ->build_state->pending_final_cpath->rend_dh_handshake_state; + /* compute and overwrite digest of cell body with the right value */ + retval = crypto_dh_compute_secret(LOG_PROTOCOL_WARN, dh_state, + (char*)rend_cell_body, DH_KEY_LEN, + keys, DIGEST_LEN+CPATH_KEY_MATERIAL_LEN); + tt_int_op(retval, OP_GT, 0); + memcpy(rend_cell_body+DH_KEY_LEN, keys, DIGEST_LEN); + } + + /* Setup the circuit */ + retval = hs_circuit_setup_e2e_rend_circ_legacy_client(or_circ, + rend_cell_body); + tt_int_op(retval, OP_EQ, 0); + + /**********************************************/ + + /* See that a hop was added to the circuit's cpath */ + retval = cpath_get_n_hops(&or_circ->cpath); + tt_int_op(retval, OP_EQ, 1); + + /* Check the digest algo */ + tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->f_digest), + OP_EQ, DIGEST_SHA1); + tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->b_digest), + OP_EQ, DIGEST_SHA1); + tt_assert(or_circ->cpath->f_crypto); + tt_assert(or_circ->cpath->b_crypto); + + /* Ensure that circ purpose was changed */ + tt_int_op(or_circ->base_.purpose, OP_EQ, CIRCUIT_PURPOSE_C_REND_JOINED); + + /* Test that stream got attached */ + tt_ptr_op(TO_EDGE_CONN(conn)->on_circuit, OP_EQ, TO_CIRCUIT(or_circ)); + + done: + connection_free_(conn); + if (or_circ) + tor_free(TO_CIRCUIT(or_circ)->n_chan); + circuit_free(TO_CIRCUIT(or_circ)); +} + +/* Test: Ensure that setting up v3 rendezvous circuits works correctly. */ +static void +test_e2e_rend_circuit_setup(void *arg) +{ + uint8_t ntor_key_seed[DIGEST256_LEN] = {0}; + origin_circuit_t *or_circ = NULL; + int retval; + connection_t *conn = NULL; + + (void) arg; + + /** In this test we create a prop224 v3 HS stream and a circuit with the same + * hidden service destination. We make the stream wait for circuits to be + * established to the hidden service, and then we complete the circuit using + * the hs_circuit_setup_e2e_rend_circ() function. We then check that the + * end-to-end cpath was setup correctly and that the stream was attached to + * the circuit as expected. */ + + MOCK(connection_ap_handshake_send_begin, + mock_connection_ap_handshake_send_begin); + + /* Setup */ + retval = helper_get_circ_and_stream_for_test( &or_circ, &conn, 0); + tt_int_op(retval, OP_EQ, 0); + tt_assert(or_circ); + tt_assert(conn); + + /* Check number of hops: There should be no hops yet to this circ */ + retval = cpath_get_n_hops(&or_circ->cpath); + tt_int_op(retval, OP_EQ, 0); + tt_ptr_op(or_circ->cpath, OP_EQ, NULL); + + /* Check that our stream is not attached on any circuits */ + tt_ptr_op(TO_EDGE_CONN(conn)->on_circuit, OP_EQ, NULL); + + /**********************************************/ + + /* Setup the circuit */ + retval = hs_circuit_setup_e2e_rend_circ(or_circ, + ntor_key_seed, sizeof(ntor_key_seed), + 0); + tt_int_op(retval, OP_EQ, 0); + + /**********************************************/ + + /* See that a hop was added to the circuit's cpath */ + retval = cpath_get_n_hops(&or_circ->cpath); + tt_int_op(retval, OP_EQ, 1); + + /* Check that the crypt path has prop224 algorithm parameters */ + tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->f_digest), + OP_EQ, DIGEST_SHA3_256); + tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->b_digest), + OP_EQ, DIGEST_SHA3_256); + tt_assert(or_circ->cpath->f_crypto); + tt_assert(or_circ->cpath->b_crypto); + + /* Ensure that circ purpose was changed */ + tt_int_op(or_circ->base_.purpose, OP_EQ, CIRCUIT_PURPOSE_C_REND_JOINED); + + /* Test that stream got attached */ + tt_ptr_op(TO_EDGE_CONN(conn)->on_circuit, OP_EQ, TO_CIRCUIT(or_circ)); + + done: + connection_free_(conn); + if (or_circ) + tor_free(TO_CIRCUIT(or_circ)->n_chan); + circuit_free(TO_CIRCUIT(or_circ)); +} + +/** Test client logic for picking intro points from a descriptor. Also test how + * ExcludeNodes and intro point failures affect picking intro points. */ +static void +test_client_pick_intro(void *arg) +{ + int ret; + ed25519_keypair_t service_kp; + hs_descriptor_t *desc = NULL; + + MOCK(networkstatus_get_live_consensus, + mock_networkstatus_get_live_consensus); + + (void) arg; + + hs_init(); + + /* Generate service keypair */ + tt_int_op(0, OP_EQ, ed25519_keypair_generate(&service_kp, 0)); + + /* Set time */ + ret = parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC", + &mock_ns.valid_after); + tt_int_op(ret, OP_EQ, 0); + ret = parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC", + &mock_ns.fresh_until); + tt_int_op(ret, OP_EQ, 0); + + update_approx_time(mock_ns.fresh_until-10); + time_t now = approx_time(); + + /* Test logic: + * + * 1) Add our desc with intro points to the HS cache. + * + * 2) Mark all descriptor intro points except _the chosen one_ as + * failed. Then query the desc to get a random intro: check that we got + * _the chosen one_. Then fail the chosen one as well, and see that no + * intros are returned. + * + * 3) Then clean the intro state cache and get an intro point. + * + * 4) Try fetching an intro with the wrong service key: shouldn't work + * + * 5) Set StrictNodes and put all our intro points in ExcludeNodes: see that + * nothing is returned. + */ + + /* 1) Add desc to HS cache */ + { + char *encoded = NULL; + desc = hs_helper_build_hs_desc_with_ip(&service_kp); + ret = hs_desc_encode_descriptor(desc, &service_kp, &encoded); + tt_int_op(ret, OP_EQ, 0); + tt_assert(encoded); + + /* store it */ + hs_cache_store_as_client(encoded, &service_kp.pubkey); + + /* fetch it to make sure it works */ + const hs_descriptor_t *fetched_desc = + hs_cache_lookup_as_client(&service_kp.pubkey); + tt_assert(fetched_desc); + tt_mem_op(fetched_desc->subcredential, OP_EQ, desc->subcredential, + DIGEST256_LEN); + tt_assert(!tor_mem_is_zero((char*)fetched_desc->subcredential, + DIGEST256_LEN)); + tor_free(encoded); + } + + /* 2) Mark all intro points except _the chosen one_ as failed. Then query the + * desc and get a random intro: check that we got _the chosen one_. */ + { + /* Pick the chosen intro point and get its ei */ + hs_desc_intro_point_t *chosen_intro_point = + smartlist_get(desc->encrypted_data.intro_points, 0); + extend_info_t *chosen_intro_ei = + desc_intro_point_to_extend_info(chosen_intro_point); + tt_assert(chosen_intro_point); + tt_assert(chosen_intro_ei); + + /* Now mark all other intro points as failed */ + SMARTLIST_FOREACH_BEGIN(desc->encrypted_data.intro_points, + hs_desc_intro_point_t *, ip) { + /* Skip the chosen intro point */ + if (ip == chosen_intro_point) { + continue; + } + ed25519_public_key_t *intro_auth_key = &ip->auth_key_cert->signed_key; + hs_cache_client_intro_state_note(&service_kp.pubkey, + intro_auth_key, + INTRO_POINT_FAILURE_GENERIC); + } SMARTLIST_FOREACH_END(ip); + + /* Try to get a random intro: Should return the chosen one! */ + extend_info_t *ip = client_get_random_intro(&service_kp.pubkey); + tor_assert(ip); + tt_assert(!tor_mem_is_zero((char*)ip->identity_digest, DIGEST_LEN)); + tt_mem_op(ip->identity_digest, OP_EQ, chosen_intro_ei->identity_digest, + DIGEST_LEN); + + extend_info_free(chosen_intro_ei); + extend_info_free(ip); + + /* Now also mark the chosen one as failed: See that we can't get any intro + points anymore. */ + hs_cache_client_intro_state_note(&service_kp.pubkey, + &chosen_intro_point->auth_key_cert->signed_key, + INTRO_POINT_FAILURE_TIMEOUT); + ip = client_get_random_intro(&service_kp.pubkey); + tor_assert(!ip); + } + + /* 3) Clean the intro state cache and get an intro point */ + { + /* Pretend we are 5 mins in the future and order a cleanup of the intro + * state. This should clean up the intro point failures and allow us to get + * an intro. */ + hs_cache_client_intro_state_clean(now + 5*60); + + /* Get an intro. It should work! */ + extend_info_t *ip = client_get_random_intro(&service_kp.pubkey); + tor_assert(ip); + extend_info_free(ip); + } + + /* 4) Try fetching an intro with the wrong service key: shouldn't work */ + { + ed25519_keypair_t dummy_kp; + tt_int_op(0, OP_EQ, ed25519_keypair_generate(&dummy_kp, 0)); + extend_info_t *ip = client_get_random_intro(&dummy_kp.pubkey); + tor_assert(!ip); + } + + /* 5) Set StrictNodes and put all our intro points in ExcludeNodes: see that + * nothing is returned. */ + { + get_options_mutable()->ExcludeNodes = routerset_new(); + get_options_mutable()->StrictNodes = 1; + SMARTLIST_FOREACH_BEGIN(desc->encrypted_data.intro_points, + hs_desc_intro_point_t *, ip) { + extend_info_t *intro_ei = desc_intro_point_to_extend_info(ip); + if (intro_ei) { + const char *ptr; + char ip_addr[TOR_ADDR_BUF_LEN]; + /* We need to decorate in case it is an IPv6 else routerset_parse() + * doesn't like it. */ + ptr = tor_addr_to_str(ip_addr, &intro_ei->addr, sizeof(ip_addr), 1); + tt_assert(ptr == ip_addr); + ret = routerset_parse(get_options_mutable()->ExcludeNodes, + ip_addr, ""); + tt_int_op(ret, OP_EQ, 0); + extend_info_free(intro_ei); + } + } SMARTLIST_FOREACH_END(ip); + + extend_info_t *ip = client_get_random_intro(&service_kp.pubkey); + tt_assert(!ip); + } + + done: + hs_descriptor_free(desc); +} + +static int +mock_router_have_minimum_dir_info_false(void) +{ + return 0; +} +static int +mock_router_have_minimum_dir_info_true(void) +{ + return 1; +} + +static hs_client_fetch_status_t +mock_fetch_v3_desc_error(const ed25519_public_key_t *key) +{ + (void) key; + return HS_CLIENT_FETCH_ERROR; +} + +static void +mock_connection_mark_unattached_ap_(entry_connection_t *conn, int endreason, + int line, const char *file) +{ + (void) line; + (void) file; + conn->edge_.end_reason = endreason; +} + +static void +test_descriptor_fetch(void *arg) +{ + int ret; + entry_connection_t *ec = NULL; + ed25519_public_key_t service_pk; + ed25519_secret_key_t service_sk; + + (void) arg; + + hs_init(); + memset(&service_sk, 'A', sizeof(service_sk)); + ret = ed25519_public_key_generate(&service_pk, &service_sk); + tt_int_op(ret, OP_EQ, 0); + + /* Initialize this so get_voting_interval() doesn't freak out. */ + ret = parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC", + &mock_ns.valid_after); + tt_int_op(ret, OP_EQ, 0); + ret = parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC", + &mock_ns.fresh_until); + tt_int_op(ret, OP_EQ, 0); + + ec = entry_connection_new(CONN_TYPE_AP, AF_INET); + tt_assert(ec); + ENTRY_TO_EDGE_CONN(ec)->hs_ident = hs_ident_edge_conn_new(&service_pk); + tt_assert(ENTRY_TO_EDGE_CONN(ec)->hs_ident); + TO_CONN(ENTRY_TO_EDGE_CONN(ec))->state = AP_CONN_STATE_RENDDESC_WAIT; + smartlist_add(get_connection_array(), &ec->edge_.base_); + + /* 1. FetchHidServDescriptors is false so we shouldn't be able to fetch. */ + get_options_mutable()->FetchHidServDescriptors = 0; + ret = hs_client_refetch_hsdesc(&service_pk); + tt_int_op(ret, OP_EQ, HS_CLIENT_FETCH_NOT_ALLOWED); + get_options_mutable()->FetchHidServDescriptors = 1; + + /* 2. We don't have a live consensus. */ + MOCK(networkstatus_get_live_consensus, + mock_networkstatus_get_live_consensus_false); + ret = hs_client_refetch_hsdesc(&service_pk); + UNMOCK(networkstatus_get_live_consensus); + tt_int_op(ret, OP_EQ, HS_CLIENT_FETCH_MISSING_INFO); + + /* From now on, return a live consensus. */ + MOCK(networkstatus_get_live_consensus, + mock_networkstatus_get_live_consensus); + + /* 3. Not enough dir information. */ + MOCK(router_have_minimum_dir_info, + mock_router_have_minimum_dir_info_false); + ret = hs_client_refetch_hsdesc(&service_pk); + UNMOCK(router_have_minimum_dir_info); + tt_int_op(ret, OP_EQ, HS_CLIENT_FETCH_MISSING_INFO); + + /* From now on, we do have enough directory information. */ + MOCK(router_have_minimum_dir_info, + mock_router_have_minimum_dir_info_true); + + /* 4. We do have a pending directory request. */ + { + dir_connection_t *dir_conn = dir_connection_new(AF_INET); + dir_conn->hs_ident = tor_malloc_zero(sizeof(hs_ident_dir_conn_t)); + TO_CONN(dir_conn)->purpose = DIR_PURPOSE_FETCH_HSDESC; + ed25519_pubkey_copy(&dir_conn->hs_ident->identity_pk, &service_pk); + smartlist_add(get_connection_array(), TO_CONN(dir_conn)); + ret = hs_client_refetch_hsdesc(&service_pk); + smartlist_remove(get_connection_array(), TO_CONN(dir_conn)); + connection_free_(TO_CONN(dir_conn)); + tt_int_op(ret, OP_EQ, HS_CLIENT_FETCH_PENDING); + } + + /* 5. We'll trigger an error on the fetch_desc_v3 and force to close all + * pending SOCKS request. */ + MOCK(router_have_minimum_dir_info, + mock_router_have_minimum_dir_info_true); + MOCK(fetch_v3_desc, mock_fetch_v3_desc_error); + MOCK(connection_mark_unattached_ap_, + mock_connection_mark_unattached_ap_); + ret = hs_client_refetch_hsdesc(&service_pk); + UNMOCK(fetch_v3_desc); + UNMOCK(connection_mark_unattached_ap_); + tt_int_op(ret, OP_EQ, HS_CLIENT_FETCH_ERROR); + /* The close waiting for descriptor function has been called. */ + tt_int_op(ec->edge_.end_reason, OP_EQ, END_STREAM_REASON_RESOLVEFAILED); + + done: + connection_free_(ENTRY_TO_CONN(ec)); + UNMOCK(networkstatus_get_live_consensus); + UNMOCK(router_have_minimum_dir_info); + hs_free_all(); +} + +struct testcase_t hs_client_tests[] = { + { "e2e_rend_circuit_setup_legacy", test_e2e_rend_circuit_setup_legacy, + TT_FORK, NULL, NULL }, + { "e2e_rend_circuit_setup", test_e2e_rend_circuit_setup, + TT_FORK, NULL, NULL }, + { "client_pick_intro", test_client_pick_intro, + TT_FORK, NULL, NULL }, + { "descriptor_fetch", test_descriptor_fetch, + TT_FORK, NULL, NULL }, + END_OF_TESTCASES +}; + diff --git a/src/test/test_hs_common.c b/src/test/test_hs_common.c new file mode 100644 index 0000000000..3ae623ed0a --- /dev/null +++ b/src/test/test_hs_common.c @@ -0,0 +1,1827 @@ +/* Copyright (c) 2017, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file test_hs_common.c + * \brief Test hidden service common functionalities. + */ + +#define HS_COMMON_PRIVATE +#define HS_CLIENT_PRIVATE +#define HS_SERVICE_PRIVATE +#define NODELIST_PRIVATE + +#include "test.h" +#include "test_helpers.h" +#include "log_test_helpers.h" +#include "hs_test_helpers.h" + +#include "connection_edge.h" +#include "hs_common.h" +#include "hs_client.h" +#include "hs_service.h" +#include "config.h" +#include "networkstatus.h" +#include "directory.h" +#include "dirvote.h" +#include "nodelist.h" +#include "routerlist.h" +#include "statefile.h" +#include "circuitlist.h" +#include "shared_random.h" +#include "util.h" + +/** Test the validation of HS v3 addresses */ +static void +test_validate_address(void *arg) +{ + int ret; + + (void) arg; + + /* Address too short and too long. */ + setup_full_capture_of_logs(LOG_WARN); + ret = hs_address_is_valid("blah"); + tt_int_op(ret, OP_EQ, 0); + expect_log_msg_containing("has an invalid length"); + teardown_capture_of_logs(); + + setup_full_capture_of_logs(LOG_WARN); + ret = hs_address_is_valid( + "p3xnclpu4mu22dwaurjtsybyqk4xfjmcfz6z62yl24uwmhjatiwnlnadb"); + tt_int_op(ret, OP_EQ, 0); + expect_log_msg_containing("has an invalid length"); + teardown_capture_of_logs(); + + /* Invalid checksum (taken from prop224) */ + setup_full_capture_of_logs(LOG_WARN); + ret = hs_address_is_valid( + "l5satjgud6gucryazcyvyvhuxhr74u6ygigiuyixe3a6ysis67ororad"); + tt_int_op(ret, OP_EQ, 0); + expect_log_msg_containing("invalid checksum"); + teardown_capture_of_logs(); + + setup_full_capture_of_logs(LOG_WARN); + ret = hs_address_is_valid( + "btojiu7nu5y5iwut64eufevogqdw4wmqzugnoluw232r4t3ecsfv37ad"); + tt_int_op(ret, OP_EQ, 0); + expect_log_msg_containing("invalid checksum"); + teardown_capture_of_logs(); + + /* Non base32 decodable string. */ + setup_full_capture_of_logs(LOG_WARN); + ret = hs_address_is_valid( + "????????????????????????????????????????????????????????"); + tt_int_op(ret, OP_EQ, 0); + expect_log_msg_containing("can't be decoded"); + teardown_capture_of_logs(); + + /* Valid address. */ + ret = hs_address_is_valid( + "25njqamcweflpvkl73j4szahhihoc4xt3ktcgjnpaingr5yhkenl5sid"); + tt_int_op(ret, OP_EQ, 1); + + done: + ; +} + +static int +mock_write_str_to_file(const char *path, const char *str, int bin) +{ + (void)bin; + tt_str_op(path, OP_EQ, "/double/five"PATH_SEPARATOR"squared"); + tt_str_op(str, OP_EQ, + "25njqamcweflpvkl73j4szahhihoc4xt3ktcgjnpaingr5yhkenl5sid.onion\n"); + + done: + return 0; +} + +/** Test building HS v3 onion addresses. Uses test vectors from the + * ./hs_build_address.py script. */ +static void +test_build_address(void *arg) +{ + int ret; + char onion_addr[HS_SERVICE_ADDR_LEN_BASE32 + 1]; + ed25519_public_key_t pubkey; + /* hex-encoded ed25519 pubkey used in hs_build_address.py */ + char pubkey_hex[] = + "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a"; + hs_service_t *service = NULL; + + (void) arg; + + MOCK(write_str_to_file, mock_write_str_to_file); + + /* The following has been created with hs_build_address.py script that + * follows proposal 224 specification to build an onion address. */ + static const char *test_addr = + "25njqamcweflpvkl73j4szahhihoc4xt3ktcgjnpaingr5yhkenl5sid"; + + /* Let's try to build the same onion address as the script */ + base16_decode((char*)pubkey.pubkey, sizeof(pubkey.pubkey), + pubkey_hex, strlen(pubkey_hex)); + hs_build_address(&pubkey, HS_VERSION_THREE, onion_addr); + tt_str_op(test_addr, OP_EQ, onion_addr); + /* Validate that address. */ + ret = hs_address_is_valid(onion_addr); + tt_int_op(ret, OP_EQ, 1); + + service = tor_malloc_zero(sizeof(hs_service_t)); + memcpy(service->onion_address, onion_addr, sizeof(service->onion_address)); + tor_asprintf(&service->config.directory_path, "/double/five"); + ret = write_address_to_file(service, "squared"); + tt_int_op(ret, OP_EQ, 0); + + done: + hs_service_free(service); +} + +/** Test that our HS time period calculation functions work properly */ +static void +test_time_period(void *arg) +{ + (void) arg; + uint64_t tn; + int retval; + time_t fake_time, correct_time, start_time; + + /* Let's do the example in prop224 section [TIME-PERIODS] */ + retval = parse_rfc1123_time("Wed, 13 Apr 2016 11:00:00 UTC", + &fake_time); + tt_int_op(retval, OP_EQ, 0); + + /* Check that the time period number is right */ + tn = hs_get_time_period_num(fake_time); + tt_u64_op(tn, OP_EQ, 16903); + + /* Increase current time to 11:59:59 UTC and check that the time period + number is still the same */ + fake_time += 3599; + tn = hs_get_time_period_num(fake_time); + tt_u64_op(tn, OP_EQ, 16903); + + { /* Check start time of next time period */ + retval = parse_rfc1123_time("Wed, 13 Apr 2016 12:00:00 UTC", + &correct_time); + tt_int_op(retval, OP_EQ, 0); + + start_time = hs_get_start_time_of_next_time_period(fake_time); + tt_int_op(start_time, OP_EQ, correct_time); + } + + /* Now take time to 12:00:00 UTC and check that the time period rotated */ + fake_time += 1; + tn = hs_get_time_period_num(fake_time); + tt_u64_op(tn, OP_EQ, 16904); + + /* Now also check our hs_get_next_time_period_num() function */ + tn = hs_get_next_time_period_num(fake_time); + tt_u64_op(tn, OP_EQ, 16905); + + { /* Check start time of next time period again */ + retval = parse_rfc1123_time("Wed, 14 Apr 2016 12:00:00 UTC", + &correct_time); + tt_int_op(retval, OP_EQ, 0); + + start_time = hs_get_start_time_of_next_time_period(fake_time); + tt_int_op(start_time, OP_EQ, correct_time); + } + + /* Now do another sanity check: The time period number at the start of the + * next time period, must be the same time period number as the one returned + * from hs_get_next_time_period_num() */ + { + time_t next_tp_start = hs_get_start_time_of_next_time_period(fake_time); + tt_u64_op(hs_get_time_period_num(next_tp_start), OP_EQ, + hs_get_next_time_period_num(fake_time)); + } + + done: + ; +} + +/** Test that we can correctly find the start time of the next time period */ +static void +test_start_time_of_next_time_period(void *arg) +{ + (void) arg; + int retval; + time_t fake_time; + char tbuf[ISO_TIME_LEN + 1]; + time_t next_tp_start_time; + + /* Do some basic tests */ + retval = parse_rfc1123_time("Wed, 13 Apr 2016 11:00:00 UTC", + &fake_time); + tt_int_op(retval, OP_EQ, 0); + next_tp_start_time = hs_get_start_time_of_next_time_period(fake_time); + /* Compare it with the correct result */ + format_iso_time(tbuf, next_tp_start_time); + tt_str_op("2016-04-13 12:00:00", OP_EQ, tbuf); + + /* Another test with an edge-case time (start of TP) */ + retval = parse_rfc1123_time("Wed, 13 Apr 2016 12:00:00 UTC", + &fake_time); + tt_int_op(retval, OP_EQ, 0); + next_tp_start_time = hs_get_start_time_of_next_time_period(fake_time); + format_iso_time(tbuf, next_tp_start_time); + tt_str_op("2016-04-14 12:00:00", OP_EQ, tbuf); + + { + /* Now pretend we are on a testing network and alter the voting schedule to + be every 10 seconds. This means that a time period has length 10*24 + seconds (4 minutes). It also means that we apply a rotational offset of + 120 seconds to the time period, so that it starts at 00:02:00 instead of + 00:00:00. */ + or_options_t *options = get_options_mutable(); + options->TestingTorNetwork = 1; + options->V3AuthVotingInterval = 10; + options->TestingV3AuthInitialVotingInterval = 10; + + retval = parse_rfc1123_time("Wed, 13 Apr 2016 00:00:00 UTC", + &fake_time); + tt_int_op(retval, OP_EQ, 0); + next_tp_start_time = hs_get_start_time_of_next_time_period(fake_time); + /* Compare it with the correct result */ + format_iso_time(tbuf, next_tp_start_time); + tt_str_op("2016-04-13 00:02:00", OP_EQ, tbuf); + + retval = parse_rfc1123_time("Wed, 13 Apr 2016 00:02:00 UTC", + &fake_time); + tt_int_op(retval, OP_EQ, 0); + next_tp_start_time = hs_get_start_time_of_next_time_period(fake_time); + /* Compare it with the correct result */ + format_iso_time(tbuf, next_tp_start_time); + tt_str_op("2016-04-13 00:06:00", OP_EQ, tbuf); + } + + done: + ; +} + +/* Cleanup the global nodelist. It also frees the "md" in the node_t because + * we allocate the memory in helper_add_hsdir_to_networkstatus(). */ +static void +cleanup_nodelist(void) +{ + smartlist_t *nodelist = nodelist_get_list(); + SMARTLIST_FOREACH_BEGIN(nodelist, node_t *, node) { + tor_free(node->md); + node->md = NULL; + } SMARTLIST_FOREACH_END(node); + nodelist_free_all(); +} + +static void +helper_add_hsdir_to_networkstatus(networkstatus_t *ns, + int identity_idx, + const char *nickname, + int is_hsdir) +{ + routerstatus_t *rs = tor_malloc_zero(sizeof(routerstatus_t)); + routerinfo_t *ri = tor_malloc_zero(sizeof(routerinfo_t)); + uint8_t identity[DIGEST_LEN]; + tor_addr_t ipv4_addr; + node_t *node = NULL; + + memset(identity, identity_idx, sizeof(identity)); + + memcpy(rs->identity_digest, identity, DIGEST_LEN); + rs->is_hs_dir = is_hsdir; + rs->supports_v3_hsdir = 1; + strlcpy(rs->nickname, nickname, sizeof(rs->nickname)); + tor_addr_parse(&ipv4_addr, "1.2.3.4"); + ri->addr = tor_addr_to_ipv4h(&ipv4_addr); + rs->addr = tor_addr_to_ipv4h(&ipv4_addr); + ri->nickname = tor_strdup(nickname); + ri->protocol_list = tor_strdup("HSDir=1-2 LinkAuth=3"); + memcpy(ri->cache_info.identity_digest, identity, DIGEST_LEN); + ri->cache_info.signing_key_cert = tor_malloc_zero(sizeof(tor_cert_t)); + /* Needed for the HSDir index computation. */ + memset(&ri->cache_info.signing_key_cert->signing_key, + identity_idx, ED25519_PUBKEY_LEN); + tt_assert(nodelist_set_routerinfo(ri, NULL)); + + node = node_get_mutable_by_id(ri->cache_info.identity_digest); + tt_assert(node); + node->rs = rs; + /* We need this to exist for node_has_descriptor() to return true. */ + node->md = tor_malloc_zero(sizeof(microdesc_t)); + /* Do this now the nodelist_set_routerinfo() function needs a "rs" to set + * the indexes which it doesn't have when it is called. */ + node_set_hsdir_index(node, ns); + node->ri = NULL; + smartlist_add(ns->routerstatus_list, rs); + + done: + if (node == NULL) + routerstatus_free(rs); + + routerinfo_free(ri); +} + +static networkstatus_t *mock_ns = NULL; + +static networkstatus_t * +mock_networkstatus_get_latest_consensus(void) +{ + time_t now = approx_time(); + + /* If initialized, return it */ + if (mock_ns) { + return mock_ns; + } + + /* Initialize fake consensus */ + mock_ns = tor_malloc_zero(sizeof(networkstatus_t)); + + /* This consensus is live */ + mock_ns->valid_after = now-1; + mock_ns->fresh_until = now+1; + mock_ns->valid_until = now+2; + /* Create routerstatus list */ + mock_ns->routerstatus_list = smartlist_new(); + mock_ns->type = NS_TYPE_CONSENSUS; + + return mock_ns; +} + +static networkstatus_t * +mock_networkstatus_get_live_consensus(time_t now) +{ + (void) now; + + tt_assert(mock_ns); + + done: + return mock_ns; +} + +/** Test the responsible HSDirs calculation function */ +static void +test_responsible_hsdirs(void *arg) +{ + time_t now = approx_time(); + smartlist_t *responsible_dirs = smartlist_new(); + networkstatus_t *ns = NULL; + int retval; + + (void) arg; + + hs_init(); + + MOCK(networkstatus_get_latest_consensus, + mock_networkstatus_get_latest_consensus); + + ns = networkstatus_get_latest_consensus(); + + { /* First router: HSdir */ + helper_add_hsdir_to_networkstatus(ns, 1, "igor", 1); + } + + { /* Second HSDir */ + helper_add_hsdir_to_networkstatus(ns, 2, "victor", 1); + } + + { /* Third relay but not HSDir */ + helper_add_hsdir_to_networkstatus(ns, 3, "spyro", 0); + } + + ed25519_keypair_t kp; + retval = ed25519_keypair_generate(&kp, 0); + tt_int_op(retval, OP_EQ , 0); + + uint64_t time_period_num = hs_get_time_period_num(now); + hs_get_responsible_hsdirs(&kp.pubkey, time_period_num, + 0, 0, responsible_dirs); + + /* Make sure that we only found 2 responsible HSDirs. + * The third relay was not an hsdir! */ + tt_int_op(smartlist_len(responsible_dirs), OP_EQ, 2); + + /** TODO: Build a bigger network and do more tests here */ + + done: + SMARTLIST_FOREACH(ns->routerstatus_list, + routerstatus_t *, rs, routerstatus_free(rs)); + smartlist_free(responsible_dirs); + smartlist_clear(ns->routerstatus_list); + networkstatus_vote_free(mock_ns); + cleanup_nodelist(); +} + +static void +mock_directory_initiate_request(directory_request_t *req) +{ + (void)req; + return; +} + +static int +mock_hs_desc_encode_descriptor(const hs_descriptor_t *desc, + const ed25519_keypair_t *signing_kp, + char **encoded_out) +{ + (void)desc; + (void)signing_kp; + + tor_asprintf(encoded_out, "lulu"); + return 0; +} + +static or_state_t dummy_state; + +/* Mock function to get fake or state (used for rev counters) */ +static or_state_t * +get_or_state_replacement(void) +{ + return &dummy_state; +} + +static int +mock_router_have_minimum_dir_info(void) +{ + return 1; +} + +/** Test that we correctly detect when the HSDir hash ring changes so that we + * reupload our descriptor. */ +static void +test_desc_reupload_logic(void *arg) +{ + networkstatus_t *ns = NULL; + + (void) arg; + + hs_init(); + + MOCK(router_have_minimum_dir_info, + mock_router_have_minimum_dir_info); + MOCK(get_or_state, + get_or_state_replacement); + MOCK(networkstatus_get_latest_consensus, + mock_networkstatus_get_latest_consensus); + MOCK(directory_initiate_request, + mock_directory_initiate_request); + MOCK(hs_desc_encode_descriptor, + mock_hs_desc_encode_descriptor); + + ns = networkstatus_get_latest_consensus(); + + /** Test logic: + * 1) Upload descriptor to HSDirs + * CHECK that previous_hsdirs list was populated. + * 2) Then call router_dir_info_changed() without an HSDir set change. + * CHECK that no reuplod occurs. + * 3) Now change the HSDir set, and call dir_info_changed() again. + * CHECK that reupload occurs. + * 4) Finally call service_desc_schedule_upload(). + * CHECK that previous_hsdirs list was cleared. + **/ + + /* Let's start by building our descriptor and service */ + hs_service_descriptor_t *desc = service_descriptor_new(); + hs_service_t *service = NULL; + /* hex-encoded ed25519 pubkey used in hs_build_address.py */ + char pubkey_hex[] = + "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a"; + char onion_addr[HS_SERVICE_ADDR_LEN_BASE32 + 1]; + ed25519_public_key_t pubkey; + base16_decode((char*)pubkey.pubkey, sizeof(pubkey.pubkey), + pubkey_hex, strlen(pubkey_hex)); + hs_build_address(&pubkey, HS_VERSION_THREE, onion_addr); + service = tor_malloc_zero(sizeof(hs_service_t)); + memcpy(service->onion_address, onion_addr, sizeof(service->onion_address)); + ed25519_secret_key_generate(&service->keys.identity_sk, 0); + ed25519_public_key_generate(&service->keys.identity_pk, + &service->keys.identity_sk); + service->desc_current = desc; + /* Also add service to service map */ + hs_service_ht *service_map = get_hs_service_map(); + tt_assert(service_map); + tt_int_op(hs_service_get_num_services(), OP_EQ, 0); + register_service(service_map, service); + tt_int_op(hs_service_get_num_services(), OP_EQ, 1); + + /* Now let's create our hash ring: */ + { + helper_add_hsdir_to_networkstatus(ns, 1, "dingus", 1); + helper_add_hsdir_to_networkstatus(ns, 2, "clive", 1); + helper_add_hsdir_to_networkstatus(ns, 3, "aaron", 1); + helper_add_hsdir_to_networkstatus(ns, 4, "lizzie", 1); + helper_add_hsdir_to_networkstatus(ns, 5, "daewon", 1); + helper_add_hsdir_to_networkstatus(ns, 6, "clarke", 1); + } + + /* Now let's upload our desc to all hsdirs */ + upload_descriptor_to_all(service, desc); + /* Check that previous hsdirs were populated */ + tt_int_op(smartlist_len(desc->previous_hsdirs), OP_EQ, 6); + + /* Poison next upload time so that we can see if it was changed by + * router_dir_info_changed(). No changes in hash ring so far, so the upload + * time should stay as is. */ + desc->next_upload_time = 42; + router_dir_info_changed(); + tt_int_op(desc->next_upload_time, OP_EQ, 42); + + /* Now change the HSDir hash ring by swapping nora for aaron. + * Start by clearing the hash ring */ + { + SMARTLIST_FOREACH(ns->routerstatus_list, + routerstatus_t *, rs, routerstatus_free(rs)); + smartlist_clear(ns->routerstatus_list); + cleanup_nodelist(); + routerlist_free_all(); + } + + { /* Now add back all the nodes */ + helper_add_hsdir_to_networkstatus(ns, 1, "dingus", 1); + helper_add_hsdir_to_networkstatus(ns, 2, "clive", 1); + helper_add_hsdir_to_networkstatus(ns, 4, "lizzie", 1); + helper_add_hsdir_to_networkstatus(ns, 5, "daewon", 1); + helper_add_hsdir_to_networkstatus(ns, 6, "clarke", 1); + helper_add_hsdir_to_networkstatus(ns, 7, "nora", 1); + } + + /* Now call service_desc_hsdirs_changed() and see that it detected the hash + ring change */ + time_t now = approx_time(); + tt_assert(now); + tt_int_op(service_desc_hsdirs_changed(service, desc), OP_EQ, 1); + tt_int_op(smartlist_len(desc->previous_hsdirs), OP_EQ, 6); + + /* Now order another upload and see that we keep having 6 prev hsdirs */ + upload_descriptor_to_all(service, desc); + /* Check that previous hsdirs were populated */ + tt_int_op(smartlist_len(desc->previous_hsdirs), OP_EQ, 6); + + /* Now restore the HSDir hash ring to its original state by swapping back + aaron for nora */ + /* First clear up the hash ring */ + { + SMARTLIST_FOREACH(ns->routerstatus_list, + routerstatus_t *, rs, routerstatus_free(rs)); + smartlist_clear(ns->routerstatus_list); + cleanup_nodelist(); + routerlist_free_all(); + } + + { /* Now populate the hash ring again */ + helper_add_hsdir_to_networkstatus(ns, 1, "dingus", 1); + helper_add_hsdir_to_networkstatus(ns, 2, "clive", 1); + helper_add_hsdir_to_networkstatus(ns, 3, "aaron", 1); + helper_add_hsdir_to_networkstatus(ns, 4, "lizzie", 1); + helper_add_hsdir_to_networkstatus(ns, 5, "daewon", 1); + helper_add_hsdir_to_networkstatus(ns, 6, "clarke", 1); + } + + /* Check that our algorithm catches this change of hsdirs */ + tt_int_op(service_desc_hsdirs_changed(service, desc), OP_EQ, 1); + + /* Now pretend that the descriptor changed, and order a reupload to all + HSDirs. Make sure that the set of previous HSDirs was cleared. */ + service_desc_schedule_upload(desc, now, 1); + tt_int_op(smartlist_len(desc->previous_hsdirs), OP_EQ, 0); + + /* Now reupload again: see that the prev hsdir set got populated again. */ + upload_descriptor_to_all(service, desc); + tt_int_op(smartlist_len(desc->previous_hsdirs), OP_EQ, 6); + + done: + SMARTLIST_FOREACH(ns->routerstatus_list, + routerstatus_t *, rs, routerstatus_free(rs)); + smartlist_clear(ns->routerstatus_list); + networkstatus_vote_free(ns); + cleanup_nodelist(); + hs_free_all(); +} + +/** Test disaster SRV computation and caching */ +static void +test_disaster_srv(void *arg) +{ + uint8_t *cached_disaster_srv_one = NULL; + uint8_t *cached_disaster_srv_two = NULL; + uint8_t srv_one[DIGEST256_LEN] = {0}; + uint8_t srv_two[DIGEST256_LEN] = {0}; + uint8_t srv_three[DIGEST256_LEN] = {0}; + uint8_t srv_four[DIGEST256_LEN] = {0}; + uint8_t srv_five[DIGEST256_LEN] = {0}; + + (void) arg; + + /* Get the cached SRVs: we gonna use them later for verification */ + cached_disaster_srv_one = get_first_cached_disaster_srv(); + cached_disaster_srv_two = get_second_cached_disaster_srv(); + + /* Compute some srvs */ + get_disaster_srv(1, srv_one); + get_disaster_srv(2, srv_two); + + /* Check that the cached ones where updated */ + tt_mem_op(cached_disaster_srv_one, OP_EQ, srv_one, DIGEST256_LEN); + tt_mem_op(cached_disaster_srv_two, OP_EQ, srv_two, DIGEST256_LEN); + + /* Ask for an SRV that has already been computed */ + get_disaster_srv(2, srv_two); + /* and check that the cache entries have not changed */ + tt_mem_op(cached_disaster_srv_one, OP_EQ, srv_one, DIGEST256_LEN); + tt_mem_op(cached_disaster_srv_two, OP_EQ, srv_two, DIGEST256_LEN); + + /* Ask for a new SRV */ + get_disaster_srv(3, srv_three); + tt_mem_op(cached_disaster_srv_one, OP_EQ, srv_three, DIGEST256_LEN); + tt_mem_op(cached_disaster_srv_two, OP_EQ, srv_two, DIGEST256_LEN); + + /* Ask for another SRV: none of the original SRVs should now be cached */ + get_disaster_srv(4, srv_four); + tt_mem_op(cached_disaster_srv_one, OP_EQ, srv_three, DIGEST256_LEN); + tt_mem_op(cached_disaster_srv_two, OP_EQ, srv_four, DIGEST256_LEN); + + /* Ask for yet another SRV */ + get_disaster_srv(5, srv_five); + tt_mem_op(cached_disaster_srv_one, OP_EQ, srv_five, DIGEST256_LEN); + tt_mem_op(cached_disaster_srv_two, OP_EQ, srv_four, DIGEST256_LEN); + + done: + ; +} + +/** Test our HS descriptor request tracker by making various requests and + * checking whether they get tracked properly. */ +static void +test_hid_serv_request_tracker(void *arg) +{ + (void) arg; + time_t retval; + routerstatus_t *hsdir = NULL, *hsdir2 = NULL, *hsdir3 = NULL; + time_t now = approx_time(); + + const char *req_key_str_first = + "vd4zb6zesaubtrjvdqcr2w7x7lhw2up4Xnw4526ThUNbL5o1go+EdUuEqlKxHkNbnK41pRzizzs"; + const char *req_key_str_second = + "g53o7iavcd62oihswhr24u6czmqws5kpXnw4526ThUNbL5o1go+EdUuEqlKxHkNbnK41pRzizzs"; + const char *req_key_str_small = "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"; + + /*************************** basic test *******************************/ + + /* Get request tracker and make sure it's empty */ + strmap_t *request_tracker = get_last_hid_serv_requests(); + tt_int_op(strmap_size(request_tracker),OP_EQ, 0); + + /* Let's register a hid serv request */ + hsdir = tor_malloc_zero(sizeof(routerstatus_t)); + memset(hsdir->identity_digest, 'Z', DIGEST_LEN); + retval = hs_lookup_last_hid_serv_request(hsdir, req_key_str_first, + now, 1); + tt_int_op(retval, OP_EQ, now); + tt_int_op(strmap_size(request_tracker),OP_EQ, 1); + + /* Let's lookup a non-existent hidserv request */ + retval = hs_lookup_last_hid_serv_request(hsdir, req_key_str_second, + now+1, 0); + tt_int_op(retval, OP_EQ, 0); + tt_int_op(strmap_size(request_tracker),OP_EQ, 1); + + /* Let's lookup a real hidserv request */ + retval = hs_lookup_last_hid_serv_request(hsdir, req_key_str_first, + now+2, 0); + tt_int_op(retval, OP_EQ, now); /* we got it */ + tt_int_op(strmap_size(request_tracker),OP_EQ, 1); + + /**********************************************************************/ + + /* Let's add another request for the same HS but on a different HSDir. */ + hsdir2 = tor_malloc_zero(sizeof(routerstatus_t)); + memset(hsdir2->identity_digest, 2, DIGEST_LEN); + retval = hs_lookup_last_hid_serv_request(hsdir2, req_key_str_first, + now+3, 1); + tt_int_op(retval, OP_EQ, now+3); + tt_int_op(strmap_size(request_tracker),OP_EQ, 2); + + /* Check that we can clean the first request based on time */ + hs_clean_last_hid_serv_requests(now+3+REND_HID_SERV_DIR_REQUERY_PERIOD); + tt_int_op(strmap_size(request_tracker),OP_EQ, 1); + /* Check that it doesn't exist anymore */ + retval = hs_lookup_last_hid_serv_request(hsdir, req_key_str_first, + now+2, 0); + tt_int_op(retval, OP_EQ, 0); + + /* Now let's add a smaller req key str */ + hsdir3 = tor_malloc_zero(sizeof(routerstatus_t)); + memset(hsdir3->identity_digest, 3, DIGEST_LEN); + retval = hs_lookup_last_hid_serv_request(hsdir3, req_key_str_small, + now+4, 1); + tt_int_op(retval, OP_EQ, now+4); + tt_int_op(strmap_size(request_tracker),OP_EQ, 2); + + /*************************** deleting entries **************************/ + + /* Add another request with very short key */ + retval = hs_lookup_last_hid_serv_request(hsdir, "l", now, 1); + tt_int_op(retval, OP_EQ, now); + tt_int_op(strmap_size(request_tracker),OP_EQ, 3); + + /* Try deleting entries with a dummy key. Check that our previous requests + * are still there */ + tor_capture_bugs_(1); + hs_purge_hid_serv_from_last_hid_serv_requests("a"); + tt_int_op(strmap_size(request_tracker),OP_EQ, 3); + tor_end_capture_bugs_(); + + /* Try another dummy key. Check that requests are still there */ + { + char dummy[2000]; + memset(dummy, 'Z', 2000); + dummy[1999] = '\x00'; + hs_purge_hid_serv_from_last_hid_serv_requests(dummy); + tt_int_op(strmap_size(request_tracker),OP_EQ, 3); + } + + /* Another dummy key! */ + hs_purge_hid_serv_from_last_hid_serv_requests(req_key_str_second); + tt_int_op(strmap_size(request_tracker),OP_EQ, 3); + + /* Now actually delete a request! */ + hs_purge_hid_serv_from_last_hid_serv_requests(req_key_str_first); + tt_int_op(strmap_size(request_tracker),OP_EQ, 2); + + /* Purge it all! */ + hs_purge_last_hid_serv_requests(); + request_tracker = get_last_hid_serv_requests(); + tt_int_op(strmap_size(request_tracker),OP_EQ, 0); + + done: + tor_free(hsdir); + tor_free(hsdir2); + tor_free(hsdir3); +} + +static void +test_parse_extended_hostname(void *arg) +{ + (void) arg; + + char address1[] = "fooaddress.onion"; + char address2[] = "aaaaaaaaaaaaaaaa.onion"; + char address3[] = "fooaddress.exit"; + char address4[] = "www.torproject.org"; + char address5[] = "foo.abcdefghijklmnop.onion"; + char address6[] = "foo.bar.abcdefghijklmnop.onion"; + char address7[] = ".abcdefghijklmnop.onion"; + char address8[] = + "www.25njqamcweflpvkl73j4szahhihoc4xt3ktcgjnpaingr5yhkenl5sid.onion"; + + tt_assert(BAD_HOSTNAME == parse_extended_hostname(address1)); + tt_assert(ONION_V2_HOSTNAME == parse_extended_hostname(address2)); + tt_str_op(address2,OP_EQ, "aaaaaaaaaaaaaaaa"); + tt_assert(EXIT_HOSTNAME == parse_extended_hostname(address3)); + tt_assert(NORMAL_HOSTNAME == parse_extended_hostname(address4)); + tt_assert(ONION_V2_HOSTNAME == parse_extended_hostname(address5)); + tt_str_op(address5,OP_EQ, "abcdefghijklmnop"); + tt_assert(ONION_V2_HOSTNAME == parse_extended_hostname(address6)); + tt_str_op(address6,OP_EQ, "abcdefghijklmnop"); + tt_assert(BAD_HOSTNAME == parse_extended_hostname(address7)); + tt_assert(ONION_V3_HOSTNAME == parse_extended_hostname(address8)); + tt_str_op(address8, OP_EQ, + "25njqamcweflpvkl73j4szahhihoc4xt3ktcgjnpaingr5yhkenl5sid"); + + done: ; +} + +static void +test_time_between_tp_and_srv(void *arg) +{ + int ret; + networkstatus_t ns; + (void) arg; + + /* This function should be returning true where "^" are: + * + * +------------------------------------------------------------------+ + * | | + * | 00:00 12:00 00:00 12:00 00:00 12:00 | + * | SRV#1 TP#1 SRV#2 TP#2 SRV#3 TP#3 | + * | | + * | $==========|-----------$===========|-----------$===========| | + * | ^^^^^^^^^^^^ ^^^^^^^^^^^^ | + * | | + * +------------------------------------------------------------------+ + */ + + ret = parse_rfc1123_time("Sat, 26 Oct 1985 00:00:00 UTC", &ns.valid_after); + tt_int_op(ret, OP_EQ, 0); + ret = parse_rfc1123_time("Sat, 26 Oct 1985 01:00:00 UTC", &ns.fresh_until); + tt_int_op(ret, OP_EQ, 0); + dirvote_recalculate_timing(get_options(), ns.valid_after); + ret = hs_in_period_between_tp_and_srv(&ns, 0); + tt_int_op(ret, OP_EQ, 0); + + ret = parse_rfc1123_time("Sat, 26 Oct 1985 11:00:00 UTC", &ns.valid_after); + tt_int_op(ret, OP_EQ, 0); + ret = parse_rfc1123_time("Sat, 26 Oct 1985 12:00:00 UTC", &ns.fresh_until); + tt_int_op(ret, OP_EQ, 0); + dirvote_recalculate_timing(get_options(), ns.valid_after); + ret = hs_in_period_between_tp_and_srv(&ns, 0); + tt_int_op(ret, OP_EQ, 0); + + ret = parse_rfc1123_time("Sat, 26 Oct 1985 12:00:00 UTC", &ns.valid_after); + tt_int_op(ret, OP_EQ, 0); + ret = parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC", &ns.fresh_until); + tt_int_op(ret, OP_EQ, 0); + dirvote_recalculate_timing(get_options(), ns.valid_after); + ret = hs_in_period_between_tp_and_srv(&ns, 0); + tt_int_op(ret, OP_EQ, 1); + + ret = parse_rfc1123_time("Sat, 26 Oct 1985 23:00:00 UTC", &ns.valid_after); + tt_int_op(ret, OP_EQ, 0); + ret = parse_rfc1123_time("Sat, 27 Oct 1985 00:00:00 UTC", &ns.fresh_until); + tt_int_op(ret, OP_EQ, 0); + dirvote_recalculate_timing(get_options(), ns.valid_after); + ret = hs_in_period_between_tp_and_srv(&ns, 0); + tt_int_op(ret, OP_EQ, 1); + + ret = parse_rfc1123_time("Sat, 27 Oct 1985 00:00:00 UTC", &ns.valid_after); + tt_int_op(ret, OP_EQ, 0); + ret = parse_rfc1123_time("Sat, 27 Oct 1985 01:00:00 UTC", &ns.fresh_until); + tt_int_op(ret, OP_EQ, 0); + dirvote_recalculate_timing(get_options(), ns.valid_after); + ret = hs_in_period_between_tp_and_srv(&ns, 0); + tt_int_op(ret, OP_EQ, 0); + + done: + ; +} + +/************ Reachability Test (it is huge) ****************/ + +/* Simulate different consensus for client and service. Used by the + * reachability test. The SRV and responsible HSDir list are used by all + * reachability tests so make them common to simplify setup and teardown. */ +static networkstatus_t *mock_service_ns = NULL; +static networkstatus_t *mock_client_ns = NULL; +static sr_srv_t current_srv, previous_srv; +static smartlist_t *service_responsible_hsdirs = NULL; +static smartlist_t *client_responsible_hsdirs = NULL; + +static networkstatus_t * +mock_networkstatus_get_live_consensus_service(time_t now) +{ + (void) now; + + if (mock_service_ns) { + return mock_service_ns; + } + + mock_service_ns = tor_malloc_zero(sizeof(networkstatus_t)); + mock_service_ns->routerstatus_list = smartlist_new(); + mock_service_ns->type = NS_TYPE_CONSENSUS; + + return mock_service_ns; +} + +static networkstatus_t * +mock_networkstatus_get_latest_consensus_service(void) +{ + return mock_networkstatus_get_live_consensus_service(0); +} + +static networkstatus_t * +mock_networkstatus_get_live_consensus_client(time_t now) +{ + (void) now; + + if (mock_client_ns) { + return mock_client_ns; + } + + mock_client_ns = tor_malloc_zero(sizeof(networkstatus_t)); + mock_client_ns->routerstatus_list = smartlist_new(); + mock_client_ns->type = NS_TYPE_CONSENSUS; + + return mock_client_ns; +} + +static networkstatus_t * +mock_networkstatus_get_latest_consensus_client(void) +{ + return mock_networkstatus_get_live_consensus_client(0); +} + +/* Mock function because we are not trying to test the close circuit that does + * an awful lot of checks on the circuit object. */ +static void +mock_circuit_mark_for_close(circuit_t *circ, int reason, int line, + const char *file) +{ + (void) circ; + (void) reason; + (void) line; + (void) file; + return; +} + +/* Initialize a big HSDir V3 hash ring. */ +static void +helper_initialize_big_hash_ring(networkstatus_t *ns) +{ + int ret; + + /* Generate 250 hsdirs! :) */ + for (int counter = 1 ; counter < 251 ; counter++) { + /* Let's generate random nickname for each hsdir... */ + char nickname_binary[8]; + char nickname_str[13] = {0}; + crypto_rand(nickname_binary, sizeof(nickname_binary)); + ret = base64_encode(nickname_str, sizeof(nickname_str), + nickname_binary, sizeof(nickname_binary), 0); + tt_int_op(ret, OP_EQ, 12); + helper_add_hsdir_to_networkstatus(ns, counter, nickname_str, 1); + } + + /* Make sure we have 200 hsdirs in our list */ + tt_int_op(smartlist_len(ns->routerstatus_list), OP_EQ, 250); + + done: + ; +} + +/** Initialize service and publish its descriptor as needed. Return the newly + * allocated service object to the caller. */ +static hs_service_t * +helper_init_service(time_t now) +{ + int retval; + hs_service_t *service = hs_service_new(get_options()); + tt_assert(service); + service->config.version = HS_VERSION_THREE; + ed25519_secret_key_generate(&service->keys.identity_sk, 0); + ed25519_public_key_generate(&service->keys.identity_pk, + &service->keys.identity_sk); + /* Register service to global map. */ + retval = register_service(get_hs_service_map(), service); + tt_int_op(retval, OP_EQ, 0); + + /* Initialize service descriptor */ + build_all_descriptors(now); + tt_assert(service->desc_current); + tt_assert(service->desc_next); + + done: + return service; +} + +/* Helper function to set the RFC 1123 time string into t. */ +static void +set_consensus_times(const char *timestr, time_t *t) +{ + tt_assert(timestr); + tt_assert(t); + + int ret = parse_rfc1123_time(timestr, t); + tt_int_op(ret, OP_EQ, 0); + + done: + return; +} + +/* Helper function to cleanup the mock consensus (client and service) */ +static void +cleanup_mock_ns(void) +{ + if (mock_service_ns) { + SMARTLIST_FOREACH(mock_service_ns->routerstatus_list, + routerstatus_t *, rs, routerstatus_free(rs)); + smartlist_clear(mock_service_ns->routerstatus_list); + mock_service_ns->sr_info.current_srv = NULL; + mock_service_ns->sr_info.previous_srv = NULL; + networkstatus_vote_free(mock_service_ns); + mock_service_ns = NULL; + } + + if (mock_client_ns) { + SMARTLIST_FOREACH(mock_client_ns->routerstatus_list, + routerstatus_t *, rs, routerstatus_free(rs)); + smartlist_clear(mock_client_ns->routerstatus_list); + mock_client_ns->sr_info.current_srv = NULL; + mock_client_ns->sr_info.previous_srv = NULL; + networkstatus_vote_free(mock_client_ns); + mock_client_ns = NULL; + } +} + +/* Helper function to setup a reachability test. Once called, the + * cleanup_reachability_test MUST be called at the end. */ +static void +setup_reachability_test(void) +{ + MOCK(circuit_mark_for_close_, mock_circuit_mark_for_close); + MOCK(get_or_state, get_or_state_replacement); + + hs_init(); + + /* Baseline to start with. */ + memset(¤t_srv, 0, sizeof(current_srv)); + memset(&previous_srv, 1, sizeof(previous_srv)); + + /* Initialize the consensuses. */ + mock_networkstatus_get_latest_consensus_service(); + mock_networkstatus_get_latest_consensus_client(); + + service_responsible_hsdirs = smartlist_new(); + client_responsible_hsdirs = smartlist_new(); +} + +/* Helper function to cleanup a reachability test initial setup. */ +static void +cleanup_reachability_test(void) +{ + smartlist_free(service_responsible_hsdirs); + service_responsible_hsdirs = NULL; + smartlist_free(client_responsible_hsdirs); + client_responsible_hsdirs = NULL; + hs_free_all(); + cleanup_mock_ns(); + UNMOCK(get_or_state); + UNMOCK(circuit_mark_for_close_); +} + +/* A reachability test always check if the resulting service and client + * responsible HSDir for the given parameters are equal. + * + * Return true iff the same exact nodes are in both list. */ +static int +are_responsible_hsdirs_equal(void) +{ + int count = 0; + tt_int_op(smartlist_len(client_responsible_hsdirs), OP_EQ, 6); + tt_int_op(smartlist_len(service_responsible_hsdirs), OP_EQ, 8); + + SMARTLIST_FOREACH_BEGIN(client_responsible_hsdirs, + const routerstatus_t *, c_rs) { + SMARTLIST_FOREACH_BEGIN(service_responsible_hsdirs, + const routerstatus_t *, s_rs) { + if (tor_memeq(c_rs->identity_digest, s_rs->identity_digest, + DIGEST_LEN)) { + count++; + break; + } + } SMARTLIST_FOREACH_END(s_rs); + } SMARTLIST_FOREACH_END(c_rs); + + done: + return (count == 6); +} + +/* Tor doesn't use such a function to get the previous HSDir, it is only used + * in node_set_hsdir_index(). We need it here so we can test the reachability + * scenario 6 that requires the previous time period to compute the list of + * responsible HSDir because of the client state timing. */ +static uint64_t +get_previous_time_period(time_t now) +{ + return hs_get_time_period_num(now) - 1; +} + +/* Configuration of a reachability test scenario. */ +typedef struct reachability_cfg_t { + /* Consensus timings to be set. They have to be compliant with + * RFC 1123 time format. */ + const char *service_valid_after; + const char *service_valid_until; + const char *client_valid_after; + const char *client_valid_until; + + /* SRVs that the service and client should use. */ + sr_srv_t *service_current_srv; + sr_srv_t *service_previous_srv; + sr_srv_t *client_current_srv; + sr_srv_t *client_previous_srv; + + /* A time period function for the service to use for this scenario. For a + * successful reachability test, the client always use the current time + * period thus why no client function. */ + uint64_t (*service_time_period_fn)(time_t); + + /* Is the client and service expected to be in a new time period. After + * setting the consensus time, the reachability test checks + * hs_in_period_between_tp_and_srv() and test the returned value against + * this. */ + unsigned int service_in_new_tp; + unsigned int client_in_new_tp; + + /* Some scenario requires a hint that the client, because of its consensus + * time, will request the "next" service descriptor so this indicates if it + * is the case or not. */ + unsigned int client_fetch_next_desc; +} reachability_cfg_t; + +/* Some defines to help with semantic while reading a configuration below. */ +#define NOT_IN_NEW_TP 0 +#define IN_NEW_TP 1 +#define DONT_NEED_NEXT_DESC 0 +#define NEED_NEXT_DESC 1 + +static reachability_cfg_t reachability_scenarios[] = { + /* Scenario 1 + * + * +------------------------------------------------------------------+ + * | | + * | 00:00 12:00 00:00 12:00 00:00 12:00 | + * | SRV#1 TP#1 SRV#2 TP#2 SRV#3 TP#3 | + * | | + * | $==========|-----------$===========|-----------$===========| | + * | ^ ^ | + * | S C | + * +------------------------------------------------------------------+ + * + * S: Service, C: Client + * + * Service consensus valid_after time is set to 13:00 and client to 15:00, + * both are after TP#1 thus have access to SRV#1. Service and client should + * be using TP#1. + */ + + { "Sat, 26 Oct 1985 13:00:00 UTC", /* Service valid_after */ + "Sat, 26 Oct 1985 14:00:00 UTC", /* Service valid_until */ + "Sat, 26 Oct 1985 15:00:00 UTC", /* Client valid_after */ + "Sat, 26 Oct 1985 16:00:00 UTC", /* Client valid_until. */ + ¤t_srv, NULL, /* Service current and previous SRV */ + ¤t_srv, NULL, /* Client current and previous SRV */ + hs_get_time_period_num, /* Service time period function. */ + IN_NEW_TP, /* Is service in new TP? */ + IN_NEW_TP, /* Is client in new TP? */ + NEED_NEXT_DESC }, + + /* Scenario 2 + * + * +------------------------------------------------------------------+ + * | | + * | 00:00 12:00 00:00 12:00 00:00 12:00 | + * | SRV#1 TP#1 SRV#2 TP#2 SRV#3 TP#3 | + * | | + * | $==========|-----------$===========|-----------$===========| | + * | ^ ^ | + * | S C | + * +------------------------------------------------------------------+ + * + * S: Service, C: Client + * + * Service consensus valid_after time is set to 23:00 and client to 01:00, + * which makes the client after the SRV#2 and the service just before. The + * service should only be using TP#1. The client should be using TP#1. + */ + + { "Sat, 26 Oct 1985 23:00:00 UTC", /* Service valid_after */ + "Sat, 27 Oct 1985 00:00:00 UTC", /* Service valid_until */ + "Sat, 27 Oct 1985 01:00:00 UTC", /* Client valid_after */ + "Sat, 27 Oct 1985 02:00:00 UTC", /* Client valid_until. */ + &previous_srv, NULL, /* Service current and previous SRV */ + ¤t_srv, &previous_srv, /* Client current and previous SRV */ + hs_get_time_period_num, /* Service time period function. */ + IN_NEW_TP, /* Is service in new TP? */ + NOT_IN_NEW_TP, /* Is client in new TP? */ + NEED_NEXT_DESC }, + + /* Scenario 3 + * + * +------------------------------------------------------------------+ + * | | + * | 00:00 12:00 00:00 12:00 00:00 12:00 | + * | SRV#1 TP#1 SRV#2 TP#2 SRV#3 TP#3 | + * | | + * | $==========|-----------$===========|----------$===========| | + * | ^ ^ | + * | S C | + * +------------------------------------------------------------------+ + * + * S: Service, C: Client + * + * Service consensus valid_after time is set to 03:00 and client to 05:00, + * which makes both after SRV#2. The service should be using TP#1 as its + * current time period. The client should be using TP#1. + */ + + { "Sat, 27 Oct 1985 03:00:00 UTC", /* Service valid_after */ + "Sat, 27 Oct 1985 04:00:00 UTC", /* Service valid_until */ + "Sat, 27 Oct 1985 05:00:00 UTC", /* Client valid_after */ + "Sat, 27 Oct 1985 06:00:00 UTC", /* Client valid_until. */ + ¤t_srv, &previous_srv, /* Service current and previous SRV */ + ¤t_srv, &previous_srv, /* Client current and previous SRV */ + hs_get_time_period_num, /* Service time period function. */ + NOT_IN_NEW_TP, /* Is service in new TP? */ + NOT_IN_NEW_TP, /* Is client in new TP? */ + DONT_NEED_NEXT_DESC }, + + /* Scenario 4 + * + * +------------------------------------------------------------------+ + * | | + * | 00:00 12:00 00:00 12:00 00:00 12:00 | + * | SRV#1 TP#1 SRV#2 TP#2 SRV#3 TP#3 | + * | | + * | $==========|-----------$===========|-----------$===========| | + * | ^ ^ | + * | S C | + * +------------------------------------------------------------------+ + * + * S: Service, C: Client + * + * Service consensus valid_after time is set to 11:00 and client to 13:00, + * which makes the service before TP#2 and the client just after. The + * service should be using TP#1 as its current time period and TP#2 as the + * next. The client should be using TP#2 time period. + */ + + { "Sat, 27 Oct 1985 11:00:00 UTC", /* Service valid_after */ + "Sat, 27 Oct 1985 12:00:00 UTC", /* Service valid_until */ + "Sat, 27 Oct 1985 13:00:00 UTC", /* Client valid_after */ + "Sat, 27 Oct 1985 14:00:00 UTC", /* Client valid_until. */ + ¤t_srv, &previous_srv, /* Service current and previous SRV */ + ¤t_srv, &previous_srv, /* Client current and previous SRV */ + hs_get_next_time_period_num, /* Service time period function. */ + NOT_IN_NEW_TP, /* Is service in new TP? */ + IN_NEW_TP, /* Is client in new TP? */ + NEED_NEXT_DESC }, + + /* Scenario 5 + * + * +------------------------------------------------------------------+ + * | | + * | 00:00 12:00 00:00 12:00 00:00 12:00 | + * | SRV#1 TP#1 SRV#2 TP#2 SRV#3 TP#3 | + * | | + * | $==========|-----------$===========|-----------$===========| | + * | ^ ^ | + * | C S | + * +------------------------------------------------------------------+ + * + * S: Service, C: Client + * + * Service consensus valid_after time is set to 01:00 and client to 23:00, + * which makes the service after SRV#2 and the client just before. The + * service should be using TP#1 as its current time period and TP#2 as the + * next. The client should be using TP#1 time period. + */ + + { "Sat, 27 Oct 1985 01:00:00 UTC", /* Service valid_after */ + "Sat, 27 Oct 1985 02:00:00 UTC", /* Service valid_until */ + "Sat, 26 Oct 1985 23:00:00 UTC", /* Client valid_after */ + "Sat, 27 Oct 1985 00:00:00 UTC", /* Client valid_until. */ + ¤t_srv, &previous_srv, /* Service current and previous SRV */ + &previous_srv, NULL, /* Client current and previous SRV */ + hs_get_time_period_num, /* Service time period function. */ + NOT_IN_NEW_TP, /* Is service in new TP? */ + IN_NEW_TP, /* Is client in new TP? */ + DONT_NEED_NEXT_DESC }, + + /* Scenario 6 + * + * +------------------------------------------------------------------+ + * | | + * | 00:00 12:00 00:00 12:00 00:00 12:00 | + * | SRV#1 TP#1 SRV#2 TP#2 SRV#3 TP#3 | + * | | + * | $==========|-----------$===========|-----------$===========| | + * | ^ ^ | + * | C S | + * +------------------------------------------------------------------+ + * + * S: Service, C: Client + * + * Service consensus valid_after time is set to 13:00 and client to 11:00, + * which makes the service outside after TP#2 and the client just before. + * The service should be using TP#1 as its current time period and TP#2 as + * its next. The client should be using TP#1 time period. + */ + + { "Sat, 27 Oct 1985 13:00:00 UTC", /* Service valid_after */ + "Sat, 27 Oct 1985 14:00:00 UTC", /* Service valid_until */ + "Sat, 27 Oct 1985 11:00:00 UTC", /* Client valid_after */ + "Sat, 27 Oct 1985 12:00:00 UTC", /* Client valid_until. */ + ¤t_srv, &previous_srv, /* Service current and previous SRV */ + ¤t_srv, &previous_srv, /* Client current and previous SRV */ + get_previous_time_period, /* Service time period function. */ + IN_NEW_TP, /* Is service in new TP? */ + NOT_IN_NEW_TP, /* Is client in new TP? */ + DONT_NEED_NEXT_DESC }, + + /* End marker. */ + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0} +}; + +/* Run a single reachability scenario. num_scenario is the corresponding + * scenario number from the documentation. It is used to log it in case of + * failure so we know which scenario fails. */ +static int +run_reachability_scenario(const reachability_cfg_t *cfg, int num_scenario) +{ + int ret = -1; + hs_service_t *service; + uint64_t service_tp, client_tp; + ed25519_public_key_t service_blinded_pk, client_blinded_pk; + + setup_reachability_test(); + + tt_assert(cfg); + + /* Set service consensus time. */ + set_consensus_times(cfg->service_valid_after, + &mock_service_ns->valid_after); + set_consensus_times(cfg->service_valid_until, + &mock_service_ns->valid_until); + set_consensus_times(cfg->service_valid_until, + &mock_service_ns->fresh_until); + dirvote_recalculate_timing(get_options(), mock_service_ns->valid_after); + /* Set client consensus time. */ + set_consensus_times(cfg->client_valid_after, + &mock_client_ns->valid_after); + set_consensus_times(cfg->client_valid_until, + &mock_client_ns->valid_until); + set_consensus_times(cfg->client_valid_until, + &mock_client_ns->fresh_until); + dirvote_recalculate_timing(get_options(), mock_client_ns->valid_after); + + /* New time period checks for this scenario. */ + tt_int_op(hs_in_period_between_tp_and_srv(mock_service_ns, 0), OP_EQ, + cfg->service_in_new_tp); + tt_int_op(hs_in_period_between_tp_and_srv(mock_client_ns, 0), OP_EQ, + cfg->client_in_new_tp); + + /* Set the SRVs for this scenario. */ + mock_client_ns->sr_info.current_srv = cfg->client_current_srv; + mock_client_ns->sr_info.previous_srv = cfg->client_previous_srv; + mock_service_ns->sr_info.current_srv = cfg->service_current_srv; + mock_service_ns->sr_info.previous_srv = cfg->service_previous_srv; + + /* Initialize a service to get keys. */ + service = helper_init_service(time(NULL)); + + /* + * === Client setup === + */ + + MOCK(networkstatus_get_live_consensus, + mock_networkstatus_get_live_consensus_client); + MOCK(networkstatus_get_latest_consensus, + mock_networkstatus_get_latest_consensus_client); + + /* Make networkstatus_is_live() happy. */ + update_approx_time(mock_client_ns->valid_after); + /* Initialize a big hashring for this consensus with the hsdir index set. */ + helper_initialize_big_hash_ring(mock_client_ns); + + /* Client ONLY use the current time period. This is the whole point of these + * reachability test that is to make sure the client can always reach the + * service using only its current time period. */ + client_tp = hs_get_time_period_num(0); + + hs_build_blinded_pubkey(&service->keys.identity_pk, NULL, 0, + client_tp, &client_blinded_pk); + hs_get_responsible_hsdirs(&client_blinded_pk, client_tp, 0, 1, + client_responsible_hsdirs); + /* Cleanup the nodelist so we can let the service computes its own set of + * node with its own hashring. */ + cleanup_nodelist(); + tt_int_op(smartlist_len(client_responsible_hsdirs), OP_EQ, 6); + + UNMOCK(networkstatus_get_latest_consensus); + UNMOCK(networkstatus_get_live_consensus); + + /* + * === Service setup === + */ + + MOCK(networkstatus_get_live_consensus, + mock_networkstatus_get_live_consensus_service); + MOCK(networkstatus_get_latest_consensus, + mock_networkstatus_get_latest_consensus_service); + + /* Make networkstatus_is_live() happy. */ + update_approx_time(mock_service_ns->valid_after); + /* Initialize a big hashring for this consensus with the hsdir index set. */ + helper_initialize_big_hash_ring(mock_service_ns); + + service_tp = cfg->service_time_period_fn(0); + + hs_build_blinded_pubkey(&service->keys.identity_pk, NULL, 0, + service_tp, &service_blinded_pk); + + /* A service builds two lists of responsible HSDir, for the current and the + * next descriptor. Depending on the scenario, the client timing indicate if + * it is fetching the current or the next descriptor so we use the + * "client_fetch_next_desc" to know which one the client is trying to get to + * confirm that the service computes the same hashring for the same blinded + * key and service time period function. */ + hs_get_responsible_hsdirs(&service_blinded_pk, service_tp, + cfg->client_fetch_next_desc, 0, + service_responsible_hsdirs); + cleanup_nodelist(); + tt_int_op(smartlist_len(service_responsible_hsdirs), OP_EQ, 8); + + UNMOCK(networkstatus_get_latest_consensus); + UNMOCK(networkstatus_get_live_consensus); + + /* Some testing of the values we just got from the client and service. */ + tt_mem_op(&client_blinded_pk, OP_EQ, &service_blinded_pk, + ED25519_PUBKEY_LEN); + tt_int_op(are_responsible_hsdirs_equal(), OP_EQ, 1); + + /* Everything went well. */ + ret = 0; + + done: + cleanup_reachability_test(); + if (ret == -1) { + /* Do this so we can know which scenario failed. */ + char msg[32]; + tor_snprintf(msg, sizeof(msg), "Scenario %d failed", num_scenario); + tt_fail_msg(msg); + } + return ret; +} + +static void +test_reachability(void *arg) +{ + (void) arg; + + /* NOTE: An important axiom to understand here is that SRV#N must only be + * used with TP#N value. For example, SRV#2 with TP#1 should NEVER be used + * together. The HSDir index computation is based on this axiom.*/ + + for (int i = 0; reachability_scenarios[i].service_valid_after; ++i) { + int ret = run_reachability_scenario(&reachability_scenarios[i], i + 1); + if (ret < 0) { + return; + } + } +} + +/** Pick an HSDir for service with <b>onion_identity_pk</b> as a client. Put + * its identity digest in <b>hsdir_digest_out</b>. */ +static void +helper_client_pick_hsdir(const ed25519_public_key_t *onion_identity_pk, + char *hsdir_digest_out) +{ + tt_assert(onion_identity_pk); + + routerstatus_t *client_hsdir = pick_hsdir_v3(onion_identity_pk); + tt_assert(client_hsdir); + digest_to_base64(hsdir_digest_out, client_hsdir->identity_digest); + + done: + ; +} + +static void +test_hs_indexes(void *arg) +{ + int ret; + uint64_t period_num = 42; + ed25519_public_key_t pubkey; + + (void) arg; + + /* Build the hs_index */ + { + uint8_t hs_index[DIGEST256_LEN]; + const char *b32_test_vector = + "37e5cbbd56a22823714f18f1623ece5983a0d64c78495a8cfab854245e5f9a8a"; + char test_vector[DIGEST256_LEN]; + ret = base16_decode(test_vector, sizeof(test_vector), b32_test_vector, + strlen(b32_test_vector)); + tt_int_op(ret, OP_EQ, sizeof(test_vector)); + /* Our test vector uses a public key set to 32 bytes of \x42. */ + memset(&pubkey, '\x42', sizeof(pubkey)); + hs_build_hs_index(1, &pubkey, period_num, hs_index); + tt_mem_op(hs_index, OP_EQ, test_vector, sizeof(hs_index)); + } + + /* Build the hsdir_index */ + { + uint8_t srv[DIGEST256_LEN]; + uint8_t hsdir_index[DIGEST256_LEN]; + const char *b32_test_vector = + "db475361014a09965e7e5e4d4a25b8f8d4b8f16cb1d8a7e95eed50249cc1a2d5"; + char test_vector[DIGEST256_LEN]; + ret = base16_decode(test_vector, sizeof(test_vector), b32_test_vector, + strlen(b32_test_vector)); + tt_int_op(ret, OP_EQ, sizeof(test_vector)); + /* Our test vector uses a public key set to 32 bytes of \x42. */ + memset(&pubkey, '\x42', sizeof(pubkey)); + memset(srv, '\x43', sizeof(srv)); + hs_build_hsdir_index(&pubkey, srv, period_num, hsdir_index); + tt_mem_op(hsdir_index, OP_EQ, test_vector, sizeof(hsdir_index)); + } + + done: + ; +} + +#define EARLY_IN_SRV_TO_TP 0 +#define LATE_IN_SRV_TO_TP 1 +#define EARLY_IN_TP_TO_SRV 2 +#define LATE_IN_TP_TO_SRV 3 + +/** Set the consensus and system time based on <b>position</b>. See the + * following diagram for details: + * + * +------------------------------------------------------------------+ + * | | + * | 00:00 12:00 00:00 12:00 00:00 12:00 | + * | SRV#1 TP#1 SRV#2 TP#2 SRV#3 TP#3 | + * | | + * | $==========|-----------$===========|----------$===========| | + * | | + * | | + * +------------------------------------------------------------------+ + */ +static time_t +helper_set_consensus_and_system_time(networkstatus_t *ns, int position) +{ + time_t real_time = 0; + + /* The period between SRV#N and TP#N is from 00:00 to 12:00 UTC. Consensus + * valid_after is what matters here, the rest is just to specify the voting + * period correctly. */ + if (position == LATE_IN_SRV_TO_TP) { + parse_rfc1123_time("Wed, 13 Apr 2016 11:00:00 UTC", &ns->valid_after); + parse_rfc1123_time("Wed, 13 Apr 2016 12:00:00 UTC", &ns->fresh_until); + parse_rfc1123_time("Wed, 13 Apr 2016 14:00:00 UTC", &ns->valid_until); + } else if (position == EARLY_IN_TP_TO_SRV) { + parse_rfc1123_time("Wed, 13 Apr 2016 13:00:00 UTC", &ns->valid_after); + parse_rfc1123_time("Wed, 13 Apr 2016 14:00:00 UTC", &ns->fresh_until); + parse_rfc1123_time("Wed, 13 Apr 2016 16:00:00 UTC", &ns->valid_until); + } else if (position == LATE_IN_TP_TO_SRV) { + parse_rfc1123_time("Wed, 13 Apr 2016 23:00:00 UTC", &ns->valid_after); + parse_rfc1123_time("Wed, 14 Apr 2016 00:00:00 UTC", &ns->fresh_until); + parse_rfc1123_time("Wed, 14 Apr 2016 02:00:00 UTC", &ns->valid_until); + } else if (position == EARLY_IN_SRV_TO_TP) { + parse_rfc1123_time("Wed, 14 Apr 2016 01:00:00 UTC", &ns->valid_after); + parse_rfc1123_time("Wed, 14 Apr 2016 02:00:00 UTC", &ns->fresh_until); + parse_rfc1123_time("Wed, 14 Apr 2016 04:00:00 UTC", &ns->valid_until); + } else { + tt_assert(0); + } + dirvote_recalculate_timing(get_options(), ns->valid_after); + + /* Set system time: pretend to be just 2 minutes before consensus expiry */ + real_time = ns->valid_until - 120; + update_approx_time(real_time); + + done: + return real_time; +} + +/** Helper function that carries out the actual test for + * test_client_service_sync() */ +static void +helper_test_hsdir_sync(networkstatus_t *ns, + int service_position, int client_position, + int client_fetches_next_desc) +{ + hs_service_descriptor_t *desc; + int retval; + + /** Test logic: + * 1) Initialize service time: consensus and system time. + * 1.1) Initialize service hash ring + * 2) Initialize service and publish descriptors. + * 3) Initialize client time: consensus and system time. + * 3.1) Initialize client hash ring + * 4) Try to fetch descriptor as client, and CHECK that the HSDir picked by + * the client was also picked by service. + */ + + /* 1) Initialize service time: consensus and real time */ + time_t now = helper_set_consensus_and_system_time(ns, service_position); + helper_initialize_big_hash_ring(ns); + + /* 2) Initialize service */ + hs_service_t *service = helper_init_service(now); + desc = client_fetches_next_desc ? service->desc_next : service->desc_current; + + /* Now let's upload our desc to all hsdirs */ + upload_descriptor_to_all(service, desc); + /* Cleanup right now so we don't memleak on error. */ + cleanup_nodelist(); + /* Check that previous hsdirs were populated */ + tt_int_op(smartlist_len(desc->previous_hsdirs), OP_EQ, 8); + + /* 3) Initialize client time */ + helper_set_consensus_and_system_time(ns, client_position); + + cleanup_nodelist(); + SMARTLIST_FOREACH(ns->routerstatus_list, + routerstatus_t *, rs, routerstatus_free(rs)); + smartlist_clear(ns->routerstatus_list); + helper_initialize_big_hash_ring(ns); + + /* 4) Pick 6 HSDirs as a client and check that they were also chosen by the + service. */ + for (int y = 0 ; y < 6 ; y++) { + char client_hsdir_b64_digest[BASE64_DIGEST_LEN+1] = {0}; + helper_client_pick_hsdir(&service->keys.identity_pk, + client_hsdir_b64_digest); + + /* CHECK: Go through the hsdirs chosen by the service and make sure that it + * contains the one picked by the client! */ + retval = smartlist_contains_string(desc->previous_hsdirs, + client_hsdir_b64_digest); + tt_int_op(retval, OP_EQ, 1); + } + + /* Finally, try to pick a 7th hsdir and see that NULL is returned since we + * exhausted all of them: */ + tt_assert(!pick_hsdir_v3(&service->keys.identity_pk)); + + done: + /* At the end: free all services and initialize the subsystem again, we will + * need it for next scenario. */ + cleanup_nodelist(); + hs_service_free_all(); + hs_service_init(); + SMARTLIST_FOREACH(ns->routerstatus_list, + routerstatus_t *, rs, routerstatus_free(rs)); + smartlist_clear(ns->routerstatus_list); +} + +/** This test ensures that client and service will pick the same HSDirs, under + * various timing scenarios: + * a) Scenario where both client and service are in the time segment between + * SRV#N and TP#N: + * b) Scenario where both client and service are in the time segment between + * TP#N and SRV#N+1. + * c) Scenario where service is between SRV#N and TP#N, but client is between + * TP#N and SRV#N+1. + * d) Scenario where service is between TP#N and SRV#N+1, but client is + * between SRV#N and TP#N. + * + * This test is important because it tests that upload_descriptor_to_all() is + * in synch with pick_hsdir_v3(). That's not the case for the + * test_reachability() test which only compares the responsible hsdir sets. + */ +static void +test_client_service_hsdir_set_sync(void *arg) +{ + networkstatus_t *ns = NULL; + + (void) arg; + + MOCK(networkstatus_get_latest_consensus, + mock_networkstatus_get_latest_consensus); + MOCK(networkstatus_get_live_consensus, + mock_networkstatus_get_live_consensus); + MOCK(get_or_state, + get_or_state_replacement); + MOCK(hs_desc_encode_descriptor, + mock_hs_desc_encode_descriptor); + MOCK(directory_initiate_request, + mock_directory_initiate_request); + + hs_init(); + + /* Initialize a big hash ring: we want it to be big so that client and + * service cannot accidentally select the same HSDirs */ + ns = networkstatus_get_latest_consensus(); + tt_assert(ns); + + /** Now test the various synch scenarios. See the helper function for more + details: */ + + /* a) Scenario where both client and service are in the time segment between + * SRV#N and TP#N. At this time the client fetches the first HS desc: + * + * +------------------------------------------------------------------+ + * | | + * | 00:00 12:00 00:00 12:00 00:00 12:00 | + * | SRV#1 TP#1 SRV#2 TP#2 SRV#3 TP#3 | + * | | + * | $==========|-----------$===========|----------$===========| | + * | ^ ^ | + * | S C | + * +------------------------------------------------------------------+ + */ + helper_test_hsdir_sync(ns, LATE_IN_SRV_TO_TP, LATE_IN_SRV_TO_TP, 0); + + /* b) Scenario where both client and service are in the time segment between + * TP#N and SRV#N+1. At this time the client fetches the second HS + * desc: + * + * +------------------------------------------------------------------+ + * | | + * | 00:00 12:00 00:00 12:00 00:00 12:00 | + * | SRV#1 TP#1 SRV#2 TP#2 SRV#3 TP#3 | + * | | + * | $==========|-----------$===========|-----------$===========| | + * | ^ ^ | + * | S C | + * +------------------------------------------------------------------+ + */ + helper_test_hsdir_sync(ns, LATE_IN_TP_TO_SRV, LATE_IN_TP_TO_SRV, 1); + + /* c) Scenario where service is between SRV#N and TP#N, but client is + * between TP#N and SRV#N+1. Client is forward in time so it fetches the + * second HS desc. + * + * +------------------------------------------------------------------+ + * | | + * | 00:00 12:00 00:00 12:00 00:00 12:00 | + * | SRV#1 TP#1 SRV#2 TP#2 SRV#3 TP#3 | + * | | + * | $==========|-----------$===========|-----------$===========| | + * | ^ ^ | + * | S C | + * +------------------------------------------------------------------+ + */ + helper_test_hsdir_sync(ns, LATE_IN_SRV_TO_TP, EARLY_IN_TP_TO_SRV, 1); + + /* d) Scenario where service is between TP#N and SRV#N+1, but client is + * between SRV#N and TP#N. Client is backwards in time so it fetches the + * first HS desc. + * + * +------------------------------------------------------------------+ + * | | + * | 00:00 12:00 00:00 12:00 00:00 12:00 | + * | SRV#1 TP#1 SRV#2 TP#2 SRV#3 TP#3 | + * | | + * | $==========|-----------$===========|-----------$===========| | + * | ^ ^ | + * | C S | + * +------------------------------------------------------------------+ + */ + helper_test_hsdir_sync(ns, EARLY_IN_TP_TO_SRV, LATE_IN_SRV_TO_TP, 0); + + /* e) Scenario where service is between SRV#N and TP#N, but client is + * between TP#N-1 and SRV#3. Client is backwards in time so it fetches + * the first HS desc. + * + * +------------------------------------------------------------------+ + * | | + * | 00:00 12:00 00:00 12:00 00:00 12:00 | + * | SRV#1 TP#1 SRV#2 TP#2 SRV#3 TP#3 | + * | | + * | $==========|-----------$===========|-----------$===========| | + * | ^ ^ | + * | C S | + * +------------------------------------------------------------------+ + */ + helper_test_hsdir_sync(ns, EARLY_IN_SRV_TO_TP, LATE_IN_TP_TO_SRV, 0); + + /* f) Scenario where service is between TP#N and SRV#N+1, but client is + * between SRV#N+1 and TP#N+1. Client is forward in time so it fetches + * the second HS desc. + * + * +------------------------------------------------------------------+ + * | | + * | 00:00 12:00 00:00 12:00 00:00 12:00 | + * | SRV#1 TP#1 SRV#2 TP#2 SRV#3 TP#3 | + * | | + * | $==========|-----------$===========|-----------$===========| | + * | ^ ^ | + * | S C | + * +------------------------------------------------------------------+ + */ + helper_test_hsdir_sync(ns, LATE_IN_TP_TO_SRV, EARLY_IN_SRV_TO_TP, 1); + + done: + networkstatus_vote_free(ns); + nodelist_free_all(); + hs_free_all(); +} + +struct testcase_t hs_common_tests[] = { + { "build_address", test_build_address, TT_FORK, + NULL, NULL }, + { "validate_address", test_validate_address, TT_FORK, + NULL, NULL }, + { "time_period", test_time_period, TT_FORK, + NULL, NULL }, + { "start_time_of_next_time_period", test_start_time_of_next_time_period, + TT_FORK, NULL, NULL }, + { "responsible_hsdirs", test_responsible_hsdirs, TT_FORK, + NULL, NULL }, + { "desc_reupload_logic", test_desc_reupload_logic, TT_FORK, + NULL, NULL }, + { "disaster_srv", test_disaster_srv, TT_FORK, + NULL, NULL }, + { "hid_serv_request_tracker", test_hid_serv_request_tracker, TT_FORK, + NULL, NULL }, + { "parse_extended_hostname", test_parse_extended_hostname, TT_FORK, + NULL, NULL }, + { "time_between_tp_and_srv", test_time_between_tp_and_srv, TT_FORK, + NULL, NULL }, + { "reachability", test_reachability, TT_FORK, + NULL, NULL }, + { "client_service_hsdir_set_sync", test_client_service_hsdir_set_sync, + TT_FORK, NULL, NULL }, + { "hs_indexes", test_hs_indexes, TT_FORK, + NULL, NULL }, + + END_OF_TESTCASES +}; + diff --git a/src/test/test_hs_config.c b/src/test/test_hs_config.c new file mode 100644 index 0000000000..a76be301d3 --- /dev/null +++ b/src/test/test_hs_config.c @@ -0,0 +1,487 @@ +/* Copyright (c) 2016, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file test_hs_config.c + * \brief Test hidden service configuration functionality. + */ + +#define CONFIG_PRIVATE +#define HS_SERVICE_PRIVATE + +#include "test.h" +#include "test_helpers.h" +#include "log_test_helpers.h" + +#include "config.h" +#include "hs_common.h" +#include "hs_config.h" +#include "hs_service.h" +#include "rendservice.h" + +static int +helper_config_service(const char *conf, int validate_only) +{ + int ret = 0; + or_options_t *options = NULL; + tt_assert(conf); + options = helper_parse_options(conf); + tt_assert(options); + ret = hs_config_service_all(options, validate_only); + done: + or_options_free(options); + return ret; +} + +static void +test_invalid_service(void *arg) +{ + int ret; + + (void) arg; + + /* Try with a missing port configuration. */ + { + const char *conf = + "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" + "HiddenServiceVersion 1\n"; /* Wrong not supported version. */ + setup_full_capture_of_logs(LOG_WARN); + ret = helper_config_service(conf, 1); + tt_int_op(ret, OP_EQ, -1); + expect_log_msg_containing("HiddenServiceVersion must be between 2 and 3"); + teardown_capture_of_logs(); + } + + /* Bad value of HiddenServiceAllowUnknownPorts. */ + { + const char *conf = + "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" + "HiddenServiceVersion 2\n" + "HiddenServiceAllowUnknownPorts 2\n"; /* Should be 0 or 1. */ + setup_full_capture_of_logs(LOG_WARN); + ret = helper_config_service(conf, 1); + tt_int_op(ret, OP_EQ, -1); + expect_log_msg_containing("HiddenServiceAllowUnknownPorts must be " + "between 0 and 1, not 2"); + teardown_capture_of_logs(); + } + + /* Bad value of HiddenServiceDirGroupReadable */ + { + const char *conf = + "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" + "HiddenServiceVersion 2\n" + "HiddenServiceDirGroupReadable 2\n"; /* Should be 0 or 1. */ + setup_full_capture_of_logs(LOG_WARN); + ret = helper_config_service(conf, 1); + tt_int_op(ret, OP_EQ, -1); + expect_log_msg_containing("HiddenServiceDirGroupReadable must be " + "between 0 and 1, not 2"); + teardown_capture_of_logs(); + } + + /* Bad value of HiddenServiceMaxStreamsCloseCircuit */ + { + const char *conf = + "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" + "HiddenServiceVersion 2\n" + "HiddenServiceMaxStreamsCloseCircuit 2\n"; /* Should be 0 or 1. */ + setup_full_capture_of_logs(LOG_WARN); + ret = helper_config_service(conf, 1); + tt_int_op(ret, OP_EQ, -1); + expect_log_msg_containing("HiddenServiceMaxStreamsCloseCircuit must " + "be between 0 and 1, not 2"); + teardown_capture_of_logs(); + } + + /* Too much max streams. */ + { + const char *conf = + "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" + "HiddenServiceVersion 2\n" + "HiddenServicePort 80\n" + "HiddenServiceMaxStreams 65536\n"; /* One too many. */ + setup_full_capture_of_logs(LOG_WARN); + ret = helper_config_service(conf, 1); + tt_int_op(ret, OP_EQ, -1); + expect_log_msg_containing("HiddenServiceMaxStreams must be between " + "0 and 65535, not 65536"); + teardown_capture_of_logs(); + } + + /* Duplicate directory directive. */ + { + const char *conf = + "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" + "HiddenServiceVersion 2\n" + "HiddenServicePort 80\n" + "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" + "HiddenServiceVersion 2\n" + "HiddenServicePort 81\n"; + setup_full_capture_of_logs(LOG_WARN); + ret = helper_config_service(conf, 1); + tt_int_op(ret, OP_EQ, -1); + expect_log_msg_containing("Another hidden service is already " + "configured for directory"); + teardown_capture_of_logs(); + } + + /* Bad port. */ + { + const char *conf = + "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" + "HiddenServiceVersion 2\n" + "HiddenServicePort 65536\n"; + setup_full_capture_of_logs(LOG_WARN); + ret = helper_config_service(conf, 1); + tt_int_op(ret, OP_EQ, -1); + expect_log_msg_containing("Missing or invalid port"); + teardown_capture_of_logs(); + } + + /* Out of order directives. */ + { + const char *conf = + "HiddenServiceVersion 2\n" + "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" + "HiddenServicePort 80\n"; + setup_full_capture_of_logs(LOG_WARN); + ret = helper_config_service(conf, 1); + tt_int_op(ret, OP_EQ, -1); + expect_log_msg_containing("HiddenServiceVersion with no preceding " + "HiddenServiceDir directive"); + teardown_capture_of_logs(); + } + + done: + ; +} + +static void +test_valid_service(void *arg) +{ + int ret; + + (void) arg; + + /* Mix of v2 and v3. Still valid. */ + { + const char *conf = + "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" + "HiddenServiceVersion 2\n" + "HiddenServicePort 80\n" + "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs2\n" + "HiddenServiceVersion 3\n" + "HiddenServicePort 81\n" + "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs3\n" + "HiddenServiceVersion 2\n" + "HiddenServicePort 82\n"; + ret = helper_config_service(conf, 1); + tt_int_op(ret, OP_EQ, 0); + } + + done: + ; +} + +static void +test_invalid_service_v2(void *arg) +{ + int validate_only = 1, ret; + + (void) arg; + + /* Try with a missing port configuration. */ + { + const char *conf = + "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" + "HiddenServiceVersion 2\n"; + setup_full_capture_of_logs(LOG_WARN); + ret = helper_config_service(conf, validate_only); + tt_int_op(ret, OP_EQ, -1); + expect_log_msg_containing("with no ports configured."); + teardown_capture_of_logs(); + } + + /* Too many introduction points. */ + { + const char *conf = + "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" + "HiddenServiceVersion 2\n" + "HiddenServicePort 80\n" + "HiddenServiceNumIntroductionPoints 11\n"; /* One too many. */ + setup_full_capture_of_logs(LOG_WARN); + ret = helper_config_service(conf, validate_only); + tt_int_op(ret, OP_EQ, -1); + expect_log_msg_containing("HiddenServiceNumIntroductionPoints should " + "be between 0 and 10, not 11"); + teardown_capture_of_logs(); + } + + /* Too little introduction points. */ + { + const char *conf = + "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" + "HiddenServiceVersion 2\n" + "HiddenServicePort 80\n" + "HiddenServiceNumIntroductionPoints -1\n"; + setup_full_capture_of_logs(LOG_WARN); + ret = helper_config_service(conf, validate_only); + tt_int_op(ret, OP_EQ, -1); + expect_log_msg_containing("HiddenServiceNumIntroductionPoints should " + "be between 0 and 10, not -1"); + teardown_capture_of_logs(); + } + + /* Bad authorized client type. */ + { + const char *conf = + "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" + "HiddenServiceVersion 2\n" + "HiddenServicePort 80\n" + "HiddenServiceAuthorizeClient blah alice,bob\n"; /* blah is no good. */ + setup_full_capture_of_logs(LOG_WARN); + ret = helper_config_service(conf, validate_only); + tt_int_op(ret, OP_EQ, -1); + expect_log_msg_containing("HiddenServiceAuthorizeClient contains " + "unrecognized auth-type"); + teardown_capture_of_logs(); + } + + done: + ; +} + +static void +test_valid_service_v2(void *arg) +{ + int ret; + + (void) arg; + + /* Valid complex configuration. Basic client authorization. */ + { + const char *conf = + "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" + "HiddenServiceVersion 2\n" + "HiddenServicePort 80\n" + "HiddenServicePort 22 localhost:22\n" +#ifdef HAVE_SYS_UN_H + "HiddenServicePort 42 unix:/path/to/socket\n" +#endif + "HiddenServiceAuthorizeClient basic alice,bob,eve\n" + "HiddenServiceAllowUnknownPorts 1\n" + "HiddenServiceMaxStreams 42\n" + "HiddenServiceMaxStreamsCloseCircuit 0\n" + "HiddenServiceDirGroupReadable 1\n" + "HiddenServiceNumIntroductionPoints 7\n"; + ret = helper_config_service(conf, 1); + tt_int_op(ret, OP_EQ, 0); + } + + /* Valid complex configuration. Stealth client authorization. */ + { + const char *conf = + "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs2\n" + "HiddenServiceVersion 2\n" + "HiddenServicePort 65535\n" + "HiddenServicePort 22 1.1.1.1:22\n" +#ifdef HAVE_SYS_UN_H + "HiddenServicePort 9000 unix:/path/to/socket\n" +#endif + "HiddenServiceAuthorizeClient stealth charlie,romeo\n" + "HiddenServiceAllowUnknownPorts 0\n" + "HiddenServiceMaxStreams 42\n" + "HiddenServiceMaxStreamsCloseCircuit 0\n" + "HiddenServiceDirGroupReadable 1\n" + "HiddenServiceNumIntroductionPoints 8\n"; + ret = helper_config_service(conf, 1); + tt_int_op(ret, OP_EQ, 0); + } + + done: + ; +} + +static void +test_invalid_service_v3(void *arg) +{ + int validate_only = 1, ret; + + (void) arg; + + /* Try with a missing port configuration. */ + { + const char *conf = + "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" + "HiddenServiceVersion 3\n"; + setup_full_capture_of_logs(LOG_WARN); + ret = helper_config_service(conf, validate_only); + tt_int_op(ret, OP_EQ, -1); + expect_log_msg_containing("with no ports configured."); + teardown_capture_of_logs(); + } + + /* Too many introduction points. */ + { + const char *conf = + "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" + "HiddenServiceVersion 3\n" + "HiddenServicePort 80\n" + "HiddenServiceNumIntroductionPoints 21\n"; /* One too many. */ + setup_full_capture_of_logs(LOG_WARN); + ret = helper_config_service(conf, validate_only); + tt_int_op(ret, OP_EQ, -1); + expect_log_msg_containing("HiddenServiceNumIntroductionPoints must " + "be between 3 and 20, not 21."); + teardown_capture_of_logs(); + } + + /* Too little introduction points. */ + { + const char *conf = + "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" + "HiddenServiceVersion 3\n" + "HiddenServicePort 80\n" + "HiddenServiceNumIntroductionPoints 1\n"; + setup_full_capture_of_logs(LOG_WARN); + ret = helper_config_service(conf, validate_only); + tt_int_op(ret, OP_EQ, -1); + expect_log_msg_containing("HiddenServiceNumIntroductionPoints must " + "be between 3 and 20, not 1."); + teardown_capture_of_logs(); + } + + done: + ; +} + +static void +test_valid_service_v3(void *arg) +{ + int ret; + + (void) arg; + + /* Valid complex configuration. */ + { + const char *conf = + "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" + "HiddenServiceVersion 3\n" + "HiddenServicePort 80\n" + "HiddenServicePort 22 localhost:22\n" +#ifdef HAVE_SYS_UN_H + "HiddenServicePort 42 unix:/path/to/socket\n" +#endif + "HiddenServiceAllowUnknownPorts 1\n" + "HiddenServiceMaxStreams 42\n" + "HiddenServiceMaxStreamsCloseCircuit 0\n" + "HiddenServiceDirGroupReadable 1\n" + "HiddenServiceNumIntroductionPoints 7\n"; + ret = helper_config_service(conf, 1); + tt_int_op(ret, OP_EQ, 0); + } + + /* Valid complex configuration. */ + { + const char *conf = + "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs2\n" + "HiddenServiceVersion 3\n" + "HiddenServicePort 65535\n" + "HiddenServicePort 22 1.1.1.1:22\n" +#ifdef HAVE_SYS_UN_H + "HiddenServicePort 9000 unix:/path/to/socket\n" +#endif + "HiddenServiceAllowUnknownPorts 0\n" + "HiddenServiceMaxStreams 42\n" + "HiddenServiceMaxStreamsCloseCircuit 0\n" + "HiddenServiceDirGroupReadable 1\n" + "HiddenServiceNumIntroductionPoints 20\n"; + ret = helper_config_service(conf, 1); + tt_int_op(ret, OP_EQ, 0); + } + + /* Mix of v2 and v3. Still valid. */ + { + const char *conf = + "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" + "HiddenServiceVersion 2\n" + "HiddenServicePort 80\n" + "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs2\n" + "HiddenServiceVersion 3\n" + "HiddenServicePort 81\n" + "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs3\n" + "HiddenServiceVersion 2\n" + "HiddenServicePort 82\n"; + ret = helper_config_service(conf, 1); + tt_int_op(ret, OP_EQ, 0); + } + + done: + ; +} + +static void +test_staging_service_v3(void *arg) +{ + int ret; + + (void) arg; + + /* We don't validate a service object, this is the service test that are in + * charge of doing so. We just check for the stable state after + * registration. */ + + hs_init(); + + /* Time for a valid v3 service that should get staged. */ + const char *conf = + "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs2\n" + "HiddenServiceVersion 3\n" + "HiddenServicePort 65535\n" + "HiddenServicePort 22 1.1.1.1:22\n" +#ifdef HAVE_SYS_UN_H + "HiddenServicePort 9000 unix:/path/to/socket\n" +#endif + "HiddenServiceAllowUnknownPorts 0\n" + "HiddenServiceMaxStreams 42\n" + "HiddenServiceMaxStreamsCloseCircuit 0\n" + "HiddenServiceDirGroupReadable 1\n" + "HiddenServiceNumIntroductionPoints 20\n"; + ret = helper_config_service(conf, 0); + tt_int_op(ret, OP_EQ, 0); + /* Ok, we have a service in our map! Registration went well. */ + tt_int_op(get_hs_service_staging_list_size(), OP_EQ, 1); + /* Make sure we don't have a magic v2 service out of this. */ + tt_int_op(rend_num_services(), OP_EQ, 0); + + done: + hs_free_all(); +} + +struct testcase_t hs_config_tests[] = { + /* Invalid service not specific to any version. */ + { "invalid_service", test_invalid_service, TT_FORK, + NULL, NULL }, + { "valid_service", test_valid_service, TT_FORK, + NULL, NULL }, + + /* Test case only for version 2. */ + { "invalid_service_v2", test_invalid_service_v2, TT_FORK, + NULL, NULL }, + { "valid_service_v2", test_valid_service_v2, TT_FORK, + NULL, NULL }, + + /* Test case only for version 3. */ + { "invalid_service_v3", test_invalid_service_v3, TT_FORK, + NULL, NULL }, + { "valid_service_v3", test_valid_service_v3, TT_FORK, + NULL, NULL }, + + /* Test service staging. */ + { "staging_service_v3", test_staging_service_v3, TT_FORK, + NULL, NULL }, + + END_OF_TESTCASES +}; + diff --git a/src/test/test_hs_descriptor.c b/src/test/test_hs_descriptor.c index 7d7ec7d9db..897b441888 100644 --- a/src/test/test_hs_descriptor.c +++ b/src/test/test_hs_descriptor.c @@ -54,7 +54,7 @@ test_cert_encoding(void *arg) /* Test the certificate encoding function. */ ret = tor_cert_encode_ed22519(cert, &encoded); - tt_int_op(ret, ==, 0); + tt_int_op(ret, OP_EQ, 0); /* Validated the certificate string. */ { @@ -63,7 +63,7 @@ test_cert_encoding(void *arg) size_t b64_cert_len; tor_cert_t *parsed_cert; - tt_int_op(strcmpstart(pos, "-----BEGIN ED25519 CERT-----\n"), ==, 0); + tt_int_op(strcmpstart(pos, "-----BEGIN ED25519 CERT-----\n"), OP_EQ, 0); pos += strlen("-----BEGIN ED25519 CERT-----\n"); /* Isolate the base64 encoded certificate and try to decode it. */ @@ -72,24 +72,25 @@ test_cert_encoding(void *arg) b64_cert = pos; b64_cert_len = end - pos; ret = base64_decode(buf, sizeof(buf), b64_cert, b64_cert_len); - tt_int_op(ret, >, 0); + tt_int_op(ret, OP_GT, 0); /* Parseable? */ parsed_cert = tor_cert_parse((uint8_t *) buf, ret); tt_assert(parsed_cert); /* Signature is valid? */ ret = tor_cert_checksig(parsed_cert, &kp.pubkey, now + 10); - tt_int_op(ret, ==, 0); + tt_int_op(ret, OP_EQ, 0); ret = tor_cert_eq(cert, parsed_cert); - tt_int_op(ret, ==, 1); + tt_int_op(ret, OP_EQ, 1); /* The cert did have the signing key? */ ret= ed25519_pubkey_eq(&parsed_cert->signing_key, &kp.pubkey); - tt_int_op(ret, ==, 1); + tt_int_op(ret, OP_EQ, 1); tor_cert_free(parsed_cert); /* Get to the end part of the certificate. */ pos += b64_cert_len; - tt_int_op(strcmpstart(pos, "-----END ED25519 CERT-----"), ==, 0); + tt_int_op(strcmpstart(pos, "-----END ED25519 CERT-----"), OP_EQ, 0); pos += strlen("-----END ED25519 CERT-----"); + tt_str_op(pos, OP_EQ, ""); } done: @@ -173,6 +174,9 @@ test_link_specifier(void *arg) ssize_t ret; hs_desc_link_specifier_t spec; smartlist_t *link_specifiers = smartlist_new(); + char buf[256]; + char *b64 = NULL; + link_specifier_t *ls = NULL; (void) arg; @@ -182,69 +186,66 @@ test_link_specifier(void *arg) /* Test IPv4 for starter. */ { - char *b64, buf[256]; uint32_t ipv4; - link_specifier_t *ls; spec.type = LS_IPV4; ret = tor_addr_parse(&spec.u.ap.addr, "1.2.3.4"); - tt_int_op(ret, ==, AF_INET); + tt_int_op(ret, OP_EQ, AF_INET); b64 = encode_link_specifiers(link_specifiers); tt_assert(b64); /* Decode it and validate the format. */ ret = base64_decode(buf, sizeof(buf), b64, strlen(b64)); - tt_int_op(ret, >, 0); + tt_int_op(ret, OP_GT, 0); /* First byte is the number of link specifier. */ - tt_int_op(get_uint8(buf), ==, 1); + tt_int_op(get_uint8(buf), OP_EQ, 1); ret = link_specifier_parse(&ls, (uint8_t *) buf + 1, ret - 1); - tt_int_op(ret, ==, 8); + tt_int_op(ret, OP_EQ, 8); /* Should be 2 bytes for port and 4 bytes for IPv4. */ - tt_int_op(link_specifier_get_ls_len(ls), ==, 6); + tt_int_op(link_specifier_get_ls_len(ls), OP_EQ, 6); ipv4 = link_specifier_get_un_ipv4_addr(ls); - tt_int_op(tor_addr_to_ipv4h(&spec.u.ap.addr), ==, ipv4); - tt_int_op(link_specifier_get_un_ipv4_port(ls), ==, spec.u.ap.port); + tt_int_op(tor_addr_to_ipv4h(&spec.u.ap.addr), OP_EQ, ipv4); + tt_int_op(link_specifier_get_un_ipv4_port(ls), OP_EQ, spec.u.ap.port); link_specifier_free(ls); + ls = NULL; tor_free(b64); } /* Test IPv6. */ { - char *b64, buf[256]; uint8_t ipv6[16]; - link_specifier_t *ls; spec.type = LS_IPV6; ret = tor_addr_parse(&spec.u.ap.addr, "[1:2:3:4::]"); - tt_int_op(ret, ==, AF_INET6); + tt_int_op(ret, OP_EQ, AF_INET6); b64 = encode_link_specifiers(link_specifiers); tt_assert(b64); /* Decode it and validate the format. */ ret = base64_decode(buf, sizeof(buf), b64, strlen(b64)); - tt_int_op(ret, >, 0); + tt_int_op(ret, OP_GT, 0); /* First byte is the number of link specifier. */ - tt_int_op(get_uint8(buf), ==, 1); + tt_int_op(get_uint8(buf), OP_EQ, 1); ret = link_specifier_parse(&ls, (uint8_t *) buf + 1, ret - 1); - tt_int_op(ret, ==, 20); + tt_int_op(ret, OP_EQ, 20); /* Should be 2 bytes for port and 16 bytes for IPv6. */ - tt_int_op(link_specifier_get_ls_len(ls), ==, 18); + tt_int_op(link_specifier_get_ls_len(ls), OP_EQ, 18); for (unsigned int i = 0; i < sizeof(ipv6); i++) { ipv6[i] = link_specifier_get_un_ipv6_addr(ls, i); } - tt_mem_op(tor_addr_to_in6_addr8(&spec.u.ap.addr), ==, ipv6, sizeof(ipv6)); - tt_int_op(link_specifier_get_un_ipv6_port(ls), ==, spec.u.ap.port); + tt_mem_op(tor_addr_to_in6_addr8(&spec.u.ap.addr), OP_EQ, ipv6, + sizeof(ipv6)); + tt_int_op(link_specifier_get_un_ipv6_port(ls), OP_EQ, spec.u.ap.port); link_specifier_free(ls); + ls = NULL; tor_free(b64); } /* Test legacy. */ { - char *b64, buf[256]; uint8_t *id; - link_specifier_t *ls; spec.type = LS_LEGACY_ID; memset(spec.u.legacy_id, 'Y', sizeof(spec.u.legacy_id)); @@ -253,12 +254,12 @@ test_link_specifier(void *arg) /* Decode it and validate the format. */ ret = base64_decode(buf, sizeof(buf), b64, strlen(b64)); - tt_int_op(ret, >, 0); + tt_int_op(ret, OP_GT, 0); /* First byte is the number of link specifier. */ - tt_int_op(get_uint8(buf), ==, 1); + tt_int_op(get_uint8(buf), OP_EQ, 1); ret = link_specifier_parse(&ls, (uint8_t *) buf + 1, ret - 1); /* 20 bytes digest + 1 byte type + 1 byte len. */ - tt_int_op(ret, ==, 22); + tt_int_op(ret, OP_EQ, 22); tt_int_op(link_specifier_getlen_un_legacy_id(ls), OP_EQ, DIGEST_LEN); /* Digest length is 20 bytes. */ tt_int_op(link_specifier_get_ls_len(ls), OP_EQ, DIGEST_LEN); @@ -266,10 +267,13 @@ test_link_specifier(void *arg) tt_mem_op(spec.u.legacy_id, OP_EQ, id, DIGEST_LEN); link_specifier_free(ls); + ls = NULL; tor_free(b64); } done: + link_specifier_free(ls); + tor_free(b64); smartlist_free(link_specifiers); } @@ -284,10 +288,10 @@ test_encode_descriptor(void *arg) (void) arg; ret = ed25519_keypair_generate(&signing_kp, 0); - tt_int_op(ret, ==, 0); + tt_int_op(ret, OP_EQ, 0); desc = hs_helper_build_hs_desc_with_ip(&signing_kp); ret = hs_desc_encode_descriptor(desc, &signing_kp, &encoded); - tt_int_op(ret, ==, 0); + tt_int_op(ret, OP_EQ, 0); tt_assert(encoded); done: @@ -304,23 +308,27 @@ test_decode_descriptor(void *arg) hs_descriptor_t *desc = NULL; hs_descriptor_t *decoded = NULL; hs_descriptor_t *desc_no_ip = NULL; + uint8_t subcredential[DIGEST256_LEN]; (void) arg; ret = ed25519_keypair_generate(&signing_kp, 0); - tt_int_op(ret, ==, 0); + tt_int_op(ret, OP_EQ, 0); desc = hs_helper_build_hs_desc_with_ip(&signing_kp); + hs_helper_get_subcred_from_identity_keypair(&signing_kp, + subcredential); + /* Give some bad stuff to the decoding function. */ - ret = hs_desc_decode_descriptor("hladfjlkjadf", NULL, &decoded); + ret = hs_desc_decode_descriptor("hladfjlkjadf", subcredential, &decoded); tt_int_op(ret, OP_EQ, -1); ret = hs_desc_encode_descriptor(desc, &signing_kp, &encoded); - tt_int_op(ret, ==, 0); + tt_int_op(ret, OP_EQ, 0); tt_assert(encoded); - ret = hs_desc_decode_descriptor(encoded, NULL, &decoded); - tt_int_op(ret, ==, 0); + ret = hs_desc_decode_descriptor(encoded, subcredential, &decoded); + tt_int_op(ret, OP_EQ, 0); tt_assert(decoded); hs_helper_desc_equal(desc, decoded); @@ -329,16 +337,18 @@ test_decode_descriptor(void *arg) { ed25519_keypair_t signing_kp_no_ip; ret = ed25519_keypair_generate(&signing_kp_no_ip, 0); - tt_int_op(ret, ==, 0); + tt_int_op(ret, OP_EQ, 0); + hs_helper_get_subcred_from_identity_keypair(&signing_kp_no_ip, + subcredential); desc_no_ip = hs_helper_build_hs_desc_no_ip(&signing_kp_no_ip); tt_assert(desc_no_ip); tor_free(encoded); ret = hs_desc_encode_descriptor(desc_no_ip, &signing_kp_no_ip, &encoded); - tt_int_op(ret, ==, 0); + tt_int_op(ret, OP_EQ, 0); tt_assert(encoded); hs_descriptor_free(decoded); - ret = hs_desc_decode_descriptor(encoded, NULL, &decoded); - tt_int_op(ret, ==, 0); + ret = hs_desc_decode_descriptor(encoded, subcredential, &decoded); + tt_int_op(ret, OP_EQ, 0); tt_assert(decoded); } @@ -430,12 +440,12 @@ test_decode_invalid_intro_point(void *arg) hs_descriptor_free(desc); desc = NULL; ret = ed25519_keypair_generate(&signing_kp, 0); - tt_int_op(ret, ==, 0); + tt_int_op(ret, OP_EQ, 0); desc = hs_helper_build_hs_desc_with_ip(&signing_kp); const char *junk = "this is not a descriptor"; ip = decode_introduction_point(desc, junk); - tt_assert(!ip); - desc_intro_point_free(ip); + tt_ptr_op(ip, OP_EQ, NULL); + hs_desc_intro_point_free(ip); ip = NULL; } @@ -450,10 +460,10 @@ test_decode_invalid_intro_point(void *arg) encoded_ip = smartlist_join_strings(lines, "\n", 0, &len_out); tt_assert(encoded_ip); ip = decode_introduction_point(desc, encoded_ip); - tt_assert(!ip); + tt_ptr_op(ip, OP_EQ, NULL); tor_free(encoded_ip); smartlist_free(lines); - desc_intro_point_free(ip); + hs_desc_intro_point_free(ip); ip = NULL; } @@ -477,7 +487,7 @@ test_decode_invalid_intro_point(void *arg) encoded_ip = smartlist_join_strings(lines, "\n", 0, &len_out); tt_assert(encoded_ip); ip = decode_introduction_point(desc, encoded_ip); - tt_assert(!ip); + tt_ptr_op(ip, OP_EQ, NULL); tor_free(encoded_ip); smartlist_free(lines); } @@ -495,7 +505,7 @@ test_decode_invalid_intro_point(void *arg) encoded_ip = smartlist_join_strings(lines, "\n", 0, &len_out); tt_assert(encoded_ip); ip = decode_introduction_point(desc, encoded_ip); - tt_assert(!ip); + tt_ptr_op(ip, OP_EQ, NULL); tor_free(encoded_ip); smartlist_free(lines); } @@ -512,7 +522,7 @@ test_decode_invalid_intro_point(void *arg) encoded_ip = smartlist_join_strings(lines, "\n", 0, &len_out); tt_assert(encoded_ip); ip = decode_introduction_point(desc, encoded_ip); - tt_assert(!ip); + tt_ptr_op(ip, OP_EQ, NULL); tor_free(encoded_ip); smartlist_free(lines); } @@ -529,7 +539,7 @@ test_decode_invalid_intro_point(void *arg) encoded_ip = smartlist_join_strings(lines, "\n", 0, &len_out); tt_assert(encoded_ip); ip = decode_introduction_point(desc, encoded_ip); - tt_assert(!ip); + tt_ptr_op(ip, OP_EQ, NULL); tor_free(encoded_ip); smartlist_free(lines); } @@ -546,14 +556,14 @@ test_decode_invalid_intro_point(void *arg) encoded_ip = smartlist_join_strings(lines, "\n", 0, &len_out); tt_assert(encoded_ip); ip = decode_introduction_point(desc, encoded_ip); - tt_assert(!ip); + tt_ptr_op(ip, OP_EQ, NULL); tor_free(encoded_ip); smartlist_free(lines); } done: hs_descriptor_free(desc); - desc_intro_point_free(ip); + hs_desc_intro_point_free(ip); } /** Make sure we fail gracefully when decoding the bad desc from #23233. */ @@ -624,7 +634,7 @@ test_decode_plaintext(void *arg) { size_t big = 64000; /* Must always be bigger than HS_DESC_MAX_LEN. */ - tt_int_op(HS_DESC_MAX_LEN, <, big); + tt_int_op(HS_DESC_MAX_LEN, OP_LT, big); char *plaintext = tor_malloc_zero(big); memset(plaintext, 'a', big); plaintext[big - 1] = '\0'; @@ -684,7 +694,7 @@ test_validate_cert(void *arg) (void) arg; ret = ed25519_keypair_generate(&kp, 0); - tt_int_op(ret, ==, 0); + tt_int_op(ret, OP_EQ, 0); /* Cert of type CERT_TYPE_AUTH_HS_IP_KEY. */ cert = tor_cert_create(&kp, CERT_TYPE_AUTH_HS_IP_KEY, @@ -735,16 +745,16 @@ test_desc_signature(void *arg) tor_asprintf(&data, "This is a signed descriptor\n"); ret = ed25519_sign_prefixed(&sig, (const uint8_t *) data, strlen(data), "Tor onion service descriptor sig v3", &kp); - tt_int_op(ret, ==, 0); + tt_int_op(ret, OP_EQ, 0); ret = ed25519_signature_to_base64(sig_b64, &sig); - tt_int_op(ret, ==, 0); + tt_int_op(ret, OP_EQ, 0); /* Build the descriptor that should be valid. */ tor_asprintf(&desc, "%ssignature %s\n", data, sig_b64); ret = desc_sig_is_valid(sig_b64, &kp.pubkey, desc, strlen(desc)); - tt_int_op(ret, ==, 1); + tt_int_op(ret, OP_EQ, 1); /* Junk signature. */ ret = desc_sig_is_valid("JUNK", &kp.pubkey, desc, strlen(desc)); - tt_int_op(ret, ==, 0); + tt_int_op(ret, OP_EQ, 0); done: tor_free(desc); @@ -806,8 +816,8 @@ test_parse_hs_desc_superencrypted(void *arg) retval = decode_superencrypted(bad_superencrypted_text1, strlen(bad_superencrypted_text1), &encrypted_out); - tt_u64_op(retval, ==, 0); - tt_assert(!encrypted_out); + tt_u64_op(retval, OP_EQ, 0); + tt_ptr_op(encrypted_out, OP_EQ, NULL); expect_log_msg_containing("Unrecognized desc auth type"); teardown_capture_of_logs(); } @@ -817,8 +827,8 @@ test_parse_hs_desc_superencrypted(void *arg) retval = decode_superencrypted(bad_superencrypted_text2, strlen(bad_superencrypted_text2), &encrypted_out); - tt_u64_op(retval, ==, 0); - tt_assert(!encrypted_out); + tt_u64_op(retval, OP_EQ, 0); + tt_ptr_op(encrypted_out, OP_EQ, NULL); expect_log_msg_containing("Bogus desc auth key in HS desc"); teardown_capture_of_logs(); } @@ -828,8 +838,8 @@ test_parse_hs_desc_superencrypted(void *arg) retval = decode_superencrypted(bad_superencrypted_text3, strlen(bad_superencrypted_text3), &encrypted_out); - tt_u64_op(retval, ==, 0); - tt_assert(!encrypted_out); + tt_u64_op(retval, OP_EQ, 0); + tt_ptr_op(encrypted_out, OP_EQ, NULL); expect_log_msg_containing("Length of descriptor\'s encrypted data " "is too small."); teardown_capture_of_logs(); @@ -840,7 +850,7 @@ test_parse_hs_desc_superencrypted(void *arg) strlen(correct_superencrypted_text), &encrypted_out); - tt_u64_op(retval, ==, strlen(correct_encrypted_plaintext)); + tt_u64_op(retval, OP_EQ, strlen(correct_encrypted_plaintext)); tt_mem_op(encrypted_out, OP_EQ, correct_encrypted_plaintext, strlen(correct_encrypted_plaintext)); diff --git a/src/test/test_hs_intropoint.c b/src/test/test_hs_intropoint.c index c6197875b5..b2d2700f8b 100644 --- a/src/test/test_hs_intropoint.c +++ b/src/test/test_hs_intropoint.c @@ -17,21 +17,73 @@ #include "log_test_helpers.h" #include "or.h" +#include "circuitlist.h" +#include "circuituse.h" #include "ht.h" +#include "relay.h" +#include "rendservice.h" + +#include "hs_cell.h" +#include "hs_circuitmap.h" +#include "hs_common.h" +#include "hs_intropoint.h" +#include "hs_service.h" /* Trunnel. */ #include "hs/cell_establish_intro.h" #include "hs/cell_introduce1.h" #include "hs/cell_common.h" -#include "hs_service.h" -#include "hs_common.h" -#include "hs_circuitmap.h" -#include "hs_intropoint.h" -#include "circuitlist.h" -#include "circuituse.h" -#include "rendservice.h" -#include "relay.h" +static size_t +new_establish_intro_cell(const char *circ_nonce, + trn_cell_establish_intro_t **cell_out) +{ + ssize_t cell_len = 0; + uint8_t buf[RELAY_PAYLOAD_SIZE] = {0}; + trn_cell_establish_intro_t *cell = NULL; + hs_service_intro_point_t *ip = NULL; + + /* Ensure that *cell_out is NULL such that we can use to check if we need to + * free `cell` in case of an error. */ + *cell_out = NULL; + + /* Auth key pair is generated in the constructor so we are all set for + * using this IP object. */ + ip = service_intro_point_new(NULL, 0); + tt_assert(ip); + cell_len = hs_cell_build_establish_intro(circ_nonce, ip, buf); + tt_i64_op(cell_len, OP_GT, 0); + + cell_len = trn_cell_establish_intro_parse(&cell, buf, sizeof(buf)); + tt_i64_op(cell_len, OP_GT, 0); + tt_assert(cell); + *cell_out = cell; + + done: + if (*cell_out == NULL) + trn_cell_establish_intro_free(cell); + + service_intro_point_free(ip); + return cell_len; +} + +static ssize_t +new_establish_intro_encoded_cell(const char *circ_nonce, uint8_t *cell_out) +{ + ssize_t cell_len = 0; + hs_service_intro_point_t *ip = NULL; + + /* Auth key pair is generated in the constructor so we are all set for + * using this IP object. */ + ip = service_intro_point_new(NULL, 0); + tt_assert(ip); + cell_len = hs_cell_build_establish_intro(circ_nonce, ip, cell_out); + tt_i64_op(cell_len, OP_GT, 0); + + done: + service_intro_point_free(ip); + return cell_len; +} /* Mock function to avoid networking in unittests */ static int @@ -122,50 +174,43 @@ static void test_establish_intro_wrong_purpose(void *arg) { int retval; - trn_cell_establish_intro_t *establish_intro_cell = NULL; - or_circuit_t *intro_circ = or_circuit_new(0,NULL);; - uint8_t cell_body[RELAY_PAYLOAD_SIZE]; ssize_t cell_len = 0; - uint8_t circuit_key_material[DIGEST_LEN] = {0}; + char circ_nonce[DIGEST_LEN] = {0}; + uint8_t cell_body[RELAY_PAYLOAD_SIZE]; + or_circuit_t *intro_circ = or_circuit_new(0,NULL); (void)arg; /* Get the auth key of the intro point */ - crypto_rand((char *) circuit_key_material, sizeof(circuit_key_material)); - memcpy(intro_circ->rend_circ_nonce, circuit_key_material, DIGEST_LEN); + crypto_rand(circ_nonce, sizeof(circ_nonce)); + memcpy(intro_circ->rend_circ_nonce, circ_nonce, DIGEST_LEN); /* Set a bad circuit purpose!! :) */ circuit_change_purpose(TO_CIRCUIT(intro_circ), CIRCUIT_PURPOSE_INTRO_POINT); /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we attempt to parse it. */ - establish_intro_cell = generate_establish_intro_cell(circuit_key_material, - sizeof(circuit_key_material)); - tt_assert(establish_intro_cell); - cell_len = get_establish_intro_payload(cell_body, sizeof(cell_body), - establish_intro_cell); - tt_int_op(cell_len, >, 0); + cell_len = new_establish_intro_encoded_cell(circ_nonce, cell_body); + tt_i64_op(cell_len, OP_GT, 0); /* Receive the cell. Should fail. */ setup_full_capture_of_logs(LOG_INFO); retval = hs_intro_received_establish_intro(intro_circ, cell_body, cell_len); expect_log_msg_containing("Rejecting ESTABLISH_INTRO on non-OR circuit."); teardown_capture_of_logs(); - tt_int_op(retval, ==, -1); + tt_int_op(retval, OP_EQ, -1); done: - trn_cell_establish_intro_free(establish_intro_cell); circuit_free(TO_CIRCUIT(intro_circ)); } /* Prepare a circuit for accepting an ESTABLISH_INTRO cell */ static void -helper_prepare_circ_for_intro(or_circuit_t *circ, - uint8_t *circuit_key_material) +helper_prepare_circ_for_intro(or_circuit_t *circ, const char *circ_nonce) { /* Prepare the circuit for the incoming ESTABLISH_INTRO */ circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_OR); - memcpy(circ->rend_circ_nonce, circuit_key_material, DIGEST_LEN); + memcpy(circ->rend_circ_nonce, circ_nonce, DIGEST_LEN); } /* Send an empty ESTABLISH_INTRO cell. Should fail. */ @@ -173,21 +218,21 @@ static void test_establish_intro_wrong_keytype(void *arg) { int retval; - or_circuit_t *intro_circ = or_circuit_new(0,NULL);; - uint8_t circuit_key_material[DIGEST_LEN] = {0}; + or_circuit_t *intro_circ = or_circuit_new(0,NULL); + char circ_nonce[DIGEST_LEN] = {0}; - (void)arg; + (void) arg; /* Get the auth key of the intro point */ - crypto_rand((char *) circuit_key_material, sizeof(circuit_key_material)); - helper_prepare_circ_for_intro(intro_circ, circuit_key_material); + crypto_rand(circ_nonce, sizeof(circ_nonce)); + helper_prepare_circ_for_intro(intro_circ, circ_nonce); /* Receive the cell. Should fail. */ setup_full_capture_of_logs(LOG_INFO); - retval = hs_intro_received_establish_intro(intro_circ, (uint8_t*)"", 0); + retval = hs_intro_received_establish_intro(intro_circ, (uint8_t *) "", 0); expect_log_msg_containing("Empty ESTABLISH_INTRO cell."); teardown_capture_of_logs(); - tt_int_op(retval, ==, -1); + tt_int_op(retval, OP_EQ, -1); done: circuit_free(TO_CIRCUIT(intro_circ)); @@ -198,26 +243,21 @@ static void test_establish_intro_wrong_keytype2(void *arg) { int retval; - trn_cell_establish_intro_t *establish_intro_cell = NULL; - or_circuit_t *intro_circ = or_circuit_new(0,NULL);; + char circ_nonce[DIGEST_LEN] = {0}; uint8_t cell_body[RELAY_PAYLOAD_SIZE]; ssize_t cell_len = 0; - uint8_t circuit_key_material[DIGEST_LEN] = {0}; + or_circuit_t *intro_circ = or_circuit_new(0,NULL); - (void)arg; + (void) arg; /* Get the auth key of the intro point */ - crypto_rand((char *) circuit_key_material, sizeof(circuit_key_material)); - helper_prepare_circ_for_intro(intro_circ, circuit_key_material); + crypto_rand(circ_nonce, sizeof(circ_nonce)); + helper_prepare_circ_for_intro(intro_circ, circ_nonce); /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we - attempt to parse it. */ - establish_intro_cell = generate_establish_intro_cell(circuit_key_material, - sizeof(circuit_key_material)); - tt_assert(establish_intro_cell); - cell_len = get_establish_intro_payload(cell_body, sizeof(cell_body), - establish_intro_cell); - tt_int_op(cell_len, >, 0); + * attempt to parse it. */ + cell_len = new_establish_intro_encoded_cell(circ_nonce, cell_body); + tt_i64_op(cell_len, OP_GT, 0); /* Mutate the auth key type! :) */ cell_body[0] = 42; @@ -227,10 +267,9 @@ test_establish_intro_wrong_keytype2(void *arg) retval = hs_intro_received_establish_intro(intro_circ, cell_body, cell_len); expect_log_msg_containing("Unrecognized AUTH_KEY_TYPE 42."); teardown_capture_of_logs(); - tt_int_op(retval, ==, -1); + tt_int_op(retval, OP_EQ, -1); done: - trn_cell_establish_intro_free(establish_intro_cell); circuit_free(TO_CIRCUIT(intro_circ)); } @@ -239,26 +278,27 @@ static void test_establish_intro_wrong_mac(void *arg) { int retval; - trn_cell_establish_intro_t *establish_intro_cell = NULL; - or_circuit_t *intro_circ = or_circuit_new(0,NULL);; - uint8_t cell_body[RELAY_PAYLOAD_SIZE]; + char circ_nonce[DIGEST_LEN] = {0}; ssize_t cell_len = 0; - uint8_t circuit_key_material[DIGEST_LEN] = {0}; + uint8_t cell_body[RELAY_PAYLOAD_SIZE]; + trn_cell_establish_intro_t *cell = NULL; + or_circuit_t *intro_circ = or_circuit_new(0,NULL); - (void)arg; + (void) arg; /* Get the auth key of the intro point */ - crypto_rand((char *) circuit_key_material, sizeof(circuit_key_material)); - helper_prepare_circ_for_intro(intro_circ, circuit_key_material); + crypto_rand(circ_nonce, sizeof(circ_nonce)); + helper_prepare_circ_for_intro(intro_circ, circ_nonce); /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we - attempt to parse it. */ - establish_intro_cell = generate_establish_intro_cell(circuit_key_material, - sizeof(circuit_key_material)); - tt_assert(establish_intro_cell); + * attempt to parse it. */ + cell_len = new_establish_intro_cell(circ_nonce, &cell); + tt_i64_op(cell_len, OP_GT, 0); + tt_assert(cell); + /* Mangle one byte of the MAC. */ uint8_t *handshake_ptr = - trn_cell_establish_intro_getarray_handshake_mac(establish_intro_cell); + trn_cell_establish_intro_getarray_handshake_mac(cell); handshake_ptr[TRUNNEL_SHA3_256_LEN - 1]++; /* We need to resign the payload with that change. */ { @@ -269,26 +309,26 @@ test_establish_intro_wrong_mac(void *arg) retval = ed25519_keypair_generate(&key_struct, 0); tt_int_op(retval, OP_EQ, 0); uint8_t *auth_key_ptr = - trn_cell_establish_intro_getarray_auth_key(establish_intro_cell); + trn_cell_establish_intro_getarray_auth_key(cell); memcpy(auth_key_ptr, key_struct.pubkey.pubkey, ED25519_PUBKEY_LEN); /* Encode payload so we can sign it. */ - cell_len = get_establish_intro_payload(cell_body, sizeof(cell_body), - establish_intro_cell); - tt_int_op(cell_len, >, 0); + cell_len = trn_cell_establish_intro_encode(cell_body, sizeof(cell_body), + cell); + tt_i64_op(cell_len, OP_GT, 0); retval = ed25519_sign_prefixed(&sig, cell_body, cell_len - - (ED25519_SIG_LEN + - sizeof(establish_intro_cell->sig_len)), + (ED25519_SIG_LEN + sizeof(cell->sig_len)), ESTABLISH_INTRO_SIG_PREFIX, &key_struct); tt_int_op(retval, OP_EQ, 0); /* And write the signature to the cell */ uint8_t *sig_ptr = - trn_cell_establish_intro_getarray_sig(establish_intro_cell); - memcpy(sig_ptr, sig.sig, establish_intro_cell->sig_len); + trn_cell_establish_intro_getarray_sig(cell); + memcpy(sig_ptr, sig.sig, cell->sig_len); /* Re-encode with the new signature. */ - cell_len = get_establish_intro_payload(cell_body, sizeof(cell_body), - establish_intro_cell); + cell_len = trn_cell_establish_intro_encode(cell_body, sizeof(cell_body), + cell); + tt_i64_op(cell_len, OP_GT, 0); } /* Receive the cell. Should fail because our MAC is wrong. */ @@ -296,10 +336,10 @@ test_establish_intro_wrong_mac(void *arg) retval = hs_intro_received_establish_intro(intro_circ, cell_body, cell_len); expect_log_msg_containing("ESTABLISH_INTRO handshake_auth not as expected"); teardown_capture_of_logs(); - tt_int_op(retval, ==, -1); + tt_int_op(retval, OP_EQ, -1); done: - trn_cell_establish_intro_free(establish_intro_cell); + trn_cell_establish_intro_free(cell); circuit_free(TO_CIRCUIT(intro_circ)); } @@ -309,42 +349,42 @@ static void test_establish_intro_wrong_auth_key_len(void *arg) { int retval; - trn_cell_establish_intro_t *establish_intro_cell = NULL; - or_circuit_t *intro_circ = or_circuit_new(0,NULL);; + char circ_nonce[DIGEST_LEN] = {0}; uint8_t cell_body[RELAY_PAYLOAD_SIZE]; ssize_t cell_len = 0; size_t bad_auth_key_len = ED25519_PUBKEY_LEN - 1; - uint8_t circuit_key_material[DIGEST_LEN] = {0}; + trn_cell_establish_intro_t *cell = NULL; + or_circuit_t *intro_circ = or_circuit_new(0,NULL); - (void)arg; + (void) arg; /* Get the auth key of the intro point */ - crypto_rand((char *) circuit_key_material, sizeof(circuit_key_material)); - helper_prepare_circ_for_intro(intro_circ, circuit_key_material); + crypto_rand(circ_nonce, sizeof(circ_nonce)); + helper_prepare_circ_for_intro(intro_circ, circ_nonce); /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we - attempt to parse it. */ - establish_intro_cell = generate_establish_intro_cell(circuit_key_material, - sizeof(circuit_key_material)); - tt_assert(establish_intro_cell); + * attempt to parse it. */ + cell_len = new_establish_intro_cell(circ_nonce, &cell); + tt_i64_op(cell_len, OP_GT, 0); + tt_assert(cell); + /* Mangle the auth key length. */ - trn_cell_establish_intro_set_auth_key_len(establish_intro_cell, - bad_auth_key_len); - trn_cell_establish_intro_setlen_auth_key(establish_intro_cell, - bad_auth_key_len); - cell_len = get_establish_intro_payload(cell_body, sizeof(cell_body), - establish_intro_cell); - tt_int_op(cell_len, >, 0); + trn_cell_establish_intro_set_auth_key_len(cell, bad_auth_key_len); + trn_cell_establish_intro_setlen_auth_key(cell, bad_auth_key_len); + /* Encode cell. */ + cell_len = trn_cell_establish_intro_encode(cell_body, sizeof(cell_body), + cell); + tt_int_op(cell_len, OP_GT, 0); /* Receive the cell. Should fail. */ setup_full_capture_of_logs(LOG_INFO); retval = hs_intro_received_establish_intro(intro_circ, cell_body, cell_len); expect_log_msg_containing("ESTABLISH_INTRO auth key length is invalid"); teardown_capture_of_logs(); - tt_int_op(retval, ==, -1); + tt_int_op(retval, OP_EQ, -1); done: - trn_cell_establish_intro_free(establish_intro_cell); + trn_cell_establish_intro_free(cell); circuit_free(TO_CIRCUIT(intro_circ)); } @@ -354,40 +394,42 @@ static void test_establish_intro_wrong_sig_len(void *arg) { int retval; - trn_cell_establish_intro_t *establish_intro_cell = NULL; - or_circuit_t *intro_circ = or_circuit_new(0,NULL);; + char circ_nonce[DIGEST_LEN] = {0}; uint8_t cell_body[RELAY_PAYLOAD_SIZE]; ssize_t cell_len = 0; size_t bad_sig_len = ED25519_SIG_LEN - 1; - uint8_t circuit_key_material[DIGEST_LEN] = {0}; + trn_cell_establish_intro_t *cell = NULL; + or_circuit_t *intro_circ = or_circuit_new(0,NULL); - (void)arg; + (void) arg; /* Get the auth key of the intro point */ - crypto_rand((char *) circuit_key_material, sizeof(circuit_key_material)); - helper_prepare_circ_for_intro(intro_circ, circuit_key_material); + crypto_rand(circ_nonce, sizeof(circ_nonce)); + helper_prepare_circ_for_intro(intro_circ, circ_nonce); /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we - attempt to parse it. */ - establish_intro_cell = generate_establish_intro_cell(circuit_key_material, - sizeof(circuit_key_material)); - tt_assert(establish_intro_cell); + * attempt to parse it. */ + cell_len = new_establish_intro_cell(circ_nonce, &cell); + tt_i64_op(cell_len, OP_GT, 0); + tt_assert(cell); + /* Mangle the signature length. */ - trn_cell_establish_intro_set_sig_len(establish_intro_cell, bad_sig_len); - trn_cell_establish_intro_setlen_sig(establish_intro_cell, bad_sig_len); - cell_len = get_establish_intro_payload(cell_body, sizeof(cell_body), - establish_intro_cell); - tt_int_op(cell_len, >, 0); + trn_cell_establish_intro_set_sig_len(cell, bad_sig_len); + trn_cell_establish_intro_setlen_sig(cell, bad_sig_len); + /* Encode cell. */ + cell_len = trn_cell_establish_intro_encode(cell_body, sizeof(cell_body), + cell); + tt_int_op(cell_len, OP_GT, 0); /* Receive the cell. Should fail. */ setup_full_capture_of_logs(LOG_INFO); retval = hs_intro_received_establish_intro(intro_circ, cell_body, cell_len); expect_log_msg_containing("ESTABLISH_INTRO sig len is invalid"); teardown_capture_of_logs(); - tt_int_op(retval, ==, -1); + tt_int_op(retval, OP_EQ, -1); done: - trn_cell_establish_intro_free(establish_intro_cell); + trn_cell_establish_intro_free(cell); circuit_free(TO_CIRCUIT(intro_circ)); } @@ -397,39 +439,34 @@ static void test_establish_intro_wrong_sig(void *arg) { int retval; - trn_cell_establish_intro_t *establish_intro_cell = NULL; - or_circuit_t *intro_circ = or_circuit_new(0,NULL);; + char circ_nonce[DIGEST_LEN] = {0}; uint8_t cell_body[RELAY_PAYLOAD_SIZE]; ssize_t cell_len = 0; - uint8_t circuit_key_material[DIGEST_LEN] = {0}; + or_circuit_t *intro_circ = or_circuit_new(0,NULL); - (void)arg; + (void) arg; /* Get the auth key of the intro point */ - crypto_rand((char *) circuit_key_material, sizeof(circuit_key_material)); - helper_prepare_circ_for_intro(intro_circ, circuit_key_material); + crypto_rand(circ_nonce, sizeof(circ_nonce)); + helper_prepare_circ_for_intro(intro_circ, circ_nonce); /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we attempt to parse it. */ - establish_intro_cell = generate_establish_intro_cell(circuit_key_material, - sizeof(circuit_key_material)); - tt_assert(establish_intro_cell); - cell_len = get_establish_intro_payload(cell_body, sizeof(cell_body), - establish_intro_cell); - tt_int_op(cell_len, >, 0); + cell_len = new_establish_intro_encoded_cell(circ_nonce, cell_body); + tt_i64_op(cell_len, OP_GT, 0); /* Mutate the last byte (signature)! :) */ - cell_body[cell_len-1]++; + cell_body[cell_len - 1]++; /* Receive the cell. Should fail. */ setup_full_capture_of_logs(LOG_INFO); - retval = hs_intro_received_establish_intro(intro_circ, cell_body, cell_len); + retval = hs_intro_received_establish_intro(intro_circ, cell_body, + (size_t)cell_len); expect_log_msg_containing("Failed to verify ESTABLISH_INTRO cell."); teardown_capture_of_logs(); - tt_int_op(retval, ==, -1); + tt_int_op(retval, OP_EQ, -1); done: - trn_cell_establish_intro_free(establish_intro_cell); circuit_free(TO_CIRCUIT(intro_circ)); } @@ -439,32 +476,33 @@ static trn_cell_establish_intro_t * helper_establish_intro_v3(or_circuit_t *intro_circ) { int retval; - trn_cell_establish_intro_t *establish_intro_cell = NULL; + char circ_nonce[DIGEST_LEN] = {0}; uint8_t cell_body[RELAY_PAYLOAD_SIZE]; ssize_t cell_len = 0; - uint8_t circuit_key_material[DIGEST_LEN] = {0}; + trn_cell_establish_intro_t *cell = NULL; tt_assert(intro_circ); /* Prepare the circuit for the incoming ESTABLISH_INTRO */ - crypto_rand((char *) circuit_key_material, sizeof(circuit_key_material)); - helper_prepare_circ_for_intro(intro_circ, circuit_key_material); + crypto_rand(circ_nonce, sizeof(circ_nonce)); + helper_prepare_circ_for_intro(intro_circ, circ_nonce); /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we - attempt to parse it. */ - establish_intro_cell = generate_establish_intro_cell(circuit_key_material, - sizeof(circuit_key_material)); - tt_assert(establish_intro_cell); - cell_len = get_establish_intro_payload(cell_body, sizeof(cell_body), - establish_intro_cell); - tt_int_op(cell_len, >, 0); + * attempt to parse it. */ + cell_len = new_establish_intro_cell(circ_nonce, &cell); + tt_i64_op(cell_len, OP_GT, 0); + tt_assert(cell); + cell_len = trn_cell_establish_intro_encode(cell_body, sizeof(cell_body), + cell); + tt_int_op(cell_len, OP_GT, 0); /* Receive the cell */ - retval = hs_intro_received_establish_intro(intro_circ, cell_body, cell_len); - tt_int_op(retval, ==, 0); + retval = hs_intro_received_establish_intro(intro_circ, cell_body, + (size_t) cell_len); + tt_int_op(retval, OP_EQ, 0); done: - return establish_intro_cell; + return cell; } /* Helper function: Send a well-formed v2 ESTABLISH_INTRO cell to @@ -476,28 +514,28 @@ helper_establish_intro_v2(or_circuit_t *intro_circ) int retval; uint8_t cell_body[RELAY_PAYLOAD_SIZE]; ssize_t cell_len = 0; - uint8_t circuit_key_material[DIGEST_LEN] = {0}; + char circ_nonce[DIGEST_LEN] = {0}; tt_assert(intro_circ); /* Prepare the circuit for the incoming ESTABLISH_INTRO */ - crypto_rand((char *) circuit_key_material, sizeof(circuit_key_material)); - helper_prepare_circ_for_intro(intro_circ, circuit_key_material); + crypto_rand(circ_nonce, sizeof(circ_nonce)); + helper_prepare_circ_for_intro(intro_circ, circ_nonce); /* Send legacy establish_intro */ key1 = pk_generate(0); - /* Use old circuit_key_material why not */ - cell_len = encode_establish_intro_cell_legacy((char*)cell_body, - sizeof(cell_body), - key1, - (char *) circuit_key_material); - tt_int_op(cell_len, >, 0); + /* Use old circ_nonce why not */ + cell_len = rend_service_encode_establish_intro_cell( + (char*)cell_body, + sizeof(cell_body), key1, + circ_nonce); + tt_int_op(cell_len, OP_GT, 0); /* Receive legacy establish_intro */ retval = hs_intro_received_establish_intro(intro_circ, - cell_body, cell_len); - tt_int_op(retval, ==, 0); + cell_body, (size_t) cell_len); + tt_int_op(retval, OP_EQ, 0); done: return key1; @@ -516,7 +554,7 @@ test_circuitmap_free_all(void) tt_assert(the_hs_circuitmap); hs_circuitmap_free_all(); the_hs_circuitmap = get_hs_circuitmap(); - tt_assert(!the_hs_circuitmap); + tt_ptr_op(the_hs_circuitmap, OP_EQ, NULL); done: ; } @@ -548,10 +586,10 @@ test_intro_point_registration(void *arg) { the_hs_circuitmap = get_hs_circuitmap(); tt_assert(the_hs_circuitmap); - tt_int_op(0, ==, HT_SIZE(the_hs_circuitmap)); + tt_int_op(0, OP_EQ, HT_SIZE(the_hs_circuitmap)); /* Do a circuitmap query in any case */ returned_intro_circ =hs_circuitmap_get_intro_circ_v3_relay_side(&auth_key); - tt_ptr_op(returned_intro_circ, ==, NULL); + tt_ptr_op(returned_intro_circ, OP_EQ, NULL); } /* Create a v3 intro point */ @@ -563,12 +601,12 @@ test_intro_point_registration(void *arg) /* Check that the intro point was registered on the HS circuitmap */ the_hs_circuitmap = get_hs_circuitmap(); tt_assert(the_hs_circuitmap); - tt_int_op(1, ==, HT_SIZE(the_hs_circuitmap)); + tt_int_op(1, OP_EQ, HT_SIZE(the_hs_circuitmap)); get_auth_key_from_cell(&auth_key, RELAY_COMMAND_ESTABLISH_INTRO, establish_intro_cell); returned_intro_circ = hs_circuitmap_get_intro_circ_v3_relay_side(&auth_key); - tt_ptr_op(intro_circ, ==, returned_intro_circ); + tt_ptr_op(intro_circ, OP_EQ, returned_intro_circ); } /* Create a v2 intro point */ @@ -583,14 +621,14 @@ test_intro_point_registration(void *arg) /* Check that the circuitmap now has two elements */ the_hs_circuitmap = get_hs_circuitmap(); tt_assert(the_hs_circuitmap); - tt_int_op(2, ==, HT_SIZE(the_hs_circuitmap)); + tt_int_op(2, OP_EQ, HT_SIZE(the_hs_circuitmap)); /* Check that the new element is our legacy intro circuit. */ retval = crypto_pk_get_digest(legacy_auth_key, key_digest); - tt_int_op(retval, ==, 0); + tt_int_op(retval, OP_EQ, 0); returned_intro_circ = hs_circuitmap_get_intro_circ_v2_relay_side((uint8_t*)key_digest); - tt_ptr_op(legacy_intro_circ, ==, returned_intro_circ); + tt_ptr_op(legacy_intro_circ, OP_EQ, returned_intro_circ); } /* XXX Continue test and try to register a second v3 intro point with the @@ -765,6 +803,7 @@ test_received_introduce1_handling(void *arg) /* Too small request length. An INTRODUCE1 expect at the very least a * DIGEST_LEN size. */ { + memset(buf, 0, sizeof(buf)); circ = helper_create_intro_circuit(); ret = hs_intro_received_introduce1(circ, buf, DIGEST_LEN - 1); tt_int_op(ret, OP_EQ, -1); @@ -778,6 +817,7 @@ test_received_introduce1_handling(void *arg) { circ = helper_create_intro_circuit(); uint8_t test[2]; /* Too small request. */ + memset(test, 0, sizeof(test)); ret = handle_introduce1(circ, test, sizeof(test)); tor_free(circ->p_chan); circuit_free(TO_CIRCUIT(circ)); diff --git a/src/test/test_hs_ntor.c b/src/test/test_hs_ntor.c new file mode 100644 index 0000000000..8eee54d4b4 --- /dev/null +++ b/src/test/test_hs_ntor.c @@ -0,0 +1,114 @@ +/* Copyright (c) 2017, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file test_hs_ntor.c + * \brief Test hidden service ntor functionality. + */ + +#include "test.h" +#include "test_helpers.h" +#include "log_test_helpers.h" + +#include "hs_ntor.h" + +/* Test the HS ntor handshake. Simulate the sending of an encrypted INTRODUCE1 + * cell, and verify the proper derivation of decryption keys on the other end. + * Then simulate the sending of an authenticated RENDEZVOUS1 cell and verify + * the proper verification on the other end. */ +static void +test_hs_ntor(void *arg) +{ + int retval; + + uint8_t subcredential[DIGEST256_LEN]; + + ed25519_keypair_t service_intro_auth_keypair; + curve25519_keypair_t service_intro_enc_keypair; + curve25519_keypair_t service_ephemeral_rend_keypair; + + curve25519_keypair_t client_ephemeral_enc_keypair; + + hs_ntor_intro_cell_keys_t client_hs_ntor_intro_cell_keys; + hs_ntor_intro_cell_keys_t service_hs_ntor_intro_cell_keys; + + hs_ntor_rend_cell_keys_t service_hs_ntor_rend_cell_keys; + hs_ntor_rend_cell_keys_t client_hs_ntor_rend_cell_keys; + + (void) arg; + + /* Generate fake data for this unittest */ + { + /* Generate fake subcredential */ + memset(subcredential, 'Z', DIGEST256_LEN); + + /* service */ + curve25519_keypair_generate(&service_intro_enc_keypair, 0); + ed25519_keypair_generate(&service_intro_auth_keypair, 0); + curve25519_keypair_generate(&service_ephemeral_rend_keypair, 0); + /* client */ + curve25519_keypair_generate(&client_ephemeral_enc_keypair, 0); + } + + /* Client: Simulate the sending of an encrypted INTRODUCE1 cell */ + retval = + hs_ntor_client_get_introduce1_keys(&service_intro_auth_keypair.pubkey, + &service_intro_enc_keypair.pubkey, + &client_ephemeral_enc_keypair, + subcredential, + &client_hs_ntor_intro_cell_keys); + tt_int_op(retval, OP_EQ, 0); + + /* Service: Simulate the decryption of the received INTRODUCE1 */ + retval = + hs_ntor_service_get_introduce1_keys(&service_intro_auth_keypair.pubkey, + &service_intro_enc_keypair, + &client_ephemeral_enc_keypair.pubkey, + subcredential, + &service_hs_ntor_intro_cell_keys); + tt_int_op(retval, OP_EQ, 0); + + /* Test that the INTRODUCE1 encryption/mac keys match! */ + tt_mem_op(client_hs_ntor_intro_cell_keys.enc_key, OP_EQ, + service_hs_ntor_intro_cell_keys.enc_key, + CIPHER256_KEY_LEN); + tt_mem_op(client_hs_ntor_intro_cell_keys.mac_key, OP_EQ, + service_hs_ntor_intro_cell_keys.mac_key, + DIGEST256_LEN); + + /* Service: Simulate creation of RENDEZVOUS1 key material. */ + retval = + hs_ntor_service_get_rendezvous1_keys(&service_intro_auth_keypair.pubkey, + &service_intro_enc_keypair, + &service_ephemeral_rend_keypair, + &client_ephemeral_enc_keypair.pubkey, + &service_hs_ntor_rend_cell_keys); + tt_int_op(retval, OP_EQ, 0); + + /* Client: Simulate the verification of a received RENDEZVOUS1 cell */ + retval = + hs_ntor_client_get_rendezvous1_keys(&service_intro_auth_keypair.pubkey, + &client_ephemeral_enc_keypair, + &service_intro_enc_keypair.pubkey, + &service_ephemeral_rend_keypair.pubkey, + &client_hs_ntor_rend_cell_keys); + tt_int_op(retval, OP_EQ, 0); + + /* Test that the RENDEZVOUS1 key material match! */ + tt_mem_op(client_hs_ntor_rend_cell_keys.rend_cell_auth_mac, OP_EQ, + service_hs_ntor_rend_cell_keys.rend_cell_auth_mac, + DIGEST256_LEN); + tt_mem_op(client_hs_ntor_rend_cell_keys.ntor_key_seed, OP_EQ, + service_hs_ntor_rend_cell_keys.ntor_key_seed, + DIGEST256_LEN); + done: + ; +} + +struct testcase_t hs_ntor_tests[] = { + { "hs_ntor", test_hs_ntor, TT_FORK, + NULL, NULL }, + + END_OF_TESTCASES +}; + diff --git a/src/test/test_hs_service.c b/src/test/test_hs_service.c index fcfb3b992d..d040f10e0c 100644 --- a/src/test/test_hs_service.c +++ b/src/test/test_hs_service.c @@ -6,243 +6,1618 @@ * \brief Test hidden service functionality. */ +#define CIRCUITBUILD_PRIVATE +#define CIRCUITLIST_PRIVATE +#define CONFIG_PRIVATE +#define CONNECTION_PRIVATE +#define CRYPTO_PRIVATE #define HS_COMMON_PRIVATE #define HS_SERVICE_PRIVATE #define HS_INTROPOINT_PRIVATE +#define HS_CIRCUIT_PRIVATE +#define MAIN_PRIVATE +#define NETWORKSTATUS_PRIVATE +#define STATEFILE_PRIVATE +#define TOR_CHANNEL_INTERNAL_ +#define HS_CLIENT_PRIVATE #include "test.h" +#include "test_helpers.h" #include "log_test_helpers.h" +#include "rend_test_helpers.h" +#include "hs_test_helpers.h" + +#include "or.h" +#include "config.h" +#include "circuitbuild.h" +#include "circuitlist.h" +#include "circuituse.h" #include "crypto.h" +#include "dirvote.h" +#include "networkstatus.h" +#include "nodelist.h" +#include "relay.h" -#include "hs/cell_establish_intro.h" #include "hs_common.h" -#include "hs_service.h" +#include "hs_config.h" +#include "hs_ident.h" #include "hs_intropoint.h" - #include "hs_ntor.h" +#include "hs_circuit.h" +#include "hs_service.h" +#include "hs_client.h" +#include "main.h" +#include "rendservice.h" +#include "statefile.h" +#include "shared_random_state.h" + +/* Trunnel */ +#include "hs/cell_establish_intro.h" + +static networkstatus_t mock_ns; + +static networkstatus_t * +mock_networkstatus_get_live_consensus(time_t now) +{ + (void) now; + return &mock_ns; +} + +static or_state_t *dummy_state = NULL; + +/* Mock function to get fake or state (used for rev counters) */ +static or_state_t * +get_or_state_replacement(void) +{ + return dummy_state; +} + +/* Mock function because we are not trying to test the close circuit that does + * an awful lot of checks on the circuit object. */ +static void +mock_circuit_mark_for_close(circuit_t *circ, int reason, int line, + const char *file) +{ + (void) circ; + (void) reason; + (void) line; + (void) file; + return; +} + +static int +mock_relay_send_command_from_edge(streamid_t stream_id, circuit_t *circ, + uint8_t relay_command, const char *payload, + size_t payload_len, + crypt_path_t *cpath_layer, + const char *filename, int lineno) +{ + (void) stream_id; + (void) circ; + (void) relay_command; + (void) payload; + (void) payload_len; + (void) cpath_layer; + (void) filename; + (void) lineno; + return 0; +} -/** We simulate the creation of an outgoing ESTABLISH_INTRO cell, and then we - * parse it from the receiver side. */ +/* Helper: from a set of options in conf, configure a service which will add + * it to the staging list of the HS subsytem. */ +static int +helper_config_service(const char *conf) +{ + int ret = 0; + or_options_t *options = NULL; + tt_assert(conf); + options = helper_parse_options(conf); + tt_assert(options); + ret = hs_config_service_all(options, 0); + done: + or_options_free(options); + return ret; +} + +/* Test: Ensure that setting up rendezvous circuits works correctly. */ static void -test_gen_establish_intro_cell(void *arg) +test_e2e_rend_circuit_setup(void *arg) { + ed25519_public_key_t service_pk; + origin_circuit_t *or_circ; + int retval; + + /** In this test we create a v3 prop224 service-side rendezvous circuit. + * We simulate an HS ntor key exchange with a client, and check that + * the circuit was setup correctly and is ready to accept rendezvous data */ + (void) arg; - ssize_t retval; - uint8_t circuit_key_material[DIGEST_LEN] = {0}; - uint8_t buf[RELAY_PAYLOAD_SIZE]; - trn_cell_establish_intro_t *cell_out = NULL; - trn_cell_establish_intro_t *cell_in = NULL; - crypto_rand((char *) circuit_key_material, sizeof(circuit_key_material)); + /* Now make dummy circuit */ + { + or_circ = origin_circuit_new(); - /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we - attempt to parse it. */ + or_circ->base_.purpose = CIRCUIT_PURPOSE_S_CONNECT_REND; + + or_circ->build_state = tor_malloc_zero(sizeof(cpath_build_state_t)); + or_circ->build_state->is_internal = 1; + + /* prop224: Setup hs conn identifier on the stream */ + ed25519_secret_key_t sk; + tt_int_op(0, OP_EQ, ed25519_secret_key_generate(&sk, 0)); + tt_int_op(0, OP_EQ, ed25519_public_key_generate(&service_pk, &sk)); + + or_circ->hs_ident = hs_ident_circuit_new(&service_pk, + HS_IDENT_CIRCUIT_RENDEZVOUS); + + TO_CIRCUIT(or_circ)->state = CIRCUIT_STATE_OPEN; + } + + /* Check number of hops */ + retval = cpath_get_n_hops(&or_circ->cpath); + tt_int_op(retval, OP_EQ, 0); + + /* Setup the circuit: do the ntor key exchange */ { - cell_out = generate_establish_intro_cell(circuit_key_material, - sizeof(circuit_key_material)); - tt_assert(cell_out); + uint8_t ntor_key_seed[DIGEST256_LEN] = {2}; + retval = hs_circuit_setup_e2e_rend_circ(or_circ, + ntor_key_seed, sizeof(ntor_key_seed), + 1); + tt_int_op(retval, OP_EQ, 0); + } + + /* See that a hop was added to the circuit's cpath */ + retval = cpath_get_n_hops(&or_circ->cpath); + tt_int_op(retval, OP_EQ, 1); + + /* Check the digest algo */ + tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->f_digest), + OP_EQ, DIGEST_SHA3_256); + tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->b_digest), + OP_EQ, DIGEST_SHA3_256); + tt_assert(or_circ->cpath->f_crypto); + tt_assert(or_circ->cpath->b_crypto); + + /* Ensure that circ purpose was changed */ + tt_int_op(or_circ->base_.purpose, OP_EQ, CIRCUIT_PURPOSE_S_REND_JOINED); + + done: + circuit_free(TO_CIRCUIT(or_circ)); +} + +/* Helper: Return a newly allocated and initialized origin circuit with + * purpose and flags. A default HS identifier is set to an ed25519 + * authentication key for introduction point. */ +static origin_circuit_t * +helper_create_origin_circuit(int purpose, int flags) +{ + origin_circuit_t *circ = NULL; + + circ = origin_circuit_init(purpose, flags); + tt_assert(circ); + circ->cpath = tor_malloc_zero(sizeof(crypt_path_t)); + circ->cpath->magic = CRYPT_PATH_MAGIC; + circ->cpath->state = CPATH_STATE_OPEN; + circ->cpath->package_window = circuit_initial_package_window(); + circ->cpath->deliver_window = CIRCWINDOW_START; + circ->cpath->prev = circ->cpath; + /* Random nonce. */ + crypto_rand(circ->cpath->prev->rend_circ_nonce, DIGEST_LEN); + /* Create a default HS identifier. */ + circ->hs_ident = tor_malloc_zero(sizeof(hs_ident_circuit_t)); + + done: + return circ; +} + +/* Helper: Return a newly allocated service object with the identity keypair + * sets and the current descriptor. Then register it to the global map. + * Caller should us hs_free_all() to free this service or remove it from the + * global map before freeing. */ +static hs_service_t * +helper_create_service(void) +{ + /* Set a service for this circuit. */ + hs_service_t *service = hs_service_new(get_options()); + tt_assert(service); + service->config.version = HS_VERSION_THREE; + ed25519_secret_key_generate(&service->keys.identity_sk, 0); + ed25519_public_key_generate(&service->keys.identity_pk, + &service->keys.identity_sk); + service->desc_current = service_descriptor_new(); + tt_assert(service->desc_current); + /* Register service to global map. */ + int ret = register_service(get_hs_service_map(), service); + tt_int_op(ret, OP_EQ, 0); + + done: + return service; +} + +/* Helper: Return a newly allocated service intro point with two link + * specifiers, one IPv4 and one legacy ID set to As. */ +static hs_service_intro_point_t * +helper_create_service_ip(void) +{ + hs_desc_link_specifier_t *ls; + hs_service_intro_point_t *ip = service_intro_point_new(NULL, 0); + tt_assert(ip); + /* Add a first unused link specifier. */ + ls = tor_malloc_zero(sizeof(*ls)); + ls->type = LS_IPV4; + smartlist_add(ip->base.link_specifiers, ls); + /* Add a second link specifier used by a test. */ + ls = tor_malloc_zero(sizeof(*ls)); + ls->type = LS_LEGACY_ID; + memset(ls->u.legacy_id, 'A', sizeof(ls->u.legacy_id)); + smartlist_add(ip->base.link_specifiers, ls); + + done: + return ip; +} + +static void +test_load_keys(void *arg) +{ + int ret; + char *conf = NULL; + char *hsdir_v2 = tor_strdup(get_fname("hs2")); + char *hsdir_v3 = tor_strdup(get_fname("hs3")); + char addr[HS_SERVICE_ADDR_LEN_BASE32 + 1]; + + (void) arg; + + /* We'll register two services, a v2 and a v3, then we'll load keys and + * validate that both are in a correct state. */ + + hs_init(); + +#define conf_fmt \ + "HiddenServiceDir %s\n" \ + "HiddenServiceVersion %d\n" \ + "HiddenServicePort 65535\n" + + /* v2 service. */ + tor_asprintf(&conf, conf_fmt, hsdir_v2, HS_VERSION_TWO); + ret = helper_config_service(conf); + tor_free(conf); + tt_int_op(ret, OP_EQ, 0); + /* This one should now be registered into the v2 list. */ + tt_int_op(get_hs_service_staging_list_size(), OP_EQ, 0); + tt_int_op(rend_num_services(), OP_EQ, 1); + + /* v3 service. */ + tor_asprintf(&conf, conf_fmt, hsdir_v3, HS_VERSION_THREE); + ret = helper_config_service(conf); + tor_free(conf); + tt_int_op(ret, OP_EQ, 0); + /* It's in staging? */ + tt_int_op(get_hs_service_staging_list_size(), OP_EQ, 1); + + /* Load the keys for these. After that, the v3 service should be registered + * in the global map. */ + hs_service_load_all_keys(); + tt_int_op(get_hs_service_map_size(), OP_EQ, 1); + hs_service_t *s = get_first_service(); + tt_assert(s); + + /* Ok we have the service object. Validate few things. */ + tt_assert(!tor_mem_is_zero(s->onion_address, sizeof(s->onion_address))); + tt_int_op(hs_address_is_valid(s->onion_address), OP_EQ, 1); + tt_assert(!tor_mem_is_zero((char *) s->keys.identity_sk.seckey, + ED25519_SECKEY_LEN)); + tt_assert(!tor_mem_is_zero((char *) s->keys.identity_pk.pubkey, + ED25519_PUBKEY_LEN)); + /* Check onion address from identity key. */ + hs_build_address(&s->keys.identity_pk, s->config.version, addr); + tt_int_op(hs_address_is_valid(addr), OP_EQ, 1); + tt_str_op(addr, OP_EQ, s->onion_address); + + done: + tor_free(hsdir_v2); + tor_free(hsdir_v3); + hs_free_all(); +} + +static void +test_access_service(void *arg) +{ + int ret; + char *conf = NULL; + char *hsdir_v3 = tor_strdup(get_fname("hs3")); + hs_service_ht *global_map; + hs_service_t *s = NULL; + + (void) arg; + + /* We'll register two services, a v2 and a v3, then we'll load keys and + * validate that both are in a correct state. */ - retval = get_establish_intro_payload(buf, sizeof(buf), cell_out); - tt_int_op(retval, >=, 0); + hs_init(); + +#define conf_fmt \ + "HiddenServiceDir %s\n" \ + "HiddenServiceVersion %d\n" \ + "HiddenServicePort 65535\n" + + /* v3 service. */ + tor_asprintf(&conf, conf_fmt, hsdir_v3, HS_VERSION_THREE); + ret = helper_config_service(conf); + tor_free(conf); + tt_int_op(ret, OP_EQ, 0); + /* It's in staging? */ + tt_int_op(get_hs_service_staging_list_size(), OP_EQ, 1); + + /* Load the keys for these. After that, the v3 service should be registered + * in the global map. */ + hs_service_load_all_keys(); + tt_int_op(get_hs_service_map_size(), OP_EQ, 1); + s = get_first_service(); + tt_assert(s); + global_map = get_hs_service_map(); + tt_assert(global_map); + + /* From here, we'll try the service accessors. */ + hs_service_t *query = find_service(global_map, &s->keys.identity_pk); + tt_assert(query); + tt_mem_op(query, OP_EQ, s, sizeof(hs_service_t)); + /* Remove service, check if it actually works and then put it back. */ + remove_service(global_map, s); + tt_int_op(get_hs_service_map_size(), OP_EQ, 0); + query = find_service(global_map, &s->keys.identity_pk); + tt_ptr_op(query, OP_EQ, NULL); + + /* Register back the service in the map. */ + ret = register_service(global_map, s); + tt_int_op(ret, OP_EQ, 0); + tt_int_op(get_hs_service_map_size(), OP_EQ, 1); + /* Twice should fail. */ + ret = register_service(global_map, s); + tt_int_op(ret, OP_EQ, -1); + /* Remove service from map so we don't double free on cleanup. */ + remove_service(global_map, s); + tt_int_op(get_hs_service_map_size(), OP_EQ, 0); + query = find_service(global_map, &s->keys.identity_pk); + tt_ptr_op(query, OP_EQ, NULL); + /* Let's try to remove twice for fun. */ + setup_full_capture_of_logs(LOG_WARN); + remove_service(global_map, s); + expect_log_msg_containing("Could not find service in the global map"); + teardown_capture_of_logs(); + + done: + hs_service_free(s); + tor_free(hsdir_v3); + hs_free_all(); +} + +/** Test that we can create intro point objects, index them and find them */ +static void +test_service_intro_point(void *arg) +{ + hs_service_t *service = NULL; + hs_service_intro_point_t *ip = NULL; + + (void) arg; + + /* Test simple creation of an object. */ + { + time_t now = time(NULL); + ip = helper_create_service_ip(); + tt_assert(ip); + /* Make sure the authentication keypair is not zeroes. */ + tt_int_op(tor_mem_is_zero((const char *) &ip->auth_key_kp, + sizeof(ed25519_keypair_t)), OP_EQ, 0); + /* The introduce2_max MUST be in that range. */ + tt_u64_op(ip->introduce2_max, OP_GE, + INTRO_POINT_MIN_LIFETIME_INTRODUCTIONS); + tt_u64_op(ip->introduce2_max, OP_LE, + INTRO_POINT_MAX_LIFETIME_INTRODUCTIONS); + /* Time to expire MUST also be in that range. We subtract 500 seconds + * because there could be a gap between setting now and the time taken in + * service_intro_point_new. On ARM and other older CPUs, it can be + * surprisingly slow... */ + tt_u64_op(ip->time_to_expire, OP_GE, + now + INTRO_POINT_LIFETIME_MIN_SECONDS - 500); + /* We add 500 seconds, because this time we're testing against the + * maximum allowed time. */ + tt_u64_op(ip->time_to_expire, OP_LE, + now + INTRO_POINT_LIFETIME_MAX_SECONDS + 500); + tt_assert(ip->replay_cache); + tt_assert(ip->base.link_specifiers); + /* By default, this is NOT a legacy object. */ + tt_int_op(ip->base.is_only_legacy, OP_EQ, 0); } - /* Parse it as the receiver */ + /* Test functions that uses a service intropoints map with that previously + * created object (non legacy). */ { - ssize_t parse_result = trn_cell_establish_intro_parse(&cell_in, - buf, sizeof(buf)); - tt_int_op(parse_result, >=, 0); + ed25519_public_key_t garbage = { {0} }; + hs_service_intro_point_t *query; + + service = hs_service_new(get_options()); + tt_assert(service); + service->desc_current = service_descriptor_new(); + tt_assert(service->desc_current); + /* Add intropoint to descriptor map. */ + service_intro_point_add(service->desc_current->intro_points.map, ip); + query = service_intro_point_find(service, &ip->auth_key_kp.pubkey); + tt_mem_op(query, OP_EQ, ip, sizeof(hs_service_intro_point_t)); + query = service_intro_point_find(service, &garbage); + tt_ptr_op(query, OP_EQ, NULL); + + /* While at it, can I find the descriptor with the intro point? */ + hs_service_descriptor_t *desc_lookup = + service_desc_find_by_intro(service, ip); + tt_mem_op(service->desc_current, OP_EQ, desc_lookup, + sizeof(hs_service_descriptor_t)); - retval = verify_establish_intro_cell(cell_in, - circuit_key_material, - sizeof(circuit_key_material)); - tt_int_op(retval, >=, 0); + /* Remove object from service descriptor and make sure it is out. */ + service_intro_point_remove(service, ip); + query = service_intro_point_find(service, &ip->auth_key_kp.pubkey); + tt_ptr_op(query, OP_EQ, NULL); } done: - trn_cell_establish_intro_free(cell_out); - trn_cell_establish_intro_free(cell_in); + /* If the test succeed, this object is no longer referenced in the service + * so we can free it without use after free. Else, it might explode because + * it's still in the service descriptor map. */ + service_intro_point_free(ip); + hs_service_free(service); } -/* Mocked ed25519_sign_prefixed() function that always fails :) */ -static int -mock_ed25519_sign_prefixed(ed25519_signature_t *signature_out, - const uint8_t *msg, size_t msg_len, - const char *prefix_str, - const ed25519_keypair_t *keypair) { - (void) signature_out; - (void) msg; - (void) msg_len; - (void) prefix_str; - (void) keypair; - return -1; +static node_t mock_node; +static const node_t * +mock_node_get_by_id(const char *digest) +{ + (void) digest; + memset(mock_node.identity, 'A', DIGEST_LEN); + /* Only return the matchin identity of As */ + if (!tor_memcmp(mock_node.identity, digest, DIGEST_LEN)) { + return &mock_node; + } + return NULL; } -/** We simulate a failure to create an ESTABLISH_INTRO cell */ static void -test_gen_establish_intro_cell_bad(void *arg) +test_helper_functions(void *arg) { + int ret; + hs_service_t *service = NULL; + hs_service_intro_point_t *ip = NULL; + hs_ident_circuit_t ident; + (void) arg; - trn_cell_establish_intro_t *cell = NULL; - uint8_t circuit_key_material[DIGEST_LEN] = {0}; - MOCK(ed25519_sign_prefixed, mock_ed25519_sign_prefixed); + MOCK(node_get_by_id, mock_node_get_by_id); + + hs_service_init(); + + service = helper_create_service(); + + ip = helper_create_service_ip(); + /* Immediately add the intro point to the service so the free service at the + * end cleans it as well. */ + service_intro_point_add(service->desc_current->intro_points.map, ip); + + /* Setup the circuit identifier. */ + ed25519_pubkey_copy(&ident.intro_auth_pk, &ip->auth_key_kp.pubkey); + ed25519_pubkey_copy(&ident.identity_pk, &service->keys.identity_pk); - crypto_rand((char *) circuit_key_material, sizeof(circuit_key_material)); + /* Testing get_objects_from_ident(). */ + { + hs_service_t *s_lookup = NULL; + hs_service_intro_point_t *ip_lookup = NULL; + hs_service_descriptor_t *desc_lookup = NULL; + + get_objects_from_ident(&ident, &s_lookup, &ip_lookup, &desc_lookup); + tt_mem_op(s_lookup, OP_EQ, service, sizeof(hs_service_t)); + tt_mem_op(ip_lookup, OP_EQ, ip, sizeof(hs_service_intro_point_t)); + tt_mem_op(desc_lookup, OP_EQ, service->desc_current, + sizeof(hs_service_descriptor_t)); + /* Reset */ + s_lookup = NULL; ip_lookup = NULL; desc_lookup = NULL; + + /* NULL parameter should work. */ + get_objects_from_ident(&ident, NULL, &ip_lookup, &desc_lookup); + tt_mem_op(ip_lookup, OP_EQ, ip, sizeof(hs_service_intro_point_t)); + tt_mem_op(desc_lookup, OP_EQ, service->desc_current, + sizeof(hs_service_descriptor_t)); + /* Reset. */ + s_lookup = NULL; ip_lookup = NULL; desc_lookup = NULL; + + /* Break the ident and we should find nothing. */ + memset(&ident, 0, sizeof(ident)); + get_objects_from_ident(&ident, &s_lookup, &ip_lookup, &desc_lookup); + tt_ptr_op(s_lookup, OP_EQ, NULL); + tt_ptr_op(ip_lookup, OP_EQ, NULL); + tt_ptr_op(desc_lookup, OP_EQ, NULL); + } + + /* Testing get_node_from_intro_point() */ + { + const node_t *node = get_node_from_intro_point(ip); + tt_ptr_op(node, OP_EQ, &mock_node); + SMARTLIST_FOREACH_BEGIN(ip->base.link_specifiers, + hs_desc_link_specifier_t *, ls) { + if (ls->type == LS_LEGACY_ID) { + /* Change legacy id in link specifier which is not the mock node. */ + memset(ls->u.legacy_id, 'B', sizeof(ls->u.legacy_id)); + } + } SMARTLIST_FOREACH_END(ls); + node = get_node_from_intro_point(ip); + tt_ptr_op(node, OP_EQ, NULL); + } + + /* Testing can_service_launch_intro_circuit() */ + { + time_t now = time(NULL); + /* Put the start of the retry period back in time, we should be allowed. + * to launch intro circuit. */ + service->state.num_intro_circ_launched = 2; + service->state.intro_circ_retry_started_time = + (now - INTRO_CIRC_RETRY_PERIOD - 1); + ret = can_service_launch_intro_circuit(service, now); + tt_int_op(ret, OP_EQ, 1); + tt_u64_op(service->state.intro_circ_retry_started_time, OP_EQ, now); + tt_u64_op(service->state.num_intro_circ_launched, OP_EQ, 0); + /* Call it again, we should still be allowed because we are under + * MAX_INTRO_CIRCS_PER_PERIOD which been set to 0 previously. */ + ret = can_service_launch_intro_circuit(service, now); + tt_int_op(ret, OP_EQ, 1); + tt_u64_op(service->state.intro_circ_retry_started_time, OP_EQ, now); + tt_u64_op(service->state.num_intro_circ_launched, OP_EQ, 0); + /* Too many intro circuit launched means we are not allowed. */ + service->state.num_intro_circ_launched = 20; + ret = can_service_launch_intro_circuit(service, now); + tt_int_op(ret, OP_EQ, 0); + } + + /* Testing intro_point_should_expire(). */ + { + time_t now = time(NULL); + /* Just some basic test of the current state. */ + tt_u64_op(ip->introduce2_max, OP_GE, + INTRO_POINT_MIN_LIFETIME_INTRODUCTIONS); + tt_u64_op(ip->introduce2_max, OP_LE, + INTRO_POINT_MAX_LIFETIME_INTRODUCTIONS); + tt_u64_op(ip->time_to_expire, OP_GE, + now + INTRO_POINT_LIFETIME_MIN_SECONDS); + tt_u64_op(ip->time_to_expire, OP_LE, + now + INTRO_POINT_LIFETIME_MAX_SECONDS); + + /* This newly created IP from above shouldn't expire now. */ + ret = intro_point_should_expire(ip, now); + tt_int_op(ret, OP_EQ, 0); + /* Maximum number of INTRODUCE2 cell reached, it should expire. */ + ip->introduce2_count = INTRO_POINT_MAX_LIFETIME_INTRODUCTIONS + 1; + ret = intro_point_should_expire(ip, now); + tt_int_op(ret, OP_EQ, 1); + ip->introduce2_count = 0; + /* It should expire if time to expire has been reached. */ + ip->time_to_expire = now - 1000; + ret = intro_point_should_expire(ip, now); + tt_int_op(ret, OP_EQ, 1); + } + done: + /* This will free the service and all objects associated to it. */ + hs_service_free_all(); + UNMOCK(node_get_by_id); +} + +/** Test that we do the right operations when an intro circuit opens */ +static void +test_intro_circuit_opened(void *arg) +{ + int flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL; + hs_service_t *service; + origin_circuit_t *circ = NULL; + + (void) arg; + + hs_init(); + MOCK(circuit_mark_for_close_, mock_circuit_mark_for_close); + MOCK(relay_send_command_from_edge_, mock_relay_send_command_from_edge); + + circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO, + flags); + + /* No service associated with this circuit. */ setup_full_capture_of_logs(LOG_WARN); - /* Easiest way to make that function fail is to mock the - ed25519_sign_prefixed() function and make it fail. */ - cell = generate_establish_intro_cell(circuit_key_material, - sizeof(circuit_key_material)); - expect_log_msg_containing("Unable to gen signature for " - "ESTABLISH_INTRO cell."); + hs_service_circuit_has_opened(circ); + expect_log_msg_containing("Unknown service identity key"); + teardown_capture_of_logs(); + + /* Set a service for this circuit. */ + { + service = helper_create_service(); + ed25519_pubkey_copy(&circ->hs_ident->identity_pk, + &service->keys.identity_pk); + + /* No intro point associated with this circuit. */ + setup_full_capture_of_logs(LOG_WARN); + hs_service_circuit_has_opened(circ); + expect_log_msg_containing("Unknown introduction point auth key"); + teardown_capture_of_logs(); + } + + /* Set an IP object now for this circuit. */ + { + hs_service_intro_point_t *ip = helper_create_service_ip(); + service_intro_point_add(service->desc_current->intro_points.map, ip); + /* Update ident to contain the intro point auth key. */ + ed25519_pubkey_copy(&circ->hs_ident->intro_auth_pk, + &ip->auth_key_kp.pubkey); + } + + /* This one should go all the way. */ + setup_full_capture_of_logs(LOG_INFO); + hs_service_circuit_has_opened(circ); + expect_log_msg_containing("Introduction circuit 0 established for service"); teardown_capture_of_logs(); - tt_assert(!cell); done: - trn_cell_establish_intro_free(cell); - UNMOCK(ed25519_sign_prefixed); + circuit_free(TO_CIRCUIT(circ)); + hs_free_all(); + UNMOCK(circuit_mark_for_close_); + UNMOCK(relay_send_command_from_edge_); } -/** Test the HS ntor handshake. Simulate the sending of an encrypted INTRODUCE1 - * cell, and verify the proper derivation of decryption keys on the other end. - * Then simulate the sending of an authenticated RENDEZVOUS1 cell and verify - * the proper verification on the other end. */ +/** Test the operations we do on a circuit after we learn that we successfuly + * established an intro point on it */ static void -test_hs_ntor(void *arg) +test_intro_established(void *arg) { - int retval; + int ret; + int flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL; + uint8_t payload[RELAY_PAYLOAD_SIZE] = {0}; + origin_circuit_t *circ = NULL; + hs_service_t *service; + hs_service_intro_point_t *ip = NULL; - uint8_t subcredential[DIGEST256_LEN]; + (void) arg; - ed25519_keypair_t service_intro_auth_keypair; - curve25519_keypair_t service_intro_enc_keypair; - curve25519_keypair_t service_ephemeral_rend_keypair; + hs_init(); + MOCK(circuit_mark_for_close_, mock_circuit_mark_for_close); - curve25519_keypair_t client_ephemeral_enc_keypair; + circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO, + flags); + tt_assert(circ); - hs_ntor_intro_cell_keys_t client_hs_ntor_intro_cell_keys; - hs_ntor_intro_cell_keys_t service_hs_ntor_intro_cell_keys; + /* Test a wrong purpose. */ + TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_S_INTRO; + setup_full_capture_of_logs(LOG_WARN); + ret = hs_service_receive_intro_established(circ, payload, sizeof(payload)); + tt_int_op(ret, OP_EQ, -1); + expect_log_msg_containing("Received an INTRO_ESTABLISHED cell on a " + "non introduction circuit of purpose"); + teardown_capture_of_logs(); + + /* Back to normal. */ + TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_S_ESTABLISH_INTRO; + + /* No service associated to it. */ + setup_full_capture_of_logs(LOG_WARN); + ret = hs_service_receive_intro_established(circ, payload, sizeof(payload)); + tt_int_op(ret, OP_EQ, -1); + expect_log_msg_containing("Unknown service identity key"); + teardown_capture_of_logs(); + + /* Set a service for this circuit. */ + service = helper_create_service(); + ed25519_pubkey_copy(&circ->hs_ident->identity_pk, + &service->keys.identity_pk); + /* No introduction point associated to it. */ + setup_full_capture_of_logs(LOG_WARN); + ret = hs_service_receive_intro_established(circ, payload, sizeof(payload)); + tt_int_op(ret, OP_EQ, -1); + expect_log_msg_containing("Introduction circuit established without an " + "intro point object on circuit"); + teardown_capture_of_logs(); + + /* Set an IP object now for this circuit. */ + { + ip = helper_create_service_ip(); + service_intro_point_add(service->desc_current->intro_points.map, ip); + /* Update ident to contain the intro point auth key. */ + ed25519_pubkey_copy(&circ->hs_ident->intro_auth_pk, + &ip->auth_key_kp.pubkey); + } + + /* Send an empty payload. INTRO_ESTABLISHED cells are basically zeroes. */ + ret = hs_service_receive_intro_established(circ, payload, sizeof(payload)); + tt_int_op(ret, OP_EQ, 0); + tt_u64_op(ip->circuit_established, OP_EQ, 1); + tt_int_op(TO_CIRCUIT(circ)->purpose, OP_EQ, CIRCUIT_PURPOSE_S_INTRO); + + done: + if (circ) + circuit_free(TO_CIRCUIT(circ)); + hs_free_all(); + UNMOCK(circuit_mark_for_close_); +} - hs_ntor_rend_cell_keys_t service_hs_ntor_rend_cell_keys; - hs_ntor_rend_cell_keys_t client_hs_ntor_rend_cell_keys; +/** Check the operations we do on a rendezvous circuit after we learn it's + * open */ +static void +test_rdv_circuit_opened(void *arg) +{ + int flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL; + origin_circuit_t *circ = NULL; + hs_service_t *service; (void) arg; - /* Generate fake data for this unittest */ + hs_init(); + MOCK(circuit_mark_for_close_, mock_circuit_mark_for_close); + MOCK(relay_send_command_from_edge_, mock_relay_send_command_from_edge); + + circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_S_CONNECT_REND, flags); + crypto_rand((char *) circ->hs_ident->rendezvous_cookie, REND_COOKIE_LEN); + crypto_rand((char *) circ->hs_ident->rendezvous_handshake_info, + sizeof(circ->hs_ident->rendezvous_handshake_info)); + + /* No service associated with this circuit. */ + setup_full_capture_of_logs(LOG_WARN); + hs_service_circuit_has_opened(circ); + expect_log_msg_containing("Unknown service identity key"); + teardown_capture_of_logs(); + /* This should be set to a non zero timestamp. */ + tt_u64_op(TO_CIRCUIT(circ)->timestamp_dirty, OP_NE, 0); + + /* Set a service for this circuit. */ + service = helper_create_service(); + ed25519_pubkey_copy(&circ->hs_ident->identity_pk, + &service->keys.identity_pk); + /* Should be all good. */ + hs_service_circuit_has_opened(circ); + tt_int_op(TO_CIRCUIT(circ)->purpose, OP_EQ, CIRCUIT_PURPOSE_S_REND_JOINED); + + done: + circuit_free(TO_CIRCUIT(circ)); + hs_free_all(); + UNMOCK(circuit_mark_for_close_); + UNMOCK(relay_send_command_from_edge_); +} + +static void +mock_assert_circuit_ok(const circuit_t *c) +{ + (void) c; + return; +} + +/** Test for the general mechanism for closing intro circs. + * Also a way to identify that #23603 has been fixed. */ +static void +test_closing_intro_circs(void *arg) +{ + hs_service_t *service = NULL; + hs_service_intro_point_t *ip = NULL, *entry = NULL; + origin_circuit_t *intro_circ = NULL, *tmp_circ; + int flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL; + + (void) arg; + + MOCK(assert_circuit_ok, mock_assert_circuit_ok); + + hs_init(); + + /* Initialize service */ + service = helper_create_service(); + /* Initialize intro point */ + ip = helper_create_service_ip(); + tt_assert(ip); + service_intro_point_add(service->desc_current->intro_points.map, ip); + + /* Initialize intro circuit */ + intro_circ = origin_circuit_init(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO, flags); + intro_circ->hs_ident = hs_ident_circuit_new(&service->keys.identity_pk, + HS_IDENT_CIRCUIT_INTRO); + /* Register circuit in the circuitmap . */ + hs_circuitmap_register_intro_circ_v3_service_side(intro_circ, + &ip->auth_key_kp.pubkey); + tmp_circ = + hs_circuitmap_get_intro_circ_v3_service_side(&ip->auth_key_kp.pubkey); + tt_ptr_op(tmp_circ, OP_EQ, intro_circ); + + /* Pretend that intro point has failed too much */ + ip->circuit_retries = MAX_INTRO_POINT_CIRCUIT_RETRIES+1; + + /* Now pretend we are freeing this intro circuit. We want to see that our + * destructor is not gonna kill our intro point structure since that's the + * job of the cleanup routine. */ + circuit_free(TO_CIRCUIT(intro_circ)); + intro_circ = NULL; + entry = service_intro_point_find(service, &ip->auth_key_kp.pubkey); + tt_assert(entry); + /* The free should also remove the circuit from the circuitmap. */ + tmp_circ = + hs_circuitmap_get_intro_circ_v3_service_side(&ip->auth_key_kp.pubkey); + tt_assert(!tmp_circ); + + /* Now pretend that a new intro point circ was launched and opened. Check + * that the intro point will be established correctly. */ + intro_circ = origin_circuit_init(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO, flags); + intro_circ->hs_ident = hs_ident_circuit_new(&service->keys.identity_pk, + HS_IDENT_CIRCUIT_INTRO); + ed25519_pubkey_copy(&intro_circ->hs_ident->intro_auth_pk, + &ip->auth_key_kp.pubkey); + /* Register circuit in the circuitmap . */ + hs_circuitmap_register_intro_circ_v3_service_side(intro_circ, + &ip->auth_key_kp.pubkey); + tmp_circ = + hs_circuitmap_get_intro_circ_v3_service_side(&ip->auth_key_kp.pubkey); + tt_ptr_op(tmp_circ, OP_EQ, intro_circ); + tt_int_op(TO_CIRCUIT(intro_circ)->marked_for_close, OP_EQ, 0); + circuit_mark_for_close(TO_CIRCUIT(intro_circ), END_CIRC_REASON_INTERNAL); + tt_int_op(TO_CIRCUIT(intro_circ)->marked_for_close, OP_NE, 0); + /* At this point, we should not be able to find it in the circuitmap. */ + tmp_circ = + hs_circuitmap_get_intro_circ_v3_service_side(&ip->auth_key_kp.pubkey); + tt_assert(!tmp_circ); + + done: + if (intro_circ) { + circuit_free(TO_CIRCUIT(intro_circ)); + } + /* Frees the service object. */ + hs_free_all(); + UNMOCK(assert_circuit_ok); +} + +/** Test sending and receiving introduce2 cells */ +static void +test_introduce2(void *arg) +{ + int ret; + int flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL; + uint8_t payload[RELAY_PAYLOAD_SIZE] = {0}; + origin_circuit_t *circ = NULL; + hs_service_t *service; + hs_service_intro_point_t *ip = NULL; + + (void) arg; + + hs_init(); + MOCK(circuit_mark_for_close_, mock_circuit_mark_for_close); + MOCK(get_or_state, + get_or_state_replacement); + + dummy_state = tor_malloc_zero(sizeof(or_state_t)); + + circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_S_INTRO, flags); + tt_assert(circ); + + /* Test a wrong purpose. */ + TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_S_ESTABLISH_INTRO; + setup_full_capture_of_logs(LOG_WARN); + ret = hs_service_receive_introduce2(circ, payload, sizeof(payload)); + tt_int_op(ret, OP_EQ, -1); + expect_log_msg_containing("Received an INTRODUCE2 cell on a " + "non introduction circuit of purpose"); + teardown_capture_of_logs(); + + /* Back to normal. */ + TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_S_INTRO; + + /* No service associated to it. */ + setup_full_capture_of_logs(LOG_WARN); + ret = hs_service_receive_introduce2(circ, payload, sizeof(payload)); + tt_int_op(ret, OP_EQ, -1); + expect_log_msg_containing("Unknown service identity key"); + teardown_capture_of_logs(); + + /* Set a service for this circuit. */ + service = helper_create_service(); + ed25519_pubkey_copy(&circ->hs_ident->identity_pk, + &service->keys.identity_pk); + /* No introduction point associated to it. */ + setup_full_capture_of_logs(LOG_WARN); + ret = hs_service_receive_introduce2(circ, payload, sizeof(payload)); + tt_int_op(ret, OP_EQ, -1); + expect_log_msg_containing("Unknown introduction auth key when handling " + "an INTRODUCE2 cell on circuit"); + teardown_capture_of_logs(); + + /* Set an IP object now for this circuit. */ { - /* Generate fake subcredential */ - memset(subcredential, 'Z', DIGEST256_LEN); + ip = helper_create_service_ip(); + service_intro_point_add(service->desc_current->intro_points.map, ip); + /* Update ident to contain the intro point auth key. */ + ed25519_pubkey_copy(&circ->hs_ident->intro_auth_pk, + &ip->auth_key_kp.pubkey); + } + + /* This will fail because receiving an INTRODUCE2 cell implies a valid cell + * and then launching circuits so let's not do that and instead test that + * behaviour differently. */ + ret = hs_service_receive_introduce2(circ, payload, sizeof(payload)); + tt_int_op(ret, OP_EQ, -1); + tt_u64_op(ip->introduce2_count, OP_EQ, 0); + + done: + or_state_free(dummy_state); + dummy_state = NULL; + if (circ) + circuit_free(TO_CIRCUIT(circ)); + hs_free_all(); + UNMOCK(circuit_mark_for_close_); +} + +/** Test basic hidden service housekeeping operations (maintaining intro + * points, etc) */ +static void +test_service_event(void *arg) +{ + int flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL; + time_t now = time(NULL); + hs_service_t *service; + origin_circuit_t *circ = NULL; - /* service */ - curve25519_keypair_generate(&service_intro_enc_keypair, 0); - ed25519_keypair_generate(&service_intro_auth_keypair, 0); - curve25519_keypair_generate(&service_ephemeral_rend_keypair, 0); - /* client */ - curve25519_keypair_generate(&client_ephemeral_enc_keypair, 0); + (void) arg; + + hs_init(); + MOCK(circuit_mark_for_close_, mock_circuit_mark_for_close); + + circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_S_INTRO, flags); + + /* Set a service for this circuit. */ + service = helper_create_service(); + ed25519_pubkey_copy(&circ->hs_ident->identity_pk, + &service->keys.identity_pk); + + /* Currently this consists of cleaning invalid intro points. So adding IPs + * here that should get cleaned up. */ + { + hs_service_intro_point_t *ip = helper_create_service_ip(); + service_intro_point_add(service->desc_current->intro_points.map, ip); + /* This run will remove the IP because we have no circuits nor node_t + * associated with it. */ + run_housekeeping_event(now); + tt_int_op(digest256map_size(service->desc_current->intro_points.map), + OP_EQ, 0); + /* We'll trigger a removal because we've reached our maximum amount of + * times we should retry a circuit. For this, we need to have a node_t + * that matches the identity of this IP. */ + routerinfo_t ri; + memset(&ri, 0, sizeof(ri)); + ip = helper_create_service_ip(); + service_intro_point_add(service->desc_current->intro_points.map, ip); + memset(ri.cache_info.identity_digest, 'A', DIGEST_LEN); + /* This triggers a node_t creation. */ + tt_assert(nodelist_set_routerinfo(&ri, NULL)); + ip->circuit_retries = MAX_INTRO_POINT_CIRCUIT_RETRIES + 1; + run_housekeeping_event(now); + tt_int_op(digest256map_size(service->desc_current->intro_points.map), + OP_EQ, 0); + /* No removal but no circuit so this means the IP object will stay in the + * descriptor map so we can retry it. */ + ip = helper_create_service_ip(); + service_intro_point_add(service->desc_current->intro_points.map, ip); + ip->circuit_established = 1; /* We'll test that, it MUST be 0 after. */ + run_housekeeping_event(now); + tt_int_op(digest256map_size(service->desc_current->intro_points.map), + OP_EQ, 1); + /* Remove the IP object at once for the next test. */ + ip->circuit_retries = MAX_INTRO_POINT_CIRCUIT_RETRIES + 1; + run_housekeeping_event(now); + tt_int_op(digest256map_size(service->desc_current->intro_points.map), + OP_EQ, 0); + /* Now, we'll create an IP with a registered circuit. The IP object + * shouldn't go away. */ + ip = helper_create_service_ip(); + service_intro_point_add(service->desc_current->intro_points.map, ip); + ed25519_pubkey_copy(&circ->hs_ident->intro_auth_pk, + &ip->auth_key_kp.pubkey); + hs_circuitmap_register_intro_circ_v3_service_side( + circ, &ip->auth_key_kp.pubkey); + run_housekeeping_event(now); + tt_int_op(digest256map_size(service->desc_current->intro_points.map), + OP_EQ, 1); + /* We'll mangle the IP object to expire. */ + ip->time_to_expire = now; + run_housekeeping_event(now); + tt_int_op(digest256map_size(service->desc_current->intro_points.map), + OP_EQ, 0); } - /* Client: Simulate the sending of an encrypted INTRODUCE1 cell */ - retval = - hs_ntor_client_get_introduce1_keys(&service_intro_auth_keypair.pubkey, - &service_intro_enc_keypair.pubkey, - &client_ephemeral_enc_keypair, - subcredential, - &client_hs_ntor_intro_cell_keys); - tt_int_op(retval, ==, 0); + done: + hs_circuitmap_remove_circuit(TO_CIRCUIT(circ)); + circuit_free(TO_CIRCUIT(circ)); + hs_free_all(); + UNMOCK(circuit_mark_for_close_); +} - /* Service: Simulate the decryption of the received INTRODUCE1 */ - retval = - hs_ntor_service_get_introduce1_keys(&service_intro_auth_keypair.pubkey, - &service_intro_enc_keypair, - &client_ephemeral_enc_keypair.pubkey, - subcredential, - &service_hs_ntor_intro_cell_keys); - tt_int_op(retval, ==, 0); +/** Test that we rotate descriptors correctly. */ +static void +test_rotate_descriptors(void *arg) +{ + int ret; + time_t next_rotation_time, now = time(NULL); + hs_service_t *service; + hs_service_descriptor_t *desc_next; - /* Test that the INTRODUCE1 encryption/mac keys match! */ - tt_mem_op(client_hs_ntor_intro_cell_keys.enc_key, OP_EQ, - service_hs_ntor_intro_cell_keys.enc_key, - CIPHER256_KEY_LEN); - tt_mem_op(client_hs_ntor_intro_cell_keys.mac_key, OP_EQ, - service_hs_ntor_intro_cell_keys.mac_key, - DIGEST256_LEN); + (void) arg; + + dummy_state = tor_malloc_zero(sizeof(or_state_t)); + + hs_init(); + MOCK(get_or_state, get_or_state_replacement); + MOCK(circuit_mark_for_close_, mock_circuit_mark_for_close); + MOCK(networkstatus_get_live_consensus, + mock_networkstatus_get_live_consensus); + + /* Descriptor rotation happens with a consensus with a new SRV. */ + + ret = parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC", + &mock_ns.valid_after); + tt_int_op(ret, OP_EQ, 0); + ret = parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC", + &mock_ns.fresh_until); + tt_int_op(ret, OP_EQ, 0); + dirvote_recalculate_timing(get_options(), mock_ns.valid_after); - /* Service: Simulate creation of RENDEZVOUS1 key material. */ - retval = - hs_ntor_service_get_rendezvous1_keys(&service_intro_auth_keypair.pubkey, - &service_intro_enc_keypair, - &service_ephemeral_rend_keypair, - &client_ephemeral_enc_keypair.pubkey, - &service_hs_ntor_rend_cell_keys); - tt_int_op(retval, ==, 0); + /* Create a service with a default descriptor and state. It's added to the + * global map. */ + service = helper_create_service(); + service_descriptor_free(service->desc_current); + service->desc_current = NULL; + /* This triggers a build for both descriptors. The time now is only used in + * the descriptor certificate which is important to be now else the decoding + * will complain that the cert has expired if we use valid_after. */ + build_all_descriptors(now); + tt_assert(service->desc_current); + tt_assert(service->desc_next); - /* Client: Simulate the verification of a received RENDEZVOUS1 cell */ - retval = - hs_ntor_client_get_rendezvous1_keys(&service_intro_auth_keypair.pubkey, - &client_ephemeral_enc_keypair, - &service_intro_enc_keypair.pubkey, - &service_ephemeral_rend_keypair.pubkey, - &client_hs_ntor_rend_cell_keys); - tt_int_op(retval, ==, 0); + /* Tweak our service next rotation time so we can use a custom time. */ + service->state.next_rotation_time = next_rotation_time = + mock_ns.valid_after + (11 * 60 * 60); - /* Test that the RENDEZVOUS1 key material match! */ - tt_mem_op(client_hs_ntor_rend_cell_keys.rend_cell_auth_mac, OP_EQ, - service_hs_ntor_rend_cell_keys.rend_cell_auth_mac, - DIGEST256_LEN); - tt_mem_op(client_hs_ntor_rend_cell_keys.ntor_key_seed, OP_EQ, - service_hs_ntor_rend_cell_keys.ntor_key_seed, - DIGEST256_LEN); + /* Nothing should happen, we are not at a new SRV. Our next rotation time + * should be untouched. */ + rotate_all_descriptors(mock_ns.valid_after); + tt_u64_op(service->state.next_rotation_time, OP_EQ, next_rotation_time); + tt_assert(service->desc_current); + tt_assert(service->desc_next); + tt_u64_op(service->desc_current->time_period_num, OP_EQ, + hs_get_previous_time_period_num(0)); + tt_u64_op(service->desc_next->time_period_num, OP_EQ, + hs_get_time_period_num(0)); + /* Keep a reference so we can compare it after rotation to the current. */ + desc_next = service->desc_next; + + /* Going right after a new SRV. */ + ret = parse_rfc1123_time("Sat, 27 Oct 1985 01:00:00 UTC", + &mock_ns.valid_after); + tt_int_op(ret, OP_EQ, 0); + ret = parse_rfc1123_time("Sat, 27 Oct 1985 02:00:00 UTC", + &mock_ns.fresh_until); + tt_int_op(ret, OP_EQ, 0); + dirvote_recalculate_timing(get_options(), mock_ns.valid_after); + + /* Note down what to expect for the next rotation time which is 01:00 + 23h + * meaning 00:00:00. */ + next_rotation_time = mock_ns.valid_after + (23 * 60 * 60); + /* We should have our next rotation time modified, our current descriptor + * cleaned up and the next descriptor becoming the current. */ + rotate_all_descriptors(mock_ns.valid_after); + tt_u64_op(service->state.next_rotation_time, OP_EQ, next_rotation_time); + tt_mem_op(service->desc_current, OP_EQ, desc_next, sizeof(*desc_next)); + tt_assert(service->desc_next == NULL); + + /* A second time should do nothing. */ + rotate_all_descriptors(mock_ns.valid_after); + tt_u64_op(service->state.next_rotation_time, OP_EQ, next_rotation_time); + tt_mem_op(service->desc_current, OP_EQ, desc_next, sizeof(*desc_next)); + tt_assert(service->desc_next == NULL); + + build_all_descriptors(now); + tt_mem_op(service->desc_current, OP_EQ, desc_next, sizeof(*desc_next)); + tt_u64_op(service->desc_current->time_period_num, OP_EQ, + hs_get_time_period_num(0)); + tt_u64_op(service->desc_next->time_period_num, OP_EQ, + hs_get_next_time_period_num(0)); + tt_assert(service->desc_next); done: - ; + hs_free_all(); + UNMOCK(get_or_state); + UNMOCK(circuit_mark_for_close_); + UNMOCK(networkstatus_get_live_consensus); } -/** Test that our HS time period calculation functions work properly */ +/** Test building descriptors: picking intro points, setting up their link + * specifiers, etc. */ static void -test_time_period(void *arg) +test_build_update_descriptors(void *arg) { + int ret; + time_t now = time(NULL); + node_t *node; + hs_service_t *service; + hs_service_intro_point_t *ip_cur, *ip_next; + routerinfo_t ri; + (void) arg; - uint64_t tn; + + hs_init(); + + MOCK(get_or_state, + get_or_state_replacement); + MOCK(networkstatus_get_live_consensus, + mock_networkstatus_get_live_consensus); + + dummy_state = tor_malloc_zero(sizeof(or_state_t)); + + ret = parse_rfc1123_time("Sat, 26 Oct 1985 03:00:00 UTC", + &mock_ns.valid_after); + tt_int_op(ret, OP_EQ, 0); + ret = parse_rfc1123_time("Sat, 26 Oct 1985 04:00:00 UTC", + &mock_ns.fresh_until); + tt_int_op(ret, OP_EQ, 0); + dirvote_recalculate_timing(get_options(), mock_ns.valid_after); + + /* Create a service without a current descriptor to trigger a build. */ + service = helper_create_service(); + tt_assert(service); + /* Unfortunately, the helper creates a dummy descriptor so get rid of it. */ + service_descriptor_free(service->desc_current); + service->desc_current = NULL; + + /* We have a fresh service so this should trigger a build for both + * descriptors for specific time period that we'll test. */ + build_all_descriptors(now); + /* Check *current* descriptor. */ + tt_assert(service->desc_current); + tt_assert(service->desc_current->desc); + tt_assert(service->desc_current->intro_points.map); + /* The current time period is the one expected when starting at 03:00. */ + tt_u64_op(service->desc_current->time_period_num, OP_EQ, + hs_get_time_period_num(0)); + /* This should be untouched, the update descriptor process changes it. */ + tt_u64_op(service->desc_current->next_upload_time, OP_EQ, 0); + + /* Check *next* descriptor. */ + tt_assert(service->desc_next); + tt_assert(service->desc_next->desc); + tt_assert(service->desc_next->intro_points.map); + tt_assert(service->desc_current != service->desc_next); + tt_u64_op(service->desc_next->time_period_num, OP_EQ, + hs_get_next_time_period_num(0)); + /* This should be untouched, the update descriptor process changes it. */ + tt_u64_op(service->desc_next->next_upload_time, OP_EQ, 0); + + /* Time to test the update of those descriptors. At first, we have no node + * in the routerlist so this will find NO suitable node for the IPs. */ + setup_full_capture_of_logs(LOG_INFO); + update_all_descriptors(now); + expect_log_msg_containing("Unable to find a suitable node to be an " + "introduction point for service"); + teardown_capture_of_logs(); + tt_int_op(digest256map_size(service->desc_current->intro_points.map), + OP_EQ, 0); + tt_int_op(digest256map_size(service->desc_next->intro_points.map), + OP_EQ, 0); + + /* Now, we'll setup a node_t. */ + { + tor_addr_t ipv4_addr; + curve25519_secret_key_t curve25519_secret_key; + + memset(&ri, 0, sizeof(routerinfo_t)); + + tor_addr_parse(&ipv4_addr, "127.0.0.1"); + ri.addr = tor_addr_to_ipv4h(&ipv4_addr); + ri.or_port = 1337; + ri.purpose = ROUTER_PURPOSE_GENERAL; + /* Ugly yes but we never free the "ri" object so this just makes things + * easier. */ + ri.protocol_list = (char *) "HSDir=1-2 LinkAuth=3"; + ret = curve25519_secret_key_generate(&curve25519_secret_key, 0); + tt_int_op(ret, OP_EQ, 0); + ri.onion_curve25519_pkey = + tor_malloc_zero(sizeof(curve25519_public_key_t)); + ri.onion_pkey = crypto_pk_new(); + curve25519_public_key_generate(ri.onion_curve25519_pkey, + &curve25519_secret_key); + memset(ri.cache_info.identity_digest, 'A', DIGEST_LEN); + /* Setup ed25519 identity */ + ed25519_keypair_t kp1; + ed25519_keypair_generate(&kp1, 0); + ri.cache_info.signing_key_cert = tor_malloc_zero(sizeof(tor_cert_t)); + tt_assert(ri.cache_info.signing_key_cert); + ed25519_pubkey_copy(&ri.cache_info.signing_key_cert->signing_key, + &kp1.pubkey); + nodelist_set_routerinfo(&ri, NULL); + node = node_get_mutable_by_id(ri.cache_info.identity_digest); + tt_assert(node); + node->is_running = node->is_valid = node->is_fast = node->is_stable = 1; + } + + /* We expect to pick only one intro point from the node above. */ + setup_full_capture_of_logs(LOG_INFO); + update_all_descriptors(now); + tor_free(node->ri->onion_curve25519_pkey); /* Avoid memleak. */ + tor_free(node->ri->cache_info.signing_key_cert); + crypto_pk_free(node->ri->onion_pkey); + expect_log_msg_containing("just picked 1 intro points and wanted 3 for next " + "descriptor. It currently has 0 intro points. " + "Launching ESTABLISH_INTRO circuit shortly."); + teardown_capture_of_logs(); + tt_int_op(digest256map_size(service->desc_current->intro_points.map), + OP_EQ, 1); + tt_int_op(digest256map_size(service->desc_next->intro_points.map), + OP_EQ, 1); + /* Get the IP object. Because we don't have the auth key of the IP, we can't + * query it so get the first element in the map. */ + { + void *obj = NULL; + const uint8_t *key; + digest256map_iter_t *iter = + digest256map_iter_init(service->desc_current->intro_points.map); + digest256map_iter_get(iter, &key, &obj); + tt_assert(obj); + ip_cur = obj; + /* Get also the IP from the next descriptor. We'll make sure it's not the + * same object as in the current descriptor. */ + iter = digest256map_iter_init(service->desc_next->intro_points.map); + digest256map_iter_get(iter, &key, &obj); + tt_assert(obj); + ip_next = obj; + } + tt_mem_op(ip_cur, OP_NE, ip_next, sizeof(hs_desc_intro_point_t)); + + /* We won't test the service IP object because there is a specific test + * already for this but we'll make sure that the state is coherent.*/ + + /* Three link specifiers are mandatoy so make sure we do have them. */ + tt_int_op(smartlist_len(ip_cur->base.link_specifiers), OP_EQ, 3); + /* Make sure we have a valid encryption keypair generated when we pick an + * intro point in the update process. */ + tt_assert(!tor_mem_is_zero((char *) ip_cur->enc_key_kp.seckey.secret_key, + CURVE25519_SECKEY_LEN)); + tt_assert(!tor_mem_is_zero((char *) ip_cur->enc_key_kp.pubkey.public_key, + CURVE25519_PUBKEY_LEN)); + tt_u64_op(ip_cur->time_to_expire, OP_GE, now + + INTRO_POINT_LIFETIME_MIN_SECONDS); + tt_u64_op(ip_cur->time_to_expire, OP_LE, now + + INTRO_POINT_LIFETIME_MAX_SECONDS); + + /* Now, we will try to set up a service after a new time period has started + * and see if it behaves as expected. */ + + ret = parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC", + &mock_ns.valid_after); + tt_int_op(ret, OP_EQ, 0); + ret = parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC", + &mock_ns.fresh_until); + tt_int_op(ret, OP_EQ, 0); + + /* Create a service without a current descriptor to trigger a build. */ + service = helper_create_service(); + tt_assert(service); + /* Unfortunately, the helper creates a dummy descriptor so get rid of it. */ + service_descriptor_free(service->desc_current); + service->desc_current = NULL; + + /* We have a fresh service so this should trigger a build for both + * descriptors for specific time period that we'll test. */ + build_all_descriptors(now); + /* Check *current* descriptor. */ + tt_assert(service->desc_current); + tt_assert(service->desc_current->desc); + tt_assert(service->desc_current->intro_points.map); + /* This should be for the previous time period. */ + tt_u64_op(service->desc_current->time_period_num, OP_EQ, + hs_get_previous_time_period_num(0)); + /* This should be untouched, the update descriptor process changes it. */ + tt_u64_op(service->desc_current->next_upload_time, OP_EQ, 0); + + /* Check *next* descriptor. */ + tt_assert(service->desc_next); + tt_assert(service->desc_next->desc); + tt_assert(service->desc_next->intro_points.map); + tt_assert(service->desc_current != service->desc_next); + tt_u64_op(service->desc_next->time_period_num, OP_EQ, + hs_get_time_period_num(0)); + /* This should be untouched, the update descriptor process changes it. */ + tt_u64_op(service->desc_next->next_upload_time, OP_EQ, 0); + + /* Let's remove the next descriptor to simulate a rotation. */ + service_descriptor_free(service->desc_next); + service->desc_next = NULL; + + build_all_descriptors(now); + /* Check *next* descriptor. */ + tt_assert(service->desc_next); + tt_assert(service->desc_next->desc); + tt_assert(service->desc_next->intro_points.map); + tt_assert(service->desc_current != service->desc_next); + tt_u64_op(service->desc_next->time_period_num, OP_EQ, + hs_get_next_time_period_num(0)); + /* This should be untouched, the update descriptor process changes it. */ + tt_u64_op(service->desc_next->next_upload_time, OP_EQ, 0); + + done: + hs_free_all(); + nodelist_free_all(); +} + +static void +test_upload_descriptors(void *arg) +{ + int ret; + time_t now = time(NULL); + hs_service_t *service; + + (void) arg; + + hs_init(); + MOCK(get_or_state, + get_or_state_replacement); + MOCK(networkstatus_get_live_consensus, + mock_networkstatus_get_live_consensus); + + dummy_state = tor_malloc_zero(sizeof(or_state_t)); + + ret = parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC", + &mock_ns.valid_after); + tt_int_op(ret, OP_EQ, 0); + ret = parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC", + &mock_ns.fresh_until); + tt_int_op(ret, OP_EQ, 0); + + /* Create a service with no descriptor. It's added to the global map. */ + service = hs_service_new(get_options()); + tt_assert(service); + service->config.version = HS_VERSION_THREE; + ed25519_secret_key_generate(&service->keys.identity_sk, 0); + ed25519_public_key_generate(&service->keys.identity_pk, + &service->keys.identity_sk); + /* Register service to global map. */ + ret = register_service(get_hs_service_map(), service); + tt_int_op(ret, OP_EQ, 0); + /* But first, build our descriptor. */ + build_all_descriptors(now); + + /* Nothing should happen because we have 0 introduction circuit established + * and we want (by default) 3 intro points. */ + run_upload_descriptor_event(now); + /* If no upload happened, this should be untouched. */ + tt_u64_op(service->desc_current->next_upload_time, OP_EQ, 0); + /* We'll simulate that we've opened our intro point circuit and that we only + * want one intro point. */ + service->config.num_intro_points = 1; + + /* Set our next upload time after now which will skip the upload. */ + service->desc_current->next_upload_time = now + 1000; + run_upload_descriptor_event(now); + /* If no upload happened, this should be untouched. */ + tt_u64_op(service->desc_current->next_upload_time, OP_EQ, now + 1000); + + done: + hs_free_all(); + UNMOCK(get_or_state); +} + +/** Test the functions that save and load HS revision counters to state. */ +static void +test_revision_counter_state(void *arg) +{ + char *state_line_one = NULL; + char *state_line_two = NULL; + + hs_service_descriptor_t *desc_one = service_descriptor_new(); + hs_service_descriptor_t *desc_two = service_descriptor_new(); + + (void) arg; + + /* Prepare both descriptors */ + desc_one->desc->plaintext_data.revision_counter = 42; + desc_two->desc->plaintext_data.revision_counter = 240; + memset(&desc_one->blinded_kp.pubkey.pubkey, 66, + sizeof(desc_one->blinded_kp.pubkey.pubkey)); + memset(&desc_two->blinded_kp.pubkey.pubkey, 240, + sizeof(desc_one->blinded_kp.pubkey.pubkey)); + + /* Turn the descriptor rev counters into state lines */ + state_line_one = encode_desc_rev_counter_for_state(desc_one); + tt_str_op(state_line_one, OP_EQ, + "QkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkI 42"); + + state_line_two = encode_desc_rev_counter_for_state(desc_two); + tt_str_op(state_line_two, OP_EQ, + "8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PA 240"); + + /* Now let's test our state parsing function: */ + int service_found; + uint64_t cached_rev_counter; + + /* First's try with wrong pubkey and check that no service was found */ + cached_rev_counter =check_state_line_for_service_rev_counter(state_line_one, + &desc_two->blinded_kp.pubkey, + &service_found); + tt_int_op(service_found, OP_EQ, 0); + tt_u64_op(cached_rev_counter, OP_EQ, 0); + + /* Now let's try with the right pubkeys */ + cached_rev_counter =check_state_line_for_service_rev_counter(state_line_one, + &desc_one->blinded_kp.pubkey, + &service_found); + tt_int_op(service_found, OP_EQ, 1); + tt_u64_op(cached_rev_counter, OP_EQ, 42); + + cached_rev_counter =check_state_line_for_service_rev_counter(state_line_two, + &desc_two->blinded_kp.pubkey, + &service_found); + tt_int_op(service_found, OP_EQ, 1); + tt_u64_op(cached_rev_counter, OP_EQ, 240); + + done: + tor_free(state_line_one); + tor_free(state_line_two); + service_descriptor_free(desc_one); + service_descriptor_free(desc_two); +} + +/** Global vars used by test_rendezvous1_parsing() */ +static char rend1_payload[RELAY_PAYLOAD_SIZE]; +static size_t rend1_payload_len = 0; + +/** Mock for relay_send_command_from_edge() to send a RENDEZVOUS1 cell. Instead + * of sending it to the network, instead save it to the global `rend1_payload` + * variable so that we can inspect it in the test_rendezvous1_parsing() + * test. */ +static int +mock_relay_send_rendezvous1(streamid_t stream_id, circuit_t *circ, + uint8_t relay_command, const char *payload, + size_t payload_len, + crypt_path_t *cpath_layer, + const char *filename, int lineno) +{ + (void) stream_id; + (void) circ; + (void) relay_command; + (void) cpath_layer; + (void) filename; + (void) lineno; + + memcpy(rend1_payload, payload, payload_len); + rend1_payload_len = payload_len; + + return 0; +} + +/** Send a RENDEZVOUS1 as a service, and parse it as a client. */ +static void +test_rendezvous1_parsing(void *arg) +{ int retval; - time_t fake_time; + static const char *test_addr = + "4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad.onion"; + hs_service_t *service = NULL; + origin_circuit_t *service_circ = NULL; + origin_circuit_t *client_circ = NULL; + ed25519_keypair_t ip_auth_kp; + curve25519_keypair_t ephemeral_kp; + curve25519_keypair_t client_kp; + curve25519_keypair_t ip_enc_kp; + int flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL; - /* Let's do the example in prop224 section [TIME-PERIODS] */ - retval = parse_rfc1123_time("Wed, 13 Apr 2016 11:00:00 UTC", - &fake_time); - tt_int_op(retval, ==, 0); + (void) arg; - /* Check that the time period number is right */ - tn = get_time_period_num(fake_time); - tt_u64_op(tn, ==, 16903); + MOCK(relay_send_command_from_edge_, mock_relay_send_rendezvous1); - /* Increase current time to 11:59:59 UTC and check that the time period - number is still the same */ - fake_time += 3599; - tn = get_time_period_num(fake_time); - tt_u64_op(tn, ==, 16903); + { + /* Let's start by setting up the service that will start the rend */ + service = tor_malloc_zero(sizeof(hs_service_t)); + ed25519_secret_key_generate(&service->keys.identity_sk, 0); + ed25519_public_key_generate(&service->keys.identity_pk, + &service->keys.identity_sk); + memcpy(service->onion_address, test_addr, sizeof(service->onion_address)); + tt_assert(service); + } + + { + /* Now let's set up the service rendezvous circuit and its keys. */ + service_circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_S_CONNECT_REND, + flags); + tor_free(service_circ->hs_ident); + hs_ntor_rend_cell_keys_t hs_ntor_rend_cell_keys; + uint8_t rendezvous_cookie[HS_REND_COOKIE_LEN]; + curve25519_keypair_generate(&ip_enc_kp, 0); + curve25519_keypair_generate(&ephemeral_kp, 0); + curve25519_keypair_generate(&client_kp, 0); + ed25519_keypair_generate(&ip_auth_kp, 0); + retval = hs_ntor_service_get_rendezvous1_keys(&ip_auth_kp.pubkey, + &ip_enc_kp, + &ephemeral_kp, + &client_kp.pubkey, + &hs_ntor_rend_cell_keys); + tt_int_op(retval, OP_EQ, 0); + + memset(rendezvous_cookie, 2, sizeof(rendezvous_cookie)); + service_circ->hs_ident = + create_rp_circuit_identifier(service, rendezvous_cookie, + &ephemeral_kp.pubkey, + &hs_ntor_rend_cell_keys); + } - /* Now take time to 12:00:00 UTC and check that the time period rotated */ - fake_time += 1; - tn = get_time_period_num(fake_time); - tt_u64_op(tn, ==, 16904); + /* Send out the RENDEZVOUS1 and make sure that our mock func worked */ + tt_assert(tor_mem_is_zero(rend1_payload, 32)); + hs_circ_service_rp_has_opened(service, service_circ); + tt_assert(!tor_mem_is_zero(rend1_payload, 32)); + tt_int_op(rend1_payload_len, OP_EQ, HS_LEGACY_RENDEZVOUS_CELL_SIZE); - /* Now also check our hs_get_next_time_period_num() function */ - tn = hs_get_next_time_period_num(fake_time); - tt_u64_op(tn, ==, 16905); + /******************************/ + + /** Now let's create the client rendezvous circuit */ + client_circ = + helper_create_origin_circuit(CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED, + flags); + /* fix up its circ ident */ + ed25519_pubkey_copy(&client_circ->hs_ident->intro_auth_pk, + &ip_auth_kp.pubkey); + memcpy(&client_circ->hs_ident->rendezvous_client_kp, + &client_kp, sizeof(client_circ->hs_ident->rendezvous_client_kp)); + memcpy(&client_circ->hs_ident->intro_enc_pk.public_key, + &ip_enc_kp.pubkey.public_key, + sizeof(client_circ->hs_ident->intro_enc_pk.public_key)); + + /* Now parse the rendezvous2 circuit and make sure it was fine. We are + * skipping 20 bytes off its payload, since that's the rendezvous cookie + * which is only present in REND1. */ + retval = handle_rendezvous2(client_circ, + (uint8_t*)rend1_payload+20, + rend1_payload_len-20); + tt_int_op(retval, OP_EQ, 0); + + /* TODO: We are only simulating client/service here. We could also simulate + * the rendezvous point by plugging in rend_mid_establish_rendezvous(). We + * would need an extra circuit and some more stuff but it's doable. */ done: - ; + circuit_free(TO_CIRCUIT(service_circ)); + circuit_free(TO_CIRCUIT(client_circ)); + hs_service_free(service); + hs_free_all(); + UNMOCK(relay_send_command_from_edge_); } struct testcase_t hs_service_tests[] = { - { "gen_establish_intro_cell", test_gen_establish_intro_cell, TT_FORK, + { "e2e_rend_circuit_setup", test_e2e_rend_circuit_setup, TT_FORK, + NULL, NULL }, + { "load_keys", test_load_keys, TT_FORK, + NULL, NULL }, + { "access_service", test_access_service, TT_FORK, + NULL, NULL }, + { "service_intro_point", test_service_intro_point, TT_FORK, + NULL, NULL }, + { "helper_functions", test_helper_functions, TT_FORK, + NULL, NULL }, + { "intro_circuit_opened", test_intro_circuit_opened, TT_FORK, + NULL, NULL }, + { "intro_established", test_intro_established, TT_FORK, + NULL, NULL }, + { "closing_intro_circs", test_closing_intro_circs, TT_FORK, + NULL, NULL }, + { "rdv_circuit_opened", test_rdv_circuit_opened, TT_FORK, + NULL, NULL }, + { "introduce2", test_introduce2, TT_FORK, + NULL, NULL }, + { "service_event", test_service_event, TT_FORK, + NULL, NULL }, + { "rotate_descriptors", test_rotate_descriptors, TT_FORK, + NULL, NULL }, + { "build_update_descriptors", test_build_update_descriptors, TT_FORK, NULL, NULL }, - { "gen_establish_intro_cell_bad", test_gen_establish_intro_cell_bad, TT_FORK, + { "upload_descriptors", test_upload_descriptors, TT_FORK, NULL, NULL }, - { "hs_ntor", test_hs_ntor, TT_FORK, + { "revision_counter_state", test_revision_counter_state, TT_FORK, NULL, NULL }, - { "time_period", test_time_period, TT_FORK, + { "rendezvous1_parsing", test_rendezvous1_parsing, TT_FORK, NULL, NULL }, END_OF_TESTCASES diff --git a/src/test/test_introduce.c b/src/test/test_introduce.c index cfb8d83b1d..d502bdddb1 100644 --- a/src/test/test_introduce.c +++ b/src/test/test_introduce.c @@ -307,7 +307,7 @@ do_parse_test(uint8_t *plaintext, size_t plaintext_len, int phase) /* Do early parsing */ parsed_req = rend_service_begin_parse_intro(cell, cell_len, 2, &err_msg); tt_assert(parsed_req); - tt_assert(!err_msg); + tt_ptr_op(err_msg, OP_EQ, NULL); tt_mem_op(parsed_req->pk,OP_EQ, digest, DIGEST_LEN); tt_assert(parsed_req->ciphertext); tt_assert(parsed_req->ciphertext_len > 0); @@ -318,7 +318,7 @@ do_parse_test(uint8_t *plaintext, size_t plaintext_len, int phase) /* Do decryption */ r = rend_service_decrypt_intro(parsed_req, k, &err_msg); tt_assert(!r); - tt_assert(!err_msg); + tt_ptr_op(err_msg, OP_EQ, NULL); tt_assert(parsed_req->plaintext); tt_assert(parsed_req->plaintext_len > 0); @@ -328,7 +328,7 @@ do_parse_test(uint8_t *plaintext, size_t plaintext_len, int phase) /* Do late parsing */ r = rend_service_parse_intro_plaintext(parsed_req, &err_msg); tt_assert(!r); - tt_assert(!err_msg); + tt_ptr_op(err_msg, OP_EQ, NULL); tt_assert(parsed_req->parsed); done: @@ -355,7 +355,7 @@ make_intro_from_plaintext( /* * Figure out an upper bound on how big the ciphertext will be - * (see crypto_pk_public_hybrid_encrypt()) + * (see crypto_pk_obsolete_public_hybrid_encrypt()) */ ciphertext_size = PKCS1_OAEP_PADDING_OVERHEAD; ciphertext_size += crypto_pk_keysize(key); @@ -372,7 +372,7 @@ make_intro_from_plaintext( tt_assert(r >= 0); /* Do encryption */ - r = crypto_pk_public_hybrid_encrypt( + r = crypto_pk_obsolete_public_hybrid_encrypt( key, cell + DIGEST_LEN, ciphertext_size, buf, len, PK_PKCS1_OAEP_PADDING, 0); diff --git a/src/test/test_key_expiration.sh b/src/test/test_key_expiration.sh new file mode 100755 index 0000000000..5511dbf18c --- /dev/null +++ b/src/test/test_key_expiration.sh @@ -0,0 +1,129 @@ +#!/bin/sh + +# Note: some of this code is lifted from zero_length_keys.sh and +# test_keygen.sh, and could be unified. + +umask 077 +set -e + +if [ $# -eq 0 ] || [ ! -f ${1} ] || [ ! -x ${1} ]; then + if [ "$TESTING_TOR_BINARY" = "" ] ; then + echo "Usage: ${0} PATH_TO_TOR [case-number]" + exit 1 + fi +fi + +if [ $# -ge 1 ]; then + TOR_BINARY="${1}" + shift +else + TOR_BINARY="${TESTING_TOR_BINARY}" +fi + +if [ $# -ge 1 ]; then + dflt=0 +else + dflt=1 +fi + +CASE1=$dflt +CASE2=$dflt +CASE3=$dflt + +if [ $# -ge 1 ]; then + eval "CASE${1}"=1 +fi + + +dump() { xxd -p "$1" | tr -d '\n '; } +die() { echo "$1" >&2 ; exit 5; } +check_dir() { [ -d "$1" ] || die "$1 did not exist"; } +check_file() { [ -e "$1" ] || die "$1 did not exist"; } +check_no_file() { [ -e "$1" ] && die "$1 was not supposed to exist" || true; } +check_files_eq() { cmp "$1" "$2" || die "$1 and $2 did not match: `dump $1` vs `dump $2`"; } +check_keys_eq() { check_files_eq "${SRC}/keys/${1}" "${ME}/keys/${1}"; } + +DATA_DIR=`mktemp -d -t tor_key_expiration_tests.XXXXXX` +if [ -z "$DATA_DIR" ]; then + echo "Failure: mktemp invocation returned empty string" >&2 + exit 3 +fi +if [ ! -d "$DATA_DIR" ]; then + echo "Failure: mktemp invocation result doesn't point to directory" >&2 + exit 3 +fi +trap "rm -rf '$DATA_DIR'" 0 + +# Use an absolute path for this or Tor will complain +DATA_DIR=`cd "${DATA_DIR}" && pwd` + +touch "${DATA_DIR}/empty_torrc" + +QUIETLY="--hush" +SILENTLY="--quiet" +TOR="${TOR_BINARY} --DisableNetwork 1 --ShutdownWaitLength 0 --ORPort 12345 --ExitRelay 0 -f ${DATA_DIR}/empty_torrc --DataDirectory ${DATA_DIR}" + +##### SETUP +# +# Here we create a set of keys. + +# Step 1: Start Tor with --list-fingerprint --quiet. Make sure everything is there. +echo "Setup step #1" +${TOR} --list-fingerprint ${SILENTLY} > /dev/null + +check_dir "${DATA_DIR}/keys" +check_file "${DATA_DIR}/keys/ed25519_master_id_public_key" +check_file "${DATA_DIR}/keys/ed25519_master_id_secret_key" +check_file "${DATA_DIR}/keys/ed25519_signing_cert" +check_file "${DATA_DIR}/keys/ed25519_signing_secret_key" +check_file "${DATA_DIR}/keys/secret_id_key" +check_file "${DATA_DIR}/keys/secret_onion_key" +check_file "${DATA_DIR}/keys/secret_onion_key_ntor" + +##### TEST CASES + +echo "=== Starting key expiration tests." + +FN="${DATA_DIR}/stderr" + +if [ "$CASE1" = 1 ]; then + echo "==== Case 1: Test --key-expiration without argument and ensure usage" + echo " instructions are printed." + + ${TOR} ${QUIETLY} --key-expiration 2>"$FN" || true + grep "No valid argument to --key-expiration found!" "$FN" >/dev/null || \ + die "Tor didn't mention supported --key-expiration argmuents" + + echo "==== Case 1: ok" +fi + +if [ "$CASE2" = 1 ]; then + echo "==== Case 2: Start Tor with --key-expiration 'sign' and make sure it prints an expiration." + + ${TOR} ${QUIETLY} --key-expiration sign 2>"$FN" + grep "signing-cert-expiry:" "$FN" >/dev/null || \ + die "Tor didn't print an expiration" + + echo "==== Case 2: ok" +fi + +if [ "$CASE3" = 1 ]; then + echo "==== Case 3: Start Tor with --key-expiration 'sign', when there is no" + echo " signing key, and make sure that Tor generates a new key" + echo " and prints its certificate's expiration." + + mv "${DATA_DIR}/keys/ed25519_signing_cert" \ + "${DATA_DIR}/keys/ed25519_signing_cert.bak" + + ${TOR} --key-expiration sign > "$FN" 2>&1 + grep "It looks like I need to generate and sign a new medium-term signing key" "$FN" >/dev/null || \ + die "Tor didn't create a new signing key" + check_file "${DATA_DIR}/keys/ed25519_signing_cert" + grep "signing-cert-expiry:" "$FN" >/dev/null || \ + die "Tor didn't print an expiration" + + mv "${DATA_DIR}/keys/ed25519_signing_cert.bak" \ + "${DATA_DIR}/keys/ed25519_signing_cert" + + echo "==== Case 3: ok" +fi diff --git a/src/test/test_keypin.c b/src/test/test_keypin.c index d2ec8e9ca7..79d7bac902 100644 --- a/src/test/test_keypin.c +++ b/src/test/test_keypin.c @@ -20,8 +20,8 @@ test_keypin_parse_line(void *arg) "aGVyZSBpcyBhIGdvb2Qgc2hhMSE " "VGhpcyBlZDI1NTE5IHNjb2ZmcyBhdCB0aGUgc2hhMS4"); tt_assert(ent); - tt_mem_op(ent->rsa_id, ==, "here is a good sha1!", 20); - tt_mem_op(ent->ed25519_key, ==, "This ed25519 scoffs at the sha1.", 32); + tt_mem_op(ent->rsa_id, OP_EQ, "here is a good sha1!", 20); + tt_mem_op(ent->ed25519_key, OP_EQ, "This ed25519 scoffs at the sha1.", 32); tor_free(ent); ent = NULL; /* Good line with extra stuff we will ignore. */ @@ -29,27 +29,27 @@ test_keypin_parse_line(void *arg) "aGVyZSBpcyBhIGdvb2Qgc2hhMSE " "VGhpcyBlZDI1NTE5IHNjb2ZmcyBhdCB0aGUgc2hhMS4helloworld"); tt_assert(ent); - tt_mem_op(ent->rsa_id, ==, "here is a good sha1!", 20); - tt_mem_op(ent->ed25519_key, ==, "This ed25519 scoffs at the sha1.", 32); + tt_mem_op(ent->rsa_id, OP_EQ, "here is a good sha1!", 20); + tt_mem_op(ent->ed25519_key, OP_EQ, "This ed25519 scoffs at the sha1.", 32); tor_free(ent); ent = NULL; /* Bad line: no space in the middle. */ ent = keypin_parse_journal_line( "aGVyZSBpcyBhIGdvb2Qgc2hhMSE?" "VGhpcyBlZDI1NTE5IHNjb2ZmcyBhdCB0aGUgc2hhMS4"); - tt_assert(! ent); + tt_ptr_op(ent, OP_EQ, NULL); /* Bad line: bad base64 in RSA ID */ ent = keypin_parse_journal_line( "aGVyZSBpcyBhIGdv!2Qgc2hhMSE " "VGhpcyBlZDI1NTE5IHNjb2ZmcyBhdCB0aGUgc2hhMS4"); - tt_assert(! ent); + tt_ptr_op(ent, OP_EQ, NULL); /* Bad line: bad base64 in Ed25519 */ ent = keypin_parse_journal_line( "aGVyZSBpcyBhIGdvb2Qgc2hhMSE " "VGhpcyBlZDI1NTE5IHNjb2ZmcyB!dCB0aGUgc2hhMS4"); - tt_assert(! ent); + tt_ptr_op(ent, OP_EQ, NULL); done: tor_free(ent); @@ -82,11 +82,11 @@ test_keypin_parse_file(void *arg) "Z2dsZSBpbiBzd29tZWVzd2FucyA aW4gdm9sdXB0YXRlIGF4ZS1oYWNrZXIgZXNzZSByaXA\n" "cHVsdXMgY3J1bW1paSBldSBtb28 ZiBudWxsYSBzbnV2di5QTFVHSFBMT1ZFUlhZWlpZLi4\n"; - tt_int_op(0, ==, keypin_load_journal_impl(data1, strlen(data1))); - tt_int_op(8, ==, smartlist_len(mock_addent_got)); + tt_int_op(0, OP_EQ, keypin_load_journal_impl(data1, strlen(data1))); + tt_int_op(8, OP_EQ, smartlist_len(mock_addent_got)); keypin_ent_t *ent = smartlist_get(mock_addent_got, 2); - tt_mem_op(ent->rsa_id, ==, "r lerkim, sed do bar", 20); - tt_mem_op(ent->ed25519_key, ==, "baloot tempor gluppitus ut labor", 32); + tt_mem_op(ent->rsa_id, OP_EQ, "r lerkim, sed do bar", 20); + tt_mem_op(ent->ed25519_key, OP_EQ, "baloot tempor gluppitus ut labor", 32); /* More complex example: weird lines, bogus lines, duplicate/conflicting lines */ @@ -107,24 +107,25 @@ test_keypin_parse_file(void *arg) "ZHMgc3BlYWsgdHJ1dGgsIGFuZCA aXQgd2FzIHRydaUgdGhhdCBhbGwgdGhlIG1hc3Rlcgo\n" ; - tt_int_op(0, ==, keypin_load_journal_impl(data2, strlen(data2))); - tt_int_op(13, ==, smartlist_len(mock_addent_got)); + tt_int_op(0, OP_EQ, keypin_load_journal_impl(data2, strlen(data2))); + tt_int_op(13, OP_EQ, smartlist_len(mock_addent_got)); ent = smartlist_get(mock_addent_got, 9); - tt_mem_op(ent->rsa_id, ==, "\"You have made a goo", 20); - tt_mem_op(ent->ed25519_key, ==, "d beginning.\" But no more. Wizar", 32); + tt_mem_op(ent->rsa_id, OP_EQ, "\"You have made a goo", 20); + tt_mem_op(ent->ed25519_key, OP_EQ, "d beginning.\" But no more. Wizar", 32); ent = smartlist_get(mock_addent_got, 12); - tt_mem_op(ent->rsa_id, ==, "ds speak truth, and ", 20); - tt_mem_op(ent->ed25519_key, ==, "it was tru\xa5 that all the master\n", 32); + tt_mem_op(ent->rsa_id, OP_EQ, "ds speak truth, and ", 20); + tt_mem_op(ent->ed25519_key, OP_EQ, + "it was tru\xa5 that all the master\n", 32); /* File truncated before NL */ const char data3[] = "Tm8gZHJhZ29uIGNhbiByZXNpc3Q IHRoZSBmYXNjaW5hdGlvbiBvZiByaWRkbGluZyB0YWw"; - tt_int_op(0, ==, keypin_load_journal_impl(data3, strlen(data3))); - tt_int_op(14, ==, smartlist_len(mock_addent_got)); + tt_int_op(0, OP_EQ, keypin_load_journal_impl(data3, strlen(data3))); + tt_int_op(14, OP_EQ, smartlist_len(mock_addent_got)); ent = smartlist_get(mock_addent_got, 13); - tt_mem_op(ent->rsa_id, ==, "No dragon can resist", 20); - tt_mem_op(ent->ed25519_key, ==, " the fascination of riddling tal", 32); + tt_mem_op(ent->rsa_id, OP_EQ, "No dragon can resist", 20); + tt_mem_op(ent->ed25519_key, OP_EQ, " the fascination of riddling tal", 32); done: keypin_clear(); @@ -141,32 +142,32 @@ test_keypin_add_entry(void *arg) (void)arg; keypin_clear(); - tt_int_op(KEYPIN_ADDED, ==, ADD("ambassadors-at-large", + tt_int_op(KEYPIN_ADDED, OP_EQ, ADD("ambassadors-at-large", "bread-and-butter thing-in-itself")); - tt_int_op(KEYPIN_ADDED, ==, ADD("gentleman-adventurer", + tt_int_op(KEYPIN_ADDED, OP_EQ, ADD("gentleman-adventurer", "cloak-and-dagger what's-his-face")); - tt_int_op(KEYPIN_FOUND, ==, ADD("ambassadors-at-large", + tt_int_op(KEYPIN_FOUND, OP_EQ, ADD("ambassadors-at-large", "bread-and-butter thing-in-itself")); - tt_int_op(KEYPIN_FOUND, ==, ADD("ambassadors-at-large", + tt_int_op(KEYPIN_FOUND, OP_EQ, ADD("ambassadors-at-large", "bread-and-butter thing-in-itself")); - tt_int_op(KEYPIN_FOUND, ==, ADD("gentleman-adventurer", + tt_int_op(KEYPIN_FOUND, OP_EQ, ADD("gentleman-adventurer", "cloak-and-dagger what's-his-face")); - tt_int_op(KEYPIN_ADDED, ==, ADD("Johnnies-come-lately", + tt_int_op(KEYPIN_ADDED, OP_EQ, ADD("Johnnies-come-lately", "run-of-the-mill root-mean-square")); - tt_int_op(KEYPIN_MISMATCH, ==, ADD("gentleman-adventurer", + tt_int_op(KEYPIN_MISMATCH, OP_EQ, ADD("gentleman-adventurer", "hypersentimental closefistedness")); - tt_int_op(KEYPIN_MISMATCH, ==, ADD("disestablismentarian", + tt_int_op(KEYPIN_MISMATCH, OP_EQ, ADD("disestablismentarian", "cloak-and-dagger what's-his-face")); - tt_int_op(KEYPIN_FOUND, ==, ADD("gentleman-adventurer", + tt_int_op(KEYPIN_FOUND, OP_EQ, ADD("gentleman-adventurer", "cloak-and-dagger what's-his-face")); - tt_int_op(KEYPIN_NOT_FOUND, ==, LONE_RSA("Llanfairpwllgwyngyll")); - tt_int_op(KEYPIN_MISMATCH, ==, LONE_RSA("Johnnies-come-lately")); + tt_int_op(KEYPIN_NOT_FOUND, OP_EQ, LONE_RSA("Llanfairpwllgwyngyll")); + tt_int_op(KEYPIN_MISMATCH, OP_EQ, LONE_RSA("Johnnies-come-lately")); done: keypin_clear(); @@ -179,51 +180,51 @@ test_keypin_journal(void *arg) char *contents = NULL; const char *fname = get_fname("keypin-journal"); - tt_int_op(0, ==, keypin_load_journal(fname)); /* ENOENT is okay */ + tt_int_op(0, OP_EQ, keypin_load_journal(fname)); /* ENOENT is okay */ update_approx_time(1217709000); - tt_int_op(0, ==, keypin_open_journal(fname)); + tt_int_op(0, OP_EQ, keypin_open_journal(fname)); - tt_int_op(KEYPIN_ADDED, ==, ADD("king-of-the-herrings", + tt_int_op(KEYPIN_ADDED, OP_EQ, ADD("king-of-the-herrings", "good-for-nothing attorney-at-law")); - tt_int_op(KEYPIN_ADDED, ==, ADD("yellowish-red-yellow", + tt_int_op(KEYPIN_ADDED, OP_EQ, ADD("yellowish-red-yellow", "salt-and-pepper high-muck-a-muck")); - tt_int_op(KEYPIN_FOUND, ==, ADD("yellowish-red-yellow", + tt_int_op(KEYPIN_FOUND, OP_EQ, ADD("yellowish-red-yellow", "salt-and-pepper high-muck-a-muck")); keypin_close_journal(); keypin_clear(); - tt_int_op(0, ==, keypin_load_journal(fname)); + tt_int_op(0, OP_EQ, keypin_load_journal(fname)); update_approx_time(1231041600); - tt_int_op(0, ==, keypin_open_journal(fname)); - tt_int_op(KEYPIN_FOUND, ==, ADD("yellowish-red-yellow", + tt_int_op(0, OP_EQ, keypin_open_journal(fname)); + tt_int_op(KEYPIN_FOUND, OP_EQ, ADD("yellowish-red-yellow", "salt-and-pepper high-muck-a-muck")); - tt_int_op(KEYPIN_ADDED, ==, ADD("theatre-in-the-round", + tt_int_op(KEYPIN_ADDED, OP_EQ, ADD("theatre-in-the-round", "holier-than-thou jack-in-the-box")); - tt_int_op(KEYPIN_ADDED, ==, ADD("no-deposit-no-return", + tt_int_op(KEYPIN_ADDED, OP_EQ, ADD("no-deposit-no-return", "across-the-board will-o-the-wisp")); - tt_int_op(KEYPIN_MISMATCH, ==, ADD("intellectualizations", + tt_int_op(KEYPIN_MISMATCH, OP_EQ, ADD("intellectualizations", "salt-and-pepper high-muck-a-muck")); keypin_close_journal(); keypin_clear(); - tt_int_op(0, ==, keypin_load_journal(fname)); + tt_int_op(0, OP_EQ, keypin_load_journal(fname)); update_approx_time(1412278354); - tt_int_op(0, ==, keypin_open_journal(fname)); - tt_int_op(KEYPIN_FOUND, ==, ADD("yellowish-red-yellow", + tt_int_op(0, OP_EQ, keypin_open_journal(fname)); + tt_int_op(KEYPIN_FOUND, OP_EQ, ADD("yellowish-red-yellow", "salt-and-pepper high-muck-a-muck")); - tt_int_op(KEYPIN_MISMATCH, ==, ADD("intellectualizations", + tt_int_op(KEYPIN_MISMATCH, OP_EQ, ADD("intellectualizations", "salt-and-pepper high-muck-a-muck")); - tt_int_op(KEYPIN_FOUND, ==, ADD("theatre-in-the-round", + tt_int_op(KEYPIN_FOUND, OP_EQ, ADD("theatre-in-the-round", "holier-than-thou jack-in-the-box")); - tt_int_op(KEYPIN_MISMATCH, ==, ADD("counterrevolutionary", + tt_int_op(KEYPIN_MISMATCH, OP_EQ, ADD("counterrevolutionary", "holier-than-thou jack-in-the-box")); - tt_int_op(KEYPIN_MISMATCH, ==, ADD("no-deposit-no-return", + tt_int_op(KEYPIN_MISMATCH, OP_EQ, ADD("no-deposit-no-return", "floccinaucinihilipilificationism")); keypin_close_journal(); contents = read_file_to_str(fname, RFTS_BIN, NULL); tt_assert(contents); - tt_str_op(contents,==, + tt_str_op(contents,OP_EQ, "\n" "@opened-at 2008-08-02 20:30:00\n" "a2luZy1vZi10aGUtaGVycmluZ3M Z29vZC1mb3Itbm90aGluZyBhdHRvcm5leS1hdC1sYXc\n" diff --git a/src/test/test_link_handshake.c b/src/test/test_link_handshake.c index c5508b0f04..422d419078 100644 --- a/src/test/test_link_handshake.c +++ b/src/test/test_link_handshake.c @@ -136,7 +136,7 @@ test_link_handshake_certs_ok(void *arg) * actually generate a CERTS cell. */ tt_int_op(tor_tls_context_init(TOR_TLS_CTX_IS_PUBLIC_SERVER, - key1, key2, 86400), ==, 0); + key1, key2, 86400), OP_EQ, 0); if (with_ed) { /* If we're making a CERTS cell for an ed handshake, let's make sure we @@ -155,63 +155,63 @@ test_link_handshake_certs_ok(void *arg) c1->base_.state = OR_CONN_STATE_OR_HANDSHAKING_V3; c1->link_proto = 3; - tt_int_op(connection_init_or_handshake_state(c1, 1), ==, 0); + tt_int_op(connection_init_or_handshake_state(c1, 1), OP_EQ, 0); /* c2 has started_here == 0 */ c2->base_.state = OR_CONN_STATE_OR_HANDSHAKING_V3; c2->link_proto = 3; - tt_int_op(connection_init_or_handshake_state(c2, 0), ==, 0); + tt_int_op(connection_init_or_handshake_state(c2, 0), OP_EQ, 0); - tt_int_op(0, ==, connection_or_send_certs_cell(c1)); + tt_int_op(0, OP_EQ, connection_or_send_certs_cell(c1)); tt_assert(mock_got_var_cell); cell1 = mock_got_var_cell; - tt_int_op(0, ==, connection_or_send_certs_cell(c2)); + tt_int_op(0, OP_EQ, connection_or_send_certs_cell(c2)); tt_assert(mock_got_var_cell); cell2 = mock_got_var_cell; - tt_int_op(cell1->command, ==, CELL_CERTS); - tt_int_op(cell1->payload_len, >, 1); + tt_int_op(cell1->command, OP_EQ, CELL_CERTS); + tt_int_op(cell1->payload_len, OP_GT, 1); - tt_int_op(cell2->command, ==, CELL_CERTS); - tt_int_op(cell2->payload_len, >, 1); + tt_int_op(cell2->command, OP_EQ, CELL_CERTS); + tt_int_op(cell2->payload_len, OP_GT, 1); - tt_int_op(cell1->payload_len, ==, + tt_int_op(cell1->payload_len, OP_EQ, certs_cell_parse(&cc1, cell1->payload, cell1->payload_len)); - tt_int_op(cell2->payload_len, ==, + tt_int_op(cell2->payload_len, OP_EQ, certs_cell_parse(&cc2, cell2->payload, cell2->payload_len)); if (with_ed) { - tt_int_op(5, ==, cc1->n_certs); - tt_int_op(5, ==, cc2->n_certs); + tt_int_op(5, OP_EQ, cc1->n_certs); + tt_int_op(5, OP_EQ, cc2->n_certs); } else { - tt_int_op(2, ==, cc1->n_certs); - tt_int_op(2, ==, cc2->n_certs); + tt_int_op(2, OP_EQ, cc1->n_certs); + tt_int_op(2, OP_EQ, cc2->n_certs); } - tt_int_op(certs_cell_get_certs(cc1, 0)->cert_type, ==, + tt_int_op(certs_cell_get_certs(cc1, 0)->cert_type, OP_EQ, CERTTYPE_RSA1024_ID_AUTH); - tt_int_op(certs_cell_get_certs(cc1, 1)->cert_type, ==, + tt_int_op(certs_cell_get_certs(cc1, 1)->cert_type, OP_EQ, CERTTYPE_RSA1024_ID_ID); - tt_int_op(certs_cell_get_certs(cc2, 0)->cert_type, ==, + tt_int_op(certs_cell_get_certs(cc2, 0)->cert_type, OP_EQ, CERTTYPE_RSA1024_ID_LINK); - tt_int_op(certs_cell_get_certs(cc2, 1)->cert_type, ==, + tt_int_op(certs_cell_get_certs(cc2, 1)->cert_type, OP_EQ, CERTTYPE_RSA1024_ID_ID); if (with_ed) { - tt_int_op(certs_cell_get_certs(cc1, 2)->cert_type, ==, + tt_int_op(certs_cell_get_certs(cc1, 2)->cert_type, OP_EQ, CERTTYPE_ED_ID_SIGN); - tt_int_op(certs_cell_get_certs(cc1, 3)->cert_type, ==, + tt_int_op(certs_cell_get_certs(cc1, 3)->cert_type, OP_EQ, CERTTYPE_ED_SIGN_AUTH); - tt_int_op(certs_cell_get_certs(cc1, 4)->cert_type, ==, + tt_int_op(certs_cell_get_certs(cc1, 4)->cert_type, OP_EQ, CERTTYPE_RSA1024_ID_EDID); - tt_int_op(certs_cell_get_certs(cc2, 2)->cert_type, ==, + tt_int_op(certs_cell_get_certs(cc2, 2)->cert_type, OP_EQ, CERTTYPE_ED_ID_SIGN); - tt_int_op(certs_cell_get_certs(cc2, 3)->cert_type, ==, + tt_int_op(certs_cell_get_certs(cc2, 3)->cert_type, OP_EQ, CERTTYPE_ED_SIGN_LINK); - tt_int_op(certs_cell_get_certs(cc2, 4)->cert_type, ==, + tt_int_op(certs_cell_get_certs(cc2, 4)->cert_type, OP_EQ, CERTTYPE_RSA1024_ID_EDID); } @@ -240,8 +240,8 @@ test_link_handshake_certs_ok(void *arg) tor_assert(c1->handshake_state->authenticated); tt_assert(c1->handshake_state->received_certs_cell); - tt_assert(c1->handshake_state->certs->auth_cert == NULL); - tt_assert(c1->handshake_state->certs->ed_sign_auth == NULL); + tt_ptr_op(c1->handshake_state->certs->auth_cert, OP_EQ, NULL); + tt_ptr_op(c1->handshake_state->certs->ed_sign_auth, OP_EQ, NULL); tt_assert(c1->handshake_state->certs->id_cert); if (with_ed) { tt_assert(c1->handshake_state->certs->ed_sign_link); @@ -250,9 +250,9 @@ test_link_handshake_certs_ok(void *arg) tt_assert(c1->handshake_state->authenticated_rsa); tt_assert(c1->handshake_state->authenticated_ed25519); } else { - tt_assert(c1->handshake_state->certs->ed_sign_link == NULL); - tt_assert(c1->handshake_state->certs->ed_rsa_crosscert == NULL); - tt_assert(c1->handshake_state->certs->ed_id_sign == NULL); + tt_ptr_op(c1->handshake_state->certs->ed_sign_link, OP_EQ, NULL); + tt_ptr_op(c1->handshake_state->certs->ed_rsa_crosscert, OP_EQ, NULL); + tt_ptr_op(c1->handshake_state->certs->ed_id_sign, OP_EQ, NULL); tt_assert(c1->handshake_state->authenticated_rsa); tt_assert(! c1->handshake_state->authenticated_ed25519); } @@ -278,9 +278,9 @@ test_link_handshake_certs_ok(void *arg) tt_assert(c2->handshake_state->certs->ed_id_sign); } else { tt_assert(c2->handshake_state->certs->auth_cert); - tt_assert(c2->handshake_state->certs->ed_sign_auth == NULL); - tt_assert(c2->handshake_state->certs->ed_rsa_crosscert == NULL); - tt_assert(c2->handshake_state->certs->ed_id_sign == NULL); + tt_ptr_op(c2->handshake_state->certs->ed_sign_auth, OP_EQ, NULL); + tt_ptr_op(c2->handshake_state->certs->ed_rsa_crosscert, OP_EQ, NULL); + tt_ptr_op(c2->handshake_state->certs->ed_id_sign, OP_EQ, NULL); } tt_assert(c2->handshake_state->certs->id_cert); tt_assert(tor_mem_is_zero( @@ -376,14 +376,14 @@ recv_certs_setup(const struct testcase_t *test) tor_addr_from_ipv4h(&d->c->base_.addr, 0x801f0127); d->c->base_.state = OR_CONN_STATE_OR_HANDSHAKING_V3; d->chan->conn = d->c; - tt_int_op(connection_init_or_handshake_state(d->c, 1), ==, 0); + tt_int_op(connection_init_or_handshake_state(d->c, 1), OP_EQ, 0); d->c->link_proto = 4; d->key1 = pk_generate(2); d->key2 = pk_generate(3); tt_int_op(tor_tls_context_init(TOR_TLS_CTX_IS_PUBLIC_SERVER, - d->key1, d->key2, 86400), ==, 0); + d->key1, d->key2, 86400), OP_EQ, 0); if (is_ed) { init_mock_ed_keys(d->key2); } else { @@ -452,7 +452,7 @@ recv_certs_setup(const struct testcase_t *test) d->cell->command = CELL_CERTS; n = certs_cell_encode(d->cell->payload, 4096, d->ccell); - tt_int_op(n, >, 0); + tt_int_op(n, OP_GT, 0); d->cell->payload_len = n; MOCK(tor_tls_cert_matches_key, mock_tls_cert_matches_key); @@ -465,9 +465,9 @@ recv_certs_setup(const struct testcase_t *test) mock_peer_cert = tor_x509_cert_dup(a); } - tt_int_op(0, ==, d->c->handshake_state->received_certs_cell); - tt_int_op(0, ==, mock_send_authenticate_called); - tt_int_op(0, ==, mock_send_netinfo_called); + tt_int_op(0, OP_EQ, d->c->handshake_state->received_certs_cell); + tt_int_op(0, OP_EQ, mock_send_authenticate_called); + tt_int_op(0, OP_EQ, mock_send_netinfo_called); return d; done: @@ -485,25 +485,25 @@ test_link_handshake_recv_certs_ok(void *arg) { certs_data_t *d = arg; channel_tls_process_certs_cell(d->cell, d->chan); - tt_int_op(0, ==, mock_close_called); - tt_int_op(d->c->handshake_state->authenticated, ==, 1); - tt_int_op(d->c->handshake_state->authenticated_rsa, ==, 1); - tt_int_op(d->c->handshake_state->received_certs_cell, ==, 1); - tt_assert(d->c->handshake_state->certs->id_cert != NULL); - tt_assert(d->c->handshake_state->certs->auth_cert == NULL); + tt_int_op(0, OP_EQ, mock_close_called); + tt_int_op(d->c->handshake_state->authenticated, OP_EQ, 1); + tt_int_op(d->c->handshake_state->authenticated_rsa, OP_EQ, 1); + tt_int_op(d->c->handshake_state->received_certs_cell, OP_EQ, 1); + tt_ptr_op(d->c->handshake_state->certs->id_cert, OP_NE, NULL); + tt_ptr_op(d->c->handshake_state->certs->auth_cert, OP_EQ, NULL); if (d->is_ed) { - tt_assert(d->c->handshake_state->certs->ed_id_sign != NULL); - tt_assert(d->c->handshake_state->certs->ed_sign_link != NULL); - tt_assert(d->c->handshake_state->certs->ed_sign_auth == NULL); - tt_assert(d->c->handshake_state->certs->ed_rsa_crosscert != NULL); - tt_int_op(d->c->handshake_state->authenticated_ed25519, ==, 1); + tt_ptr_op(d->c->handshake_state->certs->ed_id_sign, OP_NE, NULL); + tt_ptr_op(d->c->handshake_state->certs->ed_sign_link, OP_NE, NULL); + tt_ptr_op(d->c->handshake_state->certs->ed_sign_auth, OP_EQ, NULL); + tt_ptr_op(d->c->handshake_state->certs->ed_rsa_crosscert, OP_NE, NULL); + tt_int_op(d->c->handshake_state->authenticated_ed25519, OP_EQ, 1); } else { - tt_assert(d->c->handshake_state->certs->ed_id_sign == NULL); - tt_assert(d->c->handshake_state->certs->ed_sign_link == NULL); - tt_assert(d->c->handshake_state->certs->ed_sign_auth == NULL); - tt_assert(d->c->handshake_state->certs->ed_rsa_crosscert == NULL); - tt_int_op(d->c->handshake_state->authenticated_ed25519, ==, 0); + tt_ptr_op(d->c->handshake_state->certs->ed_id_sign, OP_EQ, NULL); + tt_ptr_op(d->c->handshake_state->certs->ed_sign_link, OP_EQ, NULL); + tt_ptr_op(d->c->handshake_state->certs->ed_sign_auth, OP_EQ, NULL); + tt_ptr_op(d->c->handshake_state->certs->ed_rsa_crosscert, OP_EQ, NULL); + tt_int_op(d->c->handshake_state->authenticated_ed25519, OP_EQ, 0); } done: @@ -517,17 +517,17 @@ test_link_handshake_recv_certs_ok_server(void *arg) d->c->handshake_state->started_here = 0; d->c->handshake_state->certs->started_here = 0; channel_tls_process_certs_cell(d->cell, d->chan); - tt_int_op(0, ==, mock_close_called); - tt_int_op(d->c->handshake_state->authenticated, ==, 0); - tt_int_op(d->c->handshake_state->received_certs_cell, ==, 1); - tt_assert(d->c->handshake_state->certs->id_cert != NULL); - tt_assert(d->c->handshake_state->certs->link_cert == NULL); + tt_int_op(0, OP_EQ, mock_close_called); + tt_int_op(d->c->handshake_state->authenticated, OP_EQ, 0); + tt_int_op(d->c->handshake_state->received_certs_cell, OP_EQ, 1); + tt_ptr_op(d->c->handshake_state->certs->id_cert, OP_NE, NULL); + tt_ptr_op(d->c->handshake_state->certs->link_cert, OP_EQ, NULL); if (d->is_ed) { - tt_assert(d->c->handshake_state->certs->ed_sign_auth != NULL); - tt_assert(d->c->handshake_state->certs->auth_cert == NULL); + tt_ptr_op(d->c->handshake_state->certs->ed_sign_auth, OP_NE, NULL); + tt_ptr_op(d->c->handshake_state->certs->auth_cert, OP_EQ, NULL); } else { - tt_assert(d->c->handshake_state->certs->ed_sign_auth == NULL); - tt_assert(d->c->handshake_state->certs->auth_cert != NULL); + tt_ptr_op(d->c->handshake_state->certs->ed_sign_auth, OP_EQ, NULL); + tt_ptr_op(d->c->handshake_state->certs->auth_cert, OP_NE, NULL); } done: @@ -543,11 +543,11 @@ test_link_handshake_recv_certs_ok_server(void *arg) setup_capture_of_logs(LOG_INFO); \ { code ; } \ channel_tls_process_certs_cell(d->cell, d->chan); \ - tt_int_op(1, ==, mock_close_called); \ - tt_int_op(0, ==, mock_send_authenticate_called); \ - tt_int_op(0, ==, mock_send_netinfo_called); \ - tt_int_op(0, ==, d->c->handshake_state->authenticated_rsa); \ - tt_int_op(0, ==, d->c->handshake_state->authenticated_ed25519); \ + tt_int_op(1, OP_EQ, mock_close_called); \ + tt_int_op(0, OP_EQ, mock_send_authenticate_called); \ + tt_int_op(0, OP_EQ, mock_send_netinfo_called); \ + tt_int_op(0, OP_EQ, d->c->handshake_state->authenticated_rsa); \ + tt_int_op(0, OP_EQ, d->c->handshake_state->authenticated_ed25519); \ if (require_failure_message) { \ expect_log_msg_containing(require_failure_message); \ } \ @@ -603,7 +603,7 @@ CERTS_FAIL(truncated_5, /* ed25519 */ const char *msg = certs_cell_check(d->ccell); \ if (msg) puts(msg); \ ssize_t n = certs_cell_encode(d->cell->payload, 4096, d->ccell); \ - tt_int_op(n, >, 0); \ + tt_int_op(n, OP_GT, 0); \ d->cell->payload_len = n; \ } while (0) @@ -686,9 +686,9 @@ test_link_handshake_recv_certs_missing_id(void *arg) /* ed25519 */ /* This handshake succeeds, but since we have no ID cert, we will * just do the RSA handshake. */ channel_tls_process_certs_cell(d->cell, d->chan); - tt_int_op(0, ==, mock_close_called); - tt_int_op(0, ==, d->c->handshake_state->authenticated_ed25519); - tt_int_op(1, ==, d->c->handshake_state->authenticated_rsa); + tt_int_op(0, OP_EQ, mock_close_called); + tt_int_op(0, OP_EQ, d->c->handshake_state->authenticated_ed25519); + tt_int_op(1, OP_EQ, d->c->handshake_state->authenticated_rsa); done: ; } @@ -697,7 +697,7 @@ CERTS_FAIL(missing_signing_key, /* ed25519 */ require_failure_message = "No Ed25519 signing key"; tt_int_op(certs_cell_getlen_certs(d->ccell), OP_EQ, 5); certs_cell_cert_t *cert = certs_cell_get_certs(d->ccell, 2); - tt_int_op(cert->cert_type, ==, CERTTYPE_ED_ID_SIGN); + tt_int_op(cert->cert_type, OP_EQ, CERTTYPE_ED_ID_SIGN); /* replace this with a valid master->signing cert, but with no * signing key. */ const ed25519_keypair_t *mk = get_master_identity_keypair(); @@ -905,28 +905,28 @@ test_link_handshake_send_authchallenge(void *arg) crypto_pk_t *rsa0 = pk_generate(0), *rsa1 = pk_generate(1); tt_int_op(tor_tls_context_init(TOR_TLS_CTX_IS_PUBLIC_SERVER, - rsa0, rsa1, 86400), ==, 0); + rsa0, rsa1, 86400), OP_EQ, 0); init_mock_ed_keys(rsa0); MOCK(connection_or_write_var_cell_to_buf, mock_write_var_cell); - tt_int_op(connection_init_or_handshake_state(c1, 0), ==, 0); + tt_int_op(connection_init_or_handshake_state(c1, 0), OP_EQ, 0); c1->base_.state = OR_CONN_STATE_OR_HANDSHAKING_V3; - tt_assert(! mock_got_var_cell); - tt_int_op(0, ==, connection_or_send_auth_challenge_cell(c1)); + tt_ptr_op(mock_got_var_cell, OP_EQ, NULL); + tt_int_op(0, OP_EQ, connection_or_send_auth_challenge_cell(c1)); cell1 = mock_got_var_cell; - tt_int_op(0, ==, connection_or_send_auth_challenge_cell(c1)); + tt_int_op(0, OP_EQ, connection_or_send_auth_challenge_cell(c1)); cell2 = mock_got_var_cell; - tt_int_op(38, ==, cell1->payload_len); - tt_int_op(38, ==, cell2->payload_len); - tt_int_op(0, ==, cell1->circ_id); - tt_int_op(0, ==, cell2->circ_id); - tt_int_op(CELL_AUTH_CHALLENGE, ==, cell1->command); - tt_int_op(CELL_AUTH_CHALLENGE, ==, cell2->command); + tt_int_op(38, OP_EQ, cell1->payload_len); + tt_int_op(38, OP_EQ, cell2->payload_len); + tt_int_op(0, OP_EQ, cell1->circ_id); + tt_int_op(0, OP_EQ, cell2->circ_id); + tt_int_op(CELL_AUTH_CHALLENGE, OP_EQ, cell1->command); + tt_int_op(CELL_AUTH_CHALLENGE, OP_EQ, cell2->command); - tt_mem_op("\x00\x02\x00\x01\x00\x03", ==, cell1->payload + 32, 6); - tt_mem_op("\x00\x02\x00\x01\x00\x03", ==, cell2->payload + 32, 6); - tt_mem_op(cell1->payload, !=, cell2->payload, 32); + tt_mem_op("\x00\x02\x00\x01\x00\x03", OP_EQ, cell1->payload + 32, 6); + tt_mem_op("\x00\x02\x00\x01\x00\x03", OP_EQ, cell2->payload + 32, 6); + tt_mem_op(cell1->payload, OP_NE, cell2->payload, 32); done: UNMOCK(connection_or_write_var_cell_to_buf); @@ -974,7 +974,7 @@ recv_authchallenge_setup(const struct testcase_t *test) d->c->base_.address = tor_strdup("HaveAnAddress"); d->c->base_.state = OR_CONN_STATE_OR_HANDSHAKING_V3; d->chan->conn = d->c; - tt_int_op(connection_init_or_handshake_state(d->c, 1), ==, 0); + tt_int_op(connection_init_or_handshake_state(d->c, 1), OP_EQ, 0); d->c->link_proto = 4; d->c->handshake_state->received_certs_cell = 1; d->cell = var_cell_new(128); @@ -989,9 +989,9 @@ recv_authchallenge_setup(const struct testcase_t *test) MOCK(connection_or_close_for_error, mock_close_for_err); MOCK(connection_or_send_netinfo, mock_send_netinfo); MOCK(connection_or_send_authenticate_cell, mock_send_authenticate); - tt_int_op(0, ==, d->c->handshake_state->received_auth_challenge); - tt_int_op(0, ==, mock_send_authenticate_called); - tt_int_op(0, ==, mock_send_netinfo_called); + tt_int_op(0, OP_EQ, d->c->handshake_state->received_auth_challenge); + tt_int_op(0, OP_EQ, mock_send_authenticate_called); + tt_int_op(0, OP_EQ, mock_send_netinfo_called); return d; done: @@ -1010,11 +1010,11 @@ test_link_handshake_recv_authchallenge_ok(void *arg) authchallenge_data_t *d = arg; channel_tls_process_auth_challenge_cell(d->cell, d->chan); - tt_int_op(0, ==, mock_close_called); - tt_int_op(1, ==, d->c->handshake_state->received_auth_challenge); - tt_int_op(1, ==, mock_send_authenticate_called); - tt_int_op(1, ==, mock_send_netinfo_called); - tt_int_op(1, ==, mock_send_authenticate_called_with_type); /* RSA */ + tt_int_op(0, OP_EQ, mock_close_called); + tt_int_op(1, OP_EQ, d->c->handshake_state->received_auth_challenge); + tt_int_op(1, OP_EQ, mock_send_authenticate_called); + tt_int_op(1, OP_EQ, mock_send_netinfo_called); + tt_int_op(1, OP_EQ, mock_send_authenticate_called_with_type); /* RSA */ done: ; } @@ -1029,11 +1029,11 @@ test_link_handshake_recv_authchallenge_ok_ed25519(void *arg) d->cell->payload[39] = 3; d->cell->payload_len += 2; channel_tls_process_auth_challenge_cell(d->cell, d->chan); - tt_int_op(0, ==, mock_close_called); - tt_int_op(1, ==, d->c->handshake_state->received_auth_challenge); - tt_int_op(1, ==, mock_send_authenticate_called); - tt_int_op(1, ==, mock_send_netinfo_called); - tt_int_op(3, ==, mock_send_authenticate_called_with_type); /* Ed25519 */ + tt_int_op(0, OP_EQ, mock_close_called); + tt_int_op(1, OP_EQ, d->c->handshake_state->received_auth_challenge); + tt_int_op(1, OP_EQ, mock_send_authenticate_called); + tt_int_op(1, OP_EQ, mock_send_netinfo_called); + tt_int_op(3, OP_EQ, mock_send_authenticate_called_with_type); /* Ed25519 */ done: ; } @@ -1045,10 +1045,10 @@ test_link_handshake_recv_authchallenge_ok_noserver(void *arg) get_options_mutable()->ORPort_set = 0; channel_tls_process_auth_challenge_cell(d->cell, d->chan); - tt_int_op(0, ==, mock_close_called); - tt_int_op(1, ==, d->c->handshake_state->received_auth_challenge); - tt_int_op(0, ==, mock_send_authenticate_called); - tt_int_op(0, ==, mock_send_netinfo_called); + tt_int_op(0, OP_EQ, mock_close_called); + tt_int_op(1, OP_EQ, d->c->handshake_state->received_auth_challenge); + tt_int_op(0, OP_EQ, mock_send_authenticate_called); + tt_int_op(0, OP_EQ, mock_send_netinfo_called); done: ; } @@ -1060,10 +1060,10 @@ test_link_handshake_recv_authchallenge_ok_unrecognized(void *arg) d->cell->payload[37] = 99; channel_tls_process_auth_challenge_cell(d->cell, d->chan); - tt_int_op(0, ==, mock_close_called); - tt_int_op(1, ==, d->c->handshake_state->received_auth_challenge); - tt_int_op(0, ==, mock_send_authenticate_called); - tt_int_op(1, ==, mock_send_netinfo_called); + tt_int_op(0, OP_EQ, mock_close_called); + tt_int_op(1, OP_EQ, d->c->handshake_state->received_auth_challenge); + tt_int_op(0, OP_EQ, mock_send_authenticate_called); + tt_int_op(1, OP_EQ, mock_send_netinfo_called); done: ; } @@ -1077,9 +1077,9 @@ test_link_handshake_recv_authchallenge_ok_unrecognized(void *arg) setup_capture_of_logs(LOG_INFO); \ { code ; } \ channel_tls_process_auth_challenge_cell(d->cell, d->chan); \ - tt_int_op(1, ==, mock_close_called); \ - tt_int_op(0, ==, mock_send_authenticate_called); \ - tt_int_op(0, ==, mock_send_netinfo_called); \ + tt_int_op(1, OP_EQ, mock_close_called); \ + tt_int_op(0, OP_EQ, mock_send_authenticate_called); \ + tt_int_op(0, OP_EQ, mock_send_netinfo_called); \ if (require_failure_message) { \ expect_log_msg_containing(require_failure_message); \ } \ @@ -1197,17 +1197,17 @@ authenticate_data_setup(const struct testcase_t *test) d->key1 = pk_generate(2); d->key2 = pk_generate(3); tt_int_op(tor_tls_context_init(TOR_TLS_CTX_IS_PUBLIC_SERVER, - d->key1, d->key2, 86400), ==, 0); + d->key1, d->key2, 86400), OP_EQ, 0); init_mock_ed_keys(d->key2); d->c1->base_.state = OR_CONN_STATE_OR_HANDSHAKING_V3; d->c1->link_proto = 3; - tt_int_op(connection_init_or_handshake_state(d->c1, 1), ==, 0); + tt_int_op(connection_init_or_handshake_state(d->c1, 1), OP_EQ, 0); d->c2->base_.state = OR_CONN_STATE_OR_HANDSHAKING_V3; d->c2->link_proto = 3; - tt_int_op(connection_init_or_handshake_state(d->c2, 0), ==, 0); + tt_int_op(connection_init_or_handshake_state(d->c2, 0), OP_EQ, 0); var_cell_t *cell = var_cell_new(16); cell->command = CELL_CERTS; or_handshake_state_record_var_cell(d->c1, d->c1->handshake_state, cell, 1); @@ -1260,7 +1260,7 @@ authenticate_data_setup(const struct testcase_t *test) authtype = AUTHTYPE_ED25519_SHA256_RFC5705; else authtype = AUTHTYPE_RSA_SHA256_TLSSECRET; - tt_int_op(0, ==, connection_or_send_authenticate_cell(d->c1, authtype)); + tt_int_op(0, OP_EQ, connection_or_send_authenticate_cell(d->c1, authtype)); tt_assert(mock_got_var_cell); d->cell = mock_got_var_cell; @@ -1285,65 +1285,65 @@ test_link_handshake_auth_cell(void *arg) crypto_pk_t *auth_pubkey = NULL; /* Is the cell well-formed on the outer layer? */ - tt_int_op(d->cell->command, ==, CELL_AUTHENTICATE); - tt_int_op(d->cell->payload[0], ==, 0); + tt_int_op(d->cell->command, OP_EQ, CELL_AUTHENTICATE); + tt_int_op(d->cell->payload[0], OP_EQ, 0); if (d->is_ed) - tt_int_op(d->cell->payload[1], ==, 3); + tt_int_op(d->cell->payload[1], OP_EQ, 3); else - tt_int_op(d->cell->payload[1], ==, 1); - tt_int_op(ntohs(get_uint16(d->cell->payload + 2)), ==, + tt_int_op(d->cell->payload[1], OP_EQ, 1); + tt_int_op(ntohs(get_uint16(d->cell->payload + 2)), OP_EQ, d->cell->payload_len - 4); /* Check it out for plausibility... */ auth_ctx_t ctx; ctx.is_ed = d->is_ed; - tt_int_op(d->cell->payload_len-4, ==, auth1_parse(&auth1, + tt_int_op(d->cell->payload_len-4, OP_EQ, auth1_parse(&auth1, d->cell->payload+4, d->cell->payload_len - 4, &ctx)); tt_assert(auth1); if (d->is_ed) { - tt_mem_op(auth1->type, ==, "AUTH0003", 8); + tt_mem_op(auth1->type, OP_EQ, "AUTH0003", 8); } else { - tt_mem_op(auth1->type, ==, "AUTH0001", 8); + tt_mem_op(auth1->type, OP_EQ, "AUTH0001", 8); } - tt_mem_op(auth1->tlssecrets, ==, "int getRandomNumber(){return 4;}", 32); + tt_mem_op(auth1->tlssecrets, OP_EQ, "int getRandomNumber(){return 4;}", 32); /* Is the signature okay? */ const uint8_t *start = d->cell->payload+4, *end = auth1->end_of_signed; if (d->is_ed) { ed25519_signature_t sig; - tt_int_op(auth1_getlen_sig(auth1), ==, ED25519_SIG_LEN); + tt_int_op(auth1_getlen_sig(auth1), OP_EQ, ED25519_SIG_LEN); memcpy(&sig.sig, auth1_getarray_sig(auth1), ED25519_SIG_LEN); tt_assert(!ed25519_checksig(&sig, start, end-start, &get_current_auth_keypair()->pubkey)); } else { uint8_t sig[128]; uint8_t digest[32]; - tt_int_op(auth1_getlen_sig(auth1), >, 120); + tt_int_op(auth1_getlen_sig(auth1), OP_GT, 120); auth_pubkey = tor_tls_cert_get_key( d->c2->handshake_state->certs->auth_cert); int n = crypto_pk_public_checksig( auth_pubkey, (char*)sig, sizeof(sig), (char*)auth1_getarray_sig(auth1), auth1_getlen_sig(auth1)); - tt_int_op(n, ==, 32); + tt_int_op(n, OP_EQ, 32); crypto_digest256((char*)digest, (const char*)start, end-start, DIGEST_SHA256); - tt_mem_op(sig, ==, digest, 32); + tt_mem_op(sig, OP_EQ, digest, 32); } /* Then feed it to c2. */ - tt_int_op(d->c2->handshake_state->authenticated, ==, 0); + tt_int_op(d->c2->handshake_state->authenticated, OP_EQ, 0); channel_tls_process_authenticate_cell(d->cell, d->chan2); - tt_int_op(mock_close_called, ==, 0); - tt_int_op(d->c2->handshake_state->authenticated, ==, 1); + tt_int_op(mock_close_called, OP_EQ, 0); + tt_int_op(d->c2->handshake_state->authenticated, OP_EQ, 1); if (d->is_ed) { - tt_int_op(d->c2->handshake_state->authenticated_ed25519, ==, 1); - tt_int_op(d->c2->handshake_state->authenticated_rsa, ==, 1); + tt_int_op(d->c2->handshake_state->authenticated_ed25519, OP_EQ, 1); + tt_int_op(d->c2->handshake_state->authenticated_rsa, OP_EQ, 1); } else { - tt_int_op(d->c2->handshake_state->authenticated_ed25519, ==, 0); - tt_int_op(d->c2->handshake_state->authenticated_rsa, ==, 1); + tt_int_op(d->c2->handshake_state->authenticated_ed25519, OP_EQ, 0); + tt_int_op(d->c2->handshake_state->authenticated_rsa, OP_EQ, 1); } done: @@ -1359,10 +1359,10 @@ test_link_handshake_auth_cell(void *arg) const char *require_failure_message = NULL; \ setup_capture_of_logs(LOG_INFO); \ { code ; } \ - tt_int_op(d->c2->handshake_state->authenticated, ==, 0); \ + tt_int_op(d->c2->handshake_state->authenticated, OP_EQ, 0); \ channel_tls_process_authenticate_cell(d->cell, d->chan2); \ - tt_int_op(mock_close_called, ==, 1); \ - tt_int_op(d->c2->handshake_state->authenticated, ==, 0); \ + tt_int_op(mock_close_called, OP_EQ, 1); \ + tt_int_op(d->c2->handshake_state->authenticated, OP_EQ, 0); \ if (require_failure_message) { \ expect_log_msg_containing(require_failure_message); \ } \ @@ -1390,8 +1390,8 @@ test_link_handshake_auth_already_authenticated(void *arg) setup_capture_of_logs(LOG_INFO); d->c2->handshake_state->authenticated = 1; channel_tls_process_authenticate_cell(d->cell, d->chan2); - tt_int_op(mock_close_called, ==, 1); - tt_int_op(d->c2->handshake_state->authenticated, ==, 1); + tt_int_op(mock_close_called, OP_EQ, 1); + tt_int_op(d->c2->handshake_state->authenticated, OP_EQ, 1); expect_log_msg_containing("The peer is already authenticated"); done: teardown_capture_of_logs(); @@ -1425,7 +1425,7 @@ AUTHENTICATE_FAIL(truncated_2, d->cell->payload[3]++) AUTHENTICATE_FAIL(tooshort_1, require_failure_message = "Authenticator was too short"; - tt_int_op(d->cell->payload_len, >=, 260); + tt_int_op(d->cell->payload_len, OP_GE, 260); d->cell->payload[2] -= 1; d->cell->payload_len -= 256;) AUTHENTICATE_FAIL(badcontent, diff --git a/src/test/test_logging.c b/src/test/test_logging.c index 94b3e4ea68..e373158e34 100644 --- a/src/test/test_logging.c +++ b/src/test/test_logging.c @@ -107,7 +107,7 @@ test_sigsafe_err(void *arg) close(STDERR_FILENO); content = read_file_to_str(fn, 0, NULL); - tt_assert(content != NULL); + tt_ptr_op(content, OP_NE, NULL); tor_split_lines(lines, content, (int)strlen(content)); tt_int_op(smartlist_len(lines), OP_GE, 5); @@ -140,7 +140,7 @@ test_ratelim(void *arg) char *msg = NULL; msg = rate_limit_log(&ten_min, now); - tt_assert(msg != NULL); + tt_ptr_op(msg, OP_NE, NULL); tt_str_op(msg, OP_EQ, ""); /* nothing was suppressed. */ tt_int_op(ten_min.last_allowed, OP_EQ, now); @@ -150,14 +150,14 @@ test_ratelim(void *arg) for (i = 0; i < 9; ++i) { now += 60; /* one minute has passed. */ msg = rate_limit_log(&ten_min, now); - tt_assert(msg == NULL); + tt_ptr_op(msg, OP_EQ, NULL); tt_int_op(ten_min.last_allowed, OP_EQ, start); tt_int_op(ten_min.n_calls_since_last_time, OP_EQ, i + 1); } now += 240; /* Okay, we can be done. */ msg = rate_limit_log(&ten_min, now); - tt_assert(msg != NULL); + tt_ptr_op(msg, OP_NE, NULL); tt_str_op(msg, OP_EQ, " [9 similar message(s) suppressed in last 600 seconds]"); done: diff --git a/src/test/test_microdesc.c b/src/test/test_microdesc.c index c78fda3b69..4f0ecd778b 100644 --- a/src/test/test_microdesc.c +++ b/src/test/test_microdesc.c @@ -19,7 +19,7 @@ #include <direct.h> #else #include <dirent.h> -#endif +#endif /* defined(_WIN32) */ static const char test_md1[] = "onion-key\n" @@ -464,7 +464,7 @@ test_md_generate(void *arg) microdesc_free(md); md = NULL; md = dirvote_create_microdescriptor(ri, 21); - tt_str_op(md->body, ==, test_md_18); + tt_str_op(md->body, OP_EQ, test_md_18); routerinfo_free(ri); ri = router_parse_entry_from_string(test_ri2, NULL, 0, 0, NULL, NULL); @@ -472,12 +472,12 @@ test_md_generate(void *arg) microdesc_free(md); md = NULL; md = dirvote_create_microdescriptor(ri, 18); - tt_str_op(md->body, ==, test_md2_18); + tt_str_op(md->body, OP_EQ, test_md2_18); microdesc_free(md); md = NULL; md = dirvote_create_microdescriptor(ri, 21); - tt_str_op(md->body, ==, test_md2_21); + tt_str_op(md->body, OP_EQ, test_md2_21); tt_assert(ed25519_pubkey_eq(md->ed25519_identity_pkey, &ri->cache_info.signing_key_cert->signing_key)); @@ -823,14 +823,14 @@ test_md_corrupt_desc(void *arg) "@last-listed 2015-06-22 10:00:00\n" "onion-k\n", NULL, SAVED_IN_JOURNAL, 0, time(NULL), NULL); - tt_int_op(smartlist_len(sl), ==, 0); + tt_int_op(smartlist_len(sl), OP_EQ, 0); smartlist_free(sl); sl = microdescs_add_to_cache(get_microdesc_cache(), "@last-listed 2015-06-22 10:00:00\n" "wiggly\n", NULL, SAVED_IN_JOURNAL, 0, time(NULL), NULL); - tt_int_op(smartlist_len(sl), ==, 0); + tt_int_op(smartlist_len(sl), OP_EQ, 0); smartlist_free(sl); tor_asprintf(&cp, "%s\n%s", test_md1, "@foobar\nonion-wobble\n"); @@ -838,7 +838,7 @@ test_md_corrupt_desc(void *arg) sl = microdescs_add_to_cache(get_microdesc_cache(), cp, cp+strlen(cp), SAVED_IN_JOURNAL, 0, time(NULL), NULL); - tt_int_op(smartlist_len(sl), ==, 0); + tt_int_op(smartlist_len(sl), OP_EQ, 0); done: tor_free(cp); diff --git a/src/test/test_nodelist.c b/src/test/test_nodelist.c index 256354415c..a873003d72 100644 --- a/src/test/test_nodelist.c +++ b/src/test/test_nodelist.c @@ -7,7 +7,9 @@ **/ #include "or.h" +#include "networkstatus.h" #include "nodelist.h" +#include "torcert.h" #include "test.h" /** Test the case when node_get_by_id() returns NULL, @@ -100,6 +102,107 @@ test_nodelist_node_is_dir(void *arg) return; } +static networkstatus_t *dummy_ns = NULL; +static networkstatus_t * +mock_networkstatus_get_latest_consensus(void) +{ + return dummy_ns; +} +static networkstatus_t * +mock_networkstatus_get_latest_consensus_by_flavor(consensus_flavor_t f) +{ + tor_assert(f == FLAV_MICRODESC); + return dummy_ns; +} + +static void +test_nodelist_ed_id(void *arg) +{ + routerstatus_t *rs[4]; + microdesc_t *md[4]; + routerinfo_t *ri[4]; + networkstatus_t *ns; + int i; + (void)arg; + + ns = tor_malloc_zero(sizeof(networkstatus_t)); + ns->flavor = FLAV_MICRODESC; + ns->routerstatus_list = smartlist_new(); + dummy_ns = ns; + MOCK(networkstatus_get_latest_consensus, + mock_networkstatus_get_latest_consensus); + MOCK(networkstatus_get_latest_consensus_by_flavor, + mock_networkstatus_get_latest_consensus_by_flavor); + + /* Make a bunch of dummy objects that we can play around with. Only set the + necessary fields */ + + for (i = 0; i < 4; ++i) { + rs[i] = tor_malloc_zero(sizeof(*rs[i])); + md[i] = tor_malloc_zero(sizeof(*md[i])); + ri[i] = tor_malloc_zero(sizeof(*ri[i])); + + crypto_rand(md[i]->digest, sizeof(md[i]->digest)); + md[i]->ed25519_identity_pkey = tor_malloc(sizeof(ed25519_public_key_t)); + crypto_rand((char*)md[i]->ed25519_identity_pkey, + sizeof(ed25519_public_key_t)); + crypto_rand(rs[i]->identity_digest, sizeof(rs[i]->identity_digest)); + memcpy(ri[i]->cache_info.identity_digest, rs[i]->identity_digest, + DIGEST_LEN); + memcpy(rs[i]->descriptor_digest, md[i]->digest, DIGEST256_LEN); + ri[i]->cache_info.signing_key_cert = tor_malloc_zero(sizeof(tor_cert_t)); + memcpy(&ri[i]->cache_info.signing_key_cert->signing_key, + md[i]->ed25519_identity_pkey, sizeof(ed25519_public_key_t)); + + if (i != 3) + smartlist_add(ns->routerstatus_list, rs[i]); + } + + tt_int_op(0, OP_EQ, smartlist_len(nodelist_get_list())); + + nodelist_set_consensus(ns); + + tt_int_op(3, OP_EQ, smartlist_len(nodelist_get_list())); + + /* No Ed25519 info yet, so nothing has an ED id. */ + tt_ptr_op(NULL, OP_EQ, node_get_by_ed25519_id(md[0]->ed25519_identity_pkey)); + + /* Register the first one by md, then look it up. */ + node_t *n = nodelist_add_microdesc(md[0]); + tt_ptr_op(n, OP_EQ, node_get_by_ed25519_id(md[0]->ed25519_identity_pkey)); + + /* Register the second by ri, then look it up. */ + routerinfo_t *ri_old = NULL; + n = nodelist_set_routerinfo(ri[1], &ri_old); + tt_ptr_op(n, OP_EQ, node_get_by_ed25519_id(md[1]->ed25519_identity_pkey)); + tt_ptr_op(ri_old, OP_EQ, NULL); + + /* Register it by md too. */ + node_t *n2 = nodelist_add_microdesc(md[1]); + tt_ptr_op(n2, OP_EQ, n); + tt_ptr_op(n, OP_EQ, node_get_by_ed25519_id(md[1]->ed25519_identity_pkey)); + + /* Register the 4th by ri only -- we never put it into the networkstatus, + * so it has to be independent */ + n = nodelist_set_routerinfo(ri[3], &ri_old); + tt_ptr_op(n, OP_EQ, node_get_by_ed25519_id(md[3]->ed25519_identity_pkey)); + tt_ptr_op(ri_old, OP_EQ, NULL); + tt_int_op(4, OP_EQ, smartlist_len(nodelist_get_list())); + + done: + for (i = 0; i < 4; ++i) { + tor_free(rs[i]); + tor_free(md[i]->ed25519_identity_pkey); + tor_free(md[i]); + tor_free(ri[i]->cache_info.signing_key_cert); + tor_free(ri[i]); + } + smartlist_clear(ns->routerstatus_list); + networkstatus_vote_free(ns); + UNMOCK(networkstatus_get_latest_consensus); + UNMOCK(networkstatus_get_latest_consensus_by_flavor); +} + #define NODE(name, flags) \ { #name, test_nodelist_##name, (flags), NULL, NULL } @@ -107,6 +210,7 @@ struct testcase_t nodelist_tests[] = { NODE(node_get_verbose_nickname_by_id_null_node, TT_FORK), NODE(node_get_verbose_nickname_not_named, TT_FORK), NODE(node_is_dir, TT_FORK), + NODE(ed_id, TT_FORK), END_OF_TESTCASES }; diff --git a/src/test/test_oom.c b/src/test/test_oom.c index f03a504d1d..cf28690a28 100644 --- a/src/test/test_oom.c +++ b/src/test/test_oom.c @@ -67,7 +67,7 @@ add_bytes_to_buf(buf_t *buf, size_t n_bytes) while (n_bytes) { size_t this_add = n_bytes > sizeof(b) ? sizeof(b) : n_bytes; crypto_rand(b, this_add); - write_to_buf(b, this_add, buf); + buf_add(buf, b, this_add); n_bytes -= this_add; } } diff --git a/src/test/test_oos.c b/src/test/test_oos.c index 9fd6bce5ae..e72fcf5de9 100644 --- a/src/test/test_oos.c +++ b/src/test/test_oos.c @@ -52,7 +52,7 @@ kill_conn_list_mock(smartlist_t *conns) { ++kill_conn_list_calls; - tt_assert(conns != NULL); + tt_ptr_op(conns, OP_NE, NULL); kill_conn_list_killed += smartlist_len(conns); @@ -248,7 +248,7 @@ close_for_error_mock(or_connection_t *orconn, int flush) { (void)flush; - tt_assert(orconn != NULL); + tt_ptr_op(orconn, OP_NE, NULL); ++cfe_calls; done: @@ -264,7 +264,7 @@ mark_for_close_oos_mock(connection_t *conn, (void)line; (void)file; - tt_assert(conn != NULL); + tt_ptr_op(conn, OP_NE, NULL); ++mark_calls; done: @@ -298,8 +298,8 @@ test_oos_kill_conn_list(void *arg) dir_c2->base_.purpose = DIR_PURPOSE_MIN_; c2 = TO_CONN(dir_c2); - tt_assert(c1 != NULL); - tt_assert(c2 != NULL); + tt_ptr_op(c1, OP_NE, NULL); + tt_ptr_op(c2, OP_NE, NULL); /* Make list */ l = smartlist_new(); @@ -345,7 +345,7 @@ get_num_circuits_mock(or_connection_t *conn) { int circs = 0; - tt_assert(conn != NULL); + tt_ptr_op(conn, OP_NE, NULL); if (conns_with_circs && smartlist_contains(conns_with_circs, TO_CONN(conn))) { @@ -397,7 +397,7 @@ test_oos_pick_oos_victims(void *arg) /* Try picking one */ picked = pick_oos_victims(1); /* It should be the one with circuits */ - tt_assert(picked != NULL); + tt_ptr_op(picked, OP_NE, NULL); tt_int_op(smartlist_len(picked), OP_EQ, 1); tt_assert(smartlist_contains(picked, smartlist_get(conns_for_mock, 0))); smartlist_free(picked); @@ -405,14 +405,14 @@ test_oos_pick_oos_victims(void *arg) /* Try picking none */ picked = pick_oos_victims(0); /* We should get an empty list */ - tt_assert(picked != NULL); + tt_ptr_op(picked, OP_NE, NULL); tt_int_op(smartlist_len(picked), OP_EQ, 0); smartlist_free(picked); /* Try picking two */ picked = pick_oos_victims(2); /* We should get both active orconns */ - tt_assert(picked != NULL); + tt_ptr_op(picked, OP_NE, NULL); tt_int_op(smartlist_len(picked), OP_EQ, 2); tt_assert(smartlist_contains(picked, smartlist_get(conns_for_mock, 0))); tt_assert(smartlist_contains(picked, smartlist_get(conns_for_mock, 1))); diff --git a/src/test/test_options.c b/src/test/test_options.c index ad735b72a6..62732cabf7 100644 --- a/src/test/test_options.c +++ b/src/test/test_options.c @@ -282,7 +282,7 @@ test_have_enough_mem_for_dircache(void *arg) or_options_t *opt=NULL; or_options_t *dflt=NULL; config_line_t *cl=NULL; - char *msg=NULL;; + char *msg=NULL; int r; const char *configuration = "ORPort 8080\nDirCache 1", *expect_errmsg; @@ -299,7 +299,7 @@ test_have_enough_mem_for_dircache(void *arg) /* 300 MB RAM available, DirCache enabled */ r = have_enough_mem_for_dircache(opt, MEGABYTEIFY(300), &msg); tt_int_op(r, OP_EQ, 0); - tt_assert(!msg); + tt_ptr_op(msg, OP_EQ, NULL); /* 200 MB RAM available, DirCache enabled */ r = have_enough_mem_for_dircache(opt, MEGABYTEIFY(200), &msg); @@ -322,7 +322,7 @@ test_have_enough_mem_for_dircache(void *arg) /* 300 MB RAM available, DirCache enabled, Bridge */ r = have_enough_mem_for_dircache(opt, MEGABYTEIFY(300), &msg); tt_int_op(r, OP_EQ, 0); - tt_assert(!msg); + tt_ptr_op(msg, OP_EQ, NULL); /* 200 MB RAM available, DirCache enabled, Bridge */ r = have_enough_mem_for_dircache(opt, MEGABYTEIFY(200), &msg); @@ -345,7 +345,7 @@ test_have_enough_mem_for_dircache(void *arg) /* 200 MB RAM available, DirCache disabled */ r = have_enough_mem_for_dircache(opt, MEGABYTEIFY(200), &msg); tt_int_op(r, OP_EQ, 0); - tt_assert(!msg); + tt_ptr_op(msg, OP_EQ, NULL); /* 300 MB RAM available, DirCache disabled */ r = have_enough_mem_for_dircache(opt, MEGABYTEIFY(300), &msg); @@ -398,12 +398,12 @@ fixed_get_uname(void) "V3AuthVoteDelay 20\n" \ "V3AuthDistDelay 20\n" \ "V3AuthNIntervalsValid 3\n" \ - "ClientUseIPv4 1\n" \ + "ClientUseIPv4 1\n" \ "VirtualAddrNetworkIPv4 127.192.0.0/10\n" \ "VirtualAddrNetworkIPv6 [FE80::]/10\n" \ - "SchedulerHighWaterMark__ 42\n" \ - "SchedulerLowWaterMark__ 10\n" \ - "UseEntryGuards 1\n" + "UseEntryGuards 1\n" \ + "Schedulers Vanilla\n" \ + "ClientDNSRejectInternalAddresses 1\n" typedef struct { or_options_t *old_opt; @@ -430,24 +430,24 @@ get_options_test_data(const char *conf) result->opt->ConnectionPadding = -1; // default must be "auto" rv = config_get_lines(conf, &cl, 1); - tt_assert(rv == 0); + tt_int_op(rv, OP_EQ, 0); rv = config_assign(&options_format, result->opt, cl, 0, &msg); if (msg) { /* Display the parse error message by comparing it with an empty string */ tt_str_op(msg, OP_EQ, ""); } - tt_assert(rv == 0); + tt_int_op(rv, OP_EQ, 0); config_free_lines(cl); result->opt->LogTimeGranularity = 1; result->opt->TokenBucketRefillInterval = 1; rv = config_get_lines(TEST_OPTIONS_OLD_VALUES, &cl, 1); - tt_assert(rv == 0); + tt_int_op(rv, OP_EQ, 0); rv = config_assign(&options_format, result->def_opt, cl, 0, &msg); if (msg) { /* Display the parse error message by comparing it with an empty string */ tt_str_op(msg, OP_EQ, ""); } - tt_assert(rv == 0); + tt_int_op(rv, OP_EQ, 0); done: config_free_lines(cl); @@ -507,7 +507,7 @@ test_options_validate__uname_for_server(void *ignored) fixed_get_uname_result = "Windows 2000"; mock_clean_saved_logs(); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - expect_log_entry(); + expect_no_log_entry(); tor_free(msg); done: @@ -528,6 +528,8 @@ test_options_validate__outbound_addresses(void *ignored) ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); + tt_str_op(msg, OP_EQ, "Multiple outbound bind addresses configured: " + "xxyy!!!sdfaf"); done: free_options_test_data(tdata); @@ -591,13 +593,14 @@ test_options_validate__nickname(void *ignored) tdata = get_options_test_data("Nickname AMoreValidNick"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); - tt_assert(!msg); + tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0"); + tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("DataDirectory /tmp/somewhere"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); - tt_assert(!msg); + tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0"); done: free_options_test_data(tdata); @@ -657,6 +660,7 @@ test_options_validate__logs(void *ignored) tt_str_op(tdata->opt->Logs->key, OP_EQ, "Log"); tt_str_op(tdata->opt->Logs->value, OP_EQ, "notice stdout"); tor_free(msg); + tt_int_op(ret, OP_EQ, -1); free_options_test_data(tdata); tdata = get_options_test_data(""); @@ -667,6 +671,7 @@ test_options_validate__logs(void *ignored) tt_str_op(tdata->opt->Logs->key, OP_EQ, "Log"); tt_str_op(tdata->opt->Logs->value, OP_EQ, "warn stdout"); tor_free(msg); + tt_int_op(ret, OP_EQ, -1); free_options_test_data(tdata); tdata = get_options_test_data(""); @@ -676,6 +681,7 @@ test_options_validate__logs(void *ignored) ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_assert(!tdata->opt->Logs); tor_free(msg); + tt_int_op(ret, OP_EQ, -1); free_options_test_data(tdata); tdata = get_options_test_data(""); @@ -684,6 +690,7 @@ test_options_validate__logs(void *ignored) ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 1, &msg); tt_assert(!tdata->opt->Logs); tor_free(msg); + tt_int_op(ret, OP_EQ, -1); free_options_test_data(tdata); tdata = get_options_test_data(""); @@ -692,6 +699,7 @@ test_options_validate__logs(void *ignored) ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_assert(!tdata->opt->Logs); tor_free(msg); + tt_int_op(ret, OP_EQ, -1); free_options_test_data(tdata); tdata = get_options_test_data(""); @@ -701,6 +709,7 @@ test_options_validate__logs(void *ignored) tdata->opt->Logs = cl; ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op((intptr_t)tdata->opt->Logs, OP_EQ, (intptr_t)cl); + tt_int_op(ret, OP_EQ, -1); done: quiet_level = orig_quiet_level; @@ -747,13 +756,13 @@ test_options_validate__authdir(void *ignored) mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); - tt_assert(!msg); + tt_str_op(msg, OP_EQ, "Authoritative directory servers must set " + "ContactInfo"); + tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("AuthoritativeDirectory 1\n" - "Address 100.200.10.1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "Address 100.200.10.1\n"); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -764,9 +773,7 @@ test_options_validate__authdir(void *ignored) free_options_test_data(tdata); tdata = get_options_test_data("AuthoritativeDirectory 1\n" "Address 100.200.10.1\n" - "TestingTorNetwork 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "TestingTorNetwork 1\n"); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -777,9 +784,7 @@ test_options_validate__authdir(void *ignored) free_options_test_data(tdata); tdata = get_options_test_data("AuthoritativeDirectory 1\n" "Address 100.200.10.1\n" - "ContactInfo hello@hello.com\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ContactInfo hello@hello.com\n"); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -791,9 +796,7 @@ test_options_validate__authdir(void *ignored) tdata = get_options_test_data("AuthoritativeDirectory 1\n" "Address 100.200.10.1\n" "RecommendedVersions 1.2, 3.14\n" - "ContactInfo hello@hello.com\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ContactInfo hello@hello.com\n"); mock_clean_saved_logs(); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_str_op(tdata->opt->RecommendedClientVersions->value, OP_EQ, "1.2, 3.14"); @@ -806,9 +809,7 @@ test_options_validate__authdir(void *ignored) "RecommendedVersions 1.2, 3.14\n" "RecommendedClientVersions 25\n" "RecommendedServerVersions 4.18\n" - "ContactInfo hello@hello.com\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ContactInfo hello@hello.com\n"); mock_clean_saved_logs(); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_str_op(tdata->opt->RecommendedClientVersions->value, OP_EQ, "25"); @@ -822,9 +823,7 @@ test_options_validate__authdir(void *ignored) "RecommendedVersions 1.2, 3.14\n" "RecommendedClientVersions 25\n" "RecommendedServerVersions 4.18\n" - "ContactInfo hello@hello.com\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ContactInfo hello@hello.com\n"); mock_clean_saved_logs(); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_str_op(msg, OP_EQ, "AuthoritativeDir is set, but none of (Bridge/V3)" @@ -836,9 +835,7 @@ test_options_validate__authdir(void *ignored) "Address 100.200.10.1\n" "VersioningAuthoritativeDirectory 1\n" "RecommendedServerVersions 4.18\n" - "ContactInfo hello@hello.com\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ContactInfo hello@hello.com\n"); mock_clean_saved_logs(); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_str_op(msg, OP_EQ, "Versioning authoritative dir servers must set " @@ -850,9 +847,7 @@ test_options_validate__authdir(void *ignored) "Address 100.200.10.1\n" "VersioningAuthoritativeDirectory 1\n" "RecommendedClientVersions 4.18\n" - "ContactInfo hello@hello.com\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ContactInfo hello@hello.com\n"); mock_clean_saved_logs(); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_str_op(msg, OP_EQ, "Versioning authoritative dir servers must set " @@ -863,9 +858,7 @@ test_options_validate__authdir(void *ignored) tdata = get_options_test_data("AuthoritativeDirectory 1\n" "Address 100.200.10.1\n" "UseEntryGuards 1\n" - "ContactInfo hello@hello.com\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ContactInfo hello@hello.com\n"); mock_clean_saved_logs(); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); expect_log_msg("Authoritative directory servers " @@ -877,9 +870,7 @@ test_options_validate__authdir(void *ignored) tdata = get_options_test_data("AuthoritativeDirectory 1\n" "Address 100.200.10.1\n" "V3AuthoritativeDir 1\n" - "ContactInfo hello@hello.com\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ContactInfo hello@hello.com\n"); mock_clean_saved_logs(); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); expect_log_msg("Authoritative directories always try" @@ -892,9 +883,7 @@ test_options_validate__authdir(void *ignored) "Address 100.200.10.1\n" "DownloadExtraInfo 1\n" "V3AuthoritativeDir 1\n" - "ContactInfo hello@hello.com\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ContactInfo hello@hello.com\n"); mock_clean_saved_logs(); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); expect_no_log_msg("Authoritative directories always try" @@ -905,9 +894,7 @@ test_options_validate__authdir(void *ignored) free_options_test_data(tdata); tdata = get_options_test_data("AuthoritativeDirectory 1\n" "Address 100.200.10.1\n" - "ContactInfo hello@hello.com\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ContactInfo hello@hello.com\n"); mock_clean_saved_logs(); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_str_op(msg, OP_EQ, "AuthoritativeDir is set, but none of (Bridge/V3)" @@ -919,9 +906,7 @@ test_options_validate__authdir(void *ignored) "Address 100.200.10.1\n" "BridgeAuthoritativeDir 1\n" "ContactInfo hello@hello.com\n" - "V3BandwidthsFile non-existant-file\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "V3BandwidthsFile non-existant-file\n"); mock_clean_saved_logs(); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_str_op(msg, OP_EQ, @@ -933,9 +918,7 @@ test_options_validate__authdir(void *ignored) "Address 100.200.10.1\n" "BridgeAuthoritativeDir 1\n" "ContactInfo hello@hello.com\n" - "V3BandwidthsFile non-existant-file\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "V3BandwidthsFile non-existant-file\n"); mock_clean_saved_logs(); options_validate(NULL, tdata->opt, tdata->def_opt, 0, &msg); tt_str_op(msg, OP_EQ, @@ -947,9 +930,7 @@ test_options_validate__authdir(void *ignored) "Address 100.200.10.1\n" "BridgeAuthoritativeDir 1\n" "ContactInfo hello@hello.com\n" - "GuardfractionFile non-existant-file\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "GuardfractionFile non-existant-file\n"); mock_clean_saved_logs(); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_str_op(msg, OP_EQ, @@ -961,9 +942,7 @@ test_options_validate__authdir(void *ignored) "Address 100.200.10.1\n" "BridgeAuthoritativeDir 1\n" "ContactInfo hello@hello.com\n" - "GuardfractionFile non-existant-file\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "GuardfractionFile non-existant-file\n"); mock_clean_saved_logs(); options_validate(NULL, tdata->opt, tdata->def_opt, 0, &msg); tt_str_op(msg, OP_EQ, @@ -974,9 +953,7 @@ test_options_validate__authdir(void *ignored) tdata = get_options_test_data("AuthoritativeDirectory 1\n" "Address 100.200.10.1\n" "BridgeAuthoritativeDir 1\n" - "ContactInfo hello@hello.com\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ContactInfo hello@hello.com\n"); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -989,9 +966,7 @@ test_options_validate__authdir(void *ignored) "Address 100.200.10.1\n" "DirPort 999\n" "BridgeAuthoritativeDir 1\n" - "ContactInfo hello@hello.com\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ContactInfo hello@hello.com\n"); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1008,9 +983,7 @@ test_options_validate__authdir(void *ignored) /* "ORPort 888\n" */ /* "ClientOnly 1\n" */ /* "BridgeAuthoritativeDir 1\n" */ - /* "ContactInfo hello@hello.com\n" */ - /* "SchedulerHighWaterMark__ 42\n" */ - /* "SchedulerLowWaterMark__ 10\n"); */ + /* "ContactInfo hello@hello.com\n" ); */ /* mock_clean_saved_logs(); */ /* ret = options_validate(tdata->old_opt, tdata->opt, */ /* tdata->def_opt, 0, &msg); */ @@ -1103,7 +1076,7 @@ test_options_validate__transproxy(void *ignored) tt_int_op(tdata->opt->TransProxyType_parsed, OP_EQ, TPT_PF_DIVERT); tt_str_op(msg, OP_EQ, "Cannot use TransProxyType without " "any valid TransPort."); -#endif +#endif /* !defined(OpenBSD) && !defined( DARWIN ) */ tor_free(msg); // Test tproxy trans proxy @@ -1118,7 +1091,7 @@ test_options_validate__transproxy(void *ignored) tt_int_op(tdata->opt->TransProxyType_parsed, OP_EQ, TPT_TPROXY); tt_str_op(msg, OP_EQ, "Cannot use TransProxyType without any valid " "TransPort."); -#endif +#endif /* !defined(__linux__) */ tor_free(msg); // Test ipfw trans proxy @@ -1134,7 +1107,7 @@ test_options_validate__transproxy(void *ignored) tt_int_op(tdata->opt->TransProxyType_parsed, OP_EQ, TPT_IPFW); tt_str_op(msg, OP_EQ, "Cannot use TransProxyType without any valid " "TransPort."); -#endif +#endif /* !defined(KERNEL_MAY_SUPPORT_IPFW) */ tor_free(msg); // Test unknown trans proxy @@ -1154,46 +1127,41 @@ test_options_validate__transproxy(void *ignored) "TransPort 127.0.0.1:123\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); - if (msg) { - TT_DIE(("Expected NULL but got '%s'", msg)); - } + tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0"); #elif defined(KERNEL_MAY_SUPPORT_IPFW) tdata = get_options_test_data("TransProxyType ipfw\n" "TransPort 127.0.0.1:123\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); - if (msg) { - TT_DIE(("Expected NULL but got '%s'", msg)); - } + tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0"); + tor_free(msg); #elif defined(OpenBSD) tdata = get_options_test_data("TransProxyType pf-divert\n" "TransPort 127.0.0.1:123\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); - if (msg) { - TT_DIE(("Expected NULL but got '%s'", msg)); - } + tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0"); + tor_free(msg); #elif defined(__NetBSD__) tdata = get_options_test_data("TransProxyType default\n" "TransPort 127.0.0.1:123\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); - if (msg) { - TT_DIE(("Expected NULL but got '%s'", msg)); - } -#endif + tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0"); + tor_free(msg); +#endif /* defined(__linux__) || ... */ // Assert that a test has run for some TransProxyType tt_assert(tdata); -#else +#else /* !(defined(USE_TRANSPARENT)) */ tdata = get_options_test_data("TransPort 127.0.0.1:555\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "TransPort is disabled in this build."); tor_free(msg); -#endif +#endif /* defined(USE_TRANSPARENT) */ done: free_options_test_data(tdata); @@ -1258,9 +1226,7 @@ test_options_validate__exclude_nodes(void *ignored) free_options_test_data(tdata); tdata = get_options_test_data("ExcludeNodes {cn}\n" - "StrictNodes 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "StrictNodes 1\n"); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1271,9 +1237,7 @@ test_options_validate__exclude_nodes(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("ExcludeNodes {cn}\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + tdata = get_options_test_data("ExcludeNodes {cn}\n"); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1291,49 +1255,6 @@ test_options_validate__exclude_nodes(void *ignored) } static void -test_options_validate__scheduler(void *ignored) -{ - (void)ignored; - int ret; - char *msg; - setup_capture_of_logs(LOG_DEBUG); - options_test_data_t *tdata = get_options_test_data( - "SchedulerLowWaterMark__ 0\n"); - - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); - expect_log_msg("Bad SchedulerLowWaterMark__ option\n"); - tor_free(msg); - - // TODO: this test cannot run on platforms where UINT32_MAX == UINT64_MAX. - // I suspect it's unlikely this branch can actually happen - /* free_options_test_data(tdata); */ - /* tdata = get_options_test_data( */ - /* "SchedulerLowWaterMark 10000000000000000000\n"); */ - /* tdata->opt->SchedulerLowWaterMark__ = (uint64_t)UINT32_MAX; */ - /* tdata->opt->SchedulerLowWaterMark__++; */ - /* mock_clean_saved_logs(); */ - /* ret = options_validate(tdata->old_opt, tdata->opt, */ - /* tdata->def_opt, 0, &msg); */ - /* tt_int_op(ret, OP_EQ, -1); */ - /* expect_log_msg("Bad SchedulerLowWaterMark__ option\n"); */ - - free_options_test_data(tdata); - tdata = get_options_test_data("SchedulerLowWaterMark__ 42\n" - "SchedulerHighWaterMark__ 42\n"); - mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); - expect_log_msg("Bad SchedulerHighWaterMark option\n"); - tor_free(msg); - - done: - teardown_capture_of_logs(); - free_options_test_data(tdata); - tor_free(msg); -} - -static void test_options_validate__node_families(void *ignored) { (void)ignored; @@ -1341,9 +1262,7 @@ test_options_validate__node_families(void *ignored) char *msg; options_test_data_t *tdata = get_options_test_data( "NodeFamily flux, flax\n" - "NodeFamily somewhere\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "NodeFamily somewhere\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1361,8 +1280,7 @@ test_options_validate__node_families(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + tdata = get_options_test_data(""); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1370,9 +1288,7 @@ test_options_validate__node_families(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("NodeFamily !flux\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + tdata = get_options_test_data("NodeFamily !flux\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1421,9 +1337,7 @@ test_options_validate__recommended_packages(void *ignored) setup_capture_of_logs(LOG_WARN); options_test_data_t *tdata = get_options_test_data( "RecommendedPackages foo 1.2 http://foo.com sha1=123123123123\n" - "RecommendedPackages invalid-package-line\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "RecommendedPackages invalid-package-line\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1445,9 +1359,7 @@ test_options_validate__fetch_dir(void *ignored) char *msg; options_test_data_t *tdata = get_options_test_data( "FetchDirInfoExtraEarly 1\n" - "FetchDirInfoEarly 0\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "FetchDirInfoEarly 0\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1457,9 +1369,7 @@ test_options_validate__fetch_dir(void *ignored) free_options_test_data(tdata); tdata = get_options_test_data("FetchDirInfoExtraEarly 1\n" - "FetchDirInfoEarly 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "FetchDirInfoEarly 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1479,9 +1389,7 @@ test_options_validate__conn_limit(void *ignored) int ret; char *msg; options_test_data_t *tdata = get_options_test_data( - "ConnLimit 0\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ConnLimit 0\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1489,9 +1397,7 @@ test_options_validate__conn_limit(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("ConnLimit 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + tdata = get_options_test_data("ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1513,9 +1419,7 @@ test_options_validate__paths_needed(void *ignored) setup_capture_of_logs(LOG_WARN); options_test_data_t *tdata = get_options_test_data( "PathsNeededToBuildCircuits 0.1\n" - "ConnLimit 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1528,9 +1432,7 @@ test_options_validate__paths_needed(void *ignored) free_options_test_data(tdata); mock_clean_saved_logs(); tdata = get_options_test_data("PathsNeededToBuildCircuits 0.99\n" - "ConnLimit 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1543,9 +1445,7 @@ test_options_validate__paths_needed(void *ignored) free_options_test_data(tdata); mock_clean_saved_logs(); tdata = get_options_test_data("PathsNeededToBuildCircuits 0.91\n" - "ConnLimit 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1568,9 +1468,7 @@ test_options_validate__max_client_circuits(void *ignored) char *msg; options_test_data_t *tdata = get_options_test_data( "MaxClientCircuitsPending 0\n" - "ConnLimit 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1580,9 +1478,7 @@ test_options_validate__max_client_circuits(void *ignored) free_options_test_data(tdata); tdata = get_options_test_data("MaxClientCircuitsPending 1025\n" - "ConnLimit 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1592,9 +1488,7 @@ test_options_validate__max_client_circuits(void *ignored) free_options_test_data(tdata); tdata = get_options_test_data("MaxClientCircuitsPending 1\n" - "ConnLimit 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1615,9 +1509,7 @@ test_options_validate__ports(void *ignored) options_test_data_t *tdata = get_options_test_data( "FirewallPorts 65537\n" "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1628,9 +1520,7 @@ test_options_validate__ports(void *ignored) tdata = get_options_test_data("FirewallPorts 1\n" "LongLivedPorts 124444\n" "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1642,9 +1532,7 @@ test_options_validate__ports(void *ignored) "LongLivedPorts 2\n" "RejectPlaintextPorts 112233\n" "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1657,9 +1545,7 @@ test_options_validate__ports(void *ignored) "RejectPlaintextPorts 3\n" "WarnPlaintextPorts 65536\n" "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1672,9 +1558,7 @@ test_options_validate__ports(void *ignored) "RejectPlaintextPorts 3\n" "WarnPlaintextPorts 4\n" "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1696,9 +1580,7 @@ test_options_validate__reachable_addresses(void *ignored) options_test_data_t *tdata = get_options_test_data( "FascistFirewall 1\n" "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1716,9 +1598,7 @@ test_options_validate__reachable_addresses(void *ignored) "ReachableDirAddresses *:81\n" "ReachableORAddresses *:444\n" "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ConnLimit 1\n"); tdata->opt->FirewallPorts = smartlist_new(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1732,9 +1612,7 @@ test_options_validate__reachable_addresses(void *ignored) tdata = get_options_test_data("FascistFirewall 1\n" "FirewallPort 123\n" "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1751,9 +1629,7 @@ test_options_validate__reachable_addresses(void *ignored) "ReachableAddresses *:83\n" "ReachableAddresses reject *:*\n" "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1769,9 +1645,7 @@ test_options_validate__reachable_addresses(void *ignored) tdata = get_options_test_data("ReachableAddresses *:82\n" "ORPort 127.0.0.1:5555\n" "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1782,9 +1656,7 @@ test_options_validate__reachable_addresses(void *ignored) tdata = get_options_test_data("ReachableORAddresses *:82\n" "ORPort 127.0.0.1:5555\n" "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1795,9 +1667,7 @@ test_options_validate__reachable_addresses(void *ignored) tdata = get_options_test_data("ReachableDirAddresses *:82\n" "ORPort 127.0.0.1:5555\n" "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1808,9 +1678,7 @@ test_options_validate__reachable_addresses(void *ignored) tdata = get_options_test_data("ClientUseIPv4 0\n" "ORPort 127.0.0.1:5555\n" "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1908,9 +1776,7 @@ test_options_validate__use_bridges(void *ignored) "ClientUseIPv4 1\n" "ORPort 127.0.0.1:5555\n" "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1921,9 +1787,7 @@ test_options_validate__use_bridges(void *ignored) free_options_test_data(tdata); tdata = get_options_test_data("UseBridges 1\n" "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1936,9 +1800,7 @@ test_options_validate__use_bridges(void *ignored) tdata = get_options_test_data("UseBridges 1\n" "EntryNodes {cn}\n" "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -1998,9 +1860,7 @@ test_options_validate__entry_nodes(void *ignored) "EntryNodes {cn}\n" "UseEntryGuards 0\n" "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -2012,9 +1872,7 @@ test_options_validate__entry_nodes(void *ignored) tdata = get_options_test_data("EntryNodes {cn}\n" "UseEntryGuards 1\n" "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -2035,9 +1893,7 @@ test_options_validate__safe_logging(void *ignored) char *msg; options_test_data_t *tdata = get_options_test_data( "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -2047,9 +1903,7 @@ test_options_validate__safe_logging(void *ignored) free_options_test_data(tdata); tdata = get_options_test_data("SafeLogging 0\n" "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -2059,9 +1913,7 @@ test_options_validate__safe_logging(void *ignored) free_options_test_data(tdata); tdata = get_options_test_data("SafeLogging Relay\n" "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -2071,9 +1923,7 @@ test_options_validate__safe_logging(void *ignored) free_options_test_data(tdata); tdata = get_options_test_data("SafeLogging 1\n" "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -2083,9 +1933,7 @@ test_options_validate__safe_logging(void *ignored) free_options_test_data(tdata); tdata = get_options_test_data("SafeLogging stuffy\n" "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n" - "SchedulerHighWaterMark__ 42\n" - "SchedulerLowWaterMark__ 10\n"); + "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -2230,6 +2078,7 @@ test_options_validate__testing(void *ignored) ENSURE_DEFAULT(TestingServerConsensusDownloadSchedule, 3000); ENSURE_DEFAULT(TestingClientConsensusDownloadSchedule, 3000); ENSURE_DEFAULT(TestingBridgeDownloadSchedule, 3000); + ENSURE_DEFAULT(TestingBridgeBootstrapDownloadSchedule, 3000); ENSURE_DEFAULT(TestingClientMaxIntervalWithoutRequest, 3000); ENSURE_DEFAULT(TestingDirConnectionMaxStall, 3000); ENSURE_DEFAULT(TestingConsensusMaxDownloadTries, 3000); @@ -3501,7 +3350,7 @@ test_options_validate__control(void *ignored) "can reconfigure your Tor. That's bad! You should upgrade your " "Tor controller as soon as possible.\n"); tor_free(msg); -#endif +#endif /* defined(HAVE_SYS_UN_H) */ free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES @@ -4413,7 +4262,6 @@ struct testcase_t options_tests[] = { LOCAL_VALIDATE_TEST(relay_with_hidden_services), LOCAL_VALIDATE_TEST(transproxy), LOCAL_VALIDATE_TEST(exclude_nodes), - LOCAL_VALIDATE_TEST(scheduler), LOCAL_VALIDATE_TEST(node_families), LOCAL_VALIDATE_TEST(token_bucket), LOCAL_VALIDATE_TEST(recommended_packages), diff --git a/src/test/test_policy.c b/src/test/test_policy.c index 1b2fac4325..83dca2d431 100644 --- a/src/test/test_policy.c +++ b/src/test/test_policy.c @@ -59,7 +59,7 @@ test_policy_summary_helper_family_flags(const char *policy_str, summary = policy_summarize(policy, family); - tt_assert(summary != NULL); + tt_ptr_op(summary, OP_NE, NULL); tt_str_op(summary,OP_EQ, expected_summary); short_policy = parse_short_policy(summary); @@ -147,7 +147,7 @@ test_policies_general(void *arg) p = router_parse_addr_policy_item_from_string("reject 192.168.0.0/16:*", -1, &malformed_list); - tt_assert(p != NULL); + tt_ptr_op(p, OP_NE, NULL); tt_int_op(ADDR_POLICY_REJECT,OP_EQ, p->policy_type); tor_addr_from_ipv4h(&tar, 0xc0a80000u); tt_int_op(0,OP_EQ, tor_addr_compare(&p->addr, &tar, CMP_EXACT)); @@ -192,75 +192,75 @@ test_policies_general(void *arg) policy3 = smartlist_new(); p = router_parse_addr_policy_item_from_string("reject *:*", -1, &malformed_list); - tt_assert(p != NULL); + tt_ptr_op(p, OP_NE, NULL); smartlist_add(policy3, p); p = router_parse_addr_policy_item_from_string("accept *:*", -1, &malformed_list); - tt_assert(p != NULL); + tt_ptr_op(p, OP_NE, NULL); smartlist_add(policy3, p); policy4 = smartlist_new(); p = router_parse_addr_policy_item_from_string("accept *:443", -1, &malformed_list); - tt_assert(p != NULL); + tt_ptr_op(p, OP_NE, NULL); smartlist_add(policy4, p); p = router_parse_addr_policy_item_from_string("accept *:443", -1, &malformed_list); - tt_assert(p != NULL); + tt_ptr_op(p, OP_NE, NULL); smartlist_add(policy4, p); policy5 = smartlist_new(); p = router_parse_addr_policy_item_from_string("reject 0.0.0.0/8:*", -1, &malformed_list); - tt_assert(p != NULL); + tt_ptr_op(p, OP_NE, NULL); smartlist_add(policy5, p); p = router_parse_addr_policy_item_from_string("reject 169.254.0.0/16:*", -1, &malformed_list); - tt_assert(p != NULL); + tt_ptr_op(p, OP_NE, NULL); smartlist_add(policy5, p); p = router_parse_addr_policy_item_from_string("reject 127.0.0.0/8:*", -1, &malformed_list); - tt_assert(p != NULL); + tt_ptr_op(p, OP_NE, NULL); smartlist_add(policy5, p); p = router_parse_addr_policy_item_from_string("reject 192.168.0.0/16:*", -1, &malformed_list); - tt_assert(p != NULL); + tt_ptr_op(p, OP_NE, NULL); smartlist_add(policy5, p); p = router_parse_addr_policy_item_from_string("reject 10.0.0.0/8:*", -1, &malformed_list); - tt_assert(p != NULL); + tt_ptr_op(p, OP_NE, NULL); smartlist_add(policy5, p); p = router_parse_addr_policy_item_from_string("reject 172.16.0.0/12:*", -1, &malformed_list); - tt_assert(p != NULL); + tt_ptr_op(p, OP_NE, NULL); smartlist_add(policy5, p); p = router_parse_addr_policy_item_from_string("reject 80.190.250.90:*", -1, &malformed_list); - tt_assert(p != NULL); + tt_ptr_op(p, OP_NE, NULL); smartlist_add(policy5, p); p = router_parse_addr_policy_item_from_string("reject *:1-65534", -1, &malformed_list); - tt_assert(p != NULL); + tt_ptr_op(p, OP_NE, NULL); smartlist_add(policy5, p); p = router_parse_addr_policy_item_from_string("reject *:65535", -1, &malformed_list); - tt_assert(p != NULL); + tt_ptr_op(p, OP_NE, NULL); smartlist_add(policy5, p); p = router_parse_addr_policy_item_from_string("accept *:1-65535", -1, &malformed_list); - tt_assert(p != NULL); + tt_ptr_op(p, OP_NE, NULL); smartlist_add(policy5, p); policy6 = smartlist_new(); p = router_parse_addr_policy_item_from_string("accept 43.3.0.0/9:*", -1, &malformed_list); - tt_assert(p != NULL); + tt_ptr_op(p, OP_NE, NULL); smartlist_add(policy6, p); policy7 = smartlist_new(); p = router_parse_addr_policy_item_from_string("accept 0.0.0.0/8:*", -1, &malformed_list); - tt_assert(p != NULL); + tt_ptr_op(p, OP_NE, NULL); smartlist_add(policy7, p); tt_int_op(0, OP_EQ, policies_parse_exit_policy(NULL, &policy8, @@ -282,13 +282,13 @@ test_policies_general(void *arg) policy10 = smartlist_new(); p = router_parse_addr_policy_item_from_string("accept6 *:*", -1, &malformed_list); - tt_assert(p != NULL); + tt_ptr_op(p, OP_NE, NULL); smartlist_add(policy10, p); policy11 = smartlist_new(); p = router_parse_addr_policy_item_from_string("reject6 *:*", -1, &malformed_list); - tt_assert(p != NULL); + tt_ptr_op(p, OP_NE, NULL); smartlist_add(policy11, p); tt_assert(!exit_policy_is_general_exit(policy)); @@ -392,21 +392,21 @@ test_policies_general(void *arg) p = router_parse_addr_policy_item_from_string("acce::abcd", ADDR_POLICY_ACCEPT, &malformed_list); - tt_assert(!p); + tt_ptr_op(p, OP_EQ, NULL); tt_assert(malformed_list); malformed_list = 0; p = router_parse_addr_policy_item_from_string("7:1234", ADDR_POLICY_ACCEPT, &malformed_list); - tt_assert(!p); + tt_ptr_op(p, OP_EQ, NULL); tt_assert(malformed_list); malformed_list = 0; p = router_parse_addr_policy_item_from_string("::", ADDR_POLICY_ACCEPT, &malformed_list); - tt_assert(!p); + tt_ptr_op(p, OP_EQ, NULL); tt_assert(malformed_list); malformed_list = 0; @@ -968,63 +968,63 @@ test_policies_general(void *arg) /* Make sure that IPv4 addresses are ignored in accept6/reject6 lines. */ p = router_parse_addr_policy_item_from_string("accept6 1.2.3.4:*", -1, &malformed_list); - tt_assert(p == NULL); + tt_ptr_op(p, OP_EQ, NULL); tt_assert(!malformed_list); p = router_parse_addr_policy_item_from_string("reject6 2.4.6.0/24:*", -1, &malformed_list); - tt_assert(p == NULL); + tt_ptr_op(p, OP_EQ, NULL); tt_assert(!malformed_list); p = router_parse_addr_policy_item_from_string("accept6 *4:*", -1, &malformed_list); - tt_assert(p == NULL); + tt_ptr_op(p, OP_EQ, NULL); tt_assert(!malformed_list); /* Make sure malformed policies are detected as such. */ p = router_parse_addr_policy_item_from_string("bad_token *4:*", -1, &malformed_list); - tt_assert(p == NULL); + tt_ptr_op(p, OP_EQ, NULL); tt_assert(malformed_list); p = router_parse_addr_policy_item_from_string("accept6 **:*", -1, &malformed_list); - tt_assert(p == NULL); + tt_ptr_op(p, OP_EQ, NULL); tt_assert(malformed_list); p = router_parse_addr_policy_item_from_string("accept */15:*", -1, &malformed_list); - tt_assert(p == NULL); + tt_ptr_op(p, OP_EQ, NULL); tt_assert(malformed_list); p = router_parse_addr_policy_item_from_string("reject6 */:*", -1, &malformed_list); - tt_assert(p == NULL); + tt_ptr_op(p, OP_EQ, NULL); tt_assert(malformed_list); p = router_parse_addr_policy_item_from_string("accept 127.0.0.1/33:*", -1, &malformed_list); - tt_assert(p == NULL); + tt_ptr_op(p, OP_EQ, NULL); tt_assert(malformed_list); p = router_parse_addr_policy_item_from_string("accept6 [::1]/129:*", -1, &malformed_list); - tt_assert(p == NULL); + tt_ptr_op(p, OP_EQ, NULL); tt_assert(malformed_list); p = router_parse_addr_policy_item_from_string("reject 8.8.8.8/-1:*", -1, &malformed_list); - tt_assert(p == NULL); + tt_ptr_op(p, OP_EQ, NULL); tt_assert(malformed_list); p = router_parse_addr_policy_item_from_string("reject 8.8.4.4:10-5", -1, &malformed_list); - tt_assert(p == NULL); + tt_ptr_op(p, OP_EQ, NULL); tt_assert(malformed_list); p = router_parse_addr_policy_item_from_string("reject 1.2.3.4:-1", -1, &malformed_list); - tt_assert(p == NULL); + tt_ptr_op(p, OP_EQ, NULL); tt_assert(malformed_list); /* Test a too-long policy. */ @@ -1148,7 +1148,7 @@ test_policies_reject_exit_address(void *arg) /* test that IPv4 addresses are rejected on an IPv4-only exit */ policies_parse_exit_policy_reject_private(&policy, 0, ipv4_list, 0, 0); tt_assert(policy); - tt_assert(smartlist_len(policy) == 1); + tt_int_op(smartlist_len(policy), OP_EQ, 1); tt_assert(test_policy_has_address_helper(policy, &ipv4_addr)); addr_policy_list_free(policy); policy = NULL; @@ -1158,12 +1158,12 @@ test_policies_reject_exit_address(void *arg) * on IPv4-only exits, so policies_parse_exit_policy_reject_private doesn't * need to do anything) */ policies_parse_exit_policy_reject_private(&policy, 0, ipv6_list, 0, 0); - tt_assert(policy == NULL); + tt_ptr_op(policy, OP_EQ, NULL); /* test that only IPv4 addresses are rejected on an IPv4-only exit */ policies_parse_exit_policy_reject_private(&policy, 0, both_list, 0, 0); tt_assert(policy); - tt_assert(smartlist_len(policy) == 1); + tt_int_op(smartlist_len(policy), OP_EQ, 1); tt_assert(test_policy_has_address_helper(policy, &ipv4_addr)); addr_policy_list_free(policy); policy = NULL; @@ -1171,7 +1171,7 @@ test_policies_reject_exit_address(void *arg) /* Test that lists with duplicate entries produce the same results */ policies_parse_exit_policy_reject_private(&policy, 0, dupl_list, 0, 0); tt_assert(policy); - tt_assert(smartlist_len(policy) == 1); + tt_int_op(smartlist_len(policy), OP_EQ, 1); tt_assert(test_policy_has_address_helper(policy, &ipv4_addr)); addr_policy_list_free(policy); policy = NULL; @@ -1181,7 +1181,7 @@ test_policies_reject_exit_address(void *arg) /* test that IPv4 addresses are rejected on an IPv4/IPv6 exit */ policies_parse_exit_policy_reject_private(&policy, 1, ipv4_list, 0, 0); tt_assert(policy); - tt_assert(smartlist_len(policy) == 1); + tt_int_op(smartlist_len(policy), OP_EQ, 1); tt_assert(test_policy_has_address_helper(policy, &ipv4_addr)); addr_policy_list_free(policy); policy = NULL; @@ -1189,7 +1189,7 @@ test_policies_reject_exit_address(void *arg) /* test that IPv6 addresses are rejected on an IPv4/IPv6 exit */ policies_parse_exit_policy_reject_private(&policy, 1, ipv6_list, 0, 0); tt_assert(policy); - tt_assert(smartlist_len(policy) == 1); + tt_int_op(smartlist_len(policy), OP_EQ, 1); tt_assert(test_policy_has_address_helper(policy, &ipv6_addr)); addr_policy_list_free(policy); policy = NULL; @@ -1197,7 +1197,7 @@ test_policies_reject_exit_address(void *arg) /* test that IPv4 and IPv6 addresses are rejected on an IPv4/IPv6 exit */ policies_parse_exit_policy_reject_private(&policy, 1, both_list, 0, 0); tt_assert(policy); - tt_assert(smartlist_len(policy) == 2); + tt_int_op(smartlist_len(policy), OP_EQ, 2); tt_assert(test_policy_has_address_helper(policy, &ipv4_addr)); tt_assert(test_policy_has_address_helper(policy, &ipv6_addr)); addr_policy_list_free(policy); @@ -1206,7 +1206,7 @@ test_policies_reject_exit_address(void *arg) /* Test that lists with duplicate entries produce the same results */ policies_parse_exit_policy_reject_private(&policy, 1, dupl_list, 0, 0); tt_assert(policy); - tt_assert(smartlist_len(policy) == 2); + tt_int_op(smartlist_len(policy), OP_EQ, 2); tt_assert(test_policy_has_address_helper(policy, &ipv4_addr)); tt_assert(test_policy_has_address_helper(policy, &ipv6_addr)); addr_policy_list_free(policy); @@ -1258,7 +1258,7 @@ test_policies_reject_port_address(void *arg) * with IPv6 addresses on IPv4-only exits) */ policies_parse_exit_policy_reject_private(&policy, 0, NULL, 0, 1); tt_assert(policy); - tt_assert(smartlist_len(policy) == 1); + tt_int_op(smartlist_len(policy), OP_EQ, 1); tt_assert(test_policy_has_address_helper(policy, &ipv4_port->addr)); addr_policy_list_free(policy); policy = NULL; @@ -1266,7 +1266,7 @@ test_policies_reject_port_address(void *arg) /* test that IPv4 and IPv6 ports are rejected on an IPv4/IPv6 exit */ policies_parse_exit_policy_reject_private(&policy, 1, NULL, 0, 1); tt_assert(policy); - tt_assert(smartlist_len(policy) == 2); + tt_int_op(smartlist_len(policy), OP_EQ, 2); tt_assert(test_policy_has_address_helper(policy, &ipv4_port->addr)); tt_assert(test_policy_has_address_helper(policy, &ipv6_port->addr)); addr_policy_list_free(policy); @@ -1337,7 +1337,7 @@ test_policies_reject_interface_address(void *arg) /* test that no addresses are rejected when none are supplied/requested */ policies_parse_exit_policy_reject_private(&policy, 0, NULL, 0, 0); - tt_assert(policy == NULL); + tt_ptr_op(policy, OP_EQ, NULL); /* test that only IPv4 interface addresses are rejected on an IPv4-only exit * (and allow for duplicates) @@ -1372,7 +1372,7 @@ test_policies_reject_interface_address(void *arg) /* test that no addresses are rejected when none are supplied/requested */ policies_parse_exit_policy_reject_private(&policy, 0, NULL, 0, 0); - tt_assert(policy == NULL); + tt_ptr_op(policy, OP_EQ, NULL); /* test that only IPv4 interface addresses are rejected on an IPv4-only exit */ @@ -1528,15 +1528,15 @@ test_policies_getinfo_helper_policies(void *arg) memset(&mock_my_routerinfo, 0, sizeof(mock_my_routerinfo)); rv = getinfo_helper_policies(NULL, "exit-policy/default", &answer, &errmsg); - tt_assert(rv == 0); - tt_assert(answer != NULL); + tt_int_op(rv, OP_EQ, 0); + tt_ptr_op(answer, OP_NE, NULL); tt_assert(strlen(answer) > 0); tor_free(answer); rv = getinfo_helper_policies(NULL, "exit-policy/reject-private/default", &answer, &errmsg); - tt_assert(rv == 0); - tt_assert(answer != NULL); + tt_int_op(rv, OP_EQ, 0); + tt_ptr_op(answer, OP_NE, NULL); tt_assert(strlen(answer) > 0); tor_free(answer); @@ -1550,15 +1550,15 @@ test_policies_getinfo_helper_policies(void *arg) rv = getinfo_helper_policies(NULL, "exit-policy/reject-private/relay", &answer, &errmsg); - tt_assert(rv == 0); - tt_assert(answer != NULL); + tt_int_op(rv, OP_EQ, 0); + tt_ptr_op(answer, OP_NE, NULL); tt_assert(strlen(answer) == 0); tor_free(answer); rv = getinfo_helper_policies(NULL, "exit-policy/ipv4", &answer, &errmsg); - tt_assert(rv == 0); - tt_assert(answer != NULL); + tt_int_op(rv, OP_EQ, 0); + tt_ptr_op(answer, OP_NE, NULL); ipv4_len = strlen(answer); tt_assert(ipv4_len == 0 || ipv4_len == strlen(DEFAULT_POLICY_STRING)); tt_assert(ipv4_len == 0 || !strcasecmp(answer, DEFAULT_POLICY_STRING)); @@ -1566,8 +1566,8 @@ test_policies_getinfo_helper_policies(void *arg) rv = getinfo_helper_policies(NULL, "exit-policy/ipv6", &answer, &errmsg); - tt_assert(rv == 0); - tt_assert(answer != NULL); + tt_int_op(rv, OP_EQ, 0); + tt_ptr_op(answer, OP_NE, NULL); ipv6_len = strlen(answer); tt_assert(ipv6_len == 0 || ipv6_len == strlen(DEFAULT_POLICY_STRING)); tt_assert(ipv6_len == 0 || !strcasecmp(answer, DEFAULT_POLICY_STRING)); @@ -1575,8 +1575,8 @@ test_policies_getinfo_helper_policies(void *arg) rv = getinfo_helper_policies(NULL, "exit-policy/full", &answer, &errmsg); - tt_assert(rv == 0); - tt_assert(answer != NULL); + tt_int_op(rv, OP_EQ, 0); + tt_ptr_op(answer, OP_NE, NULL); /* It's either empty or it's the default */ tt_assert(strlen(answer) == 0 || !strcasecmp(answer, DEFAULT_POLICY_STRING)); tor_free(answer); @@ -1599,8 +1599,8 @@ test_policies_getinfo_helper_policies(void *arg) rv = getinfo_helper_policies(NULL, "exit-policy/reject-private/relay", &answer, &errmsg); - tt_assert(rv == 0); - tt_assert(answer != NULL); + tt_int_op(rv, OP_EQ, 0); + tt_ptr_op(answer, OP_NE, NULL); tt_assert(strlen(answer) > 0); tor_free(answer); @@ -1609,8 +1609,8 @@ test_policies_getinfo_helper_policies(void *arg) rv = getinfo_helper_policies(NULL, "exit-policy/reject-private/relay", &answer, &errmsg); - tt_assert(rv == 0); - tt_assert(answer != NULL); + tt_int_op(rv, OP_EQ, 0); + tt_ptr_op(answer, OP_NE, NULL); tt_assert(strlen(answer) > 0); tor_free(answer); @@ -1619,8 +1619,8 @@ test_policies_getinfo_helper_policies(void *arg) rv = getinfo_helper_policies(NULL, "exit-policy/reject-private/relay", &answer, &errmsg); - tt_assert(rv == 0); - tt_assert(answer != NULL); + tt_int_op(rv, OP_EQ, 0); + tt_ptr_op(answer, OP_NE, NULL); tt_assert(strlen(answer) > 0); tor_free(answer); @@ -1629,31 +1629,31 @@ test_policies_getinfo_helper_policies(void *arg) rv = getinfo_helper_policies(NULL, "exit-policy/reject-private/relay", &answer, &errmsg); - tt_assert(rv == 0); - tt_assert(answer != NULL); + tt_int_op(rv, OP_EQ, 0); + tt_ptr_op(answer, OP_NE, NULL); tt_assert(strlen(answer) == 0); tor_free(answer); rv = getinfo_helper_policies(NULL, "exit-policy/ipv4", &answer, &errmsg); - tt_assert(rv == 0); - tt_assert(answer != NULL); + tt_int_op(rv, OP_EQ, 0); + tt_ptr_op(answer, OP_NE, NULL); ipv4_len = strlen(answer); tt_assert(ipv4_len > 0); tor_free(answer); rv = getinfo_helper_policies(NULL, "exit-policy/ipv6", &answer, &errmsg); - tt_assert(rv == 0); - tt_assert(answer != NULL); + tt_int_op(rv, OP_EQ, 0); + tt_ptr_op(answer, OP_NE, NULL); ipv6_len = strlen(answer); tt_assert(ipv6_len > 0); tor_free(answer); rv = getinfo_helper_policies(NULL, "exit-policy/full", &answer, &errmsg); - tt_assert(rv == 0); - tt_assert(answer != NULL); + tt_int_op(rv, OP_EQ, 0); + tt_ptr_op(answer, OP_NE, NULL); tt_assert(strlen(answer) > 0); tt_assert(strlen(answer) == ipv4_len + ipv6_len + 1); tor_free(answer); @@ -1746,34 +1746,34 @@ test_policies_fascist_firewall_allows_address(void *arg) mock_options.ClientUseIPv6 = 1; mock_options.UseBridges = 0; - tt_assert(fascist_firewall_allows_address(&ipv4_addr, port, policy, 0, 0) - == 1); - tt_assert(fascist_firewall_allows_address(&ipv6_addr, port, policy, 0, 0) - == 1); - tt_assert(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 0, 0) - == 0); - tt_assert(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 0, 0) - == 0); + tt_int_op(fascist_firewall_allows_address(&ipv4_addr, port, policy, 0, 0), + OP_EQ, 1); + tt_int_op(fascist_firewall_allows_address(&ipv6_addr, port, policy, 0, 0), + OP_EQ, 1); + tt_int_op(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 0, 0), + OP_EQ, 0); + tt_int_op(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 0, 0), + OP_EQ, 0); /* Preferring IPv4 */ - tt_assert(fascist_firewall_allows_address(&ipv4_addr, port, policy, 1, 0) - == 1); - tt_assert(fascist_firewall_allows_address(&ipv6_addr, port, policy, 1, 0) - == 0); - tt_assert(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 1, 0) - == 0); - tt_assert(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 1, 0) - == 0); + tt_int_op(fascist_firewall_allows_address(&ipv4_addr, port, policy, 1, 0), + OP_EQ, 1); + tt_int_op(fascist_firewall_allows_address(&ipv6_addr, port, policy, 1, 0), + OP_EQ, 0); + tt_int_op(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 1, 0), + OP_EQ, 0); + tt_int_op(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 1, 0), + OP_EQ, 0); /* Preferring IPv6 */ - tt_assert(fascist_firewall_allows_address(&ipv4_addr, port, policy, 1, 1) - == 0); - tt_assert(fascist_firewall_allows_address(&ipv6_addr, port, policy, 1, 1) - == 1); - tt_assert(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 1, 1) - == 0); - tt_assert(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 1, 1) - == 0); + tt_int_op(fascist_firewall_allows_address(&ipv4_addr, port, policy, 1, 1), + OP_EQ, 0); + tt_int_op(fascist_firewall_allows_address(&ipv6_addr, port, policy, 1, 1), + OP_EQ, 1); + tt_int_op(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 1, 1), + OP_EQ, 0); + tt_int_op(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 1, 1), + OP_EQ, 0); /* Test the function's address matching with UseBridges on */ memset(&mock_options, 0, sizeof(or_options_t)); @@ -1781,46 +1781,46 @@ test_policies_fascist_firewall_allows_address(void *arg) mock_options.ClientUseIPv6 = 1; mock_options.UseBridges = 1; - tt_assert(fascist_firewall_allows_address(&ipv4_addr, port, policy, 0, 0) - == 1); - tt_assert(fascist_firewall_allows_address(&ipv6_addr, port, policy, 0, 0) - == 1); - tt_assert(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 0, 0) - == 0); - tt_assert(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 0, 0) - == 0); + tt_int_op(fascist_firewall_allows_address(&ipv4_addr, port, policy, 0, 0), + OP_EQ, 1); + tt_int_op(fascist_firewall_allows_address(&ipv6_addr, port, policy, 0, 0), + OP_EQ, 1); + tt_int_op(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 0, 0), + OP_EQ, 0); + tt_int_op(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 0, 0), + OP_EQ, 0); /* Preferring IPv4 */ - tt_assert(fascist_firewall_allows_address(&ipv4_addr, port, policy, 1, 0) - == 1); - tt_assert(fascist_firewall_allows_address(&ipv6_addr, port, policy, 1, 0) - == 0); - tt_assert(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 1, 0) - == 0); - tt_assert(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 1, 0) - == 0); + tt_int_op(fascist_firewall_allows_address(&ipv4_addr, port, policy, 1, 0), + OP_EQ, 1); + tt_int_op(fascist_firewall_allows_address(&ipv6_addr, port, policy, 1, 0), + OP_EQ, 0); + tt_int_op(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 1, 0), + OP_EQ, 0); + tt_int_op(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 1, 0), + OP_EQ, 0); /* Preferring IPv6 */ - tt_assert(fascist_firewall_allows_address(&ipv4_addr, port, policy, 1, 1) - == 0); - tt_assert(fascist_firewall_allows_address(&ipv6_addr, port, policy, 1, 1) - == 1); - tt_assert(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 1, 1) - == 0); - tt_assert(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 1, 1) - == 0); + tt_int_op(fascist_firewall_allows_address(&ipv4_addr, port, policy, 1, 1), + OP_EQ, 0); + tt_int_op(fascist_firewall_allows_address(&ipv6_addr, port, policy, 1, 1), + OP_EQ, 1); + tt_int_op(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 1, 1), + OP_EQ, 0); + tt_int_op(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 1, 1), + OP_EQ, 0); /* bridge clients always use IPv6, regardless of ClientUseIPv6 */ mock_options.ClientUseIPv4 = 1; mock_options.ClientUseIPv6 = 0; - tt_assert(fascist_firewall_allows_address(&ipv4_addr, port, policy, 0, 0) - == 1); - tt_assert(fascist_firewall_allows_address(&ipv6_addr, port, policy, 0, 0) - == 1); - tt_assert(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 0, 0) - == 0); - tt_assert(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 0, 0) - == 0); + tt_int_op(fascist_firewall_allows_address(&ipv4_addr, port, policy, 0, 0), + OP_EQ, 1); + tt_int_op(fascist_firewall_allows_address(&ipv6_addr, port, policy, 0, 0), + OP_EQ, 1); + tt_int_op(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 0, 0), + OP_EQ, 0); + tt_int_op(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 0, 0), + OP_EQ, 0); /* Test the function's address matching with IPv4 on */ memset(&mock_options, 0, sizeof(or_options_t)); @@ -1828,14 +1828,14 @@ test_policies_fascist_firewall_allows_address(void *arg) mock_options.ClientUseIPv6 = 0; mock_options.UseBridges = 0; - tt_assert(fascist_firewall_allows_address(&ipv4_addr, port, policy, 0, 0) - == 1); - tt_assert(fascist_firewall_allows_address(&ipv6_addr, port, policy, 0, 0) - == 0); - tt_assert(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 0, 0) - == 0); - tt_assert(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 0, 0) - == 0); + tt_int_op(fascist_firewall_allows_address(&ipv4_addr, port, policy, 0, 0), + OP_EQ, 1); + tt_int_op(fascist_firewall_allows_address(&ipv6_addr, port, policy, 0, 0), + OP_EQ, 0); + tt_int_op(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 0, 0), + OP_EQ, 0); + tt_int_op(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 0, 0), + OP_EQ, 0); /* Test the function's address matching with IPv6 on */ memset(&mock_options, 0, sizeof(or_options_t)); @@ -1843,14 +1843,14 @@ test_policies_fascist_firewall_allows_address(void *arg) mock_options.ClientUseIPv6 = 1; mock_options.UseBridges = 0; - tt_assert(fascist_firewall_allows_address(&ipv4_addr, port, policy, 0, 0) - == 0); - tt_assert(fascist_firewall_allows_address(&ipv6_addr, port, policy, 0, 0) - == 1); - tt_assert(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 0, 0) - == 0); - tt_assert(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 0, 0) - == 0); + tt_int_op(fascist_firewall_allows_address(&ipv4_addr, port, policy, 0, 0), + OP_EQ, 0); + tt_int_op(fascist_firewall_allows_address(&ipv6_addr, port, policy, 0, 0), + OP_EQ, 1); + tt_int_op(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 0, 0), + OP_EQ, 0); + tt_int_op(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 0, 0), + OP_EQ, 0); /* Test the function's address matching with ClientUseIPv4 0. * This means "use IPv6" regardless of the other settings. */ @@ -1859,14 +1859,14 @@ test_policies_fascist_firewall_allows_address(void *arg) mock_options.ClientUseIPv6 = 0; mock_options.UseBridges = 0; - tt_assert(fascist_firewall_allows_address(&ipv4_addr, port, policy, 0, 0) - == 0); - tt_assert(fascist_firewall_allows_address(&ipv6_addr, port, policy, 0, 0) - == 1); - tt_assert(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 0, 0) - == 0); - tt_assert(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 0, 0) - == 0); + tt_int_op(fascist_firewall_allows_address(&ipv4_addr, port, policy, 0, 0), + OP_EQ, 0); + tt_int_op(fascist_firewall_allows_address(&ipv6_addr, port, policy, 0, 0), + OP_EQ, 1); + tt_int_op(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 0, 0), + OP_EQ, 0); + tt_int_op(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 0, 0), + OP_EQ, 0); /* Test the function's address matching for unusual inputs */ memset(&mock_options, 0, sizeof(or_options_t)); @@ -1875,27 +1875,28 @@ test_policies_fascist_firewall_allows_address(void *arg) mock_options.UseBridges = 1; /* NULL and tor_addr_is_null addresses are rejected */ - tt_assert(fascist_firewall_allows_address(NULL, port, policy, 0, 0) == 0); - tt_assert(fascist_firewall_allows_address(&n_ipv4_addr, port, policy, 0, 0) - == 0); - tt_assert(fascist_firewall_allows_address(&n_ipv6_addr, port, policy, 0, 0) - == 0); + tt_int_op(fascist_firewall_allows_address(NULL, port, policy, 0, 0), OP_EQ, + 0); + tt_int_op(fascist_firewall_allows_address(&n_ipv4_addr, port, policy, 0, 0), + OP_EQ, 0); + tt_int_op(fascist_firewall_allows_address(&n_ipv6_addr, port, policy, 0, 0), + OP_EQ, 0); /* zero ports are rejected */ - tt_assert(fascist_firewall_allows_address(&ipv4_addr, 0, policy, 0, 0) - == 0); - tt_assert(fascist_firewall_allows_address(&ipv6_addr, 0, policy, 0, 0) - == 0); + tt_int_op(fascist_firewall_allows_address(&ipv4_addr, 0, policy, 0, 0), + OP_EQ, 0); + tt_int_op(fascist_firewall_allows_address(&ipv6_addr, 0, policy, 0, 0), + OP_EQ, 0); /* NULL and empty policies accept everything */ - tt_assert(fascist_firewall_allows_address(&ipv4_addr, port, NULL, 0, 0) - == 1); - tt_assert(fascist_firewall_allows_address(&ipv6_addr, port, NULL, 0, 0) - == 1); - tt_assert(fascist_firewall_allows_address(&ipv4_addr, port, e_policy, 0, 0) - == 1); - tt_assert(fascist_firewall_allows_address(&ipv6_addr, port, e_policy, 0, 0) - == 1); + tt_int_op(fascist_firewall_allows_address(&ipv4_addr, port, NULL, 0, 0), + OP_EQ, 1); + tt_int_op(fascist_firewall_allows_address(&ipv6_addr, port, NULL, 0, 0), + OP_EQ, 1); + tt_int_op(fascist_firewall_allows_address(&ipv4_addr, port, e_policy, 0, 0), + OP_EQ, 1); + tt_int_op(fascist_firewall_allows_address(&ipv6_addr, port, e_policy, 0, 0), + OP_EQ, 1); done: addr_policy_free(item); @@ -2032,12 +2033,12 @@ test_policies_fascist_firewall_choose_address(void *arg) == &ipv6_or_ap); /* null both OR addresses */ - tt_assert(fascist_firewall_choose_address(&n_ipv4_ap, &n_ipv6_ap, 0, - FIREWALL_OR_CONNECTION, 0, 1) - == NULL); - tt_assert(fascist_firewall_choose_address(&n_ipv4_ap, &n_ipv6_ap, 1, - FIREWALL_OR_CONNECTION, 0, 0) - == NULL); + tt_ptr_op(fascist_firewall_choose_address(&n_ipv4_ap, &n_ipv6_ap, 0, + FIREWALL_OR_CONNECTION, 0, 1), + OP_EQ, NULL); + tt_ptr_op(fascist_firewall_choose_address(&n_ipv4_ap, &n_ipv6_ap, 1, + FIREWALL_OR_CONNECTION, 0, 0), + OP_EQ, NULL); /* null preferred Dir addresses */ tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &n_ipv6_ap, 0, @@ -2048,12 +2049,12 @@ test_policies_fascist_firewall_choose_address(void *arg) == &ipv6_dir_ap); /* null both Dir addresses */ - tt_assert(fascist_firewall_choose_address(&n_ipv4_ap, &n_ipv6_ap, 0, - FIREWALL_DIR_CONNECTION, 0, 1) - == NULL); - tt_assert(fascist_firewall_choose_address(&n_ipv4_ap, &n_ipv6_ap, 1, - FIREWALL_DIR_CONNECTION, 0, 0) - == NULL); + tt_ptr_op(fascist_firewall_choose_address(&n_ipv4_ap, &n_ipv6_ap, 0, + FIREWALL_DIR_CONNECTION, 0, 1), + OP_EQ, NULL); + tt_ptr_op(fascist_firewall_choose_address(&n_ipv4_ap, &n_ipv6_ap, 1, + FIREWALL_DIR_CONNECTION, 0, 0), + OP_EQ, NULL); /* Prefer IPv4 but want IPv6 (contradictory) */ tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 0, diff --git a/src/test/test_proto_http.c b/src/test/test_proto_http.c new file mode 100644 index 0000000000..2f36fbccd7 --- /dev/null +++ b/src/test/test_proto_http.c @@ -0,0 +1,213 @@ +/* Copyright (c) 2017, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file test_proto_http.c + * \brief Tests for our HTTP protocol parser code + */ + +#include "or.h" +#include "test.h" +#include "buffers.h" +#include "proto_http.h" +#include "log_test_helpers.h" + +#define S(str) str, sizeof(str)-1 + +static void +test_proto_http_peek(void *arg) +{ + (void) arg; + const struct { + int is_http; + const char *message; + size_t len; + } cases[] = { + { 1, S("GET /index HTTP/1.0\r\n") }, + { 1, S("GET /index HTTP/1.1\r\n") }, + { 1, S("GET ") }, + { 0, S("GIT ") }, + { 0, S("GET") }, + { 0, S("get ") }, + { 0, S("GETAWAY") }, + }; + unsigned i; + buf_t *buf = buf_new(); + for (i = 0; i < ARRAY_LENGTH(cases); ++i) { + TT_BLATHER(("Trying case %u", i)); + buf_add(buf, cases[i].message, cases[i].len); + tt_int_op(cases[i].is_http, OP_EQ, peek_buf_has_http_command(buf)); + buf_clear(buf); + } + done: + buf_free(buf); +} + +static void +test_proto_http_valid(void *arg) +{ + (void) arg; + const struct { + const char *message; + size_t len; + const char *headers; + const char *body; + size_t bodylen; + int should_detect_truncated; + int bytes_left_over; + } cases[] = { + { S("GET /index.html HTTP/1.0\r\n\r\n"), + "GET /index.html HTTP/1.0\r\n\r\n", + S(""), + 1, 0, + }, + { S("PUT /tor/foo HTTP/1.1\r\n" + "Content-Length: 51\r\n\r\n" + "this is a test of the http parsing system . test te"), + "PUT /tor/foo HTTP/1.1\r\n" "Content-Length: 51\r\n\r\n", + S("this is a test of the http parsing system . test te"), + 1, 0, + }, + { S("PUT /tor/foo HTTP/1.1\r\n" + "Content-Length: 5\r\n\r\n" + "there are more than 5 characters in this body."), + "PUT /tor/foo HTTP/1.1\r\n" "Content-Length: 5\r\n\r\n", + S("there"), + 0, 41, + }, + { S("PUT /tor/bar HTTP/1.1\r\n\r\n" + "this is another \x00test"), + "PUT /tor/bar HTTP/1.1\r\n\r\n", + S("this is another \x00test"), + 0, 0, + } + }; + unsigned i; + buf_t *buf = buf_new(); + char *h = NULL, *b = NULL; + + for (i = 0; i < ARRAY_LENGTH(cases); ++i) { + TT_BLATHER(("Trying case %u", i)); + size_t bl = 0; + // truncate by 2 chars + buf_add(buf, cases[i].message, cases[i].len - 2); + + if (cases[i].should_detect_truncated) { + tt_int_op(0, OP_EQ, fetch_from_buf_http(buf, &h, 1024*16, + &b, &bl, 1024*16, 0)); + tt_ptr_op(h, OP_EQ, NULL); + tt_ptr_op(b, OP_EQ, NULL); + tt_u64_op(bl, OP_EQ, 0); + tt_int_op(buf_datalen(buf), OP_EQ, cases[i].len - 2); + } + + // add the rest. + buf_add(buf, cases[i].message+cases[i].len-2, 2); + tt_int_op(1, OP_EQ, fetch_from_buf_http(buf, &h, 1024*16, + &b, &bl, 1024*16, 0)); + tt_str_op(h, OP_EQ, cases[i].headers); + tt_u64_op(bl, OP_EQ, cases[i].bodylen); + tt_mem_op(b, OP_EQ, cases[i].body, bl); + tt_int_op(buf_datalen(buf), OP_EQ, cases[i].bytes_left_over); + + buf_clear(buf); + tor_free(h); + tor_free(b); + } + done: + tor_free(h); + tor_free(b); + buf_free(buf); +} + +static void +test_proto_http_invalid(void *arg) +{ + (void) arg; + const struct { + const char *message; + size_t len; + const char *expect; + } cases[] = { + /* Overlong headers, headers not finished. */ + { S("GET /index.xhml HTTP/1.0\r\n" + "X-My-headers-are-too-long: yes indeed they are. They might be\r\n" + "X-My-headers-are-too-long: normal under other circumstances, but\r\n" + "X-My-headers-are-too-long: the 128-byte limit makes them bad\r\n"), + "headers too long." }, + /* Overlong finished headers. */ + { S("GET /index.xhml HTTP/1.0\r\n" + "X-My-headers-are-too-long: yes indeed they are. They might be\r\n" + "X-My-headers-are-too-long: normal under other circumstances, but\r\n" + "X-My-headers-are-too-long: the 128-byte limit makes them bad\r\n" + "\r\n"), + "headers too long." }, + /* Exactly too long finished headers. */ + { S("GET /index.xhml HTTP/1.0\r\n" + "X-My-headers-are-too-long: yes indeed they are. They might be\r\n" + "X-My-headers-are-too-long: normal un\r\n\r\n"), + "headerlen 129 larger than 127. Failing." }, + /* Body too long, with content-length */ + { S("GET /index.html HTTP/1.0\r\n" + "Content-Length: 129\r\n\r\n" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxx"), + "bodylen 129 larger than 127" }, + /* Body too long, with content-length lying */ + { S("GET /index.html HTTP/1.0\r\n" + "Content-Length: 99999\r\n\r\n" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxx"), + "bodylen 138 larger than 127" }, + /* Body too long, no content-length. */ + { S("GET /index.html HTTP/1.0\r\n\r\n" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxz"), + "bodylen 139 larger than 127" }, + /* Content-Length is junk. */ + { S("GET /index.html HTTP/1.0\r\n" + "Content-Length: Cheese\r\n\r\n" + "foo"), + "Content-Length is bogus; maybe someone is trying to crash us." }, + }; + unsigned i; + buf_t *buf = buf_new(); + char *h = NULL, *b = NULL; + setup_capture_of_logs(LOG_DEBUG); + + for (i = 0; i < ARRAY_LENGTH(cases); ++i) { + TT_BLATHER(("Trying case %u", i)); + size_t bl = 0; + buf_add(buf, cases[i].message, cases[i].len); + + /* Use low body limits here so we can force over-sized object warnings */ + tt_int_op(-1, OP_EQ, fetch_from_buf_http(buf, &h, 128, + &b, &bl, 128, 0)); + tt_ptr_op(h, OP_EQ, NULL); + tt_ptr_op(b, OP_EQ, NULL); + tt_u64_op(bl, OP_EQ, 0); + expect_log_msg_containing(cases[i].expect); + + buf_clear(buf); + tor_free(h); + tor_free(b); + mock_clean_saved_logs(); + } + done: + tor_free(h); + tor_free(b); + buf_free(buf); + teardown_capture_of_logs(); +} + +struct testcase_t proto_http_tests[] = { + { "peek", test_proto_http_peek, 0, NULL, NULL }, + { "valid", test_proto_http_valid, 0, NULL, NULL }, + { "invalid", test_proto_http_invalid, 0, NULL, NULL }, + + END_OF_TESTCASES +}; + diff --git a/src/test/test_proto_misc.c b/src/test/test_proto_misc.c new file mode 100644 index 0000000000..263ca47447 --- /dev/null +++ b/src/test/test_proto_misc.c @@ -0,0 +1,263 @@ +/* Copyright (c) 2017, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file test_proto_misc.c + * \brief Test our smaller buffer-based protocol functions + */ + +#include "or.h" +#include "test.h" +#include "buffers.h" +#include "connection_or.h" +#include "ext_orport.h" +#include "proto_cell.h" +#include "proto_control0.h" +#include "proto_ext_or.h" + +static void +test_proto_var_cell(void *arg) +{ + (void)arg; + char *mem_op_hex_tmp = NULL; + char tmp[1024]; + buf_t *buf = NULL; + var_cell_t *cell = NULL; + + buf = buf_new(); + memset(tmp, 0xf0, sizeof(tmp)); + + /* Short little commands will make us say "no cell yet." */ + tt_int_op(0, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4)); + tt_ptr_op(cell, OP_EQ, NULL); + buf_add(buf, "\x01\x02\x02\0x2", 4); + tt_int_op(0, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4)); + /* An incomplete fixed-length cell makes us say "no cell yet". */ + buf_add(buf, "\x03", 1); + tt_int_op(0, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4)); + /* A complete fixed length-cell makes us say "not a variable-length cell" */ + buf_add(buf, tmp, 509); + tt_int_op(0, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4)); + buf_clear(buf); + + /* An incomplete versions cell is a variable-length cell that isn't ready + * yet. */ + buf_add(buf, + "\x01\x02\x03\x04" /* circid */ + "\x07" /* VERSIONS */ + "\x00\x04" /* 4 bytes long */ + "\x00" /* incomplete */, 8); + tt_int_op(1, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4)); + tt_ptr_op(cell, OP_EQ, NULL); + /* Complete it, and it's a variable-length cell. Leave a byte on the end for + * fun. */ + buf_add(buf, "\x09\x00\x25\ff", 4); + tt_int_op(1, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4)); + tt_ptr_op(cell, OP_NE, NULL); + tt_int_op(cell->command, OP_EQ, CELL_VERSIONS); + tt_uint_op(cell->circ_id, OP_EQ, 0x01020304); + tt_int_op(cell->payload_len, OP_EQ, 4); + test_mem_op_hex(cell->payload, OP_EQ, "00090025"); + var_cell_free(cell); + cell = NULL; + tt_int_op(buf_datalen(buf), OP_EQ, 1); + buf_clear(buf); + + /* In link protocol 3 and earlier, circid fields were two bytes long. Let's + * ensure that gets handled correctly. */ + buf_add(buf, + "\x23\x45\x81\x00\x06" /* command 81; 6 bytes long */ + "coraje", 11); + tt_int_op(1, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 3)); + tt_ptr_op(cell, OP_NE, NULL); + tt_int_op(cell->command, OP_EQ, 129); + tt_uint_op(cell->circ_id, OP_EQ, 0x2345); + tt_int_op(cell->payload_len, OP_EQ, 6); + tt_mem_op(cell->payload, OP_EQ, "coraje", 6); + var_cell_free(cell); + cell = NULL; + tt_int_op(buf_datalen(buf), OP_EQ, 0); + + /* In link protocol 2, only VERSIONS cells counted as variable-length */ + buf_add(buf, + "\x23\x45\x81\x00\x06" + "coraje", 11); /* As above */ + tt_int_op(0, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 2)); + buf_clear(buf); + buf_add(buf, + "\x23\x45\x07\x00\x06" + "futuro", 11); + tt_int_op(1, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 2)); + tt_ptr_op(cell, OP_NE, NULL); + tt_int_op(cell->command, OP_EQ, 7); + tt_uint_op(cell->circ_id, OP_EQ, 0x2345); + tt_int_op(cell->payload_len, OP_EQ, 6); + tt_mem_op(cell->payload, OP_EQ, "futuro", 6); + var_cell_free(cell); + cell = NULL; + + done: + buf_free(buf); + var_cell_free(cell); + tor_free(mem_op_hex_tmp); +} + +static void +test_proto_control0(void *arg) +{ + (void)arg; + buf_t *buf = buf_new(); + + /* The only remaining function for the v0 control protocol is the function + that detects whether the user has stumbled across an old controller + that's using it. The format was: + u16 length; + u16 command; + u8 body[length]; + */ + + /* Empty buffer -- nothing to do. */ + tt_int_op(0, OP_EQ, peek_buf_has_control0_command(buf)); + /* 3 chars in buf -- can't tell */ + buf_add(buf, "AUT", 3); + tt_int_op(0, OP_EQ, peek_buf_has_control0_command(buf)); + /* command in buf -- easy to tell */ + buf_add(buf, "HENTICATE ", 10); + tt_int_op(0, OP_EQ, peek_buf_has_control0_command(buf)); + + /* Control0 command header in buf: make sure we detect it. */ + buf_clear(buf); + buf_add(buf, "\x09\x05" "\x00\x05" "blah", 8); + tt_int_op(1, OP_EQ, peek_buf_has_control0_command(buf)); + + done: + buf_free(buf); +} + +static void +test_proto_ext_or_cmd(void *arg) +{ + ext_or_cmd_t *cmd = NULL; + buf_t *buf = buf_new(); + char *tmp = NULL; + (void) arg; + + /* Empty -- should give "not there. */ + tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd)); + tt_ptr_op(NULL, OP_EQ, cmd); + + /* Three bytes: shouldn't work. */ + buf_add(buf, "\x00\x20\x00", 3); + tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd)); + tt_ptr_op(NULL, OP_EQ, cmd); + tt_int_op(3, OP_EQ, buf_datalen(buf)); + + /* 0020 0000: That's a nil command. It should work. */ + buf_add(buf, "\x00", 1); + tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd)); + tt_ptr_op(NULL, OP_NE, cmd); + tt_int_op(0x20, OP_EQ, cmd->cmd); + tt_int_op(0, OP_EQ, cmd->len); + tt_int_op(0, OP_EQ, buf_datalen(buf)); + ext_or_cmd_free(cmd); + cmd = NULL; + + /* Now try a length-6 command with one byte missing. */ + buf_add(buf, "\x10\x21\x00\x06""abcde", 9); + tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd)); + tt_ptr_op(NULL, OP_EQ, cmd); + buf_add(buf, "f", 1); + tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd)); + tt_ptr_op(NULL, OP_NE, cmd); + tt_int_op(0x1021, OP_EQ, cmd->cmd); + tt_int_op(6, OP_EQ, cmd->len); + tt_mem_op("abcdef", OP_EQ, cmd->body, 6); + tt_int_op(0, OP_EQ, buf_datalen(buf)); + ext_or_cmd_free(cmd); + cmd = NULL; + + /* Now try a length-10 command with 4 extra bytes. */ + buf_add(buf, "\xff\xff\x00\x0aloremipsum\x10\x00\xff\xff", 18); + tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd)); + tt_ptr_op(NULL, OP_NE, cmd); + tt_int_op(0xffff, OP_EQ, cmd->cmd); + tt_int_op(10, OP_EQ, cmd->len); + tt_mem_op("loremipsum", OP_EQ, cmd->body, 10); + tt_int_op(4, OP_EQ, buf_datalen(buf)); + ext_or_cmd_free(cmd); + cmd = NULL; + + /* Finally, let's try a maximum-length command. We already have the header + * waiting. */ + tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd)); + tmp = tor_malloc_zero(65535); + buf_add(buf, tmp, 65535); + tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd)); + tt_ptr_op(NULL, OP_NE, cmd); + tt_int_op(0x1000, OP_EQ, cmd->cmd); + tt_int_op(0xffff, OP_EQ, cmd->len); + tt_mem_op(tmp, OP_EQ, cmd->body, 65535); + tt_int_op(0, OP_EQ, buf_datalen(buf)); + ext_or_cmd_free(cmd); + cmd = NULL; + + done: + ext_or_cmd_free(cmd); + buf_free(buf); + tor_free(tmp); +} + +static void +test_proto_line(void *arg) +{ + (void)arg; + char tmp[60]; + buf_t *buf = buf_new(); +#define S(str) str, sizeof(str)-1 + const struct { + const char *input; + size_t input_len; + size_t line_len; + const char *output; + int returnval; + } cases[] = { + { S("Hello world"), 0, NULL, 0 }, + { S("Hello world\n"), 12, "Hello world\n", 1 }, + { S("Hello world\nMore"), 12, "Hello world\n", 1 }, + { S("\n oh hello world\nMore"), 1, "\n", 1 }, + { S("Hello worpd\n\nMore"), 12, "Hello worpd\n", 1 }, + { S("------------------------------------------------------------\n"), 0, + NULL, -1 }, + }; + unsigned i; + for (i = 0; i < ARRAY_LENGTH(cases); ++i) { + buf_add(buf, cases[i].input, cases[i].input_len); + memset(tmp, 0xfe, sizeof(tmp)); + size_t sz = sizeof(tmp); + int rv = buf_get_line(buf, tmp, &sz); + tt_int_op(rv, OP_EQ, cases[i].returnval); + if (rv == 1) { + tt_int_op(sz, OP_LT, sizeof(tmp)); + tt_mem_op(cases[i].output, OP_EQ, tmp, sz+1); + tt_int_op(buf_datalen(buf), OP_EQ, cases[i].input_len - strlen(tmp)); + tt_int_op(sz, OP_EQ, cases[i].line_len); + } else { + tt_int_op(buf_datalen(buf), OP_EQ, cases[i].input_len); + // tt_int_op(sz, OP_EQ, sizeof(tmp)); + } + buf_clear(buf); + } + + done: + buf_free(buf); +} + +struct testcase_t proto_misc_tests[] = { + { "var_cell", test_proto_var_cell, 0, NULL, NULL }, + { "control0", test_proto_control0, 0, NULL, NULL }, + { "ext_or_cmd", test_proto_ext_or_cmd, TT_FORK, NULL, NULL }, + { "line", test_proto_line, 0, NULL, NULL }, + + END_OF_TESTCASES +}; + diff --git a/src/test/test_protover.c b/src/test/test_protover.c index c093e69968..9b94044b91 100644 --- a/src/test/test_protover.c +++ b/src/test/test_protover.c @@ -88,27 +88,27 @@ test_protover_parse_fail(void *arg) /* random junk */ elts = parse_protocol_list("!!3@*"); - tt_assert(elts == NULL); + tt_ptr_op(elts, OP_EQ, NULL); /* Missing equals sign in an entry */ elts = parse_protocol_list("Link=4 Haprauxymatyve Desc=9"); - tt_assert(elts == NULL); + tt_ptr_op(elts, OP_EQ, NULL); /* Missing word. */ elts = parse_protocol_list("Link=4 =3 Desc=9"); - tt_assert(elts == NULL); + tt_ptr_op(elts, OP_EQ, NULL); /* Broken numbers */ elts = parse_protocol_list("Link=fred"); - tt_assert(elts == NULL); + tt_ptr_op(elts, OP_EQ, NULL); elts = parse_protocol_list("Link=1,fred"); - tt_assert(elts == NULL); + tt_ptr_op(elts, OP_EQ, NULL); elts = parse_protocol_list("Link=1,fred,3"); - tt_assert(elts == NULL); + tt_ptr_op(elts, OP_EQ, NULL); /* Broken range */ elts = parse_protocol_list("Link=1,9-8,3"); - tt_assert(elts == NULL); + tt_ptr_op(elts, OP_EQ, NULL); done: ; @@ -215,16 +215,16 @@ test_protover_all_supported(void *arg) char *msg = NULL; tt_assert(protover_all_supported(NULL, &msg)); - tt_assert(msg == NULL); + tt_ptr_op(msg, OP_EQ, NULL); tt_assert(protover_all_supported("", &msg)); - tt_assert(msg == NULL); + tt_ptr_op(msg, OP_EQ, NULL); // Some things that we do support tt_assert(protover_all_supported("Link=3-4", &msg)); - tt_assert(msg == NULL); + tt_ptr_op(msg, OP_EQ, NULL); tt_assert(protover_all_supported("Link=3-4 Desc=2", &msg)); - tt_assert(msg == NULL); + tt_ptr_op(msg, OP_EQ, NULL); // Some things we don't support tt_assert(! protover_all_supported("Wombat=9", &msg)); diff --git a/src/test/test_pt.c b/src/test/test_pt.c index 79b03171bc..07b6712ff9 100644 --- a/src/test/test_pt.c +++ b/src/test/test_pt.c @@ -40,34 +40,34 @@ test_pt_parsing(void *arg) /* incomplete cmethod */ strlcpy(line,"CMETHOD trebuchet",sizeof(line)); - tt_assert(parse_cmethod_line(line, mp) < 0); + tt_int_op(parse_cmethod_line(line, mp), OP_LT, 0); reset_mp(mp); /* wrong proxy type */ strlcpy(line,"CMETHOD trebuchet dog 127.0.0.1:1999",sizeof(line)); - tt_assert(parse_cmethod_line(line, mp) < 0); + tt_int_op(parse_cmethod_line(line, mp), OP_LT, 0); reset_mp(mp); /* wrong addrport */ strlcpy(line,"CMETHOD trebuchet socks4 abcd",sizeof(line)); - tt_assert(parse_cmethod_line(line, mp) < 0); + tt_int_op(parse_cmethod_line(line, mp), OP_LT, 0); reset_mp(mp); /* correct line */ strlcpy(line,"CMETHOD trebuchet socks5 127.0.0.1:1999",sizeof(line)); - tt_assert(parse_cmethod_line(line, mp) == 0); - tt_assert(smartlist_len(mp->transports) == 1); + tt_int_op(parse_cmethod_line(line, mp), OP_EQ, 0); + tt_int_op(smartlist_len(mp->transports), OP_EQ, 1); transport = smartlist_get(mp->transports, 0); /* test registered address of transport */ tor_addr_parse(&test_addr, "127.0.0.1"); tt_assert(tor_addr_eq(&test_addr, &transport->addr)); /* test registered port of transport */ - tt_assert(transport->port == 1999); + tt_uint_op(transport->port, OP_EQ, 1999); /* test registered SOCKS version of transport */ - tt_assert(transport->socks_version == PROXY_SOCKS5); + tt_int_op(transport->socks_version, OP_EQ, PROXY_SOCKS5); /* test registered name of transport */ tt_str_op(transport->name,OP_EQ, "trebuchet"); @@ -75,26 +75,26 @@ test_pt_parsing(void *arg) /* incomplete smethod */ strlcpy(line,"SMETHOD trebuchet",sizeof(line)); - tt_assert(parse_smethod_line(line, mp) < 0); + tt_int_op(parse_smethod_line(line, mp), OP_LT, 0); reset_mp(mp); /* wrong addr type */ strlcpy(line,"SMETHOD trebuchet abcd",sizeof(line)); - tt_assert(parse_smethod_line(line, mp) < 0); + tt_int_op(parse_smethod_line(line, mp), OP_LT, 0); reset_mp(mp); /* cowwect */ strlcpy(line,"SMETHOD trebuchy 127.0.0.2:2999",sizeof(line)); - tt_assert(parse_smethod_line(line, mp) == 0); - tt_assert(smartlist_len(mp->transports) == 1); + tt_int_op(parse_smethod_line(line, mp), OP_EQ, 0); + tt_int_op(smartlist_len(mp->transports), OP_EQ, 1); transport = smartlist_get(mp->transports, 0); /* test registered address of transport */ tor_addr_parse(&test_addr, "127.0.0.2"); tt_assert(tor_addr_eq(&test_addr, &transport->addr)); /* test registered port of transport */ - tt_assert(transport->port == 2999); + tt_uint_op(transport->port, OP_EQ, 2999); /* test registered name of transport */ tt_str_op(transport->name,OP_EQ, "trebuchy"); @@ -104,7 +104,7 @@ test_pt_parsing(void *arg) strlcpy(line,"SMETHOD trebuchet 127.0.0.1:9999 " "ARGS:counterweight=3,sling=snappy", sizeof(line)); - tt_assert(parse_smethod_line(line, mp) == 0); + tt_int_op(parse_smethod_line(line, mp), OP_EQ, 0); tt_int_op(1, OP_EQ, smartlist_len(mp->transports)); { const transport_t *transport_ = smartlist_get(mp->transports, 0); @@ -119,15 +119,15 @@ test_pt_parsing(void *arg) /* unsupported version */ strlcpy(line,"VERSION 666",sizeof(line)); - tt_assert(parse_version(line, mp) < 0); + tt_int_op(parse_version(line, mp), OP_LT, 0); /* incomplete VERSION */ strlcpy(line,"VERSION ",sizeof(line)); - tt_assert(parse_version(line, mp) < 0); + tt_int_op(parse_version(line, mp), OP_LT, 0); /* correct VERSION */ strlcpy(line,"VERSION 1",sizeof(line)); - tt_assert(parse_version(line, mp) == 0); + tt_int_op(parse_version(line, mp), OP_EQ, 0); done: reset_mp(mp); @@ -461,7 +461,7 @@ test_get_pt_proxy_uri(void *arg) /* Test with no proxy. */ uri = get_pt_proxy_uri(); - tt_assert(uri == NULL); + tt_ptr_op(uri, OP_EQ, NULL); /* Test with a SOCKS4 proxy. */ options->Socks4Proxy = tor_strdup("192.0.2.1:1080"); diff --git a/src/test/test_relay.c b/src/test/test_relay.c index 238d4c5baf..e3489627a0 100644 --- a/src/test/test_relay.c +++ b/src/test/test_relay.c @@ -91,14 +91,14 @@ test_relay_append_cell_to_circuit_queue(void *arg) append_cell_to_circuit_queue(TO_CIRCUIT(orcirc), nchan, cell, CELL_DIRECTION_OUT, 0); new_count = get_mock_scheduler_has_waiting_cells_count(); - tt_int_op(new_count, ==, old_count + 1); + tt_int_op(new_count, OP_EQ, old_count + 1); /* Now try the reverse direction */ old_count = get_mock_scheduler_has_waiting_cells_count(); append_cell_to_circuit_queue(TO_CIRCUIT(orcirc), pchan, cell, CELL_DIRECTION_IN, 0); new_count = get_mock_scheduler_has_waiting_cells_count(); - tt_int_op(new_count, ==, old_count + 1); + tt_int_op(new_count, OP_EQ, old_count + 1); UNMOCK(scheduler_channel_has_waiting_cells); diff --git a/src/test/test_rendcache.c b/src/test/test_rendcache.c index feba8f664e..9354dd0480 100644 --- a/src/test/test_rendcache.c +++ b/src/test/test_rendcache.c @@ -21,22 +21,6 @@ static const int TIME_IN_THE_PAST = -(REND_CACHE_MAX_AGE + \ REND_CACHE_MAX_SKEW + 60); static const int TIME_IN_THE_FUTURE = REND_CACHE_MAX_SKEW + 60; -static rend_data_t * -mock_rend_data(const char *onion_address) -{ - rend_data_v2_t *v2_data = tor_malloc_zero(sizeof(*v2_data)); - rend_data_t *rend_query = &v2_data->base_; - rend_query->version = 2; - - strlcpy(v2_data->onion_address, onion_address, - sizeof(v2_data->onion_address)); - v2_data->auth_type = REND_NO_AUTH; - rend_query->hsdirs_fp = smartlist_new(); - smartlist_add(rend_query->hsdirs_fp, tor_memdup("aaaaaaaaaaaaaaaaaaaaaaaa", - DIGEST_LEN)); - return rend_query; -} - static void test_rend_cache_lookup_entry(void *data) { @@ -74,6 +58,7 @@ test_rend_cache_lookup_entry(void *data) tt_int_op(ret, OP_EQ, 0); ret = rend_cache_lookup_entry(service_id, 2, &entry); + tt_int_op(ret, OP_EQ, 0); tt_assert(entry); tt_int_op(entry->len, OP_EQ, strlen(desc_holder->desc_str)); tt_str_op(entry->desc, OP_EQ, desc_holder->desc_str); @@ -962,9 +947,9 @@ test_rend_cache_free_all(void *data) rend_cache_free_all(); - tt_assert(!rend_cache); - tt_assert(!rend_cache_v2_dir); - tt_assert(!rend_cache_failure); + tt_ptr_op(rend_cache, OP_EQ, NULL); + tt_ptr_op(rend_cache_v2_dir, OP_EQ, NULL); + tt_ptr_op(rend_cache_failure, OP_EQ, NULL); tt_assert(!rend_cache_total_allocation); done: diff --git a/src/test/test_replay.c b/src/test/test_replay.c index 80e7203716..c379cafa7c 100644 --- a/src/test/test_replay.c +++ b/src/test/test_replay.c @@ -38,7 +38,7 @@ test_replaycache_alloc(void *arg) (void)arg; r = replaycache_new(600, 300); - tt_assert(r != NULL); + tt_ptr_op(r, OP_NE, NULL); done: if (r) replaycache_free(r); @@ -54,15 +54,15 @@ test_replaycache_badalloc(void *arg) /* Negative horizon should fail */ (void)arg; r = replaycache_new(-600, 300); - tt_assert(r == NULL); + tt_ptr_op(r, OP_EQ, NULL); /* Negative interval should get adjusted to zero */ r = replaycache_new(600, -300); - tt_assert(r != NULL); + tt_ptr_op(r, OP_NE, NULL); tt_int_op(r->scrub_interval,OP_EQ, 0); replaycache_free(r); /* Negative horizon and negative interval should still fail */ r = replaycache_new(-600, -300); - tt_assert(r == NULL); + tt_ptr_op(r, OP_EQ, NULL); done: if (r) replaycache_free(r); @@ -90,7 +90,7 @@ test_replaycache_miss(void *arg) (void)arg; r = replaycache_new(600, 300); - tt_assert(r != NULL); + tt_ptr_op(r, OP_NE, NULL); result = replaycache_add_and_test_internal(1200, r, test_buffer, @@ -123,7 +123,7 @@ test_replaycache_hit(void *arg) (void)arg; r = replaycache_new(600, 300); - tt_assert(r != NULL); + tt_ptr_op(r, OP_NE, NULL); result = replaycache_add_and_test_internal(1200, r, test_buffer, @@ -161,7 +161,7 @@ test_replaycache_age(void *arg) (void)arg; r = replaycache_new(600, 300); - tt_assert(r != NULL); + tt_ptr_op(r, OP_NE, NULL); result = replaycache_add_and_test_internal(1200, r, test_buffer, @@ -193,7 +193,7 @@ test_replaycache_elapsed(void *arg) (void)arg; r = replaycache_new(600, 300); - tt_assert(r != NULL); + tt_ptr_op(r, OP_NE, NULL); result = replaycache_add_and_test_internal(1200, r, test_buffer, @@ -220,7 +220,7 @@ test_replaycache_noexpire(void *arg) (void)arg; r = replaycache_new(0, 0); - tt_assert(r != NULL); + tt_ptr_op(r, OP_NE, NULL); result = replaycache_add_and_test_internal(1200, r, test_buffer, @@ -251,7 +251,7 @@ test_replaycache_scrub(void *arg) (void)arg; r = replaycache_new(600, 300); - tt_assert(r != NULL); + tt_ptr_op(r, OP_NE, NULL); /* Set up like in test_replaycache_hit() */ result = @@ -294,7 +294,7 @@ test_replaycache_future(void *arg) (void)arg; r = replaycache_new(600, 300); - tt_assert(r != NULL); + tt_ptr_op(r, OP_NE, NULL); /* Set up like in test_replaycache_hit() */ result = @@ -343,7 +343,7 @@ test_replaycache_realtime(void *arg) /* Test the realtime as well as *_internal() entry points */ (void)arg; r = replaycache_new(600, 300); - tt_assert(r != NULL); + tt_ptr_op(r, OP_NE, NULL); /* This should miss */ result = diff --git a/src/test/test_router.c b/src/test/test_router.c new file mode 100644 index 0000000000..4e96e24534 --- /dev/null +++ b/src/test/test_router.c @@ -0,0 +1,112 @@ +/* Copyright (c) 2017, The Tor Project, Inc. */ +/* Copyright (c) 2017, isis agora lovecruft */ +/* See LICENSE for licensing information */ + +/** + * \file test_router.c + * \brief Unittests for code in src/or/router.c + **/ + +#include "or.h" +#include "config.h" +#include "crypto_curve25519.h" +#include "crypto_ed25519.h" +#include "router.h" +#include "routerlist.h" + +/* Test suite stuff */ +#include "test.h" + +NS_DECL(const routerinfo_t *, router_get_my_routerinfo, (void)); + +static routerinfo_t* mock_routerinfo; + +static const routerinfo_t* +NS(router_get_my_routerinfo)(void) +{ + crypto_pk_t* ident_key; + crypto_pk_t* tap_key; + time_t now; + + if (!mock_routerinfo) { + /* Mock the published timestamp, otherwise router_dump_router_to_string() + * will poop its pants. */ + time(&now); + + /* We'll need keys, or router_dump_router_to_string() would return NULL. */ + ident_key = pk_generate(0); + tap_key = pk_generate(0); + + tor_assert(ident_key != NULL); + tor_assert(tap_key != NULL); + + mock_routerinfo = tor_malloc_zero(sizeof(routerinfo_t)); + mock_routerinfo->nickname = tor_strdup("ConlonNancarrow"); + mock_routerinfo->addr = 123456789; + mock_routerinfo->or_port = 443; + mock_routerinfo->platform = tor_strdup("unittest"); + mock_routerinfo->cache_info.published_on = now; + mock_routerinfo->identity_pkey = crypto_pk_dup_key(ident_key); + mock_routerinfo->onion_pkey = crypto_pk_dup_key(tap_key); + mock_routerinfo->bandwidthrate = 9001; + mock_routerinfo->bandwidthburst = 9002; + } + + return mock_routerinfo; +} + +/* If no distribution option was set, then check_bridge_distribution_setting() + * should have set it to "any". */ +static void +test_router_dump_router_to_string_no_bridge_distribution_method(void *arg) +{ + const char* needle = "bridge-distribution-request any"; + or_options_t* options = get_options_mutable(); + routerinfo_t* router = NULL; + curve25519_keypair_t ntor_keypair; + ed25519_keypair_t signing_keypair; + char* desc = NULL; + char* found = NULL; + (void)arg; + + NS_MOCK(router_get_my_routerinfo); + + options->ORPort_set = 1; + options->BridgeRelay = 1; + + /* Generate keys which router_dump_router_to_string() expects to exist. */ + tt_int_op(0, ==, curve25519_keypair_generate(&ntor_keypair, 0)); + tt_int_op(0, ==, ed25519_keypair_generate(&signing_keypair, 0)); + + /* Set up part of our routerinfo_t so that we don't trigger any other + * assertions in router_dump_router_to_string(). */ + router = (routerinfo_t*)router_get_my_routerinfo(); + tt_ptr_op(router, !=, NULL); + + router->onion_curve25519_pkey = &ntor_keypair.pubkey; + + /* Generate our server descriptor and ensure that the substring + * "bridge-distribution-request any" occurs somewhere within it. */ + desc = router_dump_router_to_string(router, + router->identity_pkey, + router->onion_pkey, + &ntor_keypair, + &signing_keypair); + tt_ptr_op(desc, !=, NULL); + found = strstr(desc, needle); + tt_ptr_op(found, !=, NULL); + + done: + NS_UNMOCK(router_get_my_routerinfo); + + tor_free(desc); +} + +#define ROUTER_TEST(name, flags) \ + { #name, test_router_ ## name, flags, NULL, NULL } + +struct testcase_t router_tests[] = { + ROUTER_TEST(dump_router_to_string_no_bridge_distribution_method, TT_FORK), + END_OF_TESTCASES +}; + diff --git a/src/test/test_routerkeys.c b/src/test/test_routerkeys.c index db6b9b3872..d8b72651a0 100644 --- a/src/test/test_routerkeys.c +++ b/src/test/test_routerkeys.c @@ -92,8 +92,8 @@ test_routerkeys_ed_certs(void *args) uint8_t *junk = NULL; char *base64 = NULL; - tt_int_op(0,==,ed25519_keypair_generate(&kp1, 0)); - tt_int_op(0,==,ed25519_keypair_generate(&kp2, 0)); + tt_int_op(0,OP_EQ,ed25519_keypair_generate(&kp1, 0)); + tt_int_op(0,OP_EQ,ed25519_keypair_generate(&kp2, 0)); for (int i = 0; i <= 1; ++i) { uint32_t flags = i ? CERT_FLAG_INCLUDE_SIGNING_KEY : 0; @@ -101,45 +101,45 @@ test_routerkeys_ed_certs(void *args) cert[i] = tor_cert_create(&kp1, 5, &kp2.pubkey, now, 10000, flags); tt_assert(cert[i]); - tt_assert(cert[i]->sig_bad == 0); - tt_assert(cert[i]->sig_ok == 1); - tt_assert(cert[i]->cert_expired == 0); - tt_assert(cert[i]->cert_valid == 1); - tt_int_op(cert[i]->cert_type, ==, 5); - tt_mem_op(cert[i]->signed_key.pubkey, ==, &kp2.pubkey.pubkey, 32); - tt_mem_op(cert[i]->signing_key.pubkey, ==, &kp1.pubkey.pubkey, 32); - tt_int_op(cert[i]->signing_key_included, ==, i); + tt_uint_op(cert[i]->sig_bad, OP_EQ, 0); + tt_uint_op(cert[i]->sig_ok, OP_EQ, 1); + tt_uint_op(cert[i]->cert_expired, OP_EQ, 0); + tt_uint_op(cert[i]->cert_valid, OP_EQ, 1); + tt_int_op(cert[i]->cert_type, OP_EQ, 5); + tt_mem_op(cert[i]->signed_key.pubkey, OP_EQ, &kp2.pubkey.pubkey, 32); + tt_mem_op(cert[i]->signing_key.pubkey, OP_EQ, &kp1.pubkey.pubkey, 32); + tt_int_op(cert[i]->signing_key_included, OP_EQ, i); tt_assert(cert[i]->encoded); - tt_int_op(cert[i]->encoded_len, ==, 104 + 36 * i); - tt_int_op(cert[i]->encoded[0], ==, 1); - tt_int_op(cert[i]->encoded[1], ==, 5); + tt_int_op(cert[i]->encoded_len, OP_EQ, 104 + 36 * i); + tt_int_op(cert[i]->encoded[0], OP_EQ, 1); + tt_int_op(cert[i]->encoded[1], OP_EQ, 5); parsed_cert[i] = tor_cert_parse(cert[i]->encoded, cert[i]->encoded_len); tt_assert(parsed_cert[i]); - tt_int_op(cert[i]->encoded_len, ==, parsed_cert[i]->encoded_len); - tt_mem_op(cert[i]->encoded, ==, parsed_cert[i]->encoded, + tt_int_op(cert[i]->encoded_len, OP_EQ, parsed_cert[i]->encoded_len); + tt_mem_op(cert[i]->encoded, OP_EQ, parsed_cert[i]->encoded, cert[i]->encoded_len); - tt_assert(parsed_cert[i]->sig_bad == 0); - tt_assert(parsed_cert[i]->sig_ok == 0); - tt_assert(parsed_cert[i]->cert_expired == 0); - tt_assert(parsed_cert[i]->cert_valid == 0); + tt_uint_op(parsed_cert[i]->sig_bad, OP_EQ, 0); + tt_uint_op(parsed_cert[i]->sig_ok, OP_EQ, 0); + tt_uint_op(parsed_cert[i]->cert_expired, OP_EQ, 0); + tt_uint_op(parsed_cert[i]->cert_valid, OP_EQ, 0); /* Expired */ tt_int_op(tor_cert_checksig(parsed_cert[i], &kp1.pubkey, now + 30000), - <, 0); - tt_assert(parsed_cert[i]->cert_expired == 1); + OP_LT, 0); + tt_uint_op(parsed_cert[i]->cert_expired, OP_EQ, 1); parsed_cert[i]->cert_expired = 0; /* Wrong key */ - tt_int_op(tor_cert_checksig(parsed_cert[i], &kp2.pubkey, now), <, 0); - tt_assert(parsed_cert[i]->sig_bad== 1); + tt_int_op(tor_cert_checksig(parsed_cert[i], &kp2.pubkey, now), OP_LT, 0); + tt_uint_op(parsed_cert[i]->sig_bad, OP_EQ, 1); parsed_cert[i]->sig_bad = 0; /* Missing key */ int ok = tor_cert_checksig(parsed_cert[i], NULL, now); - tt_int_op(ok < 0, ==, i == 0); - tt_assert(parsed_cert[i]->sig_bad == 0); + tt_int_op(ok < 0, OP_EQ, i == 0); + tt_uint_op(parsed_cert[i]->sig_bad, OP_EQ, 0); tt_assert(parsed_cert[i]->sig_ok == (i != 0)); tt_assert(parsed_cert[i]->cert_valid == (i != 0)); parsed_cert[i]->sig_bad = 0; @@ -147,29 +147,29 @@ test_routerkeys_ed_certs(void *args) parsed_cert[i]->cert_valid = 0; /* Right key */ - tt_int_op(tor_cert_checksig(parsed_cert[i], &kp1.pubkey, now), ==, 0); - tt_assert(parsed_cert[i]->sig_bad == 0); - tt_assert(parsed_cert[i]->sig_ok == 1); - tt_assert(parsed_cert[i]->cert_expired == 0); - tt_assert(parsed_cert[i]->cert_valid == 1); + tt_int_op(tor_cert_checksig(parsed_cert[i], &kp1.pubkey, now), OP_EQ, 0); + tt_uint_op(parsed_cert[i]->sig_bad, OP_EQ, 0); + tt_uint_op(parsed_cert[i]->sig_ok, OP_EQ, 1); + tt_uint_op(parsed_cert[i]->cert_expired, OP_EQ, 0); + tt_uint_op(parsed_cert[i]->cert_valid, OP_EQ, 1); } /* Now try some junky certs. */ /* - Truncated */ nocert = tor_cert_parse(cert[0]->encoded, cert[0]->encoded_len-1); - tt_ptr_op(NULL, ==, nocert); + tt_ptr_op(NULL, OP_EQ, nocert); /* - First byte modified */ cert[0]->encoded[0] = 99; nocert = tor_cert_parse(cert[0]->encoded, cert[0]->encoded_len); - tt_ptr_op(NULL, ==, nocert); + tt_ptr_op(NULL, OP_EQ, nocert); cert[0]->encoded[0] = 1; /* - Extra byte at the end*/ junk = tor_malloc_zero(cert[0]->encoded_len + 1); memcpy(junk, cert[0]->encoded, cert[0]->encoded_len); nocert = tor_cert_parse(junk, cert[0]->encoded_len+1); - tt_ptr_op(NULL, ==, nocert); + tt_ptr_op(NULL, OP_EQ, nocert); /* - Multiple signing key instances */ tor_free(junk); @@ -183,7 +183,7 @@ test_routerkeys_ed_certs(void *args) junk[77] = 32; /* extlen */ junk[78] = 4; /* exttype */ nocert = tor_cert_parse(junk, 104 + 36 * 2); - tt_ptr_op(NULL, ==, nocert); + tt_ptr_op(NULL, OP_EQ, nocert); done: tor_cert_free(cert[0]); @@ -211,11 +211,12 @@ test_routerkeys_ed_key_create(void *arg) kp2 = ed_key_new(kp1, INIT_ED_KEY_NEEDCERT, now, 3600, 4, &cert); tt_assert(kp2); tt_assert(cert); - tt_mem_op(&cert->signed_key, ==, &kp2->pubkey, sizeof(ed25519_public_key_t)); + tt_mem_op(&cert->signed_key, OP_EQ, &kp2->pubkey, + sizeof(ed25519_public_key_t)); tt_assert(! cert->signing_key_included); - tt_int_op(cert->valid_until, >=, now); - tt_int_op(cert->valid_until, <=, now+7200); + tt_int_op(cert->valid_until, OP_GE, now); + tt_int_op(cert->valid_until, OP_LE, now+7200); /* Create a new key-including certificate signed by kp1 */ ed25519_keypair_free(kp2); @@ -227,8 +228,10 @@ test_routerkeys_ed_key_create(void *arg) tt_assert(kp2); tt_assert(cert); tt_assert(cert->signing_key_included); - tt_mem_op(&cert->signed_key, ==, &kp2->pubkey, sizeof(ed25519_public_key_t)); - tt_mem_op(&cert->signing_key, ==, &kp1->pubkey,sizeof(ed25519_public_key_t)); + tt_mem_op(&cert->signed_key, OP_EQ, &kp2->pubkey, + sizeof(ed25519_public_key_t)); + tt_mem_op(&cert->signing_key, OP_EQ, &kp1->pubkey, + sizeof(ed25519_public_key_t)); done: ed25519_keypair_free(kp1); @@ -261,8 +264,8 @@ test_routerkeys_ed_key_init_basic(void *arg) NULL, now, 0, 7, &cert); tt_assert(kp1 != NULL); tt_assert(cert == NULL); - tt_int_op(stat(get_fname("test_ed_key_1_cert"), &st), <, 0); - tt_int_op(stat(get_fname("test_ed_key_1_secret_key"), &st), ==, 0); + tt_int_op(stat(get_fname("test_ed_key_1_cert"), &st), OP_LT, 0); + tt_int_op(stat(get_fname("test_ed_key_1_secret_key"), &st), OP_EQ, 0); /* Fail to load if we say we need a cert */ kp2 = ed_key_init_from_file(fname1, INIT_ED_KEY_NEEDCERT, LOG_INFO, @@ -279,14 +282,14 @@ test_routerkeys_ed_key_init_basic(void *arg) NULL, now, 0, 7, &cert); tt_assert(kp2 != NULL); tt_assert(cert == NULL); - tt_mem_op(kp1, ==, kp2, sizeof(*kp1)); + tt_mem_op(kp1, OP_EQ, kp2, sizeof(*kp1)); ed25519_keypair_free(kp2); kp2 = NULL; kp2 = ed_key_init_from_file(fname1, 0, LOG_INFO, NULL, now, 0, 7, &cert); tt_assert(kp2 != NULL); tt_assert(cert == NULL); - tt_mem_op(kp1, ==, kp2, sizeof(*kp1)); + tt_mem_op(kp1, OP_EQ, kp2, sizeof(*kp1)); ed25519_keypair_free(kp2); kp2 = NULL; /* Now create a key with a cert. */ @@ -295,34 +298,34 @@ test_routerkeys_ed_key_init_basic(void *arg) LOG_INFO, kp1, now, 7200, 7, &cert); tt_assert(kp2 != NULL); tt_assert(cert != NULL); - tt_mem_op(kp1, !=, kp2, sizeof(*kp1)); - tt_int_op(stat(get_fname("test_ed_key_2_cert"), &st), ==, 0); - tt_int_op(stat(get_fname("test_ed_key_2_secret_key"), &st), ==, 0); + tt_mem_op(kp1, OP_NE, kp2, sizeof(*kp1)); + tt_int_op(stat(get_fname("test_ed_key_2_cert"), &st), OP_EQ, 0); + tt_int_op(stat(get_fname("test_ed_key_2_secret_key"), &st), OP_EQ, 0); tt_assert(cert->cert_valid == 1); - tt_mem_op(&cert->signed_key, ==, &kp2->pubkey, 32); + tt_mem_op(&cert->signed_key, OP_EQ, &kp2->pubkey, 32); /* Now verify we can load the cert... */ kp3 = ed_key_init_from_file(fname2, (INIT_ED_KEY_CREATE| INIT_ED_KEY_NEEDCERT), LOG_INFO, kp1, now, 7200, 7, &cert2); - tt_mem_op(kp2, ==, kp3, sizeof(*kp2)); - tt_mem_op(cert2->encoded, ==, cert->encoded, cert->encoded_len); + tt_mem_op(kp2, OP_EQ, kp3, sizeof(*kp2)); + tt_mem_op(cert2->encoded, OP_EQ, cert->encoded, cert->encoded_len); ed25519_keypair_free(kp3); kp3 = NULL; tor_cert_free(cert2); cert2 = NULL; /* ... even without create... */ kp3 = ed_key_init_from_file(fname2, INIT_ED_KEY_NEEDCERT, LOG_INFO, kp1, now, 7200, 7, &cert2); - tt_mem_op(kp2, ==, kp3, sizeof(*kp2)); - tt_mem_op(cert2->encoded, ==, cert->encoded, cert->encoded_len); + tt_mem_op(kp2, OP_EQ, kp3, sizeof(*kp2)); + tt_mem_op(cert2->encoded, OP_EQ, cert->encoded, cert->encoded_len); ed25519_keypair_free(kp3); kp3 = NULL; tor_cert_free(cert2); cert2 = NULL; /* ... but that we don't crash or anything if we say we don't want it. */ kp3 = ed_key_init_from_file(fname2, INIT_ED_KEY_NEEDCERT, LOG_INFO, kp1, now, 7200, 7, NULL); - tt_mem_op(kp2, ==, kp3, sizeof(*kp2)); + tt_mem_op(kp2, OP_EQ, kp3, sizeof(*kp2)); ed25519_keypair_free(kp3); kp3 = NULL; /* Fail if we're told the wrong signing key */ @@ -367,16 +370,16 @@ test_routerkeys_ed_key_init_split(void *arg) LOG_INFO, NULL, now, 0, 7, &cert); tt_assert(kp1 != NULL); tt_assert(cert == NULL); - tt_int_op(stat(get_fname("test_ed_key_3_cert"), &st), <, 0); - tt_int_op(stat(get_fname("test_ed_key_3_secret_key"), &st), ==, 0); - tt_int_op(stat(get_fname("test_ed_key_3_public_key"), &st), ==, 0); + tt_int_op(stat(get_fname("test_ed_key_3_cert"), &st), OP_LT, 0); + tt_int_op(stat(get_fname("test_ed_key_3_secret_key"), &st), OP_EQ, 0); + tt_int_op(stat(get_fname("test_ed_key_3_public_key"), &st), OP_EQ, 0); /* Load it. */ kp2 = ed_key_init_from_file(fname1, flags|INIT_ED_KEY_CREATE, LOG_INFO, NULL, now, 0, 7, &cert); tt_assert(kp2 != NULL); tt_assert(cert == NULL); - tt_mem_op(kp1, ==, kp2, sizeof(*kp2)); + tt_mem_op(kp1, OP_EQ, kp2, sizeof(*kp2)); ed25519_keypair_free(kp2); kp2 = NULL; /* Okay, try killing the secret key and loading it. */ @@ -385,7 +388,7 @@ test_routerkeys_ed_key_init_split(void *arg) LOG_INFO, NULL, now, 0, 7, &cert); tt_assert(kp2 != NULL); tt_assert(cert == NULL); - tt_mem_op(&kp1->pubkey, ==, &kp2->pubkey, sizeof(kp2->pubkey)); + tt_mem_op(&kp1->pubkey, OP_EQ, &kp2->pubkey, sizeof(kp2->pubkey)); tt_assert(tor_mem_is_zero((char*)kp2->seckey.seckey, sizeof(kp2->seckey.seckey))); ed25519_keypair_free(kp2); kp2 = NULL; @@ -395,7 +398,7 @@ test_routerkeys_ed_key_init_split(void *arg) LOG_INFO, NULL, now, 0, 7, &cert); tt_assert(kp2 != NULL); tt_assert(cert == NULL); - tt_mem_op(&kp1->pubkey, ==, &kp2->pubkey, sizeof(kp2->pubkey)); + tt_mem_op(&kp1->pubkey, OP_EQ, &kp2->pubkey, sizeof(kp2->pubkey)); tt_assert(tor_mem_is_zero((char*)kp2->seckey.seckey, sizeof(kp2->seckey.seckey))); ed25519_keypair_free(kp2); kp2 = NULL; @@ -446,12 +449,12 @@ test_routerkeys_ed_keys_init_all(void *arg) #else mkdir(dir, 0700); mkdir(get_fname("test_ed_keys_init_all/keys"), 0700); -#endif +#endif /* defined(_WIN32) */ options->DataDirectory = dir; - tt_int_op(1, ==, load_ed_keys(options, now)); - tt_int_op(0, ==, generate_ed_link_cert(options, now, 0)); + tt_int_op(1, OP_EQ, load_ed_keys(options, now)); + tt_int_op(0, OP_EQ, generate_ed_link_cert(options, now, 0)); tt_assert(get_master_identity_key()); tt_assert(get_master_identity_key()); tt_assert(get_master_signing_keypair()); @@ -465,21 +468,21 @@ test_routerkeys_ed_keys_init_all(void *arg) link_cert = tor_cert_dup(get_current_link_cert_cert()); /* Call load_ed_keys again, but nothing has changed. */ - tt_int_op(0, ==, load_ed_keys(options, now)); - tt_int_op(0, ==, generate_ed_link_cert(options, now, 0)); - tt_mem_op(&id, ==, get_master_identity_key(), sizeof(id)); - tt_mem_op(&sign, ==, get_master_signing_keypair(), sizeof(sign)); - tt_mem_op(&auth, ==, get_current_auth_keypair(), sizeof(auth)); + tt_int_op(0, OP_EQ, load_ed_keys(options, now)); + tt_int_op(0, OP_EQ, generate_ed_link_cert(options, now, 0)); + tt_mem_op(&id, OP_EQ, get_master_identity_key(), sizeof(id)); + tt_mem_op(&sign, OP_EQ, get_master_signing_keypair(), sizeof(sign)); + tt_mem_op(&auth, OP_EQ, get_current_auth_keypair(), sizeof(auth)); tt_assert(tor_cert_eq(link_cert, get_current_link_cert_cert())); /* Force a reload: we make new link/auth keys. */ routerkeys_free_all(); - tt_int_op(1, ==, load_ed_keys(options, now)); - tt_int_op(0, ==, generate_ed_link_cert(options, now, 0)); - tt_mem_op(&id, ==, get_master_identity_key(), sizeof(id)); - tt_mem_op(&sign, ==, get_master_signing_keypair(), sizeof(sign)); + tt_int_op(1, OP_EQ, load_ed_keys(options, now)); + tt_int_op(0, OP_EQ, generate_ed_link_cert(options, now, 0)); + tt_mem_op(&id, OP_EQ, get_master_identity_key(), sizeof(id)); + tt_mem_op(&sign, OP_EQ, get_master_signing_keypair(), sizeof(sign)); tt_assert(tor_cert_eq(link_cert, get_current_link_cert_cert())); - tt_mem_op(&auth, !=, get_current_auth_keypair(), sizeof(auth)); + tt_mem_op(&auth, OP_NE, get_current_auth_keypair(), sizeof(auth)); tt_assert(get_master_signing_key_cert()); tt_assert(get_current_link_cert_cert()); tt_assert(get_current_auth_key_cert()); @@ -488,12 +491,12 @@ test_routerkeys_ed_keys_init_all(void *arg) memcpy(&auth, get_current_auth_keypair(), sizeof(auth)); /* Force a link/auth-key regeneration by advancing time. */ - tt_int_op(0, ==, load_ed_keys(options, now+3*86400)); - tt_int_op(0, ==, generate_ed_link_cert(options, now+3*86400, 0)); - tt_mem_op(&id, ==, get_master_identity_key(), sizeof(id)); - tt_mem_op(&sign, ==, get_master_signing_keypair(), sizeof(sign)); + tt_int_op(0, OP_EQ, load_ed_keys(options, now+3*86400)); + tt_int_op(0, OP_EQ, generate_ed_link_cert(options, now+3*86400, 0)); + tt_mem_op(&id, OP_EQ, get_master_identity_key(), sizeof(id)); + tt_mem_op(&sign, OP_EQ, get_master_signing_keypair(), sizeof(sign)); tt_assert(! tor_cert_eq(link_cert, get_current_link_cert_cert())); - tt_mem_op(&auth, !=, get_current_auth_keypair(), sizeof(auth)); + tt_mem_op(&auth, OP_NE, get_current_auth_keypair(), sizeof(auth)); tt_assert(get_master_signing_key_cert()); tt_assert(get_current_link_cert_cert()); tt_assert(get_current_auth_key_cert()); @@ -502,12 +505,12 @@ test_routerkeys_ed_keys_init_all(void *arg) memcpy(&auth, get_current_auth_keypair(), sizeof(auth)); /* Force a signing-key regeneration by advancing time. */ - tt_int_op(1, ==, load_ed_keys(options, now+100*86400)); - tt_int_op(0, ==, generate_ed_link_cert(options, now+100*86400, 0)); - tt_mem_op(&id, ==, get_master_identity_key(), sizeof(id)); - tt_mem_op(&sign, !=, get_master_signing_keypair(), sizeof(sign)); + tt_int_op(1, OP_EQ, load_ed_keys(options, now+100*86400)); + tt_int_op(0, OP_EQ, generate_ed_link_cert(options, now+100*86400, 0)); + tt_mem_op(&id, OP_EQ, get_master_identity_key(), sizeof(id)); + tt_mem_op(&sign, OP_NE, get_master_signing_keypair(), sizeof(sign)); tt_assert(! tor_cert_eq(link_cert, get_current_link_cert_cert())); - tt_mem_op(&auth, !=, get_current_auth_keypair(), sizeof(auth)); + tt_mem_op(&auth, OP_NE, get_current_auth_keypair(), sizeof(auth)); tt_assert(get_master_signing_key_cert()); tt_assert(get_current_link_cert_cert()); tt_assert(get_current_auth_key_cert()); @@ -520,12 +523,12 @@ test_routerkeys_ed_keys_init_all(void *arg) routerkeys_free_all(); unlink(get_fname("test_ed_keys_init_all/keys/" "ed25519_master_id_secret_key")); - tt_int_op(1, ==, load_ed_keys(options, now)); - tt_int_op(0, ==, generate_ed_link_cert(options, now, 0)); - tt_mem_op(&id, ==, get_master_identity_key(), sizeof(id)); - tt_mem_op(&sign, ==, get_master_signing_keypair(), sizeof(sign)); + tt_int_op(1, OP_EQ, load_ed_keys(options, now)); + tt_int_op(0, OP_EQ, generate_ed_link_cert(options, now, 0)); + tt_mem_op(&id, OP_EQ, get_master_identity_key(), sizeof(id)); + tt_mem_op(&sign, OP_EQ, get_master_signing_keypair(), sizeof(sign)); tt_assert(! tor_cert_eq(link_cert, get_current_link_cert_cert())); - tt_mem_op(&auth, !=, get_current_auth_keypair(), sizeof(auth)); + tt_mem_op(&auth, OP_NE, get_current_auth_keypair(), sizeof(auth)); tt_assert(get_master_signing_key_cert()); tt_assert(get_current_link_cert_cert()); tt_assert(get_current_auth_key_cert()); @@ -535,7 +538,7 @@ test_routerkeys_ed_keys_init_all(void *arg) log_global_min_severity_ = LOG_ERR; /* Suppress warnings. * XXX (better way to do this)? */ routerkeys_free_all(); - tt_int_op(-1, ==, load_ed_keys(options, now+200*86400)); + tt_int_op(-1, OP_EQ, load_ed_keys(options, now+200*86400)); done: tor_free(dir); @@ -556,20 +559,20 @@ test_routerkeys_cross_certify_ntor(void *args) time_t now = time(NULL); int sign; - tt_int_op(0, ==, ed25519_public_from_base64(&master_key, + tt_int_op(0, OP_EQ, ed25519_public_from_base64(&master_key, "IamwritingthesetestsOnARainyAfternoonin2014")); - tt_int_op(0, ==, curve25519_keypair_generate(&onion_keys, 0)); + tt_int_op(0, OP_EQ, curve25519_keypair_generate(&onion_keys, 0)); cert = make_ntor_onion_key_crosscert(&onion_keys, &master_key, now, 10000, &sign); tt_assert(cert); tt_assert(sign == 0 || sign == 1); - tt_int_op(cert->cert_type, ==, CERT_TYPE_ONION_ID); - tt_int_op(1, ==, ed25519_pubkey_eq(&cert->signed_key, &master_key)); - tt_int_op(0, ==, ed25519_public_key_from_curve25519_public_key( + tt_int_op(cert->cert_type, OP_EQ, CERT_TYPE_ONION_ID); + tt_int_op(1, OP_EQ, ed25519_pubkey_eq(&cert->signed_key, &master_key)); + tt_int_op(0, OP_EQ, ed25519_public_key_from_curve25519_public_key( &onion_check_key, &onion_keys.pubkey, sign)); - tt_int_op(0, ==, tor_cert_checksig(cert, &onion_check_key, now)); + tt_int_op(0, OP_EQ, tor_cert_checksig(cert, &onion_check_key, now)); done: tor_cert_free(cert); @@ -587,7 +590,7 @@ test_routerkeys_cross_certify_tap(void *args) char buf[128]; int n; - tt_int_op(0, ==, ed25519_public_from_base64(&master_key, + tt_int_op(0, OP_EQ, ed25519_public_from_base64(&master_key, "IAlreadyWroteTestsForRouterdescsUsingTheseX")); cc = make_tap_onion_key_crosscert(onion_key, @@ -598,14 +601,14 @@ test_routerkeys_cross_certify_tap(void *args) n = crypto_pk_public_checksig(onion_key, buf, sizeof(buf), (char*)cc, cc_len); - tt_int_op(n,>,0); - tt_int_op(n,==,52); + tt_int_op(n,OP_GT,0); + tt_int_op(n,OP_EQ,52); crypto_pk_get_digest(id_key, digest); - tt_mem_op(buf,==,digest,20); - tt_mem_op(buf+20,==,master_key.pubkey,32); + tt_mem_op(buf,OP_EQ,digest,20); + tt_mem_op(buf+20,OP_EQ,master_key.pubkey,32); - tt_int_op(0, ==, check_tap_onion_key_crosscert(cc, cc_len, + tt_int_op(0, OP_EQ, check_tap_onion_key_crosscert(cc, cc_len, onion_key, &master_key, (uint8_t*)digest)); done: diff --git a/src/test/test_routerlist.c b/src/test/test_routerlist.c index 0b4b6c5c44..3b0e943ce5 100644 --- a/src/test/test_routerlist.c +++ b/src/test/test_routerlist.c @@ -117,7 +117,7 @@ test_routerlist_launch_descriptor_downloads(void *arg) MOCK(initiate_descriptor_downloads, mock_initiate_descriptor_downloads); launch_descriptor_downloads(DIR_PURPOSE_FETCH_MICRODESC, downloadable, NULL, now); - tt_int_op(3, ==, count); + tt_int_op(3, OP_EQ, count); UNMOCK(initiate_descriptor_downloads); done: @@ -148,24 +148,24 @@ construct_consensus(char **consensus_text_md) &v1, &n_vrs, now, 1); networkstatus_vote_free(vote); tt_assert(v1); - tt_int_op(n_vrs, ==, 4); - tt_int_op(smartlist_len(v1->routerstatus_list), ==, 4); + tt_int_op(n_vrs, OP_EQ, 4); + tt_int_op(smartlist_len(v1->routerstatus_list), OP_EQ, 4); dir_common_construct_vote_2(&vote, cert2, sign_skey_2, &dir_common_gen_routerstatus_for_v3ns, &v2, &n_vrs, now, 1); networkstatus_vote_free(vote); tt_assert(v2); - tt_int_op(n_vrs, ==, 4); - tt_int_op(smartlist_len(v2->routerstatus_list), ==, 4); + tt_int_op(n_vrs, OP_EQ, 4); + tt_int_op(smartlist_len(v2->routerstatus_list), OP_EQ, 4); dir_common_construct_vote_3(&vote, cert3, sign_skey_3, &dir_common_gen_routerstatus_for_v3ns, &v3, &n_vrs, now, 1); tt_assert(v3); - tt_int_op(n_vrs, ==, 4); - tt_int_op(smartlist_len(v3->routerstatus_list), ==, 4); + tt_int_op(n_vrs, OP_EQ, 4); + tt_int_op(smartlist_len(v3->routerstatus_list), OP_EQ, 4); networkstatus_vote_free(vote); votes = smartlist_new(); smartlist_add(votes, v1); @@ -247,16 +247,16 @@ test_router_pick_directory_server_impl(void *arg) /* No consensus available, fail early */ rs = router_pick_directory_server_impl(V3_DIRINFO, (const int) 0, NULL); - tt_assert(rs == NULL); + tt_ptr_op(rs, OP_EQ, NULL); construct_consensus(&consensus_text_md); tt_assert(consensus_text_md); con_md = networkstatus_parse_vote_from_string(consensus_text_md, NULL, NS_TYPE_CONSENSUS); tt_assert(con_md); - tt_int_op(con_md->flavor,==, FLAV_MICRODESC); + tt_int_op(con_md->flavor,OP_EQ, FLAV_MICRODESC); tt_assert(con_md->routerstatus_list); - tt_int_op(smartlist_len(con_md->routerstatus_list), ==, 3); + tt_int_op(smartlist_len(con_md->routerstatus_list), OP_EQ, 3); tt_assert(!networkstatus_set_current_consensus_from_ns(con_md, "microdesc")); @@ -287,7 +287,7 @@ test_router_pick_directory_server_impl(void *arg) rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); /* We should not fail now we have a consensus and routerstatus_list * and nodelist are populated. */ - tt_assert(rs != NULL); + tt_ptr_op(rs, OP_NE, NULL); /* Manipulate the nodes so we get the dir server we expect */ router1_id = tor_malloc(DIGEST_LEN); @@ -306,7 +306,7 @@ test_router_pick_directory_server_impl(void *arg) node_router1->is_running = 0; node_router3->is_running = 0; rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); - tt_assert(rs != NULL); + tt_ptr_op(rs, OP_NE, NULL); tt_assert(tor_memeq(rs->identity_digest, router2_id, DIGEST_LEN)); rs = NULL; node_router1->is_running = 1; @@ -319,7 +319,7 @@ test_router_pick_directory_server_impl(void *arg) node_router1->rs->dir_port = 0; node_router3->rs->dir_port = 0; rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); - tt_assert(rs != NULL); + tt_ptr_op(rs, OP_NE, NULL); tt_assert(tor_memeq(rs->identity_digest, router2_id, DIGEST_LEN)); rs = NULL; node_router1->rs->is_v2_dir = 1; @@ -330,7 +330,7 @@ test_router_pick_directory_server_impl(void *arg) node_router1->is_valid = 0; node_router3->is_valid = 0; rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); - tt_assert(rs != NULL); + tt_ptr_op(rs, OP_NE, NULL); tt_assert(tor_memeq(rs->identity_digest, router2_id, DIGEST_LEN)); rs = NULL; node_router1->is_valid = 1; @@ -341,7 +341,7 @@ test_router_pick_directory_server_impl(void *arg) node_router2->rs->last_dir_503_at = now; node_router3->rs->last_dir_503_at = now; rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); - tt_assert(rs != NULL); + tt_ptr_op(rs, OP_NE, NULL); tt_assert(tor_memeq(rs->identity_digest, router1_id, DIGEST_LEN)); node_router2->rs->last_dir_503_at = 0; node_router3->rs->last_dir_503_at = 0; @@ -358,13 +358,13 @@ test_router_pick_directory_server_impl(void *arg) node_router2->rs->or_port = 443; node_router3->rs->or_port = 442; rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); - tt_assert(rs != NULL); + tt_ptr_op(rs, OP_NE, NULL); tt_assert(tor_memeq(rs->identity_digest, router3_id, DIGEST_LEN)); node_router1->rs->or_port = 442; node_router2->rs->or_port = 443; node_router3->rs->or_port = 444; rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); - tt_assert(rs != NULL); + tt_ptr_op(rs, OP_NE, NULL); tt_assert(tor_memeq(rs->identity_digest, router1_id, DIGEST_LEN)); /* Fascist firewall and overloaded */ @@ -373,7 +373,7 @@ test_router_pick_directory_server_impl(void *arg) node_router3->rs->or_port = 442; node_router3->rs->last_dir_503_at = now; rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); - tt_assert(rs != NULL); + tt_ptr_op(rs, OP_NE, NULL); tt_assert(tor_memeq(rs->identity_digest, router1_id, DIGEST_LEN)); node_router3->rs->last_dir_503_at = 0; @@ -391,7 +391,7 @@ test_router_pick_directory_server_impl(void *arg) node_router3->rs->dir_port = 81; node_router1->rs->last_dir_503_at = now; rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); - tt_assert(rs != NULL); + tt_ptr_op(rs, OP_NE, NULL); tt_assert(tor_memeq(rs->identity_digest, router1_id, DIGEST_LEN)); node_router1->rs->last_dir_503_at = 0; @@ -449,27 +449,27 @@ test_routerlist_router_is_already_dir_fetching(void *arg) /* Test that we never get 1 from a NULL connection */ mocked_connection = NULL; - tt_assert(router_is_already_dir_fetching(&test_ap, 1, 1) == 0); - tt_assert(router_is_already_dir_fetching(&test_ap, 1, 0) == 0); - tt_assert(router_is_already_dir_fetching(&test_ap, 0, 1) == 0); + tt_int_op(router_is_already_dir_fetching(&test_ap, 1, 1), OP_EQ, 0); + tt_int_op(router_is_already_dir_fetching(&test_ap, 1, 0), OP_EQ, 0); + tt_int_op(router_is_already_dir_fetching(&test_ap, 0, 1), OP_EQ, 0); /* We always expect 0 in these cases */ - tt_assert(router_is_already_dir_fetching(&test_ap, 0, 0) == 0); - tt_assert(router_is_already_dir_fetching(NULL, 1, 1) == 0); - tt_assert(router_is_already_dir_fetching(&null_addr_ap, 1, 1) == 0); - tt_assert(router_is_already_dir_fetching(&zero_port_ap, 1, 1) == 0); + tt_int_op(router_is_already_dir_fetching(&test_ap, 0, 0), OP_EQ, 0); + tt_int_op(router_is_already_dir_fetching(NULL, 1, 1), OP_EQ, 0); + tt_int_op(router_is_already_dir_fetching(&null_addr_ap, 1, 1), OP_EQ, 0); + tt_int_op(router_is_already_dir_fetching(&zero_port_ap, 1, 1), OP_EQ, 0); /* Test that we get 1 with a connection in the appropriate circumstances */ mocked_connection = connection_new(CONN_TYPE_DIR, AF_INET); - tt_assert(router_is_already_dir_fetching(&test_ap, 1, 1) == 1); - tt_assert(router_is_already_dir_fetching(&test_ap, 1, 0) == 1); - tt_assert(router_is_already_dir_fetching(&test_ap, 0, 1) == 1); + tt_int_op(router_is_already_dir_fetching(&test_ap, 1, 1), OP_EQ, 1); + tt_int_op(router_is_already_dir_fetching(&test_ap, 1, 0), OP_EQ, 1); + tt_int_op(router_is_already_dir_fetching(&test_ap, 0, 1), OP_EQ, 1); /* Test that we get 0 even with a connection in the appropriate * circumstances */ - tt_assert(router_is_already_dir_fetching(&test_ap, 0, 0) == 0); - tt_assert(router_is_already_dir_fetching(NULL, 1, 1) == 0); - tt_assert(router_is_already_dir_fetching(&null_addr_ap, 1, 1) == 0); - tt_assert(router_is_already_dir_fetching(&zero_port_ap, 1, 1) == 0); + tt_int_op(router_is_already_dir_fetching(&test_ap, 0, 0), OP_EQ, 0); + tt_int_op(router_is_already_dir_fetching(NULL, 1, 1), OP_EQ, 0); + tt_int_op(router_is_already_dir_fetching(&null_addr_ap, 1, 1), OP_EQ, 0); + tt_int_op(router_is_already_dir_fetching(&zero_port_ap, 1, 1), OP_EQ, 0); done: /* If a connection is never set up, connection_free chokes on it. */ diff --git a/src/test/test_routerset.c b/src/test/test_routerset.c index 7efd042ed5..c9c69911da 100644 --- a/src/test/test_routerset.c +++ b/src/test/test_routerset.c @@ -1602,7 +1602,7 @@ NS(test_main)(void *arg) */ NS_DECL(const node_t *, node_get_by_nickname, - (const char *nickname, int warn_if_unused)); + (const char *nickname, unsigned flags)); static const char *NS(mock_nickname); static void @@ -1632,11 +1632,11 @@ NS(test_main)(void *arg) } const node_t * -NS(node_get_by_nickname)(const char *nickname, int warn_if_unused) +NS(node_get_by_nickname)(const char *nickname, unsigned flags) { CALLED(node_get_by_nickname)++; tt_str_op(nickname, OP_EQ, NS(mock_nickname)); - tt_int_op(warn_if_unused, OP_EQ, 1); + tt_uint_op(flags, OP_EQ, 0); done: return NULL; @@ -1651,7 +1651,7 @@ NS(node_get_by_nickname)(const char *nickname, int warn_if_unused) */ NS_DECL(const node_t *, node_get_by_nickname, - (const char *nickname, int warn_if_unused)); + (const char *nickname, unsigned flags)); static const char *NS(mock_nickname); static node_t NS(mock_node); @@ -1683,11 +1683,11 @@ NS(test_main)(void *arg) } const node_t * -NS(node_get_by_nickname)(const char *nickname, int warn_if_unused) +NS(node_get_by_nickname)(const char *nickname, unsigned flags) { CALLED(node_get_by_nickname)++; tt_str_op(nickname, OP_EQ, NS(mock_nickname)); - tt_int_op(warn_if_unused, OP_EQ, 1); + tt_int_op(flags, OP_EQ, 0); done: return &NS(mock_node); @@ -1701,7 +1701,7 @@ NS(node_get_by_nickname)(const char *nickname, int warn_if_unused) */ NS_DECL(const node_t *, node_get_by_nickname, - (const char *nickname, int warn_if_unused)); + (const char *nickname, unsigned flags)); static char *NS(mock_nickname); static node_t NS(mock_node); @@ -1735,11 +1735,11 @@ NS(test_main)(void *arg) } const node_t * -NS(node_get_by_nickname)(const char *nickname, int warn_if_unused) +NS(node_get_by_nickname)(const char *nickname, unsigned flags) { CALLED(node_get_by_nickname)++; tt_str_op(nickname, OP_EQ, NS(mock_nickname)); - tt_int_op(warn_if_unused, OP_EQ, 1); + tt_int_op(flags, OP_EQ, 0); done: return &NS(mock_node); diff --git a/src/test/test_scheduler.c b/src/test/test_scheduler.c index 4c536b0905..724a6b56b2 100644 --- a/src/test/test_scheduler.c +++ b/src/test/test_scheduler.c @@ -6,11 +6,16 @@ #include <math.h> #include <event2/event.h> +#define SCHEDULER_KIST_PRIVATE #define TOR_CHANNEL_INTERNAL_ #define CHANNEL_PRIVATE_ #include "or.h" +#include "config.h" #include "compat_libevent.h" #include "channel.h" +#include "channeltls.h" +#include "connection.h" +#include "networkstatus.h" #define SCHEDULER_PRIVATE_ #include "scheduler.h" @@ -18,64 +23,100 @@ #include "test.h" #include "fakechans.h" -/* Event base for scheduelr tests */ -static struct event_base *mock_event_base = NULL; - -/* Statics controlling mocks */ -static circuitmux_t *mock_ccm_tgt_1 = NULL; -static circuitmux_t *mock_ccm_tgt_2 = NULL; +/* Shamelessly stolen from compat_libevent.c */ +#define V(major, minor, patch) \ + (((major) << 24) | ((minor) << 16) | ((patch) << 8)) -static circuitmux_t *mock_cgp_tgt_1 = NULL; -static circuitmux_policy_t *mock_cgp_val_1 = NULL; -static circuitmux_t *mock_cgp_tgt_2 = NULL; -static circuitmux_policy_t *mock_cgp_val_2 = NULL; +/****************************************************************************** + * Statistical info + *****************************************************************************/ static int scheduler_compare_channels_mock_ctr = 0; static int scheduler_run_mock_ctr = 0; -static void channel_flush_some_cells_mock_free_all(void); -static void channel_flush_some_cells_mock_set(channel_t *chan, - ssize_t num_cells); +/****************************************************************************** + * Utility functions and things we need to mock + *****************************************************************************/ +static or_options_t mocked_options; +static const or_options_t * +mock_get_options(void) +{ + return &mocked_options; +} -/* Setup for mock event stuff */ -static void mock_event_free_all(void); -static void mock_event_init(void); +static void +cleanup_scheduler_options(void) +{ + if (mocked_options.SchedulerTypes_) { + SMARTLIST_FOREACH(mocked_options.SchedulerTypes_, int *, i, tor_free(i)); + smartlist_free(mocked_options.SchedulerTypes_); + mocked_options.SchedulerTypes_ = NULL; + } +} + +static void +set_scheduler_options(int val) +{ + int *type; -/* Mocks used by scheduler tests */ -static ssize_t channel_flush_some_cells_mock(channel_t *chan, - ssize_t num_cells); -static int circuitmux_compare_muxes_mock(circuitmux_t *cmux_1, - circuitmux_t *cmux_2); -static const circuitmux_policy_t * circuitmux_get_policy_mock( - circuitmux_t *cmux); -static int scheduler_compare_channels_mock(const void *c1_v, - const void *c2_v); -static void scheduler_run_noop_mock(void); -static struct event_base * tor_libevent_get_base_mock(void); - -/* Scheduler test cases */ -static void test_scheduler_channel_states(void *arg); -static void test_scheduler_compare_channels(void *arg); -static void test_scheduler_initfree(void *arg); -static void test_scheduler_loop(void *arg); -static void test_scheduler_queue_heuristic(void *arg); - -/* Mock event init/free */ + if (mocked_options.SchedulerTypes_ == NULL) { + mocked_options.SchedulerTypes_ = smartlist_new(); + } + type = tor_malloc_zero(sizeof(int)); + *type = val; + smartlist_add(mocked_options.SchedulerTypes_, type); +} -/* Shamelessly stolen from compat_libevent.c */ -#define V(major, minor, patch) \ - (((major) << 24) | ((minor) << 16) | ((patch) << 8)) +static void +clear_options(void) +{ + cleanup_scheduler_options(); + memset(&mocked_options, 0, sizeof(mocked_options)); +} + +static int32_t +mock_vanilla_networkstatus_get_param( + const networkstatus_t *ns, const char *param_name, int32_t default_val, + int32_t min_val, int32_t max_val) +{ + (void)ns; + (void)default_val; + (void)min_val; + (void)max_val; + // only support KISTSchedRunInterval right now + tor_assert(strcmp(param_name, "KISTSchedRunInterval")==0); + return 0; +} + +static int32_t +mock_kist_networkstatus_get_param( + const networkstatus_t *ns, const char *param_name, int32_t default_val, + int32_t min_val, int32_t max_val) +{ + (void)ns; + (void)default_val; + (void)min_val; + (void)max_val; + // only support KISTSchedRunInterval right now + tor_assert(strcmp(param_name, "KISTSchedRunInterval")==0); + return 12; +} +/* Event base for scheduelr tests */ +static struct event_base *mock_event_base = NULL; +/* Setup for mock event stuff */ +static void mock_event_free_all(void); +static void mock_event_init(void); static void mock_event_free_all(void) { - tt_assert(mock_event_base != NULL); + tt_ptr_op(mock_event_base, OP_NE, NULL); if (mock_event_base) { event_base_free(mock_event_base); mock_event_base = NULL; } - tt_ptr_op(mock_event_base, ==, NULL); + tt_ptr_op(mock_event_base, OP_EQ, NULL); done: return; @@ -86,7 +127,7 @@ mock_event_init(void) { struct event_config *cfg = NULL; - tt_ptr_op(mock_event_base, ==, NULL); + tt_ptr_op(mock_event_base, OP_EQ, NULL); /* * Really cut down from tor_libevent_initialize of @@ -104,13 +145,90 @@ mock_event_init(void) event_config_free(cfg); } - tt_assert(mock_event_base != NULL); + tt_ptr_op(mock_event_base, OP_NE, NULL); done: return; } -/* Mocks */ +static struct event_base * +tor_libevent_get_base_mock(void) +{ + return mock_event_base; +} + +static int +scheduler_compare_channels_mock(const void *c1_v, + const void *c2_v) +{ + uintptr_t p1, p2; + + p1 = (uintptr_t)(c1_v); + p2 = (uintptr_t)(c2_v); + + ++scheduler_compare_channels_mock_ctr; + + if (p1 == p2) return 0; + else if (p1 < p2) return 1; + else return -1; +} + +static void +scheduler_run_noop_mock(void) +{ + ++scheduler_run_mock_ctr; +} + +static circuitmux_t *mock_ccm_tgt_1 = NULL; +static circuitmux_t *mock_ccm_tgt_2 = NULL; +static circuitmux_t *mock_cgp_tgt_1 = NULL; +static circuitmux_policy_t *mock_cgp_val_1 = NULL; +static circuitmux_t *mock_cgp_tgt_2 = NULL; +static circuitmux_policy_t *mock_cgp_val_2 = NULL; + +static const circuitmux_policy_t * +circuitmux_get_policy_mock(circuitmux_t *cmux) +{ + const circuitmux_policy_t *result = NULL; + + tt_assert(cmux != NULL); + if (cmux) { + if (cmux == mock_cgp_tgt_1) result = mock_cgp_val_1; + else if (cmux == mock_cgp_tgt_2) result = mock_cgp_val_2; + else result = circuitmux_get_policy__real(cmux); + } + + done: + return result; +} + +static int +circuitmux_compare_muxes_mock(circuitmux_t *cmux_1, + circuitmux_t *cmux_2) +{ + int result = 0; + + tt_assert(cmux_1 != NULL); + tt_assert(cmux_2 != NULL); + + if (cmux_1 != cmux_2) { + if (cmux_1 == mock_ccm_tgt_1 && cmux_2 == mock_ccm_tgt_2) result = -1; + else if (cmux_1 == mock_ccm_tgt_2 && cmux_2 == mock_ccm_tgt_1) { + result = 1; + } else { + if (cmux_1 == mock_ccm_tgt_1 || cmux_1 == mock_ccm_tgt_2) result = -1; + else if (cmux_2 == mock_ccm_tgt_1 || cmux_2 == mock_ccm_tgt_2) { + result = 1; + } else { + result = circuitmux_compare_muxes__real(cmux_1, cmux_2); + } + } + } + /* else result = 0 always */ + + done: + return result; +} typedef struct { const channel_t *chan; @@ -174,6 +292,67 @@ channel_flush_some_cells_mock_set(channel_t *chan, ssize_t num_cells) } } +static int +channel_more_to_flush_mock(channel_t *chan) +{ + tor_assert(chan); + + flush_mock_channel_t *found_mock_ch = NULL; + + /* Check if we have any queued */ + if (! TOR_SIMPLEQ_EMPTY(&chan->incoming_queue)) + return 1; + + SMARTLIST_FOREACH_BEGIN(chans_for_flush_mock, + flush_mock_channel_t *, + flush_mock_ch) { + if (flush_mock_ch != NULL && flush_mock_ch->chan != NULL) { + if (flush_mock_ch->chan == chan) { + /* Found it */ + found_mock_ch = flush_mock_ch; + break; + } + } else { + /* That shouldn't be there... */ + SMARTLIST_DEL_CURRENT(chans_for_flush_mock, flush_mock_ch); + tor_free(flush_mock_ch); + } + } SMARTLIST_FOREACH_END(flush_mock_ch); + + tor_assert(found_mock_ch); + + /* Check if any circuits would like to queue some */ + /* special for the mock: return the number of cells (instead of 1), or zero + * if nothing to flush */ + return (found_mock_ch->cells > 0 ? (int)found_mock_ch->cells : 0 ); +} + +static void +channel_write_to_kernel_mock(channel_t *chan) +{ + (void)chan; + //log_debug(LD_SCHED, "chan=%d writing to kernel", + // (int)chan->global_identifier); +} + +static int +channel_should_write_to_kernel_mock(outbuf_table_t *ot, channel_t *chan) +{ + (void)ot; + (void)chan; + return 1; + /* We could make this more complicated if we wanted. But I don't think doing + * so tests much of anything */ + //static int called_counter = 0; + //if (++called_counter >= 3) { + // called_counter -= 3; + // log_debug(LD_SCHED, "chan=%d should write to kernel", + // (int)chan->global_identifier); + // return 1; + //} + //return 0; +} + static ssize_t channel_flush_some_cells_mock(channel_t *chan, ssize_t num_cells) { @@ -181,7 +360,7 @@ channel_flush_some_cells_mock(channel_t *chan, ssize_t num_cells) char unlimited = 0; flush_mock_channel_t *found = NULL; - tt_assert(chan != NULL); + tt_ptr_op(chan, OP_NE, NULL); if (chan) { if (num_cells < 0) { num_cells = 0; @@ -215,11 +394,6 @@ channel_flush_some_cells_mock(channel_t *chan, ssize_t num_cells) flushed += max; found->cells -= max; - - if (found->cells <= 0) { - smartlist_remove(chans_for_flush_mock, found); - tor_free(found); - } } } } @@ -228,90 +402,26 @@ channel_flush_some_cells_mock(channel_t *chan, ssize_t num_cells) return flushed; } -static int -circuitmux_compare_muxes_mock(circuitmux_t *cmux_1, - circuitmux_t *cmux_2) -{ - int result = 0; - - tt_assert(cmux_1 != NULL); - tt_assert(cmux_2 != NULL); - - if (cmux_1 != cmux_2) { - if (cmux_1 == mock_ccm_tgt_1 && cmux_2 == mock_ccm_tgt_2) result = -1; - else if (cmux_1 == mock_ccm_tgt_2 && cmux_2 == mock_ccm_tgt_1) { - result = 1; - } else { - if (cmux_1 == mock_ccm_tgt_1 || cmux_1 == mock_ccm_tgt_2) result = -1; - else if (cmux_2 == mock_ccm_tgt_1 || cmux_2 == mock_ccm_tgt_2) { - result = 1; - } else { - result = circuitmux_compare_muxes__real(cmux_1, cmux_2); - } - } - } - /* else result = 0 always */ - - done: - return result; -} - -static const circuitmux_policy_t * -circuitmux_get_policy_mock(circuitmux_t *cmux) -{ - const circuitmux_policy_t *result = NULL; - - tt_assert(cmux != NULL); - if (cmux) { - if (cmux == mock_cgp_tgt_1) result = mock_cgp_val_1; - else if (cmux == mock_cgp_tgt_2) result = mock_cgp_val_2; - else result = circuitmux_get_policy__real(cmux); - } - - done: - return result; -} - -static int -scheduler_compare_channels_mock(const void *c1_v, - const void *c2_v) -{ - uintptr_t p1, p2; - - p1 = (uintptr_t)(c1_v); - p2 = (uintptr_t)(c2_v); - - ++scheduler_compare_channels_mock_ctr; - - if (p1 == p2) return 0; - else if (p1 < p2) return 1; - else return -1; -} - static void -scheduler_run_noop_mock(void) +update_socket_info_impl_mock(socket_table_ent_t *ent) { - ++scheduler_run_mock_ctr; + ent->cwnd = ent->unacked = ent->mss = ent->notsent = 0; + ent->limit = INT_MAX; } -static struct event_base * -tor_libevent_get_base_mock(void) -{ - return mock_event_base; -} - -/* Test cases */ - static void -test_scheduler_channel_states(void *arg) +perform_channel_state_tests(int KISTSchedRunInterval, int sched_type) { channel_t *ch1 = NULL, *ch2 = NULL; int old_count; - (void)arg; + /* setup options so we're sure about what sched we are running */ + MOCK(get_options, mock_get_options); + clear_options(); + mocked_options.KISTSchedRunInterval = KISTSchedRunInterval; + set_scheduler_options(sched_type); /* Set up libevent and scheduler */ - mock_event_init(); MOCK(tor_libevent_get_base, tor_libevent_get_base_mock); scheduler_init(); @@ -324,9 +434,9 @@ test_scheduler_channel_states(void *arg) * Disable scheduler_run so we can just check the state transitions * without having to make everything it might call work too. */ - MOCK(scheduler_run, scheduler_run_noop_mock); + ((scheduler_t *) the_scheduler)->run = scheduler_run_noop_mock; - tt_int_op(smartlist_len(channels_pending), ==, 0); + tt_int_op(smartlist_len(channels_pending), OP_EQ, 0); /* Set up a fake channel */ ch1 = new_fake_channel(); @@ -341,7 +451,7 @@ test_scheduler_channel_states(void *arg) tt_assert(ch1->registered); /* It should start off in SCHED_CHAN_IDLE */ - tt_int_op(ch1->scheduler_state, ==, SCHED_CHAN_IDLE); + tt_int_op(ch1->scheduler_state, OP_EQ, SCHED_CHAN_IDLE); /* Now get another one */ ch2 = new_fake_channel(); @@ -351,57 +461,69 @@ test_scheduler_channel_states(void *arg) channel_register(ch2); tt_assert(ch2->registered); - /* Send it to SCHED_CHAN_WAITING_TO_WRITE */ + /* Send ch1 to SCHED_CHAN_WAITING_TO_WRITE */ scheduler_channel_has_waiting_cells(ch1); - tt_int_op(ch1->scheduler_state, ==, SCHED_CHAN_WAITING_TO_WRITE); + tt_int_op(ch1->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_TO_WRITE); /* This should send it to SCHED_CHAN_PENDING */ scheduler_channel_wants_writes(ch1); - tt_int_op(ch1->scheduler_state, ==, SCHED_CHAN_PENDING); - tt_int_op(smartlist_len(channels_pending), ==, 1); + tt_int_op(ch1->scheduler_state, OP_EQ, SCHED_CHAN_PENDING); + tt_int_op(smartlist_len(channels_pending), OP_EQ, 1); /* Now send ch2 to SCHED_CHAN_WAITING_FOR_CELLS */ scheduler_channel_wants_writes(ch2); - tt_int_op(ch2->scheduler_state, ==, SCHED_CHAN_WAITING_FOR_CELLS); + tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_FOR_CELLS); /* Drop ch2 back to idle */ scheduler_channel_doesnt_want_writes(ch2); - tt_int_op(ch2->scheduler_state, ==, SCHED_CHAN_IDLE); + tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_IDLE); /* ...and back to SCHED_CHAN_WAITING_FOR_CELLS */ scheduler_channel_wants_writes(ch2); - tt_int_op(ch2->scheduler_state, ==, SCHED_CHAN_WAITING_FOR_CELLS); + tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_FOR_CELLS); /* ...and this should kick ch2 into SCHED_CHAN_PENDING */ scheduler_channel_has_waiting_cells(ch2); - tt_int_op(ch2->scheduler_state, ==, SCHED_CHAN_PENDING); - tt_int_op(smartlist_len(channels_pending), ==, 2); + tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_PENDING); + tt_int_op(smartlist_len(channels_pending), OP_EQ, 2); /* This should send ch2 to SCHED_CHAN_WAITING_TO_WRITE */ scheduler_channel_doesnt_want_writes(ch2); - tt_int_op(ch2->scheduler_state, ==, SCHED_CHAN_WAITING_TO_WRITE); - tt_int_op(smartlist_len(channels_pending), ==, 1); + tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_TO_WRITE); + tt_int_op(smartlist_len(channels_pending), OP_EQ, 1); /* ...and back to SCHED_CHAN_PENDING */ scheduler_channel_wants_writes(ch2); - tt_int_op(ch2->scheduler_state, ==, SCHED_CHAN_PENDING); - tt_int_op(smartlist_len(channels_pending), ==, 2); + tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_PENDING); + tt_int_op(smartlist_len(channels_pending), OP_EQ, 2); /* Now we exercise scheduler_touch_channel */ old_count = scheduler_compare_channels_mock_ctr; scheduler_touch_channel(ch1); tt_assert(scheduler_compare_channels_mock_ctr > old_count); + /* Release the ch2 and then do it another time to make sure it doesn't blow + * up and we are still in a quiescent state. */ + scheduler_release_channel(ch2); + tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_IDLE); + tt_int_op(smartlist_len(channels_pending), OP_EQ, 1); + /* Cheat a bit so make the release more confused but also will tells us if + * the release did put the channel in the right state. */ + ch2->scheduler_state = SCHED_CHAN_PENDING; + scheduler_release_channel(ch2); + tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_IDLE); + tt_int_op(smartlist_len(channels_pending), OP_EQ, 1); + /* Close */ channel_mark_for_close(ch1); - tt_int_op(ch1->state, ==, CHANNEL_STATE_CLOSING); + tt_int_op(ch1->state, OP_EQ, CHANNEL_STATE_CLOSING); channel_mark_for_close(ch2); - tt_int_op(ch2->state, ==, CHANNEL_STATE_CLOSING); + tt_int_op(ch2->state, OP_EQ, CHANNEL_STATE_CLOSING); channel_closed(ch1); - tt_int_op(ch1->state, ==, CHANNEL_STATE_CLOSED); + tt_int_op(ch1->state, OP_EQ, CHANNEL_STATE_CLOSED); ch1 = NULL; channel_closed(ch2); - tt_int_op(ch2->state, ==, CHANNEL_STATE_CLOSED); + tt_int_op(ch2->state, OP_EQ, CHANNEL_STATE_CLOSED); ch2 = NULL; /* Shut things down */ @@ -415,8 +537,9 @@ test_scheduler_channel_states(void *arg) tor_free(ch2); UNMOCK(scheduler_compare_channels); - UNMOCK(scheduler_run); UNMOCK(tor_libevent_get_base); + UNMOCK(get_options); + cleanup_scheduler_options(); return; } @@ -464,21 +587,21 @@ test_scheduler_compare_channels(void *arg) /* Equal-channel case */ result = scheduler_compare_channels(&c1, &c1); - tt_int_op(result, ==, 0); + tt_int_op(result, OP_EQ, 0); /* Distinct channels, distinct policies */ result = scheduler_compare_channels(&c1, &c2); - tt_int_op(result, ==, -1); + tt_int_op(result, OP_EQ, -1); result = scheduler_compare_channels(&c2, &c1); - tt_int_op(result, ==, 1); + tt_int_op(result, OP_EQ, 1); /* Distinct channels, same policy */ tor_free(mock_cgp_val_2); mock_cgp_val_2 = mock_cgp_val_1; result = scheduler_compare_channels(&c1, &c2); - tt_int_op(result, ==, -1); + tt_int_op(result, OP_EQ, -1); result = scheduler_compare_channels(&c2, &c1); - tt_int_op(result, ==, 1); + tt_int_op(result, OP_EQ, 1); done: @@ -502,40 +625,22 @@ test_scheduler_compare_channels(void *arg) return; } -static void -test_scheduler_initfree(void *arg) -{ - (void)arg; - - tt_ptr_op(channels_pending, ==, NULL); - tt_ptr_op(run_sched_ev, ==, NULL); - - mock_event_init(); - MOCK(tor_libevent_get_base, tor_libevent_get_base_mock); - - scheduler_init(); - - tt_assert(channels_pending != NULL); - tt_assert(run_sched_ev != NULL); - - scheduler_free_all(); - - UNMOCK(tor_libevent_get_base); - mock_event_free_all(); - - tt_ptr_op(channels_pending, ==, NULL); - tt_ptr_op(run_sched_ev, ==, NULL); - - done: - return; -} +/****************************************************************************** + * The actual tests! + *****************************************************************************/ static void -test_scheduler_loop(void *arg) +test_scheduler_loop_vanilla(void *arg) { + (void)arg; channel_t *ch1 = NULL, *ch2 = NULL; + void (*run_func_ptr)(void); - (void)arg; + /* setup options so we're sure about what sched we are running */ + MOCK(get_options, mock_get_options); + clear_options(); + set_scheduler_options(SCHEDULER_VANILLA); + mocked_options.KISTSchedRunInterval = 0; /* Set up libevent and scheduler */ @@ -551,12 +656,14 @@ test_scheduler_loop(void *arg) * Disable scheduler_run so we can just check the state transitions * without having to make everything it might call work too. */ - MOCK(scheduler_run, scheduler_run_noop_mock); + run_func_ptr = the_scheduler->run; + ((scheduler_t *) the_scheduler)->run = scheduler_run_noop_mock; - tt_int_op(smartlist_len(channels_pending), ==, 0); + tt_int_op(smartlist_len(channels_pending), OP_EQ, 0); /* Set up a fake channel */ ch1 = new_fake_channel(); + ch1->magic = TLS_CHAN_MAGIC; tt_assert(ch1); /* Start it off in OPENING */ @@ -567,13 +674,14 @@ test_scheduler_loop(void *arg) channel_register(ch1); tt_assert(ch1->registered); /* Finish opening it */ - channel_change_state(ch1, CHANNEL_STATE_OPEN); + channel_change_state_open(ch1); /* It should start off in SCHED_CHAN_IDLE */ - tt_int_op(ch1->scheduler_state, ==, SCHED_CHAN_IDLE); + tt_int_op(ch1->scheduler_state, OP_EQ, SCHED_CHAN_IDLE); /* Now get another one */ ch2 = new_fake_channel(); + ch2->magic = TLS_CHAN_MAGIC; tt_assert(ch2); ch2->state = CHANNEL_STATE_OPENING; ch2->cmux = circuitmux_alloc(); @@ -584,68 +692,62 @@ test_scheduler_loop(void *arg) * zero and we'll get coverage of that exception case in scheduler_run() */ - tt_int_op(ch1->state, ==, CHANNEL_STATE_OPEN); - tt_int_op(ch2->state, ==, CHANNEL_STATE_OPENING); + tt_int_op(ch1->state, OP_EQ, CHANNEL_STATE_OPEN); + tt_int_op(ch2->state, OP_EQ, CHANNEL_STATE_OPENING); /* Send it to SCHED_CHAN_WAITING_TO_WRITE */ scheduler_channel_has_waiting_cells(ch1); - tt_int_op(ch1->scheduler_state, ==, SCHED_CHAN_WAITING_TO_WRITE); + tt_int_op(ch1->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_TO_WRITE); /* This should send it to SCHED_CHAN_PENDING */ scheduler_channel_wants_writes(ch1); - tt_int_op(ch1->scheduler_state, ==, SCHED_CHAN_PENDING); - tt_int_op(smartlist_len(channels_pending), ==, 1); + tt_int_op(ch1->scheduler_state, OP_EQ, SCHED_CHAN_PENDING); + tt_int_op(smartlist_len(channels_pending), OP_EQ, 1); /* Now send ch2 to SCHED_CHAN_WAITING_FOR_CELLS */ scheduler_channel_wants_writes(ch2); - tt_int_op(ch2->scheduler_state, ==, SCHED_CHAN_WAITING_FOR_CELLS); + tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_FOR_CELLS); /* Drop ch2 back to idle */ scheduler_channel_doesnt_want_writes(ch2); - tt_int_op(ch2->scheduler_state, ==, SCHED_CHAN_IDLE); + tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_IDLE); /* ...and back to SCHED_CHAN_WAITING_FOR_CELLS */ scheduler_channel_wants_writes(ch2); - tt_int_op(ch2->scheduler_state, ==, SCHED_CHAN_WAITING_FOR_CELLS); + tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_FOR_CELLS); /* ...and this should kick ch2 into SCHED_CHAN_PENDING */ scheduler_channel_has_waiting_cells(ch2); - tt_int_op(ch2->scheduler_state, ==, SCHED_CHAN_PENDING); - tt_int_op(smartlist_len(channels_pending), ==, 2); + tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_PENDING); + tt_int_op(smartlist_len(channels_pending), OP_EQ, 2); /* * Now we've got two pending channels and need to fire off - * scheduler_run(); first, unmock it. + * the scheduler run() that we kept. */ - - UNMOCK(scheduler_run); - - scheduler_run(); - - /* Now re-mock it */ - MOCK(scheduler_run, scheduler_run_noop_mock); + run_func_ptr(); /* * Assert that they're still in the states we left and aren't still * pending */ - tt_int_op(ch1->state, ==, CHANNEL_STATE_OPEN); - tt_int_op(ch2->state, ==, CHANNEL_STATE_OPENING); + tt_int_op(ch1->state, OP_EQ, CHANNEL_STATE_OPEN); + tt_int_op(ch2->state, OP_EQ, CHANNEL_STATE_OPENING); tt_assert(ch1->scheduler_state != SCHED_CHAN_PENDING); tt_assert(ch2->scheduler_state != SCHED_CHAN_PENDING); - tt_int_op(smartlist_len(channels_pending), ==, 0); + tt_int_op(smartlist_len(channels_pending), OP_EQ, 0); /* Now, finish opening ch2, and get both back to pending */ - channel_change_state(ch2, CHANNEL_STATE_OPEN); + channel_change_state_open(ch2); scheduler_channel_wants_writes(ch1); scheduler_channel_wants_writes(ch2); scheduler_channel_has_waiting_cells(ch1); scheduler_channel_has_waiting_cells(ch2); - tt_int_op(ch1->state, ==, CHANNEL_STATE_OPEN); - tt_int_op(ch2->state, ==, CHANNEL_STATE_OPEN); - tt_int_op(ch1->scheduler_state, ==, SCHED_CHAN_PENDING); - tt_int_op(ch2->scheduler_state, ==, SCHED_CHAN_PENDING); - tt_int_op(smartlist_len(channels_pending), ==, 2); + tt_int_op(ch1->state, OP_EQ, CHANNEL_STATE_OPEN); + tt_int_op(ch2->state, OP_EQ, CHANNEL_STATE_OPEN); + tt_int_op(ch1->scheduler_state, OP_EQ, SCHED_CHAN_PENDING); + tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_PENDING); + tt_int_op(smartlist_len(channels_pending), OP_EQ, 2); /* Now, set up the channel_flush_some_cells() mock */ MOCK(channel_flush_some_cells, channel_flush_some_cells_mock); @@ -661,38 +763,33 @@ test_scheduler_loop(void *arg) channel_flush_some_cells_mock_set(ch2, 48); /* - * And re-run the scheduler_run() loop with non-zero returns from + * And re-run the scheduler run() loop with non-zero returns from * channel_flush_some_cells() this time. */ - UNMOCK(scheduler_run); - - scheduler_run(); - - /* Now re-mock it */ - MOCK(scheduler_run, scheduler_run_noop_mock); + run_func_ptr(); /* * ch1 should have gone to SCHED_CHAN_WAITING_FOR_CELLS, with 16 flushed * and 32 writeable. */ - tt_int_op(ch1->scheduler_state, ==, SCHED_CHAN_WAITING_FOR_CELLS); + tt_int_op(ch1->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_FOR_CELLS); /* * ...ch2 should also have gone to SCHED_CHAN_WAITING_FOR_CELLS, with * channel_more_to_flush() returning false and channel_num_cells_writeable() * > 0/ */ - tt_int_op(ch2->scheduler_state, ==, SCHED_CHAN_WAITING_FOR_CELLS); + tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_FOR_CELLS); /* Close */ channel_mark_for_close(ch1); - tt_int_op(ch1->state, ==, CHANNEL_STATE_CLOSING); + tt_int_op(ch1->state, OP_EQ, CHANNEL_STATE_CLOSING); channel_mark_for_close(ch2); - tt_int_op(ch2->state, ==, CHANNEL_STATE_CLOSING); + tt_int_op(ch2->state, OP_EQ, CHANNEL_STATE_CLOSING); channel_closed(ch1); - tt_int_op(ch1->state, ==, CHANNEL_STATE_CLOSED); + tt_int_op(ch1->state, OP_EQ, CHANNEL_STATE_CLOSED); ch1 = NULL; channel_closed(ch2); - tt_int_op(ch2->state, ==, CHANNEL_STATE_CLOSED); + tt_int_op(ch2->state, OP_EQ, CHANNEL_STATE_CLOSED); ch2 = NULL; /* Shut things down */ @@ -704,55 +801,297 @@ test_scheduler_loop(void *arg) done: tor_free(ch1); tor_free(ch2); + cleanup_scheduler_options(); UNMOCK(channel_flush_some_cells); UNMOCK(scheduler_compare_channels); - UNMOCK(scheduler_run); UNMOCK(tor_libevent_get_base); + UNMOCK(get_options); +} + +static void +test_scheduler_loop_kist(void *arg) +{ + (void) arg; + +#ifndef HAVE_KIST_SUPPORT + return; +#endif + + channel_t *ch1 = new_fake_channel(), *ch2 = new_fake_channel(); + channel_t *ch3 = new_fake_channel(); + + /* setup options so we're sure about what sched we are running */ + MOCK(get_options, mock_get_options); + MOCK(channel_flush_some_cells, channel_flush_some_cells_mock); + MOCK(channel_more_to_flush, channel_more_to_flush_mock); + MOCK(channel_write_to_kernel, channel_write_to_kernel_mock); + MOCK(channel_should_write_to_kernel, channel_should_write_to_kernel_mock); + MOCK(update_socket_info_impl, update_socket_info_impl_mock); + clear_options(); + mocked_options.KISTSchedRunInterval = 11; + set_scheduler_options(SCHEDULER_KIST); + scheduler_init(); + + tt_assert(ch1); + ch1->magic = TLS_CHAN_MAGIC; + ch1->state = CHANNEL_STATE_OPENING; + ch1->cmux = circuitmux_alloc(); + channel_register(ch1); + tt_assert(ch1->registered); + channel_change_state_open(ch1); + scheduler_channel_has_waiting_cells(ch1); + scheduler_channel_wants_writes(ch1); + channel_flush_some_cells_mock_set(ch1, 5); + + tt_assert(ch2); + ch2->magic = TLS_CHAN_MAGIC; + ch2->state = CHANNEL_STATE_OPENING; + ch2->cmux = circuitmux_alloc(); + channel_register(ch2); + tt_assert(ch2->registered); + channel_change_state_open(ch2); + scheduler_channel_has_waiting_cells(ch2); + scheduler_channel_wants_writes(ch2); + channel_flush_some_cells_mock_set(ch2, 5); + + the_scheduler->run(); + + scheduler_channel_has_waiting_cells(ch1); + channel_flush_some_cells_mock_set(ch1, 5); + + the_scheduler->run(); + + scheduler_channel_has_waiting_cells(ch1); + channel_flush_some_cells_mock_set(ch1, 5); + scheduler_channel_has_waiting_cells(ch2); + channel_flush_some_cells_mock_set(ch2, 5); + + the_scheduler->run(); + + channel_flush_some_cells_mock_free_all(); + + /* We'll try to run this closed channel threw the scheduler loop and make + * sure it ends up in the right state. */ + tt_assert(ch3); + ch3->magic = TLS_CHAN_MAGIC; + ch3->state = CHANNEL_STATE_OPEN; + circuitmux_free(ch3->cmux); + ch3->cmux = circuitmux_alloc(); + channel_register(ch3); + tt_assert(ch3->registered); + + ch3->scheduler_state = SCHED_CHAN_WAITING_FOR_CELLS; + scheduler_channel_has_waiting_cells(ch3); + /* Should be in the pending list now waiting to be handled. */ + tt_int_op(ch3->scheduler_state, OP_EQ, SCHED_CHAN_PENDING); + tt_int_op(smartlist_len(get_channels_pending()), OP_EQ, 1); + /* By running the scheduler on a closed channel, it should end up in the + * IDLE state and not in the pending channel list. */ + ch3->state = CHANNEL_STATE_CLOSED; + the_scheduler->run(); + tt_int_op(ch3->scheduler_state, OP_EQ, SCHED_CHAN_IDLE); + tt_int_op(smartlist_len(get_channels_pending()), OP_EQ, 0); + + done: + /* Prep the channel so the free() function doesn't explode. */ + ch1->state = ch2->state = ch3->state = CHANNEL_STATE_CLOSED; + ch1->registered = ch2->registered = ch3->registered = 0; + channel_free(ch1); + channel_free(ch2); + channel_free(ch3); + UNMOCK(update_socket_info_impl); + UNMOCK(channel_should_write_to_kernel); + UNMOCK(channel_write_to_kernel); + UNMOCK(channel_more_to_flush); + UNMOCK(channel_flush_some_cells); + UNMOCK(get_options); + scheduler_free_all(); + return; } static void -test_scheduler_queue_heuristic(void *arg) +test_scheduler_channel_states(void *arg) { - time_t now = approx_time(); - uint64_t qh; + (void)arg; + perform_channel_state_tests(-1, SCHEDULER_VANILLA); + perform_channel_state_tests(11, SCHEDULER_KIST_LITE); +#ifdef HAVE_KIST_SUPPORT + perform_channel_state_tests(11, SCHEDULER_KIST); +#endif +} +static void +test_scheduler_initfree(void *arg) +{ (void)arg; - queue_heuristic = 0; - queue_heuristic_timestamp = 0; + tt_ptr_op(channels_pending, ==, NULL); + tt_ptr_op(run_sched_ev, ==, NULL); - /* Not yet inited case */ - scheduler_update_queue_heuristic(now - 180); - tt_u64_op(queue_heuristic, ==, 0); - tt_int_op(queue_heuristic_timestamp, ==, now - 180); + mock_event_init(); + MOCK(tor_libevent_get_base, tor_libevent_get_base_mock); + MOCK(get_options, mock_get_options); + set_scheduler_options(SCHEDULER_KIST); + set_scheduler_options(SCHEDULER_KIST_LITE); + set_scheduler_options(SCHEDULER_VANILLA); + + scheduler_init(); - queue_heuristic = 1000000000L; - queue_heuristic_timestamp = now - 120; + tt_ptr_op(channels_pending, !=, NULL); + tt_ptr_op(run_sched_ev, !=, NULL); + /* We have specified nothing in the torrc and there's no consensus so the + * KIST scheduler is what should be in use */ + tt_ptr_op(the_scheduler, ==, get_kist_scheduler()); + tt_int_op(sched_run_interval, ==, 10); - scheduler_update_queue_heuristic(now - 119); - tt_u64_op(queue_heuristic, ==, 500000000L); - tt_int_op(queue_heuristic_timestamp, ==, now - 119); + scheduler_free_all(); - scheduler_update_queue_heuristic(now - 116); - tt_u64_op(queue_heuristic, ==, 62500000L); - tt_int_op(queue_heuristic_timestamp, ==, now - 116); + UNMOCK(tor_libevent_get_base); + mock_event_free_all(); - qh = scheduler_get_queue_heuristic(); - tt_u64_op(qh, ==, 0); + tt_ptr_op(channels_pending, ==, NULL); + tt_ptr_op(run_sched_ev, ==, NULL); done: + UNMOCK(get_options); + cleanup_scheduler_options(); + return; +} + +static void +test_scheduler_can_use_kist(void *arg) +{ + (void)arg; + + int res_should, res_freq; + MOCK(get_options, mock_get_options); + + /* Test force enabling of KIST */ + clear_options(); + mocked_options.KISTSchedRunInterval = 1234; + res_should = scheduler_can_use_kist(); + res_freq = kist_scheduler_run_interval(); +#ifdef HAVE_KIST_SUPPORT + tt_int_op(res_should, ==, 1); +#else /* HAVE_KIST_SUPPORT */ + tt_int_op(res_should, ==, 0); +#endif /* HAVE_KIST_SUPPORT */ + tt_int_op(res_freq, ==, 1234); + + /* Test defer to consensus, but no consensus available */ + clear_options(); + mocked_options.KISTSchedRunInterval = 0; + res_should = scheduler_can_use_kist(); + res_freq = kist_scheduler_run_interval(); +#ifdef HAVE_KIST_SUPPORT + tt_int_op(res_should, ==, 1); +#else /* HAVE_KIST_SUPPORT */ + tt_int_op(res_should, ==, 0); +#endif /* HAVE_KIST_SUPPORT */ + tt_int_op(res_freq, ==, 10); + + /* Test defer to consensus, and kist consensus available */ + MOCK(networkstatus_get_param, mock_kist_networkstatus_get_param); + clear_options(); + mocked_options.KISTSchedRunInterval = 0; + res_should = scheduler_can_use_kist(); + res_freq = kist_scheduler_run_interval(); +#ifdef HAVE_KIST_SUPPORT + tt_int_op(res_should, ==, 1); +#else /* HAVE_KIST_SUPPORT */ + tt_int_op(res_should, ==, 0); +#endif /* HAVE_KIST_SUPPORT */ + tt_int_op(res_freq, ==, 12); + UNMOCK(networkstatus_get_param); + + /* Test defer to consensus, and vanilla consensus available */ + MOCK(networkstatus_get_param, mock_vanilla_networkstatus_get_param); + clear_options(); + mocked_options.KISTSchedRunInterval = 0; + res_should = scheduler_can_use_kist(); + res_freq = kist_scheduler_run_interval(); + tt_int_op(res_should, ==, 0); + tt_int_op(res_freq, ==, 0); + UNMOCK(networkstatus_get_param); + + done: + UNMOCK(get_options); + return; +} + +static void +test_scheduler_ns_changed(void *arg) +{ + (void) arg; + + /* + * Currently no scheduler implementations use the old/new consensuses passed + * in scheduler_notify_networkstatus_changed, so it is okay to pass NULL. + * + * "But then what does test actually exercise???" It tests that + * scheduler_notify_networkstatus_changed fetches the correct value from the + * consensus, and then switches the scheduler if necessasry. + */ + + MOCK(get_options, mock_get_options); + clear_options(); + set_scheduler_options(SCHEDULER_KIST); + set_scheduler_options(SCHEDULER_VANILLA); + + tt_ptr_op(the_scheduler, ==, NULL); + + /* Change from vanilla to kist via consensus */ + the_scheduler = get_vanilla_scheduler(); + MOCK(networkstatus_get_param, mock_kist_networkstatus_get_param); + scheduler_notify_networkstatus_changed(); + UNMOCK(networkstatus_get_param); +#ifdef HAVE_KIST_SUPPORT + tt_ptr_op(the_scheduler, ==, get_kist_scheduler()); +#else + tt_ptr_op(the_scheduler, ==, get_vanilla_scheduler()); +#endif + + /* Change from kist to vanilla via consensus */ + the_scheduler = get_kist_scheduler(); + MOCK(networkstatus_get_param, mock_vanilla_networkstatus_get_param); + scheduler_notify_networkstatus_changed(); + UNMOCK(networkstatus_get_param); + tt_ptr_op(the_scheduler, ==, get_vanilla_scheduler()); + + /* Doesn't change when using KIST */ + the_scheduler = get_kist_scheduler(); + MOCK(networkstatus_get_param, mock_kist_networkstatus_get_param); + scheduler_notify_networkstatus_changed(); + UNMOCK(networkstatus_get_param); +#ifdef HAVE_KIST_SUPPORT + tt_ptr_op(the_scheduler, ==, get_kist_scheduler()); +#else + tt_ptr_op(the_scheduler, ==, get_vanilla_scheduler()); +#endif + + /* Doesn't change when using vanilla */ + the_scheduler = get_vanilla_scheduler(); + MOCK(networkstatus_get_param, mock_vanilla_networkstatus_get_param); + scheduler_notify_networkstatus_changed(); + UNMOCK(networkstatus_get_param); + tt_ptr_op(the_scheduler, ==, get_vanilla_scheduler()); + + done: + UNMOCK(get_options); + cleanup_scheduler_options(); return; } struct testcase_t scheduler_tests[] = { - { "channel_states", test_scheduler_channel_states, TT_FORK, NULL, NULL }, { "compare_channels", test_scheduler_compare_channels, TT_FORK, NULL, NULL }, + { "channel_states", test_scheduler_channel_states, TT_FORK, NULL, NULL }, { "initfree", test_scheduler_initfree, TT_FORK, NULL, NULL }, - { "loop", test_scheduler_loop, TT_FORK, NULL, NULL }, - { "queue_heuristic", test_scheduler_queue_heuristic, - TT_FORK, NULL, NULL }, + { "loop_vanilla", test_scheduler_loop_vanilla, TT_FORK, NULL, NULL }, + { "loop_kist", test_scheduler_loop_kist, TT_FORK, NULL, NULL }, + { "ns_changed", test_scheduler_ns_changed, TT_FORK, NULL, NULL}, + { "should_use_kist", test_scheduler_can_use_kist, TT_FORK, NULL, NULL }, END_OF_TESTCASES }; diff --git a/src/test/test_shared_random.c b/src/test/test_shared_random.c index 026a0f3825..b7cd33715f 100644 --- a/src/test/test_shared_random.c +++ b/src/test/test_shared_random.c @@ -73,65 +73,73 @@ test_get_sr_protocol_phase(void *arg) { retval = parse_rfc1123_time("Wed, 20 Apr 2015 23:59:00 UTC", &the_time); - tt_int_op(retval, ==, 0); + tt_int_op(retval, OP_EQ, 0); phase = get_sr_protocol_phase(the_time); - tt_int_op(phase, ==, SR_PHASE_REVEAL); + tt_int_op(phase, OP_EQ, SR_PHASE_REVEAL); } { retval = parse_rfc1123_time("Wed, 20 Apr 2015 00:00:00 UTC", &the_time); - tt_int_op(retval, ==, 0); + tt_int_op(retval, OP_EQ, 0); phase = get_sr_protocol_phase(the_time); - tt_int_op(phase, ==, SR_PHASE_COMMIT); + tt_int_op(phase, OP_EQ, SR_PHASE_COMMIT); } { retval = parse_rfc1123_time("Wed, 20 Apr 2015 00:00:01 UTC", &the_time); - tt_int_op(retval, ==, 0); + tt_int_op(retval, OP_EQ, 0); phase = get_sr_protocol_phase(the_time); - tt_int_op(phase, ==, SR_PHASE_COMMIT); + tt_int_op(phase, OP_EQ, SR_PHASE_COMMIT); } { retval = parse_rfc1123_time("Wed, 20 Apr 2015 11:59:00 UTC", &the_time); - tt_int_op(retval, ==, 0); + tt_int_op(retval, OP_EQ, 0); phase = get_sr_protocol_phase(the_time); - tt_int_op(phase, ==, SR_PHASE_COMMIT); + tt_int_op(phase, OP_EQ, SR_PHASE_COMMIT); } { retval = parse_rfc1123_time("Wed, 20 Apr 2015 12:00:00 UTC", &the_time); - tt_int_op(retval, ==, 0); + tt_int_op(retval, OP_EQ, 0); phase = get_sr_protocol_phase(the_time); - tt_int_op(phase, ==, SR_PHASE_REVEAL); + tt_int_op(phase, OP_EQ, SR_PHASE_REVEAL); } { retval = parse_rfc1123_time("Wed, 20 Apr 2015 12:00:01 UTC", &the_time); - tt_int_op(retval, ==, 0); + tt_int_op(retval, OP_EQ, 0); phase = get_sr_protocol_phase(the_time); - tt_int_op(phase, ==, SR_PHASE_REVEAL); + tt_int_op(phase, OP_EQ, SR_PHASE_REVEAL); } { retval = parse_rfc1123_time("Wed, 20 Apr 2015 13:00:00 UTC", &the_time); - tt_int_op(retval, ==, 0); + tt_int_op(retval, OP_EQ, 0); phase = get_sr_protocol_phase(the_time); - tt_int_op(phase, ==, SR_PHASE_REVEAL); + tt_int_op(phase, OP_EQ, SR_PHASE_REVEAL); } done: ; } -static networkstatus_t *mock_consensus = NULL; +static networkstatus_t mock_consensus; + +/* Mock function to immediately return our local 'mock_consensus'. */ +static networkstatus_t * +mock_networkstatus_get_live_consensus(time_t now) +{ + (void) now; + return &mock_consensus; +} static void test_get_state_valid_until_time(void *arg) @@ -143,11 +151,23 @@ test_get_state_valid_until_time(void *arg) (void) arg; + MOCK(networkstatus_get_live_consensus, + mock_networkstatus_get_live_consensus); + + retval = parse_rfc1123_time("Mon, 20 Apr 2015 01:00:00 UTC", + &mock_consensus.fresh_until); + tt_int_op(retval, OP_EQ, 0); + + retval = parse_rfc1123_time("Mon, 20 Apr 2015 00:00:00 UTC", + &mock_consensus.valid_after); + tt_int_op(retval, OP_EQ, 0); + { /* Get the valid until time if called at 00:00:01 */ retval = parse_rfc1123_time("Mon, 20 Apr 2015 00:00:01 UTC", ¤t_time); - tt_int_op(retval, ==, 0); + tt_int_op(retval, OP_EQ, 0); + dirvote_recalculate_timing(get_options(), current_time); valid_until_time = get_state_valid_until_time(current_time); /* Compare it with the correct result */ @@ -158,7 +178,8 @@ test_get_state_valid_until_time(void *arg) { retval = parse_rfc1123_time("Mon, 20 Apr 2015 19:22:00 UTC", ¤t_time); - tt_int_op(retval, ==, 0); + tt_int_op(retval, OP_EQ, 0); + dirvote_recalculate_timing(get_options(), current_time); valid_until_time = get_state_valid_until_time(current_time); format_iso_time(tbuf, valid_until_time); @@ -168,7 +189,8 @@ test_get_state_valid_until_time(void *arg) { retval = parse_rfc1123_time("Mon, 20 Apr 2015 23:59:00 UTC", ¤t_time); - tt_int_op(retval, ==, 0); + tt_int_op(retval, OP_EQ, 0); + dirvote_recalculate_timing(get_options(), current_time); valid_until_time = get_state_valid_until_time(current_time); format_iso_time(tbuf, valid_until_time); @@ -178,7 +200,8 @@ test_get_state_valid_until_time(void *arg) { retval = parse_rfc1123_time("Mon, 20 Apr 2015 00:00:00 UTC", ¤t_time); - tt_int_op(retval, ==, 0); + tt_int_op(retval, OP_EQ, 0); + dirvote_recalculate_timing(get_options(), current_time); valid_until_time = get_state_valid_until_time(current_time); format_iso_time(tbuf, valid_until_time); @@ -186,82 +209,148 @@ test_get_state_valid_until_time(void *arg) } done: - ; -} - -/* Mock function to immediately return our local 'mock_consensus'. */ -static networkstatus_t * -mock_networkstatus_get_live_consensus(time_t now) -{ - (void) now; - return mock_consensus; + UNMOCK(networkstatus_get_live_consensus); } -/** Test the get_next_valid_after_time() function. */ +/** Test the function that calculates the start time of the current SRV + * protocol run. */ static void -test_get_next_valid_after_time(void *arg) +test_get_start_time_of_current_run(void *arg) { - time_t current_time; - time_t valid_after_time; - char tbuf[ISO_TIME_LEN + 1]; int retval; + char tbuf[ISO_TIME_LEN + 1]; + time_t current_time, run_start_time; (void) arg; - { - /* Setup a fake consensus just to get the times out of it, since - get_next_valid_after_time() needs them. */ - mock_consensus = tor_malloc_zero(sizeof(networkstatus_t)); + MOCK(networkstatus_get_live_consensus, + mock_networkstatus_get_live_consensus); - retval = parse_rfc1123_time("Mon, 13 Jan 2016 16:00:00 UTC", - &mock_consensus->fresh_until); - tt_int_op(retval, ==, 0); + retval = parse_rfc1123_time("Mon, 20 Apr 2015 01:00:00 UTC", + &mock_consensus.fresh_until); + tt_int_op(retval, OP_EQ, 0); - retval = parse_rfc1123_time("Mon, 13 Jan 2016 15:00:00 UTC", - &mock_consensus->valid_after); - tt_int_op(retval, ==, 0); + retval = parse_rfc1123_time("Mon, 20 Apr 2015 00:00:00 UTC", + &mock_consensus.valid_after); + tt_int_op(retval, OP_EQ, 0); + + { + /* Get start time if called at 00:00:01 */ + retval = parse_rfc1123_time("Mon, 20 Apr 2015 00:00:01 UTC", + ¤t_time); + tt_int_op(retval, OP_EQ, 0); + dirvote_recalculate_timing(get_options(), current_time); + run_start_time = + sr_state_get_start_time_of_current_protocol_run(current_time); - MOCK(networkstatus_get_live_consensus, - mock_networkstatus_get_live_consensus); + /* Compare it with the correct result */ + format_iso_time(tbuf, run_start_time); + tt_str_op("2015-04-20 00:00:00", OP_EQ, tbuf); } { - /* Get the valid after time if called at 00:00:00 */ - retval = parse_rfc1123_time("Mon, 20 Apr 2015 00:00:00 UTC", + retval = parse_rfc1123_time("Mon, 20 Apr 2015 23:59:59 UTC", ¤t_time); - tt_int_op(retval, ==, 0); - valid_after_time = get_next_valid_after_time(current_time); + tt_int_op(retval, OP_EQ, 0); + dirvote_recalculate_timing(get_options(), current_time); + run_start_time = + sr_state_get_start_time_of_current_protocol_run(current_time); /* Compare it with the correct result */ - format_iso_time(tbuf, valid_after_time); - tt_str_op("2015-04-20 01:00:00", OP_EQ, tbuf); + format_iso_time(tbuf, run_start_time); + tt_str_op("2015-04-20 00:00:00", OP_EQ, tbuf); } { - /* Get the valid until time if called at 00:00:01 */ - retval = parse_rfc1123_time("Mon, 20 Apr 2015 00:00:01 UTC", + retval = parse_rfc1123_time("Mon, 20 Apr 2015 00:00:00 UTC", ¤t_time); - tt_int_op(retval, ==, 0); - valid_after_time = get_next_valid_after_time(current_time); + tt_int_op(retval, OP_EQ, 0); + dirvote_recalculate_timing(get_options(), current_time); + run_start_time = + sr_state_get_start_time_of_current_protocol_run(current_time); /* Compare it with the correct result */ - format_iso_time(tbuf, valid_after_time); - tt_str_op("2015-04-20 01:00:00", OP_EQ, tbuf); - } + format_iso_time(tbuf, run_start_time); + tt_str_op("2015-04-20 00:00:00", OP_EQ, tbuf); + } + + /* Next test is testing it without a consensus to use the testing voting + * interval . */ + UNMOCK(networkstatus_get_live_consensus); + /* Now let's alter the voting schedule and check the correctness of the + * function. Voting interval of 10 seconds, means that an SRV protocol run + * takes 10 seconds * 24 rounds = 4 mins */ { - retval = parse_rfc1123_time("Mon, 20 Apr 2015 23:30:01 UTC", + or_options_t *options = get_options_mutable(); + options->V3AuthVotingInterval = 10; + options->TestingV3AuthInitialVotingInterval = 10; + retval = parse_rfc1123_time("Mon, 20 Apr 2015 00:15:32 UTC", ¤t_time); - tt_int_op(retval, ==, 0); - valid_after_time = get_next_valid_after_time(current_time); + tt_int_op(retval, OP_EQ, 0); + dirvote_recalculate_timing(get_options(), current_time); + run_start_time = + sr_state_get_start_time_of_current_protocol_run(current_time); /* Compare it with the correct result */ - format_iso_time(tbuf, valid_after_time); - tt_str_op("2015-04-21 00:00:00", OP_EQ, tbuf); - } + format_iso_time(tbuf, run_start_time); + tt_str_op("2015-04-20 00:12:00", OP_EQ, tbuf); + } + + done: + ; +} + +/** Do some rudimentary consistency checks between the functions that + * understand the shared random protocol schedule */ +static void +test_get_start_time_functions(void *arg) +{ + (void) arg; + int retval; + + MOCK(networkstatus_get_live_consensus, + mock_networkstatus_get_live_consensus); + + retval = parse_rfc1123_time("Mon, 20 Apr 2015 01:00:00 UTC", + &mock_consensus.fresh_until); + tt_int_op(retval, OP_EQ, 0); + + retval = parse_rfc1123_time("Mon, 20 Apr 2015 00:00:00 UTC", + &mock_consensus.valid_after); + tt_int_op(retval, OP_EQ, 0); + time_t now = mock_consensus.valid_after; + + dirvote_recalculate_timing(get_options(), now); + time_t start_time_of_protocol_run = + sr_state_get_start_time_of_current_protocol_run(now); + tt_assert(start_time_of_protocol_run); + + /* Check that the round start time of the beginning of the run, is itself */ + tt_int_op(get_start_time_of_current_round(), OP_EQ, + start_time_of_protocol_run); done: - networkstatus_vote_free(mock_consensus); + UNMOCK(networkstatus_get_live_consensus); +} + +static void +test_get_sr_protocol_duration(void *arg) +{ + (void) arg; + + /* Check that by default an SR phase is 12 hours */ + tt_int_op(sr_state_get_phase_duration(), OP_EQ, 12*60*60); + tt_int_op(sr_state_get_protocol_run_duration(), OP_EQ, 24*60*60); + + /* Now alter the voting interval and check that the SR phase is 2 mins long + * if voting happens every 10 seconds (10*12 seconds = 2 mins) */ + or_options_t *options = get_options_mutable(); + options->V3AuthVotingInterval = 10; + tt_int_op(sr_state_get_phase_duration(), OP_EQ, 2*60); + tt_int_op(sr_state_get_protocol_run_duration(), OP_EQ, 4*60); + + done: ; } /* In this test we are going to generate a sr_commit_t object and validate @@ -304,18 +393,18 @@ test_sr_commit(void *arg) tt_assert(!tor_mem_is_zero((char *) our_commit->random_number, sizeof(our_commit->random_number))); /* Commit and reveal timestamp should be the same. */ - tt_u64_op(our_commit->commit_ts, ==, our_commit->reveal_ts); + tt_u64_op(our_commit->commit_ts, OP_EQ, our_commit->reveal_ts); /* We should have a hashed reveal. */ tt_assert(!tor_mem_is_zero(our_commit->hashed_reveal, sizeof(our_commit->hashed_reveal))); /* Do we have a valid encoded commit and reveal. Note the following only * tests if the generated values are correct. Their could be a bug in * the decode function but we test them seperately. */ - tt_int_op(0, ==, reveal_decode(our_commit->encoded_reveal, + tt_int_op(0, OP_EQ, reveal_decode(our_commit->encoded_reveal, &test_commit)); - tt_int_op(0, ==, commit_decode(our_commit->encoded_commit, + tt_int_op(0, OP_EQ, commit_decode(our_commit->encoded_commit, &test_commit)); - tt_int_op(0, ==, verify_commit_and_reveal(our_commit)); + tt_int_op(0, OP_EQ, verify_commit_and_reveal(our_commit)); } /* Let's make sure our verify commit and reveal function works. We'll @@ -328,21 +417,21 @@ test_sr_commit(void *arg) /* Timestamp MUST match. */ test_commit.commit_ts = test_commit.reveal_ts - 42; setup_full_capture_of_logs(LOG_WARN); - tt_int_op(-1, ==, verify_commit_and_reveal(&test_commit)); + tt_int_op(-1, OP_EQ, verify_commit_and_reveal(&test_commit)); expect_log_msg_containing("doesn't match reveal timestamp"); teardown_capture_of_logs(); memcpy(&test_commit, our_commit, sizeof(test_commit)); - tt_int_op(0, ==, verify_commit_and_reveal(&test_commit)); + tt_int_op(0, OP_EQ, verify_commit_and_reveal(&test_commit)); /* Hashed reveal must match the H(encoded_reveal). */ memset(test_commit.hashed_reveal, 'X', sizeof(test_commit.hashed_reveal)); setup_full_capture_of_logs(LOG_WARN); - tt_int_op(-1, ==, verify_commit_and_reveal(&test_commit)); + tt_int_op(-1, OP_EQ, verify_commit_and_reveal(&test_commit)); expect_single_log_msg_containing("doesn't match the commit value"); teardown_capture_of_logs(); memcpy(&test_commit, our_commit, sizeof(test_commit)); - tt_int_op(0, ==, verify_commit_and_reveal(&test_commit)); + tt_int_op(0, OP_EQ, verify_commit_and_reveal(&test_commit)); } /* We'll build a list of values from our commit that our parsing function @@ -396,26 +485,26 @@ test_encoding(void *arg) /* Hash random number because we don't expose bytes of the RNG. */ ret = crypto_digest256(hashed_rand, raw_rand, sizeof(raw_rand), SR_DIGEST_ALG); - tt_int_op(0, ==, ret); + tt_int_op(0, OP_EQ, ret); /* Hash reveal value. */ - tt_int_op(SR_REVEAL_BASE64_LEN, ==, strlen(encoded_reveal)); + tt_int_op(SR_REVEAL_BASE64_LEN, OP_EQ, strlen(encoded_reveal)); ret = crypto_digest256(hashed_reveal, encoded_reveal, strlen(encoded_reveal), SR_DIGEST_ALG); - tt_int_op(0, ==, ret); - tt_int_op(SR_COMMIT_BASE64_LEN, ==, strlen(encoded_commit)); + tt_int_op(0, OP_EQ, ret); + tt_int_op(SR_COMMIT_BASE64_LEN, OP_EQ, strlen(encoded_commit)); /* Test our commit/reveal decode functions. */ { /* Test the reveal encoded value. */ - tt_int_op(0, ==, reveal_decode(encoded_reveal, &parsed_commit)); - tt_u64_op(ts, ==, parsed_commit.reveal_ts); + tt_int_op(0, OP_EQ, reveal_decode(encoded_reveal, &parsed_commit)); + tt_u64_op(ts, OP_EQ, parsed_commit.reveal_ts); tt_mem_op(hashed_rand, OP_EQ, parsed_commit.random_number, sizeof(hashed_rand)); /* Test the commit encoded value. */ memset(&parsed_commit, 0, sizeof(parsed_commit)); - tt_int_op(0, ==, commit_decode(encoded_commit, &parsed_commit)); - tt_u64_op(ts, ==, parsed_commit.commit_ts); + tt_int_op(0, OP_EQ, commit_decode(encoded_commit, &parsed_commit)); + tt_u64_op(ts, OP_EQ, parsed_commit.commit_ts); tt_mem_op(encoded_commit, OP_EQ, parsed_commit.encoded_commit, sizeof(parsed_commit.encoded_commit)); tt_mem_op(hashed_reveal, OP_EQ, parsed_commit.hashed_reveal, @@ -430,7 +519,7 @@ test_encoding(void *arg) memcpy(parsed_commit.random_number, hashed_rand, sizeof(parsed_commit.random_number)); ret = reveal_encode(&parsed_commit, encoded, sizeof(encoded)); - tt_int_op(SR_REVEAL_BASE64_LEN, ==, ret); + tt_int_op(SR_REVEAL_BASE64_LEN, OP_EQ, ret); tt_mem_op(encoded_reveal, OP_EQ, encoded, strlen(encoded_reveal)); } @@ -441,7 +530,7 @@ test_encoding(void *arg) memcpy(parsed_commit.hashed_reveal, hashed_reveal, sizeof(parsed_commit.hashed_reveal)); ret = commit_encode(&parsed_commit, encoded, sizeof(encoded)); - tt_int_op(SR_COMMIT_BASE64_LEN, ==, ret); + tt_int_op(SR_COMMIT_BASE64_LEN, OP_EQ, ret); tt_mem_op(encoded_commit, OP_EQ, encoded, strlen(encoded_commit)); } @@ -518,7 +607,7 @@ test_vote(void *arg) tt_assert(lines); /* Split the lines. We expect 2 here. */ ret = smartlist_split_string(chunks, lines, "\n", SPLIT_IGNORE_BLANK, 0); - tt_int_op(ret, ==, 4); + tt_int_op(ret, OP_EQ, 4); tt_str_op(smartlist_get(chunks, 0), OP_EQ, "shared-rand-participate"); /* Get our commitment line and will validate it agains our commit. The * format is as follow: @@ -528,7 +617,7 @@ test_vote(void *arg) char *commit_line = smartlist_get(chunks, 1); tt_assert(commit_line); ret = smartlist_split_string(tokens, commit_line, " ", 0, 0); - tt_int_op(ret, ==, 6); + tt_int_op(ret, OP_EQ, 6); tt_str_op(smartlist_get(tokens, 0), OP_EQ, "shared-rand-commit"); tt_str_op(smartlist_get(tokens, 1), OP_EQ, "1"); tt_str_op(smartlist_get(tokens, 2), OP_EQ, @@ -536,7 +625,7 @@ test_vote(void *arg) char digest[DIGEST_LEN]; base16_decode(digest, sizeof(digest), smartlist_get(tokens, 3), HEX_DIGEST_LEN); - tt_mem_op(digest, ==, our_commit->rsa_identity, sizeof(digest)); + tt_mem_op(digest, OP_EQ, our_commit->rsa_identity, sizeof(digest)); tt_str_op(smartlist_get(tokens, 4), OP_EQ, our_commit->encoded_commit); tt_str_op(smartlist_get(tokens, 5), OP_EQ, our_commit->encoded_reveal) ; @@ -552,7 +641,7 @@ test_vote(void *arg) /* Set valid flag explicitly here to compare since it's not set by * simply parsing the commit. */ parsed_commit->valid = 1; - tt_mem_op(parsed_commit, ==, our_commit, sizeof(*our_commit)); + tt_mem_op(parsed_commit, OP_EQ, our_commit, sizeof(*our_commit)); /* minor cleanup */ SMARTLIST_FOREACH(tokens, char *, s, tor_free(s)); @@ -562,7 +651,7 @@ test_vote(void *arg) char *prev_srv_line = smartlist_get(chunks, 2); tt_assert(prev_srv_line); ret = smartlist_split_string(tokens, prev_srv_line, " ", 0, 0); - tt_int_op(ret, ==, 3); + tt_int_op(ret, OP_EQ, 3); tt_str_op(smartlist_get(tokens, 0), OP_EQ, "shared-rand-previous-value"); tt_str_op(smartlist_get(tokens, 1), OP_EQ, "42"); tt_str_op(smartlist_get(tokens, 2), OP_EQ, @@ -576,7 +665,7 @@ test_vote(void *arg) char *current_srv_line = smartlist_get(chunks, 3); tt_assert(current_srv_line); ret = smartlist_split_string(tokens, current_srv_line, " ", 0, 0); - tt_int_op(ret, ==, 3); + tt_int_op(ret, OP_EQ, 3); tt_str_op(smartlist_get(tokens, 0), OP_EQ, "shared-rand-current-value"); tt_str_op(smartlist_get(tokens, 1), OP_EQ, "128"); tt_str_op(smartlist_get(tokens, 2), OP_EQ, @@ -629,7 +718,7 @@ test_state_load_from_disk(void *arg) /* First try with a nonexistent path. */ ret = disk_state_load_from_disk_impl("NONEXISTENTNONEXISTENT"); - tt_assert(ret == -ENOENT); + tt_int_op(ret, OP_EQ, -ENOENT); /* Now create a mock state directory and state file */ #ifdef _WIN32 @@ -637,9 +726,9 @@ test_state_load_from_disk(void *arg) #else ret = mkdir(dir, 0700); #endif - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); ret = write_str_to_file(sr_state_path, sr_state_str, 0); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); /* Try to load the directory itself. Should fail. */ ret = disk_state_load_from_disk_impl(dir); @@ -647,11 +736,11 @@ test_state_load_from_disk(void *arg) /* State should be non-existent at this point. */ the_sr_state = get_sr_state(); - tt_assert(!the_sr_state); + tt_ptr_op(the_sr_state, OP_EQ, NULL); /* Now try to load the correct file! */ ret = disk_state_load_from_disk_impl(sr_state_path); - tt_assert(ret == 0); + tt_int_op(ret, OP_EQ, 0); /* Check the content of the state */ /* XXX check more deeply!!! */ @@ -689,7 +778,7 @@ test_sr_setup_commits(void) tt_assert(auth_cert); options->AuthoritativeDir = 1; - tt_int_op(0, ==, load_ed_keys(options, now)); + tt_int_op(0, OP_EQ, load_ed_keys(options, now)); } /* Generate three dummy commits according to sr_srv_calc_ref.py . Then @@ -775,11 +864,12 @@ test_sr_setup_commits(void) save_commit_to_state(commit_b); save_commit_to_state(commit_c); save_commit_to_state(commit_d); - tt_int_op(digestmap_size(get_sr_state()->commits), ==, 4); + tt_int_op(digestmap_size(get_sr_state()->commits), OP_EQ, 4); /* Now during REVEAL phase save commit D by restoring its reveal. */ set_sr_phase(SR_PHASE_REVEAL); save_commit_to_state(place_holder); + place_holder = NULL; tt_str_op(commit_d->encoded_reveal, OP_EQ, "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"); /* Go back to an empty encoded reveal value. */ @@ -788,6 +878,7 @@ test_sr_setup_commits(void) tt_assert(!commit_has_reveal_value(commit_d)); done: + tor_free(place_holder); authority_cert_free(auth_cert); } @@ -820,9 +911,9 @@ test_sr_compute_srv(void *arg) /* Check the result against the test vector */ current_srv = sr_state_get_current_srv(); tt_assert(current_srv); - tt_u64_op(current_srv->num_reveals, ==, 3); + tt_u64_op(current_srv->num_reveals, OP_EQ, 3); tt_str_op(hex_str((char*)current_srv->value, 32), - ==, + OP_EQ, SRV_TEST_VECTOR); done: @@ -878,7 +969,7 @@ test_sr_get_majority_srv_from_votes(void *arg) /* Since it's only one vote with an SRV, it should not achieve majority and hence no SRV will be returned. */ chosen_srv = get_majority_srv_from_votes(votes, 1); - tt_assert(!chosen_srv); + tt_ptr_op(chosen_srv, OP_EQ, NULL); { /* Now put in 8 more votes. Let SRV_1 have majority. */ int i; @@ -897,21 +988,21 @@ test_sr_get_majority_srv_from_votes(void *arg) smartlist_add(votes, vote); } - tt_int_op(smartlist_len(votes), ==, 9); + tt_int_op(smartlist_len(votes), OP_EQ, 9); } /* Now we achieve majority for SRV_1, but not the AuthDirNumSRVAgreements requirement. So still not picking an SRV. */ set_num_srv_agreements(8); chosen_srv = get_majority_srv_from_votes(votes, 1); - tt_assert(!chosen_srv); + tt_ptr_op(chosen_srv, OP_EQ, NULL); /* We will now lower the AuthDirNumSRVAgreements requirement by tweaking the * consensus parameter and we will try again. This time it should work. */ set_num_srv_agreements(7); chosen_srv = get_majority_srv_from_votes(votes, 1); tt_assert(chosen_srv); - tt_u64_op(chosen_srv->num_reveals, ==, 42); + tt_u64_op(chosen_srv->num_reveals, OP_EQ, 42); tt_mem_op(chosen_srv->value, OP_EQ, SRV_1, sizeof(chosen_srv->value)); done: @@ -935,7 +1026,7 @@ test_utils(void *arg) memcpy(srv->value, srv_value, sizeof(srv->value)); dup_srv = srv_dup(srv); tt_assert(dup_srv); - tt_u64_op(dup_srv->num_reveals, ==, srv->num_reveals); + tt_u64_op(dup_srv->num_reveals, OP_EQ, srv->num_reveals); tt_mem_op(dup_srv->value, OP_EQ, srv->value, sizeof(srv->value)); tor_free(srv); tor_free(dup_srv); @@ -955,10 +1046,10 @@ test_utils(void *arg) sr_commit_t commit1, commit2; memcpy(commit1.encoded_commit, payload, sizeof(commit1.encoded_commit)); memcpy(commit2.encoded_commit, payload, sizeof(commit2.encoded_commit)); - tt_int_op(commitments_are_the_same(&commit1, &commit2), ==, 1); + tt_int_op(commitments_are_the_same(&commit1, &commit2), OP_EQ, 1); /* Let's corrupt one of them. */ memset(commit1.encoded_commit, 'A', sizeof(commit1.encoded_commit)); - tt_int_op(commitments_are_the_same(&commit1, &commit2), ==, 0); + tt_int_op(commitments_are_the_same(&commit1, &commit2), OP_EQ, 0); } /* Testing commit_is_authoritative(). */ @@ -969,32 +1060,32 @@ test_utils(void *arg) tt_assert(!crypto_pk_generate_key(k)); - tt_int_op(0, ==, crypto_pk_get_digest(k, digest)); + tt_int_op(0, OP_EQ, crypto_pk_get_digest(k, digest)); memcpy(commit.rsa_identity, digest, sizeof(commit.rsa_identity)); - tt_int_op(commit_is_authoritative(&commit, digest), ==, 1); + tt_int_op(commit_is_authoritative(&commit, digest), OP_EQ, 1); /* Change the pubkey. */ memset(commit.rsa_identity, 0, sizeof(commit.rsa_identity)); - tt_int_op(commit_is_authoritative(&commit, digest), ==, 0); + tt_int_op(commit_is_authoritative(&commit, digest), OP_EQ, 0); crypto_pk_free(k); } /* Testing get_phase_str(). */ { - tt_str_op(get_phase_str(SR_PHASE_REVEAL), ==, "reveal"); - tt_str_op(get_phase_str(SR_PHASE_COMMIT), ==, "commit"); + tt_str_op(get_phase_str(SR_PHASE_REVEAL), OP_EQ, "reveal"); + tt_str_op(get_phase_str(SR_PHASE_COMMIT), OP_EQ, "commit"); } /* Testing phase transition */ { init_authority_state(); set_sr_phase(SR_PHASE_COMMIT); - tt_int_op(is_phase_transition(SR_PHASE_REVEAL), ==, 1); - tt_int_op(is_phase_transition(SR_PHASE_COMMIT), ==, 0); + tt_int_op(is_phase_transition(SR_PHASE_REVEAL), OP_EQ, 1); + tt_int_op(is_phase_transition(SR_PHASE_COMMIT), OP_EQ, 0); set_sr_phase(SR_PHASE_REVEAL); - tt_int_op(is_phase_transition(SR_PHASE_REVEAL), ==, 0); - tt_int_op(is_phase_transition(SR_PHASE_COMMIT), ==, 1); + tt_int_op(is_phase_transition(SR_PHASE_REVEAL), OP_EQ, 0); + tt_int_op(is_phase_transition(SR_PHASE_COMMIT), OP_EQ, 1); /* Junk. */ - tt_int_op(is_phase_transition(42), ==, 1); + tt_int_op(is_phase_transition(42), OP_EQ, 1); } done: @@ -1022,24 +1113,24 @@ test_state_transition(void *arg) sr_commit_t *commit = sr_generate_our_commit(now, mock_cert); tt_assert(commit); sr_state_add_commit(commit); - tt_int_op(digestmap_size(state->commits), ==, 1); + tt_int_op(digestmap_size(state->commits), OP_EQ, 1); /* Let's test our delete feature. */ sr_state_delete_commits(); - tt_int_op(digestmap_size(state->commits), ==, 0); + tt_int_op(digestmap_size(state->commits), OP_EQ, 0); /* Add it back so we can continue the rest of the test because after * deletiong our commit will be freed so generate a new one. */ commit = sr_generate_our_commit(now, mock_cert); tt_assert(commit); sr_state_add_commit(commit); - tt_int_op(digestmap_size(state->commits), ==, 1); + tt_int_op(digestmap_size(state->commits), OP_EQ, 1); state->n_reveal_rounds = 42; state->n_commit_rounds = 43; state->n_protocol_runs = 44; reset_state_for_new_protocol_run(now); - tt_int_op(state->n_reveal_rounds, ==, 0); - tt_int_op(state->n_commit_rounds, ==, 0); - tt_u64_op(state->n_protocol_runs, ==, 45); - tt_int_op(digestmap_size(state->commits), ==, 0); + tt_int_op(state->n_reveal_rounds, OP_EQ, 0); + tt_int_op(state->n_commit_rounds, OP_EQ, 0); + tt_u64_op(state->n_protocol_runs, OP_EQ, 45); + tt_int_op(digestmap_size(state->commits), OP_EQ, 0); } /* Test SRV rotation in our state. */ @@ -1052,7 +1143,7 @@ test_state_transition(void *arg) state_rotate_srv(); prev = sr_state_get_previous_srv(); tt_assert(prev == cur); - tt_assert(!sr_state_get_current_srv()); + tt_ptr_op(sr_state_get_current_srv(), OP_EQ, NULL); sr_state_clean_srvs(); } @@ -1077,18 +1168,18 @@ test_state_transition(void *arg) /* Also, make sure we did change the current. */ tt_assert(sr_state_get_current_srv() != cur); /* We should have our commitment alone. */ - tt_int_op(digestmap_size(state->commits), ==, 1); - tt_int_op(state->n_reveal_rounds, ==, 0); - tt_int_op(state->n_commit_rounds, ==, 0); + tt_int_op(digestmap_size(state->commits), OP_EQ, 1); + tt_int_op(state->n_reveal_rounds, OP_EQ, 0); + tt_int_op(state->n_commit_rounds, OP_EQ, 0); /* 46 here since we were at 45 just before. */ - tt_u64_op(state->n_protocol_runs, ==, 46); + tt_u64_op(state->n_protocol_runs, OP_EQ, 46); } /* Cleanup of SRVs. */ { sr_state_clean_srvs(); - tt_assert(!sr_state_get_current_srv()); - tt_assert(!sr_state_get_previous_srv()); + tt_ptr_op(sr_state_get_current_srv(), OP_EQ, NULL); + tt_ptr_op(sr_state_get_previous_srv(), OP_EQ, NULL); } done: @@ -1117,6 +1208,8 @@ test_keep_commit(void *arg) state = get_sr_state(); } + crypto_rand((char*)fp, sizeof(fp)); + /* Test this very important function that tells us if we should keep a * commit or not in our state. Most of it depends on the phase and what's * in the commit so we'll change the commit as we go. */ @@ -1125,21 +1218,21 @@ test_keep_commit(void *arg) /* Set us in COMMIT phase for starter. */ set_sr_phase(SR_PHASE_COMMIT); /* We should never keep a commit from a non authoritative authority. */ - tt_int_op(should_keep_commit(commit, fp, SR_PHASE_COMMIT), ==, 0); + tt_int_op(should_keep_commit(commit, fp, SR_PHASE_COMMIT), OP_EQ, 0); /* This should NOT be kept because it has a reveal value in it. */ tt_assert(commit_has_reveal_value(commit)); tt_int_op(should_keep_commit(commit, commit->rsa_identity, - SR_PHASE_COMMIT), ==, 0); + SR_PHASE_COMMIT), OP_EQ, 0); /* Add it to the state which should return to not keep it. */ sr_state_add_commit(commit); tt_int_op(should_keep_commit(commit, commit->rsa_identity, - SR_PHASE_COMMIT), ==, 0); + SR_PHASE_COMMIT), OP_EQ, 0); /* Remove it from state so we can continue our testing. */ digestmap_remove(state->commits, commit->rsa_identity); /* Let's remove our reveal value which should make it OK to keep it. */ memset(commit->encoded_reveal, 0, sizeof(commit->encoded_reveal)); tt_int_op(should_keep_commit(commit, commit->rsa_identity, - SR_PHASE_COMMIT), ==, 1); + SR_PHASE_COMMIT), OP_EQ, 1); /* Let's reset our commit and go into REVEAL phase. */ sr_commit_free(commit); @@ -1151,17 +1244,17 @@ test_keep_commit(void *arg) memset(dup_commit->encoded_reveal, 0, sizeof(dup_commit->encoded_reveal)); set_sr_phase(SR_PHASE_REVEAL); /* We should never keep a commit from a non authoritative authority. */ - tt_int_op(should_keep_commit(commit, fp, SR_PHASE_REVEAL), ==, 0); + tt_int_op(should_keep_commit(commit, fp, SR_PHASE_REVEAL), OP_EQ, 0); /* We shouldn't accept a commit that is not in our state. */ tt_int_op(should_keep_commit(commit, commit->rsa_identity, - SR_PHASE_REVEAL), ==, 0); + SR_PHASE_REVEAL), OP_EQ, 0); /* Important to add the commit _without_ the reveal here. */ sr_state_add_commit(dup_commit); - tt_int_op(digestmap_size(state->commits), ==, 1); + tt_int_op(digestmap_size(state->commits), OP_EQ, 1); /* Our commit should be valid that is authoritative, contains a reveal, be * in the state and commitment and reveal values match. */ tt_int_op(should_keep_commit(commit, commit->rsa_identity, - SR_PHASE_REVEAL), ==, 1); + SR_PHASE_REVEAL), OP_EQ, 1); /* The commit shouldn't be kept if it's not verified that is no matchin * hashed reveal. */ { @@ -1172,7 +1265,7 @@ test_keep_commit(void *arg) memset(commit->hashed_reveal, 0, sizeof(commit->hashed_reveal)); setup_full_capture_of_logs(LOG_WARN); tt_int_op(should_keep_commit(commit, commit->rsa_identity, - SR_PHASE_REVEAL), ==, 0); + SR_PHASE_REVEAL), OP_EQ, 0); expect_log_msg_containing("doesn't match the commit value."); expect_log_msg_containing("has an invalid reveal value."); assert_log_predicate(mock_saved_log_n_entries() == 2, @@ -1183,11 +1276,11 @@ test_keep_commit(void *arg) } /* We shouldn't keep a commit that has no reveal. */ tt_int_op(should_keep_commit(dup_commit, dup_commit->rsa_identity, - SR_PHASE_REVEAL), ==, 0); + SR_PHASE_REVEAL), OP_EQ, 0); /* We must not keep a commit that is not the same from the commit phase. */ memset(commit->encoded_commit, 0, sizeof(commit->encoded_commit)); tt_int_op(should_keep_commit(commit, commit->rsa_identity, - SR_PHASE_REVEAL), ==, 0); + SR_PHASE_REVEAL), OP_EQ, 0); done: teardown_capture_of_logs(); @@ -1225,35 +1318,35 @@ test_state_update(void *arg) /* We are in COMMIT phase here and we'll trigger a state update but no * transition. */ sr_state_update(commit_phase_time); - tt_int_op(state->valid_after, ==, commit_phase_time); - tt_int_op(state->n_commit_rounds, ==, 1); - tt_int_op(state->phase, ==, SR_PHASE_COMMIT); - tt_int_op(digestmap_size(state->commits), ==, 1); + tt_int_op(state->valid_after, OP_EQ, commit_phase_time); + tt_int_op(state->n_commit_rounds, OP_EQ, 1); + tt_int_op(state->phase, OP_EQ, SR_PHASE_COMMIT); + tt_int_op(digestmap_size(state->commits), OP_EQ, 1); /* We are still in the COMMIT phase here but we'll trigger a state * transition to the REVEAL phase. */ sr_state_update(reveal_phase_time); - tt_int_op(state->phase, ==, SR_PHASE_REVEAL); - tt_int_op(state->valid_after, ==, reveal_phase_time); + tt_int_op(state->phase, OP_EQ, SR_PHASE_REVEAL); + tt_int_op(state->valid_after, OP_EQ, reveal_phase_time); /* Only our commit should be in there. */ - tt_int_op(digestmap_size(state->commits), ==, 1); - tt_int_op(state->n_reveal_rounds, ==, 1); + tt_int_op(digestmap_size(state->commits), OP_EQ, 1); + tt_int_op(state->n_reveal_rounds, OP_EQ, 1); /* We can't update a state with a valid after _lower_ than the creation * time so here it is. */ sr_state_update(commit_phase_time); - tt_int_op(state->valid_after, ==, reveal_phase_time); + tt_int_op(state->valid_after, OP_EQ, reveal_phase_time); /* Finally, let's go back in COMMIT phase so we can test the state update * of a new protocol run. */ state->valid_after = 0; sr_state_update(commit_phase_time); - tt_int_op(state->valid_after, ==, commit_phase_time); - tt_int_op(state->n_commit_rounds, ==, 1); - tt_int_op(state->n_reveal_rounds, ==, 0); - tt_u64_op(state->n_protocol_runs, ==, 1); - tt_int_op(state->phase, ==, SR_PHASE_COMMIT); - tt_int_op(digestmap_size(state->commits), ==, 1); + tt_int_op(state->valid_after, OP_EQ, commit_phase_time); + tt_int_op(state->n_commit_rounds, OP_EQ, 1); + tt_int_op(state->n_reveal_rounds, OP_EQ, 0); + tt_u64_op(state->n_protocol_runs, OP_EQ, 1); + tt_int_op(state->phase, OP_EQ, SR_PHASE_COMMIT); + tt_int_op(digestmap_size(state->commits), OP_EQ, 1); tt_assert(state->current_srv); done: @@ -1270,7 +1363,11 @@ struct testcase_t sr_tests[] = { NULL, NULL }, { "encoding", test_encoding, TT_FORK, NULL, NULL }, - { "get_next_valid_after_time", test_get_next_valid_after_time, TT_FORK, + { "get_start_time_of_current_run", test_get_start_time_of_current_run, + TT_FORK, NULL, NULL }, + { "get_start_time_functions", test_get_start_time_functions, + TT_FORK, NULL, NULL }, + { "get_sr_protocol_duration", test_get_sr_protocol_duration, TT_FORK, NULL, NULL }, { "get_state_valid_until_time", test_get_state_valid_until_time, TT_FORK, NULL, NULL }, diff --git a/src/test/test_socks.c b/src/test/test_socks.c index bb1be11f2b..9ae7530e22 100644 --- a/src/test/test_socks.c +++ b/src/test/test_socks.c @@ -6,7 +6,9 @@ #include "or.h" #include "buffers.h" #include "config.h" +#include "proto_socks.h" #include "test.h" +#include "log_test_helpers.h" typedef struct socks_test_data_t { socks_request_t *req; @@ -43,7 +45,7 @@ static const struct testcase_setup_t socks_setup = { buf_t *buf = testdata->buf; \ socks_request_t *socks = testdata->req; #define ADD_DATA(buf, s) \ - write_to_buf(s, sizeof(s)-1, buf) + buf_add(buf, s, sizeof(s)-1) static void socks_request_clear(socks_request_t *socks) @@ -61,8 +63,9 @@ test_socks_4_unsupported_commands(void *ptr) /* SOCKS 4 Send BIND [02] to IP address 2.2.2.2:4369 */ ADD_DATA(buf, "\x04\x02\x11\x11\x02\x02\x02\x02\x00"); - tt_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, - get_options()->SafeSocks) == -1); + tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks), + OP_EQ, -1); tt_int_op(4,OP_EQ, socks->socks_version); tt_int_op(0,OP_EQ, socks->replylen); /* XXX: shouldn't tor reply? */ @@ -80,8 +83,9 @@ test_socks_4_supported_commands(void *ptr) /* SOCKS 4 Send CONNECT [01] to IP address 2.2.2.2:4370 */ ADD_DATA(buf, "\x04\x01\x11\x12\x02\x02\x02\x03\x00"); - tt_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, - get_options()->SafeSocks) == 1); + tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks), + OP_EQ, 1); tt_int_op(4,OP_EQ, socks->socks_version); tt_int_op(0,OP_EQ, socks->replylen); /* XXX: shouldn't tor reply? */ tt_int_op(SOCKS_COMMAND_CONNECT,OP_EQ, socks->command); @@ -95,8 +99,8 @@ test_socks_4_supported_commands(void *ptr) /* SOCKS 4 Send CONNECT [01] to IP address 2.2.2.2:4369 with userid*/ ADD_DATA(buf, "\x04\x01\x11\x12\x02\x02\x02\x04me\x00"); - tt_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, - get_options()->SafeSocks) == 1); + tt_int_op(fetch_from_buf_socks(buf, socks, 1, 0), + OP_EQ, 1); tt_int_op(4,OP_EQ, socks->socks_version); tt_int_op(0,OP_EQ, socks->replylen); /* XXX: shouldn't tor reply? */ tt_int_op(SOCKS_COMMAND_CONNECT,OP_EQ, socks->command); @@ -112,8 +116,9 @@ test_socks_4_supported_commands(void *ptr) /* SOCKS 4a Send RESOLVE [F0] request for torproject.org */ ADD_DATA(buf, "\x04\xF0\x01\x01\x00\x00\x00\x02me\x00torproject.org\x00"); - tt_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, - get_options()->SafeSocks) == 1); + tt_int_op(fetch_from_buf_socks(buf, socks, 1, + get_options()->SafeSocks), + OP_EQ, 1); tt_int_op(4,OP_EQ, socks->socks_version); tt_int_op(0,OP_EQ, socks->replylen); /* XXX: shouldn't tor reply? */ tt_str_op("torproject.org",OP_EQ, socks->address); @@ -124,6 +129,83 @@ test_socks_4_supported_commands(void *ptr) ; } +static void +test_socks_4_bad_arguments(void *ptr) +{ + SOCKS_TEST_INIT(); + setup_capture_of_logs(LOG_DEBUG); + + /* Try with 0 IPv4 address */ + ADD_DATA(buf, "\x04\x01\x00\x50\x00\x00\x00\x00\x00"); + tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks), + OP_EQ, -1); + buf_clear(buf); + expect_log_msg_containing("Port or DestIP is zero."); + mock_clean_saved_logs(); + + /* Try with 0 port */ + ADD_DATA(buf, "\x04\x01\x00\x00\x01\x02\x03\x04\x00"); + tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks), + OP_EQ, -1); + buf_clear(buf); + expect_log_msg_containing("Port or DestIP is zero."); + mock_clean_saved_logs(); + + /* Try with 2000-byte username (!) */ + ADD_DATA(buf, "\x04\x01\x00\x50\x01\x02\x03\x04"); + int i; + for (i = 0; i < 200; ++i) { + ADD_DATA(buf, "1234567890"); + } + ADD_DATA(buf, "\x00"); + tt_int_op(fetch_from_buf_socks(buf, socks, 1, 0), + OP_EQ, -1); + buf_clear(buf); + expect_log_msg_containing("user name too long; rejecting."); + mock_clean_saved_logs(); + + /* Try with 2000-byte hostname */ + ADD_DATA(buf, "\x04\x01\x00\x50\x00\x00\x00\x01\x00"); + for (i = 0; i < 200; ++i) { + ADD_DATA(buf, "1234567890"); + } + ADD_DATA(buf, "\x00"); + { + const char *p; + size_t s; + buf_pullup(buf, 9999, &p, &s); + } + tt_int_op(fetch_from_buf_socks(buf, socks, 1, 0), + OP_EQ, -1); + buf_clear(buf); + expect_log_msg_containing("Destaddr too long. Rejecting."); + mock_clean_saved_logs(); + + /* Try with 2000-byte hostname, not terminated. */ + ADD_DATA(buf, "\x04\x01\x00\x50\x00\x00\x00\x01\x00"); + for (i = 0; i < 200; ++i) { + ADD_DATA(buf, "1234567890"); + } + tt_int_op(fetch_from_buf_socks(buf, socks, 1, 0), + OP_EQ, -1); + buf_clear(buf); + expect_log_msg_containing("Destaddr too long."); + mock_clean_saved_logs(); + + /* Socks4, bogus hostname */ + ADD_DATA(buf, "\x04\x01\x00\x50\x00\x00\x00\x01\x00" "---\x00" ); + tt_int_op(fetch_from_buf_socks(buf, socks, 1, 0), OP_EQ, -1); + buf_clear(buf); + expect_log_msg_containing("Your application (using socks4 to port 80) " + "gave Tor a malformed hostname: "); + mock_clean_saved_logs(); + + done: + teardown_capture_of_logs(); +} + /** Perform unsupported SOCKS 5 commands */ static void test_socks_5_unsupported_commands(void *ptr) @@ -199,10 +281,28 @@ test_socks_5_supported_commands(void *ptr) tt_int_op(0,OP_EQ, buf_datalen(buf)); socks_request_clear(socks); + /* SOCKS 5 Send CONNECT [01] to one of the ipv6 addresses for + torproject.org:80 */ + ADD_DATA(buf, "\x05\x01\x00"); + ADD_DATA(buf, "\x05\x01\x00\x04" + "\x20\x02\x41\xb8\x02\x02\x0d\xeb\x02\x13\x21\xff\xfe\x20\x14\x26" + "\x00\x50"); + tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks),OP_EQ, 1); + tt_int_op(5,OP_EQ, socks->socks_version); + tt_int_op(2,OP_EQ, socks->replylen); + tt_int_op(5,OP_EQ, socks->reply[0]); + tt_int_op(0,OP_EQ, socks->reply[1]); + tt_str_op("[2002:41b8:202:deb:213:21ff:fe20:1426]",OP_EQ, socks->address); + tt_int_op(80,OP_EQ, socks->port); + + tt_int_op(0,OP_EQ, buf_datalen(buf)); + socks_request_clear(socks); + /* SOCKS 5 Send CONNECT [01] to FQDN torproject.org:4369 */ ADD_DATA(buf, "\x05\x01\x00"); ADD_DATA(buf, "\x05\x01\x00\x03\x0Etorproject.org\x11\x11"); - tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + tt_int_op(fetch_from_buf_socks(buf, socks, 1, get_options()->SafeSocks),OP_EQ, 1); tt_int_op(5,OP_EQ, socks->socks_version); @@ -218,8 +318,9 @@ test_socks_5_supported_commands(void *ptr) /* SOCKS 5 Send RESOLVE [F0] request for torproject.org:4369 */ ADD_DATA(buf, "\x05\x01\x00"); ADD_DATA(buf, "\x05\xF0\x00\x03\x0Etorproject.org\x01\x02"); - tt_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, - get_options()->SafeSocks) == 1); + tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks), + OP_EQ, 1); tt_int_op(5,OP_EQ, socks->socks_version); tt_int_op(2,OP_EQ, socks->replylen); tt_int_op(5,OP_EQ, socks->reply[0]); @@ -229,47 +330,46 @@ test_socks_5_supported_commands(void *ptr) tt_int_op(0,OP_EQ, buf_datalen(buf)); socks_request_clear(socks); - /* SOCKS 5 Should reject RESOLVE [F0] request for IPv4 address + /* SOCKS 5 Should NOT reject RESOLVE [F0] request for IPv4 address * string if SafeSocks is enabled. */ ADD_DATA(buf, "\x05\x01\x00"); ADD_DATA(buf, "\x05\xF0\x00\x03\x07"); ADD_DATA(buf, "8.8.8.8"); - ADD_DATA(buf, "\x01\x02"); - tt_assert(fetch_from_buf_socks(buf,socks,get_options()->TestSocks,1) - == -1); + ADD_DATA(buf, "\x11\x11"); + tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, 1), + OP_EQ, 1); - tt_int_op(5,OP_EQ,socks->socks_version); - tt_int_op(10,OP_EQ,socks->replylen); - tt_int_op(5,OP_EQ,socks->reply[0]); - tt_int_op(SOCKS5_NOT_ALLOWED,OP_EQ,socks->reply[1]); - tt_int_op(1,OP_EQ,socks->reply[3]); + tt_str_op("8.8.8.8", OP_EQ, socks->address); + tt_int_op(4369, OP_EQ, socks->port); + + tt_int_op(0, OP_EQ, buf_datalen(buf)); socks_request_clear(socks); - /* SOCKS 5 should reject RESOLVE [F0] reject for IPv6 address + /* SOCKS 5 should NOT reject RESOLVE [F0] reject for IPv6 address * string if SafeSocks is enabled. */ ADD_DATA(buf, "\x05\x01\x00"); ADD_DATA(buf, "\x05\xF0\x00\x03\x27"); ADD_DATA(buf, "2001:0db8:85a3:0000:0000:8a2e:0370:7334"); ADD_DATA(buf, "\x01\x02"); - tt_assert(fetch_from_buf_socks(buf,socks,get_options()->TestSocks,1) - == -1); + tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, 1), + OP_EQ, -1); - tt_int_op(5,OP_EQ,socks->socks_version); - tt_int_op(10,OP_EQ,socks->replylen); - tt_int_op(5,OP_EQ,socks->reply[0]); - tt_int_op(SOCKS5_NOT_ALLOWED,OP_EQ,socks->reply[1]); - tt_int_op(1,OP_EQ,socks->reply[3]); + tt_str_op("2001:0db8:85a3:0000:0000:8a2e:0370:7334", OP_EQ, socks->address); + tt_int_op(258, OP_EQ, socks->port); + + tt_int_op(0, OP_EQ, buf_datalen(buf)); socks_request_clear(socks); /* SOCKS 5 Send RESOLVE_PTR [F1] for IP address 2.2.2.5 */ ADD_DATA(buf, "\x05\x01\x00"); ADD_DATA(buf, "\x05\xF1\x00\x01\x02\x02\x02\x05\x01\x03"); - tt_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, - get_options()->SafeSocks) == 1); + tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks), + OP_EQ, 1); tt_int_op(5,OP_EQ, socks->socks_version); tt_int_op(2,OP_EQ, socks->replylen); tt_int_op(5,OP_EQ, socks->reply[0]); @@ -380,9 +480,9 @@ test_socks_5_authenticate_with_data(void *ptr) /* SOCKS 5 Send username/password */ /* SOCKS 5 Send CONNECT [01] to IP address 2.2.2.2:4369 */ ADD_DATA(buf, "\x01\x02me\x03you\x05\x01\x00\x01\x02\x02\x02\x02\x11\x11"); - tt_assert(fetch_from_buf_socks(buf, socks, - get_options()->TestSocks, - get_options()->SafeSocks) == 1); + tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks), + OP_EQ, 1); tt_int_op(5,OP_EQ, socks->socks_version); tt_int_op(2,OP_EQ, socks->replylen); tt_int_op(1,OP_EQ, socks->reply[0]); @@ -400,6 +500,48 @@ test_socks_5_authenticate_with_data(void *ptr) ; } +/** Try to negotiate an unsupported authentication type */ +static void +test_socks_5_auth_unsupported_type(void *ptr) +{ + SOCKS_TEST_INIT(); + + /* None of these authentication types are recognized. */ + ADD_DATA(buf, "\x05\x03\x99\x21\x10"); + tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks), + OP_EQ, -1); + tt_int_op(0,OP_EQ, socks->socks_version); + tt_int_op(2,OP_EQ, socks->replylen); + tt_int_op(5,OP_EQ, socks->reply[0]); + tt_int_op(0xff,OP_EQ, socks->reply[1]); + + done: + ; +} + +/** Try to negotiate an unsupported version of username/password auth. */ +static void +test_socks_5_auth_unsupported_version(void *ptr) +{ + SOCKS_TEST_INIT(); + + /* Negotiate username/password */ + ADD_DATA(buf, "\x05\x01\x02"); + tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks), + OP_EQ, 0); + tt_int_op(0,OP_EQ, buf_datalen(buf)); /* buf should be drained */ + /* Now, suggest an unrecognized username/password version */ + ADD_DATA(buf, "\x02\x05" "hello" "\x05" "world"); + tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks), + OP_EQ, -1); + + done: + ; +} + /** Perform SOCKS 5 authentication before method negotiated */ static void test_socks_5_auth_before_negotiation(void *ptr) @@ -408,9 +550,9 @@ test_socks_5_auth_before_negotiation(void *ptr) /* SOCKS 5 Send username/password */ ADD_DATA(buf, "\x01\x02me\x02me"); - tt_assert(fetch_from_buf_socks(buf, socks, - get_options()->TestSocks, - get_options()->SafeSocks) == -1); + tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks), + OP_EQ, -1); tt_int_op(0,OP_EQ, socks->socks_version); tt_int_op(0,OP_EQ, socks->replylen); tt_int_op(0,OP_EQ, socks->reply[0]); @@ -492,20 +634,397 @@ test_socks_5_malformed_commands(void *ptr) ; } +static void +test_socks_5_bad_arguments(void *ptr) +{ + SOCKS_TEST_INIT(); + setup_capture_of_logs(LOG_DEBUG); + + /* Socks5, bogus hostname */ + ADD_DATA(buf, "\x05\x01\x00" "\x05\x01\x00\x03\x03" "---" "\x00\x50" ); + tt_int_op(fetch_from_buf_socks(buf, socks, 1, 0), OP_EQ, -1); + buf_clear(buf); + expect_log_msg_containing("Your application (using socks5 to port 80) " + "gave Tor a malformed hostname: "); + mock_clean_saved_logs(); + socks_request_clear(socks); + + done: + teardown_capture_of_logs(); +} + +/** check for correct behavior when the socks command has not arrived. */ +static void +test_socks_truncated(void *ptr) +{ + const struct { + enum { NONE, AUTH, ALL } setup; + const char *body; + size_t len; + } commands[] = { + /* SOCKS4 */ + /* Connect, to an IP. */ + { NONE, "\x04\x01\x05\x05\x01\x02\x03\x04\x00", 9}, + /* Connect, to an IP, with authentication. */ + { NONE, "\x04\x01\x05\x05\x01\x02\x03\x04hello\x00", 14}, + /* SOCKS4A */ + /* Connect, to a hostname */ + { NONE, "\x04\x01\x09\x09\x00\x00\x00\x01\x00www.example.com\x00", 25}, + /* Connect, to a hostname, with authentication */ + { NONE, "\x04\x01\x09\x09\x00\x00\x00\x01hi\x00www.example.com\x00", 27}, + /* SOCKS5 */ + /* initial handshake */ + { NONE, "\x05\x00", 2 }, + /* no-auth handshake */ + { NONE, "\x05\x03\x99\x21\x10", 5 }, + /* SOCSK5, username-password, all empty. */ + { AUTH, "\x01\x00\x00", 3 }, + /* SOCSK5, username-password, 1 char each. */ + { AUTH, "\x01\x01x\x01y", 5 }, + /* SOCSK5, username-password, max length. */ + { AUTH, "\x01\xff" + "Ogni tempo ha il suo fascismo: se ne notano i segni premonitori " + "dovunque la concentrazione di potere nega al cittadino la " + "possibilit\xc3\xa0 e la capacit\xc3\xa0 di esprimere ed attuare la " + "sua volont\xc3\xa0. A questo si arriva in molti modi, non " + "necessariamente col terror" + "\xff" + "e dell'intimidazione poliziesca, ma anche negando o distorcendo " + "l'informazione, inquinando la giustizia, paralizzando la scuola, " + "diffondendo in molti modi sottili la nostalgia per un mondo in cui " + "regnava sovrano l'ordine, ed in cui la sicurezza dei pochi " + /* privilegiati riposava sul lavoro forzato e sul silenzio forzato dei + molti. -- Primo Levi */ , 513 }, + /* Socks5, IPv4 address */ + { ALL, "\x05\x01\x00\x01\x01\x02\x03\x04\x20\x20", 10 }, + /* Socks5, IPv6 address */ + { ALL, "\x05\x01\x00\x04" + "\x49\x20\x48\x41\x5a\x20\x45\x41\x53\x54\x45\x52\x20\x45\x47\x47" + "\x20\x20", 22 }, + /* Socks5, hostname, empty. */ + { ALL, "\x05\x01\x00\x03" "\x00" "\x00\x50", 7 }, + /* Socks5, hostname, moderate. */ + { ALL, "\x05\x01\x00\x03" "\x11" "onion.example.com" "\x00\x50", 24 }, + /* Socks5, hostname, maximum. */ + { ALL, "\x05\x01\x00\x03" "\xff" + "whatsoever.I.shall.see.or.hear.in.the.course.of.my.profession.as.well." + "as.outside.my.profession.in.my.intercourse.with.men.if.it.be.what." + "should.not.be.published.abroad.I.will.never.divulge.holding.such." + "things.to.be.holy.secrets.x.hippocratic.oath.wikipedia" + "\x00\x50", 262 }, + }; + unsigned i, j; + SOCKS_TEST_INIT(); + for (i = 0; i < ARRAY_LENGTH(commands); ++i) { + for (j = 0; j < commands[i].len; ++j) { + switch (commands[i].setup) { + default: /* Falls through */ + case NONE: + /* This test calls for no setup on the socks state. */ + break; + case AUTH: + /* This test calls for the socks state to be waiting for + * username/password authentication */ + ADD_DATA(buf, "\x05\x01\x02"); + tt_int_op(0, OP_EQ, fetch_from_buf_socks(buf, socks, 0, 0)); + tt_int_op(0, OP_EQ, buf_datalen(buf)); + break; + case ALL: + /* This test calls for the socks state to be waiting for + * the connection request */ + ADD_DATA(buf, "\x05\x01\x00"); + tt_int_op(0, OP_EQ, fetch_from_buf_socks(buf, socks, 0, 0)); + tt_int_op(0, OP_EQ, buf_datalen(buf)); + } + + TT_BLATHER(("Checking command %u, length %u, omitting char %u", i, j, + (unsigned)commands[i].body[j])); + buf_add(buf, commands[i].body, j); + /* This should return 0 meaning "not done yet" */ + tt_int_op(0, OP_EQ, fetch_from_buf_socks(buf, socks, 0, 0)); + tt_uint_op(j, OP_EQ, buf_datalen(buf)); /* Nothing was drained */ + buf_clear(buf); + socks_request_free(testdata->req); + socks = testdata->req = socks_request_new(); + } + } + done: + ; +} + +static void +test_socks_wrong_protocol(void *ptr) +{ + SOCKS_TEST_INIT(); + setup_capture_of_logs(LOG_DEBUG); + + /* HTTP request. */ + ADD_DATA(buf, "GET /index.html HTTP/1.0" ); + tt_int_op(fetch_from_buf_socks(buf, socks, 1, 0), OP_EQ, -1); + buf_clear(buf); + expect_log_msg_containing("Socks version 71 not recognized. " + "(This port is not an HTTP proxy;"); + mock_clean_saved_logs(); + socks_request_clear(socks); + + done: + teardown_capture_of_logs(); +} + +/* Check our client-side socks4 parsing (that is to say, our parsing of + * server responses). + */ +static void +test_socks_client_v4(void *arg) +{ + (void)arg; + buf_t *buf = buf_new(); + char *reason = NULL; + + /* Legit socks4 response, success */ + ADD_DATA(buf, "\x04\x5a\x20\x25\x01\x02\x03\x04"); + tt_int_op(1, OP_EQ, + fetch_from_buf_socks_client(buf, PROXY_SOCKS4_WANT_CONNECT_OK, + &reason)); + tt_ptr_op(reason, OP_EQ, NULL); + tt_int_op(buf_datalen(buf), OP_EQ, 0); + + /* Legit socks4 response, failure. */ + ADD_DATA(buf, "\x04\x5b\x20\x25\x01\x02\x03\x04"); + tt_int_op(-1, OP_EQ, + fetch_from_buf_socks_client(buf, PROXY_SOCKS4_WANT_CONNECT_OK, + &reason)); + tt_ptr_op(reason, OP_NE, NULL); + tt_str_op(reason, OP_EQ, "server rejected connection"); + + done: + buf_free(buf); + tor_free(reason); +} + +/* Check our client-side socks5 authentication-negotiation parsing (that is to + * say, our parsing of server responses). + */ +static void +test_socks_client_v5_auth(void *arg) +{ + (void)arg; + buf_t *buf = buf_new(); + char *reason = NULL; + + /* Legit socks5 responses, got a method we like. */ + ADD_DATA(buf, "\x05\x00"); + tt_int_op(1, OP_EQ, + fetch_from_buf_socks_client(buf, + PROXY_SOCKS5_WANT_AUTH_METHOD_NONE, + &reason)); + tt_ptr_op(reason, OP_EQ, NULL); + tt_int_op(buf_datalen(buf), OP_EQ, 0); + + /* Same, but we wanted something else. */ + ADD_DATA(buf, "\x05\x00"); + tt_int_op(1, OP_EQ, + fetch_from_buf_socks_client(buf, + PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929, + &reason)); + tt_ptr_op(reason, OP_EQ, NULL); + tt_int_op(buf_datalen(buf), OP_EQ, 0); + + /* Same, and they offered a password. */ + ADD_DATA(buf, "\x05\x02"); + tt_int_op(2, OP_EQ, + fetch_from_buf_socks_client(buf, + PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929, + &reason)); + tt_ptr_op(reason, OP_EQ, NULL); + tt_int_op(buf_datalen(buf), OP_EQ, 0); + + /* They rejected our method, or selected something we don't know. */ + ADD_DATA(buf, "\x05\xff"); + tt_int_op(-1, OP_EQ, + fetch_from_buf_socks_client(buf, + PROXY_SOCKS5_WANT_AUTH_METHOD_NONE, + &reason)); + tt_str_op(reason, OP_EQ, "server doesn't support any of our available " + "authentication methods"); + buf_clear(buf); + tor_free(reason); + ADD_DATA(buf, "\x05\xff"); + tt_int_op(-1, OP_EQ, + fetch_from_buf_socks_client(buf, + PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929, + &reason)); + tt_str_op(reason, OP_EQ, "server doesn't support any of our available " + "authentication methods"); + tor_free(reason); + buf_clear(buf); + + /* Now check for authentication responses: check success and failure. */ + ADD_DATA(buf, "\x01\x00"); + tt_int_op(1, OP_EQ, + fetch_from_buf_socks_client(buf, + PROXY_SOCKS5_WANT_AUTH_RFC1929_OK, + &reason)); + tt_ptr_op(reason, OP_EQ, NULL); + tt_int_op(buf_datalen(buf), OP_EQ, 0); + + ADD_DATA(buf, "\x01\xf0"); + tt_int_op(-1, OP_EQ, + fetch_from_buf_socks_client(buf, + PROXY_SOCKS5_WANT_AUTH_RFC1929_OK, + &reason)); + tt_ptr_op(reason, OP_NE, NULL); + tt_str_op(reason, OP_EQ, "authentication failed"); + + done: + buf_free(buf); + tor_free(reason); +} + +/* Check our client-side socks5 connect parsing (that is to say, our parsing + * of server responses). + */ +static void +test_socks_client_v5_connect(void *arg) +{ + (void)arg; + buf_t *buf = buf_new(); + char *reason = NULL; + + /* Legit socks5 responses, success, ipv4. */ + ADD_DATA(buf, "\x05\x00\x00\x01\x01\x02\x03\x04\x00\x05"); + tt_int_op(1, OP_EQ, + fetch_from_buf_socks_client(buf, + PROXY_SOCKS5_WANT_CONNECT_OK, + &reason)); + tt_ptr_op(reason, OP_EQ, NULL); + tt_int_op(buf_datalen(buf), OP_EQ, 0); + + /* Legit socks5 responses, success, ipv6. */ + ADD_DATA(buf, "\x05\x00\x00\x04" + "abcdefghijklmnop" + "\x00\x05"); + tt_int_op(1, OP_EQ, + fetch_from_buf_socks_client(buf, + PROXY_SOCKS5_WANT_CONNECT_OK, + &reason)); + tt_ptr_op(reason, OP_EQ, NULL); + tt_int_op(buf_datalen(buf), OP_EQ, 0); + + /* Legit socks5 responses, success, hostname. */ + ADD_DATA(buf, "\x05\x00\x00\x03\x12" + "gopher.example.com" + "\x00\x05"); + tt_int_op(1, OP_EQ, + fetch_from_buf_socks_client(buf, + PROXY_SOCKS5_WANT_CONNECT_OK, + &reason)); + tt_ptr_op(reason, OP_EQ, NULL); + tt_int_op(buf_datalen(buf), OP_EQ, 0); + + /* Legit socks5 responses, failure, hostname. */ + ADD_DATA(buf, "\x05\x03\x00\x03\x12" + "gopher.example.com" + "\x00\x05"); + tt_int_op(-1, OP_EQ, + fetch_from_buf_socks_client(buf, + PROXY_SOCKS5_WANT_CONNECT_OK, + &reason)); + tt_ptr_op(reason, OP_NE, NULL); + tt_str_op(reason, OP_EQ, "Network unreachable"); + tor_free(reason); + buf_clear(buf); + + /* Bogus socks5 responses: what is address type 0x17? */ + ADD_DATA(buf, "\x05\x03\x00\x17\x12 blah blah"); + tt_int_op(-1, OP_EQ, + fetch_from_buf_socks_client(buf, + PROXY_SOCKS5_WANT_CONNECT_OK, + &reason)); + tt_ptr_op(reason, OP_NE, NULL); + tt_str_op(reason, OP_EQ, "invalid response to connect request"); + buf_clear(buf); + + done: + buf_free(buf); + tor_free(reason); +} + +static void +test_socks_client_truncated(void *arg) +{ + (void)arg; + buf_t *buf = buf_new(); + char *reason = NULL; + +#define S(str) str, (sizeof(str)-1) + const struct { + int state; + const char *body; + size_t len; + } replies[] = { + { PROXY_SOCKS4_WANT_CONNECT_OK, S("\x04\x5a\x20\x25\x01\x02\x03\x04") }, + { PROXY_SOCKS4_WANT_CONNECT_OK, S("\x04\x5b\x20\x25\x01\x02\x03\x04") }, + { PROXY_SOCKS5_WANT_AUTH_METHOD_NONE, S("\x05\x00") }, + { PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929, S("\x05\x00") }, + { PROXY_SOCKS5_WANT_AUTH_RFC1929_OK, S("\x01\x00") }, + { PROXY_SOCKS5_WANT_CONNECT_OK, + S("\x05\x00\x00\x01\x01\x02\x03\x04\x00\x05") }, + { PROXY_SOCKS5_WANT_CONNECT_OK, + S("\x05\x00\x00\x04" "abcdefghijklmnop" "\x00\x05") }, + { PROXY_SOCKS5_WANT_CONNECT_OK, + S("\x05\x00\x00\x03\x12" "gopher.example.com" "\x00\x05") }, + { PROXY_SOCKS5_WANT_CONNECT_OK, + S("\x05\x03\x00\x03\x12" "gopher.example.com""\x00\x05") }, + { PROXY_SOCKS5_WANT_CONNECT_OK, + S("\x05\x03\x00\x17") }, + }; + unsigned i, j; + for (i = 0; i < ARRAY_LENGTH(replies); ++i) { + for (j = 0; j < replies[i].len; ++j) { + TT_BLATHER(("Checking command %u, length %u", i, j)); + buf_add(buf, replies[i].body, j); + /* This should return 0 meaning "not done yet" */ + tt_int_op(0, OP_EQ, + fetch_from_buf_socks_client(buf, replies[i].state, &reason)); + tt_uint_op(j, OP_EQ, buf_datalen(buf)); /* Nothing was drained */ + buf_clear(buf); + tt_ptr_op(reason, OP_EQ, NULL); + } + } + + done: + tor_free(reason); + buf_free(buf); +} + #define SOCKSENT(name) \ { #name, test_socks_##name, TT_FORK, &socks_setup, NULL } struct testcase_t socks_tests[] = { SOCKSENT(4_unsupported_commands), SOCKSENT(4_supported_commands), + SOCKSENT(4_bad_arguments), SOCKSENT(5_unsupported_commands), SOCKSENT(5_supported_commands), SOCKSENT(5_no_authenticate), + SOCKSENT(5_auth_unsupported_type), + SOCKSENT(5_auth_unsupported_version), SOCKSENT(5_auth_before_negotiation), SOCKSENT(5_authenticate), SOCKSENT(5_authenticate_with_data), SOCKSENT(5_malformed_commands), + SOCKSENT(5_bad_arguments), + + SOCKSENT(truncated), + + SOCKSENT(wrong_protocol), + + { "client/v4", test_socks_client_v4, TT_FORK, NULL, NULL }, + { "client/v5_auth", test_socks_client_v5_auth, TT_FORK, NULL, NULL }, + { "client/v5_connect", test_socks_client_v5_connect, TT_FORK, NULL, NULL }, + { "client/truncated", test_socks_client_truncated, TT_FORK, NULL, NULL }, END_OF_TESTCASES }; diff --git a/src/test/test_status.c b/src/test/test_status.c index a3b1a2af87..f86f8e3b9e 100644 --- a/src/test/test_status.c +++ b/src/test/test_status.c @@ -889,8 +889,8 @@ NS(logv)(int severity, log_domain_mask_t domain, const char *funcname, tt_str_op(format, OP_EQ, "Average packaged cell fullness: %2.3f%%. " "TLS write overhead: %.f%%"); - tt_double_op(fabs(va_arg(ap, double) - 50.0), <=, DBL_EPSILON); - tt_double_op(fabs(va_arg(ap, double) - 0.0), <=, DBL_EPSILON); + tt_double_op(fabs(va_arg(ap, double) - 50.0), OP_LE, DBL_EPSILON); + tt_double_op(fabs(va_arg(ap, double) - 0.0), OP_LE, DBL_EPSILON); break; default: tt_abort_msg("unexpected call to logv()"); // TODO: prettyprint args @@ -1039,7 +1039,7 @@ NS(logv)(int severity, log_domain_mask_t domain, "Average packaged cell fullness: %2.3f%%. " "TLS write overhead: %.f%%"); tt_int_op(fabs(va_arg(ap, double) - 100.0) <= DBL_EPSILON, OP_EQ, 1); - tt_double_op(fabs(va_arg(ap, double) - 100.0), <=, DBL_EPSILON); + tt_double_op(fabs(va_arg(ap, double) - 100.0), OP_LE, DBL_EPSILON); break; default: tt_abort_msg("unexpected call to logv()"); // TODO: prettyprint args diff --git a/src/test/test_storagedir.c b/src/test/test_storagedir.c index 19e5de4ea3..a27074c21f 100644 --- a/src/test/test_storagedir.c +++ b/src/test/test_storagedir.c @@ -338,7 +338,7 @@ test_storagedir_read_labeled(void *arg) tt_assert(labels->next->next); tt_str_op(labels->next->next->key, OP_EQ, "Yadda"); tt_str_op(labels->next->next->value, OP_EQ, "yadda."); - tt_assert(labels->next->next->next == NULL); + tt_ptr_op(labels->next->next->next, OP_EQ, NULL); /* Try reading this time. */ sz = 0; diff --git a/src/test/test_switch_id.c b/src/test/test_switch_id.c index 53de793fe8..fe36d8c6e6 100644 --- a/src/test/test_switch_id.c +++ b/src/test/test_switch_id.c @@ -71,7 +71,7 @@ check_can_bind_low_ports(void) return -1; } -#endif +#endif /* !defined(_WIN32) */ int main(int argc, char **argv) @@ -83,7 +83,7 @@ main(int argc, char **argv) fprintf(stderr, "This test is not supported on your OS.\n"); return 77; -#else +#else /* !(defined(_WIN32)) */ const char *username; const char *testname; if (argc != 3) { @@ -174,7 +174,7 @@ main(int argc, char **argv) } cap_free(caps); } -#endif +#endif /* defined(HAVE_LINUX_CAPABILITIES) */ break; default: fprintf(stderr, "Unsupported test '%s'\n", testname); @@ -187,6 +187,6 @@ main(int argc, char **argv) } return (okay ? 0 : 1); -#endif +#endif /* defined(_WIN32) */ } diff --git a/src/test/test_threads.c b/src/test/test_threads.c index 18a9407ff7..ed6d8f04aa 100644 --- a/src/test/test_threads.c +++ b/src/test/test_threads.c @@ -139,8 +139,8 @@ test_threads_basic(void *arg) !strcmp(strmap_get(thread_test_strmap_, "thread 2"), strmap_get(thread_test_strmap_, "last to run"))); - tt_int_op(thread_fns_failed, ==, 0); - tt_int_op(thread_fn_tid1, !=, thread_fn_tid2); + tt_int_op(thread_fns_failed, OP_EQ, 0); + tt_int_op(thread_fn_tid1, OP_NE, thread_fn_tid2); done: tor_free(s1); @@ -275,14 +275,14 @@ test_threads_conditionvar(void *arg) SPIN(); tor_mutex_release(ti->mutex); - tt_int_op(ti->value, ==, 1337); + tt_int_op(ti->value, OP_EQ, 1337); if (!timeout) { - tt_int_op(ti->n_shutdown, ==, 4); + tt_int_op(ti->n_shutdown, OP_EQ, 4); } else { tor_sleep_msec(200); tor_mutex_acquire(ti->mutex); - tt_int_op(ti->n_shutdown, ==, 2); - tt_int_op(ti->n_timeouts, ==, 2); + tt_int_op(ti->n_shutdown, OP_EQ, 2); + tt_int_op(ti->n_timeouts, OP_EQ, 2); tor_mutex_release(ti->mutex); } diff --git a/src/test/test_tortls.c b/src/test/test_tortls.c index 7aa3051464..29f7cc9c37 100644 --- a/src/test/test_tortls.c +++ b/src/test/test_tortls.c @@ -63,7 +63,7 @@ fake_num_ciphers(void) { return 0; } -#endif +#endif /* !defined(OPENSSL_OPAQUE) */ static void test_tortls_errno_to_tls_error(void *data) @@ -136,7 +136,7 @@ test_tortls_tor_tls_new(void *data) SSL_CTX_free(client_tls_context->ctx); client_tls_context->ctx = NULL; tls = tor_tls_new(-1, 0); - tt_assert(!tls); + tt_ptr_op(tls, OP_EQ, NULL); #ifndef OPENSSL_OPAQUE method = give_me_a_test_method(); @@ -144,8 +144,8 @@ test_tortls_tor_tls_new(void *data) method->num_ciphers = fake_num_ciphers; client_tls_context->ctx = ctx; tls = tor_tls_new(-1, 0); - tt_assert(!tls); -#endif + tt_ptr_op(tls, OP_EQ, NULL); +#endif /* !defined(OPENSSL_OPAQUE) */ done: UNMOCK(tor_tls_cert_matches_key); @@ -376,7 +376,7 @@ test_tortls_log_one_error(void *ignored) tor_tls_log_one_error(tls, ERR_PACK(1, 2, SSL_R_RECORD_TOO_LARGE), LOG_WARN, 0, NULL); expect_log_severity(LOG_INFO); -#endif +#endif /* !defined(OPENSSL_1_1_API) */ mock_clean_saved_logs(); tor_tls_log_one_error(tls, ERR_PACK(1, 2, SSL_R_UNKNOWN_PROTOCOL), @@ -490,7 +490,7 @@ test_tortls_get_error(void *ignored) tor_free(tls); SSL_CTX_free(ctx); } -#endif +#endif /* !defined(OPENSSL_OPAQUE) */ static void test_tortls_always_accept_verify_cb(void *ignored) @@ -520,7 +520,7 @@ test_tortls_x509_cert_free(void *ignored) cert->encoded = tor_malloc_zero(1); tor_x509_cert_free(cert); } -#endif +#endif /* !defined(OPENSSL_OPAQUE) */ static void test_tortls_x509_cert_get_id_digests(void *ignored) @@ -662,7 +662,7 @@ test_tortls_cert_get_key(void *ignored) tor_free(cert); crypto_pk_free(res); } -#endif +#endif /* !defined(OPENSSL_OPAQUE) */ static void test_tortls_get_my_client_auth_key(void *ignored) @@ -744,7 +744,7 @@ get_cipher_by_name(const char *name) return NULL; } -#endif +#endif /* !defined(HAVE_SSL_GET_CLIENT_CIPHERS) */ #ifndef OPENSSL_OPAQUE static void @@ -879,7 +879,7 @@ test_tortls_classify_client_ciphers(void *ignored) tor_free(tls); SSL_CTX_free(ctx); } -#endif +#endif /* !defined(OPENSSL_OPAQUE) */ static void test_tortls_client_is_using_v2_ciphers(void *ignored) @@ -921,7 +921,7 @@ test_tortls_client_is_using_v2_ciphers(void *ignored) done: SSL_free(ssl); SSL_CTX_free(ctx); -#endif +#endif /* defined(HAVE_SSL_GET_CLIENT_CIPHERS) */ } #ifndef OPENSSL_OPAQUE @@ -937,7 +937,7 @@ fixed_try_to_extract_certs_from_tls(int severity, tor_tls_t *tls, *cert_out = fixed_try_to_extract_certs_from_tls_cert_out_result; *id_cert_out = fixed_try_to_extract_certs_from_tls_id_cert_out_result; } -#endif +#endif /* !defined(OPENSSL_OPAQUE) */ #ifndef OPENSSL_OPAQUE static const char* notCompletelyValidCertString = @@ -956,7 +956,7 @@ static const char* notCompletelyValidCertString = "jC9UeuErhaA/zzWi8ewMTFZW/WshOrm3fNvcMrMLKtH534JKvcdMg6qIdjTFINIr\n" "evnAhf0cwULaebn+lMs8Pdl7y37+sfluVok=\n" "-----END CERTIFICATE-----\n"; -#endif +#endif /* !defined(OPENSSL_OPAQUE) */ static const char* validCertString = "-----BEGIN CERTIFICATE-----\n" "MIIDpTCCAY0CAg3+MA0GCSqGSIb3DQEBBQUAMF4xCzAJBgNVBAYTAlVTMREwDwYD\n" @@ -1079,7 +1079,7 @@ test_tortls_verify(void *ignored) tor_free(tls); tor_free(k); } -#endif +#endif /* !defined(OPENSSL_OPAQUE) */ #ifndef OPENSSL_OPAQUE static void @@ -1118,7 +1118,7 @@ test_tortls_check_lifetime(void *ignored) tor_free(tls); X509_free(validCert); } -#endif +#endif /* !defined(OPENSSL_OPAQUE) */ #ifndef OPENSSL_OPAQUE static int fixed_ssl_pending_result = 0; @@ -1153,7 +1153,7 @@ test_tortls_get_pending_bytes(void *ignored) tor_free(tls->ssl); tor_free(tls); } -#endif +#endif /* !defined(OPENSSL_OPAQUE) */ static void test_tortls_get_forced_write_size(void *ignored) @@ -1276,13 +1276,13 @@ test_tortls_SSL_SESSION_get_master_key(void *ignored) tt_int_op(out[0], OP_EQ, 43); done: -#endif +#endif /* !defined(HAVE_SSL_SESSION_GET_MASTER_KEY) */ tor_free(tls->ssl->session); tor_free(tls->ssl); tor_free(tls); tor_free(out); } -#endif +#endif /* !defined(OPENSSL_OPAQUE) */ #ifndef OPENSSL_OPAQUE static void @@ -1290,7 +1290,7 @@ test_tortls_get_tlssecrets(void *ignored) { (void)ignored; int ret; - uint8_t *secret_out = tor_malloc_zero(DIGEST256_LEN);; + uint8_t *secret_out = tor_malloc_zero(DIGEST256_LEN); tor_tls_t *tls; tls = tor_malloc_zero(sizeof(tor_tls_t)); tls->ssl = tor_malloc_zero(sizeof(SSL)); @@ -1308,7 +1308,7 @@ test_tortls_get_tlssecrets(void *ignored) tor_free(tls->ssl); tor_free(tls); } -#endif +#endif /* !defined(OPENSSL_OPAQUE) */ #ifndef OPENSSL_OPAQUE static void @@ -1350,7 +1350,7 @@ test_tortls_get_buffer_sizes(void *ignored) tt_int_op(rbuf_c, OP_EQ, 1); tt_int_op(wbuf_c, OP_EQ, 2); -#endif +#endif /* OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) */ done: tor_free(tls->ssl->s3->rbuf.buf); @@ -1359,7 +1359,7 @@ test_tortls_get_buffer_sizes(void *ignored) tor_free(tls->ssl); tor_free(tls); } -#endif +#endif /* !defined(OPENSSL_OPAQUE) */ static void test_tortls_evaluate_ecgroup_for_tls(void *ignored) @@ -1378,6 +1378,7 @@ test_tortls_evaluate_ecgroup_for_tls(void *ignored) ret = evaluate_ecgroup_for_tls("P224"); // tt_int_op(ret, OP_EQ, 1); This varies between machines + tt_assert(ret == 0 || ret == 1); done: (void)0; @@ -1450,7 +1451,7 @@ test_tortls_try_to_extract_certs_from_tls(void *ignored) X509_free(c1); X509_free(c2); } -#endif +#endif /* !defined(OPENSSL_OPAQUE) */ #ifndef OPENSSL_OPAQUE static void @@ -1482,7 +1483,7 @@ test_tortls_get_peer_cert(void *ignored) tor_free(tls); X509_free(cert); } -#endif +#endif /* !defined(OPENSSL_OPAQUE) */ #ifndef OPENSSL_OPAQUE static void @@ -1512,7 +1513,7 @@ test_tortls_peer_has_cert(void *ignored) tor_free(tls); X509_free(cert); } -#endif +#endif /* !defined(OPENSSL_OPAQUE) */ static void test_tortls_is_server(void *ignored) @@ -1572,7 +1573,7 @@ test_tortls_session_secret_cb(void *ignored) SSL_CTX_free(ctx); tor_free(tls); } -#endif +#endif /* !defined(OPENSSL_OPAQUE) */ #ifndef OPENSSL_OPAQUE /* TODO: It seems block_renegotiation and unblock_renegotiation and @@ -1623,7 +1624,7 @@ test_tortls_unblock_renegotiation(void *ignored) tor_free(tls->ssl); tor_free(tls); } -#endif +#endif /* !defined(OPENSSL_OPAQUE) */ #ifndef OPENSSL_OPAQUE static void @@ -1642,7 +1643,7 @@ test_tortls_assert_renegotiation_unblocked(void *ignored) tor_free(tls->ssl); tor_free(tls); } -#endif +#endif /* !defined(OPENSSL_OPAQUE) */ static void test_tortls_set_logged_address(void *ignored) @@ -1697,7 +1698,7 @@ test_tortls_set_renegotiate_callback(void *ignored) tor_free(tls->ssl); tor_free(tls); } -#endif +#endif /* !defined(OPENSSL_OPAQUE) */ #ifndef OPENSSL_OPAQUE static SSL_CIPHER *fixed_cipher1 = NULL; @@ -1715,7 +1716,7 @@ fake_get_cipher(unsigned ncipher) return NULL; } } -#endif +#endif /* !defined(OPENSSL_OPAQUE) */ #ifndef OPENSSL_OPAQUE static void @@ -1785,7 +1786,7 @@ test_tortls_find_cipher_by_id(void *ignored) SSL_CTX_free(ctx); tor_free(fixed_cipher1); } -#endif +#endif /* !defined(OPENSSL_OPAQUE) */ #ifndef OPENSSL_OPAQUE static void @@ -1813,7 +1814,7 @@ test_tortls_debug_state_callback(void *ignored) tor_free(buf); tor_free(ssl); } -#endif +#endif /* !defined(OPENSSL_OPAQUE) */ #ifndef OPENSSL_OPAQUE static void @@ -1877,7 +1878,7 @@ test_tortls_server_info_callback(void *ignored) SSL_CTX_free(ctx); tor_free(tls); } -#endif +#endif /* !defined(OPENSSL_OPAQUE) */ #ifndef OPENSSL_OPAQUE static int fixed_ssl_read_result_index; @@ -1918,7 +1919,7 @@ setting_version_and_state_ssl_shutdown(SSL *s) s->version = SSL2_VERSION; return fixed_ssl_shutdown_result; } -#endif +#endif /* !defined(LIBRESSL_VERSION_NUMBER) */ static int dummy_handshake_func(SSL *s) @@ -2014,7 +2015,7 @@ test_tortls_shutdown(void *ignored) method->ssl_shutdown = setting_version_and_state_ssl_shutdown; ret = tor_tls_shutdown(tls); tt_int_op(ret, OP_EQ, TOR_TLS_ERROR_MISC); -#endif +#endif /* !defined(LIBRESSL_VERSION_NUMBER) */ done: teardown_capture_of_logs(); @@ -2085,7 +2086,7 @@ test_tortls_read(void *ignored) ret = tor_tls_read(tls, buf, 10); tt_int_op(ret, OP_EQ, TOR_TLS_CLOSE); tt_int_op(tls->state, OP_EQ, TOR_TLS_ST_CLOSED); -#endif +#endif /* !defined(LIBRESSL_VERSION_NUMBER) */ // TODO: fill up done: @@ -2160,7 +2161,7 @@ test_tortls_write(void *ignored) tor_free(tls); tor_free(method); } -#endif +#endif /* !defined(OPENSSL_OPAQUE) */ #ifndef OPENSSL_OPAQUE static int fixed_ssl_accept_result; @@ -2240,7 +2241,7 @@ test_tortls_handshake(void *ignored) "(null):SSLv3 write client hello B)\n"); expect_log_msg("TLS error while handshaking: (null) (in system library:" "connect:SSLv3 write client hello B)\n"); -#endif +#endif /* 0 */ expect_log_severity(LOG_INFO); tls->isServer = 0; @@ -2258,7 +2259,7 @@ test_tortls_handshake(void *ignored) "(null) (in bignum routines:(null):SSLv3 write client hello B)\n"); expect_log_msg("TLS error while handshaking: " "(null) (in system library:connect:SSLv3 write client hello B)\n"); -#endif +#endif /* 0 */ expect_log_severity(LOG_WARN); done: @@ -2268,7 +2269,7 @@ test_tortls_handshake(void *ignored) tor_free(tls); tor_free(method); } -#endif +#endif /* !defined(OPENSSL_OPAQUE) */ #ifndef OPENSSL_OPAQUE static void @@ -2343,7 +2344,7 @@ test_tortls_finish_handshake(void *ignored) tor_free(method); teardown_capture_of_logs(); } -#endif +#endif /* !defined(OPENSSL_OPAQUE) */ static int fixed_crypto_pk_new_result_index; static crypto_pk_t *fixed_crypto_pk_new_result[5]; @@ -2568,7 +2569,7 @@ test_tortls_context_new(void *ignored) UNMOCK(crypto_pk_generate_key_with_bits); UNMOCK(crypto_pk_new); } -#endif +#endif /* !defined(OPENSSL_OPAQUE) */ static int fixed_crypto_pk_get_evp_pkey_result_index = 0; static EVP_PKEY *fixed_crypto_pk_get_evp_pkey_result[5]; @@ -2637,7 +2638,7 @@ test_tortls_cert_new(void *ignored) X509_get_pubkey(cert)->type = EVP_PKEY_DSA; ret = tor_x509_cert_new(cert); tt_assert(ret); -#endif +#endif /* 0 */ #ifndef OPENSSL_OPAQUE cert = read_cert_from(validCertString); @@ -2645,7 +2646,7 @@ test_tortls_cert_new(void *ignored) cert->cert_info = NULL; ret = tor_x509_cert_new(cert); tt_assert(ret); -#endif +#endif /* !defined(OPENSSL_OPAQUE) */ done: tor_x509_cert_free(ret); @@ -2692,7 +2693,7 @@ test_tortls_cert_is_valid(void *ignored) cert->cert->cert_info->key = NULL; ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, time(NULL), 1); tt_int_op(ret, OP_EQ, 0); -#endif +#endif /* !defined(OPENSSL_OPAQUE) */ #if 0 tor_x509_cert_free(cert); @@ -2731,7 +2732,7 @@ test_tortls_cert_is_valid(void *ignored) X509_get_pubkey(cert->cert)->ameth = NULL; ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, time(NULL), 0); tt_int_op(ret, OP_EQ, 0); -#endif +#endif /* 0 */ done: tor_x509_cert_free(cert); @@ -2764,7 +2765,7 @@ test_tortls_context_init_one(void *ignored) { #name, NULL, TT_SKIP, NULL, NULL } #else #define INTRUSIVE_TEST_CASE(name, flags) LOCAL_TEST_CASE(name, flags) -#endif +#endif /* defined(OPENSSL_OPAQUE) */ struct testcase_t tortls_tests[] = { LOCAL_TEST_CASE(errno_to_tls_error, 0), diff --git a/src/test/test_util.c b/src/test/test_util.c index fa6ce1dc85..0519a4758f 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -70,7 +70,7 @@ test_util_read_until_eof_impl(const char *fname, size_t file_len, fd = open(fifo_name, O_RDONLY|O_BINARY); tt_int_op(fd, OP_GE, 0); str = read_file_to_str_until_eof(fd, read_limit, &sz); - tt_assert(str != NULL); + tt_ptr_op(str, OP_NE, NULL); if (read_limit < file_len) tt_int_op(sz, OP_EQ, read_limit); @@ -367,7 +367,7 @@ test_util_time(void *arg) * calculations internally, then catches the overflow. */ #define TV_SEC_MAX TIME_MAX #define TV_SEC_MIN TIME_MIN -#endif +#endif /* defined(_WIN32) */ /* Assume tv_usec is an unsigned integer until proven otherwise */ #define TV_USEC_MAX UINT_MAX @@ -635,13 +635,16 @@ test_util_time(void *arg) * time_t */ a_time.tm_year = 2039-1900; #if SIZEOF_TIME_T == 4 + setup_full_capture_of_logs(LOG_WARN); tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time)); + expect_single_log_msg_containing("Result does not fit in tor_timegm"); + teardown_capture_of_logs(); #elif SIZEOF_TIME_T == 8 t_res = 2178252895UL; tt_int_op(t_res, OP_EQ, tor_timegm(&a_time)); tor_gmtime_r(&t_res, &b_time); TM_EQUAL(a_time, b_time); -#endif +#endif /* SIZEOF_TIME_T == 4 || ... */ /* Test tor_timegm out of range */ @@ -651,8 +654,7 @@ test_util_time(void *arg) setup_full_capture_of_logs(LOG_WARN); \ } while (0) #define CHECK_TIMEGM_WARNING(msg) do { \ - expect_log_msg_containing(msg); \ - tt_int_op(1, OP_EQ, smartlist_len(mock_saved_logs())); \ + expect_single_log_msg_containing(msg); \ teardown_capture_of_logs(); \ } while (0) @@ -689,7 +691,7 @@ test_util_time(void *arg) CAPTURE(); tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time)); CHECK_TIMEGM_ARG_OUT_OF_RANGE(); -#endif +#endif /* SIZEOF_INT == 4 || SIZEOF_INT == 8 */ #if SIZEOF_INT == 8 a_time.tm_year = -1*(1 << 48); @@ -711,7 +713,7 @@ test_util_time(void *arg) CAPTURE(); tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time)); CHECK_TIMEGM_ARG_OUT_OF_RANGE(); -#endif +#endif /* SIZEOF_INT == 8 */ /* Wrong year >= INT32_MAX - 1900 */ #if SIZEOF_INT == 4 || SIZEOF_INT == 8 @@ -724,7 +726,7 @@ test_util_time(void *arg) CAPTURE(); tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time)); CHECK_TIMEGM_ARG_OUT_OF_RANGE(); -#endif +#endif /* SIZEOF_INT == 4 || SIZEOF_INT == 8 */ #if SIZEOF_INT == 8 /* one of the largest tm_year values my 64 bit system supports */ @@ -752,7 +754,7 @@ test_util_time(void *arg) CAPTURE(); tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time)); CHECK_TIMEGM_ARG_OUT_OF_RANGE(); -#endif +#endif /* SIZEOF_INT == 8 */ /* month */ a_time.tm_year = 2007-1900; /* restore valid year */ @@ -888,7 +890,7 @@ test_util_time(void *arg) teardown_capture_of_logs(); } } -#endif +#endif /* SIZEOF_TIME_T == 8 */ /* time_t >= INT_MAX yields a year clamped to 2037 or 9999, * depending on whether the implementation of the system gmtime(_r) @@ -904,7 +906,7 @@ test_util_time(void *arg) tt_assert(b_time.tm_year == (2037-1900) || b_time.tm_year == (2038-1900)); } -#endif +#endif /* SIZEOF_TIME_T == 4 || SIZEOF_TIME_T == 8 */ #if SIZEOF_TIME_T == 8 { @@ -929,7 +931,7 @@ test_util_time(void *arg) tt_assert(b_time.tm_year == (2037-1900) || b_time.tm_year == (9999-1900)); } -#endif +#endif /* SIZEOF_TIME_T == 8 */ /* Test {format,parse}_rfc1123_time */ @@ -965,7 +967,9 @@ test_util_time(void *arg) strlcpy(timestr, "Wed, 17 Feb 2038 06:13:20 GMT", sizeof(timestr)); t_res = 0; + CAPTURE(); i = parse_rfc1123_time(timestr, &t_res); + CHECK_TIMEGM_WARNING("does not fit in tor_timegm"); tt_int_op(-1,OP_EQ, i); #elif SIZEOF_TIME_T == 8 tt_str_op("Wed, 17 Feb 2038 06:13:20 GMT",OP_EQ, timestr); @@ -974,7 +978,7 @@ test_util_time(void *arg) i = parse_rfc1123_time(timestr, &t_res); tt_int_op(0,OP_EQ, i); tt_int_op(t_res,OP_EQ, (time_t)2150000000UL); -#endif +#endif /* SIZEOF_TIME_T == 4 || ... */ /* The timezone doesn't matter */ t_res = 0; @@ -1040,13 +1044,16 @@ test_util_time(void *arg) /* This value is out of range with 32 bit time_t, but in range for 64 bit * time_t */ t_res = 0; - i = parse_iso_time("2038-02-17 06:13:20", &t_res); #if SIZEOF_TIME_T == 4 + CAPTURE(); + i = parse_iso_time("2038-02-17 06:13:20", &t_res); tt_int_op(-1,OP_EQ, i); + CHECK_TIMEGM_WARNING("does not fit in tor_timegm"); #elif SIZEOF_TIME_T == 8 + i = parse_iso_time("2038-02-17 06:13:20", &t_res); tt_int_op(0,OP_EQ, i); tt_int_op(t_res,OP_EQ, (time_t)2150000000UL); -#endif +#endif /* SIZEOF_TIME_T == 4 || ... */ tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-zz 99-99x99", &t_res)); tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-32 00:00:00", &t_res)); @@ -1129,7 +1136,7 @@ test_util_time(void *arg) /* This SHOULD work on windows too; see bug #18665 */ tt_str_op("2038-02-17 06:13:20",OP_EQ, timestr); #endif -#endif +#endif /* SIZEOF_TIME_T == 4 || ... */ #undef CAPTURE #undef CHECK_TIMEGM_ARG_OUT_OF_RANGE @@ -1218,13 +1225,16 @@ test_util_parse_http_time(void *arg) #if SIZEOF_TIME_T == 4 /* parse_http_time should indicate failure on overflow, but it doesn't yet. * Hopefully #18480 will improve the failure semantics in this case. */ + setup_full_capture_of_logs(LOG_WARN); tt_int_op(0,OP_EQ,parse_http_time("Wed, 17 Feb 2038 06:13:20 GMT", &a_time)); tt_int_op((time_t)-1,OP_EQ, tor_timegm(&a_time)); + expect_single_log_msg_containing("does not fit in tor_timegm"); + teardown_capture_of_logs(); #elif SIZEOF_TIME_T == 8 tt_int_op(0,OP_EQ,parse_http_time("Wed, 17 Feb 2038 06:13:20 GMT", &a_time)); tt_int_op((time_t)2150000000UL,OP_EQ, tor_timegm(&a_time)); T("2038-02-17 06:13:20"); -#endif +#endif /* SIZEOF_TIME_T == 4 || ... */ tt_int_op(-1,OP_EQ, parse_http_time("2004-08-zz 99-99x99 GMT", &a_time)); tt_int_op(-1,OP_EQ, parse_http_time("2011-03-32 00:00:00 GMT", &a_time)); @@ -1237,7 +1247,7 @@ test_util_parse_http_time(void *arg) #undef T done: - ; + teardown_capture_of_logs(); } static void @@ -1471,7 +1481,7 @@ test_util_config_line_comment_character(void *arg) tor_free(k); tor_free(v); test_streq(str, ""); -#endif +#endif /* 0 */ done: tor_free(k); @@ -1602,7 +1612,7 @@ test_util_config_line_escaped_content(void *arg) str = parse_config_line_from_str_verbose(str, &k, &v, NULL); tt_ptr_op(str, OP_EQ, NULL); tor_free(k); tor_free(v); -#endif +#endif /* 0 */ str = buf6; @@ -1674,14 +1684,14 @@ test_util_config_line_crlf(void *arg) tt_assert(str); tt_str_op(k,OP_EQ,"Hello"); tt_str_op(v,OP_EQ,"world"); - tt_assert(!err); + tt_ptr_op(err, OP_EQ, NULL); tor_free(k); tor_free(v); str = parse_config_line_from_str_verbose(str, &k, &v, &err); tt_assert(str); tt_str_op(k,OP_EQ,"Hello"); tt_str_op(v,OP_EQ,"nice big world"); - tt_assert(!err); + tt_ptr_op(err, OP_EQ, NULL); tor_free(k); tor_free(v); tt_str_op(str,OP_EQ, ""); @@ -1786,7 +1796,7 @@ test_util_expand_filename(void *arg) done: tor_free(str); } -#endif +#endif /* !defined(_WIN32) */ /** Test tor_escape_str_for_pt_args(). */ static void @@ -1941,7 +1951,7 @@ test_util_strmisc(void *arg) tt_assert(!tor_mem_is_zero(buf, 10)); /* Test 'escaped' */ - tt_assert(NULL == escaped(NULL)); + tt_ptr_op(escaped(NULL), OP_EQ, NULL); tt_str_op("\"\"",OP_EQ, escaped("")); tt_str_op("\"abcd\"",OP_EQ, escaped("abcd")); tt_str_op("\"\\\\ \\n\\r\\t\\\"\\'\"",OP_EQ, escaped("\\ \n\r\t\"'")); @@ -1999,23 +2009,23 @@ test_util_strmisc(void *arg) /* Test memmem and memstr */ { const char *haystack = "abcde"; - tt_assert(!tor_memmem(haystack, 5, "ef", 2)); + tt_ptr_op(tor_memmem(haystack, 5, "ef", 2), OP_EQ, NULL); tt_ptr_op(tor_memmem(haystack, 5, "cd", 2),OP_EQ, haystack + 2); tt_ptr_op(tor_memmem(haystack, 5, "cde", 3),OP_EQ, haystack + 2); - tt_assert(!tor_memmem(haystack, 4, "cde", 3)); + tt_ptr_op(tor_memmem(haystack, 4, "cde", 3), OP_EQ, NULL); haystack = "ababcad"; tt_ptr_op(tor_memmem(haystack, 7, "abc", 3),OP_EQ, haystack + 2); tt_ptr_op(tor_memmem(haystack, 7, "ad", 2),OP_EQ, haystack + 5); tt_ptr_op(tor_memmem(haystack, 7, "cad", 3),OP_EQ, haystack + 4); - tt_assert(!tor_memmem(haystack, 7, "dadad", 5)); - tt_assert(!tor_memmem(haystack, 7, "abcdefghij", 10)); + tt_ptr_op(tor_memmem(haystack, 7, "dadad", 5), OP_EQ, NULL); + tt_ptr_op(tor_memmem(haystack, 7, "abcdefghij", 10), OP_EQ, NULL); /* memstr */ tt_ptr_op(tor_memstr(haystack, 7, "abc"),OP_EQ, haystack + 2); tt_ptr_op(tor_memstr(haystack, 7, "cad"),OP_EQ, haystack + 4); - tt_assert(!tor_memstr(haystack, 6, "cad")); - tt_assert(!tor_memstr(haystack, 7, "cadd")); - tt_assert(!tor_memstr(haystack, 7, "fe")); - tt_assert(!tor_memstr(haystack, 7, "ababcade")); + tt_ptr_op(tor_memstr(haystack, 6, "cad"), OP_EQ, NULL); + tt_ptr_op(tor_memstr(haystack, 7, "cadd"), OP_EQ, NULL); + tt_ptr_op(tor_memstr(haystack, 7, "fe"), OP_EQ, NULL); + tt_ptr_op(tor_memstr(haystack, 7, "ababcade"), OP_EQ, NULL); } /* Test hex_str */ @@ -2125,10 +2135,13 @@ test_util_parse_integer(void *arg) /* Base different than 10 */ tt_int_op(2L,OP_EQ, tor_parse_long("10",2,0,100,NULL,NULL)); tt_int_op(0L,OP_EQ, tor_parse_long("2",2,0,100,NULL,NULL)); - tt_int_op(0L,OP_EQ, tor_parse_long("10",-2,0,100,NULL,NULL)); tt_int_op(68284L,OP_EQ, tor_parse_long("10abc",16,0,70000,NULL,NULL)); tt_int_op(68284L,OP_EQ, tor_parse_long("10ABC",16,0,70000,NULL,NULL)); + tor_capture_bugs_(2); + tt_int_op(0L,OP_EQ, tor_parse_long("10",-2,0,100,NULL,NULL)); tt_int_op(0,OP_EQ, tor_parse_long("10ABC",-1,0,70000,&i,NULL)); + tt_int_op(2, OP_EQ, smartlist_len(tor_get_captured_bug_log_())); + tor_end_capture_bugs_(); tt_int_op(i,OP_EQ, 0); /* Test parse_ulong */ @@ -2141,7 +2154,10 @@ test_util_parse_integer(void *arg) tt_int_op(0UL,OP_EQ, tor_parse_ulong("8",8,0,100,NULL,NULL)); tt_int_op(50UL,OP_EQ, tor_parse_ulong("50",10,50,100,NULL,NULL)); tt_int_op(0UL,OP_EQ, tor_parse_ulong("-50",10,0,100,NULL,NULL)); + tor_capture_bugs_(1); tt_int_op(0UL,OP_EQ, tor_parse_ulong("50",-1,50,100,&i,NULL)); + tt_int_op(1, OP_EQ, smartlist_len(tor_get_captured_bug_log_())); + tor_end_capture_bugs_(); tt_int_op(0,OP_EQ, i); tt_int_op(0UL,OP_EQ, tor_parse_ulong("-50",10,0,100,&i,NULL)); tt_int_op(0,OP_EQ, i); @@ -2157,8 +2173,11 @@ test_util_parse_integer(void *arg) tt_assert(U64_LITERAL(0) == tor_parse_uint64("12345678901",10,500,INT32_MAX, &i, &cp)); tt_int_op(0,OP_EQ, i); + tor_capture_bugs_(1); tt_assert(U64_LITERAL(0) == tor_parse_uint64("123",-1,0,INT32_MAX, &i, &cp)); + tt_int_op(1, OP_EQ, smartlist_len(tor_get_captured_bug_log_())); + tor_end_capture_bugs_(); tt_int_op(0,OP_EQ, i); { @@ -2170,10 +2189,13 @@ test_util_parse_integer(void *arg) tt_int_op(1,OP_EQ, i); tt_assert(DBL_TO_U64(d) == 0); d = tor_parse_double(" ", 0, (double)UINT64_MAX,&i,NULL); + tt_double_op(fabs(d), OP_LT, 1e-10); tt_int_op(0,OP_EQ, i); d = tor_parse_double(".0a", 0, (double)UINT64_MAX,&i,NULL); + tt_double_op(fabs(d), OP_LT, 1e-10); tt_int_op(0,OP_EQ, i); d = tor_parse_double(".0a", 0, (double)UINT64_MAX,&i,&cp); + tt_double_op(fabs(d), OP_LT, 1e-10); tt_int_op(1,OP_EQ, i); d = tor_parse_double("-.0", 0, (double)UINT64_MAX,&i,NULL); tt_int_op(1,OP_EQ, i); @@ -2251,15 +2273,15 @@ test_util_compress_impl(compress_method_t method) tt_assert(tor_compress_supports_method(method)); if (method != NO_METHOD) { - tt_assert(tor_compress_version_str(method) != NULL); - tt_assert(tor_compress_header_version_str(method) != NULL); + tt_ptr_op(tor_compress_version_str(method), OP_NE, NULL); + tt_ptr_op(tor_compress_header_version_str(method), OP_NE, NULL); } buf1 = tor_strdup("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ"); tt_assert(detect_compression_method(buf1, strlen(buf1)) == UNKNOWN_METHOD); tt_assert(!tor_compress(&buf2, &len1, buf1, strlen(buf1)+1, method)); - tt_assert(buf2 != NULL); + tt_ptr_op(buf2, OP_NE, NULL); if (method == NO_METHOD) { // The identity transform doesn't actually compress, and it isn't // detectable as "the identity transform." @@ -2271,7 +2293,7 @@ test_util_compress_impl(compress_method_t method) } tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1, method, 1, LOG_INFO)); - tt_assert(buf3 != NULL); + tt_ptr_op(buf3, OP_NE, NULL); tt_int_op(strlen(buf1) + 1, OP_EQ, len2); tt_str_op(buf1, OP_EQ, buf3); tt_int_op(buf3[len2], OP_EQ, 0); @@ -2318,7 +2340,7 @@ test_util_compress_impl(compress_method_t method) if (method != NO_METHOD) { tt_assert(tor_uncompress(&buf3, &len2, buf2, len1-16, method, 1, LOG_INFO)); - tt_assert(buf3 == NULL); + tt_ptr_op(buf3, OP_EQ, NULL); } done: @@ -2459,6 +2481,126 @@ test_util_decompress_concatenated(void *arg) } static void +test_util_decompress_junk_impl(compress_method_t method) +{ + char input[4096]; + char *result = NULL, *result2 = NULL; + size_t szr, szr2, sz; + int r; + + /* This shouldn't be a compressed string according to any method. */ + strlcpy(input, "This shouldn't be a compressed string by any means.", + sizeof(input)); + sz = strlen(input); + setup_capture_of_logs(LOG_WARN); + r = tor_uncompress(&result, &szr, input, sz, method, 0, LOG_WARN); + tt_int_op(r, OP_EQ, -1); + tt_ptr_op(result, OP_EQ, NULL); + expect_log_msg_containing("Error while uncompressing data: bad input?"); + mock_clean_saved_logs(); + + /* Now try again, with a compressed object that starts out good and turns to + junk. */ + crypto_rand(input, sizeof(input)); + r = tor_compress(&result, &szr, input, sizeof(input), method); + tt_int_op(r, OP_EQ, 0); + crypto_rand(result+szr/2, szr-(szr/2)); // trash the 2nd half of the result + r = tor_uncompress(&result2, &szr2, result, szr, method, 0, LOG_WARN); + tt_int_op(r, OP_EQ, -1); + expect_log_msg_containing("Error while uncompressing data: bad input?"); + + done: + teardown_capture_of_logs(); + tor_free(result); + tor_free(result2); +} + +static void +test_util_decompress_junk(void *arg) +{ + const char *methodname = arg; + tt_assert(methodname); + + compress_method_t method = compression_method_get_by_name(methodname); + tt_int_op(method, OP_NE, UNKNOWN_METHOD); + if (! tor_compress_supports_method(method)) { + tt_skip(); + } + + test_util_decompress_junk_impl(method); + done: + ; +} + +/* mock replacement for tor_compress_is_compression_bomb that doesn't + * believe in compression bombs. */ +static int +mock_is_never_compression_bomb(size_t in, size_t out) +{ + (void)in; + (void) out; + return 0; +} + +static void +test_util_decompress_dos_impl(compress_method_t method) +{ + char *input; + char *result = NULL, *result2 = NULL; + size_t szr, szr2; + int r; + + const size_t big = 1024*1024; + /* one megabyte of 0s. */ + input = tor_malloc_zero(big); + + /* Compress it into "result": it should fail. */ + setup_full_capture_of_logs(LOG_WARN); + r = tor_compress(&result, &szr, input, big, method); + tt_int_op(r, OP_EQ, -1); + expect_log_msg_containing( + "other Tors would think this was a compression bomb"); + teardown_capture_of_logs(); + + /* Try again, but this time suppress compression-bomb detection */ + MOCK(tor_compress_is_compression_bomb, mock_is_never_compression_bomb); + r = tor_compress(&result, &szr, input, big, method); + UNMOCK(tor_compress_is_compression_bomb); + tt_int_op(r, OP_EQ, 0); + tt_ptr_op(result, OP_NE, NULL); + + /* We should refuse to uncomrpess it again, since it looks like a + * compression bomb. */ + setup_capture_of_logs(LOG_WARN); + r = tor_uncompress(&result2, &szr2, result, szr, method, 0, LOG_WARN); + tt_int_op(r, OP_EQ, -1); + expect_log_msg_containing("bomb; abandoning stream"); + + done: + teardown_capture_of_logs(); + tor_free(input); + tor_free(result); + tor_free(result2); +} + +static void +test_util_decompress_dos(void *arg) +{ + const char *methodname = arg; + tt_assert(methodname); + + compress_method_t method = compression_method_get_by_name(methodname); + tt_int_op(method, OP_NE, UNKNOWN_METHOD); + if (! tor_compress_supports_method(method)) { + tt_skip(); + } + + test_util_decompress_dos_impl(method); + done: + ; +} + +static void test_util_gzip_compression_bomb(void *arg) { /* A 'compression bomb' is a very small object that uncompresses to a huge @@ -2525,7 +2667,7 @@ test_util_mmap(void *arg) crypto_rand(buf, buflen); mapping = tor_mmap_file(fname1); - tt_assert(! mapping); + tt_ptr_op(mapping, OP_EQ, NULL); write_str_to_file(fname1, "Short file.", 1); @@ -2543,7 +2685,7 @@ test_util_mmap(void *arg) tt_str_op(mapping->data,OP_EQ, "Short file."); tt_int_op(0, OP_EQ, tor_munmap_file(mapping)); mapping = NULL; -#endif +#endif /* defined(_WIN32) */ /* Now a zero-length file. */ write_str_to_file(fname1, "", 1); @@ -2554,7 +2696,7 @@ test_util_mmap(void *arg) /* Make sure that we fail to map a no-longer-existent file. */ mapping = tor_mmap_file(fname1); - tt_assert(! mapping); + tt_ptr_op(mapping, OP_EQ, NULL); /* Now try a big file that stretches across a few pages and isn't aligned */ write_bytes_to_file(fname2, buf, buflen, 1); @@ -2872,7 +3014,7 @@ test_util_sscanf(void *arg) r = tor_sscanf("9223372036854775808. -9223372036854775809.", "%d. %d.", &int1, &int2); tt_int_op(r,OP_EQ, 0); -#endif +#endif /* SIZEOF_INT == 4 || ... */ #if SIZEOF_LONG == 4 /* %lu */ @@ -2967,7 +3109,7 @@ test_util_sscanf(void *arg) r = tor_sscanf("9223372036854775808. -9223372036854775809.", "%ld. %ld.", &lng1, &lng2); tt_int_op(r,OP_EQ, 0); -#endif +#endif /* SIZEOF_LONG == 4 || ... */ r = tor_sscanf("123.456 .000007 -900123123.2000787 00003.2", "%lf %lf %lf %lf", &d1,&d2,&d3,&d4); @@ -2994,7 +3136,7 @@ strnlen(const char *s, size_t len) return len; return p - s; } -#endif +#endif /* !defined(HAVE_STRNLEN) */ static void test_util_format_time_interval(void *arg) @@ -3361,7 +3503,7 @@ test_util_format_time_interval(void *arg) tt_ci_char_op(label_m[0],OP_EQ, 'm'); /* and 7 or 8 seconds - ignored */ -#endif +#endif /* SIZEOF_LONG == 4 || SIZEOF_LONG == 8 */ #if SIZEOF_LONG == 8 @@ -3399,7 +3541,7 @@ test_util_format_time_interval(void *arg) tt_ci_char_op(label_m[0],OP_EQ, 'm'); /* and 7 or 8 seconds - ignored */ -#endif +#endif /* SIZEOF_LONG == 8 */ done: ; @@ -3442,7 +3584,7 @@ test_util_path_is_relative(void *arg) tt_int_op(0,OP_EQ, path_is_relative("\\dir")); tt_int_op(0,OP_EQ, path_is_relative("a:\\dir")); tt_int_op(0,OP_EQ, path_is_relative("z:\\dir")); -#endif +#endif /* defined(_WIN32) */ done: ; @@ -3462,7 +3604,7 @@ test_util_memarea(void *arg) malloc(), which is free to lay out memory most any way it wants. */ if (1) tt_skip(); -#endif +#endif /* defined(DISABLE_MEMORY_SENTINELS) */ (void)arg; tt_assert(area); @@ -3633,8 +3775,8 @@ test_util_strtok(void *arg) } tor_snprintf(buf, sizeof(buf), "%s", pad1); tor_snprintf(buf2, sizeof(buf2), "%s", pad2); - tt_assert(NULL == tor_strtok_r_impl(buf, " ", &cp1)); - tt_assert(NULL == tor_strtok_r_impl(buf2, ".!..;!", &cp2)); + tt_ptr_op(tor_strtok_r_impl(buf, " ", &cp1), OP_EQ, NULL); + tt_ptr_op(tor_strtok_r_impl(buf2, ".!..;!", &cp2), OP_EQ, NULL); tor_snprintf(buf, sizeof(buf), "%sGraved on the dark in gestures of descent%s", pad1, pad1); @@ -3984,7 +4126,7 @@ test_util_load_win_lib(void *ptr) if (h) FreeLibrary(h); } -#endif +#endif /* defined(_WIN32) */ #ifndef _WIN32 static void @@ -4036,7 +4178,7 @@ test_util_exit_status(void *ptr) tt_int_op(n,OP_EQ, strlen(hex_errno)); tt_int_op(n,OP_EQ, HEX_ERRNO_SIZE); -#endif +#endif /* SIZEOF_INT == 4 || ... */ clear_hex_errno(hex_errno); n = format_helper_exit_status(0x7F, 0, hex_errno); @@ -4054,7 +4196,7 @@ test_util_exit_status(void *ptr) done: ; } -#endif +#endif /* !defined(_WIN32) */ #ifndef _WIN32 static void @@ -4182,7 +4324,7 @@ test_util_string_from_pipe(void *ptr) close(test_pipe[1]); } -#endif // _WIN32 +#endif /* !defined(_WIN32) */ /** * Test for format_hex_number_sigsafe() @@ -4378,7 +4520,7 @@ test_util_split_lines(void *ptr) /* Check we have not got too many lines */ tt_int_op(MAX_SPLIT_LINE_COUNT, OP_GT, j); /* Check that there actually should be a line here */ - tt_assert(tests[i].split_line[j] != NULL); + tt_ptr_op(tests[i].split_line[j], OP_NE, NULL); log_info(LD_GENERAL, "Line %d of test %d, should be <%s>", j, i, tests[i].split_line[j]); /* Check that the line is as expected */ @@ -4494,11 +4636,11 @@ test_util_di_map(void *arg) char dflt_entry[] = "'You have made a good beginning', but no more"; - tt_int_op(32, ==, sizeof(key1)); - tt_int_op(32, ==, sizeof(key2)); - tt_int_op(32, ==, sizeof(key3)); + tt_int_op(32, OP_EQ, sizeof(key1)); + tt_int_op(32, OP_EQ, sizeof(key2)); + tt_int_op(32, OP_EQ, sizeof(key3)); - tt_ptr_op(dflt_entry, ==, dimap_search(dimap, key1, dflt_entry)); + tt_ptr_op(dflt_entry, OP_EQ, dimap_search(dimap, key1, dflt_entry)); char *str1 = tor_strdup("You are precisely as big as what you love" " and precisely as small as what you allow" @@ -4516,10 +4658,10 @@ test_util_di_map(void *arg) dimap_add_entry(&dimap, key2, str2); dimap_add_entry(&dimap, key3, str3); - tt_ptr_op(str1, ==, dimap_search(dimap, key1, dflt_entry)); - tt_ptr_op(str3, ==, dimap_search(dimap, key3, dflt_entry)); - tt_ptr_op(str2, ==, dimap_search(dimap, key2, dflt_entry)); - tt_ptr_op(dflt_entry, ==, dimap_search(dimap, key4, dflt_entry)); + tt_ptr_op(str1, OP_EQ, dimap_search(dimap, key1, dflt_entry)); + tt_ptr_op(str3, OP_EQ, dimap_search(dimap, key3, dflt_entry)); + tt_ptr_op(str2, OP_EQ, dimap_search(dimap, key2, dflt_entry)); + tt_ptr_op(dflt_entry, OP_EQ, dimap_search(dimap, key4, dflt_entry)); done: dimap_free(dimap, tor_free_); @@ -4986,34 +5128,34 @@ test_util_round_to_next_multiple_of(void *arg) { (void)arg; - tt_u64_op(round_uint64_to_next_multiple_of(0,1), ==, 0); - tt_u64_op(round_uint64_to_next_multiple_of(0,7), ==, 0); + tt_u64_op(round_uint64_to_next_multiple_of(0,1), OP_EQ, 0); + tt_u64_op(round_uint64_to_next_multiple_of(0,7), OP_EQ, 0); - tt_u64_op(round_uint64_to_next_multiple_of(99,1), ==, 99); - tt_u64_op(round_uint64_to_next_multiple_of(99,7), ==, 105); - tt_u64_op(round_uint64_to_next_multiple_of(99,9), ==, 99); + tt_u64_op(round_uint64_to_next_multiple_of(99,1), OP_EQ, 99); + tt_u64_op(round_uint64_to_next_multiple_of(99,7), OP_EQ, 105); + tt_u64_op(round_uint64_to_next_multiple_of(99,9), OP_EQ, 99); - tt_u64_op(round_uint64_to_next_multiple_of(UINT64_MAX,2), ==, + tt_u64_op(round_uint64_to_next_multiple_of(UINT64_MAX,2), OP_EQ, UINT64_MAX); - tt_int_op(round_uint32_to_next_multiple_of(0,1), ==, 0); - tt_int_op(round_uint32_to_next_multiple_of(0,7), ==, 0); + tt_int_op(round_uint32_to_next_multiple_of(0,1), OP_EQ, 0); + tt_int_op(round_uint32_to_next_multiple_of(0,7), OP_EQ, 0); - tt_int_op(round_uint32_to_next_multiple_of(99,1), ==, 99); - tt_int_op(round_uint32_to_next_multiple_of(99,7), ==, 105); - tt_int_op(round_uint32_to_next_multiple_of(99,9), ==, 99); + tt_int_op(round_uint32_to_next_multiple_of(99,1), OP_EQ, 99); + tt_int_op(round_uint32_to_next_multiple_of(99,7), OP_EQ, 105); + tt_int_op(round_uint32_to_next_multiple_of(99,9), OP_EQ, 99); - tt_int_op(round_uint32_to_next_multiple_of(UINT32_MAX,2), ==, + tt_int_op(round_uint32_to_next_multiple_of(UINT32_MAX,2), OP_EQ, UINT32_MAX); - tt_uint_op(round_to_next_multiple_of(0,1), ==, 0); - tt_uint_op(round_to_next_multiple_of(0,7), ==, 0); + tt_uint_op(round_to_next_multiple_of(0,1), OP_EQ, 0); + tt_uint_op(round_to_next_multiple_of(0,7), OP_EQ, 0); - tt_uint_op(round_to_next_multiple_of(99,1), ==, 99); - tt_uint_op(round_to_next_multiple_of(99,7), ==, 105); - tt_uint_op(round_to_next_multiple_of(99,9), ==, 99); + tt_uint_op(round_to_next_multiple_of(99,1), OP_EQ, 99); + tt_uint_op(round_to_next_multiple_of(99,7), OP_EQ, 105); + tt_uint_op(round_to_next_multiple_of(99,9), OP_EQ, 99); - tt_uint_op(round_to_next_multiple_of(UINT_MAX,2), ==, + tt_uint_op(round_to_next_multiple_of(UINT_MAX,2), OP_EQ, UINT_MAX); done: ; @@ -5034,26 +5176,26 @@ test_util_laplace(void *arg) const double delta_f = 15.0, epsilon = 0.3; /* b = 15.0 / 0.3 = 50.0 */ (void)arg; - tt_i64_op(INT64_MIN, ==, sample_laplace_distribution(mu, b, 0.0)); - tt_i64_op(-69, ==, sample_laplace_distribution(mu, b, 0.01)); - tt_i64_op(24, ==, sample_laplace_distribution(mu, b, 0.5)); - tt_i64_op(24, ==, sample_laplace_distribution(mu, b, 0.51)); - tt_i64_op(117, ==, sample_laplace_distribution(mu, b, 0.99)); + tt_i64_op(INT64_MIN, OP_EQ, sample_laplace_distribution(mu, b, 0.0)); + tt_i64_op(-69, OP_EQ, sample_laplace_distribution(mu, b, 0.01)); + tt_i64_op(24, OP_EQ, sample_laplace_distribution(mu, b, 0.5)); + tt_i64_op(24, OP_EQ, sample_laplace_distribution(mu, b, 0.51)); + tt_i64_op(117, OP_EQ, sample_laplace_distribution(mu, b, 0.99)); /* >>> laplace.ppf([0.0, 0.1, 0.25, 0.5, 0.75, 0.9, 0.99], * ... loc = 0, scale = 50) * array([ -inf, -80.47189562, -34.65735903, 0. , * 34.65735903, 80.47189562, 195.60115027]) */ - tt_i64_op(INT64_MIN + 20, ==, + tt_i64_op(INT64_MIN + 20, OP_EQ, add_laplace_noise(20, 0.0, delta_f, epsilon)); - tt_i64_op(-60, ==, add_laplace_noise(20, 0.1, delta_f, epsilon)); - tt_i64_op(-14, ==, add_laplace_noise(20, 0.25, delta_f, epsilon)); - tt_i64_op(20, ==, add_laplace_noise(20, 0.5, delta_f, epsilon)); - tt_i64_op(54, ==, add_laplace_noise(20, 0.75, delta_f, epsilon)); - tt_i64_op(100, ==, add_laplace_noise(20, 0.9, delta_f, epsilon)); - tt_i64_op(215, ==, add_laplace_noise(20, 0.99, delta_f, epsilon)); + tt_i64_op(-60, OP_EQ, add_laplace_noise(20, 0.1, delta_f, epsilon)); + tt_i64_op(-14, OP_EQ, add_laplace_noise(20, 0.25, delta_f, epsilon)); + tt_i64_op(20, OP_EQ, add_laplace_noise(20, 0.5, delta_f, epsilon)); + tt_i64_op(54, OP_EQ, add_laplace_noise(20, 0.75, delta_f, epsilon)); + tt_i64_op(100, OP_EQ, add_laplace_noise(20, 0.9, delta_f, epsilon)); + tt_i64_op(215, OP_EQ, add_laplace_noise(20, 0.99, delta_f, epsilon)); /* Test extreme values of signal with maximally negative values of noise * 1.0000000000000002 is the smallest number > 1 @@ -5066,54 +5208,54 @@ test_util_laplace(void *arg) */ const double noscale_df = 1.0, noscale_eps = 1.0; - tt_i64_op(INT64_MIN, ==, + tt_i64_op(INT64_MIN, OP_EQ, add_laplace_noise(0, 0.0, noscale_df, noscale_eps)); /* is it clipped to INT64_MIN? */ - tt_i64_op(INT64_MIN, ==, + tt_i64_op(INT64_MIN, OP_EQ, add_laplace_noise(-1, 0.0, noscale_df, noscale_eps)); - tt_i64_op(INT64_MIN, ==, + tt_i64_op(INT64_MIN, OP_EQ, add_laplace_noise(INT64_MIN, 0.0, noscale_df, noscale_eps)); /* ... even when scaled? */ - tt_i64_op(INT64_MIN, ==, + tt_i64_op(INT64_MIN, OP_EQ, add_laplace_noise(0, 0.0, delta_f, epsilon)); - tt_i64_op(INT64_MIN, ==, + tt_i64_op(INT64_MIN, OP_EQ, add_laplace_noise(0, 0.0, DBL_MAX, 1)); - tt_i64_op(INT64_MIN, ==, + tt_i64_op(INT64_MIN, OP_EQ, add_laplace_noise(INT64_MIN, 0.0, DBL_MAX, 1)); /* does it play nice with INT64_MAX? */ - tt_i64_op((INT64_MIN + INT64_MAX), ==, + tt_i64_op((INT64_MIN + INT64_MAX), OP_EQ, add_laplace_noise(INT64_MAX, 0.0, noscale_df, noscale_eps)); /* do near-zero fractional values work? */ const double min_dbl_error = 0.0000000000000002; - tt_i64_op(-35, ==, + tt_i64_op(-35, OP_EQ, add_laplace_noise(0, min_dbl_error, noscale_df, noscale_eps)); - tt_i64_op(INT64_MIN, ==, + tt_i64_op(INT64_MIN, OP_EQ, add_laplace_noise(INT64_MIN, min_dbl_error, noscale_df, noscale_eps)); - tt_i64_op((-35 + INT64_MAX), ==, + tt_i64_op((-35 + INT64_MAX), OP_EQ, add_laplace_noise(INT64_MAX, min_dbl_error, noscale_df, noscale_eps)); - tt_i64_op(INT64_MIN, ==, + tt_i64_op(INT64_MIN, OP_EQ, add_laplace_noise(0, min_dbl_error, DBL_MAX, 1)); - tt_i64_op((INT64_MAX + INT64_MIN), ==, + tt_i64_op((INT64_MAX + INT64_MIN), OP_EQ, add_laplace_noise(INT64_MAX, min_dbl_error, DBL_MAX, 1)); - tt_i64_op(INT64_MIN, ==, + tt_i64_op(INT64_MIN, OP_EQ, add_laplace_noise(INT64_MIN, min_dbl_error, DBL_MAX, 1)); /* does it play nice with INT64_MAX? */ - tt_i64_op((INT64_MAX - 35), ==, + tt_i64_op((INT64_MAX - 35), OP_EQ, add_laplace_noise(INT64_MAX, min_dbl_error, noscale_df, noscale_eps)); @@ -5128,31 +5270,31 @@ test_util_laplace(void *arg) const double max_dbl_lt_one = 0.9999999999999998; /* do near-one fractional values work? */ - tt_i64_op(35, ==, + tt_i64_op(35, OP_EQ, add_laplace_noise(0, max_dbl_lt_one, noscale_df, noscale_eps)); /* is it clipped to INT64_MAX? */ - tt_i64_op(INT64_MAX, ==, + tt_i64_op(INT64_MAX, OP_EQ, add_laplace_noise(INT64_MAX - 35, max_dbl_lt_one, noscale_df, noscale_eps)); - tt_i64_op(INT64_MAX, ==, + tt_i64_op(INT64_MAX, OP_EQ, add_laplace_noise(INT64_MAX - 34, max_dbl_lt_one, noscale_df, noscale_eps)); - tt_i64_op(INT64_MAX, ==, + tt_i64_op(INT64_MAX, OP_EQ, add_laplace_noise(INT64_MAX, max_dbl_lt_one, noscale_df, noscale_eps)); /* ... even when scaled? */ - tt_i64_op(INT64_MAX, ==, + tt_i64_op(INT64_MAX, OP_EQ, add_laplace_noise(INT64_MAX, max_dbl_lt_one, delta_f, epsilon)); - tt_i64_op((INT64_MIN + INT64_MAX), ==, + tt_i64_op((INT64_MIN + INT64_MAX), OP_EQ, add_laplace_noise(INT64_MIN, max_dbl_lt_one, DBL_MAX, 1)); - tt_i64_op(INT64_MAX, ==, + tt_i64_op(INT64_MAX, OP_EQ, add_laplace_noise(INT64_MAX, max_dbl_lt_one, DBL_MAX, 1)); /* does it play nice with INT64_MIN? */ - tt_i64_op((INT64_MIN + 35), ==, + tt_i64_op((INT64_MIN + 35), OP_EQ, add_laplace_noise(INT64_MIN, max_dbl_lt_one, noscale_df, noscale_eps)); @@ -5165,32 +5307,32 @@ test_util_clamp_double_to_int64(void *arg) { (void)arg; - tt_i64_op(INT64_MIN, ==, clamp_double_to_int64(-INFINITY_DBL)); - tt_i64_op(INT64_MIN, ==, + tt_i64_op(INT64_MIN, OP_EQ, clamp_double_to_int64(-INFINITY_DBL)); + tt_i64_op(INT64_MIN, OP_EQ, clamp_double_to_int64(-1.0 * pow(2.0, 64.0) - 1.0)); - tt_i64_op(INT64_MIN, ==, + tt_i64_op(INT64_MIN, OP_EQ, clamp_double_to_int64(-1.0 * pow(2.0, 63.0) - 1.0)); - tt_i64_op(((uint64_t) -1) << 53, ==, + tt_i64_op(((uint64_t) -1) << 53, OP_EQ, clamp_double_to_int64(-1.0 * pow(2.0, 53.0))); - tt_i64_op((((uint64_t) -1) << 53) + 1, ==, + tt_i64_op((((uint64_t) -1) << 53) + 1, OP_EQ, clamp_double_to_int64(-1.0 * pow(2.0, 53.0) + 1.0)); - tt_i64_op(-1, ==, clamp_double_to_int64(-1.0)); - tt_i64_op(0, ==, clamp_double_to_int64(-0.9)); - tt_i64_op(0, ==, clamp_double_to_int64(-0.1)); - tt_i64_op(0, ==, clamp_double_to_int64(0.0)); - tt_i64_op(0, ==, clamp_double_to_int64(NAN_DBL)); - tt_i64_op(0, ==, clamp_double_to_int64(0.1)); - tt_i64_op(0, ==, clamp_double_to_int64(0.9)); - tt_i64_op(1, ==, clamp_double_to_int64(1.0)); - tt_i64_op((((int64_t) 1) << 53) - 1, ==, + tt_i64_op(-1, OP_EQ, clamp_double_to_int64(-1.0)); + tt_i64_op(0, OP_EQ, clamp_double_to_int64(-0.9)); + tt_i64_op(0, OP_EQ, clamp_double_to_int64(-0.1)); + tt_i64_op(0, OP_EQ, clamp_double_to_int64(0.0)); + tt_i64_op(0, OP_EQ, clamp_double_to_int64(NAN_DBL)); + tt_i64_op(0, OP_EQ, clamp_double_to_int64(0.1)); + tt_i64_op(0, OP_EQ, clamp_double_to_int64(0.9)); + tt_i64_op(1, OP_EQ, clamp_double_to_int64(1.0)); + tt_i64_op((((int64_t) 1) << 53) - 1, OP_EQ, clamp_double_to_int64(pow(2.0, 53.0) - 1.0)); - tt_i64_op(((int64_t) 1) << 53, ==, + tt_i64_op(((int64_t) 1) << 53, OP_EQ, clamp_double_to_int64(pow(2.0, 53.0))); - tt_i64_op(INT64_MAX, ==, + tt_i64_op(INT64_MAX, OP_EQ, clamp_double_to_int64(pow(2.0, 63.0))); - tt_i64_op(INT64_MAX, ==, + tt_i64_op(INT64_MAX, OP_EQ, clamp_double_to_int64(pow(2.0, 64.0))); - tt_i64_op(INT64_MAX, ==, clamp_double_to_int64(INFINITY_DBL)); + tt_i64_op(INT64_MAX, OP_EQ, clamp_double_to_int64(INFINITY_DBL)); done: ; @@ -5204,7 +5346,7 @@ fd_is_cloexec(tor_socket_t fd) int flags = fcntl(fd, F_GETFD, 0); return (flags & FD_CLOEXEC) == FD_CLOEXEC; } -#endif +#endif /* defined(FD_CLOEXEC) */ #ifndef _WIN32 #define CAN_CHECK_NONBLOCK @@ -5214,7 +5356,7 @@ fd_is_nonblocking(tor_socket_t fd) int flags = fcntl(fd, F_GETFL, 0); return (flags & O_NONBLOCK) == O_NONBLOCK; } -#endif +#endif /* !defined(_WIN32) */ #define ERRNO_IS_EPROTO(e) (e == SOCK_ERRNO(EPROTONOSUPPORT)) #define SOCK_ERR_IS_EPROTO(s) ERRNO_IS_EPROTO(tor_socket_errno(s)) @@ -5258,13 +5400,13 @@ test_util_socket(void *arg) tt_int_op(fd_is_cloexec(fd2), OP_EQ, 0); tt_int_op(fd_is_cloexec(fd3), OP_EQ, 1); tt_int_op(fd_is_cloexec(fd4), OP_EQ, 1); -#endif +#endif /* defined(CAN_CHECK_CLOEXEC) */ #ifdef CAN_CHECK_NONBLOCK tt_int_op(fd_is_nonblocking(fd1), OP_EQ, 0); tt_int_op(fd_is_nonblocking(fd2), OP_EQ, 1); tt_int_op(fd_is_nonblocking(fd3), OP_EQ, 0); tt_int_op(fd_is_nonblocking(fd4), OP_EQ, 1); -#endif +#endif /* defined(CAN_CHECK_NONBLOCK) */ tor_assert(tor_close_socket == tor_close_socket__real); @@ -5320,7 +5462,7 @@ is_there_a_localhost(int family) return result; } -#endif +#endif /* 0 */ /* Test for socketpair and ersatz_socketpair(). We test them both, since * the latter is a tolerably good way to exersize tor_accept_socket(). */ @@ -5347,7 +5489,7 @@ test_util_socketpair(void *arg) * Assume we're on a machine without 127.0.0.1 or ::1 and give up now. */ tt_skip(); } -#endif +#endif /* defined(__FreeBSD__) */ tt_int_op(0, OP_EQ, socketpair_result); tt_assert(SOCKET_OK(fds[0])); @@ -5508,7 +5650,7 @@ test_util_get_avail_disk_space(void *arg) #else tt_i64_op(val, OP_GT, 0); /* You have some space. */ tt_i64_op(val, OP_LT, ((int64_t)1)<<56); /* You don't have a zebibyte */ -#endif +#endif /* !defined(HAVE_STATVFS) && !defined(_WIN32) */ done: ; @@ -5558,25 +5700,25 @@ test_util_pwdb(void *arg) /* Uncached case. */ /* Let's assume that we exist. */ me = tor_getpwuid(getuid()); - tt_assert(me != NULL); + tt_ptr_op(me, OP_NE, NULL); name = tor_strdup(me->pw_name); /* Uncached case */ me2 = tor_getpwnam(name); - tt_assert(me2 != NULL); + tt_ptr_op(me2, OP_NE, NULL); tt_int_op(me2->pw_uid, OP_EQ, getuid()); /* Cached case */ me3 = tor_getpwuid(getuid()); - tt_assert(me3 != NULL); + tt_ptr_op(me3, OP_NE, NULL); tt_str_op(me3->pw_name, OP_EQ, name); me3 = tor_getpwnam(name); - tt_assert(me3 != NULL); + tt_ptr_op(me3, OP_NE, NULL); tt_int_op(me3->pw_uid, OP_EQ, getuid()); dir = get_user_homedir(name); - tt_assert(dir != NULL); + tt_ptr_op(dir, OP_NE, NULL); /* Try failing cases. First find a user that doesn't exist by name */ char randbytes[4]; @@ -5596,7 +5738,7 @@ test_util_pwdb(void *arg) /* We should do a LOG_ERR */ setup_full_capture_of_logs(LOG_ERR); dir = get_user_homedir(badname); - tt_assert(dir == NULL); + tt_ptr_op(dir, OP_EQ, NULL); expect_log_msg_containing("not found"); tt_int_op(smartlist_len(mock_saved_logs()), OP_EQ, 1); teardown_capture_of_logs(); @@ -5618,7 +5760,7 @@ test_util_pwdb(void *arg) tor_free(dir); teardown_capture_of_logs(); } -#endif +#endif /* !defined(_WIN32) */ static void test_util_calloc_check(void *arg) @@ -5796,7 +5938,7 @@ test_util_htonll(void *arg) #else tt_u64_op(res_le, OP_EQ, tor_htonll(0x8877665544332211)); tt_u64_op(res_le, OP_EQ, tor_ntohll(0x8877665544332211)); -#endif +#endif /* defined(WORDS_BIGENDIAN) */ done: ; @@ -5895,6 +6037,16 @@ test_util_get_unquoted_path(void *arg) &passthrough_setup, \ (char*)(identifier) } +#define COMPRESS_JUNK(name, identifier) \ + { "compress_junk/" #name, test_util_decompress_junk, 0, \ + &passthrough_setup, \ + (char*)(identifier) } + +#define COMPRESS_DOS(name, identifier) \ + { "compress_dos/" #name, test_util_decompress_dos, 0, \ + &passthrough_setup, \ + (char*)(identifier) } + #ifdef _WIN32 #define UTIL_TEST_NO_WIN(n, f) { #n, NULL, TT_SKIP, NULL, NULL } #define UTIL_TEST_WIN_ONLY(n, f) UTIL_TEST(n, (f)) @@ -5903,7 +6055,7 @@ test_util_get_unquoted_path(void *arg) #define UTIL_TEST_NO_WIN(n, f) UTIL_TEST(n, (f)) #define UTIL_TEST_WIN_ONLY(n, f) { #n, NULL, TT_SKIP, NULL, NULL } #define UTIL_LEGACY_NO_WIN(n) UTIL_LEGACY(n) -#endif +#endif /* defined(_WIN32) */ struct testcase_t util_tests[] = { UTIL_LEGACY(time), @@ -5929,6 +6081,13 @@ struct testcase_t util_tests[] = { COMPRESS_CONCAT(lzma, "x-tor-lzma"), COMPRESS_CONCAT(zstd, "x-zstd"), COMPRESS_CONCAT(none, "identity"), + COMPRESS_JUNK(zlib, "deflate"), + COMPRESS_JUNK(gzip, "gzip"), + COMPRESS_JUNK(lzma, "x-tor-lzma"), + COMPRESS_DOS(zlib, "deflate"), + COMPRESS_DOS(gzip, "gzip"), + COMPRESS_DOS(lzma, "x-tor-lzma"), + COMPRESS_DOS(zstd, "x-zstd"), UTIL_TEST(gzip_compression_bomb, TT_FORK), UTIL_LEGACY(datadir), UTIL_LEGACY(memarea), diff --git a/src/test/test_util_format.c b/src/test/test_util_format.c index ea0a86499f..683d5fdac1 100644 --- a/src/test/test_util_format.c +++ b/src/test/test_util_format.c @@ -345,7 +345,7 @@ test_util_format_base32_decode(void *arg) const char *src = "mjwgc2dcnrswqmjs"; ret = base32_decode(dst, strlen(expected), src, strlen(src)); - tt_int_op(ret, ==, 0); + tt_int_op(ret, OP_EQ, 0); tt_str_op(expected, OP_EQ, dst); } @@ -356,7 +356,7 @@ test_util_format_base32_decode(void *arg) const char *src = "mjwgc2dcnrswq"; ret = base32_decode(dst, strlen(expected), src, strlen(src)); - tt_int_op(ret, ==, 0); + tt_int_op(ret, OP_EQ, 0); tt_mem_op(expected, OP_EQ, dst, strlen(expected)); } @@ -364,9 +364,9 @@ test_util_format_base32_decode(void *arg) { /* Invalid character '#'. */ ret = base32_decode(dst, real_dstlen, "#abcde", 6); - tt_int_op(ret, ==, -1); + tt_int_op(ret, OP_EQ, -1); /* Make sure the destination buffer has been zeroed even on error. */ - tt_int_op(tor_mem_is_zero(dst, real_dstlen), ==, 1); + tt_int_op(tor_mem_is_zero(dst, real_dstlen), OP_EQ, 1); } done: diff --git a/src/test/test_util_process.c b/src/test/test_util_process.c index 70292f2287..68ce6cfd40 100644 --- a/src/test/test_util_process.c +++ b/src/test/test_util_process.c @@ -67,7 +67,7 @@ test_util_process_clear_waitpid_callback(void *ignored) done: teardown_capture_of_logs(); } -#endif /* _WIN32 */ +#endif /* !defined(_WIN32) */ #ifndef _WIN32 #define TEST(name) { #name, test_util_process_##name, 0, NULL, NULL } diff --git a/src/test/test_util_slow.c b/src/test/test_util_slow.c index 3e5d78948d..2cd68cf118 100644 --- a/src/test/test_util_slow.c +++ b/src/test/test_util_slow.c @@ -22,14 +22,14 @@ #else #define TEST_CHILD (BUILDDIR "/src/test/test-child") #define EOL "\n" -#endif +#endif /* defined(_WIN32) */ #ifdef _WIN32 /* I've assumed Windows doesn't have the gap between fork and exec * that causes the race condition on unix-like platforms */ #define MATCH_PROCESS_STATUS(s1,s2) ((s1) == (s2)) -#else +#else /* !(defined(_WIN32)) */ /* work around a race condition of the timing of SIGCHLD handler updates * to the process_handle's fields, and checks of those fields * @@ -46,7 +46,7 @@ ||((s2) == PROCESS_STATUS_RUNNING_OR_NOTRUNNING \ && IS_RUNNING_OR_NOTRUNNING(s1))) -#endif // _WIN32 +#endif /* defined(_WIN32) */ /** Helper function for testing tor_spawn_background */ static void @@ -78,7 +78,7 @@ run_util_spawn_background(const char *argv[], const char *expected_out, return; } - tt_assert(process_handle != NULL); + tt_ptr_op(process_handle, OP_NE, NULL); /* When a spawned process forks, fails, then exits very quickly, * (this typically occurs when exec fails) @@ -102,7 +102,7 @@ run_util_spawn_background(const char *argv[], const char *expected_out, * that is, PROCESS_STATUS_RUNNING_OR_NOTRUNNING */ tt_assert(process_handle->waitpid_cb != NULL || expected_status == PROCESS_STATUS_RUNNING_OR_NOTRUNNING); -#endif +#endif /* !defined(_WIN32) */ #ifdef _WIN32 tt_assert(process_handle->stdout_pipe != INVALID_HANDLE_VALUE); @@ -112,7 +112,7 @@ run_util_spawn_background(const char *argv[], const char *expected_out, tt_assert(process_handle->stdout_pipe >= 0); tt_assert(process_handle->stderr_pipe >= 0); tt_assert(process_handle->stdin_pipe >= 0); -#endif +#endif /* defined(_WIN32) */ /* Check stdout */ pos = tor_read_all_from_process_stdout(process_handle, stdout_buf, @@ -178,7 +178,7 @@ test_util_spawn_background_fail(void *ptr) /* TODO: Once we can signal failure to exec, set this to be * PROCESS_STATUS_RUNNING_OR_ERROR */ const int expected_status = PROCESS_STATUS_RUNNING_OR_NOTRUNNING; -#endif +#endif /* defined(_WIN32) */ memset(expected_out, 0xf0, sizeof(expected_out)); memset(code, 0xf0, sizeof(code)); @@ -244,7 +244,7 @@ test_util_spawn_background_partial_read_impl(int exit_early) tt_assert(!eof); pos = tor_read_all_handle(process_handle->stdout_pipe, stdout_buf, sizeof(stdout_buf) - 1, NULL, &eof); -#endif +#endif /* defined(_WIN32) */ log_info(LD_GENERAL, "tor_read_all_handle() returned %d", (int)pos); /* We would have blocked, keep on trying */ @@ -270,7 +270,7 @@ test_util_spawn_background_partial_read_impl(int exit_early) sizeof(stdout_buf) - 1, process_handle); tt_int_op(0,OP_EQ, pos); -#else +#else /* !(defined(_WIN32)) */ if (!eof) { /* We should have got all the data, but maybe not the EOF flag */ pos = tor_read_all_handle(process_handle->stdout_pipe, stdout_buf, @@ -280,7 +280,7 @@ test_util_spawn_background_partial_read_impl(int exit_early) tt_assert(eof); } /* Otherwise, we got the EOF on the last read */ -#endif +#endif /* defined(_WIN32) */ /* Check it terminated correctly */ retval = tor_get_exit_code(process_handle, 1, &exit_code); @@ -351,7 +351,7 @@ test_util_spawn_background_waitpid_notify(void *arg) } tt_int_op(ms_timer, OP_GT, 0); tt_ptr_op(process_handle->waitpid_cb, OP_EQ, NULL); -#endif +#endif /* !defined(_WIN32) */ ms_timer = 30*1000; while (((retval = tor_get_exit_code(process_handle, 0, &exit_code)) diff --git a/src/test/test_workqueue.c b/src/test/test_workqueue.c index 6fa46f90d4..2b03173717 100644 --- a/src/test/test_workqueue.c +++ b/src/test/test_workqueue.c @@ -61,9 +61,9 @@ mark_handled(int serial) tor_assert(! bitarray_is_set(handled, serial)); bitarray_set(handled, serial); tor_mutex_release(&bitmap_mutex); -#else +#else /* !(defined(TRACK_RESPONSES)) */ (void)serial; -#endif +#endif /* defined(TRACK_RESPONSES) */ } static workqueue_reply_t @@ -288,7 +288,7 @@ replysock_readable_cb(tor_socket_t sock, short what, void *arg) } puts(""); tor_mutex_release(&bitmap_mutex); -#endif +#endif /* defined(TRACK_RESPONSES) */ if (n_sent - (n_received+n_successful_cancel) < opt_n_lowwater) { int n_to_send = n_received + opt_n_inflight - n_sent; @@ -422,7 +422,7 @@ main(int argc, char **argv) received = bitarray_init_zero(opt_n_items); tor_mutex_init(&bitmap_mutex); handled_len = opt_n_items; -#endif +#endif /* defined(TRACK_RESPONSES) */ for (i = 0; i < opt_n_inflight; ++i) { if (! add_work(tp)) { diff --git a/src/test/testing_common.c b/src/test/testing_common.c index d7e36edbc0..7e9c47b48d 100644 --- a/src/test/testing_common.c +++ b/src/test/testing_common.c @@ -33,7 +33,7 @@ const char tor_git_revision[] = ""; #include <direct.h> #else #include <dirent.h> -#endif +#endif /* defined(_WIN32) */ #include "or.h" @@ -84,7 +84,7 @@ setup_directory(void) (int)getpid(), rnd32); r = mkdir(temp_dir); } -#else +#else /* !(defined(_WIN32)) */ tor_snprintf(temp_dir, sizeof(temp_dir), "/tmp/tor_test_%d_%s", (int) getpid(), rnd32); r = mkdir(temp_dir, 0700); @@ -92,7 +92,7 @@ setup_directory(void) /* undo sticky bit so tests don't get confused. */ r = chown(temp_dir, getuid(), getgid()); } -#endif +#endif /* defined(_WIN32) */ if (r) { fprintf(stderr, "Can't create directory %s:", temp_dir); perror(""); @@ -241,7 +241,7 @@ main(int c, const char **v) int r = crypto_use_tor_alloc_functions(); tor_assert(r == 0); } -#endif +#endif /* defined(USE_DMALLOC) */ update_approx_time(time(NULL)); options = options_new(); diff --git a/src/test/testing_rsakeys.c b/src/test/testing_rsakeys.c index 5dff233a69..7a24c0ed14 100644 --- a/src/test/testing_rsakeys.c +++ b/src/test/testing_rsakeys.c @@ -436,7 +436,7 @@ static int next_key_idx_1024; #define N_PREGEN_KEYS_2048 ARRAY_LENGTH(PREGEN_KEYS_2048) static crypto_pk_t *pregen_keys_2048[N_PREGEN_KEYS_2048]; static int next_key_idx_2048; -#endif +#endif /* defined(USE_PREGENERATED_RSA_KEYS) */ /** Generate and return a new keypair for use in unit tests. If we're using * the key cache optimization, we might reuse keys. "idx" is ignored. @@ -466,14 +466,14 @@ pk_generate_internal(int bits) *idxp += crypto_rand_int_range(1,3); *idxp %= n_pregen; return crypto_pk_dup_key(pregen_array[*idxp]); -#else +#else /* !(defined(USE_PREGENERATED_RSA_KEYS)) */ crypto_pk_t *result; int res; result = crypto_pk_new(); res = crypto_pk_generate_key_with_bits__real(result, bits); tor_assert(!res); return result; -#endif +#endif /* defined(USE_PREGENERATED_RSA_KEYS) */ } crypto_pk_t * @@ -496,7 +496,7 @@ crypto_pk_generate_key_with_bits__get_cached(crypto_pk_t *env, int bits) } return 0; } -#endif +#endif /* defined(USE_PREGENERATED_RSA_KEYS) */ /** Free all storage used for the cached key optimization. */ void @@ -516,7 +516,7 @@ free_pregenerated_keys(void) pregen_keys_2048[idx] = NULL; } } -#endif +#endif /* defined(USE_PREGENERATED_RSA_KEYS) */ } void @@ -541,6 +541,6 @@ init_pregenerated_keys(void) MOCK(crypto_pk_generate_key_with_bits, crypto_pk_generate_key_with_bits__get_cached); -#endif +#endif /* defined(USE_PREGENERATED_RSA_KEYS) */ } |