1 /*
2 * Copyright (c) 2021 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 /* This files contains faultlog performance st test case. */
17
18 #include "faultloggerd_performance_test.h"
19
20 #include <cerrno>
21 #include <cstdio>
22 #include <cstring>
23 #include <ctime>
24 #include <dirent.h>
25 #include <fcntl.h>
26 #include <fstream>
27 #include <iostream>
28 #include <memory>
29 #include <pthread.h>
30 #include <securec.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <string>
34 #include <sys/stat.h>
35 #include <sys/time.h>
36 #include <sys/types.h>
37 #include <sys/wait.h>
38 #include <time.h>
39 #include <unistd.h>
40 #include <vector>
41 #include "dfx_define.h"
42 #include "dfx_dump_catcher.h"
43 #include "directory_ex.h"
44 #include "file_ex.h"
45 #include "syscall.h"
46
47
48 using namespace OHOS::HiviewDFX;
49 using namespace testing::ext;
50 using namespace std;
51
52 namespace {
53 static const int PERFORMANCE_TEST_NUMBER_ONE_HUNDRED = 100;
54 static const double PERFORMANCE_TEST_MAX_UNWIND_TIME_S = 0.03;
55 static const double PERFORMANCE_TEST_MAX_UNWIND_TIME_NEW_S = 0.04;
56
GetStartTime()57 clock_t GetStartTime ()
58 {
59 return clock();
60 }
61
GetStopTime(clock_t befor)62 double GetStopTime(clock_t befor)
63 {
64 clock_t StartTimer = clock();
65 return ((StartTimer - befor) / double(CLOCKS_PER_SEC));
66 }
67 }
68
SetUpTestCase(void)69 void FaultPerformanceTest::SetUpTestCase(void)
70 {
71 }
72
TearDownTestCase(void)73 void FaultPerformanceTest::TearDownTestCase(void)
74 {
75 }
76
SetUp(void)77 void FaultPerformanceTest::SetUp(void)
78 {
79 GTEST_LOG_(INFO) << "SetUp";
80 FaultPerformanceTest::StartRootCrasherLoop();
81 }
82
TearDown(void)83 void FaultPerformanceTest::TearDown(void)
84 {
85 GTEST_LOG_(INFO) << "TearDown";
86 FaultPerformanceTest::KillCrasherLoopForSomeCase();
87 }
88
89 int FaultPerformanceTest::looprootPid = 0;
ProcessDumpCommands(const std::string cmds)90 std::string FaultPerformanceTest::ProcessDumpCommands(const std::string cmds)
91 {
92 GTEST_LOG_(INFO) << "threadCMD = " << cmds;
93 FILE *procFileInfo = nullptr;
94 std::string cmdLog;
95 procFileInfo = popen(cmds.c_str(), "r");
96 if (procFileInfo == nullptr) {
97 perror("popen execute failed");
98 exit(1);
99 }
100 char result_buf_shell[NAME_LEN] = {'\0'};
101 while (fgets(result_buf_shell, sizeof(result_buf_shell), procFileInfo) != nullptr) {
102 cmdLog = cmdLog + result_buf_shell;
103 }
104 pclose(procFileInfo);
105 return cmdLog;
106 }
107
ForkAndRootCommands(const std::vector<std::string> & cmds)108 std::string FaultPerformanceTest::ForkAndRootCommands(const std::vector<std::string>& cmds)
109 {
110 int rootuid = 0;
111 setuid(rootuid);
112 system("/data/crasher_c thread-Loop &");
113 std::string procCMD = "pgrep 'crasher'";
114 GTEST_LOG_(INFO) << "threadCMD = " << procCMD;
115 FILE *procFileInfo = nullptr;
116 procFileInfo = popen(procCMD.c_str(), "r");
117 if (procFileInfo == nullptr) {
118 perror("popen execute failed");
119 exit(1);
120 }
121 std::string pidLog;
122 char result_buf_shell[NAME_LEN] = { 0, };
123 if (fgets(result_buf_shell, sizeof(result_buf_shell), procFileInfo) != nullptr) {
124 pidLog = result_buf_shell;
125 looprootPid = atoi(pidLog.c_str());
126 }
127 pclose(procFileInfo);
128 return std::to_string(looprootPid);
129 }
130
StartRootCrasherLoop()131 void FaultPerformanceTest::StartRootCrasherLoop()
132 {
133 int rootuid = 0;
134 setuid(rootuid);
135 std::vector<std::string> cmds { "crasher", "thread-Loop" };
136 FaultPerformanceTest::ForkAndRootCommands(cmds);
137 if (looprootPid == 0) {
138 exit(0);
139 }
140 }
141
KillCrasherLoopForSomeCase()142 void FaultPerformanceTest::KillCrasherLoopForSomeCase()
143 {
144 int rootuid = 0;
145 setuid(rootuid);
146 system(("kill -9 " + std::to_string(FaultPerformanceTest::looprootPid)).c_str());
147 }
148
getApplyPid(std::string applyName)149 int FaultPerformanceTest::getApplyPid(std::string applyName)
150 {
151 std::string procCMD = "pgrep '" + applyName + "'";
152 GTEST_LOG_(INFO) << "threadCMD = " << procCMD;
153 FILE *procFileInfo = nullptr;
154 procFileInfo = popen(procCMD.c_str(), "r");
155 if (procFileInfo == nullptr) {
156 perror("popen execute failed");
157 exit(1);
158 }
159 std::string applyPid;
160 char result_buf_shell[100] = { 0, };
161 while (fgets(result_buf_shell, sizeof(result_buf_shell), procFileInfo) != nullptr) {
162 applyPid = result_buf_shell;
163 GTEST_LOG_(INFO) << "applyPid: " << applyPid;
164 }
165 pclose(procFileInfo);
166 GTEST_LOG_(INFO) << applyPid;
167 int intApplyPid = std::atoi(applyPid.c_str());
168 return intApplyPid;
169 }
170
171 namespace {
172 /**
173 * @tc.name: FaultPerformanceTest001
174 * @tc.desc: test DumpCatch API: PID(root), TID(root)
175 * @tc.type: FUNC
176 */
177 HWTEST_F (FaultPerformanceTest, FaultPerformanceTest001, TestSize.Level2)
178 {
179 GTEST_LOG_(INFO) << "FaultPerformanceTest001: start.";
180 DfxDumpCatcher dumplog;
181 std::string msg;
182 clock_t befor = GetStartTime();
183 for (int i = 0; i < PERFORMANCE_TEST_NUMBER_ONE_HUNDRED; i++) {
184 dumplog.DumpCatch(FaultPerformanceTest::looprootPid, FaultPerformanceTest::looprootPid, msg);
185 }
186 GTEST_LOG_(INFO) << "DumpCatch API Performance time(PID(root), TID(root)): " << \
187 GetStopTime(befor)/PERFORMANCE_TEST_NUMBER_ONE_HUNDRED << "s";
188 double expectTime = PERFORMANCE_TEST_MAX_UNWIND_TIME_S;
189 double realTime = GetStopTime(befor)/PERFORMANCE_TEST_NUMBER_ONE_HUNDRED;
190 EXPECT_EQ(true, realTime < expectTime) << "FaultPerformanceTest001 Failed";
191 GTEST_LOG_(INFO) << "FaultPerformanceTest001: end.";
192 }
193
194 /**
195 * @tc.name: FaultPerformanceTest002
196 * @tc.desc: test DumpCatch API: PID(root), TID(0)
197 * @tc.type: FUNC
198 */
199 HWTEST_F (FaultPerformanceTest, FaultPerformanceTest002, TestSize.Level2)
200 {
201 GTEST_LOG_(INFO) << "FaultPerformanceTest002: start.";
202 DfxDumpCatcher dumplog;
203 std::string msg;
204 clock_t befor = GetStartTime();
205 for (int i = 0; i < PERFORMANCE_TEST_NUMBER_ONE_HUNDRED; i++) {
206 dumplog.DumpCatch(FaultPerformanceTest::looprootPid, 0, msg);
207 usleep(200000);
208 }
209 GTEST_LOG_(INFO) << "DumpCatch API Performance time(PID(root), TID(0)): " << \
210 GetStopTime(befor)/PERFORMANCE_TEST_NUMBER_ONE_HUNDRED << "s";
211 double expectTime = PERFORMANCE_TEST_MAX_UNWIND_TIME_S;
212 double realTime = GetStopTime(befor)/PERFORMANCE_TEST_NUMBER_ONE_HUNDRED - 0.2;
213 EXPECT_EQ(true, realTime < expectTime) << "FaultPerformanceTest002 Failed";
214 GTEST_LOG_(INFO) << "FaultPerformanceTest002: end.";
215 }
216
217 /**
218 * @tc.name: FaultPerformanceTest003
219 * @tc.desc: test dumpcatcher command: PID(root), TID(root)
220 * @tc.type: FUNC
221 */
222 HWTEST_F (FaultPerformanceTest, FaultPerformanceTest003, TestSize.Level2)
223 {
224 GTEST_LOG_(INFO) << "FaultPerformanceTest003: start.";
225 std::string procCMD = "dumpcatcher -p " + std::to_string(FaultPerformanceTest::looprootPid) + " -t "+
226 std::to_string(FaultPerformanceTest::looprootPid);
227 clock_t befor = GetStartTime();
228 for (int i = 0; i < PERFORMANCE_TEST_NUMBER_ONE_HUNDRED; i++) {
229 FaultPerformanceTest::ProcessDumpCommands(procCMD);
230 }
231 double timeInterval = GetStopTime(befor)/PERFORMANCE_TEST_NUMBER_ONE_HUNDRED;
232 GTEST_LOG_(INFO) << "dumpcatcher Command Performance time(PID(root), TID(root)): " << timeInterval << "s";
233 double expectTime = PERFORMANCE_TEST_MAX_UNWIND_TIME_S;
234 double realTime = GetStopTime(befor)/PERFORMANCE_TEST_NUMBER_ONE_HUNDRED;
235 EXPECT_EQ(true, realTime < expectTime) << "FaultPerformanceTest003 Failed";
236 GTEST_LOG_(INFO) << "FaultPerformanceTest003: end.";
237 }
238
239 /**
240 * @tc.name: FaultPerformanceTest004
241 * @tc.desc: test DumpCatch API: PID(root)
242 * @tc.type: FUNC
243 */
244 HWTEST_F (FaultPerformanceTest, FaultPerformanceTest004, TestSize.Level2)
245 {
246 GTEST_LOG_(INFO) << "FaultPerformanceTest004: start.";
247 std::string procCMD = "dumpcatcher -p " + std::to_string(FaultPerformanceTest::looprootPid);
248 clock_t befor = GetStartTime();
249 for (int i = 0; i < PERFORMANCE_TEST_NUMBER_ONE_HUNDRED; i++) {
250 FaultPerformanceTest::ProcessDumpCommands(procCMD);
251 }
252 GTEST_LOG_(INFO) << "dumpcatcher Command Performance time(PID(root)): " << \
253 GetStopTime(befor)/PERFORMANCE_TEST_NUMBER_ONE_HUNDRED << "s";
254
255 double expectTime = PERFORMANCE_TEST_MAX_UNWIND_TIME_S;
256 double realTime = GetStopTime(befor)/PERFORMANCE_TEST_NUMBER_ONE_HUNDRED;
257 EXPECT_EQ(true, realTime < expectTime) << "FaultPerformanceTest004 Failed";
258 GTEST_LOG_(INFO) << "FaultPerformanceTest004: end.";
259 }
260
261 /**
262 * @tc.name: FaultPerformanceTest005
263 * @tc.desc: test DumpCatchMultiPid API: PID(root), TID(0)
264 * @tc.type: FUNC
265 */
266 HWTEST_F (FaultPerformanceTest, FaultPerformanceTest005, TestSize.Level2)
267 {
268 GTEST_LOG_(INFO) << "FaultPerformanceTest005: start.";
269 DfxDumpCatcher dumplog;
270 std::string msg;
271 std::string apply = "foundation";
272 int applyPid = FaultPerformanceTest::getApplyPid(apply);
273 std::vector<int> multiPid {applyPid, FaultPerformanceTest::looprootPid};
274 clock_t befor = GetStartTime();
275 for (int i = 0; i < PERFORMANCE_TEST_NUMBER_ONE_HUNDRED; i++) {
276 dumplog.DumpCatchMultiPid(multiPid, msg);
277 }
278 double timeInterval = GetStopTime(befor)/PERFORMANCE_TEST_NUMBER_ONE_HUNDRED;
279 GTEST_LOG_(INFO) << "DumpCatchMultiPid API time(PID(root), PID(foundation)): " << timeInterval << "s";
280 double expectTime = PERFORMANCE_TEST_MAX_UNWIND_TIME_NEW_S;
281 double realTime = GetStopTime(befor)/PERFORMANCE_TEST_NUMBER_ONE_HUNDRED;
282 EXPECT_EQ(true, realTime < expectTime) << "FaultPerformanceTest005 Failed";
283 GTEST_LOG_(INFO) << "FaultPerformanceTest005: end.";
284 }
285
286 /**
287 * @tc.name: FaultPerformanceTest006
288 * @tc.desc: test DumpCatchFrame API: app PID(app), TID(0)
289 * @tc.type: FUNC
290 */
291 HWTEST_F (FaultPerformanceTest, FaultPerformanceTest006, TestSize.Level2)
292 {
293 GTEST_LOG_(INFO) << "FaultPerformanceTest006: start.";
294 std::string apply = "test_perfor";
295 int testPid = FaultPerformanceTest::getApplyPid(apply);
296 GTEST_LOG_(INFO) << testPid;
297 DfxDumpCatcher dumplog(testPid);
298 if (!dumplog.InitFrameCatcher()) {
299 GTEST_LOG_(ERROR) << "Failed to suspend thread(" << testPid << ").";
300 }
301 std::vector<std::shared_ptr<DfxFrame>> frameV;
302 clock_t befor = GetStartTime();
303 for (int i = 0; i < PERFORMANCE_TEST_NUMBER_ONE_HUNDRED; i++) {
304 bool ret = dumplog.CatchFrame(testPid, frameV);
305 GTEST_LOG_(INFO) << ret;
306 }
307 double timeInterval = GetStopTime(befor)/PERFORMANCE_TEST_NUMBER_ONE_HUNDRED;
308 GTEST_LOG_(INFO) << "DumpCatchFrame API time(PID(test_per), PID(test_per)):" << timeInterval << "s";
309 double expectTime = PERFORMANCE_TEST_MAX_UNWIND_TIME_S;
310 double realTime = GetStopTime(befor)/PERFORMANCE_TEST_NUMBER_ONE_HUNDRED;
311 EXPECT_EQ(true, realTime < expectTime) << "FaultPerformanceTest006 Failed";
312 GTEST_LOG_(INFO) << "FaultPerformanceTest006: end.";
313 }
314 }
315