Adds StringTraits::Literal variants that work with strings. Names the workspace CPPUtils to match the import name in TinyTest. This resolves the dependency issue.
807 lines
38 KiB
C++
807 lines
38 KiB
C++
/**********************************************************************************************************************
|
|
* *
|
|
* @file logger_test.h *
|
|
* *
|
|
* @brief Defines tests for the Logger class declared in logger.h. *
|
|
* @copyright Copyright (C) 2023 by Tom Hicks <headhunter3@gmail.com> *
|
|
* *
|
|
* Licensed under the MIT license see below for details. *
|
|
* *
|
|
* MIT License *
|
|
* *
|
|
* Copyright (c) 2023 Tom Hicks <headhunter3@gmail.com> *
|
|
* *
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated *
|
|
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation *
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and *
|
|
* to permit persons to whom the Software is furnished to do so, subject to the following conditions: *
|
|
* *
|
|
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of *
|
|
* the Software. *
|
|
* *
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO *
|
|
* THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
|
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS *
|
|
* IN THE SOFTWARE. *
|
|
* *
|
|
**********************************************************************************************************************/
|
|
#include "logger.h"
|
|
|
|
#include <iostream>
|
|
#include <memory>
|
|
#include <optional>
|
|
#include <sstream>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
#include <tuple>
|
|
#include <vector>
|
|
|
|
#include "tinytest.h"
|
|
|
|
namespace {
|
|
using CPPUtils::Logger;
|
|
using std::cout;
|
|
using std::endl;
|
|
using std::get;
|
|
using std::make_optional;
|
|
using std::make_shared;
|
|
using std::make_tuple;
|
|
using std::nullopt;
|
|
using std::optional;
|
|
using std::ostream;
|
|
using std::ostringstream;
|
|
using std::runtime_error;
|
|
using std::shared_ptr;
|
|
using std::string;
|
|
using std::tuple;
|
|
using std::vector;
|
|
using TinyTest::ExecuteSuite;
|
|
using TinyTest::MakeTest;
|
|
using TinyTest::MakeTestSuite;
|
|
using TinyTest::TestResults;
|
|
|
|
string no_errors = "no errors";
|
|
typedef tuple<Logger::MessageType, optional<string>, optional<string>> LogEntry;
|
|
|
|
class SpyLoggerDestination : public Logger::Destination {
|
|
public:
|
|
SpyLoggerDestination() {
|
|
min_type_ = Logger::MessageType::Unknown;
|
|
max_type_ = Logger::MessageType::Wtf;
|
|
}
|
|
|
|
virtual ~SpyLoggerDestination() {}
|
|
|
|
virtual void LogMessage(const Logger::MessageType &type, const std::string &message) const {
|
|
log.push_back(make_tuple(type, message, nullopt));
|
|
}
|
|
|
|
virtual void LogError(const Logger::MessageType &type, const std::exception &ex) const {
|
|
log.push_back(make_tuple(type, nullopt, ex.what()));
|
|
}
|
|
|
|
virtual void LogError(const Logger::MessageType &type, const std::string &message, const std::exception &ex) const {
|
|
log.push_back(make_tuple(type, message, ex.what()));
|
|
}
|
|
|
|
mutable vector<LogEntry> log;
|
|
};
|
|
|
|
template <typename T> ostream &PrintOptional(ostream &os, optional<T> op) {
|
|
if (op.has_value()) {
|
|
os << op.value();
|
|
} else {
|
|
os << "nullopt";
|
|
}
|
|
return os;
|
|
}
|
|
|
|
void ExpectMessageType(ostream &error_message, const Logger::MessageType &expected, const LogEntry &log_entry) {
|
|
Logger::MessageType actual = get<0>(log_entry);
|
|
if (actual != expected) {
|
|
error_message << "Unexpected MessageType expected: " << expected << ", actual: " << actual << endl;
|
|
}
|
|
}
|
|
|
|
void ExpectMessageText(ostream &error_message, optional<string> expected, const LogEntry &log_entry) {
|
|
optional<string> actual = get<1>(log_entry);
|
|
if (actual != expected) {
|
|
error_message << "Unexpected message text. Expected: ";
|
|
PrintOptional(error_message, expected) << ", Actual: ";
|
|
PrintOptional(error_message, actual) << endl;
|
|
}
|
|
}
|
|
|
|
void ExpectMessageException(ostream &error_message, optional<string> expected, const LogEntry &log_entry) {
|
|
optional<string> actual = get<2>(log_entry);
|
|
if (actual != expected) {
|
|
error_message << "Unexpected message exception. Expected: ";
|
|
PrintOptional(error_message, expected) << ", Actual: ";
|
|
PrintOptional(error_message, actual) << endl;
|
|
}
|
|
}
|
|
|
|
void ExpectLogSize(ostream &error_message, size_t expected, shared_ptr<SpyLoggerDestination> destination) {
|
|
size_t actual = destination->log.size();
|
|
if (actual != expected) {
|
|
error_message << "Unexpected number of events logged. Expected: " << expected << ", Actual: " << actual << endl;
|
|
}
|
|
}
|
|
|
|
string GetError(ostringstream &error_message) {
|
|
string error = error_message.str();
|
|
if (error.size() > 0) {
|
|
return error;
|
|
}
|
|
return no_errors;
|
|
}
|
|
} // End namespace
|
|
|
|
TestResults test_Destination_TypeRangeGettersAndSetters() {
|
|
TestResults results;
|
|
auto set_min_type = [](const Logger::MessageType &type) {
|
|
auto spy = make_shared<SpyLoggerDestination>();
|
|
if (type == Logger::MessageType::Unknown) {
|
|
spy->SetMinType(Logger::MessageType::Debug);
|
|
} else {
|
|
spy->SetMinType(Logger::MessageType::Unknown);
|
|
}
|
|
spy->SetMinType(type);
|
|
return spy->GetMinType();
|
|
};
|
|
results += ExecuteSuite(MakeTestSuite(
|
|
"CPPUtils::Logger::SetMinType(const MessageType&)",
|
|
set_min_type,
|
|
{
|
|
MakeTest(
|
|
"should set min type to Unknown", Logger::MessageType::Unknown, make_tuple(Logger::MessageType::Unknown)),
|
|
MakeTest("should set min type to Debug", Logger::MessageType::Debug, make_tuple(Logger::MessageType::Debug)),
|
|
MakeTest(
|
|
"should set min type to Verbose", Logger::MessageType::Verbose, make_tuple(Logger::MessageType::Verbose)),
|
|
MakeTest("should set min type to Info", Logger::MessageType::Info, make_tuple(Logger::MessageType::Info)),
|
|
MakeTest(
|
|
"should set min type to Warning", Logger::MessageType::Warning, make_tuple(Logger::MessageType::Warning)),
|
|
MakeTest("should set min type to Error", Logger::MessageType::Error, make_tuple(Logger::MessageType::Error)),
|
|
MakeTest("should set min type to Wtf", Logger::MessageType::Wtf, make_tuple(Logger::MessageType::Wtf)),
|
|
MakeTest("should set min type to Unknown for an invalid MessageType",
|
|
Logger::MessageType::Unknown,
|
|
(make_tuple((Logger::MessageType)-1))),
|
|
}));
|
|
auto set_max_type = [](const Logger::MessageType &type) {
|
|
auto spy = make_shared<SpyLoggerDestination>();
|
|
if (type == Logger::MessageType::Unknown) {
|
|
spy->SetMaxType(Logger::MessageType::Debug);
|
|
} else {
|
|
spy->SetMaxType(Logger::MessageType::Unknown);
|
|
}
|
|
spy->SetMaxType(type);
|
|
return spy->GetMaxType();
|
|
};
|
|
results += ExecuteSuite(MakeTestSuite(
|
|
"CPPUtils::Logger::SetMaxType(const MessageType&)",
|
|
set_max_type,
|
|
{
|
|
MakeTest(
|
|
"should set max type to Unknown", Logger::MessageType::Unknown, make_tuple(Logger::MessageType::Unknown)),
|
|
MakeTest("should set max type to Debug", Logger::MessageType::Debug, make_tuple(Logger::MessageType::Debug)),
|
|
MakeTest(
|
|
"should set max type to Verbose", Logger::MessageType::Verbose, make_tuple(Logger::MessageType::Verbose)),
|
|
MakeTest("should set max type to Info", Logger::MessageType::Info, make_tuple(Logger::MessageType::Info)),
|
|
MakeTest(
|
|
"should set max type to Warning", Logger::MessageType::Warning, make_tuple(Logger::MessageType::Warning)),
|
|
MakeTest("should set max type to Error", Logger::MessageType::Error, make_tuple(Logger::MessageType::Error)),
|
|
MakeTest("should set max type to Wtf", Logger::MessageType::Wtf, make_tuple(Logger::MessageType::Wtf)),
|
|
MakeTest("should set max type to Unknown for an invalid MessageType",
|
|
Logger::MessageType::Unknown,
|
|
(make_tuple((Logger::MessageType)-1))),
|
|
}));
|
|
return results;
|
|
}
|
|
|
|
TestResults test_Logger_GetShared() {
|
|
auto function_to_test = []() {
|
|
auto first = Logger::GetShared();
|
|
auto second = Logger::GetShared();
|
|
return first == second;
|
|
};
|
|
return ExecuteSuite(MakeTestSuite("CPPUtils::Logger::GetShared()",
|
|
function_to_test,
|
|
{
|
|
MakeTest("should get the same instance twice", true, make_tuple()),
|
|
}));
|
|
}
|
|
|
|
TestResults test_Logger_GetUnique() {
|
|
auto get_unique_is_different = []() {
|
|
auto first = Logger::GetUnique();
|
|
auto second = Logger::GetUnique();
|
|
return first != second;
|
|
};
|
|
|
|
auto get_unique_is_not_get_shared = []() {
|
|
auto shared = Logger::GetShared();
|
|
auto unique = Logger::GetUnique();
|
|
return unique != shared;
|
|
};
|
|
|
|
TestResults results;
|
|
|
|
results += ExecuteSuite(MakeTestSuite("CPPUtils::Logger::GetUnique()",
|
|
get_unique_is_different,
|
|
{
|
|
MakeTest("should get two different instances", true, make_tuple()),
|
|
}));
|
|
|
|
results += ExecuteSuite(
|
|
MakeTestSuite("CPPUtils::Logger::GetUnique()",
|
|
get_unique_is_not_get_shared,
|
|
{
|
|
MakeTest("should get and instance that is not the shared instance", true, make_tuple()),
|
|
}));
|
|
|
|
return results;
|
|
}
|
|
|
|
TestResults test_LogUnimplementedMethod() {
|
|
#if __cplusplus >= 202002L
|
|
return TestResults().fail("Not implemented for c++20 yet.");
|
|
|
|
ostringstream error_message;
|
|
error_message << "Unimplemented method: \"" << location.function_name() << "\" at " << location.file_name() << " ("
|
|
<< location.line() << ":" << location.column() << ")";
|
|
LogDebug(error_message.str());
|
|
// TODO: see what this results in when run in c++20 and test for those values.
|
|
#else
|
|
auto function_to_test = [](string method_name) -> string {
|
|
auto spy = make_shared<SpyLoggerDestination>();
|
|
auto logger = Logger::GetUnique();
|
|
logger->AddDestination(spy);
|
|
#if __cplusplus >= 202002L
|
|
std::source_location loc;
|
|
logger->LogUnimplementedMethod()
|
|
#else
|
|
logger->LogUnimplementedMethodReal(method_name);
|
|
#endif
|
|
ostringstream error_message;
|
|
ExpectLogSize(error_message, 1, spy);
|
|
if (spy->log.size() > 0) {
|
|
auto message = spy->log.at(0);
|
|
ExpectMessageType(error_message, Logger::MessageType::Debug, message);
|
|
ExpectMessageText(error_message, "Unimplemented method: int main(int argc, char* argv[])", message);
|
|
ExpectMessageException(error_message, nullopt, message);
|
|
}
|
|
return GetError(error_message);
|
|
};
|
|
return ExecuteSuite(MakeTestSuite(
|
|
"CPPUtils::Logger::LogUnimplementedMethod",
|
|
function_to_test,
|
|
{
|
|
MakeTest("should log a debug message", no_errors, make_tuple("int main(int argc, char* argv[])")),
|
|
}));
|
|
#endif
|
|
}
|
|
|
|
TestResults test_Logger_LogUnhandledError() {
|
|
auto log_unhandled_error = []() {
|
|
auto logger = Logger::GetUnique();
|
|
auto spy = make_shared<SpyLoggerDestination>();
|
|
logger->AddDestination(spy);
|
|
std::exception ex;
|
|
logger->LogUnhandledError(ex);
|
|
ostringstream error_message;
|
|
ExpectLogSize(error_message, 1, spy);
|
|
if (spy->log.size() > 0) {
|
|
auto message = spy->log.at(0);
|
|
ExpectMessageType(error_message, Logger::MessageType::Debug, message);
|
|
ExpectMessageText(error_message, "Unhandled exception", message);
|
|
ExpectMessageException(error_message, ex.what(), message);
|
|
}
|
|
return GetError(error_message);
|
|
};
|
|
return ExecuteSuite(MakeTestSuite("CPPUtils::Logger::LogUnhandledError(const std::exception&)",
|
|
log_unhandled_error,
|
|
{
|
|
MakeTest("should log an error", no_errors, make_tuple()),
|
|
}));
|
|
}
|
|
|
|
TestResults test_Logger_LogUnimplementedFeature() {
|
|
auto log_unimplemented_feature = []() {
|
|
auto logger = Logger::GetUnique();
|
|
auto spy = make_shared<SpyLoggerDestination>();
|
|
logger->AddDestination(spy);
|
|
string feature_name = "rolling over";
|
|
logger->LogUnimplementedFeature(feature_name);
|
|
ostringstream error_message;
|
|
ExpectLogSize(error_message, 1, spy);
|
|
if (spy->log.size() > 0) {
|
|
auto message = spy->log.at(0);
|
|
ExpectMessageType(error_message, Logger::MessageType::Debug, message);
|
|
ExpectMessageText(error_message, "Unimplemented feature: " + feature_name, message);
|
|
ExpectMessageException(error_message, nullopt, message);
|
|
}
|
|
return GetError(error_message);
|
|
};
|
|
return ExecuteSuite(MakeTestSuite("CPPUtils::Logger::LogUnimplementedFeature()",
|
|
log_unimplemented_feature,
|
|
{
|
|
MakeTest("should log an unimplemented feature", no_errors, make_tuple()),
|
|
}));
|
|
}
|
|
|
|
TestResults test_Logger_Log_Level() {
|
|
auto log = [](const Logger::MessageType &type,
|
|
const optional<string> &message_text,
|
|
const optional<std::exception> &ex) -> string {
|
|
ostringstream error_message;
|
|
auto logger = Logger::GetUnique();
|
|
auto spy = make_shared<SpyLoggerDestination>();
|
|
logger->AddDestination(spy);
|
|
switch (type) {
|
|
case Logger::MessageType::Debug:
|
|
if (message_text.has_value()) {
|
|
if (ex.has_value()) {
|
|
logger->LogDebug(message_text.value(), ex.value());
|
|
} else {
|
|
logger->LogDebug(message_text.value());
|
|
}
|
|
} else {
|
|
if (ex.has_value()) {
|
|
logger->LogDebug(ex.value());
|
|
}
|
|
}
|
|
break;
|
|
case Logger::MessageType::Verbose:
|
|
if (message_text.has_value()) {
|
|
if (ex.has_value()) {
|
|
logger->LogVerbose(message_text.value(), ex.value());
|
|
} else {
|
|
logger->LogVerbose(message_text.value());
|
|
}
|
|
} else {
|
|
if (ex.has_value()) {
|
|
logger->LogVerbose(ex.value());
|
|
}
|
|
}
|
|
break;
|
|
case Logger::MessageType::Info:
|
|
if (message_text.has_value()) {
|
|
if (ex.has_value()) {
|
|
logger->LogInfo(message_text.value(), ex.value());
|
|
} else {
|
|
logger->LogInfo(message_text.value());
|
|
}
|
|
} else {
|
|
if (ex.has_value()) {
|
|
logger->LogInfo(ex.value());
|
|
}
|
|
}
|
|
break;
|
|
case Logger::MessageType::Warning:
|
|
if (message_text.has_value()) {
|
|
if (ex.has_value()) {
|
|
logger->LogWarning(message_text.value(), ex.value());
|
|
} else {
|
|
logger->LogWarning(message_text.value());
|
|
}
|
|
} else {
|
|
if (ex.has_value()) {
|
|
logger->LogWarning(ex.value());
|
|
}
|
|
}
|
|
break;
|
|
case Logger::MessageType::Error:
|
|
if (message_text.has_value()) {
|
|
if (ex.has_value()) {
|
|
logger->LogError(message_text.value(), ex.value());
|
|
} else {
|
|
logger->LogError(message_text.value());
|
|
}
|
|
} else {
|
|
if (ex.has_value()) {
|
|
logger->LogError(ex.value());
|
|
}
|
|
}
|
|
break;
|
|
case Logger::MessageType::Wtf:
|
|
if (message_text.has_value()) {
|
|
if (ex.has_value()) {
|
|
logger->LogWtf(message_text.value(), ex.value());
|
|
} else {
|
|
logger->LogWtf(message_text.value());
|
|
}
|
|
} else {
|
|
if (ex.has_value()) {
|
|
logger->LogWtf(ex.value());
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
ExpectLogSize(error_message, 1, spy);
|
|
if (spy->log.size() > 0) {
|
|
auto message = spy->log.at(0);
|
|
ExpectMessageType(error_message, type, message);
|
|
ExpectMessageText(error_message, message_text, message);
|
|
ExpectMessageException(error_message, ex.has_value() ? make_optional(ex.value().what()) : nullopt, message);
|
|
}
|
|
return GetError(error_message);
|
|
};
|
|
return ExecuteSuite(
|
|
MakeTestSuite("CPPUtils::Logger::Log*(...)",
|
|
log,
|
|
{
|
|
MakeTest("should log what a terrible failure with a message",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Wtf,
|
|
(const optional<string> &)"this should never happen",
|
|
(const optional<std::exception> &)nullopt)),
|
|
MakeTest("should log what a terrible failure with a message and an exception",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Wtf,
|
|
(const optional<string> &)"this should never happen",
|
|
(const optional<std::exception> &)runtime_error("bad thing happen"))),
|
|
MakeTest("should log what a terrible failure with a message",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Wtf,
|
|
(const optional<string> &)nullopt,
|
|
(const optional<std::exception> &)runtime_error("bad thing happen"))),
|
|
MakeTest("should log an error with a message",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Error,
|
|
(const optional<string> &)"this should never happen",
|
|
(const optional<std::exception> &)nullopt)),
|
|
MakeTest("should log an error with a message and an exception",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Error,
|
|
(const optional<string> &)"this should never happen",
|
|
(const optional<std::exception> &)runtime_error("bad thing happen"))),
|
|
MakeTest("should log an error with a message",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Error,
|
|
(const optional<string> &)nullopt,
|
|
(const optional<std::exception> &)runtime_error("bad thing happen"))),
|
|
MakeTest("should log a warning with a message",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Warning,
|
|
(const optional<string> &)"this should never happen",
|
|
(const optional<std::exception> &)nullopt)),
|
|
MakeTest("should log a warning with a message and an exception",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Warning,
|
|
(const optional<string> &)"this should never happen",
|
|
(const optional<std::exception> &)runtime_error("bad thing happen"))),
|
|
MakeTest("should log a warning with a message",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Warning,
|
|
(const optional<string> &)nullopt,
|
|
(const optional<std::exception> &)runtime_error("bad thing happen"))),
|
|
MakeTest("should log an info with a message",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Info,
|
|
(const optional<string> &)"this should never happen",
|
|
(const optional<std::exception> &)nullopt)),
|
|
MakeTest("should log an info with a message and an exception",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Info,
|
|
(const optional<string> &)"this should never happen",
|
|
(const optional<std::exception> &)runtime_error("bad thing happen"))),
|
|
MakeTest("should log an info with a message",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Info,
|
|
(const optional<string> &)nullopt,
|
|
(const optional<std::exception> &)runtime_error("bad thing happen"))),
|
|
MakeTest("should log a debug with a message",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Debug,
|
|
(const optional<string> &)"this should never happen",
|
|
(const optional<std::exception> &)nullopt)),
|
|
MakeTest("should log a debug with a message and an exception",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Debug,
|
|
(const optional<string> &)"this should never happen",
|
|
(const optional<std::exception> &)runtime_error("bad thing happen"))),
|
|
MakeTest("should log a debug with a message",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Debug,
|
|
(const optional<string> &)nullopt,
|
|
(const optional<std::exception> &)runtime_error("bad thing happen"))),
|
|
MakeTest("should log a verbose with a message",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Verbose,
|
|
(const optional<string> &)"this should never happen",
|
|
(const optional<std::exception> &)nullopt)),
|
|
MakeTest("should log a verbose with a message and an exception",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Verbose,
|
|
(const optional<string> &)"this should never happen",
|
|
(const optional<std::exception> &)runtime_error("bad thing happen"))),
|
|
MakeTest("should log a verbose with a message",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Verbose,
|
|
(const optional<string> &)nullopt,
|
|
(const optional<std::exception> &)runtime_error("bad thing happen"))),
|
|
|
|
}));
|
|
}
|
|
|
|
TestResults test_Logger_Log() {
|
|
auto log = [](const Logger::MessageType &type,
|
|
const optional<string> &message_text,
|
|
const optional<std::exception> &ex) -> string {
|
|
ostringstream error_message;
|
|
auto logger = Logger::GetUnique();
|
|
auto spy = make_shared<SpyLoggerDestination>();
|
|
logger->AddDestination(spy);
|
|
switch (type) {
|
|
case Logger::MessageType::Debug:
|
|
if (message_text.has_value()) {
|
|
if (ex.has_value()) {
|
|
logger->Log(Logger::MessageType::Debug, message_text.value(), ex.value());
|
|
} else {
|
|
logger->Log(Logger::MessageType::Debug, message_text.value());
|
|
}
|
|
} else {
|
|
if (ex.has_value()) {
|
|
logger->Log(Logger::MessageType::Debug, ex.value());
|
|
}
|
|
}
|
|
break;
|
|
case Logger::MessageType::Verbose:
|
|
if (message_text.has_value()) {
|
|
if (ex.has_value()) {
|
|
logger->Log(Logger::MessageType::Verbose, message_text.value(), ex.value());
|
|
} else {
|
|
logger->Log(Logger::MessageType::Verbose, message_text.value());
|
|
}
|
|
} else {
|
|
if (ex.has_value()) {
|
|
logger->Log(Logger::MessageType::Verbose, ex.value());
|
|
}
|
|
}
|
|
break;
|
|
case Logger::MessageType::Info:
|
|
if (message_text.has_value()) {
|
|
if (ex.has_value()) {
|
|
logger->Log(Logger::MessageType::Info, message_text.value(), ex.value());
|
|
} else {
|
|
logger->Log(Logger::MessageType::Info, message_text.value());
|
|
}
|
|
} else {
|
|
if (ex.has_value()) {
|
|
logger->Log(Logger::MessageType::Info, ex.value());
|
|
}
|
|
}
|
|
break;
|
|
case Logger::MessageType::Warning:
|
|
if (message_text.has_value()) {
|
|
if (ex.has_value()) {
|
|
logger->Log(Logger::MessageType::Warning, message_text.value(), ex.value());
|
|
} else {
|
|
logger->Log(Logger::MessageType::Warning, message_text.value());
|
|
}
|
|
} else {
|
|
if (ex.has_value()) {
|
|
logger->Log(Logger::MessageType::Warning, ex.value());
|
|
}
|
|
}
|
|
break;
|
|
case Logger::MessageType::Error:
|
|
if (message_text.has_value()) {
|
|
if (ex.has_value()) {
|
|
logger->Log(Logger::MessageType::Error, message_text.value(), ex.value());
|
|
} else {
|
|
logger->Log(Logger::MessageType::Error, message_text.value());
|
|
}
|
|
} else {
|
|
if (ex.has_value()) {
|
|
logger->Log(Logger::MessageType::Error, ex.value());
|
|
}
|
|
}
|
|
break;
|
|
case Logger::MessageType::Wtf:
|
|
if (message_text.has_value()) {
|
|
if (ex.has_value()) {
|
|
logger->Log(Logger::MessageType::Wtf, message_text.value(), ex.value());
|
|
} else {
|
|
logger->Log(Logger::MessageType::Wtf, message_text.value());
|
|
}
|
|
} else {
|
|
if (ex.has_value()) {
|
|
logger->Log(Logger::MessageType::Wtf, ex.value());
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
ExpectLogSize(error_message, 1, spy);
|
|
if (spy->log.size() > 0) {
|
|
auto message = spy->log.at(0);
|
|
ExpectMessageType(error_message, type, message);
|
|
ExpectMessageText(error_message, message_text, message);
|
|
ExpectMessageException(error_message, ex.has_value() ? make_optional(ex.value().what()) : nullopt, message);
|
|
}
|
|
return GetError(error_message);
|
|
};
|
|
return ExecuteSuite(
|
|
MakeTestSuite("CPPUtils::Logger::Log(const MessageType&, ...)",
|
|
log,
|
|
{
|
|
MakeTest("should log what a terrible failure with a message",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Wtf,
|
|
(const optional<string> &)"this should never happen",
|
|
(const optional<std::exception> &)nullopt)),
|
|
MakeTest("should log what a terrible failure with a message and an exception",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Wtf,
|
|
(const optional<string> &)"this should never happen",
|
|
(const optional<std::exception> &)runtime_error("bad thing happen"))),
|
|
MakeTest("should log what a terrible failure with a message",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Wtf,
|
|
(const optional<string> &)nullopt,
|
|
(const optional<std::exception> &)runtime_error("bad thing happen"))),
|
|
MakeTest("should log an error with a message",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Error,
|
|
(const optional<string> &)"this should never happen",
|
|
(const optional<std::exception> &)nullopt)),
|
|
MakeTest("should log an error with a message and an exception",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Error,
|
|
(const optional<string> &)"this should never happen",
|
|
(const optional<std::exception> &)runtime_error("bad thing happen"))),
|
|
MakeTest("should log an error with a message",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Error,
|
|
(const optional<string> &)nullopt,
|
|
(const optional<std::exception> &)runtime_error("bad thing happen"))),
|
|
MakeTest("should log a warning with a message",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Warning,
|
|
(const optional<string> &)"this should never happen",
|
|
(const optional<std::exception> &)nullopt)),
|
|
MakeTest("should log a warning with a message and an exception",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Warning,
|
|
(const optional<string> &)"this should never happen",
|
|
(const optional<std::exception> &)runtime_error("bad thing happen"))),
|
|
MakeTest("should log a warning with a message",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Warning,
|
|
(const optional<string> &)nullopt,
|
|
(const optional<std::exception> &)runtime_error("bad thing happen"))),
|
|
MakeTest("should log an info with a message",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Info,
|
|
(const optional<string> &)"this should never happen",
|
|
(const optional<std::exception> &)nullopt)),
|
|
MakeTest("should log an info with a message and an exception",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Info,
|
|
(const optional<string> &)"this should never happen",
|
|
(const optional<std::exception> &)runtime_error("bad thing happen"))),
|
|
MakeTest("should log an info with a message",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Info,
|
|
(const optional<string> &)nullopt,
|
|
(const optional<std::exception> &)runtime_error("bad thing happen"))),
|
|
MakeTest("should log a debug with a message",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Debug,
|
|
(const optional<string> &)"this should never happen",
|
|
(const optional<std::exception> &)nullopt)),
|
|
MakeTest("should log a debug with a message and an exception",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Debug,
|
|
(const optional<string> &)"this should never happen",
|
|
(const optional<std::exception> &)runtime_error("bad thing happen"))),
|
|
MakeTest("should log a debug with a message",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Debug,
|
|
(const optional<string> &)nullopt,
|
|
(const optional<std::exception> &)runtime_error("bad thing happen"))),
|
|
MakeTest("should log a verbose with a message",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Verbose,
|
|
(const optional<string> &)"this should never happen",
|
|
(const optional<std::exception> &)nullopt)),
|
|
MakeTest("should log a verbose with a message and an exception",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Verbose,
|
|
(const optional<string> &)"this should never happen",
|
|
(const optional<std::exception> &)runtime_error("bad thing happen"))),
|
|
MakeTest("should log a verbose with a message",
|
|
no_errors,
|
|
make_tuple(Logger::MessageType::Verbose,
|
|
(const optional<string> &)nullopt,
|
|
(const optional<std::exception> &)runtime_error("bad thing happen"))),
|
|
|
|
}));
|
|
}
|
|
|
|
TestResults test_Logger_LogToDo() {
|
|
auto log_to_do = [](const string &todo_message) {
|
|
auto logger = Logger::GetUnique();
|
|
auto spy = make_shared<SpyLoggerDestination>();
|
|
logger->AddDestination(spy);
|
|
logger->LogToDo(todo_message);
|
|
ostringstream error_message;
|
|
ExpectLogSize(error_message, 1, spy);
|
|
if (spy->log.size() > 0) {
|
|
auto message = spy->log.at(0);
|
|
ExpectMessageType(error_message, Logger::MessageType::Debug, message);
|
|
ExpectMessageText(error_message, "TODO: " + todo_message, message);
|
|
ExpectMessageException(error_message, nullopt, message);
|
|
}
|
|
return GetError(error_message);
|
|
};
|
|
return ExecuteSuite(MakeTestSuite(
|
|
"CPPUtils::Logger::LogToDo(const std:;string&)",
|
|
log_to_do,
|
|
{
|
|
MakeTest("should log a TODO for \"fill in this function\"", no_errors, make_tuple("fill in this function")),
|
|
MakeTest("should log a TODO for \"delete this after fixing bug:2048\"",
|
|
no_errors,
|
|
make_tuple("delete this after fixing bug:2048")),
|
|
MakeTest("should log a TODO for \"refactor this\"", no_errors, make_tuple("refactor this")),
|
|
}));
|
|
}
|
|
|
|
TestResults test_Logger_AddDestination_and_ClearDestinations() {
|
|
auto add_destination = []() {
|
|
ostringstream error_message;
|
|
auto logger = Logger::GetUnique();
|
|
auto spy = make_shared<SpyLoggerDestination>();
|
|
ExpectLogSize(error_message, 0, spy);
|
|
logger->LogInfo("first message");
|
|
ExpectLogSize(error_message, 0, spy);
|
|
logger->AddDestination(spy);
|
|
ExpectLogSize(error_message, 0, spy);
|
|
logger->LogInfo("second message");
|
|
ExpectLogSize(error_message, 1, spy);
|
|
logger->ClearDestinations();
|
|
ExpectLogSize(error_message, 1, spy);
|
|
logger->LogInfo("third message");
|
|
ExpectLogSize(error_message, 1, spy);
|
|
if (spy->log.size() > 0) {
|
|
auto message = spy->log.at(0);
|
|
ExpectMessageType(error_message, Logger::MessageType::Info, message);
|
|
ExpectMessageText(error_message, "second message", message);
|
|
ExpectMessageException(error_message, nullopt, message);
|
|
}
|
|
return GetError(error_message);
|
|
};
|
|
return ExecuteSuite(MakeTestSuite("",
|
|
add_destination,
|
|
{
|
|
MakeTest("should add and clear destinations", no_errors, make_tuple()),
|
|
}));
|
|
}
|
|
|
|
// AddDestination
|
|
// ClearDestinations
|
|
|
|
int main(int argc, char *argv[]) {
|
|
TestResults results;
|
|
|
|
results += test_Destination_TypeRangeGettersAndSetters();
|
|
results += test_Logger_GetShared();
|
|
results += test_Logger_GetUnique();
|
|
results += test_LogUnimplementedMethod();
|
|
results += test_Logger_LogUnhandledError();
|
|
results += test_Logger_LogUnimplementedFeature();
|
|
results += test_Logger_Log_Level();
|
|
results += test_Logger_Log();
|
|
results += test_Logger_LogToDo();
|
|
results += test_Logger_AddDestination_and_ClearDestinations();
|
|
|
|
PrintResults(cout, results);
|
|
|
|
return results.Failed() + results.Errors();
|
|
}
|