Test reentrant media events and cleanup after hash failure
This commit is contained in:
1 parent
d4efdba44e
commit
c08c24140c
2 files changed
+55
-1
No files matched your search
@@ -877,6 +877,9 @@ test_media_index_LDADD = $(LIBUTUN) $(CRYPTO_LIBS) $(COMMON_LIBS)
|
||||
check_PROGRAMS += test_media_index_regressions
|
||||
test_media_index_regressions_SOURCES = test_media_index_regressions.c
|
||||
test_media_index_regressions_LDADD = $(LIBUTUN) $(COMMON_LIBS)
|
||||
if OS_LINUX
|
||||
test_media_index_regressions_LDFLAGS = -Wl,--wrap=ma_sha256_file
|
||||
endif
|
||||
|
||||
test_media_delivery_sql_SOURCES = test_media_delivery_sql.c
|
||||
test_media_delivery_sql_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/media_delivery -I$(top_srcdir)/lib
|
||||
|
||||
@@ -18,6 +18,16 @@ static uint8_t key[32] = {1}, ids[32] = {1};
|
||||
static struct media_index_result result = { .media_id = {2}, .content_hash = {3},
|
||||
.file_size = 14, .block_size = 7, .num_blocks = 2, .block_ids = ids };
|
||||
|
||||
#ifdef __linux__
|
||||
int __real_ma_sha256_file(const char*, uint8_t[32]);
|
||||
int __wrap_ma_sha256_file(const char* path, uint8_t hash[32]) {
|
||||
if (strstr(path, "/hash-failure")) {
|
||||
memset(hash, 0, 32); DEBUG_ERROR(DEBUG_CATEGORY_DEBUG, "injected hash failure after file copy path=%s", path); return -1;
|
||||
}
|
||||
return __real_ma_sha256_file(path, hash);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void sql(sqlite3* db, const char* query) { assert(sqlite3_exec(db, query, NULL, NULL, NULL) == SQLITE_OK); }
|
||||
static int scalar(sqlite3* db, const char* query) {
|
||||
sqlite3_stmt* st = NULL; assert(sqlite3_prepare_v2(db, query, -1, &st, NULL) == SQLITE_OK);
|
||||
@@ -159,12 +169,17 @@ static void long_path(void) {
|
||||
}
|
||||
|
||||
static int deleted_events, failed_submissions, successful_submissions;
|
||||
static char delete_from_event[64];
|
||||
static void event(struct UTUN_INSTANCE* inst, int type, const uint8_t* data, int length) {
|
||||
(void)inst;
|
||||
if (type == CHAT_EVT_CHANNEL_DELETED) deleted_events++;
|
||||
if (type == CHAT_EVT_MSG_SUBMITTED) {
|
||||
assert(length == 9);
|
||||
if (data[8]) successful_submissions++; else failed_submissions++;
|
||||
if (delete_from_event[0]) {
|
||||
int before = deleted_events;
|
||||
assert(CC(inst)->media_submissions); chat_core_delete_channel(inst, delete_from_event);
|
||||
assert(deleted_events == before); delete_from_event[0] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,13 +216,49 @@ static void pending_deletion(void) {
|
||||
assert(ma_file_size(source) == 14 && ma_file_size(destinations[0]) == -1 && ma_file_size(destinations[1]) == -1);
|
||||
chat_core_ensure_channel_ready(inst, channel); uasync_poll(ua, 0);
|
||||
assert(!scalar(db, "SELECT count(*) FROM media_files"));
|
||||
|
||||
/* Обработчик MSG_SUBMITTED синхронный: удаление должно увидеть ещё живую задачу. */
|
||||
chat_core_create_channel_auto(inst, "reentrant");
|
||||
assert(!sqlite3_prepare_v2(db, "SELECT channel_id FROM channels WHERE name='reentrant'", -1, &st, NULL));
|
||||
assert(sqlite3_step(st) == SQLITE_ROW);
|
||||
snprintf(req.channel_id, sizeof(req.channel_id), "%s", sqlite3_column_text(st, 0)); sqlite3_finalize(st);
|
||||
snprintf(delete_from_event, sizeof(delete_from_event), "%s", req.channel_id);
|
||||
req.request_id = 4; chat_core_submit_media_message(inst, &req);
|
||||
for (int i = 0; i < 2000 && deleted_events < 2; i++) uasync_poll(ua, 100);
|
||||
assert(deleted_events == 2 && successful_submissions == 1 && failed_submissions == 3 && !CC(inst)->media_submissions);
|
||||
assert(!scalar(db, "SELECT count(*) FROM channels WHERE name='reentrant'"));
|
||||
assert(ma_file_size(destinations[1]) == -1 && ma_file_size(source) == 14);
|
||||
utun_instance_destroy(inst); uasync_destroy(ua, 0);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "media regression pending deletion/two completions/recreation PASS");
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
static void preparation_failed(void* arg, int error, const struct media_index_result* value) {
|
||||
int* completed = arg; assert(error && !value); (*completed)++;
|
||||
}
|
||||
static void failed_preparation(void) {
|
||||
char source[MEDIA_PATH_MAX], destination[MEDIA_PATH_MAX];
|
||||
assert(!media_index_path(root, "copy-source", source) && !media_index_path(root, "hash-failure", destination));
|
||||
write_file(source); sqlite3* db = database();
|
||||
struct UASYNC* ua = uasync_create(); assert(ua);
|
||||
struct media_async* ma = media_async_create(); assert(ma); int completed = 0;
|
||||
media_index_register_async(ma, ua, db, 1, key, "failed", source, destination, 1, root, preparation_failed, &completed);
|
||||
for (int i = 0; i < 2000 && !completed; i++) uasync_poll(ua, 100);
|
||||
assert(completed == 1 && ma_file_size(destination) == 14 && !scalar(db, "SELECT count(*) FROM media_files"));
|
||||
assert(scalar(db, "SELECT count(*) FROM media_preparations") == 1);
|
||||
assert(!media_index_delete_channel(db, "failed", root));
|
||||
assert(ma_file_size(destination) == -1 && ma_file_size(source) == 14);
|
||||
media_async_destroy(ma); uasync_destroy(ua, 0); sqlite3_close(db);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "media regression failed preparation cleanup PASS");
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(void) {
|
||||
debug_config_init(); debug_set_level(DEBUG_LEVEL_WARN); debug_set_category_level(DEBUG_CATEGORY_DEBUG, DEBUG_LEVEL_INFO);
|
||||
assert(!test_mkdtemp(root)); ids[16] = 2;
|
||||
paths(); transactions(); deletion(); long_path(); pending_deletion();
|
||||
#ifdef __linux__
|
||||
failed_preparation();
|
||||
#endif
|
||||
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "test_media_index_regressions PASS"); return 0;
|
||||
}
|
||||
Reference in new issue
Block a user