From 4278eb78515d18724ffe1d06bdff39d927c87496 Mon Sep 17 00:00:00 2001 From: evgeny Date: Mon, 26 Oct 2026 14:08:54 +0100 Subject: [PATCH] Wait for incoming transport before late-peer group setup and check restored publishing --- tests/test_chat_poll_network.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/test_chat_poll_network.c b/tests/test_chat_poll_network.c index 77bdb4f1..0af702e9 100644 --- a/tests/test_chat_poll_network.c +++ b/tests/test_chat_poll_network.c @@ -84,6 +84,18 @@ static int wait_transport(struct NODE_CONN_DIRECT* ab, struct NODE_CONN_DIRECT* DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "poll network: bootstrap timeout ab=%p bc=%p", (void*)a, (void*)b); return 0; } +/* Новый узел должен получить входящий UP до группового запроса без bootstrap-адресов. */ +static int wait_new_transport(int from, int to, struct NODE_CONN_DIRECT* handle) { + uint64_t deadline = get_time_tb() + 15u * 10000u; + while (get_time_tb() < deadline) { + struct ETCP_CONN* outgoing = node_conn_direct_get_conn(handle); + struct ETCP_CONN* incoming = instance_find_conn(nodes[to], nodes[from]->node_id); + if (outgoing && incoming && outgoing->initialized && incoming->initialized && outgoing->links_up && incoming->links_up) return 1; + uasync_poll(ua, 5); + } + DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "poll network: new transport timeout from=%d to=%d", from, to); return 0; +} + static sqlite3_int64 field(struct UTUN_INSTANCE* inst, const char* json, const char* path) { sqlite3_stmt* st = NULL; assert(sqlite3_prepare_v2(inst->topo_sqlite_db, "SELECT json_extract(?1,?2)", -1, &st, NULL) == SQLITE_OK); sqlite3_bind_text(st, 1, json, -1, SQLITE_STATIC); sqlite3_bind_text(st, 2, path, -1, SQLITE_STATIC); @@ -215,6 +227,7 @@ int main(void) { x, NULL, ed, NULL, signature) == 0); chat_core_ensure_channel_ready(nodes[3], channel); seed_members(x, ed, owner_private, 4); struct NODE_CONN_DIRECT* bd = connect_node(1, 3, ports[3]); + assert(wait_new_transport(1, 3, bd)); assert(topo_group_peer_open(topo_groups_find(nodes[1]->topo_groups, gid), nodes[3]->node_id, &groups[3]) == 0); assert(topo_group_peer_open(topo_groups_find(nodes[3]->topo_groups, gid), nodes[1]->node_id, &groups[4]) == 0); assert(wait_ready(groups[3]) && wait_ready(groups[4])); subscribe(1, 3); @@ -229,6 +242,13 @@ int main(void) { assert(chat_feedback_get(nodes[3], channel, message_id, nodes[0]->node_id, CHAT_FEEDBACK_REACTION, &old) == 1); assert(old.ver == saved_reaction.ver && !memcmp(old.signature, saved_reaction.signature, 64)); puts("PASS: signed restoration reactivates cached states and delivers them to the new peer with matching Merkle roots"); + /* Возвращённый автор должен снова передавать изменения через прежний UP-транспорт. */ + run_command(0, "react", ",\"clear\":true"); + assert(wait_result(1, 2, 1, 0) && wait_result(2, 2, 1, 0) && wait_result(3, 2, 1, 0)); + assert(wait_feedback_roots(1, 2) && wait_feedback_roots(1, 3)); + assert(chat_feedback_get(nodes[3], channel, message_id, nodes[0]->node_id, CHAT_FEEDBACK_REACTION, &old) == 1); + assert(old.ver == 4 && !old.data_len); + puts("PASS: restored author can publish a new cancellation over the surviving transport"); for (int i = 0; i < 5; i++) topo_group_peer_close(groups[i]); node_conn_direct_close(ab); node_conn_direct_close(bc); node_conn_direct_close(bd); for (int i = 0; i < 4; i++) utun_instance_destroy(nodes[i]);