• 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 <directory_ex.h>
20 #include <fcntl.h>
21 #include <malloc.h>
22 #include <string_ex.h>
23 #include <thread>
24 #include <unistd.h>
25 
26 #include "backtrace_local.h"
27 #include "dfx_test_util.h"
28 #include "file_util.h"
29 
30 using namespace testing;
31 using namespace testing::ext;
32 
33 namespace OHOS {
34 namespace HiviewDFX {
35 #undef LOG_DOMAIN
36 #undef LOG_TAG
37 #define LOG_TAG "DfxBacktraceUtilsTest"
38 #define LOG_DOMAIN 0xD002D11
39 
40 #define TEST_TEMP_FILE "/data/test/testfile"
41 /*
42 expected output log should be like this(aarch64):
43     Backtrace: #01 pc 000000000000d2f8 /data/test/backtrace_utils_test
44     Backtrace: #02 pc 000000000000d164 /data/test/backtrace_utils_test
45     Backtrace: #03 pc 000000000000c86c /data/test/backtrace_utils_test
46     Backtrace: #04 pc 0000000000013f88 /data/test/backtrace_utils_test
47     Backtrace: #05 pc 00000000000148a4 /data/test/backtrace_utils_test
48     Backtrace: #06 pc 0000000000015140 /data/test/backtrace_utils_test
49     Backtrace: #07 pc 00000000000242d8 /data/test/backtrace_utils_test
50     Backtrace: #08 pc 0000000000023bd8 /data/test/backtrace_utils_test
51     Backtrace: #09 pc 000000000000df68 /data/test/backtrace_utils_test
52     Backtrace: #10 pc 00000000000dcf74 /system/lib/ld-musl-aarch64.so.1
53     Backtrace: #11 pc 000000000000c614 /data/test/backtrace_utils_test
54 */
55 
56 class BacktraceUtilsTest : public testing::Test {
57 public:
58     static void SetUpTestCase();
59     static void TearDownTestCase();
60     void SetUp();
61     void TearDown();
62 
63     uint32_t fdCount;
64     uint32_t mapsCount;
65     uint64_t memCount;
66 
67     static uint32_t fdCountTotal;
68     static uint32_t mapsCountTotal;
69     static uint64_t memCountTotal;
70 };
71 
72 uint32_t BacktraceUtilsTest::fdCountTotal = 0;
73 uint32_t BacktraceUtilsTest::mapsCountTotal = 0;
74 uint64_t BacktraceUtilsTest::memCountTotal = 0;
75 
SetUpTestCase()76 void BacktraceUtilsTest::SetUpTestCase()
77 {
78     // get memory/fd/maps
79     BacktraceUtilsTest::fdCountTotal = GetSelfFdCount();
80     BacktraceUtilsTest::mapsCountTotal = GetSelfMapsCount();
81     BacktraceUtilsTest::memCountTotal = GetSelfMemoryCount();
82 }
83 
TearDownTestCase()84 void BacktraceUtilsTest::TearDownTestCase()
85 {
86     // check memory/fd/maps
87     CheckResourceUsage(fdCountTotal, mapsCountTotal, memCountTotal);
88 }
89 
SetUp()90 void BacktraceUtilsTest::SetUp()
91 {
92     // get memory/fd/maps
93     fdCount = GetSelfFdCount();
94     mapsCount = GetSelfMapsCount();
95     memCount = GetSelfMemoryCount();
96 }
97 
TearDown()98 void BacktraceUtilsTest::TearDown()
99 {
100 #ifdef USE_JEMALLOC_DFX_INTF
101     mallopt(M_FLUSH_THREAD_CACHE, 0);
102 #endif
103     // check memory/fd/maps
104     CheckResourceUsage(fdCount, mapsCount, memCount);
105 }
106 
CheckBacktraceContent(const std::string & content,bool fast=false)107 static bool CheckBacktraceContent(const std::string& content, bool fast = false)
108 {
109     std::string existKeyWords[] = { "#04", "backtrace_utils_test", "system" };
110     std::string notExistkeyWords[] = {
111 #if defined(__aarch64__)
112         "0000000000000000",
113 #elif defined(__arm__)
114         "00000000",
115 #endif
116         "OHOS::HiviewDFX::GetBacktrace",
117         "OHOS::HiviewDFX::PrintBacktrace"
118     };
119 
120     if (!fast) {
121         for (std::string keyWord : existKeyWords) {
122             if (!CheckContent(content, keyWord, true)) {
123                 return false;
124             }
125         }
126     }
127     for (std::string keyWord : notExistkeyWords) {
128         if (!CheckContent(content, keyWord, false)) {
129             return false;
130         }
131     }
132     return true;
133 }
134 
TestGetBacktraceInterface()135 static bool TestGetBacktraceInterface()
136 {
137     std::string content;
138     if (!GetBacktrace(content)) {
139         return false;
140     }
141 
142     GTEST_LOG_(INFO) << content;
143     if (content.empty()) {
144         return false;
145     }
146 
147     if (!CheckBacktraceContent(content)) {
148         return false;
149     }
150     return true;
151 }
152 
TestGetBacktraceFastInterface()153 static bool TestGetBacktraceFastInterface()
154 {
155 #ifdef __aarch64__
156     std::string content;
157     if (!GetBacktrace(content, true)) {
158         return false;
159     }
160 
161     GTEST_LOG_(INFO) << content;
162     if (content.empty()) {
163         return false;
164     }
165 
166     if (!CheckBacktraceContent(content, true)) {
167         return false;
168     }
169 #endif
170     return true;
171 }
172 
173 /**
174  * @tc.name: BacktraceUtilsTest001
175  * @tc.desc: test log backtrace to hilog, stdout and file
176  * @tc.type: FUNC
177  */
178 HWTEST_F(BacktraceUtilsTest, BacktraceUtilsTest001, TestSize.Level2)
179 {
180     GTEST_LOG_(INFO) << "BacktraceUtilsTest001: start.";
181     ASSERT_EQ(true, PrintBacktrace(STDIN_FILENO));
182     ASSERT_EQ(true, PrintBacktrace(STDOUT_FILENO));
183     ASSERT_EQ(true, PrintBacktrace(STDERR_FILENO));
184     ASSERT_EQ(true, PrintBacktrace());
185     int fd = open(TEST_TEMP_FILE, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
186     ASSERT_TRUE(fd >= 0);
187     ASSERT_EQ(true, PrintBacktrace(fd));
188     close(fd);
189     std::string content;
190     if (!OHOS::HiviewDFX::LoadStringFromFile(TEST_TEMP_FILE, content)) {
191         FAIL();
192     }
193     ASSERT_EQ(CheckBacktraceContent(content), true);
194     GTEST_LOG_(INFO) << "BacktraceUtilsTest001: end.";
195 }
196 
197 /**
198  * @tc.name: BacktraceUtilsTest002
199  * @tc.desc: test get backtrace
200  * @tc.type: FUNC
201  */
202 HWTEST_F(BacktraceUtilsTest, BacktraceUtilsTest002, TestSize.Level2)
203 {
204     GTEST_LOG_(INFO) << "BacktraceUtilsTest002: start.";
205     ASSERT_EQ(TestGetBacktraceInterface(), true);
206     ASSERT_EQ(TestGetBacktraceFastInterface(), true);
207     GTEST_LOG_(INFO) << "BacktraceUtilsTest002: end.";
208 }
209 
210 /**
211  * @tc.name: BacktraceUtilsTest003
212  * @tc.desc: test get backtrace 100 times
213  * @tc.type: FUNC
214  */
215 HWTEST_F(BacktraceUtilsTest, BacktraceUtilsTest003, TestSize.Level2)
216 {
217     GTEST_LOG_(INFO) << "BacktraceUtilsTest003: start.";
218     int32_t loopCount = 100;
219     for (int32_t i = 0; i < loopCount; i++) {
220         ASSERT_EQ(TestGetBacktraceInterface(), true);
221     }
222     GTEST_LOG_(INFO) << "BacktraceUtilsTest003: end.";
223 }
224 
DoCheckBacktraceInMultiThread()225 void DoCheckBacktraceInMultiThread()
226 {
227     std::string content;
228     ASSERT_TRUE(GetBacktrace(content));
229     ASSERT_FALSE(content.empty());
230 }
231 
232 /**
233  * @tc.name: BacktraceUtilsTest004
234  * @tc.desc: test get backtrace in multi-thread situation
235  * @tc.type: FUNC
236  */
237 HWTEST_F(BacktraceUtilsTest, BacktraceUtilsTest004, TestSize.Level2)
238 {
239     GTEST_LOG_(INFO) << "BacktraceUtilsTest004: start.";
240     constexpr int32_t threadCount = 50;
241     std::vector<std::thread> threads(threadCount);
242     for (auto it = std::begin(threads); it != std::end(threads); ++it) {
243         *it = std::thread(DoCheckBacktraceInMultiThread);
244     }
245 
246     for (auto&& thread : threads) {
247         thread.join();
248     }
249     GTEST_LOG_(INFO) << "BacktraceUtilsTest004: end.";
250 }
251 
252 /**
253  * @tc.name: BacktraceUtilsTest005
254  * @tc.desc: test PrintTrace to hilog, stdout and file
255  * @tc.type: FUNC
256  */
257 HWTEST_F(BacktraceUtilsTest, BacktraceUtilsTest005, TestSize.Level0)
258 {
259     GTEST_LOG_(INFO) << "BacktraceUtilsTest005: start.";
260     ASSERT_EQ(true, PrintTrace(STDIN_FILENO));
261     ASSERT_EQ(true, PrintTrace(STDOUT_FILENO));
262     ASSERT_EQ(true, PrintTrace(STDERR_FILENO));
263     ASSERT_EQ(true, PrintTrace());
264     int fd = open(TEST_TEMP_FILE, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
265     ASSERT_TRUE(fd >= 0);
266     ASSERT_EQ(true, PrintTrace(fd));
267     close(fd);
268     std::string content;
269     if (!OHOS::HiviewDFX::LoadStringFromFile(TEST_TEMP_FILE, content)) {
270         FAIL();
271     }
272 
273     ASSERT_EQ(CheckBacktraceContent(content), true);
274     GTEST_LOG_(INFO) << "BacktraceUtilsTest005: end.";
275 }
276 } // namespace HiviewDFX
277 } // namepsace OHOS
278