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