mirror of
https://github.com/XRPLF/clio.git
synced 2025-12-06 17:27:58 +00:00
fix: Keep spdlog loggers valid between tests (#2614)
This commit is contained in:
@@ -42,7 +42,7 @@ using namespace util;
|
||||
static constexpr auto kLOG_FORMAT = "%Y-%m-%d %H:%M:%S.%f %^%3!l:%n%$ - %v";
|
||||
|
||||
struct BenchmarkLoggingInitializer {
|
||||
static std::shared_ptr<spdlog::sinks::sink>
|
||||
[[nodiscard]] static std::shared_ptr<spdlog::sinks::sink>
|
||||
createFileSink(LogService::FileLoggingParams const& params)
|
||||
{
|
||||
return LogService::createFileSink(params, kLOG_FORMAT);
|
||||
@@ -72,8 +72,6 @@ uniqueLogDir()
|
||||
static void
|
||||
benchmarkConcurrentFileLogging(benchmark::State& state)
|
||||
{
|
||||
spdlog::drop_all();
|
||||
|
||||
auto const numThreads = static_cast<size_t>(state.range(0));
|
||||
auto const messagesPerThread = static_cast<size_t>(state.range(1));
|
||||
|
||||
@@ -84,7 +82,9 @@ benchmarkConcurrentFileLogging(benchmark::State& state)
|
||||
state.PauseTiming();
|
||||
|
||||
std::filesystem::create_directories(logDir);
|
||||
spdlog::init_thread_pool(8192, 1);
|
||||
static constexpr size_t kQUEUE_SIZE = 8192;
|
||||
static constexpr size_t kTHREAD_COUNT = 1;
|
||||
spdlog::init_thread_pool(kQUEUE_SIZE, kTHREAD_COUNT);
|
||||
|
||||
auto fileSink = BenchmarkLoggingInitializer::createFileSink({
|
||||
.logDir = logDir,
|
||||
|
||||
@@ -54,7 +54,7 @@ OnAssert::resetAction()
|
||||
void
|
||||
OnAssert::defaultAction(std::string_view message)
|
||||
{
|
||||
if (LogService::enabled()) {
|
||||
if (LogServiceState::initialized()) {
|
||||
LOG(LogService::fatal()) << message;
|
||||
} else {
|
||||
std::cerr << message;
|
||||
|
||||
@@ -41,12 +41,12 @@
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <system_error>
|
||||
@@ -56,7 +56,10 @@
|
||||
|
||||
namespace util {
|
||||
|
||||
LogService::Data LogService::data{};
|
||||
bool LogServiceState::isAsync_{true};
|
||||
Severity LogServiceState::defaultSeverity_{Severity::NFO};
|
||||
std::vector<spdlog::sink_ptr> LogServiceState::sinks_{};
|
||||
bool LogServiceState::initialized_{false};
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -238,23 +241,71 @@ getMinSeverity(config::ClioConfigDefinition const& config, Severity defaultSever
|
||||
return minSeverity;
|
||||
}
|
||||
|
||||
std::shared_ptr<spdlog::logger>
|
||||
LogService::registerLogger(std::string const& channel, Severity severity)
|
||||
void
|
||||
LogServiceState::init(bool isAsync, Severity defaultSeverity, std::vector<spdlog::sink_ptr> const& sinks)
|
||||
{
|
||||
std::shared_ptr<spdlog::logger> logger;
|
||||
if (data.isAsync) {
|
||||
logger = std::make_shared<spdlog::async_logger>(
|
||||
channel,
|
||||
data.allSinks.begin(),
|
||||
data.allSinks.end(),
|
||||
spdlog::thread_pool(),
|
||||
spdlog::async_overflow_policy::block
|
||||
);
|
||||
} else {
|
||||
logger = std::make_shared<spdlog::logger>(channel, data.allSinks.begin(), data.allSinks.end());
|
||||
if (initialized_) {
|
||||
throw std::logic_error("LogServiceState is already initialized");
|
||||
}
|
||||
|
||||
logger->set_level(toSpdlogLevel(severity));
|
||||
isAsync_ = isAsync;
|
||||
defaultSeverity_ = defaultSeverity;
|
||||
sinks_ = sinks;
|
||||
initialized_ = true;
|
||||
|
||||
spdlog::apply_all([](std::shared_ptr<spdlog::logger> logger) {
|
||||
logger->set_level(toSpdlogLevel(defaultSeverity_));
|
||||
});
|
||||
|
||||
if (isAsync) {
|
||||
static constexpr size_t kQUEUE_SIZE = 8192;
|
||||
static constexpr size_t kTHREAD_COUNT = 1;
|
||||
spdlog::init_thread_pool(kQUEUE_SIZE, kTHREAD_COUNT);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
LogServiceState::initialized()
|
||||
{
|
||||
return initialized_;
|
||||
}
|
||||
|
||||
void
|
||||
LogServiceState::reset()
|
||||
{
|
||||
if (not initialized()) {
|
||||
throw std::logic_error("LogService is not initialized");
|
||||
}
|
||||
isAsync_ = true;
|
||||
defaultSeverity_ = Severity::NFO;
|
||||
sinks_.clear();
|
||||
initialized_ = false;
|
||||
}
|
||||
|
||||
std::shared_ptr<spdlog::logger>
|
||||
LogServiceState::registerLogger(std::string const& channel, std::optional<Severity> severity)
|
||||
{
|
||||
if (not initialized_) {
|
||||
throw std::logic_error("LogService is not initialized");
|
||||
}
|
||||
|
||||
std::shared_ptr<spdlog::logger> existingLogger = spdlog::get(channel);
|
||||
if (existingLogger != nullptr) {
|
||||
if (severity.has_value())
|
||||
existingLogger->set_level(toSpdlogLevel(*severity));
|
||||
return existingLogger;
|
||||
}
|
||||
|
||||
std::shared_ptr<spdlog::logger> logger;
|
||||
if (isAsync_) {
|
||||
logger = std::make_shared<spdlog::async_logger>(
|
||||
channel, sinks_.begin(), sinks_.end(), spdlog::thread_pool(), spdlog::async_overflow_policy::block
|
||||
);
|
||||
} else {
|
||||
logger = std::make_shared<spdlog::logger>(channel, sinks_.begin(), sinks_.end());
|
||||
}
|
||||
|
||||
logger->set_level(toSpdlogLevel(severity.value_or(defaultSeverity_)));
|
||||
logger->flush_on(spdlog::level::err);
|
||||
|
||||
spdlog::register_logger(logger);
|
||||
@@ -262,22 +313,12 @@ LogService::registerLogger(std::string const& channel, Severity severity)
|
||||
return logger;
|
||||
}
|
||||
|
||||
std::expected<void, std::string>
|
||||
LogService::init(config::ClioConfigDefinition const& config)
|
||||
std::expected<std::vector<spdlog::sink_ptr>, std::string>
|
||||
LogService::getSinks(config::ClioConfigDefinition const& config)
|
||||
{
|
||||
// Drop existing loggers
|
||||
spdlog::drop_all();
|
||||
|
||||
data.isAsync = config.get<bool>("log.is_async");
|
||||
data.defaultSeverity = getSeverityLevel(config.get<std::string>("log.level"));
|
||||
|
||||
std::string const format = config.get<std::string>("log.format");
|
||||
|
||||
if (data.isAsync) {
|
||||
spdlog::init_thread_pool(8192, 1);
|
||||
}
|
||||
|
||||
data.allSinks = createConsoleSinks(config.get<bool>("log.enable_console"), format);
|
||||
std::vector<spdlog::sink_ptr> allSinks = createConsoleSinks(config.get<bool>("log.enable_console"), format);
|
||||
|
||||
if (auto const logDir = config.maybeValue<std::string>("log.directory"); logDir.has_value()) {
|
||||
std::filesystem::path const dirPath{logDir.value()};
|
||||
@@ -294,11 +335,27 @@ LogService::init(config::ClioConfigDefinition const& config)
|
||||
.rotationSizeMB = config.get<uint32_t>("log.rotation_size"),
|
||||
.dirMaxFiles = config.get<uint32_t>("log.directory_max_files"),
|
||||
};
|
||||
data.allSinks.push_back(createFileSink(params, format));
|
||||
allSinks.push_back(createFileSink(params, format));
|
||||
}
|
||||
return allSinks;
|
||||
}
|
||||
|
||||
std::expected<void, std::string>
|
||||
LogService::init(config::ClioConfigDefinition const& config)
|
||||
{
|
||||
auto const sinksMaybe = getSinks(config);
|
||||
if (!sinksMaybe.has_value()) {
|
||||
return std::unexpected{sinksMaybe.error()};
|
||||
}
|
||||
|
||||
LogServiceState::init(
|
||||
config.get<bool>("log.is_async"),
|
||||
getSeverityLevel(config.get<std::string>("log.level")),
|
||||
std::move(sinksMaybe).value()
|
||||
);
|
||||
|
||||
// get min severity per channel, can be overridden using the `log.channels` array
|
||||
auto const maybeMinSeverity = getMinSeverity(config, data.defaultSeverity);
|
||||
auto const maybeMinSeverity = getMinSeverity(config, defaultSeverity_);
|
||||
if (!maybeMinSeverity) {
|
||||
return std::unexpected{maybeMinSeverity.error()};
|
||||
}
|
||||
@@ -307,20 +364,23 @@ LogService::init(config::ClioConfigDefinition const& config)
|
||||
// Create loggers for each channel
|
||||
for (auto const& channel : Logger::kCHANNELS) {
|
||||
auto const it = minSeverity.find(channel);
|
||||
auto const severity = (it != minSeverity.end()) ? it->second : data.defaultSeverity;
|
||||
auto const severity = (it != minSeverity.end()) ? it->second : defaultSeverity_;
|
||||
registerLogger(channel, severity);
|
||||
}
|
||||
|
||||
spdlog::set_default_logger(spdlog::get("General"));
|
||||
|
||||
LOG(LogService::info()) << "Default log level = " << toString(data.defaultSeverity);
|
||||
LOG(LogService::info()) << "Default log level = " << toString(defaultSeverity_);
|
||||
return {};
|
||||
}
|
||||
|
||||
void
|
||||
LogService::shutdown()
|
||||
{
|
||||
spdlog::shutdown();
|
||||
if (initialized_ && isAsync_) {
|
||||
// We run in async mode in production, so we need to make sure all logs are flushed before shutting down
|
||||
spdlog::shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
Logger::Pump
|
||||
@@ -359,17 +419,15 @@ LogService::fatal(SourceLocationType const& loc)
|
||||
return Logger(spdlog::default_logger()).fatal(loc);
|
||||
}
|
||||
|
||||
bool
|
||||
LogService::enabled()
|
||||
void
|
||||
LogServiceState::replaceSinks(std::vector<std::shared_ptr<spdlog::sinks::sink>> const& sinks)
|
||||
{
|
||||
return spdlog::get_level() != spdlog::level::off;
|
||||
sinks_ = sinks;
|
||||
spdlog::apply_all([](std::shared_ptr<spdlog::logger> logger) { logger->sinks() = sinks_; });
|
||||
}
|
||||
|
||||
Logger::Logger(std::string channel) : logger_(spdlog::get(channel))
|
||||
Logger::Logger(std::string channel) : logger_(LogServiceState::registerLogger(channel))
|
||||
{
|
||||
if (!logger_) {
|
||||
logger_ = LogService::registerLogger(channel);
|
||||
}
|
||||
}
|
||||
|
||||
Logger::Pump::Pump(std::shared_ptr<spdlog::logger> logger, Severity sev, SourceLocationType const& loc)
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -43,9 +44,15 @@ class sink; // NOLINT(readability-identifier-naming)
|
||||
} // namespace spdlog
|
||||
|
||||
struct BenchmarkLoggingInitializer;
|
||||
class LoggerFixture;
|
||||
struct LogServiceInitTests;
|
||||
|
||||
namespace util {
|
||||
|
||||
namespace impl {
|
||||
class OnAssert;
|
||||
} // namespace impl
|
||||
|
||||
namespace config {
|
||||
class ClioConfigDefinition;
|
||||
} // namespace config
|
||||
@@ -228,27 +235,78 @@ private:
|
||||
Logger(std::shared_ptr<spdlog::logger> logger);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Base state management class for the logging service.
|
||||
*
|
||||
* This class manages the global state and core functionality for the logging system,
|
||||
* including initialization, sink management, and logger registration.
|
||||
*/
|
||||
class LogServiceState {
|
||||
protected:
|
||||
friend struct ::LogServiceInitTests;
|
||||
friend class ::LoggerFixture;
|
||||
friend class Logger;
|
||||
friend class ::util::impl::OnAssert;
|
||||
|
||||
/**
|
||||
* @brief Initialize the logging core with specified parameters.
|
||||
*
|
||||
* @param isAsync Whether logging should be asynchronous
|
||||
* @param defaultSeverity The default severity level for new loggers
|
||||
* @param sinks Vector of spdlog sinks to use for output
|
||||
*/
|
||||
static void
|
||||
init(bool isAsync, Severity defaultSeverity, std::vector<std::shared_ptr<spdlog::sinks::sink>> const& sinks);
|
||||
|
||||
/**
|
||||
* @brief Whether the LogService is initialized or not
|
||||
*
|
||||
* @return true if the LogService is initialized
|
||||
*/
|
||||
[[nodiscard]] static bool
|
||||
initialized();
|
||||
|
||||
/**
|
||||
* @brief Reset the logging service to uninitialized state.
|
||||
*/
|
||||
static void
|
||||
reset();
|
||||
|
||||
/**
|
||||
* @brief Replace the current sinks with a new set of sinks.
|
||||
*
|
||||
* @param sinks Vector of new spdlog sinks to replace the current ones
|
||||
*/
|
||||
static void
|
||||
replaceSinks(std::vector<std::shared_ptr<spdlog::sinks::sink>> const& sinks);
|
||||
|
||||
/**
|
||||
* @brief Register a new logger for the specified channel.
|
||||
*
|
||||
* Creates and registers a new spdlog logger instance for the given channel
|
||||
* with the specified or default severity level.
|
||||
*
|
||||
* @param channel The name of the logging channel
|
||||
* @param severity Optional severity level override; uses default if not specified
|
||||
* @return Shared pointer to the registered spdlog logger
|
||||
*/
|
||||
static std::shared_ptr<spdlog::logger>
|
||||
registerLogger(std::string const& channel, std::optional<Severity> severity = std::nullopt);
|
||||
|
||||
protected:
|
||||
static bool isAsync_; // NOLINT(readability-identifier-naming)
|
||||
static Severity defaultSeverity_; // NOLINT(readability-identifier-naming)
|
||||
static std::vector<std::shared_ptr<spdlog::sinks::sink>> sinks_; // NOLINT(readability-identifier-naming)
|
||||
static bool initialized_; // NOLINT(readability-identifier-naming)
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A global logging service.
|
||||
*
|
||||
* Used to initialize and setup the logging core as well as a globally available
|
||||
* entrypoint for logging into the `General` channel as well as raising alerts.
|
||||
*/
|
||||
class LogService {
|
||||
struct Data {
|
||||
bool isAsync;
|
||||
Severity defaultSeverity;
|
||||
std::vector<std::shared_ptr<spdlog::sinks::sink>> allSinks;
|
||||
};
|
||||
|
||||
friend class Logger;
|
||||
|
||||
private:
|
||||
static Data data;
|
||||
|
||||
static std::shared_ptr<spdlog::logger>
|
||||
registerLogger(std::string const& channel, Severity severity = data.defaultSeverity);
|
||||
|
||||
class LogService : public LogServiceState {
|
||||
public:
|
||||
LogService() = delete;
|
||||
|
||||
@@ -321,15 +379,16 @@ public:
|
||||
[[nodiscard]] static Logger::Pump
|
||||
fatal(SourceLocationType const& loc = CURRENT_SRC_LOCATION);
|
||||
|
||||
/**
|
||||
* @brief Whether the LogService is enabled or not
|
||||
*
|
||||
* @return true if the LogService is enabled, false otherwise
|
||||
*/
|
||||
[[nodiscard]] static bool
|
||||
enabled();
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Parses the sinks from a @ref config::ClioConfigDefinition
|
||||
*
|
||||
* @param config The configuration to parse sinks from
|
||||
* @return A vector of sinks on success, error message on failure
|
||||
*/
|
||||
[[nodiscard]] static std::expected<std::vector<std::shared_ptr<spdlog::sinks::sink>>, std::string>
|
||||
getSinks(config::ClioConfigDefinition const& config);
|
||||
|
||||
struct FileLoggingParams {
|
||||
std::string logDir;
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
*
|
||||
* This is meant to be used as a base for other fixtures.
|
||||
*/
|
||||
struct AsyncAsioContextTest : virtual public NoLoggerFixture {
|
||||
struct AsyncAsioContextTest : virtual public ::testing::Test {
|
||||
AsyncAsioContextTest()
|
||||
{
|
||||
work_.emplace(boost::asio::make_work_guard(ctx_)); // make sure ctx does not stop on its own
|
||||
@@ -79,7 +79,7 @@ private:
|
||||
* Use `run_for(duration)` etc. directly on `ctx`.
|
||||
* This is meant to be used as a base for other fixtures.
|
||||
*/
|
||||
struct SyncAsioContextTest : virtual public NoLoggerFixture {
|
||||
struct SyncAsioContextTest : virtual public ::testing::Test {
|
||||
template <util::CoroutineFunction F>
|
||||
void
|
||||
runCoroutine(F&& f, bool allowMockLeak = false)
|
||||
|
||||
43
tests/common/util/LoggerBuffer.hpp
Normal file
43
tests/common/util/LoggerBuffer.hpp
Normal file
@@ -0,0 +1,43 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2025, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#pragma once
|
||||
#include "util/StringBuffer.hpp"
|
||||
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
class LoggerBuffer {
|
||||
public:
|
||||
std::string
|
||||
getStrAndReset()
|
||||
{
|
||||
return buffer_.getStrAndReset();
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
getStream()
|
||||
{
|
||||
return stream_;
|
||||
}
|
||||
|
||||
private:
|
||||
StringBuffer buffer_;
|
||||
std::ostream stream_ = std::ostream{&buffer_};
|
||||
};
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "util/log/Logger.hpp"
|
||||
|
||||
#include <spdlog/common.h>
|
||||
#include <spdlog/logger.h>
|
||||
#include <spdlog/pattern_formatter.h>
|
||||
#include <spdlog/sinks/ostream_sink.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
@@ -29,32 +30,40 @@
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
LoggerFixture::LoggerFixture()
|
||||
void
|
||||
LoggerFixture::init()
|
||||
{
|
||||
// Clear any existing loggers
|
||||
spdlog::drop_all();
|
||||
util::LogServiceState::init(false, util::Severity::FTL, {});
|
||||
|
||||
// Create ostream sink for testing
|
||||
auto ostreamSink = std::make_shared<spdlog::sinks::ostream_sink_mt>(stream_);
|
||||
ostreamSink->set_formatter(std::make_unique<spdlog::pattern_formatter>("%^%3!l:%n%$ - %v"));
|
||||
|
||||
// Create loggers for each channel
|
||||
std::ranges::for_each(util::Logger::kCHANNELS, [&ostreamSink](char const* channel) {
|
||||
auto logger = std::make_shared<spdlog::logger>(channel, ostreamSink);
|
||||
logger->set_level(spdlog::level::trace);
|
||||
spdlog::register_logger(logger);
|
||||
std::ranges::for_each(util::Logger::kCHANNELS, [](char const* channel) {
|
||||
util::LogService::registerLogger(channel);
|
||||
});
|
||||
|
||||
spdlog::get("General")->set_level(spdlog::level::debug);
|
||||
|
||||
auto traceLogger = std::make_shared<spdlog::logger>("Trace", ostreamSink);
|
||||
traceLogger->set_level(spdlog::level::trace);
|
||||
spdlog::register_logger(traceLogger);
|
||||
|
||||
spdlog::set_default_logger(spdlog::get("General"));
|
||||
}
|
||||
|
||||
NoLoggerFixture::NoLoggerFixture()
|
||||
void
|
||||
LoggerFixture::resetTestingLoggers()
|
||||
{
|
||||
spdlog::set_level(spdlog::level::off);
|
||||
auto ostreamSink = std::make_shared<spdlog::sinks::ostream_sink_mt>(buffer_.getStream());
|
||||
ostreamSink->set_formatter(std::make_unique<spdlog::pattern_formatter>("%^%3!l:%n%$ - %v"));
|
||||
ostreamSink->set_level(spdlog::level::trace);
|
||||
util::LogServiceState::replaceSinks({ostreamSink});
|
||||
|
||||
spdlog::apply_all([](std::shared_ptr<spdlog::logger> logger) { logger->set_level(spdlog::level::trace); });
|
||||
spdlog::get("General")->set_level(spdlog::level::debug);
|
||||
}
|
||||
|
||||
LoggerFixture::LoggerFixture()
|
||||
{
|
||||
util::LogServiceState::reset();
|
||||
util::LogServiceState::init(false, util::Severity::TRC, {});
|
||||
|
||||
resetTestingLoggers();
|
||||
}
|
||||
|
||||
LoggerFixture::~LoggerFixture()
|
||||
{
|
||||
util::LogServiceState::replaceSinks({});
|
||||
spdlog::apply_all([](std::shared_ptr<spdlog::logger> logger) { logger->set_level(spdlog::level::critical); });
|
||||
}
|
||||
|
||||
@@ -19,37 +19,39 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "util/StringBuffer.hpp"
|
||||
#include "util/LoggerBuffer.hpp"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* @brief A fixture for testing LogService and Logger.
|
||||
*/
|
||||
class LoggerFixture : virtual public ::testing::Test {
|
||||
StringBuffer buffer_;
|
||||
std::ostream stream_ = std::ostream{&buffer_};
|
||||
protected:
|
||||
LoggerBuffer buffer_;
|
||||
|
||||
public:
|
||||
// Simulates the `util::LogService::init(config)` call
|
||||
LoggerFixture();
|
||||
~LoggerFixture() override;
|
||||
|
||||
/**
|
||||
* @brief Sets up spdlog loggers for each channel. Should be called once before using any loggers.
|
||||
* Simulates the `util::LogService::init(config)` call
|
||||
*/
|
||||
static void
|
||||
init();
|
||||
|
||||
protected:
|
||||
[[nodiscard]]
|
||||
std::string
|
||||
getLoggerString()
|
||||
{
|
||||
return buffer_.getStrAndReset();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Fixture with util::Logger support but completely disabled logging.
|
||||
*
|
||||
* This is meant to be used as a base for other fixtures.
|
||||
*/
|
||||
struct NoLoggerFixture : virtual LoggerFixture {
|
||||
NoLoggerFixture();
|
||||
private:
|
||||
void
|
||||
resetTestingLoggers();
|
||||
};
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include <memory>
|
||||
|
||||
template <template <typename> typename MockType = ::testing::NiceMock>
|
||||
struct MockBackendTestBase : virtual public NoLoggerFixture {
|
||||
struct MockBackendTestBase : virtual public ::testing::Test {
|
||||
class BackendProxy {
|
||||
std::shared_ptr<MockType<MockBackend>> backend_ =
|
||||
std::make_shared<MockType<MockBackend>>(util::config::ClioConfigDefinition{{}});
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
/**
|
||||
* @brief Fixture with mock counters
|
||||
*/
|
||||
struct MockCountersTest : virtual public NoLoggerFixture {
|
||||
struct MockCountersTest : virtual public ::testing::Test {
|
||||
protected:
|
||||
std::shared_ptr<MockCounters> mockCountersPtr_ = std::make_shared<MockCounters>();
|
||||
};
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
* @brief Fixture with a mock etl service
|
||||
*/
|
||||
template <template <typename> typename MockType = ::testing::NiceMock>
|
||||
struct MockETLServiceTestBase : virtual public NoLoggerFixture {
|
||||
struct MockETLServiceTestBase : virtual public ::testing::Test {
|
||||
using Mock = MockType<MockETLService>;
|
||||
|
||||
protected:
|
||||
@@ -63,7 +63,7 @@ using MockETLServiceTestStrict = MockETLServiceTestBase<::testing::StrictMock>;
|
||||
/**
|
||||
* @brief Fixture with a mock etl balancer
|
||||
*/
|
||||
struct MockLoadBalancerTest : virtual public NoLoggerFixture {
|
||||
struct MockLoadBalancerTest : virtual public ::testing::Test {
|
||||
protected:
|
||||
std::shared_ptr<MockLoadBalancer> mockLoadBalancerPtr_ = std::make_shared<MockLoadBalancer>();
|
||||
};
|
||||
@@ -71,7 +71,7 @@ protected:
|
||||
/**
|
||||
* @brief Fixture with a mock NG etl balancer
|
||||
*/
|
||||
struct MockNgLoadBalancerTest : virtual public NoLoggerFixture {
|
||||
struct MockNgLoadBalancerTest : virtual public ::testing::Test {
|
||||
protected:
|
||||
std::shared_ptr<MockNgLoadBalancer> mockLoadBalancerPtr_ = std::make_shared<MockNgLoadBalancer>();
|
||||
};
|
||||
@@ -79,7 +79,7 @@ protected:
|
||||
/**
|
||||
* @brief Fixture with a mock ledger fetcher
|
||||
*/
|
||||
struct MockLedgerFetcherTest : virtual public NoLoggerFixture {
|
||||
struct MockLedgerFetcherTest : virtual public ::testing::Test {
|
||||
protected:
|
||||
std::shared_ptr<MockNgLedgerFetcher> mockLedgerFetcherPtr_ = std::make_shared<MockNgLedgerFetcher>();
|
||||
};
|
||||
@@ -87,7 +87,7 @@ protected:
|
||||
/**
|
||||
* @brief Fixture with a mock ledger fetcher
|
||||
*/
|
||||
struct MockAmendmentBlockHandlerTest : virtual public NoLoggerFixture {
|
||||
struct MockAmendmentBlockHandlerTest : virtual public ::testing::Test {
|
||||
protected:
|
||||
std::shared_ptr<MockAmendmentBlockHandler> mockAmendmentBlockHandlerPtr_ =
|
||||
std::make_shared<MockAmendmentBlockHandler>();
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include <memory>
|
||||
|
||||
template <template <typename> typename MockType = ::testing::NiceMock>
|
||||
struct MockMigrationBackendTestBase : virtual public NoLoggerFixture {
|
||||
struct MockMigrationBackendTestBase : virtual public ::testing::Test {
|
||||
class BackendProxy {
|
||||
std::shared_ptr<MockType<MockMigrationBackend>> backend_ =
|
||||
std::make_shared<MockType<MockMigrationBackend>>(util::config::ClioConfigDefinition{});
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
* @brief Fixture with an embedded AnyExecutionContext wrapping a SyncExecutionContext
|
||||
*
|
||||
*/
|
||||
struct SyncExecutionCtxFixture : virtual public NoLoggerFixture {
|
||||
struct SyncExecutionCtxFixture : virtual public ::testing::Test {
|
||||
protected:
|
||||
util::async::SyncExecutionContext syncCtx_;
|
||||
util::async::AnyExecutionContext ctx_{syncCtx_};
|
||||
|
||||
@@ -41,7 +41,7 @@ using namespace std;
|
||||
|
||||
using namespace data::cassandra;
|
||||
|
||||
class BackendCassandraBaseTest : public NoLoggerFixture {
|
||||
class BackendCassandraBaseTest : public virtual ::testing::Test {
|
||||
protected:
|
||||
static Handle
|
||||
createHandle(std::string_view contactPoints, std::string_view keyspace)
|
||||
|
||||
@@ -86,7 +86,7 @@ makeMigrationTestManagerAndBackend(ClioConfigDefinition const& config)
|
||||
}
|
||||
} // namespace
|
||||
|
||||
class MigrationCassandraSimpleTest : public WithPrometheus, public NoLoggerFixture {
|
||||
class MigrationCassandraSimpleTest : public WithPrometheus {
|
||||
// This function is used to prepare the database before running the tests
|
||||
// It is called in the SetUp function. Different tests can override this function to prepare the database
|
||||
// differently
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include "util/LoggerFixtures.hpp"
|
||||
#include "util/TerminationHandler.hpp"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
@@ -27,5 +28,7 @@ main(int argc, char* argv[])
|
||||
util::setTerminationHandler();
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
LoggerFixture::init();
|
||||
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
using namespace app;
|
||||
|
||||
struct StopperTest : NoLoggerFixture {
|
||||
struct StopperTest : virtual public ::testing::Test {
|
||||
protected:
|
||||
// Order here is important, stopper_ should die before mockCallback_, otherwise UB
|
||||
testing::StrictMock<testing::MockFunction<void(boost::asio::yield_context)>> mockCallback_;
|
||||
|
||||
@@ -54,7 +54,7 @@ using namespace app;
|
||||
namespace http = boost::beast::http;
|
||||
using namespace util::config;
|
||||
|
||||
struct WebHandlersTest : virtual NoLoggerFixture {
|
||||
struct WebHandlersTest : virtual public ::testing::Test {
|
||||
DOSGuardStrictMock dosGuardMock;
|
||||
util::TagDecoratorFactory const tagFactory{
|
||||
ClioConfigDefinition{{"log.tag_style", ConfigValue{ConfigType::String}.defaultValue("uint")}}
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
using namespace data;
|
||||
|
||||
struct LedgerCacheTest : util::prometheus::WithPrometheus, NoLoggerFixture {
|
||||
struct LedgerCacheTest : util::prometheus::WithPrometheus {
|
||||
LedgerCache cache;
|
||||
};
|
||||
|
||||
@@ -39,7 +39,7 @@ TEST_F(LedgerCacheTest, defaultState)
|
||||
EXPECT_EQ(cache.latestLedgerSequence(), 0u);
|
||||
}
|
||||
|
||||
struct LedgerCachePrometheusMetricTest : util::prometheus::WithMockPrometheus, NoLoggerFixture {
|
||||
struct LedgerCachePrometheusMetricTest : util::prometheus::WithMockPrometheus {
|
||||
LedgerCache cache;
|
||||
};
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ getParseSettingsConfig(boost::json::value val)
|
||||
return config;
|
||||
};
|
||||
|
||||
class SettingsProviderTest : public NoLoggerFixture {};
|
||||
class SettingsProviderTest : virtual public ::testing::Test {};
|
||||
|
||||
TEST_F(SettingsProviderTest, Defaults)
|
||||
{
|
||||
|
||||
@@ -30,7 +30,7 @@ using namespace data;
|
||||
using namespace util::prometheus;
|
||||
using namespace testing;
|
||||
|
||||
struct CorruptionDetectorTest : NoLoggerFixture, WithPrometheus {};
|
||||
struct CorruptionDetectorTest : WithPrometheus {};
|
||||
|
||||
TEST_F(CorruptionDetectorTest, DisableCacheOnCorruption)
|
||||
{
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace json = boost::json;
|
||||
using namespace util;
|
||||
using namespace testing;
|
||||
|
||||
struct ETLStateTest : public NoLoggerFixture {
|
||||
struct ETLStateTest : public virtual ::testing::Test {
|
||||
MockSource source = MockSource{};
|
||||
};
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ constexpr auto kSTART_SEQ = 1234;
|
||||
|
||||
} // namespace
|
||||
|
||||
class ETLExtractionDataPipeTest : public NoLoggerFixture {
|
||||
class ETLExtractionDataPipeTest : public ::testing::Test {
|
||||
protected:
|
||||
etl::impl::ExtractionDataPipe<uint32_t> pipe_{kSTRIDE, kSTART_SEQ};
|
||||
};
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
using namespace testing;
|
||||
using namespace etl;
|
||||
|
||||
struct ETLExtractorTest : util::prometheus::WithPrometheus, NoLoggerFixture {
|
||||
struct ETLExtractorTest : util::prometheus::WithPrometheus {
|
||||
using ExtractionDataPipeType = MockExtractionDataPipe;
|
||||
using LedgerFetcherType = MockLedgerFetcher;
|
||||
using ExtractorType = etl::impl::Extractor<ExtractionDataPipeType, LedgerFetcherType>;
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
using namespace etl::impl;
|
||||
using namespace util::config;
|
||||
|
||||
struct GrpcSourceTests : NoLoggerFixture, util::prometheus::WithPrometheus, tests::util::WithMockXrpLedgerAPIService {
|
||||
struct GrpcSourceTests : util::prometheus::WithPrometheus, tests::util::WithMockXrpLedgerAPIService {
|
||||
GrpcSourceTests()
|
||||
: WithMockXrpLedgerAPIService("localhost:0")
|
||||
, mockBackend_(std::make_shared<testing::StrictMock<MockBackend>>(ClioConfigDefinition{}))
|
||||
|
||||
@@ -56,7 +56,7 @@ constexpr auto kOFFER_ID = "AA86CBF29770F72FA3FF4A5D9A9FA54D6F399A8E038F72393EF7
|
||||
|
||||
} // namespace
|
||||
|
||||
struct NFTHelpersTest : NoLoggerFixture {
|
||||
struct NFTHelpersTest : virtual public ::testing::Test {
|
||||
protected:
|
||||
static void
|
||||
verifyNFTTransactionsData(
|
||||
|
||||
@@ -50,7 +50,7 @@ constinit auto const kLEDGER_HASH2 = "1B8590C01B0006EDFA9ED60296DD052DC5E90F9965
|
||||
constinit auto const kSEQ = 30;
|
||||
} // namespace
|
||||
|
||||
struct ExtractionModelNgTests : NoLoggerFixture {};
|
||||
struct ExtractionModelNgTests : virtual public ::testing::Test {};
|
||||
|
||||
TEST_F(ExtractionModelNgTests, LedgerDataCopyableAndEquatable)
|
||||
{
|
||||
@@ -178,7 +178,7 @@ TEST_F(ExtractionModelNgTests, BookSuccessorCopyableAndEquatable)
|
||||
}
|
||||
}
|
||||
|
||||
struct ExtractionNgTests : NoLoggerFixture {};
|
||||
struct ExtractionNgTests : public virtual ::testing::Test {};
|
||||
|
||||
TEST_F(ExtractionNgTests, ModType)
|
||||
{
|
||||
@@ -360,7 +360,7 @@ TEST_F(ExtractionNgTests, SuccessorsWithNoNeighborsIncluded)
|
||||
ASSERT_FALSE(res.has_value());
|
||||
}
|
||||
|
||||
struct ExtractionAssertTest : common::util::WithMockAssert, NoLoggerFixture {};
|
||||
struct ExtractionAssertTest : common::util::WithMockAssert {};
|
||||
|
||||
TEST_F(ExtractionAssertTest, InvalidModTypeAsserts)
|
||||
{
|
||||
|
||||
@@ -67,7 +67,7 @@ struct MockLoadObserver : etlng::InitialLoadObserverInterface {
|
||||
);
|
||||
};
|
||||
|
||||
struct GrpcSourceNgTests : virtual NoLoggerFixture, tests::util::WithMockXrpLedgerAPIService {
|
||||
struct GrpcSourceNgTests : virtual public ::testing::Test, tests::util::WithMockXrpLedgerAPIService {
|
||||
GrpcSourceNgTests()
|
||||
: WithMockXrpLedgerAPIService("localhost:0"), grpcSource_("localhost", std::to_string(getXRPLMockPort()))
|
||||
{
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
using namespace etlng::impl;
|
||||
|
||||
struct NetworkValidatedLedgersTests : NoLoggerFixture {
|
||||
struct NetworkValidatedLedgersTests : virtual public ::testing::Test {
|
||||
protected:
|
||||
util::async::CoroExecutionContext ctx_{2};
|
||||
std::shared_ptr<etl::NetworkValidatedLedgersInterface> ledgers_ =
|
||||
|
||||
@@ -254,7 +254,7 @@ struct MockExtNftBurnReadonly {
|
||||
}
|
||||
};
|
||||
|
||||
struct RegistryTest : NoLoggerFixture, util::prometheus::WithPrometheus {
|
||||
struct RegistryTest : util::prometheus::WithPrometheus {
|
||||
RegistryTest()
|
||||
{
|
||||
state_.isWriting = true;
|
||||
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
};
|
||||
} // namespace
|
||||
|
||||
struct ForwardSchedulerTests : NoLoggerFixture {
|
||||
struct ForwardSchedulerTests : virtual public ::testing::Test {
|
||||
protected:
|
||||
MockNetworkValidatedLedgersPtr networkValidatedLedgers_;
|
||||
};
|
||||
|
||||
@@ -86,7 +86,7 @@ struct MockMonitor : etlng::MonitorInterface {
|
||||
MOCK_METHOD(void, stop, (), (override));
|
||||
};
|
||||
|
||||
struct TaskManagerTests : NoLoggerFixture {
|
||||
struct TaskManagerTests : virtual public ::testing::Test {
|
||||
using MockSchedulerType = testing::NiceMock<MockScheduler>;
|
||||
using MockExtractorType = testing::NiceMock<MockExtractor>;
|
||||
using MockLoaderType = testing::NiceMock<MockLoader>;
|
||||
|
||||
@@ -59,7 +59,7 @@ createTestData()
|
||||
|
||||
} // namespace
|
||||
|
||||
struct CacheExtTests : NoLoggerFixture, util::prometheus::WithPrometheus {
|
||||
struct CacheExtTests : util::prometheus::WithPrometheus {
|
||||
protected:
|
||||
MockLedgerCache cache_;
|
||||
std::shared_ptr<etlng::impl::CacheUpdater> updater_ = std::make_shared<etlng::impl::CacheUpdater>(cache_);
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
struct MigrationManagerFactoryTests : public NoLoggerFixture {};
|
||||
struct MigrationManagerFactoryTests : public virtual ::testing::Test {};
|
||||
|
||||
TEST_F(MigrationManagerFactoryTests, InvalidDBType)
|
||||
{
|
||||
|
||||
@@ -76,7 +76,7 @@ TEST_F(FullTableScannerAssertTest, cursorsPerWorkerZero)
|
||||
);
|
||||
}
|
||||
|
||||
struct FullTableScannerTests : NoLoggerFixture {};
|
||||
struct FullTableScannerTests : public virtual ::testing::Test {};
|
||||
|
||||
TEST_F(FullTableScannerTests, SingleThreadCtx)
|
||||
{
|
||||
|
||||
@@ -38,7 +38,7 @@ using namespace util::config;
|
||||
using namespace rpc::impl;
|
||||
namespace json = boost::json;
|
||||
|
||||
class RPCAPIVersionTest : public NoLoggerFixture {
|
||||
class RPCAPIVersionTest : public virtual ::testing::Test {
|
||||
protected:
|
||||
ProductionAPIVersionParser parser_{kDEFAULT_API_VERSION, kMIN_API_VERSION, kMAX_API_VERSION};
|
||||
};
|
||||
|
||||
@@ -49,7 +49,7 @@ using namespace rpc::modifiers;
|
||||
|
||||
namespace json = boost::json;
|
||||
|
||||
class RPCBaseTest : public NoLoggerFixture {};
|
||||
class RPCBaseTest : public virtual ::testing::Test {};
|
||||
|
||||
TEST_F(RPCBaseTest, CheckType)
|
||||
{
|
||||
|
||||
@@ -38,7 +38,7 @@ using util::prometheus::CounterInt;
|
||||
using util::prometheus::WithMockPrometheus;
|
||||
using util::prometheus::WithPrometheus;
|
||||
|
||||
struct RPCCountersTest : WithPrometheus, NoLoggerFixture {
|
||||
struct RPCCountersTest : WithPrometheus {
|
||||
WorkQueue queue{4u, 1024u}; // todo: mock instead
|
||||
Counters counters{queue};
|
||||
};
|
||||
|
||||
@@ -39,7 +39,7 @@ using namespace util::config;
|
||||
using namespace rpc;
|
||||
using namespace util::prometheus;
|
||||
|
||||
struct RPCWorkQueueTestBase : NoLoggerFixture {
|
||||
struct RPCWorkQueueTestBase : public virtual ::testing::Test {
|
||||
ClioConfigDefinition cfg = {
|
||||
{"server.max_queue_size", ConfigValue{ConfigType::Integer}.defaultValue(2)},
|
||||
{"workers", ConfigValue{ConfigType::Integer}.defaultValue(4)}
|
||||
|
||||
@@ -39,7 +39,7 @@ using namespace util::config;
|
||||
using testing::MockFunction;
|
||||
using testing::StrictMock;
|
||||
|
||||
struct SignalsHandlerTestsBase : NoLoggerFixture {
|
||||
struct SignalsHandlerTestsBase : public virtual ::testing::Test {
|
||||
void
|
||||
allowTestToFinish()
|
||||
{
|
||||
|
||||
@@ -327,7 +327,7 @@ TEST_F(IncorrectOverrideValues, InvalidJsonErrors)
|
||||
EXPECT_EQ(expectedErrors, actualErrors);
|
||||
}
|
||||
|
||||
struct ClioConfigDefinitionParseArrayTest : NoLoggerFixture {
|
||||
struct ClioConfigDefinitionParseArrayTest : public virtual ::testing::Test {
|
||||
ClioConfigDefinition config{
|
||||
{"array.[].int", Array{ConfigValue{ConfigType::Integer}}},
|
||||
{"array.[].string", Array{ConfigValue{ConfigType::String}.optional()}}
|
||||
|
||||
@@ -52,7 +52,8 @@ struct ConfigFileJsonParseTestBundle {
|
||||
ValidationMap validationMap;
|
||||
};
|
||||
|
||||
struct ConfigFileJsonParseTest : NoLoggerFixture, testing::WithParamInterface<ConfigFileJsonParseTestBundle> {};
|
||||
struct ConfigFileJsonParseTest : public virtual ::testing::Test,
|
||||
testing::WithParamInterface<ConfigFileJsonParseTestBundle> {};
|
||||
|
||||
TEST_P(ConfigFileJsonParseTest, parseValues)
|
||||
{
|
||||
@@ -309,7 +310,7 @@ INSTANTIATE_TEST_CASE_P(
|
||||
tests::util::kNAME_GENERATOR
|
||||
);
|
||||
|
||||
struct ConfigFileJsonTest : NoLoggerFixture {};
|
||||
struct ConfigFileJsonTest : public virtual ::testing::Test {};
|
||||
|
||||
TEST_F(ConfigFileJsonTest, getValue)
|
||||
{
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
using namespace util::config;
|
||||
|
||||
struct ConfigValueTest : common::util::WithMockAssert, NoLoggerFixture {};
|
||||
struct ConfigValueTest : common::util::WithMockAssert {};
|
||||
|
||||
TEST_F(ConfigValueTest, construct)
|
||||
{
|
||||
@@ -138,7 +138,7 @@ TEST_F(ConfigValueConstraintTest, defaultValueWithConstraintCheckError)
|
||||
}
|
||||
|
||||
// A test for each constraint so it's easy to change in the future
|
||||
struct ConstraintTest : NoLoggerFixture {};
|
||||
struct ConstraintTest : public virtual ::testing::Test {};
|
||||
|
||||
TEST_F(ConstraintTest, PortConstraint)
|
||||
{
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include "util/StringBuffer.hpp"
|
||||
#include "util/LoggerBuffer.hpp"
|
||||
#include "util/LoggerFixtures.hpp"
|
||||
#include "util/config/Array.hpp"
|
||||
#include "util/config/ConfigConstraints.hpp"
|
||||
#include "util/config/ConfigDefinition.hpp"
|
||||
@@ -39,8 +40,6 @@
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
@@ -51,7 +50,21 @@ using util::config::ConfigFileJson;
|
||||
using util::config::ConfigType;
|
||||
using util::config::ConfigValue;
|
||||
|
||||
struct LogServiceInitTests : virtual public ::testing::Test {
|
||||
struct LogServiceInitTests : virtual public LoggerFixture {
|
||||
public:
|
||||
LogServiceInitTests()
|
||||
{
|
||||
LogServiceState::reset();
|
||||
}
|
||||
|
||||
~LogServiceInitTests() override
|
||||
{
|
||||
if (LogService::initialized()) {
|
||||
LogService::reset();
|
||||
}
|
||||
LogServiceState::init(false, Severity::FTL, {});
|
||||
}
|
||||
|
||||
protected:
|
||||
util::config::ClioConfigDefinition config_{
|
||||
{"log.channels.[].channel", Array{ConfigValue{ConfigType::String}}},
|
||||
@@ -80,26 +93,6 @@ protected:
|
||||
{
|
||||
return buffer_.getStrAndReset();
|
||||
}
|
||||
|
||||
void
|
||||
replaceSinks()
|
||||
{
|
||||
auto ostreamSink = std::make_shared<spdlog::sinks::ostream_sink_mt>(stream_);
|
||||
ostreamSink->set_formatter(std::make_unique<spdlog::pattern_formatter>("%^%3!l:%n%$ - %v"));
|
||||
|
||||
for (auto const& channel : Logger::kCHANNELS) {
|
||||
auto logger = spdlog::get(channel);
|
||||
ASSERT_TRUE(logger != nullptr);
|
||||
// It is expected that only stderrSink is present
|
||||
ASSERT_EQ(logger->sinks().size(), 1);
|
||||
logger->sinks().clear();
|
||||
logger->sinks().push_back(ostreamSink);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
StringBuffer buffer_;
|
||||
std::ostream stream_ = std::ostream{&buffer_};
|
||||
};
|
||||
|
||||
TEST_F(LogServiceInitTests, DefaultLogLevel)
|
||||
@@ -107,15 +100,15 @@ TEST_F(LogServiceInitTests, DefaultLogLevel)
|
||||
auto const parsingErrors =
|
||||
config_.parse(ConfigFileJson{boost::json::object{{"log", boost::json::object{{"level", "warn"}}}}});
|
||||
ASSERT_FALSE(parsingErrors.has_value());
|
||||
std::string const logString = "some log";
|
||||
|
||||
EXPECT_TRUE(LogService::init(config_));
|
||||
replaceSinks();
|
||||
|
||||
std::string const logString = "some log";
|
||||
for (auto const& channel : Logger::kCHANNELS) {
|
||||
Logger const log{channel};
|
||||
log.trace() << logString;
|
||||
ASSERT_TRUE(getLoggerString().empty());
|
||||
auto loggerStr = getLoggerString();
|
||||
ASSERT_TRUE(loggerStr.empty()) << " channel: " << channel << " logger_str: " << loggerStr;
|
||||
|
||||
log.debug() << logString;
|
||||
ASSERT_TRUE(getLoggerString().empty());
|
||||
@@ -149,11 +142,10 @@ TEST_F(LogServiceInitTests, ChannelLogLevel)
|
||||
|
||||
auto const parsingErrors = config_.parse(ConfigFileJson{boost::json::parse(configStr).as_object()});
|
||||
ASSERT_FALSE(parsingErrors.has_value());
|
||||
std::string const logString = "some log";
|
||||
|
||||
EXPECT_TRUE(LogService::init(config_));
|
||||
replaceSinks();
|
||||
|
||||
std::string const logString = "some log";
|
||||
for (auto const& channel : Logger::kCHANNELS) {
|
||||
Logger const log{channel};
|
||||
log.trace() << logString;
|
||||
|
||||
@@ -29,12 +29,10 @@ using namespace util;
|
||||
// Used as a fixture for tests with enabled logging
|
||||
class LoggerTest : public LoggerFixture {};
|
||||
|
||||
// Used as a fixture for tests with disabled logging
|
||||
class NoLoggerTest : public NoLoggerFixture {};
|
||||
|
||||
TEST_F(LoggerTest, Basic)
|
||||
{
|
||||
Logger const log{"General"};
|
||||
|
||||
log.info() << "Info line logged";
|
||||
ASSERT_EQ(getLoggerString(), "inf:General - Info line logged\n");
|
||||
|
||||
@@ -53,10 +51,6 @@ TEST_F(LoggerTest, Filtering)
|
||||
|
||||
log.warn() << "Warning is logged";
|
||||
ASSERT_EQ(getLoggerString(), "war:General - Warning is logged\n");
|
||||
|
||||
Logger const tlog{"Trace"};
|
||||
tlog.trace() << "Trace line logged for 'Trace' component";
|
||||
ASSERT_EQ(getLoggerString(), "tra:Trace - Trace line logged for 'Trace' component\n");
|
||||
}
|
||||
|
||||
#ifndef COVERAGE_ENABLED
|
||||
@@ -77,13 +71,3 @@ TEST_F(LoggerTest, LOGMacro)
|
||||
EXPECT_TRUE(computeCalled);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_F(NoLoggerTest, Basic)
|
||||
{
|
||||
Logger const log{"Trace"};
|
||||
log.trace() << "Nothing";
|
||||
ASSERT_TRUE(getLoggerString().empty());
|
||||
|
||||
LogService::fatal() << "Still nothing";
|
||||
ASSERT_TRUE(getLoggerString().empty());
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
namespace http = boost::beast::http;
|
||||
using namespace util::config;
|
||||
|
||||
class IPAdminVerificationStrategyTest : public NoLoggerFixture {
|
||||
class IPAdminVerificationStrategyTest : public virtual ::testing::Test {
|
||||
protected:
|
||||
web::IPAdminVerificationStrategy strat_;
|
||||
http::request<http::string_body> request_;
|
||||
@@ -53,7 +53,7 @@ TEST_F(IPAdminVerificationStrategyTest, IsAdminOnlyForIP_127_0_0_1)
|
||||
EXPECT_FALSE(strat_.isAdmin(request_, "localhost"));
|
||||
}
|
||||
|
||||
class PasswordAdminVerificationStrategyTest : public NoLoggerFixture {
|
||||
class PasswordAdminVerificationStrategyTest : public virtual ::testing::Test {
|
||||
protected:
|
||||
std::string const password_ = "secret";
|
||||
std::string const passwordHash_ = "2bb80d537b1da3e38bd30361aa855686bde0eacd7162fef6a25fe97bf527a25b";
|
||||
|
||||
@@ -141,7 +141,7 @@ getParseServerConfig(boost::json::value val)
|
||||
return config;
|
||||
};
|
||||
|
||||
struct WebServerTest : NoLoggerFixture {
|
||||
struct WebServerTest : public virtual ::testing::Test {
|
||||
~WebServerTest() override
|
||||
{
|
||||
work_.reset();
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
using namespace web;
|
||||
using namespace util::config;
|
||||
|
||||
struct SubscriptionContextTests : NoLoggerFixture {
|
||||
struct SubscriptionContextTests : public virtual ::testing::Test {
|
||||
protected:
|
||||
util::TagDecoratorFactory tagFactory_{ClioConfigDefinition{
|
||||
{"log.tag_style", ConfigValue{ConfigType::String}.defaultValue("uint")},
|
||||
|
||||
@@ -40,7 +40,7 @@ using namespace std;
|
||||
using namespace util::config;
|
||||
using namespace web::dosguard;
|
||||
|
||||
struct DOSGuardTest : NoLoggerFixture {
|
||||
struct DOSGuardTest : public virtual ::testing::Test {
|
||||
static constexpr auto kJSON_DATA = R"JSON({
|
||||
"dos_guard": {
|
||||
"max_fetches": 100,
|
||||
|
||||
@@ -39,7 +39,7 @@ using namespace util;
|
||||
using namespace util::config;
|
||||
using namespace web::dosguard;
|
||||
|
||||
struct WhitelistHandlerTest : NoLoggerFixture {};
|
||||
struct WhitelistHandlerTest : public virtual ::testing::Test {};
|
||||
|
||||
inline static ClioConfigDefinition
|
||||
getParseWhitelistHandlerConfig(boost::json::value val)
|
||||
|
||||
@@ -41,7 +41,7 @@ using namespace web::impl;
|
||||
using namespace web;
|
||||
using namespace util::config;
|
||||
|
||||
struct ErrorHandlingTests : NoLoggerFixture {
|
||||
struct ErrorHandlingTests : public virtual ::testing::Test {
|
||||
protected:
|
||||
util::TagDecoratorFactory tagFactory_{ClioConfigDefinition{
|
||||
{"log.tag_style", ConfigValue{ConfigType::String}.defaultValue("uint")},
|
||||
|
||||
@@ -73,9 +73,7 @@ struct MakeServerTestBundle {
|
||||
bool expectSuccess;
|
||||
};
|
||||
|
||||
struct MakeServerTest : util::prometheus::WithPrometheus,
|
||||
NoLoggerFixture,
|
||||
testing::WithParamInterface<MakeServerTestBundle> {
|
||||
struct MakeServerTest : util::prometheus::WithPrometheus, testing::WithParamInterface<MakeServerTestBundle> {
|
||||
protected:
|
||||
boost::asio::io_context ioContext_;
|
||||
};
|
||||
|
||||
@@ -43,7 +43,7 @@ using namespace web::ng;
|
||||
|
||||
namespace http = boost::beast::http;
|
||||
|
||||
struct NgErrorHandlingTests : NoLoggerFixture {
|
||||
struct NgErrorHandlingTests : public virtual ::testing::Test {
|
||||
static Request
|
||||
makeRequest(bool isHttp, std::optional<std::string> body = std::nullopt)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user