Page MenuHomePhorge

sieve.testc
No OneTemporary

Authored By
Unknown
Size
46 KB
Referenced Files
None
Subscribers
None

sieve.testc

/* 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

Mime Type
text/x-c
Expires
Fri, Apr 24, 1:39 PM (1 d, 14 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18870712
Default Alt Text
sieve.testc (46 KB)

Event Timeline