Replace permissive media download fixtures with verified block inputs

This commit is contained in:
evgeny committed 2026-10-22 19:16:23 +02:00
1 parent d2bf40e11a
commit 16333b989d
2 files changed
+48 -27

No files matched your search

+47 -26
View File
@@ -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);
+1 -1
View File
@@ -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);