1 /*
2 * Copyright (c) 2022-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 <fstream>
18 #include <map>
19 #include <csignal>
20 #include <string>
21 #include <unistd.h>
22 #include <vector>
23
24 #include "dfx_config.h"
25 #include "dfx_define.h"
26 #include "dfx_test_util.h"
27 #include "dfx_util.h"
28 #include "directory_ex.h"
29 #include "multithread_constructor.h"
30 #include "process_dumper.h"
31
32 using namespace OHOS::HiviewDFX;
33 using namespace testing::ext;
34 using namespace std;
35
36 namespace OHOS {
37 namespace HiviewDFX {
38 class DfxProcessDumpTest : public testing::Test {
39 public:
40 static void SetUpTestCase(void);
41 static void TearDownTestCase(void);
42 void SetUp();
43 void TearDown();
44 };
45 } // namespace HiviewDFX
46 } // namespace OHOS
47
SetUpTestCase(void)48 void DfxProcessDumpTest::SetUpTestCase(void)
49 {
50 }
51
TearDownTestCase(void)52 void DfxProcessDumpTest::TearDownTestCase(void)
53 {
54 }
55
SetUp(void)56 void DfxProcessDumpTest::SetUp(void)
57 {
58 }
59
TearDown(void)60 void DfxProcessDumpTest::TearDown(void)
61 {
62 }
63
CreateMultiThreadProcess(int threadNum)64 static pid_t CreateMultiThreadProcess(int threadNum)
65 {
66 pid_t pid = fork();
67 if (pid < 0) {
68 GTEST_LOG_(ERROR) << "Failed to fork new test process.";
69 } else if (pid == 0) {
70 (void)MultiThreadConstructor(threadNum);
71 }
72 return pid;
73 }
74
CreateMultiThreadForThreadCrash(int threadNum)75 static pid_t CreateMultiThreadForThreadCrash(int threadNum)
76 {
77 pid_t pid = fork();
78 if (pid < 0) {
79 GTEST_LOG_(ERROR) << "Failed to fork new test process.";
80 } else if (pid == 0) {
81 (void)MultiThreadConstructorForThreadCrash(threadNum);
82 }
83 return pid;
84 }
85
CheckCppCrashKeyWords(const string & filePath,pid_t pid,int sig)86 static bool CheckCppCrashKeyWords(const string& filePath, pid_t pid, int sig)
87 {
88 if (filePath.empty() || pid <= 0) {
89 return false;
90 }
91 map<int, string> sigKey = {
92 { SIGILL, string("SIGILL") },
93 { SIGTRAP, string("SIGTRAP") },
94 { SIGABRT, string("SIGABRT") },
95 { SIGBUS, string("SIGBUS") },
96 { SIGFPE, string("SIGFPE") },
97 { SIGSEGV, string("SIGSEGV") },
98 { SIGSTKFLT, string("SIGSTKFLT") },
99 { SIGSYS, string("SIGSYS") },
100 };
101 string sigKeyword = "";
102 map<int, string>::iterator iter = sigKey.find(sig);
103 if (iter != sigKey.end()) {
104 sigKeyword = iter->second;
105 }
106 string keywords[] = {
107 "Pid:" + to_string(pid), "Uid:", "test_processdump", sigKeyword, "Tid:", "#00", "Registers:", REGISTERS,
108 "FaultStack:", "Maps:", "test_processdump"
109 };
110 int length = sizeof(keywords) / sizeof(keywords[0]);
111 int minRegIdx = 6; // 6 : index of REGISTERS
112 int count = CheckKeyWords(filePath, keywords, length, minRegIdx);
113 return count == length;
114 }
115 namespace {
116 /**
117 * @tc.name: DfxProcessDumpTest001
118 * @tc.desc: test SIGILL crash
119 * @tc.type: FUNC
120 */
121 HWTEST_F(DfxProcessDumpTest, DfxProcessDumpTest001, TestSize.Level2)
122 {
123 GTEST_LOG_(INFO) << "DfxProcessDumpTest001: start.";
124 pid_t testProcess = CreateMultiThreadProcess(10); // 10 : create a process with ten threads
125 sleep(1);
126 auto curTime = GetTimeMilliSeconds();
127 kill(testProcess, SIGILL);
128 sleep(3); // 3 : wait 3s to generate cpp crash file
129 auto filename = GetCppCrashFileName(testProcess);
130 ASSERT_EQ(std::to_string(curTime).length(), filename.length() - filename.find_last_of('-') - 1);
131 ASSERT_TRUE(CheckCppCrashKeyWords(filename, testProcess, SIGILL));
132 GTEST_LOG_(INFO) << "DfxProcessDumpTest001: end.";
133 }
134
135 /**
136 * @tc.name: DfxProcessDumpTest002
137 * @tc.desc: test SIGTRAP crash
138 * @tc.type: FUNC
139 */
140 HWTEST_F(DfxProcessDumpTest, DfxProcessDumpTest002, TestSize.Level2)
141 {
142 GTEST_LOG_(INFO) << "DfxProcessDumpTest002: start.";
143 pid_t testProcess = CreateMultiThreadProcess(10); // 10 : create a process with ten threads
144 sleep(1);
145 auto curTime = GetTimeMilliSeconds();
146 kill(testProcess, SIGTRAP);
147 sleep(3); // 3 : wait 3s to generate cpp crash file
148 auto filename = GetCppCrashFileName(testProcess);
149 ASSERT_EQ(std::to_string(curTime).length(), filename.length() - filename.find_last_of('-') - 1);
150 ASSERT_TRUE(CheckCppCrashKeyWords(filename, testProcess, SIGTRAP));
151 GTEST_LOG_(INFO) << "DfxProcessDumpTest002: end.";
152 }
153
154 /**
155 * @tc.name: DfxProcessDumpTest003
156 * @tc.desc: test SIGABRT crash
157 * @tc.type: FUNC
158 */
159 HWTEST_F(DfxProcessDumpTest, DfxProcessDumpTest003, TestSize.Level2)
160 {
161 GTEST_LOG_(INFO) << "DfxProcessDumpTest003: start.";
162 pid_t testProcess = CreateMultiThreadProcess(10); // 10 : create a process with ten threads
163 sleep(1);
164 auto curTime = GetTimeMilliSeconds();
165 kill(testProcess, SIGABRT);
166 sleep(3); // 3 : wait 3s to generate cpp crash file
167 auto filename = GetCppCrashFileName(testProcess);
168 ASSERT_EQ(std::to_string(curTime).length(), filename.length() - filename.find_last_of('-') - 1);
169 ASSERT_TRUE(CheckCppCrashKeyWords(filename, testProcess, SIGABRT));
170 GTEST_LOG_(INFO) << "DfxProcessDumpTest003: end.";
171 }
172
173 /**
174 * @tc.name: DfxProcessDumpTest004
175 * @tc.desc: test SIGBUS crash
176 * @tc.type: FUNC
177 */
178 HWTEST_F(DfxProcessDumpTest, DfxProcessDumpTest004, TestSize.Level2)
179 {
180 GTEST_LOG_(INFO) << "DfxProcessDumpTest004: start.";
181 pid_t testProcess = CreateMultiThreadProcess(10); // 10 : create a process with ten threads
182 sleep(1);
183 auto curTime = GetTimeMilliSeconds();
184 kill(testProcess, SIGBUS);
185 sleep(3); // 3 : wait 3s to generate cpp crash file
186 auto filename = GetCppCrashFileName(testProcess);
187 ASSERT_EQ(std::to_string(curTime).length(), filename.length() - filename.find_last_of('-') - 1);
188 ASSERT_TRUE(CheckCppCrashKeyWords(filename, testProcess, SIGBUS));
189 GTEST_LOG_(INFO) << "DfxProcessDumpTest004: end.";
190 }
191
192 /**
193 * @tc.name: DfxProcessDumpTest005
194 * @tc.desc: test SIGFPE crash
195 * @tc.type: FUNC
196 */
197 HWTEST_F(DfxProcessDumpTest, DfxProcessDumpTest005, TestSize.Level2)
198 {
199 GTEST_LOG_(INFO) << "DfxProcessDumpTest005: start.";
200 pid_t testProcess = CreateMultiThreadProcess(10); // 10 : create a process with ten threads
201 sleep(1);
202 auto curTime = GetTimeMilliSeconds();
203 kill(testProcess, SIGFPE);
204 sleep(3); // 3 : wait 3s to generate cpp crash file
205 auto filename = GetCppCrashFileName(testProcess);
206 ASSERT_EQ(std::to_string(curTime).length(), filename.length() - filename.find_last_of('-') - 1);
207 ASSERT_TRUE(CheckCppCrashKeyWords(filename, testProcess, SIGFPE));
208 GTEST_LOG_(INFO) << "DfxProcessDumpTest005: end.";
209 }
210
211 /**
212 * @tc.name: DfxProcessDumpTest006
213 * @tc.desc: test SIGSEGV crash
214 * @tc.type: FUNC
215 */
216 HWTEST_F(DfxProcessDumpTest, DfxProcessDumpTest006, TestSize.Level2)
217 {
218 GTEST_LOG_(INFO) << "DfxProcessDumpTest006: start.";
219 pid_t testProcess = CreateMultiThreadProcess(10); // 10 : create a process with ten threads
220 GTEST_LOG_(INFO) << "process pid:" << testProcess;
221 sleep(1);
222 auto curTime = GetTimeMilliSeconds();
223 kill(testProcess, SIGSEGV);
224 sleep(3); // 3 : wait 3s to generate cpp crash file
225 auto filename = GetCppCrashFileName(testProcess);
226 ASSERT_EQ(std::to_string(curTime).length(), filename.length() - filename.find_last_of('-') - 1);
227 ASSERT_TRUE(CheckCppCrashKeyWords(filename, testProcess, SIGSEGV));
228 GTEST_LOG_(INFO) << "DfxProcessDumpTest006: end.";
229 }
230
231 /**
232 * @tc.name: DfxProcessDumpTest007
233 * @tc.desc: test SIGSTKFLT crash
234 * @tc.type: FUNC
235 */
236 HWTEST_F(DfxProcessDumpTest, DfxProcessDumpTest007, TestSize.Level2)
237 {
238 GTEST_LOG_(INFO) << "DfxProcessDumpTest007: start.";
239 pid_t testProcess = CreateMultiThreadProcess(10); // 10 : create a process with ten threads
240 sleep(1);
241 auto curTime = GetTimeMilliSeconds();
242 kill(testProcess, SIGSTKFLT);
243 sleep(3); // 3 : wait 3s to generate cpp crash file
244 auto filename = GetCppCrashFileName(testProcess);
245 ASSERT_EQ(std::to_string(curTime).length(), filename.length() - filename.find_last_of('-') - 1);
246 ASSERT_TRUE(CheckCppCrashKeyWords(filename, testProcess, SIGSTKFLT));
247 GTEST_LOG_(INFO) << "DfxProcessDumpTest007: end.";
248 }
249
250 /**
251 * @tc.name: DfxProcessDumpTest008
252 * @tc.desc: test SIGSYS crash
253 * @tc.type: FUNC
254 */
255 HWTEST_F(DfxProcessDumpTest, DfxProcessDumpTest008, TestSize.Level2)
256 {
257 GTEST_LOG_(INFO) << "DfxProcessDumpTest008: start.";
258 pid_t testProcess = CreateMultiThreadProcess(10); // 10 : create a process with ten threads
259 sleep(1);
260 auto curTime = GetTimeMilliSeconds();
261 kill(testProcess, SIGSYS);
262 sleep(3); // 3 : wait 3s to generate cpp crash file
263 auto filename = GetCppCrashFileName(testProcess);
264 ASSERT_EQ(std::to_string(curTime).length(), filename.length() - filename.find_last_of('-') - 1);
265 ASSERT_TRUE(CheckCppCrashKeyWords(filename, testProcess, SIGSYS));
266 GTEST_LOG_(INFO) << "DfxProcessDumpTest008: end.";
267 }
268
269 /**
270 * @tc.name: DfxProcessDumpTest009
271 * @tc.desc: test processdump command
272 * @tc.type: FUNC
273 * @tc.require:
274 */
275 HWTEST_F(DfxProcessDumpTest, DfxProcessDumpTest009, TestSize.Level2)
276 {
277 GTEST_LOG_(INFO) << "DfxProcessDumpTest009: start.";
278 string procCMD = "processdump";
279 string procDumpLog = ExecuteCommands(procCMD);
280 string log[] = {"please use dumpcatcher"};
281 int expectNum = sizeof(log) / sizeof(log[0]);
282 int count = GetKeywordsNum(procDumpLog, log, expectNum);
283 EXPECT_EQ(count, expectNum) << "DfxProcessDumpTest009 Failed";
284 GTEST_LOG_(INFO) << "DfxProcessDumpTest009: end.";
285 }
286
287 /**
288 * @tc.name: DfxProcessDumpTest010
289 * @tc.desc: test processdump command: -p 1
290 * @tc.type: FUNC
291 * @tc.require:
292 */
293 HWTEST_F(DfxProcessDumpTest, DfxProcessDumpTest010, TestSize.Level2)
294 {
295 GTEST_LOG_(INFO) << "DfxProcessDumpTest010: start.";
296 string procCMD = "processdump -p 1";
297 string procDumpLog = ExecuteCommands(procCMD);
298 string log[] = {"please use dumpcatcher"};
299 int expectNum = sizeof(log) / sizeof(log[0]);
300 int count = GetKeywordsNum(procDumpLog, log, expectNum);
301 EXPECT_EQ(count, expectNum) << "DfxProcessDumpTest010 Failed";
302 GTEST_LOG_(INFO) << "DfxProcessDumpTest010: end.";
303 }
304
305 /**
306 * @tc.name: DfxProcessDumpTest011
307 * @tc.desc: Testing the sub thread crash of multithreaded programs
308 * @tc.type: FUNC
309 */
310 HWTEST_F(DfxProcessDumpTest, DfxProcessDumpTest011, TestSize.Level2)
311 {
312 GTEST_LOG_(INFO) << "DfxProcessDumpTest011: start.";
313 pid_t testProcess = CreateMultiThreadForThreadCrash(10); // 10 : create a process with ten threads
314 GTEST_LOG_(INFO) << "process pid:" << testProcess;
315 sleep(3); // 3 : wait 3s to generate cpp crash file
316 auto filename = GetCppCrashFileName(testProcess);
317 ASSERT_TRUE(CheckCppCrashKeyWords(filename, testProcess, SIGSEGV));
318 GTEST_LOG_(INFO) << "DfxProcessDumpTest011: end.";
319 }
320 }