diff --git a/.hgignore b/.hgignore index bdfb8af23c419e3069bb90782ce0e35eaa3ae7a0..ead9aba20440a0422f29b69bd7ad693185f9144f 100644 --- a/.hgignore +++ b/.hgignore @@ -1,7 +1,6 @@ syntax: glob aclocal.m4 autom4te.cache -compile config.cache config.guess dsieve-config.h diff --git a/src/lib-sieve/sieve-script.c b/src/lib-sieve/sieve-script.c index 77716302478197a679621ed51a24c51296478308..6c676193634dcd94f115f043fb308239660f456e 100644 --- a/src/lib-sieve/sieve-script.c +++ b/src/lib-sieve/sieve-script.c @@ -244,6 +244,11 @@ const char *sieve_script_path(struct sieve_script *script) return script->path; } +const char *sieve_script_dirpath(struct sieve_script *script) +{ + return script->dirpath; +} + const char *sieve_script_binpath(struct sieve_script *script) { return t_strconcat(script->dirpath, "/", script->basename, ".svbin", NULL); diff --git a/src/lib-sieve/sieve-script.h b/src/lib-sieve/sieve-script.h index 548e9bc6100c362edd8a254242cd914ee53d0c8b..8747f9bcb2485e8780ec30d21c25f23f0355cada 100644 --- a/src/lib-sieve/sieve-script.h +++ b/src/lib-sieve/sieve-script.h @@ -34,5 +34,6 @@ const char *sieve_script_name(struct sieve_script *script); const char *sieve_script_filename(struct sieve_script *script); const char *sieve_script_path(struct sieve_script *script); const char *sieve_script_binpath(struct sieve_script *script); +const char *sieve_script_dirpath(struct sieve_script *script); #endif /* __SIEVE_SCRIPT_H */ diff --git a/src/testsuite/Makefile.am b/src/testsuite/Makefile.am index 945b9b7b575b899904ed6632a365567c2c24763d..a25a30c02e3b65748bf6e1ef4a1e30ccb9b7334c 100644 --- a/src/testsuite/Makefile.am +++ b/src/testsuite/Makefile.am @@ -37,17 +37,21 @@ ldadd = \ testsuite_LDADD = $(ldadd) testsuite_DEPENDENCIES = $(libs) -cmds = \ +commands = \ cmd-test.c \ cmd-test-fail.c \ cmd-test-set.c +tests = \ + tst-test-compile.c + testsuite_SOURCES = \ namespaces.c \ mail-raw.c \ testsuite-common.c \ testsuite-objects.c \ - $(cmds) \ + $(commands) \ + $(tests) \ ext-testsuite.c \ testsuite.c @@ -70,7 +74,9 @@ test_cases = \ tests/match-types/contains.svtest \ tests/match-types/matches.svtest \ tests/address-parts/subaddress.svtest \ - tests/extensions/variables/basic.svtest + tests/extensions/variables/basic.svtest \ + tests/compile/compile.svtest \ + tests/compile/compile-examples.svtest $(test_cases): @$(TESTSUITE_BIN) $@ diff --git a/src/testsuite/cmd-test-fail.c b/src/testsuite/cmd-test-fail.c index f3a9994cb1e4d24b6c3476887306dbbe86a0e5a2..9106a56985e96c150d98bbbba7a03e487cd3e67a 100644 --- a/src/testsuite/cmd-test-fail.c +++ b/src/testsuite/cmd-test-fail.c @@ -9,25 +9,18 @@ #include "testsuite-common.h" -/* Predeclarations */ - -static bool cmd_test_fail_operation_dump - (const struct sieve_operation *op, - const struct sieve_dumptime_env *denv, sieve_size_t *address); -static bool cmd_test_fail_operation_execute - (const struct sieve_operation *op, - const struct sieve_runtime_env *renv, sieve_size_t *address); +/* + * Test_fail command + * + * Syntax: + * test <reason: string> + */ static bool cmd_test_fail_validate (struct sieve_validator *validator, struct sieve_command_context *cmd); static bool cmd_test_fail_generate (const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx); -/* Test_fail command - * - * Syntax: - * test <reason: string> - */ const struct sieve_command cmd_test_fail = { "test_fail", SCT_COMMAND, @@ -38,7 +31,16 @@ const struct sieve_command cmd_test_fail = { NULL }; -/* Test operation */ +/* + * Test operation + */ + +static bool cmd_test_fail_operation_dump + (const struct sieve_operation *op, + const struct sieve_dumptime_env *denv, sieve_size_t *address); +static bool cmd_test_fail_operation_execute + (const struct sieve_operation *op, + const struct sieve_runtime_env *renv, sieve_size_t *address); const struct sieve_operation test_fail_operation = { "TEST_FAIL", @@ -48,7 +50,9 @@ const struct sieve_operation test_fail_operation = { cmd_test_fail_operation_execute }; -/* Validation */ +/* + * Validation + */ static bool cmd_test_fail_validate (struct sieve_validator *valdtr ATTR_UNUSED, struct sieve_command_context *cmd) @@ -63,7 +67,9 @@ static bool cmd_test_fail_validate return sieve_validator_argument_activate(valdtr, cmd, arg, FALSE); } -/* Code generation */ +/* + * Code generation + */ static inline struct testsuite_generator_context * _get_generator_context(struct sieve_generator *gentr) @@ -99,7 +105,7 @@ static bool cmd_test_fail_operation_dump const struct sieve_dumptime_env *denv, sieve_size_t *address) { unsigned int pc; - int offset; + int offset; sieve_code_dumpf(denv, "TEST_FAIL:"); sieve_code_descend(denv); @@ -127,18 +133,12 @@ static bool cmd_test_fail_operation_execute { string_t *reason; - t_push(); - - if ( !sieve_opr_string_read(renv, address, &reason) ) { - t_pop(); + if ( !sieve_opr_string_read(renv, address, &reason) ) return FALSE; - } sieve_runtime_trace(renv, "TEST FAIL"); testsuite_test_fail(reason); - t_pop(); - return sieve_interpreter_program_jump(renv->interp, TRUE); } diff --git a/src/testsuite/cmd-test-set.c b/src/testsuite/cmd-test-set.c index d6ffcd22c0688c3b0b865c2bab1faa8f48899b73..2381680fd7f01003c49d30ddd16b427e9910ceba 100644 --- a/src/testsuite/cmd-test-set.c +++ b/src/testsuite/cmd-test-set.c @@ -19,26 +19,18 @@ #include <stdio.h> -/* Forward declarations */ - -static bool cmd_test_set_operation_dump - (const struct sieve_operation *op, - const struct sieve_dumptime_env *denv, sieve_size_t *address); -static bool cmd_test_set_operation_execute - (const struct sieve_operation *op, - const struct sieve_runtime_env *renv, sieve_size_t *address); +/* + * Test_set command + * + * Syntax + * redirect <address: string> + */ static bool cmd_test_set_validate (struct sieve_validator *validator, struct sieve_command_context *cmd); static bool cmd_test_set_generate (const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx); -/* Test_set command - * - * Syntax - * redirect <address: string> - */ - const struct sieve_command cmd_test_set = { "test_set", SCT_COMMAND, @@ -49,7 +41,16 @@ const struct sieve_command cmd_test_set = { NULL }; -/* Test_set operation */ +/* + * Test_set operation + */ + +static bool cmd_test_set_operation_dump + (const struct sieve_operation *op, + const struct sieve_dumptime_env *denv, sieve_size_t *address); +static bool cmd_test_set_operation_execute + (const struct sieve_operation *op, + const struct sieve_runtime_env *renv, sieve_size_t *address); const struct sieve_operation test_set_operation = { "TEST_SET", @@ -93,15 +94,12 @@ static bool cmd_test_set_validate */ static bool cmd_test_set_generate - (const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx) +(const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx) { sieve_operation_emit_code(cgenv->sbin, &test_set_operation); /* Generate arguments */ - if ( !sieve_generate_arguments(cgenv, ctx, NULL) ) - return FALSE; - - return TRUE; + return sieve_generate_arguments(cgenv, ctx, NULL); } /* @@ -132,31 +130,20 @@ static bool cmd_test_set_operation_execute string_t *value; int member_id; - t_push(); - if ( (object=testsuite_object_read_member(renv->sbin, address, &member_id)) - == NULL ) { - t_pop(); + == NULL ) return FALSE; - } - if ( !sieve_opr_string_read(renv, address, &value) ) { - t_pop(); + if ( !sieve_opr_string_read(renv, address, &value) ) return FALSE; - } sieve_runtime_trace(renv, "TEST SET command (%s = \"%s\")", testsuite_object_member_name(object, member_id), str_c(value)); - if ( object->set_member == NULL ) { - t_pop(); + if ( object->set_member == NULL ) return FALSE; - } - object->set_member(member_id, value); - - t_pop(); - + object->set_member(member_id, value); return TRUE; } diff --git a/src/testsuite/cmd-test.c b/src/testsuite/cmd-test.c index 078c1535468f8ca5a8b840d8e3ca4518c173bc2f..b505f502abce0ce38da757b2a6772b547d1c98ae 100644 --- a/src/testsuite/cmd-test.c +++ b/src/testsuite/cmd-test.c @@ -9,28 +9,18 @@ #include "testsuite-common.h" -/* Predeclarations */ - -static bool cmd_test_operation_dump - (const struct sieve_operation *op, - const struct sieve_dumptime_env *denv, sieve_size_t *address); -static bool cmd_test_operation_execute - (const struct sieve_operation *op, - const struct sieve_runtime_env *renv, sieve_size_t *address); -static bool cmd_test_finish_operation_execute - (const struct sieve_operation *op, - const struct sieve_runtime_env *renv, sieve_size_t *address); +/* + * Test command + * + * Syntax: + * test <test-name: string> <block> + */ static bool cmd_test_validate (struct sieve_validator *validator, struct sieve_command_context *cmd); static bool cmd_test_generate (const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx); -/* Test command - * - * Syntax: - * test <test-name: string> <block> - */ const struct sieve_command cmd_test = { "test", SCT_COMMAND, @@ -41,8 +31,19 @@ const struct sieve_command cmd_test = { NULL }; +/* + * Test operations + */ + /* Test operation */ +static bool cmd_test_operation_dump + (const struct sieve_operation *op, + const struct sieve_dumptime_env *denv, sieve_size_t *address); +static bool cmd_test_operation_execute + (const struct sieve_operation *op, + const struct sieve_runtime_env *renv, sieve_size_t *address); + const struct sieve_operation test_operation = { "TEST", &testsuite_extension, @@ -51,6 +52,12 @@ const struct sieve_operation test_operation = { cmd_test_operation_execute }; +/* Test_finish operation */ + +static bool cmd_test_finish_operation_execute + (const struct sieve_operation *op, + const struct sieve_runtime_env *renv, sieve_size_t *address); + const struct sieve_operation test_finish_operation = { "TEST-FINISH", &testsuite_extension, @@ -59,7 +66,9 @@ const struct sieve_operation test_finish_operation = { cmd_test_finish_operation_execute }; -/* Validation */ +/* + * Validation + */ static bool cmd_test_validate (struct sieve_validator *valdtr ATTR_UNUSED, struct sieve_command_context *cmd) @@ -82,7 +91,9 @@ static bool cmd_test_validate return sieve_validator_argument_activate(valdtr, cmd, arg, FALSE); } -/* Code generation */ +/* + * Code generation + */ static inline struct testsuite_generator_context * _get_generator_context(struct sieve_generator *gentr) @@ -142,19 +153,12 @@ static bool cmd_test_operation_execute { string_t *test_name; - t_push(); - - if ( !sieve_opr_string_read(renv, address, &test_name) ) { - t_pop(); + if ( !sieve_opr_string_read(renv, address, &test_name) ) return FALSE; - } - testsuite_test_start(test_name); - sieve_runtime_trace(renv, "TEST \"%s\"", str_c(test_name)); - - t_pop(); - + + testsuite_test_start(test_name); return TRUE; } @@ -166,7 +170,6 @@ static bool cmd_test_finish_operation_execute sieve_runtime_trace(renv, "TEST FINISHED"); testsuite_test_succeed(NULL); - return TRUE; } diff --git a/src/testsuite/ext-testsuite.c b/src/testsuite/ext-testsuite.c index 2d493b3debc53d894587adad71d71e59b6ea08c5..7b4389e52c74c1fc18f1db592c85cfd939d85765 100644 --- a/src/testsuite/ext-testsuite.c +++ b/src/testsuite/ext-testsuite.c @@ -39,13 +39,18 @@ extern const struct sieve_command cmd_test; extern const struct sieve_command cmd_test_fail; extern const struct sieve_command cmd_test_set; +/* Tests */ + +extern const struct sieve_command tst_test_compile; + /* Operations */ const struct sieve_operation *testsuite_operations[] = { &test_operation, &test_finish_operation, &test_fail_operation, - &test_set_operation + &test_set_operation, + &test_compile_operation }; /* Operands */ @@ -84,6 +89,8 @@ 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, &tst_test_compile); return testsuite_validator_context_initialize(valdtr); } diff --git a/src/testsuite/tests/compile/compile-examples.svtest b/src/testsuite/tests/compile/compile-examples.svtest new file mode 100644 index 0000000000000000000000000000000000000000..b1161e47498d91f4ad16dfbde5a4f58d45751a6e --- /dev/null +++ b/src/testsuite/tests/compile/compile-examples.svtest @@ -0,0 +1,51 @@ +require "vnd.dovecot.testsuite"; + +# Compile all example scripts + +test "Elvey example" { + if not test_compile "../../../../sieve/examples/elvey.sieve" { + test_fail "could not compile"; + } +} + +test "M. Johnson example" { + if not test_compile "../../../../sieve/examples/mjohnson.sieve" { + test_fail "could not compile"; + } +} + +test "RFC 3028 example" { + if not test_compile "../../../../sieve/examples/rfc3028.sieve" { + test_fail "could not compile"; + } +} + +test "Sieve examples" { + if not test_compile "../../../../sieve/examples/sieve_examples.sieve" { + test_fail "could not compile"; + } +} + +test "Vivil example" { + if not test_compile "../../../../sieve/examples/vivil.sieve" { + test_fail "could not compile"; + } +} + +test "Jerry example" { + if not test_compile "../../../../sieve/examples/jerry.sieve" { + test_fail "could not compile"; + } +} + +test "M. Klose example" { + if not test_compile "../../../../sieve/examples/mklose.sieve" { + test_fail "could not compile"; + } +} + +test "Sanjay example" { + if not test_compile "../../../../sieve/examples/sanjay.sieve" { + test_fail "could not compile"; + } +} diff --git a/src/testsuite/tests/compile/compile.svtest b/src/testsuite/tests/compile/compile.svtest new file mode 100644 index 0000000000000000000000000000000000000000..5a54d6b558b985dd25a89f211cdfdb42479e5aeb --- /dev/null +++ b/src/testsuite/tests/compile/compile.svtest @@ -0,0 +1,16 @@ +require "vnd.dovecot.testsuite"; + +# Just test whether valid scripts will compile without problems + +test "Trivial" { + if not test_compile "trivial.sieve" { + test_fail "could not compile"; + } +} + +test "Redirect" { + if not test_compile "redirect.sieve" { + test_fail "could not compile"; + } +} + diff --git a/src/testsuite/tests/compile/redirect.sieve b/src/testsuite/tests/compile/redirect.sieve new file mode 100644 index 0000000000000000000000000000000000000000..890855202e8c4730f005a1d04103bf49fff3a8e6 --- /dev/null +++ b/src/testsuite/tests/compile/redirect.sieve @@ -0,0 +1,23 @@ +# Test various white space occurences +redirect "stephan@rename-it.nl"; +redirect " stephan@rename-it.nl"; +redirect "stephan @rename-it.nl"; +redirect "stephan@ rename-it.nl"; +redirect "stephan@rename-it.nl "; +redirect " stephan @ rename-it.nl "; +redirect "Stephan Bosch<stephan@rename-it.nl>"; +redirect " Stephan Bosch<stephan@rename-it.nl>"; +redirect "Stephan Bosch <stephan@rename-it.nl>"; +redirect "Stephan Bosch< stephan@rename-it.nl>"; +redirect "Stephan Bosch<stephan @rename-it.nl>"; +redirect "Stephan Bosch<stephan@ rename-it.nl>"; +redirect "Stephan Bosch<stephan@rename-it.nl >"; +redirect "Stephan Bosch<stephan@rename-it.nl> "; +redirect " Stephan Bosch < stephan @ rename-it.nl > "; + +# Test address syntax +redirect "\"Stephan Bosch\"@rename-it.nl"; +redirect "Stephan.Bosch@rename-it.nl"; +redirect "Stephan.Bosch@ReNaMe-It.Nl"; +redirect "Stephan Bosch <stephan@rename-it.nl>"; + diff --git a/src/testsuite/tests/compile/trivial.sieve b/src/testsuite/tests/compile/trivial.sieve new file mode 100644 index 0000000000000000000000000000000000000000..1bb76a9cc364969c8067e5eee528f616edd49109 --- /dev/null +++ b/src/testsuite/tests/compile/trivial.sieve @@ -0,0 +1,3 @@ +keep; +discard; +stop; diff --git a/src/testsuite/testsuite-common.h b/src/testsuite/testsuite-common.h index 761b4e5566c0cafe3c451417504ddc2932fffc77..54aea4f94fa41a9aa5d306d113b4947b46b0fd9d 100644 --- a/src/testsuite/testsuite-common.h +++ b/src/testsuite/testsuite-common.h @@ -42,13 +42,15 @@ enum testsuite_operation_code { TESTSUITE_OPERATION_TEST, TESTSUITE_OPERATION_TEST_FINISH, TESTSUITE_OPERATION_TEST_FAIL, - TESTSUITE_OPERATION_TEST_SET + TESTSUITE_OPERATION_TEST_SET, + TESTSUITE_OPERATION_TEST_COMPILE }; extern const struct sieve_operation test_operation; extern const struct sieve_operation test_finish_operation; extern const struct sieve_operation test_fail_operation; extern const struct sieve_operation test_set_operation; +extern const struct sieve_operation test_compile_operation; /* Testsuite operands */ diff --git a/src/testsuite/tst-test-compile.c b/src/testsuite/tst-test-compile.c new file mode 100644 index 0000000000000000000000000000000000000000..90f0a87e4c33684870452bb36b89c79f2015b83b --- /dev/null +++ b/src/testsuite/tst-test-compile.c @@ -0,0 +1,152 @@ +#include "sieve-common.h" +#include "sieve-script.h" +#include "sieve-commands.h" +#include "sieve-commands-private.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" + +/* + * Test_compile command + * + * Syntax: + * test <reason: string> + */ + +static bool tst_test_compile_validate + (struct sieve_validator *validator, struct sieve_command_context *cmd); +static bool tst_test_compile_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx); + +const struct sieve_command tst_test_compile = { + "test_compile", + SCT_TEST, + 1, 0, FALSE, FALSE, + NULL, NULL, + tst_test_compile_validate, + tst_test_compile_generate, + NULL +}; + +/* Test_compile operation */ + +static bool tst_test_compile_operation_dump + (const struct sieve_operation *op, + const struct sieve_dumptime_env *denv, sieve_size_t *address); +static bool tst_test_compile_operation_execute + (const struct sieve_operation *op, + const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation test_compile_operation = { + "TEST_COMPILE", + &testsuite_extension, + TESTSUITE_OPERATION_TEST_COMPILE, + tst_test_compile_operation_dump, + tst_test_compile_operation_execute +}; + +/* Validation */ + +static bool tst_test_compile_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, "script", 1, SAAT_STRING) ) { + 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_compile_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command_context *tst) +{ + sieve_operation_emit_code(cgenv->sbin, &test_compile_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, tst, NULL); +} + +/* + * Code dump + */ + +static bool tst_test_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_COMPILE:"); + sieve_code_descend(denv); + + if ( !sieve_opr_string_dump(denv, address) ) + return FALSE; + + return TRUE; +} + +/* + * Intepretation + */ + +static bool tst_test_compile_operation_execute +(const struct sieve_operation *op ATTR_UNUSED, + const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + struct sieve_error_handler *ehandler; + struct sieve_binary *sbin; + + string_t *script_name; + const char *script_path; + bool result = TRUE; + + if ( !sieve_opr_string_read(renv, address, &script_name) ) + return FALSE; + + sieve_runtime_trace(renv, "TEST COMPILE: %s", str_c(script_name)); + + script_path = sieve_script_dirpath(renv->script); + if ( script_path == NULL ) + return FALSE; + + script_path = t_strconcat(script_path, "/", str_c(script_name), NULL); + + /* Attempt script compile */ + + ehandler = sieve_stderr_ehandler_create(0); + sieve_error_handler_accept_infolog(ehandler, TRUE); + + if ( (sbin = sieve_compile(script_path, ehandler)) == NULL ) { + sieve_error_handler_unref(&ehandler); + result = FALSE; + } else { + sieve_close(&sbin); + } + + sieve_error_handler_unref(&ehandler); + + /* Set result */ + sieve_interpreter_set_test_result(renv->interp, result); + + return TRUE; +} + + + +