1800b99b8Sopenharmony_ci/* 2800b99b8Sopenharmony_ci * Copyright (c) 2022-2023 Huawei Device Co., Ltd. 3800b99b8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4800b99b8Sopenharmony_ci * you may not use this file except in compliance with the License. 5800b99b8Sopenharmony_ci * You may obtain a copy of the License at 6800b99b8Sopenharmony_ci * 7800b99b8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8800b99b8Sopenharmony_ci * 9800b99b8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10800b99b8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11800b99b8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12800b99b8Sopenharmony_ci * See the License for the specific language governing permissions and 13800b99b8Sopenharmony_ci * limitations under the License. 14800b99b8Sopenharmony_ci */ 15800b99b8Sopenharmony_ci 16800b99b8Sopenharmony_ci#include <gtest/gtest.h> 17800b99b8Sopenharmony_ci#include <cerrno> 18800b99b8Sopenharmony_ci#include <unistd.h> 19800b99b8Sopenharmony_ci 20800b99b8Sopenharmony_ci#include "dfx_fault_stack.h" 21800b99b8Sopenharmony_ci#include "dfx_frame_formatter.h" 22800b99b8Sopenharmony_ci#include "dfx_maps.h" 23800b99b8Sopenharmony_ci#include "dfx_regs.h" 24800b99b8Sopenharmony_ci#include "dfx_ring_buffer_wrapper.h" 25800b99b8Sopenharmony_ci#include "dfx_thread.h" 26800b99b8Sopenharmony_ci#include "dfx_unwind_remote.h" 27800b99b8Sopenharmony_ci 28800b99b8Sopenharmony_ciusing namespace OHOS::HiviewDFX; 29800b99b8Sopenharmony_ciusing namespace testing::ext; 30800b99b8Sopenharmony_ciusing namespace std; 31800b99b8Sopenharmony_ci 32800b99b8Sopenharmony_cinamespace OHOS { 33800b99b8Sopenharmony_cinamespace HiviewDFX { 34800b99b8Sopenharmony_ciclass FaultStackUnittest : public testing::Test { 35800b99b8Sopenharmony_cipublic: 36800b99b8Sopenharmony_ci static void SetUpTestCase(void); 37800b99b8Sopenharmony_ci static void TearDownTestCase(void); 38800b99b8Sopenharmony_ci void SetUp(); 39800b99b8Sopenharmony_ci void TearDown(); 40800b99b8Sopenharmony_ci 41800b99b8Sopenharmony_ci static int WriteLogFunc(int32_t fd, const char *buf, int len); 42800b99b8Sopenharmony_ci static std::string result; 43800b99b8Sopenharmony_ci}; 44800b99b8Sopenharmony_ci} // namespace HiviewDFX 45800b99b8Sopenharmony_ci} // namespace OHOS 46800b99b8Sopenharmony_ci 47800b99b8Sopenharmony_cistd::string FaultStackUnittest::result = ""; 48800b99b8Sopenharmony_ci 49800b99b8Sopenharmony_civoid FaultStackUnittest::SetUpTestCase(void) 50800b99b8Sopenharmony_ci{ 51800b99b8Sopenharmony_ci result = ""; 52800b99b8Sopenharmony_ci} 53800b99b8Sopenharmony_ci 54800b99b8Sopenharmony_civoid FaultStackUnittest::TearDownTestCase(void) 55800b99b8Sopenharmony_ci{ 56800b99b8Sopenharmony_ci} 57800b99b8Sopenharmony_ci 58800b99b8Sopenharmony_civoid FaultStackUnittest::SetUp(void) 59800b99b8Sopenharmony_ci{ 60800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().SetWriteFunc(FaultStackUnittest::WriteLogFunc); 61800b99b8Sopenharmony_ci} 62800b99b8Sopenharmony_ci 63800b99b8Sopenharmony_civoid FaultStackUnittest::TearDown(void) 64800b99b8Sopenharmony_ci{ 65800b99b8Sopenharmony_ci} 66800b99b8Sopenharmony_ci 67800b99b8Sopenharmony_ciint FaultStackUnittest::WriteLogFunc(int32_t fd, const char *buf, int len) 68800b99b8Sopenharmony_ci{ 69800b99b8Sopenharmony_ci printf("%d: %s", fd, buf); 70800b99b8Sopenharmony_ci FaultStackUnittest::result.append(std::string(buf, len)); 71800b99b8Sopenharmony_ci return 0; 72800b99b8Sopenharmony_ci} 73800b99b8Sopenharmony_ci 74800b99b8Sopenharmony_cinamespace { 75800b99b8Sopenharmony_ci/** 76800b99b8Sopenharmony_ci * @tc.name: FaultStackUnittest001 77800b99b8Sopenharmony_ci * @tc.desc: check whether fault stack and register can be print out 78800b99b8Sopenharmony_ci * @tc.type: FUNC 79800b99b8Sopenharmony_ci */ 80800b99b8Sopenharmony_ciHWTEST_F(FaultStackUnittest, FaultStackUnittest001, TestSize.Level2) 81800b99b8Sopenharmony_ci{ 82800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "FaultStackUnittest001: start."; 83800b99b8Sopenharmony_ci 84800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(); 85800b99b8Sopenharmony_ci bool unwRet = unwinder->UnwindLocal(); 86800b99b8Sopenharmony_ci if (!unwRet) { 87800b99b8Sopenharmony_ci FAIL() << "Failed to unwind local"; 88800b99b8Sopenharmony_ci } 89800b99b8Sopenharmony_ci auto frames = unwinder->GetFrames(); 90800b99b8Sopenharmony_ci int childPid = fork(); 91800b99b8Sopenharmony_ci bool isSuccess = childPid >= 0; 92800b99b8Sopenharmony_ci if (!isSuccess) { 93800b99b8Sopenharmony_ci ASSERT_FALSE(isSuccess); 94800b99b8Sopenharmony_ci printf("Failed to fork child process, errno(%d).\n", errno); 95800b99b8Sopenharmony_ci return; 96800b99b8Sopenharmony_ci } 97800b99b8Sopenharmony_ci if (childPid == 0) { 98800b99b8Sopenharmony_ci uint32_t left = 10; 99800b99b8Sopenharmony_ci while (left > 0) { 100800b99b8Sopenharmony_ci left = sleep(left); 101800b99b8Sopenharmony_ci } 102800b99b8Sopenharmony_ci _exit(0); 103800b99b8Sopenharmony_ci } 104800b99b8Sopenharmony_ci DfxThread thread(childPid, childPid, childPid); 105800b99b8Sopenharmony_ci ASSERT_EQ(true, thread.Attach()); 106800b99b8Sopenharmony_ci auto maps = DfxMaps::Create(childPid); 107800b99b8Sopenharmony_ci auto reg = DfxRegs::CreateRemoteRegs(childPid); 108800b99b8Sopenharmony_ci std::unique_ptr<FaultStack> stack = std::make_unique<FaultStack>(childPid); 109800b99b8Sopenharmony_ci stack->CollectStackInfo(frames); 110800b99b8Sopenharmony_ci stack->CollectRegistersBlock(reg, maps); 111800b99b8Sopenharmony_ci stack->Print(); 112800b99b8Sopenharmony_ci thread.Detach(); 113800b99b8Sopenharmony_ci 114800b99b8Sopenharmony_ci if (result.find("Memory near registers") == std::string::npos) { 115800b99b8Sopenharmony_ci FAIL(); 116800b99b8Sopenharmony_ci } 117800b99b8Sopenharmony_ci 118800b99b8Sopenharmony_ci if (result.find("FaultStack") == std::string::npos) { 119800b99b8Sopenharmony_ci FAIL(); 120800b99b8Sopenharmony_ci } 121800b99b8Sopenharmony_ci 122800b99b8Sopenharmony_ci if (result.find("pc") == std::string::npos) { 123800b99b8Sopenharmony_ci FAIL(); 124800b99b8Sopenharmony_ci } 125800b99b8Sopenharmony_ci 126800b99b8Sopenharmony_ci if (result.find("sp2:") == std::string::npos) { 127800b99b8Sopenharmony_ci FAIL(); 128800b99b8Sopenharmony_ci } 129800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "Result Log length:" << result.length(); 130800b99b8Sopenharmony_ci ASSERT_GT(result.length(), 0); 131800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "FaultStackUnittest001: end."; 132800b99b8Sopenharmony_ci} 133800b99b8Sopenharmony_ci}