1/* Unit test for sieve */ 2/* Heavily based on the old sieve/test.c which bore this message: 3 * 4 * - * test.c -- tester for libcyrus_sieve 5 * - * Larry Greenfield 6 * 7 */ 8#include "cunit/cyrunit.h" 9#include <malloc.h> 10#include "sieve/bytecode.h" 11#include "sieve/comparator.h" 12#include "sieve/message.h" 13#include "sieve/sieve_interface.h" 14#include "sieve/variables.h" 15#include "imap/message.h" 16#include "prot.h" 17#include "retry.h" 18#include "imap/spool.h" 19#include "map.h" 20#include "util.h" 21#include "cyrusdb.h" 22#include "libcyr_cfg.h" 23#include "libconfig.h" 24#include "xstrlcat.h" 25#include "xstrlcpy.h" 26#include "xmalloc.h" 27 28#define DBDIR "test-sieve-dbdir" 29#define PARTITION "default" 30 31typedef struct { 32 sieve_interp_t *interp; 33 sieve_execute_t *exe; 34 struct { 35 unsigned int actions; 36 unsigned int errors; 37 unsigned int redirects; 38 unsigned int discards; 39 unsigned int rejects; 40 unsigned int fileintos; 41 unsigned int keeps; 42 unsigned int notifies; 43 unsigned int vaction_responses; 44 } stats; 45 char *redirected_to; 46 char *reject_message; 47 char *filed_mailbox; 48 char *filed_flags; 49 char *notify_method; 50 char *notify_priority; 51 char *notify_options; 52 char *vacation_message; 53 char *vacation_subject; 54 char *vacation_to; 55 char *vacation_from; 56 strarray_t *compile_errors; 57 strarray_t *run_errors; 58 strarray_t *flags; 59} sieve_test_context_t; 60 61typedef struct { 62 const char *text; 63 int length; 64 struct message_content content; 65 hdrcache_t headers; 66 char *filename; 67} sieve_test_message_t; 68 69/* set to SIEVE_DONE if you want to test "already responded */ 70int autorespond_response = SIEVE_OK; 71 72extern int verbose; 73 74static void context_setup(sieve_test_context_t *ctx, 75 const char *script); 76static void context_cleanup(sieve_test_context_t *ctx); 77 78static void test_variable_modifiers(void) 79{ 80 /* 81 Examples: 82 # The value assigned to the variable is printed after the arrow 83 set "a" "juMBlEd lETteRS"; => "juMBlEd lETteRS" 84 set :length "b" "${a}"; => "15" 85 set :lower "b" "${a}"; => "jumbled letters" 86 set :upperfirst "b" "${a}"; => "JuMBlEd lETteRS" 87 set :upperfirst :lower "b" "${a}"; => "Jumbled letters" 88 set :quotewildcard "b" "^Rock*"; => "^Rock\*" 89 set :quoteregex "b" "^Rock*"; => "\^Rock\*" 90 */ 91 const char *a = "juMBlEd lETteRS"; 92 char *b; 93 CU_ASSERT_STRING_EQUAL(a, "juMBlEd lETteRS"); 94 b = variables_modify_string(a, BFV_LENGTH); 95 CU_ASSERT_STRING_EQUAL(b, "15"); 96 free(b); 97 b = variables_modify_string(a, BFV_LOWER); 98 CU_ASSERT_STRING_EQUAL(b, "jumbled letters"); 99 free(b); 100 b = variables_modify_string(a, BFV_UPPERFIRST); 101 CU_ASSERT_STRING_EQUAL(b, "JuMBlEd lETteRS"); 102 free(b); 103 b = variables_modify_string(a, BFV_UPPERFIRST | BFV_LOWER); 104 CU_ASSERT_STRING_EQUAL(b, "Jumbled letters"); 105 free(b); 106 b = variables_modify_string("^Rock*", BFV_QUOTEWILDCARD); 107 CU_ASSERT_STRING_EQUAL(b, "^Rock\\*"); 108 free(b); 109 b = variables_modify_string("^Rock*", BFV_QUOTEREGEX); 110 CU_ASSERT_STRING_EQUAL(b, "\\^Rock\\*"); 111 free(b); 112 b = variables_modify_string("~Rock\\*", BFV_QUOTEWILDCARD | BFV_ENCODEURL); 113 CU_ASSERT_STRING_EQUAL(b, "~Rock%5C%5C%5C%2A"); 114 free(b); 115} 116 117#define TESTCASE(_comp, _mode, _pat, _text, _result) \ 118 comprock = NULL; \ 119 c = lookup_comp(ctx.interp, _comp, _mode, -1, &comprock); \ 120 CU_ASSERT_PTR_NOT_NULL(c); \ 121 if (c) { \ 122 res = c(_text, strlen(_text), _pat, NULL, comprock); \ 123 CU_ASSERT_EQUAL(res, _result); \ 124 } 125 126static void test_comparator(void) 127{ 128 static const char SCRIPT[] = 129 "require [\"comparator-i;ascii-numeric\"];\n" 130 ; 131 sieve_test_context_t ctx; 132 void *comprock; 133 comparator_t *c; 134 int res; 135 136 context_setup(&ctx, SCRIPT); 137 138 TESTCASE( B_OCTET, B_IS, "", "", 1 ); 139 TESTCASE( B_OCTET, B_IS, "a", "", 0 ); 140 TESTCASE( B_OCTET, B_IS, "", "a", 0 ); 141 TESTCASE( B_OCTET, B_IS, "a", "a", 1 ); 142 TESTCASE( B_OCTET, B_IS, "a", "A", 0 ); 143 144 TESTCASE( B_ASCIICASEMAP, B_IS, "", "", 1 ); 145 TESTCASE( B_ASCIICASEMAP, B_IS, "a", "", 0 ); 146 TESTCASE( B_ASCIICASEMAP, B_IS, "", "a", 0 ); 147 TESTCASE( B_ASCIICASEMAP, B_IS, "a", "a", 1 ); 148 TESTCASE( B_ASCIICASEMAP, B_IS, "a", "A", 1 ); 149 150 TESTCASE( B_ASCIINUMERIC, B_IS, "123", "123", 1 ); 151 TESTCASE( B_ASCIINUMERIC, B_IS, "123", "-123", 0 ); 152 TESTCASE( B_ASCIINUMERIC, B_IS, "abc", "123", 0 ); 153 TESTCASE( B_ASCIINUMERIC, B_IS, "abc", "abc", 1 ); 154 TESTCASE( B_ASCIINUMERIC, B_IS, "12345678900", "3755744308", 0 ); /* test for 32bit overflow */ 155 TESTCASE( B_ASCIINUMERIC, B_IS, "1567", "1567pounds", 1 ); 156 TESTCASE( B_ASCIINUMERIC, B_IS, "", "", 1 ); 157 TESTCASE( B_ASCIINUMERIC, B_IS, "123456789", "567", 0 ); 158 TESTCASE( B_ASCIINUMERIC, B_IS, "567", "123456789", 0 ); 159 TESTCASE( B_ASCIINUMERIC, B_IS, "123456789", "00000123456789", 1 ); 160 TESTCASE( B_ASCIINUMERIC, B_IS, "102", "1024", 0 ); 161 TESTCASE( B_ASCIINUMERIC, B_IS, "1567M", "1567 arg", 1 ); 162 163 TESTCASE( B_OCTET, B_CONTAINS, "", "", 1 ); 164 TESTCASE( B_OCTET, B_CONTAINS, "", "a", 1 ); 165 TESTCASE( B_OCTET, B_CONTAINS, "a", "", 0 ); 166 TESTCASE( B_OCTET, B_CONTAINS, "a", "a", 1 ); 167 TESTCASE( B_OCTET, B_CONTAINS, "a", "ab", 1 ); 168 TESTCASE( B_OCTET, B_CONTAINS, "a", "ba", 1 ); 169 TESTCASE( B_OCTET, B_CONTAINS, "a", "aba", 1 ); 170 TESTCASE( B_OCTET, B_CONTAINS, "a", "bab", 1 ); 171 TESTCASE( B_OCTET, B_CONTAINS, "a", "bb", 0 ); 172 TESTCASE( B_OCTET, B_CONTAINS, "a", "bbb", 0 ); 173 174 TESTCASE( B_OCTET, B_MATCHES, "", "", 1 ); 175 TESTCASE( B_OCTET, B_MATCHES, "", "a", 0 ); 176 TESTCASE( B_OCTET, B_MATCHES, "a", "", 0 ); 177 TESTCASE( B_OCTET, B_MATCHES, "a", "a", 1 ); 178 TESTCASE( B_OCTET, B_MATCHES, "a", "ab", 0 ); 179 TESTCASE( B_OCTET, B_MATCHES, "a", "ba", 0 ); 180 TESTCASE( B_OCTET, B_MATCHES, "a", "aba", 0 ); 181 TESTCASE( B_OCTET, B_MATCHES, "a", "bab", 0 ); 182 TESTCASE( B_OCTET, B_MATCHES, "a", "bb", 0 ); 183 TESTCASE( B_OCTET, B_MATCHES, "a", "bbb", 0 ); 184 185 TESTCASE( B_OCTET, B_MATCHES, "*", "", 1 ); 186 TESTCASE( B_OCTET, B_MATCHES, "*", "a", 1 ); 187 TESTCASE( B_OCTET, B_MATCHES, "*a*", "", 0 ); 188 TESTCASE( B_OCTET, B_MATCHES, "*a*", "a", 1 ); 189 TESTCASE( B_OCTET, B_MATCHES, "*a*", "ab", 1 ); 190 TESTCASE( B_OCTET, B_MATCHES, "*a*", "ba", 1 ); 191 TESTCASE( B_OCTET, B_MATCHES, "*a*", "aba", 1 ); 192 TESTCASE( B_OCTET, B_MATCHES, "*a*", "bab", 1 ); 193 TESTCASE( B_OCTET, B_MATCHES, "*a*", "bb", 0 ); 194 TESTCASE( B_OCTET, B_MATCHES, "*a*", "bbb", 0 ); 195 196 TESTCASE( B_OCTET, B_MATCHES, "*a", "", 0 ); 197 TESTCASE( B_OCTET, B_MATCHES, "*a", "a", 1 ); 198 TESTCASE( B_OCTET, B_MATCHES, "*a", "ab", 0 ); 199 TESTCASE( B_OCTET, B_MATCHES, "*a", "ba", 1 ); 200 TESTCASE( B_OCTET, B_MATCHES, "*a", "aba", 1 ); 201 TESTCASE( B_OCTET, B_MATCHES, "*a", "bab", 0 ); 202 TESTCASE( B_OCTET, B_MATCHES, "*a", "bb", 0 ); 203 TESTCASE( B_OCTET, B_MATCHES, "*a", "bbb", 0 ); 204 205 TESTCASE( B_OCTET, B_MATCHES, "a*", "", 0 ); 206 TESTCASE( B_OCTET, B_MATCHES, "a*", "a", 1 ); 207 TESTCASE( B_OCTET, B_MATCHES, "a*", "ab", 1 ); 208 TESTCASE( B_OCTET, B_MATCHES, "a*", "ba", 0 ); 209 TESTCASE( B_OCTET, B_MATCHES, "a*", "aba", 1 ); 210 TESTCASE( B_OCTET, B_MATCHES, "a*", "bab", 0 ); 211 TESTCASE( B_OCTET, B_MATCHES, "a*", "bb", 0 ); 212 TESTCASE( B_OCTET, B_MATCHES, "a*", "bbb", 0 ); 213 214 TESTCASE( B_OCTET, B_MATCHES, "a*b", "", 0 ); 215 TESTCASE( B_OCTET, B_MATCHES, "a*b", "a", 0 ); 216 TESTCASE( B_OCTET, B_MATCHES, "a*b", "ab", 1 ); 217 TESTCASE( B_OCTET, B_MATCHES, "a*b", "ba", 0 ); 218 TESTCASE( B_OCTET, B_MATCHES, "a*b", "aba", 0 ); 219 TESTCASE( B_OCTET, B_MATCHES, "a*b", "bab", 0 ); 220 TESTCASE( B_OCTET, B_MATCHES, "a*b", "bb", 0 ); 221 TESTCASE( B_OCTET, B_MATCHES, "a*b", "bbb", 0 ); 222 TESTCASE( B_OCTET, B_MATCHES, "a*b", "abbb", 1 ); 223 TESTCASE( B_OCTET, B_MATCHES, "a*b", "acb", 1 ); 224 TESTCASE( B_OCTET, B_MATCHES, "a*b", "acbc", 0 ); 225 226 TESTCASE( B_OCTET, B_MATCHES, "a?b", "", 0 ); 227 TESTCASE( B_OCTET, B_MATCHES, "a?b", "a", 0 ); 228 TESTCASE( B_OCTET, B_MATCHES, "a?b", "ab", 0 ); 229 TESTCASE( B_OCTET, B_MATCHES, "a?b", "ba", 0 ); 230 TESTCASE( B_OCTET, B_MATCHES, "a?b", "aba", 0 ); 231 TESTCASE( B_OCTET, B_MATCHES, "a?b", "bab", 0 ); 232 TESTCASE( B_OCTET, B_MATCHES, "a?b", "bb", 0 ); 233 TESTCASE( B_OCTET, B_MATCHES, "a?b", "bbb", 0 ); 234 TESTCASE( B_OCTET, B_MATCHES, "a?b", "abbb", 0 ); 235 TESTCASE( B_OCTET, B_MATCHES, "a?b", "acb", 1 ); 236 TESTCASE( B_OCTET, B_MATCHES, "a?b", "acbc", 0 ); 237 238 TESTCASE( B_OCTET, B_MATCHES, "a*?b", "", 0 ); 239 TESTCASE( B_OCTET, B_MATCHES, "a*?b", "a", 0 ); 240 TESTCASE( B_OCTET, B_MATCHES, "a*?b", "ab", 0 ); 241 TESTCASE( B_OCTET, B_MATCHES, "a*?b", "ba", 0 ); 242 TESTCASE( B_OCTET, B_MATCHES, "a*?b", "aba", 0 ); 243 TESTCASE( B_OCTET, B_MATCHES, "a*?b", "bab", 0 ); 244 TESTCASE( B_OCTET, B_MATCHES, "a*?b", "bb", 0 ); 245 TESTCASE( B_OCTET, B_MATCHES, "a*?b", "bbb", 0 ); 246 TESTCASE( B_OCTET, B_MATCHES, "a*?b", "abbb", 1 ); 247 TESTCASE( B_OCTET, B_MATCHES, "a*?b", "acb", 1 ); 248 TESTCASE( B_OCTET, B_MATCHES, "a*?b", "acbc", 0 ); 249 250 TESTCASE( B_OCTET, B_MATCHES, "a?*b", "", 0 ); 251 TESTCASE( B_OCTET, B_MATCHES, "a?*b", "a", 0 ); 252 TESTCASE( B_OCTET, B_MATCHES, "a?*b", "ab", 0 ); 253 TESTCASE( B_OCTET, B_MATCHES, "a?*b", "ba", 0 ); 254 TESTCASE( B_OCTET, B_MATCHES, "a?*b", "aba", 0 ); 255 TESTCASE( B_OCTET, B_MATCHES, "a?*b", "bab", 0 ); 256 TESTCASE( B_OCTET, B_MATCHES, "a?*b", "bb", 0 ); 257 TESTCASE( B_OCTET, B_MATCHES, "a?*b", "bbb", 0 ); 258 TESTCASE( B_OCTET, B_MATCHES, "a?*b", "abbb", 1 ); 259 TESTCASE( B_OCTET, B_MATCHES, "a?*b", "acb", 1 ); 260 TESTCASE( B_OCTET, B_MATCHES, "a?*b", "acbc", 0 ); 261 262 TESTCASE( B_OCTET, B_MATCHES, "a*?*b", "", 0 ); 263 TESTCASE( B_OCTET, B_MATCHES, "a*?*b", "a", 0 ); 264 TESTCASE( B_OCTET, B_MATCHES, "a*?*b", "ab", 0 ); 265 TESTCASE( B_OCTET, B_MATCHES, "a*?*b", "ba", 0 ); 266 TESTCASE( B_OCTET, B_MATCHES, "a*?*b", "aba", 0 ); 267 TESTCASE( B_OCTET, B_MATCHES, "a*?*b", "bab", 0 ); 268 TESTCASE( B_OCTET, B_MATCHES, "a*?*b", "bb", 0 ); 269 TESTCASE( B_OCTET, B_MATCHES, "a*?*b", "bbb", 0 ); 270 TESTCASE( B_OCTET, B_MATCHES, "a*?*b", "abbb", 1 ); 271 TESTCASE( B_OCTET, B_MATCHES, "a*?*b", "acb", 1 ); 272 TESTCASE( B_OCTET, B_MATCHES, "a*?*b?", "acbc", 1 ); 273 274 TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "", 0 ); 275 TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "a", 0 ); 276 TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "ab", 1 ); 277 TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "ba", 0 ); 278 TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "aba", 0 ); 279 TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "bab", 0 ); 280 TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "bb", 0 ); 281 TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "bbb", 0 ); 282 TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "abbb", 1 ); 283 TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "acb", 1 ); 284 TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "acbc", 0 ); 285 286 TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "", 0 ); 287 TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "A", 0 ); 288 TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "Ab", 1 ); 289 TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "BA", 0 ); 290 TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "ABA", 0 ); 291 TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "BAb", 0 ); 292 TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "BB", 0 ); 293 TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "BBB", 0 ); 294 TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "aBBB", 1 ); 295 TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "ACB", 1 ); 296 TESTCASE( B_ASCIICASEMAP, B_MATCHES, "a*b", "ACBC", 0 ); 297 298 context_cleanup(&ctx); 299} 300 301 302/* gets the header "head" from msg. */ 303static int getheader(void *mc, const char *name, const char ***body) 304{ 305 sieve_test_message_t *msg = (sieve_test_message_t *)mc; 306 307 *body = spool_getheader(msg->headers, name); 308 if (!*body) 309 return SIEVE_FAIL; 310 return SIEVE_OK; 311} 312 313static int getsize(void *mc, int *size) 314{ 315 sieve_test_message_t *msg = (sieve_test_message_t *)mc; 316 317 *size = msg->length; 318 return SIEVE_OK; 319} 320 321static int getbody(void *mc, const char **content_types, sieve_bodypart_t ***parts) 322{ 323 sieve_test_message_t *msg = (sieve_test_message_t *)mc; 324 int r = 0; 325 326 if (!msg->content.body) { 327 /* parse the message body if we haven't already */ 328 FILE *fp = fopen(msg->filename, "r"); 329 CU_ASSERT_PTR_NOT_NULL(fp); 330 r = message_parse_file_buf(fp, 331 &msg->content.map, 332 &msg->content.body, 333 msg->filename); 334 CU_ASSERT_EQUAL(r, 0); 335 fclose(fp); 336 } 337 338 /* XXX currently struct bodypart as defined in message.h is the same as 339 sieve_bodypart_t as defined in sieve_interface.h, so we can typecast */ 340 if (!r) 341 message_fetch_part(&msg->content, content_types, 342 (struct bodypart ***) parts); 343 344 if (r) 345 return SIEVE_FAIL; 346 return SIEVE_OK; 347} 348 349static int getinclude(void *sc __attribute__((unused)), 350 const char *script, 351 int isglobal __attribute__((unused)), 352 char *fpath, size_t size) 353{ 354 strlcpy(fpath, script, size); 355 strlcat(fpath, ".bc", size); 356 return SIEVE_OK; 357} 358 359static int redirect(void *ac, void *ic, void *sc __attribute__((unused)), 360 void *mc __attribute__((unused)), 361 const char **errmsg __attribute__((unused))) 362{ 363 sieve_redirect_context_t *rc = (sieve_redirect_context_t *)ac; 364 sieve_test_context_t *ctx = (sieve_test_context_t *)ic; 365 366 ctx->stats.actions++; 367 ctx->stats.redirects++; 368 free(ctx->redirected_to); 369 ctx->redirected_to = xstrdup(rc->addr); 370 371 /* TODO: test returning SIEVE_FAIL */ 372 return SIEVE_OK; 373} 374 375static int discard(void *ac __attribute__((unused)), 376 void *ic, void *sc __attribute__((unused)), 377 void *mc __attribute__((unused)), 378 const char **errmsg __attribute__((unused))) 379{ 380 sieve_test_context_t *ctx = (sieve_test_context_t *)ic; 381 382 ctx->stats.actions++; 383 ctx->stats.discards++; 384 385 /* TODO: test returning SIEVE_FAIL */ 386 return SIEVE_OK; 387} 388 389static int reject(void *ac, void *ic, void *sc __attribute__((unused)), 390 void *mc __attribute__((unused)), 391 const char **errmsg __attribute__((unused))) 392{ 393 sieve_reject_context_t *rc = (sieve_reject_context_t *)ac; 394 sieve_test_context_t *ctx = (sieve_test_context_t *)ic; 395 396 ctx->stats.actions++; 397 ctx->stats.rejects++; 398 free(ctx->reject_message); 399 ctx->reject_message = xstrdup(rc->msg); 400 401 /* TODO: test returning SIEVE_FAIL */ 402 return SIEVE_OK; 403} 404 405static int fileinto(void *ac, void *ic, void *sc __attribute__((unused)), 406 void *mc, 407 const char **errmsg __attribute__((unused))) 408{ 409 sieve_fileinto_context_t *fc = (sieve_fileinto_context_t *)ac; 410 sieve_test_context_t *ctx = (sieve_test_context_t *)ic; 411 412 if (!mc) { 413 /* just doing destination mailbox resolution */ 414 return SIEVE_OK; 415 } 416 417 ctx->stats.actions++; 418 ctx->stats.fileintos++; 419 free(ctx->filed_mailbox); 420 ctx->filed_mailbox = xstrdup(fc->mailbox); 421 free(ctx->filed_flags); 422 ctx->filed_flags = strarray_join(fc->imapflags, " "); 423 strarray_free(ctx->flags); 424 ctx->flags = strarray_dup(fc->imapflags); 425 426 /* TODO: test returning SIEVE_FAIL */ 427 return SIEVE_OK; 428} 429 430static int keep(void *ac, void *ic, void *sc __attribute__((unused)), 431 void *mc, 432 const char **errmsg __attribute__((unused))) 433{ 434 sieve_keep_context_t *kc = (sieve_keep_context_t *)ac; 435 sieve_test_context_t *ctx = (sieve_test_context_t *)ic; 436 437 if (!mc) { 438 /* just doing destination mailbox resolution */ 439 return SIEVE_OK; 440 } 441 442 ctx->stats.actions++; 443 ctx->stats.keeps++; 444 free(ctx->filed_flags); 445 ctx->filed_flags = strarray_join(kc->imapflags, " "); 446 strarray_free(ctx->flags); 447 ctx->flags = strarray_dup(kc->imapflags); 448 449 /* TODO: test returning SIEVE_FAIL */ 450 return SIEVE_OK; 451} 452 453static int notify(void *ac, void *ic, void *sc __attribute__((unused)), 454 void *mc __attribute__((unused)), 455 const char **errmsg __attribute__((unused))) 456{ 457 sieve_notify_context_t *nc = (sieve_notify_context_t *)ac; 458 sieve_test_context_t *ctx = (sieve_test_context_t *)ic; 459 struct buf opts = BUF_INITIALIZER; 460 int i; 461 462 for (i = 0; i < strarray_size(nc->options); i++) { 463 if (opts.len) 464 buf_putc(&opts, ' '); 465 buf_appendcstr(&opts, strarray_nth(nc->options, i)); 466 } 467 468 ctx->stats.actions++; 469 ctx->stats.notifies++; 470 free(ctx->notify_options); 471 ctx->notify_options = buf_release(&opts); 472 free(ctx->notify_method); 473 ctx->notify_method = xstrdup(nc->method); 474 free(ctx->notify_priority); 475 ctx->notify_method = xstrdup(nc->priority); 476 477 /* TODO: test returning SIEVE_FAIL */ 478 return SIEVE_OK; 479} 480 481static int mysieve_error(int lineno, const char *msg, 482 void *ic, 483 void *sc __attribute__((unused))) 484{ 485 sieve_test_context_t *ctx = (sieve_test_context_t *)ic; 486 struct buf buf = BUF_INITIALIZER; 487 488 ctx->stats.errors++; 489 buf_printf(&buf, "line %d: %s", lineno, msg); 490 strarray_appendm(ctx->compile_errors, buf_release(&buf)); 491 492 return SIEVE_OK; 493} 494 495static int mysieve_execute_error(const char *msg, 496 void *ic, 497 void *sc __attribute__((unused)), 498 void *mc __attribute__((unused))) 499{ 500 sieve_test_context_t *ctx = (sieve_test_context_t *)ic; 501 502 ctx->stats.errors++; 503 strarray_append(ctx->run_errors, msg); 504 505 return SIEVE_OK; 506} 507 508static int autorespond(void *ac __attribute__((unused)), 509 void *ic __attribute__((unused)), 510 void *sc __attribute__((unused)), 511 void *mc __attribute__((unused)), 512 const char **errmsg __attribute__((unused))) 513{ 514 return autorespond_response; 515} 516 517static int send_response(void *ac, void *ic, void *sc __attribute__((unused)), 518 void *mc __attribute__((unused)), 519 const char **errmsg __attribute__((unused))) 520{ 521 sieve_send_response_context_t *src = (sieve_send_response_context_t *)ac; 522 sieve_test_context_t *ctx = (sieve_test_context_t *)ic; 523 524 ctx->stats.actions++; 525 ctx->stats.vaction_responses++; 526 free(ctx->vacation_message); 527 ctx->vacation_message = xstrdup(src->msg); 528 free(ctx->vacation_subject); 529 ctx->vacation_subject = xstrdup(src->subj); 530 free(ctx->vacation_to); 531 ctx->vacation_to = xstrdup(src->addr); 532 free(ctx->vacation_from); 533 ctx->vacation_from = xstrdup(src->fromaddr); 534 535 /* TODO: test returning SIEVE_FAIL */ 536 return SIEVE_OK; 537} 538 539#ifndef HAVE_FMEMOPEN 540static FILE *fmemopen(const void *buf, size_t len, const char *mode) 541{ 542 FILE *fp; 543 544 fp = fopen("/dev/null", mode); 545 if (!fp) 546 return NULL; 547 setbuffer(fp, buf, len); 548 return fp; 549} 550#endif 551 552static int set_up(void) 553{ 554 libcyrus_config_setstring(CYRUSOPT_CONFIG_DIR, DBDIR); 555 config_read_string( 556 "configdirectory: "DBDIR"/conf\n" 557 "defaultpartition: "PARTITION"\n" 558 "partition-"PARTITION": "DBDIR"/data\n" 559 "sievenotifier: mailto\n" 560 "sieve_extensions: fileinto reject vacation imapflags notify" \ 561 " envelope body relational regex subaddress copy date index" \ 562 " imap4flags variables\n" 563 ); 564 libcyrus_init(); 565 return 0; 566} 567 568static int tear_down(void) 569{ 570 int r; 571 572 libcyrus_done(); 573 config_reset(); 574 575 r = system("rm -rf " DBDIR); 576 577 return r; 578} 579 580static void context_setup(sieve_test_context_t *ctx, 581 const char *script) 582{ 583 int r; 584 static sieve_vacation_t vacation = { 585 0, /* min response */ 586 0, /* max response */ 587 &autorespond, /* autorespond() */ 588 &send_response /* send_response() */ 589 }; 590 char *errors = NULL; 591 int fd; 592 sieve_script_t *scr = NULL; 593 bytecode_info_t *bytecode = NULL; 594 char tempfile[32]; 595 596 memset(ctx, 0, sizeof(*ctx)); 597 598 ctx->compile_errors = strarray_new(); 599 ctx->run_errors = strarray_new(); 600 601 ctx->interp = sieve_interp_alloc(ctx); 602 sieve_register_redirect(ctx->interp, redirect); 603 sieve_register_discard(ctx->interp, discard); 604 sieve_register_reject(ctx->interp, reject); 605 sieve_register_fileinto(ctx->interp, fileinto); 606 sieve_register_keep(ctx->interp, keep); 607 sieve_register_size(ctx->interp, getsize); 608 sieve_register_header(ctx->interp, getheader); 609 sieve_register_envelope(ctx->interp, getheader); 610 sieve_register_body(ctx->interp, getbody); 611 sieve_register_include(ctx->interp, getinclude); 612 sieve_register_vacation(ctx->interp, &vacation); 613 sieve_register_notify(ctx->interp, notify, NULL); 614 sieve_register_parse_error(ctx->interp, mysieve_error); 615 sieve_register_execute_error(ctx->interp, mysieve_execute_error); 616 617 r = sieve_script_parse_string(ctx->interp, script, &errors, &scr); 618 CU_ASSERT_EQUAL(r, SIEVE_OK); 619 free(errors); 620 621 r = sieve_generate_bytecode(&bytecode, scr); 622 CU_ASSERT(r > 0); 623 strcpy(tempfile, "/tmp/sievetest-BC-XXXXXX"); 624 fd = mkstemp(tempfile); 625 CU_ASSERT(fd >= 0); 626 r = sieve_emit_bytecode(fd, bytecode); 627 CU_ASSERT(r > 0); 628 sieve_free_bytecode(&bytecode); 629 sieve_script_free(&scr); 630 631 /* Now load the compiled bytecode */ 632 r = sieve_script_load(tempfile, &ctx->exe); 633 CU_ASSERT_EQUAL(r, SIEVE_OK); 634 unlink(tempfile); 635} 636 637static void context_cleanup(sieve_test_context_t *ctx) 638{ 639 int r; 640 641 if (verbose > 1) { 642 int i; 643 644 fprintf(stderr, "sieve test context\n"); 645 fprintf(stderr, " actions: %u\n", ctx->stats.actions); 646 fprintf(stderr, " errors: %u\n", ctx->stats.errors); 647 fprintf(stderr, " redirects: %u\n", ctx->stats.redirects); 648 fprintf(stderr, " discards: %u\n", ctx->stats.discards); 649 fprintf(stderr, " rejects: %u\n", ctx->stats.rejects); 650 fprintf(stderr, " fileintos: %u\n", ctx->stats.fileintos); 651 fprintf(stderr, " keeps: %u\n", ctx->stats.keeps); 652 fprintf(stderr, " notifies: %u\n", ctx->stats.notifies); 653 fprintf(stderr, " vaction_responses: %u\n", ctx->stats.vaction_responses); 654 if (ctx->redirected_to) 655 fprintf(stderr, " redirected_to: %s\n", ctx->redirected_to); 656 if (ctx->reject_message) 657 fprintf(stderr, " reject_message: %s\n", ctx->reject_message); 658 if (ctx->filed_mailbox) 659 fprintf(stderr, " filed_mailbox: %s\n", ctx->filed_mailbox); 660 if (ctx->filed_flags) 661 fprintf(stderr, " filed_flags: %s\n", ctx->filed_flags); 662 if (ctx->notify_method) 663 fprintf(stderr, " notify_method: %s\n", ctx->notify_method); 664 if (ctx->notify_priority) 665 fprintf(stderr, " notify_priority: %s\n", ctx->notify_priority); 666 if (ctx->notify_options) 667 fprintf(stderr, " notify_options: %s\n", ctx->notify_options); 668 if (ctx->vacation_message) 669 fprintf(stderr, " vacation_message: %s\n", ctx->vacation_message); 670 if (ctx->vacation_subject) 671 fprintf(stderr, " vacation_subject: %s\n", ctx->vacation_subject); 672 if (ctx->vacation_to) 673 fprintf(stderr, " vacation_to: %s\n", ctx->vacation_to); 674 if (ctx->vacation_from) 675 fprintf(stderr, " vacation_from: %s\n", ctx->vacation_from); 676 if (ctx->compile_errors->count) { 677 fprintf(stderr, " compile_errors:\n"); 678 for (i = 0 ; i < ctx->compile_errors->count ; i++) 679 fprintf(stderr, "\t[%d] %s\n", i, ctx->compile_errors->data[i]); 680 } 681 if (ctx->run_errors->count) { 682 fprintf(stderr, " run_errors:\n"); 683 for (i = 0 ; i < ctx->run_errors->count ; i++) 684 fprintf(stderr, "\t[%d] %s\n", i, ctx->run_errors->data[i]); 685 } 686 } 687 688 /*used to be sieve_script_free*/ 689 r = sieve_script_unload(&ctx->exe); 690 CU_ASSERT_EQUAL(r, SIEVE_OK); 691 CU_ASSERT_PTR_NULL(ctx->exe); 692 693 r = sieve_interp_free(&ctx->interp); 694 CU_ASSERT_EQUAL(r, SIEVE_OK); 695 696 free(ctx->redirected_to); 697 free(ctx->reject_message); 698 free(ctx->filed_mailbox); 699 free(ctx->filed_flags); 700 free(ctx->notify_method); 701 free(ctx->notify_priority); 702 free(ctx->notify_options); 703 free(ctx->vacation_message); 704 free(ctx->vacation_subject); 705 free(ctx->vacation_to); 706 free(ctx->vacation_from); 707 strarray_free(ctx->compile_errors); 708 strarray_free(ctx->run_errors); 709 strarray_free(ctx->flags); 710} 711 712 713static sieve_test_message_t *sieve_test_message_new(const char *text, int len) 714{ 715 sieve_test_message_t *msg; 716 struct protstream *pin; 717 FILE *fout; 718 int fd; 719 int r; 720 char tempfile[32]; 721 722 msg = xzmalloc(sizeof(sieve_test_message_t)); 723 msg->text = text; 724 msg->length = len; 725 msg->headers = spool_new_hdrcache(); 726 727 strcpy(tempfile, "/tmp/sievetest-MS-XXXXXX"); 728 fd = mkstemp(tempfile); 729 CU_ASSERT(fd >= 0); 730 msg->filename = xstrdup(tempfile); 731 r = retry_write(fd, text, len); 732 CU_ASSERT_EQUAL(r, len); 733 lseek(fd, SEEK_SET, 0); 734 735 pin = prot_new(fd, /*read*/0); 736 CU_ASSERT_PTR_NOT_NULL(pin); 737 738 fout = fopen("/dev/null", "w"); 739 CU_ASSERT_PTR_NOT_NULL(fout); 740 741 r = spool_fill_hdrcache(pin, fout, msg->headers, NULL); 742 CU_ASSERT_EQUAL(r, 0); 743 744 fclose(fout); 745 prot_free(pin); 746 747 return msg; 748} 749 750static void message_free(sieve_test_message_t *msg) 751{ 752 spool_free_hdrcache(msg->headers); 753 if (msg->content.body) 754 message_free_body(msg->content.body); 755 buf_free(&msg->content.map); 756 unlink(msg->filename); 757 free(msg->filename); 758 free(msg); 759} 760 761 762static void run_message(sieve_test_context_t *ctx, 763 const char *text) 764{ 765 sieve_test_message_t *msg; 766 int r; 767 768 msg = sieve_test_message_new(text, strlen(text)); 769 CU_ASSERT_PTR_NOT_NULL(msg); 770 771 r = sieve_execute_bytecode(ctx->exe, ctx->interp, ctx, msg); 772 CU_ASSERT_EQUAL(r, SIEVE_OK); 773 774 message_free(msg); 775} 776 777static void test_address_all(void) 778{ 779 static const char SCRIPT_IS[] = 780 "if address :all :is \"from\" \"zme@true.com\"\n" 781 "{redirect \"me@blah.com\";}\n" 782 ; 783 static const char SCRIPT_CONTAINS[] = 784 "if address :all :contains \"from\" \"true.com\"\n" 785 "{redirect \"me@blah.com\";}\n" 786 ; 787 static const char SCRIPT_MATCHES[] = 788 "if address :all :matches \"from\" \"*true.com\"\n" 789 "{redirect \"me@blah.com\";}\n" 790 ; 791 792 static const char MSG_TRUE[] = 793 "Date: Mon, 25 Jan 2003 08:51:06 -0500\r\n" 794 "From: zme@true.com\r\n" 795 "To: you\r\n" 796 "Subject: simple address test\r\n" 797 "\r\n" 798 "blah\n" 799 ; 800 static const char MSG_FALSE[] = 801 "Date: Mon, 25 Jan 2003 08:51:06 -0500\r\n" 802 "From: zme@false.com\r\n" 803 "To: you\r\n" 804 "Subject: simple address test\r\n" 805 "\r\n" 806 "blah\n" 807 ; 808 sieve_test_context_t ctx; 809 810 /* Test :is */ 811 context_setup(&ctx, SCRIPT_IS); 812 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 813 814 run_message(&ctx, MSG_TRUE); 815 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 816 CU_ASSERT_EQUAL(ctx.stats.actions, 1); 817 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 818 CU_ASSERT_EQUAL(ctx.stats.keeps, 0); 819 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 820 821 run_message(&ctx, MSG_FALSE); 822 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 823 CU_ASSERT_EQUAL(ctx.stats.actions, 2); 824 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 825 CU_ASSERT_EQUAL(ctx.stats.keeps, 1); 826 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 827 828 context_cleanup(&ctx); 829 830 /* Test :contains */ 831 context_setup(&ctx, SCRIPT_CONTAINS); 832 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 833 834 run_message(&ctx, MSG_TRUE); 835 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 836 CU_ASSERT_EQUAL(ctx.stats.actions, 1); 837 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 838 CU_ASSERT_EQUAL(ctx.stats.keeps, 0); 839 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 840 841 run_message(&ctx, MSG_FALSE); 842 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 843 CU_ASSERT_EQUAL(ctx.stats.actions, 2); 844 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 845 CU_ASSERT_EQUAL(ctx.stats.keeps, 1); 846 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 847 848 context_cleanup(&ctx); 849 850 /* Test :matches */ 851 context_setup(&ctx, SCRIPT_MATCHES); 852 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 853 854 run_message(&ctx, MSG_TRUE); 855 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 856 CU_ASSERT_EQUAL(ctx.stats.actions, 1); 857 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 858 CU_ASSERT_EQUAL(ctx.stats.keeps, 0); 859 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 860 861 run_message(&ctx, MSG_FALSE); 862 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 863 CU_ASSERT_EQUAL(ctx.stats.actions, 2); 864 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 865 CU_ASSERT_EQUAL(ctx.stats.keeps, 1); 866 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 867 868 context_cleanup(&ctx); 869} 870 871static void test_exists(void) 872{ 873 static const char SCRIPT[] = 874 "if exists \"flooglewart\"\n" 875 "{redirect \"me@blah.com\";}\n" 876 ; 877 static const char MSG_TRUE[] = 878 "Date: Mon, 25 Jan 2003 08:51:06 -0500\r\n" 879 "From: zme@true.com\r\n" 880 "To: you\r\n" 881 "Subject: simple address test\r\n" 882 "Flooglewart: fnarp fmeh oogedyboogedy\r\n" 883 "\r\n" 884 "blah\n" 885 ; 886 static const char MSG_FALSE[] = 887 "Date: Mon, 25 Jan 2003 08:51:06 -0500\r\n" 888 "From: yme@false.com\r\n" 889 "To: you\r\n" 890 "Subject: simple address test\r\n" 891 "\r\n" 892 "blah\n" 893 ; 894 sieve_test_context_t ctx; 895 896 context_setup(&ctx, SCRIPT); 897 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 898 899 run_message(&ctx, MSG_TRUE); 900 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 901 CU_ASSERT_EQUAL(ctx.stats.actions, 1); 902 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 903 CU_ASSERT_EQUAL(ctx.stats.keeps, 0); 904 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 905 906 run_message(&ctx, MSG_FALSE); 907 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 908 CU_ASSERT_EQUAL(ctx.stats.actions, 2); 909 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 910 CU_ASSERT_EQUAL(ctx.stats.keeps, 1); 911 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 912 913 context_cleanup(&ctx); 914} 915 916static void test_address_domain(void) 917{ 918 static const char SCRIPT[] = 919 "if address :domain :is \"from\" \"true.com\"\n" 920 "{redirect \"me@blah.com\";}\n" 921 ; 922 static const char MSG_TRUE[] = 923 "Date: Mon, 25 Jan 2003 08:51:06 -0500\r\n" 924 "From: zme@true.com\r\n" 925 "To: you\r\n" 926 "Subject: simple address test\r\n" 927 "\r\n" 928 "blah\n" 929 ; 930 static const char MSG_FALSE[] = 931 "Date: Mon, 25 Jan 2003 08:51:06 -0500\r\n" 932 "From: zme@false.com\r\n" 933 "To: you\r\n" 934 "Subject: simple address test\r\n" 935 "\r\n" 936 "blah\n" 937 ; 938 sieve_test_context_t ctx; 939 940 context_setup(&ctx, SCRIPT); 941 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 942 943 run_message(&ctx, MSG_TRUE); 944 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 945 CU_ASSERT_EQUAL(ctx.stats.actions, 1); 946 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 947 CU_ASSERT_EQUAL(ctx.stats.keeps, 0); 948 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 949 950 run_message(&ctx, MSG_FALSE); 951 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 952 CU_ASSERT_EQUAL(ctx.stats.actions, 2); 953 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 954 CU_ASSERT_EQUAL(ctx.stats.keeps, 1); 955 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 956 957 context_cleanup(&ctx); 958} 959 960static void test_address_localpart(void) 961{ 962 static const char SCRIPT[] = 963 "if address :localpart :is \"from\" \"zme\"\n" 964 "{redirect \"me@blah.com\";}\n" 965 ; 966 static const char MSG_TRUE[] = 967 "Date: Mon, 25 Jan 2003 08:51:06 -0500\r\n" 968 "From: zme@true.com\r\n" 969 "To: you\r\n" 970 "Subject: simple address test\r\n" 971 "\r\n" 972 "blah\n" 973 ; 974 static const char MSG_FALSE[] = 975 "Date: Mon, 25 Jan 2003 08:51:06 -0500\r\n" 976 "From: yme@false.com\r\n" 977 "To: you\r\n" 978 "Subject: simple address test\r\n" 979 "\r\n" 980 "blah\n" 981 ; 982 sieve_test_context_t ctx; 983 984 context_setup(&ctx, SCRIPT); 985 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 986 987 run_message(&ctx, MSG_TRUE); 988 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 989 CU_ASSERT_EQUAL(ctx.stats.actions, 1); 990 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 991 CU_ASSERT_EQUAL(ctx.stats.keeps, 0); 992 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 993 994 run_message(&ctx, MSG_FALSE); 995 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 996 CU_ASSERT_EQUAL(ctx.stats.actions, 2); 997 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 998 CU_ASSERT_EQUAL(ctx.stats.keeps, 1); 999 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 1000 1001 context_cleanup(&ctx); 1002} 1003 1004static void test_address_index(void) 1005{ 1006 static const char SCRIPT[] = 1007 "require [\"index\"];\n" 1008 "if address :index 2 :is \"from\" \"zme@true.com\"\n" 1009 "{redirect \"me@blah.com\";}\n" 1010 ; 1011 1012 static const char SCRIPT_LAST[] = 1013 "require [\"index\"];\n" 1014 "if address :index 3 :last :is \"from\" \"zme@true.com\"\n" 1015 "{redirect \"me@blah.com\";}\n" 1016 ; 1017 1018 static const char MSG_TRUE[] = 1019 "Date: Mon, 25 Jan 2003 08:51:06 -0500\r\n" 1020 "From: zme@false.com\r\n" 1021 "From: zme@true.com\r\n" 1022 "From: zme@false.com\r\n" 1023 "From: zme@false.com\r\n" 1024 "To: you\r\n" 1025 "Subject: simple address test\r\n" 1026 "\r\n" 1027 "blah\n" 1028 ; 1029 static const char MSG_FALSE[] = 1030 "Date: Mon, 25 Jan 2003 08:51:06 -0500\r\n" 1031 "From: zme@true.com\r\n" 1032 "From: zme@false.com\r\n" 1033 "From: zme@true.com\r\n" 1034 "From: zme@true.com\r\n" 1035 "To: you\r\n" 1036 "Subject: simple address test\r\n" 1037 "\r\n" 1038 "blah\n" 1039 ; 1040 sieve_test_context_t ctx; 1041 1042 /* Test :index */ 1043 context_setup(&ctx, SCRIPT); 1044 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1045 1046 run_message(&ctx, MSG_TRUE); 1047 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1048 CU_ASSERT_EQUAL(ctx.stats.actions, 1); 1049 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 1050 CU_ASSERT_EQUAL(ctx.stats.keeps, 0); 1051 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 1052 1053 run_message(&ctx, MSG_FALSE); 1054 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1055 CU_ASSERT_EQUAL(ctx.stats.actions, 2); 1056 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 1057 CU_ASSERT_EQUAL(ctx.stats.keeps, 1); 1058 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 1059 1060 context_cleanup(&ctx); 1061 1062 /* Test :index :last */ 1063 context_setup(&ctx, SCRIPT_LAST); 1064 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1065 1066 run_message(&ctx, MSG_TRUE); 1067 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1068 CU_ASSERT_EQUAL(ctx.stats.actions, 1); 1069 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 1070 CU_ASSERT_EQUAL(ctx.stats.keeps, 0); 1071 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 1072 1073 run_message(&ctx, MSG_FALSE); 1074 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1075 CU_ASSERT_EQUAL(ctx.stats.actions, 2); 1076 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 1077 CU_ASSERT_EQUAL(ctx.stats.keeps, 1); 1078 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 1079 1080 context_cleanup(&ctx); 1081} 1082 1083static void test_header_index(void) 1084{ 1085 static const char SCRIPT[] = 1086 "require [\"index\"];\n" 1087 "if header :index 3 :is \"X-Virus-Status\" \"Clean\"\n" 1088 "{redirect \"me@blah.com\";}\n" 1089 ; 1090 1091 static const char SCRIPT_LAST[] = 1092 "require [\"index\"];\n" 1093 "if header :index 2 :last :is \"X-Virus-Status\" \"Clean\"\n" 1094 "{redirect \"me@blah.com\";}\n" 1095 ; 1096 1097 static const char MSG_TRUE[] = 1098 "Date: Mon, 25 Jan 2003 08:51:06 -0500\r\n" 1099 "From: zme@true.com\r\n" 1100 "To: you\r\n" 1101 "Subject: simple address test\r\n" 1102 "X-Virus-Status: *****\r\n" 1103 "X-Virus-Status: *****\r\n" 1104 "X-Virus-Status: Clean\r\n" 1105 "X-Virus-Status: *****\r\n" 1106 "\r\n" 1107 "blah\n" 1108 ; 1109 static const char MSG_FALSE[] = 1110 "Date: Mon, 25 Jan 2003 08:51:06 -0500\r\n" 1111 "From: zme@false.com\r\n" 1112 "To: you\r\n" 1113 "Subject: simple address test\r\n" 1114 "X-Virus-Status: Clean\r\n" 1115 "X-Virus-Status: Clean\r\n" 1116 "X-Virus-Status: *****\r\n" 1117 "X-Virus-Status: Clean\r\n" 1118 "\r\n" 1119 "blah\n" 1120 ; 1121 sieve_test_context_t ctx; 1122 1123 /* Test :index */ 1124 context_setup(&ctx, SCRIPT); 1125 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1126 1127 run_message(&ctx, MSG_TRUE); 1128 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1129 CU_ASSERT_EQUAL(ctx.stats.actions, 1); 1130 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 1131 CU_ASSERT_EQUAL(ctx.stats.keeps, 0); 1132 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 1133 1134 run_message(&ctx, MSG_FALSE); 1135 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1136 CU_ASSERT_EQUAL(ctx.stats.actions, 2); 1137 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 1138 CU_ASSERT_EQUAL(ctx.stats.keeps, 1); 1139 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 1140 1141 context_cleanup(&ctx); 1142 1143 /* Test :index :last */ 1144 context_setup(&ctx, SCRIPT_LAST); 1145 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1146 1147 run_message(&ctx, MSG_TRUE); 1148 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1149 CU_ASSERT_EQUAL(ctx.stats.actions, 1); 1150 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 1151 CU_ASSERT_EQUAL(ctx.stats.keeps, 0); 1152 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 1153 1154 run_message(&ctx, MSG_FALSE); 1155 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1156 CU_ASSERT_EQUAL(ctx.stats.actions, 2); 1157 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 1158 CU_ASSERT_EQUAL(ctx.stats.keeps, 1); 1159 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 1160 1161 context_cleanup(&ctx); 1162} 1163 1164static void test_date_year(void) 1165{ 1166 static const char SCRIPT[] = 1167 "require [\"date\", \"index\"];\n" 1168 "if date :index 1 :last :is \"received\" \"year\" [ \"1983\", \"1993\", \"2003\", \"2013\" ]\n" 1169 "{redirect \"me@blah.com\";}\n" 1170 ; 1171 static const char MSG_TRUE[] = 1172 "Date: Sat, 16 Nov 2013 12:46:49 +1100\r\n" 1173 "Received: from localhost (localhost [127.0.0.1])\r\n" 1174 " by mail.com (Cyrus v2.3.16) with LMTPA;\r\n" 1175 " Tue, 16 Nov 2010 12:50:12 +1100\r\n" 1176 "Received: from localhost (localhost [127.0.0.1])\r\n" 1177 " by mail.com (Cyrus v2.3.16) with LMTPA;\r\n" 1178 " Tue, 16 Nov 2013 12:50:12 +1100\r\n" 1179 "From: zme@true.com\r\n" 1180 "To: you\r\n" 1181 "Subject: simple address test\r\n" 1182 "\r\n" 1183 "blah\n" 1184 ; 1185 static const char MSG_FALSE[] = 1186 "Date: Tue, 16 Nov 2010 12:46:49 +1100\r\n" 1187 "Received: from localhost (localhost [127.0.0.1])\r\n" 1188 " by mail.com (Cyrus v2.3.16) with LMTPA;\r\n" 1189 " Tue, 16 Nov 2013 12:50:12 +1100\r\n" 1190 "Received: from localhost (localhost [127.0.0.1])\r\n" 1191 " by mail.com (Cyrus v2.3.16) with LMTPA;\r\n" 1192 " Tue, 16 Nov 2010 12:50:12 +1100\r\n" 1193 "From: yme@false.com\r\n" 1194 "To: you\r\n" 1195 "Subject: simple address test\r\n" 1196 "\r\n" 1197 "blah\n" 1198 ; 1199 sieve_test_context_t ctx; 1200 1201 context_setup(&ctx, SCRIPT); 1202 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1203 1204 run_message(&ctx, MSG_TRUE); 1205 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1206 CU_ASSERT_EQUAL(ctx.stats.actions, 1); 1207 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 1208 CU_ASSERT_EQUAL(ctx.stats.keeps, 0); 1209 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 1210 1211 run_message(&ctx, MSG_FALSE); 1212 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1213 CU_ASSERT_EQUAL(ctx.stats.actions, 2); 1214 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 1215 CU_ASSERT_EQUAL(ctx.stats.keeps, 1); 1216 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 1217 1218 context_cleanup(&ctx); 1219} 1220 1221static void test_date_zone_month(void) 1222{ 1223 static const char SCRIPT[] = 1224 "require [\"date\"];\n" 1225 "if date :is :zone \"-0800\" \"date\" \"month\" \"11\"\n" 1226 "{redirect \"me@blah.com\";}\n" 1227 ; 1228 static const char MSG_TRUE[] = 1229 "Date: Fri, 1 Nov 2013 19:46:49 +1100\r\n" 1230 "From: zme@true.com\r\n" 1231 "To: you\r\n" 1232 "Subject: simple address test\r\n" 1233 "\r\n" 1234 "blah\n" 1235 ; 1236 static const char MSG_FALSE[] = 1237 "Date: Fri, 1 Nov 2013 11:46:49 +1100\r\n" 1238 "From: yme@false.com\r\n" 1239 "To: you\r\n" 1240 "Subject: simple address test\r\n" 1241 "\r\n" 1242 "blah\n" 1243 ; 1244 sieve_test_context_t ctx; 1245 1246 context_setup(&ctx, SCRIPT); 1247 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1248 1249 run_message(&ctx, MSG_TRUE); 1250 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1251 CU_ASSERT_EQUAL(ctx.stats.actions, 1); 1252 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 1253 CU_ASSERT_EQUAL(ctx.stats.keeps, 0); 1254 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 1255 1256 run_message(&ctx, MSG_FALSE); 1257 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1258 CU_ASSERT_EQUAL(ctx.stats.actions, 2); 1259 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 1260 CU_ASSERT_EQUAL(ctx.stats.keeps, 1); 1261 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 1262 1263 context_cleanup(&ctx); 1264} 1265 1266static void test_date_date(void) 1267{ 1268 static const char SCRIPT[] = 1269 "require [\"date\"];\n" 1270 "if date :is :originalzone \"date\" \"date\" \"2013-11-02\"\n" 1271 "{redirect \"me@blah.com\";}\n" 1272 ; 1273 static const char MSG_TRUE[] = 1274 "Date: Sat, 2 Nov 2013 19:46:49 +1100\r\n" 1275 "From: zme@true.com\r\n" 1276 "To: you\r\n" 1277 "Subject: simple address test\r\n" 1278 "\r\n" 1279 "blah\n" 1280 ; 1281 static const char MSG_FALSE[] = 1282 "Date: Fri, 1 Nov 2013 19:45:49 +1100\r\n" 1283 "From: yme@false.com\r\n" 1284 "To: you\r\n" 1285 "Subject: simple address test\r\n" 1286 "\r\n" 1287 "blah\n" 1288 ; 1289 sieve_test_context_t ctx; 1290 1291 context_setup(&ctx, SCRIPT); 1292 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1293 1294 run_message(&ctx, MSG_TRUE); 1295 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1296 CU_ASSERT_EQUAL(ctx.stats.actions, 1); 1297 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 1298 CU_ASSERT_EQUAL(ctx.stats.keeps, 0); 1299 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 1300 1301 run_message(&ctx, MSG_FALSE); 1302 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1303 CU_ASSERT_EQUAL(ctx.stats.actions, 2); 1304 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 1305 CU_ASSERT_EQUAL(ctx.stats.keeps, 1); 1306 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 1307 1308 context_cleanup(&ctx); 1309} 1310 1311static void test_date_time(void) 1312{ 1313 static const char SCRIPT[] = 1314 "require [\"date\"];\n" 1315 "if date :is :originalzone \"date\" \"time\" \"19:46:49\"\n" 1316 "{redirect \"me@blah.com\";}\n" 1317 ; 1318 static const char MSG_TRUE[] = 1319 "Date: Sat, 2 Nov 2013 19:46:49 +1100\r\n" 1320 "From: zme@true.com\r\n" 1321 "To: you\r\n" 1322 "Subject: simple address test\r\n" 1323 "\r\n" 1324 "blah\n" 1325 ; 1326 static const char MSG_FALSE[] = 1327 "Date: Sat, 2 Nov 2013 19:45:49 +1100\r\n" 1328 "From: yme@false.com\r\n" 1329 "To: you\r\n" 1330 "Subject: simple address test\r\n" 1331 "\r\n" 1332 "blah\n" 1333 ; 1334 sieve_test_context_t ctx; 1335 1336 context_setup(&ctx, SCRIPT); 1337 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1338 1339 run_message(&ctx, MSG_TRUE); 1340 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1341 CU_ASSERT_EQUAL(ctx.stats.actions, 1); 1342 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 1343 CU_ASSERT_EQUAL(ctx.stats.keeps, 0); 1344 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 1345 1346 run_message(&ctx, MSG_FALSE); 1347 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1348 CU_ASSERT_EQUAL(ctx.stats.actions, 2); 1349 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 1350 CU_ASSERT_EQUAL(ctx.stats.keeps, 1); 1351 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 1352 1353 context_cleanup(&ctx); 1354} 1355 1356static void test_date_originalzone_day(void) 1357{ 1358 static const char SCRIPT[] = 1359 "require [\"date\"];\n" 1360 "if date :is :originalzone \"date\" \"day\" \"16\"\n" 1361 "{redirect \"me@blah.com\";}\n" 1362 ; 1363 static const char MSG_TRUE[] = 1364 "Date: Sat, 16 Nov 2013 12:46:49 +1100\r\n" 1365 "From: zme@true.com\r\n" 1366 "To: you\r\n" 1367 "Subject: simple address test\r\n" 1368 "\r\n" 1369 "blah\n" 1370 ; 1371 static const char MSG_FALSE[] = 1372 "Date: Fri, 15 Nov 2013 12:46:49 +1100\r\n" 1373 "From: yme@false.com\r\n" 1374 "To: you\r\n" 1375 "Subject: simple address test\r\n" 1376 "\r\n" 1377 "blah\n" 1378 ; 1379 sieve_test_context_t ctx; 1380 1381 context_setup(&ctx, SCRIPT); 1382 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1383 1384 run_message(&ctx, MSG_TRUE); 1385 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1386 CU_ASSERT_EQUAL(ctx.stats.actions, 1); 1387 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 1388 CU_ASSERT_EQUAL(ctx.stats.keeps, 0); 1389 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 1390 1391 run_message(&ctx, MSG_FALSE); 1392 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1393 CU_ASSERT_EQUAL(ctx.stats.actions, 2); 1394 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 1395 CU_ASSERT_EQUAL(ctx.stats.keeps, 1); 1396 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 1397 1398 context_cleanup(&ctx); 1399} 1400 1401static void test_date_weekend_weekday(void) 1402{ 1403 static const char SCRIPT[] = 1404 "require [\"date\"];\n" 1405 "if anyof(date :is :zone \"-0800\" \"date\" \"weekday\" \"0\",\n" 1406 " date :is :zone \"-0800\" \"date\" \"weekday\" \"6\")\n" 1407 "{redirect \"me@blah.com\";}\n" 1408 ; 1409 static const char MSG_TRUE[] = 1410 "Date: Sat, 2 Nov 2013 19:46:49 +1100\r\n" 1411 "From: zme@true.com\r\n" 1412 "To: you\r\n" 1413 "Subject: simple address test\r\n" 1414 "\r\n" 1415 "blah\n" 1416 ; 1417 static const char MSG_FALSE[] = 1418 "Date: Fri, 1 Nov 2013 11:46:49 +1100\r\n" 1419 "From: yme@false.com\r\n" 1420 "To: you\r\n" 1421 "Subject: simple address test\r\n" 1422 "\r\n" 1423 "blah\n" 1424 ; 1425 sieve_test_context_t ctx; 1426 1427 context_setup(&ctx, SCRIPT); 1428 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1429 1430 run_message(&ctx, MSG_TRUE); 1431 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1432 CU_ASSERT_EQUAL(ctx.stats.actions, 1); 1433 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 1434 CU_ASSERT_EQUAL(ctx.stats.keeps, 0); 1435 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 1436 1437 run_message(&ctx, MSG_FALSE); 1438 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1439 CU_ASSERT_EQUAL(ctx.stats.actions, 2); 1440 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 1441 CU_ASSERT_EQUAL(ctx.stats.keeps, 1); 1442 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 1443 1444 context_cleanup(&ctx); 1445} 1446 1447static void test_date_zone(void) 1448{ 1449 static const char SCRIPT[] = 1450 "require [\"date\"];\n" 1451 "if date :is :originalzone \"date\" \"zone\" \"+1100\"\n" 1452 "{redirect \"me@blah.com\";}\n" 1453 ; 1454 static const char MSG_TRUE[] = 1455 "Date: Sat, 2 Nov 2013 19:46:49 +1100\r\n" 1456 "From: zme@true.com\r\n" 1457 "To: you\r\n" 1458 "Subject: simple address test\r\n" 1459 "\r\n" 1460 "blah\n" 1461 ; 1462 static const char MSG_FALSE[] = 1463 "Date: Fri, 1 Nov 2013 11:46:49 -0700\r\n" 1464 "From: yme@false.com\r\n" 1465 "To: you\r\n" 1466 "Subject: simple address test\r\n" 1467 "\r\n" 1468 "blah\n" 1469 ; 1470 sieve_test_context_t ctx; 1471 1472 context_setup(&ctx, SCRIPT); 1473 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1474 1475 run_message(&ctx, MSG_TRUE); 1476 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1477 CU_ASSERT_EQUAL(ctx.stats.actions, 1); 1478 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 1479 CU_ASSERT_EQUAL(ctx.stats.keeps, 0); 1480 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 1481 1482 run_message(&ctx, MSG_FALSE); 1483 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1484 CU_ASSERT_EQUAL(ctx.stats.actions, 2); 1485 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 1486 CU_ASSERT_EQUAL(ctx.stats.keeps, 1); 1487 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 1488 1489 context_cleanup(&ctx); 1490} 1491 1492static void test_currentdate_true(void) 1493{ 1494 static const char SCRIPT[] = 1495 "require [\"date\", \"relational\"];\n" 1496 "if allof(currentdate :zone \"+0000\" :value \"ge\" \"date\" \"2014-01-01\",\n" 1497 " currentdate :zone \"+0000\" :value \"le\" \"date\" \"2114-01-01\")\n" 1498 "{redirect \"me@blah.com\";}\n" 1499 ; 1500 static const char MSG_TRUE[] = 1501 "Date: Tue, 16 Nov 2010 12:46:49 +1100\r\n" 1502 "From: yme@true.com\r\n" 1503 "To: you\r\n" 1504 "Subject: simple address test\r\n" 1505 "\r\n" 1506 "blah\n" 1507 ; 1508 sieve_test_context_t ctx; 1509 1510 context_setup(&ctx, SCRIPT); 1511 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1512 1513 run_message(&ctx, MSG_TRUE); 1514 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1515 CU_ASSERT_EQUAL(ctx.stats.actions, 1); 1516 CU_ASSERT_EQUAL(ctx.stats.redirects, 1); 1517 CU_ASSERT_EQUAL(ctx.stats.keeps, 0); 1518 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, "me@blah.com"); 1519 1520 context_cleanup(&ctx); 1521} 1522 1523static void test_currentdate_false(void) 1524{ 1525 static const char SCRIPT[] = 1526 "require [\"date\", \"relational\"];\n" 1527 "if allof(currentdate :zone \"+0000\" :value \"ge\" \"date\" \"1970-01-01\",\n" 1528 " currentdate :zone \"+0000\" :value \"le\" \"date\" \"2014-01-01\")\n" 1529 "{redirect \"me@blah.com\";}\n" 1530 ; 1531 static const char MSG_FALSE[] = 1532 "Date: Tue, 16 Nov 2010 12:46:49 +1100\r\n" 1533 "From: yme@false.com\r\n" 1534 "To: you\r\n" 1535 "Subject: simple address test\r\n" 1536 "\r\n" 1537 "blah\n" 1538 ; 1539 sieve_test_context_t ctx; 1540 1541 context_setup(&ctx, SCRIPT); 1542 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1543 1544 run_message(&ctx, MSG_FALSE); 1545 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1546 CU_ASSERT_EQUAL(ctx.stats.actions, 1); 1547 CU_ASSERT_EQUAL(ctx.stats.redirects, 0); 1548 CU_ASSERT_EQUAL(ctx.stats.keeps, 1); 1549 CU_ASSERT_STRING_EQUAL(ctx.redirected_to, NULL); 1550 1551 context_cleanup(&ctx); 1552} 1553 1554static void test_imap4flags_setflag(void) 1555{ 1556 static const char SCRIPT_INTERNAL[] = 1557 "require [\"imap4flags\", \"variables\"];\n" 1558 "setflag \"myvar\" [\"myval1\", \"myval2\"];\n" 1559 "keep :flags \"${myvar}\";\n" 1560 ; 1561 1562 static const char MSG_TRUE[] = 1563 "Date: Mon, 25 Jan 2003 08:51:06 -0500\r\n" 1564 "From: zme@true.com\r\n" 1565 "To: you\r\n" 1566 "Subject: simple flag test\r\n" 1567 "\r\n" 1568 "blah\n" 1569 ; 1570 sieve_test_context_t ctx; 1571 1572 /* Test setflag "variablename" "flags" */ 1573 context_setup(&ctx, SCRIPT_INTERNAL); 1574 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1575 1576 run_message(&ctx, MSG_TRUE); 1577 CU_ASSERT_EQUAL(ctx.stats.errors, 0); 1578 CU_ASSERT_EQUAL(ctx.stats.actions, 1); 1579 CU_ASSERT_EQUAL(ctx.stats.keeps, 1); 1580 CU_ASSERT_NOT_EQUAL(strarray_find_case(ctx.flags,"myval1",0),-1); 1581 CU_ASSERT_NOT_EQUAL(strarray_find_case(ctx.flags,"myval2",0),-1); 1582 1583 context_cleanup(&ctx); 1584 1585 /* Test #2 */ 1586} 1587 1588// TODO: test 1589// if size :over 10K { redirect "me@blah.com"; } 1590// TODO: test 1591// if true {...} 1592// 1593// if false {...} 1594// 1595// if not false {...} 1596// 1597// if true {...} else {...} 1598// 1599// if false {...} elsif true {...} else {...} 1600// 1601// if false {...} elsif false {...} else {...} 1602// 1603// if false {} else {...} 1604// 1605// if true { if true { if true { ... } } } 1606// 1607// if allof(false, false) {...} else {...} 1608// 1609// if allof(false,true) {...} else {...} 1610// 1611// if allof(true,false) {...} else {...} 1612// 1613// if allof(true,true) {...} else {...} 1614// 1615// if anyof(false, false) {...} else {...} 1616// 1617// if anyof(false,true) {...} else {...} 1618// 1619// if anyof(true,false) {...} else {...} 1620// 1621// if anyof(true,true) {...} else {...} 1622/* vim: set ft=c: */ 1623