test_controller_events.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. /* Copyright (c) 2013, 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 "or.h"
  7. #include "channel.h"
  8. #include "channeltls.h"
  9. #include "connection.h"
  10. #include "control.h"
  11. #include "test.h"
  12. static void
  13. help_test_bucket_note_empty(uint32_t expected_msec_since_midnight,
  14. int tokens_before, size_t tokens_removed,
  15. uint32_t msec_since_epoch)
  16. {
  17. uint32_t timestamp_var = 0;
  18. struct timeval tvnow;
  19. tvnow.tv_sec = msec_since_epoch / 1000;
  20. tvnow.tv_usec = (msec_since_epoch % 1000) * 1000;
  21. connection_buckets_note_empty_ts(&timestamp_var, tokens_before,
  22. tokens_removed, &tvnow);
  23. tt_int_op(expected_msec_since_midnight, ==, timestamp_var);
  24. done:
  25. ;
  26. }
  27. static void
  28. test_cntev_bucket_note_empty(void *arg)
  29. {
  30. (void)arg;
  31. /* Two cases with nothing to note, because bucket was empty before;
  32. * 86442200 == 1970-01-02 00:00:42.200000 */
  33. help_test_bucket_note_empty(0, 0, 0, 86442200);
  34. help_test_bucket_note_empty(0, -100, 100, 86442200);
  35. /* Nothing to note, because bucket has not been emptied. */
  36. help_test_bucket_note_empty(0, 101, 100, 86442200);
  37. /* Bucket was emptied, note 42200 msec since midnight. */
  38. help_test_bucket_note_empty(42200, 101, 101, 86442200);
  39. help_test_bucket_note_empty(42200, 101, 102, 86442200);
  40. }
  41. static void
  42. test_cntev_bucket_millis_empty(void *arg)
  43. {
  44. struct timeval tvnow;
  45. (void)arg;
  46. /* 1970-01-02 00:00:42.200000 */
  47. tvnow.tv_sec = 86400 + 42;
  48. tvnow.tv_usec = 200000;
  49. /* Bucket has not been refilled. */
  50. tt_int_op(0, ==, bucket_millis_empty(0, 42120, 0, 100, &tvnow));
  51. tt_int_op(0, ==, bucket_millis_empty(-10, 42120, -10, 100, &tvnow));
  52. /* Bucket was not empty. */
  53. tt_int_op(0, ==, bucket_millis_empty(10, 42120, 20, 100, &tvnow));
  54. /* Bucket has been emptied 80 msec ago and has just been refilled. */
  55. tt_int_op(80, ==, bucket_millis_empty(-20, 42120, -10, 100, &tvnow));
  56. tt_int_op(80, ==, bucket_millis_empty(-10, 42120, 0, 100, &tvnow));
  57. tt_int_op(80, ==, bucket_millis_empty(0, 42120, 10, 100, &tvnow));
  58. /* Bucket has been emptied 180 msec ago, last refill was 100 msec ago
  59. * which was insufficient to make it positive, so cap msec at 100. */
  60. tt_int_op(100, ==, bucket_millis_empty(0, 42020, 1, 100, &tvnow));
  61. /* 1970-01-02 00:00:00:050000 */
  62. tvnow.tv_sec = 86400;
  63. tvnow.tv_usec = 50000;
  64. /* Last emptied 30 msec before midnight, tvnow is 50 msec after
  65. * midnight, that's 80 msec in total. */
  66. tt_int_op(80, ==, bucket_millis_empty(0, 86400000 - 30, 1, 100, &tvnow));
  67. done:
  68. ;
  69. }
  70. static void
  71. add_testing_cell_stats_entry(circuit_t *circ, uint8_t command,
  72. unsigned int waiting_time,
  73. unsigned int removed, unsigned int exitward)
  74. {
  75. testing_cell_stats_entry_t *ent = tor_malloc_zero(
  76. sizeof(testing_cell_stats_entry_t));
  77. ent->command = command;
  78. ent->waiting_time = waiting_time;
  79. ent->removed = removed;
  80. ent->exitward = exitward;
  81. if (!circ->testing_cell_stats)
  82. circ->testing_cell_stats = smartlist_new();
  83. smartlist_add(circ->testing_cell_stats, ent);
  84. }
  85. static void
  86. test_cntev_sum_up_cell_stats(void *arg)
  87. {
  88. or_circuit_t *or_circ;
  89. circuit_t *circ;
  90. cell_stats_t *cell_stats;
  91. (void)arg;
  92. or_circ = tor_malloc_zero(sizeof(or_circuit_t));
  93. or_circ->base_.magic = OR_CIRCUIT_MAGIC;
  94. or_circ->base_.purpose = CIRCUIT_PURPOSE_OR;
  95. circ = TO_CIRCUIT(or_circ);
  96. /* A single RELAY cell was added to the appward queue. */
  97. cell_stats = tor_malloc_zero(sizeof(cell_stats_t));
  98. add_testing_cell_stats_entry(circ, CELL_RELAY, 0, 0, 0);
  99. sum_up_cell_stats_by_command(circ, cell_stats);
  100. tt_int_op(1, ==, cell_stats->added_cells_appward[CELL_RELAY]);
  101. /* A single RELAY cell was added to the exitward queue. */
  102. add_testing_cell_stats_entry(circ, CELL_RELAY, 0, 0, 1);
  103. sum_up_cell_stats_by_command(circ, cell_stats);
  104. tt_int_op(1, ==, cell_stats->added_cells_exitward[CELL_RELAY]);
  105. /* A single RELAY cell was removed from the appward queue where it spent
  106. * 20 msec. */
  107. add_testing_cell_stats_entry(circ, CELL_RELAY, 2, 1, 0);
  108. sum_up_cell_stats_by_command(circ, cell_stats);
  109. tt_int_op(20, ==, cell_stats->total_time_appward[CELL_RELAY]);
  110. tt_int_op(1, ==, cell_stats->removed_cells_appward[CELL_RELAY]);
  111. /* A single RELAY cell was removed from the exitward queue where it
  112. * spent 30 msec. */
  113. add_testing_cell_stats_entry(circ, CELL_RELAY, 3, 1, 1);
  114. sum_up_cell_stats_by_command(circ, cell_stats);
  115. tt_int_op(30, ==, cell_stats->total_time_exitward[CELL_RELAY]);
  116. tt_int_op(1, ==, cell_stats->removed_cells_exitward[CELL_RELAY]);
  117. done:
  118. ;
  119. }
  120. static void
  121. test_cntev_append_cell_stats(void *arg)
  122. {
  123. smartlist_t *event_parts;
  124. const char *key = "Z";
  125. uint64_t include_if_non_zero[CELL_COMMAND_MAX_ + 1],
  126. number_to_include[CELL_COMMAND_MAX_ + 1];
  127. (void)arg;
  128. event_parts = smartlist_new();
  129. memset(include_if_non_zero, 0,
  130. (CELL_COMMAND_MAX_ + 1) * sizeof(uint64_t));
  131. memset(number_to_include, 0,
  132. (CELL_COMMAND_MAX_ + 1) * sizeof(uint64_t));
  133. /* All array entries empty. */
  134. append_cell_stats_by_command(event_parts, key,
  135. include_if_non_zero,
  136. number_to_include);
  137. tt_int_op(0, ==, smartlist_len(event_parts));
  138. /* There's a RELAY cell to include, but the corresponding field in
  139. * include_if_non_zero is still zero. */
  140. number_to_include[CELL_RELAY] = 1;
  141. append_cell_stats_by_command(event_parts, key,
  142. include_if_non_zero,
  143. number_to_include);
  144. tt_int_op(0, ==, smartlist_len(event_parts));
  145. /* Now include single RELAY cell. */
  146. include_if_non_zero[CELL_RELAY] = 2;
  147. append_cell_stats_by_command(event_parts, key,
  148. include_if_non_zero,
  149. number_to_include);
  150. tt_str_op("Z=relay:1", ==, smartlist_pop_last(event_parts));
  151. /* Add four CREATE cells. */
  152. include_if_non_zero[CELL_CREATE] = 3;
  153. number_to_include[CELL_CREATE] = 4;
  154. append_cell_stats_by_command(event_parts, key,
  155. include_if_non_zero,
  156. number_to_include);
  157. tt_str_op("Z=create:4,relay:1", ==, smartlist_pop_last(event_parts));
  158. done:
  159. ;
  160. }
  161. static void
  162. test_cntev_format_cell_stats(void *arg)
  163. {
  164. char *event_string;
  165. origin_circuit_t *ocirc;
  166. or_circuit_t *or_circ;
  167. cell_stats_t *cell_stats;
  168. channel_tls_t *n_chan, *p_chan;
  169. (void)arg;
  170. n_chan = tor_malloc_zero(sizeof(channel_tls_t));
  171. n_chan->base_.global_identifier = 1;
  172. ocirc = tor_malloc_zero(sizeof(origin_circuit_t));
  173. ocirc->base_.magic = ORIGIN_CIRCUIT_MAGIC;
  174. ocirc->base_.purpose = CIRCUIT_PURPOSE_C_GENERAL;
  175. ocirc->global_identifier = 2;
  176. ocirc->base_.n_circ_id = 3;
  177. ocirc->base_.n_chan = &(n_chan->base_);
  178. /* Origin circuit was completely idle. */
  179. cell_stats = tor_malloc_zero(sizeof(cell_stats_t));
  180. format_cell_stats(&event_string, TO_CIRCUIT(ocirc), cell_stats);
  181. tt_str_op("ID=2 OutboundQueue=3 OutboundConn=1", ==, event_string);
  182. /* Origin circuit had 4 RELAY cells added to its exitward queue. */
  183. cell_stats->added_cells_exitward[CELL_RELAY] = 4;
  184. format_cell_stats(&event_string, TO_CIRCUIT(ocirc), cell_stats);
  185. tt_str_op("ID=2 OutboundQueue=3 OutboundConn=1 OutboundAdded=relay:4",
  186. ==, event_string);
  187. /* Origin circuit also had 5 CREATE2 cells added to its exitward
  188. * queue. */
  189. cell_stats->added_cells_exitward[CELL_CREATE2] = 5;
  190. format_cell_stats(&event_string, TO_CIRCUIT(ocirc), cell_stats);
  191. tt_str_op("ID=2 OutboundQueue=3 OutboundConn=1 OutboundAdded=relay:4,"
  192. "create2:5", ==, event_string);
  193. /* Origin circuit also had 7 RELAY cells removed from its exitward queue
  194. * which together spent 6 msec in the queue. */
  195. cell_stats->total_time_exitward[CELL_RELAY] = 6;
  196. cell_stats->removed_cells_exitward[CELL_RELAY] = 7;
  197. format_cell_stats(&event_string, TO_CIRCUIT(ocirc), cell_stats);
  198. tt_str_op("ID=2 OutboundQueue=3 OutboundConn=1 OutboundAdded=relay:4,"
  199. "create2:5 OutboundRemoved=relay:7 OutboundTime=relay:6",
  200. ==, event_string);
  201. p_chan = tor_malloc_zero(sizeof(channel_tls_t));
  202. p_chan->base_.global_identifier = 2;
  203. or_circ = tor_malloc_zero(sizeof(or_circuit_t));
  204. or_circ->base_.magic = OR_CIRCUIT_MAGIC;
  205. or_circ->base_.purpose = CIRCUIT_PURPOSE_OR;
  206. or_circ->p_circ_id = 8;
  207. or_circ->p_chan = &(p_chan->base_);
  208. or_circ->base_.n_circ_id = 9;
  209. or_circ->base_.n_chan = &(n_chan->base_);
  210. /* OR circuit was idle. */
  211. cell_stats = tor_malloc_zero(sizeof(cell_stats_t));
  212. format_cell_stats(&event_string, TO_CIRCUIT(or_circ), cell_stats);
  213. tt_str_op("InboundQueue=8 InboundConn=2 OutboundQueue=9 OutboundConn=1",
  214. ==, event_string);
  215. /* OR circuit had 3 RELAY cells added to its appward queue. */
  216. cell_stats->added_cells_appward[CELL_RELAY] = 3;
  217. format_cell_stats(&event_string, TO_CIRCUIT(or_circ), cell_stats);
  218. tt_str_op("InboundQueue=8 InboundConn=2 InboundAdded=relay:3 "
  219. "OutboundQueue=9 OutboundConn=1", ==, event_string);
  220. /* OR circuit had 7 RELAY cells removed from its appward queue which
  221. * together spent 6 msec in the queue. */
  222. cell_stats->total_time_appward[CELL_RELAY] = 6;
  223. cell_stats->removed_cells_appward[CELL_RELAY] = 7;
  224. format_cell_stats(&event_string, TO_CIRCUIT(or_circ), cell_stats);
  225. tt_str_op("InboundQueue=8 InboundConn=2 InboundAdded=relay:3 "
  226. "InboundRemoved=relay:7 InboundTime=relay:6 "
  227. "OutboundQueue=9 OutboundConn=1", ==, event_string);
  228. done:
  229. ;
  230. }
  231. #define TEST(name, flags) \
  232. { #name, test_cntev_ ## name, flags, 0, NULL }
  233. struct testcase_t controller_event_tests[] = {
  234. TEST(bucket_note_empty, 0),
  235. TEST(bucket_millis_empty, 0),
  236. TEST(sum_up_cell_stats, 0),
  237. TEST(append_cell_stats, 0),
  238. TEST(format_cell_stats, 0),
  239. END_OF_TESTCASES
  240. };