LCOV - code coverage report
Current view: top level - tests - catch_main.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 362 530 68.3 %
Date: 2023-07-29 22:00:24 Functions: 18 22 81.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2011-2023  Made to Order Software Corp.  All Rights Reserved
       2             : //
       3             : // https://snapwebsites.org/project/as2js
       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             : // self
      20             : //
      21             : #define CATCH_CONFIG_RUNNER
      22             : #include    "catch_main.h"
      23             : 
      24             : 
      25             : 
      26             : // as2js
      27             : //
      28             : #include    <as2js/exception.h>
      29             : #include    <as2js/version.h>
      30             : 
      31             : 
      32             : // libexcept
      33             : //
      34             : #include    <libexcept/exception.h>
      35             : 
      36             : 
      37             : // snapdev
      38             : //
      39             : #include    <snapdev/not_used.h>
      40             : #include    <snapdev/mkdir_p.h>
      41             : 
      42             : 
      43             : // C
      44             : //
      45             : #include    <sys/stat.h>
      46             : 
      47             : 
      48             : // last include
      49             : //
      50             : #include    <snapdev/poison.h>
      51             : 
      52             : 
      53             : 
      54             : 
      55             : namespace SNAP_CATCH2_NAMESPACE
      56             : {
      57             : 
      58             : 
      59             : 
      60             : #define    TO_STR_sub(s)    #s
      61             : 
      62             : 
      63             : 
      64             : // command line flags
      65             : //
      66             : std::string     g_as2js_compiler;
      67             : bool            g_run_destructive = false;
      68             : bool            g_save_parser_tests = false;
      69             : 
      70             : 
      71             : 
      72             : 
      73             : 
      74             : // class used to capture error messages
      75             : 
      76     1873468 : test_callback::test_callback(bool verbose, bool parser)
      77     1873468 :     : f_verbose(verbose)
      78     1873468 :     , f_parser(parser)
      79             : {
      80     1873468 :     as2js::set_message_callback(this);
      81     1873468 :     fix_counters();
      82     1873468 : }
      83             : 
      84             : 
      85     1873468 : test_callback::~test_callback()
      86             : {
      87             :     // make sure the pointer gets reset!
      88             :     //
      89     1873468 :     as2js::set_message_callback(nullptr);
      90     1873468 : }
      91             : 
      92             : 
      93     1873468 : void test_callback::fix_counters()
      94             : {
      95     1873468 :     g_warning_count = as2js::warning_count();
      96     1873468 :     g_error_count = as2js::error_count();
      97     1873468 : }
      98             : 
      99             : 
     100             : // implementation of the output
     101     2573474 : void test_callback::output(as2js::message_level_t message_level, as2js::err_code_t error_code, as2js::position const & pos, std::string const& message)
     102             : {
     103             :     // skip trace messages
     104             :     //
     105     2573474 :     if(message_level == as2js::message_level_t::MESSAGE_LEVEL_TRACE)
     106             :     {
     107           0 :         return;
     108             :     }
     109     2573474 :     ++f_position;
     110             : 
     111     2573474 :     if(f_expected.empty())
     112             :     {
     113           0 :         std::cerr << "\n*** STILL NECESSARY *** (#" << f_position << ")\n";
     114           0 :         std::cerr << "filename = " << pos.get_filename() << "\n";
     115           0 :         std::cerr << "message level = " << static_cast<int>(message_level) << " (" << message_level << ")\n";
     116           0 :         std::cerr << "msg = " << message << "\n";
     117           0 :         std::cerr << "page = " << pos.get_page() << "\n";
     118           0 :         std::cerr << "line = " << pos.get_line() << "\n";
     119           0 :         std::cerr << "error code = " << static_cast<int>(error_code) << " (" << error_code_to_str(error_code) << ")\n";
     120             :     }
     121             : 
     122     2573474 :     CATCH_REQUIRE(!f_expected.empty());
     123             : 
     124             :     // the compiler uses this flag to generate the following warning
     125             :     //
     126     2573474 :     if(f_parser)
     127             :     {
     128             :         std::cerr << "\n                 >>> WARNING <<<\n"
     129             :                      "  >>> You got an error from the parser. These should not happen here.\n"
     130             :                      "  >>> If you need to test something in the parser, move your test to the\n"
     131           0 :                      "  >>> tests/parser_data/*.json files instead.\n\n";
     132             :     }
     133             : 
     134     5146948 :     bool const error(!f_expected[0].f_call
     135     2573474 :               || message_level != f_expected[0].f_message_level
     136     2573474 :               || error_code != f_expected[0].f_error_code
     137     7720422 :               || pos.get_filename() != f_expected[0].f_pos.get_filename()
     138     5146948 :               || pos.get_function() != f_expected[0].f_pos.get_function()
     139     2573474 :               || pos.get_page() != f_expected[0].f_pos.get_page()
     140     2573474 :               || pos.get_page_line() != f_expected[0].f_pos.get_page_line()
     141     2573474 :               || pos.get_paragraph() != f_expected[0].f_pos.get_paragraph()
     142     2573474 :               || pos.get_line() != f_expected[0].f_pos.get_line()
     143     5146948 :               || message != f_expected[0].f_message);
     144     2573474 :     bool const verbose(f_verbose || error);
     145     2573474 :     if(verbose)
     146             :     {
     147           0 :         std::cerr << "\n";
     148           0 :         if(error)
     149             :         {
     150           0 :             std::cerr << "*** FAILED TEST *** (#" << f_position << ")\n";
     151             :         }
     152             :         else
     153             :         {
     154           0 :             std::cerr << "*** TEST MESSAGE *** (#" << f_position << ")\n";
     155             :         }
     156           0 :         std::cerr << "filename = " << pos.get_filename() << " (node) / " << f_expected[0].f_pos.get_filename() << " (JSON)\n";
     157           0 :         std::cerr << "message level = " << static_cast<int>(message_level) << " (" << message_level
     158           0 :                   << ") / " << static_cast<int>(f_expected[0].f_message_level) << " (" << f_expected[0].f_message_level << ")\n";
     159             :         std::cerr << "msg = " << message << '\n'
     160           0 :                   << "    / " << f_expected[0].f_message << '\n';
     161           0 :         std::cerr << "page = " << pos.get_page() << " / " << f_expected[0].f_pos.get_page() << '\n';
     162           0 :         std::cerr << "line = " << pos.get_line() << " / " << f_expected[0].f_pos.get_line() << '\n';
     163           0 :         std::cerr << "page line = " << pos.get_page_line() << " / " << f_expected[0].f_pos.get_page_line() << '\n';
     164           0 :         std::cerr << "error code = " << static_cast<int>(error_code) << " (" << error_code_to_str(error_code)
     165           0 :                   << ") / " << static_cast<int>(f_expected[0].f_error_code)
     166           0 :                   << " (" << error_code_to_str(f_expected[0].f_error_code) << ")\n";
     167             :     }
     168             : 
     169     2573474 :     CATCH_REQUIRE(f_expected[0].f_call);
     170     2573474 :     CATCH_REQUIRE(message_level == f_expected[0].f_message_level);
     171     2573474 :     CATCH_REQUIRE(error_code == f_expected[0].f_error_code);
     172     2573474 :     CATCH_REQUIRE(pos.get_filename() == f_expected[0].f_pos.get_filename());
     173     2573474 :     CATCH_REQUIRE(pos.get_function() == f_expected[0].f_pos.get_function());
     174     2573474 :     CATCH_REQUIRE(pos.get_page() == f_expected[0].f_pos.get_page());
     175     2573474 :     CATCH_REQUIRE(pos.get_page_line() == f_expected[0].f_pos.get_page_line());
     176     2573474 :     CATCH_REQUIRE(pos.get_paragraph() == f_expected[0].f_pos.get_paragraph());
     177     2573474 :     CATCH_REQUIRE(pos.get_line() == f_expected[0].f_pos.get_line());
     178     2573474 :     CATCH_REQUIRE(message == f_expected[0].f_message);
     179             : 
     180     2573474 :     if(message_level == as2js::message_level_t::MESSAGE_LEVEL_WARNING)
     181             :     {
     182       16398 :         ++g_warning_count;
     183       16398 :         CATCH_REQUIRE(g_warning_count == as2js::warning_count());
     184             :     }
     185             : 
     186     2573474 :     if(message_level == as2js::message_level_t::MESSAGE_LEVEL_FATAL
     187     2573474 :     || message_level == as2js::message_level_t::MESSAGE_LEVEL_ERROR)
     188             :     {
     189     2548884 :         ++g_error_count;
     190             : //std::cerr << "error: " << g_error_count << " / " << as2js::error_count() << "\n";
     191     2548884 :         CATCH_REQUIRE(g_error_count == as2js::error_count());
     192             :     }
     193             : 
     194     2573474 :     f_expected.erase(f_expected.begin());
     195             : }
     196             : 
     197     1835442 : void test_callback::got_called()
     198             : {
     199     1835442 :     if(!f_expected.empty())
     200             :     {
     201           0 :         std::cerr << "\n*** STILL " << f_expected.size() << " EXPECTED *** (#" << f_position << ")\n";
     202           0 :         std::cerr << "filename = " << f_expected[0].f_pos.get_filename() << "\n";
     203           0 :         std::cerr << "message level = " << static_cast<int>(f_expected[0].f_message_level)
     204           0 :                         << " (" << f_expected[0].f_message_level << ")\n";
     205           0 :         std::cerr << "msg = " << f_expected[0].f_message << "\n";
     206           0 :         std::cerr << "page = " << f_expected[0].f_pos.get_page() << "\n";
     207           0 :         std::cerr << "line = " << f_expected[0].f_pos.get_line() << "\n";
     208           0 :         std::cerr << "error code = " << static_cast<int>(f_expected[0].f_error_code)
     209           0 :                         << " (" << error_code_to_str(f_expected[0].f_error_code) << ")\n";
     210             :     }
     211     1835442 :     CATCH_REQUIRE(f_expected.empty());
     212     1835442 : }
     213             : 
     214             : std::int32_t    test_callback::g_warning_count = 0;
     215             : std::int32_t    test_callback::g_error_count = 0;
     216             : 
     217             : 
     218             : 
     219             : 
     220             : 
     221             : // functions to convert error codes to/from strings
     222             : 
     223             : struct err_to_string_t
     224             : {
     225             :     as2js::err_code_t       f_code;
     226             :     char const *            f_name;
     227             :     int                     f_line;
     228             : };
     229             : 
     230             : #define    ERROR_NAME(err)  { as2js::err_code_t::AS_ERR_##err, TO_STR_sub(err), __LINE__ }
     231             : 
     232             : constexpr err_to_string_t const g_error_table[] =
     233             : {
     234             :     ERROR_NAME(NONE),
     235             :     ERROR_NAME(ABSTRACT),
     236             :     ERROR_NAME(BAD_NUMERIC_TYPE),
     237             :     ERROR_NAME(BAD_PRAGMA),
     238             :     ERROR_NAME(CANNOT_COMPILE),
     239             :     ERROR_NAME(CANNOT_MATCH),
     240             :     ERROR_NAME(CANNOT_OVERLOAD),
     241             :     ERROR_NAME(CANNOT_OVERWRITE_CONST),
     242             :     ERROR_NAME(CASE_LABEL),
     243             :     ERROR_NAME(COLON_EXPECTED),
     244             :     ERROR_NAME(COMMA_EXPECTED),
     245             :     ERROR_NAME(CURVLY_BRACKETS_EXPECTED),
     246             :     ERROR_NAME(DEFAULT_LABEL),
     247             :     ERROR_NAME(DIVIDE_BY_ZERO),
     248             :     ERROR_NAME(DUPLICATES),
     249             :     ERROR_NAME(DYNAMIC),
     250             :     ERROR_NAME(EXPRESSION_EXPECTED),
     251             :     ERROR_NAME(FINAL),
     252             :     ERROR_NAME(IMPROPER_STATEMENT),
     253             :     ERROR_NAME(INACCESSIBLE_STATEMENT),
     254             :     ERROR_NAME(INCOMPATIBLE),
     255             :     ERROR_NAME(INCOMPATIBLE_PRAGMA_ARGUMENT),
     256             :     ERROR_NAME(INSTALLATION),
     257             :     ERROR_NAME(INSTANCE_EXPECTED),
     258             :     ERROR_NAME(INTERNAL_ERROR),
     259             :     ERROR_NAME(NATIVE),
     260             :     ERROR_NAME(INVALID_ARRAY_FUNCTION),
     261             :     ERROR_NAME(INVALID_ATTRIBUTES),
     262             :     ERROR_NAME(INVALID_CATCH),
     263             :     ERROR_NAME(INVALID_CLASS),
     264             :     ERROR_NAME(INVALID_CONDITIONAL),
     265             :     ERROR_NAME(INVALID_DEFINITION),
     266             :     ERROR_NAME(INVALID_DO),
     267             :     ERROR_NAME(INVALID_ENUM),
     268             :     ERROR_NAME(INVALID_EXPRESSION),
     269             :     ERROR_NAME(INVALID_FIELD),
     270             :     ERROR_NAME(INVALID_FIELD_NAME),
     271             :     ERROR_NAME(INVALID_FRAME),
     272             :     ERROR_NAME(INVALID_FUNCTION),
     273             :     ERROR_NAME(INVALID_GOTO),
     274             :     ERROR_NAME(INVALID_IMPORT),
     275             :     ERROR_NAME(INVALID_INPUT_STREAM),
     276             :     ERROR_NAME(INVALID_KEYWORD),
     277             :     ERROR_NAME(INVALID_LABEL),
     278             :     ERROR_NAME(INVALID_NAMESPACE),
     279             :     ERROR_NAME(INVALID_NODE),
     280             :     ERROR_NAME(INVALID_NUMBER),
     281             :     ERROR_NAME(INVALID_OPERATOR),
     282             :     ERROR_NAME(INVALID_PACKAGE_NAME),
     283             :     ERROR_NAME(INVALID_PARAMETERS),
     284             :     ERROR_NAME(INVALID_REST),
     285             :     ERROR_NAME(INVALID_RETURN_TYPE),
     286             :     ERROR_NAME(INVALID_SCOPE),
     287             :     ERROR_NAME(INVALID_TEMPLATE),
     288             :     ERROR_NAME(INVALID_TRY),
     289             :     ERROR_NAME(INVALID_TYPE),
     290             :     ERROR_NAME(INVALID_UNICODE_ESCAPE_SEQUENCE),
     291             :     ERROR_NAME(INVALID_VARIABLE),
     292             :     ERROR_NAME(IO_ERROR),
     293             :     ERROR_NAME(LABEL_NOT_FOUND),
     294             :     ERROR_NAME(LOOPING_REFERENCE),
     295             :     ERROR_NAME(MISMATCH_FUNC_VAR),
     296             :     ERROR_NAME(MISSSING_VARIABLE_NAME),
     297             :     ERROR_NAME(NEED_CONST),
     298             :     ERROR_NAME(NOT_ALLOWED),
     299             :     ERROR_NAME(NOT_ALLOWED_IN_STRICT_MODE),
     300             :     ERROR_NAME(NOT_FOUND),
     301             :     ERROR_NAME(NOT_SUPPORTED),
     302             :     ERROR_NAME(OBJECT_MEMBER_DEFINED_TWICE),
     303             :     ERROR_NAME(PARENTHESIS_EXPECTED),
     304             :     ERROR_NAME(PRAGMA_FAILED),
     305             :     ERROR_NAME(SEMICOLON_EXPECTED),
     306             :     ERROR_NAME(SQUARE_BRACKETS_EXPECTED),
     307             :     ERROR_NAME(STRING_EXPECTED),
     308             :     ERROR_NAME(STATIC),
     309             :     ERROR_NAME(TYPE_NOT_LINKED),
     310             :     ERROR_NAME(UNKNOWN_ESCAPE_SEQUENCE),
     311             :     ERROR_NAME(UNKNOWN_OPERATOR),
     312             :     ERROR_NAME(UNKNOWN_PRAGMA),
     313             :     ERROR_NAME(UNTERMINATED_STRING),
     314             :     ERROR_NAME(UNEXPECTED_EOF),
     315             :     ERROR_NAME(UNEXPECTED_PUNCTUATION),
     316             :     ERROR_NAME(UNEXPECTED_TOKEN),
     317             :     ERROR_NAME(UNEXPECTED_DATABASE),
     318             :     ERROR_NAME(UNEXPECTED_RC)
     319             : };
     320             : constexpr std::size_t const g_error_table_size = sizeof(g_error_table) / sizeof(g_error_table[0]);
     321             : 
     322             : 
     323     1458190 : as2js::err_code_t str_to_error_code(std::string const & error_name)
     324             : {
     325    66609810 :     for(size_t idx(0); idx < g_error_table_size; ++idx)
     326             :     {
     327    66609810 :         if(error_name == g_error_table[idx].f_name)
     328             :         {
     329     1458190 :             return g_error_table[idx].f_code;
     330             :         }
     331             :     }
     332           0 :     std::cerr << "Error name \"" << error_name << "\" not found.\n";
     333           0 :     CATCH_REQUIRE(!"error name not found, catch_parser.cpp bug");
     334           0 :     return as2js::err_code_t::AS_ERR_NONE;
     335             : }
     336             : 
     337             : 
     338           0 : char const * error_code_to_str(as2js::err_code_t const error_code)
     339             : {
     340             :     // TODO: the error code should be in order
     341             :     //       1. verify that the order is indeed correct
     342             :     //       2. use a binary search instead
     343             :     //
     344           0 :     for(std::size_t idx(0); idx < g_error_table_size; ++idx)
     345             :     {
     346           0 :         if(error_code == g_error_table[idx].f_code)
     347             :         {
     348           0 :             return g_error_table[idx].f_name;
     349             :         }
     350             :     }
     351           0 :     std::cerr << "Error code \"" << static_cast<int>(error_code) << "\" not found.\n";
     352           0 :     CATCH_REQUIRE(!"error code not found, catch_parser.cpp bug");
     353           0 :     return "unknown";
     354             : }
     355             : 
     356             : 
     357             : 
     358             : 
     359             : 
     360             : 
     361             : // Options
     362             : 
     363             : //
     364             : // we have two special pragmas that accept 0, 1, 2, or 3
     365             : // namely, those are:
     366             : //
     367             : //  . OPTION_EXTENDED_STATEMENTS -- force '{' ... '}' in
     368             : //    blocks for: if, while, do, for, with...
     369             : //
     370             : //  . OPTION_EXTENDED_OPERATORS -- force ':=' instead of '='
     371             : //
     372             : // for this reason we support and f_value which is viewed
     373             : // as a set of flags
     374             : //
     375             : named_options const g_options[] =
     376             : {
     377             :     {
     378             :         as2js::option_t::OPTION_ALLOW_WITH,
     379             :         "allow_with",
     380             :         "no_allow_with",
     381             :         1
     382             :     },
     383             :     {
     384             :         as2js::option_t::OPTION_COVERAGE,
     385             :         "coverage",
     386             :         "no_coverage",
     387             :         1
     388             :     },
     389             :     {
     390             :         as2js::option_t::OPTION_DEBUG,
     391             :         "debug",
     392             :         "no_debug",
     393             :         1
     394             :     },
     395             :     {
     396             :         as2js::option_t::OPTION_EXTENDED_ESCAPE_SEQUENCES,
     397             :         "extended_escape_sequences",
     398             :         "no_extended_escape_sequences",
     399             :         1
     400             :     },
     401             :     {
     402             :         as2js::option_t::OPTION_EXTENDED_OPERATORS,
     403             :         "extended_operators",
     404             :         "no_extended_operators",
     405             :         1
     406             :     },
     407             :     {
     408             :         as2js::option_t::OPTION_EXTENDED_OPERATORS,
     409             :         "extended_operators_safe",
     410             :         "no_extended_operators_safe",
     411             :         2
     412             :     },
     413             :     {
     414             :         as2js::option_t::OPTION_EXTENDED_STATEMENTS,
     415             :         "extended_statements",
     416             :         "no_extended_statements",
     417             :         1
     418             :     },
     419             :     {
     420             :         as2js::option_t::OPTION_EXTENDED_STATEMENTS,
     421             :         "extended_statements_safe",
     422             :         "no_extended_statements_safe",
     423             :         2
     424             :     },
     425             :     //{ -- this one does not make sense here
     426             :     //    as2js::option_t::OPTION_JSON,
     427             :     //    "json",
     428             :     //    "no_json"
     429             :     //},
     430             :     {
     431             :         as2js::option_t::OPTION_OCTAL,
     432             :         "octal",
     433             :         "no_octal",
     434             :         1
     435             :     },
     436             :     {
     437             :         as2js::option_t::OPTION_STRICT,
     438             :         "strict",
     439             :         "no_strict",
     440             :         1
     441             :     },
     442             :     {
     443             :         as2js::option_t::OPTION_TRACE,
     444             :         "trace",
     445             :         "no_trace",
     446             :         1
     447             :     },
     448             :     {
     449             :         as2js::option_t::OPTION_UNSAFE_MATH,
     450             :         "unsafe_math",
     451             :         "no_unsafe_math",
     452             :         1
     453             :     }
     454             : };
     455             : std::size_t const g_options_size = sizeof(g_options) / sizeof(g_options[0]);
     456             : 
     457             : 
     458             : 
     459             : 
     460             : 
     461             : 
     462             : // Flags
     463             : 
     464             : struct flg_to_string_t
     465             : {
     466             :     as2js::flag_t           f_flag;
     467             :     char const *            f_name;
     468             :     int                     f_line;
     469             : };
     470             : 
     471             : #define    FLAG_NAME(flg)     { as2js::flag_t::NODE_##flg, TO_STR_sub(flg), __LINE__ }
     472             : 
     473             : constexpr flg_to_string_t const g_flag_table[] =
     474             : {
     475             :     FLAG_NAME(CATCH_FLAG_TYPED),
     476             :     FLAG_NAME(DIRECTIVE_LIST_FLAG_NEW_VARIABLES),
     477             :     FLAG_NAME(ENUM_FLAG_CLASS),
     478             :     FLAG_NAME(FOR_FLAG_CONST),
     479             :     FLAG_NAME(FOR_FLAG_FOREACH),
     480             :     FLAG_NAME(FOR_FLAG_IN),
     481             :     FLAG_NAME(FUNCTION_FLAG_GETTER),
     482             :     FLAG_NAME(FUNCTION_FLAG_SETTER),
     483             :     FLAG_NAME(FUNCTION_FLAG_OUT),
     484             :     FLAG_NAME(FUNCTION_FLAG_VOID),
     485             :     FLAG_NAME(FUNCTION_FLAG_NEVER),
     486             :     FLAG_NAME(FUNCTION_FLAG_NOPARAMS),
     487             :     FLAG_NAME(FUNCTION_FLAG_OPERATOR),
     488             :     FLAG_NAME(IDENTIFIER_FLAG_WITH),
     489             :     FLAG_NAME(IDENTIFIER_FLAG_TYPED),
     490             :     FLAG_NAME(IMPORT_FLAG_IMPLEMENTS),
     491             :     FLAG_NAME(PACKAGE_FLAG_FOUND_LABELS),
     492             :     FLAG_NAME(PACKAGE_FLAG_REFERENCED),
     493             :     FLAG_NAME(PARAM_FLAG_CONST),
     494             :     FLAG_NAME(PARAM_FLAG_IN),
     495             :     FLAG_NAME(PARAM_FLAG_OUT),
     496             :     FLAG_NAME(PARAM_FLAG_NAMED),
     497             :     FLAG_NAME(PARAM_FLAG_REST),
     498             :     FLAG_NAME(PARAM_FLAG_UNCHECKED),
     499             :     FLAG_NAME(PARAM_FLAG_UNPROTOTYPED),
     500             :     FLAG_NAME(PARAM_FLAG_REFERENCED),
     501             :     FLAG_NAME(PARAM_FLAG_PARAMREF),
     502             :     FLAG_NAME(PARAM_FLAG_CATCH),
     503             :     FLAG_NAME(PARAM_MATCH_FLAG_UNPROTOTYPED),
     504             :     FLAG_NAME(SWITCH_FLAG_DEFAULT),
     505             :     FLAG_NAME(TYPE_FLAG_MODULO),
     506             :     FLAG_NAME(VARIABLE_FLAG_CONST),
     507             :     FLAG_NAME(VARIABLE_FLAG_FINAL),
     508             :     FLAG_NAME(VARIABLE_FLAG_LOCAL),
     509             :     FLAG_NAME(VARIABLE_FLAG_MEMBER),
     510             :     FLAG_NAME(VARIABLE_FLAG_ATTRIBUTES),
     511             :     FLAG_NAME(VARIABLE_FLAG_ENUM),
     512             :     FLAG_NAME(VARIABLE_FLAG_COMPILED),
     513             :     FLAG_NAME(VARIABLE_FLAG_INUSE),
     514             :     FLAG_NAME(VARIABLE_FLAG_ATTRS),
     515             :     FLAG_NAME(VARIABLE_FLAG_DEFINED),
     516             :     FLAG_NAME(VARIABLE_FLAG_DEFINING),
     517             :     FLAG_NAME(VARIABLE_FLAG_TOADD)
     518             : };
     519             : constexpr std::size_t const g_flag_table_size = sizeof(g_flag_table) / sizeof(g_flag_table[0]);
     520             : 
     521             : 
     522     1249280 : as2js::flag_t str_to_flag_code(std::string const & flag_name)
     523             : {
     524    28192768 :     for(size_t idx(0); idx < g_flag_table_size; ++idx)
     525             :     {
     526    28192768 :         if(flag_name == g_flag_table[idx].f_name)
     527             :         {
     528     1249280 :             return g_flag_table[idx].f_flag;
     529             :         }
     530             :     }
     531             :     //CATCH_REQUIRE(!"flag code not found, catch_parser.cpp bug");
     532           0 :     CATCH_REQUIRE(flag_name == "unknown flag");
     533           0 :     return as2js::flag_t::NODE_FLAG_max;
     534             : }
     535             : 
     536             : 
     537           0 : std::string flag_to_str(as2js::flag_t const flg)
     538             : {
     539           0 :     for(size_t idx(0); idx < g_flag_table_size; ++idx)
     540             :     {
     541           0 :         if(flg == g_flag_table[idx].f_flag)
     542             :         {
     543           0 :             return g_flag_table[idx].f_name;
     544             :         }
     545             :     }
     546           0 :     CATCH_REQUIRE(!"flag code not found, catch_parser.cpp bug");
     547           0 :     return "";
     548             : }
     549             : 
     550             : 
     551             : 
     552             : 
     553    13258341 : void verify_flags(as2js::node::pointer_t node, std::string const & flags_set, bool verbose)
     554             : {
     555             :     // list of flags that have to be set
     556             :     //
     557    13258341 :     std::vector<as2js::flag_t> flgs;
     558    13258341 :     char const * f(flags_set.c_str());
     559    13258341 :     char const * s(f);
     560             :     for(;;)
     561             :     {
     562    36802149 :         if(*f == ',' || *f == '\0')
     563             :         {
     564    13631077 :             if(s == f)
     565             :             {
     566    12381797 :                 break;
     567             :             }
     568     2498560 :             std::string name(s, f - s);
     569             : //std::cerr << "Checking " << name << " -> " << static_cast<int>(str_to_flag_code(name)) << "\n";
     570     1249280 :             flgs.push_back(str_to_flag_code(name));
     571     1249280 :             if(*f == '\0')
     572             :             {
     573      876544 :                 break;
     574             :             }
     575             :             do // skip commas
     576             :             {
     577      372736 :                 ++f;
     578             :             }
     579      372736 :             while(*f == ',');
     580      372736 :             s = f;
     581     1622016 :         }
     582             :         else
     583             :         {
     584    23171072 :             ++f;
     585             :         }
     586    23543808 :     }
     587             : 
     588             :     // list of flags that must be checked
     589    13258341 :     std::vector<as2js::flag_t> flgs_to_check;
     590    13258341 :     switch(node->get_type())
     591             :     {
     592       36864 :     case as2js::node_t::NODE_CATCH:
     593       36864 :         flgs_to_check.push_back(as2js::flag_t::NODE_CATCH_FLAG_TYPED);
     594       36864 :         break;
     595             : 
     596     1450855 :     case as2js::node_t::NODE_DIRECTIVE_LIST:
     597     1450855 :         flgs_to_check.push_back(as2js::flag_t::NODE_DIRECTIVE_LIST_FLAG_NEW_VARIABLES);
     598     1450855 :         break;
     599             : 
     600       90112 :     case as2js::node_t::NODE_ENUM:
     601       90112 :         flgs_to_check.push_back(as2js::flag_t::NODE_ENUM_FLAG_CLASS);
     602       90112 :         break;
     603             : 
     604       53252 :     case as2js::node_t::NODE_FOR:
     605       53252 :         flgs_to_check.push_back(as2js::flag_t::NODE_FOR_FLAG_CONST);
     606       53252 :         flgs_to_check.push_back(as2js::flag_t::NODE_FOR_FLAG_FOREACH);
     607       53252 :         flgs_to_check.push_back(as2js::flag_t::NODE_FOR_FLAG_IN);
     608       53252 :         break;
     609             : 
     610      499712 :     case as2js::node_t::NODE_FUNCTION:
     611      499712 :         flgs_to_check.push_back(as2js::flag_t::NODE_FUNCTION_FLAG_GETTER);
     612      499712 :         flgs_to_check.push_back(as2js::flag_t::NODE_FUNCTION_FLAG_NEVER);
     613      499712 :         flgs_to_check.push_back(as2js::flag_t::NODE_FUNCTION_FLAG_NOPARAMS);
     614      499712 :         flgs_to_check.push_back(as2js::flag_t::NODE_FUNCTION_FLAG_OPERATOR);
     615      499712 :         flgs_to_check.push_back(as2js::flag_t::NODE_FUNCTION_FLAG_OUT);
     616      499712 :         flgs_to_check.push_back(as2js::flag_t::NODE_FUNCTION_FLAG_SETTER);
     617      499712 :         flgs_to_check.push_back(as2js::flag_t::NODE_FUNCTION_FLAG_VOID);
     618      499712 :         break;
     619             : 
     620     2724219 :     case as2js::node_t::NODE_IDENTIFIER:
     621             :     case as2js::node_t::NODE_VIDENTIFIER:
     622             :     case as2js::node_t::NODE_STRING:
     623     2724219 :         flgs_to_check.push_back(as2js::flag_t::NODE_IDENTIFIER_FLAG_WITH);
     624     2724219 :         flgs_to_check.push_back(as2js::flag_t::NODE_IDENTIFIER_FLAG_TYPED);
     625     2724219 :         break;
     626             : 
     627       81920 :     case as2js::node_t::NODE_IMPORT:
     628       81920 :         flgs_to_check.push_back(as2js::flag_t::NODE_IMPORT_FLAG_IMPLEMENTS);
     629       81920 :         break;
     630             : 
     631       65536 :     case as2js::node_t::NODE_PACKAGE:
     632       65536 :         flgs_to_check.push_back(as2js::flag_t::NODE_PACKAGE_FLAG_FOUND_LABELS);
     633       65536 :         flgs_to_check.push_back(as2js::flag_t::NODE_PACKAGE_FLAG_REFERENCED);
     634       65536 :         break;
     635             : 
     636           0 :     case as2js::node_t::NODE_PARAM_MATCH:
     637           0 :         flgs_to_check.push_back(as2js::flag_t::NODE_PARAM_MATCH_FLAG_UNPROTOTYPED);
     638           0 :         break;
     639             : 
     640      544768 :     case as2js::node_t::NODE_PARAM:
     641      544768 :         flgs_to_check.push_back(as2js::flag_t::NODE_PARAM_FLAG_CATCH);
     642      544768 :         flgs_to_check.push_back(as2js::flag_t::NODE_PARAM_FLAG_CONST);
     643      544768 :         flgs_to_check.push_back(as2js::flag_t::NODE_PARAM_FLAG_IN);
     644      544768 :         flgs_to_check.push_back(as2js::flag_t::NODE_PARAM_FLAG_OUT);
     645      544768 :         flgs_to_check.push_back(as2js::flag_t::NODE_PARAM_FLAG_NAMED);
     646      544768 :         flgs_to_check.push_back(as2js::flag_t::NODE_PARAM_FLAG_PARAMREF);
     647      544768 :         flgs_to_check.push_back(as2js::flag_t::NODE_PARAM_FLAG_REFERENCED);
     648      544768 :         flgs_to_check.push_back(as2js::flag_t::NODE_PARAM_FLAG_REST);
     649      544768 :         flgs_to_check.push_back(as2js::flag_t::NODE_PARAM_FLAG_UNCHECKED);
     650      544768 :         flgs_to_check.push_back(as2js::flag_t::NODE_PARAM_FLAG_UNPROTOTYPED);
     651      544768 :         break;
     652             : 
     653       40960 :     case as2js::node_t::NODE_SWITCH:
     654       40960 :         flgs_to_check.push_back(as2js::flag_t::NODE_SWITCH_FLAG_DEFAULT);
     655       40960 :         break;
     656             : 
     657      385024 :     case as2js::node_t::NODE_TYPE:
     658      385024 :         flgs_to_check.push_back(as2js::flag_t::NODE_TYPE_FLAG_MODULO);
     659      385024 :         break;
     660             : 
     661      405504 :     case as2js::node_t::NODE_VARIABLE:
     662             :     case as2js::node_t::NODE_VAR_ATTRIBUTES:
     663      405504 :         flgs_to_check.push_back(as2js::flag_t::NODE_VARIABLE_FLAG_CONST);
     664      405504 :         flgs_to_check.push_back(as2js::flag_t::NODE_VARIABLE_FLAG_FINAL);
     665      405504 :         flgs_to_check.push_back(as2js::flag_t::NODE_VARIABLE_FLAG_LOCAL);
     666      405504 :         flgs_to_check.push_back(as2js::flag_t::NODE_VARIABLE_FLAG_MEMBER);
     667      405504 :         flgs_to_check.push_back(as2js::flag_t::NODE_VARIABLE_FLAG_ATTRIBUTES);
     668      405504 :         flgs_to_check.push_back(as2js::flag_t::NODE_VARIABLE_FLAG_ENUM);
     669      405504 :         flgs_to_check.push_back(as2js::flag_t::NODE_VARIABLE_FLAG_COMPILED);
     670      405504 :         flgs_to_check.push_back(as2js::flag_t::NODE_VARIABLE_FLAG_INUSE);
     671      405504 :         flgs_to_check.push_back(as2js::flag_t::NODE_VARIABLE_FLAG_ATTRS);
     672      405504 :         flgs_to_check.push_back(as2js::flag_t::NODE_VARIABLE_FLAG_DEFINED);
     673      405504 :         flgs_to_check.push_back(as2js::flag_t::NODE_VARIABLE_FLAG_DEFINING);
     674      405504 :         flgs_to_check.push_back(as2js::flag_t::NODE_VARIABLE_FLAG_TOADD);
     675      405504 :         break;
     676             : 
     677     6879615 :     default:
     678             :         // no flags supported
     679     6879615 :         break;
     680             : 
     681             :     }
     682             : 
     683    13258341 :     CATCH_REQUIRE(flgs.size() <= flgs_to_check.size());
     684             : 
     685    34895054 :     for(size_t idx(0); idx < flgs_to_check.size(); ++idx)
     686             :     {
     687    21636713 :         as2js::flag_t flg(flgs_to_check[idx]);
     688    21636713 :         std::vector<as2js::flag_t>::iterator it(std::find(flgs.begin(), flgs.end(), flg));
     689    21636713 :         if(it == flgs.end())
     690             :         {
     691             :             // expected to be unset
     692    20387433 :             if(verbose && node->get_flag(flg))
     693             :             {
     694             :                 std::cerr
     695             :                     << "\n*** Comparing flags "
     696           0 :                     << flag_to_str(flg)
     697           0 :                     << " (should not be set):\n"
     698           0 :                     << *node
     699           0 :                     << "\n";
     700             :             }
     701    20387433 :             CATCH_REQUIRE(!node->get_flag(flg));
     702             :         }
     703             :         else
     704             :         {
     705             :             // expected to be set
     706     1249280 :             flgs.erase(it);
     707     1249280 :             if(verbose && !node->get_flag(flg))
     708             :             {
     709             :                 std::cerr
     710             :                     << "\n*** Comparing flags "
     711           0 :                     << flag_to_str(flg)
     712           0 :                     << " (it should be set in this case):\n"
     713           0 :                     << *node
     714           0 :                     << "\n";
     715             :             }
     716     1249280 :             CATCH_REQUIRE(node->get_flag(flg));
     717             :         }
     718             :     }
     719             : 
     720    13258341 :     CATCH_REQUIRE(flgs.empty());
     721    26516682 : }
     722             : 
     723             : 
     724             : 
     725             : 
     726             : 
     727             : 
     728             : // Attributes
     729             : 
     730             : struct attr_to_string_t
     731             : {
     732             :     as2js::attribute_t      f_attribute;
     733             :     char const *            f_name;
     734             :     int                     f_line;
     735             : };
     736             : 
     737             : #define    ATTRIBUTE_NAME(attr)      { as2js::attribute_t::NODE_ATTR_##attr, TO_STR_sub(attr), __LINE__ }
     738             : 
     739             : constexpr attr_to_string_t const g_attribute_table[] =
     740             : {
     741             :     ATTRIBUTE_NAME(PUBLIC),
     742             :     ATTRIBUTE_NAME(PRIVATE),
     743             :     ATTRIBUTE_NAME(PROTECTED),
     744             :     ATTRIBUTE_NAME(INTERNAL),
     745             :     ATTRIBUTE_NAME(TRANSIENT),
     746             :     ATTRIBUTE_NAME(VOLATILE),
     747             :     ATTRIBUTE_NAME(STATIC),
     748             :     ATTRIBUTE_NAME(ABSTRACT),
     749             :     ATTRIBUTE_NAME(VIRTUAL),
     750             :     ATTRIBUTE_NAME(ARRAY),
     751             :     ATTRIBUTE_NAME(REQUIRE_ELSE),
     752             :     ATTRIBUTE_NAME(ENSURE_THEN),
     753             :     ATTRIBUTE_NAME(NATIVE),
     754             :     ATTRIBUTE_NAME(DEPRECATED),
     755             :     ATTRIBUTE_NAME(UNSAFE),
     756             :     ATTRIBUTE_NAME(CONSTRUCTOR),
     757             :     ATTRIBUTE_NAME(FINAL),
     758             :     ATTRIBUTE_NAME(ENUMERABLE),
     759             :     ATTRIBUTE_NAME(TRUE),
     760             :     ATTRIBUTE_NAME(FALSE),
     761             :     ATTRIBUTE_NAME(UNUSED),
     762             :     ATTRIBUTE_NAME(DYNAMIC),
     763             :     ATTRIBUTE_NAME(FOREACH),
     764             :     ATTRIBUTE_NAME(NOBREAK),
     765             :     ATTRIBUTE_NAME(AUTOBREAK),
     766             :     ATTRIBUTE_NAME(DEFINED)
     767             : };
     768             : constexpr std::size_t const g_attribute_table_size = sizeof(g_attribute_table) / sizeof(g_attribute_table[0]);
     769             : 
     770             : 
     771      364544 : as2js::attribute_t str_to_attribute_code(std::string const & attr_name)
     772             : {
     773     8085504 :     for(std::size_t idx(0); idx < g_attribute_table_size; ++idx)
     774             :     {
     775     8085504 :         if(attr_name == g_attribute_table[idx].f_name)
     776             :         {
     777      364544 :             return g_attribute_table[idx].f_attribute;
     778             :         }
     779             :     }
     780           0 :     CATCH_REQUIRE(!"attribute code not found, catch_parser.cpp bug");
     781           0 :     return as2js::attribute_t::NODE_ATTR_max;
     782             : }
     783             : 
     784             : 
     785           0 : std::string attribute_to_str(as2js::attribute_t const attr)
     786             : {
     787           0 :     for(std::size_t idx(0); idx < g_attribute_table_size; ++idx)
     788             :     {
     789           0 :         if(attr == g_attribute_table[idx].f_attribute)
     790             :         {
     791           0 :             return g_attribute_table[idx].f_name;
     792             :         }
     793             :     }
     794           0 :     CATCH_REQUIRE(!"attribute code not found, catch_parser.cpp bug");
     795           0 :     return std::string();
     796             : }
     797             : 
     798             : 
     799             : 
     800             : 
     801    13258341 : void verify_attributes(as2js::node::pointer_t n, std::string const & attributes_set, bool verbose)
     802             : {
     803             :     // list of attributes that have to be set
     804             :     //
     805    13258341 :     std::vector<as2js::attribute_t> attrs;
     806    13258341 :     char const * a(attributes_set.c_str());
     807    13258341 :     char const * s(a);
     808             :     for(;;)
     809             :     {
     810    15879781 :         if(*a == ',' || *a == '\0')
     811             :         {
     812    13368933 :             if(s == a)
     813             :             {
     814    13004389 :                 break;
     815             :             }
     816      729088 :             std::string const name(s, a - s);
     817      364544 :             attrs.push_back(str_to_attribute_code(name));
     818      364544 :             if(*a == '\0')
     819             :             {
     820      253952 :                 break;
     821             :             }
     822             :             do // skip commas
     823             :             {
     824      110592 :                 ++a;
     825             :             }
     826      110592 :             while(*a == ',');
     827      110592 :             s = a;
     828      475136 :         }
     829             :         else
     830             :         {
     831     2510848 :             ++a;
     832             :         }
     833     2621440 :     }
     834             : 
     835             :     // list of attributes that must be checked
     836    13258341 :     std::vector<as2js::attribute_t> attrs_to_check;
     837             : 
     838    13258341 :     if(n->get_type() != as2js::node_t::NODE_PROGRAM)
     839             :     {
     840             :         // except for PROGRAM, all attributes always apply
     841    12499735 :         attrs_to_check.push_back(as2js::attribute_t::NODE_ATTR_PUBLIC);
     842    12499735 :         attrs_to_check.push_back(as2js::attribute_t::NODE_ATTR_PRIVATE);
     843    12499735 :         attrs_to_check.push_back(as2js::attribute_t::NODE_ATTR_PROTECTED);
     844    12499735 :         attrs_to_check.push_back(as2js::attribute_t::NODE_ATTR_INTERNAL);
     845    12499735 :         attrs_to_check.push_back(as2js::attribute_t::NODE_ATTR_TRANSIENT);
     846    12499735 :         attrs_to_check.push_back(as2js::attribute_t::NODE_ATTR_VOLATILE);
     847    12499735 :         attrs_to_check.push_back(as2js::attribute_t::NODE_ATTR_STATIC);
     848    12499735 :         attrs_to_check.push_back(as2js::attribute_t::NODE_ATTR_ABSTRACT);
     849    12499735 :         attrs_to_check.push_back(as2js::attribute_t::NODE_ATTR_VIRTUAL);
     850    12499735 :         attrs_to_check.push_back(as2js::attribute_t::NODE_ATTR_ARRAY);
     851    12499735 :         attrs_to_check.push_back(as2js::attribute_t::NODE_ATTR_REQUIRE_ELSE);
     852    12499735 :         attrs_to_check.push_back(as2js::attribute_t::NODE_ATTR_ENSURE_THEN);
     853    12499735 :         attrs_to_check.push_back(as2js::attribute_t::NODE_ATTR_NATIVE);
     854    12499735 :         attrs_to_check.push_back(as2js::attribute_t::NODE_ATTR_DEPRECATED);
     855    12499735 :         attrs_to_check.push_back(as2js::attribute_t::NODE_ATTR_UNSAFE);
     856    12499735 :         attrs_to_check.push_back(as2js::attribute_t::NODE_ATTR_CONSTRUCTOR);
     857    12499735 :         attrs_to_check.push_back(as2js::attribute_t::NODE_ATTR_FINAL);
     858    12499735 :         attrs_to_check.push_back(as2js::attribute_t::NODE_ATTR_ENUMERABLE);
     859    12499735 :         attrs_to_check.push_back(as2js::attribute_t::NODE_ATTR_TRUE);
     860    12499735 :         attrs_to_check.push_back(as2js::attribute_t::NODE_ATTR_FALSE);
     861    12499735 :         attrs_to_check.push_back(as2js::attribute_t::NODE_ATTR_UNUSED);
     862    12499735 :         attrs_to_check.push_back(as2js::attribute_t::NODE_ATTR_DYNAMIC);
     863    12499735 :         attrs_to_check.push_back(as2js::attribute_t::NODE_ATTR_FOREACH);
     864    12499735 :         attrs_to_check.push_back(as2js::attribute_t::NODE_ATTR_NOBREAK);
     865    12499735 :         attrs_to_check.push_back(as2js::attribute_t::NODE_ATTR_AUTOBREAK);
     866    12499735 :         attrs_to_check.push_back(as2js::attribute_t::NODE_ATTR_DEFINED);
     867             :     }
     868             : 
     869    13258341 :     CATCH_REQUIRE(attrs.size() <= attrs_to_check.size());
     870             : 
     871   338251451 :     for(size_t idx(0); idx < attrs_to_check.size(); ++idx)
     872             :     {
     873   324993110 :         as2js::attribute_t attr(attrs_to_check[idx]);
     874   324993110 :         std::vector<as2js::attribute_t>::iterator it(std::find(attrs.begin(), attrs.end(), attr));
     875   324993110 :         if(it == attrs.end())
     876             :         {
     877             :             // expected to be unset
     878             :             //
     879   324628566 :             if(verbose && n->get_attribute(attr))
     880             :             {
     881             :                 std::cerr
     882             :                     << "*** Comparing attributes "
     883           0 :                     << attribute_to_str(attr)
     884           0 :                     << " (should not be set)\n"
     885           0 :                     << *n
     886           0 :                     << '\n';
     887             :             }
     888   324628566 :             CATCH_REQUIRE(!n->get_attribute(attr));
     889             :         }
     890             :         else
     891             :         {
     892             :             // expected to be set
     893             :             //
     894      364544 :             attrs.erase(it);
     895      364544 :             if(verbose && !n->get_attribute(attr))
     896             :             {
     897             :                 std::cerr
     898             :                     << "*** Comparing attributes "
     899           0 :                     << attribute_to_str(attr)
     900           0 :                     << " (it should be set in this case)\n"
     901           0 :                     << *n
     902           0 :                     << '\n';
     903             :             }
     904      364544 :             CATCH_REQUIRE(n->get_attribute(attr));
     905             :         }
     906             :     }
     907             : 
     908    13258341 :     CATCH_REQUIRE(attrs.empty());
     909    26516682 : }
     910             : 
     911             : 
     912             : 
     913    65861625 : void verify_child_node(
     914             :       std::string const & result_name
     915             :     , as2js::json::json_value::pointer_t expected
     916             :     , as2js::json::json_value::object_t const & json_object
     917             :     , as2js::node::pointer_t node
     918             :     , as2js::node::pointer_t link_node
     919             :     , char const * link_name
     920             :     , bool direct
     921             :     , bool verbose)
     922             : {
     923    65861625 :     as2js::json::json_value::object_t::const_iterator it_link(json_object.find(link_name));
     924    65861625 :     if(it_link != json_object.end())
     925             :     {
     926             :         // the children value must be an array
     927             :         //
     928      565248 :         as2js::json::json_value::array_t const & array(it_link->second->get_array());
     929      565248 :         std::size_t const max_links(array.size());
     930      565248 :         if(link_node != nullptr)
     931             :         {
     932      565248 :             if(direct)
     933             :             {
     934       86016 :                 if(verbose && max_links != 1)
     935             :                 {
     936             :                     std::cerr
     937           0 :                         << "   Expecting "
     938           0 :                         << max_links
     939             :                         << " "
     940             :                         << link_name
     941           0 :                         << ", we always have 1 in the node (direct)\n";
     942             :                 }
     943       86016 :                 CATCH_REQUIRE(max_links == 1);
     944       86016 :                 as2js::json::json_value::pointer_t link_value(array[0]);
     945       86016 :                 verify_result(result_name, link_value, link_node, verbose, true); // recursive
     946       86016 :             }
     947             :             else
     948             :             {
     949      479232 :                 if(verbose && max_links != link_node->get_children_size())
     950             :                 {
     951             :                     std::cerr
     952           0 :                         << "   Expecting "
     953           0 :                         << max_links
     954             :                         << " "
     955             :                         << link_name
     956           0 :                         << ", we have "
     957           0 :                         << link_node->get_children_size()
     958           0 :                         << " in the node\n";
     959             :                 }
     960      479232 :                 CATCH_REQUIRE(max_links == link_node->get_children_size());
     961     1056768 :                 for(std::size_t idx(0); idx < max_links; ++idx)
     962             :                 {
     963      577536 :                     as2js::json::json_value::pointer_t link_value(array[idx]);
     964      577536 :                     verify_result(result_name, link_value, link_node->get_child(idx), verbose, false); // recursive
     965      577536 :                 }
     966             :             }
     967             :         }
     968             :         else
     969             :         {
     970           0 :             if(verbose && max_links != 0)
     971             :             {
     972             :                 std::cerr
     973             :                     << "   "
     974             :                     << result_name
     975           0 :                     << ": Expecting "
     976           0 :                     << max_links
     977             :                     << ' '
     978             :                     << link_name
     979             :                     << ", we have no "
     980             :                     << link_name
     981           0 :                     << " at all in the node\n";
     982             :             }
     983           0 :             CATCH_REQUIRE(max_links == 0);
     984             :         }
     985             :     }
     986             :     else
     987             :     {
     988             :         // no children defined in the JSON, no children expected in the node
     989             :         //
     990    65296377 :         if(verbose
     991     2199552 :         && link_node != nullptr
     992    67495929 :         && link_node->get_children_size() != 0)
     993             :         {
     994             :             std::cerr
     995             :                 << "   Expecting no \""
     996             :                 << link_name
     997           0 :                 << "\" list, we have "
     998           0 :                 << link_node->get_children_size()
     999             :                 << " "
    1000             :                 << link_name
    1001           0 :                 << " in the node:\n"
    1002           0 :                 << *node
    1003           0 :                 << "JSON position: "
    1004           0 :                 << expected->get_position()
    1005           0 :                 << "\nComparing against link node:\n"
    1006           0 :                 << *link_node;
    1007             :         }
    1008    65296377 :         bool const valid_link(link_node == nullptr || link_node->get_children_size() == 0);
    1009    65296377 :         CATCH_REQUIRE(valid_link);
    1010             :     }
    1011    65861625 : }
    1012             : 
    1013             : 
    1014    13258341 : void verify_result(
    1015             :       std::string const & result_name
    1016             :     , as2js::json::json_value::pointer_t expected
    1017             :     , as2js::node::pointer_t node
    1018             :     , bool verbose
    1019             :     , bool ignore_children)
    1020             : {
    1021    26516682 :     std::string const node_type_string("node type");
    1022    26516682 :     std::string const children_string("children");
    1023             :     //std::string link_strings[static_cast<int>(as2js::link_t::LINK_max)];
    1024             :     //link_strings[0].from_utf8("link instance");
    1025             :     //link_strings[1].from_utf8("link type");
    1026             :     //link_strings[2].from_utf8("link attributes");
    1027             :     //link_strings[3].from_utf8("link goto exit");
    1028             :     //link_strings[4].from_utf8("link goto enter");
    1029    26516682 :     std::string const label_string("label");
    1030    26516682 :     std::string const flags_string("flags");;
    1031    26516682 :     std::string const attributes_string("attributes");
    1032    26516682 :     std::string const integer_string("integer");
    1033    26516682 :     std::string const float_string("float");
    1034             : 
    1035    13258341 :     CATCH_REQUIRE(expected->get_type() == as2js::json::json_value::type_t::JSON_TYPE_OBJECT);
    1036    13258341 :     as2js::json::json_value::object_t const & child_object(expected->get_object());
    1037             : 
    1038    13258341 :     as2js::json::json_value::object_t::const_iterator it_node_type(child_object.find(node_type_string));
    1039    13258341 :     if(it_node_type == child_object.end())
    1040             :     {
    1041             :         std::cerr
    1042           0 :             << "\nerror: \"node type\" is mandatory in your JSON:\n"
    1043           0 :             << *expected
    1044           0 :             << "\n";
    1045           0 :         exit(1);
    1046             :     }
    1047    13258341 :     as2js::json::json_value::pointer_t node_type_value(it_node_type->second);
    1048    13258341 :     if(verbose && node->get_type_name() != node_type_value->get_string())
    1049             :     {
    1050             :         std::cerr
    1051             :             << "*** Comparing "
    1052             :             << node->get_type_name()
    1053             :             << " (node) vs "
    1054           0 :             << node_type_value->get_string()
    1055           0 :             << " (JSON) -- pos: "
    1056           0 :             << expected->get_position()
    1057           0 :             << " -- Node:\n"
    1058           0 :             << *node
    1059           0 :             << "JSON:\n"
    1060           0 :             << *node_type_value;
    1061           0 :         switch(node->get_type())
    1062             :         {
    1063           0 :         case as2js::node_t::NODE_IDENTIFIER:
    1064           0 :             std::cerr << " \"" << node->get_string() << "\"";
    1065           0 :             break;
    1066             : 
    1067           0 :         default:
    1068             :             // no details for this node type
    1069           0 :             break;
    1070             : 
    1071             :         }
    1072           0 :         std::cerr << "\n";
    1073             :     }
    1074    13258341 :     CATCH_REQUIRE(node->get_type_name() == node_type_value->get_string());
    1075             : 
    1076    13258341 :     as2js::json::json_value::object_t::const_iterator it_label(child_object.find(label_string));
    1077    13258341 :     if(it_label != child_object.end())
    1078             :     {
    1079             :         // we expect a string in this object
    1080     5075325 :         if(verbose && node->get_string() != it_label->second->get_string())
    1081             :         {
    1082           0 :             std::cerr << "   Expecting string \"" << it_label->second->get_string() << "\", node has \"" << node->get_string() << "\"\n";
    1083             :         }
    1084     5075325 :         CATCH_REQUIRE(node->get_string() == it_label->second->get_string());
    1085             : //std::cerr << "  -- labels are a match! [" << node->get_string() << "]\n";
    1086             :     }
    1087             :     else
    1088             :     {
    1089             :         // the node cannot have a string otherwise, so we expect a throw
    1090     8183016 :         CATCH_REQUIRE_THROWS_MATCHES(
    1091             :               node->get_string()
    1092             :             , as2js::internal_error
    1093             :             , Catch::Matchers::ExceptionMessage(
    1094             :                       "internal_error: get_string() called with non-string node type: \""
    1095             :                     + std::string(node->get_type_name())
    1096             :                     + "\"."));
    1097             :     }
    1098             : 
    1099    13258341 :     as2js::json::json_value::object_t::const_iterator it_flags(child_object.find(flags_string));
    1100    13258341 :     if(it_flags != child_object.end())
    1101             :     {
    1102             :         // the tester declared as set of flags that are expected to be set
    1103             :         //
    1104      876544 :         verify_flags(node, it_flags->second->get_string(), verbose);
    1105             :     }
    1106             :     else
    1107             :     {
    1108             :         // all flags must be unset
    1109             :         //
    1110    12381797 :         verify_flags(node, "", verbose);
    1111             :     }
    1112             : 
    1113             :     // WARNING: these attributes are what we call IMMEDIATE ATTRIBUTES in case
    1114             :     //          of the parser because the parser also makes use of a
    1115             :     //          LINK_ATTRIBUTES which represents a list of attributes
    1116    13258341 :     as2js::json::json_value::object_t::const_iterator it_attributes(child_object.find(attributes_string));
    1117    13258341 :     if(it_attributes != child_object.end())
    1118             :     {
    1119             :         // the tester declared as set of attributes that are expected to be set
    1120      253952 :         verify_attributes(node, it_attributes->second->get_string(), verbose);
    1121             :     }
    1122             :     else
    1123             :     {
    1124             :         // all attributes must be unset
    1125    13004389 :         verify_attributes(node, "", verbose);
    1126             :     }
    1127             : 
    1128    13258341 :     as2js::json::json_value::object_t::const_iterator it_integer(child_object.find(integer_string));
    1129    13258341 :     if(it_integer != child_object.end())
    1130             :     {
    1131             :         // we expect an integer in this object
    1132      782619 :         if(node->get_integer().get() != it_integer->second->get_integer().get())
    1133             :         {
    1134           0 :             std::cerr << "   Expecting " << it_integer->second->get_integer().get() << ", got " << node->get_integer().get() << " in the node\n";
    1135             :         }
    1136      782619 :         CATCH_REQUIRE(node->get_integer().get() == it_integer->second->get_integer().get());
    1137             :     }
    1138             :     else
    1139             :     {
    1140             :         // the node cannot have an integer otherwise, so we expect a throw
    1141             :         //
    1142    12475722 :         CATCH_REQUIRE_THROWS_MATCHES(
    1143             :               node->get_integer()
    1144             :             , as2js::internal_error
    1145             :             , Catch::Matchers::ExceptionMessage(
    1146             :                       "internal_error: get_integer() called with a non-integer node type."));
    1147             :     }
    1148             : 
    1149    13258341 :     as2js::json::json_value::object_t::const_iterator it_float(child_object.find(float_string));
    1150    13258341 :     if(it_float != child_object.end())
    1151             :     {
    1152             :         // if we expect a NaN we have to compare specifically
    1153             :         // because (NaN == NaN) always returns false
    1154             :         //
    1155       65927 :         if(it_float->second->get_floating_point().is_nan())
    1156             :         {
    1157          74 :             CATCH_REQUIRE(node->get_floating_point().is_nan());
    1158             :         }
    1159       65853 :         else if(it_float->second->get_floating_point().is_positive_infinity())
    1160             :         {
    1161          89 :             CATCH_REQUIRE(node->get_floating_point().is_positive_infinity());
    1162             :         }
    1163       65764 :         else if(it_float->second->get_floating_point().is_negative_infinity())
    1164             :         {
    1165           1 :             CATCH_REQUIRE(node->get_floating_point().is_negative_infinity());
    1166             :         }
    1167             :         else
    1168             :         {
    1169             :             // we expect a floating point number in this object
    1170       65763 :             if(node->get_floating_point().get() - it_float->second->get_floating_point().get() > 0.0001)
    1171             :             {
    1172           0 :                 std::cerr << "   Expecting " << it_float->second->get_floating_point().get() << ", got " << node->get_floating_point().get() << " in the node\n";
    1173             :             }
    1174       65763 :             CATCH_REQUIRE(node->get_floating_point().get() - it_float->second->get_floating_point().get() <= 0.0001);
    1175             : 
    1176             :             // further, if the float is zero, it may be +0.0 or -0.0
    1177             : #pragma GCC diagnostic push
    1178             : #pragma GCC diagnostic ignored "-Wfloat-equal"
    1179       65763 :             if(it_float->second->get_floating_point().get() == 0.0)
    1180             :             {
    1181          11 :                 CATCH_REQUIRE(std::signbit(node->get_floating_point().get()) == std::signbit(it_float->second->get_floating_point().get()));
    1182             :             }
    1183             : #pragma GCC diagnostic pop
    1184             :         }
    1185             :     }
    1186             :     else
    1187             :     {
    1188             :         // the node cannot have a floating point otherwise, so we expect a throw
    1189    13192414 :         CATCH_REQUIRE_THROWS_MATCHES(
    1190             :               node->get_floating_point()
    1191             :             , as2js::internal_error
    1192             :             , Catch::Matchers::ExceptionMessage(
    1193             :                       "internal_error: get_floating_point() called with a non-floating point node type."));
    1194             :     }
    1195             : 
    1196             : // COMPILER / OPTIMIZER SPECIFIC?
    1197             :     // certain links asks us to ignore the links and children because
    1198             :     // we do not want to duplicate the whole type classes a hundred times...
    1199    13258341 :     if(!ignore_children)
    1200             :     {
    1201             : //std::cerr << "Node is [" << *node << "]\n";
    1202             : 
    1203             :         // verify the links
    1204    13172325 :         verify_child_node(result_name, expected, child_object, node, node->get_instance(),        "instance",       true,  verbose);
    1205    13172325 :         verify_child_node(result_name, expected, child_object, node, node->get_type_node(),       "type node",      true,  verbose);
    1206    13172325 :         verify_child_node(result_name, expected, child_object, node, node->get_attribute_node(),  "attribute node", false, verbose);
    1207    13172325 :         verify_child_node(result_name, expected, child_object, node, node->get_goto_exit(),       "goto exit",      false, verbose);
    1208    13172325 :         verify_child_node(result_name, expected, child_object, node, node->get_goto_enter(),      "goto enter",     false, verbose);
    1209             : 
    1210             : //        // List of links are tested just like children, only the list starts somewhere else
    1211             : //        for(int link_idx(0); link_idx < static_cast<int>(as2js::Node::link_t::LINK_max); ++link_idx)
    1212             : //        {
    1213             : //            as2js::String link_name;
    1214             : //            switch(static_cast<as2js::Node::link_t>(link_idx))
    1215             : //            {
    1216             : //            case as2js::Node::link_t::LINK_INSTANCE:
    1217             : //                link_name = "instance";
    1218             : //                break;
    1219             : //
    1220             : //            case as2js::Node::link_t::LINK_TYPE:
    1221             : //                link_name = "type";
    1222             : //                break;
    1223             : //
    1224             : //            case as2js::Node::link_t::LINK_ATTRIBUTES:
    1225             : //                link_name = "attributes";
    1226             : //                break;
    1227             : //
    1228             : //            case as2js::Node::link_t::LINK_GOTO_EXIT:
    1229             : //                link_name = "goto-exit";
    1230             : //                break;
    1231             : //
    1232             : //            case as2js::Node::link_t::LINK_GOTO_ENTER:
    1233             : //                link_name = "goto-enter";
    1234             : //                break;
    1235             : //
    1236             : //            case as2js::Node::link_t::LINK_max:
    1237             : //                CATCH_REQUIRE(!"LINK_max reached when getting the link type");
    1238             : //                break;
    1239             : //
    1240             : //            }
    1241             : //            bool direct(false);
    1242             : //            as2js::Node::pointer_t link_node(node->get_link(static_cast<as2js::Node::link_t>(link_idx)));
    1243             : //            if(link_node)
    1244             : //            {
    1245             : //                // make sure root node is of the right type
    1246             : //                // Why did I write this that way? The types from the time
    1247             : //                // we created the tree in the parser are still around...
    1248             : //                switch(static_cast<as2js::Node::link_t>(link_idx))
    1249             : //                {
    1250             : //                case as2js::Node::link_t::LINK_INSTANCE:
    1251             : //                    direct = true;
    1252             : ////std::cerr << "Instance [" << *link_node << "]\n";
    1253             : //                    //CATCH_REQUIRE(!"compiler does not use LINK_INSTANCE");
    1254             : //                    break;
    1255             : //
    1256             : //                case as2js::Node::link_t::LINK_TYPE:
    1257             : //                    direct = true;
    1258             : ////std::cerr << "Type [" << *link_node << "]\n";
    1259             : //                    //CATCH_REQUIRE(!"compiler does not use LINK_TYPE");
    1260             : //                    break;
    1261             : //
    1262             : //                case as2js::Node::link_t::LINK_ATTRIBUTES:
    1263             : //                    direct = false;
    1264             : //                    CATCH_REQUIRE(link_node->get_type() == as2js::Node::node_t::NODE_ATTRIBUTES);
    1265             : //                    break;
    1266             : //
    1267             : //                case as2js::Node::link_t::LINK_GOTO_EXIT:
    1268             : //                    CATCH_REQUIRE(!"compiler does not use LINK_GOTO_EXIT");
    1269             : //                    break;
    1270             : //
    1271             : //                case as2js::Node::link_t::LINK_GOTO_ENTER:
    1272             : //                    CATCH_REQUIRE(!"compiler does not use LINK_GOTO_ENTER");
    1273             : //                    break;
    1274             : //
    1275             : //                case as2js::Node::link_t::LINK_max:
    1276             : //                    CATCH_REQUIRE(!"LINK_max reached when testing the link_node type");
    1277             : //                    break;
    1278             : //
    1279             : //                }
    1280             : //            }
    1281             : //            as2js::JSON::JSONValue::object_t::const_iterator it_link(child_object.find(link_strings[link_idx]));
    1282             : //            if(it_link != child_object.end())
    1283             : //            {
    1284             : //                // the children value must be an array
    1285             : //                as2js::JSON::JSONValue::array_t const& array(it_link->second->get_array());
    1286             : //                size_t const max_links(array.size());
    1287             : //                if(link_node)
    1288             : //                {
    1289             : //                    if(direct)
    1290             : //                    {
    1291             : //                        if(verbose && max_links != 1)
    1292             : //                        {
    1293             : //                            std::cerr << "   Expecting " << max_links << " " << link_name << ", we always have 1 in the node (direct)\n";
    1294             : //                        }
    1295             : //                        CATCH_REQUIRE(max_links == 1);
    1296             : //                        as2js::JSON::JSONValue::pointer_t link_value(array[0]);
    1297             : //                        verify_result(result_name, link_value, link_node, verbose, true); // recursive
    1298             : //                    }
    1299             : //                    else
    1300             : //                    {
    1301             : //                        if(verbose && max_links != link_node->get_children_size())
    1302             : //                        {
    1303             : //                            std::cerr << "   Expecting " << max_links << " " << link_name << ", we have " << link_node->get_children_size() << " in the node\n";
    1304             : //                        }
    1305             : //                        CATCH_REQUIRE(max_links == link_node->get_children_size());
    1306             : //                        for(size_t idx(0); idx < max_links; ++idx)
    1307             : //                        {
    1308             : //                            as2js::JSON::JSONValue::pointer_t link_value(array[idx]);
    1309             : //                            verify_result(result_name, link_value, link_node->get_child(idx), verbose, false); // recursive
    1310             : //                        }
    1311             : //                    }
    1312             : //                }
    1313             : //                else
    1314             : //                {
    1315             : //                    if(verbose && max_links != 0)
    1316             : //                    {
    1317             : //                        std::cerr << "   Expecting " << max_links << " " << link_name << ", we have no " << link_name << " at all in the node\n";
    1318             : //                    }
    1319             : //                    CATCH_REQUIRE(max_links == 0);
    1320             : //                }
    1321             : //            }
    1322             : //            else
    1323             : //            {
    1324             : //                // no children defined in the JSON, no children expected in the node
    1325             : //                if(verbose && link_node && link_node->get_children_size() != 0)
    1326             : //                {
    1327             : //                    std::cerr << "   Expecting no " << link_name << " list, we have " << link_node->get_children_size() << " " << link_name << " in the node\n";
    1328             : //                }
    1329             : //                CATCH_REQUIRE(!link_node || link_node->get_children_size() == 0);
    1330             : //            }
    1331             : //        }
    1332             : 
    1333    13172325 :         as2js::json::json_value::object_t::const_iterator it_children(child_object.find(children_string));
    1334    13172325 :         if(it_children != child_object.end())
    1335             :         {
    1336             :             // the children value must be an array
    1337     7805230 :             as2js::json::json_value::array_t const& array(it_children->second->get_array());
    1338     7805230 :             size_t const max_children(array.size());
    1339     7805230 :             if(verbose && max_children != node->get_children_size())
    1340             :             {
    1341             :                 std::cerr
    1342           0 :                     << "   Expecting "
    1343           0 :                     << max_children
    1344           0 :                     << " children, we have "
    1345           0 :                     << node->get_children_size()
    1346           0 :                     << " in the node:\n"
    1347           0 :                     << *node;
    1348             :             }
    1349     7805230 :             CATCH_REQUIRE(max_children == node->get_children_size());
    1350    19641413 :             for(size_t idx(0); idx < max_children; ++idx)
    1351             :             {
    1352    11836183 :                 as2js::json::json_value::pointer_t children_value(array[idx]);
    1353    11836183 :                 verify_result(result_name, children_value, node->get_child(idx), verbose, ignore_children); // recursive
    1354    11836183 :             }
    1355             :         }
    1356             :         else
    1357             :         {
    1358             :             // no children defined in the JSON, no children expected in the node
    1359     5367095 :             if(verbose && node->get_children_size() != 0)
    1360             :             {
    1361             :                 std::cerr
    1362           0 :                     << "   Expecting no children, we have "
    1363           0 :                     << node->get_children_size()
    1364           0 :                     << " in the node:\n"
    1365           0 :                     << *node
    1366           0 :                     << "\n";
    1367             :             }
    1368     5367095 :             CATCH_REQUIRE(node->get_children_size() == 0);
    1369             :         }
    1370             :     }
    1371    26516682 : }
    1372             : 
    1373             : 
    1374             : // Parser verification
    1375      684032 : void verify_parser_result(
    1376             :       std::string const & result_name
    1377             :     , as2js::json::json_value::pointer_t expected
    1378             :     , as2js::node::pointer_t node
    1379             :     , bool verbose
    1380             :     , bool ignore_children)
    1381             : {
    1382      684032 :     verify_result(result_name, expected, node, verbose, ignore_children);
    1383             : 
    1384             :     // the parser does not define these so we expect them all to be null pointers
    1385      684032 :     CATCH_REQUIRE(node->get_instance() == nullptr);
    1386      684032 :     CATCH_REQUIRE(node->get_type_node() == nullptr);
    1387      684032 :     CATCH_REQUIRE(node->get_goto_exit() == nullptr);
    1388      684032 :     CATCH_REQUIRE(node->get_goto_enter() == nullptr);
    1389             : 
    1390      684032 :     as2js::json::json_value::object_t const & child_object(expected->get_object());
    1391      684032 :     as2js::json::json_value::object_t::const_iterator it_attribute(child_object.find("attribute node"));
    1392      684032 :     as2js::node::pointer_t attribute_node(node->get_attribute_node());
    1393      684032 :     if(attribute_node != nullptr)
    1394             :     {
    1395             :         // if it exists it must be a NODE_ATTRIBUTES type
    1396           0 :         CATCH_REQUIRE(attribute_node->get_type() == as2js::node_t::NODE_ATTRIBUTES);
    1397             : 
    1398           0 :         if(it_attribute == child_object.end())
    1399             :         {
    1400           0 :             std::size_t const count(attribute_node->get_children_size());
    1401           0 :             if(verbose && count > 0)
    1402             :             {
    1403             :                 std::cerr
    1404           0 :                     << "   Expecting no \"attributes\", we have "
    1405           0 :                     << count
    1406           0 :                     << " in the node\n";
    1407             :             }
    1408           0 :             CATCH_REQUIRE(count == 0);
    1409             :         }
    1410             :         else
    1411             :         {
    1412             :             // the children value must be an array
    1413           0 :             as2js::json::json_value::array_t const & array(it_attribute->second->get_array());
    1414           0 :             size_t const max_links(array.size());
    1415           0 :             if(verbose && max_links != attribute_node->get_children_size())
    1416             :             {
    1417             :                 std::cerr
    1418           0 :                     << "   Expecting "
    1419           0 :                     << max_links
    1420           0 :                     << " instance, we have "
    1421           0 :                     << attribute_node->get_children_size()
    1422           0 :                     << " in the node\n";
    1423             :             }
    1424           0 :             CATCH_REQUIRE(max_links == attribute_node->get_children_size());
    1425           0 :             for(size_t idx(0); idx < max_links; ++idx)
    1426             :             {
    1427           0 :                 as2js::json::json_value::pointer_t attribute_value(array[idx]);
    1428           0 :                 verify_result(result_name, attribute_value, attribute_node->get_child(idx), verbose, false); // recursive
    1429           0 :             }
    1430             :         }
    1431             :     }
    1432             :     else
    1433             :     {
    1434             :         // no attributes in the node, no children expected in the JSON
    1435      684032 :         if(verbose && it_attribute != child_object.end())
    1436             :         {
    1437           0 :             size_t const count(it_attribute->second->get_array().size());
    1438           0 :             std::cerr << "   Expecting " << count << " \"attributes\", we have none in the node\n";
    1439             :         }
    1440      684032 :         CATCH_REQUIRE(it_attribute == child_object.end());
    1441             :     }
    1442     1368064 : }
    1443             : 
    1444             : 
    1445             : 
    1446             : } // namespace SNAP_CATCH2_NAMESPACE
    1447             : 
    1448             : 
    1449           2 : Catch::Clara::Parser add_command_line_options(Catch::Clara::Parser const & cli)
    1450             : {
    1451             :     return cli
    1452           6 :          | Catch::Clara::Opt(SNAP_CATCH2_NAMESPACE::g_as2js_compiler, "as2js")
    1453           4 :               ["--as2js"]
    1454           4 :               ("path to the as2js compiler.")
    1455           8 :          | Catch::Clara::Opt(SNAP_CATCH2_NAMESPACE::g_run_destructive)
    1456           4 :               ["--destructive"]
    1457           4 :               ("also run the various destructive/problematic tests that can run on their own but probably not along others (if not specified, skip those tests).")
    1458           4 :          | Catch::Clara::Opt(SNAP_CATCH2_NAMESPACE::g_save_parser_tests)
    1459           4 :               ["--save-parser-tests"]
    1460          12 :               ("save the JSON used to test the parser.");
    1461             : }
    1462             : 
    1463             : 
    1464           1 : int init_test(Catch::Session & session)
    1465             : {
    1466           1 :     snapdev::NOT_USED(session);
    1467             : 
    1468             :     // in our snapcpp environment, the default working directory for our
    1469             :     // tests is the source directory (${CMAKE_SOURCE_DIR}); the as2js tests
    1470             :     // want to create folders and files inside the current working directory
    1471             :     // so instead we'd like to be in the temporary directory so change that
    1472             :     // now at the start
    1473             :     //
    1474           1 :     std::string tmp_dir(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
    1475           1 :     if(tmp_dir.empty())
    1476             :     {
    1477             :         // there is a default set to:
    1478             :         //    /tmp/<project-name>
    1479             :         // so this should never happen
    1480             :         //
    1481           0 :         std::cerr << "error: a temporary directory must be specified.\n";
    1482           0 :         return 1;
    1483             :     }
    1484             : 
    1485           1 :     int const r(chdir(tmp_dir.c_str()));
    1486           1 :     if(r != 0)
    1487             :     {
    1488             :         std::cerr << "error: could not change working directory to \""
    1489             :             << tmp_dir
    1490           0 :             << "\"; the directory must exist.\n";
    1491           0 :         return 1;
    1492             :     }
    1493           1 :     char * cwd(get_current_dir_name());
    1494           1 :     if(cwd == nullptr)
    1495             :     {
    1496           0 :         std::cerr << "error: could not retrieve the current working directory.\n";
    1497           0 :         return 1;
    1498             :     }
    1499           1 :     SNAP_CATCH2_NAMESPACE::g_tmp_dir() = cwd;
    1500           1 :     free(cwd);
    1501             : 
    1502             :     // update this path because otherwise the $HOME variable is going to be
    1503             :     // wrong (i.e. a relative path from within said relative path is not
    1504             :     // likely to work properly)
    1505             :     //
    1506           1 :     tmp_dir = SNAP_CATCH2_NAMESPACE::g_tmp_dir();
    1507             : 
    1508             :     // the snapcatch2 ensures an empty tmp directory so this should just
    1509             :     // never happen ever...
    1510             :     //
    1511           1 :     struct stat st;
    1512           1 :     if(stat("debian", &st) == 0)
    1513             :     {
    1514             :         std::cerr << "error: unexpected \"debian\" directory in the temporary directory;"
    1515           0 :             " you cannot safely specify the source directory as the temporary directory.\n";
    1516           0 :         return 1;
    1517             :     }
    1518           1 :     if(stat("as2js/CMakeLists.txt", &st) == 0)
    1519             :     {
    1520             :         std::cerr << "error: unexpected \"as2js/CMakeLists.txt\" file in the temporary directory;"
    1521           0 :             " you cannot safely specify the source directory as the temporary directory.\n";
    1522           0 :         return 1;
    1523             :     }
    1524             : 
    1525             :     // move HOME to a sub-directory inside the temporary directory so that
    1526             :     // way it is safe (we can change files there without the risk of
    1527             :     // destroying some of the developer's files)
    1528             :     //
    1529           1 :     if(snapdev::mkdir_p("home") != 0)
    1530             :     {
    1531             :         std::cerr
    1532             :             << "error: could not create a \"home\" directory in the temporary directory: \""
    1533             :             << tmp_dir
    1534           0 :             << "\".\n";
    1535           0 :         return 1;
    1536             :     }
    1537           1 :     std::string const home(tmp_dir + "/home");
    1538           1 :     setenv("HOME", home.c_str(), 1);
    1539             : 
    1540             :     // some other "modules" that require some initialization
    1541             :     //
    1542           1 :     if(SNAP_CATCH2_NAMESPACE::catch_rc_init() != 0)
    1543             :     {
    1544           0 :         return 1;
    1545             :     }
    1546           1 :     if(SNAP_CATCH2_NAMESPACE::catch_db_init() != 0)
    1547             :     {
    1548           0 :         return 1;
    1549             :     }
    1550           1 :     if(SNAP_CATCH2_NAMESPACE::catch_compiler_init() != 0)
    1551             :     {
    1552           0 :         return 1;
    1553             :     }
    1554             : 
    1555           1 :     return 0;
    1556           1 : }
    1557             : 
    1558             : 
    1559           1 : void cleanup_test()
    1560             : {
    1561           1 :     SNAP_CATCH2_NAMESPACE::catch_compiler_cleanup();
    1562           1 : }
    1563             : 
    1564             : 
    1565           2 : int main(int argc, char * argv[])
    1566             : {
    1567           2 :     return SNAP_CATCH2_NAMESPACE::snap_catch2_main(
    1568             :               "as2js"
    1569             :             , AS2JS_VERSION_STRING
    1570             :             , argc
    1571             :             , argv
    1572           2 :             , []() { libexcept::set_collect_stack(libexcept::collect_stack_t::COLLECT_STACK_NO); }
    1573             :             , &add_command_line_options
    1574             :             , &init_test
    1575             :             , &cleanup_test
    1576           2 :         );
    1577             : }
    1578             : 
    1579             : 
    1580             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.14