Line data Source code
1 : // Copyright (c) 2012-2024 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/eventdispatcher
4 : // contact@m2osw.com
5 : //
6 : // This program is free software: you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation, either version 3 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License
17 : // along with this program. If not, see <https://www.gnu.org/licenses/>.
18 :
19 : // this diagnostic has to be turned off "globally" so the catch2 does not
20 : // generate the warning on the floating point == operator
21 : //
22 : #pragma GCC diagnostic ignored "-Wfloat-equal"
23 :
24 : // self
25 : //
26 : #include "catch_main.h"
27 :
28 :
29 :
30 : // reporter
31 : //
32 : #include <eventdispatcher/reporter/executor.h>
33 :
34 : #include <eventdispatcher/reporter/parser.h>
35 : #include <eventdispatcher/reporter/variable_address.h>
36 : #include <eventdispatcher/reporter/variable_floating_point.h>
37 : #include <eventdispatcher/reporter/variable_integer.h>
38 : #include <eventdispatcher/reporter/variable_list.h>
39 : #include <eventdispatcher/reporter/variable_regex.h>
40 : #include <eventdispatcher/reporter/variable_string.h>
41 : #include <eventdispatcher/reporter/variable_timestamp.h>
42 : #include <eventdispatcher/reporter/variable_void.h>
43 :
44 :
45 : // libaddr
46 : //
47 : #include <libaddr/addr_parser.h>
48 :
49 :
50 : // eventdispatcher
51 : //
52 : #include <eventdispatcher/communicator.h>
53 : #include <eventdispatcher/tcp_client_permanent_message_connection.h>
54 :
55 :
56 : // last include
57 : //
58 : #include <snapdev/poison.h>
59 :
60 :
61 :
62 : namespace
63 : {
64 :
65 :
66 :
67 : constexpr char const * const g_program_sleep_func =
68 : "call(label: func_sleep)\n"
69 : "exit(timeout: 1)\n"
70 : "label(name: func_sleep)\n"
71 : "sleep(seconds: 2.5)\n"
72 : "return()\n"
73 : ;
74 :
75 : constexpr char const * const g_program_start_thread =
76 : "set_variable(name: test, value: 33)\n"
77 : "set_variable(name: test_copy_between_dollars, value: \"$${test}$\")\n"
78 : "run()\n"
79 : "set_variable(name: runner, value: 6.07)\n"
80 : "set_variable(name: runner_copy_as_is, value: \"runner = ${runner}\")\n"
81 : "set_variable(name: time_limit, value: @1713934141.107805991)\n"
82 : "set_variable(name: time_limit_copy, value: \"limit: ${time_limit}\")\n"
83 : "set_variable(name: host_ip, value: <127.7.3.51>)\n"
84 : "set_variable(name: host_ip_copy, value: \"Host is at ${host_ip} address\")\n"
85 : "set_variable(name: time_and_host_ip, value: \"time ${time_limit} and address ${host_ip}...\")\n"
86 : ;
87 :
88 : constexpr char const * const g_program_start_thread_twice =
89 : "set_variable(name: test, value: 33)\n"
90 : "run()\n"
91 : "set_variable(name: runner, value: 6.07)\n"
92 : "run()\n" // second run() is forbidden
93 : ;
94 :
95 : constexpr char const * const g_program_verify_computation_integer =
96 : "set_variable(name: t01, value: 3)\n"
97 :
98 : "set_variable(name: t11, value: -3)\n"
99 : "set_variable(name: t12, value: +3)\n"
100 :
101 : "set_variable(name: t21, value: 3 + 2)\n"
102 : "set_variable(name: t22, value: -(3 + 2))\n"
103 : "set_variable(name: t23, value: 20 - 4)\n"
104 : "set_variable(name: t24, value: 3 * 2)\n"
105 : "set_variable(name: t25, value: 20 / 4)\n"
106 : "set_variable(name: t26, value: 27 % 11)\n"
107 :
108 : "set_variable(name: t31, value: 3 + 2 * 5)\n"
109 : "set_variable(name: t32, value: -7 + 15 / 3)\n"
110 : "set_variable(name: t33, value: +2 + 15 % 7)\n"
111 :
112 : "set_variable(name: t41, value: (3 + 2) * 5)\n"
113 : "set_variable(name: t42, value: (-7 + 15) / 3)\n"
114 : "set_variable(name: t43, value: (+2 + 15) % 7)\n"
115 : ;
116 :
117 : constexpr char const * const g_program_verify_computation_floating_point =
118 : "set_variable(name: t01, value: 3.01)\n"
119 :
120 : "set_variable(name: t11, value: -3.5)\n"
121 : "set_variable(name: t12, value: +3.2)\n"
122 :
123 : "set_variable(name: t21ff, value: 3.01 + 2.45)\n"
124 : "set_variable(name: t21if, value: 3 + 2.54)\n"
125 : "set_variable(name: t21fi, value: 3.01 + 2)\n"
126 : "set_variable(name: t22ff, value: -(3.5 + 2.5))\n"
127 : "set_variable(name: t22if, value: -(3 + 2.11))\n"
128 : "set_variable(name: t22fi, value: -(3.07 + 2))\n"
129 : "set_variable(name: t23ff, value: 20.07 - 4.13)\n"
130 : "set_variable(name: t23if, value: 20 - 4.78)\n"
131 : "set_variable(name: t23fi, value: 20.91 - 4)\n"
132 : "set_variable(name: t24ff, value: 3.41 * 2.14)\n"
133 : "set_variable(name: t24if, value: 3 * 2.67)\n"
134 : "set_variable(name: t24fi, value: 3.32 * 2)\n"
135 : "set_variable(name: t25ff, value: 20.83 / 4.07)\n"
136 : "set_variable(name: t25if, value: 20 / 4.4)\n"
137 : "set_variable(name: t25fi, value: 20.93 / 4)\n"
138 : "set_variable(name: t26ff, value: 27.27 % 11.11)\n"
139 : "set_variable(name: t26if, value: 27 % 11.88)\n"
140 : "set_variable(name: t26fi, value: 27.72 % 11)\n"
141 :
142 : "set_variable(name: t31fff, value: 3.03 + 2.2 * 5.9)\n"
143 : "set_variable(name: t31iff, value: 3 + 2.5 * 5.7)\n"
144 : "set_variable(name: t31fif, value: 3.2 + 2 * 5.3)\n"
145 : "set_variable(name: t31ffi, value: 3.07 + 2.28 * 5)\n"
146 : "set_variable(name: t31iif, value: 3 + 2 * 5.67)\n"
147 : "set_variable(name: t31ifi, value: 3 + 2.56 * 5)\n"
148 : "set_variable(name: t31fii, value: 3.33 + 2 * 5)\n"
149 : "set_variable(name: t32fff, value: -7.11 + 15.7 / 3.06)\n"
150 : "set_variable(name: t32iff, value: -7 + 15.25 / 3.31)\n"
151 : "set_variable(name: t32fif, value: -7.78 + 15 / 3.77)\n"
152 : "set_variable(name: t32ffi, value: -7.09 + 15.34 / 3)\n"
153 : "set_variable(name: t32iif, value: -7 + 15 / 3.30)\n"
154 : "set_variable(name: t32ifi, value: -7 + 15.09 / 3)\n"
155 : "set_variable(name: t32fii, value: -7.94 + 15 / 3)\n"
156 : "set_variable(name: t33fff, value: +2.21 + 15.16 % 7.8)\n"
157 : "set_variable(name: t33iff, value: +2 + 15.12 % 7.93)\n"
158 : "set_variable(name: t33fif, value: +2.58 + 15 % 7.63)\n"
159 : "set_variable(name: t33ffi, value: +2.12 + 15.09 % 7)\n"
160 : "set_variable(name: t33iif, value: +2 + 15 % 7.19)\n"
161 : "set_variable(name: t33ifi, value: +2 + 15.18 % 7)\n"
162 : "set_variable(name: t33fii, value: +2.17 + 15 % 7)\n"
163 :
164 : "set_variable(name: t41fff, value: (3.45 + 2.06) * 5.55)\n"
165 : "set_variable(name: t41iff, value: (3 + 2.17) * 5.07)\n"
166 : "set_variable(name: t41fif, value: (3.37 + 2) * 5.12)\n"
167 : "set_variable(name: t41ffi, value: (3.45 + 2.67) * 5)\n"
168 : "set_variable(name: t41iif, value: (3 + 2) * 5.3)\n"
169 : "set_variable(name: t41ifi, value: (3 + 2.9) * 5)\n"
170 : "set_variable(name: t41fii, value: (3.4 + 2) * 5)\n"
171 : "set_variable(name: t42fff, value: (-7.4 + 15.15) / 3.93)\n"
172 : "set_variable(name: t42iff, value: (-7 + 15.21) / 3.43)\n"
173 : "set_variable(name: t42fif, value: (-7.72 + 15) / 3.31)\n"
174 : "set_variable(name: t42ffi, value: (-7.43 + 15.89) / 3)\n"
175 : "set_variable(name: t42iif, value: (-7 + 15) / 3.4)\n"
176 : "set_variable(name: t42ifi, value: (-7 + 15.09) / 3)\n"
177 : "set_variable(name: t42fii, value: (-7.73 + 15) / 3)\n"
178 : "set_variable(name: t43fff, value: (+2.25 + 15.36) % 7.47)\n"
179 : "set_variable(name: t43iff, value: (+2 + 15.16) % 7.38)\n"
180 : "set_variable(name: t43fif, value: (+2.51 + 15) % 7.59)\n"
181 : "set_variable(name: t43ffi, value: (+2.4 + 15.3) % 7)\n"
182 : "set_variable(name: t43iif, value: (+2 + 15) % 7.0)\n"
183 : "set_variable(name: t43ifi, value: (+2 + 15.8) % 7)\n"
184 : "set_variable(name: t43fii, value: (+2.07 + 15) % 7)\n"
185 : ;
186 :
187 : constexpr char const * const g_program_verify_computation_timestamp =
188 : "set_variable(name: t01, value: @123 + 5)\n"
189 : "set_variable(name: t02, value: 33 + @123)\n"
190 : "set_variable(name: t03, value: @123 - 5)\n"
191 : "set_variable(name: t04, value: 33 - @123)\n"
192 :
193 : "set_variable(name: t11, value: @123 + 5.09)\n"
194 : "set_variable(name: t12, value: 33.501923821 + @123)\n"
195 : "set_variable(name: t13, value: @123 - 5.001)\n"
196 : "set_variable(name: t14, value: 333.98201992 - @123)\n"
197 :
198 : "set_variable(name: t21, value: -@123)\n"
199 : "set_variable(name: t22, value: +@123)\n"
200 :
201 : "set_variable(name: t31, value: @300.561 - @123.231)\n"
202 : "set_variable(name: t32, value: @34.3123 + @123.9984312)\n"
203 : ;
204 :
205 : constexpr char const * const g_program_verify_now =
206 : "now(variable_name: about_now)\n"
207 : ;
208 :
209 : constexpr char const * const g_program_verify_computation_address =
210 : "set_variable(name: t01, value: <127.0.0.1> + 256)\n"
211 : "set_variable(name: t02, value: 256 + <192.168.3.57>)\n"
212 : "set_variable(name: t03, value: <172.131.4.1> - 256)\n"
213 :
214 : "set_variable(name: t11, value: <10.5.34.255> - <10.5.33.0>)\n"
215 : ;
216 :
217 : constexpr char const * const g_program_verify_computation_concatenation =
218 : "set_variable(name: t01, value: ident + ifier)\n"
219 :
220 : "set_variable(name: t11, value: 'single' + ' ' + 'string')\n"
221 : "set_variable(name: t12, value: 'single' + \" \" + 'string')\n"
222 : "set_variable(name: t13, value: 'single' + ' ' + \"string\")\n"
223 : "set_variable(name: t14, value: \"double\" + \" \" + \"string\")\n"
224 :
225 : "set_variable(name: t21, value: +identify)\n"
226 : "set_variable(name: t22, value: +'single string')\n"
227 : "set_variable(name: t23, value: +\"double string\")\n"
228 :
229 : "set_variable(name: t31, value: 'single' + 36)\n"
230 : "set_variable(name: t32, value: 258 + 'single')\n"
231 : "set_variable(name: t33, value: \"string\" + 102)\n"
232 : "set_variable(name: t34, value: 5005 + \"double\")\n"
233 : ;
234 :
235 : constexpr char const * const g_program_verify_computation_string_repeat =
236 : "set_variable(name: t01, value: 'abc' * 3)\n"
237 : "set_variable(name: t02, value: \"xyz\" * 5)\n"
238 : "set_variable(name: t03, value: \"zero\" * 0)\n"
239 : "set_variable(name: t04, value: \"one\" * 1)\n"
240 : ;
241 :
242 : constexpr char const * const g_program_verify_variable_in_string =
243 : "set_variable(name: foo, value: 'abc')\n"
244 : "set_variable(name: bar, value: \"[${foo}]\")\n"
245 : ;
246 :
247 : constexpr char const * const g_program_accept_one_message =
248 : "run()\n"
249 : "listen(address: <127.0.0.1:20002>)\n"
250 : "label(name: wait_message)\n"
251 : "clear_message()\n"
252 : "wait(timeout: 10.0, mode: wait)\n" // first wait reacts on connect(), second wait receives the REGISTER message
253 : "has_message()\n"
254 : "if(false: wait_message)\n"
255 : "show_message()\n"
256 : "verify_message(command: REGISTER, required_parameters: { service: responder, version: 1 }, optional_parameters: { commands: \"READY,HELP,STOP\" }, forbidden_parameters: { forbidden })\n"
257 : "save_parameter_value(parameter_name: version, variable_name: register_version)\n"
258 : "save_parameter_value(parameter_name: service, variable_name: register_service, type: identifier)\n"
259 : "send_message(command: READY, sent_server: reporter_test_extension, sent_service: test_processor, server: reporter_test, service: accept_one_message, parameters: { status: alive, version: 9 })\n"
260 : "wait(timeout: 10.0, mode: drain)\n"
261 : "disconnect()\n"
262 : "exit()\n"
263 : ;
264 :
265 : constexpr char const * const g_program_receive_unwanted_message =
266 : "run()\n"
267 : "listen(address: <127.0.0.1:20002>)\n"
268 : "label(name: wait_message)\n"
269 : "clear_message()\n"
270 : "wait(timeout: 10.0, mode: wait)\n"
271 : "has_message()\n"
272 : "if(false: wait_message)\n"
273 : "show_message()\n"
274 : "verify_message(command: REGISTER, required_parameters: { service: responder, version: `^[0-9]+$` }, optional_parameters: { commands: \"READY,HELP,STOP\" }, forbidden_parameters: { forbidden })\n"
275 : "save_parameter_value(parameter_name: version, variable_name: register_version, type: integer)\n"
276 : "send_message(command: READY, parameters: { version: 9 })\n"
277 : "print(message: \"nearly done\")\n"
278 : "exit(timeout: 2.5)\n"
279 : ;
280 :
281 : constexpr char const * const g_program_send_unsupported_message_parameter_type =
282 : "run()\n"
283 : "listen(address: <127.0.0.1:20002>)\n"
284 : "label(name: wait_message)\n"
285 : "clear_message()\n"
286 : "wait(timeout: 10.0, mode: wait)\n" // first wait reacts on connect(), second wait receives the REGISTER message
287 : "has_message()\n"
288 : "if(false: wait_message)\n"
289 : "show_message()\n"
290 : "verify_message(command: REGISTER, required_parameters: { service: responder, version: 1 }, optional_parameters: { commands: \"READY,HELP,STOP\" }, forbidden_parameters: { forbidden })\n"
291 : "save_parameter_value(parameter_name: version, variable_name: register_version, type: integer)\n"
292 : "send_message(command: READY, parameters: { status: 3.05 })\n" // floating point not yet supported
293 : "wait(timeout: 1.0, mode: drain)\n"
294 : ;
295 :
296 : constexpr char const * const g_program_send_invalid_parameter_value_type =
297 : "run()\n"
298 : "listen(address: <127.0.0.1:20002>)\n"
299 : "label(name: wait_message)\n"
300 : "clear_message()\n"
301 : "wait(timeout: 10.0, mode: wait)\n"
302 : "has_message()\n"
303 : "if(false: wait_message)\n"
304 : "show_message()\n"
305 : "verify_message(command: REGISTER, required_parameters: { service: responder, version: 1 }, optional_parameters: { commands: \"READY,HELP,STOP\" }, forbidden_parameters: { forbidden })\n"
306 : "save_parameter_value(parameter_name: service, variable_name: register_version, type: integer)\n" // service is not an integer
307 : "send_message(command: READY, parameters: { status: \"3.05\" })\n"
308 : "wait(timeout: 1.0, mode: drain)\n"
309 : ;
310 :
311 : constexpr char const * const g_program_save_parameter_of_type_timestamp =
312 : "run()\n"
313 : "listen(address: <127.0.0.1:20002>)\n"
314 : "label(name: wait_message)\n"
315 : "wait(timeout: 10.0, mode: wait)\n"
316 : "has_message()\n"
317 : "if(false: wait_message)\n"
318 : "show_message()\n"
319 : "verify_message(command: REGISTER, required_parameters: { service: responder, version: 1 }, optional_parameters: { commands: \"READY,HELP,STOP\" }, forbidden_parameters: { forbidden })\n"
320 : "save_parameter_value(parameter_name: version, variable_name: register_version, type: integer)\n"
321 : "save_parameter_value(parameter_name: large_number, variable_name: default_integer, type: integer)\n"
322 : "send_message(command: READY, parameters: { status: \"3.05\", date: @1715440881.543723981 })\n"
323 : "clear_message()\n"
324 : "label(name: wait_second_message)\n"
325 : "wait(timeout: 10.0, mode: wait)\n"
326 : "has_message()\n"
327 : "if(false: wait_second_message)\n"
328 : "show_message()\n"
329 : "verify_message(command: TIMED, required_parameters: { now: `^[0-9]+(\\\\.[0-9]+)?$` } )\n"
330 : "save_parameter_value(parameter_name: now, variable_name: timed_value, type: timestamp)\n"
331 : "save_parameter_value(parameter_name: not_defined, variable_name: default_time, type: timestamp)\n"
332 : "exit()\n"
333 : ;
334 :
335 : constexpr char const * const g_program_save_parameter_with_unknown_type =
336 : "run()\n"
337 : "listen(address: <127.0.0.1:20002>)\n"
338 : "label(name: wait_message)\n"
339 : "clear_message()\n"
340 : "wait(timeout: 10.0, mode: wait)\n"
341 : "has_message()\n"
342 : "if(false: wait_message)\n"
343 : "show_message()\n"
344 : "verify_message(command: REGISTER, required_parameters: { service: responder, version: 1 }, optional_parameters: { commands: \"READY,HELP,STOP\" }, forbidden_parameters: { forbidden })\n"
345 : "save_parameter_value(parameter_name: service, variable_name: register_version, type: void)\n" // "void" is not a supported type here
346 : "send_message(command: READY, parameters: { status: \"3.05\" })\n"
347 : "wait(timeout: 1.0, mode: drain)\n"
348 : ;
349 :
350 : constexpr char const * const g_program_undefined_variable =
351 : "has_type(name: undefined_variable, type: void)\n"
352 : "if(unordered: it_worked)\n"
353 : "exit(error_message: \"undefined variable not properly detected.\")\n"
354 : "label(name: it_worked)\n"
355 : "exit()\n"
356 : ;
357 :
358 : constexpr char const * const g_program_integer_variable =
359 : "set_variable(name: my_int, value: 33)\n"
360 : "has_type(name: my_int, type: string)\n"
361 : "if(false: not_string)\n"
362 : "exit(error_message: \"integer variable detected as a string.\")\n"
363 : "label(name: not_string)\n"
364 : "has_type(name: my_int, type: integer)\n"
365 : "if(true: is_integer)\n"
366 : "exit(error_message: \"integer variable not properly detected as such.\")\n"
367 : "label(name: is_integer)\n"
368 : "exit()\n"
369 : ;
370 :
371 : constexpr char const * const g_program_string_variable =
372 : "set_variable(name: my_str, value: \"3.3\")\n"
373 : "has_type(name: my_str, type: floating_point)\n"
374 : "if(false: not_floating_point)\n"
375 : "exit(error_message: \"string variable detected as a floating_point.\")\n"
376 : "label(name: not_floating_point)\n"
377 : "has_type(name: my_str, type: string)\n"
378 : "if(true: is_string)\n"
379 : "exit(error_message: \"string variable not properly detected as such.\")\n"
380 : "label(name: is_string)\n"
381 : "exit()\n"
382 : ;
383 :
384 : constexpr char const * const g_program_if_variable =
385 : "if(variable: not_defined, unordered: not_defined_worked)\n"
386 : "exit(error_message: \"if(variable: <undefined>) failed test.\")\n"
387 : "label(name: not_defined_worked)\n"
388 :
389 : // >, >=, !=, true, ordered
390 : "set_variable(name: my_var, value: 5)\n"
391 : "if(variable: my_var, greater: positive_greater_int_worked)\n"
392 : "exit(error_message: \"if(variable: <positive integer> + greater) failed test.\")\n"
393 : "label(name: positive_greater_int_worked)\n"
394 : "if(variable: my_var, greater_or_equal: positive_greater_or_equal_int_worked)\n"
395 : "exit(error_message: \"if(variable: <positive integer> + greater_or_equal) failed test.\")\n"
396 : "label(name: positive_greater_or_equal_int_worked)\n"
397 : "if(variable: my_var, not_equal: positive_not_equal_int_worked)\n"
398 : "exit(error_message: \"if(variable: <positive integer> + not_equal) failed test.\")\n"
399 : "label(name: positive_not_equal_int_worked)\n"
400 : "if(variable: my_var, true: positive_true_int_worked)\n"
401 : "exit(error_message: \"if(variable: <positive integer> + true) failed test.\")\n"
402 : "label(name: positive_true_int_worked)\n"
403 : "if(variable: my_var, ordered: positive_ordered_int_worked)\n"
404 : "exit(error_message: \"if(variable: <positive integer> + ordered) failed test.\")\n"
405 : "label(name: positive_ordered_int_worked)\n"
406 :
407 : // <, <=, !=, true, ordered
408 : "set_variable(name: my_var, value: -5)\n"
409 : "if(variable: my_var, less: negative_less_int_worked)\n"
410 : "exit(error_message: \"if(variable: <negative integer> + less) failed test.\")\n"
411 : "label(name: negative_less_int_worked)\n"
412 : "if(variable: my_var, less_or_equal: negative_less_or_equal_int_worked)\n"
413 : "exit(error_message: \"if(variable: <negative integer> + less_or_equal) failed test.\")\n"
414 : "label(name: negative_less_or_equal_int_worked)\n"
415 : "if(variable: my_var, not_equal: negative_not_equal_int_worked)\n"
416 : "exit(error_message: \"if(variable: <negative integer> + not_equal) failed test.\")\n"
417 : "label(name: negative_not_equal_int_worked)\n"
418 : "if(variable: my_var, true: negative_true_int_worked)\n"
419 : "exit(error_message: \"if(variable: <negative integer> + true) failed test.\")\n"
420 : "label(name: negative_true_int_worked)\n"
421 : "if(variable: my_var, ordered: negative_ordered_int_worked)\n"
422 : "exit(error_message: \"if(variable: <negative integer> + ordered) failed test.\")\n"
423 : "label(name: negative_ordered_int_worked)\n"
424 :
425 : // ==, false, ordered
426 : "set_variable(name: my_var, value: 0)\n"
427 : "if(variable: my_var, equal: zero_equal_int_worked)\n"
428 : "exit(error_message: \"if(variable: <zero integer> + equal) failed test.\")\n"
429 : "label(name: zero_equal_int_worked)\n"
430 : "if(variable: my_var, less_or_equal: zero_less_or_equal_int_worked)\n"
431 : "exit(error_message: \"if(variable: <negative integer> + less_or_equal) failed test.\")\n"
432 : "label(name: zero_less_or_equal_int_worked)\n"
433 : "if(variable: my_var, greater_or_equal: zero_greater_or_equal_int_worked)\n"
434 : "exit(error_message: \"if(variable: <negative integer> + greater_or_equal) failed test.\")\n"
435 : "label(name: zero_greater_or_equal_int_worked)\n"
436 : "if(variable: my_var, false: zero_false_int_worked)\n"
437 : "exit(error_message: \"if(variable: <negative integer> + false) failed test.\")\n"
438 : "label(name: zero_false_int_worked)\n"
439 : "if(variable: my_var, ordered: zero_ordered_int_worked)\n"
440 : "exit(error_message: \"if(variable: <negative integer> + ordered) failed test.\")\n"
441 : "label(name: zero_ordered_int_worked)\n"
442 :
443 : // >, >=, !=, true, ordered
444 : "set_variable(name: my_var, value: 7.3)\n"
445 : "if(variable: my_var, greater: positive_greater_flt_worked)\n"
446 : "exit(error_message: \"if(variable: <positive floating point> + greater) failed test.\")\n"
447 : "label(name: positive_greater_flt_worked)\n"
448 : "if(variable: my_var, greater_or_equal: positive_greater_or_equal_flt_worked)\n"
449 : "exit(error_message: \"if(variable: <positive floating point> + greater_or_equal) failed test.\")\n"
450 : "label(name: positive_greater_or_equal_flt_worked)\n"
451 : "if(variable: my_var, not_equal: positive_not_equal_flt_worked)\n"
452 : "exit(error_message: \"if(variable: <positive floating point> + not_equal) failed test.\")\n"
453 : "label(name: positive_not_equal_flt_worked)\n"
454 : "if(variable: my_var, true: positive_true_flt_worked)\n"
455 : "exit(error_message: \"if(variable: <positive floating point> + true) failed test.\")\n"
456 : "label(name: positive_true_flt_worked)\n"
457 : "if(variable: my_var, ordered: positive_ordered_flt_worked)\n"
458 : "exit(error_message: \"if(variable: <positive floating point> + ordered) failed test.\")\n"
459 : "label(name: positive_ordered_flt_worked)\n"
460 :
461 : // <, <=, !=, true, ordered
462 : "set_variable(name: my_var, value: -7.3)\n"
463 : "if(variable: my_var, less: negative_less_flt_worked)\n"
464 : "exit(error_message: \"if(variable: <negative floating point> + less) failed test.\")\n"
465 : "label(name: negative_less_flt_worked)\n"
466 : "if(variable: my_var, less_or_equal: negative_less_or_equal_flt_worked)\n"
467 : "exit(error_message: \"if(variable: <negative integer> + less_or_equal) failed test.\")\n"
468 : "label(name: negative_less_or_equal_flt_worked)\n"
469 : "if(variable: my_var, not_equal: negative_not_equal_flt_worked)\n"
470 : "exit(error_message: \"if(variable: <negative integer> + not_equal) failed test.\")\n"
471 : "label(name: negative_not_equal_flt_worked)\n"
472 : "if(variable: my_var, true: negative_true_flt_worked)\n"
473 : "exit(error_message: \"if(variable: <negative integer> + true) failed test.\")\n"
474 : "label(name: negative_true_flt_worked)\n"
475 : "if(variable: my_var, ordered: negative_ordered_flt_worked)\n"
476 : "exit(error_message: \"if(variable: <negative integer> + ordered) failed test.\")\n"
477 : "label(name: negative_ordered_flt_worked)\n"
478 :
479 : // ==, false, ordered
480 : "set_variable(name: my_var, value: 0.0)\n"
481 : "if(variable: my_var, equal: zero_equal_flt_worked)\n"
482 : "exit(error_message: \"if(variable: <zero floating point> + equal) failed test.\")\n"
483 : "label(name: zero_equal_flt_worked)\n"
484 : "if(variable: my_var, less_or_equal: zero_less_or_equal_flt_worked)\n"
485 : "exit(error_message: \"if(variable: <negative integer> + less_or_equal) failed test.\")\n"
486 : "label(name: zero_less_or_equal_flt_worked)\n"
487 : "if(variable: my_var, greater_or_equal: zero_greater_or_equal_flt_worked)\n"
488 : "exit(error_message: \"if(variable: <negative integer> + greater_or_equal) failed test.\")\n"
489 : "label(name: zero_greater_or_equal_flt_worked)\n"
490 : "if(variable: my_var, false: zero_false_flt_worked)\n"
491 : "exit(error_message: \"if(variable: <negative integer> + false) failed test.\")\n"
492 : "label(name: zero_false_flt_worked)\n"
493 : "if(variable: my_var, ordered: zero_ordered_flt_worked)\n"
494 : "exit(error_message: \"if(variable: <negative integer> + ordered) failed test.\")\n"
495 : "label(name: zero_ordered_flt_worked)\n"
496 :
497 : // unordered
498 : "set_variable(name: my_var, value: NaN)\n"
499 : "if(variable: my_var, unordered: unordered_flt_worked)\n"
500 : "exit(error_message: \"if(variable: <unordered floating point>) failed test.\")\n"
501 : "label(name: unordered_flt_worked)\n"
502 :
503 : "exit()\n"
504 : ;
505 :
506 : constexpr char const * const g_program_print_message =
507 : "print(message: \"testing print()\")\n"
508 : "exit()\n"
509 : ;
510 :
511 : constexpr char const * const g_program_error_message =
512 : "exit(error_message: \"testing exit with an error\")\n"
513 : ;
514 :
515 : constexpr char const * const g_program_no_condition =
516 : "if(true: exit)\n"
517 : "label(name: exit)\n"
518 : ;
519 :
520 : constexpr char const * const g_program_two_listen =
521 : "listen(address: <127.0.0.1:20002>)\n"
522 : "listen(address: <127.0.0.1:20003>)\n"
523 : ;
524 :
525 : constexpr char const * const g_program_label_bad_type =
526 : "label(name: 123)\n"
527 : ;
528 :
529 : constexpr char const * const g_program_exit_bad_type =
530 : "exit(error_message: 12.3)\n"
531 : ;
532 :
533 : constexpr char const * const g_program_unsupported_addition_address_address =
534 : "set_variable(name: bad, value: <127.0.0.1:80> + <127.0.1.5:81>)\n"
535 : ;
536 :
537 : constexpr char const * const g_program_unsupported_addition_address_string =
538 : "set_variable(name: bad, value: <127.0.0.1:80> + '127.0.1.5:81')\n"
539 : ;
540 :
541 : constexpr char const * const g_program_unsupported_addition_string_address =
542 : "set_variable(name: bad, value: '127.0.0.1:80' + <127.0.1.5:81>)\n"
543 : ;
544 :
545 : constexpr char const * const g_program_unsupported_addition_address_identifier =
546 : "set_variable(name: bad, value: <127.0.0.1:80> + alpha)\n"
547 : ;
548 :
549 : constexpr char const * const g_program_unsupported_addition_identifier_address =
550 : "set_variable(name: bad, value: beta + <127.0.1.5:81>)\n"
551 : ;
552 :
553 : constexpr char const * const g_program_unsupported_addition_identifier_string =
554 : "set_variable(name: bad, value: this + '127.0.1.5:81')\n"
555 : ;
556 :
557 : constexpr char const * const g_program_unsupported_addition_string_identifier =
558 : "set_variable(name: bad, value: '127.0.0.1:80' + that)\n"
559 : ;
560 :
561 : constexpr char const * const g_program_unsupported_subtraction_address_string =
562 : "set_variable(name: bad, value: <127.0.0.1:80> - '127.0.1.5:81')\n"
563 : ;
564 :
565 : constexpr char const * const g_program_unsupported_subtraction_string_address =
566 : "set_variable(name: bad, value: '127.0.0.1:80' - <127.0.1.5:81>)\n"
567 : ;
568 :
569 : constexpr char const * const g_program_unsupported_subtraction_address_identifier =
570 : "set_variable(name: bad, value: <127.0.0.1:80> - alpha)\n"
571 : ;
572 :
573 : constexpr char const * const g_program_unsupported_subtraction_identifier_address =
574 : "set_variable(name: bad, value: beta - <127.0.1.5:81>)\n"
575 : ;
576 :
577 : constexpr char const * const g_program_unsupported_subtraction_identifier_string =
578 : "set_variable(name: bad, value: this - '127.0.1.5:81')\n"
579 : ;
580 :
581 : constexpr char const * const g_program_unsupported_subtraction_string_identifier =
582 : "set_variable(name: bad, value: '127.0.0.1:80' - that)\n"
583 : ;
584 :
585 : constexpr char const * const g_program_unsupported_multiplication_address_address =
586 : "set_variable(name: bad, value: <127.0.0.1:80> * <192.168.2.2:443>)\n"
587 : ;
588 :
589 : constexpr char const * const g_program_unsupported_multiplication_address_string =
590 : "set_variable(name: bad, value: <127.0.0.1:80> * 'invalid')\n"
591 : ;
592 :
593 : constexpr char const * const g_program_unsupported_multiplication_string_address =
594 : "set_variable(name: bad, value: 'invalid' * <127.0.0.1:80>)\n"
595 : ;
596 :
597 : constexpr char const * const g_program_unsupported_multiplication_address_identifier =
598 : "set_variable(name: bad, value: <127.0.0.1:80> * invalid)\n"
599 : ;
600 :
601 : constexpr char const * const g_program_unsupported_multiplication_identifier_address =
602 : "set_variable(name: bad, value: invalid * <127.0.0.1:80>)\n"
603 : ;
604 :
605 : constexpr char const * const g_program_unsupported_multiplication_identifier_string =
606 : "set_variable(name: bad, value: 'invalid' * invalid)\n"
607 : ;
608 :
609 : constexpr char const * const g_program_unsupported_multiplication_string_identifier =
610 : "set_variable(name: bad, value: invalid * \"invalid\")\n"
611 : ;
612 :
613 : constexpr char const * const g_program_unsupported_multiplication_string_string =
614 : "set_variable(name: bad, value: 'invalid' * \"invalid\")\n"
615 : ;
616 :
617 : constexpr char const * const g_program_unsupported_multiplication_identifier_identifier =
618 : "set_variable(name: bad, value: invalid * not_valid)\n"
619 : ;
620 :
621 : constexpr char const * const g_program_unsupported_division_address_address =
622 : "set_variable(name: bad, value: <127.0.0.1:80> / <192.168.2.2:443>)\n"
623 : ;
624 :
625 : constexpr char const * const g_program_unsupported_division_address_string =
626 : "set_variable(name: bad, value: <127.0.0.1:80> / 'invalid')\n"
627 : ;
628 :
629 : constexpr char const * const g_program_unsupported_division_string_address =
630 : "set_variable(name: bad, value: 'invalid' / <127.0.0.1:80>)\n"
631 : ;
632 :
633 : constexpr char const * const g_program_unsupported_division_address_identifier =
634 : "set_variable(name: bad, value: <127.0.0.1:80> / invalid)\n"
635 : ;
636 :
637 : constexpr char const * const g_program_unsupported_division_identifier_address =
638 : "set_variable(name: bad, value: invalid / <127.0.0.1:80>)\n"
639 : ;
640 :
641 : constexpr char const * const g_program_unsupported_division_identifier_string =
642 : "set_variable(name: bad, value: 'invalid' / invalid)\n"
643 : ;
644 :
645 : constexpr char const * const g_program_unsupported_division_string_identifier =
646 : "set_variable(name: bad, value: invalid / \"invalid\")\n"
647 : ;
648 :
649 : constexpr char const * const g_program_unsupported_division_string_string =
650 : "set_variable(name: bad, value: 'invalid' / \"invalid\")\n"
651 : ;
652 :
653 : constexpr char const * const g_program_unsupported_division_identifier_identifier =
654 : "set_variable(name: bad, value: invalid / not_valid)\n"
655 : ;
656 :
657 : constexpr char const * const g_program_unsupported_modulo_address_address =
658 : "set_variable(name: bad, value: <127.0.0.1:80> % <192.168.2.2:443>)\n"
659 : ;
660 :
661 : constexpr char const * const g_program_unsupported_modulo_address_string =
662 : "set_variable(name: bad, value: <127.0.0.1:80> % 'invalid')\n"
663 : ;
664 :
665 : constexpr char const * const g_program_unsupported_modulo_string_address =
666 : "set_variable(name: bad, value: 'invalid' % <127.0.0.1:80>)\n"
667 : ;
668 :
669 : constexpr char const * const g_program_unsupported_modulo_address_identifier =
670 : "set_variable(name: bad, value: <127.0.0.1:80> % invalid)\n"
671 : ;
672 :
673 : constexpr char const * const g_program_unsupported_modulo_identifier_address =
674 : "set_variable(name: bad, value: invalid % <127.0.0.1:80>)\n"
675 : ;
676 :
677 : constexpr char const * const g_program_unsupported_modulo_identifier_string =
678 : "set_variable(name: bad, value: invalid % \"invalid\")\n"
679 : ;
680 :
681 : constexpr char const * const g_program_unsupported_modulo_string_identifier =
682 : "set_variable(name: bad, value: 'invalid' % invalid)\n"
683 : ;
684 :
685 : constexpr char const * const g_program_unsupported_modulo_string_string =
686 : "set_variable(name: bad, value: 'invalid' % \"invalid\")\n"
687 : ;
688 :
689 : constexpr char const * const g_program_unsupported_modulo_identifier_identifier =
690 : "set_variable(name: bad, value: invalid % not_valid)\n"
691 : ;
692 :
693 : constexpr char const * const g_program_unsupported_negation_single_string =
694 : "set_variable(name: bad, value: -'string')\n"
695 : ;
696 :
697 : constexpr char const * const g_program_unsupported_negation_double_string =
698 : "set_variable(name: bad, value: -\"string\")\n"
699 : ;
700 :
701 : constexpr char const * const g_program_unsupported_negation_address =
702 : "set_variable(name: bad, value: -<127.0.0.1:80>)\n"
703 : ;
704 :
705 : constexpr char const * const g_program_unterminated_double_string_variable =
706 : "set_variable(name: my_var, value: \"blah\")\n"
707 : "set_variable(name: missing_close, value: \"ref. ${my_var\")\n"
708 : ;
709 :
710 : constexpr char const * const g_program_regex_in_double_string_variable =
711 : "set_variable(name: my_regex, value: `[a-z]+`)\n"
712 : "set_variable(name: missing_close, value: \"ref. ${my_regex}\")\n"
713 : ;
714 :
715 : constexpr char const * const g_program_primary_variable_references =
716 : "set_variable(name: my_string_var, value: \"foo\")\n"
717 : "set_variable(name: longer_string_var, value: ${my_string_var})\n"
718 : "set_variable(name: my_integer_var, value: 41)\n"
719 : "set_variable(name: longer_integer_var, value: ${my_integer_var})\n"
720 : "set_variable(name: my_floating_point_var, value: 303.601)\n"
721 : "set_variable(name: longer_floating_point_var, value: ${my_floating_point_var})\n"
722 : "set_variable(name: my_identifier_var, value: bar)\n"
723 : "set_variable(name: longer_identifier_var, value: ${my_identifier_var})\n"
724 : "set_variable(name: my_regex_var, value: `^[regex]$`)\n"
725 : "set_variable(name: longer_regex_var, value: ${my_regex_var})\n"
726 : "set_variable(name: my_address_var, value: <10.12.14.16:89>)\n"
727 : "set_variable(name: longer_address_var, value: ${my_address_var})\n"
728 : "set_variable(name: my_timestamp_var, value: @1714241733.419438123)\n"
729 : "set_variable(name: longer_timestamp_var, value: ${my_timestamp_var})\n"
730 : ;
731 :
732 : constexpr char const * const g_program_wrong_primary_variable_reference =
733 : "set_variable(name: my_var, value: foo)\n"
734 : "set_variable(name: longer_var, value: ${wrong_name})\n"
735 : ;
736 :
737 : constexpr char const * const g_program_double_string_variable_without_name =
738 : "set_variable(name: missing_close, value: \"ref. ${} is empty\")\n"
739 : ;
740 :
741 : constexpr char const * const g_program_unsupported_negation_repeat =
742 : "set_variable(name: bad, value: 'string' * -5)\n"
743 : ;
744 :
745 : constexpr char const * const g_program_unsupported_large_repeat =
746 : "set_variable(name: bad, value: 'string' * 1001)\n"
747 : ;
748 :
749 : constexpr char const * const g_program_bad_exit =
750 : "exit(error_message: \"bad error occurred!\", timeout: 3.001)\n"
751 : ;
752 :
753 : constexpr char const * const g_program_bad_exit_timeout =
754 : "exit(timeout: 'bad')\n"
755 : ;
756 :
757 : constexpr char const * const g_program_bad_print_message =
758 : "print(message: string_expected)\n"
759 : ;
760 :
761 : constexpr char const * const g_program_send_message_without_connection =
762 : "send_message(command: WITHOUT_CONNECTION)\n"
763 : ;
764 :
765 : constexpr char const * const g_program_if_invalid_type =
766 : "set_variable(name: my_str, value: \"bad\")\n"
767 : "if(variable: my_str, unordered: unused)\n"
768 : "exit(error_message: \"if() did not fail.\")\n"
769 : "label(name: unused)\n"
770 : "exit(error_message: \"if() branched unexpectendly.\")\n"
771 : ;
772 :
773 : constexpr char const * const g_program_wait_outside_thread =
774 : "wait(timeout: 10)\n"
775 : ;
776 :
777 : constexpr char const * const g_program_wait_invalid_mode =
778 : "run()\n"
779 : "wait(timeout: 10, mode: not_this_one)\n"
780 : ;
781 :
782 : constexpr char const * const g_program_wait_no_connections =
783 : "run()\n"
784 : "wait(timeout: 10, mode: wait)\n"
785 : ;
786 :
787 : constexpr char const * const g_program_verify_message_fail_sent_server =
788 : "run()\n"
789 : "listen(address: <127.0.0.1:20002>)\n"
790 : "label(name: wait_message)\n"
791 : "clear_message()\n"
792 : "wait(timeout: 12, mode: wait)\n"
793 : "has_message()\n"
794 : "if(false: wait_message)\n"
795 : "show_message()\n"
796 : "verify_message(command: REGISTER, sent_server: not_this_one)\n"
797 : "exit()\n"
798 : ;
799 :
800 : constexpr char const * const g_program_verify_message_fail_sent_service =
801 : "run()\n"
802 : "listen(address: <127.0.0.1:20002>)\n"
803 : "label(name: wait_message)\n"
804 : "clear_message()\n"
805 : "wait(timeout: 12, mode: wait)\n"
806 : "has_message()\n"
807 : "if(false: wait_message)\n"
808 : "show_message()\n"
809 : "verify_message(command: REGISTER, sent_service: not_this_one)\n"
810 : "exit()\n"
811 : ;
812 :
813 : constexpr char const * const g_program_verify_message_fail_server =
814 : "run()\n"
815 : "listen(address: <127.0.0.1:20002>)\n"
816 : "label(name: wait_message)\n"
817 : "clear_message()\n"
818 : "wait(timeout: 12, mode: wait)\n"
819 : "has_message()\n"
820 : "if(false: wait_message)\n"
821 : "show_message()\n"
822 : "verify_message(command: REGISTER, server: not_this_one)\n"
823 : "exit()\n"
824 : ;
825 :
826 : constexpr char const * const g_program_verify_message_fail_service =
827 : "run()\n"
828 : "listen(address: <127.0.0.1:20002>)\n"
829 : "label(name: wait_message)\n"
830 : "clear_message()\n"
831 : "wait(timeout: 12, mode: wait)\n"
832 : "has_message()\n"
833 : "if(false: wait_message)\n"
834 : "show_message()\n"
835 : "verify_message(command: REGISTER, service: not_this_one)\n"
836 : "exit()\n"
837 : ;
838 :
839 : constexpr char const * const g_program_verify_message_fail_command =
840 : "run()\n"
841 : "listen(address: <127.0.0.1:20002>)\n"
842 : "label(name: wait_message)\n"
843 : "clear_message()\n"
844 : "wait(timeout: 12, mode: wait)\n"
845 : "has_message()\n"
846 : "if(false: wait_message)\n"
847 : "show_message()\n"
848 : "verify_message(command: NOT_THIS_ONE)\n"
849 : "exit()\n"
850 : ;
851 :
852 : constexpr char const * const g_program_verify_message_fail_forbidden =
853 : "run()\n"
854 : "listen(address: <127.0.0.1:20002>)\n"
855 : "label(name: wait_message)\n"
856 : "clear_message()\n"
857 : "wait(timeout: 12, mode: wait)\n"
858 : "has_message()\n"
859 : "if(false: wait_message)\n"
860 : "show_message()\n"
861 : "verify_message(command: REGISTER, forbidden_parameters: { version })\n"
862 : "exit()\n"
863 : ;
864 :
865 : constexpr char const * const g_program_verify_message_fail_required =
866 : "run()\n"
867 : "listen(address: <127.0.0.1:20002>)\n"
868 : "label(name: wait_message)\n"
869 : "clear_message()\n"
870 : "wait(timeout: 12, mode: wait)\n"
871 : "has_message()\n"
872 : "if(false: wait_message)\n"
873 : "show_message()\n"
874 : "verify_message(command: REGISTER, required_parameters: { not_this_one: 123 })\n"
875 : "exit()\n"
876 : ;
877 :
878 : constexpr char const * const g_program_verify_message_fail_required_int_value =
879 : "run()\n"
880 : "listen(address: <127.0.0.1:20002>)\n"
881 : "label(name: wait_message)\n"
882 : "clear_message()\n"
883 : "wait(timeout: 12, mode: wait)\n"
884 : "has_message()\n"
885 : "if(false: wait_message)\n"
886 : "show_message()\n"
887 : "verify_message(command: REGISTER, required_parameters: { version: 200 })\n"
888 : "exit()\n"
889 : ;
890 :
891 : constexpr char const * const g_program_verify_message_fail_required_str_value =
892 : "run()\n"
893 : "listen(address: <127.0.0.1:20002>)\n"
894 : "label(name: wait_message)\n"
895 : "clear_message()\n"
896 : "wait(timeout: 12, mode: wait)\n"
897 : "has_message()\n"
898 : "if(false: wait_message)\n"
899 : "show_message()\n"
900 : "verify_message(command: REGISTER, required_parameters: { service: not_this_one })\n"
901 : "exit()\n"
902 : ;
903 :
904 : constexpr char const * const g_program_verify_message_fail_required_flt_value =
905 : "run()\n"
906 : "listen(address: <127.0.0.1:20002>)\n"
907 : "label(name: wait_message)\n"
908 : "clear_message()\n"
909 : "wait(timeout: 12, mode: wait)\n"
910 : "has_message()\n"
911 : "if(false: wait_message)\n"
912 : "show_message()\n"
913 : "verify_message(command: REGISTER, required_parameters: { version: 1.0 })\n"
914 : "exit()\n"
915 : ;
916 :
917 : constexpr char const * const g_program_last_wait =
918 : "run()\n"
919 : "listen(address: <127.0.0.1:20002>)\n"
920 : "label(name: wait_message)\n"
921 : "clear_message()\n"
922 : "wait(timeout: 10.0, mode: wait)\n"
923 : "has_message()\n"
924 : "if(false: wait_message)\n"
925 : "show_message()\n"
926 : "verify_message(command: REGISTER, required_parameters: { service: responder, version: 1 }, optional_parameters: { commands: \"READY,HELP,STOP\" }, forbidden_parameters: { forbidden })\n"
927 : "send_message(command: READY, sent_server: reporter_test_extension, sent_service: test_processor, server: reporter_test, service: accept_one_message, parameters: { status: alive })\n"
928 : "wait(timeout: 1.0, mode: drain)\n" // hope that send_message() is small enough that a single wait is sufficient to send it
929 : "wait(timeout: 1.0)\n"
930 : "disconnect()\n"
931 : "exit()\n"
932 : ;
933 :
934 : constexpr char const * const g_program_regex_parameter_no_match =
935 : "run()\n"
936 : "listen(address: <127.0.0.1:20002>)\n"
937 : "label(name: wait_message)\n"
938 : "clear_message()\n"
939 : "wait(timeout: 10.0, mode: wait)\n"
940 : "has_message()\n"
941 : "if(false: wait_message)\n"
942 : "show_message()\n"
943 : "verify_message(command: REGISTER, required_parameters: { service: responder, version: `_[a-z]+` }, optional_parameters: { commands: \"READY,HELP,STOP\" }, forbidden_parameters: { forbidden })\n"
944 : "send_message(command: READY, sent_server: reporter_test_extension, sent_service: test_processor, server: reporter_test, service: accept_one_message, parameters: { status: alive })\n"
945 : "wait(timeout: 1.0, mode: drain)\n"
946 : "wait(timeout: 1.0)\n"
947 : "disconnect()\n"
948 : "exit()\n"
949 : ;
950 :
951 : constexpr char const * const g_program_wait_for_nothing =
952 : "run()\n"
953 : "listen(address: <127.0.0.1:20002>)\n"
954 : "label(name: wait_message)\n"
955 : "clear_message()\n"
956 : "wait(timeout: 10.0, mode: wait)\n" // first wait reacts on connect(), second wait receives the REGISTER message
957 : "has_message()\n"
958 : "if(false: wait_message)\n"
959 : "show_message()\n"
960 : "verify_message(command: REGISTER, required_parameters: { service: responder, version: 1 }, optional_parameters: { commands: \"READY,HELP,STOP\" }, forbidden_parameters: { forbidden })\n"
961 : "send_message(command: READY, sent_server: reporter_test_extension, sent_service: test_processor, server: reporter_test, service: accept_one_message, parameters: { status: alive })\n"
962 : "wait(timeout: 1.0, mode: drain)\n"
963 : "wait(timeout: 1.0)\n"
964 : "wait(timeout: 1.0)\n" // one too many wait(), it will time out
965 : "exit()\n"
966 : ;
967 :
968 : constexpr char const * const g_program_wait_for_timeout =
969 : "run()\n"
970 : "listen(address: <127.0.0.1:20002>)\n"
971 : "label(name: wait_message)\n"
972 : "clear_message()\n"
973 : "wait(timeout: 10.0, mode: wait)\n" // first wait reacts on connect(), second wait receives the REGISTER message
974 : "has_message()\n"
975 : "if(false: wait_message)\n"
976 : "show_message()\n"
977 : "verify_message(command: REGISTER, required_parameters: { service: responder, version: 1 }, optional_parameters: { commands: \"READY,HELP,STOP\" }, forbidden_parameters: { forbidden })\n"
978 : "send_message(command: READY, sent_server: reporter_test_extension, sent_service: test_processor, server: reporter_test, service: accept_one_message, parameters: { status: alive })\n"
979 : "wait(timeout: 1.0, mode: drain)\n"
980 : "wait(timeout: 1.0)\n"
981 : "wait(timeout: 1.0, mode: timeout)\n" // one extra wait(), which will time out
982 : "exit()\n"
983 : ;
984 :
985 :
986 :
987 : struct expected_trace_t
988 : {
989 : SNAP_CATCH2_NAMESPACE::reporter::callback_reason_t const
990 : f_reason = SNAP_CATCH2_NAMESPACE::reporter::callback_reason_t::CALLBACK_REASON_BEFORE_CALL;
991 : char const * const f_name = nullptr;
992 : };
993 :
994 :
995 : constexpr expected_trace_t const g_verify_starting_thread[] =
996 : {
997 : {
998 : .f_reason = SNAP_CATCH2_NAMESPACE::reporter::callback_reason_t::CALLBACK_REASON_BEFORE_CALL,
999 : .f_name = "set_variable",
1000 : },
1001 : {
1002 : .f_reason = SNAP_CATCH2_NAMESPACE::reporter::callback_reason_t::CALLBACK_REASON_AFTER_CALL,
1003 : .f_name = "set_variable",
1004 : },
1005 : {
1006 : .f_reason = SNAP_CATCH2_NAMESPACE::reporter::callback_reason_t::CALLBACK_REASON_BEFORE_CALL,
1007 : .f_name = "set_variable",
1008 : },
1009 : {
1010 : .f_reason = SNAP_CATCH2_NAMESPACE::reporter::callback_reason_t::CALLBACK_REASON_AFTER_CALL,
1011 : .f_name = "set_variable",
1012 : },
1013 : {
1014 : .f_reason = SNAP_CATCH2_NAMESPACE::reporter::callback_reason_t::CALLBACK_REASON_BEFORE_CALL,
1015 : .f_name = "run",
1016 : },
1017 : {
1018 : .f_reason = SNAP_CATCH2_NAMESPACE::reporter::callback_reason_t::CALLBACK_REASON_AFTER_CALL,
1019 : .f_name = "run",
1020 : },
1021 : {
1022 : .f_reason = SNAP_CATCH2_NAMESPACE::reporter::callback_reason_t::CALLBACK_REASON_BEFORE_CALL,
1023 : .f_name = "set_variable",
1024 : },
1025 : {
1026 : .f_reason = SNAP_CATCH2_NAMESPACE::reporter::callback_reason_t::CALLBACK_REASON_AFTER_CALL,
1027 : .f_name = "set_variable",
1028 : },
1029 : {
1030 : .f_reason = SNAP_CATCH2_NAMESPACE::reporter::callback_reason_t::CALLBACK_REASON_BEFORE_CALL,
1031 : .f_name = "set_variable",
1032 : },
1033 : {
1034 : .f_reason = SNAP_CATCH2_NAMESPACE::reporter::callback_reason_t::CALLBACK_REASON_AFTER_CALL,
1035 : .f_name = "set_variable",
1036 : },
1037 : {
1038 : .f_reason = SNAP_CATCH2_NAMESPACE::reporter::callback_reason_t::CALLBACK_REASON_BEFORE_CALL,
1039 : .f_name = "set_variable",
1040 : },
1041 : {
1042 : .f_reason = SNAP_CATCH2_NAMESPACE::reporter::callback_reason_t::CALLBACK_REASON_AFTER_CALL,
1043 : .f_name = "set_variable",
1044 : },
1045 : {
1046 : .f_reason = SNAP_CATCH2_NAMESPACE::reporter::callback_reason_t::CALLBACK_REASON_BEFORE_CALL,
1047 : .f_name = "set_variable",
1048 : },
1049 : {
1050 : .f_reason = SNAP_CATCH2_NAMESPACE::reporter::callback_reason_t::CALLBACK_REASON_AFTER_CALL,
1051 : .f_name = "set_variable",
1052 : },
1053 : {
1054 : .f_reason = SNAP_CATCH2_NAMESPACE::reporter::callback_reason_t::CALLBACK_REASON_BEFORE_CALL,
1055 : .f_name = "set_variable",
1056 : },
1057 : {
1058 : .f_reason = SNAP_CATCH2_NAMESPACE::reporter::callback_reason_t::CALLBACK_REASON_AFTER_CALL,
1059 : .f_name = "set_variable",
1060 : },
1061 : {
1062 : .f_reason = SNAP_CATCH2_NAMESPACE::reporter::callback_reason_t::CALLBACK_REASON_BEFORE_CALL,
1063 : .f_name = "set_variable",
1064 : },
1065 : {
1066 : .f_reason = SNAP_CATCH2_NAMESPACE::reporter::callback_reason_t::CALLBACK_REASON_AFTER_CALL,
1067 : .f_name = "set_variable",
1068 : },
1069 : {
1070 : .f_reason = SNAP_CATCH2_NAMESPACE::reporter::callback_reason_t::CALLBACK_REASON_BEFORE_CALL,
1071 : .f_name = "set_variable",
1072 : },
1073 : {
1074 : .f_reason = SNAP_CATCH2_NAMESPACE::reporter::callback_reason_t::CALLBACK_REASON_AFTER_CALL,
1075 : .f_name = "set_variable",
1076 : },
1077 : {}
1078 : };
1079 :
1080 :
1081 : class trace
1082 : {
1083 : public:
1084 1 : trace(expected_trace_t const * expected_trace)
1085 1 : : f_expected_trace(expected_trace)
1086 : {
1087 1 : }
1088 :
1089 : trace(trace const &) = delete;
1090 :
1091 1 : ~trace()
1092 : {
1093 : // make sure we reached the end of the list
1094 : //
1095 1 : CATCH_REQUIRE(f_expected_trace[f_pos].f_name == nullptr);
1096 1 : }
1097 :
1098 : trace operator = (trace const &) = delete;
1099 :
1100 20 : void callback(SNAP_CATCH2_NAMESPACE::reporter::state & s, SNAP_CATCH2_NAMESPACE::reporter::callback_reason_t reason)
1101 : {
1102 : // here we can be in the thread so DO NOT USE CATCH_... macros
1103 : //
1104 20 : if(f_expected_trace[f_pos].f_name == nullptr)
1105 : {
1106 0 : throw std::runtime_error(
1107 : "got more calls ("
1108 0 : + std::to_string(f_pos + 1)
1109 0 : + ") to tracer than expected.");
1110 : }
1111 :
1112 20 : if(f_expected_trace[f_pos].f_reason != reason)
1113 : {
1114 0 : throw std::runtime_error(
1115 : "unexpected reason at position "
1116 0 : + std::to_string(f_pos)
1117 0 : + " (got "
1118 0 : + std::to_string(static_cast<int>(reason))
1119 0 : + ", expected "
1120 0 : + std::to_string(static_cast<int>(f_expected_trace[f_pos].f_reason))
1121 0 : + ").");
1122 : }
1123 :
1124 20 : SNAP_CATCH2_NAMESPACE::reporter::statement::pointer_t stmt(s.get_running_statement());
1125 20 : std::string const & name(stmt->get_instruction()->get_name());
1126 : //std::cerr << "--------------------- at pos " << f_pos << " found reason " << static_cast<int>(reason) << " + name " << name << "\n";
1127 20 : if(f_expected_trace[f_pos].f_name != name)
1128 : {
1129 0 : throw std::runtime_error(
1130 : "unexpected instruction at position "
1131 0 : + std::to_string(f_pos)
1132 0 : + " (got "
1133 0 : + name
1134 0 : + ", expected "
1135 0 : + f_expected_trace[f_pos].f_name
1136 0 : + ").");
1137 : }
1138 :
1139 20 : ++f_pos;
1140 40 : }
1141 :
1142 : private:
1143 : int f_pos = 0;
1144 : expected_trace_t const * f_expected_trace = nullptr;
1145 : };
1146 :
1147 :
1148 : class messenger_responder // an equivalent to a client
1149 : : public ed::tcp_client_permanent_message_connection
1150 : {
1151 : public:
1152 : typedef std::shared_ptr<messenger_responder> pointer_t;
1153 :
1154 : enum class sequence_t
1155 : {
1156 : SEQUENCE_ONE_MESSAGE,
1157 : SEQUENCE_UNWANTED_MESSAGE,
1158 : SEQUENCE_TIMED_MESSAGE,
1159 : SEQUENCE_READY_HELP_MESSAGE,
1160 : SEQUENCE_READY_THROW,
1161 : SEQUENCE_READY_THROW_WHAT,
1162 : };
1163 :
1164 24 : messenger_responder(
1165 : addr::addr const & a
1166 : , ed::mode_t mode
1167 : , sequence_t sequence)
1168 24 : : tcp_client_permanent_message_connection(
1169 : a
1170 : , mode
1171 : , ed::DEFAULT_PAUSE_BEFORE_RECONNECTING
1172 : , true
1173 : , "responder") // service name
1174 24 : , f_sequence(sequence)
1175 : {
1176 24 : set_name("messenger_responder"); // connection name
1177 24 : }
1178 :
1179 23 : virtual void process_connected() override
1180 : {
1181 : // always register at the time we connect
1182 : //
1183 23 : tcp_client_permanent_message_connection::process_connected();
1184 23 : register_service();
1185 23 : }
1186 :
1187 12 : virtual void process_message(ed::message & msg) override
1188 : {
1189 12 : ++f_step;
1190 : std::cout
1191 12 : << "--- \"client\" message ("
1192 : << f_step
1193 : << "): "
1194 12 : << msg
1195 12 : << std::endl;
1196 :
1197 12 : bool disconnect_all(false);
1198 :
1199 12 : if(f_step == 1)
1200 : {
1201 8 : if(msg.get_command() != "READY")
1202 : {
1203 0 : throw std::runtime_error(
1204 : "first message expected to be READY, got "
1205 0 : + msg.get_command()
1206 0 : + " instead.");
1207 : }
1208 8 : if(msg.has_parameter("version"))
1209 : {
1210 : // there are cases where I put a version as an integer
1211 : //
1212 1 : std::int64_t version(msg.get_integer_parameter("version"));
1213 1 : if(version != 9)
1214 : {
1215 0 : throw std::runtime_error(
1216 : "READY version value invalid; expected 9, got "
1217 0 : + std::to_string(version)
1218 0 : + " instead.");
1219 : }
1220 : }
1221 8 : if(msg.has_parameter("date"))
1222 : {
1223 : // there are cases where I put a date as a timespec_ex (a timestamp in the language)
1224 : //
1225 1 : snapdev::timespec_ex date(msg.get_timespec_parameter("date"));
1226 1 : if(date != snapdev::timespec_ex(1715440881, 543723981))
1227 : {
1228 0 : throw std::runtime_error(
1229 : "READY date value invalid; expected 1715440881.543723981, got "
1230 0 : + date.to_timestamp()
1231 0 : + " instead.");
1232 : }
1233 : }
1234 : }
1235 :
1236 12 : switch(f_sequence)
1237 : {
1238 4 : case sequence_t::SEQUENCE_ONE_MESSAGE:
1239 4 : disconnect_all = true;
1240 4 : break;
1241 :
1242 0 : case sequence_t::SEQUENCE_UNWANTED_MESSAGE:
1243 : {
1244 0 : ed::message unwanted;
1245 0 : unwanted.reply_to(msg);
1246 0 : unwanted.set_command("UNWANTED");
1247 0 : unwanted.add_parameter("serial", 7209);
1248 0 : if(!send_message(unwanted, false))
1249 : {
1250 0 : throw std::runtime_error("could not send UNWANTED message");
1251 : }
1252 0 : }
1253 : break;
1254 :
1255 1 : case sequence_t::SEQUENCE_TIMED_MESSAGE:
1256 : {
1257 1 : ed::message unwanted;
1258 1 : unwanted.reply_to(msg);
1259 1 : unwanted.set_command("TIMED");
1260 1 : unwanted.add_parameter("now", snapdev::now());
1261 1 : if(!send_message(unwanted, false))
1262 : {
1263 0 : throw std::runtime_error("could not send TIMED message");
1264 : }
1265 1 : }
1266 : break;
1267 :
1268 3 : case sequence_t::SEQUENCE_READY_HELP_MESSAGE:
1269 3 : switch(f_step)
1270 : {
1271 1 : case 1:
1272 : // done in this case
1273 1 : break;
1274 :
1275 1 : case 2:
1276 1 : if(msg.get_command() != "HELP")
1277 : {
1278 0 : throw std::runtime_error(
1279 : "second message expected to be HELP, got "
1280 0 : + msg.get_command()
1281 0 : + " instead.");
1282 : }
1283 :
1284 : {
1285 1 : ed::message commands;
1286 1 : commands.reply_to(msg);
1287 1 : commands.set_sent_from_server("reporter_test");
1288 1 : commands.set_sent_from_service("commands_message");
1289 1 : commands.set_command("COMMANDS");
1290 1 : commands.add_parameter("list", "HELP,READY,STOP");
1291 : //std::cerr << "--- respond with COMMANDS\n";
1292 1 : if(!send_message(commands, false))
1293 : {
1294 0 : throw std::runtime_error("could not send COMMANDS message");
1295 : }
1296 1 : }
1297 : break;
1298 :
1299 1 : case 3:
1300 1 : if(msg.get_command() != "STOP")
1301 : {
1302 0 : throw std::runtime_error(
1303 : "third message expected to be STOP, got "
1304 0 : + msg.get_command()
1305 0 : + " instead.");
1306 : }
1307 :
1308 1 : disconnect_all = true;
1309 1 : break;
1310 :
1311 0 : default:
1312 0 : throw std::runtime_error("reached step 4 of SEQUENCE_READY_HELP_MESSAGE?");
1313 :
1314 : }
1315 3 : break;
1316 :
1317 2 : case sequence_t::SEQUENCE_READY_THROW:
1318 2 : switch(f_step)
1319 : {
1320 1 : case 1:
1321 : // done in this case
1322 1 : break;
1323 :
1324 1 : case 2:
1325 1 : if(msg.get_command() != "HELP")
1326 : {
1327 0 : throw std::runtime_error(
1328 : "second message expected to be HELP, got "
1329 0 : + msg.get_command()
1330 0 : + " instead.");
1331 : }
1332 :
1333 : // got the help message, now do a "legitimate" throw
1334 : //
1335 1 : throw std::runtime_error("testing that the executor catches these exceptions.");
1336 :
1337 0 : default:
1338 0 : throw std::runtime_error("reached step 4 of SEQUENCE_READY_THROW?");
1339 :
1340 : }
1341 1 : break;
1342 :
1343 2 : case sequence_t::SEQUENCE_READY_THROW_WHAT:
1344 2 : switch(f_step)
1345 : {
1346 1 : case 1:
1347 : // done in this case
1348 1 : break;
1349 :
1350 1 : case 2:
1351 1 : if(msg.get_command() != "HELP")
1352 : {
1353 0 : throw std::runtime_error(
1354 : "second message expected to be HELP, got "
1355 0 : + msg.get_command()
1356 0 : + " instead.");
1357 : }
1358 :
1359 : // got the help message, now do a "legitimate" throw
1360 : //
1361 : struct my_exception
1362 : {
1363 : int code = 0;
1364 : };
1365 1 : throw my_exception({5});
1366 :
1367 0 : default:
1368 0 : throw std::runtime_error("reached step 4 of SEQUENCE_READY_THROW_WHAT?");
1369 :
1370 : }
1371 1 : break;
1372 :
1373 : }
1374 :
1375 10 : if(disconnect_all)
1376 : {
1377 5 : remove_from_communicator();
1378 :
1379 5 : ed::connection::pointer_t timer_ptr(f_timer.lock());
1380 5 : if(timer_ptr != nullptr)
1381 : {
1382 5 : timer_ptr->remove_from_communicator();
1383 : }
1384 5 : }
1385 10 : }
1386 :
1387 19 : void set_timer(ed::connection::pointer_t done_timer)
1388 : {
1389 19 : f_timer = done_timer;
1390 19 : }
1391 :
1392 : private:
1393 : // the sequence & step define the next action
1394 : //
1395 : sequence_t f_sequence = sequence_t::SEQUENCE_ONE_MESSAGE;
1396 : int f_step = 0;
1397 : ed::connection::weak_pointer_t
1398 : f_timer = ed::connection::weak_pointer_t();
1399 : };
1400 :
1401 :
1402 : class messenger_timer
1403 : : public ed::timer
1404 : {
1405 : public:
1406 : typedef std::shared_ptr<messenger_timer> pointer_t;
1407 :
1408 19 : messenger_timer(messenger_responder::pointer_t m)
1409 19 : : timer(10'000'000)
1410 19 : , f_messenger(m)
1411 : {
1412 19 : set_name("messenger_timer");
1413 19 : }
1414 :
1415 2 : void process_timeout()
1416 : {
1417 : // call default function(s)
1418 : //
1419 2 : timer::process_timeout();
1420 :
1421 2 : remove_from_communicator();
1422 2 : f_messenger->remove_from_communicator();
1423 2 : f_timed_out = true;
1424 2 : }
1425 :
1426 19 : bool timed_out_prima() const
1427 : {
1428 19 : return f_timed_out;
1429 : }
1430 :
1431 : private:
1432 : messenger_responder::pointer_t f_messenger = messenger_responder::pointer_t();
1433 : bool f_timed_out = false;
1434 : };
1435 :
1436 :
1437 :
1438 :
1439 :
1440 :
1441 : } // no name namespace
1442 :
1443 :
1444 :
1445 11 : CATCH_TEST_CASE("reporter_executor", "[executor][reporter]")
1446 : {
1447 11 : CATCH_START_SECTION("verify sleep in a function")
1448 : {
1449 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_sleep_func.rprtr", g_program_sleep_func));
1450 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
1451 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
1452 1 : p->parse_program();
1453 :
1454 1 : CATCH_REQUIRE(s->get_statement_size() == 5);
1455 :
1456 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
1457 1 : snapdev::timespec_ex const start(snapdev::now());
1458 1 : e->start();
1459 1 : CATCH_REQUIRE(e->run());
1460 1 : snapdev::timespec_ex end(snapdev::now());
1461 1 : end -= start;
1462 1 : CATCH_REQUIRE(end.tv_sec >= 2); // we slept for 2.5 seconds, so we expect at least start + 2 seconds
1463 1 : }
1464 11 : CATCH_END_SECTION()
1465 :
1466 11 : CATCH_START_SECTION("verify starting the thread")
1467 : {
1468 1 : trace tracer(g_verify_starting_thread);
1469 :
1470 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_start_thread.rprtr", g_program_start_thread));
1471 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
1472 :
1473 : // use std::bind() to avoid copies of the tracer object
1474 : //
1475 1 : s->set_trace_callback(std::bind(&trace::callback, &tracer, std::placeholders::_1, std::placeholders::_2));
1476 :
1477 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
1478 1 : p->parse_program();
1479 :
1480 1 : CATCH_REQUIRE(s->get_statement_size() == 10);
1481 :
1482 : // before we run the script, there are no such variables
1483 : //
1484 3 : SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var(s->get_variable("test"));
1485 1 : CATCH_REQUIRE(var == nullptr);
1486 1 : var = s->get_variable("test_copy_between_dollars");
1487 1 : CATCH_REQUIRE(var == nullptr);
1488 1 : var = s->get_variable("runner");
1489 1 : CATCH_REQUIRE(var == nullptr);
1490 1 : var = s->get_variable("runner_copy_as_is");
1491 1 : CATCH_REQUIRE(var == nullptr);
1492 1 : var = s->get_variable("time_limit");
1493 1 : CATCH_REQUIRE(var == nullptr);
1494 1 : var = s->get_variable("time_limit_copy");
1495 1 : CATCH_REQUIRE(var == nullptr);
1496 1 : var = s->get_variable("host_ip");
1497 1 : CATCH_REQUIRE(var == nullptr);
1498 1 : var = s->get_variable("host_ip_copy");
1499 1 : CATCH_REQUIRE(var == nullptr);
1500 1 : var = s->get_variable("time_and_host_ip");
1501 1 : CATCH_REQUIRE(var == nullptr);
1502 :
1503 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
1504 1 : e->start();
1505 1 : CATCH_REQUIRE(e->run());
1506 :
1507 1 : var = s->get_variable("test");
1508 1 : CATCH_REQUIRE(var != nullptr);
1509 1 : CATCH_REQUIRE(var->get_name() == "test");
1510 1 : CATCH_REQUIRE(var->get_type() == "integer");
1511 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == 33);
1512 :
1513 1 : var = s->get_variable("test_copy_between_dollars");
1514 1 : CATCH_REQUIRE(var != nullptr);
1515 1 : CATCH_REQUIRE(var->get_name() == "test_copy_between_dollars");
1516 1 : CATCH_REQUIRE(var->get_type() == "string");
1517 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var)->get_string() == "$33$");
1518 :
1519 1 : var = s->get_variable("runner");
1520 1 : CATCH_REQUIRE(var != nullptr);
1521 1 : CATCH_REQUIRE(var->get_name() == "runner");
1522 1 : CATCH_REQUIRE(var->get_type() == "floating_point");
1523 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_floating_point>(var)->get_floating_point() == 6.07);
1524 :
1525 1 : var = s->get_variable("runner_copy_as_is");
1526 1 : CATCH_REQUIRE(var != nullptr);
1527 1 : CATCH_REQUIRE(var->get_name() == "runner_copy_as_is");
1528 1 : CATCH_REQUIRE(var->get_type() == "string");
1529 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var)->get_string() == "runner = 6.07");
1530 :
1531 1 : var = s->get_variable("time_limit");
1532 1 : CATCH_REQUIRE(var != nullptr);
1533 1 : CATCH_REQUIRE(var->get_name() == "time_limit");
1534 1 : CATCH_REQUIRE(var->get_type() == "timestamp");
1535 1 : snapdev::timespec_ex const time_limit(1713934141, 107805991);
1536 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_timestamp>(var)->get_timestamp() == time_limit);
1537 :
1538 1 : var = s->get_variable("time_limit_copy");
1539 1 : CATCH_REQUIRE(var != nullptr);
1540 1 : CATCH_REQUIRE(var->get_name() == "time_limit_copy");
1541 1 : CATCH_REQUIRE(var->get_type() == "string");
1542 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var)->get_string() == "limit: 1713934141.107805991");
1543 :
1544 1 : var = s->get_variable("host_ip");
1545 1 : CATCH_REQUIRE(var != nullptr);
1546 1 : CATCH_REQUIRE(var->get_name() == "host_ip");
1547 1 : CATCH_REQUIRE(var->get_type() == "address");
1548 1 : addr::addr a;
1549 1 : sockaddr_in ip = {
1550 : .sin_family = AF_INET,
1551 1 : .sin_port = htons(0),
1552 : .sin_addr = {
1553 1 : .s_addr = htonl(0x7f070333),
1554 : },
1555 : .sin_zero = {},
1556 1 : };
1557 1 : a.set_ipv4(ip);
1558 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_address>(var)->get_address() == a);
1559 :
1560 1 : var = s->get_variable("host_ip_copy");
1561 1 : CATCH_REQUIRE(var != nullptr);
1562 1 : CATCH_REQUIRE(var->get_name() == "host_ip_copy");
1563 1 : CATCH_REQUIRE(var->get_type() == "string");
1564 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var)->get_string() == "Host is at 127.7.3.51 address");
1565 :
1566 1 : var = s->get_variable("time_and_host_ip");
1567 1 : CATCH_REQUIRE(var != nullptr);
1568 1 : CATCH_REQUIRE(var->get_name() == "time_and_host_ip");
1569 1 : CATCH_REQUIRE(var->get_type() == "string");
1570 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var)->get_string() == "time 1713934141.107805991 and address 127.7.3.51...");
1571 1 : }
1572 11 : CATCH_END_SECTION()
1573 :
1574 11 : CATCH_START_SECTION("verify computation (integers)")
1575 : {
1576 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("verify_computation_integer.rprtr", g_program_verify_computation_integer));
1577 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
1578 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
1579 1 : p->parse_program();
1580 :
1581 1 : CATCH_REQUIRE(s->get_statement_size() == 15);
1582 :
1583 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
1584 1 : e->start();
1585 1 : CATCH_REQUIRE(e->run());
1586 :
1587 1 : SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var;
1588 :
1589 1 : var = s->get_variable("t01");
1590 1 : CATCH_REQUIRE(var != nullptr);
1591 1 : CATCH_REQUIRE(var->get_name() == "t01");
1592 1 : CATCH_REQUIRE(var->get_type() == "integer");
1593 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == 3);
1594 :
1595 1 : var = s->get_variable("t11");
1596 1 : CATCH_REQUIRE(var != nullptr);
1597 1 : CATCH_REQUIRE(var->get_name() == "t11");
1598 1 : CATCH_REQUIRE(var->get_type() == "integer");
1599 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == -3);
1600 :
1601 1 : var = s->get_variable("t12");
1602 1 : CATCH_REQUIRE(var != nullptr);
1603 1 : CATCH_REQUIRE(var->get_name() == "t12");
1604 1 : CATCH_REQUIRE(var->get_type() == "integer");
1605 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == +3);
1606 :
1607 1 : var = s->get_variable("t21");
1608 1 : CATCH_REQUIRE(var != nullptr);
1609 1 : CATCH_REQUIRE(var->get_name() == "t21");
1610 1 : CATCH_REQUIRE(var->get_type() == "integer");
1611 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == 3 + 2);
1612 :
1613 1 : var = s->get_variable("t22");
1614 1 : CATCH_REQUIRE(var != nullptr);
1615 1 : CATCH_REQUIRE(var->get_name() == "t22");
1616 1 : CATCH_REQUIRE(var->get_type() == "integer");
1617 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == -(3 + 2));
1618 :
1619 1 : var = s->get_variable("t23");
1620 1 : CATCH_REQUIRE(var != nullptr);
1621 1 : CATCH_REQUIRE(var->get_name() == "t23");
1622 1 : CATCH_REQUIRE(var->get_type() == "integer");
1623 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == 20 - 4);
1624 :
1625 1 : var = s->get_variable("t24");
1626 1 : CATCH_REQUIRE(var != nullptr);
1627 1 : CATCH_REQUIRE(var->get_name() == "t24");
1628 1 : CATCH_REQUIRE(var->get_type() == "integer");
1629 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == 3 * 2);
1630 :
1631 1 : var = s->get_variable("t25");
1632 1 : CATCH_REQUIRE(var != nullptr);
1633 1 : CATCH_REQUIRE(var->get_name() == "t25");
1634 1 : CATCH_REQUIRE(var->get_type() == "integer");
1635 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == 20 / 4);
1636 :
1637 1 : var = s->get_variable("t26");
1638 1 : CATCH_REQUIRE(var != nullptr);
1639 1 : CATCH_REQUIRE(var->get_name() == "t26");
1640 1 : CATCH_REQUIRE(var->get_type() == "integer");
1641 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == 27 % 11);
1642 :
1643 1 : var = s->get_variable("t31");
1644 1 : CATCH_REQUIRE(var != nullptr);
1645 1 : CATCH_REQUIRE(var->get_name() == "t31");
1646 1 : CATCH_REQUIRE(var->get_type() == "integer");
1647 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == 3 + 2 * 5);
1648 :
1649 1 : var = s->get_variable("t32");
1650 1 : CATCH_REQUIRE(var != nullptr);
1651 1 : CATCH_REQUIRE(var->get_name() == "t32");
1652 1 : CATCH_REQUIRE(var->get_type() == "integer");
1653 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == -7 + 15 / 3);
1654 :
1655 1 : var = s->get_variable("t33");
1656 1 : CATCH_REQUIRE(var != nullptr);
1657 1 : CATCH_REQUIRE(var->get_name() == "t33");
1658 1 : CATCH_REQUIRE(var->get_type() == "integer");
1659 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == +2 + 15 % 7);
1660 :
1661 1 : var = s->get_variable("t41");
1662 1 : CATCH_REQUIRE(var != nullptr);
1663 1 : CATCH_REQUIRE(var->get_name() == "t41");
1664 1 : CATCH_REQUIRE(var->get_type() == "integer");
1665 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == (3 + 2) * 5);
1666 :
1667 1 : var = s->get_variable("t42");
1668 1 : CATCH_REQUIRE(var != nullptr);
1669 1 : CATCH_REQUIRE(var->get_name() == "t42");
1670 1 : CATCH_REQUIRE(var->get_type() == "integer");
1671 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == (-7 + 15) / 3);
1672 :
1673 1 : var = s->get_variable("t43");
1674 1 : CATCH_REQUIRE(var != nullptr);
1675 1 : CATCH_REQUIRE(var->get_name() == "t43");
1676 1 : CATCH_REQUIRE(var->get_type() == "integer");
1677 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == (+2 + 15) % 7);
1678 1 : }
1679 11 : CATCH_END_SECTION()
1680 :
1681 11 : CATCH_START_SECTION("verify computation (floating points)")
1682 : {
1683 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("verify_computation_floating_point.rprtr", g_program_verify_computation_floating_point));
1684 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
1685 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
1686 1 : p->parse_program();
1687 :
1688 1 : CATCH_REQUIRE(s->get_statement_size() == 63);
1689 :
1690 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
1691 1 : e->start();
1692 1 : CATCH_REQUIRE(e->run());
1693 :
1694 : struct verify_t
1695 : {
1696 : char const * f_name = nullptr;
1697 : double f_value = 0.0;
1698 : };
1699 :
1700 1 : verify_t verify[] =
1701 : {
1702 : { "t01", 3.01 },
1703 : { "t11", -3.5 },
1704 : { "t12", +3.2 },
1705 : { "t21ff", 3.01 + 2.45 },
1706 : { "t21if", 3 + 2.54 },
1707 : { "t21fi", 3.01 + 2 },
1708 : { "t22ff", -(3.5 + 2.5) },
1709 : { "t22if", -(3 + 2.11) },
1710 : { "t22fi", -(3.07 + 2) },
1711 : { "t23ff", 20.07 - 4.13 },
1712 : { "t23if", 20 - 4.78 },
1713 : { "t23fi", 20.91 - 4 },
1714 : { "t24ff", 3.41 * 2.14 },
1715 : { "t24if", 3 * 2.67 },
1716 : { "t24fi", 3.32 * 2 },
1717 : { "t25ff", 20.83 / 4.07 },
1718 : { "t25if", 20 / 4.4 },
1719 : { "t25fi", 20.93 / 4 },
1720 1 : { "t26ff", fmod(27.27, 11.11) },
1721 1 : { "t26if", fmod(27, 11.88) },
1722 1 : { "t26fi", fmod(27.72, 11) },
1723 : { "t31fff", 3.03 + 2.2 * 5.9 },
1724 : { "t31iff", 3 + 2.5 * 5.7 },
1725 : { "t31fif", 3.2 + 2 * 5.3 },
1726 : { "t31ffi", 3.07 + 2.28 * 5 },
1727 : { "t31iif", 3 + 2 * 5.67 },
1728 : { "t31ifi", 3 + 2.56 * 5 },
1729 : { "t31fii", 3.33 + 2 * 5 },
1730 : { "t32fff", -7.11 + 15.7 / 3.06 },
1731 : { "t32iff", -7 + 15.25 / 3.31 },
1732 : { "t32fif", -7.78 + 15 / 3.77 },
1733 : { "t32ffi", -7.09 + 15.34 / 3 },
1734 : { "t32iif", -7 + 15 / 3.30 },
1735 : { "t32ifi", -7 + 15.09 / 3 },
1736 : { "t32fii", -7.94 + 15 / 3 },
1737 1 : { "t33fff", +2.21 + fmod(15.16, 7.8) },
1738 1 : { "t33iff", +2 + fmod(15.12, 7.93) },
1739 1 : { "t33fif", +2.58 + fmod(15, 7.63) },
1740 1 : { "t33ffi", +2.12 + fmod(15.09, 7) },
1741 1 : { "t33iif", +2 + fmod(15, 7.19) },
1742 1 : { "t33ifi", +2 + fmod(15.18, 7) },
1743 1 : { "t33fii", +2.17 + fmod(15, 7) },
1744 : { "t41fff", (3.45 + 2.06) * 5.55 },
1745 : { "t41iff", (3 + 2.17) * 5.07 },
1746 : { "t41fif", (3.37 + 2) * 5.12 },
1747 : { "t41ffi", (3.45 + 2.67) * 5 },
1748 : { "t41iif", (3 + 2) * 5.3 },
1749 : { "t41ifi", (3 + 2.9) * 5 },
1750 : { "t41fii", (3.4 + 2) * 5 },
1751 : { "t42fff", (-7.4 + 15.15) / 3.93 },
1752 : { "t42iff", (-7 + 15.21) / 3.43 },
1753 : { "t42fif", (-7.72 + 15) / 3.31 },
1754 : { "t42ffi", (-7.43 + 15.89) / 3 },
1755 : { "t42iif", (-7 + 15) / 3.4 },
1756 : { "t42ifi", (-7 + 15.09) / 3 },
1757 : { "t42fii", (-7.73 + 15) / 3 },
1758 1 : { "t43fff", fmod((+2.25 + 15.36), 7.47) },
1759 1 : { "t43iff", fmod((+2 + 15.16), 7.38) },
1760 1 : { "t43fif", fmod((+2.51 + 15), 7.59) },
1761 1 : { "t43ffi", fmod((+2.4 + 15.3), 7) },
1762 1 : { "t43iif", fmod((+2 + 15), 7.0) },
1763 1 : { "t43ifi", fmod((+2 + 15.8), 7) },
1764 1 : { "t43fii", fmod((+2.07 + 15), 7) },
1765 1 : };
1766 :
1767 1 : SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var;
1768 64 : for(auto const & v : verify)
1769 : {
1770 : //std::cerr << "--- testing \"" << v.f_name << "\".\n";
1771 63 : var = s->get_variable(v.f_name);
1772 63 : CATCH_REQUIRE(var != nullptr);
1773 63 : CATCH_REQUIRE(var->get_name() == v.f_name);
1774 63 : CATCH_REQUIRE(var->get_type() == "floating_point");
1775 63 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_floating_point>(var)->get_floating_point() == v.f_value);
1776 : }
1777 1 : }
1778 11 : CATCH_END_SECTION()
1779 :
1780 11 : CATCH_START_SECTION("verify computation (timestamp)")
1781 : {
1782 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("verify_computation_timestamp.rprtr", g_program_verify_computation_timestamp));
1783 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
1784 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
1785 1 : p->parse_program();
1786 :
1787 1 : CATCH_REQUIRE(s->get_statement_size() == 12);
1788 :
1789 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
1790 1 : e->start();
1791 1 : CATCH_REQUIRE(e->run());
1792 :
1793 : struct verify_t
1794 : {
1795 : char const * f_name = nullptr;
1796 : snapdev::timespec_ex f_value = snapdev::timespec_ex();
1797 : };
1798 :
1799 1 : verify_t verify[] =
1800 : {
1801 : { "t01", { 123 + 5, 0 } },
1802 : { "t02", { 33 + 123, 0 } },
1803 : { "t03", { 123 - 5, 0 } },
1804 : { "t04", { 33 - 123, 0 } },
1805 : { "t11", { 123 + 5, 89'999'999 } },
1806 : { "t12", { 33 + 123, 501'923'820 } },
1807 : { "t13", { 123 - 6, 999'000'000 } },
1808 : { "t14", { 333 - 123, 982'019'920 } },
1809 : { "t21", { -123, 0 } },
1810 : { "t22", { 123, 0 } },
1811 : { "t31", { 177, 330'000'000 } },
1812 : { "t32", { 158, 310'731'200 } },
1813 1 : };
1814 :
1815 1 : SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var;
1816 13 : for(auto const & v : verify)
1817 : {
1818 : //std::cerr << "--- testing \"" << v.f_name << "\".\n";
1819 12 : var = s->get_variable(v.f_name);
1820 12 : CATCH_REQUIRE(var != nullptr);
1821 12 : CATCH_REQUIRE(var->get_name() == v.f_name);
1822 12 : CATCH_REQUIRE(var->get_type() == "timestamp");
1823 12 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_timestamp>(var)->get_timestamp() == v.f_value);
1824 : }
1825 1 : }
1826 11 : CATCH_END_SECTION()
1827 :
1828 11 : CATCH_START_SECTION("verify now")
1829 : {
1830 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("verify_now.rprtr", g_program_verify_now));
1831 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
1832 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
1833 1 : p->parse_program();
1834 :
1835 1 : CATCH_REQUIRE(s->get_statement_size() == 1);
1836 :
1837 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
1838 1 : e->start();
1839 1 : CATCH_REQUIRE(e->run());
1840 :
1841 1 : SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var;
1842 1 : var = s->get_variable("about_now");
1843 1 : CATCH_REQUIRE(var != nullptr);
1844 1 : CATCH_REQUIRE(var->get_name() == "about_now");
1845 1 : CATCH_REQUIRE(var->get_type() == "timestamp");
1846 1 : snapdev::timespec_ex const value(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_timestamp>(var)->get_timestamp());
1847 1 : snapdev::timespec_ex const now(snapdev::now());
1848 1 : snapdev::timespec_ex const lower_value(now - snapdev::timespec_ex(1, 0));
1849 1 : CATCH_REQUIRE(lower_value <= value);
1850 1 : CATCH_REQUIRE(now >= value);
1851 1 : }
1852 11 : CATCH_END_SECTION()
1853 :
1854 11 : CATCH_START_SECTION("verify computation (address)")
1855 : {
1856 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("verify_computation_address.rprtr", g_program_verify_computation_address));
1857 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
1858 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
1859 1 : p->parse_program();
1860 :
1861 1 : CATCH_REQUIRE(s->get_statement_size() == 4);
1862 :
1863 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
1864 1 : e->start();
1865 1 : CATCH_REQUIRE(e->run());
1866 :
1867 : //"set_variable(name: t01, value: <127.0.0.1> + 256)\n"
1868 : //"set_variable(name: t02, value: 256 + <192.168.3.57>)\n"
1869 : //"set_variable(name: t03, value: <172.131.4.1> - 256)\n"
1870 : //"set_variable(name: t11, value: <10.5.34.255> - <10.5.33.0>)\n"
1871 :
1872 1 : SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var;
1873 1 : addr::addr a;
1874 :
1875 1 : var = s->get_variable("t01");
1876 1 : CATCH_REQUIRE(var != nullptr);
1877 1 : CATCH_REQUIRE(var->get_name() == "t01");
1878 1 : CATCH_REQUIRE(var->get_type() == "address");
1879 1 : a = addr::string_to_addr("127.0.1.1");
1880 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_address>(var)->get_address() == a);
1881 :
1882 1 : var = s->get_variable("t02");
1883 1 : CATCH_REQUIRE(var != nullptr);
1884 1 : CATCH_REQUIRE(var->get_name() == "t02");
1885 1 : CATCH_REQUIRE(var->get_type() == "address");
1886 1 : a = addr::string_to_addr("192.168.4.57");
1887 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_address>(var)->get_address() == a);
1888 :
1889 1 : var = s->get_variable("t03");
1890 1 : CATCH_REQUIRE(var != nullptr);
1891 1 : CATCH_REQUIRE(var->get_name() == "t03");
1892 1 : CATCH_REQUIRE(var->get_type() == "address");
1893 1 : a = addr::string_to_addr("172.131.3.1");
1894 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_address>(var)->get_address() == a);
1895 :
1896 1 : var = s->get_variable("t11");
1897 1 : CATCH_REQUIRE(var != nullptr);
1898 1 : CATCH_REQUIRE(var->get_name() == "t11");
1899 1 : CATCH_REQUIRE(var->get_type() == "integer");
1900 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == 511);
1901 1 : }
1902 11 : CATCH_END_SECTION()
1903 :
1904 11 : CATCH_START_SECTION("verify computation (concatenation)")
1905 : {
1906 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("verify_computation_concatenation.rprtr", g_program_verify_computation_concatenation));
1907 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
1908 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
1909 1 : p->parse_program();
1910 :
1911 1 : CATCH_REQUIRE(s->get_statement_size() == 12);
1912 :
1913 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
1914 1 : e->start();
1915 1 : CATCH_REQUIRE(e->run());
1916 :
1917 : struct verify_t
1918 : {
1919 : char const * f_name = nullptr;
1920 : char const * f_value = nullptr;
1921 : char const * f_type = nullptr;
1922 : };
1923 :
1924 1 : verify_t verify[] =
1925 : {
1926 : { "t01", "identifier", "identifier" },
1927 : { "t11", "single string", "string" },
1928 : { "t12", "single string", "string" },
1929 : { "t13", "single string", "string" },
1930 : { "t14", "double string", "string" },
1931 : { "t21", "identify", "identifier" },
1932 : { "t22", "single string", "string" },
1933 : { "t23", "double string", "string" },
1934 : { "t31", "single36", "string" },
1935 : { "t32", "258single", "string" },
1936 : { "t33", "string102", "string" },
1937 : { "t34", "5005double", "string" },
1938 : };
1939 :
1940 1 : SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var;
1941 13 : for(auto const & v : verify)
1942 : {
1943 : //std::cerr << "--- testing \"" << v.f_name << "\".\n";
1944 12 : var = s->get_variable(v.f_name);
1945 12 : CATCH_REQUIRE(var != nullptr);
1946 12 : CATCH_REQUIRE(var->get_name() == v.f_name);
1947 12 : CATCH_REQUIRE(var->get_type() == v.f_type);
1948 12 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var)->get_string() == v.f_value);
1949 : }
1950 1 : }
1951 11 : CATCH_END_SECTION()
1952 :
1953 11 : CATCH_START_SECTION("verify computation (string repeat)")
1954 : {
1955 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("verify_computation_string_repeat.rprtr", g_program_verify_computation_string_repeat));
1956 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
1957 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
1958 1 : p->parse_program();
1959 :
1960 1 : CATCH_REQUIRE(s->get_statement_size() == 4);
1961 :
1962 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
1963 1 : e->start();
1964 1 : CATCH_REQUIRE(e->run());
1965 :
1966 : struct verify_t
1967 : {
1968 : char const * f_name = nullptr;
1969 : char const * f_value = nullptr;
1970 : };
1971 :
1972 1 : verify_t verify[] =
1973 : {
1974 : { "t01", "abcabcabc" },
1975 : { "t02", "xyzxyzxyzxyzxyz" },
1976 : { "t03", "" },
1977 : { "t04", "one" },
1978 : };
1979 :
1980 1 : SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var;
1981 5 : for(auto const & v : verify)
1982 : {
1983 : //std::cerr << "--- testing \"" << v.f_name << "\".\n";
1984 4 : var = s->get_variable(v.f_name);
1985 4 : CATCH_REQUIRE(var != nullptr);
1986 4 : CATCH_REQUIRE(var->get_name() == v.f_name);
1987 4 : CATCH_REQUIRE(var->get_type() == "string");
1988 4 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var)->get_string() == v.f_value);
1989 : }
1990 1 : }
1991 11 : CATCH_END_SECTION()
1992 :
1993 11 : CATCH_START_SECTION("verify variable in string")
1994 : {
1995 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("verify_variable_in_string.rprtr", g_program_verify_variable_in_string));
1996 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
1997 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
1998 1 : p->parse_program();
1999 :
2000 1 : CATCH_REQUIRE(s->get_statement_size() == 2);
2001 :
2002 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
2003 1 : e->start();
2004 1 : CATCH_REQUIRE(e->run());
2005 :
2006 : struct verify_t
2007 : {
2008 : char const * f_name = nullptr;
2009 : char const * f_value = nullptr;
2010 : };
2011 :
2012 1 : verify_t verify[] =
2013 : {
2014 : { "foo", "abc" },
2015 : { "bar", "[abc]" },
2016 : };
2017 :
2018 1 : SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var;
2019 3 : for(auto const & v : verify)
2020 : {
2021 : //std::cerr << "--- testing \"" << v.f_name << "\".\n";
2022 2 : var = s->get_variable(v.f_name);
2023 2 : CATCH_REQUIRE(var != nullptr);
2024 2 : CATCH_REQUIRE(var->get_name() == v.f_name);
2025 2 : CATCH_REQUIRE(var->get_type() == "string");
2026 2 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var)->get_string() == v.f_value);
2027 : }
2028 1 : }
2029 11 : CATCH_END_SECTION()
2030 :
2031 11 : CATCH_START_SECTION("print() + message")
2032 : {
2033 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("print_message.rprtr.rprtr", g_program_print_message));
2034 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
2035 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
2036 1 : p->parse_program();
2037 :
2038 1 : CATCH_REQUIRE(s->get_statement_size() == 2);
2039 :
2040 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
2041 1 : e->start();
2042 :
2043 1 : CATCH_REQUIRE(s->get_exit_code() == 0);
2044 1 : }
2045 11 : CATCH_END_SECTION()
2046 11 : }
2047 :
2048 :
2049 9 : CATCH_TEST_CASE("reporter_executor_message", "[executor][reporter]")
2050 : {
2051 9 : CATCH_START_SECTION("send/receive one message")
2052 : {
2053 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_accept_one_message.rprtr", g_program_accept_one_message));
2054 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
2055 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
2056 1 : p->parse_program();
2057 :
2058 1 : CATCH_REQUIRE(s->get_statement_size() == 15);
2059 :
2060 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
2061 1 : e->start();
2062 1 : addr::addr a;
2063 1 : sockaddr_in ip = {
2064 : .sin_family = AF_INET,
2065 1 : .sin_port = htons(20002),
2066 : .sin_addr = {
2067 1 : .s_addr = htonl(0x7f000001),
2068 : },
2069 : .sin_zero = {},
2070 1 : };
2071 1 : a.set_ipv4(ip);
2072 1 : messenger_responder::pointer_t messenger(std::make_shared<messenger_responder>(
2073 : a
2074 1 : , ed::mode_t::MODE_PLAIN
2075 2 : , messenger_responder::sequence_t::SEQUENCE_ONE_MESSAGE));
2076 1 : ed::communicator::instance()->add_connection(messenger);
2077 1 : messenger_timer::pointer_t timer(std::make_shared<messenger_timer>(messenger));
2078 1 : ed::communicator::instance()->add_connection(timer);
2079 1 : messenger->set_timer(timer);
2080 :
2081 1 : CATCH_REQUIRE(e->run());
2082 :
2083 : // if we exited because of our timer, then the test did not pass
2084 : //
2085 1 : CATCH_REQUIRE_FALSE(timer->timed_out_prima());
2086 :
2087 1 : CATCH_REQUIRE(s->get_exit_code() == 0);
2088 :
2089 3 : SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var(s->get_variable("register_version"));
2090 1 : CATCH_REQUIRE(var != nullptr);
2091 1 : SNAP_CATCH2_NAMESPACE::reporter::variable_string::pointer_t v(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var));
2092 1 : CATCH_REQUIRE(v != nullptr);
2093 1 : CATCH_REQUIRE(v->get_string() == "1");
2094 :
2095 1 : var = s->get_variable("register_service");
2096 1 : CATCH_REQUIRE(var != nullptr);
2097 1 : v = std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var);
2098 1 : CATCH_REQUIRE(v != nullptr);
2099 1 : CATCH_REQUIRE(v->get_string() == "responder");
2100 1 : }
2101 9 : CATCH_END_SECTION()
2102 :
2103 9 : CATCH_START_SECTION("receive one unwanted/unexpected message")
2104 : {
2105 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_receive_unwanted_message.rprtr", g_program_receive_unwanted_message));
2106 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
2107 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
2108 1 : p->parse_program();
2109 :
2110 1 : CATCH_REQUIRE(s->get_statement_size() == 13);
2111 :
2112 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
2113 1 : e->start();
2114 1 : addr::addr a;
2115 1 : sockaddr_in ip = {
2116 : .sin_family = AF_INET,
2117 1 : .sin_port = htons(20002),
2118 : .sin_addr = {
2119 1 : .s_addr = htonl(0x7f000001),
2120 : },
2121 : .sin_zero = {},
2122 1 : };
2123 1 : a.set_ipv4(ip);
2124 1 : messenger_responder::pointer_t messenger(std::make_shared<messenger_responder>(
2125 : a
2126 1 : , ed::mode_t::MODE_PLAIN
2127 2 : , messenger_responder::sequence_t::SEQUENCE_UNWANTED_MESSAGE));
2128 1 : ed::communicator::instance()->add_connection(messenger);
2129 1 : e->set_thread_done_callback([messenger]()
2130 : {
2131 1 : ed::communicator::instance()->remove_connection(messenger);
2132 1 : });
2133 :
2134 1 : CATCH_REQUIRE(e->run());
2135 :
2136 1 : CATCH_REQUIRE(s->get_exit_code() == 1);
2137 1 : }
2138 9 : CATCH_END_SECTION()
2139 :
2140 9 : CATCH_START_SECTION("send message with unsupported parameter type fails")
2141 : {
2142 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_send_unsupported_message_parameter_type.rprtr", g_program_send_unsupported_message_parameter_type));
2143 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
2144 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
2145 1 : p->parse_program();
2146 :
2147 1 : CATCH_REQUIRE(s->get_statement_size() == 12);
2148 :
2149 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
2150 1 : e->start();
2151 1 : addr::addr a;
2152 1 : sockaddr_in ip = {
2153 : .sin_family = AF_INET,
2154 1 : .sin_port = htons(20002),
2155 : .sin_addr = {
2156 1 : .s_addr = htonl(0x7f000001),
2157 : },
2158 : .sin_zero = {},
2159 1 : };
2160 1 : a.set_ipv4(ip);
2161 1 : messenger_responder::pointer_t messenger(std::make_shared<messenger_responder>(
2162 : a
2163 1 : , ed::mode_t::MODE_PLAIN
2164 2 : , messenger_responder::sequence_t::SEQUENCE_UNWANTED_MESSAGE));
2165 1 : ed::communicator::instance()->add_connection(messenger);
2166 1 : e->set_thread_done_callback([messenger]()
2167 : {
2168 1 : ed::communicator::instance()->remove_connection(messenger);
2169 1 : });
2170 :
2171 1 : CATCH_REQUIRE(e->run());
2172 1 : CATCH_REQUIRE_THROWS_MATCHES(
2173 : e->stop()
2174 : , std::runtime_error
2175 : , Catch::Matchers::ExceptionMessage(
2176 : "message parameter type \"floating_point\" not supported yet."));
2177 :
2178 1 : CATCH_REQUIRE(s->get_exit_code() == -1);
2179 1 : }
2180 9 : CATCH_END_SECTION()
2181 :
2182 9 : CATCH_START_SECTION("save message parameter identifier as an integer fails")
2183 : {
2184 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_send_invalid_parameter_value_type.rprtr", g_program_send_invalid_parameter_value_type));
2185 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
2186 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
2187 1 : p->parse_program();
2188 :
2189 1 : CATCH_REQUIRE(s->get_statement_size() == 12);
2190 :
2191 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
2192 1 : e->start();
2193 1 : addr::addr a;
2194 1 : sockaddr_in ip = {
2195 : .sin_family = AF_INET,
2196 1 : .sin_port = htons(20002),
2197 : .sin_addr = {
2198 1 : .s_addr = htonl(0x7f000001),
2199 : },
2200 : .sin_zero = {},
2201 1 : };
2202 1 : a.set_ipv4(ip);
2203 1 : messenger_responder::pointer_t messenger(std::make_shared<messenger_responder>(
2204 : a
2205 1 : , ed::mode_t::MODE_PLAIN
2206 2 : , messenger_responder::sequence_t::SEQUENCE_UNWANTED_MESSAGE));
2207 1 : ed::communicator::instance()->add_connection(messenger);
2208 1 : e->set_thread_done_callback([messenger]()
2209 : {
2210 1 : ed::communicator::instance()->remove_connection(messenger);
2211 1 : });
2212 :
2213 1 : CATCH_REQUIRE(e->run());
2214 1 : CATCH_REQUIRE_THROWS_MATCHES(
2215 : e->stop()
2216 : , std::runtime_error
2217 : , Catch::Matchers::ExceptionMessage(
2218 : "value \"responder\" not recognized as a valid integer."));
2219 :
2220 1 : CATCH_REQUIRE(s->get_exit_code() == -1);
2221 1 : }
2222 9 : CATCH_END_SECTION()
2223 :
2224 9 : CATCH_START_SECTION("save message parameter of type timestamp")
2225 : {
2226 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_save_parameter_of_type_timestamp.rprtr", g_program_save_parameter_of_type_timestamp));
2227 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
2228 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
2229 1 : p->parse_program();
2230 :
2231 : //CATCH_REQUIRE(s->get_statement_size() == 19);
2232 :
2233 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
2234 1 : e->start();
2235 1 : addr::addr a;
2236 1 : sockaddr_in ip = {
2237 : .sin_family = AF_INET,
2238 1 : .sin_port = htons(20002),
2239 : .sin_addr = {
2240 1 : .s_addr = htonl(0x7f000001),
2241 : },
2242 : .sin_zero = {},
2243 1 : };
2244 1 : a.set_ipv4(ip);
2245 1 : messenger_responder::pointer_t messenger(std::make_shared<messenger_responder>(
2246 : a
2247 1 : , ed::mode_t::MODE_PLAIN
2248 2 : , messenger_responder::sequence_t::SEQUENCE_TIMED_MESSAGE));
2249 1 : ed::communicator::instance()->add_connection(messenger);
2250 1 : e->set_thread_done_callback([messenger]()
2251 : {
2252 1 : ed::communicator::instance()->remove_connection(messenger);
2253 1 : });
2254 :
2255 1 : CATCH_REQUIRE(e->run());
2256 1 : e->stop();
2257 :
2258 1 : CATCH_REQUIRE(s->get_exit_code() == 0);
2259 :
2260 3 : SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var(s->get_variable("register_version"));
2261 1 : CATCH_REQUIRE(var != nullptr);
2262 1 : SNAP_CATCH2_NAMESPACE::reporter::variable_integer::pointer_t vi(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var));
2263 1 : CATCH_REQUIRE(vi != nullptr);
2264 1 : CATCH_REQUIRE(vi->get_type() == "integer");
2265 1 : CATCH_REQUIRE(vi->get_integer() == 1);
2266 :
2267 1 : var = s->get_variable("default_integer");
2268 1 : CATCH_REQUIRE(var != nullptr);
2269 1 : vi = std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var);
2270 1 : CATCH_REQUIRE(vi != nullptr);
2271 1 : CATCH_REQUIRE(vi->get_type() == "integer");
2272 1 : CATCH_REQUIRE(vi->get_integer() == 0);
2273 :
2274 1 : var = s->get_variable("timed_value");
2275 1 : CATCH_REQUIRE(var != nullptr);
2276 1 : SNAP_CATCH2_NAMESPACE::reporter::variable_timestamp::pointer_t vts(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_timestamp>(var));
2277 1 : CATCH_REQUIRE(vts != nullptr);
2278 1 : CATCH_REQUIRE(vts->get_type() == "timestamp");
2279 1 : snapdev::timespec_ex const param_timestamp(vts->get_timestamp());
2280 1 : snapdev::timespec_ex const now(snapdev::now());
2281 1 : snapdev::timespec_ex const minimum_value(now - snapdev::timespec_ex(1, 0));
2282 1 : CATCH_REQUIRE(param_timestamp >= minimum_value);
2283 1 : CATCH_REQUIRE(param_timestamp <= now);
2284 :
2285 1 : var = s->get_variable("default_time");
2286 1 : CATCH_REQUIRE(var != nullptr);
2287 1 : vts = std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_timestamp>(var);
2288 1 : CATCH_REQUIRE(vts != nullptr);
2289 1 : CATCH_REQUIRE(vts->get_type() == "timestamp");
2290 1 : CATCH_REQUIRE(vts->get_timestamp() == snapdev::timespec_ex());
2291 1 : }
2292 9 : CATCH_END_SECTION()
2293 :
2294 9 : CATCH_START_SECTION("save message parameter with unknown type")
2295 : {
2296 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_save_parameter_with_unknown_type.rprtr", g_program_save_parameter_with_unknown_type));
2297 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
2298 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
2299 1 : p->parse_program();
2300 :
2301 1 : CATCH_REQUIRE(s->get_statement_size() == 12);
2302 :
2303 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
2304 1 : e->start();
2305 1 : addr::addr a;
2306 1 : sockaddr_in ip = {
2307 : .sin_family = AF_INET,
2308 1 : .sin_port = htons(20002),
2309 : .sin_addr = {
2310 1 : .s_addr = htonl(0x7f000001),
2311 : },
2312 : .sin_zero = {},
2313 1 : };
2314 1 : a.set_ipv4(ip);
2315 1 : messenger_responder::pointer_t messenger(std::make_shared<messenger_responder>(
2316 : a
2317 1 : , ed::mode_t::MODE_PLAIN
2318 2 : , messenger_responder::sequence_t::SEQUENCE_UNWANTED_MESSAGE));
2319 1 : ed::communicator::instance()->add_connection(messenger);
2320 1 : e->set_thread_done_callback([messenger]()
2321 : {
2322 1 : ed::communicator::instance()->remove_connection(messenger);
2323 1 : });
2324 :
2325 1 : CATCH_REQUIRE(e->run());
2326 1 : CATCH_REQUIRE_THROWS_MATCHES(
2327 : e->stop()
2328 : , std::runtime_error
2329 : , Catch::Matchers::ExceptionMessage(
2330 : "unsupported type \"void\" for save_parameter_value()."));
2331 :
2332 1 : CATCH_REQUIRE(s->get_exit_code() == -1);
2333 1 : }
2334 9 : CATCH_END_SECTION()
2335 :
2336 9 : CATCH_START_SECTION("send & receive complete messages")
2337 : {
2338 : // in this case, load the program from a file
2339 : // to verify that this works as expected
2340 : //
2341 1 : std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
2342 1 : std::string const filename(source_dir + "/tests/rprtr/send_and_receive_complete_messages");
2343 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
2344 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
2345 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
2346 1 : p->parse_program();
2347 :
2348 1 : CATCH_REQUIRE(s->get_statement_size() == 30);
2349 :
2350 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
2351 1 : e->start();
2352 1 : addr::addr a;
2353 1 : sockaddr_in ip = {
2354 : .sin_family = AF_INET,
2355 1 : .sin_port = htons(20002),
2356 : .sin_addr = {
2357 1 : .s_addr = htonl(0x7f000001),
2358 : },
2359 : .sin_zero = {},
2360 1 : };
2361 1 : a.set_ipv4(ip);
2362 1 : messenger_responder::pointer_t messenger(std::make_shared<messenger_responder>(
2363 : a
2364 1 : , ed::mode_t::MODE_PLAIN
2365 2 : , messenger_responder::sequence_t::SEQUENCE_READY_HELP_MESSAGE));
2366 1 : ed::communicator::instance()->add_connection(messenger);
2367 1 : messenger_timer::pointer_t timer(std::make_shared<messenger_timer>(messenger));
2368 1 : ed::communicator::instance()->add_connection(timer);
2369 1 : messenger->set_timer(timer);
2370 :
2371 1 : CATCH_REQUIRE(e->run());
2372 :
2373 : // if we exited because of our timer, then the test did not pass
2374 : //
2375 1 : CATCH_REQUIRE_FALSE(timer->timed_out_prima());
2376 :
2377 1 : CATCH_REQUIRE(s->get_exit_code() == 0);
2378 :
2379 : // we unset that variable, make sure that worked
2380 : //
2381 3 : SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var(s->get_variable("got_register"));
2382 1 : CATCH_REQUIRE(var == nullptr);
2383 1 : }
2384 9 : CATCH_END_SECTION()
2385 :
2386 9 : CATCH_START_SECTION("verify last wait (disconnect -> HUP)")
2387 : {
2388 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_verify_last_wait.rprtr", g_program_last_wait));
2389 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
2390 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
2391 1 : p->parse_program();
2392 :
2393 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
2394 1 : e->start();
2395 1 : addr::addr a;
2396 1 : sockaddr_in ip = {
2397 : .sin_family = AF_INET,
2398 1 : .sin_port = htons(20002),
2399 : .sin_addr = {
2400 1 : .s_addr = htonl(0x7f000001),
2401 : },
2402 : .sin_zero = {},
2403 1 : };
2404 1 : a.set_ipv4(ip);
2405 1 : messenger_responder::pointer_t messenger(std::make_shared<messenger_responder>(
2406 : a
2407 1 : , ed::mode_t::MODE_PLAIN
2408 2 : , messenger_responder::sequence_t::SEQUENCE_ONE_MESSAGE));
2409 1 : ed::communicator::instance()->add_connection(messenger);
2410 1 : messenger_timer::pointer_t timer(std::make_shared<messenger_timer>(messenger));
2411 1 : ed::communicator::instance()->add_connection(timer);
2412 1 : messenger->set_timer(timer);
2413 1 : e->set_thread_done_callback([messenger, timer]()
2414 : {
2415 1 : ed::communicator::instance()->remove_connection(messenger);
2416 1 : ed::communicator::instance()->remove_connection(timer);
2417 1 : });
2418 1 : CATCH_REQUIRE(e->run());
2419 1 : e->stop();
2420 :
2421 : // if we exited because of our timer, then the test did not pass
2422 : //
2423 1 : CATCH_REQUIRE_FALSE(timer->timed_out_prima());
2424 :
2425 1 : CATCH_REQUIRE(s->get_exit_code() == 0);
2426 1 : }
2427 9 : CATCH_END_SECTION()
2428 :
2429 9 : CATCH_START_SECTION("wait for timeout (to make sure we DO NOT receive extra messages)")
2430 : {
2431 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_wait_for_timeout.rprtr", g_program_wait_for_timeout));
2432 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
2433 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
2434 1 : p->parse_program();
2435 :
2436 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
2437 1 : e->start();
2438 1 : addr::addr a;
2439 1 : sockaddr_in ip = {
2440 : .sin_family = AF_INET,
2441 1 : .sin_port = htons(20002),
2442 : .sin_addr = {
2443 1 : .s_addr = htonl(0x7f000001),
2444 : },
2445 : .sin_zero = {},
2446 1 : };
2447 1 : a.set_ipv4(ip);
2448 1 : messenger_responder::pointer_t messenger(std::make_shared<messenger_responder>(
2449 : a
2450 1 : , ed::mode_t::MODE_PLAIN
2451 2 : , messenger_responder::sequence_t::SEQUENCE_ONE_MESSAGE));
2452 1 : ed::communicator::instance()->add_connection(messenger);
2453 1 : messenger_timer::pointer_t timer(std::make_shared<messenger_timer>(messenger));
2454 1 : ed::communicator::instance()->add_connection(timer);
2455 1 : messenger->set_timer(timer);
2456 1 : e->set_thread_done_callback([messenger, timer]()
2457 : {
2458 1 : ed::communicator::instance()->remove_connection(messenger);
2459 1 : ed::communicator::instance()->remove_connection(timer);
2460 1 : });
2461 1 : CATCH_REQUIRE(e->run());
2462 1 : e->stop();
2463 :
2464 1 : CATCH_REQUIRE_FALSE(timer->timed_out_prima());
2465 1 : CATCH_REQUIRE(s->get_exit_code() == 0);
2466 1 : }
2467 9 : CATCH_END_SECTION()
2468 9 : }
2469 :
2470 :
2471 8 : CATCH_TEST_CASE("reporter_executor_variables", "[executor][reporter][variable]")
2472 : {
2473 8 : CATCH_START_SECTION("undefined variable")
2474 : {
2475 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_undefined_variable.rprtr", g_program_undefined_variable));
2476 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
2477 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
2478 1 : p->parse_program();
2479 :
2480 1 : CATCH_REQUIRE(s->get_statement_size() == 5);
2481 :
2482 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
2483 1 : e->start();
2484 1 : CATCH_REQUIRE(e->run());
2485 :
2486 1 : CATCH_REQUIRE(s->get_exit_code() == 0);
2487 1 : }
2488 8 : CATCH_END_SECTION()
2489 :
2490 8 : CATCH_START_SECTION("detect integer variable")
2491 : {
2492 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_integer_variable.rprtr", g_program_integer_variable));
2493 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
2494 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
2495 1 : p->parse_program();
2496 :
2497 1 : CATCH_REQUIRE(s->get_statement_size() == 10);
2498 :
2499 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
2500 1 : e->start();
2501 1 : CATCH_REQUIRE(e->run());
2502 :
2503 1 : CATCH_REQUIRE(s->get_exit_code() == 0);
2504 1 : }
2505 8 : CATCH_END_SECTION()
2506 :
2507 8 : CATCH_START_SECTION("detect string variable")
2508 : {
2509 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_string_variable.rprtr", g_program_string_variable));
2510 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
2511 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
2512 1 : p->parse_program();
2513 :
2514 1 : CATCH_REQUIRE(s->get_statement_size() == 10);
2515 :
2516 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
2517 1 : e->start();
2518 1 : CATCH_REQUIRE(e->run());
2519 :
2520 1 : CATCH_REQUIRE(s->get_exit_code() == 0);
2521 1 : }
2522 8 : CATCH_END_SECTION()
2523 :
2524 8 : CATCH_START_SECTION("if variable")
2525 : {
2526 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_if_variable.rprtr", g_program_if_variable));
2527 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
2528 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
2529 1 : p->parse_program();
2530 :
2531 1 : CATCH_REQUIRE(s->get_statement_size() == 104);
2532 :
2533 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
2534 1 : e->start();
2535 1 : CATCH_REQUIRE(e->run());
2536 :
2537 1 : CATCH_REQUIRE(s->get_exit_code() == 0);
2538 1 : }
2539 8 : CATCH_END_SECTION()
2540 :
2541 8 : CATCH_START_SECTION("void variable cloning")
2542 : {
2543 : // Note: at the moment there is no call to the clone() function
2544 : // inside the library, so make sure it works as expected
2545 : // within the test
2546 : //
2547 2 : SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::variable_void>("void_var"));
2548 1 : CATCH_REQUIRE(var != nullptr);
2549 :
2550 1 : SNAP_CATCH2_NAMESPACE::reporter::variable_void::pointer_t v(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_void>(var));
2551 1 : CATCH_REQUIRE(v != nullptr);
2552 :
2553 3 : SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t clone(v->clone("clone"));
2554 1 : CATCH_REQUIRE(clone != nullptr);
2555 :
2556 1 : SNAP_CATCH2_NAMESPACE::reporter::variable_void::pointer_t c(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_void>(clone));
2557 1 : CATCH_REQUIRE(c != nullptr);
2558 :
2559 3 : SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t clone2(var->clone("clone2"));
2560 1 : CATCH_REQUIRE(clone2 != nullptr);
2561 :
2562 1 : SNAP_CATCH2_NAMESPACE::reporter::variable_void::pointer_t c2(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_void>(clone2));
2563 1 : CATCH_REQUIRE(c2 != nullptr);
2564 1 : }
2565 8 : CATCH_END_SECTION()
2566 :
2567 8 : CATCH_START_SECTION("list variable")
2568 : {
2569 : // Note: some of the list variable functions are not fully tested
2570 : // from within the app. so test more here
2571 : //
2572 2 : SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t list(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::variable_list>("list_var"));
2573 1 : CATCH_REQUIRE(list != nullptr);
2574 :
2575 1 : SNAP_CATCH2_NAMESPACE::reporter::variable_list::pointer_t l(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_list>(list));
2576 1 : CATCH_REQUIRE(l != nullptr);
2577 :
2578 1 : CATCH_REQUIRE(l->get_item_size() == 0);
2579 :
2580 2 : SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var1(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::variable_void>("void_var"));
2581 1 : CATCH_REQUIRE(var1 != nullptr);
2582 1 : l->add_item(var1);
2583 1 : CATCH_REQUIRE(l->get_item(0) == var1);
2584 1 : CATCH_REQUIRE(l->get_item(-1) == nullptr);
2585 1 : CATCH_REQUIRE(l->get_item(1) == nullptr);
2586 :
2587 2 : SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var2(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>("integer_var"));
2588 1 : CATCH_REQUIRE(var2 != nullptr);
2589 1 : l->add_item(var2);
2590 1 : CATCH_REQUIRE(l->get_item(0) == var2); // this is a map so the order is sorted by variable name
2591 1 : CATCH_REQUIRE(l->get_item(-1) == nullptr);
2592 1 : CATCH_REQUIRE(l->get_item(1) == var1);
2593 1 : CATCH_REQUIRE(l->get_item(2) == nullptr);
2594 1 : CATCH_REQUIRE(l->get_item("void_var") == var1);
2595 1 : CATCH_REQUIRE(l->get_item("integer_var") == var2);
2596 1 : CATCH_REQUIRE(l->get_item("undefined_var") == nullptr);
2597 :
2598 3 : CATCH_REQUIRE_THROWS_MATCHES(
2599 : l->add_item(var1)
2600 : , std::runtime_error
2601 : , Catch::Matchers::ExceptionMessage("variable_list::add_item() trying to re-add item named \"void_var\"."));
2602 :
2603 3 : CATCH_REQUIRE_THROWS_MATCHES(
2604 : l->add_item(var2)
2605 : , std::runtime_error
2606 : , Catch::Matchers::ExceptionMessage("variable_list::add_item() trying to re-add item named \"integer_var\"."));
2607 :
2608 3 : SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t clone(list->clone("clone"));
2609 1 : CATCH_REQUIRE(clone != nullptr);
2610 1 : SNAP_CATCH2_NAMESPACE::reporter::variable_list::pointer_t l2(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_list>(clone));
2611 1 : CATCH_REQUIRE(l2 != nullptr);
2612 :
2613 1 : CATCH_REQUIRE(l2->get_item(-1) == nullptr);
2614 1 : CATCH_REQUIRE(l2->get_item(2) == nullptr);
2615 :
2616 : // the items are also cloned so we can quickly test that they are not
2617 : // equal and then we can verify the type or the name
2618 : //
2619 1 : CATCH_REQUIRE(l2->get_item(0) != var1);
2620 1 : CATCH_REQUIRE(l2->get_item(1) != var1);
2621 1 : CATCH_REQUIRE(l2->get_item(0) != var2);
2622 1 : CATCH_REQUIRE(l2->get_item(1) != var2);
2623 :
2624 1 : CATCH_REQUIRE(l2->get_item(0)->get_type() == "integer");
2625 1 : CATCH_REQUIRE(l2->get_item(1)->get_type() == "void");
2626 :
2627 : // make sure original is still valid
2628 : //
2629 1 : CATCH_REQUIRE(l->get_item(0) == var2);
2630 1 : CATCH_REQUIRE(l->get_item(-1) == nullptr);
2631 1 : CATCH_REQUIRE(l->get_item(1) == var1);
2632 1 : CATCH_REQUIRE(l->get_item(2) == nullptr);
2633 1 : }
2634 8 : CATCH_END_SECTION()
2635 :
2636 8 : CATCH_START_SECTION("primary variable references")
2637 : {
2638 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("primary_variable_references.rprtr", g_program_primary_variable_references));
2639 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
2640 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
2641 1 : p->parse_program();
2642 :
2643 1 : CATCH_REQUIRE(s->get_statement_size() == 14);
2644 :
2645 3 : SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var(s->get_variable("my_string_var"));
2646 1 : CATCH_REQUIRE(var == nullptr);
2647 1 : var = s->get_variable("longer_string_var");
2648 1 : CATCH_REQUIRE(var == nullptr);
2649 1 : var = s->get_variable("my_integer_var");
2650 1 : CATCH_REQUIRE(var == nullptr);
2651 1 : var = s->get_variable("longer_integer_var");
2652 1 : CATCH_REQUIRE(var == nullptr);
2653 1 : var = s->get_variable("my_floating_point_var");
2654 1 : CATCH_REQUIRE(var == nullptr);
2655 1 : var = s->get_variable("longer_floating_point_var");
2656 1 : CATCH_REQUIRE(var == nullptr);
2657 1 : var = s->get_variable("my_identifier_var");
2658 1 : CATCH_REQUIRE(var == nullptr);
2659 1 : var = s->get_variable("longer_identifier_var");
2660 1 : CATCH_REQUIRE(var == nullptr);
2661 1 : var = s->get_variable("my_regex_var");
2662 1 : CATCH_REQUIRE(var == nullptr);
2663 1 : var = s->get_variable("longer_regex_var");
2664 1 : CATCH_REQUIRE(var == nullptr);
2665 1 : var = s->get_variable("my_address_var");
2666 1 : CATCH_REQUIRE(var == nullptr);
2667 1 : var = s->get_variable("longer_address_var");
2668 1 : CATCH_REQUIRE(var == nullptr);
2669 1 : var = s->get_variable("my_timestamp_var");
2670 1 : CATCH_REQUIRE(var == nullptr);
2671 1 : var = s->get_variable("longer_timestamp_var");
2672 1 : CATCH_REQUIRE(var == nullptr);
2673 :
2674 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
2675 1 : e->start();
2676 1 : CATCH_REQUIRE(e->run());
2677 :
2678 1 : var = s->get_variable("my_string_var");
2679 1 : CATCH_REQUIRE(var != nullptr);
2680 1 : SNAP_CATCH2_NAMESPACE::reporter::variable_string::pointer_t vs(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var));
2681 1 : CATCH_REQUIRE(vs != nullptr);
2682 1 : CATCH_REQUIRE(vs->get_type() == "string");
2683 1 : CATCH_REQUIRE(vs->get_string() == "foo");
2684 :
2685 1 : var = s->get_variable("longer_string_var");
2686 1 : CATCH_REQUIRE(var != nullptr);
2687 1 : vs = std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var);
2688 1 : CATCH_REQUIRE(vs != nullptr);
2689 1 : CATCH_REQUIRE(vs->get_type() == "string");
2690 1 : CATCH_REQUIRE(vs->get_string() == "foo");
2691 :
2692 1 : var = s->get_variable("my_integer_var");
2693 1 : CATCH_REQUIRE(var != nullptr);
2694 1 : SNAP_CATCH2_NAMESPACE::reporter::variable_integer::pointer_t vi(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var));
2695 1 : CATCH_REQUIRE(vi != nullptr);
2696 1 : CATCH_REQUIRE(vi->get_type() == "integer");
2697 1 : CATCH_REQUIRE(vi->get_integer() == 41);
2698 :
2699 1 : var = s->get_variable("longer_integer_var");
2700 1 : CATCH_REQUIRE(var != nullptr);
2701 1 : vi = std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var);
2702 1 : CATCH_REQUIRE(vi != nullptr);
2703 1 : CATCH_REQUIRE(vi->get_type() == "integer");
2704 1 : CATCH_REQUIRE(vi->get_integer() == 41);
2705 :
2706 1 : var = s->get_variable("my_floating_point_var");
2707 1 : CATCH_REQUIRE(var != nullptr);
2708 1 : SNAP_CATCH2_NAMESPACE::reporter::variable_floating_point::pointer_t vf(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_floating_point>(var));
2709 1 : CATCH_REQUIRE(vf != nullptr);
2710 1 : CATCH_REQUIRE(vf->get_type() == "floating_point");
2711 1 : CATCH_REQUIRE(vf->get_floating_point() == 303.601);
2712 :
2713 1 : var = s->get_variable("longer_floating_point_var");
2714 1 : CATCH_REQUIRE(var != nullptr);
2715 1 : vf = std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_floating_point>(var);
2716 1 : CATCH_REQUIRE(vf != nullptr);
2717 1 : CATCH_REQUIRE(vf->get_type() == "floating_point");
2718 1 : CATCH_REQUIRE(vf->get_floating_point() == 303.601);
2719 :
2720 1 : var = s->get_variable("my_identifier_var");
2721 1 : CATCH_REQUIRE(var != nullptr);
2722 1 : vs = std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var);
2723 1 : CATCH_REQUIRE(vs != nullptr);
2724 1 : CATCH_REQUIRE(vs->get_type() == "identifier");
2725 1 : CATCH_REQUIRE(vs->get_string() == "bar");
2726 :
2727 1 : var = s->get_variable("longer_identifier_var");
2728 1 : CATCH_REQUIRE(var != nullptr);
2729 1 : vs = std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var);
2730 1 : CATCH_REQUIRE(vs != nullptr);
2731 1 : CATCH_REQUIRE(vs->get_type() == "identifier");
2732 1 : CATCH_REQUIRE(vs->get_string() == "bar");
2733 :
2734 1 : var = s->get_variable("my_regex_var");
2735 1 : CATCH_REQUIRE(var != nullptr);
2736 1 : SNAP_CATCH2_NAMESPACE::reporter::variable_regex::pointer_t vre(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_regex>(var));
2737 1 : CATCH_REQUIRE(vre != nullptr);
2738 1 : CATCH_REQUIRE(vre->get_type() == "regex");
2739 1 : CATCH_REQUIRE(vre->get_regex() == "^[regex]$");
2740 :
2741 1 : var = s->get_variable("longer_regex_var");
2742 1 : CATCH_REQUIRE(var != nullptr);
2743 1 : vre = std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_regex>(var);
2744 1 : CATCH_REQUIRE(vre != nullptr);
2745 1 : CATCH_REQUIRE(vre->get_type() == "regex");
2746 1 : CATCH_REQUIRE(vre->get_regex() == "^[regex]$");
2747 :
2748 1 : addr::addr a;
2749 1 : sockaddr_in ip = {
2750 : .sin_family = AF_INET,
2751 1 : .sin_port = htons(89),
2752 : .sin_addr = {
2753 1 : .s_addr = htonl(0x0A0C0E10),
2754 : },
2755 : .sin_zero = {},
2756 1 : };
2757 1 : a.set_ipv4(ip);
2758 :
2759 1 : var = s->get_variable("my_address_var");
2760 1 : CATCH_REQUIRE(var != nullptr);
2761 1 : SNAP_CATCH2_NAMESPACE::reporter::variable_address::pointer_t va(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_address>(var));
2762 1 : CATCH_REQUIRE(va != nullptr);
2763 1 : CATCH_REQUIRE(va->get_type() == "address");
2764 1 : CATCH_REQUIRE(va->get_address() == a);
2765 :
2766 1 : var = s->get_variable("longer_address_var");
2767 1 : CATCH_REQUIRE(var != nullptr);
2768 1 : va = std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_address>(var);
2769 1 : CATCH_REQUIRE(va != nullptr);
2770 1 : CATCH_REQUIRE(va->get_type() == "address");
2771 1 : CATCH_REQUIRE(va->get_address() == a);
2772 :
2773 1 : snapdev::timespec_ex const expected_timestamp{ 1714241733, 419438123 };
2774 :
2775 1 : var = s->get_variable("my_timestamp_var");
2776 1 : CATCH_REQUIRE(var != nullptr);
2777 1 : SNAP_CATCH2_NAMESPACE::reporter::variable_timestamp::pointer_t vts(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_timestamp>(var));
2778 1 : CATCH_REQUIRE(vts != nullptr);
2779 1 : CATCH_REQUIRE(vts->get_type() == "timestamp");
2780 1 : CATCH_REQUIRE(vts->get_timestamp() == expected_timestamp);
2781 :
2782 1 : var = s->get_variable("longer_timestamp_var");
2783 1 : CATCH_REQUIRE(var != nullptr);
2784 1 : vts = std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_timestamp>(var);
2785 1 : CATCH_REQUIRE(vts != nullptr);
2786 1 : CATCH_REQUIRE(vts->get_type() == "timestamp");
2787 1 : CATCH_REQUIRE(vts->get_timestamp() == expected_timestamp);
2788 :
2789 1 : CATCH_REQUIRE(s->get_exit_code() == -1);
2790 1 : }
2791 8 : CATCH_END_SECTION()
2792 :
2793 8 : CATCH_START_SECTION("primary variable reference with wrong name")
2794 : {
2795 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("primary_variable_reference.rprtr", g_program_wrong_primary_variable_reference));
2796 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
2797 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
2798 1 : p->parse_program();
2799 :
2800 1 : CATCH_REQUIRE(s->get_statement_size() == 2);
2801 :
2802 3 : SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var(s->get_variable("my_var"));
2803 1 : CATCH_REQUIRE(var == nullptr);
2804 1 : var = s->get_variable("longer_var");
2805 1 : CATCH_REQUIRE(var == nullptr);
2806 :
2807 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
2808 1 : e->start();
2809 1 : CATCH_REQUIRE(e->run());
2810 :
2811 1 : var = s->get_variable("my_var");
2812 1 : CATCH_REQUIRE(var != nullptr);
2813 1 : SNAP_CATCH2_NAMESPACE::reporter::variable_string::pointer_t v(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var));
2814 1 : CATCH_REQUIRE(v != nullptr);
2815 1 : CATCH_REQUIRE(v->get_string() == "foo");
2816 :
2817 1 : var = s->get_variable("longer_var");
2818 1 : CATCH_REQUIRE(var != nullptr);
2819 1 : v = std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var);
2820 1 : CATCH_REQUIRE(v != nullptr);
2821 1 : CATCH_REQUIRE(v->get_string() == ""); // wrong name so we get an empty string
2822 :
2823 1 : CATCH_REQUIRE(s->get_exit_code() == -1);
2824 1 : }
2825 8 : CATCH_END_SECTION()
2826 8 : }
2827 :
2828 :
2829 28 : CATCH_TEST_CASE("reporter_executor_error", "[executor][reporter][error]")
2830 : {
2831 28 : CATCH_START_SECTION("if() before any condition")
2832 : {
2833 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("if_too_soon.rprtr.rprtr", g_program_no_condition));
2834 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
2835 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
2836 1 : p->parse_program();
2837 :
2838 1 : CATCH_REQUIRE(s->get_statement_size() == 2);
2839 :
2840 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
2841 1 : CATCH_REQUIRE_THROWS_MATCHES(
2842 : e->start()
2843 : , std::runtime_error
2844 : , Catch::Matchers::ExceptionMessage(
2845 : "trying to use a 'compare' result when none are currently defined."));
2846 :
2847 1 : CATCH_REQUIRE_THROWS_MATCHES(
2848 : s->set_compare(SNAP_CATCH2_NAMESPACE::reporter::compare_t::COMPARE_UNDEFINED)
2849 : , std::runtime_error
2850 : , Catch::Matchers::ExceptionMessage(
2851 : "'compare' cannot be set to \"undefined\"."));
2852 1 : }
2853 28 : CATCH_END_SECTION()
2854 :
2855 28 : CATCH_START_SECTION("exit() + error message")
2856 : {
2857 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("exit_error_message.rprtr.rprtr", g_program_error_message));
2858 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
2859 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
2860 1 : p->parse_program();
2861 :
2862 1 : CATCH_REQUIRE(s->get_statement_size() == 1);
2863 :
2864 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
2865 1 : e->start();
2866 :
2867 1 : CATCH_REQUIRE(s->get_exit_code() == 1);
2868 1 : }
2869 28 : CATCH_END_SECTION()
2870 :
2871 28 : CATCH_START_SECTION("listen() + listen()")
2872 : {
2873 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("two_listen.rprtr.rprtr", g_program_two_listen));
2874 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
2875 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
2876 1 : p->parse_program();
2877 :
2878 1 : CATCH_REQUIRE(s->get_statement_size() == 2);
2879 :
2880 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
2881 1 : CATCH_REQUIRE_THROWS_MATCHES(
2882 : e->start()
2883 : , std::runtime_error
2884 : , Catch::Matchers::ExceptionMessage(
2885 : "the listen() instruction cannot be reused without an intermediate disconnect() instruction."));
2886 1 : }
2887 28 : CATCH_END_SECTION()
2888 :
2889 28 : CATCH_START_SECTION("label(name: ...) does not accept integers")
2890 : {
2891 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("label_bad_type.rprtr.rprtr", g_program_label_bad_type));
2892 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
2893 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
2894 :
2895 : // label is a special case which we test in the state.cpp way before
2896 : // we reach the executor... (so this is not really an executor test)
2897 : //
2898 1 : CATCH_REQUIRE_THROWS_MATCHES(
2899 : p->parse_program()
2900 : , std::runtime_error
2901 : , Catch::Matchers::ExceptionMessage(
2902 : "the value of the \"name\" parameter of the \"label\" statement must be an identifier."));
2903 1 : }
2904 28 : CATCH_END_SECTION()
2905 :
2906 28 : CATCH_START_SECTION("exit(error_message: ...) does not accept floating points")
2907 : {
2908 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("exit_bad_type.rprtr", g_program_exit_bad_type));
2909 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
2910 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
2911 1 : p->parse_program();
2912 :
2913 1 : CATCH_REQUIRE(s->get_statement_size() == 1);
2914 :
2915 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
2916 1 : CATCH_REQUIRE_THROWS_MATCHES(
2917 : e->start()
2918 : , std::runtime_error
2919 : , Catch::Matchers::ExceptionMessage(
2920 : "parameter type mismatch for error_message, expected \"string\", got \"floating_point\" instead."));
2921 1 : }
2922 28 : CATCH_END_SECTION()
2923 :
2924 28 : CATCH_START_SECTION("verify starting the thread twice")
2925 : {
2926 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_start_thread_twice.rprtr", g_program_start_thread_twice));
2927 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
2928 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
2929 1 : p->parse_program();
2930 :
2931 1 : CATCH_REQUIRE(s->get_statement_size() == 4);
2932 :
2933 : // before we run the script, there are no such variables
2934 : //
2935 3 : SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var(s->get_variable("test"));
2936 1 : CATCH_REQUIRE(var == nullptr);
2937 1 : var = s->get_variable("runner");
2938 1 : CATCH_REQUIRE(var == nullptr);
2939 :
2940 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
2941 1 : e->start();
2942 1 : CATCH_REQUIRE(e->run());
2943 1 : CATCH_REQUIRE_THROWS_MATCHES(
2944 : e->stop()
2945 : , std::runtime_error
2946 : , Catch::Matchers::ExceptionMessage(
2947 : "run() instruction found when already running in the background."));
2948 :
2949 1 : var = s->get_variable("test");
2950 1 : CATCH_REQUIRE(var != nullptr);
2951 1 : CATCH_REQUIRE(var->get_name() == "test");
2952 1 : CATCH_REQUIRE(var->get_type() == "integer");
2953 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == 33);
2954 :
2955 1 : var = s->get_variable("runner");
2956 1 : CATCH_REQUIRE(var != nullptr);
2957 1 : CATCH_REQUIRE(var->get_name() == "runner");
2958 1 : CATCH_REQUIRE(var->get_type() == "floating_point");
2959 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_floating_point>(var)->get_floating_point() == 6.07);
2960 1 : }
2961 28 : CATCH_END_SECTION()
2962 :
2963 28 : CATCH_START_SECTION("<type> + <type> that are not valid")
2964 : {
2965 : struct bad_additions_t
2966 : {
2967 : char const * f_code = nullptr;
2968 : SNAP_CATCH2_NAMESPACE::reporter::token_t f_left_hand_side = SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ERROR;
2969 : SNAP_CATCH2_NAMESPACE::reporter::token_t f_right_hand_side = SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ERROR;
2970 : };
2971 1 : constexpr bad_additions_t const bad_additions[] =
2972 : {
2973 : {
2974 : g_program_unsupported_addition_address_address,
2975 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ADDRESS,
2976 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ADDRESS,
2977 : },
2978 : {
2979 : g_program_unsupported_addition_address_string,
2980 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ADDRESS,
2981 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_SINGLE_STRING,
2982 : },
2983 : {
2984 : g_program_unsupported_addition_string_address,
2985 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_SINGLE_STRING,
2986 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ADDRESS,
2987 : },
2988 : {
2989 : g_program_unsupported_addition_address_identifier,
2990 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ADDRESS,
2991 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_IDENTIFIER,
2992 : },
2993 : {
2994 : g_program_unsupported_addition_identifier_address,
2995 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_IDENTIFIER,
2996 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ADDRESS,
2997 : },
2998 : {
2999 : g_program_unsupported_addition_identifier_string,
3000 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_IDENTIFIER,
3001 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_SINGLE_STRING,
3002 : },
3003 : {
3004 : g_program_unsupported_addition_string_identifier,
3005 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_SINGLE_STRING,
3006 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_IDENTIFIER,
3007 : },
3008 : };
3009 :
3010 8 : for(auto const & ba : bad_additions)
3011 : {
3012 7 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("invalid_additions.rprtr", ba.f_code));
3013 7 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
3014 7 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
3015 7 : p->parse_program();
3016 :
3017 7 : CATCH_REQUIRE(s->get_statement_size() == 1);
3018 :
3019 7 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
3020 7 : CATCH_REQUIRE_THROWS_MATCHES(
3021 : e->start()
3022 : , std::runtime_error
3023 : , Catch::Matchers::ExceptionMessage(
3024 : "unsupported addition (token types: "
3025 : + std::to_string(static_cast<int>(ba.f_left_hand_side))
3026 : + " + "
3027 : + std::to_string(static_cast<int>(ba.f_right_hand_side))
3028 : + ")."));
3029 7 : }
3030 : }
3031 28 : CATCH_END_SECTION()
3032 :
3033 28 : CATCH_START_SECTION("<type> - <type> that are not valid")
3034 : {
3035 1 : constexpr char const * const bad_subtractions[] =
3036 : {
3037 : g_program_unsupported_subtraction_address_string,
3038 : g_program_unsupported_subtraction_string_address,
3039 : g_program_unsupported_subtraction_address_identifier,
3040 : g_program_unsupported_subtraction_identifier_address,
3041 : g_program_unsupported_subtraction_identifier_string,
3042 : g_program_unsupported_subtraction_string_identifier,
3043 : };
3044 :
3045 7 : for(auto const & program : bad_subtractions)
3046 : {
3047 : //std::cerr << "testing [" << program << "]\n";
3048 6 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("invalid_subtractions.rprtr", program));
3049 6 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
3050 6 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
3051 6 : p->parse_program();
3052 :
3053 6 : CATCH_REQUIRE(s->get_statement_size() == 1);
3054 :
3055 6 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
3056 6 : CATCH_REQUIRE_THROWS_MATCHES(
3057 : e->start()
3058 : , std::runtime_error
3059 : , Catch::Matchers::ExceptionMessage(
3060 : "unsupported subtraction."));
3061 6 : }
3062 : }
3063 28 : CATCH_END_SECTION()
3064 :
3065 28 : CATCH_START_SECTION("<type> * <type> that are not valid")
3066 : {
3067 1 : constexpr char const * const bad_multiplications[] =
3068 : {
3069 : g_program_unsupported_multiplication_address_address,
3070 : g_program_unsupported_multiplication_address_string,
3071 : g_program_unsupported_multiplication_string_address,
3072 : g_program_unsupported_multiplication_address_identifier,
3073 : g_program_unsupported_multiplication_identifier_address,
3074 : g_program_unsupported_multiplication_identifier_string,
3075 : g_program_unsupported_multiplication_string_identifier,
3076 : g_program_unsupported_multiplication_string_string,
3077 : g_program_unsupported_multiplication_identifier_identifier,
3078 : };
3079 :
3080 10 : for(auto const & program : bad_multiplications)
3081 : {
3082 : //std::cerr << "testing [" << program << "]\n";
3083 9 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("invalid_multiplications.rprtr", program));
3084 9 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
3085 9 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
3086 9 : p->parse_program();
3087 :
3088 9 : CATCH_REQUIRE(s->get_statement_size() == 1);
3089 :
3090 9 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
3091 9 : CATCH_REQUIRE_THROWS_MATCHES(
3092 : e->start()
3093 : , std::runtime_error
3094 : , Catch::Matchers::ExceptionMessage(
3095 : "unsupported multiplication."));
3096 9 : }
3097 : }
3098 28 : CATCH_END_SECTION()
3099 :
3100 28 : CATCH_START_SECTION("<type> / <type> that are not valid")
3101 : {
3102 1 : constexpr char const * const bad_divisions[] =
3103 : {
3104 : g_program_unsupported_division_address_address,
3105 : g_program_unsupported_division_address_string,
3106 : g_program_unsupported_division_string_address,
3107 : g_program_unsupported_division_address_identifier,
3108 : g_program_unsupported_division_identifier_address,
3109 : g_program_unsupported_division_identifier_string,
3110 : g_program_unsupported_division_string_identifier,
3111 : g_program_unsupported_division_string_string,
3112 : g_program_unsupported_division_identifier_identifier,
3113 : };
3114 :
3115 10 : for(auto const & program : bad_divisions)
3116 : {
3117 : //std::cerr << "testing [" << program << "]\n";
3118 9 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("invalid_divisions.rprtr", program));
3119 9 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
3120 9 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
3121 9 : p->parse_program();
3122 :
3123 9 : CATCH_REQUIRE(s->get_statement_size() == 1);
3124 :
3125 9 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
3126 9 : CATCH_REQUIRE_THROWS_MATCHES(
3127 : e->start()
3128 : , std::runtime_error
3129 : , Catch::Matchers::ExceptionMessage(
3130 : "unsupported division."));
3131 9 : }
3132 : }
3133 28 : CATCH_END_SECTION()
3134 :
3135 28 : CATCH_START_SECTION("<type> % <type> that are not valid")
3136 : {
3137 : struct bad_modulo_t
3138 : {
3139 : char const * const f_expr = nullptr;
3140 : SNAP_CATCH2_NAMESPACE::reporter::token_t f_lhs_token = SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ERROR;
3141 : SNAP_CATCH2_NAMESPACE::reporter::token_t f_rhs_token = SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ERROR;
3142 : };
3143 1 : constexpr bad_modulo_t const bad_modulos[] =
3144 : {
3145 : {
3146 : g_program_unsupported_modulo_address_address,
3147 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ADDRESS,
3148 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ADDRESS,
3149 : },
3150 : {
3151 : g_program_unsupported_modulo_address_string,
3152 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ADDRESS,
3153 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_SINGLE_STRING,
3154 : },
3155 : {
3156 : g_program_unsupported_modulo_string_address,
3157 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_SINGLE_STRING,
3158 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ADDRESS,
3159 : },
3160 : {
3161 : g_program_unsupported_modulo_address_identifier,
3162 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ADDRESS,
3163 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_IDENTIFIER,
3164 : },
3165 : {
3166 : g_program_unsupported_modulo_identifier_address,
3167 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_IDENTIFIER,
3168 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ADDRESS,
3169 : },
3170 : {
3171 : g_program_unsupported_modulo_identifier_string,
3172 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_IDENTIFIER,
3173 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_SINGLE_STRING, // the type of string was already converted by this time
3174 : },
3175 : {
3176 : g_program_unsupported_modulo_string_identifier,
3177 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_SINGLE_STRING,
3178 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_IDENTIFIER,
3179 : },
3180 : {
3181 : g_program_unsupported_modulo_string_string,
3182 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_SINGLE_STRING,
3183 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_SINGLE_STRING, // the type of string was already converted by this time
3184 : },
3185 : {
3186 : g_program_unsupported_modulo_identifier_identifier,
3187 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_IDENTIFIER,
3188 : SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_IDENTIFIER,
3189 : },
3190 : };
3191 :
3192 10 : for(auto const & program : bad_modulos)
3193 : {
3194 : //std::cerr << "testing [" << program.f_expr << "]\n";
3195 9 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("invalid_modulos.rprtr", program.f_expr));
3196 9 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
3197 9 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
3198 9 : p->parse_program();
3199 :
3200 9 : CATCH_REQUIRE(s->get_statement_size() == 1);
3201 :
3202 9 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
3203 9 : CATCH_REQUIRE_THROWS_MATCHES(
3204 : e->start()
3205 : , std::runtime_error
3206 : , Catch::Matchers::ExceptionMessage(
3207 : "unsupported modulo (types: "
3208 : + std::to_string(static_cast<int>(program.f_lhs_token))
3209 : + " and "
3210 : + std::to_string(static_cast<int>(program.f_rhs_token))
3211 : + ")."));
3212 9 : }
3213 : }
3214 28 : CATCH_END_SECTION()
3215 :
3216 28 : CATCH_START_SECTION("-<types> that are not valid")
3217 : {
3218 1 : constexpr char const * const bad_negations[] =
3219 : {
3220 : g_program_unsupported_negation_single_string,
3221 : g_program_unsupported_negation_double_string,
3222 : g_program_unsupported_negation_address,
3223 : };
3224 :
3225 4 : for(auto const & program : bad_negations)
3226 : {
3227 3 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("invalid_negate.rprtr", program));
3228 3 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
3229 3 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
3230 3 : p->parse_program();
3231 :
3232 3 : CATCH_REQUIRE(s->get_statement_size() == 1);
3233 :
3234 3 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
3235 3 : CATCH_REQUIRE_THROWS_MATCHES(
3236 : e->start()
3237 : , std::runtime_error
3238 : , Catch::Matchers::ExceptionMessage(
3239 : "unsupported negation."));
3240 3 : }
3241 : }
3242 28 : CATCH_END_SECTION()
3243 :
3244 28 : CATCH_START_SECTION("variable reference without a '}'")
3245 : {
3246 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("invalid_negate.rprtr", g_program_unterminated_double_string_variable));
3247 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
3248 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
3249 1 : p->parse_program();
3250 :
3251 1 : CATCH_REQUIRE(s->get_statement_size() == 2);
3252 :
3253 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
3254 1 : CATCH_REQUIRE_THROWS_MATCHES(
3255 : e->start()
3256 : , std::runtime_error
3257 : , Catch::Matchers::ExceptionMessage(
3258 : "invalid_negate.rprtr:2: found unclosed variable in \"ref. ${my_var\"."));
3259 1 : }
3260 28 : CATCH_END_SECTION()
3261 :
3262 28 : CATCH_START_SECTION("regex variable in double string")
3263 : {
3264 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("invalid_negate.rprtr", g_program_regex_in_double_string_variable));
3265 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
3266 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
3267 1 : p->parse_program();
3268 :
3269 1 : CATCH_REQUIRE(s->get_statement_size() == 2);
3270 :
3271 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
3272 1 : CATCH_REQUIRE_THROWS_MATCHES(
3273 : e->start()
3274 : , std::runtime_error
3275 : , Catch::Matchers::ExceptionMessage(
3276 : "found variable of type \"regex\" which is not yet supported in ${...}."));
3277 1 : }
3278 28 : CATCH_END_SECTION()
3279 :
3280 28 : CATCH_START_SECTION("variable reference without a name")
3281 : {
3282 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("invalid_negate.rprtr", g_program_double_string_variable_without_name));
3283 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
3284 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
3285 1 : p->parse_program();
3286 :
3287 1 : CATCH_REQUIRE(s->get_statement_size() == 1);
3288 :
3289 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
3290 1 : CATCH_REQUIRE_THROWS_MATCHES(
3291 : e->start()
3292 : , std::runtime_error
3293 : , Catch::Matchers::ExceptionMessage(
3294 : "invalid_negate.rprtr:1: found variable without a name in \"ref. ${} is empty\"."));
3295 1 : }
3296 28 : CATCH_END_SECTION()
3297 :
3298 28 : CATCH_START_SECTION("<string> * <negative> is not valid")
3299 : {
3300 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("invalid_string_multiplication_negative.rprtr", g_program_unsupported_negation_repeat));
3301 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
3302 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
3303 1 : p->parse_program();
3304 :
3305 1 : CATCH_REQUIRE(s->get_statement_size() == 1);
3306 :
3307 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
3308 1 : CATCH_REQUIRE_THROWS_MATCHES(
3309 : e->start()
3310 : , std::runtime_error
3311 : , Catch::Matchers::ExceptionMessage(
3312 : "string repeat needs to be positive and under 1001."));
3313 1 : }
3314 28 : CATCH_END_SECTION()
3315 :
3316 28 : CATCH_START_SECTION("<string> * <large repeat> is not valid")
3317 : {
3318 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("invalid_string_multiplication_large.rprtr", g_program_unsupported_large_repeat));
3319 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
3320 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
3321 1 : p->parse_program();
3322 :
3323 1 : CATCH_REQUIRE(s->get_statement_size() == 1);
3324 :
3325 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
3326 1 : CATCH_REQUIRE_THROWS_MATCHES(
3327 : e->start()
3328 : , std::runtime_error
3329 : , Catch::Matchers::ExceptionMessage(
3330 : "string repeat needs to be positive and under 1001."));
3331 1 : }
3332 28 : CATCH_END_SECTION()
3333 :
3334 28 : CATCH_START_SECTION("exit() with timeout & error_message is invalid")
3335 : {
3336 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("bad_exit.rprtr", g_program_bad_exit));
3337 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
3338 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
3339 1 : p->parse_program();
3340 :
3341 1 : CATCH_REQUIRE(s->get_statement_size() == 1);
3342 :
3343 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
3344 1 : CATCH_REQUIRE_THROWS_MATCHES(
3345 : e->start()
3346 : , std::runtime_error
3347 : , Catch::Matchers::ExceptionMessage(
3348 : "\"timeout\" and \"error_message\" from the exit() instruction are mutually exclusive."));
3349 1 : }
3350 28 : CATCH_END_SECTION()
3351 :
3352 28 : CATCH_START_SECTION("exit() with timeout which is not a number")
3353 : {
3354 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("bad_exit.rprtr", g_program_bad_exit_timeout));
3355 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
3356 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
3357 1 : p->parse_program();
3358 :
3359 1 : CATCH_REQUIRE(s->get_statement_size() == 1);
3360 :
3361 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
3362 1 : CATCH_REQUIRE_THROWS_MATCHES(
3363 : e->start()
3364 : , std::runtime_error
3365 : , Catch::Matchers::ExceptionMessage(
3366 : "parameter type mismatch for timeout, expected \"number\", got \"string\" instead."));
3367 1 : }
3368 28 : CATCH_END_SECTION()
3369 :
3370 28 : CATCH_START_SECTION("exit() with timeout which is not a number")
3371 : {
3372 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("bad_print.rprtr", g_program_bad_print_message));
3373 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
3374 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
3375 1 : p->parse_program();
3376 :
3377 1 : CATCH_REQUIRE(s->get_statement_size() == 1);
3378 :
3379 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
3380 1 : CATCH_REQUIRE_THROWS_MATCHES(
3381 : e->start()
3382 : , std::runtime_error
3383 : , Catch::Matchers::ExceptionMessage(
3384 : "parameter type mismatch for message, expected \"string\", got \"identifier\" instead."));
3385 1 : }
3386 28 : CATCH_END_SECTION()
3387 :
3388 28 : CATCH_START_SECTION("send_message() when not connected")
3389 : {
3390 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("bad_send_message.rprtr", g_program_send_message_without_connection));
3391 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
3392 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
3393 1 : p->parse_program();
3394 :
3395 1 : CATCH_REQUIRE(s->get_statement_size() == 1);
3396 :
3397 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
3398 1 : CATCH_REQUIRE_THROWS_MATCHES(
3399 : e->start()
3400 : , std::runtime_error
3401 : , Catch::Matchers::ExceptionMessage(
3402 : "send_message() has no connection to send a message to."));
3403 1 : }
3404 28 : CATCH_END_SECTION()
3405 :
3406 28 : CATCH_START_SECTION("if(variable) with invalid type")
3407 : {
3408 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("if_invalid_type.rprtr", g_program_if_invalid_type));
3409 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
3410 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
3411 1 : p->parse_program();
3412 :
3413 1 : CATCH_REQUIRE(s->get_statement_size() == 5);
3414 :
3415 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
3416 1 : CATCH_REQUIRE_THROWS_MATCHES(
3417 : e->start()
3418 : , std::runtime_error
3419 : , Catch::Matchers::ExceptionMessage(
3420 : "if(variable: ...) only supports variables of type integer or floating point."));
3421 1 : }
3422 28 : CATCH_END_SECTION()
3423 :
3424 28 : CATCH_START_SECTION("wait() before starting thread")
3425 : {
3426 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("wait_outside_thread.rprtr", g_program_wait_outside_thread));
3427 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
3428 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
3429 1 : p->parse_program();
3430 :
3431 1 : CATCH_REQUIRE(s->get_statement_size() == 1);
3432 :
3433 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
3434 1 : CATCH_REQUIRE_THROWS_MATCHES(
3435 : e->start()
3436 : , std::runtime_error
3437 : , Catch::Matchers::ExceptionMessage(
3438 : "wait() used before run()."));
3439 1 : }
3440 28 : CATCH_END_SECTION()
3441 :
3442 28 : CATCH_START_SECTION("wait() with invalid mode")
3443 : {
3444 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_wait_invalid_mode.rprtr", g_program_wait_invalid_mode));
3445 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
3446 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
3447 1 : p->parse_program();
3448 :
3449 1 : CATCH_REQUIRE(s->get_statement_size() == 2);
3450 :
3451 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
3452 1 : e->start();
3453 1 : addr::addr a;
3454 1 : sockaddr_in ip = {
3455 : .sin_family = AF_INET,
3456 1 : .sin_port = htons(20002),
3457 : .sin_addr = {
3458 1 : .s_addr = htonl(0x7f000001),
3459 : },
3460 : .sin_zero = {},
3461 1 : };
3462 1 : a.set_ipv4(ip);
3463 1 : messenger_responder::pointer_t messenger(std::make_shared<messenger_responder>(
3464 : a
3465 1 : , ed::mode_t::MODE_PLAIN
3466 2 : , messenger_responder::sequence_t::SEQUENCE_ONE_MESSAGE));
3467 1 : ed::communicator::instance()->add_connection(messenger);
3468 1 : messenger_timer::pointer_t timer(std::make_shared<messenger_timer>(messenger));
3469 1 : ed::communicator::instance()->add_connection(timer);
3470 1 : messenger->set_timer(timer);
3471 1 : e->set_thread_done_callback([messenger, timer]()
3472 : {
3473 1 : ed::communicator::instance()->remove_connection(messenger);
3474 1 : ed::communicator::instance()->remove_connection(timer);
3475 1 : });
3476 :
3477 1 : CATCH_REQUIRE(e->run());
3478 :
3479 : // the thread exception happens when e->stop() is called
3480 : //
3481 1 : CATCH_REQUIRE_THROWS_MATCHES(
3482 : e->stop()
3483 : , std::runtime_error
3484 : , Catch::Matchers::ExceptionMessage("program_wait_invalid_mode.rprtr:2: unknown mode \"not_this_one\" in wait()."));
3485 :
3486 : // if we exited because of our timer, then the test did not pass
3487 : //
3488 1 : CATCH_REQUIRE_FALSE(timer->timed_out_prima());
3489 :
3490 1 : CATCH_REQUIRE(s->get_exit_code() == -1);
3491 1 : }
3492 28 : CATCH_END_SECTION()
3493 :
3494 28 : CATCH_START_SECTION("wait() + drain without connections")
3495 : {
3496 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_wait_no_connection.rprtr", g_program_wait_no_connections));
3497 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
3498 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
3499 1 : p->parse_program();
3500 :
3501 1 : CATCH_REQUIRE(s->get_statement_size() == 2);
3502 :
3503 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
3504 1 : e->start();
3505 1 : CATCH_REQUIRE(e->run());
3506 :
3507 : // the thread exception happens when e->stop() is called
3508 : //
3509 1 : CATCH_REQUIRE_THROWS_MATCHES(
3510 : e->stop()
3511 : , std::runtime_error
3512 : , Catch::Matchers::ExceptionMessage("no connections to wait() on."));
3513 :
3514 1 : CATCH_REQUIRE(s->get_exit_code() == -1);
3515 1 : }
3516 28 : CATCH_END_SECTION()
3517 :
3518 28 : CATCH_START_SECTION("try reading missing file")
3519 : {
3520 1 : std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
3521 1 : std::string const filename(source_dir + "/tests/rprtr/not_this_one");
3522 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
3523 1 : CATCH_REQUIRE(l == nullptr);
3524 1 : }
3525 28 : CATCH_END_SECTION()
3526 :
3527 28 : CATCH_START_SECTION("verify that the executor::run() function does a try/catch as expected")
3528 : {
3529 : // in this case, load the program from a file
3530 : // to verify that this works as expected
3531 : //
3532 1 : std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
3533 1 : std::string const filename(source_dir + "/tests/rprtr/send_and_receive_complete_messages");
3534 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
3535 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
3536 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
3537 1 : p->parse_program();
3538 :
3539 1 : CATCH_REQUIRE(s->get_statement_size() == 30);
3540 :
3541 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
3542 1 : e->start();
3543 1 : addr::addr a;
3544 1 : sockaddr_in ip = {
3545 : .sin_family = AF_INET,
3546 1 : .sin_port = htons(20002),
3547 : .sin_addr = {
3548 1 : .s_addr = htonl(0x7f000001),
3549 : },
3550 : .sin_zero = {},
3551 1 : };
3552 1 : a.set_ipv4(ip);
3553 1 : messenger_responder::pointer_t messenger(std::make_shared<messenger_responder>(
3554 : a
3555 1 : , ed::mode_t::MODE_PLAIN
3556 2 : , messenger_responder::sequence_t::SEQUENCE_READY_THROW));
3557 1 : ed::communicator::instance()->add_connection(messenger);
3558 1 : messenger_timer::pointer_t timer(std::make_shared<messenger_timer>(messenger));
3559 1 : ed::communicator::instance()->add_connection(timer);
3560 1 : messenger->set_timer(timer);
3561 :
3562 : // the exception capture in run() is not returned; it should be
3563 : // printed in the console, making it possible to see what happened
3564 : //
3565 1 : CATCH_REQUIRE_FALSE(e->run());
3566 :
3567 1 : CATCH_REQUIRE_THROWS_MATCHES(
3568 : e->stop()
3569 : , std::runtime_error
3570 : , Catch::Matchers::ExceptionMessage("ppoll() timed out."));
3571 :
3572 : // if we exited because of our timer, then the test did not pass
3573 : //
3574 1 : CATCH_REQUIRE_FALSE(timer->timed_out_prima());
3575 :
3576 1 : CATCH_REQUIRE(s->get_exit_code() == -1);
3577 :
3578 : // in this case, the variable does not get unset because the
3579 : // crash happens before we have the chance to do that
3580 : //
3581 3 : SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var(s->get_variable("got_register"));
3582 1 : CATCH_REQUIRE(var != nullptr);
3583 1 : CATCH_REQUIRE(var->get_type() == "integer");
3584 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == 1);
3585 1 : }
3586 28 : CATCH_END_SECTION()
3587 :
3588 28 : CATCH_START_SECTION("verify that the executor::run() function does a try/catch of non-standard exceptions")
3589 : {
3590 : // in this case, load the program from a file
3591 : // to verify that this works as expected
3592 : //
3593 1 : std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
3594 1 : std::string const filename(source_dir + "/tests/rprtr/send_and_receive_complete_messages");
3595 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
3596 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
3597 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
3598 1 : p->parse_program();
3599 :
3600 1 : CATCH_REQUIRE(s->get_statement_size() == 30);
3601 :
3602 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
3603 1 : e->start();
3604 1 : addr::addr a;
3605 1 : sockaddr_in ip = {
3606 : .sin_family = AF_INET,
3607 1 : .sin_port = htons(20002),
3608 : .sin_addr = {
3609 1 : .s_addr = htonl(0x7f000001),
3610 : },
3611 : .sin_zero = {},
3612 1 : };
3613 1 : a.set_ipv4(ip);
3614 1 : messenger_responder::pointer_t messenger(std::make_shared<messenger_responder>(
3615 : a
3616 1 : , ed::mode_t::MODE_PLAIN
3617 2 : , messenger_responder::sequence_t::SEQUENCE_READY_THROW_WHAT));
3618 1 : ed::communicator::instance()->add_connection(messenger);
3619 1 : messenger_timer::pointer_t timer(std::make_shared<messenger_timer>(messenger));
3620 1 : ed::communicator::instance()->add_connection(timer);
3621 1 : messenger->set_timer(timer);
3622 :
3623 : // the exception capture in run() is not returned; it should be
3624 : // printed in the console, making it possible to see what happened
3625 : //
3626 1 : CATCH_REQUIRE_FALSE(e->run());
3627 :
3628 1 : CATCH_REQUIRE_THROWS_MATCHES(
3629 : e->stop()
3630 : , std::runtime_error
3631 : , Catch::Matchers::ExceptionMessage("ppoll() timed out."));
3632 :
3633 : // if we exited because of our timer, then the test did not pass
3634 : //
3635 1 : CATCH_REQUIRE_FALSE(timer->timed_out_prima());
3636 :
3637 1 : CATCH_REQUIRE(s->get_exit_code() == -1);
3638 :
3639 : // in this case, the variable does not get unset because the
3640 : // crash happens before we have the chance to do that
3641 : //
3642 3 : SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var(s->get_variable("got_register"));
3643 1 : CATCH_REQUIRE(var != nullptr);
3644 1 : CATCH_REQUIRE(var->get_type() == "integer");
3645 1 : CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == 1);
3646 1 : }
3647 28 : CATCH_END_SECTION()
3648 28 : }
3649 :
3650 :
3651 3 : CATCH_TEST_CASE("reporter_executor_error_message", "[executor][reporter][error]")
3652 : {
3653 3 : CATCH_START_SECTION("verify message fails")
3654 : {
3655 : struct bad_verification_t
3656 : {
3657 : char const * const f_program = nullptr;
3658 : char const * const f_error = nullptr;
3659 : };
3660 1 : bad_verification_t const bad_verifications[] =
3661 : {
3662 : {
3663 : g_program_verify_message_fail_sent_server,
3664 : "program_verify_message_fail.rprtr:9: message expected \"sent_server\", set to \"\", to match \"not_this_one\".",
3665 : },
3666 : {
3667 : g_program_verify_message_fail_sent_service,
3668 : "program_verify_message_fail.rprtr:9: message expected \"sent_service\", set to \"\", to match \"not_this_one\".",
3669 : },
3670 : {
3671 : g_program_verify_message_fail_server,
3672 : "program_verify_message_fail.rprtr:9: message expected \"server\", set to \"\", to match \"not_this_one\".",
3673 : },
3674 : {
3675 : g_program_verify_message_fail_service,
3676 : "program_verify_message_fail.rprtr:9: message expected \"service\", set to \"\", to match \"not_this_one\".",
3677 : },
3678 : {
3679 : g_program_verify_message_fail_command,
3680 : "program_verify_message_fail.rprtr:9: message expected \"command\", set to \"REGISTER\", to match \"NOT_THIS_ONE\".",
3681 : },
3682 : {
3683 : g_program_verify_message_fail_forbidden,
3684 : "program_verify_message_fail.rprtr:9: message forbidden parameter \"version\" was found in this message.",
3685 : },
3686 : {
3687 : g_program_verify_message_fail_required,
3688 : "program_verify_message_fail.rprtr:9: message required parameter \"not_this_one\" was not found in this message.",
3689 : },
3690 : {
3691 : g_program_verify_message_fail_required_int_value,
3692 : "program_verify_message_fail.rprtr:9: message expected parameter \"version\" to be an integer set to \"200\" but found \"1\" instead.",
3693 : },
3694 : {
3695 : g_program_verify_message_fail_required_str_value,
3696 : "program_verify_message_fail.rprtr:9: message expected parameter \"service\" to be a string set to \"not_this_one\" but found \"responder\" instead.",
3697 : },
3698 : {
3699 : g_program_verify_message_fail_required_flt_value,
3700 : "program_verify_message_fail.rprtr:9: message parameter type \"floating_point\" not supported yet.",
3701 : },
3702 : };
3703 11 : for(auto const & bv : bad_verifications)
3704 : {
3705 10 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_verify_message_fail.rprtr", bv.f_program));
3706 10 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
3707 10 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
3708 10 : p->parse_program();
3709 :
3710 10 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
3711 10 : e->start();
3712 10 : addr::addr a;
3713 10 : sockaddr_in ip = {
3714 : .sin_family = AF_INET,
3715 10 : .sin_port = htons(20002),
3716 : .sin_addr = {
3717 10 : .s_addr = htonl(0x7f000001),
3718 : },
3719 : .sin_zero = {},
3720 10 : };
3721 10 : a.set_ipv4(ip);
3722 10 : messenger_responder::pointer_t messenger(std::make_shared<messenger_responder>(
3723 : a
3724 10 : , ed::mode_t::MODE_PLAIN
3725 20 : , messenger_responder::sequence_t::SEQUENCE_ONE_MESSAGE));
3726 10 : ed::communicator::instance()->add_connection(messenger);
3727 10 : messenger_timer::pointer_t timer(std::make_shared<messenger_timer>(messenger));
3728 10 : ed::communicator::instance()->add_connection(timer);
3729 10 : messenger->set_timer(timer);
3730 10 : e->set_thread_done_callback([messenger, timer]()
3731 : {
3732 10 : ed::communicator::instance()->remove_connection(messenger);
3733 10 : ed::communicator::instance()->remove_connection(timer);
3734 10 : });
3735 :
3736 10 : CATCH_REQUIRE(e->run());
3737 :
3738 : // the thread exception happens when e->stop() is called
3739 : //
3740 10 : CATCH_REQUIRE_THROWS_MATCHES(
3741 : e->stop()
3742 : , std::runtime_error
3743 : , Catch::Matchers::ExceptionMessage(bv.f_error));
3744 :
3745 : // if we exited because of our timer, then the test did not pass
3746 : //
3747 10 : CATCH_REQUIRE_FALSE(timer->timed_out_prima());
3748 :
3749 10 : CATCH_REQUIRE(s->get_exit_code() == -1);
3750 10 : }
3751 : }
3752 3 : CATCH_END_SECTION()
3753 :
3754 3 : CATCH_START_SECTION("wait for nothing (should time out)")
3755 : {
3756 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_wait_for_nothing.rprtr", g_program_wait_for_nothing));
3757 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
3758 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
3759 1 : p->parse_program();
3760 :
3761 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
3762 1 : e->start();
3763 1 : addr::addr a;
3764 1 : sockaddr_in ip = {
3765 : .sin_family = AF_INET,
3766 1 : .sin_port = htons(20002),
3767 : .sin_addr = {
3768 1 : .s_addr = htonl(0x7f000001),
3769 : },
3770 : .sin_zero = {},
3771 1 : };
3772 1 : a.set_ipv4(ip);
3773 1 : messenger_responder::pointer_t messenger(std::make_shared<messenger_responder>(
3774 : a
3775 1 : , ed::mode_t::MODE_PLAIN
3776 2 : , messenger_responder::sequence_t::SEQUENCE_ONE_MESSAGE));
3777 1 : ed::communicator::instance()->add_connection(messenger);
3778 1 : messenger_timer::pointer_t timer(std::make_shared<messenger_timer>(messenger));
3779 1 : ed::communicator::instance()->add_connection(timer);
3780 1 : messenger->set_timer(timer);
3781 1 : e->set_thread_done_callback([messenger, timer]()
3782 : {
3783 1 : ed::communicator::instance()->remove_connection(messenger);
3784 1 : ed::communicator::instance()->remove_connection(timer);
3785 1 : });
3786 1 : CATCH_REQUIRE(e->run());
3787 :
3788 1 : CATCH_REQUIRE_THROWS_MATCHES(
3789 : e->stop()
3790 : , std::runtime_error
3791 : , Catch::Matchers::ExceptionMessage("ppoll() timed out."));
3792 :
3793 : // if we exited because of our timer, then the test did not pass
3794 : //
3795 1 : CATCH_REQUIRE_FALSE(timer->timed_out_prima());
3796 :
3797 1 : CATCH_REQUIRE(s->get_exit_code() == -1);
3798 1 : }
3799 3 : CATCH_END_SECTION()
3800 :
3801 3 : CATCH_START_SECTION("check parameter with incorrect regex fails")
3802 : {
3803 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_regex_parameter_no_match.rprtr", g_program_regex_parameter_no_match));
3804 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
3805 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
3806 1 : p->parse_program();
3807 :
3808 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
3809 1 : e->start();
3810 1 : addr::addr a;
3811 1 : sockaddr_in ip = {
3812 : .sin_family = AF_INET,
3813 1 : .sin_port = htons(20002),
3814 : .sin_addr = {
3815 1 : .s_addr = htonl(0x7f000001),
3816 : },
3817 : .sin_zero = {},
3818 1 : };
3819 1 : a.set_ipv4(ip);
3820 1 : messenger_responder::pointer_t messenger(std::make_shared<messenger_responder>(
3821 : a
3822 1 : , ed::mode_t::MODE_PLAIN
3823 2 : , messenger_responder::sequence_t::SEQUENCE_ONE_MESSAGE));
3824 1 : ed::communicator::instance()->add_connection(messenger);
3825 1 : messenger_timer::pointer_t timer(std::make_shared<messenger_timer>(messenger));
3826 1 : ed::communicator::instance()->add_connection(timer);
3827 1 : messenger->set_timer(timer);
3828 1 : e->set_thread_done_callback([messenger, timer]()
3829 : {
3830 1 : ed::communicator::instance()->remove_connection(messenger);
3831 1 : ed::communicator::instance()->remove_connection(timer);
3832 1 : });
3833 1 : CATCH_REQUIRE(e->run());
3834 :
3835 1 : CATCH_REQUIRE_THROWS_MATCHES(
3836 : e->stop()
3837 : , std::runtime_error
3838 : , Catch::Matchers::ExceptionMessage("program_regex_parameter_no_match.rprtr:9: message expected parameter \"version\", set to \"1\", to match regex \"_[a-z]+\"."));
3839 :
3840 : // if we exited because of our timer, then the test did not pass
3841 : //
3842 1 : CATCH_REQUIRE_FALSE(timer->timed_out_prima());
3843 :
3844 1 : CATCH_REQUIRE(s->get_exit_code() == -1);
3845 1 : }
3846 3 : CATCH_END_SECTION()
3847 3 : }
3848 :
3849 :
3850 :
3851 : // vim: ts=4 sw=4 et
|