tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

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 };