1 /* Copyright (c) 2020 Dovecot authors, see the included COPYING file */
2
3 #include "lib.h"
4 #include "test-common.h"
5 #include "mail-index-private.h"
6 #include "mail-transaction-log-private.h"
7
8 #define TEST_INDEX_FNAME ".test.index.write"
9 #define TEST_INDEXID 123456
10 #define LOG_FILE1_HEAD_OFFSET 200
11
12 static bool expect_index_rewrite;
13 static bool rotate_fail;
14
15 static struct mail_transaction_log_file log_file = {
16 .hdr = {
17 .indexid = TEST_INDEXID,
18 .file_seq = 1,
19 },
20 };
21 static struct mail_transaction_log_file log_file2 = {
22 .hdr = {
23 .indexid = TEST_INDEXID,
24 .file_seq = 2,
25 .prev_file_seq = 1,
26 .prev_file_offset = LOG_FILE1_HEAD_OFFSET,
27 },
28 };
29
mail_index_set_error(struct mail_index * index ATTR_UNUSED,const char * fmt ATTR_UNUSED,...)30 void mail_index_set_error(struct mail_index *index ATTR_UNUSED,
31 const char *fmt ATTR_UNUSED, ...)
32 {
33 }
34
mail_index_set_syscall_error(struct mail_index * index ATTR_UNUSED,const char * function)35 void mail_index_set_syscall_error(struct mail_index *index ATTR_UNUSED,
36 const char *function)
37 {
38 i_error("%s() failed: %m", function);
39 }
40
mail_index_file_set_syscall_error(struct mail_index * index ATTR_UNUSED,const char * filepath,const char * function)41 void mail_index_file_set_syscall_error(struct mail_index *index ATTR_UNUSED,
42 const char *filepath,
43 const char *function)
44 {
45 i_error("%s(%s) failed: %m", function, filepath);
46 }
47
mail_index_create_tmp_file(struct mail_index * index ATTR_UNUSED,const char * path_prefix,const char ** path_r)48 int mail_index_create_tmp_file(struct mail_index *index ATTR_UNUSED,
49 const char *path_prefix, const char **path_r)
50 {
51 const char *path;
52 int fd;
53
54 test_assert(expect_index_rewrite);
55
56 path = *path_r = t_strconcat(path_prefix, ".tmp", NULL);
57 fd = open(path, O_RDWR|O_CREAT, 0600);
58 if (fd == -1) {
59 i_error("creat() failed: %m");
60 return -1;
61 }
62 return fd;
63 }
64
mail_index_move_to_memory(struct mail_index * index ATTR_UNUSED)65 int mail_index_move_to_memory(struct mail_index *index ATTR_UNUSED)
66 {
67 return -1;
68 }
69
mail_transaction_log_rotate(struct mail_transaction_log * log,bool reset)70 int mail_transaction_log_rotate(struct mail_transaction_log *log, bool reset)
71 {
72 i_assert(!reset);
73
74 if (rotate_fail)
75 return -1;
76
77 log_file.next = &log_file2;
78 log->head = &log_file2;
79 return 0;
80 }
81
test_mail_index_write(void)82 static void test_mail_index_write(void)
83 {
84 struct mail_transaction_log log = {
85 .head = &log_file,
86 .files = &log_file,
87 };
88 struct mail_index_record_map rec_map = {
89 .records_count = 0,
90 };
91 buffer_t hdr_copy;
92 struct mail_index_map map = {
93 .hdr = {
94 .indexid = TEST_INDEXID,
95 .log_file_seq = 1,
96 .log_file_tail_offset = 100,
97 .log_file_head_offset = LOG_FILE1_HEAD_OFFSET,
98 },
99 .hdr_copy_buf = &hdr_copy,
100 .rec_map = &rec_map,
101 };
102 buffer_create_from_data(&hdr_copy, &map.hdr, sizeof(&map.hdr));
103 struct mail_index index = {
104 .event = event_create(NULL),
105 .log = &log,
106 .map = &map,
107 .dir = ".",
108 .fd = -1,
109 .indexid = TEST_INDEXID,
110 .filepath = TEST_INDEX_FNAME,
111 .log_sync_locked = TRUE,
112 };
113
114 test_begin("test_mail_index_write()");
115
116 /* test failed rotation, no index rewrite */
117 rotate_fail = TRUE;
118 expect_index_rewrite = FALSE;
119 test_assert(!index.reopen_main_index);
120 index.fd = 1; /* anything but -1 */
121 mail_index_write(&index, TRUE, "testing");
122 test_assert(log.head == log.files);
123 test_assert(index.reopen_main_index);
124
125 /* test failed rotation, with index rewrite */
126 expect_index_rewrite = TRUE;
127 index.reopen_main_index = FALSE;
128 index.fd = -1;
129 mail_index_write(&index, TRUE, "testing");
130 test_assert(log.head == log.files);
131 test_assert(!index.reopen_main_index);
132
133 /* test successful rotation, with index rewrite */
134 rotate_fail = FALSE;
135 mail_index_write(&index, TRUE, "testing");
136 test_assert(log.head != log.files && log.head == &log_file2);
137 test_assert(!index.reopen_main_index);
138
139 event_unref(&index.event);
140 i_unlink(TEST_INDEX_FNAME);
141 test_end();
142 }
143
main(void)144 int main(void)
145 {
146 static void (*const test_functions[])(void) = {
147 test_mail_index_write,
148 NULL
149 };
150 return test_run(test_functions);
151 }
152