Model admitted CHAT members in media test fixtures
This commit is contained in:
1 parent
7255e76ef7
commit
2b37d071b5
3 files changed
+54
-15
No files matched your search
@@ -10,6 +10,7 @@
|
||||
* Стенд сохраняет владение router: пакет потребляется даже при ошибке. Ответы доставляются отдельно,
|
||||
* поэтому можно проверить задержки, дубликаты, чужие ответы и состояние между пачками. */
|
||||
#include "test_utils.h"
|
||||
#include "media_members_fixture.h"
|
||||
#include "../src/utun_instance.h"
|
||||
#include "../src/chat/chat_core_priv.h"
|
||||
#include "../src/media_delivery/media_index.h"
|
||||
@@ -59,7 +60,8 @@ int __wrap_RAND_bytes(unsigned char* out, int count) {
|
||||
* В обоих исходах потребляет entry/dgram, как настоящий router; sent_hook вызывается только при успехе. */
|
||||
int __wrap_etcp_route_send(struct UTUN_INSTANCE* inst, uint64_t group, uint64_t dst,
|
||||
struct ll_entry* entry, int force, int mode) {
|
||||
(void)force; (void)mode;
|
||||
(void)force;
|
||||
REQUIRE(mode == (ROUTER_FLAG_SIGNED | ROUTER_FLAG_ENCRYPTED));
|
||||
int cmd = entry->dgram[1], rc = cmd == fail_send ? -1 : 0;
|
||||
if (cmd == MEDIA_SUBCMD_SYNC_REQ || cmd == MEDIA_SUBCMD_SYNC_RESP || cmd == MEDIA_SUBCMD_CHANGED) REQUIRE(!force);
|
||||
if (cmd == MEDIA_SUBCMD_BLOCK_REQ) request_count++;
|
||||
@@ -117,6 +119,9 @@ static struct UTUN_INSTANCE* instance(uint64_t node) {
|
||||
inst->ua = ua; inst->node_id = node;
|
||||
inst->chat_core = u_calloc(1, sizeof(struct chat_core_ctx)); REQUIRE(inst->chat_core);
|
||||
REQUIRE(sqlite3_open(":memory:", &inst->topo_sqlite_db) == SQLITE_OK);
|
||||
const uint64_t peers[] = {SERVER, SERVER + 1, SERVER + 2, CLIENT, 0x300, 0x301, 0x302, 0x303, 0x304, 0x400, 0x900,
|
||||
1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012};
|
||||
media_test_group(inst, GROUP, peers, sizeof(peers) / sizeof(*peers));
|
||||
REQUIRE(!etcp_router_init(inst) && !media_index_init(inst->topo_sqlite_db) && !media_delivery_init(inst));
|
||||
uint8_t pubkey[32]; size_t length = sizeof(pubkey);
|
||||
EVP_PKEY* key = EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL, author_key, 32); REQUIRE(key);
|
||||
@@ -133,7 +138,7 @@ static struct UTUN_INSTANCE* instance(uint64_t node) {
|
||||
/* Уничтожить media/router/SQLite/chat_core этого стенда и выполнить poll(0); inst обязателен, повтор не допускается.
|
||||
* Дополнительными ресурсами, которые тест сам добавил в inst (например topo_groups), владеет caller. */
|
||||
static void destroy(struct UTUN_INSTANCE* inst) {
|
||||
media_delivery_destroy(inst); etcp_router_destroy(inst); sqlite3_close(inst->topo_sqlite_db);
|
||||
media_delivery_destroy(inst); etcp_router_destroy(inst); media_test_groups_free(inst); sqlite3_close(inst->topo_sqlite_db);
|
||||
u_free(inst->chat_core); u_free(inst); uasync_poll(ua, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/* Минимальная CHAT-топология и результат проверки member_sync для unit-тестов медиа.
|
||||
* Не моделирует подписи участников: сетевые тесты используют test_membership.h. */
|
||||
#ifndef MEDIA_MEMBERS_FIXTURE_H
|
||||
#define MEDIA_MEMBERS_FIXTURE_H
|
||||
#include "../src/utun_instance.h"
|
||||
#include "../src/routing_layer/topo_group.h"
|
||||
#include "../lib/mem.h"
|
||||
#include "../lib/debug_config.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static void media_test_group(struct UTUN_INSTANCE* inst, uint64_t id, const uint64_t* peers, size_t count) {
|
||||
if (!inst->topo_groups) {
|
||||
inst->topo_groups = u_calloc(1, sizeof(*inst->topo_groups));
|
||||
if (!inst->topo_groups) abort();
|
||||
inst->topo_groups->instance = inst;
|
||||
inst->topo_groups->group_list = queue_new(inst->ua, 16, 0, 8, "media_test_groups");
|
||||
if (!inst->topo_groups->group_list) abort();
|
||||
}
|
||||
if (!topo_groups_find(inst->topo_groups, id)) {
|
||||
struct TOPO_GROUP* g = (void*)queue_entry_new(sizeof(*g) - sizeof(struct ll_entry));
|
||||
if (!g) abort();
|
||||
g->instance = inst; g->group_id = id; g->group_type = TOPO_GROUP_TYPE_CHAT;
|
||||
snprintf(g->channel_id, sizeof(g->channel_id), "%llu", (unsigned long long)id);
|
||||
if (queue_data_put_with_index(inst->topo_groups->group_list, &g->ll)) abort();
|
||||
}
|
||||
char sql[512];
|
||||
snprintf(sql, sizeof(sql), "CREATE TABLE IF NOT EXISTS peers_%llu(node_id INTEGER PRIMARY KEY,source INTEGER DEFAULT 0,"
|
||||
"deleted INTEGER DEFAULT 0,admitted INTEGER DEFAULT 1,node_type INTEGER DEFAULT 0,adm_tags TEXT DEFAULT '{}')",
|
||||
(unsigned long long)id);
|
||||
if (sqlite3_exec(inst->topo_sqlite_db, sql, NULL, NULL, NULL) != SQLITE_OK) abort();
|
||||
for (size_t i = 0; i <= count; i++) {
|
||||
snprintf(sql, sizeof(sql), "INSERT OR IGNORE INTO peers_%llu(node_id) VALUES(%lld)",
|
||||
(unsigned long long)id, (long long)(i == count ? inst->node_id : peers[i]));
|
||||
if (sqlite3_exec(inst->topo_sqlite_db, sql, NULL, NULL, NULL) != SQLITE_OK) abort();
|
||||
}
|
||||
}
|
||||
|
||||
/* Только для минимальных групп этого стенда, после остановки media/router. */
|
||||
static void media_test_groups_free(struct UTUN_INSTANCE* inst) {
|
||||
if (!inst->topo_groups) return;
|
||||
queue_clear(inst->topo_groups->group_list); queue_free(inst->topo_groups->group_list);
|
||||
u_free(inst->topo_groups); inst->topo_groups = NULL;
|
||||
}
|
||||
#endif
|
||||
@@ -58,18 +58,9 @@ static void write_le(void* ptr, uint64_t v, unsigned n) {
|
||||
/* Только транспорт управляемый: каталог, роли, router-очереди и обработчики — настоящие.
|
||||
* Таблица peers отражает результат уже проверенного member_sync; криптография членства проверяется его тестами. */
|
||||
static void add_group(struct UTUN_INSTANCE* inst, uint64_t group) {
|
||||
if (!inst->topo_groups) {
|
||||
inst->topo_groups = u_calloc(1, sizeof(*inst->topo_groups)); REQUIRE(inst->topo_groups);
|
||||
inst->topo_groups->instance = inst;
|
||||
inst->topo_groups->group_list = queue_new(ua, 16, 0, 8, "test_groups"); REQUIRE(inst->topo_groups->group_list);
|
||||
}
|
||||
struct ll_entry* e = queue_entry_new(sizeof(struct TOPO_GROUP) - sizeof(struct ll_entry)); REQUIRE(e);
|
||||
struct TOPO_GROUP* g = (struct TOPO_GROUP*)e;
|
||||
g->instance = inst; g->group_id = group; g->group_type = TOPO_GROUP_TYPE_CHAT;
|
||||
snprintf(g->channel_id, sizeof(g->channel_id), "%llu", (unsigned long long)group);
|
||||
queue_data_put_with_index(inst->topo_groups->group_list, e);
|
||||
media_test_group(inst, group, NULL, 0);
|
||||
char command[512];
|
||||
snprintf(command, sizeof(command), "CREATE TABLE peers_%llu(node_id INTEGER PRIMARY KEY,adm_tags TEXT,admitted INTEGER DEFAULT 1);"
|
||||
snprintf(command, sizeof(command), "DELETE FROM peers_%llu;"
|
||||
"INSERT INTO peers_%llu(node_id,adm_tags) VALUES(256,'{\"supernode\":\"yes\"}'),(512,'{\"supernode\":\"yes\"}'),(768,'{\"supernode\":\"yes\"}')",
|
||||
(unsigned long long)group, (unsigned long long)group);
|
||||
sql(inst->md.db, command);
|
||||
@@ -81,9 +72,7 @@ static struct UTUN_INSTANCE* node(uint64_t id) {
|
||||
}
|
||||
|
||||
static void free_node(struct UTUN_INSTANCE* inst) {
|
||||
struct TOPO_GROUPS* groups = inst->topo_groups;
|
||||
destroy(inst);
|
||||
if (groups) { queue_free(groups->group_list); u_free(groups); }
|
||||
}
|
||||
|
||||
static struct media_super_peer* peer(struct UTUN_INSTANCE* inst, uint64_t remote, uint64_t group) {
|
||||
|
||||
Reference in new issue
Block a user