1/*
2 * Copyright (c) 2021-2023 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 <gtest/gtest.h>
17#include <memory>
18#include <string>
19
20#include "dfx_regs.h"
21#include "dfx_regs_get.h"
22#include "dfx_ring_buffer_wrapper.h"
23#include "dfx_dump_request.h"
24#include "dfx_thread.h"
25#include "lock_parser.h"
26#include <pthread.h>
27#include "printer.h"
28#include "process_dumper.h"
29#include "dfx_unwind_async_thread.h"
30#include "dfx_unwind_remote.h"
31#include "dfx_util.h"
32#include "dfx_test_util.h"
33
34using namespace OHOS::HiviewDFX;
35using namespace testing::ext;
36using namespace std;
37
38namespace OHOS {
39namespace HiviewDFX {
40class ProcessDumpTest : public testing::Test {
41public:
42    static void SetUpTestCase(void) {}
43    static void TearDownTestCase(void) {}
44    void SetUp() {}
45    void TearDown() {}
46};
47} // namespace HiviewDFX
48} // namespace OHOS
49
50namespace {
51void *SleepThread(void *argv)
52{
53    int threadID = *(int*)argv;
54    printf("create MultiThread %d", threadID);
55
56    const int sleepTime = 10;
57    sleep(sleepTime);
58
59    return nullptr;
60}
61/**
62 * @tc.name: DfxProcessTest001
63 * @tc.desc: test DfxProcess Create
64 * @tc.type: FUNC
65 */
66HWTEST_F (ProcessDumpTest, DfxProcessTest001, TestSize.Level2)
67{
68    GTEST_LOG_(INFO) << "DfxProcessTest001: start.";
69    std::shared_ptr<DfxProcess> process = DfxProcess::Create(getpid(), getpid());
70    EXPECT_EQ(false, process == nullptr) << "DfxProcessTest001 Failed";
71    GTEST_LOG_(INFO) << "DfxProcessTest001: end.";
72}
73
74/**
75 * @tc.name: DfxProcessTest002
76 * @tc.desc: test init process threads
77 * @tc.type: FUNC
78 */
79HWTEST_F (ProcessDumpTest, DfxProcessTest002, TestSize.Level2)
80{
81    GTEST_LOG_(INFO) << "DfxProcessTest002: start.";
82    pid_t accountmgrPid = GetProcessPid(ACCOUNTMGR_NAME);
83    bool isSuccess = accountmgrPid != 0;
84    if (!isSuccess) {
85        ASSERT_FALSE(isSuccess);
86        GTEST_LOG_(INFO) << "DfxProcessTest002: get pid failed.";
87        return;
88    }
89    pid_t pid = accountmgrPid;
90    pid_t tid = accountmgrPid;
91    auto keyThread = DfxThread::Create(pid, tid, tid);
92    auto process = DfxProcess::Create(pid, pid);
93    EXPECT_EQ(true, process != nullptr) << "DfxProcessTest002 Failed";
94    GTEST_LOG_(INFO) << "DfxProcessTest002: end.";
95}
96
97/**
98 * @tc.name: DfxProcessTest003
99 * @tc.desc: test init other threads
100 * @tc.type: FUNC
101 */
102HWTEST_F (ProcessDumpTest, DfxProcessTest003, TestSize.Level2)
103{
104    GTEST_LOG_(INFO) << "DfxProcessTest003: start.";
105    std::shared_ptr<DfxProcess> process = DfxProcess::Create(getpid(), getpid());
106    auto ret = process->InitOtherThreads();
107    EXPECT_EQ(true, ret) << "DfxProcessTest003 Failed";
108    auto threads = process->GetOtherThreads();
109    EXPECT_GT(threads.size(), 0) << "DfxProcessTest003 Failed";
110    process->ClearOtherThreads();
111    threads = process->GetOtherThreads();
112    EXPECT_EQ(threads.size(), 0) << "DfxProcessTest003 Failed";
113    GTEST_LOG_(INFO) << "DfxProcessTest003: end.";
114}
115
116/**
117 * @tc.name: DfxProcessTest004
118 * @tc.desc: test Attach Detach
119 * @tc.type: FUNC
120 */
121HWTEST_F (ProcessDumpTest, DfxProcessTest004, TestSize.Level2)
122{
123    GTEST_LOG_(INFO) << "DfxProcessTest004: start.";
124    std::shared_ptr<DfxProcess> process = DfxProcess::Create(getpid(), getpid());
125    auto ret = process->InitOtherThreads();
126    EXPECT_EQ(true, ret) << "DfxProcessTest004 Failed";
127    process->Attach();
128    process->Detach();
129    GTEST_LOG_(INFO) << "DfxProcessTest004: end.";
130}
131
132/**
133 * @tc.name: DfxProcessTest005
134 * @tc.desc: test DfxProcess ChangeTid
135 * @tc.type: FUNC
136 */
137HWTEST_F (ProcessDumpTest, DfxProcessTest005, TestSize.Level2)
138{
139    GTEST_LOG_(INFO) << "DfxProcessTest005: start.";
140    pid_t pid = getpid();
141    std::shared_ptr<DfxProcess> process1 = DfxProcess::Create(pid, pid);
142    pid_t ret = process1->ChangeTid(pid, false);
143    process1->Attach();
144    process1->Detach();
145    ASSERT_EQ(ret, pid);
146    pthread_t tid;
147    int threadID[1] = {1};
148    pthread_create(&tid, NULL, SleepThread, &threadID[0]);
149    std::shared_ptr<DfxProcess> process2 = DfxProcess::Create(pid, tid);
150    ret = process2->ChangeTid(pid, false);
151    pthread_join(tid, NULL);
152    process2->Attach();
153    process2->Detach();
154    ASSERT_EQ(ret, pid);
155    GTEST_LOG_(INFO) << "DfxProcessTest005: end.";
156}
157
158/**
159 * @tc.name: DfxThreadTest001
160 * @tc.desc: test DfxThread Create
161 * @tc.type: FUNC
162 */
163HWTEST_F (ProcessDumpTest, DfxThreadTest001, TestSize.Level2)
164{
165    GTEST_LOG_(INFO) << "DfxThreadTest001: start.";
166    int32_t pid = 1, tid = 1;
167    auto thread = DfxThread::Create(pid, tid, tid);
168    EXPECT_EQ(true, thread != nullptr) << "DfxThreadTest001 failed";
169    GTEST_LOG_(INFO) << "DfxThreadTest001: end.";
170}
171
172/**
173 * @tc.name: DfxThreadTest002
174 * @tc.desc: test DfxThread GetThreadRegs
175 * @tc.type: FUNC
176 */
177HWTEST_F (ProcessDumpTest, DfxThreadTest002, TestSize.Level2)
178{
179    GTEST_LOG_(INFO) << "DfxThreadTest002: start.";
180    int32_t pid = 243, tid = 243;
181    std::shared_ptr<DfxThread> thread = std::make_shared<DfxThread>(pid, tid, tid);
182    std::shared_ptr<DfxRegs> inputrefs;
183    thread->SetThreadRegs(inputrefs);
184    std::shared_ptr<DfxRegs> outputrefs = thread->GetThreadRegs();
185    EXPECT_EQ(true, inputrefs == outputrefs) << "DfxThreadTest002 Failed";
186    GTEST_LOG_(INFO) << "DfxThreadTest002: end.";
187}
188
189/**
190 * @tc.name: DfxUnwindRemoteTest001
191 * @tc.desc: test DfxUnwindRemote UnwindProcess
192 * @tc.type: FUNC
193 */
194HWTEST_F (ProcessDumpTest, DfxUnwindRemoteTest001, TestSize.Level2)
195{
196    GTEST_LOG_(INFO) << "DfxUnwindRemoteTest001: start.";
197    pid_t pid = GetProcessPid(ACCOUNTMGR_NAME);
198    pid_t tid = pid;
199    std::shared_ptr<DfxThread> thread = DfxThread::Create(pid, tid, tid);
200    std::shared_ptr<DfxProcess> process = DfxProcess::Create(pid, pid);
201    auto unwinder = std::make_shared<Unwinder>(pid);
202    process->keyThread_ = thread;
203    thread->Attach();
204    thread->SetThreadRegs(DfxRegs::CreateRemoteRegs(pid));
205    std::shared_ptr<ProcessDumpRequest> request = std::make_shared<ProcessDumpRequest>();
206    bool ret = DfxUnwindRemote::GetInstance().UnwindProcess(request, process, unwinder);
207    thread->Detach();
208    EXPECT_EQ(true, ret) << "DfxUnwindRemoteTest001 Failed";
209    GTEST_LOG_(INFO) << "DfxUnwindRemoteTest001: end.";
210}
211
212#ifdef UNITTEST
213/**
214 * @tc.name: DfxUnwindRemoteTest002
215 * @tc.desc: test DfxUnwindRemote UnwindProcess
216 * @tc.type: FUNC
217 */
218HWTEST_F (ProcessDumpTest, DfxUnwindRemoteTest002, TestSize.Level2)
219{
220    GTEST_LOG_(INFO) << "DfxUnwindRemoteTest002: start.";
221    pid_t pid = GetProcessPid(ACCOUNTMGR_NAME);
222    pid_t tid = pid;
223    std::shared_ptr<DfxProcess> process = DfxProcess::Create(pid, pid);
224    auto unwinder = std::make_shared<Unwinder>(pid);
225    auto remote = std::make_shared<DfxUnwindRemote>();
226    std::shared_ptr<ProcessDumpRequest> request = std::make_shared<ProcessDumpRequest>();
227    bool ret = remote->UnwindProcess(request, nullptr, unwinder, 0);
228    ASSERT_EQ(ret, false);
229    ret = remote->UnwindProcess(request, process, unwinder, 0);
230    ASSERT_EQ(ret, false);
231    std::shared_ptr<DfxThread> thread = DfxThread::Create(pid, tid, tid);
232    process->keyThread_ = thread;
233    ret = remote->UnwindProcess(request, process, unwinder, 0);
234    ASSERT_EQ(ret, false);
235    GTEST_LOG_(INFO) << "DfxUnwindRemoteTest002: end.";
236}
237
238/**
239 * @tc.name: DfxRingBufferWrapperTest001
240 * @tc.desc: test DfxRingBufferWrapper SetWriteBufFd
241 * @tc.type: FUNC
242 */
243HWTEST_F (ProcessDumpTest, DfxRingBufferWrapperTest001, TestSize.Level2)
244{
245    GTEST_LOG_(INFO) << "DfxRingBufferWrapperTest001: start.";
246    auto wrapper = std::make_shared<DfxRingBufferWrapper>();
247    wrapper->SetWriteBufFd(-1);
248    int ret = wrapper->DefaultWrite(0, nullptr, 0);
249    ASSERT_EQ(ret, -1);
250    const size_t bufsize = 10;
251    char buf[bufsize];
252    ret = wrapper->DefaultWrite(1, buf, bufsize);
253    ASSERT_NE(ret, -1);
254    ret = wrapper->DefaultWrite(-1, buf, bufsize);
255    ASSERT_EQ(ret, 0);
256    GTEST_LOG_(INFO) << "DfxRingBufferWrapperTest001: end.";
257}
258
259/**
260 * @tc.name: DfxRingBufferWrapperTest002
261 * @tc.desc: test DfxRingBufferWrapper SetWriteBufFd
262 * @tc.type: FUNC
263 */
264HWTEST_F (ProcessDumpTest, DfxRingBufferWrapperTest002, TestSize.Level2)
265{
266    GTEST_LOG_(INFO) << "DfxRingBufferWrapperTest002: start.";
267    auto wrapper = std::make_shared<DfxRingBufferWrapper>();
268    wrapper->PrintBaseInfo();
269    wrapper->SetWriteBufFd(-1);
270    int ret = wrapper->DefaultWrite(0, nullptr, 0);
271    ASSERT_EQ(ret, -1);
272    GTEST_LOG_(INFO) << "DfxRingBufferWrapperTest002: end.";
273}
274
275/**
276 * @tc.name: DfxUnwindAsyncThreadTest001
277 * @tc.desc: test DfxUnwindAsyncThread GetSubmitterStack
278 * @tc.type: FUNC
279 */
280HWTEST_F (ProcessDumpTest, DfxUnwindAsyncThreadTest001, TestSize.Level2)
281{
282    GTEST_LOG_(INFO) << "DfxUnwindAsyncThreadTest001: start.";
283    Printer printer;
284    printer.PrintDumpHeader(nullptr, nullptr, nullptr);
285    printer.PrintThreadRegsByConfig(nullptr);
286    printer.PrintRegsByConfig(nullptr);
287    printer.PrintThreadOpenFiles(nullptr);
288    pid_t pid = GetProcessPid(ACCOUNTMGR_NAME);
289    pid_t tid = pid;
290    std::shared_ptr<DfxThread> thread = DfxThread::Create(pid, tid, tid);
291    auto unwinder = std::make_shared<Unwinder>(pid);
292    DfxUnwindAsyncThread asyncThread1(thread, unwinder, 0);
293    std::vector<DfxFrame> submitterFrames;
294    asyncThread1.GetSubmitterStack(submitterFrames);
295    ASSERT_EQ(asyncThread1.stackId_, 0);
296    DfxUnwindAsyncThread asyncThread2(thread, unwinder, 1);
297    asyncThread2.GetSubmitterStack(submitterFrames);
298    asyncThread2.UnwindThreadFallback();
299    asyncThread2.UnwindThreadByParseStackIfNeed();
300    ASSERT_EQ(asyncThread2.stackId_, 1);
301    DfxUnwindAsyncThread asyncThread3(nullptr, unwinder, 1);
302    asyncThread3.UnwindThreadByParseStackIfNeed();
303    ASSERT_EQ(asyncThread3.stackId_, 1);
304    GTEST_LOG_(INFO) << "DfxUnwindAsyncThreadTest001: end.";
305}
306
307/**
308 * @tc.name: DfxUnwindAsyncThreadTest002
309 * @tc.desc: test DfxUnwindAsyncThread GetSubmitterStack
310 * @tc.type: FUNC
311 */
312HWTEST_F (ProcessDumpTest, DfxUnwindAsyncThreadTest002, TestSize.Level2)
313{
314    GTEST_LOG_(INFO) << "DfxUnwindAsyncThreadTest002: start.";
315    pid_t pid = GetProcessPid(ACCOUNTMGR_NAME);
316    auto unwinder = std::make_shared<Unwinder>(pid);
317    DfxUnwindAsyncThread asyncThread1(nullptr, nullptr, 0);
318    asyncThread1.UnwindStack(0);
319    ASSERT_EQ(asyncThread1.stackId_, 0);
320    DfxUnwindAsyncThread asyncThread2(nullptr, unwinder, 0);
321    asyncThread2.UnwindStack(0);
322    std::vector<DfxFrame> submitterFrames;
323    asyncThread2.GetSubmitterStack(submitterFrames);
324    ASSERT_EQ(asyncThread2.stackId_, 0);
325    GTEST_LOG_(INFO) << "DfxUnwindAsyncThreadTest002: end.";
326}
327#endif
328}
329