* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
* libkperf licensed under the Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
* PURPOSE.
* See the Mulan PSL v2 for more details.
* Author: Mr.Lei
* Create: 2025-01-18
* Description: test for analyszing the trace data
******************************************************************************/
#include "test_common.h"
#include "common.h"
using namespace std;
class TestAnaylzeData : public testing::Test {
public:
void SetUp() {
if (GetTraceEventDir() == "") {
GTEST_SKIP();
}
}
void TearDown() {
if (appPid != 0) {
KillApp(appPid);
appPid = 0;
}
if (data != nullptr) {
PmuTraceDataFree(data);
data = nullptr;
}
PmuTraceClose(pd);
}
protected:
pid_t RunApp(const string &name)
{
char myDir[PATH_MAX] = {0};
readlink("/proc/self/exe", myDir, sizeof(myDir) - 1);
auto pid = vfork();
if (pid == 0) {
char *dirPath = dirname(myDir);
char fullPath[PATH_MAX];
snprintf(fullPath, PATH_MAX, "%s/case/%s", dirPath, name.c_str());
char *const *dummy = nullptr;
execvp(fullPath, dummy);
_exit(errno);
}
return pid;
}
void EnableTracePointer(unsigned pd, unsigned int second) {
PmuTraceEnable(pd);
sleep(second);
PmuTraceDisable(pd);
}
int pd;
pid_t appPid = 0;
PmuTraceData *data = nullptr;
};
* @brief test for configing param error
*/
TEST_F(TestAnaylzeData, config_param_error) {
const char *func1 = "testName";
const char *funcs[1] = {func1};
PmuTraceAttr traceAttr = {0};
traceAttr.funcs = funcs;
traceAttr.numFuncs = 1;
pd = PmuTraceOpen(TRACE_SYS_CALL, &traceAttr);
ASSERT_EQ(pd, -1);
ASSERT_EQ(Perrorno(), LIBPERF_ERR_INVALID_SYSCALL_FUN);
}
* @brief test for collecting single syscall trace data and single cpu
*/
TEST_F(TestAnaylzeData, collect_single_trace_data_success) {
appPid = RunTestApp("test_12threads");
int pidList[1] = {appPid};
int cpuList[1] = {1};
const char *func1 = "futex";
const char *funcs[1] = {func1};
PmuTraceAttr traceAttr = {0};
traceAttr.funcs = funcs;
traceAttr.numFuncs = 1;
traceAttr.pidList = pidList;
traceAttr.numPid = 1;
traceAttr.cpuList = cpuList;
traceAttr.numCpu = 1;
pd = PmuTraceOpen(TRACE_SYS_CALL, &traceAttr);
ASSERT_NE(pd, -1);
EnableTracePointer(pd, 1);
int len = PmuTraceRead(pd, &data);
EXPECT_TRUE(data != nullptr);
}
* @brief test for collecting single syscall trace data and all cpu
*/
TEST_F(TestAnaylzeData, collect_sleep_trace_data_success) {
appPid = RunApp("test_syscall_sleep");
int pidList[1] = {appPid};
const char *func1 = "clock_nanosleep";
const char *funcs[1] = {func1};
PmuTraceAttr traceAttr = {0};
traceAttr.funcs = funcs;
traceAttr.numFuncs = 1;
traceAttr.pidList = pidList;
traceAttr.numPid = 1;
pd = PmuTraceOpen(TRACE_SYS_CALL, &traceAttr);
ASSERT_NE(pd, -1);
EnableTracePointer(pd, 1);
int len = PmuTraceRead(pd, &data);
ASSERT_TRUE(data != nullptr);
ASSERT_LT(data[0].elapsedTime, 0.1);
}
* @brief test for collecting double syscall trace data and all cpu
*/
TEST_F(TestAnaylzeData, collect_double_trace_data_success) {
appPid = RunApp("test_syscall_read_write");
int pidList[1] = {appPid};
const char *func1 = "write";
const char *func2 = "read";
const char *funcs[2] = {func1, func2};
PmuTraceAttr traceAttr = {0};
traceAttr.funcs = funcs;
traceAttr.numFuncs = 2;
traceAttr.pidList = pidList;
traceAttr.numPid = 1;
pd = PmuTraceOpen(TRACE_SYS_CALL, &traceAttr);
ASSERT_NE(pd, -1);
EnableTracePointer(pd, 1);
int len = PmuTraceRead(pd, &data);
EXPECT_TRUE(data != nullptr);
}
* @brief test for collecting all syscall trace data in all cpu and all process
*/
TEST_F(TestAnaylzeData, collect_all_trace_data_success) {
PmuTraceAttr traceAttr = {0};
pd = PmuTraceOpen(TRACE_SYS_CALL, &traceAttr);
ASSERT_NE(pd, -1);
EnableTracePointer(pd, 1);
int len = PmuTraceRead(pd, &data);
EXPECT_TRUE(data != nullptr);
EXPECT_TRUE(data[len - 1].funcs != nullptr);
}