• 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 <array>
17 #include <cstdlib>
18 #include <cstdio>
19 #include <ctime>
20 #include <dirent.h>
21 #include <iostream>
22 #include <securec.h>
23 #include <sstream>
24 #include <stdatomic.h>
25 #include <string>
26 #include <sys/socket.h>
27 #include <sys/stat.h>
28 #include <sys/un.h>
29 #include <thread>
30 
31 #include <gtest/gtest.h>
32 #include <hilog_common.h>
33 
34 #include "hilog_base/log_base.h"
35 
36 #undef LOG_DOMAIN
37 #define LOG_DOMAIN 0xD002D00
38 
39 #undef LOG_TAG
40 #define LOG_TAG "HILOGBASETEST"
41 
42 using namespace testing::ext;
43 
44 namespace OHOS {
45 namespace HiviewDFX {
46 namespace HiLogBaseTest {
47 static constexpr unsigned int SOME_LOGS = 10;
48 static constexpr unsigned int MORE_LOGS = 100;
49 static constexpr unsigned int SHORT_LOG = 16;
50 static constexpr unsigned int LONG_LOG = 1000;
51 static constexpr unsigned int VERY_LONG_LOG = 2048;
52 static constexpr unsigned int THREAD_COUNT = 10;
53 static std::string g_str[THREAD_COUNT];
54 #define TWO (2)
55 #define NEGATIVE_ONE (-1)
56 
57 enum LogInterfaceType {
58     DEBUG_METHOD = 0,
59     INFO_METHOD = 1,
60     WARN_METHOD = 2,
61     ERROR_METHOD = 3,
62     FATAL_METHOD = 4,
63     METHODS_NUMBER = 5,
64 };
65 
66 using LogMethodFunc = std::function<void(const std::string &msg)>;
67 
68 static const std::array<std::string, METHODS_NUMBER> METHOD_NAMES = {
69     "Debug", "Info", "Warn", "Error", "Fatal"
70 };
71 
72 static const std::array<LogMethodFunc, METHODS_NUMBER> LOG_C_METHODS = {
__anon8b8c17a90102() 73     [] (const std::string &msg) {
74         HILOG_BASE_DEBUG(LOG_CORE, "%{public}s", msg.c_str());
75     },
__anon8b8c17a90202() 76     [] (const std::string &msg) {
77         HILOG_BASE_INFO(LOG_CORE, "%{public}s", msg.c_str());
78     },
__anon8b8c17a90302() 79     [] (const std::string &msg) {
80         HILOG_BASE_WARN(LOG_CORE, "%{public}s", msg.c_str());
81     },
__anon8b8c17a90402() 82     [] (const std::string &msg) {
83         HILOG_BASE_ERROR(LOG_CORE, "%{public}s", msg.c_str());
84     },
__anon8b8c17a90502() 85     [] (const std::string &msg) {
86         HILOG_BASE_FATAL(LOG_CORE, "%{public}s", msg.c_str());
87     },
88 };
89 
PopenToString(const std::string & command)90 static std::string PopenToString(const std::string &command)
91 {
92     std::string str;
93     constexpr int bufferSize = 1024;
94     FILE *fp = popen(command.c_str(), "re");
95     if (fp != nullptr) {
96         char buf[bufferSize] = {0};
97         size_t n = fread(buf, 1, sizeof(buf), fp);
98         while (n > 0) {
99             str.append(buf, n);
100             n = fread(buf, 1, sizeof(buf), fp);
101         }
102         pclose(fp);
103     }
104     return str;
105 }
106 
107 // Function executed by the subthread to print logs
FunctionPrintLog(int index)108 void FunctionPrintLog(int index)
109 {
110     HiLogBasePrint(LOG_INIT, LOG_ERROR, 0xD002D00, LOG_TAG, "FunctionPrintLog %{public}s", g_str[index].c_str());
111 }
112 
113 //Check whether corresponding logs are generated. If yes, true is returned. If no, false is returned.
CheckHiLogPrint(char * needToMatch)114 bool CheckHiLogPrint(char *needToMatch)
115 {
116     constexpr int COMMAND_SIZE = 50;
117     constexpr int BUFFER_SIZE = 1024;
118     constexpr int FAIL_CLOSE = -1;
119     bool ret = false;
120     // Use the system function to read the current hilog information.
121     char command[] = "/bin/hilog -x | grep ";
122     char finalCommand[COMMAND_SIZE];
123     int res = snprintf_s(finalCommand, COMMAND_SIZE, COMMAND_SIZE - 1, "%s%s", command, needToMatch);
124     if (res == NEGATIVE_ONE) {
125         printf("CheckHiLogPrint command generate snprintf_s failed\n");
126         return false;
127     }
128     finalCommand[COMMAND_SIZE - 1] = '\0';
129     char buffer[BUFFER_SIZE];
130     FILE* pipe = popen(finalCommand, "r");
131     if (pipe == nullptr) {
132         printf("CheckHiLogPrint: Failed to run command\n");
133         return false;
134     }
135 
136     // Read command output and print
137     while (fgets(buffer, BUFFER_SIZE, pipe) != nullptr) {
138         printf("%s", buffer);
139         ret = true;
140     }
141 
142     // Close the pipe and get the return value
143     int returnValue = pclose(pipe);
144     if (returnValue == FAIL_CLOSE) {
145         printf("CheckHiLogPrint pclose failed returnValue=-1 errno=%d\n", errno);
146     }
147     return ret;
148 }
149 
150 class HiLogBaseNDKTest : public testing::Test {
151 public:
152     static void SetUpTestCase();
TearDownTestCase()153     static void TearDownTestCase() {}
154     void SetUp();
TearDown()155     void TearDown() {}
156 };
157 
SetUpTestCase()158 void HiLogBaseNDKTest::SetUpTestCase()
159 {
160     (void)PopenToString("hilog -Q pidoff");
161     (void)PopenToString("hilog -Q domainoff");
162 }
163 
SetUp()164 void HiLogBaseNDKTest::SetUp()
165 {
166     (void)PopenToString("hilog -r");
167 }
168 
RandomStringGenerator(uint32_t logLen=16)169 static std::string RandomStringGenerator(uint32_t logLen = 16)
170 {
171     std::string str;
172     for (uint32_t i = 0; i < logLen; ++i) {
173         char newChar = rand() % ('z' - 'a') + 'a';
174         str.append(1, newChar);
175     }
176     return str;
177 }
178 
HiLogWriteTest(LogMethodFunc loggingMethod,uint32_t logCount,uint32_t logLen,bool isDebug)179 static void HiLogWriteTest(LogMethodFunc loggingMethod, uint32_t logCount, uint32_t logLen, bool isDebug)
180 {
181     std::string logMsg(RandomStringGenerator(logLen));
182     for (uint32_t i = 0; i < logCount; ++i) {
183         loggingMethod(logMsg + std::to_string(i));
184     }
185     if (logMsg.length() > MAX_LOG_LEN-1) {
186         logMsg = logMsg.substr(0, MAX_LOG_LEN-1);
187     }
188     usleep(1000); /* 1000: sleep 1 ms */
189     std::string logMsgs = PopenToString("/system/bin/hilog -x");
190     uint32_t realCount = 0;
191     std::stringstream ss(logMsgs);
192     std::string str;
193     while (!ss.eof()) {
194         getline(ss, str);
195         if (str.find(logMsg) != std::string::npos) {
196             ++realCount;
197         }
198     }
199     uint32_t allowedLeastLogCount = logCount - logCount * 1 / 10; /* 1 / 10: loss rate less than 10% */
200     if (isDebug) {
201         allowedLeastLogCount = 0; /* 0: debug log is allowed to be closed */
202     }
203     EXPECT_GE(realCount, allowedLeastLogCount);
204 }
205 
206 HWTEST_F(HiLogBaseNDKTest, SomeLogs, TestSize.Level1)
207 {
208     for(uint32_t i = 0; i < METHODS_NUMBER; ++i) {
209         std::cout << "Starting " << METHOD_NAMES[i] << " test\n";
210         HiLogWriteTest(LOG_C_METHODS[i], SOME_LOGS, SHORT_LOG, i == DEBUG_METHOD);
211     }
212 }
213 
214 HWTEST_F(HiLogBaseNDKTest, MoreLogs, TestSize.Level1)
215 {
216     for(uint32_t i = 0; i < METHODS_NUMBER; ++i) {
217         std::cout << "Starting " << METHOD_NAMES[i] << " test\n";
218         HiLogWriteTest(LOG_C_METHODS[i], MORE_LOGS, SHORT_LOG, i == DEBUG_METHOD);
219     }
220 }
221 
222 HWTEST_F(HiLogBaseNDKTest, LongLogs, TestSize.Level1)
223 {
224     for(uint32_t i = 0; i < METHODS_NUMBER; ++i) {
225         std::cout << "Starting " << METHOD_NAMES[i] << " test\n";
226         HiLogWriteTest(LOG_C_METHODS[i], 5, LONG_LOG, i == DEBUG_METHOD);
227     }
228 }
229 
230 HWTEST_F(HiLogBaseNDKTest, VeryLongLogs, TestSize.Level1)
231 {
232     for(uint32_t i = 0; i < METHODS_NUMBER; ++i) {
233         std::cout << "Starting " << METHOD_NAMES[i] << " test\n";
234         HiLogWriteTest(LOG_C_METHODS[i], 5, VERY_LONG_LOG, i == DEBUG_METHOD);
235     }
236 }
237 
238 HWTEST_F(HiLogBaseNDKTest, MemAllocTouch1, TestSize.Level1)
239 {
240     #undef TEXT_TO_CHECK
241     #define TEXT_TO_CHECK "Float potential mem alloc"
242     HILOG_BASE_ERROR(LOG_CORE, TEXT_TO_CHECK " %{public}515.2f", 123.3);
243     usleep(1000); /* 1000: sleep 1 ms */
244     std::string logMsgs = PopenToString("/system/bin/hilog -x");
245     uint32_t realCount = 0;
246     std::stringstream ss(logMsgs);
247     std::string str;
248     while (!ss.eof()) {
249         getline(ss, str);
250         if (str.find(TEXT_TO_CHECK) != std::string::npos) {
251             ++realCount;
252         }
253     }
254 
255     EXPECT_EQ(realCount, 1);
256 }
257 
258 HWTEST_F(HiLogBaseNDKTest, MemAllocTouch2, TestSize.Level1)
259 {
260     #undef TEXT_TO_CHECK
261     #define TEXT_TO_CHECK "Float potential mem alloc"
262     HILOG_BASE_ERROR(LOG_CORE, TEXT_TO_CHECK " %{public}000000005.00000002f", 123.3);
263     usleep(1000); /* 1000: sleep 1 ms */
264     std::string logMsgs = PopenToString("/system/bin/hilog -x");
265     uint32_t realCount = 0;
266     std::stringstream ss(logMsgs);
267     std::string str;
268     while (!ss.eof()) {
269         getline(ss, str);
270         if (str.find(TEXT_TO_CHECK) != std::string::npos) {
271             ++realCount;
272         }
273     }
274 
275     EXPECT_EQ(realCount, 1);
276 }
277 
278 HWTEST_F(HiLogBaseNDKTest, IsLoggable, TestSize.Level1)
279 {
280     EXPECT_TRUE(HiLogBaseIsLoggable(0xD002D00, LOG_TAG, LOG_DEBUG));
281     EXPECT_TRUE(HiLogBaseIsLoggable(0xD002D00, LOG_TAG, LOG_INFO));
282     EXPECT_TRUE(HiLogBaseIsLoggable(0xD002D00, LOG_TAG, LOG_WARN));
283     EXPECT_TRUE(HiLogBaseIsLoggable(0xD002D00, LOG_TAG, LOG_ERROR));
284     EXPECT_TRUE(HiLogBaseIsLoggable(0xD002D00, LOG_TAG, LOG_FATAL));
285     EXPECT_TRUE(HiLogBaseIsLoggable(0xD002D00, "abc", LOG_WARN));
286     EXPECT_FALSE(HiLogBaseIsLoggable(0xD002D00, "abc", LOG_LEVEL_MIN));
287 }
288 
289 HWTEST_F(HiLogBaseNDKTest, HilogBasePrintCheck, TestSize.Level1)
290 {
291     std::thread threads[THREAD_COUNT];
292     // Create threads and print logs concurrently. Logs printed by each thread cannot be lost.
293     for (int i = 0; i < THREAD_COUNT; i++) {
294         // Generate a random string, and then pass the subscript to the child thread through the value,
295         // so that the child thread can obtain the global data.
296         g_str[i] = RandomStringGenerator();
297         threads[i] = std::thread(FunctionPrintLog, i);
298     }
299     // Wait for the thread execution to complete.
300     for (int i = 0; i < THREAD_COUNT; i++) {
301         threads[i].join();
302         bool result = CheckHiLogPrint(g_str[i].data());
303         EXPECT_EQ(result, true);
304     }
305 }
306 } // namespace HiLogTest
307 } // namespace HiviewDFX
308 } // namespace OHOS