* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "cpu_usage_test.h"
#include "test_utilities.h"
using namespace testing::ext;
using namespace std::chrono;
namespace OHOS {
namespace Developtools {
namespace Hiperf {
class CpuUsageTest : public testing::Test {
public:
static void SetUpTestCase(void);
static void TearDownTestCase(void);
void SetUp();
void TearDown();
pid_t GetPidByProcessName(const std::string& procName);
int GetVmRSSLine(pid_t pid);
const char* GetItems(const char* buffer, unsigned int item);
unsigned long GetCpuTotalUsage();
unsigned long GetCpuProcUsage(int pid);
float GetCpuUsageRatio(int pid);
float GetAverageCpuUsage(pid_t pid, uint64_t timeOut);
void TestCpuUsage(const std::string &option, unsigned int expect, bool fixPid);
};
void CpuUsageTest::SetUpTestCase()
{
if (chmod("/data/test/hiperf_test_demo", 0755) == -1) {
GTEST_LOG_(ERROR) << "hiperf_test_demo chmod failed.";
}
if (system("/data/test/hiperf_test_demo &") != 0) {
GTEST_LOG_(ERROR) << "start hiperf_test_demo failed.";
} else {
GTEST_LOG_(INFO) << "start hiperf_test_demo success.";
}
}
void CpuUsageTest::TearDownTestCase()
{
if (system("kill -9 `pidof hiperf_test_demo`") != 0) {
GTEST_LOG_(ERROR) << "kill hiperf_test_demo failed.";
} else {
GTEST_LOG_(INFO) << "kill hiperf_test_demo success.";
}
}
void CpuUsageTest::SetUp() {}
void CpuUsageTest::TearDown() {}
pid_t CpuUsageTest::GetPidByProcessName(const std::string& procName)
{
FILE *fp = nullptr;
char buf[100];
pid_t pid = -1;
std::string cmd = "pidof " + procName;
if ((fp = popen(cmd.c_str(), "r")) != nullptr) {
if (fgets(buf, sizeof(buf), fp) != nullptr) {
pid = atoi(buf);
}
pclose(fp);
}
return pid;
}
int CpuUsageTest::GetVmRSSLine(pid_t pid)
{
int line = 0;
std::string fileName = "/proc" + std::to_string(pid) + "/stat";
std::ifstream in(fileName, std::ios::in);
std::string tmp;
if (in.fail()) {
return 0;
} else {
while (getline(in, tmp)) {
line++;
if (tmp.find("VmRSS")) {
return line;
}
}
}
in.close();
return -1;
}
const char* CpuUsageTest::GetItems(const char* buffer, unsigned int item)
{
const char* p = buffer;
int len = strlen(buffer);
unsigned int count = 0;
for (int i = 0; i < len; ++i) {
if (*p == ' ') {
count++;
if (count == item - 1) {
p++;
break;
}
}
p++;
}
return p;
}
unsigned long CpuUsageTest::GetCpuTotalUsage()
{
unsigned long userTime;
unsigned long niceTime;
unsigned long systemTime;
unsigned long idleTime;
FILE *fd = nullptr;
char buff[1024] = {0};
std::string fileName = "/proc/stat";
fd = fopen(fileName.c_str(), "r");
if (fd == nullptr) {
return 0;
}
fgets (buff, sizeof(buff), fd);
char name[64] = {0};
std::stringstream stream;
stream << buff;
stream >> name >> userTime >> niceTime >> systemTime >> idleTime;
fclose(fd);
stream.clear();
return (userTime + niceTime + systemTime + idleTime);
}
unsigned long CpuUsageTest::GetCpuProcUsage(int pid)
{
unsigned int tmpPid;
unsigned long utime;
unsigned long stime;
unsigned long cutime;
unsigned long cstime;
FILE *fd = nullptr;
char lineBuff[1024] = {0};
std::string fileName = "/proc" + std::to_string(pid) + "/stat";
fd = fopen(fileName.c_str(), "r");
if (fd == nullptr) {
return 0;
}
fgets(lineBuff, sizeof(lineBuff), fd);
std::stringstream stream;
stream << lineBuff;
stream >> tmpPid;
const char* q = GetItems(lineBuff, PROCESS_ITEM);
stream.clear();
stream << q;
stream >> utime >> stime >> cutime >> cstime;
fclose(fd);
return (utime + stime + cutime + cstime);
}
float CpuUsageTest::GetCpuUsageRatio(int pid)
{
unsigned long totalCpuTimepPrev;
unsigned long totalcputimeCur;
unsigned long procCpuTimepPrev;
unsigned long proccputimeCur;
totalCpuTimepPrev = GetCpuTotalUsage();
procCpuTimepPrev = GetCpuProcUsage(pid);
int timeInterval = 200000;
usleep(timeInterval);
totalcputimeCur = GetCpuTotalUsage();
proccputimeCur = GetCpuProcUsage(pid);
float pcpu = 0.0;
if (totalcputimeCur - totalCpuTimepPrev != 0) {
pcpu = (proccputimeCur - procCpuTimepPrev) / float(totalcputimeCur - totalCpuTimepPrev);
}
int cpuNum = get_nprocs();
pcpu *= cpuNum;
return pcpu;
}
float CpuUsageTest::GetAverageCpuUsage(pid_t pid, uint64_t timeOut)
{
float cpuUsage = 0.0;
int count = 0;
auto startTime = std::chrono::steady_clock::now();
while (true) {
++count;
cpuUsage += GetCpuUsageRatio(pid);
auto thisTime = std::chrono::steady_clock::now();
if ((uint64_t)duration_cast<milliseconds>(thisTime - startTime).count() > timeOut) {
break;
}
}
cpuUsage = HUNDRED * cpuUsage / count;
return cpuUsage;
}
void CpuUsageTest::TestCpuUsage(const std::string &option, unsigned int expect, bool fixPid)
{
std::string cmd = "hiperf record ";
if (fixPid) {
cmd += "--app hiperf_test_demo";
}
cmd += " " + option;
GTEST_LOG_(INFO) << "exec command: " << cmd;
std::thread perf(system, cmd.c_str());
pid_t pid = GetPidByProcessName("hiperf");
uint64_t timeOut = 2000;
float cpuUsage = GetAverageCpuUsage(pid, timeOut);
perf.join();
EXPECT_LE(cpuUsage, expect);
}
* @tc.name: recordCpuUsageF100_FP_SYSTEM
* @tc.desc: test hiperf record system wide cpu usage within required limit
* @tc.type: FUNC
*/
HWTEST_F(CpuUsageTest, recordCpuUsageF100_FP_SYSTEM, TestSize.Level0)
{
TestCpuUsage("-a -f 100 -s fp -d 2", F100_FP_CPU_LIMIT_SYSTEM, false);
}
* @tc.name: recordCpuUsageF500_FP_SYSTEM
* @tc.desc: test hiperf record system wide cpu usage within required limit
* @tc.type: FUNC
*/
HWTEST_F(CpuUsageTest, recordCpuUsageF500_FP_SYSTEM, TestSize.Level1)
{
TestCpuUsage("-a -f 500 -s fp -d 2", F500_FP_CPU_LIMIT_SYSTEM, false);
}
* @tc.name: recordCpuUsageF1000_FP_SYSTEM
* @tc.desc: test hiperf record system wide cpu usage within required limit
* @tc.type: FUNC
*/
HWTEST_F(CpuUsageTest, recordCpuUsageF1000_FP_SYSTEM, TestSize.Level2)
{
TestCpuUsage("-a -f 1000 -s fp -d 2", F1000_FP_CPU_LIMIT_SYSTEM, false);
}
* @tc.name: recordCpuUsageF2000_FP_SYSTEM
* @tc.desc: test hiperf record system wide cpu usage within required limit
* @tc.type: FUNC
*/
HWTEST_F(CpuUsageTest, recordCpuUsageF2000_FP_SYSTEM, TestSize.Level2)
{
TestCpuUsage("-a -f 2000 -s fp -d 2", F2000_FP_CPU_LIMIT_SYSTEM, false);
}
* @tc.name: recordCpuUsageF4000_FP_SYSTEM
* @tc.desc: test hiperf record system wide cpu usage within required limit
* @tc.type: FUNC
*/
HWTEST_F(CpuUsageTest, recordCpuUsageF4000_FP_SYSTEM, TestSize.Level0)
{
TestCpuUsage("-a -f 4000 -s fp -d 2", F4000_FP_CPU_LIMIT_SYSTEM, false);
}
* @tc.name: recordCpuUsageF8000_FP_SYSTEM
* @tc.desc: test hiperf record system wide cpu usage within required limit
* @tc.type: FUNC
*/
HWTEST_F(CpuUsageTest, recordCpuUsageF8000_FP_SYSTEM, TestSize.Level3)
{
TestCpuUsage("-a -f 8000 -s fp -d 2", F8000_FP_CPU_LIMIT_SYSTEM, false);
}
* @tc.name: recordCpuUsageF100_DWARF_SYSTEM
* @tc.desc: test hiperf record system wide cpu usage within required limit
* @tc.type: FUNC
*/
HWTEST_F(CpuUsageTest, recordCpuUsageF100_DWARF_SYSTEM, TestSize.Level0)
{
TestCpuUsage("-a -f 100 -s dwarf -d 2", F100_DWARF_CPU_LIMIT_SYSTEM, false);
}
* @tc.name: recordCpuUsageF500_DWARF_SYSTEM
* @tc.desc: test hiperf record system wide cpu usage within required limit
* @tc.type: FUNC
*/
HWTEST_F(CpuUsageTest, recordCpuUsageF500_DWARF_SYSTEM, TestSize.Level1)
{
TestCpuUsage("-a -f 500 -s dwarf -d 2", F500_DWARF_CPU_LIMIT_SYSTEM, false);
}
* @tc.name: recordCpuUsageF1000_DWARF_SYSTEM
* @tc.desc: test hiperf record system wide cpu usage within required limit
* @tc.type: FUNC
*/
HWTEST_F(CpuUsageTest, recordCpuUsageF1000_DWARF_SYSTEM, TestSize.Level2)
{
TestCpuUsage("-a -f 1000 -s dwarf -d 2", F1000_DWARF_CPU_LIMIT_SYSTEM, false);
}
* @tc.name: recordCpuUsageF2000_DWARF_SYSTEM
* @tc.desc: test hiperf record system wide cpu usage within required limit
* @tc.type: FUNC
*/
HWTEST_F(CpuUsageTest, recordCpuUsageF2000_DWARF_SYSTEM, TestSize.Level2)
{
TestCpuUsage("-a -f 2000 -s dwarf -d 2", F2000_DWARF_CPU_LIMIT_SYSTEM, false);
}
* @tc.name: recordCpuUsageF4000_DWARF_SYSTEM
* @tc.desc: test hiperf record system wide cpu usage within required limit
* @tc.type: FUNC
*/
HWTEST_F(CpuUsageTest, recordCpuUsageF4000_DWARF_SYSTEM, TestSize.Level0)
{
TestCpuUsage("-a -f 4000 -s dwarf -d 2", F4000_DWARF_CPU_LIMIT_SYSTEM, false);
}
* @tc.name: recordCpuUsageF8000_DWARF_SYSTEM
* @tc.desc: test hiperf record system wide cpu usage within required limit
* @tc.type: FUNC
*/
HWTEST_F(CpuUsageTest, recordCpuUsageF8000_DWARF_SYSTEM, TestSize.Level3)
{
TestCpuUsage("-a -f 8000 -s dwarf -d 2", F8000_DWARF_CPU_LIMIT_SYSTEM, false);
}
* @tc.name: recordCpuUsageF100_FP_PROCESS
* @tc.desc: test hiperf record one process cpu usage within required limit
* @tc.type: FUNC
*/
HWTEST_F(CpuUsageTest, recordCpuUsageF100_FP_PROCESS, TestSize.Level0)
{
TestCpuUsage("-f 100 -s fp -d 2", F100_FP_CPU_LIMIT_PROCESS, true);
}
* @tc.name: recordCpuUsageF500_FP_PROCESS
* @tc.desc: test hiperf record one process cpu usage within required limit
* @tc.type: FUNC
*/
HWTEST_F(CpuUsageTest, recordCpuUsageF500_FP_PROCESS, TestSize.Level1)
{
TestCpuUsage("-f 500 -s fp -d 2", F500_FP_CPU_LIMIT_PROCESS, true);
}
* @tc.name: recordCpuUsageF1000_FP_PROCESS
* @tc.desc: test hiperf record one process cpu usage within required limit
* @tc.type: FUNC
*/
HWTEST_F(CpuUsageTest, recordCpuUsageF1000_FP_PROCESS, TestSize.Level2)
{
TestCpuUsage("-f 1000 -s fp -d 2", F1000_FP_CPU_LIMIT_PROCESS, true);
}
* @tc.name: recordCpuUsageF2000_FP_PROCESS
* @tc.desc: test hiperf record one process cpu usage within required limit
* @tc.type: FUNC
*/
HWTEST_F(CpuUsageTest, recordCpuUsageF2000_FP_PROCESS, TestSize.Level2)
{
TestCpuUsage("-f 2000 -s fp -d 2", F2000_FP_CPU_LIMIT_PROCESS, true);
}
* @tc.name: recordCpuUsageF4000_FP_PROCESS
* @tc.desc: test hiperf record one process cpu usage within required limit
* @tc.type: FUNC
*/
HWTEST_F(CpuUsageTest, recordCpuUsageF4000_FP_PROCESS, TestSize.Level0)
{
TestCpuUsage("-f 4000 -s fp -d 2", F4000_FP_CPU_LIMIT_PROCESS, true);
}
* @tc.name: recordCpuUsageF8000_FP_PROCESS
* @tc.desc: test hiperf record one process cpu usage within required limit
* @tc.type: FUNC
*/
HWTEST_F(CpuUsageTest, recordCpuUsageF8000_FP_PROCESS, TestSize.Level3)
{
TestCpuUsage("-f 8000 -s fp -d 2", F8000_FP_CPU_LIMIT_PROCESS, true);
}
* @tc.name: recordCpuUsageF100_DWARF_PROCESS
* @tc.desc: test hiperf record one process cpu usage within required limit
* @tc.type: FUNC
*/
HWTEST_F(CpuUsageTest, recordCpuUsageF100_DWARF_PROCESS, TestSize.Level0)
{
TestCpuUsage("-f 100 -s dwarf -d 2", F100_DWARF_CPU_LIMIT_PROCESS, true);
}
* @tc.name: recordCpuUsageF500_DWARF_PROCESS
* @tc.desc: test hiperf record one process cpu usage within required limit
* @tc.type: FUNC
*/
HWTEST_F(CpuUsageTest, recordCpuUsageF500_DWARF_PROCESS, TestSize.Level1)
{
TestCpuUsage("-f 500 -s dwarf -d 2", F500_DWARF_CPU_LIMIT_PROCESS, true);
}
* @tc.name: recordCpuUsageF1000_DWARF_PROCESS
* @tc.desc: test hiperf record one process cpu usage within required limit
* @tc.type: FUNC
*/
HWTEST_F(CpuUsageTest, recordCpuUsageF1000_DWARF_PROCESS, TestSize.Level2)
{
TestCpuUsage("-f 1000 -s dwarf -d 2", F1000_DWARF_CPU_LIMIT_PROCESS, true);
}
* @tc.name: recordCpuUsageF2000_DWARF_PROCESS
* @tc.desc: test hiperf record one process cpu usage within required limit
* @tc.type: FUNC
*/
HWTEST_F(CpuUsageTest, recordCpuUsageF2000_DWARF_PROCESS, TestSize.Level2)
{
TestCpuUsage("-f 2000 -s dwarf -d 2", F2000_DWARF_CPU_LIMIT_PROCESS, true);
}
* @tc.name: recordCpuUsageF4000_DWARF_PROCESS
* @tc.desc: test hiperf record one process cpu usage within required limit
* @tc.type: FUNC
*/
HWTEST_F(CpuUsageTest, recordCpuUsageF4000_DWARF_PROCESS, TestSize.Level0)
{
TestCpuUsage("-f 4000 -s dwarf -d 2", F4000_DWARF_CPU_LIMIT_PROCESS, true);
}
* @tc.name: recordCpuUsageF8000_DWARF_PROCESS
* @tc.desc: test hiperf record one process cpu usage within required limit
* @tc.type: FUNC
*/
HWTEST_F(CpuUsageTest, recordCpuUsageF8000_DWARF_PROCESS, TestSize.Level3)
{
TestCpuUsage("-f 8000 -s dwarf -d 2", F8000_DWARF_CPU_LIMIT_PROCESS, true);
}
}
}
}