use spdlog for logging in ws + unittest + remove un-needed mutex

This commit is contained in:
Benjamin Sergeant
2019-05-09 15:30:44 -07:00
parent 234ce4c173
commit c7f0bf3d64
114 changed files with 29168 additions and 6 deletions

29
third_party/spdlog/tests/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,29 @@
project(spdlog-utests CXX)
find_package(Threads REQUIRED)
set(SPDLOG_UTESTS_SOURCES
test_errors.cpp
test_file_helper.cpp
test_file_logging.cpp
test_misc.cpp
test_pattern_formatter.cpp
test_async.cpp
includes.h
test_registry.cpp
test_macros.cpp
utils.cpp
utils.h
main.cpp
test_mpmc_q.cpp
test_sink.h
test_fmt_helper.cpp)
add_executable(${PROJECT_NAME} ${SPDLOG_UTESTS_SOURCES})
target_link_libraries(${PROJECT_NAME} PRIVATE Threads::Threads)
target_link_libraries(${PROJECT_NAME} PRIVATE spdlog::spdlog)
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/logs")
enable_testing()
add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME})

9427
third_party/spdlog/tests/catch.hpp vendored Normal file

File diff suppressed because it is too large Load Diff

23
third_party/spdlog/tests/catch.license vendored Normal file
View File

@ -0,0 +1,23 @@
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

23
third_party/spdlog/tests/includes.h vendored Normal file
View File

@ -0,0 +1,23 @@
#pragma once
#include "catch.hpp"
#include "utils.h"
#include <chrono>
#include <cstdio>
#include <exception>
#include <fstream>
#include <iostream>
#include <ostream>
#include <string>
#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_DEBUG
#define SPDLOG_ENABLE_MESSAGE_COUNTER
#include "spdlog/spdlog.h"
#include "spdlog/async.h"
#include "spdlog/sinks/basic_file_sink.h"
#include "spdlog/sinks/daily_file_sink.h"
#include "spdlog/sinks/null_sink.h"
#include "spdlog/sinks/ostream_sink.h"
#include "spdlog/sinks/rotating_file_sink.h"
#include "spdlog/sinks/stdout_color_sinks.h"

2
third_party/spdlog/tests/main.cpp vendored Normal file
View File

@ -0,0 +1,2 @@
#define CATCH_CONFIG_MAIN
#include "catch.hpp"

195
third_party/spdlog/tests/test_async.cpp vendored Normal file
View File

@ -0,0 +1,195 @@
#include "includes.h"
#include "spdlog/async.h"
#include "spdlog/sinks/basic_file_sink.h"
#include "test_sink.h"
TEST_CASE("basic async test ", "[async]")
{
using namespace spdlog;
auto test_sink = std::make_shared<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);
for (size_t i = 0; i < messages; i++)
{
logger->info("Hello message #{}", i);
}
logger->flush();
overrun_counter = tp->overrun_counter();
}
REQUIRE(test_sink->msg_counter() == messages);
REQUIRE(test_sink->flush_counter() == 1);
REQUIRE(overrun_counter == 0);
}
TEST_CASE("discard policy ", "[async]")
{
using namespace spdlog;
auto test_sink = std::make_shared<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);
for (size_t i = 0; i < messages; i++)
{
logger->info("Hello message");
}
REQUIRE(test_sink->msg_counter() < messages);
REQUIRE(tp->overrun_counter() > 0);
}
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]);
test_sink->set_delay(std::chrono::milliseconds(1));
for (size_t i = 0; i < messages; i++)
{
logger->info("Hello message");
}
REQUIRE(test_sink->msg_counter() < messages);
spdlog::drop_all();
}
TEST_CASE("flush", "[async]")
{
using namespace spdlog;
auto test_sink = std::make_shared<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);
for (size_t i = 0; i < messages; i++)
{
logger->info("Hello message #{}", i);
}
logger->flush();
}
// std::this_thread::sleep_for(std::chrono::milliseconds(250));
REQUIRE(test_sink->msg_counter() == messages);
REQUIRE(test_sink->flush_counter() == 1);
}
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]);
spdlog::flush_every(std::chrono::seconds(1));
std::this_thread::sleep_for(std::chrono::milliseconds(1100));
REQUIRE(test_sink->flush_counter() == 1);
spdlog::flush_every(std::chrono::seconds(0));
spdlog::drop_all();
}
TEST_CASE("tp->wait_empty() ", "[async]")
{
using namespace spdlog;
auto test_sink = std::make_shared<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);
for (size_t i = 0; i < messages; i++)
{
logger->info("Hello message #{}", i);
}
logger->flush();
tp.reset();
REQUIRE(test_sink->msg_counter() == messages);
REQUIRE(test_sink->flush_counter() == 1);
}
TEST_CASE("multi threads", "[async]")
{
using namespace spdlog;
auto test_sink = std::make_shared<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);
std::vector<std::thread> threads;
for (size_t i = 0; i < n_threads; i++)
{
threads.emplace_back([logger, messages] {
for (size_t j = 0; j < messages; j++)
{
logger->info("Hello message #{}", j);
}
});
logger->flush();
}
for (auto &t : threads)
{
t.join();
}
}
REQUIRE(test_sink->msg_counter() == messages * n_threads);
REQUIRE(test_sink->flush_counter() == n_threads);
}
TEST_CASE("to_file", "[async]")
{
prepare_logdir();
size_t messages = 1024;
size_t tp_threads = 1;
std::string filename = "logs/async_test.log";
{
auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename, true);
auto tp = std::make_shared<spdlog::details::thread_pool>(messages, tp_threads);
auto logger = std::make_shared<spdlog::async_logger>("as", std::move(file_sink), std::move(tp));
for (size_t j = 0; j < messages; j++)
{
logger->info("Hello message #{}", j);
}
}
REQUIRE(count_lines(filename) == messages);
auto contents = file_contents(filename);
REQUIRE(ends_with(contents, std::string("Hello message #1023\n")));
}
TEST_CASE("to_file multi-workers", "[async]")
{
prepare_logdir();
size_t messages = 1024 * 10;
size_t tp_threads = 10;
std::string filename = "logs/async_test.log";
{
auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename, true);
auto tp = std::make_shared<spdlog::details::thread_pool>(messages, tp_threads);
auto logger = std::make_shared<spdlog::async_logger>("as", std::move(file_sink), std::move(tp));
for (size_t j = 0; j < messages; j++)
{
logger->info("Hello message #{}", j);
}
}
REQUIRE(count_lines(filename) == messages);
}

121
third_party/spdlog/tests/test_errors.cpp vendored Normal file
View File

