diff --git a/tests/test_etcp_stcp.c b/tests/test_etcp_stcp.c index 070a1748..a8ff8686 100644 --- a/tests/test_etcp_stcp.c +++ b/tests/test_etcp_stcp.c @@ -407,6 +407,50 @@ static void connection_callback_close_case(int reality, int side, unsigned actio printf("PASS connection callback close reality=%d side=%d action=%u event=%u: no late UP\n", reality, side, action, event); } +struct creation_case { unsigned action, fired; }; +static void cancel_tcp_creation(struct ETCP_CONN *conn, struct ETCP_LINK *link, int old_state, int old_status, void *arg) { + (void)old_status; + struct creation_case *test = arg; + if (test->fired || old_state != -1 || !link->is_tcp) return; + test->fired++; + if (test->action == 3) etcp_remove_link_status_cbk(conn->instance, cancel_tcp_creation, test); + else etcp_link_close(link); +} +static void cancel_tcp_connection(struct ETCP_CONN *conn, void *arg) { + struct creation_case *test = arg; + if (test->fired) return; + test->fired++; etcp_connection_close(conn); +} +static void cancel_tcp_new_status(struct ETCP_CONN *conn, int status, void *arg) { + if (status == ETCP_CONN_STATUS_NEW) cancel_tcp_connection(conn, arg); +} +static void tcp_creation_case(int reality, int side, unsigned action) { + size_t allocated = u_get_allocated_count(); + memset(endpoints, 0, sizeof(endpoints)); phase = 0; failed = 0; + struct creation_case test = {.action = action}; + ua = uasync_create(); CHECK(ua); + start_endpoint(0, reality); start_endpoint(1, reality); + struct TOPO_NODE *peer = import_peer(0); + struct UTUN_INSTANCE *inst = endpoints[side].inst; + if (action == 2) etcp_add_new_conn_cbk(inst, cancel_tcp_connection, &test); + else if (action == 4) etcp_add_conn_status_cbk(inst, cancel_tcp_new_status, &test); + else etcp_add_link_status_cbk(inst, cancel_tcp_creation, &test); + int result = node_conn_direct_open_node(endpoints[0].inst, peer->node_id, NULL, NULL, + &endpoints[0].owner, peer, NULL); + CHECK(result >= 0 || (side == 0 && (action == 2 || action == 4))); + uint64_t deadline = get_time_tb() + 30000; + while (!test.fired && get_time_tb() < deadline) test_clock_poll(ua, 100); + CHECK(test.fired == 1); + test_clock_run_for(ua, 100); + if (action == 2) etcp_remove_new_conn_cbk(inst, cancel_tcp_connection, &test); + else if (action == 4) etcp_remove_conn_status_cbk(inst, cancel_tcp_new_status, &test); + else etcp_remove_link_status_cbk(inst, cancel_tcp_creation, &test); + stop_endpoint(0); stop_endpoint(1); uasync_drain_immediate(ua); uasync_poll(ua, 0); + CHECK(ua->timer_alloc_count == ua->timer_free_count && ua->socket_alloc_count == ua->socket_free_count); + uasync_destroy(ua, 0); CHECK(u_get_allocated_count() == allocated); + printf("PASS TCP creation reality=%d side=%d action=%u: no stale handle, balanced resources\n", reality, side, action); +} + static void reconnect_case(void) { size_t allocated = u_get_allocated_count(); memset(endpoints, 0, sizeof(endpoints)); phase = 0; failed = 0; @@ -465,6 +509,7 @@ int main(void) { for (int restarted = 0; restarted < 2; restarted++) run_case(reality, simultaneous, restarted); run_case(reality, 1, 2); for (int side = 0; side < 2; side++) { + for (unsigned action = 1; action <= 4; action++) tcp_creation_case(reality, side, action); for (unsigned action = 1; action <= 2; action++) { connection_callback_close_case(reality, side, action, ETCP_CBK_EVENT_INIT); connection_callback_close_case(reality, side, action, ETCP_CBK_EVENT_UP);