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