From 3baaa42c82cd464c8de63cc7dd7fd393df655471 Mon Sep 17 00:00:00 2001 From: evgeny Date: Sat, 10 Oct 2026 14:17:21 +0200 Subject: [PATCH] tests: accelerate BGP waits and require single-link DOWN and UP --- tests/Makefile.am | 6 ++++-- tests/test_bgp_route_exchange.c | 27 ++++++++++++++++++++++----- tests/test_bgp_triangle.c | 8 +++++--- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index 5493ff60..ebf07885 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -452,13 +452,15 @@ test_route_lib_SOURCES = test_route_lib.c test_route_lib_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib test_route_lib_LDADD = $(LIBUTUN) $(COMMON_LIBS) -test_bgp_route_exchange_SOURCES = test_bgp_route_exchange.c test_connection_loss.h +test_bgp_route_exchange_SOURCES = test_bgp_route_exchange.c test_connection_loss.h $(test_clock_sources) test_bgp_route_exchange_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib test_bgp_route_exchange_LDADD = $(LIBUTUN) $(CRYPTO_LIBS) $(COMMON_LIBS) +test_bgp_route_exchange_LDFLAGS = $(test_clock_ldflags) -test_bgp_triangle_SOURCES = test_bgp_triangle.c test_connection_loss.h +test_bgp_triangle_SOURCES = test_bgp_triangle.c test_connection_loss.h $(test_clock_sources) test_bgp_triangle_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib test_bgp_triangle_LDADD = $(LIBUTUN) $(CRYPTO_LIBS) $(COMMON_LIBS) +test_bgp_triangle_LDFLAGS = $(test_clock_ldflags) test_broadcast_SOURCES = test_broadcast.c test_broadcast_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib diff --git a/tests/test_bgp_route_exchange.c b/tests/test_bgp_route_exchange.c index d669b213..7f0163b1 100644 --- a/tests/test_bgp_route_exchange.c +++ b/tests/test_bgp_route_exchange.c @@ -26,6 +26,7 @@ #include #include "../lib/platform_compat.h" #include "test_utils.h" +#include "test_clock.h" #ifdef _WIN32 #include @@ -66,6 +67,18 @@ static void* timeout_id = NULL; // dummynet filters per link static struct test_connection_loss loss_ab, loss_bc; +static int single_link_down, single_link_up; + +static void single_link_status(struct ETCP_CONN* conn, struct ETCP_LINK* link, int old_state, int old_status, void* arg) { + (void)conn; (void)old_state; + if (link != arg || old_status == link->link_status) return; + if (link->link_status) single_link_up = 1; + else single_link_down = 1; + DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "BGP single-link test: link=%u old_status=%d status=%d down=%d up=%d", + link->local_link_id, old_status, link->link_status, single_link_down, single_link_up); +} +static int cond_single_link_down(void) { return single_link_down; } +static int cond_single_link_up(void) { return single_link_up; } static char temp_dir[] = "/tmp/utun_bgp_mesh_XXXXXX"; static char config_a[256], config_b[256], config_c[256]; @@ -259,7 +272,7 @@ static void fail(const char* msg) { static int wait_for(const char* desc, int (*cond)(void), int timeout_tb) { uint64_t start = get_time_tb(); while (!cond() && (get_time_tb() - start) < (uint64_t)timeout_tb && test_phase == 0) - uasync_poll(ua, POLL_INTERVAL_MS); + test_clock_poll(ua, POLL_INTERVAL_MS); if (!cond() && test_phase == 0) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "timeout waiting for: %s", desc); test_phase = 2; @@ -293,6 +306,7 @@ int main(void) { debug_config_init(); debug_set_level(DEBUG_LEVEL_ERROR); debug_set_categories(DEBUG_CATEGORY_BGP); + test_clock_init(1000); if (getenv("UTUN_TEST_DEBUG")) { debug_set_category_level(DEBUG_CATEGORY_BGP, DEBUG_LEVEL_DEBUG); debug_set_category_level(DEBUG_CATEGORY_ETCP, DEBUG_LEVEL_DEBUG); @@ -348,17 +362,19 @@ int main(void) { // --- Phase 2: Kill one A↔B link, verify routes stay --- PHASE("2: Kill one A↔B link"); + etcp_add_link_status_cbk(inst_a, single_link_status, ab_link1); test_loss_set(&loss_ab, 1, ab_link1, NULL); - // Wait for link-down detection by keepalive, then verify routes survive (link2 still up) - for (int i = 0; i < 200 && test_phase == 0 && ab_link1->link_status; i++) uasync_poll(ua, POLL_INTERVAL_MS); - // Small margin after link-down before checks - for (int i = 0; i < 40 && test_phase == 0; i++) uasync_poll(ua, POLL_INTERVAL_MS); + // Маршрут должен пережить подтверждённый DOWN одного линка. + ASSERT(wait_for("single A-B link DOWN", cond_single_link_down, PHASE_TIMEOUT_TB), "single link did not go DOWN"); + test_clock_run_for(ua, 400); // Сохраняем 40мс проверки стабильности после DOWN. ASSERT(check_learned_route(inst_a, ntohl(inet_addr("192.168.30.0")), 24, g_node_id_c), "routes lost after 1 link down"); ASSERT(check_learned_route(inst_c, ntohl(inet_addr("192.168.10.0")), 24, g_node_id_a), "routes lost C side"); // --- Phase 3: Restore the link --- PHASE("3: Restore one A↔B link"); test_loss_set(&loss_ab, 0, NULL, NULL); + ASSERT(wait_for("single A-B link UP", cond_single_link_up, PHASE_TIMEOUT_TB), "single link did not restore UP"); + etcp_remove_link_status_cbk(inst_a, single_link_status, ab_link1); ASSERT(wait_for("BGP recovery after ab1 restored", cond_bgp_a_to_c, PHASE_TIMEOUT_TB), "bgp A→C recovery"); // --- Phase 4: Kill B↔C link --- @@ -397,6 +413,7 @@ int main(void) { if (ua) { uasync_poll(ua, 0); uasync_destroy(ua, 0); ua = NULL; } cleanup_temp_configs(); + test_clock_finish(); printf("=== %s ===\n", test_phase == 1 ? "TEST PASSED" : "TEST FAILED"); return test_phase == 1 ? 0 : 1; } diff --git a/tests/test_bgp_triangle.c b/tests/test_bgp_triangle.c index c39290ca..cdf84ada 100644 --- a/tests/test_bgp_triangle.c +++ b/tests/test_bgp_triangle.c @@ -29,6 +29,7 @@ #include #include "../lib/platform_compat.h" #include "test_utils.h" +#include "test_clock.h" #ifdef _WIN32 #include @@ -206,7 +207,7 @@ static void fail(const char* msg) { static int wait_for(const char* desc, int (*cond)(void), int timeout_tb) { uint64_t start = get_time_tb(); while (!cond() && (get_time_tb() - start) < (uint64_t)timeout_tb && test_phase == 0) - uasync_poll(ua, POLL_INTERVAL_MS); + test_clock_poll(ua, POLL_INTERVAL_MS); if (!cond() && test_phase == 0) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "timeout waiting for: %s", desc); test_phase = 2; @@ -255,6 +256,7 @@ int main(void) { debug_config_init(); debug_set_level(DEBUG_LEVEL_ERROR); debug_set_categories(DEBUG_CATEGORY_BGP); + test_clock_init(1000); const char* log = getenv("BGP_TEST_LOG"); if (log) { debug_enable_file_output(log,1); @@ -384,8 +386,7 @@ int main(void) { ASSERT(route_count_for_node(inst_a, g_node_id_d) > 0, "D routes missing"); ASSERT(route_count_for_node(inst_a, g_node_id_e) > 0, "E routes missing"); // Дождаться фоновых candidate probes: транзитный маршрут не является прямым peer. - uint64_t probe_deadline = get_time_tb() + 22000; - while (get_time_tb() < probe_deadline && test_phase == 0) uasync_poll(ua,POLL_INTERVAL_MS); + test_clock_run_for(ua, 22000); struct UTUN_INSTANCE* probe_nodes[] = {inst_a,inst_b,inst_c,inst_d,inst_e}; for (size_t i = 0; i < sizeof(probe_nodes)/sizeof(probe_nodes[0]); i++) for (struct ETCP_SOCKET* sock = probe_nodes[i]->etcp_sockets; sock; sock = sock->next) @@ -497,6 +498,7 @@ cleanup: uasync_destroy(ua,0); ua = NULL; } + test_clock_finish(); printf("=== %s ===\n", test_phase == 1 ? "TEST PASSED" : "TEST FAILED"); return test_phase == 1 ? 0 : 1; }