Mercurial > dovecot > core-2.2
view src/lib-index/test-mail-transaction-log-view.c @ 22576:707ae9de3812
lib: istream-multiplex - Minor code cleanup
Avoid propagating the error twice, and avoid any confusion about what "got"
actually contains.
author | Timo Sirainen <timo.sirainen@dovecot.fi> |
---|---|
date | Thu, 05 Oct 2017 20:24:11 +0300 |
parents | 7d4ec76b7d94 |
children | cb108f786fb4 |
line wrap: on
line source
/* Copyright (c) 2009-2017 Dovecot authors, see the included COPYING file */ #include "lib.h" #include "array.h" #include "test-common.h" #include "mail-index-private.h" #include "mail-transaction-log-view-private.h" static struct mail_transaction_log *log; static struct mail_transaction_log_view *view; void mail_index_set_error(struct mail_index *index ATTR_UNUSED, const char *fmt ATTR_UNUSED, ...) { } void mail_transaction_log_file_set_corrupted(struct mail_transaction_log_file *file ATTR_UNUSED, const char *fmt ATTR_UNUSED, ...) { } void mail_transaction_logs_clean(struct mail_transaction_log *log ATTR_UNUSED) { } int mail_transaction_log_find_file(struct mail_transaction_log *log, uint32_t file_seq, bool nfs_flush ATTR_UNUSED, struct mail_transaction_log_file **file_r, const char **reason_r) { struct mail_transaction_log_file *file; for (file = log->files; file != NULL; file = file->next) { if (file->hdr.file_seq == file_seq) { *file_r = file; return 1; } } *reason_r = "not found"; return 0; } int mail_transaction_log_file_map(struct mail_transaction_log_file *file ATTR_UNUSED, uoff_t start_offset ATTR_UNUSED, uoff_t end_offset ATTR_UNUSED, const char **reason_r ATTR_UNUSED) { return 1; } int mail_transaction_log_file_get_highest_modseq_at( struct mail_transaction_log_file *file ATTR_UNUSED, uoff_t offset ATTR_UNUSED, uint64_t *highest_modseq_r, const char **error_r ATTR_UNUSED) { *highest_modseq_r = 0; return 0; } void mail_transaction_update_modseq(const struct mail_transaction_header *hdr ATTR_UNUSED, const void *data ATTR_UNUSED, uint64_t *cur_modseq, unsigned int version ATTR_UNUSED) { *cur_modseq += 1; } static void test_transaction_log_file_add(uint32_t file_seq) { struct mail_transaction_log_file **p, *file; file = i_new(struct mail_transaction_log_file, 1); file->hdr.file_seq = file_seq; file->hdr.hdr_size = file->sync_offset = sizeof(file->hdr); file->hdr.prev_file_seq = file_seq - 1; file->hdr.prev_file_offset = (uint32_t)-1; file->log = log; file->fd = -1; file->buffer = buffer_create_dynamic(default_pool, 256); file->buffer_offset = file->hdr.hdr_size; /* files must be sorted by file_seq */ for (p = &log->files; *p != NULL; p = &(*p)->next) { if ((*p)->hdr.file_seq > file->hdr.file_seq) { file->next = *p; break; } } *p = file; log->head = file; } static bool view_is_file_refed(uint32_t file_seq) { struct mail_transaction_log_file *const *files; unsigned int i, count; bool ret = FALSE; files = array_get(&view->file_refs, &count); for (i = 0; i < count; i++) { if (files[i]->hdr.file_seq == file_seq) { i_assert(!ret); /* could be a test too.. */ ret = TRUE; } } return ret; } static size_t add_append_record(struct mail_transaction_log_file *file, const struct mail_index_record *rec) { struct mail_transaction_header hdr; size_t size; i_zero(&hdr); hdr.type = MAIL_TRANSACTION_APPEND | MAIL_TRANSACTION_EXTERNAL; hdr.size = mail_index_uint32_to_offset(sizeof(hdr) + sizeof(*rec)); buffer_append(file->buffer, &hdr, sizeof(hdr)); buffer_append(file->buffer, rec, sizeof(*rec)); size = sizeof(hdr) + sizeof(*rec); file->sync_offset += size; return size; } static void test_mail_transaction_log_view(void) { const struct mail_transaction_header *hdr; const struct mail_index_record *rec; struct mail_index_record append_rec; const void *data; void *oldfile; uint32_t seq; uoff_t offset, last_log_size; const char *reason; bool reset; test_begin("init"); log = i_new(struct mail_transaction_log, 1); log->index = i_new(struct mail_index, 1); log->index->log = log; log->index->log_sync_locked = TRUE; test_transaction_log_file_add(1); test_transaction_log_file_add(2); test_transaction_log_file_add(3); /* add an append record to the 3rd log file */ i_zero(&append_rec); append_rec.uid = 1; last_log_size = sizeof(struct mail_transaction_log_header) + add_append_record(log->head, &append_rec); view = mail_transaction_log_view_open(log); i_assert(view != NULL); test_assert(log->views == view && !view_is_file_refed(1) && !view_is_file_refed(2) && view_is_file_refed(3)); test_end(); /* we have files 1-3 opened */ test_begin("set all"); test_assert(mail_transaction_log_view_set(view, 0, 0, (uint32_t)-1, (uoff_t)-1, &reset, &reason) == 1 && reset && view_is_file_refed(1) && view_is_file_refed(2) && view_is_file_refed(3) && !mail_transaction_log_view_is_corrupted(view)); mail_transaction_log_view_get_prev_pos(view, &seq, &offset); test_assert(seq == 1 && offset == sizeof(struct mail_transaction_log_header)); test_assert(mail_transaction_log_view_next(view, &hdr, &data) == 1); test_assert(hdr->type == (MAIL_TRANSACTION_APPEND | MAIL_TRANSACTION_EXTERNAL)); rec = data; test_assert(memcmp(rec, &append_rec, sizeof(*rec)) == 0); test_assert(mail_transaction_log_view_next(view, &hdr, &data) == 0); test_assert(mail_transaction_log_view_is_last(view)); mail_transaction_log_view_get_prev_pos(view, &seq, &offset); test_assert(seq == 3 && offset == last_log_size); test_end(); test_begin("set first"); test_assert(mail_transaction_log_view_set(view, 0, 0, 0, 0, &reset, &reason) == 1); mail_transaction_log_view_get_prev_pos(view, &seq, &offset); test_assert(seq == 1 && offset == sizeof(struct mail_transaction_log_header)); test_assert(mail_transaction_log_view_next(view, &hdr, &data) == 0); mail_transaction_log_view_get_prev_pos(view, &seq, &offset); test_assert(seq == 1 && offset == sizeof(struct mail_transaction_log_header)); test_end(); test_begin("set end"); test_assert(mail_transaction_log_view_set(view, 3, last_log_size, (uint32_t)-1, (uoff_t)-1, &reset, &reason) == 1); mail_transaction_log_view_get_prev_pos(view, &seq, &offset); test_assert(seq == 3 && offset == last_log_size); test_assert(mail_transaction_log_view_next(view, &hdr, &data) == 0); mail_transaction_log_view_get_prev_pos(view, &seq, &offset); test_assert(seq == 3 && offset == last_log_size); test_end(); test_begin("log clear"); mail_transaction_log_view_clear(view, 2); test_assert(!view_is_file_refed(1) && view_is_file_refed(2) && view_is_file_refed(3)); oldfile = log->files; buffer_free(&log->files->buffer); log->files = log->files->next; i_free(oldfile); test_assert(log->files->hdr.file_seq == 2); test_end(); /* --- first file has been removed --- */ test_begin("set 2-3"); test_assert(mail_transaction_log_view_set(view, 2, 0, (uint32_t)-1, (uoff_t)-1, &reset, &reason) == 1); test_end(); test_begin("missing log handing"); test_assert(mail_transaction_log_view_set(view, 0, 0, (uint32_t)-1, (uoff_t)-1, &reset, &reason) == 0); test_end(); test_begin("closed log handling"); view->log = NULL; test_assert(mail_transaction_log_view_set(view, 0, 0, (uint32_t)-1, (uoff_t)-1, &reset, &reason) == -1); view->log = log; test_end(); mail_transaction_log_view_close(&view); i_free(log->index); while (log->files != NULL) { oldfile = log->files; buffer_free(&log->files->buffer); log->files = log->files->next; i_free(oldfile); } i_free(log); } int main(void) { static void (*test_functions[])(void) = { test_mail_transaction_log_view, NULL }; return test_run(test_functions); }