tests: cover subgroup file receipts and endpoint storage policy across restart
This commit is contained in:
1 parent
45f4ca0f31
commit
576236daeb
2 files changed
+108
-3
No files matched your search
@@ -8,6 +8,8 @@
|
||||
#include "dm/dm_core.h"
|
||||
#include "dm/dm_crypto.h"
|
||||
#include "dm/dm_history.h"
|
||||
#include "dm/dm_media_receipt.h"
|
||||
#include "media_async/media_crypto.h"
|
||||
#include "../lib/debug_config.h"
|
||||
#include "test_utils.h"
|
||||
#include <assert.h>
|
||||
@@ -95,6 +97,51 @@ static size_t send_body(int from, const char* conv, const char* text, uint8_t bo
|
||||
memcpy(body, sqlite3_column_blob(st, 0), len); sqlite3_finalize(st); return len;
|
||||
}
|
||||
|
||||
/* Четыре участника раскрывают один файл; политика M считает только устройства получателя. */
|
||||
static void group_file(const char* conv, const char* root) {
|
||||
uint8_t data[1024] = {7}, key[32], secret[32], restored[32];
|
||||
struct dm_party parties[2];
|
||||
assert(!dm_conversation_access(nodes[0], conv, parties, NULL));
|
||||
memcpy(data + DM_MEDIA_DESC_SIZE, "DMKEY001", 8);
|
||||
uint8_t* keys = data + DM_MEDIA_DESC_SIZE + 8;
|
||||
uint64_t id = strtoull(conv, NULL, 10);
|
||||
assert(!dm_file_keys_create(id, nodes[0]->node_id, data, parties, keys, key));
|
||||
for (unsigned i = 0; i < 4; i++) {
|
||||
assert(!dm_party_private(nodes[i], parties + i / 2, secret));
|
||||
assert(!dm_file_keys_open(id, nodes[0]->node_id, data, parties, i / 2, secret, keys, restored));
|
||||
assert(!memcmp(key, restored, sizeof(key)));
|
||||
}
|
||||
char path[1024], cipher[1024];
|
||||
snprintf(path, sizeof(path), "%s/0/dm_media/07000000000000000000000000000000.file", root);
|
||||
snprintf(cipher, sizeof(cipher), "%s/0/dm_media/07000000000000000000000000000000.cipher", root);
|
||||
FILE* plain = fopen(path, "wb+"); FILE* encrypted = fopen(cipher, "wb"); assert(plain && encrypted);
|
||||
assert(fwrite("payload", 1, 7, plain) == 7); rewind(plain); uint64_t size;
|
||||
assert(!media_encrypt_stream(key, nodes[0]->node_id, data, plain, encrypted, &size, data + 24));
|
||||
assert(!fclose(plain) && !fclose(encrypted)); memcpy(data + 16, &size, 8);
|
||||
struct attachment_info info = {.kind = ATTACHMENT_FILE}; snprintf(info.name, sizeof(info.name), "group.bin");
|
||||
int n = attachment_encode(&info, data + DM_MEDIA_DESC_SIZE + DM_MEDIA_KEYS_HEADER_SIZE, ATTACHMENT_WIRE_MAX); assert(n > 0);
|
||||
assert(!dm_send(nodes[0], conv, "file", data, DM_MEDIA_DESC_SIZE + DM_MEDIA_KEYS_HEADER_SIZE + n));
|
||||
sqlite3_stmt* st = NULL;
|
||||
assert(sqlite3_prepare_v2(nodes[0]->topo_sqlite_db, "SELECT body FROM dm_files", -1, &st, NULL) == SQLITE_OK);
|
||||
assert(sqlite3_step(st) == SQLITE_ROW); uint8_t body[DM_BODY_MAX], r[DM_MEDIA_RECEIPT_SIZE], ack[DM_RECEIPT_SIZE];
|
||||
size_t len = (size_t)sqlite3_column_bytes(st, 0); memcpy(body, sqlite3_column_blob(st, 0), len); sqlite3_finalize(st);
|
||||
for (unsigned i = 1; i < 4; i++) assert(!dm_accept_message(nodes[i], body, len, ack));
|
||||
struct dm_message_view view; assert(!dm_message_parse(body, len, &view));
|
||||
assert(dm_media_user_action(nodes[2], conv, view.author, view.seq, 1) < 0); /* Само наличие сообщения — не открытие. */
|
||||
assert(dm_media_receipt_make(nodes[1], body, len, 1, r) < 0); /* Свой узел не удаляет серверный файл. */
|
||||
assert(dm_media_receipt_make(nodes[4], body, len, 0, r) < 0);
|
||||
assert(!dm_media_retention_done(nodes[0], data, 0) && !dm_media_retention_done(nodes[0], data, 1));
|
||||
assert(!dm_media_receipt_make(nodes[2], body, len, 0, r) && !dm_media_receipt_save(nodes[0], r, body, len));
|
||||
assert(!dm_media_receipt_save(nodes[0], r, body, len)); /* Повтор не увеличивает число получателей. */
|
||||
assert(!dm_media_retention_done(nodes[0], data, 0) && !dm_media_retention_done(nodes[0], data, 1));
|
||||
assert(!dm_media_receipt_make(nodes[2], body, len, 1, r) && !dm_media_receipt_save(nodes[0], r, body, len));
|
||||
assert(!dm_media_retention_done(nodes[0], data, 0) && dm_media_retention_done(nodes[0], data, 1) == 1);
|
||||
assert(!dm_media_receipt_make(nodes[3], body, len, 0, r) && !dm_media_receipt_save(nodes[0], r, body, len));
|
||||
assert(dm_media_retention_done(nodes[0], data, 0) == 1);
|
||||
assert(scalar(0, "SELECT count(*) FROM dm_file_targets WHERE side=0 AND received IS NULL") == 1);
|
||||
r[56] ^= 1; assert(dm_media_receipt_save(nodes[0], r, body, len) < 0);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
debug_config_init(); debug_set_level(DEBUG_LEVEL_WARN); debug_set_category_level(DEBUG_CATEGORY_DM, DEBUG_LEVEL_DEBUG);
|
||||
char root[512] = "/tmp/utun_dm_groups_XXXXXX"; assert(!test_mkdtemp(root));
|
||||
@@ -131,6 +178,7 @@ int main(void) {
|
||||
assert(view.mode == DM_MODE_DEVICE && view.seq == 2 && !dm_accept_message(nodes[4], reply, n, receipt));
|
||||
assert(start(0, 1, DM_MODE_DEVICE, other) == dm_derive_conv_id(nodes[0]->node_id, nodes[1]->node_id));
|
||||
n = send_body(0, other, "own device", reply); assert(!dm_accept_message(nodes[1], reply, n, receipt));
|
||||
group_file(conv, root);
|
||||
/* Выход атомарен: ошибка SQL не удаляет секреты и не закрывает беседу. */
|
||||
assert(!sqlite3_exec(nodes[0]->topo_sqlite_db, "CREATE TEMP TRIGGER fail_close BEFORE UPDATE OF closed ON dm_conversations"
|
||||
" BEGIN SELECT RAISE(ABORT,'injected closure failure'); END", NULL, NULL, NULL));
|
||||
|
||||
Reference in new issue
Block a user