test(chat): reproduce committed UI state after a finalization error

This commit is contained in:
evgeny committed 2026-10-27 07:22:45 +01:00
1 parent 34e729d988
commit 5360453960
2 files changed
+47

No files matched your search

+4
View File
@@ -306,6 +306,7 @@ check_PROGRAMS += test_group_avatar_sql
check_PROGRAMS += test_chat_member
check_PROGRAMS += test_chat_json
check_PROGRAMS += test_chat_profile
check_PROGRAMS += test_chat_preferences
check_PROGRAMS += test_instance_contract
test_instance_contract_SOURCES = test_instance_contract.c
test_instance_contract_LDADD = $(LIBUTUN) $(COMMON_LIBS)
@@ -339,6 +340,9 @@ test_chat_json_LDFLAGS = -Wl,--wrap=sqlite3_prepare_v2 -Wl,--wrap=sqlite3_bind_t
-Wl,--wrap=sqlite3_bind_int -Wl,--wrap=sqlite3_step -Wl,--wrap=sqlite3_finalize -Wl,--wrap=sqlite3_column_text \
-Wl,--wrap=u_realloc_impl -Wl,--wrap=u_calloc_impl
test_chat_profile_SOURCES = test_chat_profile.c
test_chat_preferences_SOURCES = test_chat_preferences.c
test_chat_preferences_LDADD = $(LIBUTUN) $(COMMON_LIBS)
test_chat_preferences_LDFLAGS = -Wl,--wrap=sqlite3_finalize
test_chat_profile_LDADD = $(LIBUTUN) $(COMMON_LIBS)
test_chat_profile_LDFLAGS = -Wl,--wrap=sqlite3_finalize -Wl,--wrap=sqlite3_prepare_v2 -Wl,--wrap=sqlite3_bind_text \
-Wl,--wrap=sqlite3_bind_blob -Wl,--wrap=sqlite3_bind_int64 -Wl,--wrap=sqlite3_bind_int -Wl,--wrap=sqlite3_bind_null \
+43
View File
@@ -0,0 +1,43 @@
/* UI-state:ошибка завершения SQL не должна фиксировать значение. */
#define _GNU_SOURCE
#include "../src/utun_instance.h"
#include "../src/chat/chat_core.h"
#include "../lib/debug_config.h"
#include "../lib/mem.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
static int fail_finalize;
extern int __real_sqlite3_finalize(sqlite3_stmt*);
int __wrap_sqlite3_finalize(sqlite3_stmt* st) {
const char* sql = st ? sqlite3_sql(st) : NULL;
int fail = fail_finalize && sql && !strncmp(sql, "INSERT OR REPLACE INTO ui_state", 30);
if (fail) fail_finalize = 0;
int rc = __real_sqlite3_finalize(st); return fail ? SQLITE_IOERR : rc;
}
static void value_is(sqlite3* db, const char* expected) {
sqlite3_stmt* st = NULL;
assert(sqlite3_prepare_v2(db, "SELECT value FROM ui_state WHERE key='preferences-test'", -1, &st, NULL) == SQLITE_OK);
assert(sqlite3_step(st) == SQLITE_ROW && !strcmp((const char*)sqlite3_column_text(st, 0), expected));
assert(sqlite3_finalize(st) == SQLITE_OK);
}
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);
char directory[] = "/tmp/utun-preferences-XXXXXX"; assert(mkdtemp(directory)); char config[512], database[512];
snprintf(config, sizeof(config), "[global]\nmy_node_name=preferences test\ndb_path=%s\n[ntp]\nenabled=no\n"
"[chatserver]\ngroup_autoconnect=0\nstorage_autoload=0\n", directory);
struct UTUN_INSTANCE* inst = utun_instance_create_from_str(ua, config);
assert(inst && !utun_core_start(inst) && !chat_service_start(inst));
snprintf(database, sizeof(database), "%s/chats.db", directory); sqlite3* reader = NULL;
assert(sqlite3_open_v2(database, &reader, SQLITE_OPEN_READONLY, NULL) == SQLITE_OK);
chat_core_save_ui_state(inst, "preferences-test", "old"); value_is(reader, "old");
fail_finalize = 1; chat_core_save_ui_state(inst, "preferences-test", "new"); assert(!fail_finalize);
value_is(reader, "old");
utun_instance_destroy(inst); assert(sqlite3_close(reader) == SQLITE_OK);
uasync_poll(ua, 0); uasync_destroy(ua, 0); assert(u_get_allocated_count() == baseline);
puts("PASS preferences:failed finalize preserves committed UI state"); return 0;
}