test_channel.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. /* Copyright (c) 2013, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. #define TOR_CHANNEL_INTERNAL_
  4. #include "or.h"
  5. #include "channel.h"
  6. /* For channel_note_destroy_not_pending */
  7. #include "circuitlist.h"
  8. /* For var_cell_free */
  9. #include "connection_or.h"
  10. /* For packed_cell stuff */
  11. #define RELAY_PRIVATE
  12. #include "relay.h"
  13. /* For init/free stuff */
  14. #include "scheduler.h"
  15. #include "test.h"
  16. static int test_chan_accept_cells = 0;
  17. static int test_cells_written = 0;
  18. static int test_destroy_not_pending_calls = 0;
  19. static double test_overhead_estimate = 1.0f;
  20. static void channel_note_destroy_not_pending_mock(channel_t *ch,
  21. circid_t circid);
  22. static void chan_test_close(channel_t *ch);
  23. static size_t chan_test_num_bytes_queued(channel_t *ch);
  24. static int chan_test_num_cells_writeable(channel_t *ch);
  25. static int chan_test_write_cell(channel_t *ch, cell_t *cell);
  26. static int chan_test_write_packed_cell(channel_t *ch,
  27. packed_cell_t *packed_cell);
  28. static int chan_test_write_var_cell(channel_t *ch, var_cell_t *var_cell);
  29. static void make_fake_cell(cell_t *c);
  30. static void make_fake_var_cell(var_cell_t *c);
  31. static channel_t * new_fake_channel(void);
  32. static void scheduler_release_channel_mock(channel_t *ch);
  33. static void test_channel_queue_size(void *arg);
  34. static void test_channel_write(void *arg);
  35. static void
  36. channel_note_destroy_not_pending_mock(channel_t *ch,
  37. circid_t circid)
  38. {
  39. (void)ch;
  40. (void)circid;
  41. ++test_destroy_not_pending_calls;
  42. }
  43. static void
  44. chan_test_close(channel_t *ch)
  45. {
  46. test_assert(ch);
  47. done:
  48. return;
  49. }
  50. static double
  51. chan_test_get_overhead_estimate(channel_t *ch)
  52. {
  53. test_assert(ch);
  54. done:
  55. return test_overhead_estimate;
  56. }
  57. static size_t
  58. chan_test_num_bytes_queued(channel_t *ch)
  59. {
  60. test_assert(ch);
  61. done:
  62. return 0;
  63. }
  64. static int
  65. chan_test_num_cells_writeable(channel_t *ch)
  66. {
  67. test_assert(ch);
  68. done:
  69. return 32;
  70. }
  71. static int
  72. chan_test_write_cell(channel_t *ch, cell_t *cell)
  73. {
  74. int rv = 0;
  75. test_assert(ch);
  76. test_assert(cell);
  77. if (test_chan_accept_cells) {
  78. /* Free the cell and bump the counter */
  79. tor_free(cell);
  80. ++test_cells_written;
  81. rv = 1;
  82. }
  83. /* else return 0, we didn't accept it */
  84. done:
  85. return rv;
  86. }
  87. static int
  88. chan_test_write_packed_cell(channel_t *ch,
  89. packed_cell_t *packed_cell)
  90. {
  91. int rv = 0;
  92. test_assert(ch);
  93. test_assert(packed_cell);
  94. if (test_chan_accept_cells) {
  95. /* Free the cell and bump the counter */
  96. packed_cell_free(packed_cell);
  97. ++test_cells_written;
  98. rv = 1;
  99. }
  100. /* else return 0, we didn't accept it */
  101. done:
  102. return rv;
  103. }
  104. static int
  105. chan_test_write_var_cell(channel_t *ch, var_cell_t *var_cell)
  106. {
  107. int rv = 0;
  108. test_assert(ch);
  109. test_assert(var_cell);
  110. if (test_chan_accept_cells) {
  111. /* Free the cell and bump the counter */
  112. var_cell_free(var_cell);
  113. ++test_cells_written;
  114. rv = 1;
  115. }
  116. /* else return 0, we didn't accept it */
  117. done:
  118. return rv;
  119. }
  120. static void
  121. make_fake_cell(cell_t *c)
  122. {
  123. test_assert(c != NULL);
  124. c->circ_id = 1;
  125. c->command = CELL_RELAY;
  126. memset(c->payload, 0, CELL_PAYLOAD_SIZE);
  127. done:
  128. return;
  129. }
  130. static void
  131. make_fake_var_cell(var_cell_t *c)
  132. {
  133. test_assert(c != NULL);
  134. c->circ_id = 1;
  135. c->command = CELL_VERSIONS;
  136. c->payload_len = CELL_PAYLOAD_SIZE / 2;
  137. memset(c->payload, 0, c->payload_len);
  138. done:
  139. return;
  140. }
  141. static channel_t *
  142. new_fake_channel(void)
  143. {
  144. channel_t *chan = tor_malloc_zero(sizeof(channel_t));
  145. channel_init(chan);
  146. chan->close = chan_test_close;
  147. chan->get_overhead_estimate = chan_test_get_overhead_estimate;
  148. chan->num_bytes_queued = chan_test_num_bytes_queued;
  149. chan->num_cells_writeable = chan_test_num_cells_writeable;
  150. chan->write_cell = chan_test_write_cell;
  151. chan->write_packed_cell = chan_test_write_packed_cell;
  152. chan->write_var_cell = chan_test_write_var_cell;
  153. chan->state = CHANNEL_STATE_OPEN;
  154. return chan;
  155. }
  156. static void
  157. scheduler_release_channel_mock(channel_t *ch)
  158. {
  159. (void)ch;
  160. /* Increment counter */
  161. ++test_releases_count;
  162. return;
  163. }
  164. static void
  165. test_channel_queue_size(void *arg)
  166. {
  167. channel_t *ch = NULL;
  168. cell_t *cell = NULL;
  169. int n, old_count;
  170. uint64_t global_queue_estimate;
  171. (void)arg;
  172. ch = new_fake_channel();
  173. test_assert(ch);
  174. /* Initial queue size update */
  175. channel_update_xmit_queue_size(ch);
  176. test_eq(ch->bytes_queued_for_xmit, 0);
  177. global_queue_estimate = channel_get_global_queue_estimate();
  178. test_eq(global_queue_estimate, 0);
  179. /* Test the call-through to our fake lower layer */
  180. n = channel_num_cells_writeable(ch);
  181. /* chan_test_num_cells_writeable() always returns 32 */
  182. test_eq(n, 32);
  183. /*
  184. * Now we queue some cells and check that channel_num_cells_writeable()
  185. * adjusts properly
  186. */
  187. /* tell it not to accept cells */
  188. test_chan_accept_cells = 0;
  189. /* ...and keep it from trying to flush the queue */
  190. ch->state = CHANNEL_STATE_MAINT;
  191. /* Get a fresh cell */
  192. cell = tor_malloc_zero(sizeof(cell_t));
  193. make_fake_cell(cell);
  194. old_count = test_cells_written;
  195. channel_write_cell(ch, cell);
  196. /* Assert that it got queued, not written through, correctly */
  197. test_eq(test_cells_written, old_count);
  198. /* Now check chan_test_num_cells_writeable() again */
  199. n = channel_num_cells_writeable(ch);
  200. test_eq(n, 0); /* Should return 0 since we're in CHANNEL_STATE_MAINT */
  201. /* Update queue size estimates */
  202. channel_update_xmit_queue_size(ch);
  203. /* One cell, times an overhead factor of 1.0 */
  204. test_eq(ch->bytes_queued_for_xmit, 512);
  205. /* Try a different overhead factor */
  206. test_overhead_estimate = 0.5f;
  207. /* This one should be ignored since it's below 1.0 */
  208. channel_update_xmit_queue_size(ch);
  209. test_eq(ch->bytes_queued_for_xmit, 512);
  210. /* Now try a larger one */
  211. test_overhead_estimate = 2.0f;
  212. channel_update_xmit_queue_size(ch);
  213. test_eq(ch->bytes_queued_for_xmit, 1024);
  214. /* Go back to 1.0 */
  215. test_overhead_estimate = 1.0f;
  216. channel_update_xmit_queue_size(ch);
  217. test_eq(ch->bytes_queued_for_xmit, 512);
  218. /* Check the global estimate too */
  219. global_queue_estimate = channel_get_global_queue_estimate();
  220. test_eq(global_queue_estimate, 512);
  221. /* Go to open */
  222. old_count = test_cells_written;
  223. channel_change_state(ch, CHANNEL_STATE_OPEN);
  224. /*
  225. * It should try to write, but we aren't accepting cells right now, so
  226. * it'll requeue
  227. */
  228. test_eq(test_cells_written, old_count);
  229. /* Check the queue size again */
  230. channel_update_xmit_queue_size(ch);
  231. test_eq(ch->bytes_queued_for_xmit, 512);
  232. global_queue_estimate = channel_get_global_queue_estimate();
  233. test_eq(global_queue_estimate, 512);
  234. /*
  235. * Now the cell is in the queue, and we're open, so we should get 31
  236. * writeable cells.
  237. */
  238. n = channel_num_cells_writeable(ch);
  239. test_eq(n, 31);
  240. /* Accept cells again */
  241. test_chan_accept_cells = 1;
  242. /* ...and re-process the queue */
  243. old_count = test_cells_written;
  244. channel_flush_cells(ch);
  245. test_eq(test_cells_written, old_count + 1);
  246. /* Should have 32 writeable now */
  247. n = channel_num_cells_writeable(ch);
  248. test_eq(n, 32);
  249. /* Should have queue size estimate of zero */
  250. channel_update_xmit_queue_size(ch);
  251. test_eq(ch->bytes_queued_for_xmit, 0);
  252. global_queue_estimate = channel_get_global_queue_estimate();
  253. test_eq(global_queue_estimate, 0);
  254. /* Okay, now we're done with this one */
  255. MOCK(scheduler_release_channel, scheduler_release_channel_mock);
  256. channel_mark_for_close(ch);
  257. UNMOCK(scheduler_release_channel);
  258. done:
  259. tor_free(ch);
  260. return;
  261. }
  262. static void
  263. test_channel_write(void *arg)
  264. {
  265. channel_t *ch = NULL;
  266. cell_t *cell = tor_malloc_zero(sizeof(cell_t));
  267. packed_cell_t *packed_cell = NULL;
  268. var_cell_t *var_cell =
  269. tor_malloc_zero(sizeof(var_cell_t) + CELL_PAYLOAD_SIZE);
  270. int old_count;
  271. (void)arg;
  272. init_cell_pool();
  273. packed_cell = packed_cell_new();
  274. test_assert(packed_cell);
  275. ch = new_fake_channel();
  276. test_assert(ch);
  277. make_fake_cell(cell);
  278. make_fake_var_cell(var_cell);
  279. /* Tell it to accept cells */
  280. test_chan_accept_cells = 1;
  281. old_count = test_cells_written;
  282. channel_write_cell(ch, cell);
  283. test_assert(test_cells_written == old_count + 1);
  284. channel_write_var_cell(ch, var_cell);
  285. test_assert(test_cells_written == old_count + 2);
  286. channel_write_packed_cell(ch, packed_cell);
  287. test_assert(test_cells_written == old_count + 3);
  288. /* Now we test queueing; tell it not to accept cells */
  289. test_chan_accept_cells = 0;
  290. /* ...and keep it from trying to flush the queue */
  291. ch->state = CHANNEL_STATE_MAINT;
  292. /* Get a fresh cell */
  293. cell = tor_malloc_zero(sizeof(cell_t));
  294. make_fake_cell(cell);
  295. old_count = test_cells_written;
  296. channel_write_cell(ch, cell);
  297. test_assert(test_cells_written == old_count);
  298. /*
  299. * Now change back to open with channel_change_state() and assert that it
  300. * gets drained from the queue.
  301. */
  302. test_chan_accept_cells = 1;
  303. channel_change_state(ch, CHANNEL_STATE_OPEN);
  304. test_assert(test_cells_written == old_count + 1);
  305. /*
  306. * Check the note destroy case
  307. */
  308. cell = tor_malloc_zero(sizeof(cell_t));
  309. make_fake_cell(cell);
  310. cell->command = CELL_DESTROY;
  311. /* Set up the mock */
  312. MOCK(channel_note_destroy_not_pending,
  313. channel_note_destroy_not_pending_mock);
  314. old_count = test_destroy_not_pending_calls;
  315. channel_write_cell(ch, cell);
  316. test_assert(test_destroy_not_pending_calls == old_count + 1);
  317. /* Now send a non-destroy and check we don't call it */
  318. cell = tor_malloc_zero(sizeof(cell_t));
  319. make_fake_cell(cell);
  320. channel_write_cell(ch, cell);
  321. test_assert(test_destroy_not_pending_calls == old_count + 1);
  322. UNMOCK(channel_note_destroy_not_pending);
  323. /*
  324. * Now switch it to CLOSING so we can test the discard-cells case
  325. * in the channel_write_*() functions.
  326. */
  327. MOCK(scheduler_release_channel, scheduler_release_channel_mock);
  328. channel_mark_for_close(ch);
  329. UNMOCK(scheduler_release_channel);
  330. /* Send cells that will drop in the closing state */
  331. old_count = test_cells_written;
  332. cell = tor_malloc_zero(sizeof(cell_t));
  333. make_fake_cell(cell);
  334. channel_write_cell(ch, cell);
  335. test_assert(test_cells_written == old_count);
  336. var_cell = tor_malloc_zero(sizeof(var_cell_t) + CELL_PAYLOAD_SIZE);
  337. make_fake_var_cell(var_cell);
  338. channel_write_var_cell(ch, var_cell);
  339. test_assert(test_cells_written == old_count);
  340. packed_cell = packed_cell_new();
  341. channel_write_packed_cell(ch, packed_cell);
  342. test_assert(test_cells_written == old_count);
  343. free_cell_pool();
  344. done:
  345. tor_free(ch);
  346. return;
  347. }
  348. struct testcase_t channel_tests[] = {
  349. { "queue_size", test_channel_queue_size, TT_FORK, NULL, NULL },
  350. { "write", test_channel_write, TT_FORK, NULL, NULL },
  351. END_OF_TESTCASES
  352. };