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 #include "cpu_usage_test.h"
17 #include "test_utilities.h"
18 using namespace testing::ext;
19 using namespace std::chrono;
20 namespace OHOS {
21 namespace Developtools {
22 namespace Hiperf {
23 class CpuUsageTest : public testing::Test {
24 public:
25 static void SetUpTestCase(void);
26 static void TearDownTestCase(void);
27 void SetUp();
28 void TearDown();
29
30 pid_t GetPidByProcessName(const std::string& procName);
31
32 int GetVmRSSLine(pid_t pid);
33
34 const char* GetItems(const char* buffer, unsigned int item);
35
36 unsigned long GetCpuTotalUsage();
37
38 unsigned long GetCpuProcUsage(int pid);
39
40 float GetCpuUsageRatio(int pid);
41
42 float GetAverageCpuUsage(pid_t pid, uint64_t timeOut);
43
44 void TestCpuUsage(const std::string &option, unsigned int expect, bool fixPid);
45
46 std::string testProcesses = "com.ohos.sceneboard";
47 };
48
SetUpTestCase()49 void CpuUsageTest::SetUpTestCase() {}
50
TearDownTestCase()51 void CpuUsageTest::TearDownTestCase() {}
52
SetUp()53 void CpuUsageTest::SetUp()
54 {
55 if (!HiPerf::CheckTestApp(testProcesses)) {
56 testProcesses = "com.ohos.launcher";
57 }
58 }
59
TearDown()60 void CpuUsageTest::TearDown() {}
61
GetPidByProcessName(const std::string & procName)62 pid_t CpuUsageTest::GetPidByProcessName(const std::string& procName)
63 {
64 FILE *fp = nullptr;
65 char buf[100]; // 100: buf size
66 pid_t pid = -1;
67 std::string cmd = "pidof " + procName;
68 if ((fp = popen(cmd.c_str(), "r")) != nullptr) {
69 if (fgets(buf, sizeof(buf), fp) != nullptr) {
70 pid = atoi(buf);
71 }
72 pclose(fp);
73 }
74 return pid;
75 }
76
GetVmRSSLine(pid_t pid)77 int CpuUsageTest::GetVmRSSLine(pid_t pid)
78 {
79 int line = 0;
80 std::string fileName = "/proc" + std::to_string(pid) + "/stat";
81 std::ifstream in(fileName, std::ios::in);
82 std::string tmp;
83 if (in.fail()) {
84 return 0;
85 } else {
86 while (getline(in, tmp)) {
87 line++;
88 if (tmp.find("VmRSS")) {
89 return line;
90 }
91 }
92 }
93 in.close();
94 return -1;
95 }
96
GetItems(const char * buffer,unsigned int item)97 const char* CpuUsageTest::GetItems(const char* buffer, unsigned int item)
98 {
99 // read from buffer by offset
100 const char* p = buffer;
101 int len = strlen(buffer);
102 unsigned int count = 0;
103 for (int i = 0; i < len; ++i) {
104 if (*p == ' ') {
105 count++;
106 if (count == item - 1) {
107 p++;
108 break;
109 }
110 }
111 p++;
112 }
113 return p;
114 }
115
GetCpuTotalUsage()116 unsigned long CpuUsageTest::GetCpuTotalUsage()
117 {
118 // get total cpu usage time from /proc/stat
119
120 // different mode cpu usage time
121 unsigned long userTime;
122 unsigned long niceTime;
123 unsigned long systemTime;
124 unsigned long idleTime;
125
126 FILE *fd = nullptr;
127 char buff[1024] = {0};
128 std::string fileName = "/proc/stat";
129 fd = fopen(fileName.c_str(), "r");
130 if (fd == nullptr) {
131 return 0;
132 }
133 fgets (buff, sizeof(buff), fd);
134 char name[64] = {0};
135 // get first line cpu time data
136 std::stringstream stream;
137 stream << buff;
138 stream >> name >> userTime >> niceTime >> systemTime >> idleTime;
139 fclose(fd);
140 stream.clear();
141 return (userTime + niceTime + systemTime + idleTime);
142 }
143
GetCpuProcUsage(int pid)144 unsigned long CpuUsageTest::GetCpuProcUsage(int pid)
145 {
146 // get cpu usage of specific pid
147
148 unsigned int tmpPid;
149 unsigned long utime; // user time
150 unsigned long stime; // kernel time
151 unsigned long cutime; // all usertime
152 unsigned long cstime; // all dead time
153
154 FILE *fd = nullptr;
155 char lineBuff[1024] = {0};
156 std::string fileName = "/proc" + std::to_string(pid) + "/stat";
157 fd = fopen(fileName.c_str(), "r");
158 if (fd == nullptr) {
159 return 0;
160 }
161 fgets(lineBuff, sizeof(lineBuff), fd);
162 std::stringstream stream;
163 stream << lineBuff;
164 stream >> tmpPid;
165 const char* q = GetItems(lineBuff, PROCESS_ITEM);
166 stream.clear();
167 stream << q;
168 stream >> utime >> stime >> cutime >> cstime;
169 fclose(fd);
170
171 return (utime + stime + cutime + cstime);
172 }
173
GetCpuUsageRatio(int pid)174 float CpuUsageTest::GetCpuUsageRatio(int pid)
175 {
176 unsigned long totalCpuTimepPrev;
177 unsigned long totalcputimeCur;
178 unsigned long procCpuTimepPrev;
179 unsigned long proccputimeCur;
180
181 totalCpuTimepPrev = GetCpuTotalUsage();
182 procCpuTimepPrev = GetCpuProcUsage(pid);
183
184 // sleep 200ms to get two point cpu usage snapshots
185 int timeInterval = 200000;
186 usleep(timeInterval);
187
188 totalcputimeCur = GetCpuTotalUsage();
189 proccputimeCur = GetCpuProcUsage(pid);
190
191 float pcpu = 0.0;
192 if (totalcputimeCur - totalCpuTimepPrev != 0) {
193 pcpu = (proccputimeCur - procCpuTimepPrev) / float(totalcputimeCur - totalCpuTimepPrev);
194 }
195
196 int cpuNum = get_nprocs();
197 // multi cpu machine should multiply cpu number
198 pcpu *= cpuNum;
199 return pcpu;
200 }
201
GetAverageCpuUsage(pid_t pid,uint64_t timeOut)202 float CpuUsageTest::GetAverageCpuUsage(pid_t pid, uint64_t timeOut)
203 {
204 float cpuUsage = 0.0;
205 int count = 0;
206 auto startTime = std::chrono::steady_clock::now();
207 while (true) {
208 ++count;
209 cpuUsage += GetCpuUsageRatio(pid);
210 auto thisTime = std::chrono::steady_clock::now();
211 if ((uint64_t)duration_cast<milliseconds>(thisTime - startTime).count()
212 > timeOut) {
213 break;
214 }
215 }
216 cpuUsage = HUNDRED * cpuUsage / count;
217 return cpuUsage;
218 }
219
TestCpuUsage(const std::string & option,unsigned int expect,bool fixPid)220 void CpuUsageTest::TestCpuUsage(const std::string &option, unsigned int expect, bool fixPid)
221 {
222 std::string cmd = "hiperf record ";
223 if (fixPid) {
224 cmd += "--app ";
225 cmd += " " + testProcesses;
226 }
227 cmd += " " + option;
228
229 std::thread perf(system, cmd.c_str());
230 perf.detach();
231 pid_t pid = GetPidByProcessName("hiperf");
232 uint64_t timeOut = 10000;
233 float cpuUsage = GetAverageCpuUsage(pid, timeOut);
234
235 EXPECT_LE(cpuUsage, expect);
236 }
237
238 /**
239 * @tc.name: recordCpuUsageF100_FP_SYSTEM
240 * @tc.desc: test hiperf record system wide cpu usage within required limit
241 * @tc.type: FUNC
242 */
243 HWTEST_F(CpuUsageTest, recordCpuUsageF100_FP_SYSTEM, TestSize.Level1)
244 {
245 TestCpuUsage("-a -f 100 -s fp -d 10", F100_FP_CPU_LIMIT_SYSTEM, false);
246 }
247
248 /**
249 * @tc.name: recordCpuUsageF500_FP_SYSTEM
250 * @tc.desc: test hiperf record system wide cpu usage within required limit
251 * @tc.type: FUNC
252 */
253 HWTEST_F(CpuUsageTest, recordCpuUsageF500_FP_SYSTEM, TestSize.Level1)
254 {
255 TestCpuUsage("-a -f 500 -s fp -d 10", F500_FP_CPU_LIMIT_SYSTEM, false);
256 }
257
258 /**
259 * @tc.name: recordCpuUsageF1000_FP_SYSTEM
260 * @tc.desc: test hiperf record system wide cpu usage within required limit
261 * @tc.type: FUNC
262 */
263 HWTEST_F(CpuUsageTest, recordCpuUsageF1000_FP_SYSTEM, TestSize.Level1)
264 {
265 TestCpuUsage("-a -f 1000 -s fp -d 10", F1000_FP_CPU_LIMIT_SYSTEM, false);
266 }
267
268 /**
269 * @tc.name: recordCpuUsageF2000_FP_SYSTEM
270 * @tc.desc: test hiperf record system wide cpu usage within required limit
271 * @tc.type: FUNC
272 */
273 HWTEST_F(CpuUsageTest, recordCpuUsageF2000_FP_SYSTEM, TestSize.Level1)
274 {
275 TestCpuUsage("-a -f 2000 -s fp -d 10", F2000_FP_CPU_LIMIT_SYSTEM, false);
276 }
277
278 /**
279 * @tc.name: recordCpuUsageF4000_FP_SYSTEM
280 * @tc.desc: test hiperf record system wide cpu usage within required limit
281 * @tc.type: FUNC
282 */
283 HWTEST_F(CpuUsageTest, recordCpuUsageF4000_FP_SYSTEM, TestSize.Level1)
284 {
285 TestCpuUsage("-a -f 4000 -s fp -d 10", F4000_FP_CPU_LIMIT_SYSTEM, false);
286 }
287
288 /**
289 * @tc.name: recordCpuUsageF8000_FP_SYSTEM
290 * @tc.desc: test hiperf record system wide cpu usage within required limit
291 * @tc.type: FUNC
292 */
293 HWTEST_F(CpuUsageTest, recordCpuUsageF8000_FP_SYSTEM, TestSize.Level1)
294 {
295 TestCpuUsage("-a -f 8000 -s fp -d 10", F8000_FP_CPU_LIMIT_SYSTEM, false);
296 }
297
298 /**
299 * @tc.name: recordCpuUsageF100_DWARF_SYSTEM
300 * @tc.desc: test hiperf record system wide cpu usage within required limit
301 * @tc.type: FUNC
302 */
303 HWTEST_F(CpuUsageTest, recordCpuUsageF100_DWARF_SYSTEM, TestSize.Level1)
304 {
305 TestCpuUsage("-a -f 100 -s dwarf -d 10", F100_DWARF_CPU_LIMIT_SYSTEM, false);
306 }
307
308 /**
309 * @tc.name: recordCpuUsageF500_DWARF_SYSTEM
310 * @tc.desc: test hiperf record system wide cpu usage within required limit
311 * @tc.type: FUNC
312 */
313 HWTEST_F(CpuUsageTest, recordCpuUsageF500_DWARF_SYSTEM, TestSize.Level1)
314 {
315 TestCpuUsage("-a -f 500 -s dwarf -d 10", F500_DWARF_CPU_LIMIT_SYSTEM, false);
316 }
317
318 /**
319 * @tc.name: recordCpuUsageF1000_DWARF_SYSTEM
320 * @tc.desc: test hiperf record system wide cpu usage within required limit
321 * @tc.type: FUNC
322 */
323 HWTEST_F(CpuUsageTest, recordCpuUsageF1000_DWARF_SYSTEM, TestSize.Level1)
324 {
325 TestCpuUsage("-a -f 1000 -s dwarf -d 10", F1000_DWARF_CPU_LIMIT_SYSTEM, false);
326 }
327
328 /**
329 * @tc.name: recordCpuUsageF2000_DWARF_SYSTEM
330 * @tc.desc: test hiperf record system wide cpu usage within required limit
331 * @tc.type: FUNC
332 */
333 HWTEST_F(CpuUsageTest, recordCpuUsageF2000_DWARF_SYSTEM, TestSize.Level1)
334 {
335 TestCpuUsage("-a -f 2000 -s dwarf -d 10", F2000_DWARF_CPU_LIMIT_SYSTEM, false);
336 }
337
338 /**
339 * @tc.name: recordCpuUsageF4000_DWARF_SYSTEM
340 * @tc.desc: test hiperf record system wide cpu usage within required limit
341 * @tc.type: FUNC
342 */
343 HWTEST_F(CpuUsageTest, recordCpuUsageF4000_DWARF_SYSTEM, TestSize.Level1)
344 {
345 TestCpuUsage("-a -f 4000 -s dwarf -d 10", F4000_DWARF_CPU_LIMIT_SYSTEM, false);
346 }
347
348 /**
349 * @tc.name: recordCpuUsageF8000_DWARF_SYSTEM
350 * @tc.desc: test hiperf record system wide cpu usage within required limit
351 * @tc.type: FUNC
352 */
353 HWTEST_F(CpuUsageTest, recordCpuUsageF8000_DWARF_SYSTEM, TestSize.Level1)
354 {
355 TestCpuUsage("-a -f 8000 -s dwarf -d 10", F8000_DWARF_CPU_LIMIT_SYSTEM, false);
356 }
357
358 /**
359 * @tc.name: recordCpuUsageF100_FP_PROCESS
360 * @tc.desc: test hiperf record one process cpu usage within required limit
361 * @tc.type: FUNC
362 */
363 HWTEST_F(CpuUsageTest, recordCpuUsageF100_FP_PROCESS, TestSize.Level1)
364 {
365 TestCpuUsage("-f 100 -s fp -d 10", F100_FP_CPU_LIMIT_PROCESS, true);
366 }
367
368 /**
369 * @tc.name: recordCpuUsageF500_FP_PROCESS
370 * @tc.desc: test hiperf record one process cpu usage within required limit
371 * @tc.type: FUNC
372 */
373 HWTEST_F(CpuUsageTest, recordCpuUsageF500_FP_PROCESS, TestSize.Level1)
374 {
375 TestCpuUsage("-f 500 -s fp -d 10", F500_FP_CPU_LIMIT_PROCESS, true);
376 }
377
378 /**
379 * @tc.name: recordCpuUsageF1000_FP_PROCESS
380 * @tc.desc: test hiperf record one process cpu usage within required limit
381 * @tc.type: FUNC
382 */
383 HWTEST_F(CpuUsageTest, recordCpuUsageF1000_FP_PROCESS, TestSize.Level1)
384 {
385 TestCpuUsage("-f 1000 -s fp -d 10", F1000_FP_CPU_LIMIT_PROCESS, true);
386 }
387
388 /**
389 * @tc.name: recordCpuUsageF2000_FP_PROCESS
390 * @tc.desc: test hiperf record one process cpu usage within required limit
391 * @tc.type: FUNC
392 */
393 HWTEST_F(CpuUsageTest, recordCpuUsageF2000_FP_PROCESS, TestSize.Level1)
394 {
395 TestCpuUsage("-f 2000 -s fp -d 10", F2000_FP_CPU_LIMIT_PROCESS, true);
396 }
397
398 /**
399 * @tc.name: recordCpuUsageF4000_FP_PROCESS
400 * @tc.desc: test hiperf record one process cpu usage within required limit
401 * @tc.type: FUNC
402 */
403 HWTEST_F(CpuUsageTest, recordCpuUsageF4000_FP_PROCESS, TestSize.Level1)
404 {
405 TestCpuUsage("-f 4000 -s fp -d 10", F4000_FP_CPU_LIMIT_PROCESS, true);
406 }
407
408 /**
409 * @tc.name: recordCpuUsageF8000_FP_PROCESS
410 * @tc.desc: test hiperf record one process cpu usage within required limit
411 * @tc.type: FUNC
412 */
413 HWTEST_F(CpuUsageTest, recordCpuUsageF8000_FP_PROCESS, TestSize.Level1)
414 {
415 TestCpuUsage("-f 8000 -s fp -d 10", F8000_FP_CPU_LIMIT_PROCESS, true);
416 }
417
418 /**
419 * @tc.name: recordCpuUsageF100_DWARF_PROCESS
420 * @tc.desc: test hiperf record one process cpu usage within required limit
421 * @tc.type: FUNC
422 */
423 HWTEST_F(CpuUsageTest, recordCpuUsageF100_DWARF_PROCESS, TestSize.Level1)
424 {
425 TestCpuUsage("-f 100 -s dwarf -d 10", F100_DWARF_CPU_LIMIT_PROCESS, true);
426 }
427
428 /**
429 * @tc.name: recordCpuUsageF500_DWARF_PROCESS
430 * @tc.desc: test hiperf record one process cpu usage within required limit
431 * @tc.type: FUNC
432 */
433 HWTEST_F(CpuUsageTest, recordCpuUsageF500_DWARF_PROCESS, TestSize.Level1)
434 {
435 TestCpuUsage("-f 500 -s dwarf -d 10", F500_DWARF_CPU_LIMIT_PROCESS, true);
436 }
437
438 /**
439 * @tc.name: recordCpuUsageF1000_DWARF_PROCESS
440 * @tc.desc: test hiperf record one process cpu usage within required limit
441 * @tc.type: FUNC
442 */
443 HWTEST_F(CpuUsageTest, recordCpuUsageF1000_DWARF_PROCESS, TestSize.Level1)
444 {
445 TestCpuUsage("-f 1000 -s dwarf -d 10", F1000_DWARF_CPU_LIMIT_PROCESS, true);
446 }
447
448 /**
449 * @tc.name: recordCpuUsageF2000_DWARF_PROCESS
450 * @tc.desc: test hiperf record one process cpu usage within required limit
451 * @tc.type: FUNC
452 */
453 HWTEST_F(CpuUsageTest, recordCpuUsageF2000_DWARF_PROCESS, TestSize.Level1)
454 {
455 TestCpuUsage("-f 2000 -s dwarf -d 10", F2000_DWARF_CPU_LIMIT_PROCESS, true);
456 }
457
458 /**
459 * @tc.name: recordCpuUsageF4000_DWARF_PROCESS
460 * @tc.desc: test hiperf record one process cpu usage within required limit
461 * @tc.type: FUNC
462 */
463 HWTEST_F(CpuUsageTest, recordCpuUsageF4000_DWARF_PROCESS, TestSize.Level1)
464 {
465 TestCpuUsage("-f 4000 -s dwarf -d 10", F4000_DWARF_CPU_LIMIT_PROCESS, true);
466 }
467
468 /**
469 * @tc.name: recordCpuUsageF8000_DWARF_PROCESS
470 * @tc.desc: test hiperf record one process cpu usage within required limit
471 * @tc.type: FUNC
472 */
473 HWTEST_F(CpuUsageTest, recordCpuUsageF8000_DWARF_PROCESS, TestSize.Level1)
474 {
475 TestCpuUsage("-f 8000 -s dwarf -d 10", F8000_DWARF_CPU_LIMIT_PROCESS, true);
476 }
477 } // namespace HiPerf
478 } // namespace Developtools
479 } // namespace OHOS
480