test-dsync-worker.c revision 3fe67ec75ccae1230bb9eb9f16affc48377f6441
/* Copyright (c) 2009 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "array.h"
#include "str.h"
#include "istream.h"
#include "test-dsync-worker.h"
extern struct dsync_worker_vfuncs test_dsync_worker;
struct dsync_worker *dsync_worker_init_test(void)
{
struct test_dsync_worker *worker;
worker = i_new(struct test_dsync_worker, 1);
worker->worker.v = test_dsync_worker;
worker->tmp_pool = pool_alloconly_create("test worker", 256);
i_array_init(&worker->box_events, 64);
i_array_init(&worker->msg_events, 64);
i_array_init(&worker->results, 64);
worker->body_stream = i_stream_create_from_data("hdr\n\nbody", 9);
return &worker->worker;
}
static void test_worker_deinit(struct dsync_worker *_worker)
{
struct test_dsync_worker *worker = (struct test_dsync_worker *)_worker;
pool_unref(&worker->tmp_pool);
array_free(&worker->box_events);
array_free(&worker->msg_events);
array_free(&worker->results);
i_stream_unref(&worker->body_stream);
i_free(worker);
}
static bool test_worker_is_output_full(struct dsync_worker *worker ATTR_UNUSED)
{
return FALSE;
}
static int test_worker_output_flush(struct dsync_worker *worker ATTR_UNUSED)
{
return 1;
}
static struct dsync_worker_mailbox_iter *
test_worker_mailbox_iter_init(struct dsync_worker *_worker)
{
struct test_dsync_worker *worker = (struct test_dsync_worker *)_worker;
i_assert(worker->box_iter.iter.worker == NULL);
worker->box_iter.iter.worker = _worker;
return &worker->box_iter.iter;
}
static int
test_worker_mailbox_iter_next(struct dsync_worker_mailbox_iter *_iter,
struct dsync_mailbox *dsync_box_r)
{
struct test_dsync_worker_mailbox_iter *iter =
(struct test_dsync_worker_mailbox_iter *)_iter;
if (iter->next_box == NULL)
return iter->last ? -1 : 0;
*dsync_box_r = *iter->next_box;
iter->next_box = NULL;
return 1;
}
static int
test_worker_mailbox_iter_deinit(struct dsync_worker_mailbox_iter *iter)
{
struct test_dsync_worker *worker =
(struct test_dsync_worker *)iter->worker;
memset(&worker->box_iter, 0, sizeof(worker->box_iter));
return 0;
}
static struct dsync_worker_subs_iter *
test_worker_subs_iter_init(struct dsync_worker *_worker)
{
struct test_dsync_worker *worker = (struct test_dsync_worker *)_worker;
i_assert(worker->subs_iter.iter.worker == NULL);
worker->subs_iter.iter.worker = _worker;
return &worker->subs_iter.iter;
}
static int
test_worker_subs_iter_next(struct dsync_worker_subs_iter *_iter,
struct dsync_worker_subscription *rec_r)
{
struct test_dsync_worker_subs_iter *iter =
(struct test_dsync_worker_subs_iter *)_iter;
if (iter->next_subscription == NULL)
return iter->last_subs ? -1 : 0;
*rec_r = *iter->next_subscription;
iter->next_subscription = NULL;
return 1;
}
static int
test_worker_subs_iter_next_un(struct dsync_worker_subs_iter *_iter,
struct dsync_worker_unsubscription *rec_r)
{
struct test_dsync_worker_subs_iter *iter =
(struct test_dsync_worker_subs_iter *)_iter;
if (iter->next_unsubscription == NULL)
return iter->last_unsubs ? -1 : 0;
*rec_r = *iter->next_unsubscription;
iter->next_unsubscription = NULL;
return 1;
}
static int
test_worker_subs_iter_deinit(struct dsync_worker_subs_iter *iter)
{
struct test_dsync_worker *worker =
(struct test_dsync_worker *)iter->worker;
memset(&worker->subs_iter, 0, sizeof(worker->subs_iter));
return 0;
}
static struct dsync_worker_msg_iter *
test_worker_msg_iter_init(struct dsync_worker *_worker,
const mailbox_guid_t mailboxes[],
unsigned int mailbox_count)
{
struct test_dsync_worker *worker = (struct test_dsync_worker *)_worker;
i_assert(worker->msg_iter.iter.worker == NULL);
worker->msg_iter_mailboxes =
p_new(worker->tmp_pool, mailbox_guid_t, mailbox_count);
memcpy(worker->msg_iter_mailboxes, mailboxes,
sizeof(mailboxes[0]) * mailbox_count);
worker->msg_iter_mailbox_count = mailbox_count;
i_array_init(&worker->msg_iter.msgs, 64);
worker->msg_iter.iter.worker = _worker;
return &worker->msg_iter.iter;
}
static int
test_worker_msg_iter_next(struct dsync_worker_msg_iter *_iter,
unsigned int *mailbox_idx_r,
struct dsync_message *msg_r)
{
struct test_dsync_worker_msg_iter *iter =
(struct test_dsync_worker_msg_iter *)_iter;
const struct test_dsync_worker_msg *msg;
if (iter->idx == array_count(&iter->msgs))
return iter->last ? -1 : 0;
msg = array_idx(&iter->msgs, iter->idx++);
*msg_r = msg->msg;
*mailbox_idx_r = msg->mailbox_idx;
return 1;
}
static int
test_worker_msg_iter_deinit(struct dsync_worker_msg_iter *iter)
{
struct test_dsync_worker *worker =
(struct test_dsync_worker *)iter->worker;
array_free(&worker->msg_iter.msgs);
memset(&worker->msg_iter, 0, sizeof(worker->msg_iter));
return 0;
}
static void
test_worker_set_last_box(struct dsync_worker *_worker,
const struct dsync_mailbox *dsync_box,
enum test_dsync_last_box_type type)
{
struct test_dsync_worker *worker = (struct test_dsync_worker *)_worker;
struct test_dsync_box_event event;
event.type = type;
event.box = *dsync_box;
event.box.name = p_strdup(worker->tmp_pool, dsync_box->name);
array_append(&worker->box_events, &event, 1);
}
bool test_dsync_worker_next_box_event(struct test_dsync_worker *worker,
struct test_dsync_box_event *event_r)
{
const struct test_dsync_box_event *events;
unsigned int count;
events = array_get(&worker->box_events, &count);
if (count == 0)
return FALSE;
*event_r = events[0];
array_delete(&worker->box_events, 0, 1);
return TRUE;
}
static void
test_worker_set_subscribed(struct dsync_worker *_worker,
const char *name, time_t last_change, bool set)
{
struct dsync_mailbox dsync_box;
memset(&dsync_box, 0, sizeof(dsync_box));
dsync_box.name = name;
dsync_box.last_changed = last_change;
test_worker_set_last_box(_worker, &dsync_box,
set ? LAST_BOX_TYPE_SUBSCRIBE :
LAST_BOX_TYPE_UNSUBSCRIBE);
}
static void
test_worker_create_mailbox(struct dsync_worker *_worker,
const struct dsync_mailbox *dsync_box)
{
test_worker_set_last_box(_worker, dsync_box, LAST_BOX_TYPE_CREATE);
}
static void
test_worker_delete_mailbox(struct dsync_worker *_worker,
const struct dsync_mailbox *dsync_box)
{
struct test_dsync_worker *worker = (struct test_dsync_worker *)_worker;
struct test_dsync_box_event event;
memset(&event, 0, sizeof(event));
event.type = LAST_BOX_TYPE_DELETE;
event.box = *dsync_box;
array_append(&worker->box_events, &event, 1);
}
static void
test_worker_rename_mailbox(struct dsync_worker *_worker,
const mailbox_guid_t *mailbox,
const struct dsync_mailbox *dsync_box)
{
struct test_dsync_worker *worker = (struct test_dsync_worker *)_worker;
struct test_dsync_box_event event;
memset(&event, 0, sizeof(event));
event.type = LAST_BOX_TYPE_RENAME;
event.box = *dsync_box;
event.box.mailbox_guid = *mailbox;
array_append(&worker->box_events, &event, 1);
}
static void
test_worker_update_mailbox(struct dsync_worker *_worker,
const struct dsync_mailbox *dsync_box)
{
test_worker_set_last_box(_worker, dsync_box, LAST_BOX_TYPE_UPDATE);
}
static void
test_worker_select_mailbox(struct dsync_worker *_worker,
const mailbox_guid_t *mailbox,
const ARRAY_TYPE(const_string) *cache_fields)
{
struct test_dsync_worker *worker = (struct test_dsync_worker *)_worker;
struct dsync_mailbox box;
worker->selected_mailbox = *mailbox;
worker->cache_fields = cache_fields;
memset(&box, 0, sizeof(box));
memcpy(box.mailbox_guid.guid, mailbox, sizeof(box.mailbox_guid.guid));
}
static struct test_dsync_msg_event *
test_worker_set_last_msg(struct test_dsync_worker *worker,
const struct dsync_message *msg,
enum test_dsync_last_msg_type type)
{
struct test_dsync_msg_event *event;
const char **keywords;
unsigned int i, count;
event = array_append_space(&worker->msg_events);
event->type = type;
event->msg = *msg;
event->mailbox = worker->selected_mailbox;
event->msg.guid = p_strdup(worker->tmp_pool, msg->guid);
if (msg->keywords != NULL) {
count = str_array_length(msg->keywords);
keywords = p_new(worker->tmp_pool, const char *, count+1);
for (i = 0; i < count; i++) {
keywords[i] = p_strdup(worker->tmp_pool,
msg->keywords[i]);
}
event->msg.keywords = keywords;
}
return event;
}
bool test_dsync_worker_next_msg_event(struct test_dsync_worker *worker,
struct test_dsync_msg_event *event_r)
{
const struct test_dsync_msg_event *events;
unsigned int count;
events = array_get(&worker->msg_events, &count);
if (count == 0)
return FALSE;
*event_r = events[0];
array_delete(&worker->msg_events, 0, 1);
return TRUE;
}
static void
test_worker_msg_update_metadata(struct dsync_worker *_worker,
const struct dsync_message *msg)
{
struct test_dsync_worker *worker = (struct test_dsync_worker *)_worker;
test_worker_set_last_msg(worker, msg, LAST_MSG_TYPE_UPDATE);
}
static void
test_worker_msg_update_uid(struct dsync_worker *_worker,
uint32_t old_uid, uint32_t new_uid)
{
struct test_dsync_worker *worker = (struct test_dsync_worker *)_worker;
struct dsync_message msg;
memset(&msg, 0, sizeof(msg));
msg.uid = old_uid;
msg.modseq = new_uid;
test_worker_set_last_msg(worker, &msg, LAST_MSG_TYPE_UPDATE_UID);
}
static void test_worker_msg_expunge(struct dsync_worker *_worker, uint32_t uid)
{
struct test_dsync_worker *worker = (struct test_dsync_worker *)_worker;
struct dsync_message msg;
memset(&msg, 0, sizeof(msg));
msg.uid = uid;
test_worker_set_last_msg(worker, &msg, LAST_MSG_TYPE_EXPUNGE);
}
static void
test_worker_msg_copy(struct dsync_worker *_worker,
const mailbox_guid_t *src_mailbox,
uint32_t src_uid, const struct dsync_message *dest_msg,
dsync_worker_copy_callback_t *callback, void *context)
{
struct test_dsync_worker *worker = (struct test_dsync_worker *)_worker;
struct test_dsync_msg_event *event;
event = test_worker_set_last_msg(worker, dest_msg, LAST_MSG_TYPE_COPY);
event->copy_src_mailbox = *src_mailbox;
event->copy_src_uid = src_uid;
callback(TRUE, context);
}
static void
test_worker_msg_save(struct dsync_worker *_worker,
const struct dsync_message *msg,
const struct dsync_msg_static_data *data)
{
struct test_dsync_worker *worker = (struct test_dsync_worker *)_worker;
struct test_dsync_msg_event *event;
const unsigned char *d;
size_t size;
ssize_t ret;
string_t *body;
event = test_worker_set_last_msg(worker, msg, LAST_MSG_TYPE_SAVE);
event->save_data.pop3_uidl = p_strdup(worker->tmp_pool, data->pop3_uidl);
event->save_data.received_date = data->received_date;
body = t_str_new(256);
while ((ret = i_stream_read_data(data->input, &d, &size, 0)) > 0) {
str_append_n(body, d, size);
i_stream_skip(data->input, size);
}
i_assert(ret == -1);
event->save_body = p_strdup(worker->tmp_pool, str_c(body));
}
static void
test_worker_msg_save_cancel(struct dsync_worker *_worker ATTR_UNUSED)
{
}
static void
test_worker_msg_get(struct dsync_worker *_worker,
const mailbox_guid_t *mailbox ATTR_UNUSED,
uint32_t uid ATTR_UNUSED,
dsync_worker_msg_callback_t *callback, void *context)
{
struct test_dsync_worker *worker = (struct test_dsync_worker *)_worker;
struct dsync_msg_static_data data;
memset(&data, 0, sizeof(data));
data.pop3_uidl = "uidl";
data.received_date = 123456;
data.input = worker->body_stream;
i_stream_seek(data.input, 0);
callback(DSYNC_MSG_GET_RESULT_SUCCESS, &data, context);
}
static void
test_worker_finish(struct dsync_worker *_worker ATTR_UNUSED,
dsync_worker_finish_callback_t *callback, void *context)
{
callback(TRUE, context);
}
struct dsync_worker_vfuncs test_dsync_worker = {
test_worker_deinit,
test_worker_is_output_full,
test_worker_output_flush,
test_worker_mailbox_iter_init,
test_worker_mailbox_iter_next,
test_worker_mailbox_iter_deinit,
test_worker_subs_iter_init,
test_worker_subs_iter_next,
test_worker_subs_iter_next_un,
test_worker_subs_iter_deinit,
test_worker_set_subscribed,
test_worker_msg_iter_init,
test_worker_msg_iter_next,
test_worker_msg_iter_deinit,
test_worker_create_mailbox,
test_worker_delete_mailbox,
test_worker_rename_mailbox,
test_worker_update_mailbox,
test_worker_select_mailbox,
test_worker_msg_update_metadata,
test_worker_msg_update_uid,
test_worker_msg_expunge,
test_worker_msg_copy,
test_worker_msg_save,
test_worker_msg_save_cancel,
test_worker_msg_get,
test_worker_finish
};