From a43d478495d3c239afffeba66428cd3dcad44643 Mon Sep 17 00:00:00 2001 From: evgeny Date: Fri, 23 Oct 2026 22:02:44 +0200 Subject: [PATCH] Cover close from connection INIT and UP callbacks on both roles --- tests/test_etcp_stcp.c | 51 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/tests/test_etcp_stcp.c b/tests/test_etcp_stcp.c index e53a9a15..070a1748 100644 --- a/tests/test_etcp_stcp.c +++ b/tests/test_etcp_stcp.c @@ -360,6 +360,53 @@ static void callback_close_case(int reality, int side, unsigned action, unsigned reality, side, action, on_down); } +static void close_from_conn_event(struct ETCP_CONN *conn, int event, void *arg) { + struct callback_case *test = arg; + if (test->fired) return; + test->fired = 1; test->retained = conn; + CHECK(etcp_conn_ref_take(conn) == 0); + DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "Connection callback close: action=%u event=%d", test->action, event); + if (test->action == 2) etcp_connection_close(conn); + else { CHECK(conn->links); etcp_link_close(conn->links); } +} + +static void attach_conn_close(struct ETCP_CONN *conn, void *arg) { + struct callback_case *test = arg; + etcp_conn_add_cbk(conn, close_from_conn_event, test, test->on_down); +} + +static void observe_conn_status(struct ETCP_CONN *conn, int status, void *arg) { + (void)conn; + struct callback_case *test = arg; + if (test->fired && status == ETCP_CONN_STATUS_UP) test->late_ready++; +} + +static void connection_callback_close_case(int reality, int side, unsigned action, unsigned event) { + size_t allocated = u_get_allocated_count(); + memset(endpoints, 0, sizeof(endpoints)); phase = 0; failed = 0; + struct callback_case test = {.action = action, .on_down = event}; + ua = uasync_create(); CHECK(ua); + start_endpoint(0, reality); start_endpoint(1, reality); + etcp_add_new_conn_cbk(endpoints[side].inst, attach_conn_close, &test); + etcp_add_conn_status_cbk(endpoints[side].inst, observe_conn_status, &test); + struct TOPO_NODE *peer = import_peer(0); + CHECK(node_conn_direct_open_node(endpoints[0].inst, peer->node_id, NULL, NULL, + &endpoints[0].owner, peer, NULL) >= 0); + uint64_t deadline = get_time_tb() + 30000; + while (!test.fired && get_time_tb() < deadline) test_clock_poll(ua, 100); + CHECK(test.fired == 1 && !test.late_ready); + test_clock_run_for(ua, 100); + CHECK(!test.late_ready); + etcp_remove_new_conn_cbk(endpoints[side].inst, attach_conn_close, &test); + etcp_remove_conn_status_cbk(endpoints[side].inst, observe_conn_status, &test); + etcp_conn_remove_cbk(test.retained, close_from_conn_event, &test); + etcp_conn_ref_free(test.retained); + 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 connection callback close reality=%d side=%d action=%u event=%u: no late UP\n", reality, side, action, event); +} + static void reconnect_case(void) { size_t allocated = u_get_allocated_count(); memset(endpoints, 0, sizeof(endpoints)); phase = 0; failed = 0; @@ -418,6 +465,10 @@ 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 <= 2; action++) { + connection_callback_close_case(reality, side, action, ETCP_CBK_EVENT_INIT); + connection_callback_close_case(reality, side, action, ETCP_CBK_EVENT_UP); + } for (unsigned action = 1; action <= 4; action++) callback_close_case(reality, side, action, 0); for (unsigned action = 1; action <= 4; action++) if (action != 3) callback_close_case(reality, side, action, 1);