1 /* Copyright (c) 2015-2021, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
6 #define CONNECTION_PRIVATE
7 #define MAINLOOP_PRIVATE
8 #define CONNECTION_OR_PRIVATE
10 #include "core/or/or.h"
11 #include "test/test.h"
13 #include "app/config/config.h"
14 #include "app/config/or_options_st.h"
15 #include "core/mainloop/connection.h"
16 #include "core/or/connection_edge.h"
17 #include "feature/hs/hs_common.h"
18 #include "core/mainloop/mainloop.h"
19 #include "feature/nodelist/microdesc.h"
20 #include "feature/nodelist/nodelist.h"
21 #include "feature/nodelist/networkstatus.h"
22 #include "feature/dircommon/directory.h"
23 #include "core/or/connection_or.h"
24 #include "lib/net/resolve.h"
25 #include "lib/evloop/compat_libevent.h"
27 #include "test/test_connection.h"
28 #include "test/test_helpers.h"
30 #include "feature/dircommon/dir_connection_st.h"
31 #include "core/or/entry_connection_st.h"
32 #include "feature/nodelist/node_st.h"
33 #include "core/or/or_connection_st.h"
34 #include "feature/nodelist/routerinfo_st.h"
35 #include "core/or/socks_request_st.h"
37 static void * test_conn_get_basic_setup(const struct testcase_t
*tc
);
38 static int test_conn_get_basic_teardown(const struct testcase_t
*tc
,
41 static void * test_conn_get_rsrc_setup(const struct testcase_t
*tc
);
42 static int test_conn_get_rsrc_teardown(const struct testcase_t
*tc
,
45 /* Arbitrary choice - IPv4 Directory Connection to localhost */
46 #define TEST_CONN_TYPE (CONN_TYPE_DIR)
47 /* We assume every machine has IPv4 localhost, is that ok? */
48 #define TEST_CONN_ADDRESS "127.0.0.1"
49 #define TEST_CONN_PORT (12345)
50 #define TEST_CONN_ADDRESS_PORT "127.0.0.1:12345"
51 #define TEST_CONN_FAMILY (AF_INET)
52 #define TEST_CONN_STATE (DIR_CONN_STATE_MIN_)
53 #define TEST_CONN_ADDRESS_2 "127.0.0.2"
55 #define TEST_CONN_BASIC_PURPOSE (DIR_PURPOSE_MIN_)
57 #define TEST_CONN_REND_ADDR "cfs3rltphxxvabci"
58 #define TEST_CONN_REND_PURPOSE (DIR_PURPOSE_FETCH_RENDDESC_V2)
59 #define TEST_CONN_REND_PURPOSE_SUCCESSFUL (DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2)
60 #define TEST_CONN_REND_TYPE_2 (CONN_TYPE_AP)
61 #define TEST_CONN_REND_ADDR_2 "icbavxxhptlr3sfc"
63 #define TEST_CONN_RSRC (networkstatus_get_flavor_name(FLAV_MICRODESC))
64 #define TEST_CONN_RSRC_PURPOSE (DIR_PURPOSE_FETCH_CONSENSUS)
65 #define TEST_CONN_RSRC_STATE_SUCCESSFUL (DIR_CONN_STATE_CLIENT_FINISHED)
66 #define TEST_CONN_RSRC_2 (networkstatus_get_flavor_name(FLAV_NS))
68 #define TEST_CONN_DL_STATE (DIR_CONN_STATE_CLIENT_READING)
70 /* see AP_CONN_STATE_IS_UNATTACHED() */
71 #define TEST_CONN_UNATTACHED_STATE (AP_CONN_STATE_CIRCUIT_WAIT)
72 #define TEST_CONN_ATTACHED_STATE (AP_CONN_STATE_CONNECT_WAIT)
75 test_conn_lookup_addr_helper(const char *address
, int family
, tor_addr_t
*addr
)
81 rv
= tor_addr_lookup(address
, family
, addr
);
82 /* XXXX - should we retry on transient failure? */
83 tt_int_op(rv
, OP_EQ
, 0);
84 tt_assert(tor_addr_is_loopback(addr
));
85 tt_assert(tor_addr_is_v4(addr
));
90 tor_addr_make_null(addr
, TEST_CONN_FAMILY
);
94 test_conn_get_basic_setup(const struct testcase_t
*tc
)
97 return test_conn_get_connection(TEST_CONN_STATE
, TEST_CONN_TYPE
,
98 TEST_CONN_BASIC_PURPOSE
);
102 test_conn_get_basic_teardown(const struct testcase_t
*tc
, void *arg
)
105 connection_t
*conn
= arg
;
108 assert_connection_ok(conn
, time(NULL
));
110 /* teardown the connection as fast as possible */
111 if (conn
->linked_conn
) {
112 assert_connection_ok(conn
->linked_conn
, time(NULL
));
114 /* We didn't call tor_libevent_initialize(), so event_base was NULL,
115 * so we can't rely on connection_unregister_events() use of event_del().
117 tor_event_free(conn
->linked_conn
->read_event
);
118 tor_event_free(conn
->linked_conn
->write_event
);
120 if (!conn
->linked_conn
->marked_for_close
) {
121 connection_close_immediate(conn
->linked_conn
);
122 if (CONN_IS_EDGE(conn
->linked_conn
)) {
123 /* Suppress warnings about all the stuff we didn't do */
124 TO_EDGE_CONN(conn
->linked_conn
)->edge_has_sent_end
= 1;
125 TO_EDGE_CONN(conn
->linked_conn
)->end_reason
=
126 END_STREAM_REASON_INTERNAL
;
127 if (conn
->linked_conn
->type
== CONN_TYPE_AP
) {
128 TO_ENTRY_CONN(conn
->linked_conn
)->socks_request
->has_finished
= 1;
131 connection_mark_for_close(conn
->linked_conn
);
134 close_closeable_connections();
137 /* We didn't set the events up properly, so we can't use event_del() in
138 * close_closeable_connections() > connection_free()
139 * > connection_unregister_events() */
140 tor_event_free(conn
->read_event
);
141 tor_event_free(conn
->write_event
);
143 if (!conn
->marked_for_close
) {
144 connection_close_immediate(conn
);
145 if (CONN_IS_EDGE(conn
)) {
146 /* Suppress warnings about all the stuff we didn't do */
147 TO_EDGE_CONN(conn
)->edge_has_sent_end
= 1;
148 TO_EDGE_CONN(conn
)->end_reason
= END_STREAM_REASON_INTERNAL
;
149 if (conn
->type
== CONN_TYPE_AP
) {
150 TO_ENTRY_CONN(conn
)->socks_request
->has_finished
= 1;
153 connection_mark_for_close(conn
);
156 close_closeable_connections();
158 /* The unit test will fail if we return 0 */
161 /* When conn == NULL, we can't cleanup anything */
166 static dir_connection_t
*
167 test_conn_download_status_add_a_connection(const char *resource
)
169 dir_connection_t
*conn
= DOWNCAST(dir_connection_t
,
170 test_conn_get_connection(
173 TEST_CONN_RSRC_PURPOSE
));
176 assert_connection_ok(&conn
->base_
, time(NULL
));
178 /* Replace the existing resource with the one we want */
180 if (conn
->requested_resource
) {
181 tor_free(conn
->requested_resource
);
183 conn
->requested_resource
= tor_strdup(resource
);
184 assert_connection_ok(&conn
->base_
, time(NULL
));
190 test_conn_get_rsrc_teardown(NULL
, conn
);
195 test_conn_get_rsrc_setup(const struct testcase_t
*tc
)
198 return test_conn_download_status_add_a_connection(TEST_CONN_RSRC
);
202 test_conn_get_rsrc_teardown(const struct testcase_t
*tc
, void *arg
)
206 connection_t
*conn
= (connection_t
*)arg
;
208 assert_connection_ok(conn
, time(NULL
));
210 if (conn
->type
== CONN_TYPE_DIR
) {
211 dir_connection_t
*dir_conn
= DOWNCAST(dir_connection_t
, arg
);
214 assert_connection_ok(&dir_conn
->base_
, time(NULL
));
216 /* avoid a last-ditch attempt to refetch the consensus */
217 dir_conn
->base_
.state
= TEST_CONN_RSRC_STATE_SUCCESSFUL
;
218 assert_connection_ok(&dir_conn
->base_
, time(NULL
));
221 /* connection_free_() cleans up requested_resource */
222 rv
= test_conn_get_basic_teardown(tc
, conn
);
229 test_conn_download_status_setup(const struct testcase_t
*tc
)
235 test_conn_download_status_teardown(const struct testcase_t
*tc
, void *arg
)
240 /* Ignore arg, and just loop through the connection array */
241 SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t
*, conn
) {
243 assert_connection_ok(conn
, time(NULL
));
245 /* connection_free_() cleans up requested_resource */
246 rv
= test_conn_get_rsrc_teardown(tc
, conn
);
247 tt_int_op(rv
, OP_EQ
, 1);
249 } SMARTLIST_FOREACH_END(conn
);
256 test_conn_proxy_connect_setup(const struct testcase_t
*tc
)
258 return test_conn_get_proxy_or_connection(*(unsigned int *)tc
->setup_data
);
262 test_conn_proxy_connect_teardown(const struct testcase_t
*tc
, void *arg
)
265 or_connection_t
*conn
= arg
;
268 assert_connection_ok(&conn
->base_
, time(NULL
));
274 /* Like connection_ap_make_link(), but does much less */
275 static connection_t
*
276 test_conn_get_linked_connection(connection_t
*l_conn
, uint8_t state
)
279 assert_connection_ok(l_conn
, time(NULL
));
281 /* AP connections don't seem to have purposes */
282 connection_t
*conn
= test_conn_get_connection(state
, CONN_TYPE_AP
,
286 assert_connection_ok(conn
, time(NULL
));
290 conn
->linked_conn
= l_conn
;
291 l_conn
->linked_conn
= conn
;
292 /* we never opened a real socket, so we can just overwrite it */
293 conn
->s
= TOR_INVALID_SOCKET
;
294 l_conn
->s
= TOR_INVALID_SOCKET
;
296 assert_connection_ok(conn
, time(NULL
));
297 assert_connection_ok(l_conn
, time(NULL
));
302 test_conn_download_status_teardown(NULL
, NULL
);
306 static struct testcase_setup_t test_conn_get_basic_st
= {
307 test_conn_get_basic_setup
, test_conn_get_basic_teardown
310 static struct testcase_setup_t test_conn_get_rsrc_st
= {
311 test_conn_get_rsrc_setup
, test_conn_get_rsrc_teardown
314 static struct testcase_setup_t test_conn_download_status_st
= {
315 test_conn_download_status_setup
, test_conn_download_status_teardown
318 static struct testcase_setup_t test_conn_proxy_connect_st
= {
319 test_conn_proxy_connect_setup
, test_conn_proxy_connect_teardown
323 test_conn_get_basic(void *arg
)
325 connection_t
*conn
= (connection_t
*)arg
;
326 tor_addr_t addr
, addr2
;
329 assert_connection_ok(conn
, time(NULL
));
331 test_conn_lookup_addr_helper(TEST_CONN_ADDRESS
, TEST_CONN_FAMILY
, &addr
);
332 tt_assert(!tor_addr_is_null(&addr
));
333 test_conn_lookup_addr_helper(TEST_CONN_ADDRESS_2
, TEST_CONN_FAMILY
, &addr2
);
334 tt_assert(!tor_addr_is_null(&addr2
));
336 /* Check that we get this connection back when we search for it by
337 * its attributes, but get NULL when we supply a different value. */
339 tt_assert(connection_get_by_global_id(conn
->global_identifier
) == conn
);
340 tt_ptr_op(connection_get_by_global_id(!conn
->global_identifier
), OP_EQ
,
343 tt_assert(connection_get_by_type(conn
->type
) == conn
);
344 tt_assert(connection_get_by_type(TEST_CONN_TYPE
) == conn
);
345 tt_ptr_op(connection_get_by_type(!conn
->type
), OP_EQ
, NULL
);
346 tt_ptr_op(connection_get_by_type(!TEST_CONN_TYPE
), OP_EQ
, NULL
);
348 tt_assert(connection_get_by_type_state(conn
->type
, conn
->state
)
350 tt_assert(connection_get_by_type_state(TEST_CONN_TYPE
, TEST_CONN_STATE
)
352 tt_assert(connection_get_by_type_state(!conn
->type
, !conn
->state
)
354 tt_assert(connection_get_by_type_state(!TEST_CONN_TYPE
, !TEST_CONN_STATE
)
357 /* Match on the connection fields themselves */
358 tt_assert(connection_get_by_type_addr_port_purpose(conn
->type
,
363 /* Match on the original inputs to the connection */
364 tt_assert(connection_get_by_type_addr_port_purpose(TEST_CONN_TYPE
,
369 tt_assert(connection_get_by_type_addr_port_purpose(conn
->type
,
374 tt_assert(connection_get_by_type_addr_port_purpose(conn
->type
,
379 tt_assert(connection_get_by_type_addr_port_purpose(conn
->type
,
382 TEST_CONN_BASIC_PURPOSE
)
384 tt_assert(connection_get_by_type_addr_port_purpose(TEST_CONN_TYPE
,
387 TEST_CONN_BASIC_PURPOSE
)
389 /* Then try each of the not-matching combinations */
390 tt_assert(connection_get_by_type_addr_port_purpose(!conn
->type
,
395 tt_assert(connection_get_by_type_addr_port_purpose(conn
->type
,
400 tt_assert(connection_get_by_type_addr_port_purpose(conn
->type
,
405 tt_assert(connection_get_by_type_addr_port_purpose(conn
->type
,
410 /* Then try everything not-matching */
411 tt_assert(connection_get_by_type_addr_port_purpose(!conn
->type
,
416 tt_assert(connection_get_by_type_addr_port_purpose(!TEST_CONN_TYPE
,
419 !TEST_CONN_BASIC_PURPOSE
)
426 #define sl_is_conn_assert(sl_input, conn) \
428 the_sl = (sl_input); \
429 tt_int_op(smartlist_len((the_sl)), OP_EQ, 1); \
430 tt_assert(smartlist_get((the_sl), 0) == (conn)); \
431 smartlist_free(the_sl); the_sl = NULL; \
434 #define sl_no_conn_assert(sl_input) \
436 the_sl = (sl_input); \
437 tt_int_op(smartlist_len((the_sl)), OP_EQ, 0); \
438 smartlist_free(the_sl); the_sl = NULL; \
442 test_conn_get_rsrc(void *arg
)
444 dir_connection_t
*conn
= DOWNCAST(dir_connection_t
, arg
);
445 smartlist_t
*the_sl
= NULL
;
447 assert_connection_ok(&conn
->base_
, time(NULL
));
449 sl_is_conn_assert(connection_dir_list_by_purpose_and_resource(
451 conn
->requested_resource
),
453 sl_is_conn_assert(connection_dir_list_by_purpose_and_resource(
454 TEST_CONN_RSRC_PURPOSE
,
457 sl_no_conn_assert(connection_dir_list_by_purpose_and_resource(
458 !conn
->base_
.purpose
,
460 sl_no_conn_assert(connection_dir_list_by_purpose_and_resource(
461 !TEST_CONN_RSRC_PURPOSE
,
464 sl_is_conn_assert(connection_dir_list_by_purpose_resource_and_state(
466 conn
->requested_resource
,
469 sl_is_conn_assert(connection_dir_list_by_purpose_resource_and_state(
470 TEST_CONN_RSRC_PURPOSE
,
474 sl_no_conn_assert(connection_dir_list_by_purpose_resource_and_state(
475 !conn
->base_
.purpose
,
477 !conn
->base_
.state
));
478 sl_no_conn_assert(connection_dir_list_by_purpose_resource_and_state(
479 !TEST_CONN_RSRC_PURPOSE
,
483 tt_int_op(connection_dir_count_by_purpose_and_resource(
484 conn
->base_
.purpose
, conn
->requested_resource
),
486 tt_int_op(connection_dir_count_by_purpose_and_resource(
487 TEST_CONN_RSRC_PURPOSE
, TEST_CONN_RSRC
),
489 tt_int_op(connection_dir_count_by_purpose_and_resource(
490 !conn
->base_
.purpose
, ""),
492 tt_int_op(connection_dir_count_by_purpose_and_resource(
493 !TEST_CONN_RSRC_PURPOSE
, TEST_CONN_RSRC_2
),
496 tt_int_op(connection_dir_count_by_purpose_resource_and_state(
497 conn
->base_
.purpose
, conn
->requested_resource
,
500 tt_int_op(connection_dir_count_by_purpose_resource_and_state(
501 TEST_CONN_RSRC_PURPOSE
, TEST_CONN_RSRC
, TEST_CONN_STATE
),
503 tt_int_op(connection_dir_count_by_purpose_resource_and_state(
504 !conn
->base_
.purpose
, "", !conn
->base_
.state
),
506 tt_int_op(connection_dir_count_by_purpose_resource_and_state(
507 !TEST_CONN_RSRC_PURPOSE
, TEST_CONN_RSRC_2
, !TEST_CONN_STATE
),
511 smartlist_free(the_sl
);
515 test_conn_download_status(void *arg
)
517 dir_connection_t
*conn
= NULL
;
518 dir_connection_t
*conn2
= NULL
;
519 dir_connection_t
*conn4
= NULL
;
520 connection_t
*ap_conn
= NULL
;
522 const struct testcase_t
*tc
= arg
;
523 consensus_flavor_t usable_flavor
=
524 networkstatus_parse_flavor_name((const char*) tc
->setup_data
);
526 /* The "other flavor" trick only works if there are two flavors */
527 tor_assert(N_CONSENSUS_FLAVORS
== 2);
528 consensus_flavor_t other_flavor
= ((usable_flavor
== FLAV_NS
)
531 const char *res
= networkstatus_get_flavor_name(usable_flavor
);
532 const char *other_res
= networkstatus_get_flavor_name(other_flavor
);
535 tt_int_op(networkstatus_consensus_is_already_downloading(res
), OP_EQ
, 0);
536 tt_int_op(networkstatus_consensus_is_already_downloading(other_res
), OP_EQ
,
538 tt_int_op(connection_dir_count_by_purpose_and_resource(
539 TEST_CONN_RSRC_PURPOSE
, res
),
541 tt_int_op(connection_dir_count_by_purpose_and_resource(
542 TEST_CONN_RSRC_PURPOSE
, other_res
),
545 /* one connection, not downloading */
546 conn
= test_conn_download_status_add_a_connection(res
);
547 tt_int_op(networkstatus_consensus_is_already_downloading(res
), OP_EQ
, 0);
548 tt_int_op(networkstatus_consensus_is_already_downloading(other_res
), OP_EQ
,
550 tt_int_op(connection_dir_count_by_purpose_and_resource(
551 TEST_CONN_RSRC_PURPOSE
, res
),
553 tt_int_op(connection_dir_count_by_purpose_and_resource(
554 TEST_CONN_RSRC_PURPOSE
, other_res
),
557 /* one connection, downloading but not linked (not possible on a client,
558 * but possible on a relay) */
559 conn
->base_
.state
= TEST_CONN_DL_STATE
;
560 tt_int_op(networkstatus_consensus_is_already_downloading(res
), OP_EQ
, 0);
561 tt_int_op(networkstatus_consensus_is_already_downloading(other_res
), OP_EQ
,
563 tt_int_op(connection_dir_count_by_purpose_and_resource(
564 TEST_CONN_RSRC_PURPOSE
, res
),
566 tt_int_op(connection_dir_count_by_purpose_and_resource(
567 TEST_CONN_RSRC_PURPOSE
, other_res
),
570 /* one connection, downloading and linked, but not yet attached */
571 ap_conn
= test_conn_get_linked_connection(TO_CONN(conn
),
572 TEST_CONN_UNATTACHED_STATE
);
573 tt_int_op(networkstatus_consensus_is_already_downloading(res
), OP_EQ
, 0);
574 tt_int_op(networkstatus_consensus_is_already_downloading(other_res
), OP_EQ
,
576 tt_int_op(connection_dir_count_by_purpose_and_resource(
577 TEST_CONN_RSRC_PURPOSE
, res
),
579 tt_int_op(connection_dir_count_by_purpose_and_resource(
580 TEST_CONN_RSRC_PURPOSE
, other_res
),
583 /* one connection, downloading and linked and attached */
584 ap_conn
->state
= TEST_CONN_ATTACHED_STATE
;
585 tt_int_op(networkstatus_consensus_is_already_downloading(res
), OP_EQ
, 1);
586 tt_int_op(networkstatus_consensus_is_already_downloading(other_res
), OP_EQ
,
588 tt_int_op(connection_dir_count_by_purpose_and_resource(
589 TEST_CONN_RSRC_PURPOSE
, res
),
591 tt_int_op(connection_dir_count_by_purpose_and_resource(
592 TEST_CONN_RSRC_PURPOSE
, other_res
),
595 /* one connection, linked and attached but not downloading */
596 conn
->base_
.state
= TEST_CONN_STATE
;
597 tt_int_op(networkstatus_consensus_is_already_downloading(res
), OP_EQ
, 0);
598 tt_int_op(networkstatus_consensus_is_already_downloading(other_res
), OP_EQ
,
600 tt_int_op(connection_dir_count_by_purpose_and_resource(
601 TEST_CONN_RSRC_PURPOSE
, res
),
603 tt_int_op(connection_dir_count_by_purpose_and_resource(
604 TEST_CONN_RSRC_PURPOSE
, other_res
),
607 /* two connections, both not downloading */
608 conn2
= test_conn_download_status_add_a_connection(res
);
609 tt_int_op(networkstatus_consensus_is_already_downloading(res
), OP_EQ
, 0);
610 tt_int_op(networkstatus_consensus_is_already_downloading(other_res
), OP_EQ
,
612 tt_int_op(connection_dir_count_by_purpose_and_resource(
613 TEST_CONN_RSRC_PURPOSE
, res
),
615 tt_int_op(connection_dir_count_by_purpose_and_resource(
616 TEST_CONN_RSRC_PURPOSE
, other_res
),
619 /* two connections, one downloading */
620 conn
->base_
.state
= TEST_CONN_DL_STATE
;
621 tt_int_op(networkstatus_consensus_is_already_downloading(res
), OP_EQ
, 1);
622 tt_int_op(networkstatus_consensus_is_already_downloading(other_res
), OP_EQ
,
624 tt_int_op(connection_dir_count_by_purpose_and_resource(
625 TEST_CONN_RSRC_PURPOSE
, res
),
627 tt_int_op(connection_dir_count_by_purpose_and_resource(
628 TEST_CONN_RSRC_PURPOSE
, other_res
),
630 conn
->base_
.state
= TEST_CONN_STATE
;
632 /* more connections, all not downloading */
633 /* ignore the return value, it's free'd using the connection list */
634 (void)test_conn_download_status_add_a_connection(res
);
635 tt_int_op(networkstatus_consensus_is_already_downloading(res
), OP_EQ
, 0);
636 tt_int_op(networkstatus_consensus_is_already_downloading(other_res
), OP_EQ
,
638 tt_int_op(connection_dir_count_by_purpose_and_resource(
639 TEST_CONN_RSRC_PURPOSE
, res
),
641 tt_int_op(connection_dir_count_by_purpose_and_resource(
642 TEST_CONN_RSRC_PURPOSE
, other_res
),
645 /* more connections, one downloading */
646 conn
->base_
.state
= TEST_CONN_DL_STATE
;
647 tt_int_op(networkstatus_consensus_is_already_downloading(res
), OP_EQ
, 1);
648 tt_int_op(networkstatus_consensus_is_already_downloading(other_res
), OP_EQ
,
650 tt_int_op(connection_dir_count_by_purpose_and_resource(
651 TEST_CONN_RSRC_PURPOSE
, res
),
653 tt_int_op(connection_dir_count_by_purpose_and_resource(
654 TEST_CONN_RSRC_PURPOSE
, other_res
),
657 /* more connections, two downloading (should never happen, but needs
658 * to be tested for completeness) */
659 conn2
->base_
.state
= TEST_CONN_DL_STATE
;
660 /* ignore the return value, it's free'd using the connection list */
661 (void)test_conn_get_linked_connection(TO_CONN(conn2
),
662 TEST_CONN_ATTACHED_STATE
);
663 tt_int_op(networkstatus_consensus_is_already_downloading(res
), OP_EQ
, 1);
664 tt_int_op(networkstatus_consensus_is_already_downloading(other_res
), OP_EQ
,
666 tt_int_op(connection_dir_count_by_purpose_and_resource(
667 TEST_CONN_RSRC_PURPOSE
, res
),
669 tt_int_op(connection_dir_count_by_purpose_and_resource(
670 TEST_CONN_RSRC_PURPOSE
, other_res
),
672 conn
->base_
.state
= TEST_CONN_STATE
;
674 /* more connections, a different one downloading */
675 tt_int_op(networkstatus_consensus_is_already_downloading(res
), OP_EQ
, 1);
676 tt_int_op(networkstatus_consensus_is_already_downloading(other_res
), OP_EQ
,
678 tt_int_op(connection_dir_count_by_purpose_and_resource(
679 TEST_CONN_RSRC_PURPOSE
, res
),
681 tt_int_op(connection_dir_count_by_purpose_and_resource(
682 TEST_CONN_RSRC_PURPOSE
, other_res
),
685 /* a connection for the other flavor (could happen if a client is set to
686 * cache directory documents), one preferred flavor downloading
688 conn4
= test_conn_download_status_add_a_connection(other_res
);
689 tt_int_op(networkstatus_consensus_is_already_downloading(res
), OP_EQ
, 1);
690 tt_int_op(networkstatus_consensus_is_already_downloading(other_res
), OP_EQ
,
692 tt_int_op(connection_dir_count_by_purpose_and_resource(
693 TEST_CONN_RSRC_PURPOSE
, res
),
695 tt_int_op(connection_dir_count_by_purpose_and_resource(
696 TEST_CONN_RSRC_PURPOSE
, other_res
),
699 /* a connection for the other flavor (could happen if a client is set to
700 * cache directory documents), both flavors downloading
702 conn4
->base_
.state
= TEST_CONN_DL_STATE
;
703 /* ignore the return value, it's free'd using the connection list */
704 (void)test_conn_get_linked_connection(TO_CONN(conn4
),
705 TEST_CONN_ATTACHED_STATE
);
706 tt_int_op(networkstatus_consensus_is_already_downloading(res
), OP_EQ
, 1);
707 tt_int_op(networkstatus_consensus_is_already_downloading(other_res
), OP_EQ
,
709 tt_int_op(connection_dir_count_by_purpose_and_resource(
710 TEST_CONN_RSRC_PURPOSE
, res
),
712 tt_int_op(connection_dir_count_by_purpose_and_resource(
713 TEST_CONN_RSRC_PURPOSE
, other_res
),
717 /* the teardown function removes all the connections in the global list*/;
721 test_conn_https_proxy_connect(void *arg
)
725 or_connection_t
*conn
= arg
;
727 MOCK(connection_or_change_state
, mock_connection_or_change_state
);
729 tt_int_op(conn
->base_
.proxy_state
, OP_EQ
, PROXY_HTTPS_WANT_CONNECT_OK
);
731 buf
= buf_get_contents(conn
->base_
.outbuf
, &sz
);
732 tt_str_op(buf
, OP_EQ
, "CONNECT 127.0.0.1:12345 HTTP/1.0\r\n\r\n");
735 UNMOCK(connection_or_change_state
);
739 static int handshake_start_called
= 0;
742 handshake_start(or_connection_t
*conn
, int receiving
)
748 handshake_start_called
= 1;
753 test_conn_haproxy_proxy_connect(void *arg
)
757 or_connection_t
*conn
= arg
;
759 MOCK(connection_or_change_state
, mock_connection_or_change_state
);
760 MOCK(connection_tls_start_handshake
, handshake_start
);
762 tt_int_op(conn
->base_
.proxy_state
, OP_EQ
, PROXY_HAPROXY_WAIT_FOR_FLUSH
);
764 buf
= buf_get_contents(conn
->base_
.outbuf
, &sz
);
765 tt_str_op(buf
, OP_EQ
, "PROXY TCP4 0.0.0.0 127.0.0.1 0 12345\r\n");
767 connection_or_finished_flushing(conn
);
769 tt_int_op(conn
->base_
.proxy_state
, OP_EQ
, PROXY_CONNECTED
);
770 tt_int_op(handshake_start_called
, OP_EQ
, 1);
773 UNMOCK(connection_or_change_state
);
774 UNMOCK(connection_tls_start_handshake
);
778 static node_t test_node
;
781 mock_node_get_mutable_by_id(const char *digest
)
784 static routerinfo_t node_ri
;
785 memset(&node_ri
, 0, sizeof(node_ri
));
787 test_node
.ri
= &node_ri
;
788 memset(test_node
.identity
, 'c', sizeof(test_node
.identity
));
790 tor_addr_parse(&node_ri
.ipv4_addr
, "18.0.0.1");
791 node_ri
.ipv4_orport
= 1;
796 static const node_t
*
797 mock_node_get_by_id(const char *digest
)
800 memset(test_node
.identity
, 'c', sizeof(test_node
.identity
));
804 /* Test whether we correctly track failed connections between relays. */
806 test_failed_orconn_tracker(void *arg
)
811 time_t now
= 1281533250; /* 2010-08-11 13:27:30 UTC */
814 update_approx_time(now
);
816 /* Prepare the OR connection that will be used in this test */
817 or_connection_t or_conn
;
818 memset(&or_conn
, 0, sizeof(or_conn
));
819 tt_int_op(AF_INET
,OP_EQ
, tor_addr_parse(&or_conn
.canonical_orport
.addr
,
821 tt_int_op(AF_INET
,OP_EQ
, tor_addr_parse(&or_conn
.base_
.addr
, "18.0.0.1"));
822 or_conn
.base_
.port
= 1;
823 memset(or_conn
.identity_digest
, 'c', sizeof(or_conn
.identity_digest
));
825 /* Check whether we can connect with an empty failure cache:
826 * this should succeed */
827 can_connect
= should_connect_to_relay(&or_conn
);
828 tt_int_op(can_connect
, OP_EQ
, 1);
830 /* Now add the destination to the failure cache */
831 note_or_connect_failed(&or_conn
);
833 /* Check again: now it shouldn't connect */
834 can_connect
= should_connect_to_relay(&or_conn
);
835 tt_int_op(can_connect
, OP_EQ
, 0);
837 /* Move time forward and check again: the cache should have been cleared and
838 * now it should connect */
840 update_approx_time(now
);
841 can_connect
= should_connect_to_relay(&or_conn
);
842 tt_int_op(can_connect
, OP_EQ
, 1);
844 /* Now mock the node_get_*by_id() functions to start using the node subsystem
846 MOCK(node_get_by_id
, mock_node_get_by_id
);
847 MOCK(node_get_mutable_by_id
, mock_node_get_mutable_by_id
);
849 /* Since we just started using the node subsystem it will allow connections
851 can_connect
= should_connect_to_relay(&or_conn
);
852 tt_int_op(can_connect
, OP_EQ
, 1);
854 /* Mark it as failed */
855 note_or_connect_failed(&or_conn
);
857 /* Check that it shouldn't connect now */
858 can_connect
= should_connect_to_relay(&or_conn
);
859 tt_int_op(can_connect
, OP_EQ
, 0);
861 /* Move time forward and check again: now it should connect */
863 update_approx_time(now
);
864 can_connect
= should_connect_to_relay(&or_conn
);
865 tt_int_op(can_connect
, OP_EQ
, 1);
872 test_conn_describe(void *arg
)
875 or_options_t
*options
= get_options_mutable();
876 options
->SafeLogging_
= SAFELOG_SCRUB_ALL
;
878 // Let's start with a listener connection since they're simple.
879 connection_t
*conn
= connection_new(CONN_TYPE_OR_LISTENER
, AF_INET
);
880 tor_addr_parse(&conn
->addr
, "44.22.11.11");
882 tt_str_op(connection_describe(conn
), OP_EQ
,
883 "OR listener connection (ready) on 44.22.11.11:80");
884 // If the address is unspec, we should still work.
885 tor_addr_make_unspec(&conn
->addr
);
886 tt_str_op(connection_describe(conn
), OP_EQ
,
887 "OR listener connection (ready) on <unset>:80");
888 // Try making the address null.
889 tor_addr_make_null(&conn
->addr
, AF_INET
);
890 tt_str_op(connection_describe(conn
), OP_EQ
,
891 "OR listener connection (ready) on 0.0.0.0:80");
892 // What if the address is uninitialized? (This can happen if we log about the
893 // connection before we set the address.)
894 memset(&conn
->addr
, 0, sizeof(conn
->addr
));
895 tt_str_op(connection_describe(conn
), OP_EQ
,
896 "OR listener connection (ready) on <unset>:80");
897 connection_free_minimal(conn
);
899 // Try a unix socket.
900 conn
= connection_new(CONN_TYPE_CONTROL_LISTENER
, AF_UNIX
);
901 conn
->address
= tor_strdup("/a/path/that/could/exist");
902 tt_str_op(connection_describe(conn
), OP_EQ
,
903 "Control listener connection (ready) on /a/path/that/could/exist");
904 connection_free_minimal(conn
);
906 // Try an IPv6 address.
907 conn
= connection_new(CONN_TYPE_AP_LISTENER
, AF_INET6
);
908 tor_addr_parse(&conn
->addr
, "ff00::3");
910 tt_str_op(connection_describe(conn
), OP_EQ
,
911 "Socks listener connection (ready) on [ff00::3]:9050");
912 connection_free_minimal(conn
);
914 // Now let's mess with exit connections. They have some special issues.
915 options
->SafeLogging_
= SAFELOG_SCRUB_NONE
;
916 conn
= connection_new(CONN_TYPE_EXIT
, AF_INET
);
917 // If address and state are unset, we should say SOMETHING.
918 tt_str_op(connection_describe(conn
), OP_EQ
,
919 "Exit connection (uninitialized) to <unset> (DNS lookup pending)");
920 // Now suppose that the address is set but we haven't resolved the hostname.
922 conn
->address
= tor_strdup("www.torproject.org");
923 conn
->state
= EXIT_CONN_STATE_RESOLVING
;
924 tt_str_op(connection_describe(conn
), OP_EQ
,
925 "Exit connection (waiting for dest info) to "
926 "www.torproject.org:443 (DNS lookup pending)");
927 // Now give it a hostname!
928 tor_addr_parse(&conn
->addr
, "192.168.8.8");
929 conn
->state
= EXIT_CONN_STATE_OPEN
;
930 tt_str_op(connection_describe(conn
), OP_EQ
,
931 "Exit connection (open) to 192.168.8.8:443");
932 // But what if safelogging is on?
933 options
->SafeLogging_
= SAFELOG_SCRUB_RELAY
;
934 tt_str_op(connection_describe(conn
), OP_EQ
,
935 "Exit connection (open) to [scrubbed]");
936 connection_free_minimal(conn
);
938 // Now at last we look at OR addresses, which are complicated.
939 conn
= connection_new(CONN_TYPE_OR
, AF_INET6
);
940 conn
->state
= OR_CONN_STATE_OPEN
;
942 tor_addr_parse(&conn
->addr
, "[ffff:3333:1111::2]");
943 // This should get scrubbed, since the lack of a set ID means we might be
944 // talking to a client.
945 tt_str_op(connection_describe(conn
), OP_EQ
,
946 "OR connection (open) with [scrubbed]");
947 // But now suppose we aren't safelogging? We'll get the address then.
948 options
->SafeLogging_
= SAFELOG_SCRUB_NONE
;
949 tt_str_op(connection_describe(conn
), OP_EQ
,
950 "OR connection (open) with [ffff:3333:1111::2]:8080");
951 // Suppose we have an ID, so we know it isn't a client.
952 TO_OR_CONN(conn
)->identity_digest
[3] = 7;
953 options
->SafeLogging_
= SAFELOG_SCRUB_RELAY
; // back to safelogging.
954 tt_str_op(connection_describe(conn
), OP_EQ
,
955 "OR connection (open) with [ffff:3333:1111::2]:8080 "
956 "ID=<none> RSA_ID=0000000700000000000000000000000000000000");
957 // Add a 'canonical address' that is the same as the one we have.
958 tor_addr_parse(&TO_OR_CONN(conn
)->canonical_orport
.addr
,
959 "[ffff:3333:1111::2]");
960 TO_OR_CONN(conn
)->canonical_orport
.port
= 8080;
961 tt_str_op(connection_describe(conn
), OP_EQ
,
962 "OR connection (open) with [ffff:3333:1111::2]:8080 "
963 "ID=<none> RSA_ID=0000000700000000000000000000000000000000");
964 // Add a different 'canonical address'
965 tor_addr_parse(&TO_OR_CONN(conn
)->canonical_orport
.addr
,
966 "[ffff:3333:1111::8]");
967 tt_str_op(connection_describe(conn
), OP_EQ
,
968 "OR connection (open) with [ffff:3333:1111::2]:8080 "
969 "ID=<none> RSA_ID=0000000700000000000000000000000000000000 "
970 "canonical_addr=[ffff:3333:1111::8]:8080");
972 // Clear identity_digest so that free_minimal won't complain.
973 memset(TO_OR_CONN(conn
)->identity_digest
, 0, DIGEST_LEN
);
976 connection_free_minimal(conn
);
980 #define CONNECTION_TESTCASE(name, fork, setup) \
981 { #name, test_conn_##name, fork, &setup, NULL }
984 /* where arg is an expression (constant, variable, compound expression) */
985 #define CONNECTION_TESTCASE_ARG(name, extra, fork, setup, arg) \
986 { STR(name)"/"extra, \
991 #endif /* !defined(COCCI) */
993 static const unsigned int PROXY_CONNECT_ARG
= PROXY_CONNECT
;
994 static const unsigned int PROXY_HAPROXY_ARG
= PROXY_HAPROXY
;
996 struct testcase_t connection_tests
[] = {
997 CONNECTION_TESTCASE(get_basic
, TT_FORK
, test_conn_get_basic_st
),
998 CONNECTION_TESTCASE(get_rsrc
, TT_FORK
, test_conn_get_rsrc_st
),
1000 CONNECTION_TESTCASE_ARG(download_status
, "microdesc", TT_FORK
,
1001 test_conn_download_status_st
, "microdesc"),
1002 CONNECTION_TESTCASE_ARG(download_status
, "ns", TT_FORK
,
1003 test_conn_download_status_st
, "ns"),
1005 CONNECTION_TESTCASE_ARG(https_proxy_connect
, "https", TT_FORK
,
1006 test_conn_proxy_connect_st
, &PROXY_CONNECT_ARG
),
1007 CONNECTION_TESTCASE_ARG(haproxy_proxy_connect
, "haproxy", TT_FORK
,
1008 test_conn_proxy_connect_st
, &PROXY_HAPROXY_ARG
),
1010 //CONNECTION_TESTCASE(func_suffix, TT_FORK, setup_func_pair),
1011 { "failed_orconn_tracker", test_failed_orconn_tracker
, TT_FORK
, NULL
, NULL
},
1012 { "describe", test_conn_describe
, TT_FORK
, NULL
, NULL
},