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 | |
8 | TEST_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 | |
29 | TEST_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 | |
46 | TEST_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 | |
65 | TEST_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 | |
85 | TEST_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 | |
98 | TEST_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 | |
117 | TEST_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 | |
149 | TEST_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 | |
172 | TEST_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 | |