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