]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-index: Add unit test to mail_transaction_update_modseq()
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Tue, 8 Aug 2017 11:01:18 +0000 (14:01 +0300)
committerTimo Sirainen <tss@dovecot.fi>
Fri, 11 Aug 2017 11:17:32 +0000 (14:17 +0300)
src/lib-index/Makefile.am
src/lib-index/test-mail-transaction-log-file.c [new file with mode: 0644]

index 66509e3eb3fd2ce11ecdf0bb5e2e3f1436ff4237..ecaac792af0a1561aa22a3fd3d83141b4699cd35 100644 (file)
@@ -67,6 +67,7 @@ test_programs = \
        test-mail-index-transaction-finish \
        test-mail-index-transaction-update \
        test-mail-transaction-log-append \
+       test-mail-transaction-log-file \
        test-mail-transaction-log-view
 
 noinst_PROGRAMS = $(test_programs)
@@ -102,6 +103,10 @@ test_mail_transaction_log_append_SOURCES = test-mail-transaction-log-append.c
 test_mail_transaction_log_append_LDADD = mail-transaction-log-append.lo $(test_libs)
 test_mail_transaction_log_append_DEPENDENCIES = $(test_deps)
 
+test_mail_transaction_log_file_SOURCES = test-mail-transaction-log-file.c
+test_mail_transaction_log_file_LDADD = $(noinst_LTLIBRARIES) $(test_libs)
+test_mail_transaction_log_file_DEPENDENCIES = $(test_deps)
+
 test_mail_transaction_log_view_SOURCES = test-mail-transaction-log-view.c
 test_mail_transaction_log_view_LDADD = mail-transaction-log-view.lo $(test_libs)
 test_mail_transaction_log_view_DEPENDENCIES = $(test_deps)
