1800b99b8Sopenharmony_ci/* 2800b99b8Sopenharmony_ci * Copyright (c) 2022-2024 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 18800b99b8Sopenharmony_ci#include <cstdio> 19800b99b8Sopenharmony_ci#include <cstdlib> 20800b99b8Sopenharmony_ci#include <memory> 21800b99b8Sopenharmony_ci#include <mutex> 22800b99b8Sopenharmony_ci#include <thread> 23800b99b8Sopenharmony_ci 24800b99b8Sopenharmony_ci#include <dlfcn.h> 25800b99b8Sopenharmony_ci#include <fcntl.h> 26800b99b8Sopenharmony_ci#include <securec.h> 27800b99b8Sopenharmony_ci#include <sys/wait.h> 28800b99b8Sopenharmony_ci#include <unistd.h> 29800b99b8Sopenharmony_ci 30800b99b8Sopenharmony_ci#include "backtrace_local.h" 31800b99b8Sopenharmony_ci#include "backtrace_local_thread.h" 32800b99b8Sopenharmony_ci#include "dfx_frame_formatter.h" 33800b99b8Sopenharmony_ci#include "dfx_kernel_stack.h" 34800b99b8Sopenharmony_ci#include "dfx_test_util.h" 35800b99b8Sopenharmony_ci#include "elapsed_time.h" 36800b99b8Sopenharmony_ci#include "ffrt_inner.h" 37800b99b8Sopenharmony_ci#include "unwinder_config.h" 38800b99b8Sopenharmony_ci 39800b99b8Sopenharmony_ciusing namespace testing; 40800b99b8Sopenharmony_ciusing namespace testing::ext; 41800b99b8Sopenharmony_ci 42800b99b8Sopenharmony_cinamespace OHOS { 43800b99b8Sopenharmony_cinamespace HiviewDFX { 44800b99b8Sopenharmony_ci#undef LOG_DOMAIN 45800b99b8Sopenharmony_ci#undef LOG_TAG 46800b99b8Sopenharmony_ci#define LOG_TAG "DfxBacktraceLocalTest" 47800b99b8Sopenharmony_ci#define LOG_DOMAIN 0xD002D11 48800b99b8Sopenharmony_ci#define DEFAULT_MAX_FRAME_NUM 256 49800b99b8Sopenharmony_ci#define MIN_FRAME_NUM 2 50800b99b8Sopenharmony_ci 51800b99b8Sopenharmony_ciclass BacktraceLocalTest : public testing::Test { 52800b99b8Sopenharmony_cipublic: 53800b99b8Sopenharmony_ci static void SetUpTestCase(); 54800b99b8Sopenharmony_ci static void TearDownTestCase(); 55800b99b8Sopenharmony_ci void SetUp(); 56800b99b8Sopenharmony_ci void TearDown(); 57800b99b8Sopenharmony_ci 58800b99b8Sopenharmony_ci uint32_t fdCount; 59800b99b8Sopenharmony_ci uint32_t mapsCount; 60800b99b8Sopenharmony_ci uint64_t memCount; 61800b99b8Sopenharmony_ci 62800b99b8Sopenharmony_ci static uint32_t fdCountTotal; 63800b99b8Sopenharmony_ci static uint32_t mapsCountTotal; 64800b99b8Sopenharmony_ci static uint64_t memCountTotal; 65800b99b8Sopenharmony_ci}; 66800b99b8Sopenharmony_ci 67800b99b8Sopenharmony_ciuint32_t BacktraceLocalTest::fdCountTotal = 0; 68800b99b8Sopenharmony_ciuint32_t BacktraceLocalTest::mapsCountTotal = 0; 69800b99b8Sopenharmony_ciuint64_t BacktraceLocalTest::memCountTotal = 0; 70800b99b8Sopenharmony_ci 71800b99b8Sopenharmony_ci 72800b99b8Sopenharmony_civoid BacktraceLocalTest::SetUpTestCase() 73800b99b8Sopenharmony_ci{ 74800b99b8Sopenharmony_ci BacktraceLocalTest::fdCountTotal = GetSelfFdCount(); 75800b99b8Sopenharmony_ci BacktraceLocalTest::mapsCountTotal = GetSelfMapsCount(); 76800b99b8Sopenharmony_ci BacktraceLocalTest::memCountTotal = GetSelfMemoryCount(); 77800b99b8Sopenharmony_ci} 78800b99b8Sopenharmony_ci 79800b99b8Sopenharmony_civoid BacktraceLocalTest::TearDownTestCase() 80800b99b8Sopenharmony_ci{ 81800b99b8Sopenharmony_ci CheckResourceUsage(fdCountTotal, mapsCountTotal, memCountTotal); 82800b99b8Sopenharmony_ci} 83800b99b8Sopenharmony_ci 84800b99b8Sopenharmony_civoid BacktraceLocalTest::SetUp() 85800b99b8Sopenharmony_ci{ 86800b99b8Sopenharmony_ci fdCount = GetSelfFdCount(); 87800b99b8Sopenharmony_ci mapsCount = GetSelfMapsCount(); 88800b99b8Sopenharmony_ci memCount = GetSelfMemoryCount(); 89800b99b8Sopenharmony_ci} 90800b99b8Sopenharmony_ci 91800b99b8Sopenharmony_civoid BacktraceLocalTest::TearDown() 92800b99b8Sopenharmony_ci{ 93800b99b8Sopenharmony_ci CheckResourceUsage(fdCount, mapsCount, memCount); 94800b99b8Sopenharmony_ci} 95800b99b8Sopenharmony_ci 96800b99b8Sopenharmony_ci/** 97800b99b8Sopenharmony_ci * @tc.name: BacktraceLocalTest001 98800b99b8Sopenharmony_ci * @tc.desc: test get backtrace of current thread 99800b99b8Sopenharmony_ci * @tc.type: FUNC 100800b99b8Sopenharmony_ci */ 101800b99b8Sopenharmony_ciHWTEST_F(BacktraceLocalTest, BacktraceLocalTest001, TestSize.Level2) 102800b99b8Sopenharmony_ci{ 103800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "BacktraceLocalTest001: start."; 104800b99b8Sopenharmony_ci ElapsedTime counter; 105800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(); 106800b99b8Sopenharmony_ci BacktraceLocalThread thread(BACKTRACE_CURRENT_THREAD, unwinder); 107800b99b8Sopenharmony_ci ASSERT_EQ(true, thread.Unwind(false)); 108800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindCurrentCost:" << counter.Elapsed(); 109800b99b8Sopenharmony_ci const auto& frames = thread.GetFrames(); 110800b99b8Sopenharmony_ci ASSERT_GT(frames.size(), 0); 111800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << thread.GetFormattedStr(); 112800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "BacktraceLocalTest001: end."; 113800b99b8Sopenharmony_ci} 114800b99b8Sopenharmony_ci 115800b99b8Sopenharmony_ciint32_t g_tid = 0; 116800b99b8Sopenharmony_cistd::mutex g_mutex; 117800b99b8Sopenharmony_ci__attribute__((noinline)) void Test002() 118800b99b8Sopenharmony_ci{ 119800b99b8Sopenharmony_ci printf("Test002\n"); 120800b99b8Sopenharmony_ci g_mutex.lock(); 121800b99b8Sopenharmony_ci g_mutex.unlock(); 122800b99b8Sopenharmony_ci} 123800b99b8Sopenharmony_ci 124800b99b8Sopenharmony_ci__attribute__((noinline)) void Test001() 125800b99b8Sopenharmony_ci{ 126800b99b8Sopenharmony_ci g_tid = gettid(); 127800b99b8Sopenharmony_ci printf("Test001:%d\n", g_tid); 128800b99b8Sopenharmony_ci Test002(); 129800b99b8Sopenharmony_ci} 130800b99b8Sopenharmony_ci 131800b99b8Sopenharmony_ci/** 132800b99b8Sopenharmony_ci * @tc.name: BacktraceLocalTest003 133800b99b8Sopenharmony_ci * @tc.desc: test get backtrace of a child thread 134800b99b8Sopenharmony_ci * @tc.type: FUNC 135800b99b8Sopenharmony_ci */ 136800b99b8Sopenharmony_ciHWTEST_F(BacktraceLocalTest, BacktraceLocalTest003, TestSize.Level2) 137800b99b8Sopenharmony_ci{ 138800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "BacktraceLocalTest003: start."; 139800b99b8Sopenharmony_ci g_mutex.lock(); 140800b99b8Sopenharmony_ci std::thread backtraceThread(Test001); 141800b99b8Sopenharmony_ci sleep(1); 142800b99b8Sopenharmony_ci if (g_tid <= 0) { 143800b99b8Sopenharmony_ci FAIL() << "Failed to create child thread.\n"; 144800b99b8Sopenharmony_ci } 145800b99b8Sopenharmony_ci 146800b99b8Sopenharmony_ci ElapsedTime counter; 147800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(); 148800b99b8Sopenharmony_ci BacktraceLocalThread thread(g_tid, unwinder); 149800b99b8Sopenharmony_ci ASSERT_EQ(true, thread.Unwind(false)); 150800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindCurrentCost:" << counter.Elapsed(); 151800b99b8Sopenharmony_ci const auto& frames = thread.GetFrames(); 152800b99b8Sopenharmony_ci ASSERT_GT(frames.size(), 0); 153800b99b8Sopenharmony_ci auto backtraceStr = thread.GetFormattedStr(false); 154800b99b8Sopenharmony_ci ASSERT_GT(backtraceStr.size(), 0); 155800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "backtraceStr:\n" << backtraceStr; 156800b99b8Sopenharmony_ci 157800b99b8Sopenharmony_ci std::string str; 158800b99b8Sopenharmony_ci auto ret = GetBacktraceStringByTid(str, g_tid, 0, false); 159800b99b8Sopenharmony_ci ASSERT_TRUE(ret); 160800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "GetBacktraceStringByTid:\n" << str; 161800b99b8Sopenharmony_ci g_mutex.unlock(); 162800b99b8Sopenharmony_ci g_tid = 0; 163800b99b8Sopenharmony_ci if (backtraceThread.joinable()) { 164800b99b8Sopenharmony_ci backtraceThread.join(); 165800b99b8Sopenharmony_ci } 166800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "BacktraceLocalTest003: end."; 167800b99b8Sopenharmony_ci} 168800b99b8Sopenharmony_ci 169800b99b8Sopenharmony_ci/** 170800b99b8Sopenharmony_ci * @tc.name: BacktraceLocalTest004 171800b99b8Sopenharmony_ci * @tc.desc: test get backtrace of a child thread 172800b99b8Sopenharmony_ci * @tc.type: FUNC 173800b99b8Sopenharmony_ci */ 174800b99b8Sopenharmony_ciHWTEST_F(BacktraceLocalTest, BacktraceLocalTest004, TestSize.Level2) 175800b99b8Sopenharmony_ci{ 176800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "BacktraceLocalTest004: start."; 177800b99b8Sopenharmony_ci g_mutex.lock(); 178800b99b8Sopenharmony_ci std::thread backtraceThread(Test001); 179800b99b8Sopenharmony_ci sleep(1); 180800b99b8Sopenharmony_ci if (g_tid <= 0) { 181800b99b8Sopenharmony_ci FAIL() << "Failed to create child thread.\n"; 182800b99b8Sopenharmony_ci } 183800b99b8Sopenharmony_ci 184800b99b8Sopenharmony_ci std::string str; 185800b99b8Sopenharmony_ci auto ret = GetBacktraceStringByTid(str, g_tid, 0, false); 186800b99b8Sopenharmony_ci ASSERT_TRUE(ret); 187800b99b8Sopenharmony_ci string log[] = {"#00", "backtrace_local", "Tid:", "Name"}; 188800b99b8Sopenharmony_ci log[2] = log[2] + std::to_string(g_tid); 189800b99b8Sopenharmony_ci int logSize = sizeof(log) / sizeof(log[0]); 190800b99b8Sopenharmony_ci int count = GetKeywordsNum(str, log, logSize); 191800b99b8Sopenharmony_ci EXPECT_EQ(count, logSize) << "BacktraceLocalTest004 Failed"; 192800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "GetBacktraceStringByTid:\n" << str; 193800b99b8Sopenharmony_ci g_mutex.unlock(); 194800b99b8Sopenharmony_ci g_tid = 0; 195800b99b8Sopenharmony_ci if (backtraceThread.joinable()) { 196800b99b8Sopenharmony_ci backtraceThread.join(); 197800b99b8Sopenharmony_ci } 198800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "BacktraceLocalTest004: end."; 199800b99b8Sopenharmony_ci} 200800b99b8Sopenharmony_ci 201800b99b8Sopenharmony_ci/** 202800b99b8Sopenharmony_ci * @tc.name: BacktraceLocalTest005 203800b99b8Sopenharmony_ci * @tc.desc: test get backtrace of current process 204800b99b8Sopenharmony_ci * @tc.type: FUNC 205800b99b8Sopenharmony_ci */ 206800b99b8Sopenharmony_ciHWTEST_F(BacktraceLocalTest, BacktraceLocalTest005, TestSize.Level2) 207800b99b8Sopenharmony_ci{ 208800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "BacktraceLocalTest005: start."; 209800b99b8Sopenharmony_ci g_mutex.lock(); 210800b99b8Sopenharmony_ci std::thread backtraceThread(Test001); 211800b99b8Sopenharmony_ci sleep(1); 212800b99b8Sopenharmony_ci if (g_tid <= 0) { 213800b99b8Sopenharmony_ci FAIL() << "Failed to create child thread.\n"; 214800b99b8Sopenharmony_ci } 215800b99b8Sopenharmony_ci 216800b99b8Sopenharmony_ci std::string stacktrace = GetProcessStacktrace(); 217800b99b8Sopenharmony_ci ASSERT_GT(stacktrace.size(), 0); 218800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << stacktrace; 219800b99b8Sopenharmony_ci 220800b99b8Sopenharmony_ci if (stacktrace.find("backtrace_local_test") == std::string::npos) { 221800b99b8Sopenharmony_ci FAIL() << "Failed to find pid key word.\n"; 222800b99b8Sopenharmony_ci } 223800b99b8Sopenharmony_ci if (stacktrace.find("#01") == std::string::npos) { 224800b99b8Sopenharmony_ci FAIL() << "Failed to find stack key word.\n"; 225800b99b8Sopenharmony_ci } 226800b99b8Sopenharmony_ci 227800b99b8Sopenharmony_ci g_mutex.unlock(); 228800b99b8Sopenharmony_ci g_tid = 0; 229800b99b8Sopenharmony_ci if (backtraceThread.joinable()) { 230800b99b8Sopenharmony_ci backtraceThread.join(); 231800b99b8Sopenharmony_ci } 232800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "BacktraceLocalTest005: end."; 233800b99b8Sopenharmony_ci} 234800b99b8Sopenharmony_ci 235800b99b8Sopenharmony_ci/** 236800b99b8Sopenharmony_ci * @tc.name: BacktraceLocalTest006 237800b99b8Sopenharmony_ci * @tc.desc: test GetTrace C interface 238800b99b8Sopenharmony_ci * @tc.type: FUNC 239800b99b8Sopenharmony_ci */ 240800b99b8Sopenharmony_ciHWTEST_F(BacktraceLocalTest, BacktraceLocalTest006, TestSize.Level2) 241800b99b8Sopenharmony_ci{ 242800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "BacktraceLocalTest006: start."; 243800b99b8Sopenharmony_ci const char* trace = GetTrace(); 244800b99b8Sopenharmony_ci std::string stacktrace(trace); 245800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << stacktrace; 246800b99b8Sopenharmony_ci ASSERT_TRUE(stacktrace.find("#00") != std::string::npos); 247800b99b8Sopenharmony_ci ASSERT_TRUE(stacktrace.find("pc") != std::string::npos); 248800b99b8Sopenharmony_ci ASSERT_TRUE(stacktrace.find("backtrace_local_test") != std::string::npos); 249800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "BacktraceLocalTest006: end."; 250800b99b8Sopenharmony_ci} 251800b99b8Sopenharmony_ci 252800b99b8Sopenharmony_ci/** 253800b99b8Sopenharmony_ci * @tc.name: BacktraceLocalTest007 254800b99b8Sopenharmony_ci * @tc.desc: test skip two stack frames and verify stack frame 255800b99b8Sopenharmony_ci * @tc.type: FUNC 256800b99b8Sopenharmony_ci */ 257800b99b8Sopenharmony_ciHWTEST_F(BacktraceLocalTest, BacktraceLocalTest007, TestSize.Level2) 258800b99b8Sopenharmony_ci{ 259800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "BacktraceLocalTest007: start."; 260800b99b8Sopenharmony_ci ElapsedTime counter; 261800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(); 262800b99b8Sopenharmony_ci BacktraceLocalThread oldthread(BACKTRACE_CURRENT_THREAD, unwinder); 263800b99b8Sopenharmony_ci ASSERT_EQ(true, oldthread.Unwind(false)); 264800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindCurrentCost:" << counter.Elapsed(); 265800b99b8Sopenharmony_ci const auto& oldframes = oldthread.GetFrames(); 266800b99b8Sopenharmony_ci ASSERT_GT(oldframes.size(), MIN_FRAME_NUM); 267800b99b8Sopenharmony_ci std::string oldframe = DfxFrameFormatter::GetFrameStr(oldframes[MIN_FRAME_NUM]); 268800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << oldthread.GetFormattedStr(); 269800b99b8Sopenharmony_ci BacktraceLocalThread newthread(BACKTRACE_CURRENT_THREAD, unwinder); 270800b99b8Sopenharmony_ci ASSERT_EQ(true, newthread.Unwind(false, DEFAULT_MAX_FRAME_NUM, MIN_FRAME_NUM)); 271800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindCurrentCost:" << counter.Elapsed(); 272800b99b8Sopenharmony_ci const auto& newframes = newthread.GetFrames(); 273800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << newthread.GetFormattedStr(); 274800b99b8Sopenharmony_ci ASSERT_EQ(oldframes.size(), newframes.size() + MIN_FRAME_NUM); 275800b99b8Sopenharmony_ci std::string newframe = DfxFrameFormatter::GetFrameStr(newframes[0]); 276800b99b8Sopenharmony_ci size_t skip = 3; // skip #0x 277800b99b8Sopenharmony_ci ASSERT_EQ(oldframe.erase(0, skip), newframe.erase(0, skip)); 278800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "BacktraceLocalTest007: end."; 279800b99b8Sopenharmony_ci} 280800b99b8Sopenharmony_ci 281800b99b8Sopenharmony_ci/** 282800b99b8Sopenharmony_ci * @tc.name: BacktraceLocalTest008 283800b99b8Sopenharmony_ci * @tc.desc: test skip all stack frames 284800b99b8Sopenharmony_ci * @tc.type: FUNC 285800b99b8Sopenharmony_ci */ 286800b99b8Sopenharmony_ciHWTEST_F(BacktraceLocalTest, BacktraceLocalTest008, TestSize.Level2) 287800b99b8Sopenharmony_ci{ 288800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "BacktraceLocalTest008: start."; 289800b99b8Sopenharmony_ci ElapsedTime counter; 290800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(); 291800b99b8Sopenharmony_ci BacktraceLocalThread oldthread(BACKTRACE_CURRENT_THREAD, unwinder); 292800b99b8Sopenharmony_ci ASSERT_EQ(true, oldthread.Unwind(false)); 293800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindCurrentCost:" << counter.Elapsed(); 294800b99b8Sopenharmony_ci const auto& oldframes = oldthread.GetFrames(); 295800b99b8Sopenharmony_ci ASSERT_GT(oldframes.size(), 0); 296800b99b8Sopenharmony_ci size_t oldsize = oldframes.size() - 1; 297800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << oldthread.GetFormattedStr(); 298800b99b8Sopenharmony_ci BacktraceLocalThread newthread(BACKTRACE_CURRENT_THREAD, unwinder); 299800b99b8Sopenharmony_ci ASSERT_EQ(true, newthread.Unwind(false, DEFAULT_MAX_FRAME_NUM, oldsize)); 300800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindCurrentCost:" << counter.Elapsed(); 301800b99b8Sopenharmony_ci const auto& newframes = newthread.GetFrames(); 302800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << newthread.GetFormattedStr(); 303800b99b8Sopenharmony_ci ASSERT_EQ(oldframes.size(), newframes.size() + oldsize); 304800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "BacktraceLocalTest008: end."; 305800b99b8Sopenharmony_ci} 306800b99b8Sopenharmony_ci 307800b99b8Sopenharmony_ci 308800b99b8Sopenharmony_ci/** 309800b99b8Sopenharmony_ci * @tc.name: BacktraceLocalTest009 310800b99b8Sopenharmony_ci * @tc.desc: test skip stack frames exceeding the length 311800b99b8Sopenharmony_ci * @tc.type: FUNC 312800b99b8Sopenharmony_ci */ 313800b99b8Sopenharmony_ciHWTEST_F(BacktraceLocalTest, BacktraceLocalTest009, TestSize.Level2) 314800b99b8Sopenharmony_ci{ 315800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "BacktraceLocalTest009: start."; 316800b99b8Sopenharmony_ci ElapsedTime counter; 317800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(); 318800b99b8Sopenharmony_ci BacktraceLocalThread oldthread(BACKTRACE_CURRENT_THREAD, unwinder); 319800b99b8Sopenharmony_ci ASSERT_EQ(true, oldthread.Unwind(false, DEFAULT_MAX_FRAME_NUM, -1)); 320800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindCurrentCost:" << counter.Elapsed(); 321800b99b8Sopenharmony_ci const auto& oldframes = oldthread.GetFrames(); 322800b99b8Sopenharmony_ci ASSERT_GT(oldframes.size(), MIN_FRAME_NUM); 323800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << oldthread.GetFormattedStr(); 324800b99b8Sopenharmony_ci BacktraceLocalThread newthread(BACKTRACE_CURRENT_THREAD, unwinder); 325800b99b8Sopenharmony_ci ASSERT_EQ(true, newthread.Unwind(false, DEFAULT_MAX_FRAME_NUM, DEFAULT_MAX_FRAME_NUM)); 326800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindCurrentCost:" << counter.Elapsed(); 327800b99b8Sopenharmony_ci const auto& newframes = newthread.GetFrames(); 328800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << newthread.GetFormattedStr(); 329800b99b8Sopenharmony_ci ASSERT_EQ(oldframes.size(), newframes.size()); 330800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "BacktraceLocalTest009: end."; 331800b99b8Sopenharmony_ci} 332800b99b8Sopenharmony_ci 333800b99b8Sopenharmony_ci/** 334800b99b8Sopenharmony_ci * @tc.name: BacktraceLocalTest010 335800b99b8Sopenharmony_ci * @tc.desc: test get backtrace of current thread 336800b99b8Sopenharmony_ci * @tc.type: FUNC 337800b99b8Sopenharmony_ci */ 338800b99b8Sopenharmony_ciHWTEST_F(BacktraceLocalTest, BacktraceLocalTest010, TestSize.Level2) 339800b99b8Sopenharmony_ci{ 340800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "BacktraceLocalTest010: start."; 341800b99b8Sopenharmony_ci UnwinderConfig::SetEnableMiniDebugInfo(true); 342800b99b8Sopenharmony_ci std::string frame; 343800b99b8Sopenharmony_ci ASSERT_EQ(true, GetBacktrace(frame, 0, false, DEFAULT_MAX_FRAME_NUM)); 344800b99b8Sopenharmony_ci int start = frame.find("#00"); 345800b99b8Sopenharmony_ci int end = frame.find("#01"); 346800b99b8Sopenharmony_ci std::string str = frame.substr(start, end - start); 347800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "frame" << frame; 348800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "str" << str; 349800b99b8Sopenharmony_ci ASSERT_TRUE(str.find("OHOS::HiviewDFX::GetBacktrace(") != std::string::npos); 350800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "BacktraceLocalTest010: end."; 351800b99b8Sopenharmony_ci} 352800b99b8Sopenharmony_ci 353800b99b8Sopenharmony_ci/** 354800b99b8Sopenharmony_ci * @tc.name: BacktraceLocalTest011 355800b99b8Sopenharmony_ci * @tc.desc: test get thread kernel stack 356800b99b8Sopenharmony_ci * @tc.type: FUNC 357800b99b8Sopenharmony_ci */ 358800b99b8Sopenharmony_ciHWTEST_F(BacktraceLocalTest, BacktraceLocalTest011, TestSize.Level2) 359800b99b8Sopenharmony_ci{ 360800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "BacktraceLocalTest011: start."; 361800b99b8Sopenharmony_ci std::string res = ExecuteCommands("uname"); 362800b99b8Sopenharmony_ci if (res.find("Linux") != std::string::npos) { 363800b99b8Sopenharmony_ci return; 364800b99b8Sopenharmony_ci } 365800b99b8Sopenharmony_ci std::string kernelStack; 366800b99b8Sopenharmony_ci ASSERT_EQ(DfxGetKernelStack(gettid(), kernelStack), 0); 367800b99b8Sopenharmony_ci DfxThreadStack threadStack; 368800b99b8Sopenharmony_ci ASSERT_TRUE(FormatThreadKernelStack(kernelStack, threadStack)); 369800b99b8Sopenharmony_ci ASSERT_GT(threadStack.frames.size(), 0); 370800b99b8Sopenharmony_ci for (auto const& frame : threadStack.frames) { 371800b99b8Sopenharmony_ci auto line = DfxFrameFormatter::GetFrameStr(frame); 372800b99b8Sopenharmony_ci ASSERT_NE(line.find("#"), std::string::npos); 373800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << line; 374800b99b8Sopenharmony_ci } 375800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "BacktraceLocalTest011: end."; 376800b99b8Sopenharmony_ci} 377800b99b8Sopenharmony_ci 378800b99b8Sopenharmony_ci/** 379800b99b8Sopenharmony_ci * @tc.name: BacktraceLocalTest012 380800b99b8Sopenharmony_ci * @tc.desc: test BacktraceLocal abnormal scenario 381800b99b8Sopenharmony_ci * @tc.type: FUNC 382800b99b8Sopenharmony_ci */ 383800b99b8Sopenharmony_ciHWTEST_F(BacktraceLocalTest, BacktraceLocalTest012, TestSize.Level2) 384800b99b8Sopenharmony_ci{ 385800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "BacktraceLocalTest012: start."; 386800b99b8Sopenharmony_ci std::shared_ptr<Unwinder> unwinder1 = nullptr; 387800b99b8Sopenharmony_ci const int tid = -2; 388800b99b8Sopenharmony_ci BacktraceLocalThread backtrace1(tid, unwinder1); 389800b99b8Sopenharmony_ci bool ret = backtrace1.Unwind(false, 0, 0); 390800b99b8Sopenharmony_ci ASSERT_EQ(ret, false); 391800b99b8Sopenharmony_ci std::shared_ptr<Unwinder> unwinder2 = std::make_shared<Unwinder>(); 392800b99b8Sopenharmony_ci BacktraceLocalThread backtrace2(tid, unwinder2); 393800b99b8Sopenharmony_ci ret = backtrace2.Unwind(false, 0, 0); 394800b99b8Sopenharmony_ci ASSERT_EQ(ret, false); 395800b99b8Sopenharmony_ci std::string str = backtrace2.GetFormattedStr(false); 396800b99b8Sopenharmony_ci ASSERT_EQ(str, ""); 397800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "BacktraceLocalTest012: end."; 398800b99b8Sopenharmony_ci} 399800b99b8Sopenharmony_ci 400800b99b8Sopenharmony_ci/** 401800b99b8Sopenharmony_ci * @tc.name: BacktraceLocalTest013 402800b99b8Sopenharmony_ci * @tc.desc: Test async-stacktrace api enable in ffrt backtrace 403800b99b8Sopenharmony_ci * @tc.type: FUNC 404800b99b8Sopenharmony_ci */ 405800b99b8Sopenharmony_ciHWTEST_F(BacktraceLocalTest, BacktraceLocalTest013, TestSize.Level2) 406800b99b8Sopenharmony_ci{ 407800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "BacktraceLocalTest013: start."; 408800b99b8Sopenharmony_ci ElapsedTime counter; 409800b99b8Sopenharmony_ci int x = 1; 410800b99b8Sopenharmony_ci const int num = 100; 411800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(); 412800b99b8Sopenharmony_ci BacktraceLocalThread thread(BACKTRACE_CURRENT_THREAD, unwinder); 413800b99b8Sopenharmony_ci ffrt::submit([&]{x = num; thread.Unwind(false, DEFAULT_MAX_FRAME_NUM, 0);}, {}, {&x}); 414800b99b8Sopenharmony_ci ffrt::wait(); 415800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindCurrentCost:" << counter.Elapsed(); 416800b99b8Sopenharmony_ci const auto& frames = thread.GetFrames(); 417800b99b8Sopenharmony_ci ASSERT_GT(frames.size(), MIN_FRAME_NUM); 418800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << thread.GetFormattedStr(); 419800b99b8Sopenharmony_ci bool ret = false; 420800b99b8Sopenharmony_ci for (auto const& frame : frames) { 421800b99b8Sopenharmony_ci auto line = DfxFrameFormatter::GetFrameStr(frame); 422800b99b8Sopenharmony_ci if (line.find("libffrt.so") != std::string::npos) { 423800b99b8Sopenharmony_ci ret = true; 424800b99b8Sopenharmony_ci break; 425800b99b8Sopenharmony_ci } 426800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << line; 427800b99b8Sopenharmony_ci } 428800b99b8Sopenharmony_ci ASSERT_TRUE(ret); 429800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "BacktraceLocalTest013: end."; 430800b99b8Sopenharmony_ci} 431800b99b8Sopenharmony_ci 432800b99b8Sopenharmony_ci/** 433800b99b8Sopenharmony_ci * @tc.name: BacktraceLocalTest014 434800b99b8Sopenharmony_ci * @tc.desc: Test async-stacktrace api enable in ffrt backtrace 435800b99b8Sopenharmony_ci * @tc.type: FUNC 436800b99b8Sopenharmony_ci */ 437800b99b8Sopenharmony_ciHWTEST_F(BacktraceLocalTest, BacktraceLocalTest014, TestSize.Level2) 438800b99b8Sopenharmony_ci{ 439800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "BacktraceLocalTest014: start."; 440800b99b8Sopenharmony_ci ElapsedTime counter; 441800b99b8Sopenharmony_ci int x = 1; 442800b99b8Sopenharmony_ci const int num = 100; 443800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(); 444800b99b8Sopenharmony_ci int tid = -1; 445800b99b8Sopenharmony_ci ffrt::submit([&]{x = num; tid = gettid();}, {}, {&x}); 446800b99b8Sopenharmony_ci ffrt::wait(); 447800b99b8Sopenharmony_ci ASSERT_GT(tid, 0); 448800b99b8Sopenharmony_ci BacktraceLocalThread thread(tid, unwinder); 449800b99b8Sopenharmony_ci thread.Unwind(false, DEFAULT_MAX_FRAME_NUM, 0); 450800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindCurrentCost:" << counter.Elapsed(); 451800b99b8Sopenharmony_ci const auto& frames = thread.GetFrames(); 452800b99b8Sopenharmony_ci ASSERT_GT(frames.size(), MIN_FRAME_NUM); 453800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << thread.GetFormattedStr(); 454800b99b8Sopenharmony_ci bool ret = false; 455800b99b8Sopenharmony_ci for (auto const& frame : frames) { 456800b99b8Sopenharmony_ci auto line = DfxFrameFormatter::GetFrameStr(frame); 457800b99b8Sopenharmony_ci if (line.find("libffrt.so") != std::string::npos) { 458800b99b8Sopenharmony_ci ret = true; 459800b99b8Sopenharmony_ci break; 460800b99b8Sopenharmony_ci } 461800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << line; 462800b99b8Sopenharmony_ci } 463800b99b8Sopenharmony_ci ASSERT_TRUE(ret); 464800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "BacktraceLocalTest014: end."; 465800b99b8Sopenharmony_ci} 466800b99b8Sopenharmony_ci} // namespace HiviewDFX 467800b99b8Sopenharmony_ci} // namepsace OHOS 468