Verify old relay readers survive a new download generation independently

This commit is contained in:
evgeny committed 2026-10-22 19:45:45 +02:00
1 parent bd0260040c
commit 8f97cf8070
2 files changed
+46 -6

No files matched your search

+36 -1
View File
@@ -389,6 +389,40 @@ static void test_relay_cancel(void) {
puts("relay cancellation: exact attempt, idempotent request, sibling isolation and producer failure cleanup: PASS");
}
static void test_relay_generation(void) {
for (int cancel_new = 0; cancel_new < 2; cancel_new++) {
struct fixture f = ready(1);
struct media_download* dl = download(f.client);
struct media_block_source* old_source = dl->blocks[0].source;
char old_path[FILE_IO_PATH_MAX]; snprintf(old_path, sizeof(old_path), "%s", old_source->storage.temporary);
struct packet request = request_packet(dl, 0x300); receive(f.client, &request);
struct ETCP_ROUTER_CONN* slow = etcp_router_conn_get(f.client, GROUP, 0x300, ETCP_RT_ID_MEDIA_DELIVERY);
queue_set_threshold(slow->send_q, -1, 0);
struct packet old_chunk = chunk_packet(f.client, 0, 1), old_done = done_packet(f.client);
receive(f.client, &old_chunk); receive(f.client, &old_done); poll_ready();
REQUIRE(!download(f.client) && old_source->refs == 1 && old_source->verified && !access(old_path, F_OK));
start(f.client, &f.metadata); struct packet response = answer(f.server); receive(f.client, &response);
dl = download(f.client); struct media_block_source* new_source = dl->blocks[0].source;
REQUIRE(new_source != old_source && !old_source->indexed && new_source->indexed && new_source->refs == 1);
unchanged(f.client, &old_chunk); unchanged(f.client, &old_done);
if (cancel_new) REQUIRE(!media_download_cancel(f.client, dl->media_id, NULL, 0));
capture_blocks = 1; queue_set_threshold(slow->send_q, 0, 0); poll_ready();
REQUIRE(access(old_path, F_OK) && !f.client->md.streams && packet_count == 2);
REQUIRE(packets[0].data[0] == MEDIA_SUBCMD_BLOCK_CHUNK && packets[1].data[0] == MEDIA_SUBCMD_BLOCK_DONE);
REQUIRE(!memcmp(((struct media_pkt_block_chunk*)packets[0].data)->transfer_id,
((struct media_pkt_block_req*)request.data)->transfer_id, 16));
REQUIRE(((struct media_pkt_block_done*)packets[1].data)->status == MEDIA_BLOCK_OK);
if (!cancel_new) {
REQUIRE(download(f.client) == dl && dl->blocks[0].source == new_source && new_source->indexed && !new_source->available);
struct packet chunk = chunk_packet(f.client, 0, 1), done = done_packet(f.client);
receive(f.client, &chunk); receive(f.client, &done);
REQUIRE(done_count == 2 && !done_err && !download(f.client));
} else REQUIRE(done_count == 2 && done_err == -2);
finish(&f);
}
puts("relay across restart: old verified file drains independently of a new producer's success or cancellation: PASS");
}
static void test_destinations(void) {
struct fixture f = ready(1); struct media_download* dl = download(f.client);
char alias[1024]; snprintf(alias, sizeof(alias), "%s/./result.bin", directory);
@@ -509,7 +543,8 @@ int main(void) {
ua = uasync_create(); REQUIRE(ua);
snprintf(directory, sizeof(directory), "/tmp/utun-blocks-XXXXXX"); REQUIRE(!test_mkdtemp(directory));
test_identity_and_bounds(); test_rejected_attempts(); test_io_failures(); test_reentrant_cancel();
test_growing_relay(); test_relay_cancel(); test_destinations(); test_registration_failure_and_keys(); test_relay_limit_and_idle();
test_growing_relay(); test_relay_cancel(); test_relay_generation(); test_destinations();
test_registration_failure_and_keys(); test_relay_limit_and_idle();
test_indexed_source();
REQUIRE(!rmdir(directory)); uasync_destroy(ua, 0);
puts("media block regressions: PASS"); return 0;
+10 -5
View File
@@ -94,7 +94,15 @@ static struct UTUN_INSTANCE* make_minimal_instance(sqlite3* db) {
inst->node_id = 0xDEADBEEFDEADBEEFULL;
inst->topo_sqlite_db = db;
for (int i = 0; i < 32; i++) inst->my_ed25519_privkey[i] = (uint8_t)(rand() & 0xFF);
memset(inst->my_ed25519_pubkey, 0xDD, 32);
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, inst->my_ed25519_pubkey, &key_size) != 1) exit(1);
EVP_PKEY_free(author);
if (sqlite3_exec(db, "CREATE TABLE nodes(node_id INTEGER PRIMARY KEY,ed25519_pubkey BLOB)", NULL, NULL, NULL)) exit(1);
sqlite3_stmt* row = NULL;
if (sqlite3_prepare_v2(db, "INSERT INTO nodes VALUES(0xAAA,?)", -1, &row, NULL) != SQLITE_OK
|| sqlite3_bind_blob(row, 1, inst->my_ed25519_pubkey, 32, SQLITE_STATIC) != SQLITE_OK
|| sqlite3_step(row) != SQLITE_DONE || sqlite3_finalize(row) != SQLITE_OK) exit(1);
inst->md.inst = inst;
inst->md.db = db;
@@ -129,10 +137,7 @@ 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->author_pubkey, inst->my_ed25519_pubkey, 32);
struct ll_entry* qe = queue_entry_new(sizeof(*dl));
if (!qe) { u_free(dl->blocks); u_free(dl->block_sigs); u_free(dl); return NULL; }