LCOV - code coverage report
Current view: top level - tests - catch_reporter_executor.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 97.0 % 2327 2257
Test Date: 2025-05-30 15:24:13 Functions: 97.8 % 45 44
Legend: Lines: hit not hit

            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/instruction_factory.h>
      35              : #include    <eventdispatcher/reporter/parser.h>
      36              : #include    <eventdispatcher/reporter/variable_address.h>
      37              : #include    <eventdispatcher/reporter/variable_array.h>
      38              : #include    <eventdispatcher/reporter/variable_floating_point.h>
      39              : #include    <eventdispatcher/reporter/variable_integer.h>
      40              : #include    <eventdispatcher/reporter/variable_list.h>
      41              : #include    <eventdispatcher/reporter/variable_regex.h>
      42              : #include    <eventdispatcher/reporter/variable_string.h>
      43              : #include    <eventdispatcher/reporter/variable_timestamp.h>
      44              : #include    <eventdispatcher/reporter/variable_void.h>
      45              : 
      46              : 
      47              : // libaddr
      48              : //
      49              : #include    <libaddr/addr_parser.h>
      50              : 
      51              : 
      52              : // eventdispatcher
      53              : //
      54              : #include    <eventdispatcher/communicator.h>
      55              : #include    <eventdispatcher/exception.h>
      56              : #include    <eventdispatcher/tcp_client_connection.h>
      57              : #include    <eventdispatcher/tcp_client_permanent_message_connection.h>
      58              : 
      59              : 
      60              : // snapdev
      61              : //
      62              : #include    <snapdev/gethostname.h>
      63              : 
      64              : 
      65              : // last include
      66              : //
      67              : #include    <snapdev/poison.h>
      68              : 
      69              : 
      70              : 
      71              : namespace
      72              : {
      73              : 
      74              : 
      75              : 
      76              : constexpr char const * const g_program_sleep_func =
      77              :     "call(label: func_sleep)\n"
      78              :     "exit(timeout: 1)\n"
      79              :     "label(name: func_sleep)\n"
      80              :     "sleep(seconds: 2.5)\n"
      81              :     "return()\n"
      82              : ;
      83              : 
      84              : constexpr char const * const g_program_sort_func =
      85              :     "set_variable(name: s1, value: 'hello')\n"
      86              :     "set_variable(name: s2, value: 'world')\n"
      87              :     "set_variable(name: s3, value: 'who')\n"
      88              :     "set_variable(name: s4, value: 'are')\n"
      89              :     "set_variable(name: s5, value: 'you?')\n"
      90              :     "sort(var1: s1, var2: s2, var3: s3, var4: s4, var5: s5)\n"
      91              : 
      92              :     "set_variable(name: i1, value: 506)\n"
      93              :     "set_variable(name: i2, value: 1003)\n"
      94              :     "set_variable(name: i3, value: 73)\n"
      95              :     "set_variable(name: i4, value: 1004)\n"
      96              :     "set_variable(name: i5, value: -3)\n"
      97              :     "sort(var1: i1, var2: i2, var3: i3, var4: i4, var5: i5)\n"
      98              : 
      99              :     "set_variable(name: f1, value: 50.6)\n"
     100              :     "set_variable(name: f2, value: -10.103)\n"
     101              :     "set_variable(name: f3, value: 73.5)\n"
     102              :     "set_variable(name: f4, value: 1.004)\n"
     103              :     "set_variable(name: f5, value: -0.3)\n"
     104              :     "sort(var1: f1, var2: f2, var3: f3, var4: f4, var5: f5)\n"
     105              : 
     106              :     "exit()\n"
     107              : ;
     108              : 
     109              : constexpr char const * const g_program_start_thread =
     110              :     "set_variable(name: test, value: 33)\n"
     111              :     "set_variable(name: test_copy_between_dollars, value: \"$${test}$\")\n"
     112              :     "run()\n"
     113              :     "set_variable(name: runner, value: 6.07)\n"
     114              :     "set_variable(name: runner_copy_as_is, value: \"runner = ${runner}\", type: string)\n"
     115              :     "set_variable(name: time_limit, value: @1713934141.107805991, type: timestamp)\n"
     116              :     "set_variable(name: time_limit_copy, value: \"limit: ${time_limit}\")\n"
     117              :     "set_variable(name: time_from_float, value: \"1713934141.107805991\", type: timestamp)\n"
     118              :     "set_variable(name: host_ip, value: <127.7.3.51>)\n"
     119              :     "set_variable(name: host_ip_copy, value: \"Host is at ${host_ip} address\")\n"
     120              :     "set_variable(name: time_and_host_ip, value: \"time ${time_limit} and address ${host_ip}...\")\n"
     121              :     "strlen(variable_name: length, string: ${time_and_host_ip})\n"
     122              : ;
     123              : 
     124              : constexpr char const * const g_program_start_thread_twice =
     125              :     "set_variable(name: test, value: 33)\n"
     126              :     "run()\n"
     127              :     "set_variable(name: runner, value: 6.07)\n"
     128              :     "run()\n" // second run() is forbidden
     129              : ;
     130              : 
     131              : constexpr char const * const g_program_verify_computation_integer =
     132              :     "set_variable(name: t01, value: 3)\n"
     133              : 
     134              :     "set_variable(name: t11, value: -3)\n"
     135              :     "set_variable(name: t12, value: +3)\n"
     136              : 
     137              :     "set_variable(name: t21, value: 3 + 2)\n"
     138              :     "set_variable(name: t22, value: -(3 + 2))\n"
     139              :     "set_variable(name: t23, value: 20 - 4)\n"
     140              :     "set_variable(name: t24, value: 3 * 2)\n"
     141              :     "set_variable(name: t25, value: 20 / 4)\n"
     142              :     "set_variable(name: t26, value: 27 % 11)\n"
     143              : 
     144              :     "set_variable(name: t31, value: 3 + 2 * 5)\n"
     145              :     "set_variable(name: t32, value: -7 + 15 / 3)\n"
     146              :     "set_variable(name: t33, value: +2 + 15 % 7)\n"
     147              : 
     148              :     "set_variable(name: t41, value: (3 + 2) * 5)\n"
     149              :     "set_variable(name: t42, value: (-7 + 15) / 3)\n"
     150              :     "set_variable(name: t43, value: (+2 + 15) % 7)\n"
     151              : ;
     152              : 
     153              : constexpr char const * const g_program_verify_computation_floating_point =
     154              :     "set_variable(name: t01, value: 3.01)\n"
     155              : 
     156              :     "set_variable(name: t11, value: -3.5)\n"
     157              :     "set_variable(name: t12, value: +3.2)\n"
     158              : 
     159              :     "set_variable(name: t21ff, value: 3.01 + 2.45)\n"
     160              :     "set_variable(name: t21if, value: 3 + 2.54)\n"
     161              :     "set_variable(name: t21fi, value: 3.01 + 2)\n"
     162              :     "set_variable(name: t22ff, value: -(3.5 + 2.5))\n"
     163              :     "set_variable(name: t22if, value: -(3 + 2.11))\n"
     164              :     "set_variable(name: t22fi, value: -(3.07 + 2))\n"
     165              :     "set_variable(name: t23ff, value: 20.07 - 4.13)\n"
     166              :     "set_variable(name: t23if, value: 20 - 4.78)\n"
     167              :     "set_variable(name: t23fi, value: 20.91 - 4)\n"
     168              :     "set_variable(name: t24ff, value: 3.41 * 2.14)\n"
     169              :     "set_variable(name: t24if, value: 3 * 2.67)\n"
     170              :     "set_variable(name: t24fi, value: 3.32 * 2)\n"
     171              :     "set_variable(name: t25ff, value: 20.83 / 4.07)\n"
     172              :     "set_variable(name: t25if, value: 20 / 4.4)\n"
     173              :     "set_variable(name: t25fi, value: 20.93 / 4)\n"
     174              :     "set_variable(name: t26ff, value: 27.27 % 11.11)\n"
     175              :     "set_variable(name: t26if, value: 27 % 11.88)\n"
     176              :     "set_variable(name: t26fi, value: 27.72 % 11)\n"
     177              : 
     178              :     "set_variable(name: t31fff, value: 3.03 + 2.2 * 5.9)\n"
     179              :     "set_variable(name: t31iff, value: 3 + 2.5 * 5.7)\n"
     180              :     "set_variable(name: t31fif, value: 3.2 + 2 * 5.3)\n"
     181              :     "set_variable(name: t31ffi, value: 3.07 + 2.28 * 5)\n"
     182              :     "set_variable(name: t31iif, value: 3 + 2 * 5.67)\n"
     183              :     "set_variable(name: t31ifi, value: 3 + 2.56 * 5)\n"
     184              :     "set_variable(name: t31fii, value: 3.33 + 2 * 5)\n"
     185              :     "set_variable(name: t32fff, value: -7.11 + 15.7 / 3.06)\n"
     186              :     "set_variable(name: t32iff, value: -7 + 15.25 / 3.31)\n"
     187              :     "set_variable(name: t32fif, value: -7.78 + 15 / 3.77)\n"
     188              :     "set_variable(name: t32ffi, value: -7.09 + 15.34 / 3)\n"
     189              :     "set_variable(name: t32iif, value: -7 + 15 / 3.30)\n"
     190              :     "set_variable(name: t32ifi, value: -7 + 15.09 / 3)\n"
     191              :     "set_variable(name: t32fii, value: -7.94 + 15 / 3)\n"
     192              :     "set_variable(name: t33fff, value: +2.21 + 15.16 % 7.8)\n"
     193              :     "set_variable(name: t33iff, value: +2 + 15.12 % 7.93)\n"
     194              :     "set_variable(name: t33fif, value: +2.58 + 15 % 7.63)\n"
     195              :     "set_variable(name: t33ffi, value: +2.12 + 15.09 % 7)\n"
     196              :     "set_variable(name: t33iif, value: +2 + 15 % 7.19)\n"
     197              :     "set_variable(name: t33ifi, value: +2 + 15.18 % 7)\n"
     198              :     "set_variable(name: t33fii, value: +2.17 + 15 % 7)\n"
     199              : 
     200              :     "set_variable(name: t41fff, value: (3.45 + 2.06) * 5.55)\n"
     201              :     "set_variable(name: t41iff, value: (3 + 2.17) * 5.07)\n"
     202              :     "set_variable(name: t41fif, value: (3.37 + 2) * 5.12)\n"
     203              :     "set_variable(name: t41ffi, value: (3.45 + 2.67) * 5)\n"
     204              :     "set_variable(name: t41iif, value: (3 + 2) * 5.3)\n"
     205              :     "set_variable(name: t41ifi, value: (3 + 2.9) * 5)\n"
     206              :     "set_variable(name: t41fii, value: (3.4 + 2) * 5)\n"
     207              :     "set_variable(name: t42fff, value: (-7.4 + 15.15) / 3.93)\n"
     208              :     "set_variable(name: t42iff, value: (-7 + 15.21) / 3.43)\n"
     209              :     "set_variable(name: t42fif, value: (-7.72 + 15) / 3.31)\n"
     210              :     "set_variable(name: t42ffi, value: (-7.43 + 15.89) / 3)\n"
     211              :     "set_variable(name: t42iif, value: (-7 + 15) / 3.4)\n"
     212              :     "set_variable(name: t42ifi, value: (-7 + 15.09) / 3)\n"
     213              :     "set_variable(name: t42fii, value: (-7.73 + 15) / 3)\n"
     214              :     "set_variable(name: t43fff, value: (+2.25 + 15.36) % 7.47)\n"
     215              :     "set_variable(name: t43iff, value: (+2 + 15.16) % 7.38)\n"
     216              :     "set_variable(name: t43fif, value: (+2.51 + 15) % 7.59)\n"
     217              :     "set_variable(name: t43ffi, value: (+2.4 + 15.3) % 7)\n"
     218              :     "set_variable(name: t43iif, value: (+2 + 15) % 7.0)\n"
     219              :     "set_variable(name: t43ifi, value: (+2 + 15.8) % 7)\n"
     220              :     "set_variable(name: t43fii, value: (+2.07 + 15) % 7)\n"
     221              : ;
     222              : 
     223              : constexpr char const * const g_program_verify_computation_timestamp =
     224              :     "set_variable(name: t01, value: @123 + 5)\n"
     225              :     "set_variable(name: t02, value: 33 + @123)\n"
     226              :     "set_variable(name: t03, value: @123 - 5)\n"
     227              :     "set_variable(name: t04, value: 33 - @123)\n"
     228              : 
     229              :     "set_variable(name: t11, value: @123 + 5.09)\n"
     230              :     "set_variable(name: t12, value: 33.501923821 + @123)\n"
     231              :     "set_variable(name: t13, value: @123 - 5.001)\n"
     232              :     "set_variable(name: t14, value: 333.98201992 - @123)\n"
     233              : 
     234              :     "set_variable(name: t21, value: -@123)\n"
     235              :     "set_variable(name: t22, value: +@123)\n"
     236              : 
     237              :     "set_variable(name: t31, value: @300.561 - @123.231)\n"
     238              :     "set_variable(name: t32, value: @34.3123 + @123.9984312)\n"
     239              : ;
     240              : 
     241              : constexpr char const * const g_program_verify_hex =
     242              :     "hex(variable_name: t01, value: 0x1a4fd2)\n"
     243              :     "hex(variable_name: t02, value: 0xabcdef, uppercase: 0)\n"
     244              :     "hex(variable_name: t03, value: 0xabcdef, uppercase: 1)\n"
     245              :     "hex(variable_name: t04, value: 1, width: 8)\n"
     246              :     "hex(variable_name: t05, value: 0xabcdef, uppercase: 1, width: 8)\n"
     247              : ;
     248              : 
     249              : constexpr char const * const g_program_verify_now =
     250              :     "now(variable_name: about_now)\n"
     251              :     "exit()\n"
     252              : ;
     253              : 
     254              : constexpr char const * const g_program_verify_max_pid =
     255              :     "max_pid(variable_name: top_pid)\n"
     256              :     "exit()\n"
     257              : ;
     258              : 
     259              : constexpr char const * const g_program_verify_random =
     260              :     "random(variable_name: any_number)\n"
     261              :     "random(variable_name: positive, negative: 0)\n"
     262              :     "random(variable_name: positive_or_negative, negative: 1)\n"
     263              :     "exit()\n"
     264              : ;
     265              : 
     266              : constexpr char const * const g_program_verify_hostname =
     267              :     "hostname(variable_name: host_name)\n"
     268              :     "exit()\n"
     269              : ;
     270              : 
     271              : constexpr char const * const g_program_verify_kill_number =
     272              :     "kill(signal: 18)\n"
     273              :     "exit()\n"
     274              : ;
     275              : 
     276              : constexpr char const * const g_program_verify_kill_identifier =
     277              :     "kill(signal: SIGCONT)\n"
     278              :     "exit()\n"
     279              : ;
     280              : 
     281              : constexpr char const * const g_program_verify_kill_string =
     282              :     "kill(signal: \"cont\")\n"
     283              :     "exit()\n"
     284              : ;
     285              : 
     286              : constexpr char const * const g_program_verify_kill_unsupported_timestamp =
     287              :     "kill(signal: @123.3342)\n"
     288              : 
     289              :     "exit(error_message: \"test is expected to fail before reaching this statement.\")\n"
     290              : ;
     291              : 
     292              : constexpr char const * const g_program_verify_kill_integer_too_large =
     293              :     "kill(signal: 100)\n"
     294              : 
     295              :     "exit(error_message: \"test is expected to fail before reaching this statement.\")\n"
     296              : ;
     297              : 
     298              : constexpr char const * const g_program_verify_kill_unknown_signal_name =
     299              :     "kill(signal: \"unknown\")\n"
     300              : 
     301              :     "exit(error_message: \"test is expected to fail before reaching this statement.\")\n"
     302              : ;
     303              : 
     304              : constexpr char const * const g_program_verify_computation_address =
     305              :     "set_variable(name: t01, value: <127.0.0.1> + 256)\n"
     306              :     "set_variable(name: t02, value: 256 + <192.168.3.57>)\n"
     307              :     "set_variable(name: t03, value: <172.131.4.1> - 256)\n"
     308              : 
     309              :     "set_variable(name: t11, value: <10.5.34.255> - <10.5.33.0>)\n"
     310              : ;
     311              : 
     312              : constexpr char const * const g_program_verify_computation_concatenation =
     313              :     "set_variable(name: t01, value: ident + ifier)\n"
     314              : 
     315              :     "set_variable(name: t11, value: 'single' + ' ' + 'string')\n"
     316              :     "set_variable(name: t12, value: 'single' + \" \" + 'string')\n"
     317              :     "set_variable(name: t13, value: 'single' + ' ' + \"string\")\n"
     318              :     "set_variable(name: t14, value: \"double\" + \" \" + \"string\")\n"
     319              : 
     320              :     "set_variable(name: t21, value: +identify)\n"
     321              :     "set_variable(name: t22, value: +'single string')\n"
     322              :     "set_variable(name: t23, value: +\"double string\")\n"
     323              : 
     324              :     "set_variable(name: t31, value: 'single' + 36)\n"
     325              :     "set_variable(name: t32, value: 258 + 'single')\n"
     326              :     "set_variable(name: t33, value: \"string\" + 102)\n"
     327              :     "set_variable(name: t34, value: 5005 + \"double\")\n"
     328              : 
     329              :     "set_variable(name: t41, value: 'single' + `[0-9]+`)\n"
     330              :     "set_variable(name: t42, value: `[0-9]+` + 'single')\n"
     331              :     "set_variable(name: t43, value: \"string\" + `[0-9]+`)\n"
     332              :     "set_variable(name: t44, value: `[0-9]+` + \"double\")\n"
     333              :     "set_variable(name: t45, value: 'a|b' + `[0-9]+`)\n"
     334              :     "set_variable(name: t46, value: `[0-9]+` + 'c{3,9}')\n"
     335              :     "set_variable(name: t47, value: \"[a-z]?\" + `[0-9]+`)\n"
     336              :     "set_variable(name: t48, value: `[0-9]+` + \"a?b?c?\")\n"
     337              :     "set_variable(name: t49, value: `[0-9]+` + `(a|b|c)?`)\n"
     338              : ;
     339              : 
     340              : constexpr char const * const g_program_verify_computation_string_repeat =
     341              :     "set_variable(name: t01, value: 'abc' * 3)\n"
     342              :     "set_variable(name: t02, value: \"xyz\" * 5)\n"
     343              :     "set_variable(name: t03, value: \"zero\" * 0)\n"
     344              :     "set_variable(name: t04, value: \"one\" * 1)\n"
     345              : ;
     346              : 
     347              : constexpr char const * const g_program_verify_variable_in_string =
     348              :     "set_variable(name: foo, value: 'abc')\n"
     349              :     "set_variable(name: bar, value: \"[${foo}]\")\n"
     350              : ;
     351              : 
     352              : constexpr char const * const g_program_accept_one_message =
     353              :     "run()\n"
     354              :     "listen(address: <127.0.0.1:20002>, connection_type: messenger)\n"
     355              :     "label(name: wait_message)\n"
     356              :     "clear_message()\n"
     357              :     "wait(timeout: 10.0, mode: wait)\n" // first wait reacts on connect(), second wait receives the REGISTER message
     358              :     "has_message()\n"
     359              :     "if(false: wait_message)\n"
     360              :     "show_message()\n"
     361              :     "verify_message(command: `^REGISTER$`, required_parameters: { service: responder, version: 1 }, optional_parameters: { commands: \"READY,HELP,STOP\" }, forbidden_parameters: { forbidden })\n"
     362              :     "save_parameter_value(parameter_name: command, variable_name: command)\n"
     363              :     "save_parameter_value(parameter_name: version, variable_name: register_version)\n"
     364              :     "save_parameter_value(parameter_name: service, variable_name: register_service, type: identifier)\n"
     365              :     "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"
     366              :     "wait(timeout: 10.0, mode: drain)\n"
     367              :     "disconnect()\n"
     368              :     "exit()\n"
     369              : ;
     370              : 
     371              : constexpr char const * const g_program_receive_unwanted_message =
     372              :     "run()\n"
     373              :     "listen(address: <127.0.0.1:20002>)\n"
     374              :     "label(name: wait_message)\n"
     375              :     "clear_message()\n"
     376              :     "wait(timeout: 10.0, mode: wait)\n"
     377              :     "has_message()\n"
     378              :     "if(false: wait_message)\n"
     379              :     "show_message()\n"
     380              :     "verify_message(command: REGISTER, required_parameters: { service: responder, version: `^[0-9]+$` }, optional_parameters: { commands: \"READY,HELP,STOP\" }, forbidden_parameters: { forbidden })\n"
     381              :     "save_parameter_value(parameter_name: version, variable_name: register_version, type: integer)\n"
     382              :     "send_message(command: READY, parameters: { version: 9 })\n"
     383              :     "print(message: \"nearly done\")\n"
     384              :     "exit(timeout: 2.5)\n"
     385              : ;
     386              : 
     387              : constexpr char const * const g_program_send_unsupported_message_parameter_type =
     388              :     "run()\n"
     389              :     "listen(address: <127.0.0.1:20002>)\n"
     390              :     "label(name: wait_message)\n"
     391              :     "clear_message()\n"
     392              :     "wait(timeout: 10.0, mode: wait)\n" // first wait reacts on connect(), second wait receives the REGISTER message
     393              :     "has_message()\n"
     394              :     "if(false: wait_message)\n"
     395              :     "show_message()\n"
     396              :     "verify_message(command: REGISTER, required_parameters: { service: responder, version: 1 }, optional_parameters: { commands: \"READY,HELP,STOP\" }, forbidden_parameters: { forbidden })\n"
     397              :     "save_parameter_value(parameter_name: version, variable_name: register_version, type: integer)\n"
     398              :     "send_message(command: READY, parameters: { status: 3.05 })\n" // floating point not yet supported
     399              :     "wait(timeout: 1.0, mode: drain)\n"
     400              : ;
     401              : 
     402              : constexpr char const * const g_program_send_invalid_parameter_value_type =
     403              :     "run()\n"
     404              :     "listen(address: <127.0.0.1:20002>)\n"
     405              :     "label(name: wait_message)\n"
     406              :     "clear_message()\n"
     407              :     "wait(timeout: 10.0, mode: wait)\n"
     408              :     "has_message()\n"
     409              :     "if(false: wait_message)\n"
     410              :     "show_message()\n"
     411              :     "verify_message(command: REGISTER, required_parameters: { service: responder, version: 1 }, optional_parameters: { commands: \"READY,HELP,STOP\" }, forbidden_parameters: { forbidden })\n"
     412              :     "save_parameter_value(parameter_name: service, variable_name: register_version, type: integer)\n" // service is not an integer
     413              :     "send_message(command: READY, parameters: { status: \"3.05\" })\n"
     414              :     "wait(timeout: 1.0, mode: drain)\n"
     415              : ;
     416              : 
     417              : constexpr char const * const g_program_save_parameter_of_type_timestamp =
     418              :     "run()\n"
     419              :     "listen(address: <127.0.0.1:20002>, connection_type: messenger)\n"
     420              :     "label(name: wait_message)\n"
     421              :     "wait(timeout: 10.0, mode: wait)\n"
     422              :     "has_message()\n"
     423              :     "if(false: wait_message)\n"
     424              :     "show_message()\n"
     425              :     "verify_message(command: REGISTER, required_parameters: { service: responder, version: 1 }, optional_parameters: { commands: \"READY,HELP,STOP\" }, forbidden_parameters: { forbidden })\n"
     426              :     "save_parameter_value(parameter_name: version, variable_name: register_version, type: integer)\n"
     427              :     "save_parameter_value(parameter_name: large_number, variable_name: default_integer, type: integer)\n"
     428              :     "send_message(command: READY, parameters: { status: \"3.05\", date: @1715440881.543723981 })\n"
     429              :     "clear_message()\n"
     430              :     "label(name: wait_second_message)\n"
     431              :     "wait(timeout: 10.0, mode: wait)\n"
     432              :     "has_message()\n"
     433              :     "if(false: wait_second_message)\n"
     434              :     "show_message()\n"
     435              :     "verify_message(command: TIMED, required_parameters: { now: `^[0-9]+(\\\\.[0-9]+)?$` } )\n"
     436              :     "save_parameter_value(parameter_name: now, variable_name: timed_value, type: timestamp)\n"
     437              :     "verify_message(command: TIMED, required_parameters: { now: ${timed_value} } )\n" // this time we try with a timestamp parameter
     438              :     "save_parameter_value(parameter_name: not_defined, variable_name: default_time, type: timestamp)\n"
     439              :     "exit()\n"
     440              : ;
     441              : 
     442              : constexpr char const * const g_program_save_parameter_with_unknown_type =
     443              :     "run()\n"
     444              :     "listen(address: <127.0.0.1:20002>)\n"
     445              :     "label(name: wait_message)\n"
     446              :     "clear_message()\n"
     447              :     "wait(timeout: 10.0, mode: wait)\n"
     448              :     "has_message()\n"
     449              :     "if(false: wait_message)\n"
     450              :     "show_message()\n"
     451              :     "verify_message(command: REGISTER, required_parameters: { service: responder, version: 1 }, optional_parameters: { commands: \"READY,HELP,STOP\" }, forbidden_parameters: { forbidden })\n"
     452              :     "save_parameter_value(parameter_name: service, variable_name: register_version, type: void)\n" // "void" is not a supported type here
     453              :     "send_message(command: READY, parameters: { status: \"3.05\" })\n"
     454              :     "wait(timeout: 1.0, mode: drain)\n"
     455              : ;
     456              : 
     457              : constexpr char const * const g_program_undefined_variable =
     458              :     "has_type(name: undefined_variable, type: void)\n"
     459              :     "if(unordered: it_worked)\n"
     460              :     "exit(error_message: \"undefined variable not properly detected.\")\n"
     461              :     "label(name: it_worked)\n"
     462              :     "exit()\n"
     463              : ;
     464              : 
     465              : constexpr char const * const g_program_integer_variable =
     466              :     "set_variable(name: my_int, value: 33)\n"
     467              :     "has_type(name: my_int, type: string)\n"
     468              :     "if(false: not_string)\n"
     469              :     "exit(error_message: \"integer variable detected as a string.\")\n"
     470              :     "label(name: not_string)\n"
     471              :     "has_type(name: my_int, type: integer)\n"
     472              :     "if(true: is_integer)\n"
     473              :     "exit(error_message: \"integer variable not properly detected as such.\")\n"
     474              :     "label(name: is_integer)\n"
     475              :     "exit()\n"
     476              : ;
     477              : 
     478              : constexpr char const * const g_program_string_variable =
     479              :     "set_variable(name: my_str, value: \"3.3\")\n"
     480              :     "has_type(name: my_str, type: floating_point)\n"
     481              :     "if(false: not_floating_point)\n"
     482              :     "exit(error_message: \"string variable detected as a floating_point.\")\n"
     483              :     "label(name: not_floating_point)\n"
     484              :     "has_type(name: my_str, type: string)\n"
     485              :     "if(true: is_string)\n"
     486              :     "exit(error_message: \"string variable not properly detected as such.\")\n"
     487              :     "label(name: is_string)\n"
     488              :     "exit()\n"
     489              : ;
     490              : 
     491              : constexpr char const * const g_program_if_variable =
     492              :     "if(variable: not_defined, unordered: not_defined_worked)\n"
     493              :     "exit(error_message: \"if(variable: <undefined>) failed test.\")\n"
     494              :     "label(name: not_defined_worked)\n"
     495              : 
     496              :     // >, >=, !=, true, ordered
     497              :     "set_variable(name: my_var, value: 5)\n"
     498              :     "if(variable: my_var, greater: positive_greater_int_worked)\n"
     499              :     "exit(error_message: \"if(variable: <positive integer> + greater) failed test.\")\n"
     500              :     "label(name: positive_greater_int_worked)\n"
     501              :     "if(variable: my_var, greater_or_equal: positive_greater_or_equal_int_worked)\n"
     502              :     "exit(error_message: \"if(variable: <positive integer> + greater_or_equal) failed test.\")\n"
     503              :     "label(name: positive_greater_or_equal_int_worked)\n"
     504              :     "if(variable: my_var, not_equal: positive_not_equal_int_worked)\n"
     505              :     "exit(error_message: \"if(variable: <positive integer> + not_equal) failed test.\")\n"
     506              :     "label(name: positive_not_equal_int_worked)\n"
     507              :     "if(variable: my_var, true: positive_true_int_worked)\n"
     508              :     "exit(error_message: \"if(variable: <positive integer> + true) failed test.\")\n"
     509              :     "label(name: positive_true_int_worked)\n"
     510              :     "if(variable: my_var, ordered: positive_ordered_int_worked)\n"
     511              :     "exit(error_message: \"if(variable: <positive integer> + ordered) failed test.\")\n"
     512              :     "label(name: positive_ordered_int_worked)\n"
     513              : 
     514              :     // <, <=, !=, true, ordered
     515              :     "set_variable(name: my_var, value: -5)\n"
     516              :     "if(variable: my_var, less: negative_less_int_worked)\n"
     517              :     "exit(error_message: \"if(variable: <negative integer> + less) failed test.\")\n"
     518              :     "label(name: negative_less_int_worked)\n"
     519              :     "if(variable: my_var, less_or_equal: negative_less_or_equal_int_worked)\n"
     520              :     "exit(error_message: \"if(variable: <negative integer> + less_or_equal) failed test.\")\n"
     521              :     "label(name: negative_less_or_equal_int_worked)\n"
     522              :     "if(variable: my_var, not_equal: negative_not_equal_int_worked)\n"
     523              :     "exit(error_message: \"if(variable: <negative integer> + not_equal) failed test.\")\n"
     524              :     "label(name: negative_not_equal_int_worked)\n"
     525              :     "if(variable: my_var, true: negative_true_int_worked)\n"
     526              :     "exit(error_message: \"if(variable: <negative integer> + true) failed test.\")\n"
     527              :     "label(name: negative_true_int_worked)\n"
     528              :     "if(variable: my_var, ordered: negative_ordered_int_worked)\n"
     529              :     "exit(error_message: \"if(variable: <negative integer> + ordered) failed test.\")\n"
     530              :     "label(name: negative_ordered_int_worked)\n"
     531              : 
     532              :     // ==, false, ordered
     533              :     "set_variable(name: my_var, value: 0)\n"
     534              :     "if(variable: my_var, equal: zero_equal_int_worked)\n"
     535              :     "exit(error_message: \"if(variable: <zero integer> + equal) failed test.\")\n"
     536              :     "label(name: zero_equal_int_worked)\n"
     537              :     "if(variable: my_var, less_or_equal: zero_less_or_equal_int_worked)\n"
     538              :     "exit(error_message: \"if(variable: <negative integer> + less_or_equal) failed test.\")\n"
     539              :     "label(name: zero_less_or_equal_int_worked)\n"
     540              :     "if(variable: my_var, greater_or_equal: zero_greater_or_equal_int_worked)\n"
     541              :     "exit(error_message: \"if(variable: <negative integer> + greater_or_equal) failed test.\")\n"
     542              :     "label(name: zero_greater_or_equal_int_worked)\n"
     543              :     "if(variable: my_var, false: zero_false_int_worked)\n"
     544              :     "exit(error_message: \"if(variable: <negative integer> + false) failed test.\")\n"
     545              :     "label(name: zero_false_int_worked)\n"
     546              :     "if(variable: my_var, ordered: zero_ordered_int_worked)\n"
     547              :     "exit(error_message: \"if(variable: <negative integer> + ordered) failed test.\")\n"
     548              :     "label(name: zero_ordered_int_worked)\n"
     549              : 
     550              :     // >, >=, !=, true, ordered
     551              :     "set_variable(name: my_var, value: 7.3)\n"
     552              :     "if(variable: my_var, greater: positive_greater_flt_worked)\n"
     553              :     "exit(error_message: \"if(variable: <positive floating point> + greater) failed test.\")\n"
     554              :     "label(name: positive_greater_flt_worked)\n"
     555              :     "if(variable: my_var, greater_or_equal: positive_greater_or_equal_flt_worked)\n"
     556              :     "exit(error_message: \"if(variable: <positive floating point> + greater_or_equal) failed test.\")\n"
     557              :     "label(name: positive_greater_or_equal_flt_worked)\n"
     558              :     "if(variable: my_var, not_equal: positive_not_equal_flt_worked)\n"
     559              :     "exit(error_message: \"if(variable: <positive floating point> + not_equal) failed test.\")\n"
     560              :     "label(name: positive_not_equal_flt_worked)\n"
     561              :     "if(variable: my_var, true: positive_true_flt_worked)\n"
     562              :     "exit(error_message: \"if(variable: <positive floating point> + true) failed test.\")\n"
     563              :     "label(name: positive_true_flt_worked)\n"
     564              :     "if(variable: my_var, ordered: positive_ordered_flt_worked)\n"
     565              :     "exit(error_message: \"if(variable: <positive floating point> + ordered) failed test.\")\n"
     566              :     "label(name: positive_ordered_flt_worked)\n"
     567              : 
     568              :     // <, <=, !=, true, ordered
     569              :     "set_variable(name: my_var, value: -7.3)\n"
     570              :     "if(variable: my_var, less: negative_less_flt_worked)\n"
     571              :     "exit(error_message: \"if(variable: <negative floating point> + less) failed test.\")\n"
     572              :     "label(name: negative_less_flt_worked)\n"
     573              :     "if(variable: my_var, less_or_equal: negative_less_or_equal_flt_worked)\n"
     574              :     "exit(error_message: \"if(variable: <negative integer> + less_or_equal) failed test.\")\n"
     575              :     "label(name: negative_less_or_equal_flt_worked)\n"
     576              :     "if(variable: my_var, not_equal: negative_not_equal_flt_worked)\n"
     577              :     "exit(error_message: \"if(variable: <negative integer> + not_equal) failed test.\")\n"
     578              :     "label(name: negative_not_equal_flt_worked)\n"
     579              :     "if(variable: my_var, true: negative_true_flt_worked)\n"
     580              :     "exit(error_message: \"if(variable: <negative integer> + true) failed test.\")\n"
     581              :     "label(name: negative_true_flt_worked)\n"
     582              :     "if(variable: my_var, ordered: negative_ordered_flt_worked)\n"
     583              :     "exit(error_message: \"if(variable: <negative integer> + ordered) failed test.\")\n"
     584              :     "label(name: negative_ordered_flt_worked)\n"
     585              : 
     586              :     // ==, false, ordered
     587              :     "set_variable(name: my_var, value: 0.0)\n"
     588              :     "if(variable: my_var, equal: zero_equal_flt_worked)\n"
     589              :     "exit(error_message: \"if(variable: <zero floating point> + equal) failed test.\")\n"
     590              :     "label(name: zero_equal_flt_worked)\n"
     591              :     "if(variable: my_var, less_or_equal: zero_less_or_equal_flt_worked)\n"
     592              :     "exit(error_message: \"if(variable: <negative integer> + less_or_equal) failed test.\")\n"
     593              :     "label(name: zero_less_or_equal_flt_worked)\n"
     594              :     "if(variable: my_var, greater_or_equal: zero_greater_or_equal_flt_worked)\n"
     595              :     "exit(error_message: \"if(variable: <negative integer> + greater_or_equal) failed test.\")\n"
     596              :     "label(name: zero_greater_or_equal_flt_worked)\n"
     597              :     "if(variable: my_var, false: zero_false_flt_worked)\n"
     598              :     "exit(error_message: \"if(variable: <negative integer> + false) failed test.\")\n"
     599              :     "label(name: zero_false_flt_worked)\n"
     600              :     "if(variable: my_var, ordered: zero_ordered_flt_worked)\n"
     601              :     "exit(error_message: \"if(variable: <negative integer> + ordered) failed test.\")\n"
     602              :     "label(name: zero_ordered_flt_worked)\n"
     603              : 
     604              :     // unordered
     605              :     "set_variable(name: my_var, value: NaN)\n"
     606              :     "if(variable: my_var, unordered: unordered_flt_worked)\n"
     607              :     "exit(error_message: \"if(variable: <unordered floating point>) failed test.\")\n"
     608              :     "label(name: unordered_flt_worked)\n"
     609              : 
     610              :     "exit()\n"
     611              : ;
     612              : 
     613              : constexpr char const * const g_program_compare_and_if =
     614              :     // integer greater/less
     615              :     "set_variable(name: a, value: 13)\n"
     616              :     "set_variable(name: b, value: 10)\n"
     617              :     "compare(expression: ${a} <=> ${b})\n"
     618              :     "if(greater: integer_greater)\n"
     619              :     "exit(error_message: \"if(greater: 13 <=> 10) failed test.\")\n"
     620              :     "label(name: integer_greater)\n"
     621              : 
     622              :     "compare(expression: ${b} <=> ${a})\n"
     623              :     "if(less: integer_less)\n"
     624              :     "exit(error_message: \"if(less: 10 <=> 13) failed test.\")\n"
     625              :     "label(name: integer_less)\n"
     626              : 
     627              :     "compare(expression: ${a} <=> ${a})\n"
     628              :     "if(equal: integer_equal)\n"
     629              :     "exit(error_message: \"if(equal: 13 <=> 13) failed test.\")\n"
     630              :     "label(name: integer_equal)\n"
     631              : 
     632              :     // floating point greater/less
     633              :     "set_variable(name: c, value: 13.41)\n"
     634              :     "set_variable(name: d, value: 9.05)\n"
     635              :     "compare(expression: ${c} <=> ${d})\n"
     636              :     "if(greater: floating_point_greater)\n"
     637              :     "exit(error_message: \"if(greater: 13.41 <=> 9.05) failed test.\")\n"
     638              :     "label(name: floating_point_greater)\n"
     639              : 
     640              :     "compare(expression: ${d} <=> ${c})\n"
     641              :     "if(less: floating_point_less)\n"
     642              :     "exit(error_message: \"if(less: 9.05 <=> 13.41) failed test.\")\n"
     643              :     "label(name: floating_point_less)\n"
     644              : 
     645              :     "compare(expression: ${d} <=> ${d})\n"
     646              :     "if(equal: floating_point_equal)\n"
     647              :     "exit(error_message: \"if(equal: 9.05 <=> 9.05) failed test.\")\n"
     648              :     "label(name: floating_point_equal)\n"
     649              : 
     650              :     // floating point vs integer greater/less
     651              :     "set_variable(name: c2, value: 13.0)\n"
     652              :     "set_variable(name: d2, value: 10.0)\n"
     653              :     "compare(expression: ${a} <=> ${d})\n"
     654              :     "if(greater: integer_floating_point_greater)\n"
     655              :     "exit(error_message: \"if(greater: 13 <=> 9.05) failed test.\")\n"
     656              :     "label(name: integer_floating_point_greater)\n"
     657              : 
     658              :     "compare(expression: ${d} <=> ${b})\n"
     659              :     "if(less: floating_point_integer_less)\n"
     660              :     "exit(error_message: \"if(less: 9.05 <=> 10) failed test.\")\n"
     661              :     "label(name: floating_point_integer_less)\n"
     662              : 
     663              :     "compare(expression: ${d2} <=> ${b})\n"
     664              :     "if(equal: floating_point_integer_equal)\n"
     665              :     "exit(error_message: \"if(equal: 10.0 <=> 10) failed test.\")\n"
     666              :     "label(name: floating_point_integer_equal)\n"
     667              : 
     668              :     "compare(expression: ${a} <=> ${c2})\n"
     669              :     "if(equal: integer_floating_point_equal)\n"
     670              :     "exit(error_message: \"if(equal: 10 <=> 10.0) failed test.\")\n"
     671              :     "label(name: integer_floating_point_equal)\n"
     672              : 
     673              :     "compare(expression: ${b} <=> ${c2})\n"
     674              :     "if(less: integer_floating_point_less)\n"
     675              :     "exit(error_message: \"if(less: 10 <=> 13.0) failed test.\")\n"
     676              :     "label(name: integer_floating_point_less)\n"
     677              : 
     678              :     "compare(expression: ${c} <=> ${a})\n"
     679              :     "if(greater: floating_point_integer_greater)\n"
     680              :     "exit(error_message: \"if(greater: 13.41 <=> 13) failed test.\")\n"
     681              :     "label(name: floating_point_integer_greater)\n"
     682              : 
     683              :     // timestamp greater/less (same as integers)
     684              :     "now(variable_name: now)\n"
     685              :     "set_variable(name: e, value: ${now} + 0.3)\n"
     686              :     "set_variable(name: f, value: ${now} - 0.05)\n"
     687              :     "compare(expression: ${e} <=> ${f})\n"
     688              :     "if(greater: timestamp_greater)\n"
     689              :     "exit(error_message: \"if(greater: now + 0.3 <=> now - 0x05) failed test.\")\n"
     690              :     "label(name: timestamp_greater)\n"
     691              : 
     692              :     "compare(expression: ${f} <=> ${e})\n"
     693              :     "if(less: timestamp_less)\n"
     694              :     "exit(error_message: \"if(less: now - 0.05 <=> now + 0.3) failed test.\")\n"
     695              :     "label(name: timestamp_less)\n"
     696              : 
     697              :     "compare(expression: ${f} <=> ${f})\n"
     698              :     "if(equal: timestamp_equal)\n"
     699              :     "exit(error_message: \"if(equal: now - 0.05 <=> now - 0.05) failed test.\")\n"
     700              :     "label(name: timestamp_equal)\n"
     701              : 
     702              :     // double strings greater/less/equal
     703              :     "set_variable(name: g, value: \"str9\")\n"
     704              :     "set_variable(name: h, value: \"str2\")\n"
     705              :     "compare(expression: ${g} <=> ${h})\n"
     706              :     "if(greater: double_string_greater)\n"
     707              :     "exit(error_message: \"if(greater: \\\"str9\\\" <=> \\\"str2\\\") failed test.\")\n"
     708              :     "label(name: double_string_greater)\n"
     709              : 
     710              :     "compare(expression: ${h} <=> ${g})\n"
     711              :     "if(less: double_string_less)\n"
     712              :     "exit(error_message: \"if(less: \\\"str2\\\" <=> \\\"str9\\\") failed test.\")\n"
     713              :     "label(name: double_string_less)\n"
     714              : 
     715              :     "compare(expression: ${h} <=> ${h})\n"
     716              :     "if(equal: double_string_equal)\n"
     717              :     "exit(error_message: \"if(equal: \\\"str2\\\" <=> \\\"str2\\\") failed test.\")\n"
     718              :     "label(name: double_string_equal)\n"
     719              : 
     720              :     // single strings greater/less
     721              :     "set_variable(name: i, value: 'str8')\n"
     722              :     "set_variable(name: j, value: 'str5')\n"
     723              :     "compare(expression: ${i} <=> ${j})\n"
     724              :     "if(greater: single_string_greater)\n"
     725              :     "exit(error_message: \"if(greater: 'str9' <=> 'str2') failed test.\")\n"
     726              :     "label(name: single_string_greater)\n"
     727              : 
     728              :     "compare(expression: ${j} <=> ${i})\n"
     729              :     "if(less: single_string_less)\n"
     730              :     "exit(error_message: \"if(less: 'str2' <=> 'str9') failed test.\")\n"
     731              :     "label(name: single_string_less)\n"
     732              : 
     733              :     // mixed strings greater/less
     734              :     "compare(expression: ${g} <=> ${j})\n"
     735              :     "if(greater: mixed_string_greater)\n"
     736              :     "exit(error_message: \"if(greater: \\\"str9\\\" <=> 'str5') failed test.\")\n"
     737              :     "label(name: mixed_string_greater)\n"
     738              : 
     739              :     "compare(expression: ${i} <=> ${g})\n"
     740              :     "if(less: mixed_string_less)\n"
     741              :     "exit(error_message: \"if(less: 'str8' <=> \\\"str9\\\") failed test.\")\n"
     742              :     "label(name: mixed_string_less)\n"
     743              : 
     744              :     // address greater/less
     745              :     "set_variable(name: k, value: <127.0.0.100>)\n"
     746              :     "set_variable(name: l, value: <10.127.0.100>)\n"
     747              :     "compare(expression: ${k} <=> ${l})\n"
     748              :     "if(greater: address_greater)\n"
     749              :     "exit(error_message: \"if(greater: <127.0.0.100> <=> <10.127.0.100>) failed test.\")\n"
     750              :     "label(name: address_greater)\n"
     751              : 
     752              :     "compare(expression: ${l} <=> ${k})\n"
     753              :     "if(less: address_less)\n"
     754              :     "exit(error_message: \"if(less: <10.127.0.100> <=> <127.0.0.100>) failed test.\")\n"
     755              :     "label(name: address_less)\n"
     756              : 
     757              :     "compare(expression: ${l} <=> ${l})\n"
     758              :     "if(equal: address_equal)\n"
     759              :     "exit(error_message: \"if(equal: <10.127.0.100> <=> <10.127.0.100>) failed test.\")\n"
     760              :     "label(name: address_equal)\n"
     761              : 
     762              :     "exit()\n"
     763              : ;
     764              : 
     765              : constexpr char const * const g_program_compare_with_incompatible_types =
     766              :     // cannot compare an integer vs string
     767              :     "set_variable(name: a, value: 13)\n"
     768              :     "set_variable(name: b, value: 'a string')\n"
     769              :     "compare(expression: ${a} <=> ${b})\n"
     770              : 
     771              :     "exit(error_message: \"test is expected to fail before reaching this statement.\")\n"
     772              : ;
     773              : 
     774              : constexpr char const * const g_program_compare_with_non_integer =
     775              :     // compare expression must be an integer
     776              :     "compare(expression: 'string')\n"
     777              : 
     778              :     "exit(error_message: \"test is expected to fail before reaching this statement.\")\n"
     779              : ;
     780              : 
     781              : constexpr char const * const g_program_compare_with_bad_positive_integer =
     782              :     // compare expression must be between -2 and +1
     783              :     "compare(expression: 5)\n"
     784              : 
     785              :     "exit(error_message: \"test is expected to fail before reaching this statement.\")\n"
     786              : ;
     787              : 
     788              : constexpr char const * const g_program_compare_with_bad_negative_integer =
     789              :     // compare expression must be between -2 and +1
     790              :     "compare(expression: -10)\n"
     791              : 
     792              :     "exit(error_message: \"test is expected to fail before reaching this statement.\")\n"
     793              : ;
     794              : 
     795              : constexpr char const * const g_program_print_message =
     796              :     "print(message: \"testing print()\")\n"
     797              :     "exit()\n"
     798              : ;
     799              : 
     800              : constexpr char const * const g_program_error_message =
     801              :     "exit(error_message: \"testing exit with an error\")\n"
     802              : ;
     803              : 
     804              : constexpr char const * const g_program_no_condition =
     805              :     "if(true: exit)\n"
     806              :     "label(name: exit)\n"
     807              : ;
     808              : 
     809              : constexpr char const * const g_program_two_listen =
     810              :     "listen(address: <127.0.0.1:20002>)\n"
     811              :     "listen(address: <127.0.0.1:20003>)\n"
     812              : ;
     813              : 
     814              : constexpr char const * const g_program_label_bad_type =
     815              :     "label(name: 123)\n"
     816              : ;
     817              : 
     818              : constexpr char const * const g_program_exit_bad_type =
     819              :     "exit(error_message: 12.3)\n"
     820              : ;
     821              : 
     822              : constexpr char const * const g_program_unsupported_addition_address_address =
     823              :     "set_variable(name: bad, value: <127.0.0.1:80> + <127.0.1.5:81>)\n"
     824              : ;
     825              : 
     826              : constexpr char const * const g_program_unsupported_addition_address_string =
     827              :     "set_variable(name: bad, value: <127.0.0.1:80> + '127.0.1.5:81')\n"
     828              : ;
     829              : 
     830              : constexpr char const * const g_program_unsupported_addition_string_address =
     831              :     "set_variable(name: bad, value: '127.0.0.1:80' + <127.0.1.5:81>)\n"
     832              : ;
     833              : 
     834              : constexpr char const * const g_program_unsupported_addition_address_identifier =
     835              :     "set_variable(name: bad, value: <127.0.0.1:80> + alpha)\n"
     836              : ;
     837              : 
     838              : constexpr char const * const g_program_unsupported_addition_identifier_address =
     839              :     "set_variable(name: bad, value: beta + <127.0.1.5:81>)\n"
     840              : ;
     841              : 
     842              : constexpr char const * const g_program_unsupported_addition_identifier_string =
     843              :     "set_variable(name: bad, value: this + '127.0.1.5:81')\n"
     844              : ;
     845              : 
     846              : constexpr char const * const g_program_unsupported_addition_string_identifier =
     847              :     "set_variable(name: bad, value: '127.0.0.1:80' + that)\n"
     848              : ;
     849              : 
     850              : constexpr char const * const g_program_unsupported_subtraction_address_string =
     851              :     "set_variable(name: bad, value: <127.0.0.1:80> - '127.0.1.5:81')\n"
     852              : ;
     853              : 
     854              : constexpr char const * const g_program_unsupported_subtraction_string_address =
     855              :     "set_variable(name: bad, value: '127.0.0.1:80' - <127.0.1.5:81>)\n"
     856              : ;
     857              : 
     858              : constexpr char const * const g_program_unsupported_subtraction_address_identifier =
     859              :     "set_variable(name: bad, value: <127.0.0.1:80> - alpha)\n"
     860              : ;
     861              : 
     862              : constexpr char const * const g_program_unsupported_subtraction_identifier_address =
     863              :     "set_variable(name: bad, value: beta - <127.0.1.5:81>)\n"
     864              : ;
     865              : 
     866              : constexpr char const * const g_program_unsupported_subtraction_identifier_string =
     867              :     "set_variable(name: bad, value: this - '127.0.1.5:81')\n"
     868              : ;
     869              : 
     870              : constexpr char const * const g_program_unsupported_subtraction_string_identifier =
     871              :     "set_variable(name: bad, value: '127.0.0.1:80' - that)\n"
     872              : ;
     873              : 
     874              : constexpr char const * const g_program_unsupported_multiplication_address_address =
     875              :     "set_variable(name: bad, value: <127.0.0.1:80> * <192.168.2.2:443>)\n"
     876              : ;
     877              : 
     878              : constexpr char const * const g_program_unsupported_multiplication_address_string =
     879              :     "set_variable(name: bad, value: <127.0.0.1:80> * 'invalid')\n"
     880              : ;
     881              : 
     882              : constexpr char const * const g_program_unsupported_multiplication_string_address =
     883              :     "set_variable(name: bad, value: 'invalid' * <127.0.0.1:80>)\n"
     884              : ;
     885              : 
     886              : constexpr char const * const g_program_unsupported_multiplication_address_identifier =
     887              :     "set_variable(name: bad, value: <127.0.0.1:80> * invalid)\n"
     888              : ;
     889              : 
     890              : constexpr char const * const g_program_unsupported_multiplication_identifier_address =
     891              :     "set_variable(name: bad, value: invalid * <127.0.0.1:80>)\n"
     892              : ;
     893              : 
     894              : constexpr char const * const g_program_unsupported_multiplication_identifier_string =
     895              :     "set_variable(name: bad, value: 'invalid' * invalid)\n"
     896              : ;
     897              : 
     898              : constexpr char const * const g_program_unsupported_multiplication_string_identifier =
     899              :     "set_variable(name: bad, value: invalid * \"invalid\")\n"
     900              : ;
     901              : 
     902              : constexpr char const * const g_program_unsupported_multiplication_string_string =
     903              :     "set_variable(name: bad, value: 'invalid' * \"invalid\")\n"
     904              : ;
     905              : 
     906              : constexpr char const * const g_program_unsupported_multiplication_identifier_identifier =
     907              :     "set_variable(name: bad, value: invalid * not_valid)\n"
     908              : ;
     909              : 
     910              : constexpr char const * const g_program_unsupported_division_address_address =
     911              :     "set_variable(name: bad, value: <127.0.0.1:80> / <192.168.2.2:443>)\n"
     912              : ;
     913              : 
     914              : constexpr char const * const g_program_unsupported_division_address_string =
     915              :     "set_variable(name: bad, value: <127.0.0.1:80> / 'invalid')\n"
     916              : ;
     917              : 
     918              : constexpr char const * const g_program_unsupported_division_string_address =
     919              :     "set_variable(name: bad, value: 'invalid' / <127.0.0.1:80>)\n"
     920              : ;
     921              : 
     922              : constexpr char const * const g_program_unsupported_division_address_identifier =
     923              :     "set_variable(name: bad, value: <127.0.0.1:80> / invalid)\n"
     924              : ;
     925              : 
     926              : constexpr char const * const g_program_unsupported_division_identifier_address =
     927              :     "set_variable(name: bad, value: invalid / <127.0.0.1:80>)\n"
     928              : ;
     929              : 
     930              : constexpr char const * const g_program_unsupported_division_identifier_string =
     931              :     "set_variable(name: bad, value: 'invalid' / invalid)\n"
     932              : ;
     933              : 
     934              : constexpr char const * const g_program_unsupported_division_string_identifier =
     935              :     "set_variable(name: bad, value: invalid / \"invalid\")\n"
     936              : ;
     937              : 
     938              : constexpr char const * const g_program_unsupported_division_string_string =
     939              :     "set_variable(name: bad, value: 'invalid' / \"invalid\")\n"
     940              : ;
     941              : 
     942              : constexpr char const * const g_program_unsupported_division_identifier_identifier =
     943              :     "set_variable(name: bad, value: invalid / not_valid)\n"
     944              : ;
     945              : 
     946              : constexpr char const * const g_program_unsupported_modulo_address_address =
     947              :     "set_variable(name: bad, value: <127.0.0.1:80> % <192.168.2.2:443>)\n"
     948              : ;
     949              : 
     950              : constexpr char const * const g_program_unsupported_modulo_address_string =
     951              :     "set_variable(name: bad, value: <127.0.0.1:80> % 'invalid')\n"
     952              : ;
     953              : 
     954              : constexpr char const * const g_program_unsupported_modulo_string_address =
     955              :     "set_variable(name: bad, value: 'invalid' % <127.0.0.1:80>)\n"
     956              : ;
     957              : 
     958              : constexpr char const * const g_program_unsupported_modulo_address_identifier =
     959              :     "set_variable(name: bad, value: <127.0.0.1:80> % invalid)\n"
     960              : ;
     961              : 
     962              : constexpr char const * const g_program_unsupported_modulo_identifier_address =
     963              :     "set_variable(name: bad, value: invalid % <127.0.0.1:80>)\n"
     964              : ;
     965              : 
     966              : constexpr char const * const g_program_unsupported_modulo_identifier_string =
     967              :     "set_variable(name: bad, value: invalid % \"invalid\")\n"
     968              : ;
     969              : 
     970              : constexpr char const * const g_program_unsupported_modulo_string_identifier =
     971              :     "set_variable(name: bad, value: 'invalid' % invalid)\n"
     972              : ;
     973              : 
     974              : constexpr char const * const g_program_unsupported_modulo_string_string =
     975              :     "set_variable(name: bad, value: 'invalid' % \"invalid\")\n"
     976              : ;
     977              : 
     978              : constexpr char const * const g_program_unsupported_modulo_identifier_identifier =
     979              :     "set_variable(name: bad, value: invalid % not_valid)\n"
     980              : ;
     981              : 
     982              : constexpr char const * const g_program_unsupported_negation_single_string =
     983              :     "set_variable(name: bad, value: -'string')\n"
     984              : ;
     985              : 
     986              : constexpr char const * const g_program_unsupported_negation_double_string =
     987              :     "set_variable(name: bad, value: -\"string\")\n"
     988              : ;
     989              : 
     990              : constexpr char const * const g_program_unsupported_negation_address =
     991              :     "set_variable(name: bad, value: -<127.0.0.1:80>)\n"
     992              : ;
     993              : 
     994              : constexpr char const * const g_program_unterminated_double_string_variable =
     995              :     "set_variable(name: my_var, value: \"blah\")\n"
     996              :     "set_variable(name: missing_close, value: \"ref. ${my_var\")\n"
     997              : ;
     998              : 
     999              : constexpr char const * const g_program_regex_in_double_string_variable =
    1000              :     "set_variable(name: my_regex, value: `[a-z]+`)\n"
    1001              :     "set_variable(name: missing_close, value: \"ref. ${my_regex}\")\n"
    1002              : ;
    1003              : 
    1004              : constexpr char const * const g_program_primary_variable_references =
    1005              :     "set_variable(name: my_string_var, value: \"foo\")\n"
    1006              :     "set_variable(name: longer_string_var, value: ${my_string_var})\n"
    1007              :     "set_variable(name: my_integer_var, value: 41)\n"
    1008              :     "set_variable(name: longer_integer_var, value: ${my_integer_var})\n"
    1009              :     "set_variable(name: my_floating_point_var, value: 303.601)\n"
    1010              :     "set_variable(name: longer_floating_point_var, value: ${my_floating_point_var})\n"
    1011              :     "set_variable(name: my_identifier_var, value: bar)\n"
    1012              :     "set_variable(name: longer_identifier_var, value: ${my_identifier_var})\n"
    1013              :     "set_variable(name: my_regex_var, value: `^[regex]$`)\n"
    1014              :     "set_variable(name: longer_regex_var, value: ${my_regex_var})\n"
    1015              :     "set_variable(name: my_address_var, value: <10.12.14.16:89>)\n"
    1016              :     "set_variable(name: longer_address_var, value: ${my_address_var})\n"
    1017              :     "set_variable(name: my_timestamp_var, value: @1714241733.419438123)\n"
    1018              :     "set_variable(name: longer_timestamp_var, value: ${my_timestamp_var})\n"
    1019              : ;
    1020              : 
    1021              : constexpr char const * const g_program_raw_tcp_connection =
    1022              :     "run()\n"
    1023              :     "listen(address: <127.0.0.1:20002>, connection_type: tcp)\n"
    1024              :     "label(name: wait_next_message)\n"
    1025              :     "clear_data()\n"
    1026              :     "label(name: wait_data)\n"
    1027              :     "wait(timeout: 12, mode: wait)\n"
    1028              :     "has_data(min_size: 4)\n"
    1029              :     "if(false: wait_data)\n"
    1030              :     "show_data(size: 4)\n"
    1031              :     "verify_data(values: [ 0x50, 0x49, 0x4E, 0x47 ])\n"     // PING
    1032              :     "show_data(size: 4)\n" // this will display <empty>
    1033              :     "has_data(min_size: 1)\n"
    1034              :     "if(true: unexpected_data)\n"
    1035              :     "send_data(values: [ 0x50, 0x4F, 0x4E, 0x47 ])\n"       // PONG
    1036              :     "wait(timeout: 10, mode: drain)\n"
    1037              :     "disconnect()\n"
    1038              :     "exit()\n"
    1039              :     "label(name: unexpected_data)\n"
    1040              :     "exit(error_message: \"found data when there should be none after the verify_data()\")\n"
    1041              : ;
    1042              : 
    1043              : constexpr char const * const g_program_prinbee_binary_message =
    1044              :     "run()\n"
    1045              :     "listen(address: <127.0.0.1:20002>, connection_type: tcp)\n"
    1046              :     "label(name: wait_next_message)\n"
    1047              :     "clear_data()\n"
    1048              :     "label(name: wait_data)\n"
    1049              :     "wait(timeout: 12, mode: wait)\n"
    1050              :     "has_data(min_size: 4)\n"
    1051              :     "if(false: wait_data)\n"
    1052              :     "show_data(size: 24)\n"
    1053              :     //                     magic (bm)   version  flags  name (PING)              size                     CRC16 x 2 (fake here)   data
    1054              :     "verify_data(values: [ 0x62, 0x6D,  0x01,    0x00,  0x50, 0x49, 0x4E, 0x47,  0x08, 0x00, 0x00, 0x00,  0xAA, 0x55, 0xEE, 0x77, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF ])\n"
    1055              :     "show_data(size: 24)\n" // this will display <empty>
    1056              :     "has_data(min_size: 1)\n"
    1057              :     "if(true: unexpected_data)\n"
    1058              :     // reply with a PONG and no data (size = 0)
    1059              :     "send_data(values: [ 0x62, 0x6D,  0x01,  0x00,  0x50, 0x4F, 0x4E, 0x47,  0x00, 0x00, 0x00, 0x00,  0x55, 0xAA, 0x33, 0xCC ])\n"
    1060              :     "wait(timeout: 10, mode: drain)\n"
    1061              :     "disconnect()\n"
    1062              :     "exit()\n"
    1063              :     "label(name: unexpected_data)\n"
    1064              :     "exit(error_message: \"found data when there should be none after the verify_data()\")\n"
    1065              : ;
    1066              : 
    1067              : constexpr char const * const g_program_raw_tcp_connection_read_too_large =
    1068              :     "run()\n"
    1069              :     "listen(address: <127.0.0.1:20002>, connection_type: tcp)\n"
    1070              :     "label(name: wait_next_message)\n"
    1071              :     "clear_data()\n"
    1072              :     "label(name: wait_data)\n"
    1073              :     "wait(timeout: 12, mode: wait)\n"
    1074              :     "has_data(min_size: 4)\n"
    1075              :     "if(false: wait_data)\n"
    1076              :     "show_data(size: 4)\n"
    1077              :     "verify_data(values: [ 0x50, 0x49, 0x4E, 0x47, 0x53 ])\n" // try to compare 5 bytes instead of 4
    1078              :     "exit(error_message: \"verify_data() did not fail\")\n"
    1079              : ;
    1080              : 
    1081              : constexpr char const * const g_program_raw_tcp_connection_verify_fails =
    1082              :     "run()\n"
    1083              :     "listen(address: <127.0.0.1:20002>, connection_type: tcp)\n"
    1084              :     "label(name: wait_next_message)\n"
    1085              :     "clear_data()\n"
    1086              :     "label(name: wait_data)\n"
    1087              :     "wait(timeout: 12, mode: wait)\n"
    1088              :     "has_data(min_size: 4)\n"
    1089              :     "if(false: wait_data)\n"
    1090              :     "show_data(size: 4)\n"
    1091              :     "verify_data(values: [ 0x49, 0x50, 0x4E, 0x47 ])\n" // IPNG instead of PING
    1092              :     "exit(error_message: \"verify_data() did not fail\")\n"
    1093              : ;
    1094              : 
    1095              : constexpr char const * const g_program_raw_tcp_connection_send_invalid_value_too_large =
    1096              :     "run()\n"
    1097              :     "listen(address: <127.0.0.1:20002>, connection_type: tcp)\n"
    1098              :     "label(name: wait_next_message)\n"
    1099              :     "clear_data()\n"
    1100              :     "label(name: wait_data)\n"
    1101              :     "wait(timeout: 12, mode: wait)\n"
    1102              :     "has_data(min_size: 4)\n"
    1103              :     "if(false: wait_data)\n"
    1104              :     "show_data(size: 4)\n"
    1105              :     "verify_data(values: [ 0x50, 0x49, 0x4E, 0x47 ])\n"     // PING
    1106              :     "show_data(size: 4)\n" // this will display <empty>
    1107              :     "has_data(min_size: 1)\n"
    1108              :     "if(true: unexpected_data)\n"
    1109              :     "send_data(values: [ 0x50, 0x4F, 0x100, 0x47 ])\n"      // PO?G
    1110              :     "exit(error_message: \"send_data() did not fail\")\n"
    1111              : ;
    1112              : 
    1113              : constexpr char const * const g_program_raw_tcp_connection_send_invalid_value_too_small =
    1114              :     "run()\n"
    1115              :     "listen(address: <127.0.0.1:20002>, connection_type: tcp)\n"
    1116              :     "label(name: wait_next_message)\n"
    1117              :     "clear_data()\n"
    1118              :     "label(name: wait_data)\n"
    1119              :     "wait(timeout: 12, mode: wait)\n"
    1120              :     "has_data(min_size: 4)\n"
    1121              :     "if(false: wait_data)\n"
    1122              :     "show_data(size: 4)\n"
    1123              :     "verify_data(values: [ 0x50, 0x49, 0x4E, 0x47 ])\n"     // PING
    1124              :     "show_data(size: 4)\n" // this will display <empty>
    1125              :     "has_data(min_size: 1)\n"
    1126              :     "if(true: unexpected_data)\n"
    1127              :     "send_data(values: [ 0x50, 0x4F, -129, 0x47 ])\n"      // PO?G
    1128              :     "exit(error_message: \"send_data() did not fail\")\n"
    1129              : ;
    1130              : 
    1131              : constexpr char const * const g_program_raw_tcp_connection_send_empty_array =
    1132              :     "run()\n"
    1133              :     "listen(address: <127.0.0.1:20002>, connection_type: tcp)\n"
    1134              :     "label(name: wait_next_message)\n"
    1135              :     "clear_data()\n"
    1136              :     "label(name: wait_data)\n"
    1137              :     "wait(timeout: 12, mode: wait)\n"
    1138              :     "has_data(min_size: 4)\n"
    1139              :     "if(false: wait_data)\n"
    1140              :     "show_data(size: 4)\n"
    1141              :     "verify_data(values: [ 0x50, 0x49, 0x4E, 0x47 ])\n"     // PING
    1142              :     "show_data(size: 4)\n" // this will display <empty>
    1143              :     "has_data(min_size: 1)\n"
    1144              :     "if(true: unexpected_data)\n"
    1145              :     "send_data(values: [])\n"      // empty is not valid
    1146              :     "exit(error_message: \"send_data() did not fail\")\n"
    1147              : ;
    1148              : 
    1149              : constexpr char const * const g_program_raw_tcp_connection_verify_empty_array =
    1150              :     "run()\n"
    1151              :     "listen(address: <127.0.0.1:20002>, connection_type: tcp)\n"
    1152              :     "label(name: wait_next_message)\n"
    1153              :     "clear_data()\n"
    1154              :     "label(name: wait_data)\n"
    1155              :     "wait(timeout: 12, mode: wait)\n"
    1156              :     "has_data(min_size: 4)\n"
    1157              :     "if(false: wait_data)\n"
    1158              :     "show_data(size: 4)\n"
    1159              :     "verify_data(values: [])\n"     // empty is not valid
    1160              :     "exit(error_message: \"verify_data() did not fail\")\n"
    1161              : ;
    1162              : 
    1163              : constexpr char const * const g_program_wrong_primary_variable_reference =
    1164              :     "set_variable(name: my_var, value: foo)\n"
    1165              :     "set_variable(name: longer_var, value: ${wrong_name})\n"
    1166              : ;
    1167              : 
    1168              : constexpr char const * const g_program_double_string_variable_without_name =
    1169              :     "set_variable(name: missing_close, value: \"ref. ${} is empty\")\n"
    1170              : ;
    1171              : 
    1172              : constexpr char const * const g_program_unsupported_negation_repeat =
    1173              :     "set_variable(name: bad, value: 'string' * -5)\n"
    1174              : ;
    1175              : 
    1176              : constexpr char const * const g_program_unsupported_large_repeat =
    1177              :     "set_variable(name: bad, value: 'string' * 1001)\n"
    1178              : ;
    1179              : 
    1180              : constexpr char const * const g_program_bad_exit =
    1181              :     "exit(error_message: \"bad error occurred!\", timeout: 3.001)\n"
    1182              : ;
    1183              : 
    1184              : constexpr char const * const g_program_bad_exit_timeout =
    1185              :     "exit(timeout: 'bad')\n"
    1186              : ;
    1187              : 
    1188              : constexpr char const * const g_program_bad_print_message =
    1189              :     "print(message: string_expected)\n"
    1190              : ;
    1191              : 
    1192              : constexpr char const * const g_program_send_message_without_connection =
    1193              :     "send_message(server: \"world\", service: cluckd, command: WITHOUT_CONNECTION)\n"
    1194              : ;
    1195              : 
    1196              : constexpr char const * const g_program_send_data_without_connection =
    1197              :     "send_data(values: [ 1, 2, 3 ])\n"
    1198              : ;
    1199              : 
    1200              : constexpr char const * const g_program_if_invalid_type =
    1201              :     "set_variable(name: my_str, value: \"bad\")\n"
    1202              :     "if(variable: my_str, unordered: unused)\n"
    1203              :     "exit(error_message: \"if() did not fail.\")\n"
    1204              :     "label(name: unused)\n"
    1205              :     "exit(error_message: \"if() branched unexpectendly.\")\n"
    1206              : ;
    1207              : 
    1208              : constexpr char const * const g_program_wait_outside_thread =
    1209              :     "wait(timeout: 10)\n"
    1210              : ;
    1211              : 
    1212              : constexpr char const * const g_program_wait_invalid_mode =
    1213              :     "run()\n"
    1214              :     "wait(timeout: 10, mode: not_this_one)\n"
    1215              : ;
    1216              : 
    1217              : constexpr char const * const g_program_wait_no_connections =
    1218              :     "run()\n"
    1219              :     "wait(timeout: 10, mode: wait)\n"
    1220              : ;
    1221              : 
    1222              : constexpr char const * const g_program_invalid_string_to_timestamp_cast =
    1223              :     "set_variable(name: time_limit, value: '1713b34141.10780g991', type: timestamp)\n"
    1224              : ;
    1225              : 
    1226              : constexpr char const * const g_program_unknown_string_cast =
    1227              :     "set_variable(name: time_limit, value: 'not important', type: unknown)\n"
    1228              : ;
    1229              : 
    1230              : constexpr char const * const g_program_unknown_timestamp_cast =
    1231              :     "set_variable(name: time_limit, value: @123.456, type: unknown)\n"
    1232              : ;
    1233              : 
    1234              : constexpr char const * const g_program_unknown_source_cast =
    1235              :     "set_variable(name: time_limit, value: <127.127.127.127>, type: string)\n"
    1236              : ;
    1237              : 
    1238              : constexpr char const * const g_program_sort_var1_missing =
    1239              :     "set_variable(name: s2, value: 'err33')\n"
    1240              :     "set_variable(name: s3, value: 'err13')\n"
    1241              :     "sort(var2: s2, var3: s3)\n"
    1242              : ;
    1243              : 
    1244              : constexpr char const * const g_program_sort_var1_not_string =
    1245              :     "sort(var1: 33)\n"
    1246              : ;
    1247              : 
    1248              : constexpr char const * const g_program_sort_var1_not_found =
    1249              :     "sort(var1: not_defined)\n"
    1250              : ;
    1251              : 
    1252              : constexpr char const * const g_program_sort_wrong_type =
    1253              :     // note that with time we are likely to support all types and thus
    1254              :     // this test may stop working
    1255              :     //
    1256              :     "set_variable(name: w1, value: <127.0.0.1>)\n"
    1257              :     "sort(var1: w1)\n"
    1258              : ;
    1259              : 
    1260              : constexpr char const * const g_program_sort_mixed_types =
    1261              :     "set_variable(name: s1, value: 'err13')\n"
    1262              :     "set_variable(name: s2, value: 33)\n"
    1263              :     "set_variable(name: s3, value: 'more')\n"
    1264              :     "sort(var1: s1, var2: s2, var3: s3)\n"
    1265              : ;
    1266              : 
    1267              : constexpr char const * const g_program_listen_with_unknown_connection_type =
    1268              :     "listen(address: <127.0.0.1:20002>, connection_type: unknown)\n"
    1269              : ;
    1270              : 
    1271              : 
    1272              : constexpr char const * const g_program_verify_message_fail_sent_server =
    1273              :     "run()\n"
    1274              :     "listen(address: <127.0.0.1:20002>)\n"
    1275              :     "label(name: wait_message)\n"
    1276              :     "clear_message()\n"
    1277              :     "wait(timeout: 12, mode: wait)\n"
    1278              :     "has_message()\n"
    1279              :     "if(false: wait_message)\n"
    1280              :     "show_message()\n"
    1281              :     "verify_message(command: REGISTER, sent_server: not_this_one)\n"
    1282              :     "exit()\n"
    1283              : ;
    1284              : 
    1285              : constexpr char const * const g_program_verify_message_fail_sent_service =
    1286              :     "run()\n"
    1287              :     "listen(address: <127.0.0.1:20002>)\n"
    1288              :     "label(name: wait_message)\n"
    1289              :     "clear_message()\n"
    1290              :     "wait(timeout: 12, mode: wait)\n"
    1291              :     "has_message()\n"
    1292              :     "if(false: wait_message)\n"
    1293              :     "show_message()\n"
    1294              :     "verify_message(command: REGISTER, sent_service: not_this_one)\n"
    1295              :     "exit()\n"
    1296              : ;
    1297              : 
    1298              : constexpr char const * const g_program_verify_message_fail_server =
    1299              :     "run()\n"
    1300              :     "listen(address: <127.0.0.1:20002>)\n"
    1301              :     "label(name: wait_message)\n"
    1302              :     "clear_message()\n"
    1303              :     "wait(timeout: 12, mode: wait)\n"
    1304              :     "has_message()\n"
    1305              :     "if(false: wait_message)\n"
    1306              :     "show_message()\n"
    1307              :     "verify_message(command: REGISTER, server: not_this_one)\n"
    1308              :     "exit()\n"
    1309              : ;
    1310              : 
    1311              : constexpr char const * const g_program_verify_message_fail_service =
    1312              :     "run()\n"
    1313              :     "listen(address: <127.0.0.1:20002>)\n"
    1314              :     "label(name: wait_message)\n"
    1315              :     "clear_message()\n"
    1316              :     "wait(timeout: 12, mode: wait)\n"
    1317              :     "has_message()\n"
    1318              :     "if(false: wait_message)\n"
    1319              :     "show_message()\n"
    1320              :     "verify_message(command: REGISTER, service: not_this_one)\n"
    1321              :     "exit()\n"
    1322              : ;
    1323              : 
    1324              : constexpr char const * const g_program_verify_message_fail_command =
    1325              :     "run()\n"
    1326              :     "listen(address: <127.0.0.1:20002>)\n"
    1327              :     "label(name: wait_message)\n"
    1328              :     "clear_message()\n"
    1329              :     "wait(timeout: 12, mode: wait)\n"
    1330              :     "has_message()\n"
    1331              :     "if(false: wait_message)\n"
    1332              :     "show_message()\n"
    1333              :     "verify_message(command: NOT_THIS_ONE)\n"
    1334              :     "exit()\n"
    1335              : ;
    1336              : 
    1337              : constexpr char const * const g_program_verify_message_fail_forbidden =
    1338              :     "run()\n"
    1339              :     "listen(address: <127.0.0.1:20002>)\n"
    1340              :     "label(name: wait_message)\n"
    1341              :     "clear_message()\n"
    1342              :     "wait(timeout: 12, mode: wait)\n"
    1343              :     "has_message()\n"
    1344              :     "if(false: wait_message)\n"
    1345              :     "show_message()\n"
    1346              :     "verify_message(command: REGISTER, forbidden_parameters: { version })\n"
    1347              :     "exit()\n"
    1348              : ;
    1349              : 
    1350              : constexpr char const * const g_program_verify_message_fail_required =
    1351              :     "run()\n"
    1352              :     "listen(address: <127.0.0.1:20002>)\n"
    1353              :     "label(name: wait_message)\n"
    1354              :     "clear_message()\n"
    1355              :     "wait(timeout: 12, mode: wait)\n"
    1356              :     "has_message()\n"
    1357              :     "if(false: wait_message)\n"
    1358              :     "show_message()\n"
    1359              :     "verify_message(command: REGISTER, required_parameters: { not_this_one: 123 })\n"
    1360              :     "exit()\n"
    1361              : ;
    1362              : 
    1363              : constexpr char const * const g_program_verify_message_fail_required_int_value =
    1364              :     "run()\n"
    1365              :     "listen(address: <127.0.0.1:20002>)\n"
    1366              :     "label(name: wait_message)\n"
    1367              :     "clear_message()\n"
    1368              :     "wait(timeout: 12, mode: wait)\n"
    1369              :     "has_message()\n"
    1370              :     "if(false: wait_message)\n"
    1371              :     "show_message()\n"
    1372              :     "verify_message(command: REGISTER, required_parameters: { version: 200 })\n"
    1373              :     "exit()\n"
    1374              : ;
    1375              : 
    1376              : constexpr char const * const g_program_verify_message_fail_required_str_value =
    1377              :     "run()\n"
    1378              :     "listen(address: <127.0.0.1:20002>)\n"
    1379              :     "label(name: wait_message)\n"
    1380              :     "clear_message()\n"
    1381              :     "wait(timeout: 12, mode: wait)\n"
    1382              :     "has_message()\n"
    1383              :     "if(false: wait_message)\n"
    1384              :     "show_message()\n"
    1385              :     "verify_message(command: REGISTER, required_parameters: { service: not_this_one })\n"
    1386              :     "exit()\n"
    1387              : ;
    1388              : 
    1389              : constexpr char const * const g_program_verify_message_fail_required_long_str_value =
    1390              :     "run()\n"
    1391              :     "listen(address: <127.0.0.1:20002>)\n"
    1392              :     "label(name: wait_message)\n"
    1393              :     "clear_message()\n"
    1394              :     "wait(timeout: 12, mode: wait)\n"
    1395              :     "has_message()\n"
    1396              :     "if(false: wait_message)\n"
    1397              :     "show_message()\n"
    1398              :     "verify_message(command: REGISTER, required_parameters: { service: 'responder' * 15 })\n"
    1399              :     "exit()\n"
    1400              : ;
    1401              : 
    1402              : constexpr char const * const g_program_verify_message_fail_required_flt_value =
    1403              :     "run()\n"
    1404              :     "listen(address: <127.0.0.1:20002>)\n"
    1405              :     "label(name: wait_message)\n"
    1406              :     "clear_message()\n"
    1407              :     "wait(timeout: 12, mode: wait)\n"
    1408              :     "has_message()\n"
    1409              :     "if(false: wait_message)\n"
    1410              :     "show_message()\n"
    1411              :     "verify_message(command: REGISTER, required_parameters: { version: 1.0 })\n"
    1412              :     "exit()\n"
    1413              : ;
    1414              : 
    1415              : constexpr char const * const g_program_verify_message_fail_required_timestamp_value =
    1416              :     "run()\n"
    1417              :     "listen(address: <127.0.0.1:20002>)\n"
    1418              :     "label(name: wait_message)\n"
    1419              :     "clear_message()\n"
    1420              :     "wait(timeout: 12, mode: wait)\n"
    1421              :     "has_message()\n"
    1422              :     "if(false: wait_message)\n"
    1423              :     "show_message()\n"
    1424              :     "verify_message(command: REGISTER, required_parameters: { version: @123 })\n"
    1425              :     "exit()\n"
    1426              : ;
    1427              : 
    1428              : constexpr char const * const g_program_verify_message_fail_timestamp_command =
    1429              :     "run()\n"
    1430              :     "listen(address: <127.0.0.1:20002>)\n"
    1431              :     "label(name: wait_message)\n"
    1432              :     "clear_message()\n"
    1433              :     "wait(timeout: 12, mode: wait)\n"
    1434              :     "has_message()\n"
    1435              :     "if(false: wait_message)\n"
    1436              :     "show_message()\n"
    1437              :     "verify_message(command: @123.678, required_parameters: { version: 1 })\n"
    1438              :     "exit()\n"
    1439              : ;
    1440              : 
    1441              : constexpr char const * const g_program_verify_message_fail_unexpected_command =
    1442              :     "run()\n"
    1443              :     "listen(address: <127.0.0.1:20002>)\n"
    1444              :     "label(name: wait_message)\n"
    1445              :     "clear_message()\n"
    1446              :     "wait(timeout: 12, mode: wait)\n"
    1447              :     "has_message()\n"
    1448              :     "if(false: wait_message)\n"
    1449              :     "show_message()\n"
    1450              :     "verify_message(command: `^NOT_THIS_ONE$`, required_parameters: { version: 1 })\n"
    1451              :     "exit()\n"
    1452              : ;
    1453              : 
    1454              : constexpr char const * const g_program_last_wait =
    1455              :     "run()\n"
    1456              :     "listen(address: <127.0.0.1:20002>)\n"
    1457              :     "label(name: wait_message)\n"
    1458              :     "clear_message()\n"
    1459              :     "wait(timeout: 10.0, mode: wait)\n"
    1460              :     "has_message()\n"
    1461              :     "if(false: wait_message)\n"
    1462              :     "show_message()\n"
    1463              :     "verify_message(command: REGISTER, required_parameters: { service: responder, version: 1 }, optional_parameters: { commands: \"READY,HELP,STOP\" }, forbidden_parameters: { forbidden })\n"
    1464              :     "send_message(command: READY, sent_server: reporter_test_extension, sent_service: test_processor, server: reporter_test, service: accept_one_message, parameters: { status: alive })\n"
    1465              :     "wait(timeout: 1.0, mode: drain)\n" // hope that send_message() is small enough that a single wait is sufficient to send it
    1466              :     "wait(timeout: 1.0)\n"
    1467              :     "disconnect()\n"
    1468              :     "exit()\n"
    1469              : ;
    1470              : 
    1471              : constexpr char const * const g_program_regex_parameter_no_match =
    1472              :     "run()\n"
    1473              :     "listen(address: <127.0.0.1:20002>)\n"
    1474              :     "label(name: wait_message)\n"
    1475              :     "clear_message()\n"
    1476              :     "wait(timeout: 10.0, mode: wait)\n"
    1477              :     "has_message()\n"
    1478              :     "if(false: wait_message)\n"
    1479              :     "show_message()\n"
    1480              :     "verify_message(command: REGISTER, required_parameters: { service: responder, version: `_[a-z]+` }, optional_parameters: { commands: \"READY,HELP,STOP\" }, forbidden_parameters: { forbidden })\n"
    1481              :     "send_message(command: READY, sent_server: reporter_test_extension, sent_service: test_processor, server: reporter_test, service: accept_one_message, parameters: { status: alive })\n"
    1482              :     "wait(timeout: 1.0, mode: drain)\n"
    1483              :     "wait(timeout: 1.0)\n"
    1484              :     "disconnect()\n"
    1485              :     "exit()\n"
    1486              : ;
    1487              : 
    1488              : constexpr char const * const g_program_wait_for_nothing =
    1489              :     "run()\n"
    1490              :     "listen(address: <127.0.0.1:20002>)\n"
    1491              :     "label(name: wait_message)\n"
    1492              :     "clear_message()\n"
    1493              :     "wait(timeout: 10.0, mode: wait)\n" // first wait reacts on connect(), second wait receives the REGISTER message
    1494              :     "has_message()\n"
    1495              :     "if(false: wait_message)\n"
    1496              :     "show_message()\n"
    1497              :     "verify_message(command: REGISTER, required_parameters: { service: responder, version: 1 }, optional_parameters: { commands: \"READY,HELP,STOP\" }, forbidden_parameters: { forbidden })\n"
    1498              :     "send_message(command: READY, sent_server: reporter_test_extension, sent_service: test_processor, server: reporter_test, service: accept_one_message, parameters: { status: alive })\n"
    1499              :     "wait(timeout: 1.0, mode: drain)\n"
    1500              :     "wait(timeout: 1.0)\n"
    1501              :     "wait(timeout: 1.0)\n" // one too many wait(), it will time out
    1502              :     "exit()\n"
    1503              : ;
    1504              : 
    1505              : constexpr char const * const g_program_wait_for_timeout =
    1506              :     "run()\n"
    1507              :     "listen(address: <127.0.0.1:20002>)\n"
    1508              :     "label(name: wait_message)\n"
    1509              :     "clear_message()\n"
    1510              :     "wait(timeout: 10.0, mode: wait)\n" // first wait reacts on connect(), second wait receives the REGISTER message
    1511              :     "has_message()\n"
    1512              :     "if(false: wait_message)\n"
    1513              :     "show_message()\n"
    1514              :     "verify_message(command: REGISTER, required_parameters: { service: responder, version: 1 }, optional_parameters: { commands: \"READY,HELP,STOP\" }, forbidden_parameters: { forbidden })\n"
    1515              :     "send_message(command: READY, sent_server: reporter_test_extension, sent_service: test_processor, server: reporter_test, service: accept_one_message, parameters: { status: alive })\n"
    1516              :     "wait(timeout: 1.0, mode: drain)\n"
    1517              :     "wait(timeout: 1.0)\n"
    1518              :     "wait(timeout: 1.0, mode: timeout)\n" // one extra wait(), which will time out
    1519              :     "exit()\n"
    1520              : ;
    1521              : 
    1522              : 
    1523              : 
    1524              : struct expected_trace_t
    1525              : {
    1526              :     SNAP_CATCH2_NAMESPACE::reporter::callback_reason_t const
    1527              :                         f_reason = SNAP_CATCH2_NAMESPACE::reporter::callback_reason_t::CALLBACK_REASON_BEFORE_CALL;
    1528              :     char const * const  f_name = nullptr;
    1529              : };
    1530              : #define TRACE_EXPECT(reason, name)  { .f_reason = SNAP_CATCH2_NAMESPACE::reporter::callback_reason_t::CALLBACK_REASON_##reason##_CALL, .f_name = #name }
    1531              : 
    1532              : 
    1533              : constexpr expected_trace_t const g_verify_starting_thread[] =
    1534              : {
    1535              :     TRACE_EXPECT(BEFORE, set_variable),
    1536              :     TRACE_EXPECT(AFTER, set_variable),
    1537              :     TRACE_EXPECT(BEFORE, set_variable),
    1538              :     TRACE_EXPECT(AFTER, set_variable),
    1539              :     TRACE_EXPECT(BEFORE, run),
    1540              :     TRACE_EXPECT(AFTER, run),
    1541              :     TRACE_EXPECT(BEFORE, set_variable),
    1542              :     TRACE_EXPECT(AFTER, set_variable),
    1543              :     TRACE_EXPECT(BEFORE, set_variable),
    1544              :     TRACE_EXPECT(AFTER, set_variable),
    1545              :     TRACE_EXPECT(BEFORE, set_variable),
    1546              :     TRACE_EXPECT(AFTER, set_variable),
    1547              :     TRACE_EXPECT(BEFORE, set_variable),
    1548              :     TRACE_EXPECT(AFTER, set_variable),
    1549              :     TRACE_EXPECT(BEFORE, set_variable),
    1550              :     TRACE_EXPECT(AFTER, set_variable),
    1551              :     TRACE_EXPECT(BEFORE, set_variable),
    1552              :     TRACE_EXPECT(AFTER, set_variable),
    1553              :     TRACE_EXPECT(BEFORE, set_variable),
    1554              :     TRACE_EXPECT(AFTER, set_variable),
    1555              :     TRACE_EXPECT(BEFORE, set_variable),
    1556              :     TRACE_EXPECT(AFTER, set_variable),
    1557              :     TRACE_EXPECT(BEFORE, strlen),
    1558              :     TRACE_EXPECT(AFTER, strlen),
    1559              :     {}
    1560              : };
    1561              : 
    1562              : 
    1563              : constexpr expected_trace_t const g_verify_raw_tcp_connection[] =
    1564              : {
    1565              :     TRACE_EXPECT(BEFORE, run),
    1566              :     TRACE_EXPECT(AFTER, run),
    1567              :     TRACE_EXPECT(BEFORE, listen),
    1568              :     TRACE_EXPECT(AFTER, listen),
    1569              :     TRACE_EXPECT(BEFORE, label),
    1570              :     TRACE_EXPECT(AFTER, label),
    1571              :     TRACE_EXPECT(BEFORE, clear_data),
    1572              :     TRACE_EXPECT(AFTER, clear_data),
    1573              :     TRACE_EXPECT(BEFORE, label),
    1574              :     TRACE_EXPECT(AFTER, label),
    1575              :     TRACE_EXPECT(BEFORE, wait),
    1576              :     TRACE_EXPECT(AFTER, wait),
    1577              :     TRACE_EXPECT(BEFORE, has_data),
    1578              :     TRACE_EXPECT(AFTER, has_data),
    1579              :     TRACE_EXPECT(BEFORE, if),
    1580              :     TRACE_EXPECT(AFTER, if),
    1581              :     TRACE_EXPECT(BEFORE, label),
    1582              :     TRACE_EXPECT(AFTER, label),
    1583              :     TRACE_EXPECT(BEFORE, wait),
    1584              :     TRACE_EXPECT(AFTER, wait),
    1585              :     TRACE_EXPECT(BEFORE, has_data),
    1586              :     TRACE_EXPECT(AFTER, has_data),
    1587              :     TRACE_EXPECT(BEFORE, if),
    1588              :     TRACE_EXPECT(AFTER, if),
    1589              :     TRACE_EXPECT(BEFORE, show_data),
    1590              :     TRACE_EXPECT(AFTER, show_data),
    1591              :     TRACE_EXPECT(BEFORE, verify_data),
    1592              :     TRACE_EXPECT(AFTER, verify_data),
    1593              :     TRACE_EXPECT(BEFORE, send_data),
    1594              :     TRACE_EXPECT(AFTER, send_data),
    1595              :     TRACE_EXPECT(BEFORE, wait),
    1596              :     TRACE_EXPECT(AFTER, wait),
    1597              :     TRACE_EXPECT(BEFORE, disconnect),
    1598              :     TRACE_EXPECT(AFTER, disconnect),
    1599              :     TRACE_EXPECT(BEFORE, exit),
    1600              :     TRACE_EXPECT(AFTER, exit),
    1601              :     TRACE_EXPECT(BEFORE, end), // generate an error
    1602              :     {}
    1603              : };
    1604              : 
    1605              : 
    1606              : class trace
    1607              : {
    1608              : public:
    1609            1 :     trace(expected_trace_t const * expected_trace)
    1610            1 :         : f_expected_trace(expected_trace)
    1611              :     {
    1612            1 :     }
    1613              : 
    1614              :     trace(trace const &) = delete;
    1615              : 
    1616            1 :     ~trace()
    1617              :     {
    1618              :         // make sure we reached the end of the list
    1619              :         //
    1620            1 :         CATCH_REQUIRE(f_expected_trace[f_pos].f_name == nullptr);
    1621            1 :     }
    1622              : 
    1623              :     trace operator = (trace const &) = delete;
    1624              : 
    1625           24 :     void callback(SNAP_CATCH2_NAMESPACE::reporter::state & s, SNAP_CATCH2_NAMESPACE::reporter::callback_reason_t reason)
    1626              :     {
    1627           24 :         SNAP_CATCH2_NAMESPACE::reporter::statement::pointer_t stmt(s.get_running_statement());
    1628           24 :         std::string const & name(stmt->get_instruction()->get_name());
    1629              :         std::cerr
    1630           24 :             << "--------------------- TRACE: pos: "
    1631              :             << f_pos
    1632           24 :             << " reason: "
    1633              :             << static_cast<int>(reason)
    1634              :             << " name: \""
    1635              :             << name
    1636           24 :             << "\"\n";
    1637              : 
    1638              :         // here we can be in the thread so DO NOT USE CATCH_... macros
    1639              :         //
    1640           24 :         if(f_expected_trace[f_pos].f_name == nullptr)
    1641              :         {
    1642              :             std::cerr
    1643            0 :                 << "tracer error: got more calls ("
    1644            0 :                 << f_pos + 1
    1645            0 :                 << ") to tracer than expected.\n";
    1646              :             throw std::runtime_error(
    1647              :                   "got more calls ("
    1648            0 :                 + std::to_string(f_pos + 1)
    1649            0 :                 + ") to tracer than expected.");
    1650              :         }
    1651              : 
    1652           24 :         if(f_expected_trace[f_pos].f_reason != reason)
    1653              :         {
    1654              :             std::cerr
    1655            0 :                 << "tracer error: unexpected reason at position "
    1656              :                 << f_pos
    1657            0 :                 << " (got "
    1658              :                 << static_cast<int>(reason)
    1659            0 :                 << ", expected "
    1660            0 :                 << static_cast<int>(f_expected_trace[f_pos].f_reason)
    1661            0 :                 << ").\n";
    1662              :             throw std::runtime_error(
    1663              :                   "unexpected reason at position "
    1664            0 :                 + std::to_string(f_pos)
    1665            0 :                 + " (got "
    1666            0 :                 + std::to_string(static_cast<int>(reason))
    1667            0 :                 + ", expected "
    1668            0 :                 + std::to_string(static_cast<int>(f_expected_trace[f_pos].f_reason))
    1669            0 :                 + ").");
    1670              :         }
    1671              : 
    1672           24 :         if(f_expected_trace[f_pos].f_name != name)
    1673              :         {
    1674              :             std::cerr
    1675            0 :                 << "tracer error: unexpected instruction at position "
    1676              :                 << f_pos
    1677              :                 << " (got \""
    1678              :                 << name
    1679              :                 << "\", expected \""
    1680            0 :                 << f_expected_trace[f_pos].f_name
    1681            0 :                 << "\").\n";
    1682              :             throw std::runtime_error(
    1683              :                   "unexpected instruction at position "
    1684            0 :                 + std::to_string(f_pos)
    1685            0 :                 + " (got "
    1686            0 :                 + name
    1687            0 :                 + ", expected "
    1688            0 :                 + f_expected_trace[f_pos].f_name
    1689            0 :                 + ").");
    1690              :         }
    1691              : 
    1692           24 :         ++f_pos;
    1693           48 :     }
    1694              : 
    1695              : private:
    1696              :     int                         f_pos = 0;
    1697              :     expected_trace_t const *    f_expected_trace = nullptr;
    1698              : };
    1699              : 
    1700              : 
    1701              : class messenger_responder // an equivalent to a client
    1702              :     : public ed::tcp_client_permanent_message_connection
    1703              : {
    1704              : public:
    1705              :     typedef std::shared_ptr<messenger_responder> pointer_t;
    1706              : 
    1707              :     enum class sequence_t
    1708              :     {
    1709              :         SEQUENCE_ONE_MESSAGE,
    1710              :         SEQUENCE_UNWANTED_MESSAGE,
    1711              :         SEQUENCE_TIMED_MESSAGE,
    1712              :         SEQUENCE_READY_HELP_MESSAGE,
    1713              :         SEQUENCE_READY_THROW,
    1714              :         SEQUENCE_READY_THROW_WHAT,
    1715              :     };
    1716              : 
    1717           28 :     messenger_responder(
    1718              :               addr::addr const & a
    1719              :             , ed::mode_t mode
    1720              :             , sequence_t sequence
    1721              :             , int timeout = 500'000) // or ed::DEFAULT_PAUSE_BEFORE_RECONNECTING
    1722           28 :         : tcp_client_permanent_message_connection(
    1723              :               a
    1724              :             , mode
    1725              :             , timeout
    1726              :             , true
    1727              :             , "responder")  // service name
    1728           84 :         , f_sequence(sequence)
    1729              :     {
    1730           84 :         set_name("messenger_responder");    // connection name
    1731           28 :         set_timeout_delay(500'000);         // 0.5 seconds
    1732           28 :     }
    1733              : 
    1734           27 :     virtual void process_connected() override
    1735              :     {
    1736              :         // always register at the time we connect
    1737              :         //
    1738           27 :         tcp_client_permanent_message_connection::process_connected();
    1739           27 :         register_service();
    1740           27 :     }
    1741              : 
    1742           12 :     virtual void process_message(ed::message & msg) override
    1743              :     {
    1744           12 :         ++f_step;
    1745              :         std::cout
    1746           12 :             << "--- \"client\" message ("
    1747              :             << f_step
    1748              :             << "): "
    1749           12 :             << msg
    1750           12 :             << std::endl;
    1751              : 
    1752           12 :         bool disconnect_all(false);
    1753              : 
    1754           12 :         if(f_step == 1)
    1755              :         {
    1756            8 :             if(msg.get_command() != "READY")
    1757              :             {
    1758              :                 throw std::runtime_error(
    1759              :                       "first message expected to be READY, got "
    1760            0 :                     + msg.get_command()
    1761            0 :                     + " instead.");
    1762              :             }
    1763           24 :             if(msg.has_parameter("version"))
    1764              :             {
    1765              :                 // there are cases where I put a version as an integer
    1766              :                 //
    1767            3 :                 std::int64_t version(msg.get_integer_parameter("version"));
    1768            1 :                 if(version != 9)
    1769              :                 {
    1770              :                     throw std::runtime_error(
    1771              :                           "READY version value invalid; expected 9, got "
    1772            0 :                         + std::to_string(version)
    1773            0 :                         + " instead.");
    1774              :                 }
    1775              :             }
    1776           24 :             if(msg.has_parameter("date"))
    1777              :             {
    1778              :                 // there are cases where I put a date as a timespec_ex (a timestamp in the language)
    1779              :                 //
    1780            3 :                 snapdev::timespec_ex date(msg.get_timespec_parameter("date"));
    1781            1 :                 if(date != snapdev::timespec_ex(1715440881, 543723981))
    1782              :                 {
    1783              :                     throw std::runtime_error(
    1784              :                           "READY date value invalid; expected 1715440881.543723981, got "
    1785            0 :                         + date.to_timestamp()
    1786            0 :                         + " instead.");
    1787              :                 }
    1788              :             }
    1789              :         }
    1790              : 
    1791           12 :         switch(f_sequence)
    1792              :         {
    1793            4 :         case sequence_t::SEQUENCE_ONE_MESSAGE:
    1794            4 :             disconnect_all = true;
    1795            4 :             break;
    1796              : 
    1797            0 :         case sequence_t::SEQUENCE_UNWANTED_MESSAGE:
    1798              :             {
    1799            0 :                 ed::message unwanted;
    1800            0 :                 unwanted.reply_to(msg);
    1801            0 :                 unwanted.set_command("UNWANTED");
    1802            0 :                 unwanted.add_parameter("serial", 7209);
    1803            0 :                 if(!send_message(unwanted, false))
    1804              :                 {
    1805            0 :                     throw std::runtime_error("could not send UNWANTED message");
    1806              :                 }
    1807            0 :             }
    1808              :             break;
    1809              : 
    1810            1 :         case sequence_t::SEQUENCE_TIMED_MESSAGE:
    1811              :             {
    1812            1 :                 ed::message unwanted;
    1813            1 :                 unwanted.reply_to(msg);
    1814            3 :                 unwanted.set_command("TIMED");
    1815            3 :                 unwanted.add_parameter("now", snapdev::now());
    1816            1 :                 if(!send_message(unwanted, false))
    1817              :                 {
    1818            0 :                     throw std::runtime_error("could not send TIMED message");
    1819              :                 }
    1820            1 :             }
    1821              :             break;
    1822              : 
    1823            3 :         case sequence_t::SEQUENCE_READY_HELP_MESSAGE:
    1824            3 :             switch(f_step)
    1825              :             {
    1826            1 :             case 1:
    1827              :                 // done in this case
    1828            1 :                 break;
    1829              : 
    1830            1 :             case 2:
    1831            1 :                 if(msg.get_command() != "HELP")
    1832              :                 {
    1833              :                     throw std::runtime_error(
    1834              :                           "second message expected to be HELP, got "
    1835            0 :                         + msg.get_command()
    1836            0 :                         + " instead.");
    1837              :                 }
    1838              : 
    1839              :                 {
    1840            1 :                     ed::message commands;
    1841            1 :                     commands.reply_to(msg);
    1842            3 :                     commands.set_sent_from_server("reporter_test");
    1843            3 :                     commands.set_sent_from_service("commands_message");
    1844            3 :                     commands.set_command("COMMANDS");
    1845            5 :                     commands.add_parameter("list", "HELP,READY,STOP");
    1846              : //std::cerr << "--- respond with COMMANDS\n";
    1847            1 :                     if(!send_message(commands, false))
    1848              :                     {
    1849            0 :                         throw std::runtime_error("could not send COMMANDS message");
    1850              :                     }
    1851            1 :                 }
    1852              :                 break;
    1853              : 
    1854            1 :             case 3:
    1855            1 :                 if(msg.get_command() != "STOP")
    1856              :                 {
    1857              :                     throw std::runtime_error(
    1858              :                           "third message expected to be STOP, got "
    1859            0 :                         + msg.get_command()
    1860            0 :                         + " instead.");
    1861              :                 }
    1862              : 
    1863            1 :                 disconnect_all = true;
    1864            1 :                 break;
    1865              : 
    1866            0 :             default:
    1867            0 :                 throw std::runtime_error("reached step 4 of SEQUENCE_READY_HELP_MESSAGE?");
    1868              : 
    1869              :             }
    1870            3 :             break;
    1871              : 
    1872            2 :         case sequence_t::SEQUENCE_READY_THROW:
    1873            2 :             switch(f_step)
    1874              :             {
    1875            1 :             case 1:
    1876              :                 // done in this case
    1877            1 :                 break;
    1878              : 
    1879            1 :             case 2:
    1880            1 :                 if(msg.get_command() != "HELP")
    1881              :                 {
    1882              :                     throw std::runtime_error(
    1883              :                           "second message expected to be HELP, got "
    1884            0 :                         + msg.get_command()
    1885            0 :                         + " instead.");
    1886              :                 }
    1887              : 
    1888              :                 // got the help message, now do a "legitimate" throw
    1889              :                 //
    1890            1 :                 throw std::runtime_error("testing that the executor catches these exceptions.");
    1891              : 
    1892            0 :             default:
    1893            0 :                 throw std::runtime_error("reached step 4 of SEQUENCE_READY_THROW?");
    1894              : 
    1895              :             }
    1896            1 :             break;
    1897              : 
    1898            2 :         case sequence_t::SEQUENCE_READY_THROW_WHAT:
    1899            2 :             switch(f_step)
    1900              :             {
    1901            1 :             case 1:
    1902              :                 // done in this case
    1903            1 :                 break;
    1904              : 
    1905            1 :             case 2:
    1906            1 :                 if(msg.get_command() != "HELP")
    1907              :                 {
    1908              :                     throw std::runtime_error(
    1909              :                           "second message expected to be HELP, got "
    1910            0 :                         + msg.get_command()
    1911            0 :                         + " instead.");
    1912              :                 }
    1913              : 
    1914              :                 // got the help message, now do a "legitimate" throw
    1915              :                 //
    1916              :                 struct my_exception
    1917              :                 {
    1918              :                     int code = 0;
    1919              :                 };
    1920            1 :                 throw my_exception({5});
    1921              : 
    1922            0 :             default:
    1923            0 :                 throw std::runtime_error("reached step 4 of SEQUENCE_READY_THROW_WHAT?");
    1924              : 
    1925              :             }
    1926            1 :             break;
    1927              : 
    1928              :         }
    1929              : 
    1930           10 :         if(disconnect_all)
    1931              :         {
    1932            5 :             remove_from_communicator();
    1933              : 
    1934            5 :             ed::connection::pointer_t timer_ptr(f_timer.lock());
    1935            5 :             if(timer_ptr != nullptr)
    1936              :             {
    1937            5 :                 timer_ptr->remove_from_communicator();
    1938              :             }
    1939            5 :         }
    1940           10 :     }
    1941              : 
    1942           23 :     void set_timer(ed::connection::pointer_t done_timer)
    1943              :     {
    1944           23 :         f_timer = done_timer;
    1945           23 :     }
    1946              : 
    1947              : private:
    1948              :     // the sequence & step define the next action
    1949              :     //
    1950              :     sequence_t  f_sequence = sequence_t::SEQUENCE_ONE_MESSAGE;
    1951              :     int         f_step = 0;
    1952              :     ed::connection::weak_pointer_t
    1953              :                 f_timer = ed::connection::weak_pointer_t();
    1954              : };
    1955              : 
    1956              : 
    1957              : class messenger_timer
    1958              :     : public ed::timer
    1959              : {
    1960              : public:
    1961              :     typedef std::shared_ptr<messenger_timer>        pointer_t;
    1962              : 
    1963           23 :     messenger_timer(messenger_responder::pointer_t m)
    1964           23 :         : timer(10'000'000)
    1965           23 :         , f_messenger(m)
    1966              :     {
    1967           69 :         set_name("messenger_timer");
    1968           23 :     }
    1969              : 
    1970            2 :     void process_timeout()
    1971              :     {
    1972              :         // call default function(s)
    1973              :         //
    1974            2 :         timer::process_timeout();
    1975              : 
    1976            2 :         remove_from_communicator();
    1977            2 :         f_messenger->remove_from_communicator();
    1978            2 :         f_timed_out = true;
    1979            2 :     }
    1980              : 
    1981           22 :     bool timed_out_prima() const
    1982              :     {
    1983           22 :         return f_timed_out;
    1984              :     }
    1985              : 
    1986              : private:
    1987              :     messenger_responder::pointer_t      f_messenger = messenger_responder::pointer_t();
    1988              :     bool                                f_timed_out = false;
    1989              : };
    1990              : 
    1991              : 
    1992              : 
    1993              : 
    1994              : class permanent_binary_responder // an equivalent to a client
    1995              :     : public ed::timer
    1996              : {
    1997              : public:
    1998              :     typedef std::shared_ptr<permanent_binary_responder> pointer_t;
    1999              : 
    2000              :     enum class sequence_t
    2001              :     {
    2002              :         SEQUENCE_PING_PONG,
    2003              :         SEQUENCE_PRINBEE_MESSAGE
    2004              :     };
    2005              : 
    2006              :     class binary_responder
    2007              :         : public ed::tcp_client_connection
    2008              :     {
    2009              :     public:
    2010              :         typedef std::shared_ptr<binary_responder> pointer_t;
    2011              : 
    2012            8 :         binary_responder(
    2013              :                   permanent_binary_responder * parent
    2014              :                 , addr::addr const & a
    2015              :                 , ed::mode_t mode)
    2016            8 :             : tcp_client_connection(
    2017              :                   a
    2018              :                 , mode)
    2019            8 :             , f_parent(parent)
    2020              :         {
    2021           24 :             set_name("binary_responder");       // connection name
    2022            8 :         }
    2023              : 
    2024              :         binary_responder(binary_responder const &) = delete;
    2025              :         binary_responder & operator = (binary_responder const &) = delete;
    2026              : 
    2027            2 :         virtual void process_read() override
    2028              :         {
    2029            2 :             f_parent->process_read();
    2030            2 :         }
    2031              : 
    2032              :     private:
    2033              :         permanent_binary_responder *    f_parent = nullptr;
    2034              :     };
    2035              : 
    2036            8 :     permanent_binary_responder(
    2037              :               addr::addr const & a
    2038              :             , ed::mode_t mode
    2039              :             , sequence_t sequence
    2040              :             , int timeout = 500'000) // or ed::DEFAULT_PAUSE_BEFORE_RECONNECTING
    2041            8 :         : timer(timeout)
    2042            8 :         , f_address(a)
    2043            8 :         , f_mode(mode)
    2044            8 :         , f_sequence(sequence)
    2045            8 :         , f_timeout(timeout)
    2046              :     {
    2047           24 :         set_name("permanent_binary_responder");     // connection name
    2048            8 :         set_timeout_delay(f_timeout);               // 0.5 seconds
    2049            8 :         set_enable(true);                           // be explicit that we want the timer to ping us
    2050            8 :     }
    2051              : 
    2052            0 :     virtual int get_socket() const override
    2053              :     {
    2054            0 :         if(f_responder != nullptr)
    2055              :         {
    2056            0 :             return f_responder->get_socket();
    2057              :         }
    2058            0 :         return -1;
    2059              :     }
    2060              : 
    2061            8 :     virtual void process_timeout() override
    2062              :     {
    2063              :         try
    2064              :         {
    2065           24 :             f_responder = std::make_shared<binary_responder>(
    2066           16 :                   this
    2067            8 :                 , f_address
    2068           16 :                 , f_mode);
    2069              :         }
    2070            0 :         catch(ed::failed_connecting const & e)
    2071              :         {
    2072              :             // try again later (keep timer enabled)
    2073              :             //
    2074            0 :             return;
    2075            0 :         }
    2076              :         // other errors are not legally expected
    2077              : 
    2078            8 :         ed::communicator::instance()->add_connection(f_responder);
    2079              : 
    2080              :         // we're connected, disable the timer
    2081              :         //
    2082            8 :         set_enable(false);
    2083              : 
    2084              :         // send a PING and expect a PONG as a reply
    2085              :         //
    2086            8 :         switch(f_sequence)
    2087              :         {
    2088            7 :         case sequence_t::SEQUENCE_PING_PONG:
    2089              :             {
    2090            7 :                 constexpr char const ping[] = { 'P', 'I', 'N', 'G' };
    2091            7 :                 ssize_t const written(f_responder->write(ping, sizeof(ping)));
    2092            7 :                 if(written != sizeof(ping))
    2093              :                 {
    2094            0 :                     throw std::runtime_error("could not send PING message");
    2095              :                 }
    2096              :             }
    2097              :             break;
    2098              : 
    2099            1 :         case sequence_t::SEQUENCE_PRINBEE_MESSAGE:
    2100              :             {
    2101            1 :                 constexpr char const msg[] = {
    2102              :                     'b', 'm',                           // magic ([b]inary [m]essage)
    2103              :                     1,                                  // version
    2104              :                     0,                                  // flags (none)
    2105              :                     'P', 'I', 'N', 'G',                 // message name
    2106              :                     8, 0, 0, 0,                         // size (little endian)
    2107              :                     static_cast<char>(0xaa), 0x55,      // CRC16 of data (fake)
    2108              :                     static_cast<char>(0xee), 0x77,      // CRC16 of message header
    2109              :                     0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, static_cast<char>(0xFF)  // the data
    2110              :                 };
    2111            1 :                 ssize_t const written(f_responder->write(msg, sizeof(msg)));
    2112            1 :                 if(written != sizeof(msg))
    2113              :                 {
    2114            0 :                     throw std::runtime_error("could not send the Prinbee message");
    2115              :                 }
    2116              :             }
    2117              :             break;
    2118              : 
    2119              :         }
    2120              :     }
    2121              : 
    2122              :     // this is called from the f_responder object (since this very object
    2123              :     // is just a connection with a timer, no actual socket)
    2124              :     //
    2125            2 :     virtual void process_read() override
    2126              :     {
    2127              :         // first we want the size
    2128              :         //
    2129            2 :         std::size_t size(0);
    2130            2 :         switch(f_sequence)
    2131              :         {
    2132            1 :         case sequence_t::SEQUENCE_PING_PONG:
    2133            1 :             size = 4UL;
    2134            1 :             break;
    2135              : 
    2136            1 :         case sequence_t::SEQUENCE_PRINBEE_MESSAGE:
    2137            1 :             size = 16UL;
    2138            1 :             break;
    2139              : 
    2140              :         }
    2141            2 :         if(size > sizeof(f_buffer))
    2142              :         {
    2143            0 :             throw std::runtime_error("size not supported (f_buffer too small)");
    2144              :         }
    2145              : 
    2146              :         // second we load `size` bytes, if possible, if not, just return early
    2147              :         //
    2148            4 :         while(f_buffer_size < size)
    2149              :         {
    2150            2 :             ssize_t const r(f_responder->read(f_buffer, size - f_buffer_size));
    2151            2 :             if(r < 0)
    2152              :             {
    2153            0 :                 throw std::runtime_error("unexpected I/O error reading data from binary socket");
    2154              :             }
    2155            2 :             if(r == 0)
    2156              :             {
    2157              :                 // EAGAIN or EOF, but for socket(), we don't really get EOF
    2158              :                 //
    2159            0 :                 return;
    2160              :             }
    2161            2 :             f_buffer_size += r;
    2162              :         }
    2163              : 
    2164              :         // we have a complete buffer, verify that it has the value we expect
    2165              :         //
    2166            2 :         ++f_step;
    2167              :         std::cout
    2168            2 :             << "--- "
    2169              :             << f_step
    2170            2 :             << ". binary client message ---"
    2171            2 :             << std::endl;
    2172              : 
    2173            2 :         switch(f_sequence)
    2174              :         {
    2175            1 :         case sequence_t::SEQUENCE_PING_PONG:
    2176            1 :             if(f_buffer[0] != 'P'
    2177            1 :             || f_buffer[1] != 'O'
    2178            1 :             || f_buffer[2] != 'N'
    2179            1 :             || f_buffer[3] != 'G')
    2180              :             {
    2181            0 :                 throw std::runtime_error("expected PONG binary message.");
    2182              :             }
    2183            1 :             f_complete = true;
    2184            1 :             break;
    2185              : 
    2186            1 :         case sequence_t::SEQUENCE_PRINBEE_MESSAGE:
    2187            1 :             if(f_buffer[ 0] != 'b'
    2188            1 :             || f_buffer[ 1] != 'm'
    2189            1 :             || f_buffer[ 2] != 1
    2190            1 :             || f_buffer[ 3] != 0
    2191            1 :             || f_buffer[ 4] != 'P'
    2192            1 :             || f_buffer[ 5] != 'O'
    2193            1 :             || f_buffer[ 6] != 'N'
    2194            1 :             || f_buffer[ 7] != 'G'
    2195            1 :             || f_buffer[ 8] != 0
    2196            1 :             || f_buffer[ 9] != 0
    2197            1 :             || f_buffer[10] != 0
    2198            1 :             || f_buffer[11] != 0
    2199            1 :             || f_buffer[12] != 0x55
    2200            1 :             || f_buffer[13] != static_cast<char>(0xaa)
    2201            1 :             || f_buffer[14] != 0x33
    2202            1 :             || f_buffer[15] != static_cast<char>(0xcc))
    2203              :             {
    2204            0 :                 throw std::runtime_error("expected PONG prinbee message.");
    2205              :             }
    2206            1 :             f_complete = true;
    2207            1 :             break;
    2208              : 
    2209              :         }
    2210              : 
    2211              :         // done with that buffer, reset the position/size
    2212              :         //
    2213            2 :         f_buffer_size = 0;
    2214              : 
    2215              :         //if(disconnect_all)
    2216              :         //{
    2217              :         //    remove_from_communicator();
    2218              :         //
    2219              :         //    ed::connection::pointer_t timer_ptr(f_timer.lock());
    2220              :         //    if(timer_ptr != nullptr)
    2221              :         //    {
    2222              :         //        timer_ptr->remove_from_communicator();
    2223              :         //    }
    2224              :         //}
    2225              :     }
    2226              : 
    2227            8 :     virtual void connection_removed() override
    2228              :     {
    2229            8 :         if(!f_complete)
    2230              :         {
    2231            0 :             throw std::runtime_error("binary responder not marked as complete.");
    2232              :         }
    2233              : 
    2234            8 :         if(f_responder != nullptr)
    2235              :         {
    2236            8 :             f_responder->remove_from_communicator();
    2237            8 :             f_responder.reset();
    2238              :         }
    2239            8 :     }
    2240              : 
    2241            6 :     void mark_complete()
    2242              :     {
    2243            6 :         f_complete = true;
    2244            6 :     }
    2245              : 
    2246              :     //void set_timer(ed::connection::pointer_t done_timer)
    2247              :     //{
    2248              :     //    f_timer = done_timer;
    2249              :     //}
    2250              : 
    2251              : private:
    2252              :     addr::addr                  f_address = addr::addr();
    2253              :     ed::mode_t                  f_mode = ed::mode_t::MODE_PLAIN;
    2254              :     sequence_t                  f_sequence = sequence_t::SEQUENCE_PING_PONG;
    2255              :     int                         f_step = 0;
    2256              :     int                         f_timeout = 500'000;
    2257              :     char                        f_buffer[4096] = {};
    2258              :     std::size_t                 f_buffer_size = 0; // number of bytes read so far
    2259              :     binary_responder::pointer_t f_responder = binary_responder::pointer_t();
    2260              :     bool                        f_complete = false;
    2261              : };
    2262              : 
    2263              : 
    2264              : 
    2265              : 
    2266              : 
    2267              : 
    2268              : } // no name namespace
    2269              : 
    2270              : 
    2271              : 
    2272           19 : CATCH_TEST_CASE("reporter_executor", "[executor][reporter]")
    2273              : {
    2274           19 :     CATCH_START_SECTION("reporter_executor: verify sleep in a function")
    2275              :     {
    2276            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));
    2277            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    2278            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    2279            1 :         p->parse_program();
    2280              : 
    2281            1 :         CATCH_REQUIRE(s->get_statement_size() == 5);
    2282              : 
    2283            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    2284            1 :         snapdev::timespec_ex const start(snapdev::now());
    2285            1 :         e->start();
    2286            1 :         CATCH_REQUIRE(e->run());
    2287            1 :         snapdev::timespec_ex const duration(snapdev::now() - start);
    2288            1 :         CATCH_REQUIRE(duration.tv_sec >= 2); // we slept for 2.5 seconds, so we expect at least start + 2 seconds
    2289            1 :     }
    2290           19 :     CATCH_END_SECTION()
    2291              : 
    2292           19 :     CATCH_START_SECTION("reporter_executor: verify sort function")
    2293              :     {
    2294            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_sleep_func.rprtr", g_program_sort_func));
    2295            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    2296            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    2297            1 :         p->parse_program();
    2298              : 
    2299            1 :         CATCH_REQUIRE(s->get_statement_size() == 19);
    2300              : 
    2301            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    2302            1 :         e->start();
    2303            1 :         CATCH_REQUIRE(e->run());
    2304              : 
    2305            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
    2306              : 
    2307              :         // *** STRING ***
    2308              :         struct verify_string_t
    2309              :         {
    2310              :             char const *            f_name = nullptr;
    2311              :             char const *            f_value = nullptr;
    2312              :         };
    2313              : 
    2314              :         // verify that the resulting set of variable is indeed sorted
    2315            1 :         verify_string_t string_verify[] =
    2316              :         {
    2317              :             { "s1", "are"   },
    2318              :             { "s2", "hello" },
    2319              :             { "s3", "who"   },
    2320              :             { "s4", "world" },
    2321              :             { "s5", "you?"  },
    2322              :         };
    2323              : 
    2324            6 :         for(auto const & v : string_verify)
    2325              :         {
    2326              : //std::cerr << "--- testing \"" << v.f_name << "\".\n";
    2327           15 :             SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var(s->get_variable(v.f_name));
    2328            5 :             CATCH_REQUIRE(var != nullptr);
    2329            5 :             CATCH_REQUIRE(var->get_name() == v.f_name);
    2330            5 :             CATCH_REQUIRE(var->get_type() == "string");
    2331            5 :             CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var)->get_string() == v.f_value);
    2332            5 :         }
    2333              : 
    2334              :         // *** INTEGER ***
    2335              :         struct verify_integer_t
    2336              :         {
    2337              :             char const *            f_name = nullptr;
    2338              :             int                     f_value = 0;
    2339              :         };
    2340              : 
    2341              :         // verify that the resulting set of variable is indeed sorted
    2342            1 :         verify_integer_t integer_verify[] =
    2343              :         {
    2344              :             { "i1",   -3 },
    2345              :             { "i2",   73 },
    2346              :             { "i3",  506 },
    2347              :             { "i4", 1003 },
    2348              :             { "i5", 1004 },
    2349              :         };
    2350              : 
    2351            6 :         for(auto const & v : integer_verify)
    2352              :         {
    2353              : //std::cerr << "--- testing \"" << v.f_name << "\".\n";
    2354           15 :             SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var(s->get_variable(v.f_name));
    2355            5 :             CATCH_REQUIRE(var != nullptr);
    2356            5 :             CATCH_REQUIRE(var->get_name() == v.f_name);
    2357            5 :             CATCH_REQUIRE(var->get_type() == "integer");
    2358            5 :             CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == v.f_value);
    2359            5 :         }
    2360              : 
    2361              :         // *** FLOATING POINT ***
    2362              :         struct verify_floating_point_t
    2363              :         {
    2364              :             char const *            f_name = nullptr;
    2365              :             double                  f_value = 0.0;
    2366              :         };
    2367              : 
    2368              :         // verify that the resulting set of variable is indeed sorted
    2369            1 :         verify_floating_point_t floating_point_verify[] =
    2370              :         {
    2371              :             { "f1", -10.103 },
    2372              :             { "f2",  -0.3   },
    2373              :             { "f3",   1.004 },
    2374              :             { "f4",  50.6   },
    2375              :             { "f5",  73.5   },
    2376              :         };
    2377              : 
    2378            6 :         for(auto const & v : floating_point_verify)
    2379              :         {
    2380              : //std::cerr << "--- testing \"" << v.f_name << "\".\n";
    2381           15 :             SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var(s->get_variable(v.f_name));
    2382            5 :             CATCH_REQUIRE(var != nullptr);
    2383            5 :             CATCH_REQUIRE(var->get_name() == v.f_name);
    2384            5 :             CATCH_REQUIRE(var->get_type() == "floating_point");
    2385            5 :             CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_floating_point>(var)->get_floating_point() == v.f_value);
    2386            5 :         }
    2387            1 :     }
    2388           19 :     CATCH_END_SECTION()
    2389              : 
    2390           19 :     CATCH_START_SECTION("reporter_executor: verify starting the thread")
    2391              :     {
    2392            1 :         trace tracer(g_verify_starting_thread);
    2393              : 
    2394            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));
    2395            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    2396              : 
    2397              :         // use std::bind() to avoid copies of the tracer object
    2398              :         //
    2399            1 :         s->set_trace_callback(std::bind(&trace::callback, &tracer, std::placeholders::_1, std::placeholders::_2));
    2400              : 
    2401            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    2402            1 :         p->parse_program();
    2403              : 
    2404            1 :         CATCH_REQUIRE(s->get_statement_size() == 12);
    2405              : 
    2406              :         // before we run the script, there are no such variables
    2407              :         //
    2408            3 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var(s->get_variable("test"));
    2409            1 :         CATCH_REQUIRE(var == nullptr);
    2410            3 :         var = s->get_variable("test_copy_between_dollars");
    2411            1 :         CATCH_REQUIRE(var == nullptr);
    2412            3 :         var = s->get_variable("runner");
    2413            1 :         CATCH_REQUIRE(var == nullptr);
    2414            3 :         var = s->get_variable("runner_copy_as_is");
    2415            1 :         CATCH_REQUIRE(var == nullptr);
    2416            3 :         var = s->get_variable("time_limit");
    2417            1 :         CATCH_REQUIRE(var == nullptr);
    2418            3 :         var = s->get_variable("time_limit_copy");
    2419            1 :         CATCH_REQUIRE(var == nullptr);
    2420            3 :         var = s->get_variable("time_from_float");
    2421            1 :         CATCH_REQUIRE(var == nullptr);
    2422            3 :         var = s->get_variable("host_ip");
    2423            1 :         CATCH_REQUIRE(var == nullptr);
    2424            3 :         var = s->get_variable("host_ip_copy");
    2425            1 :         CATCH_REQUIRE(var == nullptr);
    2426            3 :         var = s->get_variable("time_and_host_ip");
    2427            1 :         CATCH_REQUIRE(var == nullptr);
    2428            3 :         var = s->get_variable("length");
    2429            1 :         CATCH_REQUIRE(var == nullptr);
    2430              : 
    2431            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    2432            1 :         e->start();
    2433            1 :         CATCH_REQUIRE(e->run());
    2434              : 
    2435            3 :         var = s->get_variable("test");
    2436            1 :         CATCH_REQUIRE(var != nullptr);
    2437            1 :         CATCH_REQUIRE(var->get_name() == "test");
    2438            1 :         CATCH_REQUIRE(var->get_type() == "integer");
    2439            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == 33);
    2440              : 
    2441            3 :         var = s->get_variable("test_copy_between_dollars");
    2442            1 :         CATCH_REQUIRE(var != nullptr);
    2443            1 :         CATCH_REQUIRE(var->get_name() == "test_copy_between_dollars");
    2444            1 :         CATCH_REQUIRE(var->get_type() == "string");
    2445            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var)->get_string() == "$33$");
    2446              : 
    2447            3 :         var = s->get_variable("runner");
    2448            1 :         CATCH_REQUIRE(var != nullptr);
    2449            1 :         CATCH_REQUIRE(var->get_name() == "runner");
    2450            1 :         CATCH_REQUIRE(var->get_type() == "floating_point");
    2451            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_floating_point>(var)->get_floating_point() == 6.07);
    2452              : 
    2453            3 :         var = s->get_variable("runner_copy_as_is");
    2454            1 :         CATCH_REQUIRE(var != nullptr);
    2455            1 :         CATCH_REQUIRE(var->get_name() == "runner_copy_as_is");
    2456            1 :         CATCH_REQUIRE(var->get_type() == "string");
    2457            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var)->get_string() == "runner = 6.07");
    2458              : 
    2459            3 :         var = s->get_variable("time_limit");
    2460            1 :         CATCH_REQUIRE(var != nullptr);
    2461            1 :         CATCH_REQUIRE(var->get_name() == "time_limit");
    2462            1 :         CATCH_REQUIRE(var->get_type() == "timestamp");
    2463            1 :         snapdev::timespec_ex const time_limit(1713934141, 107805991);
    2464            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_timestamp>(var)->get_timestamp() == time_limit);
    2465              : 
    2466            3 :         var = s->get_variable("time_limit_copy");
    2467            1 :         CATCH_REQUIRE(var != nullptr);
    2468            1 :         CATCH_REQUIRE(var->get_name() == "time_limit_copy");
    2469            1 :         CATCH_REQUIRE(var->get_type() == "string");
    2470            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var)->get_string() == "limit: 1713934141.107805991");
    2471              : 
    2472            3 :         var = s->get_variable("host_ip");
    2473            1 :         CATCH_REQUIRE(var != nullptr);
    2474            1 :         CATCH_REQUIRE(var->get_name() == "host_ip");
    2475            1 :         CATCH_REQUIRE(var->get_type() == "address");
    2476            1 :         addr::addr a;
    2477            1 :         sockaddr_in ip = {
    2478              :             .sin_family = AF_INET,
    2479            1 :             .sin_port = htons(0),
    2480              :             .sin_addr = {
    2481            1 :                 .s_addr = htonl(0x7f070333),
    2482              :             },
    2483              :             .sin_zero = {},
    2484            1 :         };
    2485            1 :         a.set_ipv4(ip);
    2486            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_address>(var)->get_address() == a);
    2487              : 
    2488            3 :         var = s->get_variable("host_ip_copy");
    2489            1 :         CATCH_REQUIRE(var != nullptr);
    2490            1 :         CATCH_REQUIRE(var->get_name() == "host_ip_copy");
    2491            1 :         CATCH_REQUIRE(var->get_type() == "string");
    2492            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var)->get_string() == "Host is at 127.7.3.51 address");
    2493              : 
    2494            3 :         var = s->get_variable("time_and_host_ip");
    2495            1 :         CATCH_REQUIRE(var != nullptr);
    2496            1 :         CATCH_REQUIRE(var->get_name() == "time_and_host_ip");
    2497            1 :         CATCH_REQUIRE(var->get_type() == "string");
    2498            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...");
    2499              : 
    2500            3 :         var = s->get_variable("length");
    2501            1 :         CATCH_REQUIRE(var != nullptr);
    2502            1 :         CATCH_REQUIRE(var->get_name() == "length");
    2503            1 :         CATCH_REQUIRE(var->get_type() == "integer");
    2504            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == 51);
    2505            1 :     }
    2506           19 :     CATCH_END_SECTION()
    2507              : 
    2508           19 :     CATCH_START_SECTION("reporter_executor: verify computation (integers)")
    2509              :     {
    2510            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));
    2511            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    2512            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    2513            1 :         p->parse_program();
    2514              : 
    2515            1 :         CATCH_REQUIRE(s->get_statement_size() == 15);
    2516              : 
    2517            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    2518            1 :         e->start();
    2519            1 :         CATCH_REQUIRE(e->run());
    2520              : 
    2521            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var;
    2522              : 
    2523            3 :         var = s->get_variable("t01");
    2524            1 :         CATCH_REQUIRE(var != nullptr);
    2525            1 :         CATCH_REQUIRE(var->get_name() == "t01");
    2526            1 :         CATCH_REQUIRE(var->get_type() == "integer");
    2527            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == 3);
    2528              : 
    2529            3 :         var = s->get_variable("t11");
    2530            1 :         CATCH_REQUIRE(var != nullptr);
    2531            1 :         CATCH_REQUIRE(var->get_name() == "t11");
    2532            1 :         CATCH_REQUIRE(var->get_type() == "integer");
    2533            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == -3);
    2534              : 
    2535            3 :         var = s->get_variable("t12");
    2536            1 :         CATCH_REQUIRE(var != nullptr);
    2537            1 :         CATCH_REQUIRE(var->get_name() == "t12");
    2538            1 :         CATCH_REQUIRE(var->get_type() == "integer");
    2539            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == +3);
    2540              : 
    2541            3 :         var = s->get_variable("t21");
    2542            1 :         CATCH_REQUIRE(var != nullptr);
    2543            1 :         CATCH_REQUIRE(var->get_name() == "t21");
    2544            1 :         CATCH_REQUIRE(var->get_type() == "integer");
    2545            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == 3 + 2);
    2546              : 
    2547            3 :         var = s->get_variable("t22");
    2548            1 :         CATCH_REQUIRE(var != nullptr);
    2549            1 :         CATCH_REQUIRE(var->get_name() == "t22");
    2550            1 :         CATCH_REQUIRE(var->get_type() == "integer");
    2551            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == -(3 + 2));
    2552              : 
    2553            3 :         var = s->get_variable("t23");
    2554            1 :         CATCH_REQUIRE(var != nullptr);
    2555            1 :         CATCH_REQUIRE(var->get_name() == "t23");
    2556            1 :         CATCH_REQUIRE(var->get_type() == "integer");
    2557            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == 20 - 4);
    2558              : 
    2559            3 :         var = s->get_variable("t24");
    2560            1 :         CATCH_REQUIRE(var != nullptr);
    2561            1 :         CATCH_REQUIRE(var->get_name() == "t24");
    2562            1 :         CATCH_REQUIRE(var->get_type() == "integer");
    2563            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == 3 * 2);
    2564              : 
    2565            3 :         var = s->get_variable("t25");
    2566            1 :         CATCH_REQUIRE(var != nullptr);
    2567            1 :         CATCH_REQUIRE(var->get_name() == "t25");
    2568            1 :         CATCH_REQUIRE(var->get_type() == "integer");
    2569            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == 20 / 4);
    2570              : 
    2571            3 :         var = s->get_variable("t26");
    2572            1 :         CATCH_REQUIRE(var != nullptr);
    2573            1 :         CATCH_REQUIRE(var->get_name() == "t26");
    2574            1 :         CATCH_REQUIRE(var->get_type() == "integer");
    2575            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == 27 % 11);
    2576              : 
    2577            3 :         var = s->get_variable("t31");
    2578            1 :         CATCH_REQUIRE(var != nullptr);
    2579            1 :         CATCH_REQUIRE(var->get_name() == "t31");
    2580            1 :         CATCH_REQUIRE(var->get_type() == "integer");
    2581            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == 3 + 2 * 5);
    2582              : 
    2583            3 :         var = s->get_variable("t32");
    2584            1 :         CATCH_REQUIRE(var != nullptr);
    2585            1 :         CATCH_REQUIRE(var->get_name() == "t32");
    2586            1 :         CATCH_REQUIRE(var->get_type() == "integer");
    2587            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == -7 + 15 / 3);
    2588              : 
    2589            3 :         var = s->get_variable("t33");
    2590            1 :         CATCH_REQUIRE(var != nullptr);
    2591            1 :         CATCH_REQUIRE(var->get_name() == "t33");
    2592            1 :         CATCH_REQUIRE(var->get_type() == "integer");
    2593            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == +2 + 15 % 7);
    2594              : 
    2595            3 :         var = s->get_variable("t41");
    2596            1 :         CATCH_REQUIRE(var != nullptr);
    2597            1 :         CATCH_REQUIRE(var->get_name() == "t41");
    2598            1 :         CATCH_REQUIRE(var->get_type() == "integer");
    2599            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == (3 + 2) * 5);
    2600              : 
    2601            3 :         var = s->get_variable("t42");
    2602            1 :         CATCH_REQUIRE(var != nullptr);
    2603            1 :         CATCH_REQUIRE(var->get_name() == "t42");
    2604            1 :         CATCH_REQUIRE(var->get_type() == "integer");
    2605            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == (-7 + 15) / 3);
    2606              : 
    2607            3 :         var = s->get_variable("t43");
    2608            1 :         CATCH_REQUIRE(var != nullptr);
    2609            1 :         CATCH_REQUIRE(var->get_name() == "t43");
    2610            1 :         CATCH_REQUIRE(var->get_type() == "integer");
    2611            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == (+2 + 15) % 7);
    2612            1 :     }
    2613           19 :     CATCH_END_SECTION()
    2614              : 
    2615           19 :     CATCH_START_SECTION("reporter_executor: verify computation (floating points)")
    2616              :     {
    2617            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));
    2618            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    2619            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    2620            1 :         p->parse_program();
    2621              : 
    2622            1 :         CATCH_REQUIRE(s->get_statement_size() == 63);
    2623              : 
    2624            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    2625            1 :         e->start();
    2626            1 :         CATCH_REQUIRE(e->run());
    2627              : 
    2628              :         struct verify_t
    2629              :         {
    2630              :             char const *    f_name = nullptr;
    2631              :             double          f_value = 0.0;
    2632              :         };
    2633              : 
    2634            1 :         verify_t verify[] =
    2635              :         {
    2636              :             { "t01", 3.01 },
    2637              :             { "t11", -3.5 },
    2638              :             { "t12", +3.2 },
    2639              :             { "t21ff", 3.01 + 2.45 },
    2640              :             { "t21if", 3 + 2.54 },
    2641              :             { "t21fi", 3.01 + 2 },
    2642              :             { "t22ff", -(3.5 + 2.5) },
    2643              :             { "t22if", -(3 + 2.11) },
    2644              :             { "t22fi", -(3.07 + 2) },
    2645              :             { "t23ff", 20.07 - 4.13 },
    2646              :             { "t23if", 20 - 4.78 },
    2647              :             { "t23fi", 20.91 - 4 },
    2648              :             { "t24ff", 3.41 * 2.14 },
    2649              :             { "t24if", 3 * 2.67 },
    2650              :             { "t24fi", 3.32 * 2 },
    2651              :             { "t25ff", 20.83 / 4.07 },
    2652              :             { "t25if", 20 / 4.4 },
    2653              :             { "t25fi", 20.93 / 4 },
    2654              :             { "t26ff", fmod(27.27, 11.11) },
    2655              :             { "t26if", fmod(27, 11.88) },
    2656              :             { "t26fi", fmod(27.72, 11) },
    2657              :             { "t31fff", 3.03 + 2.2 * 5.9 },
    2658              :             { "t31iff", 3 + 2.5 * 5.7 },
    2659              :             { "t31fif", 3.2 + 2 * 5.3 },
    2660              :             { "t31ffi", 3.07 + 2.28 * 5 },
    2661              :             { "t31iif", 3 + 2 * 5.67 },
    2662              :             { "t31ifi", 3 + 2.56 * 5 },
    2663              :             { "t31fii", 3.33 + 2 * 5 },
    2664              :             { "t32fff", -7.11 + 15.7 / 3.06 },
    2665              :             { "t32iff", -7 + 15.25 / 3.31 },
    2666              :             { "t32fif", -7.78 + 15 / 3.77 },
    2667              :             { "t32ffi", -7.09 + 15.34 / 3 },
    2668              :             { "t32iif", -7 + 15 / 3.30 },
    2669              :             { "t32ifi", -7 + 15.09 / 3 },
    2670              :             { "t32fii", -7.94 + 15 / 3 },
    2671              :             { "t33fff", +2.21 + fmod(15.16, 7.8) },
    2672              :             { "t33iff", +2 + fmod(15.12, 7.93) },
    2673              :             { "t33fif", +2.58 + fmod(15, 7.63) },
    2674              :             { "t33ffi", +2.12 + fmod(15.09, 7) },
    2675              :             { "t33iif", +2 + fmod(15, 7.19) },
    2676              :             { "t33ifi", +2 + fmod(15.18, 7) },
    2677              :             { "t33fii", +2.17 + fmod(15, 7) },
    2678              :             { "t41fff", (3.45 + 2.06) * 5.55 },
    2679              :             { "t41iff", (3 + 2.17) * 5.07 },
    2680              :             { "t41fif", (3.37 + 2) * 5.12 },
    2681              :             { "t41ffi", (3.45 + 2.67) * 5 },
    2682              :             { "t41iif", (3 + 2) * 5.3 },
    2683              :             { "t41ifi", (3 + 2.9) * 5 },
    2684              :             { "t41fii", (3.4 + 2) * 5 },
    2685              :             { "t42fff", (-7.4 + 15.15) / 3.93 },
    2686              :             { "t42iff", (-7 + 15.21) / 3.43 },
    2687              :             { "t42fif", (-7.72 + 15) / 3.31 },
    2688              :             { "t42ffi", (-7.43 + 15.89) / 3 },
    2689              :             { "t42iif", (-7 + 15) / 3.4 },
    2690              :             { "t42ifi", (-7 + 15.09) / 3 },
    2691              :             { "t42fii", (-7.73 + 15) / 3 },
    2692              :             { "t43fff", fmod((+2.25 + 15.36), 7.47) },
    2693              :             { "t43iff", fmod((+2 + 15.16), 7.38) },
    2694              :             { "t43fif", fmod((+2.51 + 15), 7.59) },
    2695              :             { "t43ffi", fmod((+2.4 + 15.3), 7) },
    2696              :             { "t43iif", fmod((+2 + 15), 7.0) },
    2697              :             { "t43ifi", fmod((+2 + 15.8), 7) },
    2698              :             { "t43fii", fmod((+2.07 + 15), 7) },
    2699              :         };
    2700              : 
    2701            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var;
    2702           64 :         for(auto const & v : verify)
    2703              :         {
    2704              : //std::cerr << "--- testing \"" << v.f_name << "\".\n";
    2705          189 :             var = s->get_variable(v.f_name);
    2706           63 :             CATCH_REQUIRE(var != nullptr);
    2707           63 :             CATCH_REQUIRE(var->get_name() == v.f_name);
    2708           63 :             CATCH_REQUIRE(var->get_type() == "floating_point");
    2709           63 :             CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_floating_point>(var)->get_floating_point() == v.f_value);
    2710              :         }
    2711            1 :     }
    2712           19 :     CATCH_END_SECTION()
    2713              : 
    2714           19 :     CATCH_START_SECTION("reporter_executor: verify computation (timestamp)")
    2715              :     {
    2716            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));
    2717            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    2718            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    2719            1 :         p->parse_program();
    2720              : 
    2721            1 :         CATCH_REQUIRE(s->get_statement_size() == 12);
    2722              : 
    2723            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    2724            1 :         e->start();
    2725            1 :         CATCH_REQUIRE(e->run());
    2726              : 
    2727              :         struct verify_t
    2728              :         {
    2729              :             char const *            f_name = nullptr;
    2730              :             snapdev::timespec_ex    f_value = snapdev::timespec_ex();
    2731              :         };
    2732              : 
    2733            1 :         verify_t verify[] =
    2734              :         {
    2735              :             { "t01", { 123 + 5, 0 } },
    2736              :             { "t02", { 33 + 123, 0 } },
    2737              :             { "t03", { 123 - 5, 0 } },
    2738              :             { "t04", { 33 - 123, 0 } },
    2739              :             { "t11", { 123 + 5, 89'999'999 } },
    2740              :             { "t12", { 33 + 123, 501'923'820 } },
    2741              :             { "t13", { 123 - 6, 999'000'000 } },
    2742              :             { "t14", { 333 - 123, 982'019'920 } },
    2743              :             { "t21", { -123, 0 } },
    2744              :             { "t22", { 123, 0 } },
    2745              :             { "t31", { 177, 330'000'000 } },
    2746              :             { "t32", { 158, 310'731'200 } },
    2747            1 :         };
    2748              : 
    2749            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var;
    2750           13 :         for(auto const & v : verify)
    2751              :         {
    2752              : //std::cerr << "--- testing \"" << v.f_name << "\".\n";
    2753           36 :             var = s->get_variable(v.f_name);
    2754           12 :             CATCH_REQUIRE(var != nullptr);
    2755           12 :             CATCH_REQUIRE(var->get_name() == v.f_name);
    2756           12 :             CATCH_REQUIRE(var->get_type() == "timestamp");
    2757           12 :             CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_timestamp>(var)->get_timestamp() == v.f_value);
    2758              :         }
    2759            1 :     }
    2760           19 :     CATCH_END_SECTION()
    2761              : 
    2762           19 :     CATCH_START_SECTION("reporter_executor: verify hex() function")
    2763              :     {
    2764            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("verify_computation_timestamp.rprtr", g_program_verify_hex));
    2765            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    2766            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    2767            1 :         p->parse_program();
    2768              : 
    2769            1 :         CATCH_REQUIRE(s->get_statement_size() == 5);
    2770              : 
    2771            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    2772            1 :         e->start();
    2773            1 :         CATCH_REQUIRE(e->run());
    2774              : 
    2775              :         struct verify_t
    2776              :         {
    2777              :             char const *            f_name = nullptr;
    2778              :             char const *            f_value = nullptr;
    2779              :         };
    2780              : 
    2781            1 :         verify_t verify[] =
    2782              :         {
    2783              :             { "t01", "1a4fd2" },
    2784              :             { "t02", "abcdef" },
    2785              :             { "t03", "ABCDEF" },
    2786              :             { "t04", "00000001" },
    2787              :             { "t05", "00ABCDEF" },
    2788              :         };
    2789              : 
    2790            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var;
    2791            6 :         for(auto const & v : verify)
    2792              :         {
    2793           15 :             var = s->get_variable(v.f_name);
    2794            5 :             CATCH_REQUIRE(var != nullptr);
    2795            5 :             CATCH_REQUIRE(var->get_name() == v.f_name);
    2796            5 :             CATCH_REQUIRE(var->get_type() == "string");
    2797            5 :             CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var)->get_string() == v.f_value);
    2798              :         }
    2799            1 :     }
    2800           19 :     CATCH_END_SECTION()
    2801              : 
    2802           19 :     CATCH_START_SECTION("reporter_executor: verify now()")
    2803              :     {
    2804            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("verify_now.rprtr", g_program_verify_now));
    2805            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    2806            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    2807            1 :         p->parse_program();
    2808              : 
    2809            1 :         CATCH_REQUIRE(s->get_statement_size() == 2);
    2810              : 
    2811            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    2812            1 :         e->start();
    2813            1 :         CATCH_REQUIRE(e->run());
    2814              : 
    2815            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
    2816              : 
    2817            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var;
    2818            3 :         var = s->get_variable("about_now");
    2819            1 :         CATCH_REQUIRE(var != nullptr);
    2820            1 :         CATCH_REQUIRE(var->get_name() == "about_now");
    2821            1 :         CATCH_REQUIRE(var->get_type() == "timestamp");
    2822            1 :         snapdev::timespec_ex const value(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_timestamp>(var)->get_timestamp());
    2823            1 :         snapdev::timespec_ex const now(snapdev::now());
    2824            1 :         snapdev::timespec_ex const lower_value(now - snapdev::timespec_ex(1, 0));
    2825            1 :         CATCH_REQUIRE(lower_value <= value);
    2826            1 :         CATCH_REQUIRE(now >= value);
    2827            1 :     }
    2828           19 :     CATCH_END_SECTION()
    2829              : 
    2830           19 :     CATCH_START_SECTION("reporter_executor: verify max_pid()")
    2831              :     {
    2832            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("verify_max_pid.rprtr", g_program_verify_max_pid));
    2833            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    2834            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    2835            1 :         p->parse_program();
    2836              : 
    2837            1 :         CATCH_REQUIRE(s->get_statement_size() == 2);
    2838              : 
    2839            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    2840            1 :         e->start();
    2841            1 :         CATCH_REQUIRE(e->run());
    2842              : 
    2843            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
    2844              : 
    2845            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var;
    2846            3 :         var = s->get_variable("top_pid");
    2847            1 :         CATCH_REQUIRE(var != nullptr);
    2848            1 :         CATCH_REQUIRE(var->get_name() == "top_pid");
    2849            1 :         CATCH_REQUIRE(var->get_type() == "integer");
    2850            1 :         std::int64_t const value(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer());
    2851            1 :         CATCH_REQUIRE(cppthread::get_pid_max() == value);
    2852            1 :     }
    2853           19 :     CATCH_END_SECTION()
    2854              : 
    2855           19 :     CATCH_START_SECTION("reporter_executor: verify random()")
    2856              :     {
    2857            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("verify_random.rprtr", g_program_verify_random));
    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() == 4);
    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            1 :         CATCH_REQUIRE(e->run());
    2867              : 
    2868            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
    2869              : 
    2870            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var;
    2871            3 :         var = s->get_variable("any_number");
    2872            1 :         CATCH_REQUIRE(var != nullptr);
    2873            1 :         CATCH_REQUIRE(var->get_name() == "any_number");
    2874            1 :         CATCH_REQUIRE(var->get_type() == "integer");
    2875              : 
    2876            3 :         var = s->get_variable("positive");
    2877            1 :         CATCH_REQUIRE(var != nullptr);
    2878            1 :         CATCH_REQUIRE(var->get_name() == "positive");
    2879            1 :         CATCH_REQUIRE(var->get_type() == "integer");
    2880            1 :         std::int64_t const value(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer());
    2881            1 :         CATCH_REQUIRE(value >= 0);
    2882              : 
    2883            3 :         var = s->get_variable("positive_or_negative");
    2884            1 :         CATCH_REQUIRE(var != nullptr);
    2885            1 :         CATCH_REQUIRE(var->get_name() == "positive_or_negative");
    2886            1 :         CATCH_REQUIRE(var->get_type() == "integer");
    2887            1 :     }
    2888           19 :     CATCH_END_SECTION()
    2889              : 
    2890           19 :     CATCH_START_SECTION("reporter_executor: verify hostname")
    2891              :     {
    2892            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("verify_now.rprtr", g_program_verify_hostname));
    2893            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    2894            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    2895            1 :         p->parse_program();
    2896              : 
    2897            1 :         CATCH_REQUIRE(s->get_statement_size() == 2);
    2898              : 
    2899            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    2900            1 :         e->start();
    2901            1 :         CATCH_REQUIRE(e->run());
    2902              : 
    2903            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
    2904              : 
    2905            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var;
    2906            3 :         var = s->get_variable("host_name");
    2907            1 :         CATCH_REQUIRE(var != nullptr);
    2908            1 :         CATCH_REQUIRE(var->get_name() == "host_name");
    2909            1 :         CATCH_REQUIRE(var->get_type() == "string");
    2910            1 :         std::string const host_name(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var)->get_string());
    2911            1 :         std::string const expected_name(snapdev::gethostname());
    2912            1 :         CATCH_REQUIRE(expected_name == host_name);
    2913            1 :     }
    2914           19 :     CATCH_END_SECTION()
    2915              : 
    2916           19 :     CATCH_START_SECTION("reporter_executor: verify kill with number")
    2917              :     {
    2918            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("verify_kill_number.rprtr", g_program_verify_kill_number));
    2919            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    2920            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    2921            1 :         p->parse_program();
    2922              : 
    2923            1 :         CATCH_REQUIRE(s->get_statement_size() == 2);
    2924              : 
    2925            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    2926            1 :         e->start();
    2927            1 :         CATCH_REQUIRE(e->run());
    2928              : 
    2929            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
    2930            1 :     }
    2931           19 :     CATCH_END_SECTION()
    2932              : 
    2933           19 :     CATCH_START_SECTION("reporter_executor: verify kill with identifier")
    2934              :     {
    2935            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("verify_kill_identifier.rprtr", g_program_verify_kill_identifier));
    2936            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    2937            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    2938            1 :         p->parse_program();
    2939              : 
    2940            1 :         CATCH_REQUIRE(s->get_statement_size() == 2);
    2941              : 
    2942            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    2943            1 :         e->start();
    2944            1 :         CATCH_REQUIRE(e->run());
    2945              : 
    2946            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
    2947            1 :     }
    2948           19 :     CATCH_END_SECTION()
    2949              : 
    2950           19 :     CATCH_START_SECTION("reporter_executor: verify kill with string")
    2951              :     {
    2952            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("verify_kill_string.rprtr", g_program_verify_kill_string));
    2953            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    2954            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    2955            1 :         p->parse_program();
    2956              : 
    2957            1 :         CATCH_REQUIRE(s->get_statement_size() == 2);
    2958              : 
    2959            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    2960            1 :         e->start();
    2961            1 :         CATCH_REQUIRE(e->run());
    2962              : 
    2963            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
    2964            1 :     }
    2965           19 :     CATCH_END_SECTION()
    2966              : 
    2967           19 :     CATCH_START_SECTION("reporter_executor: verify computation (address)")
    2968              :     {
    2969            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));
    2970            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    2971            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    2972            1 :         p->parse_program();
    2973              : 
    2974            1 :         CATCH_REQUIRE(s->get_statement_size() == 4);
    2975              : 
    2976            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    2977            1 :         e->start();
    2978            1 :         CATCH_REQUIRE(e->run());
    2979              : 
    2980              :     //"set_variable(name: t01, value: <127.0.0.1> + 256)\n"
    2981              :     //"set_variable(name: t02, value: 256 + <192.168.3.57>)\n"
    2982              :     //"set_variable(name: t03, value: <172.131.4.1> - 256)\n"
    2983              :     //"set_variable(name: t11, value: <10.5.34.255> - <10.5.33.0>)\n"
    2984              : 
    2985            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var;
    2986            1 :         addr::addr a;
    2987              : 
    2988            3 :         var = s->get_variable("t01");
    2989            1 :         CATCH_REQUIRE(var != nullptr);
    2990            1 :         CATCH_REQUIRE(var->get_name() == "t01");
    2991            1 :         CATCH_REQUIRE(var->get_type() == "address");
    2992            3 :         a = addr::string_to_addr("127.0.1.1");
    2993            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_address>(var)->get_address() == a);
    2994              : 
    2995            3 :         var = s->get_variable("t02");
    2996            1 :         CATCH_REQUIRE(var != nullptr);
    2997            1 :         CATCH_REQUIRE(var->get_name() == "t02");
    2998            1 :         CATCH_REQUIRE(var->get_type() == "address");
    2999            3 :         a = addr::string_to_addr("192.168.4.57");
    3000            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_address>(var)->get_address() == a);
    3001              : 
    3002            3 :         var = s->get_variable("t03");
    3003            1 :         CATCH_REQUIRE(var != nullptr);
    3004            1 :         CATCH_REQUIRE(var->get_name() == "t03");
    3005            1 :         CATCH_REQUIRE(var->get_type() == "address");
    3006            3 :         a = addr::string_to_addr("172.131.3.1");
    3007            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_address>(var)->get_address() == a);
    3008              : 
    3009            3 :         var = s->get_variable("t11");
    3010            1 :         CATCH_REQUIRE(var != nullptr);
    3011            1 :         CATCH_REQUIRE(var->get_name() == "t11");
    3012            1 :         CATCH_REQUIRE(var->get_type() == "integer");
    3013            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == 511);
    3014            1 :     }
    3015           19 :     CATCH_END_SECTION()
    3016              : 
    3017           19 :     CATCH_START_SECTION("reporter_executor: verify computation (concatenation)")
    3018              :     {
    3019            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));
    3020            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    3021            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    3022            1 :         p->parse_program();
    3023              : 
    3024            1 :         CATCH_REQUIRE(s->get_statement_size() == 21);
    3025              : 
    3026            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    3027            1 :         e->start();
    3028            1 :         CATCH_REQUIRE(e->run());
    3029              : 
    3030              :         struct verify_t
    3031              :         {
    3032              :             char const *            f_name = nullptr;
    3033              :             char const *            f_value = nullptr;
    3034              :             char const *            f_type = nullptr;
    3035              :         };
    3036              : 
    3037            1 :         verify_t verify[] =
    3038              :         {
    3039              :             { "t01", "identifier", "identifier" },
    3040              :             { "t11", "single string", "string" },
    3041              :             { "t12", "single string", "string" },
    3042              :             { "t13", "single string", "string" },
    3043              :             { "t14", "double string", "string" },
    3044              :             { "t21", "identify", "identifier" },
    3045              :             { "t22", "single string", "string" },
    3046              :             { "t23", "double string", "string" },
    3047              :             { "t31", "single36", "string" },
    3048              :             { "t32", "258single", "string" },
    3049              :             { "t33", "string102", "string" },
    3050              :             { "t34", "5005double", "string" },
    3051              :             { "t41", "single[0-9]+", "regex" },
    3052              :             { "t42", "[0-9]+single", "regex" },
    3053              :             { "t43", "string[0-9]+", "regex" },
    3054              :             { "t44", "[0-9]+double", "regex" },
    3055              :             { "t45", "a\\|b[0-9]+", "regex" },
    3056              :             { "t46", "[0-9]+c\\{3,9\\}", "regex" },
    3057              :             { "t47", "\\[a-z\\]\\?[0-9]+", "regex" },
    3058              :             { "t48", "[0-9]+a\\?b\\?c\\?", "regex" },
    3059              :             { "t49", "[0-9]+(a|b|c)?", "regex" },
    3060              :         };
    3061              : 
    3062            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var;
    3063           22 :         for(auto const & v : verify)
    3064              :         {
    3065              : //std::cerr << "--- testing \"" << v.f_name << "\".\n";
    3066           63 :             var = s->get_variable(v.f_name);
    3067           21 :             CATCH_REQUIRE(var != nullptr);
    3068           21 :             CATCH_REQUIRE(var->get_name() == v.f_name);
    3069           21 :             CATCH_REQUIRE(var->get_type() == v.f_type);
    3070           21 :             CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var)->get_string() == v.f_value);
    3071              :         }
    3072            1 :     }
    3073           19 :     CATCH_END_SECTION()
    3074              : 
    3075           19 :     CATCH_START_SECTION("reporter_executor: verify computation (string repeat)")
    3076              :     {
    3077            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));
    3078            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    3079            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    3080            1 :         p->parse_program();
    3081              : 
    3082            1 :         CATCH_REQUIRE(s->get_statement_size() == 4);
    3083              : 
    3084            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    3085            1 :         e->start();
    3086            1 :         CATCH_REQUIRE(e->run());
    3087              : 
    3088              :         struct verify_t
    3089              :         {
    3090              :             char const *            f_name = nullptr;
    3091              :             char const *            f_value = nullptr;
    3092              :         };
    3093              : 
    3094            1 :         verify_t verify[] =
    3095              :         {
    3096              :             { "t01", "abcabcabc" },
    3097              :             { "t02", "xyzxyzxyzxyzxyz" },
    3098              :             { "t03", "" },
    3099              :             { "t04", "one" },
    3100              :         };
    3101              : 
    3102            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var;
    3103            5 :         for(auto const & v : verify)
    3104              :         {
    3105              : //std::cerr << "--- testing \"" << v.f_name << "\".\n";
    3106           12 :             var = s->get_variable(v.f_name);
    3107            4 :             CATCH_REQUIRE(var != nullptr);
    3108            4 :             CATCH_REQUIRE(var->get_name() == v.f_name);
    3109            4 :             CATCH_REQUIRE(var->get_type() == "string");
    3110            4 :             CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var)->get_string() == v.f_value);
    3111              :         }
    3112            1 :     }
    3113           19 :     CATCH_END_SECTION()
    3114              : 
    3115           19 :     CATCH_START_SECTION("reporter_executor: verify variable in string")
    3116              :     {
    3117            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));
    3118            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    3119            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    3120            1 :         p->parse_program();
    3121              : 
    3122            1 :         CATCH_REQUIRE(s->get_statement_size() == 2);
    3123              : 
    3124            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    3125            1 :         e->start();
    3126            1 :         CATCH_REQUIRE(e->run());
    3127              : 
    3128              :         struct verify_t
    3129              :         {
    3130              :             char const *            f_name = nullptr;
    3131              :             char const *            f_value = nullptr;
    3132              :         };
    3133              : 
    3134            1 :         verify_t verify[] =
    3135              :         {
    3136              :             { "foo", "abc" },
    3137              :             { "bar", "[abc]" },
    3138              :         };
    3139              : 
    3140            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var;
    3141            3 :         for(auto const & v : verify)
    3142              :         {
    3143              : //std::cerr << "--- testing \"" << v.f_name << "\".\n";
    3144            6 :             var = s->get_variable(v.f_name);
    3145            2 :             CATCH_REQUIRE(var != nullptr);
    3146            2 :             CATCH_REQUIRE(var->get_name() == v.f_name);
    3147            2 :             CATCH_REQUIRE(var->get_type() == "string");
    3148            2 :             CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var)->get_string() == v.f_value);
    3149              :         }
    3150            1 :     }
    3151           19 :     CATCH_END_SECTION()
    3152              : 
    3153           19 :     CATCH_START_SECTION("reporter_executor: print() + message")
    3154              :     {
    3155            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("print_message.rprtr", g_program_print_message));
    3156            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    3157            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    3158            1 :         p->parse_program();
    3159              : 
    3160            1 :         CATCH_REQUIRE(s->get_statement_size() == 2);
    3161              : 
    3162            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    3163            1 :         e->start();
    3164              : 
    3165            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
    3166            1 :     }
    3167           19 :     CATCH_END_SECTION()
    3168           19 : }
    3169              : 
    3170              : 
    3171            9 : CATCH_TEST_CASE("reporter_executor_message", "[executor][reporter][message]")
    3172              : {
    3173            9 :     CATCH_START_SECTION("reporter_executor_message: send/receive one message")
    3174              :     {
    3175            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));
    3176            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    3177            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    3178            1 :         p->parse_program();
    3179              : 
    3180            1 :         CATCH_REQUIRE(s->get_statement_size() == 16);
    3181              : 
    3182            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    3183            1 :         e->start();
    3184            1 :         addr::addr a;
    3185            1 :         sockaddr_in ip = {
    3186              :             .sin_family = AF_INET,
    3187            1 :             .sin_port = htons(20002),
    3188              :             .sin_addr = {
    3189            1 :                 .s_addr = htonl(0x7f000001),
    3190              :             },
    3191              :             .sin_zero = {},
    3192            1 :         };
    3193            1 :         a.set_ipv4(ip);
    3194            1 :         messenger_responder::pointer_t messenger(std::make_shared<messenger_responder>(
    3195              :                   a
    3196            1 :                 , ed::mode_t::MODE_PLAIN
    3197            2 :                 , messenger_responder::sequence_t::SEQUENCE_ONE_MESSAGE));
    3198            1 :         ed::communicator::instance()->add_connection(messenger);
    3199            1 :         messenger_timer::pointer_t timer(std::make_shared<messenger_timer>(messenger));
    3200            1 :         ed::communicator::instance()->add_connection(timer);
    3201            1 :         messenger->set_timer(timer);
    3202              : 
    3203            1 :         CATCH_REQUIRE(e->run());
    3204              : 
    3205              :         // if we exited because of our timer, then the test did not pass
    3206              :         //
    3207            1 :         CATCH_REQUIRE_FALSE(timer->timed_out_prima());
    3208              : 
    3209            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
    3210              : 
    3211            3 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var(s->get_variable("command"));
    3212            1 :         CATCH_REQUIRE(var != nullptr);
    3213            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable_string::pointer_t v(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var));
    3214            1 :         CATCH_REQUIRE(v != nullptr);
    3215            1 :         CATCH_REQUIRE(v->get_string() == "REGISTER");
    3216              : 
    3217            3 :         var = s->get_variable("register_version");
    3218            1 :         CATCH_REQUIRE(var != nullptr);
    3219            1 :         v = std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var);
    3220            1 :         CATCH_REQUIRE(v != nullptr);
    3221            1 :         CATCH_REQUIRE(v->get_string() == "1");
    3222              : 
    3223            3 :         var = s->get_variable("register_service");
    3224            1 :         CATCH_REQUIRE(var != nullptr);
    3225            1 :         v = std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var);
    3226            1 :         CATCH_REQUIRE(v != nullptr);
    3227            1 :         CATCH_REQUIRE(v->get_string() == "responder");
    3228            1 :     }
    3229            9 :     CATCH_END_SECTION()
    3230              : 
    3231            9 :     CATCH_START_SECTION("reporter_executor_message: receive one unwanted/unexpected message")
    3232              :     {
    3233            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));
    3234            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    3235            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    3236            1 :         p->parse_program();
    3237              : 
    3238            1 :         CATCH_REQUIRE(s->get_statement_size() == 13);
    3239              : 
    3240            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    3241            1 :         e->start();
    3242            1 :         addr::addr a;
    3243            1 :         sockaddr_in ip = {
    3244              :             .sin_family = AF_INET,
    3245            1 :             .sin_port = htons(20002),
    3246              :             .sin_addr = {
    3247            1 :                 .s_addr = htonl(0x7f000001),
    3248              :             },
    3249              :             .sin_zero = {},
    3250            1 :         };
    3251            1 :         a.set_ipv4(ip);
    3252            1 :         messenger_responder::pointer_t messenger(std::make_shared<messenger_responder>(
    3253              :                   a
    3254            1 :                 , ed::mode_t::MODE_PLAIN
    3255            2 :                 , messenger_responder::sequence_t::SEQUENCE_UNWANTED_MESSAGE));
    3256            1 :         ed::communicator::instance()->add_connection(messenger);
    3257            1 :         e->set_thread_done_callback([messenger]()
    3258              :             {
    3259            1 :                 ed::communicator::instance()->remove_connection(messenger);
    3260            1 :             });
    3261              : 
    3262            1 :         CATCH_REQUIRE(e->run());
    3263              : 
    3264            1 :         CATCH_REQUIRE(s->get_exit_code() == 1);
    3265            1 :     }
    3266            9 :     CATCH_END_SECTION()
    3267              : 
    3268            9 :     CATCH_START_SECTION("reporter_executor_message: send message with unsupported parameter type fails")
    3269              :     {
    3270            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));
    3271            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    3272            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    3273            1 :         p->parse_program();
    3274              : 
    3275            1 :         CATCH_REQUIRE(s->get_statement_size() == 12);
    3276              : 
    3277            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    3278            1 :         e->start();
    3279            1 :         addr::addr a;
    3280            1 :         sockaddr_in ip = {
    3281              :             .sin_family = AF_INET,
    3282            1 :             .sin_port = htons(20002),
    3283              :             .sin_addr = {
    3284            1 :                 .s_addr = htonl(0x7f000001),
    3285              :             },
    3286              :             .sin_zero = {},
    3287            1 :         };
    3288            1 :         a.set_ipv4(ip);
    3289            1 :         messenger_responder::pointer_t messenger(std::make_shared<messenger_responder>(
    3290              :                   a
    3291            1 :                 , ed::mode_t::MODE_PLAIN
    3292            2 :                 , messenger_responder::sequence_t::SEQUENCE_UNWANTED_MESSAGE));
    3293            1 :         ed::communicator::instance()->add_connection(messenger);
    3294            1 :         e->set_thread_done_callback([messenger]()
    3295              :             {
    3296            1 :                 ed::communicator::instance()->remove_connection(messenger);
    3297            1 :             });
    3298              : 
    3299            1 :         CATCH_REQUIRE(e->run());
    3300            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    3301              :               e->stop()
    3302              :             , ed::runtime_error
    3303              :             , Catch::Matchers::ExceptionMessage(
    3304              :                       "event_dispatcher_exception: message parameter type \"floating_point\" not supported yet."));
    3305              : 
    3306            1 :         CATCH_REQUIRE(s->get_exit_code() == -1);
    3307            1 :     }
    3308            9 :     CATCH_END_SECTION()
    3309              : 
    3310            9 :     CATCH_START_SECTION("reporter_executor_message: save message parameter identifier as an integer fails")
    3311              :     {
    3312            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));
    3313            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    3314            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    3315            1 :         p->parse_program();
    3316              : 
    3317            1 :         CATCH_REQUIRE(s->get_statement_size() == 12);
    3318              : 
    3319            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    3320            1 :         e->start();
    3321            1 :         addr::addr a;
    3322            1 :         sockaddr_in ip = {
    3323              :             .sin_family = AF_INET,
    3324            1 :             .sin_port = htons(20002),
    3325              :             .sin_addr = {
    3326            1 :                 .s_addr = htonl(0x7f000001),
    3327              :             },
    3328              :             .sin_zero = {},
    3329            1 :         };
    3330            1 :         a.set_ipv4(ip);
    3331            1 :         messenger_responder::pointer_t messenger(std::make_shared<messenger_responder>(
    3332              :                   a
    3333            1 :                 , ed::mode_t::MODE_PLAIN
    3334            2 :                 , messenger_responder::sequence_t::SEQUENCE_UNWANTED_MESSAGE));
    3335            1 :         ed::communicator::instance()->add_connection(messenger);
    3336            1 :         e->set_thread_done_callback([messenger]()
    3337              :             {
    3338            1 :                 ed::communicator::instance()->remove_connection(messenger);
    3339            1 :             });
    3340              : 
    3341            1 :         CATCH_REQUIRE(e->run());
    3342            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    3343              :               e->stop()
    3344              :             , ed::runtime_error
    3345              :             , Catch::Matchers::ExceptionMessage(
    3346              :                       "event_dispatcher_exception: value \"responder\" not recognized as a valid integer."));
    3347              : 
    3348            1 :         CATCH_REQUIRE(s->get_exit_code() == -1);
    3349            1 :     }
    3350            9 :     CATCH_END_SECTION()
    3351              : 
    3352            9 :     CATCH_START_SECTION("reporter_executor_message: save message parameter of type timestamp")
    3353              :     {
    3354            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));
    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              :         //CATCH_REQUIRE(s->get_statement_size() == 19);
    3360              : 
    3361            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    3362            1 :         e->start();
    3363            1 :         addr::addr a;
    3364            1 :         sockaddr_in ip = {
    3365              :             .sin_family = AF_INET,
    3366            1 :             .sin_port = htons(20002),
    3367              :             .sin_addr = {
    3368            1 :                 .s_addr = htonl(0x7f000001),
    3369              :             },
    3370              :             .sin_zero = {},
    3371            1 :         };
    3372            1 :         a.set_ipv4(ip);
    3373            1 :         messenger_responder::pointer_t messenger(std::make_shared<messenger_responder>(
    3374              :                   a
    3375            1 :                 , ed::mode_t::MODE_PLAIN
    3376            2 :                 , messenger_responder::sequence_t::SEQUENCE_TIMED_MESSAGE));
    3377            1 :         ed::communicator::instance()->add_connection(messenger);
    3378            1 :         e->set_thread_done_callback([messenger]()
    3379              :             {
    3380            1 :                 ed::communicator::instance()->remove_connection(messenger);
    3381            1 :             });
    3382              : 
    3383            1 :         CATCH_REQUIRE(e->run());
    3384            1 :         e->stop();
    3385              : 
    3386            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
    3387              : 
    3388            3 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var(s->get_variable("register_version"));
    3389            1 :         CATCH_REQUIRE(var != nullptr);
    3390            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable_integer::pointer_t vi(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var));
    3391            1 :         CATCH_REQUIRE(vi != nullptr);
    3392            1 :         CATCH_REQUIRE(vi->get_type() == "integer");
    3393            1 :         CATCH_REQUIRE(vi->get_integer() == 1);
    3394              : 
    3395            3 :         var = s->get_variable("default_integer");
    3396            1 :         CATCH_REQUIRE(var != nullptr);
    3397            1 :         vi = std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var);
    3398            1 :         CATCH_REQUIRE(vi != nullptr);
    3399            1 :         CATCH_REQUIRE(vi->get_type() == "integer");
    3400            1 :         CATCH_REQUIRE(vi->get_integer() == 0);
    3401              : 
    3402            3 :         var = s->get_variable("timed_value");
    3403            1 :         CATCH_REQUIRE(var != nullptr);
    3404            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable_timestamp::pointer_t vts(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_timestamp>(var));
    3405            1 :         CATCH_REQUIRE(vts != nullptr);
    3406            1 :         CATCH_REQUIRE(vts->get_type() == "timestamp");
    3407            1 :         snapdev::timespec_ex const param_timestamp(vts->get_timestamp());
    3408            1 :         snapdev::timespec_ex const now(snapdev::now());
    3409            1 :         snapdev::timespec_ex const minimum_value(now - snapdev::timespec_ex(1, 0));
    3410            1 :         CATCH_REQUIRE(param_timestamp >= minimum_value);
    3411            1 :         CATCH_REQUIRE(param_timestamp <= now);
    3412              : 
    3413            3 :         var = s->get_variable("default_time");
    3414            1 :         CATCH_REQUIRE(var != nullptr);
    3415            1 :         vts = std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_timestamp>(var);
    3416            1 :         CATCH_REQUIRE(vts != nullptr);
    3417            1 :         CATCH_REQUIRE(vts->get_type() == "timestamp");
    3418            1 :         CATCH_REQUIRE(vts->get_timestamp() == snapdev::timespec_ex());
    3419            1 :     }
    3420            9 :     CATCH_END_SECTION()
    3421              : 
    3422            9 :     CATCH_START_SECTION("reporter_executor_message: save message parameter with unknown type")
    3423              :     {
    3424            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));
    3425            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    3426            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    3427            1 :         p->parse_program();
    3428              : 
    3429            1 :         CATCH_REQUIRE(s->get_statement_size() == 12);
    3430              : 
    3431            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    3432            1 :         e->start();
    3433            1 :         addr::addr a;
    3434            1 :         sockaddr_in ip = {
    3435              :             .sin_family = AF_INET,
    3436            1 :             .sin_port = htons(20002),
    3437              :             .sin_addr = {
    3438            1 :                 .s_addr = htonl(0x7f000001),
    3439              :             },
    3440              :             .sin_zero = {},
    3441            1 :         };
    3442            1 :         a.set_ipv4(ip);
    3443            1 :         messenger_responder::pointer_t messenger(std::make_shared<messenger_responder>(
    3444              :                   a
    3445            1 :                 , ed::mode_t::MODE_PLAIN
    3446            2 :                 , messenger_responder::sequence_t::SEQUENCE_UNWANTED_MESSAGE));
    3447            1 :         ed::communicator::instance()->add_connection(messenger);
    3448            1 :         e->set_thread_done_callback([messenger]()
    3449              :             {
    3450            1 :                 ed::communicator::instance()->remove_connection(messenger);
    3451            1 :             });
    3452              : 
    3453            1 :         CATCH_REQUIRE(e->run());
    3454            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    3455              :               e->stop()
    3456              :             , ed::runtime_error
    3457              :             , Catch::Matchers::ExceptionMessage(
    3458              :                       "event_dispatcher_exception: unsupported type \"void\" for save_parameter_value()."));
    3459              : 
    3460            1 :         CATCH_REQUIRE(s->get_exit_code() == -1);
    3461            1 :     }
    3462            9 :     CATCH_END_SECTION()
    3463              : 
    3464            9 :     CATCH_START_SECTION("reporter_executor_message: send & receive complete messages")
    3465              :     {
    3466              :         // in this case, load the program from a file
    3467              :         // to verify that this works as expected
    3468              :         //
    3469            1 :         std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
    3470            1 :         std::string const filename(source_dir + "/tests/rprtr/send_and_receive_complete_messages");
    3471            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
    3472            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    3473            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    3474            1 :         p->parse_program();
    3475              : 
    3476            1 :         CATCH_REQUIRE(s->get_statement_size() == 34);
    3477              : 
    3478            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    3479            1 :         e->start();
    3480            1 :         addr::addr a;
    3481            1 :         sockaddr_in ip = {
    3482              :             .sin_family = AF_INET,
    3483            1 :             .sin_port = htons(20002),
    3484              :             .sin_addr = {
    3485            1 :                 .s_addr = htonl(0x7f000001),
    3486              :             },
    3487              :             .sin_zero = {},
    3488            1 :         };
    3489            1 :         a.set_ipv4(ip);
    3490            1 :         messenger_responder::pointer_t messenger(std::make_shared<messenger_responder>(
    3491              :                   a
    3492            1 :                 , ed::mode_t::MODE_PLAIN
    3493            2 :                 , messenger_responder::sequence_t::SEQUENCE_READY_HELP_MESSAGE));
    3494            1 :         ed::communicator::instance()->add_connection(messenger);
    3495            1 :         messenger_timer::pointer_t timer(std::make_shared<messenger_timer>(messenger));
    3496            1 :         ed::communicator::instance()->add_connection(timer);
    3497            1 :         messenger->set_timer(timer);
    3498              : 
    3499            1 :         CATCH_REQUIRE(e->run());
    3500              : 
    3501              :         // if we exited because of our timer, then the test did not pass
    3502              :         //
    3503            1 :         CATCH_REQUIRE_FALSE(timer->timed_out_prima());
    3504              : 
    3505            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
    3506              : 
    3507              :         // we unset that variable, make sure that worked
    3508              :         //
    3509            3 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var(s->get_variable("got_register"));
    3510            1 :         CATCH_REQUIRE(var == nullptr);
    3511              : 
    3512            3 :         var = s->get_variable("server");
    3513            1 :         CATCH_REQUIRE(var != nullptr);
    3514            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable_string::pointer_t str(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var));
    3515            1 :         CATCH_REQUIRE(str != nullptr);
    3516            1 :         CATCH_REQUIRE(str->get_type() == "string");
    3517            1 :         CATCH_REQUIRE(str->get_string() == "reporter_test_extension");
    3518              : 
    3519            3 :         var = s->get_variable("service");
    3520            1 :         CATCH_REQUIRE(var != nullptr);
    3521            1 :         str = std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var);
    3522            1 :         CATCH_REQUIRE(str != nullptr);
    3523            1 :         CATCH_REQUIRE(str->get_type() == "string");
    3524            1 :         CATCH_REQUIRE(str->get_string() == "test_processor");
    3525              : 
    3526            3 :         var = s->get_variable("sent_server");
    3527            1 :         CATCH_REQUIRE(var != nullptr);
    3528            1 :         str = std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var);
    3529            1 :         CATCH_REQUIRE(str != nullptr);
    3530            1 :         CATCH_REQUIRE(str->get_type() == "string");
    3531            1 :         CATCH_REQUIRE(str->get_string() == "reporter_test");
    3532              : 
    3533            3 :         var = s->get_variable("sent_service");
    3534            1 :         CATCH_REQUIRE(var != nullptr);
    3535            1 :         str = std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var);
    3536            1 :         CATCH_REQUIRE(str != nullptr);
    3537            1 :         CATCH_REQUIRE(str->get_type() == "string");
    3538            1 :         CATCH_REQUIRE(str->get_string() == "commands_message");
    3539            1 :     }
    3540            9 :     CATCH_END_SECTION()
    3541              : 
    3542            9 :     CATCH_START_SECTION("reporter_executor_message: verify last wait (disconnect -> HUP)")
    3543              :     {
    3544            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));
    3545            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    3546            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    3547            1 :         p->parse_program();
    3548              : 
    3549            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    3550            1 :         e->start();
    3551            1 :         addr::addr a;
    3552            1 :         sockaddr_in ip = {
    3553              :             .sin_family = AF_INET,
    3554            1 :             .sin_port = htons(20002),
    3555              :             .sin_addr = {
    3556            1 :                 .s_addr = htonl(0x7f000001),
    3557              :             },
    3558              :             .sin_zero = {},
    3559            1 :         };
    3560            1 :         a.set_ipv4(ip);
    3561            1 :         messenger_responder::pointer_t messenger(std::make_shared<messenger_responder>(
    3562              :                   a
    3563            1 :                 , ed::mode_t::MODE_PLAIN
    3564            2 :                 , messenger_responder::sequence_t::SEQUENCE_ONE_MESSAGE));
    3565            1 :         ed::communicator::instance()->add_connection(messenger);
    3566            1 :         messenger_timer::pointer_t timer(std::make_shared<messenger_timer>(messenger));
    3567            1 :         ed::communicator::instance()->add_connection(timer);
    3568            1 :         messenger->set_timer(timer);
    3569            1 :         e->set_thread_done_callback([messenger, timer]()
    3570              :             {
    3571            1 :                 ed::communicator::instance()->remove_connection(messenger);
    3572            1 :                 ed::communicator::instance()->remove_connection(timer);
    3573            1 :             });
    3574            1 :         CATCH_REQUIRE(e->run());
    3575            1 :         e->stop();
    3576              : 
    3577              :         // if we exited because of our timer, then the test did not pass
    3578              :         //
    3579            1 :         CATCH_REQUIRE_FALSE(timer->timed_out_prima());
    3580              : 
    3581            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
    3582            1 :     }
    3583            9 :     CATCH_END_SECTION()
    3584              : 
    3585            9 :     CATCH_START_SECTION("reporter_executor_message: wait for timeout (to make sure we DO NOT receive extra messages)")
    3586              :     {
    3587            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));
    3588            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    3589            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    3590            1 :         p->parse_program();
    3591              : 
    3592            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    3593            1 :         e->start();
    3594            1 :         addr::addr a;
    3595            1 :         sockaddr_in ip = {
    3596              :             .sin_family = AF_INET,
    3597            1 :             .sin_port = htons(20002),
    3598              :             .sin_addr = {
    3599            1 :                 .s_addr = htonl(0x7f000001),
    3600              :             },
    3601              :             .sin_zero = {},
    3602            1 :         };
    3603            1 :         a.set_ipv4(ip);
    3604            1 :         messenger_responder::pointer_t messenger(std::make_shared<messenger_responder>(
    3605              :                   a
    3606            1 :                 , ed::mode_t::MODE_PLAIN
    3607            2 :                 , messenger_responder::sequence_t::SEQUENCE_ONE_MESSAGE));
    3608            1 :         ed::communicator::instance()->add_connection(messenger);
    3609            1 :         messenger_timer::pointer_t timer(std::make_shared<messenger_timer>(messenger));
    3610            1 :         ed::communicator::instance()->add_connection(timer);
    3611            1 :         messenger->set_timer(timer);
    3612            1 :         e->set_thread_done_callback([messenger, timer]()
    3613              :             {
    3614            1 :                 ed::communicator::instance()->remove_connection(messenger);
    3615            1 :                 ed::communicator::instance()->remove_connection(timer);
    3616            1 :             });
    3617            1 :         CATCH_REQUIRE(e->run());
    3618            1 :         e->stop();
    3619              : 
    3620            1 :         CATCH_REQUIRE_FALSE(timer->timed_out_prima());
    3621            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
    3622            1 :     }
    3623            9 :     CATCH_END_SECTION()
    3624            9 : }
    3625              : 
    3626              : 
    3627           10 : CATCH_TEST_CASE("reporter_executor_variables", "[executor][reporter][variable]")
    3628              : {
    3629           10 :     CATCH_START_SECTION("reporter_executor_variables: undefined variable")
    3630              :     {
    3631            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));
    3632            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    3633            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    3634            1 :         p->parse_program();
    3635              : 
    3636            1 :         CATCH_REQUIRE(s->get_statement_size() == 5);
    3637              : 
    3638            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    3639            1 :         e->start();
    3640            1 :         CATCH_REQUIRE(e->run());
    3641              : 
    3642            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
    3643            1 :     }
    3644           10 :     CATCH_END_SECTION()
    3645              : 
    3646           10 :     CATCH_START_SECTION("reporter_executor_variables: detect integer variable")
    3647              :     {
    3648            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));
    3649            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    3650            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    3651            1 :         p->parse_program();
    3652              : 
    3653            1 :         CATCH_REQUIRE(s->get_statement_size() == 10);
    3654              : 
    3655            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    3656            1 :         e->start();
    3657            1 :         CATCH_REQUIRE(e->run());
    3658              : 
    3659            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
    3660            1 :     }
    3661           10 :     CATCH_END_SECTION()
    3662              : 
    3663           10 :     CATCH_START_SECTION("reporter_executor_variables: detect string variable")
    3664              :     {
    3665            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));
    3666            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    3667            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    3668            1 :         p->parse_program();
    3669              : 
    3670            1 :         CATCH_REQUIRE(s->get_statement_size() == 10);
    3671              : 
    3672            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    3673            1 :         e->start();
    3674            1 :         CATCH_REQUIRE(e->run());
    3675              : 
    3676            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
    3677            1 :     }
    3678           10 :     CATCH_END_SECTION()
    3679              : 
    3680           10 :     CATCH_START_SECTION("reporter_executor_variables: if variable")
    3681              :     {
    3682            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));
    3683            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    3684            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    3685            1 :         p->parse_program();
    3686              : 
    3687            1 :         CATCH_REQUIRE(s->get_statement_size() == 104);
    3688              : 
    3689            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    3690            1 :         e->start();
    3691            1 :         CATCH_REQUIRE(e->run());
    3692              : 
    3693            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
    3694            1 :     }
    3695           10 :     CATCH_END_SECTION()
    3696              : 
    3697           10 :     CATCH_START_SECTION("reporter_executor_variables: compare and if")
    3698              :     {
    3699            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_compare_and_if.rprtr", g_program_compare_and_if));
    3700            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    3701            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    3702            1 :         p->parse_program();
    3703              : 
    3704            1 :         CATCH_REQUIRE(s->get_statement_size() == 116);
    3705              : 
    3706            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    3707            1 :         e->start();
    3708            1 :         CATCH_REQUIRE(e->run());
    3709              : 
    3710            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
    3711            1 :     }
    3712           10 :     CATCH_END_SECTION()
    3713              : 
    3714           10 :     CATCH_START_SECTION("reporter_executor_variables: void variable cloning")
    3715              :     {
    3716              :         // Note: at the moment there is no call to the clone() function
    3717              :         //       inside the library, so make sure it works as expected
    3718              :         //       within the test
    3719              :         //
    3720            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::variable_void>("void_var"));
    3721            1 :         CATCH_REQUIRE(var != nullptr);
    3722              : 
    3723            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable_void::pointer_t v(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_void>(var));
    3724            1 :         CATCH_REQUIRE(v != nullptr);
    3725              : 
    3726            3 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t clone(v->clone("clone"));
    3727            1 :         CATCH_REQUIRE(clone != nullptr);
    3728              : 
    3729            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable_void::pointer_t c(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_void>(clone));
    3730            1 :         CATCH_REQUIRE(c != nullptr);
    3731              : 
    3732            3 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t clone2(var->clone("clone2"));
    3733            1 :         CATCH_REQUIRE(clone2 != nullptr);
    3734              : 
    3735            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable_void::pointer_t c2(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_void>(clone2));
    3736            1 :         CATCH_REQUIRE(c2 != nullptr);
    3737            1 :     }
    3738           10 :     CATCH_END_SECTION()
    3739              : 
    3740           10 :     CATCH_START_SECTION("reporter_executor_variables: list variable")
    3741              :     {
    3742              :         // Note: some of the list variable functions are not fully tested
    3743              :         //       from within the app. so test more here
    3744              :         //
    3745            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t list(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::variable_list>("list_var"));
    3746            1 :         CATCH_REQUIRE(list != nullptr);
    3747              : 
    3748            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable_list::pointer_t l(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_list>(list));
    3749            1 :         CATCH_REQUIRE(l != nullptr);
    3750              : 
    3751            1 :         CATCH_REQUIRE(l->get_item_size() == 0);
    3752              : 
    3753            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var1(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::variable_void>("void_var"));
    3754            1 :         CATCH_REQUIRE(var1 != nullptr);
    3755            1 :         l->add_item(var1);
    3756            1 :         CATCH_REQUIRE(l->get_item(0) == var1);
    3757            1 :         CATCH_REQUIRE(l->get_item(-1) == nullptr);
    3758            1 :         CATCH_REQUIRE(l->get_item(1) == nullptr);
    3759              : 
    3760            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var2(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>("integer_var"));
    3761            1 :         CATCH_REQUIRE(var2 != nullptr);
    3762            1 :         l->add_item(var2);
    3763            1 :         CATCH_REQUIRE(l->get_item(0) == var2);      // this is a map so the order is sorted by variable name
    3764            1 :         CATCH_REQUIRE(l->get_item(-1) == nullptr);
    3765            1 :         CATCH_REQUIRE(l->get_item(1) == var1);
    3766            1 :         CATCH_REQUIRE(l->get_item(2) == nullptr);
    3767            3 :         CATCH_REQUIRE(l->get_item("void_var") == var1);
    3768            3 :         CATCH_REQUIRE(l->get_item("integer_var") == var2);
    3769            3 :         CATCH_REQUIRE(l->get_item("undefined_var") == nullptr);
    3770              : 
    3771            5 :         CATCH_REQUIRE_THROWS_MATCHES(
    3772              :               l->add_item(var1)
    3773              :             , ed::runtime_error
    3774              :             , Catch::Matchers::ExceptionMessage("event_dispatcher_exception: variable_list::add_item() trying to re-add item named \"void_var\"."));
    3775              : 
    3776            5 :         CATCH_REQUIRE_THROWS_MATCHES(
    3777              :               l->add_item(var2)
    3778              :             , ed::runtime_error
    3779              :             , Catch::Matchers::ExceptionMessage("event_dispatcher_exception: variable_list::add_item() trying to re-add item named \"integer_var\"."));
    3780              : 
    3781            3 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t clone(list->clone("clone"));
    3782            1 :         CATCH_REQUIRE(clone != nullptr);
    3783            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable_list::pointer_t l2(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_list>(clone));
    3784            1 :         CATCH_REQUIRE(l2 != nullptr);
    3785              : 
    3786            1 :         CATCH_REQUIRE(l2->get_item(-1) == nullptr);
    3787            1 :         CATCH_REQUIRE(l2->get_item(2) == nullptr);
    3788              : 
    3789              :         // the items are also cloned so we can quickly test that they are not
    3790              :         // equal and then we can verify the type or the name
    3791              :         //
    3792            1 :         CATCH_REQUIRE(l2->get_item(0) != var1);
    3793            1 :         CATCH_REQUIRE(l2->get_item(1) != var1);
    3794            1 :         CATCH_REQUIRE(l2->get_item(0) != var2);
    3795            1 :         CATCH_REQUIRE(l2->get_item(1) != var2);
    3796              : 
    3797            1 :         CATCH_REQUIRE(l2->get_item(0)->get_type() == "integer");
    3798            1 :         CATCH_REQUIRE(l2->get_item(1)->get_type() == "void");
    3799              : 
    3800              :         // make sure original is still valid
    3801              :         //
    3802            1 :         CATCH_REQUIRE(l->get_item(0) == var2);
    3803            1 :         CATCH_REQUIRE(l->get_item(-1) == nullptr);
    3804            1 :         CATCH_REQUIRE(l->get_item(1) == var1);
    3805            1 :         CATCH_REQUIRE(l->get_item(2) == nullptr);
    3806            1 :     }
    3807           10 :     CATCH_END_SECTION()
    3808              : 
    3809           10 :     CATCH_START_SECTION("reporter_executor_variables: primary variable references")
    3810              :     {
    3811            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));
    3812            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    3813            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    3814            1 :         p->parse_program();
    3815              : 
    3816            1 :         CATCH_REQUIRE(s->get_statement_size() == 14);
    3817              : 
    3818            3 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var(s->get_variable("my_string_var"));
    3819            1 :         CATCH_REQUIRE(var == nullptr);
    3820            3 :         var = s->get_variable("longer_string_var");
    3821            1 :         CATCH_REQUIRE(var == nullptr);
    3822            3 :         var = s->get_variable("my_integer_var");
    3823            1 :         CATCH_REQUIRE(var == nullptr);
    3824            3 :         var = s->get_variable("longer_integer_var");
    3825            1 :         CATCH_REQUIRE(var == nullptr);
    3826            3 :         var = s->get_variable("my_floating_point_var");
    3827            1 :         CATCH_REQUIRE(var == nullptr);
    3828            3 :         var = s->get_variable("longer_floating_point_var");
    3829            1 :         CATCH_REQUIRE(var == nullptr);
    3830            3 :         var = s->get_variable("my_identifier_var");
    3831            1 :         CATCH_REQUIRE(var == nullptr);
    3832            3 :         var = s->get_variable("longer_identifier_var");
    3833            1 :         CATCH_REQUIRE(var == nullptr);
    3834            3 :         var = s->get_variable("my_regex_var");
    3835            1 :         CATCH_REQUIRE(var == nullptr);
    3836            3 :         var = s->get_variable("longer_regex_var");
    3837            1 :         CATCH_REQUIRE(var == nullptr);
    3838            3 :         var = s->get_variable("my_address_var");
    3839            1 :         CATCH_REQUIRE(var == nullptr);
    3840            3 :         var = s->get_variable("longer_address_var");
    3841            1 :         CATCH_REQUIRE(var == nullptr);
    3842            3 :         var = s->get_variable("my_timestamp_var");
    3843            1 :         CATCH_REQUIRE(var == nullptr);
    3844            3 :         var = s->get_variable("longer_timestamp_var");
    3845            1 :         CATCH_REQUIRE(var == nullptr);
    3846              : 
    3847            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    3848            1 :         e->start();
    3849            1 :         CATCH_REQUIRE(e->run());
    3850              : 
    3851            3 :         var = s->get_variable("my_string_var");
    3852            1 :         CATCH_REQUIRE(var != nullptr);
    3853            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable_string::pointer_t vs(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var));
    3854            1 :         CATCH_REQUIRE(vs != nullptr);
    3855            1 :         CATCH_REQUIRE(vs->get_type() == "string");
    3856            1 :         CATCH_REQUIRE(vs->get_string() == "foo");
    3857              : 
    3858            3 :         var = s->get_variable("longer_string_var");
    3859            1 :         CATCH_REQUIRE(var != nullptr);
    3860            1 :         vs = std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var);
    3861            1 :         CATCH_REQUIRE(vs != nullptr);
    3862            1 :         CATCH_REQUIRE(vs->get_type() == "string");
    3863            1 :         CATCH_REQUIRE(vs->get_string() == "foo");
    3864              : 
    3865            3 :         var = s->get_variable("my_integer_var");
    3866            1 :         CATCH_REQUIRE(var != nullptr);
    3867            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable_integer::pointer_t vi(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var));
    3868            1 :         CATCH_REQUIRE(vi != nullptr);
    3869            1 :         CATCH_REQUIRE(vi->get_type() == "integer");
    3870            1 :         CATCH_REQUIRE(vi->get_integer() == 41);
    3871              : 
    3872            3 :         var = s->get_variable("longer_integer_var");
    3873            1 :         CATCH_REQUIRE(var != nullptr);
    3874            1 :         vi = std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var);
    3875            1 :         CATCH_REQUIRE(vi != nullptr);
    3876            1 :         CATCH_REQUIRE(vi->get_type() == "integer");
    3877            1 :         CATCH_REQUIRE(vi->get_integer() == 41);
    3878              : 
    3879            3 :         var = s->get_variable("my_floating_point_var");
    3880            1 :         CATCH_REQUIRE(var != nullptr);
    3881            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable_floating_point::pointer_t vf(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_floating_point>(var));
    3882            1 :         CATCH_REQUIRE(vf != nullptr);
    3883            1 :         CATCH_REQUIRE(vf->get_type() == "floating_point");
    3884            1 :         CATCH_REQUIRE(vf->get_floating_point() == 303.601);
    3885              : 
    3886            3 :         var = s->get_variable("longer_floating_point_var");
    3887            1 :         CATCH_REQUIRE(var != nullptr);
    3888            1 :         vf = std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_floating_point>(var);
    3889            1 :         CATCH_REQUIRE(vf != nullptr);
    3890            1 :         CATCH_REQUIRE(vf->get_type() == "floating_point");
    3891            1 :         CATCH_REQUIRE(vf->get_floating_point() == 303.601);
    3892              : 
    3893            3 :         var = s->get_variable("my_identifier_var");
    3894            1 :         CATCH_REQUIRE(var != nullptr);
    3895            1 :         vs = std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var);
    3896            1 :         CATCH_REQUIRE(vs != nullptr);
    3897            1 :         CATCH_REQUIRE(vs->get_type() == "identifier");
    3898            1 :         CATCH_REQUIRE(vs->get_string() == "bar");
    3899              : 
    3900            3 :         var = s->get_variable("longer_identifier_var");
    3901            1 :         CATCH_REQUIRE(var != nullptr);
    3902            1 :         vs = std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var);
    3903            1 :         CATCH_REQUIRE(vs != nullptr);
    3904            1 :         CATCH_REQUIRE(vs->get_type() == "identifier");
    3905            1 :         CATCH_REQUIRE(vs->get_string() == "bar");
    3906              : 
    3907            3 :         var = s->get_variable("my_regex_var");
    3908            1 :         CATCH_REQUIRE(var != nullptr);
    3909            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable_regex::pointer_t vre(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_regex>(var));
    3910            1 :         CATCH_REQUIRE(vre != nullptr);
    3911            1 :         CATCH_REQUIRE(vre->get_type() == "regex");
    3912            1 :         CATCH_REQUIRE(vre->get_regex() == "^[regex]$");
    3913              : 
    3914            3 :         var = s->get_variable("longer_regex_var");
    3915            1 :         CATCH_REQUIRE(var != nullptr);
    3916            1 :         vre = std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_regex>(var);
    3917            1 :         CATCH_REQUIRE(vre != nullptr);
    3918            1 :         CATCH_REQUIRE(vre->get_type() == "regex");
    3919            1 :         CATCH_REQUIRE(vre->get_regex() == "^[regex]$");
    3920              : 
    3921            1 :         addr::addr a;
    3922            1 :         sockaddr_in ip = {
    3923              :             .sin_family = AF_INET,
    3924            1 :             .sin_port = htons(89),
    3925              :             .sin_addr = {
    3926            1 :                 .s_addr = htonl(0x0A0C0E10),
    3927              :             },
    3928              :             .sin_zero = {},
    3929            1 :         };
    3930            1 :         a.set_ipv4(ip);
    3931              : 
    3932            3 :         var = s->get_variable("my_address_var");
    3933            1 :         CATCH_REQUIRE(var != nullptr);
    3934            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable_address::pointer_t va(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_address>(var));
    3935            1 :         CATCH_REQUIRE(va != nullptr);
    3936            1 :         CATCH_REQUIRE(va->get_type() == "address");
    3937            1 :         CATCH_REQUIRE(va->get_address() == a);
    3938              : 
    3939            3 :         var = s->get_variable("longer_address_var");
    3940            1 :         CATCH_REQUIRE(var != nullptr);
    3941            1 :         va = std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_address>(var);
    3942            1 :         CATCH_REQUIRE(va != nullptr);
    3943            1 :         CATCH_REQUIRE(va->get_type() == "address");
    3944            1 :         CATCH_REQUIRE(va->get_address() == a);
    3945              : 
    3946            1 :         snapdev::timespec_ex const expected_timestamp{ 1714241733, 419438123 };
    3947              : 
    3948            3 :         var = s->get_variable("my_timestamp_var");
    3949            1 :         CATCH_REQUIRE(var != nullptr);
    3950            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable_timestamp::pointer_t vts(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_timestamp>(var));
    3951            1 :         CATCH_REQUIRE(vts != nullptr);
    3952            1 :         CATCH_REQUIRE(vts->get_type() == "timestamp");
    3953            1 :         CATCH_REQUIRE(vts->get_timestamp() == expected_timestamp);
    3954              : 
    3955            3 :         var = s->get_variable("longer_timestamp_var");
    3956            1 :         CATCH_REQUIRE(var != nullptr);
    3957            1 :         vts = std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_timestamp>(var);
    3958            1 :         CATCH_REQUIRE(vts != nullptr);
    3959            1 :         CATCH_REQUIRE(vts->get_type() == "timestamp");
    3960            1 :         CATCH_REQUIRE(vts->get_timestamp() == expected_timestamp);
    3961              : 
    3962            1 :         CATCH_REQUIRE(s->get_exit_code() == -1);
    3963            1 :     }
    3964           10 :     CATCH_END_SECTION()
    3965              : 
    3966           10 :     CATCH_START_SECTION("reporter_executor_variables: primary variable reference with wrong name")
    3967              :     {
    3968            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));
    3969            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    3970            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    3971            1 :         p->parse_program();
    3972              : 
    3973            1 :         CATCH_REQUIRE(s->get_statement_size() == 2);
    3974              : 
    3975            3 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var(s->get_variable("my_var"));
    3976            1 :         CATCH_REQUIRE(var == nullptr);
    3977            3 :         var = s->get_variable("longer_var");
    3978            1 :         CATCH_REQUIRE(var == nullptr);
    3979              : 
    3980            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    3981            1 :         e->start();
    3982            1 :         CATCH_REQUIRE(e->run());
    3983              : 
    3984            3 :         var = s->get_variable("my_var");
    3985            1 :         CATCH_REQUIRE(var != nullptr);
    3986            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable_string::pointer_t v(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var));
    3987            1 :         CATCH_REQUIRE(v != nullptr);
    3988            1 :         CATCH_REQUIRE(v->get_string() == "foo");
    3989              : 
    3990            3 :         var = s->get_variable("longer_var");
    3991            1 :         CATCH_REQUIRE(var != nullptr);
    3992            1 :         v = std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_string>(var);
    3993            1 :         CATCH_REQUIRE(v != nullptr);
    3994            1 :         CATCH_REQUIRE(v->get_string() == ""); // wrong name so we get an empty string
    3995              : 
    3996            1 :         CATCH_REQUIRE(s->get_exit_code() == -1);
    3997            1 :     }
    3998           10 :     CATCH_END_SECTION()
    3999              : 
    4000           10 :     CATCH_START_SECTION("reporter_executor_variables: array variable cloning")
    4001              :     {
    4002              :         // Note: at the moment there is no call to the clone() function
    4003              :         //       inside the library, so make sure it works as expected
    4004              :         //       within the test
    4005              :         //
    4006            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::variable_array>("array_var"));
    4007            1 :         CATCH_REQUIRE(var != nullptr);
    4008              : 
    4009            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable_array::pointer_t v(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_array>(var));
    4010            1 :         CATCH_REQUIRE(v != nullptr);
    4011              : 
    4012            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t i1(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>("int_a"));
    4013            1 :         std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(i1)->set_integer(123);
    4014            1 :         v->add_item(i1);
    4015              : 
    4016            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t i2(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>("int_b"));
    4017            1 :         std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(i2)->set_integer(456);
    4018            1 :         v->add_item(i2);
    4019              : 
    4020            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t i3(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>("int_c"));
    4021            1 :         std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(i3)->set_integer(789);
    4022            1 :         v->add_item(i3);
    4023              : 
    4024            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t t1(v->get_item(0));
    4025            1 :         CATCH_REQUIRE(t1 != nullptr);
    4026            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable_integer::pointer_t p1(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(t1));
    4027            1 :         CATCH_REQUIRE(p1->get_integer() == 123);
    4028              : 
    4029            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t t2(v->get_item(1));
    4030            1 :         CATCH_REQUIRE(t2 != nullptr);
    4031            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable_integer::pointer_t p2(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(t2));
    4032            1 :         CATCH_REQUIRE(p2->get_integer() == 456);
    4033              : 
    4034            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t t3(v->get_item(2));
    4035            1 :         CATCH_REQUIRE(t3 != nullptr);
    4036            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable_integer::pointer_t p3(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(t3));
    4037            1 :         CATCH_REQUIRE(p3->get_integer() == 789);
    4038              : 
    4039            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t t4(v->get_item(3));
    4040            1 :         CATCH_REQUIRE(t4 == nullptr);
    4041              : 
    4042            3 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t clone(v->clone("clone"));
    4043            1 :         CATCH_REQUIRE(clone != nullptr);
    4044              : 
    4045            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable_array::pointer_t c(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_array>(clone));
    4046            1 :         CATCH_REQUIRE(c != nullptr);
    4047              : 
    4048            3 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t clone2(var->clone("clone2"));
    4049            1 :         CATCH_REQUIRE(clone2 != nullptr);
    4050              : 
    4051            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable_array::pointer_t c2(std::dynamic_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_array>(clone2));
    4052            1 :         CATCH_REQUIRE(c2 != nullptr);
    4053            1 :     }
    4054           10 :     CATCH_END_SECTION()
    4055           10 : }
    4056              : 
    4057              : 
    4058            1 : CATCH_TEST_CASE("reporter_executor_state", "[executor][reporter][error]")
    4059              : {
    4060            1 :     CATCH_START_SECTION("reporter_executor_state: add and read data from the state")
    4061              :     {
    4062           11 :         for(int count(0); count < 10; ++count)
    4063              :         {
    4064           10 :             SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4065              : 
    4066           10 :             CATCH_REQUIRE(s->get_server_pid() == getpid());
    4067           10 :             CATCH_REQUIRE(s->data_size() == 0);
    4068              : 
    4069           10 :             SNAP_CATCH2_NAMESPACE::reporter::connection_data_t buf;
    4070           10 :             CATCH_REQUIRE(s->read_data(buf, 1024) == -1);
    4071              : 
    4072              :             // clear has no effect here
    4073              :             //
    4074           10 :             s->clear_data();
    4075              : 
    4076           10 :             CATCH_REQUIRE(s->get_server_pid() == getpid());
    4077           10 :             CATCH_REQUIRE(s->data_size() == 0);
    4078              : 
    4079           10 :             CATCH_REQUIRE(s->read_data(buf, 1024) == -1);
    4080              : 
    4081           10 :             std::size_t total(0);
    4082           30 :             std::vector<std::size_t> sizes(10);
    4083          110 :             for(int i(0); i < 10; ++i)
    4084              :             {
    4085          100 :                 sizes[i] = rand() % (1024 * 4) + 1;
    4086          100 :                 total += sizes[i];
    4087              :             }
    4088              : 
    4089           30 :             SNAP_CATCH2_NAMESPACE::reporter::connection_data_t data(total);
    4090       231115 :             for(std::size_t i(0); i < total; ++i)
    4091              :             {
    4092       231105 :                 data[i] = rand();
    4093              :             }
    4094              : 
    4095           10 :             std::size_t offset(0);
    4096          110 :             for(int i(0); i < 10; ++i)
    4097              :             {
    4098          100 :                 SNAP_CATCH2_NAMESPACE::reporter::connection_data_pointer_t d(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::connection_data_t>(data.data() + offset, data.data() + offset + sizes[i]));
    4099          100 :                 s->add_data(d);
    4100          100 :                 offset += sizes[i];
    4101          100 :                 CATCH_REQUIRE(s->data_size() == static_cast<ssize_t>(offset));
    4102          100 :             }
    4103           10 :             CATCH_REQUIRE(s->data_size() == static_cast<ssize_t>(total));
    4104              : 
    4105           10 :             offset = 0;
    4106         3626 :             while(offset < total)
    4107              :             {
    4108         3616 :                 std::size_t const expected_size(std::min(64UL, total - offset));
    4109         3616 :                 CATCH_REQUIRE(s->read_data(buf, 64) == static_cast<int>(expected_size));
    4110         3616 :                 CATCH_REQUIRE(buf.size() == expected_size);
    4111       234721 :                 for(std::size_t i(0); i < expected_size; ++i)
    4112              :                 {
    4113       231105 :                     CATCH_REQUIRE(buf[i] == data[offset + i]);
    4114              :                 }
    4115         3616 :                 offset += expected_size;
    4116              :             }
    4117              : 
    4118              :             // here the clear has an effect
    4119              :             //
    4120           10 :             s->clear_data();
    4121           10 :             CATCH_REQUIRE(s->data_size() == 0);
    4122           10 :             CATCH_REQUIRE(s->read_data(buf, 1024) == -1);
    4123           10 :         }
    4124              :     }
    4125            1 :     CATCH_END_SECTION()
    4126            1 : }
    4127              : 
    4128            2 : CATCH_TEST_CASE("reporter_tcp_connection", "[executor][reporter][error]")
    4129              : {
    4130            2 :     CATCH_START_SECTION("reporter_tcp_connection: test raw TCP connection")
    4131              :     {
    4132            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("raw_tcp_connection.rprtr", g_program_raw_tcp_connection));
    4133            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4134              : 
    4135              :         // the tracer is really practical to debug, but the possible double wait()
    4136              :         // can make it break; so I keep it commented by default
    4137              :         //trace tracer(g_verify_raw_tcp_connection);
    4138              :         //s->set_trace_callback(std::bind(&trace::callback, &tracer, std::placeholders::_1, std::placeholders::_2));
    4139              : 
    4140            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4141            1 :         p->parse_program();
    4142              : 
    4143            1 :         CATCH_REQUIRE(s->get_statement_size() == 19);
    4144              : 
    4145            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4146            1 :         e->start();
    4147            1 :         addr::addr a;
    4148            1 :         sockaddr_in ip = {
    4149              :             .sin_family = AF_INET,
    4150            1 :             .sin_port = htons(20002),
    4151              :             .sin_addr = {
    4152            1 :                 .s_addr = htonl(0x7f000001),
    4153              :             },
    4154              :             .sin_zero = {},
    4155            1 :         };
    4156            1 :         a.set_ipv4(ip);
    4157            1 :         permanent_binary_responder::pointer_t binary_responder(std::make_shared<permanent_binary_responder>(
    4158              :                   a
    4159            1 :                 , ed::mode_t::MODE_PLAIN
    4160            2 :                 , permanent_binary_responder::sequence_t::SEQUENCE_PING_PONG));
    4161            1 :         ed::communicator::instance()->add_connection(binary_responder);
    4162              : 
    4163            1 :         e->set_thread_done_callback([binary_responder]()
    4164              :             {
    4165            1 :                 ed::communicator::instance()->remove_connection(binary_responder);
    4166            1 :             });
    4167              : 
    4168            1 :         CATCH_REQUIRE(e->run());
    4169              : 
    4170            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
    4171            1 :     }
    4172            2 :     CATCH_END_SECTION()
    4173              : 
    4174            2 :     CATCH_START_SECTION("reporter_tcp_connection: test prinbee like message")
    4175              :     {
    4176            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("prinbee_binary_message.rprtr", g_program_prinbee_binary_message));
    4177            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4178            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4179            1 :         p->parse_program();
    4180              : 
    4181            1 :         CATCH_REQUIRE(s->get_statement_size() == 19);
    4182              : 
    4183            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4184            1 :         e->start();
    4185            1 :         addr::addr a;
    4186            1 :         sockaddr_in ip = {
    4187              :             .sin_family = AF_INET,
    4188            1 :             .sin_port = htons(20002),
    4189              :             .sin_addr = {
    4190            1 :                 .s_addr = htonl(0x7f000001),
    4191              :             },
    4192              :             .sin_zero = {},
    4193            1 :         };
    4194            1 :         a.set_ipv4(ip);
    4195            1 :         permanent_binary_responder::pointer_t binary_responder(std::make_shared<permanent_binary_responder>(
    4196              :                   a
    4197            1 :                 , ed::mode_t::MODE_PLAIN
    4198            2 :                 , permanent_binary_responder::sequence_t::SEQUENCE_PRINBEE_MESSAGE));
    4199            1 :         ed::communicator::instance()->add_connection(binary_responder);
    4200              : 
    4201            1 :         e->set_thread_done_callback([binary_responder]()
    4202              :             {
    4203            1 :                 ed::communicator::instance()->remove_connection(binary_responder);
    4204            1 :             });
    4205              : 
    4206            1 :         CATCH_REQUIRE(e->run());
    4207              : 
    4208            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
    4209            1 :     }
    4210            2 :     CATCH_END_SECTION()
    4211            2 : }
    4212              : 
    4213              : 
    4214           47 : CATCH_TEST_CASE("reporter_executor_error", "[executor][reporter][error]")
    4215              : {
    4216           47 :     CATCH_START_SECTION("reporter_executor_error: if() before any condition")
    4217              :     {
    4218            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("if_too_soon.rprtr", g_program_no_condition));
    4219            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4220            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4221            1 :         p->parse_program();
    4222              : 
    4223            1 :         CATCH_REQUIRE(s->get_statement_size() == 2);
    4224              : 
    4225            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4226            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    4227              :               e->start()
    4228              :             , ed::runtime_error
    4229              :             , Catch::Matchers::ExceptionMessage(
    4230              :                       "event_dispatcher_exception: trying to use a 'compare' result when none are currently defined."));
    4231              : 
    4232            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    4233              :               s->set_compare(SNAP_CATCH2_NAMESPACE::reporter::compare_t::COMPARE_UNDEFINED)
    4234              :             , ed::runtime_error
    4235              :             , Catch::Matchers::ExceptionMessage(
    4236              :                       "event_dispatcher_exception: 'compare' cannot be set to \"undefined\"."));
    4237            1 :     }
    4238           47 :     CATCH_END_SECTION()
    4239              : 
    4240           47 :     CATCH_START_SECTION("reporter_executor_error: compare() with incompatible types")
    4241              :     {
    4242            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("compare_with_incompatible_types.rprtr", g_program_compare_with_incompatible_types));
    4243            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4244            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4245            1 :         p->parse_program();
    4246              : 
    4247            1 :         CATCH_REQUIRE(s->get_statement_size() == 4);
    4248              : 
    4249            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4250            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    4251              :               e->start()
    4252              :             , ed::runtime_error
    4253              :             , Catch::Matchers::ExceptionMessage(
    4254              :                       "event_dispatcher_exception: compare_with_incompatible_types.rprtr:3: unsupported compare (token types: 3 <=> 39)."));
    4255            1 :     }
    4256           47 :     CATCH_END_SECTION()
    4257              : 
    4258           47 :     CATCH_START_SECTION("reporter_executor_error: compare() with non-integer result")
    4259              :     {
    4260            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("compare_with_non_integer.rprtr", g_program_compare_with_non_integer));
    4261            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4262            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4263            1 :         p->parse_program();
    4264              : 
    4265            1 :         CATCH_REQUIRE(s->get_statement_size() == 2);
    4266              : 
    4267            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4268            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    4269              :               e->start()
    4270              :             , ed::runtime_error
    4271              :             , Catch::Matchers::ExceptionMessage(
    4272              :                       "event_dispatcher_exception: compare_with_non_integer.rprtr:1: parameter type mismatch for expression, expected \"integer\", got \"string\" instead."));
    4273            1 :     }
    4274           47 :     CATCH_END_SECTION()
    4275              : 
    4276           47 :     CATCH_START_SECTION("reporter_executor_error: compare() with bad positive integer result")
    4277              :     {
    4278            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("compare_with_bad_positive_integer.rprtr", g_program_compare_with_bad_positive_integer));
    4279            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4280            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4281            1 :         p->parse_program();
    4282              : 
    4283            1 :         CATCH_REQUIRE(s->get_statement_size() == 2);
    4284              : 
    4285            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4286            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    4287              :               e->start()
    4288              :             , ed::runtime_error
    4289              :             , Catch::Matchers::ExceptionMessage(
    4290              :                       "event_dispatcher_exception: compare_with_bad_positive_integer.rprtr:1: unsupported integer in compare(), values are limited to -2 to 1."));
    4291            1 :     }
    4292           47 :     CATCH_END_SECTION()
    4293              : 
    4294           47 :     CATCH_START_SECTION("reporter_executor_error: compare() with bad negative integer result")
    4295              :     {
    4296            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("compare_with_bad_negative_integer.rprtr", g_program_compare_with_bad_negative_integer));
    4297            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4298            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4299            1 :         p->parse_program();
    4300              : 
    4301            1 :         CATCH_REQUIRE(s->get_statement_size() == 2);
    4302              : 
    4303            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4304            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    4305              :               e->start()
    4306              :             , ed::runtime_error
    4307              :             , Catch::Matchers::ExceptionMessage(
    4308              :                       "event_dispatcher_exception: compare_with_bad_negative_integer.rprtr:1: unsupported integer in compare(), values are limited to -2 to 1."));
    4309            1 :     }
    4310           47 :     CATCH_END_SECTION()
    4311              : 
    4312           47 :     CATCH_START_SECTION("reporter_executor_error: kill() with invalid parameter type (timestamp)")
    4313              :     {
    4314            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("kill_unsupported_timestamp.rprtr", g_program_verify_kill_unsupported_timestamp));
    4315            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4316            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4317            1 :         p->parse_program();
    4318              : 
    4319            1 :         CATCH_REQUIRE(s->get_statement_size() == 2);
    4320              : 
    4321            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4322            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    4323              :               e->start()
    4324              :             , ed::runtime_error
    4325              :             , Catch::Matchers::ExceptionMessage(
    4326              :                       "event_dispatcher_exception: kill_unsupported_timestamp.rprtr:1: kill(signal: ...) unsupported parameter type."));
    4327            1 :     }
    4328           47 :     CATCH_END_SECTION()
    4329              : 
    4330           47 :     CATCH_START_SECTION("reporter_executor_error: kill() with too large an integer")
    4331              :     {
    4332            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("kill_integer_too_large.rprtr", g_program_verify_kill_integer_too_large));
    4333            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4334            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4335            1 :         p->parse_program();
    4336              : 
    4337            1 :         CATCH_REQUIRE(s->get_statement_size() == 2);
    4338              : 
    4339            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4340            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    4341              :               e->start()
    4342              :             , ed::runtime_error
    4343              :             , Catch::Matchers::ExceptionMessage(
    4344              :                       "event_dispatcher_exception: kill_integer_too_large.rprtr:1: kill(signal: ...) unknown signal."));
    4345            1 :     }
    4346           47 :     CATCH_END_SECTION()
    4347              : 
    4348           47 :     CATCH_START_SECTION("reporter_executor_error: kill() with an unknown signal name")
    4349              :     {
    4350            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("kill_unknown_signal_name.rprtr", g_program_verify_kill_unknown_signal_name));
    4351            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4352            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4353            1 :         p->parse_program();
    4354              : 
    4355            1 :         CATCH_REQUIRE(s->get_statement_size() == 2);
    4356              : 
    4357            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4358            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    4359              :               e->start()
    4360              :             , ed::runtime_error
    4361              :             , Catch::Matchers::ExceptionMessage(
    4362              :                       "event_dispatcher_exception: kill_unknown_signal_name.rprtr:1: kill(signal: ...) unknown signal."));
    4363            1 :     }
    4364           47 :     CATCH_END_SECTION()
    4365              : 
    4366           47 :     CATCH_START_SECTION("reporter_executor_error: exit() + error message")
    4367              :     {
    4368            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("exit_error_message.rprtr", g_program_error_message));
    4369            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4370            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4371            1 :         p->parse_program();
    4372              : 
    4373            1 :         CATCH_REQUIRE(s->get_statement_size() == 1);
    4374              : 
    4375            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4376            1 :         e->start();
    4377              : 
    4378            1 :         CATCH_REQUIRE(s->get_exit_code() == 1);
    4379            1 :     }
    4380           47 :     CATCH_END_SECTION()
    4381              : 
    4382           47 :     CATCH_START_SECTION("reporter_executor_error: listen() + listen()")
    4383              :     {
    4384            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("two_listen.rprtr", g_program_two_listen));
    4385            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4386            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4387            1 :         p->parse_program();
    4388              : 
    4389            1 :         CATCH_REQUIRE(s->get_statement_size() == 2);
    4390              : 
    4391            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4392            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    4393              :               e->start()
    4394              :             , ed::runtime_error
    4395              :             , Catch::Matchers::ExceptionMessage(
    4396              :                       "event_dispatcher_exception: the listen() instruction cannot be reused without an intermediate disconnect() instruction."));
    4397            1 :     }
    4398           47 :     CATCH_END_SECTION()
    4399              : 
    4400           47 :     CATCH_START_SECTION("reporter_executor_error: label(name: ...) does not accept integers")
    4401              :     {
    4402            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("label_bad_type.rprtr", g_program_label_bad_type));
    4403            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4404            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4405              : 
    4406              :         // label is a special case which we test in the state.cpp way before
    4407              :         // we reach the executor... (so this is not really an executor test)
    4408              :         //
    4409            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    4410              :               p->parse_program()
    4411              :             , ed::runtime_error
    4412              :             , Catch::Matchers::ExceptionMessage(
    4413              :                       "event_dispatcher_exception: the value of the \"name\" parameter of the \"label\" statement must be an identifier."));
    4414            1 :     }
    4415           47 :     CATCH_END_SECTION()
    4416              : 
    4417           47 :     CATCH_START_SECTION("reporter_executor_error: exit(error_message: ...) does not accept floating points")
    4418              :     {
    4419            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));
    4420            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4421            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4422            1 :         p->parse_program();
    4423              : 
    4424            1 :         CATCH_REQUIRE(s->get_statement_size() == 1);
    4425              : 
    4426            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4427            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    4428              :               e->start()
    4429              :             , ed::runtime_error
    4430              :             , Catch::Matchers::ExceptionMessage(
    4431              :                       "event_dispatcher_exception: exit_bad_type.rprtr:1: parameter type mismatch for error_message, expected \"string\", got \"floating_point\" instead."));
    4432            1 :     }
    4433           47 :     CATCH_END_SECTION()
    4434              : 
    4435           47 :     CATCH_START_SECTION("reporter_executor_error: verify starting the thread twice")
    4436              :     {
    4437            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));
    4438            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4439            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4440            1 :         p->parse_program();
    4441              : 
    4442            1 :         CATCH_REQUIRE(s->get_statement_size() == 4);
    4443              : 
    4444              :         // before we run the script, there are no such variables
    4445              :         //
    4446            3 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var(s->get_variable("test"));
    4447            1 :         CATCH_REQUIRE(var == nullptr);
    4448            3 :         var = s->get_variable("runner");
    4449            1 :         CATCH_REQUIRE(var == nullptr);
    4450              : 
    4451            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4452            1 :         e->start();
    4453            1 :         CATCH_REQUIRE(e->run());
    4454            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    4455              :               e->stop()
    4456              :             , ed::runtime_error
    4457              :             , Catch::Matchers::ExceptionMessage(
    4458              :                       "event_dispatcher_exception: run() instruction found when already running in the background."));
    4459              : 
    4460            3 :         var = s->get_variable("test");
    4461            1 :         CATCH_REQUIRE(var != nullptr);
    4462            1 :         CATCH_REQUIRE(var->get_name() == "test");
    4463            1 :         CATCH_REQUIRE(var->get_type() == "integer");
    4464            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == 33);
    4465              : 
    4466            3 :         var = s->get_variable("runner");
    4467            1 :         CATCH_REQUIRE(var != nullptr);
    4468            1 :         CATCH_REQUIRE(var->get_name() == "runner");
    4469            1 :         CATCH_REQUIRE(var->get_type() == "floating_point");
    4470            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_floating_point>(var)->get_floating_point() == 6.07);
    4471            1 :     }
    4472           47 :     CATCH_END_SECTION()
    4473              : 
    4474           47 :     CATCH_START_SECTION("reporter_executor_error: <type> + <type> that are not valid")
    4475              :     {
    4476              :         struct bad_additions_t
    4477              :         {
    4478              :             char const *    f_code = nullptr;
    4479              :             SNAP_CATCH2_NAMESPACE::reporter::token_t  f_left_hand_side = SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ERROR;
    4480              :             SNAP_CATCH2_NAMESPACE::reporter::token_t  f_right_hand_side = SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ERROR;
    4481              :         };
    4482            1 :         constexpr bad_additions_t const bad_additions[] =
    4483              :         {
    4484              :             {
    4485              :                 g_program_unsupported_addition_address_address,
    4486              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ADDRESS,
    4487              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ADDRESS,
    4488              :             },
    4489              :             {
    4490              :                 g_program_unsupported_addition_address_string,
    4491              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ADDRESS,
    4492              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_SINGLE_STRING,
    4493              :             },
    4494              :             {
    4495              :                 g_program_unsupported_addition_string_address,
    4496              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_SINGLE_STRING,
    4497              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ADDRESS,
    4498              :             },
    4499              :             {
    4500              :                 g_program_unsupported_addition_address_identifier,
    4501              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ADDRESS,
    4502              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_IDENTIFIER,
    4503              :             },
    4504              :             {
    4505              :                 g_program_unsupported_addition_identifier_address,
    4506              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_IDENTIFIER,
    4507              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ADDRESS,
    4508              :             },
    4509              :             {
    4510              :                 g_program_unsupported_addition_identifier_string,
    4511              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_IDENTIFIER,
    4512              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_SINGLE_STRING,
    4513              :             },
    4514              :             {
    4515              :                 g_program_unsupported_addition_string_identifier,
    4516              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_SINGLE_STRING,
    4517              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_IDENTIFIER,
    4518              :             },
    4519              :         };
    4520              : 
    4521            8 :         for(auto const & ba : bad_additions)
    4522              :         {
    4523            7 :             SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("invalid_additions.rprtr", ba.f_code));
    4524            7 :             SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4525            7 :             SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4526            7 :             p->parse_program();
    4527              : 
    4528            7 :             CATCH_REQUIRE(s->get_statement_size() == 1);
    4529              : 
    4530            7 :             SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4531            7 :             CATCH_REQUIRE_THROWS_MATCHES(
    4532              :                   e->start()
    4533              :                 , ed::runtime_error
    4534              :                 , Catch::Matchers::ExceptionMessage(
    4535              :                           "event_dispatcher_exception: unsupported addition (token types: "
    4536              :                         + std::to_string(static_cast<int>(ba.f_left_hand_side))
    4537              :                         + " + "
    4538              :                         + std::to_string(static_cast<int>(ba.f_right_hand_side))
    4539              :                         + ")."));
    4540            7 :         }
    4541              :     }
    4542           47 :     CATCH_END_SECTION()
    4543              : 
    4544           47 :     CATCH_START_SECTION("reporter_executor_error: <type> - <type> that are not valid")
    4545              :     {
    4546            1 :         constexpr char const * const bad_subtractions[] =
    4547              :         {
    4548              :             g_program_unsupported_subtraction_address_string,
    4549              :             g_program_unsupported_subtraction_string_address,
    4550              :             g_program_unsupported_subtraction_address_identifier,
    4551              :             g_program_unsupported_subtraction_identifier_address,
    4552              :             g_program_unsupported_subtraction_identifier_string,
    4553              :             g_program_unsupported_subtraction_string_identifier,
    4554              :         };
    4555              : 
    4556            7 :         for(auto const & program : bad_subtractions)
    4557              :         {
    4558              : //std::cerr << "testing [" << program << "]\n";
    4559            6 :             SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("invalid_subtractions.rprtr", program));
    4560            6 :             SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4561            6 :             SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4562            6 :             p->parse_program();
    4563              : 
    4564            6 :             CATCH_REQUIRE(s->get_statement_size() == 1);
    4565              : 
    4566            6 :             SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4567           18 :             CATCH_REQUIRE_THROWS_MATCHES(
    4568              :                   e->start()
    4569              :                 , ed::runtime_error
    4570              :                 , Catch::Matchers::ExceptionMessage(
    4571              :                           "event_dispatcher_exception: unsupported subtraction."));
    4572            6 :         }
    4573              :     }
    4574           47 :     CATCH_END_SECTION()
    4575              : 
    4576           47 :     CATCH_START_SECTION("reporter_executor_error: <type> * <type> that are not valid")
    4577              :     {
    4578            1 :         constexpr char const * const bad_multiplications[] =
    4579              :         {
    4580              :             g_program_unsupported_multiplication_address_address,
    4581              :             g_program_unsupported_multiplication_address_string,
    4582              :             g_program_unsupported_multiplication_string_address,
    4583              :             g_program_unsupported_multiplication_address_identifier,
    4584              :             g_program_unsupported_multiplication_identifier_address,
    4585              :             g_program_unsupported_multiplication_identifier_string,
    4586              :             g_program_unsupported_multiplication_string_identifier,
    4587              :             g_program_unsupported_multiplication_string_string,
    4588              :             g_program_unsupported_multiplication_identifier_identifier,
    4589              :         };
    4590              : 
    4591           10 :         for(auto const & program : bad_multiplications)
    4592              :         {
    4593              : //std::cerr << "testing [" << program << "]\n";
    4594            9 :             SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("invalid_multiplications.rprtr", program));
    4595            9 :             SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4596            9 :             SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4597            9 :             p->parse_program();
    4598              : 
    4599            9 :             CATCH_REQUIRE(s->get_statement_size() == 1);
    4600              : 
    4601            9 :             SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4602           27 :             CATCH_REQUIRE_THROWS_MATCHES(
    4603              :                   e->start()
    4604              :                 , ed::runtime_error
    4605              :                 , Catch::Matchers::ExceptionMessage(
    4606              :                           "event_dispatcher_exception: unsupported multiplication."));
    4607            9 :         }
    4608              :     }
    4609           47 :     CATCH_END_SECTION()
    4610              : 
    4611           47 :     CATCH_START_SECTION("reporter_executor_error: <type> / <type> that are not valid")
    4612              :     {
    4613            1 :         constexpr char const * const bad_divisions[] =
    4614              :         {
    4615              :             g_program_unsupported_division_address_address,
    4616              :             g_program_unsupported_division_address_string,
    4617              :             g_program_unsupported_division_string_address,
    4618              :             g_program_unsupported_division_address_identifier,
    4619              :             g_program_unsupported_division_identifier_address,
    4620              :             g_program_unsupported_division_identifier_string,
    4621              :             g_program_unsupported_division_string_identifier,
    4622              :             g_program_unsupported_division_string_string,
    4623              :             g_program_unsupported_division_identifier_identifier,
    4624              :         };
    4625              : 
    4626           10 :         for(auto const & program : bad_divisions)
    4627              :         {
    4628              : //std::cerr << "testing [" << program << "]\n";
    4629            9 :             SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("invalid_divisions.rprtr", program));
    4630            9 :             SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4631            9 :             SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4632            9 :             p->parse_program();
    4633              : 
    4634            9 :             CATCH_REQUIRE(s->get_statement_size() == 1);
    4635              : 
    4636            9 :             SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4637           27 :             CATCH_REQUIRE_THROWS_MATCHES(
    4638              :                   e->start()
    4639              :                 , ed::runtime_error
    4640              :                 , Catch::Matchers::ExceptionMessage(
    4641              :                           "event_dispatcher_exception: unsupported division."));
    4642            9 :         }
    4643              :     }
    4644           47 :     CATCH_END_SECTION()
    4645              : 
    4646           47 :     CATCH_START_SECTION("reporter_executor_error: <type> % <type> that are not valid")
    4647              :     {
    4648              :         struct bad_modulo_t
    4649              :         {
    4650              :             char const * const                          f_expr = nullptr;
    4651              :             SNAP_CATCH2_NAMESPACE::reporter::token_t    f_lhs_token = SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ERROR;
    4652              :             SNAP_CATCH2_NAMESPACE::reporter::token_t    f_rhs_token = SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ERROR;
    4653              :         };
    4654            1 :         constexpr bad_modulo_t const bad_modulos[] =
    4655              :         {
    4656              :             {
    4657              :                 g_program_unsupported_modulo_address_address,
    4658              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ADDRESS,
    4659              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ADDRESS,
    4660              :             },
    4661              :             {
    4662              :                 g_program_unsupported_modulo_address_string,
    4663              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ADDRESS,
    4664              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_SINGLE_STRING,
    4665              :             },
    4666              :             {
    4667              :                 g_program_unsupported_modulo_string_address,
    4668              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_SINGLE_STRING,
    4669              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ADDRESS,
    4670              :             },
    4671              :             {
    4672              :                 g_program_unsupported_modulo_address_identifier,
    4673              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ADDRESS,
    4674              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_IDENTIFIER,
    4675              :             },
    4676              :             {
    4677              :                 g_program_unsupported_modulo_identifier_address,
    4678              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_IDENTIFIER,
    4679              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_ADDRESS,
    4680              :             },
    4681              :             {
    4682              :                 g_program_unsupported_modulo_identifier_string,
    4683              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_IDENTIFIER,
    4684              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_SINGLE_STRING, // the type of string was already converted by this time
    4685              :             },
    4686              :             {
    4687              :                 g_program_unsupported_modulo_string_identifier,
    4688              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_SINGLE_STRING,
    4689              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_IDENTIFIER,
    4690              :             },
    4691              :             {
    4692              :                 g_program_unsupported_modulo_string_string,
    4693              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_SINGLE_STRING,
    4694              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_SINGLE_STRING, // the type of string was already converted by this time
    4695              :             },
    4696              :             {
    4697              :                 g_program_unsupported_modulo_identifier_identifier,
    4698              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_IDENTIFIER,
    4699              :                 SNAP_CATCH2_NAMESPACE::reporter::token_t::TOKEN_IDENTIFIER,
    4700              :             },
    4701              :         };
    4702              : 
    4703           10 :         for(auto const & program : bad_modulos)
    4704              :         {
    4705              : //std::cerr << "testing [" << program.f_expr << "]\n";
    4706            9 :             SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("invalid_modulos.rprtr", program.f_expr));
    4707            9 :             SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4708            9 :             SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4709            9 :             p->parse_program();
    4710              : 
    4711            9 :             CATCH_REQUIRE(s->get_statement_size() == 1);
    4712              : 
    4713            9 :             SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4714            9 :             CATCH_REQUIRE_THROWS_MATCHES(
    4715              :                   e->start()
    4716              :                 , ed::runtime_error
    4717              :                 , Catch::Matchers::ExceptionMessage(
    4718              :                           "event_dispatcher_exception: unsupported modulo (types: "
    4719              :                         + std::to_string(static_cast<int>(program.f_lhs_token))
    4720              :                         + " and "
    4721              :                         + std::to_string(static_cast<int>(program.f_rhs_token))
    4722              :                         + ")."));
    4723            9 :         }
    4724              :     }
    4725           47 :     CATCH_END_SECTION()
    4726              : 
    4727           47 :     CATCH_START_SECTION("reporter_executor_error: -<types> that are not valid")
    4728              :     {
    4729            1 :         constexpr char const * const bad_negations[] =
    4730              :         {
    4731              :             g_program_unsupported_negation_single_string,
    4732              :             g_program_unsupported_negation_double_string,
    4733              :             g_program_unsupported_negation_address,
    4734              :         };
    4735              : 
    4736            4 :         for(auto const & program : bad_negations)
    4737              :         {
    4738            3 :             SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("invalid_negate.rprtr", program));
    4739            3 :             SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4740            3 :             SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4741            3 :             p->parse_program();
    4742              : 
    4743            3 :             CATCH_REQUIRE(s->get_statement_size() == 1);
    4744              : 
    4745            3 :             SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4746            9 :             CATCH_REQUIRE_THROWS_MATCHES(
    4747              :                   e->start()
    4748              :                 , ed::runtime_error
    4749              :                 , Catch::Matchers::ExceptionMessage(
    4750              :                           "event_dispatcher_exception: unsupported negation."));
    4751            3 :         }
    4752              :     }
    4753           47 :     CATCH_END_SECTION()
    4754              : 
    4755           47 :     CATCH_START_SECTION("reporter_executor_error: variable reference without a '}'")
    4756              :     {
    4757            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));
    4758            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4759            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4760            1 :         p->parse_program();
    4761              : 
    4762            1 :         CATCH_REQUIRE(s->get_statement_size() == 2);
    4763              : 
    4764            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4765            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    4766              :               e->start()
    4767              :             , ed::runtime_error
    4768              :             , Catch::Matchers::ExceptionMessage(
    4769              :                       "event_dispatcher_exception: invalid_negate.rprtr:2: found unclosed variable in \"ref. ${my_var\"."));
    4770            1 :     }
    4771           47 :     CATCH_END_SECTION()
    4772              : 
    4773           47 :     CATCH_START_SECTION("reporter_executor_error: regex variable in double string")
    4774              :     {
    4775            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));
    4776            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4777            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4778            1 :         p->parse_program();
    4779              : 
    4780            1 :         CATCH_REQUIRE(s->get_statement_size() == 2);
    4781              : 
    4782            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4783            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    4784              :               e->start()
    4785              :             , ed::runtime_error
    4786              :             , Catch::Matchers::ExceptionMessage(
    4787              :                       "event_dispatcher_exception: found variable of type \"regex\" which is not yet supported in ${...}."));
    4788            1 :     }
    4789           47 :     CATCH_END_SECTION()
    4790              : 
    4791           47 :     CATCH_START_SECTION("reporter_executor_error: variable reference without a name")
    4792              :     {
    4793            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));
    4794            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4795            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4796            1 :         p->parse_program();
    4797              : 
    4798            1 :         CATCH_REQUIRE(s->get_statement_size() == 1);
    4799              : 
    4800            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4801            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    4802              :               e->start()
    4803              :             , ed::runtime_error
    4804              :             , Catch::Matchers::ExceptionMessage(
    4805              :                       "event_dispatcher_exception: invalid_negate.rprtr:1: found variable without a name in \"ref. ${} is empty\"."));
    4806            1 :     }
    4807           47 :     CATCH_END_SECTION()
    4808              : 
    4809           47 :     CATCH_START_SECTION("reporter_executor_error: <string> * <negative> is not valid")
    4810              :     {
    4811            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));
    4812            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4813            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4814            1 :         p->parse_program();
    4815              : 
    4816            1 :         CATCH_REQUIRE(s->get_statement_size() == 1);
    4817              : 
    4818            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4819            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    4820              :               e->start()
    4821              :             , ed::runtime_error
    4822              :             , Catch::Matchers::ExceptionMessage(
    4823              :                       "event_dispatcher_exception: string repeat needs to be positive and under 1001."));
    4824            1 :     }
    4825           47 :     CATCH_END_SECTION()
    4826              : 
    4827           47 :     CATCH_START_SECTION("reporter_executor_error: <string> * <large repeat> is not valid")
    4828              :     {
    4829            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));
    4830            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4831            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4832            1 :         p->parse_program();
    4833              : 
    4834            1 :         CATCH_REQUIRE(s->get_statement_size() == 1);
    4835              : 
    4836            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4837            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    4838              :               e->start()
    4839              :             , ed::runtime_error
    4840              :             , Catch::Matchers::ExceptionMessage(
    4841              :                       "event_dispatcher_exception: string repeat needs to be positive and under 1001."));
    4842            1 :     }
    4843           47 :     CATCH_END_SECTION()
    4844              : 
    4845           47 :     CATCH_START_SECTION("reporter_executor_error: exit() with timeout & error_message is invalid")
    4846              :     {
    4847            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("bad_exit.rprtr", g_program_bad_exit));
    4848            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4849            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4850            1 :         p->parse_program();
    4851              : 
    4852            1 :         CATCH_REQUIRE(s->get_statement_size() == 1);
    4853              : 
    4854            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4855            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    4856              :               e->start()
    4857              :             , ed::runtime_error
    4858              :             , Catch::Matchers::ExceptionMessage(
    4859              :                       "event_dispatcher_exception: bad_exit.rprtr:1: \"timeout\" and \"error_message\" from the exit() instruction are mutually exclusive."));
    4860            1 :     }
    4861           47 :     CATCH_END_SECTION()
    4862              : 
    4863           47 :     CATCH_START_SECTION("reporter_executor_error: exit() with timeout which is not a number")
    4864              :     {
    4865            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));
    4866            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4867            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4868            1 :         p->parse_program();
    4869              : 
    4870            1 :         CATCH_REQUIRE(s->get_statement_size() == 1);
    4871              : 
    4872            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4873            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    4874              :               e->start()
    4875              :             , ed::runtime_error
    4876              :             , Catch::Matchers::ExceptionMessage(
    4877              :                       "event_dispatcher_exception: bad_exit.rprtr:1: parameter type mismatch for timeout, expected \"number\", got \"string\" instead."));
    4878            1 :     }
    4879           47 :     CATCH_END_SECTION()
    4880              : 
    4881           47 :     CATCH_START_SECTION("reporter_executor_error: exit() with timeout which is not a number")
    4882              :     {
    4883            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));
    4884            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4885            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4886            1 :         p->parse_program();
    4887              : 
    4888            1 :         CATCH_REQUIRE(s->get_statement_size() == 1);
    4889              : 
    4890            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4891            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    4892              :               e->start()
    4893              :             , ed::runtime_error
    4894              :             , Catch::Matchers::ExceptionMessage(
    4895              :                       "event_dispatcher_exception: bad_print.rprtr:1: parameter type mismatch for message, expected \"string\", got \"identifier\" instead."));
    4896            1 :     }
    4897           47 :     CATCH_END_SECTION()
    4898              : 
    4899           47 :     CATCH_START_SECTION("reporter_executor_error: send_message() when not connected")
    4900              :     {
    4901            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));
    4902            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4903            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4904            1 :         p->parse_program();
    4905              : 
    4906            1 :         CATCH_REQUIRE(s->get_statement_size() == 1);
    4907              : 
    4908            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4909            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    4910              :               e->start()
    4911              :             , ed::runtime_error
    4912              :             , Catch::Matchers::ExceptionMessage(
    4913              :                       "event_dispatcher_exception: send_message() has no connection to send a message to."));
    4914            1 :     }
    4915           47 :     CATCH_END_SECTION()
    4916              : 
    4917           47 :     CATCH_START_SECTION("reporter_executor_error: send_data() when not connected")
    4918              :     {
    4919            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("bad_send_data.rprtr", g_program_send_data_without_connection));
    4920            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4921            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4922            1 :         p->parse_program();
    4923              : 
    4924            1 :         CATCH_REQUIRE(s->get_statement_size() == 1);
    4925              : 
    4926            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4927            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    4928              :               e->start()
    4929              :             , ed::runtime_error
    4930              :             , Catch::Matchers::ExceptionMessage(
    4931              :                       "event_dispatcher_exception: send_data() has no connection to send data."));
    4932            1 :     }
    4933           47 :     CATCH_END_SECTION()
    4934              : 
    4935           47 :     CATCH_START_SECTION("reporter_executor_error: if(variable) with invalid type")
    4936              :     {
    4937            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));
    4938            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4939            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4940            1 :         p->parse_program();
    4941              : 
    4942            1 :         CATCH_REQUIRE(s->get_statement_size() == 5);
    4943              : 
    4944            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4945            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    4946              :               e->start()
    4947              :             , ed::runtime_error
    4948              :             , Catch::Matchers::ExceptionMessage(
    4949              :                       "event_dispatcher_exception: if(variable: ...) only supports variables of type integer or floating point."));
    4950            1 :     }
    4951           47 :     CATCH_END_SECTION()
    4952              : 
    4953           47 :     CATCH_START_SECTION("reporter_executor_error: wait() before starting thread")
    4954              :     {
    4955            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));
    4956            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4957            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4958            1 :         p->parse_program();
    4959              : 
    4960            1 :         CATCH_REQUIRE(s->get_statement_size() == 1);
    4961              : 
    4962            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4963            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    4964              :               e->start()
    4965              :             , ed::runtime_error
    4966              :             , Catch::Matchers::ExceptionMessage(
    4967              :                       "event_dispatcher_exception: wait() used before run()."));
    4968            1 :     }
    4969           47 :     CATCH_END_SECTION()
    4970              : 
    4971           47 :     CATCH_START_SECTION("reporter_executor_error: wait() with invalid mode")
    4972              :     {
    4973            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));
    4974            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    4975            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    4976            1 :         p->parse_program();
    4977              : 
    4978            1 :         CATCH_REQUIRE(s->get_statement_size() == 2);
    4979              : 
    4980            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    4981            1 :         e->start();
    4982            1 :         addr::addr a;
    4983            1 :         sockaddr_in ip = {
    4984              :             .sin_family = AF_INET,
    4985            1 :             .sin_port = htons(20002),
    4986              :             .sin_addr = {
    4987            1 :                 .s_addr = htonl(0x7f000001),
    4988              :             },
    4989              :             .sin_zero = {},
    4990            1 :         };
    4991            1 :         a.set_ipv4(ip);
    4992            1 :         messenger_responder::pointer_t messenger(std::make_shared<messenger_responder>(
    4993              :                   a
    4994            1 :                 , ed::mode_t::MODE_PLAIN
    4995            2 :                 , messenger_responder::sequence_t::SEQUENCE_ONE_MESSAGE));
    4996            1 :         ed::communicator::instance()->add_connection(messenger);
    4997            1 :         messenger_timer::pointer_t timer(std::make_shared<messenger_timer>(messenger));
    4998            1 :         ed::communicator::instance()->add_connection(timer);
    4999            1 :         messenger->set_timer(timer);
    5000            1 :         e->set_thread_done_callback([messenger, timer]()
    5001              :             {
    5002            1 :                 ed::communicator::instance()->remove_connection(messenger);
    5003            1 :                 ed::communicator::instance()->remove_connection(timer);
    5004            1 :             });
    5005              : 
    5006            1 :         CATCH_REQUIRE(e->run());
    5007              : 
    5008              :         // the thread exception happens when e->stop() is called
    5009              :         //
    5010            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    5011              :               e->stop()
    5012              :             , ed::runtime_error
    5013              :             , Catch::Matchers::ExceptionMessage("event_dispatcher_exception: program_wait_invalid_mode.rprtr:2: unknown mode \"not_this_one\" in wait()."));
    5014              : 
    5015            1 :         CATCH_REQUIRE(s->get_exit_code() == -1);
    5016            1 :     }
    5017           47 :     CATCH_END_SECTION()
    5018              : 
    5019           47 :     CATCH_START_SECTION("reporter_executor_error: wait() + drain without connections")
    5020              :     {
    5021            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));
    5022            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    5023            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    5024            1 :         p->parse_program();
    5025              : 
    5026            1 :         CATCH_REQUIRE(s->get_statement_size() == 2);
    5027              : 
    5028            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    5029            1 :         e->start();
    5030            1 :         CATCH_REQUIRE(e->run());
    5031              : 
    5032              :         // the thread exception happens when e->stop() is called
    5033              :         //
    5034            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    5035              :               e->stop()
    5036              :             , ed::runtime_error
    5037              :             , Catch::Matchers::ExceptionMessage("event_dispatcher_exception: no connections to wait() on."));
    5038              : 
    5039            1 :         CATCH_REQUIRE(s->get_exit_code() == -1);
    5040            1 :     }
    5041           47 :     CATCH_END_SECTION()
    5042              : 
    5043           47 :     CATCH_START_SECTION("reporter_executor_error: try reading missing file")
    5044              :     {
    5045            1 :         std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
    5046            1 :         std::string const filename(source_dir + "/tests/rprtr/not_this_one");
    5047            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
    5048            1 :         CATCH_REQUIRE(l == nullptr);
    5049            1 :     }
    5050           47 :     CATCH_END_SECTION()
    5051              : 
    5052           47 :     CATCH_START_SECTION("reporter_executor_error: verify that the executor::run() function does a try/catch as expected")
    5053              :     {
    5054              :         // in this case, load the program from a file
    5055              :         // to verify that this works as expected
    5056              :         //
    5057            1 :         std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
    5058            1 :         std::string const filename(source_dir + "/tests/rprtr/send_and_receive_complete_messages");
    5059            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
    5060            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    5061            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    5062            1 :         p->parse_program();
    5063              : 
    5064            1 :         CATCH_REQUIRE(s->get_statement_size() == 34);
    5065              : 
    5066            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    5067            1 :         e->start();
    5068            1 :         addr::addr a;
    5069            1 :         sockaddr_in ip = {
    5070              :             .sin_family = AF_INET,
    5071            1 :             .sin_port = htons(20002),
    5072              :             .sin_addr = {
    5073            1 :                 .s_addr = htonl(0x7f000001),
    5074              :             },
    5075              :             .sin_zero = {},
    5076            1 :         };
    5077            1 :         a.set_ipv4(ip);
    5078            1 :         messenger_responder::pointer_t messenger(std::make_shared<messenger_responder>(
    5079              :                   a
    5080            1 :                 , ed::mode_t::MODE_PLAIN
    5081            1 :                 , messenger_responder::sequence_t::SEQUENCE_READY_THROW
    5082            1 :                 , ed::DEFAULT_PAUSE_BEFORE_RECONNECTING));
    5083            1 :         ed::communicator::instance()->add_connection(messenger);
    5084            1 :         messenger_timer::pointer_t timer(std::make_shared<messenger_timer>(messenger));
    5085            1 :         ed::communicator::instance()->add_connection(timer);
    5086            1 :         messenger->set_timer(timer);
    5087              : 
    5088              :         // the exception capture in run() is not returned; it should be
    5089              :         // printed in the console, making it possible to see what happened
    5090              :         //
    5091            1 :         CATCH_REQUIRE_FALSE(e->run());
    5092              : 
    5093            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    5094              :               e->stop()
    5095              :             , ed::runtime_error
    5096              :             , Catch::Matchers::ExceptionMessage("event_dispatcher_exception: ppoll() timed out."));
    5097              : 
    5098              :         // if we exited because of our timer, then the test did not pass
    5099              :         //
    5100            1 :         CATCH_REQUIRE_FALSE(timer->timed_out_prima());
    5101              : 
    5102            1 :         CATCH_REQUIRE(s->get_exit_code() == -1);
    5103              : 
    5104              :         // in this case, the variable does not get unset because the
    5105              :         // crash happens before we have the chance to do that
    5106              :         //
    5107            3 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var(s->get_variable("got_register"));
    5108            1 :         CATCH_REQUIRE(var != nullptr);
    5109            1 :         CATCH_REQUIRE(var->get_type() == "integer");
    5110            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == 1);
    5111            1 :     }
    5112           47 :     CATCH_END_SECTION()
    5113              : 
    5114           47 :     CATCH_START_SECTION("reporter_executor_error: verify that the executor::run() function does a try/catch of non-standard exceptions")
    5115              :     {
    5116              :         // in this case, load the program from a file
    5117              :         // to verify that this works as expected
    5118              :         //
    5119            1 :         std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
    5120            1 :         std::string const filename(source_dir + "/tests/rprtr/send_and_receive_complete_messages");
    5121            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
    5122            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    5123            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    5124            1 :         p->parse_program();
    5125              : 
    5126            1 :         CATCH_REQUIRE(s->get_statement_size() == 34);
    5127              : 
    5128            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    5129            1 :         e->start();
    5130            1 :         addr::addr a;
    5131            1 :         sockaddr_in ip = {
    5132              :             .sin_family = AF_INET,
    5133            1 :             .sin_port = htons(20002),
    5134              :             .sin_addr = {
    5135            1 :                 .s_addr = htonl(0x7f000001),
    5136              :             },
    5137              :             .sin_zero = {},
    5138            1 :         };
    5139            1 :         a.set_ipv4(ip);
    5140            1 :         messenger_responder::pointer_t messenger(std::make_shared<messenger_responder>(
    5141              :                   a
    5142            1 :                 , ed::mode_t::MODE_PLAIN
    5143            2 :                 , messenger_responder::sequence_t::SEQUENCE_READY_THROW_WHAT));
    5144            1 :         ed::communicator::instance()->add_connection(messenger);
    5145            1 :         messenger_timer::pointer_t timer(std::make_shared<messenger_timer>(messenger));
    5146            1 :         ed::communicator::instance()->add_connection(timer);
    5147            1 :         messenger->set_timer(timer);
    5148              : 
    5149              :         // the exception capture in run() is not returned; it should be
    5150              :         // printed in the console, making it possible to see what happened
    5151              :         //
    5152            1 :         CATCH_REQUIRE_FALSE(e->run());
    5153              : 
    5154            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    5155              :               e->stop()
    5156              :             , ed::runtime_error
    5157              :             , Catch::Matchers::ExceptionMessage("event_dispatcher_exception: ppoll() timed out."));
    5158              : 
    5159              :         // if we exited because of our timer, then the test did not pass
    5160              :         //
    5161            1 :         CATCH_REQUIRE_FALSE(timer->timed_out_prima());
    5162              : 
    5163            1 :         CATCH_REQUIRE(s->get_exit_code() == -1);
    5164              : 
    5165              :         // in this case, the variable does not get unset because the
    5166              :         // crash happens before we have the chance to do that
    5167              :         //
    5168            3 :         SNAP_CATCH2_NAMESPACE::reporter::variable::pointer_t var(s->get_variable("got_register"));
    5169            1 :         CATCH_REQUIRE(var != nullptr);
    5170            1 :         CATCH_REQUIRE(var->get_type() == "integer");
    5171            1 :         CATCH_REQUIRE(std::static_pointer_cast<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(var)->get_integer() == 1);
    5172            1 :     }
    5173           47 :     CATCH_END_SECTION()
    5174              : 
    5175           47 :     CATCH_START_SECTION("reporter_executor_error: verify that the run() instruction does throw")
    5176              :     {
    5177            3 :         SNAP_CATCH2_NAMESPACE::reporter::instruction::pointer_t inst(SNAP_CATCH2_NAMESPACE::reporter::get_instruction("run"));
    5178            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    5179              : 
    5180            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    5181              :               inst->func(*s)
    5182              :             , ed::implementation_error
    5183              :             , Catch::Matchers::ExceptionMessage("implementation_error: run::func() was called when it should be intercepted by the executor."));
    5184            1 :     }
    5185           47 :     CATCH_END_SECTION()
    5186              : 
    5187           47 :     CATCH_START_SECTION("reporter_executor_error: invalid timestamp for set_variable() cast")
    5188              :     {
    5189            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_invalid_string_to_timestamp_cast.rprtr", g_program_invalid_string_to_timestamp_cast));
    5190            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    5191            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    5192            1 :         p->parse_program();
    5193              : 
    5194            1 :         CATCH_REQUIRE(s->get_statement_size() == 1);
    5195              : 
    5196            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    5197              : 
    5198            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    5199              :               e->start()
    5200              :             , ed::runtime_error
    5201              :             , Catch::Matchers::ExceptionMessage("event_dispatcher_exception: invalid timestamp, a valid floating point was expected (1713b34141.10780g991)."));
    5202              : 
    5203            1 :         CATCH_REQUIRE(s->get_exit_code() == -1);
    5204            1 :     }
    5205           47 :     CATCH_END_SECTION()
    5206              : 
    5207           47 :     CATCH_START_SECTION("reporter_executor_error: unknown string cast")
    5208              :     {
    5209            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_unknown_string_cast.rprtr", g_program_unknown_string_cast));
    5210            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    5211            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    5212            1 :         p->parse_program();
    5213              : 
    5214            1 :         CATCH_REQUIRE(s->get_statement_size() == 1);
    5215              : 
    5216            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    5217              : 
    5218            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    5219              :               e->start()
    5220              :             , ed::runtime_error
    5221              :             , Catch::Matchers::ExceptionMessage("event_dispatcher_exception: casting from \"string\" to \"unknown\" is not yet implemented."));
    5222              : 
    5223            1 :         CATCH_REQUIRE(s->get_exit_code() == -1);
    5224            1 :     }
    5225           47 :     CATCH_END_SECTION()
    5226              : 
    5227           47 :     CATCH_START_SECTION("reporter_executor_error: unknown timestamp cast")
    5228              :     {
    5229            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_unknown_string_cast.rprtr", g_program_unknown_timestamp_cast));
    5230            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    5231            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    5232            1 :         p->parse_program();
    5233              : 
    5234            1 :         CATCH_REQUIRE(s->get_statement_size() == 1);
    5235              : 
    5236            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    5237              : 
    5238            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    5239              :               e->start()
    5240              :             , ed::runtime_error
    5241              :             , Catch::Matchers::ExceptionMessage("event_dispatcher_exception: casting from \"timestamp\" to \"unknown\" is not yet implemented."));
    5242              : 
    5243            1 :         CATCH_REQUIRE(s->get_exit_code() == -1);
    5244            1 :     }
    5245           47 :     CATCH_END_SECTION()
    5246              : 
    5247           47 :     CATCH_START_SECTION("reporter_executor_error: unknown timestamp cast")
    5248              :     {
    5249            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_unknown_timestamp_cast.rprtr", g_program_unknown_source_cast));
    5250            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    5251            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    5252            1 :         p->parse_program();
    5253              : 
    5254            1 :         CATCH_REQUIRE(s->get_statement_size() == 1);
    5255              : 
    5256            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    5257              : 
    5258              :         // this test will fail once we implement such; at some point, all the different types will be supported and we'll have to remove this test...
    5259            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    5260              :               e->start()
    5261              :             , ed::runtime_error
    5262              :             , Catch::Matchers::ExceptionMessage("event_dispatcher_exception: casting from \"address\" to \"string\" is not yet implemented."));
    5263              : 
    5264            1 :         CATCH_REQUIRE(s->get_exit_code() == -1);
    5265            1 :     }
    5266           47 :     CATCH_END_SECTION()
    5267              : 
    5268           47 :     CATCH_START_SECTION("reporter_executor_error: sort() var1 missing")
    5269              :     {
    5270            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_sort_var1_missing.rprtr", g_program_sort_var1_missing));
    5271            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    5272            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    5273              : 
    5274              :         // this fails way before the inst_sort.func() gets called
    5275              :         //
    5276            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    5277              :               p->parse_program()
    5278              :             , ed::runtime_error
    5279              :             , Catch::Matchers::ExceptionMessage("event_dispatcher_exception: parameter \"var1\" is required by \"sort\"."));
    5280            1 :     }
    5281           47 :     CATCH_END_SECTION()
    5282              : 
    5283           47 :     CATCH_START_SECTION("reporter_executor_error: sort() var1 name must be a string")
    5284              :     {
    5285            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_sort_var1_name_not_string.rprtr", g_program_sort_var1_not_string));
    5286            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    5287            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    5288            1 :         p->parse_program();
    5289              : 
    5290            1 :         CATCH_REQUIRE(s->get_statement_size() == 1);
    5291              : 
    5292            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    5293              : 
    5294              :         // this fails before tje inst_sort.func() gets called
    5295              :         //
    5296            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    5297              :               e->start()
    5298              :             , ed::runtime_error
    5299              :             , Catch::Matchers::ExceptionMessage("event_dispatcher_exception: program_sort_var1_name_not_string.rprtr:1: parameter type mismatch for var1, expected \"string_or_identifier\", got \"integer\" instead."));
    5300              : 
    5301            1 :         CATCH_REQUIRE(s->get_exit_code() == -1);
    5302            1 :     }
    5303           47 :     CATCH_END_SECTION()
    5304              : 
    5305           47 :     CATCH_START_SECTION("reporter_executor_error: sort() var1 does not name an existing variable")
    5306              :     {
    5307            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_sort_var1_not_found.rprtr", g_program_sort_var1_not_found));
    5308            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    5309            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    5310            1 :         p->parse_program();
    5311              : 
    5312            1 :         CATCH_REQUIRE(s->get_statement_size() == 1);
    5313              : 
    5314            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    5315              : 
    5316              :         // this fails before tje inst_sort.func() gets called
    5317              :         //
    5318            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    5319              :               e->start()
    5320              :             , ed::runtime_error
    5321              :             , Catch::Matchers::ExceptionMessage("event_dispatcher_exception: program_sort_var1_not_found.rprtr:1: variable named \"not_defined\" not found."));
    5322              : 
    5323            1 :         CATCH_REQUIRE(s->get_exit_code() == -1);
    5324            1 :     }
    5325           47 :     CATCH_END_SECTION()
    5326              : 
    5327           47 :     CATCH_START_SECTION("reporter_executor_error: sort() does not accept all types yet")
    5328              :     {
    5329            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_sort_wrong_type.rprtr", g_program_sort_wrong_type));
    5330            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    5331            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    5332            1 :         p->parse_program();
    5333              : 
    5334            1 :         CATCH_REQUIRE(s->get_statement_size() == 2);
    5335              : 
    5336            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    5337              : 
    5338              :         // this fails before tje inst_sort.func() gets called
    5339              :         //
    5340            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    5341              :               e->start()
    5342              :             , ed::runtime_error
    5343              :             , Catch::Matchers::ExceptionMessage("event_dispatcher_exception: program_sort_wrong_type.rprtr:2:"
    5344              :                 " sort only supports strings, integers, or floating points."));
    5345              : 
    5346            1 :         CATCH_REQUIRE(s->get_exit_code() == -1);
    5347            1 :     }
    5348           47 :     CATCH_END_SECTION()
    5349              : 
    5350           47 :     CATCH_START_SECTION("reporter_executor_error: sort() does not accept mixed types")
    5351              :     {
    5352            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_sort_mixed_types.rprtr", g_program_sort_mixed_types));
    5353            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    5354            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    5355            1 :         p->parse_program();
    5356              : 
    5357            1 :         CATCH_REQUIRE(s->get_statement_size() == 4);
    5358              : 
    5359            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    5360              : 
    5361              :         // this fails before tje inst_sort.func() gets called
    5362              :         //
    5363            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    5364              :               e->start()
    5365              :             , ed::runtime_error
    5366              :             , Catch::Matchers::ExceptionMessage("event_dispatcher_exception: program_sort_mixed_types.rprtr:4:"
    5367              :                 " sort only supports one type of data (\"string\" in this case) for all the specified variables. \"integer\" is not compatible."));
    5368              : 
    5369            1 :         CATCH_REQUIRE(s->get_exit_code() == -1);
    5370            1 :     }
    5371           47 :     CATCH_END_SECTION()
    5372              : 
    5373           47 :     CATCH_START_SECTION("reporter_executor_error: listen() with unknown connection type")
    5374              :     {
    5375            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("listen_with_unknown_connection_type.rprtr", g_program_listen_with_unknown_connection_type));
    5376            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    5377            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    5378            1 :         p->parse_program();
    5379              : 
    5380            1 :         CATCH_REQUIRE(s->get_statement_size() == 1);
    5381              : 
    5382            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    5383            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    5384              :               e->start()
    5385              :             , ed::runtime_error
    5386              :             , Catch::Matchers::ExceptionMessage(
    5387              :                       "event_dispatcher_exception: unknown type \"unknown\" for listen()."));
    5388            1 :     }
    5389           47 :     CATCH_END_SECTION()
    5390           47 : }
    5391              : 
    5392              : 
    5393            3 : CATCH_TEST_CASE("reporter_executor_error_message", "[executor][reporter][error]")
    5394              : {
    5395            3 :     CATCH_START_SECTION("reporter_executor_error_message: verify message fails")
    5396              :     {
    5397              :         struct bad_verification_t
    5398              :         {
    5399              :             char const * const  f_program = nullptr;
    5400              :             char const * const  f_error = nullptr;
    5401              :         };
    5402            1 :         bad_verification_t const bad_verifications[] =
    5403              :         {
    5404              :             {
    5405              :                 g_program_verify_message_fail_sent_server,
    5406              :                 "event_dispatcher_exception: program_verify_message_fail.rprtr:9: message expected \"sent_server\", set to \"\", to match \"not_this_one\".",
    5407              :             },
    5408              :             {
    5409              :                 g_program_verify_message_fail_sent_service,
    5410              :                 "event_dispatcher_exception: program_verify_message_fail.rprtr:9: message expected \"sent_service\", set to \"\", to match \"not_this_one\".",
    5411              :             },
    5412              :             {
    5413              :                 g_program_verify_message_fail_server,
    5414              :                 "event_dispatcher_exception: program_verify_message_fail.rprtr:9: message expected \"server\", set to \"\", to match \"not_this_one\".",
    5415              :             },
    5416              :             {
    5417              :                 g_program_verify_message_fail_service,
    5418              :                 "event_dispatcher_exception: program_verify_message_fail.rprtr:9: message expected \"service\", set to \"\", to match \"not_this_one\".",
    5419              :             },
    5420              :             {
    5421              :                 g_program_verify_message_fail_command,
    5422              :                 "event_dispatcher_exception: program_verify_message_fail.rprtr:9: message expected \"command\", set to \"REGISTER\", to match \"NOT_THIS_ONE\".",
    5423              :             },
    5424              :             {
    5425              :                 g_program_verify_message_fail_forbidden,
    5426              :                 "event_dispatcher_exception: program_verify_message_fail.rprtr:9: message forbidden parameter \"version\" was found in this message.",
    5427              :             },
    5428              :             {
    5429              :                 g_program_verify_message_fail_required,
    5430              :                 "event_dispatcher_exception: program_verify_message_fail.rprtr:9: message required parameter \"not_this_one\" was not found in this message.",
    5431              :             },
    5432              :             {
    5433              :                 g_program_verify_message_fail_required_int_value,
    5434              :                 "event_dispatcher_exception: program_verify_message_fail.rprtr:9: message expected parameter \"version\" to be an integer set to \"200\" but found \"1\" instead.",
    5435              :             },
    5436              :             {
    5437              :                 g_program_verify_message_fail_required_str_value,
    5438              :                 "event_dispatcher_exception: program_verify_message_fail.rprtr:9: message expected parameter \"service\" to be a string set to \"not_this_one\" but found \"responder\" instead.",
    5439              :             },
    5440              :             {
    5441              :                 g_program_verify_message_fail_required_long_str_value,
    5442              :                 "event_dispatcher_exception: program_verify_message_fail.rprtr:9: message expected parameter \"service\" to be a string set to \"...responderresponderresponderresponderresponderresponderresponderresponderresponderresponderresponderresponderresponderresponder\" but found \"...\" instead.",
    5443              :             },
    5444              :             {
    5445              :                 g_program_verify_message_fail_required_flt_value,
    5446              :                 "event_dispatcher_exception: program_verify_message_fail.rprtr:9: message parameter type \"floating_point\" not supported yet.",
    5447              :             },
    5448              :             {
    5449              :                 g_program_verify_message_fail_required_timestamp_value,
    5450              :                 "event_dispatcher_exception: program_verify_message_fail.rprtr:9: message expected parameter \"version\", set to \"Thu Jan  1 00:00:01.000000000 1970\", to match timestamp \"Thu Jan  1 00:02:03.000000000 1970\".",
    5451              :             },
    5452              :             {
    5453              :                 g_program_verify_message_fail_timestamp_command,
    5454              :                 "event_dispatcher_exception: program_verify_message_fail.rprtr:9: message value \"command\" does not support type \"timestamp\".",
    5455              :             },
    5456              :             {
    5457              :                 g_program_verify_message_fail_unexpected_command,
    5458              :                 "event_dispatcher_exception: program_verify_message_fail.rprtr:9: message expected \"command\", set to \"REGISTER\", to match regex \"^NOT_THIS_ONE$\".",
    5459              :             },
    5460              :         };
    5461           15 :         for(auto const & bv : bad_verifications)
    5462              :         {
    5463           14 :             SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("program_verify_message_fail.rprtr", bv.f_program));
    5464           14 :             SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    5465           14 :             SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    5466           14 :             p->parse_program();
    5467              : 
    5468           14 :             SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    5469           14 :             e->start();
    5470           14 :             addr::addr a;
    5471           14 :             sockaddr_in ip = {
    5472              :                 .sin_family = AF_INET,
    5473           14 :                 .sin_port = htons(20002),
    5474              :                 .sin_addr = {
    5475           14 :                     .s_addr = htonl(0x7f000001),
    5476              :                 },
    5477              :                 .sin_zero = {},
    5478           14 :             };
    5479           14 :             a.set_ipv4(ip);
    5480           14 :             messenger_responder::pointer_t messenger(std::make_shared<messenger_responder>(
    5481              :                       a
    5482           14 :                     , ed::mode_t::MODE_PLAIN
    5483           28 :                     , messenger_responder::sequence_t::SEQUENCE_ONE_MESSAGE));
    5484           14 :             ed::communicator::instance()->add_connection(messenger);
    5485           14 :             messenger_timer::pointer_t timer(std::make_shared<messenger_timer>(messenger));
    5486           14 :             ed::communicator::instance()->add_connection(timer);
    5487           14 :             messenger->set_timer(timer);
    5488           14 :             e->set_thread_done_callback([messenger, timer]()
    5489              :                 {
    5490           14 :                     ed::communicator::instance()->remove_connection(messenger);
    5491           14 :                     ed::communicator::instance()->remove_connection(timer);
    5492           14 :                 });
    5493              : 
    5494           14 :             CATCH_REQUIRE(e->run());
    5495              : 
    5496              :             // the thread exception happens when e->stop() is called
    5497              :             //
    5498           42 :             CATCH_REQUIRE_THROWS_MATCHES(
    5499              :                   e->stop()
    5500              :                 , ed::runtime_error
    5501              :                 , Catch::Matchers::ExceptionMessage(bv.f_error));
    5502              : 
    5503              :             // if we exited because of our timer, then the test did not pass
    5504              :             //
    5505           14 :             CATCH_REQUIRE_FALSE(timer->timed_out_prima());
    5506              : 
    5507           14 :             CATCH_REQUIRE(s->get_exit_code() == -1);
    5508           14 :         }
    5509              :     }
    5510            3 :     CATCH_END_SECTION()
    5511              : 
    5512            3 :     CATCH_START_SECTION("reporter_executor_error_message: wait for nothing (should time out)")
    5513              :     {
    5514            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));
    5515            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    5516            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    5517            1 :         p->parse_program();
    5518              : 
    5519            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    5520            1 :         e->start();
    5521            1 :         addr::addr a;
    5522            1 :         sockaddr_in ip = {
    5523              :             .sin_family = AF_INET,
    5524            1 :             .sin_port = htons(20002),
    5525              :             .sin_addr = {
    5526            1 :                 .s_addr = htonl(0x7f000001),
    5527              :             },
    5528              :             .sin_zero = {},
    5529            1 :         };
    5530            1 :         a.set_ipv4(ip);
    5531            1 :         messenger_responder::pointer_t messenger(std::make_shared<messenger_responder>(
    5532              :                   a
    5533            1 :                 , ed::mode_t::MODE_PLAIN
    5534            2 :                 , messenger_responder::sequence_t::SEQUENCE_ONE_MESSAGE));
    5535            1 :         ed::communicator::instance()->add_connection(messenger);
    5536            1 :         messenger_timer::pointer_t timer(std::make_shared<messenger_timer>(messenger));
    5537            1 :         ed::communicator::instance()->add_connection(timer);
    5538            1 :         messenger->set_timer(timer);
    5539            1 :         e->set_thread_done_callback([messenger, timer]()
    5540              :             {
    5541            1 :                 ed::communicator::instance()->remove_connection(messenger);
    5542            1 :                 ed::communicator::instance()->remove_connection(timer);
    5543            1 :             });
    5544            1 :         CATCH_REQUIRE(e->run());
    5545              : 
    5546            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    5547              :               e->stop()
    5548              :             , ed::runtime_error
    5549              :             , Catch::Matchers::ExceptionMessage("event_dispatcher_exception: ppoll() timed out."));
    5550              : 
    5551              :         // if we exited because of our timer, then the test did not pass
    5552              :         //
    5553            1 :         CATCH_REQUIRE_FALSE(timer->timed_out_prima());
    5554              : 
    5555            1 :         CATCH_REQUIRE(s->get_exit_code() == -1);
    5556            1 :     }
    5557            3 :     CATCH_END_SECTION()
    5558              : 
    5559            3 :     CATCH_START_SECTION("reporter_executor_error_message: check parameter with incorrect regex fails")
    5560              :     {
    5561            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));
    5562            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    5563            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    5564            1 :         p->parse_program();
    5565              : 
    5566            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    5567            1 :         e->start();
    5568            1 :         addr::addr a;
    5569            1 :         sockaddr_in ip = {
    5570              :             .sin_family = AF_INET,
    5571            1 :             .sin_port = htons(20002),
    5572              :             .sin_addr = {
    5573            1 :                 .s_addr = htonl(0x7f000001),
    5574              :             },
    5575              :             .sin_zero = {},
    5576            1 :         };
    5577            1 :         a.set_ipv4(ip);
    5578            1 :         messenger_responder::pointer_t messenger(std::make_shared<messenger_responder>(
    5579              :                   a
    5580            1 :                 , ed::mode_t::MODE_PLAIN
    5581            2 :                 , messenger_responder::sequence_t::SEQUENCE_ONE_MESSAGE));
    5582            1 :         ed::communicator::instance()->add_connection(messenger);
    5583            1 :         messenger_timer::pointer_t timer(std::make_shared<messenger_timer>(messenger));
    5584            1 :         ed::communicator::instance()->add_connection(timer);
    5585            1 :         messenger->set_timer(timer);
    5586            1 :         e->set_thread_done_callback([messenger, timer]()
    5587              :             {
    5588            1 :                 ed::communicator::instance()->remove_connection(messenger);
    5589            1 :                 ed::communicator::instance()->remove_connection(timer);
    5590            1 :             });
    5591            1 :         CATCH_REQUIRE(e->run());
    5592              : 
    5593            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    5594              :               e->stop()
    5595              :             , ed::runtime_error
    5596              :             , Catch::Matchers::ExceptionMessage("event_dispatcher_exception: program_regex_parameter_no_match.rprtr:9: message expected parameter \"version\", set to \"1\", to match regex \"_[a-z]+\"."));
    5597              : 
    5598              :         // if we exited because of our timer, then the test did not pass
    5599              :         //
    5600            1 :         CATCH_REQUIRE_FALSE(timer->timed_out_prima());
    5601              : 
    5602            1 :         CATCH_REQUIRE(s->get_exit_code() == -1);
    5603            1 :     }
    5604            3 :     CATCH_END_SECTION()
    5605            3 : }
    5606              : 
    5607              : 
    5608            6 : CATCH_TEST_CASE("reporter_executor_error_data", "[executor][reporter][error]")
    5609              : {
    5610            6 :     CATCH_START_SECTION("reporter_executor_error_data: read too large")
    5611              :     {
    5612            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("raw_tcp_connection.rprtr", g_program_raw_tcp_connection_read_too_large));
    5613            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    5614            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    5615            1 :         p->parse_program();
    5616              : 
    5617            1 :         CATCH_REQUIRE(s->get_statement_size() == 11);
    5618              : 
    5619            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    5620            1 :         e->start();
    5621            1 :         addr::addr a;
    5622            1 :         sockaddr_in ip = {
    5623              :             .sin_family = AF_INET,
    5624            1 :             .sin_port = htons(20002),
    5625              :             .sin_addr = {
    5626            1 :                 .s_addr = htonl(0x7f000001),
    5627              :             },
    5628              :             .sin_zero = {},
    5629            1 :         };
    5630            1 :         a.set_ipv4(ip);
    5631            1 :         permanent_binary_responder::pointer_t binary_responder(std::make_shared<permanent_binary_responder>(
    5632              :                   a
    5633            1 :                 , ed::mode_t::MODE_PLAIN
    5634            2 :                 , permanent_binary_responder::sequence_t::SEQUENCE_PING_PONG));
    5635            1 :         ed::communicator::instance()->add_connection(binary_responder);
    5636            1 :         binary_responder->mark_complete();
    5637              : 
    5638            1 :         e->set_thread_done_callback([binary_responder]()
    5639              :             {
    5640            1 :                 ed::communicator::instance()->remove_connection(binary_responder);
    5641            1 :             });
    5642              : 
    5643            1 :         CATCH_REQUIRE(e->run());
    5644              : 
    5645            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    5646              :               e->stop()
    5647              :             , ed::runtime_error
    5648              :             , Catch::Matchers::ExceptionMessage("event_dispatcher_exception: raw_tcp_connection.rprtr:10: could not read 5 bytes from the data buffer, got 4 instead."));
    5649            1 :     }
    5650            6 :     CATCH_END_SECTION()
    5651              : 
    5652            6 :     CATCH_START_SECTION("reporter_executor_error_data: verify fails")
    5653              :     {
    5654            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("raw_tcp_connection.rprtr", g_program_raw_tcp_connection_verify_fails));
    5655            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    5656            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    5657            1 :         p->parse_program();
    5658              : 
    5659            1 :         CATCH_REQUIRE(s->get_statement_size() == 11);
    5660              : 
    5661            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    5662            1 :         e->start();
    5663            1 :         addr::addr a;
    5664            1 :         sockaddr_in ip = {
    5665              :             .sin_family = AF_INET,
    5666            1 :             .sin_port = htons(20002),
    5667              :             .sin_addr = {
    5668            1 :                 .s_addr = htonl(0x7f000001),
    5669              :             },
    5670              :             .sin_zero = {},
    5671            1 :         };
    5672            1 :         a.set_ipv4(ip);
    5673            1 :         permanent_binary_responder::pointer_t binary_responder(std::make_shared<permanent_binary_responder>(
    5674              :                   a
    5675            1 :                 , ed::mode_t::MODE_PLAIN
    5676            2 :                 , permanent_binary_responder::sequence_t::SEQUENCE_PING_PONG));
    5677            1 :         ed::communicator::instance()->add_connection(binary_responder);
    5678            1 :         binary_responder->mark_complete();
    5679              : 
    5680            1 :         e->set_thread_done_callback([binary_responder]()
    5681              :             {
    5682            1 :                 ed::communicator::instance()->remove_connection(binary_responder);
    5683            1 :             });
    5684              : 
    5685            1 :         CATCH_REQUIRE(e->run());
    5686              : 
    5687            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    5688              :               e->stop()
    5689              :             , ed::runtime_error
    5690              :             , Catch::Matchers::ExceptionMessage("event_dispatcher_exception: raw_tcp_connection.rprtr:10: values at offset 0 do not match (80 != 73)."));
    5691            1 :     }
    5692            6 :     CATCH_END_SECTION()
    5693              : 
    5694            6 :     CATCH_START_SECTION("reporter_executor_error_data: verify fails")
    5695              :     {
    5696            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("raw_tcp_connection.rprtr", g_program_raw_tcp_connection_send_invalid_value_too_large));
    5697            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    5698            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    5699            1 :         p->parse_program();
    5700              : 
    5701            1 :         CATCH_REQUIRE(s->get_statement_size() == 15);
    5702              : 
    5703            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    5704            1 :         e->start();
    5705            1 :         addr::addr a;
    5706            1 :         sockaddr_in ip = {
    5707              :             .sin_family = AF_INET,
    5708            1 :             .sin_port = htons(20002),
    5709              :             .sin_addr = {
    5710            1 :                 .s_addr = htonl(0x7f000001),
    5711              :             },
    5712              :             .sin_zero = {},
    5713            1 :         };
    5714            1 :         a.set_ipv4(ip);
    5715            1 :         permanent_binary_responder::pointer_t binary_responder(std::make_shared<permanent_binary_responder>(
    5716              :                   a
    5717            1 :                 , ed::mode_t::MODE_PLAIN
    5718            2 :                 , permanent_binary_responder::sequence_t::SEQUENCE_PING_PONG));
    5719            1 :         ed::communicator::instance()->add_connection(binary_responder);
    5720            1 :         binary_responder->mark_complete();
    5721              : 
    5722            1 :         e->set_thread_done_callback([binary_responder]()
    5723              :             {
    5724            1 :                 ed::communicator::instance()->remove_connection(binary_responder);
    5725            1 :             });
    5726              : 
    5727            1 :         CATCH_REQUIRE(e->run());
    5728              : 
    5729            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    5730              :               e->stop()
    5731              :             , ed::runtime_error
    5732              :             , Catch::Matchers::ExceptionMessage("event_dispatcher_exception: raw_tcp_connection.rprtr:14: byte values must be between -128 and +255 (position 2 has out of range value 256)."));
    5733            1 :     }
    5734            6 :     CATCH_END_SECTION()
    5735              : 
    5736            6 :     CATCH_START_SECTION("reporter_executor_error_data: verify fails")
    5737              :     {
    5738            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("raw_tcp_connection.rprtr", g_program_raw_tcp_connection_send_invalid_value_too_small));
    5739            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    5740            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    5741            1 :         p->parse_program();
    5742              : 
    5743            1 :         CATCH_REQUIRE(s->get_statement_size() == 15);
    5744              : 
    5745            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    5746            1 :         e->start();
    5747            1 :         addr::addr a;
    5748            1 :         sockaddr_in ip = {
    5749              :             .sin_family = AF_INET,
    5750            1 :             .sin_port = htons(20002),
    5751              :             .sin_addr = {
    5752            1 :                 .s_addr = htonl(0x7f000001),
    5753              :             },
    5754              :             .sin_zero = {},
    5755            1 :         };
    5756            1 :         a.set_ipv4(ip);
    5757            1 :         permanent_binary_responder::pointer_t binary_responder(std::make_shared<permanent_binary_responder>(
    5758              :                   a
    5759            1 :                 , ed::mode_t::MODE_PLAIN
    5760            2 :                 , permanent_binary_responder::sequence_t::SEQUENCE_PING_PONG));
    5761            1 :         ed::communicator::instance()->add_connection(binary_responder);
    5762            1 :         binary_responder->mark_complete();
    5763              : 
    5764            1 :         e->set_thread_done_callback([binary_responder]()
    5765              :             {
    5766            1 :                 ed::communicator::instance()->remove_connection(binary_responder);
    5767            1 :             });
    5768              : 
    5769            1 :         CATCH_REQUIRE(e->run());
    5770              : 
    5771            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    5772              :               e->stop()
    5773              :             , ed::runtime_error
    5774              :             , Catch::Matchers::ExceptionMessage("event_dispatcher_exception: raw_tcp_connection.rprtr:14: byte values must be between -128 and +255 (position 2 has out of range value -129)."));
    5775            1 :     }
    5776            6 :     CATCH_END_SECTION()
    5777              : 
    5778            6 :     CATCH_START_SECTION("reporter_executor_error_data: empty array sending data")
    5779              :     {
    5780            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("raw_tcp_connection.rprtr", g_program_raw_tcp_connection_send_empty_array));
    5781            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    5782            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    5783            1 :         p->parse_program();
    5784              : 
    5785            1 :         CATCH_REQUIRE(s->get_statement_size() == 15);
    5786              : 
    5787            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    5788            1 :         e->start();
    5789            1 :         addr::addr a;
    5790            1 :         sockaddr_in ip = {
    5791              :             .sin_family = AF_INET,
    5792            1 :             .sin_port = htons(20002),
    5793              :             .sin_addr = {
    5794            1 :                 .s_addr = htonl(0x7f000001),
    5795              :             },
    5796              :             .sin_zero = {},
    5797            1 :         };
    5798            1 :         a.set_ipv4(ip);
    5799            1 :         permanent_binary_responder::pointer_t binary_responder(std::make_shared<permanent_binary_responder>(
    5800              :                   a
    5801            1 :                 , ed::mode_t::MODE_PLAIN
    5802            2 :                 , permanent_binary_responder::sequence_t::SEQUENCE_PING_PONG));
    5803            1 :         ed::communicator::instance()->add_connection(binary_responder);
    5804            1 :         binary_responder->mark_complete();
    5805              : 
    5806            1 :         e->set_thread_done_callback([binary_responder]()
    5807              :             {
    5808            1 :                 ed::communicator::instance()->remove_connection(binary_responder);
    5809            1 :             });
    5810              : 
    5811            1 :         CATCH_REQUIRE(e->run());
    5812              : 
    5813            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    5814              :               e->stop()
    5815              :             , ed::runtime_error
    5816              :             , Catch::Matchers::ExceptionMessage("event_dispatcher_exception: raw_tcp_connection.rprtr:14: array cannot be empty."));
    5817            1 :     }
    5818            6 :     CATCH_END_SECTION()
    5819              : 
    5820            6 :     CATCH_START_SECTION("reporter_executor_error_data: empty array verifying data")
    5821              :     {
    5822            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::lexer>("raw_tcp_connection.rprtr", g_program_raw_tcp_connection_verify_empty_array));
    5823            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    5824            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    5825            1 :         p->parse_program();
    5826              : 
    5827            1 :         CATCH_REQUIRE(s->get_statement_size() == 11);
    5828              : 
    5829            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    5830            1 :         e->start();
    5831            1 :         addr::addr a;
    5832            1 :         sockaddr_in ip = {
    5833              :             .sin_family = AF_INET,
    5834            1 :             .sin_port = htons(20002),
    5835              :             .sin_addr = {
    5836            1 :                 .s_addr = htonl(0x7f000001),
    5837              :             },
    5838              :             .sin_zero = {},
    5839            1 :         };
    5840            1 :         a.set_ipv4(ip);
    5841            1 :         permanent_binary_responder::pointer_t binary_responder(std::make_shared<permanent_binary_responder>(
    5842              :                   a
    5843            1 :                 , ed::mode_t::MODE_PLAIN
    5844            2 :                 , permanent_binary_responder::sequence_t::SEQUENCE_PING_PONG));
    5845            1 :         ed::communicator::instance()->add_connection(binary_responder);
    5846            1 :         binary_responder->mark_complete();
    5847              : 
    5848            1 :         e->set_thread_done_callback([binary_responder]()
    5849              :             {
    5850            1 :                 ed::communicator::instance()->remove_connection(binary_responder);
    5851            1 :             });
    5852              : 
    5853            1 :         CATCH_REQUIRE(e->run());
    5854              : 
    5855            3 :         CATCH_REQUIRE_THROWS_MATCHES(
    5856              :               e->stop()
    5857              :             , ed::runtime_error
    5858              :             , Catch::Matchers::ExceptionMessage("event_dispatcher_exception: raw_tcp_connection.rprtr:10: array cannot be empty."));
    5859            1 :     }
    5860            6 :     CATCH_END_SECTION()
    5861            6 : }
    5862              : 
    5863              : 
    5864              : 
    5865              : // vim: ts=4 sw=4 et
        

Generated by: LCOV version 2.0-1

Snap C++ | List of projects | List of versions