Improved copy constructors and assignment operator which is needed now when LOGLEVELS can be made on the fly

This commit is contained in:
Kjell Hedstrom 2015-08-12 06:43:24 -06:00
parent 49aee72faf
commit 8dfe9e0716
5 changed files with 206 additions and 146 deletions

View File

@ -13,16 +13,17 @@
// the DEBUG logging level for G3log. In that case they can instead use the define
// "CHANGE_G3LOG_DEBUG_TO_DBUG" and G3log's logging level DEBUG is changed to be DBUG
#if (defined(CHANGE_G3LOG_DEBUG_TO_DBUG))
#if (defined(DBUG))
#error "DEBUG is already defined elsewhere which clashes with G3Log's log level DEBUG"
#endif
#if (defined(DBUG))
#error "DEBUG is already defined elsewhere which clashes with G3Log's log level DEBUG"
#endif
#else
#if (defined(DEBUG))
#error "DEBUG is already defined elsewhere which clashes with G3Log's log level DEBUG"
#endif
#if (defined(DEBUG))
#error "DEBUG is already defined elsewhere which clashes with G3Log's log level DEBUG"
#endif
#endif
#include <string>
#include <algorithm>
// Levels for logging, made so that it would be easy to change, remove, add levels -- KjellKod
@ -30,19 +31,32 @@ struct LEVELS {
// force internal copy of the const char*. This is a simple safeguard for when g3log is used in a
// "dynamic, runtime loading of shared libraries"
LEVELS(const LEVELS &other): value(other.value), text(other.text.c_str()) {}
LEVELS(int id, const char *idtext) : value(id), text(idtext) {}
LEVELS(const LEVELS& other): value(other.value), text(other.text.c_str()) {}
LEVELS(int id, const char* idtext) : value(id), text(idtext) {}
bool operator==(const LEVELS &rhs) const {
bool operator==(const LEVELS& rhs) const {
return (value == rhs.value && text == rhs.text);
}
bool operator!=(const LEVELS &rhs) const {
bool operator!=(const LEVELS& rhs) const {
return (value != rhs.value || text != rhs.text);
}
const int value;
const std::string text;
friend void swap(LEVELS& first, LEVELS& second) {
using std::swap;
swap(first.value, second.value);
swap(first.text, second.text);
}
LEVELS& operator=(LEVELS other) {
swap(*this, other);
return *this;
}
int value;
std::string text;
};
@ -89,7 +103,7 @@ namespace g3 {
/// helper function to tell the logger if a log message was fatal. If it is it will force
/// a shutdown after all log entries are saved to the sinks
bool wasFatal(const LEVELS &level);
bool wasFatal(const LEVELS& level);
}
#ifdef G3_DYNAMIC_LOGGING
@ -99,9 +113,9 @@ namespace g3 {
void setLogLevel(LEVELS level, bool enabled_status);
std::string printLevels();
void reset();
} // only_change_at_initialization
#endif
bool logLevel(LEVELS level);
bool logLevel(LEVELS level);
} // g3

View File

@ -2,7 +2,7 @@
* 2012 by KjellKod.cc. This is PUBLIC DOMAIN to use at your own risk and comes
* with no warranties. This code is yours to share, use and modify with no
* strings attached and no restrictions or obligations.
*
*
* For more information see g3log/LICENSE or refer refer to http://unlicense.org
* ============================================================================*/
@ -47,7 +47,7 @@ namespace g3 {
/// use a different format string to get a different look on the time.
// default look is Y/M/D H:M:S
std::string timestamp(const std::string &time_format = {internal::date_formatted + " " + internal::time_formatted}) const;
std::string timestamp(const std::string& time_format = {internal::date_formatted + " " + internal::time_formatted}) const;
std::string microseconds() const {
return std::to_string(_microseconds);
}
@ -55,7 +55,7 @@ namespace g3 {
std::string message() const {
return _message;
}
std::string &write() const {
std::string& write() const {
return _message;
}
@ -74,11 +74,14 @@ namespace g3 {
}
LogMessage(const std::string &file, const int line, const std::string &function, const LEVELS &level);
explicit LogMessage(const std::string &fatalOsSignalCrashMessage);
LogMessage& operator=(LogMessage other);
LogMessage(const LogMessage &);
LogMessage(LogMessage &&other);
LogMessage(const std::string& file, const int line, const std::string& function, const LEVELS& level);
explicit LogMessage(const std::string& fatalOsSignalCrashMessage);
LogMessage(const LogMessage& other);
LogMessage(LogMessage&& other);
virtual ~LogMessage() {}
//
@ -94,6 +97,26 @@ namespace g3 {
LEVELS _level;
std::string _expression; // only with content for CHECK(...) calls
mutable std::string _message;
friend void swap(LogMessage& first, LogMessage& second) {
// enable ADL (not necessary in our case, but good practice)
using std::swap;
swap(first._timestamp, second._timestamp);
swap(first._call_thread_id, second._call_thread_id);
swap(first._microseconds, second._microseconds);
swap(first._file, second._file);
swap(first._line, second._line);
swap(first._function, second._function);
swap(first._level, second._level);
swap(first._expression, second._expression);
swap(first._message, second._message);
}
private:
LogMessage() = default; // only used for internal swap
};
@ -103,8 +126,8 @@ namespace g3 {
* A thread that causes a FatalMessage will sleep forever until the
* application has exited (after message flush) */
struct FatalMessage : public LogMessage {
FatalMessage(const LogMessage &details, g3::SignalType signal_id);
FatalMessage(const FatalMessage &);
FatalMessage(const LogMessage& details, g3::SignalType signal_id);
FatalMessage(const FatalMessage&);
virtual ~FatalMessage() {}
LogMessage copyToLogMessage() const;

View File

@ -2,7 +2,7 @@
* 2012 by KjellKod.cc. This is PUBLIC DOMAIN to use at your own risk and comes
* with no warranties. This code is yours to share, use and modify with no
* strings attached and no restrictions or obligations.
*
*
* For more information see g3log/LICENSE or refer refer to http://unlicense.org
* ============================================================================*/
@ -10,8 +10,9 @@
#include "g3log/crashhandler.hpp"
#include "g3log/time.hpp"
#include "g3log/std2_make_unique.hpp"
#include <algorithm>
#include <mutex>
#include <iostream>
namespace {
std::once_flag g_start_time_flag;
@ -25,7 +26,7 @@ namespace {
return std::chrono::duration_cast<std::chrono::microseconds>(now - g_start_time).count();
}
std::string splitFileName(const std::string &str) {
std::string splitFileName(const std::string& str) {
size_t found;
found = str.find_last_of("(/\\");
return str.substr(found + 1);
@ -38,7 +39,7 @@ namespace g3 {
// helper for setting the normal log details in an entry
std::string LogDetailsToString(const LogMessage &msg) {
std::string LogDetailsToString(const LogMessage& msg) {
std::string out;
out.append("\n" + msg.timestamp() + " " + msg.microseconds() + "\t"
+ msg.level() + " [" + msg.file() + " L: " + msg.line() + "]\t");
@ -47,14 +48,14 @@ namespace g3 {
// helper for normal
std::string normalToString(const LogMessage &msg) {
std::string normalToString(const LogMessage& msg) {
auto out = LogDetailsToString(msg);
out.append('"' + msg.message() + '"');
return out;
}
// helper for fatal signal
std::string fatalSignalToString(const LogMessage &msg) {
std::string fatalSignalToString(const LogMessage& msg) {
std::string out; // clear any previous text and formatting
out.append("\n" + msg.timestamp() + "." + msg.microseconds()
+ "\n\n***** FATAL SIGNAL RECEIVED ******* \n"
@ -64,7 +65,7 @@ namespace g3 {
// helper for fatal exception (windows only)
std::string fatalExceptionToString(const LogMessage &msg) {
std::string fatalExceptionToString(const LogMessage& msg) {
std::string out; // clear any previous text and formatting
out.append("\n" + msg.timestamp() + "." + msg.microseconds()
+ "\n\n***** FATAL EXCEPTION RECEIVED ******* \n"
@ -74,7 +75,7 @@ namespace g3 {
// helper for fatal LOG
std::string fatalLogToString(const LogMessage &msg) {
std::string fatalLogToString(const LogMessage& msg) {
auto out = LogDetailsToString(msg);
static const std::string fatalExitReason = {"EXIT trigger caused by LOG(FATAL) entry: "};
out.append("\n\t*******\t " + fatalExitReason + "\n\t" + '"' + msg.message() + '"');
@ -82,7 +83,7 @@ namespace g3 {
}
// helper for fatal CHECK
std::string fatalCheckToString(const LogMessage &msg) {
std::string fatalCheckToString(const LogMessage& msg) {
auto out = LogDetailsToString(msg);
static const std::string contractExitReason = {"EXIT trigger caused by broken Contract:"};
out.append("\n\t*******\t " + contractExitReason + " CHECK(" + msg.expression() + ")\n\t"
@ -123,15 +124,21 @@ namespace g3 {
std::string LogMessage::timestamp(const std::string &time_look) const {
std::string LogMessage::timestamp(const std::string& time_look) const {
return localtime_formatted(_timestamp, time_look);
}
// By copy, not by reference. See this explanation for details:
// http://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom
LogMessage& LogMessage::operator=(LogMessage other) {
swap(*this, other);
return *this;
}
LogMessage::LogMessage(const std::string &file, const int line,
const std::string &function, const LEVELS &level)
LogMessage::LogMessage(const std::string& file, const int line,
const std::string& function, const LEVELS& level)
: _timestamp(g3::systemtime_now())
, _call_thread_id(std::this_thread::get_id())
, _microseconds(microsecondsCounter())
@ -142,12 +149,12 @@ namespace g3 {
{}
LogMessage::LogMessage(const std::string &fatalOsSignalCrashMessage)
: LogMessage({""}, 0, {""}, internal::FATAL_SIGNAL) {
LogMessage::LogMessage(const std::string& fatalOsSignalCrashMessage)
: LogMessage( {""}, 0, {""}, internal::FATAL_SIGNAL) {
_message.append(fatalOsSignalCrashMessage);
}
LogMessage::LogMessage(const LogMessage &other)
LogMessage::LogMessage(const LogMessage& other)
: _timestamp(other._timestamp)
, _call_thread_id(other._call_thread_id)
, _microseconds(other._microseconds)
@ -156,21 +163,21 @@ namespace g3 {
, _function(other._function)
, _level(other._level)
, _expression(other._expression)
, _message(other._message)
{
, _message(other._message) {
}
LogMessage::LogMessage(LogMessage&& other)
: _timestamp(0)
, _call_thread_id(0)
, _microseconds(0)
, _file("---")
, _line(0)
, _function("---")
, _level(DEBUG)
, _expression("---")
, _message("---") {
LogMessage::LogMessage(LogMessage &&other)
: _timestamp(other._timestamp)
, _call_thread_id(other._call_thread_id)
, _microseconds(other._microseconds)
, _file(std::move(other._file))
, _line(other._line)
, _function(std::move(other._function))
, _level(other._level)
, _expression(std::move(other._expression))
, _message(std::move(other._message)) {
swap(*this, other);
}
@ -180,12 +187,12 @@ namespace g3 {
return oss.str();
}
FatalMessage::FatalMessage(const LogMessage &details, g3::SignalType signal_id)
FatalMessage::FatalMessage(const LogMessage& details, g3::SignalType signal_id)
: LogMessage(details), _signal_id(signal_id) { }
FatalMessage::FatalMessage(const FatalMessage &other)
FatalMessage::FatalMessage(const FatalMessage& other)
: LogMessage(other), _signal_id(other._signal_id) {}

View File

@ -13,32 +13,32 @@
#include "g3log/stacktrace_windows.hpp"
#include <windows.h>
TEST(CrashHandler_Windows, ExceptionType) {
EXPECT_EQ(stacktrace::exceptionIdToText(123), "UNKNOWN EXCEPTION:123");
EXPECT_EQ(stacktrace::exceptionIdToText(1), "UNKNOWN EXCEPTION:1");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_ACCESS_VIOLATION), "EXCEPTION_ACCESS_VIOLATION");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_ARRAY_BOUNDS_EXCEEDED), "EXCEPTION_ARRAY_BOUNDS_EXCEEDED");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_BREAKPOINT),"EXCEPTION_BREAKPOINT");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_DATATYPE_MISALIGNMENT),"EXCEPTION_DATATYPE_MISALIGNMENT");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_FLT_DENORMAL_OPERAND),"EXCEPTION_FLT_DENORMAL_OPERAND");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_FLT_DIVIDE_BY_ZERO),"EXCEPTION_FLT_DIVIDE_BY_ZERO");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_FLT_INEXACT_RESULT),"EXCEPTION_FLT_INEXACT_RESULT");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_FLT_INEXACT_RESULT),"EXCEPTION_FLT_INEXACT_RESULT");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_FLT_INVALID_OPERATION),"EXCEPTION_FLT_INVALID_OPERATION");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_FLT_OVERFLOW),"EXCEPTION_FLT_OVERFLOW");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_FLT_STACK_CHECK),"EXCEPTION_FLT_STACK_CHECK");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_FLT_UNDERFLOW),"EXCEPTION_FLT_UNDERFLOW");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_ILLEGAL_INSTRUCTION),"EXCEPTION_ILLEGAL_INSTRUCTION");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_IN_PAGE_ERROR),"EXCEPTION_IN_PAGE_ERROR");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_INT_DIVIDE_BY_ZERO),"EXCEPTION_INT_DIVIDE_BY_ZERO");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_INT_OVERFLOW),"EXCEPTION_INT_OVERFLOW");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_INVALID_DISPOSITION),"EXCEPTION_INVALID_DISPOSITION");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_NONCONTINUABLE_EXCEPTION),"EXCEPTION_NONCONTINUABLE_EXCEPTION");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_PRIV_INSTRUCTION),"EXCEPTION_PRIV_INSTRUCTION");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_SINGLE_STEP),"EXCEPTION_SINGLE_STEP");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_STACK_OVERFLOW),"EXCEPTION_STACK_OVERFLOW");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_BREAKPOINT), "EXCEPTION_BREAKPOINT");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_DATATYPE_MISALIGNMENT), "EXCEPTION_DATATYPE_MISALIGNMENT");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_FLT_DENORMAL_OPERAND), "EXCEPTION_FLT_DENORMAL_OPERAND");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_FLT_DIVIDE_BY_ZERO), "EXCEPTION_FLT_DIVIDE_BY_ZERO");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_FLT_INEXACT_RESULT), "EXCEPTION_FLT_INEXACT_RESULT");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_FLT_INEXACT_RESULT), "EXCEPTION_FLT_INEXACT_RESULT");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_FLT_INVALID_OPERATION), "EXCEPTION_FLT_INVALID_OPERATION");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_FLT_OVERFLOW), "EXCEPTION_FLT_OVERFLOW");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_FLT_STACK_CHECK), "EXCEPTION_FLT_STACK_CHECK");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_FLT_UNDERFLOW), "EXCEPTION_FLT_UNDERFLOW");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_ILLEGAL_INSTRUCTION), "EXCEPTION_ILLEGAL_INSTRUCTION");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_IN_PAGE_ERROR), "EXCEPTION_IN_PAGE_ERROR");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_INT_DIVIDE_BY_ZERO), "EXCEPTION_INT_DIVIDE_BY_ZERO");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_INT_OVERFLOW), "EXCEPTION_INT_OVERFLOW");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_INVALID_DISPOSITION), "EXCEPTION_INVALID_DISPOSITION");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_NONCONTINUABLE_EXCEPTION), "EXCEPTION_NONCONTINUABLE_EXCEPTION");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_PRIV_INSTRUCTION), "EXCEPTION_PRIV_INSTRUCTION");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_SINGLE_STEP), "EXCEPTION_SINGLE_STEP");
EXPECT_EQ(stacktrace::exceptionIdToText(EXCEPTION_STACK_OVERFLOW), "EXCEPTION_STACK_OVERFLOW");
}
#endif // defined WIN32

