mirror of
https://github.com/intel/compute-runtime.git
synced 2026-01-12 00:59:38 +08:00
Improve code coverage for Pmu Interface
Signed-off-by: Mayank Raghuwanshi <mayank.raghuwanshi@intel.com>
This commit is contained in:
committed by
Compute-Runtime-Automation
parent
e36941b171
commit
027a916107
@@ -42,6 +42,14 @@ uint32_t PmuInterfaceImp::getEventType() {
|
|||||||
return eventTypeVal;
|
return eventTypeVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssize_t PmuInterfaceImp::readCounters(int fd, uint64_t *data, ssize_t sizeOfdata) {
|
||||||
|
return read(fd, data, sizeOfdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
int PmuInterfaceImp::getErrorNo() {
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
inline int64_t PmuInterfaceImp::perfEventOpen(perf_event_attr *attr, pid_t pid, int cpu, int groupFd, uint64_t flags) {
|
inline int64_t PmuInterfaceImp::perfEventOpen(perf_event_attr *attr, pid_t pid, int cpu, int groupFd, uint64_t flags) {
|
||||||
attr->size = sizeof(*attr);
|
attr->size = sizeof(*attr);
|
||||||
return syscall(perfEventOpenSyscallNumber, attr, pid, cpu, groupFd, flags);
|
return syscall(perfEventOpenSyscallNumber, attr, pid, cpu, groupFd, flags);
|
||||||
@@ -67,14 +75,14 @@ int64_t PmuInterfaceImp::pmuInterfaceOpen(uint64_t config, int group, uint32_t f
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
ret = perfEventOpen(&attr, -1, cpu++, group, 0);
|
ret = perfEventOpen(&attr, -1, cpu++, group, 0);
|
||||||
} while ((ret < 0 && errno == EINVAL) && (cpu < nrCpus));
|
} while ((ret < 0 && getErrorNo() == EINVAL) && (cpu < nrCpus));
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PmuInterfaceImp::pmuRead(int fd, uint64_t *data, ssize_t sizeOfdata) {
|
int PmuInterfaceImp::pmuRead(int fd, uint64_t *data, ssize_t sizeOfdata) {
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
len = read(fd, data, sizeOfdata);
|
len = readCounters(fd, data, sizeOfdata);
|
||||||
if (len != sizeOfdata) {
|
if (len != sizeOfdata) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ class PmuInterfaceImp : public PmuInterface, NEO::NonCopyableOrMovableClass {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
MOCKABLE_VIRTUAL int64_t perfEventOpen(perf_event_attr *attr, pid_t pid, int cpu, int groupFd, uint64_t flags);
|
MOCKABLE_VIRTUAL int64_t perfEventOpen(perf_event_attr *attr, pid_t pid, int cpu, int groupFd, uint64_t flags);
|
||||||
|
MOCKABLE_VIRTUAL ssize_t readCounters(int fd, uint64_t *data, ssize_t sizeOfdata);
|
||||||
|
MOCKABLE_VIRTUAL int getErrorNo();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t getEventType();
|
uint32_t getEventType();
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2021 Intel Corporation
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
#
|
||||||
|
|
||||||
|
if(UNIX)
|
||||||
|
target_sources(${TARGET_NAME} PRIVATE
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/test_pmu.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/mock_pmu.h
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_subdirectories()
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Intel Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "level_zero/core/test/unit_tests/mock.h"
|
||||||
|
#include "level_zero/tools/source/sysman/linux/pmu/pmu_imp.h"
|
||||||
|
|
||||||
|
using namespace NEO;
|
||||||
|
namespace L0 {
|
||||||
|
namespace ult {
|
||||||
|
constexpr uint64_t mockEventVal = 2u;
|
||||||
|
constexpr uint64_t mockTimeStamp = 100u;
|
||||||
|
constexpr int64_t mockPmuFd = 5;
|
||||||
|
constexpr uint64_t mockEventCount = 2u;
|
||||||
|
constexpr uint64_t mockEvent1Val = 100u;
|
||||||
|
constexpr uint64_t mockEvent2Val = 150u;
|
||||||
|
class MockPmuInterfaceImpForSysman : public PmuInterfaceImp {
|
||||||
|
public:
|
||||||
|
using PmuInterfaceImp::getErrorNo;
|
||||||
|
using PmuInterfaceImp::perfEventOpen;
|
||||||
|
using PmuInterfaceImp::readCounters;
|
||||||
|
MockPmuInterfaceImpForSysman(LinuxSysmanImp *pLinuxSysmanImp) : PmuInterfaceImp(pLinuxSysmanImp) {}
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct Mock<MockPmuInterfaceImpForSysman> : public MockPmuInterfaceImpForSysman {
|
||||||
|
Mock<MockPmuInterfaceImpForSysman>(LinuxSysmanImp *pLinuxSysmanImp) : MockPmuInterfaceImpForSysman(pLinuxSysmanImp) {}
|
||||||
|
int64_t mockedPerfEventOpenAndSuccessReturn(perf_event_attr *attr, pid_t pid, int cpu, int groupFd, uint64_t flags) {
|
||||||
|
return mockPmuFd;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t mockedPerfEventOpenAndFailureReturn(perf_event_attr *attr, pid_t pid, int cpu, int groupFd, uint64_t flags) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mockedPmuReadAfterClearAndSuccessReturn(int fd, uint64_t *data, ssize_t sizeOfdata) {
|
||||||
|
memset(data, 0, sizeOfdata);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mockedPmuReadAndFailureReturn(int fd, uint64_t *data, ssize_t sizeOfdata) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t mockReadCounterSuccess(int fd, uint64_t *data, ssize_t sizeOfdata) {
|
||||||
|
data[0] = mockEventVal;
|
||||||
|
data[1] = mockTimeStamp;
|
||||||
|
return sizeOfdata;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t mockedReadCountersForGroupSuccess(int fd, uint64_t *data, ssize_t sizeOfdata) {
|
||||||
|
data[0] = mockEventCount;
|
||||||
|
data[1] = mockTimeStamp;
|
||||||
|
data[2] = mockEvent1Val;
|
||||||
|
data[3] = mockEvent2Val;
|
||||||
|
return sizeOfdata;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t mockReadCounterFailure(int fd, uint64_t *data, ssize_t sizeOfdata) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int mockGetErrorNoSuccess() {
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
int mockGetErrorNoFailure() {
|
||||||
|
return EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOCK_METHOD(int64_t, perfEventOpen, (perf_event_attr * attr, pid_t pid, int cpu, int groupFd, uint64_t flags), (override));
|
||||||
|
MOCK_METHOD(ssize_t, readCounters, (int fd, uint64_t *data, ssize_t sizeOfdata), (override));
|
||||||
|
MOCK_METHOD(int, getErrorNo, (), (override));
|
||||||
|
};
|
||||||
|
|
||||||
|
class PmuFsAccess : public FsAccess {};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Mock<PmuFsAccess> : public PmuFsAccess {
|
||||||
|
MOCK_METHOD(ze_result_t, read, (const std::string file, uint32_t &val), (override));
|
||||||
|
ze_result_t readValSuccess(const std::string file, uint32_t &val) {
|
||||||
|
val = 18;
|
||||||
|
return ZE_RESULT_SUCCESS;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace ult
|
||||||
|
} // namespace L0
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Intel Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "level_zero/tools/test/unit_tests/sources/sysman/linux/mock_sysman_fixture.h"
|
||||||
|
#include "level_zero/tools/test/unit_tests/sources/sysman/linux/pmu/mock_pmu.h"
|
||||||
|
|
||||||
|
using ::testing::Matcher;
|
||||||
|
using ::testing::Return;
|
||||||
|
namespace L0 {
|
||||||
|
namespace ult {
|
||||||
|
struct SysmanPmuFixture : public SysmanDeviceFixture {
|
||||||
|
protected:
|
||||||
|
std::unique_ptr<Mock<MockPmuInterfaceImpForSysman>> pPmuInterface;
|
||||||
|
PmuInterface *pOriginalPmuInterface = nullptr;
|
||||||
|
std::unique_ptr<Mock<PmuFsAccess>> pFsAccess;
|
||||||
|
FsAccess *pFsAccessOriginal = nullptr;
|
||||||
|
|
||||||
|
void SetUp() override {
|
||||||
|
SysmanDeviceFixture::SetUp();
|
||||||
|
pFsAccessOriginal = pLinuxSysmanImp->pFsAccess;
|
||||||
|
pFsAccess = std::make_unique<NiceMock<Mock<PmuFsAccess>>>();
|
||||||
|
pLinuxSysmanImp->pFsAccess = pFsAccess.get();
|
||||||
|
pOriginalPmuInterface = pLinuxSysmanImp->pPmuInterface;
|
||||||
|
pPmuInterface = std::make_unique<NiceMock<Mock<MockPmuInterfaceImpForSysman>>>(pLinuxSysmanImp);
|
||||||
|
pLinuxSysmanImp->pPmuInterface = pPmuInterface.get();
|
||||||
|
ON_CALL(*pFsAccess.get(), read(_, _))
|
||||||
|
.WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock<PmuFsAccess>::readValSuccess));
|
||||||
|
ON_CALL(*pPmuInterface.get(), perfEventOpen(_, _, _, _, _))
|
||||||
|
.WillByDefault(::testing::Invoke(pPmuInterface.get(), &Mock<MockPmuInterfaceImpForSysman>::mockedPerfEventOpenAndSuccessReturn));
|
||||||
|
ON_CALL(*pPmuInterface.get(), getErrorNo())
|
||||||
|
.WillByDefault(::testing::Invoke(pPmuInterface.get(), &Mock<MockPmuInterfaceImpForSysman>::mockGetErrorNoSuccess));
|
||||||
|
ON_CALL(*pPmuInterface.get(), readCounters(_, _, _))
|
||||||
|
.WillByDefault(::testing::Invoke(pPmuInterface.get(), &Mock<MockPmuInterfaceImpForSysman>::mockReadCounterSuccess));
|
||||||
|
}
|
||||||
|
void TearDown() override {
|
||||||
|
SysmanDeviceFixture::TearDown();
|
||||||
|
pLinuxSysmanImp->pPmuInterface = pOriginalPmuInterface;
|
||||||
|
pLinuxSysmanImp->pFsAccess = pFsAccessOriginal;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(SysmanPmuFixture, GivenValidPmuHandleWhenCallingPmuReadAndReadCountersFunctionReturnsSuccessThenSuccessIsReturned) {
|
||||||
|
uint64_t data[2];
|
||||||
|
int validFd = 10;
|
||||||
|
EXPECT_EQ(0, pLinuxSysmanImp->pPmuInterface->pmuRead(validFd, data, sizeof(data)));
|
||||||
|
EXPECT_EQ(mockEventVal, data[0]);
|
||||||
|
EXPECT_EQ(mockTimeStamp, data[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SysmanPmuFixture, GivenValidPmuHandleWhenCallingPmuReadAndReadCountersFunctionReturnsFailureThenFailureIsReturned) {
|
||||||
|
ON_CALL(*pPmuInterface.get(), readCounters(_, _, _))
|
||||||
|
.WillByDefault(::testing::Invoke(pPmuInterface.get(), &Mock<MockPmuInterfaceImpForSysman>::mockReadCounterFailure));
|
||||||
|
int validFd = 10;
|
||||||
|
uint64_t data[2];
|
||||||
|
EXPECT_EQ(-1, pLinuxSysmanImp->pPmuInterface->pmuRead(validFd, data, sizeof(data)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SysmanPmuFixture, GivenValidPmuHandleWhenCallingReadCountersAndInvalidFdIsPassedToReadSyscallThenFailureIsReturned) {
|
||||||
|
MockPmuInterfaceImpForSysman *pmuInterface = new MockPmuInterfaceImpForSysman(pLinuxSysmanImp);
|
||||||
|
uint64_t data[2];
|
||||||
|
int invalidFd = -1;
|
||||||
|
EXPECT_EQ(-1, pmuInterface->readCounters(invalidFd, data, sizeof(data)));
|
||||||
|
delete pmuInterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SysmanPmuFixture, GivenValidPmuHandleWhenCallingPerfEventOpenAndInvalidConfigIsPassedThenFailureIsReturned) {
|
||||||
|
MockPmuInterfaceImpForSysman *pmuInterface = new MockPmuInterfaceImpForSysman(pLinuxSysmanImp);
|
||||||
|
struct perf_event_attr attr = {};
|
||||||
|
int cpu = 0;
|
||||||
|
attr.type = 0;
|
||||||
|
attr.read_format = static_cast<uint64_t>(PERF_FORMAT_TOTAL_TIME_ENABLED);
|
||||||
|
attr.config = 0;
|
||||||
|
EXPECT_LT(pmuInterface->perfEventOpen(&attr, -1, cpu, -1, 0), 0);
|
||||||
|
delete pmuInterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SysmanPmuFixture, GivenValidPmuHandleWhenCallingPmuInterfaceOpenAndPerfEventOpenSucceedsThenVaildFdIsReturned) {
|
||||||
|
uint64_t config = 10;
|
||||||
|
EXPECT_EQ(mockPmuFd, pLinuxSysmanImp->pPmuInterface->pmuInterfaceOpen(config, -1, PERF_FORMAT_TOTAL_TIME_ENABLED));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SysmanPmuFixture, GivenValidPmuHandleWhenReadingGroupOfEventsUsingGroupFdThenSuccessIsReturned) {
|
||||||
|
ON_CALL(*pPmuInterface.get(), readCounters(_, _, _))
|
||||||
|
.WillByDefault(::testing::Invoke(pPmuInterface.get(), &Mock<MockPmuInterfaceImpForSysman>::mockedReadCountersForGroupSuccess));
|
||||||
|
uint64_t configForEvent1 = 10;
|
||||||
|
int64_t groupFd = pLinuxSysmanImp->pPmuInterface->pmuInterfaceOpen(configForEvent1, -1, PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_GROUP); // To get group leader
|
||||||
|
uint64_t configForEvent2 = 15;
|
||||||
|
pLinuxSysmanImp->pPmuInterface->pmuInterfaceOpen(configForEvent2, static_cast<int>(groupFd), PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_GROUP);
|
||||||
|
uint64_t data[4];
|
||||||
|
EXPECT_EQ(0, pLinuxSysmanImp->pPmuInterface->pmuRead(static_cast<int>(groupFd), data, sizeof(data)));
|
||||||
|
EXPECT_EQ(mockEventCount, data[0]);
|
||||||
|
EXPECT_EQ(mockTimeStamp, data[1]);
|
||||||
|
EXPECT_EQ(mockEvent1Val, data[2]);
|
||||||
|
EXPECT_EQ(mockEvent2Val, data[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SysmanPmuFixture, GivenValidPmuHandleWhenCallingPmuInterfaceOpenAndPerfEventOpenFailsThenFailureIsReturned) {
|
||||||
|
ON_CALL(*pPmuInterface.get(), perfEventOpen(_, _, _, _, _))
|
||||||
|
.WillByDefault(::testing::Invoke(pPmuInterface.get(), &Mock<MockPmuInterfaceImpForSysman>::mockedPerfEventOpenAndFailureReturn));
|
||||||
|
uint64_t config = 10;
|
||||||
|
EXPECT_EQ(-1, pLinuxSysmanImp->pPmuInterface->pmuInterfaceOpen(config, -1, PERF_FORMAT_TOTAL_TIME_ENABLED));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SysmanPmuFixture, GivenValidPmuHandleWhenCallingPmuInterfaceOpenAndPerfEventOpenFailsAndErrNoSetBySyscallIsNotInvalidArgumentThenFailureIsReturned) {
|
||||||
|
ON_CALL(*pPmuInterface.get(), perfEventOpen(_, _, _, _, _))
|
||||||
|
.WillByDefault(::testing::Invoke(pPmuInterface.get(), &Mock<MockPmuInterfaceImpForSysman>::mockedPerfEventOpenAndFailureReturn));
|
||||||
|
ON_CALL(*pPmuInterface.get(), getErrorNo())
|
||||||
|
.WillByDefault(::testing::Invoke(pPmuInterface.get(), &Mock<MockPmuInterfaceImpForSysman>::mockGetErrorNoFailure));
|
||||||
|
uint64_t config = 10;
|
||||||
|
EXPECT_EQ(-1, pLinuxSysmanImp->pPmuInterface->pmuInterfaceOpen(config, -1, PERF_FORMAT_TOTAL_TIME_ENABLED));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SysmanPmuFixture, GivenValidPmuHandleWhenCallingReadCountersAndInvalidFdIsPassedToReadSyscallThenErrorNoInavlidFileDescriptorIsSet) {
|
||||||
|
MockPmuInterfaceImpForSysman *pmuInterface = new MockPmuInterfaceImpForSysman(pLinuxSysmanImp);
|
||||||
|
uint64_t data[2];
|
||||||
|
int invalidFd = -1;
|
||||||
|
EXPECT_EQ(-1, pmuInterface->readCounters(invalidFd, data, sizeof(data)));
|
||||||
|
EXPECT_EQ(EBADF, pmuInterface->getErrorNo());
|
||||||
|
delete pmuInterface;
|
||||||
|
}
|
||||||
|
} // namespace ult
|
||||||
|
} // namespace L0
|
||||||
Reference in New Issue
Block a user