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 
16 #include "dump_usage.h"
17 #include "cpu_dumper.h"
18 #include "executor/memory/get_heap_info.h"
19 #include "executor/memory/memory_info.h"
20 #include "executor/memory/parse/parse_smaps_info.h"
21 #include "hidumper_test_utils.h"
22 #include "securec.h"
23 
24 #include <gtest/gtest.h>
25 #include <unistd.h>
26 
27 using namespace testing::ext;
28 namespace OHOS {
29 namespace HiviewDFX {
30 static constexpr int MALLOC_SIZE = 1024;
31 static constexpr int LAUNCHER_PID_BUFFER_SIZE = 6;
32 static int g_pid = -1;
33 static int g_appManagerPid = -1;
34 const int HIDUMPER_SERVICE_RAM = 20480; //hidumper_service RAM:20MB
35 class HiDumperInnerkitsTest : public testing::Test {
36 public:
37     using ValueMap = std::map<std::string, uint64_t>;
38     using GroupMap = std::map<std::string, ValueMap>;
39     static void SetUpTestCase(void);
40     static void TearDownTestCase(void);
41     void SetUp();
42     void TearDown();
43     static void GetAppManagerPids();
44     static int GetAppManagerPid(std::string process);
45     static void StartTestProcess();
46     static void StopProcess();
47 };
48 
SetUpTestCase(void)49 void HiDumperInnerkitsTest::SetUpTestCase(void)
50 {
51     GetAppManagerPids();
52     StartTestProcess();
53     if (g_pid < 0) {
54         printf("[SetUpTestCase] fork process failure!\n");
55         return;
56     }
57     if (g_pid == 0) {
58         printf("[SetUpTestCase] this process's pid is %d, it's should be child process\n", getpid());
59         return;
60     }
61 }
TearDownTestCase(void)62 void HiDumperInnerkitsTest::TearDownTestCase(void)
63 {
64     if (g_pid < 0) {
65         printf("[TearDownTestCase] fork process failure!\n");
66         return;
67     }
68     if (g_pid == 0) {
69         printf("[TearDownTestCase] this process's pid is %d, it's should be child process\n", getpid());
70         return;
71     }
72     StopProcess();
73 }
SetUp(void)74 void HiDumperInnerkitsTest::SetUp(void)
75 {
76 }
TearDown(void)77 void HiDumperInnerkitsTest::TearDown(void)
78 {
79 }
80 
StartTestProcess()81 void HiDumperInnerkitsTest::StartTestProcess()
82 {
83     int processNum = fork();
84     if (processNum == 0) {
85         while (true) {
86             void* p = malloc(MALLOC_SIZE);
87             if (p == nullptr) {
88                 const int bufSize = 256;
89                 char buf[bufSize] = { 0 };
90                 (void)strerror_r(errno, buf, bufSize);
91                 printf("malloc failure, errno(%d:%s)", errno, buf);
92                 return;
93             }
94             usleep(1);
95             free(p);
96         }
97     } else {
98         g_pid = processNum;
99     }
100 }
101 
StopProcess()102 void HiDumperInnerkitsTest::StopProcess()
103 {
104     std::string stopCmd = "kill " + std::to_string(g_pid);
105     system(stopCmd.c_str());
106 }
107 
GetAppManagerPids()108 void HiDumperInnerkitsTest::GetAppManagerPids()
109 {
110     std::vector<std::string> processes = {"com.ohos.launcher", "com.ohos.medialibrary.medialibrarydata", "hiview",
111         "com.ohos.settingsdata", "com.ohos.systemui", "render_service"};
112     for (std::vector<std::string>::iterator iter = processes.begin(); iter != processes.end(); iter++) {
113         int res = GetAppManagerPid(*iter);
114         if (res > 0) {
115             g_appManagerPid = res;
116             break;
117         }
118     }
119 }
120 
GetAppManagerPid(std::string process)121 int HiDumperInnerkitsTest::GetAppManagerPid(std::string process)
122 {
123     std::string cmd = "pidof " + process;
124     char appManagerPidChar[LAUNCHER_PID_BUFFER_SIZE] = {"\0"};
125     int appManagerPid = -1;
126     FILE *fp = nullptr;
127     fp = popen(cmd.c_str(), "r");
128     if (fp == nullptr) {
129         return -1;
130     }
131     if (fgets(appManagerPidChar, sizeof(appManagerPidChar), fp) != nullptr) {
132         pclose(fp);
133         int ret = sscanf_s(appManagerPidChar, "%d", &appManagerPid);
134         if (ret <= 0) {
135             return -1;
136         }
137         return appManagerPid;
138     }
139     pclose(fp);
140     return -1;
141 }
142 
143 /**
144  * @tc.name: GetMemInfoTest001
145  * @tc.desc: Test GetMemInfo.
146  * @tc.type: FUNC
147  * @tc.require: issueI5NWZQ
148  */
HWTEST_F(HiDumperInnerkitsTest, GetMemInfoTest001, TestSize.Level1)149 HWTEST_F(HiDumperInnerkitsTest, GetMemInfoTest001, TestSize.Level1)
150 {
151     std::unique_ptr<DumpUsage> dumpUsage = std::make_unique<DumpUsage>();
152     MemInfoData::MemInfo info;
153     EXPECT_TRUE(dumpUsage->GetMemInfo(g_pid, info));
154     EXPECT_GT(info.pss, 0);
155 }
156 
157 /**
158  * @tc.name: GetPssTest001
159  * @tc.desc: Test GetPss.
160  * @tc.type: FUNC
161  * @tc.require: issueI5NWZQ
162  */
HWTEST_F(HiDumperInnerkitsTest, GetPssTest001, TestSize.Level1)163 HWTEST_F(HiDumperInnerkitsTest, GetPssTest001, TestSize.Level1)
164 {
165     std::unique_ptr<DumpUsage> dumpUsage = std::make_unique<DumpUsage>();
166     EXPECT_GT(dumpUsage->GetPss(g_pid), 0);
167 }
168 
169 /**
170  * @tc.name: GetPssTest002
171  * @tc.desc: Test GetPss for hidumper_service.
172  * @tc.type: FUNC
173  * @tc.require: issueI5NWZQ
174  */
HWTEST_F(HiDumperInnerkitsTest, GetPssTest002, TestSize.Level1)175 HWTEST_F(HiDumperInnerkitsTest, GetPssTest002, TestSize.Level1)
176 {
177     std::string cmd = "hidumper --mem 1";
178     std::string str = "memory";
179     ASSERT_TRUE(HidumperTestUtils::GetInstance().IsExistInCmdResult(cmd, str));
180     std::unique_ptr<DumpUsage> dumpUsage = std::make_unique<DumpUsage>();
181     int hidumperServicePid = GetAppManagerPid("hidumper_service");
182     uint64_t pss = dumpUsage->GetPss(hidumperServicePid);
183     std::cout << "hidumper_service pss: " << pss << std::endl;
184     EXPECT_LE(pss, HIDUMPER_SERVICE_RAM);
185 }
186 
187 /**
188  * @tc.name: GetPrivateDirtyTest001
189  * @tc.desc: Test GetPrivateDirty.
190  * @tc.type: FUNC
191  * @tc.require: issueI5NWZQ
192  */
HWTEST_F(HiDumperInnerkitsTest, GetPrivateDirtyTest001, TestSize.Level1)193 HWTEST_F(HiDumperInnerkitsTest, GetPrivateDirtyTest001, TestSize.Level1)
194 {
195     std::unique_ptr<DumpUsage> dumpUsage = std::make_unique<DumpUsage>();
196     EXPECT_GE(dumpUsage->GetPrivateDirty(g_pid), 0);
197 }
198 
199 /**
200  * @tc.name: GetSharedDirtyTest001
201  * @tc.desc: Test GetSharedDirty.
202  * @tc.type: FUNC
203  * @tc.require: issueI5NWZQ
204  */
HWTEST_F(HiDumperInnerkitsTest, GetSharedDirtyTest001, TestSize.Level1)205 HWTEST_F(HiDumperInnerkitsTest, GetSharedDirtyTest001, TestSize.Level1)
206 {
207     std::unique_ptr<DumpUsage> dumpUsage = std::make_unique<DumpUsage>();
208     EXPECT_GE(dumpUsage->GetSharedDirty(g_pid), 0);
209 }
210 
211 /**
212  * @tc.name: GetCpuUsage001
213  * @tc.desc: Test GetCpuUsage.
214  * @tc.type: FUNC
215  * @tc.require: issueI5NWZQ
216  */
217 #ifdef HIDUMPER_HIVIEWDFX_HIVIEW_ENABLE
HWTEST_F(HiDumperInnerkitsTest, GetCpuUsage001, TestSize.Level1)218 HWTEST_F(HiDumperInnerkitsTest, GetCpuUsage001, TestSize.Level1)
219 {
220     std::unique_ptr<DumpUsage> dumpUsage = std::make_unique<DumpUsage>();
221     EXPECT_GE(dumpUsage->GetCpuUsage(g_pid), 0);
222 }
223 #endif
224 
225 /**
226  * @tc.name: GetProcCpuInfo001
227  * @tc.desc: Test GetProcCpuInfo when a new process appeared.
228  * @tc.type: FUNC
229  */
230 #ifdef HIDUMPER_HIVIEWDFX_HIVIEW_ENABLE
HWTEST_F(HiDumperInnerkitsTest, GetProcCpuInfo001, TestSize.Level1)231 HWTEST_F(HiDumperInnerkitsTest, GetProcCpuInfo001, TestSize.Level1)
232 {
233     auto parameter = std::make_shared<DumperParameter>();
234     DumperOpts opts;
235     opts.isDumpCpuUsage_ = true;
236     opts.cpuUsagePid_ = g_pid;
237     parameter->SetOpts(opts);
238     auto dumpDatas = std::make_shared<std::vector<std::vector<std::string>>>();
239     auto cpuDumper = std::make_shared<CPUDumper>();
240     int ret = DumpStatus::DUMP_FAIL;
241     ret = cpuDumper->PreExecute(parameter, dumpDatas);
242     ASSERT_EQ(ret, DumpStatus::DUMP_OK);
243     ret = cpuDumper->Execute();
244     ASSERT_EQ(ret, DumpStatus::DUMP_OK);
245     ret = cpuDumper->AfterExecute();
246     ASSERT_EQ(ret, DumpStatus::DUMP_OK);
247 }
248 #endif
249 
250 /**
251  * @tc.name: GetProcCpuInfo001
252  * @tc.desc: Test GetProcCpuInfo when a new process appeared.
253  * @tc.type: FUNC
254  */
HWTEST_F(HiDumperInnerkitsTest, GetHeapInfo001, TestSize.Level1)255 HWTEST_F(HiDumperInnerkitsTest, GetHeapInfo001, TestSize.Level1)
256 {
257     int testPid = g_pid;
258     GroupMap groupMap;
259     std::map<std::string, uint64_t> value = {};
260     value["test"] = 1;
261     groupMap["test"] = value;
262     std::unique_ptr<GetHeapInfo> getHeapInfo = std::make_unique<GetHeapInfo>();
263     ASSERT_TRUE(getHeapInfo->GetInfo(MemoryFilter::APPOINT_PID, testPid, groupMap));
264 
265     if (g_appManagerPid != -1) {
266         testPid = g_appManagerPid;
267         ASSERT_TRUE(getHeapInfo->GetInfo(MemoryFilter::APPOINT_PID, testPid, groupMap));
268     }
269 }
270 
271 /**
272  * @tc.name: ParseSmapsInfoGetInfoTest001
273  * @tc.desc: Test GetMemInfo.
274  * @tc.type: FUNC
275  * @tc.require: issueI5NWZQ
276  */
HWTEST_F(HiDumperInnerkitsTest, ParseSmapsInfoGetInfoTest001, TestSize.Level1)277 HWTEST_F(HiDumperInnerkitsTest, ParseSmapsInfoGetInfoTest001, TestSize.Level1)
278 {
279     std::unique_ptr<ParseSmapsInfo> parseSmapsInfo = std::make_unique<ParseSmapsInfo>();
280     GroupMap groupMap;
281     GroupMap nativeGroupMap;
282     EXPECT_TRUE(parseSmapsInfo->GetInfo(MemoryFilter::APPOINT_PID, 1, nativeGroupMap, groupMap));
283 }
284 } // namespace HiviewDFX
285 } // namespace OHOS
286