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