(third_party deps) fix #177, update bundled spdlog to 1.6.0

This commit is contained in:
Benjamin Sergeant
2020-04-11 13:31:39 -07:00
parent 2eb5c9480e
commit f1c106728b
109 changed files with 2792 additions and 689 deletions

View File

@ -1,5 +1,12 @@
cmake_minimum_required(VERSION 3.2)
project(spdlog_utests CXX)
if(NOT TARGET spdlog)
# Stand-alone build
find_package(spdlog REQUIRED)
endif()
include(../cmake/utils.cmake)
find_package(PkgConfig)
@ -12,6 +19,7 @@ set(SPDLOG_UTESTS_SOURCES
test_file_logging.cpp
test_daily_logger.cpp
test_misc.cpp
test_eventlog.cpp
test_pattern_formatter.cpp
test_async.cpp
test_registry.cpp
@ -23,7 +31,8 @@ set(SPDLOG_UTESTS_SOURCES
test_fmt_helper.cpp
test_stdout_api.cpp
test_backtrace.cpp
test_create_dir.cpp)
test_create_dir.cpp
test_cfg.cpp)
if(NOT SPDLOG_NO_EXCEPTIONS)
list(APPEND SPDLOG_UTESTS_SOURCES test_errors.cpp)
@ -47,6 +56,7 @@ function(spdlog_prepare_test test_target spdlog_lib)
spdlog_enable_sanitizer(${test_target})
endif()
add_test(NAME ${test_target} COMMAND ${test_target})
set_tests_properties(${test_target} PROPERTIES RUN_SERIAL ON)
endfunction()
# The compiled library tests

View File

@ -11,6 +11,7 @@
#include <sstream>
#include <string>
#include <iomanip>
#include <stdlib.h>
#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_DEBUG
@ -22,4 +23,4 @@
#include "spdlog/sinks/ostream_sink.h"
#include "spdlog/sinks/rotating_file_sink.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/details/pattern_formatter.h"
#include "spdlog/pattern_formatter.h"

View File

@ -14,7 +14,8 @@ test_sources = files([
'test_fmt_helper.cpp',
'test_stdout_api.cpp',
'test_backtrace.cpp',
'test_create_dir.cpp'
'test_create_dir.cpp',
'test_cfg.cpp',
])
if not get_option('no_exceptions')

View File

