From 9cd8ef590d09542e8f6e511720a5149780748721 Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan@rename-it.nl> Date: Sat, 17 Oct 2009 23:05:03 +0200 Subject: [PATCH] Test suite: added multiscript support and added some new tests with the new feature. --- Makefile.am | 1 + TODO | 1 - src/testsuite/Makefile.am | 2 +- src/testsuite/ext-testsuite.c | 2 + src/testsuite/testsuite-common.h | 3 + src/testsuite/testsuite-script.c | 77 +++++++- src/testsuite/testsuite-script.h | 2 + src/testsuite/tst-test-multiscript.c | 170 ++++++++++++++++++ .../extensions/imap4flags/multiscript.svtest | 13 ++ .../imap4flags/multiscript/group-spam.sieve | 14 ++ .../imap4flags/multiscript/sent-store.sieve | 7 + .../imap4flags/multiscript/spam.sieve | 8 + 12 files changed, 294 insertions(+), 6 deletions(-) create mode 100644 src/testsuite/tst-test-multiscript.c create mode 100644 tests/extensions/imap4flags/multiscript.svtest create mode 100644 tests/extensions/imap4flags/multiscript/group-spam.sieve create mode 100644 tests/extensions/imap4flags/multiscript/sent-store.sieve create mode 100644 tests/extensions/imap4flags/multiscript/spam.sieve diff --git a/Makefile.am b/Makefile.am index 93406a2c1..bcf53d756 100644 --- a/Makefile.am +++ b/Makefile.am @@ -76,6 +76,7 @@ test_cases = \ tests/extensions/imap4flags/hasflag.svtest \ tests/extensions/imap4flags/errors.svtest \ tests/extensions/imap4flags/execute.svtest \ + tests/extensions/imap4flags/multiscript.svtest \ tests/extensions/imap4flags/flagstore.svtest \ tests/extensions/body/basic.svtest \ tests/extensions/body/raw.svtest \ diff --git a/TODO b/TODO index 001517603..7c0433df7 100644 --- a/TODO +++ b/TODO @@ -4,7 +4,6 @@ Current activities: - Implement proper :content "multipart" behavior - Implement proper :content "message/rfc822" behavior - Build test cases for decoding MIME encodings to UTF-8 -* Add multiscript support to the testsuite. * Build a sieve tool to filter an entire existing mailbox through a Sieve script: - Add commandline options to fully customize execution diff --git a/src/testsuite/Makefile.am b/src/testsuite/Makefile.am index be1fb1c6a..d722fdab2 100644 --- a/src/testsuite/Makefile.am +++ b/src/testsuite/Makefile.am @@ -35,10 +35,10 @@ commands = \ cmd-test-mailbox.c \ cmd-test-binary.c - tests = \ tst-test-script-compile.c \ tst-test-script-run.c \ + tst-test-multiscript.c \ tst-test-error.c \ tst-test-result.c \ tst-test-result-execute.c diff --git a/src/testsuite/ext-testsuite.c b/src/testsuite/ext-testsuite.c index e6f07318f..42100b5b7 100644 --- a/src/testsuite/ext-testsuite.c +++ b/src/testsuite/ext-testsuite.c @@ -58,6 +58,7 @@ const struct sieve_operation *testsuite_operations[] = { &test_set_operation, &test_script_compile_operation, &test_script_run_operation, + &test_multiscript_operation, &test_error_operation, &test_result_operation, &test_result_execute_operation, @@ -122,6 +123,7 @@ static bool ext_testsuite_validator_load(struct sieve_validator *valdtr) sieve_validator_register_command(valdtr, &tst_test_script_compile); sieve_validator_register_command(valdtr, &tst_test_script_run); + sieve_validator_register_command(valdtr, &tst_test_multiscript); sieve_validator_register_command(valdtr, &tst_test_error); sieve_validator_register_command(valdtr, &tst_test_result); sieve_validator_register_command(valdtr, &tst_test_result_execute); diff --git a/src/testsuite/testsuite-common.h b/src/testsuite/testsuite-common.h index 2d5022be0..398b4b441 100644 --- a/src/testsuite/testsuite-common.h +++ b/src/testsuite/testsuite-common.h @@ -55,6 +55,7 @@ extern const struct sieve_command cmd_test_binary; extern const struct sieve_command tst_test_script_compile; extern const struct sieve_command tst_test_script_run; +extern const struct sieve_command tst_test_multiscript; extern const struct sieve_command tst_test_error; extern const struct sieve_command tst_test_result; extern const struct sieve_command tst_test_result_execute; @@ -70,6 +71,7 @@ enum testsuite_operation_code { TESTSUITE_OPERATION_TEST_SET, TESTSUITE_OPERATION_TEST_SCRIPT_COMPILE, TESTSUITE_OPERATION_TEST_SCRIPT_RUN, + TESTSUITE_OPERATION_TEST_MULTISCRIPT, TESTSUITE_OPERATION_TEST_ERROR, TESTSUITE_OPERATION_TEST_RESULT, TESTSUITE_OPERATION_TEST_RESULT_EXECUTE, @@ -89,6 +91,7 @@ extern const struct sieve_operation test_fail_operation; extern const struct sieve_operation test_set_operation; extern const struct sieve_operation test_script_compile_operation; extern const struct sieve_operation test_script_run_operation; +extern const struct sieve_operation test_multiscript_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; diff --git a/src/testsuite/testsuite-script.c b/src/testsuite/testsuite-script.c index a12ff4005..f234d2f99 100644 --- a/src/testsuite/testsuite-script.c +++ b/src/testsuite/testsuite-script.c @@ -35,13 +35,11 @@ void testsuite_script_deinit(void) } } -bool testsuite_script_compile(const char *script_path) +static struct sieve_binary *_testsuite_script_compile(const char *script_path) { struct sieve_binary *sbin; const char *sieve_dir; - testsuite_log_clear_messages(); - /* Initialize environment */ sieve_dir = strrchr(script_path, '/'); if ( sieve_dir == NULL ) @@ -53,8 +51,19 @@ bool testsuite_script_compile(const char *script_path) env_put(t_strconcat("SIEVE_DIR=", sieve_dir, "included", NULL)); env_put(t_strconcat("SIEVE_GLOBAL_DIR=", sieve_dir, "included-global", NULL)); - if ( (sbin = sieve_compile(script_path, NULL, testsuite_log_ehandler)) == NULL ) + return NULL; + + return sbin; +} + +bool testsuite_script_compile(const char *script_path) +{ + struct sieve_binary *sbin; + + testsuite_log_clear_messages(); + + if ( (sbin=_testsuite_script_compile(script_path)) == NULL ) return FALSE; if ( _testsuite_compiled_script != NULL ) { @@ -125,3 +134,63 @@ void testsuite_script_set_binary(struct sieve_binary *sbin) sieve_binary_ref(sbin); } +/* + * Multiscript + */ + +bool testsuite_script_multiscript +(const struct sieve_runtime_env *renv, ARRAY_TYPE (const_string) *scriptfiles) +{ + struct sieve_script_env scriptenv; + struct sieve_multiscript *mscript; + struct sieve_result *result; + const char *const *scripts; + unsigned int count, i; + bool more = TRUE; + int ret; + + testsuite_log_clear_messages(); + + /* Compose script execution environment */ + memset(&scriptenv, 0, sizeof(scriptenv)); + scriptenv.default_mailbox = "INBOX"; + scriptenv.namespaces = NULL; + scriptenv.username = "user"; + scriptenv.hostname = "host.example.com"; + scriptenv.postmaster_address = "postmaster@example.com"; + scriptenv.smtp_open = NULL; + scriptenv.smtp_close = NULL; + scriptenv.duplicate_mark = NULL; + scriptenv.duplicate_check = NULL; + + result = testsuite_result_get(); + + /* Start execution */ + + mscript = sieve_multiscript_start_execute(renv->msgdata, &scriptenv); + + /* Execute scripts before main script */ + + scripts = array_get(scriptfiles, &count); + + for ( i = 0; i < count && more; i++ ) { + struct sieve_binary *sbin = NULL; + const char *script_path = scripts[i]; + bool final = ( i == count - 1 ); + + /* Open */ + + if ( (sbin=_testsuite_script_compile(script_path)) == NULL ) + break; + + /* Execute */ + + more = sieve_multiscript_run(mscript, sbin, testsuite_log_ehandler, final); + + sieve_close(&sbin); + } + + ret = sieve_multiscript_finish(&mscript, testsuite_log_ehandler, NULL); + + return ( ret > 0 ); +} diff --git a/src/testsuite/testsuite-script.h b/src/testsuite/testsuite-script.h index 7ce8992d0..2c720c2b7 100644 --- a/src/testsuite/testsuite-script.h +++ b/src/testsuite/testsuite-script.h @@ -11,6 +11,8 @@ void testsuite_script_deinit(void); bool testsuite_script_compile(const char *script_path); bool testsuite_script_run(const struct sieve_runtime_env *renv); +bool testsuite_script_multiscript +(const struct sieve_runtime_env *renv, ARRAY_TYPE (const_string) *scriptfiles); struct sieve_binary *testsuite_script_get_binary(void); void testsuite_script_set_binary(struct sieve_binary *sbin); diff --git a/src/testsuite/tst-test-multiscript.c b/src/testsuite/tst-test-multiscript.c new file mode 100644 index 000000000..e01315968 --- /dev/null +++ b/src/testsuite/tst-test-multiscript.c @@ -0,0 +1,170 @@ +/* Copyright (c) 2002-2009 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-script.h" + +/* + * Test_multiscript command + * + * Syntax: + * test_multiscript <scripts: string-list> + */ + +static bool tst_test_multiscript_validate + (struct sieve_validator *validator, struct sieve_command_context *cmd); +static bool tst_test_multiscript_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx); + +const struct sieve_command tst_test_multiscript = { + "test_multiscript", + SCT_TEST, + 1, 0, FALSE, FALSE, + NULL, NULL, + tst_test_multiscript_validate, + tst_test_multiscript_generate, + NULL +}; + +/* + * Operation + */ + +static bool tst_test_multiscript_operation_dump + (const struct sieve_operation *op, + const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int tst_test_multiscript_operation_execute + (const struct sieve_operation *op, + const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation test_multiscript_operation = { + "TEST_MULTISCRIPT", + &testsuite_extension, + TESTSUITE_OPERATION_TEST_MULTISCRIPT, + tst_test_multiscript_operation_dump, + tst_test_multiscript_operation_execute +}; + +/* + * Validation + */ + +static bool tst_test_multiscript_validate +(struct sieve_validator *valdtr ATTR_UNUSED, struct sieve_command_context *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "scripts", 1, SAAT_STRING_LIST) ) { + return FALSE; + } + + return sieve_validator_argument_activate(valdtr, tst, arg, FALSE); +} + +/* + * Code generation + */ + +static inline struct testsuite_generator_context * + _get_generator_context(struct sieve_generator *gentr) +{ + return (struct testsuite_generator_context *) + sieve_generator_extension_get_context(gentr, &testsuite_extension); +} + +static bool tst_test_multiscript_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command_context *tst) +{ + sieve_operation_emit_code(cgenv->sbin, &test_multiscript_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, tst, NULL); +} + +/* + * Code dump + */ + +static bool tst_test_multiscript_operation_dump +(const struct sieve_operation *op ATTR_UNUSED, + const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + sieve_code_dumpf(denv, "TEST_MULTISCRIPT:"); + sieve_code_descend(denv); + + if ( !sieve_opr_stringlist_dump(denv, address, "scripts") ) + return FALSE; + + return TRUE; +} + +/* + * Intepretation + */ + +static int tst_test_multiscript_operation_execute +(const struct sieve_operation *op ATTR_UNUSED, + const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + struct sieve_coded_stringlist *scripts_list; + string_t *script_name; + const char *script_path; + ARRAY_TYPE (const_string) scriptfiles; + bool result = TRUE; + + /* + * Read operands + */ + + if ( (scripts_list=sieve_opr_stringlist_read(renv, address)) == NULL ) { + sieve_runtime_trace_error(renv, "invalid scripts operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, "TEST MULTISCRIPT"); + + t_array_init(&scriptfiles, 16); + + script_path = sieve_script_dirpath(renv->script); + if ( script_path == NULL ) + return SIEVE_EXEC_FAILURE; + + script_name = NULL; + while ( result && + (result=sieve_coded_stringlist_next_item(scripts_list, &script_name)) + && script_name != NULL ) { + + const char *path = + t_strconcat(script_path, "/", str_c(script_name), NULL); + + /* Attempt script compile */ + array_append(&scriptfiles, &path, 1); + } + + result = result && testsuite_script_multiscript(renv, &scriptfiles); + + /* Set result */ + sieve_interpreter_set_test_result(renv->interp, result); + + return SIEVE_EXEC_OK; +} + + + + diff --git a/tests/extensions/imap4flags/multiscript.svtest b/tests/extensions/imap4flags/multiscript.svtest new file mode 100644 index 000000000..0a0418cb1 --- /dev/null +++ b/tests/extensions/imap4flags/multiscript.svtest @@ -0,0 +1,13 @@ +require "vnd.dovecot.testsuite"; + +test "Segfault Trigger 1" { + + if not test_multiscript [ + "multiscript/group-spam.sieve", + "multiscript/spam.sieve", + "multiscript/sent-store.sieve"] + { + test_fail "failed multiscript execution"; + } +} + diff --git a/tests/extensions/imap4flags/multiscript/group-spam.sieve b/tests/extensions/imap4flags/multiscript/group-spam.sieve new file mode 100644 index 000000000..700d33de5 --- /dev/null +++ b/tests/extensions/imap4flags/multiscript/group-spam.sieve @@ -0,0 +1,14 @@ +require ["fileinto", "variables", "envelope"]; + +if header :contains "X-Group-Mail" ["Yes", "YES", "1"] { + if header :contains "X-Spam-Flag" ["Yes", "YES", "1"] { + if envelope :matches :localpart "to" "*" { + fileinto "group/${1}/SPAM"; stop; + } + } + if address :is ["To"] "sales@florist.ru" { + fileinto "group/info/Orders"; + } + stop; +} +keep; diff --git a/tests/extensions/imap4flags/multiscript/sent-store.sieve b/tests/extensions/imap4flags/multiscript/sent-store.sieve new file mode 100644 index 000000000..e5e3906df --- /dev/null +++ b/tests/extensions/imap4flags/multiscript/sent-store.sieve @@ -0,0 +1,7 @@ +require ["imap4flags"]; + +if header :contains "X-Set-Seen" ["Yes", "YES", "1"] { + setflag "\\Seen"; +} + +keep; diff --git a/tests/extensions/imap4flags/multiscript/spam.sieve b/tests/extensions/imap4flags/multiscript/spam.sieve new file mode 100644 index 000000000..9e1b6c349 --- /dev/null +++ b/tests/extensions/imap4flags/multiscript/spam.sieve @@ -0,0 +1,8 @@ +require ["fileinto"]; + +if header :contains "X-Spam-Flag" ["Yes", "YES", "1"] { + fileinto "SPAM"; +} +keep; + + -- GitLab