diff --git a/Makefile.am b/Makefile.am index f969e5fabf173913ac1163aec9f94577d772665e..c9638a16ab19f473e2f14c6f064974662ec7bcb5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -76,7 +76,8 @@ test_cases = \ tests/extensions/enotify/valid_notify_method.svtest \ tests/extensions/enotify/notify_method_capability.svtest \ tests/extensions/enotify/errors.svtest \ - tests/extensions/enotify/execute.svtest + tests/extensions/enotify/execute.svtest \ + tests/multiscript/basic.svtest if HAVE_DOVECOT_LIBS diff --git a/src/lib-sieve/ext-reject.c b/src/lib-sieve/ext-reject.c index 8f05591aba4d129bca82d867a9ae51e4cd38968a..ce8305b8a86443b3761a027d1b1c05b184b10684 100644 --- a/src/lib-sieve/ext-reject.c +++ b/src/lib-sieve/ext-reject.c @@ -271,7 +271,7 @@ int act_reject_check_conflict if ( (act_other->action->flags & SIEVE_ACTFLAG_TRIES_DELIVER) > 0 ) { if ( !act_other->executed ) { sieve_runtime_error(renv, act->location, - "reject action conflicts with earlier triggered action: " + "reject action conflicts with other action: " "the %s action (%s) tries to deliver the message", act_other->action->name, act_other->location); return -1; @@ -283,7 +283,7 @@ int act_reject_check_conflict if ( (act_other->action->flags & SIEVE_ACTFLAG_SENDS_RESPONSE) > 0 ) { if ( !act_other->executed ) { sieve_runtime_error(renv, act->location, - "reject action conflicts with earlier triggered action: " + "reject action conflicts with other action: " "the %s action (%s) also sends a response to the sender", act_other->action->name, act_other->location); return -1; diff --git a/src/lib-sieve/plugins/vacation/cmd-vacation.c b/src/lib-sieve/plugins/vacation/cmd-vacation.c index 85e271a49b9f8eb0a06cf08e5a4591a2ae0c615b..a1d23da554b07f642e42b176099ca7fe74cd515c 100644 --- a/src/lib-sieve/plugins/vacation/cmd-vacation.c +++ b/src/lib-sieve/plugins/vacation/cmd-vacation.c @@ -704,7 +704,7 @@ int act_vacation_check_conflict if ( (act_other->action->flags & SIEVE_ACTFLAG_SENDS_RESPONSE) > 0 ) { if ( !act_other->executed ) { sieve_runtime_error(renv, act->location, - "vacation action conflicts with earlier triggered action: " + "vacation action conflicts with other action: " "the %s action (%s) also sends a response back to the sender", act_other->action->name, act_other->location); return -1; diff --git a/src/testsuite/Makefile.am b/src/testsuite/Makefile.am index 284efb2824c218a901e1a23b8068fd9721e6210b..dbb87276581a6117e36da8cea7f19ed06408642f 100644 --- a/src/testsuite/Makefile.am +++ b/src/testsuite/Makefile.am @@ -36,7 +36,8 @@ testsuite_DEPENDENCIES = $(libs) commands = \ cmd-test.c \ cmd-test-fail.c \ - cmd-test-set.c + cmd-test-set.c \ + cmd-test-result-print.c tests = \ tst-test-script-compile.c \ diff --git a/src/testsuite/cmd-test-result-print.c b/src/testsuite/cmd-test-result-print.c new file mode 100644 index 0000000000000000000000000000000000000000..c05a82db891ac3a48cc81747e3cbb0def699d123 --- /dev/null +++ b/src/testsuite/cmd-test-result-print.c @@ -0,0 +1,82 @@ +/* Copyright (c) 2002-2008 Dovecot Sieve authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-script.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-code.h" +#include "sieve-binary.h" +#include "sieve-dump.h" +#include "sieve.h" + +#include "testsuite-common.h" +#include "testsuite-result.h" + +/* + * Test_result_execute command + * + * Syntax: + * test_result_execute + */ + +static bool cmd_test_result_print_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx); + +const struct sieve_command cmd_test_result_print = { + "test_result_print", + SCT_COMMAND, + 0, 0, FALSE, FALSE, + NULL, NULL, NULL, + cmd_test_result_print_generate, + NULL +}; + +/* + * Operation + */ + +static int cmd_test_result_print_operation_execute + (const struct sieve_operation *op, + const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation test_result_print_operation = { + "TEST_RESULT_PRINT", + &testsuite_extension, + TESTSUITE_OPERATION_TEST_RESULT_PRINT, + NULL, + cmd_test_result_print_operation_execute +}; + +/* + * Code generation + */ + +static bool cmd_test_result_print_generate +(const struct sieve_codegen_env *cgenv, + struct sieve_command_context *tst ATTR_UNUSED) +{ + sieve_operation_emit_code(cgenv->sbin, &test_result_print_operation); + + return TRUE; +} + +/* + * Intepretation + */ + +static int cmd_test_result_print_operation_execute +(const struct sieve_operation *op ATTR_UNUSED, + const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED) +{ + testsuite_result_print(renv); + + return SIEVE_EXEC_OK; +} + + + + diff --git a/src/testsuite/ext-testsuite.c b/src/testsuite/ext-testsuite.c index 47b5f21402906c4052dc14fe2eb725b3cbfb9af3..ea4006aa1f1c0087de646dbf668169a831d2aa47 100644 --- a/src/testsuite/ext-testsuite.c +++ b/src/testsuite/ext-testsuite.c @@ -60,7 +60,8 @@ const struct sieve_operation *testsuite_operations[] = { &test_script_run_operation, &test_error_operation, &test_result_operation, - &test_result_execute_operation + &test_result_execute_operation, + &test_result_print_operation }; /* @@ -106,6 +107,7 @@ static bool ext_testsuite_validator_load(struct sieve_validator *valdtr) sieve_validator_register_command(valdtr, &cmd_test); sieve_validator_register_command(valdtr, &cmd_test_fail); sieve_validator_register_command(valdtr, &cmd_test_set); + sieve_validator_register_command(valdtr, &cmd_test_result_print); sieve_validator_register_command(valdtr, &tst_test_script_compile); sieve_validator_register_command(valdtr, &tst_test_script_run); diff --git a/src/testsuite/testsuite-common.h b/src/testsuite/testsuite-common.h index 0ee51adbdc066e82afdf4d99cfdd77cdc513382b..2c5beb0df38e5470394f97e96d53d6de96ee68f1 100644 --- a/src/testsuite/testsuite-common.h +++ b/src/testsuite/testsuite-common.h @@ -55,6 +55,7 @@ bool testsuite_generator_context_initialize(struct sieve_generator *gentr); extern const struct sieve_command cmd_test; extern const struct sieve_command cmd_test_fail; extern const struct sieve_command cmd_test_set; +extern const struct sieve_command cmd_test_result_print; /* * Tests @@ -80,6 +81,7 @@ enum testsuite_operation_code { TESTSUITE_OPERATION_TEST_ERROR, TESTSUITE_OPERATION_TEST_RESULT, TESTSUITE_OPERATION_TEST_RESULT_EXECUTE, + TESTSUITE_OPERATION_TEST_RESULT_PRINT, }; extern const struct sieve_operation test_operation; @@ -91,6 +93,7 @@ extern const struct sieve_operation test_script_run_operation; extern const struct sieve_operation test_error_operation; extern const struct sieve_operation test_result_operation; extern const struct sieve_operation test_result_execute_operation; +extern const struct sieve_operation test_result_print_operation; /* * Operands diff --git a/src/testsuite/testsuite-log.c b/src/testsuite/testsuite-log.c index 92c9b4a813b44e39d1e85cb6a02e726c40eb009a..e36e6e63ac8441d7d16f5af1a8e7a5728b1637ff 100644 --- a/src/testsuite/testsuite-log.c +++ b/src/testsuite/testsuite-log.c @@ -17,7 +17,7 @@ struct _testsuite_log_message { const char *message; }; -bool _testsuite_log_stdout = TRUE; +bool _testsuite_log_stdout = FALSE; unsigned int _testsuite_log_error_index = 0; diff --git a/src/testsuite/testsuite-result.c b/src/testsuite/testsuite-result.c index b9873b5eb963de5609cf6439c99cfd8e249d2270..5fb8a433d92a3c91bcb6d8bcdd06676436c8fa28 100644 --- a/src/testsuite/testsuite-result.c +++ b/src/testsuite/testsuite-result.c @@ -1,6 +1,9 @@ /* Copyright (c) 2002-2008 Dovecot Sieve authors, see the included COPYING file */ +#include "lib.h" +#include "ostream.h" + #include "sieve-common.h" #include "sieve-error.h" #include "sieve-actions.h" @@ -15,7 +18,7 @@ static struct sieve_result *_testsuite_result; void testsuite_result_init(void) { - _testsuite_result = NULL; + _testsuite_result = sieve_result_create(testsuite_log_ehandler); } void testsuite_result_deinit(void) @@ -25,13 +28,18 @@ void testsuite_result_deinit(void) } } -void testsuite_result_assign(struct sieve_result *result) +void testsuite_result_reset(void) { if ( _testsuite_result != NULL ) { sieve_result_unref(&_testsuite_result); } - _testsuite_result = result; + _testsuite_result = sieve_result_create(testsuite_log_ehandler);; +} + +struct sieve_result *testsuite_result_get(void) +{ + return _testsuite_result; } struct sieve_result_iterate_context *testsuite_result_iterate_init(void) @@ -75,4 +83,16 @@ bool testsuite_result_execute(const struct sieve_runtime_env *renv) return ( ret > 0 ); } +void testsuite_result_print +(const struct sieve_runtime_env *renv ATTR_UNUSED) +{ + struct ostream *out; + + out = o_stream_create_fd(1, 0, FALSE); + + sieve_result_print(_testsuite_result, out); + + o_stream_destroy(&out); +} + diff --git a/src/testsuite/testsuite-result.h b/src/testsuite/testsuite-result.h index ab21d0f34ada3d844721a9bd4a69eb43f3a4e714..b9b14652350c38bcd0e2e329229c53f61891e8c2 100644 --- a/src/testsuite/testsuite-result.h +++ b/src/testsuite/testsuite-result.h @@ -7,10 +7,15 @@ void testsuite_result_init(void); void testsuite_result_deinit(void); -void testsuite_result_assign(struct sieve_result *result); +void testsuite_result_reset(void); + +struct sieve_result *testsuite_result_get(void); struct sieve_result_iterate_context *testsuite_result_iterate_init(void); bool testsuite_result_execute(const struct sieve_runtime_env *renv); +void testsuite_result_print + (const struct sieve_runtime_env *renv ATTR_UNUSED); + #endif /* __TESTSUITE_RESULT_H */ diff --git a/src/testsuite/tst-test-result-execute.c b/src/testsuite/tst-test-result-execute.c index 1ccd9b238133cc6f79c683721211799a8ad5f945..bf28203cd912c0dbdde6fac7577e9c06bdb6c255 100644 --- a/src/testsuite/tst-test-result-execute.c +++ b/src/testsuite/tst-test-result-execute.c @@ -43,7 +43,7 @@ static int tst_test_result_execute_operation_execute const struct sieve_runtime_env *renv, sieve_size_t *address); const struct sieve_operation test_result_execute_operation = { - "test_result_execute", + "TEST_RESULT_EXECUTE", &testsuite_extension, TESTSUITE_OPERATION_TEST_RESULT_EXECUTE, NULL, diff --git a/src/testsuite/tst-test-script-compile.c b/src/testsuite/tst-test-script-compile.c index a2dc4e67ff86ce0d3b025f25e44c9d00be504d23..8ce4fe7b0e1b83b818273ab00b2d2ebe0eae1b3b 100644 --- a/src/testsuite/tst-test-script-compile.c +++ b/src/testsuite/tst-test-script-compile.c @@ -48,7 +48,7 @@ static int tst_test_script_compile_operation_execute const struct sieve_runtime_env *renv, sieve_size_t *address); const struct sieve_operation test_script_compile_operation = { - "test_script_compile", + "TEST_SCRIPT_COMPILE", &testsuite_extension, TESTSUITE_OPERATION_TEST_SCRIPT_COMPILE, tst_test_script_compile_operation_dump, @@ -100,7 +100,7 @@ static bool tst_test_script_compile_operation_dump (const struct sieve_operation *op ATTR_UNUSED, const struct sieve_dumptime_env *denv, sieve_size_t *address) { - sieve_code_dumpf(denv, "test_script_compile:"); + sieve_code_dumpf(denv, "TEST_SCRIPT_COMPILE:"); sieve_code_descend(denv); if ( !sieve_opr_string_dump(denv, address, "script") ) diff --git a/src/testsuite/tst-test-script-run.c b/src/testsuite/tst-test-script-run.c index f132a419d7594cc3d1cae05347424f5768181699..2ba17b85518d0e21478c2556d750c1e285c0924d 100644 --- a/src/testsuite/tst-test-script-run.c +++ b/src/testsuite/tst-test-script-run.c @@ -13,6 +13,7 @@ #include "sieve.h" #include "testsuite-common.h" +#include "testsuite-result.h" /* * Test_script_run command @@ -21,6 +22,8 @@ * test_script_run */ +static bool tst_test_script_run_registered +(struct sieve_validator *validator, struct sieve_command_registration *cmd_reg); static bool tst_test_script_run_generate (const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx); @@ -28,7 +31,8 @@ const struct sieve_command tst_test_script_run = { "test_script_run", SCT_TEST, 0, 0, FALSE, FALSE, - NULL, NULL, NULL, + tst_test_script_run_registered, + NULL, NULL, tst_test_script_run_generate, NULL }; @@ -37,6 +41,9 @@ const struct sieve_command tst_test_script_run = { * Operation */ +static bool tst_test_script_run_operation_dump + (const struct sieve_operation *op, + const struct sieve_dumptime_env *denv, sieve_size_t *address); static int tst_test_script_run_operation_execute (const struct sieve_operation *op, const struct sieve_runtime_env *renv, sieve_size_t *address); @@ -45,23 +52,89 @@ const struct sieve_operation test_script_run_operation = { "test_script_run", &testsuite_extension, TESTSUITE_OPERATION_TEST_SCRIPT_RUN, - NULL, + tst_test_script_run_operation_dump, tst_test_script_run_operation_execute }; +/* + * Tagged arguments + */ + +/* Codes for optional arguments */ + +enum cmd_vacation_optional { + OPT_END, + OPT_APPEND_RESULT +}; + +/* Tags */ + +static const struct sieve_argument append_result_tag = { + "append_result", + NULL, NULL, NULL, NULL, NULL +}; + +static bool tst_test_script_run_registered +(struct sieve_validator *validator, struct sieve_command_registration *cmd_reg) +{ + sieve_validator_register_tag + (validator, cmd_reg, &append_result_tag, OPT_APPEND_RESULT); + + return TRUE; +} + + /* * Code generation */ static bool tst_test_script_run_generate (const struct sieve_codegen_env *cgenv, - struct sieve_command_context *tst ATTR_UNUSED) + struct sieve_command_context *tst) { sieve_operation_emit_code(cgenv->sbin, &test_script_run_operation); + return sieve_generate_arguments(cgenv, tst, NULL); +} + +/* + * Code dump + */ + +static bool tst_test_script_run_operation_dump +(const struct sieve_operation *op ATTR_UNUSED, + const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + int opt_code = 1; + + sieve_code_dumpf(denv, "TEST_SCRIPT_RUN"); + sieve_code_descend(denv); + + /* Dump optional operands */ + if ( sieve_operand_optional_present(denv->sbin, address) ) { + while ( opt_code != 0 ) { + sieve_code_mark(denv); + + if ( !sieve_operand_optional_read(denv->sbin, address, &opt_code) ) + return FALSE; + + switch ( opt_code ) { + case 0: + break; + case OPT_APPEND_RESULT: + sieve_code_dumpf(denv, "append_result"); + break; + + default: + return FALSE; + } + } + } + return TRUE; } + /* * Intepretation */ @@ -71,15 +144,48 @@ static int tst_test_script_run_operation_execute const struct sieve_runtime_env *renv, sieve_size_t *address ATTR_UNUSED) { + bool append_result = FALSE; + int opt_code = 1; bool result = TRUE; + /* + * Read operands + */ + + /* Optional operands */ + if ( sieve_operand_optional_present(renv->sbin, address) ) { + while ( opt_code != 0 ) { + if ( !sieve_operand_optional_read(renv->sbin, address, &opt_code) ) { + sieve_runtime_trace_error(renv, "invalid optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + switch ( opt_code ) { + case 0: + break; + case OPT_APPEND_RESULT: + append_result = TRUE; + break; + default: + sieve_runtime_trace_error(renv, + "unknown optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + } + } + /* * Perform operation */ + /* Reset result object */ + if ( !append_result ) + testsuite_result_reset(); + + /* Run script */ result = testsuite_script_run(renv); - /* Set result */ + /* Indicate test status */ sieve_interpreter_set_test_result(renv->interp, result); return SIEVE_EXEC_OK; diff --git a/tests/multiscript/basic.svtest b/tests/multiscript/basic.svtest new file mode 100644 index 0000000000000000000000000000000000000000..54fb26b1c5e5c8d3a19764df994b8f803a93d973 --- /dev/null +++ b/tests/multiscript/basic.svtest @@ -0,0 +1,91 @@ +require "vnd.dovecot.testsuite"; + +test_set "message" text: +From: stephan@rename-it.nl +Message-ID: <frop33333333333333333@frutsens.nl> +To: nico@vestingbar.nl +Subject: Frop. + +Friep. +. +; + +test "Append" { + if not allof ( + test_script_compile "fileinto-inbox.sieve", + test_script_run ){ + test_fail "failed to compile and run first script"; + } + + if not allof ( + test_script_compile "vacation.sieve", + test_script_run :append_result ) { + test_fail "failed to compile and run second script"; + } + + if not allof ( + test_script_compile "notify.sieve", + test_script_run :append_result ) { + test_fail "failed to compile and run third script"; + } + + if not test_result :index 1 "store" { + test_fail "first action is not 'store'"; + } + + if not test_result :index 2 "vacation" { + test_fail "second action is not 'vacation'"; + } + + if not test_result :index 3 "notify" { + test_fail "third action is not 'notify'"; + } + + if not test_result_execute { + test_fail "result execute failed"; + } +} + +test "Sequential Execute" { + if not allof ( + test_script_compile "fileinto-inbox.sieve", + test_script_run ) { + test_fail "failed to compile and run first script"; + } + + if not test_result_execute { + test_fail "result execute failed after first script"; + } + + if not allof ( + test_script_compile "vacation.sieve", + test_script_run :append_result ) { + test_fail "failed to compile and run second script"; + } + + if not test_result_execute { + test_fail "result execute failed after second script"; + } + + if not allof ( + test_script_compile "notify.sieve", + test_script_run :append_result ) { + test_fail "failed to compile and run third script"; + } + + if not test_result_execute { + test_fail "result execute failed after third script"; + } + + if not test_result :index 1 "store" { + test_fail "first action is not 'store'"; + } + + if not test_result :index 2 "vacation" { + test_fail "second action is not 'vacation'"; + } + + if not test_result :index 3 "notify" { + test_fail "third action is not 'notify'"; + } +} diff --git a/tests/multiscript/conflicts.svtest b/tests/multiscript/conflicts.svtest new file mode 100644 index 0000000000000000000000000000000000000000..be9a58edc881efc0cd9418da7c61dae879be5fe4 --- /dev/null +++ b/tests/multiscript/conflicts.svtest @@ -0,0 +1,51 @@ +require "vnd.dovecot.testsuite"; + +test_set "message" text: +From: stephan@rename-it.nl +Message-ID: <frop33333333333333333@frutsens.nl> +To: nico@vestingbar.nl +Subject: Frop. + +Friep. +. +; + +test "Graceful Conflicts" { + if not allof ( + test_script_compile "fileinto-inbox.sieve", + test_script_run ){ + test_fail "failed to compile and run first script"; + } + + if not test_result_execute { + test_fail "result execute failed after first script"; + } + + if not allof ( + test_script_compile "reject-1.sieve", + test_script_run :append_result ) { + test_fail "failed to compile and run second script"; + } + + if not test_result_execute { + test_fail "result execute failed after second script"; + } + + if not allof ( + test_script_compile "reject-2.sieve", + test_script_run :append_result ) { + test_fail "failed to compile and run third script"; + } + + if not test_result_execute { + test_fail "result execute failed after third script"; + } + + if not test_result :index 1 "store" { + test_fail "first action is not 'store'"; + } + + if test_result :index 2 "reject" { + test_fail "reject action not discarded"; + } +} diff --git a/tests/multiscript/fileinto-inbox.sieve b/tests/multiscript/fileinto-inbox.sieve new file mode 100644 index 0000000000000000000000000000000000000000..b5da850e787bbe855315e549cd614caf84e09bdc --- /dev/null +++ b/tests/multiscript/fileinto-inbox.sieve @@ -0,0 +1,4 @@ +require "fileinto"; + +fileinto "INBOX"; + diff --git a/tests/multiscript/notify.sieve b/tests/multiscript/notify.sieve new file mode 100644 index 0000000000000000000000000000000000000000..9e5507bc7ff035b3ab3527911c4a775aedfb9a6b --- /dev/null +++ b/tests/multiscript/notify.sieve @@ -0,0 +1,3 @@ +require "enotify"; + +notify "mailto:stephan@rename-it.nl"; diff --git a/tests/multiscript/reject-1.sieve b/tests/multiscript/reject-1.sieve new file mode 100644 index 0000000000000000000000000000000000000000..06744f60ae60223b7eb2a596d9d1aafe581e09f4 --- /dev/null +++ b/tests/multiscript/reject-1.sieve @@ -0,0 +1,3 @@ +require "reject"; + +reject "Message is not wanted."; diff --git a/tests/multiscript/reject-2.sieve b/tests/multiscript/reject-2.sieve new file mode 100644 index 0000000000000000000000000000000000000000..96b75642fdd8dd5e9a0da9309835e5333b705f0d --- /dev/null +++ b/tests/multiscript/reject-2.sieve @@ -0,0 +1,3 @@ +require "reject"; + +reject "Will not accept this nonsense."; diff --git a/tests/multiscript/vacation.sieve b/tests/multiscript/vacation.sieve new file mode 100644 index 0000000000000000000000000000000000000000..d735da5bf881b1e4c9483c7d7b3a3c129e0f5a1a --- /dev/null +++ b/tests/multiscript/vacation.sieve @@ -0,0 +1,3 @@ +require "vacation"; + +vacation "I am not home";