1#include "includes.h"
2#include "spdlog/async.h"
3#include "spdlog/sinks/basic_file_sink.h"
4#include "test_sink.h"
5
6#define TEST_FILENAME "test_logs/async_test.log"
7
8TEST_CASE("basic async test ", "[async]")
9{
10 auto test_sink = std::make_shared<spdlog::sinks::test_sink_mt>();
11 size_t overrun_counter = 0;
12 size_t queue_size = 128;
13 size_t messages = 256;
14 {
15 auto tp = std::make_shared<spdlog::details::thread_pool>(queue_size, 1);
16 auto logger = std::make_shared<spdlog::async_logger>("as", test_sink, tp, spdlog::async_overflow_policy::block);
17 for (size_t i = 0; i < messages; i++)
18 {
19 logger->info("Hello message #{}", i);
20 }
21 logger->flush();
22 overrun_counter = tp->overrun_counter();
23 }
24 REQUIRE(test_sink->msg_counter() == messages);
25 REQUIRE(test_sink->flush_counter() == 1);
26 REQUIRE(overrun_counter == 0);
27}
28
29TEST_CASE("discard policy ", "[async]")
30{
31 auto test_sink = std::make_shared<spdlog::sinks::test_sink_mt>();
32 test_sink->set_delay(std::chrono::milliseconds(1));
33 size_t queue_size = 4;
34 size_t messages = 1024;
35
36 auto tp = std::make_shared<spdlog::details::thread_pool>(queue_size, 1);
37 auto logger = std::make_shared<spdlog::async_logger>("as", test_sink, tp, spdlog::async_overflow_policy::overrun_oldest);
38 for (size_t i = 0; i < messages; i++)
39 {
40 logger->info("Hello message");
41 }
42 REQUIRE(test_sink->msg_counter() < messages);
43 REQUIRE(tp->overrun_counter() > 0);
44}
45
46TEST_CASE("discard policy using factory ", "[async]")
47{
48 size_t queue_size = 4;
49 size_t messages = 1024;
50 spdlog::init_thread_pool(queue_size, 1);
51
52 auto logger = spdlog::create_async_nb<spdlog::sinks::test_sink_mt>("as2");
53 auto test_sink = std::static_pointer_cast<spdlog::sinks::test_sink_mt>(logger->sinks()[0]);
54 test_sink->set_delay(std::chrono::milliseconds(3));
55
56 for (size_t i = 0; i < messages; i++)
57 {
58 logger->info("Hello message");
59 }
60
61 REQUIRE(test_sink->msg_counter() < messages);
62 spdlog::drop_all();
63}
64
65TEST_CASE("flush", "[async]")
66{
67 auto test_sink = std::make_shared<spdlog::sinks::test_sink_mt>();
68 size_t queue_size = 256;
69 size_t messages = 256;
70 {
71 auto tp = std::make_shared<spdlog::details::thread_pool>(queue_size, 1);
72 auto logger = std::make_shared<spdlog::async_logger>("as", test_sink, tp, spdlog::async_overflow_policy::block);
73 for (size_t i = 0; i < messages; i++)
74 {
75 logger->info("Hello message #{}", i);
76 }
77
78 logger->flush();
79 }
80 // std::this_thread::sleep_for(std::chrono::milliseconds(250));
81 REQUIRE(test_sink->msg_counter() == messages);
82 REQUIRE(test_sink->flush_counter() == 1);
83}
84
85TEST_CASE("async periodic flush", "[async]")
86{
87
88 auto logger = spdlog::create_async<spdlog::sinks::test_sink_mt>("as");
89 auto test_sink = std::static_pointer_cast<spdlog::sinks::test_sink_mt>(logger->sinks()[0]);
90
91 spdlog::flush_every(std::chrono::seconds(1));
92 std::this_thread::sleep_for(std::chrono::milliseconds(1700));
93 REQUIRE(test_sink->flush_counter() == 1);
94 spdlog::flush_every(std::chrono::seconds(0));
95 spdlog::drop_all();
96}
97
98TEST_CASE("tp->wait_empty() ", "[async]")
99{
100 auto test_sink = std::make_shared<spdlog::sinks::test_sink_mt>();
101 test_sink->set_delay(std::chrono::milliseconds(5));
102 size_t messages = 100;
103
104 auto tp = std::make_shared<spdlog::details::thread_pool>(messages, 2);
105 auto logger = std::make_shared<spdlog::async_logger>("as", test_sink, tp, spdlog::async_overflow_policy::block);
106 for (size_t i = 0; i < messages; i++)
107 {
108 logger->info("Hello message #{}", i);
109 }
110 logger->flush();
111 tp.reset();
112
113 REQUIRE(test_sink->msg_counter() == messages);
114 REQUIRE(test_sink->flush_counter() == 1);
115}
116
117TEST_CASE("multi threads", "[async]")
118{
119 auto test_sink = std::make_shared<spdlog::sinks::test_sink_mt>();
120 size_t queue_size = 128;
121 size_t messages = 256;
122 size_t n_threads = 10;
123 {
124 auto tp = std::make_shared<spdlog::details::thread_pool>(queue_size, 1);
125 auto logger = std::make_shared<spdlog::async_logger>("as", test_sink, tp, spdlog::async_overflow_policy::block);
126
127 std::vector<std::thread> threads;
128 for (size_t i = 0; i < n_threads; i++)
129 {
130 threads.emplace_back([logger, messages] {
131 for (size_t j = 0; j < messages; j++)
132 {
133 logger->info("Hello message #{}", j);
134 }
135 });
136 logger->flush();
137 }
138
139 for (auto &t : threads)
140 {
141 t.join();
142 }
143 }
144
145 REQUIRE(test_sink->msg_counter() == messages * n_threads);
146 REQUIRE(test_sink->flush_counter() == n_threads);
147}
148
149TEST_CASE("to_file", "[async]")
150{
151 prepare_logdir();
152 size_t messages = 1024;
153 size_t tp_threads = 1;
154 spdlog::filename_t filename = SPDLOG_FILENAME_T(TEST_FILENAME);
155 {
156 auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename, true);
157 auto tp = std::make_shared<spdlog::details::thread_pool>(messages, tp_threads);
158 auto logger = std::make_shared<spdlog::async_logger>("as", std::move(file_sink), std::move(tp));
159
160 for (size_t j = 0; j < messages; j++)
161 {
162 logger->info("Hello message #{}", j);
163 }
164 }
165
166 require_message_count(TEST_FILENAME, messages);
167 auto contents = file_contents(TEST_FILENAME);
168 using spdlog::details::os::default_eol;
169 REQUIRE(ends_with(contents, spdlog::fmt_lib::format("Hello message #1023{}", default_eol)));
170}
171
172TEST_CASE("to_file multi-workers", "[async]")
173{
174 prepare_logdir();
175 size_t messages = 1024 * 10;
176 size_t tp_threads = 10;
177 spdlog::filename_t filename = SPDLOG_FILENAME_T(TEST_FILENAME);
178 {
179 auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename, true);
180 auto tp = std::make_shared<spdlog::details::thread_pool>(messages, tp_threads);
181 auto logger = std::make_shared<spdlog::async_logger>("as", std::move(file_sink), std::move(tp));
182
183 for (size_t j = 0; j < messages; j++)
184 {
185 logger->info("Hello message #{}", j);
186 }
187 }
188
189 require_message_count(TEST_FILENAME, messages);
190}
191