diff --git a/tests/test_media_delivery_download.c b/tests/test_media_delivery_download.c index c9d487c2..31ed6ff0 100644 --- a/tests/test_media_delivery_download.c +++ b/tests/test_media_delivery_download.c @@ -129,6 +129,10 @@ static struct media_download* make_test_dl(sqlite3* db, struct UTUN_INSTANCE* in dl->active = 1; dl->inst = inst; dl->author_node_id = 0xAAAA000000000001ULL; + EVP_PKEY* author = EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL, inst->my_ed25519_privkey, 32); + size_t key_size = 32; + if (!author || EVP_PKEY_get_raw_public_key(author, dl->author_pubkey, &key_size) != 1) exit(1); + EVP_PKEY_free(author); memcpy(dl->ll.data, dl->media_id, 16); struct ll_entry* qe = queue_entry_new(sizeof(*dl)); @@ -138,21 +142,20 @@ static struct media_download* make_test_dl(sqlite3* db, struct UTUN_INSTANCE* in queue_data_put_with_index(inst->md.downloads, qe); ((struct media_download*)qe->data)->entry = qe; ((struct media_download*)qe->data)->refs = 1; + dl = (struct media_download*)qe->data; + for (int bi = 0; bi < num_blocks; bi++) { + make_uuid(dl->blocks[bi].transfer_id); + dl->blocks[bi].source = md_block_create(&inst->md, dl->group_id, dl->media_id, + dl->blocks[bi].block_id, (uint32_t)bi, CHUNK_SIZE, dl->dest_path); + if (!dl->blocks[bi].source) exit(1); + } return (struct media_download*)qe->data; } 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) { - struct ll_entry* e = queue_find_data_by_index(inst->md.downloads, dl->media_id); - if (e) { queue_remove_data(inst->md.downloads, e); queue_entry_free(e); } - if (!inst->md.downloads->head) { queue_free(inst->md.downloads); inst->md.downloads = NULL; } - } + media_download_cancel(inst, dl->media_id, NULL, 0); + media_delivery_destroy(inst); } /* Полный ответ на текущую пачку; тесты задают только найденных держателей. */ @@ -181,7 +184,8 @@ static void test_chunk_offset_write(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 cdata[256]; for (int i = 0; i < 256; i++) cdata[i] = (uint8_t)(i & 0xFF); + add_holder(dl, 0, 0x1111); dl->blocks[0].holder_idx = 0; dl->blocks[0].state = MD_BLK_REQ; dl->inflight = 1; + uint8_t cdata[60]; for (int i = 0; i < 60; i++) cdata[i] = (uint8_t)i; uint8_t pkt[MEDIA_BLOCK_CHUNK_HDR_SIZE + sizeof(cdata)]; struct media_pkt_block_chunk* ch = (struct media_pkt_block_chunk*)pkt; @@ -189,23 +193,26 @@ static void test_chunk_offset_write(void) { ch->subcmd = MEDIA_SUBCMD_BLOCK_CHUNK; memcpy(ch->media_id, dl->media_id, 16); memcpy(ch->block_id, dl->blocks[0].block_id, 16); + memcpy(ch->transfer_id, dl->blocks[0].transfer_id, 16); ch->chunk = 0; ch->offset = 0; ch->data_len = (uint16_t)sizeof(cdata); memcpy(pkt + MEDIA_BLOCK_CHUNK_HDR_SIZE, cdata, sizeof(cdata)); - media_download_handle_chunk(inst, pkt, sizeof(pkt)); - char tmp[1024]; snprintf(tmp, sizeof(tmp), "%s.chunk_0", dl->dest_path); + media_download_handle_chunk(inst, dl->group_id, 0x1111, pkt, sizeof(pkt)); + const char* tmp = dl->blocks[0].source->storage.temporary; int s1 = file_size(tmp); /* дубль с тем же offset — не должен добавить данные */ - media_download_handle_chunk(inst, pkt, sizeof(pkt)); + uint64_t progress = dl->blocks[0].last_progress_tb; + media_download_handle_chunk(inst, dl->group_id, 0x1111, pkt, sizeof(pkt)); int s2 = file_size(tmp); - /* чанк со смещением 200 — пишется по offset, размер растёт до 200+256 */ - ch->offset = 200; - media_download_handle_chunk(inst, pkt, sizeof(pkt)); + /* Только непрерывный хвост укладывается в объявленный размер блока. */ + ch->offset = 60; ch->data_len = 40; + int duplicate_ignored = progress == dl->blocks[0].last_progress_tb; + media_download_handle_chunk(inst, dl->group_id, 0x1111, pkt, sizeof(*ch) + 40); int s3 = file_size(tmp); - int ok = s1 == 256 && s2 == 256 && s3 == 456 && dl->blocks[0].bytes_received == 456; + int ok = s1 == 60 && s2 == 60 && s3 == 100 && dl->blocks[0].bytes_received == 100 && duplicate_ignored; if (ok) OK(); else FAIL("s1=%d s2=%d s3=%d bytes=%u", s1, s2, s3, dl->blocks[0].bytes_received); free_test_dl(inst, dl); @@ -223,8 +230,19 @@ static void test_done_assembly(void) { if (!dl) { FAIL("make_test_dl"); sqlite3_close(db); u_free(inst); return; } uint8_t d0[CHUNK_SIZE], d1[CHUNK_SIZE]; memset(d0, 0xA0, CHUNK_SIZE); memset(d1, 0xB1, CHUNK_SIZE); - { char c[1024]; snprintf(c, sizeof(c), "%s.chunk_0", dl->dest_path); write_file(c, d0, CHUNK_SIZE); } - { char c[1024]; snprintf(c, sizeof(c), "%s.chunk_1", dl->dest_path); write_file(c, d1, CHUNK_SIZE); } + write_file(dl->blocks[0].source->storage.temporary, d0, CHUNK_SIZE); + write_file(dl->blocks[1].source->storage.temporary, d1, CHUNK_SIZE); + if (sc_ed25519_sign(inst->my_ed25519_privkey, d0, CHUNK_SIZE, dl->block_sigs) != SC_OK + || sc_ed25519_sign(inst->my_ed25519_privkey, d1, CHUNK_SIZE, dl->block_sigs + 64) != SC_OK) exit(1); + EVP_MD_CTX* hash = EVP_MD_CTX_new(); unsigned hash_size; + if (!hash || EVP_DigestInit_ex(hash, EVP_sha256(), NULL) != 1 || EVP_DigestUpdate(hash, d0, CHUNK_SIZE) != 1 + || EVP_DigestUpdate(hash, d1, CHUNK_SIZE) != 1 || EVP_DigestFinal_ex(hash, dl->content_hash, &hash_size) != 1) exit(1); + EVP_MD_CTX_free(hash); + for (int bi = 0; bi < 2; bi++) { + add_holder(dl, bi, 0x1111); dl->blocks[bi].holder_idx = 0; + dl->blocks[bi].state = MD_BLK_RECV; dl->blocks[bi].bytes_received = CHUNK_SIZE; + } + dl->inflight = 2; char dest[1024]; snprintf(dest, sizeof(dest), "%s", dl->dest_path); for (int bi = 0; bi < 2; bi++) { @@ -233,13 +251,14 @@ static void test_done_assembly(void) { bd->subcmd = MEDIA_SUBCMD_BLOCK_DONE; memcpy(bd->media_id, dl->media_id, 16); memcpy(bd->block_id, dl->blocks[bi].block_id, 16); bd->chunk = (uint32_t)bi; bd->total_size = CHUNK_SIZE; - memcpy(bd->block_sig, dl->block_sigs + bi * 64, 64); - media_download_handle_done(inst, pkt, sizeof(pkt)); + memcpy(bd->transfer_id, dl->blocks[bi].transfer_id, 16); + media_download_handle_done(inst, dl->group_id, 0x1111, pkt, sizeof(pkt)); } int sz = file_size(dest); if (sz == CHUNK_SIZE * 2) OK(); else FAIL("assembled size %d != %d", sz, CHUNK_SIZE * 2); /* dl уже освобождён через md_dl_finish */ + media_delivery_destroy(inst); sqlite3_close(db); u_free(inst); } } @@ -256,18 +275,20 @@ static void test_done_bad_sig(void) { dl->blocks[0].holder_idx = 0; uint8_t data[CHUNK_SIZE]; memset(data, 0xFF, CHUNK_SIZE); - { char c[1024]; snprintf(c, sizeof(c), "%s.chunk_0", dl->dest_path); write_file(c, data, CHUNK_SIZE); } + write_file(dl->blocks[0].source->storage.temporary, data, CHUNK_SIZE); + dl->blocks[0].state = MD_BLK_RECV; dl->blocks[0].bytes_received = CHUNK_SIZE; dl->inflight = 1; uint8_t pkt[MEDIA_BLOCK_DONE_SIZE]; memset(pkt, 0, sizeof(pkt)); struct media_pkt_block_done* bd = (struct media_pkt_block_done*)pkt; bd->subcmd = MEDIA_SUBCMD_BLOCK_DONE; memcpy(bd->media_id, dl->media_id, 16); memcpy(bd->block_id, dl->blocks[0].block_id, 16); bd->chunk = 0; bd->total_size = CHUNK_SIZE; - memset(bd->block_sig, 0xAA, 64); /* WRONG */ - media_download_handle_done(inst, pkt, sizeof(pkt)); + memcpy(bd->transfer_id, dl->blocks[0].transfer_id, 16); + memset(dl->block_sigs, 0xAA, 64); /* Неверная подпись в доверенных метаданных. */ + media_download_handle_done(inst, dl->group_id, 0x1111, pkt, sizeof(pkt)); /* файл не собран; блок в WAIT (1 держатель, попытка ушла) */ - int ok = dl->blocks_validated == 0 && !dl->assembled && dl->blocks[0].attempts == 1 && dl->blocks[0].state == MD_BLK_WAIT; + int ok = dl->blocks_validated == 0 && !dl->assembled && dl->blocks[0].attempts == 1 && dl->blocks[0].state == MD_BLK_REQ; if (ok) OK(); else FAIL("validated=%d assembled=%d attempts=%d state=%d", dl->blocks_validated, dl->assembled, dl->blocks[0].attempts, dl->blocks[0].state); free_test_dl(inst, dl); diff --git a/tests/test_media_download_timeout.c b/tests/test_media_download_timeout.c index 36c45c55..05fd220c 100644 --- a/tests/test_media_download_timeout.c +++ b/tests/test_media_download_timeout.c @@ -53,7 +53,7 @@ static struct UTUN_INSTANCE* make_minimal(void) { DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "timeout test media schema initialization failed"); exit(1); } if (sqlite3_exec(db, "CREATE TABLE nodes(node_id INTEGER PRIMARY KEY,ed25519_pubkey BLOB);" - "INSERT INTO nodes VALUES(841029813740322817,zeroblob(32)),(841029813740322818,zeroblob(32))", + "INSERT INTO nodes VALUES(0xBADF00D00000001,zeroblob(32)),(0xBADF00D00000002,zeroblob(32))", NULL, NULL, NULL) != SQLITE_OK) exit(1); for (int i = 0; i < 32; i++) inst->my_ed25519_privkey[i] = (uint8_t)(rand() & 0xFF); memset(inst->my_ed25519_pubkey, 0xDD, 32);