1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
|
/* Copyright (c) 2020 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "test-common.h"
#include "test-mail-cache.h"
static const struct mail_cache_field cache_field_foo = {
.name = "foo",
.type = MAIL_CACHE_FIELD_STRING,
.decision = MAIL_CACHE_DECISION_YES,
};
static const struct mail_cache_field cache_field_bar = {
.name = "bar",
.type = MAIL_CACHE_FIELD_STRING,
.decision = MAIL_CACHE_DECISION_YES,
};
static const struct mail_cache_field cache_field_baz = {
.name = "baz",
.type = MAIL_CACHE_FIELD_STRING,
.decision = MAIL_CACHE_DECISION_YES,
};
void test_mail_cache_init(struct mail_index *index,
struct test_mail_cache_ctx *ctx_r)
{
i_zero(ctx_r);
ctx_r->index = index;
ctx_r->cache = index->cache;
ctx_r->view = mail_index_view_open(index);
ctx_r->cache_field = cache_field_foo;
ctx_r->cache_field2 = cache_field_bar;
ctx_r->cache_field3 = cache_field_baz;
/* Try to use different file_field_maps for different index instances
by randomizing the registration order. This only works for the 2nd
index that is opened, because the initial cache is always created
with all cache fields in the same order. */
if (i_rand_limit(2) == 0) {
mail_cache_register_fields(ctx_r->cache, &ctx_r->cache_field, 1);
mail_cache_register_fields(ctx_r->cache, &ctx_r->cache_field2, 1);
mail_cache_register_fields(ctx_r->cache, &ctx_r->cache_field3, 1);
} else {
mail_cache_register_fields(ctx_r->cache, &ctx_r->cache_field3, 1);
mail_cache_register_fields(ctx_r->cache, &ctx_r->cache_field2, 1);
mail_cache_register_fields(ctx_r->cache, &ctx_r->cache_field, 1);
}
}
void test_mail_cache_deinit(struct test_mail_cache_ctx *ctx)
{
if (ctx->view != NULL)
mail_index_view_close(&ctx->view);
test_mail_index_close(&ctx->index);
}
unsigned int test_mail_cache_get_purge_count(struct test_mail_cache_ctx *ctx)
{
const struct mail_cache_header *hdr = ctx->cache->hdr;
return hdr->file_seq - hdr->indexid;
}
void test_mail_cache_index_sync(struct test_mail_cache_ctx *ctx)
{
struct mail_index_sync_ctx *sync_ctx;
struct mail_index_view *view;
struct mail_index_transaction *trans;
struct mail_index_sync_rec sync_rec;
test_assert(mail_index_sync_begin(ctx->index, &sync_ctx,
&view, &trans, 0) == 1);
while (mail_index_sync_next(sync_ctx, &sync_rec)) {
if (sync_rec.type == MAIL_INDEX_SYNC_TYPE_EXPUNGE) {
/* we're a bit kludgily assuming that there's only
one UID and also that uid==seq */
mail_index_expunge(trans, sync_rec.uid1);
}
}
test_assert(mail_index_sync_commit(&sync_ctx) == 0);
}
void test_mail_cache_view_sync(struct test_mail_cache_ctx *ctx)
{
struct mail_index_view_sync_ctx *sync_ctx;
struct mail_index_view_sync_rec sync_rec;
bool delayed_expunges;
sync_ctx = mail_index_view_sync_begin(ctx->view, MAIL_INDEX_VIEW_SYNC_FLAG_FIX_INCONSISTENT);
while (mail_index_view_sync_next(sync_ctx, &sync_rec)) ;
test_assert(mail_index_view_sync_commit(&sync_ctx, &delayed_expunges) == 0);
}
void test_mail_cache_purge(void)
{
struct test_mail_cache_ctx ctx;
test_mail_cache_init(test_mail_index_open(), &ctx);
test_assert(mail_cache_purge(ctx.cache, (uint32_t)-1, "test") == 0);
test_mail_cache_deinit(&ctx);
}
void test_mail_cache_add_mail(struct test_mail_cache_ctx *ctx,
unsigned int cache_field_idx,
const char *cache_data)
{
const struct mail_index_header *hdr = mail_index_get_header(ctx->view);
struct mail_index_transaction *trans;
struct mail_index_view *updated_view;
struct mail_cache_view *cache_view;
struct mail_cache_transaction_ctx *cache_trans;
uint32_t seq, uid_validity = 12345;
trans = mail_index_transaction_begin(ctx->view, 0);
updated_view = mail_index_transaction_open_updated_view(trans);
cache_view = mail_cache_view_open(ctx->cache, updated_view);
cache_trans = mail_cache_get_transaction(cache_view, trans);
if (hdr->uid_validity == 0) {
mail_index_update_header(trans,
offsetof(struct mail_index_header, uid_validity),
&uid_validity, sizeof(uid_validity), TRUE);
}
mail_index_append(trans, hdr->next_uid, &seq);
if (cache_field_idx != UINT_MAX) {
mail_cache_add(cache_trans, seq, cache_field_idx,
cache_data, strlen(cache_data));
}
test_assert(mail_index_transaction_commit(&trans) == 0);
mail_index_view_close(&updated_view);
mail_cache_view_close(&cache_view);
/* View needs to have the latest changes before purge transaction
is created. */
test_mail_cache_view_sync(ctx);
}
void test_mail_cache_add_field(struct test_mail_cache_ctx *ctx, uint32_t seq,
unsigned int cache_field_idx,
const char *cache_data)
{
struct mail_index_transaction *trans;
struct mail_cache_view *cache_view;
struct mail_cache_transaction_ctx *cache_trans;
cache_view = mail_cache_view_open(ctx->cache, ctx->view);
trans = mail_index_transaction_begin(ctx->view, 0);
cache_trans = mail_cache_get_transaction(cache_view, trans);
mail_cache_add(cache_trans, seq, cache_field_idx,
cache_data, strlen(cache_data));
test_assert(mail_index_transaction_commit(&trans) == 0);
mail_cache_view_close(&cache_view);
}
void test_mail_cache_update_day_first_uid7(struct test_mail_cache_ctx *ctx,
uint32_t first_new_uid)
{
struct mail_index_transaction *trans;
trans = mail_index_transaction_begin(ctx->view, 0);
mail_index_update_header(trans,
offsetof(struct mail_index_header, day_first_uid[7]),
&first_new_uid, sizeof(first_new_uid), FALSE);
test_assert(mail_index_transaction_commit(&trans) == 0);
test_mail_cache_view_sync(ctx);
}
|