• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <fstream>
19 #include <map>
20 #include <csignal>
21 #include <string>
22 #include <unistd.h>
23 #include <vector>
24 
25 #include "dfx_define.h"
26 #include "dfx_signal_local_handler.h"
27 #include "directory_ex.h"
28 
29 #if defined(__arm__)
30     #define REGISTERS           "r0:","r1:","r2:","r3:","r4:","r5:","r6:",\
31                                 "r7:","r8:","r9:","r10:","fp:","ip:","sp:","lr:","pc:"
32     #define REGISTERS_NUM       16
33     #define REGISTERS_LENGTH    10
34 #elif defined(__aarch64__)
35     #define REGISTERS           "x0:","x1:","x2:","x3:","x4:","x5:","x6:","x7:","x8:",\
36                                 "x9:","x10:","x11:","x12:","x13:","x14:","x15:","x16:",\
37                                 "x17:","x18:","x19:","x20:","x21:","x22:","x23:","x24:",\
38                                 "x25:","x26:","x27:","x28:","x29:","lr:","sp:","pc:"
39     #define REGISTERS_NUM       33
40     #define REGISTERS_LENGTH    18
41 #endif
42 
43 using namespace testing;
44 using namespace testing::ext;
45 using namespace std;
46 
47 namespace OHOS {
48 namespace HiviewDFX {
49 class SignalHandlerTest : public testing::Test {
50 public:
51     static void SetUpTestCase();
52     static void TearDownTestCase();
53     void SetUp();
54     void TearDown();
55 };
56 
SetUpTestCase()57 void SignalHandlerTest::SetUpTestCase()
58 {}
59 
TearDownTestCase()60 void SignalHandlerTest::TearDownTestCase()
61 {}
62 
SetUp()63 void SignalHandlerTest::SetUp()
64 {}
65 
TearDown()66 void SignalHandlerTest::TearDown()
67 {}
68 
CountLines(const string & filename)69 static int CountLines(const string& filename)
70 {
71     ifstream readStream;
72     string tempData;
73     readStream.open(filename.c_str(), ios::in);
74     if (readStream.fail()) {
75         return 0;
76     } else {
77         int n = 0;
78         while (getline(readStream, tempData, '\n')) {
79             n++;
80         }
81         readStream.close();
82         return n;
83     }
84 }
85 
GetCppCrashFileName(pid_t pid)86 static string GetCppCrashFileName(pid_t pid)
87 {
88     if (pid <= 0) {
89         return "";
90     }
91     vector<string> files;
92     OHOS::GetDirFiles("/data/log/faultlog/temp", files);
93     string fileNamePrefix = "cppcrash-" + to_string(pid);
94     for (const auto& file : files) {
95         if (file.find(fileNamePrefix) != string::npos) {
96             return file;
97         }
98     }
99     return "";
100 }
101 
CheckKeyWords(const string & filePath,string * keywords,int length)102 static int CheckKeyWords(const string& filePath, string *keywords, int length)
103 {
104     ifstream file;
105     file.open(filePath.c_str(), ios::in);
106     long lines = CountLines(filePath);
107     vector<string> t(lines * 4); // 4 : max string blocks of one line
108     int i = 0;
109     int j = 0;
110     string::size_type idx;
111     int count = 0;
112     int minRegIdx = 6; // 6 : index of REGISTERS
113     int maxRegIdx = minRegIdx + REGISTERS_NUM + 1;
114     while (!file.eof()) {
115         file >> t.at(i);
116         idx = t.at(i).find(keywords[j]);
117         if (idx != string::npos) {
118             GTEST_LOG_(INFO) << t.at(i);
119             if (j > minRegIdx && j < maxRegIdx && t.at(i).size() < REGISTERS_LENGTH) {
120                 count--;
121             }
122             count++;
123             j++;
124             if (j == length) {
125                 break;
126             }
127             continue;
128         }
129         i++;
130     }
131     file.close();
132     GTEST_LOG_(INFO) << count << " keys matched.";
133     return count;
134 }
135 
CheckLocalCrashKeyWords(const string & filePath,pid_t pid,int sig)136 static bool CheckLocalCrashKeyWords(const string& filePath, pid_t pid, int sig)
137 {
138     if (filePath.empty() || pid <= 0) {
139         return false;
140     }
141     map<int, string> sigKey = {
142         { SIGILL, string("Signal(4)") },
143         { SIGABRT, string("Signal(6)") },
144         { SIGBUS, string("Signal(7)") },
145         { SIGSEGV, string("Signal(11)") },
146     };
147     string sigKeyword = "";
148     map<int, string>::iterator iter = sigKey.find(sig);
149     if (iter != sigKey.end()) {
150         sigKeyword = iter->second;
151     }
152     string keywords[] = {
153         "Pid:" + to_string(pid), "Uid:", "name:./test_signalhandler", sigKeyword, "Tid:", "#00", "test_signalhandler"
154     };
155     int length = sizeof(keywords) / sizeof(keywords[0]);
156     return CheckKeyWords(filePath, keywords, length) == length;
157 }
158 
159 /**
160  * @tc.name: LocalHandlerTest001
161  * @tc.desc: test crashlocalhandler signo(SIGILL)
162  * @tc.type: FUNC
163  */
164 HWTEST_F(SignalHandlerTest, LocalHandlerTest001, TestSize.Level2)
165 {
166     GTEST_LOG_(INFO) << "DfxProcessDumpTest020: start.";
167     pid_t pid = fork();
168     if (pid < 0) {
169         GTEST_LOG_(ERROR) << "Failed to fork new test process.";
170     } else if (pid == 0) {
171         DFX_InstallLocalSignalHandler();
172         sleep(1);
173     } else {
174         usleep(10000); // 10000 : sleep 10ms
175         GTEST_LOG_(INFO) << "process(" << getpid() << ") is ready to kill process(" << pid << ")";
176         kill(pid, SIGILL);
177         sleep(2); // 2 : wait for cppcrash generating
178         bool ret = CheckLocalCrashKeyWords(GetCppCrashFileName(pid), pid, SIGILL);
179         ASSERT_TRUE(ret);
180     }
181     GTEST_LOG_(INFO) << "DfxProcessDumpTest020: end.";
182 }
183 
184 /**
185  * @tc.name: LocalHandlerTest002
186  * @tc.desc: test crashlocalhandler signo(SIGABRT)
187  * @tc.type: FUNC
188  */
189 HWTEST_F(SignalHandlerTest, LocalHandlerTest002, TestSize.Level2)
190 {
191     GTEST_LOG_(INFO) << "LocalHandlerTest002: start.";
192     pid_t pid = fork();
193     if (pid < 0) {
194         GTEST_LOG_(ERROR) << "Failed to fork new test process.";
195     } else if (pid == 0) {
196         DFX_InstallLocalSignalHandler();
197         sleep(1);
198     } else {
199         usleep(10000); // 10000 : sleep 10ms
200         GTEST_LOG_(INFO) << "process(" << getpid() << ") is ready to kill process(" << pid << ")";
201         kill(pid, SIGABRT);
202         sleep(2); // 2 : wait for cppcrash generating
203         bool ret = CheckLocalCrashKeyWords(GetCppCrashFileName(pid), pid, SIGABRT);
204         ASSERT_TRUE(ret);
205     }
206     GTEST_LOG_(INFO) << "LocalHandlerTest002: end.";
207 }
208 
209 /**
210  * @tc.name: LocalHandlerTest003
211  * @tc.desc: test crashlocalhandler signo(SIGBUS)
212  * @tc.type: FUNC
213  */
214 HWTEST_F(SignalHandlerTest, LocalHandlerTest003, TestSize.Level2)
215 {
216     GTEST_LOG_(INFO) << "LocalHandlerTest003: start.";
217     pid_t pid = fork();
218     if (pid < 0) {
219         GTEST_LOG_(ERROR) << "Failed to fork new test process.";
220     } else if (pid == 0) {
221         DFX_InstallLocalSignalHandler();
222         sleep(1);
223     } else {
224         usleep(10000); // 10000 : sleep 10ms
225         GTEST_LOG_(INFO) << "process(" << getpid() << ") is ready to kill process(" << pid << ")";
226         kill(pid, SIGBUS);
227         sleep(2); // 2 : wait for cppcrash generating
228         bool ret = CheckLocalCrashKeyWords(GetCppCrashFileName(pid), pid, SIGBUS);
229         ASSERT_TRUE(ret);
230     }
231     GTEST_LOG_(INFO) << "LocalHandlerTest003: end.";
232 }
233 
234 /**
235  * @tc.name: LocalHandlerTest004
236  * @tc.desc: test crashlocalhandler signo(SIGSEGV)
237  * @tc.type: FUNC
238  */
239 HWTEST_F(SignalHandlerTest, LocalHandlerTest004, TestSize.Level2)
240 {
241     GTEST_LOG_(INFO) << "LocalHandlerTest004: start.";
242     pid_t pid = fork();
243     if (pid < 0) {
244         GTEST_LOG_(ERROR) << "Failed to fork new test process.";
245     } else if (pid == 0) {
246         DFX_InstallLocalSignalHandler();
247         sleep(1);
248     } else {
249         usleep(10000); // 10000 : sleep 10ms
250         GTEST_LOG_(INFO) << "process(" << getpid() << ") is ready to kill process(" << pid << ")";
251         kill(pid, SIGSEGV);
252         sleep(2); // 2 : wait for cppcrash generating
253         bool ret = CheckLocalCrashKeyWords(GetCppCrashFileName(pid), pid, SIGSEGV);
254         ASSERT_TRUE(ret);
255     }
256     GTEST_LOG_(INFO) << "LocalHandlerTest004: end.";
257 }
258 } // namespace HiviewDFX
259 } // namepsace OHOS
260