Add test cases for logging

This commit is contained in:
Sebastian Meßmer 2015-10-17 15:49:54 +02:00
parent 02c49d986b
commit 9f9b4fc342
6 changed files with 298 additions and 2 deletions

View File

@ -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);
};

View File

@ -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();

View 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());
}

View 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();
}

View 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.*"));
}

View 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