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