LCOV - code coverage report
Current view: top level - tests - catch_console.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 98 98
Test Date: 2025-09-07 15:22:28 Functions: 100.0 % 6 6
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              : // self
      20              : //
      21              : #include    "catch_main.h"
      22              : 
      23              : 
      24              : // snaplogger
      25              : //
      26              : #include    <snaplogger/console_appender.h>
      27              : //#include    <snaplogger/exception.h>
      28              : //#include    <snaplogger/format.h>
      29              : #include    <snaplogger/logger.h>
      30              : #include    <snaplogger/map_diagnostic.h>
      31              : //#include    <snaplogger/message.h>
      32              : //#include    <snaplogger/severity.h>
      33              : //#include    <snaplogger/version.h>
      34              : 
      35              : 
      36              : // cppthread
      37              : //
      38              : #include    <cppthread/runner.h>
      39              : #include    <cppthread/thread.h>
      40              : 
      41              : 
      42              : // snapdev
      43              : //
      44              : #include    <snapdev/ostream_to_buf.h>
      45              : 
      46              : 
      47              : // C
      48              : //
      49              : //#include    <unistd.h>
      50              : //#include    <netdb.h>
      51              : //#include    <sys/param.h>
      52              : 
      53              : 
      54              : namespace
      55              : {
      56              : 
      57              : 
      58              : 
      59              : // a thread so we can create a pipe and read the other side so the write
      60              : // does not get stuck
      61              : //
      62              : class pipe_reader
      63              :     : public cppthread::runner
      64              : {
      65              : public:
      66              :     typedef std::shared_ptr<pipe_reader>        pointer_t;
      67              : 
      68              : 
      69            1 :     pipe_reader(int pipe)
      70            1 :         : runner("pipe-reader-runner")
      71            3 :         , f_pipe(pipe)
      72              :     {
      73            1 :     }
      74              : 
      75              : 
      76            1 :     virtual void enter() override
      77              :     {
      78              :         // avoid the cppthread "entering" message
      79            1 :     }
      80              : 
      81              : 
      82            1 :     virtual void run() override
      83              :     {
      84              :         for(;;)
      85              :         {
      86            3 :             char buf[256];
      87            3 :             ssize_t n(read(f_pipe, buf, sizeof(buf)));
      88            3 :             if(n < 0)
      89              :             {
      90            2 :                 return;
      91              :             }
      92              : //std::cout << "--- received [" << std::string(buf, n) << "]" << std::endl;
      93            6 :             f_received += std::string(buf, n);
      94            2 :         }
      95              :     }
      96              : 
      97              : 
      98            1 :     virtual void leave(cppthread::leave_status_t status) override
      99              :     {
     100              :         // avoid the cppthread "leaving" message
     101              :         //
     102            1 :         snapdev::NOT_USED(status);
     103            1 :     }
     104              : 
     105              : 
     106            1 :     std::string const & get_received() const
     107              :     {
     108            1 :         return f_received;
     109              :     }
     110              : 
     111              : private:
     112              :     int         f_pipe = -1;
     113              :     std::string f_received = std::string();
     114              : };
     115              : 
     116              : 
     117              : 
     118              : }
     119              : 
     120              : 
     121              : 
     122              : 
     123            2 : CATCH_TEST_CASE("console_appender", "[appender]")
     124              : {
     125            2 :     CATCH_START_SECTION("console_appender: create")
     126              :     {
     127            5 :         snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "one-console");
     128              : 
     129            5 :         snaplogger::appender::pointer_t console(snaplogger::create_appender("console", "test-console"));
     130            1 :         CATCH_REQUIRE(console != nullptr);
     131            1 :         CATCH_REQUIRE(console->get_type() == "console");
     132            1 :         CATCH_REQUIRE(console->get_name() == "test-console");
     133              : 
     134            1 :         snaplogger::console_appender::pointer_t console_appender(std::dynamic_pointer_cast<snaplogger::console_appender>(console));
     135            1 :         CATCH_REQUIRE(console_appender != nullptr);
     136              : 
     137            1 :         CATCH_REQUIRE_FALSE(console_appender->get_force_style());
     138            1 :         console_appender->set_force_style(true);
     139            1 :         CATCH_REQUIRE(console_appender->get_force_style());
     140            1 :         console_appender->set_force_style(false);
     141            1 :         CATCH_REQUIRE_FALSE(console_appender->get_force_style());
     142              : 
     143            1 :         snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
     144            1 :         snaplogger::appender::vector_t appenders(l->get_appenders());
     145            1 :         CATCH_REQUIRE(appenders.size() == 0);
     146            3 :         CATCH_REQUIRE_FALSE(l->has_appender("console"));
     147            3 :         CATCH_REQUIRE(l->get_appender("test-console") == nullptr);
     148            1 :         l->add_appender(console);
     149            3 :         CATCH_REQUIRE(l->has_appender("console"));
     150            3 :         CATCH_REQUIRE(l->get_appender("test-console") != nullptr);
     151            1 :         appenders = l->get_appenders();
     152            1 :         CATCH_REQUIRE(appenders.size() == 1);
     153              : 
     154              :         // trying to add another console "works" but the existing
     155              :         // appender (the "original") is kept and the second instance is
     156              :         // totally ignored
     157              :         //
     158            5 :         snaplogger::appender::pointer_t second_console(snaplogger::create_appender("console", "second-console"));
     159            1 :         CATCH_REQUIRE(second_console != nullptr);
     160            1 :         CATCH_REQUIRE(second_console->get_type() == "console");
     161            1 :         CATCH_REQUIRE(second_console->get_name() == "second-console");
     162            1 :         l->add_appender(second_console);
     163            1 :         appenders = l->get_appenders();
     164            1 :         CATCH_REQUIRE(appenders.size() == 1); // still 1!
     165            1 :         CATCH_REQUIRE(appenders[0] == console); // original, "second_console" was ignored
     166            1 :         CATCH_REQUIRE(console->get_name() == "test-console"); // still the original console!
     167              : 
     168            1 :         l->reset();
     169            1 :     }
     170            2 :     CATCH_END_SECTION()
     171              : 
     172            2 :     CATCH_START_SECTION("console_appender: default console + create user console")
     173              :     {
     174            5 :         snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "user-console");
     175              : 
     176            1 :         snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
     177            1 :         snaplogger::appender::vector_t appenders(l->get_appenders());
     178            1 :         CATCH_REQUIRE(appenders.size() == 0);
     179              : 
     180              :         // the default console is named "console"
     181              :         //
     182            1 :         snaplogger::appender::pointer_t console(l->add_console_appender());
     183            1 :         CATCH_REQUIRE(console != nullptr);
     184            1 :         CATCH_REQUIRE(console->get_type() == "console");
     185            1 :         CATCH_REQUIRE(console->get_name() == "console");
     186              : 
     187            3 :         CATCH_REQUIRE(l->has_appender("console"));
     188            3 :         CATCH_REQUIRE(l->get_appender("console") == console);
     189            1 :         appenders = l->get_appenders();
     190            1 :         CATCH_REQUIRE(appenders.size() == 1);
     191            1 :         CATCH_REQUIRE(appenders[0] == console);
     192              : 
     193              :         // trying to add another console "works" but the existing
     194              :         // appender (the "original") is kept and the second instance is
     195              :         // totally ignored except in this very special case where the
     196              :         // original was named "console"--here the original gets renamed
     197              :         // to the new console "user" name
     198              :         //
     199            5 :         snaplogger::appender::pointer_t second_console(snaplogger::create_appender("console", "user-console"));
     200            1 :         CATCH_REQUIRE(second_console != nullptr);
     201            1 :         CATCH_REQUIRE(second_console->get_type() == "console");
     202            1 :         CATCH_REQUIRE(second_console->get_name() == "user-console");
     203            1 :         l->add_appender(second_console);
     204            1 :         appenders = l->get_appenders();
     205            1 :         CATCH_REQUIRE(appenders.size() == 1); // still 1!
     206            1 :         CATCH_REQUIRE(appenders[0] == console); // original, "second_console" was ignored
     207            1 :         CATCH_REQUIRE(console->get_name() == "user-console"); // except that the name was updated
     208              : 
     209              :         {
     210              :             // by default, output is sent to stderr
     211              :             //
     212            1 :             int fifo[2]; // 0 -- read, 1 -- write
     213            1 :             int const r(pipe(fifo));
     214            1 :             CATCH_REQUIRE(r == 0);
     215              : 
     216            1 :             FILE * fout(fdopen(fifo[1], "w"));
     217            1 :             std::swap(*fout, *stderr);
     218              : 
     219            1 :             pipe_reader::pointer_t pc(std::make_shared<pipe_reader>(fifo[0]));
     220            3 :             cppthread::thread t("pipe-reader", pc.get());
     221            1 :             CATCH_REQUIRE(t.start());
     222              : 
     223            2 :             SNAP_LOG_ERROR << "Test the console." << SNAP_LOG_SEND;
     224              : 
     225            1 :             std::swap(*fout, *stderr);
     226            1 :             fclose(fout);
     227            1 :             close(fifo[0]);
     228              : 
     229              :             // we expect the default format to include the name of the
     230              :             // appender and the message above and the severity
     231              :             //
     232            1 :             std::string const & received(pc->get_received());
     233            1 :             CATCH_REQUIRE(received.find("Test the console.") != std::string::npos);
     234            1 :             CATCH_REQUIRE(received.find(console->get_name()) != std::string::npos);
     235            1 :             CATCH_REQUIRE(received.find("error") != std::string::npos);
     236            1 :         }
     237              : 
     238            1 :         l->reset();
     239            1 :     }
     240            2 :     CATCH_END_SECTION()
     241            2 : }
     242              : 
     243              : 
     244              : 
     245              : // vim: ts=4 sw=4 et
        

Generated by: LCOV version 2.0-1

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