summaryrefslogtreecommitdiffstats
path: root/src/lib-storage/test-mail-storage.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib-storage/test-mail-storage.c')
-rw-r--r--src/lib-storage/test-mail-storage.c652
1 files changed, 652 insertions, 0 deletions
diff --git a/src/lib-storage/test-mail-storage.c b/src/lib-storage/test-mail-storage.c
new file mode 100644
index 0000000..0a6b906
--- /dev/null
+++ b/src/lib-storage/test-mail-storage.c
@@ -0,0 +1,652 @@
+/* Copyright (c) 2017-2018 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "test-common.h"
+#include "master-service.h"
+#include "test-mail-storage-common.h"
+
+static void test_init_storage(struct mail_storage *storage_r)
+{
+ i_zero(storage_r);
+ storage_r->user = t_new(struct mail_user, 1);
+ storage_r->user->event = event_create(NULL);
+ storage_r->event = event_create(storage_r->user->event);
+}
+
+static void test_deinit_storage(struct mail_storage *storage)
+{
+ mail_storage_clear_error(storage);
+ if (array_is_created(&storage->error_stack)) {
+ mail_storage_clear_error(storage);
+ i_assert(array_count(&storage->error_stack) == 0);
+ array_free(&storage->error_stack);
+ }
+ event_unref(&storage->event);
+ event_unref(&storage->user->event);
+}
+
+static void test_mail_storage_errors(void)
+{
+ /* NOTE: keep in sync with test-mailbox-list.c */
+ struct mail_storage storage;
+ enum mail_error mail_error;
+ const char *errstr;
+
+ test_begin("mail storage errors");
+ test_init_storage(&storage);
+
+ /* try a regular error */
+ mail_storage_set_error(&storage, MAIL_ERROR_PERM, "error1");
+ test_assert(strcmp(mail_storage_get_last_error(&storage, &mail_error),
+ "error1") == 0);
+ test_assert(mail_error == MAIL_ERROR_PERM);
+ test_assert(strcmp(mail_storage_get_last_internal_error(&storage, &mail_error),
+ "error1") == 0);
+ test_assert(mail_error == MAIL_ERROR_PERM);
+ test_assert(!storage.last_error_is_internal);
+
+ /* set the error to itself */
+ mail_storage_set_error(&storage, MAIL_ERROR_PARAMS,
+ mail_storage_get_last_error(&storage, &mail_error));
+ test_assert(strcmp(mail_storage_get_last_error(&storage, &mail_error),
+ "error1") == 0);
+ test_assert(mail_error == MAIL_ERROR_PARAMS);
+ test_assert(strcmp(mail_storage_get_last_internal_error(&storage, &mail_error),
+ "error1") == 0);
+ test_assert(mail_error == MAIL_ERROR_PARAMS);
+ test_assert(!storage.last_error_is_internal);
+
+ /* clear the error - asking for it afterwards is a bug */
+ mail_storage_clear_error(&storage);
+ test_assert(strcmp(mail_storage_get_last_error(&storage, &mail_error),
+ "BUG: Unknown internal error") == 0);
+ test_assert(mail_error == MAIL_ERROR_TEMP);
+ test_assert(strcmp(mail_storage_get_last_internal_error(&storage, &mail_error),
+ "BUG: Unknown internal error") == 0);
+ test_assert(mail_error == MAIL_ERROR_TEMP);
+ test_assert(!storage.last_error_is_internal);
+
+ /* set internal error in preparation for the next test */
+ test_expect_error_string("critical0");
+ mail_storage_set_critical(&storage, "critical0");
+ test_expect_no_more_errors();
+ test_assert(strstr(mail_storage_get_last_error(&storage, &mail_error),
+ MAIL_ERRSTR_CRITICAL_MSG) != NULL);
+ test_assert(mail_error == MAIL_ERROR_TEMP);
+ test_assert(strcmp(mail_storage_get_last_internal_error(&storage, &mail_error),
+ "critical0") == 0);
+ test_assert(mail_error == MAIL_ERROR_TEMP);
+ test_assert(storage.last_error_is_internal);
+
+ /* internal error without specifying what it is. this needs to clear
+ the previous internal error. */
+ mail_storage_set_internal_error(&storage);
+ test_assert(strstr(mail_storage_get_last_error(&storage, &mail_error),
+ MAIL_ERRSTR_CRITICAL_MSG) != NULL);
+ test_assert(mail_error == MAIL_ERROR_TEMP);
+ test_assert(strstr(mail_storage_get_last_internal_error(&storage, &mail_error),
+ MAIL_ERRSTR_CRITICAL_MSG) != NULL);
+ test_assert(mail_error == MAIL_ERROR_TEMP);
+ test_assert(!storage.last_error_is_internal);
+
+ /* proper internal error */
+ test_expect_error_string("critical1");
+ mail_storage_set_critical(&storage, "critical1");
+ test_expect_no_more_errors();
+ test_assert(strstr(mail_storage_get_last_error(&storage, &mail_error),
+ MAIL_ERRSTR_CRITICAL_MSG) != NULL);
+ test_assert(mail_error == MAIL_ERROR_TEMP);
+ test_assert(strcmp(mail_storage_get_last_internal_error(&storage, &mail_error),
+ "critical1") == 0);
+ test_assert(mail_error == MAIL_ERROR_TEMP);
+ test_assert(storage.last_error_is_internal);
+
+ /* use it in the following internal error */
+ test_expect_error_string("critical2: critical1");
+ mail_storage_set_critical(&storage, "critical2: %s",
+ mail_storage_get_last_internal_error(&storage, &mail_error));
+ test_expect_no_more_errors();
+ test_assert(strstr(mail_storage_get_last_error(&storage, &mail_error),
+ MAIL_ERRSTR_CRITICAL_MSG) != NULL);
+ test_assert(mail_error == MAIL_ERROR_TEMP);
+ test_assert(strcmp(mail_storage_get_last_internal_error(&storage, &mail_error),
+ "critical2: critical1") == 0);
+ test_assert(mail_error == MAIL_ERROR_TEMP);
+ test_assert(storage.last_error_is_internal);
+
+ /* use the previous non-internal error as part of the internal error */
+ test_expect_error_string("critical3: "MAIL_ERRSTR_CRITICAL_MSG);
+ mail_storage_set_critical(&storage, "critical3: %s",
+ mail_storage_get_last_error(&storage, &mail_error));
+ test_expect_no_more_errors();
+ test_assert(strstr(mail_storage_get_last_error(&storage, &mail_error),
+ MAIL_ERRSTR_CRITICAL_MSG) != NULL);
+ test_assert(mail_error == MAIL_ERROR_TEMP);
+ errstr = mail_storage_get_last_internal_error(&storage, &mail_error);
+ test_assert(str_begins(errstr, "critical3: "));
+ test_assert(strstr(errstr+11, MAIL_ERRSTR_CRITICAL_MSG) != NULL);
+ test_assert(mail_error == MAIL_ERROR_TEMP);
+ test_assert(storage.last_error_is_internal);
+
+ /* clear the error again and check that all is as expected */
+ mail_storage_clear_error(&storage);
+ test_assert(strcmp(mail_storage_get_last_error(&storage, &mail_error),
+ "BUG: Unknown internal error") == 0);
+ test_assert(mail_error == MAIL_ERROR_TEMP);
+ test_assert(strcmp(mail_storage_get_last_internal_error(&storage, &mail_error),
+ "BUG: Unknown internal error") == 0);
+ test_assert(mail_error == MAIL_ERROR_TEMP);
+ test_assert(!storage.last_error_is_internal);
+
+ /* use internal error as a regular error (although that really
+ shouldn't be done) */
+ test_expect_error_string("critical4");
+ mail_storage_set_critical(&storage, "critical4");
+ mail_storage_set_error(&storage, MAIL_ERROR_PARAMS,
+ mail_storage_get_last_internal_error(&storage, &mail_error));
+ test_expect_no_more_errors();
+ test_assert(strcmp(mail_storage_get_last_error(&storage, &mail_error),
+ "critical4") == 0);
+ test_assert(mail_error == MAIL_ERROR_PARAMS);
+ test_assert(strcmp(mail_storage_get_last_internal_error(&storage, &mail_error),
+ "critical4") == 0);
+ test_assert(mail_error == MAIL_ERROR_PARAMS);
+ test_assert(!storage.last_error_is_internal);
+
+ test_deinit_storage(&storage);
+ test_end();
+}
+
+static void test_mail_storage_last_error_push_pop(void)
+{
+ /* NOTE: keep in sync with test-mailbox-list.c */
+ struct mail_storage storage;
+ enum mail_error mail_error;
+
+ test_begin("mail_storage_last_error_push/pop()");
+ test_init_storage(&storage);
+
+ /* regular error 1 */
+ mail_storage_set_error(&storage, MAIL_ERROR_PERM, "regular error 1");
+ mail_storage_last_error_push(&storage);
+
+ /* critical error 1 */
+ test_expect_error_string("critical error 1");
+ mail_storage_set_critical(&storage, "critical error 1");
+ test_expect_no_more_errors();
+ mail_storage_last_error_push(&storage);
+
+ /* regular error 2 */
+ mail_storage_set_error(&storage, MAIL_ERROR_PARAMS, "regular error 2");
+ mail_storage_last_error_push(&storage);
+
+ /* critical error 2 */
+ test_expect_error_string("critical error 2");
+ mail_storage_set_critical(&storage, "critical error 2");
+ test_expect_no_more_errors();
+ mail_storage_last_error_push(&storage);
+
+ /* -- clear all errors -- */
+ mail_storage_clear_error(&storage);
+
+ /* critical error 2 pop */
+ mail_storage_last_error_pop(&storage);
+ test_assert(strstr(mail_storage_get_last_error(&storage, &mail_error),
+ MAIL_ERRSTR_CRITICAL_MSG) != NULL);
+ test_assert(mail_error == MAIL_ERROR_TEMP);
+ test_assert(strcmp(mail_storage_get_last_internal_error(&storage, &mail_error),
+ "critical error 2") == 0);
+ test_assert(mail_error == MAIL_ERROR_TEMP);
+ test_assert(storage.last_error_is_internal);
+
+ /* regular error 2 pop */
+ mail_storage_last_error_pop(&storage);
+ test_assert(strcmp(mail_storage_get_last_error(&storage, &mail_error),
+ "regular error 2") == 0);
+ test_assert(mail_error == MAIL_ERROR_PARAMS);
+ test_assert(strcmp(mail_storage_get_last_internal_error(&storage, &mail_error),
+ "regular error 2") == 0);
+ test_assert(mail_error == MAIL_ERROR_PARAMS);
+ test_assert(!storage.last_error_is_internal);
+
+ /* critical error 1 pop */
+ mail_storage_last_error_pop(&storage);
+ test_assert(strstr(mail_storage_get_last_error(&storage, &mail_error),
+ MAIL_ERRSTR_CRITICAL_MSG) != NULL);
+ test_assert(mail_error == MAIL_ERROR_TEMP);
+ test_assert(strcmp(mail_storage_get_last_internal_error(&storage, &mail_error),
+ "critical error 1") == 0);
+ test_assert(mail_error == MAIL_ERROR_TEMP);
+ test_assert(storage.last_error_is_internal);
+
+ /* regular error 1 pop */
+ mail_storage_last_error_pop(&storage);
+ test_assert(strcmp(mail_storage_get_last_error(&storage, &mail_error),
+ "regular error 1") == 0);
+ test_assert(mail_error == MAIL_ERROR_PERM);
+ test_assert(strcmp(mail_storage_get_last_internal_error(&storage, &mail_error),
+ "regular error 1") == 0);
+ test_assert(mail_error == MAIL_ERROR_PERM);
+ test_assert(!storage.last_error_is_internal);
+
+ test_deinit_storage(&storage);
+ test_end();
+}
+
+struct mailbox_verify_test_cases {
+ char ns_sep;
+ char list_sep;
+ const char *box;
+ int ret;
+} test_cases[] = {
+ { '\0', '\0', "INBOX", 0 },
+ { '/', '/', ".DUMPSTER", 0 },
+ { '\0', '\0', "DUMPSTER", 0 },
+ { '\0', '\0', "~DUMPSTER", -1 },
+ { '/', '.', "INBOX/INBOX", 0 },
+ { '/', '/', "INBOX/INBOX", 0 },
+ { '.', '.', "INBOX/INBOX", 0 },
+ { '.', '/', "INBOX/INBOX", -1 },
+ { '\0', '\0', "/etc/passwd", -1 },
+ { '.', '.', "foo.bar", 0 },
+ { '/', '.', "foo.bar", -1 },
+ { '.', '/', "foo.bar", 0 },
+ { '/', '/', "foo.bar", 0 },
+ { '/', '\0', "/foo", -1 },
+ { '/', '\0', "foo/", -1 },
+ { '/', '\0', "foo//bar", -1 },
+ { '.', '/', "/foo", -1 },
+ { '.', '/', "foo/", -1 },
+ { '.', '/', "foo//bar", -1 },
+ { '.', '.', ".foo", -1 },
+ { '.', '.', "foo.", -1 },
+ { '.', '.', "foo..bar", -1 },
+ { '.', '/', ".foo", -1 },
+ { '.', '/', "foo.", -1 },
+ { '.', '/', "foo..bar", -1 },
+ { '.', '/', "/", -1 },
+ { '.', '.', ".", -1 },
+ { '/', '\0', "/", -1 },
+ { '\0', '/', "/", -1 },
+ { '\0', '\0', "", -1 },
+};
+
+struct mailbox_verify_test_cases layout_index_test_cases[] = {
+ { '\0', '\0', "INBOX", 0 },
+ { '/', '/', ".DUMPSTER", 0 },
+ { '\0', '\0', "DUMPSTER", 0 },
+ { '\0', '\0', "~DUMPSTER", 0 },
+ { '\0', '\0', "^DUMPSTER", 0 },
+ { '\0', '\0', "%DUMPSTER", 0 },
+ { '/', '.', "INBOX/INBOX", 0 },
+ { '/', '/', "INBOX/INBOX", 0 },
+ { '.', '.', "INBOX/INBOX", 0 },
+ { '.', '/', "INBOX/INBOX", -1 },
+ { '/', '\0', "/etc/passwd", -1 },
+ { '.', '\0', "/etc/passwd", 0 },
+ { '.', '.', "foo.bar", 0 },
+ { '/', '.', "foo.bar", -1 },
+ { '.', '/', "foo.bar", 0 },
+ { '/', '/', "foo.bar", 0 },
+ { '/', '\0', "/foo", -1 },
+ { '/', '\0', "foo/", -1 },
+ { '/', '\0', "foo//bar", -1 },
+ { '.', '/', "/foo", -1 },
+ { '.', '/', "foo/", -1 },
+ { '.', '/', "foo//bar", -1 },
+ { '.', '.', ".foo", -1 },
+ { '.', '.', "foo.", -1 },
+ { '.', '.', "foo..bar", -1 },
+ { '.', '/', ".foo", -1 },
+ { '.', '/', "foo.", -1 },
+ { '.', '/', "foo..bar", -1 },
+ { '.', '/', "/", -1 },
+ { '.', '.', ".", -1 },
+ { '/', '\0', "/", -1 },
+ { '\0', '/', "/", -1 },
+ { '\0', '\0', "", -1 },
+};
+
+static void
+test_mailbox_verify_name_one(struct mailbox_verify_test_cases *test_case,
+ struct mail_namespace *ns,
+ size_t i)
+{
+ struct mailbox *box;
+ int ret;
+
+ box = mailbox_alloc(ns->list, test_case->box, 0);
+ ret = mailbox_verify_name(box);
+#ifdef DEBUG
+ if (ret != test_case->ret) {
+ i_debug("%c == %c %c == %c",
+ test_case->ns_sep, mail_namespace_get_sep(ns),
+ test_case->list_sep, mailbox_list_get_hierarchy_sep(ns->list));
+ const char *error = "should have failed";
+ if (ret < 0)
+ error = mailbox_get_last_error(box, NULL);
+ i_debug("Failed test for mailbox %s: %s", test_case->box, error);
+ }
+#endif
+ test_assert_idx(ret == test_case->ret, i);
+
+ /* Cannot rename to INBOX */
+ if (strcmp(test_case->box, "INBOX") == 0) {
+ ret = mailbox_create(box, NULL, FALSE);
+ test_assert_idx(ret == 0, i);
+ mailbox_delete(box);
+ mailbox_free(&box);
+ return;
+ }
+
+ struct mailbox *src = mailbox_alloc(ns->list, "RENAME", 0);
+ enum mailbox_existence exists;
+ /* check if the mailbox exists */
+ ret = mailbox_exists(src, FALSE, &exists);
+ test_assert_idx(ret == 0, i);
+ if (ret != 0) {
+ mailbox_free(&box);
+ mailbox_free(&src);
+ return;
+ }
+ if (exists == MAILBOX_EXISTENCE_NONE)
+ (void)mailbox_create(src, NULL, FALSE);
+ ret = mailbox_rename(src, box);
+ #ifdef DEBUG
+ if (ret != test_case->ret) {
+ i_debug("%c == %c %c == %c",
+ test_case->ns_sep, mail_namespace_get_sep(ns),
+ test_case->list_sep, mailbox_list_get_hierarchy_sep(ns->list));
+ const char *error = "should have failed";
+ if (ret < 0)
+ error = mailbox_get_last_error(box, NULL);
+ i_debug("Failed test for mailbox %s: %s", test_case->box, error);
+ }
+#endif
+ test_assert_idx(ret == test_case->ret, i);
+ mailbox_delete(box);
+ mailbox_free(&box);
+ mailbox_free(&src);
+}
+
+static void
+test_mailbox_verify_name_continue(struct mailbox_verify_test_cases *test_cases,
+ size_t ncases, struct test_mail_storage_ctx *ctx)
+{
+ struct mail_namespace *ns =
+ mail_namespace_find_inbox(ctx->user->namespaces);
+
+ for(size_t i = 0; i < ncases; i++) {
+ if ((test_cases[i].ns_sep != '\0' &&
+ (test_cases[i].ns_sep != mail_namespace_get_sep(ns))) ||
+ (test_cases[i].list_sep != '\0' &&
+ test_cases[i].list_sep != mailbox_list_get_hierarchy_sep(ns->list)))
+ continue;
+ test_mailbox_verify_name_one(&test_cases[i], ns, i);
+ }
+}
+
+static void test_mailbox_verify_name_driver_slash(const char *driver,
+ const char *driver_opts,
+ struct test_mail_storage_ctx *ctx)
+{
+ const char *const ns2[] = {
+ "namespace=subspace",
+ "namespace/subspace/separator=/",
+ "namespace/subspace/prefix=SubSpace/",
+ NULL
+ };
+ struct test_mail_storage_settings set = {
+ .driver = driver,
+ .driver_opts = driver_opts,
+ .hierarchy_sep = "/",
+ .extra_input = ns2,
+ };
+ test_mail_storage_init_user(ctx, &set);
+
+ if (strcmp(driver_opts, ":LAYOUT=INDEX") == 0)
+ test_mailbox_verify_name_continue(layout_index_test_cases, N_ELEMENTS(layout_index_test_cases), ctx);
+ else
+ test_mailbox_verify_name_continue(test_cases, N_ELEMENTS(test_cases), ctx);
+
+ test_mail_storage_deinit_user(ctx);
+}
+
+static void test_mailbox_verify_name_driver_dot(const char *driver,
+ const char *driver_opts,
+ struct test_mail_storage_ctx *ctx)
+{
+ const char *const ns2[] = {
+ "namespace=subspace",
+ "namespace/subspace/separator=.",
+ "namespace/subspace/prefix=SubSpace.",
+ NULL
+ };
+ struct test_mail_storage_settings set = {
+ .driver = driver,
+ .driver_opts = driver_opts,
+ .hierarchy_sep = ".",
+ .extra_input = ns2,
+ };
+ test_mail_storage_init_user(ctx, &set);
+
+ if (strcmp(driver_opts, ":LAYOUT=INDEX") == 0)
+ test_mailbox_verify_name_continue(layout_index_test_cases, N_ELEMENTS(layout_index_test_cases), ctx);
+ else
+ test_mailbox_verify_name_continue(test_cases, N_ELEMENTS(test_cases), ctx);
+
+ test_mail_storage_deinit_user(ctx);
+}
+
+static void test_mailbox_verify_name(void)
+{
+ struct {
+ const char *name;
+ const char *driver;
+ const char *opts;
+ } test_cases[] = {
+ { "mbox", "mbox", "" },
+ { "mbox LAYOUT=FS", "mbox", ":LAYOUT=FS" },
+ { "mbox LAYOUT=INDEX", "mbox", ":LAYOUT=INDEX" },
+ { "maildir LAYOUT=INDEX", "maildir", ":LAYOUT=INDEX" },
+ { "sdbox", "sdbox", "" },
+ { "sdbox LAYOUT=FS", "sdbox", ":LAYOUT=FS" },
+ { "sdbox LAYOUT=INDEX", "sdbox", ":LAYOUT=INDEX" },
+ { "mdbox", "mdbox", "" },
+ { "mdbox LAYOUT=FS", "mdbox", ":LAYOUT=FS" },
+ { "mdbox LAYOUT=INDEX", "mdbox", ":LAYOUT=INDEX" },
+ };
+ struct test_mail_storage_ctx *ctx = test_mail_storage_init();
+
+ for(unsigned int i = 0; i < N_ELEMENTS(test_cases); i++) T_BEGIN {
+ test_begin(t_strdup_printf("mailbox_verify_name (%s SEP=.)", test_cases[i].name));
+ test_mailbox_verify_name_driver_dot(test_cases[i].driver, test_cases[i].opts, ctx);
+ test_end();
+ test_begin(t_strdup_printf("mailbox_verify_name (%s SEP=/)", test_cases[i].name));
+ test_mailbox_verify_name_driver_slash(test_cases[i].driver, test_cases[i].opts, ctx);
+ test_end();
+ } T_END;
+
+ test_mail_storage_deinit(&ctx);
+}
+
+static void test_mailbox_list_maildir_continue(struct test_mail_storage_ctx *ctx)
+{
+ struct mailbox_verify_test_cases test_cases[] = {
+ { '\0', '\0', "INBOX", 0 },
+ { '/', '/', ".DUMPSTER", 0 },
+ { '\0', '\0', "DUMPSTER", 0 },
+ { '\0', '\0', "~DUMPSTER", -1 },
+ { '\0', '/', "INBOX/new", -1 },
+ { '\0', '/', "INBOX/cur", -1 },
+ { '\0', '/', "INBOX/tmp", -1 },
+ { '\0', '\0', "/etc/passwd", -1 },
+ { '\0', '/', "SubSpace/new", -1 },
+ { '\0', '/', "SubSpace/cur", -1 },
+ { '\0', '/', "SubSpace/tmp", -1 },
+ { '.', '/', "INBOX.new", -1 },
+ { '.', '/', "INBOX.cur", -1 },
+ { '.', '/', "INBOX.tmp", -1 },
+ { '.', '/', "SubSpace.new", -1 },
+ { '.', '/', "SubSpace.cur", -1 },
+ { '.', '/', "SubSpace.tmp", -1 },
+ { '/', '.', "INBOX/INBOX", 0 },
+ { '/', '/', "INBOX/INBOX", 0 },
+ { '.', '.', "INBOX/INBOX", -1 },
+ { '.', '/', "INBOX/INBOX", -1 },
+ { '.', '.', "foo.bar", 0 },
+ { '/', '.', "foo.bar", -1 },
+ { '.', '/', "foo.bar", 0 },
+ { '/', '/', "foo.bar", 0 },
+ { '/', '\0', "/foo", -1 },
+ { '/', '\0', "foo/", -1 },
+ { '/', '\0', "foo//bar", -1 },
+ { '.', '/', "/foo", -1 },
+ { '.', '/', "foo/", -1 },
+ { '.', '/', "foo//bar", -1 },
+ { '.', '.', ".foo", -1 },
+ { '.', '.', "foo.", -1 },
+ { '.', '.', "foo..bar", -1 },
+ { '.', '/', ".foo", -1 },
+ { '.', '/', "foo.", -1 },
+ { '.', '/', "foo..bar", -1 },
+ { '.', '/', "/", -1 },
+ { '.', '.', ".", -1 },
+ { '/', '\0', "/", -1 },
+ { '\0', '/', "/", -1 },
+ { '\0', '\0', "", -1 },
+ };
+
+ test_mailbox_verify_name_continue(test_cases, N_ELEMENTS(test_cases), ctx);
+}
+
+static void test_mailbox_list_maildir_init(struct test_mail_storage_ctx *ctx,
+ const char *driver_opts, const char *sep)
+{
+ const char *error ATTR_UNUSED;
+ const char *const ns2[] = {
+ "namespace=subspace",
+ t_strdup_printf("namespace/subspace/separator=%s", sep),
+ t_strdup_printf("namespace/subspace/prefix=SubSpace%s", sep),
+ NULL
+ };
+
+ struct test_mail_storage_settings set = {
+ .driver = "maildir",
+ .driver_opts = driver_opts,
+ .hierarchy_sep = sep,
+ .extra_input = ns2,
+ };
+ test_mail_storage_init_user(ctx, &set);
+ test_mailbox_list_maildir_continue(ctx);
+
+ struct mail_namespace *ns =
+ mail_namespace_find_prefix(ctx->user->namespaces,
+ t_strdup_printf("SubSpace%s", sep));
+
+ struct mailbox *box = mailbox_alloc(ns->list, "SubSpace", 0);
+ int ret = mailbox_verify_name(box);
+ test_assert(ret == 0);
+#ifdef DEBUG
+ if (ret < 0) {
+ error = mailbox_get_last_error(box, NULL);
+ i_debug("Failed test for mailbox %s: %s",
+ mailbox_get_vname(box), error);
+ }
+#endif
+ mailbox_free(&box);
+ box = mailbox_alloc(ns->list, t_strdup_printf("SubSpace%sInner", sep), 0);
+ ret = mailbox_verify_name(box);
+ test_assert(ret == 0);
+#ifdef DEBUG
+ if (ret < 0) {
+ error = mailbox_get_last_error(box, NULL);
+ i_debug("Failed test for mailbox %s: %s",
+ mailbox_get_vname(box), error);
+ }
+#endif
+ mailbox_free(&box);
+
+ test_mail_storage_deinit_user(ctx);
+}
+
+static void test_mailbox_list_maildir(void)
+{
+ struct test_mail_storage_ctx *ctx = test_mail_storage_init();
+
+ test_begin("mailbox_verify_name (maildir SEP=.)");
+ test_mailbox_list_maildir_init(ctx, "", ".");
+ test_end();
+
+ test_begin("mailbox_verify_name (maildir SEP=/)");
+ test_mailbox_list_maildir_init(ctx, "", "/");
+ test_end();
+
+ test_begin("mailbox_verify_name (maildir SEP=. LAYOUT=FS)");
+ test_mailbox_list_maildir_init(ctx, "LAYOUT=FS", ".");
+ test_end();
+
+ test_begin("mailbox_verify_name (maildir SEP=/ LAYOUT=FS)");
+ test_mailbox_list_maildir_init(ctx, "LAYOUT=FS", "/");
+ test_end();
+
+ test_mail_storage_deinit(&ctx);
+}
+
+static void test_mailbox_list_mbox(void)
+{
+ struct test_mail_storage_ctx *ctx;
+ struct mailbox_verify_test_cases test_case;
+ struct mail_namespace *ns;
+
+ test_begin("mailbox_list_mbox");
+
+ ctx = test_mail_storage_init();
+
+ /* check that .lock cannot be used */
+ struct test_mail_storage_settings set = {
+ .driver = "mbox",
+ .hierarchy_sep = ".",
+ };
+ test_mail_storage_init_user(ctx, &set);
+
+ test_case.list_sep = '/';
+ test_case.ns_sep = '.';
+ test_case.box = "INBOX/.lock";
+ test_case.ret = -1;
+
+ ns = mail_namespace_find_inbox(ctx->user->namespaces);
+ test_mailbox_verify_name_one(&test_case, ns, 0);
+
+ test_mail_storage_deinit_user(ctx);
+ test_mail_storage_deinit(&ctx);
+
+ test_end();
+}
+
+int main(int argc, char **argv)
+{
+ int ret;
+ void (*const tests[])(void) = {
+ test_mail_storage_errors,
+ test_mail_storage_last_error_push_pop,
+ test_mailbox_verify_name,
+ test_mailbox_list_maildir,
+ test_mailbox_list_mbox,
+ NULL
+ };
+
+ master_service = master_service_init("test-mail-storage",
+ MASTER_SERVICE_FLAG_STANDALONE |
+ MASTER_SERVICE_FLAG_DONT_SEND_STATS |
+ MASTER_SERVICE_FLAG_NO_CONFIG_SETTINGS |
+ MASTER_SERVICE_FLAG_NO_SSL_INIT |
+ MASTER_SERVICE_FLAG_NO_INIT_DATASTACK_FRAME,
+ &argc, &argv, "");
+
+ ret = test_run(tests);
+
+ master_service_deinit(&master_service);
+
+ return ret;
+}