Coverage Report

Created: 2026-05-30 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pigeonhole/src/testsuite/tst-test-result-action.c
Line
Count
Source
1
/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file
2
 */
3
4
#include "sieve-common.h"
5
#include "sieve-error.h"
6
#include "sieve-script.h"
7
#include "sieve-commands.h"
8
#include "sieve-actions.h"
9
#include "sieve-comparators.h"
10
#include "sieve-match-types.h"
11
#include "sieve-validator.h"
12
#include "sieve-generator.h"
13
#include "sieve-interpreter.h"
14
#include "sieve-code.h"
15
#include "sieve-binary.h"
16
#include "sieve-result.h"
17
#include "sieve-dump.h"
18
#include "sieve-match.h"
19
20
#include "testsuite-common.h"
21
#include "testsuite-result.h"
22
23
/*
24
 * test_result_action command
25
 *
26
 * Syntax:
27
 *   test_result_action [MATCH-TYPE] [COMPARATOR] [:index number]
28
 *     <key-list: string-list>
29
 */
30
31
static bool tst_test_result_action_registered
32
  (struct sieve_validator *validator, const struct sieve_extension *ext,
33
    struct sieve_command_registration *cmd_reg);
34
static bool tst_test_result_action_validate
35
  (struct sieve_validator *validator, struct sieve_command *cmd);
36
static bool tst_test_result_action_generate
37
  (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx);
38
39
const struct sieve_command_def tst_test_result_action = {
40
  .identifier = "test_result_action",
41
  .type = SCT_TEST,
42
  .positional_args = 1,
43
  .subtests = 0,
44
  .block_allowed = FALSE,
45
  .block_required = FALSE,
46
  .registered = tst_test_result_action_registered,
47
  .validate = tst_test_result_action_validate,
48
  .generate = tst_test_result_action_generate
49
};
50
51
/*
52
 * Operation
53
 */
54
55
static bool tst_test_result_action_operation_dump
56
  (const struct sieve_dumptime_env *denv, sieve_size_t *address);
57
static int tst_test_result_action_operation_execute
58
  (const struct sieve_runtime_env *renv, sieve_size_t *address);
59
60
const struct sieve_operation_def test_result_action_operation = {
61
  .mnemonic = "TEST_RESULT_ACTION",
62
  .ext_def = &testsuite_extension,
63
  .code = TESTSUITE_OPERATION_TEST_RESULT_ACTION,
64
  .dump = tst_test_result_action_operation_dump,
65
  .execute = tst_test_result_action_operation_execute
66
};
67
68
/*
69
 * Tagged arguments
70
 */
71
72
/* FIXME: merge this with the test_error version of this tag */
73
74
static bool tst_test_result_action_validate_index_tag
75
  (struct sieve_validator *validator, struct sieve_ast_argument **arg,
76
    struct sieve_command *cmd);
77
78
static const struct sieve_argument_def test_result_action_index_tag = {
79
  .identifier = "index",
80
  .validate = tst_test_result_action_validate_index_tag
81
};
82
83
enum tst_test_result_action_optional {
84
  OPT_INDEX = SIEVE_MATCH_OPT_LAST,
85
};
86
87
/*
88
 * Argument implementation
89
 */
90
91
static bool tst_test_result_action_validate_index_tag
92
(struct sieve_validator *validator, struct sieve_ast_argument **arg,
93
  struct sieve_command *cmd)
94
0
{
95
0
  struct sieve_ast_argument *tag = *arg;
96
97
  /* Detach the tag itself */
98
0
  *arg = sieve_ast_arguments_detach(*arg,1);
99
100
  /* Check syntax:
101
   *   :index number
102
   */
103
0
  if ( !sieve_validate_tag_parameter
104
0
    (validator, cmd, tag, *arg, NULL, 0, SAAT_NUMBER, FALSE) ) {
105
0
    return FALSE;
106
0
  }
107
108
  /* Skip parameter */
109
0
  *arg = sieve_ast_argument_next(*arg);
110
0
  return TRUE;
111
0
}
112
113
114
/*
115
 * Command registration
116
 */
117
118
static bool tst_test_result_action_registered
119
(struct sieve_validator *validator, const struct sieve_extension *ext,
120
  struct sieve_command_registration *cmd_reg)
121
0
{
122
  /* The order of these is not significant */
123
0
  sieve_comparators_link_tag(validator, cmd_reg, SIEVE_MATCH_OPT_COMPARATOR);
124
0
  sieve_match_types_link_tags(validator, cmd_reg, SIEVE_MATCH_OPT_MATCH_TYPE);
125
126
0
  sieve_validator_register_tag
127
0
    (validator, cmd_reg, ext, &test_result_action_index_tag, OPT_INDEX);
128
129
0
  return TRUE;
130
0
}
131
132
/*
133
 * Validation
134
 */