@ -0,0 +1,121 @@
/*
* This content is released under the MIT License as specified in https://raw.githubusercontent.com/gabime/spdlog/master/LICENSE
*/
#include "includes.h"
#include <iostream>
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
{
throw std::runtime_error("some error happened during log");
}
void flush_() final
{
throw std::runtime_error("some error happened during flush");
}
};
TEST_CASE("default_error_handler", "[errors]]")
{
prepare_logdir();
std::string filename = "logs/simple_log.txt";
auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("test-error", filename, true);
logger->set_pattern("%v");
logger->info("Test message {} {}", 1);
logger->info("Test message {}", 2);
logger->flush();
REQUIRE(file_contents(filename) == std::string("Test message 2\n"));
REQUIRE(count_lines(filename) == 1);
}
struct custom_ex
{
};
TEST_CASE("custom_error_handler", "[errors]]")
{
prepare_logdir();
std::string filename = "logs/simple_log.txt";
auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("logger", filename, true);
logger->flush_on(spdlog::level::info);
logger->set_error_handler([=](const std::string &) { throw custom_ex(); });
logger->info("Good message #1");
REQUIRE_THROWS_AS(logger->info("Bad format msg {} {}", "xxx"), custom_ex);
logger->info("Good message #2");
REQUIRE(count_lines(filename) == 2);
}
TEST_CASE("default_error_handler2", "[errors]]")
{
spdlog::drop_all();
auto logger = spdlog::create<failing_sink>("failed_logger");
logger->set_error_handler([=](const std::string &) { throw custom_ex(); });
REQUIRE_THROWS_AS(logger->info("Some message"), custom_ex);
}
TEST_CASE("flush_error_handler", "[errors]]")
{
spdlog::drop_all();
auto logger = spdlog::create<failing_sink>("failed_logger");
logger->set_error_handler([=](const std::string &) { throw custom_ex(); });
REQUIRE_THROWS_AS(logger->flush(), custom_ex);
}
TEST_CASE("async_error_handler", "[errors]]")
{
prepare_logdir();
std::string err_msg("log failed with some msg");
std::string filename = "logs/simple_async_log.txt";
{
spdlog::init_thread_pool(128, 1);
auto logger = spdlog::create_async<spdlog::sinks::basic_file_sink_mt>("logger", filename, true);
logger->set_error_handler([=](const std::string &) {
std::ofstream ofs("logs/custom_err.txt");
if (!ofs)
{
throw std::runtime_error("Failed open logs/custom_err.txt");
}
ofs << err_msg;
});
logger->info("Good message #1");
logger->info("Bad format msg {} {}", "xxx");
logger->info("Good message #2");
spdlog::drop("logger"); // force logger to drain the queue and shutdown
}
spdlog::init_thread_pool(128, 1);
REQUIRE(count_lines(filename) == 2);
REQUIRE(file_contents("logs/custom_err.txt") == err_msg);
}
// Make sure async error handler is executed
TEST_CASE("async_error_handler2", "[errors]]")
{
prepare_logdir();
std::string err_msg("This is async handler error message");
{
spdlog::init_thread_pool(128, 1);
auto logger = spdlog::create_async<failing_sink>("failed_logger");
logger->set_error_handler([=](const std::string &) {
std::ofstream ofs("logs/custom_err2.txt");
if (!ofs)
throw std::runtime_error("Failed open logs/custom_err2.txt");
ofs << err_msg;
});
logger->info("Hello failure");
spdlog::drop("failed_logger"); // force logger to drain the queue and shutdown
}
spdlog::init_thread_pool(128, 1);
REQUIRE(file_contents("logs/custom_err2.txt") == err_msg);
}

View File

@ -0,0 +1,109 @@
/*
* This content is released under the MIT License as specified in https://raw.githubusercontent.com/gabime/spdlog/master/LICENSE
*/
#include "includes.h"
using spdlog::details::file_helper;
using spdlog::details::log_msg;
static const std::string target_filename = "logs/file_helper_test.txt";
static void write_with_helper(file_helper &helper, size_t howmany)
{
fmt::memory_buffer formatted;
fmt::format_to(formatted, "{}", std::string(howmany, '1'));
helper.write(formatted);
helper.flush();
}
TEST_CASE("file_helper_filename", "[file_helper::filename()]]")
{
prepare_logdir();
file_helper helper;
helper.open(target_filename);
REQUIRE(helper.filename() == target_filename);
}
TEST_CASE("file_helper_size", "[file_helper::size()]]")
{
prepare_logdir();
size_t expected_size = 123;
{
file_helper helper;
helper.open(target_filename);
write_with_helper(helper, expected_size);
REQUIRE(static_cast<size_t>(helper.size()) == expected_size);
}
REQUIRE(get_filesize(target_filename) == expected_size);
}
TEST_CASE("file_helper_exists", "[file_helper::file_exists()]]")
{
prepare_logdir();
REQUIRE(!file_helper::file_exists(target_filename));
file_helper helper;
helper.open(target_filename);
REQUIRE(file_helper::file_exists(target_filename));
}
TEST_CASE("file_helper_reopen", "[file_helper::reopen()]]")
{
prepare_logdir();
file_helper helper;
helper.open(target_filename);
write_with_helper(helper, 12);
REQUIRE(helper.size() == 12);
helper.reopen(true);
REQUIRE(helper.size() == 0);
}
TEST_CASE("file_helper_reopen2", "[file_helper::reopen(false)]]")
{
prepare_logdir();
size_t expected_size = 14;
file_helper helper;
helper.open(target_filename);
write_with_helper(helper, expected_size);
REQUIRE(helper.size() == expected_size);
helper.reopen(false);
REQUIRE(helper.size() == expected_size);
}
static void test_split_ext(const char *fname, const char *expect_base, const char *expect_ext)
{
spdlog::filename_t filename(fname);
spdlog::filename_t expected_base(expect_base);
spdlog::filename_t expected_ext(expect_ext);
#ifdef _WIN32 // replace folder sep
std::replace(filename.begin(), filename.end(), '/', '\\');
std::replace(expected_base.begin(), expected_base.end(), '/', '\\');
#endif
spdlog::filename_t basename, ext;
std::tie(basename, ext) = file_helper::split_by_extension(filename);
REQUIRE(basename == expected_base);
REQUIRE(ext == expected_ext);
}
TEST_CASE("file_helper_split_by_extension", "[file_helper::split_by_extension()]]")
{
test_split_ext("mylog.txt", "mylog", ".txt");
test_split_ext(".mylog.txt", ".mylog", ".txt");
test_split_ext(".mylog", ".mylog", "");
test_split_ext("/aaa/bb.d/mylog", "/aaa/bb.d/mylog", "");
test_split_ext("/aaa/bb.d/mylog.txt", "/aaa/bb.d/mylog", ".txt");
test_split_ext("aaa/bbb/ccc/mylog.txt", "aaa/bbb/ccc/mylog", ".txt");
test_split_ext("aaa/bbb/ccc/mylog.", "aaa/bbb/ccc/mylog.", "");
test_split_ext("aaa/bbb/ccc/.mylog.txt", "aaa/bbb/ccc/.mylog", ".txt");
test_split_ext("/aaa/bbb/ccc/mylog.txt", "/aaa/bbb/ccc/mylog", ".txt");
test_split_ext("/aaa/bbb/ccc/.mylog", "/aaa/bbb/ccc/.mylog", "");
test_split_ext("../mylog.txt", "../mylog", ".txt");
test_split_ext(".././mylog.txt", ".././mylog", ".txt");
test_split_ext(".././mylog.txt/xxx", ".././mylog.txt/xxx", "");
test_split_ext("/mylog.txt", "/mylog", ".txt");
test_split_ext("//mylog.txt", "//mylog", ".txt");
test_split_ext("", "", "");
test_split_ext(".", ".", "");
test_split_ext("..txt", ".", ".txt");
}

View File

