/* * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include "dfx_fault_stack.h" #include "dfx_frame_formatter.h" #include "dfx_maps.h" #include "dfx_regs.h" #include "dfx_ring_buffer_wrapper.h" #include "dfx_thread.h" #include "dfx_unwind_remote.h" using namespace OHOS::HiviewDFX; using namespace testing::ext; using namespace std; namespace OHOS { namespace HiviewDFX { class FaultStackUnittest : public testing::Test { public: static void SetUpTestCase(void); static void TearDownTestCase(void); void SetUp(); void TearDown(); static int WriteLogFunc(int32_t fd, const char *buf, int len); static std::string result; }; } // namespace HiviewDFX } // namespace OHOS std::string FaultStackUnittest::result = ""; void FaultStackUnittest::SetUpTestCase(void) { result = ""; } void FaultStackUnittest::TearDownTestCase(void) { } void FaultStackUnittest::SetUp(void) { DfxRingBufferWrapper::GetInstance().SetWriteFunc(FaultStackUnittest::WriteLogFunc); } void FaultStackUnittest::TearDown(void) { } int FaultStackUnittest::WriteLogFunc(int32_t fd, const char *buf, int len) { printf("%d: %s", fd, buf); FaultStackUnittest::result.append(std::string(buf, len)); return 0; } namespace { /** * @tc.name: FaultStackUnittest001 * @tc.desc: check whether fault stack and register can be print out * @tc.type: FUNC */ HWTEST_F(FaultStackUnittest, FaultStackUnittest001, TestSize.Level2) { GTEST_LOG_(INFO) << "FaultStackUnittest001: start."; auto unwinder = std::make_shared(); bool unwRet = unwinder->UnwindLocal(); if (!unwRet) { FAIL() << "Failed to unwind local"; } auto frames = unwinder->GetFrames(); int childPid = fork(); if (childPid == 0) { uint32_t left = 10; while (left > 0) { left = sleep(left); } _exit(0); } else if (childPid < 0) { printf("Failed to fork child process, errno(%d).\n", errno); return; } DfxThread thread(childPid, childPid, childPid); ASSERT_EQ(true, thread.Attach()); auto maps = DfxMaps::Create(childPid); auto reg = DfxRegs::CreateRemoteRegs(childPid); std::unique_ptr stack = std::make_unique(childPid); stack->CollectStackInfo(frames); stack->CollectRegistersBlock(reg, maps); stack->Print(); thread.Detach(); if (result.find("Memory near registers") == std::string::npos) { FAIL(); } if (result.find("FaultStack") == std::string::npos) { FAIL(); } if (result.find("pc") == std::string::npos) { FAIL(); } if (result.find("sp2:") == std::string::npos) { FAIL(); } GTEST_LOG_(INFO) << "Result Log length:" << result.length(); ASSERT_GT(result.length(), 0); GTEST_LOG_(INFO) << "FaultStackUnittest001: end."; } }