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 <gtest/gtest.h>
24 #include <hilog_common.h>
25 
26 #include "hilog_base/log_base.h"
27 
28 #undef LOG_DOMAIN
29 #define LOG_DOMAIN 0xD002D00
30 
31 #undef LOG_TAG
32 #define LOG_TAG "HILOGBASETEST"
33 
34 using namespace testing::ext;
35 
36 namespace OHOS {
37 namespace HiviewDFX {
38 namespace HiLogBaseTest {
39 static constexpr unsigned int SOME_LOGS = 10;
40 static constexpr unsigned int MORE_LOGS = 100;
41 static constexpr unsigned int SHORT_LOG = 16;
42 static constexpr unsigned int LONG_LOG = 1000;
43 static constexpr unsigned int VERY_LONG_LOG = 2048;
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<std::string, METHODS_NUMBER> METHOD_NAMES = {
57     "Debug", "Info", "Warn", "Error", "Fatal"
58 };
59 
60 static const std::array<LogMethodFunc, METHODS_NUMBER> LOG_C_METHODS = {
__anon83c8caff0102() 61     [] (const std::string &msg) {
62         HILOG_BASE_DEBUG(LOG_CORE, "%{public}s", msg.c_str());
63     },
__anon83c8caff0202() 64     [] (const std::string &msg) {
65         HILOG_BASE_INFO(LOG_CORE, "%{public}s", msg.c_str());
66     },
__anon83c8caff0302() 67     [] (const std::string &msg) {
68         HILOG_BASE_WARN(LOG_CORE, "%{public}s", msg.c_str());
69     },
__anon83c8caff0402() 70     [] (const std::string &msg) {
71         HILOG_BASE_ERROR(LOG_CORE, "%{public}s", msg.c_str());
72     },
__anon83c8caff0502() 73     [] (const std::string &msg) {
74         HILOG_BASE_FATAL(LOG_CORE, "%{public}s", msg.c_str());
75     },
76 };
77 
PopenToString(const std::string & command)78 static std::string PopenToString(const std::string &command)
79 {
80     std::string str;
81     constexpr int bufferSize = 1024;
82     FILE *fp = popen(command.c_str(), "re");
83     if (fp != nullptr) {
84         char buf[bufferSize] = {0};
85         size_t n = fread(buf, 1, sizeof(buf), fp);
86         while (n > 0) {
87             str.append(buf, n);
88             n = fread(buf, 1, sizeof(buf), fp);
89         }
90         pclose(fp);
91     }
92     return str;
93 }
94 
95 class HiLogBaseNDKTest : public testing::Test {
96 public:
97     static void SetUpTestCase();
TearDownTestCase()98     static void TearDownTestCase() {}
99     void SetUp();
TearDown()100     void TearDown() {}
101 };
102 
SetUpTestCase()103 void HiLogBaseNDKTest::SetUpTestCase()
104 {
105     (void)PopenToString("hilog -Q pidoff");
106     (void)PopenToString("hilog -Q domainoff");
107 }
108 
SetUp()109 void HiLogBaseNDKTest::SetUp()
110 {
111     (void)PopenToString("hilog -r");
112 }
113 
RandomStringGenerator(uint32_t logLen=16)114 static std::string RandomStringGenerator(uint32_t logLen = 16)
115 {
116     std::string str;
117     for (uint32_t i = 0; i < logLen; ++i) {
118         char newChar = rand() % ('z' - 'a') + 'a';
119         str.append(1, newChar);
120     }
121     return str;
122 }
123 
HiLogWriteTest(LogMethodFunc loggingMethod,uint32_t logCount,uint32_t logLen,bool isDebug)124 static void HiLogWriteTest(LogMethodFunc loggingMethod, uint32_t logCount, uint32_t logLen, bool isDebug)
125 {
126     std::string logMsg(RandomStringGenerator(logLen));
127     for (uint32_t i = 0; i < logCount; ++i) {
128         loggingMethod(logMsg + std::to_string(i));
129     }
130     if (logMsg.length() > MAX_LOG_LEN-1) {
131         logMsg = logMsg.substr(0, MAX_LOG_LEN-1);
132     }
133     usleep(1000); /* 1000: sleep 1 ms */
134     std::string logMsgs = PopenToString("/system/bin/hilog -x");
135     uint32_t realCount = 0;
136     std::stringstream ss(logMsgs);
137     std::string str;
138     while (!ss.eof()) {
139         getline(ss, str);
140         if (str.find(logMsg) != std::string::npos) {
141             ++realCount;
142         }
143     }
144     uint32_t allowedLeastLogCount = logCount - logCount * 1 / 10; /* 1 / 10: loss rate less than 10% */
145     if (isDebug) {
146         allowedLeastLogCount = 0; /* 0: debug log is allowed to be closed */
147     }
148     EXPECT_GE(realCount, allowedLeastLogCount);
149 }
150 
151 HWTEST_F(HiLogBaseNDKTest, SomeLogs, TestSize.Level1)
152 {
153     for(uint32_t i = 0; i < METHODS_NUMBER; ++i) {
154         std::cout << "Starting " << METHOD_NAMES[i] << " test\n";
155         HiLogWriteTest(LOG_C_METHODS[i], SOME_LOGS, SHORT_LOG, i == DEBUG_METHOD);
156     }
157 }
158 
159 HWTEST_F(HiLogBaseNDKTest, MoreLogs, TestSize.Level1)
160 {
161     for(uint32_t i = 0; i < METHODS_NUMBER; ++i) {
162         std::cout << "Starting " << METHOD_NAMES[i] << " test\n";
163         HiLogWriteTest(LOG_C_METHODS[i], MORE_LOGS, SHORT_LOG, i == DEBUG_METHOD);
164     }
165 }
166 
167 HWTEST_F(HiLogBaseNDKTest, LongLogs, TestSize.Level1)
168 {
169     for(uint32_t i = 0; i < METHODS_NUMBER; ++i) {
170         std::cout << "Starting " << METHOD_NAMES[i] << " test\n";
171         HiLogWriteTest(LOG_C_METHODS[i], 5, LONG_LOG, i == DEBUG_METHOD);
172     }
173 }
174 
175 HWTEST_F(HiLogBaseNDKTest, VeryLongLogs, TestSize.Level1)
176 {
177     for(uint32_t i = 0; i < METHODS_NUMBER; ++i) {
178         std::cout << "Starting " << METHOD_NAMES[i] << " test\n";
179         HiLogWriteTest(LOG_C_METHODS[i], 5, VERY_LONG_LOG, i == DEBUG_METHOD);
180     }
181 }
182 
183 HWTEST_F(HiLogBaseNDKTest, MemAllocTouch1, TestSize.Level1)
184 {
185     #undef TEXT_TO_CHECK
186     #define TEXT_TO_CHECK "Float potential mem alloc"
187     HILOG_BASE_ERROR(LOG_CORE, TEXT_TO_CHECK " %{public}515.2f", 123.3);
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(TEXT_TO_CHECK) != std::string::npos) {
196             ++realCount;
197         }
198     }
199 
200     EXPECT_EQ(realCount, 1);
201 }
202 
203 HWTEST_F(HiLogBaseNDKTest, MemAllocTouch2, TestSize.Level1)
204 {
205     #undef TEXT_TO_CHECK
206     #define TEXT_TO_CHECK "Float potential mem alloc"
207     HILOG_BASE_ERROR(LOG_CORE, TEXT_TO_CHECK " %{public}000000005.00000002f", 123.3);
208     usleep(1000); /* 1000: sleep 1 ms */
209     std::string logMsgs = PopenToString("/system/bin/hilog -x");
210     uint32_t realCount = 0;
211     std::stringstream ss(logMsgs);
212     std::string str;
213     while (!ss.eof()) {
214         getline(ss, str);
215         if (str.find(TEXT_TO_CHECK) != std::string::npos) {
216             ++realCount;
217         }
218     }
219 
220     EXPECT_EQ(realCount, 1);
221 }
222 
223 HWTEST_F(HiLogBaseNDKTest, IsLoggable, TestSize.Level1)
224 {
225     EXPECT_TRUE(HiLogBaseIsLoggable(0xD002D00, LOG_TAG, LOG_DEBUG));
226     EXPECT_TRUE(HiLogBaseIsLoggable(0xD002D00, LOG_TAG, LOG_INFO));
227     EXPECT_TRUE(HiLogBaseIsLoggable(0xD002D00, LOG_TAG, LOG_WARN));
228     EXPECT_TRUE(HiLogBaseIsLoggable(0xD002D00, LOG_TAG, LOG_ERROR));
229     EXPECT_TRUE(HiLogBaseIsLoggable(0xD002D00, LOG_TAG, LOG_FATAL));
230     EXPECT_TRUE(HiLogBaseIsLoggable(0xD002D00, "abc", LOG_WARN));
231     EXPECT_FALSE(HiLogBaseIsLoggable(0xD002D00, "abc", LOG_LEVEL_MIN));
232 }
233 
234 } // namespace HiLogTest
235 } // namespace HiviewDFX
236 } // namespace OHOS
237