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

Generated by: LCOV version 2.0-1

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