@ -0,0 +1,173 @@
/*
* This content is released under the MIT License as specified in https://raw.githubusercontent.com/gabime/spdlog/master/LICENSE
*/
#include "includes.h"
TEST_CASE("simple_file_logger", "[simple_logger]]")
{
prepare_logdir();
std::string filename = "logs/simple_log";
auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("logger", filename);
logger->set_pattern("%v");
logger->info("Test message {}", 1);
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);
}
TEST_CASE("flush_on", "[flush_on]]")
{
prepare_logdir();
std::string filename = "logs/simple_log";
auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("logger", filename);
logger->set_pattern("%v");
logger->set_level(spdlog::level::trace);
logger->flush_on(spdlog::level::info);
logger->trace("Should not be flushed");
REQUIRE(count_lines(filename) == 0);
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);
}
TEST_CASE("rotating_file_logger1", "[rotating_logger]]")
{
prepare_logdir();
size_t max_size = 1024 * 10;
std::string basename = "logs/rotating_log";
auto logger = spdlog::rotating_logger_mt("logger", basename, max_size, 0);
for (int i = 0; i < 10; ++i)
{
logger->info("Test message {}", i);
}
logger->flush();
auto filename = basename;
REQUIRE(count_lines(filename) == 10);
}
TEST_CASE("rotating_file_logger2", "[rotating_logger]]")
{
prepare_logdir();
size_t max_size = 1024 * 10;
std::string basename = "logs/rotating_log";
auto logger = spdlog::rotating_logger_mt("logger", basename, max_size, 1);
for (int i = 0; i < 10; ++i)
{
logger->info("Test message {}", i);
}
logger->flush();
auto filename = basename;
REQUIRE(count_lines(filename) == 10);
for (int i = 0; i < 1000; i++)
{
logger->info("Test message {}", i);
}
logger->flush();
REQUIRE(get_filesize(filename) <= max_size);
auto filename1 = basename + ".1";
REQUIRE(get_filesize(filename1) <= max_size);
}
TEST_CASE("daily_logger with dateonly calculator", "[daily_logger_dateonly]]")
{
using sink_type = spdlog::sinks::daily_file_sink<std::mutex, spdlog::sinks::daily_filename_calculator>;
prepare_logdir();
// calculate filename (time based)
std::string basename = "logs/daily_dateonly";
std::tm tm = spdlog::details::os::localtime();
fmt::memory_buffer w;
fmt::format_to(w, "{}_{:04d}-{:02d}-{:02d}", basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
auto logger = spdlog::create<sink_type>("logger", basename, 0, 0);
for (int i = 0; i < 10; ++i)
{
logger->info("Test message {}", i);
}
logger->flush();
auto filename = fmt::to_string(w);
REQUIRE(count_lines(filename) == 10);
}
struct custom_daily_file_name_calculator
{
static spdlog::filename_t calc_filename(const spdlog::filename_t &basename, const tm &now_tm)
{
fmt::memory_buffer w;
fmt::format_to(w, "{}{:04d}{:02d}{:02d}", basename, now_tm.tm_year + 1900, now_tm.tm_mon + 1, now_tm.tm_mday);
return fmt::to_string(w);
}
};
TEST_CASE("daily_logger with custom calculator", "[daily_logger_custom]]")
{
using sink_type = spdlog::sinks::daily_file_sink<std::mutex, custom_daily_file_name_calculator>;
prepare_logdir();
// calculate filename (time based)
std::string basename = "logs/daily_dateonly";
std::tm tm = spdlog::details::os::localtime();
fmt::memory_buffer w;
fmt::format_to(w, "{}{:04d}{:02d}{:02d}", basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
auto logger = spdlog::create<sink_type>("logger", basename, 0, 0);
for (int i = 0; i < 10; ++i)
{
logger->info("Test message {}", i);
}
logger->flush();
auto filename = fmt::to_string(w);
REQUIRE(count_lines(filename) == 10);
}
/*
* File name calculations
*/
TEST_CASE("rotating_file_sink::calc_filename1", "[rotating_file_sink]]")
{
auto filename = spdlog::sinks::rotating_file_sink_st::calc_filename("rotated.txt", 3);
REQUIRE(filename == "rotated.3.txt");
}
TEST_CASE("rotating_file_sink::calc_filename2", "[rotating_file_sink]]")
{
auto filename = spdlog::sinks::rotating_file_sink_st::calc_filename("rotated", 3);
REQUIRE(filename == "rotated.3");
}
TEST_CASE("rotating_file_sink::calc_filename3", "[rotating_file_sink]]")
{
auto filename = spdlog::sinks::rotating_file_sink_st::calc_filename("rotated.txt", 0);
REQUIRE(filename == "rotated.txt");
}
// regex supported only from gcc 4.9 and above
#if defined(_MSC_VER) || !(__GNUC__ <= 4 && __GNUC_MINOR__ < 9)
#include <regex>
TEST_CASE("daily_file_sink::daily_filename_calculator", "[daily_file_sink]]")
{
// daily_YYYY-MM-DD_hh-mm.txt
auto filename = spdlog::sinks::daily_filename_calculator::calc_filename("daily.txt", spdlog::details::os::localtime());
// date regex based on https://www.regular-expressions.info/dates.html
std::regex re(R"(^daily_(19|20)\d\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])\.txt$)");
std::smatch match;
REQUIRE(std::regex_match(filename, match, re));
}
#endif

View File

@ -0,0 +1,75 @@
#include "includes.h"
void test_pad2(int n, const char *expected)
{
fmt::memory_buffer buf;
spdlog::details::fmt_helper::pad2(n, buf);
REQUIRE(fmt::to_string(buf) == expected);
}
void test_pad3(uint32_t n, const char *expected)
{
fmt::memory_buffer buf;
spdlog::details::fmt_helper::pad3(n, buf);
REQUIRE(fmt::to_string(buf) == expected);
}
void test_pad6(std::size_t n, const char *expected)
{
fmt::memory_buffer buf;
spdlog::details::fmt_helper::pad6(n, buf);
REQUIRE(fmt::to_string(buf) == expected);
}
void test_pad9(std::size_t n, const char *expected)
{
fmt::memory_buffer buf;
spdlog::details::fmt_helper::pad9(n, buf);
REQUIRE(fmt::to_string(buf) == expected);
}
TEST_CASE("pad2", "[fmt_helper]")
{
test_pad2(0, "00");
test_pad2(3, "03");
test_pad2(23, "23");
test_pad2(123, "123");
test_pad2(1234, "1234");
test_pad2(-5, "-5");
}
TEST_CASE("pad3", "[fmt_helper]")
{
test_pad3(0, "000");
test_pad3(3, "003");
test_pad3(23, "023");
test_pad3(123, "123");
test_pad3(1234, "1234");
}
TEST_CASE("pad6", "[fmt_helper]")
{
test_pad6(0, "000000");
test_pad6(3, "000003");
test_pad6(23, "000023");
test_pad6(123, "000123");
test_pad6(1234, "001234");
test_pad6(12345, "012345");
test_pad6(123456, "123456");
}
TEST_CASE("pad9", "[fmt_helper]")
{
test_pad9(0, "000000000");
test_pad9(3, "000000003");
test_pad9(23, "000000023");
test_pad9(123, "000000123");
test_pad9(1234, "000001234");
test_pad9(12345, "000012345");
test_pad9(123456, "000123456");
test_pad9(1234567, "001234567");
test_pad9(12345678, "012345678");
test_pad9(123456789, "123456789");
test_pad9(1234567891, "1234567891");
}

View File

@ -0,0 +1,41 @@
/*
* This content is released under the MIT License as specified in https://raw.githubusercontent.com/gabime/spdlog/master/LICENSE
*/
#include "includes.h"
#if SPDLOG_ACTIVE_LEVEL != SPDLOG_LEVEL_DEBUG
#error "Invalid SPDLOG_ACTIVE_LEVEL in test. Should be SPDLOG_LEVEL_DEBUG"
#endif
TEST_CASE("debug and trace w/o format string", "[macros]]")
{
prepare_logdir();
std::string filename = "logs/simple_log";
auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("logger", filename);
logger->set_pattern("%v");
logger->set_level(spdlog::level::trace);
SPDLOG_LOGGER_TRACE(logger, "Test message 1");
SPDLOG_LOGGER_DEBUG(logger, "Test message 2");
logger->flush();
REQUIRE(ends_with(file_contents(filename), "Test message 2\n"));
REQUIRE(count_lines(filename) == 1);
spdlog::set_default_logger(logger);
SPDLOG_TRACE("Test message 3");
SPDLOG_DEBUG("Test message {}", 4);
logger->flush();
REQUIRE(ends_with(file_contents(filename), "Test message 4\n"));
REQUIRE(count_lines(filename) == 2);
}
TEST_CASE("disable param evaluation", "[macros]")
{
SPDLOG_TRACE("Test message {}", throw std::runtime_error("Should not be evaluated"));
}

233
third_party/spdlog/tests/test_misc.cpp vendored Normal file
View File

@ -0,0 +1,233 @@
#include "includes.h"
#include "test_sink.h"
template<class T>
std::string log_info(const T &what, spdlog::level::level_enum logger_level = spdlog::level::info)
{
std::ostringstream oss;
auto oss_sink = std::make_shared<spdlog::sinks::ostream_sink_mt>(oss);
spdlog::logger oss_logger("oss", oss_sink);
oss_logger.set_level(logger_level);
oss_logger.set_pattern("%v");
oss_logger.info(what);
return oss.str().substr(0, oss.str().length() - strlen(spdlog::details::os::default_eol));
}
TEST_CASE("basic_logging ", "[basic_logging]")
{
// const char
REQUIRE(log_info("Hello") == "Hello");
REQUIRE(log_info("") == "");
// std::string
REQUIRE(log_info(std::string("Hello")) == "Hello");
REQUIRE(log_info(std::string()) == std::string());
// Numbers
REQUIRE(log_info(5) == "5");
REQUIRE(log_info(5.6) == "5.6");
// User defined class
// REQUIRE(log_info(some_logged_class("some_val")) == "some_val");
}
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::info) == "Hello");
REQUIRE(log_info("Hello", spdlog::level::debug) == "Hello");
REQUIRE(log_info("Hello", spdlog::level::trace) == "Hello");
}
TEST_CASE("level_to_string_view", "[convert_to_string_view")
{
REQUIRE(spdlog::level::to_string_view(spdlog::level::trace) == "trace");
REQUIRE(spdlog::level::to_string_view(spdlog::level::debug) == "debug");
REQUIRE(spdlog::level::to_string_view(spdlog::level::info) == "info");
REQUIRE(spdlog::level::to_string_view(spdlog::level::warn) == "warning");
REQUIRE(spdlog::level::to_string_view(spdlog::level::err) == "error");
REQUIRE(spdlog::level::to_string_view(spdlog::level::critical) == "critical");
REQUIRE(spdlog::level::to_string_view(spdlog::level::off) == "off");
}
TEST_CASE("to_short_c_str", "[convert_to_short_c_str]")
{
REQUIRE(std::string(spdlog::level::to_short_c_str(spdlog::level::trace)) == "T");
REQUIRE(std::string(spdlog::level::to_short_c_str(spdlog::level::debug)) == "D");
REQUIRE(std::string(spdlog::level::to_short_c_str(spdlog::level::info)) == "I");
REQUIRE(std::string(spdlog::level::to_short_c_str(spdlog::level::warn)) == "W");
REQUIRE(std::string(spdlog::level::to_short_c_str(spdlog::level::err)) == "E");
REQUIRE(std::string(spdlog::level::to_short_c_str(spdlog::level::critical)) == "C");
REQUIRE(std::string(spdlog::level::to_short_c_str(spdlog::level::off)) == "O");
}
TEST_CASE("to_level_enum", "[convert_to_level_enum]")
{
REQUIRE(spdlog::level::from_str("trace") == spdlog::level::trace);
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("error") == spdlog::level::err);
REQUIRE(spdlog::level::from_str("critical") == spdlog::level::critical);
REQUIRE(spdlog::level::from_str("off") == spdlog::level::off);
REQUIRE(spdlog::level::from_str("null") == spdlog::level::off);
}
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]);
spdlog::flush_every(std::chrono::seconds(1));
std::this_thread::sleep_for(std::chrono::milliseconds(1250));
REQUIRE(test_sink->flush_counter() == 1);
spdlog::flush_every(std::chrono::seconds(0));
spdlog::drop_all();
}
TEST_CASE("clone-logger", "[clone]")
{
using namespace spdlog;
auto logger = spdlog::create<sinks::test_sink_mt>("orig");
auto cloned = logger->clone("clone");
REQUIRE(cloned->name() == "clone");
REQUIRE(logger->sinks() == cloned->sinks());
REQUIRE(logger->level() == cloned->level());
REQUIRE(logger->flush_level() == cloned->flush_level());
logger->info("Some message 1");
cloned->info("Some message 2");
auto test_sink = std::static_pointer_cast<sinks::test_sink_mt>(cloned->sinks()[0]);
REQUIRE(test_sink->msg_counter() == 2);
spdlog::drop_all();
}
TEST_CASE("clone async", "[clone]")
{
using namespace spdlog;
auto logger = spdlog::create_async<sinks::test_sink_mt>("orig");
auto cloned = logger->clone("clone");
REQUIRE(cloned->name() == "clone");
REQUIRE(logger->sinks() == cloned->sinks());
REQUIRE(logger->level() == cloned->level());
REQUIRE(logger->flush_level() == cloned->flush_level());
logger->info("Some message 1");
cloned->info("Some message 2");
spdlog::details::os::sleep_for_millis(10);
auto test_sink = std::static_pointer_cast<sinks::test_sink_mt>(cloned->sinks()[0]);
REQUIRE(test_sink->msg_counter() == 2);
spdlog::drop_all();
}
#include "spdlog/fmt/bin_to_hex.h"
TEST_CASE("to_hex", "[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, 0xc, 0xff, 0xff};
oss_logger.info("{}", spdlog::to_hex(v));
auto output = oss.str();
REQUIRE(ends_with(output, "0000: 09 0a 0b 0c ff ff" + std::string(spdlog::details::os::default_eol)));
}
TEST_CASE("to_hex_upper", "[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, 0xc, 0xff, 0xff};
oss_logger.info("{:X}", spdlog::to_hex(v));
auto output = oss.str();
REQUIRE(ends_with(output, "0000: 09 0A 0B 0C FF FF" + std::string(spdlog::details::os::default_eol)));
}
TEST_CASE("to_hex_no_delimiter", "[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, 0xc, 0xff, 0xff};
oss_logger.info("{:sX}", spdlog::to_hex(v));
auto output = oss.str();
REQUIRE(ends_with(output, "0000: 090A0B0CFFFF" + std::string(spdlog::details::os::default_eol)));
}
TEST_CASE("message_counter", "[message_counter]")
{
std::ostringstream oss;
auto oss_sink = std::make_shared<spdlog::sinks::ostream_sink_mt>(oss);
spdlog::logger oss_logger("oss", oss_sink);
oss_logger.set_pattern("%i %v");
oss_logger.info("Hello");
REQUIRE(oss.str() == "000001 Hello" + std::string(spdlog::details::os::default_eol));
oss.str("");
oss_logger.info("Hello again");
REQUIRE(oss.str() == "000002 Hello again" + std::string(spdlog::details::os::default_eol));
}
TEST_CASE("default logger API", "[default logger]")
{
std::ostringstream oss;
auto oss_sink = std::make_shared<spdlog::sinks::ostream_sink_mt>(oss);
spdlog::set_default_logger(std::make_shared<spdlog::logger>("oss", oss_sink));
spdlog::set_pattern("*** %v");
spdlog::default_logger()->set_level(spdlog::level::trace);
spdlog::trace("hello trace");
REQUIRE(oss.str() == "*** hello trace" + std::string(spdlog::details::os::default_eol));
oss.str("");
spdlog::debug("hello debug");
REQUIRE(oss.str() == "*** hello debug" + std::string(spdlog::details::os::default_eol));
oss.str("");
spdlog::info("Hello");
REQUIRE(oss.str() == "*** Hello" + std::string(spdlog::details::os::default_eol));
oss.str("");
spdlog::warn("Hello again {}", 2);
REQUIRE(oss.str() == "*** Hello again 2" + std::string(spdlog::details::os::default_eol));
oss.str("");
spdlog::error(123);
REQUIRE(oss.str() == "*** 123" + std::string(spdlog::details::os::default_eol));
oss.str("");
spdlog::critical(std::string("some string"));
REQUIRE(oss.str() == "*** some string" + std::string(spdlog::details::os::default_eol));
oss.str("");
spdlog::set_level(spdlog::level::info);
spdlog::debug("should not be logged");
REQUIRE(oss.str().empty());
spdlog::drop_all();
spdlog::set_pattern("%v");
}

