Add test cases for logging
This commit is contained in:
parent
02c49d986b
commit
9f9b4fc342
@ -9,10 +9,19 @@ namespace cpputils {
|
||||
namespace logging {
|
||||
class Logger {
|
||||
public:
|
||||
Logger() : _logger(spdlog::stdout_logger_mt("Log")) { }
|
||||
|
||||
void setLogger(std::shared_ptr<spdlog::logger> logger) {
|
||||
_logger = logger;
|
||||
_logger->set_level(_level);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
_level = spdlog::level::info;
|
||||
setLogger(_defaultLogger());
|
||||
}
|
||||
|
||||
void setLevel(spdlog::level::level_enum level) {
|
||||
_level = level;
|
||||
_logger->set_level(_level);
|
||||
}
|
||||
|
||||
spdlog::logger *operator->() {
|
||||
@ -20,7 +29,19 @@ namespace logging {
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static std::shared_ptr<spdlog::logger> _defaultLogger() {
|
||||
static std::shared_ptr<spdlog::logger> singleton = spdlog::stdout_logger_mt("Log");
|
||||
return singleton;
|
||||
}
|
||||
|
||||
Logger() : _logger(), _level() {
|
||||
reset();
|
||||
}
|
||||
friend Logger &logger();
|
||||
|
||||
std::shared_ptr<spdlog::logger> _logger;
|
||||
spdlog::level::level_enum _level;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Logger);
|
||||
};
|
||||
|
@ -17,6 +17,20 @@ namespace cpputils {
|
||||
logger().setLogger(newLogger);
|
||||
}
|
||||
|
||||
inline void reset() {
|
||||
logger().reset();
|
||||
}
|
||||
|
||||
inline void setLevel(Level level) {
|
||||
switch(level) {
|
||||
case ERROR: logger().setLevel(spdlog::level::err); return;
|
||||
case WARN: logger().setLevel(spdlog::level::warn); return;
|
||||
case INFO: logger().setLevel(spdlog::level::info); return;
|
||||
case DEBUG: logger().setLevel(spdlog::level::debug); return;
|
||||
}
|
||||
throw std::logic_error("Unknown logger level");
|
||||
}
|
||||
|
||||
inline spdlog::details::line_logger LOG(Level level) {
|
||||
switch(level) {
|
||||
case ERROR: return logger()->error();
|
||||
|
20
test/logging/LoggerTest.cpp
Normal file
20
test/logging/LoggerTest.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
#include "testutils/LoggingTest.h"
|
||||
|
||||
/*
|
||||
* Contains test cases for the Logger class
|
||||
*/
|
||||
|
||||
using namespace cpputils::logging;
|
||||
using std::string;
|
||||
using testing::MatchesRegex;
|
||||
|
||||
class LoggerTest: public LoggingTest {};
|
||||
|
||||
TEST_F(LoggerTest, IsSingleton) {
|
||||
ASSERT_EQ(&logger(), &logger());
|
||||
}
|
||||
|
||||
TEST_F(LoggerTest, SetLogger) {
|
||||
logger().setLogger(spdlog::stdout_logger_mt("MyTestLog1"));
|
||||
EXPECT_EQ("MyTestLog1", logger()->name());
|
||||
}
|
128
test/logging/LoggingLevelTest.cpp
Normal file
128
test/logging/LoggingLevelTest.cpp
Normal file
@ -0,0 +1,128 @@
|
||||
#include "testutils/LoggingTest.h"
|
||||
|
||||
using namespace cpputils::logging;
|
||||
using std::string;
|
||||
using testing::MatchesRegex;
|
||||
|
||||
class LoggingLevelTest: public LoggingTest {
|
||||
public:
|
||||
void EXPECT_DEBUG_LOG_ENABLED() {
|
||||
LOG(DEBUG) << "My log message";
|
||||
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[debug\\].*My log message.*"));
|
||||
}
|
||||
|
||||
void EXPECT_DEBUG_LOG_DISABLED() {
|
||||
LOG(DEBUG) << "My log message";
|
||||
EXPECT_EQ("", mockLogger.capturedLog());
|
||||
}
|
||||
|
||||
void EXPECT_INFO_LOG_ENABLED() {
|
||||
LOG(INFO) << "My log message";
|
||||
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[info\\].*My log message.*"));
|
||||
}
|
||||
|
||||
void EXPECT_INFO_LOG_DISABLED() {
|
||||
LOG(INFO) << "My log message";
|
||||
EXPECT_EQ("", mockLogger.capturedLog());
|
||||
}
|
||||
|
||||
void EXPECT_WARNING_LOG_ENABLED() {
|
||||
LOG(WARN) << "My log message";
|
||||
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[warning\\].*My log message.*"));
|
||||
}
|
||||
|
||||
void EXPECT_WARNING_LOG_DISABLED() {
|
||||
LOG(WARN) << "My log message";
|
||||
EXPECT_EQ("", mockLogger.capturedLog());
|
||||
}
|
||||
|
||||
void EXPECT_ERROR_LOG_ENABLED() {
|
||||
LOG(ERROR) << "My log message";
|
||||
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[error\\].*My log message.*"));
|
||||
}
|
||||
|
||||
void EXPECT_ERROR_LOG_DISABLED() {
|
||||
LOG(ERROR) << "My log message";
|
||||
EXPECT_EQ("", mockLogger.capturedLog());
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(LoggingLevelTest, DefaultLevelIsInfo) {
|
||||
setLogger(mockLogger.get());
|
||||
EXPECT_DEBUG_LOG_DISABLED();
|
||||
EXPECT_INFO_LOG_ENABLED();
|
||||
EXPECT_WARNING_LOG_ENABLED();
|
||||
EXPECT_ERROR_LOG_ENABLED();
|
||||
}
|
||||
|
||||
TEST_F(LoggingLevelTest, DEBUG_SetBeforeSettingLogger) {
|
||||
setLevel(DEBUG);
|
||||
setLogger(mockLogger.get());
|
||||
EXPECT_DEBUG_LOG_ENABLED();
|
||||
EXPECT_INFO_LOG_ENABLED();
|
||||
EXPECT_WARNING_LOG_ENABLED();
|
||||
EXPECT_ERROR_LOG_ENABLED();
|
||||
}
|
||||
|
||||
TEST_F(LoggingLevelTest, DEBUG_SetAfterSettingLogger) {
|
||||
setLogger(mockLogger.get());
|
||||
setLevel(DEBUG);
|
||||
EXPECT_DEBUG_LOG_ENABLED();
|
||||
EXPECT_INFO_LOG_ENABLED();
|
||||
EXPECT_WARNING_LOG_ENABLED();
|
||||
EXPECT_ERROR_LOG_ENABLED();
|
||||
}
|
||||
|
||||
TEST_F(LoggingLevelTest, INFO_SetBeforeSettingLogger) {
|
||||
setLevel(INFO);
|
||||
setLogger(mockLogger.get());
|
||||
EXPECT_DEBUG_LOG_DISABLED();
|
||||
EXPECT_INFO_LOG_ENABLED();
|
||||
EXPECT_WARNING_LOG_ENABLED();
|
||||
EXPECT_ERROR_LOG_ENABLED();
|
||||
}
|
||||
|
||||
TEST_F(LoggingLevelTest, INFO_SetAfterSettingLogger) {
|
||||
setLogger(mockLogger.get());
|
||||
setLevel(INFO);
|
||||
EXPECT_DEBUG_LOG_DISABLED();
|
||||
EXPECT_INFO_LOG_ENABLED();
|
||||
EXPECT_WARNING_LOG_ENABLED();
|
||||
EXPECT_ERROR_LOG_ENABLED();
|
||||
}
|
||||
|
||||
TEST_F(LoggingLevelTest, WARNING_SetBeforeSettingLogger) {
|
||||
setLevel(WARN);
|
||||
setLogger(mockLogger.get());
|
||||
EXPECT_DEBUG_LOG_DISABLED();
|
||||
EXPECT_INFO_LOG_DISABLED();
|
||||
EXPECT_WARNING_LOG_ENABLED();
|
||||
EXPECT_ERROR_LOG_ENABLED();
|
||||
}
|
||||
|
||||
TEST_F(LoggingLevelTest, WARNING_SetAfterSettingLogger) {
|
||||
setLogger(mockLogger.get());
|
||||
setLevel(WARN);
|
||||
EXPECT_DEBUG_LOG_DISABLED();
|
||||
EXPECT_INFO_LOG_DISABLED();
|
||||
EXPECT_WARNING_LOG_ENABLED();
|
||||
EXPECT_ERROR_LOG_ENABLED();
|
||||
}
|
||||
|
||||
TEST_F(LoggingLevelTest, ERROR_SetBeforeSettingLogger) {
|
||||
setLevel(ERROR);
|
||||
setLogger(mockLogger.get());
|
||||
EXPECT_DEBUG_LOG_DISABLED();
|
||||
EXPECT_INFO_LOG_DISABLED();
|
||||
EXPECT_WARNING_LOG_DISABLED();
|
||||
EXPECT_ERROR_LOG_ENABLED();
|
||||
}
|
||||
|
||||
TEST_F(LoggingLevelTest, ERROR_SetAfterSettingLogger) {
|
||||
setLogger(mockLogger.get());
|
||||
setLevel(ERROR);
|
||||
EXPECT_DEBUG_LOG_DISABLED();
|
||||
EXPECT_INFO_LOG_DISABLED();
|
||||
EXPECT_WARNING_LOG_DISABLED();
|
||||
EXPECT_ERROR_LOG_ENABLED();
|
||||
}
|
64
test/logging/LoggingTest.cpp
Normal file
64
test/logging/LoggingTest.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
#include "testutils/LoggingTest.h"
|
||||
|
||||
/*
|
||||
* Contains test cases for the following logging interface:
|
||||
* LOG(INFO) << "My log message"
|
||||
*/
|
||||
|
||||
using namespace cpputils::logging;
|
||||
using std::string;
|
||||
using testing::MatchesRegex;
|
||||
|
||||
TEST_F(LoggingTest, DefaultLoggerIsStdout) {
|
||||
string output = captureStdout([]{
|
||||
LOG(INFO) << "My log message";
|
||||
});
|
||||
EXPECT_THAT(output, MatchesRegex(".*\\[Log\\].*\\[info\\].*My log message.*"));
|
||||
}
|
||||
|
||||
TEST_F(LoggingTest, SetLogger_NewLoggerIsUsed) {
|
||||
setLogger(spdlog::stdout_logger_mt("MyTestLog2"));
|
||||
string output = captureStdout([]{
|
||||
LOG(INFO) << "My log message";
|
||||
});
|
||||
EXPECT_THAT(output, MatchesRegex(".*\\[MyTestLog2\\].*\\[info\\].*My log message.*"));
|
||||
}
|
||||
|
||||
TEST_F(LoggingTest, SetNonStdoutLogger_LogsToNewLogger) {
|
||||
setLogger(mockLogger.get());
|
||||
logger()->info() << "My log message";
|
||||
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[info\\].*My log message.*"));
|
||||
}
|
||||
|
||||
TEST_F(LoggingTest, SetNonStdoutLogger_DoesNotLogToStdout) {
|
||||
setLogger(mockLogger.get());
|
||||
string output = captureStdout([] {
|
||||
logger()->info() << "My log message";
|
||||
});
|
||||
EXPECT_EQ("", output);
|
||||
}
|
||||
|
||||
TEST_F(LoggingTest, InfoLog) {
|
||||
setLogger(mockLogger.get());
|
||||
LOG(INFO) << "My log message";
|
||||
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[info\\].*My log message.*"));
|
||||
}
|
||||
|
||||
TEST_F(LoggingTest, WarningLog) {
|
||||
setLogger(mockLogger.get());
|
||||
LOG(WARN) << "My log message";
|
||||
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[warning\\].*My log message.*"));
|
||||
}
|
||||
|
||||
TEST_F(LoggingTest, DebugLog) {
|
||||
setLevel(DEBUG);
|
||||
setLogger(mockLogger.get());
|
||||
LOG(DEBUG) << "My log message";
|
||||
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[debug\\].*My log message.*"));
|
||||
}
|
||||
|
||||
TEST_F(LoggingTest, ErrorLog) {
|
||||
setLogger(mockLogger.get());
|
||||
LOG(ERROR) << "My log message";
|
||||
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[error\\].*My log message.*"));
|
||||
}
|
49
test/logging/testutils/LoggingTest.h
Normal file
49
test/logging/testutils/LoggingTest.h
Normal file
@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
#ifndef MESSMER_CPPUTILS_TEST_LOGGING_TESTUTILS_LOGGINGTEST_H
|
||||
#define MESSMER_CPPUTILS_TEST_LOGGING_TESTUTILS_LOGGINGTEST_H
|
||||
|
||||
#include <google/gtest/gtest.h>
|
||||
#include <google/gmock/gmock.h>
|
||||
#include "../../../logging/logging.h"
|
||||
|
||||
class MockLogger final {
|
||||
public:
|
||||
MockLogger():
|
||||
_capturedLogData(),
|
||||
_sink(std::make_shared<spdlog::sinks::ostream_sink<std::mutex>>(_capturedLogData, true)),
|
||||
_logger(std::make_shared<spdlog::logger>("MockLogger", _sink)) {
|
||||
}
|
||||
|
||||
~MockLogger() {
|
||||
spdlog::drop("MockLogger");
|
||||
};
|
||||
|
||||
std::shared_ptr<spdlog::logger> get() {
|
||||
return _logger;
|
||||
}
|
||||
|
||||
std::string capturedLog() const {
|
||||
return _capturedLogData.str();
|
||||
}
|
||||
private:
|
||||
std::ostringstream _capturedLogData;
|
||||
std::shared_ptr<spdlog::sinks::ostream_sink<std::mutex>> _sink;
|
||||
std::shared_ptr<spdlog::logger> _logger;
|
||||
};
|
||||
|
||||
class LoggingTest: public ::testing::Test {
|
||||
public:
|
||||
std::string captureStdout(std::function<void()> func) {
|
||||
testing::internal::CaptureStdout();
|
||||
func();
|
||||
return testing::internal::GetCapturedStdout();
|
||||
}
|
||||
|
||||
~LoggingTest() {
|
||||
cpputils::logging::reset();
|
||||
}
|
||||
|
||||
MockLogger mockLogger;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user