From bc41bb68b60650034309e1c51673c91101c78cd6 Mon Sep 17 00:00:00 2001 From: evgeny Date: Tue, 27 Oct 2026 05:05:40 +0100 Subject: [PATCH] test(chat): reproduce successful avatar publication after failed hash binding --- tests/Makefile.am | 4 ++++ tests/test_group_avatar_sql.c | 44 +++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 tests/test_group_avatar_sql.c diff --git a/tests/Makefile.am b/tests/Makefile.am index 970ea7ee..713b9085 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -302,6 +302,7 @@ test_socket_monitor_LDFLAGS += -Wl,--wrap=recvfrom -Wl,--wrap=__recvfrom_chk check_PROGRAMS += test_config_parser check_PROGRAMS += test_chat_setting check_PROGRAMS += test_chat_channel +check_PROGRAMS += test_group_avatar_sql check_PROGRAMS += test_instance_contract test_instance_contract_SOURCES = test_instance_contract.c test_instance_contract_LDADD = $(LIBUTUN) $(COMMON_LIBS) @@ -319,6 +320,9 @@ test_chat_channel_LDFLAGS = -Wl,--wrap=EVP_DigestSign -Wl,--wrap=sqlite3_exec -W -Wl,--wrap=sqlite3_step -Wl,--wrap=sqlite3_changes -Wl,--wrap=sqlite3_finalize -Wl,--wrap=u_malloc_impl \ -Wl,--wrap=EVP_PKEY_CTX_new_id -Wl,--wrap=EVP_PKEY_keygen_init -Wl,--wrap=EVP_PKEY_keygen \ -Wl,--wrap=EVP_PKEY_get_raw_public_key -Wl,--wrap=EVP_PKEY_get_raw_private_key -Wl,--wrap=RAND_bytes +test_group_avatar_sql_SOURCES = test_group_avatar_sql.c +test_group_avatar_sql_LDADD = $(LIBUTUN) $(COMMON_LIBS) +test_group_avatar_sql_LDFLAGS = -Wl,--wrap=sqlite3_bind_blob else test_socket_monitor_LDFLAGS += -Wl,--wrap=read endif diff --git a/tests/test_group_avatar_sql.c b/tests/test_group_avatar_sql.c new file mode 100644 index 00000000..aa682b17 --- /dev/null +++ b/tests/test_group_avatar_sql.c @@ -0,0 +1,44 @@ +/* Аватарка: настоящий commit и подпись, отказ SQL не меняет запись и не публикует событие. */ +#define _GNU_SOURCE +#include "../src/chat/group_avatar.c" +#include "../lib/debug_config.h" +#include +#include + +static int fail_hash; +static unsigned events; + +extern int __real_sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int, void (*)(void*)); +int __wrap_sqlite3_bind_blob(sqlite3_stmt* st, int index, const void* value, int size, void (*destroy)(void*)) { + const char* target = "UPDATE channels SET avatar_version="; + if (fail_hash && index == 3 && !strncmp(sqlite3_sql(st), target, strlen(target))) { + fail_hash = 0; DEBUG_WARN(DEBUG_CATEGORY_CHAT, "avatar test: injected hash bind failure"); return SQLITE_NOMEM; + } + return __real_sqlite3_bind_blob(st, index, value, size, destroy); +} + +static void event(struct UTUN_INSTANCE* inst, int type, const uint8_t* data, int size) { + (void)inst; (void)data; (void)size; + if (type == CHAT_EVT_CHANNEL_UPDATED) events++; +} + +int main(void) { + debug_config_init(); debug_set_level(DEBUG_LEVEL_ERROR); debug_set_category_level(DEBUG_CATEGORY_CHAT, DEBUG_LEVEL_INFO); + size_t baseline = u_get_allocated_count(); utun_instance_set_tun_init_enabled(0); + char directory[] = "/tmp/utun-avatar-sql-XXXXXX"; assert(mkdtemp(directory)); + char config[512]; snprintf(config, sizeof(config), "[global]\ndb_path=%s\n[ntp]\nenabled=no\n" + "[chatserver]\ngroup_autoconnect=0\nstorage_autoload=0\n", directory); + struct UASYNC* ua = uasync_create(); assert(ua); + struct UTUN_INSTANCE* inst = utun_instance_create_from_str(ua, config); + assert(inst && !utun_core_start(inst) && !chat_service_start(inst)); + uint64_t group = chat_core_create_channel_auto(inst, "avatar SQL"); assert(group); + chat_event_set_handler(inst, event); + const uint8_t image[] = {1, 2, 3}; fail_hash = 1; + int rc = group_avatar_set(inst, group, image, sizeof(image)); + DEBUG_INFO(DEBUG_CATEGORY_CHAT, "avatar test: hash bind failure result=%d events=%u fault_pending=%d", rc, events, fail_hash); + assert(rc < 0 && !events && !fail_hash); + struct group_avatar_record current; assert(!group_avatar_get(inst, group, ¤t) && !current.version); + assert(!group_avatar_set(inst, group, image, sizeof(image)) && events == 1); + utun_instance_destroy(inst); uasync_poll(ua, 0); uasync_destroy(ua, 0); assert(u_get_allocated_count() == baseline); + DEBUG_INFO(DEBUG_CATEGORY_CHAT, "PASS avatar SQL rollback and successful retry"); return 0; +}