|
|
|
@ -1,6 +1,11 @@
|
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
|
#include "logger.hh"
|
|
|
|
|
|
|
|
|
|
#include <atomic>
|
|
|
|
|
#include <chrono>
|
|
|
|
|
#include <thread>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace
|
|
|
|
|
{
|
|
|
|
|
const std::string nonAscii = "€§";
|
|
|
|
@ -35,7 +40,7 @@ class LoggerTest : public ::testing::Test
|
|
|
|
|
|
|
|
|
|
void TearDown()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
// nothing to do here.
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -44,6 +49,7 @@ TEST_F( LoggerTest, Severities )
|
|
|
|
|
{
|
|
|
|
|
Logger L("Severities");
|
|
|
|
|
|
|
|
|
|
// printf-style ("C") API:
|
|
|
|
|
L.debug ("This is debug");
|
|
|
|
|
L.info ("This is info");
|
|
|
|
|
L.notice ("This is notice");
|
|
|
|
@ -53,7 +59,8 @@ TEST_F( LoggerTest, Severities )
|
|
|
|
|
L.alert ("This is alert");
|
|
|
|
|
L.emergency("This is emergency");
|
|
|
|
|
|
|
|
|
|
L << Logger::Debug << "Debug via stream";
|
|
|
|
|
// C++ ostream-like API:
|
|
|
|
|
L << Logger::Debug << "Debug via stream";
|
|
|
|
|
L << Logger::Info << "Info via stream";
|
|
|
|
|
L << Logger::Notice << "Notice via stream";
|
|
|
|
|
L << Logger::Warn << "Warning via stream";
|
|
|
|
@ -61,8 +68,82 @@ TEST_F( LoggerTest, Severities )
|
|
|
|
|
L << Logger::Crit << "Critical via stream";
|
|
|
|
|
L << Logger::Alert << "Alert via stream";
|
|
|
|
|
L << Logger::Emergency << "Emergency via stream";
|
|
|
|
|
|
|
|
|
|
unsigned counter = 1;
|
|
|
|
|
// string building etc. is not be done when DEBUG_ENABLED is not defined,
|
|
|
|
|
// but side effects in the expression are done anyways.
|
|
|
|
|
DEBUG_LOG(L) << "Debug log" << " which might be nullified!" << " Counter=" << (++counter);
|
|
|
|
|
EXPECT_EQ( counter, 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TEST_F( LoggerTest, SeveritiesWithFilter )
|
|
|
|
|
{
|
|
|
|
|
Logger L("Sev_Filter");
|
|
|
|
|
L.setLevel(Logger::Info); // filter everything with lower severity, i.e. Debug
|
|
|
|
|
|
|
|
|
|
unsigned counter = 1;
|
|
|
|
|
L.debug ("Debug. Counter=%u", ++counter); // not visible in log, but executed, incl. side-effects
|
|
|
|
|
EXPECT_EQ( counter, 2);
|
|
|
|
|
|
|
|
|
|
L.info ("Info. Counter=%u", ++counter); // visible in log
|
|
|
|
|
EXPECT_EQ( counter, 3);
|
|
|
|
|
|
|
|
|
|
L.notice("Notice. Counter=%u", ++counter); // visible in log
|
|
|
|
|
EXPECT_EQ( counter, 4);
|
|
|
|
|
|
|
|
|
|
// compile-time disabling of debug messages:
|
|
|
|
|
// the whole expression becomes no-op when DEBUG_ENABLED is not defined, incl. any
|
|
|
|
|
// calculations, function calls and other side-effects!
|
|
|
|
|
DEBUG_OUT( L, "compile-time disbled debug. Counter=%u", ++counter);
|
|
|
|
|
#ifdef DEBUG_ENABLED
|
|
|
|
|
EXPECT_EQ( counter, 5);
|
|
|
|
|
#else
|
|
|
|
|
EXPECT_EQ( counter, 4); // without DEBUG_ENABLED the last counter increment is not even compiled!
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// multi-threaded test and hierarchical Logger instances
|
|
|
|
|
TEST_F( LoggerTest, MT )
|
|
|
|
|
{
|
|
|
|
|
Logger L("MT");
|
|
|
|
|
L.info("Info from the main thread.");
|
|
|
|
|
|
|
|
|
|
std::atomic<int> thread_count;
|
|
|
|
|
for(unsigned t = 1; t<=10; ++t)
|
|
|
|
|
{
|
|
|
|
|
auto thread_func = [t, &L, &thread_count]()
|
|
|
|
|
{
|
|
|
|
|
Logger LL(L, std::to_string(t) );
|
|
|
|
|
LL << Logger::Info << "This is in a thread with thread-id " << std::this_thread::get_id();
|
|
|
|
|
for(unsigned u=0; u<5; ++u)
|
|
|
|
|
{
|
|
|
|
|
const unsigned delay = 100 + unsigned(drand48()*500);
|
|
|
|
|
std::this_thread::sleep_for( std::chrono::milliseconds(delay) );
|
|
|
|
|
LL << Logger::Debug << "make some noise: " << (t*117 + u*4711) << " after " << delay << " ms.";
|
|
|
|
|
}
|
|
|
|
|
LL << Logger::Debug << "Done.";
|
|
|
|
|
--thread_count;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
++thread_count;
|
|
|
|
|
std::thread th{thread_func};
|
|
|
|
|
th.detach();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while(thread_count.load() > 0)
|
|
|
|
|
{
|
|
|
|
|
std::this_thread::sleep_for( std::chrono::milliseconds(100) );
|
|
|
|
|
L.info("Wait for all threads to finish. %i threads left.", thread_count.load() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
L.info("MT is done.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// test whether overlong log lines are splitted as desired.
|
|
|
|
|
TEST_F( LoggerTest, LongLine )
|
|
|
|
|
{
|
|
|
|
|
Logger L("LongLine");
|
|
|
|
|