107
third_party/spdlog/tests/test_mpmc_q.cpp vendored Normal file
View File

@ -0,0 +1,107 @@
#include "includes.h"
using namespace std::chrono;
using std::chrono::milliseconds;
using test_clock = std::chrono::high_resolution_clock;
static milliseconds millis_from(const test_clock::time_point &tp0)
{
return std::chrono::duration_cast<milliseconds>(test_clock::now() - tp0);
}
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;
auto start = test_clock::now();
auto rv = q.dequeue_for(popped_item, milliseconds::zero());
auto delta_ms = millis_from(start);
REQUIRE(rv == false);
INFO("Delta " << delta_ms.count() << " millis");
REQUIRE(delta_ms <= tolerance_wait);
}
TEST_CASE("dequeue-empty-wait", "[mpmc_blocking_q]")
{
size_t q_size = 100;
milliseconds wait_ms(250);
milliseconds tolerance_wait(50);
spdlog::details::mpmc_blocking_queue<int> q(q_size);
int popped_item;
auto start = test_clock::now();
auto rv = q.dequeue_for(popped_item, wait_ms);
auto delta_ms = millis_from(start);
REQUIRE(rv == false);
INFO("Delta " << delta_ms.count() << " millis");
REQUIRE(delta_ms >= wait_ms - tolerance_wait);
REQUIRE(delta_ms <= wait_ms + tolerance_wait);
}
TEST_CASE("enqueue_nowait", "[mpmc_blocking_q]")
{
size_t q_size = 1;
spdlog::details::mpmc_blocking_queue<int> q(q_size);
milliseconds tolerance_wait(10);
q.enqueue(1);
REQUIRE(q.overrun_counter() == 0);
auto start = test_clock::now();
q.enqueue_nowait(2);
auto delta_ms = millis_from(start);
INFO("Delta " << delta_ms.count() << " millis");
REQUIRE(delta_ms <= tolerance_wait);
REQUIRE(q.overrun_counter() == 1);
}
TEST_CASE("bad_queue", "[mpmc_blocking_q]")
{
size_t q_size = 0;
spdlog::details::mpmc_blocking_queue<int> q(q_size);
q.enqueue_nowait(1);
REQUIRE(q.overrun_counter() == 1);
int i;
REQUIRE(q.dequeue_for(i, milliseconds(0)) == false);
}
TEST_CASE("empty_queue", "[mpmc_blocking_q]")
{
size_t q_size = 10;
spdlog::details::mpmc_blocking_queue<int> q(q_size);
int i;
REQUIRE(q.dequeue_for(i, milliseconds(10)) == false);
}
TEST_CASE("full_queue", "[mpmc_blocking_q]")
{
size_t q_size = 100;
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_nowait(123456);
REQUIRE(q.overrun_counter() == 1);
for (int i = 1; i < static_cast<int>(q_size); i++)
{
int item = -1;
q.dequeue_for(item, milliseconds(0));
REQUIRE(item == i);
}
// last item pushed has overridden the oldest.
int item = -1;
q.dequeue_for(item, milliseconds(0));
REQUIRE(item == 123456);
}

