test_circuitlist.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /* Copyright (c) 2013, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. #define TOR_CHANNEL_INTERNAL_
  4. #define CIRCUITLIST_PRIVATE
  5. #include "or.h"
  6. #include "channel.h"
  7. #include "circuitlist.h"
  8. #include "test.h"
  9. static channel_t *
  10. new_fake_channel(void)
  11. {
  12. channel_t *chan = tor_malloc_zero(sizeof(channel_t));
  13. channel_init(chan);
  14. return chan;
  15. }
  16. static struct {
  17. int ncalls;
  18. void *cmux;
  19. void *circ;
  20. cell_direction_t dir;
  21. } cam;
  22. static void
  23. circuitmux_attach_mock(circuitmux_t *cmux, circuit_t *circ,
  24. cell_direction_t dir)
  25. {
  26. ++cam.ncalls;
  27. cam.cmux = cmux;
  28. cam.circ = circ;
  29. cam.dir = dir;
  30. }
  31. static struct {
  32. int ncalls;
  33. void *cmux;
  34. void *circ;
  35. } cdm;
  36. static void
  37. circuitmux_detach_mock(circuitmux_t *cmux, circuit_t *circ)
  38. {
  39. ++cdm.ncalls;
  40. cdm.cmux = cmux;
  41. cdm.circ = circ;
  42. }
  43. #define GOT_CMUX_ATTACH(mux_, circ_, dir_) do { \
  44. tt_int_op(cam.ncalls, ==, 1); \
  45. tt_ptr_op(cam.cmux, ==, (mux_)); \
  46. tt_ptr_op(cam.circ, ==, (circ_)); \
  47. tt_ptr_op(cam.dir, ==, (dir_)); \
  48. memset(&cam, 0, sizeof(cam)); \
  49. } while (0)
  50. #define GOT_CMUX_DETACH(mux_, circ_) do { \
  51. tt_int_op(cdm.ncalls, ==, 1); \
  52. tt_ptr_op(cdm.cmux, ==, (mux_)); \
  53. tt_ptr_op(cdm.circ, ==, (circ_)); \
  54. memset(&cdm, 0, sizeof(cdm)); \
  55. } while (0)
  56. static void
  57. test_clist_maps(void *arg)
  58. {
  59. channel_t *ch1 = new_fake_channel();
  60. channel_t *ch2 = new_fake_channel();
  61. channel_t *ch3 = new_fake_channel();
  62. or_circuit_t *or_c1=NULL, *or_c2=NULL;
  63. (void) arg;
  64. MOCK(circuitmux_attach_circuit, circuitmux_attach_mock);
  65. MOCK(circuitmux_detach_circuit, circuitmux_detach_mock);
  66. memset(&cam, 0, sizeof(cam));
  67. memset(&cdm, 0, sizeof(cdm));
  68. ch1->cmux = (void*)0x1001;
  69. ch2->cmux = (void*)0x1002;
  70. ch3->cmux = (void*)0x1003;
  71. or_c1 = or_circuit_new(100, ch2);
  72. tt_assert(or_c1);
  73. GOT_CMUX_ATTACH(ch2->cmux, or_c1, CELL_DIRECTION_IN);
  74. tt_int_op(or_c1->p_circ_id, ==, 100);
  75. tt_ptr_op(or_c1->p_chan, ==, ch2);
  76. or_c2 = or_circuit_new(100, ch1);
  77. tt_assert(or_c2);
  78. GOT_CMUX_ATTACH(ch1->cmux, or_c2, CELL_DIRECTION_IN);
  79. tt_int_op(or_c2->p_circ_id, ==, 100);
  80. tt_ptr_op(or_c2->p_chan, ==, ch1);
  81. circuit_set_n_circid_chan(TO_CIRCUIT(or_c1), 200, ch1);
  82. GOT_CMUX_ATTACH(ch1->cmux, or_c1, CELL_DIRECTION_OUT);
  83. circuit_set_n_circid_chan(TO_CIRCUIT(or_c2), 200, ch2);
  84. GOT_CMUX_ATTACH(ch2->cmux, or_c2, CELL_DIRECTION_OUT);
  85. tt_ptr_op(circuit_get_by_circid_channel(200, ch1), ==, TO_CIRCUIT(or_c1));
  86. tt_ptr_op(circuit_get_by_circid_channel(200, ch2), ==, TO_CIRCUIT(or_c2));
  87. tt_ptr_op(circuit_get_by_circid_channel(100, ch2), ==, TO_CIRCUIT(or_c1));
  88. /* Try the same thing again, to test the "fast" path. */
  89. tt_ptr_op(circuit_get_by_circid_channel(100, ch2), ==, TO_CIRCUIT(or_c1));
  90. tt_assert(circuit_id_in_use_on_channel(100, ch2));
  91. tt_assert(! circuit_id_in_use_on_channel(101, ch2));
  92. /* Try changing the circuitid and channel of that circuit. */
  93. circuit_set_p_circid_chan(or_c1, 500, ch3);
  94. GOT_CMUX_DETACH(ch2->cmux, TO_CIRCUIT(or_c1));
  95. GOT_CMUX_ATTACH(ch3->cmux, TO_CIRCUIT(or_c1), CELL_DIRECTION_IN);
  96. tt_ptr_op(circuit_get_by_circid_channel(100, ch2), ==, NULL);
  97. tt_assert(! circuit_id_in_use_on_channel(100, ch2));
  98. tt_ptr_op(circuit_get_by_circid_channel(500, ch3), ==, TO_CIRCUIT(or_c1));
  99. /* Now let's see about destroy handling. */
  100. tt_assert(! circuit_id_in_use_on_channel(205, ch2));
  101. tt_assert(circuit_id_in_use_on_channel(200, ch2));
  102. channel_note_destroy_pending(ch2, 200);
  103. channel_note_destroy_pending(ch2, 205);
  104. channel_note_destroy_pending(ch1, 100);
  105. tt_assert(circuit_id_in_use_on_channel(205, ch2))
  106. tt_assert(circuit_id_in_use_on_channel(200, ch2));
  107. tt_assert(circuit_id_in_use_on_channel(100, ch1));
  108. tt_assert(TO_CIRCUIT(or_c2)->n_delete_pending != 0);
  109. tt_ptr_op(circuit_get_by_circid_channel(200, ch2), ==, TO_CIRCUIT(or_c2));
  110. tt_ptr_op(circuit_get_by_circid_channel(100, ch1), ==, TO_CIRCUIT(or_c2));
  111. /* Okay, now free ch2 and make sure that the circuit ID is STILL not
  112. * usable, because we haven't declared the destroy to be nonpending */
  113. tt_int_op(cdm.ncalls, ==, 0);
  114. circuit_free(TO_CIRCUIT(or_c2));
  115. or_c2 = NULL; /* prevent free */
  116. tt_int_op(cdm.ncalls, ==, 2);
  117. memset(&cdm, 0, sizeof(cdm));
  118. tt_assert(circuit_id_in_use_on_channel(200, ch2));
  119. tt_assert(circuit_id_in_use_on_channel(100, ch1));
  120. tt_ptr_op(circuit_get_by_circid_channel(200, ch2), ==, NULL);
  121. tt_ptr_op(circuit_get_by_circid_channel(100, ch1), ==, NULL);
  122. /* Now say that the destroy is nonpending */
  123. channel_note_destroy_not_pending(ch2, 200);
  124. tt_ptr_op(circuit_get_by_circid_channel(200, ch2), ==, NULL);
  125. channel_note_destroy_not_pending(ch1, 100);
  126. tt_ptr_op(circuit_get_by_circid_channel(100, ch1), ==, NULL);
  127. tt_assert(! circuit_id_in_use_on_channel(200, ch2));
  128. tt_assert(! circuit_id_in_use_on_channel(100, ch1));
  129. done:
  130. tor_free(ch1);
  131. tor_free(ch2);
  132. tor_free(ch3);
  133. if (or_c1)
  134. circuit_free(TO_CIRCUIT(or_c1));
  135. if (or_c2)
  136. circuit_free(TO_CIRCUIT(or_c2));
  137. UNMOCK(circuitmux_attach_circuit);
  138. UNMOCK(circuitmux_detach_circuit);
  139. }
  140. struct testcase_t circuitlist_tests[] = {
  141. { "maps", test_clist_maps, TT_FORK, NULL, NULL },
  142. END_OF_TESTCASES
  143. };