1 /*
2  * Copyright (c) 2022 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 #include <gtest/gtest.h>
16 #include <map>
17 #include <unistd.h>
18 #include <vector>
19 #include <v1_0/imemory_tracker_interface.h>
20 
21 #define private public
22 #include "executor/memory_dumper.h"
23 #undef private
24 #include "dump_client_main.h"
25 #include "dump_utils.h"
26 #include "hdf_base.h"
27 #include "executor/memory/memory_filter.h"
28 #include "executor/memory/memory_util.h"
29 #include "hidumper_test_utils.h"
30 #include "util/string_utils.h"
31 
32 using namespace testing::ext;
33 using namespace OHOS::HDI::Memorytracker::V1_0;
34 namespace OHOS {
35 namespace HiviewDFX {
36 class MemoryDumperTest : public testing::Test {
37 public:
38     static void SetUpTestCase(void);
39     static void TearDownTestCase(void);
40     void SetUp();
41     void TearDown();
42 };
43 
SetUpTestCase(void)44 void MemoryDumperTest::SetUpTestCase(void)
45 {
46 }
TearDownTestCase(void)47 void MemoryDumperTest::TearDownTestCase(void)
48 {
49 }
SetUp(void)50 void MemoryDumperTest::SetUp(void)
51 {
52 }
TearDown(void)53 void MemoryDumperTest::TearDown(void)
54 {
55 }
56 
57 /**
58  * @tc.name: MemoryDumperTest001
59  * @tc.desc: Test MemoryDumper has correct group.
60  * @tc.type: FUNC
61  * @tc.require: issueI5NWZQ
62  */
HWTEST_F(MemoryDumperTest, MemoryDumperTest001, TestSize.Level3)63 HWTEST_F(MemoryDumperTest, MemoryDumperTest001, TestSize.Level3)
64 {
65     std::string cmd = "hidumper --mem";
66     std::string str = "Anonymous Page";
67     ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
68 }
69 
70 /**
71  * @tc.name: MemoryDumperTest002
72  * @tc.desc: Test MemoryDumper has DMA group.
73  * @tc.type: FUNC
74  * @tc.require: issueI5NX04
75  */
HWTEST_F(MemoryDumperTest, MemoryDumperTest002, TestSize.Level3)76 HWTEST_F(MemoryDumperTest, MemoryDumperTest002, TestSize.Level3)
77 {
78     std::string cmd = "hidumper --mem";
79     std::string str = "DMA";
80     ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
81 }
82 
83 /**
84  * @tc.name: MemoryDumperTest003
85  * @tc.desc: Test MemoryDumper has correct group.
86  * @tc.type: FUNC
87  * @tc.require: issueI5NWZQ
88  */
HWTEST_F(MemoryDumperTest, MemoryDumperTest003, TestSize.Level3)89 HWTEST_F(MemoryDumperTest, MemoryDumperTest003, TestSize.Level3)
90 {
91     std::string cmd = "hidumper --mem 1";
92     std::string str = "Total";
93     ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
94     str = "native heap:";
95     ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
96     str = "Purgeable:";
97     ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
98     str = "DMA:";
99     ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
100 }
101 
102 /**
103  * @tc.name: MemoryDumperTest004
104  * @tc.desc: Test MemoryDumper has GPU group.
105  * @tc.type: FUNC
106  * @tc.require: issueI5NWZQ
107  */
HWTEST_F(MemoryDumperTest, MemoryDumperTest004, TestSize.Level3)108 HWTEST_F(MemoryDumperTest, MemoryDumperTest004, TestSize.Level3)
109 {
110     std::string cmd = "hidumper --mem";
111     std::string str = "GPU";
112     ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
113 }
114 
115 /**
116  * @tc.name: MemoryDumperTest005
117  * @tc.desc: Test MemoryDumper has Purgeable group.
118  * @tc.type: FUNC
119  * @tc.require: issueI5NWZQ
120  */
HWTEST_F(MemoryDumperTest, MemoryDumperTest005, TestSize.Level3)121 HWTEST_F(MemoryDumperTest, MemoryDumperTest005, TestSize.Level3)
122 {
123     std::string cmd = "hidumper --mem";
124     std::string str = "Total Purgeable";
125     ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
126     str = "Total PurgSum";
127     ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
128     str = "Total PurgPin";
129     ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
130 }
131 
132 /**
133  * @tc.name: MemoryDumperTest006
134  * @tc.desc: Test MemoryDumper has Dma/PurgSum/PurgPin group.
135  * @tc.type: FUNC
136  * @tc.require: issueI5NWZQ
137  */
HWTEST_F(MemoryDumperTest, MemoryDumperTest006, TestSize.Level3)138 HWTEST_F(MemoryDumperTest, MemoryDumperTest006, TestSize.Level3)
139 {
140     std::string cmd = "hidumper --mem";
141     std::string str = "Dma     PurgSum     PurgPin";
142     ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
143 }
144 
145 /**
146  * @tc.name: MemoryDumperTest007
147  * @tc.desc: Test zip memory not contain "Total Memory Usage by PID".
148  * @tc.type: FUNC
149  * @tc.require: issueI5NWZQ
150  */
HWTEST_F(MemoryDumperTest, MemoryDumperTest007, TestSize.Level3)151 HWTEST_F(MemoryDumperTest, MemoryDumperTest007, TestSize.Level3)
152 {
153     std::string cmd = "hidumper --mem --zip";
154     std::string str = "Total Memory Usage by PID";
155     ASSERT_FALSE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
156 }
157 
158 /**
159  * @tc.name: MemoryDumperTest008
160  * @tc.desc: Test dma is equal graph.
161  * @tc.type: FUNC
162  * @tc.require: issueI5NWZQ
163  */
HWTEST_F(MemoryDumperTest, MemoryDumperTest008, TestSize.Level3)164 HWTEST_F(MemoryDumperTest, MemoryDumperTest008, TestSize.Level3)
165 {
166     auto rsPid = static_cast<int32_t>(HidumperTestUtils::GetInstance().GetPidByName("render_service"));
167     int pid = rsPid > 0 ? rsPid : 1;
168     ASSERT_GT(pid, 0);
169     std::string cmd = "hidumper --mem " + std::to_string(pid);
170     std::string str = "Graph";
171     std::string result = "";
172     ASSERT_TRUE(HidumperTestUtils::GetInstance().GetSpecialLine(cmd, str, result));
173     std::string graphPss = HidumperTestUtils::GetInstance().GetValueInLine(result, 1);
174     ASSERT_TRUE(IsNumericStr(graphPss));
175     str = "Dma";
176     result = "";
177     ASSERT_TRUE(HidumperTestUtils::GetInstance().GetSpecialLine(cmd, str, result));
178     vector<string> values;
179     StringUtils::GetInstance().StringSplit(result, ":", values); // Dma:0 kB
180     std::string dmaStr = "";
181     if (!values.empty() && values.size() >= 2) { // 2: Dma, 0 kB
182         dmaStr = values[1];
183         if (dmaStr.size() >= 3) {
184             dmaStr = dmaStr.substr(0, dmaStr.size() - 4);  // 4: ' kB' + 1(index from to 0,1,2...)
185             ASSERT_TRUE(IsNumericStr(dmaStr));
186         }
187     }
188     ASSERT_TRUE(graphPss == dmaStr);
189 }
190 
191 /**
192  * @tc.name: MemoryDumperTest009
193  * @tc.desc: Test GL not out of bounds.
194  * @tc.type: FUNC
195  * @tc.require: issueI5NWZQ
196  */
HWTEST_F(MemoryDumperTest, MemoryDumperTest009, TestSize.Level3)197 HWTEST_F(MemoryDumperTest, MemoryDumperTest009, TestSize.Level3)
198 {
199     auto rsPid = static_cast<int32_t>(HidumperTestUtils::GetInstance().GetPidByName("render_service"));
200     int pid = rsPid > 0 ? rsPid : 1;
201     ASSERT_GT(pid, 0);
202     std::string cmd = "hidumper --mem " + std::to_string(pid);
203     std::string str = "GL";
204     std::string result = "";
205     ASSERT_TRUE(HidumperTestUtils::GetInstance().GetSpecialLine(cmd, str, result));
206     std::string glPss = HidumperTestUtils::GetInstance().GetValueInLine(result, 1);
207     ASSERT_TRUE(IsNumericStr(glPss));
208     uint64_t gl = static_cast<uint64_t>(std::stoi(glPss));
209     ASSERT_FALSE(gl < 0 || gl > UINT64_MAX);
210 }
211 
212 /**
213  * @tc.name: MemoryDumperTest010
214  * @tc.desc: Test HeapSize for "hidumper --mem `pidof com.ohos.sceneboard`"".
215  * @tc.type: FUNC
216  * @tc.require: issueI5NWZQ
217  */
HWTEST_F(MemoryDumperTest, MemoryDumperTest010, TestSize.Level3)218 HWTEST_F(MemoryDumperTest, MemoryDumperTest010, TestSize.Level3)
219 {
220     auto sceneboardPid = static_cast<int32_t>(HidumperTestUtils::GetInstance().GetPidByName("com.ohos.sceneboard"));
221     int pid = sceneboardPid > 0 ? sceneboardPid : 1;
222     ASSERT_GT(pid, 0);
223     std::string cmd = "hidumper --mem " + std::to_string(pid);
224     std::string str = "native heap";
225     std::string result = "";
226     ASSERT_TRUE(HidumperTestUtils::GetInstance().GetSpecialLine(cmd, str, result));
227     // 9: HeapSize index
228     std::string nativeHeapSizeStr = HidumperTestUtils::GetInstance().GetValueInLine(result, 9);
229     ASSERT_TRUE(IsNumericStr(nativeHeapSizeStr));
230     if (DumpUtils::IsHmKernel()) {
231         uint64_t nativeHeapSize = static_cast<uint64_t>(std::stoi(nativeHeapSizeStr));
232         ASSERT_TRUE(nativeHeapSize > 0);
233     }
234 }
235 
236 /**
237  * @tc.name: MemoryUtilTest001
238  * @tc.desc: Test IsNameLine has correct ret.
239  * @tc.type: FUNC
240  */
HWTEST_F(MemoryDumperTest, MemoryUtilTest001, TestSize.Level1)241 HWTEST_F(MemoryDumperTest, MemoryUtilTest001, TestSize.Level1)
242 {
243     const std::string valueLine = "Rss:                  24 kB";
244     std::string name;
245     uint64_t iNode = 0;
246     ASSERT_FALSE(MemoryUtil::GetInstance().IsNameLine(valueLine, name, iNode));
247     ASSERT_EQ(name, "");
248     const std::string nameLine = "ffb84000-ffba5000 rw-p 00000000 00:00 0                                  [stack]";
249     ASSERT_TRUE(MemoryUtil::GetInstance().IsNameLine(nameLine, name, iNode));
250     ASSERT_EQ(name, "[stack]");
251 }
252 
253 /**
254  * @tc.name: MemoryUtilTest002
255  * @tc.desc: Test GetTypeAndValue has correct ret.
256  * @tc.type: FUNC
257  */
HWTEST_F(MemoryDumperTest, MemoryUtilTest002, TestSize.Level1)258 HWTEST_F(MemoryDumperTest, MemoryUtilTest002, TestSize.Level1)
259 {
260     std::string type;
261     uint64_t value = 0;
262     const std::string illegalStr = "aaaaaa";
263     ASSERT_FALSE(MemoryUtil::GetInstance().GetTypeAndValue(illegalStr, type, value));
264     const std::string valueStr = "MemTotal:        2010244 kB";
265     ASSERT_TRUE(MemoryUtil::GetInstance().GetTypeAndValue(valueStr, type, value));
266     ASSERT_EQ(type, "MemTotal");
267     ASSERT_EQ(value, 2010244);
268 }
269 
270 /**
271  * @tc.name: MemoryUtilTest003
272  * @tc.desc: Test RunCMD has correct ret.
273  * @tc.type: FUNC
274  */
HWTEST_F(MemoryDumperTest, MemoryUtilTest003, TestSize.Level1)275 HWTEST_F(MemoryDumperTest, MemoryUtilTest003, TestSize.Level1)
276 {
277     const std::string cmd = "ps -ef";
278     std::vector<std::string> vec;
279     ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
280     ASSERT_GT(vec.size(), 0);
281 }
282 
283 /**
284  * @tc.name: MemoryUtilTest004
285  * @tc.desc: Test hidumper some cmd.
286  * @tc.type: FUNC
287  */
HWTEST_F(MemoryDumperTest, MemoryUtilTest004, TestSize.Level1)288 HWTEST_F(MemoryDumperTest, MemoryUtilTest004, TestSize.Level1)
289 {
290     std::string cmd = "hidumper --mem-smaps 1";
291     std::vector<std::string> vec;
292     ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
293     cmd = "hidumper --mem-smaps 1 -v";
294     ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
295     cmd = "hidumper --net 1";
296     ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
297     cmd = "hidumper --storage 1";
298     ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
299 }
300 
301 /**
302  * @tc.name: MemoryUtilTest005
303  * @tc.desc: Test no such pid.
304  * @tc.type: FUNC
305  */
HWTEST_F(MemoryDumperTest, MemoryUtilTest005, TestSize.Level1)306 HWTEST_F(MemoryDumperTest, MemoryUtilTest005, TestSize.Level1)
307 {
308     std::string cmd = "hidumper --mem-smaps 100000";
309     std::vector<std::string> vec;
310     ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
311     cmd = "hidumper --mem-smaps 100000 -v";
312     ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
313     cmd = "hidumper --cpuusage 100000";
314     ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
315     cmd = "hidumper --mem 100000";
316     ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
317     cmd = "hidumper -p 100000";
318     ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
319     cmd = "hidumper --storage 100000";
320     ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
321     cmd = "hidumper --net 100000";
322     ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
323     cmd = "hidumper --mem-jsheap 100000";
324     ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
325     cmd = "hidumper --mem-jsheap 0";
326     ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
327     cmd = "hidumper --ipc --stat 100000";
328     ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
329 }
330 } // namespace HiviewDFX
331 } // namespace OHOS