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