LCOV - code coverage report
Current view: top level - tests - catch_binary.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 301 372 80.9 %
Date: 2023-12-10 17:25:12 Functions: 12 12 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/binary.h>
      22             : 
      23             : 
      24             : 
      25             : // self
      26             : //
      27             : #include    "catch_main.h"
      28             : 
      29             : 
      30             : // snapdev
      31             : //
      32             : #include    <snapdev/file_contents.h>
      33             : #include    <snapdev/glob_to_list.h>
      34             : #include    <snapdev/pathinfo.h>
      35             : #include    <snapdev/to_lower.h>
      36             : 
      37             : 
      38             : // C++
      39             : //
      40             : #include    <iomanip>
      41             : 
      42             : 
      43             : // C
      44             : //
      45             : #include    <math.h>
      46             : 
      47             : 
      48             : // last include
      49             : //
      50             : #include    <snapdev/poison.h>
      51             : 
      52             : 
      53             : 
      54             : namespace
      55             : {
      56             : 
      57             : 
      58             : 
      59          33 : void run_script(std::string const & s)
      60             : {
      61          66 :     std::string cmd("export AS2JS_RC='");
      62          33 :     cmd += SNAP_CATCH2_NAMESPACE::g_binary_dir();
      63          33 :     cmd += "' && ";
      64             : //cmd += "gdb -ex \"catch throws\" -ex \"run\" -args ";
      65          33 :     cmd += SNAP_CATCH2_NAMESPACE::g_binary_dir();
      66          33 :     cmd += "/tools/as2js -b -o ";
      67          33 :     cmd += SNAP_CATCH2_NAMESPACE::g_binary_dir();
      68          33 :     cmd += "/tests/a.out ";
      69          33 :     cmd += s;
      70             : 
      71             :     // for the script to work, the compiler must find the scripts directory
      72             :     // which is defined in the rc file
      73             :     //
      74             :     {
      75          33 :         std::ofstream rc("as2js/as2js.rc");
      76             :         rc << "{\"scripts\":\""
      77          33 :            << SNAP_CATCH2_NAMESPACE::g_source_dir()
      78          33 :            << "/scripts\"}\n";
      79          33 :     }
      80             : 
      81             :     // first compile the file
      82             :     //
      83             :     std::cout
      84             :         << "--- compile script to binary with command \""
      85             :         << cmd
      86          33 :         << "\".\n";
      87          33 :     int const r(system(cmd.c_str()));
      88          33 : std::cerr << "-------------- system() called returned from binary test (" << r << ")\n";
      89          33 :     CATCH_REQUIRE(r == 0);
      90          66 : }
      91             : 
      92             : 
      93             : 
      94             : enum class value_type_t : std::uint16_t
      95             : {
      96             :     VALUE_TYPE_UNDEFINED,
      97             :     VALUE_TYPE_BOOLEAN,
      98             :     VALUE_TYPE_INTEGER,
      99             :     VALUE_TYPE_FLOATING_POINT,
     100             :     VALUE_TYPE_STRING,
     101             : };
     102             : 
     103             : typedef std::uint16_t           flags_t;
     104             : 
     105             : constexpr flags_t const         VALUE_FLAG_IN  = 0x0000;
     106             : constexpr flags_t const         VALUE_FLAG_OUT = 0x0001;
     107             : 
     108             : struct value_flags
     109             : {
     110             :     std::string     f_value = std::string();
     111             :     value_type_t    f_type = value_type_t::VALUE_TYPE_UNDEFINED;
     112             :     flags_t         f_flags = 0;
     113             : 
     114         732 :     void set_type(value_type_t t)
     115             :     {
     116         732 :         CATCH_REQUIRE(f_type == value_type_t::VALUE_TYPE_UNDEFINED); // trying to set the type more than once?
     117         732 :         f_type = t;
     118         732 :     }
     119             : 
     120        1437 :     void set_type(std::string t)
     121             :     {
     122        1437 :         t = snapdev::to_lower(t);
     123        1437 :         if(t == "boolean")
     124             :         {
     125         222 :             set_type(value_type_t::VALUE_TYPE_BOOLEAN);
     126             :         }
     127        1215 :         else if(t == "integer")
     128             :         {
     129          23 :             set_type(value_type_t::VALUE_TYPE_INTEGER);
     130             :         }
     131        1192 :         else if(t == "double")
     132             :         {
     133         289 :             set_type(value_type_t::VALUE_TYPE_FLOATING_POINT);
     134             :         }
     135         903 :         else if(t == "string")
     136             :         {
     137          93 :             set_type(value_type_t::VALUE_TYPE_STRING);
     138             :         }
     139         810 :         else if(t == "in")
     140             :         {
     141           0 :             f_flags |= VALUE_FLAG_IN;
     142             :         }
     143         810 :         else if(t == "out")
     144             :         {
     145         810 :             f_flags |= VALUE_FLAG_OUT;
     146             :         }
     147             :         else
     148             :         {
     149           0 :             CATCH_REQUIRE(t == "");
     150             :         }
     151        1437 :     }
     152             : 
     153        2095 :     value_type_t get_type() const
     154             :     {
     155        2095 :         return f_type == value_type_t::VALUE_TYPE_UNDEFINED
     156        2095 :                     ? value_type_t::VALUE_TYPE_INTEGER
     157        2095 :                     : f_type;
     158             :     }
     159             : 
     160        2746 :     bool is_out() const
     161             :     {
     162        2746 :         return (f_flags & VALUE_FLAG_OUT) != 0;
     163             :     }
     164             : };
     165             : 
     166             : 
     167             : typedef std::map<std::string, value_flags>      variable_t;
     168             : 
     169             : struct meta
     170             : {
     171             :     variable_t      f_variables = variable_t();
     172             :     value_flags     f_result = value_flags();
     173             : };
     174             : 
     175             : 
     176          33 : meta load_script_meta(std::string const & s)
     177             : {
     178          33 :     meta result;
     179             : 
     180         165 :     std::string const filename(snapdev::pathinfo::replace_suffix(s, ".ajs", ".meta"));
     181             : 
     182          33 :     snapdev::file_contents meta(filename);
     183          33 :     CATCH_REQUIRE(meta.read_all());
     184             : 
     185          33 :     std::string const & str(meta.contents());
     186             : 
     187          33 :     char const * m(str.c_str());
     188        2316 :     while(*m != '\0')
     189             :     {
     190        2283 :         while(*m == ' ' || *m == '\t')
     191             :         {
     192           0 :             ++m;
     193             :         }
     194        2283 :         if(*m == '\0')
     195             :         {
     196           0 :             return result;
     197             :         }
     198        2283 :         if(*m == '#')
     199             :         {
     200             :             // skip comments
     201             :             //
     202        1061 :             while(*m != '\n')
     203             :             {
     204         978 :                 if(*m == '\0')
     205             :                 {
     206           0 :                     return result;
     207             :                 }
     208         978 :                 ++m;
     209             :             }
     210          83 :             continue;
     211             :         }
     212             : 
     213        2200 :         if(*m == '\n')
     214             :         {
     215             :             // empty line
     216             :             //
     217        1251 :             ++m;
     218        1251 :             continue;
     219             :         }
     220             : 
     221             :         // we have either a variable or a result preceeded by keywords:
     222             :         //
     223             :         //   [<keyword>] (<result>)
     224             :         //   [<keyword>] <name>=<value>
     225             :         //
     226         949 :         std::string name;
     227         949 :         value_flags value;
     228       19492 :         while(*m != '=' && *m != '(')
     229             :         {
     230       18543 :             CATCH_REQUIRE(*m != '\n');
     231       18543 :             CATCH_REQUIRE(*m != '\0');
     232       18543 :             if(isspace(*m))
     233             :             {
     234             :                 // skip all spaces
     235             :                 //
     236             :                 do
     237             :                 {
     238        1437 :                     ++m;
     239             :                 }
     240        1437 :                 while(*m == ' ' || *m == '\t');
     241             : 
     242             :                 // check whether it is the last word before the '=', if so,
     243             :                 // it is taken as the variable name and not a <keyword>
     244             :                 //
     245        1437 :                 if(*m == '=')
     246             :                 {
     247           0 :                     break;
     248             :                 }
     249             : 
     250             :                 // parse as a type or flag
     251             :                 //
     252        1437 :                 value.set_type(name);
     253        1437 :                 name.clear();
     254             :             }
     255             :             else
     256             :             {
     257       17106 :                 name += *m;
     258       17106 :                 ++m;
     259             :             }
     260             :         }
     261             : 
     262         949 :         if(*m == '(')
     263             :         {
     264          33 :             CATCH_REQUIRE(name.empty());
     265          33 :             result.f_result = value;
     266             : 
     267             :             // expected result
     268             :             //   (<value>)
     269             :             //
     270          33 :             ++m;
     271          33 :             CATCH_REQUIRE(result.f_result.f_value.empty()); // prevent double definition
     272         434 :             while(*m != ')')
     273             :             {
     274         401 :                 CATCH_REQUIRE(*m != '\n');
     275         401 :                 CATCH_REQUIRE(*m != '\0');
     276         401 :                 result.f_result.f_value += *m;
     277         401 :                 ++m;
     278             :             }
     279          33 :             ++m;
     280             : 
     281          33 :             if(result.f_result.f_value.length() >= 2
     282          33 :             && (result.f_result.f_value[0] == '"' || result.f_result.f_value[0] == '\'')
     283          11 :             && result.f_result.f_value[0] == result.f_result.f_value.back()
     284          66 :             && result.f_result.get_type() == value_type_t::VALUE_TYPE_INTEGER)
     285             :             {
     286             :                 // default to INTEGER, unless value is surrounded by quotes
     287             :                 //
     288           1 :                 result.f_result.set_type(value_type_t::VALUE_TYPE_STRING);
     289             :             }
     290             : 
     291          33 :             if(result.f_result.get_type() == value_type_t::VALUE_TYPE_STRING
     292          11 :             && result.f_result.f_value.length() >= 2
     293          11 :             && (result.f_result.f_value[0] == '"' || result.f_result.f_value[0] == '\'')
     294          44 :             && result.f_result.f_value[0] == result.f_result.f_value.back())
     295             :             {
     296             :                 // remove quotes around string
     297             :                 //
     298          11 :                 result.f_result.f_value = result.f_result.f_value.substr(1, result.f_result.f_value.length() - 2);
     299             :             }
     300             : 
     301          33 :             while(*m == ' ' || *m == '\t')
     302             :             {
     303             : //std::cerr << "--- result [" << result.f_result << "] -> skipping [" << static_cast<int>(*m) << "]\n";
     304           0 :                 ++m;
     305             :             }
     306          33 :             if(*m != '\n')
     307             :             {
     308           0 :                 CATCH_REQUIRE(*m == '\0');
     309           0 :                 return result;
     310             :             }
     311          33 :             ++m;
     312          33 :             continue;
     313          33 :         }
     314         916 :         ++m;    // skip '='
     315             : 
     316         916 :         CATCH_REQUIRE_FALSE(name.empty());
     317             : 
     318        8420 :         while(*m != '\n' && *m != '\0')
     319             :         {
     320        7504 :             value.f_value += *m;
     321        7504 :             ++m;
     322             :         }
     323             : 
     324             :         // TODO: add support for spaces/tabs after the closing quotation
     325             :         //
     326         916 :         if(value.f_value.length() >= 2
     327         843 :         && (value.f_value[0] == '"' || value.f_value[0] == '\'')
     328         187 :         && value.f_value[0] == value.f_value.back()
     329        1759 :         && value.get_type() == value_type_t::VALUE_TYPE_INTEGER)
     330             :         {
     331             :             // default to INTEGER, unless value is surrounded by quotes
     332             :             //
     333         104 :             value.set_type(value_type_t::VALUE_TYPE_STRING);
     334             :         }
     335             : 
     336         916 :         if(value.get_type() == value_type_t::VALUE_TYPE_STRING
     337         187 :         && value.f_value.length() >= 2
     338         187 :         && (value.f_value[0] == '"' || value.f_value[0] == '\'')
     339        1103 :         && value.f_value[0] == value.f_value.back())
     340             :         {
     341             :             // remove quotes around string
     342             :             //
     343         187 :             value.f_value = value.f_value.substr(1, value.f_value.length() - 2);
     344             :         }
     345             : 
     346             :         // when defining an "out" the name must be distinct otherwise it would
     347             :         // smash the "in"
     348             :         //
     349         916 :         if(value.is_out())
     350             :         {
     351         810 :             name = "<-" + name;
     352             :         }
     353             : //std::cerr << "--- found name [" << name << "]\n";
     354         916 :         result.f_variables[name] = value;
     355         982 :     }
     356             : 
     357          33 :     return result;
     358          33 : }
     359             : 
     360             : 
     361          33 : void execute(meta const & m)
     362             : {
     363          33 :     std::string filename(SNAP_CATCH2_NAMESPACE::g_binary_dir());
     364          33 :     filename += "/tests/a.out";
     365             : 
     366          33 :     as2js::running_file script;
     367          33 :     CATCH_REQUIRE(script.load(filename));
     368             : 
     369         948 :     for(auto const & var : m.f_variables)
     370             :     {
     371         915 :         if(!var.second.is_out())
     372             :         {
     373             :             // TODO: support all types of variables
     374             :             //
     375         106 :             switch(var.second.get_type())
     376             :             {
     377          11 :             case value_type_t::VALUE_TYPE_BOOLEAN:
     378             :                 {
     379          11 :                     bool value(false);
     380          11 :                     if(var.second.f_value == "true")
     381             :                     {
     382           7 :                         value = true;
     383             :                     }
     384             :                     else
     385             :                     {
     386             :                         // value must be "true" or "false"
     387             :                         //
     388           4 :                         CATCH_REQUIRE(var.second.f_value == "false");
     389             :                     }
     390          11 :                     script.set_variable(var.first, value);
     391             :                 }
     392          11 :                 break;
     393             : 
     394          37 :             case value_type_t::VALUE_TYPE_INTEGER:
     395             :                 {
     396          37 :                     std::int64_t const value(std::stoll(var.second.f_value, nullptr, 0));
     397          37 :                     script.set_variable(var.first, value);
     398             :                 }
     399          37 :                 break;
     400             : 
     401          29 :             case value_type_t::VALUE_TYPE_FLOATING_POINT:
     402             :                 {
     403          29 :                     double value(0.0);
     404          29 :                     if(m.f_result.f_value == "MIN_VALUE")
     405             :                     {
     406           0 :                         value = std::numeric_limits<double>::min();
     407             :                     }
     408          29 :                     else if(m.f_result.f_value == "MAX_VALUE")
     409             :                     {
     410           0 :                         value = std::numeric_limits<double>::max();
     411             :                     }
     412          29 :                     else if(var.second.f_value == "POSITIVE_INFINITY")
     413             :                     {
     414           0 :                         value = std::numeric_limits<double>::infinity();
     415             :                     }
     416          29 :                     else if(var.second.f_value == "NEGATIVE_INFINITY")
     417             :                     {
     418           0 :                         value = -std::numeric_limits<double>::infinity();
     419             :                     }
     420          29 :                     else if(var.second.f_value == "EPSILON")
     421             :                     {
     422           0 :                         value = 2.220446049250313e-16;
     423             :                     }
     424             :                     else
     425             :                     {
     426          29 :                         value = std::stod(var.second.f_value, nullptr);
     427             :                     }
     428          29 :                     script.set_variable(var.first, value);
     429             :                 }
     430          29 :                 break;
     431             : 
     432          29 :             case value_type_t::VALUE_TYPE_STRING:
     433          29 :                 script.set_variable(var.first, var.second.f_value);
     434          29 :                 break;
     435             : 
     436             :             //case value_type_t::VALUE_TYPE_UNDEFINED:
     437           0 :             default:
     438           0 :                 CATCH_REQUIRE(!"variable type not yet implemented or somehow set to UNDEFINED.");
     439           0 :                 break;
     440             : 
     441             :             }
     442             :         }
     443             :     }
     444             : 
     445          66 :     as2js::binary_result result;
     446             : 
     447          33 :     script.run(result);
     448             : 
     449          33 :     switch(m.f_result.get_type())
     450             :     {
     451           6 :     case value_type_t::VALUE_TYPE_BOOLEAN:
     452             :         {
     453           6 :             bool expected_result(false);
     454           6 :             if(m.f_result.f_value == "true")
     455             :             {
     456           0 :                 expected_result = true;
     457             :             }
     458             :             else
     459             :             {
     460             :                 // value must be "true" or "false"
     461             :                 //
     462           6 :                 CATCH_REQUIRE(m.f_result.f_value == "false");
     463             :             }
     464           6 :             CATCH_REQUIRE(result.get_boolean() == expected_result);
     465             :         }
     466           6 :         break;
     467             : 
     468           8 :     case value_type_t::VALUE_TYPE_INTEGER:
     469             :         {
     470           8 :             std::int64_t const expected_result(std::stoll(m.f_result.f_value, nullptr, 0));
     471           8 :             if(result.get_integer() != expected_result)
     472             :             {
     473           0 :                 std::cerr << "--- (integer result) differs: " << result.get_integer() << " != " << expected_result << "\n";
     474             :             }
     475           8 :             CATCH_REQUIRE(result.get_integer() == expected_result);
     476             :         }
     477           8 :         break;
     478             : 
     479           8 :     case value_type_t::VALUE_TYPE_FLOATING_POINT:
     480             :         {
     481           8 :             double expected_result(0.0);
     482           8 :             if(m.f_result.f_value == "MIN_VALUE")
     483             :             {
     484           0 :                 expected_result = std::numeric_limits<double>::min();
     485             :             }
     486           8 :             else if(m.f_result.f_value == "MAX_VALUE")
     487             :             {
     488           0 :                 expected_result = std::numeric_limits<double>::max();
     489             :             }
     490           8 :             else if(m.f_result.f_value == "POSITIVE_INFINITY")
     491             :             {
     492           0 :                 expected_result = std::numeric_limits<double>::infinity();
     493             :             }
     494           8 :             else if(m.f_result.f_value == "NEGATIVE_INFINITY")
     495             :             {
     496           0 :                 expected_result = -std::numeric_limits<double>::infinity();
     497             :             }
     498           8 :             else if(m.f_result.f_value == "EPSILON")
     499             :             {
     500           0 :                 expected_result = 2.220446049250313e-16;
     501             :             }
     502             :             else
     503             :             {
     504           8 :                 expected_result = std::stod(m.f_result.f_value, nullptr);
     505             :             }
     506           8 :             double const final_result(result.get_floating_point());
     507           8 :             if(!SNAP_CATCH2_NAMESPACE::nearly_equal(final_result, expected_result))
     508             :             {
     509           0 :                 double const * result_ptr(&final_result);
     510           0 :                 double const * expected_ptr(&expected_result);
     511             :                 std::cerr
     512           0 :                     << "--- (double result) differs: "
     513           0 :                     << final_result
     514           0 :                     << " != "
     515           0 :                     << expected_result
     516             :                     << " (0x"
     517           0 :                     << std::setw(16) << std::setfill('0') << std::hex
     518           0 :                     << *reinterpret_cast<std::uint64_t const *>(result_ptr)
     519             :                     << " != 0x"
     520           0 :                     << std::setw(16)
     521           0 :                     << *reinterpret_cast<std::uint64_t const *>(expected_ptr)
     522           0 :                     << std::dec
     523           0 :                     << ")\n";
     524             :             }
     525           8 :             CATCH_REQUIRE(SNAP_CATCH2_NAMESPACE::nearly_equal(final_result, expected_result));
     526             :         }
     527             :         break;
     528             : 
     529          11 :     case value_type_t::VALUE_TYPE_STRING:
     530             :         {
     531          11 :             std::string const expected_result(m.f_result.f_value);
     532          11 :             if(result.get_string() != expected_result)
     533             :             {
     534           0 :                 std::cerr << "--- (string result) differs: " << result.get_string() << " != " << expected_result << "\n";
     535             :             }
     536          11 :             CATCH_REQUIRE(result.get_string() == expected_result);
     537          11 :         }
     538             :         break;
     539             : 
     540             :     //case value_type_t::VALUE_TYPE_UNDEFINED:
     541           0 :     default:
     542           0 :         CATCH_REQUIRE(!"variable type not yet implemented or somehow set to UNDEFINED.");
     543           0 :         break;
     544             : 
     545             :     }
     546             : 
     547         948 :     for(auto const & var : m.f_variables)
     548             :     {
     549         915 :         if(var.second.is_out())
     550             :         {
     551             :             // TODO: support all types of variables
     552             :             //
     553         809 :             std::string const name(var.first.substr(2));
     554         809 :             switch(var.second.get_type())
     555             :             {
     556         204 :             case value_type_t::VALUE_TYPE_BOOLEAN:
     557             :                 {
     558         204 :                     bool expected_value(false);
     559         204 :                     if(var.second.f_value == "true")
     560             :                     {
     561         101 :                         expected_value = true;
     562             :                     }
     563             :                     else
     564             :                     {
     565             :                         // value must be "true" or "false"
     566             :                         //
     567         103 :                         CATCH_REQUIRE(var.second.f_value == "false");
     568             :                     }
     569         204 :                     bool returned_value(0);
     570         204 :                     script.get_variable(name, returned_value);
     571         204 :                     if(returned_value != expected_value)
     572             :                     {
     573             :                         std::cerr
     574             :                             << "--- invalid boolean result in \""
     575           0 :                             << var.first
     576           0 :                             << "\".\n";
     577             :                     }
     578         204 :                     CATCH_REQUIRE(returned_value == expected_value);
     579             :                 }
     580             :                 break;
     581             : 
     582         195 :             case value_type_t::VALUE_TYPE_INTEGER:
     583             :                 {
     584         195 :                     std::int64_t const expected_value(std::stoll(var.second.f_value, nullptr, 0));
     585         195 :                     std::int64_t returned_value(0);
     586         195 :                     script.get_variable(name, returned_value);
     587         195 :                     if(returned_value != expected_value)
     588             :                     {
     589             :                         std::cerr
     590             :                             << "--- invalid integer result in \""
     591           0 :                             << var.first
     592           0 :                             << "\".\n";
     593             :                     }
     594         195 :                     CATCH_REQUIRE(returned_value == expected_value);
     595             :                 }
     596             :                 break;
     597             : 
     598         252 :             case value_type_t::VALUE_TYPE_FLOATING_POINT:
     599             :                 {
     600         252 :                     double returned_value(0.0);
     601         252 :                     script.get_variable(name, returned_value);
     602         252 :                     if(var.second.f_value == "NaN")
     603             :                     {
     604          16 :                         CATCH_REQUIRE(std::isnan(returned_value));
     605             :                     }
     606         236 :                     else if(var.second.f_value == "+NaN")
     607             :                     {
     608           3 :                         bool const positive_nan(std::isnan(returned_value) && signbit(returned_value) == 0);
     609           3 :                         CATCH_REQUIRE(positive_nan);
     610             :                     }
     611         233 :                     else if(var.second.f_value == "-NaN")
     612             :                     {
     613           5 :                         bool const negative_nan(std::isnan(returned_value) && signbit(returned_value) == 1);
     614           5 :                         CATCH_REQUIRE(negative_nan);
     615             :                     }
     616             :                     else
     617             :                     {
     618         228 :                         double epsilon(0.0000000000000033);
     619         228 :                         double expected_result(0.0);
     620         228 :                         if(var.second.f_value == "MIN_VALUE")
     621             :                         {
     622           2 :                             epsilon = 0.0;
     623           2 :                             expected_result = std::numeric_limits<double>::min();
     624             :                         }
     625         226 :                         else if(var.second.f_value == "MAX_VALUE")
     626             :                         {
     627           2 :                             epsilon = 0.0;
     628           2 :                             expected_result = std::numeric_limits<double>::max();
     629             :                         }
     630         224 :                         else if(var.second.f_value == "POSITIVE_INFINITY")
     631             :                         {
     632           9 :                             epsilon = 0.0;
     633           9 :                             expected_result = std::numeric_limits<double>::infinity();
     634             :                         }
     635         215 :                         else if(var.second.f_value == "NEGATIVE_INFINITY")
     636             :                         {
     637           5 :                             epsilon = 0.0;
     638           5 :                             expected_result = -std::numeric_limits<double>::infinity();
     639             :                         }
     640         210 :                         else if(var.second.f_value == "EPSILON")
     641             :                         {
     642           2 :                             epsilon = 0.0;
     643           2 :                             expected_result = 2.220446049250313e-16;
     644             :                         }
     645             :                         else
     646             :                         {
     647             :                             try
     648             :                             {
     649         208 :                                 expected_result = std::stod(var.second.f_value, nullptr);
     650             :                             }
     651           0 :                             catch(...)
     652             :                             {
     653             :                                 std::cerr << "error: could not convert \""
     654           0 :                                     << var.second.f_value
     655           0 :                                     << "\" to a floating point number.\n";
     656           0 :                                 throw;
     657           0 :                             }
     658             :                         }
     659         228 :                         if(!SNAP_CATCH2_NAMESPACE::nearly_equal(returned_value, expected_result, epsilon))
     660             :                         {
     661           0 :                             double const * value_ptr(&returned_value);
     662           0 :                             double const * expected_ptr(&expected_result);
     663             :                             std::cerr
     664             :                                 << "--- invalid floating point result in \""
     665           0 :                                 << var.first
     666             :                                 << "\" -- "
     667           0 :                                 << std::setprecision(20)
     668           0 :                                 << returned_value
     669           0 :                                 << " != "
     670           0 :                                 << expected_result
     671             :                                 << " (0x"
     672           0 :                                 << std::setw(16) << std::setfill('0') << std::hex
     673           0 :                                 << *reinterpret_cast<std::uint64_t const *>(value_ptr)
     674             :                                 << " != 0x"
     675           0 :                                 << std::setw(16)
     676           0 :                                 << *reinterpret_cast<std::uint64_t const *>(expected_ptr)
     677           0 :                                 << std::dec
     678           0 :                                 << ")\n";
     679             :                         }
     680         228 :                         CATCH_REQUIRE(SNAP_CATCH2_NAMESPACE::nearly_equal(returned_value, expected_result, epsilon));
     681             :                     }
     682             :                 }
     683             :                 break;
     684             : 
     685         158 :             case value_type_t::VALUE_TYPE_STRING:
     686             :                 {
     687         158 :                     std::string const expected_value(var.second.f_value);
     688         158 :                     std::string returned_value;
     689         158 :                     script.get_variable(name, returned_value);
     690         158 :                     if(returned_value != expected_value)
     691             :                     {
     692             :                         std::cerr
     693             :                             << "--- invalid string result in \""
     694           0 :                             << var.first
     695           0 :                             << "\".\n";
     696             :                     }
     697         158 :                     CATCH_REQUIRE(returned_value == expected_value);
     698         158 :                 }
     699             :                 break;
     700             : 
     701             :             //case value_type_t::VALUE_TYPE_UNDEFINED,
     702           0 :             default:
     703             :                 std::cerr
     704           0 :                     << "variable type "
     705           0 :                     << static_cast<int>(var.second.get_type())
     706             :                     << " not yet implemented in catch_binary.cpp ("
     707             :                     << __FILE__
     708           0 :                     << ':'
     709             :                     << __LINE__
     710           0 :                     << ")\n";
     711           0 :                 CATCH_REQUIRE(!"variable type not yet implemented or somehow set to UNDEFINED.");
     712           0 :                 break;
     713             : 
     714             :             }
     715         809 :         }
     716             :     }
     717          66 : }
     718             : 
     719             : 
     720             : 
     721             : }
     722             : 
     723             : 
     724             : 
     725             : 
     726             : 
     727             : 
     728             : 
     729           1 : CATCH_TEST_CASE("binary_integer_operators", "[binary][integer]")
     730             : {
     731           1 :     CATCH_START_SECTION("binary_integer_operators: test binary operators for integers")
     732             :     {
     733           1 :         snapdev::glob_to_list<std::list<std::string>> scripts;
     734           1 :         CATCH_REQUIRE(scripts.read_path<snapdev::glob_to_list_flag_t::GLOB_FLAG_NONE>
     735             :                                     (SNAP_CATCH2_NAMESPACE::g_source_dir()
     736             :                                         + "/tests/binary/integer_operator_*.ajs"));
     737          10 :         for(auto const & s : scripts)
     738             :         {
     739           9 :             run_script(s);
     740           9 :             meta m(load_script_meta(s));
     741           9 :             execute(m);
     742           9 :         }
     743           1 :     }
     744           1 :     CATCH_END_SECTION()
     745           1 : }
     746             : 
     747           1 : CATCH_TEST_CASE("binary_double_operators", "[binary][double][floating_point]")
     748             : {
     749           1 :     CATCH_START_SECTION("binary_double_operators: test binary operators for doubles")
     750             :     {
     751           1 :         snapdev::glob_to_list<std::list<std::string>> scripts;
     752           1 :         CATCH_REQUIRE(scripts.read_path<snapdev::glob_to_list_flag_t::GLOB_FLAG_NONE>
     753             :                                     (SNAP_CATCH2_NAMESPACE::g_source_dir()
     754             :                                         + "/tests/binary/double_operator_*.ajs"));
     755          10 :         for(auto const & s : scripts)
     756             :         {
     757           9 :             run_script(s);
     758           9 :             meta m(load_script_meta(s));
     759           9 :             execute(m);
     760           9 :         }
     761           1 :     }
     762           1 :     CATCH_END_SECTION()
     763           1 : }
     764             : 
     765           1 : CATCH_TEST_CASE("binary_boolean_operators", "[binary][boolean]")
     766             : {
     767           1 :     CATCH_START_SECTION("binary_boolean_operators: test binary operators for booleans")
     768             :     {
     769           1 :         snapdev::glob_to_list<std::list<std::string>> scripts;
     770           1 :         CATCH_REQUIRE(scripts.read_path<snapdev::glob_to_list_flag_t::GLOB_FLAG_NONE>
     771             :                                     (SNAP_CATCH2_NAMESPACE::g_source_dir()
     772             :                                         + "/tests/binary/boolean_operator_*.ajs"));
     773           5 :         for(auto const & s : scripts)
     774             :         {
     775           4 :             run_script(s);
     776           4 :             meta m(load_script_meta(s));
     777           4 :             execute(m);
     778           4 :         }
     779           1 :     }
     780           1 :     CATCH_END_SECTION()
     781           1 : }
     782             : 
     783           1 : CATCH_TEST_CASE("binary_math_operators", "[binary][binary_math]")
     784             : {
     785           1 :     CATCH_START_SECTION("binary_math_operators: test binary operators for math")
     786             :     {
     787           1 :         snapdev::glob_to_list<std::list<std::string>> scripts;
     788           1 :         CATCH_REQUIRE(scripts.read_path<snapdev::glob_to_list_flag_t::GLOB_FLAG_NONE>
     789             :                                     (SNAP_CATCH2_NAMESPACE::g_source_dir()
     790             :                                         + "/tests/binary/math_operator_*.ajs"));
     791           2 :         for(auto const & s : scripts)
     792             :         {
     793           1 :             run_script(s);
     794           1 :             meta m(load_script_meta(s));
     795           1 :             execute(m);
     796           1 :         }
     797           1 :     }
     798           1 :     CATCH_END_SECTION()
     799           1 : }
     800             : 
     801           1 : CATCH_TEST_CASE("binary_string_operators", "[binary][binary_string]")
     802             : {
     803           1 :     CATCH_START_SECTION("binary_string_operators: test binary operators for strings")
     804             :     {
     805           1 :         snapdev::glob_to_list<std::list<std::string>> scripts;
     806           1 :         CATCH_REQUIRE(scripts.read_path<snapdev::glob_to_list_flag_t::GLOB_FLAG_NONE>
     807             :                                     (SNAP_CATCH2_NAMESPACE::g_source_dir()
     808             :                                         + "/tests/binary/string_operator_*.ajs"));
     809          11 :         for(auto const & s : scripts)
     810             :         {
     811          10 :             run_script(s);
     812          10 :             meta m(load_script_meta(s));
     813          10 :             execute(m);
     814          10 :         }
     815           1 :     }
     816           1 :     CATCH_END_SECTION()
     817           1 : }
     818             : 
     819             : 
     820             : 
     821             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.14