LCOV - code coverage report
Current view: top level - tests - test_as2js_json.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1253 1264 99.1 %
Date: 2014-11-22 Functions: 26 27 96.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* test_as2js_json.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_json.h"
      37             : #include    "test_as2js_main.h"
      38             : 
      39             : #include    "as2js/json.h"
      40             : #include    "as2js/exceptions.h"
      41             : #include    "as2js/message.h"
      42             : 
      43             : // See http://icu-project.org/apiref/icu4c/index.html
      44             : #include <unicode/uchar.h>
      45             : //#include <unicode/cuchar> // once available in Linux...
      46             : 
      47             : #include    <unistd.h>
      48             : 
      49             : #include    <limits>
      50             : #include    <cstring>
      51             : #include    <algorithm>
      52             : #include    <iomanip>
      53             : 
      54             : #include    <cppunit/config/SourcePrefix.h>
      55           4 : CPPUNIT_TEST_SUITE_REGISTRATION( As2JsJSONUnitTests );
      56             : 
      57             : namespace
      58             : {
      59             : 
      60             : 
      61        1153 : int32_t generate_string(as2js::String& str, as2js::String& stringified)
      62             : {
      63        1153 :     stringified += '"';
      64             :     as2js::as_char_t c;
      65        1153 :     int32_t used(0);
      66        1153 :     int ctrl(rand() % 7);
      67        1153 :     int const max_chars(rand() % 25 + 5);
      68       20920 :     for(int j(0); j < max_chars; ++j)
      69             :     {
      70       30952 :         do
      71             :         {
      72       30952 :             c = rand() & 0x1FFFFF;
      73       30952 :             if(ctrl == 0)
      74             :             {
      75        7508 :                 ctrl = rand() % 7;
      76        7508 :                 if((ctrl & 3) == 1)
      77             :                 {
      78        2173 :                     c = c & 1 ? '"' : '\'';
      79             :                 }
      80             :                 else
      81             :                 {
      82        5335 :                     c &= 0x1F;
      83             :                 }
      84             :             }
      85             :             else
      86             :             {
      87       23444 :                 --ctrl;
      88             :             }
      89             :         }
      90             :         while(c >= 0x110000
      91       19957 :            || (c >= 0xD800 && c <= 0xDFFF)
      92       19932 :            || ((c & 0xFFFE) == 0xFFFE)
      93       19932 :            || c == '\0');
      94       19767 :         str += c;
      95       19767 :         switch(c)
      96             :         {
      97             :         case '\b':
      98         130 :             stringified += '\\';
      99         130 :             stringified += 'b';
     100         130 :             used |= 0x01;
     101         130 :             break;
     102             : 
     103             :         case '\f':
     104         161 :             stringified += '\\';
     105         161 :             stringified += 'f';
     106         161 :             used |= 0x02;
     107         161 :             break;
     108             : 
     109             :         case '\n':
     110         181 :             stringified += '\\';
     111         181 :             stringified += 'n';
     112         181 :             used |= 0x04;
     113         181 :             break;
     114             : 
     115             :         case '\r':
     116         192 :             stringified += '\\';
     117         192 :             stringified += 'r';
     118         192 :             used |= 0x08;
     119         192 :             break;
     120             : 
     121             :         case '\t':
     122         166 :             stringified += '\\';
     123         166 :             stringified += 't';
     124         166 :             used |= 0x10;
     125         166 :             break;
     126             : 
     127             :         case '"':
     128        1089 :             stringified += '\\';
     129        1089 :             stringified += '"';
     130        1089 :             used |= 0x20;
     131        1089 :             break;
     132             : 
     133             :         case '\'':
     134        1084 :             stringified += '\\';
     135        1084 :             stringified += '\'';
     136        1084 :             used |= 0x40;
     137        1084 :             break;
     138             : 
     139             :         default:
     140       16764 :             if(c < 0x0020)
     141             :             {
     142             :                 // other controls must be escaped using Unicode
     143        4340 :                 std::stringstream ss;
     144        4340 :                 ss << std::hex << "\\u" << std::setfill('0') << std::setw(4) << static_cast<int>(c);
     145        4340 :                 stringified += ss.str().c_str();
     146        4340 :                 used |= 0x80;
     147             :             }
     148             :             else
     149             :             {
     150       12424 :                 stringified += c;
     151             :             }
     152       16764 :             break;
     153             : 
     154             :         }
     155             :     }
     156        1153 :     stringified += '"';
     157             : 
     158        1153 :     return used;
     159             : }
     160             : 
     161             : 
     162         210 : void stringify_string(as2js::String const& str, as2js::String& stringified)
     163             : {
     164         210 :     stringified += '"';
     165         210 :     size_t const max_chars(str.length());
     166        3726 :     for(size_t j(0); j < max_chars; ++j)
     167             :     {
     168        3516 :         as2js::as_char_t c(str[j]);
     169        3516 :         switch(c)
     170             :         {
     171             :         case '\b':
     172          24 :             stringified += '\\';
     173          24 :             stringified += 'b';
     174          24 :             break;
     175             : 
     176             :         case '\f':
     177          15 :             stringified += '\\';
     178          15 :             stringified += 'f';
     179          15 :             break;
     180             : 
     181             :         case '\n':
     182          30 :             stringified += '\\';
     183          30 :             stringified += 'n';
     184          30 :             break;
     185             : 
     186             :         case '\r':
     187          27 :             stringified += '\\';
     188          27 :             stringified += 'r';
     189          27 :             break;
     190             : 
     191             :         case '\t':
     192          30 :             stringified += '\\';
     193          30 :             stringified += 't';
     194          30 :             break;
     195             : 
     196             :         case '"':
     197         210 :             stringified += '\\';
     198         210 :             stringified += '"';
     199         210 :             break;
     200             : 
     201             :         case '\'':
     202         168 :             stringified += '\\';
     203         168 :             stringified += '\'';
     204         168 :             break;
     205             : 
     206             :         default:
     207        3012 :             if(c < 0x0020)
     208             :             {
     209             :                 // other controls must be escaped using Unicode
     210         795 :                 std::stringstream ss;
     211         795 :                 ss << std::hex << "\\u" << std::setfill('0') << std::setw(4) << static_cast<int>(c);
     212         795 :                 stringified += ss.str().c_str();
     213             :             }
     214             :             else
     215             :             {
     216        2217 :                 stringified += c;
     217             :             }
     218        3012 :             break;
     219             : 
     220             :         }
     221             :     }
     222         210 :     stringified += '"';
     223         210 : }
     224             : 
     225             : 
     226          22 : struct test_data_t
     227             : {
     228             :     as2js::Position                     f_pos;
     229             :     as2js::JSON::JSONValue::pointer_t   f_value;
     230             :     controlled_vars::zuint32_t          f_count;
     231             : };
     232             : 
     233             : 
     234             : int const TYPE_NULL         = 0x00000001;
     235             : int const TYPE_INT64        = 0x00000002;
     236             : int const TYPE_FLOAT64      = 0x00000004;
     237             : int const TYPE_NAN          = 0x00000008;
     238             : int const TYPE_PINFINITY    = 0x00000010;
     239             : int const TYPE_MINFINITY    = 0x00000020;
     240             : int const TYPE_TRUE         = 0x00000040;
     241             : int const TYPE_FALSE        = 0x00000080;
     242             : int const TYPE_STRING       = 0x00000100;
     243             : int const TYPE_ARRAY        = 0x00000200;
     244             : int const TYPE_OBJECT       = 0x00000400;
     245             : 
     246             : int const TYPE_ALL          = 0x000007FF;
     247             : 
     248             : int g_type_used;
     249             : 
     250             : 
     251          24 : void create_item(test_data_t& data, as2js::JSON::JSONValue::pointer_t parent, int depth)
     252             : {
     253          24 :     size_t const max_items(rand() % 8 + 2);
     254         158 :     for(size_t j(0); j < max_items; ++j)
     255             :     {
     256         134 :         ++data.f_count;
     257         134 :         as2js::JSON::JSONValue::pointer_t item;
     258         134 :         int const select(rand() % 8);
     259         134 :         switch(select)
     260             :         {
     261             :         case 0: // NULL
     262          22 :             g_type_used |= TYPE_NULL;
     263          22 :             item.reset(new as2js::JSON::JSONValue(data.f_pos));
     264          22 :             break;
     265             : 
     266             :         case 1: // INT64
     267          18 :             g_type_used |= TYPE_INT64;
     268             :             {
     269          18 :                 as2js::Int64::int64_type int_value((rand() << 13) ^ rand());
     270          18 :                 as2js::Int64 integer(int_value);
     271          18 :                 item.reset(new as2js::JSON::JSONValue(data.f_pos, integer));
     272             :             }
     273          18 :             break;
     274             : 
     275             :         case 2: // FLOAT64
     276          22 :             switch(rand() % 10)
     277             :             {
     278             :             case 0:
     279           1 :                 g_type_used |= TYPE_NAN;
     280             :                 {
     281           1 :                     as2js::Float64 flt;
     282           1 :                     flt.set_NaN();
     283           1 :                     item.reset(new as2js::JSON::JSONValue(data.f_pos, flt));
     284             :                 }
     285           1 :                 break;
     286             : 
     287             :             case 1:
     288           2 :                 g_type_used |= TYPE_PINFINITY;
     289             :                 {
     290           2 :                     as2js::Float64 flt;
     291           2 :                     flt.set_infinity();
     292           2 :                     item.reset(new as2js::JSON::JSONValue(data.f_pos, flt));
     293             :                 }
     294           2 :                 break;
     295             : 
     296             :             case 2:
     297           1 :                 g_type_used |= TYPE_MINFINITY;
     298             :                 {
     299           1 :                     as2js::Float64::float64_type flt_value(-std::numeric_limits<as2js::Float64::float64_type>::infinity());
     300           1 :                     as2js::Float64 flt(flt_value);
     301           1 :                     item.reset(new as2js::JSON::JSONValue(data.f_pos, flt));
     302             :                 }
     303           1 :                 break;
     304             : 
     305             :             default:
     306          18 :                 g_type_used |= TYPE_FLOAT64;
     307             :                 {
     308          18 :                     as2js::Float64::float64_type flt_value(static_cast<double>((rand() << 16) | rand()) / static_cast<double>((rand() << 16) | rand()));
     309          18 :                     as2js::Float64 flt(flt_value);
     310          18 :                     item.reset(new as2js::JSON::JSONValue(data.f_pos, flt));
     311             :                 }
     312          18 :                 break;
     313             : 
     314             :             }
     315          22 :             break;
     316             : 
     317             :         case 3: // TRUE
     318          14 :             g_type_used |= TYPE_TRUE;
     319          14 :             item.reset(new as2js::JSON::JSONValue(data.f_pos, true));
     320          14 :             break;
     321             : 
     322             :         case 4: // FALSE
     323          19 :             g_type_used |= TYPE_FALSE;
     324          19 :             item.reset(new as2js::JSON::JSONValue(data.f_pos, false));
     325          19 :             break;
     326             : 
     327             :         case 5: // STRING
     328          14 :             g_type_used |= TYPE_STRING;
     329             :             {
     330          14 :                 as2js::String str;
     331          28 :                 as2js::String stringified;
     332          14 :                 generate_string(str, stringified);
     333          28 :                 item.reset(new as2js::JSON::JSONValue(data.f_pos, str));
     334             :             }
     335          14 :             break;
     336             : 
     337             :         case 6: // empty ARRAY
     338          15 :             g_type_used |= TYPE_ARRAY;
     339             :             {
     340          15 :                 as2js::JSON::JSONValue::array_t empty_array;
     341          15 :                 item.reset(new as2js::JSON::JSONValue(data.f_pos, empty_array));
     342          15 :                 if(depth < 5 && (rand() & 1) != 0)
     343             :                 {
     344          10 :                     create_item(data, item, depth + 1);
     345          15 :                 }
     346             :             }
     347          15 :             break;
     348             : 
     349             :         case 7: // empty OBJECT
     350          10 :             g_type_used |= TYPE_OBJECT;
     351             :             {
     352          10 :                 as2js::JSON::JSONValue::object_t empty_object;
     353          10 :                 item.reset(new as2js::JSON::JSONValue(data.f_pos, empty_object));
     354          10 :                 if(depth < 5 && (rand() & 1) != 0)
     355             :                 {
     356           4 :                     create_item(data, item, depth + 1);
     357          10 :                 }
     358             :             }
     359          10 :             break;
     360             : 
     361             :         // more?
     362             :         default:
     363           0 :             throw std::logic_error("test generated an invalid # to generate an object item");
     364             : 
     365             :         }
     366         134 :         if(parent->get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_ARRAY)
     367             :         {
     368          78 :             parent->set_item(parent->get_array().size(), item);
     369             :         }
     370             :         else
     371             :         {
     372          56 :             as2js::String field_name;
     373         112 :             as2js::String stringified_value;
     374          56 :             generate_string(field_name, stringified_value);
     375         112 :             parent->set_member(field_name, item);
     376             :         }
     377         134 :     }
     378          24 : }
     379             : 
     380             : 
     381           4 : void create_array(test_data_t& data)
     382             : {
     383           4 :     as2js::JSON::JSONValue::array_t array;
     384           4 :     data.f_value.reset(new as2js::JSON::JSONValue(data.f_pos, array));
     385           4 :     create_item(data, data.f_value, 0);
     386           4 : }
     387             : 
     388             : 
     389           6 : void create_object(test_data_t& data)
     390             : {
     391           6 :     as2js::JSON::JSONValue::object_t object;
     392           6 :     data.f_value.reset(new as2js::JSON::JSONValue(data.f_pos, object));
     393           6 :     create_item(data, data.f_value, 0);
     394           6 : }
     395             : 
     396             : 
     397         432 : void data_to_string(as2js::JSON::JSONValue::pointer_t value, as2js::String& expected)
     398             : {
     399         432 :     switch(value->get_type())
     400             :     {
     401             :     case as2js::JSON::JSONValue::type_t::JSON_TYPE_NULL:
     402          66 :         expected += "null";
     403          66 :         break;
     404             : 
     405             :     case as2js::JSON::JSONValue::type_t::JSON_TYPE_TRUE:
     406          42 :         expected += "true";
     407          42 :         break;
     408             : 
     409             :     case as2js::JSON::JSONValue::type_t::JSON_TYPE_FALSE:
     410          57 :         expected += "false";
     411          57 :         break;
     412             : 
     413             :     case as2js::JSON::JSONValue::type_t::JSON_TYPE_INT64:
     414          54 :         expected += std::to_string(value->get_int64().get());
     415          54 :         break;
     416             : 
     417             :     case as2js::JSON::JSONValue::type_t::JSON_TYPE_FLOAT64:
     418          66 :         if(value->get_float64().is_NaN())
     419             :         {
     420           3 :             expected += "NaN";
     421             :         }
     422          63 :         else if(value->get_float64().is_positive_infinity())
     423             :         {
     424           6 :             expected += "Infinity";
     425             :         }
     426          57 :         else if(value->get_float64().is_negative_infinity())
     427             :         {
     428           3 :             expected += "-Infinity";
     429             :         }
     430             :         else
     431             :         {
     432          54 :             expected += std::to_string(value->get_float64().get());
     433             :         }
     434          66 :         break;
     435             : 
     436             :     case as2js::JSON::JSONValue::type_t::JSON_TYPE_STRING:
     437          42 :         stringify_string(value->get_string(), expected);
     438          42 :         break;
     439             : 
     440             :     case as2js::JSON::JSONValue::type_t::JSON_TYPE_ARRAY:
     441          57 :         expected += '[';
     442             :         {
     443          57 :             bool first(true);
     444         291 :             for(auto it : value->get_array())
     445             :             {
     446         234 :                 if(first)
     447             :                 {
     448          42 :                     first = false;
     449             :                 }
     450             :                 else
     451             :                 {
     452         192 :                     expected += ',';
     453             :                 }
     454         234 :                 data_to_string(it, expected); // recursive
     455         234 :             }
     456             :         }
     457          57 :         expected += ']';
     458          57 :         break;
     459             : 
     460             :     case as2js::JSON::JSONValue::type_t::JSON_TYPE_OBJECT:
     461          48 :         expected += '{';
     462             :         {
     463          48 :             bool first(true);
     464         216 :             for(auto it : value->get_object())
     465             :             {
     466         168 :                 if(first)
     467             :                 {
     468          30 :                     first = false;
     469             :                 }
     470             :                 else
     471             :                 {
     472         138 :                     expected += ',';
     473             :                 }
     474         168 :                 stringify_string(it.first, expected);
     475         168 :                 expected += ':';
     476         168 :                 data_to_string(it.second, expected); // recursive
     477         168 :             }
     478             :         }
     479          48 :         expected += '}';
     480          48 :         break;
     481             : 
     482             :     // more?
     483             :     default:
     484           0 :         throw std::logic_error("test found an invalid JSONValue::type_t to stringify a value item");
     485             : 
     486             :     }
     487         432 : }
     488             : 
     489             : 
     490             : class test_callback : public as2js::MessageCallback
     491             : {
     492             : public:
     493      103349 :     test_callback()
     494      103349 :     {
     495      103349 :         as2js::Message::set_message_callback(this);
     496      103349 :         g_warning_count = as2js::Message::warning_count();
     497      103349 :         g_error_count = as2js::Message::error_count();
     498      103349 :     }
     499             : 
     500      103349 :     ~test_callback()
     501      206698 :     {
     502             :         // make sure the pointer gets reset!
     503      103349 :         as2js::Message::set_message_callback(nullptr);
     504      103349 :     }
     505             : 
     506             :     // implementation of the output
     507      206695 :     virtual void output(as2js::message_level_t message_level, as2js::err_code_t error_code, as2js::Position const& pos, std::string const& message)
     508             :     {
     509      206695 :         CPPUNIT_ASSERT(!f_expected.empty());
     510             : 
     511             : //std::cerr << "filename = " << pos.get_filename() << " / " << f_expected[0].f_pos.get_filename() << "\n";
     512             : //std::cerr << "msg = " << message << " / " << f_expected[0].f_message << "\n";
     513             : //std::cerr << "page = " << pos.get_page() << " / " << f_expected[0].f_pos.get_page() << "\n";
     514             : //std::cerr << "error_code = " << static_cast<int>(error_code) << " / " << static_cast<int>(f_expected[0].f_error_code) << "\n";
     515             : 
     516      206695 :         CPPUNIT_ASSERT(f_expected[0].f_call);
     517      206695 :         CPPUNIT_ASSERT(message_level == f_expected[0].f_message_level);
     518      206695 :         CPPUNIT_ASSERT(error_code == f_expected[0].f_error_code);
     519      206695 :         CPPUNIT_ASSERT(pos.get_filename() == f_expected[0].f_pos.get_filename());
     520      206695 :         CPPUNIT_ASSERT(pos.get_function() == f_expected[0].f_pos.get_function());
     521      206695 :         CPPUNIT_ASSERT(pos.get_page() == f_expected[0].f_pos.get_page());
     522      206695 :         CPPUNIT_ASSERT(pos.get_page_line() == f_expected[0].f_pos.get_page_line());
     523      206695 :         CPPUNIT_ASSERT(pos.get_paragraph() == f_expected[0].f_pos.get_paragraph());
     524      206695 :         CPPUNIT_ASSERT(pos.get_line() == f_expected[0].f_pos.get_line());
     525      206695 :         CPPUNIT_ASSERT(message == f_expected[0].f_message);
     526             : 
     527      206695 :         if(message_level == as2js::message_level_t::MESSAGE_LEVEL_WARNING)
     528             :         {
     529           0 :             ++g_warning_count;
     530           0 :             CPPUNIT_ASSERT(g_warning_count == as2js::Message::warning_count());
     531             :         }
     532             : 
     533      206695 :         if(message_level == as2js::message_level_t::MESSAGE_LEVEL_FATAL
     534      103348 :         || message_level == as2js::message_level_t::MESSAGE_LEVEL_ERROR)
     535             :         {
     536      206695 :             ++g_error_count;
     537             : //std::cerr << "error: " << g_error_count << " / " << as2js::Message::error_count() << "\n";
     538      206695 :             CPPUNIT_ASSERT(g_error_count == as2js::Message::error_count());
     539             :         }
     540             : 
     541      206695 :         f_expected.erase(f_expected.begin());
     542      206695 :     }
     543             : 
     544      103349 :     void got_called()
     545             :     {
     546      103349 :         if(!f_expected.empty())
     547             :         {
     548           0 :             std::cerr << "\n*** STILL EXPECTED: ***\n";
     549           0 :             std::cerr << "filename = " << f_expected[0].f_pos.get_filename() << "\n";
     550           0 :             std::cerr << "msg = " << f_expected[0].f_message << "\n";
     551           0 :             std::cerr << "page = " << f_expected[0].f_pos.get_page() << "\n";
     552           0 :             std::cerr << "error_code = " << static_cast<int>(f_expected[0].f_error_code) << "\n";
     553             :         }
     554      103349 :         CPPUNIT_ASSERT(f_expected.empty());
     555      103349 :     }
     556             : 
     557     1136818 :     struct expected_t
     558             :     {
     559             :         controlled_vars::tlbool_t   f_call;
     560             :         as2js::message_level_t      f_message_level;
     561             :         as2js::err_code_t           f_error_code;
     562             :         as2js::Position             f_pos;
     563             :         std::string                 f_message; // UTF-8 string
     564             :     };
     565             : 
     566             :     std::vector<expected_t>     f_expected;
     567             : 
     568             :     static controlled_vars::zint32_t   g_warning_count;
     569             :     static controlled_vars::zint32_t   g_error_count;
     570             : };
     571             : 
     572           4 : controlled_vars::zint32_t   test_callback::g_warning_count;
     573           4 : controlled_vars::zint32_t   test_callback::g_error_count;
     574             : 
     575             : 
     576     1112010 : bool is_identifier_char(int32_t const c)
     577             : {
     578             :     // special cases in JavaScript identifiers
     579     1112010 :     if(c == 0x200C    // ZWNJ
     580     1112009 :     || c == 0x200D)   // ZWJ
     581             :     {
     582           2 :         return true;
     583             :     }
     584             : 
     585     1112008 :     switch(u_charType(static_cast<UChar32>(c)))
     586             :     {
     587             :     case U_UPPERCASE_LETTER:
     588             :     case U_LOWERCASE_LETTER:
     589             :     case U_TITLECASE_LETTER:
     590             :     case U_MODIFIER_LETTER:
     591             :     case U_OTHER_LETTER:
     592             :     case U_LETTER_NUMBER:
     593             :     case U_NON_SPACING_MARK:
     594             :     case U_COMBINING_SPACING_MARK:
     595             :     case U_DECIMAL_DIGIT_NUMBER:
     596             :     case U_CONNECTOR_PUNCTUATION:
     597      103330 :         return true;
     598             : 
     599             :     default:
     600     1008678 :         return false;
     601             : 
     602             :     }
     603             : }
     604             : 
     605             : 
     606             : }
     607             : // no name namespace
     608             : 
     609             : 
     610             : 
     611             : 
     612           1 : void As2JsJSONUnitTests::test_basic_values()
     613             : {
     614             :     // a null pointer value...
     615           1 :     as2js::JSON::JSONValue::pointer_t const nullptr_value;
     616             : 
     617             :     // NULL value
     618             :     {
     619           1 :         as2js::Position pos;
     620           1 :         pos.reset_counters(33);
     621           1 :         pos.set_filename("data.json");
     622           1 :         pos.set_function("save_objects");
     623           2 :         as2js::JSON::JSONValue::pointer_t value(new as2js::JSON::JSONValue(pos));
     624           1 :         CPPUNIT_ASSERT(value->get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_NULL);
     625           1 :         CPPUNIT_ASSERT_THROW(value->get_int64().get() == 0, as2js::exception_internal_error);
     626           1 :         CPPUNIT_ASSERT_THROW(value->get_float64().get() >= 0.0, as2js::exception_internal_error);
     627           1 :         CPPUNIT_ASSERT_THROW(value->get_string() == "ignore", as2js::exception_internal_error);
     628           1 :         CPPUNIT_ASSERT_THROW(value->get_array(), as2js::exception_internal_error);
     629           1 :         CPPUNIT_ASSERT_THROW(value->set_item(rand(), nullptr_value), as2js::exception_internal_error);
     630           1 :         CPPUNIT_ASSERT_THROW(value->get_object(), as2js::exception_internal_error);
     631           1 :         CPPUNIT_ASSERT_THROW(value->set_member("name", nullptr_value), as2js::exception_internal_error);
     632           1 :         as2js::Position const& p(value->get_position());
     633           1 :         CPPUNIT_ASSERT(p.get_filename() == pos.get_filename());
     634           1 :         CPPUNIT_ASSERT(p.get_function() == pos.get_function());
     635           1 :         CPPUNIT_ASSERT(p.get_line() == 33);
     636           1 :         CPPUNIT_ASSERT(value->to_string() == "null");
     637             :         // copy operator
     638           2 :         as2js::JSON::JSONValue copy(*value);
     639           1 :         CPPUNIT_ASSERT(copy.get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_NULL);
     640           1 :         CPPUNIT_ASSERT_THROW(copy.get_int64().get() == 0, as2js::exception_internal_error);
     641           1 :         CPPUNIT_ASSERT_THROW(copy.get_float64().get() >= 0.0, as2js::exception_internal_error);
     642           1 :         CPPUNIT_ASSERT_THROW(copy.get_string() == "ignore", as2js::exception_internal_error);
     643           1 :         CPPUNIT_ASSERT_THROW(copy.get_array(), as2js::exception_internal_error);
     644           1 :         CPPUNIT_ASSERT_THROW(copy.set_item(rand(), nullptr_value), as2js::exception_internal_error);
     645           1 :         CPPUNIT_ASSERT_THROW(copy.get_object(), as2js::exception_internal_error);
     646           1 :         CPPUNIT_ASSERT_THROW(copy.set_member("name", nullptr_value), as2js::exception_internal_error);
     647           1 :         as2js::Position const& q(copy.get_position());
     648           1 :         CPPUNIT_ASSERT(q.get_filename() == pos.get_filename());
     649           1 :         CPPUNIT_ASSERT(q.get_function() == pos.get_function());
     650           1 :         CPPUNIT_ASSERT(q.get_line() == 33);
     651           2 :         CPPUNIT_ASSERT(copy.to_string() == "null");
     652             :     }
     653             : 
     654             :     // TRUE value
     655             :     {
     656           1 :         as2js::Position pos;
     657           1 :         pos.reset_counters(35);
     658           1 :         pos.set_filename("data.json");
     659           1 :         pos.set_function("save_objects");
     660           2 :         as2js::JSON::JSONValue::pointer_t value(new as2js::JSON::JSONValue(pos, true));
     661             :         // modify out pos object to make sure that the one in value is not a reference
     662           1 :         pos.set_filename("verify.json");
     663           1 :         pos.set_function("bad_objects");
     664           1 :         pos.new_line();
     665           1 :         CPPUNIT_ASSERT(value->get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_TRUE);
     666           1 :         CPPUNIT_ASSERT_THROW(value->get_int64().get() == 0, as2js::exception_internal_error);
     667           1 :         CPPUNIT_ASSERT_THROW(value->get_float64().get() >= 0.0, as2js::exception_internal_error);
     668           1 :         CPPUNIT_ASSERT_THROW(value->get_string() == "ignore", as2js::exception_internal_error);
     669           1 :         CPPUNIT_ASSERT_THROW(value->get_array(), as2js::exception_internal_error);
     670           1 :         CPPUNIT_ASSERT_THROW(value->set_item(rand(), nullptr_value), as2js::exception_internal_error);
     671           1 :         CPPUNIT_ASSERT_THROW(value->get_object(), as2js::exception_internal_error);
     672           1 :         CPPUNIT_ASSERT_THROW(value->set_member("name", nullptr_value), as2js::exception_internal_error);
     673           1 :         as2js::Position const& p(value->get_position());
     674           1 :         CPPUNIT_ASSERT(p.get_filename() == "data.json");
     675           1 :         CPPUNIT_ASSERT(p.get_function() == "save_objects");
     676           1 :         CPPUNIT_ASSERT(p.get_line() == 35);
     677           1 :         CPPUNIT_ASSERT(value->to_string() == "true");
     678             :         // copy operator
     679           2 :         as2js::JSON::JSONValue copy(*value);
     680           1 :         CPPUNIT_ASSERT(copy.get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_TRUE);
     681           1 :         CPPUNIT_ASSERT_THROW(copy.get_int64().get() == 0, as2js::exception_internal_error);
     682           1 :         CPPUNIT_ASSERT_THROW(copy.get_float64().get() >= 0.0, as2js::exception_internal_error);
     683           1 :         CPPUNIT_ASSERT_THROW(copy.get_string() == "ignore", as2js::exception_internal_error);
     684           1 :         CPPUNIT_ASSERT_THROW(copy.get_array(), as2js::exception_internal_error);
     685           1 :         CPPUNIT_ASSERT_THROW(copy.set_item(rand(), nullptr_value), as2js::exception_internal_error);
     686           1 :         CPPUNIT_ASSERT_THROW(copy.get_object(), as2js::exception_internal_error);
     687           1 :         CPPUNIT_ASSERT_THROW(copy.set_member("name", nullptr_value), as2js::exception_internal_error);
     688           1 :         as2js::Position const& q(copy.get_position());
     689           1 :         CPPUNIT_ASSERT(q.get_filename() == "data.json");
     690           1 :         CPPUNIT_ASSERT(q.get_function() == "save_objects");
     691           1 :         CPPUNIT_ASSERT(q.get_line() == 35);
     692           2 :         CPPUNIT_ASSERT(copy.to_string() == "true");
     693             :     }
     694             : 
     695             :     // FALSE value
     696             :     {
     697           1 :         as2js::Position pos;
     698           1 :         pos.reset_counters(53);
     699           1 :         pos.set_filename("data.json");
     700           1 :         pos.set_function("save_objects");
     701           2 :         as2js::JSON::JSONValue::pointer_t value(new as2js::JSON::JSONValue(pos, false));
     702           1 :         CPPUNIT_ASSERT(value->get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_FALSE);
     703           1 :         CPPUNIT_ASSERT_THROW(value->get_int64().get() == 0, as2js::exception_internal_error);
     704           1 :         CPPUNIT_ASSERT_THROW(value->get_float64().get() >= 0.0, as2js::exception_internal_error);
     705           1 :         CPPUNIT_ASSERT_THROW(value->get_string() == "ignore", as2js::exception_internal_error);
     706           1 :         CPPUNIT_ASSERT_THROW(value->get_array(), as2js::exception_internal_error);
     707           1 :         CPPUNIT_ASSERT_THROW(value->set_item(rand(), nullptr_value), as2js::exception_internal_error);
     708           1 :         CPPUNIT_ASSERT_THROW(value->get_object(), as2js::exception_internal_error);
     709           1 :         CPPUNIT_ASSERT_THROW(value->set_member("name", nullptr_value), as2js::exception_internal_error);
     710           1 :         as2js::Position const& p(value->get_position());
     711           1 :         CPPUNIT_ASSERT(p.get_filename() == pos.get_filename());
     712           1 :         CPPUNIT_ASSERT(p.get_function() == pos.get_function());
     713           1 :         CPPUNIT_ASSERT(p.get_line() == 53);
     714           1 :         CPPUNIT_ASSERT(value->to_string() == "false");
     715             :         // copy operator
     716           2 :         as2js::JSON::JSONValue copy(*value);
     717           1 :         CPPUNIT_ASSERT(copy.get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_FALSE);
     718           1 :         CPPUNIT_ASSERT_THROW(copy.get_int64().get() == 0, as2js::exception_internal_error);
     719           1 :         CPPUNIT_ASSERT_THROW(copy.get_float64().get() >= 0.0, as2js::exception_internal_error);
     720           1 :         CPPUNIT_ASSERT_THROW(copy.get_string() == "ignore", as2js::exception_internal_error);
     721           1 :         CPPUNIT_ASSERT_THROW(copy.get_array(), as2js::exception_internal_error);
     722           1 :         CPPUNIT_ASSERT_THROW(copy.set_item(rand(), nullptr_value), as2js::exception_internal_error);
     723           1 :         CPPUNIT_ASSERT_THROW(copy.get_object(), as2js::exception_internal_error);
     724           1 :         CPPUNIT_ASSERT_THROW(copy.set_member("name", nullptr_value), as2js::exception_internal_error);
     725           1 :         as2js::Position const& q(copy.get_position());
     726           1 :         CPPUNIT_ASSERT(q.get_filename() == pos.get_filename());
     727           1 :         CPPUNIT_ASSERT(q.get_function() == pos.get_function());
     728           1 :         CPPUNIT_ASSERT(q.get_line() == 53);
     729           2 :         CPPUNIT_ASSERT(copy.to_string() == "false");
     730             :     }
     731             : 
     732             :     // INT64 value
     733         101 :     for(int idx(0); idx < 100; ++idx)
     734             :     {
     735         100 :         as2js::Position pos;
     736         100 :         pos.reset_counters(103);
     737         100 :         pos.set_filename("data.json");
     738         100 :         pos.set_function("save_objects");
     739         100 :         as2js::Int64::int64_type int_value((rand() << 14) ^ rand());
     740         100 :         as2js::Int64 integer(int_value);
     741         200 :         as2js::JSON::JSONValue::pointer_t value(new as2js::JSON::JSONValue(pos, integer));
     742         100 :         CPPUNIT_ASSERT(value->get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_INT64);
     743         100 :         CPPUNIT_ASSERT(value->get_int64().get() == int_value);
     744         100 :         CPPUNIT_ASSERT_THROW(value->get_float64().get() >= 0.0, as2js::exception_internal_error);
     745         100 :         CPPUNIT_ASSERT_THROW(value->get_string() == "ignore", as2js::exception_internal_error);
     746         100 :         CPPUNIT_ASSERT_THROW(value->get_array(), as2js::exception_internal_error);
     747         100 :         CPPUNIT_ASSERT_THROW(value->set_item(rand(), nullptr_value), as2js::exception_internal_error);
     748         100 :         CPPUNIT_ASSERT_THROW(value->get_object(), as2js::exception_internal_error);
     749         100 :         CPPUNIT_ASSERT_THROW(value->set_member("name", nullptr_value), as2js::exception_internal_error);
     750         100 :         as2js::Position const& p(value->get_position());
     751         100 :         CPPUNIT_ASSERT(p.get_filename() == pos.get_filename());
     752         100 :         CPPUNIT_ASSERT(p.get_function() == pos.get_function());
     753         100 :         CPPUNIT_ASSERT(p.get_line() == 103);
     754         200 :         std::stringstream ss;
     755         100 :         ss << integer.get();
     756         200 :         as2js::String cmp;
     757         100 :         cmp.from_utf8(ss.str().c_str());
     758         100 :         CPPUNIT_ASSERT(value->to_string() == cmp);
     759             :         // copy operator
     760         200 :         as2js::JSON::JSONValue copy(*value);
     761         100 :         CPPUNIT_ASSERT(copy.get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_INT64);
     762         100 :         CPPUNIT_ASSERT(copy.get_int64().get() == int_value);
     763         100 :         CPPUNIT_ASSERT_THROW(copy.get_float64().get() >= 0.0, as2js::exception_internal_error);
     764         100 :         CPPUNIT_ASSERT_THROW(copy.get_string() == "ignore", as2js::exception_internal_error);
     765         100 :         CPPUNIT_ASSERT_THROW(copy.get_array(), as2js::exception_internal_error);
     766         100 :         CPPUNIT_ASSERT_THROW(copy.set_item(rand(), nullptr_value), as2js::exception_internal_error);
     767         100 :         CPPUNIT_ASSERT_THROW(copy.get_object(), as2js::exception_internal_error);
     768         100 :         CPPUNIT_ASSERT_THROW(copy.set_member("name", nullptr_value), as2js::exception_internal_error);
     769         100 :         as2js::Position const& q(copy.get_position());
     770         100 :         CPPUNIT_ASSERT(q.get_filename() == pos.get_filename());
     771         100 :         CPPUNIT_ASSERT(q.get_function() == pos.get_function());
     772         100 :         CPPUNIT_ASSERT(q.get_line() == 103);
     773         100 :         CPPUNIT_ASSERT(copy.to_string() == cmp);
     774         100 :     }
     775             : 
     776             :     // FLOAT64 value
     777             :     {
     778           1 :         as2js::Position pos;
     779           1 :         pos.reset_counters(144);
     780           1 :         pos.set_filename("data.json");
     781           1 :         pos.set_function("save_objects");
     782           1 :         as2js::Float64::float64_type flt_value(std::numeric_limits<as2js::Float64::float64_type>::quiet_NaN());
     783           1 :         as2js::Float64 flt(flt_value);
     784           2 :         as2js::JSON::JSONValue::pointer_t value(new as2js::JSON::JSONValue(pos, flt));
     785           1 :         CPPUNIT_ASSERT(value->get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_FLOAT64);
     786           1 :         CPPUNIT_ASSERT_THROW(value->get_int64().get() == 0, as2js::exception_internal_error);
     787             : #pragma GCC diagnostic push
     788             : #pragma GCC diagnostic ignored "-Wfloat-equal"
     789             :         // NaN's do not compare equal
     790           1 :         CPPUNIT_ASSERT(value->get_float64().get() != flt_value);
     791             : #pragma GCC diagnostic pop
     792           1 :         CPPUNIT_ASSERT_THROW(value->get_string() == "ignore", as2js::exception_internal_error);
     793           1 :         CPPUNIT_ASSERT_THROW(value->get_array(), as2js::exception_internal_error);
     794           1 :         CPPUNIT_ASSERT_THROW(value->set_item(rand(), nullptr_value), as2js::exception_internal_error);
     795           1 :         CPPUNIT_ASSERT_THROW(value->get_object(), as2js::exception_internal_error);
     796           1 :         CPPUNIT_ASSERT_THROW(value->set_member("name", nullptr_value), as2js::exception_internal_error);
     797           1 :         as2js::Position const& p(value->get_position());
     798           1 :         CPPUNIT_ASSERT(p.get_filename() == pos.get_filename());
     799           1 :         CPPUNIT_ASSERT(p.get_function() == pos.get_function());
     800           1 :         CPPUNIT_ASSERT(p.get_line() == 144);
     801             : //std::cerr << "compare " << value->to_string() << " with " << cmp << "\n";
     802           1 :         CPPUNIT_ASSERT(value->to_string() == "NaN");
     803             :         // copy operator
     804           2 :         as2js::JSON::JSONValue copy(*value);
     805           1 :         CPPUNIT_ASSERT(copy.get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_FLOAT64);
     806           1 :         CPPUNIT_ASSERT_THROW(copy.get_int64().get() == 0, as2js::exception_internal_error);
     807             : #pragma GCC diagnostic push
     808             : #pragma GCC diagnostic ignored "-Wfloat-equal"
     809             :         // NaN's do not compare equal
     810           1 :         CPPUNIT_ASSERT(copy.get_float64().get() != flt_value);
     811             : #pragma GCC diagnostic pop
     812           1 :         CPPUNIT_ASSERT_THROW(copy.get_string() == "ignore", as2js::exception_internal_error);
     813           1 :         CPPUNIT_ASSERT_THROW(copy.get_array(), as2js::exception_internal_error);
     814           1 :         CPPUNIT_ASSERT_THROW(copy.set_item(rand(), nullptr_value), as2js::exception_internal_error);
     815           1 :         CPPUNIT_ASSERT_THROW(copy.get_object(), as2js::exception_internal_error);
     816           1 :         CPPUNIT_ASSERT_THROW(copy.set_member("name", nullptr_value), as2js::exception_internal_error);
     817           1 :         as2js::Position const& q(copy.get_position());
     818           1 :         CPPUNIT_ASSERT(q.get_filename() == pos.get_filename());
     819           1 :         CPPUNIT_ASSERT(q.get_function() == pos.get_function());
     820           1 :         CPPUNIT_ASSERT(q.get_line() == 144);
     821           2 :         CPPUNIT_ASSERT(copy.to_string() == "NaN");
     822             :     }
     823             : 
     824         101 :     for(int idx(0); idx < 100; ++idx)
     825             :     {
     826         100 :         as2js::Position pos;
     827         100 :         pos.reset_counters(44);
     828         100 :         pos.set_filename("data.json");
     829         100 :         pos.set_function("save_objects");
     830         100 :         as2js::Float64::float64_type flt_value(static_cast<double>(rand()) / static_cast<double>(rand()));
     831         100 :         as2js::Float64 flt(flt_value);
     832         200 :         as2js::String cmp;
     833         200 :         std::string ss(std::to_string(flt_value));
     834         100 :         cmp.from_utf8(ss.c_str());
     835         200 :         as2js::JSON::JSONValue::pointer_t value(new as2js::JSON::JSONValue(pos, flt));
     836         100 :         CPPUNIT_ASSERT(value->get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_FLOAT64);
     837         100 :         CPPUNIT_ASSERT_THROW(value->get_int64().get() == 0, as2js::exception_internal_error);
     838             : #pragma GCC diagnostic push
     839             : #pragma GCC diagnostic ignored "-Wfloat-equal"
     840         100 :         CPPUNIT_ASSERT(value->get_float64().get() == flt_value);
     841             : #pragma GCC diagnostic pop
     842         100 :         CPPUNIT_ASSERT_THROW(value->get_string() == "ignore", as2js::exception_internal_error);
     843         100 :         CPPUNIT_ASSERT_THROW(value->get_array(), as2js::exception_internal_error);
     844         100 :         CPPUNIT_ASSERT_THROW(value->set_item(rand(), nullptr_value), as2js::exception_internal_error);
     845         100 :         CPPUNIT_ASSERT_THROW(value->get_object(), as2js::exception_internal_error);
     846         100 :         CPPUNIT_ASSERT_THROW(value->set_member("name", nullptr_value), as2js::exception_internal_error);
     847         100 :         as2js::Position const& p(value->get_position());
     848         100 :         CPPUNIT_ASSERT(p.get_filename() == pos.get_filename());
     849         100 :         CPPUNIT_ASSERT(p.get_function() == pos.get_function());
     850         100 :         CPPUNIT_ASSERT(p.get_line() == 44);
     851             : //std::cerr << "compare " << value->to_string() << " with " << cmp << "\n";
     852         100 :         CPPUNIT_ASSERT(value->to_string() == cmp);
     853             :         // copy operator
     854         200 :         as2js::JSON::JSONValue copy(*value);
     855         100 :         CPPUNIT_ASSERT(copy.get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_FLOAT64);
     856         100 :         CPPUNIT_ASSERT_THROW(copy.get_int64().get() == 0, as2js::exception_internal_error);
     857             : #pragma GCC diagnostic push
     858             : #pragma GCC diagnostic ignored "-Wfloat-equal"
     859         100 :         CPPUNIT_ASSERT(copy.get_float64().get() == flt_value);
     860             : #pragma GCC diagnostic pop
     861         100 :         CPPUNIT_ASSERT_THROW(copy.get_string() == "ignore", as2js::exception_internal_error);
     862         100 :         CPPUNIT_ASSERT_THROW(copy.get_array(), as2js::exception_internal_error);
     863         100 :         CPPUNIT_ASSERT_THROW(copy.set_item(rand(), nullptr_value), as2js::exception_internal_error);
     864         100 :         CPPUNIT_ASSERT_THROW(copy.get_object(), as2js::exception_internal_error);
     865         100 :         CPPUNIT_ASSERT_THROW(copy.set_member("name", nullptr_value), as2js::exception_internal_error);
     866         100 :         as2js::Position const& q(copy.get_position());
     867         100 :         CPPUNIT_ASSERT(q.get_filename() == pos.get_filename());
     868         100 :         CPPUNIT_ASSERT(q.get_function() == pos.get_function());
     869         100 :         CPPUNIT_ASSERT(q.get_line() == 44);
     870         100 :         CPPUNIT_ASSERT(copy.to_string() == cmp);
     871         100 :     }
     872             : 
     873             :     // STRING value
     874         101 :     for(size_t idx(0), used(0); idx < 100 || used != 0xFF; ++idx)
     875             :     {
     876         100 :         as2js::Position pos;
     877         100 :         pos.reset_counters(89);
     878         100 :         pos.set_filename("data.json");
     879         100 :         pos.set_function("save_objects");
     880         200 :         as2js::String str;
     881         200 :         as2js::String stringified;
     882         100 :         used |= generate_string(str, stringified);
     883         200 :         as2js::JSON::JSONValue::pointer_t value(new as2js::JSON::JSONValue(pos, str));
     884         100 :         CPPUNIT_ASSERT(value->get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_STRING);
     885         100 :         CPPUNIT_ASSERT_THROW(value->get_int64().get() == 0, as2js::exception_internal_error);
     886         100 :         CPPUNIT_ASSERT_THROW(value->get_float64().get() >= 0.0, as2js::exception_internal_error);
     887         100 :         CPPUNIT_ASSERT(value->get_string() == str);
     888         100 :         CPPUNIT_ASSERT_THROW(value->get_array(), as2js::exception_internal_error);
     889         100 :         CPPUNIT_ASSERT_THROW(value->set_item(rand(), nullptr_value), as2js::exception_internal_error);
     890         100 :         CPPUNIT_ASSERT_THROW(value->get_object(), as2js::exception_internal_error);
     891         100 :         CPPUNIT_ASSERT_THROW(value->set_member("name", nullptr_value), as2js::exception_internal_error);
     892         100 :         as2js::Position const& p(value->get_position());
     893         100 :         CPPUNIT_ASSERT(p.get_filename() == pos.get_filename());
     894         100 :         CPPUNIT_ASSERT(p.get_function() == pos.get_function());
     895         100 :         CPPUNIT_ASSERT(p.get_line() == 89);
     896             : //as2js::String r(value->to_string());
     897             : //std::cerr << std::hex << " lengths " << r.length() << " / " << stringified.length() << "\n";
     898             : //size_t max_chrs(std::min(r.length(), stringified.length()));
     899             : //for(size_t g(0); g < max_chrs; ++g)
     900             : //{
     901             : //    if(static_cast<int>(r[g]) != static_cast<int>(stringified[g]))
     902             : //    {
     903             : //        std::cerr << " --- " << static_cast<int>(r[g]) << " / " << static_cast<int>(stringified[g]) << "\n";
     904             : //    }
     905             : //    else
     906             : //    {
     907             : //        std::cerr << " " << static_cast<int>(r[g]) << " / " << static_cast<int>(stringified[g]) << "\n";
     908             : //    }
     909             : //}
     910             : //if(r.length() > stringified.length())
     911             : //{
     912             : //    for(size_t g(stringified.length()); g < r.length(); ++g)
     913             : //    {
     914             : //        std::cerr << " *** " << static_cast<int>(r[g]) << "\n";
     915             : //    }
     916             : //}
     917             : //else
     918             : //{
     919             : //    for(size_t g(r.length()); g < stringified.length(); ++g)
     920             : //    {
     921             : //        std::cerr << " +++ " << static_cast<int>(stringified[g]) << "\n";
     922             : //    }
     923             : //}
     924             : //std::cerr << std::dec;
     925         100 :         CPPUNIT_ASSERT(value->to_string() == stringified);
     926             :         // copy operator
     927         200 :         as2js::JSON::JSONValue copy(*value);
     928         100 :         CPPUNIT_ASSERT(copy.get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_STRING);
     929         100 :         CPPUNIT_ASSERT_THROW(copy.get_int64().get() == 0, as2js::exception_internal_error);
     930         100 :         CPPUNIT_ASSERT_THROW(copy.get_float64().get() >= 0.0, as2js::exception_internal_error);
     931         100 :         CPPUNIT_ASSERT(copy.get_string() == str);
     932         100 :         CPPUNIT_ASSERT_THROW(copy.get_array(), as2js::exception_internal_error);
     933         100 :         CPPUNIT_ASSERT_THROW(copy.set_item(rand(), nullptr_value), as2js::exception_internal_error);
     934         100 :         CPPUNIT_ASSERT_THROW(copy.get_object(), as2js::exception_internal_error);
     935         100 :         CPPUNIT_ASSERT_THROW(copy.set_member("name", nullptr_value), as2js::exception_internal_error);
     936         100 :         as2js::Position const& q(copy.get_position());
     937         100 :         CPPUNIT_ASSERT(q.get_filename() == pos.get_filename());
     938         100 :         CPPUNIT_ASSERT(q.get_function() == pos.get_function());
     939         100 :         CPPUNIT_ASSERT(q.get_line() == 89);
     940         100 :         CPPUNIT_ASSERT(copy.to_string() == stringified);
     941         101 :     }
     942           1 : }
     943             : 
     944             : 
     945           1 : void As2JsJSONUnitTests::test_array_value()
     946             : {
     947             :     // a null pointer value...
     948           1 :     as2js::JSON::JSONValue::pointer_t const nullptr_value;
     949             : 
     950             :     // test with an empty array
     951             :     {
     952           1 :         as2js::Position pos;
     953           1 :         pos.reset_counters(109);
     954           1 :         pos.set_filename("array.json");
     955           1 :         pos.set_function("save_array");
     956           2 :         as2js::JSON::JSONValue::array_t initial;
     957           2 :         as2js::JSON::JSONValue::pointer_t value(new as2js::JSON::JSONValue(pos, initial));
     958           1 :         CPPUNIT_ASSERT(value->get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_ARRAY);
     959           1 :         CPPUNIT_ASSERT_THROW(value->get_int64().get() == 0, as2js::exception_internal_error);
     960           1 :         CPPUNIT_ASSERT_THROW(value->get_float64().get() >= 0.0, as2js::exception_internal_error);
     961           1 :         CPPUNIT_ASSERT_THROW(value->get_string() == "ignore", as2js::exception_internal_error);
     962           1 :         as2js::JSON::JSONValue::array_t const& array(value->get_array());
     963           1 :         CPPUNIT_ASSERT(array.empty());
     964          22 :         for(int idx(-10); idx <= 10; ++idx)
     965             :         {
     966          21 :             if(idx == 0)
     967             :             {
     968             :                 // nullptr is not valid for data
     969           1 :                 CPPUNIT_ASSERT_THROW(value->set_item(idx, nullptr_value), as2js::exception_invalid_data);
     970             :             }
     971             :             else
     972             :             {
     973             :                 // index is invalid
     974          20 :                 CPPUNIT_ASSERT_THROW(value->set_item(idx, nullptr_value), as2js::exception_index_out_of_range);
     975             :             }
     976             :         }
     977           1 :         CPPUNIT_ASSERT_THROW(value->get_object(), as2js::exception_internal_error);
     978           1 :         CPPUNIT_ASSERT_THROW(value->set_member("name", nullptr_value), as2js::exception_internal_error);
     979           1 :         as2js::Position const& p(value->get_position());
     980           1 :         CPPUNIT_ASSERT(p.get_filename() == pos.get_filename());
     981           1 :         CPPUNIT_ASSERT(p.get_function() == pos.get_function());
     982           1 :         CPPUNIT_ASSERT(p.get_line() == 109);
     983             : //std::cerr << "compare " << value->to_string() << " with " << cmp << "\n";
     984           1 :         CPPUNIT_ASSERT(value->to_string() == "[]");
     985             :         // copy operator
     986           2 :         as2js::JSON::JSONValue copy(*value);
     987           1 :         CPPUNIT_ASSERT(copy.get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_ARRAY);
     988           1 :         CPPUNIT_ASSERT_THROW(copy.get_int64().get() == 0, as2js::exception_internal_error);
     989           1 :         CPPUNIT_ASSERT_THROW(copy.get_float64().get() >= 0.0, as2js::exception_internal_error);
     990           1 :         CPPUNIT_ASSERT_THROW(copy.get_string() == "ignore", as2js::exception_internal_error);
     991           1 :         as2js::JSON::JSONValue::array_t const& array_copy(value->get_array());
     992           1 :         CPPUNIT_ASSERT(array_copy.empty());
     993          22 :         for(int idx(-10); idx <= 10; ++idx)
     994             :         {
     995          21 :             if(idx == 0)
     996             :             {
     997             :                 // nullptr is not valid for data
     998           1 :                 CPPUNIT_ASSERT_THROW(copy.set_item(idx, nullptr_value), as2js::exception_invalid_data);
     999             :             }
    1000             :             else
    1001             :             {
    1002             :                 // index is invalid
    1003          20 :                 CPPUNIT_ASSERT_THROW(copy.set_item(idx, nullptr_value), as2js::exception_index_out_of_range);
    1004             :             }
    1005             :         }
    1006           1 :         CPPUNIT_ASSERT_THROW(copy.get_object(), as2js::exception_internal_error);
    1007           1 :         CPPUNIT_ASSERT_THROW(copy.set_member("name", nullptr_value), as2js::exception_internal_error);
    1008           1 :         as2js::Position const& q(copy.get_position());
    1009           1 :         CPPUNIT_ASSERT(q.get_filename() == pos.get_filename());
    1010           1 :         CPPUNIT_ASSERT(q.get_function() == pos.get_function());
    1011           1 :         CPPUNIT_ASSERT(q.get_line() == 109);
    1012           2 :         CPPUNIT_ASSERT(copy.to_string() == "[]");
    1013             :     }
    1014             : 
    1015             :     // test with a few random arrays
    1016          11 :     for(int idx(0); idx < 10; ++idx)
    1017             :     {
    1018          10 :         as2js::Position pos;
    1019          10 :         pos.reset_counters(109);
    1020          10 :         pos.set_filename("array.json");
    1021          10 :         pos.set_function("save_array");
    1022          20 :         as2js::JSON::JSONValue::array_t initial;
    1023             : 
    1024          20 :         as2js::String result("[");
    1025          10 :         size_t const max_items(rand() % 100 + 20);
    1026         630 :         for(size_t j(0); j < max_items; ++j)
    1027             :         {
    1028         620 :             if(j != 0)
    1029             :             {
    1030         610 :                 result += ",";
    1031             :             }
    1032         620 :             as2js::JSON::JSONValue::pointer_t item;
    1033         620 :             int const select(rand() % 8);
    1034         620 :             switch(select)
    1035             :             {
    1036             :             case 0: // NULL
    1037          70 :                 item.reset(new as2js::JSON::JSONValue(pos));
    1038          70 :                 result += "null";
    1039          70 :                 break;
    1040             : 
    1041             :             case 1: // INT64
    1042             :                 {
    1043          78 :                     as2js::Int64::int64_type int_value((rand() << 13) ^ rand());
    1044          78 :                     as2js::Int64 integer(int_value);
    1045          78 :                     item.reset(new as2js::JSON::JSONValue(pos, integer));
    1046          78 :                     result += std::to_string(int_value);
    1047             :                 }
    1048          78 :                 break;
    1049             : 
    1050             :             case 2: // FLOAT64
    1051             :                 {
    1052          81 :                     as2js::Float64::float64_type flt_value(static_cast<double>((rand() << 16) | rand()) / static_cast<double>((rand() << 16) | rand()));
    1053          81 :                     as2js::Float64 flt(flt_value);
    1054          81 :                     item.reset(new as2js::JSON::JSONValue(pos, flt));
    1055          81 :                     result += std::to_string(flt_value);
    1056             :                 }
    1057          81 :                 break;
    1058             : 
    1059             :             case 3: // TRUE
    1060          68 :                 item.reset(new as2js::JSON::JSONValue(pos, true));
    1061          68 :                 result += "true";
    1062          68 :                 break;
    1063             : 
    1064             :             case 4: // FALSE
    1065          82 :                 item.reset(new as2js::JSON::JSONValue(pos, false));
    1066          82 :                 result += "false";
    1067          82 :                 break;
    1068             : 
    1069             :             case 5: // STRING
    1070             :                 {
    1071          69 :                     as2js::String str;
    1072         138 :                     as2js::String stringified;
    1073          69 :                     generate_string(str, stringified);
    1074          69 :                     item.reset(new as2js::JSON::JSONValue(pos, str));
    1075         138 :                     result += stringified;
    1076             :                 }
    1077          69 :                 break;
    1078             : 
    1079             :             case 6: // empty ARRAY
    1080             :                 {
    1081          89 :                     as2js::JSON::JSONValue::array_t empty_array;
    1082          89 :                     item.reset(new as2js::JSON::JSONValue(pos, empty_array));
    1083          89 :                     result += "[]";
    1084             :                 }
    1085          89 :                 break;
    1086             : 
    1087             :             case 7: // empty OBJECT
    1088             :                 {
    1089          83 :                     as2js::JSON::JSONValue::object_t empty_object;
    1090          83 :                     item.reset(new as2js::JSON::JSONValue(pos, empty_object));
    1091          83 :                     result += "{}";
    1092             :                 }
    1093          83 :                 break;
    1094             : 
    1095             :             // more?
    1096             :             default:
    1097           0 :                 throw std::logic_error("test generated an invalid # to generate an array item");
    1098             : 
    1099             :             }
    1100         620 :             initial.push_back(item);
    1101         620 :         }
    1102          10 :         result += "]";
    1103             : 
    1104          10 :         as2js::JSON::JSONValue::pointer_t value(new as2js::JSON::JSONValue(pos, initial));
    1105          10 :         CPPUNIT_ASSERT(value->get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_ARRAY);
    1106          10 :         CPPUNIT_ASSERT_THROW(value->get_int64().get() == 0, as2js::exception_internal_error);
    1107          10 :         CPPUNIT_ASSERT_THROW(value->get_float64().get() >= 0.0, as2js::exception_internal_error);
    1108          10 :         CPPUNIT_ASSERT_THROW(value->get_string() == "ignore", as2js::exception_internal_error);
    1109          10 :         as2js::JSON::JSONValue::array_t const& array(value->get_array());
    1110          10 :         CPPUNIT_ASSERT(array.size() == max_items);
    1111             :         //for(int idx(-10); idx <= 10; ++idx)
    1112             :         //{
    1113             :         //    if(idx == 0)
    1114             :         //    {
    1115             :         //        // nullptr is not valid for data
    1116             :         //        CPPUNIT_ASSERT_THROW(value->set_item(idx, nullptr_value), as2js::exception_invalid_data);
    1117             :         //    }
    1118             :         //    else
    1119             :         //    {
    1120             :         //        // index is invalid
    1121             :         //        CPPUNIT_ASSERT_THROW(value->set_item(idx, nullptr_value), as2js::exception_index_out_of_range);
    1122             :         //    }
    1123             :         //}
    1124          10 :         CPPUNIT_ASSERT_THROW(value->get_object(), as2js::exception_internal_error);
    1125          10 :         CPPUNIT_ASSERT_THROW(value->set_member("name", nullptr_value), as2js::exception_internal_error);
    1126          10 :         as2js::Position const& p(value->get_position());
    1127          10 :         CPPUNIT_ASSERT(p.get_filename() == pos.get_filename());
    1128          10 :         CPPUNIT_ASSERT(p.get_function() == pos.get_function());
    1129          10 :         CPPUNIT_ASSERT(p.get_line() == 109);
    1130             : //as2js::String r(value->to_string());
    1131             : //std::cerr << std::hex << " lengths " << r.length() << " / " << result.length() << "\n";
    1132             : //size_t max_chrs(std::min(r.length(), result.length()));
    1133             : //for(size_t g(0); g < max_chrs; ++g)
    1134             : //{
    1135             : //    if(static_cast<int>(r[g]) != static_cast<int>(result[g]))
    1136             : //    {
    1137             : //        std::cerr << " --- " << static_cast<int>(r[g]) << " / " << static_cast<int>(result[g]) << "\n";
    1138             : //    }
    1139             : //    else
    1140             : //    {
    1141             : //        std::cerr << " " << static_cast<int>(r[g]) << " / " << static_cast<int>(result[g]) << "\n";
    1142             : //    }
    1143             : //}
    1144             : //if(r.length() > result.length())
    1145             : //{
    1146             : //}
    1147             : //else
    1148             : //{
    1149             : //    for(size_t g(r.length()); g < result.length(); ++g)
    1150             : //    {
    1151             : //        std::cerr << " +++ " << static_cast<int>(result[g]) << "\n";
    1152             : //    }
    1153             : //}
    1154             : //std::cerr << std::dec;
    1155          10 :         CPPUNIT_ASSERT(value->to_string() == result);
    1156             :         // copy operator
    1157          20 :         as2js::JSON::JSONValue copy(*value);
    1158          10 :         CPPUNIT_ASSERT(copy.get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_ARRAY);
    1159          10 :         CPPUNIT_ASSERT_THROW(copy.get_int64().get() == 0, as2js::exception_internal_error);
    1160          10 :         CPPUNIT_ASSERT_THROW(copy.get_float64().get() >= 0.0, as2js::exception_internal_error);
    1161          10 :         CPPUNIT_ASSERT_THROW(copy.get_string() == "ignore", as2js::exception_internal_error);
    1162          10 :         as2js::JSON::JSONValue::array_t const& array_copy(value->get_array());
    1163          10 :         CPPUNIT_ASSERT(array_copy.size() == max_items);
    1164             :         //for(int idx(-10); idx <= 10; ++idx)
    1165             :         //{
    1166             :         //    if(idx == 0)
    1167             :         //    {
    1168             :         //        // nullptr is not valid for data
    1169             :         //        CPPUNIT_ASSERT_THROW(copy.set_item(idx, nullptr_value), as2js::exception_invalid_data);
    1170             :         //    }
    1171             :         //    else
    1172             :         //    {
    1173             :         //        // index is invalid
    1174             :         //        CPPUNIT_ASSERT_THROW(copy.set_item(idx, nullptr_value), as2js::exception_index_out_of_range);
    1175             :         //    }
    1176             :         //}
    1177          10 :         CPPUNIT_ASSERT_THROW(copy.get_object(), as2js::exception_internal_error);
    1178          10 :         CPPUNIT_ASSERT_THROW(copy.set_member("name", nullptr_value), as2js::exception_internal_error);
    1179          10 :         as2js::Position const& q(copy.get_position());
    1180          10 :         CPPUNIT_ASSERT(q.get_filename() == pos.get_filename());
    1181          10 :         CPPUNIT_ASSERT(q.get_function() == pos.get_function());
    1182          10 :         CPPUNIT_ASSERT(q.get_line() == 109);
    1183          10 :         CPPUNIT_ASSERT(copy.to_string() == result);
    1184             :         // the cyclic flag should have been reset, make sure of that:
    1185          10 :         CPPUNIT_ASSERT(copy.to_string() == result);
    1186             : 
    1187             :         // test that we catch a direct 'array[x] = array;'
    1188          10 :         value->set_item(max_items, value);
    1189             :         // copy is not affected...
    1190          10 :         CPPUNIT_ASSERT(copy.to_string() == result);
    1191             :         // value to string fails because it is cyclic
    1192          10 :         CPPUNIT_ASSERT_THROW(value->to_string() == result, as2js::exception_cyclical_structure);
    1193          10 :         as2js::JSON::JSONValue::array_t const& cyclic_array(value->get_array());
    1194          10 :         CPPUNIT_ASSERT(cyclic_array.size() == max_items + 1);
    1195             : 
    1196             :         {
    1197          10 :             as2js::String str;
    1198          20 :             as2js::String stringified;
    1199          10 :             generate_string(str, stringified);
    1200          20 :             as2js::JSON::JSONValue::pointer_t item;
    1201          10 :             item.reset(new as2js::JSON::JSONValue(pos, str));
    1202             :             // remove the existing ']' first
    1203          10 :             result.erase(result.end() - 1);
    1204          10 :             result += ',';
    1205          10 :             result += stringified;
    1206          10 :             result += ']';
    1207          10 :             value->set_item(max_items, item);
    1208             : //as2js::String r(value->to_string());
    1209             : //std::cerr << std::hex << " lengths " << r.length() << " / " << result.length() << "\n";
    1210             : //size_t max_chrs(std::min(r.length(), result.length()));
    1211             : //for(size_t g(0); g < max_chrs; ++g)
    1212             : //{
    1213             : //    if(static_cast<int>(r[g]) != static_cast<int>(result[g]))
    1214             : //    {
    1215             : //        std::cerr << " --- " << static_cast<int>(r[g]) << " / " << static_cast<int>(result[g]) << "\n";
    1216             : //    }
    1217             : //    else
    1218             : //    {
    1219             : //        std::cerr << " " << static_cast<int>(r[g]) << " / " << static_cast<int>(result[g]) << "\n";
    1220             : //    }
    1221             : //}
    1222             : //if(r.length() > result.length())
    1223             : //{
    1224             : //}
    1225             : //else
    1226             : //{
    1227             : //    for(size_t g(r.length()); g < result.length(); ++g)
    1228             : //    {
    1229             : //        std::cerr << " +++ " << static_cast<int>(result[g]) << "\n";
    1230             : //    }
    1231             : //}
    1232             : //std::cerr << std::dec;
    1233          20 :             CPPUNIT_ASSERT(value->to_string() == result);
    1234             :         }
    1235          21 :     }
    1236           1 : }
    1237             : 
    1238             : 
    1239           1 : void As2JsJSONUnitTests::test_object_value()
    1240             : {
    1241             :     // a null pointer value...
    1242           1 :     as2js::JSON::JSONValue::pointer_t const nullptr_value;
    1243             : 
    1244             :     // test with an empty array
    1245             :     {
    1246           1 :         as2js::Position pos;
    1247           1 :         pos.reset_counters(109);
    1248           1 :         pos.set_filename("object.json");
    1249           1 :         pos.set_function("save_object");
    1250           2 :         as2js::JSON::JSONValue::object_t initial;
    1251           2 :         as2js::JSON::JSONValue::pointer_t value(new as2js::JSON::JSONValue(pos, initial));
    1252           1 :         CPPUNIT_ASSERT(value->get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_OBJECT);
    1253           1 :         CPPUNIT_ASSERT_THROW(value->get_int64().get() == 0, as2js::exception_internal_error);
    1254           1 :         CPPUNIT_ASSERT_THROW(value->get_float64().get() >= 0.0, as2js::exception_internal_error);
    1255           1 :         CPPUNIT_ASSERT_THROW(value->get_string() == "ignore", as2js::exception_internal_error);
    1256           1 :         CPPUNIT_ASSERT_THROW(value->get_array(), as2js::exception_internal_error);
    1257           1 :         CPPUNIT_ASSERT_THROW(value->set_item(-1, nullptr_value), as2js::exception_internal_error);
    1258           1 :         as2js::JSON::JSONValue::object_t const& object(value->get_object());
    1259           1 :         CPPUNIT_ASSERT(object.empty());
    1260             :         // name is invalid
    1261           1 :         CPPUNIT_ASSERT_THROW(value->set_member("", nullptr_value), as2js::exception_invalid_index);
    1262             :         // nullptr is not valid for data
    1263           1 :         CPPUNIT_ASSERT_THROW(value->set_member("ignore", nullptr_value), as2js::exception_invalid_data);
    1264           1 :         as2js::Position const& p(value->get_position());
    1265           1 :         CPPUNIT_ASSERT(p.get_filename() == pos.get_filename());
    1266           1 :         CPPUNIT_ASSERT(p.get_function() == pos.get_function());
    1267           1 :         CPPUNIT_ASSERT(p.get_line() == 109);
    1268             : //std::cerr << "compare " << value->to_string() << " with " << cmp << "\n";
    1269           1 :         CPPUNIT_ASSERT(value->to_string() == "{}");
    1270             :         // copy operator
    1271           2 :         as2js::JSON::JSONValue copy(*value);
    1272           1 :         CPPUNIT_ASSERT(copy.get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_OBJECT);
    1273           1 :         CPPUNIT_ASSERT_THROW(copy.get_int64().get() == 0, as2js::exception_internal_error);
    1274           1 :         CPPUNIT_ASSERT_THROW(copy.get_float64().get() >= 0.0, as2js::exception_internal_error);
    1275           1 :         CPPUNIT_ASSERT_THROW(copy.get_string() == "ignore", as2js::exception_internal_error);
    1276           1 :         CPPUNIT_ASSERT_THROW(copy.get_array(), as2js::exception_internal_error);
    1277           1 :         CPPUNIT_ASSERT_THROW(copy.set_item(0, nullptr_value), as2js::exception_internal_error);
    1278           1 :         as2js::JSON::JSONValue::object_t const& object_copy(value->get_object());
    1279           1 :         CPPUNIT_ASSERT(object_copy.empty());
    1280             :         // name is invalid
    1281           1 :         CPPUNIT_ASSERT_THROW(copy.set_member("", nullptr_value), as2js::exception_invalid_index);
    1282             :         // nullptr is not valid for data
    1283           1 :         CPPUNIT_ASSERT_THROW(copy.set_member("ignore", nullptr_value), as2js::exception_invalid_data);
    1284           1 :         as2js::Position const& q(copy.get_position());
    1285           1 :         CPPUNIT_ASSERT(q.get_filename() == pos.get_filename());
    1286           1 :         CPPUNIT_ASSERT(q.get_function() == pos.get_function());
    1287           1 :         CPPUNIT_ASSERT(q.get_line() == 109);
    1288           2 :         CPPUNIT_ASSERT(copy.to_string() == "{}");
    1289             :     }
    1290             : 
    1291             :     // test with a few random objects
    1292             :     typedef std::map<as2js::String, as2js::String>  sort_t;
    1293          11 :     for(int idx(0); idx < 10; ++idx)
    1294             :     {
    1295          10 :         as2js::Position pos;
    1296          10 :         pos.reset_counters(199);
    1297          10 :         pos.set_filename("object.json");
    1298          10 :         pos.set_function("save_object");
    1299          20 :         as2js::JSON::JSONValue::object_t initial;
    1300          20 :         sort_t sorted;
    1301             : 
    1302          10 :         size_t const max_items(rand() % 100 + 20);
    1303         801 :         for(size_t j(0); j < max_items; ++j)
    1304             :         {
    1305         791 :             as2js::String field_name;
    1306        1582 :             as2js::String stringified_value;
    1307         791 :             generate_string(field_name, stringified_value);
    1308         791 :             stringified_value += ':';
    1309        1582 :             as2js::JSON::JSONValue::pointer_t item;
    1310         791 :             int const select(rand() % 8);
    1311         791 :             switch(select)
    1312             :             {
    1313             :             case 0: // NULL
    1314          95 :                 item.reset(new as2js::JSON::JSONValue(pos));
    1315          95 :                 stringified_value += "null";
    1316          95 :                 break;
    1317             : 
    1318             :             case 1: // INT64
    1319             :                 {
    1320         117 :                     as2js::Int64::int64_type int_value((rand() << 13) ^ rand());
    1321         117 :                     as2js::Int64 integer(int_value);
    1322         117 :                     item.reset(new as2js::JSON::JSONValue(pos, integer));
    1323         117 :                     stringified_value += std::to_string(int_value);
    1324             :                 }
    1325         117 :                 break;
    1326             : 
    1327             :             case 2: // FLOAT64
    1328             :                 {
    1329          99 :                     as2js::Float64::float64_type flt_value(static_cast<double>((rand() << 16) | rand()) / static_cast<double>((rand() << 16) | rand()));
    1330          99 :                     as2js::Float64 flt(flt_value);
    1331          99 :                     item.reset(new as2js::JSON::JSONValue(pos, flt));
    1332          99 :                     stringified_value += std::to_string(flt_value);
    1333             :                 }
    1334          99 :                 break;
    1335             : 
    1336             :             case 3: // TRUE
    1337          82 :                 item.reset(new as2js::JSON::JSONValue(pos, true));
    1338          82 :                 stringified_value += "true";
    1339          82 :                 break;
    1340             : 
    1341             :             case 4: // FALSE
    1342         103 :                 item.reset(new as2js::JSON::JSONValue(pos, false));
    1343         103 :                 stringified_value += "false";
    1344         103 :                 break;
    1345             : 
    1346             :             case 5: // STRING
    1347             :                 {
    1348         103 :                     as2js::String str;
    1349         206 :                     as2js::String stringified;
    1350         103 :                     generate_string(str, stringified);
    1351         103 :                     item.reset(new as2js::JSON::JSONValue(pos, str));
    1352         206 :                     stringified_value += stringified;
    1353             :                 }
    1354         103 :                 break;
    1355             : 
    1356             :             case 6: // empty ARRAY
    1357             :                 {
    1358         106 :                     as2js::JSON::JSONValue::array_t empty_array;
    1359         106 :                     item.reset(new as2js::JSON::JSONValue(pos, empty_array));
    1360         106 :                     stringified_value += "[]";
    1361             :                 }
    1362         106 :                 break;
    1363             : 
    1364             :             case 7: // empty OBJECT
    1365             :                 {
    1366          86 :                     as2js::JSON::JSONValue::object_t empty_object;
    1367          86 :                     item.reset(new as2js::JSON::JSONValue(pos, empty_object));
    1368          86 :                     stringified_value += "{}";
    1369             :                 }
    1370          86 :                 break;
    1371             : 
    1372             :             // more?
    1373             :             default:
    1374           0 :                 throw std::logic_error("test generated an invalid # to generate an object item");
    1375             : 
    1376             :             }
    1377         791 :             initial[field_name] = item;
    1378         791 :             sorted[field_name] = stringified_value;
    1379         791 :         }
    1380          10 :         as2js::String result("{");
    1381          10 :         bool first(true);
    1382         801 :         for(auto it : sorted)
    1383             :         {
    1384         791 :             if(!first)
    1385             :             {
    1386         781 :                 result += ',';
    1387             :             }
    1388             :             else
    1389             :             {
    1390          10 :                 first = false;
    1391             :             }
    1392         791 :             result += it.second;
    1393         791 :         }
    1394          10 :         result += "}";
    1395             : 
    1396          20 :         as2js::JSON::JSONValue::pointer_t value(new as2js::JSON::JSONValue(pos, initial));
    1397          10 :         CPPUNIT_ASSERT(value->get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_OBJECT);
    1398          10 :         CPPUNIT_ASSERT_THROW(value->get_int64().get() == 0, as2js::exception_internal_error);
    1399          10 :         CPPUNIT_ASSERT_THROW(value->get_float64().get() >= 0.0, as2js::exception_internal_error);
    1400          10 :         CPPUNIT_ASSERT_THROW(value->get_string() == "ignore", as2js::exception_internal_error);
    1401          10 :         CPPUNIT_ASSERT_THROW(value->get_array(), as2js::exception_internal_error);
    1402          10 :         CPPUNIT_ASSERT_THROW(value->set_item(0, nullptr_value), as2js::exception_internal_error);
    1403          10 :         as2js::JSON::JSONValue::object_t const& object(value->get_object());
    1404          10 :         CPPUNIT_ASSERT(object.size() == max_items);
    1405             :         //for(int idx(-10); idx <= 10; ++idx)
    1406             :         //{
    1407             :         //    if(idx == 0)
    1408             :         //    {
    1409             :         //        // nullptr is not valid for data
    1410             :         //        CPPUNIT_ASSERT_THROW(value->set_item(idx, nullptr_value), as2js::exception_invalid_data);
    1411             :         //    }
    1412             :         //    else
    1413             :         //    {
    1414             :         //        // index is invalid
    1415             :         //        CPPUNIT_ASSERT_THROW(value->set_item(idx, nullptr_value), as2js::exception_index_out_of_range);
    1416             :         //    }
    1417             :         //}
    1418          10 :         as2js::Position const& p(value->get_position());
    1419          10 :         CPPUNIT_ASSERT(p.get_filename() == pos.get_filename());
    1420          10 :         CPPUNIT_ASSERT(p.get_function() == pos.get_function());
    1421          10 :         CPPUNIT_ASSERT(p.get_line() == 199);
    1422             : //as2js::String r(value->to_string());
    1423             : //std::cerr << std::hex << " lengths " << r.length() << " / " << result.length() << "\n";
    1424             : //size_t max_chrs(std::min(r.length(), result.length()));
    1425             : //for(size_t g(0); g < max_chrs; ++g)
    1426             : //{
    1427             : //    if(static_cast<int>(r[g]) != static_cast<int>(result[g]))
    1428             : //    {
    1429             : //        std::cerr << " --- " << static_cast<int>(r[g]) << " / " << static_cast<int>(result[g]) << "\n";
    1430             : //    }
    1431             : //    else
    1432             : //    {
    1433             : //        std::cerr << " " << static_cast<int>(r[g]) << " / " << static_cast<int>(result[g]) << "\n";
    1434             : //    }
    1435             : //}
    1436             : //if(r.length() > result.length())
    1437             : //{
    1438             : //    for(size_t g(result.length()); g < r.length(); ++g)
    1439             : //    {
    1440             : //        std::cerr << " *** " << static_cast<int>(r[g]) << "\n";
    1441             : //    }
    1442             : //}
    1443             : //else
    1444             : //{
    1445             : //    for(size_t g(r.length()); g < result.length(); ++g)
    1446             : //    {
    1447             : //        std::cerr << " +++ " << static_cast<int>(result[g]) << "\n";
    1448             : //    }
    1449             : //}
    1450             : //std::cerr << std::dec;
    1451          10 :         CPPUNIT_ASSERT(value->to_string() == result);
    1452             :         // copy operator
    1453          20 :         as2js::JSON::JSONValue copy(*value);
    1454          10 :         CPPUNIT_ASSERT(copy.get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_OBJECT);
    1455          10 :         CPPUNIT_ASSERT_THROW(copy.get_int64().get() == 0, as2js::exception_internal_error);
    1456          10 :         CPPUNIT_ASSERT_THROW(copy.get_float64().get() >= 0.0, as2js::exception_internal_error);
    1457          10 :         CPPUNIT_ASSERT_THROW(copy.get_string() == "ignore", as2js::exception_internal_error);
    1458          10 :         CPPUNIT_ASSERT_THROW(copy.get_array(), as2js::exception_internal_error);
    1459          10 :         CPPUNIT_ASSERT_THROW(copy.set_item(0, nullptr_value), as2js::exception_internal_error);
    1460          10 :         as2js::JSON::JSONValue::object_t const& object_copy(value->get_object());
    1461          10 :         CPPUNIT_ASSERT(object_copy.size() == max_items);
    1462             :         //for(int idx(-10); idx <= 10; ++idx)
    1463             :         //{
    1464             :         //    if(idx == 0)
    1465             :         //    {
    1466             :         //        // nullptr is not valid for data
    1467             :         //        CPPUNIT_ASSERT_THROW(copy.set_item(idx, nullptr_value), as2js::exception_invalid_data);
    1468             :         //    }
    1469             :         //    else
    1470             :         //    {
    1471             :         //        // index is invalid
    1472             :         //        CPPUNIT_ASSERT_THROW(copy.set_item(idx, nullptr_value), as2js::exception_index_out_of_range);
    1473             :         //    }
    1474             :         //}
    1475          10 :         as2js::Position const& q(copy.get_position());
    1476          10 :         CPPUNIT_ASSERT(q.get_filename() == pos.get_filename());
    1477          10 :         CPPUNIT_ASSERT(q.get_function() == pos.get_function());
    1478          10 :         CPPUNIT_ASSERT(q.get_line() == 199);
    1479          10 :         CPPUNIT_ASSERT(copy.to_string() == result);
    1480             :         // the cyclic flag should have been reset, make sure of that:
    1481          10 :         CPPUNIT_ASSERT(copy.to_string() == result);
    1482             : 
    1483             :         // test that we catch a direct 'object[x] = object;'
    1484          10 :         value->set_member("random", value);
    1485             :         // copy is not affected...
    1486          10 :         CPPUNIT_ASSERT(copy.to_string() == result);
    1487             :         // value to string fails because it is cyclic
    1488          10 :         CPPUNIT_ASSERT_THROW(value->to_string() == result, as2js::exception_cyclical_structure);
    1489          10 :         as2js::JSON::JSONValue::object_t const& cyclic_object(value->get_object());
    1490          10 :         CPPUNIT_ASSERT(cyclic_object.size() == max_items + 1);
    1491             : 
    1492             :         {
    1493          10 :             as2js::String str;
    1494          20 :             as2js::String stringified("\"random\":");
    1495          10 :             generate_string(str, stringified);
    1496          20 :             as2js::JSON::JSONValue::pointer_t item;
    1497          10 :             item.reset(new as2js::JSON::JSONValue(pos, str));
    1498          10 :             sorted["random"] = stringified;
    1499             :             // with objects the entire result needs to be rebuilt
    1500          10 :             result = "{";
    1501          10 :             first = true;
    1502         811 :             for(auto it : sorted)
    1503             :             {
    1504         801 :                 if(!first)
    1505             :                 {
    1506         791 :                     result += ',';
    1507             :                 }
    1508             :                 else
    1509             :                 {
    1510          10 :                     first = false;
    1511             :                 }
    1512         801 :                 result += it.second;
    1513         801 :             }
    1514          10 :             result += "}";
    1515          10 :             value->set_member("random", item);
    1516             : //as2js::String r(value->to_string());
    1517             : //std::cerr << std::hex << " lengths " << r.length() << " / " << result.length() << "\n";
    1518             : //size_t max_chrs(std::min(r.length(), result.length()));
    1519             : //for(size_t g(0); g < max_chrs; ++g)
    1520             : //{
    1521             : //    if(static_cast<int>(r[g]) != static_cast<int>(result[g]))
    1522             : //    {
    1523             : //        std::cerr << " --- " << static_cast<int>(r[g]) << " / " << static_cast<int>(result[g]) << "\n";
    1524             : //    }
    1525             : //    else
    1526             : //    {
    1527             : //        std::cerr << " " << static_cast<int>(r[g]) << " / " << static_cast<int>(result[g]) << "\n";
    1528             : //    }
    1529             : //}
    1530             : //if(r.length() > result.length())
    1531             : //{
    1532             : //    for(size_t g(result.length()); g < r.length(); ++g)
    1533             : //    {
    1534             : //        std::cerr << " *** " << static_cast<int>(r[g]) << "\n";
    1535             : //    }
    1536             : //}
    1537             : //else
    1538             : //{
    1539             : //    for(size_t g(r.length()); g < result.length(); ++g)
    1540             : //    {
    1541             : //        std::cerr << " +++ " << static_cast<int>(result[g]) << "\n";
    1542             : //    }
    1543             : //}
    1544             : //std::cerr << std::dec;
    1545          20 :             CPPUNIT_ASSERT(value->to_string() == result);
    1546             :         }
    1547          21 :     }
    1548           1 : }
    1549             : 
    1550             : 
    1551           1 : void As2JsJSONUnitTests::test_json()
    1552             : {
    1553             :     // test with a few random objects
    1554           1 :     g_type_used = 0;
    1555             :     typedef std::map<as2js::String, as2js::String>  sort_t;
    1556          11 :     for(int idx(0); idx < 10 || g_type_used != TYPE_ALL; ++idx)
    1557             :     {
    1558          10 :         as2js::String const header(rand() & 1 ? "// we can have a C++ comment\n/* or even a C like comment in the header\n(not the rest because we do not have access...) */\n" : "");
    1559             : 
    1560          20 :         test_data_t data;
    1561          10 :         data.f_pos.reset_counters(199);
    1562          10 :         data.f_pos.set_filename("full.json");
    1563          10 :         data.f_pos.set_function("save_full");
    1564             : 
    1565          10 :         if(rand() & 1)
    1566             :         {
    1567           6 :             create_object(data);
    1568             :         }
    1569             :         else
    1570             :         {
    1571           4 :             create_array(data);
    1572             :         }
    1573          20 :         as2js::String expected;
    1574          10 :         expected += 0xFEFF; // BOM
    1575          10 :         expected += header;
    1576          10 :         if(!header.empty())
    1577             :         {
    1578           4 :             expected += '\n';
    1579             :         }
    1580          10 :         data_to_string(data.f_value, expected);
    1581             : //std::cerr << "created " << data.f_count << " items.\n";
    1582             : 
    1583          20 :         as2js::JSON::pointer_t json(new as2js::JSON);
    1584          10 :         json->set_value(data.f_value);
    1585             : 
    1586          20 :         as2js::StringOutput::pointer_t out(new as2js::StringOutput);
    1587          10 :         json->output(out, header);
    1588          10 :         as2js::String const& result(out->get_string());
    1589             : //{
    1590             : //std::cerr << std::hex << " lengths " << expected.length() << " / " << result.length() << "\n";
    1591             : //size_t max_chrs(std::min(expected.length(), result.length()));
    1592             : //for(size_t g(0); g < max_chrs; ++g)
    1593             : //{
    1594             : //    if(static_cast<int>(expected[g]) != static_cast<int>(result[g]))
    1595             : //    {
    1596             : //        std::cerr << " --- " << static_cast<int>(expected[g]) << " / " << static_cast<int>(result[g]) << "\n";
    1597             : //    }
    1598             : //    else
    1599             : //    {
    1600             : //        std::cerr << " " << static_cast<int>(expected[g]) << " / " << static_cast<int>(result[g]) << "\n";
    1601             : //    }
    1602             : //}
    1603             : //if(expected.length() > result.length())
    1604             : //{
    1605             : //    for(size_t g(result.length()); g < expected.length(); ++g)
    1606             : //    {
    1607             : //        std::cerr << " *** " << static_cast<int>(expected[g]) << "\n";
    1608             : //    }
    1609             : //}
    1610             : //else
    1611             : //{
    1612             : //    for(size_t g(expected.length()); g < result.length(); ++g)
    1613             : //    {
    1614             : //        std::cerr << " +++ " << static_cast<int>(result[g]) << "\n";
    1615             : //    }
    1616             : //}
    1617             : //std::cerr << std::dec;
    1618             : //}
    1619          10 :         CPPUNIT_ASSERT(result == expected);
    1620             : 
    1621          10 :         CPPUNIT_ASSERT(json->get_value() == data.f_value);
    1622             :         // make sure the tree is also correct:
    1623          20 :         as2js::String expected_tree;
    1624          10 :         expected_tree += 0xFEFF; // BOM
    1625          10 :         expected_tree += header;
    1626          10 :         if(!header.empty())
    1627             :         {
    1628           4 :             expected_tree += '\n';
    1629             :         }
    1630          10 :         data_to_string(json->get_value(), expected_tree);
    1631          10 :         CPPUNIT_ASSERT(expected_tree == expected);
    1632             : 
    1633             :         // copy operator
    1634          20 :         as2js::JSON copy(*json);
    1635             : 
    1636             :         // the copy gets the exact same value pointer...
    1637          10 :         CPPUNIT_ASSERT(copy.get_value() == data.f_value);
    1638             :         // make sure the tree is also correct:
    1639          20 :         as2js::String expected_copy;
    1640          10 :         expected_copy += 0xFEFF; // BOM
    1641          10 :         expected_copy += header;
    1642          10 :         if(!header.empty())
    1643             :         {
    1644           4 :             expected_copy += '\n';
    1645             :         }
    1646          10 :         data_to_string(copy.get_value(), expected_copy);
    1647          10 :         CPPUNIT_ASSERT(expected_copy == expected);
    1648             : 
    1649             :         // create an unsafe temporary file and save that JSON in there...
    1650          10 :         int number(rand() % 1000000);
    1651          20 :         std::stringstream ss;
    1652          10 :         ss << "/tmp/as2js_test" << std::setfill('0') << std::setw(6) << number << ".js";
    1653             : //std::cerr << "filename [" << ss.str() << "]\n";
    1654          20 :         std::string filename(ss.str());
    1655          10 :         json->save(filename, header);
    1656             : 
    1657          20 :         as2js::JSON::pointer_t load_json(new as2js::JSON);
    1658          20 :         as2js::JSON::JSONValue::pointer_t loaded_value(load_json->load(filename));
    1659          10 :         CPPUNIT_ASSERT(loaded_value == load_json->get_value());
    1660             : 
    1661          20 :         as2js::StringOutput::pointer_t lout(new as2js::StringOutput);
    1662          10 :         load_json->output(lout, header);
    1663          10 :         as2js::String const& lresult(lout->get_string());
    1664          10 :         CPPUNIT_ASSERT(lresult == expected);
    1665             : 
    1666          10 :         unlink(filename.c_str());
    1667          10 :     }
    1668           1 : }
    1669             : 
    1670             : 
    1671           1 : void As2JsJSONUnitTests::test_json_with_positive_numbers()
    1672             : {
    1673             :     as2js::String const content(
    1674             :             "// we can have a C++ comment\n"
    1675             :             "/* or even a C like comment in the header\n"
    1676             :             "(not the rest because we do not have access...) */\n"
    1677             :             "[\n"
    1678             :             "\t+111,\n"
    1679             :             "\t+1.113,\n"
    1680             :             "\t+Infinity,\n"
    1681             :             "\t+NaN\n"
    1682             :             "]\n"
    1683           1 :         );
    1684             : 
    1685           2 :     test_data_t data;
    1686           1 :     data.f_pos.reset_counters(201);
    1687           1 :     data.f_pos.set_filename("full.json");
    1688           1 :     data.f_pos.set_function("save_full");
    1689             : 
    1690           2 :     as2js::StringInput::pointer_t in(new as2js::StringInput(content));
    1691             : 
    1692           2 :     as2js::JSON::pointer_t load_json(new as2js::JSON);
    1693           2 :     as2js::JSON::JSONValue::pointer_t loaded_value(load_json->parse(in));
    1694           1 :     CPPUNIT_ASSERT(loaded_value == load_json->get_value());
    1695             : 
    1696           2 :     as2js::JSON::JSONValue::pointer_t value(load_json->get_value());
    1697           1 :     CPPUNIT_ASSERT(value->get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_ARRAY);
    1698           2 :     as2js::JSON::JSONValue::array_t array(value->get_array());
    1699           1 :     CPPUNIT_ASSERT(array.size() == 4);
    1700             : 
    1701           1 :     CPPUNIT_ASSERT(array[0]->get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_INT64);
    1702           1 :     as2js::Int64 integer(array[0]->get_int64());
    1703           1 :     CPPUNIT_ASSERT(integer.get() == 111);
    1704             : 
    1705           1 :     CPPUNIT_ASSERT(array[1]->get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_FLOAT64);
    1706           1 :     as2js::Float64 floating_point(array[1]->get_float64());
    1707             : #pragma GCC diagnostic push
    1708             : #pragma GCC diagnostic ignored "-Wfloat-equal"
    1709           1 :     CPPUNIT_ASSERT(floating_point.get() == 1.113);
    1710             : #pragma GCC diagnostic pop
    1711             : 
    1712           1 :     CPPUNIT_ASSERT(array[2]->get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_FLOAT64);
    1713           1 :     floating_point = array[2]->get_float64();
    1714           1 :     CPPUNIT_ASSERT(floating_point.is_positive_infinity());
    1715             : 
    1716           1 :     CPPUNIT_ASSERT(array[3]->get_type() == as2js::JSON::JSONValue::type_t::JSON_TYPE_FLOAT64);
    1717           1 :     floating_point = array[3]->get_float64();
    1718           2 :     CPPUNIT_ASSERT(floating_point.is_NaN());
    1719           1 : }
    1720             : 
    1721             : 
    1722           1 : void As2JsJSONUnitTests::test_error()
    1723             : {
    1724             :     {
    1725           1 :         test_callback::expected_t expected;
    1726           1 :         expected.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_ERROR;
    1727           1 :         expected.f_error_code = as2js::err_code_t::AS_ERR_NOT_FOUND;
    1728           1 :         expected.f_pos.set_filename("/this/file/definitively/does/not/exist/so/we'll/get/an/error/immediately");
    1729           1 :         expected.f_pos.set_function("unknown-func");
    1730           1 :         expected.f_message = "cannot open JSON file \"/this/file/definitively/does/not/exist/so/we'll/get/an/error/immediately\".";
    1731             : 
    1732           2 :         test_callback tc;
    1733           1 :         tc.f_expected.push_back(expected);
    1734             : 
    1735           2 :         as2js::JSON::pointer_t load_json(new as2js::JSON);
    1736           1 :         CPPUNIT_ASSERT(load_json->load("/this/file/definitively/does/not/exist/so/we'll/get/an/error/immediately") == as2js::JSON::JSONValue::pointer_t());
    1737           2 :         tc.got_called();
    1738             :     }
    1739             : 
    1740             :     {
    1741           1 :         test_callback::expected_t expected;
    1742           1 :         expected.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_FATAL;
    1743           1 :         expected.f_error_code = as2js::err_code_t::AS_ERR_CANNOT_COMPILE;
    1744           1 :         expected.f_pos.set_filename("unknown-file");
    1745           1 :         expected.f_pos.set_function("unknown-func");
    1746           1 :         expected.f_message = "could not open output file \"/this/file/definitively/does/not/exist/so/we'll/get/an/error/immediately\".";
    1747             : 
    1748           2 :         test_callback tc;
    1749           1 :         tc.f_expected.push_back(expected);
    1750             : 
    1751           2 :         as2js::JSON::pointer_t save_json(new as2js::JSON);
    1752           1 :         CPPUNIT_ASSERT(save_json->save("/this/file/definitively/does/not/exist/so/we'll/get/an/error/immediately", "// unused\n") == false);
    1753           2 :         tc.got_called();
    1754             :     }
    1755             : 
    1756             :     {
    1757           1 :         as2js::JSON::pointer_t json(new as2js::JSON);
    1758           2 :         as2js::StringOutput::pointer_t lout(new as2js::StringOutput);
    1759           2 :         as2js::String const header("// unused\n");
    1760           2 :         CPPUNIT_ASSERT_THROW(json->output(lout, header), as2js::exception_invalid_data);
    1761             :     }
    1762             : 
    1763             :     {
    1764             :         // use an unsafe temporary file...
    1765           1 :         int number(rand() % 1000000);
    1766           1 :         std::stringstream ss;
    1767           1 :         ss << "/tmp/as2js_test" << std::setfill('0') << std::setw(6) << number << ".js";
    1768           2 :         std::string filename(ss.str());
    1769             :         // create an empty file
    1770           1 :         FILE *f(fopen(filename.c_str(), "w"));
    1771           1 :         CPPUNIT_ASSERT(f != NULL);
    1772           1 :         fclose(f);
    1773             : 
    1774           2 :         test_callback tc;
    1775             : 
    1776           2 :         test_callback::expected_t expected1;
    1777           1 :         expected1.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_ERROR;
    1778           1 :         expected1.f_error_code = as2js::err_code_t::AS_ERR_UNEXPECTED_EOF;
    1779           1 :         expected1.f_pos.set_filename(filename);
    1780           1 :         expected1.f_pos.set_function("unknown-func");
    1781           1 :         expected1.f_message = "the end of the file was reached while reading JSON data.";
    1782           1 :         tc.f_expected.push_back(expected1);
    1783             : 
    1784           2 :         test_callback::expected_t expected2;
    1785           1 :         expected2.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_FATAL;
    1786           1 :         expected2.f_error_code = as2js::err_code_t::AS_ERR_CANNOT_COMPILE;
    1787           1 :         expected2.f_pos.set_filename(filename);
    1788           1 :         expected2.f_pos.set_function("unknown-func");
    1789           1 :         expected2.f_message = "could not interpret this JSON input \"" + filename + "\".";
    1790           1 :         tc.f_expected.push_back(expected2);
    1791             : 
    1792             : //std::cerr << "filename [" << ss.str() << "]\n";
    1793           2 :         as2js::JSON::pointer_t json(new as2js::JSON);
    1794           1 :         CPPUNIT_ASSERT(json->load(filename) == as2js::JSON::JSONValue::pointer_t());
    1795           2 :         tc.got_called();
    1796             :     }
    1797             : 
    1798             :     {
    1799             :         as2js::String str(
    1800             :             "{'valid':123,,'valid too':123}"
    1801           1 :         );
    1802           2 :         as2js::StringInput::pointer_t in(new as2js::StringInput(str));
    1803             : 
    1804           2 :         test_callback tc;
    1805             : 
    1806           2 :         test_callback::expected_t expected1;
    1807           1 :         expected1.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_ERROR;
    1808           1 :         expected1.f_error_code = as2js::err_code_t::AS_ERR_STRING_EXPECTED;
    1809           1 :         expected1.f_pos.set_filename("unknown-file");
    1810           1 :         expected1.f_pos.set_function("unknown-func");
    1811           1 :         expected1.f_message = "expected a string as the JSON object member name.";
    1812           1 :         tc.f_expected.push_back(expected1);
    1813             : 
    1814           2 :         test_callback::expected_t expected2;
    1815           1 :         expected2.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_FATAL;
    1816           1 :         expected2.f_error_code = as2js::err_code_t::AS_ERR_CANNOT_COMPILE;
    1817           1 :         expected2.f_pos.set_filename("unknown-file");
    1818           1 :         expected2.f_pos.set_function("unknown-func");
    1819           1 :         expected2.f_message = "could not interpret this JSON input \"\".";
    1820           1 :         tc.f_expected.push_back(expected2);
    1821             : 
    1822           2 :         as2js::JSON::pointer_t json(new as2js::JSON);
    1823           1 :         CPPUNIT_ASSERT(json->parse(in) == as2js::JSON::JSONValue::pointer_t());
    1824           2 :         tc.got_called();
    1825             :     }
    1826             : 
    1827             :     {
    1828             :         as2js::String str(
    1829             :             "{'valid':123,invalid:123}"
    1830           1 :         );
    1831           2 :         as2js::StringInput::pointer_t in(new as2js::StringInput(str));
    1832             : 
    1833           2 :         test_callback tc;
    1834             : 
    1835           2 :         test_callback::expected_t expected1;
    1836           1 :         expected1.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_ERROR;
    1837           1 :         expected1.f_error_code = as2js::err_code_t::AS_ERR_STRING_EXPECTED;
    1838           1 :         expected1.f_pos.set_filename("unknown-file");
    1839           1 :         expected1.f_pos.set_function("unknown-func");
    1840           1 :         expected1.f_message = "expected a string as the JSON object member name.";
    1841           1 :         tc.f_expected.push_back(expected1);
    1842             : 
    1843           2 :         test_callback::expected_t expected2;
    1844           1 :         expected2.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_FATAL;
    1845           1 :         expected2.f_error_code = as2js::err_code_t::AS_ERR_CANNOT_COMPILE;
    1846           1 :         expected2.f_pos.set_filename("unknown-file");
    1847           1 :         expected2.f_pos.set_function("unknown-func");
    1848           1 :         expected2.f_message = "could not interpret this JSON input \"\".";
    1849           1 :         tc.f_expected.push_back(expected2);
    1850             : 
    1851           2 :         as2js::JSON::pointer_t json(new as2js::JSON);
    1852           1 :         CPPUNIT_ASSERT(json->parse(in) == as2js::JSON::JSONValue::pointer_t());
    1853           2 :         tc.got_called();
    1854             :     }
    1855             : 
    1856             :     {
    1857             :         as2js::String str(
    1858             :             "{'valid':123,123:'invalid'}"
    1859           1 :         );
    1860           2 :         as2js::StringInput::pointer_t in(new as2js::StringInput(str));
    1861             : 
    1862           2 :         test_callback tc;
    1863             : 
    1864           2 :         test_callback::expected_t expected1;
    1865           1 :         expected1.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_ERROR;
    1866           1 :         expected1.f_error_code = as2js::err_code_t::AS_ERR_STRING_EXPECTED;
    1867           1 :         expected1.f_pos.set_filename("unknown-file");
    1868           1 :         expected1.f_pos.set_function("unknown-func");
    1869           1 :         expected1.f_message = "expected a string as the JSON object member name.";
    1870           1 :         tc.f_expected.push_back(expected1);
    1871             : 
    1872           2 :         test_callback::expected_t expected2;
    1873           1 :         expected2.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_FATAL;
    1874           1 :         expected2.f_error_code = as2js::err_code_t::AS_ERR_CANNOT_COMPILE;
    1875           1 :         expected2.f_pos.set_filename("unknown-file");
    1876           1 :         expected2.f_pos.set_function("unknown-func");
    1877           1 :         expected2.f_message = "could not interpret this JSON input \"\".";
    1878           1 :         tc.f_expected.push_back(expected2);
    1879             : 
    1880           2 :         as2js::JSON::pointer_t json(new as2js::JSON);
    1881           1 :         CPPUNIT_ASSERT(json->parse(in) == as2js::JSON::JSONValue::pointer_t());
    1882           2 :         tc.got_called();
    1883             :     }
    1884             : 
    1885             :     {
    1886             :         as2js::String str(
    1887             :             "{'valid':123,['invalid']}"
    1888           1 :         );
    1889           2 :         as2js::StringInput::pointer_t in(new as2js::StringInput(str));
    1890             : 
    1891           2 :         test_callback tc;
    1892             : 
    1893           2 :         test_callback::expected_t expected1;
    1894           1 :         expected1.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_ERROR;
    1895           1 :         expected1.f_error_code = as2js::err_code_t::AS_ERR_STRING_EXPECTED;
    1896           1 :         expected1.f_pos.set_filename("unknown-file");
    1897           1 :         expected1.f_pos.set_function("unknown-func");
    1898           1 :         expected1.f_message = "expected a string as the JSON object member name.";
    1899           1 :         tc.f_expected.push_back(expected1);
    1900             : 
    1901           2 :         test_callback::expected_t expected2;
    1902           1 :         expected2.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_FATAL;
    1903           1 :         expected2.f_error_code = as2js::err_code_t::AS_ERR_CANNOT_COMPILE;
    1904           1 :         expected2.f_pos.set_filename("unknown-file");
    1905           1 :         expected2.f_pos.set_function("unknown-func");
    1906           1 :         expected2.f_message = "could not interpret this JSON input \"\".";
    1907           1 :         tc.f_expected.push_back(expected2);
    1908             : 
    1909           2 :         as2js::JSON::pointer_t json(new as2js::JSON);
    1910           1 :         CPPUNIT_ASSERT(json->parse(in) == as2js::JSON::JSONValue::pointer_t());
    1911           2 :         tc.got_called();
    1912             :     }
    1913             : 
    1914             :     {
    1915             :         as2js::String str(
    1916             :             "{'valid':123,{'invalid':123}}"
    1917           1 :         );
    1918           2 :         as2js::StringInput::pointer_t in(new as2js::StringInput(str));
    1919             : 
    1920           2 :         test_callback tc;
    1921             : 
    1922           2 :         test_callback::expected_t expected1;
    1923           1 :         expected1.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_ERROR;
    1924           1 :         expected1.f_error_code = as2js::err_code_t::AS_ERR_STRING_EXPECTED;
    1925           1 :         expected1.f_pos.set_filename("unknown-file");
    1926           1 :         expected1.f_pos.set_function("unknown-func");
    1927           1 :         expected1.f_message = "expected a string as the JSON object member name.";
    1928           1 :         tc.f_expected.push_back(expected1);
    1929             : 
    1930           2 :         test_callback::expected_t expected2;
    1931           1 :         expected2.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_FATAL;
    1932           1 :         expected2.f_error_code = as2js::err_code_t::AS_ERR_CANNOT_COMPILE;
    1933           1 :         expected2.f_pos.set_filename("unknown-file");
    1934           1 :         expected2.f_pos.set_function("unknown-func");
    1935           1 :         expected2.f_message = "could not interpret this JSON input \"\".";
    1936           1 :         tc.f_expected.push_back(expected2);
    1937             : 
    1938           2 :         as2js::JSON::pointer_t json(new as2js::JSON);
    1939           1 :         CPPUNIT_ASSERT(json->parse(in) == as2js::JSON::JSONValue::pointer_t());
    1940           2 :         tc.got_called();
    1941             :     }
    1942             : 
    1943             :     {
    1944             :         as2js::String str(
    1945             :             "{'valid':123,'colon missing'123}"
    1946           1 :         );
    1947           2 :         as2js::StringInput::pointer_t in(new as2js::StringInput(str));
    1948             : 
    1949           2 :         test_callback tc;
    1950             : 
    1951           2 :         test_callback::expected_t expected1;
    1952           1 :         expected1.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_ERROR;
    1953           1 :         expected1.f_error_code = as2js::err_code_t::AS_ERR_COLON_EXPECTED;
    1954           1 :         expected1.f_pos.set_filename("unknown-file");
    1955           1 :         expected1.f_pos.set_function("unknown-func");
    1956           1 :         expected1.f_message = "expected a colon (:) as the JSON object member name and member value separator.";
    1957           1 :         tc.f_expected.push_back(expected1);
    1958             : 
    1959           2 :         test_callback::expected_t expected2;
    1960           1 :         expected2.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_FATAL;
    1961           1 :         expected2.f_error_code = as2js::err_code_t::AS_ERR_CANNOT_COMPILE;
    1962           1 :         expected2.f_pos.set_filename("unknown-file");
    1963           1 :         expected2.f_pos.set_function("unknown-func");
    1964           1 :         expected2.f_message = "could not interpret this JSON input \"\".";
    1965           1 :         tc.f_expected.push_back(expected2);
    1966             : 
    1967           2 :         as2js::JSON::pointer_t json(new as2js::JSON);
    1968           1 :         CPPUNIT_ASSERT(json->parse(in) == as2js::JSON::JSONValue::pointer_t());
    1969           2 :         tc.got_called();
    1970             :     }
    1971             : 
    1972             :     {
    1973             :         as2js::String str(
    1974             :             // we use 'valid' twice but one is in a sub-object to test
    1975             :             // that does not generate a problem
    1976             :             "{'valid':123,'sub-member':{'valid':123,'sub-sub-member':{'sub-sub-invalid'123},'ignore':'this'}}"
    1977           1 :         );
    1978           2 :         as2js::StringInput::pointer_t in(new as2js::StringInput(str));
    1979             : 
    1980           2 :         test_callback tc;
    1981             : 
    1982           2 :         test_callback::expected_t expected1;
    1983           1 :         expected1.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_ERROR;
    1984           1 :         expected1.f_error_code = as2js::err_code_t::AS_ERR_COLON_EXPECTED;
    1985           1 :         expected1.f_pos.set_filename("unknown-file");
    1986           1 :         expected1.f_pos.set_function("unknown-func");
    1987           1 :         expected1.f_message = "expected a colon (:) as the JSON object member name and member value separator.";
    1988           1 :         tc.f_expected.push_back(expected1);
    1989             : 
    1990           2 :         test_callback::expected_t expected2;
    1991           1 :         expected2.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_FATAL;
    1992           1 :         expected2.f_error_code = as2js::err_code_t::AS_ERR_CANNOT_COMPILE;
    1993           1 :         expected2.f_pos.set_filename("unknown-file");
    1994           1 :         expected2.f_pos.set_function("unknown-func");
    1995           1 :         expected2.f_message = "could not interpret this JSON input \"\".";
    1996           1 :         tc.f_expected.push_back(expected2);
    1997             : 
    1998           2 :         as2js::JSON::pointer_t json(new as2js::JSON);
    1999           1 :         CPPUNIT_ASSERT(json->parse(in) == as2js::JSON::JSONValue::pointer_t());
    2000           2 :         tc.got_called();
    2001             :     }
    2002             : 
    2003             :     {
    2004             :         as2js::String str(
    2005             :             "{'valid':123,'re-valid':{'sub-valid':123,'sub-sub-member':{'sub-sub-valid':123},'more-valid':'this'},'valid':'again'}"
    2006           1 :         );
    2007           2 :         as2js::StringInput::pointer_t in(new as2js::StringInput(str));
    2008             : 
    2009           2 :         test_callback tc;
    2010             : 
    2011           2 :         test_callback::expected_t expected1;
    2012           1 :         expected1.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_ERROR;
    2013           1 :         expected1.f_error_code = as2js::err_code_t::AS_ERR_OBJECT_MEMBER_DEFINED_TWICE;
    2014           1 :         expected1.f_pos.set_filename("unknown-file");
    2015           1 :         expected1.f_pos.set_function("unknown-func");
    2016           1 :         expected1.f_message = "the same object member \"valid\" was defined twice, which is not allowed in JSON.";
    2017           1 :         tc.f_expected.push_back(expected1);
    2018             : 
    2019           2 :         as2js::JSON::pointer_t json(new as2js::JSON);
    2020             :         // defined twice does not mean we get a null pointer...
    2021             :         // (we should enhance this test to verify the result which is
    2022             :         // that we keep the first entry with a given name.)
    2023           1 :         CPPUNIT_ASSERT(json->parse(in) != as2js::JSON::JSONValue::pointer_t());
    2024           2 :         tc.got_called();
    2025             :     }
    2026             : 
    2027             :     {
    2028             :         as2js::String str(
    2029             :             "{'valid':123 'next-member':456}"
    2030           1 :         );
    2031           2 :         as2js::StringInput::pointer_t in(new as2js::StringInput(str));
    2032             : 
    2033           2 :         test_callback tc;
    2034             : 
    2035           2 :         test_callback::expected_t expected1;
    2036           1 :         expected1.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_ERROR;
    2037           1 :         expected1.f_error_code = as2js::err_code_t::AS_ERR_COMMA_EXPECTED;
    2038           1 :         expected1.f_pos.set_filename("unknown-file");
    2039           1 :         expected1.f_pos.set_function("unknown-func");
    2040           1 :         expected1.f_message = "expected a comma (,) to separate two JSON object members.";
    2041           1 :         tc.f_expected.push_back(expected1);
    2042             : 
    2043           2 :         test_callback::expected_t expected2;
    2044           1 :         expected2.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_FATAL;
    2045           1 :         expected2.f_error_code = as2js::err_code_t::AS_ERR_CANNOT_COMPILE;
    2046           1 :         expected2.f_pos.set_filename("unknown-file");
    2047           1 :         expected2.f_pos.set_function("unknown-func");
    2048           1 :         expected2.f_message = "could not interpret this JSON input \"\".";
    2049           1 :         tc.f_expected.push_back(expected2);
    2050             : 
    2051           2 :         as2js::JSON::pointer_t json(new as2js::JSON);
    2052           1 :         CPPUNIT_ASSERT(json->parse(in) == as2js::JSON::JSONValue::pointer_t());
    2053           2 :         tc.got_called();
    2054             :     }
    2055             : 
    2056             :     {
    2057             :         as2js::String str(
    2058             :             "['valid',-123,,'next-item',456]"
    2059           1 :         );
    2060           2 :         as2js::StringInput::pointer_t in(new as2js::StringInput(str));
    2061             : 
    2062           2 :         test_callback tc;
    2063             : 
    2064           2 :         test_callback::expected_t expected1;
    2065           1 :         expected1.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_ERROR;
    2066           1 :         expected1.f_error_code = as2js::err_code_t::AS_ERR_UNEXPECTED_TOKEN;
    2067           1 :         expected1.f_pos.set_filename("unknown-file");
    2068           1 :         expected1.f_pos.set_function("unknown-func");
    2069           1 :         expected1.f_message = "unexpected token (COMMA) found in a JSON input stream.";
    2070           1 :         tc.f_expected.push_back(expected1);
    2071             : 
    2072           2 :         test_callback::expected_t expected2;
    2073           1 :         expected2.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_FATAL;
    2074           1 :         expected2.f_error_code = as2js::err_code_t::AS_ERR_CANNOT_COMPILE;
    2075           1 :         expected2.f_pos.set_filename("unknown-file");
    2076           1 :         expected2.f_pos.set_function("unknown-func");
    2077           1 :         expected2.f_message = "could not interpret this JSON input \"\".";
    2078           1 :         tc.f_expected.push_back(expected2);
    2079             : 
    2080           2 :         as2js::JSON::pointer_t json(new as2js::JSON);
    2081           1 :         CPPUNIT_ASSERT(json->parse(in) == as2js::JSON::JSONValue::pointer_t());
    2082           2 :         tc.got_called();
    2083             :     }
    2084             : 
    2085             :     {
    2086             :         as2js::String str(
    2087             :             "['valid',-555,'bad-neg',-'123']"
    2088           1 :         );
    2089           2 :         as2js::StringInput::pointer_t in(new as2js::StringInput(str));
    2090             : 
    2091           2 :         test_callback tc;
    2092             : 
    2093           2 :         test_callback::expected_t expected1;
    2094           1 :         expected1.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_ERROR;
    2095           1 :         expected1.f_error_code = as2js::err_code_t::AS_ERR_UNEXPECTED_TOKEN;
    2096           1 :         expected1.f_pos.set_filename("unknown-file");
    2097           1 :         expected1.f_pos.set_function("unknown-func");
    2098           1 :         expected1.f_message = "unexpected token (STRING) found after a '-' sign, a number was expected.";
    2099           1 :         tc.f_expected.push_back(expected1);
    2100             : 
    2101           2 :         test_callback::expected_t expected2;
    2102           1 :         expected2.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_FATAL;
    2103           1 :         expected2.f_error_code = as2js::err_code_t::AS_ERR_CANNOT_COMPILE;
    2104           1 :         expected2.f_pos.set_filename("unknown-file");
    2105           1 :         expected2.f_pos.set_function("unknown-func");
    2106           1 :         expected2.f_message = "could not interpret this JSON input \"\".";
    2107           1 :         tc.f_expected.push_back(expected2);
    2108             : 
    2109           2 :         as2js::JSON::pointer_t json(new as2js::JSON);
    2110           1 :         CPPUNIT_ASSERT(json->parse(in) == as2js::JSON::JSONValue::pointer_t());
    2111           2 :         tc.got_called();
    2112             :     }
    2113             : 
    2114             :     {
    2115             :         as2js::String str(
    2116             :             "['valid',+555,'bad-pos',+'123']"
    2117           1 :         );
    2118           2 :         as2js::StringInput::pointer_t in(new as2js::StringInput(str));
    2119             : 
    2120           2 :         test_callback tc;
    2121             : 
    2122           2 :         test_callback::expected_t expected1;
    2123           1 :         expected1.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_ERROR;
    2124           1 :         expected1.f_error_code = as2js::err_code_t::AS_ERR_UNEXPECTED_TOKEN;
    2125           1 :         expected1.f_pos.set_filename("unknown-file");
    2126           1 :         expected1.f_pos.set_function("unknown-func");
    2127           1 :         expected1.f_message = "unexpected token (STRING) found after a '+' sign, a number was expected.";
    2128           1 :         tc.f_expected.push_back(expected1);
    2129             : 
    2130           2 :         test_callback::expected_t expected2;
    2131           1 :         expected2.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_FATAL;
    2132           1 :         expected2.f_error_code = as2js::err_code_t::AS_ERR_CANNOT_COMPILE;
    2133           1 :         expected2.f_pos.set_filename("unknown-file");
    2134           1 :         expected2.f_pos.set_function("unknown-func");
    2135           1 :         expected2.f_message = "could not interpret this JSON input \"\".";
    2136           1 :         tc.f_expected.push_back(expected2);
    2137             : 
    2138           2 :         as2js::JSON::pointer_t json(new as2js::JSON);
    2139           1 :         CPPUNIT_ASSERT(json->parse(in) == as2js::JSON::JSONValue::pointer_t());
    2140           2 :         tc.got_called();
    2141             :     }
    2142             : 
    2143             :     {
    2144             :         as2js::String str(
    2145             :             "['valid',123 'next-item',456]"
    2146           1 :         );
    2147           2 :         as2js::StringInput::pointer_t in(new as2js::StringInput(str));
    2148             : 
    2149           2 :         test_callback tc;
    2150             : 
    2151           2 :         test_callback::expected_t expected1;
    2152           1 :         expected1.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_ERROR;
    2153           1 :         expected1.f_error_code = as2js::err_code_t::AS_ERR_COMMA_EXPECTED;
    2154           1 :         expected1.f_pos.set_filename("unknown-file");
    2155           1 :         expected1.f_pos.set_function("unknown-func");
    2156           1 :         expected1.f_message = "expected a comma (,) to separate two JSON array items.";
    2157           1 :         tc.f_expected.push_back(expected1);
    2158             : 
    2159           2 :         test_callback::expected_t expected2;
    2160           1 :         expected2.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_FATAL;
    2161           1 :         expected2.f_error_code = as2js::err_code_t::AS_ERR_CANNOT_COMPILE;
    2162           1 :         expected2.f_pos.set_filename("unknown-file");
    2163           1 :         expected2.f_pos.set_function("unknown-func");
    2164           1 :         expected2.f_message = "could not interpret this JSON input \"\".";
    2165           1 :         tc.f_expected.push_back(expected2);
    2166             : 
    2167           2 :         as2js::JSON::pointer_t json(new as2js::JSON);
    2168           1 :         CPPUNIT_ASSERT(json->parse(in) == as2js::JSON::JSONValue::pointer_t());
    2169           2 :         tc.got_called();
    2170             :     }
    2171             : 
    2172             :     {
    2173             :         as2js::String str(
    2174             :             "['valid',[123 'next-item'],456]"
    2175           1 :         );
    2176           2 :         as2js::StringInput::pointer_t in(new as2js::StringInput(str));
    2177             : 
    2178           2 :         test_callback tc;
    2179             : 
    2180           2 :         test_callback::expected_t expected1;
    2181           1 :         expected1.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_ERROR;
    2182           1 :         expected1.f_error_code = as2js::err_code_t::AS_ERR_COMMA_EXPECTED;
    2183           1 :         expected1.f_pos.set_filename("unknown-file");
    2184           1 :         expected1.f_pos.set_function("unknown-func");
    2185           1 :         expected1.f_message = "expected a comma (,) to separate two JSON array items.";
    2186           1 :         tc.f_expected.push_back(expected1);
    2187             : 
    2188           2 :         test_callback::expected_t expected2;
    2189           1 :         expected2.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_FATAL;
    2190           1 :         expected2.f_error_code = as2js::err_code_t::AS_ERR_CANNOT_COMPILE;
    2191           1 :         expected2.f_pos.set_filename("unknown-file");
    2192           1 :         expected2.f_pos.set_function("unknown-func");
    2193           1 :         expected2.f_message = "could not interpret this JSON input \"\".";
    2194           1 :         tc.f_expected.push_back(expected2);
    2195             : 
    2196           2 :         as2js::JSON::pointer_t json(new as2js::JSON);
    2197           1 :         CPPUNIT_ASSERT(json->parse(in) == as2js::JSON::JSONValue::pointer_t());
    2198           2 :         tc.got_called();
    2199             :     }
    2200             : 
    2201             :     // skip controls to avoid problems with the lexer itself...
    2202     1114081 :     for(as2js::as_char_t c(0x20); c < 0x110000; ++c)
    2203             :     {
    2204     1114080 :         switch(c)
    2205             :         {
    2206             :         //case '\n':
    2207             :         //case '\r':
    2208             :         //case '\t':
    2209             :         case ' ':
    2210             :         case '{':
    2211             :         case '[':
    2212             :         case '\'':
    2213             :         case '"':
    2214             :         case '#':
    2215             :         case '-':
    2216             :         case '@':
    2217             :         case '\\':
    2218             :         case '`':
    2219             :         case 0x7F:
    2220             :         //case ',': -- that would generate errors because it would be in the wrong place
    2221             :         case '.':
    2222             :         case '0':
    2223             :         case '1':
    2224             :         case '2':
    2225             :         case '3':
    2226             :         case '4':
    2227             :         case '5':
    2228             :         case '6':
    2229             :         case '7':
    2230             :         case '8':
    2231             :         case '9':
    2232             :             // that looks like valid entries as is... so ignore
    2233     1010770 :             continue;
    2234             : 
    2235             :         default:
    2236     1114058 :             if(c >= 0xD800 && c <= 0xDFFF)
    2237             :             {
    2238             :                 // skip surrogate, no need to test those
    2239        2048 :                 continue;
    2240             :             }
    2241     1112010 :             if(!is_identifier_char(c))
    2242             :             {
    2243             :                 // skip "punctuation" for now...
    2244     1008678 :                 continue;
    2245             :             }
    2246      103332 :             break;
    2247             : 
    2248             :         }
    2249      103332 :         as2js::String str;
    2250      103332 :         str += c;
    2251             : 
    2252      206664 :         as2js::Node::pointer_t node;
    2253             :         {
    2254      103332 :             as2js::Options::pointer_t options(new as2js::Options);
    2255      103332 :             options->set_option(as2js::Options::option_t::OPTION_JSON, 1);
    2256      206664 :             as2js::Input::pointer_t input(new as2js::StringInput(str));
    2257      206664 :             as2js::Lexer::pointer_t lexer(new as2js::Lexer(input, options));
    2258      103332 :             CPPUNIT_ASSERT(lexer->get_input() == input);
    2259      103332 :             node = lexer->get_next_token();
    2260      206664 :             CPPUNIT_ASSERT(!!node);
    2261             :         }
    2262             : 
    2263      206664 :         as2js::StringInput::pointer_t in(new as2js::StringInput(str));
    2264             : 
    2265      206664 :         test_callback tc;
    2266             : 
    2267      206664 :         test_callback::expected_t expected1;
    2268      103332 :         expected1.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_ERROR;
    2269      103332 :         expected1.f_error_code = as2js::err_code_t::AS_ERR_UNEXPECTED_TOKEN;
    2270      103332 :         expected1.f_pos.set_filename("unknown-file");
    2271      103332 :         expected1.f_pos.set_function("unknown-func");
    2272      103332 :         expected1.f_message = "unexpected token (";
    2273      103332 :         expected1.f_message += node->get_type_name();
    2274      103332 :         expected1.f_message += ") found in a JSON input stream.";
    2275      103332 :         tc.f_expected.push_back(expected1);
    2276             : 
    2277      206664 :         test_callback::expected_t expected2;
    2278      103332 :         expected2.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_FATAL;
    2279      103332 :         expected2.f_error_code = as2js::err_code_t::AS_ERR_CANNOT_COMPILE;
    2280      103332 :         expected2.f_pos.set_filename("unknown-file");
    2281      103332 :         expected2.f_pos.set_function("unknown-func");
    2282      103332 :         expected2.f_message = "could not interpret this JSON input \"\".";
    2283      103332 :         tc.f_expected.push_back(expected2);
    2284             : 
    2285      206664 :         as2js::JSON::pointer_t json(new as2js::JSON);
    2286      103332 :         CPPUNIT_ASSERT(json->parse(in) == as2js::JSON::JSONValue::pointer_t());
    2287      103332 :         tc.got_called();
    2288      103332 :     }
    2289          13 : }
    2290             : 
    2291             : 
    2292             : 
    2293             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.10