test_circuitlist.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. /* Copyright (c) 2013-2019, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. #define TOR_CHANNEL_INTERNAL_
  4. #define CIRCUITBUILD_PRIVATE
  5. #define CIRCUITLIST_PRIVATE
  6. #define HS_CIRCUITMAP_PRIVATE
  7. #include "core/or/or.h"
  8. #include "core/or/channel.h"
  9. #include "core/or/circuitbuild.h"
  10. #include "core/or/circuitlist.h"
  11. #include "core/or/circuitmux_ewma.h"
  12. #include "feature/hs/hs_circuitmap.h"
  13. #include "test/test.h"
  14. #include "test/log_test_helpers.h"
  15. #include "core/or/or_circuit_st.h"
  16. #include "core/or/origin_circuit_st.h"
  17. #include "lib/container/bitarray.h"
  18. static channel_t *
  19. new_fake_channel(void)
  20. {
  21. channel_t *chan = tor_malloc_zero(sizeof(channel_t));
  22. channel_init(chan);
  23. return chan;
  24. }
  25. static struct {
  26. int ncalls;
  27. void *cmux;
  28. void *circ;
  29. cell_direction_t dir;
  30. } cam;
  31. static void
  32. circuitmux_attach_mock(circuitmux_t *cmux, circuit_t *circ,
  33. cell_direction_t dir)
  34. {
  35. ++cam.ncalls;
  36. cam.cmux = cmux;
  37. cam.circ = circ;
  38. cam.dir = dir;
  39. }
  40. static struct {
  41. int ncalls;
  42. void *cmux;
  43. void *circ;
  44. } cdm;
  45. static void
  46. circuitmux_detach_mock(circuitmux_t *cmux, circuit_t *circ)
  47. {
  48. ++cdm.ncalls;
  49. cdm.cmux = cmux;
  50. cdm.circ = circ;
  51. }
  52. #define GOT_CMUX_ATTACH(mux_, circ_, dir_) do { \
  53. tt_int_op(cam.ncalls, OP_EQ, 1); \
  54. tt_ptr_op(cam.cmux, OP_EQ, (mux_)); \
  55. tt_ptr_op(cam.circ, OP_EQ, (circ_)); \
  56. tt_int_op(cam.dir, OP_EQ, (dir_)); \
  57. memset(&cam, 0, sizeof(cam)); \
  58. } while (0)
  59. #define GOT_CMUX_DETACH(mux_, circ_) do { \
  60. tt_int_op(cdm.ncalls, OP_EQ, 1); \
  61. tt_ptr_op(cdm.cmux, OP_EQ, (mux_)); \
  62. tt_ptr_op(cdm.circ, OP_EQ, (circ_)); \
  63. memset(&cdm, 0, sizeof(cdm)); \
  64. } while (0)
  65. static void
  66. test_clist_maps(void *arg)
  67. {
  68. channel_t *ch1 = new_fake_channel();
  69. channel_t *ch2 = new_fake_channel();
  70. channel_t *ch3 = new_fake_channel();
  71. or_circuit_t *or_c1=NULL, *or_c2=NULL;
  72. (void) arg;
  73. MOCK(circuitmux_attach_circuit, circuitmux_attach_mock);
  74. MOCK(circuitmux_detach_circuit, circuitmux_detach_mock);
  75. memset(&cam, 0, sizeof(cam));
  76. memset(&cdm, 0, sizeof(cdm));
  77. tt_assert(ch1);
  78. tt_assert(ch2);
  79. tt_assert(ch3);
  80. ch1->cmux = tor_malloc(1);
  81. ch2->cmux = tor_malloc(1);
  82. ch3->cmux = tor_malloc(1);
  83. or_c1 = or_circuit_new(100, ch2);
  84. tt_assert(or_c1);
  85. GOT_CMUX_ATTACH(ch2->cmux, or_c1, CELL_DIRECTION_IN);
  86. tt_int_op(or_c1->p_circ_id, OP_EQ, 100);
  87. tt_ptr_op(or_c1->p_chan, OP_EQ, ch2);
  88. or_c2 = or_circuit_new(100, ch1);
  89. tt_assert(or_c2);
  90. GOT_CMUX_ATTACH(ch1->cmux, or_c2, CELL_DIRECTION_IN);
  91. tt_int_op(or_c2->p_circ_id, OP_EQ, 100);
  92. tt_ptr_op(or_c2->p_chan, OP_EQ, ch1);
  93. circuit_set_n_circid_chan(TO_CIRCUIT(or_c1), 200, ch1);
  94. GOT_CMUX_ATTACH(ch1->cmux, or_c1, CELL_DIRECTION_OUT);
  95. circuit_set_n_circid_chan(TO_CIRCUIT(or_c2), 200, ch2);
  96. GOT_CMUX_ATTACH(ch2->cmux, or_c2, CELL_DIRECTION_OUT);
  97. tt_ptr_op(circuit_get_by_circid_channel(200, ch1), OP_EQ, TO_CIRCUIT(or_c1));
  98. tt_ptr_op(circuit_get_by_circid_channel(200, ch2), OP_EQ, TO_CIRCUIT(or_c2));
  99. tt_ptr_op(circuit_get_by_circid_channel(100, ch2), OP_EQ, TO_CIRCUIT(or_c1));
  100. /* Try the same thing again, to test the "fast" path. */
  101. tt_ptr_op(circuit_get_by_circid_channel(100, ch2), OP_EQ, TO_CIRCUIT(or_c1));
  102. tt_assert(circuit_id_in_use_on_channel(100, ch2));
  103. tt_assert(! circuit_id_in_use_on_channel(101, ch2));
  104. /* Try changing the circuitid and channel of that circuit. */
  105. circuit_set_p_circid_chan(or_c1, 500, ch3);
  106. GOT_CMUX_DETACH(ch2->cmux, TO_CIRCUIT(or_c1));
  107. GOT_CMUX_ATTACH(ch3->cmux, TO_CIRCUIT(or_c1), CELL_DIRECTION_IN);
  108. tt_ptr_op(circuit_get_by_circid_channel(100, ch2), OP_EQ, NULL);
  109. tt_assert(! circuit_id_in_use_on_channel(100, ch2));
  110. tt_ptr_op(circuit_get_by_circid_channel(500, ch3), OP_EQ, TO_CIRCUIT(or_c1));
  111. /* Now let's see about destroy handling. */
  112. tt_assert(! circuit_id_in_use_on_channel(205, ch2));
  113. tt_assert(circuit_id_in_use_on_channel(200, ch2));
  114. channel_note_destroy_pending(ch2, 200);
  115. channel_note_destroy_pending(ch2, 205);
  116. channel_note_destroy_pending(ch1, 100);
  117. tt_assert(circuit_id_in_use_on_channel(205, ch2))
  118. tt_assert(circuit_id_in_use_on_channel(200, ch2));
  119. tt_assert(circuit_id_in_use_on_channel(100, ch1));
  120. tt_assert(TO_CIRCUIT(or_c2)->n_delete_pending != 0);
  121. tt_ptr_op(circuit_get_by_circid_channel(200, ch2), OP_EQ, TO_CIRCUIT(or_c2));
  122. tt_ptr_op(circuit_get_by_circid_channel(100, ch1), OP_EQ, TO_CIRCUIT(or_c2));
  123. /* Okay, now free ch2 and make sure that the circuit ID is STILL not
  124. * usable, because we haven't declared the destroy to be nonpending */
  125. tt_int_op(cdm.ncalls, OP_EQ, 0);
  126. circuit_free_(TO_CIRCUIT(or_c2));
  127. or_c2 = NULL; /* prevent free */
  128. tt_int_op(cdm.ncalls, OP_EQ, 2);
  129. memset(&cdm, 0, sizeof(cdm));
  130. tt_assert(circuit_id_in_use_on_channel(200, ch2));
  131. tt_assert(circuit_id_in_use_on_channel(100, ch1));
  132. tt_ptr_op(circuit_get_by_circid_channel(200, ch2), OP_EQ, NULL);
  133. tt_ptr_op(circuit_get_by_circid_channel(100, ch1), OP_EQ, NULL);
  134. /* Now say that the destroy is nonpending */
  135. channel_note_destroy_not_pending(ch2, 200);
  136. tt_ptr_op(circuit_get_by_circid_channel(200, ch2), OP_EQ, NULL);
  137. channel_note_destroy_not_pending(ch1, 100);
  138. tt_ptr_op(circuit_get_by_circid_channel(100, ch1), OP_EQ, NULL);
  139. tt_assert(! circuit_id_in_use_on_channel(200, ch2));
  140. tt_assert(! circuit_id_in_use_on_channel(100, ch1));
  141. done:
  142. if (or_c1)
  143. circuit_free_(TO_CIRCUIT(or_c1));
  144. if (or_c2)
  145. circuit_free_(TO_CIRCUIT(or_c2));
  146. if (ch1)
  147. tor_free(ch1->cmux);
  148. if (ch2)
  149. tor_free(ch2->cmux);
  150. if (ch3)
  151. tor_free(ch3->cmux);
  152. tor_free(ch1);
  153. tor_free(ch2);
  154. tor_free(ch3);
  155. UNMOCK(circuitmux_attach_circuit);
  156. UNMOCK(circuitmux_detach_circuit);
  157. }
  158. static void
  159. test_rend_token_maps(void *arg)
  160. {
  161. or_circuit_t *c1, *c2, *c3, *c4;
  162. origin_circuit_t *c5;
  163. const uint8_t tok1[REND_TOKEN_LEN] = "The cat can't tell y";
  164. const uint8_t tok2[REND_TOKEN_LEN] = "ou its name, and it ";
  165. const uint8_t tok3[REND_TOKEN_LEN] = "doesn't really care.";
  166. /* -- Adapted from a quote by Fredrik Lundh. */
  167. (void)arg;
  168. (void)tok1; //xxxx
  169. hs_circuitmap_init();
  170. c1 = or_circuit_new(0, NULL);
  171. c2 = or_circuit_new(0, NULL);
  172. c3 = or_circuit_new(0, NULL);
  173. c4 = or_circuit_new(0, NULL);
  174. c5 = origin_circuit_new();
  175. /* Make sure we really filled up the tok* variables */
  176. tt_int_op(tok1[REND_TOKEN_LEN-1], OP_EQ, 'y');
  177. tt_int_op(tok2[REND_TOKEN_LEN-1], OP_EQ, ' ');
  178. tt_int_op(tok3[REND_TOKEN_LEN-1], OP_EQ, '.');
  179. /* No maps; nothing there. */
  180. tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok1));
  181. tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok1));
  182. hs_circuitmap_register_rend_circ_relay_side(c1, tok1);
  183. hs_circuitmap_register_intro_circ_v2_relay_side(c2, tok2);
  184. tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok3));
  185. tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok3));
  186. tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok2));
  187. tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok1));
  188. /* Without purpose set, we don't get the circuits */
  189. tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok1));
  190. tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok2));
  191. c1->base_.purpose = CIRCUIT_PURPOSE_REND_POINT_WAITING;
  192. c2->base_.purpose = CIRCUIT_PURPOSE_INTRO_POINT;
  193. /* Okay, make sure they show up now. */
  194. tt_ptr_op(c1, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok1));
  195. tt_ptr_op(c2, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok2));
  196. /* Two items at the same place with the same token. */
  197. c3->base_.purpose = CIRCUIT_PURPOSE_REND_POINT_WAITING;
  198. hs_circuitmap_register_rend_circ_relay_side(c3, tok2);
  199. tt_ptr_op(c2, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok2));
  200. tt_ptr_op(c3, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok2));
  201. /* Marking a circuit makes it not get returned any more */
  202. circuit_mark_for_close(TO_CIRCUIT(c1), END_CIRC_REASON_FINISHED);
  203. tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok1));
  204. circuit_free_(TO_CIRCUIT(c1));
  205. c1 = NULL;
  206. /* Freeing a circuit makes it not get returned any more. */
  207. circuit_free_(TO_CIRCUIT(c2));
  208. c2 = NULL;
  209. tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok2));
  210. /* c3 -- are you still there? */
  211. tt_ptr_op(c3, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok2));
  212. /* Change its cookie. This never happens in Tor per se, but hey. */
  213. c3->base_.purpose = CIRCUIT_PURPOSE_INTRO_POINT;
  214. hs_circuitmap_register_intro_circ_v2_relay_side(c3, tok3);
  215. tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok2));
  216. tt_ptr_op(c3, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok3));
  217. /* Now replace c3 with c4. */
  218. c4->base_.purpose = CIRCUIT_PURPOSE_INTRO_POINT;
  219. hs_circuitmap_register_intro_circ_v2_relay_side(c4, tok3);
  220. tt_ptr_op(c4, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok3));
  221. tt_ptr_op(TO_CIRCUIT(c3)->hs_token, OP_EQ, NULL);
  222. tt_ptr_op(TO_CIRCUIT(c4)->hs_token, OP_NE, NULL);
  223. tt_mem_op(TO_CIRCUIT(c4)->hs_token->token, OP_EQ, tok3, REND_TOKEN_LEN);
  224. /* Now clear c4's cookie. */
  225. hs_circuitmap_remove_circuit(TO_CIRCUIT(c4));
  226. tt_ptr_op(TO_CIRCUIT(c4)->hs_token, OP_EQ, NULL);
  227. tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok3));
  228. /* Now let's do a check for the client-side rend circuitmap */
  229. c5->base_.purpose = CIRCUIT_PURPOSE_C_ESTABLISH_REND;
  230. hs_circuitmap_register_rend_circ_client_side(c5, tok1);
  231. tt_ptr_op(c5, OP_EQ, hs_circuitmap_get_rend_circ_client_side(tok1));
  232. tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_client_side(tok2));
  233. done:
  234. if (c1)
  235. circuit_free_(TO_CIRCUIT(c1));
  236. if (c2)
  237. circuit_free_(TO_CIRCUIT(c2));
  238. if (c3)
  239. circuit_free_(TO_CIRCUIT(c3));
  240. if (c4)
  241. circuit_free_(TO_CIRCUIT(c4));
  242. if (c5)
  243. circuit_free_(TO_CIRCUIT(c5));
  244. }
  245. static void
  246. mock_channel_dump_statistics(channel_t *chan, int severity)
  247. {
  248. (void)chan;
  249. (void)severity;
  250. }
  251. static void
  252. test_pick_circid(void *arg)
  253. {
  254. bitarray_t *ba = NULL;
  255. channel_t *chan1, *chan2;
  256. circid_t circid;
  257. int i;
  258. (void) arg;
  259. MOCK(channel_dump_statistics, mock_channel_dump_statistics);
  260. chan1 = tor_malloc_zero(sizeof(channel_t));
  261. chan2 = tor_malloc_zero(sizeof(channel_t));
  262. chan2->wide_circ_ids = 1;
  263. chan1->cmux = circuitmux_alloc();
  264. chan2->cmux = circuitmux_alloc();
  265. /* CIRC_ID_TYPE_NEITHER is supposed to create a warning. */
  266. chan1->circ_id_type = CIRC_ID_TYPE_NEITHER;
  267. setup_full_capture_of_logs(LOG_WARN);
  268. tt_int_op(0, OP_EQ, get_unique_circ_id_by_chan(chan1));
  269. expect_single_log_msg_containing("Trying to pick a circuit ID for a "
  270. "connection from a client with no identity.");
  271. teardown_capture_of_logs();
  272. /* Basic tests, with no collisions */
  273. chan1->circ_id_type = CIRC_ID_TYPE_LOWER;
  274. for (i = 0; i < 50; ++i) {
  275. circid = get_unique_circ_id_by_chan(chan1);
  276. tt_uint_op(0, OP_LT, circid);
  277. tt_uint_op(circid, OP_LT, (1<<15));
  278. }
  279. chan1->circ_id_type = CIRC_ID_TYPE_HIGHER;
  280. for (i = 0; i < 50; ++i) {
  281. circid = get_unique_circ_id_by_chan(chan1);
  282. tt_uint_op((1<<15), OP_LT, circid);
  283. tt_uint_op(circid, OP_LT, (1<<16));
  284. }
  285. chan2->circ_id_type = CIRC_ID_TYPE_LOWER;
  286. for (i = 0; i < 50; ++i) {
  287. circid = get_unique_circ_id_by_chan(chan2);
  288. tt_uint_op(0, OP_LT, circid);
  289. tt_uint_op(circid, OP_LT, (1u<<31));
  290. }
  291. chan2->circ_id_type = CIRC_ID_TYPE_HIGHER;
  292. for (i = 0; i < 50; ++i) {
  293. circid = get_unique_circ_id_by_chan(chan2);
  294. tt_uint_op((1u<<31), OP_LT, circid);
  295. }
  296. /* Now make sure that we can behave well when we are full up on circuits */
  297. chan1->circ_id_type = CIRC_ID_TYPE_LOWER;
  298. chan2->circ_id_type = CIRC_ID_TYPE_LOWER;
  299. chan1->wide_circ_ids = chan2->wide_circ_ids = 0;
  300. ba = bitarray_init_zero((1<<15));
  301. for (i = 0; i < (1<<15); ++i) {
  302. circid = get_unique_circ_id_by_chan(chan1);
  303. if (circid == 0) {
  304. tt_int_op(i, OP_GT, (1<<14));
  305. break;
  306. }
  307. tt_uint_op(circid, OP_LT, (1<<15));
  308. tt_assert(! bitarray_is_set(ba, circid));
  309. bitarray_set(ba, circid);
  310. channel_mark_circid_unusable(chan1, circid);
  311. }
  312. tt_int_op(i, OP_LT, (1<<15));
  313. /* Make sure that being full on chan1 does not interfere with chan2 */
  314. for (i = 0; i < 100; ++i) {
  315. circid = get_unique_circ_id_by_chan(chan2);
  316. tt_uint_op(circid, OP_GT, 0);
  317. tt_uint_op(circid, OP_LT, (1<<15));
  318. channel_mark_circid_unusable(chan2, circid);
  319. }
  320. done:
  321. circuitmux_free(chan1->cmux);
  322. circuitmux_free(chan2->cmux);
  323. tor_free(chan1);
  324. tor_free(chan2);
  325. bitarray_free(ba);
  326. circuit_free_all();
  327. teardown_capture_of_logs();
  328. UNMOCK(channel_dump_statistics);
  329. }
  330. /** Test that the circuit pools of our HS circuitmap are isolated based on
  331. * their token type. */
  332. static void
  333. test_hs_circuitmap_isolation(void *arg)
  334. {
  335. or_circuit_t *circ1 = NULL;
  336. origin_circuit_t *circ2 = NULL;
  337. or_circuit_t *circ3 = NULL;
  338. origin_circuit_t *circ4 = NULL;
  339. (void)arg;
  340. hs_circuitmap_init();
  341. {
  342. const uint8_t tok1[REND_TOKEN_LEN] = "bet i got some of th";
  343. circ1 = or_circuit_new(0, NULL);
  344. tt_assert(circ1);
  345. circ1->base_.purpose = CIRCUIT_PURPOSE_REND_POINT_WAITING;
  346. /* check that circuitmap is empty right? */
  347. tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok1));
  348. /* Register circ1 with tok1 as relay-side rend circ */
  349. hs_circuitmap_register_rend_circ_relay_side(circ1, tok1);
  350. /* check that service-side getters don't work */
  351. tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_service_side(tok1));
  352. tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2_service_side(tok1));
  353. /* Check that the right getter works. */
  354. tt_ptr_op(circ1, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok1));
  355. }
  356. {
  357. const uint8_t tok2[REND_TOKEN_LEN] = "you dont know anythi";
  358. circ2 = origin_circuit_new();
  359. tt_assert(circ2);
  360. circ2->base_.purpose = CIRCUIT_PURPOSE_S_ESTABLISH_INTRO;
  361. circ3 = or_circuit_new(0, NULL);
  362. tt_assert(circ3);
  363. circ3->base_.purpose = CIRCUIT_PURPOSE_INTRO_POINT;
  364. circ4 = origin_circuit_new();
  365. tt_assert(circ4);
  366. circ4->base_.purpose = CIRCUIT_PURPOSE_S_ESTABLISH_INTRO;
  367. /* Register circ2 with tok2 as service-side intro v2 circ */
  368. hs_circuitmap_register_intro_circ_v2_service_side(circ2, tok2);
  369. /* Register circ3 with tok2 again but for different purpose */
  370. hs_circuitmap_register_intro_circ_v2_relay_side(circ3, tok2);
  371. /* Check that the getters work */
  372. tt_ptr_op(circ2, OP_EQ,
  373. hs_circuitmap_get_intro_circ_v2_service_side(tok2));
  374. tt_ptr_op(circ3, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok2));
  375. /* Register circ4 with tok2: it should override circ2 */
  376. hs_circuitmap_register_intro_circ_v2_service_side(circ4, tok2);
  377. /* check that relay-side getters don't work */
  378. tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok2));
  379. /* Check that the getter returns circ4; the last circuit registered with
  380. * that token. */
  381. tt_ptr_op(circ4, OP_EQ,
  382. hs_circuitmap_get_intro_circ_v2_service_side(tok2));
  383. }
  384. done:
  385. circuit_free_(TO_CIRCUIT(circ1));
  386. circuit_free_(TO_CIRCUIT(circ2));
  387. circuit_free_(TO_CIRCUIT(circ3));
  388. circuit_free_(TO_CIRCUIT(circ4));
  389. }
  390. struct testcase_t circuitlist_tests[] = {
  391. { "maps", test_clist_maps, TT_FORK, NULL, NULL },
  392. { "rend_token_maps", test_rend_token_maps, TT_FORK, NULL, NULL },
  393. { "pick_circid", test_pick_circid, TT_FORK, NULL, NULL },
  394. { "hs_circuitmap_isolation", test_hs_circuitmap_isolation,
  395. TT_FORK, NULL, NULL },
  396. END_OF_TESTCASES
  397. };