Add zesDeviceReset ULTs.

This patch adds two ULTs.

Verify that an IN USE error is returned if the device is open by another
process.

Verify that reset succeeds if device is not in use.

Verify that reset with force succeeds if device is in use.

Verify that reset without force succeeds if device is opened during
reset, and process is killed.

Verify that reset with force fails with device in use
if device is opened during reset, and process will not die

Change-Id: I232572c192bc481d8d63ef39c7494976100325ff
Signed-off-by: Bill Jordan <bill.jordan@intel.com>
This commit is contained in:
Bill Jordan 2020-10-07 16:40:07 -04:00 committed by sys_ocldev
parent 8c4f3d3953
commit ccd5abfbfd
7 changed files with 323 additions and 58 deletions

View File

@ -14,7 +14,6 @@
#include <level_zero/zet_api.h>
#include <chrono>
#include <csignal>
#include <time.h>
namespace L0 {
@ -131,10 +130,6 @@ static void getPidFdsForOpenDevice(ProcfsAccess *pProcfsAccess, SysfsAccess *pSy
}
ze_result_t LinuxGlobalOperationsImp::reset(ze_bool_t force) {
FsAccess *pFsAccess = &pLinuxSysmanImp->getFsAccess();
ProcfsAccess *pProcfsAccess = &pLinuxSysmanImp->getProcfsAccess();
SysfsAccess *pSysfsAccess = &pLinuxSysmanImp->getSysfsAccess();
std::string resetPath;
std::string resetName;
ze_result_t result = ZE_RESULT_SUCCESS;
@ -165,7 +160,7 @@ ze_result_t LinuxGlobalOperationsImp::reset(ze_bool_t force) {
myPidFds = fds;
} else if (!fds.empty()) {
if (force) {
::kill(pid, SIGKILL);
pProcfsAccess->kill(pid);
} else {
// Device is in use by another process.
// Don't reset while in use.
@ -206,24 +201,25 @@ ze_result_t LinuxGlobalOperationsImp::reset(ze_bool_t force) {
if (!fds.empty()) {
// Kill all processes that have the device open.
::kill(pid, SIGKILL);
pProcfsAccess->kill(pid);
deviceUsingPids.push_back(pid);
}
}
// Wait for all the processes to exit
// If they don't all exit within 10
// seconds, just fail reset.
// If they don't all exit within resetTimeout
// just fail reset.
auto start = std::chrono::steady_clock::now();
auto end = start;
for (auto &&pid : deviceUsingPids) {
while (pProcfsAccess->isAlive(pid)) {
auto end = std::chrono::steady_clock::now();
if (std::chrono::duration_cast<std::chrono::seconds>(end - start).count() >= LinuxGlobalOperationsImp::resetTimeout) {
if (std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() > resetTimeout) {
return ZE_RESULT_ERROR_HANDLE_OBJECT_IN_USE;
}
struct ::timespec timeout = {.tv_sec = 0, .tv_nsec = 1000};
::nanosleep(&timeout, NULL);
end = std::chrono::steady_clock::now();
}
}
@ -396,6 +392,7 @@ LinuxGlobalOperationsImp::LinuxGlobalOperationsImp(OsSysman *pOsSysman) {
pLinuxSysmanImp = static_cast<LinuxSysmanImp *>(pOsSysman);
pSysfsAccess = &pLinuxSysmanImp->getSysfsAccess();
pProcfsAccess = &pLinuxSysmanImp->getProcfsAccess();
pFsAccess = &pLinuxSysmanImp->getFsAccess();
pDevice = pLinuxSysmanImp->getDeviceHandle();
}

View File

@ -31,13 +31,14 @@ class LinuxGlobalOperationsImp : public OsGlobalOperations, NEO::NonCopyableOrMo
protected:
FsAccess *pFsAccess = nullptr;
ProcfsAccess *pProcfsAccess = nullptr;
SysfsAccess *pSysfsAccess = nullptr;
LinuxSysmanImp *pLinuxSysmanImp = nullptr;
Device *pDevice = nullptr;
private:
static const int resetTimeout = 10;
int resetTimeout = 10000; // in milliseconds
private:
static const std::string deviceDir;
static const std::string vendorFile;
static const std::string deviceFile;

View File

@ -11,6 +11,7 @@
#include <array>
#include <cerrno>
#include <csignal>
#include <cstdio>
#include <cstdlib>
#include <dirent.h>
@ -186,11 +187,11 @@ ze_result_t FsAccess::canWrite(const std::string file) {
return ZE_RESULT_SUCCESS;
}
ze_result_t FsAccess::exists(const std::string file) {
bool FsAccess::fileExists(const std::string file) {
if (access(file.c_str(), F_OK)) {
return ZE_RESULT_ERROR_NOT_AVAILABLE;
return false;
}
return ZE_RESULT_SUCCESS;
return true;
}
ze_result_t FsAccess::getFileMode(const std::string file, ::mode_t &mode) {
@ -272,14 +273,6 @@ std::string FsAccess::getDirName(const std::string path) {
return path.substr(0, pos);
}
bool FsAccess::fileExists(const std::string file) {
struct stat sb;
if (stat(file.c_str(), &sb) == 0) {
return true;
}
return false;
}
// Procfs Access
const std::string ProcfsAccess::procDir = "/proc/";
const std::string ProcfsAccess::fdDir = "/fd/";
@ -354,8 +347,12 @@ ze_result_t ProcfsAccess::getFileName(const ::pid_t pid, const int fd, std::stri
return FsAccess::readSymLink(fullFdPath(pid, fd), val);
}
ze_result_t ProcfsAccess::isAlive(const ::pid_t pid) {
return FsAccess::exists(fullPath(pid));
bool ProcfsAccess::isAlive(const ::pid_t pid) {
return FsAccess::fileExists(fullPath(pid));
}
void ProcfsAccess::kill(const ::pid_t pid) {
::kill(pid, SIGKILL);
}
::pid_t ProcfsAccess::myProcessId() {
@ -553,7 +550,7 @@ bool SysfsAccess::fileExists(const std::string file) {
return FsAccess::fileExists(fullPath(file).c_str());
}
ze_bool_t SysfsAccess::isMyDeviceFile(const std::string dev) {
bool SysfsAccess::isMyDeviceFile(const std::string dev) {
// dev is a full pathname.
if (getDirName(dev).compare(drmDriverDevNodeDir)) {
for (auto &&next : deviceNames) {

View File

@ -30,7 +30,6 @@ class FsAccess {
virtual ze_result_t canRead(const std::string file);
virtual ze_result_t canWrite(const std::string file);
ze_result_t exists(const std::string file);
virtual ze_result_t getFileMode(const std::string file, ::mode_t &mode);
virtual ze_result_t read(const std::string file, uint64_t &val);
@ -58,15 +57,17 @@ class ProcfsAccess : private FsAccess {
static ProcfsAccess *create();
~ProcfsAccess() override = default;
ze_result_t listProcesses(std::vector<::pid_t> &list);
::pid_t myProcessId();
ze_result_t getFileDescriptors(const ::pid_t pid, std::vector<int> &list);
ze_result_t getFileName(const ::pid_t pid, const int fd, std::string &val);
ze_result_t isAlive(const ::pid_t pid);
MOCKABLE_VIRTUAL ze_result_t listProcesses(std::vector<::pid_t> &list);
MOCKABLE_VIRTUAL ::pid_t myProcessId();
MOCKABLE_VIRTUAL ze_result_t getFileDescriptors(const ::pid_t pid, std::vector<int> &list);
MOCKABLE_VIRTUAL ze_result_t getFileName(const ::pid_t pid, const int fd, std::string &val);
MOCKABLE_VIRTUAL bool isAlive(const ::pid_t pid);
MOCKABLE_VIRTUAL void kill(const ::pid_t pid);
private:
protected:
ProcfsAccess() = default;
private:
std::string fullPath(const ::pid_t pid);
std::string fdDirPath(const ::pid_t pid);
std::string fullFdPath(const ::pid_t pid, const int fd);
@ -100,10 +101,10 @@ class SysfsAccess : private FsAccess {
MOCKABLE_VIRTUAL ze_result_t scanDirEntries(const std::string path, std::vector<std::string> &list);
ze_result_t readSymLink(const std::string path, std::string &buf) override;
ze_result_t getRealPath(const std::string path, std::string &buf) override;
ze_result_t bindDevice(const std::string device);
ze_result_t unbindDevice(const std::string device);
bool fileExists(const std::string file) override;
ze_bool_t isMyDeviceFile(const std::string dev);
MOCKABLE_VIRTUAL ze_result_t bindDevice(const std::string device);
MOCKABLE_VIRTUAL ze_result_t unbindDevice(const std::string device);
MOCKABLE_VIRTUAL bool fileExists(const std::string file) override;
MOCKABLE_VIRTUAL bool isMyDeviceFile(const std::string dev);
private:
SysfsAccess(const std::string file);

View File

@ -39,8 +39,10 @@ const std::string engine2("2");
const std::string engine3("3");
std::string driverVersion("5.0.0-37-generic SMP mod_unload");
std::string srcVersion("5.0.0-37");
const std::string fullFunctionResetPath("/reset");
const std::string ueventWedgedFile("/var/lib/libze_intel_gpu/wedged_file");
const std::string mockFunctionResetPath("/MOCK_FUNCTION_LEVEL_RESET_PATH");
const std::string mockDeviceDir("/MOCK_DEVICE_DIR");
const std::string mockDeviceName("/MOCK_DEVICE_NAME");
class GlobalOperationsSysfsAccess : public SysfsAccess {};
@ -48,7 +50,9 @@ template <>
struct Mock<GlobalOperationsSysfsAccess> : public GlobalOperationsSysfsAccess {
ze_result_t getRealPathVal(const std::string file, std::string &val) {
if (file.compare(functionLevelReset) == 0) {
val = fullFunctionResetPath;
val = mockFunctionResetPath;
} else if (file.compare(deviceDir) == 0) {
val = mockDeviceDir;
} else {
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
@ -137,12 +141,102 @@ struct Mock<GlobalOperationsSysfsAccess> : public GlobalOperationsSysfsAccess {
return ZE_RESULT_SUCCESS;
}
ze_result_t mockDeviceOpSuccess(const std::string device) {
return ZE_RESULT_SUCCESS;
}
ze_result_t mockDeviceOpFailure(const std::string device) {
return ZE_RESULT_ERROR_UNKNOWN;
}
bool mockIsMyDeviceFile(const std::string dev) {
if (dev.compare(mockDeviceName) == 0) {
return true;
}
return false;
}
Mock<GlobalOperationsSysfsAccess>() = default;
MOCK_METHOD(ze_result_t, read, (const std::string file, std::string &val), (override));
MOCK_METHOD(ze_result_t, read, (const std::string file, uint64_t &val), (override));
MOCK_METHOD(ze_result_t, scanDirEntries, (const std::string path, std::vector<std::string> &list), (override));
MOCK_METHOD(ze_result_t, getRealPath, (const std::string path, std::string &val), (override));
MOCK_METHOD(ze_result_t, bindDevice, (const std::string device), (override));
MOCK_METHOD(ze_result_t, unbindDevice, (const std::string device), (override));
MOCK_METHOD(bool, fileExists, (const std::string file), (override));
MOCK_METHOD(bool, isMyDeviceFile, (const std::string dev), (override));
};
class GlobalOperationsProcfsAccess : public ProcfsAccess {};
template <>
struct Mock<GlobalOperationsProcfsAccess> : public GlobalOperationsProcfsAccess {
const ::pid_t extraPid = 4;
const int extraFd = 5;
std::vector<::pid_t> pidList = {1, 2, 3};
std::vector<int> fdList = {0, 1, 2};
::pid_t ourDevicePid = 0;
int ourDeviceFd = 0;
ze_result_t mockProcessListDeviceUnused(std::vector<::pid_t> &list) {
list = pidList;
return ZE_RESULT_SUCCESS;
}
ze_result_t mockProcessListDeviceInUse(std::vector<::pid_t> &list) {
list = pidList;
if (ourDevicePid) {
list.push_back(ourDevicePid);
}
return ZE_RESULT_SUCCESS;
}
::pid_t getMockMyProcessId() {
return ::getpid();
}
ze_result_t getMockFileDescriptors(const ::pid_t pid, std::vector<int> &list) {
// Give every process 3 file descriptors
// Except the device that MOCK has the device open. Give it one extra.
list.clear();
list = fdList;
if (ourDevicePid == pid) {
list.push_back(ourDeviceFd);
}
return ZE_RESULT_SUCCESS;
}
ze_result_t getMockFileName(const ::pid_t pid, const int fd, std::string &val) {
if (pid == ourDevicePid && fd == ourDeviceFd) {
val = mockDeviceName;
} else {
// return fake filenames for other file descriptors
val = std::string("/FILENAME") + std::to_string(fd);
}
return ZE_RESULT_SUCCESS;
}
bool mockIsAlive(const ::pid_t pid) {
if (pid == ourDevicePid) {
return true;
}
return false;
}
void mockKill(const ::pid_t pid) {
ourDevicePid = 0;
}
Mock<GlobalOperationsProcfsAccess>() = default;
MOCK_METHOD(ze_result_t, listProcesses, (std::vector<::pid_t> & list), (override));
MOCK_METHOD(::pid_t, myProcessId, (), (override));
MOCK_METHOD(ze_result_t, getFileDescriptors, (const ::pid_t pid, std::vector<int> &list), (override));
MOCK_METHOD(ze_result_t, getFileName, (const ::pid_t pid, const int fd, std::string &val), (override));
MOCK_METHOD(bool, isAlive, (const ::pid_t pid), (override));
MOCK_METHOD(void, kill, (const ::pid_t pid), (override));
};
class GlobalOperationsFsAccess : public FsAccess {};
@ -214,18 +308,21 @@ struct Mock<GlobalOperationsFsAccess> : public GlobalOperationsFsAccess {
return ZE_RESULT_SUCCESS;
}
ze_result_t writeSuccess(const std::string file, const std::string val) {
return ZE_RESULT_SUCCESS;
}
Mock<GlobalOperationsFsAccess>() = default;
MOCK_METHOD(ze_result_t, read, (const std::string file, std::string &val), (override));
MOCK_METHOD(ze_result_t, read, (const std::string file, uint32_t &val), (override));
MOCK_METHOD(ze_result_t, write, (const std::string file, const std::string val), (override));
MOCK_METHOD(ze_result_t, canWrite, (const std::string file), (override));
};
class PublicLinuxGlobalOperationsImp : public L0::LinuxGlobalOperationsImp {
public:
using LinuxGlobalOperationsImp::pFsAccess;
using LinuxGlobalOperationsImp::pLinuxSysmanImp;
using LinuxGlobalOperationsImp::pSysfsAccess;
using LinuxGlobalOperationsImp::resetTimeout;
};
} // namespace ult

View File

@ -32,21 +32,25 @@ const std::string expectedModelName("0x3ea5");
class SysmanGlobalOperationsFixture : public SysmanDeviceFixture {
protected:
std::unique_ptr<Mock<GlobalOperationsSysfsAccess>> pSysfsAccess;
std::unique_ptr<Mock<GlobalOperationsProcfsAccess>> pProcfsAccess;
std::unique_ptr<Mock<GlobalOperationsFsAccess>> pFsAccess;
SysfsAccess *pSysfsAccessOld = nullptr;
ProcfsAccess *pProcfsAccessOld = nullptr;
FsAccess *pFsAccessOld = nullptr;
OsGlobalOperations *pOsGlobalOperationsPrev = nullptr;
L0::GlobalOperations *pGlobalOperationsPrev = nullptr;
L0::GlobalOperationsImp *pGlobalOperationsImp;
PublicLinuxGlobalOperationsImp linuxGlobalOperationsImp;
void SetUp() override {
SysmanDeviceFixture::SetUp();
pSysfsAccessOld = pLinuxSysmanImp->pSysfsAccess;
pProcfsAccessOld = pLinuxSysmanImp->pProcfsAccess;
pFsAccessOld = pLinuxSysmanImp->pFsAccess;
pSysfsAccess = std::make_unique<NiceMock<Mock<GlobalOperationsSysfsAccess>>>();
pProcfsAccess = std::make_unique<NiceMock<Mock<GlobalOperationsProcfsAccess>>>();
pFsAccess = std::make_unique<NiceMock<Mock<GlobalOperationsFsAccess>>>();
pLinuxSysmanImp->pSysfsAccess = pSysfsAccess.get();
pLinuxSysmanImp->pProcfsAccess = pProcfsAccess.get();
pLinuxSysmanImp->pFsAccess = pFsAccess.get();
ON_CALL(*pSysfsAccess.get(), read(_, Matcher<std::string &>(_)))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<GlobalOperationsSysfsAccess>::getValString));
@ -71,6 +75,7 @@ class SysmanGlobalOperationsFixture : public SysmanDeviceFixture {
pGlobalOperationsImp = nullptr;
SysmanDeviceFixture::TearDown();
pLinuxSysmanImp->pSysfsAccess = pSysfsAccessOld;
pLinuxSysmanImp->pProcfsAccess = pProcfsAccessOld;
pLinuxSysmanImp->pFsAccess = pFsAccessOld;
}
};
@ -177,16 +182,6 @@ TEST_F(SysmanGlobalOperationsFixture, GivenValidDeviceHandleWhileReadingNonExist
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, pSysfsAccess->scanDirEntries("clients/7/busy", engineEntries));
}
TEST_F(SysmanGlobalOperationsFixture, GivenValidDeviceHandleWhenCallingResetVerifyPermissionDenied) {
ON_CALL(*pSysfsAccess.get(), getRealPath(_, Matcher<std::string &>(_)))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<GlobalOperationsSysfsAccess>::getRealPathVal));
ON_CALL(*pFsAccess.get(), canWrite(Matcher<std::string>(fullFunctionResetPath)))
.WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock<GlobalOperationsFsAccess>::getPermissionDenied));
pGlobalOperationsImp->init();
ze_result_t result = zesDeviceReset(device, true);
EXPECT_EQ(ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS, result);
}
TEST_F(SysmanGlobalOperationsFixture, GivenValidDeviceHandleWhenCallingGetDeviceStatewhenDeviceIsWedged) {
ON_CALL(*pFsAccess.get(), read(_, Matcher<uint32_t &>(_)))
.WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock<GlobalOperationsFsAccess>::getValWedgedFileTrue));
@ -216,5 +211,182 @@ TEST_F(SysmanGlobalOperationsFixture, GivenValidDeviceHandleWhenCallingGetDevice
zes_device_state_t deviceState;
EXPECT_EQ(ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS, zesDeviceGetState(device, &deviceState));
}
TEST_F(SysmanGlobalOperationsFixture, GivenValidDeviceHandleWhenCallingResetVerifyPermissionDenied) {
ON_CALL(*pSysfsAccess.get(), getRealPath(_, Matcher<std::string &>(_)))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<GlobalOperationsSysfsAccess>::getRealPathVal));
ON_CALL(*pFsAccess.get(), canWrite(Matcher<std::string>(mockFunctionResetPath)))
.WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock<GlobalOperationsFsAccess>::getPermissionDenied));
pGlobalOperationsImp->init();
ze_result_t result = zesDeviceReset(device, true);
EXPECT_EQ(ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS, result);
}
TEST_F(SysmanGlobalOperationsFixture, GivenValidDeviceHandleWhenForceFalseCallingAndInUseResetVerifyInUseError) {
pProcfsAccess->ourDevicePid = pProcfsAccess->extraPid;
pProcfsAccess->ourDeviceFd = pProcfsAccess->extraFd;
ON_CALL(*pSysfsAccess.get(), getRealPath(_, Matcher<std::string &>(_)))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<GlobalOperationsSysfsAccess>::getRealPathVal));
ON_CALL(*pFsAccess.get(), canWrite(Matcher<std::string>(mockFunctionResetPath)))
.WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock<GlobalOperationsFsAccess>::getSuccess));
ON_CALL(*pProcfsAccess.get(), listProcesses(Matcher<std::vector<::pid_t> &>(_)))
.WillByDefault(::testing::Invoke(pProcfsAccess.get(), &Mock<GlobalOperationsProcfsAccess>::mockProcessListDeviceInUse));
ON_CALL(*pProcfsAccess.get(), getFileDescriptors(_, Matcher<std::vector<int> &>(_)))
.WillByDefault(::testing::Invoke(pProcfsAccess.get(), &Mock<GlobalOperationsProcfsAccess>::getMockFileDescriptors));
ON_CALL(*pProcfsAccess.get(), getFileName(_, _, Matcher<std::string &>(_)))
.WillByDefault(::testing::Invoke(pProcfsAccess.get(), &Mock<GlobalOperationsProcfsAccess>::getMockFileName));
ON_CALL(*pSysfsAccess.get(), isMyDeviceFile(_))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<GlobalOperationsSysfsAccess>::mockIsMyDeviceFile));
pGlobalOperationsImp->init();
ze_result_t result = zesDeviceReset(device, false);
EXPECT_EQ(ZE_RESULT_ERROR_HANDLE_OBJECT_IN_USE, result);
}
TEST_F(SysmanGlobalOperationsFixture, GivenValidDeviceHandleWhenForceFalseAndNotInUseCallingResetVerifySuccess) {
// Pretend we have the device open
pProcfsAccess->ourDevicePid = getpid();
pProcfsAccess->ourDeviceFd = ::open("/dev/null", 0);
ON_CALL(*pSysfsAccess.get(), getRealPath(_, Matcher<std::string &>(_)))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<GlobalOperationsSysfsAccess>::getRealPathVal));
ON_CALL(*pFsAccess.get(), canWrite(Matcher<std::string>(mockFunctionResetPath)))
.WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock<GlobalOperationsFsAccess>::getSuccess));
// The first time we get the process list, include our own process, that has the file open
// Reset should close the file (we verify after reset). On subsequent calls, return
// the process list without our process
EXPECT_CALL(*pProcfsAccess.get(), listProcesses(Matcher<std::vector<::pid_t> &>(_)))
.WillOnce(::testing::Invoke(pProcfsAccess.get(), &Mock<GlobalOperationsProcfsAccess>::mockProcessListDeviceInUse))
.WillRepeatedly(::testing::Invoke(pProcfsAccess.get(), &Mock<GlobalOperationsProcfsAccess>::mockProcessListDeviceUnused));
ON_CALL(*pProcfsAccess.get(), myProcessId())
.WillByDefault(::testing::Invoke(pProcfsAccess.get(), &Mock<GlobalOperationsProcfsAccess>::getMockMyProcessId));
ON_CALL(*pProcfsAccess.get(), getFileDescriptors(_, Matcher<std::vector<int> &>(_)))
.WillByDefault(::testing::Invoke(pProcfsAccess.get(), &Mock<GlobalOperationsProcfsAccess>::getMockFileDescriptors));
ON_CALL(*pProcfsAccess.get(), getFileName(_, _, Matcher<std::string &>(_)))
.WillByDefault(::testing::Invoke(pProcfsAccess.get(), &Mock<GlobalOperationsProcfsAccess>::getMockFileName));
ON_CALL(*pSysfsAccess.get(), isMyDeviceFile(_))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<GlobalOperationsSysfsAccess>::mockIsMyDeviceFile));
EXPECT_CALL(*pSysfsAccess.get(), unbindDevice(_))
.WillOnce(::testing::Invoke(pSysfsAccess.get(), &Mock<GlobalOperationsSysfsAccess>::mockDeviceOpSuccess));
EXPECT_CALL(*pFsAccess.get(), write(mockFunctionResetPath, std::string("1")))
.WillOnce(::testing::Invoke(pFsAccess.get(), &Mock<GlobalOperationsFsAccess>::writeSuccess));
EXPECT_CALL(*pSysfsAccess.get(), bindDevice(_))
.WillOnce(::testing::Invoke(pSysfsAccess.get(), &Mock<GlobalOperationsSysfsAccess>::mockDeviceOpSuccess));
pGlobalOperationsImp->init();
ze_result_t result = zesDeviceReset(device, false);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
// Check that reset closed the device
// If the device is already closed, then close will fail with errno of EBADF
EXPECT_NE(0, ::close(pProcfsAccess->ourDevicePid));
EXPECT_EQ(errno, EBADF);
}
TEST_F(SysmanGlobalOperationsFixture, GivenValidDeviceHandleWhenForceTrueAndInUseCallingResetVerifySuccessAndKillProcess) {
// Pretend another process has the device open
pProcfsAccess->ourDevicePid = getpid() + 1; // make sure it isn't our process id
pProcfsAccess->ourDeviceFd = pProcfsAccess->extraFd;
ON_CALL(*pSysfsAccess.get(), getRealPath(_, Matcher<std::string &>(_)))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<GlobalOperationsSysfsAccess>::getRealPathVal));
ON_CALL(*pFsAccess.get(), canWrite(Matcher<std::string>(mockFunctionResetPath)))
.WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock<GlobalOperationsFsAccess>::getSuccess));
ON_CALL(*pProcfsAccess.get(), listProcesses(Matcher<std::vector<::pid_t> &>(_)))
.WillByDefault(::testing::Invoke(pProcfsAccess.get(), &Mock<GlobalOperationsProcfsAccess>::mockProcessListDeviceInUse));
ON_CALL(*pProcfsAccess.get(), isAlive(_))
.WillByDefault(::testing::Invoke(pProcfsAccess.get(), &Mock<GlobalOperationsProcfsAccess>::mockIsAlive));
ON_CALL(*pProcfsAccess.get(), myProcessId())
.WillByDefault(::testing::Invoke(pProcfsAccess.get(), &Mock<GlobalOperationsProcfsAccess>::getMockMyProcessId));
ON_CALL(*pProcfsAccess.get(), getFileDescriptors(_, Matcher<std::vector<int> &>(_)))
.WillByDefault(::testing::Invoke(pProcfsAccess.get(), &Mock<GlobalOperationsProcfsAccess>::getMockFileDescriptors));
ON_CALL(*pProcfsAccess.get(), getFileName(_, _, Matcher<std::string &>(_)))
.WillByDefault(::testing::Invoke(pProcfsAccess.get(), &Mock<GlobalOperationsProcfsAccess>::getMockFileName));
ON_CALL(*pSysfsAccess.get(), isMyDeviceFile(_))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<GlobalOperationsSysfsAccess>::mockIsMyDeviceFile));
EXPECT_CALL(*pProcfsAccess.get(), kill(pProcfsAccess->ourDevicePid))
.WillOnce(::testing::Invoke(pProcfsAccess.get(), &Mock<GlobalOperationsProcfsAccess>::mockKill));
EXPECT_CALL(*pSysfsAccess.get(), unbindDevice(_))
.WillOnce(::testing::Invoke(pSysfsAccess.get(), &Mock<GlobalOperationsSysfsAccess>::mockDeviceOpSuccess));
EXPECT_CALL(*pFsAccess.get(), write(mockFunctionResetPath, std::string("1")))
.WillOnce(::testing::Invoke(pFsAccess.get(), &Mock<GlobalOperationsFsAccess>::writeSuccess));
EXPECT_CALL(*pSysfsAccess.get(), bindDevice(_))
.WillOnce(::testing::Invoke(pSysfsAccess.get(), &Mock<GlobalOperationsSysfsAccess>::mockDeviceOpSuccess));
pGlobalOperationsImp->init();
ze_result_t result = zesDeviceReset(device, true);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
}
TEST_F(SysmanGlobalOperationsFixture, GivenValidDeviceHandleWhenForceFalseAndProcessStartsMidResetCallingResetVerifySuccessAndProcessKilled) {
// Pretend another process has the device open
pProcfsAccess->ourDevicePid = getpid() + 1; // make sure it isn't our process id
pProcfsAccess->ourDeviceFd = pProcfsAccess->extraFd;
ON_CALL(*pSysfsAccess.get(), getRealPath(_, Matcher<std::string &>(_)))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<GlobalOperationsSysfsAccess>::getRealPathVal));
ON_CALL(*pFsAccess.get(), canWrite(Matcher<std::string>(mockFunctionResetPath)))
.WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock<GlobalOperationsFsAccess>::getSuccess));
// Return process list without open fd on first call, but with open fd on subsequent calls
EXPECT_CALL(*pProcfsAccess.get(), listProcesses(Matcher<std::vector<::pid_t> &>(_)))
.WillOnce(::testing::Invoke(pProcfsAccess.get(), &Mock<GlobalOperationsProcfsAccess>::mockProcessListDeviceUnused))
.WillRepeatedly(::testing::Invoke(pProcfsAccess.get(), &Mock<GlobalOperationsProcfsAccess>::mockProcessListDeviceInUse));
ON_CALL(*pProcfsAccess.get(), isAlive(_))
.WillByDefault(::testing::Invoke(pProcfsAccess.get(), &Mock<GlobalOperationsProcfsAccess>::mockIsAlive));
ON_CALL(*pProcfsAccess.get(), myProcessId())
.WillByDefault(::testing::Invoke(pProcfsAccess.get(), &Mock<GlobalOperationsProcfsAccess>::getMockMyProcessId));
ON_CALL(*pProcfsAccess.get(), getFileDescriptors(_, Matcher<std::vector<int> &>(_)))
.WillByDefault(::testing::Invoke(pProcfsAccess.get(), &Mock<GlobalOperationsProcfsAccess>::getMockFileDescriptors));
ON_CALL(*pProcfsAccess.get(), getFileName(_, _, Matcher<std::string &>(_)))
.WillByDefault(::testing::Invoke(pProcfsAccess.get(), &Mock<GlobalOperationsProcfsAccess>::getMockFileName));
ON_CALL(*pSysfsAccess.get(), isMyDeviceFile(_))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<GlobalOperationsSysfsAccess>::mockIsMyDeviceFile));
EXPECT_CALL(*pProcfsAccess.get(), kill(pProcfsAccess->ourDevicePid))
.WillOnce(::testing::Invoke(pProcfsAccess.get(), &Mock<GlobalOperationsProcfsAccess>::mockKill));
EXPECT_CALL(*pSysfsAccess.get(), unbindDevice(_))
.WillOnce(::testing::Invoke(pSysfsAccess.get(), &Mock<GlobalOperationsSysfsAccess>::mockDeviceOpSuccess));
EXPECT_CALL(*pFsAccess.get(), write(mockFunctionResetPath, std::string("1")))
.WillOnce(::testing::Invoke(pFsAccess.get(), &Mock<GlobalOperationsFsAccess>::writeSuccess));
EXPECT_CALL(*pSysfsAccess.get(), bindDevice(_))
.WillOnce(::testing::Invoke(pSysfsAccess.get(), &Mock<GlobalOperationsSysfsAccess>::mockDeviceOpSuccess));
pGlobalOperationsImp->init();
ze_result_t result = zesDeviceReset(device, false);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
}
TEST_F(SysmanGlobalOperationsFixture, GivenValidDeviceHandleWhenForceTrueAndInUseButProcessWontDieCallingResetVerifyFailureInUse) {
// Pretend another process has the device open
pProcfsAccess->ourDevicePid = getpid() + 1; // make sure it isn't our process id
pProcfsAccess->ourDeviceFd = pProcfsAccess->extraFd;
static_cast<PublicLinuxGlobalOperationsImp *>(pGlobalOperationsImp->pOsGlobalOperations)->resetTimeout = 0; // timeout immediate
ON_CALL(*pSysfsAccess.get(), getRealPath(_, Matcher<std::string &>(_)))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<GlobalOperationsSysfsAccess>::getRealPathVal));
ON_CALL(*pFsAccess.get(), canWrite(Matcher<std::string>(mockFunctionResetPath)))
.WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock<GlobalOperationsFsAccess>::getSuccess));
// Return process list without open fd on first call, but with open fd on subsequent calls
EXPECT_CALL(*pProcfsAccess.get(), listProcesses(Matcher<std::vector<::pid_t> &>(_)))
.WillOnce(::testing::Invoke(pProcfsAccess.get(), &Mock<GlobalOperationsProcfsAccess>::mockProcessListDeviceUnused))
.WillRepeatedly(::testing::Invoke(pProcfsAccess.get(), &Mock<GlobalOperationsProcfsAccess>::mockProcessListDeviceInUse));
ON_CALL(*pProcfsAccess.get(), isAlive(_))
.WillByDefault(::testing::Invoke(pProcfsAccess.get(), &Mock<GlobalOperationsProcfsAccess>::mockIsAlive));
ON_CALL(*pProcfsAccess.get(), myProcessId())
.WillByDefault(::testing::Invoke(pProcfsAccess.get(), &Mock<GlobalOperationsProcfsAccess>::getMockMyProcessId));
ON_CALL(*pProcfsAccess.get(), getFileDescriptors(_, Matcher<std::vector<int> &>(_)))
.WillByDefault(::testing::Invoke(pProcfsAccess.get(), &Mock<GlobalOperationsProcfsAccess>::getMockFileDescriptors));
ON_CALL(*pProcfsAccess.get(), getFileName(_, _, Matcher<std::string &>(_)))
.WillByDefault(::testing::Invoke(pProcfsAccess.get(), &Mock<GlobalOperationsProcfsAccess>::getMockFileName));
ON_CALL(*pSysfsAccess.get(), isMyDeviceFile(_))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<GlobalOperationsSysfsAccess>::mockIsMyDeviceFile));
EXPECT_CALL(*pProcfsAccess.get(), kill(pProcfsAccess->ourDevicePid))
.Times(1);
EXPECT_CALL(*pSysfsAccess.get(), unbindDevice(_))
.WillOnce(::testing::Invoke(pSysfsAccess.get(), &Mock<GlobalOperationsSysfsAccess>::mockDeviceOpSuccess));
EXPECT_CALL(*pFsAccess.get(), write(mockFunctionResetPath, std::string("1")))
.Times(0);
EXPECT_CALL(*pSysfsAccess.get(), bindDevice(_))
.Times(0);
pGlobalOperationsImp->init();
ze_result_t result = zesDeviceReset(device, false);
EXPECT_EQ(ZE_RESULT_ERROR_HANDLE_OBJECT_IN_USE, result);
}
} // namespace ult
} // namespace L0

