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
27using namespace testing::ext;
28using namespace std;
29using OHOS::HiviewDFX::DumpClientMain;
30using OHOS::AppExecFwk::AppMgrClient;
31using OHOS::AppExecFwk::RunningProcessInfo;
32namespace OHOS {
33namespace HiviewDFX {
34const std::string TOOL_NAME = "hidumper";
35const int BUFFER_SIZE = 1024;
36class HidumperClientTest : public testing::Test {
37public:
38    static void SetUpTestCase(void);
39    static void TearDownTestCase(void);
40    void SetUp();
41    void TearDown();
42};
43
44void HidumperClientTest::SetUpTestCase(void)
45{
46}
47
48void HidumperClientTest::TearDownTestCase(void)
49{
50}
51
52void HidumperClientTest::SetUp(void)
53{
54}
55
56void HidumperClientTest::TearDown(void)
57{
58}
59
60/**
61 * @tc.name: ClientMainTest001
62 * @tc.desc: Test too many arguments.
63 * @tc.type: FUNC
64 */
65HWTEST_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 */
80HWTEST_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 */
99HWTEST_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 */
118HWTEST_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 */
134HWTEST_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 */
155HWTEST_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 */
167HWTEST_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 */
179HWTEST_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 */
193HWTEST_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 */
209HWTEST_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 */
228HWTEST_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 */
249HWTEST_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 */
278HWTEST_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 */
295HWTEST_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 */
310HWTEST_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 */
326HWTEST_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 */
341HWTEST_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 */
356HWTEST_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