• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.launcher";
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 = "hiview";
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.Level0)
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.Level2)
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.Level2)
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.Level0)
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.Level3)
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.Level0)
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.Level2)
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.Level2)
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.Level0)
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.Level3)
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.Level0)
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.Level2)
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.Level2)
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.Level0)
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.Level3)
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.Level0)
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.Level2)
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.Level2)
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.Level0)
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.Level3)
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