Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F120837049
sieve.testc
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
46 KB
Referenced Files
None
Subscribers
None
sieve.testc
View Options
/* Unit test for sieve */
/* Heavily based on the old sieve/test.c which bore this message:
*
* - * test.c -- tester for libcyrus_sieve
* - * Larry Greenfield
*
*/
#include "cunit/cunit.h"
#include <malloc.h>
#include "sieve/bytecode.h"
#include "sieve/comparator.h"
#include "sieve/message.h"
#include "sieve/sieve_interface.h"
#include "imap/message.h"
#include "prot.h"
#include "retry.h"
#include "imap/spool.h"
#include "map.h"
#include "cyrusdb.h"
#include "libcyr_cfg.h"
#include "libconfig.h"
#include "xstrlcat.h"
#include "xstrlcpy.h"
#include "xmalloc.h"
#define DBDIR "test-sieve-dbdir"
#define PARTITION "default"
typedef struct {
sieve_interp_t *interp;
sieve_execute_t *exe;
struct {
unsigned int actions;
unsigned int errors;
unsigned int redirects;
unsigned int discards;
unsigned int rejects;
unsigned int fileintos;
unsigned int keeps;
unsigned int notifies;
unsigned int vaction_responses;
} stats;
char *redirected_to;
char *reject_message;
char *filed_mailbox;
char *filed_flags;
char *notify_method;
char *notify_priority;
char *notify_options;
char *vacation_message;
char *vacation_subject;
char *vacation_to;
char *vacation_from;
strarray_t *compile_errors;
strarray_t *run_errors;
} sieve_test_context_t;
typedef struct {
const char *text;
int length;
struct message_content content;
hdrcache_t headers;
char *filename;
} sieve_test_message_t;
/* set to SIEVE_DONE if you want to test "already responded */
int autorespond_reponse = SIEVE_OK;
extern int verbose;
#define TESTCASE(_comp, _mode, _pat, _text, _result) \
comprock = NULL; \
c = lookup_comp(_comp, _mode, -1, &comprock); \
CU_ASSERT_PTR_NOT_NULL(c); \
if (c) { \
res = c(_text, strlen(_text), _pat, comprock); \
CU_ASSERT_EQUAL(res, _result); \
}
static void test_comparator(void)
{
void *comprock;
comparator_t *c;
int res;
TESTCASE( B_OCTET, B_IS, "", "", 1 );
TESTCASE( B_OCTET, B_IS, "a", "", 0 );
TESTCASE( B_OCTET, B_IS, "", "a", 0 );
TESTCASE( B_OCTET, B_IS, "a", "a", 1 );
TESTCASE( B_OCTET, B_IS, "a", "A", 0 );
TESTCASE( B_ASCIICASEMAP, B_IS, "", "", 1 );
TESTCASE( B_ASCIICASEMAP, B_IS, "a", "", 0 );
TESTCASE( B_ASCIICASEMAP, B_IS, "", "a", 0 );
TESTCASE( B_ASCIICASEMAP, B_IS, "a", "a", 1 );
TESTCASE( B_ASCIICASEMAP, B_IS, "a", "A", 1 );
TESTCASE( B_ASCIINUMERIC, B_IS, "123", "123", 1 );
TESTCASE( B_ASCIINUMERIC, B_IS, "123", "-123", 0 );
TESTCASE( B_ASCIINUMERIC, B_IS, "abc", "123", 0 );
TESTCASE( B_ASCIINUMERIC, B_IS, "abc", "abc", 1 );
TESTCASE( B_ASCIINUMERIC, B_IS, "12345678900", "3755744308", 0 ); /* test for 32bit overflow */
TESTCASE( B_ASCIINUMERIC, B_IS, "1567", "1567pounds", 1 );
TESTCASE( B_ASCIINUMERIC, B_IS, "", "", 1 );
TESTCASE( B_ASCIINUMERIC, B_IS, "123456789", "567", 0 );
TESTCASE( B_ASCIINUMERIC, B_IS, "567", "123456789", 0 );
TESTCASE( B_ASCIINUMERIC, B_IS, "123456789", "00000123456789", 1 );
TESTCASE( B_ASCIINUMERIC, B_IS, "102", "1024", 0 );
TESTCASE( B_ASCIINUMERIC, B_IS, "1567M", "1567 arg", 1 );
TESTCASE( B_OCTET, B_CONTAINS, "", "", 1 );
TESTCASE( B_OCTET, B_CONTAINS, "", "a", 1 );
TESTCASE( B_OCTET, B_CONTAINS, "a", "", 0 );
TESTCASE( B_OCTET, B_CONTAINS, "a", "a", 1 );
TESTCASE( B_OCTET, B_CONTAINS, "a", "ab", 1 );
TESTCASE( B_OCTET, B_CONTAINS, "a", "ba", 1 );
TESTCASE( B_OCTET, B_CONTAINS, "a", "aba", 1 );
TESTCASE( B_OCTET, B_CONTAINS, "a", "bab", 1 );
TESTCASE( B_OCTET, B_CONTAINS, "a", "bb", 0 );
TESTCASE( B_OCTET, B_CONTAINS, "a", "bbb", 0 );
TESTCASE( B_OCTET, B_MATCHES, "", "", 1 );
TESTCASE( B_OCTET, B_MATCHES, "", "a", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a", "", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a", "a", 1 );
TESTCASE( B_OCTET, B_MATCHES, "a", "ab", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a", "ba", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a", "aba", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a", "bab", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a", "bb", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a", "bbb", 0 );
TESTCASE( B_OCTET, B_MATCHES, "*", "", 1 );
TESTCASE( B_OCTET, B_MATCHES, "*", "a", 1 );
TESTCASE( B_OCTET, B_MATCHES, "*a*", "", 0 );
TESTCASE( B_OCTET, B_MATCHES, "*a*", "a", 1 );
TESTCASE( B_OCTET, B_MATCHES, "*a*", "ab", 1 );
TESTCASE( B_OCTET, B_MATCHES, "*a*", "ba", 1 );
TESTCASE( B_OCTET, B_MATCHES, "*a*", "aba", 1 );
TESTCASE( B_OCTET, B_MATCHES, "*a*", "bab", 1 );
TESTCASE( B_OCTET, B_MATCHES, "*a*", "bb", 0 );
TESTCASE( B_OCTET, B_MATCHES, "*a*", "bbb", 0 );
TESTCASE( B_OCTET, B_MATCHES, "*a", "", 0 );
TESTCASE( B_OCTET, B_MATCHES, "*a", "a", 1 );
TESTCASE( B_OCTET, B_MATCHES, "*a", "ab", 0 );
TESTCASE( B_OCTET, B_MATCHES, "*a", "ba", 1 );
TESTCASE( B_OCTET, B_MATCHES, "*a", "aba", 1 );
TESTCASE( B_OCTET, B_MATCHES, "*a", "bab", 0 );
TESTCASE( B_OCTET, B_MATCHES, "*a", "bb", 0 );
TESTCASE( B_OCTET, B_MATCHES, "*a", "bbb", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*", "", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*", "a", 1 );
TESTCASE( B_OCTET, B_MATCHES, "a*", "ab", 1 );
TESTCASE( B_OCTET, B_MATCHES, "a*", "ba", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*", "aba", 1 );
TESTCASE( B_OCTET, B_MATCHES, "a*", "bab", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*", "bb", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*", "bbb", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*b", "", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*b", "a", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*b", "ab", 1 );
TESTCASE( B_OCTET, B_MATCHES, "a*b", "ba", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*b", "aba", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*b", "bab", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*b", "bb", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*b", "bbb", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*b", "abbb", 1 );
TESTCASE( B_OCTET, B_MATCHES, "a*b", "acb", 1 );
TESTCASE( B_OCTET, B_MATCHES, "a*b", "acbc", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a?b", "", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a?b", "a", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a?b", "ab", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a?b", "ba", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a?b", "aba", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a?b", "bab", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a?b", "bb", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a?b", "bbb", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a?b", "abbb", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a?b", "acb", 1 );
TESTCASE( B_OCTET, B_MATCHES, "a?b", "acbc", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*?b", "", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*?b", "a", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*?b", "ab", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*?b", "ba", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*?b", "aba", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*?b", "bab", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*?b", "bb", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*?b", "bbb", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*?b", "abbb", 1 );
TESTCASE( B_OCTET, B_MATCHES, "a*?b", "acb", 1 );
TESTCASE( B_OCTET, B_MATCHES, "a*?b", "acbc", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a?*b", "", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a?*b", "a", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a?*b", "ab", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a?*b", "ba", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a?*b", "aba", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a?*b", "bab", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a?*b", "bb", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a?*b", "bbb", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a?*b", "abbb", 1 );
TESTCASE( B_OCTET, B_MATCHES, "a?*b", "acb", 1 );
TESTCASE( B_OCTET, B_MATCHES, "a?*b", "acbc", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*?*b", "", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*?*b", "a", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*?*b", "ab", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*?*b", "ba", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*?*b", "aba", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*?*b", "bab", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*?*b", "bb", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*?*b", "bbb", 0 );
TESTCASE( B_OCTET, B_MATCHES, "a*?*b", "abbb", 1 );
TESTCASE( B_OCTET, B_MATCHES, "a*?*b", "acb", 1 );
TESTCASE( B_OCTET, B_MATCHES, "a*?*b?", "acbc", 1 );
TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "", 0 );
TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "a", 0 );
TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "ab", 1 );
TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "ba", 0 );
TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "aba", 0 );
TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "bab", 0 );
TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "bb", 0 );
TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "bbb", 0 );
TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "abbb", 1 );
TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "acb", 1 );
TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "acbc", 0 );
TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "", 0 );
TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "A", 0 );
TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "Ab", 1 );
TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "BA", 0 );
TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "ABA", 0 );
TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "BAb", 0 );
TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "BB", 0 );
TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "BBB", 0 );
TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "aBBB", 1 );
TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "ACB", 1 );
TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "ACBC", 0 );
}
/* gets the header "head" from msg. */
static int getheader(void *mc, const char *name, const char ***body)
{
sieve_test_message_t *msg = (sieve_test_message_t *)mc;
*body = spool_getheader(msg->headers, name);
if (!*body)
return SIEVE_FAIL;
return SIEVE_OK;
}
static int getsize(void *mc, int *size)
{
sieve_test_message_t *msg = (sieve_test_message_t *)mc;
*size = msg->length;
return SIEVE_OK;
}
static int getbody(void *mc, const char **content_types, sieve_bodypart_t ***parts)
{
sieve_test_message_t *msg = (sieve_test_message_t *)mc;
int r = 0;
if (!msg->content.body) {
/* parse the message body if we haven't already */
FILE *fp = fopen(msg->filename, "r");
CU_ASSERT_PTR_NOT_NULL(fp);
r = message_parse_file(fp,
&msg->content.base,
&msg->content.len,
&msg->content.body);
CU_ASSERT_EQUAL(r, 0);
fclose(fp);
}
/* XXX currently struct bodypart as defined in message.h is the same as
sieve_bodypart_t as defined in sieve_interface.h, so we can typecast */
if (!r)
message_fetch_part(&msg->content, content_types,
(struct bodypart ***) parts);
if (r)
return SIEVE_FAIL;
return SIEVE_OK;
}
static int getinclude(void *sc __attribute__((unused)),
const char *script,
int isglobal __attribute__((unused)),
char *fpath, size_t size)
{
strlcpy(fpath, script, size);
strlcat(fpath, ".bc", size);
return SIEVE_OK;
}
static int redirect(void *ac, void *ic, void *sc __attribute__((unused)),
void *mc __attribute__((unused)),
const char **errmsg __attribute__((unused)))
{
sieve_redirect_context_t *rc = (sieve_redirect_context_t *)ac;
sieve_test_context_t *ctx = (sieve_test_context_t *)ic;
ctx->stats.actions++;
ctx->stats.redirects++;
free(ctx->redirected_to);
ctx->redirected_to = xstrdup(rc->addr);
/* TODO: test returning SIEVE_FAIL */
return SIEVE_OK;
}
static int discard(void *ac __attribute__((unused)),
void *ic, void *sc __attribute__((unused)),
void *mc __attribute__((unused)),
const char **errmsg __attribute__((unused)))
{
sieve_test_context_t *ctx = (sieve_test_context_t *)ic;
ctx->stats.actions++;
ctx->stats.discards++;
/* TODO: test returning SIEVE_FAIL */
return SIEVE_OK;
}
static int reject(void *ac, void *ic, void *sc __attribute__((unused)),
void *mc __attribute__((unused)),
const char **errmsg __attribute__((unused)))
{
sieve_reject_context_t *rc = (sieve_reject_context_t *)ac;
sieve_test_context_t *ctx = (sieve_test_context_t *)ic;
ctx->stats.actions++;
ctx->stats.rejects++;
free(ctx->reject_message);
ctx->reject_message = xstrdup(rc->msg);
/* TODO: test returning SIEVE_FAIL */
return SIEVE_OK;
}
static int fileinto(void *ac, void *ic, void *sc __attribute__((unused)),
void *mc __attribute__((unused)),
const char **errmsg __attribute__((unused)))
{
sieve_fileinto_context_t *fc = (sieve_fileinto_context_t *)ac;
sieve_test_context_t *ctx = (sieve_test_context_t *)ic;
ctx->stats.actions++;
ctx->stats.fileintos++;
free(ctx->filed_mailbox);
ctx->filed_mailbox = xstrdup(fc->mailbox);
free(ctx->filed_flags);
ctx->filed_flags = strarray_join(fc->imapflags, " ");
/* TODO: test returning SIEVE_FAIL */
return SIEVE_OK;
}
static int keep(void *ac, void *ic, void *sc __attribute__((unused)),
void *mc __attribute__((unused)),
const char **errmsg __attribute__((unused)))
{
sieve_keep_context_t *kc = (sieve_keep_context_t *)ac;
sieve_test_context_t *ctx = (sieve_test_context_t *)ic;
ctx->stats.actions++;
ctx->stats.keeps++;
free(ctx->filed_flags);
ctx->filed_flags = strarray_join(kc->imapflags, " ");
/* TODO: test returning SIEVE_FAIL */
return SIEVE_OK;
}
static int notify(void *ac, void *ic, void *sc __attribute__((unused)),
void *mc __attribute__((unused)),
const char **errmsg __attribute__((unused)))
{
sieve_notify_context_t *nc = (sieve_notify_context_t *)ac;
sieve_test_context_t *ctx = (sieve_test_context_t *)ic;
struct buf opts = BUF_INITIALIZER;
const char **p;
for (p = nc->options ; *p ; p++) {
if (opts.len)
buf_putc(&opts, ' ');
buf_appendcstr(&opts, *p);
}
ctx->stats.actions++;
ctx->stats.notifies++;
free(ctx->notify_options);
ctx->notify_options = buf_release(&opts);
free(ctx->notify_method);
ctx->notify_method = xstrdup(nc->method);
free(ctx->notify_priority);
ctx->notify_method = xstrdup(nc->priority);
/* TODO: test returning SIEVE_FAIL */
return SIEVE_OK;
}
static int mysieve_error(int lineno, const char *msg,
void *ic,
void *sc __attribute__((unused)))
{
sieve_test_context_t *ctx = (sieve_test_context_t *)ic;
struct buf buf = BUF_INITIALIZER;
ctx->stats.errors++;
buf_printf(&buf, "line %d: %s", lineno, msg);
strarray_appendm(ctx->compile_errors, buf_release(&buf));
return SIEVE_OK;
}
static int mysieve_execute_error(const char *msg,
void *ic,
void *sc __attribute__((unused)),
void *mc __attribute__((unused)))
{
sieve_test_context_t *ctx = (sieve_test_context_t *)ic;
ctx->stats.errors++;
strarray_append(ctx->run_errors, msg);
return SIEVE_OK;
}
static int autorespond(void *ac __attribute__((unused)),
void *ic __attribute__((unused)),
void *sc __attribute__((unused)),
void *mc __attribute__((unused)),
const char **errmsg __attribute__((unused)))
{
return autorespond_reponse;
}
static int send_response(void *ac, void *ic, void *sc __attribute__((unused)),
void *mc __attribute__((unused)),
const char **errmsg __attribute__((unused)))
{
sieve_send_response_context_t *src = (sieve_send_response_context_t *)ac;
sieve_test_context_t *ctx = (sieve_test_context_t *)ic;
ctx->stats.actions++;
ctx->stats.vaction_responses++;
free(ctx->vacation_message);
ctx->vacation_message = xstrdup(src->msg);
free(ctx->vacation_subject);
ctx->vacation_subject = xstrdup(src->subj);
free(ctx->vacation_to);
ctx->vacation_to = xstrdup(src->addr);
free(ctx->vacation_from);
ctx->vacation_from = xstrdup(src->fromaddr);
/* TODO: test returning SIEVE_FAIL */
return SIEVE_OK;
}
#ifndef HAVE_FMEMOPEN
static FILE *fmemopen(const void *buf, size_t len, const char *mode)
{
FILE *fp;
fp = fopen("/dev/null", mode);
if (!fp)
return NULL;
setbuffer(fp, buf, len);
return fp;
}
#endif
static void config_read_string(const char *s)
{
char *fname = xstrdup("/tmp/cyrus-cunit-configXXXXXX");
int fd = mkstemp(fname);
retry_write(fd, s, strlen(s));
config_reset();
config_read(fname, 0);
unlink(fname);
free(fname);
close(fd);
}
static int set_up(void)
{
libcyrus_config_setstring(CYRUSOPT_CONFIG_DIR, DBDIR);
config_read_string(
"configdirectory: "DBDIR"/conf\n"
"defaultpartition: "PARTITION"\n"
"partition-"PARTITION": "DBDIR"/data\n"
"sievenotifier: mailto\n"
"sieve_extensions: fileinto reject vacation imapflags notify" \
" envelope body relational regex subaddress copy date index\n"
);
libcyrus_init();
return 0;
}
static int tear_down(void)
{
libcyrus_done();
return 0;
}
static void context_setup(sieve_test_context_t *ctx,
const char *script)
{
int r;
static strarray_t mark = STRARRAY_INITIALIZER;
static sieve_vacation_t vacation = {
0, /* min response */
0, /* max response */
&autorespond, /* autorespond() */
&send_response /* send_response() */
};
int len = strlen(script);
int fd;
FILE *fp;
sieve_script_t *scr = NULL;
bytecode_info_t *bytecode = NULL;
char tempfile[32];
memset(ctx, 0, sizeof(*ctx));
if (!mark.count)
strarray_append(&mark, "\\flagged");
ctx->compile_errors = strarray_new();
ctx->run_errors = strarray_new();
ctx->interp = sieve_interp_alloc(ctx);
sieve_register_redirect(ctx->interp, redirect);
sieve_register_discard(ctx->interp, discard);
sieve_register_reject(ctx->interp, reject);
sieve_register_fileinto(ctx->interp, fileinto);
sieve_register_keep(ctx->interp, keep);
sieve_register_size(ctx->interp, getsize);
sieve_register_header(ctx->interp, getheader);
sieve_register_envelope(ctx->interp, getheader);
sieve_register_body(ctx->interp, getbody);
sieve_register_include(ctx->interp, getinclude);
sieve_register_vacation(ctx->interp, &vacation);
sieve_register_imapflags(ctx->interp, &mark);
sieve_register_notify(ctx->interp, notify);
sieve_register_parse_error(ctx->interp, mysieve_error);
sieve_register_execute_error(ctx->interp, mysieve_execute_error);
/* Here we pretend to be the sieve compiler, and generate
* a file of compiled bytecode from the script string */
fp = fmemopen((void *)script, len, "r");
r = sieve_script_parse(ctx->interp, fp, ctx, &scr);
CU_ASSERT_EQUAL(r, SIEVE_OK);
fclose(fp);
r = sieve_generate_bytecode(&bytecode, scr);
CU_ASSERT(r > 0);
strcpy(tempfile, "/tmp/sievetest-BC-XXXXXX");
fd = mkstemp(tempfile);
CU_ASSERT(fd >= 0);
r = sieve_emit_bytecode(fd, bytecode);
CU_ASSERT(r > 0);
sieve_free_bytecode(&bytecode);
sieve_script_free(&scr);
/* Now load the compiled bytecode */
r = sieve_script_load(tempfile, &ctx->exe);
CU_ASSERT_EQUAL(r, SIEVE_OK);
unlink(tempfile);
}
static void context_cleanup(sieve_test_context_t *ctx)
{
int r;
if (verbose > 1) {
int i;
fprintf(stderr, "sieve test context\n");
fprintf(stderr, " actions: %u\n", ctx->stats.actions);
fprintf(stderr, " errors: %u\n", ctx->stats.errors);
fprintf(stderr, " redirects: %u\n", ctx->stats.redirects);
fprintf(stderr, " discards: %u\n", ctx->stats.discards);
fprintf(stderr, " rejects: %u\n", ctx->stats.rejects);
fprintf(stderr, " fileintos: %u\n", ctx->stats.fileintos);
fprintf(stderr, " keeps: %u\n", ctx->stats.keeps);
fprintf(stderr, " notifies: %u\n", ctx->stats.notifies);
fprintf(stderr, " vaction_responses: %u\n", ctx->stats.vaction_responses);
if (ctx->redirected_to)
fprintf(stderr, " redirected_to: %s\n", ctx->redirected_to);
if (ctx->reject_message)
fprintf(stderr, " reject_message: %s\n", ctx->reject_message);
if (ctx->filed_mailbox)
fprintf(stderr, " filed_mailbox: %s\n", ctx->filed_mailbox);
if (ctx->filed_flags)
fprintf(stderr, " filed_flags: %s\n", ctx->filed_flags);
if (ctx->notify_method)
fprintf(stderr, " notify_method: %s\n", ctx->notify_method);
if (ctx->notify_priority)
fprintf(stderr, " notify_priority: %s\n", ctx->notify_priority);
if (ctx->notify_options)
fprintf(stderr, " notify_options: %s\n", ctx->notify_options);
if (ctx->vacation_message)
fprintf(stderr, " vacation_message: %s\n", ctx->vacation_message);
if (ctx->vacation_subject)
fprintf(stderr, " vacation_subject: %s\n", ctx->vacation_subject);
if (ctx->vacation_to)
fprintf(stderr, " vacation_to: %s\n", ctx->vacation_to);
if (ctx->vacation_from)
fprintf(stderr, " vacation_from: %s\n", ctx->vacation_from);
if (ctx->compile_errors->count) {
fprintf(stderr, " compile_errors:\n");
for (i = 0 ; i < ctx->compile_errors->count ; i++)
fprintf(stderr, "\t[%d] %s\n", i, ctx->compile_errors->data[i]);
}
if (ctx->run_errors->count) {
fprintf(stderr, " run_errors:\n");
for (i = 0 ; i < ctx->run_errors->count ; i++)
fprintf(stderr, "\t[%d] %s\n", i, ctx->run_errors->data[i]);
}
}
/*used to be sieve_script_free*/
r = sieve_script_unload(&ctx->exe);
CU_ASSERT_EQUAL(r, SIEVE_OK);
CU_ASSERT_PTR_NULL(ctx->exe);
r = sieve_interp_free(&ctx->interp);
CU_ASSERT_EQUAL(r, SIEVE_OK);
free(ctx->redirected_to);
free(ctx->reject_message);
free(ctx->filed_mailbox);
free(ctx->filed_flags);
free(ctx->notify_method);
free(ctx->notify_priority);
free(ctx->notify_options);
free(ctx->vacation_message);
free(ctx->vacation_subject);
free(ctx->vacation_to);
free(ctx->vacation_from);
strarray_free(ctx->compile_errors);
strarray_free(ctx->run_errors);
}
static sieve_test_message_t *message_new(const char *text, int len)
{
sieve_test_message_t *msg;
struct protstream *pin;
FILE *fout;
int fd;
int r;
char tempfile[32];
msg = xzmalloc(sizeof(sieve_test_message_t));
msg->text = text;
msg->length = len;
msg->headers = spool_new_hdrcache();
strcpy(tempfile, "/tmp/sievetest-MS-XXXXXX");
fd = mkstemp(tempfile);
CU_ASSERT(fd >= 0);
msg->filename = xstrdup(tempfile);
r = retry_write(fd, text, len);
CU_ASSERT_EQUAL(r, len);
lseek(fd, SEEK_SET, 0);
pin = prot_new(fd, /*read*/0);
CU_ASSERT_PTR_NOT_NULL(pin);
fout = fopen("/dev/null", "w");
CU_ASSERT_PTR_NOT_NULL(fout);
r = spool_fill_hdrcache(pin, fout, msg->headers, NULL);
CU_ASSERT_EQUAL(r, 0);
fclose(fout);
prot_free(pin);
return msg;
}
static void message_free(sieve_test_message_t *msg)
{
spool_free_hdrcache(msg->headers);
if (msg->content.body)
message_free_body(msg->content.body);
if (msg->content.base)
map_free(&msg->content.base, &msg->content.len);
unlink(msg->filename);
free(msg->filename);
free(msg);
}
static void run_message(sieve_test_context_t *ctx,
const char *text)
{
sieve_test_message_t *msg;
int r;
msg = message_new(text, strlen(text));
CU_ASSERT_PTR_NOT_NULL(msg);
r = sieve_execute_bytecode(ctx->exe, ctx->interp, ctx, msg);
CU_ASSERT_EQUAL(r, SIEVE_OK);
message_free(msg);
}
static void test_address_all(void)
{
static const char SCRIPT_IS[] =
"if address :all :is \"from\" \"zme@true.com\"\n"
"{redirect \"me@blah.com\";}\n"
;
static const char SCRIPT_CONTAINS[] =
"if address :all :contains \"from\" \"true.com\"\n"
"{redirect \"me@blah.com\";}\n"
;
static const char SCRIPT_MATCHES[] =
"if address :all :matches \"from\" \"*true.com\"\n"
"{redirect \"me@blah.com\";}\n"
;
static const char MSG_TRUE[] =
"Date: Mon, 25 Jan 2003 08:51:06 -0500\r\n"
"From: zme@true.com\r\n"
"To: you\r\n"
"Subject: simple address test\r\n"
"\r\n"
"blah\n"
;
static const char MSG_FALSE[] =
"Date: Mon, 25 Jan 2003 08:51:06 -0500\r\n"
"From: zme@false.com\r\n"
"To: you\r\n"
"Subject: simple address test\r\n"
"\r\n"
"blah\n"
;
sieve_test_context_t ctx;
/* Test :is */
context_setup(&ctx, SCRIPT_IS);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
run_message(&ctx, MSG_TRUE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 1);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 0);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
run_message(&ctx, MSG_FALSE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 2);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 1);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
context_cleanup(&ctx);
/* Test :contains */
context_setup(&ctx, SCRIPT_CONTAINS);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
run_message(&ctx, MSG_TRUE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 1);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 0);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
run_message(&ctx, MSG_FALSE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 2);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 1);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
context_cleanup(&ctx);
/* Test :matches */
context_setup(&ctx, SCRIPT_MATCHES);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
run_message(&ctx, MSG_TRUE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 1);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 0);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
run_message(&ctx, MSG_FALSE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 2);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 1);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
context_cleanup(&ctx);
}
static void test_exists(void)
{
static const char SCRIPT[] =
"if exists \"flooglewart\"\n"
"{redirect \"me@blah.com\";}\n"
;
static const char MSG_TRUE[] =
"Date: Mon, 25 Jan 2003 08:51:06 -0500\r\n"
"From: zme@true.com\r\n"
"To: you\r\n"
"Subject: simple address test\r\n"
"Flooglewart: fnarp fmeh oogedyboogedy\r\n"
"\r\n"
"blah\n"
;
static const char MSG_FALSE[] =
"Date: Mon, 25 Jan 2003 08:51:06 -0500\r\n"
"From: yme@false.com\r\n"
"To: you\r\n"
"Subject: simple address test\r\n"
"\r\n"
"blah\n"
;
sieve_test_context_t ctx;
context_setup(&ctx, SCRIPT);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
run_message(&ctx, MSG_TRUE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 1);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 0);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
run_message(&ctx, MSG_FALSE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 2);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 1);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
context_cleanup(&ctx);
}
static void test_address_domain(void)
{
static const char SCRIPT[] =
"if address :domain :is \"from\" \"true.com\"\n"
"{redirect \"me@blah.com\";}\n"
;
static const char MSG_TRUE[] =
"Date: Mon, 25 Jan 2003 08:51:06 -0500\r\n"
"From: zme@true.com\r\n"
"To: you\r\n"
"Subject: simple address test\r\n"
"\r\n"
"blah\n"
;
static const char MSG_FALSE[] =
"Date: Mon, 25 Jan 2003 08:51:06 -0500\r\n"
"From: zme@false.com\r\n"
"To: you\r\n"
"Subject: simple address test\r\n"
"\r\n"
"blah\n"
;
sieve_test_context_t ctx;
context_setup(&ctx, SCRIPT);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
run_message(&ctx, MSG_TRUE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 1);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 0);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
run_message(&ctx, MSG_FALSE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 2);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 1);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
context_cleanup(&ctx);
}
static void test_address_localpart(void)
{
static const char SCRIPT[] =
"if address :localpart :is \"from\" \"zme\"\n"
"{redirect \"me@blah.com\";}\n"
;
static const char MSG_TRUE[] =
"Date: Mon, 25 Jan 2003 08:51:06 -0500\r\n"
"From: zme@true.com\r\n"
"To: you\r\n"
"Subject: simple address test\r\n"
"\r\n"
"blah\n"
;
static const char MSG_FALSE[] =
"Date: Mon, 25 Jan 2003 08:51:06 -0500\r\n"
"From: yme@false.com\r\n"
"To: you\r\n"
"Subject: simple address test\r\n"
"\r\n"
"blah\n"
;
sieve_test_context_t ctx;
context_setup(&ctx, SCRIPT);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
run_message(&ctx, MSG_TRUE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 1);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 0);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
run_message(&ctx, MSG_FALSE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 2);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 1);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
context_cleanup(&ctx);
}
static void test_address_index(void)
{
static const char SCRIPT[] =
"require [\"index\"];\n"
"if address :index 2 :is \"from\" \"zme@true.com\"\n"
"{redirect \"me@blah.com\";}\n"
;
static const char SCRIPT_LAST[] =
"require [\"index\"];\n"
"if address :index 3 :last :is \"from\" \"zme@true.com\"\n"
"{redirect \"me@blah.com\";}\n"
;
static const char MSG_TRUE[] =
"Date: Mon, 25 Jan 2003 08:51:06 -0500\r\n"
"From: zme@false.com\r\n"
"From: zme@true.com\r\n"
"From: zme@false.com\r\n"
"From: zme@false.com\r\n"
"To: you\r\n"
"Subject: simple address test\r\n"
"\r\n"
"blah\n"
;
static const char MSG_FALSE[] =
"Date: Mon, 25 Jan 2003 08:51:06 -0500\r\n"
"From: zme@true.com\r\n"
"From: zme@false.com\r\n"
"From: zme@true.com\r\n"
"From: zme@true.com\r\n"
"To: you\r\n"
"Subject: simple address test\r\n"
"\r\n"
"blah\n"
;
sieve_test_context_t ctx;
/* Test :index */
context_setup(&ctx, SCRIPT);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
run_message(&ctx, MSG_TRUE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 1);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 0);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
run_message(&ctx, MSG_FALSE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 2);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 1);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
context_cleanup(&ctx);
/* Test :index :last */
context_setup(&ctx, SCRIPT_LAST);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
run_message(&ctx, MSG_TRUE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 1);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 0);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
run_message(&ctx, MSG_FALSE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 2);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 1);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
context_cleanup(&ctx);
}
static void test_header_index(void)
{
static const char SCRIPT[] =
"require [\"index\"];\n"
"if header :index 3 :is \"X-Virus-Status\" \"Clean\"\n"
"{redirect \"me@blah.com\";}\n"
;
static const char SCRIPT_LAST[] =
"require [\"index\"];\n"
"if header :index 2 :last :is \"X-Virus-Status\" \"Clean\"\n"
"{redirect \"me@blah.com\";}\n"
;
static const char MSG_TRUE[] =
"Date: Mon, 25 Jan 2003 08:51:06 -0500\r\n"
"From: zme@true.com\r\n"
"To: you\r\n"
"Subject: simple address test\r\n"
"X-Virus-Status: *****\r\n"
"X-Virus-Status: *****\r\n"
"X-Virus-Status: Clean\r\n"
"X-Virus-Status: *****\r\n"
"\r\n"
"blah\n"
;
static const char MSG_FALSE[] =
"Date: Mon, 25 Jan 2003 08:51:06 -0500\r\n"
"From: zme@false.com\r\n"
"To: you\r\n"
"Subject: simple address test\r\n"
"X-Virus-Status: Clean\r\n"
"X-Virus-Status: Clean\r\n"
"X-Virus-Status: *****\r\n"
"X-Virus-Status: Clean\r\n"
"\r\n"
"blah\n"
;
sieve_test_context_t ctx;
/* Test :index */
context_setup(&ctx, SCRIPT);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
run_message(&ctx, MSG_TRUE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 1);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 0);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
run_message(&ctx, MSG_FALSE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 2);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 1);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
context_cleanup(&ctx);
/* Test :index :last */
context_setup(&ctx, SCRIPT_LAST);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
run_message(&ctx, MSG_TRUE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 1);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 0);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
run_message(&ctx, MSG_FALSE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 2);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 1);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
context_cleanup(&ctx);
}
static void test_date_year(void)
{
static const char SCRIPT[] =
"require [\"date\", \"index\"];\n"
"if date :index 1 :last :is \"received\" \"year\" [ \"1983\", \"1993\", \"2003\", \"2013\" ]\n"
"{redirect \"me@blah.com\";}\n"
;
static const char MSG_TRUE[] =
"Date: Sat, 16 Nov 2013 12:46:49 +1100\r\n"
"Received: from localhost (localhost [127.0.0.1])\r\n"
" by mail.com (Cyrus v2.3.16) with LMTPA;\r\n"
" Tue, 16 Nov 2010 12:50:12 +1100\r\n"
"Received: from localhost (localhost [127.0.0.1])\r\n"
" by mail.com (Cyrus v2.3.16) with LMTPA;\r\n"
" Tue, 16 Nov 2013 12:50:12 +1100\r\n"
"From: zme@true.com\r\n"
"To: you\r\n"
"Subject: simple address test\r\n"
"\r\n"
"blah\n"
;
static const char MSG_FALSE[] =
"Date: Tue, 16 Nov 2010 12:46:49 +1100\r\n"
"Received: from localhost (localhost [127.0.0.1])\r\n"
" by mail.com (Cyrus v2.3.16) with LMTPA;\r\n"
" Tue, 16 Nov 2013 12:50:12 +1100\r\n"
"Received: from localhost (localhost [127.0.0.1])\r\n"
" by mail.com (Cyrus v2.3.16) with LMTPA;\r\n"
" Tue, 16 Nov 2010 12:50:12 +1100\r\n"
"From: yme@false.com\r\n"
"To: you\r\n"
"Subject: simple address test\r\n"
"\r\n"
"blah\n"
;
sieve_test_context_t ctx;
context_setup(&ctx, SCRIPT);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
run_message(&ctx, MSG_TRUE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 1);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 0);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
run_message(&ctx, MSG_FALSE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 2);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 1);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
context_cleanup(&ctx);
}
static void test_date_zone_month(void)
{
static const char SCRIPT[] =
"require [\"date\"];\n"
"if date :is :zone \"-0800\" \"date\" \"month\" \"11\"\n"
"{redirect \"me@blah.com\";}\n"
;
static const char MSG_TRUE[] =
"Date: Fri, 1 Nov 2013 19:46:49 +1100\r\n"
"From: zme@true.com\r\n"
"To: you\r\n"
"Subject: simple address test\r\n"
"\r\n"
"blah\n"
;
static const char MSG_FALSE[] =
"Date: Fri, 1 Nov 2013 11:46:49 +1100\r\n"
"From: yme@false.com\r\n"
"To: you\r\n"
"Subject: simple address test\r\n"
"\r\n"
"blah\n"
;
sieve_test_context_t ctx;
context_setup(&ctx, SCRIPT);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
run_message(&ctx, MSG_TRUE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 1);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 0);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
run_message(&ctx, MSG_FALSE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 2);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 1);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
context_cleanup(&ctx);
}
static void test_date_date(void)
{
static const char SCRIPT[] =
"require [\"date\"];\n"
"if date :is :originalzone \"date\" \"date\" \"2013-11-02\"\n"
"{redirect \"me@blah.com\";}\n"
;
static const char MSG_TRUE[] =
"Date: Sat, 2 Nov 2013 19:46:49 +1100\r\n"
"From: zme@true.com\r\n"
"To: you\r\n"
"Subject: simple address test\r\n"
"\r\n"
"blah\n"
;
static const char MSG_FALSE[] =
"Date: Fri, 1 Nov 2013 19:45:49 +1100\r\n"
"From: yme@false.com\r\n"
"To: you\r\n"
"Subject: simple address test\r\n"
"\r\n"
"blah\n"
;
sieve_test_context_t ctx;
context_setup(&ctx, SCRIPT);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
run_message(&ctx, MSG_TRUE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 1);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 0);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
run_message(&ctx, MSG_FALSE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 2);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 1);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
context_cleanup(&ctx);
}
static void test_date_time(void)
{
static const char SCRIPT[] =
"require [\"date\"];\n"
"if date :is :originalzone \"date\" \"time\" \"19:46:49\"\n"
"{redirect \"me@blah.com\";}\n"
;
static const char MSG_TRUE[] =
"Date: Sat, 2 Nov 2013 19:46:49 +1100\r\n"
"From: zme@true.com\r\n"
"To: you\r\n"
"Subject: simple address test\r\n"
"\r\n"
"blah\n"
;
static const char MSG_FALSE[] =
"Date: Sat, 2 Nov 2013 19:45:49 +1100\r\n"
"From: yme@false.com\r\n"
"To: you\r\n"
"Subject: simple address test\r\n"
"\r\n"
"blah\n"
;
sieve_test_context_t ctx;
context_setup(&ctx, SCRIPT);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
run_message(&ctx, MSG_TRUE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 1);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 0);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
run_message(&ctx, MSG_FALSE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 2);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 1);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
context_cleanup(&ctx);
}
static void test_date_originalzone_day(void)
{
static const char SCRIPT[] =
"require [\"date\"];\n"
"if date :is :originalzone \"date\" \"day\" \"16\"\n"
"{redirect \"me@blah.com\";}\n"
;
static const char MSG_TRUE[] =
"Date: Sat, 16 Nov 2013 12:46:49 +1100\r\n"
"From: zme@true.com\r\n"
"To: you\r\n"
"Subject: simple address test\r\n"
"\r\n"
"blah\n"
;
static const char MSG_FALSE[] =
"Date: Fri, 15 Nov 2013 12:46:49 +1100\r\n"
"From: yme@false.com\r\n"
"To: you\r\n"
"Subject: simple address test\r\n"
"\r\n"
"blah\n"
;
sieve_test_context_t ctx;
context_setup(&ctx, SCRIPT);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
run_message(&ctx, MSG_TRUE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 1);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 0);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
run_message(&ctx, MSG_FALSE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 2);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 1);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
context_cleanup(&ctx);
}
static void test_date_weekend_weekday(void)
{
static const char SCRIPT[] =
"require [\"date\"];\n"
"if anyof(date :is :zone \"-0800\" \"date\" \"weekday\" \"0\",\n"
" date :is :zone \"-0800\" \"date\" \"weekday\" \"6\")\n"
"{redirect \"me@blah.com\";}\n"
;
static const char MSG_TRUE[] =
"Date: Sat, 2 Nov 2013 19:46:49 +1100\r\n"
"From: zme@true.com\r\n"
"To: you\r\n"
"Subject: simple address test\r\n"
"\r\n"
"blah\n"
;
static const char MSG_FALSE[] =
"Date: Fri, 1 Nov 2013 11:46:49 +1100\r\n"
"From: yme@false.com\r\n"
"To: you\r\n"
"Subject: simple address test\r\n"
"\r\n"
"blah\n"
;
sieve_test_context_t ctx;
context_setup(&ctx, SCRIPT);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
run_message(&ctx, MSG_TRUE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 1);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 0);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
run_message(&ctx, MSG_FALSE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 2);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 1);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
context_cleanup(&ctx);
}
static void test_date_zone(void)
{
static const char SCRIPT[] =
"require [\"date\"];\n"
"if date :is :originalzone \"date\" \"zone\" \"+1100\"\n"
"{redirect \"me@blah.com\";}\n"
;
static const char MSG_TRUE[] =
"Date: Sat, 2 Nov 2013 19:46:49 +1100\r\n"
"From: zme@true.com\r\n"
"To: you\r\n"
"Subject: simple address test\r\n"
"\r\n"
"blah\n"
;
static const char MSG_FALSE[] =
"Date: Fri, 1 Nov 2013 11:46:49 -0700\r\n"
"From: yme@false.com\r\n"
"To: you\r\n"
"Subject: simple address test\r\n"
"\r\n"
"blah\n"
;
sieve_test_context_t ctx;
context_setup(&ctx, SCRIPT);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
run_message(&ctx, MSG_TRUE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 1);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 0);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
run_message(&ctx, MSG_FALSE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 2);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 1);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
context_cleanup(&ctx);
}
static void test_currentdate_true(void)
{
static const char SCRIPT[] =
"require [\"date\", \"relational\"];\n"
"if allof(currentdate :zone \"+0000\" :value \"ge\" \"date\" \"2014-01-01\",\n"
" currentdate :zone \"+0000\" :value \"le\" \"date\" \"2114-01-01\")\n"
"{redirect \"me@blah.com\";}\n"
;
static const char MSG_TRUE[] =
"Date: Tue, 16 Nov 2010 12:46:49 +1100\r\n"
"From: yme@true.com\r\n"
"To: you\r\n"
"Subject: simple address test\r\n"
"\r\n"
"blah\n"
;
sieve_test_context_t ctx;
context_setup(&ctx, SCRIPT);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
run_message(&ctx, MSG_TRUE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 1);
CU_ASSERT_EQUAL(ctx.stats.redirects, 1);
CU_ASSERT_EQUAL(ctx.stats.keeps, 0);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com");
context_cleanup(&ctx);
}
static void test_currentdate_false(void)
{
static const char SCRIPT[] =
"require [\"date\", \"relational\"];\n"
"if allof(currentdate :zone \"+0000\" :value \"ge\" \"date\" \"1970-01-01\",\n"
" currentdate :zone \"+0000\" :value \"le\" \"date\" \"2014-01-01\")\n"
"{redirect \"me@blah.com\";}\n"
;
static const char MSG_FALSE[] =
"Date: Tue, 16 Nov 2010 12:46:49 +1100\r\n"
"From: yme@false.com\r\n"
"To: you\r\n"
"Subject: simple address test\r\n"
"\r\n"
"blah\n"
;
sieve_test_context_t ctx;
context_setup(&ctx, SCRIPT);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
run_message(&ctx, MSG_FALSE);
CU_ASSERT_EQUAL(ctx.stats.errors, 0);
CU_ASSERT_EQUAL(ctx.stats.actions, 1);
CU_ASSERT_EQUAL(ctx.stats.redirects, 0);
CU_ASSERT_EQUAL(ctx.stats.keeps, 1);
CU_ASSERT_STRING_EQUAL(ctx.redirected_to, NULL);
context_cleanup(&ctx);
}
// TODO: test
// if size :over 10K { redirect "me@blah.com"; }
// TODO: test
// if true {...}
//
// if false {...}
//
// if not false {...}
//
// if true {...} else {...}
//
// if false {...} elsif true {...} else {...}
//
// if false {...} elsif false {...} else {...}
//
// if false {} else {...}
//
// if true { if true { if true { ... } } }
//
// if allof(false, false) {...} else {...}
//
// if allof(false,true) {...} else {...}
//
// if allof(true,false) {...} else {...}
//
// if allof(true,true) {...} else {...}
//
// if anyof(false, false) {...} else {...}
//
// if anyof(false,true) {...} else {...}
//
// if anyof(true,false) {...} else {...}
//
// if anyof(true,true) {...} else {...}
/* vim: set ft=c: */
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Fri, Apr 24, 1:39 PM (1 d, 13 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18870712
Default Alt Text
sieve.testc (46 KB)
Attached To
Mode
R111 cyrus-imapd
Attached
Detach File
Event Timeline