/* Copyright (c) 2009-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "ioloop.h"
#include "test-common.h"
#include "mail-index-private.h"
#include "mail-transaction-log-private.h"
struct update_modseq_test {
unsigned int version;
unsigned int count;
union {
} 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_GUID | MAIL_TRANSACTION_EXPUNGE_PROT, TEST_LOG_VERSION, NOUPDATE, 1, { } },
/* flag changes: don't increase modseq */
.flag_update = (const struct mail_transaction_flag_update[]) {
}
} },
.flag_update = (const struct mail_transaction_flag_update[]) {
}
} },
.flag_update = (const struct mail_transaction_flag_update[]) {
}
} },
.flag_update = (const struct mail_transaction_flag_update[]) {
}
} },
.flag_update = (const struct mail_transaction_flag_update[]) {
}
} },
/* flag changes: increase modseq */
.flag_update = (const struct mail_transaction_flag_update[]) {
}
} },
.flag_update = (const struct mail_transaction_flag_update[]) {
}
} },
.flag_update = (const struct mail_transaction_flag_update[]) {
}
} },
.flag_update = (const struct mail_transaction_flag_update[]) {
}
} },
.flag_update = (const struct mail_transaction_flag_update[]) {
}
} },
.flag_update = (const struct mail_transaction_flag_update[]) {
}
} },
.flag_update = (const struct mail_transaction_flag_update[]) {
}
} },
.flag_update = (const struct mail_transaction_flag_update[]) {
}
} },
.flag_update = (const struct mail_transaction_flag_update[]) {
}
} },
/* flag changes: increase modseq with old version */
.flag_update = (const struct mail_transaction_flag_update[]) {
}
} },
.flag_update = (const struct mail_transaction_flag_update[]) {
}
} },
/* modseq updates: don't increase modseq */
.modseq_update = (const struct mail_transaction_modseq_update[]) {
}
} },
.modseq_update = (const struct mail_transaction_modseq_update[]) {
}
} },
/* modseq updates: increase modseq */
.modseq_update = (const struct mail_transaction_modseq_update[]) {
}
} },
.modseq_update = (const struct mail_transaction_modseq_update[]) {
}
} },
.modseq_update = (const struct mail_transaction_modseq_update[]) {
}
} },
.modseq_update = (const struct mail_transaction_modseq_update[]) {
}
} },
/* appends, keyword changes, attribute changes: increase modseq */
/* others: don't increase modseq */
};
{
switch (type) {
case MAIL_TRANSACTION_EXPUNGE:
return sizeof(struct mail_transaction_expunge);
return sizeof(struct mail_transaction_expunge_guid);
case MAIL_TRANSACTION_APPEND:
return sizeof(struct mail_index_record);
return sizeof(struct mail_transaction_keyword_update);
return sizeof(struct mail_transaction_keyword_reset);
return 4;
return sizeof(struct mail_transaction_flag_update);
return sizeof(struct mail_transaction_modseq_update);
return 4;
case MAIL_TRANSACTION_SYNC:
break;
}
i_unreached();
}
static void test_mail_transaction_update_modseq(void)
{
test_begin("mail_transaction_update_modseq()");
for (unsigned int i = 0; i < N_ELEMENTS(update_modseq_tests); i++) {
}
test_end();
}
{
return index;
}
static void test_mail_transaction_log_file_modseq_offsets(void)
{
test_begin("mail_transaction_log_file_get_modseq_next_offset() and _get_highest_modseq_at()");
/* start with modseq=2, because modseq=1 is the initial state */
/* add a non-modseq updating change */
(enum mail_flags)MAIL_INDEX_MAIL_FLAG_DIRTY);
}
/* mail_transaction_log_file_get_highest_modseq_at() is simultaneously
tested and it can also add offsets to cache. The difference is that
it adds the highest possible offset, while
mail_transaction_log_file_get_modseq_next_offset() adds the lowest
possible offset. So we'll need to allow both. */
/* 1) mail_transaction_log_file_get_modseq_next_offset() tests */
/* initial_modseq fast path */
/* sync_highest_modseq fast path - it skips to sync_offset instead of
using exactly the same max_modseq */
/* update the offset for the random tests */
/* add to cache */
/* get it from cache */
/* get next value from cache */
/* get previous value from cache again */
/* do some random testing with cache */
for (unsigned int i = 0; i < LOG_FILE_MODSEQ_CACHE_SIZE*10; i++) {
}
/* go through all modseqs - do this after randomness testing or
modseq_alt_next_offset[] matching isn't triggered */
}
/* 2) mail_transaction_log_file_get_highest_modseq_at() tests */
const char *error;
/* initial_offset */
test_assert(mail_transaction_log_file_get_highest_modseq_at(file, modseq_next_offset[1], &modseq, &error) == 0);
/* sync_offset fast path */
test_assert(mail_transaction_log_file_get_highest_modseq_at(file, file->sync_offset, &modseq, &error) == 0);
/* do some random testing with cache */
for (unsigned int i = 0; i < LOG_FILE_MODSEQ_CACHE_SIZE*10; i++) {
test_assert(mail_transaction_log_file_get_highest_modseq_at(file, modseq_next_offset[modseq], &modseq_at, &error) == 0);
test_assert(mail_transaction_log_file_get_highest_modseq_at(file, modseq_alt_next_offset[modseq], &modseq_at, &error) == 0);
}
/* go through all modseqs - do this after randomness testing or
modseq_alt_next_offset[] matching isn't triggered */
test_assert(mail_transaction_log_file_get_highest_modseq_at(file, modseq_next_offset[modseq], &modseq_at, &error) == 0);
}
test_end();
}
static void
{
test_begin("mail_transaction_log_file_get_modseq_next_offset() inconsistency");
/* add modseq=2 */
/* emulate a broken mail_index_modseq_header header */
test_expect_error_string("Transaction log modseq tracking is corrupted");
test_end();
}
int main(void)
{
static void (*const test_functions[])(void) = {
};
ioloop_time = 1;
return test_run(test_functions);
}