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