@ -5,14 +5,13 @@
TEST_CASE("basic async test ", "[async]")
{
using namespace spdlog;
auto test_sink = std::make_shared<sinks::test_sink_mt>();
auto test_sink = std::make_shared<spdlog::sinks::test_sink_mt>();
size_t overrun_counter = 0;
size_t queue_size = 128;
size_t messages = 256;
{
auto tp = std::make_shared<details::thread_pool>(queue_size, 1);
auto logger = std::make_shared<async_logger>("as", test_sink, tp, async_overflow_policy::block);
auto tp = std::make_shared<spdlog::details::thread_pool>(queue_size, 1);
auto logger = std::make_shared<spdlog::async_logger>("as", test_sink, tp, spdlog::async_overflow_policy::block);
for (size_t i = 0; i < messages; i++)
{
logger->info("Hello message #{}", i);
@ -27,14 +26,13 @@ TEST_CASE("basic async test ", "[async]")
TEST_CASE("discard policy ", "[async]")
{
using namespace spdlog;
auto test_sink = std::make_shared<sinks::test_sink_mt>();
auto test_sink = std::make_shared<spdlog::sinks::test_sink_mt>();
test_sink->set_delay(std::chrono::milliseconds(1));
size_t queue_size = 4;
size_t messages = 1024;
auto tp = std::make_shared<details::thread_pool>(queue_size, 1);
auto logger = std::make_shared<async_logger>("as", test_sink, tp, async_overflow_policy::overrun_oldest);
auto tp = std::make_shared<spdlog::details::thread_pool>(queue_size, 1);
auto logger = std::make_shared<spdlog::async_logger>("as", test_sink, tp, spdlog::async_overflow_policy::overrun_oldest);
for (size_t i = 0; i < messages; i++)
{
logger->info("Hello message");
@ -45,13 +43,12 @@ TEST_CASE("discard policy ", "[async]")
TEST_CASE("discard policy using factory ", "[async]")
{
using namespace spdlog;
size_t queue_size = 4;
size_t messages = 1024;
spdlog::init_thread_pool(queue_size, 1);
auto logger = spdlog::create_async_nb<sinks::test_sink_mt>("as2");
auto test_sink = std::static_pointer_cast<sinks::test_sink_mt>(logger->sinks()[0]);
auto logger = spdlog::create_async_nb<spdlog::sinks::test_sink_mt>("as2");
auto test_sink = std::static_pointer_cast<spdlog::sinks::test_sink_mt>(logger->sinks()[0]);
test_sink->set_delay(std::chrono::milliseconds(1));
for (size_t i = 0; i < messages; i++)
@ -65,13 +62,12 @@ TEST_CASE("discard policy using factory ", "[async]")
TEST_CASE("flush", "[async]")
{
using namespace spdlog;
auto test_sink = std::make_shared<sinks::test_sink_mt>();
auto test_sink = std::make_shared<spdlog::sinks::test_sink_mt>();
size_t queue_size = 256;
size_t messages = 256;
{
auto tp = std::make_shared<details::thread_pool>(queue_size, 1);
auto logger = std::make_shared<async_logger>("as", test_sink, tp, async_overflow_policy::block);
auto tp = std::make_shared<spdlog::details::thread_pool>(queue_size, 1);
auto logger = std::make_shared<spdlog::async_logger>("as", test_sink, tp, spdlog::async_overflow_policy::block);
for (size_t i = 0; i < messages; i++)
{
logger->info("Hello message #{}", i);
@ -86,11 +82,9 @@ TEST_CASE("flush", "[async]")
TEST_CASE("async periodic flush", "[async]")
{
using namespace spdlog;
auto logger = spdlog::create_async<sinks::test_sink_mt>("as");
auto test_sink = std::static_pointer_cast<sinks::test_sink_mt>(logger->sinks()[0]);
auto logger = spdlog::create_async<spdlog::sinks::test_sink_mt>("as");
auto test_sink = std::static_pointer_cast<spdlog::sinks::test_sink_mt>(logger->sinks()[0]);
spdlog::flush_every(std::chrono::seconds(1));
std::this_thread::sleep_for(std::chrono::milliseconds(1100));
@ -101,13 +95,12 @@ TEST_CASE("async periodic flush", "[async]")
TEST_CASE("tp->wait_empty() ", "[async]")
{
using namespace spdlog;
auto test_sink = std::make_shared<sinks::test_sink_mt>();
auto test_sink = std::make_shared<spdlog::sinks::test_sink_mt>();
test_sink->set_delay(std::chrono::milliseconds(5));
size_t messages = 100;
auto tp = std::make_shared<details::thread_pool>(messages, 2);
auto logger = std::make_shared<async_logger>("as", test_sink, tp, async_overflow_policy::block);
auto tp = std::make_shared<spdlog::details::thread_pool>(messages, 2);
auto logger = std::make_shared<spdlog::async_logger>("as", test_sink, tp, spdlog::async_overflow_policy::block);
for (size_t i = 0; i < messages; i++)
{
logger->info("Hello message #{}", i);
@ -121,14 +114,13 @@ TEST_CASE("tp->wait_empty() ", "[async]")
TEST_CASE("multi threads", "[async]")
{
using namespace spdlog;
auto test_sink = std::make_shared<sinks::test_sink_mt>();
auto test_sink = std::make_shared<spdlog::sinks::test_sink_mt>();
size_t queue_size = 128;
size_t messages = 256;
size_t n_threads = 10;
{
auto tp = std::make_shared<details::thread_pool>(queue_size, 1);
auto logger = std::make_shared<async_logger>("as", test_sink, tp, async_overflow_policy::block);
auto tp = std::make_shared<spdlog::details::thread_pool>(queue_size, 1);
auto logger = std::make_shared<spdlog::async_logger>("as", test_sink, tp, spdlog::async_overflow_policy::block);
std::vector<std::thread> threads;
for (size_t i = 0; i < n_threads; i++)
@ -169,9 +161,10 @@ TEST_CASE("to_file", "[async]")
}
}
REQUIRE(count_lines(filename) == messages);
require_message_count(filename, messages);
auto contents = file_contents(filename);
REQUIRE(ends_with(contents, std::string("Hello message #1023\n")));
using spdlog::details::os::default_eol;
REQUIRE(ends_with(contents, fmt::format("Hello message #1023{}", default_eol)));
}
TEST_CASE("to_file multi-workers", "[async]")
@ -191,5 +184,5 @@ TEST_CASE("to_file multi-workers", "[async]")
}
}
REQUIRE(count_lines(filename) == messages);
require_message_count(filename, messages);
}

93
third_party/spdlog/tests/test_cfg.cpp vendored Normal file
View File

@ -0,0 +1,93 @@
#include "includes.h"
#include "test_sink.h"
#include <spdlog/cfg/env.h>
#include <spdlog/cfg/argv.h>
using spdlog::cfg::load_argv_levels;
using spdlog::cfg::load_env_levels;
using spdlog::sinks::test_sink_st;
TEST_CASE("env", "[cfg]")
{
spdlog::drop("l1");
auto l1 = spdlog::create<test_sink_st>("l1");
#ifdef CATCH_PLATFORM_WINDOWS
_putenv_s("SPDLOG_LEVEL", "l1=warn");
#else
setenv("SPDLOG_LEVEL", "l1=warn", 1);
#endif
load_env_levels();
REQUIRE(l1->level() == spdlog::level::warn);
spdlog::set_default_logger(spdlog::create<test_sink_st>("cfg-default"));
REQUIRE(spdlog::default_logger()->level() == spdlog::level::info);
}
TEST_CASE("argv1", "[cfg]")
{
spdlog::drop("l1");
const char *argv[] = {"ignore", "SPDLOG_LEVEL=l1=warn"};
load_argv_levels(2, argv);
auto l1 = spdlog::create<spdlog::sinks::test_sink_st>("l1");
REQUIRE(l1->level() == spdlog::level::warn);
REQUIRE(spdlog::default_logger()->level() == spdlog::level::info);
}
TEST_CASE("argv2", "[cfg]")
{
spdlog::drop("l1");
const char *argv[] = {"ignore", "SPDLOG_LEVEL=l1=warn,trace"};
load_argv_levels(2, argv);
auto l1 = spdlog::create<test_sink_st>("l1");
REQUIRE(l1->level() == spdlog::level::warn);
REQUIRE(spdlog::default_logger()->level() == spdlog::level::trace);
spdlog::set_level(spdlog::level::info);
}
TEST_CASE("argv3", "[cfg]")
{
spdlog::drop("l1");
const char *argv[] = {"ignore", "SPDLOG_LEVEL="};
load_argv_levels(2, argv);
auto l1 = spdlog::create<test_sink_st>("l1");
REQUIRE(l1->level() == spdlog::level::info);
REQUIRE(spdlog::default_logger()->level() == spdlog::level::info);
}
TEST_CASE("argv4", "[cfg]")
{
spdlog::drop("l1");
const char *argv[] = {"ignore", "SPDLOG_LEVEL=junk"};
load_argv_levels(2, argv);
auto l1 = spdlog::create<test_sink_st>("l1");
REQUIRE(l1->level() == spdlog::level::info);
}
TEST_CASE("argv5", "[cfg]")
{
spdlog::drop("l1");
const char *argv[] = {"ignore", "ignore", "SPDLOG_LEVEL=l1=warn,trace"};
load_argv_levels(3, argv);
auto l1 = spdlog::create<test_sink_st>("l1");
REQUIRE(l1->level() == spdlog::level::warn);
REQUIRE(spdlog::default_logger()->level() == spdlog::level::trace);
spdlog::set_level(spdlog::level::info);
}
TEST_CASE("argv6", "[cfg]")
{
spdlog::set_level(spdlog::level::err);
const char *argv[] = {""};
load_argv_levels(1, argv);
REQUIRE(spdlog::default_logger()->level() == spdlog::level::err);
spdlog::set_level(spdlog::level::info);
}
TEST_CASE("argv7", "[cfg]")
{
spdlog::set_level(spdlog::level::err);
const char *argv[] = {""};
load_argv_levels(0, argv);
REQUIRE(spdlog::default_logger()->level() == spdlog::level::err);
spdlog::set_level(spdlog::level::info);
}

View File

@ -24,7 +24,7 @@ TEST_CASE("daily_logger with dateonly calculator", "[daily_logger]")
logger->flush();
auto filename = fmt::to_string(w);
REQUIRE(count_lines(filename) == 10);
require_message_count(filename, 10);
}
struct custom_daily_file_name_calculator
@ -55,12 +55,10 @@ TEST_CASE("daily_logger with custom calculator", "[daily_logger]")
logger->info("Test message {}", i);
}
logger->
flush();
logger->flush();
auto filename = fmt::to_string(w);
REQUIRE(count_lines(filename) == 10);
require_message_count(filename, 10);
}
/*
@ -115,7 +113,6 @@ static void test_rotate(int days_to_run, uint16_t max_days, uint16_t expected_n_
using spdlog::log_clock;
using spdlog::details::log_msg;
using spdlog::sinks::daily_file_sink_st;
using namespace spdlog::details;
prepare_logdir();

View File

@ -2,11 +2,11 @@
#include "spdlog/sinks/dup_filter_sink.h"
#include "test_sink.h"
using namespace spdlog;
using namespace spdlog::sinks;
TEST_CASE("dup_filter_test1", "[dup_filter_sink]")
{
using spdlog::sinks::dup_filter_sink_st;
using spdlog::sinks::test_sink_mt;
dup_filter_sink_st dup_sink{std::chrono::seconds{5}};
auto test_sink = std::make_shared<test_sink_mt>();
dup_sink.add_sink(test_sink);
@ -21,6 +21,9 @@ TEST_CASE("dup_filter_test1", "[dup_filter_sink]")
TEST_CASE("dup_filter_test2", "[dup_filter_sink]")
{
using spdlog::sinks::dup_filter_sink_st;
using spdlog::sinks::test_sink_mt;
dup_filter_sink_st dup_sink{std::chrono::seconds{0}};
auto test_sink = std::make_shared<test_sink_mt>();
dup_sink.add_sink(test_sink);
@ -36,6 +39,9 @@ TEST_CASE("dup_filter_test2", "[dup_filter_sink]")
TEST_CASE("dup_filter_test3", "[dup_filter_sink]")
{
using spdlog::sinks::dup_filter_sink_st;
using spdlog::sinks::test_sink_mt;
dup_filter_sink_st dup_sink{std::chrono::seconds{1}};
auto test_sink = std::make_shared<test_sink_mt>();
dup_sink.add_sink(test_sink);
@ -51,6 +57,9 @@ TEST_CASE("dup_filter_test3", "[dup_filter_sink]")
TEST_CASE("dup_filter_test4", "[dup_filter_sink]")
{
using spdlog::sinks::dup_filter_sink_mt;
using spdlog::sinks::test_sink_mt;
dup_filter_sink_mt dup_sink{std::chrono::milliseconds{10}};
auto test_sink = std::make_shared<test_sink_mt>();
dup_sink.add_sink(test_sink);
@ -63,6 +72,9 @@ TEST_CASE("dup_filter_test4", "[dup_filter_sink]")
TEST_CASE("dup_filter_test5", "[dup_filter_sink]")
{
using spdlog::sinks::dup_filter_sink_mt;
using spdlog::sinks::test_sink_mt;
dup_filter_sink_mt dup_sink{std::chrono::seconds{5}};
auto test_sink = std::make_shared<test_sink_mt>();
dup_sink.add_sink(test_sink);

View File

@ -7,10 +7,6 @@
class failing_sink : public spdlog::sinks::base_sink<std::mutex>
{
public:
failing_sink() = default;
~failing_sink() final = default;
protected:
void sink_it_(const spdlog::details::log_msg &) final
{
@ -34,7 +30,8 @@ TEST_CASE("default_error_handler", "[errors]]")
logger->info("Test message {}", 2);
logger->flush();
REQUIRE(file_contents(filename) == std::string("Test message 2\n"));
using spdlog::details::os::default_eol;
REQUIRE(file_contents(filename) == fmt::format("Test message 2{}", default_eol));
REQUIRE(count_lines(filename) == 1);
}
@ -51,7 +48,7 @@ TEST_CASE("custom_error_handler", "[errors]]")
REQUIRE_THROWS_AS(logger->info("Bad format msg {} {}", "xxx"), custom_ex);
logger->info("Good message #2");
REQUIRE(count_lines(filename) == 2);
require_message_count(filename, 2);
}
TEST_CASE("default_error_handler2", "[errors]]")
@ -93,7 +90,7 @@ TEST_CASE("async_error_handler", "[errors]]")
spdlog::drop("logger"); // force logger to drain the queue and shutdown
}
spdlog::init_thread_pool(128, 1);
REQUIRE(count_lines(filename) == 2);
require_message_count(filename, 2);
REQUIRE(file_contents("test_logs/custom_err.txt") == err_msg);
}

View File

@ -0,0 +1,71 @@
#if _WIN32
#include "includes.h"
#include "test_sink.h"
#include "spdlog/sinks/win_eventlog_sink.h"
static const LPCSTR TEST_SOURCE = "spdlog_test";
static void test_single_print(std::function<void(std::string const &)> do_log, std::string const &expected_contents, WORD expected_ev_type)
{
using namespace std::chrono;
do_log(expected_contents);
const auto expected_time_generated = duration_cast<seconds>(system_clock::now().time_since_epoch()).count();
struct handle_t
{
HANDLE handle_;
~handle_t()
{
if (handle_)
{
REQUIRE(CloseEventLog(handle_));
}
}
} event_log{::OpenEventLog(nullptr, TEST_SOURCE)};
REQUIRE(event_log.handle_);
DWORD read_bytes{}, size_needed{};
auto ok =
::ReadEventLog(event_log.handle_, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_BACKWARDS_READ, 0, &read_bytes, 0, &read_bytes, &size_needed);
REQUIRE(!ok);
REQUIRE(::GetLastError() == ERROR_INSUFFICIENT_BUFFER);
std::vector<char> record_buffer(size_needed);
PEVENTLOGRECORD record = (PEVENTLOGRECORD)record_buffer.data();
ok = ::ReadEventLog(
event_log.handle_, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_BACKWARDS_READ, 0, record, size_needed, &read_bytes, &size_needed);
REQUIRE(ok);
REQUIRE(record->NumStrings == 1);
REQUIRE(record->EventType == expected_ev_type);
REQUIRE((expected_time_generated - record->TimeGenerated) <= 3u);
std::string message_in_log(((char *)record + record->StringOffset));
REQUIRE(message_in_log == expected_contents + spdlog::details::os::default_eol);
}
TEST_CASE("eventlog", "[eventlog]")
{
using namespace spdlog;
auto test_sink = std::make_shared<sinks::win_eventlog_sink_mt>(TEST_SOURCE);
spdlog::logger test_logger("eventlog", test_sink);
test_logger.set_level(level::trace);
test_sink->set_pattern("%v");
test_single_print([&test_logger](std::string const &msg) { test_logger.trace(msg); }, "my trace message", EVENTLOG_SUCCESS);
test_single_print([&test_logger](std::string const &msg) { test_logger.debug(msg); }, "my debug message", EVENTLOG_SUCCESS);
test_single_print([&test_logger](std::string const &msg) { test_logger.info(msg); }, "my info message", EVENTLOG_INFORMATION_TYPE);
test_single_print([&test_logger](std::string const &msg) { test_logger.warn(msg); }, "my warn message", EVENTLOG_WARNING_TYPE);
test_single_print([&test_logger](std::string const &msg) { test_logger.error(msg); }, "my error message", EVENTLOG_ERROR_TYPE);
test_single_print([&test_logger](std::string const &msg) { test_logger.critical(msg); }, "my critical message", EVENTLOG_ERROR_TYPE);
}
#endif //_WIN32

View File

@ -4,9 +4,6 @@
#include "includes.h"
using spdlog::details::file_helper;
using spdlog::details::log_msg;
static const std::string target_filename = "test_logs/file_helper_test.txt";
static void write_with_helper(file_helper &helper, size_t howmany)
{
@ -21,6 +18,7 @@ TEST_CASE("file_helper_filename", "[file_helper::filename()]]")
prepare_logdir();
file_helper helper;
std::string target_filename = "test_logs/file_helper_test.txt";
helper.open(target_filename);
REQUIRE(helper.filename() == target_filename);
}
@ -28,6 +26,7 @@ TEST_CASE("file_helper_filename", "[file_helper::filename()]]")
TEST_CASE("file_helper_size", "[file_helper::size()]]")
{
prepare_logdir();
std::string target_filename = "test_logs/file_helper_test.txt";
size_t expected_size = 123;
{
file_helper helper;
@ -41,6 +40,7 @@ TEST_CASE("file_helper_size", "[file_helper::size()]]")
TEST_CASE("file_helper_reopen", "[file_helper::reopen()]]")
{
prepare_logdir();
std::string target_filename = "test_logs/file_helper_test.txt";
file_helper helper;
helper.open(target_filename);
write_with_helper(helper, 12);
@ -52,6 +52,7 @@ TEST_CASE("file_helper_reopen", "[file_helper::reopen()]]")
TEST_CASE("file_helper_reopen2", "[file_helper::reopen(false)]]")
{
prepare_logdir();
std::string target_filename = "test_logs/file_helper_test.txt";
size_t expected_size = 14;
file_helper helper;
helper.open(target_filename);
@ -71,7 +72,8 @@ static void test_split_ext(const char *fname, const char *expect_base, const cha
std::replace(filename.begin(), filename.end(), '/', '\\');
std::replace(expected_base.begin(), expected_base.end(), '/', '\\');
#endif
spdlog::filename_t basename, ext;
spdlog::filename_t basename;
spdlog::filename_t ext;
std::tie(basename, ext) = file_helper::split_by_extension(filename);
REQUIRE(basename == expected_base);
REQUIRE(ext == expected_ext);

View File

@ -15,8 +15,9 @@ TEST_CASE("simple_file_logger", "[simple_logger]]")
logger->info("Test message {}", 2);
logger->flush();
REQUIRE(file_contents(filename) == std::string("Test message 1\nTest message 2\n"));
REQUIRE(count_lines(filename) == 2);
require_message_count(filename, 2);
using spdlog::details::os::default_eol;
REQUIRE(file_contents(filename) == fmt::format("Test message 1{}Test message 2{}", default_eol, default_eol));
}
TEST_CASE("flush_on", "[flush_on]]")
@ -34,8 +35,10 @@ TEST_CASE("flush_on", "[flush_on]]")
logger->info("Test message {}", 1);
logger->info("Test message {}", 2);
REQUIRE(file_contents(filename) == std::string("Should not be flushed\nTest message 1\nTest message 2\n"));
REQUIRE(count_lines(filename) == 3);
require_message_count(filename, 3);
using spdlog::details::os::default_eol;
REQUIRE(file_contents(filename) ==
fmt::format("Should not be flushed{}Test message 1{}Test message 2{}", default_eol, default_eol, default_eol));
}
TEST_CASE("rotating_file_logger1", "[rotating_logger]]")
@ -51,8 +54,7 @@ TEST_CASE("rotating_file_logger1", "[rotating_logger]]")
}
logger->flush();
auto filename = basename;
REQUIRE(count_lines(filename) == 10);
require_message_count(basename, 10);
}
TEST_CASE("rotating_file_logger2", "[rotating_logger]]")
@ -80,8 +82,9 @@ TEST_CASE("rotating_file_logger2", "[rotating_logger]]")
}
logger->flush();
auto filename = basename;
REQUIRE(count_lines(filename) == 10);
require_message_count(basename, 10);
for (int i = 0; i < 1000; i++)
{
@ -89,7 +92,7 @@ TEST_CASE("rotating_file_logger2", "[rotating_logger]]")
}
logger->flush();
REQUIRE(get_filesize(filename) <= max_size);
REQUIRE(get_filesize(basename) <= max_size);
auto filename1 = basename + ".1";
REQUIRE(get_filesize(filename1) <= max_size);
}

View File

@ -36,7 +36,10 @@ TEST_CASE("pad2", "[fmt_helper]")
{
test_pad2(0, "00");
test_pad2(3, "03");
test_pad2(10, "10");
test_pad2(23, "23");
test_pad2(99, "99");
test_pad2(100, "100");
test_pad2(123, "123");
test_pad2(1234, "1234");
test_pad2(-5, "-5");
@ -46,8 +49,13 @@ TEST_CASE("pad3", "[fmt_helper]")
{
test_pad3(0, "000");
test_pad3(3, "003");
test_pad3(10, "010");
test_pad3(23, "023");
test_pad3(99, "099");
test_pad3(100, "100");
test_pad3(123, "123");
test_pad3(999, "999");
test_pad3(1000, "1000");
test_pad3(1234, "1234");
}

View File

@ -22,7 +22,8 @@ TEST_CASE("debug and trace w/o format string", "[macros]]")
SPDLOG_LOGGER_DEBUG(logger, "Test message 2");
logger->flush();
REQUIRE(ends_with(file_contents(filename), "Test message 2\n"));
using spdlog::details::os::default_eol;
REQUIRE(ends_with(file_contents(filename), fmt::format("Test message 2{}", default_eol)));
REQUIRE(count_lines(filename) == 1);
spdlog::set_default_logger(logger);
@ -31,8 +32,8 @@ TEST_CASE("debug and trace w/o format string", "[macros]]")
SPDLOG_DEBUG("Test message {}", 4);
logger->flush();
REQUIRE(ends_with(file_contents(filename), "Test message 4\n"));
REQUIRE(count_lines(filename) == 2);
require_message_count(filename, 2);
REQUIRE(ends_with(file_contents(filename), fmt::format("Test message 4{}", default_eol)));
}
TEST_CASE("disable param evaluation", "[macros]")

View File

@ -21,11 +21,11 @@ TEST_CASE("basic_logging ", "[basic_logging]")
{
// const char
REQUIRE(log_info("Hello") == "Hello");
REQUIRE(log_info("") == "");
REQUIRE(log_info("").empty());
// std::string
REQUIRE(log_info(std::string("Hello")) == "Hello");
REQUIRE(log_info(std::string()) == std::string());
REQUIRE(log_info(std::string()).empty());
// Numbers
REQUIRE(log_info(5) == "5");
@ -37,8 +37,8 @@ TEST_CASE("basic_logging ", "[basic_logging]")
TEST_CASE("log_levels", "[log_levels]")
{
REQUIRE(log_info("Hello", spdlog::level::err) == "");
REQUIRE(log_info("Hello", spdlog::level::critical) == "");
REQUIRE(log_info("Hello", spdlog::level::err).empty());
REQUIRE(log_info("Hello", spdlog::level::critical).empty());
REQUIRE(log_info("Hello", spdlog::level::info) == "Hello");
REQUIRE(log_info("Hello", spdlog::level::debug) == "Hello");
REQUIRE(log_info("Hello", spdlog::level::trace) == "Hello");
@ -72,6 +72,7 @@ TEST_CASE("to_level_enum", "[convert_to_level_enum]")
REQUIRE(spdlog::level::from_str("debug") == spdlog::level::debug);
REQUIRE(spdlog::level::from_str("info") == spdlog::level::info);
REQUIRE(spdlog::level::from_str("warning") == spdlog::level::warn);
REQUIRE(spdlog::level::from_str("warn") == spdlog::level::warn);
REQUIRE(spdlog::level::from_str("error") == spdlog::level::err);
REQUIRE(spdlog::level::from_str("critical") == spdlog::level::critical);
REQUIRE(spdlog::level::from_str("off") == spdlog::level::off);
@ -80,11 +81,9 @@ TEST_CASE("to_level_enum", "[convert_to_level_enum]")
TEST_CASE("periodic flush", "[periodic_flush]")
{
using namespace spdlog;
auto logger = spdlog::create<sinks::test_sink_mt>("periodic_flush");
auto test_sink = std::static_pointer_cast<sinks::test_sink_mt>(logger->sinks()[0]);
using spdlog::sinks::test_sink_mt;
auto logger = spdlog::create<test_sink_mt>("periodic_flush");
auto test_sink = std::static_pointer_cast<test_sink_mt>(logger->sinks()[0]);
spdlog::flush_every(std::chrono::seconds(1));
std::this_thread::sleep_for(std::chrono::milliseconds(1250));
@ -95,8 +94,8 @@ TEST_CASE("periodic flush", "[periodic_flush]")
TEST_CASE("clone-logger", "[clone]")
{
using namespace spdlog;
auto test_sink = std::make_shared<sinks::test_sink_mt>();
using spdlog::sinks::test_sink_mt;
auto test_sink = std::make_shared<test_sink_mt>();
auto logger = std::make_shared<spdlog::logger>("orig", test_sink);
logger->set_pattern("%v");
auto cloned = logger->clone("clone");
@ -117,10 +116,9 @@ TEST_CASE("clone-logger", "[clone]")
TEST_CASE("clone async", "[clone]")
{
using namespace spdlog;
using spdlog::sinks::test_sink_st;
spdlog::init_thread_pool(4, 1);
auto test_sink = std::make_shared<sinks::test_sink_st>();
auto test_sink = std::make_shared<test_sink_st>();
auto logger = std::make_shared<spdlog::async_logger>("orig", test_sink, spdlog::thread_pool());
logger->set_pattern("%v");
auto cloned = logger->clone("clone");
@ -181,6 +179,57 @@ TEST_CASE("to_hex_no_delimiter", "[to_hex]")
REQUIRE(ends_with(output, "0000: 090A0B0CFFFF" + std::string(spdlog::details::os::default_eol)));
}
TEST_CASE("to_hex_show_ascii", "[to_hex]")
{
std::ostringstream oss;
auto oss_sink = std::make_shared<spdlog::sinks::ostream_sink_mt>(oss);
spdlog::logger oss_logger("oss", oss_sink);
std::vector<unsigned char> v{9, 0xa, 0xb, 0x41, 0xc, 0x4b, 0xff, 0xff};
oss_logger.info("{:Xsa}", spdlog::to_hex(v, 8));
REQUIRE(ends_with(oss.str(), "0000: 090A0B410C4BFFFF ...A.K.." + std::string(spdlog::details::os::default_eol)));
}
TEST_CASE("to_hex_different_size_per_line", "[to_hex]")
{
std::ostringstream oss;
auto oss_sink = std::make_shared<spdlog::sinks::ostream_sink_mt>(oss);
spdlog::logger oss_logger("oss", oss_sink);
std::vector<unsigned char> v{9, 0xa, 0xb, 0x41, 0xc, 0x4b, 0xff, 0xff};
oss_logger.info("{:Xsa}", spdlog::to_hex(v, 10));
REQUIRE(ends_with(oss.str(), "0000: 090A0B410C4BFFFF ...A.K.." + std::string(spdlog::details::os::default_eol)));
oss_logger.info("{:Xs}", spdlog::to_hex(v, 10));
REQUIRE(ends_with(oss.str(), "0000: 090A0B410C4BFFFF" + std::string(spdlog::details::os::default_eol)));
oss_logger.info("{:Xsa}", spdlog::to_hex(v, 6));
REQUIRE(ends_with(oss.str(), "0000: 090A0B410C4B ...A.K" + std::string(spdlog::details::os::default_eol) + "0006: FFFF .." +
std::string(spdlog::details::os::default_eol)));
oss_logger.info("{:Xs}", spdlog::to_hex(v, 6));
REQUIRE(ends_with(oss.str(), "0000: 090A0B410C4B" + std::string(spdlog::details::os::default_eol) + "0006: FFFF" +
std::string(spdlog::details::os::default_eol)));
}
TEST_CASE("to_hex_no_ascii", "[to_hex]")
{
std::ostringstream oss;
auto oss_sink = std::make_shared<spdlog::sinks::ostream_sink_mt>(oss);
spdlog::logger oss_logger("oss", oss_sink);
std::vector<unsigned char> v{9, 0xa, 0xb, 0x41, 0xc, 0x4b, 0xff, 0xff};
oss_logger.info("{:Xs}", spdlog::to_hex(v, 8));
REQUIRE(ends_with(oss.str(), "0000: 090A0B410C4BFFFF" + std::string(spdlog::details::os::default_eol)));
oss_logger.info("{:Xsna}", spdlog::to_hex(v, 8));
REQUIRE(ends_with(oss.str(), "090A0B410C4BFFFF" + std::string(spdlog::details::os::default_eol)));
}
TEST_CASE("default logger API", "[default logger]")
{
std::ostringstream oss;

View File

@ -1,6 +1,5 @@
#include "includes.h"
using namespace std::chrono;
using std::chrono::milliseconds;
using test_clock = std::chrono::high_resolution_clock;
@ -13,7 +12,7 @@ TEST_CASE("dequeue-empty-nowait", "[mpmc_blocking_q]")
size_t q_size = 100;
milliseconds tolerance_wait(10);
spdlog::details::mpmc_blocking_queue<int> q(q_size);
int popped_item;
int popped_item = 0;
auto start = test_clock::now();
auto rv = q.dequeue_for(popped_item, milliseconds::zero());
@ -32,7 +31,7 @@ TEST_CASE("dequeue-empty-wait", "[mpmc_blocking_q]")
milliseconds tolerance_wait(250);
spdlog::details::mpmc_blocking_queue<int> q(q_size);
int popped_item;
int popped_item = 0;
auto start = test_clock::now();
auto rv = q.dequeue_for(popped_item, wait_ms);
auto delta_ms = millis_from(start);
@ -69,7 +68,7 @@ TEST_CASE("bad_queue", "[mpmc_blocking_q]")
spdlog::details::mpmc_blocking_queue<int> q(q_size);
q.enqueue_nowait(1);
REQUIRE(q.overrun_counter() == 1);
int i;
int i = 0;
REQUIRE(q.dequeue_for(i, milliseconds(0)) == false);
}
@ -77,7 +76,7 @@ TEST_CASE("empty_queue", "[mpmc_blocking_q]")
{
size_t q_size = 10;
spdlog::details::mpmc_blocking_queue<int> q(q_size);
int i;
int i = 0;
REQUIRE(q.dequeue_for(i, milliseconds(10)) == false);
}
@ -87,7 +86,7 @@ TEST_CASE("full_queue", "[mpmc_blocking_q]")
spdlog::details::mpmc_blocking_queue<int> q(q_size);
for (int i = 0; i < static_cast<int>(q_size); i++)
{
q.enqueue(std::move(i));
q.enqueue(i + 0); // i+0 to force rvalue and avoid tidy warnings on the same time if we std::move(i) instead
}
q.enqueue_nowait(123456);

View File

@ -27,7 +27,7 @@ TEST_CASE("custom eol", "[pattern_formatter]")
TEST_CASE("empty format", "[pattern_formatter]")
{
REQUIRE(log_to_str("Some message", "", spdlog::pattern_time_type::local, "") == "");
REQUIRE(log_to_str("Some message", "", spdlog::pattern_time_type::local, "").empty());
}
TEST_CASE("empty format2", "[pattern_formatter]")
@ -305,14 +305,61 @@ TEST_CASE("clone-formatter-2", "[pattern_formatter]")
REQUIRE(fmt::to_string(formatted_1) == fmt::to_string(formatted_2));
}
class custom_test_flag : public spdlog::custom_flag_formatter
{
public:
explicit custom_test_flag(std::string txt)
: some_txt{std::move(txt)}
{}
void format(const spdlog::details::log_msg &, const std::tm &, spdlog::memory_buf_t &dest) override
{
if (some_txt == "throw_me")
{
throw spdlog::spdlog_ex("custom_flag_exception_test");
}
some_txt = std::string(padinfo_.width_, ' ') + some_txt;
dest.append(some_txt.data(), some_txt.data() + some_txt.size());
}
spdlog::details::padding_info get_padding_info()
{
return padinfo_;
}
std::string some_txt;
std::unique_ptr<custom_flag_formatter> clone() const override
{
return spdlog::details::make_unique<custom_test_flag>(some_txt);
}
};
// test clone with custom flag formatters
TEST_CASE("clone-custom_formatter", "[pattern_formatter]")
{
auto formatter_1 = std::make_shared<spdlog::pattern_formatter>();
formatter_1->add_flag<custom_test_flag>('t', "custom_output").set_pattern("[%n] [%t] %v");
auto formatter_2 = formatter_1->clone();
std::string logger_name = "logger-name";
spdlog::details::log_msg msg(logger_name, spdlog::level::info, "some message");
memory_buf_t formatted_1;
memory_buf_t formatted_2;
formatter_1->format(msg, formatted_1);
formatter_2->format(msg, formatted_2);
auto expected = fmt::format("[logger-name] [custom_output] some message{}", spdlog::details::os::default_eol);
REQUIRE(fmt::to_string(formatted_1) == expected);
REQUIRE(fmt::to_string(formatted_2) == expected);
}
//
// Test source location formatting
//
#ifdef _WIN32
static const char *test_path = "\\a\\b\\myfile.cpp";
static const char *const test_path = "\\a\\b\\myfile.cpp";
#else
static const char *test_path = "/a/b//myfile.cpp";
static const char *const test_path = "/a/b//myfile.cpp";
#endif
TEST_CASE("short filename formatter-1", "[pattern_formatter]")
@ -358,3 +405,39 @@ TEST_CASE("full filename formatter", "[pattern_formatter]")
formatter.format(msg, formatted);
REQUIRE(fmt::to_string(formatted) == test_path);
}
TEST_CASE("custom flags", "[pattern_formatter]")
{
auto formatter = std::make_shared<spdlog::pattern_formatter>();
formatter->add_flag<custom_test_flag>('t', "custom1").add_flag<custom_test_flag>('u', "custom2").set_pattern("[%n] [%t] [%u] %v");
memory_buf_t formatted;
spdlog::details::log_msg msg(spdlog::source_loc{}, "logger-name", spdlog::level::info, "some message");
formatter->format(msg, formatted);
auto expected = fmt::format("[logger-name] [custom1] [custom2] some message{}", spdlog::details::os::default_eol);
REQUIRE(fmt::to_string(formatted) == expected);
}
TEST_CASE("custom flags-padding", "[pattern_formatter]")
{
auto formatter = std::make_shared<spdlog::pattern_formatter>();
formatter->add_flag<custom_test_flag>('t', "custom1").add_flag<custom_test_flag>('u', "custom2").set_pattern("[%n] [%t] [%5u] %v");
memory_buf_t formatted;
spdlog::details::log_msg msg(spdlog::source_loc{}, "logger-name", spdlog::level::info, "some message");
formatter->format(msg, formatted);
auto expected = fmt::format("[logger-name] [custom1] [ custom2] some message{}", spdlog::details::os::default_eol);
REQUIRE(fmt::to_string(formatted) == expected);
}
TEST_CASE("custom flags-exception", "[pattern_formatter]")
{
auto formatter = std::make_shared<spdlog::pattern_formatter>();
formatter->add_flag<custom_test_flag>('t', "throw_me").add_flag<custom_test_flag>('u', "custom2").set_pattern("[%n] [%t] [%u] %v");
memory_buf_t formatted;
spdlog::details::log_msg msg(spdlog::source_loc{}, "logger-name", spdlog::level::info, "some message");
CHECK_THROWS_AS(formatter->format(msg, formatted), spdlog::spdlog_ex);
}

View File

@ -1,7 +1,7 @@
#include "includes.h"
static const char *tested_logger_name = "null_logger";
static const char *tested_logger_name2 = "null_logger2";
static const char *const tested_logger_name = "null_logger";
static const char *const tested_logger_name2 = "null_logger2";
#ifndef SPDLOG_NO_EXCEPTIONS
TEST_CASE("register_drop", "[registry]")

View File

@ -21,7 +21,7 @@ void prepare_logdir()
std::string file_contents(const std::string &filename)
{
std::ifstream ifs(filename);
std::ifstream ifs(filename, std::ios_base::binary);
if (!ifs)
{
throw std::runtime_error("Failed open file ");
@ -44,6 +44,18 @@ std::size_t count_lines(const std::string &filename)
return counter;
}
void require_message_count(const std::string &filename, const std::size_t messages)
{
if (strlen(spdlog::details::os::default_eol) == 0)
{
REQUIRE(count_lines(filename) == 1);
}
else
{
REQUIRE(count_lines(filename) == messages);
}
}
std::size_t get_filesize(const std::string &filename)
{
std::ifstream ifs(filename, std::ifstream::ate | std::ifstream::binary);
@ -101,7 +113,7 @@ std::size_t count_files(const std::string &folder)
throw std::runtime_error("Failed open folder " + folder);
}
struct dirent *ep;
struct dirent *ep = nullptr;
while ((ep = readdir(dp)) != nullptr)
{
if (ep->d_name[0] != '.')

View File

@ -3,8 +3,6 @@
#include <cstddef>
#include <string>
std::size_t count_lines(const std::string &filename);
std::size_t count_files(const std::string &folder);
void prepare_logdir();
@ -13,6 +11,8 @@ std::string file_contents(const std::string &filename);
std::size_t count_lines(const std::string &filename);
void require_message_count(const std::string &filename, const std::size_t messages);
std::size_t get_filesize(const std::string &filename);
bool ends_with(std::string const &value, std::string const &ending);