1 /*
2  * Copyright (c) 2024 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 <fcntl.h>
16 #include <vector>
17 #include <unistd.h>
18 #include <cstdlib>
19 #include <gtest/gtest.h>
20 #include <string_ex.h>
21 #include "inner/dump_service_id.h"
22 #include "dump_client_main.h"
23 #include "dump_controller.h"
24 #include "dump_manager_client.h"
25 #include "app_mgr_client.h"
26 
27 using namespace testing::ext;
28 using namespace std;
29 using OHOS::HiviewDFX::DumpClientMain;
30 using OHOS::AppExecFwk::AppMgrClient;
31 using OHOS::AppExecFwk::RunningProcessInfo;
32 namespace OHOS {
33 namespace HiviewDFX {
34 const std::string TOOL_NAME = "hidumper";
35 const int BUFFER_SIZE = 1024;
36 class HidumperClientTest : 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 HidumperClientTest::SetUpTestCase(void)
45 {
46 }
47 
TearDownTestCase(void)48 void HidumperClientTest::TearDownTestCase(void)
49 {
50 }
51 
SetUp(void)52 void HidumperClientTest::SetUp(void)
53 {
54 }
55 
TearDown(void)56 void HidumperClientTest::TearDown(void)
57 {
58 }
59 
60 /**
61  * @tc.name: ClientMainTest001
62  * @tc.desc: Test too many arguments.
63  * @tc.type: FUNC
64  */
65 HWTEST_F(HidumperClientTest, ClientMainTest001, TestSize.Level0)
66 {
67     char *argv[] = {
68         const_cast<char *>(TOOL_NAME.c_str()),
69     };
70     int argc = ARG_MAX_COUNT + 1;
71     int ret = DumpClientMain::GetInstance().Main(argc, argv, STDOUT_FILENO);
72     ASSERT_EQ(ret, DumpStatus::DUMP_INVALID_ARG);
73 }
74 
75 /**
76  * @tc.name: ClientMainTest002
77  * @tc.desc: Test empty argument.
78  * @tc.type: FUNC
79  */
80 HWTEST_F(HidumperClientTest, ClientMainTest002, TestSize.Level0)
81 {
82     char *argv[] = {
83         const_cast<char *>(TOOL_NAME.c_str()),
84         const_cast<char *>("--mem"),
85         const_cast<char *>("-1"),
86         const_cast<char *>(""),
87         const_cast<char *>("--mem"),
88     };
89     int argc = sizeof(argv) / sizeof(argv[0]) - 1;
90     int ret = DumpClientMain::GetInstance().Main(argc, argv, STDOUT_FILENO);
91     ASSERT_EQ(ret, DumpStatus::DUMP_INVALID_ARG);
92 }
93 
94 /**
95  * @tc.name: ClientMainTest003
96  * @tc.desc: Test too long argument .
97  * @tc.type: FUNC
98  */
99 HWTEST_F(HidumperClientTest, ClientMainTest003, TestSize.Level0)
100 {
101     std::string longArg;
102     longArg.assign(SINGLE_ARG_MAXLEN + 1, 'c');
103     char *argv[] = {
104         const_cast<char *>(TOOL_NAME.c_str()),
105         const_cast<char *>("-h"),
106         const_cast<char *>(longArg.c_str()),
107     };
108     int argc = sizeof(argv) / sizeof(argv[0]);
109     int ret = DumpClientMain::GetInstance().Main(argc, argv, STDOUT_FILENO);
110     ASSERT_EQ(ret, DumpStatus::DUMP_INVALID_ARG);
111 }
112 
113 /**
114  * @tc.name: ClientMainTest004
115  * @tc.desc: Test null argument.
116  * @tc.type: FUNC
117  */
118 HWTEST_F(HidumperClientTest, ClientMainTest004, TestSize.Level0)
119 {
120     char *argv[] = {
121         const_cast<char *>(TOOL_NAME.c_str()),
122         nullptr,
123     };
124     int argc = sizeof(argv) / sizeof(argv[0]);
125     int ret = DumpClientMain::GetInstance().Main(argc, argv, STDOUT_FILENO);
126     ASSERT_EQ(ret, DumpStatus::DUMP_INVALID_ARG);
127 }
128 
129 /**
130  * @tc.name: ClientMainTest005
131  * @tc.desc: Test null fd.
132  * @tc.type: FUNC
133  */
134 HWTEST_F(HidumperClientTest, ClientMainTest005, TestSize.Level0)
135 {
136     char *argv[] = {
137         const_cast<char *>("hidumper"),
138         const_cast<char *>("--mem"),
139         const_cast<char *>("1"),
140     };
141     int argc = sizeof(argv) / sizeof(argv[0]);
142     int fd = open("/dev/null", O_RDWR | O_CREAT | O_TRUNC, 0664);
143     if (fd <= 0) {
144         fd = STDERR_FILENO;
145     }
146     int ret = DumpClientMain::GetInstance().Main(argc, argv, fd);
147     ASSERT_EQ(ret, DumpStatus::DUMP_OK);
148 }
149 
150 /**
151  * @tc.name: ClientMainTest006
152  * @tc.desc: Test null argv.
153  * @tc.type: FUNC
154  */
155 HWTEST_F(HidumperClientTest, ClientMainTest006, TestSize.Level0)
156 {
157     int argc = ARG_MAX_COUNT;
158     int ret = DumpClientMain::GetInstance().Main(argc, nullptr, STDOUT_FILENO);
159     ASSERT_EQ(ret, DumpStatus::DUMP_INVALID_ARG);
160 }
161 
162 /**
163  * @tc.name: ManagerClientTest001
164  * @tc.desc: Test emtpy argument list.
165  * @tc.type: FUNC
166  */
167 HWTEST_F(HidumperClientTest, ManagerClientTest001, TestSize.Level0)
168 {
169     vector<u16string> args{};
170     int ret = DumpManagerClient::GetInstance().Request(args, STDOUT_FILENO);
171     ASSERT_EQ(ret, DumpStatus::DUMP_FAIL);
172 }
173 
174 /**
175  * @tc.name: ManagerClientTest002
176  * @tc.desc: Test emtpy argument.
177  * @tc.type: FUNC
178  */
179 HWTEST_F(HidumperClientTest, ManagerClientTest002, TestSize.Level0)
180 {
181     vector<u16string> args{
182         std::u16string(),
183     };
184     int ret = DumpManagerClient::GetInstance().Request(args, STDOUT_FILENO);
185     ASSERT_EQ(ret, DumpStatus::DUMP_FAIL);
186 }
187 
188 /**
189  * @tc.name: ManagerClientTest003
190  * @tc.desc: Test mamanage client Request.
191  * @tc.type: FUNC
192  */
193 HWTEST_F(HidumperClientTest, ManagerClientTest003, TestSize.Level0)
194 {
195     vector<u16string> args{
196         std::u16string(u"hidumper"),
197         std::u16string(u"-s"),
198         std::u16string(u"1212"),
199     };
200     int ret = DumpManagerClient::GetInstance().Request(args, STDOUT_FILENO);
201     ASSERT_EQ(ret, DumpStatus::DUMP_OK);
202 }
203 
204 /**
205  * @tc.name: ManagerClientTest004
206  * @tc.desc: Test mamanage client ScanPidOverLimit.
207  * @tc.type: FUNC
208  */
209 HWTEST_F(HidumperClientTest, ManagerClientTest004, TestSize.Level0)
210 {
211     sptr<IDumpBroker> proxy_ {nullptr};
212     sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
213     ASSERT_TRUE(sam != nullptr) << "ManagerClientTest004 fail to get GetSystemAbilityManager";
214     sptr<IRemoteObject> remoteObject = sam->CheckSystemAbility(DFX_HI_DUMPER_SERVICE_ABILITY_ID);
215     ASSERT_TRUE(remoteObject != nullptr) << "Get SystemAbility failed.";
216     proxy_ = iface_cast<IDumpBroker>(remoteObject);
217     std::string requestType = "fd";
218     std::vector<int32_t> pidList;
219     int ret = proxy_->ScanPidOverLimit(requestType, LIMIT_SIZE, pidList);
220     ASSERT_EQ(ret, DumpStatus::DUMP_OK);
221 }
222 
223 /**
224  * @tc.name: ManagerClientTest005
225  * @tc.desc: Test mamanage client CountFdNums.
226  * @tc.type: FUNC
227  */
228 HWTEST_F(HidumperClientTest, ManagerClientTest005, TestSize.Level0)
229 {
230     sptr<IDumpBroker> proxy_ {nullptr};
231     sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
232     ASSERT_TRUE(sam != nullptr) << "ManagerClientTest005 fail to get GetSystemAbilityManager";
233     sptr<IRemoteObject> remoteObject = sam->CheckSystemAbility(DFX_HI_DUMPER_SERVICE_ABILITY_ID);
234     ASSERT_TRUE(remoteObject != nullptr) << "Get SystemAbility failed.";
235     proxy_ = iface_cast<IDumpBroker>(remoteObject);
236     int32_t pid = 1;
237     uint32_t fdNums = 0;
238     std::string detailFdInfo;
239     std::string topLeakedType;
240     int ret = proxy_->CountFdNums(pid, fdNums, detailFdInfo, topLeakedType);
241     ASSERT_EQ(ret, DumpStatus::DUMP_OK);
242 }
243 
244 /**
245  * @tc.name: ManagerClientTest006
246  * @tc.desc: Test ipc stat dump with pid.
247  * @tc.type: FUNC
248  */
249 HWTEST_F(HidumperClientTest, ManagerClientTest006, TestSize.Level0)
250 {
251     string pid;
252     FILE* file = popen("pidof samgr", "r");
253     if (file) {
254         char buffer[BUFFER_SIZE];
255         if (fgets(buffer, sizeof(buffer), file) != nullptr) {
256             pid.assign(buffer);
257         };
258         pid = pid.substr(0, pid.length() - 1);
259         pclose(file);
260     } else {
261         std::cerr << "Failed to execute command" << std::endl;
262     }
263     vector<u16string> args{
264         std::u16string(u"hidumper"),
265         std::u16string(u"--ipc"),
266         Str8ToStr16(pid),
267         std::u16string(u"--start-stat"),
268     };
269     int32_t ret = DumpManagerClient::GetInstance().Request(args, STDOUT_FILENO);
270     ASSERT_EQ(ret, DumpStatus::DUMP_OK);
271 }
272 
273 /**
274  * @tc.name: ManagerClientTest007
275  * @tc.desc: Test ipc stat dump all.
276  * @tc.type: FUNC
277  */
278 HWTEST_F(HidumperClientTest, ManagerClientTest007, TestSize.Level0)
279 {
280     vector<u16string> args{
281         std::u16string(u"hidumper"),
282         std::u16string(u"--ipc"),
283         std::u16string(u"-a"),
284         std::u16string(u"--start-stat"),
285     };
286     int ret = DumpManagerClient::GetInstance().Request(args, STDOUT_FILENO);
287     ASSERT_EQ(ret, DumpStatus::DUMP_OK);
288 }
289 
290 /**
291  * @tc.name: ManagerClientTest008
292  * @tc.desc: Test cpuusage of all processes.
293  * @tc.type: FUNC
294  */
295 HWTEST_F(HidumperClientTest, ManagerClientTest008, TestSize.Level0)
296 {
297     vector<u16string> args{
298         std::u16string(u"hidumper"),
299         std::u16string(u"--cpuusage"),
300     };
301     int ret = DumpManagerClient::GetInstance().Request(args, STDOUT_FILENO);
302     ASSERT_EQ(ret, DumpStatus::DUMP_OK);
303 }
304 
305 /**
306  * @tc.name: ManagerClientTest009
307  * @tc.desc: Test cpuusage with pid.
308  * @tc.type: FUNC
309  */
310 HWTEST_F(HidumperClientTest, ManagerClientTest009, TestSize.Level0)
311 {
312     vector<u16string> args{
313         std::u16string(u"hidumper"),
314         std::u16string(u"--cpuusage"),
315         std::u16string(u"1"),
316     };
317     int ret = DumpManagerClient::GetInstance().Request(args, STDOUT_FILENO);
318     ASSERT_EQ(ret, DumpStatus::DUMP_OK);
319 }
320 
321 /**
322  * @tc.name: ManagerClientTest010
323  * @tc.desc: Test cpufreq.
324  * @tc.type: FUNC
325  */
326 HWTEST_F(HidumperClientTest, ManagerClientTest010, TestSize.Level0)
327 {
328     vector<u16string> args{
329         std::u16string(u"hidumper"),
330         std::u16string(u"--cpufreq"),
331     };
332     int ret = DumpManagerClient::GetInstance().Request(args, STDOUT_FILENO);
333     ASSERT_EQ(ret, DumpStatus::DUMP_OK);
334 }
335 
336 /**
337  * @tc.name: ManagerClientTest011
338  * @tc.desc: Test --mem-jsheap.
339  * @tc.type: FUNC
340  */
341 HWTEST_F(HidumperClientTest, ManagerClientTest011, TestSize.Level0)
342 {
343     vector<u16string> args{
344         std::u16string(u"hidumper"),
345         std::u16string(u"--mem-jsheap"),
346     };
347     int ret = DumpManagerClient::GetInstance().Request(args, STDOUT_FILENO);
348     ASSERT_EQ(ret, DumpStatus::DUMP_OK);
349 }
350 
351 /**
352  * @tc.name: ManagerClientTest012
353  * @tc.desc: Test --mem-jsheap.
354  * @tc.type: FUNC
355  */
356 HWTEST_F(HidumperClientTest, ManagerClientTest012, TestSize.Level0)
357 {
358     string pid;
359     auto appMgrClient = std::make_unique<AppMgrClient>();
360     std::vector<RunningProcessInfo> runningProcessInfos;
361     appMgrClient->GetAllRunningProcesses(runningProcessInfos);
362     ASSERT_TRUE(runningProcessInfos.size() > 0);
363 
364     pid = to_string(runningProcessInfos[0].pid_);
365     vector<u16string> args{
366         std::u16string(u"hidumper"),
367         std::u16string(u"--mem-jsheap"),
368         Str8ToStr16(pid)
369     };
370     int ret = DumpManagerClient::GetInstance().Request(args, STDOUT_FILENO);
371     ASSERT_EQ(ret, DumpStatus::DUMP_OK);
372 }
373 } // namespace HiviewDFX
374 } // namespace OHOS