diff --git a/tests/Makefile.am b/tests/Makefile.am index 68bd4016..a9209572 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -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 \ diff --git a/tests/test_chat_preferences.c b/tests/test_chat_preferences.c new file mode 100644 index 00000000..70414636 --- /dev/null +++ b/tests/test_chat_preferences.c @@ -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 +#include +#include + +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; +}