Browse Source

Test PM media rollback, quota, snapshots and transfer cancellation

master
evgeny 2 weeks ago
parent
commit
7bd3e0d4de
  1. 44
      tests/test_dm_media.c

44
tests/test_dm_media.c

@ -24,6 +24,7 @@
#include "../src/routing_layer/etcp_router.h"
#include "../src/transport_layer/secure_channel.h"
#include "../src/transport_layer/etcp.h"
#include "../src/media_delivery/file_transfer.h"
#include "test_utils.h"
#define GROUP 4242424242424243ULL
@ -166,6 +167,48 @@ static void control(struct media_test* t, int dst, uint64_t source, uint8_t cmd,
inst->router_bindings.callbacks[ETCP_RT_ID_DM_MEDIA](conn, e);
}
static void cancelled(void* arg, int error) {
int* calls = arg;
*calls += error == -2 ? 1 : 100;
}
/* Ошибки регистрации не расходуют seq; квота проверяется до получения байтов. */
static int protocol_checks(struct media_test* t) {
struct UTUN_INSTANCE* a = t->nodes[A];
struct UTUN_INSTANCE* m = t->nodes[M];
const uint8_t* desc = dm_message_media(t->body, t->body_len);
uint8_t input[DM_MEDIA_DESC_SIZE + 1];
memcpy(input, desc, DM_MEDIA_DESC_SIZE); input[DM_MEDIA_DESC_SIZE] = 'x';
if (sqlite3_exec(a->topo_sqlite_db, "CREATE TEMP TRIGGER reject_dm_file BEFORE INSERT ON dm_files"
" BEGIN SELECT RAISE(ABORT,'injected media registration failure'); END", NULL, NULL, NULL)) return -1;
int rejected = dm_send(a, t->conv, "file", input, sizeof(input)) < 0;
if (sqlite3_exec(a->topo_sqlite_db, "DROP TRIGGER reject_dm_file", NULL, NULL, NULL)) return -1;
if (!rejected || value(a, "SELECT last_out_seq FROM dm_conversations") != 1 ||
value(a, "SELECT count(*) FROM dm_messages") != 1 || value(a, "SELECT count(*) FROM dm_outbox") != 0) return -1;
char json[8192]; size_t len;
if (dm_list_messages_json(a, t->conv, 200, 0, json, sizeof(json), &len) ||
!strstr(json, "\"media_status\":\"delivered\"") || !strstr(json, "\"media_path\":")) return -1;
uint8_t request[8 + sizeof(t->body)];
memcpy(request, &t->ids[B], 8); memcpy(request + 8, t->body, t->body_len);
uint8_t* metadata = (uint8_t*)dm_message_media(request + 8, t->body_len);
metadata[0] ^= 0x80;
uint64_t size = 2 * 1024 * 1024;
memcpy(metadata + 16, &size, 8);
if (sc_ed25519_sign(a->my_ed25519_privkey, request + 8, t->body_len - DM_MSG_SIG_SIZE,
request + 8 + t->body_len - DM_MSG_SIG_SIZE) || chat_setting_set(m, "dm_media_storage_mb", "1")) return -1;
control(t, M, t->ids[S], DM_MEDIA_STORE, request, 8 + t->body_len);
if (value(m, "SELECT count(*) FROM dm_custody") != 0 || chat_setting_set(m, "dm_media_storage_mb", "1024")) return -1;
char path[768]; snprintf(path, sizeof(path), "%s/cancelled.download", t->dir);
int calls = 0;
struct file_transfer_op* op = file_transfer_pull(t->nodes[B]->file_transfer, GROUP, t->ids[A], t->id,
dm_media_cipher_size(FILE_BYTES), path, cancelled, &calls);
if (!op) return -1;
file_transfer_cancel_object(t->nodes[B]->file_transfer, t->id);
if (calls != 1) return -1;
DEBUG_INFO(DEBUG_CATEGORY_DM, "media protocol checks passed: SQL rollback, quota, JSON state, CM operation cancellation");
return 0;
}
/* Таймер служит heartbeat: большие криптозадачи не должны останавливать сценарий. */
static void tick(void* arg) {
struct media_test* t = arg;
@ -193,6 +236,7 @@ static void tick(void* arg) {
value(m, "SELECT count(*) FROM dm_custody") != 0) { failure(t, "direct transfer/custody isolation"); return; }
uint8_t bad[DM_MEDIA_RECEIPT_SIZE]; memcpy(bad, t->receipt, sizeof(bad)); bad[56] ^= 1;
if (!dm_media_verify_receipt(a, bad, t->body, t->body_len)) { failure(t, "forged media receipt accepted"); return; }
if (protocol_checks(t)) { failure(t, "media protocol invariants"); return; }
utun_instance_destroy(b); t->nodes[B] = NULL; t->phase++;
}
break;

Loading…
Cancel
Save