test_circuitstats.c (6445B)
1 /* Copyright (c) 2017-2021, The Tor Project, Inc. */ 2 /* See LICENSE for licensing information */ 3 4 #define CIRCUITBUILD_PRIVATE 5 #define CIRCUITSTATS_PRIVATE 6 #define CIRCUITLIST_PRIVATE 7 #define CHANNEL_FILE_PRIVATE 8 9 #include "core/or/or.h" 10 #include "test/test.h" 11 #include "test/test_helpers.h" 12 #include "test/log_test_helpers.h" 13 #include "app/config/config.h" 14 #include "core/or/circuitlist.h" 15 #include "core/or/circuitbuild.h" 16 #include "core/or/circuitstats.h" 17 #include "core/or/circuituse.h" 18 #include "core/or/channel.h" 19 20 #include "core/or/crypt_path_st.h" 21 #include "core/or/extend_info_st.h" 22 #include "core/or/origin_circuit_st.h" 23 24 static origin_circuit_t *add_opened_threehop(void); 25 static origin_circuit_t *build_unopened_fourhop(struct timeval); 26 static origin_circuit_t *subtest_fourhop_circuit(struct timeval, int); 27 28 static int marked_for_close; 29 /* Mock function because we are not trying to test the close circuit that does 30 * an awful lot of checks on the circuit object. */ 31 static void 32 mock_circuit_mark_for_close(circuit_t *circ, int reason, int line, 33 const char *file) 34 { 35 (void) circ; 36 (void) reason; 37 (void) line; 38 (void) file; 39 marked_for_close = 1; 40 return; 41 } 42 43 static origin_circuit_t * 44 add_opened_threehop(void) 45 { 46 struct timeval circ_start_time; 47 memset(&circ_start_time, 0, sizeof(circ_start_time)); 48 extend_info_t fakehop; 49 memset(&fakehop, 0, sizeof(fakehop)); 50 extend_info_t *fakehop_list[DEFAULT_ROUTE_LEN] = {&fakehop, 51 &fakehop, 52 &fakehop}; 53 54 return new_test_origin_circuit(true, 55 circ_start_time, 56 DEFAULT_ROUTE_LEN, 57 fakehop_list); 58 } 59 60 static origin_circuit_t * 61 build_unopened_fourhop(struct timeval circ_start_time) 62 { 63 extend_info_t fakehop; 64 memset(&fakehop, 0, sizeof(fakehop)); 65 extend_info_t *fakehop_list[4] = {&fakehop, 66 &fakehop, 67 &fakehop, 68 &fakehop}; 69 70 return new_test_origin_circuit(false, 71 circ_start_time, 72 4, 73 fakehop_list); 74 } 75 76 static origin_circuit_t * 77 subtest_fourhop_circuit(struct timeval circ_start_time, int should_timeout) 78 { 79 origin_circuit_t *origin_circ = build_unopened_fourhop(circ_start_time); 80 81 // Now make them open one at a time and call 82 // circuit_build_times_handle_completed_hop(); 83 origin_circ->cpath->state = CPATH_STATE_OPEN; 84 circuit_build_times_handle_completed_hop(origin_circ); 85 tt_int_op(get_circuit_build_times()->total_build_times, OP_EQ, 0); 86 87 origin_circ->cpath->next->state = CPATH_STATE_OPEN; 88 circuit_build_times_handle_completed_hop(origin_circ); 89 tt_int_op(get_circuit_build_times()->total_build_times, OP_EQ, 0); 90 91 // Third hop: We should count it now. 92 origin_circ->cpath->next->next->state = CPATH_STATE_OPEN; 93 circuit_build_times_handle_completed_hop(origin_circ); 94 tt_int_op(get_circuit_build_times()->total_build_times, OP_EQ, 95 !should_timeout); // 1 if counted, 0 otherwise 96 97 // Fourth hop: Don't double count 98 origin_circ->cpath->next->next->next->state = CPATH_STATE_OPEN; 99 circuit_build_times_handle_completed_hop(origin_circ); 100 tt_int_op(get_circuit_build_times()->total_build_times, OP_EQ, 101 !should_timeout); 102 103 done: 104 return origin_circ; 105 } 106 107 static void 108 test_circuitstats_hoplen(void *arg) 109 { 110 /* Plan: 111 * 0. Test no other opened circs (relaxed timeout) 112 * 1. Check >3 hop circ building w/o timeout 113 * 2. Check >3 hop circs w/ timeouts.. 114 */ 115 struct timeval circ_start_time; 116 origin_circuit_t *threehop = NULL; 117 origin_circuit_t *fourhop = NULL; 118 (void)arg; 119 MOCK(circuit_mark_for_close_, mock_circuit_mark_for_close); 120 121 circuit_build_times_init(get_circuit_build_times_mutable()); 122 123 // Let's set a close_ms to 2X the initial timeout, so we can 124 // test relaxed functionality (which uses the close_ms timeout) 125 get_circuit_build_times_mutable()->close_ms *= 2; 126 127 tor_gettimeofday(&circ_start_time); 128 circ_start_time.tv_sec -= 119; // make us hit "relaxed" cutoff 129 130 // Test 1: Build a fourhop circuit that should get marked 131 // as relaxed and eventually counted by circuit_expire_building 132 // (but not before) 133 fourhop = subtest_fourhop_circuit(circ_start_time, 0); 134 tt_int_op(fourhop->relaxed_timeout, OP_EQ, 0); 135 tt_int_op(marked_for_close, OP_EQ, 0); 136 circuit_expire_building(); 137 tt_int_op(marked_for_close, OP_EQ, 0); 138 tt_int_op(fourhop->relaxed_timeout, OP_EQ, 1); 139 TO_CIRCUIT(fourhop)->timestamp_began.tv_sec -= 119; 140 circuit_expire_building(); 141 tt_int_op(get_circuit_build_times()->total_build_times, OP_EQ, 1); 142 tt_int_op(marked_for_close, OP_EQ, 1); 143 144 circuit_free_(TO_CIRCUIT(fourhop)); 145 circuit_build_times_reset(get_circuit_build_times_mutable()); 146 147 // Test 2: Add a threehop circuit for non-relaxed timeouts 148 threehop = add_opened_threehop(); 149 150 /* This circuit should not timeout */ 151 tor_gettimeofday(&circ_start_time); 152 circ_start_time.tv_sec -= 59; 153 fourhop = subtest_fourhop_circuit(circ_start_time, 0); 154 circuit_expire_building(); 155 tt_int_op(get_circuit_build_times()->total_build_times, OP_EQ, 1); 156 tt_int_op(TO_CIRCUIT(fourhop)->purpose, OP_NE, 157 CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT); 158 159 circuit_free_((circuit_t *)fourhop); 160 circuit_build_times_reset(get_circuit_build_times_mutable()); 161 162 /* Test 3: This circuit should now time out and get marked as a 163 * measurement circuit, but still get counted (and counted only once) 164 */ 165 circ_start_time.tv_sec -= 2; 166 fourhop = subtest_fourhop_circuit(circ_start_time, 0); 167 tt_int_op(TO_CIRCUIT(fourhop)->purpose, OP_EQ, 168 CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT); 169 tt_int_op(get_circuit_build_times()->total_build_times, OP_EQ, 1); 170 circuit_expire_building(); 171 tt_int_op(get_circuit_build_times()->total_build_times, OP_EQ, 1); 172 173 done: 174 UNMOCK(circuit_mark_for_close_); 175 circuit_free_(TO_CIRCUIT(threehop)); 176 circuit_free_(TO_CIRCUIT(fourhop)); 177 circuit_build_times_free_timeouts(get_circuit_build_times_mutable()); 178 } 179 180 #define TEST_CIRCUITSTATS(name, flags) \ 181 { #name, test_##name, (flags), &helper_pubsub_setup, NULL } 182 183 struct testcase_t circuitstats_tests[] = { 184 TEST_CIRCUITSTATS(circuitstats_hoplen, TT_FORK), 185 END_OF_TESTCASES 186 };