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 #include "dfx_test_util.h"
25
26 using namespace OHOS::HiviewDFX;
27 using namespace testing::ext;
28 using namespace std;
29
30 namespace OHOS {
31 namespace HiviewDFX {
32 class DfxSignalTest : public testing::Test {
33 public:
SetUpTestCase(void)34 static void SetUpTestCase(void) {}
TearDownTestCase(void)35 static void TearDownTestCase(void) {}
SetUp()36 void SetUp() {}
TearDown()37 void TearDown() {}
38 };
39 } // namespace HiviewDFX
40 } // namespace OHOS
41
42 namespace {
43 /**
44 * @tc.name: DfxSignalTest001
45 * @tc.desc: test DfxSignal functions
46 * @tc.type: FUNC
47 */
48 HWTEST_F(DfxSignalTest, DfxSignalTest001, TestSize.Level2)
49 {
50 GTEST_LOG_(INFO) << "DfxSignalTest001: start.";
51 siginfo_t si = {
52 .si_signo = SIGSEGV,
53 .si_errno = 0,
54 .si_code = -1,
55 .si_value.sival_int = static_cast<int>(gettid())
56 };
57 std::map<int, std::string> sigKey = {
58 { SIGILL, string("SIGILL") },
59 { SIGTRAP, string("SIGTRAP") },
60 { SIGABRT, string("SIGABRT") },
61 { SIGBUS, string("SIGBUS") },
62 { SIGFPE, string("SIGFPE") },
63 { SIGSEGV, string("SIGSEGV") },
64 { SIGSTKFLT, string("SIGSTKFLT") },
65 { SIGSYS, string("SIGSYS") },
66 };
67 for (auto sigKey : sigKey) {
68 std::string sigKeyword = "Signal:";
69 si.si_signo = sigKey.first;
70 sigKeyword += sigKey.second;
71 std::string sigStr = DfxSignal::PrintSignal(si) + "\n";
72 GTEST_LOG_(INFO) << sigStr;
73 ASSERT_TRUE(sigStr.find(sigKeyword) != std::string::npos);
74 }
75 GTEST_LOG_(INFO) << "DfxSignalTest001: end.";
76 }
77
78 /**
79 * @tc.name: DfxSignalTest002
80 * @tc.desc: test if signal info is available
81 * @tc.type: FUNC
82 */
83 HWTEST_F(DfxSignalTest, DfxSignalTest002, TestSize.Level2)
84 {
85 GTEST_LOG_(INFO) << "DfxSignalTest002: start.";
86 int32_t input = 1;
87 std::shared_ptr<DfxSignal> signal = std::make_shared<DfxSignal>(input);
88 bool ret = signal->IsAvailable();
89 EXPECT_EQ(true, ret != true) << "DfxSignalTest002 Failed";
90 GTEST_LOG_(INFO) << "DfxSignalTest002: end.";
91 }
92
TestSignalHandler(int sig,siginfo_t * si,void * context)93 static void TestSignalHandler(int sig, siginfo_t * si, void * context)
94 {
95 GTEST_LOG_(INFO) << "Enter TestSignalHandler";
96 }
97
98 /**
99 * @tc.name: DfxSignalTest003
100 * @tc.desc: test if signal info is available in normal status
101 * @tc.type: FUNC
102 */
103 HWTEST_F(DfxSignalTest, DfxSignalTest003, TestSize.Level2)
104 {
105 GTEST_LOG_(INFO) << "DfxSignalTest003: start.";
106 pid_t child = fork();
107 if (child == 0) {
108 int32_t input = SIGINT;
109 struct sigaction action;
110 (void)memset_s(&action, sizeof(action), 0, sizeof(action));
111 action.sa_sigaction = TestSignalHandler;
112 action.sa_flags = SA_SIGINFO;
113 int rc = sigaction(input, &action, nullptr);
114 EXPECT_EQ(rc, 0) << "DfxSignalTest003 Failed, sigaction signal failed";
115
116 std::shared_ptr<DfxSignal> signal = std::make_shared<DfxSignal>(input);
117 bool ret = signal->IsAvailable();
118 EXPECT_EQ(true, ret) << "DfxSignalTest003 Failed";
119 CheckAndExit(HasFailure());
120 }
121 int status;
122 wait(&status);
123 ASSERT_EQ(status, 0);
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 { ILL_ILLPACCFI, string("ILL_ILLPACCFI") },
231 { SI_USER, string("SI_USER") },
232 };
233 std::map<int, std::string> fpeCode = {
234 { FPE_INTDIV, string("FPE_INTDIV") },
235 { FPE_INTOVF, string("FPE_INTOVF") },
236 { FPE_FLTDIV, string("FPE_FLTDIV") },
237 { FPE_FLTOVF, string("FPE_FLTOVF") },
238 { FPE_FLTUND, string("FPE_FLTUND") },
239 { FPE_FLTRES, string("FPE_FLTRES") },
240 { FPE_FLTINV, string("FPE_FLTINV") },
241 { FPE_FLTSUB, string("FPE_FLTSUB") },
242 { SI_USER, string("SI_USER") },
243 };
244 std::map<int, std::string> busCode = {
245 { BUS_ADRALN, string("BUS_ADRALN") },
246 { BUS_ADRERR, string("BUS_ADRERR") },
247 { BUS_OBJERR, string("BUS_OBJERR") },
248 { BUS_MCEERR_AR, string("BUS_MCEERR_AR") },
249 { BUS_MCEERR_AO, string("BUS_MCEERR_AO") },
250 { SI_USER, string("SI_USER") },
251 };
252 /**
253 * @tc.name: DfxSignalTest009
254 * @tc.desc: test DfxSignal functions
255 * @tc.type: FUNC
256 */
257 HWTEST_F(DfxSignalTest, DfxSignalTest009, TestSize.Level2)
258 {
259 GTEST_LOG_(INFO) << "DfxSignalTest009: start.";
260 siginfo_t si = {
261 .si_signo = SIGSEGV,
262 .si_errno = 0,
263 .si_code = -1,
264 .si_value.sival_int = static_cast<int>(gettid())
265 };
266 for (auto sigKey : sigKeys) {
267 si.si_signo = sigKey.first;
268 std::map<int, std::string> codeMap;
269 switch (si.si_signo) {
270 case SIGILL:
271 codeMap = illCode;
272 break;
273 case SIGTRAP:
274 codeMap = trapCode;
275 break;
276 case SIGBUS:
277 codeMap = busCode;
278 break;
279 case SIGFPE:
280 codeMap = fpeCode;
281 break;
282 case SIGSEGV:
283 codeMap = segvCode;
284 break;
285 default:
286 break;
287 }
288 for (auto& code : codeMap) {
289 std::string sigKeyword = "Signal:";
290 sigKeyword += sigKey.second;
291 si.si_code = code.first;
292 sigKeyword = sigKeyword + "(" + code.second + ")";
293 std::string sigStr = DfxSignal::PrintSignal(si) + "\n";
294 GTEST_LOG_(INFO) << sigStr;
295 ASSERT_TRUE(sigStr.find(sigKeyword) != std::string::npos);
296 }
297 }
298 GTEST_LOG_(INFO) << "DfxSignalTest009: end.";
299 }
300 }
301