Prop210: Close excess connections once a consensus is downloading
[tor.git] / src / test / test_connection.c
blob1067b5fa1f9709ccb02a49766b07b3936c320edc
1 /* Copyright (c) 2015, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
4 #include "orconfig.h"
6 #define CONNECTION_PRIVATE
7 #define MAIN_PRIVATE
9 #include "or.h"
10 #include "test.h"
12 #include "connection.h"
13 #include "main.h"
14 #include "networkstatus.h"
15 #include "rendcache.h"
16 #include "directory.h"
18 static void test_conn_lookup_addr_helper(const char *address,
19 int family,
20 tor_addr_t *addr);
22 static void * test_conn_get_basic_setup(const struct testcase_t *tc);
23 static int test_conn_get_basic_teardown(const struct testcase_t *tc,
24 void *arg);
26 static void * test_conn_get_rend_setup(const struct testcase_t *tc);
27 static int test_conn_get_rend_teardown(const struct testcase_t *tc,
28 void *arg);
30 static void * test_conn_get_rsrc_setup(const struct testcase_t *tc);
31 static int test_conn_get_rsrc_teardown(const struct testcase_t *tc,
32 void *arg);
34 /* Arbitrary choice - IPv4 Directory Connection to localhost */
35 #define TEST_CONN_TYPE (CONN_TYPE_DIR)
36 /* We assume every machine has IPv4 localhost, is that ok? */
37 #define TEST_CONN_ADDRESS "127.0.0.1"
38 #define TEST_CONN_PORT (12345)
39 #define TEST_CONN_ADDRESS_PORT "127.0.0.1:12345"
40 #define TEST_CONN_FAMILY (AF_INET)
41 #define TEST_CONN_STATE (DIR_CONN_STATE_MIN_)
42 #define TEST_CONN_ADDRESS_2 "127.0.0.2"
44 #define TEST_CONN_BASIC_PURPOSE (DIR_PURPOSE_MIN_)
46 #define TEST_CONN_REND_ADDR "cfs3rltphxxvabci"
47 #define TEST_CONN_REND_PURPOSE (DIR_PURPOSE_FETCH_RENDDESC_V2)
48 #define TEST_CONN_REND_PURPOSE_SUCCESSFUL (DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2)
49 #define TEST_CONN_REND_TYPE_2 (CONN_TYPE_AP)
50 #define TEST_CONN_REND_ADDR_2 "icbavxxhptlr3sfc"
52 #define TEST_CONN_RSRC (networkstatus_get_flavor_name(FLAV_MICRODESC))
53 #define TEST_CONN_RSRC_PURPOSE (DIR_PURPOSE_FETCH_CONSENSUS)
54 #define TEST_CONN_RSRC_STATE_SUCCESSFUL (DIR_CONN_STATE_CLIENT_FINISHED)
55 #define TEST_CONN_RSRC_2 (networkstatus_get_flavor_name(FLAV_NS))
57 #define TEST_CONN_DL_STATE (DIR_CONN_STATE_CLIENT_SENDING)
59 #define TEST_CONN_FD_INIT 50
60 static int mock_connection_connect_sockaddr_called = 0;
61 static int fake_socket_number = TEST_CONN_FD_INIT;
63 static int
64 mock_connection_connect_sockaddr(connection_t *conn,
65 const struct sockaddr *sa,
66 socklen_t sa_len,
67 const struct sockaddr *bindaddr,
68 socklen_t bindaddr_len,
69 int *socket_error)
71 (void)sa_len;
72 (void)bindaddr;
73 (void)bindaddr_len;
75 tor_assert(conn);
76 tor_assert(sa);
77 tor_assert(socket_error);
79 mock_connection_connect_sockaddr_called++;
81 conn->s = fake_socket_number++;
82 tt_assert(SOCKET_OK(conn->s));
83 /* We really should call tor_libevent_initialize() here. Because we don't,
84 * we are relying on other parts of the code not checking if the_event_base
85 * (and therefore event->ev_base) is NULL. */
86 tt_assert(connection_add_connecting(conn) == 0);
88 done:
89 /* Fake "connected" status */
90 return 1;
93 static void
94 test_conn_lookup_addr_helper(const char *address, int family, tor_addr_t *addr)
96 int rv = 0;
98 tt_assert(addr);
100 rv = tor_addr_lookup(address, family, addr);
101 /* XXXX - should we retry on transient failure? */
102 tt_assert(rv == 0);
103 tt_assert(tor_addr_is_loopback(addr));
104 tt_assert(tor_addr_is_v4(addr));
106 return;
108 done:
109 tor_addr_make_null(addr, TEST_CONN_FAMILY);
112 static void *
113 test_conn_get_basic_setup(const struct testcase_t *tc)
115 connection_t *conn = NULL;
116 tor_addr_t addr;
117 int socket_err = 0;
118 int in_progress = 0;
119 (void)tc;
121 MOCK(connection_connect_sockaddr,
122 mock_connection_connect_sockaddr);
124 init_connection_lists();
126 conn = connection_new(TEST_CONN_TYPE, TEST_CONN_FAMILY);
127 tt_assert(conn);
129 test_conn_lookup_addr_helper(TEST_CONN_ADDRESS, TEST_CONN_FAMILY, &addr);
130 tt_assert(!tor_addr_is_null(&addr));
132 /* XXXX - connection_connect doesn't set these, should it? */
133 tor_addr_copy_tight(&conn->addr, &addr);
134 conn->port = TEST_CONN_PORT;
135 mock_connection_connect_sockaddr_called = 0;
136 in_progress = connection_connect(conn, TEST_CONN_ADDRESS_PORT, &addr,
137 TEST_CONN_PORT, &socket_err);
138 tt_assert(mock_connection_connect_sockaddr_called == 1);
139 tt_assert(!socket_err);
140 tt_assert(in_progress == 0 || in_progress == 1);
142 /* fake some of the attributes so the connection looks OK */
143 conn->state = TEST_CONN_STATE;
144 conn->purpose = TEST_CONN_BASIC_PURPOSE;
145 assert_connection_ok(conn, time(NULL));
147 UNMOCK(connection_connect_sockaddr);
149 return conn;
151 /* On failure */
152 done:
153 UNMOCK(connection_connect_sockaddr);
154 test_conn_get_basic_teardown(tc, conn);
156 /* Returning NULL causes the unit test to fail */
157 return NULL;
160 static int
161 test_conn_get_basic_teardown(const struct testcase_t *tc, void *arg)
163 (void)tc;
164 connection_t *conn = arg;
166 tt_assert(conn);
167 assert_connection_ok(conn, time(NULL));
169 /* teardown the connection as fast as possible */
170 if (conn->linked_conn) {
171 assert_connection_ok(conn->linked_conn, time(NULL));
173 /* We didn't call tor_libevent_initialize(), so event_base was NULL,
174 * so we can't rely on connection_unregister_events() use of event_del().
176 if (conn->linked_conn->read_event) {
177 tor_free(conn->linked_conn->read_event);
178 conn->linked_conn->read_event = NULL;
180 if (conn->linked_conn->write_event) {
181 tor_free(conn->linked_conn->write_event);
182 conn->linked_conn->write_event = NULL;
185 connection_free(conn->linked_conn);
186 conn->linked_conn = NULL;
188 conn->linked_conn->linked_conn = NULL;
189 if (!conn->linked_conn->marked_for_close) {
190 connection_close_immediate(conn->linked_conn);
191 connection_mark_for_close(conn->linked_conn);
195 /* We didn't set the events up properly, so we can't use event_del() in
196 * close_closeable_connections() > connection_free()
197 * > connection_unregister_events() */
198 if (conn->read_event) {
199 tor_free(conn->read_event);
200 conn->read_event = NULL;
202 if (conn->write_event) {
203 tor_free(conn->write_event);
204 conn->write_event = NULL;
207 if (!conn->marked_for_close) {
208 connection_close_immediate(conn);
209 connection_mark_for_close(conn);
212 close_closeable_connections();
214 /* The unit test will fail if we return 0 */
215 return 1;
217 /* When conn == NULL, we can't cleanup anything */
218 done:
219 return 0;
222 static void *
223 test_conn_get_rend_setup(const struct testcase_t *tc)
225 dir_connection_t *conn = DOWNCAST(dir_connection_t,
226 test_conn_get_basic_setup(tc));
227 tt_assert(conn);
228 assert_connection_ok(&conn->base_, time(NULL));
230 rend_cache_init();
232 /* TODO: use directory_initiate_command_rend() to do this - maybe? */
233 conn->rend_data = tor_malloc_zero(sizeof(rend_data_t));
234 memcpy(conn->rend_data->onion_address,
235 TEST_CONN_REND_ADDR,
236 REND_SERVICE_ADDRESS_LEN+1);
237 conn->rend_data->hsdirs_fp = smartlist_new();
238 conn->base_.purpose = TEST_CONN_REND_PURPOSE;
240 assert_connection_ok(&conn->base_, time(NULL));
241 return conn;
243 /* On failure */
244 done:
245 test_conn_get_rend_teardown(tc, conn);
246 /* Returning NULL causes the unit test to fail */
247 return NULL;
250 static int
251 test_conn_get_rend_teardown(const struct testcase_t *tc, void *arg)
253 dir_connection_t *conn = DOWNCAST(dir_connection_t, arg);
254 int rv = 0;
256 tt_assert(conn);
257 assert_connection_ok(&conn->base_, time(NULL));
259 /* avoid a last-ditch attempt to refetch the descriptor */
260 conn->base_.purpose = TEST_CONN_REND_PURPOSE_SUCCESSFUL;
262 /* connection_free_() cleans up rend_data */
263 rv = test_conn_get_basic_teardown(tc, arg);
264 done:
265 rend_cache_free_all();
266 return rv;
269 static void *
270 test_conn_get_rsrc_setup(const struct testcase_t *tc)
272 dir_connection_t *conn = DOWNCAST(dir_connection_t,
273 test_conn_get_basic_setup(tc));
274 tt_assert(conn);
275 assert_connection_ok(&conn->base_, time(NULL));
277 /* TODO: use the canonical function to do this - maybe? */
278 conn->requested_resource = tor_strdup(TEST_CONN_RSRC);
279 conn->base_.purpose = TEST_CONN_RSRC_PURPOSE;
281 assert_connection_ok(&conn->base_, time(NULL));
282 return conn;
284 /* On failure */
285 done:
286 test_conn_get_rend_teardown(tc, conn);
287 /* Returning NULL causes the unit test to fail */
288 return NULL;
291 static int
292 test_conn_get_rsrc_teardown(const struct testcase_t *tc, void *arg)
294 dir_connection_t *conn = DOWNCAST(dir_connection_t, arg);
295 int rv = 0;
297 tt_assert(conn);
298 assert_connection_ok(&conn->base_, time(NULL));
300 /* avoid a last-ditch attempt to refetch the consensus */
301 conn->base_.state = TEST_CONN_RSRC_STATE_SUCCESSFUL;
303 /* connection_free_() cleans up requested_resource */
304 rv = test_conn_get_basic_teardown(tc, arg);
305 done:
306 return rv;
309 static void *
310 test_conn_download_status_setup(const struct testcase_t *tc)
312 (void)tc;
314 /* Don't return NULL, that causes the test to fail */
315 return "ok";
318 static int
319 test_conn_download_status_teardown(const struct testcase_t *tc, void *arg)
321 (void)arg;
322 int rv = 0;
324 /* Ignore arg, and just loop through the connection array */
325 SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) {
326 if (conn) {
327 assert_connection_ok(conn, time(NULL));
329 /* connection_free_() cleans up requested_resource */
330 rv = test_conn_get_rsrc_teardown(tc, conn);
331 tt_assert(rv == 1);
333 } SMARTLIST_FOREACH_END(conn);
335 done:
336 return rv;
339 static dir_connection_t *
340 test_conn_download_status_add_a_connection(void)
342 dir_connection_t *conn = DOWNCAST(dir_connection_t,
343 test_conn_get_rsrc_setup(NULL));
345 tt_assert(conn);
346 assert_connection_ok(&conn->base_, time(NULL));
348 return conn;
350 done:
351 test_conn_download_status_teardown(NULL, NULL);
352 return NULL;
355 static struct testcase_setup_t test_conn_get_basic_st = {
356 test_conn_get_basic_setup, test_conn_get_basic_teardown
359 static struct testcase_setup_t test_conn_get_rend_st = {
360 test_conn_get_rend_setup, test_conn_get_rend_teardown
363 static struct testcase_setup_t test_conn_get_rsrc_st = {
364 test_conn_get_rsrc_setup, test_conn_get_rsrc_teardown
367 static struct testcase_setup_t test_conn_download_status_st = {
368 test_conn_download_status_setup, test_conn_download_status_teardown
371 static void
372 test_conn_get_basic(void *arg)
374 connection_t *conn = (connection_t*)arg;
375 tor_addr_t addr, addr2;
377 tt_assert(conn);
378 assert_connection_ok(conn, time(NULL));
380 test_conn_lookup_addr_helper(TEST_CONN_ADDRESS, TEST_CONN_FAMILY, &addr);
381 tt_assert(!tor_addr_is_null(&addr));
382 test_conn_lookup_addr_helper(TEST_CONN_ADDRESS_2, TEST_CONN_FAMILY, &addr2);
383 tt_assert(!tor_addr_is_null(&addr2));
385 /* Check that we get this connection back when we search for it by
386 * its attributes, but get NULL when we supply a different value. */
388 tt_assert(connection_get_by_global_id(conn->global_identifier) == conn);
389 tt_assert(connection_get_by_global_id(!conn->global_identifier) == NULL);
391 tt_assert(connection_get_by_type(conn->type) == conn);
392 tt_assert(connection_get_by_type(TEST_CONN_TYPE) == conn);
393 tt_assert(connection_get_by_type(!conn->type) == NULL);
394 tt_assert(connection_get_by_type(!TEST_CONN_TYPE) == NULL);
396 tt_assert(connection_get_by_type_state(conn->type, conn->state)
397 == conn);
398 tt_assert(connection_get_by_type_state(TEST_CONN_TYPE, TEST_CONN_STATE)
399 == conn);
400 tt_assert(connection_get_by_type_state(!conn->type, !conn->state)
401 == NULL);
402 tt_assert(connection_get_by_type_state(!TEST_CONN_TYPE, !TEST_CONN_STATE)
403 == NULL);
405 /* Match on the connection fields themselves */
406 tt_assert(connection_get_by_type_addr_port_purpose(conn->type,
407 &conn->addr,
408 conn->port,
409 conn->purpose)
410 == conn);
411 /* Match on the original inputs to the connection */
412 tt_assert(connection_get_by_type_addr_port_purpose(TEST_CONN_TYPE,
413 &conn->addr,
414 conn->port,
415 conn->purpose)
416 == conn);
417 tt_assert(connection_get_by_type_addr_port_purpose(conn->type,
418 &addr,
419 conn->port,
420 conn->purpose)
421 == conn);
422 tt_assert(connection_get_by_type_addr_port_purpose(conn->type,
423 &conn->addr,
424 TEST_CONN_PORT,
425 conn->purpose)
426 == conn);
427 tt_assert(connection_get_by_type_addr_port_purpose(conn->type,
428 &conn->addr,
429 conn->port,
430 TEST_CONN_BASIC_PURPOSE)
431 == conn);
432 tt_assert(connection_get_by_type_addr_port_purpose(TEST_CONN_TYPE,
433 &addr,
434 TEST_CONN_PORT,
435 TEST_CONN_BASIC_PURPOSE)
436 == conn);
437 /* Then try each of the not-matching combinations */
438 tt_assert(connection_get_by_type_addr_port_purpose(!conn->type,
439 &conn->addr,
440 conn->port,
441 conn->purpose)
442 == NULL);
443 tt_assert(connection_get_by_type_addr_port_purpose(conn->type,
444 &addr2,
445 conn->port,
446 conn->purpose)
447 == NULL);
448 tt_assert(connection_get_by_type_addr_port_purpose(conn->type,
449 &conn->addr,
450 !conn->port,
451 conn->purpose)
452 == NULL);
453 tt_assert(connection_get_by_type_addr_port_purpose(conn->type,
454 &conn->addr,
455 conn->port,
456 !conn->purpose)
457 == NULL);
458 /* Then try everything not-matching */
459 tt_assert(connection_get_by_type_addr_port_purpose(!conn->type,
460 &addr2,
461 !conn->port,
462 !conn->purpose)
463 == NULL);
464 tt_assert(connection_get_by_type_addr_port_purpose(!TEST_CONN_TYPE,
465 &addr2,
466 !TEST_CONN_PORT,
467 !TEST_CONN_BASIC_PURPOSE)
468 == NULL);
470 done:
474 static void
475 test_conn_get_rend(void *arg)
477 dir_connection_t *conn = DOWNCAST(dir_connection_t, arg);
478 tt_assert(conn);
479 assert_connection_ok(&conn->base_, time(NULL));
481 tt_assert(connection_get_by_type_state_rendquery(
482 conn->base_.type,
483 conn->base_.state,
484 conn->rend_data->onion_address)
485 == TO_CONN(conn));
486 tt_assert(connection_get_by_type_state_rendquery(
487 TEST_CONN_TYPE,
488 TEST_CONN_STATE,
489 TEST_CONN_REND_ADDR)
490 == TO_CONN(conn));
491 tt_assert(connection_get_by_type_state_rendquery(TEST_CONN_REND_TYPE_2,
492 !conn->base_.state,
494 == NULL);
495 tt_assert(connection_get_by_type_state_rendquery(TEST_CONN_REND_TYPE_2,
496 !TEST_CONN_STATE,
497 TEST_CONN_REND_ADDR_2)
498 == NULL);
500 done:
504 #define sl_is_conn_assert(sl, conn) \
505 do { \
506 tt_assert(smartlist_len((sl)) == 1); \
507 tt_assert(smartlist_get((sl), 0) == (conn)); \
508 } while (0)
510 #define sl_no_conn_assert(sl) \
511 do { \
512 tt_assert(smartlist_len((sl)) == 0); \
513 } while (0)
515 static void
516 test_conn_get_rsrc(void *arg)
518 dir_connection_t *conn = DOWNCAST(dir_connection_t, arg);
519 tt_assert(conn);
520 assert_connection_ok(&conn->base_, time(NULL));
522 tt_assert(connection_dir_get_by_purpose_and_resource(
523 conn->base_.purpose,
524 conn->requested_resource)
525 == conn);
526 tt_assert(connection_dir_get_by_purpose_and_resource(
527 TEST_CONN_RSRC_PURPOSE,
528 TEST_CONN_RSRC)
529 == conn);
530 tt_assert(connection_dir_get_by_purpose_and_resource(
531 !conn->base_.purpose,
533 == NULL);
534 tt_assert(connection_dir_get_by_purpose_and_resource(
535 !TEST_CONN_RSRC_PURPOSE,
536 TEST_CONN_RSRC_2)
537 == NULL);
539 tt_assert(connection_dir_get_by_purpose_resource_and_state(
540 conn->base_.purpose,
541 conn->requested_resource,
542 conn->base_.state)
543 == conn);
544 tt_assert(connection_dir_get_by_purpose_resource_and_state(
545 TEST_CONN_RSRC_PURPOSE,
546 TEST_CONN_RSRC,
547 TEST_CONN_STATE)
548 == conn);
549 tt_assert(connection_dir_get_by_purpose_resource_and_state(
550 !conn->base_.purpose,
552 !conn->base_.state)
553 == NULL);
554 tt_assert(connection_dir_get_by_purpose_resource_and_state(
555 !TEST_CONN_RSRC_PURPOSE,
556 TEST_CONN_RSRC_2,
557 !TEST_CONN_STATE)
558 == NULL);
560 sl_is_conn_assert(connection_dir_list_by_purpose_and_resource(
561 conn->base_.purpose,
562 conn->requested_resource),
563 conn);
564 sl_is_conn_assert(connection_dir_list_by_purpose_and_resource(
565 TEST_CONN_RSRC_PURPOSE,
566 TEST_CONN_RSRC),
567 conn);
568 sl_no_conn_assert(connection_dir_list_by_purpose_and_resource(
569 !conn->base_.purpose,
570 ""));
571 sl_no_conn_assert(connection_dir_list_by_purpose_and_resource(
572 !TEST_CONN_RSRC_PURPOSE,
573 TEST_CONN_RSRC_2));
575 sl_is_conn_assert(connection_dir_list_by_purpose_resource_and_state(
576 conn->base_.purpose,
577 conn->requested_resource,
578 conn->base_.state),
579 conn);
580 sl_is_conn_assert(connection_dir_list_by_purpose_resource_and_state(
581 TEST_CONN_RSRC_PURPOSE,
582 TEST_CONN_RSRC,
583 TEST_CONN_STATE),
584 conn);
585 sl_no_conn_assert(connection_dir_list_by_purpose_resource_and_state(
586 !conn->base_.purpose,
588 !conn->base_.state));
589 sl_no_conn_assert(connection_dir_list_by_purpose_resource_and_state(
590 !TEST_CONN_RSRC_PURPOSE,
591 TEST_CONN_RSRC_2,
592 !TEST_CONN_STATE));
594 tt_assert(connection_dir_count_by_purpose_and_resource(
595 conn->base_.purpose,
596 conn->requested_resource)
597 == 1);
598 tt_assert(connection_dir_count_by_purpose_and_resource(
599 TEST_CONN_RSRC_PURPOSE,
600 TEST_CONN_RSRC)
601 == 1);
602 tt_assert(connection_dir_count_by_purpose_and_resource(
603 !conn->base_.purpose,
605 == 0);
606 tt_assert(connection_dir_count_by_purpose_and_resource(
607 !TEST_CONN_RSRC_PURPOSE,
608 TEST_CONN_RSRC_2)
609 == 0);
611 tt_assert(connection_dir_count_by_purpose_resource_and_state(
612 conn->base_.purpose,
613 conn->requested_resource,
614 conn->base_.state)
615 == 1);
616 tt_assert(connection_dir_count_by_purpose_resource_and_state(
617 TEST_CONN_RSRC_PURPOSE,
618 TEST_CONN_RSRC,
619 TEST_CONN_STATE)
620 == 1);
621 tt_assert(connection_dir_count_by_purpose_resource_and_state(
622 !conn->base_.purpose,
624 !conn->base_.state)
625 == 0);
626 tt_assert(connection_dir_count_by_purpose_resource_and_state(
627 !TEST_CONN_RSRC_PURPOSE,
628 TEST_CONN_RSRC_2,
629 !TEST_CONN_STATE)
630 == 0);
632 done:
636 static void
637 test_conn_download_status(void *arg)
639 (void)arg;
640 dir_connection_t *conn = NULL;
641 dir_connection_t *conn2 = NULL;
642 dir_connection_t *conn3 = NULL;
644 /* no connections, no excess, not downloading */
645 tt_assert(networkstatus_consensus_has_excess_connections() == 0);
646 tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 0);
647 tt_assert(connection_dir_avoid_extra_connection_for_purpose(
648 TEST_CONN_RSRC_PURPOSE) == 0);
650 /* one connection, no excess, not downloading */
651 conn = test_conn_download_status_add_a_connection();
652 tt_assert(networkstatus_consensus_has_excess_connections() == 0);
653 tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 0);
654 tt_assert(connection_dir_avoid_extra_connection_for_purpose(
655 TEST_CONN_RSRC_PURPOSE) == 0);
657 /* one connection, no excess, but downloading */
658 conn->base_.state = TEST_CONN_DL_STATE;
659 tt_assert(networkstatus_consensus_has_excess_connections() == 0);
660 tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 1);
661 tt_assert(connection_dir_avoid_extra_connection_for_purpose(
662 TEST_CONN_RSRC_PURPOSE) == 1);
663 conn->base_.state = TEST_CONN_STATE;
665 /* two connections, excess, but not downloading */
666 conn2 = test_conn_download_status_add_a_connection();
667 tt_assert(networkstatus_consensus_has_excess_connections() == 1);
668 tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 0);
669 tt_assert(connection_dir_avoid_extra_connection_for_purpose(
670 TEST_CONN_RSRC_PURPOSE) == 0);
672 /* two connections, excess, downloading */
673 conn2->base_.state = TEST_CONN_DL_STATE;
674 tt_assert(networkstatus_consensus_has_excess_connections() == 1);
675 tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 1);
676 tt_assert(connection_dir_avoid_extra_connection_for_purpose(
677 TEST_CONN_RSRC_PURPOSE) == 1);
678 conn2->base_.state = TEST_CONN_STATE;
680 /* more connections, excess, but not downloading */
681 conn3 = test_conn_download_status_add_a_connection();
682 tt_assert(networkstatus_consensus_has_excess_connections() == 1);
683 tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 0);
684 tt_assert(connection_dir_avoid_extra_connection_for_purpose(
685 TEST_CONN_RSRC_PURPOSE) == 0);
687 /* more connections, excess, downloading */
688 conn3->base_.state = TEST_CONN_DL_STATE;
689 tt_assert(networkstatus_consensus_has_excess_connections() == 1);
690 tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 1);
691 tt_assert(connection_dir_avoid_extra_connection_for_purpose(
692 TEST_CONN_RSRC_PURPOSE) == 1);
694 /* more connections, more downloading */
695 conn2->base_.state = TEST_CONN_DL_STATE;
696 tt_assert(networkstatus_consensus_has_excess_connections() == 1);
697 tt_assert(networkstatus_consensus_is_downloading_usable_flavor() == 1);
698 tt_assert(connection_dir_avoid_extra_connection_for_purpose(
699 TEST_CONN_RSRC_PURPOSE) == 1);
701 /* now try closing the one that isn't downloading:
702 * these tests won't work unless tor thinks it is bootstrapping */
703 tt_assert(networkstatus_consensus_is_boostrapping(time(NULL)));
705 tt_assert(connection_dir_count_by_purpose_and_resource(
706 TEST_CONN_RSRC_PURPOSE,
707 TEST_CONN_RSRC) == 3);
708 tt_assert(connection_dir_avoid_extra_connection_for_purpose(
709 TEST_CONN_RSRC_PURPOSE) == 1);
710 tt_assert(connection_dir_close_consensus_conn_if_extra(conn) == -1);
711 tt_assert(connection_dir_count_by_purpose_and_resource(
712 TEST_CONN_RSRC_PURPOSE,
713 TEST_CONN_RSRC) == 2);
714 tt_assert(connection_dir_avoid_extra_connection_for_purpose(
715 TEST_CONN_RSRC_PURPOSE) == 1);
717 /* now try closing one that is already closed - nothing happens */
718 tt_assert(connection_dir_close_consensus_conn_if_extra(conn) == 0);
719 tt_assert(connection_dir_count_by_purpose_and_resource(
720 TEST_CONN_RSRC_PURPOSE,
721 TEST_CONN_RSRC) == 2);
722 tt_assert(connection_dir_avoid_extra_connection_for_purpose(
723 TEST_CONN_RSRC_PURPOSE) == 1);
726 /* now try closing one that is downloading - it stays open */
727 tt_assert(connection_dir_close_consensus_conn_if_extra(conn2) == 0);
728 tt_assert(connection_dir_count_by_purpose_and_resource(
729 TEST_CONN_RSRC_PURPOSE,
730 TEST_CONN_RSRC) == 2);
731 tt_assert(connection_dir_avoid_extra_connection_for_purpose(
732 TEST_CONN_RSRC_PURPOSE) == 1);
734 /* now try closing all excess connections */
735 connection_dir_close_extra_consensus_conns();
736 tt_assert(connection_dir_count_by_purpose_and_resource(
737 TEST_CONN_RSRC_PURPOSE,
738 TEST_CONN_RSRC) == 1);
739 tt_assert(connection_dir_avoid_extra_connection_for_purpose(
740 TEST_CONN_RSRC_PURPOSE) == 1);
742 done:
743 /* the teardown function removes all the connections */;
746 #define CONNECTION_TESTCASE(name, fork, setup) \
747 { #name, test_conn_##name, fork, &setup, NULL }
749 struct testcase_t connection_tests[] = {
750 CONNECTION_TESTCASE(get_basic, TT_FORK, test_conn_get_basic_st),
751 CONNECTION_TESTCASE(get_rend, TT_FORK, test_conn_get_rend_st),
752 CONNECTION_TESTCASE(get_rsrc, TT_FORK, test_conn_get_rsrc_st),
753 CONNECTION_TESTCASE(download_status, TT_FORK, test_conn_download_status_st),
754 //CONNECTION_TESTCASE(func_suffix, TT_FORK, setup_func_pair),
755 END_OF_TESTCASES