LCOV - code coverage report
Current view: top level - tests - catch_message.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 99.9 % 846 845
Test Date: 2025-08-10 10:49:55 Functions: 100.0 % 11 11
Legend: Lines: hit not hit

            Line data    Source code
       1              : // Copyright (c) 2006-2025  Made to Order Software Corp.  All Rights Reserved
       2              : //
       3              : // https://snapwebsites.org/project/snaplogger
       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 2 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 along
      17              : // with this program; if not, write to the Free Software Foundation, Inc.,
      18              : // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      19              : 
      20              : // header being tested
      21              : //
      22              : #include    <snaplogger/message.h>
      23              : 
      24              : 
      25              : // self
      26              : //
      27              : #include    "catch_main.h"
      28              : 
      29              : 
      30              : // cppthread
      31              : //
      32              : #include    <cppthread/log.h>
      33              : 
      34              : 
      35              : // as2js
      36              : //
      37              : #include    <as2js/message.h>
      38              : 
      39              : 
      40              : // snaplogger
      41              : //
      42              : #include    <snaplogger/buffer_appender.h>
      43              : #include    <snaplogger/exception.h>
      44              : #include    <snaplogger/format.h>
      45              : #include    <snaplogger/logger.h>
      46              : #include    <snaplogger/map_diagnostic.h>
      47              : #include    <snaplogger/severity.h>
      48              : #include    <snaplogger/version.h>
      49              : 
      50              : 
      51              : // snapdev
      52              : //
      53              : #include    <snapdev/enum_class_math.h>
      54              : 
      55              : 
      56              : // advgetopt
      57              : //
      58              : #include    <advgetopt/exception.h>
      59              : 
      60              : 
      61              : // C
      62              : //
      63              : #include    <math.h>
      64              : #include    <unistd.h>
      65              : 
      66              : 
      67              : namespace
      68              : {
      69              : 
      70              : 
      71            1 : std::source_location get_other_loc()
      72              : {
      73            1 :     return std::source_location::current();
      74              : }
      75              : 
      76              : 
      77              : 
      78              : } // no name namespace
      79              : 
      80              : 
      81            2 : CATCH_TEST_CASE("not_a_message", "[message]")
      82              : {
      83            2 :     CATCH_START_SECTION("message: Call send_message() with wrong ostream")
      84              :     {
      85            3 :         CATCH_REQUIRE_THROWS_MATCHES(
      86              :                   snaplogger::send_message(std::cout)
      87              :                 , snaplogger::not_a_message
      88              :                 , Catch::Matchers::ExceptionMessage(
      89              :                           "logger_error: the 'out' parameter to the send_message() function is expected to be a snaplogger::message object."));
      90              :     }
      91            2 :     CATCH_END_SECTION()
      92              : 
      93            2 :     CATCH_START_SECTION("message: Print snaplogger::secure to wrong ostream")
      94              :     {
      95            1 :         std::stringstream buffer;
      96            1 :         std::streambuf * old(std::cout.rdbuf(buffer.rdbuf()));
      97            1 :         std::cout << snaplogger::secure << std::endl;
      98            1 :         CATCH_REQUIRE(buffer.str() == "(section:secure)\n");
      99            1 :         std::cout.rdbuf(old);
     100            1 :     }
     101            2 :     CATCH_END_SECTION()
     102            2 : }
     103              : 
     104              : 
     105              : 
     106            2 : CATCH_TEST_CASE("message_capture", "[message]")
     107              : {
     108            2 :     CATCH_START_SECTION("message: Buffering")
     109              :     {
     110            5 :         snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "message-logging");
     111              : 
     112            1 :         snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
     113            1 :         snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
     114              : 
     115            1 :         CATCH_REQUIRE(buffer->get_type() == "buffer");
     116              : 
     117            1 :         char const * cargv[] =
     118              :         {
     119              :             "/usr/bin/daemon",
     120              :             nullptr
     121              :         };
     122            1 :         int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
     123            1 :         char ** argv = const_cast<char **>(cargv);
     124              : 
     125            1 :         advgetopt::options_environment environment_options;
     126            1 :         environment_options.f_project_name = "test-logger";
     127            1 :         environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
     128            1 :         advgetopt::getopt opts(environment_options);
     129            1 :         opts.parse_program_name(argv);
     130            1 :         opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     131              : 
     132            1 :         buffer->set_config(opts);
     133              : 
     134            1 :         snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${severity}: ${message}"));
     135            1 :         buffer->set_format(f);
     136              : 
     137            1 :         l->add_appender(buffer);
     138              : 
     139            2 :         SNAP_LOG_ERROR << snaplogger::precise_time << "Logging this error" << SNAP_LOG_SEND;
     140            1 :         CATCH_REQUIRE(buffer->str() == "error: Logging this error\n");
     141              : 
     142              :         // test the other str() function too
     143              :         //
     144            3 :         buffer->str("Start: ");
     145              : 
     146              :         // show that the "\n" does not get duplicated
     147              :         //
     148            2 :         SNAP_LOG_ERROR << "Error with newline\n" << SNAP_LOG_SEND;
     149            1 :         CATCH_REQUIRE(buffer->str() == "Start: error: Error with newline\n");
     150            1 :         buffer->clear();
     151              : 
     152              :         // show that the "\r\n" gets replaced by "\n"
     153              :         //
     154            2 :         SNAP_LOG_ERROR << "Error with CRLF\r\n" << SNAP_LOG_SEND;
     155            1 :         CATCH_REQUIRE(buffer->str() == "error: Error with CRLF\n");
     156            1 :         buffer->clear();
     157              : 
     158              :         // severity too low, no change to buffer
     159              :         //
     160            2 :         SNAP_LOG_DEBUG << "Debug Message " << M_PI << " which does not make it at all...\n" << SNAP_LOG_SEND;
     161            1 :         CATCH_REQUIRE(buffer->empty());
     162              : 
     163            1 :         l->reset();
     164            1 :     }
     165            2 :     CATCH_END_SECTION()
     166              : 
     167            2 :     CATCH_START_SECTION("message: JSON Buffering")
     168              :     {
     169            5 :         snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "json-logging");
     170              : 
     171            1 :         snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
     172            1 :         snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("json-buffer"));
     173              : 
     174            1 :         CATCH_REQUIRE(buffer->get_type() == "buffer");
     175              : 
     176            1 :         char const * cargv[] =
     177              :         {
     178              :             "/usr/bin/daemon",
     179              :             nullptr
     180              :         };
     181            1 :         int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
     182            1 :         char ** argv = const_cast<char **>(cargv);
     183              : 
     184            1 :         advgetopt::options_environment environment_options;
     185            1 :         environment_options.f_project_name = "json-logger";
     186            1 :         environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
     187            1 :         advgetopt::getopt opts(environment_options);
     188            1 :         opts.parse_program_name(argv);
     189            1 :         opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     190              : 
     191            1 :         buffer->set_config(opts);
     192              : 
     193            1 :         snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>(
     194              :                     "{\"version\":1,"
     195            1 :                     "\"message\":\"${message:escape='\\\r\n\t\"'}\"}"));
     196            1 :         buffer->set_format(f);
     197              : 
     198            1 :         l->add_appender(buffer);
     199              : 
     200            4 :         SNAP_LOG_ERROR
     201            6 :             << SNAP_LOG_FIELD(std::string("format"), std::string("json"))
     202              :             << "A JSON error message (format:${field:name=format})"
     203              :             << SNAP_LOG_SEND;
     204            1 :         CATCH_REQUIRE(buffer->str() == "{\"version\":1,\"message\":\"A JSON error message (format:json)\"}\n");
     205            1 :         buffer->clear();
     206              : 
     207              :         // show that the "\n" does not get duplicated
     208              :         //
     209            5 :         SNAP_LOG_ERROR
     210              :             << "See what happens with a \"quoted string\" within the message (${fields})\n"
     211            6 :             << SNAP_LOG_FIELD(std::string("format"), std::string("json"))
     212            6 :             << SNAP_LOG_FIELD(std::string("language"), std::string("js"))
     213              :             << SNAP_LOG_SEND;
     214            1 :         std::string const expected(std::regex_replace(buffer->str(), std::regex("\\\\\"id\\\\\":\\\\\"[0-9]+\\\\\","), ""));
     215            1 :         CATCH_REQUIRE(expected == "{\"version\":1,\"message\":\"See what happens with a \\\"quoted string\\\" within the message ({\\\"format\\\":\\\"json\\\",\\\"language\\\":\\\"js\\\"})\"}\n");
     216            1 :         buffer->clear();
     217              : 
     218            1 :         l->reset();
     219            1 :     }
     220            2 :     CATCH_END_SECTION()
     221            2 : }
     222              : 
     223              : 
     224            1 : CATCH_TEST_CASE("message_copy", "[message]")
     225              : {
     226            1 :     CATCH_START_SECTION("message: Copy")
     227              :     {
     228            5 :         snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "message-copying");
     229              : 
     230            1 :         snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
     231            1 :         snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
     232              : 
     233            1 :         CATCH_REQUIRE(buffer->get_type() == "buffer");
     234              : 
     235            1 :         char const * cargv[] =
     236              :         {
     237              :             "/usr/bin/daemon",
     238              :             nullptr
     239              :         };
     240            1 :         int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
     241            1 :         char ** argv = const_cast<char **>(cargv);
     242              : 
     243            1 :         advgetopt::options_environment environment_options;
     244            1 :         environment_options.f_project_name = "test-logger";
     245            1 :         environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
     246            1 :         advgetopt::getopt opts(environment_options);
     247            1 :         opts.parse_program_name(argv);
     248            1 :         opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     249              : 
     250            1 :         buffer->set_config(opts);
     251              : 
     252            1 :         snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${message}"));
     253            1 :         buffer->set_format(f);
     254              : 
     255            1 :         l->add_appender(buffer);
     256              : 
     257            1 :         std::source_location const loc(std::source_location::current());
     258            1 :         snaplogger::message::pointer_t msg(std::make_shared<snaplogger::message>
     259            1 :                         (::snaplogger::severity_t::SEVERITY_ERROR, loc));
     260              : 
     261            1 :         CATCH_REQUIRE(msg->get_filename() == loc.file_name());
     262            1 :         CATCH_REQUIRE(msg->get_function() == loc.function_name());
     263            1 :         CATCH_REQUIRE(msg->get_line() == loc.line());
     264            1 :         CATCH_REQUIRE(msg->get_column() == loc.column());
     265              : 
     266              :         // using a standard location
     267              :         //
     268            1 :         std::source_location const other_loc(get_other_loc());
     269              : 
     270            1 :         CATCH_REQUIRE(msg->get_filename() == loc.file_name());
     271            1 :         CATCH_REQUIRE(msg->get_function() == loc.function_name());
     272            1 :         CATCH_REQUIRE(msg->get_line() == loc.line());
     273            1 :         CATCH_REQUIRE(msg->get_column() == loc.column());
     274              : 
     275              :         // direct
     276              :         //
     277            3 :         msg->set_filename("we-are-under-control.cpp");
     278            3 :         msg->set_function("testing_set_function");
     279            1 :         msg->set_line(123);
     280            1 :         msg->set_column(64);
     281              : 
     282            1 :         CATCH_REQUIRE(msg->get_filename() == "we-are-under-control.cpp");
     283            1 :         CATCH_REQUIRE(msg->get_function() == "testing_set_function");
     284            1 :         CATCH_REQUIRE(msg->get_line() == 123);
     285            1 :         CATCH_REQUIRE(msg->get_column() == 64);
     286              : 
     287            1 :         *msg << "Logging an error.";
     288              : 
     289            1 :         CATCH_REQUIRE(msg->str() == "Logging an error.");
     290              : 
     291            1 :         snaplogger::message::pointer_t copy(std::make_shared<snaplogger::message>(*msg, *msg));
     292              : 
     293            1 :         CATCH_REQUIRE(msg->str() == "Logging an error.");
     294            1 :         CATCH_REQUIRE(copy->str() == "Logging an error.");
     295              : 
     296              :         // no destructor called, the output is still empty
     297              :         //
     298            1 :         CATCH_REQUIRE(buffer->empty());
     299              : 
     300            1 :         copy.reset();
     301              : 
     302              :         // msg not lost
     303              :         //
     304            1 :         CATCH_REQUIRE(msg->str() == "Logging an error.");
     305              : 
     306              :         // destructor against copy does not trigger send_message()
     307              :         //
     308            1 :         CATCH_REQUIRE(buffer->empty());
     309              : 
     310            1 :         snaplogger::send_message(*msg);
     311              : 
     312              :         // now we get the message as expected!
     313              :         //
     314              :         // (note that internally we can skip receiving the message on the
     315              :         // original, but not as a client... we may want to have the ability
     316              :         // to cancel a message, though.)
     317              :         //
     318            1 :         CATCH_REQUIRE(buffer->str() == "Logging an error.\n");
     319              : 
     320            1 :         msg.reset();
     321              : 
     322            1 :         CATCH_REQUIRE(buffer->str() == "Logging an error.\n");
     323              : 
     324            1 :         l->reset();
     325            1 :     }
     326            1 :     CATCH_END_SECTION()
     327            1 : }
     328              : 
     329              : 
     330            2 : CATCH_TEST_CASE("message_severity", "[message][severity]")
     331              : {
     332            2 :     CATCH_START_SECTION("message: Appender vs Message severity")
     333              :     {
     334            5 :         snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "message-severity");
     335              : 
     336            1 :         snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
     337            1 :         snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
     338              : 
     339            1 :         char const * cargv[] =
     340              :         {
     341              :             "/usr/bin/daemon",
     342              :             nullptr
     343              :         };
     344            1 :         int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
     345            1 :         char ** argv = const_cast<char **>(cargv);
     346              : 
     347            1 :         advgetopt::options_environment environment_options;
     348            1 :         environment_options.f_project_name = "test-logger";
     349            1 :         environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
     350            1 :         advgetopt::getopt opts(environment_options);
     351            1 :         opts.parse_program_name(argv);
     352            1 :         opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     353              : 
     354            1 :         buffer->set_config(opts);
     355              : 
     356            1 :         snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${message}"));
     357            1 :         buffer->set_format(f);
     358              : 
     359            1 :         l->add_appender(buffer);
     360              : 
     361              :         // ++<enum> works here because of this header:
     362              :         //    <snapdev/enum_class_math.h>
     363              :         //
     364          257 :         for(snaplogger::severity_t i(snaplogger::severity_t::SEVERITY_MIN); i <= snaplogger::severity_t::SEVERITY_MAX; ++i)
     365              :         {
     366          256 :             buffer->set_severity(i);
     367        65792 :             for(snaplogger::severity_t j(snaplogger::severity_t::SEVERITY_MIN); j <= snaplogger::severity_t::SEVERITY_MAX; ++j)
     368              :             {
     369       131072 :                 snaplogger::send_message(*::snaplogger::create_message(j)
     370              :                                                 << "The message itself");
     371              : 
     372        65536 :                 if(j >= i
     373        32896 :                 && i != snaplogger::severity_t::SEVERITY_OFF
     374        32895 :                 && j != snaplogger::severity_t::SEVERITY_OFF)
     375              :                 {
     376        32640 :                     CATCH_REQUIRE(buffer->str() == "The message itself\n");
     377        32640 :                 }
     378              :                 else
     379              :                 {
     380        32896 :                     CATCH_REQUIRE(buffer->empty());
     381              :                 }
     382        65536 :                 buffer->clear();
     383              :             }
     384              :         }
     385              : 
     386            1 :         l->reset();
     387            1 :     }
     388            2 :     CATCH_END_SECTION()
     389              : 
     390            2 :     CATCH_START_SECTION("message: Changing message severity (takes about 3.5min)")
     391              :     {
     392            5 :         snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "message-copying");
     393              : 
     394            1 :         snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
     395            1 :         snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
     396              : 
     397            1 :         char const * cargv[] =
     398              :         {
     399              :             "/usr/bin/daemon",
     400              :             nullptr
     401              :         };
     402            1 :         int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
     403            1 :         char ** argv = const_cast<char **>(cargv);
     404              : 
     405            1 :         advgetopt::options_environment environment_options;
     406            1 :         environment_options.f_project_name = "test-logger";
     407            1 :         environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
     408            1 :         advgetopt::getopt opts(environment_options);
     409            1 :         opts.parse_program_name(argv);
     410            1 :         opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     411              : 
     412            1 :         buffer->set_config(opts);
     413              : 
     414            1 :         snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${message}"));
     415            1 :         buffer->set_format(f);
     416              : 
     417            1 :         l->add_appender(buffer);
     418              : 
     419              :         // <enum> += n works here because of this header:
     420              :         //    <snapdev/enum_class_math.h>
     421              :         //
     422           28 :         for(snaplogger::severity_t i(snaplogger::severity_t::SEVERITY_MIN); i <= snaplogger::severity_t::SEVERITY_MAX; i += 1 + (rand() & 15))
     423              :         {
     424           27 :             buffer->set_severity(i);
     425          851 :             for(snaplogger::severity_t j(snaplogger::severity_t::SEVERITY_MIN); j <= snaplogger::severity_t::SEVERITY_MAX; j += 1 + (rand() & 15))
     426              :             {
     427        26136 :                 for(snaplogger::severity_t k(snaplogger::severity_t::SEVERITY_MIN); k <= snaplogger::severity_t::SEVERITY_MAX; k += 1 + (rand() & 15))
     428              :                 {
     429        25312 :                     ::snaplogger::message::pointer_t msg(std::make_shared<::snaplogger::message>(j));
     430        25312 :                     *msg << "Start of message";
     431        25312 :                     msg->set_severity(k);
     432        25312 :                     *msg << " -- end of message";
     433        25312 :                     snaplogger::send_message(*msg);
     434              : //std::cerr << "checking with " << i << ", " << j << ", " << k << "\n";
     435              : 
     436        25312 :                     if(j >= i
     437        13363 :                     && k >= i
     438         9112 :                     && i != snaplogger::severity_t::SEVERITY_OFF
     439         9112 :                     && j != snaplogger::severity_t::SEVERITY_OFF)
     440              :                     //&& k != snaplogger::severity_t::SEVERITY_OFF)
     441              :                     {
     442         9056 :                         if(j >= i)
     443              :                         {
     444         9056 :                             CATCH_REQUIRE(buffer->str() == "Start of message -- end of message\n");
     445              :                         }
     446              :                         else
     447              :                         {
     448            0 :                             CATCH_REQUIRE(buffer->str() == "Start of message\n");
     449              :                         }
     450         9056 :                     }
     451              :                     else
     452              :                     {
     453        16256 :                         CATCH_REQUIRE(buffer->empty());
     454              :                     }
     455        25312 :                     buffer->clear();
     456        25312 :                 }
     457              :             }
     458              :         }
     459              : 
     460            1 :         l->reset();
     461            1 :     }
     462            2 :     CATCH_END_SECTION()
     463            2 : }
     464              : 
     465              : 
     466            4 : CATCH_TEST_CASE("message_format", "[message][format]")
     467              : {
     468            4 :     CATCH_START_SECTION("message: Recursivity")
     469              :     {
     470            5 :         snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "basic-format");
     471              : 
     472              :         // these two are not called in this test
     473              :         //
     474            5 :         snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROJECT_NAME, "test-logger");
     475            5 :         snaplogger::set_diagnostic(snaplogger::DIAG_KEY_VERSION, "5.32.1024");
     476              : 
     477            1 :         snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
     478            1 :         snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
     479              : 
     480            1 :         char const * cargv[] =
     481              :         {
     482              :             "/usr/bin/daemon",
     483              :             nullptr
     484              :         };
     485            1 :         int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
     486            1 :         char ** argv = const_cast<char **>(cargv);
     487              : 
     488            1 :         advgetopt::options_environment environment_options;
     489            1 :         environment_options.f_project_name = "test-logger";
     490            1 :         environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
     491            1 :         environment_options.f_version = "5.32.1024";
     492            1 :         advgetopt::getopt opts(environment_options);
     493            1 :         opts.parse_program_name(argv);
     494            1 :         opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     495              : 
     496            1 :         buffer->set_config(opts);
     497              : 
     498            1 :         snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${project_name} ${message} v${version}"));
     499            1 :         buffer->set_format(f);
     500              : 
     501            1 :         l->add_appender(buffer);
     502              : 
     503            2 :         SNAP_LOG_WARNING
     504              :             << "Message Project Name = ${project_name} and Version = ${version} -- uses \"recursive\""
     505              :             << SNAP_LOG_SEND;
     506              : 
     507            1 :         CATCH_REQUIRE(buffer->str() ==
     508              :                 "test-logger Message Project Name = test-logger and"
     509              :                 " Version = 5.32.1024 -- uses \"recursive\" v5.32.1024"
     510              :                 "\n");
     511              : 
     512            1 :         l->reset();
     513            1 :     }
     514            4 :     CATCH_END_SECTION()
     515              : 
     516            4 :     CATCH_START_SECTION("message: ${message} itself is not recursive")
     517              :     {
     518            5 :         snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "prevent-infinite-loop");
     519              : 
     520              :         // these two are not called in this test
     521              :         //
     522            5 :         snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROJECT_NAME, "test-logger");
     523            5 :         snaplogger::set_diagnostic(snaplogger::DIAG_KEY_VERSION, "5.32.1024");
     524              : 
     525            1 :         snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
     526            1 :         snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
     527              : 
     528            1 :         char const * cargv[] =
     529              :         {
     530              :             "/usr/bin/daemon",
     531              :             nullptr
     532              :         };
     533            1 :         int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
     534            1 :         char ** argv = const_cast<char **>(cargv);
     535              : 
     536            1 :         advgetopt::options_environment environment_options;
     537            1 :         environment_options.f_project_name = "test-logger";
     538            1 :         environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
     539            1 :         environment_options.f_version = "5.32.1024";
     540            1 :         advgetopt::getopt opts(environment_options);
     541            1 :         opts.parse_program_name(argv);
     542            1 :         opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     543              : 
     544            1 :         buffer->set_config(opts);
     545              : 
     546            1 :         snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${project_name} ${message} v${version}"));
     547            1 :         buffer->set_format(f);
     548              : 
     549            1 :         l->add_appender(buffer);
     550              : 
     551            2 :         SNAP_LOG_WARNING
     552              :             << "Message ${message} says: Project Name = ${project_name} and Version = ${version} -- uses \"recursive\""
     553              :             << SNAP_LOG_SEND;
     554              : 
     555            1 :         CATCH_REQUIRE(buffer->str() ==
     556              :                 "test-logger Message  says: Project Name = test-logger and"
     557              :                 " Version = 5.32.1024 -- uses \"recursive\" v5.32.1024"
     558              :                 "\n");
     559              : 
     560            1 :         buffer->clear();
     561              : 
     562            3 :         snaplogger::unset_diagnostic(snaplogger::DIAG_KEY_VERSION);
     563              : 
     564            2 :         SNAP_LOG_WARNING
     565              :             << "Removed the version: ${message} says: Project Name = ${project_name} and Version = ${version} -- uses \"recursive\""
     566              :             << SNAP_LOG_SEND;
     567              : 
     568            1 :         CATCH_REQUIRE(buffer->str() ==
     569              :                 "test-logger Removed the version:  says: Project Name = test-logger and"
     570              :                 " Version =  -- uses \"recursive\" v"
     571              :                 "\n");
     572              : 
     573            1 :         l->reset();
     574            1 :     }
     575            4 :     CATCH_END_SECTION()
     576              : 
     577            4 :     CATCH_START_SECTION("message: ${pid} uses the get_environment() function")
     578              :     {
     579            5 :         snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "get-environment");
     580              : 
     581            1 :         snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
     582            1 :         snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
     583              : 
     584            1 :         char const * cargv[] =
     585              :         {
     586              :             "/usr/bin/daemon",
     587              :             nullptr
     588              :         };
     589            1 :         int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
     590            1 :         char ** argv = const_cast<char **>(cargv);
     591              : 
     592            1 :         advgetopt::options_environment environment_options;
     593            1 :         environment_options.f_project_name = "test-logger";
     594            1 :         environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
     595            1 :         advgetopt::getopt opts(environment_options);
     596            1 :         opts.parse_program_name(argv);
     597            1 :         opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     598              : 
     599            1 :         buffer->set_config(opts);
     600              : 
     601            1 :         snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${message}"));
     602            1 :         buffer->set_format(f);
     603              : 
     604            1 :         l->add_appender(buffer);
     605              : 
     606            2 :         SNAP_LOG_WARNING
     607              :             << "Test PID = ${pid} == ${pid:running}"
     608              :             << SNAP_LOG_SEND;
     609              : 
     610            1 :         CATCH_REQUIRE(buffer->str() ==
     611              :                   "Test PID = " + std::to_string(getpid())
     612              :                 + " == " + std::to_string(getpid())
     613              :                 + "\n");
     614              : 
     615            1 :         l->reset();
     616            1 :     }
     617            4 :     CATCH_END_SECTION()
     618              : 
     619            4 :     CATCH_START_SECTION("message: Verify year")
     620              :     {
     621            5 :         snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "get-environment");
     622              : 
     623            1 :         snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
     624            3 :         CATCH_REQUIRE(l->get_appender("test-buffer") == nullptr);
     625              : 
     626            1 :         snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
     627              : 
     628            1 :         char const * cargv[] =
     629              :         {
     630              :             "/usr/bin/daemon",
     631              :             nullptr
     632              :         };
     633            1 :         int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
     634            1 :         char ** argv = const_cast<char **>(cargv);
     635              : 
     636            1 :         advgetopt::options_environment environment_options;
     637            1 :         environment_options.f_project_name = "test-logger";
     638            1 :         environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
     639            1 :         advgetopt::getopt opts(environment_options);
     640            1 :         opts.parse_program_name(argv);
     641            1 :         opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     642              : 
     643            1 :         buffer->set_config(opts);
     644              : 
     645            1 :         snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${message}"));
     646            1 :         buffer->set_format(f);
     647              : 
     648            1 :         l->add_appender(buffer);
     649              : 
     650            3 :         CATCH_REQUIRE(l->get_appender("test-buffer") == buffer);
     651              : 
     652              :         // we create a message so we can check the timestamp in our test
     653              :         //
     654            1 :         snaplogger::message::pointer_t msg(std::make_shared<snaplogger::message>
     655            1 :                         (::snaplogger::severity_t::SEVERITY_ERROR));
     656            1 :         *msg << "Created message on YYYY = ${date:year}, MM = ${date:month}, DD = ${date:day}";
     657              : 
     658            1 :         timespec const stamp(msg->get_timestamp());
     659              : 
     660            1 :         snaplogger::send_message(*msg);
     661              : 
     662            1 :         tm t;
     663            1 :         gmtime_r(&stamp.tv_sec, &t);
     664            1 :         char year[16];
     665            1 :         char month[16];
     666            1 :         char day[16];
     667            1 :         strftime(year,  16, "%Y", &t);
     668            1 :         strftime(month, 16, "%m", &t);
     669            1 :         strftime(day,   16, "%d", &t);
     670              : 
     671            3 :         CATCH_REQUIRE(buffer->str() ==
     672              :                   std::string("Created message on YYYY = ")
     673              :                 + year
     674              :                 + ", MM = "
     675              :                 + std::to_string(std::atoi(month))  // remove the leading '0' if necessary
     676              :                 + ", DD = "
     677              :                 + std::to_string(std::atoi(day))    // remove the leading '0' if necessary
     678              :                 + "\n");
     679              : 
     680            1 :         l->reset();
     681            1 :     }
     682            4 :     CATCH_END_SECTION()
     683            4 : }
     684              : 
     685              : 
     686            1 : CATCH_TEST_CASE("message_component_filter", "[message][component]")
     687              : {
     688            1 :     CATCH_START_SECTION("message: Filter Message with Component")
     689              :     {
     690            5 :         snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "component-filter");
     691              : 
     692            1 :         snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
     693            1 :         snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
     694              : 
     695            1 :         char const * cargv[] =
     696              :         {
     697              :             "/usr/bin/daemon",
     698              :             nullptr
     699              :         };
     700            1 :         int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
     701            1 :         char ** argv = const_cast<char **>(cargv);
     702              : 
     703            1 :         advgetopt::options_environment environment_options;
     704            1 :         environment_options.f_project_name = "test-logger";
     705            1 :         environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
     706            1 :         advgetopt::getopt opts(environment_options);
     707            1 :         opts.parse_program_name(argv);
     708            1 :         opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     709              : 
     710            1 :         buffer->set_config(opts);
     711              : 
     712            1 :         snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${message} (${severity:format=number})"));
     713            1 :         buffer->set_format(f);
     714              : 
     715            1 :         l->add_appender(buffer);
     716              : 
     717            3 :         SNAP_LOG_WARNING
     718            1 :             << snaplogger::secure       // mark as a secure message
     719              :             << "This message is secure but not the buffer"
     720              :             << SNAP_LOG_SEND;
     721              : 
     722            1 :         CATCH_REQUIRE(buffer->empty());
     723              : 
     724            3 :         SNAP_LOG_WARNING
     725            1 :             << "Test number: "
     726              :             << 2
     727            1 :             << " with buffer still unsecure..."
     728            1 :             << SNAP_LOG_SEND_SECURELY;  // mark at the end
     729              : 
     730            1 :         CATCH_REQUIRE(buffer->empty());
     731              : 
     732              :         // mark the buffer as a secure buffer now
     733              :         //
     734            1 :         buffer->add_component(snaplogger::g_secure_component);
     735              : 
     736            3 :         SNAP_LOG_WARNING
     737            1 :             << snaplogger::secure       // mark as a secure message
     738              :             << "This message is secure and so is the buffer"
     739              :             << SNAP_LOG_SEND;
     740              : 
     741              :         // TODO: get the WARNING severity level dynamically
     742            1 :         std::string const expected1("This message is secure and so is the buffer ("
     743            2 :                 + std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_WARNING))
     744            2 :                 + ")\n");
     745            1 :         CATCH_REQUIRE(buffer->str() == expected1);
     746              : 
     747            1 :         buffer->clear();
     748              : 
     749            3 :         SNAP_LOG_WARNING
     750            1 :             << "Test number: "
     751              :             << 4
     752            1 :             << " with secure buffer...\r\n"
     753            1 :             << SNAP_LOG_SEND_SECURELY;  // mark at the end
     754              : 
     755              :         // TODO: get the WARNING severity level dynamically
     756            1 :         std::string const expected2("Test number: 4 with secure buffer... ("
     757            2 :                 + std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_WARNING))
     758            2 :                 + ")\n");
     759            1 :         CATCH_REQUIRE(buffer->str() == expected2);
     760              : 
     761            1 :         l->reset();
     762            1 :     }
     763            1 :     CATCH_END_SECTION()
     764            1 : }
     765              : 
     766              : 
     767            1 : CATCH_TEST_CASE("message_cppthread", "[message][cppthread]")
     768              : {
     769            1 :     CATCH_START_SECTION("message: send log messages through cppthreadd with all levels")
     770              :     {
     771            1 :         snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
     772            1 :         snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("cppthread-buffer"));
     773              : 
     774            1 :         char const * cargv[] =
     775              :         {
     776              :             "/usr/bin/daemon",
     777              :             nullptr
     778              :         };
     779            1 :         int const argc(std::size(cargv) - 1);
     780            1 :         char ** argv = const_cast<char **>(cargv);
     781              : 
     782            1 :         advgetopt::options_environment environment_options;
     783            1 :         environment_options.f_project_name = "test-logger";
     784            1 :         environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
     785            1 :         advgetopt::getopt opts(environment_options);
     786            1 :         opts.parse_program_name(argv);
     787            1 :         opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     788              : 
     789            1 :         buffer->set_config(opts);
     790              : 
     791            1 :         snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>(
     792            1 :                 "${message} (${severity:format=number})"));
     793            1 :         buffer->set_format(f);
     794              : 
     795            1 :         l->add_appender(buffer);
     796            1 :         l->set_severity(snaplogger::severity_t::SEVERITY_ALL);
     797              : 
     798              :         cppthread::log
     799            2 :             << cppthread::log_level_t::debug
     800            1 :             << "a perfectly fine debug message here."
     801            2 :             << cppthread::end;
     802              : 
     803            1 :         std::string expected;
     804            1 :         expected = "a perfectly fine debug message here. (";
     805            1 :         expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_DEBUG));
     806            1 :         expected += ")\n";
     807            1 :         CATCH_REQUIRE(buffer->str() == expected);
     808            1 :         buffer->clear();
     809              : 
     810              :         cppthread::log
     811            2 :             << cppthread::log_level_t::info
     812            1 :             << "a good old info message there."
     813            2 :             << cppthread::end;
     814              : 
     815            1 :         expected = "a good old info message there. (";
     816            1 :         expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_INFORMATION));
     817            1 :         expected += ")\n";
     818            1 :         CATCH_REQUIRE(buffer->str() == expected);
     819            1 :         buffer->clear();
     820              : 
     821              :         cppthread::log
     822            2 :             << cppthread::log_level_t::warning
     823            1 :             << "a funny warning message here."
     824            2 :             << cppthread::end;
     825              : 
     826            1 :         expected = "a funny warning message here. (";
     827            1 :         expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_WARNING));
     828            1 :         expected += ")\n";
     829            1 :         CATCH_REQUIRE(buffer->str() == expected);
     830            1 :         buffer->clear();
     831              : 
     832              :         cppthread::log
     833            2 :             << cppthread::log_level_t::error
     834            1 :             << "a real error message here."
     835            2 :             << cppthread::end;
     836              : 
     837            1 :         expected = "a real error message here. (";
     838            1 :         expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_ERROR));
     839            1 :         expected += ")\n";
     840            1 :         CATCH_REQUIRE(buffer->str() == expected);
     841            1 :         buffer->clear();
     842              : 
     843              :         cppthread::log
     844            2 :             << cppthread::log_level_t::fatal
     845            1 :             << "an ending fatal message here."
     846            2 :             << cppthread::end;
     847              : 
     848            1 :         expected = "an ending fatal message here. (";
     849            1 :         expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_FATAL));
     850            1 :         expected += ")\n";
     851            1 :         CATCH_REQUIRE(buffer->str() == expected);
     852            1 :         buffer->clear();
     853              : 
     854              :         // try again when the CPPTHREAD component is turned off
     855              :         //
     856            1 :         l->add_component_to_ignore(snaplogger::g_cppthread_component);
     857              : 
     858              :         cppthread::log
     859            2 :             << cppthread::log_level_t::debug
     860            1 :             << "a perfectly fine debug message here."
     861            2 :             << cppthread::end;
     862              : 
     863            1 :         CATCH_REQUIRE(buffer->empty());
     864            1 :         buffer->clear();
     865              : 
     866              :         cppthread::log
     867            2 :             << cppthread::log_level_t::info
     868            1 :             << "a good old info message there."
     869            2 :             << cppthread::end;
     870              : 
     871            1 :         CATCH_REQUIRE(buffer->empty());
     872            1 :         buffer->clear();
     873              : 
     874              :         cppthread::log
     875            2 :             << cppthread::log_level_t::warning
     876            1 :             << "a funny warning message here."
     877            2 :             << cppthread::end;
     878              : 
     879            1 :         CATCH_REQUIRE(buffer->empty());
     880            1 :         buffer->clear();
     881              : 
     882              :         cppthread::log
     883            2 :             << cppthread::log_level_t::error
     884            1 :             << "a real error message here."
     885            2 :             << cppthread::end;
     886              : 
     887            1 :         CATCH_REQUIRE(buffer->empty());
     888            1 :         buffer->clear();
     889              : 
     890              :         cppthread::log
     891            2 :             << cppthread::log_level_t::fatal
     892            1 :             << "an ending fatal message here."
     893            2 :             << cppthread::end;
     894              : 
     895            1 :         CATCH_REQUIRE(buffer->empty());
     896            1 :         buffer->clear();
     897              : 
     898            1 :         l->remove_component_to_ignore(snaplogger::g_cppthread_component);
     899            1 :         l->reset();
     900            1 :     }
     901            1 :     CATCH_END_SECTION()
     902            1 : }
     903              : 
     904              : 
     905            1 : CATCH_TEST_CASE("message_as2js", "[message][as2js]")
     906              : {
     907            1 :     CATCH_START_SECTION("message: send log messages through as2js with all levels")
     908              :     {
     909            1 :         snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
     910            1 :         snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("as2js-buffer"));
     911              : 
     912            1 :         char const * cargv[] =
     913              :         {
     914              :             "/usr/bin/daemon",
     915              :             nullptr
     916              :         };
     917            1 :         int const argc(std::size(cargv) - 1);
     918            1 :         char ** argv = const_cast<char **>(cargv);
     919              : 
     920            1 :         advgetopt::options_environment environment_options;
     921            1 :         environment_options.f_project_name = "test-logger";
     922            1 :         environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
     923            1 :         advgetopt::getopt opts(environment_options);
     924            1 :         opts.parse_program_name(argv);
     925            1 :         opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     926              : 
     927            1 :         buffer->set_config(opts);
     928              : 
     929            1 :         snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>(
     930            1 :                 "${message} (${severity:format=number})"));
     931            1 :         buffer->set_format(f);
     932              : 
     933            1 :         l->add_appender(buffer);
     934            1 :         l->set_severity(snaplogger::severity_t::SEVERITY_ALL);
     935              : 
     936            1 :         as2js::set_message_level(as2js::message_level_t::MESSAGE_LEVEL_TRACE);
     937              : 
     938              :         {
     939              :             {
     940            1 :                 as2js::position pos;
     941            3 :                 pos.set_filename("trace-me.as");
     942            3 :                 pos.set_function("getUs");
     943            1 :                 pos.reset_counters(15);
     944            1 :                 as2js::message msg(as2js::message_level_t::MESSAGE_LEVEL_TRACE, as2js::err_code_t::AS_ERR_NONE, pos);
     945            1 :                 msg << "as2js supports tracing too.";
     946            1 :             }
     947              : 
     948            1 :             std::string expected;
     949            1 :             expected = "trace-me.as:15: as2js supports tracing too. (";
     950            1 :             expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_TRACE));
     951            1 :             expected += ")\n";
     952            1 :             CATCH_REQUIRE(buffer->str() == expected);
     953            1 :             buffer->clear();
     954            1 :         }
     955              : 
     956              :         {
     957              :             {
     958            1 :                 as2js::position pos;
     959            3 :                 pos.set_filename("debug.as");
     960            3 :                 pos.set_function("getFluff");
     961            1 :                 pos.reset_counters(5);
     962            1 :                 pos.new_column();
     963            1 :                 pos.new_column();
     964            1 :                 pos.new_column();
     965            1 :                 as2js::message msg(as2js::message_level_t::MESSAGE_LEVEL_DEBUG, as2js::err_code_t::AS_ERR_INVALID_EXPRESSION, pos);
     966            1 :                 msg << "This is the debug message.";
     967            1 :             }
     968              : 
     969            1 :             std::string expected;
     970            1 :             expected = "debug.as:5:4:err:";
     971            1 :             expected += std::to_string(static_cast<int>(as2js::err_code_t::AS_ERR_INVALID_EXPRESSION));
     972            1 :             expected += ": This is the debug message. (";
     973            1 :             expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_DEBUG));
     974            1 :             expected += ")\n";
     975            1 :             CATCH_REQUIRE(buffer->str() == expected);
     976            1 :             buffer->clear();
     977            1 :         }
     978              : 
     979              :         {
     980              :             {
     981            1 :                 as2js::position pos;
     982            3 :                 pos.set_filename("info.as");
     983            3 :                 pos.set_function("marvelous");
     984            1 :                 pos.reset_counters(33);
     985            1 :                 pos.new_column();
     986            1 :                 pos.new_column();
     987            1 :                 pos.new_column();
     988            1 :                 pos.new_column();
     989            1 :                 pos.new_column();
     990            1 :                 as2js::message msg(as2js::message_level_t::MESSAGE_LEVEL_INFO, as2js::err_code_t::AS_ERR_ABSTRACT, pos);
     991            1 :                 msg << "This is the info message.";
     992            1 :             }
     993              : 
     994            1 :             std::string expected;
     995            1 :             expected = "info.as:33:6:err:";
     996            1 :             expected += std::to_string(static_cast<int>(as2js::err_code_t::AS_ERR_ABSTRACT));
     997            1 :             expected += ": This is the info message. (";
     998            1 :             expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_INFORMATION));
     999            1 :             expected += ")\n";
    1000            1 :             CATCH_REQUIRE(buffer->str() == expected);
    1001            1 :             buffer->clear();
    1002            1 :         }
    1003              : 
    1004              :         {
    1005              :             {
    1006            1 :                 as2js::position pos;
    1007            3 :                 pos.set_filename("warning.as");
    1008            3 :                 pos.set_function("getWarningSigns");
    1009            1 :                 pos.reset_counters(3);
    1010            1 :                 pos.new_column();
    1011            1 :                 pos.new_column();
    1012            1 :                 as2js::message msg(as2js::message_level_t::MESSAGE_LEVEL_WARNING, as2js::err_code_t::AS_ERR_FINAL, pos);
    1013            1 :                 msg << "This is the warning message.";
    1014            1 :             }
    1015              : 
    1016            1 :             std::string expected;
    1017            1 :             expected = "warning.as:3:3:err:";
    1018            1 :             expected += std::to_string(static_cast<int>(as2js::err_code_t::AS_ERR_FINAL));
    1019            1 :             expected += ": This is the warning message. (";
    1020            1 :             expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_WARNING));
    1021            1 :             expected += ")\n";
    1022            1 :             CATCH_REQUIRE(buffer->str() == expected);
    1023            1 :             buffer->clear();
    1024            1 :         }
    1025              : 
    1026              :         {
    1027              :             {
    1028            1 :                 as2js::position pos;
    1029            3 :                 pos.set_filename("error.as");
    1030            3 :                 pos.set_function("gotMade");
    1031            1 :                 pos.reset_counters(65);
    1032            1 :                 pos.new_column();
    1033            1 :                 pos.new_column();
    1034            1 :                 as2js::message msg(as2js::message_level_t::MESSAGE_LEVEL_ERROR, as2js::err_code_t::AS_ERR_DIVIDE_BY_ZERO, pos);
    1035            1 :                 msg << "we got a real error here.";
    1036            1 :             }
    1037              : 
    1038            1 :             std::string expected;
    1039            1 :             expected = "error.as:65:3:err:";
    1040            1 :             expected += std::to_string(static_cast<int>(as2js::err_code_t::AS_ERR_DIVIDE_BY_ZERO));
    1041            1 :             expected += ": we got a real error here. (";
    1042            1 :             expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_ERROR));
    1043            1 :             expected += ")\n";
    1044            1 :             CATCH_REQUIRE(buffer->str() == expected);
    1045            1 :             buffer->clear();
    1046            1 :         }
    1047              : 
    1048              :         {
    1049              :             {
    1050            1 :                 as2js::position pos;
    1051            3 :                 pos.set_filename("fatal.as");
    1052            3 :                 pos.set_function("done");
    1053            1 :                 pos.reset_counters(789);
    1054            1 :                 pos.new_column();
    1055            1 :                 pos.new_column();
    1056            1 :                 pos.new_column();
    1057            1 :                 pos.new_column();
    1058            1 :                 pos.new_column();
    1059            1 :                 pos.new_column();
    1060            1 :                 as2js::message msg(as2js::message_level_t::MESSAGE_LEVEL_FATAL, as2js::err_code_t::AS_ERR_NOT_SUPPORTED, pos);
    1061            1 :                 msg << "this is not yet implemented.";
    1062            1 :             }
    1063              : 
    1064            1 :             std::string expected;
    1065            1 :             expected = "fatal.as:789:7:err:";
    1066            1 :             expected += std::to_string(static_cast<int>(as2js::err_code_t::AS_ERR_NOT_SUPPORTED));
    1067            1 :             expected += ": this is not yet implemented. (";
    1068            1 :             expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_FATAL));
    1069            1 :             expected += ")\n";
    1070            1 :             CATCH_REQUIRE(buffer->str() == expected);
    1071            1 :             buffer->clear();
    1072            1 :         }
    1073              : 
    1074              : 
    1075              :         // try again when the AS2JS component is turned off
    1076              :         //
    1077            1 :         l->add_component_to_ignore(snaplogger::g_as2js_component);
    1078              : 
    1079              :         {
    1080              :             {
    1081            1 :                 as2js::position pos;
    1082            3 :                 pos.set_filename("trace-me.as");
    1083            3 :                 pos.set_function("getUs");
    1084            1 :                 pos.reset_counters(15);
    1085            1 :                 as2js::message msg(as2js::message_level_t::MESSAGE_LEVEL_TRACE, as2js::err_code_t::AS_ERR_NOT_SUPPORTED, pos);
    1086            1 :                 msg << "as2js supports tracing too.";
    1087            1 :             }
    1088              : 
    1089            1 :             CATCH_REQUIRE(buffer->empty());
    1090            1 :             buffer->clear();
    1091              :         }
    1092              : 
    1093              :         {
    1094              :             {
    1095            1 :                 as2js::position pos;
    1096            3 :                 pos.set_filename("debug.as");
    1097            3 :                 pos.set_function("getFluff");
    1098            1 :                 pos.reset_counters(5);
    1099            1 :                 pos.new_column();
    1100            1 :                 pos.new_column();
    1101            1 :                 pos.new_column();
    1102            1 :                 as2js::message msg(as2js::message_level_t::MESSAGE_LEVEL_DEBUG, as2js::err_code_t::AS_ERR_INVALID_EXPRESSION, pos);
    1103            1 :                 msg << "This is the debug message.";
    1104            1 :             }
    1105              : 
    1106            1 :             CATCH_REQUIRE(buffer->empty());
    1107            1 :             buffer->clear();
    1108              :         }
    1109              : 
    1110              :         {
    1111              :             {
    1112            1 :                 as2js::position pos;
    1113            3 :                 pos.set_filename("info.as");
    1114            3 :                 pos.set_function("marvelous");
    1115            1 :                 pos.reset_counters(33);
    1116            1 :                 pos.new_column();
    1117            1 :                 pos.new_column();
    1118            1 :                 pos.new_column();
    1119            1 :                 pos.new_column();
    1120            1 :                 pos.new_column();
    1121            1 :                 as2js::message msg(as2js::message_level_t::MESSAGE_LEVEL_INFO, as2js::err_code_t::AS_ERR_ABSTRACT, pos);
    1122            1 :                 msg << "This is the info message.";
    1123            1 :             }
    1124              : 
    1125            1 :             CATCH_REQUIRE(buffer->empty());
    1126            1 :             buffer->clear();
    1127              :         }
    1128              : 
    1129              :         {
    1130              :             {
    1131            1 :                 as2js::position pos;
    1132            3 :                 pos.set_filename("warning.as");
    1133            3 :                 pos.set_function("getWarningSigns");
    1134            1 :                 pos.reset_counters(3);
    1135            1 :                 pos.new_column();
    1136            1 :                 pos.new_column();
    1137            1 :                 as2js::message msg(as2js::message_level_t::MESSAGE_LEVEL_WARNING, as2js::err_code_t::AS_ERR_FINAL, pos);
    1138            1 :                 msg << "This is the warning message.";
    1139            1 :             }
    1140              : 
    1141            1 :             CATCH_REQUIRE(buffer->empty());
    1142            1 :             buffer->clear();
    1143              :         }
    1144              : 
    1145              :         {
    1146              :             {
    1147            1 :                 as2js::position pos;
    1148            3 :                 pos.set_filename("error.as");
    1149            3 :                 pos.set_function("gotMade");
    1150            1 :                 pos.reset_counters(65);
    1151            1 :                 pos.new_column();
    1152            1 :                 pos.new_column();
    1153            1 :                 as2js::message msg(as2js::message_level_t::MESSAGE_LEVEL_ERROR, as2js::err_code_t::AS_ERR_DIVIDE_BY_ZERO, pos);
    1154            1 :                 msg << "we got a real error here.";
    1155            1 :             }
    1156              : 
    1157            1 :             CATCH_REQUIRE(buffer->empty());
    1158            1 :             buffer->clear();
    1159              :         }
    1160              : 
    1161              :         {
    1162              :             {
    1163            1 :                 as2js::position pos;
    1164            3 :                 pos.set_filename("fatal.as");
    1165            3 :                 pos.set_function("done");
    1166            1 :                 pos.reset_counters(789);
    1167            1 :                 pos.new_column();
    1168            1 :                 pos.new_column();
    1169            1 :                 pos.new_column();
    1170            1 :                 pos.new_column();
    1171            1 :                 pos.new_column();
    1172            1 :                 pos.new_column();
    1173            1 :                 as2js::message msg(as2js::message_level_t::MESSAGE_LEVEL_FATAL, as2js::err_code_t::AS_ERR_NOT_SUPPORTED, pos);
    1174            1 :                 msg << "this is not yet implemented.";
    1175            1 :             }
    1176              : 
    1177            1 :             CATCH_REQUIRE(buffer->empty());
    1178            1 :             buffer->clear();
    1179              :         }
    1180              : 
    1181            1 :         l->remove_component_to_ignore(snaplogger::g_as2js_component);
    1182              : 
    1183              : 
    1184              :         {
    1185            1 :             snaplogger::format::pointer_t j(std::make_shared<snaplogger::format>(
    1186            1 :                     "{\"message\":\"${message}\"${fields:format=json:json=start_comma}}"));
    1187            1 :             buffer->set_format(j);
    1188              : 
    1189              :             {
    1190            1 :                 as2js::position pos;
    1191            3 :                 pos.set_filename("json.as");
    1192            3 :                 pos.set_function("convoluted");
    1193            1 :                 pos.reset_counters(11);
    1194            1 :                 pos.new_column();
    1195            1 :                 pos.new_column();
    1196            1 :                 pos.new_column();
    1197            1 :                 pos.new_column();
    1198            1 :                 as2js::message msg(as2js::message_level_t::MESSAGE_LEVEL_ERROR, as2js::err_code_t::AS_ERR_DYNAMIC, pos);
    1199            1 :                 msg << "verify fields using JSON.";
    1200            1 :             }
    1201              : 
    1202            1 :             std::string expected;
    1203            1 :             expected = "{\"message\":\"json.as:11:5:err:15: verify fields using JSON.\",\"error_code\":\"";
    1204            1 :             expected += std::to_string(static_cast<int>(as2js::err_code_t::AS_ERR_DYNAMIC));
    1205            1 :             expected += "\",\"id\":\"";
    1206            1 :             expected += std::to_string(snaplogger::get_last_message_id());
    1207            1 :             expected += "\",\"position\":\"json.as:11:5:\"";
    1208            1 :             expected += "}\n";
    1209            1 :             CATCH_REQUIRE(buffer->str() == expected);
    1210            1 :             buffer->clear();
    1211            1 :         }
    1212              : 
    1213              : 
    1214            1 :         l->reset();
    1215            1 :     }
    1216            1 :     CATCH_END_SECTION()
    1217            1 : }
    1218              : 
    1219              : 
    1220            1 : CATCH_TEST_CASE("message_clog", "[message][clog]")
    1221              : {
    1222            1 :     CATCH_START_SECTION("message: send log messages through std::clog with all supported levels")
    1223              :     {
    1224            1 :         snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
    1225            1 :         snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("clog-buffer"));
    1226              : 
    1227            1 :         char const * cargv[] =
    1228              :         {
    1229              :             "/usr/bin/daemon",
    1230              :             nullptr
    1231              :         };
    1232            1 :         int const argc(std::size(cargv) - 1);
    1233            1 :         char ** argv = const_cast<char **>(cargv);
    1234              : 
    1235            1 :         advgetopt::options_environment environment_options;
    1236            1 :         environment_options.f_project_name = "test-logger";
    1237            1 :         environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
    1238            1 :         advgetopt::getopt opts(environment_options);
    1239            1 :         opts.parse_program_name(argv);
    1240            1 :         opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
    1241              : 
    1242            1 :         buffer->set_config(opts);
    1243              : 
    1244            1 :         snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>(
    1245            1 :                 "${message} (${severity:format=number})"));
    1246            1 :         buffer->set_format(f);
    1247              : 
    1248            1 :         l->add_appender(buffer);
    1249            1 :         l->set_severity(snaplogger::severity_t::SEVERITY_ALL);
    1250              : 
    1251            1 :         as2js::set_message_level(as2js::message_level_t::MESSAGE_LEVEL_TRACE);
    1252              : 
    1253              :         // debug
    1254              :         //
    1255            1 :         std::clog << "debug: check with a debug message.\n";
    1256            1 :         std::string expected;
    1257            1 :         expected = "check with a debug message. (";
    1258            1 :         expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_DEBUG));
    1259            1 :         expected += ")\n";
    1260            1 :         CATCH_REQUIRE(buffer->str() == expected);
    1261            1 :         buffer->clear();
    1262              : 
    1263            1 :         std::clog << "Debug: nice upper to start word.\n";
    1264            1 :         expected = "nice upper to start word. (";
    1265            1 :         expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_DEBUG));
    1266            1 :         expected += ")\n";
    1267            1 :         CATCH_REQUIRE(buffer->str() == expected);
    1268            1 :         buffer->clear();
    1269              : 
    1270            1 :         std::clog << "DEBUG: check that case is ignored.\n";
    1271            1 :         expected = "check that case is ignored. (";
    1272            1 :         expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_DEBUG));
    1273            1 :         expected += ")\n";
    1274            1 :         CATCH_REQUIRE(buffer->str() == expected);
    1275            1 :         buffer->clear();
    1276              : 
    1277              :         // info
    1278              :         //
    1279            1 :         std::clog << "info: check with an informational message.\n";
    1280            1 :         expected = "check with an informational message. (";
    1281            1 :         expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_INFORMATION));
    1282            1 :         expected += ")\n";
    1283            1 :         CATCH_REQUIRE(buffer->str() == expected);
    1284            1 :         buffer->clear();
    1285              : 
    1286            1 :         std::clog << "advanced information: word just needs to appear.\n";
    1287            1 :         expected = "word just needs to appear. (";
    1288            1 :         expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_INFORMATION));
    1289            1 :         expected += ")\n";
    1290            1 :         CATCH_REQUIRE(buffer->str() == expected);
    1291            1 :         buffer->clear();
    1292              : 
    1293            1 :         std::clog << "INFO: like with debug, case does not matter.\n";
    1294            1 :         expected = "like with debug, case does not matter. (";
    1295            1 :         expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_INFORMATION));
    1296            1 :         expected += ")\n";
    1297            1 :         CATCH_REQUIRE(buffer->str() == expected);
    1298            1 :         buffer->clear();
    1299              : 
    1300              :         // warning
    1301              :         //
    1302            1 :         std::clog << "warning: verify warnings too.\n";
    1303            1 :         expected = "verify warnings too. (";
    1304            1 :         expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_WARNING));
    1305            1 :         expected += ")\n";
    1306            1 :         CATCH_REQUIRE(buffer->str() == expected);
    1307            1 :         buffer->clear();
    1308              : 
    1309            1 :         std::clog << "warn: word can be shorten.\n";
    1310            1 :         expected = "word can be shorten. (";
    1311            1 :         expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_WARNING));
    1312            1 :         expected += ")\n";
    1313            1 :         CATCH_REQUIRE(buffer->str() == expected);
    1314            1 :         buffer->clear();
    1315              : 
    1316              :         // error
    1317              :         //
    1318            1 :         std::clog << "error: this just doesn't work, does it?\n";
    1319            1 :         expected = "this just doesn't work, does it? (";
    1320            1 :         expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_ERROR));
    1321            1 :         expected += ")\n";
    1322            1 :         CATCH_REQUIRE(buffer->str() == expected);
    1323            1 :         buffer->clear();
    1324              : 
    1325              :         // fatal
    1326              :         //
    1327            1 :         std::clog << "fatal error: this one is tricky, we have to test fatal first.\n";
    1328            1 :         expected = "this one is tricky, we have to test fatal first. (";
    1329            1 :         expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_FATAL));
    1330            1 :         expected += ")\n";
    1331            1 :         CATCH_REQUIRE(buffer->str() == expected);
    1332            1 :         buffer->clear();
    1333              : 
    1334              :         // empty line
    1335              :         //
    1336            1 :         std::clog << "\n";
    1337            1 :         CATCH_REQUIRE(buffer->empty());
    1338            1 :         buffer->clear();
    1339              : 
    1340              : 
    1341              :         // try again when the CLOG component is turned off
    1342              :         //
    1343            1 :         l->add_component_to_ignore(snaplogger::g_clog_component);
    1344              : 
    1345              : 
    1346              :         // error
    1347              :         //
    1348            1 :         std::clog << "error: clog can be filtered out.\n";
    1349            1 :         CATCH_REQUIRE(buffer->empty());
    1350            1 :         buffer->clear();
    1351              : 
    1352              : 
    1353            1 :         l->remove_component_to_ignore(snaplogger::g_clog_component);
    1354              : 
    1355            1 :         l->reset();
    1356            1 :     }
    1357            1 :     CATCH_END_SECTION()
    1358            1 : }
    1359              : 
    1360              : 
    1361              : 
    1362            2 : CATCH_TEST_CASE("message_exception", "[message][exception]")
    1363              : {
    1364            2 :     CATCH_START_SECTION("message: Use '... << exception << ...'")
    1365              :     {
    1366            1 :         snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
    1367            1 :         snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
    1368              : 
    1369            1 :         char const * cargv[] =
    1370              :         {
    1371              :             "/usr/bin/daemon",
    1372              :             nullptr
    1373              :         };
    1374            1 :         int const argc(std::size(cargv) - 1);
    1375            1 :         char ** argv = const_cast<char **>(cargv);
    1376              : 
    1377            1 :         advgetopt::options_environment environment_options;
    1378            1 :         environment_options.f_project_name = "test-logger";
    1379            1 :         environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
    1380            1 :         advgetopt::getopt opts(environment_options);
    1381            1 :         opts.parse_program_name(argv);
    1382            1 :         opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
    1383              : 
    1384            1 :         buffer->set_config(opts);
    1385              : 
    1386            1 :         snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>(
    1387            1 :                 "${message} (${severity:format=number}) exit code: ${field:name=exception_exit_code}"));
    1388            1 :         buffer->set_format(f);
    1389              : 
    1390            1 :         l->add_appender(buffer);
    1391              : 
    1392            3 :         advgetopt::getopt_exit const error("testing an exception -> logging", 123);
    1393              : 
    1394            2 :         SNAP_LOG_WARNING
    1395              :             << "We got an exception! ["
    1396              :             << error
    1397              :             << "]"
    1398              :             << SNAP_LOG_SEND;
    1399              : 
    1400            1 :         CATCH_REQUIRE_FALSE(buffer->empty());
    1401              : 
    1402            1 :         std::string const expected("We got an exception! [getopt_exception: testing an exception -> logging] ("
    1403            2 :                                         + std::to_string(static_cast<int>(::snaplogger::severity_t::SEVERITY_WARNING))
    1404            2 :                                         + ") exit code: 123\n");
    1405            1 :         CATCH_REQUIRE(buffer->str() == expected);
    1406              : 
    1407            1 :         buffer->clear();
    1408              : 
    1409            1 :         l->reset();
    1410            1 :     }
    1411            2 :     CATCH_END_SECTION()
    1412              : 
    1413            2 :     CATCH_START_SECTION("message: Use '... << stringstream << ...'")
    1414              :     {
    1415            1 :         snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
    1416            1 :         snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
    1417              : 
    1418            1 :         char const * cargv[] =
    1419              :         {
    1420              :             "/usr/bin/daemon",
    1421              :             nullptr
    1422              :         };
    1423            1 :         int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
    1424            1 :         char ** argv = const_cast<char **>(cargv);
    1425              : 
    1426            1 :         advgetopt::options_environment environment_options;
    1427            1 :         environment_options.f_project_name = "test-logger";
    1428            1 :         environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
    1429            1 :         advgetopt::getopt opts(environment_options);
    1430            1 :         opts.parse_program_name(argv);
    1431            1 :         opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
    1432              : 
    1433            1 :         buffer->set_config(opts);
    1434              : 
    1435            1 :         snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${message} (${severity:format=number})"));
    1436            1 :         buffer->set_format(f);
    1437              : 
    1438            1 :         l->add_appender(buffer);
    1439              : 
    1440            1 :         std::stringstream ss;
    1441            1 :         ss << "testing that we can also \"send\" the content of a string stream";
    1442              : 
    1443            2 :         SNAP_LOG_WARNING
    1444              :             << "We got an exception! ["
    1445              :             << ss
    1446              :             << "]"
    1447              :             << SNAP_LOG_SEND;
    1448              : 
    1449            1 :         CATCH_REQUIRE_FALSE(buffer->empty());
    1450              : 
    1451            1 :         std::string const expected("We got an exception! [testing that we can also \"send\" the content of a string stream] ("
    1452            2 :                                         + std::to_string(static_cast<int>(::snaplogger::severity_t::SEVERITY_WARNING))
    1453            2 :                                         + ")\n");
    1454            1 :         CATCH_REQUIRE(buffer->str() == expected);
    1455              : 
    1456            1 :         buffer->clear();
    1457              : 
    1458            1 :         l->reset();
    1459            1 :     }
    1460            2 :     CATCH_END_SECTION()
    1461            2 : }
    1462              : 
    1463              : 
    1464              : 
    1465              : // vim: ts=4 sw=4 et
        

Generated by: LCOV version 2.0-1

Snap C++ | List of projects | List of versions