test_relay.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /* Copyright (c) 2014-2017, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. #include "or.h"
  4. #define CIRCUITBUILD_PRIVATE
  5. #include "circuitbuild.h"
  6. #include "circuitlist.h"
  7. #include "rephist.h"
  8. #include "channeltls.h"
  9. #define RELAY_PRIVATE
  10. #include "relay.h"
  11. /* For init/free stuff */
  12. #include "scheduler.h"
  13. /* Test suite stuff */
  14. #include "test.h"
  15. #include "fakechans.h"
  16. static or_circuit_t * new_fake_orcirc(channel_t *nchan, channel_t *pchan);
  17. static void test_relay_append_cell_to_circuit_queue(void *arg);
  18. uint64_t find_largest_max(bw_array_t *b);
  19. void commit_max(bw_array_t *b);
  20. void advance_obs(bw_array_t *b);
  21. static or_circuit_t *
  22. new_fake_orcirc(channel_t *nchan, channel_t *pchan)
  23. {
  24. or_circuit_t *orcirc = NULL;
  25. circuit_t *circ = NULL;
  26. orcirc = tor_malloc_zero(sizeof(*orcirc));
  27. circ = &(orcirc->base_);
  28. circ->magic = OR_CIRCUIT_MAGIC;
  29. circuit_set_n_circid_chan(circ, get_unique_circ_id_by_chan(nchan), nchan);
  30. cell_queue_init(&(circ->n_chan_cells));
  31. circ->n_hop = NULL;
  32. circ->streams_blocked_on_n_chan = 0;
  33. circ->streams_blocked_on_p_chan = 0;
  34. circ->n_delete_pending = 0;
  35. circ->p_delete_pending = 0;
  36. circ->received_destroy = 0;
  37. circ->state = CIRCUIT_STATE_OPEN;
  38. circ->purpose = CIRCUIT_PURPOSE_OR;
  39. circ->package_window = CIRCWINDOW_START_MAX;
  40. circ->deliver_window = CIRCWINDOW_START_MAX;
  41. circ->n_chan_create_cell = NULL;
  42. circuit_set_p_circid_chan(orcirc, get_unique_circ_id_by_chan(pchan), pchan);
  43. cell_queue_init(&(orcirc->p_chan_cells));
  44. return orcirc;
  45. }
  46. static void
  47. assert_circuit_ok_mock(const circuit_t *c)
  48. {
  49. (void) c;
  50. return;
  51. }
  52. static void
  53. test_relay_close_circuit(void *arg)
  54. {
  55. channel_t *nchan = NULL, *pchan = NULL;
  56. or_circuit_t *orcirc = NULL;
  57. cell_t *cell = NULL;
  58. int old_count, new_count;
  59. (void)arg;
  60. /* Make fake channels to be nchan and pchan for the circuit */
  61. nchan = new_fake_channel();
  62. tt_assert(nchan);
  63. pchan = new_fake_channel();
  64. tt_assert(pchan);
  65. /* We'll need chans with working cmuxes */
  66. nchan->cmux = circuitmux_alloc();
  67. pchan->cmux = circuitmux_alloc();
  68. /* Make a fake orcirc */
  69. orcirc = new_fake_orcirc(nchan, pchan);
  70. tt_assert(orcirc);
  71. circuitmux_attach_circuit(nchan->cmux, TO_CIRCUIT(orcirc),
  72. CELL_DIRECTION_OUT);
  73. circuitmux_attach_circuit(pchan->cmux, TO_CIRCUIT(orcirc),
  74. CELL_DIRECTION_IN);
  75. /* Make a cell */
  76. cell = tor_malloc_zero(sizeof(cell_t));
  77. make_fake_cell(cell);
  78. MOCK(scheduler_channel_has_waiting_cells,
  79. scheduler_channel_has_waiting_cells_mock);
  80. MOCK(assert_circuit_ok,
  81. assert_circuit_ok_mock);
  82. /* Append it */
  83. old_count = get_mock_scheduler_has_waiting_cells_count();
  84. append_cell_to_circuit_queue(TO_CIRCUIT(orcirc), nchan, cell,
  85. CELL_DIRECTION_OUT, 0);
  86. new_count = get_mock_scheduler_has_waiting_cells_count();
  87. tt_int_op(new_count, OP_EQ, old_count + 1);
  88. /* Now try the reverse direction */
  89. old_count = get_mock_scheduler_has_waiting_cells_count();
  90. append_cell_to_circuit_queue(TO_CIRCUIT(orcirc), pchan, cell,
  91. CELL_DIRECTION_IN, 0);
  92. new_count = get_mock_scheduler_has_waiting_cells_count();
  93. tt_int_op(new_count, OP_EQ, old_count + 1);
  94. /* Ensure our write totals are 0 */
  95. tt_int_op(find_largest_max(write_array), OP_EQ, 0);
  96. /* Mark the circuit for close */
  97. circuit_mark_for_close(TO_CIRCUIT(orcirc), 0);
  98. /* Check our write totals. */
  99. advance_obs(write_array);
  100. commit_max(write_array);
  101. /* Check for two cells plus overhead */
  102. tt_int_op(find_largest_max(write_array), OP_EQ,
  103. 2*(get_cell_network_size(nchan->wide_circ_ids)
  104. +TLS_PER_CELL_OVERHEAD));
  105. UNMOCK(scheduler_channel_has_waiting_cells);
  106. /* Get rid of the fake channels */
  107. MOCK(scheduler_release_channel, scheduler_release_channel_mock);
  108. channel_mark_for_close(nchan);
  109. channel_mark_for_close(pchan);
  110. UNMOCK(scheduler_release_channel);
  111. /* Shut down channels */
  112. channel_free_all();
  113. done:
  114. tor_free(cell);
  115. if (orcirc) {
  116. circuitmux_detach_circuit(nchan->cmux, TO_CIRCUIT(orcirc));
  117. circuitmux_detach_circuit(pchan->cmux, TO_CIRCUIT(orcirc));
  118. cell_queue_clear(&orcirc->base_.n_chan_cells);
  119. cell_queue_clear(&orcirc->p_chan_cells);
  120. }
  121. tor_free(orcirc);
  122. free_fake_channel(nchan);
  123. free_fake_channel(pchan);
  124. UNMOCK(assert_circuit_ok);
  125. return;
  126. }
  127. static void
  128. test_relay_append_cell_to_circuit_queue(void *arg)
  129. {
  130. channel_t *nchan = NULL, *pchan = NULL;
  131. or_circuit_t *orcirc = NULL;
  132. cell_t *cell = NULL;
  133. int old_count, new_count;
  134. (void)arg;
  135. /* Make fake channels to be nchan and pchan for the circuit */
  136. nchan = new_fake_channel();
  137. tt_assert(nchan);
  138. pchan = new_fake_channel();
  139. tt_assert(pchan);
  140. /* Make a fake orcirc */
  141. orcirc = new_fake_orcirc(nchan, pchan);
  142. tt_assert(orcirc);
  143. circuitmux_attach_circuit(nchan->cmux, TO_CIRCUIT(orcirc),
  144. CELL_DIRECTION_OUT);
  145. circuitmux_attach_circuit(pchan->cmux, TO_CIRCUIT(orcirc),
  146. CELL_DIRECTION_IN);
  147. /* Make a cell */
  148. cell = tor_malloc_zero(sizeof(cell_t));
  149. make_fake_cell(cell);
  150. MOCK(scheduler_channel_has_waiting_cells,
  151. scheduler_channel_has_waiting_cells_mock);
  152. /* Append it */
  153. old_count = get_mock_scheduler_has_waiting_cells_count();
  154. append_cell_to_circuit_queue(TO_CIRCUIT(orcirc), nchan, cell,
  155. CELL_DIRECTION_OUT, 0);
  156. new_count = get_mock_scheduler_has_waiting_cells_count();
  157. tt_int_op(new_count, OP_EQ, old_count + 1);
  158. /* Now try the reverse direction */
  159. old_count = get_mock_scheduler_has_waiting_cells_count();
  160. append_cell_to_circuit_queue(TO_CIRCUIT(orcirc), pchan, cell,
  161. CELL_DIRECTION_IN, 0);
  162. new_count = get_mock_scheduler_has_waiting_cells_count();
  163. tt_int_op(new_count, OP_EQ, old_count + 1);
  164. UNMOCK(scheduler_channel_has_waiting_cells);
  165. /* Get rid of the fake channels */
  166. MOCK(scheduler_release_channel, scheduler_release_channel_mock);
  167. channel_mark_for_close(nchan);
  168. channel_mark_for_close(pchan);
  169. UNMOCK(scheduler_release_channel);
  170. /* Shut down channels */
  171. channel_free_all();
  172. done:
  173. tor_free(cell);
  174. if (orcirc) {
  175. circuitmux_detach_circuit(nchan->cmux, TO_CIRCUIT(orcirc));
  176. circuitmux_detach_circuit(pchan->cmux, TO_CIRCUIT(orcirc));
  177. cell_queue_clear(&orcirc->base_.n_chan_cells);
  178. cell_queue_clear(&orcirc->p_chan_cells);
  179. }
  180. tor_free(orcirc);
  181. free_fake_channel(nchan);
  182. free_fake_channel(pchan);
  183. return;
  184. }
  185. struct testcase_t relay_tests[] = {
  186. { "append_cell_to_circuit_queue", test_relay_append_cell_to_circuit_queue,
  187. TT_FORK, NULL, NULL },
  188. { "close_circ_rephist", test_relay_close_circuit,
  189. TT_FORK, NULL, NULL },
  190. END_OF_TESTCASES
  191. };