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