• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }