LCOV - code coverage report
Current view: top level - tests - test_as2js_node.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1292 1305 99.0 %
Date: 2014-11-22 Functions: 15 15 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* test_as2js_node.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_node.h"
      37             : #include    "test_as2js_main.h"
      38             : 
      39             : #include    "as2js/node.h"
      40             : #include    "as2js/message.h"
      41             : #include    "as2js/exceptions.h"
      42             : 
      43             : #include    <cstring>
      44             : #include    <algorithm>
      45             : #include    <iomanip>
      46             : 
      47             : #include    <cppunit/config/SourcePrefix.h>
      48           4 : CPPUNIT_TEST_SUITE_REGISTRATION( As2JsNodeUnitTests );
      49             : 
      50             : 
      51             : #include "test_as2js_node_data.ci"
      52             : 
      53             : 
      54           1 : void As2JsNodeUnitTests::test_type()
      55             : {
      56             :     // test all the different types available
      57           1 :     std::bitset<static_cast<size_t>(as2js::Node::node_t::NODE_max)> valid_types;
      58         171 :     for(size_t i(0); i < g_node_types_size; ++i)
      59             :     {
      60             :         // define the type
      61         170 :         as2js::Node::node_t const node_type(g_node_types[i].f_type);
      62             : 
      63         170 :         if(static_cast<size_t>(node_type) > static_cast<size_t>(as2js::Node::node_t::NODE_max))
      64             :         {
      65           1 :             if(node_type != as2js::Node::node_t::NODE_EOF)
      66             :             {
      67           0 :                 std::cerr << "Somehow a node type (" << static_cast<int>(node_type)
      68           0 :                           << ") is larger than the maximum allowed ("
      69           0 :                           << static_cast<int>(as2js::Node::node_t::NODE_max) << ")" << std::endl;
      70             :             }
      71             :         }
      72             :         else
      73             :         {
      74         169 :             valid_types[static_cast<size_t>(node_type)] = true;
      75             :         }
      76             : 
      77             :         // get the next type of node
      78         170 :         as2js::Node::pointer_t node(new as2js::Node(node_type));
      79             : 
      80             :         // check the type
      81         170 :         CPPUNIT_ASSERT(node->get_type() == node_type);
      82             : 
      83             :         // get the name
      84         170 :         char const *name(node->get_type_name());
      85             : //std::cerr << "type = " << static_cast<int>(node_type) << " / " << name << "\n";
      86         170 :         CPPUNIT_ASSERT(strcmp(name, g_node_types[i].f_name) == 0);
      87             : 
      88             :         // test functions determining general types
      89         170 :         CPPUNIT_ASSERT(node->is_number() == false || node->is_number() == true);
      90         170 :         CPPUNIT_ASSERT(static_cast<as2js::Node const *>(node.get())->is_number() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_NUMBER) == 0));
      91             : 
      92             :         // This NaN test is not sufficient for strings
      93         170 :         CPPUNIT_ASSERT(node->is_nan() == false || node->is_nan() == true);
      94         170 :         CPPUNIT_ASSERT(static_cast<as2js::Node const *>(node.get())->is_nan() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_NAN) == 0));
      95             : 
      96         170 :         CPPUNIT_ASSERT(node->is_int64() == false || node->is_int64() == true);
      97         170 :         CPPUNIT_ASSERT(static_cast<as2js::Node const *>(node.get())->is_int64() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_INT64) == 0));
      98             : 
      99         170 :         CPPUNIT_ASSERT(node->is_float64() == false || node->is_float64() == true);
     100         170 :         CPPUNIT_ASSERT(static_cast<as2js::Node const *>(node.get())->is_float64() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_FLOAT64) == 0));
     101             : 
     102         170 :         CPPUNIT_ASSERT(node->is_boolean() == false || node->is_boolean() == true);
     103         170 :         CPPUNIT_ASSERT(static_cast<as2js::Node const *>(node.get())->is_boolean() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_BOOLEAN) == 0));
     104             : 
     105         170 :         CPPUNIT_ASSERT(node->is_true() == false || node->is_true() == true);
     106         170 :         CPPUNIT_ASSERT(static_cast<as2js::Node const *>(node.get())->is_true() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_TRUE) == 0));
     107             : 
     108         170 :         CPPUNIT_ASSERT(node->is_false() == false || node->is_false() == true);
     109         170 :         CPPUNIT_ASSERT(static_cast<as2js::Node const *>(node.get())->is_false() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_FALSE) == 0));
     110             : 
     111         170 :         CPPUNIT_ASSERT(node->is_string() == false || node->is_string() == true);
     112         170 :         CPPUNIT_ASSERT(static_cast<as2js::Node const *>(node.get())->is_string() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_STRING) == 0));
     113             : 
     114         170 :         CPPUNIT_ASSERT(node->is_undefined() == false || node->is_undefined() == true);
     115         170 :         CPPUNIT_ASSERT(static_cast<as2js::Node const *>(node.get())->is_undefined() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_UNDEFINED) == 0));
     116             : 
     117         170 :         CPPUNIT_ASSERT(node->is_null() == false || node->is_null() == true);
     118         170 :         CPPUNIT_ASSERT(static_cast<as2js::Node const *>(node.get())->is_null() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_NULL) == 0));
     119             : 
     120         170 :         CPPUNIT_ASSERT(node->is_identifier() == false || node->is_identifier() == true);
     121         170 :         CPPUNIT_ASSERT(static_cast<as2js::Node const *>(node.get())->is_identifier() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_IDENTIFIER) == 0));
     122             : 
     123         170 :         CPPUNIT_ASSERT(node->is_literal() == false || node->is_literal() == true);
     124         340 :         CPPUNIT_ASSERT(static_cast<as2js::Node const *>(node.get())->is_literal() ^ ((g_node_types[i].f_flags & (
     125             :                                                                                           TEST_NODE_IS_INT64
     126             :                                                                                         | TEST_NODE_IS_FLOAT64
     127             :                                                                                         | TEST_NODE_IS_TRUE
     128             :                                                                                         | TEST_NODE_IS_FALSE
     129             :                                                                                         | TEST_NODE_IS_STRING
     130             :                                                                                         | TEST_NODE_IS_UNDEFINED
     131         170 :                                                                                         | TEST_NODE_IS_NULL)) == 0));
     132             : 
     133         170 :         if(!node->is_literal())
     134             :         {
     135         163 :             as2js::Node::pointer_t literal(new as2js::Node(as2js::Node::node_t::NODE_STRING));
     136         163 :             CPPUNIT_ASSERT(as2js::Node::compare(node, literal, as2js::Node::compare_mode_t::COMPARE_STRICT)  == as2js::compare_t::COMPARE_ERROR);
     137         163 :             CPPUNIT_ASSERT(as2js::Node::compare(node, literal, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_ERROR);
     138         163 :             CPPUNIT_ASSERT(as2js::Node::compare(node, literal, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_ERROR);
     139         163 :             CPPUNIT_ASSERT(as2js::Node::compare(literal, node, as2js::Node::compare_mode_t::COMPARE_STRICT)  == as2js::compare_t::COMPARE_ERROR);
     140         163 :             CPPUNIT_ASSERT(as2js::Node::compare(literal, node, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_ERROR);
     141         163 :             CPPUNIT_ASSERT(as2js::Node::compare(literal, node, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_ERROR);
     142         163 :             CPPUNIT_ASSERT(as2js::Node::compare(literal, node, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_ERROR);
     143             :         }
     144             : 
     145         170 :         CPPUNIT_ASSERT(node->has_side_effects() == false || node->has_side_effects() == true);
     146         170 :         CPPUNIT_ASSERT(static_cast<as2js::Node const *>(node.get())->has_side_effects() ^ ((g_node_types[i].f_flags & TEST_NODE_HAS_SIDE_EFFECTS) == 0));
     147             : 
     148         170 :         if(g_node_types[i].f_operator != nullptr)
     149             :         {
     150          58 :             char const *op(as2js::Node::operator_to_string(g_node_types[i].f_type));
     151          58 :             CPPUNIT_ASSERT(op != nullptr);
     152          58 :             CPPUNIT_ASSERT(strcmp(g_node_types[i].f_operator, op) == 0);
     153             :             //std::cerr << " testing " << node->get_type_name() << " from " << op << std::endl;
     154          58 :             CPPUNIT_ASSERT(as2js::Node::string_to_operator(op) == g_node_types[i].f_type);
     155             : 
     156             :             // check the special case for not equal
     157          58 :             if(strcmp(g_node_types[i].f_operator, "!=") == 0)
     158             :             {
     159           1 :                 CPPUNIT_ASSERT(as2js::Node::string_to_operator("<>") == g_node_types[i].f_type);
     160             :             }
     161             : 
     162             :             // check the special case for assignment
     163          58 :             if(strcmp(g_node_types[i].f_operator, "=") == 0)
     164             :             {
     165           1 :                 CPPUNIT_ASSERT(as2js::Node::string_to_operator(":=") == g_node_types[i].f_type);
     166             :             }
     167             :         }
     168             :         else
     169             :         {
     170             :             // static function can also be called from the node pointer
     171             :             //std::cerr << " testing " << node->get_type_name() << std::endl;
     172         112 :             CPPUNIT_ASSERT(node->operator_to_string(g_node_types[i].f_type) == nullptr);
     173         112 :             CPPUNIT_ASSERT(as2js::Node::string_to_operator(node->get_type_name()) == as2js::Node::node_t::NODE_UNKNOWN);
     174             :         }
     175             : 
     176         170 :         if((g_node_types[i].f_flags & TEST_NODE_IS_SWITCH_OPERATOR) == 0)
     177             :         {
     178             :             // only NODE_PARAM_MATCH accepts this call
     179         155 :             as2js::Node::pointer_t node_switch(new as2js::Node(as2js::Node::node_t::NODE_SWITCH));
     180         155 :             CPPUNIT_ASSERT_THROW(node_switch->set_switch_operator(node_type), as2js::exception_internal_error);
     181             :         }
     182             :         else
     183             :         {
     184          15 :             as2js::Node::pointer_t node_switch(new as2js::Node(as2js::Node::node_t::NODE_SWITCH));
     185          15 :             node_switch->set_switch_operator(node_type);
     186          15 :             CPPUNIT_ASSERT(node_switch->get_switch_operator() == node_type);
     187             :         }
     188         170 :         if(node_type != as2js::Node::node_t::NODE_SWITCH)
     189             :         {
     190             :             // a valid operator, but not a valid node to set
     191         169 :             CPPUNIT_ASSERT_THROW(node->set_switch_operator(as2js::Node::node_t::NODE_STRICTLY_EQUAL), as2js::exception_internal_error);
     192             :             // not a valid node to get
     193         169 :             CPPUNIT_ASSERT_THROW(node->get_switch_operator(), as2js::exception_internal_error);
     194             :         }
     195             : 
     196         170 :         if((g_node_types[i].f_flags & TEST_NODE_IS_PARAM_MATCH) == 0)
     197             :         {
     198             :             // only NODE_PARAM_MATCH accepts this call
     199         169 :             CPPUNIT_ASSERT_THROW(node->set_param_size(10), as2js::exception_internal_error);
     200             :         }
     201             :         else
     202             :         {
     203             :             // zero is not acceptable
     204           1 :             CPPUNIT_ASSERT_THROW(node->set_param_size(0), as2js::exception_internal_error);
     205             :             // this one is accepted
     206           1 :             node->set_param_size(10);
     207             :             // cannot change the size once set
     208           1 :             CPPUNIT_ASSERT_THROW(node->set_param_size(10), as2js::exception_internal_error);
     209             :         }
     210             : 
     211         170 :         if((g_node_types[i].f_flags & TEST_NODE_IS_BOOLEAN) == 0)
     212             :         {
     213         168 :             CPPUNIT_ASSERT_THROW(node->get_boolean(), as2js::exception_internal_error);
     214         168 :             CPPUNIT_ASSERT_THROW(node->set_boolean(rand() & 1), as2js::exception_internal_error);
     215             :         }
     216           2 :         else if((g_node_types[i].f_flags & TEST_NODE_IS_TRUE) != 0)
     217             :         {
     218           1 :             CPPUNIT_ASSERT(node->get_boolean());
     219             :         }
     220             :         else
     221             :         {
     222           1 :             CPPUNIT_ASSERT(!node->get_boolean());
     223             :         }
     224             : 
     225         170 :         if((g_node_types[i].f_flags & TEST_NODE_IS_INT64) == 0)
     226             :         {
     227         169 :             CPPUNIT_ASSERT_THROW(node->get_int64(), as2js::exception_internal_error);
     228         169 :             as2js::Int64 random(rand());
     229         169 :             CPPUNIT_ASSERT_THROW(node->set_int64(random), as2js::exception_internal_error);
     230             :         }
     231             : 
     232         170 :         if((g_node_types[i].f_flags & TEST_NODE_IS_FLOAT64) == 0)
     233             :         {
     234         169 :             CPPUNIT_ASSERT_THROW(node->get_float64(), as2js::exception_internal_error);
     235         169 :             as2js::Float64 random(rand());
     236         169 :             CPPUNIT_ASSERT_THROW(node->set_float64(random), as2js::exception_internal_error);
     237             :         }
     238             : 
     239             :         // here we have a special case as "many" different nodes accept
     240             :         // a string to represent one thing or another
     241         170 :         if((g_node_types[i].f_flags & TEST_NODE_ACCEPT_STRING) == 0)
     242             :         {
     243         151 :             CPPUNIT_ASSERT_THROW(node->get_string(), as2js::exception_internal_error);
     244         151 :             CPPUNIT_ASSERT_THROW(node->set_string("test"), as2js::exception_internal_error);
     245             :         }
     246             :         else
     247             :         {
     248          19 :             node->set_string("random test");
     249          19 :             CPPUNIT_ASSERT(node->get_string() == "random test");
     250             :         }
     251             : 
     252             :         // first test the flags that this type of node accepts
     253         170 :         std::bitset<static_cast<int>(as2js::Node::flag_t::NODE_FLAG_max)> valid_flags;
     254         454 :         for(flags_per_node_t const *node_flags(g_node_types[i].f_node_flags);
     255         227 :                                     node_flags->f_flag != as2js::Node::flag_t::NODE_FLAG_max;
     256             :                                     ++node_flags)
     257             :         {
     258             :             // mark this specific flag as valid
     259          57 :             valid_flags[static_cast<int>(node_flags->f_flag)] = true;
     260             : 
     261          57 :             as2js::Node::flag_set_t set;
     262          57 :             CPPUNIT_ASSERT(node->compare_all_flags(set));
     263             : 
     264             : 
     265             :             // before we set it, always false
     266          57 :             CPPUNIT_ASSERT(!node->get_flag(node_flags->f_flag));
     267          57 :             node->set_flag(node_flags->f_flag, true);
     268          57 :             CPPUNIT_ASSERT(node->get_flag(node_flags->f_flag));
     269             : 
     270          57 :             CPPUNIT_ASSERT(!node->compare_all_flags(set));
     271          57 :             set[static_cast<int>(node_flags->f_flag)] = true;
     272          57 :             CPPUNIT_ASSERT(node->compare_all_flags(set));
     273             : 
     274          57 :             node->set_flag(node_flags->f_flag, false);
     275          57 :             CPPUNIT_ASSERT(!node->get_flag(node_flags->f_flag));
     276             :         }
     277             : 
     278             :         // now test all the other flags
     279        9180 :         for(int j(-5); j <= static_cast<int>(as2js::Node::flag_t::NODE_FLAG_max) + 5; ++j)
     280             :         {
     281       19890 :             if(j < 0
     282        8160 :             || j >= static_cast<int>(as2js::Node::flag_t::NODE_FLAG_max)
     283       32300 :             || !valid_flags[j])
     284             :             {
     285        8953 :                 CPPUNIT_ASSERT_THROW(node->get_flag(static_cast<as2js::Node::flag_t>(j)), as2js::exception_internal_error);
     286        8953 :                 CPPUNIT_ASSERT_THROW(node->set_flag(static_cast<as2js::Node::flag_t>(j), true), as2js::exception_internal_error);
     287        8953 :                 CPPUNIT_ASSERT_THROW(node->set_flag(static_cast<as2js::Node::flag_t>(j), false), as2js::exception_internal_error);
     288             :             }
     289             :         }
     290             : 
     291             :         // test completely invalid attribute indices
     292        1020 :         for(int j(-5); j < 0; ++j)
     293             :         {
     294         850 :             CPPUNIT_ASSERT_THROW(node->get_attribute(static_cast<as2js::Node::attribute_t>(j)), as2js::exception_internal_error);
     295         850 :             CPPUNIT_ASSERT_THROW(node->set_attribute(static_cast<as2js::Node::attribute_t>(j), true), as2js::exception_internal_error);
     296         850 :             CPPUNIT_ASSERT_THROW(node->set_attribute(static_cast<as2js::Node::attribute_t>(j), false), as2js::exception_internal_error);
     297         850 :             CPPUNIT_ASSERT_THROW(node->attribute_to_string(static_cast<as2js::Node::attribute_t>(j)), as2js::exception_internal_error);
     298         850 :             CPPUNIT_ASSERT_THROW(as2js::Node::attribute_to_string(static_cast<as2js::Node::attribute_t>(j)), as2js::exception_internal_error);
     299             :         }
     300        1190 :         for(int j(static_cast<int>(as2js::Node::attribute_t::NODE_ATTR_max));
     301             :                 j <= static_cast<int>(as2js::Node::attribute_t::NODE_ATTR_max) + 5;
     302             :                 ++j)
     303             :         {
     304        1020 :             CPPUNIT_ASSERT_THROW(node->get_attribute(static_cast<as2js::Node::attribute_t>(j)), as2js::exception_internal_error);
     305        1020 :             CPPUNIT_ASSERT_THROW(node->set_attribute(static_cast<as2js::Node::attribute_t>(j), true), as2js::exception_internal_error);
     306        1020 :             CPPUNIT_ASSERT_THROW(node->set_attribute(static_cast<as2js::Node::attribute_t>(j), false), as2js::exception_internal_error);
     307        1020 :             CPPUNIT_ASSERT_THROW(node->attribute_to_string(static_cast<as2js::Node::attribute_t>(j)), as2js::exception_internal_error);
     308        1020 :             CPPUNIT_ASSERT_THROW(as2js::Node::attribute_to_string(static_cast<as2js::Node::attribute_t>(j)), as2js::exception_internal_error);
     309             :         }
     310             : 
     311             :         // attributes can be assigned to all types except NODE_PROGRAM
     312             :         // which only accepts NODE_DEFINED
     313        4760 :         for(int j(0); j < static_cast<int>(as2js::Node::attribute_t::NODE_ATTR_max); ++j)
     314             :         {
     315        4590 :             if(node_type == as2js::Node::node_t::NODE_PROGRAM
     316          27 :             && j != static_cast<int>(as2js::Node::attribute_t::NODE_ATTR_DEFINED))
     317             :             {
     318          26 :                 CPPUNIT_ASSERT_THROW(node->get_attribute(static_cast<as2js::Node::attribute_t>(j)), as2js::exception_internal_error);
     319          26 :                 CPPUNIT_ASSERT_THROW(node->set_attribute(static_cast<as2js::Node::attribute_t>(j), true), as2js::exception_internal_error);
     320          26 :                 CPPUNIT_ASSERT_THROW(node->set_attribute(static_cast<as2js::Node::attribute_t>(j), false), as2js::exception_internal_error);
     321             :             }
     322             :             else
     323             :             {
     324             :                 // before we set it, always false
     325        4564 :                 CPPUNIT_ASSERT(!node->get_attribute(static_cast<as2js::Node::attribute_t>(j)));
     326        4564 :                 node->set_attribute(static_cast<as2js::Node::attribute_t>(j), true);
     327        4564 :                 CPPUNIT_ASSERT(node->get_attribute(static_cast<as2js::Node::attribute_t>(j)));
     328             :                 // since we reset them all we won't have a problem with conflicts in this loop
     329        4564 :                 node->set_attribute(static_cast<as2js::Node::attribute_t>(j), false);
     330        4564 :                 CPPUNIT_ASSERT(!node->get_attribute(static_cast<as2js::Node::attribute_t>(j)));
     331             :             }
     332        4590 :             char const *attr_name1(node->attribute_to_string(static_cast<as2js::Node::attribute_t>(j)));
     333        4590 :             CPPUNIT_ASSERT(attr_name1 != nullptr);
     334        4590 :             char const *attr_name2(as2js::Node::attribute_to_string(static_cast<as2js::Node::attribute_t>(j)));
     335        4590 :             CPPUNIT_ASSERT(attr_name2 != nullptr);
     336        4590 :             CPPUNIT_ASSERT(strcmp(attr_name1, attr_name2) == 0);
     337             : 
     338        4590 :             switch(static_cast<as2js::Node::attribute_t>(j))
     339             :             {
     340         170 :             case as2js::Node::attribute_t::NODE_ATTR_PUBLIC:       CPPUNIT_ASSERT(strcmp(attr_name1, "PUBLIC")         == 0); break;
     341         170 :             case as2js::Node::attribute_t::NODE_ATTR_PRIVATE:      CPPUNIT_ASSERT(strcmp(attr_name1, "PRIVATE")        == 0); break;
     342         170 :             case as2js::Node::attribute_t::NODE_ATTR_PROTECTED:    CPPUNIT_ASSERT(strcmp(attr_name1, "PROTECTED")      == 0); break;
     343         170 :             case as2js::Node::attribute_t::NODE_ATTR_INTERNAL:     CPPUNIT_ASSERT(strcmp(attr_name1, "INTERNAL")       == 0); break;
     344         170 :             case as2js::Node::attribute_t::NODE_ATTR_TRANSIENT:    CPPUNIT_ASSERT(strcmp(attr_name1, "TRANSIENT")      == 0); break;
     345         170 :             case as2js::Node::attribute_t::NODE_ATTR_VOLATILE:     CPPUNIT_ASSERT(strcmp(attr_name1, "VOLATILE")       == 0); break;
     346         170 :             case as2js::Node::attribute_t::NODE_ATTR_STATIC:       CPPUNIT_ASSERT(strcmp(attr_name1, "STATIC")         == 0); break;
     347         170 :             case as2js::Node::attribute_t::NODE_ATTR_ABSTRACT:     CPPUNIT_ASSERT(strcmp(attr_name1, "ABSTRACT")       == 0); break;
     348         170 :             case as2js::Node::attribute_t::NODE_ATTR_VIRTUAL:      CPPUNIT_ASSERT(strcmp(attr_name1, "VIRTUAL")        == 0); break;
     349         170 :             case as2js::Node::attribute_t::NODE_ATTR_ARRAY:        CPPUNIT_ASSERT(strcmp(attr_name1, "ARRAY")          == 0); break;
     350         170 :             case as2js::Node::attribute_t::NODE_ATTR_INLINE:       CPPUNIT_ASSERT(strcmp(attr_name1, "INLINE")         == 0); break;
     351         170 :             case as2js::Node::attribute_t::NODE_ATTR_REQUIRE_ELSE: CPPUNIT_ASSERT(strcmp(attr_name1, "REQUIRE_ELSE")   == 0); break;
     352         170 :             case as2js::Node::attribute_t::NODE_ATTR_ENSURE_THEN:  CPPUNIT_ASSERT(strcmp(attr_name1, "ENSURE_THEN")    == 0); break;
     353         170 :             case as2js::Node::attribute_t::NODE_ATTR_NATIVE:       CPPUNIT_ASSERT(strcmp(attr_name1, "NATIVE")         == 0); break;
     354         170 :             case as2js::Node::attribute_t::NODE_ATTR_DEPRECATED:   CPPUNIT_ASSERT(strcmp(attr_name1, "DEPRECATED")     == 0); break;
     355         170 :             case as2js::Node::attribute_t::NODE_ATTR_UNSAFE:       CPPUNIT_ASSERT(strcmp(attr_name1, "UNSAFE")         == 0); break;
     356         170 :             case as2js::Node::attribute_t::NODE_ATTR_CONSTRUCTOR:  CPPUNIT_ASSERT(strcmp(attr_name1, "CONSTRUCTOR")    == 0); break;
     357         170 :             case as2js::Node::attribute_t::NODE_ATTR_FINAL:        CPPUNIT_ASSERT(strcmp(attr_name1, "FINAL")          == 0); break;
     358         170 :             case as2js::Node::attribute_t::NODE_ATTR_ENUMERABLE:   CPPUNIT_ASSERT(strcmp(attr_name1, "ENUMERABLE")     == 0); break;
     359         170 :             case as2js::Node::attribute_t::NODE_ATTR_TRUE:         CPPUNIT_ASSERT(strcmp(attr_name1, "TRUE")           == 0); break;
     360         170 :             case as2js::Node::attribute_t::NODE_ATTR_FALSE:        CPPUNIT_ASSERT(strcmp(attr_name1, "FALSE")          == 0); break;
     361         170 :             case as2js::Node::attribute_t::NODE_ATTR_UNUSED:       CPPUNIT_ASSERT(strcmp(attr_name1, "UNUSED")         == 0); break;
     362         170 :             case as2js::Node::attribute_t::NODE_ATTR_DYNAMIC:      CPPUNIT_ASSERT(strcmp(attr_name1, "DYNAMIC")        == 0); break;
     363         170 :             case as2js::Node::attribute_t::NODE_ATTR_FOREACH:      CPPUNIT_ASSERT(strcmp(attr_name1, "FOREACH")        == 0); break;
     364         170 :             case as2js::Node::attribute_t::NODE_ATTR_NOBREAK:      CPPUNIT_ASSERT(strcmp(attr_name1, "NOBREAK")        == 0); break;
     365         170 :             case as2js::Node::attribute_t::NODE_ATTR_AUTOBREAK:    CPPUNIT_ASSERT(strcmp(attr_name1, "AUTOBREAK")      == 0); break;
     366         170 :             case as2js::Node::attribute_t::NODE_ATTR_DEFINED:      CPPUNIT_ASSERT(strcmp(attr_name1, "DEFINED")        == 0); break;
     367           0 :             case as2js::Node::attribute_t::NODE_ATTR_max:          CPPUNIT_ASSERT(!"attribute max should not be checked in this test"); break;
     368             :             }
     369             :         }
     370         170 :     }
     371             : 
     372             :     // make sure that special numbers are correctly caught
     373        1146 :     for(size_t i(0); i < static_cast<size_t>(as2js::Node::node_t::NODE_max); ++i)
     374             :     {
     375        1145 :         if(!valid_types[i])
     376             :         {
     377         976 :             as2js::Node::node_t node_type(static_cast<as2js::Node::node_t>(i));
     378             : //std::cerr << "assert node type " << i << "\n";
     379         976 :             CPPUNIT_ASSERT_THROW(new as2js::Node(node_type), as2js::exception_incompatible_node_type);
     380             :         }
     381             :     }
     382             : 
     383             :     // test with completely random numbers too (outside of the
     384             :     // standard range of node types.)
     385         101 :     for(size_t i(0); i < 100; ++i)
     386             :     {
     387         100 :         int32_t j((rand() << 16) ^ rand());
     388         100 :         if(j < -1 || j >= static_cast<ssize_t>(as2js::Node::node_t::NODE_max))
     389             :         {
     390         100 :             as2js::Node::node_t node_type(static_cast<as2js::Node::node_t>(j));
     391         100 :             CPPUNIT_ASSERT_THROW(new as2js::Node(node_type), as2js::exception_incompatible_node_type);
     392             :         }
     393             :     }
     394           1 : }
     395             : 
     396             : 
     397           1 : void As2JsNodeUnitTests::test_compare()
     398             : {
     399           1 :     as2js::Node::pointer_t node1_true(new as2js::Node(as2js::Node::node_t::NODE_TRUE));
     400           2 :     as2js::Node::pointer_t node2_false(new as2js::Node(as2js::Node::node_t::NODE_FALSE));
     401           2 :     as2js::Node::pointer_t node3_true(new as2js::Node(as2js::Node::node_t::NODE_TRUE));
     402           2 :     as2js::Node::pointer_t node4_false(new as2js::Node(as2js::Node::node_t::NODE_FALSE));
     403             : 
     404           2 :     as2js::Node::pointer_t node5_33(new as2js::Node(as2js::Node::node_t::NODE_INT64));
     405           1 :     as2js::Int64 i33;
     406           1 :     i33.set(33);
     407           1 :     node5_33->set_int64(i33);
     408             : 
     409           2 :     as2js::Node::pointer_t node6_101(new as2js::Node(as2js::Node::node_t::NODE_INT64));
     410           1 :     as2js::Int64 i101;
     411           1 :     i101.set(101);
     412           1 :     node6_101->set_int64(i101);
     413             : 
     414           2 :     as2js::Node::pointer_t node7_33(new as2js::Node(as2js::Node::node_t::NODE_FLOAT64));
     415           1 :     as2js::Float64 f33;
     416           1 :     f33.set(3.3);
     417           1 :     node7_33->set_float64(f33);
     418             : 
     419           2 :     as2js::Node::pointer_t node7_nearly33(new as2js::Node(as2js::Node::node_t::NODE_FLOAT64));
     420           1 :     as2js::Float64 fnearly33;
     421           1 :     fnearly33.set(3.300001);
     422           1 :     node7_nearly33->set_float64(fnearly33);
     423             : 
     424           2 :     as2js::Node::pointer_t node8_101(new as2js::Node(as2js::Node::node_t::NODE_FLOAT64));
     425           1 :     as2js::Float64 f101;
     426           1 :     f101.set(1.01);
     427           1 :     node8_101->set_float64(f101);
     428             : 
     429           2 :     as2js::Node::pointer_t node9_null(new as2js::Node(as2js::Node::node_t::NODE_NULL));
     430           2 :     as2js::Node::pointer_t node10_null(new as2js::Node(as2js::Node::node_t::NODE_NULL));
     431             : 
     432           2 :     as2js::Node::pointer_t node11_undefined(new as2js::Node(as2js::Node::node_t::NODE_UNDEFINED));
     433           2 :     as2js::Node::pointer_t node12_undefined(new as2js::Node(as2js::Node::node_t::NODE_UNDEFINED));
     434             : 
     435           2 :     as2js::Node::pointer_t node13_empty_string(new as2js::Node(as2js::Node::node_t::NODE_STRING));
     436           2 :     as2js::Node::pointer_t node14_blah(new as2js::Node(as2js::Node::node_t::NODE_STRING));
     437           1 :     node14_blah->set_string("blah");
     438           2 :     as2js::Node::pointer_t node15_foo(new as2js::Node(as2js::Node::node_t::NODE_STRING));
     439           1 :     node15_foo->set_string("foo");
     440           2 :     as2js::Node::pointer_t node16_07(new as2js::Node(as2js::Node::node_t::NODE_STRING));
     441           1 :     node16_07->set_string("0.7");
     442           2 :     as2js::Node::pointer_t node17_nearly33(new as2js::Node(as2js::Node::node_t::NODE_STRING));
     443           1 :     node17_nearly33->set_string("3.300001");
     444             : 
     445             :     // BOOLEAN
     446           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node1_true, node1_true, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     447           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node1_true, node3_true, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     448           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node3_true, node1_true, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     449           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node3_true, node3_true, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     450             : 
     451           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node1_true, node1_true, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     452           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node1_true, node3_true, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     453           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node3_true, node1_true, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     454           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node3_true, node3_true, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     455             : 
     456           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node1_true, node1_true, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     457           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node1_true, node3_true, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     458           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node3_true, node1_true, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     459           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node3_true, node3_true, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     460             : 
     461           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node2_false, node2_false, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     462           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node2_false, node4_false, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     463           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node4_false, node2_false, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     464           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node4_false, node4_false, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     465             : 
     466           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node2_false, node2_false, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     467           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node2_false, node4_false, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     468           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node4_false, node2_false, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     469           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node4_false, node4_false, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     470             : 
     471           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node2_false, node2_false, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     472           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node2_false, node4_false, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     473           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node4_false, node2_false, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     474           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node4_false, node4_false, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     475             : 
     476           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node1_true, node2_false, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_GREATER);
     477           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node3_true, node2_false, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_GREATER);
     478           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node1_true, node4_false, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_GREATER);
     479           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node3_true, node4_false, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_GREATER);
     480             : 
     481           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node1_true, node2_false, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
     482           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node3_true, node2_false, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
     483           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node1_true, node4_false, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
     484           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node3_true, node4_false, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
     485             : 
     486           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node1_true, node2_false, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
     487           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node3_true, node2_false, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
     488           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node1_true, node4_false, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
     489           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node3_true, node4_false, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
     490             : 
     491           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node2_false, node1_true, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_LESS);
     492           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node2_false, node3_true, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_LESS);
     493           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node4_false, node1_true, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_LESS);
     494           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node4_false, node3_true, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_LESS);
     495             : 
     496           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node2_false, node1_true, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
     497           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node2_false, node3_true, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
     498           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node4_false, node1_true, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
     499           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node4_false, node3_true, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
     500             : 
     501           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node2_false, node1_true, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
     502           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node2_false, node3_true, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
     503           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node4_false, node1_true, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
     504           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node4_false, node3_true, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
     505             : 
     506             :     // FLOAT
     507           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node7_33, node7_33, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     508           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node7_33, node7_nearly33, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_LESS);
     509           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node7_nearly33, node7_33, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_GREATER);
     510           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node7_33, node17_nearly33, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
     511           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node17_nearly33, node7_33, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
     512           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node7_33, node8_101, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_GREATER);
     513           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node7_33, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_LESS);
     514           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node8_101, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     515             : 
     516           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node7_33, node7_33, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     517           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node7_33, node7_nearly33, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
     518           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node7_nearly33, node7_33, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
     519           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node7_33, node17_nearly33, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
     520           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node17_nearly33, node7_33, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
     521           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node7_33, node8_101, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
     522           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node7_33, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
     523           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node8_101, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     524             : 
     525           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node7_33, node7_33, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     526           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node7_33, node7_nearly33, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     527           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node7_nearly33, node7_33, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     528           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node7_33, node17_nearly33, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     529           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node17_nearly33, node7_33, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     530           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node7_33, node8_101, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
     531           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node7_33, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
     532           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node8_101, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     533             : 
     534             :     // INTEGER
     535           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node5_33, node5_33, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     536           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node5_33, node6_101, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_LESS);
     537           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node6_101, node5_33, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_GREATER);
     538           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node6_101, node6_101, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     539             : 
     540           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node5_33, node5_33, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     541           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node5_33, node6_101, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
     542           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node6_101, node5_33, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
     543           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node6_101, node6_101, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     544             : 
     545           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node5_33, node5_33, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     546           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node5_33, node6_101, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
     547           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node6_101, node5_33, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
     548           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node6_101, node6_101, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     549             : 
     550             :     // NULL
     551           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node9_null, node9_null, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     552           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node9_null, node10_null, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     553           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node10_null, node9_null, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     554           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node10_null, node10_null, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     555             : 
     556           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node9_null, node9_null, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     557           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node9_null, node10_null, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     558           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node10_null, node9_null, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     559           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node10_null, node10_null, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     560             : 
     561           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node9_null, node9_null, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     562           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node9_null, node10_null, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     563           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node10_null, node9_null, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     564           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node10_null, node10_null, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     565             : 
     566             :     // UNDEFINED
     567           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node11_undefined, node11_undefined, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     568           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node11_undefined, node12_undefined, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     569           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node12_undefined, node11_undefined, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     570           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node12_undefined, node12_undefined, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     571             : 
     572           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node11_undefined, node11_undefined, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     573           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node11_undefined, node12_undefined, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     574           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node12_undefined, node11_undefined, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     575           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node12_undefined, node12_undefined, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     576             : 
     577           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node11_undefined, node11_undefined, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     578           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node11_undefined, node12_undefined, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     579           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node12_undefined, node11_undefined, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     580           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node12_undefined, node12_undefined, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     581             : 
     582             :     // STRING
     583           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node13_empty_string, node13_empty_string, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     584           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node13_empty_string, node14_blah, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_LESS);
     585           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node13_empty_string, node15_foo, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_LESS);
     586           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node14_blah, node13_empty_string, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_GREATER);
     587           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node14_blah, node14_blah, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     588           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node14_blah, node15_foo, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_LESS);
     589           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node15_foo, node13_empty_string, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_GREATER);
     590           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node15_foo, node14_blah, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_GREATER);
     591           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node15_foo, node15_foo, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     592             : 
     593           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node13_empty_string, node13_empty_string, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     594           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node13_empty_string, node14_blah, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
     595           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node13_empty_string, node15_foo, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
     596           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node14_blah, node13_empty_string, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
     597           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node14_blah, node14_blah, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     598           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node14_blah, node15_foo, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
     599           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node15_foo, node13_empty_string, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
     600           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node15_foo, node14_blah, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
     601           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node15_foo, node15_foo, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     602             : 
     603           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node13_empty_string, node13_empty_string, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     604           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node13_empty_string, node14_blah, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
     605           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node13_empty_string, node15_foo, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
     606           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node14_blah, node13_empty_string, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
     607           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node14_blah, node14_blah, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     608           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node14_blah, node15_foo, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
     609           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node15_foo, node13_empty_string, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
     610           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node15_foo, node14_blah, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
     611           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node15_foo, node15_foo, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     612             : 
     613             :     // NULL vs UNDEFINED
     614           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node9_null, node11_undefined, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
     615           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node9_null, node12_undefined, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
     616           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node10_null, node11_undefined, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
     617           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node10_null, node12_undefined, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
     618           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node11_undefined, node9_null, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
     619           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node12_undefined, node9_null, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
     620           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node11_undefined, node10_null, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
     621           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node12_undefined, node10_null, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
     622             : 
     623           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node9_null, node11_undefined, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     624           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node9_null, node12_undefined, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     625           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node10_null, node11_undefined, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     626           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node10_null, node12_undefined, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     627           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node11_undefined, node9_null, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     628           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node12_undefined, node9_null, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     629           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node11_undefined, node10_null, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     630           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node12_undefined, node10_null, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     631             : 
     632           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node9_null, node11_undefined, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     633           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node9_null, node12_undefined, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     634           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node10_null, node11_undefined, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     635           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node10_null, node12_undefined, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     636           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node11_undefined, node9_null, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     637           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node12_undefined, node9_null, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     638           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node11_undefined, node10_null, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     639           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node12_undefined, node10_null, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     640             : 
     641             :     // <any> against FLOAT64
     642           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node1_true, node7_33, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
     643           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node2_false, node7_33, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
     644           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node5_33, node7_33, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
     645           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node6_101, node7_33, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
     646           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node9_null, node7_33, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
     647           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node11_undefined, node7_33, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
     648           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node13_empty_string, node7_33, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
     649           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node14_blah, node7_33, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
     650           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node16_07, node7_33, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
     651             : 
     652           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node1_true, node7_33, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
     653           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node2_false, node7_33, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
     654           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node5_33, node7_33, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
     655           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node6_101, node7_33, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
     656           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node9_null, node7_33, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
     657           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node11_undefined, node7_33, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_UNORDERED);
     658           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node13_empty_string, node7_33, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
     659           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node14_blah, node7_33, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_UNORDERED);
     660           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node16_07, node7_33, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
     661             : 
     662           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node1_true, node7_33, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
     663           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node2_false, node7_33, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
     664           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node5_33, node7_33, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
     665           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node6_101, node7_33, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
     666           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node9_null, node7_33, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
     667           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node11_undefined, node7_33, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_UNORDERED);
     668           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node13_empty_string, node7_33, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
     669           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node14_blah, node7_33, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_UNORDERED);
     670           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node16_07, node7_33, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
     671             : 
     672             :     // FLOAT64 against <any>
     673           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node1_true, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
     674           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node2_false, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
     675           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node5_33, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
     676           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node6_101, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
     677           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node9_null, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
     678           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node11_undefined, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
     679           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node13_empty_string, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
     680           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node14_blah, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
     681           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node16_07, as2js::Node::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
     682             : 
     683           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node1_true, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
     684           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node2_false, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
     685           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node5_33, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
     686           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node6_101, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
     687           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node9_null, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
     688           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node11_undefined, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_UNORDERED);
     689           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node13_empty_string, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
     690           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node14_blah, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_UNORDERED);
     691           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node16_07, as2js::Node::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
     692             : 
     693           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node2_false, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
     694           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node5_33, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
     695           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node6_101, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
     696           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node9_null, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
     697           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node11_undefined, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_UNORDERED);
     698           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node13_empty_string, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
     699           1 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node14_blah, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_UNORDERED);
     700           2 :     CPPUNIT_ASSERT(as2js::Node::compare(node8_101, node16_07, as2js::Node::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
     701           1 : }
     702             : 
     703             : 
     704           1 : void As2JsNodeUnitTests::test_conversions()
     705             : {
     706             :     // first test simple conversions
     707         171 :     for(size_t i(0); i < g_node_types_size; ++i)
     708             :     {
     709             :         // original type
     710         170 :         as2js::Node::node_t original_type(g_node_types[i].f_type);
     711             : 
     712             :         // all nodes can be converted to UNKNOWN
     713             :         {
     714         170 :             as2js::Node::pointer_t node(new as2js::Node(original_type));
     715             :             {
     716         170 :                 as2js::NodeLock lock(node);
     717         170 :                 CPPUNIT_ASSERT_THROW(node->to_unknown(), as2js::exception_locked_node);
     718         170 :                 CPPUNIT_ASSERT(node->get_type() == original_type);
     719             :             }
     720         170 :             node->to_unknown();
     721         170 :             CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_UNKNOWN);
     722             :         }
     723             : 
     724             :         // CALL can be convert to AS
     725             :         {
     726         170 :             as2js::Node::pointer_t node(new as2js::Node(original_type));
     727             :             {
     728         170 :                 as2js::NodeLock lock(node);
     729         170 :                 CPPUNIT_ASSERT_THROW(node->to_as(), as2js::exception_locked_node);
     730         170 :                 CPPUNIT_ASSERT(node->get_type() == original_type);
     731             :             }
     732         170 :             if(original_type == as2js::Node::node_t::NODE_CALL)
     733             :             {
     734             :                 // in this case it works
     735           1 :                 CPPUNIT_ASSERT(node->to_as());
     736           1 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_AS);
     737             :             }
     738             :             else
     739             :             {
     740             :                 // in this case it fails
     741         169 :                 CPPUNIT_ASSERT(!node->to_as());
     742         169 :                 CPPUNIT_ASSERT(node->get_type() == original_type);
     743         170 :             }
     744             :         }
     745             : 
     746             :         // test what would happen if we were to call to_boolean()
     747             :         {
     748         170 :             as2js::Node::pointer_t node(new as2js::Node(original_type));
     749             :             {
     750         170 :                 as2js::NodeLock lock(node);
     751         170 :                 node->to_boolean_type_only();
     752         170 :                 CPPUNIT_ASSERT(node->get_type() == original_type);
     753             :             }
     754         170 :             as2js::Node::node_t new_type(node->to_boolean_type_only());
     755         170 :             switch(original_type)
     756             :             {
     757             :             case as2js::Node::node_t::NODE_TRUE:
     758           1 :                 CPPUNIT_ASSERT(new_type == as2js::Node::node_t::NODE_TRUE);
     759           1 :                 break;
     760             : 
     761             :             case as2js::Node::node_t::NODE_FALSE:
     762             :             case as2js::Node::node_t::NODE_NULL:
     763             :             case as2js::Node::node_t::NODE_UNDEFINED:
     764             :             case as2js::Node::node_t::NODE_INT64: // by default integers are set to zero
     765             :             case as2js::Node::node_t::NODE_FLOAT64: // by default floating points are set to zero
     766             :             case as2js::Node::node_t::NODE_STRING: // by default strings are empty
     767           6 :                 CPPUNIT_ASSERT(new_type == as2js::Node::node_t::NODE_FALSE);
     768           6 :                 break;
     769             : 
     770             :             default:
     771         163 :                 CPPUNIT_ASSERT(new_type == as2js::Node::node_t::NODE_UNDEFINED);
     772         163 :                 break;
     773             : 
     774         170 :             }
     775             :         }
     776             : 
     777             :         // a few nodes can be converted to a boolean value
     778             :         {
     779         170 :             as2js::Node::pointer_t node(new as2js::Node(original_type));
     780             :             {
     781         170 :                 as2js::NodeLock lock(node);
     782         170 :                 CPPUNIT_ASSERT_THROW(node->to_boolean(), as2js::exception_locked_node);
     783         170 :                 CPPUNIT_ASSERT(node->get_type() == original_type);
     784             :             }
     785         170 :             switch(original_type)
     786             :             {
     787             :             case as2js::Node::node_t::NODE_TRUE:
     788           1 :                 CPPUNIT_ASSERT(node->to_boolean());
     789           1 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_TRUE);
     790           1 :                 break;
     791             : 
     792             :             case as2js::Node::node_t::NODE_FALSE:
     793             :             case as2js::Node::node_t::NODE_NULL:
     794             :             case as2js::Node::node_t::NODE_UNDEFINED:
     795             :             case as2js::Node::node_t::NODE_INT64: // by default integers are set to zero
     796             :             case as2js::Node::node_t::NODE_FLOAT64: // by default floating points are set to zero
     797             :             case as2js::Node::node_t::NODE_STRING: // by default strings are empty
     798           6 :                 CPPUNIT_ASSERT(node->to_boolean());
     799           6 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_FALSE);
     800           6 :                 break;
     801             : 
     802             :             default:
     803         163 :                 CPPUNIT_ASSERT(!node->to_boolean());
     804         163 :                 CPPUNIT_ASSERT(node->get_type() == original_type);
     805         163 :                 break;
     806             : 
     807         170 :             }
     808             :         }
     809             : 
     810             :         // a couple types of nodes can be converted to a CALL
     811             :         {
     812         170 :             as2js::Node::pointer_t node(new as2js::Node(original_type));
     813             :             {
     814         170 :                 as2js::NodeLock lock(node);
     815         170 :                 CPPUNIT_ASSERT_THROW(node->to_call(), as2js::exception_locked_node);
     816         170 :                 CPPUNIT_ASSERT(node->get_type() == original_type);
     817             :             }
     818         170 :             switch(original_type)
     819             :             {
     820             :             case as2js::Node::node_t::NODE_ASSIGNMENT:
     821             :             case as2js::Node::node_t::NODE_MEMBER:
     822           2 :                 CPPUNIT_ASSERT(node->to_call());
     823           2 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_CALL);
     824           2 :                 break;
     825             : 
     826             :             default:
     827         168 :                 CPPUNIT_ASSERT(!node->to_call());
     828         168 :                 CPPUNIT_ASSERT(node->get_type() == original_type);
     829         168 :                 break;
     830             : 
     831         170 :             }
     832             :         }
     833             : 
     834             :         // a few types of nodes can be converted to an INT64
     835             :         {
     836         170 :             as2js::Node::pointer_t node(new as2js::Node(original_type));
     837             :             {
     838         170 :                 as2js::NodeLock lock(node);
     839         170 :                 CPPUNIT_ASSERT_THROW(node->to_int64(), as2js::exception_locked_node);
     840         170 :                 CPPUNIT_ASSERT(node->get_type() == original_type);
     841             :             }
     842         170 :             switch(original_type)
     843             :             {
     844             :             case as2js::Node::node_t::NODE_INT64: // no change
     845           1 :                 CPPUNIT_ASSERT(node->to_int64());
     846           1 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_INT64);
     847           1 :                 break;
     848             : 
     849             :             case as2js::Node::node_t::NODE_FLOAT64:
     850           1 :                 CPPUNIT_ASSERT(node->to_int64());
     851           1 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_INT64);
     852           1 :                 break;
     853             : 
     854             :             case as2js::Node::node_t::NODE_FALSE:
     855             :             case as2js::Node::node_t::NODE_NULL:
     856             :             case as2js::Node::node_t::NODE_UNDEFINED:
     857           3 :                 CPPUNIT_ASSERT(node->to_int64());
     858           3 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_INT64);
     859           3 :                 CPPUNIT_ASSERT(node->get_int64().get() == 0);
     860           3 :                 break;
     861             : 
     862             :             case as2js::Node::node_t::NODE_STRING: // empty string to start with...
     863           1 :                 CPPUNIT_ASSERT(node->to_int64());
     864           1 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_INT64);
     865           1 :                 CPPUNIT_ASSERT(node->get_int64().get() == 0);
     866             : 
     867             :                 // if not empty...
     868             :                 {
     869           1 :                     as2js::Node::pointer_t node_str(new as2js::Node(original_type));
     870           1 :                     node_str->set_string("34");
     871           1 :                     CPPUNIT_ASSERT(node_str->to_int64());
     872           1 :                     CPPUNIT_ASSERT(node_str->get_type() == as2js::Node::node_t::NODE_INT64);
     873           1 :                     CPPUNIT_ASSERT(node_str->get_int64().get() == 34);
     874             :                 }
     875             :                 {
     876           1 :                     as2js::Node::pointer_t node_str(new as2js::Node(original_type));
     877           1 :                     node_str->set_string("+84");
     878           1 :                     CPPUNIT_ASSERT(node_str->to_int64());
     879           1 :                     CPPUNIT_ASSERT(node_str->get_type() == as2js::Node::node_t::NODE_INT64);
     880           1 :                     CPPUNIT_ASSERT(node_str->get_int64().get() == 84);
     881             :                 }
     882             :                 {
     883           1 :                     as2js::Node::pointer_t node_str(new as2js::Node(original_type));
     884           1 :                     node_str->set_string("-37");
     885           1 :                     CPPUNIT_ASSERT(node_str->to_int64());
     886           1 :                     CPPUNIT_ASSERT(node_str->get_type() == as2js::Node::node_t::NODE_INT64);
     887           1 :                     CPPUNIT_ASSERT(node_str->get_int64().get() == -37);
     888             :                 }
     889             :                 {
     890           1 :                     as2js::Node::pointer_t node_str(new as2js::Node(original_type));
     891           1 :                     node_str->set_string("3.4");
     892           1 :                     CPPUNIT_ASSERT(node_str->to_int64());
     893           1 :                     CPPUNIT_ASSERT(node_str->get_type() == as2js::Node::node_t::NODE_INT64);
     894           1 :                     CPPUNIT_ASSERT(node_str->get_int64().get() == 3);
     895             :                 }
     896             :                 {
     897           1 :                     as2js::Node::pointer_t node_str(new as2js::Node(original_type));
     898           1 :                     node_str->set_string("34e+5");
     899           1 :                     CPPUNIT_ASSERT(node_str->to_int64());
     900           1 :                     CPPUNIT_ASSERT(node_str->get_type() == as2js::Node::node_t::NODE_INT64);
     901           1 :                     CPPUNIT_ASSERT(node_str->get_int64().get() == 3400000);
     902             :                 }
     903             :                 {
     904           1 :                     as2js::Node::pointer_t node_str(new as2js::Node(original_type));
     905           1 :                     node_str->set_string("some NaN");
     906           1 :                     CPPUNIT_ASSERT(node_str->to_int64());
     907           1 :                     CPPUNIT_ASSERT(node_str->get_type() == as2js::Node::node_t::NODE_INT64);
     908           1 :                     CPPUNIT_ASSERT(node_str->get_int64().get() == 0);
     909             :                 }
     910           1 :                 break;
     911             : 
     912             :             case as2js::Node::node_t::NODE_TRUE:
     913           1 :                 CPPUNIT_ASSERT(node->to_int64());
     914           1 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_INT64);
     915           1 :                 CPPUNIT_ASSERT(node->get_int64().get() == 1);
     916           1 :                 break;
     917             : 
     918             :             default:
     919         163 :                 CPPUNIT_ASSERT(!node->to_int64());
     920         163 :                 CPPUNIT_ASSERT(node->get_type() == original_type);
     921         163 :                 break;
     922             : 
     923         170 :             }
     924             :         }
     925             : 
     926             :         // a few types of nodes can be converted to a FLOAT64
     927             :         {
     928         170 :             as2js::Node::pointer_t node(new as2js::Node(original_type));
     929             :             {
     930         170 :                 as2js::NodeLock lock(node);
     931         170 :                 CPPUNIT_ASSERT_THROW(node->to_float64(), as2js::exception_locked_node);
     932         170 :                 CPPUNIT_ASSERT(node->get_type() == original_type);
     933             :             }
     934         170 :             switch(original_type)
     935             :             {
     936             :             case as2js::Node::node_t::NODE_INT64: // no change
     937           1 :                 CPPUNIT_ASSERT(node->to_float64());
     938           1 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_FLOAT64);
     939           1 :                 break;
     940             : 
     941             :             case as2js::Node::node_t::NODE_FLOAT64:
     942           1 :                 CPPUNIT_ASSERT(node->to_float64());
     943           1 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_FLOAT64);
     944           1 :                 break;
     945             : 
     946             :             case as2js::Node::node_t::NODE_FALSE:
     947             :             case as2js::Node::node_t::NODE_NULL:
     948             :             case as2js::Node::node_t::NODE_STRING:
     949           3 :                 CPPUNIT_ASSERT(node->to_float64());
     950           3 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_FLOAT64);
     951             : #pragma GCC diagnostic push
     952             : #pragma GCC diagnostic ignored "-Wfloat-equal"
     953           3 :                 CPPUNIT_ASSERT(node->get_float64().get() == 0.0);
     954             : #pragma GCC diagnostic pop
     955           3 :                 break;
     956             : 
     957             :             case as2js::Node::node_t::NODE_TRUE:
     958           1 :                 CPPUNIT_ASSERT(node->to_float64());
     959           1 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_FLOAT64);
     960             : #pragma GCC diagnostic push
     961             : #pragma GCC diagnostic ignored "-Wfloat-equal"
     962           1 :                 CPPUNIT_ASSERT(node->get_float64().get() == 1.0);
     963             : #pragma GCC diagnostic pop
     964           1 :                 break;
     965             : 
     966             :             case as2js::Node::node_t::NODE_UNDEFINED:
     967           1 :                 CPPUNIT_ASSERT(node->to_float64());
     968           1 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_FLOAT64);
     969           1 :                 CPPUNIT_ASSERT(node->get_float64().is_NaN());
     970           1 :                 break;
     971             : 
     972             :             default:
     973         163 :                 CPPUNIT_ASSERT(!node->to_float64());
     974         163 :                 CPPUNIT_ASSERT(node->get_type() == original_type);
     975         163 :                 break;
     976             : 
     977         170 :             }
     978             :         }
     979             : 
     980             :         // IDENTIFIER can be converted to LABEL
     981             :         {
     982         170 :             as2js::Node::pointer_t node(new as2js::Node(original_type));
     983             :             {
     984         170 :                 as2js::NodeLock lock(node);
     985         170 :                 CPPUNIT_ASSERT_THROW(node->to_label(), as2js::exception_locked_node);
     986         170 :                 CPPUNIT_ASSERT(node->get_type() == original_type);
     987             :             }
     988         170 :             if(original_type == as2js::Node::node_t::NODE_IDENTIFIER)
     989             :             {
     990             :                 // in this case it works
     991           1 :                 node->to_label();
     992           1 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_LABEL);
     993             :             }
     994             :             else
     995             :             {
     996             :                 // this one fails with a soft error (returns false)
     997         169 :                 CPPUNIT_ASSERT(!node->to_label());
     998         169 :                 CPPUNIT_ASSERT(node->get_type() == original_type);
     999         170 :             }
    1000             :         }
    1001             : 
    1002             :         // a few types of nodes can be converted to a Number
    1003             :         {
    1004         170 :             as2js::Node::pointer_t node(new as2js::Node(original_type));
    1005             :             {
    1006         170 :                 as2js::NodeLock lock(node);
    1007         170 :                 CPPUNIT_ASSERT_THROW(node->to_number(), as2js::exception_locked_node);
    1008         170 :                 CPPUNIT_ASSERT(node->get_type() == original_type);
    1009             :             }
    1010         170 :             switch(original_type)
    1011             :             {
    1012             :             case as2js::Node::node_t::NODE_INT64: // no change!
    1013             :             case as2js::Node::node_t::NODE_FLOAT64: // no change!
    1014           2 :                 CPPUNIT_ASSERT(node->to_number());
    1015           2 :                 CPPUNIT_ASSERT(node->get_type() == original_type);
    1016           2 :                 break;
    1017             : 
    1018             :             case as2js::Node::node_t::NODE_FALSE:
    1019             :             case as2js::Node::node_t::NODE_NULL:
    1020           2 :                 CPPUNIT_ASSERT(node->to_number());
    1021           2 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_INT64);
    1022           2 :                 CPPUNIT_ASSERT(node->get_int64().get() == 0);
    1023           2 :                 break;
    1024             : 
    1025             :             case as2js::Node::node_t::NODE_TRUE:
    1026           1 :                 CPPUNIT_ASSERT(node->to_number());
    1027           1 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_INT64);
    1028           1 :                 CPPUNIT_ASSERT(node->get_int64().get() == 1);
    1029           1 :                 break;
    1030             : 
    1031             :             case as2js::Node::node_t::NODE_STRING: // empty strings represent 0 here
    1032           1 :                 CPPUNIT_ASSERT(node->to_number());
    1033           1 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_FLOAT64);
    1034             : #pragma GCC diagnostic push
    1035             : #pragma GCC diagnostic ignored "-Wfloat-equal"
    1036           1 :                 CPPUNIT_ASSERT(node->get_float64().get() == 0.0);
    1037             : #pragma GCC diagnostic pop
    1038           1 :                 break;
    1039             : 
    1040             :             case as2js::Node::node_t::NODE_UNDEFINED:
    1041             : //std::cerr << " . type = " << static_cast<int>(original_type) << " / " << node->get_type_name() << "\n";
    1042           1 :                 CPPUNIT_ASSERT(node->to_number());
    1043           1 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_FLOAT64);
    1044           1 :                 CPPUNIT_ASSERT(node->get_float64().is_NaN());
    1045           1 :                 break;
    1046             : 
    1047             :             default:
    1048         163 :                 CPPUNIT_ASSERT(!node->to_number());
    1049         163 :                 CPPUNIT_ASSERT(node->get_type() == original_type);
    1050         163 :                 break;
    1051             : 
    1052         170 :             }
    1053             :         }
    1054             : 
    1055             :         // a few types of nodes can be converted to a STRING
    1056             :         {
    1057         170 :             as2js::Node::pointer_t node(new as2js::Node(original_type));
    1058             :             {
    1059         170 :                 as2js::NodeLock lock(node);
    1060         170 :                 CPPUNIT_ASSERT_THROW(node->to_string(), as2js::exception_locked_node);
    1061         170 :                 CPPUNIT_ASSERT(node->get_type() == original_type);
    1062             :             }
    1063         170 :             switch(original_type)
    1064             :             {
    1065             :             case as2js::Node::node_t::NODE_STRING:
    1066           1 :                 CPPUNIT_ASSERT(node->to_string());
    1067           1 :                 CPPUNIT_ASSERT(node->get_type() == original_type);
    1068           1 :                 CPPUNIT_ASSERT(node->get_string() == "");
    1069           1 :                 break;
    1070             : 
    1071             :             case as2js::Node::node_t::NODE_FLOAT64:
    1072             :             case as2js::Node::node_t::NODE_INT64:
    1073             :                 // by default numbers are zero; we have other tests
    1074             :                 // to verify the conversion
    1075           2 :                 CPPUNIT_ASSERT(node->to_string());
    1076           2 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_STRING);
    1077           2 :                 CPPUNIT_ASSERT(node->get_string() == "0");
    1078           2 :                 break;
    1079             : 
    1080             :             case as2js::Node::node_t::NODE_FALSE:
    1081           1 :                 CPPUNIT_ASSERT(node->to_string());
    1082           1 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_STRING);
    1083           1 :                 CPPUNIT_ASSERT(node->get_string() == "false");
    1084           1 :                 break;
    1085             : 
    1086             :             case as2js::Node::node_t::NODE_TRUE:
    1087           1 :                 CPPUNIT_ASSERT(node->to_string());
    1088           1 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_STRING);
    1089           1 :                 CPPUNIT_ASSERT(node->get_string() == "true");
    1090           1 :                 break;
    1091             : 
    1092             :             case as2js::Node::node_t::NODE_NULL:
    1093           1 :                 CPPUNIT_ASSERT(node->to_string());
    1094           1 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_STRING);
    1095           1 :                 CPPUNIT_ASSERT(node->get_string() == "null");
    1096           1 :                 break;
    1097             : 
    1098             :             case as2js::Node::node_t::NODE_UNDEFINED:
    1099           1 :                 CPPUNIT_ASSERT(node->to_string());
    1100           1 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_STRING);
    1101           1 :                 CPPUNIT_ASSERT(node->get_string() == "undefined");
    1102           1 :                 break;
    1103             : 
    1104             :             case as2js::Node::node_t::NODE_IDENTIFIER: // the string remains the same
    1105             :             //case as2js::Node::node_t::NODE_VIDENTIFIER: // should the VIDENTIFIER be supported too?
    1106           1 :                 CPPUNIT_ASSERT(node->to_string());
    1107           1 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_STRING);
    1108           1 :                 break;
    1109             : 
    1110             :             default:
    1111         162 :                 CPPUNIT_ASSERT(!node->to_string());
    1112         162 :                 CPPUNIT_ASSERT(node->get_type() == original_type);
    1113         162 :                 break;
    1114             : 
    1115         170 :             }
    1116             :         }
    1117             : 
    1118             :         // a few types of nodes can be converted to an IDENTIFIER
    1119             :         {
    1120         170 :             as2js::Node::pointer_t node(new as2js::Node(original_type));
    1121             :             {
    1122         170 :                 as2js::NodeLock lock(node);
    1123         170 :                 CPPUNIT_ASSERT_THROW(node->to_identifier(), as2js::exception_locked_node);
    1124         170 :                 CPPUNIT_ASSERT(node->get_type() == original_type);
    1125             :             }
    1126         170 :             switch(original_type)
    1127             :             {
    1128             :             case as2js::Node::node_t::NODE_IDENTIFIER:
    1129           1 :                 CPPUNIT_ASSERT(node->to_identifier());
    1130           1 :                 CPPUNIT_ASSERT(node->get_type() == original_type);
    1131           1 :                 CPPUNIT_ASSERT(node->get_string() == "");
    1132           1 :                 break;
    1133             : 
    1134             :             case as2js::Node::node_t::NODE_PRIVATE:
    1135           1 :                 CPPUNIT_ASSERT(node->to_identifier());
    1136           1 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_IDENTIFIER);
    1137           1 :                 CPPUNIT_ASSERT(node->get_string() == "private");
    1138           1 :                 break;
    1139             : 
    1140             :             case as2js::Node::node_t::NODE_PROTECTED:
    1141           1 :                 CPPUNIT_ASSERT(node->to_identifier());
    1142           1 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_IDENTIFIER);
    1143           1 :                 CPPUNIT_ASSERT(node->get_string() == "protected");
    1144           1 :                 break;
    1145             : 
    1146             :             case as2js::Node::node_t::NODE_PUBLIC:
    1147           1 :                 CPPUNIT_ASSERT(node->to_identifier());
    1148           1 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_IDENTIFIER);
    1149           1 :                 CPPUNIT_ASSERT(node->get_string() == "public");
    1150           1 :                 break;
    1151             : 
    1152             :             default:
    1153         166 :                 CPPUNIT_ASSERT(!node->to_identifier());
    1154         166 :                 CPPUNIT_ASSERT(node->get_type() == original_type);
    1155         166 :                 break;
    1156             : 
    1157         170 :             }
    1158             :         }
    1159             : 
    1160             :         // IDENTIFIER can be converted to VIDENTIFIER
    1161             :         {
    1162         170 :             as2js::Node::pointer_t node(new as2js::Node(original_type));
    1163             :             {
    1164         170 :                 as2js::NodeLock lock(node);
    1165         170 :                 CPPUNIT_ASSERT_THROW(node->to_videntifier(), as2js::exception_locked_node);
    1166         170 :                 CPPUNIT_ASSERT(node->get_type() == original_type);
    1167             :             }
    1168         170 :             if(original_type == as2js::Node::node_t::NODE_IDENTIFIER)
    1169             :             {
    1170             :                 // in this case it works
    1171           1 :                 node->to_videntifier();
    1172           1 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_VIDENTIFIER);
    1173             :             }
    1174             :             else
    1175             :             {
    1176             :                 // this one fails dramatically
    1177         169 :                 CPPUNIT_ASSERT_THROW(node->to_videntifier(), as2js::exception_internal_error);
    1178         169 :                 CPPUNIT_ASSERT(node->get_type() == original_type);
    1179         170 :             }
    1180             :         }
    1181             : 
    1182             :         // VARIABLE can be converted to VAR_ATTRIBUTES
    1183             :         {
    1184         170 :             as2js::Node::pointer_t node(new as2js::Node(original_type));
    1185             :             {
    1186         170 :                 as2js::NodeLock lock(node);
    1187         170 :                 CPPUNIT_ASSERT_THROW(node->to_var_attributes(), as2js::exception_locked_node);
    1188         170 :                 CPPUNIT_ASSERT(node->get_type() == original_type);
    1189             :             }
    1190         170 :             if(original_type == as2js::Node::node_t::NODE_VARIABLE)
    1191             :             {
    1192             :                 // in this case it works
    1193           1 :                 node->to_var_attributes();
    1194           1 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_VAR_ATTRIBUTES);
    1195             :             }
    1196             :             else
    1197             :             {
    1198             :                 // in this case it fails
    1199         169 :                 CPPUNIT_ASSERT_THROW(node->to_var_attributes(), as2js::exception_internal_error);
    1200         169 :                 CPPUNIT_ASSERT(node->get_type() == original_type);
    1201         170 :             }
    1202             :         }
    1203             :     }
    1204             : 
    1205           1 :     bool got_dot(false);
    1206         101 :     for(int i(0); i < 100; ++i)
    1207             :     {
    1208             :         // Integer to other types
    1209             :         {
    1210         100 :             as2js::Int64 j((static_cast<int64_t>(rand()) << 48)
    1211         100 :                          ^ (static_cast<int64_t>(rand()) << 32)
    1212         100 :                          ^ (static_cast<int64_t>(rand()) << 16)
    1213         100 :                          ^ (static_cast<int64_t>(rand()) <<  0));
    1214             : 
    1215             :             {
    1216         100 :                 as2js::Node::pointer_t node(new as2js::Node(as2js::Node::node_t::NODE_INT64));
    1217         100 :                 node->set_int64(j);
    1218         100 :                 as2js::Float64 invalid;
    1219         100 :                 CPPUNIT_ASSERT_THROW(node->set_float64(invalid), as2js::exception_internal_error);
    1220         100 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_INT64);
    1221         100 :                 CPPUNIT_ASSERT(node->to_int64());
    1222             :                 // probably always true here; we had false in the loop prior
    1223         100 :                 CPPUNIT_ASSERT(node->get_int64().get() == j.get());
    1224             :             }
    1225             : 
    1226             :             {
    1227         100 :                 as2js::Node::pointer_t node(new as2js::Node(as2js::Node::node_t::NODE_INT64));
    1228         100 :                 node->set_int64(j);
    1229         100 :                 CPPUNIT_ASSERT(node->to_number());
    1230             :                 // probably always true here; we had false in the loop prior
    1231         100 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_INT64);
    1232         100 :                 CPPUNIT_ASSERT(node->get_int64().get() == j.get());
    1233             :             }
    1234             : 
    1235             :             {
    1236         100 :                 as2js::Node::pointer_t node(new as2js::Node(as2js::Node::node_t::NODE_INT64));
    1237         100 :                 node->set_int64(j);
    1238         100 :                 as2js::Node::node_t bool_type(node->to_boolean_type_only());
    1239             :                 // probably always true here; we had false in the loop prior
    1240         100 :                 CPPUNIT_ASSERT(bool_type == (j.get() ? as2js::Node::node_t::NODE_TRUE : as2js::Node::node_t::NODE_FALSE));
    1241             :             }
    1242             : 
    1243             :             {
    1244         100 :                 as2js::Node::pointer_t node(new as2js::Node(as2js::Node::node_t::NODE_INT64));
    1245         100 :                 node->set_int64(j);
    1246         100 :                 CPPUNIT_ASSERT(node->to_boolean());
    1247             :                 // probably always true here; we had false in the loop prior
    1248         100 :                 CPPUNIT_ASSERT(node->get_type() == (j.get() ? as2js::Node::node_t::NODE_TRUE : as2js::Node::node_t::NODE_FALSE));
    1249             :             }
    1250             : 
    1251             :             {
    1252         100 :                 as2js::Node::pointer_t node(new as2js::Node(as2js::Node::node_t::NODE_INT64));
    1253         100 :                 node->set_int64(j);
    1254         100 :                 CPPUNIT_ASSERT(node->to_float64());
    1255             :                 // probably always true here; we had false in the loop prior
    1256         100 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_FLOAT64);
    1257         100 :                 as2js::Float64 flt(j.get());
    1258         100 :                 CPPUNIT_ASSERT(node->get_float64().nearly_equal(flt, 0.0001));
    1259             :             }
    1260             : 
    1261             :             {
    1262         100 :                 as2js::Node::pointer_t node(new as2js::Node(as2js::Node::node_t::NODE_INT64));
    1263         100 :                 node->set_int64(j);
    1264         100 :                 CPPUNIT_ASSERT(node->to_string());
    1265             :                 // probably always true here; we had false in the loop prior
    1266         100 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_STRING);
    1267         100 :                 CPPUNIT_ASSERT(node->get_string() == as2js::String(std::to_string(j.get())));
    1268             :             }
    1269             :         }
    1270             : 
    1271             :         // Floating point to other values
    1272         100 :         bool first(true);
    1273        1088 :         do
    1274             :         {
    1275             :             // generate a random 64 bit number
    1276        1088 :             double s1(rand() & 1 ? -1 : 1);
    1277        1088 :             double n1(static_cast<double>((static_cast<int64_t>(rand()) << 48)
    1278        1088 :                                         ^ (static_cast<int64_t>(rand()) << 32)
    1279        1088 :                                         ^ (static_cast<int64_t>(rand()) << 16)
    1280        1088 :                                         ^ (static_cast<int64_t>(rand()) <<  0)));
    1281        1088 :             double d1(static_cast<double>((static_cast<int64_t>(rand()) << 48)
    1282        1088 :                                         ^ (static_cast<int64_t>(rand()) << 32)
    1283        1088 :                                         ^ (static_cast<int64_t>(rand()) << 16)
    1284        1088 :                                         ^ (static_cast<int64_t>(rand()) <<  0)));
    1285        1088 :             if(!first && n1 >= d1)
    1286             :             {
    1287             :                 // the dot is easier to reach with very small numbers
    1288             :                 // so create a small number immediately
    1289         486 :                 std::swap(n1, d1);
    1290         486 :                 d1 *= 1e+4;
    1291             :             }
    1292        1088 :             double r(n1 / d1 * s1);
    1293        1088 :             as2js::Float64 j(r);
    1294             : 
    1295             :             {
    1296        1088 :                 as2js::Node::pointer_t node(new as2js::Node(as2js::Node::node_t::NODE_FLOAT64));
    1297        1088 :                 node->set_float64(j);
    1298        1088 :                 CPPUNIT_ASSERT(node->to_int64());
    1299        1088 :                 CPPUNIT_ASSERT(node->get_int64().get() == static_cast<as2js::Int64::int64_type>(j.get()));
    1300             :             }
    1301             : 
    1302             :             {
    1303        1088 :                 as2js::Node::pointer_t node(new as2js::Node(as2js::Node::node_t::NODE_FLOAT64));
    1304        1088 :                 node->set_float64(j);
    1305        1088 :                 CPPUNIT_ASSERT(node->to_number());
    1306        1088 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_FLOAT64);
    1307             : #pragma GCC diagnostic push
    1308             : #pragma GCC diagnostic ignored "-Wfloat-equal"
    1309        1088 :                 CPPUNIT_ASSERT(node->get_float64().get() == j.get());
    1310        1088 : #pragma GCC diagnostic pop
    1311             :             }
    1312             : 
    1313             :             {
    1314        1088 :                 as2js::Node::pointer_t node(new as2js::Node(as2js::Node::node_t::NODE_FLOAT64));
    1315        1088 :                 node->set_float64(j);
    1316        1088 :                 as2js::Node::node_t bool_type(node->to_boolean_type_only());
    1317             :                 // probably always true here; we had false in the loop prior
    1318             : #pragma GCC diagnostic push
    1319             : #pragma GCC diagnostic ignored "-Wfloat-equal"
    1320        1088 :                 CPPUNIT_ASSERT(bool_type == (j.get() ? as2js::Node::node_t::NODE_TRUE : as2js::Node::node_t::NODE_FALSE));
    1321        1088 : #pragma GCC diagnostic pop
    1322             :             }
    1323             : 
    1324             :             {
    1325        1088 :                 as2js::Node::pointer_t node(new as2js::Node(as2js::Node::node_t::NODE_FLOAT64));
    1326        1088 :                 node->set_float64(j);
    1327        1088 :                 CPPUNIT_ASSERT(node->to_boolean());
    1328             :                 // probably always true here; we had false in the loop prior
    1329             : #pragma GCC diagnostic push
    1330             : #pragma GCC diagnostic ignored "-Wfloat-equal"
    1331        1088 :                 CPPUNIT_ASSERT(node->get_type() == (j.get() ? as2js::Node::node_t::NODE_TRUE : as2js::Node::node_t::NODE_FALSE));
    1332             : #pragma GCC diagnostic pop
    1333             : 
    1334             :                 // also test the set_boolean() with valid values
    1335        1088 :                 node->set_boolean(true);
    1336        1088 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_TRUE);
    1337        1088 :                 node->set_boolean(false);
    1338        1088 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_FALSE);
    1339             :             }
    1340             : 
    1341             :             {
    1342        1088 :                 as2js::Node::pointer_t node(new as2js::Node(as2js::Node::node_t::NODE_FLOAT64));
    1343        1088 :                 node->set_float64(j);
    1344        1088 :                 CPPUNIT_ASSERT(node->to_float64());
    1345        1088 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_FLOAT64);
    1346             : #pragma GCC diagnostic push
    1347             : #pragma GCC diagnostic ignored "-Wfloat-equal"
    1348        1088 :                 CPPUNIT_ASSERT(node->get_float64().get() == j.get());
    1349        1088 : #pragma GCC diagnostic pop
    1350             :             }
    1351             : 
    1352             :             {
    1353        1088 :                 as2js::Node::pointer_t node(new as2js::Node(as2js::Node::node_t::NODE_FLOAT64));
    1354        1088 :                 node->set_float64(j);
    1355        1088 :                 CPPUNIT_ASSERT(node->to_string());
    1356        1088 :                 CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_STRING);
    1357        2176 :                 as2js::String str(as2js::String(std::to_string(j.get())));
    1358        1088 :                 if(str.find('.') != as2js::String::npos)
    1359             :                 {
    1360             :                     // remove all least significant zeroes if any
    1361        2289 :                     while(str.back() == '0')
    1362             :                     {
    1363         113 :                         str.pop_back();
    1364             :                     }
    1365             :                     // make sure the number does not end with a period
    1366        1088 :                     if(str.back() == '.')
    1367             :                     {
    1368           1 :                         str.pop_back();
    1369           1 :                         got_dot = true;
    1370             :                     }
    1371             :                 }
    1372        2176 :                 CPPUNIT_ASSERT(node->get_string() == str);
    1373             :             }
    1374        1088 :             first = false;
    1375             :         }
    1376        1088 :         while(!got_dot);
    1377             :     }
    1378             : 
    1379             :     // verify special floating point values
    1380             :     { // NaN -> String
    1381           1 :         as2js::Float64 j;
    1382           1 :         as2js::Node::pointer_t node(new as2js::Node(as2js::Node::node_t::NODE_FLOAT64));
    1383           1 :         j.set_NaN();
    1384           1 :         node->set_float64(j);
    1385           1 :         CPPUNIT_ASSERT(node->to_string());
    1386           1 :         CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_STRING);
    1387           1 :         CPPUNIT_ASSERT(node->get_string() == "NaN");
    1388             :     }
    1389             :     { // NaN -> Int64
    1390           1 :         as2js::Float64 j;
    1391           1 :         as2js::Node::pointer_t node(new as2js::Node(as2js::Node::node_t::NODE_FLOAT64));
    1392           1 :         j.set_NaN();
    1393           1 :         node->set_float64(j);
    1394           1 :         CPPUNIT_ASSERT(node->to_int64());
    1395           1 :         CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_INT64);
    1396           1 :         CPPUNIT_ASSERT(node->get_int64().get() == 0);
    1397             :     }
    1398             :     { // +Infinity
    1399           1 :         as2js::Float64 j;
    1400           1 :         as2js::Node::pointer_t node(new as2js::Node(as2js::Node::node_t::NODE_FLOAT64));
    1401           1 :         j.set_infinity();
    1402           1 :         node->set_float64(j);
    1403           1 :         CPPUNIT_ASSERT(node->to_string());
    1404           1 :         CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_STRING);
    1405           1 :         CPPUNIT_ASSERT(node->get_string() == "Infinity");
    1406             :     }
    1407             :     { // +Infinity
    1408           1 :         as2js::Float64 j;
    1409           1 :         as2js::Node::pointer_t node(new as2js::Node(as2js::Node::node_t::NODE_FLOAT64));
    1410           1 :         j.set_infinity();
    1411           1 :         node->set_float64(j);
    1412           1 :         CPPUNIT_ASSERT(node->to_int64());
    1413           1 :         CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_INT64);
    1414           1 :         CPPUNIT_ASSERT(node->get_int64().get() == 0);
    1415             :     }
    1416             :     { // -Infinity
    1417           1 :         as2js::Float64 j;
    1418           1 :         as2js::Node::pointer_t node(new as2js::Node(as2js::Node::node_t::NODE_FLOAT64));
    1419           1 :         j.set_infinity();
    1420           1 :         j.set(-j.get());
    1421           1 :         node->set_float64(j);
    1422           1 :         CPPUNIT_ASSERT(node->to_string());
    1423           1 :         CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_STRING);
    1424           1 :         CPPUNIT_ASSERT(node->get_string() == "-Infinity");
    1425             :     }
    1426             :     { // +Infinity
    1427           1 :         as2js::Float64 j;
    1428           1 :         as2js::Node::pointer_t node(new as2js::Node(as2js::Node::node_t::NODE_FLOAT64));
    1429           1 :         j.set_infinity();
    1430           1 :         j.set(-j.get());
    1431           1 :         node->set_float64(j);
    1432           1 :         CPPUNIT_ASSERT(node->to_int64());
    1433           1 :         CPPUNIT_ASSERT(node->get_type() == as2js::Node::node_t::NODE_INT64);
    1434           1 :         CPPUNIT_ASSERT(node->get_int64().get() == 0);
    1435             :     }
    1436           1 : }
    1437             : 
    1438             : 
    1439           1 : void As2JsNodeUnitTests::test_tree()
    1440             : {
    1441             :     class TrackedNode : public as2js::Node
    1442             :     {
    1443             :     public:
    1444       29102 :         TrackedNode(as2js::Node::node_t type, int& count)
    1445             :             : Node(type)
    1446       29102 :             , f_count(count)
    1447             :         {
    1448       29102 :             ++f_count;
    1449       29102 :         }
    1450             : 
    1451       29102 :         ~TrackedNode()
    1452       29102 :         {
    1453       29102 :             --f_count;
    1454       29102 :         }
    1455             : 
    1456             :     private:
    1457             :         int&        f_count;
    1458             :     };
    1459             : 
    1460             :     // counter to know how many nodes we currently have allocated
    1461           1 :     int counter(0);
    1462             : 
    1463             :     // a few basic tests
    1464             :     {
    1465           1 :         as2js::Node::pointer_t parent(new TrackedNode(as2js::Node::node_t::NODE_DIRECTIVE_LIST, counter));
    1466             : 
    1467           1 :         CPPUNIT_ASSERT_THROW(parent->get_child(-1), std::out_of_range);
    1468           1 :         CPPUNIT_ASSERT_THROW(parent->get_child(0), std::out_of_range);
    1469           1 :         CPPUNIT_ASSERT_THROW(parent->get_child(1), std::out_of_range);
    1470             : 
    1471             :         // now we properly test whether the append_child(),
    1472             :         // insert_child(), and set_child() functions are used
    1473             :         // with a null pointer (which is considered illegal)
    1474           2 :         as2js::Node::pointer_t null_pointer;
    1475           1 :         CPPUNIT_ASSERT_THROW(parent->append_child(null_pointer), as2js::exception_invalid_data);
    1476           1 :         CPPUNIT_ASSERT_THROW(parent->insert_child(123, null_pointer), as2js::exception_invalid_data);
    1477           1 :         CPPUNIT_ASSERT_THROW(parent->set_child(9, null_pointer), as2js::exception_invalid_data);
    1478             : 
    1479          21 :         for(int i(0); i < 20; ++i)
    1480             :         {
    1481          20 :             as2js::Node::pointer_t child(new TrackedNode(as2js::Node::node_t::NODE_DIRECTIVE_LIST, counter));
    1482          20 :             parent->append_child(child);
    1483             : 
    1484          20 :             CPPUNIT_ASSERT_THROW(parent->get_child(-1), std::out_of_range);
    1485         230 :             for(int j(0); j <= i; ++j)
    1486             :             {
    1487         210 :                 parent->get_child(j);
    1488             :             }
    1489          20 :             CPPUNIT_ASSERT_THROW(parent->get_child(i + 1), std::out_of_range);
    1490          20 :             CPPUNIT_ASSERT_THROW(parent->get_child(i + 2), std::out_of_range);
    1491          21 :         }
    1492             :     }
    1493             : 
    1494             :     // first test: try with all types as the parent and children
    1495         171 :     for(size_t i(0); i < g_node_types_size; ++i)
    1496             :     {
    1497             :         // type
    1498         170 :         as2js::Node::node_t parent_type(g_node_types[i].f_type);
    1499             : 
    1500         170 :         as2js::Node::pointer_t parent(new TrackedNode(parent_type, counter));
    1501         170 :         CPPUNIT_ASSERT(parent->get_children_size() == 0);
    1502             : 
    1503         170 :         size_t valid_children(0);
    1504       29070 :         for(size_t j(0); j < g_node_types_size; ++j)
    1505             :         {
    1506       28900 :             as2js::Node::node_t child_type(g_node_types[j].f_type);
    1507             : 
    1508       28900 :             as2js::Node::pointer_t child(new TrackedNode(child_type, counter));
    1509             : 
    1510             : //std::cerr << "parent " << parent->get_type_name() << " child " << child->get_type_name() << "\n";
    1511             :             // some nodes cannot be parents...
    1512       28900 :             switch(parent_type)
    1513             :             {
    1514             :             case as2js::Node::node_t::NODE_ABSTRACT:
    1515             :             case as2js::Node::node_t::NODE_AUTO:
    1516             :             case as2js::Node::node_t::NODE_BOOLEAN:
    1517             :             case as2js::Node::node_t::NODE_BREAK:
    1518             :             case as2js::Node::node_t::NODE_BYTE:
    1519             :             case as2js::Node::node_t::NODE_CLOSE_CURVLY_BRACKET:
    1520             :             case as2js::Node::node_t::NODE_CLOSE_PARENTHESIS:
    1521             :             case as2js::Node::node_t::NODE_CLOSE_SQUARE_BRACKET:
    1522             :             case as2js::Node::node_t::NODE_CHAR:
    1523             :             case as2js::Node::node_t::NODE_COLON:
    1524             :             case as2js::Node::node_t::NODE_COMMA:
    1525             :             case as2js::Node::node_t::NODE_CONST:
    1526             :             case as2js::Node::node_t::NODE_CONTINUE:
    1527             :             case as2js::Node::node_t::NODE_DEFAULT:
    1528             :             case as2js::Node::node_t::NODE_DOUBLE:
    1529             :             case as2js::Node::node_t::NODE_ELSE:
    1530             :             case as2js::Node::node_t::NODE_THEN:
    1531             :             case as2js::Node::node_t::NODE_EMPTY:
    1532             :             case as2js::Node::node_t::NODE_EOF:
    1533             :             case as2js::Node::node_t::NODE_IDENTIFIER:
    1534             :             case as2js::Node::node_t::NODE_INLINE:
    1535             :             case as2js::Node::node_t::NODE_INT64:
    1536             :             case as2js::Node::node_t::NODE_FALSE:
    1537             :             case as2js::Node::node_t::NODE_FINAL:
    1538             :             case as2js::Node::node_t::NODE_FLOAT:
    1539             :             case as2js::Node::node_t::NODE_FLOAT64:
    1540             :             case as2js::Node::node_t::NODE_GOTO:
    1541             :             case as2js::Node::node_t::NODE_LONG:
    1542             :             case as2js::Node::node_t::NODE_NATIVE:
    1543             :             case as2js::Node::node_t::NODE_NULL:
    1544             :             case as2js::Node::node_t::NODE_OPEN_CURVLY_BRACKET:
    1545             :             case as2js::Node::node_t::NODE_OPEN_PARENTHESIS:
    1546             :             case as2js::Node::node_t::NODE_OPEN_SQUARE_BRACKET:
    1547             :             case as2js::Node::node_t::NODE_PRIVATE:
    1548             :             case as2js::Node::node_t::NODE_PROTECTED:
    1549             :             case as2js::Node::node_t::NODE_PUBLIC:
    1550             :             case as2js::Node::node_t::NODE_REGULAR_EXPRESSION:
    1551             :             case as2js::Node::node_t::NODE_REST:
    1552             :             case as2js::Node::node_t::NODE_SEMICOLON:
    1553             :             case as2js::Node::node_t::NODE_SHORT:
    1554             :             case as2js::Node::node_t::NODE_STRING:
    1555             :             case as2js::Node::node_t::NODE_STATIC:
    1556             :             case as2js::Node::node_t::NODE_THIS:
    1557             :             case as2js::Node::node_t::NODE_TRANSIENT:
    1558             :             case as2js::Node::node_t::NODE_TRUE:
    1559             :             case as2js::Node::node_t::NODE_UNDEFINED:
    1560             :             case as2js::Node::node_t::NODE_VIDENTIFIER:
    1561             :             case as2js::Node::node_t::NODE_VOID:
    1562             :             case as2js::Node::node_t::NODE_VOLATILE:
    1563             :                 // append child to parent must fail
    1564        8330 :                 if(rand() & 1)
    1565             :                 {
    1566        4098 :                     CPPUNIT_ASSERT_THROW(parent->append_child(child), as2js::exception_incompatible_node_type);
    1567             :                 }
    1568             :                 else
    1569             :                 {
    1570        4232 :                     CPPUNIT_ASSERT_THROW(child->set_parent(parent), as2js::exception_incompatible_node_type);
    1571             :                 }
    1572        8330 :                 break;
    1573             : 
    1574             :             default:
    1575       20570 :                 switch(child_type)
    1576             :                 {
    1577             :                 case as2js::Node::node_t::NODE_CLOSE_CURVLY_BRACKET:
    1578             :                 case as2js::Node::node_t::NODE_CLOSE_PARENTHESIS:
    1579             :                 case as2js::Node::node_t::NODE_CLOSE_SQUARE_BRACKET:
    1580             :                 case as2js::Node::node_t::NODE_COLON:
    1581             :                 case as2js::Node::node_t::NODE_COMMA:
    1582             :                 case as2js::Node::node_t::NODE_ELSE:
    1583             :                 case as2js::Node::node_t::NODE_THEN:
    1584             :                 case as2js::Node::node_t::NODE_EOF:
    1585             :                 case as2js::Node::node_t::NODE_OPEN_CURVLY_BRACKET:
    1586             :                 case as2js::Node::node_t::NODE_OPEN_PARENTHESIS:
    1587             :                 case as2js::Node::node_t::NODE_OPEN_SQUARE_BRACKET:
    1588             :                 case as2js::Node::node_t::NODE_ROOT:
    1589             :                 case as2js::Node::node_t::NODE_SEMICOLON:
    1590             :                     // append child to parent must fail
    1591        1573 :                     if(rand() & 1)
    1592             :                     {
    1593         769 :                         CPPUNIT_ASSERT_THROW(parent->append_child(child), as2js::exception_incompatible_node_type);
    1594             :                     }
    1595             :                     else
    1596             :                     {
    1597         804 :                         CPPUNIT_ASSERT_THROW(child->set_parent(parent), as2js::exception_incompatible_node_type);
    1598             :                     }
    1599        1573 :                     break;
    1600             : 
    1601             :                 default:
    1602             :                     // append child to parent
    1603       18997 :                     if(rand() & 1)
    1604             :                     {
    1605        9546 :                         parent->append_child(child);
    1606             :                     }
    1607             :                     else
    1608             :                     {
    1609        9451 :                         child->set_parent(parent);
    1610             :                     }
    1611             : 
    1612       18997 :                     CPPUNIT_ASSERT(parent->get_children_size() == valid_children + 1);
    1613       18997 :                     CPPUNIT_ASSERT(child->get_parent() == parent);
    1614       18997 :                     CPPUNIT_ASSERT(child->get_offset() == valid_children);
    1615       18997 :                     CPPUNIT_ASSERT(parent->get_child(valid_children) == child);
    1616       18997 :                     CPPUNIT_ASSERT(parent->find_first_child(child_type) == child);
    1617       18997 :                     CPPUNIT_ASSERT(!parent->find_next_child(child, child_type));
    1618             : 
    1619       18997 :                     ++valid_children;
    1620       18997 :                     break;
    1621             : 
    1622             :                 }
    1623       20570 :                 break;
    1624             : 
    1625             :             }
    1626       28900 :         }
    1627         170 :     }
    1628             : 
    1629             :     // we deleted as many nodes as we created
    1630           1 :     CPPUNIT_ASSERT(counter == 0);
    1631             : 
    1632             :     // Test a more realistic tree with a few nodes and make sure we
    1633             :     // can apply certain function and that the tree exactly results
    1634             :     // in what we expect
    1635             :     {
    1636             :         // 1. Create the following in directive a:
    1637             :         //
    1638             :         //  // first block (directive_a)
    1639             :         //  {
    1640             :         //      a = Math.e ** 1.424;
    1641             :         //  }
    1642             :         //  // second block (directive_b)
    1643             :         //  {
    1644             :         //  }
    1645             :         //
    1646             :         // 2. Move it to directive b
    1647             :         //
    1648             :         //  // first block (directive_a)
    1649             :         //  {
    1650             :         //  }
    1651             :         //  // second block (directive_b)
    1652             :         //  {
    1653             :         //      a = Math.e ** 1.424;
    1654             :         //  }
    1655             :         //
    1656             :         // 3. Verify that it worked
    1657             :         //
    1658             : 
    1659             :         // create all the nodes as the lexer would do
    1660           1 :         as2js::Node::pointer_t root(new TrackedNode(as2js::Node::node_t::NODE_ROOT, counter));
    1661           2 :         as2js::Position pos;
    1662           1 :         pos.reset_counters(22);
    1663           1 :         pos.set_filename("test.js");
    1664           1 :         root->set_position(pos);
    1665           2 :         as2js::Node::pointer_t directive_list_a(new TrackedNode(as2js::Node::node_t::NODE_DIRECTIVE_LIST, counter));
    1666           2 :         as2js::Node::pointer_t directive_list_b(new TrackedNode(as2js::Node::node_t::NODE_DIRECTIVE_LIST, counter));
    1667           2 :         as2js::Node::pointer_t assignment(new TrackedNode(as2js::Node::node_t::NODE_ASSIGNMENT, counter));
    1668           2 :         as2js::Node::pointer_t identifier_a(new TrackedNode(as2js::Node::node_t::NODE_IDENTIFIER, counter));
    1669           1 :         identifier_a->set_string("a");
    1670           2 :         as2js::Node::pointer_t power(new TrackedNode(as2js::Node::node_t::NODE_POWER, counter));
    1671           2 :         as2js::Node::pointer_t member(new TrackedNode(as2js::Node::node_t::NODE_MEMBER, counter));
    1672           2 :         as2js::Node::pointer_t identifier_math(new TrackedNode(as2js::Node::node_t::NODE_IDENTIFIER, counter));
    1673           1 :         identifier_math->set_string("Math");
    1674           2 :         as2js::Node::pointer_t identifier_e(new TrackedNode(as2js::Node::node_t::NODE_IDENTIFIER, counter));
    1675           1 :         identifier_e->set_string("e");
    1676           2 :         as2js::Node::pointer_t literal(new TrackedNode(as2js::Node::node_t::NODE_FLOAT64, counter));
    1677           1 :         as2js::Float64 f;
    1678           1 :         f.set(1.424);
    1679           1 :         literal->set_float64(f);
    1680             : 
    1681             :         // build the tree as the parser would do
    1682           1 :         root->append_child(directive_list_a);
    1683           1 :         root->append_child(directive_list_b);
    1684           1 :         directive_list_a->append_child(assignment);
    1685           1 :         assignment->append_child(identifier_a);
    1686           1 :         assignment->insert_child(-1, power);
    1687           1 :         power->append_child(member);
    1688           1 :         CPPUNIT_ASSERT_THROW(power->insert_child(10, literal), as2js::exception_index_out_of_range);
    1689           1 :         power->insert_child(1, literal);
    1690           1 :         member->append_child(identifier_e);
    1691           1 :         member->insert_child(0, identifier_math);
    1692             : 
    1693             :         // verify we can unlock mid-way
    1694           2 :         as2js::NodeLock temp_lock(member);
    1695           1 :         CPPUNIT_ASSERT(member->is_locked());
    1696           1 :         temp_lock.unlock();
    1697           1 :         CPPUNIT_ASSERT(!member->is_locked());
    1698             : 
    1699             :         // as a complement to testing the lock, make sure that emptiness
    1700             :         // (i.e. null pointer) is properly handled all the way
    1701             :         {
    1702           1 :             as2js::Node::pointer_t empty;
    1703           1 :             as2js::NodeLock empty_lock(empty);
    1704             :         }
    1705             :         {
    1706           1 :             as2js::Node::pointer_t empty;
    1707           2 :             as2js::NodeLock empty_lock(empty);
    1708           2 :             empty_lock.unlock();
    1709             :         }
    1710             : 
    1711             :         // apply some tests
    1712           1 :         CPPUNIT_ASSERT(root->get_children_size() == 2);
    1713           1 :         CPPUNIT_ASSERT(directive_list_a->get_children_size() == 1);
    1714           1 :         CPPUNIT_ASSERT(directive_list_a->get_child(0) == assignment);
    1715           1 :         CPPUNIT_ASSERT(directive_list_b->get_children_size() == 0);
    1716           1 :         CPPUNIT_ASSERT(assignment->get_children_size() == 2);
    1717           1 :         CPPUNIT_ASSERT(assignment->get_child(0) == identifier_a);
    1718           1 :         CPPUNIT_ASSERT(assignment->get_child(1) == power);
    1719           1 :         CPPUNIT_ASSERT(identifier_a->get_children_size() == 0);
    1720           1 :         CPPUNIT_ASSERT(power->get_children_size() == 2);
    1721           1 :         CPPUNIT_ASSERT(power->get_child(0) == member);
    1722           1 :         CPPUNIT_ASSERT(power->get_child(1) == literal);
    1723           1 :         CPPUNIT_ASSERT(member->get_children_size() == 2);
    1724           1 :         CPPUNIT_ASSERT(member->get_child(0) == identifier_math);
    1725           1 :         CPPUNIT_ASSERT(member->get_child(1) == identifier_e);
    1726           1 :         CPPUNIT_ASSERT(identifier_math->get_children_size() == 0);
    1727           1 :         CPPUNIT_ASSERT(identifier_e->get_children_size() == 0);
    1728           1 :         CPPUNIT_ASSERT(literal->get_children_size() == 0);
    1729             : 
    1730           1 :         CPPUNIT_ASSERT(root->has_side_effects());
    1731           1 :         CPPUNIT_ASSERT(directive_list_a->has_side_effects());
    1732           1 :         CPPUNIT_ASSERT(!directive_list_b->has_side_effects());
    1733           1 :         CPPUNIT_ASSERT(!power->has_side_effects());
    1734             : 
    1735             :         // now move the assignment from a to b
    1736           1 :         assignment->set_parent(directive_list_b);
    1737             : 
    1738           1 :         CPPUNIT_ASSERT(root->get_children_size() == 2);
    1739           1 :         CPPUNIT_ASSERT(directive_list_a->get_children_size() == 0);
    1740           1 :         CPPUNIT_ASSERT(directive_list_b->get_children_size() == 1);
    1741           1 :         CPPUNIT_ASSERT(directive_list_b->get_child(0) == assignment);
    1742           1 :         CPPUNIT_ASSERT(assignment->get_children_size() == 2);
    1743           1 :         CPPUNIT_ASSERT(assignment->get_child(0) == identifier_a);
    1744           1 :         CPPUNIT_ASSERT(assignment->get_child(1) == power);
    1745           1 :         CPPUNIT_ASSERT(identifier_a->get_children_size() == 0);
    1746           1 :         CPPUNIT_ASSERT(power->get_children_size() == 2);
    1747           1 :         CPPUNIT_ASSERT(power->get_child(0) == member);
    1748           1 :         CPPUNIT_ASSERT(power->get_child(1) == literal);
    1749           1 :         CPPUNIT_ASSERT(member->get_children_size() == 2);
    1750           1 :         CPPUNIT_ASSERT(member->get_child(0) == identifier_math);
    1751           1 :         CPPUNIT_ASSERT(member->get_child(1) == identifier_e);
    1752           1 :         CPPUNIT_ASSERT(identifier_math->get_children_size() == 0);
    1753           1 :         CPPUNIT_ASSERT(identifier_e->get_children_size() == 0);
    1754           1 :         CPPUNIT_ASSERT(literal->get_children_size() == 0);
    1755             : 
    1756           1 :         power->delete_child(0);
    1757           1 :         CPPUNIT_ASSERT(power->get_children_size() == 1);
    1758           1 :         CPPUNIT_ASSERT(power->get_child(0) == literal);
    1759             : 
    1760           1 :         power->insert_child(0, member);
    1761           1 :         CPPUNIT_ASSERT(power->get_children_size() == 2);
    1762           1 :         CPPUNIT_ASSERT(power->get_child(0) == member);
    1763           1 :         CPPUNIT_ASSERT(power->get_child(1) == literal);
    1764             : 
    1765           1 :         CPPUNIT_ASSERT(root->has_side_effects());
    1766           1 :         CPPUNIT_ASSERT(!directive_list_a->has_side_effects());
    1767           1 :         CPPUNIT_ASSERT(directive_list_b->has_side_effects());
    1768           1 :         CPPUNIT_ASSERT(!power->has_side_effects());
    1769             : 
    1770             :         // create a new literal
    1771           2 :         as2js::Node::pointer_t literal_seven(new TrackedNode(as2js::Node::node_t::NODE_FLOAT64, counter));
    1772           1 :         as2js::Float64 f7;
    1773           1 :         f7.set(-7.33312);
    1774           1 :         literal_seven->set_float64(f7);
    1775           1 :         directive_list_a->append_child(literal_seven);
    1776           1 :         CPPUNIT_ASSERT(directive_list_a->get_children_size() == 1);
    1777           1 :         CPPUNIT_ASSERT(directive_list_a->get_child(0) == literal_seven);
    1778             : 
    1779             :         // now replace the old literal with the new one (i.e. a full move actually)
    1780           1 :         power->set_child(1, literal_seven);
    1781           1 :         CPPUNIT_ASSERT(power->get_children_size() == 2);
    1782           1 :         CPPUNIT_ASSERT(power->get_child(0) == member);
    1783           1 :         CPPUNIT_ASSERT(power->get_child(1) == literal_seven);
    1784             : 
    1785             :         // replace with itself should work just fine
    1786           1 :         power->set_child(0, member);
    1787           1 :         CPPUNIT_ASSERT(power->get_children_size() == 2);
    1788           1 :         CPPUNIT_ASSERT(power->get_child(0) == member);
    1789           1 :         CPPUNIT_ASSERT(power->get_child(1) == literal_seven);
    1790             : 
    1791             :         // verify that a replace fails if the node pointer is null
    1792           2 :         as2js::Node::pointer_t null_pointer;
    1793           1 :         CPPUNIT_ASSERT_THROW(literal_seven->replace_with(null_pointer), as2js::exception_invalid_data);
    1794             : 
    1795             :         // replace with the old literal
    1796           1 :         literal_seven->replace_with(literal);
    1797           1 :         CPPUNIT_ASSERT(power->get_children_size() == 2);
    1798           1 :         CPPUNIT_ASSERT(power->get_child(0) == member);
    1799           1 :         CPPUNIT_ASSERT(power->get_child(1) == literal);
    1800             : 
    1801             :         // verify that a node without a parent generates an exception
    1802           1 :         CPPUNIT_ASSERT_THROW(root->replace_with(literal_seven), as2js::exception_no_parent);
    1803             : 
    1804             :         // verify that we cannot get an offset on a node without a parent
    1805           1 :         CPPUNIT_ASSERT_THROW(root->get_offset(), as2js::exception_no_parent);
    1806             : 
    1807             :         // check out our tree textually
    1808             :         //std::cout << std::endl << *root << std::endl;
    1809             : 
    1810             :         // finally mark a node as unknown and call clean_tree()
    1811           1 :         CPPUNIT_ASSERT(!member->is_locked());
    1812             :         {
    1813           1 :             as2js::NodeLock lock(member);
    1814           1 :             CPPUNIT_ASSERT(member->is_locked());
    1815           1 :             CPPUNIT_ASSERT_THROW(member->to_unknown(), as2js::exception_locked_node);
    1816           1 :             CPPUNIT_ASSERT(member->get_type() == as2js::Node::node_t::NODE_MEMBER);
    1817             :         }
    1818           1 :         CPPUNIT_ASSERT(!member->is_locked());
    1819             :         // try too many unlock!
    1820           1 :         CPPUNIT_ASSERT_THROW(member->unlock(), as2js::exception_internal_error);
    1821           1 :         member->to_unknown();
    1822           1 :         CPPUNIT_ASSERT(member->get_type() == as2js::Node::node_t::NODE_UNKNOWN);
    1823             :         {
    1824           1 :             as2js::NodeLock lock(member);
    1825           1 :             CPPUNIT_ASSERT_THROW(root->clean_tree(), as2js::exception_locked_node);
    1826           1 :             CPPUNIT_ASSERT(member->get_type() == as2js::Node::node_t::NODE_UNKNOWN);
    1827           1 :             CPPUNIT_ASSERT(member->get_parent());
    1828             :         }
    1829           1 :         root->clean_tree();
    1830             : 
    1831             :         // manual lock, no unlock before deletion...
    1832             :         {
    1833           1 :             as2js::Node *bad_lock(new as2js::Node(as2js::Node::node_t::NODE_UNKNOWN));
    1834           1 :             bad_lock->lock();
    1835           1 :             bool success(false);
    1836             :             try
    1837             :             {
    1838             :                 // Somehow it looks like the message is not being checked
    1839             :                 //test_callback c;
    1840             :                 //c.f_expected_message_level = as2js::message_level_t::MESSAGE_LEVEL_FATAL;
    1841             :                 //c.f_expected_error_code = as2js::err_code_t::AS_ERR_NOT_ALLOWED;
    1842             :                 //c.f_expected_pos.set_filename("unknown-file");
    1843             :                 //c.f_expected_pos.set_function("unknown-func");
    1844             :                 //c.f_expected_message = "a node got deleted while still locked.";
    1845             : 
    1846           1 :                 delete bad_lock;
    1847             :             }
    1848           2 :             catch(as2js::exception_exit const&)
    1849             :             {
    1850             :                 // NOTE: because of the exception we get a leak here
    1851             :                 //       (i.e. exception in a destructor!!!)
    1852           1 :                 success = true;
    1853             :             }
    1854             :             catch(...)
    1855             :             {
    1856             :                 CPPUNIT_ASSERT(!"delete bad_lock; generated the wrong exception");
    1857             :             }
    1858           1 :             if(!success)
    1859             :             {
    1860           0 :                 CPPUNIT_ASSERT(!"delete bad_lock; did not generate an exception");
    1861             :             }
    1862             :         }
    1863             : 
    1864             :         // check that the tree looks as expected
    1865           1 :         CPPUNIT_ASSERT(root->get_children_size() == 2);
    1866           1 :         CPPUNIT_ASSERT(directive_list_a->get_children_size() == 0);
    1867           1 :         CPPUNIT_ASSERT(directive_list_b->get_children_size() == 1);
    1868           1 :         CPPUNIT_ASSERT(directive_list_b->get_child(0) == assignment);
    1869           1 :         CPPUNIT_ASSERT(assignment->get_children_size() == 2);
    1870           1 :         CPPUNIT_ASSERT(assignment->get_child(0) == identifier_a);
    1871           1 :         CPPUNIT_ASSERT(assignment->get_child(1) == power);
    1872           1 :         CPPUNIT_ASSERT(identifier_a->get_children_size() == 0);
    1873           1 :         CPPUNIT_ASSERT(power->get_children_size() == 1);
    1874             :         // Although member is not in the tree anymore, its children
    1875             :         // are still there as expected (because we hold a smart pointers
    1876             :         // to all of that)
    1877             :         //CPPUNIT_ASSERT(power->get_child(0) == member);
    1878           1 :         CPPUNIT_ASSERT(power->get_child(0) == literal);
    1879           1 :         CPPUNIT_ASSERT(!member->get_parent());
    1880           1 :         CPPUNIT_ASSERT(member->get_children_size() == 2);
    1881           1 :         CPPUNIT_ASSERT(member->get_child(0) == identifier_math);
    1882           1 :         CPPUNIT_ASSERT(member->get_child(1) == identifier_e);
    1883           1 :         CPPUNIT_ASSERT(identifier_math->get_children_size() == 0);
    1884           1 :         CPPUNIT_ASSERT(identifier_math->get_parent() == member);
    1885           1 :         CPPUNIT_ASSERT(identifier_e->get_children_size() == 0);
    1886           1 :         CPPUNIT_ASSERT(identifier_e->get_parent() == member);
    1887           2 :         CPPUNIT_ASSERT(literal->get_children_size() == 0);
    1888             :     }
    1889             : 
    1890             :     // we again deleted as many nodes as we created
    1891           1 :     CPPUNIT_ASSERT(counter == 0);
    1892           1 : }
    1893             : 
    1894             : 
    1895           1 : void As2JsNodeUnitTests::test_param()
    1896             : {
    1897             :     {
    1898           1 :         as2js::Node::pointer_t match(new as2js::Node(as2js::Node::node_t::NODE_PARAM_MATCH));
    1899             : 
    1900           1 :         CPPUNIT_ASSERT(match->get_param_size() == 0);
    1901             : 
    1902             :         // zero is not acceptable
    1903           1 :         CPPUNIT_ASSERT_THROW(match->set_param_size(0), as2js::exception_internal_error);
    1904             : 
    1905           1 :         match->set_param_size(5);
    1906           1 :         CPPUNIT_ASSERT(match->get_param_size() == 5);
    1907             : 
    1908             :         // cannot change the size once set
    1909           1 :         CPPUNIT_ASSERT_THROW(match->set_param_size(10), as2js::exception_internal_error);
    1910             : 
    1911           1 :         CPPUNIT_ASSERT(match->get_param_size() == 5);
    1912             : 
    1913             :         // first set the depth, try with an out of range index too
    1914           6 :         for(int i(-5); i < 0; ++i)
    1915             :         {
    1916           5 :             CPPUNIT_ASSERT_THROW(match->set_param_depth(i, rand()), std::out_of_range);
    1917             :         }
    1918             :         ssize_t depths[5];
    1919           6 :         for(int i(0); i < 5; ++i)
    1920             :         {
    1921           5 :             depths[i] = rand();
    1922           5 :             match->set_param_depth(i, depths[i]);
    1923             :         }
    1924           7 :         for(int i(5); i <= 10; ++i)
    1925             :         {
    1926           6 :             CPPUNIT_ASSERT_THROW(match->set_param_depth(i, rand()), std::out_of_range);
    1927             :         }
    1928             : 
    1929             :         // now test that what we saved can be read back, also with some out of range
    1930           6 :         for(int i(-5); i < 0; ++i)
    1931             :         {
    1932           5 :             CPPUNIT_ASSERT_THROW(match->get_param_depth(i), std::out_of_range);
    1933             :         }
    1934           6 :         for(int i(0); i < 5; ++i)
    1935             :         {
    1936           5 :             CPPUNIT_ASSERT(match->get_param_depth(i) == depths[i]);
    1937             :         }
    1938           6 :         for(int i(5); i < 10; ++i)
    1939             :         {
    1940           5 :             CPPUNIT_ASSERT_THROW(match->get_param_depth(i), std::out_of_range);
    1941             :         }
    1942             : 
    1943             :         // second set the index, try with an out of range index too
    1944           6 :         for(int i(-5); i < 0; ++i)
    1945             :         {
    1946           5 :             CPPUNIT_ASSERT_THROW(match->set_param_index(i, rand() % 5), std::out_of_range);
    1947           5 :             CPPUNIT_ASSERT_THROW(match->set_param_index(i, rand()), std::out_of_range);
    1948             :         }
    1949             :         size_t index[5];
    1950           6 :         for(int i(0); i < 5; ++i)
    1951             :         {
    1952           5 :             index[i] = rand() % 5;
    1953           5 :             match->set_param_index(i, index[i]);
    1954             : 
    1955             :             // if 'j' is invalid, then just throw
    1956             :             // and do not change the valid value
    1957          55 :             for(int k(0); k < 10; ++k)
    1958             :             {
    1959          50 :                 int j(0);
    1960          50 :                 do
    1961             :                 {
    1962          50 :                     j = rand();
    1963             :                 }
    1964          50 :                 while(j >= 0 && j <= 5);
    1965          50 :                 CPPUNIT_ASSERT_THROW(match->set_param_index(i, j), std::out_of_range);
    1966             :             }
    1967             :         }
    1968           7 :         for(int i(5); i <= 10; ++i)
    1969             :         {
    1970           6 :             CPPUNIT_ASSERT_THROW(match->set_param_index(i, rand() % 5), std::out_of_range);
    1971           6 :             CPPUNIT_ASSERT_THROW(match->set_param_index(i, rand()), std::out_of_range);
    1972             :         }
    1973             : 
    1974             :         // now test that what we saved can be read back, also with some out of range
    1975           6 :         for(int i(-5); i < 0; ++i)
    1976             :         {
    1977           5 :             CPPUNIT_ASSERT_THROW(match->get_param_index(i), std::out_of_range);
    1978             :         }
    1979           6 :         for(int i(0); i < 5; ++i)
    1980             :         {
    1981           5 :             CPPUNIT_ASSERT(match->get_param_index(i) == index[i]);
    1982             :         }
    1983           6 :         for(int i(5); i < 10; ++i)
    1984             :         {
    1985           5 :             CPPUNIT_ASSERT_THROW(match->get_param_index(i), std::out_of_range);
    1986           1 :         }
    1987             :     }
    1988           1 : }
    1989             : 
    1990             : 
    1991           1 : void As2JsNodeUnitTests::test_position()
    1992             : {
    1993           1 :     as2js::Position pos;
    1994           1 :     pos.set_filename("file.js");
    1995           1 :     int total_line(1);
    1996          10 :     for(int page(1); page < 10; ++page)
    1997             :     {
    1998           9 :         int paragraphs(rand() % 10 + 10);
    1999           9 :         int page_line(1);
    2000           9 :         int paragraph(1);
    2001         900 :         for(int line(1); line < 100; ++line)
    2002             :         {
    2003         891 :             CPPUNIT_ASSERT(pos.get_page() == page);
    2004         891 :             CPPUNIT_ASSERT(pos.get_page_line() == page_line);
    2005         891 :             CPPUNIT_ASSERT(pos.get_paragraph() == paragraph);
    2006         891 :             CPPUNIT_ASSERT(pos.get_line() == total_line);
    2007             : 
    2008         891 :             std::stringstream pos_str;
    2009         891 :             pos_str << pos;
    2010        1782 :             std::stringstream test_str;
    2011         891 :             test_str << "file.js:" << total_line << ":";
    2012         891 :             CPPUNIT_ASSERT(pos_str.str() == test_str.str());
    2013             : 
    2014             :             // create any valid type of node
    2015         891 :             size_t const idx(rand() % g_node_types_size);
    2016        1782 :             as2js::Node::pointer_t node(new as2js::Node(g_node_types[idx].f_type));
    2017             : 
    2018             :             // set our current position in there
    2019         891 :             node->set_position(pos);
    2020             : 
    2021             :             // verify that the node position is equal to ours
    2022         891 :             as2js::Position const& node_pos(node->get_position());
    2023         891 :             CPPUNIT_ASSERT(node_pos.get_page() == page);
    2024         891 :             CPPUNIT_ASSERT(node_pos.get_page_line() == page_line);
    2025         891 :             CPPUNIT_ASSERT(node_pos.get_paragraph() == paragraph);
    2026         891 :             CPPUNIT_ASSERT(node_pos.get_line() == total_line);
    2027             : 
    2028        1782 :             std::stringstream node_pos_str;
    2029         891 :             node_pos_str << node_pos;
    2030        1782 :             std::stringstream node_test_str;
    2031         891 :             node_test_str << "file.js:" << total_line << ":";
    2032         891 :             CPPUNIT_ASSERT(node_pos_str.str() == node_test_str.str());
    2033             : 
    2034             :             // create a replacement now
    2035         891 :             size_t const idx_replacement(rand() % g_node_types_size);
    2036        1782 :             as2js::Node::pointer_t replacement(node->create_replacement(g_node_types[idx_replacement].f_type));
    2037             : 
    2038             :             // verify that the replacement position is equal to ours
    2039             :             // (and thus the node's)
    2040         891 :             as2js::Position const& replacement_pos(node->get_position());
    2041         891 :             CPPUNIT_ASSERT(replacement_pos.get_page() == page);
    2042         891 :             CPPUNIT_ASSERT(replacement_pos.get_page_line() == page_line);
    2043         891 :             CPPUNIT_ASSERT(replacement_pos.get_paragraph() == paragraph);
    2044         891 :             CPPUNIT_ASSERT(replacement_pos.get_line() == total_line);
    2045             : 
    2046        1782 :             std::stringstream replacement_pos_str;
    2047         891 :             replacement_pos_str << replacement_pos;
    2048        1782 :             std::stringstream replacement_test_str;
    2049         891 :             replacement_test_str << "file.js:" << total_line << ":";
    2050         891 :             CPPUNIT_ASSERT(replacement_pos_str.str() == replacement_test_str.str());
    2051             : 
    2052             :             // verify that the node position has not changed
    2053         891 :             as2js::Position const& node_pos2(node->get_position());
    2054         891 :             CPPUNIT_ASSERT(node_pos2.get_page() == page);
    2055         891 :             CPPUNIT_ASSERT(node_pos2.get_page_line() == page_line);
    2056         891 :             CPPUNIT_ASSERT(node_pos2.get_paragraph() == paragraph);
    2057         891 :             CPPUNIT_ASSERT(node_pos2.get_line() == total_line);
    2058             : 
    2059        1782 :             std::stringstream node_pos2_str;
    2060         891 :             node_pos2_str << node_pos2;
    2061        1782 :             std::stringstream node_test2_str;
    2062         891 :             node_test2_str << "file.js:" << total_line << ":";
    2063         891 :             CPPUNIT_ASSERT(node_pos2_str.str() == node_test2_str.str());
    2064             : 
    2065             :             // go to the next line, paragraph, etc.
    2066         891 :             if(line % paragraphs == 0)
    2067             :             {
    2068          56 :                 pos.new_paragraph();
    2069          56 :                 ++paragraph;
    2070             :             }
    2071         891 :             pos.new_line();
    2072         891 :             ++total_line;
    2073         891 :             ++page_line;
    2074         891 :         }
    2075           9 :         pos.new_page();
    2076           1 :     }
    2077             : 
    2078           1 : }
    2079             : 
    2080             : 
    2081           1 : void As2JsNodeUnitTests::test_links()
    2082             : {
    2083          11 :     for(int i(0); i < 10; ++i)
    2084             :     {
    2085             :         // create any valid type of node
    2086          10 :         size_t const idx_node(rand() % g_node_types_size);
    2087          10 :         as2js::Node::pointer_t node(new as2js::Node(g_node_types[idx_node].f_type));
    2088             : 
    2089          10 :         size_t const idx_bad_link(rand() % g_node_types_size);
    2090          20 :         as2js::Node::pointer_t bad_link(new as2js::Node(g_node_types[idx_bad_link].f_type));
    2091             : 
    2092             :         // try with offsets that are too small
    2093          60 :         for(int j(-5); j < 0; ++j)
    2094             :         {
    2095          50 :             CPPUNIT_ASSERT_THROW(node->set_link(static_cast<as2js::Node::link_t>(j), bad_link), std::out_of_range);
    2096             :         }
    2097             : 
    2098             :         // do it with valid offsets
    2099          20 :         as2js::Node::pointer_t links[static_cast<int>(as2js::Node::link_t::LINK_max)];
    2100          60 :         for(int j(0); j < static_cast<int>(as2js::Node::link_t::LINK_max); ++j)
    2101             :         {
    2102             :             // before setting anything we expect nullptr in a link
    2103          50 :             CPPUNIT_ASSERT(node->get_link(static_cast<as2js::Node::link_t>(j)) == as2js::Node::pointer_t());
    2104             : 
    2105          50 :             size_t const idx_link(rand() % g_node_types_size);
    2106          50 :             links[j].reset(new as2js::Node(g_node_types[idx_link].f_type));
    2107          50 :             node->set_link(static_cast<as2js::Node::link_t>(j), links[j]);
    2108             : 
    2109             :             // if already set, setting again fails
    2110          50 :             CPPUNIT_ASSERT_THROW(node->set_link(static_cast<as2js::Node::link_t>(j), bad_link), as2js::exception_already_defined);
    2111             :         }
    2112             : 
    2113             :         // try with offsets that are too large
    2114         110 :         for(int j(static_cast<int>(as2js::Node::link_t::LINK_max)); j < static_cast<int>(as2js::Node::link_t::LINK_max) + 10; ++j)
    2115             :         {
    2116         100 :             CPPUNIT_ASSERT_THROW(node->set_link(static_cast<as2js::Node::link_t>(j), bad_link), std::out_of_range);
    2117             :         }
    2118             : 
    2119             :         // try with offsets that are too small
    2120          60 :         for(int j(-5); j < 0; ++j)
    2121             :         {
    2122          50 :             CPPUNIT_ASSERT_THROW(node->get_link(static_cast<as2js::Node::link_t>(j)), std::out_of_range);
    2123             :         }
    2124             : 
    2125             :         // then verify that the links are indeed valid
    2126          60 :         for(int j(0); j < static_cast<int>(as2js::Node::link_t::LINK_max); ++j)
    2127             :         {
    2128          50 :             CPPUNIT_ASSERT(node->get_link(static_cast<as2js::Node::link_t>(j)) == links[j]);
    2129             :         }
    2130             : 
    2131             :         // try with offsets that are too large
    2132         110 :         for(int j(static_cast<int>(as2js::Node::link_t::LINK_max)); j < static_cast<int>(as2js::Node::link_t::LINK_max) + 10; ++j)
    2133             :         {
    2134         100 :             CPPUNIT_ASSERT_THROW(node->get_link(static_cast<as2js::Node::link_t>(j)), std::out_of_range);
    2135             :         }
    2136             : 
    2137             :         // we can reset a link to set it to another pointer
    2138          60 :         for(int j(0); j < static_cast<int>(as2js::Node::link_t::LINK_max); ++j)
    2139             :         {
    2140          50 :             size_t const idx_link(rand() % g_node_types_size);
    2141          50 :             links[j].reset(new as2js::Node(g_node_types[idx_link].f_type));
    2142             :             // reset
    2143          50 :             node->set_link(static_cast<as2js::Node::link_t>(j), as2js::Node::pointer_t());
    2144             :             // set again
    2145          50 :             node->set_link(static_cast<as2js::Node::link_t>(j), links[j]);
    2146             : 
    2147             :             // and again, if set, it fails
    2148          50 :             CPPUNIT_ASSERT_THROW(node->set_link(static_cast<as2js::Node::link_t>(j), bad_link), as2js::exception_already_defined);
    2149             :         }
    2150          10 :     }
    2151           1 : }
    2152             : 
    2153             : 
    2154           1 : void As2JsNodeUnitTests::test_variables()
    2155             : {
    2156          11 :     for(int i(0); i < 10; ++i)
    2157             :     {
    2158             :         // create any valid type of node
    2159          10 :         size_t const idx_node(rand() % g_node_types_size);
    2160          10 :         as2js::Node::pointer_t node(new as2js::Node(g_node_types[idx_node].f_type));
    2161             : 
    2162             :         // create a node that is not a NODE_VARIABLE
    2163             :         size_t idx_bad_link;
    2164          10 :         do
    2165             :         {
    2166          10 :             idx_bad_link = rand() % g_node_types_size;
    2167             :         }
    2168          10 :         while(g_node_types[idx_bad_link].f_type == as2js::Node::node_t::NODE_VARIABLE);
    2169          20 :         as2js::Node::pointer_t not_variable(new as2js::Node(g_node_types[idx_bad_link].f_type));
    2170          10 :         CPPUNIT_ASSERT_THROW(node->add_variable(not_variable), as2js::exception_incompatible_node_type);
    2171             : 
    2172             :         // add 10 valid variables
    2173          20 :         as2js::Node::pointer_t variables[10];
    2174         110 :         for(size_t j(0); j < 10; ++j)
    2175             :         {
    2176         100 :             CPPUNIT_ASSERT(node->get_variable_size() == j);
    2177             : 
    2178         100 :             variables[j].reset(new as2js::Node(as2js::Node::node_t::NODE_VARIABLE));
    2179         100 :             node->add_variable(variables[j]);
    2180             :         }
    2181          10 :         CPPUNIT_ASSERT(node->get_variable_size() == 10);
    2182             : 
    2183             :         // try with offsets that are too small
    2184          60 :         for(int j(-5); j < 0; ++j)
    2185             :         {
    2186          50 :             CPPUNIT_ASSERT_THROW(node->get_variable(j), std::out_of_range);
    2187             :         }
    2188             : 
    2189             :         // then verify that the links are indeed valid
    2190          60 :         for(int j(0); j < static_cast<int>(as2js::Node::link_t::LINK_max); ++j)
    2191             :         {
    2192          50 :             CPPUNIT_ASSERT(node->get_variable(j) == variables[j]);
    2193             :         }
    2194             : 
    2195             :         // try with offsets that are too large
    2196         110 :         for(int j(10); j < 20; ++j)
    2197             :         {
    2198         100 :             CPPUNIT_ASSERT_THROW(node->get_variable(j), std::out_of_range);
    2199             :         }
    2200          10 :     }
    2201           1 : }
    2202             : 
    2203             : 
    2204           1 : void As2JsNodeUnitTests::test_labels()
    2205             : {
    2206          11 :     for(int i(0); i < 10; ++i)
    2207             :     {
    2208             :         // create a NODE_FUNCTION
    2209          10 :         as2js::Node::pointer_t function(new as2js::Node(as2js::Node::node_t::NODE_FUNCTION));
    2210             : 
    2211             :         // create a node that is not a NODE_LABEL
    2212             :         size_t idx_bad_label;
    2213          10 :         do
    2214             :         {
    2215          10 :             idx_bad_label = rand() % g_node_types_size;
    2216             :         }
    2217          10 :         while(g_node_types[idx_bad_label].f_type == as2js::Node::node_t::NODE_LABEL);
    2218          20 :         as2js::Node::pointer_t not_label(new as2js::Node(g_node_types[idx_bad_label].f_type));
    2219          10 :         CPPUNIT_ASSERT_THROW(function->add_label(not_label), as2js::exception_incompatible_node_type);
    2220             : 
    2221         110 :         for(int j(0); j < 10; ++j)
    2222             :         {
    2223             :             // create a node that is not a NODE_LABEL
    2224         100 :             as2js::Node::pointer_t label(new as2js::Node(as2js::Node::node_t::NODE_LABEL));
    2225             : 
    2226             :             // create a node that is not a NODE_FUNCTION
    2227             :             size_t idx_bad_function;
    2228         100 :             do
    2229             :             {
    2230         100 :                 idx_bad_function = rand() % g_node_types_size;
    2231             :             }
    2232         100 :             while(g_node_types[idx_bad_function].f_type == as2js::Node::node_t::NODE_FUNCTION);
    2233         200 :             as2js::Node::pointer_t not_function(new as2js::Node(g_node_types[idx_bad_function].f_type));
    2234         100 :             CPPUNIT_ASSERT_THROW(not_function->add_label(label), as2js::exception_incompatible_node_type);
    2235             : 
    2236             :             // labels need to have a name
    2237         100 :             CPPUNIT_ASSERT_THROW(function->add_label(label), as2js::exception_incompatible_node_data);
    2238             : 
    2239             :             // save the label with a name
    2240         200 :             std::string label_name("label" + std::to_string(j));
    2241         100 :             label->set_string(label_name);
    2242         100 :             function->add_label(label);
    2243             : 
    2244             :             // trying to add two labels (or the same) with the same name err
    2245         100 :             CPPUNIT_ASSERT_THROW(function->add_label(label), as2js::exception_already_defined);
    2246             : 
    2247             :             // verify that we can find that label
    2248         100 :             CPPUNIT_ASSERT(function->find_label(label_name) == label);
    2249         100 :         }
    2250          10 :     }
    2251           1 : }
    2252             : 
    2253             : 
    2254           1 : void As2JsNodeUnitTests::test_attributes()
    2255             : {
    2256          11 :     for(int i(0); i < 10; ++i)
    2257             :     {
    2258             :         // create a node that is not a NODE_PROGRAM
    2259             :         // (i.e. a node that accepts all attributes)
    2260             :         size_t idx_node;
    2261          10 :         do
    2262             :         {
    2263          10 :             idx_node = rand() % g_node_types_size;
    2264             :         }
    2265          10 :         while(g_node_types[idx_node].f_type == as2js::Node::node_t::NODE_PROGRAM);
    2266          10 :         as2js::Node::pointer_t node(new as2js::Node(g_node_types[idx_node].f_type));
    2267             : 
    2268             :         // need to test all combinatorial cases...
    2269          60 :         for(size_t j(0); j < g_groups_of_attributes_size; ++j)
    2270             :         {
    2271             :             // go through the list of attributes that generate conflicts
    2272         380 :             for(as2js::Node::attribute_t const *attr_list(g_groups_of_attributes[j].f_attributes);
    2273         190 :                                          *attr_list != as2js::Node::attribute_t::NODE_ATTR_max;
    2274             :                                          ++attr_list)
    2275             :             {
    2276         140 :                 as2js::Node::attribute_set_t set;
    2277         140 :                 CPPUNIT_ASSERT(node->compare_all_attributes(set));
    2278             : 
    2279             :                 // set that one attribute first
    2280         140 :                 node->set_attribute(*attr_list, true);
    2281             : 
    2282         140 :                 CPPUNIT_ASSERT(!node->compare_all_attributes(set));
    2283         140 :                 set[static_cast<int>(*attr_list)] = true;
    2284         140 :                 CPPUNIT_ASSERT(node->compare_all_attributes(set));
    2285             : 
    2286         140 :                 as2js::String str(g_attribute_names[static_cast<int>(*attr_list)]);
    2287             : 
    2288             :                 // test against all the other attributes
    2289        3920 :                 for(int a(0); a < static_cast<int>(as2js::Node::attribute_t::NODE_ATTR_max); ++a)
    2290             :                 {
    2291             :                     // no need to test with itself, we do that earlier
    2292        3780 :                     if(static_cast<as2js::Node::attribute_t>(a) == *attr_list)
    2293             :                     {
    2294         140 :                         continue;
    2295             :                     }
    2296             : 
    2297             :                     // is attribute 'a' in conflict with attribute '*attr_list'?
    2298        3640 :                     if(in_conflict(j, *attr_list, static_cast<as2js::Node::attribute_t>(a)))
    2299             :                     {
    2300         320 :                         test_callback c;
    2301         320 :                         c.f_expected_message_level = as2js::message_level_t::MESSAGE_LEVEL_ERROR;
    2302         320 :                         c.f_expected_error_code = as2js::err_code_t::AS_ERR_INVALID_ATTRIBUTES;
    2303         320 :                         c.f_expected_pos.set_filename("unknown-file");
    2304         320 :                         c.f_expected_pos.set_function("unknown-func");
    2305         320 :                         c.f_expected_message = "Attributes " + std::string(g_groups_of_attributes[j].f_names) + " are mutually exclusive. Only one of them can be used.";
    2306             : 
    2307             : //std::cerr << "next conflict: " << c.f_expected_message << "\n";
    2308             :                         // if in conflict, trying to set the flag generates
    2309             :                         // an error
    2310         320 :                         CPPUNIT_ASSERT(!node->get_attribute(static_cast<as2js::Node::attribute_t>(a)));
    2311         320 :                         node->set_attribute(static_cast<as2js::Node::attribute_t>(a), true);
    2312             :                         // the set_attribute() did not change the attribute because it is
    2313             :                         // in conflict with another attribute which is set at this time...
    2314         320 :                         CPPUNIT_ASSERT(!node->get_attribute(static_cast<as2js::Node::attribute_t>(a)));
    2315             :                     }
    2316             :                     else
    2317             :                     {
    2318             :                         // before we set it, always false
    2319             : //std::cerr << "next valid attr: " << static_cast<int>(*attr_list) << " against " << a << "\n";
    2320        3320 :                         CPPUNIT_ASSERT(!node->get_attribute(static_cast<as2js::Node::attribute_t>(a)));
    2321        3320 :                         node->set_attribute(static_cast<as2js::Node::attribute_t>(a), true);
    2322        3320 :                         CPPUNIT_ASSERT(node->get_attribute(static_cast<as2js::Node::attribute_t>(a)));
    2323        3320 :                         node->set_attribute(static_cast<as2js::Node::attribute_t>(a), false);
    2324        3320 :                         CPPUNIT_ASSERT(!node->get_attribute(static_cast<as2js::Node::attribute_t>(a)));
    2325             :                     }
    2326             :                 }
    2327             : 
    2328             :                 // we are done with that loop, restore the attribute to the default
    2329         140 :                 node->set_attribute(*attr_list, false);
    2330         140 :             }
    2331             :         }
    2332          10 :     }
    2333           1 : }
    2334             : 
    2335             : 
    2336             : // is attribute 'a' in conflict with attribute '*attr_list'?
    2337        7280 : bool As2JsNodeUnitTests::in_conflict(size_t j, as2js::Node::attribute_t attr, as2js::Node::attribute_t a) const
    2338             : {
    2339       55840 :     for(as2js::Node::attribute_t const *conflict_list(g_groups_of_attributes[j].f_attributes);
    2340       27920 :                                        *conflict_list != as2js::Node::attribute_t::NODE_ATTR_max;
    2341             :                                        ++conflict_list)
    2342             :     {
    2343       21200 :         if(a == *conflict_list)
    2344             :         {
    2345         560 :             return true;
    2346             :         }
    2347             :     }
    2348             : 
    2349             :     // the following handles exceptions
    2350             :     //
    2351             :     // From the function type:
    2352             :     //  . abstract, constructor, static, virtual
    2353             :     //
    2354             :     // We also get:
    2355             :     //  . abstract / native
    2356             :     //  . abstract / constructor / inline / virtual
    2357        6720 :     switch(attr)
    2358             :     {
    2359             :     case as2js::Node::attribute_t::NODE_ATTR_ABSTRACT:
    2360         460 :         switch(a)
    2361             :         {
    2362             :         case as2js::Node::attribute_t::NODE_ATTR_NATIVE:
    2363             :         case as2js::Node::attribute_t::NODE_ATTR_INLINE:
    2364          40 :             return true;
    2365             :             break;
    2366             : 
    2367             :         default:
    2368         420 :             break;
    2369             : 
    2370             :         }
    2371         420 :         break;
    2372             : 
    2373             :     case as2js::Node::attribute_t::NODE_ATTR_CONSTRUCTOR:
    2374         460 :         switch(a)
    2375             :         {
    2376             :         case as2js::Node::attribute_t::NODE_ATTR_INLINE:
    2377          20 :             return true;
    2378             :             break;
    2379             : 
    2380             :         default:
    2381         440 :             break;
    2382             : 
    2383             :         }
    2384         440 :         break;
    2385             : 
    2386             :     case as2js::Node::attribute_t::NODE_ATTR_INLINE:
    2387           0 :         switch(a)
    2388             :         {
    2389             :         case as2js::Node::attribute_t::NODE_ATTR_ABSTRACT:
    2390             :         case as2js::Node::attribute_t::NODE_ATTR_CONSTRUCTOR:
    2391             :         case as2js::Node::attribute_t::NODE_ATTR_NATIVE:
    2392             :         case as2js::Node::attribute_t::NODE_ATTR_VIRTUAL:
    2393           0 :             return true;
    2394             :             break;
    2395             : 
    2396             :         default:
    2397           0 :             break;
    2398             : 
    2399             :         }
    2400           0 :         break;
    2401             : 
    2402             :     case as2js::Node::attribute_t::NODE_ATTR_NATIVE:
    2403           0 :         switch(a)
    2404             :         {
    2405             :         case as2js::Node::attribute_t::NODE_ATTR_ABSTRACT:
    2406             :         case as2js::Node::attribute_t::NODE_ATTR_INLINE:
    2407           0 :             return true;
    2408             :             break;
    2409             : 
    2410             :         default:
    2411           0 :             break;
    2412             : 
    2413             :         }
    2414           0 :         break;
    2415             : 
    2416             : 
    2417             :     case as2js::Node::attribute_t::NODE_ATTR_VIRTUAL:
    2418         460 :         switch(a)
    2419             :         {
    2420             :         case as2js::Node::attribute_t::NODE_ATTR_INLINE:
    2421          20 :             return true;
    2422             : 
    2423             :         default:
    2424         440 :             break;
    2425             : 
    2426             :         }
    2427         440 :         break;
    2428             : 
    2429             :     default:
    2430        5340 :         break;
    2431             : 
    2432             :     }
    2433             : 
    2434        6640 :     return false;
    2435          12 : }
    2436             : 
    2437             : 
    2438             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.10