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 <array>
17 #include <cstdlib>
18 #include <ctime>
19 #include <iostream>
20 #include <sstream>
21 #include <string>
22
23 #include <unistd.h>
24
25 #include <gtest/gtest.h>
26
27 #include "hilog/log.h"
28 #include "parameters.h"
29
30 #undef LOG_DOMAIN
31 #define LOG_DOMAIN 0xD002D00
32
33 #undef LOG_TAG
34 #define LOG_TAG "HILOGTEST_C"
35
36 using namespace testing::ext;
37
38 namespace OHOS {
39 namespace HiviewDFX {
40 namespace HiLogTest {
41 const HiLogLabel APP_LABEL = { LOG_APP, 0x002a, "HILOGTEST_CPP" };
42 const HiLogLabel LABEL = { LOG_CORE, 0xD002D00, "HILOGTEST_CPP" };
43 const HiLogLabel ILLEGAL_DOMAIN_LABEL = { LOG_CORE, 0xD00EEEE, "HILOGTEST_CPP" };
44 static constexpr unsigned int SOME_LOGS = 10;
45 static constexpr unsigned int MORE_LOGS = 100;
46 static constexpr unsigned int OVER_LOGS = 1000;
47
48 enum LogInterfaceType {
49 DEBUG_METHOD = 0,
50 INFO_METHOD = 1,
51 WARN_METHOD = 2,
52 ERROR_METHOD = 3,
53 FATAL_METHOD = 4,
54 METHODS_NUMBER = 5,
55 };
56
57 using LogMethodFunc = std::function<void(const std::string &msg)>;
58
59 static const std::array<LogMethodFunc, METHODS_NUMBER> LOG_C_METHODS = {
__anon0caaf0ac0102() 60 [] (const std::string &msg) {
61 HILOG_DEBUG(LOG_CORE, "%{public}s", msg.c_str());
62 },
__anon0caaf0ac0202() 63 [] (const std::string &msg) {
64 HILOG_INFO(LOG_CORE, "%{public}s", msg.c_str());
65 },
__anon0caaf0ac0302() 66 [] (const std::string &msg) {
67 HILOG_WARN(LOG_CORE, "%{public}s", msg.c_str());
68 },
__anon0caaf0ac0402() 69 [] (const std::string &msg) {
70 HILOG_ERROR(LOG_CORE, "%{public}s", msg.c_str());
71 },
__anon0caaf0ac0502() 72 [] (const std::string &msg) {
73 HILOG_FATAL(LOG_CORE, "%{public}s", msg.c_str());
74 },
75 };
76
77 static const std::array<LogMethodFunc, METHODS_NUMBER> LOG_CPP_METHODS = {
__anon0caaf0ac0602() 78 [] (const std::string &msg) {
79 HiLog::Debug(LABEL, "%{public}s", msg.c_str());
80 },
__anon0caaf0ac0702() 81 [] (const std::string &msg) {
82 HiLog::Info(LABEL, "%{public}s", msg.c_str());
83 },
__anon0caaf0ac0802() 84 [] (const std::string &msg) {
85 HiLog::Warn(LABEL, "%{public}s", msg.c_str());
86 },
__anon0caaf0ac0902() 87 [] (const std::string &msg) {
88 HiLog::Error(LABEL, "%{public}s", msg.c_str());
89 },
__anon0caaf0ac0a02() 90 [] (const std::string &msg) {
91 HiLog::Fatal(LABEL, "%{public}s", msg.c_str());
92 },
93 };
94
PopenToString(const std::string & command)95 static std::string PopenToString(const std::string &command)
96 {
97 std::string str;
98 constexpr int bufferSize = 1024;
99 FILE *fp = popen(command.c_str(), "re");
100 if (fp != nullptr) {
101 char buf[bufferSize] = {0};
102 size_t n = fread(buf, 1, sizeof(buf), fp);
103 while (n > 0) {
104 str.append(buf, n);
105 n = fread(buf, 1, sizeof(buf), fp);
106 }
107 pclose(fp);
108 }
109 std::cout << "PopenToString res: " << str << std::endl;
110 return str;
111 }
112
113 class HiLogNDKTest : public testing::Test {
114 public:
115 static void SetUpTestCase();
TearDownTestCase()116 static void TearDownTestCase() {}
117 void SetUp();
TearDown()118 void TearDown() {}
119 };
120
SetUpTestCase()121 void HiLogNDKTest::SetUpTestCase()
122 {
123 (void)PopenToString("hilog -Q pidoff");
124 (void)PopenToString("hilog -Q domainoff");
125 }
126
SetUp()127 void HiLogNDKTest::SetUp()
128 {
129 (void)PopenToString("hilog -r");
130 }
131
RandomStringGenerator()132 static std::string RandomStringGenerator()
133 {
134 std::string str;
135 int logLen = 16;
136 char index;
137 for (int i = 0; i < logLen; ++i) {
138 index = rand() % ('z' - 'a') + 'a';
139 str.append(1, index);
140 }
141 return str;
142 }
143
HiLogWriteTest(LogInterfaceType methodType,unsigned int count,const std::array<LogMethodFunc,METHODS_NUMBER> & logMethods)144 static void HiLogWriteTest(LogInterfaceType methodType, unsigned int count,
145 const std::array<LogMethodFunc, METHODS_NUMBER> &logMethods)
146 {
147 std::string logMsg(RandomStringGenerator());
148 for (unsigned int i = 0; i < count; ++i) {
149 logMethods.at(methodType)(logMsg + std::to_string(i));
150 }
151 usleep(1000); /* 1000: sleep 1 ms */
152 std::string logMsgs = PopenToString("/system/bin/hilog -x");
153 unsigned int realCount = 0;
154 std::stringstream ss(logMsgs);
155 std::string str;
156 while (!ss.eof()) {
157 getline(ss, str);
158 if (str.find(logMsg) != std::string::npos) {
159 ++realCount;
160 }
161 }
162 unsigned int allowedLeastLogCount = count - count * 1 / 10; /* 1 / 10: loss rate less than 10% */
163 if (methodType == DEBUG_METHOD) {
164 allowedLeastLogCount = 0; /* 0: debug log is allowed to be closed */
165 }
166 EXPECT_GE(realCount, allowedLeastLogCount);
167 }
168
FlowCtlTest(const HiLogLabel & label,const std::string keyWord)169 static void FlowCtlTest(const HiLogLabel &label, const std::string keyWord)
170 {
171 const std::string str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
172 for (unsigned int i = 0; i < OVER_LOGS; ++i) {
173 HiLog::Info(label, "%{public}s:%{public}d", str.c_str(), i);
174 }
175 sleep(1); /* 1: sleep 1 s */
176 HiLog::Info(label, "%{public}s", str.c_str());
177 std::string logMsgs = PopenToString("hilog -x -T LOGLIMIT");
178 EXPECT_TRUE(logMsgs.find(keyWord) != std::string::npos);
179 }
180
181 /**
182 * @tc.name: Dfx_HiLogNDKTest_PrintDebugLog_001
183 * @tc.desc: Call HILOG_DEBUG to print logs.
184 * @tc.type: FUNC
185 */
186 HWTEST_F(HiLogNDKTest, PrintDebugLog_001, TestSize.Level1)
187 {
188 /**
189 * @tc.steps: step1. Call HILOG_DEBUG to print logs and call hilog to read it
190 * @tc.expected: step1. Logs can be printed only if hilog.debug is enabled.
191 */
192 HiLogWriteTest(DEBUG_METHOD, SOME_LOGS, LOG_C_METHODS);
193 }
194
195 /**
196 * @tc.name: Dfx_HiLogNDKTest_PrintInfoLog_001
197 * @tc.desc: Call HILOG_INFO to print logs.
198 * @tc.type: FUNC
199 */
200 HWTEST_F(HiLogNDKTest, PrintInfoLog_001, TestSize.Level1)
201 {
202 /**
203 * @tc.steps: step1. Call HILOG_INFO to print logs and call hilog to read it
204 * @tc.expected: step1. Logs printed without loss.
205 */
206 HiLogWriteTest(INFO_METHOD, SOME_LOGS, LOG_C_METHODS);
207 }
208
209 /**
210 * @tc.name: Dfx_HiLogNDKTest_PrintWarnLog_001
211 * @tc.desc: Call HILOG_WARN to print logs.
212 * @tc.type: FUNC
213 */
214 HWTEST_F(HiLogNDKTest, PrintWarnLog_001, TestSize.Level1)
215 {
216 /**
217 * @tc.steps: step1. Call HILOG_WARN to print logs and call hilog to read it
218 * @tc.expected: step1. Logs printed without loss.
219 */
220 HiLogWriteTest(WARN_METHOD, SOME_LOGS, LOG_C_METHODS);
221 }
222
223 /**
224 * @tc.name: Dfx_HiLogNDKTest_PrintErrorLog_001
225 * @tc.desc: Call HILOG_ERROR to print logs.
226 * @tc.type: FUNC
227 */
228 HWTEST_F(HiLogNDKTest, PrintErrorLog_001, TestSize.Level1)
229 {
230 /**
231 * @tc.steps: step1. Call HILOG_ERROR to print logs and call hilog to read it
232 * @tc.expected: step1. Logs printed without loss.
233 */
234 HiLogWriteTest(ERROR_METHOD, SOME_LOGS, LOG_C_METHODS);
235 }
236
237 /**
238 * @tc.name: Dfx_HiLogNDKTest_PrintFatalLog_001
239 * @tc.desc: Call HILOG_FATAL to print logs.
240 * @tc.type: FUNC
241 */
242 HWTEST_F(HiLogNDKTest, PrintFatalLog_001, TestSize.Level1)
243 {
244 /**
245 * @tc.steps: step1. Call HILOG_FATAL to print logs and call hilog to read it
246 * @tc.expected: step1. Logs printed without loss.
247 */
248 HiLogWriteTest(FATAL_METHOD, SOME_LOGS, LOG_C_METHODS);
249 }
250
251 /**
252 * @tc.name: Dfx_HiLogNDKTest_LogLossCheck_001
253 * @tc.desc: HiLog log loss rate must less than 10%.
254 * @tc.type: FUNC
255 */
256 HWTEST_F(HiLogNDKTest, LogLossCheck_001, TestSize.Level1)
257 {
258 /**
259 * @tc.steps: step1. Call HILOG_INFO to print logs and call hilog to read it
260 * @tc.expected: step1. Calculate log loss rate and it should less than 10%
261 */
262 HiLogWriteTest(INFO_METHOD, MORE_LOGS, LOG_C_METHODS);
263 }
264
265 /**
266 * @tc.name: Dfx_HiLogNDKTest_PrintDebugLog_002
267 * @tc.desc: Call HiLog::Debug to print logs.
268 * @tc.type: FUNC
269 */
270 HWTEST_F(HiLogNDKTest, PrintDebugLog_002, TestSize.Level1)
271 {
272 /**
273 * @tc.steps: step1. Call HiLog::Debug to print logs and call hilog to read it
274 * @tc.expected: step1. Logs can be printed only if hilog.debug is enabled.
275 */
276 HiLogWriteTest(DEBUG_METHOD, SOME_LOGS, LOG_CPP_METHODS);
277 }
278
279 /**
280 * @tc.name: Dfx_HiLogNDKTest_PrintInfoLog_002
281 * @tc.desc: Call HiLog::Info to print logs.
282 * @tc.type: FUNC
283 */
284 HWTEST_F(HiLogNDKTest, PrintInfoLog_002, TestSize.Level1)
285 {
286 /**
287 * @tc.steps: step1. Call HiLog::Info to print logs and call hilog to read it
288 * @tc.expected: step1. Logs printed without loss.
289 */
290 HiLogWriteTest(INFO_METHOD, SOME_LOGS, LOG_CPP_METHODS);
291 }
292
293 /**
294 * @tc.name: Dfx_HiLogNDKTest_PrintWarnLog_002
295 * @tc.desc: Call HiLog::Warn print logs.
296 * @tc.type: FUNC
297 */
298 HWTEST_F(HiLogNDKTest, PrintWarnLog_002, TestSize.Level1)
299 {
300 /**
301 * @tc.steps: step1. Call HiLog::Warn to print logs and call hilog to read it
302 * @tc.expected: step1. Logs printed without loss.
303 */
304 HiLogWriteTest(WARN_METHOD, SOME_LOGS, LOG_CPP_METHODS);
305 }
306
307 /**
308 * @tc.name: Dfx_HiLogNDKTest_PrintErrorLog_002
309 * @tc.desc: Call HiLog::Error to print logs.
310 * @tc.type: FUNC
311 */
312 HWTEST_F(HiLogNDKTest, PrintErrorLog_002, TestSize.Level1)
313 {
314 /**
315 * @tc.steps: step1. Call HiLog::Error to print logs and call hilog to read it
316 * @tc.expected: step1. Logs printed without loss.
317 */
318 HiLogWriteTest(ERROR_METHOD, SOME_LOGS, LOG_CPP_METHODS);
319 }
320
321 /**
322 * @tc.name: Dfx_HiLogNDKTest_PrintFatalLog_002
323 * @tc.desc: Call HiLog::Fatal to print logs.
324 * @tc.type: FUNC
325 */
326 HWTEST_F(HiLogNDKTest, PrintFatalLog_002, TestSize.Level1)
327 {
328 /**
329 * @tc.steps: step1. Call HiLog::Fatal to print logs and call hilog to read it
330 * @tc.expected: step1. Logs printed without loss.
331 */
332 HiLogWriteTest(FATAL_METHOD, SOME_LOGS, LOG_CPP_METHODS);
333 }
334
335 /**
336 * @tc.name: Dfx_HiLogNDKTest_LogLossCheck_002
337 * @tc.desc: HiLog log loss rate must less than 10%
338 * @tc.type: FUNC
339 */
340 HWTEST_F(HiLogNDKTest, LogLossCheck_002, TestSize.Level1)
341 {
342 /**
343 * @tc.steps: step1. Call HiLog::Info to print logs and call hilog to read it
344 * @tc.expected: step1. Calculate log loss rate and it should less than 10%
345 */
346 HiLogWriteTest(INFO_METHOD, MORE_LOGS, LOG_CPP_METHODS);
347 }
348
349 /**
350 * @tc.name: Dfx_HiLogNDKTest_IsLoggable_001
351 * @tc.desc: Check whether is loggable for each log level
352 * @tc.type: FUNC
353 */
354 HWTEST_F(HiLogNDKTest, IsLoggable_001, TestSize.Level1)
355 {
356 /**
357 * @tc.steps: step1. Call HiLogIsLoggable to check whether is loggable for each log level.
358 * @tc.expected: step1. LOG_DEBUG and lower level should return false in release version, and others return true.
359 */
360 if (OHOS::system::GetParameter("hilog.loggable.global", "D") == "D") {
361 EXPECT_TRUE(HiLogIsLoggable(0xD002D00, LOG_TAG, LOG_DEBUG));
362 } else {
363 EXPECT_FALSE(HiLogIsLoggable(0xD002D00, LOG_TAG, LOG_DEBUG));
364 }
365 EXPECT_TRUE(HiLogIsLoggable(0xD002D00, LOG_TAG, LOG_INFO));
366 EXPECT_TRUE(HiLogIsLoggable(0xD002D00, LOG_TAG, LOG_WARN));
367 EXPECT_TRUE(HiLogIsLoggable(0xD002D00, LOG_TAG, LOG_ERROR));
368 EXPECT_TRUE(HiLogIsLoggable(0xD002D00, LOG_TAG, LOG_FATAL));
369 EXPECT_TRUE(HiLogIsLoggable(0xD002D00, "abc", LOG_WARN));
370 }
371
372 /**
373 * @tc.name: Dfx_HiLogNDKTest_DomainCheck_001
374 * @tc.desc: test illegal domainID
375 * @tc.type: FUNC
376 * @tc.require:issueI5NU4L
377 */
378 HWTEST_F(HiLogNDKTest, DomainCheck_001, TestSize.Level1)
379 {
380 (void)PopenToString("param set hilog.debug.on false");
381 (void)PopenToString("param set persist.sys.hilog.debug.on false");
382 std::string logMsg(RandomStringGenerator());
383 for (unsigned int i = 0; i < SOME_LOGS; ++i) {
384 HiLog::Info(ILLEGAL_DOMAIN_LABEL, "%{public}s", logMsg.c_str());
385 }
386 usleep(1000); /* 1000: sleep 1 ms */
387 std::string logMsgs = PopenToString("/system/bin/hilog -x");
388 unsigned int realCount = 0;
389 std::stringstream ss(logMsgs);
390 std::string str;
391 while (!ss.eof()) {
392 getline(ss, str);
393 if (str.find(logMsg) != std::string::npos) {
394 ++realCount;
395 }
396 }
397 EXPECT_EQ(realCount, 0);
398 }
399
400 /**
401 * @tc.name: Dfx_HiLogNDKTest_hilogSocketTest
402 * @tc.desc: Query hilog socket rights
403 * @tc.type: FUNC
404 * @tc.require:issueI5NU7F
405 */
406 HWTEST_F(HiLogNDKTest, hilogSocketTest, TestSize.Level1)
407 {
408 std::string str;
409 std::string hilogControlRights = "srw-rw----";
410 std::string logMsgs = PopenToString("ls -al //dev/unix/socket/hilogControl");
411 std::stringstream ss(logMsgs);
412 getline(ss, str);
413 EXPECT_TRUE(str.find(hilogControlRights) != std::string::npos);
414 }
415
416 /**
417 * @tc.name: Dfx_HiLogNDKTest_pidFlowCtrlTest
418 * @tc.desc: hilog pidFlowCtrlTest
419 * @tc.type: FUNC
420 */
421 HWTEST_F(HiLogNDKTest, pidFlowCtrlTest, TestSize.Level1)
422 {
423 (void)PopenToString("hilog -Q pidon");
424 const std::string pidCtrlLog = "DROPPED";
425 FlowCtlTest(APP_LABEL, pidCtrlLog);
426 (void)PopenToString("hilog -Q pidoff");
427 }
428
429 /**
430 * @tc.name: Dfx_HiLogNDKTest_domainFlowCtrlTest
431 * @tc.desc: hilog domainFlowCtrlTest
432 * @tc.type: FUNC
433 */
434 HWTEST_F(HiLogNDKTest, domainFlowCtrlTest, TestSize.Level1)
435 {
436 (void)PopenToString("hilog -Q domainon");
437 const std::string domainCtrlLog = "dropped";
438 FlowCtlTest(LABEL, domainCtrlLog);
439 (void)PopenToString("hilog -Q domainoff");
440 }
441 } // namespace HiLogTest
442 } // namespace HiviewDFX
443 } // namespace OHOS
444