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-error.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-comparators.h"
9
#include "sieve-match-types.h"
10
#include "sieve-validator.h"
11
#include "sieve-generator.h"
12
#include "sieve-interpreter.h"
13
#include "sieve-code.h"
14
#include "sieve-binary.h"
15
#include "sieve-dump.h"
16
#include "sieve-match.h"
17
18
#include "testsuite-common.h"
19
#include "testsuite-log.h"
20
21
/*
22
 * Test_error command
23
 *
24
 * Syntax:
25
 *   test [MATCH-TYPE] [COMPARATOR] [:index number] <key-list: string-list>
26
 */
27
28
static bool tst_test_error_registered
29
  (struct sieve_validator *valdtr, const struct sieve_extension *ext,
30
    struct sieve_command_registration *cmd_reg);
31
static bool tst_test_error_validate
32
  (struct sieve_validator *valdtr, struct sieve_command *cmd);
33
static bool tst_test_error_generate
34
  (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx);
35
36
const struct sieve_command_def tst_test_error = {
37
  .identifier = "test_error",
38
  .type = SCT_TEST,
39
  .positional_args = 1,
40
  .subtests = 0,
41
  .block_allowed = FALSE,
42
  .block_required = FALSE,
43
  .registered = tst_test_error_registered,
44
  .validate = tst_test_error_validate,
45
  .generate = tst_test_error_generate
46
};
47
48
/*
49
 * Operation
50
 */
51
52
static bool tst_test_error_operation_dump
53
  (const struct sieve_dumptime_env *denv, sieve_size_t *address);
54
static int tst_test_error_operation_execute
55
  (const struct sieve_runtime_env *renv, sieve_size_t *address);
56
57
const struct sieve_operation_def test_error_operation = {
58
  .mnemonic = "TEST_ERROR",
59
  .ext_def = &testsuite_extension,
60
  .code = TESTSUITE_OPERATION_TEST_ERROR,
61
  .dump = tst_test_error_operation_dump,
62
  .execute = tst_test_error_operation_execute
63
};
64
65
/*
66
 * Tagged arguments
67
 */
68
69
/* NOTE: This will be merged with the date-index extension when it is
70
 * implemented.
71
 */
72
73
static bool tst_test_error_validate_index_tag
74
  (struct sieve_validator *valdtr, struct sieve_ast_argument **arg,
75
    struct sieve_command *cmd);
76
77
static const struct sieve_argument_def test_error_index_tag = {
78
  .identifier = "index",
79
  .validate = tst_test_error_validate_index_tag
80
};
81
82
enum tst_test_error_optional {
83
  OPT_INDEX = SIEVE_MATCH_OPT_LAST,
84
};
85
86
87
/*
88
 * Argument implementation
89
 */
90
91
static bool tst_test_error_validate_index_tag
92
(struct sieve_validator *valdtr, 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
    (valdtr, 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_error_registered
119
(struct sieve_validator *valdtr, 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(valdtr, cmd_reg, SIEVE_MATCH_OPT_COMPARATOR);
124
0
  sieve_match_types_link_tags(valdtr, cmd_reg, SIEVE_MATCH_OPT_MATCH_TYPE);
125
126
0
  sieve_validator_register_tag
127
0
    (valdtr, cmd_reg, ext, &test_error_index_tag, OPT_INDEX);
128
129
0
  return TRUE;
130
0
}
131
132
/*
133
 * Validation
134
 */
135
136
static bool tst_test_error_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_error_generate
163
(const struct sieve_codegen_env *cgenv, struct sieve_command *tst)
164
0
{
165
0
  sieve_operation_emit(cgenv->sblock, tst->ext, &test_error_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_error_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_ERROR:");
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_error_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_COMPARATOR_DEFAULT(is_match_type);
214
0
  struct sieve_stringlist *value_list, *key_list;
215
0
  int index = -1;
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
  if ( index > 0 )
253
0
    sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS,
254
0
      "testsuite: test_error test; match error message [index=%d]", index);
255
0
  else
256
0
    sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS,
257
0
      "testsuite: test_error test; match error messages");
258
259
  /* Create value stringlist */
260
0
  value_list = testsuite_log_stringlist_create(renv, index);
261
262
  /* Perform match */
263
0
  if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret)) < 0 )
264
0
    return ret;
265
266
  /* Set test result for subsequent conditional jump */
267
0
  sieve_interpreter_set_test_result(renv->interp, match > 0);
268
0
  return SIEVE_EXEC_OK;
269
0
}
270
271
272
273