View File

@ -0,0 +1,255 @@
#include "includes.h"
// log to str and return it
template<typename... Args>
static std::string log_to_str(const std::string &msg, const Args &... args)
{
std::ostringstream oss;
auto oss_sink = std::make_shared<spdlog::sinks::ostream_sink_mt>(oss);
spdlog::logger oss_logger("pattern_tester", oss_sink);
oss_logger.set_level(spdlog::level::info);
oss_logger.set_formatter(std::unique_ptr<spdlog::formatter>(new spdlog::pattern_formatter(args...)));
oss_logger.info(msg);
return oss.str();
}
TEST_CASE("custom eol", "[pattern_formatter]")
{
std::string msg = "Hello custom eol test";
std::string eol = ";)";
REQUIRE(log_to_str(msg, "%v", spdlog::pattern_time_type::local, ";)") == msg + eol);
}
TEST_CASE("empty format", "[pattern_formatter]")
{
REQUIRE(log_to_str("Some message", "", spdlog::pattern_time_type::local, "") == "");
}
TEST_CASE("empty format2", "[pattern_formatter]")
{
REQUIRE(log_to_str("Some message", "", spdlog::pattern_time_type::local, "\n") == "\n");
}
TEST_CASE("level", "[pattern_formatter]")
{
REQUIRE(log_to_str("Some message", "[%l] %v", spdlog::pattern_time_type::local, "\n") == "[info] Some message\n");
}
TEST_CASE("short level", "[pattern_formatter]")
{
REQUIRE(log_to_str("Some message", "[%L] %v", spdlog::pattern_time_type::local, "\n") == "[I] Some message\n");
}
TEST_CASE("name", "[pattern_formatter]")
{
REQUIRE(log_to_str("Some message", "[%n] %v", spdlog::pattern_time_type::local, "\n") == "[pattern_tester] Some message\n");
}
TEST_CASE("date MM/DD/YY ", "[pattern_formatter]")
{
auto now_tm = spdlog::details::os::localtime();
std::stringstream oss;
oss << std::setfill('0') << std::setw(2) << now_tm.tm_mon + 1 << "/" << std::setw(2) << now_tm.tm_mday << "/" << std::setw(2)
<< (now_tm.tm_year + 1900) % 1000 << " Some message\n";
REQUIRE(log_to_str("Some message", "%D %v", spdlog::pattern_time_type::local, "\n") == oss.str());
}
TEST_CASE("color range test1", "[pattern_formatter]")
{
auto formatter = std::make_shared<spdlog::pattern_formatter>("%^%v%$", spdlog::pattern_time_type::local, "\n");
fmt::memory_buffer buf;
fmt::format_to(buf, "Hello");
fmt::memory_buffer formatted;
std::string logger_name = "test";
spdlog::details::log_msg msg(&logger_name, spdlog::level::info, spdlog::string_view_t(buf.data(), buf.size()));
formatter->format(msg, formatted);
REQUIRE(msg.color_range_start == 0);
REQUIRE(msg.color_range_end == 5);
REQUIRE(log_to_str("hello", "%^%v%$", spdlog::pattern_time_type::local, "\n") == "hello\n");
}
TEST_CASE("color range test2", "[pattern_formatter]")
{
auto formatter = std::make_shared<spdlog::pattern_formatter>("%^%$", spdlog::pattern_time_type::local, "\n");
std::string logger_name = "test";
spdlog::details::log_msg msg(&logger_name, spdlog::level::info, "");
fmt::memory_buffer formatted;
formatter->format(msg, formatted);
REQUIRE(msg.color_range_start == 0);
REQUIRE(msg.color_range_end == 0);
REQUIRE(log_to_str("", "%^%$", spdlog::pattern_time_type::local, "\n") == "\n");
}
TEST_CASE("color range test3", "[pattern_formatter]")
{
auto formatter = std::make_shared<spdlog::pattern_formatter>("%^***%$");
std::string logger_name = "test";
spdlog::details::log_msg msg(&logger_name, spdlog::level::info, "ignored");
fmt::memory_buffer formatted;
formatter->format(msg, formatted);
REQUIRE(msg.color_range_start == 0);
REQUIRE(msg.color_range_end == 3);
}
TEST_CASE("color range test4", "[pattern_formatter]")
{
auto formatter = std::make_shared<spdlog::pattern_formatter>("XX%^YYY%$", spdlog::pattern_time_type::local, "\n");
std::string logger_name = "test";
spdlog::details::log_msg msg(&logger_name, spdlog::level::info, "ignored");
fmt::memory_buffer formatted;
formatter->format(msg, formatted);
REQUIRE(msg.color_range_start == 2);
REQUIRE(msg.color_range_end == 5);
REQUIRE(log_to_str("ignored", "XX%^YYY%$", spdlog::pattern_time_type::local, "\n") == "XXYYY\n");
}
TEST_CASE("color range test5", "[pattern_formatter]")
{
auto formatter = std::make_shared<spdlog::pattern_formatter>("**%^");
std::string logger_name = "test";
spdlog::details::log_msg msg(&logger_name, spdlog::level::info, "ignored");
fmt::memory_buffer formatted;
formatter->format(msg, formatted);
REQUIRE(msg.color_range_start == 2);
REQUIRE(msg.color_range_end == 0);
}
TEST_CASE("color range test6", "[pattern_formatter]")
{
auto formatter = std::make_shared<spdlog::pattern_formatter>("**%$");
std::string logger_name = "test";
spdlog::details::log_msg msg(&logger_name, spdlog::level::info, "ignored");
fmt::memory_buffer formatted;
formatter->format(msg, formatted);
REQUIRE(msg.color_range_start == 0);
REQUIRE(msg.color_range_end == 2);
}
//
// Test padding
//
TEST_CASE("level_left_padded", "[pattern_formatter]")
{
REQUIRE(log_to_str("Some message", "[%8l] %v", spdlog::pattern_time_type::local, "\n") == "[ info] Some message\n");
}
TEST_CASE("level_right_padded", "[pattern_formatter]")
{
REQUIRE(log_to_str("Some message", "[%-8l] %v", spdlog::pattern_time_type::local, "\n") == "[info ] Some message\n");
}
TEST_CASE("level_center_padded", "[pattern_formatter]")
{
REQUIRE(log_to_str("Some message", "[%=8l] %v", spdlog::pattern_time_type::local, "\n") == "[ info ] Some message\n");
}
TEST_CASE("short level_left_padded", "[pattern_formatter]")
{
REQUIRE(log_to_str("Some message", "[%3L] %v", spdlog::pattern_time_type::local, "\n") == "[ I] Some message\n");
}
TEST_CASE("short level_right_padded", "[pattern_formatter]")
{
REQUIRE(log_to_str("Some message", "[%-3L] %v", spdlog::pattern_time_type::local, "\n") == "[I ] Some message\n");
}
TEST_CASE("short level_center_padded", "[pattern_formatter]")
{
REQUIRE(log_to_str("Some message", "[%=3L] %v", spdlog::pattern_time_type::local, "\n") == "[ I ] Some message\n");
}
TEST_CASE("left_padded_short", "[pattern_formatter]")
{
REQUIRE(log_to_str("Some message", "[%3n] %v", spdlog::pattern_time_type::local, "\n") == "[pattern_tester] Some message\n");
}
TEST_CASE("right_padded_short", "[pattern_formatter]")
{
REQUIRE(log_to_str("Some message", "[%-3n] %v", spdlog::pattern_time_type::local, "\n") == "[pattern_tester] Some message\n");
}
TEST_CASE("center_padded_short", "[pattern_formatter]")
{
REQUIRE(log_to_str("Some message", "[%=3n] %v", spdlog::pattern_time_type::local, "\n") == "[pattern_tester] Some message\n");
}
TEST_CASE("left_padded_huge", "[pattern_formatter]")
{
REQUIRE(
log_to_str("Some message", "[%-300n] %v", spdlog::pattern_time_type::local, "\n") ==
"[pattern_tester ]"
" Some message\n");
}
TEST_CASE("left_padded_max", "[pattern_formatter]")
{
REQUIRE(
log_to_str("Some message", "[%-128n] %v", spdlog::pattern_time_type::local, "\n") ==
"[pattern_tester ]"
" Some message\n");
}
TEST_CASE("clone-default-formatter", "[pattern_formatter]")
{
auto formatter_1 = std::make_shared<spdlog::pattern_formatter>();
auto formatter_2 = formatter_1->clone();
std::string logger_name = "test";
spdlog::details::log_msg msg(&logger_name, spdlog::level::info, "some message");
fmt::memory_buffer formatted_1;
fmt::memory_buffer formatted_2;
formatter_1->format(msg, formatted_1);
formatter_2->format(msg, formatted_2);
REQUIRE(fmt::to_string(formatted_1) == fmt::to_string(formatted_2));
}
TEST_CASE("clone-default-formatter2", "[pattern_formatter]")
{
auto formatter_1 = std::make_shared<spdlog::pattern_formatter>("%+");
auto formatter_2 = formatter_1->clone();
std::string logger_name = "test";
spdlog::details::log_msg msg(&logger_name, spdlog::level::info, "some message");
fmt::memory_buffer formatted_1;
fmt::memory_buffer formatted_2;
formatter_1->format(msg, formatted_1);
formatter_2->format(msg, formatted_2);
REQUIRE(fmt::to_string(formatted_1) == fmt::to_string(formatted_2));
}
TEST_CASE("clone-formatter", "[pattern_formatter]")
{
auto formatter_1 = std::make_shared<spdlog::pattern_formatter>("%D %X [%] [%n] %v");
auto formatter_2 = formatter_1->clone();
std::string logger_name = "test";
spdlog::details::log_msg msg(&logger_name, spdlog::level::info, "some message");
fmt::memory_buffer formatted_1;
fmt::memory_buffer formatted_2;
formatter_1->format(msg, formatted_1);
formatter_2->format(msg, formatted_2);
REQUIRE(fmt::to_string(formatted_1) == fmt::to_string(formatted_2));
}
TEST_CASE("clone-formatter-2", "[pattern_formatter]")
{
using spdlog::pattern_time_type;
auto formatter_1 = std::make_shared<spdlog::pattern_formatter>("%D %X [%] [%n] %v", pattern_time_type::utc, "xxxxxx\n");
auto formatter_2 = formatter_1->clone();
std::string logger_name = "test2";
spdlog::details::log_msg msg(&logger_name, spdlog::level::info, "some message");
fmt::memory_buffer formatted_1;
fmt::memory_buffer formatted_2;
formatter_1->format(msg, formatted_1);
formatter_2->format(msg, formatted_2);
REQUIRE(fmt::to_string(formatted_1) == fmt::to_string(formatted_2));
}

