test_connection.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756
  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. connection_free(conn->linked_conn);
  146. conn->linked_conn = NULL;
  147. conn->linked_conn->linked_conn = NULL;
  148. if (!conn->linked_conn->marked_for_close) {
  149. connection_close_immediate(conn->linked_conn);
  150. connection_mark_for_close(conn->linked_conn);
  151. }
  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. memcpy(conn->rend_data->onion_address,
  186. TEST_CONN_REND_ADDR,
  187. REND_SERVICE_ADDRESS_LEN+1);
  188. conn->rend_data->hsdirs_fp = smartlist_new();
  189. conn->base_.purpose = TEST_CONN_REND_PURPOSE;
  190. assert_connection_ok(&conn->base_, time(NULL));
  191. return conn;
  192. /* On failure */
  193. done:
  194. test_conn_get_rend_teardown(tc, conn);
  195. /* Returning NULL causes the unit test to fail */
  196. return NULL;
  197. }
  198. static int
  199. test_conn_get_rend_teardown(const struct testcase_t *tc, void *arg)
  200. {
  201. dir_connection_t *conn = DOWNCAST(dir_connection_t, arg);
  202. int rv = 0;
  203. tt_assert(conn);
  204. assert_connection_ok(&conn->base_, time(NULL));
  205. /* avoid a last-ditch attempt to refetch the descriptor */
  206. conn->base_.purpose = TEST_CONN_REND_PURPOSE_SUCCESSFUL;
  207. /* connection_free_() cleans up rend_data */
  208. rv = test_conn_get_basic_teardown(tc, arg);
  209. done:
  210. rend_cache_free_all();
  211. return rv;
  212. }
  213. static void *
  214. test_conn_get_rsrc_setup(const struct testcase_t *tc)
  215. {
  216. dir_connection_t *conn = DOWNCAST(dir_connection_t,
  217. test_conn_get_basic_setup(tc));
  218. tt_assert(conn);
  219. assert_connection_ok(&conn->base_, time(NULL));
  220. /* TODO: use the canonical function to do this - maybe? */
  221. conn->requested_resource = tor_strdup(TEST_CONN_RSRC);
  222. conn->base_.purpose = TEST_CONN_RSRC_PURPOSE;
  223. assert_connection_ok(&conn->base_, time(NULL));
  224. return conn;
  225. /* On failure */
  226. done:
  227. test_conn_get_rend_teardown(tc, conn);
  228. /* Returning NULL causes the unit test to fail */
  229. return NULL;
  230. }
  231. static int
  232. test_conn_get_rsrc_teardown(const struct testcase_t *tc, void *arg)
  233. {
  234. dir_connection_t *conn = DOWNCAST(dir_connection_t, arg);
  235. int rv = 0;
  236. tt_assert(conn);
  237. assert_connection_ok(&conn->base_, time(NULL));
  238. /* avoid a last-ditch attempt to refetch the consensus */
  239. conn->base_.state = TEST_CONN_RSRC_STATE_SUCCESSFUL;
  240. /* connection_free_() cleans up requested_resource */
  241. rv = test_conn_get_basic_teardown(tc, arg);
  242. done:
  243. return rv;
  244. }
  245. static void *
  246. test_conn_download_status_setup(const struct testcase_t *tc)
  247. {
  248. (void)tc;
  249. /* Don't return NULL, that causes the test to fail */
  250. return (void*)"ok";
  251. }
  252. static int
  253. test_conn_download_status_teardown(const struct testcase_t *tc, void *arg)
  254. {
  255. (void)arg;
  256. int rv = 0;
  257. /* Ignore arg, and just loop through the connection array */
  258. SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) {
  259. if (conn) {
  260. assert_connection_ok(conn, time(NULL));
  261. /* connection_free_() cleans up requested_resource */
  262. rv = test_conn_get_rsrc_teardown(tc, conn);
  263. tt_assert(rv == 1);
  264. }
  265. } SMARTLIST_FOREACH_END(conn);
  266. done:
  267. return rv;
  268. }
  269. static dir_connection_t *
  270. test_conn_download_status_add_a_connection(void)
  271. {
  272. dir_connection_t *conn = DOWNCAST(dir_connection_t,
  273. test_conn_get_rsrc_setup(NULL));
  274. tt_assert(conn);
  275. assert_connection_ok(&conn->base_, time(NULL));
  276. return conn;
  277. done:
  278. test_conn_download_status_teardown(NULL, NULL);
  279. return NULL;
  280. }
  281. static struct testcase_setup_t test_conn_get_basic_st = {
  282. test_conn_get_basic_setup, test_conn_get_basic_teardown
  283. };
  284. static struct testcase_setup_t test_conn_get_rend_st = {
  285. test_conn_get_rend_setup, test_conn_get_rend_teardown
  286. };
  287. static struct testcase_setup_t test_conn_get_rsrc_st = {
  288. test_conn_get_rsrc_setup, test_conn_get_rsrc_teardown
  289. };
  290. static struct testcase_setup_t test_conn_download_status_st = {
  291. test_conn_download_status_setup, test_conn_download_status_teardown
  292. };
  293. static void
  294. test_conn_get_basic(void *arg)
  295. {
  296. connection_t *conn = (connection_t*)arg;
  297. tor_addr_t addr, addr2;
  298. tt_assert(conn);
  299. assert_connection_ok(conn, time(NULL));
  300. test_conn_lookup_addr_helper(TEST_CONN_ADDRESS, TEST_CONN_FAMILY, &addr);
  301. tt_assert(!tor_addr_is_null(&addr));
  302. test_conn_lookup_addr_helper(TEST_CONN_ADDRESS_2, TEST_CONN_FAMILY, &addr2);
  303. tt_assert(!tor_addr_is_null(&addr2));
  304. /* Check that we get this connection back when we search for it by
  305. * its attributes, but get NULL when we supply a different value. */
  306. tt_assert(connection_get_by_global_id(conn->global_identifier) == conn);
  307. tt_assert(connection_get_by_global_id(!conn->global_identifier) == NULL);
  308. tt_assert(connection_get_by_type(conn->type) == conn);
  309. tt_assert(connection_get_by_type(TEST_CONN_TYPE) == conn);
  310. tt_assert(connection_get_by_type(!conn->type) == NULL);
  311. tt_assert(connection_get_by_type(!TEST_CONN_TYPE) == NULL);
  312. tt_assert(connection_get_by_type_state(conn->type, conn->state)
  313. == conn);
  314. tt_assert(connection_get_by_type_state(TEST_CONN_TYPE, TEST_CONN_STATE)
  315. == conn);
  316. tt_assert(connection_get_by_type_state(!conn->type, !conn->state)
  317. == NULL);
  318. tt_assert(connection_get_by_type_state(!TEST_CONN_TYPE, !TEST_CONN_STATE)
  319. == NULL);
  320. /* Match on the connection fields themselves */
  321. tt_assert(connection_get_by_type_addr_port_purpose(conn->type,
  322. &conn->addr,
  323. conn->port,
  324. conn->purpose)
  325. == conn);
  326. /* Match on the original inputs to the connection */
  327. tt_assert(connection_get_by_type_addr_port_purpose(TEST_CONN_TYPE,
  328. &conn->addr,
  329. conn->port,
  330. conn->purpose)
  331. == conn);
  332. tt_assert(connection_get_by_type_addr_port_purpose(conn->type,
  333. &addr,
  334. conn->port,
  335. conn->purpose)
  336. == conn);
  337. tt_assert(connection_get_by_type_addr_port_purpose(conn->type,
  338. &conn->addr,
  339. TEST_CONN_PORT,
  340. conn->purpose)
  341. == conn);
  342. tt_assert(connection_get_by_type_addr_port_purpose(conn->type,
  343. &conn->addr,
  344. conn->port,
  345. TEST_CONN_BASIC_PURPOSE)
  346. == conn);
  347. tt_assert(connection_get_by_type_addr_port_purpose(TEST_CONN_TYPE,
  348. &addr,
  349. TEST_CONN_PORT,
  350. TEST_CONN_BASIC_PURPOSE)
  351. == conn);
  352. /* Then try each of the not-matching combinations */
  353. tt_assert(connection_get_by_type_addr_port_purpose(!conn->type,
  354. &conn->addr,
  355. conn->port,
  356. conn->purpose)
  357. == NULL);
  358. tt_assert(connection_get_by_type_addr_port_purpose(conn->type,
  359. &addr2,
  360. conn->port,
  361. conn->purpose)
  362. == NULL);
  363. tt_assert(connection_get_by_type_addr_port_purpose(conn->type,
  364. &conn->addr,
  365. !conn->port,
  366. conn->purpose)
  367. == NULL);
  368. tt_assert(connection_get_by_type_addr_port_purpose(conn->type,
  369. &conn->addr,
  370. conn->port,
  371. !conn->purpose)
  372. == NULL);
  373. /* Then try everything not-matching */
  374. tt_assert(connection_get_by_type_addr_port_purpose(!conn->type,
  375. &addr2,
  376. !conn->port,
  377. !conn->purpose)
  378. == NULL);
  379. tt_assert(connection_get_by_type_addr_port_purpose(!TEST_CONN_TYPE,
  380. &addr2,
  381. !TEST_CONN_PORT,
  382. !TEST_CONN_BASIC_PURPOSE)
  383. == NULL);
  384. done:
  385. ;
  386. }
  387. static void
  388. test_conn_get_rend(void *arg)
  389. {
  390. dir_connection_t *conn = DOWNCAST(dir_connection_t, arg);
  391. tt_assert(conn);
  392. assert_connection_ok(&conn->base_, time(NULL));
  393. tt_assert(connection_get_by_type_state_rendquery(
  394. conn->base_.type,
  395. conn->base_.state,
  396. conn->rend_data->onion_address)
  397. == TO_CONN(conn));
  398. tt_assert(connection_get_by_type_state_rendquery(
  399. TEST_CONN_TYPE,
  400. TEST_CONN_STATE,
  401. TEST_CONN_REND_ADDR)
  402. == TO_CONN(conn));
  403. tt_assert(connection_get_by_type_state_rendquery(TEST_CONN_REND_TYPE_2,
  404. !conn->base_.state,
  405. "")
  406. == NULL);
  407. tt_assert(connection_get_by_type_state_rendquery(TEST_CONN_REND_TYPE_2,
  408. !TEST_CONN_STATE,
  409. TEST_CONN_REND_ADDR_2)
  410. == NULL);
  411. done:
  412. ;
  413. }
  414. #define sl_is_conn_assert(sl, conn) \
  415. do { \
  416. tt_assert(smartlist_len((sl)) == 1); \
  417. tt_assert(smartlist_get((sl), 0) == (conn)); \
  418. } while (0)
  419. #define sl_no_conn_assert(sl) \
  420. do { \
  421. tt_assert(smartlist_len((sl)) == 0); \
  422. } while (0)
  423. static void
  424. test_conn_get_rsrc(void *arg)
  425. {
  426. dir_connection_t *conn = DOWNCAST(dir_connection_t, arg);
  427. tt_assert(conn);
  428. assert_connection_ok(&conn->base_, time(NULL));
  429. tt_assert(connection_dir_get_by_purpose_and_resource(
  430. conn->base_.purpose,
  431. conn->requested_resource)
  432. == conn);
  433. tt_assert(connection_dir_get_by_purpose_and_resource(
  434. TEST_CONN_RSRC_PURPOSE,
  435. TEST_CONN_RSRC)
  436. == conn);
  437. tt_assert(connection_dir_get_by_purpose_and_resource(
  438. !conn->base_.purpose,
  439. "")
  440. == NULL);
  441. tt_assert(connection_dir_get_by_purpose_and_resource(
  442. !TEST_CONN_RSRC_PURPOSE,
  443. TEST_CONN_RSRC_2)
  444. == NULL);
  445. tt_assert(connection_dir_get_by_purpose_resource_and_state(
  446. conn->base_.purpose,
  447. conn->requested_resource,
  448. conn->base_.state)
  449. == conn);
  450. tt_assert(connection_dir_get_by_purpose_resource_and_state(
  451. TEST_CONN_RSRC_PURPOSE,
  452. TEST_CONN_RSRC,
  453. TEST_CONN_STATE)
  454. == conn);
  455. tt_assert(connection_dir_get_by_purpose_resource_and_state(
  456. !conn->base_.purpose,
  457. "",
  458. !conn->base_.state)
  459. == NULL);
  460. tt_assert(connection_dir_get_by_purpose_resource_and_state(
  461. !TEST_CONN_RSRC_PURPOSE,
  462. TEST_CONN_RSRC_2,
  463. !TEST_CONN_STATE)
  464. == NULL);
  465. sl_is_conn_assert(connection_dir_list_by_purpose_and_resource(
  466. conn->base_.purpose,
  467. conn->requested_resource),
  468. conn);
  469. sl_is_conn_assert(connection_dir_list_by_purpose_and_resource(
  470. TEST_CONN_RSRC_PURPOSE,
  471. TEST_CONN_RSRC),
  472. conn);
  473. sl_no_conn_assert(connection_dir_list_by_purpose_and_resource(
  474. !conn->base_.purpose,
  475. ""));
  476. sl_no_conn_assert(connection_dir_list_by_purpose_and_resource(
  477. !TEST_CONN_RSRC_PURPOSE,
  478. TEST_CONN_RSRC_2));
  479. sl_is_conn_assert(connection_dir_list_by_purpose_resource_and_state(
  480. conn->base_.purpose,
  481. conn->requested_resource,
  482. conn->base_.state),
  483. conn);
  484. sl_is_conn_assert(connection_dir_list_by_purpose_resource_and_state(
  485. TEST_CONN_RSRC_PURPOSE,
  486. TEST_CONN_RSRC,
  487. TEST_CONN_STATE),
  488. conn);
  489. sl_no_conn_assert(connection_dir_list_by_purpose_resource_and_state(
  490. !conn->base_.purpose,
  491. "",
  492. !conn->base_.state));
  493. sl_no_conn_assert(connection_dir_list_by_purpose_resource_and_state(
  494. !TEST_CONN_RSRC_PURPOSE,
  495. TEST_CONN_RSRC_2,
  496. !TEST_CONN_STATE));
  497. tt_assert(connection_dir_count_by_purpose_and_resource(
  498. conn->base_.purpose,
  499. conn->requested_resource)
  500. == 1);
  501. tt_assert(connection_dir_count_by_purpose_and_resource(
  502. TEST_CONN_RSRC_PURPOSE,
  503. TEST_CONN_RSRC)
  504. == 1);
  505. tt_assert(connection_dir_count_by_purpose_and_resource(
  506. !conn->base_.purpose,
  507. "")
  508. == 0);
  509. tt_assert(connection_dir_count_by_purpose_and_resource(
  510. !TEST_CONN_RSRC_PURPOSE,
  511. TEST_CONN_RSRC_2)
  512. == 0);
  513. tt_assert(connection_dir_count_by_purpose_resource_and_state(
  514. conn->base_.purpose,
  515. conn->requested_resource,
  516. conn->base_.state)
  517. == 1);
  518. tt_assert(connection_dir_count_by_purpose_resource_and_state(
  519. TEST_CONN_RSRC_PURPOSE,
  520. TEST_CONN_RSRC,
  521. TEST_CONN_STATE)
  522. == 1);
  523. tt_assert(connection_dir_count_by_purpose_resource_and_state(
  524. !conn->base_.purpose,
  525. "",
  526. !conn->base_.state)
  527. == 0);
  528. tt_assert(connection_dir_count_by_purpose_resource_and_state(
  529. !TEST_CONN_RSRC_PURPOSE,
  530. TEST_CONN_RSRC_2,
  531. !TEST_CONN_STATE)
  532. == 0);
  533. done:
  534. ;
  535. }
  536. static void
  537. test_conn_download_status(void *arg)
  538. {
  539. (void)arg;
  540. dir_connection_t *conn = NULL;
  541. dir_connection_t *conn2 = NULL;
  542. dir_connection_t *conn3 = NULL;
  543. /* no connections, no excess, not downloading */
  544. tt_assert(networkstatus_consensus_has_excess_connections() == 0);
  545. tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 0);
  546. tt_assert(connection_dir_avoid_extra_connection_for_purpose(
  547. TEST_CONN_RSRC_PURPOSE) == 0);
  548. /* one connection, no excess, not downloading */
  549. conn = test_conn_download_status_add_a_connection();
  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, but downloading */
  555. conn->base_.state = TEST_CONN_DL_STATE;
  556. tt_assert(networkstatus_consensus_has_excess_connections() == 0);
  557. tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 1);
  558. tt_assert(connection_dir_avoid_extra_connection_for_purpose(
  559. TEST_CONN_RSRC_PURPOSE) == 1);
  560. conn->base_.state = TEST_CONN_STATE;
  561. /* two connections, excess, but not downloading */
  562. conn2 = test_conn_download_status_add_a_connection();
  563. tt_assert(networkstatus_consensus_has_excess_connections() == 1);
  564. tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 0);
  565. tt_assert(connection_dir_avoid_extra_connection_for_purpose(
  566. TEST_CONN_RSRC_PURPOSE) == 0);
  567. /* two connections, excess, downloading */
  568. conn2->base_.state = TEST_CONN_DL_STATE;
  569. tt_assert(networkstatus_consensus_has_excess_connections() == 1);
  570. tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 1);
  571. tt_assert(connection_dir_avoid_extra_connection_for_purpose(
  572. TEST_CONN_RSRC_PURPOSE) == 1);
  573. conn2->base_.state = TEST_CONN_STATE;
  574. /* more connections, excess, but not downloading */
  575. conn3 = test_conn_download_status_add_a_connection();
  576. tt_assert(networkstatus_consensus_has_excess_connections() == 1);
  577. tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 0);
  578. tt_assert(connection_dir_avoid_extra_connection_for_purpose(
  579. TEST_CONN_RSRC_PURPOSE) == 0);
  580. /* more connections, excess, downloading */
  581. conn3->base_.state = TEST_CONN_DL_STATE;
  582. tt_assert(networkstatus_consensus_has_excess_connections() == 1);
  583. tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 1);
  584. tt_assert(connection_dir_avoid_extra_connection_for_purpose(
  585. TEST_CONN_RSRC_PURPOSE) == 1);
  586. /* more connections, more downloading */
  587. conn2->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. /* now try closing the one that isn't downloading:
  593. * these tests won't work unless tor thinks it is bootstrapping */
  594. tt_assert(networkstatus_consensus_is_boostrapping(time(NULL)));
  595. tt_assert(connection_dir_count_by_purpose_and_resource(
  596. TEST_CONN_RSRC_PURPOSE,
  597. TEST_CONN_RSRC) == 3);
  598. tt_assert(connection_dir_avoid_extra_connection_for_purpose(
  599. TEST_CONN_RSRC_PURPOSE) == 1);
  600. tt_assert(connection_dir_close_consensus_conn_if_extra(conn) == -1);
  601. tt_assert(connection_dir_count_by_purpose_and_resource(
  602. TEST_CONN_RSRC_PURPOSE,
  603. TEST_CONN_RSRC) == 2);
  604. tt_assert(connection_dir_avoid_extra_connection_for_purpose(
  605. TEST_CONN_RSRC_PURPOSE) == 1);
  606. /* now try closing one that is already closed - nothing happens */
  607. tt_assert(connection_dir_close_consensus_conn_if_extra(conn) == 0);
  608. tt_assert(connection_dir_count_by_purpose_and_resource(
  609. TEST_CONN_RSRC_PURPOSE,
  610. TEST_CONN_RSRC) == 2);
  611. tt_assert(connection_dir_avoid_extra_connection_for_purpose(
  612. TEST_CONN_RSRC_PURPOSE) == 1);
  613. /* now try closing one that is downloading - it stays open */
  614. tt_assert(connection_dir_close_consensus_conn_if_extra(conn2) == 0);
  615. tt_assert(connection_dir_count_by_purpose_and_resource(
  616. TEST_CONN_RSRC_PURPOSE,
  617. TEST_CONN_RSRC) == 2);
  618. tt_assert(connection_dir_avoid_extra_connection_for_purpose(
  619. TEST_CONN_RSRC_PURPOSE) == 1);
  620. /* now try closing all excess connections */
  621. connection_dir_close_extra_consensus_conns();
  622. tt_assert(connection_dir_count_by_purpose_and_resource(
  623. TEST_CONN_RSRC_PURPOSE,
  624. TEST_CONN_RSRC) == 1);
  625. tt_assert(connection_dir_avoid_extra_connection_for_purpose(
  626. TEST_CONN_RSRC_PURPOSE) == 1);
  627. done:
  628. /* the teardown function removes all the connections */;
  629. }
  630. #define CONNECTION_TESTCASE(name, fork, setup) \
  631. { #name, test_conn_##name, fork, &setup, NULL }
  632. struct testcase_t connection_tests[] = {
  633. CONNECTION_TESTCASE(get_basic, TT_FORK, test_conn_get_basic_st),
  634. CONNECTION_TESTCASE(get_rend, TT_FORK, test_conn_get_rend_st),
  635. CONNECTION_TESTCASE(get_rsrc, TT_FORK, test_conn_get_rsrc_st),
  636. CONNECTION_TESTCASE(download_status, TT_FORK, test_conn_download_status_st),
  637. //CONNECTION_TESTCASE(func_suffix, TT_FORK, setup_func_pair),
  638. END_OF_TESTCASES
  639. };