diff --git a/tests/Makefile.am b/tests/Makefile.am index 36a9da1c..68bd4016 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -343,7 +343,8 @@ 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 \ -Wl,--wrap=sqlite3_step -Wl,--wrap=sqlite3_column_text -Wl,--wrap=sqlite3_exec -Wl,--wrap=sc_ed25519_sign \ - -Wl,--wrap=sc_ed25519_verify -Wl,--wrap=u_malloc_impl -Wl,--wrap=member_sync_add_apply_cbk -Wl,--wrap=sqlite3_changes + -Wl,--wrap=sc_ed25519_verify -Wl,--wrap=u_malloc_impl -Wl,--wrap=member_sync_add_apply_cbk -Wl,--wrap=sqlite3_changes \ + -Wl,--wrap=u_calloc_impl -Wl,--wrap=u_realloc_impl -Wl,--wrap=u_strdup_impl else test_socket_monitor_LDFLAGS += -Wl,--wrap=read endif diff --git a/tests/test_chat_profile.c b/tests/test_chat_profile.c index bb34d931..f2d02fea 100644 --- a/tests/test_chat_profile.c +++ b/tests/test_chat_profile.c @@ -23,6 +23,8 @@ static enum fault fault; static const char* target; static int index_number, last_target, fail_rollback, fail_member_rollback, member_rollback_failed, releases_after_failure; static int fail_sign, fail_verify, fail_member_malloc, fail_apply_registration, delete_on_event; +static unsigned tag_alloc_fail, tag_alloc_seen; +static int tag_alloc_record; static unsigned events, sequence; static sqlite3* reader; static char channel[32]; @@ -107,6 +109,27 @@ void* __wrap_u_malloc_impl(uint32_t bytes, const char* location) { if (fail_member_malloc && strstr(location, "member_sync.c")) { fail_member_malloc = 0; return NULL; } return __real_u_malloc_impl(bytes, location); } + +static int tag_allocation(const char* location, const char* module) { + if (!strstr(location, module)) return 0; + if (tag_alloc_record) tag_alloc_seen++; + if (tag_alloc_fail && !--tag_alloc_fail) { + DEBUG_WARN(DEBUG_CATEGORY_CHAT, "tags test: allocation refused at %s", location); return 1; + } + return 0; +} +extern void* __real_u_calloc_impl(uint32_t, uint32_t, const char*); +void* __wrap_u_calloc_impl(uint32_t count, uint32_t bytes, const char* location) { + return tag_allocation(location, "chat_core.c") ? NULL : __real_u_calloc_impl(count, bytes, location); +} +extern void* __real_u_realloc_impl(void*, uint32_t, const char*); +void* __wrap_u_realloc_impl(void* ptr, uint32_t bytes, const char* location) { + return tag_allocation(location, "strbuf.c") ? NULL : __real_u_realloc_impl(ptr, bytes, location); +} +extern char* __real_u_strdup_impl(const char*, const char*); +char* __wrap_u_strdup_impl(const char* text, const char* location) { + return tag_allocation(location, "chat_core.c") ? NULL : __real_u_strdup_impl(text, location); +} extern int __real_member_sync_add_apply_cbk(struct UTUN_INSTANCE*, member_apply_cbk_fn, void*); int __wrap_member_sync_add_apply_cbk(struct UTUN_INSTANCE* inst, member_apply_cbk_fn callback, void* arg) { if (fail_apply_registration) { fail_apply_registration = 0; fail_member_malloc = 1; } @@ -421,6 +444,20 @@ static void tags_patch(struct UTUN_INSTANCE* inst, const char* json) { assert(strlen(json) < sizeof(req->json)); strcpy(req->json, json); chat_member_tags_commit_trampoline(req); } +static void tags_allocation_faults(struct UTUN_INSTANCE* inst) { + struct chat_member_tags* edit = chat_member_tags_load(inst, channel, inst->node_id); assert(edit); + assert(!chat_member_tags_set(edit, "owner_test", "memory-00000000")); + tag_alloc_seen = 0; tag_alloc_record = 1; assert(!chat_member_tags_commit(inst, edit)); tag_alloc_record = 0; + unsigned cases = tag_alloc_seen; assert(cases >= 8); chat_member_tags_free(edit); + for (unsigned i = 1; i <= cases; i++) { + edit = chat_member_tags_load(inst, channel, inst->node_id); assert(edit); + char value[32]; snprintf(value, sizeof(value), "memory-%08u", i); assert(!chat_member_tags_set(edit, "owner_test", value)); + tag_alloc_fail = i; tags_refused(inst, edit); assert(!tag_alloc_fail && !strcmp(chat_member_tags_get(edit, "owner_test"), value)); + assert(!chat_member_tags_commit(inst, edit)); chat_member_tags_free(edit); + } + printf("PASS tags memory:%u allocation faults/retries through snapshot,JSON growth,and prepared editor\n", cases); +} + static void tags_semantics(struct UTUN_INSTANCE* inst) { struct chat_member_tags* first = chat_member_tags_load(inst, channel, inst->node_id); struct chat_member_tags* stale = chat_member_tags_load(inst, channel, inst->node_id); assert(first && stale); @@ -527,7 +564,8 @@ int main(void) { assert(rc < 0 && !fail_read && timestamp == 123 && !memcmp(profile, previous, sizeof(profile)) && !memcmp(signature, old_signature, 64)); assert(!chat_core_get_my_profile(inst, channel, profile, sizeof(profile), signature, ×tamp) && timestamp > 0); chat_event_set_handler(inst, event); reader_faults(inst); writer_faults(inst); damaged_profile(inst); semantic_profile(inst); - owner_faults(inst); avatar(inst); tags_reader_failure(inst); tags_faults(inst); tags_semantics(inst); tags_long_history(inst); tags_callback_deletion(inst); + owner_faults(inst); avatar(inst); tags_reader_failure(inst); tags_faults(inst); tags_allocation_faults(inst); + tags_semantics(inst); tags_long_history(inst); tags_callback_deletion(inst); registration_failure(inst, ua); callback_deletion(inst); uint8_t before[32], after[32]; snapshot(reader, before); unsigned count = events; target = "COMMIT /* profile */"; fault = F_EXEC; fail_rollback = 1; inst->running = 1;