mirror of https://github.com/gabime/spdlog.git
attribute testing (#3)
* initial testing of attributes * updating test cases for new api * more testing, fixing bugs found * fixed unused error * errors might be caused due to passing pointers by reference, these simple pointer passes should be by value * my only other idea for getting this to work. will experiment * fixing tests before merge (#4) * my only other idea for getting this to work. will experiment * I think I fixed the thread issue, lets see... * unused lambda capture acting funny * see if its the context that is causing issues * unused warning... again * reverting to basic, see where the issue is in github actions (testing most of it locally) * this works again? * some diff cleanup before squash merging * cleaner search for stop iteratorpull/2687/head
parent
b800164d11
commit
3d27666650
@ -0,0 +1,108 @@
|
||||
// make attributes conform to spdlog requirements (thread-safe, exception-safe, etc)
|
||||
#include "includes.h"
|
||||
#include "test_sink.h"
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
|
||||
#define TEST_FILENAME "test_logs/attr_test.log"
|
||||
|
||||
// see if multiple async logs to a single file is thread-safe, i.e. produces coherent structured logs
|
||||
TEST_CASE("async attributes test with threads ", "[attributes]")
|
||||
{
|
||||
auto test_sink = std::make_shared<spdlog::sinks::test_sink_mt>();
|
||||
|
||||
constexpr int num_loggers = 10;
|
||||
constexpr int num_msgs = 10;
|
||||
size_t overrun_counter = 0;
|
||||
|
||||
{
|
||||
auto tp = std::make_shared<spdlog::details::thread_pool>(num_loggers * num_msgs, 1);
|
||||
std::vector<std::shared_ptr<spdlog::logger>> loggers;
|
||||
for (int i = 0; i < num_loggers; ++i) {
|
||||
loggers.push_back(std::make_shared<spdlog::async_logger>(
|
||||
"attr_logger_"+std::to_string(i), test_sink, tp, spdlog::async_overflow_policy::block));
|
||||
}
|
||||
|
||||
std::vector<std::thread> threads;
|
||||
for (auto lg : loggers) {
|
||||
threads.emplace_back([=](){
|
||||
// push and pop context are not guaranteed to be thread safe
|
||||
// therefore, messages from the same logger object have to be in the same thread
|
||||
// to guarantee thread safety, use a different logger object for each thread
|
||||
for (int i = 0; i < num_msgs; ++i) {
|
||||
lg->push_context({{"key"+std::to_string(i), "val"+std::to_string(i)}});
|
||||
lg->info("testing {}", i);
|
||||
lg->pop_context();
|
||||
}
|
||||
});
|
||||
}
|
||||
for (auto& th : threads) {
|
||||
th.join();
|
||||
}
|
||||
|
||||
for (auto lg : loggers) {
|
||||
lg->flush();
|
||||
}
|
||||
overrun_counter += tp->overrun_counter();
|
||||
}
|
||||
|
||||
REQUIRE(test_sink->msg_counter() == num_loggers * num_msgs);
|
||||
REQUIRE(test_sink->flush_counter() == num_loggers);
|
||||
REQUIRE(overrun_counter == 0);
|
||||
|
||||
// todo: better parsing of keys and values, maybe using regex
|
||||
for (auto& line : test_sink->lines()) {
|
||||
REQUIRE(line.find("key") != std::string::npos);
|
||||
REQUIRE(line.find("val") != std::string::npos);
|
||||
}
|
||||
}
|
||||
|
||||
// testing custom patterns, including the new attribute patterns, with many use cases.
|
||||
// some use cases may result in errors or undesirable behaviour, but the test should not crash.
|
||||
TEST_CASE("pattern matching with attributes ", "[attributes]")
|
||||
{
|
||||
auto test_sink = std::make_shared<spdlog::sinks::test_sink_mt>();
|
||||
auto logger = std::make_shared<spdlog::logger>("attr_logger", test_sink);
|
||||
std::string msg = "testing";
|
||||
logger->push_context({{"key1", "value1"}, {"key2", "value2"}});
|
||||
|
||||
// a pattern with no stop flag will consider the stop flag as the end
|
||||
logger->set_pattern("%v%( %K=%V");
|
||||
logger->info(msg);
|
||||
|
||||
REQUIRE(test_sink->lines()[test_sink->msg_counter()-1] == msg+" key1=value1 key2=value2");
|
||||
|
||||
// a pattern with no start flag will be parsed as-is. the new flags will be treated as empty strings.
|
||||
logger->set_pattern("%v %K=%V%) %v end");
|
||||
logger->info("testing");
|
||||
|
||||
REQUIRE(test_sink->lines()[test_sink->msg_counter()-1] == msg+" = "+msg+" end");
|
||||
|
||||
// a pattern with nested flags will print those flags for every key-value pair
|
||||
logger->set_pattern("%(%v %K=%V %)");
|
||||
logger->info("testing");
|
||||
REQUIRE(test_sink->lines()[test_sink->msg_counter()-1] == msg+" key1=value1 "+msg+" key2=value2 ");
|
||||
|
||||
logger->set_pattern("%v start%( %K=%V%) %v end");
|
||||
// zero kv pairs
|
||||
logger->clear_context();
|
||||
logger->push_context({});
|
||||
logger->info(msg);
|
||||
|
||||
REQUIRE(test_sink->lines()[test_sink->msg_counter()-1] == msg+" start "+msg+" end");
|
||||
|
||||
// N kv pairs
|
||||
for (int i = 0; i < 50; ++i) {
|
||||
logger->push_context({{"key"+std::to_string(i), "value"+std::to_string(i)}});
|
||||
logger->info("testing");
|
||||
std::stringstream ss;
|
||||
ss << msg << " start";
|
||||
for (int j = 0; j <= i; ++j) {
|
||||
ss << " key" << j << "=value" << j;
|
||||
}
|
||||
ss << ' ' << msg << " end";
|
||||
|
||||
REQUIRE(test_sink->lines()[test_sink->msg_counter()-1] == ss.str());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue