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