• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2024 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 
18 #include <cstdio>
19 #include <cstdlib>
20 #include <memory>
21 #include <mutex>
22 #include <pthread.h>
23 #include <csignal>
24 #include <thread>
25 
26 #include <dlfcn.h>
27 #include <fcntl.h>
28 #include <securec.h>
29 #include <sys/wait.h>
30 #include <unistd.h>
31 
32 #include "backtrace_local.h"
33 #include "backtrace_local_thread.h"
34 #include "dfx_frame_formatter.h"
35 #include "dfx_json_formatter.h"
36 #include "dfx_kernel_stack.h"
37 #include "dfx_test_util.h"
38 #include "elapsed_time.h"
39 #include "ffrt_inner.h"
40 #include "procinfo.h"
41 #include "unwinder_config.h"
42 
43 using namespace testing;
44 using namespace testing::ext;
45 
46 namespace OHOS {
47 namespace HiviewDFX {
48 #undef LOG_DOMAIN
49 #undef LOG_TAG
50 #define LOG_TAG "DfxBacktraceLocalTest"
51 #define LOG_DOMAIN 0xD002D11
52 #define DEFAULT_MAX_FRAME_NUM 256
53 #define MIN_FRAME_NUM 2
54 
55 class BacktraceLocalTest : public testing::Test {
56 public:
57     static void SetUpTestCase();
58     static void TearDownTestCase();
59     void SetUp();
60     void TearDown();
61 
62     uint32_t fdCount;
63     uint32_t mapsCount;
64     uint64_t memCount;
65 
66     static uint32_t fdCountTotal;
67     static uint32_t mapsCountTotal;
68     static uint64_t memCountTotal;
69 };
70 
71 uint32_t BacktraceLocalTest::fdCountTotal = 0;
72 uint32_t BacktraceLocalTest::mapsCountTotal = 0;
73 uint64_t BacktraceLocalTest::memCountTotal = 0;
74 
75 
SetUpTestCase()76 void BacktraceLocalTest::SetUpTestCase()
77 {
78     BacktraceLocalTest::fdCountTotal = GetSelfFdCount();
79     BacktraceLocalTest::mapsCountTotal = GetSelfMapsCount();
80     BacktraceLocalTest::memCountTotal = GetSelfMemoryCount();
81 }
82 
TearDownTestCase()83 void BacktraceLocalTest::TearDownTestCase()
84 {
85     CheckResourceUsage(fdCountTotal, mapsCountTotal, memCountTotal);
86 }
87 
SetUp()88 void BacktraceLocalTest::SetUp()
89 {
90     fdCount = GetSelfFdCount();
91     mapsCount = GetSelfMapsCount();
92     memCount = GetSelfMemoryCount();
93 }
94 
TearDown()95 void BacktraceLocalTest::TearDown()
96 {
97     CheckResourceUsage(fdCount, mapsCount, memCount);
98 }
99 
RequestMemory(char * msg)100 static void RequestMemory(char* msg)
101 {
102     usleep(2000); // 2000 : sleep 2ms
103     const int32_t initAllocSz = 11;
104     void* p = malloc(initAllocSz);
105     int ret = memcpy_s(p, initAllocSz, msg, initAllocSz - 1);
106     if (ret < 0) {
107         ASSERT_GT(ret, 0);
108     }
109     free(p);
110 }
111 
112 /**
113  * @tc.name: BacktraceLocalTest001
114  * @tc.desc: test get backtrace of current thread
115  * @tc.type: FUNC
116  */
117 HWTEST_F(BacktraceLocalTest, BacktraceLocalTest001, TestSize.Level2)
118 {
119     GTEST_LOG_(INFO) << "BacktraceLocalTest001: start.";
120     ElapsedTime counter;
121     Unwinder unwinder;
122     BacktraceLocalThread thread(BACKTRACE_CURRENT_THREAD);
123     ASSERT_EQ(true, thread.Unwind(unwinder, false));
124     GTEST_LOG_(INFO) << "UnwindCurrentCost:" << counter.Elapsed();
125     const auto& frames = thread.GetFrames();
126     ASSERT_GT(frames.size(), 0);
127     GTEST_LOG_(INFO) << thread.GetFormattedStr();
128     thread.SetFrames(frames);
129     GTEST_LOG_(INFO) << "BacktraceLocalTest001: end.";
130 }
131 
132 int32_t g_tid = 0;
133 std::mutex g_mutex;
Test002()134 __attribute__((noinline)) void Test002()
135 {
136     printf("Test002\n");
137     g_mutex.lock();
138     g_mutex.unlock();
139 }
140 
Test001()141 __attribute__((noinline)) void Test001()
142 {
143     g_tid = gettid();
144     printf("Test001:%d\n", g_tid);
145     Test002();
146 }
147 
Test003()148 __attribute__((noinline)) void Test003()
149 {
150     g_mutex.lock();
151     printf("Test003:%d\n", gettid());
152     std::thread backtraceThread(Test001);
153     sleep(1);
154     std::string stacktrace = GetProcessStacktrace();
155     g_mutex.unlock();
156     ASSERT_GT(stacktrace.size(), 0);
157     GTEST_LOG_(INFO) << stacktrace;
158     backtraceThread.join();
159     return;
160 }
161 
TestMaskSigDumpLocalInner()162 __attribute__((noinline)) void TestMaskSigDumpLocalInner()
163 {
164     printf("TestMaskSigDumpLocalInner\n");
165     g_mutex.lock();
166     g_mutex.unlock();
167 }
168 
TestMaskSigDumpLocal()169 __attribute__((noinline)) void TestMaskSigDumpLocal()
170 {
171     sigset_t set;
172     sigemptyset(&set);
173     sigaddset(&set, SIGLOCAL_DUMP);
174     if (pthread_sigmask(SIG_BLOCK, &set, nullptr) != 0) {
175         printf("pthread sigmask failed, err(%d)\n", errno);
176     }
177     g_tid = gettid();
178     printf("TestMaskSigDumpLocal:%d\n", g_tid);
179     TestMaskSigDumpLocalInner();
180 }
181 
182 /**
183  * @tc.name: BacktraceLocalTest003
184  * @tc.desc: test get backtrace of a child thread
185  * @tc.type: FUNC
186  */
187 HWTEST_F(BacktraceLocalTest, BacktraceLocalTest003, TestSize.Level2)
188 {
189     GTEST_LOG_(INFO) << "BacktraceLocalTest003: start.";
190     g_mutex.lock();
191     std::thread backtraceThread(Test001);
192     sleep(1);
193     if (g_tid <= 0) {
194         FAIL() << "Failed to create child thread.\n";
195     }
196 
197     ElapsedTime counter;
198     Unwinder unwinder;
199     BacktraceLocalThread thread(g_tid);
200     ASSERT_EQ(true, thread.Unwind(unwinder, false));
201     GTEST_LOG_(INFO) << "UnwindCurrentCost:" << counter.Elapsed();
202     const auto& frames = thread.GetFrames();
203     ASSERT_GT(frames.size(), 0);
204     auto backtraceStr = thread.GetFormattedStr(false);
205     ASSERT_GT(backtraceStr.size(), 0);
206     GTEST_LOG_(INFO) << "backtraceStr:\n" << backtraceStr;
207 
208     std::string str;
209     auto ret = GetBacktraceStringByTid(str, g_tid, 0, false);
210     ASSERT_TRUE(ret);
211     GTEST_LOG_(INFO) << "GetBacktraceStringByTid:\n" << str;
212     g_mutex.unlock();
213     g_tid = 0;
214     if (backtraceThread.joinable()) {
215         backtraceThread.join();
216     }
217     GTEST_LOG_(INFO) << "BacktraceLocalTest003: end.";
218 }
219 
220 /**
221  * @tc.name: BacktraceLocalTest004
222  * @tc.desc: test get backtrace of a child thread
223  * @tc.type: FUNC
224  */
225 HWTEST_F(BacktraceLocalTest, BacktraceLocalTest004, TestSize.Level0)
226 {
227     GTEST_LOG_(INFO) << "BacktraceLocalTest004: start.";
228     g_mutex.lock();
229     std::thread backtraceThread(Test001);
230     sleep(1);
231     if (g_tid <= 0) {
232         FAIL() << "Failed to create child thread.\n";
233     }
234 
235     std::string str;
236     auto ret = GetBacktraceStringByTid(str, g_tid, 0, false);
237     ASSERT_TRUE(ret);
238     string log[] = {"#00", "backtrace_local", "Tid:", "Name"};
239     log[2] = log[2] + std::to_string(g_tid);
240     int logSize = sizeof(log) / sizeof(log[0]);
241     int count = GetKeywordsNum(str, log, logSize);
242     EXPECT_EQ(count, logSize) << "BacktraceLocalTest004 Failed";
243     GTEST_LOG_(INFO) << "GetBacktraceStringByTid:\n" << str;
244     g_mutex.unlock();
245     g_tid = 0;
246     if (backtraceThread.joinable()) {
247         backtraceThread.join();
248     }
249     GTEST_LOG_(INFO) << "BacktraceLocalTest004: end.";
250 }
251 
252 /**
253  * @tc.name: BacktraceLocalTest005
254  * @tc.desc: test get backtrace of current process
255  * @tc.type: FUNC
256  */
257 HWTEST_F(BacktraceLocalTest, BacktraceLocalTest005, TestSize.Level2)
258 {
259     GTEST_LOG_(INFO) << "BacktraceLocalTest005: start.";
260     g_mutex.lock();
261     std::thread backtraceThread(Test001);
262     sleep(1);
263     if (g_tid <= 0) {
264         FAIL() << "Failed to create child thread.\n";
265     }
266 
267     std::string stacktrace = GetProcessStacktrace();
268     ASSERT_GT(stacktrace.size(), 0);
269     GTEST_LOG_(INFO) << stacktrace;
270 
271     if (stacktrace.find("backtrace_local_test") == std::string::npos) {
272         FAIL() << "Failed to find pid key word.\n";
273     }
274     if (stacktrace.find("#01") == std::string::npos) {
275         FAIL() << "Failed to find stack key word.\n";
276     }
277 
278     g_mutex.unlock();
279     g_tid = 0;
280     if (backtraceThread.joinable()) {
281         backtraceThread.join();
282     }
283     GTEST_LOG_(INFO) << "BacktraceLocalTest005: end.";
284 }
285 
286 /**
287  * @tc.name: BacktraceLocalTest006
288  * @tc.desc: test GetTrace C interface
289  * @tc.type: FUNC
290  */
291 HWTEST_F(BacktraceLocalTest, BacktraceLocalTest006, TestSize.Level2)
292 {
293     GTEST_LOG_(INFO) << "BacktraceLocalTest006: start.";
294     const char* trace = GetTrace();
295     std::string stacktrace(trace);
296     GTEST_LOG_(INFO) << stacktrace;
297     ASSERT_TRUE(stacktrace.find("#00") != std::string::npos);
298     ASSERT_TRUE(stacktrace.find("pc") != std::string::npos);
299     ASSERT_TRUE(stacktrace.find("backtrace_local_test") != std::string::npos);
300     GTEST_LOG_(INFO) << "BacktraceLocalTest006: end.";
301 }
302 
303 /**
304  * @tc.name: BacktraceLocalTest007
305  * @tc.desc: test skip two stack frames and verify stack frame
306  * @tc.type: FUNC
307  */
308 HWTEST_F(BacktraceLocalTest, BacktraceLocalTest007, TestSize.Level2)
309 {
310     GTEST_LOG_(INFO) << "BacktraceLocalTest007: start.";
311     ElapsedTime counter;
312     Unwinder unwinder;
313     BacktraceLocalThread oldthread(BACKTRACE_CURRENT_THREAD);
314     ASSERT_EQ(true, oldthread.Unwind(unwinder, false));
315     GTEST_LOG_(INFO) << "UnwindCurrentCost:" << counter.Elapsed();
316     const auto& oldframes = oldthread.GetFrames();
317     ASSERT_GT(oldframes.size(), MIN_FRAME_NUM);
318     std::string oldframe = DfxFrameFormatter::GetFrameStr(oldframes[MIN_FRAME_NUM]);
319     GTEST_LOG_(INFO) << oldthread.GetFormattedStr();
320     BacktraceLocalThread newthread(BACKTRACE_CURRENT_THREAD);
321     ASSERT_EQ(true, newthread.Unwind(unwinder, false, DEFAULT_MAX_FRAME_NUM, MIN_FRAME_NUM));
322     GTEST_LOG_(INFO) << "UnwindCurrentCost:" << counter.Elapsed();
323     const auto& newframes = newthread.GetFrames();
324     GTEST_LOG_(INFO) << newthread.GetFormattedStr();
325     ASSERT_EQ(oldframes.size(), newframes.size() + MIN_FRAME_NUM);
326     std::string newframe = DfxFrameFormatter::GetFrameStr(newframes[0]);
327     size_t skip = 3; // skip #0x
328     ASSERT_EQ(oldframe.erase(0, skip), newframe.erase(0, skip));
329     GTEST_LOG_(INFO) << "BacktraceLocalTest007: end.";
330 }
331 
332 /**
333  * @tc.name: BacktraceLocalTest008
334  * @tc.desc: test skip all stack frames
335  * @tc.type: FUNC
336  */
337 HWTEST_F(BacktraceLocalTest, BacktraceLocalTest008, TestSize.Level2)
338 {
339     GTEST_LOG_(INFO) << "BacktraceLocalTest008: start.";
340     ElapsedTime counter;
341     Unwinder unwinder;
342     BacktraceLocalThread oldthread(BACKTRACE_CURRENT_THREAD);
343     ASSERT_EQ(true, oldthread.Unwind(unwinder, false));
344     GTEST_LOG_(INFO) << "UnwindCurrentCost:" << counter.Elapsed();
345     const auto& oldframes = oldthread.GetFrames();
346     ASSERT_GT(oldframes.size(), 0);
347     size_t oldsize = oldframes.size() - 1;
348     GTEST_LOG_(INFO) << oldthread.GetFormattedStr();
349     BacktraceLocalThread newthread(BACKTRACE_CURRENT_THREAD);
350     ASSERT_EQ(true, newthread.Unwind(unwinder, false, DEFAULT_MAX_FRAME_NUM, oldsize));
351     GTEST_LOG_(INFO) << "UnwindCurrentCost:" << counter.Elapsed();
352     const auto& newframes = newthread.GetFrames();
353     GTEST_LOG_(INFO) << newthread.GetFormattedStr();
354     ASSERT_EQ(oldframes.size(), newframes.size() + oldsize);
355     GTEST_LOG_(INFO) << "BacktraceLocalTest008: end.";
356 }
357 
358 
359 /**
360  * @tc.name: BacktraceLocalTest009
361  * @tc.desc: test skip stack frames exceeding the length
362  * @tc.type: FUNC
363  */
364 HWTEST_F(BacktraceLocalTest, BacktraceLocalTest009, TestSize.Level2)
365 {
366     GTEST_LOG_(INFO) << "BacktraceLocalTest009: start.";
367     ElapsedTime counter;
368     Unwinder unwinder;
369     BacktraceLocalThread oldthread(BACKTRACE_CURRENT_THREAD);
370     ASSERT_EQ(true, oldthread.Unwind(unwinder, false, DEFAULT_MAX_FRAME_NUM, -2));
371     GTEST_LOG_(INFO) << "UnwindCurrentCost:" << counter.Elapsed();
372     const auto& oldframes = oldthread.GetFrames();
373     ASSERT_GT(oldframes.size(), MIN_FRAME_NUM);
374     GTEST_LOG_(INFO) << oldthread.GetFormattedStr();
375     BacktraceLocalThread newthread(BACKTRACE_CURRENT_THREAD);
376     ASSERT_EQ(true, newthread.Unwind(unwinder, false, DEFAULT_MAX_FRAME_NUM, DEFAULT_MAX_FRAME_NUM));
377     GTEST_LOG_(INFO) << "UnwindCurrentCost:" << counter.Elapsed();
378     const auto& newframes = newthread.GetFrames();
379     GTEST_LOG_(INFO) << newthread.GetFormattedStr();
380     ASSERT_EQ(oldframes.size(), newframes.size());
381     GTEST_LOG_(INFO) << "BacktraceLocalTest009: end.";
382 }
383 
384 /**
385  * @tc.name: BacktraceLocalTest010
386  * @tc.desc: test get backtrace of current thread
387  * @tc.type: FUNC
388  */
389 HWTEST_F(BacktraceLocalTest, BacktraceLocalTest010, TestSize.Level2)
390 {
391     GTEST_LOG_(INFO) << "BacktraceLocalTest010: start.";
392     UnwinderConfig::SetEnableMiniDebugInfo(true);
393     std::string frameAll;
394     GetBacktrace(frameAll, DEFAULT_MAX_FRAME_NUM, false, DEFAULT_MAX_FRAME_NUM);
395     GTEST_LOG_(INFO) << "--------all frames begin-----------";
396     GTEST_LOG_(INFO) << frameAll;
397     GTEST_LOG_(INFO) << "--------all frames end-----------";
398     std::string frame;
399     ASSERT_EQ(true, GetBacktrace(frame, 0, false, DEFAULT_MAX_FRAME_NUM));
400     int start = frame.find("#00");
401     int end = frame.find("#01");
402     std::string str = frame.substr(start, end - start);
403     GTEST_LOG_(INFO) << "frame" << frame;
404     GTEST_LOG_(INFO) << "str" << str;
405     ASSERT_TRUE(str.find("OHOS::HiviewDFX::GetBacktrace(") != std::string::npos);
406     GTEST_LOG_(INFO) << "BacktraceLocalTest010: end.";
407 }
408 
409 /**
410  * @tc.name: BacktraceLocalTest011
411  * @tc.desc: test get thread kernel stack
412  * @tc.type: FUNC
413  */
414 HWTEST_F(BacktraceLocalTest, BacktraceLocalTest011, TestSize.Level2)
415 {
416     GTEST_LOG_(INFO) << "BacktraceLocalTest011: start.";
417     std::string res = ExecuteCommands("uname");
418     if (res.find("Linux") != std::string::npos) {
419         ASSERT_NE(res.find("Linux"), std::string::npos);
420     } else {
421         std::string kernelStack;
422         ASSERT_EQ(DfxGetKernelStack(gettid(), kernelStack), 0);
423         DfxThreadStack threadStack;
424         ASSERT_TRUE(FormatThreadKernelStack(kernelStack, threadStack));
425         ASSERT_GT(threadStack.frames.size(), 0);
426         for (const auto& frame : threadStack.frames) {
427             auto line = DfxFrameFormatter::GetFrameStr(frame);
428             ASSERT_NE(line.find("#"), std::string::npos);
429             GTEST_LOG_(INFO) << line;
430         }
431         std::vector<DfxThreadStack> processStack;
432         ASSERT_TRUE(FormatProcessKernelStack(kernelStack, processStack));
433         for (const auto& stack : processStack) {
434             ASSERT_GT(stack.frames.size(), 0);
435         }
436         std::string formattedStack;
437         ASSERT_TRUE(DfxJsonFormatter::FormatKernelStack(kernelStack, formattedStack, false));
438         ASSERT_GT(formattedStack.size(), 0);
439         ASSERT_TRUE(formattedStack.find("Tid:") != std::string::npos) << formattedStack;
440         ASSERT_TRUE(formattedStack.find("backtrace_local_test") != std::string::npos) << formattedStack;
441 
442         ASSERT_TRUE(DfxJsonFormatter::FormatKernelStack(kernelStack, formattedStack, true));
443         ASSERT_TRUE(formattedStack.find("\"tid\":") != std::string::npos) << formattedStack;
444         ASSERT_TRUE(formattedStack.find("backtrace_local_test") != std::string::npos) << formattedStack;
445         GTEST_LOG_(INFO) << "BacktraceLocalTest011: end.";
446     }
447 }
448 
449 /**
450  * @tc.name: BacktraceLocalTest012
451  * @tc.desc: test BacktraceLocal abnormal scenario
452  * @tc.type: FUNC
453  */
454 HWTEST_F(BacktraceLocalTest, BacktraceLocalTest012, TestSize.Level2)
455 {
456     GTEST_LOG_(INFO) << "BacktraceLocalTest012: start.";
457     const int tid = -2;
458     Unwinder unwinder;
459     BacktraceLocalThread backtrace(tid);
460     ASSERT_EQ(backtrace.Unwind(unwinder, false, 0, 0), false);
461     std::string str = backtrace.GetFormattedStr(false);
462     ASSERT_EQ(str, "");
463     GTEST_LOG_(INFO) << "BacktraceLocalTest012: end.";
464 }
465 
466 /**
467  * @tc.name: BacktraceLocalTest013
468  * @tc.desc: Test async-stacktrace api enable in ffrt backtrace
469  * @tc.type: FUNC
470  */
471 HWTEST_F(BacktraceLocalTest, BacktraceLocalTest013, TestSize.Level2)
472 {
473     GTEST_LOG_(INFO) << "BacktraceLocalTest013: start.";
474     ElapsedTime counter;
475     int x = 1;
476     const int num = 100;
477     Unwinder unwinder;
478     BacktraceLocalThread thread(BACKTRACE_CURRENT_THREAD);
__anon565d91c80102null479     ffrt::submit([&]{x = num; thread.Unwind(unwinder, false, DEFAULT_MAX_FRAME_NUM, 0);}, {}, {&x});
480     ffrt::wait();
481     GTEST_LOG_(INFO) << "UnwindCurrentCost:" << counter.Elapsed();
482     const auto& frames = thread.GetFrames();
483     ASSERT_GT(frames.size(), MIN_FRAME_NUM);
484     GTEST_LOG_(INFO) << thread.GetFormattedStr();
485     bool ret = false;
486     for (auto const& frame : frames) {
487         auto line = DfxFrameFormatter::GetFrameStr(frame);
488         if (line.find("libffrt.so") != std::string::npos) {
489             ret = true;
490             break;
491         }
492         GTEST_LOG_(INFO) << line;
493     }
494     ASSERT_TRUE(ret);
495     GTEST_LOG_(INFO) << "BacktraceLocalTest013: end.";
496 }
497 
498 /**
499  * @tc.name: BacktraceLocalTest014
500  * @tc.desc: Test async-stacktrace api enable in ffrt backtrace
501  * @tc.type: FUNC
502  */
503 HWTEST_F(BacktraceLocalTest, BacktraceLocalTest014, TestSize.Level2)
504 {
505     GTEST_LOG_(INFO) << "BacktraceLocalTest014: start.";
506     ElapsedTime counter;
507     int x = 1;
508     const int num = 100;
509     Unwinder unwinder;
510     int tid = -1;
__anon565d91c80202null511     ffrt::submit([&]{x = num; tid = gettid();}, {}, {&x});
512     ffrt::wait();
513     ASSERT_GT(tid, 0);
514     BacktraceLocalThread thread(tid);
515     thread.Unwind(unwinder, false, DEFAULT_MAX_FRAME_NUM, 0);
516     GTEST_LOG_(INFO) << "UnwindCurrentCost:" << counter.Elapsed();
517     const auto& frames = thread.GetFrames();
518     ASSERT_GT(frames.size(), MIN_FRAME_NUM);
519     GTEST_LOG_(INFO) << thread.GetFormattedStr();
520     bool ret = false;
521     for (auto const& frame : frames) {
522         auto line = DfxFrameFormatter::GetFrameStr(frame);
523         if (line.find("libffrt.so") != std::string::npos) {
524             ret = true;
525             break;
526         }
527         GTEST_LOG_(INFO) << line;
528     }
529     ASSERT_TRUE(ret);
530     GTEST_LOG_(INFO) << "BacktraceLocalTest014: end.";
531 }
532 
533 /**
534 * @tc.name: BacktraceLocalTest015
535 * @tc.desc: Test lock exit after being loacl
536 * @tc.type: FUNC
537 */
538 HWTEST_F(BacktraceLocalTest, BacktraceLocalTest015, TestSize.Level2)
539 {
540     GTEST_LOG_(INFO) << "BacktraceLocalTest015: start.";
541     const size_t count = 50;
542     const size_t msgSize = 10;
543     char msg[msgSize] = {'a', 'b', 'c', 'd'};
544     for (size_t i = 0; i < count; i++) {
545         std::thread shmThread(RequestMemory, msg);
546         std::string stacktrace = GetProcessStacktrace();
547         ASSERT_GT(stacktrace.size(), 0);
548         GTEST_LOG_(INFO) << stacktrace;
549         shmThread.detach();
550     }
551     GTEST_LOG_(INFO) << "BacktraceLocalTest015: end.";
552 }
553 
GetLastLineAddr(const std::string & inputStr,int colNumber)554 std::vector<std::string> GetLastLineAddr(const std::string& inputStr, int colNumber)
555 {
556     std::istringstream iss(inputStr);
557     std::string line;
558     std::vector<std::string> lines;
559     std::vector<std::string> results;
560     // get lines
561     while (std::getline(iss, line)) {
562         if (line.find("backtrace_local_test") != std::string::npos) {
563             lines.push_back(line);
564         }
565     }
566     // get column
567     for (const auto& stackLine : lines) {
568         std::istringstream lineIss(stackLine);
569         std::string token;
570         int tokenCount = 0;
571         while (lineIss >> token) {
572             tokenCount++;
573             if (tokenCount == colNumber) {
574                 results.push_back(token);
575                 break;
576             }
577         }
578     }
579     return results;
580 }
581 
Compare(const std::string & oldStr,const std::string & mixStr,int colNumber)582 void Compare(const std::string& oldStr, const std::string& mixStr, int colNumber)
583 {
584     std::vector<std::string> oldStrAddrs = GetLastLineAddr(oldStr, colNumber);
585     std::vector<std::string> mixStrAddrs = GetLastLineAddr(mixStr, colNumber);
586     ASSERT_EQ(oldStrAddrs, mixStrAddrs);
587 }
588 
CallMixLast(int tid,bool fast,int colNumber)589 void CallMixLast(int tid, bool fast, int colNumber)
590 {
591     std::string oldStr;
592     bool ret = GetBacktraceStringByTid(oldStr, tid, 0, fast);
593     ASSERT_TRUE(ret) << "GetBacktraceStringByTid failed";
594     std::string mixStr;
595     ret = GetBacktraceStringByTidWithMix(mixStr, tid, 0, fast);
596     ASSERT_TRUE(ret) << "GetBacktraceStringByTidWithMix failed";
597     GTEST_LOG_(INFO) << "oldStr:" << oldStr;
598     GTEST_LOG_(INFO) << "mixStr:" << mixStr;
599     Compare(oldStr, mixStr, colNumber);
600 }
601 
CallMixFirst(int tid,bool fast,int colNumber)602 void CallMixFirst(int tid, bool fast, int colNumber)
603 {
604     std::string mixStr;
605     bool ret = GetBacktraceStringByTidWithMix(mixStr, tid, 0, fast);
606     ASSERT_TRUE(ret) << "GetBacktraceStringByTidWithMix failed";
607     std::string oldStr;
608     ret = GetBacktraceStringByTid(oldStr, tid, 0, fast);
609     ASSERT_TRUE(ret) << "GetBacktraceStringByTid failed";
610     GTEST_LOG_(INFO) << "oldStr:" << oldStr;
611     GTEST_LOG_(INFO) << "mixStr:" << mixStr;
612     Compare(oldStr, mixStr, colNumber);
613 }
614 
615 #if defined(__arm__) || defined(__aarch64__)
616 /**
617  * @tc.name: BacktraceLocalTest016
618  * @tc.desc: test backtrace other thread
619  * @tc.type: FUNC
620  */
621 HWTEST_F(BacktraceLocalTest, BacktraceLocalTest016, TestSize.Level2)
622 {
623     g_mutex.lock();
624     std::thread backtraceTread(Test001);
625     sleep(1);
626     if (g_tid <= 0) {
627         FAIL() << "Failed to create child thread.\n";
628     }
629     CallMixLast(g_tid, false, 3);
630     CallMixFirst(g_tid, false, 3);
631     CallMixLast(g_tid, true, 3);
632     CallMixFirst(g_tid, true, 3);
633     g_mutex.unlock();
634     g_tid = 0;
635     if (backtraceTread.joinable()) {
636         backtraceTread.join();
637     }
638 }
639 #endif
640 
641 /**
642  * @tc.name: BacktraceLocalTest017
643  * @tc.desc: test FormatProcessKernelStack
644  * @tc.type: FUNC
645  */
646 HWTEST_F(BacktraceLocalTest, BacktraceLocalTest017, TestSize.Level2)
647 {
648     GTEST_LOG_(INFO) << "BacktraceLocalTest017: start.";
649     std::string res = ExecuteCommands("uname");
650     if (res.find("Linux") != std::string::npos) {
651         ASSERT_NE(res.find("Linux"), std::string::npos);
652     } else {
653         pid_t pid = GetProcessPid(FOUNDATION_NAME);
654         std::vector<int> tids;
655         std::vector<int> nstids;
656         ASSERT_TRUE(GetTidsByPid(pid, tids, nstids));
657         std::string processKernelStackInfo;
658         for (const auto& tid : tids) {
659             std::string kernelStack;
660             ASSERT_EQ(DfxGetKernelStack(tid, kernelStack), 0);
661             processKernelStackInfo += kernelStack;
662         }
663         std::vector<DfxThreadStack> processStack;
664         ASSERT_TRUE(FormatProcessKernelStack(processKernelStackInfo, processStack));
665         for (const auto& threadStack : processStack) {
666             ASSERT_GT(threadStack.frames.size(), 0);
667             for (auto const& frame : threadStack.frames) {
668                 auto line = DfxFrameFormatter::GetFrameStr(frame);
669                 ASSERT_NE(line.find("#"), std::string::npos);
670                 GTEST_LOG_(INFO) << line;
671             }
672         }
673         GTEST_LOG_(INFO) << "BacktraceLocalTest017: end.";
674     }
675 }
676 
677 /**
678  * @tc.name: BacktraceLocalTest018
679  * @tc.desc: test backtrace using kernel stack
680  * @tc.type: FUNC
681  */
682 HWTEST_F(BacktraceLocalTest, BacktraceLocalTest018, TestSize.Level2)
683 {
684     GTEST_LOG_(INFO) << "BacktraceLocalTest018: start.";
685     std::string res = ExecuteCommands("uname");
686     if (res.find("Linux") != std::string::npos) {
687         ASSERT_NE(res.find("Linux"), std::string::npos);
688     } else {
689         g_mutex.lock();
690         std::thread backtraceThread(TestMaskSigDumpLocal);
691         sleep(1);
692         if (g_tid <= 0) {
693             FAIL() << "Failed to create child thread.\n";
694         }
695         std::string str;
696         ASSERT_TRUE(GetBacktraceStringByTid(str, g_tid, 0, false)) << str;
697         ASSERT_TRUE(GetBacktraceStringByTidWithMix(str, g_tid, 0, false)) << str;
698         ASSERT_TRUE(!GetProcessStacktrace().empty());
699         g_mutex.unlock();
700         g_tid = 0;
701         if (backtraceThread.joinable()) {
702             backtraceThread.join();
703         }
704         GTEST_LOG_(INFO) << "BacktraceLocalTest018: end.";
705     }
706 }
707 
708 /**
709  * @tc.name: BacktraceLocalTest019
710  * @tc.desc: test get backtrace of current process
711  * @tc.type: FUNC
712  */
713 HWTEST_F(BacktraceLocalTest, BacktraceLocalTest019, TestSize.Level2)
714 {
715     std::thread backtraceThread(Test003);
716     backtraceThread.join();
717     ASSERT_GT(g_tid, 0) << "Failed to create child thread.\n";
718     g_tid = 0;
719 }
720 } // namespace HiviewDFX
721 } // namepsace OHOS
722