spdlog
Loading...
Searching...
No Matches
test_pattern_formatter.cpp
Go to the documentation of this file.
1#include "includes.h"
2#include "test_sink.h"
3
5
6// log to str and return it
7template<typename... Args>
8static std::string log_to_str(const std::string &msg, const Args &...args)
9{
12 spdlog::logger oss_logger("pattern_tester", oss_sink);
14
16
17 oss_logger.info(msg);
18 return oss.str();
19}
20
21TEST_CASE("custom eol", "[pattern_formatter]")
22{
23 std::string msg = "Hello custom eol test";
24 std::string eol = ";)";
25 REQUIRE(log_to_str(msg, "%v", spdlog::pattern_time_type::local, ";)") == msg + eol);
26}
27
28TEST_CASE("empty format", "[pattern_formatter]")
29{
30 REQUIRE(log_to_str("Some message", "", spdlog::pattern_time_type::local, "").empty());
31}
32
33TEST_CASE("empty format2", "[pattern_formatter]")
34{
35 REQUIRE(log_to_str("Some message", "", spdlog::pattern_time_type::local, "\n") == "\n");
36}
37
38TEST_CASE("level", "[pattern_formatter]")
39{
40 REQUIRE(log_to_str("Some message", "[%l] %v", spdlog::pattern_time_type::local, "\n") == "[info] Some message\n");
41}
42
43TEST_CASE("short level", "[pattern_formatter]")
44{
45 REQUIRE(log_to_str("Some message", "[%L] %v", spdlog::pattern_time_type::local, "\n") == "[I] Some message\n");
46}
47
48TEST_CASE("name", "[pattern_formatter]")
49{
50 REQUIRE(log_to_str("Some message", "[%n] %v", spdlog::pattern_time_type::local, "\n") == "[pattern_tester] Some message\n");
51}
52
53TEST_CASE("date MM/DD/YY ", "[pattern_formatter]")
54{
55 auto now_tm = spdlog::details::os::localtime();
57 oss << std::setfill('0') << std::setw(2) << now_tm.tm_mon + 1 << "/" << std::setw(2) << now_tm.tm_mday << "/" << std::setw(2)
58 << (now_tm.tm_year + 1900) % 1000 << " Some message\n";
59 REQUIRE(log_to_str("Some message", "%D %v", spdlog::pattern_time_type::local, "\n") == oss.str());
60}
61
62TEST_CASE("color range test1", "[pattern_formatter]")
63{
65
66 memory_buf_t buf;
67 fmt::format_to(std::back_inserter(buf), "Hello");
68 memory_buf_t formatted;
69 std::string logger_name = "test";
70 spdlog::details::log_msg msg(logger_name, spdlog::level::info, spdlog::string_view_t(buf.data(), buf.size()));
71 formatter->format(msg, formatted);
72 REQUIRE(msg.color_range_start == 0);
73 REQUIRE(msg.color_range_end == 5);
74 REQUIRE(log_to_str("hello", "%^%v%$", spdlog::pattern_time_type::local, "\n") == "hello\n");
75}
76
77TEST_CASE("color range test2", "[pattern_formatter]")
78{
80 std::string logger_name = "test";
82 memory_buf_t formatted;
83 formatter->format(msg, formatted);
84 REQUIRE(msg.color_range_start == 0);
85 REQUIRE(msg.color_range_end == 0);
86 REQUIRE(log_to_str("", "%^%$", spdlog::pattern_time_type::local, "\n") == "\n");
87}
88
89TEST_CASE("color range test3", "[pattern_formatter]")
90{
92 std::string logger_name = "test";
93 spdlog::details::log_msg msg(logger_name, spdlog::level::info, "ignored");
94 memory_buf_t formatted;
95 formatter->format(msg, formatted);
96 REQUIRE(msg.color_range_start == 0);
97 REQUIRE(msg.color_range_end == 3);
98}
99
100TEST_CASE("color range test4", "[pattern_formatter]")
101{
103 std::string logger_name = "test";
104 spdlog::details::log_msg msg(logger_name, spdlog::level::info, "ignored");
105
106 memory_buf_t formatted;
107 formatter->format(msg, formatted);
108 REQUIRE(msg.color_range_start == 2);
109 REQUIRE(msg.color_range_end == 5);
110 REQUIRE(log_to_str("ignored", "XX%^YYY%$", spdlog::pattern_time_type::local, "\n") == "XXYYY\n");
111}
112
113TEST_CASE("color range test5", "[pattern_formatter]")
114{
116 std::string logger_name = "test";
117 spdlog::details::log_msg msg(logger_name, spdlog::level::info, "ignored");
118 memory_buf_t formatted;
119 formatter->format(msg, formatted);
120 REQUIRE(msg.color_range_start == 2);
121 REQUIRE(msg.color_range_end == 0);
122}
123
124TEST_CASE("color range test6", "[pattern_formatter]")
125{
127 std::string logger_name = "test";
128 spdlog::details::log_msg msg(logger_name, spdlog::level::info, "ignored");
129 memory_buf_t formatted;
130 formatter->format(msg, formatted);
131 REQUIRE(msg.color_range_start == 0);
132 REQUIRE(msg.color_range_end == 2);
133}
134
135//
136// Test padding
137//
138
139TEST_CASE("level_left_padded", "[pattern_formatter]")
140{
141 REQUIRE(log_to_str("Some message", "[%8l] %v", spdlog::pattern_time_type::local, "\n") == "[ info] Some message\n");
142 REQUIRE(log_to_str("Some message", "[%8!l] %v", spdlog::pattern_time_type::local, "\n") == "[ info] Some message\n");
143}
144
145TEST_CASE("level_right_padded", "[pattern_formatter]")
146{
147 REQUIRE(log_to_str("Some message", "[%-8l] %v", spdlog::pattern_time_type::local, "\n") == "[info ] Some message\n");
148 REQUIRE(log_to_str("Some message", "[%-8!l] %v", spdlog::pattern_time_type::local, "\n") == "[info ] Some message\n");
149}
150
151TEST_CASE("level_center_padded", "[pattern_formatter]")
152{
153 REQUIRE(log_to_str("Some message", "[%=8l] %v", spdlog::pattern_time_type::local, "\n") == "[ info ] Some message\n");
154 REQUIRE(log_to_str("Some message", "[%=8!l] %v", spdlog::pattern_time_type::local, "\n") == "[ info ] Some message\n");
155}
156
157TEST_CASE("short level_left_padded", "[pattern_formatter]")
158{
159 REQUIRE(log_to_str("Some message", "[%3L] %v", spdlog::pattern_time_type::local, "\n") == "[ I] Some message\n");
160 REQUIRE(log_to_str("Some message", "[%3!L] %v", spdlog::pattern_time_type::local, "\n") == "[ I] Some message\n");
161}
162
163TEST_CASE("short level_right_padded", "[pattern_formatter]")
164{
165 REQUIRE(log_to_str("Some message", "[%-3L] %v", spdlog::pattern_time_type::local, "\n") == "[I ] Some message\n");
166 REQUIRE(log_to_str("Some message", "[%-3!L] %v", spdlog::pattern_time_type::local, "\n") == "[I ] Some message\n");
167}
168
169TEST_CASE("short level_center_padded", "[pattern_formatter]")
170{
171 REQUIRE(log_to_str("Some message", "[%=3L] %v", spdlog::pattern_time_type::local, "\n") == "[ I ] Some message\n");
172 REQUIRE(log_to_str("Some message", "[%=3!L] %v", spdlog::pattern_time_type::local, "\n") == "[ I ] Some message\n");
173}
174
175TEST_CASE("left_padded_short", "[pattern_formatter]")
176{
177 REQUIRE(log_to_str("Some message", "[%3n] %v", spdlog::pattern_time_type::local, "\n") == "[pattern_tester] Some message\n");
178 REQUIRE(log_to_str("Some message", "[%3!n] %v", spdlog::pattern_time_type::local, "\n") == "[pat] Some message\n");
179}
180
181TEST_CASE("right_padded_short", "[pattern_formatter]")
182{
183 REQUIRE(log_to_str("Some message", "[%-3n] %v", spdlog::pattern_time_type::local, "\n") == "[pattern_tester] Some message\n");
184 REQUIRE(log_to_str("Some message", "[%-3!n] %v", spdlog::pattern_time_type::local, "\n") == "[pat] Some message\n");
185}
186
187TEST_CASE("center_padded_short", "[pattern_formatter]")
188{
189 REQUIRE(log_to_str("Some message", "[%=3n] %v", spdlog::pattern_time_type::local, "\n") == "[pattern_tester] Some message\n");
190 REQUIRE(log_to_str("Some message", "[%=3!n] %v", spdlog::pattern_time_type::local, "\n") == "[pat] Some message\n");
191}
192
193TEST_CASE("left_padded_huge", "[pattern_formatter]")
194{
195 REQUIRE(log_to_str("Some message", "[%-300n] %v", spdlog::pattern_time_type::local, "\n") ==
196 "[pattern_tester ] Some message\n");
197
198 REQUIRE(log_to_str("Some message", "[%-300!n] %v", spdlog::pattern_time_type::local, "\n") ==
199 "[pattern_tester ] Some message\n");
200}
201
202TEST_CASE("left_padded_max", "[pattern_formatter]")
203{
204 REQUIRE(log_to_str("Some message", "[%-64n] %v", spdlog::pattern_time_type::local, "\n") ==
205 "[pattern_tester ] Some message\n");
206
207 REQUIRE(log_to_str("Some message", "[%-64!n] %v", spdlog::pattern_time_type::local, "\n") ==
208 "[pattern_tester ] Some message\n");
209}
210
211// Test padding + truncate flag
212
213TEST_CASE("paddinng_truncate", "[pattern_formatter]")
214{
215 REQUIRE(log_to_str("123456", "%6!v", spdlog::pattern_time_type::local, "\n") == "123456\n");
216 REQUIRE(log_to_str("123456", "%5!v", spdlog::pattern_time_type::local, "\n") == "12345\n");
217 REQUIRE(log_to_str("123456", "%7!v", spdlog::pattern_time_type::local, "\n") == " 123456\n");
218
219 REQUIRE(log_to_str("123456", "%-6!v", spdlog::pattern_time_type::local, "\n") == "123456\n");
220 REQUIRE(log_to_str("123456", "%-5!v", spdlog::pattern_time_type::local, "\n") == "12345\n");
221 REQUIRE(log_to_str("123456", "%-7!v", spdlog::pattern_time_type::local, "\n") == "123456 \n");
222
223 REQUIRE(log_to_str("123456", "%=6!v", spdlog::pattern_time_type::local, "\n") == "123456\n");
224 REQUIRE(log_to_str("123456", "%=5!v", spdlog::pattern_time_type::local, "\n") == "12345\n");
225 REQUIRE(log_to_str("123456", "%=7!v", spdlog::pattern_time_type::local, "\n") == "123456 \n");
226
227 REQUIRE(log_to_str("123456", "%0!v", spdlog::pattern_time_type::local, "\n") == "\n");
228}
229
230TEST_CASE("padding_truncate_funcname", "[pattern_formatter]")
231{
233
234 const char *pattern = "%v [%5!!]";
236 test_sink.set_formatter(std::move(formatter));
237
238 spdlog::details::log_msg msg1{spdlog::source_loc{"ignored", 1, "func"}, "test_logger", spdlog::level::info, "message"};
239 test_sink.log(msg1);
240 REQUIRE(test_sink.lines()[0] == "message [ func]");
241
242 spdlog::details::log_msg msg2{spdlog::source_loc{"ignored", 1, "function"}, "test_logger", spdlog::level::info, "message"};
243 test_sink.log(msg2);
244 REQUIRE(test_sink.lines()[1] == "message [funct]");
245}
246
247TEST_CASE("padding_funcname", "[pattern_formatter]")
248{
250
251 const char *pattern = "%v [%10!]";
253 test_sink.set_formatter(std::move(formatter));
254
255 spdlog::details::log_msg msg1{spdlog::source_loc{"ignored", 1, "func"}, "test_logger", spdlog::level::info, "message"};
256 test_sink.log(msg1);
257 REQUIRE(test_sink.lines()[0] == "message [ func]");
258
259 spdlog::details::log_msg msg2{spdlog::source_loc{"ignored", 1, "func567890123"}, "test_logger", spdlog::level::info, "message"};
260 test_sink.log(msg2);
261 REQUIRE(test_sink.lines()[1] == "message [func567890123]");
262}
263
264TEST_CASE("clone-default-formatter", "[pattern_formatter]")
265{
267 auto formatter_2 = formatter_1->clone();
268 std::string logger_name = "test";
269 spdlog::details::log_msg msg(logger_name, spdlog::level::info, "some message");
270
271 memory_buf_t formatted_1;
272 memory_buf_t formatted_2;
273 formatter_1->format(msg, formatted_1);
274 formatter_2->format(msg, formatted_2);
275
276 REQUIRE(fmt::to_string(formatted_1) == fmt::to_string(formatted_2));
277}
278
279TEST_CASE("clone-default-formatter2", "[pattern_formatter]")
280{
281 auto formatter_1 = std::make_shared<spdlog::pattern_formatter>("%+");
282 auto formatter_2 = formatter_1->clone();
283 std::string logger_name = "test";
284 spdlog::details::log_msg msg(logger_name, spdlog::level::info, "some message");
285
286 memory_buf_t formatted_1;
287 memory_buf_t formatted_2;
288 formatter_1->format(msg, formatted_1);
289 formatter_2->format(msg, formatted_2);
290
291 REQUIRE(fmt::to_string(formatted_1) == fmt::to_string(formatted_2));
292}
293
294TEST_CASE("clone-formatter", "[pattern_formatter]")
295{
296 auto formatter_1 = std::make_shared<spdlog::pattern_formatter>("%D %X [%] [%n] %v");
297 auto formatter_2 = formatter_1->clone();
298 std::string logger_name = "test";
299 spdlog::details::log_msg msg(logger_name, spdlog::level::info, "some message");
300
301 memory_buf_t formatted_1;
302 memory_buf_t formatted_2;
303 formatter_1->format(msg, formatted_1);
304 formatter_2->format(msg, formatted_2);
305 REQUIRE(fmt::to_string(formatted_1) == fmt::to_string(formatted_2));
306}
307
308TEST_CASE("clone-formatter-2", "[pattern_formatter]")
309{
311 auto formatter_1 = std::make_shared<spdlog::pattern_formatter>("%D %X [%] [%n] %v", pattern_time_type::utc, "xxxxxx\n");
312 auto formatter_2 = formatter_1->clone();
313 std::string logger_name = "test2";
314 spdlog::details::log_msg msg(logger_name, spdlog::level::info, "some message");
315
316 memory_buf_t formatted_1;
317 memory_buf_t formatted_2;
318 formatter_1->format(msg, formatted_1);
319 formatter_2->format(msg, formatted_2);
320 REQUIRE(fmt::to_string(formatted_1) == fmt::to_string(formatted_2));
321}
322
324{
325public:
327 : some_txt{std::move(txt)}
328 {}
329
330 void format(const spdlog::details::log_msg &, const std::tm &, spdlog::memory_buf_t &dest) override
331 {
332 if (some_txt == "throw_me")
333 {
334 throw spdlog::spdlog_ex("custom_flag_exception_test");
335 }
338 }
343
345
347 {
348 return spdlog::details::make_unique<custom_test_flag>(some_txt);
349 }
350};
351// test clone with custom flag formatters
352TEST_CASE("clone-custom_formatter", "[pattern_formatter]")
353{
355 formatter_1->add_flag<custom_test_flag>('t', "custom_output").set_pattern("[%n] [%t] %v");
356 auto formatter_2 = formatter_1->clone();
357 std::string logger_name = "logger-name";
358 spdlog::details::log_msg msg(logger_name, spdlog::level::info, "some message");
359
360 memory_buf_t formatted_1;
361 memory_buf_t formatted_2;
362 formatter_1->format(msg, formatted_1);
363 formatter_2->format(msg, formatted_2);
364
365 auto expected = fmt::format("[logger-name] [custom_output] some message{}", spdlog::details::os::default_eol);
366 REQUIRE(fmt::to_string(formatted_1) == expected);
367 REQUIRE(fmt::to_string(formatted_2) == expected);
368}
369
370//
371// Test source location formatting
372//
373
374#ifdef _WIN32
375static const char *const test_path = "\\a\\b\\c/myfile.cpp";
376#else
377static const char *const test_path = "/a/b//myfile.cpp";
378#endif
379
380TEST_CASE("short filename formatter-1", "[pattern_formatter]")
381{
383 memory_buf_t formatted;
384 std::string logger_name = "logger-name";
385 spdlog::source_loc source_loc{test_path, 123, "some_func()"};
386 spdlog::details::log_msg msg(source_loc, "logger-name", spdlog::level::info, "Hello");
387 formatter.format(msg, formatted);
388 REQUIRE(fmt::to_string(formatted) == "myfile.cpp");
389}
390
391TEST_CASE("short filename formatter-2", "[pattern_formatter]")
392{
394 memory_buf_t formatted;
395 std::string logger_name = "logger-name";
396 spdlog::source_loc source_loc{"myfile.cpp", 123, "some_func()"};
397 spdlog::details::log_msg msg(source_loc, "logger-name", spdlog::level::info, "Hello");
398 formatter.format(msg, formatted);
399 REQUIRE(fmt::to_string(formatted) == "myfile.cpp:123");
400}
401
402TEST_CASE("short filename formatter-3", "[pattern_formatter]")
403{
405 memory_buf_t formatted;
406 std::string logger_name = "logger-name";
407 spdlog::source_loc source_loc{"", 123, "some_func()"};
408 spdlog::details::log_msg msg(source_loc, "logger-name", spdlog::level::info, "Hello");
409 formatter.format(msg, formatted);
410 REQUIRE(fmt::to_string(formatted) == " Hello");
411}
412
413TEST_CASE("full filename formatter", "[pattern_formatter]")
414{
416 memory_buf_t formatted;
417 std::string logger_name = "logger-name";
418 spdlog::source_loc source_loc{test_path, 123, "some_func()"};
419 spdlog::details::log_msg msg(source_loc, "logger-name", spdlog::level::info, "Hello");
420 formatter.format(msg, formatted);
421 REQUIRE(fmt::to_string(formatted) == test_path);
422}
423
424TEST_CASE("custom flags", "[pattern_formatter]")
425{
427 formatter->add_flag<custom_test_flag>('t', "custom1").add_flag<custom_test_flag>('u', "custom2").set_pattern("[%n] [%t] [%u] %v");
428
429 memory_buf_t formatted;
430
431 spdlog::details::log_msg msg(spdlog::source_loc{}, "logger-name", spdlog::level::info, "some message");
432 formatter->format(msg, formatted);
433 auto expected = fmt::format("[logger-name] [custom1] [custom2] some message{}", spdlog::details::os::default_eol);
434 REQUIRE(fmt::to_string(formatted) == expected);
435}
436
437TEST_CASE("custom flags-padding", "[pattern_formatter]")
438{
440 formatter->add_flag<custom_test_flag>('t', "custom1").add_flag<custom_test_flag>('u', "custom2").set_pattern("[%n] [%t] [%5u] %v");
441
442 memory_buf_t formatted;
443
444 spdlog::details::log_msg msg(spdlog::source_loc{}, "logger-name", spdlog::level::info, "some message");
445 formatter->format(msg, formatted);
446 auto expected = fmt::format("[logger-name] [custom1] [ custom2] some message{}", spdlog::details::os::default_eol);
447 REQUIRE(fmt::to_string(formatted) == expected);
448}
449
450TEST_CASE("custom flags-exception", "[pattern_formatter]")
451{
453 formatter->add_flag<custom_test_flag>('t', "throw_me").add_flag<custom_test_flag>('u', "custom2").set_pattern("[%n] [%t] [%u] %v");
454
455 memory_buf_t formatted;
456 spdlog::details::log_msg msg(spdlog::source_loc{}, "logger-name", spdlog::level::info, "some message");
457 CHECK_THROWS_AS(formatter->format(msg, formatted), spdlog::spdlog_ex);
458}
T append(T... args)
T back_inserter(T... args)
#define CHECK_THROWS_AS(expr, exceptionType)
Definition catch.hpp:15101
#define TEST_CASE(...)
Definition catch.hpp:15119
#define REQUIRE(...)
Definition catch.hpp:15083
std::unique_ptr< custom_flag_formatter > clone() const override
custom_test_flag(std::string txt)
spdlog::details::padding_info get_padding_info()
void format(const spdlog::details::log_msg &, const std::tm &, spdlog::memory_buf_t &dest) override
void set_formatter(std::unique_ptr< formatter > f)
Definition logger-inl.h:84
void info(fmt::format_string< Args... > fmt, Args &&...args)
Definition logger.h:156
void set_level(level::level_enum log_level)
Definition logger-inl.h:67
void log(const details::log_msg &msg) final
void set_formatter(std::unique_ptr< spdlog::formatter > sink_formatter) final
std::vector< std::string > lines()
Definition test_sink.h:43
T data(T... args)
T make_shared(T... args)
static SPDLOG_CONSTEXPR const char * default_eol
Definition details/os.h:32
SPDLOG_INLINE std::tm localtime() SPDLOG_NOEXCEPT
Definition os-inl.h:97
fmt::basic_string_view< char > string_view_t
Definition common.h:114
pattern_time_type
Definition common.h:218
fmt::basic_memory_buffer< char, 250 > memory_buf_t
Definition common.h:116
T setfill(T... args)
T setw(T... args)
T size(T... args)
T str(T... args)
static const char *const test_path
static std::string log_to_str(const std::string &msg, const Args &...args)