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 
34 using namespace OHOS::HiviewDFX;
35 using namespace testing::ext;
36 using namespace std;
37 
38 namespace OHOS {
39 namespace HiviewDFX {
40 class ProcessDumpTest : public testing::Test {
41 public:
SetUpTestCase(void)42     static void SetUpTestCase(void) {}
TearDownTestCase(void)43     static void TearDownTestCase(void) {}
SetUp()44     void SetUp() {}
TearDown()45     void TearDown() {}
46 };
47 } // namespace HiviewDFX
48 } // namespace OHOS
49 
50 namespace {
SleepThread(void *argv)51 void *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  */
HWTEST_F(ProcessDumpTest, DfxProcessTest001, TestSize.Level2)66 HWTEST_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  */
HWTEST_F(ProcessDumpTest, DfxProcessTest002, TestSize.Level2)79 HWTEST_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  */
HWTEST_F(ProcessDumpTest, DfxProcessTest003, TestSize.Level2)102 HWTEST_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  */
HWTEST_F(ProcessDumpTest, DfxProcessTest004, TestSize.Level2)121 HWTEST_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  */
HWTEST_F(ProcessDumpTest, DfxProcessTest005, TestSize.Level2)137 HWTEST_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  */
HWTEST_F(ProcessDumpTest, DfxThreadTest001, TestSize.Level2)163 HWTEST_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  */
HWTEST_F(ProcessDumpTest, DfxThreadTest002, TestSize.Level2)177 HWTEST_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  */
HWTEST_F(ProcessDumpTest, DfxUnwindRemoteTest001, TestSize.Level2)194 HWTEST_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  */
HWTEST_F(ProcessDumpTest, DfxUnwindRemoteTest002, TestSize.Level2)218 HWTEST_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  */
HWTEST_F(ProcessDumpTest, DfxRingBufferWrapperTest001, TestSize.Level2)243 HWTEST_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  */
HWTEST_F(ProcessDumpTest, DfxRingBufferWrapperTest002, TestSize.Level2)264 HWTEST_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  */
HWTEST_F(ProcessDumpTest, DfxUnwindAsyncThreadTest001, TestSize.Level2)280 HWTEST_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  */
HWTEST_F(ProcessDumpTest, DfxUnwindAsyncThreadTest002, TestSize.Level2)312 HWTEST_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