1800b99b8Sopenharmony_ci/*
2800b99b8Sopenharmony_ci * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3800b99b8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4800b99b8Sopenharmony_ci * you may not use this file except in compliance with the License.
5800b99b8Sopenharmony_ci * You may obtain a copy of the License at
6800b99b8Sopenharmony_ci *
7800b99b8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8800b99b8Sopenharmony_ci *
9800b99b8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10800b99b8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11800b99b8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12800b99b8Sopenharmony_ci * See the License for the specific language governing permissions and
13800b99b8Sopenharmony_ci * limitations under the License.
14800b99b8Sopenharmony_ci */
15800b99b8Sopenharmony_ci
16800b99b8Sopenharmony_ci#include <gtest/gtest.h>
17800b99b8Sopenharmony_ci
18800b99b8Sopenharmony_ci#include <cstdio>
19800b99b8Sopenharmony_ci#include <directory_ex.h>
20800b99b8Sopenharmony_ci#include <fcntl.h>
21800b99b8Sopenharmony_ci#include <malloc.h>
22800b99b8Sopenharmony_ci#include <string_ex.h>
23800b99b8Sopenharmony_ci#include <thread>
24800b99b8Sopenharmony_ci#include <unistd.h>
25800b99b8Sopenharmony_ci
26800b99b8Sopenharmony_ci#include "backtrace_local.h"
27800b99b8Sopenharmony_ci#include "dfx_test_util.h"
28800b99b8Sopenharmony_ci#include "file_util.h"
29800b99b8Sopenharmony_ci
30800b99b8Sopenharmony_ciusing namespace testing;
31800b99b8Sopenharmony_ciusing namespace testing::ext;
32800b99b8Sopenharmony_ci
33800b99b8Sopenharmony_cinamespace OHOS {
34800b99b8Sopenharmony_cinamespace HiviewDFX {
35800b99b8Sopenharmony_ci#undef LOG_DOMAIN
36800b99b8Sopenharmony_ci#undef LOG_TAG
37800b99b8Sopenharmony_ci#define LOG_TAG "DfxBacktraceUtilsTest"
38800b99b8Sopenharmony_ci#define LOG_DOMAIN 0xD002D11
39800b99b8Sopenharmony_ci
40800b99b8Sopenharmony_ci#define TEST_TEMP_FILE "/data/test/testfile"
41800b99b8Sopenharmony_ci/*
42800b99b8Sopenharmony_ciexpected output log should be like this(aarch64):
43800b99b8Sopenharmony_ci    Backtrace: #01 pc 000000000000d2f8 /data/test/backtrace_utils_test
44800b99b8Sopenharmony_ci    Backtrace: #02 pc 000000000000d164 /data/test/backtrace_utils_test
45800b99b8Sopenharmony_ci    Backtrace: #03 pc 000000000000c86c /data/test/backtrace_utils_test
46800b99b8Sopenharmony_ci    Backtrace: #04 pc 0000000000013f88 /data/test/backtrace_utils_test
47800b99b8Sopenharmony_ci    Backtrace: #05 pc 00000000000148a4 /data/test/backtrace_utils_test
48800b99b8Sopenharmony_ci    Backtrace: #06 pc 0000000000015140 /data/test/backtrace_utils_test
49800b99b8Sopenharmony_ci    Backtrace: #07 pc 00000000000242d8 /data/test/backtrace_utils_test
50800b99b8Sopenharmony_ci    Backtrace: #08 pc 0000000000023bd8 /data/test/backtrace_utils_test
51800b99b8Sopenharmony_ci    Backtrace: #09 pc 000000000000df68 /data/test/backtrace_utils_test
52800b99b8Sopenharmony_ci    Backtrace: #10 pc 00000000000dcf74 /system/lib/ld-musl-aarch64.so.1
53800b99b8Sopenharmony_ci    Backtrace: #11 pc 000000000000c614 /data/test/backtrace_utils_test
54800b99b8Sopenharmony_ci*/
55800b99b8Sopenharmony_ci
56800b99b8Sopenharmony_ciclass BacktraceUtilsTest : public testing::Test {
57800b99b8Sopenharmony_cipublic:
58800b99b8Sopenharmony_ci    static void SetUpTestCase();
59800b99b8Sopenharmony_ci    static void TearDownTestCase();
60800b99b8Sopenharmony_ci    void SetUp();
61800b99b8Sopenharmony_ci    void TearDown();
62800b99b8Sopenharmony_ci
63800b99b8Sopenharmony_ci    uint32_t fdCount;
64800b99b8Sopenharmony_ci    uint32_t mapsCount;
65800b99b8Sopenharmony_ci    uint64_t memCount;
66800b99b8Sopenharmony_ci
67800b99b8Sopenharmony_ci    static uint32_t fdCountTotal;
68800b99b8Sopenharmony_ci    static uint32_t mapsCountTotal;
69800b99b8Sopenharmony_ci    static uint64_t memCountTotal;
70800b99b8Sopenharmony_ci};
71800b99b8Sopenharmony_ci
72800b99b8Sopenharmony_ciuint32_t BacktraceUtilsTest::fdCountTotal = 0;
73800b99b8Sopenharmony_ciuint32_t BacktraceUtilsTest::mapsCountTotal = 0;
74800b99b8Sopenharmony_ciuint64_t BacktraceUtilsTest::memCountTotal = 0;
75800b99b8Sopenharmony_ci
76800b99b8Sopenharmony_civoid BacktraceUtilsTest::SetUpTestCase()
77800b99b8Sopenharmony_ci{
78800b99b8Sopenharmony_ci    // get memory/fd/maps
79800b99b8Sopenharmony_ci    BacktraceUtilsTest::fdCountTotal = GetSelfFdCount();
80800b99b8Sopenharmony_ci    BacktraceUtilsTest::mapsCountTotal = GetSelfMapsCount();
81800b99b8Sopenharmony_ci    BacktraceUtilsTest::memCountTotal = GetSelfMemoryCount();
82800b99b8Sopenharmony_ci}
83800b99b8Sopenharmony_ci
84800b99b8Sopenharmony_civoid BacktraceUtilsTest::TearDownTestCase()
85800b99b8Sopenharmony_ci{
86800b99b8Sopenharmony_ci    // check memory/fd/maps
87800b99b8Sopenharmony_ci    CheckResourceUsage(fdCountTotal, mapsCountTotal, memCountTotal);
88800b99b8Sopenharmony_ci}
89800b99b8Sopenharmony_ci
90800b99b8Sopenharmony_civoid BacktraceUtilsTest::SetUp()
91800b99b8Sopenharmony_ci{
92800b99b8Sopenharmony_ci    // get memory/fd/maps
93800b99b8Sopenharmony_ci    fdCount = GetSelfFdCount();
94800b99b8Sopenharmony_ci    mapsCount = GetSelfMapsCount();
95800b99b8Sopenharmony_ci    memCount = GetSelfMemoryCount();
96800b99b8Sopenharmony_ci}
97800b99b8Sopenharmony_ci
98800b99b8Sopenharmony_civoid BacktraceUtilsTest::TearDown()
99800b99b8Sopenharmony_ci{
100800b99b8Sopenharmony_ci#ifdef USE_JEMALLOC_DFX_INTF
101800b99b8Sopenharmony_ci    mallopt(M_FLUSH_THREAD_CACHE, 0);
102800b99b8Sopenharmony_ci#endif
103800b99b8Sopenharmony_ci    // check memory/fd/maps
104800b99b8Sopenharmony_ci    CheckResourceUsage(fdCount, mapsCount, memCount);
105800b99b8Sopenharmony_ci}
106800b99b8Sopenharmony_ci
107800b99b8Sopenharmony_cistatic bool CheckBacktraceContent(const std::string& content, bool fast = false)
108800b99b8Sopenharmony_ci{
109800b99b8Sopenharmony_ci    std::string existKeyWords[] = { "#09", "backtrace_utils_test", "system" };
110800b99b8Sopenharmony_ci    std::string notExistkeyWords[] = {
111800b99b8Sopenharmony_ci#if defined(__aarch64__)
112800b99b8Sopenharmony_ci        "0000000000000000"
113800b99b8Sopenharmony_ci#elif defined(__arm__)
114800b99b8Sopenharmony_ci        "00000000"
115800b99b8Sopenharmony_ci#endif
116800b99b8Sopenharmony_ci    };
117800b99b8Sopenharmony_ci
118800b99b8Sopenharmony_ci    if (!fast) {
119800b99b8Sopenharmony_ci        for (std::string keyWord : existKeyWords) {
120800b99b8Sopenharmony_ci            if (!CheckContent(content, keyWord, true)) {
121800b99b8Sopenharmony_ci                return false;
122800b99b8Sopenharmony_ci            }
123800b99b8Sopenharmony_ci        }
124800b99b8Sopenharmony_ci    }
125800b99b8Sopenharmony_ci    for (std::string keyWord : notExistkeyWords) {
126800b99b8Sopenharmony_ci        if (!CheckContent(content, keyWord, false)) {
127800b99b8Sopenharmony_ci            return false;
128800b99b8Sopenharmony_ci        }
129800b99b8Sopenharmony_ci    }
130800b99b8Sopenharmony_ci    return true;
131800b99b8Sopenharmony_ci}
132800b99b8Sopenharmony_ci
133800b99b8Sopenharmony_cistatic bool TestGetBacktraceInterface()
134800b99b8Sopenharmony_ci{
135800b99b8Sopenharmony_ci    std::string content;
136800b99b8Sopenharmony_ci    if (!GetBacktrace(content)) {
137800b99b8Sopenharmony_ci        return false;
138800b99b8Sopenharmony_ci    }
139800b99b8Sopenharmony_ci
140800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << content;
141800b99b8Sopenharmony_ci    if (content.empty()) {
142800b99b8Sopenharmony_ci        return false;
143800b99b8Sopenharmony_ci    }
144800b99b8Sopenharmony_ci
145800b99b8Sopenharmony_ci    if (!CheckBacktraceContent(content)) {
146800b99b8Sopenharmony_ci        return false;
147800b99b8Sopenharmony_ci    }
148800b99b8Sopenharmony_ci    return true;
149800b99b8Sopenharmony_ci}
150800b99b8Sopenharmony_ci
151800b99b8Sopenharmony_cistatic bool TestGetBacktraceFastInterface()
152800b99b8Sopenharmony_ci{
153800b99b8Sopenharmony_ci#ifdef __aarch64__
154800b99b8Sopenharmony_ci    std::string content;
155800b99b8Sopenharmony_ci    if (!GetBacktrace(content, true)) {
156800b99b8Sopenharmony_ci        return false;
157800b99b8Sopenharmony_ci    }
158800b99b8Sopenharmony_ci
159800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << content;
160800b99b8Sopenharmony_ci    if (content.empty()) {
161800b99b8Sopenharmony_ci        return false;
162800b99b8Sopenharmony_ci    }
163800b99b8Sopenharmony_ci
164800b99b8Sopenharmony_ci    if (!CheckBacktraceContent(content, true)) {
165800b99b8Sopenharmony_ci        return false;
166800b99b8Sopenharmony_ci    }
167800b99b8Sopenharmony_ci#endif
168800b99b8Sopenharmony_ci    return true;
169800b99b8Sopenharmony_ci}
170800b99b8Sopenharmony_ci
171800b99b8Sopenharmony_ci/**
172800b99b8Sopenharmony_ci * @tc.name: BacktraceUtilsTest001
173800b99b8Sopenharmony_ci * @tc.desc: test log backtrace to hilog, stdout and file
174800b99b8Sopenharmony_ci * @tc.type: FUNC
175800b99b8Sopenharmony_ci */
176800b99b8Sopenharmony_ciHWTEST_F(BacktraceUtilsTest, BacktraceUtilsTest001, TestSize.Level2)
177800b99b8Sopenharmony_ci{
178800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "BacktraceUtilsTest001: start.";
179800b99b8Sopenharmony_ci    ASSERT_EQ(true, PrintBacktrace(STDIN_FILENO));
180800b99b8Sopenharmony_ci    ASSERT_EQ(true, PrintBacktrace(STDOUT_FILENO));
181800b99b8Sopenharmony_ci    ASSERT_EQ(true, PrintBacktrace(STDERR_FILENO));
182800b99b8Sopenharmony_ci    ASSERT_EQ(true, PrintBacktrace());
183800b99b8Sopenharmony_ci    int fd = open(TEST_TEMP_FILE, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
184800b99b8Sopenharmony_ci    ASSERT_TRUE(fd >= 0);
185800b99b8Sopenharmony_ci    ASSERT_EQ(true, PrintBacktrace(fd));
186800b99b8Sopenharmony_ci    close(fd);
187800b99b8Sopenharmony_ci    std::string content;
188800b99b8Sopenharmony_ci    if (!OHOS::HiviewDFX::LoadStringFromFile(TEST_TEMP_FILE, content)) {
189800b99b8Sopenharmony_ci        FAIL();
190800b99b8Sopenharmony_ci    }
191800b99b8Sopenharmony_ci    ASSERT_EQ(CheckBacktraceContent(content), true);
192800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "BacktraceUtilsTest001: end.";
193800b99b8Sopenharmony_ci}
194800b99b8Sopenharmony_ci
195800b99b8Sopenharmony_ci/**
196800b99b8Sopenharmony_ci * @tc.name: BacktraceUtilsTest002
197800b99b8Sopenharmony_ci * @tc.desc: test get backtrace
198800b99b8Sopenharmony_ci * @tc.type: FUNC
199800b99b8Sopenharmony_ci */
200800b99b8Sopenharmony_ciHWTEST_F(BacktraceUtilsTest, BacktraceUtilsTest002, TestSize.Level2)
201800b99b8Sopenharmony_ci{
202800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "BacktraceUtilsTest002: start.";
203800b99b8Sopenharmony_ci    ASSERT_EQ(TestGetBacktraceInterface(), true);
204800b99b8Sopenharmony_ci    ASSERT_EQ(TestGetBacktraceFastInterface(), true);
205800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "BacktraceUtilsTest002: end.";
206800b99b8Sopenharmony_ci}
207800b99b8Sopenharmony_ci
208800b99b8Sopenharmony_ci/**
209800b99b8Sopenharmony_ci * @tc.name: BacktraceUtilsTest003
210800b99b8Sopenharmony_ci * @tc.desc: test get backtrace 100 times
211800b99b8Sopenharmony_ci * @tc.type: FUNC
212800b99b8Sopenharmony_ci */
213800b99b8Sopenharmony_ciHWTEST_F(BacktraceUtilsTest, BacktraceUtilsTest003, TestSize.Level2)
214800b99b8Sopenharmony_ci{
215800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "BacktraceUtilsTest003: start.";
216800b99b8Sopenharmony_ci    int32_t loopCount = 100;
217800b99b8Sopenharmony_ci    for (int32_t i = 0; i < loopCount; i++) {
218800b99b8Sopenharmony_ci        ASSERT_EQ(TestGetBacktraceInterface(), true);
219800b99b8Sopenharmony_ci    }
220800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "BacktraceUtilsTest003: end.";
221800b99b8Sopenharmony_ci}
222800b99b8Sopenharmony_ci
223800b99b8Sopenharmony_civoid DoCheckBacktraceInMultiThread()
224800b99b8Sopenharmony_ci{
225800b99b8Sopenharmony_ci    std::string content;
226800b99b8Sopenharmony_ci    ASSERT_TRUE(GetBacktrace(content));
227800b99b8Sopenharmony_ci    ASSERT_FALSE(content.empty());
228800b99b8Sopenharmony_ci}
229800b99b8Sopenharmony_ci
230800b99b8Sopenharmony_ci/**
231800b99b8Sopenharmony_ci * @tc.name: BacktraceUtilsTest004
232800b99b8Sopenharmony_ci * @tc.desc: test get backtrace in multi-thread situation
233800b99b8Sopenharmony_ci * @tc.type: FUNC
234800b99b8Sopenharmony_ci */
235800b99b8Sopenharmony_ciHWTEST_F(BacktraceUtilsTest, BacktraceUtilsTest004, TestSize.Level2)
236800b99b8Sopenharmony_ci{
237800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "BacktraceUtilsTest004: start.";
238800b99b8Sopenharmony_ci    constexpr int32_t threadCount = 50;
239800b99b8Sopenharmony_ci    std::vector<std::thread> threads(threadCount);
240800b99b8Sopenharmony_ci    for (auto it = std::begin(threads); it != std::end(threads); ++it) {
241800b99b8Sopenharmony_ci        *it = std::thread(DoCheckBacktraceInMultiThread);
242800b99b8Sopenharmony_ci    }
243800b99b8Sopenharmony_ci
244800b99b8Sopenharmony_ci    for (auto&& thread : threads) {
245800b99b8Sopenharmony_ci        thread.join();
246800b99b8Sopenharmony_ci    }
247800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "BacktraceUtilsTest004: end.";
248800b99b8Sopenharmony_ci}
249800b99b8Sopenharmony_ci
250800b99b8Sopenharmony_ci/**
251800b99b8Sopenharmony_ci * @tc.name: BacktraceUtilsTest005
252800b99b8Sopenharmony_ci * @tc.desc: test PrintTrace to hilog, stdout and file
253800b99b8Sopenharmony_ci * @tc.type: FUNC
254800b99b8Sopenharmony_ci */
255800b99b8Sopenharmony_ciHWTEST_F(BacktraceUtilsTest, BacktraceUtilsTest005, TestSize.Level2)
256800b99b8Sopenharmony_ci{
257800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "BacktraceUtilsTest005: start.";
258800b99b8Sopenharmony_ci    ASSERT_EQ(true, PrintTrace(STDIN_FILENO));
259800b99b8Sopenharmony_ci    ASSERT_EQ(true, PrintTrace(STDOUT_FILENO));
260800b99b8Sopenharmony_ci    ASSERT_EQ(true, PrintTrace(STDERR_FILENO));
261800b99b8Sopenharmony_ci    ASSERT_EQ(true, PrintTrace());
262800b99b8Sopenharmony_ci    int fd = open(TEST_TEMP_FILE, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
263800b99b8Sopenharmony_ci    ASSERT_TRUE(fd >= 0);
264800b99b8Sopenharmony_ci    ASSERT_EQ(true, PrintTrace(fd));
265800b99b8Sopenharmony_ci    close(fd);
266800b99b8Sopenharmony_ci    std::string content;
267800b99b8Sopenharmony_ci    if (!OHOS::HiviewDFX::LoadStringFromFile(TEST_TEMP_FILE, content)) {
268800b99b8Sopenharmony_ci        FAIL();
269800b99b8Sopenharmony_ci    }
270800b99b8Sopenharmony_ci
271800b99b8Sopenharmony_ci    ASSERT_EQ(CheckBacktraceContent(content), true);
272800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "BacktraceUtilsTest005: end.";
273800b99b8Sopenharmony_ci}
274800b99b8Sopenharmony_ci} // namespace HiviewDFX
275800b99b8Sopenharmony_ci} // namepsace OHOS
276