aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/bench.c19
-rw-r--r--src/test/fuzz/include.am79
-rw-r--r--src/test/include.am28
-rw-r--r--src/test/log_test_helpers.h4
-rw-r--r--src/test/rend_test_helpers.c1
-rw-r--r--src/test/rust_supp.txt1
-rw-r--r--src/test/test-memwipe.c2
-rw-r--r--src/test/test-timers.c8
-rw-r--r--src/test/test.c401
-rw-r--r--src/test/test.h17
-rw-r--r--src/test/test_addr.c155
-rw-r--r--src/test/test_address_set.c1
-rw-r--r--src/test/test_bridges.c614
-rw-r--r--src/test/test_buffers.c1
-rw-r--r--src/test/test_bwmgt.c233
-rw-r--r--src/test/test_cell_formats.c1
-rw-r--r--src/test/test_channel.c14
-rw-r--r--src/test/test_channelpadding.c16
-rw-r--r--src/test/test_circuitlist.c1
-rw-r--r--src/test/test_circuitmux.c47
-rw-r--r--src/test/test_compat_libevent.c61
-rw-r--r--src/test/test_config.c6
-rw-r--r--src/test/test_consdiffmgr.c1
-rw-r--r--src/test/test_containers.c1
-rw-r--r--src/test/test_controller.c56
-rw-r--r--src/test/test_controller_events.c75
-rw-r--r--src/test/test_crypto.c3
-rw-r--r--src/test/test_crypto_openssl.c4
-rw-r--r--src/test/test_crypto_slow.c1
-rw-r--r--src/test/test_dir.c329
-rw-r--r--src/test/test_dir_common.c4
-rw-r--r--src/test/test_dir_handle_get.c10
-rw-r--r--src/test/test_dos.c1
-rw-r--r--src/test/test_entrynodes.c221
-rw-r--r--src/test/test_extorport.c1
-rw-r--r--src/test/test_geoip.c578
-rw-r--r--src/test/test_helpers.c4
-rw-r--r--src/test/test_hs_cell.c1
-rw-r--r--src/test/test_hs_client.c34
-rw-r--r--src/test/test_hs_common.c37
-rw-r--r--src/test/test_hs_control.c5
-rw-r--r--src/test/test_hs_descriptor.c2
-rw-r--r--src/test/test_hs_intropoint.c3
-rw-r--r--src/test/test_hs_service.c28
-rw-r--r--src/test/test_mainloop.c142
-rw-r--r--src/test/test_microdesc.c48
-rw-r--r--src/test/test_nodelist.c1
-rw-r--r--src/test/test_oom.c1
-rw-r--r--src/test/test_options.c54
-rw-r--r--src/test/test_periodic_event.c329
-rw-r--r--src/test/test_policy.c80
-rw-r--r--src/test/test_protover.c12
-rw-r--r--src/test/test_relaycell.c818
-rw-r--r--src/test/test_relaycrypt.c185
-rw-r--r--src/test/test_routerlist.c180
-rw-r--r--src/test/test_scheduler.c75
-rw-r--r--src/test/test_shared_random.c33
-rw-r--r--src/test/test_storagedir.c1
-rw-r--r--src/test/test_tortls.c90
-rw-r--r--src/test/test_util.c74
-rw-r--r--src/test/test_util_format.c1
-rw-r--r--src/test/test_voting_schedule.c64
-rw-r--r--src/test/test_workqueue.c49
-rw-r--r--src/test/testing_common.c6
-rw-r--r--src/test/testing_rsakeys.c1
65 files changed, 4399 insertions, 954 deletions
diff --git a/src/test/bench.c b/src/test/bench.c
index 92d7a244f7..9ab23c9921 100644
--- a/src/test/bench.c
+++ b/src/test/bench.c
@@ -12,7 +12,7 @@
#include "or.h"
#include "onion_tap.h"
-#include "relay.h"
+#include "relay_crypto.h"
#include <openssl/opensslv.h>
#include <openssl/evp.h>
#include <openssl/ec.h>
@@ -23,6 +23,7 @@
#include "crypto_curve25519.h"
#include "onion_ntor.h"
#include "crypto_ed25519.h"
+#include "crypto_rand.h"
#include "consdiff.h"
#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID)
@@ -505,10 +506,10 @@ bench_cell_ops(void)
char key1[CIPHER_KEY_LEN], key2[CIPHER_KEY_LEN];
crypto_rand(key1, sizeof(key1));
crypto_rand(key2, sizeof(key2));
- or_circ->p_crypto = crypto_cipher_new(key1);
- or_circ->n_crypto = crypto_cipher_new(key2);
- or_circ->p_digest = crypto_digest_new();
- or_circ->n_digest = crypto_digest_new();
+ or_circ->crypto.f_crypto = crypto_cipher_new(key1);
+ or_circ->crypto.b_crypto = crypto_cipher_new(key2);
+ or_circ->crypto.f_digest = crypto_digest_new();
+ or_circ->crypto.b_digest = crypto_digest_new();
reset_perftime();
@@ -518,7 +519,8 @@ bench_cell_ops(void)
for (i = 0; i < iters; ++i) {
char recognized = 0;
crypt_path_t *layer_hint = NULL;
- relay_crypt(TO_CIRCUIT(or_circ), cell, d, &layer_hint, &recognized);
+ relay_decrypt_cell(TO_CIRCUIT(or_circ), cell, d,
+ &layer_hint, &recognized);
}
end = perftime();
printf("%sbound cells: %.2f ns per cell. (%.2f ns per byte of payload)\n",
@@ -527,10 +529,7 @@ bench_cell_ops(void)
NANOCOUNT(start,end,iters*CELL_PAYLOAD_SIZE));
}
- crypto_digest_free(or_circ->p_digest);
- crypto_digest_free(or_circ->n_digest);
- crypto_cipher_free(or_circ->p_crypto);
- crypto_cipher_free(or_circ->n_crypto);
+ relay_crypto_clear(&or_circ->crypto);
tor_free(or_circ);
tor_free(cell);
}
diff --git a/src/test/fuzz/include.am b/src/test/fuzz/include.am
index cd16dc05be..39d6d3c17b 100644
--- a/src/test/fuzz/include.am
+++ b/src/test/fuzz/include.am
@@ -17,8 +17,9 @@ FUZZING_LIBS = \
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@ @TOR_LIB_USERENV@ @CURVE25519_LIBS@ \
+ @TOR_LIBEVENT_LIBS@ \
+ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
+ @CURVE25519_LIBS@ \
@TOR_SYSTEMD_LIBS@ \
@TOR_LZMA_LIBS@ \
@TOR_ZSTD_LIBS@
@@ -46,6 +47,7 @@ LIBOSS_FUZZ_CPPFLAGS = $(FUZZING_CPPFLAGS) -DLLVM_FUZZ
LIBOSS_FUZZ_CFLAGS = $(FUZZING_CFLAGS)
# ===== AFL fuzzers
+if UNITTESTS_ENABLED
src_test_fuzz_fuzz_consensus_SOURCES = \
src/test/fuzz/fuzzing_common.c \
src/test/fuzz/fuzz_consensus.c
@@ -53,7 +55,9 @@ src_test_fuzz_fuzz_consensus_CPPFLAGS = $(FUZZING_CPPFLAGS)
src_test_fuzz_fuzz_consensus_CFLAGS = $(FUZZING_CFLAGS)
src_test_fuzz_fuzz_consensus_LDFLAGS = $(FUZZING_LDFLAG)
src_test_fuzz_fuzz_consensus_LDADD = $(FUZZING_LIBS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_fuzz_descriptor_SOURCES = \
src/test/fuzz/fuzzing_common.c \
src/test/fuzz/fuzz_descriptor.c
@@ -61,7 +65,9 @@ src_test_fuzz_fuzz_descriptor_CPPFLAGS = $(FUZZING_CPPFLAGS)
src_test_fuzz_fuzz_descriptor_CFLAGS = $(FUZZING_CFLAGS)
src_test_fuzz_fuzz_descriptor_LDFLAGS = $(FUZZING_LDFLAG)
src_test_fuzz_fuzz_descriptor_LDADD = $(FUZZING_LIBS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_fuzz_diff_SOURCES = \
src/test/fuzz/fuzzing_common.c \
src/test/fuzz/fuzz_diff.c
@@ -69,7 +75,9 @@ 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)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_fuzz_diff_apply_SOURCES = \
src/test/fuzz/fuzzing_common.c \
src/test/fuzz/fuzz_diff_apply.c
@@ -77,7 +85,9 @@ 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)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_fuzz_extrainfo_SOURCES = \
src/test/fuzz/fuzzing_common.c \
src/test/fuzz/fuzz_extrainfo.c
@@ -85,7 +95,9 @@ 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)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_fuzz_hsdescv2_SOURCES = \
src/test/fuzz/fuzzing_common.c \
src/test/fuzz/fuzz_hsdescv2.c
@@ -93,7 +105,9 @@ src_test_fuzz_fuzz_hsdescv2_CPPFLAGS = $(FUZZING_CPPFLAGS)
src_test_fuzz_fuzz_hsdescv2_CFLAGS = $(FUZZING_CFLAGS)
src_test_fuzz_fuzz_hsdescv2_LDFLAGS = $(FUZZING_LDFLAG)
src_test_fuzz_fuzz_hsdescv2_LDADD = $(FUZZING_LIBS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_fuzz_hsdescv3_SOURCES = \
src/test/fuzz/fuzzing_common.c \
src/test/fuzz/fuzz_hsdescv3.c
@@ -101,7 +115,9 @@ 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)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_fuzz_http_SOURCES = \
src/test/fuzz/fuzzing_common.c \
src/test/fuzz/fuzz_http.c
@@ -109,7 +125,9 @@ 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)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_fuzz_http_connect_SOURCES = \
src/test/fuzz/fuzzing_common.c \
src/test/fuzz/fuzz_http_connect.c
@@ -117,7 +135,9 @@ 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)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_fuzz_iptsv2_SOURCES = \
src/test/fuzz/fuzzing_common.c \
src/test/fuzz/fuzz_iptsv2.c
@@ -125,7 +145,9 @@ src_test_fuzz_fuzz_iptsv2_CPPFLAGS = $(FUZZING_CPPFLAGS)
src_test_fuzz_fuzz_iptsv2_CFLAGS = $(FUZZING_CFLAGS)
src_test_fuzz_fuzz_iptsv2_LDFLAGS = $(FUZZING_LDFLAG)
src_test_fuzz_fuzz_iptsv2_LDADD = $(FUZZING_LIBS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_fuzz_microdesc_SOURCES = \
src/test/fuzz/fuzzing_common.c \
src/test/fuzz/fuzz_microdesc.c
@@ -133,7 +155,9 @@ src_test_fuzz_fuzz_microdesc_CPPFLAGS = $(FUZZING_CPPFLAGS)
src_test_fuzz_fuzz_microdesc_CFLAGS = $(FUZZING_CFLAGS)
src_test_fuzz_fuzz_microdesc_LDFLAGS = $(FUZZING_LDFLAG)
src_test_fuzz_fuzz_microdesc_LDADD = $(FUZZING_LIBS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_fuzz_vrs_SOURCES = \
src/test/fuzz/fuzzing_common.c \
src/test/fuzz/fuzz_vrs.c
@@ -141,7 +165,9 @@ src_test_fuzz_fuzz_vrs_CPPFLAGS = $(FUZZING_CPPFLAGS)
src_test_fuzz_fuzz_vrs_CFLAGS = $(FUZZING_CFLAGS)
src_test_fuzz_fuzz_vrs_LDFLAGS = $(FUZZING_LDFLAG)
src_test_fuzz_fuzz_vrs_LDADD = $(FUZZING_LIBS)
+endif
+if UNITTESTS_ENABLED
FUZZERS = \
src/test/fuzz/fuzz-consensus \
src/test/fuzz/fuzz-descriptor \
@@ -155,93 +181,118 @@ FUZZERS = \
src/test/fuzz/fuzz-iptsv2 \
src/test/fuzz/fuzz-microdesc \
src/test/fuzz/fuzz-vrs
+endif
# ===== libfuzzer
if LIBFUZZER_ENABLED
+if UNITTESTS_ENABLED
src_test_fuzz_lf_fuzz_consensus_SOURCES = \
$(src_test_fuzz_fuzz_consensus_SOURCES)
src_test_fuzz_lf_fuzz_consensus_CPPFLAGS = $(LIBFUZZER_CPPFLAGS)
src_test_fuzz_lf_fuzz_consensus_CFLAGS = $(LIBFUZZER_CFLAGS)
src_test_fuzz_lf_fuzz_consensus_LDFLAGS = $(LIBFUZZER_LDFLAG)
src_test_fuzz_lf_fuzz_consensus_LDADD = $(LIBFUZZER_LIBS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_lf_fuzz_descriptor_SOURCES = \
$(src_test_fuzz_fuzz_descriptor_SOURCES)
src_test_fuzz_lf_fuzz_descriptor_CPPFLAGS = $(LIBFUZZER_CPPFLAGS)
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)
+endif
+if UNITTESTS_ENABLED
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)
+endif
+if UNITTESTS_ENABLED
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)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_lf_fuzz_extrainfo_SOURCES = \
$(src_test_fuzz_fuzz_extrainfo_SOURCES)
src_test_fuzz_lf_fuzz_extrainfo_CPPFLAGS = $(LIBFUZZER_CPPFLAGS)
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)
+endif
+if UNITTESTS_ENABLED
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)
+endif
+if UNITTESTS_ENABLED
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)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_lf_fuzz_http_SOURCES = \
$(src_test_fuzz_fuzz_http_SOURCES)
src_test_fuzz_lf_fuzz_http_CPPFLAGS = $(LIBFUZZER_CPPFLAGS)
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)
+endif
+if UNITTESTS_ENABLED
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)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_lf_fuzz_iptsv2_SOURCES = \
$(src_test_fuzz_fuzz_iptsv2_SOURCES)
src_test_fuzz_lf_fuzz_iptsv2_CPPFLAGS = $(LIBFUZZER_CPPFLAGS)
src_test_fuzz_lf_fuzz_iptsv2_CFLAGS = $(LIBFUZZER_CFLAGS)
src_test_fuzz_lf_fuzz_iptsv2_LDFLAGS = $(LIBFUZZER_LDFLAG)
src_test_fuzz_lf_fuzz_iptsv2_LDADD = $(LIBFUZZER_LIBS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_lf_fuzz_microdesc_SOURCES = \
$(src_test_fuzz_fuzz_microdesc_SOURCES)
src_test_fuzz_lf_fuzz_microdesc_CPPFLAGS = $(LIBFUZZER_CPPFLAGS)
src_test_fuzz_lf_fuzz_microdesc_CFLAGS = $(LIBFUZZER_CFLAGS)
src_test_fuzz_lf_fuzz_microdesc_LDFLAGS = $(LIBFUZZER_LDFLAG)
src_test_fuzz_lf_fuzz_microdesc_LDADD = $(LIBFUZZER_LIBS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_lf_fuzz_vrs_SOURCES = \
$(src_test_fuzz_fuzz_vrs_SOURCES)
src_test_fuzz_lf_fuzz_vrs_CPPFLAGS = $(LIBFUZZER_CPPFLAGS)
src_test_fuzz_lf_fuzz_vrs_CFLAGS = $(LIBFUZZER_CFLAGS)
src_test_fuzz_lf_fuzz_vrs_LDFLAGS = $(LIBFUZZER_LDFLAG)
src_test_fuzz_lf_fuzz_vrs_LDADD = $(LIBFUZZER_LIBS)
+endif
LIBFUZZER_FUZZERS = \
src/test/fuzz/lf-fuzz-consensus \
@@ -264,65 +315,89 @@ endif
# ===== oss-fuzz
if OSS_FUZZ_ENABLED
+if UNITTESTS_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)
src_test_fuzz_liboss_fuzz_consensus_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_liboss_fuzz_descriptor_a_SOURCES = \
$(src_test_fuzz_fuzz_descriptor_SOURCES)
src_test_fuzz_liboss_fuzz_descriptor_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS)
src_test_fuzz_liboss_fuzz_descriptor_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS)
+endif
+if UNITTESTS_ENABLED
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)
+endif
+if UNITTESTS_ENABLED
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)
+endif
+if UNITTESTS_ENABLED
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)
+endif
+if UNITTESTS_ENABLED
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)
+endif
+if UNITTESTS_ENABLED
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)
+endif
+if UNITTESTS_ENABLED
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)
+endif
+if UNITTESTS_ENABLED
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)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_liboss_fuzz_iptsv2_a_SOURCES = \
$(src_test_fuzz_fuzz_iptsv2_SOURCES)
src_test_fuzz_liboss_fuzz_iptsv2_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS)
src_test_fuzz_liboss_fuzz_iptsv2_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_liboss_fuzz_microdesc_a_SOURCES = \
$(src_test_fuzz_fuzz_microdesc_SOURCES)
src_test_fuzz_liboss_fuzz_microdesc_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS)
src_test_fuzz_liboss_fuzz_microdesc_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_liboss_fuzz_vrs_a_SOURCES = \
$(src_test_fuzz_fuzz_vrs_SOURCES)
src_test_fuzz_liboss_fuzz_vrs_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS)
src_test_fuzz_liboss_fuzz_vrs_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS)
+endif
OSS_FUZZ_FUZZERS = \
src/test/fuzz/liboss-fuzz-consensus.a \
diff --git a/src/test/include.am b/src/test/include.am
index 93fc008419..70df3aac14 100644
--- a/src/test/include.am
+++ b/src/test/include.am
@@ -10,7 +10,10 @@ TESTS_ENVIRONMENT = \
export TESTING_TOR_BINARY="$(TESTING_TOR_BINARY)"; \
export CARGO="$(CARGO)"; \
export EXTRA_CARGO_OPTIONS="$(EXTRA_CARGO_OPTIONS)"; \
- export CARGO_ONLINE="$(CARGO_ONLINE)";
+ export CARGO_ONLINE="$(CARGO_ONLINE)"; \
+ export CCLD="$(CCLD)"; \
+ chmod +x "$(abs_top_builddir)/link_rust.sh"; \
+ export RUSTFLAGS="-C linker=$(abs_top_builddir)/link_rust.sh";
TESTSCRIPTS = \
src/test/fuzz_static_testcases.sh \
@@ -80,7 +83,10 @@ src_test_AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \
# This seems to matter nowhere but on Windows, but I assure you that it
# matters a lot there, and is quite hard to debug if you forget to do it.
-src_test_test_SOURCES = \
+src_test_test_SOURCES =
+
+if UNITTESTS_ENABLED
+src_test_test_SOURCES += \
src/test/log_test_helpers.c \
src/test/hs_test_helpers.c \
src/test/rend_test_helpers.c \
@@ -89,7 +95,9 @@ src_test_test_SOURCES = \
src/test/test_addr.c \
src/test/test_address.c \
src/test/test_address_set.c \
+ src/test/test_bridges.c \
src/test/test_buffers.c \
+ src/test/test_bwmgt.c \
src/test/test_cell_formats.c \
src/test/test_cell_queue.c \
src/test/test_channel.c \
@@ -119,6 +127,7 @@ src_test_test_SOURCES = \
src/test/test_dos.c \
src/test/test_entryconn.c \
src/test/test_entrynodes.c \
+ src/test/test_geoip.c \
src/test/test_guardfraction.c \
src/test/test_extorport.c \
src/test/test_hs.c \
@@ -137,11 +146,13 @@ src_test_test_SOURCES = \
src/test/test_keypin.c \
src/test/test_link_handshake.c \
src/test/test_logging.c \
+ src/test/test_mainloop.c \
src/test/test_microdesc.c \
src/test/test_nodelist.c \
src/test/test_oom.c \
src/test/test_oos.c \
src/test/test_options.c \
+ src/test/test_periodic_event.c \
src/test/test_policy.c \
src/test/test_procmon.c \
src/test/test_proto_http.c \
@@ -151,6 +162,7 @@ src_test_test_SOURCES = \
src/test/test_pubsub.c \
src/test/test_relay.c \
src/test/test_relaycell.c \
+ src/test/test_relaycrypt.c \
src/test/test_rendcache.c \
src/test/test_replay.c \
src/test/test_router.c \
@@ -167,19 +179,24 @@ src_test_test_SOURCES = \
src/test/test_util.c \
src/test/test_util_format.c \
src/test/test_util_process.c \
+ src/test/test_voting_schedule.c \
src/test/test_helpers.c \
src/test/test_dns.c \
src/test/testing_common.c \
src/test/testing_rsakeys.c \
src/ext/tinytest.c
+endif
-src_test_test_slow_SOURCES = \
+src_test_test_slow_SOURCES =
+if UNITTESTS_ENABLED
+src_test_test_slow_SOURCES += \
src/test/test_slow.c \
src/test/test_crypto_slow.c \
src/test/test_util_slow.c \
src/test/testing_common.c \
src/test/testing_rsakeys.c \
src/ext/tinytest.c
+endif
src_test_test_memwipe_SOURCES = \
src/test/test-memwipe.c
@@ -326,6 +343,7 @@ src_test_test_hs_ntor_cl_AM_CPPFLAGS = \
-I"$(top_srcdir)/src/or"
+if UNITTESTS_ENABLED
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 \
@@ -333,9 +351,10 @@ src_test_test_bt_cl_LDADD = src/common/libor-testing.a \
src/trace/libor-trace.a \
$(rust_ldadd) \
@TOR_LIB_MATH@ \
- @TOR_LIB_WS32@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@
+ @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)
+endif
EXTRA_DIST += \
src/test/bt_test.py \
@@ -346,6 +365,7 @@ EXTRA_DIST += \
src/test/fuzz_static_testcases.sh \
src/test/slownacl_curve25519.py \
src/test/zero_length_keys.sh \
+ src/test/rust_supp.txt \
src/test/test_keygen.sh \
src/test/test_key_expiration.sh \
src/test/test_zero_length_keys.sh \
diff --git a/src/test/log_test_helpers.h b/src/test/log_test_helpers.h
index f74028a8ae..8057995070 100644
--- a/src/test/log_test_helpers.h
+++ b/src/test/log_test_helpers.h
@@ -90,6 +90,10 @@ void mock_dump_saved_logs(void);
assert_log_predicate(!mock_saved_log_has_message(str), \
"expected log to not contain " # str);
+#define expect_no_log_msg_containing(str) \
+ assert_log_predicate(!mock_saved_log_has_message_containing(str), \
+ "expected log to not contain " # str);
+
#define expect_log_severity(severity) \
assert_log_predicate(mock_saved_log_has_severity(severity), \
"expected log to contain severity " # severity);
diff --git a/src/test/rend_test_helpers.c b/src/test/rend_test_helpers.c
index 095bfecf21..9ac3894b0b 100644
--- a/src/test/rend_test_helpers.c
+++ b/src/test/rend_test_helpers.c
@@ -2,6 +2,7 @@
/* See LICENSE for licensing information */
#include "or.h"
+#include "crypto_rand.h"
#include "test.h"
#include "rendcommon.h"
#include "rend_test_helpers.h"
diff --git a/src/test/rust_supp.txt b/src/test/rust_supp.txt
new file mode 100644
index 0000000000..7fa50f3fb1
--- /dev/null
+++ b/src/test/rust_supp.txt
@@ -0,0 +1 @@
+leak:backtrace_alloc
diff --git a/src/test/test-memwipe.c b/src/test/test-memwipe.c
index 4beb613693..9e7dff5f63 100644
--- a/src/test/test-memwipe.c
+++ b/src/test/test-memwipe.c
@@ -7,7 +7,7 @@
#include <sys/types.h>
#include <stdlib.h>
-#include "crypto.h"
+#include "crypto_util.h"
#include "compat.h"
#include "util.h"
diff --git a/src/test/test-timers.c b/src/test/test-timers.c
index a0b5b535c2..f20f29578b 100644
--- a/src/test/test-timers.c
+++ b/src/test/test-timers.c
@@ -7,11 +7,9 @@
#include <stdio.h>
#include <string.h>
-#include <event2/event.h>
-
#include "compat.h"
#include "compat_libevent.h"
-#include "crypto.h"
+#include "crypto_rand.h"
#include "timers.h"
#include "util.h"
@@ -50,7 +48,7 @@ timer_cb(tor_timer_t *t, void *arg, const monotime_t *now_mono)
// printf("%d / %d\n",n_fired, N_TIMERS);
if (n_fired == n_active_timers) {
- event_base_loopbreak(tor_libevent_get_base());
+ tor_libevent_exit_loop_after_callback(tor_libevent_get_base());
}
}
@@ -90,7 +88,7 @@ main(int argc, char **argv)
--n_active_timers;
}
- event_base_loop(tor_libevent_get_base(), 0);
+ tor_libevent_run_event_loop(tor_libevent_get_base(), 0);
int64_t total_difference = 0;
uint64_t total_square_difference = 0;
diff --git a/src/test/test.c b/src/test/test.c
index 2e7d399322..aea3ad6595 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -9,6 +9,7 @@
**/
#include "orconfig.h"
+#include "crypto_rand.h"
#include <stdio.h>
#ifdef HAVE_FCNTL_H
@@ -26,7 +27,6 @@
/* These macros pull in declarations for some functions and structures that
* are typically file-private. */
-#define GEOIP_PRIVATE
#define ROUTER_PRIVATE
#define CIRCUITSTATS_PRIVATE
#define CIRCUITLIST_PRIVATE
@@ -41,7 +41,6 @@
#include "compress.h"
#include "config.h"
#include "connection_edge.h"
-#include "geoip.h"
#include "rendcommon.h"
#include "rendcache.h"
#include "test.h"
@@ -345,6 +344,18 @@ test_onion_queues(void *arg)
tor_free(onionskin);
}
+static crypto_cipher_t *crypto_rand_aes_cipher = NULL;
+
+// Mock replacement for crypto_rand: Generates bytes from a provided AES_CTR
+// cipher in <b>crypto_rand_aes_cipher</b>.
+static void
+crypto_rand_deterministic_aes(char *out, size_t n)
+{
+ tor_assert(crypto_rand_aes_cipher);
+ memset(out, 0, n);
+ crypto_cipher_crypt_inplace(crypto_rand_aes_cipher, out, n);
+}
+
static void
test_circuit_timeout(void *arg)
{
@@ -374,6 +385,11 @@ test_circuit_timeout(void *arg)
state = or_state_new();
+ // Use a deterministic RNG here, or else we'll get nondeterministic
+ // coverage in some of the circuitstats functions.
+ MOCK(crypto_rand, crypto_rand_deterministic_aes);
+ crypto_rand_aes_cipher = crypto_cipher_new("xyzzyplughplover");
+
circuitbuild_running_unit_tests();
#define timeout0 (build_time_t)(30*1000.0)
initial.Xm = 3000;
@@ -508,6 +524,8 @@ test_circuit_timeout(void *arg)
circuit_build_times_free_timeouts(&final);
or_state_free(state);
teardown_periodic_events();
+ UNMOCK(crypto_rand);
+ crypto_cipher_free(crypto_rand_aes_cipher);
}
/** Test encoding and parsing of rendezvous service descriptors. */
@@ -623,376 +641,6 @@ test_rend_fns(void *arg)
tor_free(intro_points_encrypted);
}
- /* Record odd numbered fake-IPs using ipv6, even numbered fake-IPs
- * using ipv4. Since our fake geoip database is the same between
- * ipv4 and ipv6, we should get the same result no matter which
- * address family we pick for each IP. */
-#define SET_TEST_ADDRESS(i) do { \
- if ((i) & 1) { \
- SET_TEST_IPV6(i); \
- tor_addr_from_in6(&addr, &in6); \
- } else { \
- tor_addr_from_ipv4h(&addr, (uint32_t) i); \
- } \
- } while (0)
-
- /* Make sure that country ID actually works. */
-#define SET_TEST_IPV6(i) \
- do { \
- set_uint32(in6.s6_addr + 12, htonl((uint32_t) (i))); \
- } while (0)
-#define CHECK_COUNTRY(country, val) do { \
- /* test ipv4 country lookup */ \
- tt_str_op(country, OP_EQ, \
- geoip_get_country_name(geoip_get_country_by_ipv4(val))); \
- /* test ipv6 country lookup */ \
- SET_TEST_IPV6(val); \
- tt_str_op(country, OP_EQ, \
- geoip_get_country_name(geoip_get_country_by_ipv6(&in6))); \
- } while (0)
-
-/** Run unit tests for GeoIP code. */
-static void
-test_geoip(void *arg)
-{
- int i, j;
- time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
- char *s = NULL, *v = NULL;
- const char *bridge_stats_1 =
- "bridge-stats-end 2010-08-12 13:27:30 (86400 s)\n"
- "bridge-ips zz=24,xy=8\n"
- "bridge-ip-versions v4=16,v6=16\n"
- "bridge-ip-transports <OR>=24\n",
- *dirreq_stats_1 =
- "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n"
- "dirreq-v3-ips ab=8\n"
- "dirreq-v3-reqs ab=8\n"
- "dirreq-v3-resp ok=0,not-enough-sigs=0,unavailable=0,not-found=0,"
- "not-modified=0,busy=0\n"
- "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n"
- "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n",
- *dirreq_stats_2 =
- "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n"
- "dirreq-v3-ips \n"
- "dirreq-v3-reqs \n"
- "dirreq-v3-resp ok=0,not-enough-sigs=0,unavailable=0,not-found=0,"
- "not-modified=0,busy=0\n"
- "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n"
- "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n",
- *dirreq_stats_3 =
- "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n"
- "dirreq-v3-ips \n"
- "dirreq-v3-reqs \n"
- "dirreq-v3-resp ok=8,not-enough-sigs=0,unavailable=0,not-found=0,"
- "not-modified=0,busy=0\n"
- "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n"
- "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n",
- *dirreq_stats_4 =
- "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n"
- "dirreq-v3-ips \n"
- "dirreq-v3-reqs \n"
- "dirreq-v3-resp ok=8,not-enough-sigs=0,unavailable=0,not-found=0,"
- "not-modified=0,busy=0\n"
- "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n"
- "dirreq-v3-tunneled-dl complete=0,timeout=0,running=4\n",
- *entry_stats_1 =
- "entry-stats-end 2010-08-12 13:27:30 (86400 s)\n"
- "entry-ips ab=8\n",
- *entry_stats_2 =
- "entry-stats-end 2010-08-12 13:27:30 (86400 s)\n"
- "entry-ips \n";
- tor_addr_t addr;
- struct in6_addr in6;
-
- /* Populate the DB a bit. Add these in order, since we can't do the final
- * 'sort' step. These aren't very good IP addresses, but they're perfectly
- * fine uint32_t values. */
- (void)arg;
- tt_int_op(0,OP_EQ, geoip_parse_entry("10,50,AB", AF_INET));
- tt_int_op(0,OP_EQ, geoip_parse_entry("52,90,XY", AF_INET));
- tt_int_op(0,OP_EQ, geoip_parse_entry("95,100,AB", AF_INET));
- tt_int_op(0,OP_EQ, geoip_parse_entry("\"105\",\"140\",\"ZZ\"", AF_INET));
- tt_int_op(0,OP_EQ, geoip_parse_entry("\"150\",\"190\",\"XY\"", AF_INET));
- tt_int_op(0,OP_EQ, geoip_parse_entry("\"200\",\"250\",\"AB\"", AF_INET));
-
- /* Populate the IPv6 DB equivalently with fake IPs in the same range */
- tt_int_op(0,OP_EQ, geoip_parse_entry("::a,::32,AB", AF_INET6));
- tt_int_op(0,OP_EQ, geoip_parse_entry("::34,::5a,XY", AF_INET6));
- tt_int_op(0,OP_EQ, geoip_parse_entry("::5f,::64,AB", AF_INET6));
- tt_int_op(0,OP_EQ, geoip_parse_entry("::69,::8c,ZZ", AF_INET6));
- tt_int_op(0,OP_EQ, geoip_parse_entry("::96,::be,XY", AF_INET6));
- tt_int_op(0,OP_EQ, geoip_parse_entry("::c8,::fa,AB", AF_INET6));
-
- /* We should have 4 countries: ??, ab, xy, zz. */
- tt_int_op(4,OP_EQ, geoip_get_n_countries());
- memset(&in6, 0, sizeof(in6));
-
- CHECK_COUNTRY("??", 3);
- CHECK_COUNTRY("ab", 32);
- CHECK_COUNTRY("??", 5);
- CHECK_COUNTRY("??", 51);
- CHECK_COUNTRY("xy", 150);
- CHECK_COUNTRY("xy", 190);
- CHECK_COUNTRY("??", 2000);
-
- tt_int_op(0,OP_EQ, geoip_get_country_by_ipv4(3));
- SET_TEST_IPV6(3);
- tt_int_op(0,OP_EQ, geoip_get_country_by_ipv6(&in6));
-
- get_options_mutable()->BridgeRelay = 1;
- get_options_mutable()->BridgeRecordUsageByCountry = 1;
- /* Put 9 observations in AB... */
- for (i=32; i < 40; ++i) {
- SET_TEST_ADDRESS(i);
- geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now-7200);
- }
- SET_TEST_ADDRESS(225);
- geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now-7200);
- /* and 3 observations in XY, several times. */
- for (j=0; j < 10; ++j)
- for (i=52; i < 55; ++i) {
- SET_TEST_ADDRESS(i);
- geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now-3600);
- }
- /* and 17 observations in ZZ... */
- for (i=110; i < 127; ++i) {
- SET_TEST_ADDRESS(i);
- geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now);
- }
- geoip_get_client_history(GEOIP_CLIENT_CONNECT, &s, &v);
- tt_assert(s);
- tt_assert(v);
- tt_str_op("zz=24,ab=16,xy=8",OP_EQ, s);
- tt_str_op("v4=16,v6=16",OP_EQ, v);
- tor_free(s);
- tor_free(v);
-
- /* Now clear out all the AB observations. */
- geoip_remove_old_clients(now-6000);
- geoip_get_client_history(GEOIP_CLIENT_CONNECT, &s, &v);
- tt_assert(s);
- tt_assert(v);
- tt_str_op("zz=24,xy=8",OP_EQ, s);
- tt_str_op("v4=16,v6=16",OP_EQ, v);
- tor_free(s);
- tor_free(v);
-
- /* 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_ptr_op(s, OP_EQ, NULL);
-
- /* Initialize stats and generate the bridge-stats history string out of
- * the connecting clients added above. */
- geoip_bridge_stats_init(now);
- s = geoip_format_bridge_stats(now + 86400);
- tt_assert(s);
- tt_str_op(bridge_stats_1,OP_EQ, s);
- tor_free(s);
-
- /* Stop collecting bridge stats and make sure we don't write a history
- * string anymore. */
- geoip_bridge_stats_term();
- s = geoip_format_bridge_stats(now + 86400);
- tt_ptr_op(s, OP_EQ, NULL);
-
- /* Stop being a bridge and start being a directory mirror that gathers
- * directory request statistics. */
- geoip_bridge_stats_term();
- get_options_mutable()->BridgeRelay = 0;
- get_options_mutable()->BridgeRecordUsageByCountry = 0;
- get_options_mutable()->DirReqStatistics = 1;
-
- /* Start testing dirreq statistics by making sure that we don't collect
- * dirreq stats without initializing them. */
- SET_TEST_ADDRESS(100);
- geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now);
- s = geoip_format_dirreq_stats(now + 86400);
- tt_ptr_op(s, OP_EQ, NULL);
-
- /* Initialize stats, note one connecting client, and generate the
- * dirreq-stats history string. */
- geoip_dirreq_stats_init(now);
- SET_TEST_ADDRESS(100);
- geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now);
- s = geoip_format_dirreq_stats(now + 86400);
- tt_str_op(dirreq_stats_1,OP_EQ, s);
- tor_free(s);
-
- /* Stop collecting stats, add another connecting client, and ensure we
- * don't generate a history string. */
- geoip_dirreq_stats_term();
- SET_TEST_ADDRESS(101);
- geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now);
- s = geoip_format_dirreq_stats(now + 86400);
- 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. */
- geoip_dirreq_stats_init(now);
- SET_TEST_ADDRESS(100);
- geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now);
- geoip_reset_dirreq_stats(now);
- s = geoip_format_dirreq_stats(now + 86400);
- tt_str_op(dirreq_stats_2,OP_EQ, s);
- tor_free(s);
-
- /* Note a successful network status response and make sure that it
- * appears in the history string. */
- geoip_note_ns_response(GEOIP_SUCCESS);
- s = geoip_format_dirreq_stats(now + 86400);
- tt_str_op(dirreq_stats_3,OP_EQ, s);
- tor_free(s);
-
- /* Start a tunneled directory request. */
- geoip_start_dirreq((uint64_t) 1, 1024, DIRREQ_TUNNELED);
- s = geoip_format_dirreq_stats(now + 86400);
- tt_str_op(dirreq_stats_4,OP_EQ, s);
- tor_free(s);
-
- /* Stop collecting directory request statistics and start gathering
- * entry stats. */
- geoip_dirreq_stats_term();
- get_options_mutable()->DirReqStatistics = 0;
- get_options_mutable()->EntryStatistics = 1;
-
- /* Start testing entry statistics by making sure that we don't collect
- * anything without initializing entry stats. */
- SET_TEST_ADDRESS(100);
- geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now);
- s = geoip_format_entry_stats(now + 86400);
- tt_ptr_op(s, OP_EQ, NULL);
-
- /* Initialize stats, note one connecting client, and generate the
- * entry-stats history string. */
- geoip_entry_stats_init(now);
- SET_TEST_ADDRESS(100);
- geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now);
- s = geoip_format_entry_stats(now + 86400);
- tt_str_op(entry_stats_1,OP_EQ, s);
- tor_free(s);
-
- /* Stop collecting stats, add another connecting client, and ensure we
- * don't generate a history string. */
- geoip_entry_stats_term();
- SET_TEST_ADDRESS(101);
- geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now);
- s = geoip_format_entry_stats(now + 86400);
- 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. */
- geoip_entry_stats_init(now);
- SET_TEST_ADDRESS(100);
- geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now);
- geoip_reset_entry_stats(now);
- s = geoip_format_entry_stats(now + 86400);
- tt_str_op(entry_stats_2,OP_EQ, s);
- tor_free(s);
-
- /* Test the OOM handler. Add a client, run the OOM. */
- geoip_entry_stats_init(now);
- SET_TEST_ADDRESS(100);
- geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL,
- now - (12 * 60 * 60));
- /* We've seen this 12 hours ago. Run the OOM, it should clean the entry
- * because it is above the minimum cutoff of 4 hours. */
- size_t bytes_removed = geoip_client_cache_handle_oom(now, 1000);
- tt_size_op(bytes_removed, OP_GT, 0);
-
- /* Do it again but this time with an entry with a lower cutoff. */
- geoip_entry_stats_init(now);
- SET_TEST_ADDRESS(100);
- geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL,
- now - (3 * 60 * 60));
- bytes_removed = geoip_client_cache_handle_oom(now, 1000);
- tt_size_op(bytes_removed, OP_EQ, 0);
-
- /* Stop collecting entry statistics. */
- geoip_entry_stats_term();
- get_options_mutable()->EntryStatistics = 0;
-
- done:
- tor_free(s);
- tor_free(v);
-}
-
-static void
-test_geoip_with_pt(void *arg)
-{
- time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
- char *s = NULL;
- int i;
- tor_addr_t addr;
- struct in6_addr in6;
-
- (void)arg;
- get_options_mutable()->BridgeRelay = 1;
- get_options_mutable()->BridgeRecordUsageByCountry = 1;
-
- memset(&in6, 0, sizeof(in6));
-
- /* No clients seen yet. */
- s = geoip_get_transport_history();
- tor_assert(!s);
-
- /* 4 connections without a pluggable transport */
- for (i=0; i < 4; ++i) {
- SET_TEST_ADDRESS(i);
- geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now-7200);
- }
-
- /* 9 connections with "alpha" */
- for (i=4; i < 13; ++i) {
- SET_TEST_ADDRESS(i);
- geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "alpha", now-7200);
- }
-
- /* one connection with "beta" */
- SET_TEST_ADDRESS(13);
- geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "beta", now-7200);
-
- /* 14 connections with "charlie" */
- for (i=14; i < 28; ++i) {
- SET_TEST_ADDRESS(i);
- geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "charlie", now-7200);
- }
-
- /* 131 connections with "ddr" */
- for (i=28; i < 159; ++i) {
- SET_TEST_ADDRESS(i);
- geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "ddr", now-7200);
- }
-
- /* 8 connections with "entropy" */
- for (i=159; i < 167; ++i) {
- SET_TEST_ADDRESS(i);
- geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "entropy", now-7200);
- }
-
- /* 2 connections from the same IP with two different transports. */
- SET_TEST_ADDRESS(++i);
- geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "fire", now-7200);
- geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "google", now-7200);
-
- /* Test the transport history string. */
- s = geoip_get_transport_history();
- tor_assert(s);
- tt_str_op(s,OP_EQ, "<OR>=8,alpha=16,beta=8,charlie=16,ddr=136,"
- "entropy=8,fire=8,google=8");
-
- /* Stop collecting entry statistics. */
- geoip_entry_stats_term();
- get_options_mutable()->EntryStatistics = 0;
-
- done:
- tor_free(s);
-}
-
-#undef SET_TEST_ADDRESS
-#undef SET_TEST_IPV6
-#undef CHECK_COUNTRY
-
/** Run unit tests for stats code. */
static void
test_stats(void *arg)
@@ -1166,8 +814,6 @@ static struct testcase_t test_array[] = {
{ "fast_handshake", test_fast_handshake, 0, NULL, NULL },
FORK(circuit_timeout),
FORK(rend_fns),
- ENT(geoip),
- FORK(geoip_with_pt),
FORK(stats),
END_OF_TESTCASES
@@ -1179,7 +825,9 @@ struct testgroup_t testgroups[] = {
{ "addr/", addr_tests },
{ "address/", address_tests },
{ "address_set/", address_set_tests },
+ { "bridges/", bridges_tests },
{ "buffer/", buffer_tests },
+ { "bwmgt/", bwmgt_tests },
{ "cellfmt/", cell_format_tests },
{ "cellqueue/", cell_queue_tests },
{ "channel/", channel_tests },
@@ -1205,11 +853,13 @@ struct testgroup_t testgroups[] = {
{ "dir/", dir_tests },
{ "dir_handle_get/", dir_handle_get_tests },
{ "dir/md/", microdesc_tests },
+ { "dir/voting-schedule/", voting_schedule_tests },
{ "dos/", dos_tests },
{ "entryconn/", entryconn_tests },
{ "entrynodes/", entrynodes_tests },
{ "guardfraction/", guardfraction_tests },
{ "extorport/", extorport_tests },
+ { "geoip/", geoip_tests },
{ "legacy_hs/", hs_tests },
{ "hs_cache/", hs_cache },
{ "hs_cell/", hs_cell_tests },
@@ -1224,10 +874,12 @@ struct testgroup_t testgroups[] = {
{ "introduce/", introduce_tests },
{ "keypin/", keypin_tests },
{ "link-handshake/", link_handshake_tests },
+ { "mainloop/", mainloop_tests },
{ "nodelist/", nodelist_tests },
{ "oom/", oom_tests },
{ "oos/", oos_tests },
{ "options/", options_tests },
+ { "periodic-event/" , periodic_event_tests },
{ "policy/" , policy_tests },
{ "procmon/", procmon_tests },
{ "proto/http/", proto_http_tests },
@@ -1236,6 +888,7 @@ struct testgroup_t testgroups[] = {
{ "pt/", pt_tests },
{ "relay/" , relay_tests },
{ "relaycell/", relaycell_tests },
+ { "relaycrypt/", relaycrypt_tests },
{ "rend_cache/", rend_cache_tests },
{ "replaycache/", replaycache_tests },
{ "router/", router_tests },
diff --git a/src/test/test.h b/src/test/test.h
index 26139fc5fe..63b2b30746 100644
--- a/src/test/test.h
+++ b/src/test/test.h
@@ -11,6 +11,8 @@
* \brief Macros and functions used by unit tests.
*/
+#define DEBUG_SMARTLIST 1
+
#include "compat.h"
#include "tinytest.h"
#define TT_EXIT_TEST_FUNCTION STMT_BEGIN goto done; STMT_END
@@ -72,6 +74,14 @@
I64_PRINTF_TYPE, I64_FORMAT, \
{print_ = (I64_PRINTF_TYPE) value_;}, {}, TT_EXIT_TEST_FUNCTION)
+/**
+ * Declare that the test is done, even though no tt___op() calls were made.
+ *
+ * For use when you only want to test calling something, but not check
+ * any values/pointers/etc afterwards.
+ */
+#define tt_finished() TT_EXIT_TEST_FUNCTION
+
const char *get_fname(const char *name);
const char *get_fname_rnd(const char *name);
struct crypto_pk_t *pk_generate(int idx);
@@ -178,6 +188,8 @@ extern struct testcase_t accounting_tests[];
extern struct testcase_t addr_tests[];
extern struct testcase_t address_tests[];
extern struct testcase_t address_set_tests[];
+extern struct testcase_t bridges_tests[];
+extern struct testcase_t bwmgt_tests[];
extern struct testcase_t buffer_tests[];
extern struct testcase_t cell_format_tests[];
extern struct testcase_t cell_queue_tests[];
@@ -208,6 +220,7 @@ extern struct testcase_t entryconn_tests[];
extern struct testcase_t entrynodes_tests[];
extern struct testcase_t guardfraction_tests[];
extern struct testcase_t extorport_tests[];
+extern struct testcase_t geoip_tests[];
extern struct testcase_t hs_tests[];
extern struct testcase_t hs_cache[];
extern struct testcase_t hs_cell_tests[];
@@ -223,11 +236,13 @@ extern struct testcase_t introduce_tests[];
extern struct testcase_t keypin_tests[];
extern struct testcase_t link_handshake_tests[];
extern struct testcase_t logging_tests[];
+extern struct testcase_t mainloop_tests[];
extern struct testcase_t microdesc_tests[];
extern struct testcase_t nodelist_tests[];
extern struct testcase_t oom_tests[];
extern struct testcase_t oos_tests[];
extern struct testcase_t options_tests[];
+extern struct testcase_t periodic_event_tests[];
extern struct testcase_t policy_tests[];
extern struct testcase_t procmon_tests[];
extern struct testcase_t proto_http_tests[];
@@ -237,6 +252,7 @@ extern struct testcase_t pubsub_tests[];
extern struct testcase_t pt_tests[];
extern struct testcase_t relay_tests[];
extern struct testcase_t relaycell_tests[];
+extern struct testcase_t relaycrypt_tests[];
extern struct testcase_t rend_cache_tests[];
extern struct testcase_t replaycache_tests[];
extern struct testcase_t router_tests[];
@@ -252,6 +268,7 @@ extern struct testcase_t tortls_tests[];
extern struct testcase_t util_tests[];
extern struct testcase_t util_format_tests[];
extern struct testcase_t util_process_tests[];
+extern struct testcase_t voting_schedule_tests[];
extern struct testcase_t dns_tests[];
extern struct testcase_t handle_tests[];
extern struct testcase_t sr_tests[];
diff --git a/src/test/test_addr.c b/src/test/test_addr.c
index e1a40b7e60..40db31320f 100644
--- a/src/test/test_addr.c
+++ b/src/test/test_addr.c
@@ -6,8 +6,10 @@
#define ADDRESSMAP_PRIVATE
#include "orconfig.h"
#include "or.h"
+#include "crypto_rand.h"
#include "test.h"
#include "addressmap.h"
+#include "log_test_helpers.h"
/** Mocking replacement: only handles localhost. */
static int
@@ -941,6 +943,158 @@ test_virtaddrmap(void *data)
;
}
+static const char *canned_data = NULL;
+static size_t canned_data_len = 0;
+
+/* Mock replacement for crypto_rand() that returns canned data from
+ * canned_data above. */
+static void
+crypto_canned(char *ptr, size_t n)
+{
+ if (canned_data_len) {
+ size_t to_copy = MIN(n, canned_data_len);
+ memcpy(ptr, canned_data, to_copy);
+ canned_data += to_copy;
+ canned_data_len -= to_copy;
+ n -= to_copy;
+ ptr += to_copy;
+ }
+ if (n) {
+ crypto_rand_unmocked(ptr, n);
+ }
+}
+
+static void
+test_virtaddrmap_persist(void *data)
+{
+ (void)data;
+ const char *a, *b, *c;
+ tor_addr_t addr;
+ char *ones = NULL;
+
+ addressmap_init();
+
+ // Try a hostname.
+ a = addressmap_register_virtual_address(RESOLVED_TYPE_HOSTNAME,
+ tor_strdup("foobar.baz"));
+ tt_assert(a);
+ tt_assert(!strcmpend(a, ".virtual"));
+
+ // mock crypto_rand to repeat the same result twice; make sure we get
+ // different outcomes. (Because even though the odds for receiving the
+ // same 80-bit address twice is only 1/2^40, it could still happen for
+ // some user -- but running our test through 2^40 iterations isn't
+ // reasonable.)
+ canned_data = "1234567890" // the first call returns this.
+ "1234567890" // the second call returns this.
+ "abcdefghij"; // the third call returns this.
+ canned_data_len = 30;
+ MOCK(crypto_rand, crypto_canned);
+
+ a = addressmap_register_virtual_address(RESOLVED_TYPE_HOSTNAME,
+ tor_strdup("quuxit.baz"));
+ b = addressmap_register_virtual_address(RESOLVED_TYPE_HOSTNAME,
+ tor_strdup("nescio.baz"));
+ tt_assert(a);
+ tt_assert(b);
+ tt_str_op(a, OP_EQ, "gezdgnbvgy3tqojq.virtual");
+ tt_str_op(b, OP_EQ, "mfrggzdfmztwq2lk.virtual");
+
+ // Now try something to get us an ipv4 address
+ UNMOCK(crypto_rand);
+ tt_int_op(0,OP_EQ, parse_virtual_addr_network("192.168.0.0/16",
+ AF_INET, 0, NULL));
+ a = addressmap_register_virtual_address(RESOLVED_TYPE_IPV4,
+ tor_strdup("foobar.baz"));
+ tt_assert(a);
+ tt_assert(!strcmpstart(a, "192.168."));
+ tor_addr_parse(&addr, a);
+ tt_int_op(AF_INET, OP_EQ, tor_addr_family(&addr));
+
+ b = addressmap_register_virtual_address(RESOLVED_TYPE_IPV4,
+ tor_strdup("quuxit.baz"));
+ tt_str_op(b, OP_NE, a);
+ tt_assert(!strcmpstart(b, "192.168."));
+
+ // Try some canned entropy and verify all the we discard duplicates,
+ // addresses that end with 0, and addresses that end with 255.
+ MOCK(crypto_rand, crypto_canned);
+ canned_data = "\x01\x02\x03\x04" // okay
+ "\x01\x02\x03\x04" // duplicate
+ "\x03\x04\x00\x00" // bad ending 1
+ "\x05\x05\x00\xff" // bad ending 2
+ "\x05\x06\x07\xf0"; // okay
+ canned_data_len = 20;
+ a = addressmap_register_virtual_address(RESOLVED_TYPE_IPV4,
+ tor_strdup("wumble.onion"));
+ b = addressmap_register_virtual_address(RESOLVED_TYPE_IPV4,
+ tor_strdup("wumpus.onion"));
+ tt_str_op(a, OP_EQ, "192.168.3.4");
+ tt_str_op(b, OP_EQ, "192.168.7.240");
+
+ // Now try IPv6!
+ UNMOCK(crypto_rand);
+ tt_int_op(0,OP_EQ, parse_virtual_addr_network("1010:F000::/20",
+ AF_INET6, 0, NULL));
+ a = addressmap_register_virtual_address(RESOLVED_TYPE_IPV6,
+ tor_strdup("foobar.baz"));
+ tt_assert(a);
+ tt_assert(!strcmpstart(a, "[1010:f"));
+ tor_addr_parse(&addr, a);
+ tt_int_op(AF_INET6, OP_EQ, tor_addr_family(&addr));
+
+ b = addressmap_register_virtual_address(RESOLVED_TYPE_IPV6,
+ tor_strdup("quuxit.baz"));
+ tt_str_op(b, OP_NE, a);
+ tt_assert(!strcmpstart(b, "[1010:f"));
+
+ // Try IPv6 with canned entropy, to make sure we detect duplicates.
+ MOCK(crypto_rand, crypto_canned);
+ canned_data = "acanthopterygian" // okay
+ "cinematographist" // okay
+ "acanthopterygian" // duplicate
+ "acanthopterygian" // duplicate
+ "acanthopterygian" // duplicate
+ "cinematographist" // duplicate
+ "coadministration"; // okay
+ canned_data_len = 16 * 7;
+ a = addressmap_register_virtual_address(RESOLVED_TYPE_IPV6,
+ tor_strdup("wuffle.baz"));
+ b = addressmap_register_virtual_address(RESOLVED_TYPE_IPV6,
+ tor_strdup("gribble.baz"));
+ c = addressmap_register_virtual_address(RESOLVED_TYPE_IPV6,
+ tor_strdup("surprisingly-legible.baz"));
+ tt_str_op(a, OP_EQ, "[1010:f16e:7468:6f70:7465:7279:6769:616e]");
+ tt_str_op(b, OP_EQ, "[1010:fe65:6d61:746f:6772:6170:6869:7374]");
+ tt_str_op(c, OP_EQ, "[1010:f164:6d69:6e69:7374:7261:7469:6f6e]");
+
+ // Try address exhaustion: make sure we can actually fail if we
+ // get too many already-existing addresses.
+ canned_data_len = 128*1024;
+ canned_data = ones = tor_malloc(canned_data_len);
+ memset(ones, 1, canned_data_len);
+ // There is some chance this one will fail if a previous random
+ // allocation gave out the address already.
+ a = addressmap_register_virtual_address(RESOLVED_TYPE_IPV4,
+ tor_strdup("might-work.onion"));
+ if (a) {
+ tt_str_op(a, OP_EQ, "192.168.1.1");
+ }
+ setup_capture_of_logs(LOG_WARN);
+ // This one will definitely fail, since we've set up the RNG to hand
+ // out "1" forever.
+ b = addressmap_register_virtual_address(RESOLVED_TYPE_IPV4,
+ tor_strdup("wont-work.onion"));
+ tt_assert(b == NULL);
+ expect_single_log_msg_containing("Ran out of virtual addresses!");
+
+ done:
+ UNMOCK(crypto_rand);
+ tor_free(ones);
+ addressmap_free_all();
+ teardown_capture_of_logs();
+}
+
static void
test_addr_localname(void *arg)
{
@@ -1095,6 +1249,7 @@ struct testcase_t addr_tests[] = {
ADDR_LEGACY(ip6_helpers),
ADDR_LEGACY(parse),
{ "virtaddr", test_virtaddrmap, 0, NULL, NULL },
+ { "virtaddr_persist", test_virtaddrmap_persist, TT_FORK, NULL, NULL },
{ "localname", test_addr_localname, 0, NULL, NULL },
{ "dup_ip", test_addr_dup_ip, 0, NULL, NULL },
{ "sockaddr_to_str", test_addr_sockaddr_to_str, 0, NULL, NULL },
diff --git a/src/test/test_address_set.c b/src/test/test_address_set.c
index df022f539a..f7441a6491 100644
--- a/src/test/test_address_set.c
+++ b/src/test/test_address_set.c
@@ -2,6 +2,7 @@
/* See LICENSE for licensing information */
#include "or.h"
+#include "crypto_rand.h"
#include "address_set.h"
#include "microdesc.h"
#include "networkstatus.h"
diff --git a/src/test/test_bridges.c b/src/test/test_bridges.c
new file mode 100644
index 0000000000..c44f791e0d
--- /dev/null
+++ b/src/test/test_bridges.c
@@ -0,0 +1,614 @@
+/* Copyright (c) 2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file test_bridges.c
+ * \brief Unittests for code in src/or/bridges.c
+ **/
+
+#define TOR_BRIDGES_PRIVATE
+#define PT_PRIVATE /* Only needed for the mock_* items below */
+
+#include <stdbool.h>
+
+#include "or.h"
+#include "address.h"
+#include "bridges.h"
+#include "config.h"
+#include "container.h"
+#include "transports.h"
+#include "util.h"
+
+/* Test suite stuff */
+#include "test.h"
+
+/**
+ * A mocked transport_t, constructed via mock_transport_get_by_name().
+ */
+static transport_t *mock_transport = NULL;
+
+/**
+ * Mock transport_get_by_name() to simply return a transport_t for the
+ * transport name that was input to it.
+ */
+static transport_t *
+mock_transport_get_by_name(const char *name)
+{
+ tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
+ uint16_t port = 9999;
+ int socksv = 9;
+ char *args = tor_strdup("foo=bar");
+
+ if (!mock_transport) {
+ tor_addr_parse(addr, "99.99.99.99");
+ mock_transport = transport_new(addr, port, name, socksv, args);
+ }
+
+ tor_free(addr);
+ tor_free(args);
+
+ return mock_transport;
+}
+
+#undef PT_PRIVATE /* defined(PT_PRIVATE) */
+
+/**
+ * Test helper: Add a variety of bridges to our global bridgelist.
+ */
+static void
+helper_add_bridges_to_bridgelist(void *arg)
+{
+ /* Note: the two bridges which do not have specified fingerprints will be
+ * internally stored as both having the same fingerprint of all-zero bytes.
+ */
+
+ (void)arg;
+ char *bridge0 = tor_strdup("6.6.6.6:6666");
+ char *bridge1 = tor_strdup("6.6.6.7:6667 "
+ "A10C4F666D27364036B562823E5830BC448E046A");
+ char *bridge2 = tor_strdup("obfs4 198.245.60.51:443 "
+ "752CF7825B3B9EA6A98C83AC41F7099D67007EA5 "
+ "cert=xpmQtKUqQ/6v5X7ijgYE/f03+l2/EuQ1dexjyUhh16wQlu/"
+ "cpXUGalmhDIlhuiQPNEKmKw iat-mode=0");
+ char *bridge3 = tor_strdup("banana 5.5.5.5:5555 "
+ "9D6AE1BD4FDF39721CE908966E79E16F9BFCCF2F");
+ char *bridge4 = tor_strdup("obfs4 1.2.3.4:1234 "
+ "foo=abcdefghijklmnopqrstuvwxyz");
+ char *bridge5 = tor_strdup("apple 4.4.4.4:4444 "
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA "
+ "foo=abcdefghijklmnopqrstuvwxyz");
+
+ mark_bridge_list();
+
+#define ADD_BRIDGE(bridge) \
+ bridge_line_t *bridge_line_ ##bridge = parse_bridge_line(bridge); \
+ if (!bridge_line_ ##bridge) { \
+ printf("Unparseable bridge line: '%s'", #bridge); \
+ } else { \
+ bridge_add_from_config(bridge_line_ ##bridge); \
+ } \
+ tor_free(bridge);
+
+ ADD_BRIDGE(bridge0);
+ ADD_BRIDGE(bridge1);
+ ADD_BRIDGE(bridge2);
+ ADD_BRIDGE(bridge3);
+ ADD_BRIDGE(bridge4);
+ ADD_BRIDGE(bridge5);
+#undef ADD_BRIDGES
+
+ sweep_bridge_list();
+}
+
+/**
+ * Make sure our test helper works too.
+ */
+static void
+test_bridges_helper_func_add_bridges_to_bridgelist(void *arg)
+{
+ helper_add_bridges_to_bridgelist(arg);
+ tt_finished();
+
+ done:
+ mark_bridge_list();
+ sweep_bridge_list();
+}
+
+/**
+ * Calling bridge_list_get() should create a new bridgelist if we
+ * didn't have one before.
+ */
+static void
+test_bridges_bridge_list_get_creates_new_bridgelist(void *arg)
+{
+ const smartlist_t *bridgelist = bridge_list_get();
+
+ (void)arg;
+
+ tt_ptr_op(bridgelist, OP_NE, NULL);
+
+ done:
+ return;
+}
+
+/**
+ * Calling clear_bridge_list() should remove all bridges from the bridgelist.
+ */
+static void
+test_bridges_clear_bridge_list(void *arg)
+{
+ const smartlist_t *bridgelist;
+ const smartlist_t *bridgelist_after;
+ const bridge_info_t *bridge;
+
+ helper_add_bridges_to_bridgelist(arg);
+ bridgelist = bridge_list_get();
+ tt_ptr_op(bridgelist, OP_NE, NULL);
+
+ bridge = smartlist_get(bridgelist, 0);
+ tt_ptr_op(bridge, OP_NE, NULL);
+
+ clear_bridge_list();
+ bridgelist_after = bridge_list_get();
+ tt_ptr_op(bridgelist_after, OP_NE, NULL);
+ tt_int_op(smartlist_len(bridgelist_after), OP_EQ, 0);
+
+ done:
+ return;
+}
+
+/**
+ * Calling bridge_get_addrport() should give me the address and port
+ * of the bridge. In this case, we sort the smartlist of bridges on
+ * fingerprints and choose the first one.
+ */
+static void
+test_bridges_bridge_get_addrport(void *arg)
+{
+ smartlist_t *bridgelist;
+ const bridge_info_t *bridge;
+ const tor_addr_port_t *addrport;
+
+ helper_add_bridges_to_bridgelist(arg);
+ bridgelist = (smartlist_t*)bridge_list_get();
+ tt_ptr_op(bridgelist, OP_NE, NULL);
+
+ // This should be the bridge at 6.6.6.6:6666 with fingerprint
+ // 0000000000000000000000000000000000000000
+ bridge = smartlist_get(bridgelist, 0);
+ tt_ptr_op(bridge, OP_NE, NULL);
+
+ addrport = bridge_get_addr_port(bridge);
+ tt_int_op(addrport->port, OP_EQ, 6666);
+
+ done:
+ mark_bridge_list();
+ sweep_bridge_list();
+}
+
+/**
+ * Calling get_configured_bridge_by_orports_digest() with two
+ * configured bridge orports and an invalid digest should return the
+ * bridge of the first addrport in the list.
+ */
+static void
+test_bridges_get_configured_bridge_by_orports_digest(void *arg)
+{
+ smartlist_t *orports = NULL;
+ const smartlist_t *bridgelist;
+ const bridge_info_t *bridge1;
+ const bridge_info_t *bridge2;
+ const bridge_info_t *ret;
+ tor_addr_port_t *addrport1;
+ tor_addr_port_t *addrport2;
+ const char *digest;
+
+ helper_add_bridges_to_bridgelist(arg);
+ bridgelist = bridge_list_get();
+ tt_ptr_op(bridgelist, OP_NE, NULL);
+
+ // This should be the bridge at 6.6.6.6:6666 with fingerprint
+ // 0000000000000000000000000000000000000000
+ bridge1 = smartlist_get(bridgelist, 0);
+ tt_ptr_op(bridge1, OP_NE, NULL);
+ // This should be the bridge at 6.6.6.7:6667 with fingerprint
+ // A10C4F666D27364036B562823E5830BC448E046A
+ bridge2 = smartlist_get(bridgelist, 1);
+ tt_ptr_op(bridge2, OP_NE, NULL);
+
+ addrport1 = (tor_addr_port_t*)bridge_get_addr_port(bridge1);
+ tt_int_op(addrport1->port, OP_EQ, 6666);
+ addrport2 = (tor_addr_port_t*)bridge_get_addr_port(bridge2);
+ tt_int_op(addrport2->port, OP_EQ, 6667);
+
+ orports = smartlist_new();
+ smartlist_add(orports, addrport1);
+ smartlist_add(orports, addrport2);
+
+ digest = "zzzzzzzzzzzzzzzz";
+
+ ret = get_configured_bridge_by_orports_digest(digest, orports);
+ tt_ptr_op(ret, OP_NE, NULL);
+
+ tt_assert(tor_addr_port_eq(addrport1, bridge_get_addr_port(ret)));
+
+ done:
+ smartlist_free(orports);
+
+ mark_bridge_list();
+ sweep_bridge_list();
+}
+
+/**
+ * Calling get_configured_bridge_by_addr_port_digest() with a digest that we do
+ * have and an addr:port pair we don't should return the bridge for that
+ * digest.
+ */
+static void
+test_bridges_get_configured_bridge_by_addr_port_digest_digest_only(void *arg)
+{
+ char digest[DIGEST_LEN];
+ bridge_info_t *bridge;
+ const char fingerprint[HEX_DIGEST_LEN] =
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+ tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
+ char ret_addr[16];
+ uint16_t port = 11111;
+ int ret;
+
+ helper_add_bridges_to_bridgelist(arg);
+
+ // We don't actually have a bridge with this addr:port pair
+ base16_decode(digest, DIGEST_LEN, fingerprint, HEX_DIGEST_LEN);
+ ret = tor_addr_parse(addr, "111.111.111.111");
+ tt_int_op(ret, OP_EQ, 2); // it returns the address family on success
+
+ bridge = get_configured_bridge_by_addr_port_digest(addr, port, digest);
+ tt_ptr_op(bridge, OP_NE, NULL);
+
+ tor_addr_to_str(ret_addr, &bridge_get_addr_port(bridge)->addr, 16, 0);
+ tt_str_op("4.4.4.4", OP_EQ, ret_addr);
+
+ done:
+ tor_free(addr);
+
+ mark_bridge_list();
+ sweep_bridge_list();
+}
+
+/**
+ * Calling get_configured_bridge_by_addr_port_digest() with only an
+ * addr:port (i.e. digest set to NULL) should return the bridge for
+ * that digest when there is such a bridge.
+ */
+static void
+test_bridges_get_configured_bridge_by_addr_port_digest_address_only(void *arg)
+{
+ bridge_info_t *bridge;
+ tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
+ char ret_addr[16];
+ uint16_t port = 6666;
+ int ret;
+
+ helper_add_bridges_to_bridgelist(arg);
+
+ ret = tor_addr_parse(addr, "6.6.6.6");
+ tt_int_op(ret, OP_EQ, 2); // it returns the address family on success
+
+ bridge = get_configured_bridge_by_addr_port_digest(addr, port, NULL);
+ tt_ptr_op(bridge, OP_NE, NULL);
+
+ tor_addr_to_str(ret_addr, &bridge_get_addr_port(bridge)->addr, 16, 0);
+ tt_str_op("6.6.6.6", OP_EQ, ret_addr);
+
+ done:
+ tor_free(addr);
+
+ mark_bridge_list();
+ sweep_bridge_list();
+}
+
+/**
+ * Calling get_configured_bridge_by_exact_addr_port_digest() with a digest that
+ * we do have, and an addr:port pair we don't have, should return NULL.
+ */
+static void
+test_bridges_get_configured_bridge_by_exact_addr_port_digest_donly(void *arg)
+{
+ char digest[DIGEST_LEN];
+ bridge_info_t *bridge;
+ const char fingerprint[HEX_DIGEST_LEN] =
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+ tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
+ uint16_t port = 11111;
+ int ret;
+
+ helper_add_bridges_to_bridgelist(arg);
+
+ // We don't actually have a bridge with this addr:port pair
+ base16_decode(digest, DIGEST_LEN, fingerprint, HEX_DIGEST_LEN);
+ ret = tor_addr_parse(addr, "111.111.111.111");
+ tt_int_op(ret, OP_EQ, 2); // it returns the address family on success
+
+ bridge = get_configured_bridge_by_exact_addr_port_digest(addr, port, digest);
+ tt_ptr_op(bridge, OP_EQ, NULL);
+
+ done:
+ tor_free(addr);
+
+ mark_bridge_list();
+ sweep_bridge_list();
+}
+
+/**
+ * Calling get_configured_bridge_by_exact_addr_port_digest() with a digest that
+ * we do have, and an addr:port pair we do have, should return the bridge.
+ */
+static void
+test_bridges_get_configured_bridge_by_exact_addr_port_digest_both(void *arg)
+{
+ char digest[DIGEST_LEN];
+ bridge_info_t *bridge;
+ const char fingerprint[HEX_DIGEST_LEN] =
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+ tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
+ uint16_t port = 4444;
+ char ret_addr[16];
+ int ret;
+
+ helper_add_bridges_to_bridgelist(arg);
+
+ base16_decode(digest, DIGEST_LEN, fingerprint, HEX_DIGEST_LEN);
+ ret = tor_addr_parse(addr, "4.4.4.4");
+ tt_int_op(ret, OP_EQ, 2); // it returns the address family on success
+
+ bridge = get_configured_bridge_by_exact_addr_port_digest(addr, port, digest);
+ tt_ptr_op(bridge, OP_NE, NULL);
+
+ tor_addr_to_str(ret_addr, &bridge_get_addr_port(bridge)->addr, 16, 0);
+ tt_str_op("4.4.4.4", OP_EQ, ret_addr);
+
+ done:
+ tor_free(addr);
+
+ mark_bridge_list();
+ sweep_bridge_list();
+}
+
+/**
+ * Calling get_configured_bridge_by_exact_addr_port_digest() with no digest,
+ * and an addr:port pair we do have, should return the bridge.
+ */
+static void
+test_bridges_get_configured_bridge_by_exact_addr_port_digest_aonly(void *arg)
+{
+ bridge_info_t *bridge;
+ tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
+ uint16_t port = 4444;
+ char ret_addr[16];
+ int ret;
+
+ helper_add_bridges_to_bridgelist(arg);
+
+ ret = tor_addr_parse(addr, "4.4.4.4");
+ tt_int_op(ret, OP_EQ, 2); // it returns the address family on success
+
+ bridge = get_configured_bridge_by_exact_addr_port_digest(addr, port, NULL);
+ tt_ptr_op(bridge, OP_NE, NULL);
+
+ tor_addr_to_str(ret_addr, &bridge_get_addr_port(bridge)->addr, 16, 0);
+ tt_str_op("4.4.4.4", OP_EQ, ret_addr);
+
+ done:
+ tor_free(addr);
+
+ mark_bridge_list();
+ sweep_bridge_list();
+}
+
+/**
+ * Calling find_bridge_by_digest() when we have a bridge with a known
+ * identity digest should return the bridge's information.
+ */
+static void
+test_bridges_find_bridge_by_digest_known(void *arg)
+{
+ char digest1[DIGEST_LEN];
+ bridge_info_t *bridge;
+ const char fingerprint[HEX_DIGEST_LEN] =
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+
+ helper_add_bridges_to_bridgelist(arg);
+
+ base16_decode(digest1, DIGEST_LEN, fingerprint, HEX_DIGEST_LEN);
+ bridge = find_bridge_by_digest(digest1);
+
+ tt_ptr_op(bridge, OP_NE, NULL);
+
+ /* We have to call bridge_get_rsa_id_digest() here because the bridge_info_t
+ * struct is opaquely defined in bridges.h. */
+ const uint8_t *digest2 = bridge_get_rsa_id_digest(bridge);
+
+ tt_mem_op((char*)digest2, OP_EQ, digest1, DIGEST_LEN);
+
+ done:
+ mark_bridge_list();
+ sweep_bridge_list();
+}
+
+/**
+ * Calling find_bridge_by_digest() when we do NOT have a bridge with that
+ * identity digest should return NULL.
+ */
+static void
+test_bridges_find_bridge_by_digest_unknown(void *arg)
+{
+ const char *fingerprint = "cccccccccccccccccccccccccccccccccccccccc";
+ bridge_info_t *bridge;
+
+ helper_add_bridges_to_bridgelist(arg);
+
+ bridge = find_bridge_by_digest(fingerprint);
+
+ tt_ptr_op(bridge, OP_EQ, NULL);
+
+ done:
+ mark_bridge_list();
+ sweep_bridge_list();
+}
+
+/**
+ * Calling bridge_resolve_conflicts() with an identical bridge to one we've
+ * already configure should mark the pre-configured bridge for removal.
+ */
+static void
+test_bridges_bridge_resolve_conflicts(void *arg)
+{
+ tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
+ uint16_t port = 4444;
+ const char *digest = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
+ const char *transport = "apple";
+ int ret;
+
+ helper_add_bridges_to_bridgelist(arg);
+
+ ret = tor_addr_parse(addr, "4.4.4.4");
+ tt_int_op(ret, OP_EQ, 2); // it returns the address family on success
+
+ bridge_resolve_conflicts((const tor_addr_t*)addr, port, digest, transport);
+
+ /* The bridge should now be marked for removal, and removed when we sweep the
+ * bridge_list */
+ sweep_bridge_list();
+ ret = addr_is_a_configured_bridge((const tor_addr_t*)addr, port, digest);
+ tt_int_op(ret, OP_EQ, 0);
+
+ done:
+ tor_free(addr);
+
+ mark_bridge_list();
+ sweep_bridge_list();
+}
+
+/**
+ * Calling transport_is_needed() with a transport we do need ("obfs4") and a
+ * bogus transport that we don't need should return 1 and 0, respectively.
+ */
+static void
+test_bridges_transport_is_needed(void *arg)
+{
+ int ret;
+
+ helper_add_bridges_to_bridgelist(arg);
+
+ ret = transport_is_needed("obfs4");
+ tt_int_op(ret, OP_EQ, 1);
+
+ ret = transport_is_needed("apowefjaoewpaief");
+ tt_int_op(ret, OP_EQ, 0);
+
+ done:
+ mark_bridge_list();
+ sweep_bridge_list();
+}
+
+/**
+ * Calling get_transport_by_bridge_addrport() with the address and port of a
+ * configured bridge which uses a pluggable transport when there is no global
+ * transport_list should return -1 and the transport_t should be NULL.
+ */
+static void
+test_bridges_get_transport_by_bridge_addrport_no_ptlist(void *arg)
+{
+ transport_t *transport = NULL;
+ tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
+ uint16_t port = 1234;
+ int ret;
+
+ helper_add_bridges_to_bridgelist(arg);
+
+ ret = tor_addr_parse(addr, "1.2.3.4");
+ tt_int_op(ret, OP_EQ, 2); // it returns the address family on success?
+
+ /* This will fail because the global transport_list has nothing in it, and so
+ * transport_get_by_name() has nothing to return, even the the bridge *did*
+ * say it had an obfs4 transport.
+ */
+ ret = get_transport_by_bridge_addrport((const tor_addr_t*)addr, port,
+ (const transport_t**)&transport);
+ tt_int_op(ret, OP_EQ, -1); // returns -1 on failure
+ tt_ptr_op(transport, OP_EQ, NULL);
+
+ done:
+ tor_free(addr);
+
+ mark_bridge_list();
+ sweep_bridge_list();
+}
+
+#define PT_PRIVATE
+
+/**
+ * Calling get_transport_by_bridge_addrport() with the address and port of a
+ * configured bridge which uses a pluggable transport should return 0 and set
+ * appropriate transport_t.
+ */
+static void
+test_bridges_get_transport_by_bridge_addrport(void *arg)
+{
+ transport_t *transport = NULL;
+ tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
+ uint16_t port = 1234;
+ int ret;
+
+ helper_add_bridges_to_bridgelist(arg);
+ mark_transport_list(); // Also initialise our transport_list
+
+ ret = tor_addr_parse(addr, "1.2.3.4");
+ tt_int_op(ret, OP_EQ, 2); // it returns the address family on success?
+
+ /* After we mock transport_get_by_name() to return a bogus transport_t with
+ * the name it was asked for, the call should succeed.
+ */
+ MOCK(transport_get_by_name, mock_transport_get_by_name);
+ ret = get_transport_by_bridge_addrport((const tor_addr_t*)addr, port,
+ (const transport_t**)&transport);
+ tt_int_op(ret, OP_EQ, 0); // returns 0 on success
+ tt_ptr_op(transport, OP_NE, NULL);
+ tt_str_op(transport->name, OP_EQ, "obfs4");
+
+ done:
+ UNMOCK(transport_get_by_name);
+
+ tor_free(addr);
+ transport_free(transport);
+
+ mark_bridge_list();
+ sweep_bridge_list();
+}
+
+#undef PT_PRIVATE /* defined(PT_PRIVATE) */
+
+#define B_TEST(name, flags) \
+ { #name, test_bridges_ ##name, (flags), NULL, NULL }
+
+struct testcase_t bridges_tests[] = {
+ B_TEST(helper_func_add_bridges_to_bridgelist, 0),
+ B_TEST(bridge_list_get_creates_new_bridgelist, 0),
+ B_TEST(clear_bridge_list, 0),
+ B_TEST(bridge_get_addrport, 0),
+ B_TEST(get_configured_bridge_by_orports_digest, 0),
+ B_TEST(get_configured_bridge_by_addr_port_digest_digest_only, 0),
+ B_TEST(get_configured_bridge_by_addr_port_digest_address_only, 0),
+ B_TEST(get_configured_bridge_by_exact_addr_port_digest_donly, 0),
+ B_TEST(get_configured_bridge_by_exact_addr_port_digest_both, 0),
+ B_TEST(get_configured_bridge_by_exact_addr_port_digest_aonly, 0),
+ B_TEST(find_bridge_by_digest_known, 0),
+ B_TEST(find_bridge_by_digest_unknown, 0),
+ B_TEST(bridge_resolve_conflicts, 0),
+ B_TEST(get_transport_by_bridge_addrport_no_ptlist, 0),
+ B_TEST(get_transport_by_bridge_addrport, 0),
+ B_TEST(transport_is_needed, 0),
+ END_OF_TESTCASES
+};
+
diff --git a/src/test/test_buffers.c b/src/test/test_buffers.c
index 057d9fa2dc..868f6a8ba4 100644
--- a/src/test/test_buffers.c
+++ b/src/test/test_buffers.c
@@ -8,6 +8,7 @@
#include "or.h"
#include "buffers.h"
#include "buffers_tls.h"
+#include "crypto_rand.h"
#include "proto_http.h"
#include "proto_socks.h"
#include "test.h"
diff --git a/src/test/test_bwmgt.c b/src/test/test_bwmgt.c
new file mode 100644
index 0000000000..463a36b24e
--- /dev/null
+++ b/src/test/test_bwmgt.c
@@ -0,0 +1,233 @@
+/* Copyright (c) 2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file test_bwmgt.c
+ * \brief tests for bandwidth management / token bucket functions
+ */
+
+#define TOKEN_BUCKET_PRIVATE
+
+#include "or.h"
+#include "test.h"
+
+#include "token_bucket.h"
+
+// an imaginary time, in timestamp units. Chosen so it will roll over.
+static const uint32_t START_TS = UINT32_MAX-10;
+static const int32_t KB = 1024;
+static const uint32_t GB = (U64_LITERAL(1) << 30);
+
+static void
+test_bwmgt_token_buf_init(void *arg)
+{
+ (void)arg;
+ token_bucket_rw_t b;
+
+ token_bucket_rw_init(&b, 16*KB, 64*KB, START_TS);
+ // Burst is correct
+ tt_uint_op(b.cfg.burst, OP_EQ, 64*KB);
+ // Rate is correct, within 1 percent.
+ {
+ uint32_t ticks_per_sec =
+ (uint32_t) monotime_msec_to_approx_coarse_stamp_units(1000);
+ uint32_t rate_per_sec = (b.cfg.rate * ticks_per_sec / TICKS_PER_STEP);
+
+ tt_uint_op(rate_per_sec, OP_GT, 16*KB-160);
+ tt_uint_op(rate_per_sec, OP_LT, 16*KB+160);
+ }
+ // Bucket starts out full:
+ tt_uint_op(b.last_refilled_at_timestamp, OP_EQ, START_TS);
+ tt_int_op(b.read_bucket.bucket, OP_EQ, 64*KB);
+
+ done:
+ ;
+}
+
+static void
+test_bwmgt_token_buf_adjust(void *arg)
+{
+ (void)arg;
+ token_bucket_rw_t b;
+
+ token_bucket_rw_init(&b, 16*KB, 64*KB, START_TS);
+
+ uint32_t rate_orig = b.cfg.rate;
+ // Increasing burst
+ token_bucket_rw_adjust(&b, 16*KB, 128*KB);
+ tt_uint_op(b.cfg.rate, OP_EQ, rate_orig);
+ tt_uint_op(b.read_bucket.bucket, OP_EQ, 64*KB);
+ tt_uint_op(b.cfg.burst, OP_EQ, 128*KB);
+
+ // Decreasing burst but staying above bucket
+ token_bucket_rw_adjust(&b, 16*KB, 96*KB);
+ tt_uint_op(b.cfg.rate, OP_EQ, rate_orig);
+ tt_uint_op(b.read_bucket.bucket, OP_EQ, 64*KB);
+ tt_uint_op(b.cfg.burst, OP_EQ, 96*KB);
+
+ // Decreasing burst below bucket,
+ token_bucket_rw_adjust(&b, 16*KB, 48*KB);
+ tt_uint_op(b.cfg.rate, OP_EQ, rate_orig);
+ tt_uint_op(b.read_bucket.bucket, OP_EQ, 48*KB);
+ tt_uint_op(b.cfg.burst, OP_EQ, 48*KB);
+
+ // Changing rate.
+ token_bucket_rw_adjust(&b, 32*KB, 48*KB);
+ tt_uint_op(b.cfg.rate, OP_GE, rate_orig*2 - 10);
+ tt_uint_op(b.cfg.rate, OP_LE, rate_orig*2 + 10);
+ tt_uint_op(b.read_bucket.bucket, OP_EQ, 48*KB);
+ tt_uint_op(b.cfg.burst, OP_EQ, 48*KB);
+
+ done:
+ ;
+}
+
+static void
+test_bwmgt_token_buf_dec(void *arg)
+{
+ (void)arg;
+ token_bucket_rw_t b;
+ token_bucket_rw_init(&b, 16*KB, 64*KB, START_TS);
+
+ // full-to-not-full.
+ tt_int_op(0, OP_EQ, token_bucket_rw_dec_read(&b, KB));
+ tt_int_op(b.read_bucket.bucket, OP_EQ, 63*KB);
+
+ // Full to almost-not-full
+ tt_int_op(0, OP_EQ, token_bucket_rw_dec_read(&b, 63*KB - 1));
+ tt_int_op(b.read_bucket.bucket, OP_EQ, 1);
+
+ // almost-not-full to empty.
+ tt_int_op(1, OP_EQ, token_bucket_rw_dec_read(&b, 1));
+ tt_int_op(b.read_bucket.bucket, OP_EQ, 0);
+
+ // reset bucket, try full-to-empty
+ token_bucket_rw_init(&b, 16*KB, 64*KB, START_TS);
+ tt_int_op(1, OP_EQ, token_bucket_rw_dec_read(&b, 64*KB));
+ tt_int_op(b.read_bucket.bucket, OP_EQ, 0);
+
+ // reset bucket, try underflow.
+ token_bucket_rw_init(&b, 16*KB, 64*KB, START_TS);
+ tt_int_op(1, OP_EQ, token_bucket_rw_dec_read(&b, 64*KB + 1));
+ tt_int_op(b.read_bucket.bucket, OP_EQ, -1);
+
+ // A second underflow does not make the bucket empty.
+ tt_int_op(0, OP_EQ, token_bucket_rw_dec_read(&b, 1000));
+ tt_int_op(b.read_bucket.bucket, OP_EQ, -1001);
+
+ done:
+ ;
+}
+
+static void
+test_bwmgt_token_buf_refill(void *arg)
+{
+ (void)arg;
+ token_bucket_rw_t b;
+ const uint32_t BW_SEC =
+ (uint32_t)monotime_msec_to_approx_coarse_stamp_units(1000);
+ token_bucket_rw_init(&b, 16*KB, 64*KB, START_TS);
+
+ /* Make the buffer much emptier, then let one second elapse. */
+ token_bucket_rw_dec_read(&b, 48*KB);
+ tt_int_op(b.read_bucket.bucket, OP_EQ, 16*KB);
+ tt_int_op(0, OP_EQ, token_bucket_rw_refill(&b, START_TS + BW_SEC));
+ tt_int_op(b.read_bucket.bucket, OP_GT, 32*KB - 300);
+ tt_int_op(b.read_bucket.bucket, OP_LT, 32*KB + 300);
+
+ /* Another half second. */
+ tt_int_op(0, OP_EQ, token_bucket_rw_refill(&b, START_TS + BW_SEC*3/2));
+ tt_int_op(b.read_bucket.bucket, OP_GT, 40*KB - 400);
+ tt_int_op(b.read_bucket.bucket, OP_LT, 40*KB + 400);
+ tt_uint_op(b.last_refilled_at_timestamp, OP_EQ, START_TS + BW_SEC*3/2);
+
+ /* No time: nothing happens. */
+ {
+ const uint32_t bucket_orig = b.read_bucket.bucket;
+ tt_int_op(0, OP_EQ, token_bucket_rw_refill(&b, START_TS + BW_SEC*3/2));
+ tt_int_op(b.read_bucket.bucket, OP_EQ, bucket_orig);
+ }
+
+ /* Another 30 seconds: fill the bucket. */
+ tt_int_op(0, OP_EQ, token_bucket_rw_refill(&b,
+ START_TS + BW_SEC*3/2 + BW_SEC*30));
+ tt_int_op(b.read_bucket.bucket, OP_EQ, b.cfg.burst);
+ tt_uint_op(b.last_refilled_at_timestamp, OP_EQ,
+ START_TS + BW_SEC*3/2 + BW_SEC*30);
+
+ /* Another 30 seconds: nothing happens. */
+ tt_int_op(0, OP_EQ, token_bucket_rw_refill(&b,
+ START_TS + BW_SEC*3/2 + BW_SEC*60));
+ tt_int_op(b.read_bucket.bucket, OP_EQ, b.cfg.burst);
+ tt_uint_op(b.last_refilled_at_timestamp, OP_EQ,
+ START_TS + BW_SEC*3/2 + BW_SEC*60);
+
+ /* Empty the bucket, let two seconds pass, and make sure that a refill is
+ * noticed. */
+ tt_int_op(1, OP_EQ, token_bucket_rw_dec_read(&b, b.cfg.burst));
+ tt_int_op(0, OP_EQ, b.read_bucket.bucket);
+ tt_int_op(1, OP_EQ, token_bucket_rw_refill(&b,
+ START_TS + BW_SEC*3/2 + BW_SEC*61));
+ tt_int_op(0, OP_EQ, token_bucket_rw_refill(&b,
+ START_TS + BW_SEC*3/2 + BW_SEC*62));
+ tt_int_op(b.read_bucket.bucket, OP_GT, 32*KB-400);
+ tt_int_op(b.read_bucket.bucket, OP_LT, 32*KB+400);
+
+ /* Underflow the bucket, make sure we detect when it has tokens again. */
+ tt_int_op(1, OP_EQ,
+ token_bucket_rw_dec_read(&b, b.read_bucket.bucket+16*KB));
+ tt_int_op(-16*KB, OP_EQ, b.read_bucket.bucket);
+ // half a second passes...
+ tt_int_op(0, OP_EQ, token_bucket_rw_refill(&b, START_TS + BW_SEC*64));
+ tt_int_op(b.read_bucket.bucket, OP_GT, -8*KB-300);
+ tt_int_op(b.read_bucket.bucket, OP_LT, -8*KB+300);
+ // a second passes
+ tt_int_op(1, OP_EQ, token_bucket_rw_refill(&b, START_TS + BW_SEC*65));
+ tt_int_op(b.read_bucket.bucket, OP_GT, 8*KB-400);
+ tt_int_op(b.read_bucket.bucket, OP_LT, 8*KB+400);
+
+ // We step a second backwards, and nothing happens.
+ tt_int_op(0, OP_EQ, token_bucket_rw_refill(&b, START_TS + BW_SEC*64));
+ tt_int_op(b.read_bucket.bucket, OP_GT, 8*KB-400);
+ tt_int_op(b.read_bucket.bucket, OP_LT, 8*KB+400);
+
+ // A ridiculous amount of time passes.
+ tt_int_op(0, OP_EQ, token_bucket_rw_refill(&b, INT32_MAX));
+ tt_int_op(b.read_bucket.bucket, OP_EQ, b.cfg.burst);
+
+ done:
+ ;
+}
+
+/* Test some helper functions we use within the token bucket interface. */
+static void
+test_bwmgt_token_buf_helpers(void *arg)
+{
+ uint32_t ret;
+
+ (void) arg;
+
+ /* The returned value will be OS specific but in any case, it should be
+ * greater than 1 since we are passing 1GB/sec rate. */
+ ret = rate_per_sec_to_rate_per_step(1 * GB);
+ tt_u64_op(ret, OP_GT, 1);
+
+ /* We default to 1 in case rate is 0. */
+ ret = rate_per_sec_to_rate_per_step(0);
+ tt_u64_op(ret, OP_EQ, 1);
+
+ done:
+ ;
+}
+
+#define BWMGT(name) \
+ { #name, test_bwmgt_ ## name , 0, NULL, NULL }
+
+struct testcase_t bwmgt_tests[] = {
+ BWMGT(token_buf_init),
+ BWMGT(token_buf_adjust),
+ BWMGT(token_buf_dec),
+ BWMGT(token_buf_refill),
+ BWMGT(token_buf_helpers),
+ END_OF_TESTCASES
+};
diff --git a/src/test/test_cell_formats.c b/src/test/test_cell_formats.c
index 88cdef383f..54d9716780 100644
--- a/src/test/test_cell_formats.c
+++ b/src/test/test_cell_formats.c
@@ -12,6 +12,7 @@
#include "connection_edge.h"
#include "connection_or.h"
#include "config.h"
+#include "crypto_rand.h"
#include "onion.h"
#include "onion_tap.h"
#include "onion_fast.h"
diff --git a/src/test/test_channel.c b/src/test/test_channel.c
index bdc9d32f78..76124a6e75 100644
--- a/src/test/test_channel.c
+++ b/src/test/test_channel.c
@@ -12,6 +12,7 @@
#include "circuitmux_ewma.h"
/* For var_cell_free */
#include "connection_or.h"
+#include "crypto_rand.h"
/* For packed_cell stuff */
#define RELAY_PRIVATE
#include "relay.h"
@@ -281,6 +282,7 @@ new_fake_channel(void)
chan->state = CHANNEL_STATE_OPEN;
chan->cmux = circuitmux_alloc();
+ circuitmux_set_policy(chan->cmux, &ewma_policy);
return chan;
}
@@ -543,6 +545,13 @@ test_channel_outbound_cell(void *arg)
(void) arg;
+ /* Set the test time to be mocked, since this test assumes that no
+ * time will pass, ewma values will not need to be re-scaled, and so on */
+ monotime_enable_test_mocking();
+ monotime_set_mock_time_nsec(U64_LITERAL(1000000000) * 12345);
+
+ cmux_ewma_set_options(NULL,NULL);
+
/* The channel will be freed so we need to hijack this so the scheduler
* doesn't get confused. */
MOCK(scheduler_release_channel, scheduler_release_channel_mock);
@@ -575,15 +584,13 @@ test_channel_outbound_cell(void *arg)
channel_register(chan);
tt_int_op(chan->registered, OP_EQ, 1);
/* Set EWMA policy so we can pick it when flushing. */
- channel_set_cmux_policy_everywhere(&ewma_policy);
+ circuitmux_set_policy(chan->cmux, &ewma_policy);
tt_ptr_op(circuitmux_get_policy(chan->cmux), OP_EQ, &ewma_policy);
/* Register circuit to the channel circid map which will attach the circuit
* to the channel's cmux as well. */
circuit_set_n_circid_chan(TO_CIRCUIT(circ), 42, chan);
tt_int_op(channel_num_circuits(chan), OP_EQ, 1);
- tt_assert(!TO_CIRCUIT(circ)->next_active_on_n_chan);
- tt_assert(!TO_CIRCUIT(circ)->prev_active_on_n_chan);
/* Test the cmux state. */
tt_ptr_op(TO_CIRCUIT(circ)->n_mux, OP_EQ, chan->cmux);
tt_int_op(circuitmux_is_circuit_attached(chan->cmux, TO_CIRCUIT(circ)),
@@ -659,6 +666,7 @@ test_channel_outbound_cell(void *arg)
tor_free(p_cell);
channel_free_all();
UNMOCK(scheduler_release_channel);
+ monotime_disable_test_mocking();
}
/* Test inbound cell. The callstack is:
diff --git a/src/test/test_channelpadding.c b/src/test/test_channelpadding.c
index 90da2163a6..4261bc1b67 100644
--- a/src/test/test_channelpadding.c
+++ b/src/test/test_channelpadding.c
@@ -15,7 +15,6 @@
#include "channelpadding.h"
#include "compat_libevent.h"
#include "config.h"
-#include <event2/event.h>
#include "compat_time.h"
#include "main.h"
#include "networkstatus.h"
@@ -65,7 +64,7 @@ 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());
+ tor_libevent_exit_loop_after_callback(tor_libevent_get_base());
return 0;
}
@@ -75,7 +74,7 @@ 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());
+ tor_libevent_exit_loop_after_callback(tor_libevent_get_base());
return 0;
}
@@ -85,7 +84,7 @@ 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());
+ tor_libevent_exit_loop_after_callback(tor_libevent_get_base());
return 0;
}
@@ -95,7 +94,7 @@ 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());
+ tor_libevent_exit_loop_after_callback(tor_libevent_get_base());
return 0;
}
@@ -105,7 +104,7 @@ 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());
+ tor_libevent_exit_loop_after_callback(tor_libevent_get_base());
return 0;
}
@@ -246,7 +245,7 @@ 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());
+ tor_libevent_exit_loop_after_callback(tor_libevent_get_base());
return;
}
@@ -264,7 +263,8 @@ dummy_nop_timer(void)
timer_schedule(dummy_timer, &timeout);
- event_base_loop(tor_libevent_get_base(), 0);
+ tor_libevent_run_event_loop(tor_libevent_get_base(), 0);
+
timer_free(dummy_timer);
}
diff --git a/src/test/test_circuitlist.c b/src/test/test_circuitlist.c
index d170009a9c..3794ffc2c6 100644
--- a/src/test/test_circuitlist.c
+++ b/src/test/test_circuitlist.c
@@ -9,6 +9,7 @@
#include "channel.h"
#include "circuitbuild.h"
#include "circuitlist.h"
+#include "circuitmux_ewma.h"
#include "hs_circuitmap.h"
#include "test.h"
#include "log_test_helpers.h"
diff --git a/src/test/test_circuitmux.c b/src/test/test_circuitmux.c
index 854f725054..c81d53ae51 100644
--- a/src/test/test_circuitmux.c
+++ b/src/test/test_circuitmux.c
@@ -3,14 +3,18 @@
#define TOR_CHANNEL_INTERNAL_
#define CIRCUITMUX_PRIVATE
+#define CIRCUITMUX_EWMA_PRIVATE
#define RELAY_PRIVATE
#include "or.h"
#include "channel.h"
#include "circuitmux.h"
+#include "circuitmux_ewma.h"
#include "relay.h"
#include "scheduler.h"
#include "test.h"
+#include <math.h>
+
/* XXXX duplicated function from test_circuitlist.c */
static channel_t *
new_fake_channel(void)
@@ -45,6 +49,7 @@ test_cmux_destroy_cell_queue(void *arg)
cmux = circuitmux_alloc();
tt_assert(cmux);
ch = new_fake_channel();
+ circuitmux_set_policy(cmux, &ewma_policy);
ch->has_queued_writes = has_queued_writes;
ch->wide_circ_ids = 1;
@@ -77,8 +82,50 @@ test_cmux_destroy_cell_queue(void *arg)
tor_free(dc);
}
+static void
+test_cmux_compute_ticks(void *arg)
+{
+ const int64_t NS_PER_S = 1000 * 1000 * 1000;
+ const int64_t START_NS = U64_LITERAL(1217709000)*NS_PER_S;
+ int64_t now;
+ double rem;
+ unsigned tick;
+ (void)arg;
+ circuitmux_ewma_free_all();
+ monotime_enable_test_mocking();
+
+ monotime_coarse_set_mock_time_nsec(START_NS);
+ cell_ewma_initialize_ticks();
+ const unsigned tick_zero = cell_ewma_get_current_tick_and_fraction(&rem);
+ tt_double_op(rem, OP_GT, -1e-9);
+ tt_double_op(rem, OP_LT, 1e-9);
+
+ /* 1.5 second later and we should still be in the same tick. */
+ now = START_NS + NS_PER_S + NS_PER_S/2;
+ monotime_coarse_set_mock_time_nsec(now);
+ tick = cell_ewma_get_current_tick_and_fraction(&rem);
+ tt_uint_op(tick, OP_EQ, tick_zero);
+#ifdef USING_32BIT_MSEC_HACK
+ const double tolerance = .0005;
+#else
+ const double tolerance = .00000001;
+#endif
+ tt_double_op(fabs(rem - .15), OP_LT, tolerance);
+
+ /* 25 second later and we should be in another tick. */
+ now = START_NS + NS_PER_S * 25;
+ monotime_coarse_set_mock_time_nsec(now);
+ tick = cell_ewma_get_current_tick_and_fraction(&rem);
+ tt_uint_op(tick, OP_EQ, tick_zero + 2);
+ tt_double_op(fabs(rem - .5), OP_LT, tolerance);
+
+ done:
+ ;
+}
+
struct testcase_t circuitmux_tests[] = {
{ "destroy_cell_queue", test_cmux_destroy_cell_queue, TT_FORK, NULL, NULL },
+ { "compute_ticks", test_cmux_compute_ticks, TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
diff --git a/src/test/test_compat_libevent.c b/src/test/test_compat_libevent.c
index 7dd8e65194..85f69bd626 100644
--- a/src/test/test_compat_libevent.c
+++ b/src/test/test_compat_libevent.c
@@ -10,7 +10,6 @@
#include "compat_libevent.h"
#include <event2/event.h>
-#include <event2/thread.h>
#include "log_test_helpers.h"
@@ -122,10 +121,70 @@ test_compat_libevent_header_version(void *ignored)
(void)0;
}
+/* Test for postloop events */
+
+/* Event callback to increment a counter. */
+static void
+increment_int_counter_cb(periodic_timer_t *timer, void *arg)
+{
+ (void)timer;
+ int *ctr = arg;
+ ++*ctr;
+}
+
+static int activated_counter = 0;
+
+/* Mainloop event callback to activate another mainloop event */
+static void
+activate_event_cb(mainloop_event_t *ev, void *arg)
+{
+ (void)ev;
+ mainloop_event_t **other_event = arg;
+ mainloop_event_activate(*other_event);
+ ++activated_counter;
+}
+
+static void
+test_compat_libevent_postloop_events(void *arg)
+{
+ (void)arg;
+ mainloop_event_t *a = NULL, *b = NULL;
+ periodic_timer_t *timed = NULL;
+
+ tor_libevent_postfork();
+
+ /* If postloop events don't work, then these events will activate one
+ * another ad infinitum and, and the periodic event will never occur. */
+ b = mainloop_event_postloop_new(activate_event_cb, &a);
+ a = mainloop_event_postloop_new(activate_event_cb, &b);
+
+ int counter = 0;
+ struct timeval fifty_ms = { 0, 10 * 1000 };
+ timed = periodic_timer_new(tor_libevent_get_base(), &fifty_ms,
+ increment_int_counter_cb, &counter);
+
+ mainloop_event_activate(a);
+ int r;
+ do {
+ r = tor_libevent_run_event_loop(tor_libevent_get_base(), 0);
+ if (r == -1)
+ break;
+ } while (counter < 5);
+
+ tt_int_op(activated_counter, OP_GE, 2);
+
+ done:
+ mainloop_event_free(a);
+ mainloop_event_free(b);
+ periodic_timer_free(timed);
+}
+
struct testcase_t compat_libevent_tests[] = {
{ "logging_callback", test_compat_libevent_logging_callback,
TT_FORK, NULL, NULL },
{ "header_version", test_compat_libevent_header_version, 0, NULL, NULL },
+ { "postloop_events", test_compat_libevent_postloop_events,
+ TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
diff --git a/src/test/test_config.c b/src/test/test_config.c
index 2bcc0cad7b..8662b832b8 100644
--- a/src/test/test_config.c
+++ b/src/test/test_config.c
@@ -20,12 +20,11 @@
#include "connection_edge.h"
#include "test.h"
#include "util.h"
-#include "address.h"
#include "connection_or.h"
#include "control.h"
#include "cpuworker.h"
#include "dirserv.h"
-#include "dirvote.h"
+#include "dirauth/dirvote.h"
#include "dns.h"
#include "entrynodes.h"
#include "transports.h"
@@ -42,9 +41,6 @@
#include "routerlist.h"
#include "routerset.h"
#include "statefile.h"
-#include "test.h"
-#include "transports.h"
-#include "util.h"
#include "test_helpers.h"
diff --git a/src/test/test_consdiffmgr.c b/src/test/test_consdiffmgr.c
index a9a4b6a98e..3b91baca39 100644
--- a/src/test/test_consdiffmgr.c
+++ b/src/test/test_consdiffmgr.c
@@ -9,6 +9,7 @@
#include "consdiff.h"
#include "consdiffmgr.h"
#include "cpuworker.h"
+#include "crypto_rand.h"
#include "networkstatus.h"
#include "routerparse.h"
#include "workqueue.h"
diff --git a/src/test/test_containers.c b/src/test/test_containers.c
index c4dba73750..3fc3523af4 100644
--- a/src/test/test_containers.c
+++ b/src/test/test_containers.c
@@ -5,6 +5,7 @@
#include "orconfig.h"
#include "or.h"
+#include "crypto_rand.h"
#include "fp_pair.h"
#include "test.h"
diff --git a/src/test/test_controller.c b/src/test/test_controller.c
index 1c285bb3a2..1a350f66c0 100644
--- a/src/test/test_controller.c
+++ b/src/test/test_controller.c
@@ -1470,6 +1470,61 @@ test_download_status_bridge(void *arg)
return;
}
+/** Set timeval to a mock date and time. This is necessary
+ * to make tor_gettimeofday() mockable. */
+static void
+mock_tor_gettimeofday(struct timeval *timeval)
+{
+ timeval->tv_sec = 1523405073;
+ timeval->tv_usec = 271645;
+}
+
+static void
+test_current_time(void *arg)
+{
+ /* We just need one of these to pass, it doesn't matter what's in it */
+ control_connection_t dummy;
+ /* Get results out */
+ char *answer = NULL;
+ const char *errmsg = NULL;
+
+ (void)arg;
+
+ /* We need these for storing the (mock) time. */
+ MOCK(tor_gettimeofday, mock_tor_gettimeofday);
+ struct timeval now;
+ tor_gettimeofday(&now);
+ char timebuf[ISO_TIME_LEN+1];
+
+ /* Case 1 - local time */
+ format_local_iso_time_nospace(timebuf, (time_t)now.tv_sec);
+ getinfo_helper_current_time(&dummy,
+ "current-time/local",
+ &answer, &errmsg);
+ tt_ptr_op(answer, OP_NE, NULL);
+ tt_ptr_op(errmsg, OP_EQ, NULL);
+ tt_str_op(answer, OP_EQ, timebuf);
+ tor_free(answer);
+ errmsg = NULL;
+
+ /* Case 2 - UTC time */
+ format_iso_time_nospace(timebuf, (time_t)now.tv_sec);
+ getinfo_helper_current_time(&dummy,
+ "current-time/utc",
+ &answer, &errmsg);
+ tt_ptr_op(answer, OP_NE, NULL);
+ tt_ptr_op(errmsg, OP_EQ, NULL);
+ tt_str_op(answer, OP_EQ, timebuf);
+ tor_free(answer);
+ errmsg = NULL;
+
+ done:
+ UNMOCK(tor_gettimeofday);
+ tor_free(answer);
+
+ return;
+}
+
struct testcase_t controller_tests[] = {
{ "add_onion_helper_keyarg_v2", test_add_onion_helper_keyarg_v2, 0,
NULL, NULL },
@@ -1486,6 +1541,7 @@ struct testcase_t controller_tests[] = {
NULL },
{ "download_status_desc", test_download_status_desc, 0, NULL, NULL },
{ "download_status_bridge", test_download_status_bridge, 0, NULL, NULL },
+ { "current_time", test_current_time, 0, NULL, NULL },
END_OF_TESTCASES
};
diff --git a/src/test/test_controller_events.c b/src/test/test_controller_events.c
index 901ad7ab3d..e81aea8d66 100644
--- a/src/test/test_controller_events.c
+++ b/src/test/test_controller_events.c
@@ -12,79 +12,6 @@
#include "test.h"
static void
-help_test_bucket_note_empty(uint32_t expected_msec_since_midnight,
- int tokens_before, size_t tokens_removed,
- uint32_t msec_since_epoch)
-{
- uint32_t timestamp_var = 0;
- struct timeval tvnow;
- tvnow.tv_sec = msec_since_epoch / 1000;
- tvnow.tv_usec = (msec_since_epoch % 1000) * 1000;
- connection_buckets_note_empty_ts(&timestamp_var, tokens_before,
- tokens_removed, &tvnow);
- tt_int_op(expected_msec_since_midnight, OP_EQ, timestamp_var);
-
- done:
- ;
-}
-
-static void
-test_cntev_bucket_note_empty(void *arg)
-{
- (void)arg;
-
- /* Two cases with nothing to note, because bucket was empty before;
- * 86442200 == 1970-01-02 00:00:42.200000 */
- help_test_bucket_note_empty(0, 0, 0, 86442200);
- help_test_bucket_note_empty(0, -100, 100, 86442200);
-
- /* Nothing to note, because bucket has not been emptied. */
- help_test_bucket_note_empty(0, 101, 100, 86442200);
-
- /* Bucket was emptied, note 42200 msec since midnight. */
- help_test_bucket_note_empty(42200, 101, 101, 86442200);
- help_test_bucket_note_empty(42200, 101, 102, 86442200);
-}
-
-static void
-test_cntev_bucket_millis_empty(void *arg)
-{
- struct timeval tvnow;
- (void)arg;
-
- /* 1970-01-02 00:00:42.200000 */
- tvnow.tv_sec = 86400 + 42;
- tvnow.tv_usec = 200000;
-
- /* Bucket has not been refilled. */
- tt_int_op(0, OP_EQ, bucket_millis_empty(0, 42120, 0, 100, &tvnow));
- tt_int_op(0, OP_EQ, bucket_millis_empty(-10, 42120, -10, 100, &tvnow));
-
- /* Bucket was not empty. */
- tt_int_op(0, OP_EQ, bucket_millis_empty(10, 42120, 20, 100, &tvnow));
-
- /* Bucket has been emptied 80 msec ago and has just been refilled. */
- tt_int_op(80, OP_EQ, bucket_millis_empty(-20, 42120, -10, 100, &tvnow));
- tt_int_op(80, OP_EQ, bucket_millis_empty(-10, 42120, 0, 100, &tvnow));
- tt_int_op(80, OP_EQ, bucket_millis_empty(0, 42120, 10, 100, &tvnow));
-
- /* Bucket has been emptied 180 msec ago, last refill was 100 msec ago
- * which was insufficient to make it positive, so cap msec at 100. */
- tt_int_op(100, OP_EQ, bucket_millis_empty(0, 42020, 1, 100, &tvnow));
-
- /* 1970-01-02 00:00:00:050000 */
- tvnow.tv_sec = 86400;
- tvnow.tv_usec = 50000;
-
- /* Last emptied 30 msec before midnight, tvnow is 50 msec after
- * midnight, that's 80 msec in total. */
- tt_int_op(80, OP_EQ, bucket_millis_empty(0, 86400000 - 30, 1, 100, &tvnow));
-
- done:
- ;
-}
-
-static void
add_testing_cell_stats_entry(circuit_t *circ, uint8_t command,
unsigned int waiting_time,
unsigned int removed, unsigned int exitward)
@@ -395,8 +322,6 @@ test_cntev_event_mask(void *arg)
{ #name, test_cntev_ ## name, flags, 0, NULL }
struct testcase_t controller_event_tests[] = {
- TEST(bucket_note_empty, TT_FORK),
- TEST(bucket_millis_empty, TT_FORK),
TEST(sum_up_cell_stats, TT_FORK),
TEST(append_cell_stats, TT_FORK),
TEST(format_cell_stats, TT_FORK),
diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c
index 83d97f2867..bb2e340dd2 100644
--- a/src/test/test_crypto.c
+++ b/src/test/test_crypto.c
@@ -5,7 +5,7 @@
#include "orconfig.h"
#define CRYPTO_CURVE25519_PRIVATE
-#define CRYPTO_PRIVATE
+#define CRYPTO_RAND_PRIVATE
#include "or.h"
#include "test.h"
#include "aes.h"
@@ -13,6 +13,7 @@
#include "siphash.h"
#include "crypto_curve25519.h"
#include "crypto_ed25519.h"
+#include "crypto_rand.h"
#include "ed25519_vectors.inc"
/** Run unit tests for Diffie-Hellman functionality. */
diff --git a/src/test/test_crypto_openssl.c b/src/test/test_crypto_openssl.c
index 090cb4242b..a016277508 100644
--- a/src/test/test_crypto_openssl.c
+++ b/src/test/test_crypto_openssl.c
@@ -5,9 +5,9 @@
#include "orconfig.h"
-#define CRYPTO_PRIVATE
+#define CRYPTO_RAND_PRIVATE
-#include "crypto.h"
+#include "crypto_rand.h"
#include "util.h"
#include "util_format.h"
#include "compat.h"
diff --git a/src/test/test_crypto_slow.c b/src/test/test_crypto_slow.c
index 2afb71ff5a..0e1f5bd227 100644
--- a/src/test/test_crypto_slow.c
+++ b/src/test/test_crypto_slow.c
@@ -9,6 +9,7 @@
#include "test.h"
#include "crypto_s2k.h"
#include "crypto_pwbox.h"
+#include "crypto_rand.h"
#if defined(HAVE_LIBSCRYPT_H) && defined(HAVE_LIBSCRYPT_SCRYPT)
#define HAVE_LIBSCRYPT
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index a33b23bcc9..37b015b72d 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -23,9 +23,10 @@
#include "config.h"
#include "control.h"
#include "crypto_ed25519.h"
+#include "crypto_rand.h"
#include "directory.h"
#include "dirserv.h"
-#include "dirvote.h"
+#include "dirauth/dirvote.h"
#include "entrynodes.h"
#include "hibernate.h"
#include "memarea.h"
@@ -35,12 +36,13 @@
#include "routerlist.h"
#include "routerparse.h"
#include "routerset.h"
-#include "shared_random_state.h"
+#include "dirauth/shared_random_state.h"
#include "test.h"
#include "test_dir_common.h"
#include "torcert.h"
#include "relay.h"
#include "log_test_helpers.h"
+#include "voting_schedule.h"
#define NS_MODULE dir
@@ -1499,6 +1501,13 @@ test_dir_measured_bw_kb(void *arg)
"bw=1024 junk=007\n",
"misc=junk node_id=$557365204145532d32353620696e73746561642e "
"bw=1024 junk=007\n",
+ /* check whether node_id can be at the end */
+ "bw=1024 node_id=$557365204145532d32353620696e73746561642e\n",
+ /* check whether node_id can be at the end and bw has something in front*/
+ "foo=bar bw=1024 node_id=$557365204145532d32353620696e73746561642e\n",
+ /* check whether node_id can be at the end and something in the
+ * in the middle of bw and node_id */
+ "bw=1024 foo=bar node_id=$557365204145532d32353620696e73746561642e\n",
"end"
};
const char *lines_fail[] = {
@@ -1538,12 +1547,18 @@ 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_int_op(measured_bw_line_parse(&mbwl, lines_fail[i]), OP_EQ, -1);
+ /* Testing only with line_is_after_headers = 1. Tests with
+ * line_is_after_headers = 0 in
+ * test_dir_measured_bw_kb_line_is_after_headers */
+ tt_assert(measured_bw_line_parse(&mbwl, lines_fail[i], 1) == -1);
}
for (i = 0; strcmp(lines_pass[i], "end"); i++) {
//fprintf(stderr, "Testing: %s %d\n", lines_pass[i], TOR_ISSPACE('\n'));
- tt_int_op(measured_bw_line_parse(&mbwl, lines_pass[i]), OP_EQ, 0);
+ /* Testing only with line_is_after_headers = 1. Tests with
+ * line_is_after_headers = 0 in
+ * test_dir_measured_bw_kb_line_is_after_headers */
+ tt_assert(measured_bw_line_parse(&mbwl, lines_pass[i], 1) == 0);
tt_assert(mbwl.bw_kb == 1024);
tt_assert(strcmp(mbwl.node_hex,
"557365204145532d32353620696e73746561642e") == 0);
@@ -1555,7 +1570,7 @@ test_dir_measured_bw_kb(void *arg)
/* Test dirserv_read_measured_bandwidths */
static void
-test_dir_dirserv_read_measured_bandwidths(void *arg)
+test_dir_dirserv_read_measured_bandwidths_empty(void *arg)
{
char *fname=NULL;
(void)arg;
@@ -1572,6 +1587,129 @@ test_dir_dirserv_read_measured_bandwidths(void *arg)
teardown_capture_of_logs();
}
+/* Unit tests for measured_bw_line_parse using line_is_after_headers flag.
+ * When the end of the header is detected (a first complete bw line is parsed),
+ * incomplete lines fail and give warnings, but do not give warnings if
+ * the header is not ended, allowing to ignore additional header lines. */
+static void
+test_dir_measured_bw_kb_line_is_after_headers(void *arg)
+{
+ (void)arg;
+ measured_bw_line_t mbwl;
+ const char *line_pass = \
+ "node_id=$557365204145532d32353620696e73746561642e bw=1024\n";
+ int i;
+ const char *lines_fail[] = {
+ "node_id=$557365204145532d32353620696e73746561642e \n",
+ "bw=1024\n",
+ "rtt=300\n",
+ "end"
+ };
+
+ setup_capture_of_logs(LOG_DEBUG);
+
+ /* Test bw lines when header has ended */
+ for (i = 0; strcmp(lines_fail[i], "end"); i++) {
+ tt_assert(measured_bw_line_parse(&mbwl, lines_fail[i], 1) == -1);
+ expect_log_msg_containing("Incomplete line in bandwidth file:");
+ mock_clean_saved_logs();
+ }
+
+ tt_assert(measured_bw_line_parse(&mbwl, line_pass, 1) == 0);
+
+ /* Test bw lines when header has not ended */
+ for (i = 0; strcmp(lines_fail[i], "end"); i++) {
+ tt_assert(measured_bw_line_parse(&mbwl, lines_fail[i], 0) == -1);
+ expect_log_msg_containing("Missing bw or node_id in bandwidth file line:");
+ mock_clean_saved_logs();
+ }
+
+ tt_assert(measured_bw_line_parse(&mbwl, line_pass, 0) == 0);
+
+ done:
+ teardown_capture_of_logs();
+}
+
+/* Test dirserv_read_measured_bandwidths with whole files. */
+static void
+test_dir_dirserv_read_measured_bandwidths(void *arg)
+{
+ (void)arg;
+ char *content = NULL;
+ time_t timestamp = time(NULL);
+ char *fname = tor_strdup(get_fname("V3BandwidthsFile"));
+
+ /* Test Torflow file only with timestamp*/
+ tor_asprintf(&content, "%ld", (long)timestamp);
+ write_str_to_file(fname, content, 0);
+ tor_free(content);
+ tt_int_op(-1, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL));
+
+ /* Test Torflow file with timestamp followed by '\n' */
+ tor_asprintf(&content, "%ld\n", (long)timestamp);
+ write_str_to_file(fname, content, 0);
+ tor_free(content);
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL));
+
+ /* Test Torflow complete file*/
+ const char *torflow_relay_lines=
+ "node_id=$557365204145532d32353620696e73746561642e bw=1024 "
+ "nick=Test measured_at=1523911725 updated_at=1523911725 "
+ "pid_error=4.11374090719 pid_error_sum=4.11374090719 "
+ "pid_bw=57136645 pid_delta=2.12168374577 circ_fail=0.2 "
+ "scanner=/filepath\n";
+
+ tor_asprintf(&content, "%ld\n%s", (long)timestamp, torflow_relay_lines);
+ write_str_to_file(fname, content, 0);
+ tor_free(content);
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL));
+
+ /* Test Torflow complete file including v1.1.0 headers */
+ const char *v110_header_lines=
+ "version=1.1.0\n"
+ "software=sbws\n"
+ "software_version=0.1.0\n"
+ "generator_started=2018-05-08T16:13:25\n"
+ "earliest_bandwidth=2018-05-08T16:13:26\n"
+ "====\n";
+
+ tor_asprintf(&content, "%ld\n%s%s", (long)timestamp, v110_header_lines,
+ torflow_relay_lines);
+ write_str_to_file(fname, content, 0);
+ tor_free(content);
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL));
+
+ /* Test Torflow with additional headers afer a correct bw line */
+ tor_asprintf(&content, "%ld\n%s%s", (long)timestamp, torflow_relay_lines,
+ v110_header_lines);
+ write_str_to_file(fname, content, 0);
+ tor_free(content);
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL));
+
+ /* Test Torflow with additional headers afer a correct bw line and more
+ * bw lines after the headers. */
+ tor_asprintf(&content, "%ld\n%s%s%s", (long)timestamp, torflow_relay_lines,
+ v110_header_lines, torflow_relay_lines);
+ write_str_to_file(fname, content, 0);
+ tor_free(content);
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL));
+
+ /* Test sbws file */
+ const char *sbws_relay_lines=
+ "node_id=$68A483E05A2ABDCA6DA5A3EF8DB5177638A27F80 "
+ "master_key_ed25519=YaqV4vbvPYKucElk297eVdNArDz9HtIwUoIeo0+cVIpQ "
+ "bw=760 nick=Test rtt=380 time=2018-05-08T16:13:26\n";
+
+ tor_asprintf(&content, "%ld\n%s%s", (long)timestamp, v110_header_lines,
+ sbws_relay_lines);
+ write_str_to_file(fname, content, 0);
+ tor_free(content);
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL));
+
+ done:
+ tor_free(fname);
+}
+
#define MBWC_INIT_TIME 1000
/** Do the measured bandwidth cache unit test */
@@ -2398,7 +2536,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);
+ voting_schedule_recalculate_timing(get_options(), now);
sr_state_init(0, 0);
tt_assert(!crypto_pk_read_private_key_from_string(sign_skey_1,
@@ -2936,8 +3074,9 @@ gen_routerstatus_for_umbw(int idx, time_t now)
rs->addr = 0x99008801;
rs->or_port = 443;
rs->dir_port = 8000;
- /* all flags but running cleared */
+ /* all flags but running and valid cleared */
rs->is_flagged_running = 1;
+ rs->is_valid = 1;
/*
* This one has measured bandwidth below the clip cutoff, and
* so shouldn't be clipped; we'll have to test that it isn't
@@ -3010,8 +3149,9 @@ gen_routerstatus_for_umbw(int idx, time_t now)
rs->addr = 0xC0000203;
rs->or_port = 500;
rs->dir_port = 1999;
- /* all flags but running cleared */
+ /* all flags but running and valid cleared */
rs->is_flagged_running = 1;
+ rs->is_valid = 1;
/*
* This one has unmeasured bandwidth below the clip cutoff, and
* so shouldn't be clipped; we'll have to test that it isn't
@@ -3033,7 +3173,7 @@ gen_routerstatus_for_umbw(int idx, time_t now)
if (vrs) {
vrs->microdesc = tor_malloc_zero(sizeof(vote_microdesc_hash_t));
tor_asprintf(&vrs->microdesc->microdesc_hash_line,
- "m 9,10,11,12,13,14,15,16,17 "
+ "m 25,26,27,28 "
"sha256=xyzajkldsdsajdadlsdjaslsdksdjlsdjsdaskdaaa%d\n",
idx);
}
@@ -3059,7 +3199,7 @@ vote_tweaks_for_umbw(networkstatus_t *v, int voter, time_t now)
smartlist_clear(v->supported_methods);
/* Method 17 is MIN_METHOD_TO_CLIP_UNMEASURED_BW_KB */
smartlist_split_string(v->supported_methods,
- "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17",
+ "25 26 27 28",
NULL, 0, -1);
/* If we're using a non-default clip bandwidth, add it to net_params */
if (alternate_clip_bw > 0) {
@@ -3221,9 +3361,9 @@ test_routerstatus_for_umbw(routerstatus_t *rs, time_t now)
tt_assert(!rs->is_fast);
tt_assert(!rs->is_possible_guard);
tt_assert(!rs->is_stable);
- /* (If it wasn't running it wouldn't be here) */
+ /* (If it wasn't running and valid it wouldn't be here) */
tt_assert(rs->is_flagged_running);
- tt_assert(!rs->is_valid);
+ tt_assert(rs->is_valid);
tt_assert(!rs->is_named);
/* This one should have measured bandwidth below the clip cutoff */
tt_assert(rs->has_bandwidth);
@@ -4082,34 +4222,19 @@ test_dir_download_status_increment(void *arg)
DL_WANT_ANY_DIRSERVER,
DL_SCHED_INCREMENT_ATTEMPT,
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 current_time = time(NULL);
- /* Provide some values for the schedules */
- delay0 = 10;
- delay1 = 99;
- delay2 = 20;
-
- /* 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);
+ const int delay0 = 10;
+ const int no_delay = 0;
+ const int schedule = 10;
+ const int schedule_no_initial_delay = 0;
/* 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->TestingBridgeBootstrapDownloadInitialDelay = schedule;
+ mock_options->TestingClientDownloadInitialDelay = schedule;
MOCK(get_options, mock_get_options);
@@ -4117,13 +4242,13 @@ test_dir_download_status_increment(void *arg)
* whether or not it was reset before being used */
/* regression test for 17750: no initial delay */
- mock_options->TestingClientDownloadSchedule = schedule_no_initial_delay;
+ mock_options->TestingClientDownloadInitialDelay = 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. */
/* regression test for 17750: exponential, no initial delay */
- mock_options->TestingClientDownloadSchedule = schedule_no_initial_delay;
+ mock_options->TestingClientDownloadInitialDelay = 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. */
@@ -4136,7 +4261,7 @@ test_dir_download_status_increment(void *arg)
tt_int_op(mock_get_options_calls, OP_GE, 1);
/* regression test for 17750: exponential, initial delay */
- mock_options->TestingClientDownloadSchedule = schedule;
+ mock_options->TestingClientDownloadInitialDelay = 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. */
@@ -4149,9 +4274,6 @@ test_dir_download_status_increment(void *arg)
tt_int_op(mock_get_options_calls, OP_GE, 1);
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;
@@ -5469,7 +5591,7 @@ mock_num_bridges_usable(int use_maybe_reachable)
* fallbacks.
*/
static void
-test_dir_find_dl_schedule(void* data)
+test_dir_find_dl_min_delay(void* data)
{
const char *str = (const char *)data;
@@ -5502,44 +5624,45 @@ test_dir_find_dl_schedule(void* data)
mock_num_bridges_usable);
download_status_t dls;
- smartlist_t server, client, server_cons, client_cons;
- smartlist_t client_boot_auth_only_cons, client_boot_auth_cons;
- smartlist_t client_boot_fallback_cons, bridge, bridge_bootstrap;
+
+ const int server=10, client=20, server_cons=30, client_cons=40;
+ const int client_boot_auth_only_cons=50, client_boot_auth_cons=60;
+ const int client_boot_fallback_cons=70, bridge=80, bridge_bootstrap=90;
mock_options = tor_malloc(sizeof(or_options_t));
reset_options(mock_options, &mock_get_options_calls);
MOCK(get_options, mock_get_options);
- mock_options->TestingServerDownloadSchedule = &server;
- mock_options->TestingClientDownloadSchedule = &client;
- mock_options->TestingServerConsensusDownloadSchedule = &server_cons;
- mock_options->TestingClientConsensusDownloadSchedule = &client_cons;
- mock_options->ClientBootstrapConsensusAuthorityOnlyDownloadSchedule =
- &client_boot_auth_only_cons;
- mock_options->ClientBootstrapConsensusAuthorityDownloadSchedule =
- &client_boot_auth_cons;
- mock_options->ClientBootstrapConsensusFallbackDownloadSchedule =
- &client_boot_fallback_cons;
- mock_options->TestingBridgeDownloadSchedule = &bridge;
- mock_options->TestingBridgeBootstrapDownloadSchedule = &bridge_bootstrap;
+ mock_options->TestingServerDownloadInitialDelay = server;
+ mock_options->TestingClientDownloadInitialDelay = client;
+ mock_options->TestingServerConsensusDownloadInitialDelay = server_cons;
+ mock_options->TestingClientConsensusDownloadInitialDelay = client_cons;
+ mock_options->ClientBootstrapConsensusAuthorityOnlyDownloadInitialDelay =
+ client_boot_auth_only_cons;
+ mock_options->ClientBootstrapConsensusAuthorityDownloadInitialDelay =
+ client_boot_auth_cons;
+ mock_options->ClientBootstrapConsensusFallbackDownloadInitialDelay =
+ client_boot_fallback_cons;
+ mock_options->TestingBridgeDownloadInitialDelay = bridge;
+ mock_options->TestingBridgeBootstrapDownloadInitialDelay = bridge_bootstrap;
dls.schedule = DL_SCHED_GENERIC;
/* client */
mock_options->ClientOnly = 1;
- tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, &client);
+ tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ, client);
mock_options->ClientOnly = 0;
/* dir mode */
mock_options->DirPort_set = 1;
mock_options->DirCache = 1;
- tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, &server);
+ tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ, server);
mock_options->DirPort_set = 0;
mock_options->DirCache = 0;
dls.schedule = DL_SCHED_CONSENSUS;
/* public server mode */
mock_options->ORPort_set = 1;
- tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, &server_cons);
+ tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ, server_cons);
mock_options->ORPort_set = 0;
/* client and bridge modes */
@@ -5548,30 +5671,30 @@ test_dir_find_dl_schedule(void* data)
dls.want_authority = 1;
/* client */
mock_options->ClientOnly = 1;
- tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ,
- &client_boot_auth_cons);
+ tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ,
+ client_boot_auth_cons);
mock_options->ClientOnly = 0;
/* bridge relay */
mock_options->ORPort_set = 1;
mock_options->BridgeRelay = 1;
- tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ,
- &client_boot_auth_cons);
+ tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ,
+ client_boot_auth_cons);
mock_options->ORPort_set = 0;
mock_options->BridgeRelay = 0;
dls.want_authority = 0;
/* client */
mock_options->ClientOnly = 1;
- tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ,
- &client_boot_fallback_cons);
+ tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ,
+ client_boot_fallback_cons);
mock_options->ClientOnly = 0;
/* bridge relay */
mock_options->ORPort_set = 1;
mock_options->BridgeRelay = 1;
- tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ,
- &client_boot_fallback_cons);
+ tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ,
+ client_boot_fallback_cons);
mock_options->ORPort_set = 0;
mock_options->BridgeRelay = 0;
@@ -5579,30 +5702,30 @@ test_dir_find_dl_schedule(void* data)
/* dls.want_authority is ignored */
/* client */
mock_options->ClientOnly = 1;
- tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ,
- &client_boot_auth_only_cons);
+ tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ,
+ client_boot_auth_only_cons);
mock_options->ClientOnly = 0;
/* bridge relay */
mock_options->ORPort_set = 1;
mock_options->BridgeRelay = 1;
- tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ,
- &client_boot_auth_only_cons);
+ tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ,
+ client_boot_auth_only_cons);
mock_options->ORPort_set = 0;
mock_options->BridgeRelay = 0;
}
} else {
/* client */
mock_options->ClientOnly = 1;
- tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ,
- &client_cons);
+ tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ,
+ client_cons);
mock_options->ClientOnly = 0;
/* bridge relay */
mock_options->ORPort_set = 1;
mock_options->BridgeRelay = 1;
- tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ,
- &client_cons);
+ tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ,
+ client_cons);
mock_options->ORPort_set = 0;
mock_options->BridgeRelay = 0;
}
@@ -5612,9 +5735,9 @@ test_dir_find_dl_schedule(void* data)
mock_options->ClientOnly = 1;
mock_options->UseBridges = 1;
if (num_bridges_usable(0) > 0) {
- tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, &bridge);
+ tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ, bridge);
} else {
- tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, &bridge_bootstrap);
+ tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ, bridge_bootstrap);
}
done:
@@ -5634,9 +5757,8 @@ test_dir_assumed_flags(void *arg)
memarea_t *area = memarea_new();
routerstatus_t *rs = NULL;
- /* First, we should always assume that the Running flag is set, even
- * when it isn't listed, since the consensus method is always
- * higher than 4. */
+ /* We can assume that consensus method is higher than 24, so Running and
+ * Valid are always implicitly set */
const char *str1 =
"r example hereiswhereyouridentitygoes 2015-08-30 12:00:00 "
"192.168.0.1 9001 0\n"
@@ -5645,17 +5767,6 @@ test_dir_assumed_flags(void *arg)
const char *cp = str1;
rs = routerstatus_parse_entry_from_string(area, &cp, tokens, NULL, NULL,
- 23, FLAV_MICRODESC);
- tt_assert(rs);
- tt_assert(rs->is_flagged_running);
- tt_assert(! rs->is_valid);
- tt_assert(! rs->is_exit);
- tt_assert(rs->is_fast);
- routerstatus_free(rs);
-
- /* With method 24 or later, we can assume "valid" is set. */
- cp = str1;
- rs = routerstatus_parse_entry_from_string(area, &cp, tokens, NULL, NULL,
24, FLAV_MICRODESC);
tt_assert(rs);
tt_assert(rs->is_flagged_running);
@@ -5788,22 +5899,10 @@ test_dir_networkstatus_consensus_has_ipv6(void *arg)
/* Test the bounds for A lines in the NS consensus */
mock_options->UseMicrodescriptors = 0;
- mock_networkstatus->consensus_method = MIN_METHOD_FOR_A_LINES;
- has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
- tt_assert(has_ipv6);
-
- mock_networkstatus->consensus_method = MIN_METHOD_FOR_A_LINES + 1;
+ mock_networkstatus->consensus_method = MIN_SUPPORTED_CONSENSUS_METHOD;
has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
tt_assert(has_ipv6);
- mock_networkstatus->consensus_method = MIN_METHOD_FOR_A_LINES + 20;
- has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
- tt_assert(has_ipv6);
-
- mock_networkstatus->consensus_method = MIN_METHOD_FOR_A_LINES - 1;
- has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
- tt_assert(!has_ipv6);
-
/* Test the bounds for A lines in the microdesc consensus */
mock_options->UseMicrodescriptors = 1;
@@ -5812,6 +5911,10 @@ test_dir_networkstatus_consensus_has_ipv6(void *arg)
has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
tt_assert(has_ipv6);
+ mock_networkstatus->consensus_method = MAX_SUPPORTED_CONSENSUS_METHOD + 20;
+ has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
+ tt_assert(has_ipv6);
+
mock_networkstatus->consensus_method =
MIN_METHOD_FOR_A_LINES_IN_MICRODESC_CONSENSUS + 1;
has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
@@ -5926,9 +6029,11 @@ struct testcase_t dir_tests[] = {
DIR_LEGACY(versions),
DIR_LEGACY(fp_pairs),
DIR(split_fps, 0),
- DIR_LEGACY(dirserv_read_measured_bandwidths),
+ DIR_LEGACY(dirserv_read_measured_bandwidths_empty),
DIR_LEGACY(measured_bw_kb),
+ DIR_LEGACY(measured_bw_kb_line_is_after_headers),
DIR_LEGACY(measured_bw_kb_cache),
+ DIR_LEGACY(dirserv_read_measured_bandwidths),
DIR_LEGACY(param_voting),
DIR(param_voting_lookup, 0),
DIR_LEGACY(v3_networkstatus),
@@ -5960,14 +6065,14 @@ 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, "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_ARG(find_dl_min_delay, TT_FORK, "bfd"),
+ DIR_ARG(find_dl_min_delay, TT_FORK, "bad"),
+ DIR_ARG(find_dl_min_delay, TT_FORK, "cfd"),
+ DIR_ARG(find_dl_min_delay, TT_FORK, "cad"),
+ DIR_ARG(find_dl_min_delay, TT_FORK, "bfr"),
+ DIR_ARG(find_dl_min_delay, TT_FORK, "bar"),
+ DIR_ARG(find_dl_min_delay, TT_FORK, "cfr"),
+ DIR_ARG(find_dl_min_delay, TT_FORK, "car"),
DIR(assumed_flags, 0),
DIR(networkstatus_compute_bw_weights_v10, 0),
DIR(platform_str, 0),
diff --git a/src/test/test_dir_common.c b/src/test/test_dir_common.c
index fdf43533a8..230410f7fa 100644
--- a/src/test/test_dir_common.c
+++ b/src/test/test_dir_common.c
@@ -5,14 +5,14 @@
#include "orconfig.h"
#define DIRVOTE_PRIVATE
-#include "crypto.h"
#include "test.h"
#include "container.h"
#include "or.h"
-#include "dirvote.h"
+#include "dirauth/dirvote.h"
#include "nodelist.h"
#include "routerlist.h"
#include "test_dir_common.h"
+#include "voting_schedule.h"
void dir_common_setup_vote(networkstatus_t **vote, time_t now);
networkstatus_t * dir_common_add_rs_and_parse(networkstatus_t *vote,
diff --git a/src/test/test_dir_handle_get.c b/src/test/test_dir_handle_get.c
index ca64dce5fe..688d26bdc1 100644
--- a/src/test/test_dir_handle_get.c
+++ b/src/test/test_dir_handle_get.c
@@ -16,7 +16,6 @@
#include "directory.h"
#include "test.h"
#include "compress.h"
-#include "connection.h"
#include "rendcommon.h"
#include "rendcache.h"
#include "router.h"
@@ -31,8 +30,9 @@
#include "proto_http.h"
#include "geoip.h"
#include "dirserv.h"
-#include "dirvote.h"
+#include "dirauth/dirvote.h"
#include "log_test_helpers.h"
+#include "voting_schedule.h"
#ifdef _WIN32
/* For mkdir() */
@@ -2057,7 +2057,7 @@ test_dir_handle_get_status_vote_d(void* data)
mock_options->TestingV3AuthInitialDistDelay = 1;
time_t now = 1441223455 -1;
- dirvote_recalculate_timing(mock_options, now);
+ voting_schedule_recalculate_timing(mock_options, now);
const char *msg_out = NULL;
int status_out = 0;
@@ -2403,7 +2403,7 @@ test_dir_handle_get_status_vote_next_authority(void* data)
mock_options->TestingV3AuthInitialDistDelay = 1;
time_t now = 1441223455 -1;
- dirvote_recalculate_timing(mock_options, now);
+ voting_schedule_recalculate_timing(mock_options, now);
struct pending_vote_t *vote = dirvote_add_vote(VOTE_BODY_V3, &msg_out,
&status_out);
@@ -2482,7 +2482,7 @@ test_dir_handle_get_status_vote_current_authority(void* data)
mock_options->TestingV3AuthInitialDistDelay = 1;
time_t now = 1441223455;
- dirvote_recalculate_timing(mock_options, now-1);
+ voting_schedule_recalculate_timing(mock_options, now-1);
struct pending_vote_t *vote = dirvote_add_vote(VOTE_BODY_V3, &msg_out,
&status_out);
diff --git a/src/test/test_dos.c b/src/test/test_dos.c
index cb9d9e559c..8ae967f3ae 100644
--- a/src/test/test_dos.c
+++ b/src/test/test_dos.c
@@ -8,6 +8,7 @@
#include "or.h"
#include "dos.h"
#include "circuitlist.h"
+#include "crypto_rand.h"
#include "geoip.h"
#include "channel.h"
#include "microdesc.h"
diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c
index 3b54ffa2e9..e0162e3058 100644
--- a/src/test/test_entrynodes.c
+++ b/src/test/test_entrynodes.c
@@ -4,6 +4,7 @@
#include "orconfig.h"
#define CIRCUITLIST_PRIVATE
+#define CIRCUITBUILD_PRIVATE
#define STATEFILE_PRIVATE
#define ENTRYNODES_PRIVATE
#define ROUTERLIST_PRIVATE
@@ -14,8 +15,10 @@
#include "bridges.h"
#include "circuitlist.h"
+#include "circuitbuild.h"
#include "config.h"
#include "confparse.h"
+#include "crypto_rand.h"
#include "directory.h"
#include "entrynodes.h"
#include "nodelist.h"
@@ -74,6 +77,17 @@ bfn_mock_node_get_by_id(const char *id)
return NULL;
}
+/* Helper function to free a test node. */
+static void
+test_node_free(node_t *n)
+{
+ tor_free(n->rs);
+ tor_free(n->md->onion_curve25519_pkey);
+ short_policy_free(n->md->exit_policy);
+ tor_free(n->md);
+ tor_free(n);
+}
+
/* Unittest cleanup function: Cleanup the fake network. */
static int
big_fake_network_cleanup(const struct testcase_t *testcase, void *ptr)
@@ -83,9 +97,7 @@ big_fake_network_cleanup(const struct testcase_t *testcase, void *ptr)
if (big_fake_net_nodes) {
SMARTLIST_FOREACH(big_fake_net_nodes, node_t *, n, {
- tor_free(n->rs);
- tor_free(n->md);
- tor_free(n);
+ test_node_free(n);
});
smartlist_free(big_fake_net_nodes);
}
@@ -113,9 +125,18 @@ big_fake_network_setup(const struct testcase_t *testcase)
big_fake_net_nodes = smartlist_new();
for (i = 0; i < N_NODES; ++i) {
+ curve25519_secret_key_t curve25519_secret_key;
+
node_t *n = tor_malloc_zero(sizeof(node_t));
n->md = tor_malloc_zero(sizeof(microdesc_t));
+ /* Generate curve25519 key for this node */
+ n->md->onion_curve25519_pkey =
+ tor_malloc_zero(sizeof(curve25519_public_key_t));
+ curve25519_secret_key_generate(&curve25519_secret_key, 0);
+ curve25519_public_key_generate(n->md->onion_curve25519_pkey,
+ &curve25519_secret_key);
+
crypto_rand(n->identity, sizeof(n->identity));
n->rs = tor_malloc_zero(sizeof(routerstatus_t));
@@ -135,8 +156,8 @@ big_fake_network_setup(const struct testcase_t *testcase)
{
char nickname_binary[8];
crypto_rand(nickname_binary, sizeof(nickname_binary));
- base64_encode(n->rs->nickname, sizeof(n->rs->nickname),
- nickname_binary, sizeof(nickname_binary), 0);
+ base32_encode(n->rs->nickname, sizeof(n->rs->nickname),
+ nickname_binary, sizeof(nickname_binary));
}
/* Call half of the nodes a possible guard. */
@@ -144,6 +165,12 @@ big_fake_network_setup(const struct testcase_t *testcase)
n->is_possible_guard = 1;
n->rs->guardfraction_percentage = 100;
n->rs->has_guardfraction = 1;
+ n->rs->is_possible_guard = 1;
+ }
+
+ /* Make some of these nodes a possible exit */
+ if (i % 7 == 0) {
+ n->md->exit_policy = parse_short_policy("accept 443");
}
smartlist_add(big_fake_net_nodes, n);
@@ -1075,9 +1102,7 @@ test_entry_guard_expand_sample_small_net(void *arg)
/* Fun corner case: not enough guards to make up our whole sample size. */
SMARTLIST_FOREACH(big_fake_net_nodes, node_t *, n, {
if (n_sl_idx >= 15) {
- tor_free(n->rs);
- tor_free(n->md);
- tor_free(n);
+ test_node_free(n);
SMARTLIST_DEL_CURRENT(big_fake_net_nodes, n);
} else {
n->rs->addr = 0; // make the filter reject this.
@@ -1174,9 +1199,7 @@ test_entry_guard_update_from_consensus_status(void *arg)
node_t *n = (node_t*) bfn_mock_node_get_by_id(g->identity);
tt_assert(n);
smartlist_remove(big_fake_net_nodes, n);
- tor_free(n->rs);
- tor_free(n->md);
- tor_free(n);
+ test_node_free(n);
}
update_approx_time(start + 300);
sampled_guards_update_from_consensus(gs);
@@ -2685,6 +2708,23 @@ test_enty_guard_should_expire_waiting(void *arg)
tor_free(fake_state);
}
+/** Test that the number of primary guards can be controlled using torrc */
+static void
+test_entry_guard_number_of_primaries(void *arg)
+{
+ (void) arg;
+
+ /* Get default value */
+ tt_int_op(get_n_primary_guards(), OP_EQ, DFLT_N_PRIMARY_GUARDS);
+
+ /* Set number of primaries using torrc */
+ get_options_mutable()->NumPrimaryGuards = 42;
+ tt_int_op(get_n_primary_guards(), OP_EQ, 42);
+
+ done:
+ ;
+}
+
static void
mock_directory_initiate_request(directory_request_t *req)
{
@@ -2796,6 +2836,161 @@ test_entry_guard_outdated_dirserver_exclusion(void *arg)
}
}
+/** Test helper to extend the <b>oc</b> circuit path <b>n</b> times and then
+ * ensure that the circuit is now complete. */
+static void
+helper_extend_circuit_path_n_times(origin_circuit_t *oc, int n)
+{
+ int retval;
+ int i;
+
+ /* Extend path n times */
+ for (i = 0 ; i < n ; i++) {
+ retval = onion_extend_cpath(oc);
+ tt_int_op(retval, OP_EQ, 0);
+ tt_int_op(circuit_get_cpath_len(oc), OP_EQ, i+1);
+ }
+
+ /* Now do it one last time and see that circ is complete */
+ retval = onion_extend_cpath(oc);
+ tt_int_op(retval, OP_EQ, 1);
+
+ done:
+ ;
+}
+
+/** Test for basic Tor path selection. Makes sure we build 3-hop circuits. */
+static void
+test_entry_guard_basic_path_selection(void *arg)
+{
+ (void) arg;
+
+ int retval;
+
+ /* Enable entry guards */
+ or_options_t *options = get_options_mutable();
+ options->UseEntryGuards = 1;
+
+ /* disables /16 check since all nodes have the same addr... */
+ options->EnforceDistinctSubnets = 0;
+
+ /* Create our circuit */
+ circuit_t *circ = dummy_origin_circuit_new(30);
+ origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(circ);
+ oc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
+
+ /* First pick the exit and pin it on the build_state */
+ retval = onion_pick_cpath_exit(oc, NULL, 0);
+ tt_int_op(retval, OP_EQ, 0);
+
+ /* Extend path 3 times. First we pick guard, then middle, then exit. */
+ helper_extend_circuit_path_n_times(oc, 3);
+
+ done:
+ circuit_free_(circ);
+}
+
+/** Test helper to build an L2 and L3 vanguard list. The vanguard lists
+ * produced should be completely disjoint. */
+static void
+helper_setup_vanguard_list(or_options_t *options)
+{
+ int i = 0;
+
+ /* Add some nodes to the vanguard L2 list */
+ options->HSLayer2Nodes = routerset_new();
+ for (i = 0; i < 10 ; i += 2) {
+ node_t *vanguard_node = smartlist_get(big_fake_net_nodes, i);
+ tt_assert(vanguard_node->is_possible_guard);
+ routerset_parse(options->HSLayer2Nodes, vanguard_node->rs->nickname, "l2");
+ }
+ /* also add some nodes to vanguard L3 list
+ * (L2 list and L3 list should be disjoint for this test to work) */
+ options->HSLayer3Nodes = routerset_new();
+ for (i = 10; i < 20 ; i += 2) {
+ node_t *vanguard_node = smartlist_get(big_fake_net_nodes, i);
+ tt_assert(vanguard_node->is_possible_guard);
+ routerset_parse(options->HSLayer3Nodes, vanguard_node->rs->nickname, "l3");
+ }
+
+ done:
+ ;
+}
+
+/** Test to ensure that vanguard path selection works properly. Ensures that
+ * default vanguard circuits are 4 hops, and that path selection works
+ * correctly given the vanguard settings. */
+static void
+test_entry_guard_vanguard_path_selection(void *arg)
+{
+ (void) arg;
+
+ int retval;
+
+ /* Enable entry guards */
+ or_options_t *options = get_options_mutable();
+ options->UseEntryGuards = 1;
+
+ /* XXX disables /16 check */
+ options->EnforceDistinctSubnets = 0;
+
+ /* Setup our vanguard list */
+ helper_setup_vanguard_list(options);
+
+ /* Create our circuit */
+ circuit_t *circ = dummy_origin_circuit_new(30);
+ origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(circ);
+ oc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
+ oc->build_state->is_internal = 1;
+
+ /* Switch circuit purpose to vanguards */
+ circ->purpose = CIRCUIT_PURPOSE_HS_VANGUARDS;
+
+ /* First pick the exit and pin it on the build_state */
+ tt_int_op(oc->build_state->desired_path_len, OP_EQ, 0);
+ retval = onion_pick_cpath_exit(oc, NULL, 0);
+ tt_int_op(retval, OP_EQ, 0);
+
+ /* Ensure that vanguards make 4-hop circuits by default */
+ tt_int_op(oc->build_state->desired_path_len, OP_EQ, 4);
+
+ /* Extend path as many times as needed to have complete circ. */
+ helper_extend_circuit_path_n_times(oc, oc->build_state->desired_path_len);
+
+ /* Test that the cpath linked list is set correctly. */
+ crypt_path_t *l1_node = oc->cpath;
+ crypt_path_t *l2_node = l1_node->next;
+ crypt_path_t *l3_node = l2_node->next;
+ crypt_path_t *l4_node = l3_node->next;
+ crypt_path_t *l1_node_again = l4_node->next;
+ tt_ptr_op(l1_node, OP_EQ, l1_node_again);
+
+ /* Test that L2 is indeed HSLayer2Node */
+ retval = routerset_contains_extendinfo(options->HSLayer2Nodes,
+ l2_node->extend_info);
+ tt_int_op(retval, OP_EQ, 4);
+ /* test that L3 node is _not_ contained in HSLayer2Node */
+ retval = routerset_contains_extendinfo(options->HSLayer2Nodes,
+ l3_node->extend_info);
+ tt_int_op(retval, OP_LT, 4);
+
+ /* Test that L3 is indeed HSLayer3Node */
+ retval = routerset_contains_extendinfo(options->HSLayer3Nodes,
+ l3_node->extend_info);
+ tt_int_op(retval, OP_EQ, 4);
+ /* test that L2 node is _not_ contained in HSLayer3Node */
+ retval = routerset_contains_extendinfo(options->HSLayer3Nodes,
+ l2_node->extend_info);
+ tt_int_op(retval, OP_LT, 4);
+
+ /* TODO: Test that L1 can be the same as exit. To test this we need start
+ enforcing EnforceDistinctSubnets again, which means that we need to give
+ each test node a different address which currently breaks some tests. */
+
+ done:
+ circuit_free_(circ);
+}
+
static const struct testcase_setup_t big_fake_network = {
big_fake_network_setup, big_fake_network_cleanup
};
@@ -2835,6 +3030,8 @@ struct testcase_t entrynodes_tests[] = {
test_entry_guard_parse_from_state_broken, TT_FORK, NULL, NULL },
{ "get_guard_selection_by_name",
test_entry_guard_get_guard_selection_by_name, TT_FORK, NULL, NULL },
+ { "number_of_primaries",
+ test_entry_guard_number_of_primaries, TT_FORK, NULL, NULL },
BFN_TEST(choose_selection_initial),
BFN_TEST(add_single_guard),
BFN_TEST(node_filter),
@@ -2857,6 +3054,8 @@ struct testcase_t entrynodes_tests[] = {
BFN_TEST(select_and_cancel),
BFN_TEST(drop_guards),
BFN_TEST(outdated_dirserver_exclusion),
+ BFN_TEST(basic_path_selection),
+ BFN_TEST(vanguard_path_selection),
UPGRADE_TEST(upgrade_a_circuit, "c1-done c2-done"),
UPGRADE_TEST(upgrade_blocked_by_live_primary_guards, "c1-done c2-done"),
diff --git a/src/test/test_extorport.c b/src/test/test_extorport.c
index cadef257f1..e05342cb8a 100644
--- a/src/test/test_extorport.c
+++ b/src/test/test_extorport.c
@@ -10,6 +10,7 @@
#include "connection_or.h"
#include "config.h"
#include "control.h"
+#include "crypto_rand.h"
#include "ext_orport.h"
#include "main.h"
#include "test.h"
diff --git a/src/test/test_geoip.c b/src/test/test_geoip.c
new file mode 100644
index 0000000000..6f849f436b
--- /dev/null
+++ b/src/test/test_geoip.c
@@ -0,0 +1,578 @@
+/* Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+
+/* These macros pull in declarations for some functions and structures that
+ * are typically file-private. */
+#define GEOIP_PRIVATE
+#include "or.h"
+#include "config.h"
+#include "geoip.h"
+#include "test.h"
+
+ /* Record odd numbered fake-IPs using ipv6, even numbered fake-IPs
+ * using ipv4. Since our fake geoip database is the same between
+ * ipv4 and ipv6, we should get the same result no matter which
+ * address family we pick for each IP. */
+#define SET_TEST_ADDRESS(i) do { \
+ if ((i) & 1) { \
+ SET_TEST_IPV6(i); \
+ tor_addr_from_in6(&addr, &in6); \
+ } else { \
+ tor_addr_from_ipv4h(&addr, (uint32_t) i); \
+ } \
+ } while (0)
+
+ /* Make sure that country ID actually works. */
+#define SET_TEST_IPV6(i) \
+ do { \
+ set_uint32(in6.s6_addr + 12, htonl((uint32_t) (i))); \
+ } while (0)
+#define CHECK_COUNTRY(country, val) do { \
+ /* test ipv4 country lookup */ \
+ tt_str_op(country, OP_EQ, \
+ geoip_get_country_name(geoip_get_country_by_ipv4(val))); \
+ /* test ipv6 country lookup */ \
+ SET_TEST_IPV6(val); \
+ tt_str_op(country, OP_EQ, \
+ geoip_get_country_name(geoip_get_country_by_ipv6(&in6))); \
+ } while (0)
+
+/** Run unit tests for GeoIP code. */
+static void
+test_geoip(void *arg)
+{
+ int i, j;
+ time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
+ char *s = NULL, *v = NULL;
+ const char *bridge_stats_1 =
+ "bridge-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "bridge-ips zz=24,xy=8\n"
+ "bridge-ip-versions v4=16,v6=16\n"
+ "bridge-ip-transports <OR>=24\n",
+ *dirreq_stats_1 =
+ "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "dirreq-v3-ips ab=8\n"
+ "dirreq-v3-reqs ab=8\n"
+ "dirreq-v3-resp ok=0,not-enough-sigs=0,unavailable=0,not-found=0,"
+ "not-modified=0,busy=0\n"
+ "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n"
+ "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n",
+ *dirreq_stats_2 =
+ "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "dirreq-v3-ips \n"
+ "dirreq-v3-reqs \n"
+ "dirreq-v3-resp ok=0,not-enough-sigs=0,unavailable=0,not-found=0,"
+ "not-modified=0,busy=0\n"
+ "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n"
+ "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n",
+ *dirreq_stats_3 =
+ "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "dirreq-v3-ips \n"
+ "dirreq-v3-reqs \n"
+ "dirreq-v3-resp ok=8,not-enough-sigs=0,unavailable=0,not-found=0,"
+ "not-modified=0,busy=0\n"
+ "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n"
+ "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n",
+ *dirreq_stats_4 =
+ "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "dirreq-v3-ips \n"
+ "dirreq-v3-reqs \n"
+ "dirreq-v3-resp ok=8,not-enough-sigs=0,unavailable=0,not-found=0,"
+ "not-modified=0,busy=0\n"
+ "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n"
+ "dirreq-v3-tunneled-dl complete=0,timeout=0,running=4\n",
+ *entry_stats_1 =
+ "entry-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "entry-ips ab=8\n",
+ *entry_stats_2 =
+ "entry-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "entry-ips \n";
+ tor_addr_t addr;
+ struct in6_addr in6;
+
+ /* Populate the DB a bit. Add these in order, since we can't do the final
+ * 'sort' step. These aren't very good IP addresses, but they're perfectly
+ * fine uint32_t values. */
+ (void)arg;
+ tt_int_op(0,OP_EQ, geoip_parse_entry("10,50,AB", AF_INET));
+ tt_int_op(0,OP_EQ, geoip_parse_entry("52,90,XY", AF_INET));
+ tt_int_op(0,OP_EQ, geoip_parse_entry("95,100,AB", AF_INET));
+ tt_int_op(0,OP_EQ, geoip_parse_entry("\"105\",\"140\",\"ZZ\"", AF_INET));
+ tt_int_op(0,OP_EQ, geoip_parse_entry("\"150\",\"190\",\"XY\"", AF_INET));
+ tt_int_op(0,OP_EQ, geoip_parse_entry("\"200\",\"250\",\"AB\"", AF_INET));
+
+ /* Populate the IPv6 DB equivalently with fake IPs in the same range */
+ tt_int_op(0,OP_EQ, geoip_parse_entry("::a,::32,AB", AF_INET6));
+ tt_int_op(0,OP_EQ, geoip_parse_entry("::34,::5a,XY", AF_INET6));
+ tt_int_op(0,OP_EQ, geoip_parse_entry("::5f,::64,AB", AF_INET6));
+ tt_int_op(0,OP_EQ, geoip_parse_entry("::69,::8c,ZZ", AF_INET6));
+ tt_int_op(0,OP_EQ, geoip_parse_entry("::96,::be,XY", AF_INET6));
+ tt_int_op(0,OP_EQ, geoip_parse_entry("::c8,::fa,AB", AF_INET6));
+
+ /* We should have 4 countries: ??, ab, xy, zz. */
+ tt_int_op(4,OP_EQ, geoip_get_n_countries());
+ memset(&in6, 0, sizeof(in6));
+
+ CHECK_COUNTRY("??", 3);
+ CHECK_COUNTRY("ab", 32);
+ CHECK_COUNTRY("??", 5);
+ CHECK_COUNTRY("??", 51);
+ CHECK_COUNTRY("xy", 150);
+ CHECK_COUNTRY("xy", 190);
+ CHECK_COUNTRY("??", 2000);
+
+ tt_int_op(0,OP_EQ, geoip_get_country_by_ipv4(3));
+ SET_TEST_IPV6(3);
+ tt_int_op(0,OP_EQ, geoip_get_country_by_ipv6(&in6));
+
+ get_options_mutable()->BridgeRelay = 1;
+ get_options_mutable()->BridgeRecordUsageByCountry = 1;
+ /* Put 9 observations in AB... */
+ for (i=32; i < 40; ++i) {
+ SET_TEST_ADDRESS(i);
+ geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now-7200);
+ }
+ SET_TEST_ADDRESS(225);
+ geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now-7200);
+ /* and 3 observations in XY, several times. */
+ for (j=0; j < 10; ++j)
+ for (i=52; i < 55; ++i) {
+ SET_TEST_ADDRESS(i);
+ geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now-3600);
+ }
+ /* and 17 observations in ZZ... */
+ for (i=110; i < 127; ++i) {
+ SET_TEST_ADDRESS(i);
+ geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now);
+ }
+ geoip_get_client_history(GEOIP_CLIENT_CONNECT, &s, &v);
+ tt_assert(s);
+ tt_assert(v);
+ tt_str_op("zz=24,ab=16,xy=8",OP_EQ, s);
+ tt_str_op("v4=16,v6=16",OP_EQ, v);
+ tor_free(s);
+ tor_free(v);
+
+ /* Now clear out all the AB observations. */
+ geoip_remove_old_clients(now-6000);
+ geoip_get_client_history(GEOIP_CLIENT_CONNECT, &s, &v);
+ tt_assert(s);
+ tt_assert(v);
+ tt_str_op("zz=24,xy=8",OP_EQ, s);
+ tt_str_op("v4=16,v6=16",OP_EQ, v);
+ tor_free(s);
+ tor_free(v);
+
+ /* 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_ptr_op(s, OP_EQ, NULL);
+
+ /* Initialize stats and generate the bridge-stats history string out of
+ * the connecting clients added above. */
+ geoip_bridge_stats_init(now);
+ s = geoip_format_bridge_stats(now + 86400);
+ tt_assert(s);
+ tt_str_op(bridge_stats_1,OP_EQ, s);
+ tor_free(s);
+
+ /* Stop collecting bridge stats and make sure we don't write a history
+ * string anymore. */
+ geoip_bridge_stats_term();
+ s = geoip_format_bridge_stats(now + 86400);
+ tt_ptr_op(s, OP_EQ, NULL);
+
+ /* Stop being a bridge and start being a directory mirror that gathers
+ * directory request statistics. */
+ geoip_bridge_stats_term();
+ get_options_mutable()->BridgeRelay = 0;
+ get_options_mutable()->BridgeRecordUsageByCountry = 0;
+ get_options_mutable()->DirReqStatistics = 1;
+
+ /* Start testing dirreq statistics by making sure that we don't collect
+ * dirreq stats without initializing them. */
+ SET_TEST_ADDRESS(100);
+ geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now);
+ s = geoip_format_dirreq_stats(now + 86400);
+ tt_ptr_op(s, OP_EQ, NULL);
+
+ /* Initialize stats, note one connecting client, and generate the
+ * dirreq-stats history string. */
+ geoip_dirreq_stats_init(now);
+ SET_TEST_ADDRESS(100);
+ geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now);
+ s = geoip_format_dirreq_stats(now + 86400);
+ tt_str_op(dirreq_stats_1,OP_EQ, s);
+ tor_free(s);
+
+ /* Stop collecting stats, add another connecting client, and ensure we
+ * don't generate a history string. */
+ geoip_dirreq_stats_term();
+ SET_TEST_ADDRESS(101);
+ geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now);
+ s = geoip_format_dirreq_stats(now + 86400);
+ 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. */
+ geoip_dirreq_stats_init(now);
+ SET_TEST_ADDRESS(100);
+ geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now);
+ geoip_reset_dirreq_stats(now);
+ s = geoip_format_dirreq_stats(now + 86400);
+ tt_str_op(dirreq_stats_2,OP_EQ, s);
+ tor_free(s);
+
+ /* Note a successful network status response and make sure that it
+ * appears in the history string. */
+ geoip_note_ns_response(GEOIP_SUCCESS);
+ s = geoip_format_dirreq_stats(now + 86400);
+ tt_str_op(dirreq_stats_3,OP_EQ, s);
+ tor_free(s);
+
+ /* Start a tunneled directory request. */
+ geoip_start_dirreq((uint64_t) 1, 1024, DIRREQ_TUNNELED);
+ s = geoip_format_dirreq_stats(now + 86400);
+ tt_str_op(dirreq_stats_4,OP_EQ, s);
+ tor_free(s);
+
+ /* Stop collecting directory request statistics and start gathering
+ * entry stats. */
+ geoip_dirreq_stats_term();
+ get_options_mutable()->DirReqStatistics = 0;
+ get_options_mutable()->EntryStatistics = 1;
+
+ /* Start testing entry statistics by making sure that we don't collect
+ * anything without initializing entry stats. */
+ SET_TEST_ADDRESS(100);
+ geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now);
+ s = geoip_format_entry_stats(now + 86400);
+ tt_ptr_op(s, OP_EQ, NULL);
+
+ /* Initialize stats, note one connecting client, and generate the
+ * entry-stats history string. */
+ geoip_entry_stats_init(now);
+ SET_TEST_ADDRESS(100);
+ geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now);
+ s = geoip_format_entry_stats(now + 86400);
+ tt_str_op(entry_stats_1,OP_EQ, s);
+ tor_free(s);
+
+ /* Stop collecting stats, add another connecting client, and ensure we
+ * don't generate a history string. */
+ geoip_entry_stats_term();
+ SET_TEST_ADDRESS(101);
+ geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now);
+ s = geoip_format_entry_stats(now + 86400);
+ 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. */
+ geoip_entry_stats_init(now);
+ SET_TEST_ADDRESS(100);
+ geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now);
+ geoip_reset_entry_stats(now);
+ s = geoip_format_entry_stats(now + 86400);
+ tt_str_op(entry_stats_2,OP_EQ, s);
+ tor_free(s);
+
+ /* Test the OOM handler. Add a client, run the OOM. */
+ geoip_entry_stats_init(now);
+ SET_TEST_ADDRESS(100);
+ geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL,
+ now - (12 * 60 * 60));
+ /* We've seen this 12 hours ago. Run the OOM, it should clean the entry
+ * because it is above the minimum cutoff of 4 hours. */
+ size_t bytes_removed = geoip_client_cache_handle_oom(now, 1000);
+ tt_size_op(bytes_removed, OP_GT, 0);
+
+ /* Do it again but this time with an entry with a lower cutoff. */
+ geoip_entry_stats_init(now);
+ SET_TEST_ADDRESS(100);
+ geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL,
+ now - (3 * 60 * 60));
+ bytes_removed = geoip_client_cache_handle_oom(now, 1000);
+ tt_size_op(bytes_removed, OP_EQ, 0);
+
+ /* Stop collecting entry statistics. */
+ geoip_entry_stats_term();
+ get_options_mutable()->EntryStatistics = 0;
+
+ done:
+ tor_free(s);
+ tor_free(v);
+}
+
+static void
+test_geoip_with_pt(void *arg)
+{
+ time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
+ char *s = NULL;
+ int i;
+ tor_addr_t addr;
+ struct in6_addr in6;
+
+ (void)arg;
+ get_options_mutable()->BridgeRelay = 1;
+ get_options_mutable()->BridgeRecordUsageByCountry = 1;
+
+ memset(&in6, 0, sizeof(in6));
+
+ /* No clients seen yet. */
+ s = geoip_get_transport_history();
+ tor_assert(!s);
+
+ /* 4 connections without a pluggable transport */
+ for (i=0; i < 4; ++i) {
+ SET_TEST_ADDRESS(i);
+ geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now-7200);
+ }
+
+ /* 9 connections with "alpha" */
+ for (i=4; i < 13; ++i) {
+ SET_TEST_ADDRESS(i);
+ geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "alpha", now-7200);
+ }
+
+ /* one connection with "beta" */
+ SET_TEST_ADDRESS(13);
+ geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "beta", now-7200);
+
+ /* 14 connections with "charlie" */
+ for (i=14; i < 28; ++i) {
+ SET_TEST_ADDRESS(i);
+ geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "charlie", now-7200);
+ }
+
+ /* 131 connections with "ddr" */
+ for (i=28; i < 159; ++i) {
+ SET_TEST_ADDRESS(i);
+ geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "ddr", now-7200);
+ }
+
+ /* 8 connections with "entropy" */
+ for (i=159; i < 167; ++i) {
+ SET_TEST_ADDRESS(i);
+ geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "entropy", now-7200);
+ }
+
+ /* 2 connections from the same IP with two different transports. */
+ SET_TEST_ADDRESS(++i);
+ geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "fire", now-7200);
+ geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "google", now-7200);
+
+ /* Test the transport history string. */
+ s = geoip_get_transport_history();
+ tor_assert(s);
+ tt_str_op(s,OP_EQ, "<OR>=8,alpha=16,beta=8,charlie=16,ddr=136,"
+ "entropy=8,fire=8,google=8");
+
+ /* Stop collecting entry statistics. */
+ geoip_entry_stats_term();
+ get_options_mutable()->EntryStatistics = 0;
+
+ done:
+ tor_free(s);
+}
+
+#undef SET_TEST_ADDRESS
+#undef SET_TEST_IPV6
+#undef CHECK_COUNTRY
+
+static const char GEOIP_CONTENT[] =
+ "134445936,134445939,MP\n"
+ "134445940,134447103,GU\n"
+ "134447104,134738943,US\n"
+ "134738944,134739199,CA\n"
+ "134739200,135192575,US\n"
+ "135192576,135200767,MX\n"
+ "135200768,135430143,US\n"
+ "135430144,135430399,CA\n"
+ "135430400,135432191,US\n";
+
+static void
+test_geoip_load_file(void *arg)
+{
+ (void)arg;
+ char *contents = NULL;
+ char *dhex = NULL;
+
+ /* A nonexistant filename should fail. */
+ tt_int_op(-1, OP_EQ,
+ geoip_load_file(AF_INET, "/you/did/not/put/a/file/here/I/hope"));
+
+ /* We start out with only "Ningunpartia" in the database. */
+ tt_int_op(1, OP_EQ, geoip_get_n_countries());
+ tt_str_op("??", OP_EQ, geoip_get_country_name(0));
+ /* Any lookup attempt should say "-1" because we have no info */
+ tt_int_op(-1, OP_EQ, geoip_get_country_by_ipv4(0x01020304));
+ /* There should be no 'digest' for a nonexistant file */
+ tt_str_op("0000000000000000000000000000000000000000", OP_EQ,
+ geoip_db_digest(AF_INET));
+
+ const char *fname = get_fname("geoip");
+ tt_int_op(0, OP_EQ, write_str_to_file(fname, GEOIP_CONTENT, 1));
+
+ int rv = geoip_load_file(AF_INET, fname);
+ if (rv != 0) {
+ TT_GRIPE(("Unable to load geoip from %s", escaped(fname)));
+ }
+ tt_int_op(0, OP_EQ, rv);
+
+ /* Check that we loaded some countries; this will fail if there are ever
+ * fewer than 5 countries in our test above. */
+ tt_int_op(geoip_get_n_countries(), OP_GE, 5);
+
+ /* Let's see where 8.8.8.8 is. */
+ int country = geoip_get_country_by_ipv4(0x08080808);
+ tt_int_op(country, OP_GE, 1); /* It shouldn't be 'unknown' or 'nowhere' */
+ const char *cc = geoip_get_country_name(country);
+ tt_int_op(strlen(cc), OP_EQ, 2);
+
+ /* The digest should be set.... */
+ tt_str_op("0000000000000000000000000000000000000000", OP_NE,
+ geoip_db_digest(AF_INET));
+
+ /* And it should be set correctly */
+ contents = read_file_to_str(fname, RFTS_BIN, NULL);
+ uint8_t d[DIGEST_LEN];
+ crypto_digest((char*)d, contents, strlen(contents));
+ dhex = tor_strdup(hex_str((char*)d, DIGEST_LEN));
+ tt_str_op(dhex, OP_EQ, geoip_db_digest(AF_INET));
+
+ /* Make sure geoip_free_all() works. */
+ geoip_free_all();
+ tt_int_op(1, OP_EQ, geoip_get_n_countries());
+ tt_str_op("??", OP_EQ, geoip_get_country_name(0));
+ tt_int_op(-1, OP_EQ, geoip_get_country_by_ipv4(0x01020304));
+ tt_str_op("0000000000000000000000000000000000000000", OP_EQ,
+ geoip_db_digest(AF_INET)); // <--- nick bets this will fail.
+
+ done:
+ tor_free(contents);
+ tor_free(dhex);
+}
+
+static void
+test_geoip6_load_file(void *arg)
+{
+ (void)arg;
+ struct in6_addr iaddr6;
+ char *contents = NULL;
+ char *dhex = NULL;
+
+ /* A nonexistant filename should fail. */
+ tt_int_op(-1, OP_EQ,
+ geoip_load_file(AF_INET6, "/you/did/not/put/a/file/here/I/hope"));
+
+ /* Any lookup attempt should say "-1" because we have no info */
+ tor_inet_pton(AF_INET6, "2001:4860:4860::8888", &iaddr6);
+ tt_int_op(-1, OP_EQ, geoip_get_country_by_ipv6(&iaddr6));
+
+ /* Load geiop6 file */
+ const char *fname6 = get_fname("geoip6");
+ const char CONTENT[] =
+ "2001:4830:6010::,2001:4830:601f:ffff:ffff:ffff:ffff:ffff,GB\n"
+ "2001:4830:6020::,2001:4830:ffff:ffff:ffff:ffff:ffff:ffff,US\n"
+ "2001:4838::,2001:4838:ffff:ffff:ffff:ffff:ffff:ffff,US\n"
+ "2001:4840::,2001:4840:ffff:ffff:ffff:ffff:ffff:ffff,XY\n"
+ "2001:4848::,2001:4848:ffff:ffff:ffff:ffff:ffff:ffff,ZD\n"
+ "2001:4850::,2001:4850:ffff:ffff:ffff:ffff:ffff:ffff,RO\n"
+ "2001:4858::,2001:4858:ffff:ffff:ffff:ffff:ffff:ffff,TC\n"
+ "2001:4860::,2001:4860:ffff:ffff:ffff:ffff:ffff:ffff,US\n"
+ "2001:4868::,2001:4868:ffff:ffff:ffff:ffff:ffff:ffff,US\n"
+ "2001:4870::,2001:4871:ffff:ffff:ffff:ffff:ffff:ffff,NB\n"
+ "2001:4878::,2001:4878:128:ffff:ffff:ffff:ffff:ffff,US\n"
+ "2001:4878:129::,2001:4878:129:ffff:ffff:ffff:ffff:ffff,CR\n"
+ "2001:4878:12a::,2001:4878:203:ffff:ffff:ffff:ffff:ffff,US\n"
+ "2001:4878:204::,2001:4878:204:ffff:ffff:ffff:ffff:ffff,DE\n"
+ "2001:4878:205::,2001:4878:214:ffff:ffff:ffff:ffff:ffff,US\n";
+ tt_int_op(0, OP_EQ, write_str_to_file(fname6, CONTENT, 1));
+
+ tt_int_op(0, OP_EQ, geoip_load_file(AF_INET6, fname6));
+
+ /* Check that we loaded some countries; this will fail if there are ever
+ * fewer than 5 countries in our test data above. */
+ tt_int_op(geoip_get_n_countries(), OP_GE, 5);
+
+ /* Let's see where 2001:4860:4860::8888 (google dns) is. */
+ const char *caddr6 = "2001:4860:4860::8888";
+ tor_inet_pton(AF_INET6, caddr6, &iaddr6);
+ int country6 = geoip_get_country_by_ipv6(&iaddr6);
+ tt_int_op(country6, OP_GE, 1);
+
+ const char *cc6 = geoip_get_country_name(country6);
+ tt_int_op(strlen(cc6), OP_EQ, 2);
+
+ /* The digest should be set.... */
+ tt_str_op("0000000000000000000000000000000000000000", OP_NE,
+ geoip_db_digest(AF_INET6));
+
+ /* And it should be set correctly */
+ contents = read_file_to_str(fname6, RFTS_BIN, NULL);
+ uint8_t d[DIGEST_LEN];
+ crypto_digest((char*)d, contents, strlen(contents));
+ dhex = tor_strdup(hex_str((char*)d, DIGEST_LEN));
+ tt_str_op(dhex, OP_EQ, geoip_db_digest(AF_INET6));
+
+ /* Make sure geoip_free_all() works. */
+ geoip_free_all();
+ tt_int_op(1, OP_EQ, geoip_get_n_countries());
+ tt_str_op("??", OP_EQ, geoip_get_country_name(0));
+ tor_inet_pton(AF_INET6, "::1:2:3:4", &iaddr6);
+ tt_int_op(-1, OP_EQ, geoip_get_country_by_ipv6(&iaddr6));
+ tt_str_op("0000000000000000000000000000000000000000", OP_EQ,
+ geoip_db_digest(AF_INET6));
+
+ done:
+ tor_free(contents);
+ tor_free(dhex);
+}
+
+static void
+test_geoip_load_2nd_file(void *arg)
+{
+ (void)arg;
+
+ char *fname_geoip = tor_strdup(get_fname("geoip_data"));
+ char *fname_empty = tor_strdup(get_fname("geoip_empty"));
+
+ tt_int_op(0, OP_EQ, write_str_to_file(fname_geoip, GEOIP_CONTENT, 1));
+ tt_int_op(0, OP_EQ, write_str_to_file(fname_empty, "\n", 1));
+
+ /* Load 1st geoip file */
+ tt_int_op(0, OP_EQ, geoip_load_file(AF_INET, fname_geoip));
+
+ /* Load 2nd geoip (empty) file */
+ /* It has to be the same IP address family */
+ tt_int_op(0, OP_EQ, geoip_load_file(AF_INET, fname_empty));
+
+ /* Check that there is no geoip information for 8.8.8.8, */
+ /* since loading the empty 2nd file should have delete it. */
+ int country = geoip_get_country_by_ipv4(0x08080808);
+ tt_int_op(country, OP_EQ, 0);
+
+ done:
+ tor_free(fname_geoip);
+ tor_free(fname_empty);
+}
+
+#define ENT(name) \
+ { #name, test_ ## name , 0, NULL, NULL }
+#define FORK(name) \
+ { #name, test_ ## name , TT_FORK, NULL, NULL }
+
+struct testcase_t geoip_tests[] = {
+ { "geoip", test_geoip, TT_FORK, NULL, NULL },
+ { "geoip_with_pt", test_geoip_with_pt, TT_FORK, NULL, NULL },
+ { "load_file", test_geoip_load_file, TT_FORK, NULL, NULL },
+ { "load_file6", test_geoip6_load_file, TT_FORK, NULL, NULL },
+ { "load_2nd_file", test_geoip_load_2nd_file, TT_FORK, NULL, NULL },
+
+ END_OF_TESTCASES
+};
+
diff --git a/src/test/test_helpers.c b/src/test/test_helpers.c
index 0da9cf64d0..1db5e9064f 100644
--- a/src/test/test_helpers.c
+++ b/src/test/test_helpers.c
@@ -18,6 +18,7 @@
#include "config.h"
#include "confparse.h"
#include "connection.h"
+#include "crypto_rand.h"
#include "main.h"
#include "nodelist.h"
#include "relay.h"
@@ -33,7 +34,6 @@ DISABLE_GCC_WARNING(overlength-strings)
* at large. */
#endif
#include "test_descriptors.inc"
-#include "or.h"
#include "circuitlist.h"
#ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
ENABLE_GCC_WARNING(overlength-strings)
@@ -156,7 +156,7 @@ mock_tor_addr_lookup__fail_on_bad_addrs(const char *name,
/* Helper for test_conn_get_connection() */
static int
-fake_close_socket(evutil_socket_t sock)
+fake_close_socket(tor_socket_t sock)
{
(void)sock;
return 0;
diff --git a/src/test/test_hs_cell.c b/src/test/test_hs_cell.c
index aed28d3bd2..8e15184c2a 100644
--- a/src/test/test_hs_cell.c
+++ b/src/test/test_hs_cell.c
@@ -14,6 +14,7 @@
#include "log_test_helpers.h"
#include "crypto_ed25519.h"
+#include "crypto_rand.h"
#include "hs_cell.h"
#include "hs_intropoint.h"
#include "hs_service.h"
diff --git a/src/test/test_hs_client.c b/src/test/test_hs_client.c
index 7ee7210bc9..50dca588ed 100644
--- a/src/test/test_hs_client.c
+++ b/src/test/test_hs_client.c
@@ -213,12 +213,12 @@ test_e2e_rend_circuit_setup_legacy(void *arg)
tt_int_op(retval, OP_EQ, 1);
/* Check the digest algo */
- tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->f_digest),
+ tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->crypto.f_digest),
OP_EQ, DIGEST_SHA1);
- tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->b_digest),
+ tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->crypto.b_digest),
OP_EQ, DIGEST_SHA1);
- tt_assert(or_circ->cpath->f_crypto);
- tt_assert(or_circ->cpath->b_crypto);
+ tt_assert(or_circ->cpath->crypto.f_crypto);
+ tt_assert(or_circ->cpath->crypto.b_crypto);
/* Ensure that circ purpose was changed */
tt_int_op(or_circ->base_.purpose, OP_EQ, CIRCUIT_PURPOSE_C_REND_JOINED);
@@ -283,12 +283,12 @@ test_e2e_rend_circuit_setup(void *arg)
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),
+ tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->crypto.f_digest),
OP_EQ, DIGEST_SHA3_256);
- tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->b_digest),
+ tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->crypto.b_digest),
OP_EQ, DIGEST_SHA3_256);
- tt_assert(or_circ->cpath->f_crypto);
- tt_assert(or_circ->cpath->b_crypto);
+ tt_assert(or_circ->cpath->crypto.f_crypto);
+ tt_assert(or_circ->cpath->crypto.b_crypto);
/* Ensure that circ purpose was changed */
tt_int_op(or_circ->base_.purpose, OP_EQ, CIRCUIT_PURPOSE_C_REND_JOINED);
@@ -397,21 +397,25 @@ test_client_pick_intro(void *arg)
} 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);
+ /* (We try several times, to make sure this behavior is consistent, and to
+ * cover the different cases of client_get_random_intro().) */
+ for (int i = 0; i < 64; ++i) {
+ 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(ip);
+ }
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);
+ extend_info_t *ip = client_get_random_intro(&service_kp.pubkey);
tor_assert(!ip);
}
diff --git a/src/test/test_hs_common.c b/src/test/test_hs_common.c
index 16803dbd16..7348eb746c 100644
--- a/src/test/test_hs_common.c
+++ b/src/test/test_hs_common.c
@@ -17,19 +17,21 @@
#include "hs_test_helpers.h"
#include "connection_edge.h"
+#include "crypto_rand.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 "dirauth/dirvote.h"
#include "nodelist.h"
#include "routerlist.h"
#include "statefile.h"
#include "circuitlist.h"
-#include "shared_random.h"
+#include "dirauth/shared_random.h"
#include "util.h"
+#include "voting_schedule.h"
/** Test the validation of HS v3 addresses */
static void
@@ -364,11 +366,8 @@ mock_networkstatus_get_live_consensus(time_t now)
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();
@@ -390,12 +389,12 @@ test_responsible_hsdirs(void *arg)
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);
+ /* Use a fixed time period and pub key so we always take the same path */
+ ed25519_public_key_t pubkey;
+ uint64_t time_period_num = 17653; // 2 May, 2018, 14:00.
+ memset(&pubkey, 42, sizeof(pubkey));
- uint64_t time_period_num = hs_get_time_period_num(now);
- hs_get_responsible_hsdirs(&kp.pubkey, time_period_num,
+ hs_get_responsible_hsdirs(&pubkey, time_period_num,
0, 0, responsible_dirs);
/* Make sure that we only found 2 responsible HSDirs.
@@ -817,7 +816,7 @@ test_time_between_tp_and_srv(void *arg)
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);
+ voting_schedule_recalculate_timing(get_options(), ns.valid_after);
ret = hs_in_period_between_tp_and_srv(&ns, 0);
tt_int_op(ret, OP_EQ, 0);
@@ -825,7 +824,7 @@ test_time_between_tp_and_srv(void *arg)
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);
+ voting_schedule_recalculate_timing(get_options(), ns.valid_after);
ret = hs_in_period_between_tp_and_srv(&ns, 0);
tt_int_op(ret, OP_EQ, 0);
@@ -833,7 +832,7 @@ test_time_between_tp_and_srv(void *arg)
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);
+ voting_schedule_recalculate_timing(get_options(), ns.valid_after);
ret = hs_in_period_between_tp_and_srv(&ns, 0);
tt_int_op(ret, OP_EQ, 1);
@@ -841,7 +840,7 @@ test_time_between_tp_and_srv(void *arg)
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);
+ voting_schedule_recalculate_timing(get_options(), ns.valid_after);
ret = hs_in_period_between_tp_and_srv(&ns, 0);
tt_int_op(ret, OP_EQ, 1);
@@ -849,7 +848,7 @@ test_time_between_tp_and_srv(void *arg)
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);
+ voting_schedule_recalculate_timing(get_options(), ns.valid_after);
ret = hs_in_period_between_tp_and_srv(&ns, 0);
tt_int_op(ret, OP_EQ, 0);
@@ -1336,7 +1335,8 @@ run_reachability_scenario(const reachability_cfg_t *cfg, int num_scenario)
&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);
+ voting_schedule_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);
@@ -1344,7 +1344,8 @@ run_reachability_scenario(const reachability_cfg_t *cfg, int num_scenario)
&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);
+ voting_schedule_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,
@@ -1568,7 +1569,7 @@ helper_set_consensus_and_system_time(networkstatus_t *ns, int position)
} else {
tt_assert(0);
}
- dirvote_recalculate_timing(get_options(), ns->valid_after);
+ voting_schedule_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;
diff --git a/src/test/test_hs_control.c b/src/test/test_hs_control.c
index 207a55de6d..308843e9b8 100644
--- a/src/test/test_hs_control.c
+++ b/src/test/test_hs_control.c
@@ -76,9 +76,8 @@ mock_node_get_by_id(const char *digest)
{
static node_t node;
memcpy(node.identity, digest, DIGEST_LEN);
- node.hsdir_index = tor_malloc_zero(sizeof(hsdir_index_t));
- memset(node.hsdir_index->fetch, 'C', DIGEST256_LEN);
- memset(node.hsdir_index->store_first, 'D', DIGEST256_LEN);
+ memset(node.hsdir_index.fetch, 'C', DIGEST256_LEN);
+ memset(node.hsdir_index.store_first, 'D', DIGEST256_LEN);
return &node;
}
diff --git a/src/test/test_hs_descriptor.c b/src/test/test_hs_descriptor.c
index 8772461f90..14f1a664e7 100644
--- a/src/test/test_hs_descriptor.c
+++ b/src/test/test_hs_descriptor.c
@@ -9,6 +9,8 @@
#define HS_DESCRIPTOR_PRIVATE
#include "crypto_ed25519.h"
+#include "crypto_digest.h"
+#include "crypto_rand.h"
#include "ed25519_cert.h"
#include "or.h"
#include "hs_descriptor.h"
diff --git a/src/test/test_hs_intropoint.c b/src/test/test_hs_intropoint.c
index ec4dcb4705..faa14d9015 100644
--- a/src/test/test_hs_intropoint.c
+++ b/src/test/test_hs_intropoint.c
@@ -13,8 +13,7 @@
#include "test.h"
#include "log_test_helpers.h"
-#include "crypto.h"
-#include "log_test_helpers.h"
+#include "crypto_rand.h"
#include "or.h"
#include "circuitlist.h"
diff --git a/src/test/test_hs_service.c b/src/test/test_hs_service.c
index c1e9f3ced6..7972434d69 100644
--- a/src/test/test_hs_service.c
+++ b/src/test/test_hs_service.c
@@ -33,13 +33,12 @@
#include "circuitbuild.h"
#include "circuitlist.h"
#include "circuituse.h"
-#include "crypto.h"
-#include "dirvote.h"
+#include "crypto_rand.h"
+#include "dirauth/dirvote.h"
#include "networkstatus.h"
#include "nodelist.h"
#include "relay.h"
#include "routerparse.h"
-
#include "hs_common.h"
#include "hs_config.h"
#include "hs_ident.h"
@@ -51,7 +50,8 @@
#include "main.h"
#include "rendservice.h"
#include "statefile.h"
-#include "shared_random_state.h"
+#include "dirauth/shared_random_state.h"
+#include "voting_schedule.h"
/* Trunnel */
#include "hs/cell_establish_intro.h"
@@ -173,12 +173,12 @@ test_e2e_rend_circuit_setup(void *arg)
tt_int_op(retval, OP_EQ, 1);
/* Check the digest algo */
- tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->f_digest),
+ tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->crypto.f_digest),
OP_EQ, DIGEST_SHA3_256);
- tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->b_digest),
+ tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->crypto.b_digest),
OP_EQ, DIGEST_SHA3_256);
- tt_assert(or_circ->cpath->f_crypto);
- tt_assert(or_circ->cpath->b_crypto);
+ tt_assert(or_circ->cpath->crypto.f_crypto);
+ tt_assert(or_circ->cpath->crypto.b_crypto);
/* Ensure that circ purpose was changed */
tt_int_op(or_circ->base_.purpose, OP_EQ, CIRCUIT_PURPOSE_S_REND_JOINED);
@@ -492,6 +492,8 @@ test_helper_functions(void *arg)
MOCK(node_get_by_id, mock_node_get_by_id);
hs_service_init();
+ time_t now = time(NULL);
+ update_approx_time(now);
service = helper_create_service();
@@ -551,7 +553,6 @@ test_helper_functions(void *arg)
/* 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;
@@ -575,7 +576,6 @@ test_helper_functions(void *arg)
/* Testing intro_point_should_expire(). */
{
- time_t now = time(NULL);
/* Just some basic test of the current state. */
tt_u64_op(ip->introduce2_max, OP_GE,
INTRO_POINT_MIN_LIFETIME_INTRODUCTIONS);
@@ -1057,7 +1057,7 @@ test_rotate_descriptors(void *arg)
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);
+ voting_schedule_recalculate_timing(get_options(), mock_ns.valid_after);
/* Create a service with a default descriptor and state. It's added to the
* global map. */
@@ -1095,7 +1095,7 @@ test_rotate_descriptors(void *arg)
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);
+ voting_schedule_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. */
@@ -1157,7 +1157,7 @@ test_build_update_descriptors(void *arg)
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);
+ voting_schedule_recalculate_timing(get_options(), mock_ns.valid_after);
/* Create a service without a current descriptor to trigger a build. */
service = helper_create_service();
@@ -1237,7 +1237,7 @@ test_build_update_descriptors(void *arg)
node->is_running = node->is_valid = node->is_fast = node->is_stable = 1;
}
- /* We have to set thise, or the lack of microdescriptors for these
+ /* We have to set this, or the lack of microdescriptors for these
* nodes will make them unusable. */
get_options_mutable()->UseMicrodescriptors = 0;
diff --git a/src/test/test_mainloop.c b/src/test/test_mainloop.c
new file mode 100644
index 0000000000..9da8a039dd
--- /dev/null
+++ b/src/test/test_mainloop.c
@@ -0,0 +1,142 @@
+/* Copyright (c) 2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file test_mainloop.c
+ * \brief Tests for functions closely related to the Tor main loop
+ */
+
+#include "test.h"
+#include "log_test_helpers.h"
+
+#include "or.h"
+#include "main.h"
+
+static const uint64_t BILLION = 1000000000;
+
+static void
+test_mainloop_update_time_normal(void *arg)
+{
+ (void)arg;
+
+ monotime_enable_test_mocking();
+ /* This is arbitrary */
+ uint64_t mt_now = U64_LITERAL(7493289274986);
+ /* This time is in the past as of when this test was written. */
+ time_t now = 1525272090;
+ monotime_coarse_set_mock_time_nsec(mt_now);
+ reset_uptime();
+ update_current_time(now);
+ tt_int_op(approx_time(), OP_EQ, now);
+ tt_int_op(get_uptime(), OP_EQ, 0);
+
+ update_current_time(now); // Same time as before is a no-op.
+ tt_int_op(get_uptime(), OP_EQ, 0);
+
+ now += 1;
+ mt_now += BILLION;
+ monotime_coarse_set_mock_time_nsec(mt_now);
+ update_current_time(now);
+ tt_int_op(approx_time(), OP_EQ, now);
+ tt_int_op(get_uptime(), OP_EQ, 1);
+
+ now += 2; // two-second jump is unremarkable.
+ mt_now += 2*BILLION;
+ update_current_time(now);
+ monotime_coarse_set_mock_time_nsec(mt_now);
+ tt_int_op(approx_time(), OP_EQ, now);
+ tt_int_op(get_uptime(), OP_EQ, 3);
+
+ now -= 1; // a one-second hop backwards is also unremarkable.
+ update_current_time(now);
+ tt_int_op(approx_time(), OP_EQ, now); // it changes the approx time...
+ tt_int_op(get_uptime(), OP_EQ, 3); // but it doesn't roll back our uptime
+
+ done:
+ monotime_disable_test_mocking();
+}
+
+static void
+test_mainloop_update_time_jumps(void *arg)
+{
+ (void)arg;
+
+ monotime_enable_test_mocking();
+ /* This is arbitrary */
+ uint64_t mt_now = U64_LITERAL(7493289274986);
+ /* This time is in the past as of when this test was written. */
+ time_t now = 220897152;
+ monotime_coarse_set_mock_time_nsec(mt_now);
+ reset_uptime();
+ update_current_time(now);
+ tt_int_op(approx_time(), OP_EQ, now);
+ tt_int_op(get_uptime(), OP_EQ, 0);
+
+ /* Put some uptime on the clock.. */
+ now += 3;
+ mt_now += 3*BILLION;
+ monotime_coarse_set_mock_time_nsec(mt_now);
+ update_current_time(now);
+ tt_int_op(approx_time(), OP_EQ, now);
+ tt_int_op(get_uptime(), OP_EQ, 3);
+
+ /* Now try jumping forward and backward, without updating the monotonic
+ * clock. */
+ setup_capture_of_logs(LOG_NOTICE);
+ now += 1800;
+ update_current_time(now);
+ expect_single_log_msg_containing(
+ "Your system clock just jumped 1800 seconds forward");
+ tt_int_op(approx_time(), OP_EQ, now);
+ tt_int_op(get_uptime(), OP_EQ, 3); // no uptime change.
+ mock_clean_saved_logs();
+
+ now -= 600;
+ update_current_time(now);
+ expect_single_log_msg_containing(
+ "Your system clock just jumped 600 seconds backward");
+ tt_int_op(approx_time(), OP_EQ, now);
+ tt_int_op(get_uptime(), OP_EQ, 3); // no uptime change.
+ mock_clean_saved_logs();
+
+ /* uptime tracking should go normally now if the clock moves sensibly. */
+ now += 2;
+ mt_now += 2*BILLION;
+ update_current_time(now);
+ tt_int_op(approx_time(), OP_EQ, now);
+ tt_int_op(get_uptime(), OP_EQ, 5);
+
+ /* If we skip forward by a few minutes but the monotonic clock agrees,
+ * we've just been idle: that counts as not worth warning about. */
+ now += 1800;
+ mt_now += 1800*BILLION;
+ monotime_coarse_set_mock_time_nsec(mt_now);
+ update_current_time(now);
+ expect_no_log_entry();
+ tt_int_op(approx_time(), OP_EQ, now);
+ tt_int_op(get_uptime(), OP_EQ, 5); // this doesn't count to uptime, though.
+
+ /* If we skip forward by a long time, even if the clock agrees, it's
+ * idnless that counts. */
+ now += 4000;
+ mt_now += 4000*BILLION;
+ monotime_coarse_set_mock_time_nsec(mt_now);
+ update_current_time(now);
+ expect_single_log_msg_containing("Tor has been idle for 4000 seconds");
+ tt_int_op(approx_time(), OP_EQ, now);
+ tt_int_op(get_uptime(), OP_EQ, 5);
+
+ done:
+ teardown_capture_of_logs();
+ monotime_disable_test_mocking();
+}
+
+#define MAINLOOP_TEST(name) \
+ { #name, test_mainloop_## name , TT_FORK, NULL, NULL }
+
+struct testcase_t mainloop_tests[] = {
+ MAINLOOP_TEST(update_time_normal),
+ MAINLOOP_TEST(update_time_jumps),
+ END_OF_TESTCASES
+};
+
diff --git a/src/test/test_microdesc.c b/src/test/test_microdesc.c
index 59b28f7580..4b168f49ed 100644
--- a/src/test/test_microdesc.c
+++ b/src/test/test_microdesc.c
@@ -5,7 +5,8 @@
#include "or.h"
#include "config.h"
-#include "dirvote.h"
+#define DIRVOTE_PRIVATE
+#include "dirauth/dirvote.h"
#include "microdesc.h"
#include "networkstatus.h"
#include "routerlist.h"
@@ -385,25 +386,6 @@ static const char test_ri2[] =
"cf34GXHv61XReJF3AlzNHFpbrPOYmowmhrTULKyMqow=\n"
"-----END SIGNATURE-----\n";
-static const char test_md_8[] =
- "onion-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBANBJz8Vldl12aFeSMPLiA4nOetLDN0oxU8bB1SDhO7Uu2zdWYVYAF5J0\n"
- "st7WvrVy/jA9v/fsezNAPskBanecHRSkdMTpkcgRPMHE7CTGEwIy1Yp1X4bPgDlC\n"
- "VCnbs5Pcts5HnWEYNK7qHDAUn+IlmjOO+pTUY8uyq+GQVz6H9wFlAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n";
-
-static const char test_md_16[] =
- "onion-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBANBJz8Vldl12aFeSMPLiA4nOetLDN0oxU8bB1SDhO7Uu2zdWYVYAF5J0\n"
- "st7WvrVy/jA9v/fsezNAPskBanecHRSkdMTpkcgRPMHE7CTGEwIy1Yp1X4bPgDlC\n"
- "VCnbs5Pcts5HnWEYNK7qHDAUn+IlmjOO+pTUY8uyq+GQVz6H9wFlAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key Gg73xH7+kTfT6bi1uNVx9gwQdQas9pROIfmc4NpAdC4=\n"
- "p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n";
-
static const char test_md_18[] =
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
@@ -415,16 +397,6 @@ static const char test_md_18[] =
"p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n"
"id rsa1024 Cd47okjCHD83YGzThGBDptXs9Z4\n";
-static const char test_md2_18[] =
- "onion-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAL2R8EfubUcahxha4u02P4VAR0llQIMwFAmrHPjzcK7apcQgDOf2ovOA\n"
- "+YQnJFxlpBmCoCZC6ssCi+9G0mqo650lFuTMP5I90BdtjotfzESfTykHLiChyvhd\n"
- "l0dlqclb2SU/GKem/fLRXH16aNi72CdSUu/1slKs/70ILi34QixRAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key hbxdRnfVUJJY7+KcT4E3Rs7/zuClbN3hJrjSBiEGMgI=\n"
- "id rsa1024 t+J/EEITw28T5+mCkYKEXklZl6A\n";
-
static const char test_md2_21[] =
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
@@ -444,17 +416,6 @@ test_md_generate(void *arg)
ri = router_parse_entry_from_string(test_ri, NULL, 0, 0, NULL, NULL);
tt_assert(ri);
- md = dirvote_create_microdescriptor(ri, 8);
- tt_str_op(md->body, OP_EQ, test_md_8);
-
- /* XXXX test family lines. */
- /* XXXX test method 14 for A lines. */
- /* XXXX test method 15 for P6 lines. */
-
- microdesc_free(md);
- md = NULL;
- md = dirvote_create_microdescriptor(ri, 16);
- tt_str_op(md->body, OP_EQ, test_md_16);
microdesc_free(md);
md = NULL;
@@ -471,11 +432,6 @@ test_md_generate(void *arg)
microdesc_free(md);
md = NULL;
- md = dirvote_create_microdescriptor(ri, 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, OP_EQ, test_md2_21);
tt_assert(ed25519_pubkey_eq(md->ed25519_identity_pkey,
diff --git a/src/test/test_nodelist.c b/src/test/test_nodelist.c
index 094e934712..7d8e57543c 100644
--- a/src/test/test_nodelist.c
+++ b/src/test/test_nodelist.c
@@ -7,6 +7,7 @@
**/
#include "or.h"
+#include "crypto_rand.h"
#include "networkstatus.h"
#include "nodelist.h"
#include "torcert.h"
diff --git a/src/test/test_oom.c b/src/test/test_oom.c
index c172fe60c7..abf8896452 100644
--- a/src/test/test_oom.c
+++ b/src/test/test_oom.c
@@ -13,6 +13,7 @@
#include "compat_libevent.h"
#include "connection.h"
#include "config.h"
+#include "crypto_rand.h"
#include "relay.h"
#include "test.h"
#include "test_helpers.h"
diff --git a/src/test/test_options.c b/src/test/test_options.c
index eaf5034397..65564f324c 100644
--- a/src/test/test_options.c
+++ b/src/test/test_options.c
@@ -2067,12 +2067,12 @@ test_options_validate__testing(void *ignored)
ENSURE_DEFAULT(TestingV3AuthVotingStartOffset, 3000);
ENSURE_DEFAULT(TestingAuthDirTimeToLearnReachability, 3000);
ENSURE_DEFAULT(TestingEstimatedDescriptorPropagationTime, 3000);
- ENSURE_DEFAULT(TestingServerDownloadSchedule, 3000);
- ENSURE_DEFAULT(TestingClientDownloadSchedule, 3000);
- ENSURE_DEFAULT(TestingServerConsensusDownloadSchedule, 3000);
- ENSURE_DEFAULT(TestingClientConsensusDownloadSchedule, 3000);
- ENSURE_DEFAULT(TestingBridgeDownloadSchedule, 3000);
- ENSURE_DEFAULT(TestingBridgeBootstrapDownloadSchedule, 3000);
+ ENSURE_DEFAULT(TestingServerDownloadInitialDelay, 3000);
+ ENSURE_DEFAULT(TestingClientDownloadInitialDelay, 3000);
+ ENSURE_DEFAULT(TestingServerConsensusDownloadInitialDelay, 3000);
+ ENSURE_DEFAULT(TestingClientConsensusDownloadInitialDelay, 3000);
+ ENSURE_DEFAULT(TestingBridgeDownloadInitialDelay, 3000);
+ ENSURE_DEFAULT(TestingBridgeBootstrapDownloadInitialDelay, 3000);
ENSURE_DEFAULT(TestingClientMaxIntervalWithoutRequest, 3000);
ENSURE_DEFAULT(TestingDirConnectionMaxStall, 3000);
ENSURE_DEFAULT(TestingAuthKeyLifetime, 3000);
@@ -2422,37 +2422,6 @@ test_options_validate__circuits(void *ignored)
}
static void
-test_options_validate__port_forwarding(void *ignored)
-{
- (void)ignored;
- int ret;
- char *msg;
- options_test_data_t *tdata = NULL;
-
- free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "PortForwarding 1\nSandbox 1\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, "PortForwarding is not compatible with Sandbox;"
- " at most one can be set");
- tor_free(msg);
-
- free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "PortForwarding 1\nSandbox 0\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, 0);
- tt_assert(!msg);
- tor_free(msg);
-
- done:
- free_options_test_data(tdata);
- policies_free_all();
- tor_free(msg);
-}
-
-static void
test_options_validate__tor2web(void *ignored)
{
(void)ignored;
@@ -4135,16 +4104,6 @@ test_options_validate__testing_options(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
"TestingEnableTbEmptyEvent 1\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, "TestingEnableTbEmptyEvent may only be changed "
- "in testing Tor networks!");
- tor_free(msg);
-
- free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "TestingEnableTbEmptyEvent 1\n"
VALID_DIR_AUTH
"TestingTorNetwork 1\n"
"___UsingTestNetworkDefaults 0\n"
@@ -4261,7 +4220,6 @@ struct testcase_t options_tests[] = {
LOCAL_VALIDATE_TEST(path_bias),
LOCAL_VALIDATE_TEST(bandwidth),
LOCAL_VALIDATE_TEST(circuits),
- LOCAL_VALIDATE_TEST(port_forwarding),
LOCAL_VALIDATE_TEST(tor2web),
LOCAL_VALIDATE_TEST(rend),
LOCAL_VALIDATE_TEST(single_onion),
diff --git a/src/test/test_periodic_event.c b/src/test/test_periodic_event.c
new file mode 100644
index 0000000000..f159c4f83a
--- /dev/null
+++ b/src/test/test_periodic_event.c
@@ -0,0 +1,329 @@
+/* Copyright (c) 2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file test_periodic_event.c
+ * \brief Test the periodic events that Tor uses for different roles. They are
+ * part of the libevent mainloop
+ */
+
+#define CONFIG_PRIVATE
+#define HS_SERVICE_PRIVATE
+#define MAIN_PRIVATE
+
+#include "test.h"
+#include "test_helpers.h"
+
+#include "or.h"
+#include "config.h"
+#include "hibernate.h"
+#include "hs_service.h"
+#include "main.h"
+#include "periodic.h"
+
+/** Helper function: This is replaced in some tests for the event callbacks so
+ * we don't actually go into the code path of those callbacks. */
+static int
+dumb_event_fn(time_t now, const or_options_t *options)
+{
+ (void) now;
+ (void) options;
+
+ /* Will get rescheduled in 300 seconds. It just can't be 0. */
+ return 300;
+}
+
+static void
+register_dummy_hidden_service(hs_service_t *service)
+{
+ memset(service, 0, sizeof(hs_service_t));
+ memset(&service->keys.identity_pk, 'A', sizeof(service->keys.identity_pk));
+ (void) register_service(get_hs_service_map(), service);
+}
+
+static void
+test_pe_initialize(void *arg)
+{
+ (void) arg;
+
+ /* Initialize the events but the callback won't get called since we would
+ * need to run the main loop and then wait for a second delaying the unit
+ * tests. Instead, we'll test the callback work indepedently elsewhere. */
+ initialize_periodic_events();
+
+ /* Validate that all events have been set up. */
+ for (int i = 0; periodic_events[i].name; ++i) {
+ periodic_event_item_t *item = &periodic_events[i];
+ tt_assert(item->ev);
+ tt_assert(item->fn);
+ tt_u64_op(item->last_action_time, OP_EQ, 0);
+ /* Every event must have role(s) assign to it. This is done statically. */
+ tt_u64_op(item->roles, OP_NE, 0);
+ tt_uint_op(periodic_event_is_enabled(item), OP_EQ, 0);
+ }
+
+ done:
+ teardown_periodic_events();
+}
+
+static void
+test_pe_launch(void *arg)
+{
+ hs_service_t service, *to_remove = NULL;
+ or_options_t *options;
+
+ (void) arg;
+
+ hs_init();
+ /* We need to put tor in hibernation live state so the events requiring
+ * network gets enabled. */
+ consider_hibernation(time(NULL));
+
+ /* Hack: We'll set a dumb fn() of each events so they don't get called when
+ * dispatching them. We just want to test the state of the callbacks, not
+ * the whole code path. */
+ for (int i = 0; periodic_events[i].name; ++i) {
+ periodic_event_item_t *item = &periodic_events[i];
+ item->fn = dumb_event_fn;
+ }
+
+ /* Lets make sure that before intialization, we can't scan the periodic
+ * events list and launch them. Lets try by being a Client. */
+ options = get_options_mutable();
+ options->SocksPort_set = 1;
+ periodic_events_on_new_options(options);
+ for (int i = 0; periodic_events[i].name; ++i) {
+ periodic_event_item_t *item = &periodic_events[i];
+ tt_int_op(periodic_event_is_enabled(item), OP_EQ, 0);
+ }
+
+ initialize_periodic_events();
+
+ /* Now that we've initialized, rescan the list to launch. */
+ periodic_events_on_new_options(options);
+
+ for (int i = 0; periodic_events[i].name; ++i) {
+ periodic_event_item_t *item = &periodic_events[i];
+ if (item->roles & PERIODIC_EVENT_ROLE_CLIENT) {
+ tt_int_op(periodic_event_is_enabled(item), OP_EQ, 1);
+ } else {
+ tt_int_op(periodic_event_is_enabled(item), OP_EQ, 0);
+ }
+ // enabled or not, the event has not yet been run.
+ tt_u64_op(item->last_action_time, OP_EQ, 0);
+ }
+
+ /* Remove Client but become a Relay. */
+ options->SocksPort_set = 0;
+ options->ORPort_set = 1;
+ periodic_events_on_new_options(options);
+
+ unsigned roles = get_my_roles(options);
+ tt_uint_op(roles, OP_EQ,
+ PERIODIC_EVENT_ROLE_RELAY|PERIODIC_EVENT_ROLE_DIRSERVER);
+
+ for (int i = 0; periodic_events[i].name; ++i) {
+ periodic_event_item_t *item = &periodic_events[i];
+ /* Only Client role should be disabled. */
+ if (item->roles == PERIODIC_EVENT_ROLE_CLIENT) {
+ tt_int_op(periodic_event_is_enabled(item), OP_EQ, 0);
+ }
+ if (item->roles & PERIODIC_EVENT_ROLE_RELAY) {
+ tt_int_op(periodic_event_is_enabled(item), OP_EQ, 1);
+ }
+ /* Non Relay role should be disabled, except for Dirserver. */
+ if (!(item->roles & roles)) {
+ tt_int_op(periodic_event_is_enabled(item), OP_EQ, 0);
+ }
+ }
+
+ /* Disable everything and we'll enable them ALL. */
+ options->SocksPort_set = 0;
+ options->ORPort_set = 0;
+ periodic_events_on_new_options(options);
+
+ for (int i = 0; periodic_events[i].name; ++i) {
+ periodic_event_item_t *item = &periodic_events[i];
+ tt_int_op(periodic_event_is_enabled(item), OP_EQ, 0);
+ }
+
+ /* Enable everything. */
+ options->SocksPort_set = 1; options->ORPort_set = 1;
+ options->BridgeRelay = 1; options->AuthoritativeDir = 1;
+ options->V3AuthoritativeDir = 1; options->BridgeAuthoritativeDir = 1;
+ register_dummy_hidden_service(&service);
+ periodic_events_on_new_options(options);
+ /* Note down the reference because we need to remove this service from the
+ * global list before the hs_free_all() call so it doesn't try to free
+ * memory on the stack. Furthermore, we can't remove it now else it will
+ * trigger a rescan of the event disabling the HS service event. */
+ to_remove = &service;
+
+ for (int i = 0; periodic_events[i].name; ++i) {
+ periodic_event_item_t *item = &periodic_events[i];
+ tt_int_op(periodic_event_is_enabled(item), OP_EQ, 1);
+ }
+
+ done:
+ if (to_remove) {
+ remove_service(get_hs_service_map(), to_remove);
+ }
+ hs_free_all();
+}
+
+static void
+test_pe_get_roles(void *arg)
+{
+ int roles;
+
+ (void) arg;
+
+ /* Just so the HS global map exists. */
+ hs_init();
+
+ or_options_t *options = get_options_mutable();
+ tt_assert(options);
+
+ /* Nothing configured, should be no roles. */
+ roles = get_my_roles(options);
+ tt_int_op(roles, OP_EQ, 0);
+
+ /* Indicate we have a SocksPort, roles should be come Client. */
+ options->SocksPort_set = 1;
+ roles = get_my_roles(options);
+ tt_int_op(roles, OP_EQ, PERIODIC_EVENT_ROLE_CLIENT);
+
+ /* Now, we'll add a ORPort so should now be a Relay + Client. */
+ options->ORPort_set = 1;
+ roles = get_my_roles(options);
+ tt_int_op(roles, OP_EQ,
+ (PERIODIC_EVENT_ROLE_CLIENT | PERIODIC_EVENT_ROLE_RELAY |
+ PERIODIC_EVENT_ROLE_DIRSERVER));
+
+ /* Now add a Bridge. */
+ options->BridgeRelay = 1;
+ roles = get_my_roles(options);
+ tt_int_op(roles, OP_EQ,
+ (PERIODIC_EVENT_ROLE_CLIENT | PERIODIC_EVENT_ROLE_RELAY |
+ PERIODIC_EVENT_ROLE_BRIDGE | PERIODIC_EVENT_ROLE_DIRSERVER));
+ tt_assert(roles & PERIODIC_EVENT_ROLE_ROUTER);
+ /* Unset client so we can solely test Router role. */
+ options->SocksPort_set = 0;
+ roles = get_my_roles(options);
+ tt_int_op(roles, OP_EQ,
+ PERIODIC_EVENT_ROLE_ROUTER | PERIODIC_EVENT_ROLE_DIRSERVER);
+
+ /* Reset options so we can test authorities. */
+ options->SocksPort_set = 0;
+ options->ORPort_set = 0;
+ options->BridgeRelay = 0;
+ roles = get_my_roles(options);
+ tt_int_op(roles, OP_EQ, 0);
+
+ /* Now upgrade to Dirauth. */
+ options->DirPort_set = 1;
+ options->AuthoritativeDir = 1;
+ options->V3AuthoritativeDir = 1;
+ roles = get_my_roles(options);
+ tt_int_op(roles, OP_EQ,
+ PERIODIC_EVENT_ROLE_DIRAUTH|PERIODIC_EVENT_ROLE_DIRSERVER);
+ tt_assert(roles & PERIODIC_EVENT_ROLE_AUTHORITIES);
+
+ /* Now Bridge Authority. */
+ options->V3AuthoritativeDir = 0;
+ options->BridgeAuthoritativeDir = 1;
+ roles = get_my_roles(options);
+ tt_int_op(roles, OP_EQ,
+ PERIODIC_EVENT_ROLE_BRIDGEAUTH|PERIODIC_EVENT_ROLE_DIRSERVER);
+ tt_assert(roles & PERIODIC_EVENT_ROLE_AUTHORITIES);
+
+ /* Move that bridge auth to become a relay. */
+ options->ORPort_set = 1;
+ roles = get_my_roles(options);
+ tt_int_op(roles, OP_EQ,
+ (PERIODIC_EVENT_ROLE_BRIDGEAUTH | PERIODIC_EVENT_ROLE_RELAY
+ | PERIODIC_EVENT_ROLE_DIRSERVER));
+ tt_assert(roles & PERIODIC_EVENT_ROLE_AUTHORITIES);
+
+ /* And now an Hidden service. */
+ hs_service_t service;
+ register_dummy_hidden_service(&service);
+ roles = get_my_roles(options);
+ /* Remove it now so the hs_free_all() doesn't try to free stack memory. */
+ remove_service(get_hs_service_map(), &service);
+ tt_int_op(roles, OP_EQ,
+ (PERIODIC_EVENT_ROLE_BRIDGEAUTH | PERIODIC_EVENT_ROLE_RELAY |
+ PERIODIC_EVENT_ROLE_HS_SERVICE | PERIODIC_EVENT_ROLE_DIRSERVER));
+ tt_assert(roles & PERIODIC_EVENT_ROLE_AUTHORITIES);
+
+ done:
+ hs_free_all();
+}
+
+static void
+test_pe_hs_service(void *arg)
+{
+ hs_service_t service, *to_remove = NULL;
+
+ (void) arg;
+
+ hs_init();
+ /* We need to put tor in hibernation live state so the events requiring
+ * network gets enabled. */
+ consider_hibernation(time(NULL));
+ /* Initialize the events so we can enable them */
+ initialize_periodic_events();
+
+ /* Hack: We'll set a dumb fn() of each events so they don't get called when
+ * dispatching them. We just want to test the state of the callbacks, not
+ * the whole code path. */
+ for (int i = 0; periodic_events[i].name; ++i) {
+ periodic_event_item_t *item = &periodic_events[i];
+ item->fn = dumb_event_fn;
+ }
+
+ /* This should trigger a rescan of the list and enable the HS service
+ * events. */
+ register_dummy_hidden_service(&service);
+ /* Note down the reference because we need to remove this service from the
+ * global list before the hs_free_all() call so it doesn't try to free
+ * memory on the stack. Furthermore, we can't remove it now else it will
+ * trigger a rescan of the event disabling the HS service event. */
+ to_remove = &service;
+
+ for (int i = 0; periodic_events[i].name; ++i) {
+ periodic_event_item_t *item = &periodic_events[i];
+ if (item->roles & PERIODIC_EVENT_ROLE_HS_SERVICE) {
+ tt_int_op(periodic_event_is_enabled(item), OP_EQ, 1);
+ }
+ }
+ to_remove = NULL;
+
+ /* Remove the service from the global map, it should trigger a rescan and
+ * disable the HS service events. */
+ remove_service(get_hs_service_map(), &service);
+ for (int i = 0; periodic_events[i].name; ++i) {
+ periodic_event_item_t *item = &periodic_events[i];
+ if (item->roles & PERIODIC_EVENT_ROLE_HS_SERVICE) {
+ tt_int_op(periodic_event_is_enabled(item), OP_EQ, 0);
+ }
+ }
+
+ done:
+ if (to_remove) {
+ remove_service(get_hs_service_map(), to_remove);
+ }
+ hs_free_all();
+}
+
+#define PE_TEST(name) \
+ { #name, test_pe_## name , TT_FORK, NULL, NULL }
+
+struct testcase_t periodic_event_tests[] = {
+ PE_TEST(initialize),
+ PE_TEST(launch),
+ PE_TEST(get_roles),
+ PE_TEST(hs_service),
+
+ END_OF_TESTCASES
+};
diff --git a/src/test/test_policy.c b/src/test/test_policy.c
index f8aa8ac40b..e89d49aaf5 100644
--- a/src/test/test_policy.c
+++ b/src/test/test_policy.c
@@ -1496,9 +1496,21 @@ test_dump_exit_policy_to_string(void *arg)
}
static routerinfo_t *mock_desc_routerinfo = NULL;
+static int routerinfo_err;
+
static const routerinfo_t *
-mock_router_get_my_routerinfo(void)
+mock_router_get_my_routerinfo_with_err(int *err)
{
+ if (routerinfo_err) {
+ if (err)
+ *err = routerinfo_err;
+
+ return NULL;
+ }
+
+ if (err)
+ *err = 0;
+
return mock_desc_routerinfo;
}
@@ -1541,7 +1553,8 @@ test_policies_getinfo_helper_policies(void *arg)
tor_free(answer);
memset(&mock_my_routerinfo, 0, sizeof(routerinfo_t));
- MOCK(router_get_my_routerinfo, mock_router_get_my_routerinfo);
+ MOCK(router_get_my_routerinfo_with_err,
+ mock_router_get_my_routerinfo_with_err);
mock_my_routerinfo.exit_policy = smartlist_new();
mock_desc_routerinfo = &mock_my_routerinfo;
@@ -1658,6 +1671,55 @@ test_policies_getinfo_helper_policies(void *arg)
tt_assert(strlen(answer) == ipv4_len + ipv6_len + 1);
tor_free(answer);
+ routerinfo_err = TOR_ROUTERINFO_ERROR_NO_EXT_ADDR;
+ rv = getinfo_helper_policies(NULL, "exit-policy/full", &answer,
+ &errmsg);
+ tt_int_op(rv, OP_EQ, -1);
+ tt_ptr_op(answer, OP_EQ, NULL);
+ tt_ptr_op(errmsg, OP_NE, NULL);
+ tt_str_op(errmsg, OP_EQ, "No known exit address yet");
+
+ routerinfo_err = TOR_ROUTERINFO_ERROR_CANNOT_PARSE;
+ rv = getinfo_helper_policies(NULL, "exit-policy/full", &answer,
+ &errmsg);
+ tt_int_op(rv, OP_EQ, -1);
+ tt_ptr_op(answer, OP_EQ, NULL);
+ tt_ptr_op(errmsg, OP_NE, NULL);
+ tt_str_op(errmsg, OP_EQ, "Cannot parse descriptor");
+
+ routerinfo_err = TOR_ROUTERINFO_ERROR_NOT_A_SERVER;
+ rv = getinfo_helper_policies(NULL, "exit-policy/full", &answer,
+ &errmsg);
+ tt_int_op(rv, OP_EQ, 0);
+ tt_ptr_op(answer, OP_EQ, NULL);
+ tt_ptr_op(errmsg, OP_NE, NULL);
+ tt_str_op(errmsg, OP_EQ, "Not running in server mode");
+
+ routerinfo_err = TOR_ROUTERINFO_ERROR_DIGEST_FAILED;
+ rv = getinfo_helper_policies(NULL, "exit-policy/full", &answer,
+ &errmsg);
+
+ tt_int_op(rv, OP_EQ, 0);
+ tt_ptr_op(answer, OP_EQ, NULL);
+ tt_ptr_op(errmsg, OP_NE, NULL);
+ tt_str_op(errmsg, OP_EQ, "Key digest failed");
+
+ routerinfo_err = TOR_ROUTERINFO_ERROR_CANNOT_GENERATE;
+ rv = getinfo_helper_policies(NULL, "exit-policy/full", &answer,
+ &errmsg);
+ tt_int_op(rv, OP_EQ, -1);
+ tt_ptr_op(answer, OP_EQ, NULL);
+ tt_ptr_op(errmsg, OP_NE, NULL);
+ tt_str_op(errmsg, OP_EQ, "Cannot generate descriptor");
+
+ routerinfo_err = TOR_ROUTERINFO_ERROR_DESC_REBUILDING;
+ rv = getinfo_helper_policies(NULL, "exit-policy/full", &answer,
+ &errmsg);
+ tt_int_op(rv, OP_EQ, -1);
+ tt_ptr_op(answer, OP_EQ, NULL);
+ tt_ptr_op(errmsg, OP_NE, NULL);
+ tt_str_op(errmsg, OP_EQ, "Descriptor still rebuilding - not ready yet");
+
done:
tor_free(answer);
UNMOCK(get_options);
@@ -1923,11 +1985,8 @@ test_policies_fascist_firewall_allows_address(void *arg)
tor_addr_port_t chosen_rs_ap; \
tor_addr_make_null(&chosen_rs_ap.addr, AF_INET); \
chosen_rs_ap.port = 0; \
- tt_int_op(fascist_firewall_choose_address_rs(&(fake_rs), \
- (fw_connection), \
- (pref_only), \
- &chosen_rs_ap), \
- OP_EQ, (expect_rv)); \
+ fascist_firewall_choose_address_rs(&(fake_rs), (fw_connection), \
+ (pref_only), &chosen_rs_ap); \
tt_assert(tor_addr_eq(&(expect_ap).addr, &chosen_rs_ap.addr)); \
tt_int_op((expect_ap).port, OP_EQ, chosen_rs_ap.port); \
STMT_END
@@ -1940,11 +1999,8 @@ test_policies_fascist_firewall_allows_address(void *arg)
tor_addr_port_t chosen_node_ap; \
tor_addr_make_null(&chosen_node_ap.addr, AF_INET); \
chosen_node_ap.port = 0; \
- tt_int_op(fascist_firewall_choose_address_node(&(fake_node), \
- (fw_connection), \
- (pref_only), \
- &chosen_node_ap), \
- OP_EQ, (expect_rv)); \
+ fascist_firewall_choose_address_node(&(fake_node),(fw_connection), \
+ (pref_only), &chosen_node_ap); \
tt_assert(tor_addr_eq(&(expect_ap).addr, &chosen_node_ap.addr)); \
tt_int_op((expect_ap).port, OP_EQ, chosen_node_ap.port); \
STMT_END
diff --git a/src/test/test_protover.c b/src/test/test_protover.c
index bdfb2d13cd..06fd575631 100644
--- a/src/test/test_protover.c
+++ b/src/test/test_protover.c
@@ -229,8 +229,8 @@ test_protover_vote(void *arg)
/* Protocol name too long */
smartlist_clear(lst);
smartlist_add(lst, (void*) "DoSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
result = protover_compute_vote(lst, 1);
tt_str_op(result, OP_EQ, "");
tor_free(result);
@@ -321,10 +321,10 @@ test_protover_all_supported(void *arg)
#ifndef HAVE_RUST // XXXXXX ?????
tor_capture_bugs_(1);
tt_assert(protover_all_supported(
- "DoSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaaaaaa=1-65536", &msg));
+ "DoSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaa=1-65536", &msg));
tor_end_capture_bugs_();
#endif
diff --git a/src/test/test_relaycell.c b/src/test/test_relaycell.c
index eea1f5dc80..2fc0288f69 100644
--- a/src/test/test_relaycell.c
+++ b/src/test/test_relaycell.c
@@ -4,13 +4,28 @@
/* Unit tests for handling different kinds of relay cell */
#define RELAY_PRIVATE
+#define CIRCUITLIST_PRIVATE
+#define CONNECTION_EDGE_PRIVATE
+#define CONNECTION_PRIVATE
+
#include "or.h"
+#include "main.h"
#include "config.h"
#include "connection.h"
+#include "crypto.h"
+#include "crypto_rand.h"
+#include "circuitbuild.h"
+#include "circuitlist.h"
#include "connection_edge.h"
+#include "log_test_helpers.h"
#include "relay.h"
#include "test.h"
+#include "log_test_helpers.h"
+
+#include "circpathbias.h"
+#include "connection_edge.h"
+
static int srm_ncalls;
static entry_connection_t *srm_conn;
static int srm_atype;
@@ -60,6 +75,805 @@ mark_unattached_mock(entry_connection_t *conn, int endreason,
(void) file;
}
+/* 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);
+ tor_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;
+ /* Create a default HS identifier. */
+ circ->hs_ident = tor_malloc_zero(sizeof(hs_ident_circuit_t));
+
+ return circ;
+}
+
+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
+mock_mark_circ_for_close(circuit_t *circ, int reason, int line,
+ const char *file)
+{
+ (void)reason; (void)line; (void)file;
+
+ circ->marked_for_close = 1;
+ return;
+}
+
+static void
+mock_mark_for_close(connection_t *conn,
+ int line, const char *file)
+{
+ (void)line;
+ (void)file;
+
+ conn->marked_for_close = 1;
+ return;
+}
+
+static void
+mock_start_reading(connection_t *conn)
+{
+ (void)conn;
+ return;
+}
+
+static int
+mock_send_command(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;
+}
+
+static entry_connection_t *
+fake_entry_conn(origin_circuit_t *oncirc, streamid_t id)
+{
+ edge_connection_t *edgeconn;
+ entry_connection_t *entryconn;
+
+ entryconn = entry_connection_new(CONN_TYPE_AP, AF_INET);
+ edgeconn = ENTRY_TO_EDGE_CONN(entryconn);
+ edgeconn->base_.state = AP_CONN_STATE_CONNECT_WAIT;
+ edgeconn->deliver_window = STREAMWINDOW_START;
+ edgeconn->package_window = STREAMWINDOW_START;
+
+ edgeconn->stream_id = id;
+ edgeconn->on_circuit = TO_CIRCUIT(oncirc);
+ edgeconn->cpath_layer = oncirc->cpath;
+
+ return entryconn;
+}
+
+#define PACK_CELL(id, cmd, body_s) do { \
+ memset(&cell, 0, sizeof(cell)); \
+ memset(&rh, 0, sizeof(rh)); \
+ memcpy(cell.payload+RELAY_HEADER_SIZE, (body_s), sizeof((body_s))-1); \
+ rh.length = sizeof((body_s))-1; \
+ rh.command = (cmd); \
+ rh.stream_id = (id); \
+ relay_header_pack((uint8_t*)&cell.payload, &rh); \
+ } while (0)
+#define ASSERT_COUNTED_BW() do { \
+ tt_int_op(circ->n_delivered_read_circ_bw, OP_EQ, delivered+rh.length); \
+ tt_int_op(circ->n_overhead_read_circ_bw, OP_EQ, \
+ overhead+RELAY_PAYLOAD_SIZE-rh.length); \
+ delivered = circ->n_delivered_read_circ_bw; \
+ overhead = circ->n_overhead_read_circ_bw; \
+ } while (0)
+#define ASSERT_UNCOUNTED_BW() do { \
+ tt_int_op(circ->n_delivered_read_circ_bw, OP_EQ, delivered); \
+ tt_int_op(circ->n_overhead_read_circ_bw, OP_EQ, overhead); \
+ } while (0)
+
+static int
+subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id)
+{
+ cell_t cell;
+ relay_header_t rh;
+ edge_connection_t *edgeconn;
+ entry_connection_t *entryconn2=NULL;
+ entry_connection_t *entryconn3=NULL;
+ entry_connection_t *entryconn4=NULL;
+ int delivered = circ->n_delivered_read_circ_bw;
+ int overhead = circ->n_overhead_read_circ_bw;
+
+ /* Make new entryconns */
+ entryconn2 = fake_entry_conn(circ, init_id);
+ entryconn2->socks_request->has_finished = 1;
+ entryconn3 = fake_entry_conn(circ, init_id+1);
+ entryconn3->socks_request->has_finished = 1;
+ entryconn4 = fake_entry_conn(circ, init_id+2);
+ entryconn4->socks_request->has_finished = 1;
+ edgeconn = ENTRY_TO_EDGE_CONN(entryconn2);
+ edgeconn->package_window = 23;
+ edgeconn->base_.state = AP_CONN_STATE_OPEN;
+
+ int data_cells = edgeconn->deliver_window;
+ int sendme_cells = (STREAMWINDOW_START-edgeconn->package_window)
+ /STREAMWINDOW_INCREMENT;
+ ENTRY_TO_CONN(entryconn2)->marked_for_close = 0;
+ ENTRY_TO_CONN(entryconn2)->outbuf_flushlen = 0;
+ connection_edge_reached_eof(edgeconn);
+
+ /* Data cell not in the half-opened list */
+ PACK_CELL(4000, RELAY_COMMAND_DATA, "Data1234");
+ if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
+ pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
+ else
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
+ circ->cpath);
+ ASSERT_UNCOUNTED_BW();
+
+ /* Sendme cell not in the half-opened list */
+ PACK_CELL(4000, RELAY_COMMAND_SENDME, "Data1234");
+ if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
+ pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
+ else
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
+ circ->cpath);
+ ASSERT_UNCOUNTED_BW();
+
+ /* Connected cell not in the half-opened list */
+ PACK_CELL(4000, RELAY_COMMAND_CONNECTED, "Data1234");
+ if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
+ pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
+ else
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
+ circ->cpath);
+ ASSERT_UNCOUNTED_BW();
+
+ /* Resolved cell not in the half-opened list */
+ PACK_CELL(4000, RELAY_COMMAND_RESOLVED, "Data1234");
+ if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
+ pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
+ else
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
+ circ->cpath);
+ ASSERT_UNCOUNTED_BW();
+
+ /* Connected cell: not counted -- we were open */
+ edgeconn = ENTRY_TO_EDGE_CONN(entryconn2);
+ PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_CONNECTED, "Data1234");
+ if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
+ pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
+ else
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
+ circ->cpath);
+ ASSERT_UNCOUNTED_BW();
+
+ /* DATA cells up to limit */
+ while (data_cells > 0) {
+ ENTRY_TO_CONN(entryconn2)->marked_for_close = 0;
+ ENTRY_TO_CONN(entryconn2)->outbuf_flushlen = 0;
+ PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234");
+ if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
+ pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
+ else
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
+ circ->cpath);
+ ASSERT_COUNTED_BW();
+ data_cells--;
+ }
+ ENTRY_TO_CONN(entryconn2)->marked_for_close = 0;
+ ENTRY_TO_CONN(entryconn2)->outbuf_flushlen = 0;
+ PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234");
+ if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
+ pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
+ else
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
+ circ->cpath);
+ ASSERT_UNCOUNTED_BW();
+
+ /* SENDME cells up to limit */
+ while (sendme_cells > 0) {
+ ENTRY_TO_CONN(entryconn2)->marked_for_close = 0;
+ ENTRY_TO_CONN(entryconn2)->outbuf_flushlen = 0;
+ PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234");
+ if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
+ pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
+ else
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
+ circ->cpath);
+ ASSERT_COUNTED_BW();
+ sendme_cells--;
+ }
+ ENTRY_TO_CONN(entryconn2)->marked_for_close = 0;
+ ENTRY_TO_CONN(entryconn2)->outbuf_flushlen = 0;
+ PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234");
+ if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
+ pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
+ else
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
+ circ->cpath);
+ ASSERT_UNCOUNTED_BW();
+
+ /* Only one END cell */
+ ENTRY_TO_CONN(entryconn2)->marked_for_close = 0;
+ ENTRY_TO_CONN(entryconn2)->outbuf_flushlen = 0;
+ PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234");
+ if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
+ pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
+ else
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
+ circ->cpath);
+ ASSERT_COUNTED_BW();
+
+ ENTRY_TO_CONN(entryconn2)->marked_for_close = 0;
+ ENTRY_TO_CONN(entryconn2)->outbuf_flushlen = 0;
+ PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234");
+ if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
+ pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
+ else
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
+ circ->cpath);
+ ASSERT_UNCOUNTED_BW();
+
+ edgeconn = ENTRY_TO_EDGE_CONN(entryconn3);
+ edgeconn->base_.state = AP_CONN_STATE_OPEN;
+ ENTRY_TO_CONN(entryconn3)->marked_for_close = 0;
+ ENTRY_TO_CONN(entryconn3)->outbuf_flushlen = 0;
+ /* sendme cell on open entryconn with full window */
+ PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234");
+ int ret =
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
+ circ->cpath);
+ tt_int_op(ret, OP_EQ, -END_CIRC_REASON_TORPROTOCOL);
+ ASSERT_UNCOUNTED_BW();
+
+ /* connected cell on a after EOF */
+ ENTRY_TO_CONN(entryconn3)->marked_for_close = 0;
+ ENTRY_TO_CONN(entryconn3)->outbuf_flushlen = 0;
+ edgeconn->base_.state = AP_CONN_STATE_CONNECT_WAIT;
+ connection_edge_reached_eof(edgeconn);
+ PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_CONNECTED, "Data1234");
+ if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
+ pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
+ else
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
+ circ->cpath);
+ ASSERT_COUNTED_BW();
+
+ ENTRY_TO_CONN(entryconn3)->marked_for_close = 0;
+ ENTRY_TO_CONN(entryconn3)->outbuf_flushlen = 0;
+ PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_CONNECTED, "Data1234");
+ if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
+ pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
+ else
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
+ circ->cpath);
+ ASSERT_UNCOUNTED_BW();
+
+ /* DATA and SENDME after END cell */
+ ENTRY_TO_CONN(entryconn3)->marked_for_close = 0;
+ ENTRY_TO_CONN(entryconn3)->outbuf_flushlen = 0;
+ PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234");
+ if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
+ pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
+ else
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
+ circ->cpath);
+ ASSERT_COUNTED_BW();
+
+ ENTRY_TO_CONN(entryconn3)->marked_for_close = 0;
+ ENTRY_TO_CONN(entryconn3)->outbuf_flushlen = 0;
+ PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234");
+ ret =
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
+ circ->cpath);
+ tt_int_op(ret, OP_NE, -END_CIRC_REASON_TORPROTOCOL);
+ ASSERT_UNCOUNTED_BW();
+
+ ENTRY_TO_CONN(entryconn3)->marked_for_close = 0;
+ ENTRY_TO_CONN(entryconn3)->outbuf_flushlen = 0;
+ PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234");
+ if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
+ pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
+ else
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
+ circ->cpath);
+ ASSERT_UNCOUNTED_BW();
+
+ /* Resolved: 1 counted, more not */
+ edgeconn = ENTRY_TO_EDGE_CONN(entryconn4);
+ entryconn4->socks_request->command = SOCKS_COMMAND_RESOLVE;
+ edgeconn->base_.state = AP_CONN_STATE_RESOLVE_WAIT;
+ edgeconn->on_circuit = TO_CIRCUIT(circ);
+ ENTRY_TO_CONN(entryconn4)->marked_for_close = 0;
+ ENTRY_TO_CONN(entryconn4)->outbuf_flushlen = 0;
+ connection_edge_reached_eof(edgeconn);
+
+ ENTRY_TO_CONN(entryconn4)->marked_for_close = 0;
+ ENTRY_TO_CONN(entryconn4)->outbuf_flushlen = 0;
+ PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_RESOLVED,
+ "\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00");
+ if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
+ pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
+ else
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
+ circ->cpath);
+ ASSERT_COUNTED_BW();
+
+ ENTRY_TO_CONN(entryconn4)->marked_for_close = 0;
+ ENTRY_TO_CONN(entryconn4)->outbuf_flushlen = 0;
+ PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_RESOLVED,
+ "\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00");
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
+ circ->cpath);
+ ASSERT_UNCOUNTED_BW();
+
+ /* Data not counted after resolved */
+ ENTRY_TO_CONN(entryconn4)->marked_for_close = 0;
+ ENTRY_TO_CONN(entryconn4)->outbuf_flushlen = 0;
+ PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234");
+ if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
+ pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
+ else
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
+ circ->cpath);
+ ASSERT_UNCOUNTED_BW();
+
+ /* End not counted after resolved */
+ ENTRY_TO_CONN(entryconn4)->marked_for_close = 0;
+ ENTRY_TO_CONN(entryconn4)->outbuf_flushlen = 0;
+ PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234");
+ if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
+ pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
+ else
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
+ circ->cpath);
+ ASSERT_UNCOUNTED_BW();
+
+ connection_free_minimal(ENTRY_TO_CONN(entryconn2));
+ connection_free_minimal(ENTRY_TO_CONN(entryconn3));
+ connection_free_minimal(ENTRY_TO_CONN(entryconn4));
+ return 1;
+ done:
+ connection_free_minimal(ENTRY_TO_CONN(entryconn2));
+ connection_free_minimal(ENTRY_TO_CONN(entryconn3));
+ connection_free_minimal(ENTRY_TO_CONN(entryconn4));
+ return 0;
+}
+
+static int
+halfstream_insert(origin_circuit_t *circ, edge_connection_t *edgeconn,
+ streamid_t *streams, int num, int random)
+{
+ int inserted = 0;
+
+ /* Insert num random elements */
+ while (inserted < num) {
+ streamid_t id;
+
+ if (random)
+ id = (streamid_t)crypto_rand_int(65535)+1;
+ else
+ id = get_unique_stream_id_by_circ(circ);
+
+ edgeconn->stream_id = id;
+
+ /* Ensure it isn't there */
+ if (connection_half_edge_find_stream_id(circ->half_streams, id)) {
+ continue;
+ }
+
+ connection_half_edge_add(edgeconn, circ);
+ if (streams)
+ streams[inserted] = id;
+ inserted++;
+ }
+
+ return inserted;
+}
+
+static void
+subtest_halfstream_insertremove(int num)
+{
+ origin_circuit_t *circ =
+ helper_create_origin_circuit(CIRCUIT_PURPOSE_C_GENERAL, 0);
+ edge_connection_t *edgeconn;
+ entry_connection_t *entryconn;
+ streamid_t *streams = tor_malloc_zero(num*sizeof(streamid_t));
+ int i = 0;
+
+ circ->cpath->state = CPATH_STATE_AWAITING_KEYS;
+ circ->cpath->deliver_window = CIRCWINDOW_START;
+
+ entryconn = fake_entry_conn(circ, 23);
+ edgeconn = ENTRY_TO_EDGE_CONN(entryconn);
+
+ /* Explicity test all operations on an absent stream list */
+ tt_int_op(connection_half_edge_is_valid_data(circ->half_streams,
+ 23), OP_EQ, 0);
+ tt_int_op(connection_half_edge_is_valid_connected(circ->half_streams,
+ 23), OP_EQ, 0);
+ tt_int_op(connection_half_edge_is_valid_sendme(circ->half_streams,
+ 23), OP_EQ, 0);
+ tt_int_op(connection_half_edge_is_valid_resolved(circ->half_streams,
+ 23), OP_EQ, 0);
+ tt_int_op(connection_half_edge_is_valid_end(circ->half_streams,
+ 23), OP_EQ, 0);
+
+ /* Insert a duplicate element; verify that other elements absent;
+ * ensure removing it once works */
+ edgeconn->stream_id = 23;
+ connection_half_edge_add(edgeconn, circ);
+ connection_half_edge_add(edgeconn, circ);
+ connection_half_edge_add(edgeconn, circ);
+
+ /* Verify that other elements absent */
+ tt_int_op(connection_half_edge_is_valid_data(circ->half_streams,
+ 22), OP_EQ, 0);
+ tt_int_op(connection_half_edge_is_valid_connected(circ->half_streams,
+ 22), OP_EQ, 0);
+ tt_int_op(connection_half_edge_is_valid_sendme(circ->half_streams,
+ 22), OP_EQ, 0);
+ tt_int_op(connection_half_edge_is_valid_resolved(circ->half_streams,
+ 22), OP_EQ, 0);
+ tt_int_op(connection_half_edge_is_valid_end(circ->half_streams,
+ 22), OP_EQ, 0);
+
+ tt_int_op(connection_half_edge_is_valid_data(circ->half_streams,
+ 24), OP_EQ, 0);
+ tt_int_op(connection_half_edge_is_valid_connected(circ->half_streams,
+ 24), OP_EQ, 0);
+ tt_int_op(connection_half_edge_is_valid_sendme(circ->half_streams,
+ 24), OP_EQ, 0);
+ tt_int_op(connection_half_edge_is_valid_resolved(circ->half_streams,
+ 24), OP_EQ, 0);
+ tt_int_op(connection_half_edge_is_valid_end(circ->half_streams,
+ 24), OP_EQ, 0);
+
+ /* Verify we only remove it once */
+ tt_int_op(connection_half_edge_is_valid_end(circ->half_streams,
+ 23), OP_EQ, 1);
+ tt_int_op(connection_half_edge_is_valid_end(circ->half_streams,
+ 23), OP_EQ, 0);
+
+ halfstream_insert(circ, edgeconn, streams, num, 1);
+
+ /* Remove half of them */
+ for (i = 0; i < num/2; i++) {
+ tt_int_op(connection_half_edge_is_valid_end(circ->half_streams,
+ streams[i]),
+ OP_EQ, 1);
+ }
+
+ /* Verify first half of list is gone */
+ for (i = 0; i < num/2; i++) {
+ tt_ptr_op(connection_half_edge_find_stream_id(circ->half_streams,
+ streams[i]),
+ OP_EQ, NULL);
+ }
+
+ /* Verify second half of list is present */
+ for (; i < num; i++) {
+ tt_ptr_op(connection_half_edge_find_stream_id(circ->half_streams,
+ streams[i]),
+ OP_NE, NULL);
+ }
+
+ /* Remove other half. Verify list is empty. */
+ for (i = num/2; i < num; i++) {
+ tt_int_op(connection_half_edge_is_valid_end(circ->half_streams,
+ streams[i]),
+ OP_EQ, 1);
+ }
+ tt_int_op(smartlist_len(circ->half_streams), OP_EQ, 0);
+
+ /* Explicity test all operations on an empty stream list */
+ tt_int_op(connection_half_edge_is_valid_data(circ->half_streams,
+ 23), OP_EQ, 0);
+ tt_int_op(connection_half_edge_is_valid_connected(circ->half_streams,
+ 23), OP_EQ, 0);
+ tt_int_op(connection_half_edge_is_valid_sendme(circ->half_streams,
+ 23), OP_EQ, 0);
+ tt_int_op(connection_half_edge_is_valid_resolved(circ->half_streams,
+ 23), OP_EQ, 0);
+ tt_int_op(connection_half_edge_is_valid_end(circ->half_streams,
+ 23), OP_EQ, 0);
+
+ /* For valgrind, leave some around then free the circ */
+ halfstream_insert(circ, edgeconn, NULL, 10, 0);
+
+ done:
+ tor_free(streams);
+ circuit_free_(TO_CIRCUIT(circ));
+ connection_free_minimal(ENTRY_TO_CONN(entryconn));
+}
+
+static void
+test_halfstream_insertremove(void *arg)
+{
+ (void)arg;
+
+ /* Suppress the WARN message we generate in this test */
+ setup_full_capture_of_logs(LOG_WARN);
+
+ /* Test insertion and removal with a few different sizes */
+ subtest_halfstream_insertremove(10);
+ subtest_halfstream_insertremove(100);
+ subtest_halfstream_insertremove(1000);
+}
+
+static void
+test_halfstream_wrap(void *arg)
+{
+ origin_circuit_t *circ =
+ helper_create_origin_circuit(CIRCUIT_PURPOSE_C_GENERAL, 0);
+ edge_connection_t *edgeconn;
+ entry_connection_t *entryconn;
+
+ circ->cpath->state = CPATH_STATE_AWAITING_KEYS;
+ circ->cpath->deliver_window = CIRCWINDOW_START;
+
+ entryconn = fake_entry_conn(circ, 23);
+ edgeconn = ENTRY_TO_EDGE_CONN(entryconn);
+
+ (void)arg;
+
+ /* Suppress the WARN message we generate in this test */
+ setup_full_capture_of_logs(LOG_WARN);
+ MOCK(connection_mark_for_close_internal_, mock_mark_for_close);
+
+ /* Verify that get_unique_stream_id_by_circ() can wrap uint16_t */
+ circ->next_stream_id = 65530;
+ halfstream_insert(circ, edgeconn, NULL, 7, 0);
+ tt_int_op(circ->next_stream_id, OP_EQ, 2);
+ tt_int_op(smartlist_len(circ->half_streams), OP_EQ, 7);
+
+ /* Insert full-1 */
+ halfstream_insert(circ, edgeconn, NULL,
+ 65534-smartlist_len(circ->half_streams), 0);
+ tt_int_op(smartlist_len(circ->half_streams), OP_EQ, 65534);
+
+ /* Verify that we can get_unique_stream_id_by_circ() successfully */
+ edgeconn->stream_id = get_unique_stream_id_by_circ(circ);
+ tt_int_op(edgeconn->stream_id, OP_NE, 0); /* 0 is failure */
+
+ /* Insert an opened stream on the circ with that id */
+ ENTRY_TO_CONN(entryconn)->marked_for_close = 0;
+ ENTRY_TO_CONN(entryconn)->outbuf_flushlen = 0;
+ edgeconn->base_.state = AP_CONN_STATE_CONNECT_WAIT;
+ circ->p_streams = edgeconn;
+
+ /* Verify that get_unique_stream_id_by_circ() fails */
+ tt_int_op(get_unique_stream_id_by_circ(circ), OP_EQ, 0); /* 0 is failure */
+
+ /* eof the one opened stream. Verify it is now in half-closed */
+ tt_int_op(smartlist_len(circ->half_streams), OP_EQ, 65534);
+ connection_edge_reached_eof(edgeconn);
+ tt_int_op(smartlist_len(circ->half_streams), OP_EQ, 65535);
+
+ /* Verify get_unique_stream_id_by_circ() fails due to full half-closed */
+ circ->p_streams = NULL;
+ tt_int_op(get_unique_stream_id_by_circ(circ), OP_EQ, 0); /* 0 is failure */
+
+ done:
+ circuit_free_(TO_CIRCUIT(circ));
+ connection_free_minimal(ENTRY_TO_CONN(entryconn));
+ UNMOCK(connection_mark_for_close_internal_);
+}
+
+static void
+test_circbw_relay(void *arg)
+{
+ cell_t cell;
+ relay_header_t rh;
+ tor_addr_t addr;
+ edge_connection_t *edgeconn;
+ entry_connection_t *entryconn1=NULL;
+ origin_circuit_t *circ;
+ int delivered = 0;
+ int overhead = 0;
+
+ (void)arg;
+
+ MOCK(connection_mark_unattached_ap_, mock_connection_mark_unattached_ap_);
+ MOCK(connection_start_reading, mock_start_reading);
+ MOCK(connection_mark_for_close_internal_, mock_mark_for_close);
+ MOCK(relay_send_command_from_edge_, mock_send_command);
+ MOCK(circuit_mark_for_close_, mock_mark_circ_for_close);
+
+ circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_C_GENERAL, 0);
+ circ->cpath->state = CPATH_STATE_AWAITING_KEYS;
+ circ->cpath->deliver_window = CIRCWINDOW_START;
+
+ entryconn1 = fake_entry_conn(circ, 1);
+ edgeconn = ENTRY_TO_EDGE_CONN(entryconn1);
+
+ /* Stream id 0: Not counted */
+ PACK_CELL(0, RELAY_COMMAND_END, "Data1234");
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
+ circ->cpath);
+ ASSERT_UNCOUNTED_BW();
+
+ /* Stream id 1: Counted */
+ PACK_CELL(1, RELAY_COMMAND_END, "Data1234");
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
+ circ->cpath);
+ ASSERT_COUNTED_BW();
+
+ /* Properly formatted connect cell: counted */
+ PACK_CELL(1, RELAY_COMMAND_CONNECTED, "Data1234");
+ tor_addr_parse(&addr, "30.40.50.60");
+ rh.length = connected_cell_format_payload(cell.payload+RELAY_HEADER_SIZE,
+ &addr, 1024);
+ relay_header_pack((uint8_t*)&cell.payload, &rh); \
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
+ circ->cpath);
+ ASSERT_COUNTED_BW();
+
+ /* Properly formatted resolved cell in correct state: counted */
+ edgeconn->base_.state = AP_CONN_STATE_RESOLVE_WAIT;
+ entryconn1->socks_request->command = SOCKS_COMMAND_RESOLVE;
+ edgeconn->on_circuit = TO_CIRCUIT(circ);
+ PACK_CELL(1, RELAY_COMMAND_RESOLVED,
+ "\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00");
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
+ circ->cpath);
+ ASSERT_COUNTED_BW();
+
+ edgeconn->base_.state = AP_CONN_STATE_OPEN;
+ entryconn1->socks_request->has_finished = 1;
+
+ /* Connected cell after open: not counted */
+ PACK_CELL(1, RELAY_COMMAND_CONNECTED, "Data1234");
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
+ circ->cpath);
+ ASSERT_UNCOUNTED_BW();
+
+ /* Resolved cell after open: not counted */
+ PACK_CELL(1, RELAY_COMMAND_RESOLVED, "Data1234");
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
+ circ->cpath);
+ ASSERT_UNCOUNTED_BW();
+
+ /* Drop cell: not counted */
+ PACK_CELL(1, RELAY_COMMAND_DROP, "Data1234");
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
+ circ->cpath);
+ ASSERT_UNCOUNTED_BW();
+
+ /* Data cell on stream 0: not counted */
+ PACK_CELL(0, RELAY_COMMAND_DATA, "Data1234");
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
+ circ->cpath);
+ ASSERT_UNCOUNTED_BW();
+
+ /* Data cell on open connection: counted */
+ ENTRY_TO_CONN(entryconn1)->marked_for_close = 0;
+ PACK_CELL(1, RELAY_COMMAND_DATA, "Data1234");
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
+ circ->cpath);
+ ASSERT_COUNTED_BW();
+
+ /* Empty Data cell on open connection: not counted */
+ ENTRY_TO_CONN(entryconn1)->marked_for_close = 0;
+ PACK_CELL(1, RELAY_COMMAND_DATA, "");
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
+ circ->cpath);
+ ASSERT_UNCOUNTED_BW();
+
+ /* Sendme on valid stream: counted */
+ edgeconn->package_window -= STREAMWINDOW_INCREMENT;
+ ENTRY_TO_CONN(entryconn1)->outbuf_flushlen = 0;
+ PACK_CELL(1, RELAY_COMMAND_SENDME, "Data1234");
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
+ circ->cpath);
+ ASSERT_COUNTED_BW();
+
+ /* Sendme on valid stream with full window: not counted */
+ ENTRY_TO_CONN(entryconn1)->outbuf_flushlen = 0;
+ PACK_CELL(1, RELAY_COMMAND_SENDME, "Data1234");
+ edgeconn->package_window = STREAMWINDOW_START;
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
+ circ->cpath);
+ ASSERT_UNCOUNTED_BW();
+
+ /* Sendme on unknown stream: not counted */
+ ENTRY_TO_CONN(entryconn1)->outbuf_flushlen = 0;
+ PACK_CELL(1, RELAY_COMMAND_SENDME, "Data1234");
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
+ circ->cpath);
+ ASSERT_UNCOUNTED_BW();
+
+ /* Sendme on circuit with full window: not counted */
+ PACK_CELL(0, RELAY_COMMAND_SENDME, "Data1234");
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
+ circ->cpath);
+ ASSERT_UNCOUNTED_BW();
+
+ /* Sendme on circuit with non-full window: counted */
+ PACK_CELL(0, RELAY_COMMAND_SENDME, "Data1234");
+ circ->cpath->package_window = 900;
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
+ circ->cpath);
+ ASSERT_COUNTED_BW();
+
+ /* Invalid extended cell: not counted */
+ PACK_CELL(1, RELAY_COMMAND_EXTENDED2, "Data1234");
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
+ circ->cpath);
+ ASSERT_UNCOUNTED_BW();
+
+ /* Invalid extended cell: not counted */
+ PACK_CELL(1, RELAY_COMMAND_EXTENDED, "Data1234");
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
+ circ->cpath);
+ ASSERT_UNCOUNTED_BW();
+
+ /* Invalid HS cell: not counted */
+ PACK_CELL(1, RELAY_COMMAND_ESTABLISH_INTRO, "Data1234");
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
+ circ->cpath);
+ ASSERT_UNCOUNTED_BW();
+
+ /* "Valid" HS cell in expected state: counted */
+ TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_C_ESTABLISH_REND;
+ PACK_CELL(1, RELAY_COMMAND_RENDEZVOUS_ESTABLISHED, "Data1234");
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
+ circ->cpath);
+ ASSERT_COUNTED_BW();
+
+ /* End cell on non-closed connection: counted */
+ PACK_CELL(1, RELAY_COMMAND_END, "Data1234");
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
+ circ->cpath);
+ ASSERT_COUNTED_BW();
+
+ /* End cell on connection that already got one: not counted */
+ PACK_CELL(1, RELAY_COMMAND_END, "Data1234");
+ connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
+ circ->cpath);
+ ASSERT_UNCOUNTED_BW();
+
+ /* Simulate closed stream on entryconn, then test: */
+ if (!subtest_circbw_halfclosed(circ, 2))
+ goto done;
+
+ circ->base_.purpose = CIRCUIT_PURPOSE_PATH_BIAS_TESTING;
+ if (!subtest_circbw_halfclosed(circ, 6))
+ goto done;
+
+ /* Path bias: truncated */
+ tt_int_op(circ->base_.marked_for_close, OP_EQ, 0);
+ PACK_CELL(0, RELAY_COMMAND_TRUNCATED, "Data1234");
+ pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
+ tt_int_op(circ->base_.marked_for_close, OP_EQ, 1);
+
+ done:
+ UNMOCK(connection_start_reading);
+ UNMOCK(connection_mark_unattached_ap_);
+ UNMOCK(connection_mark_for_close_internal_);
+ UNMOCK(relay_send_command_from_edge_);
+ UNMOCK(circuit_mark_for_close_);
+ circuit_free_(TO_CIRCUIT(circ));
+ connection_free_minimal(ENTRY_TO_CONN(entryconn1));
+}
+
/* Tests for connection_edge_process_resolved_cell().
The point of ..process_resolved_cell() is to handle an incoming cell
@@ -244,6 +1058,8 @@ test_relaycell_resolved(void *arg)
struct testcase_t relaycell_tests[] = {
{ "resolved", test_relaycell_resolved, TT_FORK, NULL, NULL },
+ { "circbw", test_circbw_relay, TT_FORK, NULL, NULL },
+ { "halfstream", test_halfstream_insertremove, TT_FORK, NULL, NULL },
+ { "streamwrap", test_halfstream_wrap, TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
-
diff --git a/src/test/test_relaycrypt.c b/src/test/test_relaycrypt.c
new file mode 100644
index 0000000000..60bd479719
--- /dev/null
+++ b/src/test/test_relaycrypt.c
@@ -0,0 +1,185 @@
+/* Copyright 2001-2004 Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "or.h"
+#include "circuitbuild.h"
+#define CIRCUITLIST_PRIVATE
+#include "circuitlist.h"
+#include "crypto_rand.h"
+#include "relay.h"
+#include "relay_crypto.h"
+#include "test.h"
+
+static const char KEY_MATERIAL[3][CPATH_KEY_MATERIAL_LEN] = {
+ " 'My public key is in this signed x509 object', said Tom assertively.",
+ "'Let's chart the pedal phlanges in the tomb', said Tom cryptographically",
+ " 'Segmentation fault bugs don't _just happen_', said Tom seethingly.",
+};
+
+typedef struct testing_circuitset_t {
+ or_circuit_t *or_circ[3];
+ origin_circuit_t *origin_circ;
+} testing_circuitset_t;
+
+static int testing_circuitset_teardown(const struct testcase_t *testcase,
+ void *ptr);
+
+static void *
+testing_circuitset_setup(const struct testcase_t *testcase)
+{
+ testing_circuitset_t *cs = tor_malloc_zero(sizeof(testing_circuitset_t));
+ int i;
+
+ for (i=0; i<3; ++i) {
+ cs->or_circ[i] = or_circuit_new(0, NULL);
+ tt_int_op(0, OP_EQ,
+ relay_crypto_init(&cs->or_circ[i]->crypto,
+ KEY_MATERIAL[i], sizeof(KEY_MATERIAL[i]),
+ 0, 0));
+ }
+
+ cs->origin_circ = origin_circuit_new();
+ cs->origin_circ->base_.purpose = CIRCUIT_PURPOSE_C_GENERAL;
+ for (i=0; i<3; ++i) {
+ crypt_path_t *hop = tor_malloc_zero(sizeof(*hop));
+ relay_crypto_init(&hop->crypto, KEY_MATERIAL[i], sizeof(KEY_MATERIAL[i]),
+ 0, 0);
+ hop->state = CPATH_STATE_OPEN;
+ onion_append_to_cpath(&cs->origin_circ->cpath, hop);
+ tt_ptr_op(hop, OP_EQ, cs->origin_circ->cpath->prev);
+ }
+
+ return cs;
+ done:
+ testing_circuitset_teardown(testcase, cs);
+ return NULL;
+}
+
+static int
+testing_circuitset_teardown(const struct testcase_t *testcase, void *ptr)
+{
+ (void)testcase;
+ testing_circuitset_t *cs = ptr;
+ int i;
+ for (i=0; i<3; ++i) {
+ circuit_free_(TO_CIRCUIT(cs->or_circ[i]));
+ }
+ circuit_free_(TO_CIRCUIT(cs->origin_circ));
+ tor_free(cs);
+ return 1;
+}
+
+static const struct testcase_setup_t relaycrypt_setup = {
+ testing_circuitset_setup, testing_circuitset_teardown
+};
+
+/* Test encrypting a cell to the final hop on a circuit, decrypting it
+ * at each hop, and recognizing it at the other end. Then do it again
+ * and again as the state evolves. */
+static void
+test_relaycrypt_outbound(void *arg)
+{
+ testing_circuitset_t *cs = arg;
+ tt_assert(cs);
+
+ relay_header_t rh;
+ cell_t orig;
+ cell_t encrypted;
+ int i, j;
+
+ for (i = 0; i < 50; ++i) {
+ crypto_rand((char *)&orig, sizeof(orig));
+
+ relay_header_unpack(&rh, orig.payload);
+ rh.recognized = 0;
+ memset(rh.integrity, 0, sizeof(rh.integrity));
+ relay_header_pack(orig.payload, &rh);
+
+ memcpy(&encrypted, &orig, sizeof(orig));
+
+ /* Encrypt the cell to the last hop */
+ relay_encrypt_cell_outbound(&encrypted, cs->origin_circ,
+ cs->origin_circ->cpath->prev);
+
+ for (j = 0; j < 3; ++j) {
+ crypt_path_t *layer_hint = NULL;
+ char recognized = 0;
+ int r = relay_decrypt_cell(TO_CIRCUIT(cs->or_circ[j]),
+ &encrypted,
+ CELL_DIRECTION_OUT,
+ &layer_hint, &recognized);
+ tt_int_op(r, OP_EQ, 0);
+ tt_ptr_op(layer_hint, OP_EQ, NULL);
+ tt_int_op(recognized != 0, OP_EQ, j == 2);
+ }
+
+ tt_mem_op(orig.payload, OP_EQ, encrypted.payload, CELL_PAYLOAD_SIZE);
+ }
+
+ done:
+ ;
+}
+
+/* As above, but simulate inbound cells from the last hop. */
+static void
+test_relaycrypt_inbound(void *arg)
+{
+ testing_circuitset_t *cs = arg;
+ tt_assert(cs);
+
+ relay_header_t rh;
+ cell_t orig;
+ cell_t encrypted;
+ int i, j;
+
+ for (i = 0; i < 50; ++i) {
+ crypto_rand((char *)&orig, sizeof(orig));
+
+ relay_header_unpack(&rh, orig.payload);
+ rh.recognized = 0;
+ memset(rh.integrity, 0, sizeof(rh.integrity));
+ relay_header_pack(orig.payload, &rh);
+
+ memcpy(&encrypted, &orig, sizeof(orig));
+
+ /* Encrypt the cell to the last hop */
+ relay_encrypt_cell_inbound(&encrypted, cs->or_circ[2]);
+
+ crypt_path_t *layer_hint = NULL;
+ char recognized = 0;
+ int r;
+ for (j = 1; j >= 0; --j) {
+ r = relay_decrypt_cell(TO_CIRCUIT(cs->or_circ[j]),
+ &encrypted,
+ CELL_DIRECTION_IN,
+ &layer_hint, &recognized);
+ tt_int_op(r, OP_EQ, 0);
+ tt_ptr_op(layer_hint, OP_EQ, NULL);
+ tt_int_op(recognized, OP_EQ, 0);
+ }
+
+ relay_decrypt_cell(TO_CIRCUIT(cs->origin_circ),
+ &encrypted,
+ CELL_DIRECTION_IN,
+ &layer_hint, &recognized);
+ tt_int_op(r, OP_EQ, 0);
+ tt_int_op(recognized, OP_EQ, 1);
+ tt_ptr_op(layer_hint, OP_EQ, cs->origin_circ->cpath->prev);
+
+ tt_mem_op(orig.payload, OP_EQ, encrypted.payload, CELL_PAYLOAD_SIZE);
+ }
+ done:
+ ;
+}
+
+#define TEST(name) \
+ { # name, test_relaycrypt_ ## name, 0, &relaycrypt_setup, NULL }
+
+struct testcase_t relaycrypt_tests[] = {
+ TEST(outbound),
+ TEST(inbound),
+ END_OF_TESTCASES
+};
+
diff --git a/src/test/test_routerlist.c b/src/test/test_routerlist.c
index c19d66ef9d..701227c1c7 100644
--- a/src/test/test_routerlist.c
+++ b/src/test/test_routerlist.c
@@ -18,8 +18,9 @@
#include "connection.h"
#include "container.h"
#include "control.h"
+#include "crypto_rand.h"
#include "directory.h"
-#include "dirvote.h"
+#include "dirauth/dirvote.h"
#include "entrynodes.h"
#include "hibernate.h"
#include "microdesc.h"
@@ -30,13 +31,13 @@
#include "routerlist.h"
#include "routerset.h"
#include "routerparse.h"
-#include "shared_random.h"
+#include "dirauth/shared_random.h"
#include "statefile.h"
#include "test.h"
#include "test_dir_common.h"
#include "log_test_helpers.h"
-void construct_consensus(char **consensus_text_md);
+void construct_consensus(char **consensus_text_md, time_t now);
static authority_cert_t *mock_cert;
@@ -135,7 +136,7 @@ test_routerlist_launch_descriptor_downloads(void *arg)
}
void
-construct_consensus(char **consensus_text_md)
+construct_consensus(char **consensus_text_md, time_t now)
{
networkstatus_t *vote = NULL;
networkstatus_t *v1 = NULL, *v2 = NULL, *v3 = NULL;
@@ -143,7 +144,6 @@ construct_consensus(char **consensus_text_md)
authority_cert_t *cert1=NULL, *cert2=NULL, *cert3=NULL;
crypto_pk_t *sign_skey_1=NULL, *sign_skey_2=NULL, *sign_skey_3=NULL;
crypto_pk_t *sign_skey_leg=NULL;
- time_t now = time(NULL);
smartlist_t *votes = NULL;
int n_vrs;
@@ -258,7 +258,7 @@ test_router_pick_directory_server_impl(void *arg)
rs = router_pick_directory_server_impl(V3_DIRINFO, (const int) 0, NULL);
tt_ptr_op(rs, OP_EQ, NULL);
- construct_consensus(&consensus_text_md);
+ construct_consensus(&consensus_text_md, now);
tt_assert(consensus_text_md);
con_md = networkstatus_parse_vote_from_string(consensus_text_md, NULL,
NS_TYPE_CONSENSUS);
@@ -452,6 +452,7 @@ test_directory_guard_fetch_with_no_dirinfo(void *arg)
int retval;
char *consensus_text_md = NULL;
or_options_t *options = get_options_mutable();
+ time_t now = time(NULL);
(void) arg;
@@ -495,7 +496,7 @@ test_directory_guard_fetch_with_no_dirinfo(void *arg)
conn->requested_resource = tor_strdup("ns");
/* Construct a consensus */
- construct_consensus(&consensus_text_md);
+ construct_consensus(&consensus_text_md, now);
tt_assert(consensus_text_md);
/* Place the consensus in the dirconn */
@@ -506,7 +507,7 @@ test_directory_guard_fetch_with_no_dirinfo(void *arg)
args.body_len = strlen(consensus_text_md);
/* Update approx time so that the consensus is considered live */
- update_approx_time(time(NULL)+1010);
+ update_approx_time(now+1010);
setup_capture_of_logs(LOG_DEBUG);
@@ -598,11 +599,167 @@ test_routerlist_router_is_already_dir_fetching(void *arg)
#undef TEST_ADDR_STR
#undef TEST_DIR_PORT
+static long mock_apparent_skew = 0;
+
+/** Store apparent_skew and assert that the other arguments are as
+ * expected. */
+static void
+mock_clock_skew_warning(const connection_t *conn, long apparent_skew,
+ int trusted, log_domain_mask_t domain,
+ const char *received, const char *source)
+{
+ (void)conn;
+ mock_apparent_skew = apparent_skew;
+ tt_int_op(trusted, OP_EQ, 1);
+ tt_int_op(domain, OP_EQ, LD_GENERAL);
+ tt_str_op(received, OP_EQ, "microdesc flavor consensus");
+ tt_str_op(source, OP_EQ, "CONSENSUS");
+ done:
+ ;
+}
+
+/** Do common setup for test_timely_consensus() and
+ * test_early_consensus(). Call networkstatus_set_current_consensus()
+ * on a constructed consensus and with an appropriately-modified
+ * approx_time. Callers expect presence or absence of appropriate log
+ * messages and control events. */
+static int
+test_skew_common(void *arg, time_t now, unsigned long *offset)
+{
+ char *consensus = NULL;
+ int retval = 0;
+
+ *offset = strtoul(arg, NULL, 10);
+
+ /* Initialize the SRV subsystem */
+ MOCK(get_my_v3_authority_cert, get_my_v3_authority_cert_m);
+ mock_cert = authority_cert_parse_from_string(AUTHORITY_CERT_1, NULL);
+ sr_init(0);
+ UNMOCK(get_my_v3_authority_cert);
+
+ construct_consensus(&consensus, now);
+ tt_assert(consensus);
+
+ update_approx_time(now + *offset);
+
+ mock_apparent_skew = 0;
+ /* Caller will call UNMOCK() */
+ MOCK(clock_skew_warning, mock_clock_skew_warning);
+ /* Caller will call teardown_capture_of_logs() */
+ setup_capture_of_logs(LOG_WARN);
+ retval = networkstatus_set_current_consensus(consensus, "microdesc", 0,
+ NULL);
+
+ done:
+ tor_free(consensus);
+ return retval;
+}
+
+/** Test non-early consensus */
+static void
+test_timely_consensus(void *arg)
+{
+ time_t now = time(NULL);
+ unsigned long offset = 0;
+ int retval = 0;
+
+ retval = test_skew_common(arg, now, &offset);
+ (void)offset;
+ expect_no_log_msg_containing("behind the time published in the consensus");
+ tt_int_op(retval, OP_EQ, 0);
+ tt_int_op(mock_apparent_skew, OP_EQ, 0);
+ done:
+ teardown_capture_of_logs();
+ UNMOCK(clock_skew_warning);
+}
+
+/** Test early consensus */
+static void
+test_early_consensus(void *arg)
+{
+ time_t now = time(NULL);
+ unsigned long offset = 0;
+ int retval = 0;
+
+ retval = test_skew_common(arg, now, &offset);
+ /* Can't use expect_single_log_msg() because of unrecognized authorities */
+ expect_log_msg_containing("behind the time published in the consensus");
+ tt_int_op(retval, OP_EQ, 0);
+ /* This depends on construct_consensus() setting valid_after=now+1000 */
+ tt_int_op(mock_apparent_skew, OP_EQ, offset - 1000);
+ done:
+ teardown_capture_of_logs();
+ UNMOCK(clock_skew_warning);
+}
+
+/** Test warn_early_consensus(), expecting no warning */
+static void
+test_warn_early_consensus_no(const networkstatus_t *c, time_t now,
+ long offset)
+{
+ mock_apparent_skew = 0;
+ setup_capture_of_logs(LOG_WARN);
+ warn_early_consensus(c, "microdesc", now + offset);
+ expect_no_log_msg_containing("behind the time published in the consensus");
+ tt_int_op(mock_apparent_skew, OP_EQ, 0);
+ done:
+ teardown_capture_of_logs();
+}
+
+/** Test warn_early_consensus(), expecting a warning */
+static void
+test_warn_early_consensus_yes(const networkstatus_t *c, time_t now,
+ long offset)
+{
+ mock_apparent_skew = 0;
+ setup_capture_of_logs(LOG_WARN);
+ warn_early_consensus(c, "microdesc", now + offset);
+ /* Can't use expect_single_log_msg() because of unrecognized authorities */
+ expect_log_msg_containing("behind the time published in the consensus");
+ tt_int_op(mock_apparent_skew, OP_EQ, offset);
+ done:
+ teardown_capture_of_logs();
+}
+
+/**
+ * Test warn_early_consensus() directly, checking both the non-warning
+ * case (consensus is not early) and the warning case (consensus is
+ * early). Depends on EARLY_CONSENSUS_NOTICE_SKEW=60.
+ */
+static void
+test_warn_early_consensus(void *arg)
+{
+ networkstatus_t *c = NULL;
+ time_t now = time(NULL);
+
+ (void)arg;
+ c = tor_malloc_zero(sizeof *c);
+ c->valid_after = now;
+ c->dist_seconds = 300;
+ mock_apparent_skew = 0;
+ MOCK(clock_skew_warning, mock_clock_skew_warning);
+ test_warn_early_consensus_no(c, now, 60);
+ test_warn_early_consensus_no(c, now, 0);
+ test_warn_early_consensus_no(c, now, -60);
+ test_warn_early_consensus_no(c, now, -360);
+ test_warn_early_consensus_yes(c, now, -361);
+ test_warn_early_consensus_yes(c, now, -600);
+ UNMOCK(clock_skew_warning);
+ tor_free(c);
+}
+
#define NODE(name, flags) \
{ #name, test_routerlist_##name, (flags), NULL, NULL }
#define ROUTER(name,flags) \
{ #name, test_router_##name, (flags), NULL, NULL }
+#define TIMELY(name, arg) \
+ { name, test_timely_consensus, TT_FORK, &passthrough_setup, \
+ (char *)(arg) }
+#define EARLY(name, arg) \
+ { name, test_early_consensus, TT_FORK, &passthrough_setup, \
+ (char *)(arg) }
+
struct testcase_t routerlist_tests[] = {
NODE(initiate_descriptor_downloads, 0),
NODE(launch_descriptor_downloads, 0),
@@ -610,6 +767,13 @@ struct testcase_t routerlist_tests[] = {
ROUTER(pick_directory_server_impl, TT_FORK),
{ "directory_guard_fetch_with_no_dirinfo",
test_directory_guard_fetch_with_no_dirinfo, TT_FORK, NULL, NULL },
+ /* These depend on construct_consensus() setting
+ * valid_after=now+1000 and dist_seconds=250 */
+ TIMELY("timely_consensus1", "1010"),
+ TIMELY("timely_consensus2", "1000"),
+ TIMELY("timely_consensus3", "690"),
+ EARLY("early_consensus1", "689"),
+ { "warn_early_consensus", test_warn_early_consensus, 0, NULL, NULL },
END_OF_TESTCASES
};
diff --git a/src/test/test_scheduler.c b/src/test/test_scheduler.c
index ebba71266c..841fc69456 100644
--- a/src/test/test_scheduler.c
+++ b/src/test/test_scheduler.c
@@ -4,7 +4,6 @@
#include "orconfig.h"
#include <math.h>
-#include <event2/event.h>
#define SCHEDULER_KIST_PRIVATE
#define TOR_CHANNEL_INTERNAL_
@@ -101,62 +100,6 @@ mock_kist_networkstatus_get_param(
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_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, OP_EQ, NULL);
-
- done:
- return;
-}
-
-static void
-mock_event_init(void)
-{
- struct event_config *cfg = NULL;
-
- tt_ptr_op(mock_event_base, OP_EQ, NULL);
-
- /*
- * Really cut down from tor_libevent_initialize of
- * src/common/compat_libevent.c to kill config dependencies
- */
-
- if (!mock_event_base) {
- cfg = event_config_new();
-#if LIBEVENT_VERSION_NUMBER >= V(2,0,9)
- /* We can enable changelist support with epoll, since we don't give
- * Libevent any dup'd fds. This lets us avoid some syscalls. */
- event_config_set_flag(cfg, EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST);
-#endif
- mock_event_base = event_base_new_with_config(cfg);
- event_config_free(cfg);
- }
-
- tt_ptr_op(mock_event_base, OP_NE, NULL);
-
- done:
- return;
-}
-
-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)
@@ -417,9 +360,7 @@ perform_channel_state_tests(int KISTSchedRunInterval, int sched_type)
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);
+ /* Set up scheduler */
scheduler_init();
/*
* Install the compare channels mock so we can test
@@ -523,14 +464,12 @@ perform_channel_state_tests(int KISTSchedRunInterval, int sched_type)
channel_free_all();
scheduler_free_all();
- mock_event_free_all();
done:
tor_free(ch1);
tor_free(ch2);
UNMOCK(scheduler_compare_channels);
- UNMOCK(tor_libevent_get_base);
UNMOCK(get_options);
cleanup_scheduler_options();
@@ -635,10 +574,7 @@ test_scheduler_loop_vanilla(void *arg)
set_scheduler_options(SCHEDULER_VANILLA);
mocked_options.KISTSchedRunInterval = 0;
- /* Set up libevent and scheduler */
-
- mock_event_init();
- MOCK(tor_libevent_get_base, tor_libevent_get_base_mock);
+ /* Set up scheduler */
scheduler_init();
/*
* Install the compare channels mock so we can test
@@ -786,7 +722,6 @@ test_scheduler_loop_vanilla(void *arg)
channel_flush_some_cells_mock_free_all();
channel_free_all();
scheduler_free_all();
- mock_event_free_all();
done:
tor_free(ch1);
@@ -795,7 +730,6 @@ test_scheduler_loop_vanilla(void *arg)
UNMOCK(channel_flush_some_cells);
UNMOCK(scheduler_compare_channels);
- UNMOCK(tor_libevent_get_base);
UNMOCK(get_options);
}
@@ -917,8 +851,6 @@ test_scheduler_initfree(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);
MOCK(get_options, mock_get_options);
set_scheduler_options(SCHEDULER_KIST);
set_scheduler_options(SCHEDULER_KIST_LITE);
@@ -935,9 +867,6 @@ test_scheduler_initfree(void *arg)
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);
diff --git a/src/test/test_shared_random.c b/src/test/test_shared_random.c
index 2283976415..43ba0d9e53 100644
--- a/src/test/test_shared_random.c
+++ b/src/test/test_shared_random.c
@@ -9,15 +9,18 @@
#include "or.h"
#include "test.h"
#include "config.h"
-#include "dirvote.h"
-#include "shared_random.h"
-#include "shared_random_state.h"
+#include "crypto_rand.h"
+#include "dirauth/dirvote.h"
+#include "dirauth/shared_random.h"
+#include "dirauth/shared_random_state.h"
+#include "log_test_helpers.h"
+#include "networkstatus.h"
+#include "router.h"
#include "routerkeys.h"
#include "routerlist.h"
-#include "router.h"
#include "routerparse.h"
-#include "networkstatus.h"
-#include "log_test_helpers.h"
+#include "shared_random_client.h"
+#include "voting_schedule.h"
static authority_cert_t *mock_cert;
@@ -170,7 +173,7 @@ test_get_state_valid_until_time(void *arg)
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);
+ voting_schedule_recalculate_timing(get_options(), current_time);
valid_until_time = get_state_valid_until_time(current_time);
/* Compare it with the correct result */
@@ -182,7 +185,7 @@ 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, OP_EQ, 0);
- dirvote_recalculate_timing(get_options(), current_time);
+ voting_schedule_recalculate_timing(get_options(), current_time);
valid_until_time = get_state_valid_until_time(current_time);
format_iso_time(tbuf, valid_until_time);
@@ -193,7 +196,7 @@ 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, OP_EQ, 0);
- dirvote_recalculate_timing(get_options(), current_time);
+ voting_schedule_recalculate_timing(get_options(), current_time);
valid_until_time = get_state_valid_until_time(current_time);
format_iso_time(tbuf, valid_until_time);
@@ -204,7 +207,7 @@ 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, OP_EQ, 0);
- dirvote_recalculate_timing(get_options(), current_time);
+ voting_schedule_recalculate_timing(get_options(), current_time);
valid_until_time = get_state_valid_until_time(current_time);
format_iso_time(tbuf, valid_until_time);
@@ -242,7 +245,7 @@ test_get_start_time_of_current_run(void *arg)
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);
+ voting_schedule_recalculate_timing(get_options(), current_time);
run_start_time =
sr_state_get_start_time_of_current_protocol_run(current_time);
@@ -255,7 +258,7 @@ test_get_start_time_of_current_run(void *arg)
retval = parse_rfc1123_time("Mon, 20 Apr 2015 23:59:59 UTC",
&current_time);
tt_int_op(retval, OP_EQ, 0);
- dirvote_recalculate_timing(get_options(), current_time);
+ voting_schedule_recalculate_timing(get_options(), current_time);
run_start_time =
sr_state_get_start_time_of_current_protocol_run(current_time);
@@ -268,7 +271,7 @@ test_get_start_time_of_current_run(void *arg)
retval = parse_rfc1123_time("Mon, 20 Apr 2015 00:00:00 UTC",
&current_time);
tt_int_op(retval, OP_EQ, 0);
- dirvote_recalculate_timing(get_options(), current_time);
+ voting_schedule_recalculate_timing(get_options(), current_time);
run_start_time =
sr_state_get_start_time_of_current_protocol_run(current_time);
@@ -291,7 +294,7 @@ test_get_start_time_of_current_run(void *arg)
retval = parse_rfc1123_time("Mon, 20 Apr 2015 00:15:32 UTC",
&current_time);
tt_int_op(retval, OP_EQ, 0);
- dirvote_recalculate_timing(get_options(), current_time);
+ voting_schedule_recalculate_timing(get_options(), current_time);
run_start_time =
sr_state_get_start_time_of_current_protocol_run(current_time);
@@ -324,7 +327,7 @@ test_get_start_time_functions(void *arg)
tt_int_op(retval, OP_EQ, 0);
time_t now = mock_consensus.valid_after;
- dirvote_recalculate_timing(get_options(), now);
+ voting_schedule_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);
diff --git a/src/test/test_storagedir.c b/src/test/test_storagedir.c
index a27074c21f..26606f9b6e 100644
--- a/src/test/test_storagedir.c
+++ b/src/test/test_storagedir.c
@@ -2,6 +2,7 @@
/* See LICENSE for licensing information */
#include "or.h"
+#include "crypto_rand.h"
#include "storagedir.h"
#include "test.h"
diff --git a/src/test/test_tortls.c b/src/test/test_tortls.c
index a661eb5c5d..5b5e69b002 100644
--- a/src/test/test_tortls.c
+++ b/src/test/test_tortls.c
@@ -203,6 +203,17 @@ test_tortls_tor_tls_get_error(void *data)
}
static void
+library_init(void)
+{
+#ifdef OPENSSL_1_1_API
+ OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
+#else
+ SSL_library_init();
+ SSL_load_error_strings();
+#endif
+}
+
+static void
test_tortls_get_state_description(void *ignored)
{
(void)ignored;
@@ -210,9 +221,7 @@ test_tortls_get_state_description(void *ignored)
char *buf;
SSL_CTX *ctx;
- SSL_library_init();
- SSL_load_error_strings();
-
+ library_init();
ctx = SSL_CTX_new(SSLv23_method());
buf = tor_malloc_zero(1000);
@@ -274,8 +283,7 @@ test_tortls_get_by_ssl(void *ignored)
SSL_CTX *ctx;
SSL *ssl;
- SSL_library_init();
- SSL_load_error_strings();
+ library_init();
tor_tls_allocate_tor_tls_object_ex_data_index();
ctx = SSL_CTX_new(SSLv23_method());
@@ -322,8 +330,7 @@ test_tortls_log_one_error(void *ignored)
SSL_CTX *ctx;
SSL *ssl = NULL;
- SSL_library_init();
- SSL_load_error_strings();
+ library_init();
ctx = SSL_CTX_new(SSLv23_method());
tls = tor_malloc_zero(sizeof(tor_tls_t));
@@ -415,8 +422,7 @@ test_tortls_get_error(void *ignored)
int ret;
SSL_CTX *ctx;
- SSL_library_init();
- SSL_load_error_strings();
+ library_init();
ctx = SSL_CTX_new(SSLv23_method());
setup_capture_of_logs(LOG_INFO);
@@ -516,7 +522,7 @@ test_tortls_x509_cert_free(void *ignored)
tor_x509_cert_free(cert);
cert = tor_malloc_zero(sizeof(tor_x509_cert_t));
- cert->cert = tor_malloc_zero(sizeof(X509));
+ cert->cert = X509_new();
cert->encoded = tor_malloc_zero(1);
tor_x509_cert_free(cert);
}
@@ -547,6 +553,15 @@ test_tortls_x509_cert_get_id_digests(void *ignored)
}
#ifndef OPENSSL_OPAQUE
+/*
+ * Use only for the matching fake_x509_free() call
+ */
+static X509 *
+fake_x509_malloc(void)
+{
+ return tor_malloc_zero(sizeof(X509));
+}
+
static void
fake_x509_free(X509 *cert)
{
@@ -643,7 +658,7 @@ test_tortls_cert_get_key(void *ignored)
crypto_pk_t *res = NULL;
cert = tor_malloc_zero(sizeof(tor_x509_cert_t));
X509 *key = NULL;
- key = tor_malloc_zero(sizeof(X509));
+ key = fake_x509_malloc();
key->references = 1;
res = tor_tls_cert_get_key(cert);
@@ -793,8 +808,8 @@ test_tortls_classify_client_ciphers(void *ignored)
STACK_OF(SSL_CIPHER) *ciphers;
SSL_CIPHER *tmp_cipher;
- SSL_library_init();
- SSL_load_error_strings();
+ library_init();
+
tor_tls_allocate_tor_tls_object_ex_data_index();
tls = tor_malloc_zero(sizeof(tor_tls_t));
@@ -900,8 +915,7 @@ test_tortls_client_is_using_v2_ciphers(void *ignored)
SSL_SESSION *sess;
STACK_OF(SSL_CIPHER) *ciphers;
- SSL_library_init();
- SSL_load_error_strings();
+ library_init();
ctx = SSL_CTX_new(TLSv1_method());
ssl = SSL_new(ctx);
@@ -1545,8 +1559,8 @@ test_tortls_session_secret_cb(void *ignored)
STACK_OF(SSL_CIPHER) *ciphers = NULL;
SSL_CIPHER *one;
- SSL_library_init();
- SSL_load_error_strings();
+ library_init();
+
tor_tls_allocate_tor_tls_object_ex_data_index();
tls = tor_malloc_zero(sizeof(tor_tls_t));
@@ -1737,8 +1751,7 @@ test_tortls_find_cipher_by_id(void *ignored)
fixed_cipher2 = tor_malloc_zero(sizeof(SSL_CIPHER));
fixed_cipher2->id = 0xC00A;
- SSL_library_init();
- SSL_load_error_strings();
+ library_init();
ctx = SSL_CTX_new(m);
ssl = SSL_new(ctx);
@@ -1829,8 +1842,7 @@ test_tortls_server_info_callback(void *ignored)
SSL_CTX *ctx;
SSL *ssl;
- SSL_library_init();
- SSL_load_error_strings();
+ library_init();
ctx = SSL_CTX_new(TLSv1_method());
ssl = SSL_new(ctx);
@@ -2473,8 +2485,8 @@ test_tortls_context_new(void *ignored)
fixed_crypto_pk_generate_key_with_bits_result[1] = 0;
fixed_tor_tls_create_certificate_result_index = 0;
fixed_tor_tls_create_certificate_result[0] = NULL;
- fixed_tor_tls_create_certificate_result[1] = tor_malloc_zero(sizeof(X509));
- fixed_tor_tls_create_certificate_result[2] = tor_malloc_zero(sizeof(X509));
+ fixed_tor_tls_create_certificate_result[1] = X509_new();
+ fixed_tor_tls_create_certificate_result[2] = X509_new();
ret = tor_tls_context_new(NULL, 0, 0, 0);
tt_assert(!ret);
@@ -2484,9 +2496,9 @@ test_tortls_context_new(void *ignored)
fixed_crypto_pk_new_result[2] = NULL;
fixed_crypto_pk_generate_key_with_bits_result_index = 0;
fixed_tor_tls_create_certificate_result_index = 0;
- fixed_tor_tls_create_certificate_result[0] = tor_malloc_zero(sizeof(X509));
+ fixed_tor_tls_create_certificate_result[0] = X509_new();
fixed_tor_tls_create_certificate_result[1] = NULL;
- fixed_tor_tls_create_certificate_result[2] = tor_malloc_zero(sizeof(X509));
+ fixed_tor_tls_create_certificate_result[2] = X509_new();
ret = tor_tls_context_new(NULL, 0, 0, 0);
tt_assert(!ret);
@@ -2496,8 +2508,8 @@ test_tortls_context_new(void *ignored)
fixed_crypto_pk_new_result[2] = NULL;
fixed_crypto_pk_generate_key_with_bits_result_index = 0;
fixed_tor_tls_create_certificate_result_index = 0;
- fixed_tor_tls_create_certificate_result[0] = tor_malloc_zero(sizeof(X509));
- fixed_tor_tls_create_certificate_result[1] = tor_malloc_zero(sizeof(X509));
+ fixed_tor_tls_create_certificate_result[0] = X509_new();
+ fixed_tor_tls_create_certificate_result[1] = X509_new();
fixed_tor_tls_create_certificate_result[2] = NULL;
ret = tor_tls_context_new(NULL, 0, 0, 0);
tt_assert(!ret);
@@ -2509,9 +2521,9 @@ test_tortls_context_new(void *ignored)
fixed_crypto_pk_new_result[2] = NULL;
fixed_crypto_pk_generate_key_with_bits_result_index = 0;
fixed_tor_tls_create_certificate_result_index = 0;
- fixed_tor_tls_create_certificate_result[0] = tor_malloc_zero(sizeof(X509));
- fixed_tor_tls_create_certificate_result[1] = tor_malloc_zero(sizeof(X509));
- fixed_tor_tls_create_certificate_result[2] = tor_malloc_zero(sizeof(X509));
+ fixed_tor_tls_create_certificate_result[0] = X509_new();
+ fixed_tor_tls_create_certificate_result[1] = X509_new();
+ fixed_tor_tls_create_certificate_result[2] = X509_new();
fixed_tor_x509_cert_new_result_index = 0;
fixed_tor_x509_cert_new_result[0] = NULL;
fixed_tor_x509_cert_new_result[1] = NULL;
@@ -2525,9 +2537,9 @@ test_tortls_context_new(void *ignored)
fixed_crypto_pk_new_result[2] = NULL;
fixed_crypto_pk_generate_key_with_bits_result_index = 0;
fixed_tor_tls_create_certificate_result_index = 0;
- fixed_tor_tls_create_certificate_result[0] = tor_malloc_zero(sizeof(X509));
- fixed_tor_tls_create_certificate_result[1] = tor_malloc_zero(sizeof(X509));
- fixed_tor_tls_create_certificate_result[2] = tor_malloc_zero(sizeof(X509));
+ fixed_tor_tls_create_certificate_result[0] = X509_new();
+ fixed_tor_tls_create_certificate_result[1] = X509_new();
+ fixed_tor_tls_create_certificate_result[2] = X509_new();
fixed_tor_x509_cert_new_result_index = 0;
fixed_tor_x509_cert_new_result[0] = tor_malloc_zero(sizeof(tor_x509_cert_t));
fixed_tor_x509_cert_new_result[1] = NULL;
@@ -2541,9 +2553,9 @@ test_tortls_context_new(void *ignored)
fixed_crypto_pk_new_result[2] = NULL;
fixed_crypto_pk_generate_key_with_bits_result_index = 0;
fixed_tor_tls_create_certificate_result_index = 0;
- fixed_tor_tls_create_certificate_result[0] = tor_malloc_zero(sizeof(X509));
- fixed_tor_tls_create_certificate_result[1] = tor_malloc_zero(sizeof(X509));
- fixed_tor_tls_create_certificate_result[2] = tor_malloc_zero(sizeof(X509));
+ fixed_tor_tls_create_certificate_result[0] = X509_new();
+ fixed_tor_tls_create_certificate_result[1] = X509_new();
+ fixed_tor_tls_create_certificate_result[2] = X509_new();
fixed_tor_x509_cert_new_result_index = 0;
fixed_tor_x509_cert_new_result[0] = tor_malloc_zero(sizeof(tor_x509_cert_t));
fixed_tor_x509_cert_new_result[1] = tor_malloc_zero(sizeof(tor_x509_cert_t));
@@ -2557,9 +2569,9 @@ test_tortls_context_new(void *ignored)
fixed_crypto_pk_new_result[2] = NULL;
fixed_crypto_pk_generate_key_with_bits_result_index = 0;
fixed_tor_tls_create_certificate_result_index = 0;
- fixed_tor_tls_create_certificate_result[0] = tor_malloc_zero(sizeof(X509));
- fixed_tor_tls_create_certificate_result[1] = tor_malloc_zero(sizeof(X509));
- fixed_tor_tls_create_certificate_result[2] = tor_malloc_zero(sizeof(X509));
+ fixed_tor_tls_create_certificate_result[0] = X509_new();
+ fixed_tor_tls_create_certificate_result[1] = X509_new();
+ fixed_tor_tls_create_certificate_result[2] = X509_new();
fixed_tor_x509_cert_new_result_index = 0;
fixed_tor_x509_cert_new_result[0] = tor_malloc_zero(sizeof(tor_x509_cert_t));
fixed_tor_x509_cert_new_result[1] = tor_malloc_zero(sizeof(tor_x509_cert_t));
diff --git a/src/test/test_util.c b/src/test/test_util.c
index 036f739b89..ec11bfd5f5 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -12,10 +12,12 @@
#include "buffers.h"
#include "config.h"
#include "control.h"
+#include "crypto_rand.h"
#include "test.h"
#include "memarea.h"
#include "util_process.h"
#include "log_test_helpers.h"
+#include "compress_zstd.h"
#ifdef HAVE_PWD_H
#include <pwd.h>
@@ -2396,6 +2398,37 @@ test_util_compress_stream_impl(compress_method_t method,
tor_free(buf3);
}
+/** Setup function for compression tests: handles x-zstd:nostatic
+ */
+static void *
+compression_test_setup(const struct testcase_t *testcase)
+{
+ tor_assert(testcase->setup_data);
+ tor_assert(testcase->setup_data != (void*)TT_SKIP);
+ const char *methodname = testcase->setup_data;
+
+ if (!strcmp(methodname, "x-zstd:nostatic")) {
+ methodname = "x-zstd";
+ tor_zstd_set_static_apis_disabled_for_testing(1);
+ }
+
+ return (void *)methodname;
+}
+
+/** Cleanup for compression tests: disables nostatic */
+static int
+compression_test_cleanup(const struct testcase_t *testcase, void *ptr)
+{
+ (void)testcase;
+ (void)ptr;
+ tor_zstd_set_static_apis_disabled_for_testing(0);
+ return 1;
+}
+
+static const struct testcase_setup_t compress_setup = {
+ compression_test_setup, compression_test_cleanup
+};
+
/** Run unit tests for compression functions */
static void
test_util_compress(void *arg)
@@ -5875,6 +5908,13 @@ test_util_monotonic_time(void *arg)
tt_u64_op(coarse_stamp_diff, OP_GE, 120);
tt_u64_op(coarse_stamp_diff, OP_LE, 1200);
+ {
+ uint64_t units = monotime_msec_to_approx_coarse_stamp_units(5000);
+ uint64_t ms = monotime_coarse_stamp_units_to_approx_msec(units);
+ tt_u64_op(ms, OP_GE, 4950);
+ tt_u64_op(ms, OP_LT, 5050);
+ }
+
done:
;
}
@@ -5996,6 +6036,9 @@ test_util_monotonic_time_add_msec(void *arg)
monotime_coarse_add_msec(&ct2, &ct1, 1337);
tt_i64_op(monotime_diff_msec(&t1, &t2), OP_EQ, 1337);
tt_i64_op(monotime_coarse_diff_msec(&ct1, &ct2), OP_EQ, 1337);
+ // The 32-bit variant must be within 1% of the regular one.
+ tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_GT, 1323);
+ tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_LT, 1350);
/* Add 1337 msec twice more; make sure that any second rollover issues
* worked. */
@@ -6005,6 +6048,25 @@ test_util_monotonic_time_add_msec(void *arg)
monotime_coarse_add_msec(&ct2, &ct2, 1337);
tt_i64_op(monotime_diff_msec(&t1, &t2), OP_EQ, 1337*3);
tt_i64_op(monotime_coarse_diff_msec(&ct1, &ct2), OP_EQ, 1337*3);
+ tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_GT, 3970);
+ tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_LT, 4051);
+
+ done:
+ ;
+}
+
+static void
+test_util_nowrap_math(void *arg)
+{
+ (void)arg;
+
+ tt_u64_op(0, OP_EQ, tor_add_u32_nowrap(0, 0));
+ tt_u64_op(1, OP_EQ, tor_add_u32_nowrap(0, 1));
+ tt_u64_op(1, OP_EQ, tor_add_u32_nowrap(1, 0));
+ tt_u64_op(4, OP_EQ, tor_add_u32_nowrap(2, 2));
+ tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(UINT32_MAX-1, 2));
+ tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(2, UINT32_MAX-1));
+ tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(UINT32_MAX, UINT32_MAX));
done:
;
@@ -6122,22 +6184,22 @@ test_util_get_unquoted_path(void *arg)
{ #name, test_util_ ## name, flags, NULL, NULL }
#define COMPRESS(name, identifier) \
- { "compress/" #name, test_util_compress, 0, &passthrough_setup, \
+ { "compress/" #name, test_util_compress, 0, &compress_setup, \
(char*)(identifier) }
#define COMPRESS_CONCAT(name, identifier) \
{ "compress_concat/" #name, test_util_decompress_concatenated, 0, \
- &passthrough_setup, \
+ &compress_setup, \
(char*)(identifier) }
#define COMPRESS_JUNK(name, identifier) \
{ "compress_junk/" #name, test_util_decompress_junk, 0, \
- &passthrough_setup, \
+ &compress_setup, \
(char*)(identifier) }
#define COMPRESS_DOS(name, identifier) \
{ "compress_dos/" #name, test_util_decompress_dos, 0, \
- &passthrough_setup, \
+ &compress_setup, \
(char*)(identifier) }
#ifdef _WIN32
@@ -6168,11 +6230,13 @@ struct testcase_t util_tests[] = {
COMPRESS(gzip, "gzip"),
COMPRESS(lzma, "x-tor-lzma"),
COMPRESS(zstd, "x-zstd"),
+ COMPRESS(zstd_nostatic, "x-zstd:nostatic"),
COMPRESS(none, "identity"),
COMPRESS_CONCAT(zlib, "deflate"),
COMPRESS_CONCAT(gzip, "gzip"),
COMPRESS_CONCAT(lzma, "x-tor-lzma"),
COMPRESS_CONCAT(zstd, "x-zstd"),
+ COMPRESS_CONCAT(zstd_nostatic, "x-zstd:nostatic"),
COMPRESS_CONCAT(none, "identity"),
COMPRESS_JUNK(zlib, "deflate"),
COMPRESS_JUNK(gzip, "gzip"),
@@ -6181,6 +6245,7 @@ struct testcase_t util_tests[] = {
COMPRESS_DOS(gzip, "gzip"),
COMPRESS_DOS(lzma, "x-tor-lzma"),
COMPRESS_DOS(zstd, "x-zstd"),
+ COMPRESS_DOS(zstd_nostatic, "x-zstd:nostatic"),
UTIL_TEST(gzip_compression_bomb, TT_FORK),
UTIL_LEGACY(datadir),
UTIL_LEGACY(memarea),
@@ -6201,6 +6266,7 @@ struct testcase_t util_tests[] = {
UTIL_TEST(listdir, 0),
UTIL_TEST(parent_dir, 0),
UTIL_TEST(ftruncate, 0),
+ UTIL_TEST(nowrap_math, 0),
UTIL_TEST(num_cpus, 0),
UTIL_TEST_WIN_ONLY(load_win_lib, 0),
UTIL_TEST_NO_WIN(exit_status, 0),
diff --git a/src/test/test_util_format.c b/src/test/test_util_format.c
index 683d5fdac1..10645fe117 100644
--- a/src/test/test_util_format.c
+++ b/src/test/test_util_format.c
@@ -6,6 +6,7 @@
#include "test.h"
+#include "crypto_rand.h"
#define UTIL_FORMAT_PRIVATE
#include "util_format.h"
diff --git a/src/test/test_voting_schedule.c b/src/test/test_voting_schedule.c
new file mode 100644
index 0000000000..df6058b74f
--- /dev/null
+++ b/src/test/test_voting_schedule.c
@@ -0,0 +1,64 @@
+/* Copyright (c) 2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+
+#include "or.h"
+#include "voting_schedule.h"
+
+#include "test.h"
+
+static void
+test_voting_schedule_interval_start(void *arg)
+{
+#define next_interval voting_schedule_get_start_of_next_interval
+ (void)arg;
+ char buf[ISO_TIME_LEN+1];
+
+ // Midnight UTC tonight (as I am writing this test)
+ const time_t midnight = 1525651200;
+ format_iso_time(buf, midnight);
+ tt_str_op(buf, OP_EQ, "2018-05-07 00:00:00");
+
+ /* Some simple tests with a 50-minute voting interval */
+
+ tt_i64_op(next_interval(midnight, 3000, 0), OP_EQ,
+ midnight+3000);
+
+ tt_i64_op(next_interval(midnight+100, 3000, 0), OP_EQ,
+ midnight+3000);
+
+ tt_i64_op(next_interval(midnight+3000, 3000, 0), OP_EQ,
+ midnight+6000);
+
+ tt_i64_op(next_interval(midnight+3001, 3000, 0), OP_EQ,
+ midnight+6000);
+
+ /* Make sure that we roll around properly at midnight */
+ tt_i64_op(next_interval(midnight+83000, 3000, 0), OP_EQ,
+ midnight+84000);
+
+ /* We start fresh at midnight UTC, even if there are leftover seconds. */
+ tt_i64_op(next_interval(midnight+84005, 3000, 0), OP_EQ,
+ midnight+86400);
+
+ /* Now try with offsets. (These are only used for test networks.) */
+ tt_i64_op(next_interval(midnight, 3000, 99), OP_EQ,
+ midnight+99);
+
+ tt_i64_op(next_interval(midnight+100, 3000, 99), OP_EQ,
+ midnight+3099);
+
+ done:
+ ;
+#undef next_interval
+}
+
+#define VS(name,flags) \
+ { #name, test_voting_schedule_##name, (flags), NULL, NULL }
+
+struct testcase_t voting_schedule_tests[] = {
+ VS(interval_start, 0),
+ END_OF_TESTCASES
+};
+
diff --git a/src/test/test_workqueue.c b/src/test/test_workqueue.c
index 2b03173717..cc7073850c 100644
--- a/src/test/test_workqueue.c
+++ b/src/test/test_workqueue.c
@@ -7,12 +7,11 @@
#include "compat_threads.h"
#include "onion.h"
#include "workqueue.h"
-#include "crypto.h"
#include "crypto_curve25519.h"
+#include "crypto_rand.h"
#include "compat_libevent.h"
#include <stdio.h>
-#include <event2/event.h>
#define MAX_INFLIGHT (1<<16)
@@ -159,6 +158,7 @@ static tor_weak_rng_t weak_rng;
static int n_sent = 0;
static int rsa_sent = 0;
static int ecdh_sent = 0;
+static int n_received_previously = 0;
static int n_received = 0;
static int no_shutdown = 0;
@@ -224,18 +224,24 @@ add_n_work_items(threadpool_t *tp, int n)
workqueue_entry_t **to_cancel;
workqueue_entry_t *ent;
- to_cancel = tor_malloc(sizeof(workqueue_entry_t*) * opt_n_cancel);
+ // We'll choose randomly which entries to cancel.
+ to_cancel = tor_calloc(opt_n_cancel, sizeof(workqueue_entry_t*));
while (n_queued++ < n) {
ent = add_work(tp);
if (! ent) {
puts("Z");
- tor_event_base_loopexit(tor_libevent_get_base(), NULL);
+ tor_libevent_exit_loop_after_delay(tor_libevent_get_base(), NULL);
return -1;
}
- if (n_try_cancel < opt_n_cancel &&
- tor_weak_random_range(&weak_rng, n) < opt_n_cancel) {
+
+ if (n_try_cancel < opt_n_cancel) {
to_cancel[n_try_cancel++] = ent;
+ } else {
+ int p = tor_weak_random_range(&weak_rng, n_queued);
+ if (p < n_try_cancel) {
+ to_cancel[p] = ent;
+ }
}
}
@@ -256,19 +262,13 @@ add_n_work_items(threadpool_t *tp, int n)
static int shutting_down = 0;
static void
-replysock_readable_cb(tor_socket_t sock, short what, void *arg)
+replysock_readable_cb(threadpool_t *tp)
{
- threadpool_t *tp = arg;
- replyqueue_t *rq = threadpool_get_replyqueue(tp);
-
- int old_r = n_received;
- (void) sock;
- (void) what;
-
- replyqueue_process(rq);
- if (old_r == n_received)
+ if (n_received_previously == n_received)
return;
+ n_received_previously = n_received;
+
if (opt_verbose) {
printf("%d / %d", n_received, n_sent);
if (opt_n_cancel)
@@ -308,7 +308,7 @@ replysock_readable_cb(tor_socket_t sock, short what, void *arg)
handle_reply_shutdown, NULL);
{
struct timeval limit = { 2, 0 };
- tor_event_base_loopexit(tor_libevent_get_base(), &limit);
+ tor_libevent_exit_loop_after_delay(tor_libevent_get_base(), &limit);
}
}
}
@@ -337,7 +337,6 @@ main(int argc, char **argv)
threadpool_t *tp;
int i;
tor_libevent_cfg evcfg;
- struct event *ev;
uint32_t as_flags = 0;
for (i = 1; i < argc; ++i) {
@@ -411,11 +410,11 @@ main(int argc, char **argv)
memset(&evcfg, 0, sizeof(evcfg));
tor_libevent_initialize(&evcfg);
- ev = tor_event_new(tor_libevent_get_base(),
- replyqueue_get_socket(rq), EV_READ|EV_PERSIST,
- replysock_readable_cb, tp);
-
- event_add(ev, NULL);
+ {
+ int r = threadpool_register_reply_event(tp,
+ replysock_readable_cb);
+ tor_assert(r == 0);
+ }
#ifdef TRACK_RESPONSES
handled = bitarray_init_zero(opt_n_items);
@@ -433,10 +432,10 @@ main(int argc, char **argv)
{
struct timeval limit = { 180, 0 };
- tor_event_base_loopexit(tor_libevent_get_base(), &limit);
+ tor_libevent_exit_loop_after_delay(tor_libevent_get_base(), &limit);
}
- event_base_loop(tor_libevent_get_base(), 0);
+ tor_libevent_run_event_loop(tor_libevent_get_base(), 0);
if (n_sent != opt_n_items || n_received+n_successful_cancel != n_sent) {
printf("%d vs %d\n", n_sent, opt_n_items);
diff --git a/src/test/testing_common.c b/src/test/testing_common.c
index 52729147b2..4c3fe15960 100644
--- a/src/test/testing_common.c
+++ b/src/test/testing_common.c
@@ -8,14 +8,17 @@
* \brief Common pieces to implement unit tests.
**/
+#define MAIN_PRIVATE
#include "orconfig.h"
#include "or.h"
#include "control.h"
#include "config.h"
+#include "crypto_rand.h"
#include "rephist.h"
#include "backtrace.h"
#include "test.h"
#include "channelpadding.h"
+#include "main.h"
#include <stdio.h>
#ifdef HAVE_FCNTL_H
@@ -29,8 +32,6 @@
#include <dirent.h>
#endif /* defined(_WIN32) */
-#include "or.h"
-
#ifdef USE_DMALLOC
#include <dmalloc.h>
#include "main.h"
@@ -292,6 +293,7 @@ main(int c, const char **v)
}
rep_hist_init();
setup_directory();
+ initialize_mainloop_events();
options_init(options);
options->DataDirectory = tor_strdup(temp_dir);
tor_asprintf(&options->KeyDirectory, "%s"PATH_SEPARATOR"keys",
diff --git a/src/test/testing_rsakeys.c b/src/test/testing_rsakeys.c
index 7a24c0ed14..94d3db328a 100644
--- a/src/test/testing_rsakeys.c
+++ b/src/test/testing_rsakeys.c
@@ -3,6 +3,7 @@
* Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+#include "crypto_rand.h"
#include "orconfig.h"
#include "or.h"
#include "test.h"