135
136
static bool tst_test_result_action_validate
137
(struct sieve_validator *valdtr ATTR_UNUSED, struct sieve_command *tst)
138
0
{
139
0
  struct sieve_ast_argument *arg = tst->first_positional;
140
0
  struct sieve_comparator cmp_default =
141
0
    SIEVE_COMPARATOR_DEFAULT(i_octet_comparator);
142
0
  struct sieve_match_type mcht_default =
143
0
    SIEVE_COMPARATOR_DEFAULT(is_match_type);
144
145
0
  if ( !sieve_validate_positional_argument
146
0
    (valdtr, tst, arg, "key list", 2, SAAT_STRING_LIST) ) {
147
0
    return FALSE;
148
0
  }
149
150
0
  if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) )
151
0
    return FALSE;
152
153
  /* Validate the key argument to a specified match type */
154
0
  return sieve_match_type_validate
155
0
    (valdtr, tst, arg, &mcht_default, &cmp_default);
156
0
}
157
158
/*
159
 * Code generation
160
 */
161
162
static bool tst_test_result_action_generate
163
(const struct sieve_codegen_env *cgenv, struct sieve_command *tst)
164
0
{
165
0
  sieve_operation_emit(cgenv->sblock, tst->ext, &test_result_action_operation);
166
167
  /* Generate arguments */
168
0
  return sieve_generate_arguments(cgenv, tst, NULL);
169
0
}
170
171
/*
172
 * Code dump
173
 */
174
175
static bool tst_test_result_action_operation_dump
176
(const struct sieve_dumptime_env *denv, sieve_size_t *address)
177
0
{
178
0
  int opt_code = 0;
179
180
0
  sieve_code_dumpf(denv, "TEST_RESULT_ACTION:");
181
0
  sieve_code_descend(denv);
182
183
  /* Handle any optional arguments */
184
0
  for (;;) {
185
0
    int opt;
186
187
0
    if ( (opt=sieve_match_opr_optional_dump(denv, address, &opt_code))
188
0
      < 0 )
189
0
      return FALSE;
190
191
0
    if ( opt == 0 ) break;
192
193
0
    if ( opt_code == OPT_INDEX ) {
194
0
      if ( !sieve_opr_number_dump(denv, address, "index") )
195
0
        return FALSE;
196
0
    } else {
197
0
      return FALSE;
198
0
    }
199
0
  }
200
201
0
  return sieve_opr_stringlist_dump(denv, address, "key list");
202
0
}
203
204
/*
205
 * Intepretation
206
 */
207
208
static int tst_test_result_action_operation_execute
209
(const struct sieve_runtime_env *renv, sieve_size_t *address)
210
0
{
211
0
  int opt_code = 0;
212
0
  struct sieve_comparator cmp = SIEVE_COMPARATOR_DEFAULT(i_octet_comparator);
213
0
  struct sieve_match_type mcht = SIEVE_MATCH_TYPE_DEFAULT(is_match_type);
214
0
  struct sieve_stringlist *value_list, *key_list;
215
0
  int index = 0;
216
0
  int match, ret;
217
218
  /*
219
   * Read operands
220
   */
221
222
  /* Read optional operands */
223
0
  for (;;) {
224
0
    sieve_number_t number;
225
0
    int opt;
226
227
0
    if ( (opt=sieve_match_opr_optional_read
228
0
      (renv, address, &opt_code, &ret, &cmp, &mcht)) < 0 )
229
0
      return ret;
230
231
0
    if ( opt == 0 ) break;
232
233
0
    if ( opt_code == OPT_INDEX ) {
234
0
      if ( (ret=sieve_opr_number_read(renv, address, "index", &number)) <= 0 )
235
0
        return ret;
236
0
      index = (int) number;
237
0
    } else {
238
0
      sieve_runtime_trace_error(renv, "invalid optional operand");
239
0
      return SIEVE_EXEC_BIN_CORRUPT;
240
0
    }
241
0
  }
242
243
  /* Read key-list */
244
0
  if ( (ret=sieve_opr_stringlist_read(renv, address, "key-list", &key_list))
245
0
    <= 0 )
246
0
    return ret;
247
248
  /*
249
   * Perform operation
250
   */
251
252
0
  sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS,
253
0
    "testsuite: test_result_action test; match result name (index: %d)", index);
254
255
  /* Create value stringlist */
256
0
  value_list = testsuite_result_stringlist_create(renv, index);
257
258
  /* Perform match */
259
0
  if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret)) < 0 )
260
0
    return ret;
261
262
  /* Set test result for subsequent conditional jump */
263
0
  sieve_interpreter_set_test_result(renv->interp, match > 0);
264
0
  return SIEVE_EXEC_OK;
265
0
}
266
267
268