From f47e80571df0278902cd67565bd2135bc2ad8ac9 Mon Sep 17 00:00:00 2001 From: evgeny Date: Thu, 22 Oct 2026 18:13:25 +0200 Subject: [PATCH] Assert media QUERY results and preserve transport ownership in tests --- tests/Makefile.am | 8 +++++ tests/test_media_delivery_download.c | 52 +++++++++++++++++++--------- 2 files changed, 43 insertions(+), 17 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index 0962d716..02152e7f 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -888,10 +888,18 @@ test_media_delivery_sql_LDADD = $(LIBUTUN) $(CRYPTO_LIBS) $(COMMON_LIBS) test_media_delivery_download_SOURCES = test_media_delivery_download.c test_media_delivery_download_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/media_delivery -I$(top_srcdir)/src/media_async -I$(top_srcdir)/lib -I$(top_srcdir)/src/transport_layer -I$(top_srcdir)/src/routing_layer -I$(top_srcdir)/src/chat test_media_delivery_download_LDADD = $(LIBUTUN) $(CRYPTO_LIBS) $(COMMON_LIBS) +test_media_delivery_download_LDFLAGS = -Wl,--wrap=etcp_route_send test_media_download_timeout_SOURCES = test_media_download_timeout.c test_media_download_timeout_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/media_delivery -I$(top_srcdir)/src/media_async -I$(top_srcdir)/lib -I$(top_srcdir)/src/transport_layer -I$(top_srcdir)/src/routing_layer -I$(top_srcdir)/src/chat test_media_download_timeout_LDADD = $(LIBUTUN) $(CRYPTO_LIBS) $(COMMON_LIBS) +test_media_download_timeout_LDFLAGS = -Wl,--wrap=etcp_route_send + +check_PROGRAMS += test_media_query +test_media_query_SOURCES = test_media_query.c +test_media_query_CFLAGS = $(test_media_delivery_download_CFLAGS) +test_media_query_LDADD = $(LIBUTUN) $(CRYPTO_LIBS) $(COMMON_LIBS) +test_media_query_LDFLAGS = -Wl,--wrap=etcp_route_send -Wl,--wrap=RAND_bytes test_media_delivery_integration_SOURCES = test_media_delivery_integration.c test_media_delivery_integration_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/media_delivery -I$(top_srcdir)/src/media_async -I$(top_srcdir)/lib -I$(top_srcdir)/src/transport_layer -I$(top_srcdir)/src/routing_layer -I$(top_srcdir)/src/chat diff --git a/tests/test_media_delivery_download.c b/tests/test_media_delivery_download.c index 40d4fa4c..5fc95caf 100644 --- a/tests/test_media_delivery_download.c +++ b/tests/test_media_delivery_download.c @@ -33,6 +33,13 @@ #include #include +/* Доставка принята транспортом, ответа нет. Владение entry совпадает с реальным router во всех исходах. */ +int __wrap_etcp_route_send(struct UTUN_INSTANCE* inst, uint64_t group, uint64_t dst, + struct ll_entry* entry, int force, int mode) { + (void)inst; (void)group; (void)dst; (void)force; (void)mode; + queue_dgram_free(entry); queue_entry_free(entry); return 0; +} + #define TEMP_DIR "/tmp/test_mdl_dl_XXXXXX" #define CHUNK_SIZE 100 #define NUM_BLOCKS 3 @@ -135,6 +142,8 @@ static struct media_download* make_test_dl(sqlite3* db, struct UTUN_INSTANCE* in static void free_test_dl(struct UTUN_INSTANCE* inst, struct media_download* dl) { if (!dl) return; if (dl->watchdog_timer) { uasync_cancel_timeout(inst->ua, dl->watchdog_timer); dl->watchdog_timer = NULL; } + if (dl->pump_timer) uasync_call_soon_cancel(inst->ua, dl->pump_timer); + for (int pi = 0; pi < dl->num_peers; pi++) if (dl->peers[pi].cm_handle) conn_mgr_close(dl->peers[pi].cm_handle); u_free(dl->blocks); u_free(dl->block_sigs); if (inst->md.downloads) { @@ -143,6 +152,17 @@ static void free_test_dl(struct UTUN_INSTANCE* inst, struct media_download* dl) } } +/* Полный ответ на текущую пачку; тесты задают только найденных держателей. */ +static void query_response(struct media_download* dl, uint8_t* wire, int count) { + memset(wire, 0, MEDIA_QUERY_RESP_HDR_SIZE + (size_t)count * sizeof(struct media_pkt_query_resp_entry)); + struct media_pkt_query_resp* r = (struct media_pkt_query_resp*)wire; + r->subcmd = MEDIA_SUBCMD_QUERY_RESP; r->num_blocks = (uint16_t)count; + memcpy(r->media_id, dl->media_id, 16); memset(r->request_id, 0xA5, 16); memcpy(dl->query_id, r->request_id, 16); + dl->query_node = 0x9001; dl->query_count = count; dl->query_deadline_tb = get_time_tb() + 20000; + struct media_pkt_query_resp_entry* entries = (struct media_pkt_query_resp_entry*)(wire + MEDIA_QUERY_RESP_HDR_SIZE); + for (int bi = 0; bi < count; bi++) { dl->query_blocks[bi] = bi; memcpy(entries[bi].block_id, dl->blocks[bi].block_id, 16); } +} + static void add_holder(struct media_download* dl, int bi, uint64_t node_id) { struct media_download_block* b = &dl->blocks[bi]; if (b->num_holders < MD_MAX_HOLDERS_PER_BLOCK) @@ -412,10 +432,12 @@ static void test_query_resp_empty(void) { struct media_download* dl = make_test_dl(db, inst, 1); if (!dl) { FAIL("make_test_dl"); sqlite3_close(db); u_free(inst); return; } - uint8_t pkt[MEDIA_QUERY_RESP_HDR_SIZE]; memset(pkt, 0, sizeof(pkt)); - pkt[0] = MEDIA_SUBCMD_QUERY_RESP; /* num_entries = 0 */ - media_download_handle_query_resp(inst, pkt, sizeof(pkt)); - OK(); + uint8_t pkt[MEDIA_QUERY_RESP_HDR_SIZE + sizeof(struct media_pkt_query_resp_entry)]; + query_response(dl, pkt, 1); + media_download_handle_query_resp(inst, dl->group_id, dl->query_node, pkt, sizeof(pkt)); + if (dl->blocks[0].num_holders == 1 && dl->blocks[0].holders[0] == dl->author_node_id + && dl->blocks[0].state == MD_BLK_REQ && !dl->query_deadline_tb) OK(); + else FAIL("empty result did not use author fallback"); free_test_dl(inst, dl); sqlite3_close(db); u_free(inst); @@ -433,17 +455,13 @@ static void test_query_resp_assign(void) { /* 2 держателя на каждый блок */ uint64_t n1 = 0x1111, n2 = 0x2222; - struct media_pkt_query_resp_entry entries[6]; - memset(entries, 0, sizeof(entries)); + uint8_t pkt[MEDIA_QUERY_RESP_HDR_SIZE + 3 * sizeof(struct media_pkt_query_resp_entry)]; + query_response(dl, pkt, 3); + struct media_pkt_query_resp_entry* entries = (struct media_pkt_query_resp_entry*)(pkt + MEDIA_QUERY_RESP_HDR_SIZE); for (int i = 0; i < 3; i++) { - entries[i * 2 + 0].node_id = n1; memcpy(entries[i * 2 + 0].block_id, dl->blocks[i].block_id, 16); - entries[i * 2 + 1].node_id = n2; memcpy(entries[i * 2 + 1].block_id, dl->blocks[i].block_id, 16); + entries[i].num_holders = 2; entries[i].holders[0] = n1; entries[i].holders[1] = n2; } - uint8_t pkt[3 + sizeof(entries)]; - pkt[0] = MEDIA_SUBCMD_QUERY_RESP; - uint16_t ne = 6; memcpy(pkt + 1, &ne, 2); - memcpy(pkt + 3, entries, sizeof(entries)); - media_download_handle_query_resp(inst, pkt, sizeof(pkt)); + media_download_handle_query_resp(inst, dl->group_id, dl->query_node, pkt, sizeof(pkt)); /* блоки разложены: holder_idx = i % num_holders (стартовый разброс) */ int ok = 1; @@ -498,11 +516,11 @@ static void test_cm_handle_lifetime(void) { h->ua = g_ua; h->deliver_up_token = uasync_call_soon(g_ua, &late, late_up); dl->num_peers = 1; dl->peers[0].node_id = 0x1111; dl->peers[0].cm_handle = h; uint8_t wire[MEDIA_QUERY_RESP_HDR_SIZE + 2 * sizeof(struct media_pkt_query_resp_entry)] = {MEDIA_SUBCMD_QUERY_RESP}; - uint16_t count = 2; memcpy(wire + 1, &count, 2); + query_response(dl, wire, 2); struct media_pkt_query_resp_entry* entries = (struct media_pkt_query_resp_entry*)(wire + MEDIA_QUERY_RESP_HDR_SIZE); - for (int bi = 0; bi < 2; bi++) { entries[bi].node_id = 0x1111; memcpy(entries[bi].block_id, dl->blocks[bi].block_id, 16); } - media_download_handle_query_resp(inst, wire, sizeof(wire)); - media_download_handle_query_resp(inst, wire, sizeof(wire)); + for (int bi = 0; bi < 2; bi++) { entries[bi].num_holders = 1; entries[bi].holders[0] = 0x1111; } + media_download_handle_query_resp(inst, dl->group_id, dl->query_node, wire, sizeof(wire)); + media_download_handle_query_resp(inst, dl->group_id, dl->query_node, wire, sizeof(wire)); int retained = dl->num_peers == 1 && dl->peers[0].cm_handle == h && dl->blocks[0].state == MD_BLK_CONN && dl->blocks[1].state == MD_BLK_CONN && dl->blocks[0].holder_idx == 0 && dl->blocks[1].holder_idx == 0; md_dl_conn_cb(h, 0x1111, dl->group_id, CONN_EVENT_TIMEOUT, dl);