diff options
Diffstat (limited to 'pigeonhole/src/testsuite/cmd-test-config.c')
-rw-r--r-- | pigeonhole/src/testsuite/cmd-test-config.c | 504 |
1 files changed, 504 insertions, 0 deletions
diff --git a/pigeonhole/src/testsuite/cmd-test-config.c b/pigeonhole/src/testsuite/cmd-test-config.c new file mode 100644 index 0000000..c1399b0 --- /dev/null +++ b/pigeonhole/src/testsuite/cmd-test-config.c @@ -0,0 +1,504 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-settings.h" +#include "sieve-extensions.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 "testsuite-common.h" +#include "testsuite-settings.h" + +/* + * Commands + */ + +static bool +cmd_test_config_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +/* Test_config_set command + * + * Syntax: + * test_config_set <setting: string> <value: string> + */ + +static bool +cmd_test_config_set_validate(struct sieve_validator *valdtr, + struct sieve_command *cmd); + +const struct sieve_command_def cmd_test_config_set = { + .identifier = "test_config_set", + .type = SCT_COMMAND, + .positional_args = 2, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = cmd_test_config_set_validate, + .generate = cmd_test_config_generate +}; + +/* Test_config_unset command + * + * Syntax: + * test_config_unset <setting: string> + */ + +static bool +cmd_test_config_unset_validate(struct sieve_validator *valdtr, + struct sieve_command *cmd); + +const struct sieve_command_def cmd_test_config_unset = { + .identifier = "test_config_unset", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = cmd_test_config_unset_validate, + .generate = cmd_test_config_generate, +}; + +/* Test_config_reload command + * + * Syntax: + * test_config_reload [:extension <extension: string>] + */ + +static bool +cmd_test_config_reload_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); + +const struct sieve_command_def cmd_test_config_reload = { + .identifier = "test_config_reload", + .type = SCT_COMMAND, + .positional_args = 0, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = cmd_test_config_reload_registered, + .generate = cmd_test_config_generate +}; + +/* + * Command tags + */ + +/* Forward declarations */ + +static bool +cmd_test_config_reload_validate_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +/* Argument objects */ + +static const struct sieve_argument_def test_config_reload_extension_tag = { + .identifier = "extension", + .validate = cmd_test_config_reload_validate_tag, +}; + +/* Codes for optional arguments */ + +enum cmd_test_config_optional { + OPT_END, + OPT_EXTENSION +}; + +/* + * Operations + */ + +/* Test_config_set operation */ + +static bool +cmd_test_config_set_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +cmd_test_config_set_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def test_config_set_operation = { + .mnemonic = "TEST_CONFIG_SET", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERATION_TEST_CONFIG_SET, + .dump = cmd_test_config_set_operation_dump, + .execute = cmd_test_config_set_operation_execute +}; + +/* Test_config_unset operation */ + +static bool +cmd_test_config_unset_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +cmd_test_config_unset_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def test_config_unset_operation = { + .mnemonic = "TEST_CONFIG_UNSET", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERATION_TEST_CONFIG_UNSET, + .dump = cmd_test_config_unset_operation_dump, + .execute = cmd_test_config_unset_operation_execute +}; + +/* Test_config_read operation */ + +static bool +cmd_test_config_reload_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +cmd_test_config_reload_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def test_config_reload_operation = { + .mnemonic = "TEST_CONFIG_RELOAD", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERATION_TEST_CONFIG_RELOAD, + .dump = cmd_test_config_reload_operation_dump, + .execute = cmd_test_config_reload_operation_execute +}; + +/* + * Tag validation + */ + +static bool +cmd_test_config_reload_validate_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg,1); + + /* Check syntax: + * :extension <extension: string> + */ + if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL, 0, + SAAT_STRING, TRUE)) + return FALSE; + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +/* + * Command registration + */ + +static bool +cmd_test_config_reload_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &test_config_reload_extension_tag, + OPT_EXTENSION); + return TRUE; +} + +/* + * Command validation + */ + +static bool +cmd_test_config_set_validate(struct sieve_validator *valdtr, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + + /* Check syntax: + * <setting: string> <value: string> + */ + + if (!sieve_validate_positional_argument(valdtr, cmd, arg, "setting", + 1, SAAT_STRING)) + return FALSE; + + if (!sieve_validator_argument_activate(valdtr, cmd, arg, FALSE)) + return FALSE; + + arg = sieve_ast_argument_next(arg); + + if (!sieve_validate_positional_argument(valdtr, cmd, arg, "value", 2, + SAAT_STRING)) + return FALSE; + + return sieve_validator_argument_activate(valdtr, cmd, arg, FALSE); +} + +static bool +cmd_test_config_unset_validate(struct sieve_validator *valdtr, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + + /* Check syntax: + * <setting: string> + */ + if (!sieve_validate_positional_argument(valdtr, cmd, arg, "setting", 1, + SAAT_STRING)) + return FALSE; + + return sieve_validator_argument_activate(valdtr, cmd, arg, FALSE); +} + +/* + * Code generation + */ + +static bool +cmd_test_config_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd) +{ + if (sieve_command_is(cmd, cmd_test_config_set)) { + sieve_operation_emit(cgenv->sblock, cmd->ext, + &test_config_set_operation); + } else if (sieve_command_is(cmd, cmd_test_config_unset)) { + sieve_operation_emit(cgenv->sblock, cmd->ext, + &test_config_unset_operation); + } else if (sieve_command_is(cmd, cmd_test_config_reload)) { + sieve_operation_emit(cgenv->sblock, cmd->ext, + &test_config_reload_operation); + } else { + i_unreached(); + } + + /* Generate arguments */ + if (!sieve_generate_arguments(cgenv, cmd, NULL)) + return FALSE; + return TRUE; +} + +/* + * Code dump + */ + +static bool +cmd_test_config_set_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + sieve_code_dumpf(denv, "TEST_CONFIG_SET:"); + + sieve_code_descend(denv); + + return (sieve_opr_string_dump(denv, address, "setting") && + sieve_opr_string_dump(denv, address, "value")); +} + +static bool +cmd_test_config_unset_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + sieve_code_dumpf(denv, "TEST_CONFIG_UNSET:"); + + sieve_code_descend(denv); + + return sieve_opr_string_dump(denv, address, "setting"); +} + +static bool +cmd_test_config_reload_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + int opt_code = 0; + + sieve_code_dumpf(denv, "TEST_CONFIG_RELOAD:"); + sieve_code_descend(denv); + + /* Dump optional operands */ + + for (;;) { + int opt; + bool opok = TRUE; + + if ((opt = sieve_opr_optional_dump(denv, address, + &opt_code)) < 0) + return FALSE; + + if (opt == 0) + break; + + switch (opt_code) { + case OPT_EXTENSION: + opok = sieve_opr_string_dump(denv, address, + "extensions"); + break; + default: + opok = FALSE; + break; + } + + if (!opok) + return FALSE; + } + + return TRUE; +} + +/* + * Interpretation + */ + +static int +cmd_test_config_set_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + string_t *setting; + string_t *value; + int ret; + + /* + * Read operands + */ + + /* Setting */ + if ((ret = sieve_opr_string_read(renv, address, "setting", + &setting)) <= 0) + return ret; + + /* Value */ + if ((ret = sieve_opr_string_read(renv, address, "value", + &value)) <= 0) + return ret; + + /* + * Perform operation + */ + + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS)) { + sieve_runtime_trace( + renv, 0, "testsuite: test_config_set command"); + sieve_runtime_trace_descend(renv); + sieve_runtime_trace( + renv, 0, "set config `%s' = `%s'", + str_c(setting), str_c(value)); + } + + testsuite_setting_set(str_c(setting), str_c(value)); + + return SIEVE_EXEC_OK; +} + +static int +cmd_test_config_unset_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + string_t *setting; + int ret; + + /* + * Read operands + */ + + /* Setting */ + if ((ret = sieve_opr_string_read(renv, address, "setting", + &setting)) <= 0) + return ret; + + /* + * Perform operation + */ + + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS)) { + sieve_runtime_trace( + renv, 0, "testsuite: test_config_unset command"); + sieve_runtime_trace_descend(renv); + sieve_runtime_trace( + renv, 0, "unset config `%s'", str_c(setting)); + } + + testsuite_setting_unset(str_c(setting)); + + return SIEVE_EXEC_OK; +} + +static int +cmd_test_config_reload_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + const struct sieve_extension *ext; + int opt_code = 0; + string_t *extension = NULL; + int ret; + + /* + * Read operands + */ + + /* Optional operands */ + for (;;) { + int opt; + + if ((opt = sieve_opr_optional_read(renv, address, + &opt_code)) < 0) + return SIEVE_EXEC_BIN_CORRUPT; + + if (opt == 0) + break; + + switch (opt_code) { + case OPT_EXTENSION: + ret = sieve_opr_string_read(renv, address, "extension", + &extension); + break; + default: + sieve_runtime_trace_error( + renv, "unknown optional operand"); + ret = SIEVE_EXEC_BIN_CORRUPT; + } + + if (ret <= 0) + return ret; + } + + /* + * Perform operation + */ + + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS)) { + sieve_runtime_trace( + renv, 0, "testsuite: test_config_reload command"); + sieve_runtime_trace_descend(renv); + } + + if (extension == NULL) { + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS)) { + sieve_runtime_trace( + renv, 0, + "reload configuration for sieve engine"); + } + + sieve_settings_load(eenv->svinst); + } else { + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS)) { + sieve_runtime_trace( + renv, 0, + "reload configuration for extension `%s'", + str_c(extension)); + } + + ext = sieve_extension_get_by_name(eenv->svinst, + str_c(extension)); + if (ext == NULL) { + return testsuite_test_failf( + renv, "test_config_reload: " + "unknown extension '%s'", str_c(extension)); + } + sieve_extension_reload(ext); + } + return SIEVE_EXEC_OK; +} |