1 /*
2 * Copyright (c) 2022 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 <thread>
20 #include <unistd.h>
21 #include <hilog/log.h>
22 #include <malloc.h>
23 #include <libunwind_i-ohos.h>
24 #include <libunwind.h>
25 #include <securec.h>
26
27 #include "dfx_config.h"
28 #include "elapsed_time.h"
29 #include "dwarf_unwinder.h"
30 #include "fp_unwinder.h"
31
32 using namespace testing;
33 using namespace testing::ext;
34
35 namespace OHOS {
36 namespace HiviewDFX {
37 #undef LOG_DOMAIN
38 #undef LOG_TAG
39 #define LOG_TAG "UnwinderTest"
40 #define LOG_DOMAIN 0xD002D11
41
42 class UnwinderTest : public testing::Test {
43 public:
44 static void SetUpTestCase();
45 static void TearDownTestCase();
46 void SetUp();
47 void TearDown();
48 };
49
SetUpTestCase()50 void UnwinderTest::SetUpTestCase()
51 {
52 }
53
TearDownTestCase()54 void UnwinderTest::TearDownTestCase()
55 {
56 }
57
SetUp()58 void UnwinderTest::SetUp()
59 {
60 }
61
TearDown()62 void UnwinderTest::TearDown()
63 {
64 }
65
66 /**
67 * @tc.name: DfxConfigTest001
68 * @tc.desc: test DfxConfig class functions
69 * @tc.type: FUNC
70 */
71 HWTEST_F(UnwinderTest, DfxConfigTest001, TestSize.Level2)
72 {
73 GTEST_LOG_(INFO) << "DfxConfigTest001: start.";
74 ASSERT_EQ(DfxConfig::GetConfig().logPersist, false);
75 ASSERT_EQ(DfxConfig::GetConfig().displayRegister, true);
76 ASSERT_EQ(DfxConfig::GetConfig().displayBacktrace, true);
77 ASSERT_EQ(DfxConfig::GetConfig().displayMaps, true);
78 ASSERT_EQ(DfxConfig::GetConfig().displayFaultStack, true);
79 ASSERT_EQ(DfxConfig::GetConfig().dumpOtherThreads, false);
80 ASSERT_EQ(DfxConfig::GetConfig().highAddressStep, 512);
81 ASSERT_EQ(DfxConfig::GetConfig().lowAddressStep, 16);
82 ASSERT_EQ(DfxConfig::GetConfig().maxFrameNums, 64);
83 GTEST_LOG_(INFO) << "DfxConfigTest001: end.";
84 }
85
86 /**
87 * @tc.name: UnwinderTest000
88 * @tc.desc: test dwarf unwinder UnwindWithContext
89 * @tc.type: FUNC
90 */
91 HWTEST_F(UnwinderTest, UnwinderTest000, TestSize.Level2)
92 {
93 GTEST_LOG_(INFO) << "UnwinderTest000: start.";
94 ElapsedTime counter;
95 unw_context_t context;
96 (void)memset_s(&context, sizeof(unw_context_t), 0, sizeof(unw_context_t));
97 unw_getcontext(&context);
98 pid_t child = fork();
99 if (child == 0) {
100 unw_addr_space_t as;
101 unw_init_local_address_space(&as);
102 if (as == nullptr) {
103 FAIL() << "Failed to init address space.";
104 return;
105 }
106
107 auto symbol = std::make_shared<DfxSymbols>();
108 ElapsedTime counter2;
109 DwarfUnwinder unwinder;
110 ASSERT_EQ(true, unwinder.UnwindWithContext(as, context, symbol, 0));
111 GTEST_LOG_(INFO) << "ChildProcessElapse:" << counter2.Elapsed();
112 const auto& frames = unwinder.GetFrames();
113 ASSERT_GT(frames.size(), 0);
114 unw_destroy_local_address_space(as);
115 _exit(0);
116 }
117 GTEST_LOG_(INFO) << "CurrentThreadElapse:" << counter.Elapsed();
118
119 int status;
120 int ret = wait(&status);
121 GTEST_LOG_(INFO) << "Status:" << status << " Result:" << ret;
122 GTEST_LOG_(INFO) << "UnwinderTest000: end.";
123 }
124
125 /**
126 * @tc.name: UnwinderTest001
127 * @tc.desc: test fp unwinder UnwindWithContext
128 * @tc.type: FUNC
129 */
130 HWTEST_F(UnwinderTest, UnwinderTest001, TestSize.Level2)
131 {
132 GTEST_LOG_(INFO) << "UnwinderTest001: start.";
133 #ifdef __aarch64__
134 ElapsedTime counter;
135 unw_context_t context;
136 (void)memset_s(&context, sizeof(unw_context_t), 0, sizeof(unw_context_t));
137 unw_getcontext(&context);
138 pid_t child = fork();
139 if (child == 0) {
140 ElapsedTime counter2;
141 FpUnwinder unwinder;
142 ASSERT_EQ(true, unwinder.UnwindWithContext(context, 0));
143 GTEST_LOG_(INFO) << "ChildProcessElapse:" << counter2.Elapsed();
144 const auto& frames = unwinder.GetFrames();
145 ASSERT_GT(frames.size(), 0);
146 _exit(0);
147 }
148 GTEST_LOG_(INFO) << "CurrentThreadElapse:" << counter.Elapsed();
149
150 int status;
151 int ret = wait(&status);
152 GTEST_LOG_(INFO) << "Status:" << status << " Result:" << ret;
153 #endif
154 GTEST_LOG_(INFO) << "UnwinderTest001: end.";
155 }
156
157 /**
158 * @tc.name: UnwinderTest002
159 * @tc.desc: test fp unwinder Unwind
160 * @tc.type: FUNC
161 */
162 HWTEST_F(UnwinderTest, UnwinderTest002, TestSize.Level2)
163 {
164 GTEST_LOG_(INFO) << "UnwinderTest002: start.";
165 #ifdef __aarch64__
166 ElapsedTime counter;
167 pid_t child = fork();
168 if (child == 0) {
169 ElapsedTime counter2;
170 FpUnwinder unwinder;
171 ASSERT_EQ(true, unwinder.Unwind(0));
172 GTEST_LOG_(INFO) << "ChildProcessElapse:" << counter2.Elapsed();
173 const auto& frames = unwinder.GetFrames();
174 ASSERT_GT(frames.size(), 0);
175 _exit(0);
176 }
177 GTEST_LOG_(INFO) << "CurrentThreadElapse:" << counter.Elapsed();
178
179 int status;
180 int ret = wait(&status);
181 GTEST_LOG_(INFO) << "Status:" << status << " Result:" << ret;
182 #endif
183 GTEST_LOG_(INFO) << "UnwinderTest002: end.";
184 }
185
186 /**
187 * @tc.name: UnwinderTest003
188 * @tc.desc: test dwarf unwinder Unwind
189 * @tc.type: FUNC
190 */
191 HWTEST_F(UnwinderTest, UnwinderTest003, TestSize.Level2)
192 {
193 GTEST_LOG_(INFO) << "UnwinderTest003: start.";
194 ElapsedTime counter;
195 pid_t child = fork();
196 if (child == 0) {
197 ElapsedTime counter2;
198 DwarfUnwinder unwinder;
199 ASSERT_EQ(true, unwinder.Unwind(0));
200 GTEST_LOG_(INFO) << "ChildProcessElapse:" << counter2.Elapsed();
201 const auto& frames = unwinder.GetFrames();
202 ASSERT_GT(frames.size(), 0);
203 _exit(0);
204 }
205 GTEST_LOG_(INFO) << "CurrentThreadElapse:" << counter.Elapsed();
206
207 int status;
208 int ret = wait(&status);
209 GTEST_LOG_(INFO) << "Status:" << status << " Result:" << ret;
210 GTEST_LOG_(INFO) << "UnwinderTest003: end.";
211 }
212 } // namespace HiviewDFX
213 } // namepsace OHOS
214