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