View File

@ -0,0 +1,114 @@
#include "includes.h"
static const char *tested_logger_name = "null_logger";
static const char *tested_logger_name2 = "null_logger2";
TEST_CASE("register_drop", "[registry]")
{
spdlog::drop_all();
spdlog::create<spdlog::sinks::null_sink_mt>(tested_logger_name);
REQUIRE(spdlog::get(tested_logger_name) != nullptr);
// Throw if registring existing name
REQUIRE_THROWS_AS(spdlog::create<spdlog::sinks::null_sink_mt>(tested_logger_name), const spdlog::spdlog_ex &);
}
TEST_CASE("explicit register", "[registry]")
{
spdlog::drop_all();
auto logger = std::make_shared<spdlog::logger>(tested_logger_name, std::make_shared<spdlog::sinks::null_sink_st>());
spdlog::register_logger(logger);
REQUIRE(spdlog::get(tested_logger_name) != nullptr);
// Throw if registring existing name
REQUIRE_THROWS_AS(spdlog::create<spdlog::sinks::null_sink_mt>(tested_logger_name), const spdlog::spdlog_ex &);
}
TEST_CASE("apply_all", "[registry]")
{
spdlog::drop_all();
auto logger = std::make_shared<spdlog::logger>(tested_logger_name, std::make_shared<spdlog::sinks::null_sink_st>());
spdlog::register_logger(logger);
auto logger2 = std::make_shared<spdlog::logger>(tested_logger_name2, std::make_shared<spdlog::sinks::null_sink_st>());
spdlog::register_logger(logger2);
int counter = 0;
spdlog::apply_all([&counter](std::shared_ptr<spdlog::logger>) { counter++; });
REQUIRE(counter == 2);
counter = 0;
spdlog::drop(tested_logger_name2);
spdlog::apply_all([&counter](std::shared_ptr<spdlog::logger> l) {
REQUIRE(l->name() == tested_logger_name);
counter++;
});
REQUIRE(counter == 1);
}
TEST_CASE("drop", "[registry]")
{
spdlog::drop_all();
spdlog::create<spdlog::sinks::null_sink_mt>(tested_logger_name);
spdlog::drop(tested_logger_name);
REQUIRE_FALSE(spdlog::get(tested_logger_name));
}
TEST_CASE("drop-default", "[registry]")
{
spdlog::set_default_logger(spdlog::null_logger_st(tested_logger_name));
spdlog::drop(tested_logger_name);
REQUIRE_FALSE(spdlog::default_logger());
REQUIRE_FALSE(spdlog::get(tested_logger_name));
}
TEST_CASE("drop_all", "[registry]")
{
spdlog::drop_all();
spdlog::create<spdlog::sinks::null_sink_mt>(tested_logger_name);
spdlog::create<spdlog::sinks::null_sink_mt>(tested_logger_name2);
spdlog::drop_all();
REQUIRE_FALSE(spdlog::get(tested_logger_name));
REQUIRE_FALSE(spdlog::get(tested_logger_name2));
REQUIRE_FALSE(spdlog::default_logger());
}
TEST_CASE("drop non existing", "[registry]")
{
spdlog::drop_all();
spdlog::create<spdlog::sinks::null_sink_mt>(tested_logger_name);
spdlog::drop("some_name");
REQUIRE_FALSE(spdlog::get("some_name"));
REQUIRE(spdlog::get(tested_logger_name));
spdlog::drop_all();
}
TEST_CASE("default logger", "[registry]")
{
spdlog::drop_all();
spdlog::set_default_logger(spdlog::null_logger_st(tested_logger_name));
REQUIRE(spdlog::get(tested_logger_name) == spdlog::default_logger());
spdlog::drop_all();
}
TEST_CASE("set_default_logger(nullptr)", "[registry]")
{
spdlog::set_default_logger(nullptr);
REQUIRE_FALSE(spdlog::default_logger());
}
TEST_CASE("disable automatic registration", "[registry]")
{
// set some global parameters
spdlog::level::level_enum log_level = spdlog::level::level_enum::warn;
spdlog::set_level(log_level);
// but disable automatic registration
spdlog::set_automatic_registration(false);
auto logger1 = spdlog::create<spdlog::sinks::daily_file_sink_st>(tested_logger_name, "filename", 11, 59);
auto logger2 = spdlog::create_async<spdlog::sinks::stdout_color_sink_mt>(tested_logger_name2);
// loggers should not be part of the registry
REQUIRE_FALSE(spdlog::get(tested_logger_name));
REQUIRE_FALSE(spdlog::get(tested_logger_name2));
// but make sure they are still initialized according to global defaults
REQUIRE(logger1->level() == log_level);
REQUIRE(logger2->level() == log_level);
spdlog::set_level(spdlog::level::info);
spdlog::set_automatic_registration(true);
}

