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