test(member-files): preserve unowned download temp on refusal

This commit is contained in:
evgeny committed 2026-10-24 17:33:47 +02:00
1 parent 8185b83eba
commit 27dd9e7b60
1 file changed
+33
+33
View File
@@ -49,6 +49,8 @@ struct network_test {
int (*server_receive_ready)(struct UTUN_INSTANCE*, uint64_t, uint64_t, const uint8_t*, size_t);
int (*saved_receive_ready)(struct UTUN_INSTANCE*, uint64_t, uint64_t, const uint8_t*, size_t);
unsigned restart_tick;
unsigned preservation_case;
char preserved_temp[864];
struct api_case api[8];
void* timer;
};
@@ -124,6 +126,27 @@ static int check_file(const char* path, unsigned size) {
fclose(file); return ok;
}
/* Чужой temp и прежнее назначение должны пережить отказ до создания своего файла. */
static void preservation_start(struct network_test* t) {
struct api_case* c = &t->api[7]; memset(c, 0, sizeof(*c)); c->id = 207 + t->preservation_case;
snprintf(c->local, sizeof(c->local), "%s/preserved.bin", t->dir);
snprintf(t->preserved_temp, sizeof(t->preserved_temp), "%s.utun-%016llx.part", c->local, (unsigned long long)c->id);
const char* paths[] = { c->local, t->preserved_temp };
for (unsigned n = 0; n < 2; n++) {
FILE* file = fopen(paths[n], "wb");
if (!file) { fail(t, "preservation fixture open"); return; }
int error = 0;
for (unsigned i = 0; i < 37; i++) if (fputc((i * 73 + 19) & 255, file) == EOF) error = 1;
if (fclose(file) || error) { fail(t, "preservation fixture write/close"); return; }
}
struct mf_transfer_request q = { .inst = t->nodes[READER], .id = c->id, .group = GROUP,
.server = t->ids[SERVER], .owner = t->ids[AUTHOR], .max_bytes = t->preservation_case == 1 ? BYTES - 1 : 0 };
snprintf(q.remote, sizeof(q.remote), "file.bin"); snprintf(q.local, sizeof(q.local), "%s", c->local);
c->handle = member_files_transfer_start(&q, api_event, c);
if (!c->handle) { fail(t, "preservation transfer start"); return; }
if (t->preservation_case == 2) member_files_transfer_cancel(c->handle);
}
static int hold_receive(struct UTUN_INSTANCE* inst, uint64_t group, uint64_t peer, const uint8_t* payload, size_t bytes) {
(void)inst; (void)group; (void)peer; (void)payload; (void)bytes; return 0;
}
@@ -298,6 +321,16 @@ static void tick(void* arg) {
if (t->api[7].status != MF_STALE || !check_file(t->api[7].local, 0)) {
fail(t, "stale download changed existing destination"); return;
}
t->phase = 23; preservation_start(t);
} else if (t->phase == 23 && t->api[7].finished) {
const int expected[] = { MF_EXISTS, MF_INVALID_RANGE, MF_CANCELLED };
int target_ok = check_file(t->api[7].local, 37), temp_ok = check_file(t->preserved_temp, 37);
DEBUG_INFO(DEBUG_CATEGORY_MEDIA, "member_files: preservation case=%u status=%s expected=%s target=%d foreign_temp=%d",
t->preservation_case, mf_status_text(t->api[7].status), mf_status_text(expected[t->preservation_case]), target_ok, temp_ok);
if (t->api[7].status != expected[t->preservation_case] || !target_ok || !temp_ok) {
fail(t, "download refusal/cancel removed unowned temp or changed target"); return;
}
if (++t->preservation_case < 3) { preservation_start(t); goto again; }
t->phase = 10; t->answered = 0;
struct mf_message q = { .command = MF_STAT, .owner = t->ids[AUTHOR] }; snprintf(q.path, sizeof(q.path), "cancelled.bin");
if (!member_files_request(t->nodes[READER], GROUP, t->ids[SERVER], &q, response, t)) { fail(t, "cancelled STAT"); return; }