View File

@ -46,14 +46,14 @@ TEST_F(SysmanDeviceFixture, GivenValidPathnameWhenCallingFsAccessExistsThenSucce
char cwd[PATH_MAX];
std::string path = getcwd(cwd, PATH_MAX);
EXPECT_EQ(FsAccess.exists(path), ZE_RESULT_SUCCESS);
EXPECT_TRUE(FsAccess.fileExists(path));
}
TEST_F(SysmanDeviceFixture, GivenInvalidPathnameWhenCallingFsAccessExistsThenErrorIsReturned) {
auto FsAccess = pLinuxSysmanImp->getFsAccess();
std::string path = "noSuchFileOrDirectory";
EXPECT_EQ(FsAccess.exists(path), ZE_RESULT_ERROR_NOT_AVAILABLE);
EXPECT_FALSE(FsAccess.fileExists(path));
}
TEST_F(SysmanDeviceFixture, GivenCreateSysfsAccessHandleWhenCallinggetSysfsAccessThenCreatedSysfsAccessHandleHandleWillBeRetrieved) {
@ -79,13 +79,13 @@ TEST_F(SysmanDeviceFixture, GivenCreateProcfsAccessHandleWhenCallinggetProcfsAcc
TEST_F(SysmanDeviceFixture, GivenValidPidWhenCallingProcfsAccessIsAliveThenSuccessIsReturned) {
auto ProcfsAccess = pLinuxSysmanImp->getProcfsAccess();
EXPECT_EQ(ProcfsAccess.isAlive(getpid()), ZE_RESULT_SUCCESS);
EXPECT_TRUE(ProcfsAccess.isAlive(getpid()));
}
TEST_F(SysmanDeviceFixture, GivenInvalidPidWhenCallingProcfsAccessIsAliveThenErrorIsReturned) {
auto ProcfsAccess = pLinuxSysmanImp->getProcfsAccess();
EXPECT_EQ(ProcfsAccess.isAlive(reinterpret_cast<::pid_t>(-1)), ZE_RESULT_ERROR_NOT_AVAILABLE);
EXPECT_FALSE(ProcfsAccess.isAlive(reinterpret_cast<::pid_t>(-1)));
}
TEST_F(SysmanDeviceFixture, GivenPmtHandleWhenCallinggetPlatformMonitoringTechAccessThenCreatedPmtHandleWillBeRetrieved) {