aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/Makefile.nmake3
-rw-r--r--src/test/bench.c30
-rwxr-xr-xsrc/test/bt_test.py2
-rw-r--r--src/test/ed25519_exts_ref.py38
-rw-r--r--src/test/ed25519_vectors.inc32
-rw-r--r--src/test/fakechans.h2
-rw-r--r--src/test/fuzz/dict/hsdescv36
-rw-r--r--src/test/fuzz/dict/http2
-rw-r--r--src/test/fuzz/fuzz_consensus.c2
-rw-r--r--src/test/fuzz/fuzz_descriptor.c2
-rw-r--r--src/test/fuzz/fuzz_diff.c69
-rw-r--r--src/test/fuzz/fuzz_diff_apply.c65
-rw-r--r--src/test/fuzz/fuzz_extrainfo.c2
-rw-r--r--src/test/fuzz/fuzz_hsdescv2.c2
-rw-r--r--src/test/fuzz/fuzz_hsdescv3.c99
-rw-r--r--src/test/fuzz/fuzz_http.c6
-rw-r--r--src/test/fuzz/fuzz_http_connect.c106
-rw-r--r--src/test/fuzz/fuzz_iptsv2.c2
-rw-r--r--src/test/fuzz/fuzz_microdesc.c2
-rw-r--r--src/test/fuzz/fuzz_vrs.c2
-rw-r--r--src/test/fuzz/fuzzing.h2
-rw-r--r--src/test/fuzz/fuzzing_common.c10
-rw-r--r--src/test/fuzz/include.am181
-rwxr-xr-xsrc/test/fuzz_static_testcases.sh2
-rw-r--r--src/test/hs_build_address.py38
-rw-r--r--src/test/hs_indexes.py70
-rw-r--r--src/test/hs_ntor_ref.py425
-rw-r--r--src/test/hs_test_helpers.c276
-rw-r--r--src/test/hs_test_helpers.h25
-rw-r--r--src/test/include.am102
-rw-r--r--src/test/log_test_helpers.c2
-rw-r--r--src/test/log_test_helpers.h8
-rwxr-xr-xsrc/test/ntor_ref.py2
-rw-r--r--src/test/rend_test_helpers.c18
-rw-r--r--src/test/rend_test_helpers.h5
-rw-r--r--src/test/test-child.c4
-rwxr-xr-xsrc/test/test-network.sh185
-rw-r--r--src/test/test-timers.c2
-rw-r--r--src/test/test.c95
-rw-r--r--src/test/test.h25
-rw-r--r--src/test/test_addr.c66
-rw-r--r--src/test/test_address.c82
-rw-r--r--src/test/test_bt_cl.c4
-rw-r--r--src/test/test_buffers.c474
-rw-r--r--src/test/test_cell_formats.c2
-rw-r--r--src/test/test_cell_queue.c2
-rw-r--r--src/test/test_channel.c319
-rw-r--r--src/test/test_channelpadding.c1130
-rw-r--r--src/test/test_channeltls.c32
-rw-r--r--src/test/test_checkdir.c4
-rw-r--r--src/test/test_circuitbuild.c133
-rw-r--r--src/test/test_circuitlist.c150
-rw-r--r--src/test/test_circuitmux.c8
-rw-r--r--src/test/test_circuituse.c33
-rw-r--r--src/test/test_compat_libevent.c2
-rw-r--r--src/test/test_config.c1542
-rw-r--r--src/test/test_connection.c413
-rw-r--r--src/test/test_connection.h13
-rw-r--r--src/test/test_conscache.c340
-rw-r--r--src/test/test_consdiff.c1185
-rw-r--r--src/test/test_consdiffmgr.c896
-rw-r--r--src/test/test_containers.c75
-rw-r--r--src/test/test_controller.c314
-rw-r--r--src/test/test_controller_events.c2
-rw-r--r--src/test/test_crypto.c224
-rw-r--r--src/test/test_crypto_openssl.c107
-rw-r--r--src/test/test_crypto_slow.c36
-rw-r--r--src/test/test_data.c2
-rw-r--r--src/test/test_dir.c1180
-rw-r--r--src/test/test_dir_common.c4
-rw-r--r--src/test/test_dir_common.h2
-rw-r--r--src/test/test_dir_handle_get.c152
-rw-r--r--src/test/test_dns.c64
-rw-r--r--src/test/test_entryconn.c128
-rw-r--r--src/test/test_entrynodes.c119
-rw-r--r--src/test/test_extorport.c30
-rw-r--r--src/test/test_guardfraction.c50
-rw-r--r--src/test/test_handles.c2
-rw-r--r--src/test/test_helpers.c152
-rw-r--r--src/test/test_helpers.h12
-rw-r--r--src/test/test_hs.c328
-rw-r--r--src/test/test_hs_cache.c265
-rw-r--r--src/test/test_hs_cell.c130
-rw-r--r--src/test/test_hs_client.c599
-rw-r--r--src/test/test_hs_common.c1822
-rw-r--r--src/test/test_hs_config.c487
-rw-r--r--src/test/test_hs_descriptor.c564
-rw-r--r--src/test/test_hs_descriptor.inc224
-rw-r--r--src/test/test_hs_intropoint.c452
-rw-r--r--src/test/test_hs_ntor.c114
-rwxr-xr-xsrc/test/test_hs_ntor.sh11
-rw-r--r--src/test/test_hs_ntor_cl.c255
-rw-r--r--src/test/test_hs_service.c1539
-rw-r--r--src/test/test_introduce.c12
-rwxr-xr-xsrc/test/test_key_expiration.sh129
-rw-r--r--src/test/test_keypin.c105
-rw-r--r--src/test/test_link_handshake.c312
-rw-r--r--src/test/test_logging.c10
-rw-r--r--src/test/test_microdesc.c22
-rw-r--r--src/test/test_nodelist.c106
-rw-r--r--src/test/test_ntor_cl.c2
-rw-r--r--src/test/test_oom.c4
-rw-r--r--src/test/test_oos.c20
-rw-r--r--src/test/test_options.c748
-rw-r--r--src/test/test_policy.c367
-rw-r--r--src/test/test_procmon.c2
-rw-r--r--src/test/test_proto_http.c213
-rw-r--r--src/test/test_proto_misc.c263
-rw-r--r--src/test/test_protover.c24
-rw-r--r--src/test/test_pt.c42
-rw-r--r--src/test/test_pubsub.c2
-rw-r--r--src/test/test_relay.c6
-rw-r--r--src/test/test_relaycell.c2
-rw-r--r--src/test/test_rendcache.c26
-rw-r--r--src/test/test_replay.c26
-rw-r--r--src/test/test_router.c112
-rw-r--r--src/test/test_routerkeys.c203
-rw-r--r--src/test/test_routerlist.c68
-rw-r--r--src/test/test_routerset.c18
-rw-r--r--src/test/test_rust.c31
-rwxr-xr-xsrc/test/test_rust.sh13
-rw-r--r--src/test/test_scheduler.c798
-rw-r--r--src/test/test_shared_random.c407
-rw-r--r--src/test/test_slow.c2
-rw-r--r--src/test/test_socks.c595
-rw-r--r--src/test/test_status.c6
-rw-r--r--src/test/test_storagedir.c375
-rw-r--r--src/test/test_switch_id.c10
-rw-r--r--src/test/test_threads.c14
-rw-r--r--src/test/test_tortls.c98
-rw-r--r--src/test/test_util.c951
-rw-r--r--src/test/test_util_format.c78
-rw-r--r--src/test/test_util_process.c4
-rw-r--r--src/test/test_util_slow.c28
-rw-r--r--src/test/test_workqueue.c14
-rw-r--r--src/test/testing_common.c22
-rw-r--r--src/test/testing_rsakeys.c14
137 files changed, 19226 insertions, 5304 deletions
diff --git a/src/test/Makefile.nmake b/src/test/Makefile.nmake
index 0ba56d7036..605f1a92c3 100644
--- a/src/test/Makefile.nmake
+++ b/src/test/Makefile.nmake
@@ -12,11 +12,12 @@ LIBS = ..\..\..\build-alpha\lib\libevent.lib \
crypt32.lib gdi32.lib user32.lib
TEST_OBJECTS = test.obj test_addr.obj test_channel.obj test_channeltls.obj \
- test_containers.obj \
+ test_consdiff.obj test_containers.obj \
test_controller_events.obj test_crypto.obj test_data.obj test_dir.obj \
test_checkdir.obj test_microdesc.obj test_pt.obj test_util.obj \
test_config.obj test_connection.obj \
test_cell_formats.obj test_relay.obj test_replay.obj \
+ test_channelpadding.obj \
test_scheduler.obj test_introduce.obj test_hs.obj tinytest.obj
tinytest.obj: ..\ext\tinytest.c
diff --git a/src/test/bench.c b/src/test/bench.c
index 99bc686f30..b7b123eee2 100644
--- a/src/test/bench.c
+++ b/src/test/bench.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
extern const char tor_git_revision[];
@@ -28,6 +28,7 @@ const char tor_git_revision[] = "";
#include "crypto_curve25519.h"
#include "onion_ntor.h"
#include "crypto_ed25519.h"
+#include "consdiff.h"
#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID)
static uint64_t nanostart;
@@ -57,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)
@@ -72,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) )
@@ -199,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();
@@ -673,6 +675,28 @@ main(int argc, const char **argv)
or_options_t *options;
tor_threads_init();
+ tor_compress_init();
+
+ if (argc == 4 && !strcmp(argv[1], "diff")) {
+ init_logging(1);
+ const int N = 200;
+ char *f1 = read_file_to_str(argv[2], RFTS_BIN, NULL);
+ char *f2 = read_file_to_str(argv[3], RFTS_BIN, NULL);
+ if (! f1 || ! f2) {
+ perror("X");
+ return 1;
+ }
+ for (i = 0; i < N; ++i) {
+ char *diff = consensus_diff_generate(f1, f2);
+ tor_free(diff);
+ }
+ char *diff = consensus_diff_generate(f1, f2);
+ printf("%s", diff);
+ tor_free(f1);
+ tor_free(f2);
+ tor_free(diff);
+ return 0;
+ }
for (i = 1; i < argc; ++i) {
if (!strcmp(argv[i], "--list")) {
diff --git a/src/test/bt_test.py b/src/test/bt_test.py
index 30591453b9..4cb3326042 100755
--- a/src/test/bt_test.py
+++ b/src/test/bt_test.py
@@ -1,4 +1,4 @@
-# Copyright 2013-2015, The Tor Project, Inc
+# Copyright 2013-2017, The Tor Project, Inc
# See LICENSE for licensing information
"""
diff --git a/src/test/ed25519_exts_ref.py b/src/test/ed25519_exts_ref.py
index d5a3a79910..f84d3002d3 100644
--- a/src/test/ed25519_exts_ref.py
+++ b/src/test/ed25519_exts_ref.py
@@ -1,5 +1,5 @@
#!/usr/bin/python
-# Copyright 2014-2015, The Tor Project, Inc
+# Copyright 2014-2017, The Tor Project, Inc
# See LICENSE for licensing information
"""
@@ -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/fakechans.h b/src/test/fakechans.h
index fa0e37dbe6..c0de430e3d 100644
--- a/src/test/fakechans.h
+++ b/src/test/fakechans.h
@@ -1,4 +1,4 @@
- /* Copyright (c) 2014-2016, The Tor Project, Inc. */
+ /* Copyright (c) 2014-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_FAKECHANS_H
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/dict/http b/src/test/fuzz/dict/http
index 1a7b61e8d4..3b0531579d 100644
--- a/src/test/fuzz/dict/http
+++ b/src/test/fuzz/dict/http
@@ -4,7 +4,7 @@
#
# Extracted from directory_handle_command() in the tor source code
#
-# Copyright (c) 2016, The Tor Project, Inc.
+# Copyright (c) 2016-2017, The Tor Project, Inc.
# See LICENSE for licensing information
#
# Usage:
diff --git a/src/test/fuzz/fuzz_consensus.c b/src/test/fuzz/fuzz_consensus.c
index f5d22f69ae..6610ade7ad 100644
--- a/src/test/fuzz/fuzz_consensus.c
+++ b/src/test/fuzz/fuzz_consensus.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Tor Project, Inc. */
+/* Copyright (c) 2016-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define ROUTERPARSE_PRIVATE
#include "or.h"
diff --git a/src/test/fuzz/fuzz_descriptor.c b/src/test/fuzz/fuzz_descriptor.c
index d19386d77f..1a50beae17 100644
--- a/src/test/fuzz/fuzz_descriptor.c
+++ b/src/test/fuzz/fuzz_descriptor.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Tor Project, Inc. */
+/* Copyright (c) 2016-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define ROUTERPARSE_PRIVATE
#include "or.h"
diff --git a/src/test/fuzz/fuzz_diff.c b/src/test/fuzz/fuzz_diff.c
new file mode 100644
index 0000000000..642380b512
--- /dev/null
+++ b/src/test/fuzz/fuzz_diff.c
@@ -0,0 +1,69 @@
+/* Copyright (c) 2016, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#define CONSDIFF_PRIVATE
+
+#include "orconfig.h"
+#include "or.h"
+#include "consdiff.h"
+
+#include "fuzzing.h"
+
+static int
+mock_consensus_compute_digest_(const char *c, consensus_digest_t *d)
+{
+ (void)c;
+ memset(d->sha3_256, 3, sizeof(d->sha3_256));
+ return 0;
+}
+
+int
+fuzz_init(void)
+{
+ MOCK(consensus_compute_digest, mock_consensus_compute_digest_);
+ MOCK(consensus_compute_digest_as_signed, mock_consensus_compute_digest_);
+ return 0;
+}
+
+int
+fuzz_cleanup(void)
+{
+ UNMOCK(consensus_compute_digest);
+ UNMOCK(consensus_compute_digest_as_signed);
+ return 0;
+}
+
+int
+fuzz_main(const uint8_t *stdin_buf, size_t data_size)
+{
+#define SEP "=====\n"
+#define SEPLEN strlen(SEP)
+ const uint8_t *separator = tor_memmem(stdin_buf, data_size, SEP, SEPLEN);
+ if (! separator)
+ return 0;
+ size_t c1_len = separator - stdin_buf;
+ char *c1 = tor_memdup_nulterm(stdin_buf, c1_len);
+ size_t c2_len = data_size - c1_len - SEPLEN;
+ char *c2 = tor_memdup_nulterm(separator + SEPLEN, c2_len);
+
+ char *c3 = consensus_diff_generate(c1, c2);
+
+ if (c3) {
+ char *c4 = consensus_diff_apply(c1, c3);
+ tor_assert(c4);
+ if (strcmp(c2, c4)) {
+ printf("%s\n", escaped(c1));
+ printf("%s\n", escaped(c2));
+ printf("%s\n", escaped(c3));
+ printf("%s\n", escaped(c4));
+ }
+ tor_assert(! strcmp(c2, c4));
+ tor_free(c3);
+ tor_free(c4);
+ }
+ tor_free(c1);
+ tor_free(c2);
+
+ return 0;
+}
+
diff --git a/src/test/fuzz/fuzz_diff_apply.c b/src/test/fuzz/fuzz_diff_apply.c
new file mode 100644
index 0000000000..8d7bf751bf
--- /dev/null
+++ b/src/test/fuzz/fuzz_diff_apply.c
@@ -0,0 +1,65 @@
+/* Copyright (c) 2016, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#define CONSDIFF_PRIVATE
+
+#include "orconfig.h"
+#include "or.h"
+#include "consdiff.h"
+
+#include "fuzzing.h"
+
+static int
+mock_consensus_compute_digest_(const char *c, consensus_digest_t *d)
+{
+ (void)c;
+ memset(d->sha3_256, 3, sizeof(d->sha3_256));
+ return 0;
+}
+
+static int
+mock_consensus_digest_eq_(const uint8_t *a, const uint8_t *b)
+{
+ (void)a;
+ (void)b;
+ return 1;
+}
+
+int
+fuzz_init(void)
+{
+ MOCK(consensus_compute_digest, mock_consensus_compute_digest_);
+ MOCK(consensus_digest_eq, mock_consensus_digest_eq_);
+ return 0;
+}
+
+int
+fuzz_cleanup(void)
+{
+ UNMOCK(consensus_compute_digest);
+ UNMOCK(consensus_digest_eq);
+ return 0;
+}
+
+int
+fuzz_main(const uint8_t *stdin_buf, size_t data_size)
+{
+#define SEP "=====\n"
+#define SEPLEN strlen(SEP)
+ const uint8_t *separator = tor_memmem(stdin_buf, data_size, SEP, SEPLEN);
+ if (! separator)
+ return 0;
+ size_t c1_len = separator - stdin_buf;
+ char *c1 = tor_memdup_nulterm(stdin_buf, c1_len);
+ size_t c2_len = data_size - c1_len - SEPLEN;
+ char *c2 = tor_memdup_nulterm(separator + SEPLEN, c2_len);
+
+ char *c3 = consensus_diff_apply(c1, c2);
+
+ tor_free(c1);
+ tor_free(c2);
+ tor_free(c3);
+
+ return 0;
+}
+
diff --git a/src/test/fuzz/fuzz_extrainfo.c b/src/test/fuzz/fuzz_extrainfo.c
index 6251e606d0..2a3de7ecf7 100644
--- a/src/test/fuzz/fuzz_extrainfo.c
+++ b/src/test/fuzz/fuzz_extrainfo.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Tor Project, Inc. */
+/* Copyright (c) 2016-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define ROUTERPARSE_PRIVATE
#include "or.h"
diff --git a/src/test/fuzz/fuzz_hsdescv2.c b/src/test/fuzz/fuzz_hsdescv2.c
index 53b7cbe2f7..19db265716 100644
--- a/src/test/fuzz/fuzz_hsdescv2.c
+++ b/src/test/fuzz/fuzz_hsdescv2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Tor Project, Inc. */
+/* Copyright (c) 2016-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define ROUTERPARSE_PRIVATE
#include "or.h"
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.c b/src/test/fuzz/fuzz_http.c
index 01c3815f18..2ffeb60244 100644
--- a/src/test/fuzz/fuzz_http.c
+++ b/src/test/fuzz/fuzz_http.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Tor Project, Inc. */
+/* Copyright (c) 2016-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -18,10 +18,10 @@
static void
mock_connection_write_to_buf_impl_(const char *string, size_t len,
- connection_t *conn, int zlib)
+ connection_t *conn, int compressed)
{
log_debug(LD_GENERAL, "%sResponse:\n%u\nConnection: %p\n%s\n",
- zlib ? "Compressed " : "", (unsigned)len, conn, string);
+ compressed ? "Compressed " : "", (unsigned)len, conn, string);
}
static int
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/fuzz_iptsv2.c b/src/test/fuzz/fuzz_iptsv2.c
index 341d4880bd..4abde0c16d 100644
--- a/src/test/fuzz/fuzz_iptsv2.c
+++ b/src/test/fuzz/fuzz_iptsv2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Tor Project, Inc. */
+/* Copyright (c) 2016-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define ROUTERPARSE_PRIVATE
#include "or.h"
diff --git a/src/test/fuzz/fuzz_microdesc.c b/src/test/fuzz/fuzz_microdesc.c
index bb89546191..396115026e 100644
--- a/src/test/fuzz/fuzz_microdesc.c
+++ b/src/test/fuzz/fuzz_microdesc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Tor Project, Inc. */
+/* Copyright (c) 2016-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define ROUTERPARSE_PRIVATE
#include "or.h"
diff --git a/src/test/fuzz/fuzz_vrs.c b/src/test/fuzz/fuzz_vrs.c
index 9301a9bcc8..baf0610a0b 100644
--- a/src/test/fuzz/fuzz_vrs.c
+++ b/src/test/fuzz/fuzz_vrs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Tor Project, Inc. */
+/* Copyright (c) 2016-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define ROUTERPARSE_PRIVATE
#define NETWORKSTATUS_PRIVATE
diff --git a/src/test/fuzz/fuzzing.h b/src/test/fuzz/fuzzing.h
index 4295743458..aecdbb4e52 100644
--- a/src/test/fuzz/fuzzing.h
+++ b/src/test/fuzz/fuzzing.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Tor Project, Inc. */
+/* Copyright (c) 2016-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef FUZZING_H
#define FUZZING_H
diff --git a/src/test/fuzz/fuzzing_common.c b/src/test/fuzz/fuzzing_common.c
index e4920d3ee7..1e98eb6c85 100644
--- a/src/test/fuzz/fuzzing_common.c
+++ b/src/test/fuzz/fuzzing_common.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Tor Project, Inc. */
+/* Copyright (c) 2016-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CRYPTO_ED25519_PRIVATE
#include "orconfig.h"
@@ -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
@@ -96,6 +97,7 @@ static void
global_init(void)
{
tor_threads_init();
+ tor_compress_init();
{
struct sipkey sipkey = { 1337, 7331 };
siphash_set_global_key(&sipkey);
@@ -106,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 806710879b..cd16dc05be 100644
--- a/src/test/fuzz/include.am
+++ b/src/test/fuzz/include.am
@@ -1,4 +1,5 @@
-
+# This file was generated by fuzzing_include_am.py; do not hand-edit unless
+# you enjoy having your changes erased.
FUZZING_CPPFLAGS = \
$(src_test_AM_CPPFLAGS) $(TEST_CPPFLAGS)
FUZZING_CFLAGS = \
@@ -14,10 +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_SYSTEMD_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@
oss-fuzz-prereqs: \
src/or/libtor-testing.a \
@@ -32,6 +36,16 @@ oss-fuzz-prereqs: \
noinst_HEADERS += \
src/test/fuzz/fuzzing.h
+LIBFUZZER = -lFuzzer
+LIBFUZZER_CPPFLAGS = $(FUZZING_CPPFLAGS) -DLLVM_FUZZ
+LIBFUZZER_CFLAGS = $(FUZZING_CFLAGS)
+LIBFUZZER_LDFLAG = $(FUZZING_LDFLAG)
+LIBFUZZER_LIBS = $(FUZZING_LIBS) $(LIBFUZZER) -lstdc++
+
+LIBOSS_FUZZ_CPPFLAGS = $(FUZZING_CPPFLAGS) -DLLVM_FUZZ
+LIBOSS_FUZZ_CFLAGS = $(FUZZING_CFLAGS)
+
+# ===== AFL fuzzers
src_test_fuzz_fuzz_consensus_SOURCES = \
src/test/fuzz/fuzzing_common.c \
src/test/fuzz/fuzz_consensus.c
@@ -48,13 +62,29 @@ src_test_fuzz_fuzz_descriptor_CFLAGS = $(FUZZING_CFLAGS)
src_test_fuzz_fuzz_descriptor_LDFLAGS = $(FUZZING_LDFLAG)
src_test_fuzz_fuzz_descriptor_LDADD = $(FUZZING_LIBS)
-src_test_fuzz_fuzz_http_SOURCES = \
+src_test_fuzz_fuzz_diff_SOURCES = \
src/test/fuzz/fuzzing_common.c \
- src/test/fuzz/fuzz_http.c
-src_test_fuzz_fuzz_http_CPPFLAGS = $(FUZZING_CPPFLAGS)
-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_diff.c
+src_test_fuzz_fuzz_diff_CPPFLAGS = $(FUZZING_CPPFLAGS)
+src_test_fuzz_fuzz_diff_CFLAGS = $(FUZZING_CFLAGS)
+src_test_fuzz_fuzz_diff_LDFLAGS = $(FUZZING_LDFLAG)
+src_test_fuzz_fuzz_diff_LDADD = $(FUZZING_LIBS)
+
+src_test_fuzz_fuzz_diff_apply_SOURCES = \
+ src/test/fuzz/fuzzing_common.c \
+ src/test/fuzz/fuzz_diff_apply.c
+src_test_fuzz_fuzz_diff_apply_CPPFLAGS = $(FUZZING_CPPFLAGS)
+src_test_fuzz_fuzz_diff_apply_CFLAGS = $(FUZZING_CFLAGS)
+src_test_fuzz_fuzz_diff_apply_LDFLAGS = $(FUZZING_LDFLAG)
+src_test_fuzz_fuzz_diff_apply_LDADD = $(FUZZING_LIBS)
+
+src_test_fuzz_fuzz_extrainfo_SOURCES = \
+ src/test/fuzz/fuzzing_common.c \
+ src/test/fuzz/fuzz_extrainfo.c
+src_test_fuzz_fuzz_extrainfo_CPPFLAGS = $(FUZZING_CPPFLAGS)
+src_test_fuzz_fuzz_extrainfo_CFLAGS = $(FUZZING_CFLAGS)
+src_test_fuzz_fuzz_extrainfo_LDFLAGS = $(FUZZING_LDFLAG)
+src_test_fuzz_fuzz_extrainfo_LDADD = $(FUZZING_LIBS)
src_test_fuzz_fuzz_hsdescv2_SOURCES = \
src/test/fuzz/fuzzing_common.c \
@@ -64,6 +94,30 @@ 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
+src_test_fuzz_fuzz_http_CPPFLAGS = $(FUZZING_CPPFLAGS)
+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
@@ -72,14 +126,6 @@ src_test_fuzz_fuzz_iptsv2_CFLAGS = $(FUZZING_CFLAGS)
src_test_fuzz_fuzz_iptsv2_LDFLAGS = $(FUZZING_LDFLAG)
src_test_fuzz_fuzz_iptsv2_LDADD = $(FUZZING_LIBS)
-src_test_fuzz_fuzz_extrainfo_SOURCES = \
- src/test/fuzz/fuzzing_common.c \
- src/test/fuzz/fuzz_extrainfo.c
-src_test_fuzz_fuzz_extrainfo_CPPFLAGS = $(FUZZING_CPPFLAGS)
-src_test_fuzz_fuzz_extrainfo_CFLAGS = $(FUZZING_CFLAGS)
-src_test_fuzz_fuzz_extrainfo_LDFLAGS = $(FUZZING_LDFLAG)
-src_test_fuzz_fuzz_extrainfo_LDADD = $(FUZZING_LIBS)
-
src_test_fuzz_fuzz_microdesc_SOURCES = \
src/test/fuzz/fuzzing_common.c \
src/test/fuzz/fuzz_microdesc.c
@@ -99,19 +145,18 @@ src_test_fuzz_fuzz_vrs_LDADD = $(FUZZING_LIBS)
FUZZERS = \
src/test/fuzz/fuzz-consensus \
src/test/fuzz/fuzz-descriptor \
+ src/test/fuzz/fuzz-diff \
+ src/test/fuzz/fuzz-diff-apply \
src/test/fuzz/fuzz-extrainfo \
- src/test/fuzz/fuzz-http \
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
-
-LIBFUZZER = /home/nickm/build/libfuzz/libFuzzer.a
-LIBFUZZER_CPPFLAGS = $(FUZZING_CPPFLAGS) -DLLVM_FUZZ
-LIBFUZZER_CFLAGS = $(FUZZING_CFLAGS)
-LIBFUZZER_LDFLAG = $(FUZZING_LDFLAG)
-LIBFUZZER_LIBS = $(FUZZING_LIBS) $(LIBFUZZER) -lstdc++
+# ===== libfuzzer
if LIBFUZZER_ENABLED
src_test_fuzz_lf_fuzz_consensus_SOURCES = \
@@ -128,6 +173,20 @@ src_test_fuzz_lf_fuzz_descriptor_CFLAGS = $(LIBFUZZER_CFLAGS)
src_test_fuzz_lf_fuzz_descriptor_LDFLAGS = $(LIBFUZZER_LDFLAG)
src_test_fuzz_lf_fuzz_descriptor_LDADD = $(LIBFUZZER_LIBS)
+src_test_fuzz_lf_fuzz_diff_SOURCES = \
+ $(src_test_fuzz_fuzz_diff_SOURCES)
+src_test_fuzz_lf_fuzz_diff_CPPFLAGS = $(LIBFUZZER_CPPFLAGS)
+src_test_fuzz_lf_fuzz_diff_CFLAGS = $(LIBFUZZER_CFLAGS)
+src_test_fuzz_lf_fuzz_diff_LDFLAGS = $(LIBFUZZER_LDFLAG)
+src_test_fuzz_lf_fuzz_diff_LDADD = $(LIBFUZZER_LIBS)
+
+src_test_fuzz_lf_fuzz_diff_apply_SOURCES = \
+ $(src_test_fuzz_fuzz_diff_apply_SOURCES)
+src_test_fuzz_lf_fuzz_diff_apply_CPPFLAGS = $(LIBFUZZER_CPPFLAGS)
+src_test_fuzz_lf_fuzz_diff_apply_CFLAGS = $(LIBFUZZER_CFLAGS)
+src_test_fuzz_lf_fuzz_diff_apply_LDFLAGS = $(LIBFUZZER_LDFLAG)
+src_test_fuzz_lf_fuzz_diff_apply_LDADD = $(LIBFUZZER_LIBS)
+
src_test_fuzz_lf_fuzz_extrainfo_SOURCES = \
$(src_test_fuzz_fuzz_extrainfo_SOURCES)
src_test_fuzz_lf_fuzz_extrainfo_CPPFLAGS = $(LIBFUZZER_CPPFLAGS)
@@ -135,6 +194,20 @@ src_test_fuzz_lf_fuzz_extrainfo_CFLAGS = $(LIBFUZZER_CFLAGS)
src_test_fuzz_lf_fuzz_extrainfo_LDFLAGS = $(LIBFUZZER_LDFLAG)
src_test_fuzz_lf_fuzz_extrainfo_LDADD = $(LIBFUZZER_LIBS)
+src_test_fuzz_lf_fuzz_hsdescv2_SOURCES = \
+ $(src_test_fuzz_fuzz_hsdescv2_SOURCES)
+src_test_fuzz_lf_fuzz_hsdescv2_CPPFLAGS = $(LIBFUZZER_CPPFLAGS)
+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)
@@ -142,12 +215,12 @@ 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_hsdescv2_SOURCES = \
- $(src_test_fuzz_fuzz_hsdescv2_SOURCES)
-src_test_fuzz_lf_fuzz_hsdescv2_CPPFLAGS = $(LIBFUZZER_CPPFLAGS)
-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_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)
@@ -173,9 +246,13 @@ src_test_fuzz_lf_fuzz_vrs_LDADD = $(LIBFUZZER_LIBS)
LIBFUZZER_FUZZERS = \
src/test/fuzz/lf-fuzz-consensus \
src/test/fuzz/lf-fuzz-descriptor \
+ src/test/fuzz/lf-fuzz-diff \
+ src/test/fuzz/lf-fuzz-diff-apply \
src/test/fuzz/lf-fuzz-extrainfo \
- src/test/fuzz/lf-fuzz-http \
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
@@ -184,10 +261,9 @@ else
LIBFUZZER_FUZZERS =
endif
-if OSS_FUZZ_ENABLED
-LIBOSS_FUZZ_CPPFLAGS = $(FUZZING_CPPFLAGS) -DLLVM_FUZZ
-LIBOSS_FUZZ_CFLAGS = $(FUZZING_CFLAGS)
+# ===== oss-fuzz
+if OSS_FUZZ_ENABLED
src_test_fuzz_liboss_fuzz_consensus_a_SOURCES = \
$(src_test_fuzz_fuzz_consensus_SOURCES)
src_test_fuzz_liboss_fuzz_consensus_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS)
@@ -198,20 +274,40 @@ src_test_fuzz_liboss_fuzz_descriptor_a_SOURCES = \
src_test_fuzz_liboss_fuzz_descriptor_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS)
src_test_fuzz_liboss_fuzz_descriptor_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS)
+src_test_fuzz_liboss_fuzz_diff_a_SOURCES = \
+ $(src_test_fuzz_fuzz_diff_SOURCES)
+src_test_fuzz_liboss_fuzz_diff_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS)
+src_test_fuzz_liboss_fuzz_diff_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS)
+
+src_test_fuzz_liboss_fuzz_diff_apply_a_SOURCES = \
+ $(src_test_fuzz_fuzz_diff_apply_SOURCES)
+src_test_fuzz_liboss_fuzz_diff_apply_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS)
+src_test_fuzz_liboss_fuzz_diff_apply_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS)
+
src_test_fuzz_liboss_fuzz_extrainfo_a_SOURCES = \
$(src_test_fuzz_fuzz_extrainfo_SOURCES)
src_test_fuzz_liboss_fuzz_extrainfo_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS)
src_test_fuzz_liboss_fuzz_extrainfo_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS)
+src_test_fuzz_liboss_fuzz_hsdescv2_a_SOURCES = \
+ $(src_test_fuzz_fuzz_hsdescv2_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_hsdescv2_a_SOURCES = \
- $(src_test_fuzz_fuzz_hsdescv2_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_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)
@@ -231,12 +327,17 @@ src_test_fuzz_liboss_fuzz_vrs_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS)
OSS_FUZZ_FUZZERS = \
src/test/fuzz/liboss-fuzz-consensus.a \
src/test/fuzz/liboss-fuzz-descriptor.a \
+ src/test/fuzz/liboss-fuzz-diff.a \
+ src/test/fuzz/liboss-fuzz-diff-apply.a \
src/test/fuzz/liboss-fuzz-extrainfo.a \
- src/test/fuzz/liboss-fuzz-http.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
+
else
OSS_FUZZ_FUZZERS =
endif
diff --git a/src/test/fuzz_static_testcases.sh b/src/test/fuzz_static_testcases.sh
index bfe1677573..3cb45ad5e6 100755
--- a/src/test/fuzz_static_testcases.sh
+++ b/src/test/fuzz_static_testcases.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-# Copyright (c) 2016, The Tor Project, Inc.
+# Copyright (c) 2016-2017, The Tor Project, Inc.
# See LICENSE for licensing information
set -e
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
new file mode 100644
index 0000000000..2ed9324e1f
--- /dev/null
+++ b/src/test/hs_ntor_ref.py
@@ -0,0 +1,425 @@
+#!/usr/bin/python
+# Copyright 2017, The Tor Project, Inc
+# See LICENSE for licensing information
+
+"""
+hs_ntor_ref.py
+
+This module is a reference implementation of the modified ntor protocol
+proposed for Tor hidden services in proposal 224 (Next Generation Hidden
+Services) in section [NTOR-WITH-EXTRA-DATA].
+
+The modified ntor protocol is a single-round protocol, with three steps in total:
+
+ 1: Client generates keys and sends them to service via INTRODUCE cell
+
+ 2: Service computes key material based on client's keys, and sends its own
+ keys to client via RENDEZVOUS cell
+
+ 3: Client computes key material as well.
+
+It's meant to be used to validate Tor's HS ntor implementation by conducting
+various integration tests. Specifically it conducts the following three tests:
+
+- Tests our Python implementation by running the whole protocol in Python and
+ making sure that results are consistent.
+
+- Tests little-t-tor ntor implementation. We use this Python code to instrument
+ little-t-tor and carry out the handshake by using little-t-tor code. The
+ small C wrapper at src/test/test-hs-ntor-cl is used for this Python module to
+ interface with little-t-tor.
+
+- Cross-tests Python and little-t-tor implementation by running half of the
+ protocol in Python code and the other in little-t-tor. This is actually two
+ tests so that all parts of the protocol are run both by little-t-tor and
+ Python.
+
+It requires the curve25519 python module from the curve25519-donna package.
+
+The whole logic and concept for this test suite was taken from ntor_ref.py.
+
+ *** DO NOT USE THIS IN PRODUCTION. ***
+"""
+
+import struct
+import os, sys
+import binascii
+import subprocess
+
+try:
+ import curve25519
+ curve25519mod = curve25519.keys
+except ImportError:
+ curve25519 = None
+ import slownacl_curve25519
+ curve25519mod = slownacl_curve25519
+
+import hashlib
+try:
+ import sha3
+except ImportError:
+ # In python 3.6, the sha3 functions are in hashlib whether we
+ # import sha3 or not.
+ sha3 = None
+
+try:
+ # Pull the sha3 functions in.
+ from hashlib import sha3_256, shake_256
+ shake_squeeze = shake_256.digest
+except ImportError:
+ if hasattr(sha3, "SHA3256"):
+ # If this happens, then we have the old "sha3" module which
+ # hashlib and pysha3 superseded.
+ sha3_256 = sha3.SHA3256
+ shake_256 = sha3.SHAKE256
+ shake_squeeze = shake_256.squeeze
+ else:
+ # error code 77 tells automake to skip this test
+ sys.exit(77)
+
+# Import Nick's ntor reference implementation in Python
+# We are gonna use a few of its utilities.
+from ntor_ref import hash_nil
+from ntor_ref import PrivateKey
+
+# String constants used in this protocol
+PROTOID = b"tor-hs-ntor-curve25519-sha3-256-1"
+T_HSENC = PROTOID + b":hs_key_extract"
+T_HSVERIFY = PROTOID + b":hs_verify"
+T_HSMAC = PROTOID + b":hs_mac"
+M_HSEXPAND = PROTOID + b":hs_key_expand"
+
+INTRO_SECRET_LEN = 161
+REND_SECRET_LEN = 225
+AUTH_INPUT_LEN = 199
+
+# Implements MAC(k,m) = H(htonll(len(k)) | k | m)
+def mac(k,m):
+ def htonll(num):
+ return struct.pack('!q', num)
+
+ s = sha3_256()
+ s.update(htonll(len(k)))
+ s.update(k)
+ s.update(m)
+ return s.digest()
+
+######################################################################
+
+# Functions that implement the modified HS ntor protocol
+
+"""As client compute key material for INTRODUCE cell as follows:
+
+ intro_secret_hs_input = EXP(B,x) | AUTH_KEY | X | B | PROTOID
+ info = m_hsexpand | subcredential
+ hs_keys = KDF(intro_secret_hs_input | t_hsenc | info, S_KEY_LEN+MAC_LEN)
+ ENC_KEY = hs_keys[0:S_KEY_LEN]
+ MAC_KEY = hs_keys[S_KEY_LEN:S_KEY_LEN+MAC_KEY_LEN]
+"""
+def intro2_ntor_client(intro_auth_pubkey_str, intro_enc_pubkey,
+ client_ephemeral_enc_pubkey, client_ephemeral_enc_privkey, subcredential):
+
+ dh_result = client_ephemeral_enc_privkey.get_shared_key(intro_enc_pubkey, hash_nil)
+ secret = dh_result + intro_auth_pubkey_str + client_ephemeral_enc_pubkey.serialize() + intro_enc_pubkey.serialize() + PROTOID
+ assert(len(secret) == INTRO_SECRET_LEN)
+ info = M_HSEXPAND + subcredential
+
+ kdf = shake_256()
+ kdf.update(secret + T_HSENC + info)
+ key_material = shake_squeeze(kdf, 64*8)
+
+ enc_key = key_material[0:32]
+ mac_key = key_material[32:64]
+
+ return enc_key, mac_key
+
+"""Wrapper over intro2_ntor_client()"""
+def client_part1(intro_auth_pubkey_str, intro_enc_pubkey,
+ client_ephemeral_enc_pubkey, client_ephemeral_enc_privkey, subcredential):
+ enc_key, mac_key = intro2_ntor_client(intro_auth_pubkey_str, intro_enc_pubkey, client_ephemeral_enc_pubkey, client_ephemeral_enc_privkey, subcredential)
+ assert(enc_key)
+ assert(mac_key)
+
+ return enc_key, mac_key
+
+"""As service compute key material for INTRODUCE cell as follows:
+
+ intro_secret_hs_input = EXP(X,b) | AUTH_KEY | X | B | PROTOID
+ info = m_hsexpand | subcredential
+ hs_keys = KDF(intro_secret_hs_input | t_hsenc | info, S_KEY_LEN+MAC_LEN)
+ HS_DEC_KEY = hs_keys[0:S_KEY_LEN]
+ HS_MAC_KEY = hs_keys[S_KEY_LEN:S_KEY_LEN+MAC_KEY_LEN]
+"""
+def intro2_ntor_service(intro_auth_pubkey_str, client_enc_pubkey, service_enc_privkey, service_enc_pubkey, subcredential):
+ dh_result = service_enc_privkey.get_shared_key(client_enc_pubkey, hash_nil)
+ secret = dh_result + intro_auth_pubkey_str + client_enc_pubkey.serialize() + service_enc_pubkey.serialize() + PROTOID
+ assert(len(secret) == INTRO_SECRET_LEN)
+ info = M_HSEXPAND + subcredential
+
+ kdf = shake_256()
+ kdf.update(secret + T_HSENC + info)
+ key_material = shake_squeeze(kdf, 64*8)
+
+ enc_key = key_material[0:32]
+ mac_key = key_material[32:64]
+
+ return enc_key, mac_key
+
+"""As service compute key material for INTRODUCE and REDNEZVOUS cells.
+
+ Use intro2_ntor_service() to calculate the INTRODUCE key material, and use
+ the following computations to do the RENDEZVOUS ones:
+
+ rend_secret_hs_input = EXP(X,y) | EXP(X,b) | AUTH_KEY | B | X | Y | PROTOID
+ NTOR_KEY_SEED = MAC(rend_secret_hs_input, t_hsenc)
+ verify = MAC(rend_secret_hs_input, t_hsverify)
+ auth_input = verify | AUTH_KEY | B | Y | X | PROTOID | "Server"
+ AUTH_INPUT_MAC = MAC(auth_input, t_hsmac)
+"""
+def service_part1(intro_auth_pubkey_str, client_enc_pubkey, intro_enc_privkey, intro_enc_pubkey, subcredential):
+ intro_enc_key, intro_mac_key = intro2_ntor_service(intro_auth_pubkey_str, client_enc_pubkey, intro_enc_privkey, intro_enc_pubkey, subcredential)
+ assert(intro_enc_key)
+ assert(intro_mac_key)
+
+ service_ephemeral_privkey = PrivateKey()
+ service_ephemeral_pubkey = service_ephemeral_privkey.get_public()
+
+ dh_result1 = service_ephemeral_privkey.get_shared_key(client_enc_pubkey, hash_nil)
+ dh_result2 = intro_enc_privkey.get_shared_key(client_enc_pubkey, hash_nil)
+ rend_secret_hs_input = dh_result1 + dh_result2 + intro_auth_pubkey_str + intro_enc_pubkey.serialize() + client_enc_pubkey.serialize() + service_ephemeral_pubkey.serialize() + PROTOID
+ assert(len(rend_secret_hs_input) == REND_SECRET_LEN)
+
+ ntor_key_seed = mac(rend_secret_hs_input, T_HSENC)
+ verify = mac(rend_secret_hs_input, T_HSVERIFY)
+ auth_input = verify + intro_auth_pubkey_str + intro_enc_pubkey.serialize() + service_ephemeral_pubkey.serialize() + client_enc_pubkey.serialize() + PROTOID + b"Server"
+ assert(len(auth_input) == AUTH_INPUT_LEN)
+ auth_input_mac = mac(auth_input, T_HSMAC)
+
+ assert(ntor_key_seed)
+ assert(auth_input_mac)
+ assert(service_ephemeral_pubkey)
+
+ return intro_enc_key, intro_mac_key, ntor_key_seed, auth_input_mac, service_ephemeral_pubkey
+
+"""As client compute key material for rendezvous cells as follows:
+
+ rend_secret_hs_input = EXP(Y,x) | EXP(B,x) | AUTH_KEY | B | X | Y | PROTOID
+ NTOR_KEY_SEED = MAC(ntor_secret_input, t_hsenc)
+ verify = MAC(ntor_secret_input, t_hsverify)
+ auth_input = verify | AUTH_KEY | B | Y | X | PROTOID | "Server"
+ AUTH_INPUT_MAC = MAC(auth_input, t_hsmac)
+"""
+def client_part2(intro_auth_pubkey_str, client_ephemeral_enc_pubkey, client_ephemeral_enc_privkey,
+ intro_enc_pubkey, service_ephemeral_rend_pubkey):
+ dh_result1 = client_ephemeral_enc_privkey.get_shared_key(service_ephemeral_rend_pubkey, hash_nil)
+ dh_result2 = client_ephemeral_enc_privkey.get_shared_key(intro_enc_pubkey, hash_nil)
+ rend_secret_hs_input = dh_result1 + dh_result2 + intro_auth_pubkey_str + intro_enc_pubkey.serialize() + client_ephemeral_enc_pubkey.serialize() + service_ephemeral_rend_pubkey.serialize() + PROTOID
+ assert(len(rend_secret_hs_input) == REND_SECRET_LEN)
+
+ ntor_key_seed = mac(rend_secret_hs_input, T_HSENC)
+ verify = mac(rend_secret_hs_input, T_HSVERIFY)
+ auth_input = verify + intro_auth_pubkey_str + intro_enc_pubkey.serialize() + service_ephemeral_rend_pubkey.serialize() + client_ephemeral_enc_pubkey.serialize() + PROTOID + b"Server"
+ assert(len(auth_input) == AUTH_INPUT_LEN)
+ auth_input_mac = mac(auth_input, T_HSMAC)
+
+ assert(ntor_key_seed)
+ assert(auth_input_mac)
+
+ return ntor_key_seed, auth_input_mac
+
+#################################################################################
+
+"""
+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)
+dehex=lambda s: binascii.a2b_hex(s.strip())
+
+def tor_client1(intro_auth_pubkey_str, intro_enc_pubkey,
+ client_ephemeral_enc_privkey, subcredential):
+ p = subprocess.Popen([PROG, "client1",
+ enhex(intro_auth_pubkey_str),
+ enhex(intro_enc_pubkey.serialize()),
+ enhex(client_ephemeral_enc_privkey.serialize()),
+ enhex(subcredential)],
+ stdout=subprocess.PIPE)
+ return map(dehex, p.stdout.readlines())
+
+def tor_server1(intro_auth_pubkey_str, intro_enc_privkey,
+ client_ephemeral_enc_pubkey, subcredential):
+ p = subprocess.Popen([PROG, "server1",
+ enhex(intro_auth_pubkey_str),
+ enhex(intro_enc_privkey.serialize()),
+ enhex(client_ephemeral_enc_pubkey.serialize()),
+ enhex(subcredential)],
+ stdout=subprocess.PIPE)
+ return map(dehex, p.stdout.readlines())
+
+def tor_client2(intro_auth_pubkey_str, client_ephemeral_enc_privkey,
+ intro_enc_pubkey, service_ephemeral_rend_pubkey, subcredential):
+ p = subprocess.Popen([PROG, "client2",
+ enhex(intro_auth_pubkey_str),
+ enhex(client_ephemeral_enc_privkey.serialize()),
+ enhex(intro_enc_pubkey.serialize()),
+ enhex(service_ephemeral_rend_pubkey.serialize()),
+ enhex(subcredential)],
+ stdout=subprocess.PIPE)
+ return map(dehex, p.stdout.readlines())
+
+##################################################################################
+
+# Perform a pure python ntor test
+def do_pure_python_ntor_test():
+ # Initialize all needed key material
+ client_ephemeral_enc_privkey = PrivateKey()
+ client_ephemeral_enc_pubkey = client_ephemeral_enc_privkey.get_public()
+ intro_enc_privkey = PrivateKey()
+ intro_enc_pubkey = intro_enc_privkey.get_public()
+ intro_auth_pubkey_str = os.urandom(32)
+ subcredential = os.urandom(32)
+
+ client_enc_key, client_mac_key = client_part1(intro_auth_pubkey_str, intro_enc_pubkey, client_ephemeral_enc_pubkey, client_ephemeral_enc_privkey, subcredential)
+
+ service_enc_key, service_mac_key, service_ntor_key_seed, service_auth_input_mac, service_ephemeral_pubkey = service_part1(intro_auth_pubkey_str, client_ephemeral_enc_pubkey, intro_enc_privkey, intro_enc_pubkey, subcredential)
+
+ assert(client_enc_key == service_enc_key)
+ assert(client_mac_key == service_mac_key)
+
+ client_ntor_key_seed, client_auth_input_mac = client_part2(intro_auth_pubkey_str, client_ephemeral_enc_pubkey, client_ephemeral_enc_privkey,
+ intro_enc_pubkey, service_ephemeral_pubkey)
+
+ assert(client_ntor_key_seed == service_ntor_key_seed)
+ assert(client_auth_input_mac == service_auth_input_mac)
+
+ print("DONE: python dance [%s]" % repr(client_auth_input_mac))
+
+# Perform a pure little-t-tor integration test.
+def do_little_t_tor_ntor_test():
+ # Initialize all needed key material
+ subcredential = os.urandom(32)
+ client_ephemeral_enc_privkey = PrivateKey()
+ client_ephemeral_enc_pubkey = client_ephemeral_enc_privkey.get_public()
+ intro_enc_privkey = PrivateKey()
+ intro_enc_pubkey = intro_enc_privkey.get_public() # service-side enc key
+ intro_auth_pubkey_str = os.urandom(32)
+
+ client_enc_key, client_mac_key = tor_client1(intro_auth_pubkey_str, intro_enc_pubkey,
+ client_ephemeral_enc_privkey, subcredential)
+ assert(client_enc_key)
+ assert(client_mac_key)
+
+ service_enc_key, service_mac_key, service_ntor_auth_mac, service_ntor_key_seed, service_eph_pubkey = tor_server1(intro_auth_pubkey_str,
+ intro_enc_privkey,
+ client_ephemeral_enc_pubkey,
+ subcredential)
+ assert(service_enc_key)
+ assert(service_mac_key)
+ assert(service_ntor_auth_mac)
+ assert(service_ntor_key_seed)
+
+ assert(client_enc_key == service_enc_key)
+ assert(client_mac_key == service_mac_key)
+
+ # Turn from bytes to key
+ service_eph_pubkey = curve25519mod.Public(service_eph_pubkey)
+
+ client_ntor_auth_mac, client_ntor_key_seed = tor_client2(intro_auth_pubkey_str, client_ephemeral_enc_privkey,
+ intro_enc_pubkey, service_eph_pubkey, subcredential)
+ assert(client_ntor_auth_mac)
+ assert(client_ntor_key_seed)
+
+ assert(client_ntor_key_seed == service_ntor_key_seed)
+ assert(client_ntor_auth_mac == service_ntor_auth_mac)
+
+ print("DONE: tor dance [%s]" % repr(client_ntor_auth_mac))
+
+"""
+Do mixed test as follows:
+ 1. C -> S (python mode)
+ 2. C <- S (tor mode)
+ 3. Client computes keys (python mode)
+"""
+def do_first_mixed_test():
+ subcredential = os.urandom(32)
+
+ client_ephemeral_enc_privkey = PrivateKey()
+ client_ephemeral_enc_pubkey = client_ephemeral_enc_privkey.get_public()
+ intro_enc_privkey = PrivateKey()
+ intro_enc_pubkey = intro_enc_privkey.get_public() # service-side enc key
+
+ intro_auth_pubkey_str = os.urandom(32)
+
+ # Let's do mixed
+ client_enc_key, client_mac_key = client_part1(intro_auth_pubkey_str, intro_enc_pubkey,
+ client_ephemeral_enc_pubkey, client_ephemeral_enc_privkey,
+ subcredential)
+
+ service_enc_key, service_mac_key, service_ntor_auth_mac, service_ntor_key_seed, service_eph_pubkey = tor_server1(intro_auth_pubkey_str,
+ intro_enc_privkey,
+ client_ephemeral_enc_pubkey,
+ subcredential)
+ assert(service_enc_key)
+ assert(service_mac_key)
+ assert(service_ntor_auth_mac)
+ assert(service_ntor_key_seed)
+ assert(service_eph_pubkey)
+
+ assert(client_enc_key == service_enc_key)
+ assert(client_mac_key == service_mac_key)
+
+ # Turn from bytes to key
+ service_eph_pubkey = curve25519mod.Public(service_eph_pubkey)
+
+ client_ntor_key_seed, client_auth_input_mac = client_part2(intro_auth_pubkey_str, client_ephemeral_enc_pubkey, client_ephemeral_enc_privkey,
+ intro_enc_pubkey, service_eph_pubkey)
+
+ assert(client_auth_input_mac == service_ntor_auth_mac)
+ assert(client_ntor_key_seed == service_ntor_key_seed)
+
+ print("DONE: 1st mixed dance [%s]" % repr(client_auth_input_mac))
+
+"""
+Do mixed test as follows:
+ 1. C -> S (tor mode)
+ 2. C <- S (python mode)
+ 3. Client computes keys (tor mode)
+"""
+def do_second_mixed_test():
+ subcredential = os.urandom(32)
+
+ client_ephemeral_enc_privkey = PrivateKey()
+ client_ephemeral_enc_pubkey = client_ephemeral_enc_privkey.get_public()
+ intro_enc_privkey = PrivateKey()
+ intro_enc_pubkey = intro_enc_privkey.get_public() # service-side enc key
+
+ intro_auth_pubkey_str = os.urandom(32)
+
+ # Let's do mixed
+ client_enc_key, client_mac_key = tor_client1(intro_auth_pubkey_str, intro_enc_pubkey,
+ client_ephemeral_enc_privkey, subcredential)
+ assert(client_enc_key)
+ assert(client_mac_key)
+
+ service_enc_key, service_mac_key, service_ntor_key_seed, service_ntor_auth_mac, service_ephemeral_pubkey = service_part1(intro_auth_pubkey_str, client_ephemeral_enc_pubkey, intro_enc_privkey, intro_enc_pubkey, subcredential)
+
+ client_ntor_auth_mac, client_ntor_key_seed = tor_client2(intro_auth_pubkey_str, client_ephemeral_enc_privkey,
+ intro_enc_pubkey, service_ephemeral_pubkey, subcredential)
+ assert(client_ntor_auth_mac)
+ assert(client_ntor_key_seed)
+
+ assert(client_ntor_key_seed == service_ntor_key_seed)
+ assert(client_ntor_auth_mac == service_ntor_auth_mac)
+
+ print("DONE: 2nd mixed dance [%s]" % repr(client_ntor_auth_mac))
+
+def do_mixed_tests():
+ do_first_mixed_test()
+ do_second_mixed_test()
+
+if __name__ == '__main__':
+ do_pure_python_ntor_test()
+ do_little_t_tor_ntor_test()
+ do_mixed_tests()
diff --git a/src/test/hs_test_helpers.c b/src/test/hs_test_helpers.c
new file mode 100644
index 0000000000..9355971267
--- /dev/null
+++ b/src/test/hs_test_helpers.c
@@ -0,0 +1,276 @@
+/* Copyright (c) 2017, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "or.h"
+#include "crypto_ed25519.h"
+#include "test.h"
+#include "torcert.h"
+
+#include "hs_common.h"
+#include "hs_test_helpers.h"
+
+hs_desc_intro_point_t *
+hs_helper_build_intro_point(const ed25519_keypair_t *signing_kp, time_t now,
+ const char *addr, int legacy)
+{
+ int ret;
+ ed25519_keypair_t auth_kp;
+ hs_desc_intro_point_t *intro_point = NULL;
+ 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_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_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_legacy);
+ smartlist_add(ip->link_specifiers, ls_v4);
+ }
+
+ ret = ed25519_keypair_generate(&auth_kp, 0);
+ tt_int_op(ret, ==, 0);
+ ip->auth_key_cert = tor_cert_create(signing_kp, CERT_TYPE_AUTH_HS_IP_KEY,
+ &auth_kp.pubkey, now,
+ HS_DESC_CERT_LIFETIME,
+ CERT_FLAG_INCLUDE_SIGNING_KEY);
+ tt_assert(ip->auth_key_cert);
+
+ if (legacy) {
+ ip->legacy.key = crypto_pk_new();
+ tt_assert(ip->legacy.key);
+ ret = crypto_pk_generate_key(ip->legacy.key);
+ tt_int_op(ret, ==, 0);
+ ssize_t cert_len = tor_make_rsa_ed25519_crosscert(
+ &signing_kp->pubkey, ip->legacy.key,
+ now + HS_DESC_CERT_LIFETIME,
+ &ip->legacy.cert.encoded);
+ tt_assert(ip->legacy.cert.encoded);
+ tt_u64_op(cert_len, OP_GT, 0);
+ ip->legacy.cert.len = cert_len;
+ }
+
+ /* Encryption key. */
+ {
+ int signbit;
+ curve25519_keypair_t curve25519_kp;
+ ed25519_keypair_t ed25519_kp;
+ tor_cert_t *cross_cert;
+
+ ret = curve25519_keypair_generate(&curve25519_kp, 0);
+ tt_int_op(ret, ==, 0);
+ ed25519_keypair_from_curve25519_keypair(&ed25519_kp, &signbit,
+ &curve25519_kp);
+ cross_cert = tor_cert_create(signing_kp, CERT_TYPE_CROSS_HS_IP_KEYS,
+ &ed25519_kp.pubkey, time(NULL),
+ HS_DESC_CERT_LIFETIME,
+ CERT_FLAG_INCLUDE_SIGNING_KEY);
+ tt_assert(cross_cert);
+ ip->enc_key_cert = cross_cert;
+ }
+
+ intro_point = ip;
+ done:
+ return intro_point;
+}
+
+/* Return a valid hs_descriptor_t object. If no_ip is set, no introduction
+ * points are added. */
+static hs_descriptor_t *
+hs_helper_build_hs_desc_impl(unsigned int no_ip,
+ const ed25519_keypair_t *signing_kp)
+{
+ time_t now = approx_time();
+ ed25519_keypair_t blinded_kp;
+ hs_descriptor_t *descp = NULL, *desc = tor_malloc_zero(sizeof(*desc));
+
+ desc->plaintext_data.version = HS_DESC_SUPPORTED_FORMAT_VERSION_MAX;
+
+ /* Copy only the public key into the descriptor. */
+ memcpy(&desc->plaintext_data.signing_pubkey, &signing_kp->pubkey,
+ sizeof(ed25519_public_key_t));
+
+ 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));
+
+ desc->plaintext_data.signing_key_cert =
+ tor_cert_create(&blinded_kp, CERT_TYPE_SIGNING_HS_DESC,
+ &signing_kp->pubkey, now, 3600,
+ CERT_FLAG_INCLUDE_SIGNING_KEY);
+ tt_assert(desc->plaintext_data.signing_key_cert);
+ 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();
+ desc->encrypted_data.single_onion_service = 1;
+ smartlist_add(desc->encrypted_data.intro_auth_types, tor_strdup("ed25519"));
+ desc->encrypted_data.intro_points = smartlist_new();
+ if (!no_ip) {
+ /* Add four intro points. */
+ smartlist_add(desc->encrypted_data.intro_points,
+ hs_helper_build_intro_point(signing_kp, now, "1.2.3.4", 0));
+ smartlist_add(desc->encrypted_data.intro_points,
+ hs_helper_build_intro_point(signing_kp, now, "[2600::1]", 0));
+ 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, "5.6.7.8", 1));
+ }
+
+ descp = desc;
+ done:
+ 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)
+{
+ return hs_helper_build_hs_desc_impl(0, signing_kp);
+}
+
+/* Build a descriptor without any introduction points. */
+hs_descriptor_t *
+hs_helper_build_hs_desc_no_ip(const ed25519_keypair_t *signing_kp)
+{
+ return hs_helper_build_hs_desc_impl(1, signing_kp);
+}
+
+void
+hs_helper_desc_equal(const hs_descriptor_t *desc1,
+ const hs_descriptor_t *desc2)
+{
+ char *addr1 = NULL, *addr2 = NULL;
+ /* Plaintext data section. */
+ tt_int_op(desc1->plaintext_data.version, OP_EQ,
+ desc2->plaintext_data.version);
+ tt_uint_op(desc1->plaintext_data.lifetime_sec, OP_EQ,
+ desc2->plaintext_data.lifetime_sec);
+ tt_assert(tor_cert_eq(desc1->plaintext_data.signing_key_cert,
+ desc2->plaintext_data.signing_key_cert));
+ tt_mem_op(desc1->plaintext_data.signing_pubkey.pubkey, OP_EQ,
+ desc2->plaintext_data.signing_pubkey.pubkey,
+ ED25519_PUBKEY_LEN);
+ tt_mem_op(desc1->plaintext_data.blinded_pubkey.pubkey, OP_EQ,
+ desc2->plaintext_data.blinded_pubkey.pubkey,
+ ED25519_PUBKEY_LEN);
+ tt_u64_op(desc1->plaintext_data.revision_counter, ==,
+ desc2->plaintext_data.revision_counter);
+
+ /* NOTE: We can't compare the encrypted blob because when encoding the
+ * descriptor, the object is immutable thus we don't update it with the
+ * encrypted blob. As contrast to the decoding process where we populate a
+ * descriptor object. */
+
+ /* Encrypted data section. */
+ tt_uint_op(desc1->encrypted_data.create2_ntor, ==,
+ desc2->encrypted_data.create2_ntor);
+
+ /* Authentication type. */
+ tt_int_op(!!desc1->encrypted_data.intro_auth_types, ==,
+ !!desc2->encrypted_data.intro_auth_types);
+ if (desc1->encrypted_data.intro_auth_types &&
+ desc2->encrypted_data.intro_auth_types) {
+ tt_int_op(smartlist_len(desc1->encrypted_data.intro_auth_types), ==,
+ smartlist_len(desc2->encrypted_data.intro_auth_types));
+ for (int i = 0;
+ i < smartlist_len(desc1->encrypted_data.intro_auth_types);
+ i++) {
+ tt_str_op(smartlist_get(desc1->encrypted_data.intro_auth_types, i),OP_EQ,
+ smartlist_get(desc2->encrypted_data.intro_auth_types, i));
+ }
+ }
+
+ /* Introduction points. */
+ {
+ tt_assert(desc1->encrypted_data.intro_points);
+ tt_assert(desc2->encrypted_data.intro_points);
+ tt_int_op(smartlist_len(desc1->encrypted_data.intro_points), ==,
+ smartlist_len(desc2->encrypted_data.intro_points));
+ for (int i=0; i < smartlist_len(desc1->encrypted_data.intro_points); i++) {
+ hs_desc_intro_point_t *ip1 = smartlist_get(desc1->encrypted_data
+ .intro_points, i),
+ *ip2 = smartlist_get(desc2->encrypted_data
+ .intro_points, i);
+ tt_assert(tor_cert_eq(ip1->auth_key_cert, ip2->auth_key_cert));
+ if (ip1->legacy.key) {
+ tt_int_op(crypto_pk_cmp_keys(ip1->legacy.key, ip2->legacy.key),
+ OP_EQ, 0);
+ } else {
+ tt_mem_op(&ip1->enc_key, OP_EQ, &ip2->enc_key, CURVE25519_PUBKEY_LEN);
+ }
+
+ tt_int_op(smartlist_len(ip1->link_specifiers), ==,
+ smartlist_len(ip2->link_specifiers));
+ for (int j = 0; j < smartlist_len(ip1->link_specifiers); j++) {
+ hs_desc_link_specifier_t *ls1 = smartlist_get(ip1->link_specifiers, j),
+ *ls2 = smartlist_get(ip2->link_specifiers, j);
+ tt_int_op(ls1->type, ==, ls2->type);
+ switch (ls1->type) {
+ case LS_IPV4:
+ case LS_IPV6:
+ {
+ addr1 = tor_addr_to_str_dup(&ls1->u.ap.addr);
+ addr2 = tor_addr_to_str_dup(&ls2->u.ap.addr);
+ tt_str_op(addr1, OP_EQ, addr2);
+ tor_free(addr1);
+ tor_free(addr2);
+ tt_int_op(ls1->u.ap.port, ==, ls2->u.ap.port);
+ }
+ break;
+ case LS_LEGACY_ID:
+ tt_mem_op(ls1->u.legacy_id, OP_EQ, ls2->u.legacy_id,
+ sizeof(ls1->u.legacy_id));
+ break;
+ default:
+ /* Unknown type, caught it and print its value. */
+ tt_int_op(ls1->type, OP_EQ, -1);
+ }
+ }
+ }
+ }
+
+ done:
+ tor_free(addr1);
+ tor_free(addr2);
+}
+
diff --git a/src/test/hs_test_helpers.h b/src/test/hs_test_helpers.h
new file mode 100644
index 0000000000..b1b0490f05
--- /dev/null
+++ b/src/test/hs_test_helpers.h
@@ -0,0 +1,25 @@
+/* Copyright (c) 2017, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_HS_TEST_HELPERS_H
+#define TOR_HS_TEST_HELPERS_H
+
+#include "ed25519_cert.h"
+#include "hs_descriptor.h"
+
+/* Set of functions to help build and test descriptors. */
+hs_desc_intro_point_t *hs_helper_build_intro_point(
+ const ed25519_keypair_t *signing_kp, time_t now,
+ const char *addr, int legacy);
+hs_descriptor_t *hs_helper_build_hs_desc_no_ip(
+ const ed25519_keypair_t *signing_kp);
+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 /* !defined(TOR_HS_TEST_HELPERS_H) */
+
diff --git a/src/test/include.am b/src/test/include.am
index 1c0726fd3a..610918e9da 100644
--- a/src/test/include.am
+++ b/src/test/include.am
@@ -5,8 +5,11 @@ TESTS_ENVIRONMENT = \
export PYTHON="$(PYTHON)"; \
export SHELL="$(SHELL)"; \
export abs_top_srcdir="$(abs_top_srcdir)"; \
+ export abs_top_builddir="$(abs_top_builddir)"; \
export builddir="$(builddir)"; \
- export TESTING_TOR_BINARY="$(TESTING_TOR_BINARY)";
+ export TESTING_TOR_BINARY="$(TESTING_TOR_BINARY)"; \
+ export CARGO="$(CARGO)"; \
+ export CARGO_ONLINE="$(CARGO_ONLINE)";
TESTSCRIPTS = \
src/test/fuzz_static_testcases.sh \
@@ -19,23 +22,32 @@ TESTSCRIPTS = \
src/test/test_workqueue_socketpair.sh \
src/test/test_switch_id.sh
+if USE_RUST
+TESTSCRIPTS += \
+ src/test/test_rust.sh
+endif
+
if USEPYTHON
-TESTSCRIPTS += src/test/test_ntor.sh src/test/test_bt.sh
+TESTSCRIPTS += src/test/test_ntor.sh src/test/test_hs_ntor.sh src/test/test_bt.sh
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.
@@ -69,6 +81,7 @@ src_test_AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \
src_test_test_SOURCES = \
src/test/log_test_helpers.c \
+ src/test/hs_test_helpers.c \
src/test/rend_test_helpers.c \
src/test/test.c \
src/test/test_accounting.c \
@@ -78,18 +91,24 @@ src_test_test_SOURCES = \
src/test/test_cell_formats.c \
src/test/test_cell_queue.c \
src/test/test_channel.c \
+ src/test/test_channelpadding.c \
src/test/test_channeltls.c \
src/test/test_checkdir.c \
src/test/test_circuitlist.c \
src/test/test_circuitmux.c \
+ src/test/test_circuitbuild.c \
src/test/test_circuituse.c \
src/test/test_compat_libevent.c \
src/test/test_config.c \
src/test/test_connection.c \
+ src/test/test_conscache.c \
+ src/test/test_consdiff.c \
+ src/test/test_consdiffmgr.c \
src/test/test_containers.c \
src/test/test_controller.c \
src/test/test_controller_events.c \
src/test/test_crypto.c \
+ src/test/test_crypto_openssl.c \
src/test/test_data.c \
src/test/test_dir.c \
src/test/test_dir_common.c \
@@ -99,7 +118,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 \
@@ -115,6 +139,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 \
@@ -122,13 +148,16 @@ 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 \
+ src/test/test_rust.c \
src/test/test_scheduler.c \
src/test/test_shared_random.c \
src/test/test_socks.c \
src/test/test_status.c \
+ src/test/test_storagedir.c \
src/test/test_threads.c \
src/test/test_tortls.c \
src/test/test_util.c \
@@ -174,7 +203,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 \
- @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@
+ $(rust_ldadd) \
+ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \
+ @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@
@@ -186,9 +218,12 @@ src_test_test_LDADD = src/or/libtor-testing.a \
src/common/libor-ctime-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_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)
@@ -209,9 +244,12 @@ src_test_bench_LDADD = src/or/libtor.a src/common/libor.a \
src/common/libor-ctime.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_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@
@@ -220,8 +258,12 @@ src_test_test_workqueue_LDADD = src/or/libtor-testing.a \
src/common/libor-ctime-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_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)
@@ -230,54 +272,82 @@ 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_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+= \
src/test/fakechans.h \
+ src/test/hs_test_helpers.h \
src/test/log_test_helpers.h \
src/test/rend_test_helpers.h \
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 \
src/test/ed25519_vectors.inc \
src/test/test_descriptors.inc \
+ src/test/test_hs_descriptor.inc \
src/test/vote_descriptors.inc
noinst_PROGRAMS+= src/test/test-ntor-cl
+noinst_PROGRAMS+= src/test/test-hs-ntor-cl
src_test_test_ntor_cl_SOURCES = src/test/test_ntor_cl.c
src_test_test_ntor_cl_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@
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_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"
+src_test_test_hs_ntor_cl_SOURCES = src/test/test_hs_ntor_cl.c
+src_test_test_hs_ntor_cl_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@
+src_test_test_hs_ntor_cl_LDADD = src/or/libtor.a src/common/libor.a \
+ src/common/libor-ctime.a \
+ src/common/libor-crypto.a $(LIBKECCAK_TINY) $(LIBDONNA) \
+ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \
+ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@
+src_test_test_hs_ntor_cl_AM_CPPFLAGS = \
+ -I"$(top_srcdir)/src/or"
+
+
noinst_PROGRAMS += src/test/test-bt-cl
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@
+ @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)
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_bt.sh \
+ src/test/test_ntor.sh src/test/test_hs_ntor.sh src/test/test_bt.sh \
src/test/test-network.sh \
+ src/test/test_rust.sh \
src/test/test_switch_id.sh \
src/test/test_workqueue_cancel.sh \
src/test/test_workqueue_efd.sh \
diff --git a/src/test/log_test_helpers.c b/src/test/log_test_helpers.c
index c788a33c17..d5a39cfeee 100644
--- a/src/test/log_test_helpers.c
+++ b/src/test/log_test_helpers.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Tor Project, Inc. */
+/* Copyright (c) 2015-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define LOG_PRIVATE
#include "torlog.h"
diff --git a/src/test/log_test_helpers.h b/src/test/log_test_helpers.h
index 922c68b42f..70c584eb37 100644
--- a/src/test/log_test_helpers.h
+++ b/src/test/log_test_helpers.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Tor Project, Inc. */
+/* Copyright (c) 2014-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "or.h"
@@ -71,14 +71,14 @@ void mock_dump_saved_logs(void);
\
assert_log_predicate(mock_saved_log_has_message_containing(str) && \
mock_saved_log_n_entries() == 1, \
- "expected log to contain exactly 1 message: " # str); \
+ "expected log to contain exactly 1 message " # str); \
} while (0);
#define expect_single_log_msg_containing(str) \
do { \
assert_log_predicate(mock_saved_log_has_message_containing(str)&& \
mock_saved_log_n_entries() == 1 , \
- "expected log to contain 1 message, containing" # str); \
+ "expected log to contain 1 message, containing " # str); \
} while (0);
#define expect_no_log_msg(str) \
@@ -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 df065853f3..c753588f97 100755
--- a/src/test/ntor_ref.py
+++ b/src/test/ntor_ref.py
@@ -1,5 +1,5 @@
#!/usr/bin/python
-# Copyright 2012-2015, The Tor Project, Inc
+# Copyright 2012-2017, The Tor Project, Inc
# See LICENSE for licensing information
"""
diff --git a/src/test/rend_test_helpers.c b/src/test/rend_test_helpers.c
index 377337bcb9..095bfecf21 100644
--- a/src/test/rend_test_helpers.c
+++ b/src/test/rend_test_helpers.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Tor Project, Inc. */
+/* Copyright (c) 2014-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "or.h"
@@ -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 180a4e8fde..abf4324988 100644
--- a/src/test/rend_test_helpers.h
+++ b/src/test/rend_test_helpers.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Tor Project, Inc. */
+/* Copyright (c) 2014-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "or.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 fdf3ccec0a..f78a829107 100644
--- a/src/test/test-child.c
+++ b/src/test/test-child.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2016, The Tor Project, Inc. */
+/* Copyright (c) 2011-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -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-network.sh b/src/test/test-network.sh
index 10bd370ff3..6e0f286573 100755
--- a/src/test/test-network.sh
+++ b/src/test/test-network.sh
@@ -1,119 +1,45 @@
#!/bin/sh
-# use bash if it is available, as this script doesn't work well in non-bash sh
-# this will be fixed in #19699
-# there is no simple, portable way of checking the name of the shell, so we
-# exec bash even when sh is bash
-if [ -x /bin/bash -a "$USING_BASH" != true ]; then
- # only do this once
- export USING_BASH=true
- exec /bin/bash "$0" "$@"
+# This script calls the equivalent script in chutney/tools
+
+# If we already know CHUTNEY_PATH, don't bother with argument parsing
+TEST_NETWORK="$CHUTNEY_PATH/tools/test-network.sh"
+# Call the chutney version of this script, if it exists, and we can find it
+if [ -d "$CHUTNEY_PATH" -a -x "$TEST_NETWORK" ]; then
+ # we can't produce any output, because we might be --quiet
+ # this preserves arguments with spaces correctly
+ exec "$TEST_NETWORK" "$@"
fi
-# Please do not modify this script, it has been moved to chutney/tools
-
-export ECHO="${ECHO:-echo}"
-export ECHO_N="${ECHO_N:-/bin/echo -n}"
+# We need to go looking for CHUTNEY_PATH
+# Do we output anything at all?
+ECHO="${ECHO:-echo}"
# Output is prefixed with the name of the script
myname=$(basename $0)
-# We need to find CHUTNEY_PATH, so that we can call the version of this script
-# in chutney/tools. And we want to pass any arguments to that script as well.
-# So we source this script, which processes its arguments to find CHUTNEY_PATH.
-
-# Avoid recursively sourcing this script, and don't call the chutney version
-# while recursing, either
-if [ "$TEST_NETWORK_RECURSING" != true ]; then
- # Process the arguments into environmental variables with this script
- # to make sure $CHUTNEY_PATH is set
- # When we switch to using test-network.sh in chutney/tools, --dry-run
- # can be removed, because this script will find chutney, then pass all
- # arguments to chutney's test-network.sh
- export TEST_NETWORK_RECURSING=true
- # passing arguments to a sourced script only works in bash
- # this will be fixed in #19699
- . "$0" --dry-run "$@"
-
- # Call the chutney version of this script, if it exists, and we can find it
- if [ -d "$CHUTNEY_PATH" -a -x "$CHUTNEY_PATH/tools/test-network.sh" ]; then
- unset NETWORK_DRY_RUN
- $ECHO "$myname: Calling newer chutney script \
-$CHUTNEY_PATH/tools/test-network.sh"
- "$CHUTNEY_PATH/tools/test-network.sh" "$@"
- exit $?
- else
- $ECHO "$myname: This script has moved to chutney/tools."
- $ECHO "$myname: Please update your chutney using 'git pull'."
- # When we switch to using test-network.sh in chutney/tools, we should
- # exit with a very loud failure here
- $ECHO "$myname: Falling back to the old tor version of the script."
- fi
-fi
+# Save the arguments before we destroy them
+# This might not preserve arguments with spaces in them
+ORIGINAL_ARGS="$@"
+# We need to find CHUTNEY_PATH, so that we can call the version of this script
+# in chutney/tools with the same arguments. We also need to respect --quiet.
until [ -z "$1" ]
do
case "$1" in
--chutney-path)
- export CHUTNEY_PATH="$2"
+ CHUTNEY_PATH="$2"
shift
;;
--tor-path)
- export TOR_DIR="$2"
- shift
- ;;
- # When we switch to using test-network.sh in chutney/tools, only the
- # --chutney-path and --tor-path arguments need to be processed by this
- # script, everything else can be handled by chutney's test-network.sh
- --flavor|--flavour|--network-flavor|--network-flavour)
- export NETWORK_FLAVOUR="$2"
+ TOR_DIR="$2"
shift
;;
- --delay|--sleep|--bootstrap-time|--time)
- export BOOTSTRAP_TIME="$2"
- shift
- ;;
- # Environmental variables used by chutney verify performance tests
- # Send this many bytes per client connection (10 KBytes)
- --data|--data-bytes|--data-byte|--bytes|--byte)
- export CHUTNEY_DATA_BYTES="$2"
- shift
- ;;
- # Make this many connections per client (1)
- # Note: If you create 7 or more connections to a hidden service from
- # a single Tor 0.2.7 client, you'll likely get a verification failure due
- # to #15937. This is fixed in 0.2.8.
- --connections|--connection|--connection-count|--count)
- export CHUTNEY_CONNECTIONS="$2"
- shift
- ;;
- # Make each client connect to each HS (0)
- # 0 means a single client connects to each HS
- # 1 means every client connects to every HS
- --hs-multi-client|--hs-multi-clients|--hs-client|--hs-clients)
- export CHUTNEY_HS_MULTI_CLIENT="$2"
- shift
- ;;
- --coverage)
- export USE_COVERAGE_BINARY=true
- ;;
- --dry-run)
- # process arguments, but don't call any other scripts
- export NETWORK_DRY_RUN=true
- ;;
--quiet)
- export ECHO=true
- export ECHO_N=true
- ;;
+ ECHO=true
+ ;;
*)
- $ECHO "$myname: Sorry, I don't know what to do with '$1'."
- $ECHO "$myname: Maybe chutney's test-network.sh understands '$1'."
- $ECHO "$myname: Please update your chutney using 'git pull', and set \
-\$CHUTNEY_PATH"
- # continue processing arguments during a dry run
- if [ "$NETWORK_DRY_RUN" != true ]; then
- exit 2
- fi
+ # maybe chutney's test-network.sh can handle it
;;
esac
shift
@@ -122,7 +48,7 @@ done
# optional: $TOR_DIR is the tor build directory
# it's used to find the location of tor binaries
# if it's not set:
-# - set it ro $BUILDDIR, or
+# - set it to $BUILDDIR, or
# - if $PWD looks like a tor build directory, set it to $PWD, or
# - unset $TOR_DIR, and let chutney fall back to finding tor binaries in $PATH
if [ ! -d "$TOR_DIR" ]; then
@@ -130,12 +56,12 @@ if [ ! -d "$TOR_DIR" ]; then
# Choose the build directory
# But only if it looks like one
$ECHO "$myname: \$TOR_DIR not set, trying \$BUILDDIR"
- export TOR_DIR="$BUILDDIR"
+ TOR_DIR="$BUILDDIR"
elif [ -d "$PWD/src/or" -a -d "$PWD/src/tools" ]; then
# Guess the tor directory is the current directory
# But only if it looks like one
$ECHO "$myname: \$TOR_DIR not set, trying \$PWD"
- export TOR_DIR="$PWD"
+ TOR_DIR="$PWD"
else
$ECHO "$myname: no \$TOR_DIR, chutney will use \$PATH for tor binaries"
unset TOR_DIR
@@ -150,14 +76,12 @@ fi
if [ ! -d "$CHUTNEY_PATH" -o ! -x "$CHUTNEY_PATH/chutney" ]; then
if [ -x "$PWD/chutney" ]; then
$ECHO "$myname: \$CHUTNEY_PATH not valid, trying \$PWD"
- export CHUTNEY_PATH="$PWD"
+ CHUTNEY_PATH="$PWD"
elif [ -d "$TOR_DIR" -a -d "$TOR_DIR/../chutney" -a \
-x "$TOR_DIR/../chutney/chutney" ]; then
$ECHO "$myname: \$CHUTNEY_PATH not valid, trying \$TOR_DIR/../chutney"
- export CHUTNEY_PATH="$TOR_DIR/../chutney"
+ CHUTNEY_PATH="$TOR_DIR/../chutney"
else
- # TODO: work out how to package and install chutney,
- # so users can find it in $PATH
$ECHO "$myname: missing 'chutney' in \$CHUTNEY_PATH ($CHUTNEY_PATH)"
$ECHO "$myname: Get chutney: git clone https://git.torproject.org/\
chutney.git"
@@ -168,46 +92,17 @@ CHUTNEY_PATH=\`pwd\`/chutney"
fi
fi
-# When we switch to using test-network.sh in chutney/tools, this comment and
-# everything below it can be removed
-
-# For picking up the right tor binaries.
-# If these varibles aren't set, chutney looks for tor binaries in $PATH
-if [ -d "$TOR_DIR" ]; then
- tor_name=tor
- tor_gencert_name=tor-gencert
- if [ "$USE_COVERAGE_BINARY" = true ]; then
- tor_name=tor-cov
- fi
- export CHUTNEY_TOR="${TOR_DIR}/src/or/${tor_name}"
- export CHUTNEY_TOR_GENCERT="${TOR_DIR}/src/tools/${tor_gencert_name}"
-fi
-
-# Set the variables for the chutney network flavour
-export NETWORK_FLAVOUR=${NETWORK_FLAVOUR:-"bridges+hs"}
-export CHUTNEY_NETWORK=networks/$NETWORK_FLAVOUR
-
-# And finish up if we're doing a dry run
-if [ "$NETWORK_DRY_RUN" = true ]; then
- # we can't exit here, it breaks argument processing
- # this only works in bash: return semantics are shell-specific
- # this will be fixed in #19699
- return 2>/dev/null || exit
+TEST_NETWORK="$CHUTNEY_PATH/tools/test-network.sh"
+# Call the chutney version of this script, if it exists, and we can find it
+if [ -d "$CHUTNEY_PATH" -a -x "$TEST_NETWORK" ]; then
+ $ECHO "$myname: Calling newer chutney script $TEST_NETWORK"
+ # this may fail if some arguments have spaces in them
+ # if so, set CHUTNEY_PATH before calling test-network.sh, and spaces
+ # will be handled correctly
+ exec "$TEST_NETWORK" $ORIGINAL_ARGS
+else
+ $ECHO "$myname: Could not find tools/test-network.sh in CHUTNEY_PATH."
+ $ECHO "$myname: Please update your chutney using 'git pull'."
+ # We have failed to do what the user asked
+ exit 1
fi
-
-cd "$CHUTNEY_PATH"
-./tools/bootstrap-network.sh $NETWORK_FLAVOUR || exit 3
-
-# Sleep some, waiting for the network to bootstrap.
-# TODO: Add chutney command 'bootstrap-status' and use that instead.
-BOOTSTRAP_TIME=${BOOTSTRAP_TIME:-35}
-$ECHO_N "$myname: sleeping for $BOOTSTRAP_TIME seconds"
-n=$BOOTSTRAP_TIME; while [ $n -gt 0 ]; do
- sleep 1; n=$(expr $n - 1); $ECHO_N .
-done; $ECHO ""
-./chutney verify $CHUTNEY_NETWORK
-VERIFY_EXIT_STATUS=$?
-# work around a bug/feature in make -j2 (or more)
-# where make hangs if any child processes are still alive
-./chutney stop $CHUTNEY_NETWORK
-exit $VERIFY_EXIT_STATUS
diff --git a/src/test/test-timers.c b/src/test/test-timers.c
index b5fcade7f8..99715f4333 100644
--- a/src/test/test-timers.c
+++ b/src/test/test-timers.c
@@ -1,4 +1,4 @@
-/* Copyright 2016, The Tor Project, Inc. */
+/* Copyright 2016-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test.c b/src/test/test.c
index 866408e856..da4f7a0553 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -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. */
@@ -44,13 +44,13 @@ double fabs(double x);
#include "buffers.h"
#include "circuitlist.h"
#include "circuitstats.h"
+#include "compress.h"
#include "config.h"
#include "connection_edge.h"
#include "geoip.h"
#include "rendcommon.h"
#include "rendcache.h"
#include "test.h"
-#include "torgzip.h"
#include "main.h"
#include "memarea.h"
#include "onion.h"
@@ -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. */
@@ -1011,7 +996,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. */
@@ -1049,7 +1034,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. */
@@ -1068,7 +1053,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);
@@ -1085,7 +1070,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. */
@@ -1103,7 +1088,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. */
@@ -1138,7 +1123,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. */
@@ -1186,18 +1171,24 @@ struct testgroup_t testgroups[] = {
{ "cellfmt/", cell_format_tests },
{ "cellqueue/", cell_queue_tests },
{ "channel/", channel_tests },
+ { "channelpadding/", channelpadding_tests },
{ "channeltls/", channeltls_tests },
{ "checkdir/", checkdir_tests },
+ { "circuitbuild/", circuitbuild_tests },
{ "circuitlist/", circuitlist_tests },
{ "circuitmux/", circuitmux_tests },
{ "circuituse/", circuituse_tests },
{ "compat/libevent/", compat_libevent_tests },
{ "config/", config_tests },
{ "connection/", connection_tests },
+ { "conscache/", conscache_tests },
+ { "consdiff/", consdiff_tests },
+ { "consdiffmgr/", consdiffmgr_tests },
{ "container/", container_tests },
{ "control/", controller_tests },
{ "control/event/", controller_event_tests },
{ "crypto/", crypto_tests },
+ { "crypto/openssl/", crypto_openssl_tests },
{ "dir/", dir_tests },
{ "dir_handle_get/", dir_handle_get_tests },
{ "dir/md/", microdesc_tests },
@@ -1207,8 +1198,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 },
@@ -1219,19 +1215,24 @@ 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 },
+ { "rust/", rust_tests },
{ "scheduler/", scheduler_tests },
{ "socks/", socks_tests },
{ "shared-random/", sr_tests },
{ "status/" , status_tests },
+ { "storagedir/", storagedir_tests },
{ "tortls/", tortls_tests },
{ "util/", util_tests },
{ "util/format/", util_format_tests },
diff --git a/src/test/test.h b/src/test/test.h
index 2bd58f51c8..634f3e7b02 100644
--- a/src/test/test.h
+++ b/src/test/test.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2003, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_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_), \
@@ -181,18 +181,24 @@ extern struct testcase_t buffer_tests[];
extern struct testcase_t cell_format_tests[];
extern struct testcase_t cell_queue_tests[];
extern struct testcase_t channel_tests[];
+extern struct testcase_t channelpadding_tests[];
extern struct testcase_t channeltls_tests[];
extern struct testcase_t checkdir_tests[];
+extern struct testcase_t circuitbuild_tests[];
extern struct testcase_t circuitlist_tests[];
extern struct testcase_t circuitmux_tests[];
extern struct testcase_t circuituse_tests[];
extern struct testcase_t compat_libevent_tests[];
extern struct testcase_t config_tests[];
extern struct testcase_t connection_tests[];
+extern struct testcase_t conscache_tests[];
+extern struct testcase_t consdiff_tests[];
+extern struct testcase_t consdiffmgr_tests[];
extern struct testcase_t container_tests[];
extern struct testcase_t controller_tests[];
extern struct testcase_t controller_event_tests[];
extern struct testcase_t crypto_tests[];
+extern struct testcase_t crypto_openssl_tests[];
extern struct testcase_t dir_tests[];
extern struct testcase_t dir_handle_get_tests[];
extern struct testcase_t entryconn_tests[];
@@ -201,8 +207,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[];
@@ -215,6 +226,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[];
@@ -226,7 +239,9 @@ extern struct testcase_t router_tests[];
extern struct testcase_t routerkeys_tests[];
extern struct testcase_t routerlist_tests[];
extern struct testcase_t routerset_tests[];
+extern struct testcase_t rust_tests[];
extern struct testcase_t scheduler_tests[];
+extern struct testcase_t storagedir_tests[];
extern struct testcase_t socks_tests[];
extern struct testcase_t status_tests[];
extern struct testcase_t thread_tests[];
@@ -256,5 +271,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 be440a0925..e1a40b7e60 100644
--- a/src/test/test_addr.c
+++ b/src/test/test_addr.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define ADDRESSMAP_PRIVATE
@@ -9,6 +9,24 @@
#include "test.h"
#include "addressmap.h"
+/** Mocking replacement: only handles localhost. */
+static int
+mock_tor_addr_lookup(const char *name, uint16_t family, tor_addr_t *addr_out)
+{
+ if (!strcmp(name, "localhost")) {
+ if (family == AF_INET || family == AF_UNSPEC) {
+ tor_addr_from_ipv4h(addr_out, 0x7f000001);
+ return 0;
+ } else if (family == AF_INET6) {
+ char bytes[16] = { 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1 };
+ tor_addr_from_ipv6_bytes(addr_out, bytes);
+ return 0;
+ }
+ }
+ return -1;
+}
+
static void
test_addr_basic(void *arg)
{
@@ -29,6 +47,9 @@ test_addr_basic(void *arg)
tt_int_op(u32,OP_EQ, 0x04030201u);
tt_int_op(u16,OP_EQ, 99);
tor_free(cp);
+
+ MOCK(tor_addr_lookup, mock_tor_addr_lookup);
+
tt_assert(!addr_port_lookup(LOG_WARN, "nonexistent.address:4040",
&cp, NULL, &u16));
tt_str_op(cp,OP_EQ, "nonexistent.address");
@@ -36,8 +57,8 @@ test_addr_basic(void *arg)
tor_free(cp);
tt_assert(!addr_port_lookup(LOG_WARN, "localhost:9999", &cp, &u32, &u16));
tt_str_op(cp,OP_EQ, "localhost");
- tt_int_op(u32,OP_EQ, 0x7f000001u);
tt_int_op(u16,OP_EQ, 9999);
+ tt_int_op(u32,OP_EQ, 0x7f000001u);
tor_free(cp);
u32 = 3;
tt_assert(!addr_port_lookup(LOG_WARN, "localhost", NULL, &u32, &u16));
@@ -75,6 +96,7 @@ test_addr_basic(void *arg)
}
done:
+ UNMOCK(tor_addr_lookup);
tor_free(cp);
}
@@ -429,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);
@@ -615,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);
@@ -664,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 */
@@ -730,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)));
@@ -988,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 0d142ad483..f36ff6998b 100644
--- a/src/test/test_address.c
+++ b/src/test/test_address.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Tor Project, Inc. */
+/* Copyright (c) 2014-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define ADDRESS_PRIVATE
@@ -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 709d599f52..b5c8d7cf9e 100644
--- a/src/test/test_bt_cl.c
+++ b/src/test/test_bt_cl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Tor Project, Inc. */
+/* Copyright (c) 2012-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -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 9e7bdb8911..9f4e19bc5f 100644
--- a/src/test/test_buffers.c
+++ b/src/test/test_buffers.c
@@ -1,12 +1,15 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#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));
@@ -578,120 +504,150 @@ test_buffer_time_tracking(void *arg)
}
static void
-test_buffers_zlib_impl(int finalize_with_nil)
+test_buffers_compress_fin_at_chunk_end_impl(compress_method_t method,
+ compression_level_t level)
{
char *msg = NULL;
char *contents = NULL;
char *expanded = NULL;
buf_t *buf = NULL;
- tor_zlib_state_t *zlib_state = NULL;
+ tor_compress_state_t *compress_state = NULL;
size_t out_len, in_len;
- int done;
+ size_t sz, headerjunk;
buf = buf_new_with_capacity(128); /* will round up */
- zlib_state = tor_zlib_new(1, ZLIB_METHOD, HIGH_COMPRESSION);
+ sz = buf_get_default_chunk_size(buf);
+ msg = tor_malloc_zero(sz);
- msg = tor_malloc(512);
- crypto_rand(msg, 512);
- tt_int_op(write_to_buf_zlib(buf, zlib_state, msg, 128, 0), OP_EQ, 0);
- tt_int_op(write_to_buf_zlib(buf, zlib_state, msg+128, 128, 0), OP_EQ, 0);
- tt_int_op(write_to_buf_zlib(buf, zlib_state, msg+256, 256, 0), OP_EQ, 0);
- done = !finalize_with_nil;
- tt_int_op(write_to_buf_zlib(buf, zlib_state, "all done", 9, done), OP_EQ, 0);
- if (finalize_with_nil) {
- tt_int_op(write_to_buf_zlib(buf, zlib_state, "", 0, 1), OP_EQ, 0);
- }
+ 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;
+ 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(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_gzip_uncompress(&expanded, &out_len,
- contents, in_len,
- ZLIB_METHOD, 1,
- LOG_WARN));
+ if (method == NO_METHOD) {
+ tt_uint_op(in_len, OP_EQ, headerjunk);
+ } else {
+ tt_uint_op(in_len, OP_GT, headerjunk);
+ }
- tt_int_op(out_len, OP_GE, 128);
- tt_mem_op(msg, OP_EQ, expanded, 128);
- tt_int_op(out_len, OP_GE, 512);
- tt_mem_op(msg, OP_EQ, expanded, 512);
- tt_int_op(out_len, OP_EQ, 512+9);
- tt_mem_op("all done", OP_EQ, expanded+512, 9);
+ tt_int_op(0, OP_EQ, tor_uncompress(&expanded, &out_len,
+ contents + headerjunk,
+ in_len - headerjunk,
+ method, 1,
+ LOG_WARN));
+
+ tt_int_op(out_len, OP_EQ, 0);
+ tt_assert(expanded);
done:
buf_free(buf);
- tor_zlib_free(zlib_state);
+ tor_compress_free(compress_state);
tor_free(contents);
tor_free(expanded);
tor_free(msg);
}
static void
-test_buffers_zlib(void *arg)
-{
- (void) arg;
- test_buffers_zlib_impl(0);
-}
-static void
-test_buffers_zlib_fin_with_nil(void *arg)
-{
- (void) arg;
- test_buffers_zlib_impl(1);
-}
-
-static void
-test_buffers_zlib_fin_at_chunk_end(void *arg)
+test_buffers_compress_impl(compress_method_t method,
+ compression_level_t level,
+ int finalize_with_nil)
{
char *msg = NULL;
char *contents = NULL;
char *expanded = NULL;
buf_t *buf = NULL;
- tor_zlib_state_t *zlib_state = NULL;
+ tor_compress_state_t *compress_state = NULL;
size_t out_len, in_len;
- size_t sz, headerjunk;
- (void) arg;
+ int done;
buf = buf_new_with_capacity(128); /* will round up */
- sz = buf_get_default_chunk_size(buf);
- msg = tor_malloc_zero(sz);
+ compress_state = tor_compress_new(1, method, level);
- write_to_buf(msg, 1, buf);
- tt_assert(buf->head);
-
- /* Fill up the chunk so the zlib 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);
- 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. */
- zlib_state = tor_zlib_new(1, ZLIB_METHOD, HIGH_COMPRESSION);
- tt_int_op(write_to_buf_zlib(buf, zlib_state, "", 0, 1), OP_EQ, 0);
+ msg = tor_malloc(512);
+ crypto_rand(msg, 512);
+ tt_int_op(buf_add_compress(buf, compress_state,
+ msg, 128, 0), OP_EQ, 0);
+ tt_int_op(buf_add_compress(buf, compress_state,
+ msg+128, 128, 0), OP_EQ, 0);
+ tt_int_op(buf_add_compress(buf, compress_state,
+ msg+256, 256, 0), OP_EQ, 0);
+ done = !finalize_with_nil;
+ tt_int_op(buf_add_compress(buf, compress_state,
+ "all done", 9, done), OP_EQ, 0);
+ if (finalize_with_nil) {
+ 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_uint_op(in_len, OP_GT, headerjunk);
+ tt_int_op(buf_get_bytes(buf, contents, in_len), OP_EQ, 0);
- tt_int_op(0, OP_EQ, tor_gzip_uncompress(&expanded, &out_len,
- contents + headerjunk, in_len - headerjunk,
- ZLIB_METHOD, 1,
- LOG_WARN));
+ tt_int_op(0, OP_EQ, tor_uncompress(&expanded, &out_len,
+ contents, in_len,
+ method, 1,
+ LOG_WARN));
- tt_int_op(out_len, OP_EQ, 0);
- tt_assert(expanded);
+ tt_int_op(out_len, OP_GE, 128);
+ tt_mem_op(msg, OP_EQ, expanded, 128);
+ tt_int_op(out_len, OP_GE, 512);
+ tt_mem_op(msg, OP_EQ, expanded, 512);
+ tt_int_op(out_len, OP_EQ, 512+9);
+ tt_mem_op("all done", OP_EQ, expanded+512, 9);
done:
buf_free(buf);
- tor_zlib_free(zlib_state);
+ tor_compress_free(compress_state);
tor_free(contents);
tor_free(expanded);
tor_free(msg);
}
+static void
+test_buffers_compress(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();
+ }
+
+ compression_level_t levels[] = {
+ BEST_COMPRESSION,
+ HIGH_COMPRESSION,
+ MEDIUM_COMPRESSION,
+ LOW_COMPRESSION
+ };
+
+ for (unsigned l = 0; l < ARRAY_LENGTH(levels); ++l) {
+ compression_level_t level = levels[l];
+
+ test_buffers_compress_impl(method, level, 0);
+ test_buffers_compress_impl(method, level, 1);
+ test_buffers_compress_fin_at_chunk_end_impl(method, level);
+ }
+
+ done:
+ ;
+}
+
static const uint8_t *tls_read_ptr;
static int n_remaining;
static int next_reply_val[16];
@@ -732,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);
@@ -750,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:
;
}
@@ -801,29 +757,63 @@ 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 },
- { "zlib", test_buffers_zlib, TT_FORK, NULL, NULL },
- { "zlib_fin_with_nil", test_buffers_zlib_fin_with_nil, TT_FORK, NULL, NULL },
- { "zlib_fin_at_chunk_end", test_buffers_zlib_fin_at_chunk_end, TT_FORK,
- NULL, NULL},
{ "tls_read_mocked", test_buffers_tls_read_mocked, 0,
NULL, NULL },
{ "chunk_size", test_buffers_chunk_size, 0, NULL, NULL },
{ "find_contentlen", test_buffers_find_contentlen, 0, NULL, NULL },
+
+ { "compress/zlib", test_buffers_compress, TT_FORK,
+ &passthrough_setup, (char*)"deflate" },
+ { "compress/gzip", test_buffers_compress, TT_FORK,
+ &passthrough_setup, (char*)"gzip" },
+ { "compress/zstd", test_buffers_compress, TT_FORK,
+ &passthrough_setup, (char*)"x-zstd" },
+ { "compress/lzma", test_buffers_compress, TT_FORK,
+ &passthrough_setup, (char*)"x-tor-lzma" },
+ { "compress/none", test_buffers_compress, TT_FORK,
+ &passthrough_setup, (char*)"identity" },
+
END_OF_TESTCASES
};
diff --git a/src/test/test_cell_formats.c b/src/test/test_cell_formats.c
index 22c34b6d6c..007f7e3d3e 100644
--- a/src/test/test_cell_formats.c
+++ b/src/test/test_cell_formats.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_cell_queue.c b/src/test/test_cell_queue.c
index 93ac9854d8..69e89b69b0 100644
--- a/src/test/test_cell_queue.c
+++ b/src/test/test_cell_queue.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Tor Project, Inc. */
+/* Copyright (c) 2013-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CIRCUITLIST_PRIVATE
diff --git a/src/test/test_channel.c b/src/test/test_channel.c
index 862bd6dfa6..023c2950c9 100644
--- a/src/test/test_channel.c
+++ b/src/test/test_channel.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Tor Project, Inc. */
+/* Copyright (c) 2013-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define TOR_CHANNEL_INTERNAL_
@@ -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
new file mode 100644
index 0000000000..d5713688a0
--- /dev/null
+++ b/src/test/test_channelpadding.c
@@ -0,0 +1,1130 @@
+#define TOR_CHANNEL_INTERNAL_
+#define MAIN_PRIVATE
+#define NETWORKSTATUS_PRIVATE
+#define TOR_TIMERS_PRIVATE
+#include "or.h"
+#include "test.h"
+#include "testsupport.h"
+#include "connection.h"
+#include "connection_or.h"
+#include "channel.h"
+#include "channeltls.h"
+#include "channelpadding.h"
+#include "compat_libevent.h"
+#include "config.h"
+#include <event2/event.h>
+#include "compat_time.h"
+#include "main.h"
+#include "networkstatus.h"
+#include "log_test_helpers.h"
+
+int channelpadding_get_netflow_inactive_timeout_ms(channel_t *chan);
+int64_t channelpadding_compute_time_until_pad_for_netflow(channel_t *chan);
+int channelpadding_send_disable_command(channel_t*);
+int channelpadding_find_timerslot(channel_t *chan);
+
+void test_channelpadding_timers(void *arg);
+void test_channelpadding_consensus(void *arg);
+void test_channelpadding_negotiation(void *arg);
+void test_channelpadding_decide_to_pad_channel(void *arg);
+void test_channelpadding_killonehop(void *arg);
+
+void dummy_nop_timer(void);
+
+#define NSEC_PER_MSEC (1000*1000)
+
+/* Thing to cast to fake tor_tls_t * to appease assert_connection_ok() */
+static int fake_tortls = 0; /* Bleh... */
+
+static int dont_stop_libevent = 0;
+
+// From test_channel.c
+channel_t * new_fake_channel(void);
+void free_fake_channel(channel_t*);
+
+static int
+mock_channel_has_queued_writes(channel_t *chan)
+{
+ (void)chan;
+ return 0;
+}
+
+static int tried_to_write_cell = 0;
+
+static channel_t *relay1_relay2;
+static channel_t *relay2_relay1;
+static channel_t *relay3_client;
+static channel_t *client_relay3;
+
+static int
+mock_channel_write_cell_relay2(channel_t *chan, cell_t *cell)
+{
+ (void)chan;
+ tried_to_write_cell++;
+ channel_tls_handle_cell(cell, ((channel_tls_t*)relay1_relay2)->conn);
+ event_base_loopbreak(tor_libevent_get_base());
+ return 0;
+}
+
+static int
+mock_channel_write_cell_relay1(channel_t *chan, cell_t *cell)
+{
+ (void)chan;
+ tried_to_write_cell++;
+ channel_tls_handle_cell(cell, ((channel_tls_t*)relay2_relay1)->conn);
+ event_base_loopbreak(tor_libevent_get_base());
+ return 0;
+}
+
+static int
+mock_channel_write_cell_relay3(channel_t *chan, cell_t *cell)
+{
+ (void)chan;
+ tried_to_write_cell++;
+ channel_tls_handle_cell(cell, ((channel_tls_t*)client_relay3)->conn);
+ event_base_loopbreak(tor_libevent_get_base());
+ return 0;
+}
+
+static int
+mock_channel_write_cell_client(channel_t *chan, cell_t *cell)
+{
+ (void)chan;
+ tried_to_write_cell++;
+ channel_tls_handle_cell(cell, ((channel_tls_t*)relay3_client)->conn);
+ event_base_loopbreak(tor_libevent_get_base());
+ return 0;
+}
+
+static int
+mock_channel_write_cell(channel_t *chan, cell_t *cell)
+{
+ tried_to_write_cell++;
+ channel_tls_handle_cell(cell, ((channel_tls_t*)chan)->conn);
+ if (!dont_stop_libevent)
+ event_base_loopbreak(tor_libevent_get_base());
+ return 0;
+}
+
+static void
+setup_fake_connection_for_channel(channel_tls_t *chan)
+{
+ or_connection_t *conn = (or_connection_t*)connection_new(CONN_TYPE_OR,
+ AF_INET);
+
+ conn->base_.conn_array_index = smartlist_len(connection_array);
+ smartlist_add(connection_array, conn);
+
+ conn->chan = chan;
+ chan->conn = conn;
+
+ conn->base_.magic = OR_CONNECTION_MAGIC;
+ conn->base_.state = OR_CONN_STATE_OPEN;
+ conn->base_.type = CONN_TYPE_OR;
+ conn->base_.socket_family = AF_INET;
+ conn->base_.address = tor_strdup("<fake>");
+
+ conn->base_.port = 4242;
+
+ conn->tls = (tor_tls_t *)((void *)(&fake_tortls));
+
+ conn->link_proto = MIN_LINK_PROTO_FOR_CHANNEL_PADDING;
+
+ connection_or_set_canonical(conn, 1);
+}
+
+static channel_tls_t *
+new_fake_channeltls(uint8_t id)
+{
+ channel_tls_t *chan = tor_realloc(new_fake_channel(), sizeof(channel_tls_t));
+ chan->base_.magic = TLS_CHAN_MAGIC;
+ setup_fake_connection_for_channel(chan);
+ chan->base_.channel_usage = CHANNEL_USED_FOR_FULL_CIRCS;
+ chan->base_.has_queued_writes = mock_channel_has_queued_writes;
+ chan->base_.write_cell = mock_channel_write_cell;
+ chan->base_.padding_enabled = 1;
+
+ chan->base_.identity_digest[0] = id;
+ channel_register(&chan->base_);
+
+ return chan;
+}
+
+static void
+free_fake_channeltls(channel_tls_t *chan)
+{
+ channel_unregister(&chan->base_);
+
+ tor_free(((channel_tls_t*)chan)->conn->base_.address);
+ buf_free(((channel_tls_t*)chan)->conn->base_.inbuf);
+ buf_free(((channel_tls_t*)chan)->conn->base_.outbuf);
+ tor_free(((channel_tls_t*)chan)->conn);
+
+ timer_free(chan->base_.padding_timer);
+ channel_handle_free(chan->base_.timer_handle);
+ channel_handles_clear(&chan->base_);
+
+ free_fake_channel(&chan->base_);
+
+ return;
+}
+
+static void
+setup_mock_consensus(void)
+{
+ current_md_consensus = current_ns_consensus
+ = tor_malloc_zero(sizeof(networkstatus_t));
+ current_md_consensus->net_params = smartlist_new();
+ current_md_consensus->routerstatus_list = smartlist_new();
+ channelpadding_new_consensus_params(current_md_consensus);
+}
+
+static void
+free_mock_consensus(void)
+{
+ SMARTLIST_FOREACH(current_md_consensus->routerstatus_list, void *, r,
+ tor_free(r));
+ smartlist_free(current_md_consensus->routerstatus_list);
+ smartlist_free(current_ns_consensus->net_params);
+ tor_free(current_ns_consensus);
+}
+
+static void
+setup_mock_network(void)
+{
+ routerstatus_t *relay;
+ if (!connection_array)
+ connection_array = smartlist_new();
+
+ relay1_relay2 = (channel_t*)new_fake_channeltls(2);
+ relay1_relay2->write_cell = mock_channel_write_cell_relay1;
+ channel_timestamp_active(relay1_relay2);
+ relay = tor_malloc_zero(sizeof(routerstatus_t));
+ relay->identity_digest[0] = 1;
+ smartlist_add(current_md_consensus->routerstatus_list, relay);
+
+ relay2_relay1 = (channel_t*)new_fake_channeltls(1);
+ relay2_relay1->write_cell = mock_channel_write_cell_relay2;
+ channel_timestamp_active(relay2_relay1);
+ relay = tor_malloc_zero(sizeof(routerstatus_t));
+ relay->identity_digest[0] = 2;
+ smartlist_add(current_md_consensus->routerstatus_list, relay);
+
+ relay3_client = (channel_t*)new_fake_channeltls(0);
+ relay3_client->write_cell = mock_channel_write_cell_relay3;
+ relay3_client->is_client = 1;
+ channel_timestamp_active(relay3_client);
+ relay = tor_malloc_zero(sizeof(routerstatus_t));
+ relay->identity_digest[0] = 3;
+ smartlist_add(current_md_consensus->routerstatus_list, relay);
+
+ client_relay3 = (channel_t*)new_fake_channeltls(3);
+ client_relay3->write_cell = mock_channel_write_cell_client;
+ channel_timestamp_active(client_relay3);
+
+ channel_do_open_actions(relay1_relay2);
+ channel_do_open_actions(relay2_relay1);
+ channel_do_open_actions(relay3_client);
+ channel_do_open_actions(client_relay3);
+}
+
+static void
+free_mock_network(void)
+{
+ free_fake_channeltls((channel_tls_t*)relay1_relay2);
+ free_fake_channeltls((channel_tls_t*)relay2_relay1);
+ free_fake_channeltls((channel_tls_t*)relay3_client);
+ free_fake_channeltls((channel_tls_t*)client_relay3);
+
+ smartlist_free(connection_array);
+}
+
+static void
+dummy_timer_cb(tor_timer_t *t, void *arg, const monotime_t *now_mono)
+{
+ (void)t; (void)arg; (void)now_mono;
+ event_base_loopbreak(tor_libevent_get_base());
+ return;
+}
+
+// This hack adds a dummy timer so that the libevent base loop
+// actually returns when we don't expect any timers to fire. Otherwise,
+// the global_timer_event gets scheduled an hour from now, and the
+// base loop never returns.
+void
+dummy_nop_timer(void)
+{
+ tor_timer_t *dummy_timer = timer_new(dummy_timer_cb, NULL);
+ struct timeval timeout;
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
+
+ timer_schedule(dummy_timer, &timeout);
+
+ event_base_loop(tor_libevent_get_base(), 0);
+ timer_free(dummy_timer);
+}
+
+#define CHANNELPADDING_MAX_TIMERS 25
+#define CHANNELS_TO_TEST (CHANNELPADDING_MAX_TIMERS*4)
+/**
+ * Tests to ensure that we handle more than the max number of pending
+ * timers properly.
+ */
+void
+test_channelpadding_timers(void *arg)
+{
+ channelpadding_decision_t decision;
+ channel_t *chans[CHANNELS_TO_TEST];
+ int64_t new_time;
+ (void)arg;
+
+ tor_libevent_postfork();
+
+ if (!connection_array)
+ connection_array = smartlist_new();
+
+ monotime_init();
+ monotime_enable_test_mocking();
+ monotime_set_mock_time_nsec(1);
+ monotime_coarse_set_mock_time_nsec(1);
+
+ timers_initialize();
+ channelpadding_new_consensus_params(NULL);
+
+ for (int i = 0; i < CHANNELS_TO_TEST; i++) {
+ chans[i] = (channel_t*)new_fake_channeltls(0);
+ channel_timestamp_active(chans[i]);
+ }
+
+ for (int j = 0; j < 2; j++) {
+ tried_to_write_cell = 0;
+ int i = 0;
+
+ /* This loop fills our timerslot array with timers of increasing time
+ * until they fire */
+ for (; i < CHANNELPADDING_MAX_TIMERS; i++) {
+ chans[i]->next_padding_time_ms = monotime_coarse_absolute_msec()
+ + 10 + i*4;
+ decision = channelpadding_decide_to_pad_channel(chans[i]);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_SCHEDULED);
+ tt_assert(chans[i]->pending_padding_callback);
+ tt_int_op(tried_to_write_cell, OP_EQ, 0);
+ }
+
+ /* This loop should add timers to the first position in the timerslot
+ * array, since its timeout is before all other timers. */
+ for (; i < CHANNELS_TO_TEST/3; i++) {
+ chans[i]->next_padding_time_ms = monotime_coarse_absolute_msec() + 1;
+ decision = channelpadding_decide_to_pad_channel(chans[i]);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_SCHEDULED);
+ tt_assert(chans[i]->pending_padding_callback);
+ tt_int_op(tried_to_write_cell, OP_EQ, 0);
+ }
+
+ /* This loop should add timers to our existing lists in a weak
+ * pseudorandom pattern. It ensures that the lists can grow with multiple
+ * timers in them. */
+ for (; i < CHANNELS_TO_TEST/2; i++) {
+ chans[i]->next_padding_time_ms = monotime_coarse_absolute_msec() + 10 +
+ i*3 % CHANNELPADDING_MAX_TIMERS;
+ decision = channelpadding_decide_to_pad_channel(chans[i]);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_SCHEDULED);
+ tt_assert(chans[i]->pending_padding_callback);
+ tt_int_op(tried_to_write_cell, OP_EQ, 0);
+ }
+
+ /* This loop should add timers to the last position in the timerslot
+ * array, since its timeout is after all other timers. */
+ for (; i < CHANNELS_TO_TEST; i++) {
+ chans[i]->next_padding_time_ms = monotime_coarse_absolute_msec() + 500 +
+ i % CHANNELPADDING_MAX_TIMERS;
+ decision = channelpadding_decide_to_pad_channel(chans[i]);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_SCHEDULED);
+ tt_assert(chans[i]->pending_padding_callback);
+ tt_int_op(tried_to_write_cell, OP_EQ, 0);
+ }
+
+ // Wait for the timers and then kill the event loop.
+ new_time = (monotime_coarse_absolute_msec()+1001)*NSEC_PER_MSEC;
+ monotime_coarse_set_mock_time_nsec(new_time);
+ monotime_set_mock_time_nsec(new_time);
+ timers_run_pending();
+
+ tt_int_op(tried_to_write_cell, OP_EQ, CHANNELS_TO_TEST);
+
+ // Test that we have no pending callbacks and all empty slots now
+ for (i = 0; i < CHANNELS_TO_TEST; i++) {
+ tt_assert(!chans[i]->pending_padding_callback);
+ }
+ }
+
+ done:
+ for (int i = 0; i < CHANNELS_TO_TEST; i++) {
+ free_fake_channeltls((channel_tls_t*)chans[i]);
+ }
+ smartlist_free(connection_array);
+
+ timers_shutdown();
+ monotime_disable_test_mocking();
+ channel_free_all();
+
+ return;
+}
+
+void
+test_channelpadding_killonehop(void *arg)
+{
+ channelpadding_decision_t decision;
+ int64_t new_time;
+ (void)arg;
+ tor_libevent_postfork();
+
+ routerstatus_t *relay = tor_malloc_zero(sizeof(routerstatus_t));
+ monotime_init();
+ monotime_enable_test_mocking();
+ monotime_set_mock_time_nsec(1);
+ monotime_coarse_set_mock_time_nsec(1);
+
+ timers_initialize();
+ setup_mock_consensus();
+ setup_mock_network();
+
+ /* Do we disable padding if tor2webmode or rsos are enabled, and
+ * the consensus says don't pad? */
+
+ /* Ensure we can kill tor2web and rsos padding if we want. */
+ // First, test that padding works if either is enabled
+ smartlist_clear(current_md_consensus->net_params);
+ channelpadding_new_consensus_params(current_md_consensus);
+
+ tried_to_write_cell = 0;
+ get_options_mutable()->Tor2webMode = 1;
+ client_relay3->next_padding_time_ms = monotime_coarse_absolute_msec() + 100;
+ decision = channelpadding_decide_to_pad_channel(client_relay3);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_SCHEDULED);
+ tt_assert(client_relay3->pending_padding_callback);
+ tt_int_op(tried_to_write_cell, OP_EQ, 0);
+
+ decision = channelpadding_decide_to_pad_channel(client_relay3);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_ALREADY_SCHEDULED);
+
+ // Wait for the timer
+ new_time = (monotime_coarse_absolute_msec()+101)*NSEC_PER_MSEC;
+ monotime_coarse_set_mock_time_nsec(new_time);
+ monotime_set_mock_time_nsec(new_time);
+ timers_run_pending();
+ tt_int_op(tried_to_write_cell, OP_EQ, 1);
+ tt_assert(!client_relay3->pending_padding_callback);
+
+ // Then test disabling each via consensus param
+ smartlist_add(current_md_consensus->net_params,
+ (void*)"nf_pad_tor2web=0");
+ channelpadding_new_consensus_params(current_md_consensus);
+
+ // Before the client tries to pad, the relay will still pad:
+ tried_to_write_cell = 0;
+ relay3_client->next_padding_time_ms = monotime_coarse_absolute_msec() + 100;
+ get_options_mutable()->ORPort_set = 1;
+ get_options_mutable()->Tor2webMode = 0;
+ decision = channelpadding_decide_to_pad_channel(relay3_client);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_SCHEDULED);
+ tt_assert(relay3_client->pending_padding_callback);
+
+ // Wait for the timer
+ new_time = (monotime_coarse_absolute_msec()+101)*NSEC_PER_MSEC;
+ monotime_coarse_set_mock_time_nsec(new_time);
+ monotime_set_mock_time_nsec(new_time);
+ timers_run_pending();
+ tt_int_op(tried_to_write_cell, OP_EQ, 1);
+ tt_assert(!client_relay3->pending_padding_callback);
+
+ // Test client side (it should stop immediately, but send a negotiate)
+ tried_to_write_cell = 0;
+ tt_assert(relay3_client->padding_enabled);
+ tt_assert(client_relay3->padding_enabled);
+ get_options_mutable()->Tor2webMode = 1;
+ /* For the relay to recieve the negotiate: */
+ get_options_mutable()->ORPort_set = 1;
+ decision = channelpadding_decide_to_pad_channel(client_relay3);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_WONTPAD);
+ tt_int_op(tried_to_write_cell, OP_EQ, 1);
+ tt_assert(!client_relay3->pending_padding_callback);
+ tt_assert(!relay3_client->padding_enabled);
+
+ // Test relay side (it should have gotten the negotiation to disable)
+ get_options_mutable()->ORPort_set = 1;
+ get_options_mutable()->Tor2webMode = 0;
+ tt_int_op(channelpadding_decide_to_pad_channel(relay3_client), OP_EQ,
+ CHANNELPADDING_WONTPAD);
+ tt_assert(!relay3_client->padding_enabled);
+
+ /* Repeat for SOS */
+ // First, test that padding works if either is enabled
+ smartlist_clear(current_md_consensus->net_params);
+ channelpadding_new_consensus_params(current_md_consensus);
+
+ relay3_client->padding_enabled = 1;
+ client_relay3->padding_enabled = 1;
+
+ tried_to_write_cell = 0;
+ get_options_mutable()->ORPort_set = 0;
+ get_options_mutable()->HiddenServiceSingleHopMode = 1;
+ get_options_mutable()->HiddenServiceNonAnonymousMode = 1;
+ client_relay3->next_padding_time_ms = monotime_coarse_absolute_msec() + 100;
+ decision = channelpadding_decide_to_pad_channel(client_relay3);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_SCHEDULED);
+ tt_assert(client_relay3->pending_padding_callback);
+ tt_int_op(tried_to_write_cell, OP_EQ, 0);
+
+ decision = channelpadding_decide_to_pad_channel(client_relay3);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_ALREADY_SCHEDULED);
+
+ // Wait for the timer
+ new_time = (monotime_coarse_absolute_msec()+101)*NSEC_PER_MSEC;
+ monotime_coarse_set_mock_time_nsec(new_time);
+ monotime_set_mock_time_nsec(new_time);
+ timers_run_pending();
+ tt_int_op(tried_to_write_cell, OP_EQ, 1);
+ tt_assert(!client_relay3->pending_padding_callback);
+
+ // Then test disabling each via consensus param
+ smartlist_add(current_md_consensus->net_params,
+ (void*)"nf_pad_single_onion=0");
+ channelpadding_new_consensus_params(current_md_consensus);
+
+ // Before the client tries to pad, the relay will still pad:
+ tried_to_write_cell = 0;
+ relay3_client->next_padding_time_ms = monotime_coarse_absolute_msec() + 100;
+ get_options_mutable()->ORPort_set = 1;
+ get_options_mutable()->HiddenServiceSingleHopMode = 0;
+ get_options_mutable()->HiddenServiceNonAnonymousMode = 0;
+ decision = channelpadding_decide_to_pad_channel(relay3_client);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_SCHEDULED);
+ tt_assert(relay3_client->pending_padding_callback);
+
+ // Wait for the timer
+ new_time = (monotime_coarse_absolute_msec()+101)*NSEC_PER_MSEC;
+ monotime_coarse_set_mock_time_nsec(new_time);
+ monotime_set_mock_time_nsec(new_time);
+ timers_run_pending();
+ tt_int_op(tried_to_write_cell, OP_EQ, 1);
+ tt_assert(!client_relay3->pending_padding_callback);
+
+ // Test client side (it should stop immediately)
+ get_options_mutable()->HiddenServiceSingleHopMode = 1;
+ get_options_mutable()->HiddenServiceNonAnonymousMode = 1;
+ /* For the relay to recieve the negotiate: */
+ get_options_mutable()->ORPort_set = 1;
+ decision = channelpadding_decide_to_pad_channel(client_relay3);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_WONTPAD);
+ tt_assert(!client_relay3->pending_padding_callback);
+
+ // Test relay side (it should have gotten the negotiation to disable)
+ get_options_mutable()->ORPort_set = 1;
+ get_options_mutable()->HiddenServiceSingleHopMode = 0;
+ get_options_mutable()->HiddenServiceNonAnonymousMode = 0;
+ tt_int_op(channelpadding_decide_to_pad_channel(relay3_client), OP_EQ,
+ CHANNELPADDING_WONTPAD);
+ tt_assert(!relay3_client->padding_enabled);
+
+ done:
+ free_mock_consensus();
+ free_mock_network();
+ tor_free(relay);
+
+ timers_shutdown();
+ monotime_disable_test_mocking();
+ channel_free_all();
+}
+
+void
+test_channelpadding_consensus(void *arg)
+{
+ channelpadding_decision_t decision;
+ or_options_t *options = get_options_mutable();
+ int64_t val;
+ int64_t new_time;
+ (void)arg;
+
+ tor_libevent_postfork();
+
+ /*
+ * Params tested:
+ * nf_pad_before_usage
+ * nf_pad_relays
+ * nf_ito_low
+ * nf_ito_high
+ *
+ * Plan:
+ * 1. Padding can be completely disabled via consensus
+ * 2. Negotiation can't re-enable consensus-disabled padding
+ * 3. Negotiation can't increase padding from relays beyond
+ * consensus defaults
+ * 4. Relay-to-relay padding can be enabled/disabled in consensus
+ * 5. Can enable/disable padding before actually using a connection
+ * 6. Can we control circ and TLS conn lifetime from the consensus?
+ */
+ channel_t *chan;
+ routerstatus_t *relay = tor_malloc_zero(sizeof(routerstatus_t));
+ monotime_enable_test_mocking();
+ monotime_set_mock_time_nsec(1);
+ monotime_coarse_set_mock_time_nsec(1);
+ timers_initialize();
+
+ if (!connection_array)
+ connection_array = smartlist_new();
+ chan = (channel_t*)new_fake_channeltls(0);
+ channel_timestamp_active(chan);
+
+ setup_mock_consensus();
+
+ get_options_mutable()->ORPort_set = 1;
+
+ /* Test 1: Padding can be completely disabled via consensus */
+ tried_to_write_cell = 0;
+ chan->next_padding_time_ms = monotime_coarse_absolute_msec() + 100;
+ decision = channelpadding_decide_to_pad_channel(chan);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_SCHEDULED);
+ tt_assert(chan->pending_padding_callback);
+ tt_int_op(tried_to_write_cell, OP_EQ, 0);
+
+ decision = channelpadding_decide_to_pad_channel(chan);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_ALREADY_SCHEDULED);
+
+ // Wait for the timer
+ new_time = (monotime_coarse_absolute_msec()+101)*NSEC_PER_MSEC;
+ monotime_coarse_set_mock_time_nsec(new_time);
+ monotime_set_mock_time_nsec(new_time);
+ timers_run_pending();
+ tt_int_op(tried_to_write_cell, OP_EQ, 1);
+ tt_assert(!chan->pending_padding_callback);
+
+ smartlist_add(current_md_consensus->net_params,
+ (void*)"nf_ito_low=0");
+ smartlist_add(current_md_consensus->net_params,
+ (void*)"nf_ito_high=0");
+ get_options_mutable()->ConnectionPadding = 1;
+ channelpadding_new_consensus_params(current_md_consensus);
+
+ decision = channelpadding_decide_to_pad_channel(chan);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_WONTPAD);
+ tt_assert(!chan->pending_padding_callback);
+ val = channelpadding_get_netflow_inactive_timeout_ms(chan);
+ tt_i64_op(val, OP_EQ, 0);
+ val = channelpadding_compute_time_until_pad_for_netflow(chan);
+ tt_i64_op(val, OP_EQ, -2);
+
+ /* Test 2: Negotiation can't re-enable consensus-disabled padding */
+ channelpadding_send_enable_command(chan, 100, 200);
+ tried_to_write_cell = 0;
+ decision = channelpadding_decide_to_pad_channel(chan);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_WONTPAD);
+ tt_assert(!chan->pending_padding_callback);
+ val = channelpadding_get_netflow_inactive_timeout_ms(chan);
+ tt_i64_op(val, OP_EQ, 0);
+ val = channelpadding_compute_time_until_pad_for_netflow(chan);
+ tt_i64_op(val, OP_EQ, -2);
+ tt_assert(!chan->next_padding_time_ms);
+
+ smartlist_clear(current_md_consensus->net_params);
+
+ /* Test 3: Negotiation can't increase padding from relays beyond consensus
+ * values */
+ smartlist_add(current_md_consensus->net_params,
+ (void*)"nf_ito_low=100");
+ smartlist_add(current_md_consensus->net_params,
+ (void*)"nf_ito_high=200");
+ channelpadding_new_consensus_params(current_md_consensus);
+
+ tried_to_write_cell = 0;
+ chan->next_padding_time_ms = monotime_coarse_absolute_msec() + 100;
+ decision = channelpadding_decide_to_pad_channel(chan);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_SCHEDULED);
+ tt_assert(chan->pending_padding_callback);
+ tt_int_op(tried_to_write_cell, OP_EQ, 0);
+ val = channelpadding_get_netflow_inactive_timeout_ms(chan);
+ tt_i64_op(val, OP_GE, 100);
+ tt_i64_op(val, OP_LE, 200);
+ val = channelpadding_compute_time_until_pad_for_netflow(chan);
+ tt_i64_op(val, OP_LE, 200);
+
+ // Wait for the timer
+ new_time = (monotime_coarse_absolute_msec()+201)*NSEC_PER_MSEC;
+ monotime_set_mock_time_nsec(new_time);
+ monotime_coarse_set_mock_time_nsec(new_time);
+ timers_run_pending();
+ tt_int_op(tried_to_write_cell, OP_EQ, 1);
+ tt_assert(!chan->pending_padding_callback);
+
+ smartlist_clear(current_md_consensus->net_params);
+ smartlist_add(current_md_consensus->net_params,
+ (void*)"nf_ito_low=1500");
+ smartlist_add(current_md_consensus->net_params,
+ (void*)"nf_ito_high=4500");
+ channelpadding_new_consensus_params(current_md_consensus);
+
+ channelpadding_send_enable_command(chan, 100, 200);
+ tried_to_write_cell = 0;
+ decision = channelpadding_decide_to_pad_channel(chan);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_PADLATER);
+ tt_assert(!chan->pending_padding_callback);
+ val = channelpadding_get_netflow_inactive_timeout_ms(chan);
+ tt_i64_op(val, OP_GE, 1500);
+ tt_i64_op(val, OP_LE, 4500);
+ val = channelpadding_compute_time_until_pad_for_netflow(chan);
+ tt_i64_op(val, OP_LE, 4500);
+
+ /* Test 4: Relay-to-relay padding can be enabled/disabled in consensus */
+ /* Make this channel a relay's channel */
+ memcpy(relay->identity_digest,
+ ((channel_tls_t *)chan)->conn->identity_digest, DIGEST_LEN);
+ smartlist_add(current_md_consensus->routerstatus_list, relay);
+
+ tried_to_write_cell = 0;
+ decision = channelpadding_decide_to_pad_channel(chan);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_WONTPAD);
+ tt_assert(!chan->pending_padding_callback);
+
+ smartlist_add(current_md_consensus->net_params,
+ (void*)"nf_pad_relays=1");
+ channelpadding_new_consensus_params(current_md_consensus);
+
+ decision = channelpadding_decide_to_pad_channel(chan);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_PADLATER);
+ tt_assert(!chan->pending_padding_callback);
+ val = channelpadding_get_netflow_inactive_timeout_ms(chan);
+ tt_i64_op(val, OP_GE, 1500);
+ tt_i64_op(val, OP_LE, 4500);
+ val = channelpadding_compute_time_until_pad_for_netflow(chan);
+ tt_i64_op(val, OP_LE, 4500);
+
+ /* Test 5: If we disable padding before channel usage, does that work? */
+ smartlist_add(current_md_consensus->net_params,
+ (void*)"nf_pad_before_usage=0");
+ channelpadding_new_consensus_params(current_md_consensus);
+ tried_to_write_cell = 0;
+ decision = channelpadding_decide_to_pad_channel(chan);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_WONTPAD);
+ tt_assert(!chan->pending_padding_callback);
+
+ /* Test 6: Can we control circ and TLS conn lifetime from the consensus? */
+ val = channelpadding_get_channel_idle_timeout(NULL, 0);
+ tt_i64_op(val, OP_GE, 180);
+ tt_i64_op(val, OP_LE, 180+90);
+ val = channelpadding_get_channel_idle_timeout(chan, 0);
+ tt_i64_op(val, OP_GE, 180);
+ tt_i64_op(val, OP_LE, 180+90);
+ options->ReducedConnectionPadding = 1;
+ val = channelpadding_get_channel_idle_timeout(chan, 0);
+ tt_i64_op(val, OP_GE, 180/2);
+ tt_i64_op(val, OP_LE, (180+90)/2);
+
+ options->ReducedConnectionPadding = 0;
+ options->ORPort_set = 1;
+ smartlist_add(current_md_consensus->net_params,
+ (void*)"nf_conntimeout_relays=600");
+ channelpadding_new_consensus_params(current_md_consensus);
+ val = channelpadding_get_channel_idle_timeout(chan, 1);
+ tt_i64_op(val, OP_GE, 450);
+ tt_i64_op(val, OP_LE, 750);
+
+ val = channelpadding_get_circuits_available_timeout();
+ tt_i64_op(val, OP_GE, 30*60);
+ tt_i64_op(val, OP_LE, 30*60*2);
+
+ options->ReducedConnectionPadding = 1;
+ smartlist_add(current_md_consensus->net_params,
+ (void*)"nf_conntimeout_clients=600");
+ channelpadding_new_consensus_params(current_md_consensus);
+ val = channelpadding_get_circuits_available_timeout();
+ tt_i64_op(val, OP_GE, 600/2);
+ tt_i64_op(val, OP_LE, 600*2/2);
+
+ options->ReducedConnectionPadding = 0;
+ options->CircuitsAvailableTimeout = 24*60*60;
+ val = channelpadding_get_circuits_available_timeout();
+ tt_i64_op(val, OP_GE, 24*60*60);
+ tt_i64_op(val, OP_LE, 24*60*60*2);
+
+ done:
+ free_mock_consensus();
+ free_fake_channeltls((channel_tls_t*)chan);
+ smartlist_free(connection_array);
+
+ timers_shutdown();
+ monotime_disable_test_mocking();
+ channel_free_all();
+
+ return;
+}
+
+void
+test_channelpadding_negotiation(void *arg)
+{
+ channelpadding_negotiate_t disable;
+ cell_t cell;
+ channelpadding_decision_t decision;
+ int val;
+ (void)arg;
+
+ /* Plan:
+ * 1. Clients reject negotiation, relays accept it.
+ * * Bridges accept negotiation from their clients,
+ * but not from relays.
+ * 2. Torrc options can override client-side negotiation
+ * 3. Test a version issue in channelpadidng cell
+ * 4. Test channelpadding_reduced_padding
+ */
+ monotime_init();
+ monotime_enable_test_mocking();
+ monotime_set_mock_time_nsec(1);
+ monotime_coarse_set_mock_time_nsec(1);
+ timers_initialize();
+ setup_mock_consensus();
+ setup_mock_network();
+
+ /* Test case #1: Do the right things ignore negotiation? */
+ /* relay-to-client case: */
+ channelpadding_send_disable_command(relay3_client);
+ tt_assert(client_relay3->padding_enabled);
+
+ /* client-to-relay case: */
+ get_options_mutable()->ORPort_set = 1;
+ channelpadding_disable_padding_on_channel(client_relay3);
+ tt_int_op(channelpadding_decide_to_pad_channel(relay3_client), OP_EQ,
+ CHANNELPADDING_WONTPAD);
+ tt_assert(!relay3_client->padding_enabled);
+ relay3_client->padding_enabled = 1;
+ client_relay3->padding_enabled = 1;
+
+ /* Bridge case from relay */
+ get_options_mutable()->BridgeRelay = 1;
+ channelpadding_disable_padding_on_channel(relay2_relay1);
+ tt_assert(relay1_relay2->padding_enabled);
+
+ /* Bridge case from client */
+ channelpadding_disable_padding_on_channel(client_relay3);
+ tt_assert(!relay3_client->padding_enabled);
+ tt_int_op(channelpadding_decide_to_pad_channel(relay3_client), OP_EQ,
+ CHANNELPADDING_WONTPAD);
+ relay3_client->padding_enabled = 1;
+ client_relay3->padding_enabled = 1;
+ get_options_mutable()->BridgeRelay = 0;
+ get_options_mutable()->ORPort_set = 0;
+
+ /* Test case #2: Torrc options */
+ /* ConnectionPadding auto; Relay doesn't suport us */
+ ((channel_tls_t*)relay3_client)->conn->link_proto = 4;
+ relay3_client->padding_enabled = 0;
+ tried_to_write_cell = 0;
+ decision = channelpadding_decide_to_pad_channel(relay3_client);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_WONTPAD);
+ tt_assert(!relay3_client->pending_padding_callback);
+ tt_int_op(tried_to_write_cell, OP_EQ, 0);
+ ((channel_tls_t*)relay3_client)->conn->link_proto = 5;
+ relay3_client->padding_enabled = 1;
+
+ /* ConnectionPadding 1; Relay doesn't suport us */
+ get_options_mutable()->ConnectionPadding = 1;
+ tried_to_write_cell = 0;
+ decision = channelpadding_decide_to_pad_channel(client_relay3);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_PADLATER);
+ tt_assert(!client_relay3->pending_padding_callback);
+ tt_int_op(tried_to_write_cell, OP_EQ, 0);
+ get_options_mutable()->ConnectionPadding = 0;
+
+ /* Test case #3: Test a version issue in channelpadding cell */
+ get_options_mutable()->ORPort_set = 1;
+ client_relay3->padding_enabled = 1;
+ relay3_client->padding_enabled = 1;
+ memset(&cell, 0, sizeof(cell_t));
+ memset(&disable, 0, sizeof(channelpadding_negotiate_t));
+ cell.command = CELL_PADDING_NEGOTIATE;
+
+ channelpadding_negotiate_set_command(&disable, CHANNELPADDING_COMMAND_STOP);
+ disable.version = 1;
+ channelpadding_negotiate_encode(cell.payload, CELL_PAYLOAD_SIZE, &disable);
+ client_relay3->write_cell(client_relay3, &cell);
+ tt_assert(relay3_client->padding_enabled);
+ tt_int_op(channelpadding_update_padding_for_channel(client_relay3, &disable),
+ OP_EQ, -1);
+ tt_assert(client_relay3->padding_enabled);
+
+ disable.version = 0;
+ channelpadding_negotiate_encode(cell.payload, CELL_PAYLOAD_SIZE, &disable);
+ client_relay3->write_cell(client_relay3, &cell);
+ tt_assert(!relay3_client->padding_enabled);
+
+ /* Test case 4: Reducing padding actually reduces it */
+ relay3_client->padding_enabled = 1;
+ client_relay3->padding_enabled = 1;
+
+ decision = channelpadding_decide_to_pad_channel(relay3_client);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_PADLATER);
+
+ channelpadding_reduce_padding_on_channel(client_relay3);
+
+ tried_to_write_cell = 0;
+ decision = channelpadding_decide_to_pad_channel(relay3_client);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_WONTPAD);
+
+ get_options_mutable()->ORPort_set = 0;
+ decision = channelpadding_decide_to_pad_channel(client_relay3);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_PADLATER);
+
+ tt_assert(!client_relay3->pending_padding_callback);
+ val = channelpadding_get_netflow_inactive_timeout_ms(client_relay3);
+ tt_int_op(val, OP_GE, 9000);
+ tt_int_op(val, OP_LE, 14000);
+ int64_t val64 =
+ channelpadding_compute_time_until_pad_for_netflow(client_relay3);
+ tt_i64_op(val64, OP_LE, 14000);
+
+ done:
+ free_mock_network();
+ free_mock_consensus();
+
+ timers_shutdown();
+ monotime_disable_test_mocking();
+ channel_free_all();
+
+ return;
+}
+
+void
+test_channelpadding_decide_to_pad_channel(void *arg)
+{
+ channelpadding_decision_t decision;
+ /**
+ * Test case plan:
+ *
+ * 1. Channel that has "sent a packet" before the timeout.
+ * + We should decide to pad later
+ * 2. Channel that has not "sent a packet" before the timeout:
+ * 2a. Not within 1.1s of the timeout.
+ * + We should decide to pad later
+ * 2b. Within 1.1s of the timemout.
+ * + We should schedule padding
+ * + We should get feedback that we wrote a cell
+ * 2c. Within 0.1s of the timeout.
+ * + We should schedule padding
+ * + We should get feedback that we wrote a cell
+ * 2d. Channel that asks to pad while timeout is scheduled
+ * + We should schedule padding
+ * + We should get feedback that we wrote a cell
+ * 2e. 0s of the timeout
+ * + We should send padding immediately
+ * + We should get feedback that we wrote a cell
+ * 2f. <0s of the timeout
+ * + We should send padding immediately
+ * + We should get feedback that we wrote a cell
+ * 3. Channel that sends a packet while timeout is scheduled
+ * + We should not get feedback that we wrote a cell
+ * 4. Channel that closes while timeout is scheduled
+ * + We should not get feedback that we wrote a cell
+ * 5. Make sure the channel still would work if repaired
+ * + We should be able to schedule padding and resend
+ * 6. Channel is not used for full circuits
+ * 7. Channel that disappears while timeout is scheduled
+ * + We should not send padding
+ */
+ channel_t *chan;
+ int64_t new_time;
+ if (!connection_array)
+ connection_array = smartlist_new();
+ (void)arg;
+
+ tor_libevent_postfork();
+
+ monotime_init();
+ monotime_enable_test_mocking();
+ monotime_set_mock_time_nsec(1);
+ monotime_coarse_set_mock_time_nsec(1);
+ timers_initialize();
+ setup_full_capture_of_logs(LOG_WARN);
+ channelpadding_new_consensus_params(NULL);
+
+ chan = (channel_t*)new_fake_channeltls(0);
+ channel_timestamp_active(chan);
+
+ /* Test case #1: Channel that has "sent a packet" before the timeout. */
+ tried_to_write_cell = 0;
+ decision = channelpadding_decide_to_pad_channel(chan);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_PADLATER);
+ tt_assert(!chan->pending_padding_callback);
+ tt_int_op(tried_to_write_cell, OP_EQ, 0);
+
+ /* Test case #2a: > 1.1s until timeout */
+ tried_to_write_cell = 0;
+ chan->next_padding_time_ms = monotime_coarse_absolute_msec() + 1200;
+ decision = channelpadding_decide_to_pad_channel(chan);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_PADLATER);
+ tt_assert(!chan->pending_padding_callback);
+ tt_int_op(tried_to_write_cell, OP_EQ, 0);
+
+ /* Test case #2b: >= 1.0s until timeout */
+ tried_to_write_cell = 0;
+ chan->next_padding_time_ms = monotime_coarse_absolute_msec() + 1000;
+ decision = channelpadding_decide_to_pad_channel(chan);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_SCHEDULED);
+ tt_assert(chan->pending_padding_callback);
+ tt_int_op(tried_to_write_cell, OP_EQ, 0);
+
+ // Wait for the timer from case #2b
+ new_time = (monotime_coarse_absolute_msec() + 1000)*NSEC_PER_MSEC;
+ monotime_set_mock_time_nsec(new_time);
+ monotime_coarse_set_mock_time_nsec(new_time);
+ timers_run_pending();
+ tt_int_op(tried_to_write_cell, OP_EQ, 1);
+ tt_assert(!chan->pending_padding_callback);
+
+ /* Test case #2c: > 0.1s until timeout */
+ tried_to_write_cell = 0;
+ chan->next_padding_time_ms = monotime_coarse_absolute_msec() + 100;
+ decision = channelpadding_decide_to_pad_channel(chan);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_SCHEDULED);
+ tt_assert(chan->pending_padding_callback);
+ tt_int_op(tried_to_write_cell, OP_EQ, 0);
+
+ /* Test case #2d: Channel that asks to pad while timeout is scheduled */
+ decision = channelpadding_decide_to_pad_channel(chan);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_ALREADY_SCHEDULED);
+
+ // Wait for the timer
+ new_time = (monotime_coarse_absolute_msec()+101)*NSEC_PER_MSEC;
+ monotime_coarse_set_mock_time_nsec(new_time);
+ monotime_set_mock_time_nsec(new_time);
+ timers_run_pending();
+ tt_int_op(tried_to_write_cell, OP_EQ, 1);
+ tt_assert(!chan->pending_padding_callback);
+
+ /* Test case #2e: 0s until timeout */
+ tried_to_write_cell = 0;
+ chan->next_padding_time_ms = monotime_coarse_absolute_msec();
+ decision = channelpadding_decide_to_pad_channel(chan);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_SENT);
+ tt_int_op(tried_to_write_cell, OP_EQ, 1);
+ tt_assert(!chan->pending_padding_callback);
+
+ /* Test case #2f: <0s until timeout */
+ tried_to_write_cell = 0;
+ chan->next_padding_time_ms = monotime_coarse_absolute_msec() - 100;
+ decision = channelpadding_decide_to_pad_channel(chan);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_SENT);
+ tt_int_op(tried_to_write_cell, OP_EQ, 1);
+ tt_assert(!chan->pending_padding_callback);
+
+ /* Test case #3: Channel that sends a packet while timeout is scheduled */
+ tried_to_write_cell = 0;
+ chan->next_padding_time_ms = monotime_coarse_absolute_msec() + 100;
+ decision = channelpadding_decide_to_pad_channel(chan);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_SCHEDULED);
+ tt_int_op(tried_to_write_cell, OP_EQ, 0);
+ tt_assert(chan->pending_padding_callback);
+
+ // Pretend the channel sent a packet
+ channel_timestamp_active(chan);
+
+ // We don't expect any timer callbacks here. Make a dummy one to be sure.
+ // Wait for the timer
+ new_time = (monotime_coarse_absolute_msec()+101)*NSEC_PER_MSEC;
+ monotime_coarse_set_mock_time_nsec(new_time);
+ monotime_set_mock_time_nsec(new_time);
+ timers_run_pending();
+
+ tt_int_op(tried_to_write_cell, OP_EQ, 0);
+ tt_assert(!chan->pending_padding_callback);
+
+ /* Test case #4: Channel that closes while a timeout is scheduled */
+ tried_to_write_cell = 0;
+ chan->next_padding_time_ms = monotime_coarse_absolute_msec() + 100;
+ decision = channelpadding_decide_to_pad_channel(chan);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_SCHEDULED);
+ tt_int_op(tried_to_write_cell, OP_EQ, 0);
+ tt_assert(chan->pending_padding_callback);
+
+ // Pretend the channel is temporarily down
+ chan->state = CHANNEL_STATE_MAINT;
+
+ // We don't expect any timer callbacks here. Make a dummy one to be sure.
+ new_time = (monotime_coarse_absolute_msec()+101)*NSEC_PER_MSEC;
+ monotime_coarse_set_mock_time_nsec(new_time);
+ monotime_set_mock_time_nsec(new_time);
+ timers_run_pending();
+
+ tt_int_op(tried_to_write_cell, OP_EQ, 0);
+ tt_assert(!chan->pending_padding_callback);
+ chan->state = CHANNEL_STATE_OPEN;
+
+ /* Test case #5: Make sure previous test case didn't break everything */
+ tried_to_write_cell = 0;
+ chan->next_padding_time_ms = monotime_coarse_absolute_msec() + 100;
+ decision = channelpadding_decide_to_pad_channel(chan);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_SCHEDULED);
+ tt_assert(chan->pending_padding_callback);
+ tt_int_op(tried_to_write_cell, OP_EQ, 0);
+
+ // Wait for the timer
+ new_time = (monotime_coarse_absolute_msec()+101)*NSEC_PER_MSEC;
+ monotime_coarse_set_mock_time_nsec(new_time);
+ monotime_set_mock_time_nsec(new_time);
+ timers_run_pending();
+
+ tt_int_op(tried_to_write_cell, OP_EQ, 1);
+ tt_assert(!chan->pending_padding_callback);
+
+ /* Test case #6. Channel is not used for full circuits */
+ chan->channel_usage = CHANNEL_USED_NOT_USED_FOR_FULL_CIRCS;
+ decision = channelpadding_decide_to_pad_channel(chan);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_WONTPAD);
+ tt_assert(!chan->pending_padding_callback);
+ chan->channel_usage = CHANNEL_USED_FOR_FULL_CIRCS;
+
+ /* Test case #7. Channel is closed while timeout is scheduled.
+ *
+ * NOTE: This test deliberately breaks the channel callback mechanism.
+ * It must be last.
+ */
+ tried_to_write_cell = 0;
+ chan->next_padding_time_ms = monotime_coarse_absolute_msec() + 100;
+ decision = channelpadding_decide_to_pad_channel(chan);
+ tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_SCHEDULED);
+ tt_int_op(tried_to_write_cell, OP_EQ, 0);
+ tt_assert(chan->pending_padding_callback);
+
+ // Close the connection while the timer is scheduled
+ free_fake_channeltls((channel_tls_t*)chan);
+
+ // We don't expect any timer callbacks here. Make a dummy one to be sure.
+ new_time = (monotime_coarse_absolute_msec()+101)*NSEC_PER_MSEC;
+ monotime_coarse_set_mock_time_nsec(new_time);
+ monotime_set_mock_time_nsec(new_time);
+ timers_run_pending();
+
+ tt_int_op(tried_to_write_cell, OP_EQ, 0);
+
+ done:
+ smartlist_free(connection_array);
+
+ teardown_capture_of_logs();
+ monotime_disable_test_mocking();
+ timers_shutdown();
+ channel_free_all();
+
+ return;
+}
+
+#define TEST_CHANNELPADDING(name, flags) \
+ { #name, test_##name, (flags), NULL, NULL }
+
+struct testcase_t channelpadding_tests[] = {
+ //TEST_CHANNELPADDING(channelpadding_decide_to_pad_channel, 0),
+ TEST_CHANNELPADDING(channelpadding_decide_to_pad_channel, TT_FORK),
+ TEST_CHANNELPADDING(channelpadding_negotiation, TT_FORK),
+ TEST_CHANNELPADDING(channelpadding_consensus, TT_FORK),
+ TEST_CHANNELPADDING(channelpadding_killonehop, TT_FORK),
+ TEST_CHANNELPADDING(channelpadding_timers, TT_FORK),
+ END_OF_TESTCASES
+};
+
diff --git a/src/test/test_channeltls.c b/src/test/test_channeltls.c
index fd98ee40fb..94f1893cae 100644
--- a/src/test/test_channeltls.c
+++ b/src/test/test_channeltls.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Tor Project, Inc. */
+/* Copyright (c) 2014-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -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 fbb33f87f6..bf6a8376b3 100644
--- a/src/test/test_checkdir.c
+++ b/src/test/test_checkdir.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Tor Project, Inc. */
+/* Copyright (c) 2014-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -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_circuitbuild.c b/src/test/test_circuitbuild.c
new file mode 100644
index 0000000000..a5282df69d
--- /dev/null
+++ b/src/test/test_circuitbuild.c
@@ -0,0 +1,133 @@
+/* Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2016, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#define CIRCUITBUILD_PRIVATE
+
+#include "or.h"
+#include "test.h"
+#include "test_helpers.h"
+#include "log_test_helpers.h"
+#include "config.h"
+#include "circuitbuild.h"
+
+/* Dummy nodes smartlist for testing */
+static smartlist_t dummy_nodes;
+/* Dummy exit extend_info for testing */
+static extend_info_t dummy_ei;
+
+static int
+mock_count_acceptable_nodes(smartlist_t *nodes)
+{
+ (void)nodes;
+
+ return DEFAULT_ROUTE_LEN + 1;
+}
+
+/* Test route lengths when the caller of new_route_len() doesn't
+ * specify exit_ei. */
+static void
+test_new_route_len_noexit(void *arg)
+{
+ int r;
+
+ (void)arg;
+ MOCK(count_acceptable_nodes, mock_count_acceptable_nodes);
+
+ r = new_route_len(CIRCUIT_PURPOSE_C_GENERAL, NULL, &dummy_nodes);
+ tt_int_op(DEFAULT_ROUTE_LEN, OP_EQ, r);
+
+ r = new_route_len(CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT, NULL, &dummy_nodes);
+ tt_int_op(DEFAULT_ROUTE_LEN, OP_EQ, r);
+
+ r = new_route_len(CIRCUIT_PURPOSE_S_CONNECT_REND, NULL, &dummy_nodes);
+ tt_int_op(DEFAULT_ROUTE_LEN, OP_EQ, r);
+
+ done:
+ UNMOCK(count_acceptable_nodes);
+}
+
+/* Test route lengths where someone else chose the "exit" node, which
+ * require an extra hop for safety. */
+static void
+test_new_route_len_unsafe_exit(void *arg)
+{
+ int r;
+
+ (void)arg;
+ MOCK(count_acceptable_nodes, mock_count_acceptable_nodes);
+
+ /* connecting to hidden service directory */
+ r = new_route_len(CIRCUIT_PURPOSE_C_GENERAL, &dummy_ei, &dummy_nodes);
+ tt_int_op(DEFAULT_ROUTE_LEN + 1, OP_EQ, r);
+
+ /* client connecting to introduction point */
+ r = new_route_len(CIRCUIT_PURPOSE_C_INTRODUCING, &dummy_ei, &dummy_nodes);
+ tt_int_op(DEFAULT_ROUTE_LEN + 1, OP_EQ, r);
+
+ /* hidden service connecting to rendezvous point */
+ r = new_route_len(CIRCUIT_PURPOSE_S_CONNECT_REND, &dummy_ei, &dummy_nodes);
+ tt_int_op(DEFAULT_ROUTE_LEN + 1, OP_EQ, r);
+
+ done:
+ UNMOCK(count_acceptable_nodes);
+}
+
+/* Test route lengths where we chose the "exit" node, which don't
+ * require an extra hop for safety. */
+static void
+test_new_route_len_safe_exit(void *arg)
+{
+ int r;
+
+ (void)arg;
+ MOCK(count_acceptable_nodes, mock_count_acceptable_nodes);
+
+ /* hidden service connecting to introduction point */
+ r = new_route_len(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO, &dummy_ei,
+ &dummy_nodes);
+ tt_int_op(DEFAULT_ROUTE_LEN, OP_EQ, r);
+
+ /* router testing its own reachability */
+ r = new_route_len(CIRCUIT_PURPOSE_TESTING, &dummy_ei, &dummy_nodes);
+ tt_int_op(DEFAULT_ROUTE_LEN, OP_EQ, r);
+
+ done:
+ UNMOCK(count_acceptable_nodes);
+}
+
+/* Make sure a non-fatal assertion fails when new_route_len() gets an
+ * unexpected circuit purpose. */
+static void
+test_new_route_len_unhandled_exit(void *arg)
+{
+ int r;
+
+ (void)arg;
+ MOCK(count_acceptable_nodes, mock_count_acceptable_nodes);
+
+ tor_capture_bugs_(1);
+ setup_full_capture_of_logs(LOG_WARN);
+ r = new_route_len(CIRCUIT_PURPOSE_CONTROLLER, &dummy_ei, &dummy_nodes);
+ tt_int_op(DEFAULT_ROUTE_LEN + 1, OP_EQ, r);
+ 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,
+ "!(exit_ei && !known_purpose)");
+ expect_single_log_msg_containing("Unhandled purpose");
+ expect_single_log_msg_containing("with a chosen exit; assuming routelen");
+ teardown_capture_of_logs();
+ tor_end_capture_bugs_();
+
+ done:
+ UNMOCK(count_acceptable_nodes);
+}
+
+struct testcase_t circuitbuild_tests[] = {
+ { "noexit", test_new_route_len_noexit, 0, NULL, NULL },
+ { "safe_exit", test_new_route_len_safe_exit, 0, NULL, NULL },
+ { "unsafe_exit", test_new_route_len_unsafe_exit, 0, NULL, NULL },
+ { "unhandled_exit", test_new_route_len_unhandled_exit, 0, NULL, NULL },
+ END_OF_TESTCASES
+};
+
diff --git a/src/test/test_circuitlist.c b/src/test/test_circuitlist.c
index 7eed5fe225..f622704ec5 100644
--- a/src/test/test_circuitlist.c
+++ b/src/test/test_circuitlist.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Tor Project, Inc. */
+/* Copyright (c) 2013-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define TOR_CHANNEL_INTERNAL_
@@ -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');
@@ -201,68 +203,75 @@ test_rend_token_maps(void *arg)
tt_int_op(tok3[REND_TOKEN_LEN-1], OP_EQ, '.');
/* No maps; nothing there. */
- tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ(tok1));
- tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2(tok1));
+ tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok1));
+ tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok1));
- hs_circuitmap_register_rend_circ(c1, tok1);
- hs_circuitmap_register_intro_circ_v2(c2, tok2);
+ hs_circuitmap_register_rend_circ_relay_side(c1, tok1);
+ hs_circuitmap_register_intro_circ_v2_relay_side(c2, tok2);
- tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ(tok3));
- tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2(tok3));
- tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ(tok2));
- tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2(tok1));
+ tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok3));
+ tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok3));
+ tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok2));
+ tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok1));
/* Without purpose set, we don't get the circuits */
- tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ(tok1));
- tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2(tok2));
+ tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok1));
+ tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok2));
c1->base_.purpose = CIRCUIT_PURPOSE_REND_POINT_WAITING;
c2->base_.purpose = CIRCUIT_PURPOSE_INTRO_POINT;
/* Okay, make sure they show up now. */
- tt_ptr_op(c1, OP_EQ, hs_circuitmap_get_rend_circ(tok1));
- tt_ptr_op(c2, OP_EQ, hs_circuitmap_get_intro_circ_v2(tok2));
+ tt_ptr_op(c1, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok1));
+ tt_ptr_op(c2, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok2));
/* Two items at the same place with the same token. */
c3->base_.purpose = CIRCUIT_PURPOSE_REND_POINT_WAITING;
- hs_circuitmap_register_rend_circ(c3, tok2);
- tt_ptr_op(c2, OP_EQ, hs_circuitmap_get_intro_circ_v2(tok2));
- tt_ptr_op(c3, OP_EQ, hs_circuitmap_get_rend_circ(tok2));
+ hs_circuitmap_register_rend_circ_relay_side(c3, tok2);
+ tt_ptr_op(c2, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok2));
+ tt_ptr_op(c3, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok2));
/* Marking a circuit makes it not get returned any more */
circuit_mark_for_close(TO_CIRCUIT(c1), END_CIRC_REASON_FINISHED);
- tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ(tok1));
+ tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok1));
circuit_free(TO_CIRCUIT(c1));
c1 = NULL;
/* Freeing a circuit makes it not get returned any more. */
circuit_free(TO_CIRCUIT(c2));
c2 = NULL;
- tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2(tok2));
+ tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok2));
/* c3 -- are you still there? */
- tt_ptr_op(c3, OP_EQ, hs_circuitmap_get_rend_circ(tok2));
+ tt_ptr_op(c3, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok2));
/* Change its cookie. This never happens in Tor per se, but hey. */
c3->base_.purpose = CIRCUIT_PURPOSE_INTRO_POINT;
- hs_circuitmap_register_intro_circ_v2(c3, tok3);
+ hs_circuitmap_register_intro_circ_v2_relay_side(c3, tok3);
- tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ(tok2));
- tt_ptr_op(c3, OP_EQ, hs_circuitmap_get_intro_circ_v2(tok3));
+ tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok2));
+ tt_ptr_op(c3, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok3));
/* Now replace c3 with c4. */
c4->base_.purpose = CIRCUIT_PURPOSE_INTRO_POINT;
- hs_circuitmap_register_intro_circ_v2(c4, tok3);
+ hs_circuitmap_register_intro_circ_v2_relay_side(c4, tok3);
- tt_ptr_op(c4, OP_EQ, hs_circuitmap_get_intro_circ_v2(tok3));
+ tt_ptr_op(c4, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok3));
- tt_ptr_op(c3->hs_token, OP_EQ, NULL);
- tt_ptr_op(c4->hs_token, OP_NE, NULL);
- tt_mem_op(c4->hs_token->token, OP_EQ, tok3, REND_TOKEN_LEN);
+ tt_ptr_op(TO_CIRCUIT(c3)->hs_token, OP_EQ, NULL);
+ tt_ptr_op(TO_CIRCUIT(c4)->hs_token, OP_NE, NULL);
+ tt_mem_op(TO_CIRCUIT(c4)->hs_token->token, OP_EQ, tok3, REND_TOKEN_LEN);
/* Now clear c4's cookie. */
- hs_circuitmap_remove_circuit(c4);
- tt_ptr_op(c4->hs_token, OP_EQ, NULL);
- tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2(tok3));
+ hs_circuitmap_remove_circuit(TO_CIRCUIT(c4));
+ 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)
@@ -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
@@ -370,10 +381,89 @@ test_pick_circid(void *arg)
UNMOCK(channel_dump_statistics);
}
+/** Test that the circuit pools of our HS circuitmap are isolated based on
+ * their token type. */
+static void
+test_hs_circuitmap_isolation(void *arg)
+{
+ or_circuit_t *circ1 = NULL;
+ origin_circuit_t *circ2 = NULL;
+ or_circuit_t *circ3 = NULL;
+ origin_circuit_t *circ4 = NULL;
+
+ (void)arg;
+
+ hs_circuitmap_init();
+
+ {
+ const uint8_t tok1[REND_TOKEN_LEN] = "bet i got some of th";
+
+ circ1 = or_circuit_new(0, NULL);
+ tt_assert(circ1);
+ circ1->base_.purpose = CIRCUIT_PURPOSE_REND_POINT_WAITING;
+
+ /* check that circuitmap is empty right? */
+ tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok1));
+
+ /* Register circ1 with tok1 as relay-side rend circ */
+ hs_circuitmap_register_rend_circ_relay_side(circ1, tok1);
+
+ /* check that service-side getters don't work */
+ tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_service_side(tok1));
+ tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2_service_side(tok1));
+
+ /* Check that the right getter works. */
+ tt_ptr_op(circ1, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok1));
+ }
+
+ {
+ const uint8_t tok2[REND_TOKEN_LEN] = "you dont know anythi";
+
+ circ2 = origin_circuit_new();
+ tt_assert(circ2);
+ circ2->base_.purpose = CIRCUIT_PURPOSE_S_ESTABLISH_INTRO;
+ circ3 = or_circuit_new(0, NULL);
+ tt_assert(circ3);
+ circ3->base_.purpose = CIRCUIT_PURPOSE_INTRO_POINT;
+ circ4 = origin_circuit_new();
+ tt_assert(circ4);
+ circ4->base_.purpose = CIRCUIT_PURPOSE_S_ESTABLISH_INTRO;
+
+ /* Register circ2 with tok2 as service-side intro v2 circ */
+ hs_circuitmap_register_intro_circ_v2_service_side(circ2, tok2);
+ /* Register circ3 with tok2 again but for different purpose */
+ hs_circuitmap_register_intro_circ_v2_relay_side(circ3, tok2);
+
+ /* Check that the getters work */
+ tt_ptr_op(circ2, OP_EQ,
+ hs_circuitmap_get_intro_circ_v2_service_side(tok2));
+ tt_ptr_op(circ3, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok2));
+
+ /* Register circ4 with tok2: it should override circ2 */
+ hs_circuitmap_register_intro_circ_v2_service_side(circ4, tok2);
+
+ /* check that relay-side getters don't work */
+ tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok2));
+
+ /* Check that the getter returns circ4; the last circuit registered with
+ * that token. */
+ tt_ptr_op(circ4, OP_EQ,
+ hs_circuitmap_get_intro_circ_v2_service_side(tok2));
+ }
+
+ done:
+ circuit_free(TO_CIRCUIT(circ1));
+ circuit_free(TO_CIRCUIT(circ2));
+ circuit_free(TO_CIRCUIT(circ3));
+ circuit_free(TO_CIRCUIT(circ4));
+}
+
struct testcase_t circuitlist_tests[] = {
{ "maps", test_clist_maps, TT_FORK, NULL, NULL },
{ "rend_token_maps", test_rend_token_maps, TT_FORK, NULL, NULL },
{ "pick_circid", test_pick_circid, TT_FORK, NULL, NULL },
+ { "hs_circuitmap_isolation", test_hs_circuitmap_isolation,
+ TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
diff --git a/src/test/test_circuitmux.c b/src/test/test_circuitmux.c
index 9e8fb54964..c5f4f67fa0 100644
--- a/src/test/test_circuitmux.c
+++ b/src/test/test_circuitmux.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Tor Project, Inc. */
+/* Copyright (c) 2013-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define TOR_CHANNEL_INTERNAL_
@@ -48,8 +48,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);
@@ -58,7 +58,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 27a87660ff..df1b43807f 100644
--- a/src/test/test_circuituse.c
+++ b/src/test/test_circuituse.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CIRCUITLIST_PRIVATE
@@ -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_compat_libevent.c b/src/test/test_compat_libevent.c
index 0443cc0b1c..7dd8e65194 100644
--- a/src/test/test_compat_libevent.c
+++ b/src/test/test_compat_libevent.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2016, The Tor Project, Inc. */
+/* Copyright (c) 2010-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define COMPAT_LIBEVENT_PRIVATE
diff --git a/src/test/test_config.c b/src/test/test_config.c
index 3c2b52ca00..456d8bcc3e 100644
--- a/src/test/test_config.c
+++ b/src/test/test_config.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -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.
@@ -854,9 +855,23 @@ static void
test_config_fix_my_family(void *arg)
{
char *err = NULL;
- const char *family = "$1111111111111111111111111111111111111111, "
- "1111111111111111111111111111111111111112, "
- "$1111111111111111111111111111111111111113";
+ config_line_t *family = tor_malloc_zero(sizeof(config_line_t));
+ family->key = tor_strdup("MyFamily");
+ family->value = tor_strdup("$1111111111111111111111111111111111111111, "
+ "1111111111111111111111111111111111111112, "
+ "$1111111111111111111111111111111111111113");
+
+ config_line_t *family2 = tor_malloc_zero(sizeof(config_line_t));
+ family2->key = tor_strdup("MyFamily");
+ family2->value = tor_strdup("1111111111111111111111111111111111111114");
+
+ config_line_t *family3 = tor_malloc_zero(sizeof(config_line_t));
+ family3->key = tor_strdup("MyFamily");
+ family3->value = tor_strdup("$1111111111111111111111111111111111111115");
+
+ family->next = family2;
+ family2->next = family3;
+ family3->next = NULL;
or_options_t* options = options_new();
or_options_t* defaults = options_new();
@@ -864,7 +879,7 @@ test_config_fix_my_family(void *arg)
options_init(options);
options_init(defaults);
- options->MyFamily = tor_strdup(family);
+ options->MyFamily_lines = family;
options_validate(NULL, options, defaults, 0, &err) ;
@@ -872,18 +887,23 @@ test_config_fix_my_family(void *arg)
TT_FAIL(("options_validate failed: %s", err));
}
- tt_str_op(options->MyFamily,OP_EQ,
- "$1111111111111111111111111111111111111111, "
- "$1111111111111111111111111111111111111112, "
- "$1111111111111111111111111111111111111113");
-
- done:
- if (err != NULL) {
- tor_free(err);
- }
+ const char *valid[] = { "$1111111111111111111111111111111111111111",
+ "$1111111111111111111111111111111111111112",
+ "$1111111111111111111111111111111111111113",
+ "$1111111111111111111111111111111111111114",
+ "$1111111111111111111111111111111111111115" };
+ int ret_size = 0;
+ config_line_t *ret;
+ for (ret = options->MyFamily; ret && ret_size < 5; ret = ret->next) {
+ tt_str_op(ret->value, OP_EQ, valid[ret_size]);
+ ret_size++;
+ }
+ tt_int_op(ret_size, OP_EQ, 5);
- or_options_free(options);
- or_options_free(defaults);
+ done:
+ tor_free(err);
+ or_options_free(options);
+ or_options_free(defaults);
}
static int n_hostname_01010101 = 0;
@@ -1120,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);
@@ -1145,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);
@@ -1177,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);
@@ -1200,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);
@@ -1222,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);
@@ -1243,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);
@@ -1266,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);
@@ -1296,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);
@@ -1326,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);
@@ -1356,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);
@@ -1400,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:
@@ -1427,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);
@@ -1456,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);
@@ -1491,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();
@@ -1524,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();
@@ -1569,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:
@@ -1604,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:
@@ -1630,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);
@@ -1819,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);
@@ -1838,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,
@@ -1850,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) -
@@ -1860,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);
}
}
@@ -1901,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);
@@ -1910,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;
@@ -1922,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;
@@ -1934,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;
@@ -1946,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;
@@ -1965,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;
@@ -1977,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;
@@ -1989,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;
@@ -2001,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;
@@ -2013,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);
}
}
@@ -2042,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);
@@ -2051,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;
@@ -2063,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;
@@ -2075,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;
@@ -2087,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;
@@ -2106,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;
@@ -2118,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;
@@ -2130,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;
@@ -2142,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;
@@ -2154,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);
}
}
@@ -2183,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);
@@ -2192,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;
@@ -2204,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;
@@ -2216,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;
@@ -2228,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;
@@ -2247,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;
@@ -2259,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;
@@ -2271,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;
@@ -2283,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;
@@ -2295,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);
}
}
@@ -2325,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);
@@ -2334,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;
@@ -2346,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;
@@ -2358,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;
@@ -2370,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;
@@ -2389,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;
@@ -2401,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;
@@ -2413,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;
@@ -2425,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;
@@ -2437,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);
}
}
@@ -2477,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);
@@ -2498,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;
@@ -2510,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;
@@ -2522,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
@@ -2548,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;
@@ -2560,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;
@@ -2572,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;
@@ -2584,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;
@@ -2596,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
@@ -2631,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);
@@ -2652,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;
@@ -2664,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;
@@ -2676,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
@@ -2702,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;
@@ -2714,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;
@@ -2726,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;
@@ -2738,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;
@@ -2750,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
@@ -2794,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);
@@ -2816,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;
@@ -2828,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;
@@ -2840,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),
@@ -2867,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;
@@ -2879,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;
@@ -2891,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;
@@ -2903,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;
@@ -2915,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),
@@ -2951,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);
@@ -2974,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;
@@ -2986,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;
@@ -2998,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),
@@ -3025,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;
@@ -3037,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;
@@ -3049,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;
@@ -3061,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;
@@ -3073,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),
@@ -3117,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);
@@ -3139,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;
@@ -3151,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;
@@ -3163,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
@@ -3190,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;
@@ -3202,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;
@@ -3214,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;
@@ -3226,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;
@@ -3238,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
@@ -3280,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);
@@ -3302,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;
@@ -3314,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;
@@ -3326,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
@@ -3353,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;
@@ -3365,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;
@@ -3377,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;
@@ -3389,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;
@@ -3401,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
@@ -3458,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);
@@ -3471,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);
@@ -3540,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 */
@@ -3560,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 */
@@ -3570,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
@@ -3583,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
@@ -3610,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
@@ -3639,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;
@@ -3666,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;
@@ -3676,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);
@@ -3725,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);
@@ -3864,144 +3884,6 @@ mock_config_line(const char *key, const char *val)
}
static void
-test_config_parse_port_config__listenaddress(void *data)
-{
- (void)data;
- int ret;
- config_line_t *config_listen_address = NULL, *config_listen_address2 = NULL,
- *config_listen_address3 = NULL;
- config_line_t *config_port1 = NULL, *config_port2 = NULL,
- *config_port3 = NULL, *config_port4 = NULL, *config_port5 = NULL;
- smartlist_t *slout = NULL;
- port_cfg_t *port_cfg = NULL;
-
- // Test basic invocation with no arguments
- ret = parse_port_config(NULL, NULL, NULL, NULL, 0, NULL, 0, 0);
- tt_int_op(ret, OP_EQ, 0);
-
- // Setup some test data
- config_listen_address = mock_config_line("DNSListenAddress", "127.0.0.1");
- config_listen_address2 = mock_config_line("DNSListenAddress", "x$$$:::345");
- config_listen_address3 = mock_config_line("DNSListenAddress",
- "127.0.0.1:1442");
- config_port1 = mock_config_line("DNSPort", "42");
- config_port2 = mock_config_line("DNSPort", "43");
- config_port1->next = config_port2;
- config_port3 = mock_config_line("DNSPort", "auto");
- config_port4 = mock_config_line("DNSPort", "55542");
- config_port5 = mock_config_line("DNSPort", "666777");
-
- // Test failure when we have a ListenAddress line and several
- // Port lines for the same portname
- ret = parse_port_config(NULL, config_port1, config_listen_address, "DNS", 0,
- NULL, 0, 0);
-
- tt_int_op(ret, OP_EQ, -1);
-
- // Test case when we have a listen address, no default port and allow
- // spurious listen address lines
- ret = parse_port_config(NULL, NULL, config_listen_address, "DNS", 0, NULL,
- 0, CL_PORT_ALLOW_EXTRA_LISTENADDR);
- tt_int_op(ret, OP_EQ, 1);
-
- // Test case when we have a listen address, no default port but doesn't
- // allow spurious listen address lines
- ret = parse_port_config(NULL, NULL, config_listen_address, "DNS", 0, NULL,
- 0, 0);
- tt_int_op(ret, OP_EQ, -1);
-
- // Test case when we have a listen address, and a port that points to auto,
- // should use the AUTO port
- slout = smartlist_new();
- ret = parse_port_config(slout, config_port3, config_listen_address, "DNS",
- 0, NULL, 0, 0);
- 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->port, OP_EQ, CFG_AUTO_PORT);
-
- // Test when we have a listen address and a custom port
- ret = parse_port_config(slout, config_port4, config_listen_address, "DNS",
- 0, NULL, 0, 0);
- tt_int_op(ret, OP_EQ, 0);
- tt_int_op(smartlist_len(slout), OP_EQ, 2);
- port_cfg = (port_cfg_t *)smartlist_get(slout, 1);
- tt_int_op(port_cfg->port, OP_EQ, 55542);
-
- // Test when we have a listen address and an invalid custom port
- ret = parse_port_config(slout, config_port5, config_listen_address, "DNS",
- 0, NULL, 0, 0);
- tt_int_op(ret, OP_EQ, -1);
-
- // Test we get a server port configuration when asked for it
- ret = parse_port_config(slout, NULL, config_listen_address, "DNS", 0, NULL,
- 123, CL_PORT_SERVER_OPTIONS);
- tt_int_op(ret, OP_EQ, 0);
- tt_int_op(smartlist_len(slout), OP_EQ, 4);
- port_cfg = (port_cfg_t *)smartlist_get(slout, 2);
- tt_int_op(port_cfg->port, OP_EQ, 123);
- tt_int_op(port_cfg->server_cfg.no_listen, OP_EQ, 1);
- tt_int_op(port_cfg->server_cfg.bind_ipv4_only, OP_EQ, 1);
-
- // Test an invalid ListenAddress configuration
- ret = parse_port_config(NULL, NULL, config_listen_address2, "DNS", 0, NULL,
- 222, 0);
- tt_int_op(ret, OP_EQ, -1);
-
- // Test default to the port in the listen address if available
- ret = parse_port_config(slout, config_port2, config_listen_address3, "DNS",
- 0, NULL, 0, 0);
- tt_int_op(ret, OP_EQ, 0);
- tt_int_op(smartlist_len(slout), OP_EQ, 5);
- port_cfg = (port_cfg_t *)smartlist_get(slout, 4);
- tt_int_op(port_cfg->port, OP_EQ, 1442);
-
- // Test we work correctly without an out, but with a listen address
- // and a port
- ret = parse_port_config(NULL, config_port2, config_listen_address, "DNS",
- 0, NULL, 0, 0);
- tt_int_op(ret, OP_EQ, 0);
-
- // Test warning nonlocal control
- ret = parse_port_config(slout, config_port2, config_listen_address, "DNS",
- CONN_TYPE_CONTROL_LISTENER, NULL, 0,
- CL_PORT_WARN_NONLOCAL);
- tt_int_op(ret, OP_EQ, 0);
-
- // Test warning nonlocal ext or listener
- ret = parse_port_config(slout, config_port2, config_listen_address, "DNS",
- CONN_TYPE_EXT_OR_LISTENER, NULL, 0,
- CL_PORT_WARN_NONLOCAL);
- tt_int_op(ret, OP_EQ, 0);
-
- // Test warning nonlocal other
- SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
- smartlist_clear(slout);
- ret = parse_port_config(slout, config_port2, config_listen_address, "DNS",
- 0, NULL, 0, CL_PORT_WARN_NONLOCAL);
- tt_int_op(ret, OP_EQ, 0);
-
- // Test warning nonlocal control without an out
- ret = parse_port_config(NULL, config_port2, config_listen_address, "DNS",
- CONN_TYPE_CONTROL_LISTENER, NULL, 0,
- CL_PORT_WARN_NONLOCAL);
- tt_int_op(ret, OP_EQ, 0);
-
- done:
- config_free_lines(config_listen_address);
- config_free_lines(config_listen_address2);
- config_free_lines(config_listen_address3);
- config_free_lines(config_port1);
- /* 2 was linked from 1. */
- config_free_lines(config_port3);
- config_free_lines(config_port4);
- config_free_lines(config_port5);
- if (slout)
- SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
- smartlist_free(slout);
-}
-
-static void
test_config_parse_port_config__ports__no_ports_given(void *data)
{
(void)data;
@@ -4012,40 +3894,40 @@ test_config_parse_port_config__ports__no_ports_given(void *data)
slout = smartlist_new();
// Test no defaultport, no defaultaddress and no out
- ret = parse_port_config(NULL, NULL, NULL, "DNS", 0, NULL, 0, 0);
+ ret = parse_port_config(NULL, NULL, "DNS", 0, NULL, 0, 0);
tt_int_op(ret, OP_EQ, 0);
// Test with defaultport, no defaultaddress and no out
- ret = parse_port_config(NULL, NULL, NULL, "DNS", 0, NULL, 42, 0);
+ ret = parse_port_config(NULL, NULL, "DNS", 0, NULL, 42, 0);
tt_int_op(ret, OP_EQ, 0);
// Test no defaultport, with defaultaddress and no out
- ret = parse_port_config(NULL, NULL, NULL, "DNS", 0, "127.0.0.2", 0, 0);
+ ret = parse_port_config(NULL, NULL, "DNS", 0, "127.0.0.2", 0, 0);
tt_int_op(ret, OP_EQ, 0);
// Test with defaultport, with defaultaddress and no out
- ret = parse_port_config(NULL, NULL, NULL, "DNS", 0, "127.0.0.2", 42, 0);
+ ret = parse_port_config(NULL, NULL, "DNS", 0, "127.0.0.2", 42, 0);
tt_int_op(ret, OP_EQ, 0);
// Test no defaultport, no defaultaddress and with out
- ret = parse_port_config(slout, NULL, NULL, "DNS", 0, NULL, 0, 0);
+ ret = parse_port_config(slout, NULL, "DNS", 0, NULL, 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 0);
// Test with defaultport, no defaultaddress and with out
- ret = parse_port_config(slout, NULL, NULL, "DNS", 0, NULL, 42, 0);
+ ret = parse_port_config(slout, NULL, "DNS", 0, NULL, 42, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 0);
// Test no defaultport, with defaultaddress and with out
- ret = parse_port_config(slout, NULL, NULL, "DNS", 0, "127.0.0.2", 0, 0);
+ ret = parse_port_config(slout, NULL, "DNS", 0, "127.0.0.2", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 0);
// Test with defaultport, with defaultaddress and out, adds a new port cfg
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
- ret = parse_port_config(slout, NULL, NULL, "DNS", 0, "127.0.0.2", 42, 0);
+ ret = parse_port_config(slout, NULL, "DNS", 0, "127.0.0.2", 42, 0);
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);
@@ -4056,7 +3938,7 @@ test_config_parse_port_config__ports__no_ports_given(void *data)
// for a unix address
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
- ret = parse_port_config(slout, NULL, NULL, "DNS", 0, "/foo/bar/unixdomain",
+ ret = parse_port_config(slout, NULL, "DNS", 0, "/foo/bar/unixdomain",
42, CL_PORT_IS_UNIXSOCKET);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4085,28 +3967,28 @@ test_config_parse_port_config__ports__ports_given(void *data)
// Test error when encounters an invalid Port specification
config_port_invalid = mock_config_line("DNSPort", "");
- ret = parse_port_config(NULL, config_port_invalid, NULL, "DNS", 0, NULL,
+ ret = parse_port_config(NULL, config_port_invalid, "DNS", 0, NULL,
0, 0);
tt_int_op(ret, OP_EQ, -1);
// Test error when encounters an empty unix domain specification
config_free_lines(config_port_invalid); config_port_invalid = NULL;
config_port_invalid = mock_config_line("DNSPort", "unix:");
- ret = parse_port_config(NULL, config_port_invalid, NULL, "DNS", 0, NULL,
+ ret = parse_port_config(NULL, config_port_invalid, "DNS", 0, NULL,
0, 0);
tt_int_op(ret, OP_EQ, -1);
// Test error when encounters a unix domain specification but the listener
// doesn't support domain sockets
config_port_valid = mock_config_line("DNSPort", "unix:/tmp/foo/bar");
- ret = parse_port_config(NULL, config_port_valid, NULL, "DNS",
+ ret = parse_port_config(NULL, config_port_valid, "DNS",
CONN_TYPE_AP_DNS_LISTENER, NULL, 0, 0);
tt_int_op(ret, OP_EQ, -1);
// Test valid unix domain
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
- ret = parse_port_config(slout, config_port_valid, NULL, "SOCKS",
+ ret = parse_port_config(slout, config_port_valid, "SOCKS",
CONN_TYPE_AP_LISTENER, NULL, 0, 0);
#ifdef _WIN32
tt_int_op(ret, OP_EQ, -1);
@@ -4123,7 +4005,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
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.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;
@@ -4131,7 +4013,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
"unix:/tmp/foo/bar NoIPv4Traffic "
"NoIPv6Traffic "
"NoOnionTraffic");
- ret = parse_port_config(NULL, config_port_invalid, NULL, "SOCKS",
+ ret = parse_port_config(NULL, config_port_invalid, "SOCKS",
CONN_TYPE_AP_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
tt_int_op(ret, OP_EQ, -1);
@@ -4140,7 +4022,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
config_free_lines(config_port_invalid); config_port_invalid = NULL;
config_port_invalid = mock_config_line("DNSPort",
"127.0.0.1:80 NoDNSRequest");
- ret = parse_port_config(NULL, config_port_invalid, NULL, "DNS",
+ ret = parse_port_config(NULL, config_port_invalid, "DNS",
CONN_TYPE_AP_DNS_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
tt_int_op(ret, OP_EQ, -1);
@@ -4153,7 +4035,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
config_port_valid = mock_config_line("DNSPort", "127.0.0.1:80 "
"NoIPv6Traffic "
"NoIPv4Traffic NoOnionTraffic");
- ret = parse_port_config(slout, config_port_valid, NULL, "DNS",
+ ret = parse_port_config(slout, config_port_valid, "DNS",
CONN_TYPE_AP_DNS_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
tt_int_op(ret, OP_EQ, 0);
@@ -4169,7 +4051,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
config_port_invalid = mock_config_line("SOCKSPort",
"NoIPv6Traffic "
"unix:/tmp/foo/bar NoIPv4Traffic");
- ret = parse_port_config(NULL, config_port_invalid, NULL, "SOCKS",
+ ret = parse_port_config(NULL, config_port_invalid, "SOCKS",
CONN_TYPE_AP_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
tt_int_op(ret, OP_EQ, -1);
@@ -4182,7 +4064,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
config_port_valid = mock_config_line("SOCKSPort", "unix:/tmp/foo/bar "
"NoIPv6Traffic "
"NoDNSRequest NoIPv4Traffic");
- ret = parse_port_config(slout, config_port_valid, NULL, "SOCKS",
+ ret = parse_port_config(slout, config_port_valid, "SOCKS",
CONN_TYPE_AP_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
#ifdef _WIN32
@@ -4195,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;
@@ -4204,7 +4086,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
config_port_valid = mock_config_line("SOCKSPort", "unix:\"/tmp/foo/ bar\" "
"NoIPv6Traffic "
"NoDNSRequest NoIPv4Traffic");
- ret = parse_port_config(slout, config_port_valid, NULL, "SOCKS",
+ ret = parse_port_config(slout, config_port_valid, "SOCKS",
CONN_TYPE_AP_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
#ifdef _WIN32
@@ -4217,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;
@@ -4226,7 +4108,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
config_port_valid = mock_config_line("SOCKSPort", "unix:\"/tmp/foo/ bar "
"NoIPv6Traffic "
"NoDNSRequest NoIPv4Traffic");
- ret = parse_port_config(slout, config_port_valid, NULL, "SOCKS",
+ ret = parse_port_config(slout, config_port_valid, "SOCKS",
CONN_TYPE_AP_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
tt_int_op(ret, OP_EQ, -1);
@@ -4238,7 +4120,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
config_port_valid = mock_config_line("SOCKSPort", "unix:\"\" "
"NoIPv6Traffic "
"NoDNSRequest NoIPv4Traffic");
- ret = parse_port_config(slout, config_port_valid, NULL, "SOCKS",
+ ret = parse_port_config(slout, config_port_valid, "SOCKS",
CONN_TYPE_AP_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
tt_int_op(ret, OP_EQ, -1);
@@ -4249,7 +4131,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
smartlist_clear(slout);
config_port_valid = mock_config_line("SOCKSPort", "unix:/tmp/foo/bar "
"OnionTrafficOnly");
- ret = parse_port_config(slout, config_port_valid, NULL, "SOCKS",
+ ret = parse_port_config(slout, config_port_valid, "SOCKS",
CONN_TYPE_AP_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
#ifdef _WIN32
@@ -4262,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;
@@ -4270,7 +4152,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
smartlist_clear(slout);
config_port_valid = mock_config_line("SOCKSPort", "unix:/tmp/foo/bar "
"NoIPv4Traffic IPv6Traffic");
- ret = parse_port_config(slout, config_port_valid, NULL, "SOCKS",
+ ret = parse_port_config(slout, config_port_valid, "SOCKS",
CONN_TYPE_AP_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
#ifdef _WIN32
@@ -4281,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;
@@ -4289,7 +4171,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
smartlist_clear(slout);
config_port_valid = mock_config_line("SOCKSPort", "unix:/tmp/foo/bar "
"IPv4Traffic IPv6Traffic");
- ret = parse_port_config(slout, config_port_valid, NULL, "SOCKS",
+ ret = parse_port_config(slout, config_port_valid, "SOCKS",
CONN_TYPE_AP_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
#ifdef _WIN32
@@ -4300,33 +4182,33 @@ 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;
config_port_invalid = mock_config_line("DNSPort", "42 WorldWritable");
- ret = parse_port_config(NULL, config_port_invalid, NULL, "DNS", 0,
+ ret = parse_port_config(NULL, config_port_invalid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, -1);
// Test failure if we specify group writable for an IP Port
config_free_lines(config_port_invalid); config_port_invalid = NULL;
config_port_invalid = mock_config_line("DNSPort", "42 GroupWritable");
- ret = parse_port_config(NULL, config_port_invalid, NULL, "DNS", 0,
+ ret = parse_port_config(NULL, config_port_invalid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, -1);
// Test failure if we specify group writable for an IP Port
config_free_lines(config_port_invalid); config_port_invalid = NULL;
config_port_invalid = mock_config_line("DNSPort", "42 RelaxDirModeCheck");
- ret = parse_port_config(NULL, config_port_invalid, NULL, "DNS", 0,
+ ret = parse_port_config(NULL, config_port_invalid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, -1);
// Test success with only a port (this will fail without a default address)
config_free_lines(config_port_valid); config_port_valid = NULL;
config_port_valid = mock_config_line("DNSPort", "42");
- ret = parse_port_config(NULL, config_port_valid, NULL, "DNS", 0,
+ ret = parse_port_config(NULL, config_port_valid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, 0);
@@ -4335,7 +4217,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 IsolateDestPort");
- ret = parse_port_config(slout, config_port_valid, NULL, "DNS", 0,
+ ret = parse_port_config(slout, config_port_valid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4348,7 +4230,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 NoIsolateDestPorts");
- ret = parse_port_config(slout, config_port_valid, NULL, "DNS", 0,
+ ret = parse_port_config(slout, config_port_valid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4361,7 +4243,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 IsolateDestAddr");
- ret = parse_port_config(slout, config_port_valid, NULL, "DNS", 0,
+ ret = parse_port_config(slout, config_port_valid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4374,7 +4256,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 IsolateSOCKSAuth");
- ret = parse_port_config(slout, config_port_valid, NULL, "DNS", 0,
+ ret = parse_port_config(slout, config_port_valid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4387,7 +4269,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 IsolateClientProtocol");
- ret = parse_port_config(slout, config_port_valid, NULL, "DNS", 0,
+ ret = parse_port_config(slout, config_port_valid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4400,7 +4282,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 IsolateClientAddr");
- ret = parse_port_config(slout, config_port_valid, NULL, "DNS", 0,
+ ret = parse_port_config(slout, config_port_valid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4411,7 +4293,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
// Test success with ignored unknown options
config_free_lines(config_port_valid); config_port_valid = NULL;
config_port_valid = mock_config_line("DNSPort", "42 ThisOptionDoesntExist");
- ret = parse_port_config(NULL, config_port_valid, NULL, "DNS", 0,
+ ret = parse_port_config(NULL, config_port_valid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, 0);
@@ -4420,7 +4302,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 NoIsolateSOCKSAuth");
- ret = parse_port_config(slout, config_port_valid, NULL, "DNS", 0,
+ ret = parse_port_config(slout, config_port_valid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4433,7 +4315,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
smartlist_clear(slout);
config_port_valid = mock_config_line("SOCKSPort",
"42 IPv6Traffic PreferIPv6");
- ret = parse_port_config(slout, config_port_valid, NULL, "SOCKS",
+ ret = parse_port_config(slout, config_port_valid, "SOCKS",
CONN_TYPE_AP_LISTENER, "127.0.0.42", 0,
CL_PORT_TAKES_HOSTNAMES);
tt_int_op(ret, OP_EQ, 0);
@@ -4446,7 +4328,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 CacheIPv4DNS");
- ret = parse_port_config(slout, config_port_valid, NULL, "DNS", 0,
+ ret = parse_port_config(slout, config_port_valid, "DNS", 0,
"127.0.0.42", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4459,7 +4341,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 CacheIPv6DNS");
- ret = parse_port_config(slout, config_port_valid, NULL, "DNS", 0,
+ ret = parse_port_config(slout, config_port_valid, "DNS", 0,
"127.0.0.42", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4472,7 +4354,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 NoCacheIPv4DNS");
- ret = parse_port_config(slout, config_port_valid, NULL, "DNS", 0,
+ ret = parse_port_config(slout, config_port_valid, "DNS", 0,
"127.0.0.42", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4485,7 +4367,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 CacheDNS");
- ret = parse_port_config(slout, config_port_valid, NULL, "DNS", 0,
+ ret = parse_port_config(slout, config_port_valid, "DNS", 0,
"127.0.0.42", 0, CL_PORT_TAKES_HOSTNAMES);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4498,7 +4380,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 UseIPv4Cache");
- ret = parse_port_config(slout, config_port_valid, NULL, "DNS", 0,
+ ret = parse_port_config(slout, config_port_valid, "DNS", 0,
"127.0.0.42", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4511,7 +4393,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 UseIPv6Cache");
- ret = parse_port_config(slout, config_port_valid, NULL, "DNS", 0,
+ ret = parse_port_config(slout, config_port_valid, "DNS", 0,
"127.0.0.42", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4524,7 +4406,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 UseDNSCache");
- ret = parse_port_config(slout, config_port_valid, NULL, "DNS", 0,
+ ret = parse_port_config(slout, config_port_valid, "DNS", 0,
"127.0.0.42", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4537,7 +4419,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 NoPreferIPv6Automap");
- ret = parse_port_config(slout, config_port_valid, NULL, "DNS", 0,
+ ret = parse_port_config(slout, config_port_valid, "DNS", 0,
"127.0.0.42", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4549,7 +4431,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 PreferSOCKSNoAuth");
- ret = parse_port_config(slout, config_port_valid, NULL, "DNS", 0,
+ ret = parse_port_config(slout, config_port_valid, "DNS", 0,
"127.0.0.42", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4564,14 +4446,14 @@ test_config_parse_port_config__ports__ports_given(void *data)
config_port_invalid = mock_config_line("DNSPort", "0");
config_port_valid = mock_config_line("DNSPort", "42");
config_port_invalid->next = config_port_valid;
- ret = parse_port_config(slout, config_port_invalid, NULL, "DNS", 0,
+ ret = parse_port_config(slout, config_port_invalid, "DNS", 0,
"127.0.0.42", 0, 0);
tt_int_op(ret, OP_EQ, -1);
// Test success with warn non-local control
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
- ret = parse_port_config(slout, config_port_valid, NULL, "Control",
+ ret = parse_port_config(slout, config_port_valid, "Control",
CONN_TYPE_CONTROL_LISTENER, "127.0.0.42", 0,
CL_PORT_WARN_NONLOCAL);
tt_int_op(ret, OP_EQ, 0);
@@ -4579,7 +4461,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
// Test success with warn non-local listener
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
- ret = parse_port_config(slout, config_port_valid, NULL, "ExtOR",
+ ret = parse_port_config(slout, config_port_valid, "ExtOR",
CONN_TYPE_EXT_OR_LISTENER, "127.0.0.42", 0,
CL_PORT_WARN_NONLOCAL);
tt_int_op(ret, OP_EQ, 0);
@@ -4587,12 +4469,12 @@ test_config_parse_port_config__ports__ports_given(void *data)
// Test success with warn non-local other
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
- ret = parse_port_config(slout, config_port_valid, NULL, "DNS", 0,
+ ret = parse_port_config(slout, config_port_valid, "DNS", 0,
"127.0.0.42", 0, CL_PORT_WARN_NONLOCAL);
tt_int_op(ret, OP_EQ, 0);
// Test success with warn non-local other without out
- ret = parse_port_config(NULL, config_port_valid, NULL, "DNS", 0,
+ ret = parse_port_config(NULL, config_port_valid, "DNS", 0,
"127.0.0.42", 0, CL_PORT_WARN_NONLOCAL);
tt_int_op(ret, OP_EQ, 0);
@@ -4603,7 +4485,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 IPv4Traffic "
"IPv6Traffic");
- ret = parse_port_config(slout, config_port_valid, NULL, "DNS", 0,
+ ret = parse_port_config(slout, config_port_valid, "DNS", 0,
"127.0.0.44", 0,
CL_PORT_TAKES_HOSTNAMES |
CL_PORT_NO_STREAM_OPTIONS);
@@ -4618,7 +4500,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_invalid = mock_config_line("DNSPort", "42 SessionGroup=invalid");
- ret = parse_port_config(slout, config_port_invalid, NULL, "DNS", 0,
+ ret = parse_port_config(slout, config_port_invalid, "DNS", 0,
"127.0.0.44", 0, CL_PORT_NO_STREAM_OPTIONS);
tt_int_op(ret, OP_EQ, -1);
@@ -4630,7 +4512,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_invalid = mock_config_line("DNSPort", "42 SessionGroup=123");
- ret = parse_port_config(slout, config_port_invalid, NULL, "DNS", 0,
+ ret = parse_port_config(slout, config_port_invalid, "DNS", 0,
"127.0.0.44", 0, 0);
tt_int_op(ret, OP_EQ, -1);
@@ -4640,7 +4522,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
smartlist_clear(slout);
config_port_invalid = mock_config_line("DNSPort", "42 SessionGroup=123 "
"SessionGroup=321");
- ret = parse_port_config(slout, config_port_invalid, NULL, "DNS", 0,
+ ret = parse_port_config(slout, config_port_invalid, "DNS", 0,
"127.0.0.44", 0, CL_PORT_NO_STREAM_OPTIONS);
tt_int_op(ret, OP_EQ, -1);
@@ -4649,7 +4531,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 SessionGroup=1111122");
- ret = parse_port_config(slout, config_port_valid, NULL, "DNS", 0,
+ ret = parse_port_config(slout, config_port_valid, "DNS", 0,
"127.0.0.44", 0, CL_PORT_NO_STREAM_OPTIONS);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4661,7 +4543,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "0");
- ret = parse_port_config(slout, config_port_valid, NULL, "DNS", 0,
+ ret = parse_port_config(slout, config_port_valid, "DNS", 0,
"127.0.0.45", 0, CL_PORT_IS_UNIXSOCKET);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 0);
@@ -4671,7 +4553,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "something");
- ret = parse_port_config(slout, config_port_valid, NULL, "DNS", 0,
+ ret = parse_port_config(slout, config_port_valid, "DNS", 0,
"127.0.0.45", 0, CL_PORT_IS_UNIXSOCKET);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4684,7 +4566,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "auto");
- ret = parse_port_config(slout, config_port_valid, NULL, "DNS", 0,
+ ret = parse_port_config(slout, config_port_valid, "DNS", 0,
"127.0.0.46", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4698,7 +4580,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "127.0.0.122:auto");
- ret = parse_port_config(slout, config_port_valid, NULL, "DNS", 0,
+ ret = parse_port_config(slout, config_port_valid, "DNS", 0,
"127.0.0.46", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4711,7 +4593,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
config_free_lines(config_port_invalid); config_port_invalid = NULL;
config_port_invalid = mock_config_line("DNSPort", "invalidstuff!!:auto");
MOCK(tor_addr_lookup, mock_tor_addr_lookup__fail_on_bad_addrs);
- ret = parse_port_config(NULL, config_port_invalid, NULL, "DNS", 0,
+ ret = parse_port_config(NULL, config_port_invalid, "DNS", 0,
"127.0.0.46", 0, 0);
UNMOCK(tor_addr_lookup);
tt_int_op(ret, OP_EQ, -1);
@@ -4721,7 +4603,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "127.0.0.123:656");
- ret = parse_port_config(slout, config_port_valid, NULL, "DNS", 0,
+ ret = parse_port_config(slout, config_port_valid, "DNS", 0,
"127.0.0.46", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4735,7 +4617,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_invalid = mock_config_line("DNSPort", "something wrong");
- ret = parse_port_config(slout, config_port_invalid, NULL, "DNS", 0,
+ ret = parse_port_config(slout, config_port_invalid, "DNS", 0,
"127.0.0.46", 0, 0);
tt_int_op(ret, OP_EQ, -1);
@@ -4744,7 +4626,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_invalid = mock_config_line("DNSPort", "127.0.1.0:123:auto");
- ret = parse_port_config(slout, config_port_invalid, NULL, "DNS", 0,
+ ret = parse_port_config(slout, config_port_invalid, "DNS", 0,
"127.0.0.46", 0, 0);
tt_int_op(ret, OP_EQ, -1);
@@ -4754,7 +4636,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("SOCKSPort", "unix:/tmp/somewhere");
- ret = parse_port_config(slout, config_port_valid, NULL, "SOCKS",
+ ret = parse_port_config(slout, config_port_valid, "SOCKS",
CONN_TYPE_AP_LISTENER, "127.0.0.46", 0,
CL_PORT_DFLT_GROUP_WRITABLE);
#ifdef _WIN32
@@ -4764,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)
@@ -4789,7 +4671,7 @@ test_config_parse_port_config__ports__server_options(void *data)
config_free_lines(config_port_valid); config_port_valid = NULL;
config_port_valid = mock_config_line("DNSPort",
"127.0.0.124:656 NoAdvertise");
- ret = parse_port_config(slout, config_port_valid, NULL, "DNS", 0, NULL, 0,
+ ret = parse_port_config(slout, config_port_valid, "DNS", 0, NULL, 0,
CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4802,7 +4684,7 @@ test_config_parse_port_config__ports__server_options(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "127.0.0.124:656 NoListen");
- ret = parse_port_config(slout, config_port_valid, NULL, "DNS", 0, NULL, 0,
+ ret = parse_port_config(slout, config_port_valid, "DNS", 0, NULL, 0,
CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4816,7 +4698,7 @@ test_config_parse_port_config__ports__server_options(void *data)
smartlist_clear(slout);
config_port_invalid = mock_config_line("DNSPort", "127.0.0.124:656 NoListen "
"NoAdvertise");
- ret = parse_port_config(slout, config_port_invalid, NULL, "DNS", 0, NULL,
+ ret = parse_port_config(slout, config_port_invalid, "DNS", 0, NULL,
0, CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, -1);
@@ -4825,7 +4707,7 @@ test_config_parse_port_config__ports__server_options(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "127.0.0.124:656 IPv4Only");
- ret = parse_port_config(slout, config_port_valid, NULL, "DNS", 0, NULL, 0,
+ ret = parse_port_config(slout, config_port_valid, "DNS", 0, NULL, 0,
CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4838,7 +4720,7 @@ test_config_parse_port_config__ports__server_options(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "[::1]:656 IPv6Only");
- ret = parse_port_config(slout, config_port_valid, NULL, "DNS", 0, NULL, 0,
+ ret = parse_port_config(slout, config_port_valid, "DNS", 0, NULL, 0,
CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4852,7 +4734,7 @@ test_config_parse_port_config__ports__server_options(void *data)
smartlist_clear(slout);
config_port_invalid = mock_config_line("DNSPort", "127.0.0.124:656 IPv6Only "
"IPv4Only");
- ret = parse_port_config(slout, config_port_invalid, NULL, "DNS", 0, NULL,
+ ret = parse_port_config(slout, config_port_invalid, "DNS", 0, NULL,
0, CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, -1);
@@ -4861,7 +4743,7 @@ test_config_parse_port_config__ports__server_options(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "127.0.0.124:656 unknown");
- ret = parse_port_config(slout, config_port_valid, NULL, "DNS", 0, NULL, 0,
+ ret = parse_port_config(slout, config_port_valid, "DNS", 0, NULL, 0,
CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4872,7 +4754,7 @@ test_config_parse_port_config__ports__server_options(void *data)
smartlist_clear(slout);
config_port_invalid = mock_config_line("DNSPort",
"127.0.0.124:656 IPv6Only");
- ret = parse_port_config(slout, config_port_invalid, NULL, "DNS", 0, NULL,
+ ret = parse_port_config(slout, config_port_invalid, "DNS", 0, NULL,
0, CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, -1);
@@ -4881,7 +4763,7 @@ test_config_parse_port_config__ports__server_options(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_invalid = mock_config_line("DNSPort", "[::1]:656 IPv4Only");
- ret = parse_port_config(slout, config_port_invalid, NULL, "DNS", 0, NULL,
+ ret = parse_port_config(slout, config_port_invalid, "DNS", 0, NULL,
0, CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, -1);
@@ -4890,7 +4772,7 @@ test_config_parse_port_config__ports__server_options(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_invalid = mock_config_line("ORPort", "unix:\"\"");
- ret = parse_port_config(slout, config_port_invalid, NULL, "ORPort", 0, NULL,
+ ret = parse_port_config(slout, config_port_invalid, "ORPort", 0, NULL,
0, CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, -1);
@@ -4929,6 +4811,708 @@ test_config_parse_log_severity(void *data)
tor_free(severity);
}
+static void
+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);
+
+#ifdef _WIN32
+ tt_int_op(mkdir(dir), OP_EQ, 0);
+#else
+ tt_int_op(mkdir(dir, 0700), OP_EQ, 0);
+#endif
+
+ tor_asprintf(&torrc_path, "%s"PATH_SEPARATOR"torrc", dir);
+ char torrc_contents[1000];
+ tor_snprintf(torrc_contents, sizeof(torrc_contents), "%%include %s",
+ torrc_path);
+ tt_int_op(write_str_to_file(torrc_path, torrc_contents, 0), OP_EQ, 0);
+
+ tt_int_op(config_get_lines_include(torrc_contents, &result, 0, NULL),
+ OP_EQ, -1);
+
+ done:
+ config_free_lines(result);
+ tor_free(torrc_path);
+ tor_free(dir);
+}
+
+static void
+test_config_include_does_not_exist(void *data)
+{
+ (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
+ tt_int_op(mkdir(dir), OP_EQ, 0);
+#else
+ tt_int_op(mkdir(dir, 0700), OP_EQ, 0);
+#endif
+
+ tor_asprintf(&missing_path, "%s"PATH_SEPARATOR"missing", dir);
+ char torrc_contents[1000];
+ tor_snprintf(torrc_contents, sizeof(torrc_contents), "%%include %s",
+ missing_path);
+
+ tt_int_op(config_get_lines_include(torrc_contents, &result, 0, NULL),
+ OP_EQ, -1);
+
+ done:
+ config_free_lines(result);
+ tor_free(dir);
+ tor_free(missing_path);
+}
+
+static void
+test_config_include_error_in_included_file(void *data)
+{
+ (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
+ tt_int_op(mkdir(dir), OP_EQ, 0);
+#else
+ tt_int_op(mkdir(dir, 0700), OP_EQ, 0);
+#endif
+
+ 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];
+ tor_snprintf(torrc_contents, sizeof(torrc_contents), "%%include %s",
+ invalid_path);
+
+ tt_int_op(config_get_lines_include(torrc_contents, &result, 0, NULL),
+ OP_EQ, -1);
+
+ done:
+ config_free_lines(result);
+ tor_free(dir);
+ tor_free(invalid_path);
+}
+
+static void
+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);
+
+#ifdef _WIN32
+ tt_int_op(mkdir(dir), OP_EQ, 0);
+#else
+ tt_int_op(mkdir(dir, 0700), OP_EQ, 0);
+#endif
+
+ 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
+ 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];
+ tor_snprintf(torrc_contents, sizeof(torrc_contents),
+ "%%include %s\n"
+ "%%include %s\n",
+ folder_path, file_path);
+
+ int include_used;
+ tt_int_op(config_get_lines_include(torrc_contents, &result, 0,&include_used),
+ OP_EQ, 0);
+ tt_ptr_op(result, OP_EQ, NULL);
+ tt_int_op(include_used, OP_EQ, 1);
+
+ 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);
+
+#ifdef _WIN32
+ tt_int_op(mkdir(dir), OP_EQ, 0);
+#else
+ tt_int_op(mkdir(dir, 0700), OP_EQ, 0);
+#endif
+
+ tor_asprintf(&torrc_path, "%s"PATH_SEPARATOR"torrc", dir);
+
+ char file_contents[1000];
+ const int limit = MAX_INCLUDE_RECURSION_LEVEL;
+ int i;
+ // Loop backwards so file_contents has the contents of the first file by the
+ // end of the loop
+ for (i = limit; i > 0; i--) {
+ if (i < limit) {
+ tor_snprintf(file_contents, sizeof(file_contents),
+ "Test %d\n"
+ "%%include %s%d\n"
+ "Test %d\n",
+ i, torrc_path, i + 1, 2 * limit - i);
+ } else {
+ tor_snprintf(file_contents, sizeof(file_contents), "Test %d\n", i);
+ }
+
+ if (i > 1) {
+ 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);
+ }
+ }
+
+ int include_used;
+ tt_int_op(config_get_lines_include(file_contents, &result, 0, &include_used),
+ OP_EQ, 0);
+ tt_ptr_op(result, OP_NE, NULL);
+ tt_int_op(include_used, OP_EQ, 1);
+
+ int len = 0;
+ config_line_t *next;
+ for (next = result; next != NULL; next = next->next) {
+ char expected[10];
+ tor_snprintf(expected, sizeof(expected), "%d", len + 1);
+ tt_str_op(next->key, OP_EQ, "Test");
+ tt_str_op(next->value, OP_EQ, expected);
+ len++;
+ }
+ tt_int_op(len, OP_EQ, 2 * limit - 1);
+
+ done:
+ config_free_lines(result);
+ tor_free(dir);
+ tor_free(torrc_path);
+}
+
+static void
+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);
+
+#ifdef _WIN32
+ tt_int_op(mkdir(dir), OP_EQ, 0);
+#else
+ tt_int_op(mkdir(dir, 0700), OP_EQ, 0);
+#endif
+
+ tor_asprintf(&torrc_path, "%s"PATH_SEPARATOR"torrc", dir);
+
+ char file_contents[1000];
+ const int limit = MAX_INCLUDE_RECURSION_LEVEL;
+ int i;
+ // Loop backwards so file_contents has the contents of the first file by the
+ // end of the loop
+ for (i = limit; i > 0; i--) {
+ int n = (i - limit - 1) * -1;
+ if (i < limit) {
+ tor_snprintf(file_contents, sizeof(file_contents),
+ "%%include %s%d\n"
+ "Test %d\n",
+ torrc_path, i + 1, n);
+ } else {
+ tor_snprintf(file_contents, sizeof(file_contents), "Test %d\n", n);
+ }
+
+ if (i > 1) {
+ 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);
+ }
+ }
+
+ int include_used;
+ tt_int_op(config_get_lines_include(file_contents, &result, 0, &include_used),
+ OP_EQ, 0);
+ tt_ptr_op(result, OP_NE, NULL);
+ tt_int_op(include_used, OP_EQ, 1);
+
+ int len = 0;
+ config_line_t *next;
+ for (next = result; next != NULL; next = next->next) {
+ char expected[10];
+ tor_snprintf(expected, sizeof(expected), "%d", len + 1);
+ tt_str_op(next->key, OP_EQ, "Test");
+ tt_str_op(next->value, OP_EQ, expected);
+ len++;
+ }
+ tt_int_op(len, OP_EQ, limit);
+
+ done:
+ config_free_lines(result);
+ tor_free(dir);
+ tor_free(torrc_path);
+}
+
+static void
+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);
+
+#ifdef _WIN32
+ tt_int_op(mkdir(dir), OP_EQ, 0);
+#else
+ tt_int_op(mkdir(dir, 0700), OP_EQ, 0);
+#endif
+
+ tor_asprintf(&torrcd, "%s"PATH_SEPARATOR"%s", dir, "torrc.d");
+
+#ifdef _WIN32
+ tt_int_op(mkdir(torrcd), OP_EQ, 0);
+#else
+ tt_int_op(mkdir(torrcd, 0700), OP_EQ, 0);
+#endif
+
+ // test that files in subfolders are ignored
+ tor_asprintf(&path, "%s"PATH_SEPARATOR"%s", torrcd, "subfolder");
+
+#ifdef _WIN32
+ tt_int_op(mkdir(path), OP_EQ, 0);
+#else
+ tt_int_op(mkdir(path, 0700), OP_EQ, 0);
+#endif
+
+ 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_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_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_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_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_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),
+ "%%include %s\n",
+ torrcd);
+
+ int include_used;
+ tt_int_op(config_get_lines_include(torrc_contents, &result, 0,&include_used),
+ OP_EQ, 0);
+ tt_ptr_op(result, OP_NE, NULL);
+ tt_int_op(include_used, OP_EQ, 1);
+
+ int len = 0;
+ config_line_t *next;
+ for (next = result; next != NULL; next = next->next) {
+ char expected[10];
+ tor_snprintf(expected, sizeof(expected), "%d", len + 1);
+ tt_str_op(next->key, OP_EQ, "Test");
+ tt_str_op(next->value, OP_EQ, expected);
+ len++;
+ }
+ tt_int_op(len, OP_EQ, 4);
+
+ done:
+ config_free_lines(result);
+ tor_free(torrcd);
+ tor_free(path);
+ tor_free(path2);
+ tor_free(dir);
+}
+
+static void
+test_config_include_path_syntax(void *data)
+{
+ (void)data;
+
+ config_line_t *result = NULL;
+ char *dir = tor_strdup(get_fname("test_include_path_syntax"));
+ char *esc_dir = NULL, *dir_with_pathsep = NULL,
+ *esc_dir_with_pathsep = NULL, *torrc_contents = NULL;
+ tt_ptr_op(dir, OP_NE, NULL);
+
+#ifdef _WIN32
+ tt_int_op(mkdir(dir), OP_EQ, 0);
+#else
+ tt_int_op(mkdir(dir, 0700), OP_EQ, 0);
+#endif
+
+ esc_dir = esc_for_log(dir);
+ tor_asprintf(&dir_with_pathsep, "%s%s", dir, PATH_SEPARATOR);
+ esc_dir_with_pathsep = esc_for_log(dir_with_pathsep);
+
+ tor_asprintf(&torrc_contents,
+ "%%include %s\n"
+ "%%include %s%s \n" // space to avoid suppressing newline
+ "%%include %s\n",
+ esc_dir,
+ dir, PATH_SEPARATOR,
+ esc_dir_with_pathsep);
+
+ int include_used;
+ tt_int_op(config_get_lines_include(torrc_contents, &result, 0,&include_used),
+ OP_EQ, 0);
+ tt_ptr_op(result, OP_EQ, NULL);
+ tt_int_op(include_used, OP_EQ, 1);
+
+ done:
+ config_free_lines(result);
+ tor_free(dir);
+ tor_free(torrc_contents);
+ tor_free(esc_dir);
+ tor_free(dir_with_pathsep);
+ tor_free(esc_dir_with_pathsep);
+}
+
+static void
+test_config_include_not_processed(void *data)
+{
+ (void)data;
+
+ char torrc_contents[1000] = "%include does_not_exist\n";
+ config_line_t *result = NULL;
+ tt_int_op(config_get_lines(torrc_contents, &result, 0),OP_EQ, 0);
+ tt_ptr_op(result, OP_NE, NULL);
+
+ int len = 0;
+ config_line_t *next;
+ for (next = result; next != NULL; next = next->next) {
+ tt_str_op(next->key, OP_EQ, "%include");
+ tt_str_op(next->value, OP_EQ, "does_not_exist");
+ len++;
+ }
+ tt_int_op(len, OP_EQ, 1);
+
+ done:
+ config_free_lines(result);
+}
+
+static void
+test_config_include_has_include(void *data)
+{
+ (void)data;
+
+ config_line_t *result = NULL;
+ char *dir = tor_strdup(get_fname("test_include_has_include"));
+ tt_ptr_op(dir, OP_NE, NULL);
+
+#ifdef _WIN32
+ tt_int_op(mkdir(dir), OP_EQ, 0);
+#else
+ tt_int_op(mkdir(dir, 0700), OP_EQ, 0);
+#endif
+
+ char torrc_contents[1000] = "Test 1\n";
+ int include_used;
+
+ tt_int_op(config_get_lines_include(torrc_contents, &result, 0,&include_used),
+ OP_EQ, 0);
+ tt_int_op(include_used, OP_EQ, 0);
+ config_free_lines(result);
+
+ tor_snprintf(torrc_contents, sizeof(torrc_contents), "%%include %s\n", dir);
+ tt_int_op(config_get_lines_include(torrc_contents, &result, 0,&include_used),
+ OP_EQ, 0);
+ tt_int_op(include_used, OP_EQ, 1);
+
+ done:
+ config_free_lines(result);
+ tor_free(dir);
+}
+
+static void
+test_config_include_flag_both_without(void *data)
+{
+ (void)data;
+
+ char *errmsg = NULL;
+ char conf_empty[1000];
+ tor_snprintf(conf_empty, sizeof(conf_empty),
+ "DataDirectory %s\n",
+ get_fname(NULL));
+ // test with defaults-torrc and torrc without include
+ int ret = options_init_from_string(conf_empty, conf_empty, CMD_RUN_UNITTESTS,
+ NULL, &errmsg);
+ tt_int_op(ret, OP_EQ, 0);
+
+ const or_options_t *options = get_options();
+ tt_int_op(options->IncludeUsed, OP_EQ, 0);
+
+ done:
+ tor_free(errmsg);
+}
+
+static void
+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);
+
+#ifdef _WIN32
+ tt_int_op(mkdir(dir), OP_EQ, 0);
+#else
+ tt_int_op(mkdir(dir, 0700), OP_EQ, 0);
+#endif
+
+ 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];
+ tor_snprintf(conf_empty, sizeof(conf_empty),
+ "DataDirectory %s\n",
+ get_fname(NULL));
+ char conf_include[1000];
+ tor_snprintf(conf_include, sizeof(conf_include), "%%include %s", path);
+
+ // test with defaults-torrc without include and torrc with include
+ int ret = options_init_from_string(conf_empty, conf_include,
+ CMD_RUN_UNITTESTS, NULL, &errmsg);
+ tt_int_op(ret, OP_EQ, 0);
+
+ const or_options_t *options = get_options();
+ tt_int_op(options->IncludeUsed, OP_EQ, 1);
+
+ done:
+ tor_free(errmsg);
+ tor_free(path);
+ tor_free(dir);
+}
+
+static void
+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);
+
+#ifdef _WIN32
+ tt_int_op(mkdir(dir), OP_EQ, 0);
+#else
+ tt_int_op(mkdir(dir, 0700), OP_EQ, 0);
+#endif
+
+ 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];
+ tor_snprintf(conf_empty, sizeof(conf_empty),
+ "DataDirectory %s\n",
+ get_fname(NULL));
+ char conf_include[1000];
+ tor_snprintf(conf_include, sizeof(conf_include), "%%include %s", path);
+
+ // test with defaults-torrc with include and torrc without include
+ int ret = options_init_from_string(conf_include, conf_empty,
+ CMD_RUN_UNITTESTS, NULL, &errmsg);
+ tt_int_op(ret, OP_EQ, 0);
+
+ const or_options_t *options = get_options();
+ tt_int_op(options->IncludeUsed, OP_EQ, 0);
+
+ 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 = (char*)("");
+ 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);
+ done:
+ return;
+}
+
+/* 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 }
@@ -4951,11 +5535,31 @@ struct testcase_t config_tests[] = {
CONFIG_TEST(fix_my_family, 0),
CONFIG_TEST(directory_fetch, 0),
CONFIG_TEST(port_cfg_line_extract_addrport, 0),
- CONFIG_TEST(parse_port_config__listenaddress, 0),
CONFIG_TEST(parse_port_config__ports__no_ports_given, 0),
CONFIG_TEST(parse_port_config__ports__server_options, 0),
CONFIG_TEST(parse_port_config__ports__ports_given, 0),
CONFIG_TEST(parse_log_severity, 0),
+ CONFIG_TEST(include_limit, 0),
+ 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),
+ CONFIG_TEST(include_path_syntax, 0),
+ CONFIG_TEST(include_not_processed, 0),
+ CONFIG_TEST(include_has_include, 0),
+ 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 5cda4f3175..314b90cfda 100644
--- a/src/test/test_connection.c
+++ b/src/test/test_connection.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Tor Project, Inc. */
+/* Copyright (c) 2015-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -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)
{
@@ -265,7 +178,7 @@ test_conn_get_rend_setup(const struct testcase_t *tc)
rend_cache_init();
- /* TODO: use directory_initiate_command_rend() to do this - maybe? */
+ /* TODO: use directory_initiate_request() to do this - maybe? */
tor_assert(strlen(TEST_CONN_REND_ADDR) == REND_SERVICE_ID_LEN_BASE32);
conn->rend_data = rend_data_client_create(TEST_CONN_REND_ADDR, NULL, NULL,
REND_NO_AUTH);
@@ -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
new file mode 100644
index 0000000000..ddb1bc53c1
--- /dev/null
+++ b/src/test/test_conscache.c
@@ -0,0 +1,340 @@
+/* Copyright (c) 2017, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "or.h"
+#include "config.h"
+#include "conscache.h"
+#include "test.h"
+
+#ifdef HAVE_UTIME_H
+#include <utime.h>
+#endif
+
+static void
+test_conscache_open_failure(void *arg)
+{
+ (void) arg;
+ /* Try opening a directory that doesn't exist and which we shouldn't be
+ * able to create. */
+ consensus_cache_t *cache = consensus_cache_open("a/b/c/d/e/f/g", 128);
+ tt_ptr_op(cache, OP_EQ, NULL);
+
+ done:
+ ;
+}
+
+static void
+test_conscache_simple_usage(void *arg)
+{
+ (void)arg;
+ consensus_cache_entry_t *ent = NULL, *ent2 = NULL;
+
+ /* Make a temporary datadir for these tests */
+ char *ddir_fname = tor_strdup(get_fname_rnd("datadir_cache"));
+ tor_free(get_options_mutable()->DataDirectory);
+ get_options_mutable()->DataDirectory = tor_strdup(ddir_fname);
+ check_private_dir(ddir_fname, CPD_CREATE, NULL);
+ consensus_cache_t *cache = consensus_cache_open("cons", 128);
+
+ tt_assert(cache);
+
+ /* Create object; make sure it exists. */
+ config_line_t *labels = NULL;
+ config_line_append(&labels, "Hello", "world");
+ config_line_append(&labels, "Adios", "planetas");
+ ent = consensus_cache_add(cache,
+ labels, (const uint8_t *)"A\0B\0C", 5);
+ config_free_lines(labels);
+ labels = NULL;
+ tt_assert(ent);
+
+ /* Make a second object */
+ config_line_append(&labels, "Hello", "mundo");
+ config_line_append(&labels, "Adios", "planets");
+ ent2 = consensus_cache_add(cache,
+ labels, (const uint8_t *)"xyzzy", 5);
+ config_free_lines(labels);
+ labels = NULL;
+ tt_assert(ent2);
+ tt_assert(! consensus_cache_entry_is_mapped(ent2));
+ consensus_cache_entry_decref(ent2);
+ ent2 = NULL;
+
+ /* Check get_value */
+ tt_ptr_op(NULL, OP_EQ, consensus_cache_entry_get_value(ent, "hebbo"));
+ tt_str_op("world", OP_EQ, consensus_cache_entry_get_value(ent, "Hello"));
+
+ /* Check find_first */
+ ent2 = consensus_cache_find_first(cache, "Hello", "world!");
+ tt_ptr_op(ent2, OP_EQ, NULL);
+ ent2 = consensus_cache_find_first(cache, "Hello", "world");
+ tt_ptr_op(ent2, OP_EQ, ent);
+ ent2 = consensus_cache_find_first(cache, "Hello", "mundo");
+ tt_ptr_op(ent2, OP_NE, ent);
+
+ tt_assert(! consensus_cache_entry_is_mapped(ent));
+
+ /* Check get_body */
+ const uint8_t *bp = NULL;
+ size_t sz = 0;
+ int r = consensus_cache_entry_get_body(ent, &bp, &sz);
+ tt_int_op(r, OP_EQ, 0);
+ tt_u64_op(sz, OP_EQ, 5);
+ tt_mem_op(bp, OP_EQ, "A\0B\0C", 5);
+ tt_assert(consensus_cache_entry_is_mapped(ent));
+
+ /* Free and re-create the cache, to rescan the directory. */
+ consensus_cache_free(cache);
+ consensus_cache_entry_decref(ent);
+ cache = consensus_cache_open("cons", 128);
+
+ /* Make sure the entry is still there */
+ ent = consensus_cache_find_first(cache, "Hello", "mundo");
+ tt_assert(ent);
+ ent2 = consensus_cache_find_first(cache, "Adios", "planets");
+ tt_ptr_op(ent, OP_EQ, ent2);
+ consensus_cache_entry_incref(ent);
+ tt_assert(! consensus_cache_entry_is_mapped(ent));
+ r = consensus_cache_entry_get_body(ent, &bp, &sz);
+ tt_int_op(r, OP_EQ, 0);
+ tt_u64_op(sz, OP_EQ, 5);
+ tt_mem_op(bp, OP_EQ, "xyzzy", 5);
+ tt_assert(consensus_cache_entry_is_mapped(ent));
+
+ /* There should be two entries total. */
+ smartlist_t *entries = smartlist_new();
+ consensus_cache_find_all(entries, cache, NULL, NULL);
+ int n = smartlist_len(entries);
+ smartlist_free(entries);
+ tt_int_op(n, OP_EQ, 2);
+
+ done:
+ consensus_cache_entry_decref(ent);
+ tor_free(ddir_fname);
+ consensus_cache_free(cache);
+}
+
+static void
+test_conscache_cleanup(void *arg)
+{
+ (void)arg;
+ const int N = 20;
+ consensus_cache_entry_t **ents =
+ tor_calloc(N, sizeof(consensus_cache_entry_t*));
+
+ /* Make a temporary datadir for these tests */
+ char *ddir_fname = tor_strdup(get_fname_rnd("datadir_cache"));
+ tor_free(get_options_mutable()->DataDirectory);
+ get_options_mutable()->DataDirectory = tor_strdup(ddir_fname);
+ check_private_dir(ddir_fname, CPD_CREATE, NULL);
+ consensus_cache_t *cache = consensus_cache_open("cons", 128);
+
+ tt_assert(cache);
+
+ /* Create a bunch of entries. */
+ int i;
+ for (i = 0; i < N; ++i) {
+ config_line_t *labels = NULL;
+ char num[8];
+ tor_snprintf(num, sizeof(num), "%d", i);
+ config_line_append(&labels, "test-id", "cleanup");
+ config_line_append(&labels, "index", num);
+ size_t bodylen = i * 3;
+ uint8_t *body = tor_malloc(bodylen);
+ memset(body, i, bodylen);
+ ents[i] = consensus_cache_add(cache, labels, body, bodylen);
+ tor_free(body);
+ config_free_lines(labels);
+ tt_assert(ents[i]);
+ /* We're still holding a reference to each entry at this point. */
+ }
+
+ /* Page all of the entries into RAM */
+ for (i = 0; i < N; ++i) {
+ const uint8_t *bp;
+ size_t sz;
+ tt_assert(! consensus_cache_entry_is_mapped(ents[i]));
+ consensus_cache_entry_get_body(ents[i], &bp, &sz);
+ tt_assert(consensus_cache_entry_is_mapped(ents[i]));
+ }
+
+ /* Mark some of the entries as deletable. */
+ for (i = 7; i < N; i += 7) {
+ consensus_cache_entry_mark_for_removal(ents[i]);
+ tt_assert(consensus_cache_entry_is_mapped(ents[i]));
+ }
+
+ /* Mark some of the entries as aggressively unpaged. */
+ for (i = 3; i < N; i += 3) {
+ consensus_cache_entry_mark_for_aggressive_release(ents[i]);
+ tt_assert(consensus_cache_entry_is_mapped(ents[i]));
+ }
+
+ /* Incref some of the entries again */
+ for (i = 0; i < N; i += 2) {
+ consensus_cache_entry_incref(ents[i]);
+ }
+
+ /* Now we're going to decref everything. We do so at a specific time. I'm
+ * picking the moment when I was writing this test, at 2017-04-05 12:16:48
+ * UTC. */
+ const time_t example_time = 1491394608;
+ update_approx_time(example_time);
+ for (i = 0; i < N; ++i) {
+ consensus_cache_entry_decref(ents[i]);
+ if (i % 2) {
+ ents[i] = NULL; /* We're no longer holding any reference here. */
+ }
+ }
+
+ /* At this point, the aggressively-released items with refcount 1 should
+ * be unmapped. Nothing should be deleted. */
+ consensus_cache_entry_t *e_tmp;
+ e_tmp = consensus_cache_find_first(cache, "index", "3");
+ tt_assert(e_tmp);
+ tt_assert(! consensus_cache_entry_is_mapped(e_tmp));
+ e_tmp = consensus_cache_find_first(cache, "index", "5");
+ tt_assert(e_tmp);
+ tt_assert(consensus_cache_entry_is_mapped(e_tmp));
+ e_tmp = consensus_cache_find_first(cache, "index", "6");
+ tt_assert(e_tmp);
+ tt_assert(consensus_cache_entry_is_mapped(e_tmp));
+ e_tmp = consensus_cache_find_first(cache, "index", "7");
+ tt_ptr_op(e_tmp, OP_EQ, NULL); // not found because pending deletion.
+
+ /* Delete the pending-deletion items. */
+ consensus_cache_delete_pending(cache, 0);
+ {
+ smartlist_t *entries = smartlist_new();
+ consensus_cache_find_all(entries, cache, NULL, NULL);
+ int n = smartlist_len(entries);
+ smartlist_free(entries);
+ 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_ptr_op(e_tmp, OP_EQ, NULL); // so deleted.
+ e_tmp = consensus_cache_find_first(cache, "index", "14"); // refcnt == 2
+ tt_ptr_op(e_tmp, OP_EQ, NULL); // not deleted; but not found.
+
+ /* Now do lazy unmapping. */
+ // should do nothing.
+ consensus_cache_unmap_lazy(cache, example_time - 10);
+ e_tmp = consensus_cache_find_first(cache, "index", "11");
+ tt_assert(e_tmp);
+ tt_assert(consensus_cache_entry_is_mapped(e_tmp));
+ // should actually unmap
+ consensus_cache_unmap_lazy(cache, example_time + 10);
+ e_tmp = consensus_cache_find_first(cache, "index", "11");
+ tt_assert(e_tmp);
+ tt_assert(! consensus_cache_entry_is_mapped(e_tmp));
+ // This one will still be mapped, since it has a reference.
+ e_tmp = consensus_cache_find_first(cache, "index", "16");
+ tt_assert(e_tmp);
+ tt_assert(consensus_cache_entry_is_mapped(e_tmp));
+
+ for (i = 0; i < N; ++i) {
+ consensus_cache_entry_decref(ents[i]);
+ ents[i] = NULL;
+ }
+
+ /* Free and re-create the cache, to rescan the directory. Make sure the
+ * deleted thing is still deleted, along with the other deleted thing. */
+ consensus_cache_free(cache);
+ cache = consensus_cache_open("cons", 128);
+ {
+ smartlist_t *entries = smartlist_new();
+ consensus_cache_find_all(entries, cache, NULL, NULL);
+ int n = smartlist_len(entries);
+ smartlist_free(entries);
+ tt_int_op(n, OP_EQ, 18);
+ }
+
+ done:
+ for (i = 0; i < N; ++i) {
+ consensus_cache_entry_decref(ents[i]);
+ }
+ tor_free(ents);
+ tor_free(ddir_fname);
+ consensus_cache_free(cache);
+}
+
+static void
+test_conscache_filter(void *arg)
+{
+ (void)arg;
+ const int N = 30;
+ smartlist_t *lst = NULL;
+
+ /* Make a temporary datadir for these tests */
+ char *ddir_fname = tor_strdup(get_fname_rnd("datadir_cache"));
+ tor_free(get_options_mutable()->DataDirectory);
+ get_options_mutable()->DataDirectory = tor_strdup(ddir_fname);
+ check_private_dir(ddir_fname, CPD_CREATE, NULL);
+ consensus_cache_t *cache = consensus_cache_open("cons", 128);
+
+ tt_assert(cache);
+
+ /* Create a bunch of entries with different labels */
+ int i;
+ for (i = 0; i < N; ++i) {
+ config_line_t *labels = NULL;
+ char num[8];
+ tor_snprintf(num, sizeof(num), "%d", i);
+ config_line_append(&labels, "test-id", "filter");
+ config_line_append(&labels, "index", num);
+ tor_snprintf(num, sizeof(num), "%d", i % 3);
+ config_line_append(&labels, "mod3", num);
+ tor_snprintf(num, sizeof(num), "%d", i % 5);
+ config_line_append(&labels, "mod5", num);
+
+ size_t bodylen = i * 3;
+ uint8_t *body = tor_malloc(bodylen);
+ memset(body, i, bodylen);
+ consensus_cache_entry_t *ent =
+ consensus_cache_add(cache, labels, body, bodylen);
+ tor_free(body);
+ config_free_lines(labels);
+ tt_assert(ent);
+ consensus_cache_entry_decref(ent);
+ }
+
+ lst = smartlist_new();
+ /* Find nothing. */
+ consensus_cache_find_all(lst, cache, "mod5", "5");
+ tt_int_op(smartlist_len(lst), OP_EQ, 0);
+ /* Find everything. */
+ consensus_cache_find_all(lst, cache, "test-id", "filter");
+ tt_int_op(smartlist_len(lst), OP_EQ, N);
+
+ /* Now filter to find the entries that have i%3 == 1 */
+ consensus_cache_filter_list(lst, "mod3", "1");
+ tt_int_op(smartlist_len(lst), OP_EQ, 10);
+ /* Now filter to find the entries that also have i%5 == 3 */
+ consensus_cache_filter_list(lst, "mod5", "3");
+ tt_int_op(smartlist_len(lst), OP_EQ, 2);
+ /* So now we have those entries for which i%15 == 13. */
+
+ consensus_cache_entry_t *ent1 = smartlist_get(lst, 0);
+ consensus_cache_entry_t *ent2 = smartlist_get(lst, 1);
+ const char *idx1 = consensus_cache_entry_get_value(ent1, "index");
+ const char *idx2 = consensus_cache_entry_get_value(ent2, "index");
+ tt_assert( (!strcmp(idx1, "28") && !strcmp(idx2, "13")) ||
+ (!strcmp(idx1, "13") && !strcmp(idx2, "28")) );
+
+ done:
+ tor_free(ddir_fname);
+ consensus_cache_free(cache);
+ smartlist_free(lst);
+}
+
+#define ENT(name) \
+ { #name, test_conscache_ ## name, TT_FORK, NULL, NULL }
+
+struct testcase_t conscache_tests[] = {
+ ENT(open_failure),
+ ENT(simple_usage),
+ ENT(cleanup),
+ ENT(filter),
+ END_OF_TESTCASES
+};
+
diff --git a/src/test/test_consdiff.c b/src/test/test_consdiff.c
new file mode 100644
index 0000000000..fda3a7f186
--- /dev/null
+++ b/src/test/test_consdiff.c
@@ -0,0 +1,1185 @@
+/* Copyright (c) 2014, Daniel Martí
+ * Copyright (c) 2014, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#define CONSDIFF_PRIVATE
+
+#include "or.h"
+#include "test.h"
+
+#include "consdiff.h"
+#include "memarea.h"
+#include "log_test_helpers.h"
+
+#define tt_str_eq_line(a,b) \
+ tt_assert(line_str_eq((b),(a)))
+
+static void
+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, &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(&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(&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:
+ tor_free(sls);
+ smartlist_free(sl);
+}
+
+static void
+test_consdiff_smartlist_slice_string_pos(void *arg)
+{
+ smartlist_t *sl = smartlist_new();
+ smartlist_slice_t *sls;
+ memarea_t *area = memarea_new();
+
+ /* Create a regular smartlist. */
+ (void)arg;
+ consensus_split_lines(sl, "a\nd\nc\na\nb\n", area);
+
+ /* See that smartlist_slice_string_pos respects the bounds of the slice. */
+ sls = smartlist_slice(sl, 2, 5);
+ cdline_t a_line = { "a", 1 };
+ tt_int_op(3, OP_EQ, smartlist_slice_string_pos(sls, &a_line));
+ cdline_t d_line = { "d", 1 };
+ tt_int_op(-1, OP_EQ, smartlist_slice_string_pos(sls, &d_line));
+
+ done:
+ tor_free(sls);
+ smartlist_free(sl);
+ memarea_drop_all(area);
+}
+
+static void
+test_consdiff_lcs_lengths(void *arg)
+{
+ smartlist_t *sl1 = smartlist_new();
+ smartlist_t *sl2 = smartlist_new();
+ smartlist_slice_t *sls1, *sls2;
+ int *lengths1, *lengths2;
+ memarea_t *area = memarea_new();
+
+ /* Expected lcs lengths in regular and reverse order. */
+ int e_lengths1[] = { 0, 1, 2, 3, 3, 4 };
+ int e_lengths2[] = { 0, 1, 1, 2, 3, 4 };
+
+ (void)arg;
+ consensus_split_lines(sl1, "a\nb\nc\nd\ne\n", area);
+ consensus_split_lines(sl2, "a\nc\nd\ni\ne\n", area);
+
+ sls1 = smartlist_slice(sl1, 0, -1);
+ sls2 = smartlist_slice(sl2, 0, -1);
+
+ lengths1 = lcs_lengths(sls1, sls2, 1);
+ lengths2 = lcs_lengths(sls1, sls2, -1);
+ tt_mem_op(e_lengths1, OP_EQ, lengths1, sizeof(int) * 6);
+ tt_mem_op(e_lengths2, OP_EQ, lengths2, sizeof(int) * 6);
+
+ done:
+ tor_free(lengths1);
+ tor_free(lengths2);
+ tor_free(sls1);
+ tor_free(sls2);
+ smartlist_free(sl1);
+ smartlist_free(sl2);
+ memarea_drop_all(area);
+}
+
+static void
+test_consdiff_trim_slices(void *arg)
+{
+ smartlist_t *sl1 = smartlist_new();
+ smartlist_t *sl2 = smartlist_new();
+ smartlist_t *sl3 = smartlist_new();
+ smartlist_t *sl4 = smartlist_new();
+ smartlist_slice_t *sls1, *sls2, *sls3, *sls4;
+ memarea_t *area = memarea_new();
+
+ (void)arg;
+ consensus_split_lines(sl1, "a\nb\nb\nb\nd\n", area);
+ consensus_split_lines(sl2, "a\nc\nc\nc\nd\n", area);
+ consensus_split_lines(sl3, "a\nb\nb\nb\na\n", area);
+ consensus_split_lines(sl4, "c\nb\nb\nb\nc\n", area);
+ sls1 = smartlist_slice(sl1, 0, -1);
+ sls2 = smartlist_slice(sl2, 0, -1);
+ sls3 = smartlist_slice(sl3, 0, -1);
+ sls4 = smartlist_slice(sl4, 0, -1);
+
+ /* They should be trimmed by one line at each end. */
+ tt_int_op(5, OP_EQ, sls1->len);
+ tt_int_op(5, OP_EQ, sls2->len);
+ trim_slices(sls1, sls2);
+ tt_int_op(3, OP_EQ, sls1->len);
+ tt_int_op(3, OP_EQ, sls2->len);
+
+ /* They should not be trimmed at all. */
+ tt_int_op(5, OP_EQ, sls3->len);
+ tt_int_op(5, OP_EQ, sls4->len);
+ trim_slices(sls3, sls4);
+ tt_int_op(5, OP_EQ, sls3->len);
+ tt_int_op(5, OP_EQ, sls4->len);
+
+ done:
+ tor_free(sls1);
+ tor_free(sls2);
+ tor_free(sls3);
+ tor_free(sls4);
+ smartlist_free(sl1);
+ smartlist_free(sl2);
+ smartlist_free(sl3);
+ smartlist_free(sl4);
+ memarea_drop_all(area);
+}
+
+static void
+test_consdiff_set_changed(void *arg)
+{
+ smartlist_t *sl1 = smartlist_new();
+ smartlist_t *sl2 = smartlist_new();
+ bitarray_t *changed1 = bitarray_init_zero(4);
+ bitarray_t *changed2 = bitarray_init_zero(4);
+ smartlist_slice_t *sls1, *sls2;
+ memarea_t *area = memarea_new();
+
+ (void)arg;
+ consensus_split_lines(sl1, "a\nb\na\na\n", area);
+ consensus_split_lines(sl2, "a\na\na\na\n", area);
+
+ /* Length of sls1 is 0. */
+ sls1 = smartlist_slice(sl1, 0, 0);
+ sls2 = smartlist_slice(sl2, 1, 3);
+ set_changed(changed1, changed2, sls1, sls2);
+
+ /* The former is not changed, the latter changes all of its elements. */
+ tt_assert(!bitarray_is_set(changed1, 0));
+ tt_assert(!bitarray_is_set(changed1, 1));
+ tt_assert(!bitarray_is_set(changed1, 2));
+ tt_assert(!bitarray_is_set(changed1, 3));
+
+ tt_assert(!bitarray_is_set(changed2, 0));
+ tt_assert(bitarray_is_set(changed2, 1));
+ tt_assert(bitarray_is_set(changed2, 2));
+ tt_assert(!bitarray_is_set(changed2, 3));
+ bitarray_clear(changed2, 1);
+ bitarray_clear(changed2, 2);
+
+ /* Length of sls1 is 1 and its element is in sls2. */
+ tor_free(sls1);
+ sls1 = smartlist_slice(sl1, 0, 1);
+ set_changed(changed1, changed2, sls1, sls2);
+
+ /* The latter changes all elements but the (first) common one. */
+ tt_assert(!bitarray_is_set(changed1, 0));
+ tt_assert(!bitarray_is_set(changed1, 1));
+ tt_assert(!bitarray_is_set(changed1, 2));
+ tt_assert(!bitarray_is_set(changed1, 3));
+
+ tt_assert(!bitarray_is_set(changed2, 0));
+ tt_assert(!bitarray_is_set(changed2, 1));
+ tt_assert(bitarray_is_set(changed2, 2));
+ tt_assert(!bitarray_is_set(changed2, 3));
+ bitarray_clear(changed2, 2);
+
+ /* Length of sls1 is 1 and its element is not in sls2. */
+ tor_free(sls1);
+ sls1 = smartlist_slice(sl1, 1, 2);
+ set_changed(changed1, changed2, sls1, sls2);
+
+ /* The former changes its element, the latter changes all elements. */
+ tt_assert(!bitarray_is_set(changed1, 0));
+ tt_assert(bitarray_is_set(changed1, 1));
+ tt_assert(!bitarray_is_set(changed1, 2));
+ tt_assert(!bitarray_is_set(changed1, 3));
+
+ tt_assert(!bitarray_is_set(changed2, 0));
+ tt_assert(bitarray_is_set(changed2, 1));
+ tt_assert(bitarray_is_set(changed2, 2));
+ tt_assert(!bitarray_is_set(changed2, 3));
+
+ done:
+ bitarray_free(changed1);
+ bitarray_free(changed2);
+ smartlist_free(sl1);
+ smartlist_free(sl2);
+ tor_free(sls1);
+ tor_free(sls2);
+ memarea_drop_all(area);
+}
+
+static void
+test_consdiff_calc_changes(void *arg)
+{
+ smartlist_t *sl1 = smartlist_new();
+ smartlist_t *sl2 = smartlist_new();
+ smartlist_slice_t *sls1, *sls2;
+ bitarray_t *changed1 = bitarray_init_zero(4);
+ bitarray_t *changed2 = bitarray_init_zero(4);
+ memarea_t *area = memarea_new();
+
+ (void)arg;
+ consensus_split_lines(sl1, "a\na\na\na\n", area);
+ consensus_split_lines(sl2, "a\na\na\na\n", area);
+
+ sls1 = smartlist_slice(sl1, 0, -1);
+ sls2 = smartlist_slice(sl2, 0, -1);
+ calc_changes(sls1, sls2, changed1, changed2);
+
+ /* Nothing should be set to changed. */
+ tt_assert(!bitarray_is_set(changed1, 0));
+ tt_assert(!bitarray_is_set(changed1, 1));
+ tt_assert(!bitarray_is_set(changed1, 2));
+ tt_assert(!bitarray_is_set(changed1, 3));
+
+ tt_assert(!bitarray_is_set(changed2, 0));
+ tt_assert(!bitarray_is_set(changed2, 1));
+ tt_assert(!bitarray_is_set(changed2, 2));
+ tt_assert(!bitarray_is_set(changed2, 3));
+
+ smartlist_clear(sl2);
+ consensus_split_lines(sl2, "a\nb\na\nb\n", area);
+ tor_free(sls1);
+ tor_free(sls2);
+ sls1 = smartlist_slice(sl1, 0, -1);
+ sls2 = smartlist_slice(sl2, 0, -1);
+ calc_changes(sls1, sls2, changed1, changed2);
+
+ /* Two elements are changed. */
+ tt_assert(!bitarray_is_set(changed1, 0));
+ tt_assert(bitarray_is_set(changed1, 1));
+ tt_assert(bitarray_is_set(changed1, 2));
+ tt_assert(!bitarray_is_set(changed1, 3));
+ bitarray_clear(changed1, 1);
+ bitarray_clear(changed1, 2);
+
+ tt_assert(!bitarray_is_set(changed2, 0));
+ tt_assert(bitarray_is_set(changed2, 1));
+ tt_assert(!bitarray_is_set(changed2, 2));
+ tt_assert(bitarray_is_set(changed2, 3));
+ bitarray_clear(changed1, 1);
+ bitarray_clear(changed1, 3);
+
+ smartlist_clear(sl2);
+ consensus_split_lines(sl2, "b\nb\nb\nb\n", area);
+ tor_free(sls1);
+ tor_free(sls2);
+ sls1 = smartlist_slice(sl1, 0, -1);
+ sls2 = smartlist_slice(sl2, 0, -1);
+ calc_changes(sls1, sls2, changed1, changed2);
+
+ /* All elements are changed. */
+ tt_assert(bitarray_is_set(changed1, 0));
+ tt_assert(bitarray_is_set(changed1, 1));
+ tt_assert(bitarray_is_set(changed1, 2));
+ tt_assert(bitarray_is_set(changed1, 3));
+
+ tt_assert(bitarray_is_set(changed2, 0));
+ tt_assert(bitarray_is_set(changed2, 1));
+ tt_assert(bitarray_is_set(changed2, 2));
+ tt_assert(bitarray_is_set(changed2, 3));
+
+ done:
+ bitarray_free(changed1);
+ bitarray_free(changed2);
+ smartlist_free(sl1);
+ smartlist_free(sl2);
+ tor_free(sls1);
+ tor_free(sls2);
+ memarea_drop_all(area);
+}
+
+static void
+test_consdiff_get_id_hash(void *arg)
+{
+ (void)arg;
+
+ cdline_t line1 = { "r name", 6 };
+ cdline_t line2 = { "r name _hash_isnt_base64 etc", 28 };
+ cdline_t line3 = { "r name hash+valid+base64 etc", 28 };
+ cdline_t tmp;
+
+ /* No hash. */
+ tt_int_op(-1, OP_EQ, get_id_hash(&line1, &tmp));
+ /* The hash contains characters that are not base64. */
+ tt_int_op(-1, OP_EQ, get_id_hash(&line2, &tmp));
+
+ /* valid hash. */
+ tt_int_op(0, OP_EQ, get_id_hash(&line3, &tmp));
+ tt_ptr_op(tmp.s, OP_EQ, line3.s + 7);
+ tt_uint_op(tmp.len, OP_EQ, line3.len - 11);
+
+ done:
+ ;
+}
+
+static void
+test_consdiff_is_valid_router_entry(void *arg)
+{
+ /* Doesn't start with "r ". */
+ (void)arg;
+ cdline_t line0 = { "foo", 3 };
+ tt_int_op(0, OP_EQ, is_valid_router_entry(&line0));
+
+ /* These are already tested with get_id_hash, but make sure it's run
+ * properly. */
+
+ cdline_t line1 = { "r name", 6 };
+ cdline_t line2 = { "r name _hash_isnt_base64 etc", 28 };
+ cdline_t line3 = { "r name hash+valid+base64 etc", 28 };
+ tt_int_op(0, OP_EQ, is_valid_router_entry(&line1));
+ tt_int_op(0, OP_EQ, is_valid_router_entry(&line2));
+ tt_int_op(1, OP_EQ, is_valid_router_entry(&line3));
+
+ done:
+ ;
+}
+
+static void
+test_consdiff_next_router(void *arg)
+{
+ smartlist_t *sl = smartlist_new();
+ memarea_t *area = memarea_new();
+ (void)arg;
+ smartlist_add_linecpy(sl, area, "foo");
+ smartlist_add_linecpy(sl, area,
+ "r name hash+longer+than+27+chars+and+valid+base64 etc");
+ smartlist_add_linecpy(sl, area, "foo");
+ smartlist_add_linecpy(sl, area, "foo");
+ smartlist_add_linecpy(sl, area,
+ "r name hash+longer+than+27+chars+and+valid+base64 etc");
+ smartlist_add_linecpy(sl, area, "foo");
+
+ /* Not currently on a router entry line, finding the next one. */
+ tt_int_op(1, OP_EQ, next_router(sl, 0));
+ tt_int_op(4, OP_EQ, next_router(sl, 2));
+
+ /* Already at the beginning of a router entry line, ignore it. */
+ tt_int_op(4, OP_EQ, next_router(sl, 1));
+
+ /* There are no more router entries, so return the line after the last. */
+ tt_int_op(6, OP_EQ, next_router(sl, 4));
+ tt_int_op(6, OP_EQ, next_router(sl, 5));
+
+ done:
+ smartlist_free(sl);
+ memarea_drop_all(area);
+}
+
+static int
+base64cmp_wrapper(const char *a, const char *b)
+{
+ cdline_t aa = { a, a ? (uint32_t) strlen(a) : 0 };
+ cdline_t bb = { b, b ? (uint32_t) strlen(b) : 0 };
+ return base64cmp(&aa, &bb);
+}
+
+static void
+test_consdiff_base64cmp(void *arg)
+{
+ /* NULL arguments. */
+ (void)arg;
+ tt_int_op(0, OP_EQ, base64cmp_wrapper(NULL, NULL));
+ tt_int_op(-1, OP_EQ, base64cmp_wrapper(NULL, "foo"));
+ tt_int_op(1, OP_EQ, base64cmp_wrapper("bar", NULL));
+
+ /* Nil base64 values. */
+ tt_int_op(0, OP_EQ, base64cmp_wrapper("", ""));
+ tt_int_op(0, OP_EQ, base64cmp_wrapper("_", "&"));
+
+ /* Exact same valid strings. */
+ tt_int_op(0, OP_EQ, base64cmp_wrapper("abcABC/+", "abcABC/+"));
+ /* Both end with an invalid base64 char other than '\0'. */
+ tt_int_op(0, OP_EQ, base64cmp_wrapper("abcABC/+ ", "abcABC/+ "));
+ /* Only one ends with an invalid base64 char other than '\0'. */
+ tt_int_op(-1, OP_EQ, base64cmp_wrapper("abcABC/+ ", "abcABC/+a"));
+
+ /* Comparisons that would return differently with strcmp(). */
+ tt_int_op(strcmp("/foo", "Afoo"), OP_LT, 0);
+ tt_int_op(base64cmp_wrapper("/foo", "Afoo"), OP_GT, 0);
+ tt_int_op(strcmp("Afoo", "0foo"), OP_GT, 0);
+ tt_int_op(base64cmp_wrapper("Afoo", "0foo"), OP_LT, 0);
+
+ /* Comparisons that would return the same as with strcmp(). */
+ tt_int_op(strcmp("afoo", "Afoo"), OP_GT, 0);
+ tt_int_op(base64cmp_wrapper("afoo", "Afoo"), OP_GT, 0);
+
+ /* Different lengths */
+ tt_int_op(base64cmp_wrapper("afoo", "afooo"), OP_LT, 0);
+ tt_int_op(base64cmp_wrapper("afooo", "afoo"), OP_GT, 0);
+
+ done:
+ ;
+}
+
+static void
+test_consdiff_gen_ed_diff(void *arg)
+{
+ smartlist_t *cons1=NULL, *cons2=NULL, *diff=NULL;
+ int i;
+ memarea_t *area = memarea_new();
+ setup_capture_of_logs(LOG_WARN);
+
+ (void)arg;
+ cons1 = smartlist_new();
+ cons2 = smartlist_new();
+
+ /* Identity hashes are not sorted properly, return NULL. */
+ smartlist_add_linecpy(cons1, area, "r name bbbbbbbbbbbbbbbbbbbbbbbbbbb etc");
+ smartlist_add_linecpy(cons1, area, "foo");
+ smartlist_add_linecpy(cons1, area, "r name aaaaaaaaaaaaaaaaaaaaaaaaaaa etc");
+ smartlist_add_linecpy(cons1, area, "bar");
+
+ smartlist_add_linecpy(cons2, area, "r name aaaaaaaaaaaaaaaaaaaaaaaaaaa etc");
+ smartlist_add_linecpy(cons2, area, "foo");
+ smartlist_add_linecpy(cons2, area, "r name ccccccccccccccccccccccccccc etc");
+ smartlist_add_linecpy(cons2, area, "bar");
+
+ diff = gen_ed_diff(cons1, cons2, area);
+ tt_ptr_op(NULL, OP_EQ, diff);
+ expect_single_log_msg_containing("Refusing to generate consensus diff "
+ "because the base consensus doesn't have its router entries sorted "
+ "properly.");
+
+ /* Same, but now with the second consensus. */
+ mock_clean_saved_logs();
+ diff = gen_ed_diff(cons2, cons1, area);
+ tt_ptr_op(NULL, OP_EQ, diff);
+ expect_single_log_msg_containing("Refusing to generate consensus diff "
+ "because the target consensus doesn't have its router entries sorted "
+ "properly.");
+
+ /* Same as the two above, but with the reversed thing immediately after a
+ match. (The code handles this differently) */
+ smartlist_del(cons1, 0);
+ smartlist_add_linecpy(cons1, area, "r name aaaaaaaaaaaaaaaaaaaaaaaaaaa etc");
+
+ mock_clean_saved_logs();
+ diff = gen_ed_diff(cons1, cons2, area);
+ tt_ptr_op(NULL, OP_EQ, diff);
+ expect_single_log_msg_containing("Refusing to generate consensus diff "
+ "because the base consensus doesn't have its router entries sorted "
+ "properly.");
+
+ mock_clean_saved_logs();
+ diff = gen_ed_diff(cons2, cons1, area);
+ tt_ptr_op(NULL, OP_EQ, diff);
+ expect_single_log_msg_containing("Refusing to generate consensus diff "
+ "because the target consensus doesn't have its router entries sorted "
+ "properly.");
+
+ /* Identity hashes are repeated, return NULL. */
+ smartlist_clear(cons1);
+
+ smartlist_add_linecpy(cons1, area, "r name bbbbbbbbbbbbbbbbbbbbbbbbbbb etc");
+ smartlist_add_linecpy(cons1, area, "foo");
+ smartlist_add_linecpy(cons1, area, "r name bbbbbbbbbbbbbbbbbbbbbbbbbbb etc");
+ smartlist_add_linecpy(cons1, area, "bar");
+
+ mock_clean_saved_logs();
+ diff = gen_ed_diff(cons1, cons2, area);
+ tt_ptr_op(NULL, OP_EQ, diff);
+ expect_single_log_msg_containing("Refusing to generate consensus diff "
+ "because the base consensus doesn't have its router entries sorted "
+ "properly.");
+
+ /* We have to add a line that is just a dot, return NULL. */
+ smartlist_clear(cons1);
+ smartlist_clear(cons2);
+
+ smartlist_add_linecpy(cons1, area, "foo1");
+ smartlist_add_linecpy(cons1, area, "foo2");
+
+ smartlist_add_linecpy(cons2, area, "foo1");
+ smartlist_add_linecpy(cons2, area, ".");
+ smartlist_add_linecpy(cons2, area, "foo2");
+
+ mock_clean_saved_logs();
+ diff = gen_ed_diff(cons1, cons2, area);
+ tt_ptr_op(NULL, OP_EQ, diff);
+ expect_single_log_msg_containing("Cannot generate consensus diff "
+ "because one of the lines to be added is \".\".");
+
+#define MAX_LINE_COUNT (10000)
+ /* Too many lines to be fed to the quadratic-time function. */
+ smartlist_clear(cons1);
+ smartlist_clear(cons2);
+
+ for (i=0; i < MAX_LINE_COUNT; ++i) smartlist_add_linecpy(cons1, area, "a");
+ for (i=0; i < MAX_LINE_COUNT; ++i) smartlist_add_linecpy(cons1, area, "b");
+
+ mock_clean_saved_logs();
+ diff = gen_ed_diff(cons1, cons2, area);
+
+ tt_ptr_op(NULL, OP_EQ, diff);
+ expect_single_log_msg_containing("Refusing to generate consensus diff "
+ "because we found too few common router ids.");
+
+ /* We have dot lines, but they don't interfere with the script format. */
+ smartlist_clear(cons1);
+ smartlist_clear(cons2);
+
+ smartlist_add_linecpy(cons1, area, "foo1");
+ smartlist_add_linecpy(cons1, area, ".");
+ smartlist_add_linecpy(cons1, area, ".");
+ smartlist_add_linecpy(cons1, area, "foo2");
+
+ smartlist_add_linecpy(cons2, area, "foo1");
+ smartlist_add_linecpy(cons2, area, ".");
+ smartlist_add_linecpy(cons2, area, "foo2");
+
+ diff = gen_ed_diff(cons1, cons2, area);
+ tt_ptr_op(NULL, OP_NE, diff);
+ smartlist_free(diff);
+
+ /* Empty diff tests. */
+ smartlist_clear(cons1);
+ smartlist_clear(cons2);
+
+ diff = gen_ed_diff(cons1, cons2, area);
+ tt_ptr_op(NULL, OP_NE, diff);
+ tt_int_op(0, OP_EQ, smartlist_len(diff));
+ smartlist_free(diff);
+
+ smartlist_add_linecpy(cons1, area, "foo");
+ smartlist_add_linecpy(cons1, area, "bar");
+
+ smartlist_add_linecpy(cons2, area, "foo");
+ smartlist_add_linecpy(cons2, area, "bar");
+
+ diff = gen_ed_diff(cons1, cons2, area);
+ tt_ptr_op(NULL, OP_NE, diff);
+ tt_int_op(0, OP_EQ, smartlist_len(diff));
+ smartlist_free(diff);
+
+ /* Everything is deleted. */
+ smartlist_clear(cons2);
+
+ diff = gen_ed_diff(cons1, cons2, area);
+ tt_ptr_op(NULL, OP_NE, diff);
+ tt_int_op(1, OP_EQ, smartlist_len(diff));
+ tt_str_eq_line("1,2d", smartlist_get(diff, 0));
+
+ smartlist_free(diff);
+
+ /* Everything is added. */
+ diff = gen_ed_diff(cons2, cons1, area);
+ tt_ptr_op(NULL, OP_NE, diff);
+ tt_int_op(4, OP_EQ, smartlist_len(diff));
+ tt_str_eq_line("0a", smartlist_get(diff, 0));
+ tt_str_eq_line("foo", smartlist_get(diff, 1));
+ tt_str_eq_line("bar", smartlist_get(diff, 2));
+ tt_str_eq_line(".", smartlist_get(diff, 3));
+
+ smartlist_free(diff);
+
+ /* Everything is changed. */
+ smartlist_add_linecpy(cons2, area, "foo2");
+ smartlist_add_linecpy(cons2, area, "bar2");
+ diff = gen_ed_diff(cons1, cons2, area);
+ tt_ptr_op(NULL, OP_NE, diff);
+ tt_int_op(4, OP_EQ, smartlist_len(diff));
+ tt_str_eq_line("1,2c", smartlist_get(diff, 0));
+ tt_str_eq_line("foo2", smartlist_get(diff, 1));
+ tt_str_eq_line("bar2", smartlist_get(diff, 2));
+ tt_str_eq_line(".", smartlist_get(diff, 3));
+
+ smartlist_free(diff);
+
+ /* Test 'a', 'c' and 'd' together. See that it is done in reverse order. */
+ smartlist_clear(cons1);
+ smartlist_clear(cons2);
+ consensus_split_lines(cons1, "A\nB\nC\nD\nE\n", area);
+ consensus_split_lines(cons2, "A\nC\nO\nE\nU\n", area);
+ diff = gen_ed_diff(cons1, cons2, area);
+ tt_ptr_op(NULL, OP_NE, diff);
+ tt_int_op(7, OP_EQ, smartlist_len(diff));
+ tt_str_eq_line("5a", smartlist_get(diff, 0));
+ tt_str_eq_line("U", smartlist_get(diff, 1));
+ tt_str_eq_line(".", smartlist_get(diff, 2));
+ tt_str_eq_line("4c", smartlist_get(diff, 3));
+ tt_str_eq_line("O", smartlist_get(diff, 4));
+ tt_str_eq_line(".", smartlist_get(diff, 5));
+ tt_str_eq_line("2d", smartlist_get(diff, 6));
+
+ smartlist_free(diff);
+
+ smartlist_clear(cons1);
+ smartlist_clear(cons2);
+ consensus_split_lines(cons1, "B\n", area);
+ consensus_split_lines(cons2, "A\nB\n", area);
+ diff = gen_ed_diff(cons1, cons2, area);
+ tt_ptr_op(NULL, OP_NE, diff);
+ tt_int_op(3, OP_EQ, smartlist_len(diff));
+ tt_str_eq_line("0a", smartlist_get(diff, 0));
+ tt_str_eq_line("A", smartlist_get(diff, 1));
+ tt_str_eq_line(".", smartlist_get(diff, 2));
+
+ /* TODO: small real use-cases, i.e. consensuses. */
+
+ done:
+ teardown_capture_of_logs();
+ smartlist_free(cons1);
+ smartlist_free(cons2);
+ smartlist_free(diff);
+ memarea_drop_all(area);
+}
+
+static void
+test_consdiff_apply_ed_diff(void *arg)
+{
+ smartlist_t *cons1=NULL, *cons2=NULL, *diff=NULL;
+ memarea_t *area = memarea_new();
+ (void)arg;
+ cons1 = smartlist_new();
+ diff = smartlist_new();
+ setup_capture_of_logs(LOG_WARN);
+
+ consensus_split_lines(cons1, "A\nB\nC\nD\nE\n", area);
+
+ /* Command without range. */
+ smartlist_add_linecpy(diff, area, "a");
+ cons2 = apply_ed_diff(cons1, diff, 0);
+ tt_ptr_op(NULL, OP_EQ, cons2);
+ smartlist_clear(diff);
+ expect_single_log_msg_containing("an ed command was missing a line number");
+
+ /* Range without command. */
+ smartlist_add_linecpy(diff, area, "1");
+ mock_clean_saved_logs();
+ cons2 = apply_ed_diff(cons1, diff, 0);
+ tt_ptr_op(NULL, OP_EQ, cons2);
+ expect_single_log_msg_containing("a line with no ed command was found");
+
+ smartlist_clear(diff);
+
+ /* Range without end. */
+ smartlist_add_linecpy(diff, area, "1,");
+ mock_clean_saved_logs();
+ cons2 = apply_ed_diff(cons1, diff, 0);
+ tt_ptr_op(NULL, OP_EQ, cons2);
+ expect_single_log_msg_containing("an ed command was missing a range "
+ "end line number.");
+
+ smartlist_clear(diff);
+
+ /* Incoherent ranges. */
+ smartlist_add_linecpy(diff, area, "1,1");
+ mock_clean_saved_logs();
+ cons2 = apply_ed_diff(cons1, diff, 0);
+ tt_ptr_op(NULL, OP_EQ, cons2);
+ expect_single_log_msg_containing("an invalid range was found");
+
+ smartlist_clear(diff);
+
+ smartlist_add_linecpy(diff, area, "3,2");
+ mock_clean_saved_logs();
+ cons2 = apply_ed_diff(cons1, diff, 0);
+ tt_ptr_op(NULL, OP_EQ, cons2);
+ expect_single_log_msg_containing("an invalid range was found");
+
+ smartlist_clear(diff);
+
+ /* Unexpected range for add command. */
+ smartlist_add_linecpy(diff, area, "1,2a");
+ mock_clean_saved_logs();
+ cons2 = apply_ed_diff(cons1, diff, 0);
+ tt_ptr_op(NULL, OP_EQ, cons2);
+ expect_single_log_msg_containing("add lines after a range");
+
+ smartlist_clear(diff);
+
+ /* $ for a non-delete command. */
+ smartlist_add_linecpy(diff, area, "1,$c");
+ mock_clean_saved_logs();
+ cons2 = apply_ed_diff(cons1, diff, 0);
+ tt_ptr_op(NULL, OP_EQ, cons2);
+ expect_single_log_msg_containing("it wanted to use $ with a command "
+ "other than delete");
+
+ smartlist_clear(diff);
+
+ /* Script is not in reverse order. */
+ smartlist_add_linecpy(diff, area, "1d");
+ smartlist_add_linecpy(diff, area, "3d");
+ mock_clean_saved_logs();
+ cons2 = apply_ed_diff(cons1, diff, 0);
+ tt_ptr_op(NULL, OP_EQ, cons2);
+ expect_single_log_msg_containing("its commands are not properly sorted");
+
+ smartlist_clear(diff);
+
+ /* Script contains unrecognised commands longer than one char. */
+ smartlist_add_linecpy(diff, area, "1foo");
+ mock_clean_saved_logs();
+ cons2 = apply_ed_diff(cons1, diff, 0);
+ tt_ptr_op(NULL, OP_EQ, cons2);
+ expect_single_log_msg_containing("an ed command longer than one char was "
+ "found");
+
+ smartlist_clear(diff);
+
+ /* Script contains unrecognised commands. */
+ smartlist_add_linecpy(diff, area, "1e");
+ mock_clean_saved_logs();
+ cons2 = apply_ed_diff(cons1, diff, 0);
+ tt_ptr_op(NULL, OP_EQ, cons2);
+ expect_single_log_msg_containing("an unrecognised ed command was found");
+
+ smartlist_clear(diff);
+
+ /* Command that should be followed by at least one line and a ".", but
+ * isn't. */
+ smartlist_add_linecpy(diff, area, "0a");
+ mock_clean_saved_logs();
+ cons2 = apply_ed_diff(cons1, diff, 0);
+ tt_ptr_op(NULL, OP_EQ, cons2);
+ expect_single_log_msg_containing("it has an ed command that tries to "
+ "insert zero lines.");
+
+ /* Now it is followed by a ".", but it inserts zero lines. */
+ smartlist_add_linecpy(diff, area, ".");
+ mock_clean_saved_logs();
+ cons2 = apply_ed_diff(cons1, diff, 0);
+ tt_ptr_op(NULL, OP_EQ, cons2);
+ expect_single_log_msg_containing("it has an ed command that tries to "
+ "insert zero lines.");
+
+ smartlist_clear(diff);
+
+ /* Now it it inserts something, but has no terminator. */
+ smartlist_add_linecpy(diff, area, "0a");
+ smartlist_add_linecpy(diff, area, "hello");
+ mock_clean_saved_logs();
+ cons2 = apply_ed_diff(cons1, diff, 0);
+ tt_ptr_op(NULL, OP_EQ, cons2);
+ expect_single_log_msg_containing("lines to be inserted that don't end with "
+ "a \".\".");
+
+ smartlist_clear(diff);
+
+ /* Ranges must be numeric only and cannot contain spaces. */
+ smartlist_add_linecpy(diff, area, "0, 4d");
+ mock_clean_saved_logs();
+ cons2 = apply_ed_diff(cons1, diff, 0);
+ tt_ptr_op(NULL, OP_EQ, cons2);
+ expect_single_log_msg_containing("an ed command was missing a range "
+ "end line number.");
+
+ smartlist_clear(diff);
+
+ /* '+' is not a number. */
+ smartlist_add_linecpy(diff, area, "+0,4d");
+ mock_clean_saved_logs();
+ cons2 = apply_ed_diff(cons1, diff, 0);
+ tt_ptr_op(NULL, OP_EQ, cons2);
+ expect_single_log_msg_containing("an ed command was missing a line number");
+
+ smartlist_clear(diff);
+
+ /* range duplication */
+ smartlist_add_linecpy(diff, area, "0,4d,5d");
+ mock_clean_saved_logs();
+ cons2 = apply_ed_diff(cons1, diff, 0);
+ tt_ptr_op(NULL, OP_EQ, cons2);
+ expect_single_log_msg_containing("an ed command longer than one char was "
+ "found");
+
+ smartlist_clear(diff);
+
+ /* space before command */
+ smartlist_add_linecpy(diff, area, "0,4 d");
+ mock_clean_saved_logs();
+ cons2 = apply_ed_diff(cons1, diff, 0);
+ tt_ptr_op(NULL, OP_EQ, cons2);
+ expect_single_log_msg_containing("an ed command longer than one char was "
+ "found");
+
+ smartlist_clear(diff);
+
+ /* space inside number */
+ smartlist_add_linecpy(diff, area, "0,4 5d");
+ mock_clean_saved_logs();
+ cons2 = apply_ed_diff(cons1, diff, 0);
+ tt_ptr_op(NULL, OP_EQ, cons2);
+ expect_single_log_msg_containing("an ed command longer than one char was "
+ "found");
+
+ smartlist_clear(diff);
+
+ /* Test appending text, 'a'. */
+ consensus_split_lines(diff, "3a\nU\nO\n.\n0a\nV\n.\n", area);
+ cons2 = apply_ed_diff(cons1, diff, 0);
+ tt_ptr_op(NULL, OP_NE, cons2);
+ tt_int_op(8, OP_EQ, smartlist_len(cons2));
+ tt_str_eq_line("V", smartlist_get(cons2, 0));
+ tt_str_eq_line("A", smartlist_get(cons2, 1));
+ tt_str_eq_line("B", smartlist_get(cons2, 2));
+ tt_str_eq_line("C", smartlist_get(cons2, 3));
+ tt_str_eq_line("U", smartlist_get(cons2, 4));
+ tt_str_eq_line("O", smartlist_get(cons2, 5));
+ tt_str_eq_line("D", smartlist_get(cons2, 6));
+ tt_str_eq_line("E", smartlist_get(cons2, 7));
+
+ smartlist_clear(diff);
+ smartlist_free(cons2);
+
+ /* Test deleting text, 'd'. */
+ consensus_split_lines(diff, "4d\n1,2d\n", area);
+ cons2 = apply_ed_diff(cons1, diff, 0);
+ tt_ptr_op(NULL, OP_NE, cons2);
+ tt_int_op(2, OP_EQ, smartlist_len(cons2));
+ tt_str_eq_line("C", smartlist_get(cons2, 0));
+ tt_str_eq_line("E", smartlist_get(cons2, 1));
+
+ smartlist_clear(diff);
+ smartlist_free(cons2);
+
+ /* Test changing text, 'c'. */
+ consensus_split_lines(diff, "4c\nT\nX\n.\n1,2c\nM\n.\n", area);
+ cons2 = apply_ed_diff(cons1, diff, 0);
+ tt_ptr_op(NULL, OP_NE, cons2);
+ tt_int_op(5, OP_EQ, smartlist_len(cons2));
+ tt_str_eq_line("M", smartlist_get(cons2, 0));
+ tt_str_eq_line("C", smartlist_get(cons2, 1));
+ tt_str_eq_line("T", smartlist_get(cons2, 2));
+ tt_str_eq_line("X", smartlist_get(cons2, 3));
+ tt_str_eq_line("E", smartlist_get(cons2, 4));
+
+ smartlist_clear(diff);
+ smartlist_free(cons2);
+
+ /* Test 'a', 'd' and 'c' together. */
+ consensus_split_lines(diff, "4c\nT\nX\n.\n2d\n0a\nM\n.\n", area);
+ cons2 = apply_ed_diff(cons1, diff, 0);
+ tt_ptr_op(NULL, OP_NE, cons2);
+ tt_int_op(6, OP_EQ, smartlist_len(cons2));
+ tt_str_eq_line("M", smartlist_get(cons2, 0));
+ tt_str_eq_line("A", smartlist_get(cons2, 1));
+ tt_str_eq_line("C", smartlist_get(cons2, 2));
+ tt_str_eq_line("T", smartlist_get(cons2, 3));
+ tt_str_eq_line("X", smartlist_get(cons2, 4));
+ tt_str_eq_line("E", smartlist_get(cons2, 5));
+
+ done:
+ teardown_capture_of_logs();
+ smartlist_free(cons1);
+ smartlist_free(cons2);
+ smartlist_free(diff);
+ memarea_drop_all(area);
+}
+
+static void
+test_consdiff_gen_diff(void *arg)
+{
+ char *cons1_str=NULL, *cons2_str=NULL;
+ smartlist_t *cons1=NULL, *cons2=NULL, *diff=NULL;
+ consensus_digest_t digests1, digests2;
+ memarea_t *area = memarea_new();
+ (void)arg;
+ cons1 = smartlist_new();
+ cons2 = smartlist_new();
+
+ /* Identity hashes are not sorted properly, return NULL.
+ * Already tested in gen_ed_diff, but see that a NULL ed diff also makes
+ * gen_diff return NULL. */
+ cons1_str = tor_strdup(
+ "network-status-version foo\n"
+ "r name bbbbbbbbbbbbbbbbb etc\nfoo\n"
+ "r name aaaaaaaaaaaaaaaaa etc\nbar\n"
+ "directory-signature foo bar\nbar\n"
+ );
+ cons2_str = tor_strdup(
+ "network-status-version foo\n"
+ "r name aaaaaaaaaaaaaaaaa etc\nfoo\n"
+ "r name ccccccccccccccccc etc\nbar\n"
+ "directory-signature foo bar\nbar\n"
+ );
+
+ tt_int_op(0, OP_EQ,
+ consensus_compute_digest_as_signed(cons1_str, &digests1));
+ tt_int_op(0, OP_EQ,
+ consensus_compute_digest(cons2_str, &digests2));
+
+ consensus_split_lines(cons1, cons1_str, area);
+ consensus_split_lines(cons2, cons2_str, area);
+
+ diff = consdiff_gen_diff(cons1, cons2, &digests1, &digests2, area);
+ tt_ptr_op(NULL, OP_EQ, diff);
+
+ /* Check that the headers are done properly. */
+ tor_free(cons1_str);
+ cons1_str = tor_strdup(
+ "network-status-version foo\n"
+ "r name ccccccccccccccccc etc\nfoo\n"
+ "r name eeeeeeeeeeeeeeeee etc\nbar\n"
+ "directory-signature foo bar\nbar\n"
+ );
+ tt_int_op(0, OP_EQ,
+ consensus_compute_digest_as_signed(cons1_str, &digests1));
+ smartlist_clear(cons1);
+ consensus_split_lines(cons1, cons1_str, area);
+ diff = consdiff_gen_diff(cons1, cons2, &digests1, &digests2, area);
+ tt_ptr_op(NULL, OP_NE, diff);
+ tt_int_op(11, OP_EQ, smartlist_len(diff));
+ tt_assert(line_str_eq(smartlist_get(diff, 0),
+ "network-status-diff-version 1"));
+ tt_assert(line_str_eq(smartlist_get(diff, 1), "hash "
+ "95D70F5A3CC65F920AA8B44C4563D7781A082674329661884E19E94B79D539C2 "
+ "7AFECEFA4599BA33D603653E3D2368F648DF4AC4723929B0F7CF39281596B0C1"));
+ tt_assert(line_str_eq(smartlist_get(diff, 2), "6,$d"));
+ tt_assert(line_str_eq(smartlist_get(diff, 3), "3,4c"));
+ tt_assert(line_str_eq(smartlist_get(diff, 4), "bar"));
+ tt_assert(line_str_eq(smartlist_get(diff, 5),
+ "directory-signature foo bar"));
+ tt_assert(line_str_eq(smartlist_get(diff, 6),
+ "."));
+ tt_assert(line_str_eq(smartlist_get(diff, 7), "1a"));
+ tt_assert(line_str_eq(smartlist_get(diff, 8),
+ "r name aaaaaaaaaaaaaaaaa etc"));
+ tt_assert(line_str_eq(smartlist_get(diff, 9), "foo"));
+ tt_assert(line_str_eq(smartlist_get(diff, 10), "."));
+
+ /* TODO: small real use-cases, i.e. consensuses. */
+
+ done:
+ tor_free(cons1_str);
+ tor_free(cons2_str);
+ smartlist_free(cons1);
+ smartlist_free(cons2);
+ smartlist_free(diff);
+ memarea_drop_all(area);
+}
+
+static void
+test_consdiff_apply_diff(void *arg)
+{
+ smartlist_t *cons1=NULL, *diff=NULL;
+ char *cons1_str=NULL, *cons2 = NULL;
+ consensus_digest_t digests1;
+ (void)arg;
+ memarea_t *area = memarea_new();
+ cons1 = smartlist_new();
+ diff = smartlist_new();
+ setup_capture_of_logs(LOG_INFO);
+
+ cons1_str = tor_strdup(
+ "network-status-version foo\n"
+ "r name ccccccccccccccccc etc\nfoo\n"
+ "r name eeeeeeeeeeeeeeeee etc\nbar\n"
+ "directory-signature foo bar\nbar\n"
+ );
+ tt_int_op(0, OP_EQ,
+ consensus_compute_digest(cons1_str, &digests1));
+ consensus_split_lines(cons1, cons1_str, area);
+
+ /* diff doesn't have enough lines. */
+ cons2 = consdiff_apply_diff(cons1, diff, &digests1);
+ tt_ptr_op(NULL, OP_EQ, cons2);
+ expect_single_log_msg_containing("too short")
+
+ /* first line doesn't match format-version string. */
+ smartlist_add_linecpy(diff, area, "foo-bar");
+ smartlist_add_linecpy(diff, area, "header-line");
+ mock_clean_saved_logs();
+ cons2 = consdiff_apply_diff(cons1, diff, &digests1);
+ tt_ptr_op(NULL, OP_EQ, cons2);
+ expect_single_log_msg_containing("format is not known")
+
+ /* The first word of the second header line is not "hash". */
+ smartlist_clear(diff);
+ smartlist_add_linecpy(diff, area, "network-status-diff-version 1");
+ smartlist_add_linecpy(diff, area, "word a b");
+ smartlist_add_linecpy(diff, area, "x");
+ mock_clean_saved_logs();
+ cons2 = consdiff_apply_diff(cons1, diff, &digests1);
+ tt_ptr_op(NULL, OP_EQ, cons2);
+ expect_single_log_msg_containing("does not include the necessary digests")
+
+ /* Wrong number of words after "hash". */
+ smartlist_clear(diff);
+ smartlist_add_linecpy(diff, area, "network-status-diff-version 1");
+ smartlist_add_linecpy(diff, area, "hash a b c");
+ mock_clean_saved_logs();
+ cons2 = consdiff_apply_diff(cons1, diff, &digests1);
+ tt_ptr_op(NULL, OP_EQ, cons2);
+ expect_single_log_msg_containing("does not include the necessary digests")
+
+ /* base16 digests do not have the expected length. */
+ smartlist_clear(diff);
+ smartlist_add_linecpy(diff, area, "network-status-diff-version 1");
+ smartlist_add_linecpy(diff, area, "hash aaa bbb");
+ mock_clean_saved_logs();
+ cons2 = consdiff_apply_diff(cons1, diff, &digests1);
+ tt_ptr_op(NULL, OP_EQ, cons2);
+ expect_single_log_msg_containing("includes base16-encoded digests of "
+ "incorrect size")
+
+ /* base16 digests contain non-base16 characters. */
+ smartlist_clear(diff);
+ smartlist_add_linecpy(diff, area, "network-status-diff-version 1");
+ smartlist_add_linecpy(diff, area, "hash"
+ " ????????????????????????????????????????????????????????????????"
+ " ----------------------------------------------------------------");
+ mock_clean_saved_logs();
+ cons2 = consdiff_apply_diff(cons1, diff, &digests1);
+ tt_ptr_op(NULL, OP_EQ, cons2);
+ expect_single_log_msg_containing("includes malformed digests")
+
+ /* Invalid ed diff.
+ * As tested in apply_ed_diff, but check that apply_diff does return NULL if
+ * the ed diff can't be applied. */
+ smartlist_clear(diff);
+ smartlist_add_linecpy(diff, area, "network-status-diff-version 1");
+ smartlist_add_linecpy(diff, area, "hash"
+ /* sha3 of cons1. */
+ " 06646D6CF563A41869D3B02E73254372AE3140046C5E7D83C9F71E54976AF9B4"
+ /* sha256 of cons2. */
+ " 635D34593020C08E5ECD865F9986E29D50028EFA62843766A8197AD228A7F6AA");
+ smartlist_add_linecpy(diff, area, "foobar");
+ mock_clean_saved_logs();
+ cons2 = consdiff_apply_diff(cons1, diff, &digests1);
+ tt_ptr_op(NULL, OP_EQ, cons2);
+ expect_single_log_msg_containing("because an ed command was missing a line "
+ "number")
+
+ /* Base consensus doesn't match its digest as found in the diff. */
+ smartlist_clear(diff);
+ smartlist_add_linecpy(diff, area, "network-status-diff-version 1");
+ smartlist_add_linecpy(diff, area, "hash"
+ /* bogus sha256. */
+ " 3333333333333333333333333333333333333333333333333333333333333333"
+ /* sha256 of cons2. */
+ " 635D34593020C08E5ECD865F9986E29D50028EFA62843766A8197AD228A7F6AA");
+ mock_clean_saved_logs();
+ cons2 = consdiff_apply_diff(cons1, diff, &digests1);
+ tt_ptr_op(NULL, OP_EQ, cons2);
+ expect_log_msg_containing("base consensus doesn't match the digest "
+ "as found");
+
+ /* Resulting consensus doesn't match its digest as found in the diff. */
+ smartlist_clear(diff);
+ smartlist_add_linecpy(diff, area, "network-status-diff-version 1");
+ smartlist_add_linecpy(diff, area, "hash"
+ /* sha3 of cons1. */
+ " 06646D6CF563A41869D3B02E73254372AE3140046C5E7D83C9F71E54976AF9B4"
+ /* bogus sha3. */
+ " 3333333333333333333333333333333333333333333333333333333333333333");
+ mock_clean_saved_logs();
+ cons2 = consdiff_apply_diff(cons1, diff, &digests1);
+ tt_ptr_op(NULL, OP_EQ, cons2);
+ expect_log_msg_containing("resulting consensus doesn't match the "
+ "digest as found");
+
+#if 0
+ /* XXXX No longer possible, since we aren't using the other algorithm. */
+ /* Resulting consensus digest cannot be computed */
+ smartlist_clear(diff);
+ smartlist_add_linecpy(diff, area, "network-status-diff-version 1");
+ smartlist_add_linecpy(diff, area, "hash"
+ /* sha3 of cons1. */
+ " 06646D6CF563A41869D3B02E73254372AE3140046C5E7D83C9F71E54976AF9B4"
+ /* bogus sha3. */
+ " 3333333333333333333333333333333333333333333333333333333333333333");
+ smartlist_add_linecpy(diff, area, "1,2d"); // remove starting line
+ mock_clean_saved_logs();
+ cons2 = consdiff_apply_diff(cons1, diff, &digests1);
+ 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 /* 0 */
+
+ /* Very simple test, only to see that nothing errors. */
+ smartlist_clear(diff);
+ smartlist_add_linecpy(diff, area, "network-status-diff-version 1");
+ smartlist_add_linecpy(diff, area, "hash"
+ /* sha3 of cons1. */
+ " 06646D6CF563A41869D3B02E73254372AE3140046C5E7D83C9F71E54976AF9B4"
+ /* sha3 of cons2. */
+ " 90A418881B2FCAB3D9E60EE02E4D666D56CFA38F8A3B7AA3E0ADBA530DDA9353");
+ smartlist_add_linecpy(diff, area, "3c");
+ smartlist_add_linecpy(diff, area, "sample");
+ smartlist_add_linecpy(diff, area, ".");
+ cons2 = consdiff_apply_diff(cons1, diff, &digests1);
+ tt_ptr_op(NULL, OP_NE, cons2);
+ tt_str_op(
+ "network-status-version foo\n"
+ "r name ccccccccccccccccc etc\nsample\n"
+ "r name eeeeeeeeeeeeeeeee etc\nbar\n"
+ "directory-signature foo bar\nbar\n", OP_EQ,
+ cons2);
+ tor_free(cons2);
+
+ /* Check that lowercase letters in base16-encoded digests work too. */
+ smartlist_clear(diff);
+ smartlist_add_linecpy(diff, area, "network-status-diff-version 1");
+ smartlist_add_linecpy(diff, area, "hash"
+ /* sha3 of cons1. */
+ " 06646d6cf563a41869d3b02e73254372ae3140046c5e7d83c9f71e54976af9b4"
+ /* sha3 of cons2. */
+ " 90a418881b2fcab3d9e60ee02e4d666d56cfa38f8a3b7aa3e0adba530dda9353");
+ smartlist_add_linecpy(diff, area, "3c");
+ smartlist_add_linecpy(diff, area, "sample");
+ smartlist_add_linecpy(diff, area, ".");
+ cons2 = consdiff_apply_diff(cons1, diff, &digests1);
+ tt_ptr_op(NULL, OP_NE, cons2);
+ tt_str_op(
+ "network-status-version foo\n"
+ "r name ccccccccccccccccc etc\nsample\n"
+ "r name eeeeeeeeeeeeeeeee etc\nbar\n"
+ "directory-signature foo bar\nbar\n", OP_EQ,
+ cons2);
+ tor_free(cons2);
+
+ smartlist_clear(diff);
+
+ done:
+ teardown_capture_of_logs();
+ tor_free(cons1_str);
+ smartlist_free(cons1);
+ smartlist_free(diff);
+ memarea_drop_all(area);
+}
+
+#define CONSDIFF_LEGACY(name) \
+ { #name, test_consdiff_ ## name , 0, NULL, NULL }
+
+struct testcase_t consdiff_tests[] = {
+ CONSDIFF_LEGACY(smartlist_slice),
+ CONSDIFF_LEGACY(smartlist_slice_string_pos),
+ CONSDIFF_LEGACY(lcs_lengths),
+ CONSDIFF_LEGACY(trim_slices),
+ CONSDIFF_LEGACY(set_changed),
+ CONSDIFF_LEGACY(calc_changes),
+ CONSDIFF_LEGACY(get_id_hash),
+ CONSDIFF_LEGACY(is_valid_router_entry),
+ CONSDIFF_LEGACY(next_router),
+ CONSDIFF_LEGACY(base64cmp),
+ CONSDIFF_LEGACY(gen_ed_diff),
+ CONSDIFF_LEGACY(apply_ed_diff),
+ CONSDIFF_LEGACY(gen_diff),
+ CONSDIFF_LEGACY(apply_diff),
+ END_OF_TESTCASES
+};
+
diff --git a/src/test/test_consdiffmgr.c b/src/test/test_consdiffmgr.c
new file mode 100644
index 0000000000..80d3f943ab
--- /dev/null
+++ b/src/test/test_consdiffmgr.c
@@ -0,0 +1,896 @@
+/* Copyright (c) 2017, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#define CONSDIFFMGR_PRIVATE
+
+#include "or.h"
+#include "config.h"
+#include "conscache.h"
+#include "consdiff.h"
+#include "consdiffmgr.h"
+#include "cpuworker.h"
+#include "networkstatus.h"
+#include "routerparse.h"
+#include "workqueue.h"
+
+#include "test.h"
+#include "log_test_helpers.h"
+
+// ============================== Setup/teardown the consdiffmgr
+// These functions get run before/after each test in this module
+
+static void *
+consdiffmgr_test_setup(const struct testcase_t *arg)
+{
+ (void)arg;
+ char *ddir_fname = tor_strdup(get_fname_rnd("datadir_cdm"));
+ tor_free(get_options_mutable()->DataDirectory);
+ get_options_mutable()->DataDirectory = ddir_fname; // now owns the pointer.
+ check_private_dir(ddir_fname, CPD_CREATE, NULL);
+
+ consdiff_cfg_t consdiff_cfg = { 300 };
+ consdiffmgr_configure(&consdiff_cfg);
+ return (void *)1; // must return something non-null.
+}
+static int
+consdiffmgr_test_teardown(const struct testcase_t *arg, void *ignore)
+{
+ (void)arg;
+ (void)ignore;
+ consdiffmgr_free_all();
+ return 1;
+}
+static struct testcase_setup_t setup_diffmgr = {
+ consdiffmgr_test_setup,
+ consdiffmgr_test_teardown
+};
+
+// ============================== NS faking functions
+// These functions are for making quick fake consensus objects and
+// strings that are just good enough for consdiff and consdiffmgr.
+
+static networkstatus_t *
+fake_ns_new(consensus_flavor_t flav, time_t valid_after)
+{
+ networkstatus_t *ns = tor_malloc_zero(sizeof(networkstatus_t));
+ ns->type = NS_TYPE_CONSENSUS;
+ ns->flavor = flav;
+ ns->valid_after = valid_after;
+ return ns;
+}
+
+static char *
+fake_ns_body_new(consensus_flavor_t flav, time_t valid_after)
+{
+ const char *flavor_string = flav == FLAV_NS ? "" : " microdesc";
+ char valid_after_string[ISO_TIME_LEN+1];
+
+ format_iso_time(valid_after_string, valid_after);
+ char *random_stuff = crypto_random_hostname(3, 25, "junk ", "");
+ char *random_stuff2 = crypto_random_hostname(3, 10, "", "");
+
+ char *consensus;
+ tor_asprintf(&consensus,
+ "network-status-version 3%s\n"
+ "vote-status consensus\n"
+ "valid-after %s\n"
+ "r name ccccccccccccccccc etc\nsample\n"
+ "r name eeeeeeeeeeeeeeeee etc\nbar\n"
+ "%s\n"
+ "directory-signature hello-there\n"
+ "directory-signature %s\n",
+ flavor_string,
+ valid_after_string,
+ random_stuff,
+ random_stuff2);
+ tor_free(random_stuff);
+ tor_free(random_stuff2);
+ return consensus;
+}
+
+// ============================== Cpuworker mocking code
+// These mocking functions and types capture the cpuworker calls
+// so we can inspect them and run them in the main thread.
+static smartlist_t *fake_cpuworker_queue = NULL;
+typedef struct fake_work_queue_ent_t {
+ enum workqueue_reply_t (*fn)(void *, void *);
+ void (*reply_fn)(void *);
+ void *arg;
+} fake_work_queue_ent_t;
+static struct workqueue_entry_s *
+mock_cpuworker_queue_work(workqueue_priority_t prio,
+ enum workqueue_reply_t (*fn)(void *, void *),
+ void (*reply_fn)(void *),
+ void *arg)
+{
+ (void) prio;
+
+ if (! fake_cpuworker_queue)
+ fake_cpuworker_queue = smartlist_new();
+
+ fake_work_queue_ent_t *ent = tor_malloc_zero(sizeof(*ent));
+ ent->fn = fn;
+ ent->reply_fn = reply_fn;
+ ent->arg = arg;
+ smartlist_add(fake_cpuworker_queue, ent);
+ return (struct workqueue_entry_s *)ent;
+}
+static int
+mock_cpuworker_run_work(void)
+{
+ if (! fake_cpuworker_queue)
+ return 0;
+ SMARTLIST_FOREACH(fake_cpuworker_queue, fake_work_queue_ent_t *, ent, {
+ enum workqueue_reply_t r = ent->fn(NULL, ent->arg);
+ if (r != WQ_RPL_REPLY)
+ return -1;
+ });
+ return 0;
+}
+static void
+mock_cpuworker_handle_replies(void)
+{
+ if (! fake_cpuworker_queue)
+ return;
+ SMARTLIST_FOREACH(fake_cpuworker_queue, fake_work_queue_ent_t *, ent, {
+ ent->reply_fn(ent->arg);
+ tor_free(ent);
+ });
+ smartlist_free(fake_cpuworker_queue);
+ fake_cpuworker_queue = NULL;
+}
+
+// ============================== Other helpers
+
+static consdiff_status_t
+lookup_diff_from(consensus_cache_entry_t **out,
+ consensus_flavor_t flav,
+ const char *str1)
+{
+ uint8_t digest[DIGEST256_LEN];
+ if (router_get_networkstatus_v3_sha3_as_signed(digest, str1)<0) {
+ TT_FAIL(("Unable to compute sha3-as-signed"));
+ return CONSDIFF_NOT_FOUND;
+ }
+ return consdiffmgr_find_diff_from(out, flav,
+ DIGEST_SHA3_256, digest, sizeof(digest),
+ NO_METHOD);
+}
+
+static int
+lookup_apply_and_verify_diff(consensus_flavor_t flav,
+ const char *str1,
+ const char *str2)
+{
+ consensus_cache_entry_t *ent = NULL;
+ consdiff_status_t status = lookup_diff_from(&ent, flav, str1);
+ if (ent == NULL || status != CONSDIFF_AVAILABLE) {
+ return -1;
+ }
+
+ consensus_cache_entry_incref(ent);
+ size_t size;
+ char *diff_string = NULL;
+ int r = uncompress_or_copy(&diff_string, &size, ent);
+ consensus_cache_entry_decref(ent);
+ if (diff_string == NULL || r < 0)
+ return -1;
+
+ char *applied = consensus_diff_apply(str1, diff_string);
+ tor_free(diff_string);
+ if (applied == NULL)
+ return -1;
+
+ int match = !strcmp(applied, str2);
+ tor_free(applied);
+ return match ? 0 : -1;
+}
+
+static void
+cdm_reload(void)
+{
+ consdiffmgr_free_all();
+ cdm_cache_get();
+ consdiffmgr_rescan();
+}
+
+// ============================== Beginning of tests
+
+#if 0
+static int got_failure = 0;
+static void
+got_assertion_failure(void)
+{
+ ++got_failure;
+}
+
+/* XXXX This test won't work, because there is currently no way to actually
+ * XXXX capture a real assertion failure. */
+static void
+test_consdiffmgr_init_failure(void *arg)
+{
+ (void)arg;
+ // Capture assertions and bugs.
+
+ /* As in ...test_setup, but do not create the datadir. The missing directory
+ * will cause a failure. */
+ char *ddir_fname = tor_strdup(get_fname_rnd("datadir_cdm"));
+ tor_free(get_options_mutable()->DataDirectory);
+ get_options_mutable()->DataDirectory = ddir_fname; // now owns the pointer.
+
+ consdiff_cfg_t consdiff_cfg = { 7200, 300 };
+
+ tor_set_failed_assertion_callback(got_assertion_failure);
+ tor_capture_bugs_(1);
+ consdiffmgr_configure(&consdiff_cfg); // This should fail.
+ tt_int_op(got_failure, OP_EQ, 1);
+ const smartlist_t *bugs = tor_get_captured_bug_log_();
+ tt_int_op(smartlist_len(bugs), OP_EQ, 1);
+
+ done:
+ tor_end_capture_bugs_();
+}
+#endif /* 0 */
+
+static void
+test_consdiffmgr_sha3_helper(void *arg)
+{
+ (void) arg;
+ consensus_cache_t *cache = cdm_cache_get(); // violate abstraction barrier
+ config_line_t *lines = NULL;
+ char *mem_op_hex_tmp = NULL;
+ config_line_prepend(&lines, "good-sha",
+ "F00DF00DF00DF00DF00DF00DF00DF00D"
+ "F00DF00DF00DF00DF00DF00DF00DF00D");
+ config_line_prepend(&lines, "short-sha",
+ "F00DF00DF00DF00DF00DF00DF00DF00D"
+ "F00DF00DF00DF00DF00DF00DF00DF0");
+ config_line_prepend(&lines, "long-sha",
+ "F00DF00DF00DF00DF00DF00DF00DF00D"
+ "F00DF00DF00DF00DF00DF00DF00DF00DF00D");
+ config_line_prepend(&lines, "not-sha",
+ "F00DF00DF00DF00DF00DF00DF00DF00D"
+ "F00DF00DF00DF00DF00DF00DF00DXXXX");
+ consensus_cache_entry_t *ent =
+ consensus_cache_add(cache, lines, (const uint8_t *)"Hi there", 8);
+
+ uint8_t buf[DIGEST256_LEN];
+ tt_int_op(-1, OP_EQ, cdm_entry_get_sha3_value(buf, NULL, "good-sha"));
+ tt_int_op(0, OP_EQ, cdm_entry_get_sha3_value(buf, ent, "good-sha"));
+ test_memeq_hex(buf, "F00DF00DF00DF00DF00DF00DF00DF00D"
+ "F00DF00DF00DF00DF00DF00DF00DF00D");
+
+ tt_int_op(-1, OP_EQ, cdm_entry_get_sha3_value(buf, ent, "missing-sha"));
+ tt_int_op(-2, OP_EQ, cdm_entry_get_sha3_value(buf, ent, "short-sha"));
+ tt_int_op(-2, OP_EQ, cdm_entry_get_sha3_value(buf, ent, "long-sha"));
+ tt_int_op(-2, OP_EQ, cdm_entry_get_sha3_value(buf, ent, "not-sha"));
+
+ done:
+ consensus_cache_entry_decref(ent);
+ config_free_lines(lines);
+ tor_free(mem_op_hex_tmp);
+}
+
+static void
+test_consdiffmgr_add(void *arg)
+{
+ (void) arg;
+ time_t now = approx_time();
+
+ char *body = NULL;
+
+ consensus_cache_entry_t *ent = NULL;
+ networkstatus_t *ns_tmp = fake_ns_new(FLAV_NS, now);
+ const char *dummy = "foo";
+ int r = consdiffmgr_add_consensus(dummy, ns_tmp);
+ tt_int_op(r, OP_EQ, 0);
+
+ /* If we add it again, it won't work */
+ setup_capture_of_logs(LOG_INFO);
+ dummy = "bar";
+ r = consdiffmgr_add_consensus(dummy, ns_tmp);
+ tt_int_op(r, OP_EQ, -1);
+ expect_single_log_msg_containing("We already have a copy of that "
+ "consensus");
+ mock_clean_saved_logs();
+
+ /* But it will work fine if the flavor is different */
+ dummy = "baz";
+ ns_tmp->flavor = FLAV_MICRODESC;
+ r = consdiffmgr_add_consensus(dummy, ns_tmp);
+ tt_int_op(r, OP_EQ, 0);
+
+ /* And it will work fine if the time is different */
+ dummy = "quux";
+ ns_tmp->flavor = FLAV_NS;
+ ns_tmp->valid_after = now - 60;
+ r = consdiffmgr_add_consensus(dummy, ns_tmp);
+ tt_int_op(r, OP_EQ, 0);
+
+ /* If we add one a long long time ago, it will fail. */
+ dummy = "xyzzy";
+ ns_tmp->valid_after = 86400 * 100; /* A few months into 1970 */
+ r = consdiffmgr_add_consensus(dummy, ns_tmp);
+ tt_int_op(r, OP_EQ, -1);
+ expect_log_msg_containing("it's too old.");
+
+ /* Try looking up a consensuses. */
+ ent = cdm_cache_lookup_consensus(FLAV_NS, now-60);
+ tt_assert(ent);
+ consensus_cache_entry_incref(ent);
+ size_t s;
+ r = uncompress_or_copy(&body, &s, ent);
+ tt_int_op(r, OP_EQ, 0);
+ tt_int_op(s, OP_EQ, 4);
+ tt_mem_op(body, OP_EQ, "quux", 4);
+
+ /* Try looking up another entry, but fail */
+ 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);
+ teardown_capture_of_logs();
+ consensus_cache_entry_decref(ent);
+ tor_free(body);
+}
+
+static void
+test_consdiffmgr_make_diffs(void *arg)
+{
+ (void)arg;
+ networkstatus_t *ns = NULL;
+ char *ns_body = NULL, *md_ns_body = NULL, *md_ns_body_2 = NULL;
+ char *applied = NULL, *diff_text = NULL;
+ time_t now = approx_time();
+ int r;
+ consensus_cache_entry_t *diff = NULL;
+ uint8_t md_ns_sha3[DIGEST256_LEN];
+ consdiff_status_t diff_status;
+
+ MOCK(cpuworker_queue_work, mock_cpuworker_queue_work);
+
+ // Try rescan with no consensuses: shouldn't crash or queue work.
+ consdiffmgr_rescan();
+ tt_ptr_op(NULL, OP_EQ, fake_cpuworker_queue);
+
+ // Make two consensuses, 1 hour sec ago.
+ ns = fake_ns_new(FLAV_NS, now-3600);
+ ns_body = fake_ns_body_new(FLAV_NS, now-3600);
+ r = consdiffmgr_add_consensus(ns_body, ns);
+ networkstatus_vote_free(ns);
+ tor_free(ns_body);
+ tt_int_op(r, OP_EQ, 0);
+
+ ns = fake_ns_new(FLAV_MICRODESC, now-3600);
+ md_ns_body = fake_ns_body_new(FLAV_MICRODESC, now-3600);
+ r = consdiffmgr_add_consensus(md_ns_body, ns);
+ router_get_networkstatus_v3_sha3_as_signed(md_ns_sha3, md_ns_body);
+ networkstatus_vote_free(ns);
+ tt_int_op(r, OP_EQ, 0);
+
+ // No diffs will be generated.
+ consdiffmgr_rescan();
+ tt_ptr_op(NULL, OP_EQ, fake_cpuworker_queue);
+
+ // Add a MD consensus from 45 minutes ago. This should cause one diff
+ // worth of work to get queued.
+ ns = fake_ns_new(FLAV_MICRODESC, now-45*60);
+ md_ns_body_2 = fake_ns_body_new(FLAV_MICRODESC, now-45*60);
+ r = consdiffmgr_add_consensus(md_ns_body_2, ns);
+ networkstatus_vote_free(ns);
+ tt_int_op(r, OP_EQ, 0);
+
+ consdiffmgr_rescan();
+ tt_ptr_op(NULL, OP_NE, fake_cpuworker_queue);
+ tt_int_op(1, OP_EQ, smartlist_len(fake_cpuworker_queue));
+ diff_status = consdiffmgr_find_diff_from(&diff, FLAV_MICRODESC,
+ DIGEST_SHA3_256,
+ md_ns_sha3, DIGEST256_LEN,
+ NO_METHOD);
+ tt_int_op(CONSDIFF_IN_PROGRESS, OP_EQ, diff_status);
+
+ // Now run that process and get the diff.
+ r = mock_cpuworker_run_work();
+ tt_int_op(r, OP_EQ, 0);
+ mock_cpuworker_handle_replies();
+
+ // At this point we should be able to get that diff.
+ diff_status = consdiffmgr_find_diff_from(&diff, FLAV_MICRODESC,
+ DIGEST_SHA3_256,
+ md_ns_sha3, DIGEST256_LEN,
+ NO_METHOD);
+ tt_int_op(CONSDIFF_AVAILABLE, OP_EQ, diff_status);
+ tt_assert(diff);
+
+ /* Make sure applying the diff actually works */
+ const uint8_t *diff_body;
+ size_t diff_size;
+ r = consensus_cache_entry_get_body(diff, &diff_body, &diff_size);
+ tt_int_op(r, OP_EQ, 0);
+ diff_text = tor_memdup_nulterm(diff_body, diff_size);
+ applied = consensus_diff_apply(md_ns_body, diff_text);
+ tt_assert(applied);
+ tt_str_op(applied, OP_EQ, md_ns_body_2);
+
+ /* Rescan again: no more work to do. */
+ consdiffmgr_rescan();
+ tt_ptr_op(NULL, OP_EQ, fake_cpuworker_queue);
+
+ done:
+ tor_free(md_ns_body);
+ tor_free(md_ns_body_2);
+ tor_free(diff_text);
+ tor_free(applied);
+}
+
+static void
+test_consdiffmgr_diff_rules(void *arg)
+{
+ (void)arg;
+#define N 6
+ char *md_body[N], *ns_body[N];
+ networkstatus_t *md_ns[N], *ns_ns[N];
+ int i;
+
+ MOCK(cpuworker_queue_work, mock_cpuworker_queue_work);
+
+ /* Create a bunch of consensus things at 15-second intervals. */
+ time_t start = approx_time() - 120;
+ for (i = 0; i < N; ++i) {
+ time_t when = start + i * 15;
+ md_body[i] = fake_ns_body_new(FLAV_MICRODESC, when);
+ ns_body[i] = fake_ns_body_new(FLAV_NS, when);
+ md_ns[i] = fake_ns_new(FLAV_MICRODESC, when);
+ ns_ns[i] = fake_ns_new(FLAV_NS, when);
+ }
+
+ /* For the MD consensuses: add 4 of them, and make sure that
+ * diffs are created to one consensus (the most recent) only. */
+ tt_int_op(0, OP_EQ, consdiffmgr_add_consensus(md_body[1], md_ns[1]));
+ tt_int_op(0, OP_EQ, consdiffmgr_add_consensus(md_body[2], md_ns[2]));
+ tt_int_op(0, OP_EQ, consdiffmgr_add_consensus(md_body[3], md_ns[3]));
+ tt_int_op(0, OP_EQ, consdiffmgr_add_consensus(md_body[4], md_ns[4]));
+ consdiffmgr_rescan();
+ tt_ptr_op(NULL, OP_NE, fake_cpuworker_queue);
+ tt_int_op(3, OP_EQ, smartlist_len(fake_cpuworker_queue));
+ tt_int_op(0, OP_EQ, mock_cpuworker_run_work());
+ mock_cpuworker_handle_replies();
+ tt_ptr_op(NULL, OP_EQ, fake_cpuworker_queue);
+
+ /* For the NS consensuses: add 3, generate, and add one older one and
+ * make sure that older one is the only one whose diff is generated */
+ tt_int_op(0, OP_EQ, consdiffmgr_add_consensus(ns_body[0], ns_ns[0]));
+ tt_int_op(0, OP_EQ, consdiffmgr_add_consensus(ns_body[1], ns_ns[1]));
+ tt_int_op(0, OP_EQ, consdiffmgr_add_consensus(ns_body[5], ns_ns[5]));
+ consdiffmgr_rescan();
+ tt_ptr_op(NULL, OP_NE, fake_cpuworker_queue);
+ tt_int_op(2, OP_EQ, smartlist_len(fake_cpuworker_queue));
+ tt_int_op(0, OP_EQ, mock_cpuworker_run_work());
+ mock_cpuworker_handle_replies();
+
+ /* At this point, we should actually have working diffs! */
+ tt_int_op(0, OP_EQ,
+ lookup_apply_and_verify_diff(FLAV_NS, ns_body[0], ns_body[5]));
+ tt_int_op(0, OP_EQ,
+ lookup_apply_and_verify_diff(FLAV_NS, ns_body[1], ns_body[5]));
+
+ tt_int_op(0, OP_EQ,
+ lookup_apply_and_verify_diff(FLAV_MICRODESC, md_body[1], md_body[4]));
+ tt_int_op(0, OP_EQ,
+ lookup_apply_and_verify_diff(FLAV_MICRODESC, md_body[2], md_body[4]));
+ tt_int_op(0, OP_EQ,
+ lookup_apply_and_verify_diff(FLAV_MICRODESC, md_body[3], md_body[4]));
+
+ /* Self-to-self diff won't be present */
+ consensus_cache_entry_t *ent;
+ tt_int_op(CONSDIFF_NOT_FOUND, OP_EQ,
+ lookup_diff_from(&ent, FLAV_NS, ns_body[5]));
+ /* No diff from 2 has been added yet */
+ tt_int_op(CONSDIFF_NOT_FOUND, OP_EQ,
+ lookup_diff_from(&ent, FLAV_NS, ns_body[2]));
+ /* No diff arriving at old things. */
+ tt_int_op(-1, OP_EQ,
+ lookup_apply_and_verify_diff(FLAV_MICRODESC, md_body[1], md_body[2]));
+ /* No backwards diff */
+ tt_int_op(-1, OP_EQ,
+ lookup_apply_and_verify_diff(FLAV_MICRODESC, md_body[4], md_body[3]));
+
+ /* Now, an update: add number 2 and make sure it's the only one whose diff
+ * is regenerated. */
+ tt_int_op(0, OP_EQ, consdiffmgr_add_consensus(ns_body[2], ns_ns[2]));
+ consdiffmgr_rescan();
+ tt_ptr_op(NULL, OP_NE, fake_cpuworker_queue);
+ tt_int_op(1, OP_EQ, smartlist_len(fake_cpuworker_queue));
+ tt_int_op(0, OP_EQ, mock_cpuworker_run_work());
+ mock_cpuworker_handle_replies();
+
+ tt_int_op(0, OP_EQ,
+ lookup_apply_and_verify_diff(FLAV_NS, ns_body[2], ns_body[5]));
+
+ /* Finally: reload, and make sure that the information is still indexed */
+ cdm_reload();
+
+ tt_int_op(0, OP_EQ,
+ lookup_apply_and_verify_diff(FLAV_NS, ns_body[0], ns_body[5]));
+ tt_int_op(0, OP_EQ,
+ lookup_apply_and_verify_diff(FLAV_NS, ns_body[2], ns_body[5]));
+ tt_int_op(0, OP_EQ,
+ lookup_apply_and_verify_diff(FLAV_NS, ns_body[1], ns_body[5]));
+
+ tt_int_op(0, OP_EQ,
+ lookup_apply_and_verify_diff(FLAV_MICRODESC, md_body[1], md_body[4]));
+ tt_int_op(0, OP_EQ,
+ lookup_apply_and_verify_diff(FLAV_MICRODESC, md_body[2], md_body[4]));
+ tt_int_op(0, OP_EQ,
+ lookup_apply_and_verify_diff(FLAV_MICRODESC, md_body[3], md_body[4]));
+
+ done:
+ for (i = 0; i < N; ++i) {
+ tor_free(md_body[i]);
+ tor_free(ns_body[i]);
+ networkstatus_vote_free(md_ns[i]);
+ networkstatus_vote_free(ns_ns[i]);
+ }
+ UNMOCK(cpuworker_queue_work);
+#undef N
+}
+
+static void
+test_consdiffmgr_diff_failure(void *arg)
+{
+ (void)arg;
+ MOCK(cpuworker_queue_work, mock_cpuworker_queue_work);
+
+ /* We're going to make sure that if we have a bogus request where
+ * we can't actually compute a diff, the world must not end. */
+ networkstatus_t *ns1 = NULL;
+ networkstatus_t *ns2 = NULL;
+ int r;
+
+ ns1 = fake_ns_new(FLAV_NS, approx_time()-100);
+ ns2 = fake_ns_new(FLAV_NS, approx_time()-50);
+ r = consdiffmgr_add_consensus("foo bar baz\n", ns1);
+ tt_int_op(r, OP_EQ, 0);
+ // We refuse to compute a diff to or from a line holding only a single dot.
+ // We can add it here, though.
+ r = consdiffmgr_add_consensus("foo bar baz\n.\n.\n", ns2);
+ tt_int_op(r, OP_EQ, 0);
+
+ consdiffmgr_rescan();
+ tt_ptr_op(NULL, OP_NE, fake_cpuworker_queue);
+ setup_capture_of_logs(LOG_WARN);
+ tt_int_op(1, OP_EQ, smartlist_len(fake_cpuworker_queue));
+ tt_int_op(0, OP_EQ, mock_cpuworker_run_work());
+ expect_single_log_msg_containing("one of the lines to be added is \".\".");
+ mock_clean_saved_logs();
+ mock_cpuworker_handle_replies();
+ expect_single_log_msg_containing("Worker was unable to compute consensus "
+ "diff from ");
+
+ /* Make sure the diff is not present */
+ consensus_cache_entry_t *ent;
+ tt_int_op(CONSDIFF_NOT_FOUND, OP_EQ,
+ lookup_diff_from(&ent, FLAV_NS, "foo bar baz\n"));
+
+ done:
+ teardown_capture_of_logs();
+ UNMOCK(cpuworker_queue_work);
+ networkstatus_vote_free(ns1);
+ networkstatus_vote_free(ns2);
+}
+
+static void
+test_consdiffmgr_diff_pending(void *arg)
+{
+#define N 3
+ (void)arg;
+ char *md_body[N];
+ networkstatus_t *md_ns[N];
+ time_t start = approx_time() - 120;
+ int i;
+ for (i = 0; i < N; ++i) {
+ time_t when = start + i * 30;
+ md_body[i] = fake_ns_body_new(FLAV_MICRODESC, when);
+ md_ns[i] = fake_ns_new(FLAV_MICRODESC, when);
+ }
+
+ MOCK(cpuworker_queue_work, mock_cpuworker_queue_work);
+
+ tt_int_op(0, OP_EQ, consdiffmgr_add_consensus(md_body[1], md_ns[1]));
+ tt_int_op(0, OP_EQ, consdiffmgr_add_consensus(md_body[2], md_ns[2]));
+ /* Make a diff */
+ consdiffmgr_rescan();
+ tt_int_op(1, OP_EQ, smartlist_len(fake_cpuworker_queue));
+
+ /* Look it up. Is it pending? */
+ consensus_cache_entry_t *ent = NULL;
+ consdiff_status_t diff_status;
+ diff_status = lookup_diff_from(&ent, FLAV_MICRODESC, md_body[1]);
+ tt_int_op(CONSDIFF_IN_PROGRESS, OP_EQ, diff_status);
+ tt_ptr_op(ent, OP_EQ, NULL);
+
+ /* Add another old consensus. only one new diff should launch! */
+ tt_int_op(0, OP_EQ, consdiffmgr_add_consensus(md_body[0], md_ns[0]));
+ consdiffmgr_rescan();
+ tt_int_op(2, OP_EQ, smartlist_len(fake_cpuworker_queue));
+
+ tt_int_op(0, OP_EQ, mock_cpuworker_run_work());
+ mock_cpuworker_handle_replies();
+
+ tt_int_op(0, OP_EQ,
+ lookup_apply_and_verify_diff(FLAV_MICRODESC, md_body[0], md_body[2]));
+ tt_int_op(0, OP_EQ,
+ lookup_apply_and_verify_diff(FLAV_MICRODESC, md_body[1], md_body[2]));
+
+ done:
+ UNMOCK(cpuworker_queue_work);
+ for (i = 0; i < N; ++i) {
+ tor_free(md_body[i]);
+ networkstatus_vote_free(md_ns[i]);
+ }
+#undef N
+}
+
+static void
+test_consdiffmgr_cleanup_old(void *arg)
+{
+ (void)arg;
+ config_line_t *labels = NULL;
+ consensus_cache_entry_t *ent = NULL;
+ consensus_cache_t *cache = cdm_cache_get(); // violate abstraction barrier
+
+ /* This item will be will be cleanable because it has a valid-after
+ * time far in the past. */
+ config_line_prepend(&labels, "document-type", "confribble-blarg");
+ config_line_prepend(&labels, "consensus-valid-after",
+ "1980-10-10T10:10:10");
+ ent = consensus_cache_add(cache, labels, (const uint8_t*)"Foo", 3);
+ tt_assert(ent);
+ consensus_cache_entry_decref(ent);
+
+ setup_capture_of_logs(LOG_DEBUG);
+ tt_int_op(1, OP_EQ, consdiffmgr_cleanup());
+ expect_log_msg_containing("Deleting entry because its consensus-valid-"
+ "after value (1980-10-10T10:10:10) was too old");
+
+ done:
+ teardown_capture_of_logs();
+ config_free_lines(labels);
+}
+
+static void
+test_consdiffmgr_cleanup_bad_valid_after(void *arg)
+{
+ /* This will seem cleanable, but isn't, because its valid-after time is
+ * misformed. */
+
+ (void)arg;
+ config_line_t *labels = NULL;
+ consensus_cache_entry_t *ent = NULL;
+ consensus_cache_t *cache = cdm_cache_get(); // violate abstraction barrier
+
+ config_line_prepend(&labels, "document-type", "consensus");
+ config_line_prepend(&labels, "consensus-valid-after",
+ "whan that aprille with his shoures soote"); // (~1385?)
+ ent = consensus_cache_add(cache, labels, (const uint8_t*)"Foo", 3);
+ tt_assert(ent);
+ consensus_cache_entry_decref(ent);
+
+ setup_capture_of_logs(LOG_DEBUG);
+ tt_int_op(0, OP_EQ, consdiffmgr_cleanup());
+ expect_log_msg_containing("Ignoring entry because its consensus-valid-"
+ "after value (\"whan that aprille with his "
+ "shoures soote\") was unparseable");
+
+ done:
+ teardown_capture_of_logs();
+ config_free_lines(labels);
+}
+
+static void
+test_consdiffmgr_cleanup_no_valid_after(void *arg)
+{
+ (void)arg;
+ config_line_t *labels = NULL;
+ consensus_cache_entry_t *ent = NULL;
+ consensus_cache_t *cache = cdm_cache_get(); // violate abstraction barrier
+
+ /* This item will be will be uncleanable because it has no recognized
+ * valid-after. */
+ config_line_prepend(&labels, "document-type", "consensus");
+ config_line_prepend(&labels, "confrooble-voolid-oofter",
+ "2010-10-10T09:08:07");
+ ent = consensus_cache_add(cache, labels, (const uint8_t*)"Foo", 3);
+ tt_assert(ent);
+ consensus_cache_entry_decref(ent);
+
+ setup_capture_of_logs(LOG_DEBUG);
+ tt_int_op(0, OP_EQ, consdiffmgr_cleanup());
+ expect_log_msg_containing("Ignoring entry because it had no consensus-"
+ "valid-after label");
+
+ done:
+ teardown_capture_of_logs();
+ config_free_lines(labels);
+}
+
+static void
+test_consdiffmgr_cleanup_old_diffs(void *arg)
+{
+ (void)arg;
+#define N 4
+ char *md_body[N];
+ networkstatus_t *md_ns[N];
+ int i;
+ consensus_cache_entry_t *hold_ent = NULL, *ent;
+
+ /* Make sure that the cleanup function removes diffs to the not-most-recent
+ * consensus. */
+
+ MOCK(cpuworker_queue_work, mock_cpuworker_queue_work);
+
+ /* Create a bunch of consensus things at 15-second intervals. */
+ time_t start = approx_time() - 120;
+ for (i = 0; i < N; ++i) {
+ time_t when = start + i * 15;
+ md_body[i] = fake_ns_body_new(FLAV_MICRODESC, when);
+ md_ns[i] = fake_ns_new(FLAV_MICRODESC, when);
+ }
+
+ /* add the first 3. */
+ tt_int_op(0, OP_EQ, consdiffmgr_add_consensus(md_body[0], md_ns[0]));
+ tt_int_op(0, OP_EQ, consdiffmgr_add_consensus(md_body[1], md_ns[1]));
+ tt_int_op(0, OP_EQ, consdiffmgr_add_consensus(md_body[2], md_ns[2]));
+ /* Make diffs. */
+ consdiffmgr_rescan();
+ tt_ptr_op(NULL, OP_NE, fake_cpuworker_queue);
+ tt_int_op(2, OP_EQ, smartlist_len(fake_cpuworker_queue));
+ tt_int_op(0, OP_EQ, mock_cpuworker_run_work());
+ mock_cpuworker_handle_replies();
+ tt_ptr_op(NULL, OP_EQ, fake_cpuworker_queue);
+
+ /* Nothing is deletable now */
+ tt_int_op(0, OP_EQ, consdiffmgr_cleanup());
+ tt_int_op(0, OP_EQ,
+ lookup_apply_and_verify_diff(FLAV_MICRODESC, md_body[0], md_body[2]));
+ tt_int_op(0, OP_EQ,
+ lookup_apply_and_verify_diff(FLAV_MICRODESC, md_body[1], md_body[2]));
+
+ tt_int_op(CONSDIFF_AVAILABLE, OP_EQ,
+ lookup_diff_from(&hold_ent, FLAV_MICRODESC, md_body[1]));
+ consensus_cache_entry_incref(hold_ent); // incref, so it is preserved.
+
+ /* Now add an even-more-recent consensus; this should make all previous
+ * diffs deletable, and make delete */
+ tt_int_op(0, OP_EQ, consdiffmgr_add_consensus(md_body[3], md_ns[3]));
+ tt_int_op(2 * n_diff_compression_methods() +
+ (n_consensus_compression_methods() - 1) , OP_EQ,
+ consdiffmgr_cleanup());
+
+ tt_int_op(CONSDIFF_NOT_FOUND, OP_EQ,
+ lookup_diff_from(&ent, FLAV_MICRODESC, md_body[0]));
+ /* This one is marked deletable but still in the hashtable */
+ tt_int_op(CONSDIFF_AVAILABLE, OP_EQ,
+ lookup_diff_from(&ent, FLAV_MICRODESC, md_body[1]));
+ tt_int_op(CONSDIFF_NOT_FOUND, OP_EQ,
+ lookup_diff_from(&ent, FLAV_MICRODESC, md_body[2]));
+
+ /* Everything should be valid at this point */
+ tt_int_op(0, OP_EQ, consdiffmgr_validate());
+
+ /* And if we recan NOW, we'll purge the hashtable of the entries,
+ * and launch attempts to generate new ones */
+ consdiffmgr_rescan();
+ tt_int_op(CONSDIFF_IN_PROGRESS, OP_EQ,
+ lookup_diff_from(&ent, FLAV_MICRODESC, md_body[0]));
+ tt_int_op(CONSDIFF_IN_PROGRESS, OP_EQ,
+ lookup_diff_from(&ent, FLAV_MICRODESC, md_body[1]));
+ tt_int_op(CONSDIFF_IN_PROGRESS, OP_EQ,
+ lookup_diff_from(&ent, FLAV_MICRODESC, md_body[2]));
+
+ /* We're still holding on to this, though, so we can still map it! */
+ const uint8_t *t1 = NULL;
+ size_t s;
+ int r = consensus_cache_entry_get_body(hold_ent, &t1, &s);
+ tt_int_op(r, OP_EQ, 0);
+ tt_assert(t1);
+
+ done:
+ for (i = 0; i < N; ++i) {
+ tor_free(md_body[i]);
+ networkstatus_vote_free(md_ns[i]);
+ }
+ consensus_cache_entry_decref(hold_ent);
+ UNMOCK(cpuworker_queue_work);
+#undef N
+}
+
+static void
+test_consdiffmgr_validate(void *arg)
+{
+ (void)arg;
+ config_line_t *lines = NULL;
+ consensus_cache_entry_t *ent = NULL;
+ consensus_cache_t *cache = cdm_cache_get(); // violate abstraction barrier
+ smartlist_t *vals = smartlist_new();
+
+ /* Put these: objects in the cache: one with a good sha3, one with bad sha3,
+ * one with a wrong sha3, and one with no sha3. */
+ config_line_prepend(&lines, "id", "wrong sha3");
+ config_line_prepend(&lines, "sha3-digest",
+ "F00DF00DF00DF00DF00DF00DF00DF00D"
+ "F00DF00DF00DF00DF00DF00DF00DF00D");
+ ent = consensus_cache_add(cache, lines, (const uint8_t *)"Hi there", 8);
+ consensus_cache_entry_decref(ent);
+ config_free_lines(lines);
+ lines = NULL;
+
+ config_line_prepend(&lines, "id", "bad sha3");
+ config_line_prepend(&lines, "sha3-digest",
+ "now is the winter of our dicotheque");
+ ent = consensus_cache_add(cache, lines, (const uint8_t *)"Hi there", 8);
+ consensus_cache_entry_decref(ent);
+ config_free_lines(lines);
+ lines = NULL;
+
+ config_line_prepend(&lines, "id", "no sha3");
+ ent = consensus_cache_add(cache, lines, (const uint8_t *)"Hi there", 8);
+ consensus_cache_entry_decref(ent);
+ config_free_lines(lines);
+ lines = NULL;
+
+ config_line_prepend(&lines, "id", "good sha3");
+ config_line_prepend(&lines, "sha3-digest",
+ "8d8b1998616cd6b4c4055da8d38728dc"
+ "93c758d4131a53c7d81aa6337dee1c05");
+ ent = consensus_cache_add(cache, lines, (const uint8_t *)"Hi there", 8);
+ consensus_cache_entry_decref(ent);
+ config_free_lines(lines);
+ lines = NULL;
+
+ cdm_reload();
+ cache = cdm_cache_get();
+ tt_int_op(1, OP_EQ, consdiffmgr_validate());
+
+ consensus_cache_find_all(vals, cache, "id", "good sha3");
+ tt_int_op(smartlist_len(vals), OP_EQ, 1);
+ smartlist_clear(vals);
+
+ consensus_cache_find_all(vals, cache, "id", "no sha3");
+ tt_int_op(smartlist_len(vals), OP_EQ, 1);
+ smartlist_clear(vals);
+
+ consensus_cache_find_all(vals, cache, "id", "wrong sha3");
+ tt_int_op(smartlist_len(vals), OP_EQ, 0);
+ consensus_cache_find_all(vals, cache, "id", "bad sha3");
+ tt_int_op(smartlist_len(vals), OP_EQ, 0);
+
+ done:
+ smartlist_free(vals);
+}
+
+#define TEST(name) \
+ { #name, test_consdiffmgr_ ## name , TT_FORK, &setup_diffmgr, NULL }
+
+struct testcase_t consdiffmgr_tests[] = {
+#if 0
+ { "init_failure", test_consdiffmgr_init_failure, TT_FORK, NULL, NULL },
+#endif
+ TEST(sha3_helper),
+ TEST(add),
+ TEST(make_diffs),
+ TEST(diff_rules),
+ TEST(diff_failure),
+ TEST(diff_pending),
+ TEST(cleanup_old),
+ TEST(cleanup_bad_valid_after),
+ TEST(cleanup_no_valid_after),
+ TEST(cleanup_old_diffs),
+ TEST(validate),
+
+ // XXXX Test: non-cacheing cases of replyfn().
+
+ END_OF_TESTCASES
+};
+
diff --git a/src/test/test_containers.c b/src/test/test_containers.c
index 41f3f873de..c4dba73750 100644
--- a/src/test/test_containers.c
+++ b/src/test/test_containers.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -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 d9c0a1eaac..472fcb8c53 100644
--- a/src/test/test_controller.c
+++ b/src/test/test_controller.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Tor Project, Inc. */
+/* Copyright (c) 2015-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONTROL_PRIVATE
@@ -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:
@@ -109,6 +109,45 @@ test_add_onion_helper_keyarg(void *arg)
}
static void
+test_getinfo_helper_onion(void *arg)
+{
+ (void)arg;
+ control_connection_t dummy;
+ /* Get results out */
+ char *answer = NULL;
+ const char *errmsg = NULL;
+ char *service_id = NULL;
+ int rt = 0;
+
+ dummy.ephemeral_onion_services = NULL;
+
+ /* successfully get an empty answer */
+ rt = getinfo_helper_onions(&dummy, "onions/current", &answer, &errmsg);
+ 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_int_op(rt, OP_EQ, 0);
+ tt_str_op(answer, OP_EQ, "");
+ tor_free(answer);
+
+ /* get an answer for one onion service */
+ service_id = tor_strdup("dummy_onion_id");
+ dummy.ephemeral_onion_services = smartlist_new();
+ smartlist_add(dummy.ephemeral_onion_services, service_id);
+ rt = getinfo_helper_onions(&dummy, "onions/current", &answer, &errmsg);
+ tt_int_op(rt, OP_EQ, 0);
+ tt_str_op(answer, OP_EQ, "dummy_onion_id");
+
+ done:
+ tor_free(answer);
+ tor_free(service_id);
+ smartlist_free(dummy.ephemeral_onion_services);
+}
+
+static void
test_rend_service_parse_port_config(void *arg)
{
const char *sep = ",";
@@ -120,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;
@@ -147,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);
@@ -165,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;
@@ -174,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);
@@ -191,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);
@@ -199,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);
@@ -222,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" */
@@ -230,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);
@@ -505,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';
@@ -529,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';
@@ -583,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';
@@ -667,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';
@@ -734,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();
@@ -749,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;
@@ -760,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;
@@ -771,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;
@@ -783,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;
@@ -795,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;
@@ -807,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;
@@ -816,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;
@@ -851,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;
@@ -861,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);
@@ -874,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);
@@ -885,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);
@@ -896,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);
@@ -910,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);
@@ -924,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);
@@ -938,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);
@@ -952,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);
@@ -966,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;
@@ -977,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;
@@ -989,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;
@@ -1001,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;
@@ -1014,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;
@@ -1026,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;
@@ -1038,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");
@@ -1053,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;
@@ -1066,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;
@@ -1079,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");
@@ -1094,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");
@@ -1109,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");
@@ -1146,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;
@@ -1156,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);
@@ -1169,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);
@@ -1183,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;
@@ -1193,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;
@@ -1203,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;
@@ -1213,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;
@@ -1250,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;
@@ -1260,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);
@@ -1273,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);
@@ -1287,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;
@@ -1297,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;
@@ -1307,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;
@@ -1317,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;
@@ -1332,6 +1371,7 @@ test_download_status_bridge(void *arg)
struct testcase_t controller_tests[] = {
{ "add_onion_helper_keyarg", test_add_onion_helper_keyarg, 0, NULL, NULL },
+ { "getinfo_helper_onion", test_getinfo_helper_onion, 0, NULL, NULL },
{ "rend_service_parse_port_config", test_rend_service_parse_port_config, 0,
NULL, NULL },
{ "add_onion_helper_clientauth", test_add_onion_helper_clientauth, 0, NULL,
diff --git a/src/test/test_controller_events.c b/src/test/test_controller_events.c
index 11e1e3dc8f..901ad7ab3d 100644
--- a/src/test/test_controller_events.c
+++ b/src/test/test_controller_events.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Tor Project, Inc. */
+/* Copyright (c) 2013-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONNECTION_PRIVATE
diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c
index d66ddccd4f..c8443fd3bb 100644
--- a/src/test/test_crypto.c
+++ b/src/test/test_crypto.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -15,9 +15,6 @@
#include "crypto_ed25519.h"
#include "ed25519_vectors.inc"
-#include <openssl/evp.h>
-#include <openssl/rand.h>
-
/** Run unit tests for Diffie-Hellman functionality. */
static void
test_crypto_dh(void *arg)
@@ -331,38 +328,6 @@ test_crypto_rng_strongest(void *arg)
#undef N
}
-/* Test for rectifying openssl RAND engine. */
-static void
-test_crypto_rng_engine(void *arg)
-{
- (void)arg;
- RAND_METHOD dummy_method;
- 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_assert(RAND_get_rand_method() == RAND_OpenSSL());
-
- /* We should correct the method if it's a dummy. */
- RAND_set_rand_method(&dummy_method);
-#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());
-#else
- tt_assert(RAND_get_rand_method() == &dummy_method);
- tt_int_op(1, ==, crypto_force_rand_ssleay());
-#endif
- tt_assert(RAND_get_rand_method() == RAND_OpenSSL());
-
- /* Make sure we aren't calling dummy_method */
- crypto_rand((void *) &dummy_method, sizeof(dummy_method));
- crypto_rand((void *) &dummy_method, sizeof(dummy_method));
-
- done:
- ;
-}
-
/** Run unit tests for our AES128 functionality */
static void
test_crypto_aes128(void *arg)
@@ -1174,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 */
@@ -1243,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,
@@ -1280,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);
@@ -1299,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)
@@ -1379,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);
@@ -1418,7 +1383,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
@@ -1441,6 +1406,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);
@@ -1477,28 +1443,6 @@ test_crypto_digest_names(void *arg)
;
}
-#ifndef OPENSSL_1_1_API
-#define EVP_ENCODE_CTX_new() tor_malloc_zero(sizeof(EVP_ENCODE_CTX))
-#define EVP_ENCODE_CTX_free(ctx) tor_free(ctx)
-#endif
-
-/** Encode src into dest with OpenSSL's EVP Encode interface, returning the
- * length of the encoded data in bytes.
- */
-static int
-base64_encode_evp(char *dest, char *src, size_t srclen)
-{
- const unsigned char *s = (unsigned char*)src;
- EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new();
- int len, ret;
-
- EVP_EncodeInit(ctx);
- EVP_EncodeUpdate(ctx, (unsigned char *)dest, &len, s, (int)srclen);
- EVP_EncodeFinal(ctx, (unsigned char *)(dest + len), &ret);
- EVP_ENCODE_CTX_free(ctx);
- return ret+ len;
-}
-
/** Run unit tests for misc crypto formatting functionality (base64, base32,
* fingerprints, etc) */
static void
@@ -1527,7 +1471,7 @@ test_crypto_formats(void *arg)
tt_int_op(i, OP_GE, 0);
tt_int_op(i, OP_EQ, strlen(data2));
tt_assert(! strchr(data2, '='));
- j = base64_decode_nopad((uint8_t*)data3, 1024, data2, i);
+ j = base64_decode(data3, 1024, data2, i);
tt_int_op(j, OP_EQ, idx);
tt_mem_op(data3,OP_EQ, data1, idx);
}
@@ -1552,21 +1496,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);
-
- for (i = 0; i < 256; i++) {
- /* Test the multiline format Base64 encoder with 0 .. 256 bytes of
- * output against OpenSSL.
- */
- const size_t enclen = base64_encode_size(i, BASE64_ENCODE_MULTILINE);
- data1[i] = i;
- j = base64_encode(data2, 1024, data1, i, BASE64_ENCODE_MULTILINE);
- tt_int_op(j, OP_EQ, enclen);
- j = base64_encode_evp(data3, data1, i);
- tt_int_op(j, OP_EQ, enclen);
- tt_mem_op(data2, OP_EQ, data3, enclen);
- tt_int_op(j, OP_EQ, strlen(data2));
- }
+ tt_int_op(digest_from_base64(data3, "###"), OP_LT, 0);
/* Encoding SHA256 */
crypto_rand(data2, DIGEST256_LEN);
@@ -1977,7 +1907,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";
@@ -1985,7 +1915,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];
@@ -2241,6 +2171,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));
@@ -2612,6 +2545,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)
{
@@ -2629,6 +2595,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))
@@ -2710,8 +2678,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);
@@ -2903,6 +2871,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)
{
@@ -2910,17 +2939,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:
;
@@ -2941,7 +2970,6 @@ struct testcase_t crypto_tests[] = {
CRYPTO_LEGACY(formats),
CRYPTO_LEGACY(rng),
{ "rng_range", test_crypto_rng_range, 0, NULL, NULL },
- { "rng_engine", test_crypto_rng_engine, TT_FORK, NULL, NULL },
{ "rng_strongest", test_crypto_rng_strongest, TT_FORK, NULL, NULL },
{ "rng_strongest_nosyscall", test_crypto_rng_strongest, TT_FORK,
&passthrough_setup, (void*)"nosyscall" },
@@ -2989,7 +3017,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
new file mode 100644
index 0000000000..090cb4242b
--- /dev/null
+++ b/src/test/test_crypto_openssl.c
@@ -0,0 +1,107 @@
+/* Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+
+#define CRYPTO_PRIVATE
+
+#include "crypto.h"
+#include "util.h"
+#include "util_format.h"
+#include "compat.h"
+#include "test.h"
+
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include "compat_openssl.h"
+
+/* Test for rectifying openssl RAND engine. */
+static void
+test_crypto_rng_engine(void *arg)
+{
+ (void)arg;
+ RAND_METHOD dummy_method;
+ memset(&dummy_method, 0, sizeof(dummy_method));
+
+ /* We should be a no-op if we're already on RAND_OpenSSL */
+ 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. */
+ RAND_set_rand_method(&dummy_method);
+#ifdef LIBRESSL_VERSION_NUMBER
+ /* On libressl, you can't override the RNG. */
+ tt_assert(RAND_get_rand_method() == RAND_OpenSSL());
+ tt_int_op(0, OP_EQ, crypto_force_rand_ssleay());
+#else
+ tt_assert(RAND_get_rand_method() == &dummy_method);
+ 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 */
+ crypto_rand((void *) &dummy_method, sizeof(dummy_method));
+ crypto_rand((void *) &dummy_method, sizeof(dummy_method));
+
+ done:
+ ;
+}
+
+#ifndef OPENSSL_1_1_API
+#define EVP_ENCODE_CTX_new() tor_malloc_zero(sizeof(EVP_ENCODE_CTX))
+#define EVP_ENCODE_CTX_free(ctx) tor_free(ctx)
+#endif
+
+/** Encode src into dest with OpenSSL's EVP Encode interface, returning the
+ * length of the encoded data in bytes.
+ */
+static int
+base64_encode_evp(char *dest, char *src, size_t srclen)
+{
+ const unsigned char *s = (unsigned char*)src;
+ EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new();
+ int len, ret;
+
+ EVP_EncodeInit(ctx);
+ EVP_EncodeUpdate(ctx, (unsigned char *)dest, &len, s, (int)srclen);
+ EVP_EncodeFinal(ctx, (unsigned char *)(dest + len), &ret);
+ EVP_ENCODE_CTX_free(ctx);
+ return ret+ len;
+}
+
+static void
+test_crypto_base64_encode_matches(void *arg)
+{
+ (void)arg;
+ int i, j;
+ char data1[1024];
+ char data2[1024];
+ char data3[1024];
+
+ for (i = 0; i < 256; i++) {
+ /* Test the multiline format Base64 encoder with 0 .. 256 bytes of
+ * output against OpenSSL.
+ */
+ const size_t enclen = base64_encode_size(i, BASE64_ENCODE_MULTILINE);
+ data1[i] = i;
+ j = base64_encode(data2, 1024, data1, i, BASE64_ENCODE_MULTILINE);
+ tt_int_op(j, OP_EQ, enclen);
+ j = base64_encode_evp(data3, data1, i);
+ tt_int_op(j, OP_EQ, enclen);
+ tt_mem_op(data2, OP_EQ, data3, enclen);
+ tt_int_op(j, OP_EQ, strlen(data2));
+ }
+
+ done:
+ ;
+}
+
+struct testcase_t crypto_openssl_tests[] = {
+ { "rng_engine", test_crypto_rng_engine, TT_FORK, NULL, NULL },
+ { "base64_encode_match", test_crypto_base64_encode_matches,
+ TT_FORK, NULL, NULL },
+ END_OF_TESTCASES
+};
+
diff --git a/src/test/test_crypto_slow.c b/src/test/test_crypto_slow.c
index 0be58c9389..2afb71ff5a 100644
--- a/src/test/test_crypto_slow.c
+++ b/src/test/test_crypto_slow.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -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_data.c b/src/test/test_data.c
index 788489a097..ce6c3394f6 100644
--- a/src/test/test_data.c
+++ b/src/test/test_data.c
@@ -1,6 +1,6 @@
/* Copyright 2001-2004 Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "test.h"
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index 4e5876fa3c..ee4a9780b1 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -1,12 +1,13 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
#include <math.h>
#define CONFIG_PRIVATE
+#define CONTROL_PRIVATE
#define DIRSERV_PRIVATE
#define DIRVOTE_PRIVATE
#define ROUTER_PRIVATE
@@ -17,8 +18,10 @@
#define RELAY_PRIVATE
#include "or.h"
+#include "bridges.h"
#include "confparse.h"
#include "config.h"
+#include "control.h"
#include "crypto_ed25519.h"
#include "directory.h"
#include "dirserv.h"
@@ -273,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);
@@ -292,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));
}
@@ -329,7 +332,7 @@ test_dir_formats(void *arg)
ntor_cc = make_ntor_onion_key_crosscert(&r2_onion_keypair,
&kp1.pubkey,
r2->cache_info.published_on,
- MIN_ONION_KEY_LIFETIME,
+ get_onion_key_lifetime(),
&ntor_cc_sign);
tt_assert(ntor_cc);
base64_encode(cert_buf, sizeof(cert_buf),
@@ -390,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);
@@ -420,7 +423,7 @@ test_dir_formats(void *arg)
add_fingerprint_to_dir(buf, fingerprint_list, 0);
}
-#endif
+#endif /* 0 */
dirserv_free_fingerprint_list();
done:
@@ -476,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);
@@ -630,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);
@@ -910,6 +913,23 @@ mock_get_by_ei_desc_digest(const char *d)
}
}
+static signed_descriptor_t *
+mock_ei_get_by_ei_digest(const char *d)
+{
+ char hex[HEX_DIGEST_LEN+1];
+ base16_encode(hex, sizeof(hex), d, DIGEST_LEN);
+ signed_descriptor_t *sd = &sd_ei_minimal;
+
+ if (!strcmp(hex, "11E0EDF526950739F7769810FCACAB8C882FAEEE")) {
+ sd->signed_descriptor_body = (char *)EX_EI_MINIMAL;
+ sd->signed_descriptor_len = sizeof(EX_EI_MINIMAL);
+ sd->annotations_len = 0;
+ sd->saved_location = SAVED_NOWHERE;
+ return sd;
+ }
+ return NULL;
+}
+
static smartlist_t *mock_ei_insert_list = NULL;
static was_router_added_t
mock_ei_insert(routerlist_t *rl, extrainfo_t *ei, int warn_if_incompatible)
@@ -999,6 +1019,37 @@ test_dir_load_extrainfo(void *arg)
}
static void
+test_dir_getinfo_extra(void *arg)
+{
+ int r;
+ char *answer = NULL;
+ const char *errmsg = NULL;
+
+ (void)arg;
+ MOCK(extrainfo_get_by_descriptor_digest, mock_ei_get_by_ei_digest);
+ r = getinfo_helper_dir(NULL, "extra-info/digest/"
+ "11E0EDF526950739F7769810FCACAB8C882FAEEE", &answer,
+ &errmsg);
+ tt_int_op(0, OP_EQ, r);
+ tt_ptr_op(NULL, OP_EQ, errmsg);
+ tt_str_op(answer, OP_EQ, EX_EI_MINIMAL);
+ tor_free(answer);
+
+ answer = NULL;
+ r = getinfo_helper_dir(NULL, "extra-info/digest/"
+ "NOTAVALIDHEXSTRINGNOTAVALIDHEXSTRINGNOTA", &answer,
+ &errmsg);
+ tt_int_op(0, OP_EQ, r);
+ /* getinfo_helper_dir() should maybe return an error here but doesn't */
+ tt_ptr_op(NULL, OP_EQ, errmsg);
+ /* In any case, there should be no answer for an invalid hex string. */
+ tt_ptr_op(NULL, OP_EQ, answer);
+
+ done:
+ UNMOCK(extrainfo_get_by_descriptor_digest);
+}
+
+static void
test_dir_versions(void *arg)
{
tor_version_t ver1;
@@ -1065,6 +1116,7 @@ test_dir_versions(void *arg)
tt_int_op(0, OP_EQ, ver1.patchlevel);
tt_int_op(VER_RELEASE, OP_EQ, ver1.status);
tt_str_op("alpha", OP_EQ, ver1.status_tag);
+ /* Go through the full set of status tags */
tt_int_op(0, OP_EQ, tor_version_parse("2.1.700-alpha", &ver1));
tt_int_op(2, OP_EQ, ver1.major);
tt_int_op(1, OP_EQ, ver1.minor);
@@ -1079,6 +1131,60 @@ test_dir_versions(void *arg)
tt_int_op(0, OP_EQ, ver1.patchlevel);
tt_int_op(VER_RELEASE, OP_EQ, ver1.status);
tt_str_op("alpha-dev", OP_EQ, ver1.status_tag);
+ tt_int_op(0, OP_EQ, tor_version_parse("0.2.9.5-rc", &ver1));
+ tt_int_op(0, OP_EQ, ver1.major);
+ tt_int_op(2, OP_EQ, ver1.minor);
+ tt_int_op(9, OP_EQ, ver1.micro);
+ tt_int_op(5, OP_EQ, ver1.patchlevel);
+ tt_int_op(VER_RELEASE, OP_EQ, ver1.status);
+ tt_str_op("rc", OP_EQ, ver1.status_tag);
+ tt_int_op(0, OP_EQ, tor_version_parse("0.2.9.6-rc-dev", &ver1));
+ tt_int_op(0, OP_EQ, ver1.major);
+ tt_int_op(2, OP_EQ, ver1.minor);
+ tt_int_op(9, OP_EQ, ver1.micro);
+ tt_int_op(6, OP_EQ, ver1.patchlevel);
+ tt_int_op(VER_RELEASE, OP_EQ, ver1.status);
+ tt_str_op("rc-dev", OP_EQ, ver1.status_tag);
+ tt_int_op(0, OP_EQ, tor_version_parse("0.2.9.8", &ver1));
+ tt_int_op(0, OP_EQ, ver1.major);
+ tt_int_op(2, OP_EQ, ver1.minor);
+ tt_int_op(9, OP_EQ, ver1.micro);
+ tt_int_op(8, OP_EQ, ver1.patchlevel);
+ tt_int_op(VER_RELEASE, OP_EQ, ver1.status);
+ tt_str_op("", OP_EQ, ver1.status_tag);
+ tt_int_op(0, OP_EQ, tor_version_parse("0.2.9.9-dev", &ver1));
+ tt_int_op(0, OP_EQ, ver1.major);
+ tt_int_op(2, OP_EQ, ver1.minor);
+ tt_int_op(9, OP_EQ, ver1.micro);
+ tt_int_op(9, OP_EQ, ver1.patchlevel);
+ tt_int_op(VER_RELEASE, OP_EQ, ver1.status);
+ tt_str_op("dev", OP_EQ, ver1.status_tag);
+ /* In #21450, we fixed an inconsistency in parsing versions > INT32_MAX
+ * between i386 and x86_64, as we used tor_parse_long, and then cast to int
+ */
+ tt_int_op(0, OP_EQ, tor_version_parse("0.2147483647.0", &ver1));
+ tt_int_op(0, OP_EQ, ver1.major);
+ tt_int_op(2147483647, OP_EQ, ver1.minor);
+ tt_int_op(0, OP_EQ, ver1.micro);
+ tt_int_op(0, OP_EQ, ver1.patchlevel);
+ tt_int_op(VER_RELEASE, OP_EQ, ver1.status);
+ tt_str_op("", OP_EQ, ver1.status_tag);
+ tt_int_op(-1, OP_EQ, tor_version_parse("0.2147483648.0", &ver1));
+ tt_int_op(-1, OP_EQ, tor_version_parse("0.4294967295.0", &ver1));
+ /* In #21278, we reject negative version components */
+ tt_int_op(-1, OP_EQ, tor_version_parse("0.-1.0", &ver1));
+ tt_int_op(-1, OP_EQ, tor_version_parse("0.-2147483648.0", &ver1));
+ tt_int_op(-1, OP_EQ, tor_version_parse("0.-4294967295.0", &ver1));
+ /* In #21507, we reject version components with non-numeric prefixes */
+ tt_int_op(-1, OP_EQ, tor_version_parse("0.-0.0", &ver1));
+ tt_int_op(-1, OP_EQ, tor_version_parse("+1.0.0", &ver1));
+ /* use the list in isspace() */
+ tt_int_op(-1, OP_EQ, tor_version_parse("0.\t0.0", &ver1));
+ tt_int_op(-1, OP_EQ, tor_version_parse("0.\n0.0", &ver1));
+ tt_int_op(-1, OP_EQ, tor_version_parse("0.\v0.0", &ver1));
+ tt_int_op(-1, OP_EQ, tor_version_parse("0.\f0.0", &ver1));
+ tt_int_op(-1, OP_EQ, tor_version_parse("0.\r0.0", &ver1));
+ tt_int_op(-1, OP_EQ, tor_version_parse("0. 0.0", &ver1));
#define tt_versionstatus_op(vs1, op, vs2) \
tt_assert_test_type(vs1,vs2,#vs1" "#op" "#vs2,version_status_t, \
@@ -1098,6 +1204,7 @@ test_dir_versions(void *arg)
test_v_i_o(VS_RECOMMENDED, "0.0.7rc2", "0.0.7,Tor 0.0.7rc2,Tor 0.0.8");
test_v_i_o(VS_OLD, "0.0.5.0", "0.0.5.1-cvs");
test_v_i_o(VS_NEW_IN_SERIES, "0.0.5.1-cvs", "0.0.5, 0.0.6");
+ test_v_i_o(VS_NEW, "0.2.9.9-dev", "0.2.9.9");
/* Not on list, but newer than any in same series. */
test_v_i_o(VS_NEW_IN_SERIES, "0.1.0.3",
"Tor 0.1.0.2,Tor 0.0.9.5,Tor 0.1.1.0");
@@ -1136,6 +1243,70 @@ test_dir_versions(void *arg)
"Tor 0.2.1.0-dev (r99)"));
tt_int_op(1,OP_EQ, tor_version_as_new_as("Tor 0.2.1.1",
"Tor 0.2.1.0-dev (r99)"));
+ /* And git revisions */
+ tt_int_op(1,OP_EQ, tor_version_as_new_as(
+ "Tor 0.2.9.9 (git-56788a2489127072)",
+ "Tor 0.2.9.9 (git-56788a2489127072)"));
+ /* a git revision is newer than no git revision */
+ tt_int_op(1,OP_EQ, tor_version_as_new_as(
+ "Tor 0.2.9.9 (git-56788a2489127072)",
+ "Tor 0.2.9.9"));
+ /* a longer git revision is newer than a shorter git revision
+ * this should be true if they prefix-match, but if they don't, they are
+ * incomparable, because hashes aren't ordered (but we compare their bytes
+ * anyway) */
+ tt_int_op(1,OP_EQ, tor_version_as_new_as(
+ "Tor 0.2.9.9 (git-56788a2489127072d513cf4baf35a8ff475f3c7b)",
+ "Tor 0.2.9.9 (git-56788a2489127072)"));
+ tt_int_op(1,OP_EQ, tor_version_as_new_as(
+ "Tor 0.2.9.9 (git-0102)",
+ "Tor 0.2.9.9 (git-03)"));
+ tt_int_op(1,OP_EQ, tor_version_as_new_as(
+ "Tor 0.2.9.9 (git-0102)",
+ "Tor 0.2.9.9 (git-00)"));
+ tt_int_op(1,OP_EQ, tor_version_as_new_as(
+ "Tor 0.2.9.9 (git-01)",
+ "Tor 0.2.9.9 (git-00)"));
+ tt_int_op(0,OP_EQ, tor_version_as_new_as(
+ "Tor 0.2.9.9 (git-00)",
+ "Tor 0.2.9.9 (git-01)"));
+ /* In #21278, we comapre without integer overflows.
+ * But since #21450 limits version components to [0, INT32_MAX], it is no
+ * longer possible to cause an integer overflow in tor_version_compare() */
+ tt_int_op(0,OP_EQ, tor_version_as_new_as(
+ "Tor 0.0.0.0",
+ "Tor 2147483647.0.0.0"));
+ tt_int_op(1,OP_EQ, tor_version_as_new_as(
+ "Tor 2147483647.0.0.0",
+ "Tor 0.0.0.0"));
+ /* These versions used to cause an overflow, now they don't parse
+ * (and authorities reject their descriptors), and log a BUG message */
+ setup_full_capture_of_logs(LOG_WARN);
+ tt_int_op(0,OP_EQ, tor_version_as_new_as(
+ "Tor 0.0.0.0",
+ "Tor 0.-2147483648.0.0"));
+ expect_single_log_msg_containing("unparseable");
+ mock_clean_saved_logs();
+ tt_int_op(0,OP_EQ, tor_version_as_new_as(
+ "Tor 0.2147483647.0.0",
+ "Tor 0.-1.0.0"));
+ expect_single_log_msg_containing("unparseable");
+ mock_clean_saved_logs();
+ tt_int_op(0,OP_EQ, tor_version_as_new_as(
+ "Tor 0.2147483647.0.0",
+ "Tor 0.-2147483648.0.0"));
+ expect_single_log_msg_containing("unparseable");
+ mock_clean_saved_logs();
+ tt_int_op(1,OP_EQ, tor_version_as_new_as(
+ "Tor 4294967295.0.0.0",
+ "Tor 0.0.0.0"));
+ expect_no_log_entry();
+ tt_int_op(0,OP_EQ, tor_version_as_new_as(
+ "Tor 0.4294967295.0.0",
+ "Tor 0.-4294967295.0.0"));
+ expect_single_log_msg_containing("unparseable");
+ mock_clean_saved_logs();
+ teardown_capture_of_logs();
/* Now try git revisions */
tt_int_op(0,OP_EQ, tor_version_parse("0.5.6.7 (git-ff00ff)", &ver1));
@@ -1145,11 +1316,24 @@ test_dir_versions(void *arg)
tt_int_op(7,OP_EQ, ver1.patchlevel);
tt_int_op(3,OP_EQ, ver1.git_tag_len);
tt_mem_op(ver1.git_tag,OP_EQ, "\xff\x00\xff", 3);
+ /* reject bad hex digits */
tt_int_op(-1,OP_EQ, tor_version_parse("0.5.6.7 (git-ff00xx)", &ver1));
+ /* reject odd hex digit count */
tt_int_op(-1,OP_EQ, tor_version_parse("0.5.6.7 (git-ff00fff)", &ver1));
+ /* ignore "git " */
tt_int_op(0,OP_EQ, tor_version_parse("0.5.6.7 (git ff00fff)", &ver1));
+ /* standard length is 16 hex digits */
+ tt_int_op(0,OP_EQ, tor_version_parse("0.5.6.7 (git-0010203040506070)",
+ &ver1));
+ /* length limit is 40 hex digits */
+ tt_int_op(0,OP_EQ, tor_version_parse(
+ "0.5.6.7 (git-000102030405060708090a0b0c0d0e0f10111213)",
+ &ver1));
+ tt_int_op(-1,OP_EQ, tor_version_parse(
+ "0.5.6.7 (git-000102030405060708090a0b0c0d0e0f1011121314)",
+ &ver1));
done:
- ;
+ teardown_capture_of_logs();
}
/** Run unit tests for directory fp_pair functions. */
@@ -1354,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);
@@ -1602,7 +1786,7 @@ test_dir_param_voting_lookup(void *arg)
dirvote_get_intermediate_param_value(lst, "moomin", -100));
tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_EQ, 1);
tt_str_op(smartlist_get(tor_get_captured_bug_log_(), 0), OP_EQ,
- "!(n_found > 1)");
+ "n_found == 0");
tor_end_capture_bugs_();
/* There is no 'fred=', so that is treated as not existing. */
tt_int_op(-100, OP_EQ,
@@ -1690,8 +1874,7 @@ vote_tweaks_for_v3ns(networkstatus_t *v, int voter, time_t now)
measured_bw_line_t mbw;
memset(mbw.node_id, 33, sizeof(mbw.node_id));
mbw.bw_kb = 1024;
- tt_assert(measured_bw_line_apply(&mbw,
- v->routerstatus_list) == 1);
+ tt_int_op(measured_bw_line_apply(&mbw, v->routerstatus_list), OP_EQ, 1);
} else if (voter == 2 || voter == 3) {
/* Monkey around with the list a bit */
vrs = smartlist_get(v->routerstatus_list, 2);
@@ -1807,7 +1990,7 @@ test_consensus_for_v3ns(networkstatus_t *con, time_t now)
(void)now;
tt_assert(con);
- tt_assert(!con->cert);
+ tt_ptr_op(con->cert, OP_EQ, NULL);
tt_int_op(2,OP_EQ, smartlist_len(con->routerstatus_list));
/* There should be two listed routers: one with identity 3, one with
* identity 5. */
@@ -1877,7 +2060,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:
@@ -2069,6 +2252,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 "
@@ -2085,6 +2269,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 "
@@ -2101,6 +2286,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 "
@@ -2121,6 +2307,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));
@@ -2192,6 +2379,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,
@@ -2821,7 +3009,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));
@@ -2961,7 +3149,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:
@@ -2977,9 +3165,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 */
@@ -3076,7 +3264,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:
@@ -3183,7 +3371,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),
@@ -3244,15 +3432,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 */
@@ -3264,17 +3454,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 */
@@ -3288,17 +3478,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 */
@@ -3314,16 +3504,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);
@@ -3341,11 +3531,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);
@@ -3363,11 +3553,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 */
@@ -3386,11 +3576,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 */
@@ -3410,16 +3600,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);
@@ -3475,7 +3665,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"
@@ -3483,23 +3673,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);
@@ -3512,8 +3702,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_();
@@ -3527,11 +3717,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: ;
}
@@ -3539,7 +3730,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: ;
@@ -3550,12 +3741,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: ;
}
@@ -3565,24 +3756,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: ;
}
@@ -3635,9 +3827,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");
@@ -3754,7 +3946,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"
@@ -3926,47 +4118,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;
@@ -3978,32 +4228,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);
@@ -4013,76 +4328,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;
@@ -4090,22 +4405,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;
@@ -4118,19 +4433,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;
@@ -4141,65 +4457,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;
@@ -4207,22 +4523,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;
@@ -4235,9 +4551,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 */
@@ -4250,13 +4567,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;
@@ -4399,15 +4717,7 @@ test_dir_should_use_directory_guards(void *data)
}
NS_DECL(void,
-directory_initiate_command_routerstatus, (const routerstatus_t *status,
- uint8_t dir_purpose,
- uint8_t router_purpose,
- dir_indirection_t indirection,
- const char *resource,
- const char *payload,
- size_t payload_len,
- time_t if_modified_since,
- circuit_guard_state_t *guardstate));
+directory_initiate_request, (directory_request_t *req));
static void
test_dir_should_not_init_request_to_ourselves(void *data)
@@ -4417,7 +4727,7 @@ test_dir_should_not_init_request_to_ourselves(void *data)
crypto_pk_t *key = pk_generate(2);
(void) data;
- NS_MOCK(directory_initiate_command_routerstatus);
+ NS_MOCK(directory_initiate_request);
clear_dir_servers();
routerlist_free_all();
@@ -4432,15 +4742,15 @@ test_dir_should_not_init_request_to_ourselves(void *data)
dir_server_add(ourself);
directory_get_from_all_authorities(DIR_PURPOSE_FETCH_STATUS_VOTE, 0, NULL);
- tt_int_op(CALLED(directory_initiate_command_routerstatus), OP_EQ, 0);
+ tt_int_op(CALLED(directory_initiate_request), OP_EQ, 0);
directory_get_from_all_authorities(DIR_PURPOSE_FETCH_DETACHED_SIGNATURES, 0,
NULL);
- tt_int_op(CALLED(directory_initiate_command_routerstatus), OP_EQ, 0);
+ tt_int_op(CALLED(directory_initiate_request), OP_EQ, 0);
done:
- NS_UNMOCK(directory_initiate_command_routerstatus);
+ NS_UNMOCK(directory_initiate_request);
clear_dir_servers();
routerlist_free_all();
crypto_pk_free(key);
@@ -4454,7 +4764,7 @@ test_dir_should_not_init_request_to_dir_auths_without_v3_info(void *data)
| MICRODESC_DIRINFO;
(void) data;
- NS_MOCK(directory_initiate_command_routerstatus);
+ NS_MOCK(directory_initiate_request);
clear_dir_servers();
routerlist_free_all();
@@ -4465,14 +4775,14 @@ test_dir_should_not_init_request_to_dir_auths_without_v3_info(void *data)
dir_server_add(ds);
directory_get_from_all_authorities(DIR_PURPOSE_FETCH_STATUS_VOTE, 0, NULL);
- tt_int_op(CALLED(directory_initiate_command_routerstatus), OP_EQ, 0);
+ tt_int_op(CALLED(directory_initiate_request), OP_EQ, 0);
directory_get_from_all_authorities(DIR_PURPOSE_FETCH_DETACHED_SIGNATURES, 0,
NULL);
- tt_int_op(CALLED(directory_initiate_command_routerstatus), OP_EQ, 0);
+ tt_int_op(CALLED(directory_initiate_request), OP_EQ, 0);
done:
- NS_UNMOCK(directory_initiate_command_routerstatus);
+ NS_UNMOCK(directory_initiate_request);
clear_dir_servers();
routerlist_free_all();
}
@@ -4483,7 +4793,7 @@ test_dir_should_init_request_to_dir_auths(void *data)
dir_server_t *ds = NULL;
(void) data;
- NS_MOCK(directory_initiate_command_routerstatus);
+ NS_MOCK(directory_initiate_request);
clear_dir_servers();
routerlist_free_all();
@@ -4494,39 +4804,23 @@ test_dir_should_init_request_to_dir_auths(void *data)
dir_server_add(ds);
directory_get_from_all_authorities(DIR_PURPOSE_FETCH_STATUS_VOTE, 0, NULL);
- tt_int_op(CALLED(directory_initiate_command_routerstatus), OP_EQ, 1);
+ tt_int_op(CALLED(directory_initiate_request), OP_EQ, 1);
directory_get_from_all_authorities(DIR_PURPOSE_FETCH_DETACHED_SIGNATURES, 0,
NULL);
- tt_int_op(CALLED(directory_initiate_command_routerstatus), OP_EQ, 2);
+ tt_int_op(CALLED(directory_initiate_request), OP_EQ, 2);
done:
- NS_UNMOCK(directory_initiate_command_routerstatus);
+ NS_UNMOCK(directory_initiate_request);
clear_dir_servers();
routerlist_free_all();
}
void
-NS(directory_initiate_command_routerstatus)(const routerstatus_t *status,
- uint8_t dir_purpose,
- uint8_t router_purpose,
- dir_indirection_t indirection,
- const char *resource,
- const char *payload,
- size_t payload_len,
- time_t if_modified_since,
- circuit_guard_state_t *guardstate)
+NS(directory_initiate_request)(directory_request_t *req)
{
- (void)status;
- (void)dir_purpose;
- (void)router_purpose;
- (void)indirection;
- (void)resource;
- (void)payload;
- (void)payload_len;
- (void)if_modified_since;
- (void)guardstate;
- CALLED(directory_initiate_command_routerstatus)++;
+ (void)req;
+ CALLED(directory_initiate_request)++;
}
static void
@@ -4589,13 +4883,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) {
@@ -4622,7 +4916,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);
@@ -4651,8 +4945,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);
@@ -4778,7 +5072,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);
/*
@@ -4791,21 +5085,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);
/*
@@ -4813,8 +5107,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.
@@ -4826,14 +5120,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 */
@@ -4842,21 +5136,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);
/*
@@ -4864,8 +5159,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
@@ -4877,14 +5172,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 */
@@ -4893,14 +5188,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 */
@@ -4909,21 +5205,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);
/*
@@ -4931,8 +5228,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
@@ -4944,14 +5241,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 */
@@ -4960,14 +5257,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 */
@@ -4976,21 +5274,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);
/*
@@ -4998,8 +5297,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
@@ -5011,14 +5310,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 */
@@ -5027,14 +5326,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 */
@@ -5043,21 +5343,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);
/*
@@ -5065,8 +5366,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
@@ -5078,14 +5379,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 */
@@ -5094,14 +5395,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 */
@@ -5110,14 +5412,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 */
@@ -5126,21 +5429,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);
/*
@@ -5148,8 +5452,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
@@ -5161,14 +5465,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 */
@@ -5177,14 +5481,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 */
@@ -5193,14 +5498,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 */
@@ -5209,21 +5515,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);
/*
@@ -5231,8 +5538,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:
@@ -5279,7 +5586,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;
@@ -5342,53 +5649,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 */
@@ -5397,10 +5704,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 =
@@ -5413,10 +5720,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);
@@ -5429,13 +5736,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);
@@ -5444,9 +5751,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:
@@ -5568,9 +5875,17 @@ mock_networkstatus_consensus_can_use_extra_fallbacks(
return mock_networkstatus_consensus_can_use_extra_fallbacks_value;
}
-/* data is a 2 character nul-terminated string.
+static int mock_any_bridge_descriptors_known_value = 0;
+static int
+mock_any_bridge_descriptors_known(void)
+{
+ return mock_any_bridge_descriptors_known_value;
+}
+
+/* data is a 3 character nul-terminated string.
* If data[0] is 'b', set bootstrapping, anything else means not bootstrapping
* If data[1] is 'f', set extra fallbacks, anything else means no extra
+ * If data[2] is 'f', set running bridges, anything else means no extra
* fallbacks.
*/
static void
@@ -5578,7 +5893,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;
@@ -5592,15 +5907,23 @@ test_dir_find_dl_schedule(void* data)
mock_networkstatus_consensus_can_use_extra_fallbacks_value = 0;
}
+ if (str[2] == 'r') {
+ mock_any_bridge_descriptors_known_value = 1;
+ } else {
+ mock_any_bridge_descriptors_known_value = 0;
+ }
+
MOCK(networkstatus_consensus_is_bootstrapping,
mock_networkstatus_consensus_is_bootstrapping);
MOCK(networkstatus_consensus_can_use_extra_fallbacks,
mock_networkstatus_consensus_can_use_extra_fallbacks);
+ MOCK(any_bridge_descriptors_known,
+ mock_any_bridge_descriptors_known);
download_status_t dls;
smartlist_t server, client, server_cons, client_cons;
smartlist_t client_boot_auth_only_cons, client_boot_auth_cons;
- smartlist_t client_boot_fallback_cons, bridge;
+ smartlist_t client_boot_fallback_cons, bridge, bridge_bootstrap;
mock_options = tor_malloc(sizeof(or_options_t));
reset_options(mock_options, &mock_get_options_calls);
@@ -5617,6 +5940,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 */
@@ -5705,11 +6029,17 @@ test_dir_find_dl_schedule(void* data)
dls.schedule = DL_SCHED_BRIDGE;
/* client */
mock_options->ClientOnly = 1;
- tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, &bridge);
+ mock_options->UseBridges = 1;
+ if (any_bridge_descriptors_known()) {
+ tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, &bridge);
+ } else {
+ tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, &bridge_bootstrap);
+ }
done:
UNMOCK(networkstatus_consensus_is_bootstrapping);
UNMOCK(networkstatus_consensus_can_use_extra_fallbacks);
+ UNMOCK(any_bridge_descriptors_known);
UNMOCK(get_options);
tor_free(mock_options);
mock_options = NULL;
@@ -5819,6 +6149,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 }
@@ -5837,6 +6190,7 @@ struct testcase_t dir_tests[] = {
DIR(parse_router_list, TT_FORK),
DIR(load_routers, TT_FORK),
DIR(load_extrainfo, TT_FORK),
+ DIR(getinfo_extra, 0),
DIR_LEGACY(versions),
DIR_LEGACY(fp_pairs),
DIR(split_fps, 0),
@@ -5862,6 +6216,7 @@ struct testcase_t dir_tests[] = {
DIR(packages, 0),
DIR(download_status_schedule, 0),
DIR(download_status_random_backoff, 0),
+ DIR(download_status_random_backoff_ranges, 0),
DIR(download_status_increment, 0),
DIR(authdir_type_to_string, 0),
DIR(conn_purpose_to_string, 0),
@@ -5873,12 +6228,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 ca43dd4c04..fdf43533a8 100644
--- a/src/test/test_dir_common.c
+++ b/src/test/test_dir_common.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -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_common.h b/src/test/test_dir_common.h
index 9682b0db49..65b9cf6436 100644
--- a/src/test/test_dir_common.h
+++ b/src/test/test_dir_common.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "or.h"
diff --git a/src/test/test_dir_handle_get.c b/src/test/test_dir_handle_get.c
index a0868f9253..fe26657ad8 100644
--- a/src/test/test_dir_handle_get.c
+++ b/src/test/test_dir_handle_get.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define RENDCOMMON_PRIVATE
@@ -12,8 +12,10 @@
#include "or.h"
#include "config.h"
#include "connection.h"
+#include "consdiffmgr.h"
#include "directory.h"
#include "test.h"
+#include "compress.h"
#include "connection.h"
#include "rendcommon.h"
#include "rendcache.h"
@@ -26,9 +28,9 @@
#include "entrynodes.h"
#include "routerparse.h"
#include "networkstatus.h"
+#include "proto_http.h"
#include "geoip.h"
#include "dirserv.h"
-#include "torgzip.h"
#include "dirvote.h"
#include "log_test_helpers.h"
@@ -37,7 +39,7 @@
#include <direct.h>
#else
#include <dirent.h>
-#endif
+#endif /* defined(_WIN32) */
#ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
DISABLE_GCC_WARNING(overlength-strings)
@@ -63,6 +65,7 @@ new_dir_conn(void)
{
dir_connection_t *conn = dir_connection_new(AF_INET);
tor_addr_from_ipv4h(&conn->base_.addr, 0x7f000001);
+ TO_CONN(conn)->address = tor_strdup("127.0.0.1");
return conn;
}
@@ -465,6 +468,8 @@ init_mock_options(void)
mock_options = tor_malloc(sizeof(or_options_t));
memset(mock_options, 0, sizeof(or_options_t));
mock_options->TestingTorNetwork = 1;
+ mock_options->DataDirectory = tor_strdup(get_fname_rnd("datadir_tmp"));
+ check_private_dir(mock_options->DataDirectory, CPD_CREATE, NULL);
}
static const or_options_t *
@@ -501,14 +506,6 @@ test_dir_handle_get_micro_d(void *data)
/* SETUP */
init_mock_options();
- const char *fn = get_fname("dir_handle_datadir_test1");
- mock_options->DataDirectory = tor_strdup(fn);
-
-#ifdef _WIN32
- tt_int_op(0, OP_EQ, mkdir(mock_options->DataDirectory));
-#else
- tt_int_op(0, OP_EQ, mkdir(mock_options->DataDirectory, 0700));
-#endif
/* Add microdesc to cache */
crypto_digest256(digest, microdesc, strlen(microdesc), DIGEST_SHA256);
@@ -568,14 +565,6 @@ test_dir_handle_get_micro_d_server_busy(void *data)
/* SETUP */
init_mock_options();
- const char *fn = get_fname("dir_handle_datadir_test2");
- mock_options->DataDirectory = tor_strdup(fn);
-
-#ifdef _WIN32
- tt_int_op(0, OP_EQ, mkdir(mock_options->DataDirectory));
-#else
- tt_int_op(0, OP_EQ, mkdir(mock_options->DataDirectory, 0700));
-#endif
/* Add microdesc to cache */
crypto_digest256(digest, microdesc, strlen(microdesc), DIGEST_SHA256);
@@ -743,7 +732,7 @@ test_dir_handle_get_server_descriptors_not_found(void* data)
NULL, NULL, 1, 0);
tt_str_op(NOT_FOUND, OP_EQ, header);
- tt_int_op(conn->dir_spool_src, OP_EQ, DIR_SPOOL_SERVER_BY_FP);
+ tt_ptr_op(conn->spool, OP_EQ, NULL);
done:
UNMOCK(connection_write_to_buf_impl_);
@@ -773,6 +762,7 @@ test_dir_handle_get_server_descriptors_all(void* data)
tt_int_op(smartlist_len(our_routerlist->routers), OP_GE, 1);
mock_routerinfo = smartlist_get(our_routerlist->routers, 0);
set_server_identity_key(mock_routerinfo->identity_pkey);
+ mock_routerinfo->cache_info.published_on = time(NULL);
/* Treat "all" requests as if they were unencrypted */
mock_routerinfo->cache_info.send_unencrypted = 1;
@@ -787,7 +777,7 @@ test_dir_handle_get_server_descriptors_all(void* data)
//which is smaller than that by annotation_len bytes
fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
&body, &body_used,
- mock_routerinfo->cache_info.signed_descriptor_len+1, 0);
+ 1024*1024, 0);
tt_assert(header);
tt_assert(body);
@@ -803,7 +793,7 @@ test_dir_handle_get_server_descriptors_all(void* data)
tt_str_op(body, OP_EQ, mock_routerinfo->cache_info.signed_descriptor_body +
mock_routerinfo->cache_info.annotations_len);
- tt_int_op(conn->dir_spool_src, OP_EQ, DIR_SPOOL_NONE);
+ tt_ptr_op(conn->spool, OP_EQ, NULL);
done:
NS_UNMOCK(router_get_my_routerinfo);
@@ -880,8 +870,9 @@ 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);
conn = new_dir_conn();
@@ -904,7 +895,7 @@ test_dir_handle_get_server_descriptors_authority(void* data)
tt_int_op(body_used, OP_EQ, strlen(body));
tt_str_op(body, OP_EQ, TEST_DESCRIPTOR + annotation_len);
- tt_int_op(conn->dir_spool_src, OP_EQ, DIR_SPOOL_NONE);
+ tt_ptr_op(conn->spool, OP_EQ, NULL);
done:
NS_UNMOCK(router_get_my_routerinfo);
@@ -946,6 +937,7 @@ test_dir_handle_get_server_descriptors_fp(void* data)
mock_routerinfo->cache_info.signed_descriptor_len =
strlen(TEST_DESCRIPTOR) - annotation_len;
mock_routerinfo->cache_info.annotations_len = annotation_len;
+ mock_routerinfo->cache_info.published_on = time(NULL);
conn = new_dir_conn();
@@ -975,7 +967,7 @@ test_dir_handle_get_server_descriptors_fp(void* data)
tt_int_op(body_used, OP_EQ, strlen(body));
tt_str_op(body, OP_EQ, TEST_DESCRIPTOR + annotation_len);
- tt_int_op(conn->dir_spool_src, OP_EQ, DIR_SPOOL_NONE);
+ tt_ptr_op(conn->spool, OP_EQ, NULL);
done:
NS_UNMOCK(router_get_my_routerinfo);
@@ -1041,7 +1033,7 @@ test_dir_handle_get_server_descriptors_d(void* data)
tt_str_op(body, OP_EQ, router->cache_info.signed_descriptor_body +
router->cache_info.annotations_len);
- tt_int_op(conn->dir_spool_src, OP_EQ, DIR_SPOOL_NONE);
+ tt_ptr_op(conn->spool, OP_EQ, NULL);
done:
UNMOCK(connection_write_to_buf_impl_);
@@ -1096,7 +1088,7 @@ test_dir_handle_get_server_descriptors_busy(void* data)
tt_assert(header);
tt_str_op(SERVER_BUSY, OP_EQ, header);
- tt_int_op(conn->dir_spool_src, OP_EQ, DIR_SPOOL_NONE);
+ tt_ptr_op(conn->spool, OP_EQ, NULL);
done:
UNMOCK(get_options);
@@ -1618,8 +1610,13 @@ test_dir_handle_get_status_vote_current_consensus_ns_not_enough_sigs(void* d)
/* init mock */
mock_ns_val = tor_malloc_zero(sizeof(networkstatus_t));
mock_ns_val->flavor = FLAV_NS;
+ mock_ns_val->type = NS_TYPE_CONSENSUS;
mock_ns_val->voters = smartlist_new();
- mock_ns_val->valid_until = time(NULL);
+ mock_ns_val->valid_after = time(NULL) - 1800;
+ mock_ns_val->valid_until = time(NULL) - 60;
+
+ #define NETWORK_STATUS "some network status string"
+ consdiffmgr_add_consensus(NETWORK_STATUS, mock_ns_val);
/* init mock */
init_mock_options();
@@ -1707,10 +1704,17 @@ test_dir_handle_get_status_vote_current_consensus_too_old(void *data)
(void)data;
mock_ns_val = tor_malloc_zero(sizeof(networkstatus_t));
+ mock_ns_val->type = NS_TYPE_CONSENSUS;
mock_ns_val->flavor = FLAV_MICRODESC;
- mock_ns_val->valid_until = time(NULL) - (60 * 60 * 24) - 1;
+ mock_ns_val->valid_after = time(NULL) - (24 * 60 * 60 + 1800);
+ mock_ns_val->fresh_until = time(NULL) - (24 * 60 * 60 + 900);
+ mock_ns_val->valid_until = time(NULL) - (24 * 60 * 60 + 20);
+
+ #define NETWORK_STATUS "some network status string"
+ consdiffmgr_add_consensus(NETWORK_STATUS, mock_ns_val);
init_mock_options();
+
MOCK(get_options, mock_get_options);
MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
MOCK(networkstatus_get_latest_consensus_by_flavor, mock_ns_get_by_flavor);
@@ -1731,6 +1735,17 @@ test_dir_handle_get_status_vote_current_consensus_too_old(void *data)
tor_free(header);
teardown_capture_of_logs();
+ tor_free(mock_ns_val);
+
+ mock_ns_val = tor_malloc_zero(sizeof(networkstatus_t));
+ mock_ns_val->type = NS_TYPE_CONSENSUS;
+ mock_ns_val->flavor = FLAV_NS;
+ mock_ns_val->valid_after = time(NULL) - (24 * 60 * 60 + 1800);
+ mock_ns_val->fresh_until = time(NULL) - (24 * 60 * 60 + 900);
+ mock_ns_val->valid_until = time(NULL) - (24 * 60 * 60 + 20);
+
+ #define NETWORK_STATUS "some network status string"
+ consdiffmgr_add_consensus(NETWORK_STATUS, mock_ns_val);
setup_capture_of_logs(LOG_WARN);
@@ -1769,12 +1784,26 @@ static void
status_vote_current_consensus_ns_test(char **header, char **body,
size_t *body_len)
{
- common_digests_t digests;
dir_connection_t *conn = NULL;
#define NETWORK_STATUS "some network status string"
+#if 0
+ common_digests_t digests;
+ uint8_t sha3[DIGEST256_LEN];
+ memset(&digests, 0x60, sizeof(digests));
+ memset(sha3, 0x06, sizeof(sha3));
dirserv_set_cached_consensus_networkstatus(NETWORK_STATUS, "ns", &digests,
+ sha3,
time(NULL));
+#endif /* 0 */
+ networkstatus_t *ns = tor_malloc_zero(sizeof(networkstatus_t));
+ ns->type = NS_TYPE_CONSENSUS;
+ ns->flavor = FLAV_NS;
+ ns->valid_after = time(NULL) - 1800;
+ ns->fresh_until = time(NULL) - 900;
+ ns->valid_until = time(NULL) - 60;
+ consdiffmgr_add_consensus(NETWORK_STATUS, ns);
+ networkstatus_vote_free(ns);
MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
@@ -1787,7 +1816,6 @@ status_vote_current_consensus_ns_test(char **header, char **body,
tt_str_op("ab", OP_EQ, geoip_get_country_name(1));
conn = new_dir_conn();
- TO_CONN(conn)->address = tor_strdup("127.0.0.1");
tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
GET("/tor/status-vote/current/consensus-ns"), NULL, 0));
@@ -1829,8 +1857,8 @@ test_dir_handle_get_status_vote_current_consensus_ns(void* data)
comp_body_used);
tt_int_op(ZLIB_METHOD, OP_EQ, compression);
- tor_gzip_uncompress(&body, &body_used, comp_body, comp_body_used,
- compression, 0, LOG_PROTOCOL_WARN);
+ tor_uncompress(&body, &body_used, comp_body, comp_body_used,
+ compression, 0, LOG_PROTOCOL_WARN);
tt_str_op(NETWORK_STATUS, OP_EQ, body);
tt_int_op(strlen(NETWORK_STATUS), OP_EQ, body_used);
@@ -2494,6 +2522,53 @@ test_dir_handle_get_status_vote_current_authority(void* data)
dirvote_free_all();
}
+static void
+test_dir_handle_get_parse_accept_encoding(void *arg)
+{
+ (void)arg;
+ const unsigned B_NONE = 1u << NO_METHOD;
+ const unsigned B_ZLIB = 1u << ZLIB_METHOD;
+ const unsigned B_GZIP = 1u << GZIP_METHOD;
+ const unsigned B_LZMA = 1u << LZMA_METHOD;
+ const unsigned B_ZSTD = 1u << ZSTD_METHOD;
+
+ unsigned encodings;
+
+ encodings = parse_accept_encoding_header("");
+ tt_uint_op(B_NONE, OP_EQ, encodings);
+
+ encodings = parse_accept_encoding_header(" ");
+ tt_uint_op(B_NONE, OP_EQ, encodings);
+
+ encodings = parse_accept_encoding_header("dewey, cheatham, and howe ");
+ tt_uint_op(B_NONE, OP_EQ, encodings);
+
+ encodings = parse_accept_encoding_header("dewey, cheatham, and gzip");
+ tt_uint_op(B_NONE, OP_EQ, encodings);
+
+ encodings = parse_accept_encoding_header("dewey, cheatham, and, gzip");
+ tt_uint_op(B_NONE|B_GZIP, OP_EQ, encodings);
+
+ encodings = parse_accept_encoding_header(" gzip");
+ tt_uint_op(B_NONE|B_GZIP, OP_EQ, encodings);
+
+ encodings = parse_accept_encoding_header("gzip");
+ tt_uint_op(B_NONE|B_GZIP, OP_EQ, encodings);
+
+ encodings = parse_accept_encoding_header("x-zstd, deflate, x-tor-lzma");
+ tt_uint_op(B_NONE|B_ZLIB|B_ZSTD|B_LZMA, OP_EQ, encodings);
+
+ encodings = parse_accept_encoding_header(
+ "x-zstd, deflate, x-tor-lzma, gzip");
+ tt_uint_op(B_NONE|B_ZLIB|B_ZSTD|B_LZMA|B_GZIP, OP_EQ, encodings);
+
+ encodings = parse_accept_encoding_header("x-zstd,deflate,x-tor-lzma,gzip");
+ tt_uint_op(B_NONE|B_ZLIB|B_ZSTD|B_LZMA|B_GZIP, OP_EQ, encodings);
+
+ done:
+ ;
+}
+
#define DIR_HANDLE_CMD(name,flags) \
{ #name, test_dir_handle_get_##name, (flags), NULL, NULL }
@@ -2538,11 +2613,11 @@ struct testcase_t dir_handle_get_tests[] = {
DIR_HANDLE_CMD(status_vote_current_authority, 0),
DIR_HANDLE_CMD(status_vote_next_authority_not_found, 0),
DIR_HANDLE_CMD(status_vote_next_authority, 0),
- DIR_HANDLE_CMD(status_vote_current_consensus_ns_not_enough_sigs, 0),
- DIR_HANDLE_CMD(status_vote_current_consensus_ns_not_found, 0),
- DIR_HANDLE_CMD(status_vote_current_consensus_too_old, 0),
- DIR_HANDLE_CMD(status_vote_current_consensus_ns_busy, 0),
- DIR_HANDLE_CMD(status_vote_current_consensus_ns, 0),
+ DIR_HANDLE_CMD(status_vote_current_consensus_ns_not_enough_sigs, TT_FORK),
+ DIR_HANDLE_CMD(status_vote_current_consensus_ns_not_found, TT_FORK),
+ DIR_HANDLE_CMD(status_vote_current_consensus_too_old, TT_FORK),
+ DIR_HANDLE_CMD(status_vote_current_consensus_ns_busy, TT_FORK),
+ DIR_HANDLE_CMD(status_vote_current_consensus_ns, TT_FORK),
DIR_HANDLE_CMD(status_vote_current_d_not_found, 0),
DIR_HANDLE_CMD(status_vote_next_d_not_found, 0),
DIR_HANDLE_CMD(status_vote_d, 0),
@@ -2552,6 +2627,7 @@ struct testcase_t dir_handle_get_tests[] = {
DIR_HANDLE_CMD(status_vote_next_consensus_signatures_not_found, 0),
DIR_HANDLE_CMD(status_vote_next_consensus_signatures_busy, 0),
DIR_HANDLE_CMD(status_vote_next_consensus_signatures, 0),
+ DIR_HANDLE_CMD(parse_accept_encoding, 0),
END_OF_TESTCASES
};
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 50848cfec2..c29b1a7126 100644
--- a/src/test/test_entryconn.c
+++ b/src/test/test_entryconn.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Tor Project, Inc. */
+/* Copyright (c) 2014-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -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 e215c60e23..f9d981953d 100644
--- a/src/test/test_entrynodes.c
+++ b/src/test/test_entrynodes.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Tor Project, Inc. */
+/* Copyright (c) 2014-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -455,29 +455,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 +595,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 +625,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 +730,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 +742,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 +750,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 +767,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 +847,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 +886,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 +917,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 +925,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 +950,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 +994,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 +1018,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));
@@ -1520,7 +1522,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);
@@ -1637,6 +1639,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);
@@ -1707,7 +1730,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());
@@ -1727,7 +1750,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());
@@ -1755,7 +1778,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);
@@ -1813,7 +1836,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));
@@ -1913,7 +1936,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);
@@ -1945,7 +1968,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);
@@ -1981,7 +2004,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);
@@ -2036,7 +2059,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);
@@ -2050,7 +2073,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);
@@ -2102,7 +2125,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);
@@ -2119,7 +2142,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);
@@ -2145,7 +2168,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);
@@ -2194,7 +2217,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);
@@ -2202,7 +2225,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);
diff --git a/src/test/test_extorport.c b/src/test/test_extorport.c
index 1f92780177..e18deb2700 100644
--- a/src/test/test_extorport.c
+++ b/src/test/test_extorport.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Tor Project, Inc. */
+/* Copyright (c) 2013-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONNECTION_PRIVATE
@@ -72,13 +72,13 @@ test_ext_or_id_map(void *arg)
* writes to outbuf. */
static void
connection_write_to_buf_impl_replacement(const char *string, size_t len,
- connection_t *conn, int zlib)
+ connection_t *conn, int compressed)
{
- (void) zlib;
+ (void) compressed;
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 8173e44d47..51ca8f08ec 100644
--- a/src/test/test_guardfraction.c
+++ b/src/test/test_guardfraction.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Tor Project, Inc. */
+/* Copyright (c) 2014-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define DIRSERV_PRIVATE
@@ -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_handles.c b/src/test/test_handles.c
index 536a478689..7ddee6e376 100644
--- a/src/test/test_handles.c
+++ b/src/test/test_handles.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Tor Project, Inc. */
+/* Copyright (c) 2016-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_helpers.c b/src/test/test_helpers.c
index 5b84366e6d..0da9cf64d0 100644
--- a/src/test/test_helpers.c
+++ b/src/test/test_helpers.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Tor Project, Inc. */
+/* Copyright (c) 2014-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -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) {
@@ -98,14 +107,14 @@ helper_setup_fake_routerlist(void)
void
connection_write_to_buf_mock(const char *string, size_t len,
- connection_t *conn, int zlib)
+ connection_t *conn, int compressed)
{
- (void) zlib;
+ (void) compressed;
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 c6d4d9c41f..9bc8553257 100644
--- a/src/test/test_helpers.h
+++ b/src/test/test_helpers.h
@@ -1,9 +1,11 @@
-/* Copyright (c) 2014-2016, 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);
@@ -15,12 +17,16 @@ void helper_setup_fake_routerlist(void);
#define GET(path) "GET " path " HTTP/1.0\r\n\r\n"
void connection_write_to_buf_mock(const char *string, size_t len,
- connection_t *conn, int zlib);
+ connection_t *conn, int compressed);
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 fbaabe91d8..7737499f50 100644
--- a/src/test/test_hs.c
+++ b/src/test/test_hs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2016, The Tor Project, Inc. */
+/* Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -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. */
@@ -210,14 +299,35 @@ test_hs_desc_event(void *arg)
tt_str_op(received_msg,OP_EQ, expected_msg);
tor_free(received_msg);
- /* test valid content. */
+ /* test no HSDir fingerprint type */
+ rend_query.auth_type = REND_NO_AUTH;
+ control_event_hs_descriptor_failed(&rend_query.base_, NULL,
+ "QUERY_NO_HSDIR");
+ expected_msg = "650 HS_DESC FAILED "STR_HS_ADDR" NO_AUTH " \
+ "UNKNOWN REASON=QUERY_NO_HSDIR\r\n";
+ tt_assert(received_msg);
+ tt_str_op(received_msg,OP_EQ, expected_msg);
+ tor_free(received_msg);
+
+ /* Test invalid content with no HSDir fingerprint. */
char *exp_msg;
control_event_hs_descriptor_content(rend_query.onion_address,
+ STR_HS_CONTENT_DESC_ID, NULL, NULL);
+ tor_asprintf(&exp_msg, "650+HS_DESC_CONTENT " STR_HS_ADDR " "\
+ STR_HS_CONTENT_DESC_ID " UNKNOWN" \
+ "\r\n\r\n.\r\n650 OK\r\n");
+ tt_assert(received_msg);
+ tt_str_op(received_msg, OP_EQ, exp_msg);
+ tor_free(received_msg);
+ tor_free(exp_msg);
+
+ /* 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);
@@ -253,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:
@@ -288,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:
@@ -325,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));
@@ -357,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);
@@ -380,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;
@@ -406,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,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));
@@ -484,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));
@@ -493,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 */
@@ -551,32 +661,24 @@ test_single_onion_poisoning(void *arg)
char *dir2 = tor_strdup(get_fname_rnd("test_hs_dir2"));
smartlist_t *services = smartlist_new();
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;
@@ -586,194 +688,197 @@ test_single_onion_poisoning(void *arg)
/* Add port to service 1 */
service_1->ports = smartlist_new();
service_2->ports = smartlist_new();
- char *err_msg = NULL;
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 */
@@ -785,6 +890,7 @@ test_single_onion_poisoning(void *arg)
rend_service_free(service_2);
UNMOCK(get_options);
tor_free(mock_options->DataDirectory);
+ tor_free(err_msg);
}
static rend_service_t *
@@ -821,7 +927,9 @@ test_prune_services_on_reload(void *arg)
smartlist_add(old, e1);
/* Only put the non ephemeral in the new list. */
smartlist_add(new, s1);
- prune_services_on_reload(old, new);
+ set_rend_service_list(old);
+ set_rend_rend_service_staging_list(new);
+ rend_service_prune_list_impl_();
/* We expect that the ephemeral one is in the new list but removed from
* the old one. */
tt_int_op(smartlist_len(old), OP_EQ, 1);
@@ -840,7 +948,9 @@ test_prune_services_on_reload(void *arg)
* one. */
smartlist_add(old, s1);
smartlist_add(old, e1);
- prune_services_on_reload(old, new);
+ set_rend_service_list(old);
+ set_rend_rend_service_staging_list(new);
+ rend_service_prune_list_impl_();
tt_int_op(smartlist_len(old), OP_EQ, 1);
tt_assert(smartlist_get(old, 0) == s1);
tt_int_op(smartlist_len(new), OP_EQ, 1);
@@ -855,7 +965,9 @@ test_prune_services_on_reload(void *arg)
* list being completely different. */
smartlist_add(new, s1);
smartlist_add(new, e1);
- prune_services_on_reload(old, new);
+ set_rend_service_list(old);
+ set_rend_rend_service_staging_list(new);
+ rend_service_prune_list_impl_();
tt_int_op(smartlist_len(old), OP_EQ, 0);
tt_int_op(smartlist_len(new), OP_EQ, 2);
tt_assert(smartlist_get(new, 0) == s1);
@@ -871,7 +983,9 @@ test_prune_services_on_reload(void *arg)
/* Setup our list. */
smartlist_add(old, s1);
smartlist_add(new, s2);
- prune_services_on_reload(old, new);
+ set_rend_service_list(old);
+ set_rend_rend_service_staging_list(new);
+ rend_service_prune_list_impl_();
tt_int_op(smartlist_len(old), OP_EQ, 1);
/* Intro nodes have been moved to the s2 in theory so it must be empty. */
tt_int_op(smartlist_len(s1->intro_nodes), OP_EQ, 0);
@@ -892,7 +1006,9 @@ test_prune_services_on_reload(void *arg)
/* Test two ephemeral services. */
smartlist_add(old, e1);
smartlist_add(old, e2);
- prune_services_on_reload(old, new);
+ set_rend_service_list(old);
+ set_rend_rend_service_staging_list(new);
+ rend_service_prune_list_impl_();
/* Check if they've all been transfered. */
tt_int_op(smartlist_len(old), OP_EQ, 0);
tt_int_op(smartlist_len(new), OP_EQ, 2);
@@ -910,6 +1026,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 1943d0ffac..91b13be862 100644
--- a/src/test/test_hs_cache.c
+++ b/src/test/test_hs_cache.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Tor Project, Inc. */
+/* Copyright (c) 2016-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -7,104 +7,21 @@
*/
#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"
#include "test.h"
-/* Build an intro point using a blinded key and an address. */
-static hs_desc_intro_point_t *
-helper_build_intro_point(const ed25519_keypair_t *blinded_kp,
- const char *addr)
-{
- 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_link_specifier_t *ls = tor_malloc_zero(sizeof(*ls));
- ls->u.ap.port = 9001;
- int family = tor_addr_parse(&ls->u.ap.addr, addr);
- switch (family) {
- case AF_INET:
- ls->type = LS_IPV4;
- break;
- case AF_INET6:
- ls->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);
- }
-
- ret = ed25519_keypair_generate(&auth_kp, 0);
- tt_int_op(ret, ==, 0);
- ip->auth_key_cert = tor_cert_create(blinded_kp, CERT_TYPE_AUTH_HS_IP_KEY,
- &auth_kp.pubkey, time(NULL),
- HS_DESC_CERT_LIFETIME,
- CERT_FLAG_INCLUDE_SIGNING_KEY);
- tt_assert(ip->auth_key_cert);
-
- ret = curve25519_keypair_generate(&ip->enc_key.curve25519, 0);
- tt_int_op(ret, ==, 0);
- ip->enc_key_type = HS_DESC_KEY_TYPE_CURVE25519;
- intro_point = ip;
- done:
- return intro_point;
-}
-
-/* Return a valid hs_descriptor_t object. */
-static hs_descriptor_t *
-helper_build_hs_desc(uint64_t revision_counter, uint32_t lifetime,
- ed25519_public_key_t *signing_pubkey)
-{
- int ret;
- ed25519_keypair_t blinded_kp;
- hs_descriptor_t *descp = NULL, *desc = tor_malloc_zero(sizeof(*desc));
-
- desc->plaintext_data.version = HS_DESC_SUPPORTED_FORMAT_VERSION_MAX;
-
- /* Copy only the public key into the descriptor. */
- memcpy(&desc->plaintext_data.signing_pubkey, signing_pubkey,
- sizeof(ed25519_public_key_t));
-
- ret = ed25519_keypair_generate(&blinded_kp, 0);
- tt_int_op(ret, ==, 0);
- /* Copy only the public key into the descriptor. */
- memcpy(&desc->plaintext_data.blinded_pubkey, &blinded_kp.pubkey,
- sizeof(ed25519_public_key_t));
-
- desc->plaintext_data.signing_key_cert =
- tor_cert_create(&blinded_kp, CERT_TYPE_SIGNING_HS_DESC, signing_pubkey,
- time(NULL), 3600, CERT_FLAG_INCLUDE_SIGNING_KEY);
- tt_assert(desc->plaintext_data.signing_key_cert);
- desc->plaintext_data.revision_counter = revision_counter;
- desc->plaintext_data.lifetime_sec = lifetime;
-
- /* Setup encrypted data section. */
- desc->encrypted_data.create2_ntor = 1;
- desc->encrypted_data.auth_types = smartlist_new();
- smartlist_add(desc->encrypted_data.auth_types, tor_strdup("ed25519"));
- desc->encrypted_data.intro_points = smartlist_new();
- /* Add an intro point. */
- smartlist_add(desc->encrypted_data.intro_points,
- helper_build_intro_point(&blinded_kp, "1.2.3.4"));
-
- descp = desc;
- done:
- return descp;
-}
-
/* Static variable used to encoded the HSDir query. */
static char query_b64[256];
@@ -140,8 +57,8 @@ 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);
- desc1 = helper_build_hs_desc(42, 3 * 60 * 60, &signing_kp1.pubkey);
+ 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);
tt_int_op(ret, OP_EQ, 0);
@@ -164,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);
}
@@ -173,10 +90,12 @@ 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 = helper_build_hs_desc(1, 0, &signing_kp_zero.pubkey);
+ desc_zero_lifetime = hs_helper_build_hs_desc_with_ip(&signing_kp_zero);
tt_assert(desc_zero_lifetime);
+ desc_zero_lifetime->plaintext_data.revision_counter = 1;
+ desc_zero_lifetime->plaintext_data.lifetime_sec = 0;
char *desc_zero_lifetime_str;
ret = hs_desc_encode_descriptor(desc_zero_lifetime, &signing_kp_zero,
&desc_zero_lifetime_str);
@@ -199,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);
}
@@ -261,8 +180,8 @@ test_clean_as_dir(void *arg)
/* Generate a valid descriptor with values. */
ret = ed25519_keypair_generate(&signing_kp1, 0);
- tt_int_op(ret, ==, 0);
- desc1 = helper_build_hs_desc(42, 3 * 60 * 60, &signing_kp1.pubkey);
+ 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);
tt_int_op(ret, OP_EQ, 0);
@@ -271,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);
@@ -315,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);
}
@@ -333,7 +252,7 @@ helper_fetch_desc_from_hsdir(const ed25519_public_key_t *blinded_key)
size_t body_used = 0;
fetch_from_buf_http(TO_CONN(conn)->outbuf, &headers, MAX_HEADERS_SIZE,
- &received_desc, &body_used, 10000, 0);
+ &received_desc, &body_used, HS_DESC_MAX_LEN, 0);
tor_free(headers);
}
@@ -374,8 +293,8 @@ 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);
- published_desc = helper_build_hs_desc(42, 3 * 60 * 60, &signing_kp.pubkey);
+ 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);
@@ -385,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 */
@@ -426,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;
@@ -437,9 +357,8 @@ 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);
- published_desc = helper_build_hs_desc(1312, 3 * 60 * 60,
- &signing_kp.pubkey);
+ 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);
@@ -449,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. */
@@ -463,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, ==, 1312);
+ tt_u64_op(received_desc->plaintext_data.revision_counter, OP_EQ, 42);
hs_descriptor_free(received_desc);
received_desc = NULL;
@@ -486,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
@@ -497,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:
@@ -512,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,
@@ -522,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..b435a93e33
--- /dev/null
+++ b/src/test/test_hs_common.c
@@ -0,0 +1,1822 @@
+/* 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;
+
+ 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_t *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:
+ 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 *time, time_t *t)
+{
+ tt_assert(time);
+ tt_assert(t);
+
+ int ret = parse_rfc1123_time(time, 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(&current_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, 6);
+
+ 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. */
+ &current_srv, NULL, /* Service current and previous SRV */
+ &current_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 */
+ &current_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. */
+ &current_srv, &previous_srv, /* Service current and previous SRV */
+ &current_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. */
+ &current_srv, &previous_srv, /* Service current and previous SRV */
+ &current_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. */
+ &current_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. */
+ &current_srv, &previous_srv, /* Service current and previous SRV */
+ &current_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, 6);
+
+ 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, 6);
+
+ /* 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 97fe1910b8..9ec183db06 100644
--- a/src/test/test_hs_descriptor.c
+++ b/src/test/test_hs_descriptor.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Tor Project, Inc. */
+/* Copyright (c) 2016-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -15,220 +15,17 @@
#include "test.h"
#include "torcert.h"
-static hs_desc_intro_point_t *
-helper_build_intro_point(const ed25519_keypair_t *blinded_kp, time_t now,
- const char *addr, int legacy)
-{
- 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_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;
- break;
- case AF_INET6:
- ls->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);
- }
-
- ret = ed25519_keypair_generate(&auth_kp, 0);
- tt_int_op(ret, ==, 0);
- ip->auth_key_cert = tor_cert_create(blinded_kp, CERT_TYPE_AUTH_HS_IP_KEY,
- &auth_kp.pubkey, now,
- HS_DESC_CERT_LIFETIME,
- CERT_FLAG_INCLUDE_SIGNING_KEY);
- tt_assert(ip->auth_key_cert);
-
- if (legacy) {
- ip->enc_key.legacy = crypto_pk_new();
- ip->enc_key_type = HS_DESC_KEY_TYPE_LEGACY;
- tt_assert(ip->enc_key.legacy);
- ret = crypto_pk_generate_key(ip->enc_key.legacy);
- tt_int_op(ret, ==, 0);
- } else {
- ret = curve25519_keypair_generate(&ip->enc_key.curve25519, 0);
- tt_int_op(ret, ==, 0);
- ip->enc_key_type = HS_DESC_KEY_TYPE_CURVE25519;
- }
-
- intro_point = ip;
- done:
- return intro_point;
-}
+#include "hs_test_helpers.h"
+#include "test_helpers.h"
+#include "log_test_helpers.h"
-/* Return a valid hs_descriptor_t object. If no_ip is set, no introduction
- * points are added. */
-static hs_descriptor_t *
-helper_build_hs_desc(unsigned int no_ip, ed25519_public_key_t *signing_pubkey)
-{
- int ret;
- time_t now = time(NULL);
- ed25519_keypair_t blinded_kp;
- hs_descriptor_t *descp = NULL, *desc = tor_malloc_zero(sizeof(*desc));
-
- desc->plaintext_data.version = HS_DESC_SUPPORTED_FORMAT_VERSION_MAX;
-
- /* Copy only the public key into the descriptor. */
- memcpy(&desc->plaintext_data.signing_pubkey, signing_pubkey,
- sizeof(ed25519_public_key_t));
-
- ret = ed25519_keypair_generate(&blinded_kp, 0);
- tt_int_op(ret, ==, 0);
- /* Copy only the public key into the descriptor. */
- memcpy(&desc->plaintext_data.blinded_pubkey, &blinded_kp.pubkey,
- sizeof(ed25519_public_key_t));
-
- desc->plaintext_data.signing_key_cert =
- tor_cert_create(&blinded_kp, CERT_TYPE_SIGNING_HS_DESC, signing_pubkey,
- now, 3600, CERT_FLAG_INCLUDE_SIGNING_KEY);
- tt_assert(desc->plaintext_data.signing_key_cert);
- desc->plaintext_data.revision_counter = 42;
- desc->plaintext_data.lifetime_sec = 3 * 60 * 60;
-
- /* Setup encrypted data section. */
- desc->encrypted_data.create2_ntor = 1;
- desc->encrypted_data.auth_types = smartlist_new();
- desc->encrypted_data.single_onion_service = 1;
- smartlist_add(desc->encrypted_data.auth_types, tor_strdup("ed25519"));
- desc->encrypted_data.intro_points = smartlist_new();
- if (!no_ip) {
- /* Add four intro points. */
- smartlist_add(desc->encrypted_data.intro_points,
- helper_build_intro_point(&blinded_kp, now, "1.2.3.4", 0));
- smartlist_add(desc->encrypted_data.intro_points,
- helper_build_intro_point(&blinded_kp, now, "[2600::1]", 0));
- smartlist_add(desc->encrypted_data.intro_points,
- helper_build_intro_point(&blinded_kp, now, "3.2.1.4", 1));
- smartlist_add(desc->encrypted_data.intro_points,
- helper_build_intro_point(&blinded_kp, now, "", 1));
- }
-
- descp = desc;
- done:
- return descp;
-}
-
-static void
-helper_compare_hs_desc(const hs_descriptor_t *desc1,
- const hs_descriptor_t *desc2)
-{
- char *addr1 = NULL, *addr2 = NULL;
- /* Plaintext data section. */
- tt_int_op(desc1->plaintext_data.version, OP_EQ,
- desc2->plaintext_data.version);
- tt_uint_op(desc1->plaintext_data.lifetime_sec, OP_EQ,
- desc2->plaintext_data.lifetime_sec);
- tt_assert(tor_cert_eq(desc1->plaintext_data.signing_key_cert,
- desc2->plaintext_data.signing_key_cert));
- tt_mem_op(desc1->plaintext_data.signing_pubkey.pubkey, OP_EQ,
- desc2->plaintext_data.signing_pubkey.pubkey,
- ED25519_PUBKEY_LEN);
- tt_mem_op(desc1->plaintext_data.blinded_pubkey.pubkey, OP_EQ,
- desc2->plaintext_data.blinded_pubkey.pubkey,
- ED25519_PUBKEY_LEN);
- tt_u64_op(desc1->plaintext_data.revision_counter, ==,
- desc2->plaintext_data.revision_counter);
-
- /* NOTE: We can't compare the encrypted blob because when encoding the
- * descriptor, the object is immutable thus we don't update it with the
- * encrypted blob. As contrast to the decoding process where we populate a
- * descriptor object. */
-
- /* Encrypted data section. */
- tt_uint_op(desc1->encrypted_data.create2_ntor, ==,
- desc2->encrypted_data.create2_ntor);
-
- /* Authentication type. */
- tt_int_op(!!desc1->encrypted_data.auth_types, ==,
- !!desc2->encrypted_data.auth_types);
- if (desc1->encrypted_data.auth_types && desc2->encrypted_data.auth_types) {
- tt_int_op(smartlist_len(desc1->encrypted_data.auth_types), ==,
- smartlist_len(desc2->encrypted_data.auth_types));
- for (int i = 0; i < smartlist_len(desc1->encrypted_data.auth_types); i++) {
- tt_str_op(smartlist_get(desc1->encrypted_data.auth_types, i), OP_EQ,
- smartlist_get(desc2->encrypted_data.auth_types, i));
- }
- }
-
- /* Introduction points. */
- {
- tt_assert(desc1->encrypted_data.intro_points);
- tt_assert(desc2->encrypted_data.intro_points);
- tt_int_op(smartlist_len(desc1->encrypted_data.intro_points), ==,
- smartlist_len(desc2->encrypted_data.intro_points));
- for (int i=0; i < smartlist_len(desc1->encrypted_data.intro_points); i++) {
- hs_desc_intro_point_t *ip1 = smartlist_get(desc1->encrypted_data
- .intro_points, i),
- *ip2 = smartlist_get(desc2->encrypted_data
- .intro_points, i);
- tt_assert(tor_cert_eq(ip1->auth_key_cert, ip2->auth_key_cert));
- tt_int_op(ip1->enc_key_type, OP_EQ, ip2->enc_key_type);
- tt_assert(ip1->enc_key_type == HS_DESC_KEY_TYPE_LEGACY ||
- ip1->enc_key_type == HS_DESC_KEY_TYPE_CURVE25519);
- switch (ip1->enc_key_type) {
- case HS_DESC_KEY_TYPE_LEGACY:
- tt_int_op(crypto_pk_cmp_keys(ip1->enc_key.legacy, ip2->enc_key.legacy),
- OP_EQ, 0);
- break;
- case HS_DESC_KEY_TYPE_CURVE25519:
- tt_mem_op(ip1->enc_key.curve25519.pubkey.public_key, OP_EQ,
- ip2->enc_key.curve25519.pubkey.public_key,
- CURVE25519_PUBKEY_LEN);
- break;
- }
-
- tt_int_op(smartlist_len(ip1->link_specifiers), ==,
- smartlist_len(ip2->link_specifiers));
- for (int j = 0; j < smartlist_len(ip1->link_specifiers); j++) {
- hs_desc_link_specifier_t *ls1 = smartlist_get(ip1->link_specifiers, j),
- *ls2 = smartlist_get(ip2->link_specifiers, j);
- tt_int_op(ls1->type, ==, ls2->type);
- switch (ls1->type) {
- case LS_IPV4:
- case LS_IPV6:
- {
- addr1 = tor_addr_to_str_dup(&ls1->u.ap.addr);
- addr2 = tor_addr_to_str_dup(&ls2->u.ap.addr);
- tt_str_op(addr1, OP_EQ, addr2);
- tor_free(addr1);
- tor_free(addr2);
- tt_int_op(ls1->u.ap.port, ==, ls2->u.ap.port);
- }
- break;
- case LS_LEGACY_ID:
- tt_mem_op(ls1->u.legacy_id, OP_EQ, ls2->u.legacy_id,
- sizeof(ls1->u.legacy_id));
- break;
- default:
- /* Unknown type, caught it and print its value. */
- tt_int_op(ls1->type, OP_EQ, -1);
- }
- }
- }
- }
-
- done:
- tor_free(addr1);
- tor_free(addr2);
-}
+#ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
+DISABLE_GCC_WARNING(overlength-strings)
+/* We allow huge string constants in the unit tests, but not in the code
+ * at large. */
+#endif
+#include "test_hs_descriptor.inc"
+ENABLE_GCC_WARNING(overlength-strings)
/* Test certificate encoding put in a descriptor. */
static void
@@ -257,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. */
{
@@ -266,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. */
@@ -275,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:
@@ -311,13 +109,13 @@ test_descriptor_padding(void *arg)
/* Example: if l = 129, the ceiled division gives 2 and then multiplied by 128
* to give 256. With l = 127, ceiled division gives 1 then times 128. */
#define PADDING_EXPECTED_LEN(l) \
- CEIL_DIV(l, HS_DESC_PLAINTEXT_PADDING_MULTIPLE) * \
- HS_DESC_PLAINTEXT_PADDING_MULTIPLE
+ CEIL_DIV(l, HS_DESC_SUPERENC_PLAINTEXT_PAD_MULTIPLE) * \
+ HS_DESC_SUPERENC_PLAINTEXT_PAD_MULTIPLE
(void) arg;
{ /* test #1: no padding */
- plaintext_len = HS_DESC_PLAINTEXT_PADDING_MULTIPLE;
+ plaintext_len = HS_DESC_SUPERENC_PLAINTEXT_PAD_MULTIPLE;
plaintext = tor_malloc(plaintext_len);
padded_len = build_plaintext_padding(plaintext, plaintext_len,
&padded_plaintext);
@@ -333,7 +131,7 @@ test_descriptor_padding(void *arg)
}
{ /* test #2: one byte padding? */
- plaintext_len = HS_DESC_PLAINTEXT_PADDING_MULTIPLE - 1;
+ plaintext_len = HS_DESC_SUPERENC_PLAINTEXT_PAD_MULTIPLE - 1;
plaintext = tor_malloc(plaintext_len);
padded_plaintext = NULL;
padded_len = build_plaintext_padding(plaintext, plaintext_len,
@@ -350,7 +148,7 @@ test_descriptor_padding(void *arg)
}
{ /* test #3: Lots more bytes of padding? */
- plaintext_len = HS_DESC_PLAINTEXT_PADDING_MULTIPLE + 1;
+ plaintext_len = HS_DESC_SUPERENC_PLAINTEXT_PAD_MULTIPLE + 1;
plaintext = tor_malloc(plaintext_len);
padded_plaintext = NULL;
padded_len = build_plaintext_padding(plaintext, plaintext_len,
@@ -391,22 +189,22 @@ test_link_specifier(void *arg)
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);
tor_free(b64);
@@ -420,24 +218,25 @@ test_link_specifier(void *arg)
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);
tor_free(b64);
@@ -456,12 +255,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);
@@ -487,10 +286,10 @@ test_encode_descriptor(void *arg)
(void) arg;
ret = ed25519_keypair_generate(&signing_kp, 0);
- tt_int_op(ret, ==, 0);
- desc = helper_build_hs_desc(0, &signing_kp.pubkey);
+ 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:
@@ -507,41 +306,47 @@ 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);
- desc = helper_build_hs_desc(0, &signing_kp.pubkey);
+ 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);
- helper_compare_hs_desc(desc, decoded);
+ hs_helper_desc_equal(desc, decoded);
/* Decode a descriptor with _no_ introduction points. */
{
ed25519_keypair_t signing_kp_no_ip;
ret = ed25519_keypair_generate(&signing_kp_no_ip, 0);
- tt_int_op(ret, ==, 0);
- desc_no_ip = helper_build_hs_desc(1, &signing_kp_no_ip.pubkey);
+ 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);
}
@@ -587,24 +392,17 @@ test_encrypted_data_len(void *arg)
/* No length, error. */
ret = encrypted_data_length_is_valid(0);
tt_int_op(ret, OP_EQ, 0);
- /* This value is missing data. */
- value = HS_DESC_ENCRYPTED_SALT_LEN + DIGEST256_LEN;
- ret = encrypted_data_length_is_valid(value);
- tt_int_op(ret, OP_EQ, 0);
/* Valid value. */
- value = HS_DESC_PADDED_PLAINTEXT_MAX_LEN + HS_DESC_ENCRYPTED_SALT_LEN +
- DIGEST256_LEN;
+ value = HS_DESC_ENCRYPTED_SALT_LEN + DIGEST256_LEN + 1;
ret = encrypted_data_length_is_valid(value);
tt_int_op(ret, OP_EQ, 1);
- /* XXX: Test maximum possible size. */
-
done:
;
}
static void
-test_decode_intro_point(void *arg)
+test_decode_invalid_intro_point(void *arg)
{
int ret;
char *encoded_ip = NULL;
@@ -615,9 +413,6 @@ test_decode_intro_point(void *arg)
(void) arg;
- /* The following certificate expires in 2036. After that, one of the test
- * will fail because of the expiry time. */
-
/* Seperate pieces of a valid encoded introduction point. */
const char *intro_point =
"introduction-point AQIUMDI5OUYyNjhGQ0E5RDU1Q0QxNTc=";
@@ -630,72 +425,25 @@ test_decode_intro_point(void *arg)
"-----END ED25519 CERT-----";
const char *enc_key =
"enc-key ntor bpZKLsuhxP6woDQ3yVyjm5gUKSk7RjfAijT2qrzbQk0=";
- const char *enc_key_legacy =
- "enc-key legacy\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAO4bATcW8kW4h6RQQAKEgg+aXCpF4JwbcO6vGZtzXTDB+HdPVQzwqkbh\n"
- "XzFM6VGArhYw4m31wcP1Z7IwULir7UMnAFd7Zi62aYfU6l+Y1yAoZ1wzu1XBaAMK\n"
- "ejpwQinW9nzJn7c2f69fVke3pkhxpNdUZ+vplSA/l9iY+y+v+415AgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----";
const char *enc_key_cert =
- "enc-key-certification\n"
+ "enc-key-cert\n"
"-----BEGIN ED25519 CERT-----\n"
"AQsACOhZAUpNvCZ1aJaaR49lS6MCdsVkhVGVrRqoj0Y2T4SzroAtAQAgBABFOcGg\n"
"lbTt1DF5nKTE/gU3Fr8ZtlCIOhu1A+F5LM7fqCUupfesg0KTHwyIZOYQbJuM5/he\n"
"/jDNyLy9woPJdjkxywaY2RPUxGjLYtMQV0E8PUxWyICV+7y52fTCYaKpYQw=\n"
"-----END ED25519 CERT-----";
- const char *enc_key_cert_legacy =
- "enc-key-certification\n"
- "-----BEGIN CROSSCERT-----\n"
- "Sk28JnVolppHj2VLowJ2xWSFUZWtGqiPRjZPhLOugC0ACOhZgFPA5egeRDUXMM1U\n"
- "Fn3c7Je0gJS6mVma5FzwlgwggeriF13UZcaT71vEAN/ZJXbxOfQVGMZ0rXuFpjUq\n"
- "C8CvqmZIwEUaPE1nDFtmnTcucvNS1YQl9nsjH3ejbxc+4yqps/cXh46FmXsm5yz7\n"
- "NZjBM9U1fbJhlNtOvrkf70K8bLk6\n"
- "-----END CROSSCERT-----";
-
- (void) enc_key_legacy;
- (void) enc_key_cert_legacy;
-
- /* Start by testing the "decode all intro points" function. */
- {
- char *line;
- ret = ed25519_keypair_generate(&signing_kp, 0);
- tt_int_op(ret, ==, 0);
- desc = helper_build_hs_desc(0, &signing_kp.pubkey);
- tt_assert(desc);
- /* Only try to decode an incomplete introduction point section. */
- tor_asprintf(&line, "\n%s", intro_point);
- ret = decode_intro_points(desc, &desc->encrypted_data, line);
- tor_free(line);
- tt_int_op(ret, ==, -1);
-
- /* Decode one complete intro point. */
- smartlist_t *lines = smartlist_new();
- smartlist_add(lines, (char *) intro_point);
- smartlist_add(lines, (char *) auth_key);
- smartlist_add(lines, (char *) enc_key);
- smartlist_add(lines, (char *) enc_key_cert);
- encoded_ip = smartlist_join_strings(lines, "\n", 0, &len_out);
- tt_assert(encoded_ip);
- tor_asprintf(&line, "\n%s", encoded_ip);
- tor_free(encoded_ip);
- ret = decode_intro_points(desc, &desc->encrypted_data, line);
- tor_free(line);
- smartlist_free(lines);
- tt_int_op(ret, ==, 0);
- }
/* Try to decode a junk string. */
{
hs_descriptor_free(desc);
desc = NULL;
ret = ed25519_keypair_generate(&signing_kp, 0);
- tt_int_op(ret, ==, 0);
- desc = helper_build_hs_desc(0, &signing_kp.pubkey);
+ 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;
}
@@ -710,10 +458,10 @@ test_decode_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;
}
@@ -737,7 +485,7 @@ test_decode_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);
}
@@ -755,7 +503,7 @@ test_decode_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);
}
@@ -772,7 +520,7 @@ test_decode_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);
}
@@ -789,7 +537,7 @@ test_decode_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);
}
@@ -797,7 +545,7 @@ test_decode_intro_point(void *arg)
/* Invalid enc-key invalid legacy. */
{
smartlist_t *lines = smartlist_new();
- const char *bad_line = "enc-key legacy blah===";
+ const char *bad_line = "legacy-key blah===";
/* Build intro point text. */
smartlist_add(lines, (char *) intro_point);
smartlist_add(lines, (char *) auth_key);
@@ -806,30 +554,36 @@ test_decode_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);
- tor_free(encoded_ip);
- smartlist_free(lines);
- }
-
- /* Valid object. */
- {
- smartlist_t *lines = smartlist_new();
- /* Build intro point text. */
- smartlist_add(lines, (char *) intro_point);
- smartlist_add(lines, (char *) auth_key);
- smartlist_add(lines, (char *) enc_key);
- smartlist_add(lines, (char *) enc_key_cert);
- 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. */
+static void
+test_decode_bad_signature(void *arg)
+{
+ hs_desc_plaintext_data_t desc_plaintext;
+ int ret;
+
+ (void) arg;
+
+ /* Update approx time to dodge cert expiration */
+ update_approx_time(1502661599);
+
+ setup_full_capture_of_logs(LOG_WARN);
+ ret = hs_desc_decode_plaintext(HS_DESC_BAD_SIG, &desc_plaintext);
+ tt_int_op(ret, OP_EQ, -1);
+ expect_log_msg_containing("Malformed signature line. Rejecting.");
+ teardown_capture_of_logs();
+
+ done:
+ desc_plaintext_data_free_contents(&desc_plaintext);
}
static void
@@ -878,7 +632,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';
@@ -938,7 +692,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,
@@ -989,22 +743,119 @@ 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);
tor_free(data);
}
+/* bad desc auth type */
+static const char bad_superencrypted_text1[] = "desc-auth-type scoobysnack\n"
+ "desc-auth-ephemeral-key A/O8DVtnUheb3r1JqoB8uJB7wxXL1XJX3eny4yB+eFA=\n"
+ "auth-client oiNrQB8WwKo S5D02W7vKgiWIMygrBl8RQ FB//SfOBmLEx1kViEWWL1g\n"
+ "encrypted\n"
+ "-----BEGIN MESSAGE-----\n"
+ "YmVpbmcgb24gbW91bnRhaW5zLCB0aGlua2luZyBhYm91dCBjb21wdXRlcnMsIGlzIG5vdC"
+ "BiYWQgYXQgYWxs\n"
+ "-----END MESSAGE-----\n";
+
+/* bad ephemeral key */
+static const char bad_superencrypted_text2[] = "desc-auth-type x25519\n"
+ "desc-auth-ephemeral-key differentalphabet\n"
+ "auth-client oiNrQB8WwKo S5D02W7vKgiWIMygrBl8RQ FB//SfOBmLEx1kViEWWL1g\n"
+ "encrypted\n"
+ "-----BEGIN MESSAGE-----\n"
+ "YmVpbmcgb24gbW91bnRhaW5zLCB0aGlua2luZyBhYm91dCBjb21wdXRlcnMsIGlzIG5vdC"
+ "BiYWQgYXQgYWxs\n"
+ "-----END MESSAGE-----\n";
+
+/* bad encrypted msg */
+static const char bad_superencrypted_text3[] = "desc-auth-type x25519\n"
+ "desc-auth-ephemeral-key A/O8DVtnUheb3r1JqoB8uJB7wxXL1XJX3eny4yB+eFA=\n"
+ "auth-client oiNrQB8WwKo S5D02W7vKgiWIMygrBl8RQ FB//SfOBmLEx1kViEWWL1g\n"
+ "encrypted\n"
+ "-----BEGIN MESSAGE-----\n"
+ "SO SMALL NOT GOOD\n"
+ "-----END MESSAGE-----\n";
+
+static const char correct_superencrypted_text[] = "desc-auth-type x25519\n"
+ "desc-auth-ephemeral-key A/O8DVtnUheb3r1JqoB8uJB7wxXL1XJX3eny4yB+eFA=\n"
+ "auth-client oiNrQB8WwKo S5D02W7vKgiWIMygrBl8RQ FB//SfOBmLEx1kViEWWL1g\n"
+ "auth-client Od09Qu636Qo /PKLzqewAdS/+0+vZC+MvQ dpw4NFo13zDnuPz45rxrOg\n"
+ "auth-client JRr840iGYN0 8s8cxYqF7Lx23+NducC4Qg zAafl4wPLURkuEjJreZq1g\n"
+ "encrypted\n"
+ "-----BEGIN MESSAGE-----\n"
+ "YmVpbmcgb24gbW91bnRhaW5zLCB0aGlua2luZyBhYm91dCBjb21wdXRlcnMsIGlzIG5vdC"
+ "BiYWQgYXQgYWxs\n"
+ "-----END MESSAGE-----\n";
+
+static const char correct_encrypted_plaintext[] = "being on mountains, "
+ "thinking about computers, is not bad at all";
+
+static void
+test_parse_hs_desc_superencrypted(void *arg)
+{
+ (void) arg;
+ size_t retval;
+ uint8_t *encrypted_out = NULL;
+
+ {
+ setup_full_capture_of_logs(LOG_WARN);
+ retval = decode_superencrypted(bad_superencrypted_text1,
+ strlen(bad_superencrypted_text1),
+ &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();
+ }
+
+ {
+ setup_full_capture_of_logs(LOG_WARN);
+ retval = decode_superencrypted(bad_superencrypted_text2,
+ strlen(bad_superencrypted_text2),
+ &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();
+ }
+
+ {
+ setup_full_capture_of_logs(LOG_WARN);
+ retval = decode_superencrypted(bad_superencrypted_text3,
+ strlen(bad_superencrypted_text3),
+ &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();
+ }
+
+ /* Now finally the good one */
+ retval = decode_superencrypted(correct_superencrypted_text,
+ strlen(correct_superencrypted_text),
+ &encrypted_out);
+
+ tt_u64_op(retval, OP_EQ, strlen(correct_encrypted_plaintext));
+ tt_mem_op(encrypted_out, OP_EQ, correct_encrypted_plaintext,
+ strlen(correct_encrypted_plaintext));
+
+ done:
+ tor_free(encrypted_out);
+}
+
struct testcase_t hs_descriptor[] = {
/* Encoding tests. */
{ "cert_encoding", test_cert_encoding, TT_FORK,
@@ -1021,10 +872,12 @@ struct testcase_t hs_descriptor[] = {
NULL, NULL },
{ "encrypted_data_len", test_encrypted_data_len, TT_FORK,
NULL, NULL },
- { "decode_intro_point", test_decode_intro_point, TT_FORK,
+ { "decode_invalid_intro_point", test_decode_invalid_intro_point, TT_FORK,
NULL, NULL },
{ "decode_plaintext", test_decode_plaintext, TT_FORK,
NULL, NULL },
+ { "decode_bad_signature", test_decode_bad_signature, TT_FORK,
+ NULL, NULL },
/* Misc. */
{ "version", test_supported_version, TT_FORK,
@@ -1034,6 +887,9 @@ struct testcase_t hs_descriptor[] = {
{ "desc_signature", test_desc_signature, TT_FORK,
NULL, NULL },
+ { "parse_hs_desc_superencrypted", test_parse_hs_desc_superencrypted,
+ TT_FORK, NULL, NULL },
+
END_OF_TESTCASES
};
diff --git a/src/test/test_hs_descriptor.inc b/src/test/test_hs_descriptor.inc
new file mode 100644
index 0000000000..70a2c7c2f7
--- /dev/null
+++ b/src/test/test_hs_descriptor.inc
@@ -0,0 +1,224 @@
+static const char* HS_DESC_BAD_SIG =
+"hs-descriptor 3\n"
+"descriptor-lifetime 180\n"
+"descriptor-signing-key-cert\n"
+"-----BEGIN ED25519 CERT-----\n"
+"AQgABl5+AQoPXRnCGEOxIup3AcjQXb8npNiUFm2Qv7A6JKk/K+EuAQAgBAD18iUD\n"
+"nbkUblnUvTHzipq4bcr6aPyFVB42Ptobg4xr8s3VjHiJtjs9MDEdr6nXS7UlyhEl\n"
+"78vsuFEvLp7cvAgGxYY1xGXdn5RdHMCdi8W9yZLKMQX9OuJckmp1C6q+cA4=\n"
+"-----END ED25519 CERT-----\n"
+"revision-counter 42\n"
+"superencrypted\n"
+"-----BEGIN MESSAGE-----\n"
+"BxzghAOjM4De6Z6eGTvBrTP2SJDdQOYV/u9qtvlFsa2FRQWk20Adv3zJ/AI10CQO\n"
+"mUP4DNXM8FWQYGTvmD7wGz2/cXGjKwBXg1qO7zF5eP/D/My1sXsIfCcb41mkheNt\n"
+"xn1I5eKXcnghtd4lw7OkPVjSb/Z+VARUMmf+0qSNgmHLgEVnAoGJsn8W8B4qtIay\n"
+"4h4PuV0jPPlqJx6jMFOOEW72uqnfmqeNvClENXXW60xhnaxsf0up62fuW8ktu6Wf\n"
+"lnX/lvTstBFZZQ8/XI1+G+BPf8TZf7mxu0WYVg1s/KWYasYMSw46as59nkqdq2Ii\n"
+"qJnqHX/R20mWBhgpLse6wO0aNpky/rozEnikaPqyO1DShf6a6jXY8ADBg7spnK2/\n"
+"h7sf1+F1xfi2dy2WGxc1EUMP1kTVUmbft7kOo2nA7+3YZwQuSJHaN/66HrzU2x5z\n"
+"ayRUJ8+qDtfpEf17xthc/Uh253blFK96IoJJiqBfI6xt3IqOdHJq0OOC9zBbF6Rj\n"
+"vKMsaxmc/nc6uOB2WePYSgkZ0qs/dRKBJs6+Ahn1KdGkadyd8mDKL86Oe8lncHdB\n"
+"m/6sQjhKqFgngkCDOIlEJyWizqfN84AGqD5Zyxq0rbsN+9KLsHFfEbCRjgqjO5nS\n"
+"FYSFtuKgCZl2gaYEslL1pIEYE6BD2Whjn/HWTRyWiULJr6SuavgcbxeNEQDuVCC+\n"
+"fm0X7Z+qERaMAMR0vTMJK/NzT4GifrDpgmgbxc+34CtNBF5TriM8aXTNZZlsW00k\n"
+"d0XRxFbbbtiT5VOaEHbny7R3MdTVutEc9E/BhLBvjSSrGX7vrryh6Oj++nthIIzm\n"
+"F4M7I11S0TyA+UE06qF1C8rKmhcqU9MWy1SiccJ9KOWhJ5xwlsXBIID7wVygUhVl\n"
+"ovzfKkDDPfRoBch6NdVkxNJx3gb63CUmC2TzfwOMh973nntMVzqqw9A7jYkro9ln\n"
+"217kHUwMk3e83UgFL4nn7NCf3Kj0zhJ4jSfAsuQpV6e7dhzrlNya0lqrUsY2zFXP\n"
+"xv8wUtg6Vo1KewgVQas4oElkgFjDN8RJ7uBAwfuE/b9NnYJoQd76G8DHei/1PHbu\n"
+"tbtwN9I5RHaTvEOfetsJFnIAkCG6O4CQpzwHu1DdvEP4s6/el10b/4awBJ4VwOVZ\n"
+"YHSe4X0DStTV4Cu6aLh5OvrOmGbieRj6HdGQ6syYCaEBTuxbBUUpjIAfVlReAIph\n"
+"6aOrY6HNcCmeVmL5qm4dKr2XXOREsnUFuMqmfQuQd9pN3zlmS+RqCgSJuFrguFpd\n"
+"mjo6UxZvbjE7yJjtCih38HRe5BaigP5RDRkXmiXjqJ4koLJpyjQh19k3BYGcdxUC\n"
+"RCcYXydbGF7qHlnoaX9HnX7y6ZRsyKQpt91PMTGOUsB4fS8NhsqPpl2gdp4poLNs\n"
+"+hqjWZJ3uuLotXBcgM39Dtq9tqqu9vM12T80UAfWnVEHrBphmukh49EhEr2sx/la\n"
+"kAzRoTbLyTdlGVei8hI7/RtZIaIcOkzlhcFI5zmBlydyrv6/79vzt6WI/w9GVGpM\n"
+"OuSM0NS2CDJ7Iw412nz3CV1pEXB551ZBmbme6NHUe4EtEsDbgkP1Z201H4j51yVz\n"
+"wNoIksE5Bh5XRKuu4We5f9KZb+AEG9kxKJ5DbJk2YGJEQFTyfv0H68pl9urstPXD\n"
+"aMQF806COe2uhGm5gV/skvPVTeEvStE3K8DxZgcWNcTMVk8ZjrUHNfguVVToP8hT\n"
+"Fl4Iqo3r+JZEAGXnAbTpxUVC2Xxspf3jsT5xhUfB/NOexZxrXWnQZ+pscsbow0ba\n"
+"GATtakD3TF2WBqq5WscmOex+lrJcBCWVIzVWdwi5ngAtm1S7efkJlFUvmi4OuYnN\n"
+"RyZfxVIpoer8f2/xPXvxkOWFminDy5sFEvlh2/pnymfKOUV+CKih9ZApt+izlRJn\n"
+"+sMIOW6Jhf/WYyjeN6KQpwi6CDpclQJXA1SVoOVVL5A3lotLjs0x7ThIcBoxCZBq\n"
+"rFBhBu1gJgJ8guMySAHssIvhHHwXJsYEwzWCVAg/zIUXy4PLwIkgHApl+vGcldGv\n"
+"Br5HNCuqQ2pD9z2RvzNneB/LrYB214i+BP2piO5HbmeJBhby93blGXVfQewQT6aF\n"
+"dBlK8/jQM0rvb+LkmvQm2ypOttRpX2kyQXooJHYTTusaUr4jVmgngCvGtgqAQVqD\n"
+"HULXfHWvugZbAh6dXF7gKnnsyDOWwAgy4OJRi8i0jCaZ8aWSFRUjeGKT26dg/ayB\n"
+"U4QfMb8vL8tMdXVBfQLGcBgvrzQYrY69//pV6bX3SbLfUfWXV9eqUVWVPqVyPEwa\n"
+"Tz/aGVnGv/dY8h2cVnrgSXJGlOO+mCwSl+k9nk7VcEaKYuNlaOP3ZlKJvVj1LefM\n"
+"FODh4qTDBo5NkyfKu5fcZcOqDMBeGWXZzltE7CmvY7fOpDNMsuAoXYWI7q9gK82F\n"
+"w+nS0tVFCIWYa9DgGMv9GKTOk4Ia9elkbWypdRE/4oz4QxmHsArEsK4gDI+wmcp7\n"
+"/NsAZeuy96r2YDIUam4uASKOiAqrEfCv6B6cYctdYwZbAEXdo4fkGrCIjNRZmZGv\n"
+"kcZzHzIymnAmKRTkPt/LQ7Rx27Qd/Vt++B3zt2ORFuopqowOP0ocGZtkm0daK3Fc\n"
+"YDXMwIpf6Z8PwvvsG1bQHcSR+cUZi7vK7+hj/LGhMPafHM7HmFUbAxpJYr5CvR6y\n"
+"V1pZQYltT8xWayCeMHlLAAg10RgDkqCnY4dHnrY4GdwI2O7Wpxomni7qVHMjn+cN\n"
+"UTrd7EeVw+dxAIYosuqG7ua7ee3VGoOs+XMLrscAqHahfGbyYC+j+6Tow4qwWBdU\n"
+"/W3NJXnRWaHTXFHllpClnxggPRQx4yPtgTOmBBVl/O0T6i4Bv0ygsJeZAqC3VmAJ\n"
+"QodQTzGf2jwqsZf4uHKQa0EKGQvTGjFVgAFNpHmAuzyqh0b1pq5JeXiFERGsKC3j\n"
+"xcJilq1XeIx4SL38YNuCxi4pnyJyLnGGHpNjdjeFO5lvgCaKPegsPo4hpNpTvBJ1\n"
+"D7+o3E5CqxzjRt9kQmtwBbuH/SQX2T0x8aQ6vhwjj8ftDfw+FbjpMR9zfU0Lf8V7\n"
+"UjVGIl2yiVBGScBZu1nSD83PxjFy3XdFtBYoU5OrlXwBEYQs91jwK7UCiGtjI2Ao\n"
+"ZGkJaBd4AqP6voyJiGnC3LWFcmeMyzfExgiclQwfhFqqf762TX5JwG6xGqtdcNKS\n"
+"k54LlcI/RfvJw3ncSs9YsodZr6Jz5irpRTHX5WwCrX9mLukP96SXo29bIXEZAqEr\n"
+"ZxEcF0zlYE+km5bRfRCRcVVrScugCshSNLOdQp6fOAtHCl7rdQ/8Rz7oHuqieLVi\n"
+"UldRsAmpk9fIfRLphXj4j24jRP0VtL/LoJwakWTa0xO8K7eBAMVITI+HgFfN4wSO\n"
+"Yh1B+bGD5WKxFsWSgBMmW+YLF5ZtxVmmbg7wK2dIpJs4pjg2YO/MTO7SifJ9kjcb\n"
+"bCc74Tjs5mLLGGjGCIoXfda6WXbt2it40XhFk2zUAcPPsgjbctftkaWph7JSZpmZ\n"
+"fVcPqKdhmA1U0LA2XEOMTxGyCAeseH6pJXZm9LdBozc1CwyWP8XEDHHJf35vfPKY\n"
+"JDe2PanFepIOHaoRTgE7ZkGWKzOIKlS0Ucr1ezVfcxiFgQUNM+MYXXbUz51BVVq1\n"
+"Dulg4VvX104nt/ULijcfa/TsE+uklEnkyk1mhavH337NQg38XF4cAngNlUF4nSW/\n"
+"j0jizbAtaSx1f7q6xqPm3zPRlHrGQizHXLyl+SLzDUVPOXbPwcoeev97YeeyB6h5\n"
+"NBbIK9hmekNDmYIwI0bmlrg6IXhC5pyvRe8sQlV+9wBY2liF0M1mq5onW3a55afp\n"
+"+ynxXfQucb1HxZLXvRIGMBgWSQ7HfIPASqSE90Vu6qQCfkOW5PDqONr4BM65V4+g\n"
+"AYsVEgaosgHw9CF7yKgkvmZpToOtGpCHVcdUeeY2/rrQnAQeSy19gj/baJ+OKl6Q\n"
+"i1EGU8Yqo2r0d4XDFp/eKgC4sv57qp1PwkYQ/HKqoelJ09IAZL2sQWc05BGwt1A0\n"
+"11qDIEdkZBjzK3qUnY3QlOuoZtALZrnPg56SlF1RGDOPqbcF+3opqsvzBoiikh4V\n"
+"WV5OUYjRDMUDLQqf/OkuktdYf5N3RcbYP0XsAvY0ZWG3Gp068b3p8peCpkDzrF9p\n"
+"bQ2ZvS304tN7+p0hif3+JyZy5/sxl17RxTeg5I3mo2+J0ptQDYwF/WadONO8r7uU\n"
+"YlRltFtQfyMzyVzHON4NHGjZh7dDGtWp0MGeHRBHQsC8bEChhvWme19VXhgZoWpl\n"
+"dUIZkSuvRwiURXjhKbZrEdJbVmr9FX6zoyOahv3VnmcEARoR+umxzvo3hGQPbHyH\n"
+"jTsQtSBjs75/9fCxcYmBWkh3JHVDVsCbV+z+5KZpk3m50J4Y1hC8hvepC9CaBqOM\n"
+"DjfyXh58x1yKiueEbcjSWsRuF7CjcrYnFUBHOs9U1j9WytCI3fhOWPMgR4UZpGuU\n"
+"WlcR1BXg1wYxX273xOS/jYn9MLAVlbRpPTUMIH9VRP+sc8+XaxKpJSCl4C+vcwNY\n"
+"1YdKD2QiuoBJ3fXGtqMVRtn9eZvatSJuY9CnRKRbf0hWmFD4D5RkiwE0WkdtwoHR\n"
+"uEXJ47RlF0/JDU1fY1mXBkq3usvB4Absy78qL06vh45xkk9bHbdf+7Ao1RQKmqiB\n"
+"NL5XnjBu+YX535WG7t7Su3mTCJXYHvn72ATxry8yhSLgWqt81STkRwc14HmrOGG8\n"
+"Gw7bz7y5vikj/rnPyr7ry+QRgNNDDayAqenAu2vEAzWir0RQC/iZ9rc/r7YQWGgL\n"
+"Xrd4TQ6rTZePARhwB3VomnLDDvLvi2oq/jPzLKSYM2a7qj/vBSbJ/NnNaDW5Ccew\n"
+"RjMI1lIHeedqYTVAW/CKoSEPcFSAzi/Ija0gcWLgX5xsFDGIYBepAX0KS9426kMu\n"
+"0r/V66zmPMusMilqRTx7KW+jZMVxXVc2zClcdmohMmtjsbqLkczprfSbdGswMv9Q\n"
+"I1ktHJHIRD0vPeZXnvKZsRKZw3sKb0ltZi33ZxCJFQPeGGtM5aAFthj6awcXy6Tt\n"
+"DPUQdCU/vh1zmGRAX17/Xb0irfvN+GhQLEl42pzhigJXc/rCG3a4Na8wT+xAIZVf\n"
+"WUI7hMslx5wA+iB4lrAjCq0YIrjINI/lHYpotXUZGmz5wz0jOciTmXMSx9du4cpk\n"
+"fIQJfR+fr5tG3fjHMgSP+p+RewHkd/7RUAmHC2k3cuk5pCJvUVJrhUIqsi1fa0LG\n"
+"GA0UU6Nr9tpYdNr1WkbKQjxTg0D//AXe61jmUS5XUU4AQf6zQVfN0TMtmuYeacbK\n"
+"4r6Z1CSIRbsgcnL1BN8GSd4KddkCqSk941aJUCoX+77ou4t0btVSB9FnLKipigtE\n"
+"E/Rpmv+81lA4fLiIag62/pcJ3uppsZ9aaHdR10SMmuCjAVLYHqhJfrHHn32dyqLK\n"
+"UI8kEZJ6GQzHLUXcGbbdnk1Qm6JwO8TeF/oQvh9y9py+oAyFy0qzP2UeUMUI2yRQ\n"
+"mlWSy+wX1DbVDQ3UHwJjWp65CgyYXuW8eCB0AbyF0kF4KGf7/7Ae7tEGbmYSm5MA\n"
+"71z+Azxtv5gRyRb787V2dyo0wcmbRlL7iUBVXNM/czQo31tAZIwLc+lKNp0SPH6g\n"
+"gJ2yX/GeDSFNAeEVUZ/f4KZIa7QQsnGWrUr+agSnQFkySmIjWYjwC/abJwah0v0d\n"
+"ulwr3tECaaXtoWVdYXa3utEclBz9umBwMJ9MQCm4Kx7dTYUWFT3bMM/ESTkGPcfm\n"
+"m+C4FsqFBs80WY0ududu50vTDSdJt1RqZ7Sg6DNH6acBvWyXOpT5mPJKUjnSFwyG\n"
+"oVLgv0aDDx7lLZdCkhyz/Ff5LNmBgQsjGllPszJ2gTZxZ5LD68S4kUirQG/qtzlS\n"
+"PGfDOC79SMZGgsoAnr4wV3RUTxsTVFlxVHsBMB+EXOFHAr3wHTVxUGBbGzxBlQ9w\n"
+"I/jlu8LIIexXAU75HS5KCGGfg0Z7BLqEzqpMKqcBQC7BD7GnCXrDSQ2DCXnl7bLN\n"
+"lIrQ/z2Y8AgSdED46R40MqyyN6CPPNiOCjONHZ30fLEXuEgCp4R/+x0WWsWpjGk2\n"
+"Ydkc03cx/X6moUYxB5HTqTodBmAQuWMX0rxFDrnR0SWghWjdWth9gjd+dvZ82tt1\n"
+"UMUywDPhcYchtUi2lnqnYJm5p00GN9Mk14MC5ZC5qP57IJVqxu0ktOMpks+CLPnz\n"
+"qp9OBpI4sIzd0y0aUJC2Gd+E9aAhlREIiicyBDmxLdk1i37QeeCralI3eubLNmE+\n"
+"CjDjD8t8FUGPpKglSD3lfLTqbp2TUvyWfvJC6ulFPNsAbeLHTnPnpyPQmWxhMNGt\n"
+"h67B9tbYww2TvNwqIgmB4+YIR4/pSs15TpAqvuUvjpmRwGklqgiSmrQrlIxCxux/\n"
+"mfsaL3KE97wm8BsaMpMkjUL7ByTIFhFZ/gHPTxaFpbqTZ4G+lABLgp3bIsB9Dl/P\n"
+"ovoqX+qL2Mq9T0GrVJGfRBuA5hISw63hx5zdsj2Cj3A3khHPqR+GRN/rVYUuOpLm\n"
+"z3v5pU/74vZRmNMAIhyhmweSEPNtyVkgSdgbFErqvhxN0om2Cd/7cWh2g5BXHyUL\n"
+"PBr7ZkgfsE9TnuDH7Z0JoBqXJki+MO6nqz73oH2Mm86yxcXp6O/ieKTollrUJ3yQ\n"
+"P6hLcEbYPzUV99del7Va5Wi0nn0wbRXCGVQdwY+iWc7pT+VVlncyg0TvLXi0OtOt\n"
+"O8xbT2DAzVXxMwOsKV9ZgS/0dtwzwICpnTzBI/47V8GYhHbOUNTBPZ52GaXMeWlX\n"
+"cuRGb0+7OkKWuriyOQ5z5xaASCVfqgnOwSZYiAk0gcDoK+JHdr64/sMoJhH87R4i\n"
+"2TO90whkScgiGR7A06Ba42bT1nJtI6pxvzdB2b4BDAs2Lr2OdcB3BY1dtzKjFkw/\n"
+"qfIw3F55UQwcs84ZEFQDAB/tmfNHajblDFpXR4N5QvU/PdWVWJUub7oNyhIX6ruu\n"
+"ln4H7lpTUHJZ7jkr1qpnvkztZtHGlpJ0QdUHgyMYER1xU58Hg77yzIW3EdAa2PyK\n"
+"1t4udKbQKChShlShIMzwzj57ss/69QobrpYAHYi6IRMaMUGBfipGBACK3yeXsXz0\n"
+"c3Q2J5vI6QbxNsiJ5t7Ry1IqotbJcU7HND/yVUAUbEg5CpEDOSeSOW/ulyLuFxEV\n"
+"lRTwIO/68BoIoR7umlP23/1N5OYzaBHhH2nThILBovHeJRXnGXSgeFfwSj7LIYEV\n"
+"c1MdDSg/HzoADPXyEPLzqFzHRHeNiqEolmOPnFh0hRzbMZ0W5TQPDGWJdF21g816\n"
+"vA0WW4UQjLM+vnX9kKKLA1ut+9JWk1dGKsmWtdWUDfJjUP/L6dS4OYEl6O6+SjM9\n"
+"GcyGvHTiC5OpJllYpvELP/NjtTf9or8Bmruuga/axeOuS5ocYLK/sGRlmO6Z96da\n"
+"QSlyGWEQAnM2D1cDmdd4CetPslOVIcQ41+coWCi2xg3UjO/bFK1CA4R1rb4ekXfs\n"
+"s5U2XChyHhUPgl57y1r0ILXRXWJTJ0/F9hhu4aYQVFeIV/IuzJbmTKKkAcCOH6ys\n"
+"qnu2BXz8Pm2tU10JFfRcuZ8rHuUyUErA40ESsLijON98GMwL4Rat9ZSCNS5hlK7y\n"
+"yRJdr0ITp8oTbduAoulgWOvtcw1L87QBVojWz3cbhXra+WITirYuGNbzfmZn1WQM\n"
+"kukEZUEHSypGOrHr1XiuY4Rw/DBaJSLyZ+VybEOfXqXkDBh5s1ayypBvzrzFZCIn\n"
+"PJxIVsvrkhrpEbTJ9d7zLWjhOa9ZWw8lAubllbGm+7qCfdHmGsfBtvJdzx6zhB1Y\n"
+"otL/PCis2XVTBEDJeB8pGqKFOZjNz8PC5qP+ymtAfy2ktl/u4HsFlxV7CsEKGYPm\n"
+"p3LqnhPUy5M5gin4E4uPPyzzD2kcM3way49FKWUKlblQU0SyWtHRmMB3vcVmyT85\n"
+"BRULXF7jgog7XR/EMltwQyJI6GcUCrnWZu+G0BEwXG+CsgCzE7assDavc1NSGLZM\n"
+"rmzXiFFyfk7CE6lW2Lm+oWaFwKdvpmNZJFGGX8ZHRE9ZvkFMnfw9MYf2W7xa0jf7\n"
+"k3c6X5wMuk9mznVtq5itNFVXh1mT1ujeWOiiqyH5UhQQjj6O+ZXt4gqt/jT6dd1i\n"
+"jRuhhxaUGOlhpVBW/ySXhZ+HgOy9aCJ/bgjRGaqGixogk4f4rcgigHruwTpOQuDn\n"
+"xDZ3Xns70S40WtHSYN+Gbl9nIh4yl78aNnA4FVtTAuLlVKEKlMJi9OBFuP5TEczG\n"
+"+0HTwL/VPSCI+8FUZBhlz3YwecYq6dY5mS46+luPW+5Wl+5jtzb8V9oxVnRx2hQq\n"
+"B5HJsM5FOOhHDHMXoCsevj7N/ufK7cU7Wbr0DkgYRwvb0ZJB5WYgcaQ0W7aduhGb\n"
+"MQsandhP8Ajb2cmLobi3mHHPbcEkvjT8JP9Sim5xtfF+oCMMB5ByA5bI2aIFybZm\n"
+"jX9e/V8wNgtpDKDVKPjB3+9dj5gU1N5JsrjQwQDB0kVRMWdpJCtD4hZ2+T/QE3SI\n"
+"f8Rdk8pj8qBzRPbnhW6qsoWZdjMRC8qixZqHw4jol09UF7Ab9hjEF5ZDTfNGXwy8\n"
+"/hz8su+mr8hhrlCrOF2vBYUayAA96zhbDWfg3Pdxo9bTn3/DmyAngL4J5Gu679xK\n"
+"rWN4j7uQG4bzTa8WJb09/lW49UzWvmrz0c6/yexk3T//xDD067FafdnP5pYs4Cvp\n"
+"rCoHpXbKjxx99DJmb5iXW0JRLSpFSCbf1HPHbmzST3minSXap5FCWDJcSgExKIJp\n"
+"DXZ9rk0LMnQA74MWC5gjjM+5t0AHKuNRhJbQSwYWTKqeApXho53T/COlfDlSs2tb\n"
+"Vz1Ia5z7IOfu1QheE93huNAHT3Ob+mSmUq782SqFPr6uwud/l5uP3HpcuwugdlFm\n"
+"Jw8uBBOQ53W4lLbYfQYTVgieClVhmYMu7Ye0xYZ5B2jf714sjZRMa0LCbsyj58xH\n"
+"uzs8ddNN1fLMzb0JRBE8JWj5PbxhA/sTwMkD7SnEMBUTtP0obmuQ982aTfyvQCH/\n"
+"ve8OUPtYf5XWNv18mpR+h+riMt1Y8Eb6BJzTMFNWagMJAe3JV6A6upHroNFo2FxY\n"
+"1XPRM1Rt0zKo7GD+oXnixfpl1aG8yqZhYo1ZC9buaHwH6zvM+xoiGD0iujeDtpVy\n"
+"Vp6cAqqaGmrNwcPVBLc7hNKrJnbFKyhjL5/xp9j6jQov1aWQ8HsaNvh0p2ljmlwb\n"
+"daTYZcwLgSgPna7HhiqnOSAmXZ7St/qe/b9TqBtIVzwzmtevgMyG98QV0syFP5X6\n"
+"2Jc1g9733sTZp7njq4Cu07JhpICpinhLWR3nkODJbjk/mpLcQZgtV6W749AUo8oT\n"
+"jRVEJ8MpCo1h0bVDxsRnA3DrMneD88L8/b10aHs+bPm1HKbCmT+kJAFaUQNa8JvJ\n"
+"pReN37qTWvZCte7vaPAIP5cboATMu/J4t3izpm+YJoJlWcIegGx3kQ+17P4MbgDl\n"
+"S93U4sOLvTk9+MoyPo9yGWU/zHgzcQ6wCFdzWMDRswuh+/4TJ2+yg6maq3iBtj39\n"
+"gNLMR+sRgGGvYisqE9bfvNQy5IWrABBKcSBTXeTM1DmW6jv3TI8DoCzCbpjqcIwT\n"
+"u2J+7k8wJEHPcAwnBjlyWphVvwNwM0cXqOnlJZ/4z7OGgjiNEem7TMuvxk+YkiXK\n"
+"OzftdTjeIpzBwsGRP8/teMBpjS95M7GloKtxO+muBVxXbmsq8GBRC9vtNJ2Ma/xP\n"
+"bXvd+7caytD3ob6ZfOzCpi4ZS8uByEfIMxlgZ5Sn3jhgEkcIU+YW9b3teMZOuWdA\n"
+"QpDCoMpXaHVyRqwVV59JjmftiBnNBEo1/QzRj2UxRi7fHMfmNxL5LRM4CHSLUSCq\n"
+"Y3A3pkxvBHUzemhynSFvtCPa8GHiUpe9so0V/2hlgaENAVELPjMlWytaYufRllgy\n"
+"tUnCd32C5PrrmYzMKnxKRPXLcxLgziruJGSks9vIspoPk0pWgkZm+M9fRpJKlWHF\n"
+"yT9OOGBW2yynw/yvXssxJmdUDxVcWL4uS2bZc4s0Zc6RSL9uQPjZVX0JLj+cXfx4\n"
+"93Gn5bDhMgm+CGM6j3RiAAD7tT5V0sytNFjXd1A4U1u8yj3wzhKqOtZpDmuGUlMn\n"
+"EODu7I5KtWxOTPThy7TecI5r+F/6KL+2MOtRhj2PmlT/Xed6PaAmDkQeiXGps08x\n"
+"u0JIpuB61axvT4PAsKZNUd4ExbzNxRDAARUMgY8krpmyKZyHVFIQ19uHM2lGl9/i\n"
+"h3PKlLHYI8RsHutHElzq+F5tWd5AA99LVRZX4axAVIQNiqRg8IMSoCwUaCCbjUMz\n"
+"sJCo2t36GYk5S2BRnfrCqYoZRHw+ENYN0tDEMhXq1OqjvNHW3TzL3DsUhM6EZU5n\n"
+"cRR4ynUvPqqWFphLefRW10vCtaW9roJQZyFYf9kd8xgW/BhcDNbTTaQ1U6xCHgX+\n"
+"78DKee/NvY1WIEBR8X0iVk5XlSJb14eRtxNawXFyebVdmC/DiMNgnTBncMbePnZi\n"
+"KCl1r5xqo7tSIoJ6Z0l6qINd89T9fcg9mujTVwsfQ+5/kdEy0Iw7CQcTOGvMaoPX\n"
+"IAJlWSVeZ8eu8kmsD1Z8ewoPufMKiY4cPRAK5bCDgsrK6bAExOlCwPnNNM8Ym1Hz\n"
+"aYFeGs5sW468Qww+Nbl5xcNFKtwUKZ6EebRHjwttiyTgCdAhv9wL1u2WFydWWgkG\n"
+"rwUbNpSLKls+pijCeJAscvxzbZz96iOaYrY8IyzGBFwfgFAESfnzBc8SQjZzMzoO\n"
+"vmYIRon2m/5w5AZA2IjQ4VxXJDK6XExD/ZLsxNXzMnROD++hE+s8DvPlRPmN4egF\n"
+"gAzJs/9t7IyE/dDf7gSSBqzEBbwduD8ozzYHwELUc4ERdRzjEdBM0azT61g7Yilr\n"
+"iT5Hy+2iw/pNwiqVOYiAbj2lwcoMlFZmdxviD4IMXdsNVWsCAVJL0PqIh1UDDb3z\n"
+"Urv3idBJeSBuuFr6AFS6kAgvrwV/pEGoBoHuyii/rZxVugGKeuMynKEvSHuFNuQU\n"
+"qIHcNgqQR34v2Ut5pQ1R8s7K3Rae/AhE5GncJa6FJmB9TF8MYMu9PlSZV/eGv8UL\n"
+"IDWQ7sY3NdhZini//xtwPqIw29yOeZ0X6Aqsek9tfh21UwKSpHb7T+PwXYmoB+23\n"
+"p3FXkP/rv4AGRq1xJqFYzKJvwsXqTFuNFWP74yhTg6rC90w2p5TeH1rJMAnv4u0L\n"
+"hGtG/NL+D1Tzdf00TYAjno5Ia5dQJDd/eO+Ygqnhl6hAqGtS6r9JhIEXw1nQD7SC\n"
+"lj96ZuKdUWO8rpIiAtvHAsn++xvMVPm/S1SwA8oE049iVwS8/eNNiMKoSlTlYc7o\n"
+"pusBZQrVF4We4HHYFjysBbcXlvoXDd8LkZ8Nh63VQPnoIGNKH2U6aXCnQcJ8dZqO\n"
+"DNxL4uyM4A578FUUR6vxqt2asnLHQ0Z7pPE4uqtz/WgbiHI/i2oHS8oe1clsifCw\n"
+"3ZY33kflqLftkTNka1oiftDb0OqFLjkS7/AUorqHazw53gM3gqJY5EXA3Px9+nhu\n"
+"NzxSK/t41JoCfgQJHMkIWb3yUcO4OFZeGCeAxIJY95hv/brt6/WNielXjNaohYvc\n"
+"lsSUHEJRHwVxQmWK0LS+g13HAgOI7cNt3MA8sSkzTneHGFgEvmrSyb0wCEmushC9\n"
+"mjQThvaxfQk9douA/cR2bHr7axXqv9vjztmxUr0a30a7lvLMBQbJmFtJJylW+tJe\n"
+"v/vKNOB+9mK793cttr2JFnMhwUKFKWiFDQJtxw/eLQWY4BJ19Rs2x4BJgmV+u1jB\n"
+"zR8uvxuArG/cqVEJsoC6uuSzhAWSwdvumijO6yuyWF6nHY6aAcy8dyFQlDFHAd+/\n"
+"J05Lrbzj4N9lcI7hPalh0uMdERGvtUdT8QRm5ebP1zogYEkZk/1GOU29dMawkAt/\n"
+"SWhp2yWdjLt8f5HQKu72vUF/yyTfzfdqQqJwfthP7+vp+sHDO85AMF45uU9g3pxW\n"
+"IbXSbZ4fFGC1/41db/2GOHFgaheMXj0SIWHqQE1jtihr3BBBO4b3Ccz5QCnrn48J\n"
+"8L+QRdh4a/cAx4ty/oHEiXwpSBBSFRl5+y2NijC8GITA5dRjCRWP+Y0zuTrJ7j1a\n"
+"h+3kGs1kxqskhaEuhXnXyknGLjXrU+ewRGhHzP23o5betVhX+c1XjVqmJNZ5OPn/\n"
+"wrqx/XwoIl/3F5lMmGDG9mPtyg0E227nKl9Sy0Vbwx2tu1unjOlzSCa7lpoD4TIX\n"
+"PBJ5+Zb0CE6HEt3V0ec1m4uUe/xObAnzyr4UbzdqLaMy8vTcF/qsncXyPBjwqdjR\n"
+"ReDAtt99bAPY4roPKGt8dgKUPE0t/XoY+SlmUp75TkZDXrOIJXpEW0GpLPf53T+W\n"
+"Ex3KtfLAnZzrw8+dIageY7IgoQ85h3sYE7uEI8QlcO/o4udqUzTp4Sn4sWvdTLrx\n"
+"W7ImvK2rsU5ubVdsEaFKM7+7nxGn2JyMpIWFz0SbP34CkXHhrXxyRD+GhMIDHFxV\n"
+"uBnZnjJsw+ooIm1rL4I7/VMWEwmVegreT6w9Gsmb5igw+zu9v2YBgTOhysA9XZd4\n"
+"7O3VjqKkhTXcBqdpRWuz8gPQ+4rfwij28Gg2alG04Eh3G3868NOCFJhhaHVmwYR2\n"
+"ygRm6N9eDW1bHhYSN75HSEb6aIebk+1AT4S1QtJaPSH0EduIXO++JYAs+jIFKy2c\n"
+"jCVFlO/LbXl7iCdXurJHpSbMNmZFNUri6zEolENODLwke836jBOKiVrWzLnEMxHI\n"
+"WDDTpLTYhR3C7sEprpEQm9SX2Eik3WxVb4ZTb7SZFU1y1d4tWnjGu3U1D+vO9wVq\n"
+"Sss9lDipbkhQ9k4j1/Pqozaxvi8lYLbh3WEjK3Iwpr66Bk6Ai2oRg4b+7vzV4o+6\n"
+"L47JPJhajdHac0CIlmupyA4eejECS6OpoLDf5Wr/616k3dxM//3kAWGUnXVw9GSo\n"
+"UF5W8AaKlaGZ6EZk09NyGSFRjEs18z+g5ckviGF0EhZI7ZPWQQmlqWUsL9O0S4GO\n"
+"ZZ9f0UhNmHEspcugbs7e1yfjwGVyxIBkrmxpkmfHE4Gb47UGlJevg2OvZOPT3wMH\n"
+"vOds2BtqdT3tuss9k+7hsISGse7isEOb7TN5MHb6yyzqnCUZhp5m3Iag7TUkiyfU\n"
+"jKH5R13tHqKUoJ2rofWoLO2H5xSfp/lqF9sLd4rJ+Pbjhiuvfwz5copYsuTNL4kB\n"
+"SPUikHlTxSOgTBYNV77qxpsqOI3+iziCrSqHsxNdlaA1T3fiq6SeZBNdD822AYm9\n"
+"L5hbcgpDPEEwT/n5kWNbRNueerJkJwboaOnT1ZX1601Pwj5QDi+YM1NYy5PsdWxb\n"
+"bPGpQyZ+uf917q9gV7Ykr5cic10YD11khAghr0n6fYfb8Ijc22uP6m47KItDqQc1\n"
+"eFym149F56B0yg5FR85Arg==\n"
+"-----END MESSAGE-----\n"
+" signature Of+jvQKzH9ot2NV5twlDO2CFbzLSB4absWTwG58TCHb+TWgQi3z6SZIoTnGGY/uicJgEkCN++bZZR49GiyHyCQ\n";
diff --git a/src/test/test_hs_intropoint.c b/src/test/test_hs_intropoint.c
index b207cd4ce3..0cae2de7e1 100644
--- a/src/test/test_hs_intropoint.c
+++ b/src/test/test_hs_intropoint.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Tor Project, Inc. */
+/* Copyright (c) 2016-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -17,21 +17,66 @@
#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;
+
+ /* 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:
+ 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
@@ -69,10 +114,10 @@ helper_create_intro_circuit(void)
return circ;
}
-static hs_cell_introduce1_t *
+static trn_cell_introduce1_t *
helper_create_introduce1_cell(void)
{
- hs_cell_introduce1_t *cell = NULL;
+ trn_cell_introduce1_t *cell = NULL;
ed25519_keypair_t auth_key_kp;
/* Generate the auth_key of the cell. */
@@ -80,39 +125,39 @@ helper_create_introduce1_cell(void)
goto err;
}
- cell = hs_cell_introduce1_new();
+ cell = trn_cell_introduce1_new();
tt_assert(cell);
/* Set the auth key. */
{
size_t auth_key_len = sizeof(auth_key_kp.pubkey);
- hs_cell_introduce1_set_auth_key_type(cell,
+ trn_cell_introduce1_set_auth_key_type(cell,
HS_INTRO_AUTH_KEY_TYPE_ED25519);
- hs_cell_introduce1_set_auth_key_len(cell, auth_key_len);
- hs_cell_introduce1_setlen_auth_key(cell, auth_key_len);
- uint8_t *auth_key_ptr = hs_cell_introduce1_getarray_auth_key(cell);
+ trn_cell_introduce1_set_auth_key_len(cell, auth_key_len);
+ trn_cell_introduce1_setlen_auth_key(cell, auth_key_len);
+ uint8_t *auth_key_ptr = trn_cell_introduce1_getarray_auth_key(cell);
memcpy(auth_key_ptr, auth_key_kp.pubkey.pubkey, auth_key_len);
}
/* Set the cell extentions to none. */
{
- cell_extension_t *ext = cell_extension_new();
- cell_extension_set_num(ext, 0);
- hs_cell_introduce1_set_extensions(cell, ext);
+ trn_cell_extension_t *ext = trn_cell_extension_new();
+ trn_cell_extension_set_num(ext, 0);
+ trn_cell_introduce1_set_extensions(cell, ext);
}
/* Set the encrypted section to some data. */
{
size_t enc_len = 128;
- hs_cell_introduce1_setlen_encrypted(cell, enc_len);
- uint8_t *enc_ptr = hs_cell_introduce1_getarray_encrypted(cell);
+ trn_cell_introduce1_setlen_encrypted(cell, enc_len);
+ uint8_t *enc_ptr = trn_cell_introduce1_getarray_encrypted(cell);
memset(enc_ptr, 'a', enc_len);
}
return cell;
err:
done:
- hs_cell_introduce1_free(cell);
+ trn_cell_introduce1_free(cell);
return NULL;
}
@@ -122,50 +167,43 @@ static void
test_establish_intro_wrong_purpose(void *arg)
{
int retval;
- hs_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:
- hs_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 +211,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 +236,21 @@ static void
test_establish_intro_wrong_keytype2(void *arg)
{
int retval;
- hs_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 +260,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:
- hs_cell_establish_intro_free(establish_intro_cell);
circuit_free(TO_CIRCUIT(intro_circ));
}
@@ -239,26 +271,27 @@ static void
test_establish_intro_wrong_mac(void *arg)
{
int retval;
- hs_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 =
- hs_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 +302,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 =
- hs_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 =
- hs_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 +329,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:
- hs_cell_establish_intro_free(establish_intro_cell);
+ trn_cell_establish_intro_free(cell);
circuit_free(TO_CIRCUIT(intro_circ));
}
@@ -309,42 +342,42 @@ static void
test_establish_intro_wrong_auth_key_len(void *arg)
{
int retval;
- hs_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. */
- hs_cell_establish_intro_set_auth_key_len(establish_intro_cell,
- bad_auth_key_len);
- hs_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:
- hs_cell_establish_intro_free(establish_intro_cell);
+ trn_cell_establish_intro_free(cell);
circuit_free(TO_CIRCUIT(intro_circ));
}
@@ -354,40 +387,42 @@ static void
test_establish_intro_wrong_sig_len(void *arg)
{
int retval;
- hs_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. */
- hs_cell_establish_intro_set_sig_len(establish_intro_cell, bad_sig_len);
- hs_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:
- hs_cell_establish_intro_free(establish_intro_cell);
+ trn_cell_establish_intro_free(cell);
circuit_free(TO_CIRCUIT(intro_circ));
}
@@ -397,74 +432,70 @@ static void
test_establish_intro_wrong_sig(void *arg)
{
int retval;
- hs_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:
- hs_cell_establish_intro_free(establish_intro_cell);
circuit_free(TO_CIRCUIT(intro_circ));
}
/* Helper function: Send a well-formed v3 ESTABLISH_INTRO cell to
* <b>intro_circ</b>. Return the cell. */
-static hs_cell_establish_intro_t *
+static trn_cell_establish_intro_t *
helper_establish_intro_v3(or_circuit_t *intro_circ)
{
int retval;
- hs_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,33 +507,51 @@ 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;
}
+/* Helper function: test circuitmap free_all function outside of
+ * test_intro_point_registration to prevent Coverity from seeing a
+ * double free if the assertion hypothetically fails.
+ */
+static void
+test_circuitmap_free_all(void)
+{
+ hs_circuitmap_ht *the_hs_circuitmap = NULL;
+
+ the_hs_circuitmap = get_hs_circuitmap();
+ tt_assert(the_hs_circuitmap);
+ hs_circuitmap_free_all();
+ the_hs_circuitmap = get_hs_circuitmap();
+ tt_ptr_op(the_hs_circuitmap, OP_EQ, NULL);
+ done:
+ ;
+}
+
/** Successfuly register a v2 intro point and a v3 intro point. Ensure that HS
* circuitmap is maintained properly. */
static void
@@ -512,7 +561,7 @@ test_intro_point_registration(void *arg)
hs_circuitmap_ht *the_hs_circuitmap = NULL;
or_circuit_t *intro_circ = NULL;
- hs_cell_establish_intro_t *establish_intro_cell = NULL;
+ trn_cell_establish_intro_t *establish_intro_cell = NULL;
ed25519_public_key_t auth_key;
crypto_pk_t *legacy_auth_key = NULL;
@@ -530,10 +579,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(&auth_key);
- tt_ptr_op(returned_intro_circ, ==, NULL);
+ returned_intro_circ =hs_circuitmap_get_intro_circ_v3_relay_side(&auth_key);
+ tt_ptr_op(returned_intro_circ, OP_EQ, NULL);
}
/* Create a v3 intro point */
@@ -545,11 +594,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(&auth_key);
- tt_ptr_op(intro_circ, ==, returned_intro_circ);
+ returned_intro_circ =
+ hs_circuitmap_get_intro_circ_v3_relay_side(&auth_key);
+ tt_ptr_op(intro_circ, OP_EQ, returned_intro_circ);
}
/* Create a v2 intro point */
@@ -564,13 +614,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);
- returned_intro_circ= hs_circuitmap_get_intro_circ_v2((uint8_t*)key_digest);
- tt_ptr_op(legacy_intro_circ, ==, returned_intro_circ);
+ 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, OP_EQ, returned_intro_circ);
}
/* XXX Continue test and try to register a second v3 intro point with the
@@ -580,15 +631,8 @@ test_intro_point_registration(void *arg)
crypto_pk_free(legacy_auth_key);
circuit_free(TO_CIRCUIT(intro_circ));
circuit_free(TO_CIRCUIT(legacy_intro_circ));
- hs_cell_establish_intro_free(establish_intro_cell);
-
- { /* Test circuitmap free_all function. */
- the_hs_circuitmap = get_hs_circuitmap();
- tt_assert(the_hs_circuitmap);
- hs_circuitmap_free_all();
- the_hs_circuitmap = get_hs_circuitmap();
- tt_assert(!the_hs_circuitmap);
- }
+ trn_cell_establish_intro_free(establish_intro_cell);
+ test_circuitmap_free_all();
UNMOCK(hs_intro_send_intro_established_cell);
}
@@ -674,7 +718,7 @@ static void
test_introduce1_validation(void *arg)
{
int ret;
- hs_cell_introduce1_t *cell = NULL;
+ trn_cell_introduce1_t *cell = NULL;
(void) arg;
@@ -714,25 +758,25 @@ test_introduce1_validation(void *arg)
ret = validate_introduce1_parsed_cell(cell);
tt_int_op(ret, OP_EQ, 0);
/* Set an invalid size of the auth key buffer. */
- hs_cell_introduce1_setlen_auth_key(cell, 3);
+ trn_cell_introduce1_setlen_auth_key(cell, 3);
ret = validate_introduce1_parsed_cell(cell);
tt_int_op(ret, OP_EQ, -1);
/* Reset auth key buffer and make sure it works. */
- hs_cell_introduce1_setlen_auth_key(cell, sizeof(ed25519_public_key_t));
+ trn_cell_introduce1_setlen_auth_key(cell, sizeof(ed25519_public_key_t));
ret = validate_introduce1_parsed_cell(cell);
tt_int_op(ret, OP_EQ, 0);
/* Empty encrypted section. */
- hs_cell_introduce1_setlen_encrypted(cell, 0);
+ trn_cell_introduce1_setlen_encrypted(cell, 0);
ret = validate_introduce1_parsed_cell(cell);
tt_int_op(ret, OP_EQ, -1);
/* Reset it to some non zero bytes and validate. */
- hs_cell_introduce1_setlen_encrypted(cell, 1);
+ trn_cell_introduce1_setlen_encrypted(cell, 1);
ret = validate_introduce1_parsed_cell(cell);
tt_int_op(ret, OP_EQ, 0);
done:
- hs_cell_introduce1_free(cell);
+ trn_cell_introduce1_free(cell);
}
static void
@@ -740,7 +784,7 @@ test_received_introduce1_handling(void *arg)
{
int ret;
uint8_t *request = NULL, buf[128];
- hs_cell_introduce1_t *cell = NULL;
+ trn_cell_introduce1_t *cell = NULL;
or_circuit_t *circ = NULL;
(void) arg;
@@ -752,6 +796,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);
@@ -765,6 +810,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));
@@ -774,12 +820,12 @@ test_received_introduce1_handling(void *arg)
/* Valid case. */
{
cell = helper_create_introduce1_cell();
- ssize_t request_len = hs_cell_introduce1_encoded_len(cell);
- tt_size_op(request_len, OP_GT, 0);
+ ssize_t request_len = trn_cell_introduce1_encoded_len(cell);
+ tt_int_op((int)request_len, OP_GT, 0);
request = tor_malloc_zero(request_len);
ssize_t encoded_len =
- hs_cell_introduce1_encode(request, request_len, cell);
- tt_size_op(encoded_len, OP_GT, 0);
+ trn_cell_introduce1_encode(request, request_len, cell);
+ tt_int_op((int)encoded_len, OP_GT, 0);
circ = helper_create_intro_circuit();
or_circuit_t *service_circ = helper_create_intro_circuit();
@@ -788,9 +834,9 @@ test_received_introduce1_handling(void *arg)
/* Register the circuit in the map for the auth key of the cell. */
ed25519_public_key_t auth_key;
const uint8_t *cell_auth_key =
- hs_cell_introduce1_getconstarray_auth_key(cell);
+ trn_cell_introduce1_getconstarray_auth_key(cell);
memcpy(auth_key.pubkey, cell_auth_key, ED25519_PUBKEY_LEN);
- hs_circuitmap_register_intro_circ_v3(service_circ, &auth_key);
+ hs_circuitmap_register_intro_circ_v3_relay_side(service_circ, &auth_key);
ret = hs_intro_received_introduce1(circ, request, request_len);
circuit_free(TO_CIRCUIT(circ));
circuit_free(TO_CIRCUIT(service_circ));
@@ -800,17 +846,17 @@ test_received_introduce1_handling(void *arg)
/* Valid legacy cell. */
{
tor_free(request);
- hs_cell_introduce1_free(cell);
+ trn_cell_introduce1_free(cell);
cell = helper_create_introduce1_cell();
- uint8_t *legacy_key_id = hs_cell_introduce1_getarray_legacy_key_id(cell);
+ uint8_t *legacy_key_id = trn_cell_introduce1_getarray_legacy_key_id(cell);
memset(legacy_key_id, 'a', DIGEST_LEN);
/* Add an arbitrary amount of data for the payload of a v2 cell. */
- size_t request_len = hs_cell_introduce1_encoded_len(cell) + 256;
+ size_t request_len = trn_cell_introduce1_encoded_len(cell) + 256;
tt_size_op(request_len, OP_GT, 0);
request = tor_malloc_zero(request_len + 256);
ssize_t encoded_len =
- hs_cell_introduce1_encode(request, request_len, cell);
- tt_size_op(encoded_len, OP_GT, 0);
+ trn_cell_introduce1_encode(request, request_len, cell);
+ tt_int_op((int)encoded_len, OP_GT, 0);
circ = helper_create_intro_circuit();
or_circuit_t *service_circ = helper_create_intro_circuit();
@@ -819,7 +865,7 @@ test_received_introduce1_handling(void *arg)
/* Register the circuit in the map for the auth key of the cell. */
uint8_t token[REND_TOKEN_LEN];
memcpy(token, legacy_key_id, sizeof(token));
- hs_circuitmap_register_intro_circ_v2(service_circ, token);
+ hs_circuitmap_register_intro_circ_v2_relay_side(service_circ, token);
ret = hs_intro_received_introduce1(circ, request, request_len);
circuit_free(TO_CIRCUIT(circ));
circuit_free(TO_CIRCUIT(service_circ));
@@ -827,7 +873,7 @@ test_received_introduce1_handling(void *arg)
}
done:
- hs_cell_introduce1_free(cell);
+ trn_cell_introduce1_free(cell);
tor_free(request);
hs_circuitmap_free_all();
UNMOCK(relay_send_command_from_edge_);
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_ntor.sh b/src/test/test_hs_ntor.sh
new file mode 100755
index 0000000000..8a0003d44a
--- /dev/null
+++ b/src/test/test_hs_ntor.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+# Validate Tor's ntor implementation.
+
+exitcode=0
+
+# Run the python integration test sand return the exitcode of the python
+# script. The python script might ask the testsuite to skip it if not all
+# python dependencies are covered.
+"${PYTHON:-python}" "${abs_top_srcdir:-.}/src/test/hs_ntor_ref.py" || exitcode=$?
+
+exit ${exitcode}
diff --git a/src/test/test_hs_ntor_cl.c b/src/test/test_hs_ntor_cl.c
new file mode 100644
index 0000000000..ed1eda58ea
--- /dev/null
+++ b/src/test/test_hs_ntor_cl.c
@@ -0,0 +1,255 @@
+/* Copyright (c) 2017, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/** This is a wrapper over the little-t-tor HS ntor functions. The wrapper is
+ * used by src/test/hs_ntor_ref.py to conduct the HS ntor integration
+ * tests.
+ *
+ * The logic of this wrapper is basically copied from src/test/test_ntor_cl.c
+ */
+
+#include "orconfig.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+#define ONION_NTOR_PRIVATE
+#include "or.h"
+#include "util.h"
+#include "compat.h"
+#include "crypto.h"
+#include "crypto_curve25519.h"
+#include "hs_ntor.h"
+#include "onion_ntor.h"
+
+#define N_ARGS(n) STMT_BEGIN { \
+ if (argc < (n)) { \
+ fprintf(stderr, "%s needs %d arguments.\n",argv[1],n); \
+ return 1; \
+ } \
+ } STMT_END
+#define BASE16(idx, var, n) STMT_BEGIN { \
+ const char *s = argv[(idx)]; \
+ if (base16_decode((char*)var, n, s, strlen(s)) < (int)n ) { \
+ fprintf(stderr, "couldn't decode argument %d (%s)\n",idx,s); \
+ return 1; \
+ } \
+ } STMT_END
+#define INT(idx, var) STMT_BEGIN { \
+ var = atoi(argv[(idx)]); \
+ if (var <= 0) { \
+ fprintf(stderr, "bad integer argument %d (%s)\n",idx,argv[(idx)]); \
+ } \
+ } STMT_END
+
+/** The first part of the HS ntor protocol. The client-side computes all
+ necessary key material and sends the appropriate message to the service. */
+static int
+client1(int argc, char **argv)
+{
+ int retval;
+
+ /* Inputs */
+ curve25519_public_key_t intro_enc_pubkey;
+ ed25519_public_key_t intro_auth_pubkey;
+ curve25519_keypair_t client_ephemeral_enc_keypair;
+ uint8_t subcredential[DIGEST256_LEN];
+
+ /* Output */
+ hs_ntor_intro_cell_keys_t hs_ntor_intro_cell_keys;
+
+ char buf[256];
+
+ N_ARGS(6);
+ BASE16(2, intro_auth_pubkey.pubkey, ED25519_PUBKEY_LEN);
+ BASE16(3, intro_enc_pubkey.public_key, CURVE25519_PUBKEY_LEN);
+ BASE16(4, client_ephemeral_enc_keypair.seckey.secret_key,
+ CURVE25519_SECKEY_LEN);
+ BASE16(5, subcredential, DIGEST256_LEN);
+
+ /* Generate keypair */
+ curve25519_public_key_generate(&client_ephemeral_enc_keypair.pubkey,
+ &client_ephemeral_enc_keypair.seckey);
+
+ retval = hs_ntor_client_get_introduce1_keys(&intro_auth_pubkey,
+ &intro_enc_pubkey,
+ &client_ephemeral_enc_keypair,
+ subcredential,
+ &hs_ntor_intro_cell_keys);
+ if (retval < 0) {
+ goto done;
+ }
+
+ /* Send ENC_KEY */
+ base16_encode(buf, sizeof(buf),
+ (const char*)hs_ntor_intro_cell_keys.enc_key,
+ sizeof(hs_ntor_intro_cell_keys.enc_key));
+ printf("%s\n", buf);
+ /* Send MAC_KEY */
+ base16_encode(buf, sizeof(buf),
+ (const char*)hs_ntor_intro_cell_keys.mac_key,
+ sizeof(hs_ntor_intro_cell_keys.mac_key));
+ printf("%s\n", buf);
+
+ done:
+ return retval;
+}
+
+/** The second part of the HS ntor protocol. The service-side computes all
+ necessary key material and sends the appropriate message to the client */
+static int
+server1(int argc, char **argv)
+{
+ int retval;
+
+ /* Inputs */
+ curve25519_keypair_t intro_enc_keypair;
+ ed25519_public_key_t intro_auth_pubkey;
+ curve25519_public_key_t client_ephemeral_enc_pubkey;
+ uint8_t subcredential[DIGEST256_LEN];
+
+ /* Output */
+ hs_ntor_intro_cell_keys_t hs_ntor_intro_cell_keys;
+ hs_ntor_rend_cell_keys_t hs_ntor_rend_cell_keys;
+ curve25519_keypair_t service_ephemeral_rend_keypair;
+
+ char buf[256];
+
+ N_ARGS(6);
+ BASE16(2, intro_auth_pubkey.pubkey, ED25519_PUBKEY_LEN);
+ BASE16(3, intro_enc_keypair.seckey.secret_key, CURVE25519_SECKEY_LEN);
+ BASE16(4, client_ephemeral_enc_pubkey.public_key, CURVE25519_PUBKEY_LEN);
+ BASE16(5, subcredential, DIGEST256_LEN);
+
+ /* Generate keypair */
+ curve25519_public_key_generate(&intro_enc_keypair.pubkey,
+ &intro_enc_keypair.seckey);
+ curve25519_keypair_generate(&service_ephemeral_rend_keypair, 0);
+
+ /* Get INTRODUCE1 keys */
+ retval = hs_ntor_service_get_introduce1_keys(&intro_auth_pubkey,
+ &intro_enc_keypair,
+ &client_ephemeral_enc_pubkey,
+ subcredential,
+ &hs_ntor_intro_cell_keys);
+ if (retval < 0) {
+ goto done;
+ }
+
+ /* Get RENDEZVOUS1 keys */
+ retval = hs_ntor_service_get_rendezvous1_keys(&intro_auth_pubkey,
+ &intro_enc_keypair,
+ &service_ephemeral_rend_keypair,
+ &client_ephemeral_enc_pubkey,
+ &hs_ntor_rend_cell_keys);
+ if (retval < 0) {
+ goto done;
+ }
+
+ /* Send ENC_KEY */
+ base16_encode(buf, sizeof(buf),
+ (const char*)hs_ntor_intro_cell_keys.enc_key,
+ sizeof(hs_ntor_intro_cell_keys.enc_key));
+ printf("%s\n", buf);
+ /* Send MAC_KEY */
+ base16_encode(buf, sizeof(buf),
+ (const char*)hs_ntor_intro_cell_keys.mac_key,
+ sizeof(hs_ntor_intro_cell_keys.mac_key));
+ printf("%s\n", buf);
+ /* Send AUTH_MAC */
+ base16_encode(buf, sizeof(buf),
+ (const char*)hs_ntor_rend_cell_keys.rend_cell_auth_mac,
+ sizeof(hs_ntor_rend_cell_keys.rend_cell_auth_mac));
+ printf("%s\n", buf);
+ /* Send NTOR_KEY_SEED */
+ base16_encode(buf, sizeof(buf),
+ (const char*)hs_ntor_rend_cell_keys.ntor_key_seed,
+ sizeof(hs_ntor_rend_cell_keys.ntor_key_seed));
+ printf("%s\n", buf);
+ /* Send service ephemeral pubkey (Y) */
+ base16_encode(buf, sizeof(buf),
+ (const char*)service_ephemeral_rend_keypair.pubkey.public_key,
+ sizeof(service_ephemeral_rend_keypair.pubkey.public_key));
+ printf("%s\n", buf);
+
+ done:
+ return retval;
+}
+
+/** The final step of the ntor protocol, the client computes and returns the
+ * rendezvous key material. */
+static int
+client2(int argc, char **argv)
+{
+ int retval;
+
+ /* Inputs */
+ curve25519_public_key_t intro_enc_pubkey;
+ ed25519_public_key_t intro_auth_pubkey;
+ curve25519_keypair_t client_ephemeral_enc_keypair;
+ curve25519_public_key_t service_ephemeral_rend_pubkey;
+ uint8_t subcredential[DIGEST256_LEN];
+
+ /* Output */
+ hs_ntor_rend_cell_keys_t hs_ntor_rend_cell_keys;
+
+ char buf[256];
+
+ N_ARGS(7);
+ BASE16(2, intro_auth_pubkey.pubkey, ED25519_PUBKEY_LEN);
+ BASE16(3, client_ephemeral_enc_keypair.seckey.secret_key,
+ CURVE25519_SECKEY_LEN);
+ BASE16(4, intro_enc_pubkey.public_key, CURVE25519_PUBKEY_LEN);
+ BASE16(5, service_ephemeral_rend_pubkey.public_key, CURVE25519_PUBKEY_LEN);
+ BASE16(6, subcredential, DIGEST256_LEN);
+
+ /* Generate keypair */
+ curve25519_public_key_generate(&client_ephemeral_enc_keypair.pubkey,
+ &client_ephemeral_enc_keypair.seckey);
+
+ /* Get RENDEZVOUS1 keys */
+ retval = hs_ntor_client_get_rendezvous1_keys(&intro_auth_pubkey,
+ &client_ephemeral_enc_keypair,
+ &intro_enc_pubkey,
+ &service_ephemeral_rend_pubkey,
+ &hs_ntor_rend_cell_keys);
+ if (retval < 0) {
+ goto done;
+ }
+
+ /* Send AUTH_MAC */
+ base16_encode(buf, sizeof(buf),
+ (const char*)hs_ntor_rend_cell_keys.rend_cell_auth_mac,
+ sizeof(hs_ntor_rend_cell_keys.rend_cell_auth_mac));
+ printf("%s\n", buf);
+ /* Send NTOR_KEY_SEED */
+ base16_encode(buf, sizeof(buf),
+ (const char*)hs_ntor_rend_cell_keys.ntor_key_seed,
+ sizeof(hs_ntor_rend_cell_keys.ntor_key_seed));
+ printf("%s\n", buf);
+
+ done:
+ return 1;
+}
+
+/** Perform a different part of the protocol depdning on the argv used. */
+int
+main(int argc, char **argv)
+{
+ if (argc < 2) {
+ fprintf(stderr, "I need arguments. Read source for more info.\n");
+ return 1;
+ }
+
+ curve25519_init();
+ if (!strcmp(argv[1], "client1")) {
+ return client1(argc, argv);
+ } else if (!strcmp(argv[1], "server1")) {
+ return server1(argc, argv);
+ } else if (!strcmp(argv[1], "client2")) {
+ return client2(argc, argv);
+ } else {
+ fprintf(stderr, "What's a %s?\n", argv[1]);
+ return 1;
+ }
+}
+
diff --git a/src/test/test_hs_service.c b/src/test/test_hs_service.c
index 039d727cea..3084c6b958 100644
--- a/src/test/test_hs_service.c
+++ b/src/test/test_hs_service.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Tor Project, Inc. */
+/* Copyright (c) 2016-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -6,104 +6,1527 @@
* \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_service.h"
+#include "hs_common.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;
+}
+
+/* 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_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;
+
+ /* Now make dummy circuit */
+ {
+ or_circ = origin_circuit_new();
+
+ 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 */
+ {
+ 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. */
+
+ 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();
+}
-/** We simulate the creation of an outgoing ESTABLISH_INTRO cell, and then we
- * parse it from the receiver side. */
+/** Test that we can create intro point objects, index them and find them */
static void
-test_gen_establish_intro_cell(void *arg)
+test_service_intro_point(void *arg)
{
+ hs_service_t *service = NULL;
+ hs_service_intro_point_t *ip = NULL;
+
(void) arg;
- ssize_t retval;
- uint8_t circuit_key_material[DIGEST_LEN] = {0};
- uint8_t buf[RELAY_PAYLOAD_SIZE];
- hs_cell_establish_intro_t *cell_out = NULL;
- hs_cell_establish_intro_t *cell_in = NULL;
- crypto_rand((char *) circuit_key_material, sizeof(circuit_key_material));
+ /* 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 add 5 seconds because
+ * there could be a gap between setting now and the time taken in
+ * service_intro_point_new. On ARM, it can be surprisingly slow... */
+ tt_u64_op(ip->time_to_expire, OP_GE,
+ now + INTRO_POINT_LIFETIME_MIN_SECONDS + 5);
+ tt_u64_op(ip->time_to_expire, OP_LE,
+ now + INTRO_POINT_LIFETIME_MAX_SECONDS + 5);
+ 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);
+ }
+
+ /* Test functions that uses a service intropoints map with that previously
+ * created object (non legacy). */
+ {
+ 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));
+
+ /* 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:
+ /* 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);
+}
+
+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;
+}
+
+static void
+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;
+
+ 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);
+
+ /* 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;
- /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we
- attempt to parse it. */
+ /* 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() */
{
- cell_out = generate_establish_intro_cell(circuit_key_material,
- sizeof(circuit_key_material));
- tt_assert(cell_out);
+ 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);
+ }
- retval = get_establish_intro_payload(buf, sizeof(buf), cell_out);
- tt_int_op(retval, >=, 0);
+ /* 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);
}
- /* Parse it as the receiver */
+ /* Testing intro_point_should_expire(). */
{
- ssize_t parse_result = hs_cell_establish_intro_parse(&cell_in,
- buf, sizeof(buf));
- tt_int_op(parse_result, >=, 0);
+ 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);
- retval = verify_establish_intro_cell(cell_in,
- circuit_key_material,
- sizeof(circuit_key_material));
- tt_int_op(retval, >=, 0);
+ /* 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:
- hs_cell_establish_intro_free(cell_out);
- hs_cell_establish_intro_free(cell_in);
+ /* This will free the service and all objects associated to it. */
+ hs_service_free_all();
+ UNMOCK(node_get_by_id);
}
-/* 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;
+/** 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);
+ 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();
+
+ done:
+ circuit_free(TO_CIRCUIT(circ));
+ hs_free_all();
+ UNMOCK(circuit_mark_for_close_);
+ UNMOCK(relay_send_command_from_edge_);
+}
+
+/** Test the operations we do on a circuit after we learn that we successfuly
+ * established an intro point on it */
+static void
+test_intro_established(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);
+
+ circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO,
+ flags);
+ tt_assert(circ);
+
+ /* 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_);
+}
+
+/** 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;
+
+ 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_);
}
-/** We simulate a failure to create an ESTABLISH_INTRO cell */
+/** Test sending and receiving introduce2 cells */
static void
-test_gen_establish_intro_cell_bad(void *arg)
+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_cell_establish_intro_t *cell = NULL;
- uint8_t circuit_key_material[DIGEST_LEN] = {0};
- MOCK(ed25519_sign_prefixed, mock_ed25519_sign_prefixed);
+ 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));
- crypto_rand((char *) circuit_key_material, sizeof(circuit_key_material));
+ 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);
- /* 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.");
+ 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. */
+ {
+ 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;
+
+ (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);
+ }
+
+ done:
+ hs_circuitmap_remove_circuit(TO_CIRCUIT(circ));
+ circuit_free(TO_CIRCUIT(circ));
+ hs_free_all();
+ UNMOCK(circuit_mark_for_close_);
+}
+
+/** 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;
+
+ (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);
+
+ /* 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);
+
+ /* 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);
+
+ /* 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 building descriptors: picking intro points, setting up their link
+ * specifiers, etc. */
+static void
+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;
+
+ 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_assert(!cell);
+ 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:
- hs_cell_establish_intro_free(cell);
- UNMOCK(ed25519_sign_prefixed);
+ 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;
+ 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;
+
+ (void) arg;
+
+ MOCK(relay_send_command_from_edge_, mock_relay_send_rendezvous1);
+
+ {
+ /* 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);
+ }
+
+ /* 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 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 },
+ { "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 },
+ { "upload_descriptors", test_upload_descriptors, TT_FORK,
+ NULL, NULL },
+ { "revision_counter_state", test_revision_counter_state, TT_FORK,
NULL, NULL },
- { "gen_establish_intro_cell_bad", test_gen_establish_intro_cell_bad, 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 810b03c93d..d502bdddb1 100644
--- a/src/test/test_introduce.c
+++ b/src/test/test_introduce.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Tor Project, Inc. */
+/* Copyright (c) 2012-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -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 95657349c6..79d7bac902 100644
--- a/src/test/test_keypin.c
+++ b/src/test/test_keypin.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Tor Project, Inc. */
+/* Copyright (c) 2014-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -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 467bba3a64..422d419078 100644
--- a/src/test/test_link_handshake.c
+++ b/src/test/test_link_handshake.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Tor Project, Inc. */
+/* Copyright (c) 2014-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -10,13 +10,6 @@
#include "compat.h"
-/* Some versions of OpenSSL declare SSL_get_selected_srtp_profile twice in
- * srtp.h. Suppress the GCC warning so we can build with -Wredundant-decl. */
-DISABLE_GCC_WARNING(redundant-decls)
-#include <openssl/x509.h>
-#include <openssl/ssl.h>
-ENABLE_GCC_WARNING(redundant-decls)
-
#include "or.h"
#include "config.h"
#include "connection.h"
@@ -143,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
@@ -162,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);
}
@@ -247,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);
@@ -257,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);
}
@@ -285,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(
@@ -383,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 {
@@ -459,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);
@@ -472,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:
@@ -492,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:
@@ -524,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:
@@ -550,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); \
} \
@@ -610,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)
@@ -693,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:
;
}
@@ -704,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();
@@ -808,19 +801,14 @@ CERTS_FAIL(expired_rsa_id, /* both */
certs_cell_cert_t *cert = certs_cell_get_certs(d->ccell, 1);
const tor_x509_cert_t *idc;
tor_tls_get_my_certs(1, NULL, &idc);
- X509 *newc = X509_dup(idc->cert);
+ tor_x509_cert_t *newc;
time_t new_end = time(NULL) - 86400 * 10;
- X509_time_adj(X509_get_notAfter(newc), 0, &new_end);
- EVP_PKEY *pk = crypto_pk_get_evp_pkey_(d->key2, 1);
- tt_assert(X509_sign(newc, pk, EVP_sha1()));
- int len = i2d_X509(newc, NULL);
- certs_cell_cert_setlen_body(cert, len);
- uint8_t *body = certs_cell_cert_getarray_body(cert);
- int len2 = i2d_X509(newc, &body);
- tt_int_op(len, ==, len2);
+ newc = tor_x509_cert_replace_expiration(idc, new_end, d->key2);
+ certs_cell_cert_setlen_body(cert, newc->encoded_len);
+ memcpy(certs_cell_cert_getarray_body(cert),
+ newc->encoded, newc->encoded_len);
REENCODE();
- X509_free(newc);
- EVP_PKEY_free(pk);
+ tor_x509_cert_free(newc);
})
CERTS_FAIL(expired_ed_id, /* ed25519 */
{
@@ -917,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);
@@ -986,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);
@@ -1001,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:
@@ -1022,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:
;
}
@@ -1041,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:
;
}
@@ -1057,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:
;
}
@@ -1072,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:
;
}
@@ -1089,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); \
} \
@@ -1209,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);
@@ -1272,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;
@@ -1297,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:
@@ -1371,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); \
} \
@@ -1402,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();
@@ -1437,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 15471e46d0..e373158e34 100644
--- a/src/test/test_logging.c
+++ b/src/test/test_logging.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Tor Project, Inc. */
+/* Copyright (c) 2013-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -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 2ae605b8db..4f0ecd778b 100644
--- a/src/test/test_microdesc.c
+++ b/src/test/test_microdesc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2016, The Tor Project, Inc. */
+/* Copyright (c) 2010-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -14,18 +14,12 @@
#include "test.h"
-DISABLE_GCC_WARNING(redundant-decls)
-#include <openssl/rsa.h>
-#include <openssl/bn.h>
-#include <openssl/pem.h>
-ENABLE_GCC_WARNING(redundant-decls)
-
#ifdef _WIN32
/* For mkdir() */
#include <direct.h>
#else
#include <dirent.h>
-#endif
+#endif /* defined(_WIN32) */
static const char test_md1[] =
"onion-key\n"
@@ -470,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);
@@ -478,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));
@@ -829,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");
@@ -844,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 d58f8a7fca..a873003d72 100644
--- a/src/test/test_nodelist.c
+++ b/src/test/test_nodelist.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2016, The Tor Project, Inc. */
+/* Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -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_ntor_cl.c b/src/test/test_ntor_cl.c
index a560e5fc5e..d0eea85d6f 100644
--- a/src/test/test_ntor_cl.c
+++ b/src/test/test_ntor_cl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Tor Project, Inc. */
+/* Copyright (c) 2012-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_oom.c b/src/test/test_oom.c
index 0f97972032..cf28690a28 100644
--- a/src/test/test_oom.c
+++ b/src/test/test_oom.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Tor Project, Inc. */
+/* Copyright (c) 2014-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/* Unit tests for OOM handling logic */
@@ -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 db06625116..e72fcf5de9 100644
--- a/src/test/test_oos.c
+++ b/src/test/test_oos.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Tor Project, Inc. */
+/* Copyright (c) 2016-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/* Unit tests for OOS handler */
@@ -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 d5782e9ec0..62732cabf7 100644
--- a/src/test/test_options.c
+++ b/src/test/test_options.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONFIG_PRIVATE
@@ -105,11 +105,71 @@ clear_log_messages(void)
"EDE6D711294FADF8E7951F4DE6CA56B58 194.109.206.212:80 7EA6 EAD6 FD83" \
" 083C 538F 4403 8BBF A077 587D D755\n"
+static int
+test_options_checklog(const char *configuration, int expect_log_severity,
+ const char *expect_log)
+{
+ int found = 0, ret = -1;
+ char *actual_log = NULL;
+
+ if (messages) {
+ SMARTLIST_FOREACH_BEGIN(messages, logmsg_t *, m) {
+ if (m->severity == expect_log_severity &&
+ strstr(m->msg, expect_log)) {
+ found = 1;
+ break;
+ }
+ } SMARTLIST_FOREACH_END(m);
+ }
+ if (!found) {
+ actual_log = dump_logs();
+ TT_DIE(("Expected log message [%s] %s from <%s>, but got <%s>.",
+ log_level_to_string(expect_log_severity), expect_log,
+ configuration, actual_log));
+ }
+ ret = 0;
+
+ done:
+ tor_free(actual_log);
+ return ret;
+}
+
+static int
+test_options_checkmsgs(const char *configuration,
+ const char *expect_errmsg,
+ int expect_log_severity,
+ const char *expect_log,
+ char *msg)
+{
+ if (expect_errmsg && !msg) {
+ TT_DIE(("Expected error message <%s> from <%s>, but got none.",
+ expect_errmsg, configuration));
+ } else if (expect_errmsg && !strstr(msg, expect_errmsg)) {
+ TT_DIE(("Expected error message <%s> from <%s>, but got <%s>.",
+ expect_errmsg, configuration, msg));
+ } else if (!expect_errmsg && msg) {
+ TT_DIE(("Expected no error message from <%s> but got <%s>.",
+ configuration, msg));
+ }
+ if (expect_log) {
+ return test_options_checklog(configuration, expect_log_severity,
+ expect_log);
+ }
+ return 0;
+
+ done:
+ return -1;
+}
+
+/* Which phases of config parsing/validation to check for messages/logs */
+enum { PH_GETLINES, PH_ASSIGN, PH_VALIDATE };
+
static void
test_options_validate_impl(const char *configuration,
const char *expect_errmsg,
int expect_log_severity,
- const char *expect_log)
+ const char *expect_log,
+ int phase)
{
or_options_t *opt=NULL;
or_options_t *dflt;
@@ -120,43 +180,34 @@ test_options_validate_impl(const char *configuration,
setup_options(opt, dflt);
r = config_get_lines(configuration, &cl, 1);
- tt_int_op(r, OP_EQ, 0);
+ if (phase == PH_GETLINES) {
+ if (test_options_checkmsgs(configuration, expect_errmsg,
+ expect_log_severity,
+ expect_log, msg))
+ goto done;
+ }
+ if (r)
+ goto done;
r = config_assign(&options_format, opt, cl, 0, &msg);
- tt_int_op(r, OP_EQ, 0);
-
- r = options_validate(NULL, opt, dflt, 0, &msg);
- if (expect_errmsg && !msg) {
- TT_DIE(("Expected error message <%s> from <%s>, but got none.",
- expect_errmsg, configuration));
- } else if (expect_errmsg && !strstr(msg, expect_errmsg)) {
- TT_DIE(("Expected error message <%s> from <%s>, but got <%s>.",
- expect_errmsg, configuration, msg));
- } else if (!expect_errmsg && msg) {
- TT_DIE(("Expected no error message from <%s> but got <%s>.",
- configuration, msg));
+ if (phase == PH_ASSIGN) {
+ if (test_options_checkmsgs(configuration, expect_errmsg,
+ expect_log_severity,
+ expect_log, msg))
+ goto done;
}
tt_int_op((r == 0), OP_EQ, (msg == NULL));
+ if (r)
+ goto done;
- if (expect_log) {
- int found = 0;
- if (messages) {
- SMARTLIST_FOREACH_BEGIN(messages, logmsg_t *, m) {
- if (m->severity == expect_log_severity &&
- strstr(m->msg, expect_log)) {
- found = 1;
- break;
- }
- } SMARTLIST_FOREACH_END(m);
- }
- if (!found) {
- tor_free(msg);
- msg = dump_logs();
- TT_DIE(("Expected log message [%s] %s from <%s>, but got <%s>.",
- log_level_to_string(expect_log_severity), expect_log,
- configuration, msg));
- }
+ r = options_validate(NULL, opt, dflt, 0, &msg);
+ if (phase == PH_VALIDATE) {
+ if (test_options_checkmsgs(configuration, expect_errmsg,
+ expect_log_severity,
+ expect_log, msg))
+ goto done;
}
+ tt_int_op((r == 0), OP_EQ, (msg == NULL));
done:
escaped(NULL);
@@ -168,14 +219,14 @@ test_options_validate_impl(const char *configuration,
clear_log_messages();
}
-#define WANT_ERR(config, msg) \
- test_options_validate_impl((config), (msg), 0, NULL)
-#define WANT_LOG(config, severity, msg) \
- test_options_validate_impl((config), NULL, (severity), (msg))
-#define WANT_ERR_LOG(config, msg, severity, logmsg) \
- test_options_validate_impl((config), (msg), (severity), (logmsg))
-#define OK(config) \
- test_options_validate_impl((config), NULL, 0, NULL)
+#define WANT_ERR(config, msg, ph) \
+ test_options_validate_impl((config), (msg), 0, NULL, (ph))
+#define WANT_LOG(config, severity, msg, ph) \
+ test_options_validate_impl((config), NULL, (severity), (msg), (ph))
+#define WANT_ERR_LOG(config, msg, severity, logmsg, ph) \
+ test_options_validate_impl((config), (msg), (severity), (logmsg), (ph))
+#define OK(config, ph) \
+ test_options_validate_impl((config), NULL, 0, NULL, (ph))
static void
test_options_validate(void *arg)
@@ -184,21 +235,39 @@ test_options_validate(void *arg)
setup_log_callback();
sandbox_disable_getaddrinfo_cache();
- WANT_ERR("ExtORPort 500000", "Invalid ExtORPort");
+ WANT_ERR("ExtORPort 500000", "Invalid ExtORPort", PH_VALIDATE);
WANT_ERR_LOG("ServerTransportOptions trebuchet",
"ServerTransportOptions did not parse",
- LOG_WARN, "Too few arguments");
- OK("ServerTransportOptions trebuchet sling=snappy");
- OK("ServerTransportOptions trebuchet sling=");
+ LOG_WARN, "Too few arguments", PH_VALIDATE);
+ OK("ServerTransportOptions trebuchet sling=snappy", PH_VALIDATE);
+ OK("ServerTransportOptions trebuchet sling=", PH_VALIDATE);
WANT_ERR_LOG("ServerTransportOptions trebuchet slingsnappy",
"ServerTransportOptions did not parse",
- LOG_WARN, "\"slingsnappy\" is not a k=v");
+ LOG_WARN, "\"slingsnappy\" is not a k=v", PH_VALIDATE);
WANT_ERR("DirPort 8080\nDirCache 0",
- "DirPort configured but DirCache disabled.");
+ "DirPort configured but DirCache disabled.", PH_VALIDATE);
WANT_ERR("BridgeRelay 1\nDirCache 0",
- "We're a bridge but DirCache is disabled.");
+ "We're a bridge but DirCache is disabled.", PH_VALIDATE);
+
+ WANT_ERR_LOG("HeartbeatPeriod 21 snarks",
+ "Interval 'HeartbeatPeriod 21 snarks' is malformed or"
+ " out of bounds.", LOG_WARN, "Unknown unit 'snarks'.",
+ PH_ASSIGN);
+ WANT_ERR_LOG("LogTimeGranularity 21 snarks",
+ "Msec interval 'LogTimeGranularity 21 snarks' is malformed or"
+ " out of bounds.", LOG_WARN, "Unknown unit 'snarks'.",
+ PH_ASSIGN);
+ OK("HeartbeatPeriod 1 hour", PH_VALIDATE);
+ OK("LogTimeGranularity 100 milliseconds", PH_VALIDATE);
+
+ WANT_LOG("ControlSocket \"string with trailing garbage\" bogus", LOG_WARN,
+ "Error while parsing configuration: "
+ "Excess data after quoted string", PH_GETLINES);
+ WANT_LOG("ControlSocket \"bogus escape \\@\"", LOG_WARN,
+ "Error while parsing configuration: "
+ "Invalid escape sequence in quoted string", PH_GETLINES);
close_temp_logs();
clear_log_messages();
@@ -213,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;
@@ -230,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);
@@ -253,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);
@@ -276,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);
@@ -329,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;
@@ -354,25 +423,31 @@ get_options_test_data(const char *conf)
result->opt = options_new();
result->old_opt = options_new();
result->def_opt = options_new();
+
+ // XXX: Really, all of these options should be set to defaults
+ // with options_init(), but about a dozen tests break when I do that.
+ // Being kinda lame and just fixing the immedate breakage for now..
+ 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);
@@ -402,7 +477,7 @@ test_options_validate__uname_for_server(void *ignored)
(void)ignored;
char *msg;
options_test_data_t *tdata = get_options_test_data(
- "ORListenAddress 127.0.0.1:5555");
+ "ORPort 127.0.0.1:5555");
setup_capture_of_logs(LOG_WARN);
MOCK(get_uname, fixed_get_uname);
@@ -432,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:
@@ -453,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);
@@ -516,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);
@@ -536,7 +614,7 @@ test_options_validate__contactinfo(void *ignored)
int ret;
char *msg;
options_test_data_t *tdata = get_options_test_data(
- "ORListenAddress 127.0.0.1:5555\nORPort 955");
+ "ORPort 127.0.0.1:5555");
setup_capture_of_logs(LOG_DEBUG);
tdata->opt->ContactInfo = NULL;
@@ -549,7 +627,7 @@ test_options_validate__contactinfo(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("ORListenAddress 127.0.0.1:5555\nORPort 955\n"
+ tdata = get_options_test_data("ORPort 127.0.0.1:5555\n"
"ContactInfo hella@example.org");
mock_clean_saved_logs();
ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
@@ -582,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("");
@@ -592,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("");
@@ -601,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("");
@@ -609,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("");
@@ -617,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("");
@@ -626,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;
@@ -672,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);
@@ -689,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);
@@ -702,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);
@@ -716,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");
@@ -731,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");
@@ -747,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)"
@@ -761,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 "
@@ -775,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 "
@@ -788,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 "
@@ -802,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"
@@ -817,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"
@@ -830,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)"
@@ -844,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,
@@ -858,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,
@@ -872,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,
@@ -886,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,
@@ -899,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);
@@ -914,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);
@@ -933,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); */
@@ -957,8 +1005,7 @@ test_options_validate__relay_with_hidden_services(void *ignored)
char *msg;
setup_capture_of_logs(LOG_DEBUG);
options_test_data_t *tdata = get_options_test_data(
- "ORListenAddress 127.0.0.1:5555\n"
- "ORPort 955\n"
+ "ORPort 127.0.0.1:5555\n"
"HiddenServiceDir "
"/Library/Tor/var/lib/tor/hidden_service/\n"
"HiddenServicePort 80 127.0.0.1:8080\n"
@@ -1028,8 +1075,8 @@ test_options_validate__transproxy(void *ignored)
#else
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 or TransListenAddress.");
-#endif
+ "any valid TransPort.");
+#endif /* !defined(OpenBSD) && !defined( DARWIN ) */
tor_free(msg);
// Test tproxy trans proxy
@@ -1043,8 +1090,8 @@ test_options_validate__transproxy(void *ignored)
#else
tt_int_op(tdata->opt->TransProxyType_parsed, OP_EQ, TPT_TPROXY);
tt_str_op(msg, OP_EQ, "Cannot use TransProxyType without any valid "
- "TransPort or TransListenAddress.");
-#endif
+ "TransPort.");
+#endif /* !defined(__linux__) */
tor_free(msg);
// Test ipfw trans proxy
@@ -1059,8 +1106,8 @@ test_options_validate__transproxy(void *ignored)
#else
tt_int_op(tdata->opt->TransProxyType_parsed, OP_EQ, TPT_IPFW);
tt_str_op(msg, OP_EQ, "Cannot use TransProxyType without any valid "
- "TransPort or TransListenAddress.");
-#endif
+ "TransPort.");
+#endif /* !defined(KERNEL_MAY_SUPPORT_IPFW) */
tor_free(msg);
// Test unknown trans proxy
@@ -1080,47 +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 and TransListenAddress are disabled in "
- "this build.");
+ 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);
@@ -1185,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);
@@ -1198,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);
@@ -1218,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;
@@ -1268,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);
@@ -1288,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);
@@ -1297,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);
@@ -1313,54 +1302,6 @@ test_options_validate__node_families(void *ignored)
}
static void
-test_options_validate__tlsec(void *ignored)
-{
- (void)ignored;
- int ret;
- char *msg;
- setup_capture_of_logs(LOG_DEBUG);
- options_test_data_t *tdata = get_options_test_data(
- "TLSECGroup ed25519\n"
- "SchedulerHighWaterMark__ 42\n"
- "SchedulerLowWaterMark__ 10\n");
-
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
- expect_log_msg("Unrecognized TLSECGroup: Falling back to the default.\n");
- tt_assert(!tdata->opt->TLSECGroup);
- tor_free(msg);
-
- free_options_test_data(tdata);
- tdata = get_options_test_data("TLSECGroup P224\n"
- "SchedulerHighWaterMark__ 42\n"
- "SchedulerLowWaterMark__ 10\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_no_log_msg(
- "Unrecognized TLSECGroup: Falling back to the default.\n");
- tt_assert(tdata->opt->TLSECGroup);
- tor_free(msg);
-
- free_options_test_data(tdata);
- tdata = get_options_test_data("TLSECGroup P256\n"
- "SchedulerHighWaterMark__ 42\n"
- "SchedulerLowWaterMark__ 10\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_no_log_msg(
- "Unrecognized TLSECGroup: Falling back to the default.\n");
- tt_assert(tdata->opt->TLSECGroup);
- tor_free(msg);
-
- done:
- teardown_capture_of_logs();
- free_options_test_data(tdata);
- tor_free(msg);
-}
-
-static void
test_options_validate__token_bucket(void *ignored)
{
(void)ignored;
@@ -1396,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);
@@ -1420,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);
@@ -1432,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);
@@ -1454,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);
@@ -1464,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);
@@ -1488,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);
@@ -1503,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);
@@ -1518,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);
@@ -1543,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);
@@ -1555,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);
@@ -1567,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);
@@ -1590,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);
@@ -1603,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);
@@ -1617,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);
@@ -1632,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);
@@ -1647,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);
@@ -1671,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);
@@ -1691,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);
@@ -1707,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);
@@ -1726,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);
@@ -1742,12 +1643,9 @@ test_options_validate__reachable_addresses(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data("ReachableAddresses *:82\n"
- "ORListenAddress 127.0.0.1:5555\n"
- "ORPort 955\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);
@@ -1756,12 +1654,9 @@ test_options_validate__reachable_addresses(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data("ReachableORAddresses *:82\n"
- "ORListenAddress 127.0.0.1:5555\n"
- "ORPort 955\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);
@@ -1770,12 +1665,9 @@ test_options_validate__reachable_addresses(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data("ReachableDirAddresses *:82\n"
- "ORListenAddress 127.0.0.1:5555\n"
- "ORPort 955\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);
@@ -1784,12 +1676,9 @@ test_options_validate__reachable_addresses(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data("ClientUseIPv4 0\n"
- "ORListenAddress 127.0.0.1:5555\n"
- "ORPort 955\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);
@@ -1885,12 +1774,9 @@ test_options_validate__use_bridges(void *ignored)
options_test_data_t *tdata = get_options_test_data(
"UseBridges 1\n"
"ClientUseIPv4 1\n"
- "ORListenAddress 127.0.0.1:5555\n"
- "ORPort 955\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);
@@ -1901,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);
@@ -1916,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);
@@ -1978,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);
@@ -1992,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);
@@ -2008,56 +1886,6 @@ test_options_validate__entry_nodes(void *ignored)
}
static void
-test_options_validate__invalid_nodes(void *ignored)
-{
- (void)ignored;
- int ret;
- char *msg;
- options_test_data_t *tdata = get_options_test_data(
- "AllowInvalidNodes something_stupid\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n"
- "SchedulerHighWaterMark__ 42\n"
- "SchedulerLowWaterMark__ 10\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,
- "Unrecognized value 'something_stupid' in AllowInvalidNodes");
- tor_free(msg);
-
- free_options_test_data(tdata);
- tdata = get_options_test_data("AllowInvalidNodes entry, middle, exit\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n"
- "SchedulerHighWaterMark__ 42\n"
- "SchedulerLowWaterMark__ 10\n");
-
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
- tt_int_op(tdata->opt->AllowInvalid_, OP_EQ, ALLOW_INVALID_ENTRY |
- ALLOW_INVALID_EXIT | ALLOW_INVALID_MIDDLE);
- tor_free(msg);
-
- free_options_test_data(tdata);
- tdata = get_options_test_data("AllowInvalidNodes introduction, rendezvous\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n"
- "SchedulerHighWaterMark__ 42\n"
- "SchedulerLowWaterMark__ 10\n");
-
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
- tt_int_op(tdata->opt->AllowInvalid_, OP_EQ, ALLOW_INVALID_INTRODUCTION |
- ALLOW_INVALID_RENDEZVOUS);
- tor_free(msg);
-
- done:
- free_options_test_data(tdata);
- tor_free(msg);
-}
-
-static void
test_options_validate__safe_logging(void *ignored)
{
(void)ignored;
@@ -2065,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);
@@ -2077,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);
@@ -2089,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);
@@ -2101,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);
@@ -2113,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);
@@ -2260,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);
@@ -2327,30 +2146,6 @@ test_options_validate__hidserv(void *ignored)
}
static void
-test_options_validate__predicted_ports(void *ignored)
-{
- (void)ignored;
- int ret;
- char *msg;
- setup_capture_of_logs(LOG_WARN);
-
- options_test_data_t *tdata = get_options_test_data(
- "PredictedPortsRelevanceTime 100000000\n"
- TEST_OPTIONS_DEFAULT_VALUES);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, 0);
- expect_log_msg("PredictedPortsRelevanceTime is too "
- "large; clipping to 3600s.\n");
- tt_int_op(tdata->opt->PredictedPortsRelevanceTime, OP_EQ, 3600);
-
- done:
- teardown_capture_of_logs();
- policies_free_all();
- free_options_test_data(tdata);
- tor_free(msg);
-}
-
-static void
test_options_validate__path_bias(void *ignored)
{
(void)ignored;
@@ -2496,8 +2291,7 @@ test_options_validate__bandwidth(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ORListenAddress 127.0.0.1:5555\n"
- "ORPort 955\n"
+ "ORPort 127.0.0.1:5555\n"
"BandwidthRate 1\n"
);
ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
@@ -2508,8 +2302,7 @@ test_options_validate__bandwidth(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ORListenAddress 127.0.0.1:5555\n"
- "ORPort 955\n"
+ "ORPort 127.0.0.1:5555\n"
"BandwidthRate 76800\n"
"MaxAdvertisedBandwidth 30000\n"
);
@@ -2521,8 +2314,7 @@ test_options_validate__bandwidth(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ORListenAddress 127.0.0.1:5555\n"
- "ORPort 955\n"
+ "ORPort 127.0.0.1:5555\n"
"BandwidthRate 76800\n"
"RelayBandwidthRate 1\n"
"MaxAdvertisedBandwidth 38400\n"
@@ -2535,8 +2327,7 @@ test_options_validate__bandwidth(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ORListenAddress 127.0.0.1:5555\n"
- "ORPort 955\n"
+ "ORPort 127.0.0.1:5555\n"
"BandwidthRate 76800\n"
"BandwidthBurst 76800\n"
"RelayBandwidthRate 76800\n"
@@ -2974,8 +2765,7 @@ test_options_validate__accounting(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data(
TEST_OPTIONS_DEFAULT_VALUES
- "ORListenAddress 127.0.0.1:5555\n"
- "ORPort 955\n"
+ "ORPort 127.0.0.1:5555\n"
"BandwidthRate 76800\n"
"BandwidthBurst 76800\n"
"MaxAdvertisedBandwidth 38400\n"
@@ -3560,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
@@ -3609,8 +3399,7 @@ test_options_validate__families(void *ignored)
tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
"MyFamily home\n"
"BridgeRelay 1\n"
- "ORListenAddress 127.0.0.1:5555\n"
- "ORPort 955\n"
+ "ORPort 127.0.0.1:5555\n"
"BandwidthRate 51300\n"
"BandwidthBurst 51300\n"
"MaxAdvertisedBandwidth 25700\n"
@@ -3839,8 +3628,7 @@ test_options_validate__transport(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
"ServerTransportPlugin foo exec bar\n"
- "ORListenAddress 127.0.0.1:5555\n"
- "ORPort 955\n"
+ "ORPort 127.0.0.1:5555\n"
"BandwidthRate 76900\n"
"BandwidthBurst 76900\n"
"MaxAdvertisedBandwidth 38500\n"
@@ -3882,8 +3670,7 @@ test_options_validate__transport(void *ignored)
tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
"ServerTransportListenAddr foo 127.0.0.42:55\n"
"ServerTransportPlugin foo exec bar\n"
- "ORListenAddress 127.0.0.1:5555\n"
- "ORPort 955\n"
+ "ORPort 127.0.0.1:5555\n"
"BandwidthRate 76900\n"
"BandwidthBurst 76900\n"
"MaxAdvertisedBandwidth 38500\n"
@@ -4240,48 +4027,6 @@ test_options_validate__virtual_addr(void *ignored)
}
static void
-test_options_validate__exits(void *ignored)
-{
- (void)ignored;
- int ret;
- char *msg;
- options_test_data_t *tdata = NULL;
- setup_capture_of_logs(LOG_WARN);
-
- free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "AllowSingleHopExits 1"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, 0);
- expect_log_msg("You have set AllowSingleHopExits; "
- "now your relay will allow others to make one-hop exits. However,"
- " since by default most clients avoid relays that set this option,"
- " most clients will ignore you.\n");
- tor_free(msg);
-
- free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "AllowSingleHopExits 1\n"
- VALID_DIR_AUTH
- );
- mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, 0);
- expect_no_log_msg("You have set AllowSingleHopExits; "
- "now your relay will allow others to make one-hop exits. However,"
- " since by default most clients avoid relays that set this option,"
- " most clients will ignore you.\n");
- tor_free(msg);
-
- done:
- policies_free_all();
- teardown_capture_of_logs();
- free_options_test_data(tdata);
- tor_free(msg);
-}
-
-static void
test_options_validate__testing_options(void *ignored)
{
(void)ignored;
@@ -4517,9 +4262,7 @@ 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(tlsec),
LOCAL_VALIDATE_TEST(token_bucket),
LOCAL_VALIDATE_TEST(recommended_packages),
LOCAL_VALIDATE_TEST(fetch_dir),
@@ -4530,12 +4273,10 @@ struct testcase_t options_tests[] = {
LOCAL_VALIDATE_TEST(reachable_addresses),
LOCAL_VALIDATE_TEST(use_bridges),
LOCAL_VALIDATE_TEST(entry_nodes),
- LOCAL_VALIDATE_TEST(invalid_nodes),
LOCAL_VALIDATE_TEST(safe_logging),
LOCAL_VALIDATE_TEST(publish_server_descriptor),
LOCAL_VALIDATE_TEST(testing),
LOCAL_VALIDATE_TEST(hidserv),
- LOCAL_VALIDATE_TEST(predicted_ports),
LOCAL_VALIDATE_TEST(path_bias),
LOCAL_VALIDATE_TEST(bandwidth),
LOCAL_VALIDATE_TEST(circuits),
@@ -4553,7 +4294,6 @@ struct testcase_t options_tests[] = {
LOCAL_VALIDATE_TEST(constrained_sockets),
LOCAL_VALIDATE_TEST(v3_auth),
LOCAL_VALIDATE_TEST(virtual_addr),
- LOCAL_VALIDATE_TEST(exits),
LOCAL_VALIDATE_TEST(testing_options),
LOCAL_VALIDATE_TEST(accel),
END_OF_TESTCASES /* */
diff --git a/src/test/test_policy.c b/src/test/test_policy.c
index e86d0f0274..83dca2d431 100644
--- a/src/test/test_policy.c
+++ b/src/test/test_policy.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Tor Project, Inc. */
+/* Copyright (c) 2013-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "or.h"
@@ -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_procmon.c b/src/test/test_procmon.c
index 9e63fc006d..5c52af8693 100644
--- a/src/test/test_procmon.c
+++ b/src/test/test_procmon.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2016, The Tor Project, Inc. */
+/* Copyright (c) 2010-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define PROCMON_PRIVATE
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 f00955d1b4..6ce54890d6 100644
--- a/src/test/test_protover.c
+++ b/src/test/test_protover.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Tor Project, Inc. */
+/* Copyright (c) 2016-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define PROTOVER_PRIVATE
@@ -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:
;
@@ -151,16 +151,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 f93019f1c4..07b6712ff9 100644
--- a/src/test/test_pt.c
+++ b/src/test/test_pt.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -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);
@@ -284,13 +284,13 @@ test_pt_get_extrainfo_string(void *arg)
}
#ifdef _WIN32
-#define STDIN_HANDLE HANDLE
+#define STDIN_HANDLE HANDLE*
#else
-#define STDIN_HANDLE FILE
+#define STDIN_HANDLE int
#endif
static smartlist_t *
-tor_get_lines_from_handle_replacement(STDIN_HANDLE *handle,
+tor_get_lines_from_handle_replacement(STDIN_HANDLE handle,
enum stream_status *stream_status_out)
{
static int times_called = 0;
@@ -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_pubsub.c b/src/test/test_pubsub.c
index 547d6c6b32..2f047d9f2c 100644
--- a/src/test/test_pubsub.c
+++ b/src/test/test_pubsub.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Tor Project, Inc. */
+/* Copyright (c) 2016-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/test_relay.c b/src/test/test_relay.c
index 4713c79ea5..e3489627a0 100644
--- a/src/test/test_relay.c
+++ b/src/test/test_relay.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Tor Project, Inc. */
+/* Copyright (c) 2014-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "or.h"
@@ -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_relaycell.c b/src/test/test_relaycell.c
index fb6748965a..eea1f5dc80 100644
--- a/src/test/test_relaycell.c
+++ b/src/test/test_relaycell.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Tor Project, Inc. */
+/* Copyright (c) 2014-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/* Unit tests for handling different kinds of relay cell */
diff --git a/src/test/test_rendcache.c b/src/test/test_rendcache.c
index 0d53c78817..9354dd0480 100644
--- a/src/test/test_rendcache.c
+++ b/src/test/test_rendcache.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2016, The Tor Project, Inc. */
+/* Copyright (c) 2010-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -11,7 +11,6 @@
#include "routerlist.h"
#include "config.h"
#include "hs_common.h"
-#include <openssl/rsa.h>
#include "rend_test_helpers.h"
#include "log_test_helpers.h"
@@ -22,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)
{
@@ -75,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);
@@ -963,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 e882bc6164..c379cafa7c 100644
--- a/src/test/test_replay.c
+++ b/src/test/test_replay.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Tor Project, Inc. */
+/* Copyright (c) 2012-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define REPLAYCACHE_PRIVATE
@@ -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 13059267ac..d8b72651a0 100644
--- a/src/test/test_routerkeys.c
+++ b/src/test/test_routerkeys.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -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 78f1cf16b7..3b0e943ce5 100644
--- a/src/test/test_routerlist.c
+++ b/src/test/test_routerlist.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Tor Project, Inc. */
+/* Copyright (c) 2014-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -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_rust.c b/src/test/test_rust.c
new file mode 100644
index 0000000000..6ad57d6fcb
--- /dev/null
+++ b/src/test/test_rust.c
@@ -0,0 +1,31 @@
+/* Copyright (c) 2017, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+#include "compat_rust.h"
+#include "test.h"
+#include "util.h"
+
+static void
+test_welcome_string(void *arg)
+{
+ (void)arg;
+ rust_str_t s = rust_welcome_string();
+ const char *c_str = rust_str_get(s);
+ tt_assert(c_str);
+ size_t len = strlen(c_str);
+#ifdef HAVE_RUST
+ tt_assert(len > 0);
+#else
+ tt_assert(len == 0);
+#endif
+
+ done:
+ rust_str_free(s);
+}
+
+struct testcase_t rust_tests[] = {
+ { "welcome_string", test_welcome_string, 0, NULL, NULL },
+ END_OF_TESTCASES
+};
+
diff --git a/src/test/test_rust.sh b/src/test/test_rust.sh
new file mode 100755
index 0000000000..d559f94ce0
--- /dev/null
+++ b/src/test/test_rust.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+# Test all the Rust crates we're using
+
+crates=tor_util
+
+exitcode=0
+
+for crate in $crates; do
+ cd "${abs_top_srcdir:-.}/src/rust/${crate}"
+ CARGO_TARGET_DIR="${abs_top_builddir}/src/rust/target" CARGO_HOME="${abs_top_builddir}/src/rust" "${CARGO:-cargo}" test ${CARGO_ONLINE-"--frozen"} || exitcode=1
+done
+
+exit $exitcode
diff --git a/src/test/test_scheduler.c b/src/test/test_scheduler.c
index 05ea8e86e8..d679d7cfe1 100644
--- a/src/test/test_scheduler.c
+++ b/src/test/test_scheduler.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Tor Project, Inc. */
+/* Copyright (c) 2014-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -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,41 +461,41 @@ 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;
@@ -394,14 +504,14 @@ test_scheduler_channel_states(void *arg)
/* 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 +525,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 +575,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 +613,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 +644,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 +662,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 +680,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 +751,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 +789,274 @@ 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_queue_heuristic(void *arg)
+test_scheduler_loop_kist(void *arg)
{
- time_t now = approx_time();
- uint64_t qh;
+ (void) arg;
+#ifndef HAVE_KIST_SUPPORT
+ return;
+#endif
+
+ channel_t *ch1 = new_fake_channel(), *ch2 = 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();
+ tt_int_op(1,==,1);
+
+ done:
+ /* Prep the channel so the free() function doesn't explode. */
+ ch1->state = ch2->state = CHANNEL_STATE_CLOSED;
+ ch1->registered = ch2->registered = 0;
+ channel_free(ch1);
+ channel_free(ch2);
+ 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_channel_states(void *arg)
+{
+ (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(NULL);
+#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(NULL);
+#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(NULL);
+#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(NULL);
+ 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(NULL, NULL);
+ 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(NULL, NULL);
+ 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(NULL, NULL);
+ 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(NULL, NULL);
+ 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..cac78baecf 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",
&current_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",
&current_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",
&current_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",
&current_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",
+ &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);
- 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",
&current_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",
&current_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",
&current_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,7 +864,7 @@ 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);
@@ -820,9 +909,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 +967,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 +986,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 +1024,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 +1044,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 +1058,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 +1111,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 +1141,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 +1166,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 +1206,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 +1216,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 +1242,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 +1263,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 +1274,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 +1316,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 +1361,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_slow.c b/src/test/test_slow.c
index 7c9f0b1cc2..e640702499 100644
--- a/src/test/test_slow.c
+++ b/src/test/test_slow.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/test_socks.c b/src/test/test_socks.c
index 62ff12fe15..9ae7530e22 100644
--- a/src/test/test_socks.c
+++ b/src/test/test_socks.c
@@ -1,12 +1,14 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "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
new file mode 100644
index 0000000000..a27074c21f
--- /dev/null
+++ b/src/test/test_storagedir.c
@@ -0,0 +1,375 @@
+/* Copyright (c) 2017, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "or.h"
+#include "storagedir.h"
+#include "test.h"
+
+#ifdef HAVE_UTIME_H
+#include <utime.h>
+#endif
+
+static void
+test_storagedir_empty(void *arg)
+{
+ char *dirname = tor_strdup(get_fname_rnd("store_dir"));
+ storage_dir_t *d = NULL;
+ (void)arg;
+
+ tt_int_op(FN_NOENT, OP_EQ, file_status(dirname));
+
+ d = storage_dir_new(dirname, 10);
+ tt_assert(d);
+
+ tt_int_op(FN_DIR, OP_EQ, file_status(dirname));
+
+ tt_int_op(0, OP_EQ, smartlist_len(storage_dir_list(d)));
+ tt_u64_op(0, OP_EQ, storage_dir_get_usage(d));
+
+ storage_dir_free(d);
+ d = storage_dir_new(dirname, 10);
+ tt_assert(d);
+
+ tt_int_op(FN_DIR, OP_EQ, file_status(dirname));
+
+ tt_int_op(0, OP_EQ, smartlist_len(storage_dir_list(d)));
+ tt_u64_op(0, OP_EQ, storage_dir_get_usage(d));
+
+ done:
+ storage_dir_free(d);
+ tor_free(dirname);
+}
+
+static void
+test_storagedir_basic(void *arg)
+{
+ char *dirname = tor_strdup(get_fname_rnd("store_dir"));
+ storage_dir_t *d = NULL;
+ uint8_t *junk = NULL, *bytes = NULL;
+ const size_t junklen = 1024;
+ char *fname1 = NULL, *fname2 = NULL;
+ const char hello_str[] = "then what are we but cold, alone ... ?";
+ tor_mmap_t *mapping = NULL;
+ (void)arg;
+
+ junk = tor_malloc(junklen);
+ crypto_rand((void*)junk, junklen);
+
+ d = storage_dir_new(dirname, 10);
+ tt_assert(d);
+ tt_u64_op(0, OP_EQ, storage_dir_get_usage(d));
+
+ int r;
+ r = storage_dir_save_string_to_file(d, hello_str, 1, &fname1);
+ tt_int_op(r, OP_EQ, 0);
+ tt_ptr_op(fname1, OP_NE, NULL);
+ tt_u64_op(strlen(hello_str), OP_EQ, storage_dir_get_usage(d));
+
+ r = storage_dir_save_bytes_to_file(d, junk, junklen, 1, &fname2);
+ tt_int_op(r, OP_EQ, 0);
+ tt_ptr_op(fname2, OP_NE, NULL);
+
+ tt_str_op(fname1, OP_NE, fname2);
+
+ tt_int_op(2, OP_EQ, smartlist_len(storage_dir_list(d)));
+ tt_u64_op(junklen + strlen(hello_str), OP_EQ, storage_dir_get_usage(d));
+ tt_assert(smartlist_contains_string(storage_dir_list(d), fname1));
+ tt_assert(smartlist_contains_string(storage_dir_list(d), fname2));
+
+ storage_dir_free(d);
+ d = storage_dir_new(dirname, 10);
+ tt_assert(d);
+ tt_int_op(2, OP_EQ, smartlist_len(storage_dir_list(d)));
+ tt_u64_op(junklen + strlen(hello_str), OP_EQ, storage_dir_get_usage(d));
+ tt_assert(smartlist_contains_string(storage_dir_list(d), fname1));
+ tt_assert(smartlist_contains_string(storage_dir_list(d), fname2));
+
+ size_t n;
+ bytes = storage_dir_read(d, fname2, 1, &n);
+ tt_assert(bytes);
+ tt_u64_op(n, OP_EQ, junklen);
+ tt_mem_op(bytes, OP_EQ, junk, junklen);
+
+ mapping = storage_dir_map(d, fname1);
+ tt_assert(mapping);
+ tt_u64_op(mapping->size, OP_EQ, strlen(hello_str));
+ tt_mem_op(mapping->data, OP_EQ, hello_str, strlen(hello_str));
+
+ done:
+ tor_free(dirname);
+ tor_free(junk);
+ tor_free(bytes);
+ tor_munmap_file(mapping);
+ storage_dir_free(d);
+ tor_free(fname1);
+ tor_free(fname2);
+}
+
+static void
+test_storagedir_deletion(void *arg)
+{
+ (void)arg;
+ char *dirname = tor_strdup(get_fname_rnd("store_dir"));
+ storage_dir_t *d = NULL;
+ char *fn1 = NULL, *fn2 = NULL;
+ char *bytes = NULL;
+ int r;
+ const char str1[] = "There are nine and sixty ways to disguise communiques";
+ const char str2[] = "And rather more than one of them is right";
+
+ // Make sure the directory is there. */
+ d = storage_dir_new(dirname, 10);
+ storage_dir_free(d);
+ d = NULL;
+
+ tor_asprintf(&fn1, "%s/1007", dirname);
+ r = write_str_to_file(fn1, str1, 0);
+ tt_int_op(r, OP_EQ, 0);
+
+ tor_asprintf(&fn2, "%s/1003.tmp", dirname);
+ r = write_str_to_file(fn2, str2, 0);
+ tt_int_op(r, OP_EQ, 0);
+
+ // The tempfile should be deleted the next time we list the directory.
+ d = storage_dir_new(dirname, 10);
+ tt_int_op(1, OP_EQ, smartlist_len(storage_dir_list(d)));
+ tt_u64_op(strlen(str1), OP_EQ, storage_dir_get_usage(d));
+ tt_int_op(FN_FILE, OP_EQ, file_status(fn1));
+ tt_int_op(FN_NOENT, OP_EQ, file_status(fn2));
+
+ bytes = (char*) storage_dir_read(d, "1007", 1, NULL);
+ tt_str_op(bytes, OP_EQ, str1);
+
+ // Should have no effect; file already gone.
+ storage_dir_remove_file(d, "1003.tmp");
+ tt_int_op(1, OP_EQ, smartlist_len(storage_dir_list(d)));
+ tt_u64_op(strlen(str1), OP_EQ, storage_dir_get_usage(d));
+
+ // Actually remove a file.
+ storage_dir_remove_file(d, "1007");
+ tt_int_op(FN_NOENT, OP_EQ, file_status(fn1));
+ tt_int_op(0, OP_EQ, smartlist_len(storage_dir_list(d)));
+ tt_u64_op(0, OP_EQ, storage_dir_get_usage(d));
+
+ done:
+ tor_free(dirname);
+ tor_free(fn1);
+ tor_free(fn2);
+ storage_dir_free(d);
+ tor_free(bytes);
+}
+
+static void
+test_storagedir_full(void *arg)
+{
+ (void)arg;
+
+ char *dirname = tor_strdup(get_fname_rnd("store_dir"));
+ storage_dir_t *d = NULL;
+ const char str[] = "enemies of the peephole";
+ int r;
+
+ d = storage_dir_new(dirname, 3);
+ tt_assert(d);
+
+ r = storage_dir_save_string_to_file(d, str, 1, NULL);
+ tt_int_op(r, OP_EQ, 0);
+ r = storage_dir_save_string_to_file(d, str, 1, NULL);
+ tt_int_op(r, OP_EQ, 0);
+ r = storage_dir_save_string_to_file(d, str, 1, NULL);
+ tt_int_op(r, OP_EQ, 0);
+
+ // These should fail!
+ r = storage_dir_save_string_to_file(d, str, 1, NULL);
+ tt_int_op(r, OP_EQ, -1);
+ r = storage_dir_save_string_to_file(d, str, 1, NULL);
+ tt_int_op(r, OP_EQ, -1);
+
+ tt_u64_op(strlen(str) * 3, OP_EQ, storage_dir_get_usage(d));
+
+ done:
+ tor_free(dirname);
+ storage_dir_free(d);
+}
+
+static void
+test_storagedir_cleaning(void *arg)
+{
+ (void)arg;
+
+ char *dirname = tor_strdup(get_fname_rnd("store_dir"));
+ storage_dir_t *d = NULL;
+ const char str[] =
+ "On a mountain halfway between Reno and Rome / "
+ "We have a machine in a plexiglass dome / "
+ "Which listens and looks into everyone's home."
+ " -- Dr. Seuss";
+ char *fns[8];
+ int r, i;
+
+ memset(fns, 0, sizeof(fns));
+ d = storage_dir_new(dirname, 10);
+ tt_assert(d);
+
+ for (i = 0; i < 8; ++i) {
+ r = storage_dir_save_string_to_file(d, str+i*2, 1, &fns[i]);
+ tt_int_op(r, OP_EQ, 0);
+ }
+
+ /* Now we're going to make sure all the files have distinct mtimes. */
+ time_t now = time(NULL);
+ struct utimbuf ub;
+ ub.actime = now;
+ ub.modtime = now - 1000;
+ for (i = 0; i < 8; ++i) {
+ char *f = NULL;
+ tor_asprintf(&f, "%s/%s", dirname, fns[i]);
+ r = utime(f, &ub);
+ tor_free(f);
+ tt_int_op(r, OP_EQ, 0);
+ ub.modtime += 5;
+ }
+
+ const uint64_t usage_orig = storage_dir_get_usage(d);
+ /* No changes needed if we are already under target. */
+ storage_dir_shrink(d, 1024*1024, 0);
+ tt_u64_op(usage_orig, OP_EQ, storage_dir_get_usage(d));
+
+ /* Get rid of at least one byte. This will delete fns[0]. */
+ storage_dir_shrink(d, usage_orig - 1, 0);
+ tt_u64_op(usage_orig, OP_GT, storage_dir_get_usage(d));
+ tt_u64_op(usage_orig - strlen(str), OP_EQ, storage_dir_get_usage(d));
+
+ /* Get rid of at least two files. This will delete fns[1] and fns[2]. */
+ storage_dir_shrink(d, 1024*1024, 2);
+ tt_u64_op(usage_orig - strlen(str)*3 + 6, OP_EQ, storage_dir_get_usage(d));
+
+ /* Get rid of everything. */
+ storage_dir_remove_all(d);
+ tt_u64_op(0, OP_EQ, storage_dir_get_usage(d));
+
+ done:
+ tor_free(dirname);
+ storage_dir_free(d);
+ for (i = 0; i < 8; ++i) {
+ tor_free(fns[i]);
+ }
+}
+
+static void
+test_storagedir_save_labeled(void *arg)
+{
+ (void)arg;
+ char *dirname = tor_strdup(get_fname_rnd("store_dir"));
+ storage_dir_t *d = NULL;
+ uint8_t *inp = tor_malloc_zero(8192);
+ config_line_t *labels = NULL;
+ char *fname = NULL;
+ uint8_t *saved = NULL;
+
+ d = storage_dir_new(dirname, 10);
+ tt_assert(d);
+
+ crypto_rand((char *)inp, 8192);
+
+ config_line_append(&labels, "Foo", "bar baz");
+ config_line_append(&labels, "quux", "quuzXxz");
+ const char expected[] =
+ "Foo bar baz\n"
+ "quux quuzXxz\n";
+
+ int r = storage_dir_save_labeled_to_file(d, labels, inp, 8192, &fname);
+ tt_int_op(r, OP_EQ, 0);
+
+ size_t n;
+ saved = storage_dir_read(d, fname, 1, &n);
+ tt_assert(memchr(saved, '\0', n));
+ tt_str_op((char*)saved, OP_EQ, expected); /* NUL guarantees strcmp works */
+ tt_mem_op(saved+strlen(expected)+1, OP_EQ, inp, 8192);
+
+ done:
+ storage_dir_free(d);
+ tor_free(dirname);
+ tor_free(inp);
+ tor_free(fname);
+ config_free_lines(labels);
+ tor_free(saved);
+}
+
+static void
+test_storagedir_read_labeled(void *arg)
+{
+ (void)arg;
+ char *dirname = tor_strdup(get_fname_rnd("store_dir"));
+ storage_dir_t *d = NULL;
+ uint8_t *inp = tor_malloc_zero(8192);
+ config_line_t *labels = NULL, *labels2 = NULL;
+ char *fname = NULL;
+ tor_mmap_t *map = NULL;
+ uint8_t *as_read = NULL;
+
+ d = storage_dir_new(dirname, 10);
+ tt_assert(d);
+
+ tor_snprintf((char*)inp, 8192,
+ "Hello world\n"
+ "This is a test\n"
+ "Yadda yadda.\n");
+ size_t bodylen = 8192 - strlen((char*)inp) - 1;
+ crypto_rand((char *)inp+strlen((char*)inp)+1, bodylen);
+
+ int r = storage_dir_save_bytes_to_file(d, inp, 8192, 1, &fname);
+ tt_int_op(r, OP_EQ, 0);
+
+ /* Try mapping */
+ const uint8_t *datap = NULL;
+ size_t sz = 0;
+ map = storage_dir_map_labeled(d, fname, &labels, &datap, &sz);
+ tt_assert(map);
+ tt_assert(datap);
+ tt_u64_op(sz, OP_EQ, bodylen);
+ tt_mem_op(datap, OP_EQ, inp+strlen((char*)inp)+1, bodylen);
+ tt_assert(labels);
+ tt_str_op(labels->key, OP_EQ, "Hello");
+ tt_str_op(labels->value, OP_EQ, "world");
+ tt_assert(labels->next);
+ tt_str_op(labels->next->key, OP_EQ, "This");
+ tt_str_op(labels->next->value, OP_EQ, "is a test");
+ 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_ptr_op(labels->next->next->next, OP_EQ, NULL);
+
+ /* Try reading this time. */
+ sz = 0;
+ as_read = storage_dir_read_labeled(d, fname, &labels2, &sz);
+ tt_assert(as_read);
+ tt_u64_op(sz, OP_EQ, bodylen);
+ tt_mem_op(as_read, OP_EQ, inp+strlen((char*)inp)+1, bodylen);
+ tt_assert(config_lines_eq(labels, labels2));
+
+ done:
+ storage_dir_free(d);
+ tor_free(dirname);
+ tor_free(inp);
+ tor_free(fname);
+ config_free_lines(labels);
+ config_free_lines(labels2);
+ tor_munmap_file(map);
+ tor_free(as_read);
+}
+
+#define ENT(name) \
+ { #name, test_storagedir_ ## name, TT_FORK, NULL, NULL }
+
+struct testcase_t storagedir_tests[] = {
+ ENT(empty),
+ ENT(basic),
+ ENT(deletion),
+ ENT(full),
+ ENT(cleaning),
+ ENT(save_labeled),
+ ENT(read_labeled),
+ END_OF_TESTCASES
+};
+
diff --git a/src/test/test_switch_id.c b/src/test/test_switch_id.c
index e12205bb2e..fe36d8c6e6 100644
--- a/src/test/test_switch_id.c
+++ b/src/test/test_switch_id.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Tor Project, Inc. */
+/* Copyright (c) 2015-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "or.h"
@@ -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 ebbc95c7ca..ed6d8f04aa 100644
--- a/src/test/test_threads.c
+++ b/src/test/test_threads.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -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 4bfcea211d..29f7cc9c37 100644
--- a/src/test/test_tortls.c
+++ b/src/test/test_tortls.c
@@ -1,7 +1,8 @@
-/* Copyright (c) 2010-2016, The Tor Project, Inc. */
+/* Copyright (c) 2010-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define TORTLS_PRIVATE
+#define TORTLS_OPENSSL_PRIVATE
#define LOG_PRIVATE
#include "orconfig.h"
@@ -62,7 +63,7 @@ fake_num_ciphers(void)
{
return 0;
}
-#endif
+#endif /* !defined(OPENSSL_OPAQUE) */
static void
test_tortls_errno_to_tls_error(void *data)
@@ -135,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();
@@ -143,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);
@@ -375,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),
@@ -489,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)
@@ -519,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)
@@ -661,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)
@@ -743,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
@@ -878,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)
@@ -920,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
@@ -936,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 =
@@ -955,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"
@@ -1078,7 +1079,7 @@ test_tortls_verify(void *ignored)
tor_free(tls);
tor_free(k);
}
-#endif
+#endif /* !defined(OPENSSL_OPAQUE) */
#ifndef OPENSSL_OPAQUE
static void
@@ -1117,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;
@@ -1152,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)
@@ -1275,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
@@ -1289,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));
@@ -1307,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
@@ -1349,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);
@@ -1358,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)
@@ -1377,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;
@@ -1449,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
@@ -1481,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
@@ -1511,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)
@@ -1571,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
@@ -1622,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
@@ -1641,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)
@@ -1696,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;
@@ -1714,7 +1716,7 @@ fake_get_cipher(unsigned ncipher)
return NULL;
}
}
-#endif
+#endif /* !defined(OPENSSL_OPAQUE) */
#ifndef OPENSSL_OPAQUE
static void
@@ -1784,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
@@ -1812,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
@@ -1876,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;
@@ -1917,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)
@@ -2013,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();
@@ -2084,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:
@@ -2159,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;
@@ -2239,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;
@@ -2257,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:
@@ -2267,7 +2269,7 @@ test_tortls_handshake(void *ignored)
tor_free(tls);
tor_free(method);
}
-#endif
+#endif /* !defined(OPENSSL_OPAQUE) */
#ifndef OPENSSL_OPAQUE
static void
@@ -2342,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];
@@ -2567,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];
@@ -2636,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);
@@ -2644,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);
@@ -2691,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);
@@ -2730,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);
@@ -2763,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 ab6fe8ded9..0519a4758f 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -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);
@@ -2242,114 +2264,340 @@ test_util_pow2(void *arg)
;
}
-/** Run unit tests for compression functions */
static void
-test_util_gzip(void *arg)
+test_util_compress_impl(compress_method_t method)
{
- char *buf1=NULL, *buf2=NULL, *buf3=NULL, *cp1, *cp2;
- const char *ccp2;
+ char *buf1=NULL, *buf2=NULL, *buf3=NULL;
size_t len1, len2;
- tor_zlib_state_t *state = NULL;
- (void)arg;
- buf1 = tor_strdup("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ");
- tt_assert(detect_compression_method(buf1, strlen(buf1)) == UNKNOWN_METHOD);
-
- tt_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1,
- GZIP_METHOD));
- tt_assert(buf2);
- tt_assert(len1 < strlen(buf1));
- tt_assert(detect_compression_method(buf2, len1) == GZIP_METHOD);
+ tt_assert(tor_compress_supports_method(method));
- tt_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1,
- GZIP_METHOD, 1, LOG_INFO));
- tt_assert(buf3);
- tt_int_op(strlen(buf1) + 1,OP_EQ, len2);
- tt_str_op(buf1,OP_EQ, buf3);
+ if (method != NO_METHOD) {
+ tt_ptr_op(tor_compress_version_str(method), OP_NE, NULL);
+ tt_ptr_op(tor_compress_header_version_str(method), OP_NE, NULL);
+ }
- tor_free(buf2);
- tor_free(buf3);
+ buf1 = tor_strdup("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ");
+ tt_assert(detect_compression_method(buf1, strlen(buf1)) == UNKNOWN_METHOD);
- tt_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1,
- ZLIB_METHOD));
- tt_assert(buf2);
- tt_assert(detect_compression_method(buf2, len1) == ZLIB_METHOD);
+ tt_assert(!tor_compress(&buf2, &len1, buf1, strlen(buf1)+1, method));
+ 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."
+ tt_int_op(len1, OP_EQ, strlen(buf1)+1);
+ tt_int_op(detect_compression_method(buf2, len1), OP_EQ, UNKNOWN_METHOD);
+ } else {
+ tt_int_op(len1, OP_LT, strlen(buf1));
+ tt_int_op(detect_compression_method(buf2, len1), OP_EQ, method);
+ }
- tt_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1,
- ZLIB_METHOD, 1, LOG_INFO));
- tt_assert(buf3);
- tt_int_op(strlen(buf1) + 1,OP_EQ, len2);
- tt_str_op(buf1,OP_EQ, buf3);
+ tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1, method, 1, LOG_INFO));
+ 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);
/* Check whether we can uncompress concatenated, compressed strings. */
tor_free(buf3);
buf2 = tor_reallocarray(buf2, len1, 2);
memcpy(buf2+len1, buf2, len1);
- tt_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1*2,
- ZLIB_METHOD, 1, LOG_INFO));
- tt_int_op((strlen(buf1)+1)*2,OP_EQ, len2);
- tt_mem_op(buf3,OP_EQ,
+ tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1*2, method, 1, LOG_INFO));
+ tt_int_op((strlen(buf1)+1)*2, OP_EQ, len2);
+ tt_mem_op(buf3, OP_EQ,
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0"
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0",
(strlen(buf1)+1)*2);
+ tt_int_op(buf3[len2], OP_EQ, 0);
+
+ /* Check whether we can uncompress partial strings */
tor_free(buf1);
tor_free(buf2);
tor_free(buf3);
- /* Check whether we can uncompress partial strings. */
- buf1 =
- tor_strdup("String with low redundancy that won't be compressed much.");
- tt_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1,
- ZLIB_METHOD));
- tt_assert(len1>16);
- /* when we allow an incomplete string, we should succeed.*/
- tt_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1-16,
- ZLIB_METHOD, 0, LOG_INFO));
- tt_assert(len2 > 5);
- buf3[len2]='\0';
- tt_assert(!strcmpstart(buf1, buf3));
-
- /* when we demand a complete string, this must fail. */
+ size_t b1len = 1<<10;
+ if (method == ZSTD_METHOD) {
+ // zstd needs a big input before it starts generating output that it
+ // can partially decompress.
+ b1len = 1<<18;
+ }
+ buf1 = tor_malloc(b1len);
+ crypto_rand(buf1, b1len);
+ tt_assert(!tor_compress(&buf2, &len1, buf1, b1len, method));
+ tt_int_op(len1, OP_GT, 16);
+ /* when we allow an incomplete output we should succeed.*/
+ tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1-16,
+ method, 0, LOG_INFO));
+ tt_int_op(len2, OP_GT, 5);
+ tt_int_op(len2, OP_LE, len1);
+ tt_assert(fast_memeq(buf1, buf3, len2));
+ tt_int_op(buf3[len2], OP_EQ, 0);
+
+ /* when we demand a complete output from a real compression method, this
+ * must fail. */
tor_free(buf3);
- tt_assert(tor_gzip_uncompress(&buf3, &len2, buf2, len1-16,
- ZLIB_METHOD, 1, LOG_INFO));
- tt_assert(!buf3);
+ if (method != NO_METHOD) {
+ tt_assert(tor_uncompress(&buf3, &len2, buf2, len1-16,
+ method, 1, LOG_INFO));
+ tt_ptr_op(buf3, OP_EQ, NULL);
+ }
- /* Now, try streaming compression. */
+ done:
tor_free(buf1);
tor_free(buf2);
tor_free(buf3);
- state = tor_zlib_new(1, ZLIB_METHOD, HIGH_COMPRESSION);
+}
+
+static void
+test_util_compress_stream_impl(compress_method_t method,
+ compression_level_t level)
+{
+ char *buf1=NULL, *buf2=NULL, *buf3=NULL, *cp1, *cp2;
+ const char *ccp2;
+ size_t len1, len2;
+
+ tor_compress_state_t *state = NULL;
+ state = tor_compress_new(1, method, level);
tt_assert(state);
cp1 = buf1 = tor_malloc(1024);
len1 = 1024;
ccp2 = "ABCDEFGHIJABCDEFGHIJ";
len2 = 21;
- tt_assert(tor_zlib_process(state, &cp1, &len1, &ccp2, &len2, 0)
- == TOR_ZLIB_OK);
- tt_int_op(0,OP_EQ, len2); /* Make sure we compressed it all. */
+ tt_int_op(tor_compress_process(state, &cp1, &len1, &ccp2, &len2, 0),
+ OP_EQ, TOR_COMPRESS_OK);
+ tt_int_op(0, OP_EQ, len2); /* Make sure we compressed it all. */
tt_assert(cp1 > buf1);
len2 = 0;
cp2 = cp1;
- tt_assert(tor_zlib_process(state, &cp1, &len1, &ccp2, &len2, 1)
- == TOR_ZLIB_DONE);
- tt_int_op(0,OP_EQ, len2);
- tt_assert(cp1 > cp2); /* Make sure we really added something. */
+ tt_int_op(tor_compress_process(state, &cp1, &len1, &ccp2, &len2, 1),
+ OP_EQ, TOR_COMPRESS_DONE);
+ tt_int_op(0, OP_EQ, len2);
+ if (method == NO_METHOD) {
+ tt_ptr_op(cp1, OP_EQ, cp2);
+ } else {
+ tt_assert(cp1 > cp2); /* Make sure we really added something. */
+ }
+
+ tt_int_op(tor_compress_state_size(state), OP_GT, 0);
- tt_assert(!tor_gzip_uncompress(&buf3, &len2, buf1, 1024-len1,
- ZLIB_METHOD, 1, LOG_WARN));
+ tt_assert(!tor_uncompress(&buf3, &len2, buf1, 1024-len1,
+ method, 1, LOG_WARN));
/* Make sure it compressed right. */
tt_str_op(buf3, OP_EQ, "ABCDEFGHIJABCDEFGHIJ");
- tt_int_op(21,OP_EQ, len2);
+ tt_int_op(21, OP_EQ, len2);
done:
if (state)
- tor_zlib_free(state);
+ tor_compress_free(state);
+ tor_free(buf1);
tor_free(buf2);
tor_free(buf3);
- tor_free(buf1);
+}
+
+/** Run unit tests for compression functions */
+static void
+test_util_compress(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();
+ }
+
+ compression_level_t levels[] = {
+ BEST_COMPRESSION,
+ HIGH_COMPRESSION,
+ MEDIUM_COMPRESSION,
+ LOW_COMPRESSION
+ };
+
+ test_util_compress_impl(method);
+
+ for (unsigned l = 0; l < ARRAY_LENGTH(levels); ++l) {
+ compression_level_t level = levels[l];
+ test_util_compress_stream_impl(method, level);
+ }
+ done:
+ ;
+}
+
+static void
+test_util_decompress_concatenated_impl(compress_method_t method)
+{
+ char input[4096];
+ char *c1 = NULL, *c2 = NULL, *c3 = NULL;
+ char *result = NULL;
+ size_t sz1, sz2, sz3, szr;
+ int r;
+
+ crypto_rand(input, sizeof(input));
+
+ /* Compress the input in two chunks. */
+ r = tor_compress(&c1, &sz1, input, 2048, method);
+ tt_int_op(r, OP_EQ, 0);
+ r = tor_compress(&c2, &sz2, input+2048, 2048, method);
+ tt_int_op(r, OP_EQ, 0);
+
+ /* concatenate the chunks. */
+ sz3 = sz1 + sz2;
+ c3 = tor_malloc(sz3);
+ memcpy(c3, c1, sz1);
+ memcpy(c3+sz1, c2, sz2);
+
+ /* decompress the concatenated result */
+ r = tor_uncompress(&result, &szr, c3, sz3, method, 0, LOG_WARN);
+ tt_int_op(r, OP_EQ, 0);
+ tt_int_op(szr, OP_EQ, sizeof(input));
+ tt_mem_op(result, OP_EQ, input, sizeof(input));
+
+ done:
+ tor_free(c1);
+ tor_free(c2);
+ tor_free(c3);
+ tor_free(result);
+}
+
+static void
+test_util_decompress_concatenated(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_concatenated_impl(method);
+ done:
+ ;
+}
+
+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
@@ -2364,44 +2612,44 @@ test_util_gzip_compression_bomb(void *arg)
char *one_mb = tor_malloc_zero(one_million);
char *result = NULL;
size_t result_len = 0;
- tor_zlib_state_t *state = NULL;
+ tor_compress_state_t *state = NULL;
/* Make sure we can't produce a compression bomb */
setup_full_capture_of_logs(LOG_WARN);
- tt_int_op(-1, OP_EQ, tor_gzip_compress(&result, &result_len,
- one_mb, one_million,
- ZLIB_METHOD));
+ tt_int_op(-1, OP_EQ, tor_compress(&result, &result_len,
+ one_mb, one_million,
+ ZLIB_METHOD));
expect_single_log_msg_containing(
"We compressed something and got an insanely high "
"compression factor; other Tors would think this "
- "was a zlib bomb.");
+ "was a compression bomb.");
teardown_capture_of_logs();
/* Here's a compression bomb that we made manually. */
const char compression_bomb[1039] =
{ 0x78, 0xDA, 0xED, 0xC1, 0x31, 0x01, 0x00, 0x00, 0x00, 0xC2,
0xA0, 0xF5, 0x4F, 0x6D, 0x08, 0x5F, 0xA0 /* .... */ };
- tt_int_op(-1, OP_EQ, tor_gzip_uncompress(&result, &result_len,
- compression_bomb, 1039,
- ZLIB_METHOD, 0, LOG_WARN));
+ tt_int_op(-1, OP_EQ, tor_uncompress(&result, &result_len,
+ compression_bomb, 1039,
+ ZLIB_METHOD, 0, LOG_WARN));
/* Now try streaming that. */
- state = tor_zlib_new(0, ZLIB_METHOD, HIGH_COMPRESSION);
- tor_zlib_output_t r;
+ state = tor_compress_new(0, ZLIB_METHOD, HIGH_COMPRESSION);
+ tor_compress_output_t r;
const char *inp = compression_bomb;
size_t inlen = 1039;
do {
char *outp = one_mb;
size_t outleft = 4096; /* small on purpose */
- r = tor_zlib_process(state, &outp, &outleft, &inp, &inlen, 0);
+ r = tor_compress_process(state, &outp, &outleft, &inp, &inlen, 0);
tt_int_op(inlen, OP_NE, 0);
- } while (r == TOR_ZLIB_BUF_FULL);
+ } while (r == TOR_COMPRESS_BUFFER_FULL);
- tt_int_op(r, OP_EQ, TOR_ZLIB_ERR);
+ tt_int_op(r, OP_EQ, TOR_COMPRESS_ERROR);
done:
tor_free(one_mb);
- tor_zlib_free(state);
+ tor_compress_free(state);
}
/** Run unit tests for mmap() wrapper functionality. */
@@ -2419,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);
@@ -2437,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);
@@ -2448,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);
@@ -2766,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 */
@@ -2861,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);
@@ -2888,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)
@@ -3255,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
@@ -3293,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:
;
@@ -3336,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:
;
@@ -3351,6 +3599,13 @@ test_util_memarea(void *arg)
void *malloced_ptr = NULL;
int i;
+#ifdef DISABLE_MEMORY_SENTINELS
+ /* If memory sentinels are disabled, this whole module is just an alias for
+ malloc(), which is free to lay out memory most any way it wants. */
+ if (1)
+ tt_skip();
+#endif /* defined(DISABLE_MEMORY_SENTINELS) */
+
(void)arg;
tt_assert(area);
@@ -3520,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);
@@ -3871,7 +4126,7 @@ test_util_load_win_lib(void *ptr)
if (h)
FreeLibrary(h);
}
-#endif
+#endif /* defined(_WIN32) */
#ifndef _WIN32
static void
@@ -3923,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);
@@ -3941,20 +4196,16 @@ test_util_exit_status(void *ptr)
done:
;
}
-#endif
+#endif /* !defined(_WIN32) */
#ifndef _WIN32
-/* Check that fgets with a non-blocking pipe returns partial lines and sets
- * EAGAIN, returns full lines and sets no error, and returns NULL on EOF and
- * sets no error */
static void
-test_util_fgets_eagain(void *ptr)
+test_util_string_from_pipe(void *ptr)
{
int test_pipe[2] = {-1, -1};
- int retval;
+ int retval = 0;
+ enum stream_status status = IO_STREAM_TERM;
ssize_t retlen;
- char *retptr;
- FILE *test_stream = NULL;
char buf[4] = { 0 };
(void)ptr;
@@ -3965,91 +4216,115 @@ test_util_fgets_eagain(void *ptr)
retval = pipe(test_pipe);
tt_int_op(retval, OP_EQ, 0);
- /* Set up the read-end to be non-blocking */
- retval = fcntl(test_pipe[0], F_SETFL, O_NONBLOCK);
- tt_int_op(retval, OP_EQ, 0);
+ /* Send in a string. */
+ retlen = write(test_pipe[1], "ABC", 3);
+ tt_int_op(retlen, OP_EQ, 3);
- /* Open it as a stdio stream */
- test_stream = fdopen(test_pipe[0], "r");
- tt_ptr_op(test_stream, OP_NE, NULL);
+ status = get_string_from_pipe(test_pipe[0], buf, sizeof(buf)-1);
+ tt_int_op(errno, OP_EQ, 0);
+ tt_int_op(status, OP_EQ, IO_STREAM_OKAY);
+ tt_str_op(buf, OP_EQ, "ABC");
+ errno = 0;
+
+ /* Send in a string that contains a nul. */
+ retlen = write(test_pipe[1], "AB\0", 3);
+ tt_int_op(retlen, OP_EQ, 3);
+
+ status = get_string_from_pipe(test_pipe[0], buf, sizeof(buf)-1);
+ tt_int_op(errno, OP_EQ, 0);
+ tt_int_op(status, OP_EQ, IO_STREAM_OKAY);
+ tt_str_op(buf, OP_EQ, "AB");
+ errno = 0;
- /* Send in a partial line */
- retlen = write(test_pipe[1], "A", 1);
+ /* Send in a string that contains a nul only. */
+ retlen = write(test_pipe[1], "\0", 1);
tt_int_op(retlen, OP_EQ, 1);
- retptr = fgets(buf, sizeof(buf), test_stream);
- tt_int_op(errno, OP_EQ, EAGAIN);
- tt_ptr_op(retptr, OP_EQ, buf);
- tt_str_op(buf, OP_EQ, "A");
+
+ status = get_string_from_pipe(test_pipe[0], buf, sizeof(buf)-1);
+ tt_int_op(errno, OP_EQ, 0);
+ tt_int_op(status, OP_EQ, IO_STREAM_OKAY);
+ tt_str_op(buf, OP_EQ, "");
errno = 0;
- /* Send in the rest */
- retlen = write(test_pipe[1], "B\n", 2);
- tt_int_op(retlen, OP_EQ, 2);
- retptr = fgets(buf, sizeof(buf), test_stream);
+ /* Send in a string that contains a trailing newline. */
+ retlen = write(test_pipe[1], "AB\n", 3);
+ tt_int_op(retlen, OP_EQ, 3);
+
+ status = get_string_from_pipe(test_pipe[0], buf, sizeof(buf)-1);
tt_int_op(errno, OP_EQ, 0);
- tt_ptr_op(retptr, OP_EQ, buf);
- tt_str_op(buf, OP_EQ, "B\n");
+ tt_int_op(status, OP_EQ, IO_STREAM_OKAY);
+ tt_str_op(buf, OP_EQ, "AB");
errno = 0;
- /* Send in a full line */
- retlen = write(test_pipe[1], "CD\n", 3);
+ /* Send in a string that contains a newline only. */
+ retlen = write(test_pipe[1], "\n", 1);
+ tt_int_op(retlen, OP_EQ, 1);
+
+ status = get_string_from_pipe(test_pipe[0], buf, sizeof(buf)-1);
+ tt_int_op(errno, OP_EQ, 0);
+ tt_int_op(status, OP_EQ, IO_STREAM_OKAY);
+ tt_str_op(buf, OP_EQ, "");
+ errno = 0;
+
+ /* Send in a string and check that we nul terminate return values. */
+ retlen = write(test_pipe[1], "AAA", 3);
tt_int_op(retlen, OP_EQ, 3);
- retptr = fgets(buf, sizeof(buf), test_stream);
+
+ status = get_string_from_pipe(test_pipe[0], buf, sizeof(buf)-1);
tt_int_op(errno, OP_EQ, 0);
- tt_ptr_op(retptr, OP_EQ, buf);
- tt_str_op(buf, OP_EQ, "CD\n");
+ tt_int_op(status, OP_EQ, IO_STREAM_OKAY);
+ tt_str_op(buf, OP_EQ, "AAA");
+ tt_mem_op(buf, OP_EQ, "AAA\0", sizeof(buf));
errno = 0;
- /* Send in a partial line */
- retlen = write(test_pipe[1], "E", 1);
+ retlen = write(test_pipe[1], "B", 1);
tt_int_op(retlen, OP_EQ, 1);
- retptr = fgets(buf, sizeof(buf), test_stream);
- tt_int_op(errno, OP_EQ, EAGAIN);
- tt_ptr_op(retptr, OP_EQ, buf);
- tt_str_op(buf, OP_EQ, "E");
+
+ memset(buf, '\xff', sizeof(buf));
+ status = get_string_from_pipe(test_pipe[0], buf, sizeof(buf)-1);
+ tt_int_op(errno, OP_EQ, 0);
+ tt_int_op(status, OP_EQ, IO_STREAM_OKAY);
+ tt_str_op(buf, OP_EQ, "B");
+ tt_mem_op(buf, OP_EQ, "B\0\xff\xff", sizeof(buf));
errno = 0;
- /* Send in the rest */
- retlen = write(test_pipe[1], "F\n", 2);
- tt_int_op(retlen, OP_EQ, 2);
- retptr = fgets(buf, sizeof(buf), test_stream);
+ /* Send in multiple lines. */
+ retlen = write(test_pipe[1], "A\nB", 3);
+ tt_int_op(retlen, OP_EQ, 3);
+
+ status = get_string_from_pipe(test_pipe[0], buf, sizeof(buf)-1);
tt_int_op(errno, OP_EQ, 0);
- tt_ptr_op(retptr, OP_EQ, buf);
- tt_str_op(buf, OP_EQ, "F\n");
+ tt_int_op(status, OP_EQ, IO_STREAM_OKAY);
+ tt_str_op(buf, OP_EQ, "A\nB");
errno = 0;
- /* Send in a full line and close */
- retlen = write(test_pipe[1], "GH", 2);
+ /* Send in a line and close */
+ retlen = write(test_pipe[1], "AB", 2);
tt_int_op(retlen, OP_EQ, 2);
retval = close(test_pipe[1]);
tt_int_op(retval, OP_EQ, 0);
test_pipe[1] = -1;
- retptr = fgets(buf, sizeof(buf), test_stream);
+
+ status = get_string_from_pipe(test_pipe[0], buf, sizeof(buf)-1);
tt_int_op(errno, OP_EQ, 0);
- tt_ptr_op(retptr, OP_EQ, buf);
- tt_str_op(buf, OP_EQ, "GH");
+ tt_int_op(status, OP_EQ, IO_STREAM_OKAY);
+ tt_str_op(buf, OP_EQ, "AB");
errno = 0;
/* Check for EOF */
- retptr = fgets(buf, sizeof(buf), test_stream);
+ status = get_string_from_pipe(test_pipe[0], buf, sizeof(buf)-1);
tt_int_op(errno, OP_EQ, 0);
- tt_ptr_op(retptr, OP_EQ, NULL);
- retval = feof(test_stream);
- tt_int_op(retval, OP_NE, 0);
+ tt_int_op(status, OP_EQ, IO_STREAM_CLOSED);
errno = 0;
- /* Check that buf is unchanged according to C99 and C11 */
- tt_str_op(buf, OP_EQ, "GH");
-
done:
- if (test_stream != NULL)
- fclose(test_stream);
if (test_pipe[0] != -1)
close(test_pipe[0]);
if (test_pipe[1] != -1)
close(test_pipe[1]);
}
-#endif
+
+#endif /* !defined(_WIN32) */
/**
* Test for format_hex_number_sigsafe()
@@ -4245,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 */
@@ -4361,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"
@@ -4383,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_);
@@ -4853,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:
;
@@ -4901,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
@@ -4933,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));
@@ -4995,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));
@@ -5032,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:
;
@@ -5071,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
@@ -5081,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))
@@ -5125,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);
@@ -5187,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(). */
@@ -5214,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]));
@@ -5375,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:
;
@@ -5425,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];
@@ -5463,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();
@@ -5485,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)
@@ -5663,18 +5938,115 @@ 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:
;
}
+static void
+test_util_get_unquoted_path(void *arg)
+{
+ (void)arg;
+
+ char *r = NULL;
+
+ r = get_unquoted_path("\""); // "
+ tt_ptr_op(r, OP_EQ, NULL);
+ tor_free(r);
+
+ r = get_unquoted_path("\"\"\""); // """
+ tt_ptr_op(r, OP_EQ, NULL);
+ tor_free(r);
+
+ r = get_unquoted_path("\\\""); // \"
+ tt_ptr_op(r, OP_EQ, NULL);
+ tor_free(r);
+
+ r = get_unquoted_path("\\\"\\\""); // \"\"
+ tt_ptr_op(r, OP_EQ, NULL);
+ tor_free(r);
+
+ r = get_unquoted_path("A\\B\\C\""); // A\B\C"
+ tt_ptr_op(r, OP_EQ, NULL);
+ tor_free(r);
+
+ r = get_unquoted_path("\"A\\B\\C"); // "A\B\C
+ tt_ptr_op(r, OP_EQ, NULL);
+ tor_free(r);
+
+ r = get_unquoted_path("\"A\\B\"C\""); // "A\B"C"
+ tt_ptr_op(r, OP_EQ, NULL);
+ tor_free(r);
+
+ r = get_unquoted_path("A\\B\"C"); // A\B"C
+ tt_ptr_op(r, OP_EQ, NULL);
+ tor_free(r);
+
+ r = get_unquoted_path("");
+ tt_str_op(r, OP_EQ, "");
+ tor_free(r);
+
+ r = get_unquoted_path("\"\""); // ""
+ tt_str_op(r, OP_EQ, "");
+ tor_free(r);
+
+ r = get_unquoted_path("A\\B\\C"); // A\B\C
+ tt_str_op(r, OP_EQ, "A\\B\\C"); // A\B\C
+ tor_free(r);
+
+ r = get_unquoted_path("\"A\\B\\C\""); // "A\B\C"
+ tt_str_op(r, OP_EQ, "A\\B\\C"); // A\B\C
+ tor_free(r);
+
+ r = get_unquoted_path("\"\\\""); // "\"
+ tt_str_op(r, OP_EQ, "\\"); // \ /* comment to prevent line continuation */
+ tor_free(r);
+
+ r = get_unquoted_path("\"\\\"\""); // "\""
+ tt_str_op(r, OP_EQ, "\""); // "
+ tor_free(r);
+
+ r = get_unquoted_path("\"A\\B\\C\\\"\""); // "A\B\C\""
+ tt_str_op(r, OP_EQ, "A\\B\\C\""); // A\B\C"
+ tor_free(r);
+
+ r = get_unquoted_path("A\\B\\\"C"); // A\B\"C
+ tt_str_op(r, OP_EQ, "A\\B\"C"); // A\B"C
+ tor_free(r);
+
+ r = get_unquoted_path("\"A\\B\\\"C\""); // "A\B\"C"
+ tt_str_op(r, OP_EQ, "A\\B\"C"); // A\B"C
+
+ done:
+ tor_free(r);
+}
+
#define UTIL_LEGACY(name) \
{ #name, test_util_ ## name , 0, NULL, NULL }
#define UTIL_TEST(name, flags) \
{ #name, test_util_ ## name, flags, NULL, NULL }
+#define COMPRESS(name, identifier) \
+ { "compress/" #name, test_util_compress, 0, &passthrough_setup, \
+ (char*)(identifier) }
+
+#define COMPRESS_CONCAT(name, identifier) \
+ { "compress_concat/" #name, test_util_decompress_concatenated, 0, \
+ &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))
@@ -5683,7 +6055,7 @@ test_util_htonll(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),
@@ -5699,7 +6071,23 @@ struct testcase_t util_tests[] = {
UTIL_LEGACY(strmisc),
UTIL_TEST(parse_integer, 0),
UTIL_LEGACY(pow2),
- UTIL_LEGACY(gzip),
+ COMPRESS(zlib, "deflate"),
+ COMPRESS(gzip, "gzip"),
+ COMPRESS(lzma, "x-tor-lzma"),
+ COMPRESS(zstd, "x-zstd"),
+ COMPRESS(none, "identity"),
+ COMPRESS_CONCAT(zlib, "deflate"),
+ COMPRESS_CONCAT(gzip, "gzip"),
+ 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),
@@ -5723,7 +6111,7 @@ struct testcase_t util_tests[] = {
UTIL_TEST(num_cpus, 0),
UTIL_TEST_WIN_ONLY(load_win_lib, 0),
UTIL_TEST_NO_WIN(exit_status, 0),
- UTIL_TEST_NO_WIN(fgets_eagain, 0),
+ UTIL_TEST_NO_WIN(string_from_pipe, 0),
UTIL_TEST(format_hex_number, 0),
UTIL_TEST(format_dec_number, 0),
UTIL_TEST(join_win_cmdline, 0),
@@ -5763,6 +6151,7 @@ struct testcase_t util_tests[] = {
UTIL_TEST(monotonic_time, 0),
UTIL_TEST(monotonic_time_ratchet, TT_FORK),
UTIL_TEST(htonll, 0),
+ UTIL_TEST(get_unquoted_path, 0),
END_OF_TESTCASES
};
diff --git a/src/test/test_util_format.c b/src/test/test_util_format.c
index 21a6923c6d..683d5fdac1 100644
--- a/src/test/test_util_format.c
+++ b/src/test/test_util_format.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2016, The Tor Project, Inc. */
+/* Copyright (c) 2010-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -133,48 +133,54 @@ test_util_format_base64_encode(void *ignored)
}
static void
-test_util_format_base64_decode_nopad(void *ignored)
+test_util_format_base64_decode_oddsize(void *ignored)
{
(void)ignored;
int res;
int i;
char *src;
- uint8_t *dst, *real_dst;
- uint8_t expected[] = {0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65};
+ char *dst, real_dst[7];
+ char expected[] = {0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65};
char real_src[] = "ZXhhbXBsZQ";
+ char expected40[] = "testing40characteroddsizebase64encoding!";
+ char src40[] = "dGVzdGluZzQwY2hhcmFjdGVyb2Rkc2l6ZWJhc2U2NGVuY29kaW5nIQ";
+ char pad40[] = "dGVzdGluZzQwY2hhcmFjdGVyb2Rkc2l6ZWJhc2U2NGVuY29kaW5nIQ==";
src = tor_malloc_zero(256);
dst = tor_malloc_zero(1000);
- real_dst = tor_malloc_zero(10);
for (i=0;i<256;i++) {
src[i] = (char)i;
}
- res = base64_decode_nopad(dst, 1, src, SIZE_T_CEILING);
- tt_int_op(res, OP_EQ, -1);
-
- res = base64_decode_nopad(dst, 1, src, 5);
+ res = base64_decode(dst, 1, src, 5);
tt_int_op(res, OP_EQ, -1);
const char *s = "SGVsbG8gd29ybGQ";
- res = base64_decode_nopad(dst, 1000, s, strlen(s));
+ res = base64_decode(dst, 1000, s, strlen(s));
tt_int_op(res, OP_EQ, 11);
tt_mem_op(dst, OP_EQ, "Hello world", 11);
s = "T3BhIG11bmRv";
- res = base64_decode_nopad(dst, 9, s, strlen(s));
+ res = base64_decode(dst, 9, s, strlen(s));
tt_int_op(res, OP_EQ, 9);
tt_mem_op(dst, OP_EQ, "Opa mundo", 9);
- res = base64_decode_nopad(real_dst, 10, real_src, 10);
+ res = base64_decode(real_dst, sizeof(real_dst), real_src, 10);
tt_int_op(res, OP_EQ, 7);
tt_mem_op(real_dst, OP_EQ, expected, 7);
+ res = base64_decode(dst, 40, src40, strlen(src40));
+ tt_int_op(res, OP_EQ, 40);
+ tt_mem_op(dst, OP_EQ, expected40, 40);
+
+ res = base64_decode(dst, 40, pad40, strlen(pad40));
+ tt_int_op(res, OP_EQ, 40);
+ tt_mem_op(dst, OP_EQ, expected40, 40);
+
done:
tor_free(src);
tor_free(dst);
- tor_free(real_dst);
}
static void
@@ -196,13 +202,10 @@ test_util_format_base64_decode(void *ignored)
src[i] = (char)i;
}
- res = base64_decode(dst, 1, src, SIZE_T_CEILING);
+ res = base64_decode(dst, 1, src, 100);
tt_int_op(res, OP_EQ, -1);
- res = base64_decode(dst, SIZE_T_CEILING+1, src, 10);
- tt_int_op(res, OP_EQ, -1);
-
- res = base64_decode(dst, 1, real_src, SIZE_MAX/3+1);
+ res = base64_decode(dst, 1, real_src, 10);
tt_int_op(res, OP_EQ, -1);
const char *s = "T3BhIG11bmRv";
@@ -342,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);
}
@@ -353,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));
}
@@ -361,20 +364,48 @@ 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:
tor_free(dst);
}
+static void
+test_util_format_encoded_size(void *arg)
+{
+ (void)arg;
+ uint8_t inbuf[256];
+ char outbuf[1024];
+ unsigned i;
+
+ crypto_rand((char *)inbuf, sizeof(inbuf));
+ for (i = 0; i <= sizeof(inbuf); ++i) {
+ /* XXXX (Once the return values are consistent, check them too.) */
+
+ base32_encode(outbuf, sizeof(outbuf), (char *)inbuf, i);
+ /* The "+ 1" below is an API inconsistency. */
+ tt_int_op(strlen(outbuf) + 1, OP_EQ, base32_encoded_size(i));
+
+ base64_encode(outbuf, sizeof(outbuf), (char *)inbuf, i, 0);
+ tt_int_op(strlen(outbuf), OP_EQ, base64_encode_size(i, 0));
+ base64_encode(outbuf, sizeof(outbuf), (char *)inbuf, i,
+ BASE64_ENCODE_MULTILINE);
+ tt_int_op(strlen(outbuf), OP_EQ,
+ base64_encode_size(i, BASE64_ENCODE_MULTILINE));
+ }
+
+ done:
+ ;
+}
+
struct testcase_t util_format_tests[] = {
{ "unaligned_accessors", test_util_format_unaligned_accessors, 0,
NULL, NULL },
{ "base64_encode", test_util_format_base64_encode, 0, NULL, NULL },
- { "base64_decode_nopad", test_util_format_base64_decode_nopad, 0,
+ { "base64_decode_oddsize", test_util_format_base64_decode_oddsize, 0,
NULL, NULL },
{ "base64_decode", test_util_format_base64_decode, 0, NULL, NULL },
{ "base16_decode", test_util_format_base16_decode, 0, NULL, NULL },
@@ -382,6 +413,7 @@ struct testcase_t util_format_tests[] = {
NULL, NULL },
{ "base32_decode", test_util_format_base32_decode, 0,
NULL, NULL },
+ { "encoded_size", test_util_format_encoded_size, 0, NULL, NULL },
END_OF_TESTCASES
};
diff --git a/src/test/test_util_process.c b/src/test/test_util_process.c
index 4e75b97f3d..68ce6cfd40 100644
--- a/src/test/test_util_process.c
+++ b/src/test/test_util_process.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2016, The Tor Project, Inc. */
+/* Copyright (c) 2010-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define UTIL_PROCESS_PRIVATE
@@ -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 1e7160598c..2cd68cf118 100644
--- a/src/test/test_util_slow.c
+++ b/src/test/test_util_slow.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -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));
@@ -242,9 +242,9 @@ test_util_spawn_background_partial_read_impl(int exit_early)
#else
/* Check that we didn't read the end of file last time */
tt_assert(!eof);
- pos = tor_read_all_handle(process_handle->stdout_handle, stdout_buf,
+ 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,17 +270,17 @@ 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_handle, stdout_buf,
+ pos = tor_read_all_handle(process_handle->stdout_pipe, stdout_buf,
sizeof(stdout_buf) - 1,
process_handle, &eof);
tt_int_op(0,OP_EQ, pos);
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 ccb8d0c8ca..2b03173717 100644
--- a/src/test/test_workqueue.c
+++ b/src/test/test_workqueue.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "or.h"
@@ -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
@@ -200,7 +200,9 @@ add_work(threadpool_t *tp)
crypto_rand((char*)w->msg, 20);
w->msglen = 20;
++rsa_sent;
- return threadpool_queue_work(tp, workqueue_do_rsa, handle_reply, w);
+ return threadpool_queue_work_priority(tp,
+ WQ_PRI_MED,
+ workqueue_do_rsa, handle_reply, w);
} else {
ecdh_work_t *w = tor_malloc_zero(sizeof(*w));
w->serial = n_sent++;
@@ -286,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;
@@ -420,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 caeae13a38..7e9c47b48d 100644
--- a/src/test/testing_common.c
+++ b/src/test/testing_common.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
extern const char tor_git_revision[];
@@ -21,6 +21,7 @@ const char tor_git_revision[] = "";
#include "rephist.h"
#include "backtrace.h"
#include "test.h"
+#include "channelpadding.h"
#include <stdio.h>
#ifdef HAVE_FCNTL_H
@@ -32,13 +33,12 @@ const char tor_git_revision[] = "";
#include <direct.h>
#else
#include <dirent.h>
-#endif
+#endif /* defined(_WIN32) */
#include "or.h"
#ifdef USE_DMALLOC
#include <dmalloc.h>
-#include <openssl/crypto.h>
#include "main.h"
#endif
@@ -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("");
@@ -238,14 +238,15 @@ main(int c, const char **v)
#ifdef USE_DMALLOC
{
- int r = CRYPTO_set_mem_ex_functions(tor_malloc_, tor_realloc_, tor_free_);
- tor_assert(r);
+ int r = crypto_use_tor_alloc_functions();
+ tor_assert(r == 0);
}
-#endif
+#endif /* defined(USE_DMALLOC) */
update_approx_time(time(NULL));
options = options_new();
tor_threads_init();
+ tor_compress_init();
network_init();
@@ -304,10 +305,15 @@ main(int c, const char **v)
tor_free(errmsg);
return 1;
}
+
tor_set_failed_assertion_callback(an_assertion_failed);
init_pregenerated_keys();
+ channelpadding_new_consensus_params(NULL);
+
+ predicted_ports_init();
+
atexit(remove_directory);
int have_failed = (tinytest_main(c, v, testgroups) != 0);
diff --git a/src/test/testing_rsakeys.c b/src/test/testing_rsakeys.c
index 134770bb0d..7a24c0ed14 100644
--- a/src/test/testing_rsakeys.c
+++ b/src/test/testing_rsakeys.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -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) */
}