test(chat): exercise channel deletion from a topology notification

This commit is contained in:
evgeny committed 2026-10-27 11:48:09 +01:00
1 parent 189ae43a7c
commit 33556fefea
1 file changed
+29 -3
+29 -3
View File
@@ -21,6 +21,9 @@ static int argument, last_target;
static sqlite3* reader;
static struct nodeinfo_cbk_entry* preserved_callback;
static unsigned ready;
static uint64_t route_group;
static int route_delete, route_inspect;
static unsigned route_seen, route_events;
extern int __real_member_sync_add_props_cbk(struct UTUN_INSTANCE*, node_props_changed_fn, void*);
int __wrap_member_sync_add_props_cbk(struct UTUN_INSTANCE* inst, node_props_changed_fn callback, void* arg) {
if (fail_props) { fail_props = 0; fail_malloc = 1; }
@@ -97,7 +100,13 @@ static void snapshot(sqlite3* db, uint8_t out[32]) {
}
static void event(struct UTUN_INSTANCE* inst, int type, const uint8_t* data, int bytes) {
(void)data; (void)bytes;
if (type == CHAT_EVT_MEMBER_UPDATED && route_group && bytes > 0 && data[0] < 21 && bytes > data[0]) {
char ch[21]; memcpy(ch, data + 1, data[0]); ch[data[0]] = 0;
if (strtoull(ch, NULL, 10) == route_group) {
route_events++;
if (route_delete) { route_delete = 0; chat_core_delete_channel(inst, ch); }
}
}
if (type != CHAT_EVT_DB_READY && type != CHAT_EVT_MY_NODE_ID) return;
assert(chat_core_is_initialized(inst) && sqlite3_get_autocommit(inst->topo_sqlite_db));
sqlite3_stmt* st = NULL;
@@ -129,7 +138,11 @@ static int deny_accounts(void* arg, int action, const char* name, const char* a,
}
static int veto(void* arg) { (*(unsigned*)arg)++; return 1; }
static void preserved(struct TOPO_GROUP* group, struct TOPO_GROUP_NODE* node, void* arg) { (void)group; (void)node; (void)arg; }
static void preserved(struct TOPO_GROUP* group, struct TOPO_GROUP_NODE* node, void* arg) {
if (route_inspect) {
assert(group->group_id == route_group && node->node_id == ((struct UTUN_INSTANCE*)arg)->node_id); route_seen++;
}
}
static void sql_faults(struct UTUN_INSTANCE* inst, const char* path) {
const char* queries[] = {"INSERT OR REPLACE INTO local_identity", "SELECT value FROM ui_state WHERE key='media_base'"}; unsigned cases = 0;
@@ -205,6 +218,19 @@ static void activation(struct UTUN_INSTANCE* inst, const char* path) {
puts("PASS lifecycle:corrupt catalog rejected;second channel activation failure cleans all runtime,keeps data,and retries without false ready");
}
static void route_notifications(struct UTUN_INSTANCE* inst, struct UASYNC* ua) {
ready = 0; assert(!chat_service_start(inst) && ready == 2);
route_group = chat_core_create_channel_auto(inst, "delete after route dispatch"); assert(route_group); uasync_poll(ua, 0);
struct TOPO_GROUP* group = topo_groups_find(inst->topo_groups, route_group); assert(group && group->local_node);
route_seen = route_events = 0; route_inspect = route_delete = 1;
topo_fire_nodeinfo_cbk(inst, group, group->local_node);
assert(group->local_node->node_id == inst->node_id && route_seen == 1 && route_delete && !route_events);
route_inspect = 0; uasync_poll(ua, 0);
assert(!route_delete && route_events == 1 && !topo_groups_find(inst->topo_groups, route_group));
route_group = 0; chat_service_stop(inst);
puts("PASS lifecycle:route observers and caller retain live group/node until dispatch returns;deferred event may delete channel");
}
int main(void) {
debug_config_init(); debug_set_level(DEBUG_LEVEL_ERROR); size_t baseline = u_get_allocated_count();
utun_instance_set_tun_init_enabled(0); struct UASYNC* ua = uasync_create(); assert(ua);
@@ -217,7 +243,7 @@ int main(void) {
assert(!utun_add_nodeinfo_cbk(inst, preserved, inst)); preserved_callback = inst->nodeinfo_cbks;
unsigned denied = 0; assert(sqlite3_set_authorizer(inst->topo_sqlite_db, deny_accounts, &denied) == SQLITE_OK);
refused(inst, database); assert(denied == 1); assert(sqlite3_set_authorizer(inst->topo_sqlite_db, NULL, NULL) == SQLITE_OK);
retry(inst, database); sql_faults(inst, database); validation(inst, database); activation(inst, database);
retry(inst, database); sql_faults(inst, database); validation(inst, database); activation(inst, database); route_notifications(inst, ua);
uint8_t before[32], after[32]; snapshot(reader, before); ready = 0;
target = "COMMIT /* chat init */"; fault = F_EXEC; fail_rollback = 1; inst->running = 1;
assert(chat_core_init(inst, database) < 0 && fault == F_NONE && !fail_rollback && !inst->running && !inst->chat_core);