From e6a812042ff898387b27377a9d49aae4c3719406 Mon Sep 17 00:00:00 2001 From: evgeny Date: Sat, 24 Oct 2026 16:17:20 +0200 Subject: [PATCH] Check CM bootstrap ownership and mandatory monitor timers --- tests/test_topo_node_wire.c | 45 ++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/tests/test_topo_node_wire.c b/tests/test_topo_node_wire.c index ef09180e..4a6d6d3e 100644 --- a/tests/test_topo_node_wire.c +++ b/tests/test_topo_node_wire.c @@ -7,6 +7,7 @@ #include "routing_layer/topo_group.h" #include "routing_layer/topo_node_sqlite.h" #include "routing_layer/route_lib.h" +#include "routing_layer/conn_mgr_priv.h" #include "config_parser.h" #include "transport_layer/etcp.h" #include "../lib/debug_config.h" @@ -30,6 +31,7 @@ static int track_allocations; static int lifecycle_faults; static const char* fail_pool_name; static int fail_schema, fail_registry_entry; +static int fail_group_entry, fail_cm_entry, fail_cm_handle; static const char* fail_timer_name; struct memory_pool* __real_memory_pool_init(size_t, const char*); @@ -47,6 +49,8 @@ int __wrap_topo_node_sqlite_init(sqlite3* db) { struct ll_entry* __real_queue_entry_new(size_t); struct ll_entry* __wrap_queue_entry_new(size_t size) { if (fail_registry_entry && size == 8 + sizeof(void*)) { fail_registry_entry = 0; return NULL; } + if (fail_group_entry && size == sizeof(struct TOPO_GROUP_NODE) - sizeof(struct ll_entry)) { fail_group_entry = 0; return NULL; } + if (fail_cm_entry && size == sizeof(struct CONN_MGR_ENTRY) - sizeof(struct ll_entry)) { fail_cm_entry = 0; return NULL; } return __real_queue_entry_new(size); } @@ -74,6 +78,9 @@ void *__wrap_u_malloc_impl(uint32_t size, const char *where) { void *__real_u_calloc_impl(uint32_t, uint32_t, const char *); void *__wrap_u_calloc_impl(uint32_t count, uint32_t size, const char *where) { + if (fail_cm_handle && size == sizeof(struct CONN_MGR_HANDLE) && strstr(where, "conn_mgr_core.c:")) { + fail_cm_handle = 0; return NULL; + } if (!inside_pool && allocation_fails(where)) return NULL; return __real_u_calloc_impl(count, size, where); } @@ -332,6 +339,10 @@ static void test_bootstrap_allocation_failures(struct wire_fixture *f) { } /* Уже опубликованный local_node и его маршруты переживают любой отказ подготовки новой группы. */ +static void cm_fault_callback(struct CONN_MGR_HANDLE* h, uint64_t node_id, uint64_t group_id, enum conn_mgr_event event, void* arg) { + (void)h; (void)node_id; (void)group_id; (void)event; (*(int*)arg)++; +} + static void test_local_allocation_failures(struct wire_fixture *f) { struct CFG_ROUTE_ENTRY v6 = {.ip.family = AF_INET6, .netmask = 64}; memcpy(&v6.ip.addr.v6, (uint8_t[]){0x20, 1, 0xdb, 8}, 4); @@ -398,9 +409,37 @@ static void test_local_allocation_failures(struct wire_fixture *f) { assert(node->group_ref_count == before_refs && f->inst.rt->count == routes && live_allocations() == before); } lifecycle_faults = 0; fail_at = 0; - fail_timer_name = "radio_talker"; - assert(!topo_groups_create_group(&f->groups, 43, TOPO_GROUP_TYPE_UTUN, NULL)); - fail_timer_name = NULL; uasync_poll(f->inst.ua, 0); + const char* timers[] = {"radio_talker", "conn_mgr_bg_ping", "conn_mgr_cand_ping"}; + for (size_t i = 0; i < sizeof(timers) / sizeof(timers[0]); i++) { + size_t before = live_allocations(); + fail_timer_name = timers[i]; + assert(!topo_groups_create_group(&f->groups, 43, TOPO_GROUP_TYPE_UTUN, NULL)); + fail_timer_name = NULL; uasync_poll(f->inst.ua, 0); + assert(live_allocations() == before); + } + created = topo_groups_create_group(&f->groups, 43, TOPO_GROUP_TYPE_UTUN, NULL); assert(created); + assert(!f->inst.topo_sqlite_db && sqlite3_open(":memory:", &f->inst.topo_sqlite_db) == SQLITE_OK); + assert(!topo_node_sqlite_init(f->inst.topo_sqlite_db)); + struct SC_MYKEYS peer_keys; assert(sc_generate_keypair(&peer_keys) == SC_OK); + struct TOPO_ADDR4 address = {.addr = {127,0,0,1}, .port = 9, .protocol = TOPO_PROTO_UDP, .type = TOPO_ADDR_INTERFACE}; + struct TOPO_NODE bootstrap = {.node_id = sc_derive_node_id_from_pubkey(peer_keys.public_key), .v4_addrs = &address}; + memcpy(bootstrap.public_key, peer_keys.public_key, 32); + assert(!topo_node_sqlite_node_update_verified(f->inst.topo_sqlite_db, bootstrap.node_id, "bootstrap", bootstrap.public_key, + f->inst.my_ed25519_pubkey, 1, 1)); + assert(!topo_node_sqlite_addrs_put(f->inst.topo_sqlite_db, bootstrap.node_id, &bootstrap)); + int* failures[] = {&fail_registry_entry, &fail_group_entry, &fail_cm_entry, &fail_cm_handle}; + for (size_t i = 0; i < sizeof(failures) / sizeof(failures[0]); i++) { + size_t before = live_allocations(); + struct CONN_MGR_HANDLE* handle = NULL; int callbacks = 0; + *failures[i] = 1; + assert(conn_mgr_open(&f->inst, 43, bootstrap.node_id, cm_fault_callback, &callbacks, &handle) == -1); + cm_collect(created->conn_mgr); + assert(!*failures[i] && !handle && !callbacks && !created->conn_mgr->entries->head); + assert(!topo_node_find_by_id(created, bootstrap.node_id) && !topo_node_registry_find(&f->groups, bootstrap.node_id)); + assert(live_allocations() == before); + } + assert(sqlite3_close(f->inst.topo_sqlite_db) == SQLITE_OK); f->inst.topo_sqlite_db = NULL; + topo_groups_remove_group(&f->groups, 43); uasync_poll(f->inst.ua, 0); queue_free(f->groups.group_list); f->groups.group_list = NULL; DEBUG_INFO(DEBUG_CATEGORY_BGP, "[PASS] group creation: %u allocation failures roll back all resources; radio retry preserved", creation_allocations);