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 #include "hidumper_service_test.h"
16 #include <fstream>
17 #include <fcntl.h>
18 #include <iservice_registry.h>
19 #include "dump_manager_client.h"
20 #include "dump_manager_service.h"
21 #include "inner/dump_service_id.h"
22 #include "dump_on_demand_load.h"
23 #include "executor/memory/memory_util.h"
24 #include "string_ex.h"
25
26 using namespace std;
27 using namespace testing::ext;
28 using namespace OHOS;
29 using namespace OHOS::HiviewDFX;
30 namespace OHOS {
31 namespace HiviewDFX {
32 constexpr int32_t HidumperServiceTest::LIMIT_SIZE = 5000;
33 namespace {
WriteFile(const std::string & content,const std::string & filename)34 void WriteFile(const std::string &content, const std::string &filename)
35 {
36 std::ofstream outFile(filename);
37 if (!outFile) {
38 std::cerr << "open file failed: " << filename << std::endl;
39 return;
40 }
41
42 outFile << content;
43 outFile.close();
44
45 std::cout << "write success" << std::endl;
46 }
47
IsProcessExist(int pid)48 bool IsProcessExist(int pid)
49 {
50 string path = "/proc/" + to_string(pid);
51 return access(path.c_str(), F_OK) == 0;
52 }
53 }
54
SetUpTestCase(void)55 void HidumperServiceTest::SetUpTestCase(void)
56 {
57 }
58
TearDownTestCase(void)59 void HidumperServiceTest::TearDownTestCase(void)
60 {
61 }
62
SetUp(void)63 void HidumperServiceTest::SetUp(void)
64 {
65 }
66
TearDown(void)67 void HidumperServiceTest::TearDown(void)
68 {
69 }
70
71 /**
72 * @tc.name: HidumperServiceTest001
73 * @tc.desc: Test DumpManagerService service ready.
74 * @tc.type: FUNC
75 */
76 HWTEST_F(HidumperServiceTest, HidumperServiceTest001, TestSize.Level3)
77 {
78 sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
79 ASSERT_TRUE(sam != nullptr) << "HidumperServiceTest001 fail to get GetSystemAbilityManager";
80 sptr<OnDemandLoadCallback> loadCallback = new OnDemandLoadCallback();
81 int32_t result = sam->LoadSystemAbility(DFX_SYS_HIDUMPER_ABILITY_ID, loadCallback);
82 ASSERT_TRUE(result == ERR_OK) << "GetSystemAbility failed.";
83 }
84
85 /**
86 * @tc.name: DumpManagerService002
87 * @tc.desc: Test DumpManagerService Request.
88 * @tc.type: FUNC
89 */
90 HWTEST_F(HidumperServiceTest, DumpManagerService002, TestSize.Level3)
91 {
92 auto dumpManagerService = std::make_shared<DumpManagerService>();
93 dumpManagerService->OnStart();
94 dumpManagerService->started_ = true;
95 std::vector<std::u16string> args;
96 int32_t ret = ERR_OK;
97 ret = dumpManagerService->Dump(-1, args);
98 ASSERT_TRUE(ret == ERR_OK);
99 ret = dumpManagerService->Request(args, -1);
100 ASSERT_TRUE(ret == ERR_OK);
101
102 dumpManagerService->OnStop();
103 }
104
105 /**
106 * @tc.name: DumpManagerService003
107 * @tc.desc: Test DumpManagerService CountFdNums.
108 * @tc.type: FUNC
109 */
110 HWTEST_F(HidumperServiceTest, DumpManagerService003, TestSize.Level3)
111 {
112 auto dumpManagerService = std::make_shared<DumpManagerService>();
113 int32_t pid = 1;
114 uint32_t fdNums = 0;
115 std::string detailFdInfo;
116 std::vector<std::string> topLeakedTypeList;
117 int32_t ret = dumpManagerService->CountFdNums(pid, fdNums, detailFdInfo, topLeakedTypeList);
118 cout << "pid:" << pid << " fdNums:" << fdNums << endl;
119 cout << "topLeakedTypeList:" << endl;
120 for (const auto& type : topLeakedTypeList) {
121 cout << " " << type << endl;
122 }
123 cout << "detailFdInfo:" << endl << detailFdInfo << endl;
124 ASSERT_TRUE(ret == 0);
125 ASSERT_FALSE(detailFdInfo.empty());
126 ASSERT_FALSE(topLeakedTypeList.empty());
127 }
128
129 /**
130 * @tc.name: DumpManagerService004
131 * @tc.desc: Test DumpManagerService ScanPidOverLimit.
132 * @tc.type: FUNC
133 */
134 HWTEST_F(HidumperServiceTest, DumpManagerService004, TestSize.Level3)
135 {
136 auto dumpManagerService = std::make_shared<DumpManagerService>();
137 std::string requestType = "fd";
138 std::vector<int32_t> pidList;
139 int32_t ret = dumpManagerService->ScanPidOverLimit(requestType, LIMIT_SIZE, pidList);
140 ASSERT_TRUE(ret == 0);
141 ret = dumpManagerService->ScanPidOverLimit(requestType, 0, pidList);
142 ASSERT_TRUE(ret == 0);
143
144 ret = dumpManagerService->ScanPidOverLimit(requestType, -1, pidList);
145 ASSERT_TRUE(ret != 0);
146
147 requestType = "..";
148 ret = dumpManagerService->ScanPidOverLimit(requestType, 1, pidList);
149 ASSERT_TRUE(ret == 0);
150 }
151
152 /**
153 * @tc.name: DumpManagerService005
154 * @tc.desc: Test DumpManagerService Request.
155 * @tc.type: FUNC
156 */
157 HWTEST_F(HidumperServiceTest, DumpManagerService005, TestSize.Level3)
158 {
159 auto dumpManagerService = std::make_shared<DumpManagerService>();
160 dumpManagerService->OnStart();
161 dumpManagerService->started_ = true;
162 dumpManagerService->OnStart();
163
164 std::vector<std::u16string> args;
165 dumpManagerService->blockRequest_ = true;
166 int32_t ret = dumpManagerService->Request(args, -1);
167 ASSERT_TRUE(ret != 0);
168 dumpManagerService->blockRequest_ = false;
169 dumpManagerService->started_ = false;
170 ret = dumpManagerService->Request(args, -1);
171 ASSERT_TRUE(ret != 0);
172 dumpManagerService->OnStop();
173 dumpManagerService->started_ = false;
174 dumpManagerService->OnStop();
175 }
176
177 /**
178 * @tc.name: DumpManagerService006
179 * @tc.desc: Test DumpManagerService error request.
180 * @tc.type: FUNC
181 */
182 HWTEST_F(HidumperServiceTest, DumpManagerService006, TestSize.Level3)
183 {
184 auto dumpManagerService = std::make_shared<DumpManagerService>();
185 std::vector<std::u16string> args;
186 int outfd = -1;
187 dumpManagerService->HandleRequestError(args, outfd, -1, "test");
188 ASSERT_TRUE(args.size() == 0);
189 args.push_back(Str8ToStr16("test"));
190 dumpManagerService->HandleRequestError(args, outfd, -1, "test");
191 ASSERT_TRUE(args.size() == 0);
192 }
193
194 /**
195 * @tc.name: DumpManagerService007
196 * @tc.desc: Test DumpManagerService OnIdle.
197 * @tc.type: FUNC
198 */
199 HWTEST_F(HidumperServiceTest, DumpManagerService007, TestSize.Level3)
200 {
201 auto dumpManagerService = std::make_shared<DumpManagerService>();
202 SystemAbilityOnDemandReason idleReason;
203 int32_t ret = dumpManagerService->OnIdle(idleReason);
204 ASSERT_TRUE(ret == 0);
205 idleReason.SetId(OnDemandReasonId::INTERFACE_CALL);
206 ret = dumpManagerService->OnIdle(idleReason);
207 ASSERT_TRUE(ret == 0);
208 std::vector<std::u16string> args;
209 args.push_back(Str8ToStr16("test"));
210 dumpManagerService->AddRequestRawParam(args, -1);
211 ret = dumpManagerService->OnIdle(idleReason);
212 ASSERT_TRUE(ret == 120000);
213 dumpManagerService->SetCpuSchedAffinity();
214 }
215
216 /**
217 * @tc.name: DumpManagerService008
218 * @tc.desc: Test DumpManagerService GetFdLink with invalid symlink.
219 * @tc.type: FUNC
220 */
221 HWTEST_F(HidumperServiceTest, DumpManagerService008, TestSize.Level3)
222 {
223 const std::string invalidLinkPath = "/tmp/nonexistent_link";
224 auto dumpManagerService = std::make_shared<DumpManagerService>();
225 std::string result = dumpManagerService->GetFdLink(invalidLinkPath);
226 printf("Retrieved symlink content: '%s'\n", result.c_str());
227 ASSERT_TRUE(result == "unknown");
228 WriteFile(result, "/data/local/tmp/DumpManagerService008_result");
229 }
230
231 /**
232 * @tc.name: DumpManagerService009
233 * @tc.desc: Test DumpManagerService GetFdLinks with valid symlinks.
234 * @tc.type: FUNC
235 */
236 HWTEST_F(HidumperServiceTest, DumpManagerService009, TestSize.Level1)
237 {
238 int pid = 1;
239 auto dumpService = std::make_shared<DumpManagerService>();
240 std::vector<std::string> links = dumpService->GetFdLinks(pid);
241
242 cout << "links.size:" << links.size() << endl;
243
244 EXPECT_GT(links.size(), 0);
245
246 std::cout << "DumpManagerService009 passed with " << links.size() << " links." << std::endl;
247 }
248
249 /**
250 * @tc.name: DumpManagerService010
251 * @tc.desc: Test DumpManagerService GetFdLinks with non-existent fd directory.
252 * @tc.type: FUNC
253 */
254 HWTEST_F(HidumperServiceTest, DumpManagerService010, TestSize.Level1)
255 {
256 int pid = 65533;
257 // 确保该进程不存在
258 if (IsProcessExist(pid)) {
259 GTEST_SKIP() << "进程 " << pid << " 已经存在,跳过测试。";
260 }
261
262 auto dumpService = std::make_shared<DumpManagerService>();
263 std::vector<std::string> links = dumpService->GetFdLinks(pid);
264 EXPECT_TRUE(links.empty());
265 std::cout << "DumpManagerService010 passed with empty links." << std::endl;
266 }
267
268 /**
269 * @tc.name: DumpManagerService011
270 * @tc.desc: Test MaybeKnownType with valid eventfd type in link.
271 * @tc.type: FUNC
272 */
273 HWTEST_F(HidumperServiceTest, DumpManagerService011, TestSize.Level3)
274 {
275 std::string link = "eventfd";
276 auto dumpManagerService = std::make_shared<DumpManagerService>();
277 std::string result = dumpManagerService->MaybeKnownType(link);
278 ASSERT_TRUE(result == "eventfd");
279 std::cout << "DumpManagerService011 passed for eventfd." << std::endl;
280 }
281
282 /**
283 * @tc.name: DumpManagerService012
284 * @tc.desc: Test MaybeKnownType with valid eventpoll type in link.
285 * @tc.type: FUNC
286 */
287 HWTEST_F(HidumperServiceTest, DumpManagerService012, TestSize.Level3)
288 {
289 std::string link = "eventpoll";
290 auto dumpManagerService = std::make_shared<DumpManagerService>();
291 std::string result = dumpManagerService->MaybeKnownType(link);
292 ASSERT_TRUE(result == "eventpoll");
293 std::cout << "DumpManagerService012 passed for eventpoll." << std::endl;
294 }
295
296 /**
297 * @tc.name: DumpManagerService013
298 * @tc.desc: Test MaybeKnownType with valid sync_file type in link.
299 * @tc.type: FUNC
300 */
301 HWTEST_F(HidumperServiceTest, DumpManagerService013, TestSize.Level3)
302 {
303 std::string link = "/proc/123/fd/4->sync_file";
304 auto dumpManagerService = std::make_shared<DumpManagerService>();
305 std::string result = dumpManagerService->MaybeKnownType(link);
306 ASSERT_TRUE(result == "sync_file");
307 std::cout << "DumpManagerService013 passed for sync_file." << std::endl;
308 }
309
310 /**
311 * @tc.name: DumpManagerService014
312 * @tc.desc: Test MaybeKnownType with valid dmabuf type in link.
313 * @tc.type: FUNC
314 */
315 HWTEST_F(HidumperServiceTest, DumpManagerService014, TestSize.Level3)
316 {
317 std::string link = "dmabuf";
318 auto dumpManagerService = std::make_shared<DumpManagerService>();
319 std::string result = dumpManagerService->MaybeKnownType(link);
320 ASSERT_TRUE(result == "dmabuf");
321 std::cout << "DumpManagerService014 passed for dmabuf." << std::endl;
322 }
323
324 /**
325 * @tc.name: DumpManagerService015
326 * @tc.desc: Test MaybeKnownType with valid socket type in link.
327 * @tc.type: FUNC
328 */
329 HWTEST_F(HidumperServiceTest, DumpManagerService015, TestSize.Level3)
330 {
331 std::string link = "socket:[12345]";
332 auto dumpManagerService = std::make_shared<DumpManagerService>();
333 std::string result = dumpManagerService->MaybeKnownType(link);
334 ASSERT_TRUE(result == "socket");
335 std::cout << "DumpManagerService015 passed for socket." << std::endl;
336 }
337
338 /**
339 * @tc.name: DumpManagerService016
340 * @tc.desc: Test MaybeKnownType with valid pipe type in link.
341 * @tc.type: FUNC
342 */
343 HWTEST_F(HidumperServiceTest, DumpManagerService016, TestSize.Level3)
344 {
345 std::string link = "pipe:1234";
346 auto dumpManagerService = std::make_shared<DumpManagerService>();
347 std::string result = dumpManagerService->MaybeKnownType(link);
348 ASSERT_TRUE(result == "pipe");
349 std::cout << "DumpManagerService016 passed for pipe." << std::endl;
350 }
351
352 /**
353 * @tc.name: DumpManagerService017
354 * @tc.desc: Test MaybeKnownType with valid ashmem type in link.
355 * @tc.type: FUNC
356 */
357 HWTEST_F(HidumperServiceTest, DumpManagerService017, TestSize.Level3)
358 {
359 std::string link = "ashmem: /dev/ashmem";
360 auto dumpManagerService = std::make_shared<DumpManagerService>();
361 std::string result = dumpManagerService->MaybeKnownType(link);
362 ASSERT_TRUE(result == "ashmem");
363 std::cout << "DumpManagerService017 passed for ashmem." << std::endl;
364 }
365
366 /**
367 * @tc.name: DumpManagerService018
368 * @tc.desc: Test MaybeKnownType with unknown type in link.
369 * @tc.type: FUNC
370 */
371 HWTEST_F(HidumperServiceTest, DumpManagerService018, TestSize.Level3)
372 {
373 std::string link = "/dev/random-file";
374 auto dumpManagerService = std::make_shared<DumpManagerService>();
375 std::string result = dumpManagerService->MaybeKnownType(link);
376 ASSERT_TRUE(result == "unknown");
377 std::cout << "DumpManagerService018 passed for unknown type." << std::endl;
378 }
379
380 /**
381 * @tc.name: DumpManagerService019
382 * @tc.desc: Test MaybeKnownType with multiple known types in link (returns first match).
383 * @tc.type: FUNC
384 */
385 HWTEST_F(HidumperServiceTest, DumpManagerService019, TestSize.Level3)
386 {
387 std::string link = "eventfd_with_pipe";
388 auto dumpManagerService = std::make_shared<DumpManagerService>();
389 std::string result = dumpManagerService->MaybeKnownType(link);
390 ASSERT_TRUE(result == "eventfd");
391 std::cout << "DumpManagerService019 passed for priority match." << std::endl;
392 }
393
394 /**
395 * @tc.name: DumpManagerService020
396 * @tc.desc: Test CountPaths with multiple paths, check if counts are correct.
397 * @tc.type: FUNC
398 */
399 HWTEST_F(HidumperServiceTest, DumpManagerService020, TestSize.Level3)
400 {
401 // 准备测试数据
402 std::vector<std::string> links = {
403 "/data/log/a.txt",
404 "/data/log/b.txt",
405 "/data/log/a.txt",
406 "/data/log/c.txt",
407 "/data/log/b.txt",
408 "/data/log/b.txt"
409 };
410
411 // 创建 DumpManagerService 实例
412 auto dumpManagerService = std::make_shared<DumpManagerService>();
413
414 // 调用待测函数
415 std::unordered_map<std::string, int> result = dumpManagerService->CountPaths(links);
416
417 // 预期结果
418 std::unordered_map<std::string, int> expected = {
419 { "/data/log/a.txt", 2 },
420 { "/data/log/b.txt", 3 },
421 { "/data/log/c.txt", 1 }
422 };
423
424 // 断言结果是否与预期一致
425 ASSERT_TRUE(result == expected);
426 std::cout << "DumpManagerService020 passed for path counting." << std::endl;
427 }
428
429 /**
430 * @tc.name: DumpManagerService021
431 * @tc.desc: Test TopN with valid input and n >= counter size.
432 * @tc.type: FUNC
433 */
434 HWTEST_F(HidumperServiceTest, DumpManagerService021, TestSize.Level3)
435 {
436 std::unordered_map<std::string, int> counter = {
437 {"eventfd", 10}, {"pipe", 8}, {"ashmem", 7}, {"socket", 12}, {"unknown1", 5}
438 };
439 size_t n = 3;
440 auto dumpManagerService = std::make_shared<DumpManagerService>();
441 std::vector<std::pair<std::string, int>> result = dumpManagerService->TopN(counter, n);
442
443 EXPECT_EQ(result.size(), 3);
444 EXPECT_EQ(result[0].first, "socket");
445 EXPECT_EQ(result[0].second, 12);
446 EXPECT_EQ(result[1].first, "eventfd");
447 EXPECT_EQ(result[1].second, 10);
448 EXPECT_EQ(result[2].first, "pipe");
449 EXPECT_EQ(result[2].second, 8);
450 std::cout << "DumpManagerService021 passed: Top3 entries correct." << std::endl;
451 }
452
453 /**
454 * @tc.name: DumpManagerService022
455 * @tc.desc: Test TopN when n is larger than counter size.
456 * @tc.type: FUNC
457 */
458 HWTEST_F(HidumperServiceTest, DumpManagerService022, TestSize.Level3)
459 {
460 std::unordered_map<std::string, int> counter = {{"a", 3}, {"b", 2}, {"c", 1}};
461 size_t n = 5;
462 auto dumpManagerService = std::make_shared<DumpManagerService>();
463 std::vector<std::pair<std::string, int>> result = dumpManagerService->TopN(counter, n);
464
465 EXPECT_EQ(result.size(), 3);
466 EXPECT_EQ(result[0].first, "a");
467 EXPECT_EQ(result[1].first, "b");
468 EXPECT_EQ(result[2].first, "c");
469 std::cout << "DumpManagerService022 passed: All entries returned when n > size." << std::endl;
470 }
471
472 /**
473 * @tc.name: DumpManagerService023
474 * @tc.desc: Test TopN with empty counter.
475 * @tc.type: FUNC
476 */
477 HWTEST_F(HidumperServiceTest, DumpManagerService023, TestSize.Level3)
478 {
479 std::unordered_map<std::string, int> counter = {};
480 size_t n = 2;
481 auto dumpManagerService = std::make_shared<DumpManagerService>();
482 std::vector<std::pair<std::string, int>> result = dumpManagerService->TopN(counter, n);
483
484 EXPECT_TRUE(result.empty());
485 std::cout << "DumpManagerService023 passed: Empty counter returns empty list." << std::endl;
486 }
487
488 /**
489 * @tc.name: DumpManagerService024
490 * @tc.desc: Test heap replacement logic in TopN.
491 * @tc.type: FUNC
492 */
493 HWTEST_F(HidumperServiceTest, DumpManagerService024, TestSize.Level3)
494 {
495 std::unordered_map<std::string, int> counter = {
496 {"a", 1}, {"b", 3}, {"c", 2}, {"d", 5}, {"e", 4}
497 };
498 size_t n = 3;
499 auto dumpManagerService = std::make_shared<DumpManagerService>();
500 std::vector<std::pair<std::string, int>> result = dumpManagerService->TopN(counter, n);
501
502 EXPECT_EQ(result.size(), 3);
503 EXPECT_EQ(result[0].first, "d");
504 EXPECT_EQ(result[0].second, 5);
505 EXPECT_EQ(result[1].first, "e");
506 EXPECT_EQ(result[1].second, 4);
507 EXPECT_EQ(result[2].first, "b");
508 EXPECT_EQ(result[2].second, 3);
509 std::cout << "DumpManagerService024 passed: Heap replacement logic works as expected." << std::endl;
510 }
511
512 /**
513 * @tc.name: DumpManagerService025
514 * @tc.desc: Test GetTopFdInfo with normal input containing multiple entries.
515 * @tc.type: FUNC
516 */
517 HWTEST_F(HidumperServiceTest, DumpManagerService025, TestSize.Level3)
518 {
519 std::vector<std::pair<std::string, int>> topLinks = {
520 {"eventfd", 3},
521 {"pipe", 5},
522 {"ashmem", 2}
523 };
524 auto dumpManagerService = std::make_shared<DumpManagerService>();
525 std::string result = dumpManagerService->GetTopFdInfo(topLinks);
526 std::string expected = "3\teventfd\n5\tpipe\n2\tashmem\n";
527 EXPECT_EQ(result, expected);
528 std::cout << "DumpManagerService025 passed: Normal input format correct." << std::endl;
529 }
530
531 /**
532 * @tc.name: DumpManagerService026
533 * @tc.desc: Test GetTopFdInfo with empty input.
534 * @tc.type: FUNC
535 */
536 HWTEST_F(HidumperServiceTest, DumpManagerService026, TestSize.Level3)
537 {
538 std::vector<std::pair<std::string, int>> topLinks = {};
539 auto dumpManagerService = std::make_shared<DumpManagerService>();
540 std::string result = dumpManagerService->GetTopFdInfo(topLinks);
541 std::string expected = "";
542 EXPECT_EQ(result, expected);
543 std::cout << "DumpManagerService026 passed: Empty input returns empty string." << std::endl;
544 }
545
546 /**
547 * @tc.name: DumpManagerService027
548 * @tc.desc: Test GetTopFdInfo with single entry.
549 * @tc.type: FUNC
550 */
551 HWTEST_F(HidumperServiceTest, DumpManagerService027, TestSize.Level3)
552 {
553 std::vector<std::pair<std::string, int>> topLinks = {{"socket", 1}};
554 auto dumpManagerService = std::make_shared<DumpManagerService>();
555 std::string result = dumpManagerService->GetTopFdInfo(topLinks);
556 std::string expected = "1\tsocket\n";
557 EXPECT_EQ(result, expected);
558 std::cout << "DumpManagerService027 passed: Single entry returns correct string." << std::endl;
559 }
560
561 /**
562 * @tc.name: DumpManagerService028
563 * @tc.desc: Test GetTopFdInfo with non-ASCII characters in names.
564 * @tc.type: FUNC
565 */
566 HWTEST_F(HidumperServiceTest, DumpManagerService028, TestSize.Level3)
567 {
568 std::vector<std::pair<std::string, int>> topLinks = {
569 {"fd\\twith\\tnull", 2},
570 {"file\\nwith\\nnewline", 3}
571 };
572 auto dumpManagerService = std::make_shared<DumpManagerService>();
573 std::string result = dumpManagerService->GetTopFdInfo(topLinks);
574 std::string expected = "2\tfd\\twith\\tnull\n3\tfile\\nwith\\nnewline\n";
575 EXPECT_EQ(result, expected);
576 std::cout << "DumpManagerService028 passed: Non-ASCII characters in names handled properly." << std::endl;
577 }
578
579 /**
580 * @tc.name: DumpManagerService029
581 * @tc.desc: Test GetTopDirInfo with paths exceeding FD_TOP_CNT (10).
582 * @tc.type: FUNC
583 */
584 HWTEST_F(HidumperServiceTest, DumpManagerService029, TestSize.Level3)
585 {
586 std::vector<std::pair<std::string, int>> topTypes = {
587 {"eventfd", 50} // Arbitrary value for total
588 };
589 std::map<std::string, std::unordered_map<std::string, int>> typePaths = {
590 {"eventfd", {
591 {"path1", 5},
592 {"path2", 4},
593 {"path3", 3},
594 {"path4", 2},
595 {"path5", 1},
596 {"path6", 6},
597 {"path7", 7},
598 {"path8", 8},
599 {"path9", 9},
600 {"path10", 10},
601 {"path11", 11}, // Exceed FD_TOP_CNT (10)
602 {"path12", 12},
603 }}
604 };
605 auto dumpManagerService = std::make_shared<DumpManagerService>();
606 std::string result = dumpManagerService->GetTopDirInfo(topTypes, typePaths);
607 std::string expected = "50\teventfd\n012\tpath12\n011\tpath11\n010\tpath10\n09\tpath9\n08\tpath8\n"
608 "07\tpath7\n06\tpath6\n05\tpath1\n04\tpath2\n03\tpath3\n";
609 EXPECT_EQ(result, expected);
610 std::cout << "DumpManagerService029 passed: Paths exceeding FD_TOP_CNT add ellipsis." << std::endl;
611 }
612
613 /**
614 * @tc.name: DumpManagerService030
615 * @tc.desc: Test GetTopDirInfo with empty input
616 * @tc.type: FUNC
617 */
618 HWTEST_F(HidumperServiceTest, DumpManagerService030, TestSize.Level3)
619 {
620 std::vector<std::pair<std::string, int>> topTypes = {};
621 std::map<std::string, std::unordered_map<std::string, int>> typePaths = {};
622 auto dumpManagerService = std::make_shared<DumpManagerService>();
623 std::string result = dumpManagerService->GetTopDirInfo(topTypes, typePaths);
624 std::string expected = "";
625 EXPECT_EQ(result, expected);
626 std::cout << "DumpManagerService030 passed: Empty input returns empty string." << std::endl;
627 }
628
629 /**
630 * @tc.name: DumpManagerService031
631 * @tc.desc: Test GetTopDirInfo with type path equal to type name
632 * @tc.type: FUNC
633 */
634 HWTEST_F(HidumperServiceTest, DumpManagerService031, TestSize.Level3)
635 {
636 std::vector<std::pair<std::string, int>> topTypes = {
637 {"socket", 5}
638 };
639 std::map<std::string, std::unordered_map<std::string, int>> typePaths = {
640 {"socket", {
641 {"socket_2", 3},
642 {"socket_1", 2}
643 }}
644 };
645 auto dumpManagerService = std::make_shared<DumpManagerService>();
646 std::string result = dumpManagerService->GetTopDirInfo(topTypes, typePaths);
647 std::string expected = "5 socket\n03\tsocket_2\n02\tsocket_1\n";
648 EXPECT_EQ(result, expected);
649 std::cout << "DumpManagerService031 passed: Skip path equal to type name." << std::endl;
650 }
651
652 /**
653 * @tc.name: DumpManagerService032
654 * @tc.desc: Test GetSummary when both vectors are empty
655 * @tc.type: FUNC
656 */
657 HWTEST_F(HidumperServiceTest, DumpManagerService032, TestSize.Level3)
658 {
659 std::vector<std::pair<std::string, int>> topLinks{};
660 std::vector<std::pair<std::string, int>> topTypes{};
661 auto dumpManagerService = std::make_shared<DumpManagerService>();
662 std::string result = dumpManagerService->GetSummary(topLinks, topTypes);
663 std::string expected = "";
664 EXPECT_EQ(result, expected);
665 std::cout << "DumpManagerService032 passed: Both vectors empty returns empty." << std::endl;
666 }
667
668 /**
669 * @tc.name: DumpManagerService033
670 * @tc.desc: Test GetSummary when only topLinks is empty
671 * @tc.type: FUNC
672 */
673 HWTEST_F(HidumperServiceTest, DumpManagerService033, TestSize.Level3)
674 {
675 std::vector<std::pair<std::string, int>> topLinks{};
676 std::vector<std::pair<std::string, int>> topTypes = {{"dir_inode", 10}};
677 auto dumpManagerService = std::make_shared<DumpManagerService>();
678 std::string result = dumpManagerService->GetSummary(topLinks, topTypes);
679 std::string expected = "Leaked dir:dir_inode";
680 EXPECT_EQ(result, expected);
681 std::cout << "DumpManagerService033 passed: Only topTypes has data." << std::endl;
682 }
683
684 /**
685 * @tc.name: DumpManagerService034
686 * @tc.desc: Test GetSummary when only topTypes is empty
687 * @tc.type: FUNC
688 */
689 HWTEST_F(HidumperServiceTest, DumpManagerService034, TestSize.Level3)
690 {
691 std::vector<std::pair<std::string, int>> topLinks = {{"fd_pipe", 7}};
692 std::vector<std::pair<std::string, int>> topTypes{};
693 auto dumpManagerService = std::make_shared<DumpManagerService>();
694 std::string result = dumpManagerService->GetSummary(topLinks, topTypes);
695 std::string expected = "Leaked fd:fd_pipe";
696 EXPECT_EQ(result, expected);
697 std::cout << "DumpManagerService034 passed: Only topLinks has data." << std::endl;
698 }
699
700 /**
701 * @tc.name: DumpManagerService035
702 * @tc.desc: Test GetSummary when topLinks count is greater
703 * @tc.type: FUNC
704 */
705 HWTEST_F(HidumperServiceTest, DumpManagerService035, TestSize.Level3)
706 {
707 std::vector<std::pair<std::string, int>> topLinks = {{"fd_char", 10}};
708 std::vector<std::pair<std::string, int>> topTypes = {{"dir_block", 5}};
709 auto dumpManagerService = std::make_shared<DumpManagerService>();
710 std::string result = dumpManagerService->GetSummary(topLinks, topTypes);
711 std::string expected = "Leaked fd:fd_char";
712 EXPECT_EQ(result, expected);
713 std::cout << "DumpManagerService035 passed: Link count dominates." << std::endl;
714 }
715
716 /**
717 * @tc.name: DumpManagerService036
718 * @tc.desc: Test GetSummary when counts are equal
719 * @tc.type: FUNC
720 */
721 HWTEST_F(HidumperServiceTest, DumpManagerService036, TestSize.Level3)
722 {
723 std::vector<std::pair<std::string, int>> topLinks = {{"fd_dev", 8}};
724 std::vector<std::pair<std::string, int>> topTypes = {{"dir_dev", 8}};
725 auto dumpManagerService = std::make_shared<DumpManagerService>();
726 std::string result = dumpManagerService->GetSummary(topLinks, topTypes);
727 std::string expected = "Leaked fd:fd_dev";
728 EXPECT_EQ(result, expected);
729 std::cout << "DumpManagerService036 passed: Equal counts choose fd." << std::endl;
730 }
731 } // namespace HiviewDFX
732 } // namespace OHOS
733