test_pattern_formatter.cpp 21 KB

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