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 */
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 */
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 */
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 = " PurgSum:0 kB";
99 ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
100 str = " PurgPin:0 kB";
101 ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
102 str = "DMA:";
103 ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
104 }
105
106 /**
107 * @tc.name: MemoryDumperTest004
108 * @tc.desc: Test MemoryDumper has GPU group.
109 * @tc.type: FUNC
110 * @tc.require: issueI5NWZQ
111 */
112 HWTEST_F(MemoryDumperTest, MemoryDumperTest004, TestSize.Level3)
113 {
114 std::string cmd = "hidumper --mem";
115 std::string str = "GPU";
116 ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
117 }
118
119 /**
120 * @tc.name: MemoryDumperTest005
121 * @tc.desc: Test MemoryDumper has Purgeable group.
122 * @tc.type: FUNC
123 * @tc.require: issueI5NWZQ
124 */
125 HWTEST_F(MemoryDumperTest, MemoryDumperTest005, TestSize.Level3)
126 {
127 std::string cmd = "hidumper --mem";
128 std::string str = "Total Purgeable";
129 ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
130 str = "Total PurgSum";
131 ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
132 str = "Total PurgPin";
133 ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
134 }
135
136 /**
137 * @tc.name: MemoryDumperTest006
138 * @tc.desc: Test MemoryDumper has Dma/PurgSum/PurgPin group.
139 * @tc.type: FUNC
140 * @tc.require: issueI5NWZQ
141 */
142 HWTEST_F(MemoryDumperTest, MemoryDumperTest006, TestSize.Level3)
143 {
144 std::string cmd = "hidumper --mem";
145 std::string str = "Dma PurgSum PurgPin";
146 ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
147 }
148
149 /**
150 * @tc.name: MemoryDumperTest007
151 * @tc.desc: Test zip memory not contain "Total Memory Usage by PID".
152 * @tc.type: FUNC
153 * @tc.require: issueI5NWZQ
154 */
155 HWTEST_F(MemoryDumperTest, MemoryDumperTest007, TestSize.Level3)
156 {
157 std::string cmd = "hidumper --mem --zip";
158 std::string str = "Total Memory Usage by PID";
159 ASSERT_FALSE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
160 }
161
162 /**
163 * @tc.name: MemoryDumperTest008
164 * @tc.desc: Test dma is equal graph.
165 * @tc.type: FUNC
166 * @tc.require: issueI5NWZQ
167 */
168 HWTEST_F(MemoryDumperTest, MemoryDumperTest008, TestSize.Level3)
169 {
170 auto rsPid = static_cast<int32_t>(HidumperTestUtils::GetInstance().GetPidByName("render_service"));
171 int pid = rsPid > 0 ? rsPid : 1;
172 ASSERT_GT(pid, 0);
173 std::string cmd = "hidumper --mem " + std::to_string(pid);
174 std::string str = "Graph";
175 std::string result = "";
176 ASSERT_TRUE(HidumperTestUtils::GetInstance().GetSpecialLine(cmd, str, result));
177 std::string graphPss = HidumperTestUtils::GetInstance().GetValueInLine(result, 1);
178 ASSERT_TRUE(IsNumericStr(graphPss));
179 str = "Dma";
180 result = "";
181 ASSERT_TRUE(HidumperTestUtils::GetInstance().GetSpecialLine(cmd, str, result));
182 vector<string> values;
183 StringUtils::GetInstance().StringSplit(result, ":", values); // Dma:0 kB
184 std::string dmaStr = "";
185 if (!values.empty() && values.size() >= 2) { // 2: Dma, 0 kB
186 dmaStr = values[1];
187 if (dmaStr.size() >= 3) {
188 dmaStr = dmaStr.substr(0, dmaStr.size() - 4); // 4: ' kB' + 1(index from to 0,1,2...)
189 ASSERT_TRUE(IsNumericStr(dmaStr));
190 }
191 }
192 ASSERT_TRUE(graphPss == dmaStr);
193 }
194
195 /**
196 * @tc.name: MemoryDumperTest009
197 * @tc.desc: Test GL not out of bounds.
198 * @tc.type: FUNC
199 * @tc.require: issueI5NWZQ
200 */
201 HWTEST_F(MemoryDumperTest, MemoryDumperTest009, TestSize.Level3)
202 {
203 auto rsPid = static_cast<int32_t>(HidumperTestUtils::GetInstance().GetPidByName("render_service"));
204 int pid = rsPid > 0 ? rsPid : 1;
205 ASSERT_GT(pid, 0);
206 std::string cmd = "hidumper --mem " + std::to_string(pid);
207 std::string str = "GL";
208 std::string result = "";
209 ASSERT_TRUE(HidumperTestUtils::GetInstance().GetSpecialLine(cmd, str, result));
210 std::string glPss = HidumperTestUtils::GetInstance().GetValueInLine(result, 1);
211 ASSERT_TRUE(IsNumericStr(glPss));
212 uint64_t gl = static_cast<uint64_t>(std::stoi(glPss));
213 ASSERT_FALSE(gl < 0 || gl > UINT64_MAX);
214 }
215
216 /**
217 * @tc.name: MemoryDumperTest010
218 * @tc.desc: Test HeapSize for "hidumper --mem `pidof com.ohos.sceneboard`"".
219 * @tc.type: FUNC
220 * @tc.require: issueI5NWZQ
221 */
222 HWTEST_F(MemoryDumperTest, MemoryDumperTest010, TestSize.Level3)
223 {
224 auto sceneboardPid = static_cast<int32_t>(HidumperTestUtils::GetInstance().GetPidByName("com.ohos.sceneboard"));
225 int pid = sceneboardPid > 0 ? sceneboardPid : 1;
226 ASSERT_GT(pid, 0);
227 std::string cmd = "hidumper --mem " + std::to_string(pid);
228 std::string str = "native heap";
229 std::string result = "";
230 ASSERT_TRUE(HidumperTestUtils::GetInstance().GetSpecialLine(cmd, str, result));
231 // 9: HeapSize index
232 std::string nativeHeapSizeStr = HidumperTestUtils::GetInstance().GetValueInLine(result, 9);
233 ASSERT_TRUE(IsNumericStr(nativeHeapSizeStr));
234 if (DumpUtils::IsHmKernel()) {
235 uint64_t nativeHeapSize = static_cast<uint64_t>(std::stoi(nativeHeapSizeStr));
236 ASSERT_TRUE(nativeHeapSize > 0);
237 }
238 }
239
240 /**
241 * @tc.name: MemoryDumperTest011
242 * @tc.desc: Test MemoryDumper has correct print.
243 * @tc.type: FUNC
244 * @tc.require: issueI5NWZQ
245 */
246 HWTEST_F(MemoryDumperTest, MemoryDumperTest011, TestSize.Level3)
247 {
248 std::string cmd = "hidumper --mem";
249 std::string str = "-------------------------------[memory]-------------------------------";
250 ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
251 str = "Total Memory Usage by PID:";
252 ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
253 std::string titleTmp = "PID Total Pss(xxx in SwapPss) Total Vss Total Rss Total Uss";
254 str = titleTmp + " GL Graph Dma PurgSum PurgPin Name";
255 ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
256 str = "Total Memory Usage by Size:";
257 ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
258 str = "Total Pss by OOM adjustment:";
259 ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
260 }
261
262 /**
263 * @tc.name: MemoryDumperTest012
264 * @tc.desc: Test --mem-smaps has correct print.
265 * @tc.type: FUNC
266 * @tc.require: issueI5NWZQ
267 */
268 HWTEST_F(MemoryDumperTest, MemoryDumperTest012, TestSize.Level3)
269 {
270 std::string cmd = "hidumper --mem-smaps 1";
271 std::string str = "-------------------------------[memory]-------------------------------";
272 ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
273 std::string titleTmp = "Size Rss Pss Clean Dirty Clean Dirty";
274 str = titleTmp + " Swap SwapPss Counts Category Name";
275 ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
276 str = ".so /system";
277 ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
278 str = " Summary";
279 ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
280 }
281
282 /**
283 * @tc.name: MemoryDumperTest013
284 * @tc.desc: Test --mem-smaps -v has correct print.
285 * @tc.type: FUNC
286 * @tc.require: issueI5NWZQ
287 */
288 HWTEST_F(MemoryDumperTest, MemoryDumperTest013, TestSize.Level3)
289 {
290 std::string cmd = "hidumper --mem-smaps 1 -v";
291 std::string str = "-------------------------------[memory]-------------------------------";
292 ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
293 std::string titleTmp = "Size Rss Pss Clean Dirty Clean Dirty Swap";
294 str = titleTmp + " SwapPss Perm Start End Category Name";
295 ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
296 str = "dev /dev";
297 ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
298 str = " Summary";
299 ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
300 }
301
302 /**
303 * @tc.name: MemoryDumperTest014
304 * @tc.desc: Test hidumper --mem --prune has correct print.
305 * @tc.type: FUNC
306 * @tc.require: issueI5NWZQ
307 */
308 HWTEST_F(MemoryDumperTest, MemoryDumperTest014, TestSize.Level3)
309 {
310 std::string cmd = "hidumper --mem --prune";
311 std::string str = "-------------------------------[memory]-------------------------------";
312 ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
313 str = "Total Memory Usage by PID:";
314 ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
315 str = "PID Total Pss(xxx in SwapPss) GL AdjLabel Name";
316 ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
317 }
318
319 /**
320 * @tc.name: MemoryUtilTest001
321 * @tc.desc: Test IsNameLine has correct ret.
322 * @tc.type: FUNC
323 */
324 HWTEST_F(MemoryDumperTest, MemoryUtilTest001, TestSize.Level1)
325 {
326 const std::string valueLine = "Rss: 24 kB";
327 std::string name;
328 uint64_t iNode = 0;
329 ASSERT_FALSE(MemoryUtil::GetInstance().IsNameLine(valueLine, name, iNode));
330 ASSERT_EQ(name, "");
331 const std::string nameLine = "ffb84000-ffba5000 rw-p 00000000 00:00 0 [stack]";
332 ASSERT_TRUE(MemoryUtil::GetInstance().IsNameLine(nameLine, name, iNode));
333 ASSERT_EQ(name, "[stack]");
334 }
335
336 /**
337 * @tc.name: MemoryUtilTest002
338 * @tc.desc: Test GetTypeAndValue has correct ret.
339 * @tc.type: FUNC
340 */
341 HWTEST_F(MemoryDumperTest, MemoryUtilTest002, TestSize.Level1)
342 {
343 std::string type;
344 uint64_t value = 0;
345 const std::string illegalStr = "aaaaaa";
346 ASSERT_FALSE(MemoryUtil::GetInstance().GetTypeAndValue(illegalStr, type, value));
347 const std::string valueStr = "MemTotal: 2010244 kB";
348 ASSERT_TRUE(MemoryUtil::GetInstance().GetTypeAndValue(valueStr, type, value));
349 ASSERT_EQ(type, "MemTotal");
350 ASSERT_EQ(value, 2010244);
351 }
352
353 /**
354 * @tc.name: MemoryUtilTest003
355 * @tc.desc: Test RunCMD has correct ret.
356 * @tc.type: FUNC
357 */
358 HWTEST_F(MemoryDumperTest, MemoryUtilTest003, TestSize.Level1)
359 {
360 const std::string cmd = "ps -ef";
361 std::vector<std::string> vec;
362 ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
363 ASSERT_GT(vec.size(), 0);
364 }
365
366 /**
367 * @tc.name: MemoryUtilTest004
368 * @tc.desc: Test hidumper some cmd.
369 * @tc.type: FUNC
370 */
371 HWTEST_F(MemoryDumperTest, MemoryUtilTest004, TestSize.Level1)
372 {
373 std::string cmd = "hidumper --mem-smaps 1";
374 std::vector<std::string> vec;
375 ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
376 cmd = "hidumper --mem-smaps 1 -v";
377 ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
378 cmd = "hidumper --net 1";
379 ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
380 cmd = "hidumper --storage 1";
381 ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
382 }
383
384 /**
385 * @tc.name: MemoryUtilTest005
386 * @tc.desc: Test no such pid.
387 * @tc.type: FUNC
388 */
389 HWTEST_F(MemoryDumperTest, MemoryUtilTest005, TestSize.Level1)
390 {
391 std::string cmd = "hidumper --mem-smaps 100000";
392 std::vector<std::string> vec;
393 ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
394 cmd = "hidumper --mem-smaps 100000 -v";
395 ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
396 cmd = "hidumper --cpuusage 100000";
397 ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
398 cmd = "hidumper --mem 100000";
399 ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
400 cmd = "hidumper -p 100000";
401 ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
402 cmd = "hidumper --storage 100000";
403 ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
404 cmd = "hidumper --net 100000";
405 ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
406 cmd = "hidumper --mem-jsheap 100000";
407 ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
408 cmd = "hidumper --mem-jsheap 0";
409 ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
410 cmd = "hidumper --mem-cjheap 100000";
411 ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
412 cmd = "hidumper --mem-cjheap 0";
413 ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
414 cmd = "hidumper --ipc --stat 100000";
415 ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
416 }
417
418 /**
419 * @tc.name: MemoryUtilTest006
420 * @tc.desc: Test hidumper process exit success.
421 * @tc.type: FUNC
422 */
423 HWTEST_F(MemoryDumperTest, MemoryUtilTest006, TestSize.Level1)
424 {
425 std::vector<std::string> vec;
426 std::string cmd = "hidumper -h";
427 ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
428 ASSERT_GT(vec.size(), 0);
429 vec.clear();
430 cmd = "pidof hidumper";
431 ASSERT_TRUE(MemoryUtil::GetInstance().RunCMD(cmd, vec));
432 ASSERT_EQ(vec.size(), 0);
433 }
434 } // namespace HiviewDFX
435 } // namespace OHOS