1 /*
2 * Copyright (c) 2024 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 <random>
21 #include <sstream>
22 #include <string>
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 0x2D00
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 static constexpr uint16_t SOME_LOGS = 10;
42 static constexpr uint16_t MORE_LOGS = 100;
43 static constexpr uint16_t OVER_LOGS = 1000;
44
45 enum LogInterfaceType {
46 DEBUG_METHOD = 0,
47 INFO_METHOD = 1,
48 WARN_METHOD = 2,
49 ERROR_METHOD = 3,
50 FATAL_METHOD = 4,
51 METHODS_NUMBER = 5,
52 };
53
54 using LogMethodFunc = std::function<void(const std::string &msg)>;
55
56 static const std::array<LogMethodFunc, METHODS_NUMBER> LOG_C_METHODS = {
__anon3a528b480102() 57 [] (const std::string &msg) {
58 OH_LOG_DEBUG(LOG_APP, "%{public}s", msg.c_str());
59 },
__anon3a528b480202() 60 [] (const std::string &msg) {
61 OH_LOG_INFO(LOG_APP, "%{public}s", msg.c_str());
62 },
__anon3a528b480302() 63 [] (const std::string &msg) {
64 OH_LOG_WARN(LOG_APP, "%{public}s", msg.c_str());
65 },
__anon3a528b480402() 66 [] (const std::string &msg) {
67 OH_LOG_ERROR(LOG_APP, "%{public}s", msg.c_str());
68 },
__anon3a528b480502() 69 [] (const std::string &msg) {
70 OH_LOG_FATAL(LOG_APP, "%{public}s", msg.c_str());
71 },
72 };
73
PopenToString(const std::string & command)74 static std::string PopenToString(const std::string &command)
75 {
76 std::string str;
77 constexpr int bufferSize = 1024;
78 FILE *fp = popen(command.c_str(), "re");
79 if (fp != nullptr) {
80 char buf[bufferSize] = {0};
81 size_t n = fread(buf, 1, sizeof(buf), fp);
82 while (n > 0) {
83 str.append(buf, n);
84 n = fread(buf, 1, sizeof(buf), fp);
85 }
86 pclose(fp);
87 }
88 std::cout << "PopenToString res: " << str << std::endl;
89 return str;
90 }
91
92 class HiLogNDKZTest : public testing::Test {
93 public:
94 static void SetUpTestCase();
TearDownTestCase()95 static void TearDownTestCase() {}
96 void SetUp();
TearDown()97 void TearDown() {}
98 };
99
SetUpTestCase()100 void HiLogNDKZTest::SetUpTestCase()
101 {
102 (void)PopenToString("hilog -Q pidoff");
103 (void)PopenToString("hilog -Q domainoff");
104 }
105
SetUp()106 void HiLogNDKZTest::SetUp()
107 {
108 (void)PopenToString("hilog -r");
109 }
110
111
RandomNum()112 uint64_t RandomNum()
113 {
114 std::random_device seed;
115 std::mt19937_64 gen(seed());
116 std::uniform_int_distribution<uint64_t> dis(0, std::numeric_limits<uint64_t>::max());
117 return dis(gen);
118 }
119
RandomStringGenerator()120 static std::string RandomStringGenerator()
121 {
122 std::string str;
123 int logLen = 16;
124 char index;
125 for (int i = 0; i < logLen; ++i) {
126 index = RandomNum() % ('z' - 'a') + 'a';
127 str.append(1, index);
128 }
129 return str;
130 }
131
HilogPrint(LogInterfaceType methodType,uint16_t count,const std::array<LogMethodFunc,METHODS_NUMBER> & logMethods)132 static uint16_t HilogPrint(LogInterfaceType methodType, uint16_t count,
133 const std::array<LogMethodFunc, METHODS_NUMBER> &logMethods)
134 {
135 std::string logMsg(RandomStringGenerator());
136 for (uint16_t i = 0; i < count; ++i) {
137 logMethods.at(methodType)(logMsg + std::to_string(i));
138 }
139 usleep(1000); /* 1000: sleep 1 ms */
140 std::string logMsgs = PopenToString("/system/bin/hilog -x");
141 uint16_t realCount = 0;
142 std::stringstream ss(logMsgs);
143 std::string str;
144 while (!ss.eof()) {
145 getline(ss, str);
146 if (str.find(logMsg) != std::string::npos) {
147 ++realCount;
148 }
149 }
150 return realCount;
151 }
152
HiLogWriteTest(LogInterfaceType methodType,uint16_t count,const std::array<LogMethodFunc,METHODS_NUMBER> & logMethods)153 static void HiLogWriteTest(LogInterfaceType methodType, uint16_t count,
154 const std::array<LogMethodFunc, METHODS_NUMBER> &logMethods)
155 {
156 uint16_t realCount = HilogPrint(methodType, count, logMethods);
157 uint16_t allowedLeastLogCount = count - count * 1 / 10; /* 1 / 10: loss rate less than 10% */
158 if (methodType == DEBUG_METHOD) {
159 allowedLeastLogCount = 0; /* 0: debug log is allowed to be closed */
160 }
161 EXPECT_GE(realCount, allowedLeastLogCount);
162 }
163
HiLogWriteFailedTest(LogInterfaceType methodType,uint16_t count,const std::array<LogMethodFunc,METHODS_NUMBER> & logMethods)164 static inline void HiLogWriteFailedTest(LogInterfaceType methodType, uint16_t count,
165 const std::array<LogMethodFunc, METHODS_NUMBER> &logMethods)
166 {
167 EXPECT_EQ(HilogPrint(methodType, count, logMethods), 0);
168 }
169
FlowCtlTest(const std::string keyWord)170 static void FlowCtlTest(const std::string keyWord)
171 {
172 const std::string str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
173 for (uint16_t i = 0; i < OVER_LOGS; ++i) {
174 OH_LOG_INFO(LOG_APP, "%{public}s:%{public}d", str.c_str(), i);
175 }
176 sleep(1); /* 1: sleep 1 s */
177 OH_LOG_INFO(LOG_APP, "%{public}s", str.c_str());
178 std::string logMsgs = PopenToString("hilog -x -T LOGLIMIT");
179 EXPECT_TRUE(logMsgs.find(keyWord) != std::string::npos);
180 }
181
182 /**
183 * @tc.name: Dfx_HiLogNDKZTest_PrintDebugLog_001
184 * @tc.desc: Call OH_LOG_DEBUG to print logs.
185 * @tc.type: FUNC
186 */
187 HWTEST_F(HiLogNDKZTest, PrintDebugLog_001, TestSize.Level1)
188 {
189 /**
190 * @tc.steps: step1. Call OH_LOG_DEBUG to print logs and call hilog to read it
191 * @tc.expected: step1. Logs can be printed only if hilog.debug is enabled.
192 */
193 HiLogWriteTest(DEBUG_METHOD, SOME_LOGS, LOG_C_METHODS);
194 }
195
196 /**
197 * @tc.name: Dfx_HiLogNDKZTest_PrintInfoLog_001
198 * @tc.desc: Call OH_LOG_INFO to print logs.
199 * @tc.type: FUNC
200 */
201 HWTEST_F(HiLogNDKZTest, PrintInfoLog_001, TestSize.Level1)
202 {
203 /**
204 * @tc.steps: step1. Call OH_LOG_INFO to print logs and call hilog to read it
205 * @tc.expected: step1. Logs printed without loss.
206 */
207 HiLogWriteTest(INFO_METHOD, SOME_LOGS, LOG_C_METHODS);
208 }
209
210 /**
211 * @tc.name: Dfx_HiLogNDKZTest_PrintWarnLog_001
212 * @tc.desc: Call OH_LOG_WARN to print logs.
213 * @tc.type: FUNC
214 */
215 HWTEST_F(HiLogNDKZTest, PrintWarnLog_001, TestSize.Level1)
216 {
217 /**
218 * @tc.steps: step1. Call OH_LOG_WARN to print logs and call hilog to read it
219 * @tc.expected: step1. Logs printed without loss.
220 */
221 HiLogWriteTest(WARN_METHOD, SOME_LOGS, LOG_C_METHODS);
222 }
223
224 /**
225 * @tc.name: Dfx_HiLogNDKZTest_PrintErrorLog_001
226 * @tc.desc: Call OH_LOG_ERROR to print logs.
227 * @tc.type: FUNC
228 */
229 HWTEST_F(HiLogNDKZTest, PrintErrorLog_001, TestSize.Level1)
230 {
231 /**
232 * @tc.steps: step1. Call OH_LOG_ERROR to print logs and call hilog to read it
233 * @tc.expected: step1. Logs printed without loss.
234 */
235 HiLogWriteTest(ERROR_METHOD, SOME_LOGS, LOG_C_METHODS);
236 }
237
238 /**
239 * @tc.name: Dfx_HiLogNDKZTest_PrintFatalLog_001
240 * @tc.desc: Call OH_LOG_FATAL to print logs.
241 * @tc.type: FUNC
242 */
243 HWTEST_F(HiLogNDKZTest, PrintFatalLog_001, TestSize.Level1)
244 {
245 /**
246 * @tc.steps: step1. Call OH_LOG_FATAL to print logs and call hilog to read it
247 * @tc.expected: step1. Logs printed without loss.
248 */
249 HiLogWriteTest(FATAL_METHOD, SOME_LOGS, LOG_C_METHODS);
250 }
251
252 /**
253 * @tc.name: Dfx_HiLogNDKZTest_LogLossCheck_001
254 * @tc.desc: HiLog log loss rate must less than 10%.
255 * @tc.type: FUNC
256 */
257 HWTEST_F(HiLogNDKZTest, LogLossCheck_001, TestSize.Level1)
258 {
259 /**
260 * @tc.steps: step1. Call OH_LOG_INFO to print logs and call hilog to read it
261 * @tc.expected: step1. Calculate log loss rate and it should less than 10%
262 */
263 HiLogWriteTest(INFO_METHOD, MORE_LOGS, LOG_C_METHODS);
264 }
265
266 /**
267 * @tc.name: Dfx_HiLogNDKZTest_IsLoggable_001
268 * @tc.desc: Check whether is loggable for each log level
269 * @tc.type: FUNC
270 */
271 HWTEST_F(HiLogNDKZTest, IsLoggable_001, TestSize.Level1)
272 {
273 /**
274 * @tc.steps: step1. Call OH_LOG_IsLoggable to check whether is loggable for each log level.
275 * @tc.expected: step1. LOG_DEBUG and lower level should return false in release version, and others return true.
276 */
277 if (OHOS::system::GetParameter("hilog.loggable.global", "D") == "D") {
278 EXPECT_TRUE(OH_LOG_IsLoggable(0x2D00, LOG_TAG, LOG_DEBUG));
279 } else {
280 EXPECT_FALSE(OH_LOG_IsLoggable(0x2D00, LOG_TAG, LOG_DEBUG));
281 }
282 EXPECT_TRUE(OH_LOG_IsLoggable(0x2D00, LOG_TAG, LOG_INFO));
283 EXPECT_TRUE(OH_LOG_IsLoggable(0x2D00, LOG_TAG, LOG_WARN));
284 EXPECT_TRUE(OH_LOG_IsLoggable(0x2D00, LOG_TAG, LOG_ERROR));
285 EXPECT_TRUE(OH_LOG_IsLoggable(0x2D00, LOG_TAG, LOG_FATAL));
286 EXPECT_TRUE(OH_LOG_IsLoggable(0x2D00, "abc", LOG_WARN));
287 }
288
289
290 /**
291 * @tc.name: Dfx_HiLogNDKZTest_hilogSocketTest
292 * @tc.desc: Query hilog socket rights
293 * @tc.type: FUNC
294 * @tc.require:issueI5NU7F
295 */
296 HWTEST_F(HiLogNDKZTest, hilogSocketTest, TestSize.Level1)
297 {
298 std::string str;
299 std::string hilogControlRights = "srw-rw----";
300 std::string logMsgs = PopenToString("ls -al //dev/unix/socket/hilogControl");
301 std::stringstream ss(logMsgs);
302 getline(ss, str);
303 EXPECT_TRUE(str.find(hilogControlRights) != std::string::npos);
304 }
305
306 /**
307 * @tc.name: Dfx_HiLogNDKZTest_pidFlowCtrlTest
308 * @tc.desc: hilog pidFlowCtrlTest
309 * @tc.type: FUNC
310 */
311 HWTEST_F(HiLogNDKZTest, pidFlowCtrlTest, TestSize.Level1)
312 {
313 (void)PopenToString("hilog -Q pidon");
314 const std::string pidCtrlLog = "DROPPED";
315 FlowCtlTest(pidCtrlLog);
316 (void)PopenToString("hilog -Q pidoff");
317 }
318
319 /**
320 * @tc.name: Dfx_HiLogNDKZTest_SetMinLevelTest
321 * @tc.desc: hilog setMinLevelTest
322 * @tc.type: FUNC
323 */
324 HWTEST_F(HiLogNDKZTest, setMinLevelTest, TestSize.Level1)
325 {
326 HiLogWriteTest(INFO_METHOD, SOME_LOGS, LOG_C_METHODS);
327 OH_LOG_SetMinLogLevel(LOG_WARN);
328 HiLogWriteFailedTest(INFO_METHOD, SOME_LOGS, LOG_C_METHODS);
329 OH_LOG_SetMinLogLevel(LOG_DEBUG);
330 HiLogWriteFailedTest(DEBUG_METHOD, SOME_LOGS, LOG_C_METHODS);
331 HiLogWriteTest(INFO_METHOD, SOME_LOGS, LOG_C_METHODS);
332 }
333
334 } // namespace HiLogTest
335 } // namespace HiviewDFX
336 } // namespace OHOS
337