1
/* Copyright (c) 2002-2009 Dovecot Sieve authors, see the included COPYING file
4
/* FIXME: this file is very similar to tst-test-error.c. Maybe it is best to
5
* implement errors and actions as testsuite-objects and implement a common
6
* interface to test these.
9
#include "sieve-common.h"
10
#include "sieve-error.h"
11
#include "sieve-script.h"
12
#include "sieve-commands.h"
13
#include "sieve-actions.h"
14
#include "sieve-comparators.h"
15
#include "sieve-match-types.h"
16
#include "sieve-validator.h"
17
#include "sieve-generator.h"
18
#include "sieve-interpreter.h"
19
#include "sieve-code.h"
20
#include "sieve-binary.h"
21
#include "sieve-result.h"
22
#include "sieve-dump.h"
23
#include "sieve-match.h"
25
#include "testsuite-common.h"
26
#include "testsuite-result.h"
32
* test_result [MATCH-TYPE] [COMPARATOR] [:index number]
33
* <key-list: string-list>
36
static bool tst_test_result_registered
37
(struct sieve_validator *validator, struct sieve_command_registration *cmd_reg);
38
static bool tst_test_result_validate
39
(struct sieve_validator *validator, struct sieve_command_context *cmd);
40
static bool tst_test_result_generate
41
(const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx);
43
const struct sieve_command tst_test_result = {
47
tst_test_result_registered,
49
tst_test_result_validate,
50
tst_test_result_generate,
58
static bool tst_test_result_operation_dump
59
(const struct sieve_operation *op,
60
const struct sieve_dumptime_env *denv, sieve_size_t *address);
61
static int tst_test_result_operation_execute
62
(const struct sieve_operation *op,
63
const struct sieve_runtime_env *renv, sieve_size_t *address);
65
const struct sieve_operation test_result_operation = {
68
TESTSUITE_OPERATION_TEST_RESULT,
69
tst_test_result_operation_dump,
70
tst_test_result_operation_execute
77
/* NOTE: This will be merged with the date-index extension when it is
81
/* FIXME: at least merge this with the test_error version of this tag */
83
static bool tst_test_result_validate_index_tag
84
(struct sieve_validator *validator, struct sieve_ast_argument **arg,
85
struct sieve_command_context *cmd);
87
static const struct sieve_argument test_result_index_tag = {
90
tst_test_result_validate_index_tag,
94
enum tst_test_result_optional {
95
OPT_INDEX = SIEVE_MATCH_OPT_LAST,
99
* Argument implementation
102
static bool tst_test_result_validate_index_tag
103
(struct sieve_validator *validator, struct sieve_ast_argument **arg,
104
struct sieve_command_context *cmd)
106
struct sieve_ast_argument *tag = *arg;
108
/* Detach the tag itself */
109
*arg = sieve_ast_arguments_detach(*arg,1);
114
if ( !sieve_validate_tag_parameter
115
(validator, cmd, tag, *arg, SAAT_NUMBER) ) {
120
*arg = sieve_ast_argument_next(*arg);
126
* Command registration
129
static bool tst_test_result_registered
130
(struct sieve_validator *validator, struct sieve_command_registration *cmd_reg)
132
/* The order of these is not significant */
133
sieve_comparators_link_tag(validator, cmd_reg, SIEVE_MATCH_OPT_COMPARATOR);
134
sieve_match_types_link_tags(validator, cmd_reg, SIEVE_MATCH_OPT_MATCH_TYPE);
136
sieve_validator_register_tag
137
(validator, cmd_reg, &test_result_index_tag, OPT_INDEX);
146
static bool tst_test_result_validate
147
(struct sieve_validator *valdtr ATTR_UNUSED, struct sieve_command_context *tst)
149
struct sieve_ast_argument *arg = tst->first_positional;
151
if ( !sieve_validate_positional_argument
152
(valdtr, tst, arg, "key list", 2, SAAT_STRING_LIST) ) {
156
if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) )
159
/* Validate the key argument to a specified match type */
160
return sieve_match_type_validate
161
(valdtr, tst, arg, &is_match_type, &i_octet_comparator);
168
static inline struct testsuite_generator_context *
169
_get_generator_context(struct sieve_generator *gentr)
171
return (struct testsuite_generator_context *)
172
sieve_generator_extension_get_context(gentr, &testsuite_extension);
175
static bool tst_test_result_generate
176
(const struct sieve_codegen_env *cgenv, struct sieve_command_context *tst)
178
sieve_operation_emit_code(cgenv->sbin, &test_result_operation);
180
/* Generate arguments */
181
return sieve_generate_arguments(cgenv, tst, NULL);
188
static bool tst_test_result_operation_dump
189
(const struct sieve_operation *op ATTR_UNUSED,
190
const struct sieve_dumptime_env *denv, sieve_size_t *address)
194
sieve_code_dumpf(denv, "TEST_RESULT:");
195
sieve_code_descend(denv);
197
/* Handle any optional arguments */
199
if ( !sieve_match_dump_optional_operands(denv, address, &opt_code) )
202
switch ( opt_code ) {
203
case SIEVE_MATCH_OPT_END:
206
if ( !sieve_opr_number_dump(denv, address, "index") )
212
} while ( opt_code != SIEVE_MATCH_OPT_END );
214
return sieve_opr_stringlist_dump(denv, address, "key list");
221
static int tst_test_result_operation_execute
222
(const struct sieve_operation *op ATTR_UNUSED,
223
const struct sieve_runtime_env *renv, sieve_size_t *address)
227
const struct sieve_comparator *cmp = &i_octet_comparator;
228
const struct sieve_match_type *mtch = &is_match_type;
229
struct sieve_match_context *mctx;
230
struct sieve_coded_stringlist *key_list;
232
struct sieve_result_iterate_context *rictx;
233
const struct sieve_action *action;
235
int cur_index = 0, index = 0;
242
/* Handle optional operands */
244
sieve_number_t number;
246
if ( (ret=sieve_match_read_optional_operands
247
(renv, address, &opt_code, &cmp, &mtch)) <= 0 )
250
switch ( opt_code ) {
251
case SIEVE_MATCH_OPT_END:
254
if ( !sieve_opr_number_read(renv, address, &number) ) {
255
sieve_runtime_trace_error(renv, "invalid index operand");
256
return SIEVE_EXEC_BIN_CORRUPT;
258
index = (int) number;
261
sieve_runtime_trace_error(renv, "invalid optional operand");
262
return SIEVE_EXEC_BIN_CORRUPT;
264
} while ( opt_code != SIEVE_MATCH_OPT_END);
267
if ( (key_list=sieve_opr_stringlist_read(renv, address)) == NULL ) {
268
sieve_runtime_trace_error(renv, "invalid key-list operand");
269
return SIEVE_EXEC_BIN_CORRUPT;
276
sieve_runtime_trace(renv, "TEST_RESULT test (index: %d)", index);
278
rictx = testsuite_result_iterate_init();
280
/* Initialize match */
281
mctx = sieve_match_begin(renv->interp, mtch, cmp, NULL, key_list);
283
/* Iterate through all errors to match */
287
while ( result && !matched &&
288
(action=sieve_result_iterate_next(rictx, &keep, NULL)) != NULL ) {
289
const char *act_name;
294
act_name = ( action == NULL || action->name == NULL ) ? "" : action->name;
296
if ( index == 0 || index == cur_index ) {
297
if ( (ret=sieve_match_value(mctx, act_name, strlen(act_name))) < 0 ) {
308
if ( (ret=sieve_match_end(&mctx)) < 0 )
311
matched = ( ret > 0 || matched );
313
/* Set test result for subsequent conditional jump */
315
sieve_interpreter_set_test_result(renv->interp, matched);
316
return SIEVE_EXEC_OK;
319
sieve_runtime_trace_error(renv, "invalid string-list item");
320
return SIEVE_EXEC_BIN_CORRUPT;