123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- /* Copyright (c) 2017-2019, The Tor Project, Inc. */
- /* See LICENSE for licensing information */
- #define CIRCUITBUILD_PRIVATE
- #define CIRCUITSTATS_PRIVATE
- #define CIRCUITLIST_PRIVATE
- #define CHANNEL_PRIVATE_
- #include "core/or/or.h"
- #include "test/test.h"
- #include "test/test_helpers.h"
- #include "test/log_test_helpers.h"
- #include "app/config/config.h"
- #include "core/or/circuitlist.h"
- #include "core/or/circuitbuild.h"
- #include "core/or/circuitstats.h"
- #include "core/or/circuituse.h"
- #include "core/or/channel.h"
- #include "core/or/cpath_build_state_st.h"
- #include "core/or/crypt_path_st.h"
- #include "core/or/extend_info_st.h"
- #include "core/or/origin_circuit_st.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);
- 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);
- tor_free(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
- };
|