test_controller_events.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. /* Copyright (c) 2013-2019, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. #define CONNECTION_PRIVATE
  4. #define TOR_CHANNEL_INTERNAL_
  5. #define CONTROL_PRIVATE
  6. #include "core/or/or.h"
  7. #include "core/or/channel.h"
  8. #include "core/or/channeltls.h"
  9. #include "core/or/circuitlist.h"
  10. #include "core/mainloop/connection.h"
  11. #include "feature/control/control.h"
  12. #include "test/test.h"
  13. #include "core/or/or_circuit_st.h"
  14. #include "core/or/origin_circuit_st.h"
  15. static void
  16. add_testing_cell_stats_entry(circuit_t *circ, uint8_t command,
  17. unsigned int waiting_time,
  18. unsigned int removed, unsigned int exitward)
  19. {
  20. testing_cell_stats_entry_t *ent = tor_malloc_zero(
  21. sizeof(testing_cell_stats_entry_t));
  22. ent->command = command;
  23. ent->waiting_time = waiting_time;
  24. ent->removed = removed;
  25. ent->exitward = exitward;
  26. if (!circ->testing_cell_stats)
  27. circ->testing_cell_stats = smartlist_new();
  28. smartlist_add(circ->testing_cell_stats, ent);
  29. }
  30. static void
  31. test_cntev_sum_up_cell_stats(void *arg)
  32. {
  33. or_circuit_t *or_circ;
  34. circuit_t *circ;
  35. cell_stats_t *cell_stats = NULL;
  36. (void)arg;
  37. /* This circuit is fake. */
  38. or_circ = tor_malloc_zero(sizeof(or_circuit_t));
  39. or_circ->base_.magic = OR_CIRCUIT_MAGIC;
  40. or_circ->base_.purpose = CIRCUIT_PURPOSE_OR;
  41. circ = TO_CIRCUIT(or_circ);
  42. /* A single RELAY cell was added to the appward queue. */
  43. cell_stats = tor_malloc_zero(sizeof(cell_stats_t));
  44. add_testing_cell_stats_entry(circ, CELL_RELAY, 0, 0, 0);
  45. sum_up_cell_stats_by_command(circ, cell_stats);
  46. tt_u64_op(1, OP_EQ, cell_stats->added_cells_appward[CELL_RELAY]);
  47. /* A single RELAY cell was added to the exitward queue. */
  48. add_testing_cell_stats_entry(circ, CELL_RELAY, 0, 0, 1);
  49. sum_up_cell_stats_by_command(circ, cell_stats);
  50. tt_u64_op(1, OP_EQ, cell_stats->added_cells_exitward[CELL_RELAY]);
  51. /* A single RELAY cell was removed from the appward queue where it spent
  52. * 20 msec. */
  53. add_testing_cell_stats_entry(circ, CELL_RELAY, 2, 1, 0);
  54. sum_up_cell_stats_by_command(circ, cell_stats);
  55. tt_u64_op(20, OP_EQ, cell_stats->total_time_appward[CELL_RELAY]);
  56. tt_u64_op(1, OP_EQ, cell_stats->removed_cells_appward[CELL_RELAY]);
  57. /* A single RELAY cell was removed from the exitward queue where it
  58. * spent 30 msec. */
  59. add_testing_cell_stats_entry(circ, CELL_RELAY, 3, 1, 1);
  60. sum_up_cell_stats_by_command(circ, cell_stats);
  61. tt_u64_op(30, OP_EQ, cell_stats->total_time_exitward[CELL_RELAY]);
  62. tt_u64_op(1, OP_EQ, cell_stats->removed_cells_exitward[CELL_RELAY]);
  63. done:
  64. tor_free(cell_stats);
  65. tor_free(or_circ);
  66. }
  67. static void
  68. test_cntev_append_cell_stats(void *arg)
  69. {
  70. smartlist_t *event_parts;
  71. char *cp = NULL;
  72. const char *key = "Z";
  73. uint64_t include_if_non_zero[CELL_COMMAND_MAX_ + 1],
  74. number_to_include[CELL_COMMAND_MAX_ + 1];
  75. (void)arg;
  76. event_parts = smartlist_new();
  77. memset(include_if_non_zero, 0,
  78. (CELL_COMMAND_MAX_ + 1) * sizeof(uint64_t));
  79. memset(number_to_include, 0,
  80. (CELL_COMMAND_MAX_ + 1) * sizeof(uint64_t));
  81. /* All array entries empty. */
  82. append_cell_stats_by_command(event_parts, key,
  83. include_if_non_zero,
  84. number_to_include);
  85. tt_int_op(0, OP_EQ, smartlist_len(event_parts));
  86. /* There's a RELAY cell to include, but the corresponding field in
  87. * include_if_non_zero is still zero. */
  88. number_to_include[CELL_RELAY] = 1;
  89. append_cell_stats_by_command(event_parts, key,
  90. include_if_non_zero,
  91. number_to_include);
  92. tt_int_op(0, OP_EQ, smartlist_len(event_parts));
  93. /* Now include single RELAY cell. */
  94. include_if_non_zero[CELL_RELAY] = 2;
  95. append_cell_stats_by_command(event_parts, key,
  96. include_if_non_zero,
  97. number_to_include);
  98. cp = smartlist_pop_last(event_parts);
  99. tt_str_op("Z=relay:1", OP_EQ, cp);
  100. tor_free(cp);
  101. /* Add four CREATE cells. */
  102. include_if_non_zero[CELL_CREATE] = 3;
  103. number_to_include[CELL_CREATE] = 4;
  104. append_cell_stats_by_command(event_parts, key,
  105. include_if_non_zero,
  106. number_to_include);
  107. cp = smartlist_pop_last(event_parts);
  108. tt_str_op("Z=create:4,relay:1", OP_EQ, cp);
  109. done:
  110. tor_free(cp);
  111. smartlist_free(event_parts);
  112. }
  113. static void
  114. test_cntev_format_cell_stats(void *arg)
  115. {
  116. char *event_string = NULL;
  117. origin_circuit_t *ocirc = NULL;
  118. or_circuit_t *or_circ = NULL;
  119. cell_stats_t *cell_stats = NULL;
  120. channel_tls_t *n_chan=NULL, *p_chan=NULL;
  121. (void)arg;
  122. n_chan = tor_malloc_zero(sizeof(channel_tls_t));
  123. n_chan->base_.global_identifier = 1;
  124. ocirc = tor_malloc_zero(sizeof(origin_circuit_t));
  125. ocirc->base_.magic = ORIGIN_CIRCUIT_MAGIC;
  126. ocirc->base_.purpose = CIRCUIT_PURPOSE_C_GENERAL;
  127. ocirc->global_identifier = 2;
  128. ocirc->base_.n_circ_id = 3;
  129. ocirc->base_.n_chan = &(n_chan->base_);
  130. /* Origin circuit was completely idle. */
  131. cell_stats = tor_malloc_zero(sizeof(cell_stats_t));
  132. format_cell_stats(&event_string, TO_CIRCUIT(ocirc), cell_stats);
  133. tt_str_op("ID=2 OutboundQueue=3 OutboundConn=1", OP_EQ, event_string);
  134. tor_free(event_string);
  135. /* Origin circuit had 4 RELAY cells added to its exitward queue. */
  136. cell_stats->added_cells_exitward[CELL_RELAY] = 4;
  137. format_cell_stats(&event_string, TO_CIRCUIT(ocirc), cell_stats);
  138. tt_str_op("ID=2 OutboundQueue=3 OutboundConn=1 OutboundAdded=relay:4",
  139. OP_EQ, event_string);
  140. tor_free(event_string);
  141. /* Origin circuit also had 5 CREATE2 cells added to its exitward
  142. * queue. */
  143. cell_stats->added_cells_exitward[CELL_CREATE2] = 5;
  144. format_cell_stats(&event_string, TO_CIRCUIT(ocirc), cell_stats);
  145. tt_str_op("ID=2 OutboundQueue=3 OutboundConn=1 OutboundAdded=relay:4,"
  146. "create2:5", OP_EQ, event_string);
  147. tor_free(event_string);
  148. /* Origin circuit also had 7 RELAY cells removed from its exitward queue
  149. * which together spent 6 msec in the queue. */
  150. cell_stats->total_time_exitward[CELL_RELAY] = 6;
  151. cell_stats->removed_cells_exitward[CELL_RELAY] = 7;
  152. format_cell_stats(&event_string, TO_CIRCUIT(ocirc), cell_stats);
  153. tt_str_op("ID=2 OutboundQueue=3 OutboundConn=1 OutboundAdded=relay:4,"
  154. "create2:5 OutboundRemoved=relay:7 OutboundTime=relay:6",
  155. OP_EQ, event_string);
  156. tor_free(event_string);
  157. p_chan = tor_malloc_zero(sizeof(channel_tls_t));
  158. p_chan->base_.global_identifier = 2;
  159. or_circ = tor_malloc_zero(sizeof(or_circuit_t));
  160. or_circ->base_.magic = OR_CIRCUIT_MAGIC;
  161. or_circ->base_.purpose = CIRCUIT_PURPOSE_OR;
  162. or_circ->p_circ_id = 8;
  163. or_circ->p_chan = &(p_chan->base_);
  164. or_circ->base_.n_circ_id = 9;
  165. or_circ->base_.n_chan = &(n_chan->base_);
  166. tor_free(cell_stats);
  167. /* OR circuit was idle. */
  168. cell_stats = tor_malloc_zero(sizeof(cell_stats_t));
  169. format_cell_stats(&event_string, TO_CIRCUIT(or_circ), cell_stats);
  170. tt_str_op("InboundQueue=8 InboundConn=2 OutboundQueue=9 OutboundConn=1",
  171. OP_EQ, event_string);
  172. tor_free(event_string);
  173. /* OR circuit had 3 RELAY cells added to its appward queue. */
  174. cell_stats->added_cells_appward[CELL_RELAY] = 3;
  175. format_cell_stats(&event_string, TO_CIRCUIT(or_circ), cell_stats);
  176. tt_str_op("InboundQueue=8 InboundConn=2 InboundAdded=relay:3 "
  177. "OutboundQueue=9 OutboundConn=1", OP_EQ, event_string);
  178. tor_free(event_string);
  179. /* OR circuit had 7 RELAY cells removed from its appward queue which
  180. * together spent 6 msec in the queue. */
  181. cell_stats->total_time_appward[CELL_RELAY] = 6;
  182. cell_stats->removed_cells_appward[CELL_RELAY] = 7;
  183. format_cell_stats(&event_string, TO_CIRCUIT(or_circ), cell_stats);
  184. tt_str_op("InboundQueue=8 InboundConn=2 InboundAdded=relay:3 "
  185. "InboundRemoved=relay:7 InboundTime=relay:6 "
  186. "OutboundQueue=9 OutboundConn=1", OP_EQ, event_string);
  187. done:
  188. tor_free(cell_stats);
  189. tor_free(event_string);
  190. tor_free(or_circ);
  191. tor_free(ocirc);
  192. tor_free(p_chan);
  193. tor_free(n_chan);
  194. }
  195. static void
  196. test_cntev_event_mask(void *arg)
  197. {
  198. unsigned int test_event, selected_event;
  199. (void)arg;
  200. /* Check that nothing is interesting when no events are set */
  201. control_testing_set_global_event_mask(EVENT_MASK_NONE_);
  202. /* Check that nothing is interesting between EVENT_MIN_ and EVENT_MAX_ */
  203. for (test_event = EVENT_MIN_; test_event <= EVENT_MAX_; test_event++)
  204. tt_assert(!control_event_is_interesting(test_event));
  205. /* Check that nothing is interesting outside EVENT_MIN_ to EVENT_MAX_
  206. * This will break if control_event_is_interesting() checks its arguments */
  207. for (test_event = 0; test_event < EVENT_MIN_; test_event++)
  208. tt_assert(!control_event_is_interesting(test_event));
  209. for (test_event = EVENT_MAX_ + 1;
  210. test_event < EVENT_CAPACITY_;
  211. test_event++)
  212. tt_assert(!control_event_is_interesting(test_event));
  213. /* Check that all valid events are interesting when all events are set */
  214. control_testing_set_global_event_mask(EVENT_MASK_ALL_);
  215. /* Check that everything is interesting between EVENT_MIN_ and EVENT_MAX_ */
  216. for (test_event = EVENT_MIN_; test_event <= EVENT_MAX_; test_event++)
  217. tt_assert(control_event_is_interesting(test_event));
  218. /* Check that nothing is interesting outside EVENT_MIN_ to EVENT_MAX_
  219. * This will break if control_event_is_interesting() checks its arguments */
  220. for (test_event = 0; test_event < EVENT_MIN_; test_event++)
  221. tt_assert(!control_event_is_interesting(test_event));
  222. for (test_event = EVENT_MAX_ + 1;
  223. test_event < EVENT_CAPACITY_;
  224. test_event++)
  225. tt_assert(!control_event_is_interesting(test_event));
  226. /* Check that only that event is interesting when a single event is set */
  227. for (selected_event = EVENT_MIN_;
  228. selected_event <= EVENT_MAX_;
  229. selected_event++) {
  230. control_testing_set_global_event_mask(EVENT_MASK_(selected_event));
  231. /* Check that only this event is interesting
  232. * between EVENT_MIN_ and EVENT_MAX_ */
  233. for (test_event = EVENT_MIN_; test_event <= EVENT_MAX_; test_event++) {
  234. if (test_event == selected_event) {
  235. tt_assert(control_event_is_interesting(test_event));
  236. } else {
  237. tt_assert(!control_event_is_interesting(test_event));
  238. }
  239. }
  240. /* Check that nothing is interesting outside EVENT_MIN_ to EVENT_MAX_
  241. * This will break if control_event_is_interesting checks its arguments */
  242. for (test_event = 0; test_event < EVENT_MIN_; test_event++)
  243. tt_assert(!control_event_is_interesting(test_event));
  244. for (test_event = EVENT_MAX_ + 1;
  245. test_event < EVENT_CAPACITY_;
  246. test_event++)
  247. tt_assert(!control_event_is_interesting(test_event));
  248. }
  249. /* Check that only that event is not-interesting
  250. * when a single event is un-set */
  251. for (selected_event = EVENT_MIN_;
  252. selected_event <= EVENT_MAX_;
  253. selected_event++) {
  254. control_testing_set_global_event_mask(
  255. EVENT_MASK_ALL_
  256. & ~(EVENT_MASK_(selected_event))
  257. );
  258. /* Check that only this event is not-interesting
  259. * between EVENT_MIN_ and EVENT_MAX_ */
  260. for (test_event = EVENT_MIN_; test_event <= EVENT_MAX_; test_event++) {
  261. if (test_event == selected_event) {
  262. tt_assert(!control_event_is_interesting(test_event));
  263. } else {
  264. tt_assert(control_event_is_interesting(test_event));
  265. }
  266. }
  267. /* Check that nothing is interesting outside EVENT_MIN_ to EVENT_MAX_
  268. * This will break if control_event_is_interesting checks its arguments */
  269. for (test_event = 0; test_event < EVENT_MIN_; test_event++)
  270. tt_assert(!control_event_is_interesting(test_event));
  271. for (test_event = EVENT_MAX_ + 1;
  272. test_event < EVENT_CAPACITY_;
  273. test_event++)
  274. tt_assert(!control_event_is_interesting(test_event));
  275. }
  276. done:
  277. ;
  278. }
  279. static char *saved_event_str = NULL;
  280. static void
  281. mock_queue_control_event_string(uint16_t event, char *msg)
  282. {
  283. (void)event;
  284. tor_free(saved_event_str);
  285. saved_event_str = msg;
  286. }
  287. /* Helper macro for checking bootstrap control event strings */
  288. #define assert_bootmsg(s) \
  289. tt_ptr_op(strstr(saved_event_str, "650 STATUS_CLIENT NOTICE " \
  290. "BOOTSTRAP PROGRESS=" s), OP_EQ, saved_event_str)
  291. /* Test deferral of directory bootstrap messages (requesting_descriptors) */
  292. static void
  293. test_cntev_dirboot_defer_desc(void *arg)
  294. {
  295. (void)arg;
  296. MOCK(queue_control_event_string, mock_queue_control_event_string);
  297. control_testing_set_global_event_mask(EVENT_MASK_(EVENT_STATUS_CLIENT));
  298. control_event_bootstrap(BOOTSTRAP_STATUS_STARTING, 0);
  299. assert_bootmsg("0 TAG=starting");
  300. /* This event should get deferred */
  301. control_event_boot_dir(BOOTSTRAP_STATUS_REQUESTING_DESCRIPTORS, 0);
  302. assert_bootmsg("0 TAG=starting");
  303. control_event_bootstrap(BOOTSTRAP_STATUS_CONN_DIR, 0);
  304. assert_bootmsg("5 TAG=conn_dir");
  305. control_event_bootstrap(BOOTSTRAP_STATUS_HANDSHAKE, 0);
  306. assert_bootmsg("10 TAG=handshake_dir");
  307. /* The deferred event should appear */
  308. control_event_boot_first_orconn();
  309. assert_bootmsg("45 TAG=requesting_descriptors");
  310. done:
  311. tor_free(saved_event_str);
  312. UNMOCK(queue_control_event_string);
  313. }
  314. /* Test deferral of directory bootstrap messages (conn_or) */
  315. static void
  316. test_cntev_dirboot_defer_orconn(void *arg)
  317. {
  318. (void)arg;
  319. MOCK(queue_control_event_string, mock_queue_control_event_string);
  320. control_testing_set_global_event_mask(EVENT_MASK_(EVENT_STATUS_CLIENT));
  321. control_event_bootstrap(BOOTSTRAP_STATUS_STARTING, 0);
  322. assert_bootmsg("0 TAG=starting");
  323. /* This event should get deferred */
  324. control_event_boot_dir(BOOTSTRAP_STATUS_CONN_OR, 0);
  325. assert_bootmsg("0 TAG=starting");
  326. control_event_bootstrap(BOOTSTRAP_STATUS_CONN_DIR, 0);
  327. assert_bootmsg("5 TAG=conn_dir");
  328. control_event_bootstrap(BOOTSTRAP_STATUS_HANDSHAKE, 0);
  329. assert_bootmsg("10 TAG=handshake_dir");
  330. /* The deferred event should appear */
  331. control_event_boot_first_orconn();
  332. assert_bootmsg("80 TAG=conn_or");
  333. done:
  334. tor_free(saved_event_str);
  335. UNMOCK(queue_control_event_string);
  336. }
  337. #define TEST(name, flags) \
  338. { #name, test_cntev_ ## name, flags, 0, NULL }
  339. struct testcase_t controller_event_tests[] = {
  340. TEST(sum_up_cell_stats, TT_FORK),
  341. TEST(append_cell_stats, TT_FORK),
  342. TEST(format_cell_stats, TT_FORK),
  343. TEST(event_mask, TT_FORK),
  344. TEST(dirboot_defer_desc, TT_FORK),
  345. TEST(dirboot_defer_orconn, TT_FORK),
  346. END_OF_TESTCASES
  347. };