1 /**
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "os/file.h"
17 #include "os/thread.h"
18 #include "utils/logger.h"
19 #include "utils/string_helpers.h"
20
21 #include <cstdio>
22
23 #include <fstream>
24 #include <regex>
25 #include <streambuf>
26
27 #include <gtest/gtest.h>
28
29 namespace panda::test {
30
31 class LoggerTest : public testing::Test {
32 public:
SetUpTestSuite()33 static void SetUpTestSuite()
34 {
35 #ifndef HOST_UT
36 system("mount -o rw,remount /");
37 #endif
38 }
39 };
40
HWTEST_F(LoggerTest, Initialization, testing::ext::TestSize.Level0)41 HWTEST_F(LoggerTest, Initialization, testing::ext::TestSize.Level0)
42 {
43 EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
44
45 testing::FLAGS_gtest_death_test_style = "fast";
46 testing::internal::CaptureStderr();
47
48 LOG(DEBUG, COMMON) << "1";
49 LOG(INFO, COMMON) << "2";
50 LOG(ERROR, COMMON) << "3";
51
52 std::string err = testing::internal::GetCapturedStderr();
53 EXPECT_EQ(err, "");
54
55 EXPECT_DEATH_IF_SUPPORTED(LOG(FATAL, COMMON) << "4", "");
56
57 Logger::InitializeStdLogging(Logger::Level::DEBUG, panda::LoggerComponentMaskAll);
58 EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
59
60 testing::internal::CaptureStderr();
61
62 LOG(DEBUG, COMMON) << "a";
63 LOG(INFO, COMMON) << "b";
64 LOG(ERROR, COMMON) << "c";
65
66 err = testing::internal::GetCapturedStderr();
67 uint32_t tid = os::thread::GetCurrentThreadId();
68 std::string res = helpers::string::Format(
69 #ifndef NDEBUG
70 "[TID %06x] D/common: a\n"
71 #endif
72 "[TID %06x] I/common: b\n"
73 "[TID %06x] E/common: c\n",
74 tid, tid, tid);
75 EXPECT_EQ(err, res);
76
77 EXPECT_DEATH_IF_SUPPORTED(LOG(FATAL, COMMON) << "d", "\\[TID [0-9a-f]{6}\\] F/common: d");
78
79 Logger::Destroy();
80 EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
81
82 testing::internal::CaptureStderr();
83
84 LOG(DEBUG, COMMON) << "1";
85 LOG(INFO, COMMON) << "2";
86 LOG(ERROR, COMMON) << "3";
87
88 err = testing::internal::GetCapturedStderr();
89 EXPECT_EQ(err, "");
90
91 EXPECT_DEATH_IF_SUPPORTED(LOG(FATAL, COMMON) << "4", "");
92 }
93
HWTEST_F(LoggerTest, LoggingExceptionsFatal, testing::ext::TestSize.Level0)94 HWTEST_F(LoggerTest, LoggingExceptionsFatal, testing::ext::TestSize.Level0)
95 {
96 testing::FLAGS_gtest_death_test_style = "fast";
97
98 panda::Logger::ComponentMask component_mask;
99 component_mask.set(Logger::Component::COMPILER);
100
101 Logger::InitializeStdLogging(Logger::Level::FATAL, component_mask);
102 EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::COMPILER));
103 EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ASSEMBLER));
104 EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::DISASSEMBLER));
105 EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::ERROR, Logger::Component::COMPILER));
106 EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::ERROR, Logger::Component::ASSEMBLER));
107 EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::ERROR, Logger::Component::DISASSEMBLER));
108
109 EXPECT_DEATH_IF_SUPPORTED(LOG(FATAL, COMPILER) << "d1", "\\[TID [0-9a-f]{6}\\] F/compiler: d1");
110 EXPECT_DEATH_IF_SUPPORTED(LOG(FATAL, ASSEMBLER) << "d2", "\\[TID [0-9a-f]{6}\\] F/assembler: d2");
111 EXPECT_DEATH_IF_SUPPORTED(LOG(FATAL, DISASSEMBLER) << "d3", "\\[TID [0-9a-f]{6}\\] F/disassembler: d3");
112
113 testing::internal::CaptureStderr();
114
115 LOG(ERROR, COMPILER) << "c";
116 LOG(ERROR, ASSEMBLER) << "a";
117 LOG(ERROR, DISASSEMBLER) << "d";
118
119 std::string err = testing::internal::GetCapturedStderr();
120 EXPECT_EQ(err, "");
121
122 Logger::Destroy();
123 }
124
HWTEST_F(LoggerTest, LoggingExceptionsError, testing::ext::TestSize.Level0)125 HWTEST_F(LoggerTest, LoggingExceptionsError, testing::ext::TestSize.Level0)
126 {
127 testing::FLAGS_gtest_death_test_style = "fast";
128
129 panda::Logger::ComponentMask component_mask;
130 component_mask.set(Logger::Component::COMPILER);
131
132 Logger::InitializeStdLogging(Logger::Level::ERROR, component_mask);
133 EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::COMPILER));
134 EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ASSEMBLER));
135 EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::DISASSEMBLER));
136 EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::ERROR, Logger::Component::COMPILER));
137 EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::ERROR, Logger::Component::ASSEMBLER));
138 EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::ERROR, Logger::Component::DISASSEMBLER));
139
140 EXPECT_DEATH_IF_SUPPORTED(LOG(FATAL, COMPILER) << "d1", "\\[TID [0-9a-f]{6}\\] F/compiler: d1");
141 EXPECT_DEATH_IF_SUPPORTED(LOG(FATAL, ASSEMBLER) << "d2", "\\[TID [0-9a-f]{6}\\] F/assembler: d2");
142 EXPECT_DEATH_IF_SUPPORTED(LOG(FATAL, DISASSEMBLER) << "d3", "\\[TID [0-9a-f]{6}\\] F/disassembler: d3");
143
144 testing::internal::CaptureStderr();
145
146 LOG(ERROR, COMPILER) << "c";
147 LOG(ERROR, ASSEMBLER) << "a";
148 LOG(ERROR, DISASSEMBLER) << "d";
149
150 std::string err = testing::internal::GetCapturedStderr();
151 uint32_t tid = os::thread::GetCurrentThreadId();
152 std::string res = helpers::string::Format("[TID %06x] E/compiler: c\n", tid);
153 EXPECT_EQ(err, res);
154
155 Logger::Destroy();
156 }
157
HWTEST_F(LoggerTest, FilterInfo, testing::ext::TestSize.Level0)158 HWTEST_F(LoggerTest, FilterInfo, testing::ext::TestSize.Level0)
159 {
160 Logger::InitializeStdLogging(Logger::Level::INFO, panda::LoggerComponentMaskAll);
161 EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
162
163 testing::internal::CaptureStderr();
164
165 LOG(DEBUG, COMMON) << "a";
166 LOG(INFO, COMMON) << "b";
167 LOG(ERROR, COMMON) << "c";
168
169 std::string err = testing::internal::GetCapturedStderr();
170 uint32_t tid = os::thread::GetCurrentThreadId();
171 std::string res = helpers::string::Format(
172 "[TID %06x] I/common: b\n"
173 "[TID %06x] E/common: c\n",
174 tid, tid);
175 EXPECT_EQ(err, res);
176
177 Logger::Destroy();
178 EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
179 }
180
HWTEST_F(LoggerTest, FilterError, testing::ext::TestSize.Level0)181 HWTEST_F(LoggerTest, FilterError, testing::ext::TestSize.Level0)
182 {
183 Logger::InitializeStdLogging(Logger::Level::ERROR, panda::LoggerComponentMaskAll);
184 EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
185
186 testing::internal::CaptureStderr();
187
188 LOG(DEBUG, COMMON) << "a";
189 LOG(INFO, COMMON) << "b";
190 LOG(ERROR, COMMON) << "c";
191
192 std::string err = testing::internal::GetCapturedStderr();
193 uint32_t tid = os::thread::GetCurrentThreadId();
194 std::string res = helpers::string::Format("[TID %06x] E/common: c\n", tid);
195 EXPECT_EQ(err, res);
196
197 Logger::Destroy();
198 EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
199 }
200
HWTEST_F(LoggerTest, FilterFatal, testing::ext::TestSize.Level0)201 HWTEST_F(LoggerTest, FilterFatal, testing::ext::TestSize.Level0)
202 {
203 Logger::InitializeStdLogging(Logger::Level::FATAL, panda::LoggerComponentMaskAll);
204 EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
205
206 testing::internal::CaptureStderr();
207
208 LOG(DEBUG, COMMON) << "a";
209 LOG(INFO, COMMON) << "b";
210 LOG(ERROR, COMMON) << "c";
211
212 std::string err = testing::internal::GetCapturedStderr();
213 EXPECT_EQ(err, "");
214
215 Logger::Destroy();
216 EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
217 }
218
HWTEST_F(LoggerTest, ComponentFilter, testing::ext::TestSize.Level0)219 HWTEST_F(LoggerTest, ComponentFilter, testing::ext::TestSize.Level0)
220 {
221 panda::Logger::ComponentMask component_mask;
222 component_mask.set(Logger::Component::COMPILER);
223 component_mask.set(Logger::Component::GC);
224
225 Logger::InitializeStdLogging(Logger::Level::INFO, component_mask);
226 EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::WARNING, Logger::Component::ALLOC));
227 EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::COMPILER));
228 EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::GC));
229
230 testing::internal::CaptureStderr();
231
232 LOG(INFO, COMMON) << "a";
233 LOG(INFO, COMPILER) << "b";
234 LOG(INFO, RUNTIME) << "c";
235 LOG(INFO, GC) << "d";
236
237 std::string err = testing::internal::GetCapturedStderr();
238 uint32_t tid = os::thread::GetCurrentThreadId();
239 std::string res = helpers::string::Format(
240 "[TID %06x] I/compiler: b\n"
241 "[TID %06x] I/gc: d\n",
242 tid, tid);
243 EXPECT_EQ(err, res);
244
245 Logger::Destroy();
246 EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
247 }
248
HWTEST_F(LoggerTest, FileLogging, testing::ext::TestSize.Level0)249 HWTEST_F(LoggerTest, FileLogging, testing::ext::TestSize.Level0)
250 {
251 uint32_t tid = os::thread::GetCurrentThreadId();
252 std::string log_filename = helpers::string::Format("/tmp/gtest_panda_logger_file_%06x", tid);
253
254 auto file = os::file::Open(log_filename, os::file::Mode::READWRITECREATE);
255 ASSERT_TRUE(file.IsValid());
256
257 Logger::InitializeFileLogging(log_filename, Logger::Level::INFO,
258 panda::Logger::ComponentMask().set(Logger::Component::COMMON));
259 EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
260 EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::COMMON));
261
262 LOG(DEBUG, COMMON) << "a";
263 LOG(INFO, COMMON) << "b";
264 LOG(ERROR, COMPILER) << "c";
265 LOG(ERROR, COMMON) << "d";
266
267 #if GTEST_HAS_DEATH_TEST
268 testing::FLAGS_gtest_death_test_style = "fast";
269
270 EXPECT_DEATH(LOG(FATAL, COMMON) << "e", "");
271
272 std::string res = helpers::string::Format(
273 "\\[TID %06x\\] I/common: b\n"
274 "\\[TID %06x\\] E/common: d\n"
275 "\\[TID [0-9a-f]{6}\\] F/common: e\n",
276 tid, tid);
277 std::regex e(res);
278 {
279 std::ifstream log_file_stream(log_filename);
280 std::string log_file_content((std::istreambuf_iterator<char>(log_file_stream)),
281 std::istreambuf_iterator<char>());
282 EXPECT_TRUE(std::regex_match(log_file_content, e));
283 }
284 #endif // GTEST_HAS_DEATH_TEST
285
286 EXPECT_EQ(std::remove(log_filename.c_str()), 0);
287
288 Logger::Destroy();
289 EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
290 }
291
HWTEST_F(LoggerTest, Multiline, testing::ext::TestSize.Level0)292 HWTEST_F(LoggerTest, Multiline, testing::ext::TestSize.Level0)
293 {
294 Logger::InitializeStdLogging(Logger::Level::INFO, panda::Logger::ComponentMask().set(Logger::Component::COMMON));
295 EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
296 EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::COMMON));
297
298 testing::internal::CaptureStderr();
299
300 LOG(INFO, COMMON) << "a\nb\nc\n\nd\n";
301
302 std::string err = testing::internal::GetCapturedStderr();
303 uint32_t tid = os::thread::GetCurrentThreadId();
304 std::string res = helpers::string::Format(
305 "[TID %06x] I/common: a\n"
306 "[TID %06x] I/common: b\n"
307 "[TID %06x] I/common: c\n"
308 "[TID %06x] I/common: \n"
309 "[TID %06x] I/common: d\n"
310 "[TID %06x] I/common: \n",
311 tid, tid, tid, tid, tid, tid);
312 EXPECT_EQ(err, res);
313
314 Logger::Destroy();
315 EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
316 }
317
HWTEST_F(LoggerTest, LogIf, testing::ext::TestSize.Level0)318 HWTEST_F(LoggerTest, LogIf, testing::ext::TestSize.Level0)
319 {
320 Logger::InitializeStdLogging(Logger::Level::INFO, panda::LoggerComponentMaskAll);
321 EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
322
323 testing::internal::CaptureStderr();
324
325 LOG_IF(true, INFO, COMMON) << "a";
326 LOG_IF(false, INFO, COMMON) << "b";
327
328 std::string err = testing::internal::GetCapturedStderr();
329 uint32_t tid = os::thread::GetCurrentThreadId();
330 std::string res = helpers::string::Format("[TID %06x] I/common: a\n", tid);
331 EXPECT_EQ(err, res);
332
333 Logger::Destroy();
334 EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
335 }
336
HWTEST_F(LoggerTest, LogOnce, testing::ext::TestSize.Level0)337 HWTEST_F(LoggerTest, LogOnce, testing::ext::TestSize.Level0)
338 {
339 Logger::InitializeStdLogging(Logger::Level::INFO, panda::LoggerComponentMaskAll);
340 EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
341
342 testing::internal::CaptureStderr();
343
344 LOG_ONCE(INFO, COMMON) << "a";
345 for (int i = 0; i < 10; ++i) {
346 LOG_ONCE(INFO, COMMON) << "b";
347 }
348 LOG_ONCE(INFO, COMMON) << "c";
349
350 std::string err = testing::internal::GetCapturedStderr();
351 uint32_t tid = os::thread::GetCurrentThreadId();
352 std::string res = helpers::string::Format(
353 "[TID %06x] I/common: a\n"
354 "[TID %06x] I/common: b\n"
355 "[TID %06x] I/common: c\n",
356 tid, tid, tid);
357 EXPECT_EQ(err, res);
358
359 Logger::Destroy();
360 EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
361 }
362
363 } // namespace panda::test
364