Replace permissive media download fixtures with verified block inputs
This commit is contained in:
1 parent
d2bf40e11a
commit
16333b989d
2 files changed
+48
-27
No files matched your search
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user