exception safety tests

pull/2687/head
Bailey Chittle 3 years ago
parent 3d27666650
commit bfb8ea1f6e

@ -7,6 +7,51 @@
#define TEST_FILENAME "test_logs/attr_test.log"
// helper classes for exception-safe attribute push/pop
// these use RAII to ensure that the context is popped even if an exception is thrown
class scoped_context {
std::shared_ptr<spdlog::logger> logger_;
std::size_t push_counter_ = 0;
public:
scoped_context(std::shared_ptr<spdlog::logger> logger) : logger_(logger) {}
scoped_context(std::shared_ptr<spdlog::logger> logger, spdlog::attribute_list attrs) : scoped_context(logger) {
push(attrs);
}
void push(spdlog::attribute_list attrs) {
logger_->push_context(attrs);
++push_counter_;
}
~scoped_context() {
for (std::size_t i = 0; i < push_counter_; ++i) {
logger_->pop_context();
}
}
};
TEST_CASE("attributes test with exceptions ", "[attributes]")
{
auto test_sink = std::make_shared<spdlog::sinks::test_sink_mt>();
auto logger = std::make_shared<spdlog::logger>("attr_logger", test_sink);
logger->set_pattern("%v%( %K=%V%)");
// push and pop context are not guaranteed to be exception safe
// so we use the helper class
try {
auto ctx = scoped_context(logger, {{"key1", "val1"}});
logger->info("testing");
throw std::runtime_error("test exception");
} catch (const std::exception& e) {
logger->info("caught exception: {}", e.what());
}
REQUIRE(test_sink->msg_counter() == 2);
REQUIRE(test_sink->lines()[0] == "testing key1=val1"); // has kv pair in this msg
REQUIRE(test_sink->lines()[1] == "caught exception: test exception"); // doesn't have kv pair in error msg
}
// 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]")
{
@ -28,8 +73,7 @@ TEST_CASE("async attributes test with threads ", "[attributes]")
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
// to guarantee thread safety, use a different logger object for each thread when using attributes
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);

Loading…
Cancel
Save