diff options
Diffstat (limited to '')
-rw-r--r-- | src/lib-index/test-mail-index.c | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/src/lib-index/test-mail-index.c b/src/lib-index/test-mail-index.c new file mode 100644 index 0000000..3e2fd02 --- /dev/null +++ b/src/lib-index/test-mail-index.c @@ -0,0 +1,169 @@ +/* Copyright (c) 2019 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "array.h" +#include "test-common.h" +#include "test-mail-index.h" +#include "mail-transaction-log-private.h" + +static void test_mail_index_rotate(void) +{ + struct mail_index *index, *index2; + struct mail_index_view *view; + struct mail_index_transaction *trans; + struct mail_transaction_log_file *file; + const char *reason; + + test_begin("mail index rotate"); + index = test_mail_index_init(); + index2 = test_mail_index_open(); + view = mail_index_view_open(index); + + /* First rotation of the index. The view will point to the old index. */ + trans = mail_index_transaction_begin(view, 0); + mail_index_reset(trans); + test_assert(mail_index_transaction_commit(&trans) == 0); + + /* Second rotation of the index. The log head doesn't have any extra + references. */ + trans = mail_index_transaction_begin(view, 0); + mail_index_reset(trans); + test_assert(mail_index_transaction_commit(&trans) == 0); + + /* The 2nd index's log head also doesn't have any extra references. + Check that it doesn't crash. */ + test_assert(mail_transaction_log_find_file(index2->log, 3, FALSE, &file, &reason) == 0); + + mail_index_view_close(&view); + test_mail_index_deinit(&index); + test_mail_index_deinit(&index2); + test_end(); +} + +static void +test_mail_index_new_extension_rotate_write(struct mail_index *index2, + uint32_t uid) +{ + struct mail_index_view *view2; + struct mail_index_transaction *trans; + uint32_t hdr_ext_id, rec_ext_id, file_seq, seq, rec_ext = 0x12345678; + uoff_t file_offset; + + /* Rotate the index in the index */ + test_assert(mail_transaction_log_sync_lock(index2->log, "test", + &file_seq, &file_offset) == 0); + mail_index_write(index2, TRUE, "test"); + mail_transaction_log_sync_unlock(index2->log, "test"); + + /* Write a new extension header to the 2nd index. */ + hdr_ext_id = mail_index_ext_register(index2, "test", + sizeof(hdr_ext_id), 0, 0); + rec_ext_id = mail_index_ext_register(index2, "test-rec", 0, + sizeof(uint32_t), sizeof(uint32_t)); + view2 = mail_index_view_open(index2); + trans = mail_index_transaction_begin(view2, + MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL); + mail_index_update_header_ext(trans, hdr_ext_id, 0, + &hdr_ext_id, sizeof(hdr_ext_id)); + mail_index_append(trans, uid, &seq); + mail_index_update_ext(trans, seq, rec_ext_id, &rec_ext, NULL); + test_assert(mail_index_transaction_commit(&trans) == 0); + mail_index_view_close(&view2); +} + +static void test_mail_index_new_extension_sync(struct mail_index_view *view) +{ + struct mail_index_view_sync_ctx *sync_ctx; + struct mail_index_view_sync_rec sync_rec; + bool delayed_expunges; + + test_assert(mail_index_refresh(view->index) == 0); + sync_ctx = mail_index_view_sync_begin(view, + MAIL_INDEX_VIEW_SYNC_FLAG_NOEXPUNGES); + test_assert(!mail_index_view_sync_next(sync_ctx, &sync_rec)); + test_assert(mail_index_view_sync_commit(&sync_ctx, &delayed_expunges) == 0); +} + +static void test_mail_index_new_extension(void) +{ + struct mail_index *index, *index2; + struct mail_index_view *view, *view2; + struct mail_index_transaction *trans; + uint32_t seq, rec_ext_id, rec_ext = 0x12345678; + + test_begin("mail index new extension"); + index = test_mail_index_init(); + index2 = test_mail_index_open(); + view = mail_index_view_open(index); + + rec_ext_id = mail_index_ext_register(index, "test-rec", 0, + sizeof(uint32_t), sizeof(uint32_t)); + + /* Save two mails */ + uint32_t uid_validity = 123456; + trans = mail_index_transaction_begin(view, + MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL); + mail_index_update_header(trans, + offsetof(struct mail_index_header, uid_validity), + &uid_validity, sizeof(uid_validity), TRUE); + mail_index_append(trans, 1, &seq); + mail_index_update_ext(trans, seq, rec_ext_id, &rec_ext, NULL); + mail_index_append(trans, 2, &seq); + mail_index_update_ext(trans, seq, rec_ext_id, &rec_ext, NULL); + test_assert(mail_index_transaction_commit(&trans) == 0); + + /* refresh indexes and view */ + test_assert(mail_index_refresh(index2) == 0); + mail_index_view_close(&view); + view = mail_index_view_open(index); + + /* Expunge the mail in the 2nd index */ + view2 = mail_index_view_open(index2); + trans = mail_index_transaction_begin(view2, + MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL); + mail_index_expunge(trans, 1); + test_assert(mail_index_transaction_commit(&trans) == 0); + mail_index_view_close(&view2); + + /* Sync the first view without expunges */ + test_mail_index_new_extension_sync(view); + + for (unsigned int i = 0; i < 3; i++) + test_mail_index_new_extension_rotate_write(index2, 3 + i); + + /* Sync the first view. It needs to generate the missing view. */ + test_expect_error_string("generating missing logs"); + test_mail_index_new_extension_sync(view); + test_expect_no_more_errors(); + test_assert(mail_index_get_header(view)->messages_count == 5); + + /* Make sure the extensions records are still there. + Note that this works, because the extensions are looked up from the + newly refreshed index, not the old index. */ + for (seq = 1; seq <= 5; seq++) { + const void *data; + bool expunged; + mail_index_lookup_ext(view, seq, rec_ext_id, &data, &expunged); + test_assert_idx(memcmp(data, &rec_ext, sizeof(rec_ext)) == 0, seq); + } + + /* Once more rotate and write using the new extension */ + test_mail_index_new_extension_rotate_write(index2, 6); + /* Make sure the first view understands the new extension by ID */ + test_mail_index_new_extension_sync(view); + + mail_index_view_close(&view); + test_mail_index_deinit(&index); + test_mail_index_deinit(&index2); + test_end(); +} + +int main(void) +{ + static void (*const test_functions[])(void) = { + test_mail_index_rotate, + test_mail_index_new_extension, + NULL + }; + return test_run(test_functions); +} |