test_circuitstats.c 6.6 KB

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