From c5f743a09d100827e20bad6665da289b433dc596 Mon Sep 17 00:00:00 2001 From: evgeny Date: Fri, 23 Oct 2026 14:01:57 +0200 Subject: [PATCH] Cover INIT liveness with an independent healthy link --- tests/test_etcp_init_liveness.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/tests/test_etcp_init_liveness.c b/tests/test_etcp_init_liveness.c index 0319054b..4b39bfb0 100644 --- a/tests/test_etcp_init_liveness.c +++ b/tests/test_etcp_init_liveness.c @@ -123,7 +123,10 @@ static void setup(unsigned swapped, unsigned count) { static void teardown(void) { close_action = 0; etcp_conn_ref_free(ep[1].conn); - for (unsigned side = 0; side < 2; side++) utun_instance_destroy(ep[side].inst); + for (unsigned side = 0; side < 2; side++) { + etcp_remove_link_status_cbk(ep[side].inst, link_event, &ep[side]); + utun_instance_destroy(ep[side].inst); + } uasync_poll(ua, 0); CHECK(ua->timer_alloc_count == ua->timer_free_count); uasync_destroy(ua, 0); @@ -160,6 +163,28 @@ static void close_in_callback(unsigned action) { teardown(); } +/* INIT на неработающем пути не меняет доступность соединения с другим исправным линком. */ +static void healthy_alternative(void) { + setup(0, 2); + struct ETCP_LINK* broken = first_link(0); + CHECK(broken->next && broken->link_status && broken->next->link_status); + ep[1].block_id = broken->remote_link_id; + run_for(15000); CHECK(!broken->link_status && ep[0].conn->links_up && ep[1].conn->links_up); + unsigned before = ep[0].init_zero; + etcp_link_enter_reinit(broken); run_for(5000); + DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "Alternative: INIT0=%u broken=%u role=%u state=%u up=%u/%u DOWN=%u/%u block_id=%u", + ep[0].init_zero - before, broken->link_status, broken->is_server, broken->link_state, + ep[0].conn->links_up, ep[1].conn->links_up, ep[0].down, ep[1].down, ep[1].block_id); + /* При исправном обходном пути таймер подавляет повторы INIT; первый запрос всё равно принимается. */ + CHECK(ep[0].init_zero == before + 1 && !broken->link_status && !ep[0].down && !ep[1].down); + struct ll_entry* entry = ll_alloc_lldgram(2); CHECK(entry); + entry->len = 2; entry->dgram[0] = 253; entry->dgram[1] = 17; + CHECK(etcp_send(ep[0].conn, entry) == 0); run_for(1000); CHECK(ep[1].received == 1); + ep[1].block_id = 0; run_for(10000); + CHECK(broken->link_status && !ep[0].down && !ep[1].down && !ep[0].reinit && !ep[1].reinit); + teardown(); +} + /* При отказе показать конкретные живые блоки вместо одного несовпавшего счётчика. */ static void check_memory(size_t baseline) { if (u_get_allocated_count() == baseline) return; @@ -179,6 +204,7 @@ int main(void) { one_way(swapped, 1 - order); check_memory(baseline); } for (unsigned action = 1; action <= 2; action++) { close_in_callback(action); check_memory(baseline); } + healthy_alternative(); check_memory(baseline); DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "PASS encrypted INIT liveness: cold start, one-way loss, repeated INIT, recovery and callback close"); test_clock_finish(); socket_platform_cleanup(); return 0; }