test-mail-transaction-log-view.c revision 02c335c23bf5fa225a467c19f2c063fb0dc7b8c3
c77a61a72b5ecdc507d6cf104142edd371a16c84yz/* Copyright (c) 2009-2016 Dovecot authors, see the included COPYING file */
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yz#include "lib.h"
c77a61a72b5ecdc507d6cf104142edd371a16c84yz#include "array.h"
c77a61a72b5ecdc507d6cf104142edd371a16c84yz#include "test-common.h"
c77a61a72b5ecdc507d6cf104142edd371a16c84yz#include "mail-index-private.h"
c77a61a72b5ecdc507d6cf104142edd371a16c84yz#include "mail-transaction-log-view-private.h"
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yzstatic struct mail_transaction_log *log;
c77a61a72b5ecdc507d6cf104142edd371a16c84yzstatic struct mail_transaction_log_view *view;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yzvoid mail_transaction_log_file_set_corrupted(struct mail_transaction_log_file *file ATTR_UNUSED,
c77a61a72b5ecdc507d6cf104142edd371a16c84yz const char *fmt ATTR_UNUSED, ...)
c77a61a72b5ecdc507d6cf104142edd371a16c84yz{
c77a61a72b5ecdc507d6cf104142edd371a16c84yz}
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yzvoid mail_transaction_logs_clean(struct mail_transaction_log *log ATTR_UNUSED)
c77a61a72b5ecdc507d6cf104142edd371a16c84yz{
c77a61a72b5ecdc507d6cf104142edd371a16c84yz}
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yzint mail_transaction_log_find_file(struct mail_transaction_log *log,
6847c243c8d8a90a8d64e720e19e1353c0cb9889Raymond Chen uint32_t file_seq, bool nfs_flush ATTR_UNUSED,
c77a61a72b5ecdc507d6cf104142edd371a16c84yz struct mail_transaction_log_file **file_r)
c77a61a72b5ecdc507d6cf104142edd371a16c84yz{
c77a61a72b5ecdc507d6cf104142edd371a16c84yz struct mail_transaction_log_file *file;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yz for (file = log->files; file != NULL; file = file->next) {
c77a61a72b5ecdc507d6cf104142edd371a16c84yz if (file->hdr.file_seq == file_seq) {
c77a61a72b5ecdc507d6cf104142edd371a16c84yz *file_r = file;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz return 1;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz }
c77a61a72b5ecdc507d6cf104142edd371a16c84yz }
c77a61a72b5ecdc507d6cf104142edd371a16c84yz return 0;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz}
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yzint mail_transaction_log_file_map(struct mail_transaction_log_file *file ATTR_UNUSED,
c77a61a72b5ecdc507d6cf104142edd371a16c84yz uoff_t start_offset ATTR_UNUSED, uoff_t end_offset ATTR_UNUSED)
c77a61a72b5ecdc507d6cf104142edd371a16c84yz{
c77a61a72b5ecdc507d6cf104142edd371a16c84yz return 1;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz}
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yzint mail_transaction_log_file_get_highest_modseq_at(
c77a61a72b5ecdc507d6cf104142edd371a16c84yz struct mail_transaction_log_file *file ATTR_UNUSED,
c77a61a72b5ecdc507d6cf104142edd371a16c84yz uoff_t offset ATTR_UNUSED, uint64_t *highest_modseq_r)
c77a61a72b5ecdc507d6cf104142edd371a16c84yz{
c77a61a72b5ecdc507d6cf104142edd371a16c84yz *highest_modseq_r = 0;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz return 0;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz}
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yzvoid mail_transaction_update_modseq(const struct mail_transaction_header *hdr ATTR_UNUSED,
c77a61a72b5ecdc507d6cf104142edd371a16c84yz const void *data ATTR_UNUSED,
c77a61a72b5ecdc507d6cf104142edd371a16c84yz uint64_t *cur_modseq)
c77a61a72b5ecdc507d6cf104142edd371a16c84yz{
c77a61a72b5ecdc507d6cf104142edd371a16c84yz *cur_modseq += 1;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz}
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yzstatic void
c77a61a72b5ecdc507d6cf104142edd371a16c84yztest_transaction_log_file_add(uint32_t file_seq)
c77a61a72b5ecdc507d6cf104142edd371a16c84yz{
c77a61a72b5ecdc507d6cf104142edd371a16c84yz struct mail_transaction_log_file **p, *file;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yz file = i_new(struct mail_transaction_log_file, 1);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz file->hdr.file_seq = file_seq;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz file->hdr.hdr_size = file->sync_offset = sizeof(file->hdr);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz file->hdr.prev_file_seq = file_seq - 1;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz file->hdr.prev_file_offset = (uint32_t)-1;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz file->log = log;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz file->fd = -1;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz file->buffer = buffer_create_dynamic(default_pool, 256);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz file->buffer_offset = file->hdr.hdr_size;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yz /* files must be sorted by file_seq */
c77a61a72b5ecdc507d6cf104142edd371a16c84yz for (p = &log->files; *p != NULL; p = &(*p)->next) {
c77a61a72b5ecdc507d6cf104142edd371a16c84yz if ((*p)->hdr.file_seq > file->hdr.file_seq) {
c77a61a72b5ecdc507d6cf104142edd371a16c84yz file->next = *p;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz break;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz }
c77a61a72b5ecdc507d6cf104142edd371a16c84yz }
c77a61a72b5ecdc507d6cf104142edd371a16c84yz *p = file;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz log->head = file;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz}
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yzstatic bool view_is_file_refed(uint32_t file_seq)
c77a61a72b5ecdc507d6cf104142edd371a16c84yz{
c77a61a72b5ecdc507d6cf104142edd371a16c84yz struct mail_transaction_log_file *const *files;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz unsigned int i, count;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz bool ret = FALSE;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yz files = array_get(&view->file_refs, &count);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz for (i = 0; i < count; i++) {
c77a61a72b5ecdc507d6cf104142edd371a16c84yz if (files[i]->hdr.file_seq == file_seq) {
c77a61a72b5ecdc507d6cf104142edd371a16c84yz i_assert(!ret); /* could be a test too.. */
c77a61a72b5ecdc507d6cf104142edd371a16c84yz ret = TRUE;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz }
c77a61a72b5ecdc507d6cf104142edd371a16c84yz }
c77a61a72b5ecdc507d6cf104142edd371a16c84yz return ret;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz}
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yzstatic size_t
c77a61a72b5ecdc507d6cf104142edd371a16c84yzadd_append_record(struct mail_transaction_log_file *file,
c77a61a72b5ecdc507d6cf104142edd371a16c84yz const struct mail_index_record *rec)
c77a61a72b5ecdc507d6cf104142edd371a16c84yz{
c77a61a72b5ecdc507d6cf104142edd371a16c84yz struct mail_transaction_header hdr;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz size_t size;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yz memset(&hdr, 0, sizeof(hdr));
c77a61a72b5ecdc507d6cf104142edd371a16c84yz hdr.type = MAIL_TRANSACTION_APPEND | MAIL_TRANSACTION_EXTERNAL;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz hdr.size = mail_index_uint32_to_offset(sizeof(hdr) + sizeof(*rec));
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yz buffer_append(file->buffer, &hdr, sizeof(hdr));
c77a61a72b5ecdc507d6cf104142edd371a16c84yz buffer_append(file->buffer, rec, sizeof(*rec));
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yz size = sizeof(hdr) + sizeof(*rec);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz file->sync_offset += size;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz return size;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz}
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yzstatic void test_mail_transaction_log_view(void)
c77a61a72b5ecdc507d6cf104142edd371a16c84yz{
c77a61a72b5ecdc507d6cf104142edd371a16c84yz const struct mail_transaction_header *hdr;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz const struct mail_index_record *rec;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz struct mail_index_record append_rec;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz const void *data;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz void *oldfile;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz uint32_t seq;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz uoff_t offset, last_log_size;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz const char *reason;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz bool reset;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_begin("init");
c77a61a72b5ecdc507d6cf104142edd371a16c84yz log = i_new(struct mail_transaction_log, 1);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz log->index = i_new(struct mail_index, 1);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz log->index->log = log;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz log->index->log_sync_locked = TRUE;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_transaction_log_file_add(1);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_transaction_log_file_add(2);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_transaction_log_file_add(3);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yz /* add an append record to the 3rd log file */
c77a61a72b5ecdc507d6cf104142edd371a16c84yz memset(&append_rec, 0, sizeof(append_rec));
c77a61a72b5ecdc507d6cf104142edd371a16c84yz append_rec.uid = 1;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yz last_log_size = sizeof(struct mail_transaction_log_header) +
c77a61a72b5ecdc507d6cf104142edd371a16c84yz add_append_record(log->head, &append_rec);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yz view = mail_transaction_log_view_open(log);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz i_assert(view != NULL);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_assert(log->views == view &&
c77a61a72b5ecdc507d6cf104142edd371a16c84yz !view_is_file_refed(1) && !view_is_file_refed(2) &&
c77a61a72b5ecdc507d6cf104142edd371a16c84yz view_is_file_refed(3));
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_end();
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yz /* we have files 1-3 opened */
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_begin("set all");
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_assert(mail_transaction_log_view_set(view, 0, 0, (uint32_t)-1, (uoff_t)-1, &reset, &reason) == 1 &&
c77a61a72b5ecdc507d6cf104142edd371a16c84yz reset && view_is_file_refed(1) && view_is_file_refed(2) &&
c77a61a72b5ecdc507d6cf104142edd371a16c84yz view_is_file_refed(3) &&
c77a61a72b5ecdc507d6cf104142edd371a16c84yz !mail_transaction_log_view_is_corrupted(view));
c77a61a72b5ecdc507d6cf104142edd371a16c84yz mail_transaction_log_view_get_prev_pos(view, &seq, &offset);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_assert(seq == 1 && offset == sizeof(struct mail_transaction_log_header));
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_assert(mail_transaction_log_view_next(view, &hdr, &data) == 1);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_assert(hdr->type == (MAIL_TRANSACTION_APPEND | MAIL_TRANSACTION_EXTERNAL));
c77a61a72b5ecdc507d6cf104142edd371a16c84yz rec = data;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_assert(memcmp(rec, &append_rec, sizeof(*rec)) == 0);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_assert(mail_transaction_log_view_next(view, &hdr, &data) == 0);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_assert(mail_transaction_log_view_is_last(view));
c77a61a72b5ecdc507d6cf104142edd371a16c84yz mail_transaction_log_view_get_prev_pos(view, &seq, &offset);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_assert(seq == 3 && offset == last_log_size);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_end();
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_begin("set first");
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_assert(mail_transaction_log_view_set(view, 0, 0, 0, 0, &reset, &reason) == 1);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz mail_transaction_log_view_get_prev_pos(view, &seq, &offset);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_assert(seq == 1 && offset == sizeof(struct mail_transaction_log_header));
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_assert(mail_transaction_log_view_next(view, &hdr, &data) == 0);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz mail_transaction_log_view_get_prev_pos(view, &seq, &offset);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_assert(seq == 1 && offset == sizeof(struct mail_transaction_log_header));
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_end();
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_begin("set end");
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_assert(mail_transaction_log_view_set(view, 3, last_log_size, (uint32_t)-1, (uoff_t)-1, &reset, &reason) == 1);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz mail_transaction_log_view_get_prev_pos(view, &seq, &offset);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_assert(seq == 3 && offset == last_log_size);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_assert(mail_transaction_log_view_next(view, &hdr, &data) == 0);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz mail_transaction_log_view_get_prev_pos(view, &seq, &offset);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_assert(seq == 3 && offset == last_log_size);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_end();
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_begin("log clear");
c77a61a72b5ecdc507d6cf104142edd371a16c84yz mail_transaction_log_view_clear(view, 2);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_assert(!view_is_file_refed(1) && view_is_file_refed(2) &&
c77a61a72b5ecdc507d6cf104142edd371a16c84yz view_is_file_refed(3));
c77a61a72b5ecdc507d6cf104142edd371a16c84yz oldfile = log->files;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz buffer_free(&log->files->buffer);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz log->files = log->files->next;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz i_free(oldfile);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_assert(log->files->hdr.file_seq == 2);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_end();
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yz /* --- first file has been removed --- */
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_begin("set 2-3");
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_assert(mail_transaction_log_view_set(view, 2, 0, (uint32_t)-1, (uoff_t)-1, &reset, &reason) == 1);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_end();
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_begin("missing log handing");
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_assert(mail_transaction_log_view_set(view, 0, 0, (uint32_t)-1, (uoff_t)-1, &reset, &reason) == 0);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_end();
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_begin("closed log handling");
c77a61a72b5ecdc507d6cf104142edd371a16c84yz view->log = NULL;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_assert(mail_transaction_log_view_set(view, 0, 0, (uint32_t)-1, (uoff_t)-1, &reset, &reason) == -1);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz view->log = log;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_end();
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yz mail_transaction_log_view_close(&view);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz i_free(log->index);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz while (log->files != NULL) {
c77a61a72b5ecdc507d6cf104142edd371a16c84yz oldfile = log->files;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz buffer_free(&log->files->buffer);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz log->files = log->files->next;
c77a61a72b5ecdc507d6cf104142edd371a16c84yz i_free(oldfile);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz }
c77a61a72b5ecdc507d6cf104142edd371a16c84yz i_free(log);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz}
c77a61a72b5ecdc507d6cf104142edd371a16c84yz
c77a61a72b5ecdc507d6cf104142edd371a16c84yzint main(void)
c77a61a72b5ecdc507d6cf104142edd371a16c84yz{
c77a61a72b5ecdc507d6cf104142edd371a16c84yz static void (*test_functions[])(void) = {
c77a61a72b5ecdc507d6cf104142edd371a16c84yz test_mail_transaction_log_view,
c77a61a72b5ecdc507d6cf104142edd371a16c84yz NULL
c77a61a72b5ecdc507d6cf104142edd371a16c84yz };
c77a61a72b5ecdc507d6cf104142edd371a16c84yz return test_run(test_functions);
c77a61a72b5ecdc507d6cf104142edd371a16c84yz}
c77a61a72b5ecdc507d6cf104142edd371a16c84yz