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[] = { "#09", "backtrace_utils_test", "system" };
110 std::string notExistkeyWords[] = {
111 #if defined(__aarch64__)
112 "0000000000000000"
113 #elif defined(__arm__)
114 "00000000"
115 #endif
116 };
117
118 if (!fast) {
119 for (std::string keyWord : existKeyWords) {
120 if (!CheckContent(content, keyWord, true)) {
121 return false;
122 }
123 }
124 }
125 for (std::string keyWord : notExistkeyWords) {
126 if (!CheckContent(content, keyWord, false)) {
127 return false;
128 }
129 }
130 return true;
131 }
132
TestGetBacktraceInterface()133 static bool TestGetBacktraceInterface()
134 {
135 std::string content;
136 if (!GetBacktrace(content)) {
137 return false;
138 }
139
140 GTEST_LOG_(INFO) << content;
141 if (content.empty()) {
142 return false;
143 }
144
145 if (!CheckBacktraceContent(content)) {
146 return false;
147 }
148 return true;
149 }
150
TestGetBacktraceFastInterface()151 static bool TestGetBacktraceFastInterface()
152 {
153 #ifdef __aarch64__
154 std::string content;
155 if (!GetBacktrace(content, true)) {
156 return false;
157 }
158
159 GTEST_LOG_(INFO) << content;
160 if (content.empty()) {
161 return false;
162 }
163
164 if (!CheckBacktraceContent(content, true)) {
165 return false;
166 }
167 #endif
168 return true;
169 }
170
171 /**
172 * @tc.name: BacktraceUtilsTest001
173 * @tc.desc: test log backtrace to hilog, stdout and file
174 * @tc.type: FUNC
175 */
176 HWTEST_F(BacktraceUtilsTest, BacktraceUtilsTest001, TestSize.Level2)
177 {
178 GTEST_LOG_(INFO) << "BacktraceUtilsTest001: start.";
179 ASSERT_EQ(true, PrintBacktrace(STDIN_FILENO));
180 ASSERT_EQ(true, PrintBacktrace(STDOUT_FILENO));
181 ASSERT_EQ(true, PrintBacktrace(STDERR_FILENO));
182 ASSERT_EQ(true, PrintBacktrace());
183 int fd = open(TEST_TEMP_FILE, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
184 if (fd < 0) {
185 FAIL();
186 return;
187 }
188 ASSERT_EQ(true, PrintBacktrace(fd));
189 close(fd);
190 std::string content;
191 if (!OHOS::HiviewDFX::LoadStringFromFile(TEST_TEMP_FILE, content)) {
192 FAIL();
193 }
194
195 ASSERT_EQ(CheckBacktraceContent(content), true);
196 GTEST_LOG_(INFO) << "BacktraceUtilsTest001: end.";
197 }
198
199 /**
200 * @tc.name: BacktraceUtilsTest002
201 * @tc.desc: test get backtrace
202 * @tc.type: FUNC
203 */
204 HWTEST_F(BacktraceUtilsTest, BacktraceUtilsTest002, TestSize.Level2)
205 {
206 GTEST_LOG_(INFO) << "BacktraceUtilsTest002: start.";
207 ASSERT_EQ(TestGetBacktraceInterface(), true);
208 ASSERT_EQ(TestGetBacktraceFastInterface(), true);
209 GTEST_LOG_(INFO) << "BacktraceUtilsTest002: end.";
210 }
211
212 /**
213 * @tc.name: BacktraceUtilsTest003
214 * @tc.desc: test get backtrace 100 times
215 * @tc.type: FUNC
216 */
217 HWTEST_F(BacktraceUtilsTest, BacktraceUtilsTest003, TestSize.Level2)
218 {
219 GTEST_LOG_(INFO) << "BacktraceUtilsTest003: start.";
220 int32_t loopCount = 100;
221 for (int32_t i = 0; i < loopCount; i++) {
222 ASSERT_EQ(TestGetBacktraceInterface(), true);
223 }
224 GTEST_LOG_(INFO) << "BacktraceUtilsTest003: end.";
225 }
226
DoCheckBacktraceInMultiThread()227 void DoCheckBacktraceInMultiThread()
228 {
229 std::string content;
230 ASSERT_TRUE(GetBacktrace(content));
231 ASSERT_FALSE(content.empty());
232 }
233
234 /**
235 * @tc.name: BacktraceUtilsTest004
236 * @tc.desc: test get backtrace in multi-thread situation
237 * @tc.type: FUNC
238 */
239 HWTEST_F(BacktraceUtilsTest, BacktraceUtilsTest004, TestSize.Level2)
240 {
241 GTEST_LOG_(INFO) << "BacktraceUtilsTest004: start.";
242 constexpr int32_t threadCount = 50;
243 std::vector<std::thread> threads(threadCount);
244 for (auto it = std::begin(threads); it != std::end(threads); ++it) {
245 *it = std::thread(DoCheckBacktraceInMultiThread);
246 }
247
248 for (auto&& thread : threads) {
249 thread.join();
250 }
251 GTEST_LOG_(INFO) << "BacktraceUtilsTest004: end.";
252 }
253
254 /**
255 * @tc.name: BacktraceUtilsTest005
256 * @tc.desc: test PrintTrace to hilog, stdout and file
257 * @tc.type: FUNC
258 */
259 HWTEST_F(BacktraceUtilsTest, BacktraceUtilsTest005, TestSize.Level2)
260 {
261 GTEST_LOG_(INFO) << "BacktraceUtilsTest005: start.";
262 ASSERT_EQ(true, PrintTrace(STDIN_FILENO));
263 ASSERT_EQ(true, PrintTrace(STDOUT_FILENO));
264 ASSERT_EQ(true, PrintTrace(STDERR_FILENO));
265 ASSERT_EQ(true, PrintTrace());
266 int fd = open(TEST_TEMP_FILE, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
267 if (fd < 0) {
268 FAIL();
269 return;
270 }
271 ASSERT_EQ(true, PrintTrace(fd));
272 close(fd);
273 std::string content;
274 if (!OHOS::HiviewDFX::LoadStringFromFile(TEST_TEMP_FILE, content)) {
275 FAIL();
276 }
277
278 ASSERT_EQ(CheckBacktraceContent(content), true);
279 GTEST_LOG_(INFO) << "BacktraceUtilsTest005: end.";
280 }
281 } // namespace HiviewDFX
282 } // namepsace OHOS
283