test_connection.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761
  1. /* Copyright (c) 2015, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. #include "orconfig.h"
  4. #define CONNECTION_PRIVATE
  5. #define MAIN_PRIVATE
  6. #include "or.h"
  7. #include "test.h"
  8. #include "connection.h"
  9. #include "main.h"
  10. #include "networkstatus.h"
  11. #include "rendcache.h"
  12. #include "directory.h"
  13. static void test_conn_lookup_addr_helper(const char *address,
  14. int family,
  15. tor_addr_t *addr);
  16. static void * test_conn_get_basic_setup(const struct testcase_t *tc);
  17. static int test_conn_get_basic_teardown(const struct testcase_t *tc,
  18. void *arg);
  19. static void * test_conn_get_rend_setup(const struct testcase_t *tc);
  20. static int test_conn_get_rend_teardown(const struct testcase_t *tc,
  21. void *arg);
  22. static void * test_conn_get_rsrc_setup(const struct testcase_t *tc);
  23. static int test_conn_get_rsrc_teardown(const struct testcase_t *tc,
  24. void *arg);
  25. /* Arbitrary choice - IPv4 Directory Connection to localhost */
  26. #define TEST_CONN_TYPE (CONN_TYPE_DIR)
  27. /* We assume every machine has IPv4 localhost, is that ok? */
  28. #define TEST_CONN_ADDRESS "127.0.0.1"
  29. #define TEST_CONN_PORT (12345)
  30. #define TEST_CONN_ADDRESS_PORT "127.0.0.1:12345"
  31. #define TEST_CONN_FAMILY (AF_INET)
  32. #define TEST_CONN_STATE (DIR_CONN_STATE_MIN_)
  33. #define TEST_CONN_ADDRESS_2 "127.0.0.2"
  34. #define TEST_CONN_BASIC_PURPOSE (DIR_PURPOSE_MIN_)
  35. #define TEST_CONN_REND_ADDR "cfs3rltphxxvabci"
  36. #define TEST_CONN_REND_PURPOSE (DIR_PURPOSE_FETCH_RENDDESC_V2)
  37. #define TEST_CONN_REND_PURPOSE_SUCCESSFUL (DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2)
  38. #define TEST_CONN_REND_TYPE_2 (CONN_TYPE_AP)
  39. #define TEST_CONN_REND_ADDR_2 "icbavxxhptlr3sfc"
  40. #define TEST_CONN_RSRC (networkstatus_get_flavor_name(FLAV_MICRODESC))
  41. #define TEST_CONN_RSRC_PURPOSE (DIR_PURPOSE_FETCH_CONSENSUS)
  42. #define TEST_CONN_RSRC_STATE_SUCCESSFUL (DIR_CONN_STATE_CLIENT_FINISHED)
  43. #define TEST_CONN_RSRC_2 (networkstatus_get_flavor_name(FLAV_NS))
  44. #define TEST_CONN_DL_STATE (DIR_CONN_STATE_CLIENT_SENDING)
  45. #define TEST_CONN_FD_INIT 50
  46. static int mock_connection_connect_sockaddr_called = 0;
  47. static int fake_socket_number = TEST_CONN_FD_INIT;
  48. static int
  49. mock_connection_connect_sockaddr(connection_t *conn,
  50. const struct sockaddr *sa,
  51. socklen_t sa_len,
  52. const struct sockaddr *bindaddr,
  53. socklen_t bindaddr_len,
  54. int *socket_error)
  55. {
  56. (void)sa_len;
  57. (void)bindaddr;
  58. (void)bindaddr_len;
  59. tor_assert(conn);
  60. tor_assert(sa);
  61. tor_assert(socket_error);
  62. mock_connection_connect_sockaddr_called++;
  63. conn->s = fake_socket_number++;
  64. tt_assert(SOCKET_OK(conn->s));
  65. /* We really should call tor_libevent_initialize() here. Because we don't,
  66. * we are relying on other parts of the code not checking if the_event_base
  67. * (and therefore event->ev_base) is NULL. */
  68. tt_assert(connection_add_connecting(conn) == 0);
  69. done:
  70. /* Fake "connected" status */
  71. return 1;
  72. }
  73. static void
  74. test_conn_lookup_addr_helper(const char *address, int family, tor_addr_t *addr)
  75. {
  76. int rv = 0;
  77. tt_assert(addr);
  78. rv = tor_addr_lookup(address, family, addr);
  79. /* XXXX - should we retry on transient failure? */
  80. tt_assert(rv == 0);
  81. tt_assert(tor_addr_is_loopback(addr));
  82. tt_assert(tor_addr_is_v4(addr));
  83. return;
  84. done:
  85. tor_addr_make_null(addr, TEST_CONN_FAMILY);
  86. }
  87. static void *
  88. test_conn_get_basic_setup(const struct testcase_t *tc)
  89. {
  90. connection_t *conn = NULL;
  91. tor_addr_t addr;
  92. int socket_err = 0;
  93. int in_progress = 0;
  94. (void)tc;
  95. MOCK(connection_connect_sockaddr,
  96. mock_connection_connect_sockaddr);
  97. init_connection_lists();
  98. conn = connection_new(TEST_CONN_TYPE, TEST_CONN_FAMILY);
  99. tt_assert(conn);
  100. test_conn_lookup_addr_helper(TEST_CONN_ADDRESS, TEST_CONN_FAMILY, &addr);
  101. tt_assert(!tor_addr_is_null(&addr));
  102. /* XXXX - connection_connect doesn't set these, should it? */
  103. tor_addr_copy_tight(&conn->addr, &addr);
  104. conn->port = TEST_CONN_PORT;
  105. mock_connection_connect_sockaddr_called = 0;
  106. in_progress = connection_connect(conn, TEST_CONN_ADDRESS_PORT, &addr,
  107. TEST_CONN_PORT, &socket_err);
  108. tt_assert(mock_connection_connect_sockaddr_called == 1);
  109. tt_assert(!socket_err);
  110. tt_assert(in_progress == 0 || in_progress == 1);
  111. /* fake some of the attributes so the connection looks OK */
  112. conn->state = TEST_CONN_STATE;
  113. conn->purpose = TEST_CONN_BASIC_PURPOSE;
  114. assert_connection_ok(conn, time(NULL));
  115. UNMOCK(connection_connect_sockaddr);
  116. return conn;
  117. /* On failure */
  118. done:
  119. UNMOCK(connection_connect_sockaddr);
  120. test_conn_get_basic_teardown(tc, conn);
  121. /* Returning NULL causes the unit test to fail */
  122. return NULL;
  123. }
  124. static int
  125. test_conn_get_basic_teardown(const struct testcase_t *tc, void *arg)
  126. {
  127. (void)tc;
  128. connection_t *conn = arg;
  129. tt_assert(conn);
  130. assert_connection_ok(conn, time(NULL));
  131. /* teardown the connection as fast as possible */
  132. if (conn->linked_conn) {
  133. assert_connection_ok(conn->linked_conn, time(NULL));
  134. /* We didn't call tor_libevent_initialize(), so event_base was NULL,
  135. * so we can't rely on connection_unregister_events() use of event_del().
  136. */
  137. if (conn->linked_conn->read_event) {
  138. tor_free(conn->linked_conn->read_event);
  139. conn->linked_conn->read_event = NULL;
  140. }
  141. if (conn->linked_conn->write_event) {
  142. tor_free(conn->linked_conn->write_event);
  143. conn->linked_conn->write_event = NULL;
  144. }
  145. if (!conn->linked_conn->marked_for_close) {
  146. connection_close_immediate(conn->linked_conn);
  147. connection_mark_for_close(conn->linked_conn);
  148. }
  149. conn->linked_conn->linked_conn = NULL;
  150. connection_free(conn->linked_conn);
  151. conn->linked_conn = NULL;
  152. }
  153. /* We didn't set the events up properly, so we can't use event_del() in
  154. * close_closeable_connections() > connection_free()
  155. * > connection_unregister_events() */
  156. if (conn->read_event) {
  157. tor_free(conn->read_event);
  158. conn->read_event = NULL;
  159. }
  160. if (conn->write_event) {
  161. tor_free(conn->write_event);
  162. conn->write_event = NULL;
  163. }
  164. if (!conn->marked_for_close) {
  165. connection_close_immediate(conn);
  166. connection_mark_for_close(conn);
  167. }
  168. close_closeable_connections();
  169. /* The unit test will fail if we return 0 */
  170. return 1;
  171. /* When conn == NULL, we can't cleanup anything */
  172. done:
  173. return 0;
  174. }
  175. static void *
  176. test_conn_get_rend_setup(const struct testcase_t *tc)
  177. {
  178. dir_connection_t *conn = DOWNCAST(dir_connection_t,
  179. test_conn_get_basic_setup(tc));
  180. tt_assert(conn);
  181. assert_connection_ok(&conn->base_, time(NULL));
  182. rend_cache_init();
  183. /* TODO: use directory_initiate_command_rend() to do this - maybe? */
  184. conn->rend_data = tor_malloc_zero(sizeof(rend_data_t));
  185. tor_assert(strlen(TEST_CONN_REND_ADDR) == REND_SERVICE_ID_LEN_BASE32);
  186. memcpy(conn->rend_data->onion_address,
  187. TEST_CONN_REND_ADDR,
  188. REND_SERVICE_ID_LEN_BASE32+1);
  189. conn->rend_data->hsdirs_fp = smartlist_new();
  190. conn->base_.purpose = TEST_CONN_REND_PURPOSE;
  191. assert_connection_ok(&conn->base_, time(NULL));
  192. return conn;
  193. /* On failure */
  194. done:
  195. test_conn_get_rend_teardown(tc, conn);
  196. /* Returning NULL causes the unit test to fail */
  197. return NULL;
  198. }
  199. static int
  200. test_conn_get_rend_teardown(const struct testcase_t *tc, void *arg)
  201. {
  202. dir_connection_t *conn = DOWNCAST(dir_connection_t, arg);
  203. int rv = 0;
  204. tt_assert(conn);
  205. assert_connection_ok(&conn->base_, time(NULL));
  206. /* avoid a last-ditch attempt to refetch the descriptor */
  207. conn->base_.purpose = TEST_CONN_REND_PURPOSE_SUCCESSFUL;
  208. /* connection_free_() cleans up rend_data */
  209. rv = test_conn_get_basic_teardown(tc, arg);
  210. done:
  211. rend_cache_free_all();
  212. return rv;
  213. }
  214. static void *
  215. test_conn_get_rsrc_setup(const struct testcase_t *tc)
  216. {
  217. dir_connection_t *conn = DOWNCAST(dir_connection_t,
  218. test_conn_get_basic_setup(tc));
  219. tt_assert(conn);
  220. assert_connection_ok(&conn->base_, time(NULL));
  221. /* TODO: use the canonical function to do this - maybe? */
  222. conn->requested_resource = tor_strdup(TEST_CONN_RSRC);
  223. conn->base_.purpose = TEST_CONN_RSRC_PURPOSE;
  224. assert_connection_ok(&conn->base_, time(NULL));
  225. return conn;
  226. /* On failure */
  227. done:
  228. test_conn_get_rend_teardown(tc, conn);
  229. /* Returning NULL causes the unit test to fail */
  230. return NULL;
  231. }
  232. static int
  233. test_conn_get_rsrc_teardown(const struct testcase_t *tc, void *arg)
  234. {
  235. dir_connection_t *conn = DOWNCAST(dir_connection_t, arg);
  236. int rv = 0;
  237. tt_assert(conn);
  238. assert_connection_ok(&conn->base_, time(NULL));
  239. /* avoid a last-ditch attempt to refetch the consensus */
  240. conn->base_.state = TEST_CONN_RSRC_STATE_SUCCESSFUL;
  241. /* connection_free_() cleans up requested_resource */
  242. rv = test_conn_get_basic_teardown(tc, arg);
  243. done:
  244. return rv;
  245. }
  246. static void *
  247. test_conn_download_status_setup(const struct testcase_t *tc)
  248. {
  249. (void)tc;
  250. /* Don't return NULL, that causes the test to fail */
  251. return (void*)"ok";
  252. }
  253. static int
  254. test_conn_download_status_teardown(const struct testcase_t *tc, void *arg)
  255. {
  256. (void)arg;
  257. int rv = 0;
  258. /* Ignore arg, and just loop through the connection array */
  259. SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) {
  260. if (conn) {
  261. assert_connection_ok(conn, time(NULL));
  262. /* connection_free_() cleans up requested_resource */
  263. rv = test_conn_get_rsrc_teardown(tc, conn);
  264. tt_assert(rv == 1);
  265. }
  266. } SMARTLIST_FOREACH_END(conn);
  267. done:
  268. return rv;
  269. }
  270. static dir_connection_t *
  271. test_conn_download_status_add_a_connection(void)
  272. {
  273. dir_connection_t *conn = DOWNCAST(dir_connection_t,
  274. test_conn_get_rsrc_setup(NULL));
  275. tt_assert(conn);
  276. assert_connection_ok(&conn->base_, time(NULL));
  277. return conn;
  278. done:
  279. test_conn_download_status_teardown(NULL, NULL);
  280. return NULL;
  281. }
  282. static struct testcase_setup_t test_conn_get_basic_st = {
  283. test_conn_get_basic_setup, test_conn_get_basic_teardown
  284. };
  285. static struct testcase_setup_t test_conn_get_rend_st = {
  286. test_conn_get_rend_setup, test_conn_get_rend_teardown
  287. };
  288. static struct testcase_setup_t test_conn_get_rsrc_st = {
  289. test_conn_get_rsrc_setup, test_conn_get_rsrc_teardown
  290. };
  291. static struct testcase_setup_t test_conn_download_status_st = {
  292. test_conn_download_status_setup, test_conn_download_status_teardown
  293. };
  294. static void
  295. test_conn_get_basic(void *arg)
  296. {
  297. connection_t *conn = (connection_t*)arg;
  298. tor_addr_t addr, addr2;
  299. tt_assert(conn);
  300. assert_connection_ok(conn, time(NULL));
  301. test_conn_lookup_addr_helper(TEST_CONN_ADDRESS, TEST_CONN_FAMILY, &addr);
  302. tt_assert(!tor_addr_is_null(&addr));
  303. test_conn_lookup_addr_helper(TEST_CONN_ADDRESS_2, TEST_CONN_FAMILY, &addr2);
  304. tt_assert(!tor_addr_is_null(&addr2));
  305. /* Check that we get this connection back when we search for it by
  306. * its attributes, but get NULL when we supply a different value. */
  307. tt_assert(connection_get_by_global_id(conn->global_identifier) == conn);
  308. tt_assert(connection_get_by_global_id(!conn->global_identifier) == NULL);
  309. tt_assert(connection_get_by_type(conn->type) == conn);
  310. tt_assert(connection_get_by_type(TEST_CONN_TYPE) == conn);
  311. tt_assert(connection_get_by_type(!conn->type) == NULL);
  312. tt_assert(connection_get_by_type(!TEST_CONN_TYPE) == NULL);
  313. tt_assert(connection_get_by_type_state(conn->type, conn->state)
  314. == conn);
  315. tt_assert(connection_get_by_type_state(TEST_CONN_TYPE, TEST_CONN_STATE)
  316. == conn);
  317. tt_assert(connection_get_by_type_state(!conn->type, !conn->state)
  318. == NULL);
  319. tt_assert(connection_get_by_type_state(!TEST_CONN_TYPE, !TEST_CONN_STATE)
  320. == NULL);
  321. /* Match on the connection fields themselves */
  322. tt_assert(connection_get_by_type_addr_port_purpose(conn->type,
  323. &conn->addr,
  324. conn->port,
  325. conn->purpose)
  326. == conn);
  327. /* Match on the original inputs to the connection */
  328. tt_assert(connection_get_by_type_addr_port_purpose(TEST_CONN_TYPE,
  329. &conn->addr,
  330. conn->port,
  331. conn->purpose)
  332. == conn);
  333. tt_assert(connection_get_by_type_addr_port_purpose(conn->type,
  334. &addr,
  335. conn->port,
  336. conn->purpose)
  337. == conn);
  338. tt_assert(connection_get_by_type_addr_port_purpose(conn->type,
  339. &conn->addr,
  340. TEST_CONN_PORT,
  341. conn->purpose)
  342. == conn);
  343. tt_assert(connection_get_by_type_addr_port_purpose(conn->type,
  344. &conn->addr,
  345. conn->port,
  346. TEST_CONN_BASIC_PURPOSE)
  347. == conn);
  348. tt_assert(connection_get_by_type_addr_port_purpose(TEST_CONN_TYPE,
  349. &addr,
  350. TEST_CONN_PORT,
  351. TEST_CONN_BASIC_PURPOSE)
  352. == conn);
  353. /* Then try each of the not-matching combinations */
  354. tt_assert(connection_get_by_type_addr_port_purpose(!conn->type,
  355. &conn->addr,
  356. conn->port,
  357. conn->purpose)
  358. == NULL);
  359. tt_assert(connection_get_by_type_addr_port_purpose(conn->type,
  360. &addr2,
  361. conn->port,
  362. conn->purpose)
  363. == NULL);
  364. tt_assert(connection_get_by_type_addr_port_purpose(conn->type,
  365. &conn->addr,
  366. !conn->port,
  367. conn->purpose)
  368. == NULL);
  369. tt_assert(connection_get_by_type_addr_port_purpose(conn->type,
  370. &conn->addr,
  371. conn->port,
  372. !conn->purpose)
  373. == NULL);
  374. /* Then try everything not-matching */
  375. tt_assert(connection_get_by_type_addr_port_purpose(!conn->type,
  376. &addr2,
  377. !conn->port,
  378. !conn->purpose)
  379. == NULL);
  380. tt_assert(connection_get_by_type_addr_port_purpose(!TEST_CONN_TYPE,
  381. &addr2,
  382. !TEST_CONN_PORT,
  383. !TEST_CONN_BASIC_PURPOSE)
  384. == NULL);
  385. done:
  386. ;
  387. }
  388. static void
  389. test_conn_get_rend(void *arg)
  390. {
  391. dir_connection_t *conn = DOWNCAST(dir_connection_t, arg);
  392. tt_assert(conn);
  393. assert_connection_ok(&conn->base_, time(NULL));
  394. tt_assert(connection_get_by_type_state_rendquery(
  395. conn->base_.type,
  396. conn->base_.state,
  397. conn->rend_data->onion_address)
  398. == TO_CONN(conn));
  399. tt_assert(connection_get_by_type_state_rendquery(
  400. TEST_CONN_TYPE,
  401. TEST_CONN_STATE,
  402. TEST_CONN_REND_ADDR)
  403. == TO_CONN(conn));
  404. tt_assert(connection_get_by_type_state_rendquery(TEST_CONN_REND_TYPE_2,
  405. !conn->base_.state,
  406. "")
  407. == NULL);
  408. tt_assert(connection_get_by_type_state_rendquery(TEST_CONN_REND_TYPE_2,
  409. !TEST_CONN_STATE,
  410. TEST_CONN_REND_ADDR_2)
  411. == NULL);
  412. done:
  413. ;
  414. }
  415. #define sl_is_conn_assert(sl_input, conn) \
  416. do { \
  417. the_sl = (sl_input); \
  418. tt_assert(smartlist_len((the_sl)) == 1); \
  419. tt_assert(smartlist_get((the_sl), 0) == (conn)); \
  420. smartlist_free(the_sl); the_sl = NULL; \
  421. } while (0)
  422. #define sl_no_conn_assert(sl_input) \
  423. do { \
  424. the_sl = (sl_input); \
  425. tt_assert(smartlist_len((the_sl)) == 0); \
  426. smartlist_free(the_sl); the_sl = NULL; \
  427. } while (0)
  428. static void
  429. test_conn_get_rsrc(void *arg)
  430. {
  431. dir_connection_t *conn = DOWNCAST(dir_connection_t, arg);
  432. smartlist_t *the_sl = NULL;
  433. tt_assert(conn);
  434. assert_connection_ok(&conn->base_, time(NULL));
  435. tt_assert(connection_dir_get_by_purpose_and_resource(
  436. conn->base_.purpose,
  437. conn->requested_resource)
  438. == conn);
  439. tt_assert(connection_dir_get_by_purpose_and_resource(
  440. TEST_CONN_RSRC_PURPOSE,
  441. TEST_CONN_RSRC)
  442. == conn);
  443. tt_assert(connection_dir_get_by_purpose_and_resource(
  444. !conn->base_.purpose,
  445. "")
  446. == NULL);
  447. tt_assert(connection_dir_get_by_purpose_and_resource(
  448. !TEST_CONN_RSRC_PURPOSE,
  449. TEST_CONN_RSRC_2)
  450. == NULL);
  451. tt_assert(connection_dir_get_by_purpose_resource_and_state(
  452. conn->base_.purpose,
  453. conn->requested_resource,
  454. conn->base_.state)
  455. == conn);
  456. tt_assert(connection_dir_get_by_purpose_resource_and_state(
  457. TEST_CONN_RSRC_PURPOSE,
  458. TEST_CONN_RSRC,
  459. TEST_CONN_STATE)
  460. == conn);
  461. tt_assert(connection_dir_get_by_purpose_resource_and_state(
  462. !conn->base_.purpose,
  463. "",
  464. !conn->base_.state)
  465. == NULL);
  466. tt_assert(connection_dir_get_by_purpose_resource_and_state(
  467. !TEST_CONN_RSRC_PURPOSE,
  468. TEST_CONN_RSRC_2,
  469. !TEST_CONN_STATE)
  470. == NULL);
  471. sl_is_conn_assert(connection_dir_list_by_purpose_and_resource(
  472. conn->base_.purpose,
  473. conn->requested_resource),
  474. conn);
  475. sl_is_conn_assert(connection_dir_list_by_purpose_and_resource(
  476. TEST_CONN_RSRC_PURPOSE,
  477. TEST_CONN_RSRC),
  478. conn);
  479. sl_no_conn_assert(connection_dir_list_by_purpose_and_resource(
  480. !conn->base_.purpose,
  481. ""));
  482. sl_no_conn_assert(connection_dir_list_by_purpose_and_resource(
  483. !TEST_CONN_RSRC_PURPOSE,
  484. TEST_CONN_RSRC_2));
  485. sl_is_conn_assert(connection_dir_list_by_purpose_resource_and_state(
  486. conn->base_.purpose,
  487. conn->requested_resource,
  488. conn->base_.state),
  489. conn);
  490. sl_is_conn_assert(connection_dir_list_by_purpose_resource_and_state(
  491. TEST_CONN_RSRC_PURPOSE,
  492. TEST_CONN_RSRC,
  493. TEST_CONN_STATE),
  494. conn);
  495. sl_no_conn_assert(connection_dir_list_by_purpose_resource_and_state(
  496. !conn->base_.purpose,
  497. "",
  498. !conn->base_.state));
  499. sl_no_conn_assert(connection_dir_list_by_purpose_resource_and_state(
  500. !TEST_CONN_RSRC_PURPOSE,
  501. TEST_CONN_RSRC_2,
  502. !TEST_CONN_STATE));
  503. tt_assert(connection_dir_count_by_purpose_and_resource(
  504. conn->base_.purpose,
  505. conn->requested_resource)
  506. == 1);
  507. tt_assert(connection_dir_count_by_purpose_and_resource(
  508. TEST_CONN_RSRC_PURPOSE,
  509. TEST_CONN_RSRC)
  510. == 1);
  511. tt_assert(connection_dir_count_by_purpose_and_resource(
  512. !conn->base_.purpose,
  513. "")
  514. == 0);
  515. tt_assert(connection_dir_count_by_purpose_and_resource(
  516. !TEST_CONN_RSRC_PURPOSE,
  517. TEST_CONN_RSRC_2)
  518. == 0);
  519. tt_assert(connection_dir_count_by_purpose_resource_and_state(
  520. conn->base_.purpose,
  521. conn->requested_resource,
  522. conn->base_.state)
  523. == 1);
  524. tt_assert(connection_dir_count_by_purpose_resource_and_state(
  525. TEST_CONN_RSRC_PURPOSE,
  526. TEST_CONN_RSRC,
  527. TEST_CONN_STATE)
  528. == 1);
  529. tt_assert(connection_dir_count_by_purpose_resource_and_state(
  530. !conn->base_.purpose,
  531. "",
  532. !conn->base_.state)
  533. == 0);
  534. tt_assert(connection_dir_count_by_purpose_resource_and_state(
  535. !TEST_CONN_RSRC_PURPOSE,
  536. TEST_CONN_RSRC_2,
  537. !TEST_CONN_STATE)
  538. == 0);
  539. done:
  540. smartlist_free(the_sl);
  541. }
  542. static void
  543. test_conn_download_status(void *arg)
  544. {
  545. (void)arg;
  546. dir_connection_t *conn = NULL;
  547. dir_connection_t *conn2 = NULL;
  548. dir_connection_t *conn3 = NULL;
  549. /* no connections, no excess, not downloading */
  550. tt_assert(networkstatus_consensus_has_excess_connections() == 0);
  551. tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 0);
  552. tt_assert(connection_dir_avoid_extra_connection_for_purpose(
  553. TEST_CONN_RSRC_PURPOSE) == 0);
  554. /* one connection, no excess, not downloading */
  555. conn = test_conn_download_status_add_a_connection();
  556. tt_assert(networkstatus_consensus_has_excess_connections() == 0);
  557. tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 0);
  558. tt_assert(connection_dir_avoid_extra_connection_for_purpose(
  559. TEST_CONN_RSRC_PURPOSE) == 0);
  560. /* one connection, no excess, but downloading */
  561. conn->base_.state = TEST_CONN_DL_STATE;
  562. tt_assert(networkstatus_consensus_has_excess_connections() == 0);
  563. tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 1);
  564. tt_assert(connection_dir_avoid_extra_connection_for_purpose(
  565. TEST_CONN_RSRC_PURPOSE) == 1);
  566. conn->base_.state = TEST_CONN_STATE;
  567. /* two connections, excess, but not downloading */
  568. conn2 = test_conn_download_status_add_a_connection();
  569. tt_assert(networkstatus_consensus_has_excess_connections() == 1);
  570. tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 0);
  571. tt_assert(connection_dir_avoid_extra_connection_for_purpose(
  572. TEST_CONN_RSRC_PURPOSE) == 0);
  573. /* two connections, excess, downloading */
  574. conn2->base_.state = TEST_CONN_DL_STATE;
  575. tt_assert(networkstatus_consensus_has_excess_connections() == 1);
  576. tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 1);
  577. tt_assert(connection_dir_avoid_extra_connection_for_purpose(
  578. TEST_CONN_RSRC_PURPOSE) == 1);
  579. conn2->base_.state = TEST_CONN_STATE;
  580. /* more connections, excess, but not downloading */
  581. conn3 = test_conn_download_status_add_a_connection();
  582. tt_assert(networkstatus_consensus_has_excess_connections() == 1);
  583. tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 0);
  584. tt_assert(connection_dir_avoid_extra_connection_for_purpose(
  585. TEST_CONN_RSRC_PURPOSE) == 0);
  586. /* more connections, excess, downloading */
  587. conn3->base_.state = TEST_CONN_DL_STATE;
  588. tt_assert(networkstatus_consensus_has_excess_connections() == 1);
  589. tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 1);
  590. tt_assert(connection_dir_avoid_extra_connection_for_purpose(
  591. TEST_CONN_RSRC_PURPOSE) == 1);
  592. /* more connections, more downloading */
  593. conn2->base_.state = TEST_CONN_DL_STATE;
  594. tt_assert(networkstatus_consensus_has_excess_connections() == 1);
  595. tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 1);
  596. tt_assert(connection_dir_avoid_extra_connection_for_purpose(
  597. TEST_CONN_RSRC_PURPOSE) == 1);
  598. /* now try closing the one that isn't downloading:
  599. * these tests won't work unless tor thinks it is bootstrapping */
  600. tt_assert(networkstatus_consensus_is_boostrapping(time(NULL)));
  601. tt_assert(connection_dir_count_by_purpose_and_resource(
  602. TEST_CONN_RSRC_PURPOSE,
  603. TEST_CONN_RSRC) == 3);
  604. tt_assert(connection_dir_avoid_extra_connection_for_purpose(
  605. TEST_CONN_RSRC_PURPOSE) == 1);
  606. tt_assert(connection_dir_close_consensus_conn_if_extra(conn) == -1);
  607. tt_assert(connection_dir_count_by_purpose_and_resource(
  608. TEST_CONN_RSRC_PURPOSE,
  609. TEST_CONN_RSRC) == 2);
  610. tt_assert(connection_dir_avoid_extra_connection_for_purpose(
  611. TEST_CONN_RSRC_PURPOSE) == 1);
  612. /* now try closing one that is already closed - nothing happens */
  613. tt_assert(connection_dir_close_consensus_conn_if_extra(conn) == 0);
  614. tt_assert(connection_dir_count_by_purpose_and_resource(
  615. TEST_CONN_RSRC_PURPOSE,
  616. TEST_CONN_RSRC) == 2);
  617. tt_assert(connection_dir_avoid_extra_connection_for_purpose(
  618. TEST_CONN_RSRC_PURPOSE) == 1);
  619. /* now try closing one that is downloading - it stays open */
  620. tt_assert(connection_dir_close_consensus_conn_if_extra(conn2) == 0);
  621. tt_assert(connection_dir_count_by_purpose_and_resource(
  622. TEST_CONN_RSRC_PURPOSE,
  623. TEST_CONN_RSRC) == 2);
  624. tt_assert(connection_dir_avoid_extra_connection_for_purpose(
  625. TEST_CONN_RSRC_PURPOSE) == 1);
  626. /* now try closing all excess connections */
  627. connection_dir_close_extra_consensus_conns();
  628. tt_assert(connection_dir_count_by_purpose_and_resource(
  629. TEST_CONN_RSRC_PURPOSE,
  630. TEST_CONN_RSRC) == 1);
  631. tt_assert(connection_dir_avoid_extra_connection_for_purpose(
  632. TEST_CONN_RSRC_PURPOSE) == 1);
  633. done:
  634. /* the teardown function removes all the connections */;
  635. }
  636. #define CONNECTION_TESTCASE(name, fork, setup) \
  637. { #name, test_conn_##name, fork, &setup, NULL }
  638. struct testcase_t connection_tests[] = {
  639. CONNECTION_TESTCASE(get_basic, TT_FORK, test_conn_get_basic_st),
  640. CONNECTION_TESTCASE(get_rend, TT_FORK, test_conn_get_rend_st),
  641. CONNECTION_TESTCASE(get_rsrc, TT_FORK, test_conn_get_rsrc_st),
  642. CONNECTION_TESTCASE(download_status, TT_FORK, test_conn_download_status_st),
  643. //CONNECTION_TESTCASE(func_suffix, TT_FORK, setup_func_pair),
  644. END_OF_TESTCASES
  645. };