59
third_party/spdlog/tests/test_sink.h vendored Normal file
View File

@ -0,0 +1,59 @@
//
// Copyright(c) 2018 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//
#pragma once
#include "spdlog/details/null_mutex.h"
#include "spdlog/sinks/base_sink.h"
#include <chrono>
#include <mutex>
#include <thread>
namespace spdlog {
namespace sinks {
template<class Mutex>
class test_sink : public base_sink<Mutex>
{
public:
size_t msg_counter()
{
std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
return msg_counter_;
}
size_t flush_counter()
{
std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
return flush_counter_;
}
void set_delay(std::chrono::milliseconds delay)
{
delay_ = delay;
}
protected:
void sink_it_(const details::log_msg &) override
{
msg_counter_++;
std::this_thread::sleep_for(delay_);
}
void flush_() override
{
flush_counter_++;
}
size_t msg_counter_{0};
size_t flush_counter_{0};
std::chrono::milliseconds delay_{std::chrono::milliseconds::zero()};
};
using test_sink_mt = test_sink<std::mutex>;
using test_sink_st = test_sink<details::null_mutex>;
} // namespace sinks
} // namespace spdlog

98
third_party/spdlog/tests/tests.sln vendored Normal file
View File

@ -0,0 +1,98 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27428.2037
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tests", "tests.vcxproj", "{59A07559-5F38-4DD6-A7FA-DB4153690B42}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "spdlog", "spdlog", "{0C043010-E40A-43B9-A5EA-B931FC8B6EFB}"
ProjectSection(SolutionItems) = preProject
..\include\spdlog\async.h = ..\include\spdlog\async.h
..\include\spdlog\async_logger.h = ..\include\spdlog\async_logger.h
..\include\spdlog\common.h = ..\include\spdlog\common.h
..\include\spdlog\formatter.h = ..\include\spdlog\formatter.h
..\include\spdlog\logger.h = ..\include\spdlog\logger.h
..\include\spdlog\spdlog.h = ..\include\spdlog\spdlog.h
..\include\spdlog\tweakme.h = ..\include\spdlog\tweakme.h
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "details", "details", "{C8A207B7-6930-4D28-85BB-EA79ADFD7DAC}"
ProjectSection(SolutionItems) = preProject
..\include\spdlog\details\async_logger_impl.h = ..\include\spdlog\details\async_logger_impl.h
..\include\spdlog\details\file_helper.h = ..\include\spdlog\details\file_helper.h
..\include\spdlog\details\log_msg.h = ..\include\spdlog\details\log_msg.h
..\include\spdlog\details\logger_impl.h = ..\include\spdlog\details\logger_impl.h
..\include\spdlog\details\mpmc_bounded_q.h = ..\include\spdlog\details\mpmc_bounded_q.h
..\include\spdlog\details\null_mutex.h = ..\include\spdlog\details\null_mutex.h
..\include\spdlog\details\os.h = ..\include\spdlog\details\os.h
..\include\spdlog\details\pattern_formatter.h = ..\include\spdlog\details\pattern_formatter.h
..\include\spdlog\details\registry.h = ..\include\spdlog\details\registry.h
..\include\spdlog\details\spdlog_impl.h = ..\include\spdlog\details\spdlog_impl.h
..\include\spdlog\details\thread_pool.h = ..\include\spdlog\details\thread_pool.h
..\include\spdlog\details\traits.h = ..\include\spdlog\details\traits.h
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "fmt", "fmt", "{6512BA57-E9B9-4971-BC3A-83C784CC59A5}"
ProjectSection(SolutionItems) = preProject
..\include\spdlog\fmt\fmt.h = ..\include\spdlog\fmt\fmt.h
..\include\spdlog\fmt\ostr.h = ..\include\spdlog\fmt\ostr.h
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "bundled", "bundled", "{F0D4A944-E0C7-4575-8254-06AC92B384E6}"
ProjectSection(SolutionItems) = preProject
..\include\spdlog\fmt\bundled\format.cc = ..\include\spdlog\fmt\bundled\format.cc
..\include\spdlog\fmt\bundled\format.h = ..\include\spdlog\fmt\bundled\format.h
..\include\spdlog\fmt\bundled\LICENSE.rst = ..\include\spdlog\fmt\bundled\LICENSE.rst
..\include\spdlog\fmt\bundled\ostream.cc = ..\include\spdlog\fmt\bundled\ostream.cc
..\include\spdlog\fmt\bundled\ostream.h = ..\include\spdlog\fmt\bundled\ostream.h
..\include\spdlog\fmt\bundled\posix.cc = ..\include\spdlog\fmt\bundled\posix.cc
..\include\spdlog\fmt\bundled\posix.h = ..\include\spdlog\fmt\bundled\posix.h
..\include\spdlog\fmt\bundled\time.h = ..\include\spdlog\fmt\bundled\time.h
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sinks", "sinks", "{093AE34A-B617-467E-8F31-3C5A85EF51EB}"
ProjectSection(SolutionItems) = preProject
..\include\spdlog\sinks\android_sink.h = ..\include\spdlog\sinks\android_sink.h
..\include\spdlog\sinks\ansicolor_sink.h = ..\include\spdlog\sinks\ansicolor_sink.h
..\include\spdlog\sinks\base_sink.h = ..\include\spdlog\sinks\base_sink.h
..\include\spdlog\sinks\dist_sink.h = ..\include\spdlog\sinks\dist_sink.h
..\include\spdlog\sinks\msvc_sink.h = ..\include\spdlog\sinks\msvc_sink.h
..\include\spdlog\sinks\null_sink.h = ..\include\spdlog\sinks\null_sink.h
..\include\spdlog\sinks\ostream_sink.h = ..\include\spdlog\sinks\ostream_sink.h
..\include\spdlog\sinks\sink.h = ..\include\spdlog\sinks\sink.h
..\include\spdlog\sinks\stdout_color_sinks.h = ..\include\spdlog\sinks\stdout_color_sinks.h
..\include\spdlog\sinks\stdout_sinks.h = ..\include\spdlog\sinks\stdout_sinks.h
..\include\spdlog\sinks\syslog_sink.h = ..\include\spdlog\sinks\syslog_sink.h
..\include\spdlog\sinks\wincolor_sink.h = ..\include\spdlog\sinks\wincolor_sink.h
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{59A07559-5F38-4DD6-A7FA-DB4153690B42}.Debug|Win32.ActiveCfg = Debug|Win32
{59A07559-5F38-4DD6-A7FA-DB4153690B42}.Debug|Win32.Build.0 = Debug|Win32
{59A07559-5F38-4DD6-A7FA-DB4153690B42}.Debug|x64.ActiveCfg = Debug|x64
{59A07559-5F38-4DD6-A7FA-DB4153690B42}.Debug|x64.Build.0 = Debug|x64
{59A07559-5F38-4DD6-A7FA-DB4153690B42}.Release|Win32.ActiveCfg = Release|Win32
{59A07559-5F38-4DD6-A7FA-DB4153690B42}.Release|Win32.Build.0 = Release|Win32
{59A07559-5F38-4DD6-A7FA-DB4153690B42}.Release|x64.ActiveCfg = Release|x64
{59A07559-5F38-4DD6-A7FA-DB4153690B42}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{C8A207B7-6930-4D28-85BB-EA79ADFD7DAC} = {0C043010-E40A-43B9-A5EA-B931FC8B6EFB}
{6512BA57-E9B9-4971-BC3A-83C784CC59A5} = {0C043010-E40A-43B9-A5EA-B931FC8B6EFB}
{F0D4A944-E0C7-4575-8254-06AC92B384E6} = {6512BA57-E9B9-4971-BC3A-83C784CC59A5}
{093AE34A-B617-467E-8F31-3C5A85EF51EB} = {0C043010-E40A-43B9-A5EA-B931FC8B6EFB}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {1D363F0E-2DC2-4544-963A-9812679AFF6B}
EndGlobalSection
EndGlobal

