From 6bf6d99b9cdc3ae1d6bacf03d424adf00686dbf1 Mon Sep 17 00:00:00 2001 From: evgeny Date: Sat, 24 Oct 2026 14:50:32 +0200 Subject: [PATCH] Test service cancellation after encrypted attachment rename --- tests/Makefile.am | 3 +++ tests/test_attachment_send.c | 37 ++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/tests/Makefile.am b/tests/Makefile.am index 902c1ad9..1a2aef68 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -403,6 +403,9 @@ test_encrypted_attachment_LDFLAGS += -Wl,--wrap=uasync_set_timeout -Wl,--wrap=me endif test_attachment_send_SOURCES = test_attachment_send.c test_attachment_send_LDADD = $(LIBUTUN) $(CRYPTO_LIBS) $(COMMON_LIBS) +if OS_LINUX +test_attachment_send_LDFLAGS = -Wl,--wrap=media_async_submit +endif test_dm_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/transport_layer -I$(top_srcdir)/lib test_dm_LDADD = $(LIBUTUN) $(CRYPTO_LIBS) $(COMMON_LIBS) diff --git a/tests/test_attachment_send.c b/tests/test_attachment_send.c index c764e32c..2c48baa5 100644 --- a/tests/test_attachment_send.c +++ b/tests/test_attachment_send.c @@ -11,6 +11,7 @@ #include "../src/dm/dm_core.h" #include "../src/dm/dm_crypto.h" #include "../src/media_async/attachment_send.h" +#include "../src/media_async/media_async.h" #include "test_utils.h" #define REQUIRE(value) do { if (!(value)) { DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "attachment send check line=%d", __LINE__); return 1; } } while (0) @@ -22,6 +23,27 @@ struct test_state { }; static struct test_state test; +#ifdef __linux__ +static pthread_barrier_t prepared_barrier; +static int capture_work; +static ma_work_fn captured_work; +void __real_media_async_submit(struct media_async*, struct UASYNC*, ma_work_fn, void*, ma_done_fn, void*); +static void prepared_work(void* arg) { + captured_work(arg); + pthread_barrier_wait(&prepared_barrier); +} +/* Завершить настоящий crypto worker, сохранив completion до остановки сервиса. */ +void __wrap_media_async_submit(struct media_async* ma, struct UASYNC* ua, ma_work_fn work, void* data, ma_done_fn done, void* arg) { + if (capture_work) { capture_work = 0; captured_work = work; work = prepared_work; } + __real_media_async_submit(ma, ua, work, data, done, arg); +} +#endif + +static void count_temps(void* arg, const char* path, int64_t size) { + (void)size; + if (strstr(path, ".tmp.")) (*(unsigned*)arg)++; +} + static void release_pcm(void* owner) { struct test_state* state = owner; state->released++; state->release_in_worker = !pthread_equal(pthread_self(), state->event_thread); @@ -89,7 +111,20 @@ int main(void) { char prepared[1024]; snprintf(prepared, sizeof(prepared), "%s/cancel-encrypted.bin", dir); FILE* prepared_file = fopen(prepared, "wb"); REQUIRE(prepared_file && fputc(42, prepared_file) != EOF && !fclose(prepared_file)); struct attachment_info encrypted_info = { .kind = ATTACHMENT_FILE, .name = "cancel.bin" }; uint8_t no_reply[32] = {0}; +#ifdef __linux__ + REQUIRE(!pthread_barrier_init(&prepared_barrier, NULL, 2)); capture_work = 1; +#endif REQUIRE(!chat_attachment_send(inst, channel_id, prepared, &encrypted_info, "application/octet-stream", no_reply, 0)); + sqlite3_stmt* paths = NULL; + REQUIRE(!sqlite3_prepare_v2(inst->topo_sqlite_db, "SELECT cipher_path,plain_path FROM attachment_keys", -1, &paths, NULL)); + REQUIRE(sqlite3_step(paths) == SQLITE_ROW); + char cancelled_cipher[1024], cancelled_plain[1024]; + snprintf(cancelled_cipher, sizeof(cancelled_cipher), "%s", sqlite3_column_text(paths, 0)); + snprintf(cancelled_plain, sizeof(cancelled_plain), "%s", sqlite3_column_text(paths, 1)); sqlite3_finalize(paths); +#ifdef __linux__ + pthread_barrier_wait(&prepared_barrier); REQUIRE(!pthread_barrier_destroy(&prepared_barrier)); + REQUIRE(ma_file_size(cancelled_cipher) > 0 && ma_file_size(cancelled_plain) == 1); +#endif req = u_calloc(1, sizeof(*req)); REQUIRE(req); req->inst = inst; req->is_dm = 1; req->info.kind = ATTACHMENT_VOICE; req->preset = 1; snprintf(req->target, sizeof(req->target), "%s", conv); @@ -100,6 +135,8 @@ int main(void) { sqlite3_stmt* cancelled_key = NULL; REQUIRE(!sqlite3_prepare_v2(inst->topo_sqlite_db, "SELECT count(*) FROM attachment_keys", -1, &cancelled_key, NULL)); REQUIRE(sqlite3_step(cancelled_key) == SQLITE_ROW && sqlite3_column_int(cancelled_key, 0) == 0); sqlite3_finalize(cancelled_key); + REQUIRE(ma_file_size(cancelled_cipher) < 0 && ma_file_size(cancelled_plain) < 0 && ma_file_size(prepared) < 0); + unsigned temps = 0; REQUIRE(!ma_dir_walk(dir, count_temps, &temps) && !temps); uasync_poll(ua, 0); REQUIRE(test.failed == 1); /* Отклонение после stop удаляет только переданный собственный cache. */