bleh
This commit is contained in:
parent
6e5045f1f4
commit
693fa17d10
266 changed files with 60543 additions and 1000 deletions
|
@ -0,0 +1,143 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("arithmetic_types_logging")
|
||||
{
|
||||
static constexpr char const* filename = "arithmetic_types_logging.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
BackendOptions bo;
|
||||
bo.error_notifier = [](std::string const&) {};
|
||||
Backend::start(bo);
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
{
|
||||
bool b = true;
|
||||
LOG_INFO(logger, "v [{}]", b);
|
||||
|
||||
char c = 'a';
|
||||
LOG_INFO(logger, "c [{}]", c);
|
||||
|
||||
short int si = -12;
|
||||
LOG_INFO(logger, "si [{}]", si);
|
||||
|
||||
int i = -123;
|
||||
LOG_INFO(logger, "i [{}]", i);
|
||||
|
||||
long int li = 9876;
|
||||
LOG_INFO(logger, "li [{}]", li);
|
||||
|
||||
long long int lli = 321;
|
||||
LOG_INFO(logger, "lli [{}]", lli);
|
||||
|
||||
unsigned short int usi = 15;
|
||||
LOG_INFO(logger, "usi [{}]", usi);
|
||||
|
||||
unsigned int ui = 123;
|
||||
LOG_INFO(logger, "ui [{}]", ui);
|
||||
|
||||
unsigned long int uli = 2876;
|
||||
LOG_INFO(logger, "uli [{}]", uli);
|
||||
|
||||
unsigned long long int ulli = 1321;
|
||||
LOG_INFO(logger, "ulli [{}]", ulli);
|
||||
|
||||
float f = 323.31f;
|
||||
LOG_INFO(logger, "f [{}]", f);
|
||||
|
||||
double d = 3213213.123;
|
||||
LOG_INFO(logger, "d [{}]", d);
|
||||
|
||||
int const& cri = i;
|
||||
LOG_INFO(logger, "cri [{}]", cri);
|
||||
|
||||
int& ci = i;
|
||||
LOG_INFO(logger, "ci [{}]", ci);
|
||||
|
||||
LOG_INFO(logger, "invalid format [{%f}]", 321.1);
|
||||
}
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
REQUIRE_FALSE(Backend::is_running());
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " v [true]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " c [a]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " si [-12]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " i [-123]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " li [9876]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " lli [321]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " usi [15]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ui [123]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " uli [2876]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ulli [1321]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " f [323.31]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " d [3213213.123]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " cri [-123]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents,
|
||||
std::string{"LOG_INFO " + logger_name +
|
||||
" [Could not format log statement. message: \"invalid format [{%f}]\""}));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
#if !defined(QUILL_NO_EXCEPTIONS)
|
||||
|
||||
/***/
|
||||
TEST_CASE("backend_exception_notifier")
|
||||
{
|
||||
static constexpr char const* filename = "backend_exception_notifier.log";
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger("logger", std::move(file_sink));
|
||||
|
||||
// counter to check our error handler was invoked
|
||||
// atomic because we check this value on this thread, but the backend worker thread updates it
|
||||
std::atomic<size_t> error_notifier_invoked{0};
|
||||
|
||||
// Set invalid thread name
|
||||
BackendOptions backend_options;
|
||||
|
||||
// Setting to an invalid CPU. When we call quill::start() our error handler will be invoked and an error will be logged
|
||||
backend_options.backend_cpu_affinity = static_cast<uint16_t>(std::numeric_limits<uint16_t>::max() - 1);
|
||||
|
||||
backend_options.thread_name =
|
||||
"Lorem_ipsum_dolor_sit_amet_consectetur_adipiscing_elit_sed_do_eiusmod_tempor_incididunt_ut_"
|
||||
"labore_et_dolore_magna_aliqua";
|
||||
|
||||
backend_options.error_notifier = [logger, &error_notifier_invoked](std::string const& error_message)
|
||||
{
|
||||
// Log inside the function from the backend thread, for testing
|
||||
|
||||
// Note that this log is asynchronous here which means when error_notifier_invoked is
|
||||
// incremented does not mean we have logged this yet
|
||||
|
||||
// flush_log() is not permitted inside this callback
|
||||
LOG_WARNING(logger, "error handler invoked {}", error_message);
|
||||
|
||||
error_notifier_invoked.fetch_add(1);
|
||||
};
|
||||
|
||||
Backend::start(backend_options);
|
||||
|
||||
// Log a message and wait for it to get processed, that way we know the backend thread has started
|
||||
LOG_INFO(logger, "frontend");
|
||||
logger->flush_log();
|
||||
|
||||
// Check our handler was invoked since either set_backend_thread_name or set_backend_thread_cpu_affinity should have failed
|
||||
REQUIRE_GE(error_notifier_invoked.load(), 1);
|
||||
|
||||
// Now we can try to get another exception by calling LOG_BACKTRACE without calling init first
|
||||
error_notifier_invoked.store(0);
|
||||
|
||||
LOG_BACKTRACE(logger, "Backtrace message");
|
||||
logger->flush_log();
|
||||
|
||||
// Check our handler was invoked
|
||||
REQUIRE_EQ(error_notifier_invoked.load(), 1);
|
||||
|
||||
// Pass an invalid fmt format and see if it throws
|
||||
error_notifier_invoked.store(0);
|
||||
|
||||
LOG_INFO(logger, "Format {:>321.}", 321.3);
|
||||
logger->flush_log();
|
||||
|
||||
// Check our handler was invoked
|
||||
REQUIRE_EQ(error_notifier_invoked.load(), 1);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// After the backend has stopped, all messages include the async ones from the notifier will
|
||||
// be in the log file. At this point we can safely check it
|
||||
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
REQUIRE_GE(file_contents.size(), 5);
|
||||
|
||||
// Look for the async errors
|
||||
std::string const expected_string_1 = "error handler invoked Failed to set cpu affinity ";
|
||||
std::string const expected_string_2 = "error handler invoked Failed to set thread name ";
|
||||
|
||||
bool const has_any_error = quill::testing::file_contains(file_contents, expected_string_1) ||
|
||||
quill::testing::file_contains(file_contents, expected_string_2);
|
||||
|
||||
REQUIRE(has_any_error);
|
||||
|
||||
std::string const expected_string_3 = "error handler invoked logger->init_backtrace(...)";
|
||||
REQUIRE(quill::testing::file_contains(file_contents, expected_string_3));
|
||||
|
||||
std::string const expected_string_4 = "error handler invoked [Could not format log statement.";
|
||||
REQUIRE(quill::testing::file_contains(file_contents, expected_string_4));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,90 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("backend_long_sleep_and_notify")
|
||||
{
|
||||
static constexpr size_t number_of_messages = 100u;
|
||||
static constexpr size_t number_of_threads = 4;
|
||||
static constexpr char const* filename = "log_backend_long_sleep_and_notify.log";
|
||||
static std::string const logger_name_prefix = "logger_";
|
||||
|
||||
// Start the backend thread
|
||||
BackendOptions backend_options;
|
||||
backend_options.sleep_duration = std::chrono::hours{24};
|
||||
Backend::start(backend_options);
|
||||
|
||||
std::vector<std::thread> threads;
|
||||
for (size_t i = 0; i < number_of_threads; ++i)
|
||||
{
|
||||
threads.emplace_back(
|
||||
[i]() mutable
|
||||
{
|
||||
// Also use preallocate
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger =
|
||||
Frontend::create_or_get_logger(logger_name_prefix + std::to_string(i), std::move(file_sink));
|
||||
|
||||
for (size_t j = 0; j < number_of_messages; ++j)
|
||||
{
|
||||
LOG_INFO(logger, "Hello from thread {thread_index} this is message {message_num}", i, j);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (auto& elem : threads)
|
||||
{
|
||||
elem.join();
|
||||
}
|
||||
|
||||
// The backend worker is still sleeping here so no file should exist
|
||||
REQUIRE_EQ(testing::file_contents(filename).size(), 0);
|
||||
|
||||
// Notify the backend to wake up and process
|
||||
Backend::notify();
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = testing::file_contents(filename);
|
||||
REQUIRE_EQ(file_contents.size(), number_of_messages * number_of_threads);
|
||||
|
||||
for (size_t i = 0; i < number_of_threads; ++i)
|
||||
{
|
||||
// for each thread
|
||||
for (size_t j = 0; j < number_of_messages; ++j)
|
||||
{
|
||||
std::string expected_string = logger_name_prefix + std::to_string(i) +
|
||||
" Hello from thread " + std::to_string(i) + " this is message " + std::to_string(j);
|
||||
|
||||
REQUIRE(testing::file_contains(file_contents, expected_string));
|
||||
}
|
||||
}
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("backend_transit_buffer_hard_limit")
|
||||
{
|
||||
static constexpr size_t number_of_messages = 500u;
|
||||
static constexpr size_t number_of_threads = 10;
|
||||
static constexpr char const* filename = "backend_transit_buffer_hard_limit.log";
|
||||
static std::string const logger_name_prefix = "logger_";
|
||||
|
||||
// Start the backend thread
|
||||
BackendOptions backend_options;
|
||||
backend_options.transit_events_hard_limit = 0;
|
||||
backend_options.transit_event_buffer_initial_capacity = 0;
|
||||
Backend::start(backend_options);
|
||||
|
||||
std::vector<std::thread> threads;
|
||||
|
||||
for (size_t i = 0; i < number_of_threads; ++i)
|
||||
{
|
||||
threads.emplace_back(
|
||||
[i]() mutable
|
||||
{
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger =
|
||||
Frontend::create_or_get_logger(logger_name_prefix + std::to_string(i), std::move(file_sink));
|
||||
|
||||
for (size_t j = 0; j < number_of_messages; ++j)
|
||||
{
|
||||
LOG_INFO(logger, "Hello from thread {thread_index} this is message {message_num}", i, j);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (auto& elem : threads)
|
||||
{
|
||||
elem.join();
|
||||
}
|
||||
|
||||
// flush all log and remove all loggers
|
||||
for (Logger* logger : Frontend::get_all_loggers())
|
||||
{
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
}
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = testing::file_contents(filename);
|
||||
|
||||
REQUIRE_EQ(file_contents.size(), number_of_messages * number_of_threads);
|
||||
|
||||
for (size_t i = 0; i < number_of_threads; ++i)
|
||||
{
|
||||
// for each thread
|
||||
for (size_t j = 0; j < number_of_messages; ++j)
|
||||
{
|
||||
std::string expected_string = logger_name_prefix + std::to_string(i) +
|
||||
" Hello from thread " + std::to_string(i) + " this is message " + std::to_string(j);
|
||||
|
||||
REQUIRE(testing::file_contains(file_contents, expected_string));
|
||||
}
|
||||
}
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("backend_transit_buffer_soft_limit")
|
||||
{
|
||||
static constexpr char const* filename = "backend_transit_buffer_soft_limit.log";
|
||||
static std::string const logger_name = "logger";
|
||||
size_t constexpr soft_limit = 100;
|
||||
|
||||
// First log some messages and then start the backend worker thread so that the soft limit is hit
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
for (size_t i = 0; i < soft_limit * 2; ++i)
|
||||
{
|
||||
// log all messages
|
||||
LOG_INFO(logger, "Message num {}", i);
|
||||
}
|
||||
|
||||
// Start the backend thread
|
||||
BackendOptions backend_options;
|
||||
backend_options.transit_events_soft_limit = soft_limit;
|
||||
Backend::start(backend_options);
|
||||
|
||||
// log more messages after the backend started
|
||||
for (size_t i = soft_limit * 2; i < soft_limit * 4; ++i)
|
||||
{
|
||||
// log all messages
|
||||
LOG_INFO(logger, "Message num {}", i);
|
||||
}
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = testing::file_contents(filename);
|
||||
|
||||
size_t const total_messages = soft_limit * 4;
|
||||
REQUIRE_EQ(file_contents.size(), total_messages);
|
||||
|
||||
for (size_t i = 0; i < total_messages; ++i)
|
||||
{
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " Message num "} + std::to_string(i)));
|
||||
}
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("backtrace_dynamic_log_level")
|
||||
{
|
||||
static constexpr char const* filename = "backtrace_dynamic_log_level.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
// Enable backtrace for 2 messages for error
|
||||
logger->init_backtrace(2, LogLevel::Error);
|
||||
|
||||
// log using dynamic log level and flush on warning instead
|
||||
LOG_DYNAMIC(logger, LogLevel::Info, "Before dynamic backtrace log");
|
||||
for (size_t i = 100; i < 120; ++i)
|
||||
{
|
||||
#if defined(__aarch64__) || ((__ARM_ARCH >= 6) || defined(_M_ARM64))
|
||||
// On ARM we add a small delay because log messages can get the same timestamp from rdtsc
|
||||
// when in this loop and make the test unstable
|
||||
std::this_thread::sleep_for(std::chrono::microseconds{200});
|
||||
#endif
|
||||
LOG_DYNAMIC(logger, LogLevel::Backtrace, "Dynamic backtrace log {}", i);
|
||||
}
|
||||
|
||||
LOG_DYNAMIC(logger, LogLevel::Error, "After dynamic error");
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
|
||||
REQUIRE_EQ(file_contents.size(), 4);
|
||||
|
||||
std::string expected_string_1 =
|
||||
"LOG_INFO " + logger_name + " Before dynamic backtrace log";
|
||||
REQUIRE(quill::testing::file_contains(file_contents, expected_string_1));
|
||||
|
||||
std::string expected_string_2 = "LOG_ERROR " + logger_name + " After dynamic error";
|
||||
REQUIRE(quill::testing::file_contains(file_contents, expected_string_2));
|
||||
|
||||
std::string expected_string_3 =
|
||||
"LOG_BACKTRACE " + logger_name + " Dynamic backtrace log 118";
|
||||
REQUIRE(quill::testing::file_contains(file_contents, expected_string_3));
|
||||
|
||||
std::string expected_string_4 =
|
||||
"LOG_BACKTRACE " + logger_name + " Dynamic backtrace log 119";
|
||||
REQUIRE(quill::testing::file_contains(file_contents, expected_string_4));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("backtrace_flush_on_error")
|
||||
{
|
||||
static constexpr char const* filename = "backtrace_flush_on_error.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
// Enable backtrace for 2 messages for error
|
||||
logger->init_backtrace(2, LogLevel::Error);
|
||||
|
||||
// flush backtrace on error
|
||||
LOG_INFO(logger, "Before backtrace log");
|
||||
for (size_t i = 0; i < 12; ++i)
|
||||
{
|
||||
#if defined(__aarch64__) || ((__ARM_ARCH >= 6) || defined(_M_ARM64))
|
||||
// On ARM we add a small delay because log messages can get the same timestamp from rdtsc
|
||||
// when in this loop and make the test unstable
|
||||
std::this_thread::sleep_for(std::chrono::microseconds{200});
|
||||
#endif
|
||||
LOG_BACKTRACE(logger, "Backtrace log {}", i);
|
||||
}
|
||||
LOG_ERROR(logger, "After error");
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
|
||||
REQUIRE_EQ(file_contents.size(), 4);
|
||||
|
||||
std::string expected_string_1 = "LOG_INFO " + logger_name + " Before backtrace log";
|
||||
REQUIRE(quill::testing::file_contains(file_contents, expected_string_1));
|
||||
|
||||
std::string expected_string_2 = "LOG_ERROR " + logger_name + " After error";
|
||||
REQUIRE(quill::testing::file_contains(file_contents, expected_string_2));
|
||||
|
||||
std::string expected_string_3 = "LOG_BACKTRACE " + logger_name + " Backtrace log 10";
|
||||
REQUIRE(quill::testing::file_contains(file_contents, expected_string_3));
|
||||
|
||||
std::string expected_string_4 = "LOG_BACKTRACE " + logger_name + " Backtrace log 11";
|
||||
REQUIRE(quill::testing::file_contains(file_contents, expected_string_4));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("backtrace_manual_flush")
|
||||
{
|
||||
static constexpr char const* filename = "backtrace_manual_flush.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
// Enable backtrace for 2 messages for error
|
||||
logger->init_backtrace(2, LogLevel::Error);
|
||||
|
||||
// flush backtrace on error
|
||||
LOG_INFO(logger, "Before backtrace log");
|
||||
for (size_t i = 0; i < 12; ++i)
|
||||
{
|
||||
#if defined(__aarch64__) || ((__ARM_ARCH >= 6) || defined(_M_ARM64))
|
||||
// On ARM we add a small delay because log messages can get the same timestamp from rdtsc
|
||||
// when in this loop and make the test unstable
|
||||
std::this_thread::sleep_for(std::chrono::microseconds{200});
|
||||
#endif
|
||||
LOG_BACKTRACE(logger, "Backtrace log {}", i);
|
||||
}
|
||||
|
||||
logger->flush_backtrace();
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
|
||||
REQUIRE_EQ(file_contents.size(), 3);
|
||||
|
||||
std::string expected_string_1 = "LOG_INFO " + logger_name + " Before backtrace log";
|
||||
REQUIRE(quill::testing::file_contains(file_contents, expected_string_1));
|
||||
|
||||
std::string expected_string_3 = "LOG_BACKTRACE " + logger_name + " Backtrace log 10";
|
||||
REQUIRE(quill::testing::file_contains(file_contents, expected_string_3));
|
||||
|
||||
std::string expected_string_4 = "LOG_BACKTRACE " + logger_name + " Backtrace log 11";
|
||||
REQUIRE(quill::testing::file_contains(file_contents, expected_string_4));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("backtrace_no_flush")
|
||||
{
|
||||
static constexpr char const* filename = "backtrace_no_flush.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
// Enable backtrace for 2 messages for warning
|
||||
logger->init_backtrace(2, LogLevel::Error);
|
||||
|
||||
// try with LOG_WARNING and expect no flush
|
||||
LOG_INFO(logger, "Before backtrace log retry");
|
||||
for (size_t i = 0; i < 12; ++i)
|
||||
{
|
||||
LOG_BACKTRACE(logger, "Backtrace log {}", i);
|
||||
}
|
||||
LOG_WARNING(logger, "After backtrace log retry");
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
|
||||
REQUIRE_EQ(file_contents.size(), 2);
|
||||
|
||||
std::string expected_string_1 =
|
||||
"LOG_INFO " + logger_name + " Before backtrace log retry";
|
||||
REQUIRE(quill::testing::file_contains(file_contents, expected_string_1));
|
||||
|
||||
std::string expected_string_2 =
|
||||
"LOG_WARNING " + logger_name + " After backtrace log retry";
|
||||
REQUIRE(quill::testing::file_contains(file_contents, expected_string_2));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("backtrace_terminated_thread_flush")
|
||||
{
|
||||
// In this test we store in backtrace from one thread that terminates
|
||||
// then we log that backtrace from a different thread
|
||||
|
||||
static constexpr char const* filename = "backtrace_terminated_thread_flush.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
std::thread thread_a(
|
||||
[]()
|
||||
{
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
// Get a logger and enable backtrace
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
// Enable backtrace for 2 messages
|
||||
logger->init_backtrace(2, LogLevel::Error);
|
||||
|
||||
LOG_INFO(logger, "Before backtrace log");
|
||||
for (uint32_t i = 0; i < 12; ++i)
|
||||
{
|
||||
LOG_BACKTRACE(logger, "Backtrace message {}", i);
|
||||
}
|
||||
});
|
||||
|
||||
thread_a.join();
|
||||
|
||||
// thread_a logged something in backtrace and finished.
|
||||
// Now we spawn a different thread and LOG_ERROR
|
||||
// we expect to see the backtrace from the previous thread
|
||||
std::thread thread_b(
|
||||
[]()
|
||||
{
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
// Get a logger and enable backtrace
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
LOG_ERROR(logger, "After error");
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
});
|
||||
|
||||
thread_b.join();
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
|
||||
REQUIRE_EQ(file_contents.size(), 4);
|
||||
|
||||
std::string expected_string_1 = "LOG_INFO " + logger_name + " Before backtrace log";
|
||||
REQUIRE(quill::testing::file_contains(file_contents, expected_string_1));
|
||||
|
||||
std::string expected_string_2 = "LOG_ERROR " + logger_name + " After error";
|
||||
REQUIRE(quill::testing::file_contains(file_contents, expected_string_2));
|
||||
|
||||
std::string expected_string_3 = "LOG_BACKTRACE " + logger_name + " Backtrace message 10";
|
||||
REQUIRE(quill::testing::file_contains(file_contents, expected_string_3));
|
||||
|
||||
std::string expected_string_4 = "LOG_BACKTRACE " + logger_name + " Backtrace message 11";
|
||||
REQUIRE(quill::testing::file_contains(file_contents, expected_string_4));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
// Define custom Frontend Options
|
||||
struct CustomFrontendOptions
|
||||
{
|
||||
static constexpr quill::QueueType queue_type = quill::QueueType::BoundedBlocking;
|
||||
static constexpr uint32_t initial_queue_capacity = 131'072;
|
||||
static constexpr uint32_t blocking_queue_retry_interval_ns = 800;
|
||||
static constexpr bool huge_pages_enabled = false;
|
||||
};
|
||||
|
||||
using CustomFrontend = FrontendImpl<CustomFrontendOptions>;
|
||||
using CustomLogger = LoggerImpl<CustomFrontendOptions>;
|
||||
|
||||
TEST_CASE("bounded_blocking_queue")
|
||||
{
|
||||
static constexpr char const* filename = "bounded_blocking_queue.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
auto file_sink = CustomFrontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
CustomLogger* logger = CustomFrontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
for (int i = 0; i < 5000; ++i)
|
||||
{
|
||||
LOG_INFO(logger, "Log something to fulfill the bound queue {}", i);
|
||||
LOG_WARNING(logger, "Log something to fulfill the bound queue {}", i);
|
||||
LOG_ERROR(logger, "Log something to fulfill the bound queue {}", i);
|
||||
}
|
||||
|
||||
logger->flush_log();
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check the first messages as we can't if some were dropped
|
||||
std::vector<std::string> const file_contents = testing::file_contents(filename);
|
||||
|
||||
for (int i = 0; i < 5000; ++i)
|
||||
{
|
||||
std::string expected_string_1 = "LOG_INFO " + logger_name +
|
||||
" Log something to fulfill the bound queue " + std::to_string(i);
|
||||
|
||||
std::string expected_string_2 = "LOG_WARNING " + logger_name +
|
||||
" Log something to fulfill the bound queue " + std::to_string(i);
|
||||
|
||||
std::string expected_string_3 = "LOG_ERROR " + logger_name +
|
||||
" Log something to fulfill the bound queue " + std::to_string(i);
|
||||
|
||||
REQUIRE(testing::file_contains(file_contents, expected_string_1));
|
||||
REQUIRE(testing::file_contains(file_contents, expected_string_2));
|
||||
REQUIRE(testing::file_contains(file_contents, expected_string_3));
|
||||
}
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
// Define custom Frontend Options
|
||||
struct CustomFrontendOptions
|
||||
{
|
||||
static constexpr quill::QueueType queue_type = quill::QueueType::BoundedDropping;
|
||||
static constexpr uint32_t initial_queue_capacity = 131'072;
|
||||
static constexpr uint32_t blocking_queue_retry_interval_ns = 800;
|
||||
static constexpr bool huge_pages_enabled = false;
|
||||
};
|
||||
|
||||
using CustomFrontend = FrontendImpl<CustomFrontendOptions>;
|
||||
using CustomLogger = LoggerImpl<CustomFrontendOptions>;
|
||||
|
||||
TEST_CASE("bounded_dropping_queue")
|
||||
{
|
||||
static constexpr char const* filename = "bounded_dropping_queue.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
auto file_sink = CustomFrontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
CustomLogger* logger = CustomFrontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
for (int i = 0; i < 5000; ++i)
|
||||
{
|
||||
LOG_INFO(logger, "Log something to fulfill the bound queue {}", i);
|
||||
LOG_WARNING(logger, "Log something to fulfill the bound queue {}", i);
|
||||
LOG_ERROR(logger, "Log something to fulfill the bound queue {}", i);
|
||||
}
|
||||
|
||||
logger->flush_log();
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check the first messages as we can't if some were dropped
|
||||
std::vector<std::string> const file_contents = testing::file_contents(filename);
|
||||
|
||||
for (int i = 0; i < 100; ++i)
|
||||
{
|
||||
std::string expected_string_1 = "LOG_INFO " + logger_name +
|
||||
" Log something to fulfill the bound queue " + std::to_string(i);
|
||||
|
||||
std::string expected_string_2 = "LOG_WARNING " + logger_name +
|
||||
" Log something to fulfill the bound queue " + std::to_string(i);
|
||||
|
||||
std::string expected_string_3 = "LOG_ERROR " + logger_name +
|
||||
" Log something to fulfill the bound queue " + std::to_string(i);
|
||||
|
||||
REQUIRE(testing::file_contains(file_contents, expected_string_1));
|
||||
REQUIRE(testing::file_contains(file_contents, expected_string_2));
|
||||
REQUIRE(testing::file_contains(file_contents, expected_string_3));
|
||||
}
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
function(quill_add_test TEST_NAME SOURCES)
|
||||
set(HEADER_FILES
|
||||
${PROJECT_SOURCE_DIR}/quill/test/bundled/doctest/doctest.h
|
||||
${PROJECT_SOURCE_DIR}/quill/test/misc/TestUtilities.h
|
||||
)
|
||||
|
||||
set(ADD_SOURCE_FILES
|
||||
${PROJECT_SOURCE_DIR}/quill/test/misc/TestMain.cpp
|
||||
${PROJECT_SOURCE_DIR}/quill/test/misc/TestUtilities.cpp
|
||||
${PROJECT_SOURCE_DIR}/quill/test/misc/DocTestExtensions.cpp)
|
||||
|
||||
list(APPEND SOURCES ${ADD_SOURCE_FILES})
|
||||
|
||||
# Create a test executable
|
||||
add_executable(${TEST_NAME} "")
|
||||
|
||||
set_common_compile_options(${TEST_NAME})
|
||||
|
||||
# Add sources
|
||||
target_sources(${TEST_NAME} PRIVATE ${SOURCES} ${HEADER_FILES})
|
||||
|
||||
# include dirs
|
||||
target_include_directories(${TEST_NAME}
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/quill/test/misc>
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/quill/test/bundled>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
PRIVATE
|
||||
${PROJECT_SOURCE_DIR}/quill/test)
|
||||
|
||||
# Link dependencies
|
||||
target_link_libraries(${TEST_NAME} quill)
|
||||
|
||||
# Do not decay cxx standard if not specified
|
||||
set_property(TARGET ${TEST_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# Set output test directory
|
||||
set_target_properties(${TEST_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build/test)
|
||||
|
||||
# Add this target to the post build unit tests
|
||||
doctest_discover_tests(${TEST_NAME})
|
||||
endfunction()
|
||||
|
||||
include(${PROJECT_SOURCE_DIR}/cmake/doctest.cmake)
|
||||
|
||||
quill_add_test(TEST_ArithmeticTypesLogging ArithmeticTypesLoggingTest.cpp)
|
||||
quill_add_test(TEST_BackendExceptionNotifier BackendExceptionNotifierTest.cpp)
|
||||
quill_add_test(TEST_BackendLongSleepAndNotify BackendLongSleepAndNotifyTest.cpp)
|
||||
quill_add_test(TEST_BackendTransitBufferHardLimit BackendTransitBufferHardLimitTest.cpp)
|
||||
quill_add_test(TEST_BackendTransitBufferSoftLimit BackendTransitBufferSoftLimitTest.cpp)
|
||||
quill_add_test(TEST_BacktraceDynamicLogLevel BacktraceDynamicLogLevelTest.cpp)
|
||||
quill_add_test(TEST_BacktraceFlushOnError BacktraceFlushOnErrorTest.cpp)
|
||||
quill_add_test(TEST_BacktraceManualFlush BacktraceManualFlushTest.cpp)
|
||||
quill_add_test(TEST_BacktraceNoFlush BacktraceNoFlushTest.cpp)
|
||||
quill_add_test(TEST_BacktraceTerminatedThreadFlush BacktraceTerminatedThreadFlushTest.cpp)
|
||||
quill_add_test(TEST_BoundedBlockingQueue BoundedBlockingQueueTest.cpp)
|
||||
quill_add_test(TEST_BoundedDroppingQueue BoundedDroppingQueueTest.cpp)
|
||||
quill_add_test(TEST_ConsoleSinkStderrMultipleFormats ConsoleSinkStderrMultipleFormatsTest.cpp)
|
||||
quill_add_test(TEST_ConsoleSinkStdoutMultipleFormats ConsoleSinkStdoutMultipleFormatsTest.cpp)
|
||||
quill_add_test(TEST_LoggerAddRemoveGet LoggerAddRemoveGetTest.cpp)
|
||||
quill_add_test(TEST_EnumLogging EnumLoggingTest.cpp)
|
||||
quill_add_test(TEST_FlushWithoutAnyLog FlushWithoutAnyLog.cpp)
|
||||
quill_add_test(TEST_JsonConsoleLoggingTest JsonConsoleLoggingTest.cpp)
|
||||
quill_add_test(TEST_JsonFileLogging JsonFileLoggingTest.cpp)
|
||||
quill_add_test(TEST_LogArgumentsEvaluation LogArgumentsEvaluationTest.cpp)
|
||||
quill_add_test(TEST_LogFlushWithSoftLimit LogFlushWithSoftLimitTest.cpp)
|
||||
quill_add_test(TEST_MultiFrontendThreads MultiFrontendThreadsTest.cpp)
|
||||
quill_add_test(TEST_MultipleSinksSameLogger MultipleSinksSameLoggerTest.cpp)
|
||||
quill_add_test(TEST_RotatingSinkDailyRotation RotatingSinkDailyRotationTest.cpp)
|
||||
quill_add_test(TEST_RotatingSinkKeepOldest RotatingSinkKeepOldestTest.cpp)
|
||||
quill_add_test(TEST_RotatingSinkOverwriteOldest RotatingSinkOverwriteOldestTest.cpp)
|
||||
quill_add_test(TEST_SignalHandler SignalHandlerTest.cpp)
|
||||
quill_add_test(TEST_SingleFrontendThread SingleFrontendThreadTest.cpp)
|
||||
quill_add_test(TEST_SinkFilter SinkFilterTest.cpp)
|
||||
quill_add_test(TEST_StdArrayLogging StdArrayLoggingTest.cpp)
|
||||
quill_add_test(TEST_StdDequeLogging StdDequeLoggingTest.cpp)
|
||||
quill_add_test(TEST_StdFilesystemPathLogging StdFilesystemPathLoggingTest.cpp)
|
||||
quill_add_test(TEST_StdForwardListLogging StdForwardListLoggingTest.cpp)
|
||||
quill_add_test(TEST_StdListLogging StdListLoggingTest.cpp)
|
||||
quill_add_test(TEST_StdMapLogging StdMapLoggingTest.cpp)
|
||||
quill_add_test(TEST_StdMultiMapLogging StdMultiMapLoggingTest.cpp)
|
||||
quill_add_test(TEST_StdMultiSetLogging StdMultiSetLoggingTest.cpp)
|
||||
quill_add_test(TEST_StdOptionalLogging StdOptionalLoggingTest.cpp)
|
||||
quill_add_test(TEST_StdPairLogging StdPairLoggingTest.cpp)
|
||||
quill_add_test(TEST_StdSetLogging StdSetLoggingTest.cpp)
|
||||
quill_add_test(TEST_StdTupleLogging StdTupleLoggingTest.cpp)
|
||||
quill_add_test(TEST_StdUnorderedMapLogging StdUnorderedMapLoggingTest.cpp)
|
||||
quill_add_test(TEST_StdUnorderedMultiMapLogging StdUnorderedMultiMapLoggingTest.cpp)
|
||||
quill_add_test(TEST_StdUnorderedMultiSetLogging StdUnorderedMultiSetLoggingTest.cpp)
|
||||
quill_add_test(TEST_StdUnorderedSetLogging StdUnorderedSetLoggingTest.cpp)
|
||||
quill_add_test(TEST_StdVectorLogging StdVectorLoggingTest.cpp)
|
||||
quill_add_test(TEST_SinkLogLevelFilter SinkLogLevelFilterTest.cpp)
|
||||
quill_add_test(TEST_StringLargeLogging StringLargeLoggingTest.cpp)
|
||||
quill_add_test(TEST_StringLoggingDynamicLogLevel StringLoggingDynamicLogLevelTest.cpp)
|
||||
quill_add_test(TEST_StringLogging StringLoggingTest.cpp)
|
||||
quill_add_test(TEST_StringRandomLargeLogging StringRandomLargeLoggingTest.cpp)
|
||||
quill_add_test(TEST_StringRandomLogging StringRandomLoggingTest.cpp)
|
||||
quill_add_test(TEST_StringRandomSmallLogging StringRandomSmallLoggingTest.cpp)
|
||||
quill_add_test(TEST_TagsLogging TagsLoggingTest.cpp)
|
||||
quill_add_test(TEST_UserClockSource UserClockSourceTest.cpp)
|
||||
quill_add_test(TEST_UserDefinedTypeLogging UserDefinedTypeLoggingTest.cpp)
|
||||
|
||||
quill_add_test(TEST_CompileActiveLogLevel CompileActiveLogLevelTest.cpp)
|
||||
target_compile_definitions(TEST_CompileActiveLogLevel PRIVATE -DQUILL_COMPILE_ACTIVE_LOG_LEVEL=QUILL_COMPILE_ACTIVE_LOG_LEVEL_WARNING)
|
||||
|
||||
if (WIN32)
|
||||
quill_add_test(TEST_WideStdTypesLogging WideStdTypesLoggingTest.cpp)
|
||||
quill_add_test(TEST_WideStringLogging WideStringLoggingTest.cpp)
|
||||
endif ()
|
|
@ -0,0 +1,67 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("compile_active_log_level")
|
||||
{
|
||||
// we build this target with
|
||||
// add_compile_definitions(-DQUILL_COMPILE_ACTIVE_LOG_LEVEL=QUILL_COMPILE_ACTIVE_LOG_LEVEL_WARNING)
|
||||
static constexpr char const* filename = "compile_active_log_level.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
logger->set_log_level(quill::LogLevel::TraceL3);
|
||||
REQUIRE_EQ(logger->get_log_level(), quill::LogLevel::TraceL3);
|
||||
|
||||
LOG_TRACE_L3(logger, "This is a log trace l3 example {}", 1);
|
||||
LOG_TRACE_L2(logger, "This is a log trace l2 example {} {}", 2, 2.3);
|
||||
LOG_TRACE_L1(logger, "This is a log trace l1 {} example", "string");
|
||||
LOG_DEBUG(logger, "This is a log debug example {}", 4);
|
||||
LOG_INFO(logger, "This is a log info example {}", 21);
|
||||
LOG_WARNING(logger, "This is a log warning example {}", 11);
|
||||
LOG_ERROR(logger, "This is a log error example {}", 3212);
|
||||
LOG_CRITICAL(logger, "This is a log critical example {}", 321);
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check, we only except statements above warning
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
REQUIRE_EQ(file_contents.size(), 3);
|
||||
|
||||
REQUIRE(quill::testing::file_contains(file_contents, std::string{"This is a log warning example 11"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(file_contents, std::string{"This is a log error example 3212"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(file_contents, std::string{"This is a log critical example 321"}));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/bundled/fmt/format.h"
|
||||
#include "quill/bundled/fmt/ranges.h"
|
||||
#include "quill/sinks/ConsoleSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("console_sink_stderr_multiple_formats")
|
||||
{
|
||||
static std::string const logger_name_a = "logger_a";
|
||||
static std::string const logger_name_b = "logger_b";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
quill::testing::CaptureStderr();
|
||||
|
||||
// Set writing logging to a file
|
||||
bool const using_colours = false;
|
||||
std::string const stream = "stderr";
|
||||
auto console_sink = Frontend::create_or_get_sink<ConsoleSink>("console_sink", using_colours, stream);
|
||||
|
||||
Logger* logger_a = Frontend::create_or_get_logger(logger_name_a, console_sink);
|
||||
Logger* logger_b = Frontend::create_or_get_logger(logger_name_b, console_sink,
|
||||
"%(logger) - %(message) (%(caller_function))");
|
||||
|
||||
console_sink.reset();
|
||||
|
||||
// log a few messages so we rotate files
|
||||
for (size_t i = 0; i < 20; ++i)
|
||||
{
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
LOG_INFO(logger_a, "Hello log num {}", i);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_INFO(logger_b, "Hello log num {}", i);
|
||||
}
|
||||
}
|
||||
|
||||
// flush all log and remove all loggers
|
||||
for (Logger* logger : Frontend::get_all_loggers())
|
||||
{
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
}
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// convert result to vector
|
||||
std::string results = quill::testing::GetCapturedStderr();
|
||||
std::stringstream data(results);
|
||||
|
||||
std::string line;
|
||||
std::vector<std::string> result_arr;
|
||||
while (std::getline(data, line, '\n'))
|
||||
{
|
||||
result_arr.push_back(line);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < 20; ++i)
|
||||
{
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
std::string expected_string =
|
||||
"LOG_INFO " + logger_name_a + " Hello log num " + std::to_string(i);
|
||||
|
||||
if (!quill::testing::file_contains(result_arr, expected_string))
|
||||
{
|
||||
FAIL(fmtquill::format("expected [{}] is not in results [{}]", expected_string, result_arr).data());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string expected_string =
|
||||
logger_name_b + " - Hello log num " + std::to_string(i) + " (DOCTEST_ANON_FUNC_2)";
|
||||
|
||||
if (!quill::testing::file_contains(result_arr, expected_string))
|
||||
{
|
||||
FAIL(fmtquill::format("expected [{}] is not in results [{}]", expected_string, result_arr).data());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/bundled/fmt/format.h"
|
||||
#include "quill/bundled/fmt/ranges.h"
|
||||
#include "quill/sinks/ConsoleSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("console_sink_stdout_multiple_formats")
|
||||
{
|
||||
static std::string const logger_name_a = "logger_a";
|
||||
static std::string const logger_name_b = "logger_b";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
quill::testing::CaptureStdout();
|
||||
|
||||
// Set writing logging to a file
|
||||
bool const using_colours = false;
|
||||
std::string const stream = "stdout";
|
||||
auto console_sink = Frontend::create_or_get_sink<ConsoleSink>("console_sink", using_colours, stream);
|
||||
|
||||
Logger* logger_a = Frontend::create_or_get_logger(logger_name_a, console_sink);
|
||||
Logger* logger_b = Frontend::create_or_get_logger(logger_name_b, console_sink,
|
||||
"%(logger) - %(message) (%(caller_function))");
|
||||
|
||||
console_sink.reset();
|
||||
|
||||
// log a few messages so we rotate files
|
||||
for (size_t i = 0; i < 20; ++i)
|
||||
{
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
LOG_INFO(logger_a, "Hello log num {}", i);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_INFO(logger_b, "Hello log num {}", i);
|
||||
}
|
||||
}
|
||||
|
||||
// flush all log and remove all loggers
|
||||
for (Logger* logger : Frontend::get_all_loggers())
|
||||
{
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
}
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// convert result to vector
|
||||
std::string results = quill::testing::GetCapturedStdout();
|
||||
std::stringstream data(results);
|
||||
|
||||
std::string line;
|
||||
std::vector<std::string> result_arr;
|
||||
while (std::getline(data, line, '\n'))
|
||||
{
|
||||
result_arr.push_back(line);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < 20; ++i)
|
||||
{
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
std::string expected_string =
|
||||
"LOG_INFO " + logger_name_a + " Hello log num " + std::to_string(i);
|
||||
|
||||
if (!quill::testing::file_contains(result_arr, expected_string))
|
||||
{
|
||||
FAIL(fmtquill::format("expected [{}] is not in results [{}]", expected_string, result_arr).data());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string expected_string =
|
||||
logger_name_b + " - Hello log num " + std::to_string(i) + " (DOCTEST_ANON_FUNC_2)";
|
||||
|
||||
if (!quill::testing::file_contains(result_arr, expected_string))
|
||||
{
|
||||
FAIL(fmtquill::format("expected [{}] is not in results [{}]", expected_string, result_arr).data());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/bundled/fmt/format.h"
|
||||
#include "quill/bundled/fmt/ostream.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
enum TestEnum : int
|
||||
{
|
||||
Test1 = 1,
|
||||
Test2 = 2,
|
||||
Test3 = 3
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, TestEnum const& test_enum)
|
||||
{
|
||||
switch (test_enum)
|
||||
{
|
||||
case TestEnum::Test1:
|
||||
os << "Test1";
|
||||
break;
|
||||
case TestEnum::Test2:
|
||||
os << "Test2";
|
||||
break;
|
||||
case TestEnum::Test3:
|
||||
os << "Test3";
|
||||
break;
|
||||
default:
|
||||
os << "Unknown";
|
||||
break;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
template <>
|
||||
struct fmtquill::formatter<TestEnum> : fmtquill::ostream_formatter
|
||||
{
|
||||
};
|
||||
|
||||
enum class TestEnumClass : uint64_t
|
||||
{
|
||||
Test4 = 4,
|
||||
Test5 = 5,
|
||||
Test6 = 6
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const TestEnumClass& test_enum_class)
|
||||
{
|
||||
switch (test_enum_class)
|
||||
{
|
||||
case TestEnumClass::Test4:
|
||||
os << "Test4";
|
||||
break;
|
||||
case TestEnumClass::Test5:
|
||||
os << "Test5";
|
||||
break;
|
||||
case TestEnumClass::Test6:
|
||||
os << "Test6";
|
||||
break;
|
||||
default:
|
||||
os << "Unknown";
|
||||
break;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
template <>
|
||||
struct fmtquill::formatter<TestEnumClass> : fmtquill::ostream_formatter
|
||||
{
|
||||
};
|
||||
|
||||
/***/
|
||||
TEST_CASE("enum_logging")
|
||||
{
|
||||
static constexpr char const* filename = "enum_logging.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
LOG_INFO(logger, "{} -> {}, {} -> {}", TestEnum::Test1, static_cast<int>(TestEnum::Test1),
|
||||
TestEnumClass::Test4, static_cast<uint64_t>(TestEnumClass::Test4));
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
|
||||
std::string expected_string = "LOG_INFO " + logger_name + " Test1 -> 1, Test4 -> 4";
|
||||
REQUIRE(quill::testing::file_contains(file_contents, expected_string));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("flush_without_any_log")
|
||||
{
|
||||
static constexpr char const* filename = "flush_without_any_log.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
std::atomic<bool> is_flush_done = false;
|
||||
|
||||
std::thread watcher(
|
||||
[&is_flush_done]()
|
||||
{
|
||||
uint32_t try_count = 2000;
|
||||
while (!is_flush_done.load() && try_count--)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
REQUIRE_EQ(is_flush_done.load(), true);
|
||||
});
|
||||
|
||||
logger->flush_log();
|
||||
is_flush_done = true;
|
||||
|
||||
watcher.join();
|
||||
Backend::stop();
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/JsonConsoleSink.h"
|
||||
|
||||
#include "quill/bundled/fmt/format.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("json_console_logging")
|
||||
{
|
||||
static constexpr size_t number_of_messages = 50;
|
||||
static std::string const logger_name_a = "logger_a";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
quill::testing::CaptureStdout();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto console_sink = Frontend::create_or_get_sink<JsonConsoleSink>("json_console");
|
||||
Logger* logger_a = Frontend::create_or_get_logger(logger_name_a, console_sink);
|
||||
|
||||
// log a few messages
|
||||
for (size_t i = 0; i < number_of_messages; ++i)
|
||||
{
|
||||
LOG_INFO(logger_a, "Hello log num [{num}, {multiply}, {add}]", i, i * i, i + i);
|
||||
}
|
||||
|
||||
// flush all log and remove all loggers
|
||||
for (Logger* logger : Frontend::get_all_loggers())
|
||||
{
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
}
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// convert result to vector
|
||||
std::string results = quill::testing::GetCapturedStdout();
|
||||
std::stringstream data(results);
|
||||
|
||||
std::string line;
|
||||
std::vector<std::string> file_contents;
|
||||
while (std::getline(data, line, '\n'))
|
||||
{
|
||||
file_contents.push_back(line);
|
||||
}
|
||||
|
||||
REQUIRE_EQ(file_contents.size(), number_of_messages);
|
||||
|
||||
for (size_t i = 0; i < number_of_messages; ++i)
|
||||
{
|
||||
std::string const expected_format =
|
||||
R"("logger_a","log_level":"INFO","message":"Hello log num [{{num}}, {{multiply}}, {{add}}]","num":"{}","multiply":"{}","add":"{}")";
|
||||
std::string const expected_string =
|
||||
fmtquill::format(fmtquill::runtime(expected_format), i, i * i, i + i);
|
||||
|
||||
REQUIRE(testing::file_contains(file_contents, expected_string));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,180 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/bundled/fmt/format.h"
|
||||
#include "quill/bundled/fmt/ostream.h"
|
||||
#include "quill/sinks/JsonFileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
class UserDefinedType
|
||||
{
|
||||
public:
|
||||
UserDefinedType() = default;
|
||||
UserDefinedType(size_t i, std::string const& s) : _i(i), _s(s) {}
|
||||
|
||||
virtual ~UserDefinedType() = default;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, UserDefinedType const& obj)
|
||||
{
|
||||
if (obj._i && obj._s)
|
||||
{
|
||||
os << "i: " << *obj._i << ", s: " << *obj._s;
|
||||
}
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
private:
|
||||
std::optional<size_t> _i;
|
||||
std::optional<std::string> _s;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct fmtquill::formatter<UserDefinedType> : fmtquill::ostream_formatter
|
||||
{
|
||||
};
|
||||
|
||||
/***/
|
||||
TEST_CASE("json_file_logging")
|
||||
{
|
||||
static constexpr size_t number_of_messages = 500u;
|
||||
static constexpr size_t number_of_threads = 6;
|
||||
static constexpr char const* json_filename = "json_file_logging.json";
|
||||
static constexpr char const* filename = "json_file_logging_file.log";
|
||||
static std::string const logger_name_prefix = "logger_";
|
||||
|
||||
// Start the logging backend thread
|
||||
BackendOptions bo;
|
||||
bo.error_notifier = [](std::string const&) {};
|
||||
Backend::start(bo);
|
||||
|
||||
std::vector<std::thread> threads;
|
||||
|
||||
for (size_t i = 0; i < number_of_threads; ++i)
|
||||
{
|
||||
threads.emplace_back(
|
||||
[i]() mutable
|
||||
{
|
||||
// log to json
|
||||
auto json_file_sink = Frontend::create_or_get_sink<JsonFileSink>(
|
||||
json_filename,
|
||||
[]()
|
||||
{
|
||||
JsonFileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(
|
||||
logger_name_prefix + std::to_string(i),
|
||||
std::initializer_list<std::shared_ptr<Sink>>{std::move(json_file_sink), std::move(file_sink)},
|
||||
"%(time) [%(thread_id)] %(short_source_location:<28) LOG_%(log_level:<9) %(logger:<12) "
|
||||
"%(message) [%(named_args)]");
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
// log a message without any args, only from the first thread
|
||||
LOG_INFO(logger, "Hello from thread");
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < number_of_messages; ++j)
|
||||
{
|
||||
LOG_INFO(logger,
|
||||
"Hello from thread {thread_index} this is message {message_num} [{custom}]", i,
|
||||
j, fmtquill::format("{}", UserDefinedType{j, std::to_string(j)}));
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
// log an invalid format for testing, only from the first thread
|
||||
LOG_INFO(logger, "invalid format [{%f}]", 321.1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (auto& elem : threads)
|
||||
{
|
||||
elem.join();
|
||||
}
|
||||
|
||||
// flush all log and remove all loggers
|
||||
for (Logger* logger : Frontend::get_all_loggers())
|
||||
{
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
}
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(json_filename);
|
||||
std::vector<std::string> const file_contents_s = quill::testing::file_contents(filename);
|
||||
|
||||
REQUIRE_EQ(file_contents.size(), number_of_messages * number_of_threads + 2);
|
||||
REQUIRE_EQ(file_contents_s.size(), number_of_messages * number_of_threads + 2);
|
||||
|
||||
for (size_t i = 0; i < number_of_threads; ++i)
|
||||
{
|
||||
// for each thread
|
||||
for (size_t j = 0; j < number_of_messages; ++j)
|
||||
{
|
||||
// check json log
|
||||
std::string expected_json_string = std::string{"\"logger\":\""} + logger_name_prefix +
|
||||
std::to_string(i) +
|
||||
std::string{
|
||||
"\",\"log_level\":\"INFO\",\"message\":\"Hello from thread {thread_index} this is "
|
||||
"message {message_num} [{custom}]\","} +
|
||||
std::string{"\"thread_index\":\""} + std::to_string(i) +
|
||||
std::string{"\",\"message_num\":\""} + std::to_string(j) +
|
||||
std::string{"\",\"custom\":\"i: "} + std::to_string(j) + ", s: " + std::to_string(j) +
|
||||
std::string{"\""};
|
||||
|
||||
REQUIRE(quill::testing::file_contains(file_contents, expected_json_string));
|
||||
|
||||
// check standard log
|
||||
// for each thread [i: 0, s: 0]
|
||||
std::string expected_string = logger_name_prefix + std::to_string(i) +
|
||||
" Hello from thread " + std::to_string(i) + " this is message " + std::to_string(j) +
|
||||
+" [i: " + std::to_string(j) + ", s: " + std::to_string(j) +
|
||||
"] [thread_index: " + std::to_string(i) + ", message_num: " + std::to_string(j) + ", ";
|
||||
|
||||
REQUIRE(quill::testing::file_contains(file_contents_s, expected_string));
|
||||
}
|
||||
|
||||
std::string expected_no_args_json = "\"log_level\":\"INFO\",\"message\":\"Hello from thread\"";
|
||||
std::string expected_no_args_fmt = "Hello from thread";
|
||||
REQUIRE(quill::testing::file_contains(file_contents, expected_no_args_json));
|
||||
REQUIRE(quill::testing::file_contains(file_contents_s, expected_no_args_fmt));
|
||||
|
||||
std::string expected_invalid_fmt_json =
|
||||
"\"log_level\":\"INFO\",\"message\":\"invalid format [{%f}]\"";
|
||||
std::string expected_invalid_fmt = "invalid format [{%f}]\", location: \"";
|
||||
REQUIRE(quill::testing::file_contains(file_contents, expected_invalid_fmt_json));
|
||||
REQUIRE(quill::testing::file_contains(file_contents_s, expected_invalid_fmt));
|
||||
}
|
||||
|
||||
testing::remove_file(json_filename);
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("log_arguments_evaluation")
|
||||
{
|
||||
static constexpr char const* filename = "log_arguments_evaluation.log";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
std::string const logger_name = "logger";
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
size_t cnt{0};
|
||||
auto arg_str = [&cnt]()
|
||||
{
|
||||
++cnt;
|
||||
return "expensive_calculation";
|
||||
};
|
||||
|
||||
// 1. checks that log arguments are not evaluated when we don't log
|
||||
logger->set_log_level(quill::LogLevel::Info);
|
||||
LOG_DEBUG(logger, "Test log arguments {}", arg_str());
|
||||
LOG_TRACE_L1(logger, "Test log arguments {}", arg_str());
|
||||
REQUIRE_EQ(cnt, 0);
|
||||
|
||||
// 2. checks that log arguments are evaluated only once per log statement
|
||||
LOG_INFO(logger, "Test log arguments {}", arg_str());
|
||||
REQUIRE_EQ(cnt, 1);
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
REQUIRE_EQ(file_contents.size(), 1);
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("log_flush_with_soft_limit_test")
|
||||
{
|
||||
static constexpr char const* filename = "log_flush_with_soft_limit_test.log";
|
||||
static std::string const logger_name = "logger";
|
||||
static size_t constexpr soft_limit = 100;
|
||||
|
||||
// make sure we at least x 100 the soft limit to make sure we are testing what we want
|
||||
// to not reduce this number. Increasing is fine
|
||||
static size_t constexpr number_of_messages = soft_limit * 100;
|
||||
static constexpr size_t number_of_threads = 4;
|
||||
|
||||
// When hitting the transit_events_soft_limit several events are processed in the backend at the
|
||||
// same time If all of them are processed there is a chance to miss messages that where in the
|
||||
// queues but never buffered result in example issuing the flush_log() earlier than it should
|
||||
|
||||
// Start the backend thread
|
||||
BackendOptions backend_options;
|
||||
backend_options.transit_events_soft_limit = soft_limit;
|
||||
Backend::start(backend_options);
|
||||
|
||||
std::vector<std::thread> threads;
|
||||
for (size_t i = 0; i < number_of_threads; ++i)
|
||||
{
|
||||
threads.emplace_back(
|
||||
[i]() mutable
|
||||
{
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
cfg.set_do_fsync(true);
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
for (size_t j = 0; j < number_of_messages; ++j)
|
||||
{
|
||||
LOG_INFO(logger, "Hello from thread {} this is message {}", i, j);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (auto& elem : threads)
|
||||
{
|
||||
elem.join();
|
||||
}
|
||||
|
||||
Frontend::get_valid_logger()->flush_log();
|
||||
|
||||
// Now check we have all messages in the file after the flush statement
|
||||
|
||||
size_t const total_messages = number_of_messages * number_of_threads;
|
||||
// Read file and check
|
||||
REQUIRE_EQ(testing::file_contents(filename).size(), total_messages);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check again, nothing else was logged
|
||||
REQUIRE_EQ(testing::file_contents(filename).size(), total_messages);
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/**
|
||||
* A test class example that is using the logger
|
||||
*/
|
||||
class LoggingTestClass
|
||||
{
|
||||
public:
|
||||
LoggingTestClass(std::string const& filename, std::string const& logger_name)
|
||||
{
|
||||
// create a new logger in the ctor
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
cfg.set_do_fsync(true);
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
quill::Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
~LoggingTestClass()
|
||||
{
|
||||
_logger->flush_log();
|
||||
Frontend::remove_logger(_logger);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use logger in const function
|
||||
*/
|
||||
void use_logger_const() const noexcept { LOG_INFO(_logger, "Test message for test class const"); }
|
||||
|
||||
/**
|
||||
* Use logger in normal function
|
||||
*/
|
||||
void use_logger() const { LOG_INFO(_logger, "Test message for test class non const"); }
|
||||
|
||||
private:
|
||||
quill::Logger* _logger{nullptr};
|
||||
};
|
||||
|
||||
/***/
|
||||
TEST_CASE("logger_add_remove_get")
|
||||
{
|
||||
// Verifies logging behavior adding, removing and getting loggers
|
||||
// and logging from const member functions while dynamically creating and
|
||||
// removing loggers and reusing the same file after removal.
|
||||
static constexpr size_t iterations = 100;
|
||||
static constexpr char const* filename = "logger_add_remove_get.log";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
for (size_t i = 0; i < iterations; ++i)
|
||||
{
|
||||
std::string const logger_a_name = "logger_a" + std::to_string(i);
|
||||
std::string const logger_b_name = "logger_b" + std::to_string(i);
|
||||
|
||||
{
|
||||
// log for class a
|
||||
LoggingTestClass logging_test_class_a{filename, logger_a_name};
|
||||
logging_test_class_a.use_logger_const();
|
||||
logging_test_class_a.use_logger();
|
||||
|
||||
// log again for class b
|
||||
LoggingTestClass const logging_test_class_b{filename, logger_b_name};
|
||||
logging_test_class_b.use_logger_const();
|
||||
}
|
||||
|
||||
// Test that get_all_loggers() works and also it should be empty after removing the loggers
|
||||
REQUIRE(Frontend::get_all_loggers().empty());
|
||||
REQUIRE(!Frontend::get_logger(logger_a_name));
|
||||
REQUIRE(!Frontend::get_logger(logger_b_name));
|
||||
|
||||
// The only safe way to know that the loggers are really removed is currently this
|
||||
while (Frontend::get_number_of_loggers())
|
||||
{
|
||||
// wait for all the to be removed first by the backend thread first then repeat the test
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds{1});
|
||||
}
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
REQUIRE_EQ(file_contents.size(), 3);
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
||||
|
||||
Backend::stop();
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("multi_frontend_threads")
|
||||
{
|
||||
static constexpr size_t number_of_messages = 1000;
|
||||
static constexpr size_t number_of_threads = 10;
|
||||
static constexpr char const* filename = "multi_frontend_threads.log";
|
||||
static std::string const logger_name_prefix = "logger_";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
std::vector<std::thread> threads;
|
||||
|
||||
for (size_t i = 0; i < number_of_threads; ++i)
|
||||
{
|
||||
threads.emplace_back(
|
||||
[i]() mutable
|
||||
{
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(
|
||||
logger_name_prefix + std::to_string(i), std::move(file_sink),
|
||||
"%(time) [%(thread_id)] %(short_source_location:<28) LOG_%(log_level:<9) %(logger:<12) "
|
||||
"%(message)",
|
||||
"%Y-%m-%d %H:%M:%S.%Qns", Timezone::GmtTime, ClockSourceType::System);
|
||||
|
||||
for (size_t j = 0; j < number_of_messages; ++j)
|
||||
{
|
||||
LOG_INFO(logger, "Hello from thread {} this is message {}", i, j);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (auto& elem : threads)
|
||||
{
|
||||
elem.join();
|
||||
}
|
||||
|
||||
// flush all log and remove all loggers
|
||||
for (Logger* logger : Frontend::get_all_loggers())
|
||||
{
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
}
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
REQUIRE_EQ(file_contents.size(), number_of_messages * number_of_threads);
|
||||
|
||||
for (size_t i = 0; i < number_of_threads; ++i)
|
||||
{
|
||||
// for each thread
|
||||
for (size_t j = 0; j < number_of_messages; ++j)
|
||||
{
|
||||
std::string expected_string = logger_name_prefix + std::to_string(i) +
|
||||
" Hello from thread " + std::to_string(i) + " this is message " + std::to_string(j);
|
||||
|
||||
REQUIRE(testing::file_contains(file_contents, expected_string));
|
||||
}
|
||||
}
|
||||
|
||||
// Check log file is timestamp ordered
|
||||
REQUIRE(quill::testing::is_timestamp_ordered(file_contents));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/ConsoleSink.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("multiple_sinks_same_logger")
|
||||
{
|
||||
static constexpr size_t number_of_messages = 10000;
|
||||
static constexpr char const* filename = "multiple_sinks_same_logger.log";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
quill::testing::CaptureStdout();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
bool const using_colours = false;
|
||||
std::string const stream = "stdout";
|
||||
auto console_sink = Frontend::create_or_get_sink<ConsoleSink>("console_sink", using_colours, stream);
|
||||
|
||||
std::string const logger_name = "logger";
|
||||
Logger* logger =
|
||||
Frontend::create_or_get_logger(logger_name, {std::move(file_sink), std::move(console_sink)});
|
||||
|
||||
for (size_t i = 0; i < number_of_messages; ++i)
|
||||
{
|
||||
LOG_INFO(logger, "This is message {}", i);
|
||||
}
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
{
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
|
||||
REQUIRE_EQ(file_contents.size(), number_of_messages);
|
||||
|
||||
for (size_t i = 0; i < number_of_messages; ++i)
|
||||
{
|
||||
std::string expected_string = logger_name + " This is message " + std::to_string(i);
|
||||
REQUIRE(quill::testing::file_contains(file_contents, expected_string));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// convert stdout result to vector
|
||||
std::string results = quill::testing::GetCapturedStdout();
|
||||
std::stringstream data(results);
|
||||
|
||||
std::string line;
|
||||
std::vector<std::string> file_contents;
|
||||
while (std::getline(data, line, '\n'))
|
||||
{
|
||||
file_contents.push_back(line);
|
||||
}
|
||||
|
||||
REQUIRE_EQ(file_contents.size(), number_of_messages);
|
||||
|
||||
for (size_t i = 0; i < number_of_messages; ++i)
|
||||
{
|
||||
std::string expected_string = "logger This is message " + std::to_string(i);
|
||||
REQUIRE(quill::testing::file_contains(file_contents, expected_string));
|
||||
}
|
||||
}
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/RotatingFileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("rotating_sink_daily_rotation")
|
||||
{
|
||||
// This test has 2 loggers that they logged to different rotating file handlers
|
||||
static char const* base_filename = "rotating_sink_daily_rotation.log";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
// Create a rotating file handler
|
||||
std::shared_ptr<quill::Sink> rotating_file_sink_a =
|
||||
Frontend::create_or_get_sink<RotatingFileSink>(base_filename,
|
||||
[]()
|
||||
{
|
||||
RotatingFileSinkConfig rfh_cfg;
|
||||
rfh_cfg.set_rotation_time_daily("00:00");
|
||||
rfh_cfg.set_open_mode('w');
|
||||
return rfh_cfg;
|
||||
}());
|
||||
|
||||
// Get the same instance back - we search it again (for testing only)
|
||||
quill::Logger* logger = Frontend::create_or_get_logger("logger", std::move(rotating_file_sink_a));
|
||||
|
||||
// log a few messages so we rotate files
|
||||
for (uint32_t i = 0; i < 20; ++i)
|
||||
{
|
||||
LOG_INFO(logger, "Hello daily file log num {}", i);
|
||||
}
|
||||
|
||||
// flush all log and remove all loggers
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(base_filename);
|
||||
REQUIRE_EQ(file_contents.size(), 20);
|
||||
|
||||
testing::remove_file(base_filename);
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/RotatingFileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("rotating_sink_keep_oldest")
|
||||
{
|
||||
// This test has 2 loggers that they logged to different rotating file handlers
|
||||
static char const* base_filename_a = "rotating_sink_keep_oldest_a.log";
|
||||
static constexpr char const* base_filename_a_1 = "rotating_sink_keep_oldest_a.1.log";
|
||||
static constexpr char const* base_filename_a_2 = "rotating_sink_keep_oldest_a.2.log";
|
||||
|
||||
static char const* base_filename_b = "rotating_sink_keep_oldest_b.log";
|
||||
static constexpr char const* base_filename_b_1 = "rotating_sink_keep_oldest_b.1.log";
|
||||
|
||||
static constexpr size_t max_file_size = 900;
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
// Create a rotating file handler
|
||||
std::shared_ptr<quill::Sink> rotating_file_sink_a =
|
||||
Frontend::create_or_get_sink<RotatingFileSink>(base_filename_a,
|
||||
[]()
|
||||
{
|
||||
RotatingFileSinkConfig rfh_cfg;
|
||||
rfh_cfg.set_rotation_max_file_size(max_file_size);
|
||||
rfh_cfg.set_max_backup_files(2);
|
||||
rfh_cfg.set_overwrite_rolled_files(false);
|
||||
rfh_cfg.set_open_mode('w');
|
||||
return rfh_cfg;
|
||||
}());
|
||||
|
||||
// Get the same instance back - we search it again (for testing only)
|
||||
quill::Logger* logger_a = Frontend::create_or_get_logger("logger_a", std::move(rotating_file_sink_a));
|
||||
|
||||
// Another rotating logger to another file with max backup count 1 this time. Here we rotate only once
|
||||
std::shared_ptr<quill::Sink> rotating_file_sink_b =
|
||||
Frontend::create_or_get_sink<RotatingFileSink>(base_filename_b,
|
||||
[]()
|
||||
{
|
||||
RotatingFileSinkConfig rfh_cfg;
|
||||
rfh_cfg.set_rotation_max_file_size(max_file_size);
|
||||
rfh_cfg.set_max_backup_files(1);
|
||||
rfh_cfg.set_overwrite_rolled_files(false);
|
||||
rfh_cfg.set_open_mode('w');
|
||||
return rfh_cfg;
|
||||
}());
|
||||
|
||||
quill::Logger* logger_b = Frontend::create_or_get_logger("logger_b", std::move(rotating_file_sink_b));
|
||||
|
||||
// log a few messages so we rotate files
|
||||
for (uint32_t i = 0; i < 20; ++i)
|
||||
{
|
||||
LOG_INFO(logger_a, "Hello rotating file log num {}", i);
|
||||
LOG_INFO(logger_b, "Hello rotating file log num {}", i);
|
||||
}
|
||||
|
||||
// flush all log and remove all loggers
|
||||
for (Logger* logger : Frontend::get_all_loggers())
|
||||
{
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
}
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(base_filename_a);
|
||||
REQUIRE_GE(file_contents.size(), 3);
|
||||
|
||||
std::vector<std::string> const file_contents_1 = quill::testing::file_contents(base_filename_a_1);
|
||||
REQUIRE_GE(file_contents_1.size(), 7);
|
||||
|
||||
std::vector<std::string> const file_contents_2 = quill::testing::file_contents(base_filename_a_2);
|
||||
REQUIRE_GE(file_contents_2.size(), 7);
|
||||
|
||||
// File from 2nd logger
|
||||
std::vector<std::string> const file_contents_3 = quill::testing::file_contents(base_filename_b);
|
||||
REQUIRE_GE(file_contents_3.size(), 11);
|
||||
|
||||
std::vector<std::string> const file_contents_4 = quill::testing::file_contents(base_filename_b_1);
|
||||
REQUIRE_GE(file_contents_4.size(), 7);
|
||||
|
||||
// Remove filenames
|
||||
testing::remove_file(base_filename_a);
|
||||
testing::remove_file(base_filename_a_1);
|
||||
testing::remove_file(base_filename_a_2);
|
||||
testing::remove_file(base_filename_b);
|
||||
testing::remove_file(base_filename_b_1);
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/RotatingFileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("rotating_sink_overwrite_oldest")
|
||||
{
|
||||
// This test has 2 loggers that they logged to different rotating file handlers
|
||||
static char const* base_filename_a = "rotating_sink_overwrite_oldest_a.log";
|
||||
static constexpr char const* base_filename_a_1 = "rotating_sink_overwrite_oldest_a.1.log";
|
||||
static constexpr char const* base_filename_a_2 = "rotating_sink_overwrite_oldest_a.2.log";
|
||||
|
||||
static char const* base_filename_b = "rotating_sink_overwrite_oldest_b.log";
|
||||
static constexpr char const* base_filename_b_1 = "rotating_sink_overwrite_oldest_b.1.log";
|
||||
|
||||
static constexpr size_t max_file_size = 900;
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
// Create a rotating file handler
|
||||
std::shared_ptr<quill::Sink> rotating_file_sink_a =
|
||||
Frontend::create_or_get_sink<RotatingFileSink>(base_filename_a,
|
||||
[]()
|
||||
{
|
||||
RotatingFileSinkConfig rfh_cfg;
|
||||
rfh_cfg.set_rotation_max_file_size(max_file_size);
|
||||
rfh_cfg.set_max_backup_files(2);
|
||||
rfh_cfg.set_overwrite_rolled_files(true);
|
||||
rfh_cfg.set_open_mode('w');
|
||||
return rfh_cfg;
|
||||
}());
|
||||
|
||||
// Get the same instance back - we search it again (for testing only)
|
||||
quill::Logger* logger_a = Frontend::create_or_get_logger("logger_a", std::move(rotating_file_sink_a));
|
||||
|
||||
// Another rotating logger to another file with max backup count 1 this time. Here we rotate only once
|
||||
std::shared_ptr<quill::Sink> rotating_file_sink_b =
|
||||
Frontend::create_or_get_sink<RotatingFileSink>(base_filename_b,
|
||||
[]()
|
||||
{
|
||||
RotatingFileSinkConfig rfh_cfg;
|
||||
rfh_cfg.set_rotation_max_file_size(max_file_size);
|
||||
rfh_cfg.set_max_backup_files(1);
|
||||
rfh_cfg.set_overwrite_rolled_files(true);
|
||||
rfh_cfg.set_open_mode('w');
|
||||
return rfh_cfg;
|
||||
}());
|
||||
|
||||
quill::Logger* logger_b = Frontend::create_or_get_logger("logger_b", std::move(rotating_file_sink_b));
|
||||
|
||||
// log a few messages so we rotate files
|
||||
for (uint32_t i = 0; i < 20; ++i)
|
||||
{
|
||||
LOG_INFO(logger_a, "Hello rotating file log num {}", i);
|
||||
LOG_INFO(logger_b, "Hello rotating file log num {}", i);
|
||||
}
|
||||
|
||||
// flush all log and remove all loggers
|
||||
for (Logger* logger : Frontend::get_all_loggers())
|
||||
{
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
}
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(base_filename_a);
|
||||
REQUIRE_GE(file_contents.size(), 3);
|
||||
|
||||
std::vector<std::string> const file_contents_1 = quill::testing::file_contents(base_filename_a_1);
|
||||
REQUIRE_GE(file_contents_1.size(), 7);
|
||||
|
||||
std::vector<std::string> const file_contents_2 = quill::testing::file_contents(base_filename_a_2);
|
||||
REQUIRE_GE(file_contents_2.size(), 7);
|
||||
|
||||
// File from 2nd logger
|
||||
std::vector<std::string> const file_contents_3 = quill::testing::file_contents(base_filename_b);
|
||||
REQUIRE_GE(file_contents_3.size(), 4);
|
||||
|
||||
std::vector<std::string> const file_contents_4 = quill::testing::file_contents(base_filename_b_1);
|
||||
REQUIRE_GE(file_contents_4.size(), 7);
|
||||
|
||||
// Remove filenames
|
||||
testing::remove_file(base_filename_a);
|
||||
testing::remove_file(base_filename_a_1);
|
||||
testing::remove_file(base_filename_a_2);
|
||||
testing::remove_file(base_filename_b);
|
||||
testing::remove_file(base_filename_b_1);
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("signal_handler")
|
||||
{
|
||||
static constexpr char const* filename = "signal_handler.log";
|
||||
static std::string const logger_name = "logger";
|
||||
static constexpr size_t number_of_messages = 10;
|
||||
static constexpr size_t number_of_threads = 10;
|
||||
static std::string const logger_name_prefix = "logger_";
|
||||
|
||||
// Start the logging backend thread, we expect the signal handler to catch the signal,
|
||||
// flush the log and raise the signal back
|
||||
Backend::start_with_signal_handler<FrontendOptions>(BackendOptions{},
|
||||
std::initializer_list<int>{SIGABRT}, 40);
|
||||
|
||||
// For testing purposes we want to keep the application running, we do not reraise the signal
|
||||
detail::SignalHandlerContext::instance().should_reraise_signal.store(false);
|
||||
|
||||
quill::Frontend::preallocate();
|
||||
|
||||
std::vector<std::thread> threads;
|
||||
|
||||
for (size_t i = 0; i < number_of_threads; ++i)
|
||||
{
|
||||
threads.emplace_back(
|
||||
[i]() mutable
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
// NOTE: On windows the signal handler must be installed on each new thread
|
||||
quill::init_signal_handler<quill::FrontendOptions>();
|
||||
#endif
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
cfg.set_do_fsync(true);
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger =
|
||||
Frontend::create_or_get_logger(logger_name_prefix + std::to_string(i), std::move(file_sink));
|
||||
|
||||
for (size_t j = 0; j < number_of_messages; ++j)
|
||||
{
|
||||
LOG_INFO(logger, "{} {} {}", i, j,
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor "
|
||||
"incididunt ut labore et dolore magna aliqua.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (auto& elem : threads)
|
||||
{
|
||||
elem.join();
|
||||
}
|
||||
|
||||
// Now raise a signal
|
||||
std::raise(SIGABRT);
|
||||
|
||||
{
|
||||
// Except the log and the signal handler in the logs
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
|
||||
for (size_t i = 0; i < number_of_threads; ++i)
|
||||
{
|
||||
// for each thread
|
||||
for (size_t j = 0; j < number_of_messages; ++j)
|
||||
{
|
||||
std::string expected_string = logger_name_prefix + std::to_string(i) + " " +
|
||||
std::to_string(i) + " " + std::to_string(j) +
|
||||
" Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor "
|
||||
"incididunt ut labore et dolore magna aliqua.";
|
||||
|
||||
REQUIRE(testing::file_contains(file_contents, expected_string));
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
REQUIRE(quill::testing::file_contains(file_contents, std::string{"Received signal: 22 (signum: 22)"}));
|
||||
#elif defined(__apple_build_version__)
|
||||
REQUIRE(quill::testing::file_contains(file_contents, std::string{"Received signal: Abort trap: 6 (signum: 6)"}));
|
||||
#else
|
||||
REQUIRE(quill::testing::file_contains(file_contents, std::string{"Received signal: Aborted (signum: 6)"}));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
for (Logger* logger : Frontend::get_all_loggers())
|
||||
{
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
}
|
||||
|
||||
Backend::stop();
|
||||
REQUIRE_FALSE(Backend::is_running());
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("single_frontend_thread")
|
||||
{
|
||||
static constexpr size_t number_of_messages = 10000;
|
||||
static constexpr char const* filename = "single_frontend_thread.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
for (size_t i = 0; i < number_of_messages; ++i)
|
||||
{
|
||||
LOG_INFO(logger, "This is message {}", i);
|
||||
}
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
REQUIRE_EQ(file_contents.size(), number_of_messages);
|
||||
|
||||
for (size_t i = 0; i < number_of_messages; ++i)
|
||||
{
|
||||
std::string expected_string = logger_name + " This is message " + std::to_string(i);
|
||||
REQUIRE(quill::testing::file_contains(file_contents, expected_string));
|
||||
}
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/**
|
||||
* Filter class for our file handler
|
||||
*/
|
||||
class FileFilterA : public Filter
|
||||
{
|
||||
public:
|
||||
FileFilterA() : Filter("FileFilterA") {}
|
||||
|
||||
QUILL_NODISCARD bool filter(MacroMetadata const* log_metadata, uint64_t log_timestamp, std::string_view thread_id,
|
||||
std::string_view thread_name, std::string_view logger_name,
|
||||
LogLevel log_level, std::string_view log_message) noexcept override
|
||||
{
|
||||
if (log_metadata->log_level() < LogLevel::Warning)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Filter for the stdout handler
|
||||
*/
|
||||
class FileFilterB : public Filter
|
||||
{
|
||||
public:
|
||||
FileFilterB() : Filter("FileFilterB") {}
|
||||
|
||||
QUILL_NODISCARD bool filter(MacroMetadata const* log_metadata, uint64_t log_timestamp, std::string_view thread_id,
|
||||
std::string_view thread_name, std::string_view logger_name,
|
||||
LogLevel log_level, std::string_view log_message) noexcept override
|
||||
{
|
||||
if (log_metadata->log_level() >= LogLevel::Warning)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/***/
|
||||
TEST_CASE("sink_filter")
|
||||
{
|
||||
static constexpr char const* filename_a = "sink_filter_a.log";
|
||||
static constexpr char const* filename_b = "sink_filter_b.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink_a = Frontend::create_or_get_sink<FileSink>(
|
||||
filename_a,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
// log to filename_a anything below warning
|
||||
std::unique_ptr<Filter> filter_a = std::make_unique<FileFilterA>();
|
||||
|
||||
// Also test get_filter_name()
|
||||
REQUIRE_EQ(filter_a->get_filter_name(), std::string_view{"FileFilterA"});
|
||||
|
||||
// Add the filter
|
||||
file_sink_a->add_filter(std::move(filter_a));
|
||||
|
||||
// Try to add the same again (same name)
|
||||
std::unique_ptr<Filter> filter_a_2 = std::make_unique<FileFilterA>();
|
||||
REQUIRE_EQ(filter_a_2->get_filter_name(), std::string_view{"FileFilterA"});
|
||||
REQUIRE_THROWS_AS(file_sink_a->add_filter(std::move(filter_a_2)), QuillError);
|
||||
|
||||
auto file_sink_b = Frontend::create_or_get_sink<FileSink>(
|
||||
filename_b,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
// log to filename_b warning, error, critical
|
||||
file_sink_b->add_filter(std::make_unique<FileFilterB>());
|
||||
|
||||
Logger* logger =
|
||||
Frontend::create_or_get_logger(logger_name, {std::move(file_sink_a), std::move(file_sink_b)});
|
||||
|
||||
LOG_INFO(logger, "Lorem ipsum dolor sit amet, consectetur adipiscing elit");
|
||||
LOG_ERROR(logger, "Nulla tempus, libero at dignissim viverra, lectus libero finibus ante");
|
||||
|
||||
// Let all log get flushed to the file
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents_a = quill::testing::file_contents(filename_a);
|
||||
REQUIRE_EQ(file_contents_a.size(), 1);
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents_a,
|
||||
std::string{"LOG_INFO " + logger_name + " Lorem ipsum dolor sit amet, consectetur adipiscing elit"}));
|
||||
|
||||
std::vector<std::string> const file_contents_b = quill::testing::file_contents(filename_b);
|
||||
REQUIRE_EQ(file_contents_b.size(), 1);
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents_b,
|
||||
std::string{"LOG_ERROR " + logger_name +
|
||||
" Nulla tempus, libero at dignissim viverra, lectus libero finibus ante"}));
|
||||
|
||||
testing::remove_file(filename_a);
|
||||
testing::remove_file(filename_b);
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("sink_log_level_filter")
|
||||
{
|
||||
static constexpr char const* filename_a = "sink_log_level_filter_a.log";
|
||||
static constexpr char const* filename_b = "sink_log_level_filter_b.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink_a = Frontend::create_or_get_sink<FileSink>(
|
||||
filename_a,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
// Set filters to our handlers
|
||||
REQUIRE_EQ(file_sink_a->get_log_level_filter(), LogLevel::TraceL3);
|
||||
file_sink_a->set_log_level_filter(LogLevel::Info);
|
||||
REQUIRE_EQ(file_sink_a->get_log_level_filter(), LogLevel::Info);
|
||||
|
||||
auto file_sink_b = Frontend::create_or_get_sink<FileSink>(
|
||||
filename_b,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
// log to filename_b warning, error, critical
|
||||
REQUIRE_EQ(file_sink_b->get_log_level_filter(), LogLevel::TraceL3);
|
||||
file_sink_b->set_log_level_filter(LogLevel::Error);
|
||||
REQUIRE_EQ(file_sink_b->get_log_level_filter(), LogLevel::Error);
|
||||
|
||||
Logger* logger =
|
||||
Frontend::create_or_get_logger(logger_name, {std::move(file_sink_a), std::move(file_sink_b)});
|
||||
|
||||
LOG_INFO(logger, "Lorem ipsum dolor sit amet, consectetur adipiscing elit");
|
||||
LOG_ERROR(logger, "Nulla tempus, libero at dignissim viverra, lectus libero finibus ante");
|
||||
|
||||
// Let all log get flushed to the file
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents_a = quill::testing::file_contents(filename_a);
|
||||
REQUIRE_EQ(file_contents_a.size(), 2);
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents_a,
|
||||
std::string{"LOG_INFO " + logger_name + " Lorem ipsum dolor sit amet, consectetur adipiscing elit"}));
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents_a,
|
||||
std::string{"LOG_ERROR " + logger_name +
|
||||
" Nulla tempus, libero at dignissim viverra, lectus libero finibus ante"}));
|
||||
|
||||
std::vector<std::string> const file_contents_b = quill::testing::file_contents(filename_b);
|
||||
REQUIRE_EQ(file_contents_b.size(), 1);
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents_b,
|
||||
std::string{"LOG_ERROR " + logger_name +
|
||||
" Nulla tempus, libero at dignissim viverra, lectus libero finibus ante"}));
|
||||
|
||||
testing::remove_file(filename_a);
|
||||
testing::remove_file(filename_b);
|
||||
}
|
|
@ -0,0 +1,209 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
#include "quill/std/Array.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("std_array_logging")
|
||||
{
|
||||
static constexpr char const* filename = "std_array_logging.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
{
|
||||
std::array<bool, 2> b = {true, false};
|
||||
LOG_INFO(logger, "v {}", b);
|
||||
|
||||
std::array<char, 2> c = {'a', 'c'};
|
||||
LOG_INFO(logger, "c {}", c);
|
||||
|
||||
std::array<short, 2> si = {-12, 10};
|
||||
LOG_INFO(logger, "si {}", si);
|
||||
|
||||
std::array<int, 2> i = {-123, 1};
|
||||
LOG_INFO(logger, "i {}", i);
|
||||
|
||||
std::array<long, 2> li = {9876, 1232};
|
||||
LOG_INFO(logger, "li {}", li);
|
||||
|
||||
std::array<long long, 2> lli = {321, 231};
|
||||
LOG_INFO(logger, "lli {}", lli);
|
||||
|
||||
std::array<unsigned short, 2> usi = {15, 2};
|
||||
LOG_INFO(logger, "usi {}", usi);
|
||||
|
||||
std::array<unsigned int, 2> ui = {123, 2};
|
||||
LOG_INFO(logger, "ui {}", ui);
|
||||
|
||||
std::array<unsigned long, 2> uli = {3213, 2876};
|
||||
LOG_INFO(logger, "uli {}", uli);
|
||||
|
||||
std::array<unsigned long long, 2> ulli = {321, 1321};
|
||||
LOG_INFO(logger, "ulli {}", ulli);
|
||||
|
||||
std::array<float, 2> f = {111.1f, 323.31f};
|
||||
LOG_INFO(logger, "f {}", f);
|
||||
|
||||
std::array<double, 2> d = {12.1, 3213213.123};
|
||||
LOG_INFO(logger, "d {}", d);
|
||||
|
||||
std::array<int, 2> const& cri = i;
|
||||
LOG_INFO(logger, "cri {}", cri);
|
||||
|
||||
std::array<int, 2>& ci = i;
|
||||
LOG_INFO(logger, "ci {}", ci);
|
||||
|
||||
std::array<std::string, 2> sa = {"test", "string"};
|
||||
LOG_INFO(logger, "sa {}", sa);
|
||||
|
||||
std::array<std::string_view, 2> sva = {"test", "string_view"};
|
||||
LOG_INFO(logger, "sva {}", sva);
|
||||
|
||||
std::array<char const*, 4> scva = {"c style", "string test", "test", "log"};
|
||||
LOG_INFO(logger, "scva {}", scva);
|
||||
|
||||
std::array<std::array<int, 2>, 3> aai = {{{321, 123}, {444, 333}, {111, 222}}};
|
||||
LOG_INFO(logger, "aai {}", aai);
|
||||
|
||||
std::array<std::array<char const*, 2>, 3> aacs = {
|
||||
{{"one", "two"}, {"three", "four"}, {"five", "six"}}};
|
||||
LOG_INFO(logger, "aacs {}", aacs);
|
||||
|
||||
std::array<std::array<std::array<char const*, 2>, 2>, 3> aaacs = {
|
||||
{{{{"one", "two"}, {"three", "four"}}},
|
||||
{{{"five", "six"}, {"seven", "eight"}}},
|
||||
{{{"nine", "ten"}, {"eleven", "twelve"}}}}};
|
||||
LOG_INFO(logger, "aaacs {}", aaacs);
|
||||
|
||||
std::array<std::array<std::array<std::string, 2>, 2>, 3> aaabcs = {
|
||||
{{{{"std_one", "two"}, {"three", "four"}}},
|
||||
{{{"five", "six"}, {"seven", "eight"}}},
|
||||
{{{"std_nine", "ten"}, {"eleven", "twelve"}}}}};
|
||||
LOG_INFO(logger, "aaabcs {}", aaabcs);
|
||||
|
||||
std::array<std::array<std::array<std::string_view, 2>, 2>, 3> aaaccs = {
|
||||
{{{{"std_one", "two"}, {"three_std", "four"}}},
|
||||
{{{"five", "six"}, {"seven_std", "eight"}}},
|
||||
{{{"std_nine", "ten"}, {"eleven", "twelve"}}}}};
|
||||
LOG_INFO(logger, "aaaccs {}", aaaccs);
|
||||
|
||||
LOG_INFO(logger, "scva {} sa {} ulli {} scva {} sa {} aaacs {} aai {}", scva, sa, ulli, scva, sa, aaacs, aai);
|
||||
|
||||
std::array<int, 4> empt{};
|
||||
LOG_INFO(logger, "empt {}", empt);
|
||||
}
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " v [true, false]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " c ['a', 'c']"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " si [-12, 10]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " i [-123, 1]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " li [9876, 1232]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " lli [321, 231]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " usi [15, 2]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ui [123, 2]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " uli [3213, 2876]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ulli [321, 1321]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " f [111.1, 323.31]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " d [12.1, 3213213.123]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " cri [-123, 1]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ci [-123, 1]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " sa [\"test\", \"string\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " sva [\"test\", \"string_view\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " scva [\"c style\", \"string test\", \"test\", \"log\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " aai [[321, 123], [444, 333], [111, 222]]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents,
|
||||
std::string{"LOG_INFO " + logger_name +
|
||||
" aacs [[\"one\", \"two\"], [\"three\", \"four\"], [\"five\", \"six\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " aaabcs [[[\"std_one\", \"two\"], [\"three\", \"four\"]], [[\"five\", \"six\"], [\"seven\", \"eight\"]], [[\"std_nine\", \"ten\"], [\"eleven\", \"twelve\"]]]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " aaaccs [[[\"std_one\", \"two\"], [\"three_std\", \"four\"]], [[\"five\", \"six\"], [\"seven_std\", \"eight\"]], [[\"std_nine\", \"ten\"], [\"eleven\", \"twelve\"]]]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " aaacs [[[\"one\", \"two\"], [\"three\", \"four\"]], [[\"five\", \"six\"], [\"seven\", \"eight\"]], [[\"nine\", \"ten\"], [\"eleven\", \"twelve\"]]]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " scva [\"c style\", \"string test\", \"test\", \"log\"] sa [\"test\", \"string\"] ulli [321, 1321] scva [\"c style\", \"string test\", \"test\", \"log\"] sa [\"test\", \"string\"] aaacs [[[\"one\", \"two\"], [\"three\", \"four\"]], [[\"five\", \"six\"], [\"seven\", \"eight\"]], [[\"nine\", \"ten\"], [\"eleven\", \"twelve\"]]] aai [[321, 123], [444, 333], [111, 222]]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " empt [0, 0, 0, 0]"}));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,250 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
#include "quill/std/Deque.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <deque>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("std_deque_logging")
|
||||
{
|
||||
static constexpr char const* filename = "std_deque_logging.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
{
|
||||
std::deque<char> c = {'a', 'c'};
|
||||
LOG_INFO(logger, "c {}", c);
|
||||
|
||||
std::deque<short> si = {-12, 10};
|
||||
LOG_INFO(logger, "si {}", si);
|
||||
|
||||
std::deque<int> i = {-123, 1};
|
||||
LOG_INFO(logger, "i {}", i);
|
||||
|
||||
std::deque<long> li = {9876, 1232};
|
||||
LOG_INFO(logger, "li {}", li);
|
||||
|
||||
std::deque<long long> lli = {321, 231};
|
||||
LOG_INFO(logger, "lli {}", lli);
|
||||
|
||||
std::deque<unsigned short> usi = {15, 2};
|
||||
LOG_INFO(logger, "usi {}", usi);
|
||||
|
||||
std::deque<unsigned int> ui = {123, 2};
|
||||
LOG_INFO(logger, "ui {}", ui);
|
||||
|
||||
std::deque<unsigned long> uli = {3213, 2876};
|
||||
LOG_INFO(logger, "uli {}", uli);
|
||||
|
||||
std::deque<unsigned long long> ulli = {321, 1321};
|
||||
LOG_INFO(logger, "ulli {}", ulli);
|
||||
|
||||
std::deque<float> f = {111.1f, 323.31f};
|
||||
LOG_INFO(logger, "f {}", f);
|
||||
|
||||
std::deque<double> d = {12.1, 3213213.123};
|
||||
LOG_INFO(logger, "d {}", d);
|
||||
|
||||
std::deque<int> const& cri = i;
|
||||
LOG_INFO(logger, "cri {}", cri);
|
||||
|
||||
std::deque<int>& ci = i;
|
||||
LOG_INFO(logger, "ci {}", ci);
|
||||
|
||||
std::deque<std::string> sa = {"test", "string"};
|
||||
LOG_INFO(logger, "sa {}", sa);
|
||||
|
||||
std::deque<std::string_view> sva = {"test", "string_view"};
|
||||
LOG_INFO(logger, "sva {}", sva);
|
||||
|
||||
std::deque<char const*> scva = {"c style", "string test", "test", "log"};
|
||||
LOG_INFO(logger, "scva {}", scva);
|
||||
|
||||
std::deque<std::deque<int>> aai = {{{321, 123}, {444, 333}, {111, 222}}};
|
||||
LOG_INFO(logger, "aai {}", aai);
|
||||
|
||||
std::deque<std::deque<char const*>> aacs = {
|
||||
{{"one", "two"}, {"three", "four"}, {"five", "six"}}};
|
||||
LOG_INFO(logger, "aacs {}", aacs);
|
||||
|
||||
std::deque<std::deque<std::deque<char const*>>> aaacs = {
|
||||
{{{{"one", "two"}, {"three", "four"}}},
|
||||
{{{"five", "six"}, {"seven", "eight"}}},
|
||||
{{{"nine", "ten"}, {"eleven", "twelve"}}}}};
|
||||
LOG_INFO(logger, "aaacs {}", aaacs);
|
||||
|
||||
{
|
||||
std::deque<std::deque<std::deque<std::string>>> aaabcs;
|
||||
|
||||
// First outer deque
|
||||
std::deque<std::deque<std::string>> first_outer = {{"std_one", "two"}, {"three", "four"}};
|
||||
|
||||
// Second outer deque
|
||||
std::deque<std::deque<std::string>> second_outer = {{"five", "six"}, {"seven", "eight"}};
|
||||
|
||||
// Third outer deque
|
||||
std::deque<std::deque<std::string>> third_outer = {{"std_nine", "ten"}, {"eleven", "twelve"}};
|
||||
|
||||
aaabcs.push_back(first_outer);
|
||||
aaabcs.push_back(second_outer);
|
||||
aaabcs.push_back(third_outer);
|
||||
|
||||
LOG_INFO(logger, "aaabcs {}", aaabcs);
|
||||
}
|
||||
|
||||
{
|
||||
std::deque<std::deque<std::deque<std::string>>> aaaccs;
|
||||
|
||||
// First outer deque
|
||||
std::deque<std::deque<std::string>> first_outer = {{"std_one", "two"}, {"three_std", "four"}};
|
||||
|
||||
// Second outer deque
|
||||
std::deque<std::deque<std::string>> second_outer = {{"five", "six"}, {"seven_std", "eight"}};
|
||||
|
||||
// Third outer deque
|
||||
std::deque<std::deque<std::string>> third_outer = {{"std_nine", "ten"}, {"eleven", "twelve"}};
|
||||
|
||||
aaaccs.push_back(first_outer);
|
||||
aaaccs.push_back(second_outer);
|
||||
aaaccs.push_back(third_outer);
|
||||
|
||||
LOG_INFO(logger, "aaaccs {}", aaaccs);
|
||||
}
|
||||
|
||||
LOG_INFO(logger, "scva {} sa {} ulli {} scva {} sa {} aaacs {} aai {}", scva, sa, ulli, scva, sa, aaacs, aai);
|
||||
|
||||
std::deque<int> loopv;
|
||||
for (int iter = 0; iter < 100; ++iter)
|
||||
{
|
||||
loopv.push_back(iter);
|
||||
}
|
||||
|
||||
LOG_INFO(logger, "loopv {}", loopv);
|
||||
|
||||
std::deque<std::string> loopsv;
|
||||
for (int iter = 0; iter < 100; ++iter)
|
||||
{
|
||||
loopsv.push_back(std::to_string(iter));
|
||||
}
|
||||
|
||||
LOG_INFO(logger, "loopsv {}", loopsv);
|
||||
|
||||
std::deque<int> empt;
|
||||
LOG_INFO(logger, "empt {}", empt);
|
||||
}
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " c ['a', 'c']"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " si [-12, 10]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " i [-123, 1]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " li [9876, 1232]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " lli [321, 231]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " usi [15, 2]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ui [123, 2]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " uli [3213, 2876]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ulli [321, 1321]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " f [111.1, 323.31]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " d [12.1, 3213213.123]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " cri [-123, 1]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ci [-123, 1]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " sa [\"test\", \"string\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " sva [\"test\", \"string_view\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " scva [\"c style\", \"string test\", \"test\", \"log\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " aai [[321, 123], [444, 333], [111, 222]]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents,
|
||||
std::string{"LOG_INFO " + logger_name +
|
||||
" aacs [[\"one\", \"two\"], [\"three\", \"four\"], [\"five\", \"six\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " aaabcs [[[\"std_one\", \"two\"], [\"three\", \"four\"]], [[\"five\", \"six\"], [\"seven\", \"eight\"]], [[\"std_nine\", \"ten\"], [\"eleven\", \"twelve\"]]]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " aaaccs [[[\"std_one\", \"two\"], [\"three_std\", \"four\"]], [[\"five\", \"six\"], [\"seven_std\", \"eight\"]], [[\"std_nine\", \"ten\"], [\"eleven\", \"twelve\"]]]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " aaacs [[[\"one\", \"two\"], [\"three\", \"four\"]], [[\"five\", \"six\"], [\"seven\", \"eight\"]], [[\"nine\", \"ten\"], [\"eleven\", \"twelve\"]]]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " scva [\"c style\", \"string test\", \"test\", \"log\"] sa [\"test\", \"string\"] ulli [321, 1321] scva [\"c style\", \"string test\", \"test\", \"log\"] sa [\"test\", \"string\"] aaacs [[[\"one\", \"two\"], [\"three\", \"four\"]], [[\"five\", \"six\"], [\"seven\", \"eight\"]], [[\"nine\", \"ten\"], [\"eleven\", \"twelve\"]]] aai [[321, 123], [444, 333], [111, 222]]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " loopv [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " loopsv [\"0\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"10\", \"11\", \"12\", \"13\", \"14\", \"15\", \"16\", \"17\", \"18\", \"19\", \"20\", \"21\", \"22\", \"23\", \"24\", \"25\", \"26\", \"27\", \"28\", \"29\", \"30\", \"31\", \"32\", \"33\", \"34\", \"35\", \"36\", \"37\", \"38\", \"39\", \"40\", \"41\", \"42\", \"43\", \"44\", \"45\", \"46\", \"47\", \"48\", \"49\", \"50\", \"51\", \"52\", \"53\", \"54\", \"55\", \"56\", \"57\", \"58\", \"59\", \"60\", \"61\", \"62\", \"63\", \"64\", \"65\", \"66\", \"67\", \"68\", \"69\", \"70\", \"71\", \"72\", \"73\", \"74\", \"75\", \"76\", \"77\", \"78\", \"79\", \"80\", \"81\", \"82\", \"83\", \"84\", \"85\", \"86\", \"87\", \"88\", \"89\", \"90\", \"91\", \"92\", \"93\", \"94\", \"95\", \"96\", \"97\", \"98\", \"99\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " empt []"}));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/core/Filesystem.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include "quill/std/FilesystemPath.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstdio>
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("std_filesystem_path_logging")
|
||||
{
|
||||
static constexpr char const* filename = "std_filesystem_path_logging.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
{
|
||||
fs::path sp{"/usr/local/bin"};
|
||||
LOG_INFO(logger, "sp {} {} {}", sp, sp, sp);
|
||||
LOG_INFO(logger, "sp_2 {} {} {}", sp, sp, sp);
|
||||
}
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " sp /usr/local/bin /usr/local/bin /usr/local/bin"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " sp_2 /usr/local/bin /usr/local/bin /usr/local/bin"}));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
#include "quill/std/ForwardList.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <forward_list>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("std_forward_list_logging")
|
||||
{
|
||||
static constexpr char const* filename = "std_forward_list_logging.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
{
|
||||
std::forward_list<char> c = {'a', 'c'};
|
||||
LOG_INFO(logger, "c {}", c);
|
||||
|
||||
std::forward_list<short> si = {-12, 10};
|
||||
LOG_INFO(logger, "si {}", si);
|
||||
|
||||
std::forward_list<int> i = {-123, 1};
|
||||
LOG_INFO(logger, "i {}", i);
|
||||
|
||||
std::forward_list<long> li = {9876, 1232};
|
||||
LOG_INFO(logger, "li {}", li);
|
||||
|
||||
std::forward_list<long long> lli = {321, 231};
|
||||
LOG_INFO(logger, "lli {}", lli);
|
||||
|
||||
std::forward_list<unsigned short> usi = {15, 2};
|
||||
LOG_INFO(logger, "usi {}", usi);
|
||||
|
||||
std::forward_list<unsigned int> ui = {123, 2};
|
||||
LOG_INFO(logger, "ui {}", ui);
|
||||
|
||||
std::forward_list<unsigned long> uli = {3213, 2876};
|
||||
LOG_INFO(logger, "uli {}", uli);
|
||||
|
||||
std::forward_list<unsigned long long> ulli = {321, 1321};
|
||||
LOG_INFO(logger, "ulli {}", ulli);
|
||||
|
||||
std::forward_list<float> f = {111.1f, 323.31f};
|
||||
LOG_INFO(logger, "f {}", f);
|
||||
|
||||
std::forward_list<double> d = {12.1, 3213213.123};
|
||||
LOG_INFO(logger, "d {}", d);
|
||||
|
||||
std::forward_list<int> const& cri = i;
|
||||
LOG_INFO(logger, "cri {}", cri);
|
||||
|
||||
std::forward_list<int>& ci = i;
|
||||
LOG_INFO(logger, "ci {}", ci);
|
||||
|
||||
std::forward_list<std::string> sa = {"test", "string"};
|
||||
LOG_INFO(logger, "sa {}", sa);
|
||||
|
||||
std::forward_list<std::string_view> sva = {"test", "string_view"};
|
||||
LOG_INFO(logger, "sva {}", sva);
|
||||
|
||||
std::forward_list<char const*> scva = {"c style", "string test", "test", "log"};
|
||||
LOG_INFO(logger, "scva {}", scva);
|
||||
|
||||
LOG_INFO(logger, "scva {} sa {} ulli {} scva {} sa {}", scva, sa, ulli, scva, sa);
|
||||
|
||||
std::forward_list<int> empt;
|
||||
LOG_INFO(logger, "empt {}", empt);
|
||||
}
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " c ['a', 'c']"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " si [-12, 10]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " i [-123, 1]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " li [9876, 1232]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " lli [321, 231]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " usi [15, 2]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ui [123, 2]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " uli [3213, 2876]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ulli [321, 1321]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " f [111.1, 323.31]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " d [12.1, 3213213.123]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " cri [-123, 1]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ci [-123, 1]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " sa [\"test\", \"string\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " sva [\"test\", \"string_view\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " scva [\"c style\", \"string test\", \"test\", \"log\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " scva [\"c style\", \"string test\", \"test\", \"log\"] sa [\"test\", \"string\"] ulli [321, 1321] scva [\"c style\", \"string test\", \"test\", \"log\"] sa [\"test\", \"string\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " empt []"}));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
#include "quill/std/List.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("std_list_logging")
|
||||
{
|
||||
static constexpr char const* filename = "std_list_logging.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
{
|
||||
std::list<char> c = {'a', 'c'};
|
||||
LOG_INFO(logger, "c {}", c);
|
||||
|
||||
std::list<short> si = {-12, 10};
|
||||
LOG_INFO(logger, "si {}", si);
|
||||
|
||||
std::list<int> i = {-123, 1};
|
||||
LOG_INFO(logger, "i {}", i);
|
||||
|
||||
std::list<long> li = {9876, 1232};
|
||||
LOG_INFO(logger, "li {}", li);
|
||||
|
||||
std::list<long long> lli = {321, 231};
|
||||
LOG_INFO(logger, "lli {}", lli);
|
||||
|
||||
std::list<unsigned short> usi = {15, 2};
|
||||
LOG_INFO(logger, "usi {}", usi);
|
||||
|
||||
std::list<unsigned int> ui = {123, 2};
|
||||
LOG_INFO(logger, "ui {}", ui);
|
||||
|
||||
std::list<unsigned long> uli = {3213, 2876};
|
||||
LOG_INFO(logger, "uli {}", uli);
|
||||
|
||||
std::list<unsigned long long> ulli = {321, 1321};
|
||||
LOG_INFO(logger, "ulli {}", ulli);
|
||||
|
||||
std::list<float> f = {111.1f, 323.31f};
|
||||
LOG_INFO(logger, "f {}", f);
|
||||
|
||||
std::list<double> d = {12.1, 3213213.123};
|
||||
LOG_INFO(logger, "d {}", d);
|
||||
|
||||
std::list<int> const& cri = i;
|
||||
LOG_INFO(logger, "cri {}", cri);
|
||||
|
||||
std::list<int>& ci = i;
|
||||
LOG_INFO(logger, "ci {}", ci);
|
||||
|
||||
std::list<std::string> sa = {"test", "string"};
|
||||
LOG_INFO(logger, "sa {}", sa);
|
||||
|
||||
std::list<std::string_view> sva = {"test", "string_view"};
|
||||
LOG_INFO(logger, "sva {}", sva);
|
||||
|
||||
std::list<char const*> scva = {"c style", "string test", "test", "log"};
|
||||
LOG_INFO(logger, "scva {}", scva);
|
||||
|
||||
LOG_INFO(logger, "scva {} sa {} ulli {} scva {} sa {}", scva, sa, ulli, scva, sa);
|
||||
|
||||
std::list<int> empt;
|
||||
LOG_INFO(logger, "empt {}", empt);
|
||||
}
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " c ['a', 'c']"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " si [-12, 10]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " i [-123, 1]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " li [9876, 1232]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " lli [321, 231]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " usi [15, 2]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ui [123, 2]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " uli [3213, 2876]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ulli [321, 1321]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " f [111.1, 323.31]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " d [12.1, 3213213.123]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " cri [-123, 1]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ci [-123, 1]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " sa [\"test\", \"string\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " sva [\"test\", \"string_view\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " scva [\"c style\", \"string test\", \"test\", \"log\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " scva [\"c style\", \"string test\", \"test\", \"log\"] sa [\"test\", \"string\"] ulli [321, 1321] scva [\"c style\", \"string test\", \"test\", \"log\"] sa [\"test\", \"string\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " empt []"}));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
#include "quill/std/Map.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
struct CStringComparator
|
||||
{
|
||||
bool operator()(char const* a, char const* b) const { return std::strcmp(a, b) < 0; }
|
||||
};
|
||||
|
||||
/***/
|
||||
TEST_CASE("std_map_logging")
|
||||
{
|
||||
static constexpr char const* filename = "std_map_logging.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
{
|
||||
std::map<int, double> idm = {{111, 3213.21}, {222, 321.19}, {333, 5555.99}};
|
||||
LOG_INFO(logger, "idm {}", idm);
|
||||
|
||||
std::map<int, std::string> loopv;
|
||||
for (int iter = 0; iter < 25; ++iter)
|
||||
{
|
||||
loopv.emplace(iter, std::to_string(iter));
|
||||
}
|
||||
LOG_INFO(logger, "loopv {}", loopv);
|
||||
|
||||
std::map<std::string, std::string> loopsv;
|
||||
for (int iter = 0; iter < 25; ++iter)
|
||||
{
|
||||
loopsv.emplace(std::to_string(iter), std::to_string(iter * 2));
|
||||
}
|
||||
LOG_INFO(logger, "loopsv {}", loopv);
|
||||
|
||||
std::map<char const*, char const*, CStringComparator> ccm = {
|
||||
{"4", "400"}, {"3", "300"}, {"1", "100"}, {"2", "200"}};
|
||||
LOG_INFO(logger, "ccm {}", ccm);
|
||||
|
||||
std::map<char const*, int, CStringComparator> cim = {{"4", 4}, {"3", 3}, {"1", 1}, {"2", 2}};
|
||||
LOG_INFO(logger, "cim {}", cim);
|
||||
}
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " idm {111: 3213.21, 222: 321.19, 333: 5555.99}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " loopv {0: \"0\", 1: \"1\", 2: \"2\", 3: \"3\", 4: \"4\", 5: \"5\", 6: \"6\", 7: \"7\", 8: \"8\", 9: \"9\", 10: \"10\", 11: \"11\", 12: \"12\", 13: \"13\", 14: \"14\", 15: \"15\", 16: \"16\", 17: \"17\", 18: \"18\", 19: \"19\", 20: \"20\", 21: \"21\", 22: \"22\", 23: \"23\", 24: \"24\"}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " loopsv {0: \"0\", 1: \"1\", 2: \"2\", 3: \"3\", 4: \"4\", 5: \"5\", 6: \"6\", 7: \"7\", 8: \"8\", 9: \"9\", 10: \"10\", 11: \"11\", 12: \"12\", 13: \"13\", 14: \"14\", 15: \"15\", 16: \"16\", 17: \"17\", 18: \"18\", 19: \"19\", 20: \"20\", 21: \"21\", 22: \"22\", 23: \"23\", 24: \"24\""}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents,
|
||||
std::string{"LOG_INFO " + logger_name +
|
||||
" ccm {\"1\": \"100\", \"2\": \"200\", \"3\": \"300\", \"4\": \"400\"}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " cim {\"1\": 1, \"2\": 2, \"3\": 3, \"4\": 4}"}));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
#include "quill/std/Map.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
struct CStringComparator
|
||||
{
|
||||
bool operator()(char const* a, char const* b) const { return std::strcmp(a, b) < 0; }
|
||||
};
|
||||
|
||||
/***/
|
||||
TEST_CASE("std_multimap_logging")
|
||||
{
|
||||
static constexpr char const* filename = "std_multimap_logging.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
{
|
||||
std::multimap<int, double> idm = {{111, 3213.21}, {222, 321.19}, {333, 5555.99}};
|
||||
LOG_INFO(logger, "idm {}", idm);
|
||||
|
||||
std::multimap<int, std::string> loopv;
|
||||
for (int iter = 0; iter < 25; ++iter)
|
||||
{
|
||||
loopv.emplace(iter, std::to_string(iter));
|
||||
}
|
||||
LOG_INFO(logger, "loopv {}", loopv);
|
||||
|
||||
std::multimap<std::string, std::string> loopsv;
|
||||
for (int iter = 0; iter < 25; ++iter)
|
||||
{
|
||||
loopsv.emplace(std::to_string(iter), std::to_string(iter * 2));
|
||||
}
|
||||
LOG_INFO(logger, "loopsv {}", loopv);
|
||||
|
||||
std::multimap<char const*, char const*, CStringComparator> ccm = {
|
||||
{"4", "400"}, {"3", "300"}, {"1", "100"}, {"2", "200"}};
|
||||
LOG_INFO(logger, "ccm {}", ccm);
|
||||
|
||||
std::multimap<char const*, int, CStringComparator> cim = {{"4", 4}, {"3", 3}, {"1", 1}, {"2", 2}};
|
||||
LOG_INFO(logger, "cim {}", cim);
|
||||
}
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " idm {111: 3213.21, 222: 321.19, 333: 5555.99}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " loopv {0: \"0\", 1: \"1\", 2: \"2\", 3: \"3\", 4: \"4\", 5: \"5\", 6: \"6\", 7: \"7\", 8: \"8\", 9: \"9\", 10: \"10\", 11: \"11\", 12: \"12\", 13: \"13\", 14: \"14\", 15: \"15\", 16: \"16\", 17: \"17\", 18: \"18\", 19: \"19\", 20: \"20\", 21: \"21\", 22: \"22\", 23: \"23\", 24: \"24\"}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " loopsv {0: \"0\", 1: \"1\", 2: \"2\", 3: \"3\", 4: \"4\", 5: \"5\", 6: \"6\", 7: \"7\", 8: \"8\", 9: \"9\", 10: \"10\", 11: \"11\", 12: \"12\", 13: \"13\", 14: \"14\", 15: \"15\", 16: \"16\", 17: \"17\", 18: \"18\", 19: \"19\", 20: \"20\", 21: \"21\", 22: \"22\", 23: \"23\", 24: \"24\""}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents,
|
||||
std::string{"LOG_INFO " + logger_name +
|
||||
" ccm {\"1\": \"100\", \"2\": \"200\", \"3\": \"300\", \"4\": \"400\"}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " cim {\"1\": 1, \"2\": 2, \"3\": 3, \"4\": 4}"}));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,218 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
#include "quill/std/Set.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
struct CStringComparator
|
||||
{
|
||||
bool operator()(char const* a, char const* b) const { return std::strcmp(a, b) < 0; }
|
||||
};
|
||||
|
||||
/***/
|
||||
TEST_CASE("std_multiset_logging")
|
||||
{
|
||||
static constexpr char const* filename = "std_multiset_logging.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
{
|
||||
std::multiset<char> c = {'a', 'c'};
|
||||
LOG_INFO(logger, "c {}", c);
|
||||
|
||||
std::multiset<short> si = {-12, 10};
|
||||
LOG_INFO(logger, "si {}", si);
|
||||
|
||||
std::multiset<int> i = {-123, 1};
|
||||
LOG_INFO(logger, "i {}", i);
|
||||
|
||||
std::multiset<long> li = {9876, 1232};
|
||||
LOG_INFO(logger, "li {}", li);
|
||||
|
||||
std::multiset<long long> lli = {321, 231};
|
||||
LOG_INFO(logger, "lli {}", lli);
|
||||
|
||||
std::multiset<unsigned short> usi = {15, 2};
|
||||
LOG_INFO(logger, "usi {}", usi);
|
||||
|
||||
std::multiset<unsigned int> ui = {123, 2};
|
||||
LOG_INFO(logger, "ui {}", ui);
|
||||
|
||||
std::multiset<unsigned long> uli = {3213, 2876};
|
||||
LOG_INFO(logger, "uli {}", uli);
|
||||
|
||||
std::multiset<unsigned long long> ulli = {321, 1321};
|
||||
LOG_INFO(logger, "ulli {}", ulli);
|
||||
|
||||
std::multiset<float> f = {111.1f, 323.31f};
|
||||
LOG_INFO(logger, "f {}", f);
|
||||
|
||||
std::multiset<double> d = {12.1, 3213213.123};
|
||||
LOG_INFO(logger, "d {}", d);
|
||||
|
||||
std::multiset<int> const& cri = i;
|
||||
LOG_INFO(logger, "cri {}", cri);
|
||||
|
||||
std::multiset<int>& ci = i;
|
||||
LOG_INFO(logger, "ci {}", ci);
|
||||
|
||||
std::multiset<std::string> sa = {"test", "string"};
|
||||
LOG_INFO(logger, "sa {}", sa);
|
||||
|
||||
std::multiset<std::string_view> sva = {"test", "string_view"};
|
||||
LOG_INFO(logger, "sva {}", sva);
|
||||
|
||||
std::multiset<char const*, CStringComparator> scva = {"c_style", "aa", "string_test", "test",
|
||||
"log"};
|
||||
LOG_INFO(logger, "scva {}", scva);
|
||||
|
||||
std::multiset<std::multiset<int>> aai = {{{321, 123}, {444, 333}, {111, 222}}};
|
||||
LOG_INFO(logger, "aai {}", aai);
|
||||
|
||||
{
|
||||
std::multiset<std::multiset<char const*, CStringComparator>> aacs = {
|
||||
{{"one", "two"}, {"three", "four"}, {"five", "six"}}};
|
||||
LOG_INFO(logger, "aacs {}", aacs);
|
||||
}
|
||||
|
||||
{
|
||||
std::multiset<std::multiset<std::multiset<char const*, CStringComparator>>> aaacs = {
|
||||
{{{{"one", "two"}, {"three", "four"}}},
|
||||
{{{"five", "six"}, {"seven", "eight"}}},
|
||||
{{{"nine", "ten"}, {"eleven", "twelve"}}}}};
|
||||
LOG_INFO(logger, "aaacs {}", aaacs);
|
||||
}
|
||||
|
||||
LOG_INFO(logger, "scva {} sa {} ulli {} scva {} sa {} aai {}", scva, sa, ulli, scva, sa, aai);
|
||||
|
||||
std::multiset<int> loopv;
|
||||
for (int iter = 0; iter < 100; ++iter)
|
||||
{
|
||||
loopv.insert(iter);
|
||||
}
|
||||
|
||||
LOG_INFO(logger, "loopv {}", loopv);
|
||||
|
||||
std::multiset<std::string> loopsv;
|
||||
for (int iter = 0; iter < 100; ++iter)
|
||||
{
|
||||
loopsv.insert(std::to_string(iter));
|
||||
}
|
||||
|
||||
LOG_INFO(logger, "loopsv {}", loopsv);
|
||||
|
||||
std::multiset<int> empt;
|
||||
LOG_INFO(logger, "empt {}", empt);
|
||||
}
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " c {'a', 'c'}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " si {-12, 10}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " i {-123, 1}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " li {1232, 9876}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " lli {231, 321}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " usi {2, 15}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ui {2, 123}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " uli {2876, 3213}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ulli {321, 1321}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " f {111.1, 323.31}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " d {12.1, 3213213.123}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " cri {-123, 1}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ci {-123, 1}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " sa {\"string\", \"test\"}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " sva {\"string_view\", \"test\"}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents,
|
||||
std::string{"LOG_INFO " + logger_name +
|
||||
" scva {\"aa\", \"c_style\", \"log\", \"string_test\", \"test\"}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " aai {{111, 222}, {123, 321}, {333, 444}}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " aacs {{"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " aaacs {{{"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " scva {\"aa\", \"c_style\", \"log\", \"string_test\", \"test\"} sa {\"string\", \"test\"} ulli {321, 1321} scva {\"aa\", \"c_style\", \"log\", \"string_test\", \"test\"} sa {\"string\", \"test\"} aai {{111, 222}, {123, 321}, {333, 444}}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " loopv {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " loopsv {\"0\", \"1\", \"10\", \"11\", \"12\", \"13\", \"14\", \"15\", \"16\", \"17\", \"18\", \"19\", \"2\", \"20\", \"21\", \"22\", \"23\", \"24\", \"25\", \"26\", \"27\", \"28\", \"29\", \"3\", \"30\", \"31\", \"32\", \"33\", \"34\", \"35\", \"36\", \"37\", \"38\", \"39\", \"4\", \"40\", \"41\", \"42\", \"43\", \"44\", \"45\", \"46\", \"47\", \"48\", \"49\", \"5\", \"50\", \"51\", \"52\", \"53\", \"54\", \"55\", \"56\", \"57\", \"58\", \"59\", \"6\", \"60\", \"61\", \"62\", \"63\", \"64\", \"65\", \"66\", \"67\", \"68\", \"69\", \"7\", \"70\", \"71\", \"72\", \"73\", \"74\", \"75\", \"76\", \"77\", \"78\", \"79\", \"8\", \"80\", \"81\", \"82\", \"83\", \"84\", \"85\", \"86\", \"87\", \"88\", \"89\", \"9\", \"90\", \"91\", \"92\", \"93\", \"94\", \"95\", \"96\", \"97\", \"98\", \"99\"}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " empt {}"}));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include "quill/std/Optional.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstdio>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("std_optional_logging")
|
||||
{
|
||||
static constexpr char const* filename = "std_optional_logging.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
{
|
||||
std::optional<int> ei{std::nullopt};
|
||||
LOG_INFO(logger, "ei [{}]", ei);
|
||||
|
||||
std::optional<double> ed{std::nullopt};
|
||||
LOG_INFO(logger, "ed [{}]", ed);
|
||||
|
||||
std::optional<char const*> ccp{"testing"};
|
||||
LOG_INFO(logger, "ccp [{}]", ccp);
|
||||
|
||||
std::optional<std::string> sp{"sp_testing"};
|
||||
LOG_INFO(logger, "sp [{}]", sp);
|
||||
|
||||
std::optional<std::string> esp{std::nullopt};
|
||||
LOG_INFO(logger, "esp [{}]", esp);
|
||||
|
||||
std::optional<std::string_view> svp{"svp_testing"};
|
||||
LOG_INFO(logger, "svp [{}]", svp);
|
||||
|
||||
std::optional<int> i{123321};
|
||||
LOG_INFO(logger, "i [{}]", i);
|
||||
|
||||
std::optional<double> d{333.221};
|
||||
LOG_INFO(logger, "d [{}]", d);
|
||||
|
||||
LOG_INFO(logger, "zzzz [{}] [{}] [{}] [{}] [{}]", d, "test", *svp, *sp, ccp);
|
||||
}
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ei [none]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ed [none]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ccp [optional(\"testing\")]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " sp [optional(\"sp_testing\")]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " esp [none]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " svp [optional(\"svp_testing\")]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " i [optional(123321)]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " d [optional(333.221)]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " zzzz [optional(333.221)] [test] [svp_testing] [sp_testing] [optional(\"testing\")]"}));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include "quill/std/Pair.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("std_pair_logging")
|
||||
{
|
||||
static constexpr char const* filename = "std_pair_logging.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
{
|
||||
std::pair<bool, int> b = {true, 312};
|
||||
LOG_INFO(logger, "v {}", b);
|
||||
|
||||
std::pair<std::string, std::string> sa = {"test", "string"};
|
||||
LOG_INFO(logger, "sa {}", sa);
|
||||
|
||||
std::pair<std::string_view, std::string> sva = {"test", "string_view"};
|
||||
LOG_INFO(logger, "sva {}", sva);
|
||||
|
||||
std::pair<char const*, std::string> scva = {"c style", "string test"};
|
||||
LOG_INFO(logger, "scva {}", scva);
|
||||
|
||||
std::pair<std::pair<std::string, std::string_view>, std::pair<const char*, uint32_t>> cp = {
|
||||
{"pair", "testing"}, {"first", 2}};
|
||||
LOG_INFO(logger, "cp {}", cp);
|
||||
|
||||
std::pair<int, double> empt;
|
||||
LOG_INFO(logger, "empt {}", empt);
|
||||
}
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " v (true, 312)"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " sa (\"test\", \"string\")"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " sva (\"test\", \"string_view\")"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " scva (\"c style\", \"string test\")"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " cp ((\"pair\", \"testing\"), (\"first\", 2))"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " empt (0, 0)"}));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,217 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
#include "quill/std/Set.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
struct CStringComparator
|
||||
{
|
||||
bool operator()(char const* a, char const* b) const { return std::strcmp(a, b) < 0; }
|
||||
};
|
||||
|
||||
/***/
|
||||
TEST_CASE("std_set_logging")
|
||||
{
|
||||
static constexpr char const* filename = "std_set_logging.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
{
|
||||
std::set<char> c = {'a', 'c'};
|
||||
LOG_INFO(logger, "c {}", c);
|
||||
|
||||
std::set<short> si = {-12, 10};
|
||||
LOG_INFO(logger, "si {}", si);
|
||||
|
||||
std::set<int> i = {-123, 1};
|
||||
LOG_INFO(logger, "i {}", i);
|
||||
|
||||
std::set<long> li = {9876, 1232};
|
||||
LOG_INFO(logger, "li {}", li);
|
||||
|
||||
std::set<long long> lli = {321, 231};
|
||||
LOG_INFO(logger, "lli {}", lli);
|
||||
|
||||
std::set<unsigned short> usi = {15, 2};
|
||||
LOG_INFO(logger, "usi {}", usi);
|
||||
|
||||
std::set<unsigned int> ui = {123, 2};
|
||||
LOG_INFO(logger, "ui {}", ui);
|
||||
|
||||
std::set<unsigned long> uli = {3213, 2876};
|
||||
LOG_INFO(logger, "uli {}", uli);
|
||||
|
||||
std::set<unsigned long long> ulli = {321, 1321};
|
||||
LOG_INFO(logger, "ulli {}", ulli);
|
||||
|
||||
std::set<float> f = {111.1f, 323.31f};
|
||||
LOG_INFO(logger, "f {}", f);
|
||||
|
||||
std::set<double> d = {12.1, 3213213.123};
|
||||
LOG_INFO(logger, "d {}", d);
|
||||
|
||||
std::set<int> const& cri = i;
|
||||
LOG_INFO(logger, "cri {}", cri);
|
||||
|
||||
std::set<int>& ci = i;
|
||||
LOG_INFO(logger, "ci {}", ci);
|
||||
|
||||
std::set<std::string> sa = {"test", "string"};
|
||||
LOG_INFO(logger, "sa {}", sa);
|
||||
|
||||
std::set<std::string_view> sva = {"test", "string_view"};
|
||||
LOG_INFO(logger, "sva {}", sva);
|
||||
|
||||
std::set<char const*, CStringComparator> scva = {"c_style", "aa", "string_test", "test", "log"};
|
||||
LOG_INFO(logger, "scva {}", scva);
|
||||
|
||||
std::set<std::set<int>> aai = {{{321, 123}, {444, 333}, {111, 222}}};
|
||||
LOG_INFO(logger, "aai {}", aai);
|
||||
|
||||
{
|
||||
std::set<std::set<char const*, CStringComparator>> aacs = {
|
||||
{{"one", "two"}, {"three", "four"}, {"five", "six"}}};
|
||||
LOG_INFO(logger, "aacs {}", aacs);
|
||||
}
|
||||
|
||||
{
|
||||
std::set<std::set<std::set<char const*, CStringComparator>>> aaacs = {
|
||||
{{{{"one", "two"}, {"three", "four"}}},
|
||||
{{{"five", "six"}, {"seven", "eight"}}},
|
||||
{{{"nine", "ten"}, {"eleven", "twelve"}}}}};
|
||||
LOG_INFO(logger, "aaacs {}", aaacs);
|
||||
}
|
||||
|
||||
LOG_INFO(logger, "scva {} sa {} ulli {} scva {} sa {} aai {}", scva, sa, ulli, scva, sa, aai);
|
||||
|
||||
std::set<int> loopv;
|
||||
for (int iter = 0; iter < 100; ++iter)
|
||||
{
|
||||
loopv.insert(iter);
|
||||
}
|
||||
|
||||
LOG_INFO(logger, "loopv {}", loopv);
|
||||
|
||||
std::set<std::string> loopsv;
|
||||
for (int iter = 0; iter < 100; ++iter)
|
||||
{
|
||||
loopsv.insert(std::to_string(iter));
|
||||
}
|
||||
|
||||
LOG_INFO(logger, "loopsv {}", loopsv);
|
||||
|
||||
std::set<int> empt;
|
||||
LOG_INFO(logger, "empt {}", empt);
|
||||
}
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " c {'a', 'c'}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " si {-12, 10}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " i {-123, 1}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " li {1232, 9876}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " lli {231, 321}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " usi {2, 15}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ui {2, 123}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " uli {2876, 3213}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ulli {321, 1321}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " f {111.1, 323.31}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " d {12.1, 3213213.123}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " cri {-123, 1}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ci {-123, 1}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " sa {\"string\", \"test\"}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " sva {\"string_view\", \"test\"}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents,
|
||||
std::string{"LOG_INFO " + logger_name +
|
||||
" scva {\"aa\", \"c_style\", \"log\", \"string_test\", \"test\"}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " aai {{111, 222}, {123, 321}, {333, 444}}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " aacs {{"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " aaacs {{{"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " scva {\"aa\", \"c_style\", \"log\", \"string_test\", \"test\"} sa {\"string\", \"test\"} ulli {321, 1321} scva {\"aa\", \"c_style\", \"log\", \"string_test\", \"test\"} sa {\"string\", \"test\"} aai {{111, 222}, {123, 321}, {333, 444}}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " loopv {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " loopsv {\"0\", \"1\", \"10\", \"11\", \"12\", \"13\", \"14\", \"15\", \"16\", \"17\", \"18\", \"19\", \"2\", \"20\", \"21\", \"22\", \"23\", \"24\", \"25\", \"26\", \"27\", \"28\", \"29\", \"3\", \"30\", \"31\", \"32\", \"33\", \"34\", \"35\", \"36\", \"37\", \"38\", \"39\", \"4\", \"40\", \"41\", \"42\", \"43\", \"44\", \"45\", \"46\", \"47\", \"48\", \"49\", \"5\", \"50\", \"51\", \"52\", \"53\", \"54\", \"55\", \"56\", \"57\", \"58\", \"59\", \"6\", \"60\", \"61\", \"62\", \"63\", \"64\", \"65\", \"66\", \"67\", \"68\", \"69\", \"7\", \"70\", \"71\", \"72\", \"73\", \"74\", \"75\", \"76\", \"77\", \"78\", \"79\", \"8\", \"80\", \"81\", \"82\", \"83\", \"84\", \"85\", \"86\", \"87\", \"88\", \"89\", \"9\", \"90\", \"91\", \"92\", \"93\", \"94\", \"95\", \"96\", \"97\", \"98\", \"99\"}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " empt {}"}));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include "quill/std/Tuple.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("std_tuple_logging")
|
||||
{
|
||||
static constexpr char const* filename = "std_tuple_logging.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
{
|
||||
std::tuple<std::string> st{"123456789"};
|
||||
LOG_INFO(logger, "st {}", st);
|
||||
|
||||
std::tuple<std::string, int> et;
|
||||
LOG_INFO(logger, "et {}", et);
|
||||
|
||||
std::tuple<std::string, std::string_view, int, double, char const*, std::string, int> ct{
|
||||
"string", "string_view", 213, 33.12, "c_style", "another_string", 123};
|
||||
LOG_INFO(logger, "ct {}", ct);
|
||||
|
||||
LOG_INFO(logger, "ct {} et {} st {}", ct, et, st);
|
||||
}
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " st (\"123456789\")"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " et (\"\", 0)"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ct (\"string\", \"string_view\", 213, 33.12, \"c_style\", \"another_string\", 123)"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ct (\"string\", \"string_view\", 213, 33.12, \"c_style\", \"another_string\", 123) et (\"\", 0) st (\"123456789\")"}));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
#include "quill/std/UnorderedMap.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("std_unordered_map_logging")
|
||||
{
|
||||
static constexpr char const* filename = "std_unordered_map_logging.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
{
|
||||
std::unordered_map<int, double> idm = {{111, 3213.21}};
|
||||
LOG_INFO(logger, "idm {}", idm);
|
||||
|
||||
std::unordered_map<int, std::string> loopv;
|
||||
for (int iter = 0; iter < 25; ++iter)
|
||||
{
|
||||
loopv.emplace(iter, std::to_string(iter));
|
||||
}
|
||||
LOG_INFO(logger, "loopv {}", loopv);
|
||||
|
||||
std::unordered_map<std::string, std::string> loopsv;
|
||||
for (int iter = 0; iter < 25; ++iter)
|
||||
{
|
||||
loopsv.emplace(std::to_string(iter), std::to_string(iter * 2));
|
||||
}
|
||||
LOG_INFO(logger, "loopsv {}", loopv);
|
||||
|
||||
std::unordered_map<char const*, char const*> ccm = {{"4", "400"}};
|
||||
LOG_INFO(logger, "ccm {}", ccm);
|
||||
|
||||
std::unordered_map<char const*, int> cim = {{"4", 4}};
|
||||
LOG_INFO(logger, "cim {}", cim);
|
||||
}
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " idm {111: 3213.21}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " loopv {"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " loopsv {"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ccm {\"4\": \"400\"}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " cim {\"4\": 4}"}));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
#include "quill/std/UnorderedMap.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("std_unordered_multimap_logging")
|
||||
{
|
||||
static constexpr char const* filename = "std_unordered_multimap_logging.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
{
|
||||
std::unordered_multimap<int, double> idm = {{111, 3213.21}};
|
||||
LOG_INFO(logger, "idm {}", idm);
|
||||
|
||||
std::unordered_multimap<int, std::string> loopv;
|
||||
for (int iter = 0; iter < 25; ++iter)
|
||||
{
|
||||
loopv.emplace(iter, std::to_string(iter));
|
||||
}
|
||||
LOG_INFO(logger, "loopv {}", loopv);
|
||||
|
||||
std::unordered_multimap<std::string, std::string> loopsv;
|
||||
for (int iter = 0; iter < 25; ++iter)
|
||||
{
|
||||
loopsv.emplace(std::to_string(iter), std::to_string(iter * 2));
|
||||
}
|
||||
LOG_INFO(logger, "loopsv {}", loopv);
|
||||
|
||||
std::unordered_multimap<char const*, char const*> ccm = {{"4", "400"}};
|
||||
LOG_INFO(logger, "ccm {}", ccm);
|
||||
|
||||
std::unordered_multimap<char const*, int> cim = {{"4", 4}};
|
||||
LOG_INFO(logger, "cim {}", cim);
|
||||
}
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " idm {111: 3213.21}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " loopv {"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " loopsv {"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ccm {\"4\": \"400\"}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " cim {\"4\": 4}"}));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,184 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
#include "quill/std/UnorderedSet.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("std_unordered_multi_set_logging")
|
||||
{
|
||||
static constexpr char const* filename = "std_unordered_multi_set_logging.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
{
|
||||
std::unordered_multiset<char> c = {'a'};
|
||||
LOG_INFO(logger, "c {}", c);
|
||||
|
||||
std::unordered_multiset<short> si = {-12};
|
||||
LOG_INFO(logger, "si {}", si);
|
||||
|
||||
std::unordered_multiset<int> i = {-123};
|
||||
LOG_INFO(logger, "i {}", i);
|
||||
|
||||
std::unordered_multiset<long> li = {9876};
|
||||
LOG_INFO(logger, "li {}", li);
|
||||
|
||||
std::unordered_multiset<long long> lli = {321};
|
||||
LOG_INFO(logger, "lli {}", lli);
|
||||
|
||||
std::unordered_multiset<unsigned short> usi = {15};
|
||||
LOG_INFO(logger, "usi {}", usi);
|
||||
|
||||
std::unordered_multiset<unsigned int> ui = {123};
|
||||
LOG_INFO(logger, "ui {}", ui);
|
||||
|
||||
std::unordered_multiset<unsigned long> uli = {3213};
|
||||
LOG_INFO(logger, "uli {}", uli);
|
||||
|
||||
std::unordered_multiset<unsigned long long> ulli = {321};
|
||||
LOG_INFO(logger, "ulli {}", ulli);
|
||||
|
||||
std::unordered_multiset<float> f = {111.1f};
|
||||
LOG_INFO(logger, "f {}", f);
|
||||
|
||||
std::unordered_multiset<double> d = {12.1};
|
||||
LOG_INFO(logger, "d {}", d);
|
||||
|
||||
std::unordered_multiset<int> const& cri = i;
|
||||
LOG_INFO(logger, "cri {}", cri);
|
||||
|
||||
std::unordered_multiset<int>& ci = i;
|
||||
LOG_INFO(logger, "ci {}", ci);
|
||||
|
||||
std::unordered_multiset<std::string> sa = {"test"};
|
||||
LOG_INFO(logger, "sa {}", sa);
|
||||
|
||||
std::unordered_multiset<std::string_view> sva = {"string_view"};
|
||||
LOG_INFO(logger, "sva {}", sva);
|
||||
|
||||
std::unordered_multiset<char const*> scva = {"c_style"};
|
||||
LOG_INFO(logger, "scva {}", scva);
|
||||
|
||||
LOG_INFO(logger, "scva {} sa {} ulli {} scva {} sa {}", scva, sa, ulli, scva, sa);
|
||||
|
||||
std::unordered_multiset<int> loopv;
|
||||
for (int iter = 0; iter < 100; ++iter)
|
||||
{
|
||||
loopv.insert(iter);
|
||||
}
|
||||
|
||||
LOG_INFO(logger, "loopv {}", loopv);
|
||||
|
||||
std::unordered_multiset<std::string> loopsv;
|
||||
for (int iter = 0; iter < 100; ++iter)
|
||||
{
|
||||
loopsv.insert(std::to_string(iter));
|
||||
}
|
||||
|
||||
LOG_INFO(logger, "loopsv {}", loopsv);
|
||||
|
||||
std::unordered_multiset<int> empt;
|
||||
LOG_INFO(logger, "empt {}", empt);
|
||||
}
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " c {'a'}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " si {-12}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " i {-123}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " li {9876}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " lli {321}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " usi {15}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ui {123}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " uli {3213}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ulli {321}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " f {111.1}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " d {12.1}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " cri {-123}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ci {-123}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " sa {\"test\"}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " sva {\"string_view\"}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " scva {\"c_style\"}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " scva {\"c_style\"} sa {\"test\"} ulli {321} scva {\"c_style\"} sa {\"test\"}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " loopv {"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " loopsv {"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " empt {}"}));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,184 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
#include "quill/std/UnorderedSet.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("std_unordered_set_logging")
|
||||
{
|
||||
static constexpr char const* filename = "std_unordered_set_logging.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
{
|
||||
std::unordered_set<char> c = {'a'};
|
||||
LOG_INFO(logger, "c {}", c);
|
||||
|
||||
std::unordered_set<short> si = {-12};
|
||||
LOG_INFO(logger, "si {}", si);
|
||||
|
||||
std::unordered_set<int> i = {-123};
|
||||
LOG_INFO(logger, "i {}", i);
|
||||
|
||||
std::unordered_set<long> li = {9876};
|
||||
LOG_INFO(logger, "li {}", li);
|
||||
|
||||
std::unordered_set<long long> lli = {321};
|
||||
LOG_INFO(logger, "lli {}", lli);
|
||||
|
||||
std::unordered_set<unsigned short> usi = {15};
|
||||
LOG_INFO(logger, "usi {}", usi);
|
||||
|
||||
std::unordered_set<unsigned int> ui = {123};
|
||||
LOG_INFO(logger, "ui {}", ui);
|
||||
|
||||
std::unordered_set<unsigned long> uli = {3213};
|
||||
LOG_INFO(logger, "uli {}", uli);
|
||||
|
||||
std::unordered_set<unsigned long long> ulli = {321};
|
||||
LOG_INFO(logger, "ulli {}", ulli);
|
||||
|
||||
std::unordered_set<float> f = {111.1f};
|
||||
LOG_INFO(logger, "f {}", f);
|
||||
|
||||
std::unordered_set<double> d = {12.1};
|
||||
LOG_INFO(logger, "d {}", d);
|
||||
|
||||
std::unordered_set<int> const& cri = i;
|
||||
LOG_INFO(logger, "cri {}", cri);
|
||||
|
||||
std::unordered_set<int>& ci = i;
|
||||
LOG_INFO(logger, "ci {}", ci);
|
||||
|
||||
std::unordered_set<std::string> sa = {"test"};
|
||||
LOG_INFO(logger, "sa {}", sa);
|
||||
|
||||
std::unordered_set<std::string_view> sva = {"string_view"};
|
||||
LOG_INFO(logger, "sva {}", sva);
|
||||
|
||||
std::unordered_set<char const*> scva = {"c_style"};
|
||||
LOG_INFO(logger, "scva {}", scva);
|
||||
|
||||
LOG_INFO(logger, "scva {} sa {} ulli {} scva {} sa {}", scva, sa, ulli, scva, sa);
|
||||
|
||||
std::unordered_set<int> loopv;
|
||||
for (int iter = 0; iter < 100; ++iter)
|
||||
{
|
||||
loopv.insert(iter);
|
||||
}
|
||||
|
||||
LOG_INFO(logger, "loopv {}", loopv);
|
||||
|
||||
std::unordered_set<std::string> loopsv;
|
||||
for (int iter = 0; iter < 100; ++iter)
|
||||
{
|
||||
loopsv.insert(std::to_string(iter));
|
||||
}
|
||||
|
||||
LOG_INFO(logger, "loopsv {}", loopsv);
|
||||
|
||||
std::unordered_set<int> empt;
|
||||
LOG_INFO(logger, "empt {}", empt);
|
||||
}
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " c {'a'}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " si {-12}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " i {-123}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " li {9876}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " lli {321}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " usi {15}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ui {123}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " uli {3213}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ulli {321}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " f {111.1}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " d {12.1}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " cri {-123}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ci {-123}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " sa {\"test\"}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " sva {\"string_view\"}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " scva {\"c_style\"}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " scva {\"c_style\"} sa {\"test\"} ulli {321} scva {\"c_style\"} sa {\"test\"}"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " loopv {"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " loopsv {"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " empt {}"}));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,255 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
#include "quill/std/Vector.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("std_vector_logging")
|
||||
{
|
||||
static constexpr char const* filename = "std_vector_logging.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
{
|
||||
std::vector<char> c = {'a', 'c'};
|
||||
LOG_INFO(logger, "c {}", c);
|
||||
|
||||
std::vector<short> si = {-12, 10};
|
||||
LOG_INFO(logger, "si {}", si);
|
||||
|
||||
std::vector<int> i = {-123, 1};
|
||||
LOG_INFO(logger, "i {}", i);
|
||||
|
||||
std::vector<long> li = {9876, 1232};
|
||||
LOG_INFO(logger, "li {}", li);
|
||||
|
||||
std::vector<long long> lli = {321, 231};
|
||||
LOG_INFO(logger, "lli {}", lli);
|
||||
|
||||
std::vector<unsigned short> usi = {15, 2};
|
||||
LOG_INFO(logger, "usi {}", usi);
|
||||
|
||||
std::vector<unsigned int> ui = {123, 2};
|
||||
LOG_INFO(logger, "ui {}", ui);
|
||||
|
||||
std::vector<unsigned long> uli = {3213, 2876};
|
||||
LOG_INFO(logger, "uli {}", uli);
|
||||
|
||||
std::vector<unsigned long long> ulli = {321, 1321};
|
||||
LOG_INFO(logger, "ulli {}", ulli);
|
||||
|
||||
std::vector<float> f = {111.1f, 323.31f};
|
||||
LOG_INFO(logger, "f {}", f);
|
||||
|
||||
std::vector<double> d = {12.1, 3213213.123};
|
||||
LOG_INFO(logger, "d {}", d);
|
||||
|
||||
std::vector<int> const& cri = i;
|
||||
LOG_INFO(logger, "cri {}", cri);
|
||||
|
||||
std::vector<int>& ci = i;
|
||||
LOG_INFO(logger, "ci {}", ci);
|
||||
|
||||
std::vector<std::string> sa = {"test", "string"};
|
||||
LOG_INFO(logger, "sa {}", sa);
|
||||
|
||||
std::vector<std::string_view> sva = {"test", "string_view"};
|
||||
LOG_INFO(logger, "sva {}", sva);
|
||||
|
||||
std::vector<char const*> scva = {"c style", "string test", "test", "log"};
|
||||
LOG_INFO(logger, "scva {}", scva);
|
||||
|
||||
std::vector<std::vector<int>> aai = {{{321, 123}, {444, 333}, {111, 222}}};
|
||||
LOG_INFO(logger, "aai {}", aai);
|
||||
|
||||
std::vector<std::vector<char const*>> aacs = {
|
||||
{{"one", "two"}, {"three", "four"}, {"five", "six"}}};
|
||||
LOG_INFO(logger, "aacs {}", aacs);
|
||||
|
||||
std::vector<std::vector<std::vector<char const*>>> aaacs = {
|
||||
{{{{"one", "two"}, {"three", "four"}}},
|
||||
{{{"five", "six"}, {"seven", "eight"}}},
|
||||
{{{"nine", "ten"}, {"eleven", "twelve"}}}}};
|
||||
LOG_INFO(logger, "aaacs {}", aaacs);
|
||||
|
||||
{
|
||||
std::vector<std::vector<std::vector<std::string>>> aaabcs;
|
||||
|
||||
// First outer vector
|
||||
std::vector<std::vector<std::string>> first_outer = {{"std_one", "two"}, {"three", "four"}};
|
||||
|
||||
// Second outer vector
|
||||
std::vector<std::vector<std::string>> second_outer = {{"five", "six"}, {"seven", "eight"}};
|
||||
|
||||
// Third outer vector
|
||||
std::vector<std::vector<std::string>> third_outer = {{"std_nine", "ten"},
|
||||
{"eleven", "twelve"}};
|
||||
|
||||
aaabcs.push_back(first_outer);
|
||||
aaabcs.push_back(second_outer);
|
||||
aaabcs.push_back(third_outer);
|
||||
|
||||
LOG_INFO(logger, "aaabcs {}", aaabcs);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<std::vector<std::vector<std::string>>> aaaccs;
|
||||
|
||||
// First outer vector
|
||||
std::vector<std::vector<std::string>> first_outer = {{"std_one", "two"},
|
||||
{"three_std", "four"}};
|
||||
|
||||
// Second outer vector
|
||||
std::vector<std::vector<std::string>> second_outer = {{"five", "six"}, {"seven_std", "eight"}};
|
||||
|
||||
// Third outer vector
|
||||
std::vector<std::vector<std::string>> third_outer = {{"std_nine", "ten"},
|
||||
{"eleven", "twelve"}};
|
||||
|
||||
aaaccs.push_back(first_outer);
|
||||
aaaccs.push_back(second_outer);
|
||||
aaaccs.push_back(third_outer);
|
||||
|
||||
LOG_INFO(logger, "aaaccs {}", aaaccs);
|
||||
}
|
||||
|
||||
LOG_INFO(logger, "scva {} sa {} ulli {} scva {} sa {} aaacs {} aai {}", scva, sa, ulli, scva, sa, aaacs, aai);
|
||||
|
||||
std::vector<int> loopv;
|
||||
loopv.reserve(100);
|
||||
for (int iter = 0; iter < 100; ++iter)
|
||||
{
|
||||
loopv.push_back(iter);
|
||||
}
|
||||
|
||||
LOG_INFO(logger, "loopv {}", loopv);
|
||||
|
||||
std::vector<std::string> loopsv;
|
||||
loopsv.reserve(100);
|
||||
for (int iter = 0; iter < 100; ++iter)
|
||||
{
|
||||
loopsv.push_back(std::to_string(iter));
|
||||
}
|
||||
|
||||
LOG_INFO(logger, "loopsv {}", loopsv);
|
||||
|
||||
std::vector<int> empt;
|
||||
LOG_INFO(logger, "empt {}", empt);
|
||||
}
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " c ['a', 'c']"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " si [-12, 10]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " i [-123, 1]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " li [9876, 1232]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " lli [321, 231]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " usi [15, 2]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ui [123, 2]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " uli [3213, 2876]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ulli [321, 1321]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " f [111.1, 323.31]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " d [12.1, 3213213.123]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " cri [-123, 1]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ci [-123, 1]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " sa [\"test\", \"string\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " sva [\"test\", \"string_view\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " scva [\"c style\", \"string test\", \"test\", \"log\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " aai [[321, 123], [444, 333], [111, 222]]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents,
|
||||
std::string{"LOG_INFO " + logger_name +
|
||||
" aacs [[\"one\", \"two\"], [\"three\", \"four\"], [\"five\", \"six\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " aaabcs [[[\"std_one\", \"two\"], [\"three\", \"four\"]], [[\"five\", \"six\"], [\"seven\", \"eight\"]], [[\"std_nine\", \"ten\"], [\"eleven\", \"twelve\"]]]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " aaaccs [[[\"std_one\", \"two\"], [\"three_std\", \"four\"]], [[\"five\", \"six\"], [\"seven_std\", \"eight\"]], [[\"std_nine\", \"ten\"], [\"eleven\", \"twelve\"]]]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " aaacs [[[\"one\", \"two\"], [\"three\", \"four\"]], [[\"five\", \"six\"], [\"seven\", \"eight\"]], [[\"nine\", \"ten\"], [\"eleven\", \"twelve\"]]]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " scva [\"c style\", \"string test\", \"test\", \"log\"] sa [\"test\", \"string\"] ulli [321, 1321] scva [\"c style\", \"string test\", \"test\", \"log\"] sa [\"test\", \"string\"] aaacs [[[\"one\", \"two\"], [\"three\", \"four\"]], [[\"five\", \"six\"], [\"seven\", \"eight\"]], [[\"nine\", \"ten\"], [\"eleven\", \"twelve\"]]] aai [[321, 123], [444, 333], [111, 222]]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " loopv [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " loopsv [\"0\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"10\", \"11\", \"12\", \"13\", \"14\", \"15\", \"16\", \"17\", \"18\", \"19\", \"20\", \"21\", \"22\", \"23\", \"24\", \"25\", \"26\", \"27\", \"28\", \"29\", \"30\", \"31\", \"32\", \"33\", \"34\", \"35\", \"36\", \"37\", \"38\", \"39\", \"40\", \"41\", \"42\", \"43\", \"44\", \"45\", \"46\", \"47\", \"48\", \"49\", \"50\", \"51\", \"52\", \"53\", \"54\", \"55\", \"56\", \"57\", \"58\", \"59\", \"60\", \"61\", \"62\", \"63\", \"64\", \"65\", \"66\", \"67\", \"68\", \"69\", \"70\", \"71\", \"72\", \"73\", \"74\", \"75\", \"76\", \"77\", \"78\", \"79\", \"80\", \"81\", \"82\", \"83\", \"84\", \"85\", \"86\", \"87\", \"88\", \"89\", \"90\", \"91\", \"92\", \"93\", \"94\", \"95\", \"96\", \"97\", \"98\", \"99\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " empt []"}));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("string_large_logging")
|
||||
{
|
||||
static constexpr char const* filename = "string_large_logging.log";
|
||||
static std::string const logger_name = "logger";
|
||||
static constexpr size_t number_of_messages = 100;
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
for (size_t i = 0; i < number_of_messages; ++i)
|
||||
{
|
||||
std::string v{
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor "
|
||||
"incididunt ut labore et dolore magna aliqua. Dui accumsan sit amet nulla facilisi "
|
||||
"morbi tempus. Diam ut venenatis tellus in metus vulputate eu scelerisque felis. Lorem "
|
||||
"mollis aliquam ut porttitor leo a. Posuere urna nec tincidunt praesent semper feugiat "
|
||||
"nibh sed. Auctor urna nunc id cursus metus aliquam eleifend mi. Et ultrices neque ornare "
|
||||
"aenean euismod elementum nisi quis. Phasellus vestibulum lorem sed risus ultricies "
|
||||
"tristique nulla. Porta nibh venenatis cras sed felis eget velit aliquet sagittis. "
|
||||
"Eget arcu dictum varius duis at consectetur lorem. Diam quam nulla porttitor massa id "
|
||||
"neque aliquam vestibulum morbi. Sed euismod nisi porta lorem mollis aliquam. Arcu "
|
||||
"felis bibendum ut tristique. Lorem ipsum dolor sit amet consectetur adipiscing elit "
|
||||
"pellentesque habitant. Mauris augue neque gravida in. Dictum fusce ut placerat orci "
|
||||
"nulla pellentesque dignissim "};
|
||||
|
||||
v += std::to_string(i);
|
||||
|
||||
LOG_INFO(logger, "Logging int: {}, int: {}, string: {}, string: {}", i, i * 10, v, v);
|
||||
}
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
REQUIRE_EQ(file_contents.size(), number_of_messages);
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("string_logging_dynamic_log_level")
|
||||
{
|
||||
static constexpr char const* filename = "string_logging_dynamic_log_level.log";
|
||||
static std::string const logger_name = "logger";
|
||||
static constexpr size_t number_of_messages = 10000;
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
logger->set_log_level(LogLevel::TraceL3);
|
||||
|
||||
{
|
||||
std::string s = "adipiscing";
|
||||
std::string const empty_s{};
|
||||
|
||||
std::string_view begin_s{"begin_s"};
|
||||
std::string_view const end_s{"end_s"};
|
||||
std::string_view empty_sv{};
|
||||
|
||||
char const* c_style_string_empty = "";
|
||||
const char* c_style_string = "Lorem ipsum";
|
||||
|
||||
char c_style_char_array_empty[] = "";
|
||||
char const c_style_char_array[] = "dolor";
|
||||
|
||||
char c_style_string_array_non_terminated[3];
|
||||
c_style_string_array_non_terminated[0] = 'A';
|
||||
c_style_string_array_non_terminated[1] = 'B';
|
||||
c_style_string_array_non_terminated[2] = 'C';
|
||||
|
||||
LOG_DYNAMIC(logger, LogLevel::TraceL3, "s [{}]", s);
|
||||
LOG_DYNAMIC(logger, LogLevel::TraceL2, "empty_s [{}]", empty_s);
|
||||
LOG_DYNAMIC(logger, LogLevel::TraceL1, "begin_s [{}]", begin_s);
|
||||
LOG_DYNAMIC(logger, LogLevel::Debug, "end_s [{}]", end_s);
|
||||
LOG_DYNAMIC(logger, LogLevel::Info, "empty_sv [{}]", empty_sv);
|
||||
LOG_DYNAMIC(logger, LogLevel::Warning, "c_style_string_empty [{}]", c_style_string_empty);
|
||||
LOG_DYNAMIC(logger, LogLevel::Error, "c_style_string [{}]", c_style_string);
|
||||
LOG_DYNAMIC(logger, LogLevel::Critical, "c_style_char_array_empty [{}]", c_style_char_array_empty);
|
||||
LOG_DYNAMIC(logger, LogLevel::Info, "c_style_char_array [{}]", c_style_char_array);
|
||||
LOG_DYNAMIC(logger, LogLevel::Info, "c_style_string_array_non_terminated [{}]",
|
||||
c_style_string_array_non_terminated);
|
||||
|
||||
LOG_DYNAMIC(
|
||||
logger, LogLevel::Info,
|
||||
"Lorem ipsum dolor sit amet, consectetur [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] "
|
||||
"[{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}]",
|
||||
s, "elit", 1, 3.14, empty_s, begin_s, end_s, empty_sv, c_style_string_empty, c_style_string,
|
||||
c_style_char_array_empty, c_style_char_array, c_style_string_array_non_terminated, s, "elit",
|
||||
1, 3.14, empty_s, begin_s, end_s, empty_sv, c_style_string_empty, c_style_string,
|
||||
c_style_char_array_empty, c_style_char_array, c_style_string_array_non_terminated);
|
||||
|
||||
LOG_DYNAMIC(logger, LogLevel::Error,
|
||||
"Nulla tempus, libero at dignissim viverra, lectus libero finibus ante [{}] [{}] "
|
||||
"[{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] "
|
||||
"[{}] [{}] [{}] [{}]",
|
||||
2, true, begin_s, empty_sv, empty_s, c_style_string_array_non_terminated, c_style_string_empty,
|
||||
c_style_string, end_s, c_style_char_array_empty, c_style_char_array, 2, true,
|
||||
begin_s, empty_sv, empty_s, c_style_string_array_non_terminated, c_style_string_empty,
|
||||
c_style_string, end_s, c_style_char_array_empty, c_style_char_array);
|
||||
}
|
||||
|
||||
// Log a big string
|
||||
for (size_t i = 0; i < number_of_messages; ++i)
|
||||
{
|
||||
std::string v{"Lorem ipsum dolor sit amet, consectetur "};
|
||||
v += std::to_string(i);
|
||||
|
||||
LOG_DYNAMIC(logger, LogLevel::Info, "Logging int: {}, int: {}, string: {}, char: {}", i, i * 10,
|
||||
v, v.c_str());
|
||||
}
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
REQUIRE_EQ(file_contents.size(), number_of_messages + 12);
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_TRACE_L3 " + logger_name + " s [adipiscing]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_TRACE_L2 " + logger_name + " empty_s []"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_TRACE_L1 " + logger_name + " begin_s [begin_s]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_DEBUG " + logger_name + " end_s [end_s]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " empty_sv []"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_WARNING " + logger_name + " c_style_string_empty []"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_ERROR " + logger_name + " c_style_string [Lorem ipsum]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_CRITICAL " + logger_name + " c_style_char_array_empty []"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " c_style_char_array [dolor]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " c_style_string_array_non_terminated [ABC]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " Lorem ipsum dolor sit amet, consectetur [adipiscing] [elit] [1] [3.14] [] [begin_s] [end_s] [] [] [Lorem ipsum] [] [dolor] [ABC] [adipiscing] [elit] [1] [3.14] [] [begin_s] [end_s] [] [] [Lorem ipsum] [] [dolor] [ABC]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_ERROR " + logger_name + " Nulla tempus, libero at dignissim viverra, lectus libero finibus ante [2] [true] [begin_s] [] [] [ABC] [] [Lorem ipsum] [end_s] [] [dolor] [2] [true] [begin_s] [] [] [ABC] [] [Lorem ipsum] [end_s] [] [dolor]"}));
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " Logging int: 0, int: 0, string: Lorem ipsum dolor sit amet, consectetur 0, char: Lorem ipsum dolor sit amet, consectetur 0"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " Logging int: 1999, int: 19990, string: Lorem ipsum dolor sit amet, consectetur 1999, char: Lorem ipsum dolor sit amet, consectetur 1999"}));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("string_logging")
|
||||
{
|
||||
static constexpr char const* filename = "string_logging.log";
|
||||
static std::string const logger_name = "logger";
|
||||
static constexpr size_t number_of_messages = 10000;
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
{
|
||||
std::string s = "adipiscing";
|
||||
std::string const& scr = s;
|
||||
std::string& sr = s;
|
||||
std::string const empty_s{};
|
||||
|
||||
std::string_view begin_s{"begin_s"};
|
||||
std::string_view const end_s{"end_s"};
|
||||
std::string_view empty_sv{};
|
||||
|
||||
char const* c_style_string_empty = "";
|
||||
const char* c_style_string = "Lorem ipsum";
|
||||
|
||||
char c_style_char_array_empty[] = "";
|
||||
char const c_style_char_array[] = "dolor";
|
||||
|
||||
char c_style_string_array_non_terminated[3];
|
||||
c_style_string_array_non_terminated[0] = 'A';
|
||||
c_style_string_array_non_terminated[1] = 'B';
|
||||
c_style_string_array_non_terminated[2] = 'C';
|
||||
|
||||
LOG_INFO(logger, "s [{}]", s);
|
||||
LOG_INFO(logger, "scr [{}]", scr);
|
||||
LOG_INFO(logger, "sr [{}]", sr);
|
||||
LOG_INFO(logger, "empty_s [{}]", empty_s);
|
||||
LOG_INFO(logger, "begin_s [{}]", begin_s);
|
||||
LOG_INFO(logger, "end_s [{}]", end_s);
|
||||
LOG_INFO(logger, "empty_sv [{}]", empty_sv);
|
||||
LOG_INFO(logger, "c_style_string_empty [{}]", c_style_string_empty);
|
||||
LOG_INFO(logger, "c_style_string [{}]", c_style_string);
|
||||
LOG_INFO(logger, "c_style_char_array_empty [{}]", c_style_char_array_empty);
|
||||
LOG_INFO(logger, "c_style_char_array [{}]", c_style_char_array);
|
||||
LOG_INFO(logger, "c_style_string_array_non_terminated [{}]", c_style_string_array_non_terminated);
|
||||
|
||||
LOG_INFO(logger,
|
||||
"Lorem ipsum dolor sit amet, consectetur [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] "
|
||||
"[{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}]",
|
||||
s, "elit", 1, 3.14, empty_s, begin_s, end_s, empty_sv, c_style_string_empty, c_style_string,
|
||||
c_style_char_array_empty, c_style_char_array, c_style_string_array_non_terminated, s,
|
||||
"elit", 1, 3.14, empty_s, begin_s, end_s, empty_sv, c_style_string_empty, c_style_string,
|
||||
c_style_char_array_empty, c_style_char_array, c_style_string_array_non_terminated);
|
||||
|
||||
LOG_ERROR(logger,
|
||||
"Nulla tempus, libero at dignissim viverra, lectus libero finibus ante [{}] [{}] "
|
||||
"[{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] "
|
||||
"[{}] [{}] [{}] [{}]",
|
||||
2, true, begin_s, empty_sv, empty_s, c_style_string_array_non_terminated, c_style_string_empty,
|
||||
c_style_string, end_s, c_style_char_array_empty, c_style_char_array, 2, true, begin_s,
|
||||
empty_sv, empty_s, c_style_string_array_non_terminated, c_style_string_empty,
|
||||
c_style_string, end_s, c_style_char_array_empty, c_style_char_array);
|
||||
}
|
||||
|
||||
// Log a big string
|
||||
for (size_t i = 0; i < number_of_messages; ++i)
|
||||
{
|
||||
std::string v{"Lorem ipsum dolor sit amet, consectetur "};
|
||||
v += std::to_string(i);
|
||||
|
||||
LOG_INFO(logger, "Logging int: {}, int: {}, string: {}, char: {}", i, i * 10, v, v.c_str());
|
||||
}
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
REQUIRE_EQ(file_contents.size(), number_of_messages + 14);
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " s [adipiscing]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " scr [adipiscing]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " sr [adipiscing]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " empty_s []"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " begin_s [begin_s]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " end_s [end_s]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " empty_sv []"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " c_style_string_empty []"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " c_style_string [Lorem ipsum]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " c_style_char_array_empty []"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " c_style_char_array [dolor]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " c_style_string_array_non_terminated [ABC]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " Lorem ipsum dolor sit amet, consectetur [adipiscing] [elit] [1] [3.14] [] [begin_s] [end_s] [] [] [Lorem ipsum] [] [dolor] [ABC] [adipiscing] [elit] [1] [3.14] [] [begin_s] [end_s] [] [] [Lorem ipsum] [] [dolor] [ABC]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_ERROR " + logger_name + " Nulla tempus, libero at dignissim viverra, lectus libero finibus ante [2] [true] [begin_s] [] [] [ABC] [] [Lorem ipsum] [end_s] [] [dolor] [2] [true] [begin_s] [] [] [ABC] [] [Lorem ipsum] [end_s] [] [dolor]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " Logging int: 0, int: 0, string: Lorem ipsum dolor sit amet, consectetur 0, char: Lorem ipsum dolor sit amet, consectetur 0"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " Logging int: 1999, int: 19990, string: Lorem ipsum dolor sit amet, consectetur 1999, char: Lorem ipsum dolor sit amet, consectetur 1999"}));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("string_random_large_logging")
|
||||
{
|
||||
static constexpr char const* filename = "string_random_large_logging.log";
|
||||
static std::string const logger_name = "logger";
|
||||
static constexpr size_t number_of_strings = 500;
|
||||
static constexpr int min_string_len = 10000;
|
||||
static constexpr int max_string_len = 20000;
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
std::vector<std::string> random_strings_vec =
|
||||
quill::testing::gen_random_strings(number_of_strings, min_string_len, max_string_len);
|
||||
|
||||
// First push in sequence
|
||||
int32_t i = 0;
|
||||
for (auto const& elem : random_strings_vec)
|
||||
{
|
||||
LOG_INFO(logger, "{}", elem);
|
||||
LOG_INFO(logger, "{}", elem.c_str());
|
||||
LOG_INFO(logger, "{}", std::string_view{elem});
|
||||
LOG_INFO(logger, "{} {}", i, static_cast<double>(i));
|
||||
++i;
|
||||
logger->flush_log();
|
||||
}
|
||||
|
||||
for (auto const& elem : random_strings_vec)
|
||||
{
|
||||
LOG_INFO(logger, "{}", elem);
|
||||
LOG_INFO(logger, "{} {}", i, static_cast<double>(i));
|
||||
++i;
|
||||
logger->flush_log();
|
||||
}
|
||||
|
||||
for (auto const& elem : random_strings_vec)
|
||||
{
|
||||
LOG_INFO(logger, "{}", elem.c_str());
|
||||
LOG_INFO(logger, "{} {}", i, static_cast<double>(i));
|
||||
++i;
|
||||
logger->flush_log();
|
||||
}
|
||||
|
||||
for (auto const& elem : random_strings_vec)
|
||||
{
|
||||
LOG_INFO(logger, "{}", std::string_view{elem});
|
||||
LOG_INFO(logger, "{} {}", i, static_cast<double>(i));
|
||||
++i;
|
||||
logger->flush_log();
|
||||
}
|
||||
|
||||
// Then also try to push all
|
||||
for (auto const& elem : random_strings_vec)
|
||||
{
|
||||
LOG_INFO(logger, "{}", elem);
|
||||
LOG_INFO(logger, "{}", elem.c_str());
|
||||
LOG_INFO(logger, "{}", std::string_view{elem});
|
||||
LOG_INFO(logger, "{} {}", i, static_cast<double>(i));
|
||||
++i;
|
||||
}
|
||||
|
||||
// clear the vector for the strings to go out of scope for additional testing
|
||||
size_t const total_log_messages = random_strings_vec.size() * 14;
|
||||
random_strings_vec.clear();
|
||||
|
||||
// Let all log get flushed to the file
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check we logged everything
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
REQUIRE_EQ(file_contents.size(), total_log_messages);
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("string_random_logging")
|
||||
{
|
||||
static constexpr char const* filename = "string_random_logging.log";
|
||||
static std::string const logger_name = "logger";
|
||||
static constexpr size_t number_of_strings = 2000;
|
||||
static constexpr int min_string_len = 1;
|
||||
static constexpr int max_string_len = 1500;
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
std::vector<std::string> random_strings_vec =
|
||||
quill::testing::gen_random_strings(number_of_strings, min_string_len, max_string_len);
|
||||
|
||||
// First push in sequence
|
||||
for (auto const& elem : random_strings_vec)
|
||||
{
|
||||
LOG_INFO(logger, "{}", elem);
|
||||
LOG_INFO(logger, "{}", elem.c_str());
|
||||
LOG_INFO(logger, "{}", std::string_view{elem});
|
||||
logger->flush_log();
|
||||
}
|
||||
|
||||
for (auto const& elem : random_strings_vec)
|
||||
{
|
||||
LOG_INFO(logger, "{}", elem);
|
||||
logger->flush_log();
|
||||
}
|
||||
|
||||
for (auto const& elem : random_strings_vec)
|
||||
{
|
||||
LOG_INFO(logger, "{}", elem.c_str());
|
||||
logger->flush_log();
|
||||
}
|
||||
|
||||
for (auto const& elem : random_strings_vec)
|
||||
{
|
||||
LOG_INFO(logger, "{}", std::string_view{elem});
|
||||
logger->flush_log();
|
||||
}
|
||||
|
||||
// Then also try to push all
|
||||
for (auto const& elem : random_strings_vec)
|
||||
{
|
||||
LOG_INFO(logger, "{}", elem);
|
||||
LOG_INFO(logger, "{}", elem.c_str());
|
||||
LOG_INFO(logger, "{}", std::string_view{elem});
|
||||
}
|
||||
|
||||
// clear the vector for the strings to go out of scope for additional testing
|
||||
size_t const total_log_messages = random_strings_vec.size() * 9;
|
||||
random_strings_vec.clear();
|
||||
|
||||
// Let all log get flushed to the file
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check we logged everything
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
REQUIRE_EQ(file_contents.size(), total_log_messages);
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("string_random_small_logging")
|
||||
{
|
||||
static constexpr char const* filename = "string_random_small_logging.log";
|
||||
static std::string const logger_name = "logger";
|
||||
static constexpr size_t number_of_strings = 500;
|
||||
static constexpr int min_string_len = 1;
|
||||
static constexpr int max_string_len = 50;
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
std::vector<std::string> random_strings_vec =
|
||||
quill::testing::gen_random_strings(number_of_strings, min_string_len, max_string_len);
|
||||
|
||||
// First push in sequence
|
||||
for (auto const& elem : random_strings_vec)
|
||||
{
|
||||
LOG_INFO(logger, "{}", elem);
|
||||
LOG_INFO(logger, "{}", elem.c_str());
|
||||
LOG_INFO(logger, "{}", std::string_view{elem});
|
||||
logger->flush_log();
|
||||
}
|
||||
|
||||
for (auto const& elem : random_strings_vec)
|
||||
{
|
||||
LOG_INFO(logger, "{}", elem);
|
||||
logger->flush_log();
|
||||
}
|
||||
|
||||
for (auto const& elem : random_strings_vec)
|
||||
{
|
||||
LOG_INFO(logger, "{}", elem.c_str());
|
||||
logger->flush_log();
|
||||
}
|
||||
|
||||
for (auto const& elem : random_strings_vec)
|
||||
{
|
||||
LOG_INFO(logger, "{}", std::string_view{elem});
|
||||
logger->flush_log();
|
||||
}
|
||||
|
||||
// Then also try to push all
|
||||
for (auto const& elem : random_strings_vec)
|
||||
{
|
||||
LOG_INFO(logger, "{}", elem);
|
||||
LOG_INFO(logger, "{}", elem.c_str());
|
||||
LOG_INFO(logger, "{}", std::string_view{elem});
|
||||
}
|
||||
|
||||
// clear the vector for the strings to go out of scope for additional testing
|
||||
size_t const total_log_messages = random_strings_vec.size() * 9;
|
||||
random_strings_vec.clear();
|
||||
|
||||
// Let all log get flushed to the file
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check we logged everything
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
REQUIRE_EQ(file_contents.size(), total_log_messages);
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/Utility.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
class TestTags : public quill::Tags
|
||||
{
|
||||
public:
|
||||
explicit constexpr TestTags(char const* tag_a) : _tag_a(tag_a) {}
|
||||
|
||||
void format(std::string& out) const override { out.append(fmtquill::format("{}", _tag_a)); }
|
||||
|
||||
private:
|
||||
char const* _tag_a;
|
||||
};
|
||||
|
||||
static constexpr TestTags tags_a{"TAG_A"};
|
||||
static constexpr TestTags tags_b{"TAG_B"};
|
||||
|
||||
static constexpr quill::utility::CombinedTags<TestTags, TestTags> tags_ab{tags_a, tags_b, " -- "};
|
||||
|
||||
/***/
|
||||
TEST_CASE("tags_logging")
|
||||
{
|
||||
static constexpr char const* filename = "tags_logging.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(
|
||||
logger_name, std::move(file_sink),
|
||||
"%(time) [%(thread_id)] %(short_source_location:<28) LOG_%(log_level:<9) "
|
||||
"%(logger:<12) [%(tags)] %(message)\"");
|
||||
|
||||
logger->set_log_level(quill::LogLevel::TraceL3);
|
||||
|
||||
LOG_TRACE_L3_WITH_TAGS(logger, tags_ab, "Lorem ipsum dolor sit amet, consectetur {} {} {}", "elit", 1, 3.14);
|
||||
LOG_TRACE_L2_WITH_TAGS(logger, tags_ab, "Lorem ipsum dolor sit amet, consectetur {} {} {}", "elit", 1, 3.14);
|
||||
LOG_TRACE_L1_WITH_TAGS(logger, tags_ab, "Lorem ipsum dolor sit amet, consectetur {} {} {}", "elit", 1, 3.14);
|
||||
LOG_DEBUG_WITH_TAGS(logger, tags_ab, "Lorem ipsum dolor sit amet, consectetur {} {} {}", "elit", 1, 3.14);
|
||||
LOG_INFO_WITH_TAGS(logger, tags_ab, "Lorem ipsum dolor sit amet, consectetur {} {} {}", "elit", 1, 3.14);
|
||||
LOG_WARNING_WITH_TAGS(logger, tags_ab, "Lorem ipsum dolor sit amet, consectetur {} {} {}", "elit", 1, 3.14);
|
||||
LOG_ERROR_WITH_TAGS(logger, tags_ab, "Lorem ipsum dolor sit amet, consectetur {} {} {}", "elit", 1, 3.14);
|
||||
LOG_CRITICAL_WITH_TAGS(logger, tags_ab, "Lorem ipsum dolor sit amet, consectetur {} {} {}", "elit", 1, 3.14);
|
||||
|
||||
LOG_ERROR_WITH_TAGS(
|
||||
logger, tags_ab, "Nulla tempus, libero at dignissim viverra, lectus libero finibus ante {} {}", 2, true);
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
REQUIRE_EQ(file_contents.size(), 9);
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents,
|
||||
std::string{"LOG_TRACE_L3 " + logger_name +
|
||||
" [TAG_A -- TAG_B] Lorem ipsum dolor sit amet, consectetur elit 1 3.14"}));
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents,
|
||||
std::string{"LOG_TRACE_L2 " + logger_name +
|
||||
" [TAG_A -- TAG_B] Lorem ipsum dolor sit amet, consectetur elit 1 3.14"}));
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents,
|
||||
std::string{"LOG_TRACE_L1 " + logger_name +
|
||||
" [TAG_A -- TAG_B] Lorem ipsum dolor sit amet, consectetur elit 1 3.14"}));
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents,
|
||||
std::string{"LOG_DEBUG " + logger_name +
|
||||
" [TAG_A -- TAG_B] Lorem ipsum dolor sit amet, consectetur elit 1 3.14"}));
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents,
|
||||
std::string{"LOG_INFO " + logger_name +
|
||||
" [TAG_A -- TAG_B] Lorem ipsum dolor sit amet, consectetur elit 1 3.14"}));
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents,
|
||||
std::string{"LOG_WARNING " + logger_name +
|
||||
" [TAG_A -- TAG_B] Lorem ipsum dolor sit amet, consectetur elit 1 3.14"}));
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents,
|
||||
std::string{"LOG_ERROR " + logger_name +
|
||||
" [TAG_A -- TAG_B] Lorem ipsum dolor sit amet, consectetur elit 1 3.14"}));
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents,
|
||||
std::string{"LOG_CRITICAL " + logger_name +
|
||||
" [TAG_A -- TAG_B] Lorem ipsum dolor sit amet, consectetur elit 1 3.14"}));
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_ERROR " + logger_name + " [TAG_A -- TAG_B] Nulla tempus, libero at dignissim viverra, lectus libero finibus ante 2 true"}));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/**
|
||||
* Custom timestamp class
|
||||
*/
|
||||
class UserClockSourceTest : public UserClockSource
|
||||
{
|
||||
public:
|
||||
UserClockSourceTest() = default;
|
||||
|
||||
/**
|
||||
* Required by TimestampClock
|
||||
* @return current time now, in nanoseconds since epoch
|
||||
*/
|
||||
uint64_t now() const override { return _ts.load(); }
|
||||
|
||||
/**
|
||||
* set custom timestamp
|
||||
* @param time_since_epoch timestamp
|
||||
*/
|
||||
void set_timestamp(std::chrono::seconds time_since_epoch)
|
||||
{
|
||||
// always convert to nanos
|
||||
_ts.store(static_cast<uint64_t>(std::chrono::nanoseconds{time_since_epoch}.count()));
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* time since epoch - must always be in nanoseconds
|
||||
* This class needs to be thread-safe, unless only a single thread in the application calling LOG macros
|
||||
* **/
|
||||
std::atomic<uint64_t> _ts;
|
||||
};
|
||||
|
||||
/***/
|
||||
TEST_CASE("user_clock_source")
|
||||
{
|
||||
static constexpr size_t number_of_messages = 10;
|
||||
static constexpr char const* filename = "user_clock_source.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
UserClockSourceTest uct;
|
||||
uct.set_timestamp(std::chrono::seconds{1655007309});
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink),
|
||||
"%(time) %(log_level) %(logger:<16) %(message)", // format
|
||||
"%Y-%m-%d %H:%M:%S.%Qms", // timestamp format
|
||||
quill::Timezone::GmtTime, ClockSourceType::User, &uct);
|
||||
|
||||
for (size_t i = 0; i < number_of_messages; ++i)
|
||||
{
|
||||
// log an array so the log message is pushed to the queue
|
||||
LOG_INFO(logger, "Lorem ipsum dolor sit amet, consectetur adipiscing elit {}", i);
|
||||
}
|
||||
|
||||
uct.set_timestamp(std::chrono::seconds{1656007309});
|
||||
|
||||
for (size_t i = 0; i < number_of_messages; ++i)
|
||||
{
|
||||
LOG_ERROR(logger, "Nulla tempus, libero at dignissim viverra, lectus libero finibus ante {}", i);
|
||||
}
|
||||
|
||||
// Let all log get flushed to the file
|
||||
uct.set_timestamp(std::chrono::seconds{1658007309});
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
REQUIRE_EQ(file_contents.size(), number_of_messages * 2);
|
||||
|
||||
for (size_t i = 0; i < number_of_messages; ++i)
|
||||
{
|
||||
std::string expected_string = "2022-06-12 04:15:09.000 INFO " + logger_name +
|
||||
" Lorem ipsum dolor sit amet, consectetur adipiscing elit " + std::to_string(i);
|
||||
REQUIRE(quill::testing::file_contains(file_contents, expected_string));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < number_of_messages; ++i)
|
||||
{
|
||||
std::string expected_string = "2022-06-23 18:01:49.000 ERROR " + logger_name +
|
||||
" Nulla tempus, libero at dignissim viverra, lectus libero finibus ante " +
|
||||
std::to_string(i);
|
||||
REQUIRE(quill::testing::file_contains(file_contents, expected_string));
|
||||
}
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/Utility.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include "quill/core/Codec.h"
|
||||
#include "quill/core/DynamicFormatArgStore.h"
|
||||
#include "quill/std/Array.h"
|
||||
#include "quill/std/Vector.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/**
|
||||
* CustomType defined type
|
||||
*/
|
||||
struct CustomType
|
||||
{
|
||||
std::string name;
|
||||
std::string surname;
|
||||
uint32_t age;
|
||||
std::array<std::string, 3> favorite_colors;
|
||||
};
|
||||
|
||||
/***/
|
||||
template <>
|
||||
struct fmtquill::formatter<CustomType>
|
||||
{
|
||||
template <typename FormatContext>
|
||||
constexpr auto parse(FormatContext& ctx)
|
||||
{
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(::CustomType const& custom_type, FormatContext& ctx) const
|
||||
{
|
||||
return fmtquill::format_to(ctx.out(), "Name: {}, Surname: {}, Age: {}, Favorite Colors: {}",
|
||||
custom_type.name, custom_type.surname, custom_type.age,
|
||||
custom_type.favorite_colors);
|
||||
}
|
||||
};
|
||||
|
||||
/***/
|
||||
template <>
|
||||
struct quill::detail::ArgSizeCalculator<CustomType>
|
||||
{
|
||||
static size_t calculate(std::vector<size_t>& conditional_arg_size_cache, ::CustomType const& custom_type) noexcept
|
||||
{
|
||||
// pass as arguments the class members you want to serialize
|
||||
return calculate_total_size(conditional_arg_size_cache, custom_type.name, custom_type.surname,
|
||||
custom_type.age, custom_type.favorite_colors);
|
||||
}
|
||||
};
|
||||
|
||||
/***/
|
||||
template <>
|
||||
struct quill::detail::Encoder<CustomType>
|
||||
{
|
||||
static void encode(std::byte*& buffer, std::vector<size_t> const& conditional_arg_size_cache,
|
||||
uint32_t& conditional_arg_size_cache_index, ::CustomType const& custom_type) noexcept
|
||||
{
|
||||
// You must encode the same members and in the same order as in the ArgSizeCalculator::calculate
|
||||
encode_members(buffer, conditional_arg_size_cache, conditional_arg_size_cache_index,
|
||||
custom_type.name, custom_type.surname, custom_type.age, custom_type.favorite_colors);
|
||||
}
|
||||
};
|
||||
|
||||
/***/
|
||||
template <>
|
||||
struct quill::detail::Decoder<CustomType>
|
||||
{
|
||||
static ::CustomType decode(std::byte*& buffer, DynamicFormatArgStore* args_store)
|
||||
{
|
||||
// You must decode the same members and in the same order as in the Encoder::encode
|
||||
::CustomType custom_type;
|
||||
decode_and_assign_members(buffer, args_store, custom_type, custom_type.name,
|
||||
custom_type.surname, custom_type.age, custom_type.favorite_colors);
|
||||
return custom_type;
|
||||
}
|
||||
};
|
||||
|
||||
/***/
|
||||
TEST_CASE("custom_type_defined_type_logging")
|
||||
{
|
||||
static constexpr char const* filename = "custom_type_defined_type_logging.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(
|
||||
logger_name, std::move(file_sink),
|
||||
"%(time) [%(thread_id)] %(short_source_location:<28) LOG_%(log_level:<9) "
|
||||
"%(logger:<12) %(message)");
|
||||
|
||||
logger->set_log_level(quill::LogLevel::TraceL3);
|
||||
|
||||
CustomType custom_type;
|
||||
custom_type.name = "Quill";
|
||||
custom_type.surname = "Library";
|
||||
custom_type.age = 4;
|
||||
custom_type.favorite_colors[0] = "red";
|
||||
custom_type.favorite_colors[1] = "green";
|
||||
custom_type.favorite_colors[2] = "blue";
|
||||
|
||||
LOG_INFO(logger, "The answer is {}", custom_type);
|
||||
|
||||
std::vector<CustomType> const custom_types = {{"Alice", "Doe", 25, {"red", "green"}},
|
||||
{"Bob", "Smith", 30, {"blue", "yellow"}},
|
||||
{"Charlie", "Johnson", 35, {"green", "orange"}},
|
||||
{"David", "Brown", 40, {"red", "blue", "yellow"}}};
|
||||
|
||||
LOG_INFO(logger, "The answers are {}", custom_types);
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
REQUIRE_EQ(file_contents.size(), 2);
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " The answer is Name: Quill, Surname: Library, Age: 4, Favorite Colors: [\"red\", \"green\", \"blue\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " The answers are [Name: Alice, Surname: Doe, Age: 25, Favorite Colors: [\"red\", \"green\", \"\"], Name: Bob, Surname: Smith, Age: 30, Favorite Colors: [\"blue\", \"yellow\", \"\"], Name: Charlie, Surname: Johnson, Age: 35, Favorite Colors: [\"green\", \"orange\", \"\"], Name: David, Surname: Brown, Age: 40, Favorite Colors: [\"red\", \"blue\", \"yellow\"]]"}));
|
||||
|
||||
testing::remove_file(filename);
|
||||
}
|
|
@ -0,0 +1,330 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/core/Filesystem.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include "quill/std/Array.h"
|
||||
#include "quill/std/Deque.h"
|
||||
#include "quill/std/FilesystemPath.h"
|
||||
#include "quill/std/ForwardList.h"
|
||||
#include "quill/std/List.h"
|
||||
#include "quill/std/Map.h"
|
||||
#include "quill/std/Optional.h"
|
||||
#include "quill/std/Pair.h"
|
||||
#include "quill/std/Set.h"
|
||||
#include "quill/std/UnorderedMap.h"
|
||||
#include "quill/std/UnorderedSet.h"
|
||||
#include "quill/std/Vector.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstdio>
|
||||
#include <deque>
|
||||
#include <forward_list>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
struct CWideStringComparator
|
||||
{
|
||||
bool operator()(wchar_t const* a, wchar_t const* b) const { return std::wcscmp(a, b) < 0; }
|
||||
};
|
||||
|
||||
/***/
|
||||
TEST_CASE("wide_std_types_logging")
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
static constexpr char const* filename = "wide_std_types_logging.log";
|
||||
static std::string const logger_name = "logger";
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
{
|
||||
fs::path wp{L"C:\\some\\path"};
|
||||
LOG_INFO(logger, "wp {}", wp);
|
||||
|
||||
fs::path p{"C:\\another\\path"};
|
||||
LOG_INFO(logger, "p {}", p);
|
||||
|
||||
LOG_INFO(logger, "wp {} p {}", wp, p);
|
||||
|
||||
std::array<std::wstring, 2> wsa = {L"test", L"string"};
|
||||
LOG_INFO(logger, "wsa {}", wsa);
|
||||
|
||||
std::array<std::wstring_view, 2> wsva = {L"test", L"string_view"};
|
||||
LOG_INFO(logger, "wsva {}", wsva);
|
||||
|
||||
std::array<wchar_t const*, 4> wscva = {L"c style", L"string test", L"test", L"log"};
|
||||
LOG_INFO(logger, "wscva {}", wscva);
|
||||
|
||||
std::deque<std::wstring> wds = {L"test", L"string"};
|
||||
LOG_INFO(logger, "wds {}", wds);
|
||||
|
||||
std::deque<std::wstring_view> wdsv = {L"test", L"string_view"};
|
||||
LOG_INFO(logger, "wdsv {}", wdsv);
|
||||
|
||||
std::deque<wchar_t const*> wdcs = {L"c style", L"string test", L"test", L"log"};
|
||||
LOG_INFO(logger, "wdcs {}", wdcs);
|
||||
|
||||
std::forward_list<std::wstring> wfs = {L"test", L"string"};
|
||||
LOG_INFO(logger, "wfs {}", wfs);
|
||||
|
||||
std::forward_list<std::wstring_view> wfsv = {L"test", L"string_view"};
|
||||
LOG_INFO(logger, "wfsv {}", wfsv);
|
||||
|
||||
std::forward_list<wchar_t const*> wfcs = {L"c style", L"string test", L"test", L"log"};
|
||||
LOG_INFO(logger, "wfcs {}", wfcs);
|
||||
|
||||
std::list<std::wstring> sl = {L"test", L"string"};
|
||||
LOG_INFO(logger, "sl {}", sl);
|
||||
|
||||
std::list<std::wstring_view> svl = {L"test", L"string_view"};
|
||||
LOG_INFO(logger, "svl {}", svl);
|
||||
|
||||
std::list<wchar_t const*> scl = {L"c style", L"string test", L"test", L"log"};
|
||||
LOG_INFO(logger, "scl {}", scl);
|
||||
|
||||
std::vector<std::wstring> wsv = {L"test", L"string"};
|
||||
LOG_INFO(logger, "wsv {}", wsv);
|
||||
|
||||
std::vector<std::wstring_view> wsvv = {L"test", L"string_view"};
|
||||
LOG_INFO(logger, "wsvv {}", wsvv);
|
||||
|
||||
std::vector<wchar_t const*> wscv = {L"c style", L"string test", L"test", L"log"};
|
||||
LOG_INFO(logger, "wscv {}", wscv);
|
||||
|
||||
std::pair<std::wstring, std::wstring> wpss = {L"test", L"string"};
|
||||
LOG_INFO(logger, "wpss {}", wpss);
|
||||
|
||||
std::pair<std::wstring_view, std::wstring> wpsv = {L"test", L"string_view"};
|
||||
LOG_INFO(logger, "wpsv {}", wpsv);
|
||||
|
||||
std::pair<wchar_t const*, std::wstring> wscs = {L"c style", L"string test"};
|
||||
LOG_INFO(logger, "wscs {}", wscs);
|
||||
|
||||
std::pair<int, std::wstring> wscsi = {1231, L"string test"};
|
||||
LOG_INFO(logger, "wscsi {}", wscsi);
|
||||
|
||||
std::pair<std::wstring, double> wscsd = {L"string test", 443.2};
|
||||
LOG_INFO(logger, "wscsd {}", wscsd);
|
||||
|
||||
std::optional<std::wstring> weo{std::nullopt};
|
||||
LOG_INFO(logger, "eo {}", weo);
|
||||
|
||||
std::optional<std::wstring> wos{L"test"};
|
||||
LOG_INFO(logger, "wos {}", wos);
|
||||
|
||||
std::optional<std::wstring_view> wosv{L"test"};
|
||||
LOG_INFO(logger, "wosv {}", wosv);
|
||||
|
||||
std::optional<wchar_t const*> woc{L"test"};
|
||||
LOG_INFO(logger, "woc {}", woc);
|
||||
|
||||
std::set<std::wstring> sa = {L"test", L"string"};
|
||||
LOG_INFO(logger, "sa {}", sa);
|
||||
|
||||
std::set<std::wstring> sva = {L"test", L"string_view"};
|
||||
LOG_INFO(logger, "sva {}", sva);
|
||||
|
||||
std::set<wchar_t const*, CWideStringComparator> scva = {L"c_style", L"aa", L"string_test",
|
||||
L"test", L"log"};
|
||||
LOG_INFO(logger, "scva {}", scva);
|
||||
|
||||
std::map<std::wstring, std::wstring> ccm = {{L"4", L"400"}, {L"3", L"300"}, {L"1", L"100"}};
|
||||
LOG_INFO(logger, "ccm {}", ccm);
|
||||
|
||||
std::map<std::wstring, int> ccmx = {{L"4", 400}, {L"3", 300}, {L"1", 100}};
|
||||
LOG_INFO(logger, "ccmx {}", ccmx);
|
||||
|
||||
std::map<wchar_t const*, std::wstring, CWideStringComparator> ccmc = {
|
||||
{L"4", L"400"}, {L"3", L"300"}, {L"1", L"100"}};
|
||||
LOG_INFO(logger, "ccmc {}", ccmc);
|
||||
|
||||
std::map<int, std::wstring> ccmi = {{4, L"400"}, {3, L"300"}, {1, L"100"}};
|
||||
LOG_INFO(logger, "ccmi {}", ccmi);
|
||||
|
||||
std::unordered_set<std::wstring> uss = {L"test"};
|
||||
LOG_INFO(logger, "uss {}", uss);
|
||||
|
||||
std::unordered_set<std::wstring_view> usvs = {L"string_view"};
|
||||
LOG_INFO(logger, "usvs {}", usvs);
|
||||
|
||||
std::unordered_set<wchar_t const*> uscs = {L"c_style"};
|
||||
LOG_INFO(logger, "uscs {}", uscs);
|
||||
|
||||
std::unordered_map<std::wstring, std::wstring> uccm = {{L"4", L"400"}};
|
||||
LOG_INFO(logger, "uccm {}", uccm);
|
||||
|
||||
std::unordered_map<std::wstring, int> uccmx = {{L"5", 500}};
|
||||
LOG_INFO(logger, "uccmx {}", uccmx);
|
||||
|
||||
std::unordered_map<wchar_t const*, std::wstring> uccmc = {{L"6", L"600"}};
|
||||
LOG_INFO(logger, "uccmc {}", uccmc);
|
||||
|
||||
std::unordered_map<int, std::wstring> uccmi = {{7, L"700"}};
|
||||
LOG_INFO(logger, "uccmi {}", uccmi);
|
||||
}
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " wp C:\\some\\path"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " p C:\\another\\path"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " wp C:\\some\\path p C:\\another\\path"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " wsa [\"test\", \"string\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " wsva [\"test\", \"string_view\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " wscva [\"c style\", \"string test\", \"test\", \"log\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " wds [\"test\", \"string\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " wdsv [\"test\", \"string_view\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " wdcs [\"c style\", \"string test\", \"test\", \"log\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " wfs [\"test\", \"string\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " wfsv [\"test\", \"string_view\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " wfcs [\"c style\", \"string test\", \"test\", \"log\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " sl [\"test\", \"string\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " svl [\"test\", \"string_view\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " scl [\"c style\", \"string test\", \"test\", \"log\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " wsv [\"test\", \"string\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " wsvv [\"test\", \"string_view\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " wscv [\"c style\", \"string test\", \"test\", \"log\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " wpss (\"test\", \"string\")"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " wpsv (\"test\", \"string_view\")"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " wscs (\"c style\", \"string test\")"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " wscsi (1231, \"string test\")"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " wscsd (\"string test\", 443.2)"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " eo none"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " wos optional(\"test\")"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " wosv optional(\"test\")"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " woc optional(\"test\")"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " sa [\"string\", \"test\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " sva [\"string_view\", \"test\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents,
|
||||
std::string{"LOG_INFO " + logger_name +
|
||||
" scva [\"aa\", \"c_style\", \"log\", \"string_test\", \"test\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ccm [(\"1\", \"100\"), (\"3\", \"300\"), (\"4\", \"400\")]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ccmx [(\"1\", 100), (\"3\", 300), (\"4\", 400)]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ccmc [(\"1\", \"100\"), (\"3\", \"300\"), (\"4\", \"400\")]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ccmi [(1, \"100\"), (3, \"300\"), (4, \"400\")]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " uss [\"test\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " usvs [\"string_view\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " uscs [\"c_style\"]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " uccm [(\"4\", \"400\")]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " uccmx [(\"5\", 500)]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " uccmc [(\"6\", \"600\")]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " uccmi [(7, \"700\")]"}));
|
||||
|
||||
testing::remove_file(filename);
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
#include "doctest/doctest.h"
|
||||
|
||||
#include "misc/TestUtilities.h"
|
||||
#include "quill/Backend.h"
|
||||
#include "quill/Frontend.h"
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
using namespace quill;
|
||||
|
||||
/***/
|
||||
TEST_CASE("wide_string_logging")
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
static constexpr char const* filename = "wide_string_logging.log";
|
||||
static std::string const logger_name = "logger";
|
||||
static constexpr size_t number_of_messages = 10000;
|
||||
|
||||
// Start the logging backend thread
|
||||
Backend::start();
|
||||
|
||||
Frontend::preallocate();
|
||||
|
||||
// Set writing logging to a file
|
||||
auto file_sink = Frontend::create_or_get_sink<FileSink>(
|
||||
filename,
|
||||
[]()
|
||||
{
|
||||
FileSinkConfig cfg;
|
||||
cfg.set_open_mode('w');
|
||||
return cfg;
|
||||
}(),
|
||||
FileEventNotifier{});
|
||||
|
||||
Logger* logger = Frontend::create_or_get_logger(logger_name, std::move(file_sink));
|
||||
|
||||
{
|
||||
std::string s = "adipiscing";
|
||||
std::wstring ws = L"adipiscing";
|
||||
std::wstring const empty_s{};
|
||||
|
||||
std::wstring_view begin_s{L"begin_s"};
|
||||
std::wstring_view const end_s{L"end_s"};
|
||||
std::wstring_view empty_sv{};
|
||||
|
||||
wchar_t const* c_style_string_empty = L"";
|
||||
wchar_t const* c_style_string = L"Lorem ipsum";
|
||||
|
||||
LOG_INFO(logger, "s [{}]", s);
|
||||
LOG_INFO(logger, "ws [{}]", ws);
|
||||
LOG_INFO(logger, "empty_s [{}]", empty_s);
|
||||
LOG_INFO(logger, "begin_s [{}]", begin_s);
|
||||
LOG_INFO(logger, "end_s [{}]", end_s);
|
||||
LOG_INFO(logger, "empty_sv [{}]", empty_sv);
|
||||
LOG_INFO(logger, "c_style_string_empty [{}]", c_style_string_empty);
|
||||
LOG_INFO(logger, "c_style_string [{}]", c_style_string);
|
||||
|
||||
LOG_INFO(logger,
|
||||
"Lorem ipsum dolor sit amet, consectetur [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] "
|
||||
"[{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}]",
|
||||
ws, "elit", 1, 3.14, empty_s, begin_s, end_s, empty_sv, c_style_string_empty,
|
||||
c_style_string, ws, "elit", 1, 3.14, empty_s, begin_s, end_s, empty_sv,
|
||||
c_style_string_empty, c_style_string, s);
|
||||
|
||||
LOG_ERROR(logger,
|
||||
"Nulla tempus, libero at dignissim viverra, lectus libero finibus ante [{}] [{}] "
|
||||
"[{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}]",
|
||||
2, true, begin_s, empty_sv, empty_s, c_style_string_empty, c_style_string, end_s, 2,
|
||||
true, begin_s, empty_sv, empty_s, c_style_string_empty, c_style_string, end_s, s);
|
||||
}
|
||||
|
||||
// Log a big string
|
||||
for (size_t i = 0; i < number_of_messages; ++i)
|
||||
{
|
||||
std::wstring v{
|
||||
L"Lorem ipsum dolor sit amet, consectetur Lorem ipsum dolor sit amet, consectetur Lorem "
|
||||
L"ipsum dolor sit amet, consectetur "};
|
||||
v += std::to_wstring(i);
|
||||
|
||||
LOG_INFO(logger, "Logging int: {}, int: {}, string: {}, char: {}", i, i * 10, v, v.c_str());
|
||||
}
|
||||
|
||||
logger->flush_log();
|
||||
Frontend::remove_logger(logger);
|
||||
|
||||
// Wait until the backend thread stops for test stability
|
||||
Backend::stop();
|
||||
|
||||
// Read file and check
|
||||
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
|
||||
REQUIRE_EQ(file_contents.size(), number_of_messages + 10);
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " s [adipiscing]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " ws [adipiscing]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " empty_s []"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " begin_s [begin_s]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " end_s [end_s]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " empty_sv []"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " c_style_string_empty []"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " c_style_string [Lorem ipsum]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " Lorem ipsum dolor sit amet, consectetur [adipiscing] [elit] [1] [3.14] [] [begin_s] [end_s] [] [] [Lorem ipsum] [adipiscing] [elit] [1] [3.14] [] [begin_s] [end_s] [] [] [Lorem ipsum] [adipiscing]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_ERROR " + logger_name + " Nulla tempus, libero at dignissim viverra, lectus libero finibus ante [2] [true] [begin_s] [] [] [] [Lorem ipsum] [end_s] [2] [true] [begin_s] [] [] [] [Lorem ipsum] [end_s] [adipiscing]"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " Logging int: 0, int: 0, string: Lorem ipsum dolor sit amet, consectetur Lorem ipsum dolor sit amet, consectetur Lorem ipsum dolor sit amet, consectetur 0, char: Lorem ipsum dolor sit amet, consectetur Lorem ipsum dolor sit amet, consectetur Lorem ipsum dolor sit amet, consectetur 0"}));
|
||||
|
||||
REQUIRE(quill::testing::file_contains(
|
||||
file_contents, std::string{"LOG_INFO " + logger_name + " Logging int: 1999, int: 19990, string: Lorem ipsum dolor sit amet, consectetur Lorem ipsum dolor sit amet, consectetur Lorem ipsum dolor sit amet, consectetur 1999, char: Lorem ipsum dolor sit amet, consectetur Lorem ipsum dolor sit amet, consectetur Lorem ipsum dolor sit amet, consectetur 1999"}));
|
||||
|
||||
testing::remove_file(filename);
|
||||
#endif
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue