1 /* Copyright (c) 2015, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
6 #define CONNECTION_PRIVATE
12 #include "connection.h"
14 #include "networkstatus.h"
15 #include "rendcache.h"
16 #include "directory.h"
18 static void test_conn_lookup_addr_helper(const char *address
,
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
,
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
,
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
,
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
;
64 mock_connection_connect_sockaddr(connection_t
*conn
,
65 const struct sockaddr
*sa
,
67 const struct sockaddr
*bindaddr
,
68 socklen_t bindaddr_len
,
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);
89 /* Fake "connected" status */
94 test_conn_lookup_addr_helper(const char *address
, int family
, tor_addr_t
*addr
)
100 rv
= tor_addr_lookup(address
, family
, addr
);
101 /* XXXX - should we retry on transient failure? */
103 tt_assert(tor_addr_is_loopback(addr
));
104 tt_assert(tor_addr_is_v4(addr
));
109 tor_addr_make_null(addr
, TEST_CONN_FAMILY
);
113 test_conn_get_basic_setup(const struct testcase_t
*tc
)
115 connection_t
*conn
= NULL
;
121 MOCK(connection_connect_sockaddr
,
122 mock_connection_connect_sockaddr
);
124 init_connection_lists();
126 conn
= connection_new(TEST_CONN_TYPE
, TEST_CONN_FAMILY
);
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
);
153 UNMOCK(connection_connect_sockaddr
);
154 test_conn_get_basic_teardown(tc
, conn
);
156 /* Returning NULL causes the unit test to fail */
161 test_conn_get_basic_teardown(const struct testcase_t
*tc
, void *arg
)
164 connection_t
*conn
= arg
;
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 */
217 /* When conn == NULL, we can't cleanup anything */
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
));
228 assert_connection_ok(&conn
->base_
, time(NULL
));
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
,
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
));
245 test_conn_get_rend_teardown(tc
, conn
);
246 /* Returning NULL causes the unit test to fail */
251 test_conn_get_rend_teardown(const struct testcase_t
*tc
, void *arg
)
253 dir_connection_t
*conn
= DOWNCAST(dir_connection_t
, arg
);
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
);
265 rend_cache_free_all();
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
));
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
));
286 test_conn_get_rend_teardown(tc
, conn
);
287 /* Returning NULL causes the unit test to fail */
292 test_conn_get_rsrc_teardown(const struct testcase_t
*tc
, void *arg
)
294 dir_connection_t
*conn
= DOWNCAST(dir_connection_t
, arg
);
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
);
310 test_conn_download_status_setup(const struct testcase_t
*tc
)
314 /* Don't return NULL, that causes the test to fail */
319 test_conn_download_status_teardown(const struct testcase_t
*tc
, void *arg
)
324 /* Ignore arg, and just loop through the connection array */
325 SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t
*, conn
) {
327 assert_connection_ok(conn
, time(NULL
));
329 /* connection_free_() cleans up requested_resource */
330 rv
= test_conn_get_rsrc_teardown(tc
, conn
);
333 } SMARTLIST_FOREACH_END(conn
);
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
));
346 assert_connection_ok(&conn
->base_
, time(NULL
));
351 test_conn_download_status_teardown(NULL
, 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
372 test_conn_get_basic(void *arg
)
374 connection_t
*conn
= (connection_t
*)arg
;
375 tor_addr_t addr
, addr2
;
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
)
398 tt_assert(connection_get_by_type_state(TEST_CONN_TYPE
, TEST_CONN_STATE
)
400 tt_assert(connection_get_by_type_state(!conn
->type
, !conn
->state
)
402 tt_assert(connection_get_by_type_state(!TEST_CONN_TYPE
, !TEST_CONN_STATE
)
405 /* Match on the connection fields themselves */
406 tt_assert(connection_get_by_type_addr_port_purpose(conn
->type
,
411 /* Match on the original inputs to the connection */
412 tt_assert(connection_get_by_type_addr_port_purpose(TEST_CONN_TYPE
,
417 tt_assert(connection_get_by_type_addr_port_purpose(conn
->type
,
422 tt_assert(connection_get_by_type_addr_port_purpose(conn
->type
,
427 tt_assert(connection_get_by_type_addr_port_purpose(conn
->type
,
430 TEST_CONN_BASIC_PURPOSE
)
432 tt_assert(connection_get_by_type_addr_port_purpose(TEST_CONN_TYPE
,
435 TEST_CONN_BASIC_PURPOSE
)
437 /* Then try each of the not-matching combinations */
438 tt_assert(connection_get_by_type_addr_port_purpose(!conn
->type
,
443 tt_assert(connection_get_by_type_addr_port_purpose(conn
->type
,
448 tt_assert(connection_get_by_type_addr_port_purpose(conn
->type
,
453 tt_assert(connection_get_by_type_addr_port_purpose(conn
->type
,
458 /* Then try everything not-matching */
459 tt_assert(connection_get_by_type_addr_port_purpose(!conn
->type
,
464 tt_assert(connection_get_by_type_addr_port_purpose(!TEST_CONN_TYPE
,
467 !TEST_CONN_BASIC_PURPOSE
)
475 test_conn_get_rend(void *arg
)
477 dir_connection_t
*conn
= DOWNCAST(dir_connection_t
, arg
);
479 assert_connection_ok(&conn
->base_
, time(NULL
));
481 tt_assert(connection_get_by_type_state_rendquery(
484 conn
->rend_data
->onion_address
)
486 tt_assert(connection_get_by_type_state_rendquery(
491 tt_assert(connection_get_by_type_state_rendquery(TEST_CONN_REND_TYPE_2
,
495 tt_assert(connection_get_by_type_state_rendquery(TEST_CONN_REND_TYPE_2
,
497 TEST_CONN_REND_ADDR_2
)
504 #define sl_is_conn_assert(sl, conn) \
506 tt_assert(smartlist_len((sl)) == 1); \
507 tt_assert(smartlist_get((sl), 0) == (conn)); \
510 #define sl_no_conn_assert(sl) \
512 tt_assert(smartlist_len((sl)) == 0); \
516 test_conn_get_rsrc(void *arg
)
518 dir_connection_t
*conn
= DOWNCAST(dir_connection_t
, arg
);
520 assert_connection_ok(&conn
->base_
, time(NULL
));
522 tt_assert(connection_dir_get_by_purpose_and_resource(
524 conn
->requested_resource
)
526 tt_assert(connection_dir_get_by_purpose_and_resource(
527 TEST_CONN_RSRC_PURPOSE
,
530 tt_assert(connection_dir_get_by_purpose_and_resource(
531 !conn
->base_
.purpose
,
534 tt_assert(connection_dir_get_by_purpose_and_resource(
535 !TEST_CONN_RSRC_PURPOSE
,
539 tt_assert(connection_dir_get_by_purpose_resource_and_state(
541 conn
->requested_resource
,
544 tt_assert(connection_dir_get_by_purpose_resource_and_state(
545 TEST_CONN_RSRC_PURPOSE
,
549 tt_assert(connection_dir_get_by_purpose_resource_and_state(
550 !conn
->base_
.purpose
,
554 tt_assert(connection_dir_get_by_purpose_resource_and_state(
555 !TEST_CONN_RSRC_PURPOSE
,
560 sl_is_conn_assert(connection_dir_list_by_purpose_and_resource(
562 conn
->requested_resource
),
564 sl_is_conn_assert(connection_dir_list_by_purpose_and_resource(
565 TEST_CONN_RSRC_PURPOSE
,
568 sl_no_conn_assert(connection_dir_list_by_purpose_and_resource(
569 !conn
->base_
.purpose
,
571 sl_no_conn_assert(connection_dir_list_by_purpose_and_resource(
572 !TEST_CONN_RSRC_PURPOSE
,
575 sl_is_conn_assert(connection_dir_list_by_purpose_resource_and_state(
577 conn
->requested_resource
,
580 sl_is_conn_assert(connection_dir_list_by_purpose_resource_and_state(
581 TEST_CONN_RSRC_PURPOSE
,
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
,
594 tt_assert(connection_dir_count_by_purpose_and_resource(
596 conn
->requested_resource
)
598 tt_assert(connection_dir_count_by_purpose_and_resource(
599 TEST_CONN_RSRC_PURPOSE
,
602 tt_assert(connection_dir_count_by_purpose_and_resource(
603 !conn
->base_
.purpose
,
606 tt_assert(connection_dir_count_by_purpose_and_resource(
607 !TEST_CONN_RSRC_PURPOSE
,
611 tt_assert(connection_dir_count_by_purpose_resource_and_state(
613 conn
->requested_resource
,
616 tt_assert(connection_dir_count_by_purpose_resource_and_state(
617 TEST_CONN_RSRC_PURPOSE
,
621 tt_assert(connection_dir_count_by_purpose_resource_and_state(
622 !conn
->base_
.purpose
,
626 tt_assert(connection_dir_count_by_purpose_resource_and_state(
627 !TEST_CONN_RSRC_PURPOSE
,
637 test_conn_download_status(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);
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),