From f597ac97e279ff3b17cb24c5acd124a2184facdc Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan@rename-it.nl> Date: Mon, 28 Jul 2008 20:39:51 +0200 Subject: [PATCH] Testsuite: added a few more compile error test cases. --- src/lib-sieve/sieve-error.c | 6 + src/lib-sieve/sieve-error.h | 2 + src/lib-sieve/sieve-validator.c | 20 +-- src/testsuite/tests/compile/errors.svtest | 125 +++++++++++++++--- .../tests/compile/errors/address.sieve | 71 ++++++++++ .../tests/compile/errors/header.sieve | 47 ++++--- src/testsuite/tests/compile/errors/if.sieve | 78 +++++++++++ .../tests/compile/errors/require.sieve | 39 ++++++ src/testsuite/testsuite-common.c | 6 +- 9 files changed, 351 insertions(+), 43 deletions(-) create mode 100644 src/testsuite/tests/compile/errors/address.sieve create mode 100644 src/testsuite/tests/compile/errors/if.sieve create mode 100644 src/testsuite/tests/compile/errors/require.sieve diff --git a/src/lib-sieve/sieve-error.c b/src/lib-sieve/sieve-error.c index 44bb0cc40..a2247787e 100644 --- a/src/lib-sieve/sieve-error.c +++ b/src/lib-sieve/sieve-error.c @@ -168,6 +168,12 @@ void sieve_error_handler_unref(struct sieve_error_handler **ehandler) *ehandler = NULL; } +void sieve_error_handler_reset(struct sieve_error_handler *ehandler) +{ + ehandler->errors = 0; + ehandler->warnings = 0; +} + /* Output errors directly to stderror (merge this with logfile below?) */ static void sieve_stderr_verror diff --git a/src/lib-sieve/sieve-error.h b/src/lib-sieve/sieve-error.h index e3a02ac63..5d25c0138 100644 --- a/src/lib-sieve/sieve-error.h +++ b/src/lib-sieve/sieve-error.h @@ -121,6 +121,8 @@ bool sieve_errors_more_allowed(struct sieve_error_handler *ehandler); void sieve_error_handler_ref(struct sieve_error_handler *ehandler); void sieve_error_handler_unref(struct sieve_error_handler **ehandler); +void sieve_error_handler_reset(struct sieve_error_handler *ehandler); + /* * Error handlers */ diff --git a/src/lib-sieve/sieve-validator.c b/src/lib-sieve/sieve-validator.c index 01f81bb4a..f6f38ff8a 100644 --- a/src/lib-sieve/sieve-validator.c +++ b/src/lib-sieve/sieve-validator.c @@ -826,6 +826,7 @@ static bool sieve_validate_command enum sieve_ast_type ast_type = sieve_ast_node_type(cmd_node); bool result = TRUE; struct sieve_command_registration *cmd_reg; + const struct sieve_command *command = NULL; i_assert( ast_type == SAT_TEST || ast_type == SAT_COMMAND ); @@ -835,7 +836,7 @@ static bool sieve_validate_command (valdtr, cmd_node->identifier); if ( cmd_reg != NULL && cmd_reg->command != NULL ) { - const struct sieve_command *command = cmd_reg->command; + command = cmd_reg->command; /* Identifier = "" when the command was previously marked as unknown */ if ( *(command->identifier) != '\0' ) { @@ -899,14 +900,17 @@ static bool sieve_validate_command * Descend further into the AST */ - /* Tests */ - if ( result || sieve_errors_more_allowed(valdtr->ehandler) ) - result = sieve_validate_test_list(valdtr, cmd_node) && result; + if ( command != NULL ) { + /* Tests */ + if ( command->subtests > 0 && + (result || sieve_errors_more_allowed(valdtr->ehandler)) ) + result = sieve_validate_test_list(valdtr, cmd_node) && result; - /* Command block */ - if ( ast_type == SAT_COMMAND && - (result || sieve_errors_more_allowed(valdtr->ehandler)) ) - result = sieve_validate_block(valdtr, cmd_node) && result; + /* Command block */ + if ( command->block_allowed && ast_type == SAT_COMMAND && + (result || sieve_errors_more_allowed(valdtr->ehandler)) ) + result = sieve_validate_block(valdtr, cmd_node) && result; + } return result; } diff --git a/src/testsuite/tests/compile/errors.svtest b/src/testsuite/tests/compile/errors.svtest index ac841bd80..28e709856 100644 --- a/src/testsuite/tests/compile/errors.svtest +++ b/src/testsuite/tests/compile/errors.svtest @@ -3,64 +3,157 @@ require "vnd.dovecot.testsuite"; require "relational"; require "comparator-i;ascii-numeric"; +/* + * Errors triggered in the compiled scripts are pretty reduntant over the + * tested commands, but we want to be thorough. + */ + +/* + * Header test + */ + test "Header errors" { if test_compile "errors/header.sieve" { test_fail "compile should have failed."; } - if not test_error :count "eq" :comparator "i;ascii-numeric" "11" { + if not test_error :count "eq" :comparator "i;ascii-numeric" "10" { test_fail "wrong number of errors reported"; } if not test_error :index 1 :matches - "unknown * ':isnot' for * header test *" { + "unknown * ':all' for * header test *" { test_fail "error 1 is invalid"; } - if not test_error :index 2 :matches - ":comparator * requires one string argument, * number *" { + if not test_error :index 2 :matches + "*header test * string list * 1 (header names), but * number *" { test_fail "error 2 is invalid"; } if not test_error :index 3 :matches - "unknown tagged argument ':all' * header test *" { + "*header test * string list * 2 (key list), * number *" { test_fail "error 3 is invalid"; - } + } - if not test_error :index 4 :matches - "*header test * string list * 2 (key list), * number *" { + if not test_error :index 4 :matches + "* unexpected tagged argument ':tag' while *" { test_fail "error 4 is invalid"; } if not test_error :index 5 :matches - "*header test expects * string list * 1 (header names), but * number *" { + "* header test requires 2 *, but 1 *" { test_fail "error 5 is invalid"; } if not test_error :index 6 :matches - "* unexpected tagged argument ':tag' while *" { + "* header test requires 2 *, but 0 *" { test_fail "error 6 is invalid"; } if not test_error :index 7 :matches - "* header test requires 2 *, but 1 *" { + "*header test accepts no sub-tests* are specified*" { test_fail "error 7 is invalid"; } if not test_error :index 8 :matches - "* header test requires 2 *, but 0 *" { + "* use test 'header' * command*" { test_fail "error 8 is invalid"; } if not test_error :index 9 :matches - "*unknown * ':hufter' * header test *" { + "* use test 'header' * command*" { test_fail "error 9 is invalid"; } - if not test_error :index 10 :matches - "*header test accepts no sub-tests, but tests * anyway" { - test_fail "error 10 is invalid"; + if test_error :index 4 :contains "radish" { + test_fail "error test matched nonsense"; } } +/* + * Address test + */ + + +test "Address errors" { + if test_compile "errors/address.sieve" { + test_fail "compile should have failed."; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "9" { + test_fail "wrong number of errors reported"; + } + + if not test_error :index 1 :matches + "*unknown * ':nonsense' * address test*" { + test_fail "error 1 is invalid"; + } + + if not test_error :index 2 :matches + "*address test expects *string list * 1 (header list),* number * found*" { + test_fail "error 2 is invalid"; + } + + if not test_error :index 3 :matches + "*address test expects *string list * 2 (key list),* number * found*" { + test_fail "error 3 is invalid"; + } + if not test_error :index 4 :matches + "*unexpected *':is' * address test*" { + test_fail "error 4 is invalid"; + } + + if not test_error :index 5 :matches + "*address test * 2 positional arg*, but 1*" { + test_fail "error 5 is invalid"; + } + + if not test_error :index 6 :matches + "*address test * 2 positional arg*, but 0*" { + test_fail "error 6 is invalid"; + } + + if not test_error :index 7 :matches + "*'frop' *not allowed *address test*" { + test_fail "error 7 is invalid"; + } + + if not test_error :index 8 :matches + "*'frop' *not allowed *address test*" { + test_fail "error 8 is invalid"; + } + + if test_error :index 23 :contains "radish" { + test_fail "error test matched nonsense"; + } +} + +/* + * If command + */ + +test "If errors (FIXME: count only)" { + if test_compile "errors/if.sieve" { + test_fail "compile should have failed."; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "12" { + test_fail "wrong number of errors reported"; + } +} + +/* + * Require command + */ + +test "Require errors (FIXME: count only)" { + if test_compile "errors/require.sieve" { + test_fail "compile should have failed."; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "12" { + test_fail "wrong number of errors reported"; + } +} diff --git a/src/testsuite/tests/compile/errors/address.sieve b/src/testsuite/tests/compile/errors/address.sieve new file mode 100644 index 000000000..917da1f8e --- /dev/null +++ b/src/testsuite/tests/compile/errors/address.sieve @@ -0,0 +1,71 @@ +require "comparator-i;ascii-numeric"; + +/* + * Address test errors + * + * Total count: 8 (+1 = 9) + */ + +/* + * Command structure + */ + +# Invalid tag +if address :nonsense :comparator "i;ascii-casemap" :localpart "From" "nico" { + discard; +} + +# Invalid first argument +if address :is :comparator "i;ascii-numeric" :localpart 45 "nico" { + discard; +} + +# Invalid second argument +if address :is :comparator "i;ascii-numeric" :localpart "From" 45 { + discard; +} + +# Invalid second argument +if address :comparator "i;ascii-numeric" :localpart "From" :is { + discard; +} + +# Missing second argument +if address :is :comparator "i;ascii-numeric" :localpart "From" { + discard; +} + +# Missing arguments +if address :is :comparator "i;ascii-numeric" :localpart { + discard; +} + +# Not an error +if address :localpart :is :comparator "i;ascii-casemap" "from" ["frop", "frop"] { + discard; +} + +/* + * Specified headers must contain addresses + */ + +# Invalid header +if address :is "frop" "frml" { + keep; +} + +# Not an error +if address :is "reply-to" "frml" { + keep; +} + +# Invalid header (#2) +if address :is ["to", "frop"] "frml" { + keep; +} + +# Not an error +if address :is ["to", "reply-to"] "frml" { + keep; +} + diff --git a/src/testsuite/tests/compile/errors/header.sieve b/src/testsuite/tests/compile/errors/header.sieve index ac6108ba1..1c87f9425 100644 --- a/src/testsuite/tests/compile/errors/header.sieve +++ b/src/testsuite/tests/compile/errors/header.sieve @@ -1,44 +1,57 @@ require "comparator-i;ascii-numeric"; -if header :isnot :comparator "i;ascii-casemap" "From" "nico" { - discard; -} +/* + * Compile errors for the header test + * + * Total errors: 9 (+1 validation failed msg = 10) + */ -if header :is :comparator 45 "From" "nico" { - discard; +# Unknown tagged argument +if header :all :comparator "i;ascii-casemap" "From" "nico" { + keep; } -if header :all :comparator "i;ascii-numeric" { - keep; +# Wrong first argument +if header :is :comparator "i;ascii-numeric" 45 "nico" { + keep; } +# Wrong second argument if header :is :comparator "i;ascii-numeric" "From" 45 { discard; } -if header :is :comparator "i;ascii-numeric" 45 "nico" { - discard; -} - +# Wrong second argument if header :is :comparator "i;ascii-numeric" "From" :tag { - discard; + stop; } +# Missing second argument if header :is :comparator "i;ascii-numeric" "From" { - discard; + stop; } +# Missing arguments if header :is :comparator "i;ascii-numeric" { - discard; + keep; } +# Not an error if header :is :comparator "i;ascii-casemap" "frop" ["frop", "frop"] { discard; } -if header :hufter :is :comparator "i;ascii-casemap" "frop" ["frop", "frop"] { - discard; +# Spurious sub-test +if header "frop" "frop" true { + discard; } -if header "frop" "frop" true { +# Test used as command with block +header "frop" "frop" { + discard; } + +# Test used as command +header "frop" "frop"; + + diff --git a/src/testsuite/tests/compile/errors/if.sieve b/src/testsuite/tests/compile/errors/if.sieve new file mode 100644 index 000000000..fa741c9c6 --- /dev/null +++ b/src/testsuite/tests/compile/errors/if.sieve @@ -0,0 +1,78 @@ +/* + * If command errors + * + * Total errors: 11 (+1 = 12) + */ + +# Spurious argument +if "frop" true {} + +# Spurious argument +elsif "frop" true {} + +# Spurious string list +if [ "false", "false", "false" ] false { + stop; +} + +# No block +if true; + +# No test +if { + keep; +} + +# Spurious test list +if ( false, false, true ) { + keep; +} + +stop; + +# If-less else +else { + keep; +} + +# Not an error +if true { + keep; +} + +stop; + +# If-less if structure (should produce only one error) +elsif true { + keep; +} +elsif true { + keep; +} +else { +} + +# Elsif after else +if true { + keep; +} else { + stop; +} elsif true { + stop; +} + +# If used as test +if if true { +} + +# Else if in stead of elsif + +if true { + stop; +} else if false { + keep; +} + + + + diff --git a/src/testsuite/tests/compile/errors/require.sieve b/src/testsuite/tests/compile/errors/require.sieve new file mode 100644 index 000000000..93508ad58 --- /dev/null +++ b/src/testsuite/tests/compile/errors/require.sieve @@ -0,0 +1,39 @@ +/* + * Require errors + * + * Total errors: 11 (+1 = 12) + */ + +# Not an error +require "fileinto"; + +# Missing argument +require; + +# Too many arguments +require "fileinto" "vacation"; + +# Invalid argument +require 45; + +# Invalid extensions (3 errors) +require ["_frop", "_friep", "_frml"]; + +# Invalid arguments +require "dovecot.test" true; + +# Invalid extension +require "_frop"; + +# Spurious command block +require "fileinto" { + keep; +} + +# Nested require +if true { + require "relional"; +} + +# Require after other command than require +require "copy"; diff --git a/src/testsuite/testsuite-common.c b/src/testsuite/testsuite-common.c index 034829f55..39a5f65ef 100644 --- a/src/testsuite/testsuite-common.c +++ b/src/testsuite/testsuite-common.c @@ -335,6 +335,8 @@ static void testsuite_script_clear_messages(void) ("testsuite_script_messages", 8192); p_array_init(&_testsuite_script_errors, _testsuite_scriptmsg_pool, 128); + + sieve_error_handler_reset(test_script_ehandler); } void testsuite_script_get_error_init(void) @@ -359,10 +361,10 @@ const char *testsuite_script_get_error_next(bool location) static void testsuite_script_init(void) { - testsuite_script_clear_messages(); - test_script_ehandler = _testsuite_script_ehandler_create(); sieve_error_handler_accept_infolog(test_script_ehandler, TRUE); + + testsuite_script_clear_messages(); } bool testsuite_script_compile(const char *script_path) -- GitLab