Test current group devices without changing frozen delivery targets

This commit is contained in:
evgeny committed 2026-11-03 14:12:34 +01:00
1 parent a89c204586
commit 88035fc25d
2 files changed
+29

No files matched your search

+28
View File
@@ -10,6 +10,8 @@
#include "dm/dm_history.h"
#include "dm/dm_media_receipt.h"
#include "media_async/media_crypto.h"
#include "member_files/protocol.h"
#include "../lib/mem.h"
#include "../lib/debug_config.h"
#include "test_utils.h"
#include <assert.h>
@@ -80,6 +82,24 @@ static void seed_groups(void) {
}
}
static void check_members(int node, const char* conv, int own, int peer) {
uint8_t* data = NULL; size_t bytes = 0; uint64_t generation = dm_history_generation(nodes[node], conv);
assert(!dm_members_snapshot(nodes[node], conv, generation, &data, &bytes));
assert(data && data[0] == strlen(conv) && !memcmp(data + 1, conv, data[0]));
assert(mf_get64(data + 1 + data[0]) == generation);
unsigned count = mf_get16(data + 9 + data[0]); assert(count == (unsigned)(own + peer));
assert(bytes == 11 + data[0] + count * DM_MEMBER_WIRE_SIZE);
unsigned sides[2] = {0};
for (unsigned i = 0; i < count; i++) {
const uint8_t* row = data + 11 + data[0] + i * DM_MEMBER_WIRE_SIZE; struct chat_member_display member;
assert(row[0] <= 1 && !chat_core_deserialize_member(row + 1, &member)); sides[row[0]]++;
assert(member.node_id && member.name[0] && member.is_self == (member.node_id == nodes[node]->node_id));
assert(member.online == member.is_self); /* Никаких маршрутов: собственный узел online, остальные остаются в панели offline. */
}
assert(sides[0] == (unsigned)own && sides[1] == (unsigned)peer); u_free(data);
assert(dm_members_snapshot(nodes[node], conv, generation + 1, &data, &bytes) < 0 && !data && !bytes);
}
static uint64_t start(int from, int to, enum dm_mode mode, char conv[64]) {
uint64_t id = 0;
assert(!dm_start(nodes[from], nodes[to]->node_id, nodes[to]->my_keys.public_key, nodes[to]->my_ed25519_pubkey,
@@ -148,6 +168,7 @@ int main(void) {
struct UASYNC* ua = uasync_create(); assert(ua); create_nodes(ua, root); seed_channel(); seed_groups();
char conv[64], other[64]; uint64_t group_id = start(0, 2, DM_MODE_GROUPS, conv);
assert(start(0, 3, DM_MODE_GROUPS, other) == group_id);
check_members(0, conv, 2, 2);
uint8_t body[DM_BODY_MAX], reply[DM_BODY_MAX], receipt[DM_RECEIPT_SIZE];
size_t len = send_body(0, conv, "from A1", body);
struct dm_message_view view; assert(!dm_message_parse(body, len, &view) && view.target_count == 4 && view.seq == 1);
@@ -162,6 +183,7 @@ int main(void) {
}
assert(scalar(1, "SELECT dir FROM dm_messages") == 1 && scalar(1, "SELECT count(*) FROM dm_outbox") == 0);
assert(scalar(1, "SELECT last_out_seq FROM dm_conversations") == 0);
check_members(1, conv, 2, 2); check_members(2, conv, 2, 2);
for (int author = 1; author <= 3; author++) {
size_t n = send_body(author, conv, "another author", reply);
assert(!dm_message_parse(reply, n, &view) && view.seq == 1);
@@ -173,12 +195,17 @@ int main(void) {
assert(!dm_list_messages_json(nodes[0], conv, 200, 0, json, sizeof(json), &json_len));
assert(strstr(json, "from A1") && strstr(json, "another author") && !strstr(json, "\"pending\":true"));
uint64_t mixed = start(0, 4, DM_MODE_GROUPS, other);
check_members(0, other, 2, 1);
assert(mixed != group_id && mixed != start(0, 4, DM_MODE_DEVICE, other));
size_t n = send_body(0, other, "device to D", reply); assert(!dm_message_parse(reply, n, &view));
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);
assert(!chat_devgroup_leave(nodes[1]));
assert(!devgroup_project(nodes[0]->topo_sqlite_db, topo_node_registry_find(nodes[1]->topo_groups, nodes[1]->node_id)));
check_members(0, conv, 1, 2);
assert(scalar(0, "SELECT count(*) FROM dm_file_targets") == 3); /* Текущий состав не меняет delivery snapshot. */
/* Выход атомарен: ошибка 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));
@@ -186,6 +213,7 @@ int main(void) {
assert(!sqlite3_exec(nodes[0]->topo_sqlite_db, "DROP TRIGGER fail_close", NULL, NULL, NULL));
send_body(0, conv, "pending at exit", reply);
assert(!chat_devgroup_leave(nodes[0]));
check_members(0, conv, 0, 0);
assert(scalar(0, "SELECT count(*) FROM devgroup_local") == 0);
assert(scalar(0, "SELECT count(*) FROM dm_outbox o JOIN dm_conversations c USING(conv_id) WHERE c.mode=1") == 0);
assert(dm_send(nodes[0], conv, "text", (const uint8_t*)"forbidden", 9) < 0);