LCOV - code coverage report
Current view: top level - tests - test_as2js_optimizer.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 346 521 66.4 %
Date: 2014-11-22 Functions: 26 34 76.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* test_as2js_optimizer.cpp -- written by Alexis WILKE for Made to Order Software Corp. (c) 2005-2014 */
       2             : 
       3             : /*
       4             : 
       5             : Copyright (c) 2005-2014 Made to Order Software Corp.
       6             : 
       7             : http://snapwebsites.org/project/as2js
       8             : 
       9             : Permission is hereby granted, free of charge, to any
      10             : person obtaining a copy of this software and
      11             : associated documentation files (the "Software"), to
      12             : deal in the Software without restriction, including
      13             : without limitation the rights to use, copy, modify,
      14             : merge, publish, distribute, sublicense, and/or sell
      15             : copies of the Software, and to permit persons to whom
      16             : the Software is furnished to do so, subject to the
      17             : following conditions:
      18             : 
      19             : The above copyright notice and this permission notice
      20             : shall be included in all copies or substantial
      21             : portions of the Software.
      22             : 
      23             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
      24             : ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
      25             : LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
      26             : FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
      27             : EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
      28             : LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
      29             : WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      30             : ARISING FROM, OUT OF OR IN CONNECTION WITH THE
      31             : SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      32             : SOFTWARE.
      33             : 
      34             : */
      35             : 
      36             : #include    "test_as2js_optimizer.h"
      37             : #include    "test_as2js_main.h"
      38             : 
      39             : #include    "as2js/optimizer.h"
      40             : #include    "as2js/parser.h"
      41             : #include    "as2js/exceptions.h"
      42             : #include    "as2js/message.h"
      43             : #include    "as2js/json.h"
      44             : 
      45             : #include    <controlled_vars/controlled_vars_limited_auto_enum_init.h>
      46             : 
      47             : #include    <unistd.h>
      48             : #include    <sys/stat.h>
      49             : 
      50             : #include    <cstring>
      51             : #include    <algorithm>
      52             : #include    <iomanip>
      53             : 
      54             : #include    <cppunit/config/SourcePrefix.h>
      55           4 : CPPUNIT_TEST_SUITE_REGISTRATION( As2JsOptimizerUnitTests );
      56             : 
      57             : namespace
      58             : {
      59             : 
      60             : 
      61             : struct err_to_string_t
      62             : {
      63             :     as2js::err_code_t       f_code;
      64             :     char const *            f_name;
      65             :     int                     f_line;
      66             : };
      67             : 
      68             : #define    TO_STR_sub(s)            #s
      69             : #define    ERROR_NAME(err)     { as2js::err_code_t::AS_ERR_##err, TO_STR_sub(err), __LINE__ }
      70             : 
      71             : err_to_string_t const g_error_table[] =
      72             : {
      73             :     ERROR_NAME(NONE),
      74             :     ERROR_NAME(ABSTRACT),
      75             :     ERROR_NAME(BAD_NUMERIC_TYPE),
      76             :     ERROR_NAME(BAD_PRAGMA),
      77             :     ERROR_NAME(CANNOT_COMPILE),
      78             :     ERROR_NAME(CANNOT_MATCH),
      79             :     ERROR_NAME(CANNOT_OVERLOAD),
      80             :     ERROR_NAME(CANNOT_OVERWRITE_CONST),
      81             :     ERROR_NAME(CASE_LABEL),
      82             :     ERROR_NAME(COLON_EXPECTED),
      83             :     ERROR_NAME(COMMA_EXPECTED),
      84             :     ERROR_NAME(CURVLY_BRACKETS_EXPECTED),
      85             :     ERROR_NAME(DEFAULT_LABEL),
      86             :     ERROR_NAME(DIVIDE_BY_ZERO),
      87             :     ERROR_NAME(DUPLICATES),
      88             :     ERROR_NAME(DYNAMIC),
      89             :     ERROR_NAME(EXPRESSION_EXPECTED),
      90             :     ERROR_NAME(FINAL),
      91             :     ERROR_NAME(IMPROPER_STATEMENT),
      92             :     ERROR_NAME(INACCESSIBLE_STATEMENT),
      93             :     ERROR_NAME(INCOMPATIBLE),
      94             :     ERROR_NAME(INCOMPATIBLE_PRAGMA_ARGUMENT),
      95             :     ERROR_NAME(INSTALLATION),
      96             :     ERROR_NAME(INSTANCE_EXPECTED),
      97             :     ERROR_NAME(INTERNAL_ERROR),
      98             :     ERROR_NAME(NATIVE),
      99             :     ERROR_NAME(INVALID_ARRAY_FUNCTION),
     100             :     ERROR_NAME(INVALID_ATTRIBUTES),
     101             :     ERROR_NAME(INVALID_CATCH),
     102             :     ERROR_NAME(INVALID_CLASS),
     103             :     ERROR_NAME(INVALID_CONDITIONAL),
     104             :     ERROR_NAME(INVALID_DEFINITION),
     105             :     ERROR_NAME(INVALID_DO),
     106             :     ERROR_NAME(INVALID_ENUM),
     107             :     ERROR_NAME(INVALID_EXPRESSION),
     108             :     ERROR_NAME(INVALID_FIELD),
     109             :     ERROR_NAME(INVALID_FIELD_NAME),
     110             :     ERROR_NAME(INVALID_FRAME),
     111             :     ERROR_NAME(INVALID_FUNCTION),
     112             :     ERROR_NAME(INVALID_GOTO),
     113             :     ERROR_NAME(INVALID_IMPORT),
     114             :     ERROR_NAME(INVALID_INPUT_STREAM),
     115             :     ERROR_NAME(INVALID_KEYWORD),
     116             :     ERROR_NAME(INVALID_LABEL),
     117             :     ERROR_NAME(INVALID_NAMESPACE),
     118             :     ERROR_NAME(INVALID_NODE),
     119             :     ERROR_NAME(INVALID_NUMBER),
     120             :     ERROR_NAME(INVALID_OPERATOR),
     121             :     ERROR_NAME(INVALID_PACKAGE_NAME),
     122             :     ERROR_NAME(INVALID_PARAMETERS),
     123             :     ERROR_NAME(INVALID_REST),
     124             :     ERROR_NAME(INVALID_RETURN_TYPE),
     125             :     ERROR_NAME(INVALID_SCOPE),
     126             :     ERROR_NAME(INVALID_TRY),
     127             :     ERROR_NAME(INVALID_TYPE),
     128             :     ERROR_NAME(INVALID_UNICODE_ESCAPE_SEQUENCE),
     129             :     ERROR_NAME(INVALID_VARIABLE),
     130             :     ERROR_NAME(IO_ERROR),
     131             :     ERROR_NAME(LABEL_NOT_FOUND),
     132             :     ERROR_NAME(LOOPING_REFERENCE),
     133             :     ERROR_NAME(MISMATCH_FUNC_VAR),
     134             :     ERROR_NAME(MISSSING_VARIABLE_NAME),
     135             :     ERROR_NAME(NEED_CONST),
     136             :     ERROR_NAME(NOT_ALLOWED),
     137             :     ERROR_NAME(NOT_ALLOWED_IN_STRICT_MODE),
     138             :     ERROR_NAME(NOT_FOUND),
     139             :     ERROR_NAME(NOT_SUPPORTED),
     140             :     ERROR_NAME(OBJECT_MEMBER_DEFINED_TWICE),
     141             :     ERROR_NAME(PARENTHESIS_EXPECTED),
     142             :     ERROR_NAME(PRAGMA_FAILED),
     143             :     ERROR_NAME(SEMICOLON_EXPECTED),
     144             :     ERROR_NAME(SQUARE_BRACKETS_EXPECTED),
     145             :     ERROR_NAME(STRING_EXPECTED),
     146             :     ERROR_NAME(STATIC),
     147             :     ERROR_NAME(TYPE_NOT_LINKED),
     148             :     ERROR_NAME(UNKNOWN_ESCAPE_SEQUENCE),
     149             :     ERROR_NAME(UNKNOWN_OPERATOR),
     150             :     ERROR_NAME(UNTERMINATED_STRING),
     151             :     ERROR_NAME(UNEXPECTED_EOF),
     152             :     ERROR_NAME(UNEXPECTED_PUNCTUATION),
     153             :     ERROR_NAME(UNEXPECTED_TOKEN),
     154             :     ERROR_NAME(UNEXPECTED_DATABASE),
     155             :     ERROR_NAME(UNEXPECTED_RC)
     156             : };
     157             : size_t const g_error_table_size = sizeof(g_error_table) / sizeof(g_error_table[0]);
     158             : 
     159             : 
     160          14 : as2js::err_code_t str_to_error_code(as2js::String const& error_name)
     161             : {
     162         658 :     for(size_t idx(0); idx < g_error_table_size; ++idx)
     163             :     {
     164         658 :         if(error_name == g_error_table[idx].f_name)
     165             :         {
     166          14 :             return g_error_table[idx].f_code;
     167             :         }
     168             :     }
     169           0 :     std::cerr << "Error name \"" << error_name << "\" not found.\n";
     170           0 :     CPPUNIT_ASSERT(!"error name not found, test_as2js_optimizer.cpp bug");
     171           0 :     return as2js::err_code_t::AS_ERR_NONE;
     172             : }
     173             : 
     174             : 
     175           0 : char const *error_code_to_str(as2js::err_code_t const& error_code)
     176             : {
     177           0 :     for(size_t idx(0); idx < g_error_table_size; ++idx)
     178             :     {
     179           0 :         if(error_code == g_error_table[idx].f_code)
     180             :         {
     181           0 :             return g_error_table[idx].f_name;
     182             :         }
     183             :     }
     184           0 :     std::cerr << "Error code \"" << static_cast<int>(error_code) << "\" not found.\n";
     185           0 :     CPPUNIT_ASSERT(!"error code not found, test_as2js_optimizer.cpp bug");
     186           0 :     return "unknown";
     187             : }
     188             : 
     189             : 
     190             : 
     191             : class test_callback : public as2js::MessageCallback
     192             : {
     193             : public:
     194         422 :     test_callback(bool verbose)
     195         422 :         : f_verbose(verbose)
     196             :     {
     197         422 :         as2js::Message::set_message_callback(this);
     198         422 :         g_warning_count = as2js::Message::warning_count();
     199         422 :         g_error_count = as2js::Message::error_count();
     200         422 :     }
     201             : 
     202         422 :     ~test_callback()
     203         844 :     {
     204             :         // make sure the pointer gets reset!
     205         422 :         as2js::Message::set_message_callback(nullptr);
     206         422 :     }
     207             : 
     208             :     // implementation of the output
     209          14 :     virtual void output(as2js::message_level_t message_level, as2js::err_code_t error_code, as2js::Position const& pos, std::string const& message)
     210             :     {
     211             :         // skip trace messages which happen all the time because of the
     212             :         // lexer debug option
     213          14 :         if(message_level == as2js::message_level_t::MESSAGE_LEVEL_TRACE)
     214             :         {
     215          14 :             return;
     216             :         }
     217             : 
     218          14 :         if(f_expected.empty())
     219             :         {
     220           0 :             std::cerr << "\n*** STILL NECESSARY ***\n";
     221           0 :             std::cerr << "filename = " << pos.get_filename() << "\n";
     222           0 :             std::cerr << "msg = " << message << "\n";
     223           0 :             std::cerr << "page = " << pos.get_page() << "\n";
     224           0 :             std::cerr << "line = " << pos.get_line() << "\n";
     225           0 :             std::cerr << "error_code = " << static_cast<int>(error_code) << " (" << error_code_to_str(error_code) << ")\n";
     226             :         }
     227             : 
     228          14 :         CPPUNIT_ASSERT(!f_expected.empty());
     229             : 
     230          14 :         if(f_verbose)
     231             :         {
     232           0 :             std::cerr << "filename = " << pos.get_filename() << " (node) / " << f_expected[0].f_pos.get_filename() << " (JSON)\n";
     233           0 :             std::cerr << "msg = " << message << " / " << f_expected[0].f_message << "\n";
     234           0 :             std::cerr << "page = " << pos.get_page() << " / " << f_expected[0].f_pos.get_page() << "\n";
     235           0 :             std::cerr << "line = " << pos.get_line() << " / " << f_expected[0].f_pos.get_line() << "\n";
     236           0 :             std::cerr << "page line = " << pos.get_page_line() << " / " << f_expected[0].f_pos.get_page_line() << "\n";
     237           0 :             std::cerr << "error_code = " << static_cast<int>(error_code) << " (" << error_code_to_str(error_code) << ") / " << static_cast<int>(f_expected[0].f_error_code) << " (" << error_code_to_str(f_expected[0].f_error_code) << ")\n";
     238             :         }
     239             : 
     240          14 :         CPPUNIT_ASSERT(f_expected[0].f_call);
     241          14 :         CPPUNIT_ASSERT(message_level == f_expected[0].f_message_level);
     242          14 :         CPPUNIT_ASSERT(error_code == f_expected[0].f_error_code);
     243          14 :         CPPUNIT_ASSERT(pos.get_filename() == f_expected[0].f_pos.get_filename());
     244          14 :         CPPUNIT_ASSERT(pos.get_function() == f_expected[0].f_pos.get_function());
     245          14 :         CPPUNIT_ASSERT(pos.get_page() == f_expected[0].f_pos.get_page());
     246          14 :         CPPUNIT_ASSERT(pos.get_page_line() == f_expected[0].f_pos.get_page_line());
     247          14 :         CPPUNIT_ASSERT(pos.get_paragraph() == f_expected[0].f_pos.get_paragraph());
     248          14 :         CPPUNIT_ASSERT(pos.get_line() == f_expected[0].f_pos.get_line());
     249          14 :         CPPUNIT_ASSERT(message == f_expected[0].f_message.to_utf8());
     250             : 
     251          14 :         if(message_level == as2js::message_level_t::MESSAGE_LEVEL_WARNING)
     252             :         {
     253          14 :             ++g_warning_count;
     254          14 :             CPPUNIT_ASSERT(g_warning_count == as2js::Message::warning_count());
     255             :         }
     256             : 
     257          14 :         if(message_level == as2js::message_level_t::MESSAGE_LEVEL_FATAL
     258          14 :         || message_level == as2js::message_level_t::MESSAGE_LEVEL_ERROR)
     259             :         {
     260           0 :             ++g_error_count;
     261             : //std::cerr << "error: " << g_error_count << " / " << as2js::Message::error_count() << "\n";
     262           0 :             CPPUNIT_ASSERT(g_error_count == as2js::Message::error_count());
     263             :         }
     264             : 
     265          14 :         f_expected.erase(f_expected.begin());
     266             :     }
     267             : 
     268         422 :     void got_called()
     269             :     {
     270         422 :         if(!f_expected.empty())
     271             :         {
     272           0 :             std::cerr << "\n*** STILL " << f_expected.size() << " EXPECTED ***\n";
     273           0 :             std::cerr << "filename = " << f_expected[0].f_pos.get_filename() << "\n";
     274           0 :             std::cerr << "msg = " << f_expected[0].f_message << "\n";
     275           0 :             std::cerr << "page = " << f_expected[0].f_pos.get_page() << "\n";
     276           0 :             std::cerr << "error_code = " << static_cast<int>(f_expected[0].f_error_code) << "\n";
     277             :         }
     278         422 :         CPPUNIT_ASSERT(f_expected.empty());
     279         422 :     }
     280             : 
     281          56 :     struct expected_t
     282             :     {
     283             :         controlled_vars::tlbool_t   f_call;
     284             :         as2js::message_level_t      f_message_level;
     285             :         as2js::err_code_t           f_error_code;
     286             :         as2js::Position             f_pos;
     287             :         as2js::String               f_message; // UTF-8 string
     288             :     };
     289             : 
     290             :     std::vector<expected_t>     f_expected;
     291             :     controlled_vars::fbool_t    f_verbose;
     292             : 
     293             :     static controlled_vars::zint32_t   g_warning_count;
     294             :     static controlled_vars::zint32_t   g_error_count;
     295             : };
     296             : 
     297           4 : controlled_vars::zint32_t   test_callback::g_warning_count;
     298           4 : controlled_vars::zint32_t   test_callback::g_error_count;
     299             : 
     300           4 : controlled_vars::zint32_t   g_empty_home_too_late;
     301             : 
     302             : 
     303             : //
     304             : // we have two special pragmas that accept 0, 1, 2, or 3
     305             : // namely, those are:
     306             : //
     307             : //  . OPTION_EXTENDED_STATEMENTS -- force '{' ... '}' in
     308             : //    blocks for: if, while, do, for, with...
     309             : //
     310             : //  . OPTION_EXTENDED_OPERATORS -- force ':=' instead of '='
     311             : //
     312             : // for this reason we support and f_value which is viewed
     313             : // as a set of flags
     314             : //
     315             : struct named_options
     316             : {
     317             :     as2js::Options::option_t    f_option;
     318             :     char const *                f_name;
     319             :     char const *                f_neg_name;
     320             :     int                         f_value;
     321             : };
     322             : named_options const g_options[] =
     323             : {
     324             :     {
     325             :         as2js::Options::option_t::OPTION_ALLOW_WITH,
     326             :         "allow_with",
     327             :         "no_allow_with",
     328             :         1
     329             :     },
     330             :     {
     331             :         as2js::Options::option_t::OPTION_BINARY,
     332             :         "binary",
     333             :         "no_binary",
     334             :         1
     335             :     },
     336             :     {
     337             :         as2js::Options::option_t::OPTION_COVERAGE,
     338             :         "coverage",
     339             :         "no_coverage",
     340             :         1
     341             :     },
     342             :     {
     343             :         as2js::Options::option_t::OPTION_DEBUG,
     344             :         "debug",
     345             :         "no_debug",
     346             :         1
     347             :     },
     348             :     {
     349             :         as2js::Options::option_t::OPTION_EXTENDED_ESCAPE_SEQUENCES,
     350             :         "extended_escape_sequences",
     351             :         "no_extended_escape_sequences",
     352             :         1
     353             :     },
     354             :     {
     355             :         as2js::Options::option_t::OPTION_EXTENDED_OPERATORS,
     356             :         "extended_operators",
     357             :         "no_extended_operators",
     358             :         1
     359             :     },
     360             :     {
     361             :         as2js::Options::option_t::OPTION_EXTENDED_OPERATORS,
     362             :         "extended_operators_safe",
     363             :         "no_extended_operators_safe",
     364             :         2
     365             :     },
     366             :     {
     367             :         as2js::Options::option_t::OPTION_EXTENDED_STATEMENTS,
     368             :         "extended_statements",
     369             :         "no_extended_statements",
     370             :         1
     371             :     },
     372             :     {
     373             :         as2js::Options::option_t::OPTION_EXTENDED_STATEMENTS,
     374             :         "extended_statements_safe",
     375             :         "no_extended_statements_safe",
     376             :         2
     377             :     },
     378             :     //{ -- this one does not make sense here
     379             :     //    as2js::Options::option_t::OPTION_JSON,
     380             :     //    "json",
     381             :     //    "no_json"
     382             :     //},
     383             :     {
     384             :         as2js::Options::option_t::OPTION_OCTAL,
     385             :         "octal",
     386             :         "no_octal",
     387             :         1
     388             :     },
     389             :     {
     390             :         as2js::Options::option_t::OPTION_STRICT,
     391             :         "strict",
     392             :         "no_strict",
     393             :         1
     394             :     },
     395             :     {
     396             :         as2js::Options::option_t::OPTION_TRACE,
     397             :         "trace",
     398             :         "no_trace",
     399             :         1
     400             :     },
     401             :     {
     402             :         as2js::Options::option_t::OPTION_UNSAFE_MATH,
     403             :         "unsafe_math",
     404             :         "no_unsafe_math",
     405             :         1
     406             :     }
     407             : };
     408             : size_t const g_options_size(sizeof(g_options) / sizeof(g_options[0]));
     409             : 
     410             : 
     411             : struct flg_to_string_t
     412             : {
     413             :     as2js::Node::flag_t     f_flag;
     414             :     char const *            f_name;
     415             :     int                     f_line;
     416             : };
     417             : 
     418             : #define    FLAG_NAME(flg)     { as2js::Node::flag_t::NODE_##flg, TO_STR_sub(flg), __LINE__ }
     419             : 
     420             : flg_to_string_t const g_flag_table[] =
     421             : {
     422             :     FLAG_NAME(CATCH_FLAG_TYPED),
     423             :     FLAG_NAME(DIRECTIVE_LIST_FLAG_NEW_VARIABLES),
     424             :     FLAG_NAME(ENUM_FLAG_CLASS),
     425             :     FLAG_NAME(FOR_FLAG_CONST),
     426             :     FLAG_NAME(FOR_FLAG_FOREACH),
     427             :     FLAG_NAME(FOR_FLAG_IN),
     428             :     FLAG_NAME(FUNCTION_FLAG_GETTER),
     429             :     FLAG_NAME(FUNCTION_FLAG_SETTER),
     430             :     FLAG_NAME(FUNCTION_FLAG_OUT),
     431             :     FLAG_NAME(FUNCTION_FLAG_VOID),
     432             :     FLAG_NAME(FUNCTION_FLAG_NEVER),
     433             :     FLAG_NAME(FUNCTION_FLAG_NOPARAMS),
     434             :     FLAG_NAME(FUNCTION_FLAG_OPERATOR),
     435             :     FLAG_NAME(IDENTIFIER_FLAG_WITH),
     436             :     FLAG_NAME(IDENTIFIER_FLAG_TYPED),
     437             :     FLAG_NAME(IMPORT_FLAG_IMPLEMENTS),
     438             :     FLAG_NAME(PACKAGE_FLAG_FOUND_LABELS),
     439             :     FLAG_NAME(PACKAGE_FLAG_REFERENCED),
     440             :     FLAG_NAME(PARAM_FLAG_CONST),
     441             :     FLAG_NAME(PARAM_FLAG_IN),
     442             :     FLAG_NAME(PARAM_FLAG_OUT),
     443             :     FLAG_NAME(PARAM_FLAG_NAMED),
     444             :     FLAG_NAME(PARAM_FLAG_REST),
     445             :     FLAG_NAME(PARAM_FLAG_UNCHECKED),
     446             :     FLAG_NAME(PARAM_FLAG_UNPROTOTYPED),
     447             :     FLAG_NAME(PARAM_FLAG_REFERENCED),
     448             :     FLAG_NAME(PARAM_FLAG_PARAMREF),
     449             :     FLAG_NAME(PARAM_FLAG_CATCH),
     450             :     FLAG_NAME(PARAM_MATCH_FLAG_UNPROTOTYPED),
     451             :     FLAG_NAME(SWITCH_FLAG_DEFAULT),
     452             :     FLAG_NAME(TYPE_FLAG_MODULO),
     453             :     FLAG_NAME(VARIABLE_FLAG_CONST),
     454             :     FLAG_NAME(VARIABLE_FLAG_LOCAL),
     455             :     FLAG_NAME(VARIABLE_FLAG_MEMBER),
     456             :     FLAG_NAME(VARIABLE_FLAG_ATTRIBUTES),
     457             :     FLAG_NAME(VARIABLE_FLAG_ENUM),
     458             :     FLAG_NAME(VARIABLE_FLAG_COMPILED),
     459             :     FLAG_NAME(VARIABLE_FLAG_INUSE),
     460             :     FLAG_NAME(VARIABLE_FLAG_ATTRS),
     461             :     FLAG_NAME(VARIABLE_FLAG_DEFINED),
     462             :     FLAG_NAME(VARIABLE_FLAG_DEFINING),
     463             :     FLAG_NAME(VARIABLE_FLAG_TOADD)
     464             : };
     465             : size_t const g_flag_table_size = sizeof(g_flag_table) / sizeof(g_flag_table[0]);
     466             : 
     467             : 
     468           0 : as2js::Node::flag_t str_to_flag_code(as2js::String const& flag_name)
     469             : {
     470           0 :     for(size_t idx(0); idx < g_flag_table_size; ++idx)
     471             :     {
     472           0 :         if(flag_name == g_flag_table[idx].f_name)
     473             :         {
     474           0 :             return g_flag_table[idx].f_flag;
     475             :         }
     476             :     }
     477           0 :     CPPUNIT_ASSERT(!"flag code not found, test_as2js_optimizer.cpp bug");
     478           0 :     return as2js::Node::flag_t::NODE_FLAG_max;
     479             : }
     480             : 
     481             : 
     482           0 : as2js::String flag_to_str(as2js::Node::flag_t& flg)
     483             : {
     484           0 :     for(size_t idx(0); idx < g_flag_table_size; ++idx)
     485             :     {
     486           0 :         if(flg == g_flag_table[idx].f_flag)
     487             :         {
     488           0 :             return g_flag_table[idx].f_name;
     489             :         }
     490             :     }
     491           0 :     CPPUNIT_ASSERT(!"flag code not found, test_as2js_optimizer.cpp bug");
     492           0 :     return "";
     493             : }
     494             : 
     495             : 
     496             : 
     497             : 
     498        3682 : void verify_flags(as2js::Node::pointer_t node, as2js::String const& flags_set, bool verbose)
     499             : {
     500             :     // list of flags that have to be set
     501        3682 :     std::vector<as2js::Node::flag_t> flgs;
     502        3682 :     as2js::as_char_t const *f(flags_set.c_str());
     503        3682 :     as2js::as_char_t const *s(f);
     504             :     for(;;)
     505             :     {
     506        3682 :         if(*f == ',' || *f == '\0')
     507             :         {
     508        3682 :             if(s == f)
     509             :             {
     510        7364 :                 break;
     511             :             }
     512           0 :             as2js::String name(s, f - s);
     513             : //std::cerr << "Checking " << name << " -> " << static_cast<int>(str_to_flag_code(name)) << "\n";
     514           0 :             flgs.push_back(str_to_flag_code(name));
     515           0 :             if(*f == '\0')
     516             :             {
     517           0 :                 break;
     518             :             }
     519           0 :             do // skip commas
     520             :             {
     521           0 :                 ++f;
     522             :             }
     523           0 :             while(*f == ',');
     524           0 :             s = f;
     525             :         }
     526             :         else
     527             :         {
     528           0 :             ++f;
     529             :         }
     530           0 :     }
     531             : 
     532             :     // list of flags that must be checked
     533        7364 :     std::vector<as2js::Node::flag_t> flgs_to_check;
     534        3682 :     switch(node->get_type())
     535             :     {
     536             :     case as2js::Node::node_t::NODE_CATCH:
     537           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_CATCH_FLAG_TYPED);
     538           0 :         break;
     539             : 
     540             :     case as2js::Node::node_t::NODE_DIRECTIVE_LIST:
     541         869 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_DIRECTIVE_LIST_FLAG_NEW_VARIABLES);
     542         869 :         break;
     543             : 
     544             :     case as2js::Node::node_t::NODE_ENUM:
     545           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_ENUM_FLAG_CLASS);
     546           0 :         break;
     547             : 
     548             :     case as2js::Node::node_t::NODE_FOR:
     549           4 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_FOR_FLAG_CONST);
     550           4 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_FOR_FLAG_FOREACH);
     551           4 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_FOR_FLAG_IN);
     552           4 :         break;
     553             : 
     554             :     case as2js::Node::node_t::NODE_FUNCTION:
     555           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_FUNCTION_FLAG_GETTER);
     556           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_FUNCTION_FLAG_NEVER);
     557           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_FUNCTION_FLAG_NOPARAMS);
     558           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_FUNCTION_FLAG_OPERATOR);
     559           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_FUNCTION_FLAG_OUT);
     560           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_FUNCTION_FLAG_SETTER);
     561           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_FUNCTION_FLAG_VOID);
     562           0 :         break;
     563             : 
     564             :     case as2js::Node::node_t::NODE_IDENTIFIER:
     565             :     case as2js::Node::node_t::NODE_VIDENTIFIER:
     566             :     case as2js::Node::node_t::NODE_STRING:
     567         381 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_IDENTIFIER_FLAG_WITH);
     568         381 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_IDENTIFIER_FLAG_TYPED);
     569         381 :         break;
     570             : 
     571             :     case as2js::Node::node_t::NODE_IMPORT:
     572           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_IMPORT_FLAG_IMPLEMENTS);
     573           0 :         break;
     574             : 
     575             :     case as2js::Node::node_t::NODE_PACKAGE:
     576           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_PACKAGE_FLAG_FOUND_LABELS);
     577           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_PACKAGE_FLAG_REFERENCED);
     578           0 :         break;
     579             : 
     580             :     case as2js::Node::node_t::NODE_PARAM_MATCH:
     581           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_PARAM_MATCH_FLAG_UNPROTOTYPED);
     582           0 :         break;
     583             : 
     584             :     case as2js::Node::node_t::NODE_PARAM:
     585           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_PARAM_FLAG_CATCH);
     586           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_PARAM_FLAG_CONST);
     587           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_PARAM_FLAG_IN);
     588           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_PARAM_FLAG_OUT);
     589           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_PARAM_FLAG_NAMED);
     590           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_PARAM_FLAG_PARAMREF);
     591           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_PARAM_FLAG_REFERENCED);
     592           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_PARAM_FLAG_REST);
     593           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_PARAM_FLAG_UNCHECKED);
     594           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_PARAM_FLAG_UNPROTOTYPED);
     595           0 :         break;
     596             : 
     597             :     case as2js::Node::node_t::NODE_SWITCH:
     598           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_SWITCH_FLAG_DEFAULT);
     599           0 :         break;
     600             : 
     601             :     case as2js::Node::node_t::NODE_TYPE:
     602           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_TYPE_FLAG_MODULO);
     603           0 :         break;
     604             : 
     605             :     case as2js::Node::node_t::NODE_VARIABLE:
     606             :     case as2js::Node::node_t::NODE_VAR_ATTRIBUTES:
     607           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_VARIABLE_FLAG_CONST);
     608           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_VARIABLE_FLAG_LOCAL);
     609           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_VARIABLE_FLAG_MEMBER);
     610           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_VARIABLE_FLAG_ATTRIBUTES);
     611           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_VARIABLE_FLAG_ENUM);
     612           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_VARIABLE_FLAG_COMPILED);
     613           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_VARIABLE_FLAG_INUSE);
     614           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_VARIABLE_FLAG_ATTRS);
     615           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_VARIABLE_FLAG_DEFINED);
     616           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_VARIABLE_FLAG_DEFINING);
     617           0 :         flgs_to_check.push_back(as2js::Node::flag_t::NODE_VARIABLE_FLAG_TOADD);
     618           0 :         break;
     619             : 
     620             :     default:
     621             :         // no flags supported
     622        2428 :         break;
     623             : 
     624             :     }
     625             : 
     626        3682 :     CPPUNIT_ASSERT(flgs.size() <= flgs_to_check.size());
     627             : 
     628        5325 :     for(size_t idx(0); idx < flgs_to_check.size(); ++idx)
     629             :     {
     630        1643 :         as2js::Node::flag_t flg(flgs_to_check[idx]);
     631        1643 :         std::vector<as2js::Node::flag_t>::iterator it(std::find(flgs.begin(), flgs.end(), flg));
     632        1643 :         if(it == flgs.end())
     633             :         {
     634             :             // expected to be unset
     635        1643 :             if(verbose && node->get_flag(flg))
     636             :             {
     637           0 :                 std::cerr << "*** Comparing flags " << flag_to_str(flg) << " (should not be set)\n";
     638             :             }
     639        1643 :             CPPUNIT_ASSERT(!node->get_flag(flg));
     640             :         }
     641             :         else
     642             :         {
     643             :             // expected to be set
     644           0 :             flgs.erase(it);
     645           0 :             if(verbose && !node->get_flag(flg))
     646             :             {
     647           0 :                 std::cerr << "*** Comparing flags " << flag_to_str(flg) << " (it should be set in this case)\n";
     648             :             }
     649           0 :             CPPUNIT_ASSERT(node->get_flag(flg));
     650             :         }
     651             :     }
     652             : 
     653        7364 :     CPPUNIT_ASSERT(flgs.empty());
     654        3682 : }
     655             : 
     656             : 
     657             : 
     658             : 
     659             : struct attr_to_string_t
     660             : {
     661             :     as2js::Node::attribute_t    f_attribute;
     662             :     char const *                f_name;
     663             :     int                         f_line;
     664             : };
     665             : 
     666             : #define    ATTRIBUTE_NAME(attr)      { as2js::Node::attribute_t::NODE_ATTR_##attr, TO_STR_sub(attr), __LINE__ }
     667             : 
     668             : attr_to_string_t const g_attribute_table[] =
     669             : {
     670             :     ATTRIBUTE_NAME(PUBLIC),
     671             :     ATTRIBUTE_NAME(PRIVATE),
     672             :     ATTRIBUTE_NAME(PROTECTED),
     673             :     ATTRIBUTE_NAME(INTERNAL),
     674             :     ATTRIBUTE_NAME(TRANSIENT),
     675             :     ATTRIBUTE_NAME(VOLATILE),
     676             :     ATTRIBUTE_NAME(STATIC),
     677             :     ATTRIBUTE_NAME(ABSTRACT),
     678             :     ATTRIBUTE_NAME(VIRTUAL),
     679             :     ATTRIBUTE_NAME(ARRAY),
     680             :     ATTRIBUTE_NAME(REQUIRE_ELSE),
     681             :     ATTRIBUTE_NAME(ENSURE_THEN),
     682             :     ATTRIBUTE_NAME(NATIVE),
     683             :     ATTRIBUTE_NAME(DEPRECATED),
     684             :     ATTRIBUTE_NAME(UNSAFE),
     685             :     ATTRIBUTE_NAME(CONSTRUCTOR),
     686             :     ATTRIBUTE_NAME(FINAL),
     687             :     ATTRIBUTE_NAME(ENUMERABLE),
     688             :     ATTRIBUTE_NAME(TRUE),
     689             :     ATTRIBUTE_NAME(FALSE),
     690             :     ATTRIBUTE_NAME(UNUSED),
     691             :     ATTRIBUTE_NAME(DYNAMIC),
     692             :     ATTRIBUTE_NAME(FOREACH),
     693             :     ATTRIBUTE_NAME(NOBREAK),
     694             :     ATTRIBUTE_NAME(AUTOBREAK),
     695             :     ATTRIBUTE_NAME(DEFINED)
     696             : };
     697             : size_t const g_attribute_table_size = sizeof(g_attribute_table) / sizeof(g_attribute_table[0]);
     698             : 
     699             : 
     700           0 : as2js::Node::attribute_t str_to_attribute_code(as2js::String const& attr_name)
     701             : {
     702           0 :     for(size_t idx(0); idx < g_attribute_table_size; ++idx)
     703             :     {
     704           0 :         if(attr_name == g_attribute_table[idx].f_name)
     705             :         {
     706           0 :             return g_attribute_table[idx].f_attribute;
     707             :         }
     708             :     }
     709           0 :     CPPUNIT_ASSERT(!"attribute code not found, test_as2js_optimizer.cpp bug");
     710           0 :     return as2js::Node::attribute_t::NODE_ATTR_max;
     711             : }
     712             : 
     713             : 
     714           0 : as2js::String attribute_to_str(as2js::Node::attribute_t& attr)
     715             : {
     716           0 :     for(size_t idx(0); idx < g_attribute_table_size; ++idx)
     717             :     {
     718           0 :         if(attr == g_attribute_table[idx].f_attribute)
     719             :         {
     720           0 :             return g_attribute_table[idx].f_name;
     721             :         }
     722             :     }
     723           0 :     CPPUNIT_ASSERT(!"attribute code not found, test_as2js_optimizer.cpp bug");
     724           0 :     return "";
     725             : }
     726             : 
     727             : 
     728             : 
     729             : 
     730        3682 : void verify_attributes(as2js::Node::pointer_t node, as2js::String const& attributes_set, bool verbose)
     731             : {
     732             :     // list of attributes that have to be set
     733        3682 :     std::vector<as2js::Node::attribute_t> attrs;
     734        3682 :     as2js::as_char_t const *a(attributes_set.c_str());
     735        3682 :     as2js::as_char_t const *s(a);
     736             :     for(;;)
     737             :     {
     738        3682 :         if(*a == ',' || *a == '\0')
     739             :         {
     740        3682 :             if(s == a)
     741             :             {
     742        7364 :                 break;
     743             :             }
     744           0 :             as2js::String name(s, a - s);
     745           0 :             attrs.push_back(str_to_attribute_code(name));
     746           0 :             if(*a == '\0')
     747             :             {
     748           0 :                 break;
     749             :             }
     750           0 :             do // skip commas
     751             :             {
     752           0 :                 ++a;
     753             :             }
     754           0 :             while(*a == ',');
     755           0 :             s = a;
     756             :         }
     757             :         else
     758             :         {
     759           0 :             ++a;
     760             :         }
     761           0 :     }
     762             : 
     763             :     // list of attributes that must be checked
     764        7364 :     std::vector<as2js::Node::attribute_t> attrs_to_check;
     765             : 
     766        3682 :     if(node->get_type() != as2js::Node::node_t::NODE_PROGRAM)
     767             :     {
     768             :         // except for PROGRAM, all attributes always apply
     769        2838 :         attrs_to_check.push_back(as2js::Node::attribute_t::NODE_ATTR_PUBLIC);
     770        2838 :         attrs_to_check.push_back(as2js::Node::attribute_t::NODE_ATTR_PRIVATE);
     771        2838 :         attrs_to_check.push_back(as2js::Node::attribute_t::NODE_ATTR_PROTECTED);
     772        2838 :         attrs_to_check.push_back(as2js::Node::attribute_t::NODE_ATTR_INTERNAL);
     773        2838 :         attrs_to_check.push_back(as2js::Node::attribute_t::NODE_ATTR_TRANSIENT);
     774        2838 :         attrs_to_check.push_back(as2js::Node::attribute_t::NODE_ATTR_VOLATILE);
     775        2838 :         attrs_to_check.push_back(as2js::Node::attribute_t::NODE_ATTR_STATIC);
     776        2838 :         attrs_to_check.push_back(as2js::Node::attribute_t::NODE_ATTR_ABSTRACT);
     777        2838 :         attrs_to_check.push_back(as2js::Node::attribute_t::NODE_ATTR_VIRTUAL);
     778        2838 :         attrs_to_check.push_back(as2js::Node::attribute_t::NODE_ATTR_ARRAY);
     779        2838 :         attrs_to_check.push_back(as2js::Node::attribute_t::NODE_ATTR_REQUIRE_ELSE);
     780        2838 :         attrs_to_check.push_back(as2js::Node::attribute_t::NODE_ATTR_ENSURE_THEN);
     781        2838 :         attrs_to_check.push_back(as2js::Node::attribute_t::NODE_ATTR_NATIVE);
     782        2838 :         attrs_to_check.push_back(as2js::Node::attribute_t::NODE_ATTR_DEPRECATED);
     783        2838 :         attrs_to_check.push_back(as2js::Node::attribute_t::NODE_ATTR_UNSAFE);
     784        2838 :         attrs_to_check.push_back(as2js::Node::attribute_t::NODE_ATTR_CONSTRUCTOR);
     785        2838 :         attrs_to_check.push_back(as2js::Node::attribute_t::NODE_ATTR_FINAL);
     786        2838 :         attrs_to_check.push_back(as2js::Node::attribute_t::NODE_ATTR_ENUMERABLE);
     787        2838 :         attrs_to_check.push_back(as2js::Node::attribute_t::NODE_ATTR_TRUE);
     788        2838 :         attrs_to_check.push_back(as2js::Node::attribute_t::NODE_ATTR_FALSE);
     789        2838 :         attrs_to_check.push_back(as2js::Node::attribute_t::NODE_ATTR_UNUSED);
     790        2838 :         attrs_to_check.push_back(as2js::Node::attribute_t::NODE_ATTR_DYNAMIC);
     791        2838 :         attrs_to_check.push_back(as2js::Node::attribute_t::NODE_ATTR_FOREACH);
     792        2838 :         attrs_to_check.push_back(as2js::Node::attribute_t::NODE_ATTR_NOBREAK);
     793        2838 :         attrs_to_check.push_back(as2js::Node::attribute_t::NODE_ATTR_AUTOBREAK);
     794        2838 :         attrs_to_check.push_back(as2js::Node::attribute_t::NODE_ATTR_DEFINED);
     795             :     }
     796             : 
     797        3682 :     CPPUNIT_ASSERT(attrs.size() <= attrs_to_check.size());
     798             : 
     799       77470 :     for(size_t idx(0); idx < attrs_to_check.size(); ++idx)
     800             :     {
     801       73788 :         as2js::Node::attribute_t attr(attrs_to_check[idx]);
     802       73788 :         std::vector<as2js::Node::attribute_t>::iterator it(std::find(attrs.begin(), attrs.end(), attr));
     803       73788 :         if(it == attrs.end())
     804             :         {
     805             :             // expected to be unset
     806       73788 :             if(verbose && node->get_attribute(attr))
     807             :             {
     808           0 :                 std::cerr << "*** Comparing attributes " << attribute_to_str(attr) << " (should not be set)\n";
     809             :             }
     810       73788 :             CPPUNIT_ASSERT(!node->get_attribute(attr));
     811             :         }
     812             :         else
     813             :         {
     814             :             // expected to be set
     815           0 :             attrs.erase(it);
     816           0 :             if(verbose && !node->get_attribute(attr))
     817             :             {
     818           0 :                 std::cerr << "*** Comparing attributes " << attribute_to_str(attr) << " (it should be set in this case)\n";
     819             :             }
     820           0 :             CPPUNIT_ASSERT(node->get_attribute(attr));
     821             :         }
     822             :     }
     823             : 
     824        7364 :     CPPUNIT_ASSERT(attrs.empty());
     825        3682 : }
     826             : 
     827             : 
     828             : 
     829             : 
     830        3682 : void verify_result(as2js::JSON::JSONValue::pointer_t expected, as2js::Node::pointer_t node, bool verbose)
     831             : {
     832        3682 :     as2js::String node_type_string;
     833        3682 :     node_type_string.from_utf8("node type");
     834        7364 :     as2js::String children_string;
     835        3682 :     children_string.from_utf8("children");
     836        7364 :     as2js::String link_strings[static_cast<int>(as2js::Node::link_t::LINK_max)];
     837        3682 :     link_strings[0].from_utf8("link instance");
     838        3682 :     link_strings[1].from_utf8("link type");
     839        3682 :     link_strings[2].from_utf8("link attributes");
     840        3682 :     link_strings[3].from_utf8("link goto exit");
     841        3682 :     link_strings[4].from_utf8("link goto enter");
     842        7364 :     as2js::String label_string;
     843        3682 :     label_string.from_utf8("label");
     844        7364 :     as2js::String flags_string;
     845        3682 :     flags_string.from_utf8("flags");
     846        7364 :     as2js::String attributes_string;
     847        3682 :     attributes_string.from_utf8("attributes");
     848        7364 :     as2js::String integer_string;
     849        3682 :     integer_string.from_utf8("integer");
     850        7364 :     as2js::String float_string;
     851        3682 :     float_string.from_utf8("float");
     852             : 
     853        3682 :     CPPUNIT_ASSERT(expected->get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_OBJECT);
     854        3682 :     as2js::JSON::JSONValue::object_t const& child_object(expected->get_object());
     855             : 
     856        3682 :     as2js::JSON::JSONValue::object_t::const_iterator it_node_type(child_object.find(node_type_string));
     857        3682 :     if(it_node_type == child_object.end())
     858             :     {
     859           0 :         std::cerr << "\nerror: \"node type\" is mandatory in your JSON.\n";
     860           0 :         exit(1);
     861             :     }
     862        7364 :     as2js::JSON::JSONValue::pointer_t node_type_value(it_node_type->second);
     863        3682 :     if(verbose || node->get_type_name() != node_type_value->get_string())
     864             :     {
     865          64 :         std::cerr << "*** Comparing " << node->get_type_name() << " (node) vs " << node_type_value->get_string() << " (JSON)\n";
     866             :     }
     867        3682 :     CPPUNIT_ASSERT(node->get_type_name() == node_type_value->get_string());
     868             : 
     869        3682 :     as2js::JSON::JSONValue::object_t::const_iterator it_label(child_object.find(label_string));
     870        3682 :     if(it_label != child_object.end())
     871             :     {
     872             :         // we expect a string in this object
     873         381 :         if(node->get_string() != it_label->second->get_string())
     874             :         {
     875           0 :             std::cerr << "   Expecting string \"" << it_label->second->get_string() << "\", node has \"" << node->get_string() << "\"\n";
     876             :         }
     877         381 :         CPPUNIT_ASSERT(node->get_string() == it_label->second->get_string());
     878             :     }
     879             :     else
     880             :     {
     881             :         // the node cannot have a string otherwise, so we expect a throw
     882        3301 :         CPPUNIT_ASSERT_THROW(node->get_string(), as2js::exception_internal_error);
     883             :     }
     884             : 
     885        3682 :     as2js::JSON::JSONValue::object_t::const_iterator it_flags(child_object.find(flags_string));
     886        3682 :     if(it_flags != child_object.end())
     887             :     {
     888             :         // the tester declared as set of flags that are expected to be set
     889           0 :         verify_flags(node, it_flags->second->get_string(), verbose);
     890             :     }
     891             :     else
     892             :     {
     893             :         // all flags must be unset
     894        3682 :         verify_flags(node, "", verbose);
     895             :     }
     896             : 
     897             :     // WARNING: these attributes are what we call IMMEDIATE ATTRIBUTES in case
     898             :     //          of the parser because the parser also makes use of a
     899             :     //          LINK_ATTRIBUTES which represents a list of attributes
     900        3682 :     as2js::JSON::JSONValue::object_t::const_iterator it_attributes(child_object.find(attributes_string));
     901        3682 :     if(it_attributes != child_object.end())
     902             :     {
     903             :         // the tester declared as set of attributes that are expected to be set
     904           0 :         verify_attributes(node, it_attributes->second->get_string(), verbose);
     905             :     }
     906             :     else
     907             :     {
     908             :         // all attributes must be unset
     909        3682 :         verify_attributes(node, "", verbose);
     910             :     }
     911             : 
     912        3682 :     as2js::JSON::JSONValue::object_t::const_iterator it_integer(child_object.find(integer_string));
     913        3682 :     if(it_integer != child_object.end())
     914             :     {
     915             :         // we expect an integer in this object
     916         283 :         if(node->get_int64().get() != it_integer->second->get_int64().get())
     917             :         {
     918           0 :             std::cerr << "   Expecting " << it_integer->second->get_int64().get() << ", got " << node->get_int64().get() << " in the node\n";
     919             :         }
     920         283 :         CPPUNIT_ASSERT(node->get_int64().get() == it_integer->second->get_int64().get());
     921             :     }
     922             :     else
     923             :     {
     924             :         // the node cannot have an integer otherwise, so we expect a throw
     925        3399 :         CPPUNIT_ASSERT_THROW(node->get_int64(), as2js::exception_internal_error);
     926             :     }
     927             : 
     928        3682 :     as2js::JSON::JSONValue::object_t::const_iterator it_float(child_object.find(float_string));
     929        3682 :     if(it_float != child_object.end())
     930             :     {
     931             :         // if we expect a NaN we have to compare specifically
     932             :         // because (NaN == NaN) always returns false
     933         391 :         if(it_float->second->get_float64().is_NaN())
     934             :         {
     935          74 :             CPPUNIT_ASSERT(node->get_float64().is_NaN());
     936             :         }
     937         317 :         else if(it_float->second->get_float64().is_positive_infinity())
     938             :         {
     939          89 :             CPPUNIT_ASSERT(node->get_float64().is_positive_infinity());
     940             :         }
     941         228 :         else if(it_float->second->get_float64().is_negative_infinity())
     942             :         {
     943           1 :             CPPUNIT_ASSERT(node->get_float64().is_negative_infinity());
     944             :         }
     945             :         else
     946             :         {
     947             :             // we expect a floating point in this object
     948         227 :             if(node->get_float64().get() - it_float->second->get_float64().get() > 0.0001)
     949             :             {
     950           0 :                 std::cerr << "   Expecting " << it_float->second->get_float64().get() << ", got " << node->get_float64().get() << " in the node\n";
     951             :             }
     952         227 :             CPPUNIT_ASSERT(node->get_float64().get() - it_float->second->get_float64().get() <= 0.0001);
     953             : 
     954             : #pragma GCC diagnostic push
     955             : #pragma GCC diagnostic ignored "-Wfloat-equal"
     956             :             // further, if the float is zero, it may be +0.0 or -0.0
     957         227 :             if(it_float->second->get_float64().get() == 0.0)
     958             :             {
     959          11 :                 CPPUNIT_ASSERT(std::signbit(node->get_float64().get()) == std::signbit(it_float->second->get_float64().get()));
     960             :             }
     961             : #pragma GCC diagnostic pop
     962             :         }
     963             :     }
     964             :     else
     965             :     {
     966             :         // the node cannot have a float otherwise, so we expect a throw
     967        3291 :         CPPUNIT_ASSERT_THROW(node->get_float64(), as2js::exception_internal_error);
     968             :     }
     969             : 
     970             :     // List of links are tested just like children, only the list starts somewhere else
     971       22092 :     for(int link_idx(0); link_idx < static_cast<int>(as2js::Node::link_t::LINK_max); ++link_idx)
     972             :     {
     973       18410 :         as2js::String link_name;
     974       18410 :         switch(static_cast<as2js::Node::link_t>(link_idx))
     975             :         {
     976             :         case as2js::Node::link_t::LINK_INSTANCE:
     977        3682 :             link_name = "instance";
     978        3682 :             break;
     979             : 
     980             :         case as2js::Node::link_t::LINK_TYPE:
     981        3682 :             link_name = "type";
     982        3682 :             break;
     983             : 
     984             :         case as2js::Node::link_t::LINK_ATTRIBUTES:
     985        3682 :             link_name = "attributes";
     986        3682 :             break;
     987             : 
     988             :         case as2js::Node::link_t::LINK_GOTO_EXIT:
     989        3682 :             link_name = "goto-exit";
     990        3682 :             break;
     991             : 
     992             :         case as2js::Node::link_t::LINK_GOTO_ENTER:
     993        3682 :             link_name = "goto-enter";
     994        3682 :             break;
     995             : 
     996             :         case as2js::Node::link_t::LINK_max:
     997           0 :             CPPUNIT_ASSERT(!"LINK_max reached when getting the link type");
     998           0 :             break;
     999             : 
    1000             :         }
    1001       18410 :         as2js::JSON::JSONValue::object_t::const_iterator it_link(child_object.find(link_strings[link_idx]));
    1002       18410 :         as2js::Node::pointer_t link_node(node->get_link(static_cast<as2js::Node::link_t>(link_idx)));
    1003       18410 :         if(link_node)
    1004             :         {
    1005             :             // make sure root node is of the right type
    1006           0 :             switch(static_cast<as2js::Node::link_t>(link_idx))
    1007             :             {
    1008             :             case as2js::Node::link_t::LINK_INSTANCE:
    1009           0 :                 CPPUNIT_ASSERT(!"optimizer does not use LINK_INSTANCE");
    1010           0 :                 break;
    1011             : 
    1012             :             case as2js::Node::link_t::LINK_TYPE:
    1013           0 :                 CPPUNIT_ASSERT(!"optimizer does not use LINK_TYPE");
    1014           0 :                 break;
    1015             : 
    1016             :             case as2js::Node::link_t::LINK_ATTRIBUTES:
    1017           0 :                 CPPUNIT_ASSERT(link_node->get_type() == as2js::Node::node_t::NODE_ATTRIBUTES);
    1018           0 :                 break;
    1019             : 
    1020             :             case as2js::Node::link_t::LINK_GOTO_EXIT:
    1021           0 :                 CPPUNIT_ASSERT(!"optimizer does not use LINK_GOTO_EXIT");
    1022           0 :                 break;
    1023             : 
    1024             :             case as2js::Node::link_t::LINK_GOTO_ENTER:
    1025           0 :                 CPPUNIT_ASSERT(!"optimizer does not use LINK_GOTO_ENTER");
    1026           0 :                 break;
    1027             : 
    1028             :             case as2js::Node::link_t::LINK_max:
    1029           0 :                 CPPUNIT_ASSERT(!"LINK_max reached when testing the link_node type");
    1030           0 :                 break;
    1031             : 
    1032             :             }
    1033             :         }
    1034       18410 :         if(it_link != child_object.end())
    1035             :         {
    1036             :             // the children value must be an array
    1037           0 :             as2js::JSON::JSONValue::array_t const& array(it_link->second->get_array());
    1038           0 :             size_t const max_links(array.size());
    1039           0 :             if(link_node)
    1040             :             {
    1041           0 :                 if(verbose && max_links != link_node->get_children_size())
    1042             :                 {
    1043           0 :                     std::cerr << "   Expecting " << max_links << " " << link_name << ", we have " << link_node->get_children_size() << " in the node\n";
    1044             :                 }
    1045           0 :                 CPPUNIT_ASSERT(max_links == link_node->get_children_size());
    1046           0 :                 for(size_t idx(0); idx < max_links; ++idx)
    1047             :                 {
    1048           0 :                     as2js::JSON::JSONValue::pointer_t link_value(array[idx]);
    1049           0 :                     verify_result(link_value, link_node->get_child(idx), verbose); // recursive
    1050           0 :                 }
    1051             :             }
    1052             :             else
    1053             :             {
    1054           0 :                 if(verbose && max_links != 0)
    1055             :                 {
    1056           0 :                     std::cerr << "   Expecting " << max_links << " " << link_name << ", we have no " << link_name << " at all in the node\n";
    1057             :                 }
    1058           0 :                 CPPUNIT_ASSERT(max_links == 0);
    1059             :             }
    1060             :         }
    1061             :         else
    1062             :         {
    1063             :             // no children defined in the JSON, no children expected in the node
    1064       18410 :             if(verbose && link_node && link_node->get_children_size() != 0)
    1065             :             {
    1066           0 :                 std::cerr << "   Expecting no " << link_name << " list, we have " << link_node->get_children_size() << " " << link_name << " in the node\n";
    1067             :             }
    1068       18410 :             CPPUNIT_ASSERT(!link_node || link_node->get_children_size() == 0);
    1069             :         }
    1070       18410 :     }
    1071             : 
    1072        3682 :     as2js::JSON::JSONValue::object_t::const_iterator it_children(child_object.find(children_string));
    1073        3682 :     if(it_children != child_object.end())
    1074             :     {
    1075             :         // the children value must be an array
    1076        2349 :         as2js::JSON::JSONValue::array_t const& array(it_children->second->get_array());
    1077        2349 :         size_t const max_children(array.size());
    1078        2349 :         if(verbose && max_children != node->get_children_size())
    1079             :         {
    1080           0 :             std::cerr << "   Expecting " << max_children << " children, we have " << node->get_children_size() << " in the node\n";
    1081             :         }
    1082        2349 :         CPPUNIT_ASSERT(max_children == node->get_children_size());
    1083        5187 :         for(size_t idx(0); idx < max_children; ++idx)
    1084             :         {
    1085        2838 :             as2js::JSON::JSONValue::pointer_t children_value(array[idx]);
    1086        2838 :             verify_result(children_value, node->get_child(idx), verbose); // recursive
    1087        2838 :         }
    1088             :     }
    1089             :     else
    1090             :     {
    1091             :         // no children defined in the JSON, no children expected in the node
    1092        1333 :         if(verbose && node->get_children_size() != 0)
    1093             :         {
    1094           0 :             std::cerr << "   Expecting no children, we have " << node->get_children_size() << " in the node\n";
    1095             :         }
    1096        1333 :         CPPUNIT_ASSERT(node->get_children_size() == 0);
    1097        3682 :     }
    1098        3682 : }
    1099             : 
    1100             : 
    1101             : //
    1102             : // JSON data used to test the optimizer, most of the work is in this table
    1103             : // these are long JSON strings! It is actually generated using the
    1104             : // json_to_string tool and the test_as2js_optimizer_*.json source files.
    1105             : //
    1106             : // Note: the top entries are arrays so we can execute programs in the
    1107             : //       order we define them...
    1108             : //
    1109             : char const g_optimizer_additive[] =
    1110             : #include "test_as2js_optimizer_additive.ci"
    1111             : ;
    1112             : char const g_optimizer_assignments[] =
    1113             : #include "test_as2js_optimizer_assignments.ci"
    1114             : ;
    1115             : char const g_optimizer_bitwise[] =
    1116             : #include "test_as2js_optimizer_bitwise.ci"
    1117             : ;
    1118             : char const g_optimizer_compare[] =
    1119             : #include "test_as2js_optimizer_compare.ci"
    1120             : ;
    1121             : char const g_optimizer_conditional[] =
    1122             : #include "test_as2js_optimizer_conditional.ci"
    1123             : ;
    1124             : char const g_optimizer_equality[] =
    1125             : #include "test_as2js_optimizer_equality.ci"
    1126             : ;
    1127             : char const g_optimizer_logical[] =
    1128             : #include "test_as2js_optimizer_logical.ci"
    1129             : ;
    1130             : char const g_optimizer_match[] =
    1131             : #include "test_as2js_optimizer_match.ci"
    1132             : ;
    1133             : char const g_optimizer_multiplicative[] =
    1134             : #include "test_as2js_optimizer_multiplicative.ci"
    1135             : ;
    1136             : char const g_optimizer_relational[] =
    1137             : #include "test_as2js_optimizer_relational.ci"
    1138             : ;
    1139             : char const g_optimizer_statements[] =
    1140             : #include "test_as2js_optimizer_statements.ci"
    1141             : ;
    1142             : 
    1143             : 
    1144             : 
    1145             : 
    1146             : 
    1147             : 
    1148             : 
    1149             : 
    1150             : // This function runs all the tests defined in the
    1151             : // string 'data'
    1152          10 : void run_tests(char const *data, char const *filename)
    1153             : {
    1154          10 :     as2js::String input_data;
    1155          10 :     input_data.from_utf8(data);
    1156             : 
    1157          10 :     if(as2js_test::g_save_parser_tests)
    1158             :     {
    1159           0 :         std::ofstream json_file;
    1160           0 :         json_file.open(filename);
    1161           0 :         CPPUNIT_ASSERT(json_file.is_open());
    1162           0 :         json_file << "// To properly indent this JSON you may use http://json-indent.appspot.com/"
    1163           0 :                 << std::endl << data << std::endl;
    1164             :     }
    1165             : 
    1166          20 :     as2js::StringInput::pointer_t in(new as2js::StringInput(input_data));
    1167          20 :     as2js::JSON::pointer_t json_data(new as2js::JSON);
    1168          20 :     as2js::JSON::JSONValue::pointer_t json(json_data->parse(in));
    1169             : 
    1170             :     // verify that the optimizer() did not fail
    1171          10 :     CPPUNIT_ASSERT(!!json);
    1172          10 :     CPPUNIT_ASSERT(json->get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_ARRAY);
    1173             : 
    1174          20 :     as2js::String name_string;
    1175          10 :     name_string.from_utf8("name");
    1176          20 :     as2js::String program_string;
    1177          10 :     program_string.from_utf8("program");
    1178          20 :     as2js::String verbose_string;
    1179          10 :     verbose_string.from_utf8("verbose");
    1180          20 :     as2js::String slow_string;
    1181          10 :     slow_string.from_utf8("slow");
    1182          20 :     as2js::String parser_result_string;
    1183          10 :     parser_result_string.from_utf8("parser result");
    1184          20 :     as2js::String optimizer_result_string;
    1185          10 :     optimizer_result_string.from_utf8("optimizer result");
    1186          20 :     as2js::String expected_messages_string;
    1187          10 :     expected_messages_string.from_utf8("expected messages");
    1188             : 
    1189          10 :     std::cout << "\n";
    1190             : 
    1191          10 :     as2js::JSON::JSONValue::array_t const& array(json->get_array());
    1192          10 :     size_t const max_programs(array.size());
    1193         432 :     for(size_t idx(0); idx < max_programs; ++idx)
    1194             :     {
    1195         422 :         as2js::JSON::JSONValue::pointer_t prog_obj(array[idx]);
    1196         422 :         CPPUNIT_ASSERT(prog_obj->get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_OBJECT);
    1197         422 :         as2js::JSON::JSONValue::object_t const& prog(prog_obj->get_object());
    1198             : 
    1199         422 :         bool verbose(false);
    1200         422 :         as2js::JSON::JSONValue::object_t::const_iterator verbose_it(prog.find(verbose_string));
    1201         422 :         if(verbose_it != prog.end())
    1202             :         {
    1203           5 :             verbose = verbose_it->second->get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_TRUE;
    1204             :         }
    1205             : 
    1206         422 :         bool slow(false);
    1207         422 :         as2js::JSON::JSONValue::object_t::const_iterator slow_it(prog.find(slow_string));
    1208         422 :         if(slow_it != prog.end())
    1209             :         {
    1210           0 :             slow = slow_it->second->get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_TRUE;
    1211             :         }
    1212             : 
    1213             :         // got a program, try to compile it with all the possible options
    1214         844 :         as2js::JSON::JSONValue::pointer_t name(prog.find(name_string)->second);
    1215         422 :         std::cout << "  -- working on \"" << name->get_string() << "\" " << (slow ? "" : "...") << std::flush;
    1216             : 
    1217             :         {
    1218         422 :             as2js::JSON::JSONValue::pointer_t program_value(prog.find(program_string)->second);
    1219         844 :             as2js::String program_source(program_value->get_string());
    1220             : //std::cerr << "prog = [" << program_source << "]\n";
    1221         844 :             as2js::StringInput::pointer_t prog_text(new as2js::StringInput(program_source));
    1222         844 :             as2js::Options::pointer_t options(new as2js::Options);
    1223         844 :             as2js::Parser::pointer_t parser(new as2js::Parser(prog_text, options));
    1224             : 
    1225         844 :             test_callback tc(verbose);
    1226             : 
    1227             :             // no errors exepected while parsing (if you want to test errors
    1228             :             // in the parser, use the test_as2js_parser.cpp test instead)
    1229         844 :             as2js::Node::pointer_t root(parser->parse());
    1230             : 
    1231             :             // verify the parser result, that way we can make sure we are
    1232             :             // testing the tree we want to test in the optimizer
    1233         422 :             verify_result(prog.find(parser_result_string)->second, root, verbose);
    1234             : 
    1235             :             // now the optimizer may end up generating messages...
    1236             :             // (there are not many, mainly things like division by zero
    1237             :             // and illegal operation.)
    1238         422 :             as2js::JSON::JSONValue::object_t::const_iterator expected_msg_it(prog.find(expected_messages_string));
    1239         422 :             if(expected_msg_it != prog.end())
    1240             :             {
    1241             : 
    1242             :                 // the expected messages value must be an array
    1243          14 :                 as2js::JSON::JSONValue::array_t const& msg_array(expected_msg_it->second->get_array());
    1244          14 :                 size_t const max_msgs(msg_array.size());
    1245          28 :                 for(size_t j(0); j < max_msgs; ++j)
    1246             :                 {
    1247          14 :                     as2js::JSON::JSONValue::pointer_t message_value(msg_array[j]);
    1248          14 :                     as2js::JSON::JSONValue::object_t const& message(message_value->get_object());
    1249             : 
    1250          14 :                     as2js::JSON::JSONValue::object_t::const_iterator const message_options_iterator(message.find("options"));
    1251          14 :                     if(message_options_iterator != message.end())
    1252             :                     {
    1253             : //{
    1254             : //as2js::JSON::JSONValue::object_t::const_iterator line_it(message.find("line #"));
    1255             : //if(line_it != message.end())
    1256             : //{
    1257             : //    int64_t lines(line_it->second->get_int64().get());
    1258             : //std::cerr << "_________\nLine #" << lines << "\n";
    1259             : //}
    1260             : //else
    1261             : //std::cerr << "_________\nLine #<undefined>\n";
    1262             : //}
    1263          14 :                         test_callback::expected_t expected;
    1264          14 :                         expected.f_message_level = static_cast<as2js::message_level_t>(message.find("message level")->second->get_int64().get());
    1265          14 :                         expected.f_error_code = str_to_error_code(message.find("error code")->second->get_string());
    1266          14 :                         expected.f_pos.set_filename("unknown-file");
    1267          14 :                         as2js::JSON::JSONValue::object_t::const_iterator func_it(message.find("function name"));
    1268          14 :                         if(func_it == message.end())
    1269             :                         {
    1270          14 :                             expected.f_pos.set_function("unknown-func");
    1271             :                         }
    1272             :                         else
    1273             :                         {
    1274           0 :                             expected.f_pos.set_function(func_it->second->get_string());
    1275             :                         }
    1276          14 :                         as2js::JSON::JSONValue::object_t::const_iterator line_it(message.find("line #"));
    1277          14 :                         if(line_it != message.end())
    1278             :                         {
    1279          14 :                             int64_t lines(line_it->second->get_int64().get());
    1280          14 :                             for(int64_t l(1); l < lines; ++l)
    1281             :                             {
    1282           0 :                                 expected.f_pos.new_line();
    1283             :                             }
    1284             :                         }
    1285          14 :                         expected.f_message = message.find("message")->second->get_string();
    1286          14 :                         tc.f_expected.push_back(expected);
    1287             :                     }
    1288          14 :                 }
    1289             :             }
    1290             : 
    1291             :             // run the optimizer
    1292         422 :             as2js::Optimizer::optimize(root);
    1293             : 
    1294         422 :             tc.got_called();
    1295             : 
    1296             :             // the result is object which can have children
    1297             :             // which are represented by an array of objects
    1298         844 :             verify_result(prog.find(optimizer_result_string)->second, root, verbose);
    1299             :         }
    1300             : 
    1301         422 :         std::cout << " OK\n";
    1302         432 :     }
    1303          10 : }
    1304             : 
    1305             : 
    1306             : }
    1307             : // no name namespace
    1308             : 
    1309             : 
    1310             : 
    1311             : 
    1312             : 
    1313           1 : void As2JsOptimizerUnitTests::test_optimizer_invalid_nodes()
    1314             : {
    1315             :     // empty node does nothing, return false
    1316             :     {
    1317           1 :         as2js::Node::pointer_t node;
    1318           1 :         CPPUNIT_ASSERT(!as2js::Optimizer::optimize(node));
    1319             :     }
    1320             : 
    1321             :     // unknown node does nothing, return false
    1322             :     {
    1323           1 :         as2js::Node::pointer_t node(new as2js::Node(as2js::Node::node_t::NODE_UNKNOWN));
    1324           1 :         CPPUNIT_ASSERT(!as2js::Optimizer::optimize(node));
    1325           1 :         CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_UNKNOWN);
    1326           1 :         CPPUNIT_ASSERT(node->get_children_size() == 0);
    1327             :     }
    1328             : 
    1329             :     // a special case where an optimization occurs on a node without a parent
    1330             :     // (something that should not occur in a real tree)
    1331             :     {
    1332             :         // ADD
    1333             :         //   INT64 = 3
    1334             :         //   INT64 = 20
    1335           1 :         as2js::Node::pointer_t node_add(new as2js::Node(as2js::Node::node_t::NODE_ADD));
    1336             : 
    1337           2 :         as2js::Node::pointer_t node_three(new as2js::Node(as2js::Node::node_t::NODE_INT64));
    1338           1 :         as2js::Int64 three;
    1339           1 :         three.set(3);
    1340           1 :         node_three->set_int64(three);
    1341           1 :         node_add->append_child(node_three);
    1342             : 
    1343           2 :         as2js::Node::pointer_t node_twenty(new as2js::Node(as2js::Node::node_t::NODE_INT64));
    1344           1 :         as2js::Int64 twenty;
    1345           1 :         twenty.set(20);
    1346           1 :         node_twenty->set_int64(twenty);
    1347           1 :         node_add->append_child(node_twenty);
    1348             : 
    1349             :         // optimization does not happen
    1350           1 :         CPPUNIT_ASSERT_THROW(!as2js::Optimizer::optimize(node_add), as2js::exception_internal_error);
    1351             : 
    1352             :         // verify that nothing changed
    1353           1 :         CPPUNIT_ASSERT(node_add->get_type() == as2js::Node::node_t::NODE_ADD);
    1354           1 :         CPPUNIT_ASSERT(node_add->get_children_size() == 2);
    1355           1 :         CPPUNIT_ASSERT(node_three->get_type() == as2js::Node::node_t::NODE_INT64);
    1356           1 :         CPPUNIT_ASSERT(node_three->get_children_size() == 0);
    1357           1 :         CPPUNIT_ASSERT(node_three->get_int64().compare(three) == as2js::compare_t::COMPARE_EQUAL);
    1358           1 :         CPPUNIT_ASSERT(node_twenty->get_type() == as2js::Node::node_t::NODE_INT64);
    1359           1 :         CPPUNIT_ASSERT(node_twenty->get_children_size() == 0);
    1360           2 :         CPPUNIT_ASSERT(node_twenty->get_int64().compare(twenty) == as2js::compare_t::COMPARE_EQUAL);
    1361             :     }
    1362           1 : }
    1363             : 
    1364             : 
    1365           1 : void As2JsOptimizerUnitTests::test_optimizer_additive()
    1366             : {
    1367           1 :     run_tests(g_optimizer_additive, "test_optimizer_additive.json");
    1368           1 : }
    1369             : 
    1370           1 : void As2JsOptimizerUnitTests::test_optimizer_assignments()
    1371             : {
    1372           1 :     run_tests(g_optimizer_assignments, "test_optimizer_assignments.json");
    1373           1 : }
    1374             : 
    1375           1 : void As2JsOptimizerUnitTests::test_optimizer_bitwise()
    1376             : {
    1377           1 :     run_tests(g_optimizer_bitwise, "test_optimizer_bitwise.json");
    1378           1 : }
    1379             : 
    1380           1 : void As2JsOptimizerUnitTests::test_optimizer_compare()
    1381             : {
    1382           1 :     run_tests(g_optimizer_compare, "test_optimizer_compare.json");
    1383           1 : }
    1384             : 
    1385           1 : void As2JsOptimizerUnitTests::test_optimizer_conditional()
    1386             : {
    1387           1 :     run_tests(g_optimizer_conditional, "test_optimizer_conditional.json");
    1388           1 : }
    1389             : 
    1390           1 : void As2JsOptimizerUnitTests::test_optimizer_equality()
    1391             : {
    1392           1 :     run_tests(g_optimizer_equality, "test_optimizer_equality.json");
    1393           1 : }
    1394             : 
    1395           1 : void As2JsOptimizerUnitTests::test_optimizer_logical()
    1396             : {
    1397           1 :     run_tests(g_optimizer_logical, "test_optimizer_logical.json");
    1398           1 : }
    1399             : 
    1400           1 : void As2JsOptimizerUnitTests::test_optimizer_match()
    1401             : {
    1402             : // regex is not well supported before 4.9.0
    1403             : #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
    1404             :     run_tests(g_optimizer_match, "test_optimizer_match.json");
    1405             : #else
    1406           1 :     std::cerr << " -- warning: test As2JsOptimizerUnitTests::test_optimizer_match() skip since you are compiling with a g++ version prior to 4.9.0" << std::endl;
    1407             : #endif
    1408           1 : }
    1409             : 
    1410           1 : void As2JsOptimizerUnitTests::test_optimizer_multiplicative()
    1411             : {
    1412           1 :     run_tests(g_optimizer_multiplicative, "test_optimizer_multiplicative.json");
    1413           1 : }
    1414             : 
    1415           1 : void As2JsOptimizerUnitTests::test_optimizer_relational()
    1416             : {
    1417           1 :     run_tests(g_optimizer_relational, "test_optimizer_relational.json");
    1418           1 : }
    1419             : 
    1420           1 : void As2JsOptimizerUnitTests::test_optimizer_statements()
    1421             : {
    1422           1 :     run_tests(g_optimizer_statements, "test_optimizer_statements.json");
    1423          13 : }
    1424             : 
    1425             : 
    1426             : 
    1427             : 
    1428             : 
    1429             : 
    1430             : 
    1431             : 
    1432             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.10