1#include "includes.h"
2#include "test_sink.h"
3#include "spdlog/fmt/bin_to_hex.h"
4
5template<class T>
6std::string log_info(const T &what, spdlog::level::level_enum logger_level = spdlog::level::info)
7{
8
9 std::ostringstream oss;
10 auto oss_sink = std::make_shared<spdlog::sinks::ostream_sink_mt>(oss);
11
12 spdlog::logger oss_logger("oss", oss_sink);
13 oss_logger.set_level(logger_level);
14 oss_logger.set_pattern("%v");
15 oss_logger.info(what);
16
17 return oss.str().substr(0, oss.str().length() - strlen(spdlog::details::os::default_eol));
18}
19
20TEST_CASE("basic_logging ", "[basic_logging]")
21{
22 // const char
23 REQUIRE(log_info("Hello") == "Hello");
24 REQUIRE(log_info("").empty());
25
26 // std::string
27 REQUIRE(log_info(std::string("Hello")) == "Hello");
28 REQUIRE(log_info(std::string()).empty());
29
30 // Numbers
31 REQUIRE(log_info(5) == "5");
32 REQUIRE(log_info(5.6) == "5.6");
33
34 // User defined class
35 // REQUIRE(log_info(some_logged_class("some_val")) == "some_val");
36}
37
38TEST_CASE("log_levels", "[log_levels]")
39{
40 REQUIRE(log_info("Hello", spdlog::level::err).empty());
41 REQUIRE(log_info("Hello", spdlog::level::critical).empty());
42 REQUIRE(log_info("Hello", spdlog::level::info) == "Hello");
43 REQUIRE(log_info("Hello", spdlog::level::debug) == "Hello");
44 REQUIRE(log_info("Hello", spdlog::level::trace) == "Hello");
45}
46
47TEST_CASE("level_to_string_view", "[convert_to_string_view")
48{
49 REQUIRE(spdlog::level::to_string_view(spdlog::level::trace) == "trace");
50 REQUIRE(spdlog::level::to_string_view(spdlog::level::debug) == "debug");
51 REQUIRE(spdlog::level::to_string_view(spdlog::level::info) == "info");
52 REQUIRE(spdlog::level::to_string_view(spdlog::level::warn) == "warning");
53 REQUIRE(spdlog::level::to_string_view(spdlog::level::err) == "error");
54 REQUIRE(spdlog::level::to_string_view(spdlog::level::critical) == "critical");
55 REQUIRE(spdlog::level::to_string_view(spdlog::level::off) == "off");
56}
57
58TEST_CASE("to_short_c_str", "[convert_to_short_c_str]")
59{
60 REQUIRE(std::string(spdlog::level::to_short_c_str(spdlog::level::trace)) == "T");
61 REQUIRE(std::string(spdlog::level::to_short_c_str(spdlog::level::debug)) == "D");
62 REQUIRE(std::string(spdlog::level::to_short_c_str(spdlog::level::info)) == "I");
63 REQUIRE(std::string(spdlog::level::to_short_c_str(spdlog::level::warn)) == "W");
64 REQUIRE(std::string(spdlog::level::to_short_c_str(spdlog::level::err)) == "E");
65 REQUIRE(std::string(spdlog::level::to_short_c_str(spdlog::level::critical)) == "C");
66 REQUIRE(std::string(spdlog::level::to_short_c_str(spdlog::level::off)) == "O");
67}
68
69TEST_CASE("to_level_enum", "[convert_to_level_enum]")
70{
71 REQUIRE(spdlog::level::from_str("trace") == spdlog::level::trace);
72 REQUIRE(spdlog::level::from_str("debug") == spdlog::level::debug);
73 REQUIRE(spdlog::level::from_str("info") == spdlog::level::info);
74 REQUIRE(spdlog::level::from_str("warning") == spdlog::level::warn);
75 REQUIRE(spdlog::level::from_str("warn") == spdlog::level::warn);
76 REQUIRE(spdlog::level::from_str("error") == spdlog::level::err);
77 REQUIRE(spdlog::level::from_str("critical") == spdlog::level::critical);
78 REQUIRE(spdlog::level::from_str("off") == spdlog::level::off);
79 REQUIRE(spdlog::level::from_str("null") == spdlog::level::off);
80}
81
82TEST_CASE("periodic flush", "[periodic_flush]")
83{
84 using spdlog::sinks::test_sink_mt;
85 auto logger = spdlog::create<test_sink_mt>("periodic_flush");
86 auto test_sink = std::static_pointer_cast<test_sink_mt>(logger->sinks()[0]);
87
88 spdlog::flush_every(std::chrono::seconds(1));
89 std::this_thread::sleep_for(std::chrono::milliseconds(1250));
90 REQUIRE(test_sink->flush_counter() == 1);
91 spdlog::flush_every(std::chrono::seconds(0));
92 spdlog::drop_all();
93}
94
95TEST_CASE("clone-logger", "[clone]")
96{
97 using spdlog::sinks::test_sink_mt;
98 auto test_sink = std::make_shared<test_sink_mt>();
99 auto logger = std::make_shared<spdlog::logger>("orig", test_sink);
100 logger->set_pattern("%v");
101 auto cloned = logger->clone("clone");
102
103 REQUIRE(cloned->name() == "clone");
104 REQUIRE(logger->sinks() == cloned->sinks());
105 REQUIRE(logger->level() == cloned->level());
106 REQUIRE(logger->flush_level() == cloned->flush_level());
107 logger->info("Some message 1");
108 cloned->info("Some message 2");
109
110 REQUIRE(test_sink->lines().size() == 2);
111 REQUIRE(test_sink->lines()[0] == "Some message 1");
112 REQUIRE(test_sink->lines()[1] == "Some message 2");
113
114 spdlog::drop_all();
115}
116
117TEST_CASE("clone async", "[clone]")
118{
119 using spdlog::sinks::test_sink_st;
120 spdlog::init_thread_pool(4, 1);
121 auto test_sink = std::make_shared<test_sink_st>();
122 auto logger = std::make_shared<spdlog::async_logger>("orig", test_sink, spdlog::thread_pool());
123 logger->set_pattern("%v");
124 auto cloned = logger->clone("clone");
125
126 REQUIRE(cloned->name() == "clone");
127 REQUIRE(logger->sinks() == cloned->sinks());
128 REQUIRE(logger->level() == cloned->level());
129 REQUIRE(logger->flush_level() == cloned->flush_level());
130
131 logger->info("Some message 1");
132 cloned->info("Some message 2");
133
134 spdlog::details::os::sleep_for_millis(100);
135
136 REQUIRE(test_sink->lines().size() == 2);
137 REQUIRE(test_sink->lines()[0] == "Some message 1");
138 REQUIRE(test_sink->lines()[1] == "Some message 2");
139
140 spdlog::drop_all();
141}
142
143TEST_CASE("to_hex", "[to_hex]")
144{
145 std::ostringstream oss;
146 auto oss_sink = std::make_shared<spdlog::sinks::ostream_sink_mt>(oss);
147 spdlog::logger oss_logger("oss", oss_sink);
148
149 std::vector<unsigned char> v{9, 0xa, 0xb, 0xc, 0xff, 0xff};
150 oss_logger.info("{}", spdlog::to_hex(v));
151
152 auto output = oss.str();
153 REQUIRE(ends_with(output, "0000: 09 0a 0b 0c ff ff" + std::string(spdlog::details::os::default_eol)));
154}
155
156TEST_CASE("to_hex_upper", "[to_hex]")
157{
158 std::ostringstream oss;
159 auto oss_sink = std::make_shared<spdlog::sinks::ostream_sink_mt>(oss);
160 spdlog::logger oss_logger("oss", oss_sink);
161
162 std::vector<unsigned char> v{9, 0xa, 0xb, 0xc, 0xff, 0xff};
163 oss_logger.info("{:X}", spdlog::to_hex(v));
164
165 auto output = oss.str();
166 REQUIRE(ends_with(output, "0000: 09 0A 0B 0C FF FF" + std::string(spdlog::details::os::default_eol)));
167}
168
169TEST_CASE("to_hex_no_delimiter", "[to_hex]")
170{
171 std::ostringstream oss;
172 auto oss_sink = std::make_shared<spdlog::sinks::ostream_sink_mt>(oss);
173 spdlog::logger oss_logger("oss", oss_sink);
174
175 std::vector<unsigned char> v{9, 0xa, 0xb, 0xc, 0xff, 0xff};
176 oss_logger.info("{:sX}", spdlog::to_hex(v));
177
178 auto output = oss.str();
179 REQUIRE(ends_with(output, "0000: 090A0B0CFFFF" + std::string(spdlog::details::os::default_eol)));
180}
181
182TEST_CASE("to_hex_show_ascii", "[to_hex]")
183{
184 std::ostringstream oss;
185 auto oss_sink = std::make_shared<spdlog::sinks::ostream_sink_mt>(oss);
186 spdlog::logger oss_logger("oss", oss_sink);
187
188 std::vector<unsigned char> v{9, 0xa, 0xb, 0x41, 0xc, 0x4b, 0xff, 0xff};
189 oss_logger.info("{:Xsa}", spdlog::to_hex(v, 8));
190
191 REQUIRE(ends_with(oss.str(), "0000: 090A0B410C4BFFFF ...A.K.." + std::string(spdlog::details::os::default_eol)));
192}
193
194TEST_CASE("to_hex_different_size_per_line", "[to_hex]")
195{
196 std::ostringstream oss;
197 auto oss_sink = std::make_shared<spdlog::sinks::ostream_sink_mt>(oss);
198 spdlog::logger oss_logger("oss", oss_sink);
199
200 std::vector<unsigned char> v{9, 0xa, 0xb, 0x41, 0xc, 0x4b, 0xff, 0xff};
201
202 oss_logger.info("{:Xsa}", spdlog::to_hex(v, 10));
203 REQUIRE(ends_with(oss.str(), "0000: 090A0B410C4BFFFF ...A.K.." + std::string(spdlog::details::os::default_eol)));
204
205 oss_logger.info("{:Xs}", spdlog::to_hex(v, 10));
206 REQUIRE(ends_with(oss.str(), "0000: 090A0B410C4BFFFF" + std::string(spdlog::details::os::default_eol)));
207
208 oss_logger.info("{:Xsa}", spdlog::to_hex(v, 6));
209 REQUIRE(ends_with(oss.str(), "0000: 090A0B410C4B ...A.K" + std::string(spdlog::details::os::default_eol) + "0006: FFFF .." +
210 std::string(spdlog::details::os::default_eol)));
211
212 oss_logger.info("{:Xs}", spdlog::to_hex(v, 6));
213 REQUIRE(ends_with(oss.str(), "0000: 090A0B410C4B" + std::string(spdlog::details::os::default_eol) + "0006: FFFF" +
214 std::string(spdlog::details::os::default_eol)));
215}
216
217TEST_CASE("to_hex_no_ascii", "[to_hex]")
218{
219 std::ostringstream oss;
220 auto oss_sink = std::make_shared<spdlog::sinks::ostream_sink_mt>(oss);
221 spdlog::logger oss_logger("oss", oss_sink);
222
223 std::vector<unsigned char> v{9, 0xa, 0xb, 0x41, 0xc, 0x4b, 0xff, 0xff};
224 oss_logger.info("{:Xs}", spdlog::to_hex(v, 8));
225
226 REQUIRE(ends_with(oss.str(), "0000: 090A0B410C4BFFFF" + std::string(spdlog::details::os::default_eol)));
227
228 oss_logger.info("{:Xsna}", spdlog::to_hex(v, 8));
229
230 REQUIRE(ends_with(oss.str(), "090A0B410C4BFFFF" + std::string(spdlog::details::os::default_eol)));
231}
232
233TEST_CASE("default logger API", "[default logger]")
234{
235 std::ostringstream oss;
236 auto oss_sink = std::make_shared<spdlog::sinks::ostream_sink_mt>(oss);
237
238 spdlog::set_default_logger(std::make_shared<spdlog::logger>("oss", oss_sink));
239 spdlog::set_pattern("*** %v");
240
241 spdlog::default_logger()->set_level(spdlog::level::trace);
242 spdlog::trace("hello trace");
243 REQUIRE(oss.str() == "*** hello trace" + std::string(spdlog::details::os::default_eol));
244
245 oss.str("");
246 spdlog::debug("hello debug");
247 REQUIRE(oss.str() == "*** hello debug" + std::string(spdlog::details::os::default_eol));
248
249 oss.str("");
250 spdlog::info("Hello");
251 REQUIRE(oss.str() == "*** Hello" + std::string(spdlog::details::os::default_eol));
252
253 oss.str("");
254 spdlog::warn("Hello again {}", 2);
255 REQUIRE(oss.str() == "*** Hello again 2" + std::string(spdlog::details::os::default_eol));
256
257 oss.str("");
258 spdlog::error(123);
259 REQUIRE(oss.str() == "*** 123" + std::string(spdlog::details::os::default_eol));
260
261 oss.str("");
262 spdlog::critical(std::string("some string"));
263 REQUIRE(oss.str() == "*** some string" + std::string(spdlog::details::os::default_eol));
264
265 oss.str("");
266 spdlog::set_level(spdlog::level::info);
267 spdlog::debug("should not be logged");
268 REQUIRE(oss.str().empty());
269 spdlog::drop_all();
270 spdlog::set_pattern("%v");
271}
272