Verify media source admission, redirect bounds and transmit I/O failure cleanup
This commit is contained in:
1 parent
47addfeffc
commit
fabeb770a7
1 file changed
+60
-9
@@ -122,8 +122,7 @@ static void test_identity_and_bounds(void) {
|
||||
for (size_t length = 0; length < done.len; length++) {
|
||||
struct packet bad = done; bad.len = length; unchanged(f.client, &bad);
|
||||
}
|
||||
for (int variant = 0; variant < 12; variant++) {
|
||||
if (variant < 6) {
|
||||
for (int variant = 0; variant < 6; variant++) {
|
||||
struct packet bad = done;
|
||||
struct media_pkt_block_done* d = (struct media_pkt_block_done*)bad.data;
|
||||
switch (variant) {
|
||||
@@ -135,14 +134,24 @@ static void test_identity_and_bounds(void) {
|
||||
case 5: d->chunk++; break;
|
||||
}
|
||||
unchanged(f.client, &bad);
|
||||
} else {
|
||||
struct packet bad = {.from = good.from, .group = GROUP, .len = sizeof(struct media_pkt_block_overloaded)};
|
||||
struct media_pkt_block_overloaded* ov = (struct media_pkt_block_overloaded*)bad.data;
|
||||
ov->subcmd = MEDIA_SUBCMD_BLOCK_OVERLOADED; memcpy(ov->media_id, f.metadata.media_id, 16);
|
||||
memcpy(ov->block_id, f.metadata.block_ids, 16); memset(ov->transfer_id, 0xFF, 16);
|
||||
unchanged(f.client, &bad);
|
||||
}
|
||||
}
|
||||
struct packet stale = {.from = good.from, .group = GROUP, .len = sizeof(struct media_pkt_block_overloaded)};
|
||||
struct media_pkt_block_overloaded* ov = (struct media_pkt_block_overloaded*)stale.data;
|
||||
ov->subcmd = MEDIA_SUBCMD_BLOCK_OVERLOADED; memcpy(ov->media_id, f.metadata.media_id, 16);
|
||||
memcpy(ov->block_id, f.metadata.block_ids, 16); memset(ov->transfer_id, 0xFF, 16); unchanged(f.client, &stale);
|
||||
struct packet redirect = {.from = good.from, .group = GROUP, .len = MEDIA_RELAY_FULL_HDR_SIZE + 8};
|
||||
struct media_pkt_block_relay_full* full = (struct media_pkt_block_relay_full*)redirect.data;
|
||||
full->subcmd = MEDIA_SUBCMD_BLOCK_RELAY_FULL; full->num_relay_nodes = 1;
|
||||
memcpy(full->media_id, f.metadata.media_id, 16); memcpy(full->block_id, f.metadata.block_ids, 16);
|
||||
memcpy(full->transfer_id, download(f.client)->blocks[0].transfer_id, 16);
|
||||
uint64_t node = 0x300; memcpy(redirect.data + sizeof(*full), &node, 8);
|
||||
for (size_t length = 0; length < redirect.len; length++) {
|
||||
struct packet bad = redirect; bad.len = length; unchanged(f.client, &bad);
|
||||
}
|
||||
stale = redirect; stale.len++; unchanged(f.client, &stale);
|
||||
stale = redirect; ((struct media_pkt_block_relay_full*)stale.data)->num_relay_nodes = UINT16_MAX;
|
||||
unchanged(f.client, &stale);
|
||||
stale = redirect; ((struct media_pkt_block_relay_full*)stale.data)->transfer_id[0]++; unchanged(f.client, &stale);
|
||||
finish(&f); REQUIRE(done_count == 1 && done_err == -2);
|
||||
puts("block identity, exact input bounds and duplicate without progress: PASS");
|
||||
}
|
||||
@@ -436,6 +445,47 @@ static void test_relay_limit_and_idle(void) {
|
||||
puts("relay admission permits five readers, echoes redirect attempt and releases idle readers: PASS");
|
||||
}
|
||||
|
||||
static void test_indexed_source(void) {
|
||||
for (int variant = 0; variant < 4; variant++) {
|
||||
struct fixture f = ready(4);
|
||||
struct media_download* dl = download(f.client);
|
||||
struct packet requests[4];
|
||||
for (int i = 0; i < 4; i++) requests[i] = request_packet(dl, 0x300 + i);
|
||||
struct packet chunk = chunk_packet(f.client, 0, 4), done = done_packet(f.client);
|
||||
receive(f.client, &chunk); receive(f.client, &done); REQUIRE(done_count == 1 && !done_err);
|
||||
capture_blocks = 1;
|
||||
receive(f.client, &requests[0]); REQUIRE(f.client->md.active_streams == 1);
|
||||
if (variant) {
|
||||
const enum io_fault operations[] = {IO_NONE, IO_READ, IO_SEEK, IO_CLOSE};
|
||||
fault = operations[variant]; poll_ready(); REQUIRE(fault_hits == 1 && !f.client->md.active_streams);
|
||||
REQUIRE(!f.client->md.streams && !f.client->md.file_loads->head && packet_count == 1);
|
||||
REQUIRE(packets[0].data[0] == MEDIA_SUBCMD_BLOCK_DONE
|
||||
&& ((struct media_pkt_block_done*)packets[0].data)->status == MEDIA_BLOCK_UNAVAILABLE);
|
||||
} else {
|
||||
receive(f.client, &requests[0]); REQUIRE(f.client->md.active_streams == 1);
|
||||
receive(f.client, &requests[1]); receive(f.client, &requests[2]); receive(f.client, &requests[3]);
|
||||
REQUIRE(f.client->md.active_streams == 3 && packet_count == 1 && packets[0].data[0] == MEDIA_SUBCMD_BLOCK_RELAY_FULL);
|
||||
const struct media_pkt_block_relay_full* full = (const struct media_pkt_block_relay_full*)packets[0].data;
|
||||
REQUIRE(full->num_relay_nodes == 3 && !memcmp(full->transfer_id,
|
||||
((struct media_pkt_block_req*)requests[3].data)->transfer_id, 16));
|
||||
struct packet cancel = cancellation(&requests[2]); receive(f.client, &cancel);
|
||||
struct md_file_load* load = md_file_load_find(&f.client->md, f.metadata.media_id);
|
||||
REQUIRE(f.client->md.active_streams == 2 && load->active_downloads == 2
|
||||
&& load->downloader_ids[0] == 0x300 && load->downloader_ids[1] == 0x301);
|
||||
cancel = cancellation(&requests[0]); receive(f.client, &cancel);
|
||||
REQUIRE(load->active_downloads == 1 && load->downloader_ids[0] == 0x301);
|
||||
receive(f.client, &requests[3]); REQUIRE(f.client->md.active_streams == 2);
|
||||
media_delivery_cancel_channel(f.client, GROUP);
|
||||
REQUIRE(!f.client->md.streams && !f.client->md.active_streams && !f.client->md.file_loads->head);
|
||||
poll_ready(); REQUIRE(packet_count == 1); // Отменённые pump не отправили DATA/DONE.
|
||||
}
|
||||
char path[512]; snprintf(path, sizeof(path), "%s/result.bin", directory);
|
||||
uint8_t hash[32]; REQUIRE(!ma_sha256_file(path, hash) && !memcmp(hash, f.metadata.content_hash, 32));
|
||||
finish(&f);
|
||||
}
|
||||
puts("indexed source: idempotency, source admission/redirect, exact cancellation counters and TX I/O failures: PASS");
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
debug_config_init(); debug_set_level(DEBUG_LEVEL_ERROR);
|
||||
if (getenv("UTUN_TEST_DEBUG")) debug_set_category_level(DEBUG_CATEGORY_MEDIA, DEBUG_LEVEL_DEBUG);
|
||||
@@ -450,6 +500,7 @@ int main(void) {
|
||||
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_indexed_source();
|
||||
REQUIRE(!rmdir(directory)); uasync_destroy(ua, 0);
|
||||
puts("media block regressions: PASS"); return 0;
|
||||
}
|
||||
Reference in new issue
Block a user