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