148
third_party/spdlog/tests/tests.vcxproj vendored Normal file
View File

@ -0,0 +1,148 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{59A07559-5F38-4DD6-A7FA-DB4153690B42}</ProjectGuid>
<RootNamespace>tests</RootNamespace>
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(SolutionDir)\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(SolutionDir)\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="errors.cpp" />
<ClCompile Include="file_helper.cpp" />
<ClCompile Include="file_log.cpp" />
<ClCompile Include="test_async.cpp" />
<ClCompile Include="test_misc.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="registry.cpp" />
<ClCompile Include="test_macros.cpp" />
<ClCompile Include="test_pattern_formatter.cpp" />
<ClCompile Include="utils.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="catch.hpp" />
<ClInclude Include="includes.h" />
<ClInclude Include="utils.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="file_log.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="registry.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="file_helper.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="utils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="errors.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="test_macros.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="test_pattern_formatter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="test_misc.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="test_async.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="includes.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="catch.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="utils.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>

67
third_party/spdlog/tests/utils.cpp vendored Normal file
View File

@ -0,0 +1,67 @@
#include "includes.h"
void prepare_logdir()
{
spdlog::drop_all();
#ifdef _WIN32
system("if not exist logs mkdir logs");
system("del /F /Q logs\\*");
#else
auto rv = system("mkdir -p logs");
if (rv != 0)
{
throw std::runtime_error("Failed to mkdir -p logs");
}
rv = system("rm -f logs/*");
if (rv != 0)
{
throw std::runtime_error("Failed to rm -f logs/*");
}
#endif
}
std::string file_contents(const std::string &filename)
{
std::ifstream ifs(filename);
if (!ifs)
{
throw std::runtime_error("Failed open file ");
}
return std::string((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
}
std::size_t count_lines(const std::string &filename)
{
std::ifstream ifs(filename);
if (!ifs)
{
throw std::runtime_error("Failed open file ");
}
std::string line;
size_t counter = 0;
while (std::getline(ifs, line))
counter++;
return counter;
}
std::size_t get_filesize(const std::string &filename)
{
std::ifstream ifs(filename, std::ifstream::ate | std::ifstream::binary);
if (!ifs)
{
throw std::runtime_error("Failed open file ");
}
return static_cast<std::size_t>(ifs.tellg());
}
// source: https://stackoverflow.com/a/2072890/192001
bool ends_with(std::string const &value, std::string const &ending)
{
if (ending.size() > value.size())
{
return false;
}
return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
}

16
third_party/spdlog/tests/utils.h vendored Normal file
View File

@ -0,0 +1,16 @@
#pragma once
#include <cstddef>
#include <string>
std::size_t count_lines(const std::string &filename);
void prepare_logdir();
std::string file_contents(const std::string &filename);
std::size_t count_lines(const std::string &filename);
std::size_t get_filesize(const std::string &filename);
bool ends_with(std::string const &value, std::string const &ending);