View File

@ -2,7 +2,7 @@
* 2011 by KjellKod.cc. This is PUBLIC DOMAIN to use at your own risk and comes
* with no warranties. This code is yours to share, use and modify with no
* strings attached and no restrictions or obligations.
*
*
* For more information see g3log/LICENSE or refer refer to http://unlicense.org
* ============================================================================*/
@ -21,18 +21,18 @@
#include <algorithm>
namespace {
const std::string log_directory = "./";
const std::string t_info = "test INFO ";
const std::string t_info2 = "test INFO 123";
const std::string t_debug = "test DEBUG ";
const std::string t_debug3 = "test DEBUG 1.123456";
const std::string t_warning = "test WARNING ";
const std::string t_warning3 = "test WARNING yello";
const std::string log_directory = "./";
const std::string t_info = "test INFO ";
const std::string t_info2 = "test INFO 123";
const std::string t_debug = "test DEBUG ";
const std::string t_debug3 = "test DEBUG 1.123456";
const std::string t_warning = "test WARNING ";
const std::string t_warning3 = "test WARNING yello";
std::atomic<size_t> g_fatal_counter = {0};
void fatalCounter() {
++g_fatal_counter;
}
std::atomic<size_t> g_fatal_counter = {0};
void fatalCounter() {
++g_fatal_counter;
}
} // end anonymous namespace
@ -40,12 +40,12 @@ void fatalCounter() {
using namespace testing_helpers;
/// THIS MUST BE THE FIRST UNIT TEST TO RUN! If any unit test run before this
/// THIS MUST BE THE FIRST UNIT TEST TO RUN! If any unit test run before this
/// one then it could fail. For dynamic levels all levels are turned on only AT
/// instantiation so we do different test for dynamic logging levels
///
/// TODO : (gtest issue)
///Move out to separate unit test binary to ensure reordering of tests does not happen
///Move out to separate unit test binary to ensure reordering of tests does not happen
#ifdef G3_DYNAMIC_LOGGING
TEST(Initialization, No_Logger_Initialized___LevelsAreONByDefault) {
EXPECT_FALSE(g3::internal::isLoggingInitialized());
@ -83,7 +83,7 @@ TEST(Initialization, No_Logger_Initialized___Expecting_LOG_calls_to_be_Still_OKi
auto content = logger.resetAndRetrieveContent(); // this synchronizes with the LOG(INFO) call if debug level would be ON.
ASSERT_TRUE(verifyContent(content, err_msg1)) << "Content: [" << content << "]";
ASSERT_FALSE(verifyContent(content, err_msg3_ignored)) << "Content: [" << content << "]";
ASSERT_TRUE(verifyContent(content, good_msg1)) << "Content: [" << content << "]";
ASSERT_TRUE(verifyContent(content, good_msg1)) << "Content: [" << content << "]";
}
#else
TEST(Initialization, No_Logger_Initialized___Expecting_LOG_calls_to_be_Still_OKish) {
@ -111,23 +111,38 @@ TEST(Initialization, No_Logger_Initialized___Expecting_LOG_calls_to_be_Still_OKi
ASSERT_TRUE(verifyContent(content, err_msg1)) << "Content: [" << content << "]";
ASSERT_FALSE(verifyContent(content, err_msg3_ignored)) << "Content: [" << content << "]";
ASSERT_TRUE(verifyContent(content, good_msg1)) << "Content: [" << content << "]";
}
}
#endif // #ifdef G3_DYNAMIC_LOGGING
TEST(Basics, Levels) {
TEST(Basics, Levels_StdFind) {
std::vector<LEVELS> levels = {INFO, WARNING, FATAL};
auto info = INFO;
auto warning = WARNING;
auto debug = DEBUG;
auto found_info = std::find(levels.begin(), levels.end(), info);
EXPECT_TRUE(found_info != levels.end());
auto found_warning = std::find(levels.begin(), levels.end(), WARNING);
EXPECT_TRUE(found_warning != levels.end());
auto not_found_debug = std::find(levels.begin(), levels.end(), DEBUG);
EXPECT_FALSE(not_found_debug!= levels.end());
EXPECT_NE(INFO, WARNING);
bool wasFound = (levels.end() != std::find(levels.begin(), levels.end(), info));
EXPECT_TRUE(wasFound);
auto wasNotFound = (levels.end() == std::find(levels.begin(), levels.end(), debug));
EXPECT_TRUE(wasNotFound);
auto foundWarningIterator = std::find(levels.begin(), levels.end(), WARNING);
EXPECT_TRUE(foundWarningIterator != levels.end());
foundWarningIterator = std::find(levels.begin(), levels.end(), warning);
EXPECT_TRUE(foundWarningIterator != levels.end());
auto wasNotFoundIterator = std::find(levels.begin(), levels.end(), DEBUG);
EXPECT_FALSE(wasNotFoundIterator != levels.end());
}
TEST(Basics, Levels_Operator) {
auto info = INFO;
auto warning = WARNING;
EXPECT_NE(INFO, WARNING);
EXPECT_EQ(info, INFO);
EXPECT_TRUE(INFO == INFO);
EXPECT_FALSE(info == WARNING);
@ -302,12 +317,13 @@ TEST(LogTest, LOG_preFatalLogging_hook) {
RestoreFileLogger logger(log_directory);
ASSERT_FALSE(mockFatalWasCalled());
g_fatal_counter.store(0);
g3::setFatalPreLoggingHook(fatalCounter);
g3::setFatalPreLoggingHook(fatalCounter);
LOG(FATAL) << "This message is fatal";
logger.reset();
EXPECT_EQ(g_fatal_counter.load(), size_t{1});
}
{ // Now with no fatal pre-logging-hook
{
// Now with no fatal pre-logging-hook
RestoreFileLogger logger(log_directory);
ASSERT_FALSE(mockFatalWasCalled());
g_fatal_counter.store(0);
@ -321,14 +337,14 @@ TEST(LogTest, LOG_preFatalLogging_hook) {
TEST(LogTest, LOG_FATAL) {
RestoreFileLogger logger(log_directory);
ASSERT_FALSE(mockFatalWasCalled());
LOG(FATAL) << "This message is fatal";
EXPECT_TRUE(mockFatalWasCalled());
EXPECT_TRUE(verifyContent(mockFatalMessage(), "EXIT trigger caused by "));
EXPECT_TRUE(verifyContent(mockFatalMessage(), "This message is fatal"))
<< "\ncontent: [[" << mockFatalMessage() << "]]";
<< "\ncontent: [[" << mockFatalMessage() << "]]";
EXPECT_TRUE(verifyContent(mockFatalMessage(), "FATAL"));
logger.reset();
@ -441,31 +457,31 @@ TEST(CHECK, CHECK_ThatWontThrow) {
TEST(CustomLogLevels, AddANonFatal){
TEST(CustomLogLevels, AddANonFatal) {
RestoreFileLogger logger(log_directory);
const LEVELS MYINFO {WARNING.value +1, {"MY_INFO_LEVEL"}};
#ifdef G3_DYNAMIC_LOGGING
const LEVELS MYINFO {WARNING.value + 1, {"MY_INFO_LEVEL"}};
#ifdef G3_DYNAMIC_LOGGING
g3::only_change_at_initialization::setLogLevel(MYINFO, true);
#endif
#endif
LOG(MYINFO) << "Testing my own custom level"; auto line = __LINE__;
logger.reset();
std::string file_content = readFileToText(logger.logFile());
std::string expected;
expected += "MY_INFO_LEVEL [test_io.cpp L: " + std::to_string(line);
EXPECT_TRUE(verifyContent(file_content, expected)) << file_content
<< "\n\nExpected: \n" << expected;
EXPECT_TRUE(verifyContent(file_content, expected)) << file_content
<< "\n\nExpected: \n" << expected;
}
TEST(CustomLogLevels, AddFatal){
TEST(CustomLogLevels, AddFatal) {
RestoreFileLogger logger(log_directory);
const LEVELS DEADLY {FATAL.value +1, {"DEADLY"}};
const LEVELS DEADLY {FATAL.value + 1, {"DEADLY"}};
EXPECT_TRUE(g3::internal::wasFatal(DEADLY));
g_fatal_counter.store(0);
ASSERT_FALSE(mockFatalWasCalled());
g3::setFatalPreLoggingHook(fatalCounter);
#ifdef G3_DYNAMIC_LOGGING
g3::setFatalPreLoggingHook(fatalCounter);
#ifdef G3_DYNAMIC_LOGGING
g3::only_change_at_initialization::setLogLevel(DEADLY, true);
#endif
#endif
LOG(DEADLY) << "Testing my own custom level"; auto line = __LINE__;
logger.reset();
@ -475,13 +491,13 @@ TEST(CustomLogLevels, AddFatal){
std::string file_content = readFileToText(logger.logFile());
std::string expected;
expected += "DEADLY [test_io.cpp L: " + std::to_string(line);
EXPECT_TRUE(verifyContent(file_content, expected)) << file_content
<< "\n\nExpected: \n" << expected;
EXPECT_TRUE(verifyContent(file_content, expected)) << file_content
<< "\n\nExpected: \n" << expected;
g_fatal_counter.store(0); // restore
}
#ifdef G3_DYNAMIC_LOGGING
#ifdef G3_DYNAMIC_LOGGING
namespace {
// Restore dynamic levels if turned off
@ -499,9 +515,9 @@ namespace {
} // anonymous
TEST(CustomLogLevels, AddANonFatal__ThenReset){
TEST(CustomLogLevels, AddANonFatal__ThenReset) {
RestoreFileLogger logger(log_directory);
const LEVELS MYINFO {WARNING.value +2, {"MY_INFO_LEVEL"}};
const LEVELS MYINFO {WARNING.value + 2, {"MY_INFO_LEVEL"}};
EXPECT_FALSE(g3::logLevel(MYINFO));
g3::only_change_at_initialization::setLogLevel(MYINFO, true);
EXPECT_TRUE(g3::logLevel(MYINFO));
@ -510,22 +526,22 @@ TEST(CustomLogLevels, AddANonFatal__ThenReset){
}
TEST(CustomLogLevels, AddANonFatal__DidNotAddItToEnabledValue1){
TEST(CustomLogLevels, AddANonFatal__DidNotAddItToEnabledValue1) {
RestoreFileLogger logger(log_directory);
const LEVELS MYINFO {WARNING.value +2, {"MY_INFO_LEVEL"}};
const LEVELS MYINFO {WARNING.value + 2, {"MY_INFO_LEVEL"}};
LOG(MYINFO) << "Testing my own custom level"; auto line = __LINE__;
logger.reset();
std::string file_content = readFileToText(logger.logFile());
std::string expected;
expected += "MY_INFO_LEVEL [test_io.cpp L: " + std::to_string(line);
EXPECT_FALSE(verifyContent(file_content, expected)) << file_content
<< "\n\nExpected: \n" << expected << "\nLevels:\n" << g3::only_change_at_initialization::printLevels();
EXPECT_FALSE(verifyContent(file_content, expected)) << file_content
<< "\n\nExpected: \n" << expected << "\nLevels:\n" << g3::only_change_at_initialization::printLevels();
}
TEST(CustomLogLevels, AddANonFatal__DidNotAddItToEnabledValue2){
TEST(CustomLogLevels, AddANonFatal__DidNotAddItToEnabledValue2) {
RestoreFileLogger logger(log_directory);
const LEVELS MYINFO {WARNING.value +2, {"MY_INFO_LEVEL"}};
const LEVELS MYINFO {WARNING.value + 2, {"MY_INFO_LEVEL"}};
EXPECT_FALSE(g3::logLevel(MYINFO));
LOG(MYINFO) << "Testing my own custom level"; auto line = __LINE__;
logger.reset();
@ -533,21 +549,21 @@ TEST(CustomLogLevels, AddANonFatal__DidNotAddItToEnabledValue2){
std::string file_content = readFileToText(logger.logFile());
std::string expected;
expected += "MY_INFO_LEVEL [test_io.cpp L: " + std::to_string(line);
EXPECT_FALSE(verifyContent(file_content, expected)) << file_content
<< "\n\nExpected: \n" << expected << "\nLevels:\n" << g3::only_change_at_initialization::printLevels();
EXPECT_FALSE(verifyContent(file_content, expected)) << file_content
<< "\n\nExpected: \n" << expected << "\nLevels:\n" << g3::only_change_at_initialization::printLevels();
}
TEST(CustomLogLevels, AddANonFatal__DidtAddItToEnabledValue){
TEST(CustomLogLevels, AddANonFatal__DidtAddItToEnabledValue) {
RestoreFileLogger logger(log_directory);
const LEVELS MYINFO {WARNING.value +3, {"MY_INFO_LEVEL"}};
const LEVELS MYINFO {WARNING.value + 3, {"MY_INFO_LEVEL"}};
g3::only_change_at_initialization::setLogLevel(MYINFO, true);
LOG(MYINFO) << "Testing my own custom level"; auto line = __LINE__;
logger.reset();
std::string file_content = readFileToText(logger.logFile());
std::string expected;
expected += "MY_INFO_LEVEL [test_io.cpp L: " + std::to_string(line);
EXPECT_TRUE(verifyContent(file_content, expected)) << file_content
<< "\n\nExpected: \n" << expected;
EXPECT_TRUE(verifyContent(file_content, expected)) << file_content
<< "\n\nExpected: \n" << expected;
}
@ -584,7 +600,7 @@ TEST(DynamicLogging, DynamicLogging_IS_ENABLED) {
}
TEST(DynamicLogging, DynamicLogging_No_Logs_If_Disabled) {
{
RestoreFileLogger logger(log_directory);
RestoreFileLogger logger(log_directory);
ASSERT_TRUE(g3::logLevel(DEBUG));
ASSERT_TRUE(g3::logLevel(INFO));
ASSERT_TRUE(g3::logLevel(WARNING));
@ -592,16 +608,16 @@ TEST(DynamicLogging, DynamicLogging_No_Logs_If_Disabled) {
}
RestoreDynamicLoggingLevels raiiLevelRestore;
std::string msg_debugOn = "This %s SHOULD appear in the %s";
std::string msg_debugOff = "This message should never appear in the log";
std::string msg_info1 = "This info msg log";
try {
{
RestoreFileLogger logger(log_directory);
LOGF(DEBUG, msg_debugOn.c_str(), "msg", "log");
auto content = logger.resetAndRetrieveContent();
ASSERT_TRUE(verifyContent(content, "This msg SHOULD appear in the log")) << "Content: [" << content << "]";
RestoreFileLogger logger(log_directory);
LOGF(DEBUG, msg_debugOn.c_str(), "msg", "log");
auto content = logger.resetAndRetrieveContent();
ASSERT_TRUE(verifyContent(content, "This msg SHOULD appear in the log")) << "Content: [" << content << "]";
}
{
@ -612,8 +628,8 @@ TEST(DynamicLogging, DynamicLogging_No_Logs_If_Disabled) {
auto content = logger.resetAndRetrieveContent();
ASSERT_FALSE(verifyContent(content, "This message should never appear in the log")) << "Content: [" << content << "]";
}
} catch (std::exception const &e) {
} catch (std::exception const& e) {
std::cerr << e.what() << std::endl;
ADD_FAILURE() << "Should never have thrown";
}
@ -632,11 +648,11 @@ TEST(DynamicLogging, DynamicLogging_No_Fatal_If_Disabled) {
EXPECT_TRUE(mockFatalWasCalled());
EXPECT_FALSE(mockFatalMessage().empty());
EXPECT_TRUE(verifyContent(mockFatalMessage(), msg1));
clearMockFatal();
EXPECT_FALSE(mockFatalWasCalled());
g3::only_change_at_initialization::setLogLevel(FATAL, false);
std::string msg3 = "This is NOT fatal (not crash, since it is unit test. FATAL is disabled";
LOG(FATAL) << msg3;
@ -655,10 +671,10 @@ TEST(DynamicLogging, DynamicLogging_Check_WillAlsoBeTurnedOffWhen_Fatal_Is_Disab
LOG(FATAL) << msg1;
EXPECT_TRUE(mockFatalWasCalled());
EXPECT_TRUE(verifyContent(mockFatalMessage(), msg1));
clearMockFatal();
EXPECT_FALSE(mockFatalWasCalled());
// Disable also CHECK calls
g3::only_change_at_initialization::setLogLevel(FATAL, false);
ASSERT_FALSE(g3::logLevel(FATAL));
@ -669,7 +685,7 @@ TEST(DynamicLogging, DynamicLogging_Check_WillAlsoBeTurnedOffWhen_Fatal_Is_Disab
#else
#else
TEST(DynamicLogging, DynamicLogging_IS_NOT_ENABLED) {
ASSERT_TRUE(g3::logLevel(DEBUG));
//g3::setLogLevel(DEBUG, false); this line will not compile since G3_DYNAMIC_LOGGING is not enabled. Kept for show.