• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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/thread.h"
17 #include "utils/logger.h"
18 #include "utils/string_helpers.h"
19 
20 #include <cstdio>
21 
22 #include <fstream>
23 #include <regex>
24 #include <streambuf>
25 
26 #include <gtest/gtest.h>
27 
28 namespace panda::test {
29 
TEST(Logger,Initialization)30 TEST(Logger, Initialization)
31 {
32     EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
33 
34     testing::FLAGS_gtest_death_test_style = "fast";
35     testing::internal::CaptureStderr();
36 
37     LOG(DEBUG, COMMON) << "1";
38     LOG(INFO, COMMON) << "2";
39     LOG(ERROR, COMMON) << "3";
40 
41     std::string err = testing::internal::GetCapturedStderr();
42     EXPECT_EQ(err, "");
43 
44     EXPECT_DEATH_IF_SUPPORTED(LOG(FATAL, COMMON) << "4", "");
45 
46     Logger::InitializeStdLogging(Logger::Level::DEBUG, panda::LoggerComponentMaskAll);
47     EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
48 
49     testing::internal::CaptureStderr();
50 
51     LOG(DEBUG, COMMON) << "a";
52     LOG(INFO, COMMON) << "b";
53     LOG(ERROR, COMMON) << "c";
54 
55     err = testing::internal::GetCapturedStderr();
56     uint32_t tid = os::thread::GetCurrentThreadId();
57     std::string res = helpers::string::Format(
58 #ifndef NDEBUG
59         "[TID %06x] D/common: a\n"
60 #endif
61         "[TID %06x] I/common: b\n"
62         "[TID %06x] E/common: c\n",
63         tid, tid, tid);
64     EXPECT_EQ(err, res);
65 
66     EXPECT_DEATH_IF_SUPPORTED(LOG(FATAL, COMMON) << "d", "\\[TID [0-9a-f]{6}\\] F/common: d");
67 
68     Logger::Destroy();
69     EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
70 
71     testing::internal::CaptureStderr();
72 
73     LOG(DEBUG, COMMON) << "1";
74     LOG(INFO, COMMON) << "2";
75     LOG(ERROR, COMMON) << "3";
76 
77     err = testing::internal::GetCapturedStderr();
78     EXPECT_EQ(err, "");
79 
80     EXPECT_DEATH_IF_SUPPORTED(LOG(FATAL, COMMON) << "4", "");
81 }
82 
TEST(Logger,FilterInfo)83 TEST(Logger, FilterInfo)
84 {
85     Logger::InitializeStdLogging(Logger::Level::INFO, panda::LoggerComponentMaskAll);
86     EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
87 
88     testing::internal::CaptureStderr();
89 
90     LOG(DEBUG, COMMON) << "a";
91     LOG(INFO, COMMON) << "b";
92     LOG(ERROR, COMMON) << "c";
93 
94     std::string err = testing::internal::GetCapturedStderr();
95     uint32_t tid = os::thread::GetCurrentThreadId();
96     std::string res = helpers::string::Format(
97         "[TID %06x] I/common: b\n"
98         "[TID %06x] E/common: c\n",
99         tid, tid);
100     EXPECT_EQ(err, res);
101 
102     Logger::Destroy();
103     EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
104 }
105 
TEST(Logger,FilterError)106 TEST(Logger, FilterError)
107 {
108     Logger::InitializeStdLogging(Logger::Level::ERROR, panda::LoggerComponentMaskAll);
109     EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
110 
111     testing::internal::CaptureStderr();
112 
113     LOG(DEBUG, COMMON) << "a";
114     LOG(INFO, COMMON) << "b";
115     LOG(ERROR, COMMON) << "c";
116 
117     std::string err = testing::internal::GetCapturedStderr();
118     uint32_t tid = os::thread::GetCurrentThreadId();
119     std::string res = helpers::string::Format("[TID %06x] E/common: c\n", tid);
120     EXPECT_EQ(err, res);
121 
122     Logger::Destroy();
123     EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
124 }
125 
TEST(Logger,FilterFatal)126 TEST(Logger, FilterFatal)
127 {
128     Logger::InitializeStdLogging(Logger::Level::FATAL, panda::LoggerComponentMaskAll);
129     EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
130 
131     testing::internal::CaptureStderr();
132 
133     LOG(DEBUG, COMMON) << "a";
134     LOG(INFO, COMMON) << "b";
135     LOG(ERROR, COMMON) << "c";
136 
137     std::string err = testing::internal::GetCapturedStderr();
138     uint32_t tid = os::thread::GetCurrentThreadId();
139     EXPECT_EQ(err, "");
140 
141     Logger::Destroy();
142     EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
143 }
144 
TEST(Logger,ComponentFilter)145 TEST(Logger, ComponentFilter)
146 {
147     panda::Logger::ComponentMask component_mask;
148     component_mask.set(Logger::Component::CLASS_LINKER);
149     component_mask.set(Logger::Component::GC);
150 
151     Logger::InitializeStdLogging(Logger::Level::INFO, component_mask);
152     EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
153     EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::CLASS_LINKER));
154     EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::GC));
155 
156     testing::internal::CaptureStderr();
157 
158     LOG(INFO, COMMON) << "a";
159     LOG(INFO, CLASS_LINKER) << "b";
160     LOG(INFO, RUNTIME) << "c";
161     LOG(INFO, GC) << "d";
162 
163     std::string err = testing::internal::GetCapturedStderr();
164     uint32_t tid = os::thread::GetCurrentThreadId();
165     std::string res = helpers::string::Format(
166         "[TID %06x] I/classlinker: b\n"
167         "[TID %06x] I/gc: d\n",
168         tid, tid);
169     EXPECT_EQ(err, res);
170 
171     Logger::Destroy();
172     EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
173 }
174 
TEST(Logger,FileLogging)175 TEST(Logger, FileLogging)
176 {
177     uint32_t tid = os::thread::GetCurrentThreadId();
178     std::string log_filename = helpers::string::Format("/tmp/gtest_panda_logger_file_%06x", tid);
179 
180     Logger::InitializeFileLogging(log_filename, Logger::Level::INFO,
181                                   panda::Logger::ComponentMask().set(Logger::Component::COMMON));
182     EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
183     EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::COMMON));
184 
185     LOG(DEBUG, COMMON) << "a";
186     LOG(INFO, COMMON) << "b";
187     LOG(ERROR, CLASS_LINKER) << "c";
188     LOG(ERROR, COMMON) << "d";
189 
190 #if GTEST_HAS_DEATH_TEST
191     testing::FLAGS_gtest_death_test_style = "fast";
192 
193     EXPECT_DEATH(LOG(FATAL, COMMON) << "e", "");
194 
195     std::string res = helpers::string::Format(
196         "\\[TID %06x\\] I/common: b\n"
197         "\\[TID %06x\\] E/common: d\n"
198         "\\[TID [0-9a-f]{6}\\] F/common: e\n",
199         tid, tid);
200     std::regex e(res);
201     {
202         std::ifstream log_file_stream(log_filename);
203         std::string log_file_content((std::istreambuf_iterator<char>(log_file_stream)),
204                                      std::istreambuf_iterator<char>());
205         EXPECT_TRUE(std::regex_match(log_file_content, e));
206     }
207 #endif  // GTEST_HAS_DEATH_TEST
208 
209     EXPECT_EQ(std::remove(log_filename.c_str()), 0);
210 
211     Logger::Destroy();
212     EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
213 }
214 
TEST(Logger,Multiline)215 TEST(Logger, Multiline)
216 {
217     Logger::InitializeStdLogging(Logger::Level::INFO, panda::Logger::ComponentMask().set(Logger::Component::COMMON));
218     EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
219     EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::COMMON));
220 
221     testing::internal::CaptureStderr();
222 
223     LOG(INFO, COMMON) << "a\nb\nc\n\nd\n";
224 
225     std::string err = testing::internal::GetCapturedStderr();
226     uint32_t tid = os::thread::GetCurrentThreadId();
227     std::string res = helpers::string::Format(
228         "[TID %06x] I/common: a\n"
229         "[TID %06x] I/common: b\n"
230         "[TID %06x] I/common: c\n"
231         "[TID %06x] I/common: \n"
232         "[TID %06x] I/common: d\n"
233         "[TID %06x] I/common: \n",
234         tid, tid, tid, tid, tid, tid);
235     EXPECT_EQ(err, res);
236 
237     Logger::Destroy();
238     EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
239 }
240 
TEST(Logger,PLog)241 TEST(Logger, PLog)
242 {
243     Logger::InitializeStdLogging(Logger::Level::INFO, panda::LoggerComponentMaskAll);
244     EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
245 
246     testing::internal::CaptureStderr();
247 
248     int errnum = errno;
249 
250     errno = EEXIST;
251     PLOG(ERROR, COMMON) << "a";
252     errno = EACCES;
253     PLOG(INFO, CLASS_LINKER) << "b";
254     errno = errnum;
255 
256     std::string err = testing::internal::GetCapturedStderr();
257     uint32_t tid = os::thread::GetCurrentThreadId();
258     std::string res = helpers::string::Format(
259         "[TID %06x] E/common: a: File exists\n"
260         "[TID %06x] I/classlinker: b: Permission denied\n",
261         tid, tid, tid, tid);
262     EXPECT_EQ(err, res);
263 
264     Logger::Destroy();
265     EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
266 }
267 
TEST(Logger,LogIf)268 TEST(Logger, LogIf)
269 {
270     Logger::InitializeStdLogging(Logger::Level::INFO, panda::LoggerComponentMaskAll);
271     EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
272 
273     testing::internal::CaptureStderr();
274 
275     LOG_IF(true, INFO, COMMON) << "a";
276     LOG_IF(false, INFO, COMMON) << "b";
277 
278     std::string err = testing::internal::GetCapturedStderr();
279     uint32_t tid = os::thread::GetCurrentThreadId();
280     std::string res = helpers::string::Format("[TID %06x] I/common: a\n", tid);
281     EXPECT_EQ(err, res);
282 
283     Logger::Destroy();
284     EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
285 }
286 
TEST(Logger,LogOnce)287 TEST(Logger, LogOnce)
288 {
289     Logger::InitializeStdLogging(Logger::Level::INFO, panda::LoggerComponentMaskAll);
290     EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
291 
292     testing::internal::CaptureStderr();
293 
294     LOG_ONCE(INFO, COMMON) << "a";
295     for (int i = 0; i < 10; ++i) {
296         LOG_ONCE(INFO, COMMON) << "b";
297     }
298     LOG_ONCE(INFO, COMMON) << "c";
299 
300     std::string err = testing::internal::GetCapturedStderr();
301     uint32_t tid = os::thread::GetCurrentThreadId();
302     std::string res = helpers::string::Format(
303         "[TID %06x] I/common: a\n"
304         "[TID %06x] I/common: b\n"
305         "[TID %06x] I/common: c\n",
306         tid, tid, tid);
307     EXPECT_EQ(err, res);
308 
309     Logger::Destroy();
310     EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
311 }
312 
TEST(Logger,LogDfx)313 TEST(Logger, LogDfx)
314 {
315     Logger::InitializeStdLogging(Logger::Level::ERROR, panda::LoggerComponentMaskAll);
316     EXPECT_TRUE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
317 
318     DfxController::Initialize();
319     EXPECT_TRUE(DfxController::IsInitialized());
320     EXPECT_EQ(DfxController::GetOptionValue(DfxOptionHandler::DFXLOG), 0);
321 
322     testing::internal::CaptureStderr();
323 
324     LOG_DFX(COMMON) << "a";
325     LOG_DFX(COMMON) << "b";
326     LOG_DFX(COMMON) << "c";
327 
328     std::string err = testing::internal::GetCapturedStderr();
329     EXPECT_EQ(err, "");
330 
331     DfxController::ResetOptionValueFromString("dfx-log:1");
332     EXPECT_EQ(DfxController::GetOptionValue(DfxOptionHandler::DFXLOG), 1);
333 
334     testing::internal::CaptureStderr();
335 
336     LOG_DFX(COMMON) << "a";
337     LOG_DFX(COMMON) << "b";
338     LOG_DFX(COMMON) << "c";
339 
340     err = testing::internal::GetCapturedStderr();
341     uint32_t tid = os::thread::GetCurrentThreadId();
342     std::string res = helpers::string::Format(
343         "[TID %06x] E/dfx: common log:a\n"
344         "[TID %06x] E/dfx: common log:b\n"
345         "[TID %06x] E/dfx: common log:c\n",
346         tid, tid, tid);
347     EXPECT_EQ(err, res);
348 
349     Logger::Destroy();
350     EXPECT_FALSE(Logger::IsLoggingOn(Logger::Level::FATAL, Logger::Component::ALLOC));
351 
352     DfxController::Destroy();
353     EXPECT_FALSE(DfxController::IsInitialized());
354 }
355 
356 }  // namespace panda::test
357