1 /*
2 * Copyright (c) 2023 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 #include <map>
18 #include <memory>
19 #include <securec.h>
20 #include <csignal>
21 #include <string>
22
23 #include "dfx_signal.h"
24
25 using namespace OHOS::HiviewDFX;
26 using namespace testing::ext;
27 using namespace std;
28
29 namespace OHOS {
30 namespace HiviewDFX {
31 class DfxSignalTest : public testing::Test {
32 public:
SetUpTestCase(void)33 static void SetUpTestCase(void) {}
TearDownTestCase(void)34 static void TearDownTestCase(void) {}
SetUp()35 void SetUp() {}
TearDown()36 void TearDown() {}
37 };
38 } // namespace HiviewDFX
39 } // namespace OHOS
40
41 namespace {
42 /**
43 * @tc.name: DfxSignalTest001
44 * @tc.desc: test DfxSignal functions
45 * @tc.type: FUNC
46 */
47 HWTEST_F(DfxSignalTest, DfxSignalTest001, TestSize.Level2)
48 {
49 GTEST_LOG_(INFO) << "DfxSignalTest001: start.";
50 siginfo_t si = {
51 .si_signo = SIGSEGV,
52 .si_errno = 0,
53 .si_code = -1,
54 .si_value.sival_int = static_cast<int>(gettid())
55 };
56 std::map<int, std::string> sigKey = {
57 { SIGILL, string("SIGILL") },
58 { SIGTRAP, string("SIGTRAP") },
59 { SIGABRT, string("SIGABRT") },
60 { SIGBUS, string("SIGBUS") },
61 { SIGFPE, string("SIGFPE") },
62 { SIGSEGV, string("SIGSEGV") },
63 { SIGSTKFLT, string("SIGSTKFLT") },
64 { SIGSYS, string("SIGSYS") },
65 };
66 for (auto sigKey : sigKey) {
67 std::string sigKeyword = "Signal:";
68 si.si_signo = sigKey.first;
69 sigKeyword += sigKey.second;
70 std::string sigStr = DfxSignal::PrintSignal(si) + "\n";
71 GTEST_LOG_(INFO) << sigStr;
72 ASSERT_TRUE(sigStr.find(sigKeyword) != std::string::npos);
73 }
74 GTEST_LOG_(INFO) << "DfxSignalTest001: end.";
75 }
76
77 /**
78 * @tc.name: DfxSignalTest002
79 * @tc.desc: test if signal info is available
80 * @tc.type: FUNC
81 */
82 HWTEST_F(DfxSignalTest, DfxSignalTest002, TestSize.Level2)
83 {
84 GTEST_LOG_(INFO) << "DfxSignalTest002: start.";
85 int32_t input = 1;
86 std::shared_ptr<DfxSignal> signal = std::make_shared<DfxSignal>(input);
87 bool ret = signal->IsAvailable();
88 EXPECT_EQ(true, ret != true) << "DfxSignalTest002 Failed";
89 GTEST_LOG_(INFO) << "DfxSignalTest002: end.";
90 }
91
TestSignalHandler(int sig,siginfo_t * si,void * context)92 static void TestSignalHandler(int sig, siginfo_t * si, void * context)
93 {
94 GTEST_LOG_(INFO) << "Enter TestSignalHandler";
95 }
96
97 /**
98 * @tc.name: DfxSignalTest003
99 * @tc.desc: test if signal info is available in normal status
100 * @tc.type: FUNC
101 */
102 HWTEST_F(DfxSignalTest, DfxSignalTest003, TestSize.Level2)
103 {
104 GTEST_LOG_(INFO) << "DfxSignalTest003: start.";
105 pid_t child = fork();
106 if (child == 0) {
107 int32_t input = SIGINT;
108 struct sigaction action;
109 (void)memset_s(&action, sizeof(action), 0, sizeof(action));
110 action.sa_sigaction = TestSignalHandler;
111 action.sa_flags = SA_SIGINFO;
112 int rc = sigaction(input, &action, nullptr);
113 ASSERT_EQ(rc, 0) << "DfxSignalTest003 Failed, sigaction signal failed";
114
115 std::shared_ptr<DfxSignal> signal = std::make_shared<DfxSignal>(input);
116 bool ret = signal->IsAvailable();
117 ASSERT_EQ(true, ret) << "DfxSignalTest003 Failed";
118 _exit(0);
119 }
120 int status;
121 int ret = wait(&status);
122 ASSERT_EQ(status, 0);
123 GTEST_LOG_(INFO) << "Status:" << status << " Result:" << ret;
124 GTEST_LOG_(INFO) << "DfxSignalTest003: end.";
125 }
126
127 /**
128 * @tc.name: DfxSignalTest004
129 * @tc.desc: test if addr is available
130 * @tc.type: FUNC
131 */
132 HWTEST_F(DfxSignalTest, DfxSignalTest004, TestSize.Level2)
133 {
134 GTEST_LOG_(INFO) << "DfxSignalTest004: start.";
135 int32_t input = -100; // -100 is an unexpected signal
136 std::shared_ptr<DfxSignal> signal = std::make_shared<DfxSignal>(input);
137 bool ret = signal->IsAddrAvailable();
138 EXPECT_EQ(true, ret != true) << "DfxSignalTest004 Failed";
139 GTEST_LOG_(INFO) << "DfxSignalTest004: end.";
140 }
141
142 /**
143 * @tc.name: DfxSignalTest005
144 * @tc.desc: test if addr is available in normal status
145 * @tc.type: FUNC
146 */
147 HWTEST_F(DfxSignalTest, DfxSignalTest005, TestSize.Level2)
148 {
149 GTEST_LOG_(INFO) << "DfxSignalTest005: start.";
150 int32_t input = SIGSEGV;
151 std::shared_ptr<DfxSignal> signal = std::make_shared<DfxSignal>(input);
152 bool ret = signal->IsAddrAvailable();
153 EXPECT_EQ(true, ret) << "DfxSignalTest005 Failed";
154 GTEST_LOG_(INFO) << "DfxSignalTest005: end.";
155 }
156
157 /**
158 * @tc.name: DfxSignalTest006
159 * @tc.desc: test if pid is available
160 * @tc.type: FUNC
161 */
162 HWTEST_F(DfxSignalTest, DfxSignalTest006, TestSize.Level2)
163 {
164 int32_t input = 100; // 100 is an unexpected signal
165 GTEST_LOG_(INFO) << "DfxSignalTest006: start.";
166 std::shared_ptr<DfxSignal> signal = std::make_shared<DfxSignal>(input);
167 bool ret = signal->IsPidAvailable();
168 EXPECT_EQ(true, ret != true) << "DfxSignalTest006 Failed";
169 GTEST_LOG_(INFO) << "DfxSignalTest006: end.";
170 }
171
172 /**
173 * @tc.name: DfxSignalTest007
174 * @tc.desc: test if pid is available in normal status
175 * @tc.type: FUNC
176 */
177 HWTEST_F(DfxSignalTest, DfxSignalTest007, TestSize.Level2)
178 {
179 int32_t input = SI_USER;
180 GTEST_LOG_(INFO) << "DfxSignalTest007: start.";
181 std::shared_ptr<DfxSignal> signal = std::make_shared<DfxSignal>(input);
182 bool ret = signal->IsPidAvailable();
183 EXPECT_EQ(true, ret) << "DfxSignalTest007 Failed";
184 GTEST_LOG_(INFO) << "DfxSignalTest007: end.";
185 }
186
187 /**
188 * @tc.name: DfxSignalTest008
189 * @tc.desc: test if GetSignal
190 * @tc.type: FUNC
191 */
192 HWTEST_F(DfxSignalTest, DfxSignalTest008, TestSize.Level2)
193 {
194 GTEST_LOG_(INFO) << "DfxSignalTest008: start.";
195 int32_t input = 1;
196 std::shared_ptr<DfxSignal> signal = std::make_shared<DfxSignal>(input);
197 int32_t output = signal->GetSignal();
198 EXPECT_EQ(true, output == input) << "DfxSignalTest008 Failed";
199 GTEST_LOG_(INFO) << "DfxSignalTest008: end.";
200 }
201
202 std::map<int32_t, std::string> sigKeys = {
203 { SIGILL, std::string("SIGILL") },
204 { SIGTRAP, std::string("SIGTRAP") },
205 { SIGBUS, std::string("SIGBUS") },
206 { SIGFPE, std::string("SIGFPE") },
207 { SIGSEGV, std::string("SIGSEGV") },
208 };
209 std::map<int, std::string> segvCode = {
210 { SEGV_MAPERR, string("SEGV_MAPERR") },
211 { SEGV_ACCERR, string("SEGV_ACCERR") },
212 { SI_USER, string("SI_USER") },
213 };
214 std::map<int, std::string> trapCode = {
215 { TRAP_BRKPT, string("TRAP_BRKPT") },
216 { TRAP_TRACE, string("TRAP_TRACE") },
217 { TRAP_BRANCH, string("TRAP_BRANCH") },
218 { TRAP_HWBKPT, string("TRAP_HWBKPT") },
219 { SI_USER, string("SI_USER") },
220 };
221 std::map<int, std::string> illCode = {
222 { ILL_ILLOPC, string("ILL_ILLOPC") },
223 { ILL_ILLOPN, string("ILL_ILLOPN") },
224 { ILL_ILLADR, string("ILL_ILLADR") },
225 { ILL_ILLTRP, string("ILL_ILLTRP") },
226 { ILL_PRVOPC, string("ILL_PRVOPC") },
227 { ILL_PRVREG, string("ILL_PRVREG") },
228 { ILL_COPROC, string("ILL_COPROC") },
229 { ILL_BADSTK, string("ILL_BADSTK") },
230 { SI_USER, string("SI_USER") },
231 };
232 std::map<int, std::string> fpeCode = {
233 { FPE_INTDIV, string("FPE_INTDIV") },
234 { FPE_INTOVF, string("FPE_INTOVF") },
235 { FPE_FLTDIV, string("FPE_FLTDIV") },
236 { FPE_FLTOVF, string("FPE_FLTOVF") },
237 { FPE_FLTUND, string("FPE_FLTUND") },
238 { FPE_FLTRES, string("FPE_FLTRES") },
239 { FPE_FLTINV, string("FPE_FLTINV") },
240 { FPE_FLTSUB, string("FPE_FLTSUB") },
241 { SI_USER, string("SI_USER") },
242 };
243 std::map<int, std::string> busCode = {
244 { BUS_ADRALN, string("BUS_ADRALN") },
245 { BUS_ADRERR, string("BUS_ADRERR") },
246 { BUS_OBJERR, string("BUS_OBJERR") },
247 { BUS_MCEERR_AR, string("BUS_MCEERR_AR") },
248 { BUS_MCEERR_AO, string("BUS_MCEERR_AO") },
249 { SI_USER, string("SI_USER") },
250 };
251 /**
252 * @tc.name: DfxSignalTest009
253 * @tc.desc: test DfxSignal functions
254 * @tc.type: FUNC
255 */
256 HWTEST_F(DfxSignalTest, DfxSignalTest009, TestSize.Level2)
257 {
258 GTEST_LOG_(INFO) << "DfxSignalTest009: start.";
259 siginfo_t si = {
260 .si_signo = SIGSEGV,
261 .si_errno = 0,
262 .si_code = -1,
263 .si_value.sival_int = static_cast<int>(gettid())
264 };
265 for (auto sigKey : sigKeys) {
266 si.si_signo = sigKey.first;
267 std::map<int, std::string> codeMap;
268 switch (si.si_signo) {
269 case SIGILL:
270 codeMap = illCode;
271 break;
272 case SIGTRAP:
273 codeMap = trapCode;
274 break;
275 case SIGBUS:
276 codeMap = busCode;
277 break;
278 case SIGFPE:
279 codeMap = fpeCode;
280 break;
281 case SIGSEGV:
282 codeMap = segvCode;
283 break;
284 default:
285 break;
286 }
287 for (auto& code : codeMap) {
288 std::string sigKeyword = "Signal:";
289 sigKeyword += sigKey.second;
290 si.si_code = code.first;
291 sigKeyword = sigKeyword + "(" + code.second + ")";
292 std::string sigStr = DfxSignal::PrintSignal(si) + "\n";
293 GTEST_LOG_(INFO) << sigStr;
294 ASSERT_TRUE(sigStr.find(sigKeyword) != std::string::npos);
295 }
296 }
297 GTEST_LOG_(INFO) << "DfxSignalTest009: end.";
298 }
299 }
300