Branch data Line data Source code
1 : : // Copyright (c) 2019-2022 The Bitcoin Core developers
2 : : // Distributed under the MIT software license, see the accompanying
3 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 : :
5 : : #include <init/common.h>
6 : : #include <logging.h>
7 : : #include <logging/timer.h>
8 : : #include <test/util/setup_common.h>
9 : : #include <util/string.h>
10 : :
11 : : #include <chrono>
12 : : #include <fstream>
13 : : #include <iostream>
14 : : #include <unordered_map>
15 : : #include <utility>
16 : : #include <vector>
17 : :
18 : : #include <boost/test/unit_test.hpp>
19 : :
20 : : using util::SplitString;
21 : : using util::TrimString;
22 : :
23 : : BOOST_FIXTURE_TEST_SUITE(logging_tests, BasicTestingSetup)
24 : :
25 : 3 : static void ResetLogger()
26 : : {
27 : 3 : LogInstance().SetLogLevel(BCLog::DEFAULT_LOG_LEVEL);
28 [ + - ]: 3 : LogInstance().SetCategoryLogLevel({});
29 : 3 : }
30 : :
31 : : struct LogSetup : public BasicTestingSetup {
32 : : fs::path prev_log_path;
33 : : fs::path tmp_log_path;
34 : : bool prev_reopen_file;
35 : : bool prev_print_to_file;
36 : : bool prev_log_timestamps;
37 : : bool prev_log_threadnames;
38 : : bool prev_log_sourcelocations;
39 : : std::unordered_map<BCLog::LogFlags, BCLog::Level> prev_category_levels;
40 : : BCLog::Level prev_log_level;
41 : :
42 [ + - ]: 6 : LogSetup() : prev_log_path{LogInstance().m_file_path},
43 [ + - + - ]: 12 : tmp_log_path{m_args.GetDataDirBase() / "tmp_debug.log"},
44 [ + - + - ]: 6 : prev_reopen_file{LogInstance().m_reopen_file},
45 [ + - ]: 6 : prev_print_to_file{LogInstance().m_print_to_file},
46 [ + - ]: 6 : prev_log_timestamps{LogInstance().m_log_timestamps},
47 [ + - ]: 6 : prev_log_threadnames{LogInstance().m_log_threadnames},
48 [ + - ]: 6 : prev_log_sourcelocations{LogInstance().m_log_sourcelocations},
49 [ + - + - ]: 6 : prev_category_levels{LogInstance().CategoryLevels()},
50 [ + - + - : 12 : prev_log_level{LogInstance().LogLevel()}
+ - ]
51 : : {
52 [ + - + - ]: 6 : LogInstance().m_file_path = tmp_log_path;
53 [ + - + - ]: 6 : LogInstance().m_reopen_file = true;
54 [ + - ]: 6 : LogInstance().m_print_to_file = true;
55 [ + - ]: 6 : LogInstance().m_log_timestamps = false;
56 [ + - ]: 6 : LogInstance().m_log_threadnames = false;
57 : :
58 : : // Prevent tests from failing when the line number of the logs changes.
59 [ + - ]: 6 : LogInstance().m_log_sourcelocations = false;
60 : :
61 [ + - + - ]: 6 : LogInstance().SetLogLevel(BCLog::Level::Debug);
62 [ + - + - ]: 6 : LogInstance().SetCategoryLogLevel({});
63 [ + - ]: 12 : }
64 : :
65 : 6 : ~LogSetup()
66 : : {
67 : 6 : LogInstance().m_file_path = prev_log_path;
68 : 6 : LogPrintf("Sentinel log to reopen log file\n");
69 : 6 : LogInstance().m_print_to_file = prev_print_to_file;
70 : 6 : LogInstance().m_reopen_file = prev_reopen_file;
71 : 6 : LogInstance().m_log_timestamps = prev_log_timestamps;
72 : 6 : LogInstance().m_log_threadnames = prev_log_threadnames;
73 : 6 : LogInstance().m_log_sourcelocations = prev_log_sourcelocations;
74 : 6 : LogInstance().SetLogLevel(prev_log_level);
75 : 6 : LogInstance().SetCategoryLogLevel(prev_category_levels);
76 : 18 : }
77 : : };
78 : :
79 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(logging_timer)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
80 : : {
81 [ + - + - ]: 2 : auto micro_timer = BCLog::Timer<std::chrono::microseconds>("tests", "end_msg");
82 [ + - ]: 1 : const std::string_view result_prefix{"tests: msg ("};
83 [ + - + - : 2 : BOOST_CHECK_EQUAL(micro_timer.LogMsg("msg").substr(0, result_prefix.size()), result_prefix);
+ - + - ]
84 : 1 : }
85 : :
86 [ + - + - : 7 : BOOST_FIXTURE_TEST_CASE(logging_LogPrintStr, LogSetup)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
87 : : {
88 : 1 : LogInstance().m_log_sourcelocations = true;
89 : 1 : LogInstance().LogPrintStr("foo1: bar1", "fn1", "src1", 1, BCLog::LogFlags::NET, BCLog::Level::Debug);
90 : 1 : LogInstance().LogPrintStr("foo2: bar2", "fn2", "src2", 2, BCLog::LogFlags::NET, BCLog::Level::Info);
91 : 1 : LogInstance().LogPrintStr("foo3: bar3", "fn3", "src3", 3, BCLog::LogFlags::ALL, BCLog::Level::Debug);
92 : 1 : LogInstance().LogPrintStr("foo4: bar4", "fn4", "src4", 4, BCLog::LogFlags::ALL, BCLog::Level::Info);
93 : 1 : LogInstance().LogPrintStr("foo5: bar5", "fn5", "src5", 5, BCLog::LogFlags::NONE, BCLog::Level::Debug);
94 : 1 : LogInstance().LogPrintStr("foo6: bar6", "fn6", "src6", 6, BCLog::LogFlags::NONE, BCLog::Level::Info);
95 : 1 : std::ifstream file{tmp_log_path};
96 : 1 : std::vector<std::string> log_lines;
97 [ + - + + ]: 7 : for (std::string log; std::getline(file, log);) {
98 [ + - ]: 6 : log_lines.push_back(log);
99 : 0 : }
100 : 1 : std::vector<std::string> expected = {
101 : : "[src1:1] [fn1] [net] foo1: bar1",
102 : : "[src2:2] [fn2] [net:info] foo2: bar2",
103 : : "[src3:3] [fn3] [debug] foo3: bar3",
104 : : "[src4:4] [fn4] foo4: bar4",
105 : : "[src5:5] [fn5] [debug] foo5: bar5",
106 : : "[src6:6] [fn6] foo6: bar6",
107 [ + - ]: 1 : };
108 [ + - + - : 2 : BOOST_CHECK_EQUAL_COLLECTIONS(log_lines.begin(), log_lines.end(), expected.begin(), expected.end());
+ - ]
109 : 1 : }
110 : :
111 [ + - + - : 7 : BOOST_FIXTURE_TEST_CASE(logging_LogPrintMacrosDeprecated, LogSetup)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
112 : : {
113 : 1 : LogPrintf("foo5: %s\n", "bar5");
114 [ - + ]: 1 : LogPrintLevel(BCLog::NET, BCLog::Level::Trace, "foo4: %s\n", "bar4"); // not logged
115 [ + - ]: 1 : LogPrintLevel(BCLog::NET, BCLog::Level::Debug, "foo7: %s\n", "bar7");
116 [ + - ]: 1 : LogPrintLevel(BCLog::NET, BCLog::Level::Info, "foo8: %s\n", "bar8");
117 [ + - ]: 1 : LogPrintLevel(BCLog::NET, BCLog::Level::Warning, "foo9: %s\n", "bar9");
118 [ + - ]: 1 : LogPrintLevel(BCLog::NET, BCLog::Level::Error, "foo10: %s\n", "bar10");
119 : 1 : std::ifstream file{tmp_log_path};
120 : 1 : std::vector<std::string> log_lines;
121 [ + - + + ]: 6 : for (std::string log; std::getline(file, log);) {
122 [ + - ]: 5 : log_lines.push_back(log);
123 : 0 : }
124 : 1 : std::vector<std::string> expected = {
125 : : "foo5: bar5",
126 : : "[net] foo7: bar7",
127 : : "[net:info] foo8: bar8",
128 : : "[net:warning] foo9: bar9",
129 : : "[net:error] foo10: bar10",
130 [ + - ]: 1 : };
131 [ + - + - : 2 : BOOST_CHECK_EQUAL_COLLECTIONS(log_lines.begin(), log_lines.end(), expected.begin(), expected.end());
+ - ]
132 : 1 : }
133 : :
134 [ + - + - : 7 : BOOST_FIXTURE_TEST_CASE(logging_LogPrintMacros, LogSetup)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
135 : : {
136 [ - + ]: 1 : LogTrace(BCLog::NET, "foo6: %s", "bar6"); // not logged
137 [ + - ]: 1 : LogDebug(BCLog::NET, "foo7: %s", "bar7");
138 : 1 : LogInfo("foo8: %s", "bar8");
139 : 1 : LogWarning("foo9: %s", "bar9");
140 : 2 : LogError("foo10: %s", "bar10");
141 : 1 : std::ifstream file{tmp_log_path};
142 : 1 : std::vector<std::string> log_lines;
143 [ + - + + ]: 5 : for (std::string log; std::getline(file, log);) {
144 [ + - ]: 4 : log_lines.push_back(log);
145 : 0 : }
146 : 1 : std::vector<std::string> expected = {
147 : : "[net] foo7: bar7",
148 : : "foo8: bar8",
149 : : "[warning] foo9: bar9",
150 : : "[error] foo10: bar10",
151 [ + - ]: 1 : };
152 [ + - + - : 2 : BOOST_CHECK_EQUAL_COLLECTIONS(log_lines.begin(), log_lines.end(), expected.begin(), expected.end());
+ - ]
153 : 1 : }
154 : :
155 [ + - + - : 7 : BOOST_FIXTURE_TEST_CASE(logging_LogPrintMacros_CategoryName, LogSetup)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
156 : : {
157 : 1 : LogInstance().EnableCategory(BCLog::LogFlags::ALL);
158 : 1 : const auto concatenated_category_names = LogInstance().LogCategoriesString();
159 : 1 : std::vector<std::pair<BCLog::LogFlags, std::string>> expected_category_names;
160 [ + - ]: 1 : const auto category_names = SplitString(concatenated_category_names, ',');
161 [ + + ]: 29 : for (const auto& category_name : category_names) {
162 : 28 : BCLog::LogFlags category;
163 [ + - ]: 28 : const auto trimmed_category_name = TrimString(category_name);
164 [ + - + - : 56 : BOOST_REQUIRE(GetLogCategory(category, trimmed_category_name));
+ - + - ]
165 [ + - ]: 28 : expected_category_names.emplace_back(category, trimmed_category_name);
166 : 28 : }
167 : :
168 : 1 : std::vector<std::string> expected;
169 [ + - + + ]: 29 : for (const auto& [category, name] : expected_category_names) {
170 [ + - + - : 28 : LogDebug(category, "foo: %s\n", "bar");
+ - ]
171 [ + - ]: 28 : std::string expected_log = "[";
172 [ + - ]: 28 : expected_log += name;
173 [ + - ]: 28 : expected_log += "] foo: bar";
174 [ + - ]: 28 : expected.push_back(expected_log);
175 : 28 : }
176 : :
177 [ + - ]: 1 : std::ifstream file{tmp_log_path};
178 : 1 : std::vector<std::string> log_lines;
179 [ + - + + ]: 29 : for (std::string log; std::getline(file, log);) {
180 [ + - ]: 28 : log_lines.push_back(log);
181 : 0 : }
182 [ + - + - : 2 : BOOST_CHECK_EQUAL_COLLECTIONS(log_lines.begin(), log_lines.end(), expected.begin(), expected.end());
+ - ]
183 : 1 : }
184 : :
185 [ + - + - : 7 : BOOST_FIXTURE_TEST_CASE(logging_SeverityLevels, LogSetup)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
186 : : {
187 : 1 : LogInstance().EnableCategory(BCLog::LogFlags::ALL);
188 : :
189 : 1 : LogInstance().SetLogLevel(BCLog::Level::Debug);
190 : 1 : LogInstance().SetCategoryLogLevel(/*category_str=*/"net", /*level_str=*/"info");
191 : :
192 : : // Global log level
193 [ + - ]: 1 : LogPrintLevel(BCLog::HTTP, BCLog::Level::Info, "foo1: %s\n", "bar1");
194 [ - + ]: 1 : LogPrintLevel(BCLog::MEMPOOL, BCLog::Level::Trace, "foo2: %s. This log level is lower than the global one.\n", "bar2");
195 [ + - ]: 1 : LogPrintLevel(BCLog::VALIDATION, BCLog::Level::Warning, "foo3: %s\n", "bar3");
196 [ + - ]: 1 : LogPrintLevel(BCLog::RPC, BCLog::Level::Error, "foo4: %s\n", "bar4");
197 : :
198 : : // Category-specific log level
199 [ + - ]: 1 : LogPrintLevel(BCLog::NET, BCLog::Level::Warning, "foo5: %s\n", "bar5");
200 [ - + ]: 1 : LogPrintLevel(BCLog::NET, BCLog::Level::Debug, "foo6: %s. This log level is the same as the global one but lower than the category-specific one, which takes precedence. \n", "bar6");
201 [ + - ]: 1 : LogPrintLevel(BCLog::NET, BCLog::Level::Error, "foo7: %s\n", "bar7");
202 : :
203 : 1 : std::vector<std::string> expected = {
204 : : "[http:info] foo1: bar1",
205 : : "[validation:warning] foo3: bar3",
206 : : "[rpc:error] foo4: bar4",
207 : : "[net:warning] foo5: bar5",
208 : : "[net:error] foo7: bar7",
209 : 1 : };
210 [ + - ]: 1 : std::ifstream file{tmp_log_path};
211 : 1 : std::vector<std::string> log_lines;
212 [ + - + + ]: 6 : for (std::string log; std::getline(file, log);) {
213 [ + - ]: 5 : log_lines.push_back(log);
214 : 0 : }
215 [ + - + - : 2 : BOOST_CHECK_EQUAL_COLLECTIONS(log_lines.begin(), log_lines.end(), expected.begin(), expected.end());
+ - ]
216 : 1 : }
217 : :
218 [ + - + - : 7 : BOOST_FIXTURE_TEST_CASE(logging_Conf, LogSetup)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
219 : : {
220 : : // Set global log level
221 : 1 : {
222 : 1 : ResetLogger();
223 : 1 : ArgsManager args;
224 [ + - + - : 2 : args.AddArg("-loglevel", "...", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
+ - ]
225 : 1 : const char* argv_test[] = {"bitcoind", "-loglevel=debug"};
226 [ + - ]: 1 : std::string err;
227 [ + - + - : 2 : BOOST_REQUIRE(args.ParseParameters(2, argv_test, err));
+ - + - ]
228 : :
229 [ + - ]: 1 : auto result = init::SetLoggingLevel(args);
230 [ + - + - : 2 : BOOST_REQUIRE(result);
+ - ]
231 [ + - + - : 1 : BOOST_CHECK_EQUAL(LogInstance().LogLevel(), BCLog::Level::Debug);
+ - ]
232 : 1 : }
233 : :
234 : : // Set category-specific log level
235 : 1 : {
236 : 1 : ResetLogger();
237 : 1 : ArgsManager args;
238 [ + - + - : 2 : args.AddArg("-loglevel", "...", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
+ - ]
239 : 1 : const char* argv_test[] = {"bitcoind", "-loglevel=net:trace"};
240 [ + - ]: 1 : std::string err;
241 [ + - + - : 2 : BOOST_REQUIRE(args.ParseParameters(2, argv_test, err));
+ - + - ]
242 : :
243 [ + - ]: 1 : auto result = init::SetLoggingLevel(args);
244 [ + - + - : 2 : BOOST_REQUIRE(result);
+ - ]
245 [ + - + - : 1 : BOOST_CHECK_EQUAL(LogInstance().LogLevel(), BCLog::DEFAULT_LOG_LEVEL);
+ - ]
246 : :
247 [ + - + - ]: 1 : const auto& category_levels{LogInstance().CategoryLevels()};
248 : 1 : const auto net_it{category_levels.find(BCLog::LogFlags::NET)};
249 [ + - + - : 2 : BOOST_REQUIRE(net_it != category_levels.end());
+ - ]
250 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(net_it->second, BCLog::Level::Trace);
251 : 1 : }
252 : :
253 : : // Set both global log level and category-specific log level
254 : 1 : {
255 : 1 : ResetLogger();
256 : 1 : ArgsManager args;
257 [ + - + - : 2 : args.AddArg("-loglevel", "...", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
+ - ]
258 : 1 : const char* argv_test[] = {"bitcoind", "-loglevel=debug", "-loglevel=net:trace", "-loglevel=http:info"};
259 [ + - ]: 1 : std::string err;
260 [ + - + - : 2 : BOOST_REQUIRE(args.ParseParameters(4, argv_test, err));
+ - + - ]
261 : :
262 [ + - ]: 1 : auto result = init::SetLoggingLevel(args);
263 [ + - + - : 2 : BOOST_REQUIRE(result);
+ - ]
264 [ + - + - : 1 : BOOST_CHECK_EQUAL(LogInstance().LogLevel(), BCLog::Level::Debug);
+ - ]
265 : :
266 [ + - + - ]: 1 : const auto& category_levels{LogInstance().CategoryLevels()};
267 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(category_levels.size(), 2);
268 : :
269 : 1 : const auto net_it{category_levels.find(BCLog::LogFlags::NET)};
270 [ + - + - : 2 : BOOST_CHECK(net_it != category_levels.end());
+ - ]
271 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(net_it->second, BCLog::Level::Trace);
272 : :
273 : 1 : const auto http_it{category_levels.find(BCLog::LogFlags::HTTP)};
274 [ + - + - : 2 : BOOST_CHECK(http_it != category_levels.end());
+ - ]
275 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(http_it->second, BCLog::Level::Info);
276 : 1 : }
277 : 1 : }
278 : :
279 : : BOOST_AUTO_TEST_SUITE_END()
|