summaryrefslogtreecommitdiffstats
path: root/src/lib-index/test-mail-index-transaction-update.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib-index/test-mail-index-transaction-update.c')
-rw-r--r--src/lib-index/test-mail-index-transaction-update.c683
1 files changed, 683 insertions, 0 deletions
diff --git a/src/lib-index/test-mail-index-transaction-update.c b/src/lib-index/test-mail-index-transaction-update.c
new file mode 100644
index 0000000..cdfa951
--- /dev/null
+++ b/src/lib-index/test-mail-index-transaction-update.c
@@ -0,0 +1,683 @@
+/* Copyright (c) 2009-2018 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "array.h"
+#include "env-util.h"
+#include "test-common.h"
+#include "mail-index-private.h"
+#include "mail-index-transaction-private.h"
+
+#include <time.h>
+
+static struct mail_index_header hdr;
+static struct mail_index_record rec;
+
+const struct mail_index_header *
+mail_index_get_header(struct mail_index_view *view ATTR_UNUSED)
+{
+ return &hdr;
+}
+
+const struct mail_index_record *
+mail_index_lookup(struct mail_index_view *view ATTR_UNUSED,
+ uint32_t seq ATTR_UNUSED)
+{
+ return &rec;
+}
+
+void mail_index_lookup_keywords(struct mail_index_view *view ATTR_UNUSED,
+ uint32_t seq ATTR_UNUSED,
+ ARRAY_TYPE(keyword_indexes) *keyword_idx ATTR_UNUSED)
+{
+ array_clear(keyword_idx);
+}
+
+bool mail_index_map_get_ext_idx(struct mail_index_map *map ATTR_UNUSED,
+ uint32_t ext_id ATTR_UNUSED,
+ uint32_t *idx_r ATTR_UNUSED)
+{
+ return FALSE;
+}
+
+uint32_t mail_index_view_get_messages_count(struct mail_index_view *view ATTR_UNUSED)
+{
+ return hdr.messages_count;
+}
+
+void mail_index_transaction_lookup_latest_keywords(struct mail_index_transaction *t ATTR_UNUSED,
+ uint32_t seq ATTR_UNUSED,
+ ARRAY_TYPE(keyword_indexes) *keywords ATTR_UNUSED)
+{
+}
+
+struct mail_keywords *
+mail_index_keywords_create_from_indexes(struct mail_index *index ATTR_UNUSED,
+ const ARRAY_TYPE(keyword_indexes)
+ *keyword_indexes ATTR_UNUSED)
+{
+ return NULL;
+}
+
+void mail_index_keywords_unref(struct mail_keywords **keywords ATTR_UNUSED)
+{
+}
+
+static struct mail_index_transaction *
+mail_index_transaction_new(void)
+{
+ struct mail_index_transaction *t;
+
+ t = t_new(struct mail_index_transaction, 1);
+ t->first_new_seq = hdr.messages_count + 1;
+ return t;
+}
+static void mail_index_transaction_cleanup(struct mail_index_transaction *t)
+{
+ if (array_is_created(&t->appends))
+ array_free(&t->appends);
+ if (array_is_created(&t->updates))
+ array_free(&t->updates);
+ if (array_is_created(&t->modseq_updates))
+ array_free(&t->modseq_updates);
+ if (array_is_created(&t->expunges))
+ array_free(&t->expunges);
+}
+
+static void test_mail_index_append(void)
+{
+ struct mail_index_transaction *t;
+ const struct mail_index_record *appends;
+ ARRAY_TYPE(seq_range) saved_uids_arr;
+ const struct seq_range *saved_uids;
+ unsigned int count;
+ uint32_t seq;
+
+ hdr.messages_count = 4;
+ t = mail_index_transaction_new();
+
+ test_begin("mail index append");
+ mail_index_append(t, 0, &seq);
+ test_assert(t->log_updates);
+ test_assert(seq == 5);
+ mail_index_append(t, 0, &seq);
+ test_assert(seq == 6);
+ test_assert(!t->appends_nonsorted);
+
+ t_array_init(&saved_uids_arr, 128);
+ mail_index_append_finish_uids(t, 123, &saved_uids_arr);
+ saved_uids = array_get(&saved_uids_arr, &count);
+ test_assert(count == 1);
+ test_assert(saved_uids[0].seq1 == 123 && saved_uids[0].seq2 == 124);
+
+ appends = array_get(&t->appends, &count);
+ test_assert(appends[0].uid == 123);
+ test_assert(appends[0].flags == 0);
+ test_assert(appends[1].uid == 124);
+ test_assert(appends[1].flags == 0);
+ test_end();
+ mail_index_transaction_cleanup(t);
+
+ /* test with some uids */
+ t = mail_index_transaction_new();
+
+ test_begin("mail index append with uids");
+ mail_index_append(t, 0, &seq);
+ test_assert(seq == 5);
+ mail_index_append(t, 126, &seq);
+ test_assert(seq == 6);
+ test_assert(!t->appends_nonsorted);
+ mail_index_append(t, 124, &seq);
+ test_assert(seq == 7);
+ test_assert(t->appends_nonsorted);
+ mail_index_append(t, 0, &seq);
+ test_assert(seq == 8);
+ mail_index_append(t, 128, &seq);
+ test_assert(seq == 9);
+ test_assert(t->highest_append_uid == 128);
+
+ mail_index_append_finish_uids(t, 125, &saved_uids_arr);
+ saved_uids = array_get(&saved_uids_arr, &count);
+ test_assert(count == 4);
+ test_assert(saved_uids[0].seq1 == 129 && saved_uids[0].seq2 == 129);
+ test_assert(saved_uids[1].seq1 == 126 && saved_uids[1].seq2 == 126);
+ test_assert(saved_uids[2].seq1 == 130 && saved_uids[2].seq2 == 131);
+ test_assert(saved_uids[3].seq1 == 128 && saved_uids[3].seq2 == 128);
+
+ appends = array_get(&t->appends, &count);
+ test_assert(count == 5);
+ test_assert(appends[0].uid == 129);
+ test_assert(appends[1].uid == 126);
+ test_assert(appends[2].uid == 130);
+ test_assert(appends[3].uid == 131);
+ test_assert(appends[4].uid == 128);
+ test_end();
+
+ mail_index_transaction_cleanup(t);
+}
+
+static void test_mail_index_flag_update_fastpath(void)
+{
+ struct mail_index_transaction *t;
+ const struct mail_index_flag_update *updates;
+ unsigned int count;
+
+ hdr.messages_count = 20;
+ t = mail_index_transaction_new();
+
+ test_begin("mail index flag update fast paths");
+
+ mail_index_update_flags_range(t, 13, 14, MODIFY_REPLACE,
+ MAIL_DELETED);
+ test_assert(t->last_update_idx == 0);
+ test_assert(array_count(&t->updates) == 1);
+
+ mail_index_update_flags_range(t, 15, 15, MODIFY_REPLACE,
+ MAIL_DELETED);
+ test_assert(t->last_update_idx == 0);
+ test_assert(array_count(&t->updates) == 1);
+
+ mail_index_update_flags_range(t, 16, 16, MODIFY_ADD,
+ MAIL_DELETED);
+ test_assert(t->last_update_idx == 1);
+ test_assert(array_count(&t->updates) == 2);
+
+ updates = array_get(&t->updates, &count);
+ test_assert(updates[0].uid1 == 13);
+ test_assert(updates[0].uid2 == 15);
+ test_assert(updates[0].add_flags == MAIL_DELETED);
+ test_assert(updates[0].remove_flags ==
+ (MAIL_ANSWERED | MAIL_FLAGGED | MAIL_SEEN | MAIL_DRAFT));
+ test_assert(updates[1].uid1 == 16);
+ test_assert(updates[1].uid2 == 16);
+ test_assert(updates[1].add_flags == MAIL_DELETED);
+ test_assert(updates[1].remove_flags == 0);
+ test_assert(!t->log_updates);
+ test_end();
+
+ mail_index_transaction_cleanup(t);
+}
+
+static void test_mail_index_flag_update_simple_merges(void)
+{
+ struct mail_index_transaction *t;
+ const struct mail_index_flag_update *updates;
+ unsigned int count;
+
+ hdr.messages_count = 20;
+ t = mail_index_transaction_new();
+
+ test_begin("mail index flag update simple merges");
+
+ mail_index_update_flags_range(t, 6, 8, MODIFY_ADD,
+ MAIL_FLAGGED);
+ test_assert(t->last_update_idx == 0);
+ mail_index_update_flags_range(t, 5, 6, MODIFY_ADD,
+ MAIL_FLAGGED);
+ test_assert(t->last_update_idx == 0);
+ mail_index_update_flags_range(t, 4, 4, MODIFY_ADD,
+ MAIL_FLAGGED);
+ test_assert(t->last_update_idx == 0);
+ mail_index_update_flags_range(t, 7, 9, MODIFY_ADD,
+ MAIL_FLAGGED);
+ test_assert(t->last_update_idx == 0);
+ mail_index_update_flags_range(t, 10, 10, MODIFY_ADD,
+ MAIL_FLAGGED);
+ updates = array_get(&t->updates, &count);
+ test_assert(count == 1);
+ test_assert(updates[0].uid1 == 4);
+ test_assert(updates[0].uid2 == 10);
+ test_assert(updates[0].add_flags == MAIL_FLAGGED);
+ test_assert(updates[0].remove_flags == 0);
+
+ mail_index_update_flags_range(t, 12, 12, MODIFY_ADD,
+ MAIL_FLAGGED);
+ mail_index_update_flags_range(t, 11, 11, MODIFY_ADD,
+ MAIL_FLAGGED);
+ updates = array_get(&t->updates, &count);
+ test_assert(count == 1);
+ test_assert(updates[0].uid1 == 4);
+ test_assert(updates[0].uid2 == 12);
+ test_end();
+
+ mail_index_transaction_cleanup(t);
+}
+
+static void test_mail_index_flag_update_complex_merges(void)
+{
+ struct mail_index_transaction *t;
+ const struct mail_index_flag_update *updates;
+ unsigned int count;
+
+ hdr.messages_count = 20;
+ t = mail_index_transaction_new();
+
+ test_begin("mail index flag update complex merges");
+
+ mail_index_update_flags_range(t, 6, 8, MODIFY_REPLACE,
+ MAIL_SEEN);
+ mail_index_update_flags_range(t, 3, 6, MODIFY_ADD,
+ MAIL_FLAGGED);
+ mail_index_update_flags_range(t, 5, 7, MODIFY_ADD,
+ MAIL_DRAFT);
+ mail_index_update_flags_range(t, 6, 6, MODIFY_REPLACE,
+ MAIL_SEEN | MAIL_ANSWERED);
+ mail_index_update_flags_range(t, 5, 10, MODIFY_REMOVE,
+ MAIL_ANSWERED);
+ mail_index_update_flags_range(t, 7, 12, MODIFY_ADD,
+ MAIL_DELETED);
+
+ updates = array_get(&t->updates, &count);
+ test_assert(count == 7);
+ test_assert(updates[0].uid1 == 3);
+ test_assert(updates[0].uid2 == 4);
+ test_assert(updates[0].add_flags == MAIL_FLAGGED);
+ test_assert(updates[0].remove_flags == 0);
+ test_assert(updates[1].uid1 == 5);
+ test_assert(updates[1].uid2 == 5);
+ test_assert(updates[1].add_flags == (MAIL_DRAFT | MAIL_FLAGGED));
+ test_assert(updates[1].remove_flags == MAIL_ANSWERED);
+ test_assert(updates[2].uid1 == 6);
+ test_assert(updates[2].uid2 == 6);
+ test_assert(updates[2].add_flags == MAIL_SEEN);
+ test_assert(updates[2].remove_flags == (MAIL_ANSWERED | MAIL_FLAGGED | MAIL_DELETED | MAIL_DRAFT));
+ test_assert(updates[3].uid1 == 7);
+ test_assert(updates[3].uid2 == 7);
+ test_assert(updates[3].add_flags == (MAIL_SEEN | MAIL_DRAFT | MAIL_DELETED));
+ test_assert(updates[3].remove_flags == (MAIL_ANSWERED | MAIL_FLAGGED));
+ test_assert(updates[4].uid1 == 8);
+ test_assert(updates[4].uid2 == 8);
+ test_assert(updates[4].add_flags == (MAIL_SEEN | MAIL_DELETED));
+ test_assert(updates[4].remove_flags == (MAIL_ANSWERED | MAIL_FLAGGED | MAIL_DRAFT));
+ test_assert(updates[5].uid1 == 9);
+ test_assert(updates[5].uid2 == 10);
+ test_assert(updates[5].add_flags == MAIL_DELETED);
+ test_assert(updates[5].remove_flags == MAIL_ANSWERED);
+ test_assert(updates[6].uid1 == 11);
+ test_assert(updates[6].uid2 == 12);
+ test_assert(updates[6].add_flags == MAIL_DELETED);
+ test_assert(updates[6].remove_flags == 0);
+
+ test_end();
+
+ mail_index_transaction_cleanup(t);
+}
+
+static void
+flags_array_check(struct mail_index_transaction *t,
+ const enum mail_flags *flags, unsigned int msg_count)
+{
+ const struct mail_index_flag_update *updates;
+ unsigned int i, count, seq;
+
+ if (array_is_created(&t->updates))
+ updates = array_get(&t->updates, &count);
+ else {
+ updates = NULL;
+ count = 0;
+ }
+ for (seq = 1, i = 0; i < count; i++) {
+ if (i > 0) {
+ test_assert(updates[i-1].uid2 < updates[i].uid1);
+ test_assert(updates[i-1].uid2 + 1 != updates[i].uid1 ||
+ updates[i-1].add_flags != updates[i].add_flags ||
+ updates[i-1].remove_flags != updates[i].remove_flags);
+ }
+ for (; seq != updates[i].uid1; seq++)
+ test_assert(flags[seq] == 0);
+ for (; seq <= updates[i].uid2; seq++)
+ test_assert(flags[seq] == updates[i].add_flags);
+ }
+ for (; seq <= msg_count; seq++)
+ test_assert(flags[seq] == 0);
+}
+
+static void test_mail_index_flag_update_random(void)
+{
+ struct mail_index_transaction *t;
+ unsigned int r, seq1, seq2, seq;
+ enum mail_flags *flags, change;
+ enum modify_type modify_type;
+
+ hdr.messages_count = 20;
+ t = mail_index_transaction_new();
+
+ test_begin("mail index flag update random");
+
+ flags = t_new(enum mail_flags, hdr.messages_count + 1);
+ for (r = 0; r < 1000; r++) {
+ change = i_rand_limit(MAIL_FLAGS_NONRECENT + 1);
+ seq1 = i_rand_minmax(1, hdr.messages_count);
+ seq2 = seq1 == hdr.messages_count ? seq1 :
+ i_rand_minmax(seq1, hdr.messages_count);
+
+ switch (i_rand_limit(3)) {
+ case 0:
+ modify_type = MODIFY_ADD;
+ for (seq = seq1; seq <= seq2; seq++)
+ flags[seq] |= change;
+ break;
+ case 1:
+ modify_type = MODIFY_REMOVE;
+ for (seq = seq1; seq <= seq2; seq++)
+ flags[seq] &= ENUM_NEGATE(change);
+ break;
+ case 2:
+ modify_type = MODIFY_REPLACE;
+ for (seq = seq1; seq <= seq2; seq++)
+ flags[seq] = change;
+ break;
+ default:
+ i_unreached();
+ }
+ mail_index_update_flags_range(t, seq1, seq2, modify_type,
+ change);
+ flags_array_check(t, flags, hdr.messages_count);
+ }
+ test_end();
+
+ mail_index_transaction_cleanup(t);
+}
+
+static void test_mail_index_cancel_flag_updates(void)
+{
+ struct mail_index_transaction *t;
+ const struct mail_index_flag_update *updates;
+ unsigned int count;
+
+ hdr.messages_count = 20;
+ t = mail_index_transaction_new();
+
+ test_begin("mail index cancel flag updates");
+
+ mail_index_update_flags_range(t, 5, 7, MODIFY_REPLACE, 0);
+ updates = array_get(&t->updates, &count);
+ test_assert(count == 1);
+ test_assert(updates[0].uid1 == 5 && updates[0].uid2 == 7);
+ test_assert(mail_index_cancel_flag_updates(t, 5));
+ test_assert(updates[0].uid1 == 6 && updates[0].uid2 == 7);
+ test_assert(mail_index_cancel_flag_updates(t, 7));
+ test_assert(updates[0].uid1 == 6 && updates[0].uid2 == 6);
+ test_assert(mail_index_cancel_flag_updates(t, 6));
+ test_assert(!array_is_created(&t->updates));
+
+ mail_index_update_flags_range(t, 5, 7, MODIFY_REPLACE, 0);
+ test_assert(mail_index_cancel_flag_updates(t, 6));
+ updates = array_get(&t->updates, &count);
+ test_assert(count == 2);
+ test_assert(updates[0].uid1 == 5 && updates[0].uid2 == 5);
+ test_assert(updates[1].uid1 == 7 && updates[1].uid2 == 7);
+
+ test_end();
+
+ mail_index_transaction_cleanup(t);
+}
+
+static void test_mail_index_flag_update_appends(void)
+{
+ struct mail_index_transaction *t;
+ const struct mail_index_record *appends;
+ const struct mail_index_flag_update *updates;
+ unsigned int count;
+ uint32_t seq;
+
+ hdr.messages_count = 4;
+ t = mail_index_transaction_new();
+
+ test_begin("mail index flag update appends");
+ mail_index_append(t, 0, &seq);
+ test_assert(seq == 5);
+ mail_index_append(t, 0, &seq);
+ test_assert(seq == 6);
+ mail_index_append(t, 0, &seq);
+ test_assert(seq == 7);
+
+ mail_index_update_flags_range(t, 5, 6, MODIFY_REPLACE,
+ MAIL_SEEN | MAIL_FLAGGED);
+ mail_index_update_flags_range(t, 6, 7, MODIFY_ADD,
+ MAIL_DRAFT | MAIL_FLAGGED);
+ mail_index_update_flags_range(t, 5, 7, MODIFY_REMOVE,
+ MAIL_FLAGGED);
+
+ appends = array_get(&t->appends, &count);
+ test_assert(count == 3);
+ test_assert(appends[0].flags == MAIL_SEEN);
+ test_assert(appends[1].flags == (MAIL_SEEN | MAIL_DRAFT));
+ test_assert(appends[2].flags == MAIL_DRAFT);
+
+ /* mixed existing/appends */
+ mail_index_update_flags_range(t, 4, 5, MODIFY_ADD,
+ MAIL_ANSWERED);
+ test_assert(appends[0].flags == (MAIL_SEEN | MAIL_ANSWERED));
+
+ updates = array_get(&t->updates, &count);
+ test_assert(count == 1);
+ test_assert(updates[0].uid1 == 4);
+ test_assert(updates[0].uid2 == 4);
+ test_assert(updates[0].add_flags == MAIL_ANSWERED);
+ test_end();
+
+ mail_index_transaction_cleanup(t);
+}
+
+static bool test_flag_update_pos(struct mail_index_transaction *t,
+ uint32_t seq, unsigned int idx)
+{
+ unsigned int i, j, count;
+
+ count = array_count(&t->updates);
+ for (i = 0; i < idx; i++) {
+ for (j = idx + 1; j <= count; j++) {
+ if (mail_index_transaction_get_flag_update_pos(t, i, j, seq) != idx) {
+ test_assert(FALSE);
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
+static void test_mail_index_transaction_get_flag_update_pos(void)
+{
+ struct mail_index_transaction *t;
+
+ test_begin("mail index transaction get flag update pos");
+
+ hdr.messages_count = 10;
+ t = mail_index_transaction_new();
+ mail_index_update_flags_range(t, 1, 1, MODIFY_REPLACE, 0);
+ mail_index_update_flags_range(t, 3, 4, MODIFY_REPLACE, 0);
+ mail_index_update_flags_range(t, 6, 7, MODIFY_REPLACE, 0);
+ mail_index_update_flags_range(t, 9, 10, MODIFY_REPLACE, 0);
+
+ test_assert(test_flag_update_pos(t, 1, 0));
+ test_assert(test_flag_update_pos(t, 2, 1));
+ test_assert(test_flag_update_pos(t, 3, 1));
+ test_assert(test_flag_update_pos(t, 4, 1));
+ test_assert(test_flag_update_pos(t, 5, 2));
+ test_assert(test_flag_update_pos(t, 6, 2));
+ test_assert(test_flag_update_pos(t, 7, 2));
+ test_assert(test_flag_update_pos(t, 8, 3));
+ test_assert(test_flag_update_pos(t, 9, 3));
+ test_assert(test_flag_update_pos(t, 10, 3));
+ test_assert(test_flag_update_pos(t, 11, 4));
+ test_assert(test_flag_update_pos(t, 12, 4));
+ test_end();
+
+ mail_index_transaction_cleanup(t);
+}
+
+static void test_mail_index_modseq_update(void)
+{
+ struct mail_index_transaction *t;
+ const struct mail_transaction_modseq_update *ups;
+ unsigned int count;
+
+ test_begin("mail index modseq update");
+
+ hdr.messages_count = 10;
+ t = mail_index_transaction_new();
+
+ mail_index_update_modseq(t, 4, 0x8234fefa02747429ULL);
+ mail_index_update_modseq(t, 6, 0x1234567890abcdefULL);
+ mail_index_update_modseq(t, 2, 0xfeed);
+ mail_index_update_modseq(t, 4, 2);
+ /* modseq=1 updates are ignored: */
+ mail_index_update_modseq(t, 5, 1);
+ mail_index_update_modseq(t, 6, 1);
+
+ ups = array_get(&t->modseq_updates, &count);
+ test_assert(count == 4);
+ test_assert(ups[0].uid == 4 &&
+ ups[0].modseq_high32 == 0x8234fefa &&
+ ups[0].modseq_low32 == 0x02747429);
+ test_assert(ups[1].uid == 6 &&
+ ups[1].modseq_high32 == 0x12345678 &&
+ ups[1].modseq_low32 == 0x90abcdef);
+ test_assert(ups[2].uid == 2 &&
+ ups[2].modseq_high32 == 0 &&
+ ups[2].modseq_low32 == 0xfeed);
+ test_assert(ups[3].uid == 4 &&
+ ups[3].modseq_high32 == 0 &&
+ ups[3].modseq_low32 == 2);
+ test_end();
+
+ mail_index_transaction_cleanup(t);
+}
+
+static void test_mail_index_expunge(void)
+{
+ static guid_128_t empty_guid = { 0, };
+ struct mail_index_transaction *t;
+ const struct mail_transaction_expunge_guid *expunges;
+ guid_128_t guid2, guid3, guid4;
+ unsigned int i, count;
+
+ test_begin("mail index expunge");
+
+ hdr.messages_count = 10;
+ t = mail_index_transaction_new();
+ for (i = 0; i < sizeof(guid2); i++) {
+ guid2[i] = i + 1;
+ guid3[i] = i ^ 0xff;
+ guid4[i] = i + 0x80;
+ }
+
+ mail_index_expunge_guid(t, 4, guid4);
+ test_assert(!t->expunges_nonsorted);
+ mail_index_expunge_guid(t, 2, guid2);
+ test_assert(t->expunges_nonsorted);
+ mail_index_expunge_guid(t, 3, guid3);
+ mail_index_expunge(t, 1);
+ mail_index_expunge(t, 5);
+
+ expunges = array_get(&t->expunges, &count);
+ test_assert(count == 5);
+ test_assert(expunges[0].uid == 4);
+ test_assert(memcmp(expunges[0].guid_128, guid4, sizeof(guid4)) == 0);
+ test_assert(expunges[1].uid == 2);
+ test_assert(memcmp(expunges[1].guid_128, guid2, sizeof(guid2)) == 0);
+ test_assert(expunges[2].uid == 3);
+ test_assert(memcmp(expunges[2].guid_128, guid3, sizeof(guid3)) == 0);
+ test_assert(expunges[3].uid == 1);
+ test_assert(memcmp(expunges[3].guid_128, empty_guid, sizeof(empty_guid)) == 0);
+ test_assert(expunges[4].uid == 5);
+ test_assert(memcmp(expunges[4].guid_128, empty_guid, sizeof(empty_guid)) == 0);
+
+ test_end();
+
+ mail_index_transaction_cleanup(t);
+}
+
+static void test_mail_index_update_day_first_uid(void)
+{
+ struct {
+ uint32_t now;
+ uint32_t old_day_stamp;
+ uint32_t new_day_stamp;
+ uint32_t new_day_first_uid[8];
+ } tests[] = {
+ /* 1487116800 = 2017-02-15 00:00:00 UTC */
+ { 1487116800, 1487116800, 1487116800, { 8, 7, 6, 5, 4, 3, 2, 1 } },
+ /* still same day */
+ { 1487116800+3600*24-1, 1487116800, 1487116800, { 8, 7, 6, 5, 4, 3, 2, 1 } },
+ /* one day earlier */
+ { 1487116800-1, 1487116800, 1487116800, { 8, 7, 6, 5, 4, 3, 2, 1 } },
+ /* next day */
+ { 1487116800+3600*24, 1487116800, 1487116800+3600*24, { 9, 8, 7, 6, 5, 4, 3, 2 } },
+ { 1487116800+3600*24*2-1, 1487116800, 1487116800+3600*24, { 9, 8, 7, 6, 5, 4, 3, 2 } },
+ /* 2 days */
+ { 1487116800+3600*24*2, 1487116800, 1487116800+3600*24*2, { 9, 8, 8, 7, 6, 5, 4, 3 } },
+ /* 3 days */
+ { 1487116800+3600*24*3, 1487116800, 1487116800+3600*24*3, { 9, 8, 8, 8, 7, 6, 5, 4 } },
+ /* 4 days */
+ { 1487116800+3600*24*4, 1487116800, 1487116800+3600*24*4, { 9, 8, 8, 8, 8, 7, 6, 5 } },
+ /* 5 days */
+ { 1487116800+3600*24*5, 1487116800, 1487116800+3600*24*5, { 9, 8, 8, 8, 8, 8, 7, 6 } },
+ /* 6 days */
+ { 1487116800+3600*24*6, 1487116800, 1487116800+3600*24*6, { 9, 8, 8, 8, 8, 8, 8, 7 } },
+ /* 7 days */
+ { 1487116800+3600*24*7, 1487116800, 1487116800+3600*24*7, { 9, 8, 8, 8, 8, 8, 8, 8 } },
+ /* 8 days */
+ { 1487116800+3600*24*8, 1487116800, 1487116800+3600*24*8, { 9, 8, 8, 8, 8, 8, 8, 8 } },
+ /* 366 days */
+ { 1487116800+3600*24*366, 1487116800, 1487116800+3600*24*366, { 9, 8, 8, 8, 8, 8, 8, 8 } },
+ };
+ struct mail_index_transaction *t;
+ struct mail_index_record *rec;
+ unsigned int i, j;
+
+ test_begin("mail index update day first uid");
+
+ /* daylight savings times were confusing these tests, so we'll now
+ just assume that TZ=UTC */
+ test_assert(timezone == 0);
+
+ hdr.messages_count = 10;
+ t = mail_index_transaction_new();
+ t->view = t_new(struct mail_index_view, 1);
+ t->view->map = t_new(struct mail_index_map, 1);
+
+ t_array_init(&t->appends, 1);
+ rec = array_append_space(&t->appends);
+ rec->uid = 9;
+
+ for (i = 0; i < N_ELEMENTS(tests); i++) {
+ i_zero(&hdr);
+ for (j = 0; j < N_ELEMENTS(hdr.day_first_uid); j++)
+ hdr.day_first_uid[j] = 8-j;
+ hdr.day_stamp = tests[i].old_day_stamp + timezone;
+ memcpy(t->post_hdr_change, &hdr, sizeof(hdr));
+ mail_index_update_day_headers(t, tests[i].now + timezone);
+
+ struct mail_index_header new_hdr;
+ memcpy(&new_hdr, t->post_hdr_change, sizeof(new_hdr));
+ test_assert_idx(new_hdr.day_stamp == tests[i].new_day_stamp + timezone, i);
+ test_assert_idx(memcmp(new_hdr.day_first_uid,
+ tests[i].new_day_first_uid,
+ sizeof(uint32_t) * 8) == 0, i);
+ }
+
+ test_end();
+}
+
+int main(void)
+{
+ static void (*const test_functions[])(void) = {
+ test_mail_index_append,
+ test_mail_index_flag_update_fastpath,
+ test_mail_index_flag_update_simple_merges,
+ test_mail_index_flag_update_complex_merges,
+ test_mail_index_flag_update_random,
+ test_mail_index_flag_update_appends,
+ test_mail_index_cancel_flag_updates,
+ test_mail_index_transaction_get_flag_update_pos,
+ test_mail_index_modseq_update,
+ test_mail_index_expunge,
+ test_mail_index_update_day_first_uid,
+ NULL
+ };
+ /* daylight saving time confuses things */
+ env_put("TZ", "UTC");
+ tzset();
+ return test_run(test_functions);
+}