aboutsummaryrefslogtreecommitdiff
path: root/src/test/test_circuitstats.c
diff options
context:
space:
mode:
authorMike Perry <mikeperry-git@torproject.org>2017-09-20 20:24:59 +0000
committerMike Perry <mikeperry-git@torproject.org>2017-12-07 00:04:39 +0000
commit050bb67974c11e0f390f4b1fa1b067c86538c59e (patch)
tree7ecf0e8ceaca199177e203c8d35936ae41279899 /src/test/test_circuitstats.c
parent125df07d609933a7974f362706b126a4bf339788 (diff)
downloadtor-050bb67974c11e0f390f4b1fa1b067c86538c59e.tar.gz
tor-050bb67974c11e0f390f4b1fa1b067c86538c59e.zip
Add tests for circuitstats.c
These tests primarily test the relaxed and measured behavior of circuitstats.c, to make sure we did not break it with #23100 or #23114.
Diffstat (limited to 'src/test/test_circuitstats.c')
-rw-r--r--src/test/test_circuitstats.c199
1 files changed, 199 insertions, 0 deletions
diff --git a/src/test/test_circuitstats.c b/src/test/test_circuitstats.c
new file mode 100644
index 0000000000..1c6a2ba28f
--- /dev/null
+++ b/src/test/test_circuitstats.c
@@ -0,0 +1,199 @@
+/* Copyright (c) 2017, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#define CIRCUITBUILD_PRIVATE
+#define CIRCUITSTATS_PRIVATE
+#define CHANNEL_PRIVATE_
+
+#include "or.h"
+#include "test.h"
+#include "test_helpers.h"
+#include "log_test_helpers.h"
+#include "config.h"
+#include "circuitlist.h"
+#include "circuitbuild.h"
+#include "circuitstats.h"
+#include "circuituse.h"
+#include "channel.h"
+
+void test_circuitstats_timeout(void *arg);
+void test_circuitstats_hoplen(void *arg);
+origin_circuit_t *subtest_fourhop_circuit(struct timeval, int);
+origin_circuit_t *add_opened_threehop(void);
+origin_circuit_t *build_unopened_fourhop(struct timeval);
+
+void circuit_free(circuit_t *circ);
+int onion_append_hop(crypt_path_t **head_ptr, extend_info_t *choice);
+
+static int marked_for_close;
+/* Mock function because we are not trying to test the close circuit that does
+ * an awful lot of checks on the circuit object. */
+static void
+mock_circuit_mark_for_close(circuit_t *circ, int reason, int line,
+ const char *file)
+{
+ (void) circ;
+ (void) reason;
+ (void) line;
+ (void) file;
+ marked_for_close = 1;
+ return;
+}
+
+origin_circuit_t *
+add_opened_threehop(void)
+{
+ origin_circuit_t *or_circ = origin_circuit_new();
+ extend_info_t fakehop;
+ memset(&fakehop, 0, sizeof(fakehop));
+
+ TO_CIRCUIT(or_circ)->purpose = CIRCUIT_PURPOSE_C_GENERAL;
+
+ or_circ->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
+ or_circ->build_state->desired_path_len = DEFAULT_ROUTE_LEN;
+
+ onion_append_hop(&or_circ->cpath, &fakehop);
+ onion_append_hop(&or_circ->cpath, &fakehop);
+ onion_append_hop(&or_circ->cpath, &fakehop);
+
+ or_circ->has_opened = 1;
+ TO_CIRCUIT(or_circ)->state = CIRCUIT_STATE_OPEN;
+ TO_CIRCUIT(or_circ)->purpose = CIRCUIT_PURPOSE_C_GENERAL;
+
+ return or_circ;
+}
+
+origin_circuit_t *
+build_unopened_fourhop(struct timeval circ_start_time)
+{
+ origin_circuit_t *or_circ = origin_circuit_new();
+ extend_info_t *fakehop = tor_malloc_zero(sizeof(extend_info_t));
+ memset(fakehop, 0, sizeof(extend_info_t));
+
+ TO_CIRCUIT(or_circ)->purpose = CIRCUIT_PURPOSE_C_GENERAL;
+ TO_CIRCUIT(or_circ)->timestamp_began = circ_start_time;
+ TO_CIRCUIT(or_circ)->timestamp_created = circ_start_time;
+
+ or_circ->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
+ or_circ->build_state->desired_path_len = 4;
+
+ onion_append_hop(&or_circ->cpath, fakehop);
+ onion_append_hop(&or_circ->cpath, fakehop);
+ onion_append_hop(&or_circ->cpath, fakehop);
+ onion_append_hop(&or_circ->cpath, fakehop);
+
+ return or_circ;
+}
+
+origin_circuit_t *
+subtest_fourhop_circuit(struct timeval circ_start_time, int should_timeout)
+{
+ origin_circuit_t *or_circ = build_unopened_fourhop(circ_start_time);
+
+ // Now make them open one at a time and call
+ // circuit_build_times_handle_completed_hop();
+ or_circ->cpath->state = CPATH_STATE_OPEN;
+ circuit_build_times_handle_completed_hop(or_circ);
+ tt_int_op(get_circuit_build_times()->total_build_times, OP_EQ, 0);
+
+ or_circ->cpath->next->state = CPATH_STATE_OPEN;
+ circuit_build_times_handle_completed_hop(or_circ);
+ tt_int_op(get_circuit_build_times()->total_build_times, OP_EQ, 0);
+
+ // Third hop: We should count it now.
+ or_circ->cpath->next->next->state = CPATH_STATE_OPEN;
+ circuit_build_times_handle_completed_hop(or_circ);
+ tt_int_op(get_circuit_build_times()->total_build_times, OP_EQ,
+ !should_timeout); // 1 if counted, 0 otherwise
+
+ // Fourth hop: Don't double count
+ or_circ->cpath->next->next->next->state = CPATH_STATE_OPEN;
+ circuit_build_times_handle_completed_hop(or_circ);
+ tt_int_op(get_circuit_build_times()->total_build_times, OP_EQ,
+ !should_timeout);
+
+ done:
+ return or_circ;
+}
+
+void
+test_circuitstats_hoplen(void *arg)
+{
+ /* Plan:
+ * 0. Test no other opened circs (relaxed timeout)
+ * 1. Check >3 hop circ building w/o timeout
+ * 2. Check >3 hop circs w/ timeouts..
+ */
+ struct timeval circ_start_time;
+ origin_circuit_t *threehop = NULL;
+ origin_circuit_t *fourhop = NULL;
+ (void)arg;
+ MOCK(circuit_mark_for_close_, mock_circuit_mark_for_close);
+
+ circuit_build_times_init(get_circuit_build_times_mutable());
+
+ // Let's set a close_ms to 2X the initial timeout, so we can
+ // test relaxed functionality (which uses the close_ms timeout)
+ get_circuit_build_times_mutable()->close_ms *= 2;
+
+ tor_gettimeofday(&circ_start_time);
+ circ_start_time.tv_sec -= 119; // make us hit "relaxed" cutoff
+
+ // Test 1: Build a fourhop circuit that should get marked
+ // as relaxed and eventually counted by circuit_expire_building
+ // (but not before)
+ fourhop = subtest_fourhop_circuit(circ_start_time, 0);
+ tt_int_op(fourhop->relaxed_timeout, OP_EQ, 0);
+ tt_int_op(marked_for_close, OP_EQ, 0);
+ circuit_expire_building();
+ tt_int_op(marked_for_close, OP_EQ, 0);
+ tt_int_op(fourhop->relaxed_timeout, OP_EQ, 1);
+ TO_CIRCUIT(fourhop)->timestamp_began.tv_sec -= 119;
+ circuit_expire_building();
+ tt_int_op(get_circuit_build_times()->total_build_times, OP_EQ, 1);
+ tt_int_op(marked_for_close, OP_EQ, 1);
+
+ circuit_free(TO_CIRCUIT(fourhop));
+ circuit_build_times_reset(get_circuit_build_times_mutable());
+
+ // Test 2: Add a threehop circuit for non-relaxed timeouts
+ threehop = add_opened_threehop();
+
+ /* This circuit should not timeout */
+ tor_gettimeofday(&circ_start_time);
+ circ_start_time.tv_sec -= 59;
+ fourhop = subtest_fourhop_circuit(circ_start_time, 0);
+ circuit_expire_building();
+ tt_int_op(get_circuit_build_times()->total_build_times, OP_EQ, 1);
+ tt_int_op(TO_CIRCUIT(fourhop)->purpose, OP_NE,
+ CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT);
+
+ circuit_free((circuit_t *)fourhop);
+ circuit_build_times_reset(get_circuit_build_times_mutable());
+
+ /* Test 3: This circuit should now time out and get marked as a
+ * measurement circuit, but still get counted (and counted only once)
+ */
+ circ_start_time.tv_sec -= 2;
+ fourhop = subtest_fourhop_circuit(circ_start_time, 0);
+ tt_int_op(TO_CIRCUIT(fourhop)->purpose, OP_EQ,
+ CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT);
+ tt_int_op(get_circuit_build_times()->total_build_times, OP_EQ, 1);
+ circuit_expire_building();
+ tt_int_op(get_circuit_build_times()->total_build_times, OP_EQ, 1);
+
+ done:
+ UNMOCK(circuit_mark_for_close_);
+ circuit_free(TO_CIRCUIT(threehop));
+ circuit_free(TO_CIRCUIT(fourhop));
+ circuit_build_times_free_timeouts(get_circuit_build_times_mutable());
+}
+
+#define TEST_CIRCUITSTATS(name, flags) \
+ { #name, test_##name, (flags), NULL, NULL }
+
+struct testcase_t circuitstats_tests[] = {
+ TEST_CIRCUITSTATS(circuitstats_hoplen, TT_FORK),
+ END_OF_TESTCASES
+};
+