LCOV - code coverage report
Current view: top level - tests - catch_string.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 372 372 100.0 %
Date: 2023-07-29 22:00:24 Functions: 6 6 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2011-2023  Made to Order Software Corp.  All Rights Reserved
       2             : //
       3             : // https://snapwebsites.org/project/as2js
       4             : // contact@m2osw.com
       5             : //
       6             : // This program is free software: you can redistribute it and/or modify
       7             : // it under the terms of the GNU General Public License as published by
       8             : // the Free Software Foundation, either version 3 of the License, or
       9             : // (at your option) any later version.
      10             : //
      11             : // This program is distributed in the hope that it will be useful,
      12             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             : // GNU General Public License for more details.
      15             : //
      16             : // You should have received a copy of the GNU General Public License
      17             : // along with this program.  If not, see <https://www.gnu.org/licenses/>.
      18             : 
      19             : // as2js
      20             : //
      21             : #include    <as2js/string.h>
      22             : #include    <as2js/exception.h>
      23             : 
      24             : 
      25             : // self
      26             : //
      27             : #include    "catch_main.h"
      28             : 
      29             : 
      30             : // C++
      31             : //
      32             : #include    <algorithm>
      33             : #include    <cstring>
      34             : #include    <iomanip>
      35             : 
      36             : 
      37             : // last include
      38             : //
      39             : #include    <snapdev/poison.h>
      40             : 
      41             : 
      42             : 
      43             : namespace
      44             : {
      45             : 
      46             : 
      47             : 
      48       10215 : bool close_double(double a, double b, double epsilon)
      49             : {
      50       10215 :     return a >= b - epsilon && a <= b + epsilon;
      51             : }
      52             : 
      53             : 
      54             : 
      55             : }
      56             : // no name namespace
      57             : 
      58             : 
      59             : 
      60             : 
      61           1 : CATCH_TEST_CASE("string_empty", "[string][type]")
      62             : {
      63           1 :     CATCH_START_SECTION("string: empty string validity")
      64             :     {
      65             :         // a little extra test, make sure a string is empty on
      66             :         // creation without anything
      67             :         //
      68           1 :         std::string str1;
      69           1 :         CATCH_REQUIRE(as2js::valid(str1));
      70           1 :     }
      71           1 :     CATCH_END_SECTION()
      72           1 : }
      73             : 
      74             : 
      75           1 : CATCH_TEST_CASE("string_bad_utf8", "[string][type]")
      76             : {
      77           1 :     CATCH_START_SECTION("string: bad UTF-8 sequences")
      78             :     {
      79             :         // UTF-8 starts with 0xC0 to 0xF4 and those must be followed by
      80             :         // 0x80 to 0xBF bytes anything else is incorrect
      81             :         //
      82          54 :         for(int i(0xC0); i <= 0xF4; ++i)
      83             :         {
      84             :             // too small a number just after 0xA0 to 0xF4
      85             :             //
      86        6784 :             for(int j(0x01); j <= 0x7F; ++j)
      87             :             {
      88        6731 :                 char const buf[3]{
      89             :                     static_cast<char>(i),
      90             :                     static_cast<char>(j),
      91             :                     '\0'
      92        6731 :                 };
      93       13462 :                 std::string const bad_utf8(buf);
      94        6731 :                 CATCH_REQUIRE_FALSE(as2js::valid(bad_utf8));
      95             : 
      96        6731 :                 std::string const start_string(SNAP_CATCH2_NAMESPACE::random_string(1, 100, SNAP_CATCH2_NAMESPACE::character_t::CHARACTER_ASCII));
      97        6731 :                 std::string const end_string(SNAP_CATCH2_NAMESPACE::random_string(1, 100, SNAP_CATCH2_NAMESPACE::character_t::CHARACTER_ASCII));
      98        6731 :                 CATCH_REQUIRE(as2js::valid(start_string));
      99        6731 :                 CATCH_REQUIRE(as2js::valid(end_string));
     100             : 
     101             :                 // make sure it gets caught anywhere in a string
     102             :                 //
     103       13462 :                 std::string const complete_string(start_string + bad_utf8 + end_string);
     104        6731 :                 CATCH_REQUIRE_FALSE(as2js::valid(complete_string));
     105        6731 :             }
     106             : 
     107             :             // too large a number just after 0xA0 to 0xFF
     108             :             //
     109        3445 :             for(int j(0xC0); j <= 0xFF; ++j)
     110             :             {
     111        3392 :                 char buf[3]{
     112             :                     static_cast<char>(i),
     113             :                     static_cast<char>(j),
     114             :                     '\0'
     115        3392 :                 };
     116        6784 :                 std::string const bad_utf8(buf);
     117        3392 :                 CATCH_REQUIRE_FALSE(as2js::valid(bad_utf8));
     118             : 
     119        3392 :                 std::string const start_string(SNAP_CATCH2_NAMESPACE::random_string(1, 100, SNAP_CATCH2_NAMESPACE::character_t::CHARACTER_ASCII));
     120        3392 :                 std::string const end_string(SNAP_CATCH2_NAMESPACE::random_string(1, 100, SNAP_CATCH2_NAMESPACE::character_t::CHARACTER_ASCII));
     121        3392 :                 CATCH_REQUIRE(as2js::valid(start_string));
     122        3392 :                 CATCH_REQUIRE(as2js::valid(end_string));
     123             : 
     124             :                 // make sure it gets caught anywhere in a string
     125             :                 //
     126        6784 :                 std::string const complete_string(start_string + bad_utf8 + end_string);
     127        3392 :                 CATCH_REQUIRE_FALSE(as2js::valid(complete_string));
     128        3392 :             }
     129             : 
     130             :             // note: the libutf8 already has many tests so I won't check
     131             :             //       every single possibility of invalid UTF-8; if there is
     132             :             //       an issue with such, we should verify with libutf8 instead
     133             :         }
     134             :     }
     135           1 :     CATCH_END_SECTION()
     136           1 : }
     137             : 
     138             : 
     139           3 : CATCH_TEST_CASE("string", "[string][type]")
     140             : {
     141           3 :     CATCH_START_SECTION("string: check valid characters")
     142             :     {
     143     1112065 :         for(char32_t c(0); c < 0x110000; ++c)
     144             :         {
     145             :             // skip the surrogates at once
     146             :             //
     147     1112064 :             if(c == 0xD800)
     148             :             {
     149           1 :                 c = 0xE000;
     150             :             }
     151     1112064 :             CATCH_REQUIRE(as2js::valid_character(c));
     152             :         }
     153             :     }
     154           3 :     CATCH_END_SECTION()
     155             : 
     156           3 :     CATCH_START_SECTION("string: check surrogates (not valid UTF-32)")
     157             :     {
     158        2049 :         for(char32_t c(0xD800); c < 0xE000; ++c)
     159             :         {
     160        2048 :             CATCH_REQUIRE_FALSE(as2js::valid_character(c));
     161             :         }
     162             :     }
     163           3 :     CATCH_END_SECTION()
     164             : 
     165           3 :     CATCH_START_SECTION("string: check outside range (not valid UTF-32)")
     166             :     {
     167        1001 :         for(int i(0); i < 1000; ++i)
     168             :         {
     169        1000 :             char32_t c(0);
     170             :             do
     171             :             {
     172        1000 :                 SNAP_CATCH2_NAMESPACE::random(c);
     173             :             }
     174        1000 :             while(c < 0x110000);
     175        1000 :             CATCH_REQUIRE_FALSE(as2js::valid_character(c));
     176             :         }
     177             :     }
     178           3 :     CATCH_END_SECTION()
     179           3 : }
     180             : 
     181             : 
     182           9 : CATCH_TEST_CASE("string_number", "[string][type][number]")
     183             : {
     184           9 :     CATCH_START_SECTION("string_number: empty string is 0, 0.0, and false")
     185             :     {
     186           1 :         std::string str;
     187           1 :         CATCH_REQUIRE(as2js::is_integer(str));
     188           1 :         CATCH_REQUIRE(as2js::is_floating_point(str));
     189           1 :         CATCH_REQUIRE(as2js::is_number(str));
     190           1 :         CATCH_REQUIRE(as2js::to_integer(str) == 0);
     191             : #pragma GCC diagnostic push
     192             : #pragma GCC diagnostic ignored "-Wfloat-equal"
     193           1 :         bool const is_equal(as2js::to_floating_point(str) == 0.0);
     194             : #pragma GCC diagnostic pop
     195           1 :         CATCH_REQUIRE(is_equal);
     196           1 :         CATCH_REQUIRE_FALSE(as2js::is_true(str));
     197           1 :     }
     198           9 :     CATCH_END_SECTION()
     199             : 
     200           9 :     CATCH_START_SECTION("string_number: a period alone is not a floating point number")
     201             :     {
     202           2 :         std::string str(".");
     203           1 :         CATCH_REQUIRE_FALSE(as2js::is_integer(str));
     204           1 :         CATCH_REQUIRE_FALSE(as2js::is_floating_point(str));
     205           1 :         CATCH_REQUIRE_FALSE(as2js::is_number(str));
     206           1 :         CATCH_REQUIRE(as2js::is_true(str));
     207           1 :     }
     208           9 :     CATCH_END_SECTION()
     209             : 
     210           9 :     CATCH_START_SECTION("string_number: no integral part means not a floating point")
     211             :     {
     212           2 :         std::string str("xyz");
     213           1 :         CATCH_REQUIRE_FALSE(as2js::is_integer(str));
     214           1 :         CATCH_REQUIRE_FALSE(as2js::is_floating_point(str));
     215           1 :         CATCH_REQUIRE_FALSE(as2js::is_number(str));
     216           1 :         CATCH_REQUIRE(as2js::is_true(str));
     217           1 :     }
     218           9 :     CATCH_END_SECTION()
     219             : 
     220           9 :     CATCH_START_SECTION("string_number: an exponent must be followed by a number")
     221             :     {
     222           2 :         std::string str("31.4159e");
     223           1 :         CATCH_REQUIRE_FALSE(as2js::is_integer(str));
     224           1 :         CATCH_REQUIRE_FALSE(as2js::is_floating_point(str));
     225           1 :         CATCH_REQUIRE_FALSE(as2js::is_number(str));
     226           1 :         CATCH_REQUIRE(as2js::is_true(str));
     227             : 
     228             :         // adding a sign is not enough
     229             :         //
     230           1 :         str += '+';
     231           1 :         CATCH_REQUIRE_FALSE(as2js::is_integer(str));
     232           1 :         CATCH_REQUIRE_FALSE(as2js::is_floating_point(str));
     233           1 :         CATCH_REQUIRE_FALSE(as2js::is_number(str));
     234           1 :         CATCH_REQUIRE(as2js::is_true(str));
     235             : 
     236           1 :         str[str.length() - 1] = '-';
     237           1 :         CATCH_REQUIRE_FALSE(as2js::is_integer(str));
     238           1 :         CATCH_REQUIRE_FALSE(as2js::is_floating_point(str));
     239           1 :         CATCH_REQUIRE_FALSE(as2js::is_number(str));
     240           1 :         CATCH_REQUIRE(as2js::is_true(str));
     241           1 :     }
     242           9 :     CATCH_END_SECTION()
     243             : 
     244           9 :     CATCH_START_SECTION("string_number: 0x and 0X are not hexadecimal numbers")
     245             :     {
     246             :         {
     247           2 :             std::string str("0x");
     248           1 :             CATCH_REQUIRE_FALSE(as2js::is_integer(str));
     249           1 :             CATCH_REQUIRE_FALSE(as2js::is_floating_point(str));
     250           1 :             CATCH_REQUIRE_FALSE(as2js::is_number(str));
     251           1 :             CATCH_REQUIRE_THROWS_MATCHES(
     252             :                       as2js::to_integer(str)
     253             :                     , as2js::internal_error
     254             :                     , Catch::Matchers::ExceptionMessage(
     255             :                               "internal_error: to_integer(std::string const & s) called with an invalid integer."));
     256           1 :             CATCH_REQUIRE(std::isnan(as2js::to_floating_point(str)));
     257           1 :             CATCH_REQUIRE(as2js::is_true(str));
     258           1 :         }
     259             : 
     260             :         {
     261           2 :             std::string str("0X");
     262           1 :             CATCH_REQUIRE_FALSE(as2js::is_integer(str));
     263           1 :             CATCH_REQUIRE_FALSE(as2js::is_floating_point(str));
     264           1 :             CATCH_REQUIRE_FALSE(as2js::is_number(str));
     265           1 :             CATCH_REQUIRE_THROWS_MATCHES(
     266             :                       as2js::to_integer(str)
     267             :                     , as2js::internal_error
     268             :                     , Catch::Matchers::ExceptionMessage(
     269             :                               "internal_error: to_integer(std::string const & s) called with an invalid integer."));
     270           1 :             CATCH_REQUIRE(std::isnan(as2js::to_floating_point(str)));
     271           1 :             CATCH_REQUIRE(as2js::is_true(str));
     272           1 :         }
     273             :     }
     274           9 :     CATCH_END_SECTION()
     275             : 
     276           9 :     CATCH_START_SECTION("string_number: integers -100,000 to +100,000")
     277             :     {
     278      200002 :         for(int64_t i(-100'000); i <= 100'000; ++i)
     279             :         {
     280             :             // decimal
     281             :             {
     282      200001 :                 std::stringstream ss;
     283      200001 :                 ss << (i >= 0 && (rand() & 1) ? "+" : "") << i;
     284      200001 :                 std::string str(ss.str());
     285      200001 :                 CATCH_REQUIRE(as2js::is_integer(str));
     286      200001 :                 CATCH_REQUIRE(as2js::is_floating_point(str));
     287      200001 :                 CATCH_REQUIRE(as2js::is_number(str));
     288      200001 :                 CATCH_REQUIRE(as2js::to_integer(str) == i);
     289             : #pragma GCC diagnostic push
     290             : #pragma GCC diagnostic ignored "-Wfloat-equal"
     291      200001 :                 bool const is_equal(as2js::to_floating_point(str) == static_cast<double>(i));
     292             : #pragma GCC diagnostic pop
     293      200001 :                 CATCH_REQUIRE(is_equal);
     294      200001 :                 CATCH_REQUIRE(as2js::is_true(str));
     295      200001 :             }
     296             : 
     297             :             // hexadecimal
     298             :             {
     299             :                 // not that in C/C++ hexadecimal numbers cannot really be
     300             :                 // negative; in JavaScript it's fine
     301             :                 //
     302      200001 :                 std::stringstream ss;
     303      200001 :                 ss << (i < 0 ? "-" : (rand() & 1 ? "+" : "")) << "0" << (rand() & 1 ? "x" : "X") << std::hex << labs(i);
     304      200001 :                 std::string const str(ss.str());
     305      200001 :                 CATCH_REQUIRE(as2js::is_integer(str));
     306      200001 :                 CATCH_REQUIRE_FALSE(as2js::is_floating_point(str));
     307      200001 :                 CATCH_REQUIRE(as2js::is_number(str));
     308      200001 :                 CATCH_REQUIRE(as2js::to_integer(str) == i);
     309      200001 :                 CATCH_REQUIRE(std::isnan(as2js::to_floating_point(str)));
     310      200001 :                 CATCH_REQUIRE(as2js::is_true(str));
     311      200001 :             }
     312             :         }
     313             :     }
     314           9 :     CATCH_END_SECTION()
     315             : 
     316           9 :     CATCH_START_SECTION("string_number: floating points")
     317             :     {
     318        3406 :         for(double i(-1000.00); i <= 1000.00; i += (rand() % 120) / 100.0)
     319             :         {
     320        3405 :             std::stringstream ss;
     321        3405 :             ss << i;
     322        6810 :             if(ss.str().find('e') != std::string::npos
     323        6810 :             || ss.str().find('E') != std::string::npos)
     324             :             {
     325             :                 // this happens with numbers very close to zero and the
     326             :                 // system decides to write them as '1e-12' for example
     327             :                 //
     328             :                 continue; // LCOV_EXCL_LINE -- does not matter if it does not happen
     329             :             }
     330        3405 :             std::string const str1(ss.str());
     331        3405 :             std::int64_t const integer1(lrint(i));
     332        3405 :             bool const is_integer1(std::find(str1.cbegin(), str1.cend(), '.') == str1.cend());
     333             : 
     334        3405 :             CATCH_REQUIRE(as2js::is_integer(str1) == is_integer1);
     335        3405 :             CATCH_REQUIRE(as2js::is_floating_point(str1));
     336        3405 :             CATCH_REQUIRE(as2js::is_number(str1));
     337        3405 :             CATCH_REQUIRE(as2js::is_true(str1));
     338        3405 :             if(is_integer1)
     339             :             {
     340          25 :                 CATCH_REQUIRE(as2js::to_integer(str1) == integer1);
     341             :             }
     342             :             else
     343             :             {
     344        3380 :                 CATCH_REQUIRE_THROWS_MATCHES(
     345             :                       as2js::to_integer(str1)
     346             :                     , as2js::internal_error
     347             :                     , Catch::Matchers::ExceptionMessage(
     348             :                               "internal_error: to_integer(std::string const & s) called with an invalid integer."));
     349             :             }
     350        3405 :             CATCH_REQUIRE(close_double(as2js::to_floating_point(str1), i, 0.01));
     351             : 
     352             :             // add x 1000 as an exponent
     353        3405 :             ss << "e" << ((rand() & 1) != 0 ? "+" : "") << "3";
     354        3405 :             std::string const str2(ss.str());
     355             :             // the 'e' "breaks" the integer test in JavaScript
     356        3405 :             CATCH_REQUIRE_FALSE(as2js::is_integer(str2));
     357        3405 :             CATCH_REQUIRE(as2js::is_floating_point(str2));
     358        3405 :             CATCH_REQUIRE(as2js::is_number(str2));
     359        3405 :             CATCH_REQUIRE(as2js::is_true(str2));
     360        3405 :             CATCH_REQUIRE_THROWS_MATCHES(
     361             :                   as2js::to_integer(str2)
     362             :                 , as2js::internal_error
     363             :                 , Catch::Matchers::ExceptionMessage(
     364             :                           "internal_error: to_integer(std::string const & s) called with an invalid integer."));
     365        3405 :             CATCH_REQUIRE(close_double(as2js::to_floating_point(str2), i * 1000.0, 0.01));
     366             : 
     367             :             // add / 1000 as an exponent
     368        3405 :             ss.str(""); // reset the string
     369        3405 :             ss << i << "e-3";
     370        3405 :             std::string const str3(ss.str());
     371             :             // the 'e' "breaks" the integer test in JavaScript
     372        3405 :             CATCH_REQUIRE_FALSE(as2js::is_integer(str3));
     373        3405 :             CATCH_REQUIRE(as2js::is_floating_point(str3));
     374        3405 :             CATCH_REQUIRE(as2js::is_number(str3));
     375        3405 :             CATCH_REQUIRE(as2js::is_true(str3));
     376        3405 :             CATCH_REQUIRE_THROWS_MATCHES(
     377             :                   as2js::to_integer(str3)
     378             :                 , as2js::internal_error
     379             :                 , Catch::Matchers::ExceptionMessage(
     380             :                           "internal_error: to_integer(std::string const & s) called with an invalid integer."));
     381        3405 :             CATCH_REQUIRE(close_double(as2js::to_floating_point(str3), i / 1000.0, 0.00001));
     382        3405 :         }
     383             :     }
     384           9 :     CATCH_END_SECTION()
     385             : 
     386           9 :     CATCH_START_SECTION("string_number: random 64 bits integers")
     387             :     {
     388             :         // a few more using random
     389      100001 :         for(int i(0); i < 100000; ++i)
     390             :         {
     391      100000 :             std::int64_t value(0);
     392      100000 :             SNAP_CATCH2_NAMESPACE::random(value);
     393      100000 :             std::stringstream ss;
     394      100000 :             ss << value;
     395      100000 :             std::string const str(ss.str());
     396      100000 :             CATCH_REQUIRE(as2js::is_integer(str));
     397      100000 :             CATCH_REQUIRE(as2js::is_floating_point(str));
     398      100000 :             CATCH_REQUIRE(as2js::is_number(str));
     399      100000 :             CATCH_REQUIRE(as2js::is_true(str));
     400      100000 :             CATCH_REQUIRE(as2js::to_integer(str) == value);
     401             : 
     402             :             // this is important since double mantissa is only 52 bits
     403             :             // and here our integral numbers are 64 bits
     404             :             //
     405      100000 :             as2js::floating_point const flt1(as2js::to_floating_point(str));
     406      100000 :             as2js::floating_point const flt2(static_cast<as2js::floating_point::value_type>(value));
     407      100000 :             CATCH_REQUIRE(flt1.nearly_equal(flt2, 0.0001));
     408      100000 :             CATCH_REQUIRE(flt2.nearly_equal(flt1, 0.0001));
     409      100000 :         }
     410             :     }
     411           9 :     CATCH_END_SECTION()
     412             : 
     413           9 :     CATCH_START_SECTION("string_number: NULL value")
     414             :     {
     415             :         // test a few non-hexadecimal numbers
     416             :         //
     417         101 :         for(int i(0); i < 100; ++i)
     418             :         {
     419             :             // get a character which is not a valid hex digit and not '\0'
     420             :             // and not 0x7F (Del)
     421             :             //
     422             :             char c;
     423             :             do
     424             :             {
     425         114 :                 c = static_cast<char>(rand() % 0x7D + 1);
     426             :             }
     427          61 :             while((c >= '0' && c <= '9')
     428         107 :                || (c >= 'a' && c <= 'f')
     429         217 :                || (c >= 'A' && c <= 'F'));
     430             : 
     431             :             // bad character is right at the beginning of the hex number
     432         100 :             std::stringstream ss1;
     433         100 :             ss1 << "0" << (rand() & 1 ? "x" : "X") << c << "123ABC";
     434         100 :             std::string str1(ss1.str());
     435         100 :             CATCH_REQUIRE_FALSE(as2js::is_integer(str1));
     436         100 :             CATCH_REQUIRE_FALSE(as2js::is_floating_point(str1));
     437         100 :             CATCH_REQUIRE_FALSE(as2js::is_number(str1));
     438         100 :             CATCH_REQUIRE(as2js::is_true(str1));
     439         100 :             CATCH_REQUIRE_THROWS_MATCHES(
     440             :                   as2js::to_integer(str1)
     441             :                 , as2js::internal_error
     442             :                 , Catch::Matchers::ExceptionMessage(
     443             :                           "internal_error: to_integer(std::string const & s) called with an invalid integer."));
     444         100 :             CATCH_REQUIRE(std::isnan(as2js::to_floating_point(str1)));
     445             : 
     446             :             // invalid character is in the middle of the hex number
     447             :             //
     448         100 :             std::stringstream ss2;
     449         100 :             ss2 << "0" << (rand() & 1 ? "x" : "X") << "123" << c << "ABC";
     450         100 :             std::string str2(ss2.str());
     451         100 :             CATCH_REQUIRE_FALSE(as2js::is_integer(str2));
     452         100 :             CATCH_REQUIRE_FALSE(as2js::is_floating_point(str2));
     453         100 :             CATCH_REQUIRE_FALSE(as2js::is_number(str2));
     454         100 :             CATCH_REQUIRE(as2js::is_true(str2));
     455         100 :             CATCH_REQUIRE_THROWS_MATCHES(
     456             :                   as2js::to_integer(str2)
     457             :                 , as2js::internal_error
     458             :                 , Catch::Matchers::ExceptionMessage(
     459             :                           "internal_error: to_integer(std::string const & s) called with an invalid integer."));
     460         100 :             CATCH_REQUIRE(std::isnan(as2js::to_floating_point(str2)));
     461             : 
     462             :             // invalid character is at the very end of the hex number
     463             :             //
     464         100 :             std::stringstream ss3;
     465         100 :             ss3 << "0" << (rand() & 1 ? "x" : "X") << "123ABC" << c;
     466         100 :             std::string str3(ss3.str());
     467         100 :             CATCH_REQUIRE_FALSE(as2js::is_integer(str3));
     468         100 :             CATCH_REQUIRE_FALSE(as2js::is_floating_point(str3));
     469         100 :             CATCH_REQUIRE_FALSE(as2js::is_number(str3));
     470         100 :             CATCH_REQUIRE(as2js::is_true(str3));
     471         100 :             CATCH_REQUIRE_THROWS_MATCHES(
     472             :                   as2js::to_integer(str3)
     473             :                 , as2js::internal_error
     474             :                 , Catch::Matchers::ExceptionMessage(
     475             :                           "internal_error: to_integer(std::string const & s) called with an invalid integer."));
     476         100 :             CATCH_REQUIRE(std::isnan(as2js::to_floating_point(str3)));
     477         100 :         }
     478             :     }
     479           9 :     CATCH_END_SECTION()
     480           9 : }
     481             : 
     482             : 
     483          17 : CATCH_TEST_CASE("string_simplify", "[string][type]")
     484             : {
     485          17 :     CATCH_START_SECTION("string_simplify: starting spaces")
     486             :     {
     487           2 :         std::string const str("    blah");
     488           1 :         std::string const simplified(as2js::simplify(str));
     489           1 :         CATCH_REQUIRE(simplified == "blah");
     490           1 :     }
     491          17 :     CATCH_END_SECTION()
     492             : 
     493          17 :     CATCH_START_SECTION("string_simplify: ending spaces")
     494             :     {
     495           2 :         std::string const str("blah    ");
     496           1 :         std::string const simplified(as2js::simplify(str));
     497           1 :         CATCH_REQUIRE(simplified == "blah");
     498           1 :     }
     499          17 :     CATCH_END_SECTION()
     500             : 
     501          17 :     CATCH_START_SECTION("string_simplify: starting & ending spaces")
     502             :     {
     503           2 :         std::string const str("    blah    ");
     504           1 :         std::string const simplified(as2js::simplify(str));
     505           1 :         CATCH_REQUIRE(simplified == "blah");
     506           1 :     }
     507          17 :     CATCH_END_SECTION()
     508             : 
     509          17 :     CATCH_START_SECTION("string_simplify: inside spaces")
     510             :     {
     511           2 :         std::string const str("blah    foo");
     512           1 :         std::string const simplified(as2js::simplify(str));
     513           1 :         CATCH_REQUIRE(simplified == "blah foo");
     514           1 :     }
     515          17 :     CATCH_END_SECTION()
     516             : 
     517          17 :     CATCH_START_SECTION("string_simplify: simplify starting, inside, and ending spaces")
     518             :     {
     519           2 :         std::string const str("    blah    foo    ");
     520           1 :         std::string const simplified(as2js::simplify(str));
     521           1 :         CATCH_REQUIRE(simplified == "blah foo");
     522           1 :     }
     523          17 :     CATCH_END_SECTION()
     524             : 
     525          17 :     CATCH_START_SECTION("string_simplify: simplify spaces including newlines")
     526             :     {
     527           2 :         std::string const str("blah  \n  foo");
     528           1 :         std::string const simplified(as2js::simplify(str));
     529           1 :         CATCH_REQUIRE(simplified == "blah foo");
     530           1 :     }
     531          17 :     CATCH_END_SECTION()
     532             : 
     533          17 :     CATCH_START_SECTION("string_simplify: empty string becomes zero")
     534             :     {
     535           1 :         std::string const str;
     536           1 :         std::string const simplified(as2js::simplify(str));
     537           1 :         CATCH_REQUIRE(simplified == "0");
     538           1 :     }
     539          17 :     CATCH_END_SECTION()
     540             : 
     541          17 :     CATCH_START_SECTION("string_simplify: spaces only string becomes zero")
     542             :     {
     543           2 :         std::string const str("     ");
     544           1 :         std::string const simplified(as2js::simplify(str));
     545           1 :         CATCH_REQUIRE(simplified == "0");
     546           1 :     }
     547          17 :     CATCH_END_SECTION()
     548             : 
     549          17 :     CATCH_START_SECTION("string_simplify: simplify number with spaces around")
     550             :     {
     551           2 :         std::string const str("  3.14159  ");
     552           1 :         std::string const simplified(as2js::simplify(str));
     553           1 :         CATCH_REQUIRE(simplified == "3.14159");
     554           1 :         CATCH_REQUIRE_FALSE(as2js::is_integer(simplified));
     555           1 :         CATCH_REQUIRE(as2js::is_floating_point(simplified));
     556           1 :         CATCH_REQUIRE(as2js::is_number(simplified));
     557           1 :         CATCH_REQUIRE(as2js::floating_point(as2js::to_floating_point(simplified)).nearly_equal(3.14159, 1.0e-8));
     558           1 :     }
     559          17 :     CATCH_END_SECTION()
     560             : 
     561          17 :     CATCH_START_SECTION("string_simplify: simplify number with left over")
     562             :     {
     563           2 :         std::string const str("  3.14159 ignore that part  ");
     564           1 :         std::string const simplified(as2js::simplify(str));
     565           1 :         CATCH_REQUIRE(simplified == "3.14159");
     566           1 :         CATCH_REQUIRE_FALSE(as2js::is_integer(simplified));
     567           1 :         CATCH_REQUIRE(as2js::is_floating_point(simplified));
     568           1 :         CATCH_REQUIRE(as2js::is_number(simplified));
     569           1 :         CATCH_REQUIRE(as2js::floating_point(as2js::to_floating_point(simplified)).nearly_equal(3.14159, 1.0e-8));
     570           1 :     }
     571          17 :     CATCH_END_SECTION()
     572             : 
     573          17 :     CATCH_START_SECTION("string_simplify: simplify positive number with left over")
     574             :     {
     575           2 :         std::string const str("  +3.14159 ignore that part  ");
     576           1 :         std::string const simplified(as2js::simplify(str));
     577           1 :         CATCH_REQUIRE(simplified == "+3.14159");
     578           1 :         CATCH_REQUIRE(as2js::is_floating_point(simplified));
     579           1 :         CATCH_REQUIRE(as2js::is_number(simplified));
     580           1 :         CATCH_REQUIRE(as2js::floating_point(as2js::to_floating_point(simplified)).nearly_equal(3.14159, 1.0e-8));
     581           1 :     }
     582          17 :     CATCH_END_SECTION()
     583             : 
     584          17 :     CATCH_START_SECTION("string_simplify: simplify negative integer with left over")
     585             :     {
     586           2 :         std::string const str("  -314159 ignore that part  ");
     587           1 :         std::string const simplified(as2js::simplify(str));
     588           1 :         CATCH_REQUIRE(simplified == "-314159");
     589           1 :         CATCH_REQUIRE(as2js::is_integer(simplified));
     590           1 :         CATCH_REQUIRE(as2js::to_integer(simplified) == -314159);
     591           1 :         CATCH_REQUIRE(as2js::is_floating_point(simplified));
     592           1 :         CATCH_REQUIRE(as2js::is_number(simplified));
     593           1 :         CATCH_REQUIRE(as2js::floating_point(as2js::to_floating_point(simplified)).nearly_equal(-314159.0, 1.0e-8));
     594           1 :     }
     595          17 :     CATCH_END_SECTION()
     596             : 
     597          17 :     CATCH_START_SECTION("string_simplify: simplify the positive number with exponent and left over")
     598             :     {
     599           2 :         std::string const str("  +0.00314159e3 ignore that part  ");
     600           1 :         std::string const simplified(as2js::simplify(str));
     601           1 :         CATCH_REQUIRE(simplified == "+0.00314159e3");
     602           1 :         CATCH_REQUIRE(as2js::is_floating_point(simplified));
     603           1 :         CATCH_REQUIRE(as2js::is_number(simplified));
     604           1 :         CATCH_REQUIRE(as2js::floating_point(as2js::to_floating_point(simplified)).nearly_equal(3.14159, 1e-8));
     605           1 :     }
     606          17 :     CATCH_END_SECTION()
     607             : 
     608          17 :     CATCH_START_SECTION("string_simplify: simplify the positive number with positive exponent and left over")
     609             :     {
     610           2 :         std::string const str("  +0.00314159e+3 ignore that part  ");
     611           1 :         std::string const simplified(as2js::simplify(str));
     612           1 :         CATCH_REQUIRE(simplified == "+0.00314159e+3");
     613           1 :         CATCH_REQUIRE(as2js::is_floating_point(simplified));
     614           1 :         CATCH_REQUIRE(as2js::is_number(simplified));
     615           1 :         CATCH_REQUIRE(as2js::floating_point(as2js::to_floating_point(simplified)).nearly_equal(3.14159, 1e-8));
     616           1 :     }
     617          17 :     CATCH_END_SECTION()
     618             : 
     619          17 :     CATCH_START_SECTION("string_simplify: simplify the negative number with negative exponent and left over")
     620             :     {
     621           2 :         std::string const str("  -314159e-5 ignore that part  ");
     622           1 :         std::string const simplified(as2js::simplify(str));
     623           1 :         CATCH_REQUIRE(simplified == "-314159");
     624           1 :         CATCH_REQUIRE(as2js::is_integer(simplified));
     625           1 :         CATCH_REQUIRE(as2js::to_integer(simplified) == -314159);
     626           1 :         CATCH_REQUIRE(as2js::is_floating_point(simplified));
     627           1 :         CATCH_REQUIRE(as2js::is_number(simplified));
     628           1 :         CATCH_REQUIRE(as2js::floating_point(as2js::to_floating_point(simplified)).nearly_equal(-314159, 1e-8));
     629           1 :     }
     630          17 :     CATCH_END_SECTION()
     631             : 
     632          17 :     CATCH_START_SECTION("string_simplify: simplify negative number with negative exponent and left over")
     633             :     {
     634           2 :         std::string str("  -314159.e-5 ignore that part  ");
     635           1 :         std::string simplified(as2js::simplify(str));
     636           1 :         CATCH_REQUIRE(simplified == "-314159.e-5");
     637           1 :         CATCH_REQUIRE(as2js::is_floating_point(simplified));
     638           1 :         CATCH_REQUIRE(as2js::is_number(simplified));
     639           1 :         CATCH_REQUIRE(as2js::floating_point(as2js::to_floating_point(simplified)).nearly_equal(-3.14159, 1e-8));
     640           1 :     }
     641          17 :     CATCH_END_SECTION()
     642             : 
     643          17 :     CATCH_START_SECTION("string_simplify: simplify negative number with large negative exponent and left over")
     644             :     {
     645           2 :         std::string str("  -314159.0e-105ignorethatpart");
     646           1 :         std::string simplified(as2js::simplify(str));
     647           1 :         CATCH_REQUIRE(simplified == "-314159.0e-105");
     648           1 :         CATCH_REQUIRE(as2js::is_floating_point(simplified));
     649           1 :         CATCH_REQUIRE(as2js::is_number(simplified));
     650           1 :         CATCH_REQUIRE(as2js::floating_point(as2js::to_floating_point(simplified)).nearly_equal(-3.14159e-100, 1e-8));
     651           1 :     }
     652          17 :     CATCH_END_SECTION()
     653          17 : }
     654             : 
     655             : 
     656             : 
     657             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.14