bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2015-2018 Dovecot authors, see the included COPYING file */
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen#include "lib.h"
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen#include "ioloop.h"
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen#include "str.h"
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen#include "test-common.h"
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen#include "mail-search-build.h"
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen#include "mail-search-parser.h"
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen#include "mail-search.h"
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen#define CURRENT_UNIX_TIME 1000000
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen
b7324e421e2132cbbf753e6fdbe675bbaecdf929Timo Sirainenstatic const struct {
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen const char *input, *output;
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen} tests[] = {
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "ALL", NULL },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "1,5:6,10:15", NULL },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "UID 1,5:6,10:15", NULL },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "ANSWERED FLAGGED DELETED SEEN DRAFT RECENT",
92f5ea24e989266539e97c6fe59ede0565aec6fdTimo Sirainen "ANSWERED FLAGGED DELETED SEEN DRAFT RECENT" },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "KEYWORD foo KEYWORD bar", NULL },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "BEFORE 20-May-2015", "BEFORE \"20-May-2015\"" },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "ON 20-May-2015", "ON \"20-May-2015\"" },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "SINCE 20-May-2015", "SINCE \"20-May-2015\"" },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "SENTBEFORE 20-May-2015", "SENTBEFORE \"20-May-2015\"" },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "SENTON 20-May-2015", "SENTON \"20-May-2015\"" },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "SENTSINCE 20-May-2015", "SENTSINCE \"20-May-2015\"" },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "X-SAVEDBEFORE 20-May-2015", "X-SAVEDBEFORE \"20-May-2015\"" },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "X-SAVEDON 20-May-2015", "X-SAVEDON \"20-May-2015\"" },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "X-SAVEDSINCE 20-May-2015", "X-SAVEDSINCE \"20-May-2015\"" },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "OLDER 1", NULL },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "OLDER 1000", NULL },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "YOUNGER 1", NULL },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "YOUNGER 1000", NULL },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "SMALLER 0", NULL },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "SMALLER 1", NULL },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "SMALLER 4294967295", NULL },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "LARGER 0", NULL },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "LARGER 1", NULL },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "LARGER 4294967295", NULL },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "FROM foo", NULL },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "TO foo", NULL },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "CC foo", NULL },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "BCC foo", NULL },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "SUBJECT foo", NULL },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "HEADER subjecT foo", "SUBJECT foo" },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "HEADER subjecT2 foo", "HEADER SUBJECT2 foo" },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "BODY foo", NULL },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "TEXT foo", NULL },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "MODSEQ 0", NULL },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "MODSEQ 1", NULL },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "MODSEQ 18446744073709551615", NULL },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "MODSEQ /flags/keyword all 0", NULL },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "MODSEQ /flags/\\Seen all 0", NULL },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "MODSEQ /flags/\\Seen priv 0", NULL },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "MODSEQ /flags/\\Seen shared 0", NULL },
92f5ea24e989266539e97c6fe59ede0565aec6fdTimo Sirainen { "INTHREAD REFERENCES seen", "INTHREAD REFERENCES (SEEN)" },
92f5ea24e989266539e97c6fe59ede0565aec6fdTimo Sirainen { "INTHREAD ORDEREDSUBJECT seen", "INTHREAD ORDEREDSUBJECT (SEEN)" },
92f5ea24e989266539e97c6fe59ede0565aec6fdTimo Sirainen { "INTHREAD REFS seen", "INTHREAD REFS (SEEN)" },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "INTHREAD REFS ( OR text foo OR keyword bar seen )",
5b2062e40f54535b212e800ffc79de0e405d4560Timo Sirainen "INTHREAD REFS ((OR TEXT foo OR KEYWORD bar SEEN))" },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "X-GUID foo", NULL },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { "X-MAILBOX foo", NULL },
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch { "X-REAL-UID 1,5:6,10:15", NULL },
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch /* SEARCH=X-MIMEPART */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch { "MIMEPART CHILD EXISTS", NULL },
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch { "MIMEPART ( CHILD EXISTS )",
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch "MIMEPART CHILD EXISTS" },
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch { "MIMEPART ( CHILD EXISTS HEADER Comment Hopla )",
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch "MIMEPART (CHILD EXISTS HEADER COMMENT Hopla)" },
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch { "MIMEPART ( DESCRIPTION Frop ENCODING base64 )",
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch "MIMEPART (DESCRIPTION Frop ENCODING base64)" },
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch { "MIMEPART ( DISPOSITION TYPE attachment "
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch "DISPOSITION PARAM FILENAME frop.txt )",
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch "MIMEPART (DISPOSITION TYPE attachment "
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch "DISPOSITION PARAM FILENAME frop.txt)" },
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch { "MIMEPART ( ID <frop.example.com> LANGUAGE en )",
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch "MIMEPART (ID <frop.example.com> LANGUAGE en)" },
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch { "MIMEPART ( LOCATION http://www.dovecot.org )",
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch "MIMEPART LOCATION http://www.dovecot.org" },
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch { "MIMEPART NOT MD5 373def35afde6378efd6172dfeadfd", NULL },
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch { "MIMEPART OR PARAM charset utf-8 TYPE text",
5b2062e40f54535b212e800ffc79de0e405d4560Timo Sirainen "MIMEPART OR PARAM CHARSET utf-8 TYPE text" },
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch { "MIMEPART ( OR SIZE LARGER 25 SIZE SMALLER 1023 )",
5b2062e40f54535b212e800ffc79de0e405d4560Timo Sirainen "MIMEPART OR SIZE LARGER 25 SIZE SMALLER 1023" },
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch { "MIMEPART ( TYPE video SUBTYPE mpeg )",
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch "MIMEPART (TYPE video SUBTYPE mpeg)" },
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch { "( OR MIMEPART ( DEPTH 2 INDEX 1 ) MIMEPART ( DEPTH MAX 4 INDEX 3 ) )",
5b2062e40f54535b212e800ffc79de0e405d4560Timo Sirainen "(OR MIMEPART (DEPTH 2 INDEX 1) MIMEPART (DEPTH MAX 4 INDEX 3))" },
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch { "MIMEPART FILENAME IS frop.txt", NULL },
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch { "MIMEPART FILENAME BEGINS frop", NULL },
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch { "MIMEPART FILENAME ENDS .txt", NULL },
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch { "MIMEPART FILENAME CONTAINS frop", NULL },
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch { "MIMEPART BODY frop MIMEPART TEXT frop", NULL },
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch { "MIMEPART ( CC appie BCC theo FROM leo REPLY-TO henk SENDER arie )",
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch "MIMEPART (CC appie BCC theo FROM leo REPLY-TO henk SENDER arie)" },
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch { "MIMEPART ( MESSAGE-ID <frop4222> IN-REPLY-TO <frop421> )",
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch "MIMEPART (MESSAGE-ID <frop4222> IN-REPLY-TO <frop421>)" },
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch { "MIMEPART ( SUBJECT Frop TO henkie SENTON 20-Feb-2017 )",
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch "MIMEPART (SUBJECT Frop TO henkie SENTON \"20-Feb-2017\")" },
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch { "MIMEPART ( OR SENTBEFORE 20-May-2015 SENTSINCE 20-Feb-2017 )",
5b2062e40f54535b212e800ffc79de0e405d4560Timo Sirainen "MIMEPART OR SENTBEFORE \"20-May-2015\" SENTSINCE \"20-Feb-2017\"" },
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch { "MIMEPART ( ID <frop> PARENT ID <friep> )",
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch "MIMEPART (ID <frop> PARENT (ID <friep>))" },
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch { "MIMEPART ( ID <frop> CHILD ( DESCRIPTION frop ID friep ) )",
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch "MIMEPART (ID <frop> CHILD (DESCRIPTION frop ID friep))" },
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch { "MIMEPART CHILD EXISTS MIMEPART PARENT EXISTS", NULL },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen};
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainenstatic struct mail_search_arg test_failures[] = {
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { .type = SEARCH_MAILBOX },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { .type = SEARCH_MAILBOX_GUID },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { .type = SEARCH_BEFORE, .value = {
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen .date_type = MAIL_SEARCH_DATE_TYPE_SENT, .time = 86400-1 } },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { .type = SEARCH_ON, .value = {
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen .date_type = MAIL_SEARCH_DATE_TYPE_SENT, .time = 86400-1 } },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { .type = SEARCH_SINCE, .value = {
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen .date_type = MAIL_SEARCH_DATE_TYPE_SENT, .time = 86400-1 } },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { .type = SEARCH_ON, .value = {
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen .date_type = MAIL_SEARCH_DATE_TYPE_RECEIVED, .time = 86400-1 } },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { .type = SEARCH_BEFORE, .value = {
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen .date_type = MAIL_SEARCH_DATE_TYPE_SAVED, .time = 86400-1 } },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { .type = SEARCH_ON, .value = {
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen .date_type = MAIL_SEARCH_DATE_TYPE_SAVED, .time = 86400-1 } },
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen { .type = SEARCH_SINCE, .value = {
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen .date_type = MAIL_SEARCH_DATE_TYPE_SAVED, .time = 86400-1 } }
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen};
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainenstatic struct mail_search_args *
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainentest_build_search_args(const char *args)
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen{
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen struct mail_search_parser *parser;
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen struct mail_search_args *sargs;
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen const char *error, *charset = "UTF-8";
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen parser = mail_search_parser_init_cmdline(t_strsplit(args, " "));
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen if (mail_search_build(mail_search_register_get_imap(),
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen parser, &charset, &sargs, &error) < 0)
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen i_panic("%s", error);
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen mail_search_parser_deinit(&parser);
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen return sargs;
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen}
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainenstatic void test_mail_search_args_imap(void)
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen{
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen struct mail_search_args *args;
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen string_t *str = t_str_new(256);
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen const char *output, *error;
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen unsigned int i;
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen ioloop_time = CURRENT_UNIX_TIME; /* YOUNGER/OLDER tests need this */
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen test_begin("mail search args imap");
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen for (i = 0; i < N_ELEMENTS(tests); i++) {
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen args = test_build_search_args(tests[i].input);
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen output = tests[i].output != NULL ?
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen tests[i].output : tests[i].input;
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen str_truncate(str, 0);
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen test_assert_idx(mail_search_args_to_imap(str, args->args, &error), i);
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen test_assert_idx(strcmp(str_c(str), output) == 0, i);
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen mail_search_args_unref(&args);
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen }
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen for (i = 0; i < N_ELEMENTS(test_failures); i++)
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen test_assert_idx(!mail_search_args_to_imap(str, &test_failures[i], &error), i);
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen test_end();
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen}
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainenint main(void)
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen{
baf3e87e186453fda13bd21f7cbcb2efc8492e8bTimo Sirainen static void (*const test_functions[])(void) = {
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen test_mail_search_args_imap,
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen NULL
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen };
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen return test_run(test_functions);
9b92e796224f39ee4a65f7108376db9bfe0e22ddTimo Sirainen}