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