diff --git a/src/lib-index/test-mail-transaction-log-file.c b/src/lib-index/test-mail-transaction-log-file.c
new file mode 100644 (file)
index 0000000..8ed1420
--- /dev/null
@@ -0,0 +1,250 @@
+/* Copyright (c) 2009-2017 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "test-common.h"
+#include "mail-index-private.h"
+#include "mail-transaction-log-private.h"
+
+#define TEST_LOG_VERSION MAIL_TRANSACTION_LOG_VERSION_FULL(1, 3)
+
+#define INITIAL_MODSEQ 100
+
+struct update_modseq_test {
+       enum mail_transaction_type type;
+       unsigned int version;
+#define NOUPDATE (INITIAL_MODSEQ)
+#define UPDATE (INITIAL_MODSEQ+1)
+       uint64_t expected_modseq;
+       unsigned int count;
+       union {
+               const struct mail_transaction_flag_update *flag_update;
+               const struct mail_transaction_modseq_update *modseq_update;
+       } v;
+} update_modseq_tests[] = {
+       /* expunges: increase modseq */
+       { MAIL_TRANSACTION_EXPUNGE | MAIL_TRANSACTION_EXPUNGE_PROT | MAIL_TRANSACTION_EXTERNAL, TEST_LOG_VERSION, UPDATE, 1, { } },
+       { MAIL_TRANSACTION_EXPUNGE_GUID | MAIL_TRANSACTION_EXPUNGE_PROT | MAIL_TRANSACTION_EXTERNAL, TEST_LOG_VERSION, UPDATE, 1, { } },
+       /* expunges: don't increase modseq */
+       { MAIL_TRANSACTION_EXPUNGE | MAIL_TRANSACTION_EXPUNGE_PROT, TEST_LOG_VERSION, NOUPDATE, 1, { } },
+       { MAIL_TRANSACTION_EXPUNGE_GUID | MAIL_TRANSACTION_EXPUNGE_PROT, TEST_LOG_VERSION, NOUPDATE, 1, { } },
+       { MAIL_TRANSACTION_EXPUNGE | MAIL_TRANSACTION_EXTERNAL, TEST_LOG_VERSION, NOUPDATE, 1, { } },
+       { MAIL_TRANSACTION_EXPUNGE_GUID | MAIL_TRANSACTION_EXTERNAL, TEST_LOG_VERSION, NOUPDATE, 1, { } },
+
+       /* flag changes: don't increase modseq */
+       { MAIL_TRANSACTION_FLAG_UPDATE, TEST_LOG_VERSION, NOUPDATE, 1, {
+               .flag_update = (const struct mail_transaction_flag_update[]) {
+                       { .uid1 = 1, .uid2 = 2, .add_flags = 0 }
+               }
+       } },
+       { MAIL_TRANSACTION_FLAG_UPDATE, TEST_LOG_VERSION, NOUPDATE, 1, {
+               .flag_update = (const struct mail_transaction_flag_update[]) {
+                       { .uid1 = 1, .uid2 = 2, .add_flags = MAIL_INDEX_MAIL_FLAG_BACKEND }
+               }
+       } },
+       { MAIL_TRANSACTION_FLAG_UPDATE, TEST_LOG_VERSION, NOUPDATE, 1, {
+               .flag_update = (const struct mail_transaction_flag_update[]) {
+                       { .uid1 = 1, .uid2 = 2, .remove_flags = MAIL_INDEX_MAIL_FLAG_BACKEND }
+               }
+       } },
+       { MAIL_TRANSACTION_FLAG_UPDATE, TEST_LOG_VERSION, NOUPDATE, 1, {
+               .flag_update = (const struct mail_transaction_flag_update[]) {
+                       { .uid1 = 1, .uid2 = 2, .add_flags = MAIL_INDEX_MAIL_FLAG_DIRTY }
+               }
+       } },
+       { MAIL_TRANSACTION_FLAG_UPDATE, TEST_LOG_VERSION, NOUPDATE, 1, {
+               .flag_update = (const struct mail_transaction_flag_update[]) {
+                       { .uid1 = 1, .uid2 = 2, .remove_flags = MAIL_INDEX_MAIL_FLAG_DIRTY }
+               }
+       } },
+       /* flag changes: increase modseq */
+       { MAIL_TRANSACTION_FLAG_UPDATE, TEST_LOG_VERSION, UPDATE, 1, {
+               .flag_update = (const struct mail_transaction_flag_update[]) {
+                       { .uid1 = 1, .uid2 = 2, .add_flags = MAIL_SEEN }
+               }
+       } },
+       { MAIL_TRANSACTION_FLAG_UPDATE, TEST_LOG_VERSION, UPDATE, 1, {
+               .flag_update = (const struct mail_transaction_flag_update[]) {
+                       { .uid1 = 1, .uid2 = 2, .remove_flags = MAIL_SEEN }
+               }
+       } },
+       { MAIL_TRANSACTION_FLAG_UPDATE, TEST_LOG_VERSION, UPDATE, 1, {
+               .flag_update = (const struct mail_transaction_flag_update[]) {
+                       { .uid1 = 1, .uid2 = 2, .add_flags = MAIL_SEEN | MAIL_INDEX_MAIL_FLAG_BACKEND }
+               }
+       } },
+       { MAIL_TRANSACTION_FLAG_UPDATE, TEST_LOG_VERSION, UPDATE, 1, {
+               .flag_update = (const struct mail_transaction_flag_update[]) {
+                       { .uid1 = 1, .uid2 = 2, .add_flags = MAIL_SEEN | MAIL_INDEX_MAIL_FLAG_DIRTY }
+               }
+       } },
+       { MAIL_TRANSACTION_FLAG_UPDATE, TEST_LOG_VERSION, UPDATE, 1, {
+               .flag_update = (const struct mail_transaction_flag_update[]) {
+                       { .uid1 = 1, .uid2 = 2, .remove_flags = MAIL_SEEN | MAIL_INDEX_MAIL_FLAG_BACKEND }
+               }
+       } },
+       { MAIL_TRANSACTION_FLAG_UPDATE, TEST_LOG_VERSION, UPDATE, 1, {
+               .flag_update = (const struct mail_transaction_flag_update[]) {
+                       { .uid1 = 1, .uid2 = 2, .remove_flags = MAIL_SEEN | MAIL_INDEX_MAIL_FLAG_DIRTY }
+               }
+       } },
+       { MAIL_TRANSACTION_FLAG_UPDATE, TEST_LOG_VERSION, UPDATE, 2, {
+               .flag_update = (const struct mail_transaction_flag_update[]) {
+                       { .uid1 = 1, .uid2 = 2, .add_flags = MAIL_INDEX_MAIL_FLAG_DIRTY },
+                       { .uid1 = 3, .uid2 = 4, .add_flags = MAIL_SEEN }
+               }
+       } },
+       { MAIL_TRANSACTION_FLAG_UPDATE, TEST_LOG_VERSION, UPDATE, 1, {
+               .flag_update = (const struct mail_transaction_flag_update[]) {
+                       { .uid1 = 1, .uid2 = 2, .add_flags = 0, .modseq_inc_flag = 1 }
+               }
+       } },
+       { MAIL_TRANSACTION_FLAG_UPDATE, TEST_LOG_VERSION, UPDATE, 2, {
+               .flag_update = (const struct mail_transaction_flag_update[]) {
+                       { .uid1 = 1, .uid2 = 2, .add_flags = MAIL_INDEX_MAIL_FLAG_DIRTY },
+                       { .uid1 = 1, .uid2 = 2, .add_flags = MAIL_INDEX_MAIL_FLAG_DIRTY, .modseq_inc_flag = 1 }
+               }
+       } },
+       /* flag changes: increase modseq with old version */
+       { MAIL_TRANSACTION_FLAG_UPDATE, MAIL_TRANSACTION_LOG_VERSION_FULL(1, 2), UPDATE, 1, {
+               .flag_update = (const struct mail_transaction_flag_update[]) {
+                       { .uid1 = 1, .uid2 = 2, .add_flags = MAIL_INDEX_MAIL_FLAG_BACKEND }
+               }
+       } },
+       { MAIL_TRANSACTION_FLAG_UPDATE, MAIL_TRANSACTION_LOG_VERSION_FULL(1, 2), UPDATE, 1, {
+               .flag_update = (const struct mail_transaction_flag_update[]) {
+                       { .uid1 = 1, .uid2 = 2, .add_flags = MAIL_INDEX_MAIL_FLAG_DIRTY }
+               }
+       } },
+       /* modseq updates: don't increase modseq */
+       { MAIL_TRANSACTION_MODSEQ_UPDATE, TEST_LOG_VERSION, NOUPDATE, 1, {
+               .modseq_update = (const struct mail_transaction_modseq_update[]) {
+                       { .uid = 1, .modseq_low32 = 50, .modseq_high32 = 0 }
+               }
+       } },
+       { MAIL_TRANSACTION_MODSEQ_UPDATE, TEST_LOG_VERSION, NOUPDATE, 1, {
+               .modseq_update = (const struct mail_transaction_modseq_update[]) {
+                       { .uid = 1, .modseq_low32 = 100, .modseq_high32 = 0 }
+               }
+       } },
+       /* modseq updates: increase modseq */
+       { MAIL_TRANSACTION_MODSEQ_UPDATE, TEST_LOG_VERSION, 500, 1, {
+               .modseq_update = (const struct mail_transaction_modseq_update[]) {
+                       { .uid = 1, .modseq_low32 = 500, .modseq_high32 = 0 }
+               }
+       } },
+       { MAIL_TRANSACTION_MODSEQ_UPDATE, TEST_LOG_VERSION, 500, 2, {
+               .modseq_update = (const struct mail_transaction_modseq_update[]) {
+                       { .uid = 1, .modseq_low32 = 50, .modseq_high32 = 0 },
+                       { .uid = 1, .modseq_low32 = 500, .modseq_high32 = 0 }
+               }
+       } },
+       { MAIL_TRANSACTION_MODSEQ_UPDATE, TEST_LOG_VERSION, 500, 1, {
+               .modseq_update = (const struct mail_transaction_modseq_update[]) {
+                       { .uid = 1, .modseq_low32 = 500, .modseq_high32 = 0 },
+                       { .uid = 1, .modseq_low32 = 200, .modseq_high32 = 0 }
+               }
+       } },
+       { MAIL_TRANSACTION_MODSEQ_UPDATE, TEST_LOG_VERSION, (uint64_t)4294967346, 1, {
+               .modseq_update = (const struct mail_transaction_modseq_update[]) {
+                       { .uid = 1, .modseq_low32 = 50, .modseq_high32 = 1 }
+               }
+       } },
+
+       /* appends, keyword changes, attribute changes: increase modseq */
+       { MAIL_TRANSACTION_APPEND, TEST_LOG_VERSION, UPDATE, 1, { } },
+       { MAIL_TRANSACTION_KEYWORD_UPDATE, TEST_LOG_VERSION, UPDATE, 1, { } },
+       { MAIL_TRANSACTION_KEYWORD_RESET, TEST_LOG_VERSION, UPDATE, 1, { } },
+       { MAIL_TRANSACTION_ATTRIBUTE_UPDATE, TEST_LOG_VERSION, UPDATE, 1, { } },
+
+       /* others: don't increase modseq */
+       { MAIL_TRANSACTION_HEADER_UPDATE, TEST_LOG_VERSION, NOUPDATE, 1, { } },
+       { MAIL_TRANSACTION_HEADER_UPDATE, TEST_LOG_VERSION, NOUPDATE, 1, { } },
+       { MAIL_TRANSACTION_EXT_INTRO, TEST_LOG_VERSION, NOUPDATE, 1, { } },
+       { MAIL_TRANSACTION_EXT_RESET, TEST_LOG_VERSION, NOUPDATE, 1, { } },
+       { MAIL_TRANSACTION_EXT_HDR_UPDATE, TEST_LOG_VERSION, NOUPDATE, 1, { } },
+       { MAIL_TRANSACTION_EXT_REC_UPDATE, TEST_LOG_VERSION, NOUPDATE, 1, { } },
+       { MAIL_TRANSACTION_EXT_ATOMIC_INC, TEST_LOG_VERSION, NOUPDATE, 1, { } },
+       { MAIL_TRANSACTION_EXT_HDR_UPDATE32, TEST_LOG_VERSION, NOUPDATE, 1, { } },
+       { MAIL_TRANSACTION_INDEX_DELETED, TEST_LOG_VERSION, NOUPDATE, 1, { } },
+       { MAIL_TRANSACTION_INDEX_UNDELETED, TEST_LOG_VERSION, NOUPDATE, 1, { } },
+};
+
+static size_t update_modseq_test_get_size(const struct update_modseq_test *test)
+{
+       enum mail_transaction_type type =
+               test->type & MAIL_TRANSACTION_TYPE_MASK;
+
+       if (type == (MAIL_TRANSACTION_EXPUNGE | MAIL_TRANSACTION_EXPUNGE_PROT))
+               type = MAIL_TRANSACTION_EXPUNGE;
+       if (type == (MAIL_TRANSACTION_EXPUNGE_GUID | MAIL_TRANSACTION_EXPUNGE_PROT))
+               type = MAIL_TRANSACTION_EXPUNGE_GUID;
+
+       switch (type) {
+       case MAIL_TRANSACTION_EXPUNGE:
+               return sizeof(struct mail_transaction_expunge);
+       case MAIL_TRANSACTION_EXPUNGE_GUID:
+               return sizeof(struct mail_transaction_expunge_guid);
+       case MAIL_TRANSACTION_APPEND:
+               return sizeof(struct mail_index_record);
+       case MAIL_TRANSACTION_KEYWORD_UPDATE:
+               return sizeof(struct mail_transaction_keyword_update);
+       case MAIL_TRANSACTION_KEYWORD_RESET:
+               return sizeof(struct mail_transaction_keyword_reset);
+       case MAIL_TRANSACTION_ATTRIBUTE_UPDATE:
+               return 4;
+       case MAIL_TRANSACTION_FLAG_UPDATE:
+               return sizeof(struct mail_transaction_flag_update);
+       case MAIL_TRANSACTION_MODSEQ_UPDATE:
+               return sizeof(struct mail_transaction_modseq_update);
+       case MAIL_TRANSACTION_HEADER_UPDATE:
+       case MAIL_TRANSACTION_EXT_INTRO:
+       case MAIL_TRANSACTION_EXT_RESET:
+       case MAIL_TRANSACTION_EXT_HDR_UPDATE:
+       case MAIL_TRANSACTION_EXT_REC_UPDATE:
+       case MAIL_TRANSACTION_EXT_ATOMIC_INC:
+       case MAIL_TRANSACTION_EXT_HDR_UPDATE32:
+       case MAIL_TRANSACTION_INDEX_DELETED:
+       case MAIL_TRANSACTION_INDEX_UNDELETED:
+               return 4;
+       case MAIL_TRANSACTION_TYPE_MASK:
+       case MAIL_TRANSACTION_BOUNDARY:
+       case MAIL_TRANSACTION_EXPUNGE_PROT:
+       case MAIL_TRANSACTION_EXTERNAL:
+       case MAIL_TRANSACTION_SYNC:
+               break;
+       }
+       i_unreached();
+}
+
+static void test_mail_transaction_update_modseq(void)
+{
+       struct mail_transaction_header hdr;
+       unsigned char tempbuf[1024] = { 0 };
+
+       test_begin("mail_transaction_update_modseq()");
+       for (unsigned int i = 0; i < N_ELEMENTS(update_modseq_tests); i++) {
+               const struct update_modseq_test *test = &update_modseq_tests[i];
+               const void *data = test->v.flag_update;
+               uint64_t cur_modseq = INITIAL_MODSEQ;
+
+               if (data == NULL)
+                       data = tempbuf;
+
+               hdr.type = test->type;
+               hdr.size = sizeof(hdr) + update_modseq_test_get_size(test) * test->count;
+               hdr.size = mail_index_uint32_to_offset(hdr.size);
+               mail_transaction_update_modseq(&hdr, data, &cur_modseq, test->version);
+               test_assert_idx(cur_modseq >= INITIAL_MODSEQ, i);
+               test_assert_idx(test->expected_modseq == cur_modseq, i);
+       }
+       test_end();
+}
+
+int main(void)
+{
+       static void (*const test_functions[])(void) = {
+               test_mail_transaction_update_modseq,
+               NULL
+       };
+       return test_run(test_functions);
+}