diff --git a/level_zero/core/source/driver/driver.cpp b/level_zero/core/source/driver/driver.cpp index 07cac06d13..5fe70eb478 100644 --- a/level_zero/core/source/driver/driver.cpp +++ b/level_zero/core/source/driver/driver.cpp @@ -75,31 +75,37 @@ void DriverImp::initialize(ze_result_t *result) { executionEnvironment->incRefInternal(); auto neoDevices = NEO::DeviceFactory::createDevices(*executionEnvironment); + bool isDevicePermissionError = executionEnvironment->isDevicePermissionError(); executionEnvironment->decRefInternal(); - if (!neoDevices.empty()) { - auto deviceGroups = NEO::Device::groupDevices(std::move(neoDevices)); - for (auto &devices : deviceGroups) { - auto driverHandle = DriverHandle::create(std::move(devices), envVariables, result); - if (driverHandle) { - globalDriverHandles->push_back(driverHandle); - } + if (neoDevices.empty()) { + if (isDevicePermissionError) { + *result = ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS; } + return; + } - if (globalDriverHandles->size() > 0) { - *result = ZE_RESULT_SUCCESS; + auto deviceGroups = NEO::Device::groupDevices(std::move(neoDevices)); + for (auto &devices : deviceGroups) { + auto driverHandle = DriverHandle::create(std::move(devices), envVariables, result); + if (driverHandle) { + globalDriverHandles->push_back(driverHandle); + } + } - if (envVariables.metrics) { - *result = MetricDeviceContext::enableMetricApi(); - } - if (*result != ZE_RESULT_SUCCESS) { - for (auto &driverHandle : *globalDriverHandles) { - delete static_cast(driverHandle); - } - globalDriverHandles->clear(); - } else if (envVariables.pin) { - std::unique_lock mtx{this->gtpinInitMtx}; - this->gtPinInitializationNeeded = true; + if (globalDriverHandles->size() > 0) { + *result = ZE_RESULT_SUCCESS; + + if (envVariables.metrics) { + *result = MetricDeviceContext::enableMetricApi(); + } + if (*result != ZE_RESULT_SUCCESS) { + for (auto &driverHandle : *globalDriverHandles) { + delete static_cast(driverHandle); } + globalDriverHandles->clear(); + } else if (envVariables.pin) { + std::unique_lock mtx{this->gtpinInitMtx}; + this->gtPinInitializationNeeded = true; } } } diff --git a/shared/source/execution_environment/execution_environment.h b/shared/source/execution_environment/execution_environment.h index 091d2d575b..ca62419a34 100644 --- a/shared/source/execution_environment/execution_environment.h +++ b/shared/source/execution_environment/execution_environment.h @@ -64,6 +64,10 @@ class ExecutionEnvironment : public ReferenceTrackedObject fp64EmulationEnabled = true; } bool isFP64EmulationEnabled() const { return fp64EmulationEnabled; } + void setDevicePermissionError(bool value) { + devicePermissionError = value; + } + bool isDevicePermissionError() const { return devicePermissionError; } void setOneApiPvcWaEnv(bool val) { oneApiPvcWaEnv = val; @@ -79,7 +83,7 @@ class ExecutionEnvironment : public ReferenceTrackedObject std::unique_ptr osEnvironment; std::vector> rootDeviceEnvironments; void releaseRootDeviceEnvironmentResources(RootDeviceEnvironment *rootDeviceEnvironment); - // Map of Sub Device Indicies set during Affinity Mask in the form of: + // Map of Sub Device Indices set during Affinity Mask in the form of: // // Primarily used by the Metrics Library to communicate the actual Sub Device Index being used in queries. std::unordered_map> mapOfSubDeviceIndices; @@ -95,6 +99,7 @@ class ExecutionEnvironment : public ReferenceTrackedObject bool metricsEnabled = false; bool fp64EmulationEnabled = false; bool oneApiPvcWaEnv = true; + bool devicePermissionError = false; DeviceHierarchyMode deviceHierarchyMode = DeviceHierarchyMode::composite; DebuggingMode debuggingEnabledMode = DebuggingMode::disabled; diff --git a/shared/source/os_interface/linux/drm_neo.cpp b/shared/source/os_interface/linux/drm_neo.cpp index b08f4c59aa..3683199562 100644 --- a/shared/source/os_interface/linux/drm_neo.cpp +++ b/shared/source/os_interface/linux/drm_neo.cpp @@ -669,9 +669,15 @@ std::vector> Drm::discoverDevices(ExecutionEnvironme numRootDevices = debugManager.flags.CreateMultipleRootDevices.get(); } + errno = 0; std::vector files = Directory::getFiles(Os::pciDevicesDirectory); + int returnedErrno = errno; if (files.size() == 0) { + if (returnedErrno == EACCES || returnedErrno == EPERM) { + executionEnvironment.setDevicePermissionError(true); + } + const char *pathPrefix = "/dev/dri/renderD"; const unsigned int maxDrmDevices = 64; unsigned int startNum = 128; @@ -681,6 +687,10 @@ std::vector> Drm::discoverDevices(ExecutionEnvironme int fileDescriptor = SysCalls::open(path.c_str(), O_RDWR | O_CLOEXEC); if (fileDescriptor < 0) { + returnedErrno = errno; + if (returnedErrno == EACCES || returnedErrno == EPERM) { + executionEnvironment.setDevicePermissionError(true); + } continue; } auto pciPath = NEO::getPciPath(fileDescriptor); @@ -690,6 +700,11 @@ std::vector> Drm::discoverDevices(ExecutionEnvironme break; } } + + if (!hwDeviceIds.empty()) { + executionEnvironment.setDevicePermissionError(false); + } + return hwDeviceIds; } @@ -714,7 +729,7 @@ std::vector> Drm::discoverDevices(ExecutionEnvironme if (!osPciPath.empty()) { if (osPciPath.compare(pciPath) != 0) { - // if osPciPath is non-empty, then interest is only in discovering device having same bdf as ocPciPath. Skip all other devices. + // if osPciPath is non-empty, then interest is only in discovering device having same bdf as osPciPath. Skip all other devices. continue; } } @@ -725,6 +740,15 @@ std::vector> Drm::discoverDevices(ExecutionEnvironme } } int fileDescriptor = SysCalls::open(file->c_str(), O_RDWR | O_CLOEXEC); + + if (fileDescriptor < 0) { + returnedErrno = errno; + if (returnedErrno == EACCES || returnedErrno == EPERM) { + executionEnvironment.setDevicePermissionError(true); + } + continue; + } + appendHwDeviceId(hwDeviceIds, fileDescriptor, pciPath.c_str(), file->c_str()); if (!hwDeviceIds.empty() && hwDeviceIds.size() == numRootDevices) { break; @@ -734,6 +758,11 @@ std::vector> Drm::discoverDevices(ExecutionEnvironme return hwDeviceIds; } } while (hwDeviceIds.size() < numRootDevices); + + if (!hwDeviceIds.empty()) { + executionEnvironment.setDevicePermissionError(false); + } + return hwDeviceIds; } diff --git a/shared/source/os_interface/windows/wddm/wddm.cpp b/shared/source/os_interface/windows/wddm/wddm.cpp index 4a1d4e4f8c..51c08cbcb6 100644 --- a/shared/source/os_interface/windows/wddm/wddm.cpp +++ b/shared/source/os_interface/windows/wddm/wddm.cpp @@ -446,6 +446,7 @@ std::vector> Wddm::discoverDevices(ExecutionEnvironm return {}; } + executionEnvironment.setDevicePermissionError(false); auto adapterFactory = AdapterFactory::create(Wddm::dXCoreCreateAdapterFactory, Wddm::createDxgiFactory); if (false == adapterFactory->isSupported()) { diff --git a/shared/test/common/libult/linux/directory_linux.cpp b/shared/test/common/libult/linux/directory_linux.cpp index a96a7ff1da..f5e6f26bc8 100644 --- a/shared/test/common/libult/linux/directory_linux.cpp +++ b/shared/test/common/libult/linux/directory_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021-2024 Intel Corporation + * Copyright (C) 2021-2025 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -19,11 +19,13 @@ extern bool returnEmptyFilesVector; std::string byPathPattern(std::string(NEO_SHARED_TEST_FILES_DIR) + "/linux/by-path"); std::string deviceDrmPath(std::string(NEO_SHARED_TEST_FILES_DIR) + "/linux/devices/device/drm"); std::map> directoryFilesMap = {}; +int setErrno = 0; std::vector Directory::getFiles(const std::string &path) { std::vector files; if (returnEmptyFilesVector) { + errno = setErrno; return files; } diff --git a/shared/test/unit_test/execution_environment/execution_environment_tests.cpp b/shared/test/unit_test/execution_environment/execution_environment_tests.cpp index 9b5d092fd0..ca432a0e7f 100644 --- a/shared/test/unit_test/execution_environment/execution_environment_tests.cpp +++ b/shared/test/unit_test/execution_environment/execution_environment_tests.cpp @@ -759,6 +759,18 @@ TEST(ExecutionEnvironment, givenExecutionEnvironmentWhenGetErrorDescriptionIsCal EXPECT_EQ(0, strcmp(errorString.c_str(), pStr)); } +TEST(ExecutionEnvironment, givenExecutionEnvironmentWhenSetDevicePermissionErrorIsCalledThenCorrectValueIsReturned) { + MockExecutionEnvironment executionEnvironment; + + EXPECT_FALSE(executionEnvironment.isDevicePermissionError()); + + executionEnvironment.setDevicePermissionError(true); + EXPECT_TRUE(executionEnvironment.isDevicePermissionError()); + + executionEnvironment.setDevicePermissionError(false); + EXPECT_FALSE(executionEnvironment.isDevicePermissionError()); +} + void ExecutionEnvironmentSortTests::SetUp() { executionEnvironment.prepareRootDeviceEnvironments(numRootDevices); for (uint32_t rootDeviceIndex = 0; rootDeviceIndex < numRootDevices; rootDeviceIndex++) { diff --git a/shared/test/unit_test/os_interface/linux/drm_tests.cpp b/shared/test/unit_test/os_interface/linux/drm_tests.cpp index c60b06794b..0b93bb2402 100644 --- a/shared/test/unit_test/os_interface/linux/drm_tests.cpp +++ b/shared/test/unit_test/os_interface/linux/drm_tests.cpp @@ -41,7 +41,9 @@ using namespace NEO; namespace NEO { extern bool returnEmptyFilesVector; -} +extern int setErrno; +extern std::map> directoryFilesMap; +} // namespace NEO std::string getLinuxDevicesPath(const char *file) { std::string resultString(Os::sysFsPciPathPrefix); @@ -1811,6 +1813,186 @@ TEST(DrmTest, GivenDrmWhenDiscoveringDevicesThenCloseOnExecFlagIsPassedToFdOpen) EXPECT_NE(0u, SysCalls::openFuncCalled); } +TEST(DrmTest, GivenAccessDeniedWhenDiscoveringDevicesThenDevicePermissionErrorIsSet) { + SysCalls::openFuncCalled = 0; + VariableBackup openCounter(&SysCalls::openFuncCalled); + VariableBackup mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + errno = EACCES; + return -1; + }); + VariableBackup emptyDir(&NEO::returnEmptyFilesVector, true); + + auto executionEnvironment = std::make_unique(); + + EXPECT_FALSE(executionEnvironment->isDevicePermissionError()); + auto devices = Drm::discoverDevices(*executionEnvironment); + EXPECT_TRUE(executionEnvironment->isDevicePermissionError()); + EXPECT_TRUE(devices.empty()); + EXPECT_NE(0u, SysCalls::openFuncCalled); +} + +TEST(DrmTest, GivenInufficientPermissionsWhenDiscoveringDevicesThenDevicePermissionErrorIsSet) { + SysCalls::openFuncCalled = 0; + VariableBackup openCounter(&SysCalls::openFuncCalled); + VariableBackup mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + errno = EPERM; + return -1; + }); + VariableBackup emptyDir(&NEO::returnEmptyFilesVector, true); + + auto executionEnvironment = std::make_unique(); + + EXPECT_FALSE(executionEnvironment->isDevicePermissionError()); + auto devices = Drm::discoverDevices(*executionEnvironment); + EXPECT_TRUE(executionEnvironment->isDevicePermissionError()); + EXPECT_TRUE(devices.empty()); + EXPECT_NE(0u, SysCalls::openFuncCalled); +} + +TEST(DrmTest, GivenOtherErrorWhenDiscoveringDevicesThenDevicePermissionErrorIsNotSet) { + SysCalls::openFuncCalled = 0; + VariableBackup openCounter(&SysCalls::openFuncCalled); + VariableBackup mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + errno = ENOENT; + return -1; + }); + VariableBackup emptyDir(&NEO::returnEmptyFilesVector, true); + + auto executionEnvironment = std::make_unique(); + + EXPECT_FALSE(executionEnvironment->isDevicePermissionError()); + auto devices = Drm::discoverDevices(*executionEnvironment); + EXPECT_FALSE(executionEnvironment->isDevicePermissionError()); + EXPECT_TRUE(devices.empty()); + EXPECT_NE(0u, SysCalls::openFuncCalled); +} + +TEST(DrmTest, GivenAccessDeniedWithNonEmptyFilesListWhenDiscoveringDevicesThenDevicePermissionErrorIsSet) { + SysCalls::openFuncCalled = 0; + VariableBackup openCounter(&SysCalls::openFuncCalled); + VariableBackup mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + errno = EACCES; + return -1; + }); + + NEO::directoryFilesMap.insert({"/dev/dri/by-path/pci-0000:00:01.0-render", {"unknown"}}); + NEO::directoryFilesMap.insert({"/dev/dri/by-path/pci-0000:00:02.0-render", {"unknown"}}); + NEO::directoryFilesMap.insert({"/dev/dri/by-path/pci-0000:00:03.0-render", {"unknown"}}); + + auto executionEnvironment = std::make_unique(); + + EXPECT_FALSE(executionEnvironment->isDevicePermissionError()); + auto devices = Drm::discoverDevices(*executionEnvironment); + EXPECT_TRUE(executionEnvironment->isDevicePermissionError()); + EXPECT_TRUE(devices.empty()); + EXPECT_NE(0u, SysCalls::openFuncCalled); + + NEO::directoryFilesMap.clear(); +} + +TEST(DrmTest, GivenInufficientPermissionsWithNonEmptyFilesListWhenDiscoveringDevicesThenDevicePermissionErrorIsSet) { + SysCalls::openFuncCalled = 0; + VariableBackup openCounter(&SysCalls::openFuncCalled); + VariableBackup mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + errno = EPERM; + return -1; + }); + + NEO::directoryFilesMap.insert({"/dev/dri/by-path/pci-0000:00:01.0-render", {"unknown"}}); + NEO::directoryFilesMap.insert({"/dev/dri/by-path/pci-0000:00:02.0-render", {"unknown"}}); + NEO::directoryFilesMap.insert({"/dev/dri/by-path/pci-0000:00:03.0-render", {"unknown"}}); + + auto executionEnvironment = std::make_unique(); + + EXPECT_FALSE(executionEnvironment->isDevicePermissionError()); + auto devices = Drm::discoverDevices(*executionEnvironment); + EXPECT_TRUE(executionEnvironment->isDevicePermissionError()); + EXPECT_TRUE(devices.empty()); + EXPECT_NE(0u, SysCalls::openFuncCalled); + + NEO::directoryFilesMap.clear(); +} + +TEST(DrmTest, GivenOtherErrorWithNonEmptyFilesListWhenDiscoveringDevicesThenDevicePermissionErrorIsNotSet) { + SysCalls::openFuncCalled = 0; + VariableBackup openCounter(&SysCalls::openFuncCalled); + VariableBackup mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + errno = ENOENT; + return -1; + }); + + NEO::directoryFilesMap.insert({"/dev/dri/by-path/pci-0000:00:01.0-render", {"unknown"}}); + NEO::directoryFilesMap.insert({"/dev/dri/by-path/pci-0000:00:02.0-render", {"unknown"}}); + NEO::directoryFilesMap.insert({"/dev/dri/by-path/pci-0000:00:03.0-render", {"unknown"}}); + + auto executionEnvironment = std::make_unique(); + + EXPECT_FALSE(executionEnvironment->isDevicePermissionError()); + auto devices = Drm::discoverDevices(*executionEnvironment); + EXPECT_FALSE(executionEnvironment->isDevicePermissionError()); + EXPECT_TRUE(devices.empty()); + EXPECT_NE(0u, SysCalls::openFuncCalled); + + NEO::directoryFilesMap.clear(); +} + +TEST(DrmTest, GivenAccessDeniedForDirectoryWhenDiscoveringDevicesThenDevicePermissionErrorIsSet) { + SysCalls::openFuncCalled = 0; + VariableBackup openCounter(&SysCalls::openFuncCalled); + VariableBackup mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + errno = ENOENT; + return -1; + }); + VariableBackup emptyDir(&NEO::returnEmptyFilesVector, true); + VariableBackup errnoNumber(&NEO::setErrno, EACCES); + + auto executionEnvironment = std::make_unique(); + + EXPECT_FALSE(executionEnvironment->isDevicePermissionError()); + auto devices = Drm::discoverDevices(*executionEnvironment); + EXPECT_TRUE(executionEnvironment->isDevicePermissionError()); + EXPECT_TRUE(devices.empty()); + EXPECT_NE(0u, SysCalls::openFuncCalled); +} + +TEST(DrmTest, GivenInufficientPermissionsForDirectoryWhenDiscoveringDevicesThenDevicePermissionErrorIsSet) { + SysCalls::openFuncCalled = 0; + VariableBackup openCounter(&SysCalls::openFuncCalled); + VariableBackup mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + errno = ENOENT; + return -1; + }); + VariableBackup emptyDir(&NEO::returnEmptyFilesVector, true); + VariableBackup errnoNumber(&NEO::setErrno, EPERM); + + auto executionEnvironment = std::make_unique(); + + EXPECT_FALSE(executionEnvironment->isDevicePermissionError()); + auto devices = Drm::discoverDevices(*executionEnvironment); + EXPECT_TRUE(executionEnvironment->isDevicePermissionError()); + EXPECT_TRUE(devices.empty()); + EXPECT_NE(0u, SysCalls::openFuncCalled); +} + +TEST(DrmTest, GivenOtherErrorForDirectoryWhenDiscoveringDevicesThenDevicePermissionErrorIsNotSet) { + SysCalls::openFuncCalled = 0; + VariableBackup openCounter(&SysCalls::openFuncCalled); + VariableBackup mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + errno = ENOENT; + return -1; + }); + VariableBackup emptyDir(&NEO::returnEmptyFilesVector, true); + VariableBackup errnoNumber(&NEO::setErrno, ENOENT); + + auto executionEnvironment = std::make_unique(); + + EXPECT_FALSE(executionEnvironment->isDevicePermissionError()); + auto devices = Drm::discoverDevices(*executionEnvironment); + EXPECT_FALSE(executionEnvironment->isDevicePermissionError()); + EXPECT_TRUE(devices.empty()); + EXPECT_NE(0u, SysCalls::openFuncCalled); +} + TEST(DrmWrapperTest, WhenGettingDrmIoctlVersionValueThenIoctlHelperIsNotNeeded) { EXPECT_EQ(getIoctlRequestValue(DrmIoctl::version, nullptr), static_cast(DRM_IOCTL_VERSION)); } diff --git a/shared/test/unit_test/os_interface/wddm_linux/CMakeLists.txt b/shared/test/unit_test/os_interface/wddm_linux/CMakeLists.txt index 3bd362e884..6187cd6103 100644 --- a/shared/test/unit_test/os_interface/wddm_linux/CMakeLists.txt +++ b/shared/test/unit_test/os_interface/wddm_linux/CMakeLists.txt @@ -9,6 +9,7 @@ if(UNIX AND NOT DISABLE_WDDM_LINUX) ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt ${CMAKE_CURRENT_SOURCE_DIR}/configure_device_address_space_drm_or_wddm_test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ccs_mode_drm_or_wddm_test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/drm_or_wddm_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/wddm32_tests_extra.cpp ) endif() diff --git a/shared/test/unit_test/os_interface/wddm_linux/drm_or_wddm_tests.cpp b/shared/test/unit_test/os_interface/wddm_linux/drm_or_wddm_tests.cpp new file mode 100644 index 0000000000..cda361d95e --- /dev/null +++ b/shared/test/unit_test/os_interface/wddm_linux/drm_or_wddm_tests.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2025 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/source/os_interface/os_interface.h" +#include "shared/test/common/helpers/variable_backup.h" +#include "shared/test/common/mocks/mock_execution_environment.h" +#include "shared/test/common/os_interface/linux/sys_calls_linux_ult.h" + +#include "gtest/gtest.h" + +using namespace NEO; + +namespace NEO { +extern bool returnEmptyFilesVector; +extern int setErrno; +extern std::map> directoryFilesMap; +} // namespace NEO + +TEST(DrmOrWddmTest, GivenAccessDeniedWhenDiscoveringDevicesThenDevicePermissionErrorIsNotSet) { + SysCalls::openFuncCalled = 0; + VariableBackup openCounter(&SysCalls::openFuncCalled); + VariableBackup mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + errno = EACCES; + return -1; + }); + VariableBackup emptyDir(&NEO::returnEmptyFilesVector, true); + + auto executionEnvironment = std::make_unique(); + + EXPECT_FALSE(executionEnvironment->isDevicePermissionError()); + auto devices = OSInterface::discoverDevices(*executionEnvironment); + EXPECT_FALSE(executionEnvironment->isDevicePermissionError()); + EXPECT_FALSE(devices.empty()); + EXPECT_NE(0u, SysCalls::openFuncCalled); +} + +TEST(DrmOrWddmTest, GivenInufficientPermissionsWhenDiscoveringDevicesThenDevicePermissionErrorIsNotSet) { + SysCalls::openFuncCalled = 0; + VariableBackup openCounter(&SysCalls::openFuncCalled); + VariableBackup mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + errno = EPERM; + return -1; + }); + VariableBackup emptyDir(&NEO::returnEmptyFilesVector, true); + + auto executionEnvironment = std::make_unique(); + + EXPECT_FALSE(executionEnvironment->isDevicePermissionError()); + auto devices = OSInterface::discoverDevices(*executionEnvironment); + EXPECT_FALSE(executionEnvironment->isDevicePermissionError()); + EXPECT_FALSE(devices.empty()); + EXPECT_NE(0u, SysCalls::openFuncCalled); +} + +TEST(DrmOrWddmTest, GivenOtherErrorWhenDiscoveringDevicesThenDevicePermissionErrorIsNotSet) { + SysCalls::openFuncCalled = 0; + VariableBackup openCounter(&SysCalls::openFuncCalled); + VariableBackup mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + errno = ENOENT; + return -1; + }); + VariableBackup emptyDir(&NEO::returnEmptyFilesVector, true); + + auto executionEnvironment = std::make_unique(); + + EXPECT_FALSE(executionEnvironment->isDevicePermissionError()); + auto devices = OSInterface::discoverDevices(*executionEnvironment); + EXPECT_FALSE(executionEnvironment->isDevicePermissionError()); + EXPECT_FALSE(devices.empty()); + EXPECT_NE(0u, SysCalls::openFuncCalled); +} + +TEST(DrmOrWddmTest, GivenAccessDeniedWithNonEmptyFilesListWhenDiscoveringDevicesThenDevicePermissionErrorIsNotSet) { + SysCalls::openFuncCalled = 0; + VariableBackup openCounter(&SysCalls::openFuncCalled); + VariableBackup mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + errno = EACCES; + return -1; + }); + + NEO::directoryFilesMap.insert({"/dev/dri/by-path/pci-0000:00:01.0-render", {"unknown"}}); + NEO::directoryFilesMap.insert({"/dev/dri/by-path/pci-0000:00:02.0-render", {"unknown"}}); + NEO::directoryFilesMap.insert({"/dev/dri/by-path/pci-0000:00:03.0-render", {"unknown"}}); + + auto executionEnvironment = std::make_unique(); + + EXPECT_FALSE(executionEnvironment->isDevicePermissionError()); + auto devices = OSInterface::discoverDevices(*executionEnvironment); + EXPECT_FALSE(executionEnvironment->isDevicePermissionError()); + EXPECT_FALSE(devices.empty()); + EXPECT_NE(0u, SysCalls::openFuncCalled); + + NEO::directoryFilesMap.clear(); +} + +TEST(DrmOrWddmTest, GivenInufficientPermissionsWithNonEmptyFilesListWhenDiscoveringDevicesThenDevicePermissionErrorIsNotSet) { + SysCalls::openFuncCalled = 0; + VariableBackup openCounter(&SysCalls::openFuncCalled); + VariableBackup mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + errno = EPERM; + return -1; + }); + + NEO::directoryFilesMap.insert({"/dev/dri/by-path/pci-0000:00:01.0-render", {"unknown"}}); + NEO::directoryFilesMap.insert({"/dev/dri/by-path/pci-0000:00:02.0-render", {"unknown"}}); + NEO::directoryFilesMap.insert({"/dev/dri/by-path/pci-0000:00:03.0-render", {"unknown"}}); + + auto executionEnvironment = std::make_unique(); + + EXPECT_FALSE(executionEnvironment->isDevicePermissionError()); + auto devices = OSInterface::discoverDevices(*executionEnvironment); + EXPECT_FALSE(executionEnvironment->isDevicePermissionError()); + EXPECT_FALSE(devices.empty()); + EXPECT_NE(0u, SysCalls::openFuncCalled); + + NEO::directoryFilesMap.clear(); +} + +TEST(DrmOrWddmTest, GivenAccessDeniedForDirectoryWhenDiscoveringDevicesThenDevicePermissionErrorIsNotSet) { + SysCalls::openFuncCalled = 0; + VariableBackup openCounter(&SysCalls::openFuncCalled); + VariableBackup mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + errno = ENOENT; + return -1; + }); + VariableBackup emptyDir(&NEO::returnEmptyFilesVector, true); + VariableBackup errnoNumber(&NEO::setErrno, EACCES); + + auto executionEnvironment = std::make_unique(); + + EXPECT_FALSE(executionEnvironment->isDevicePermissionError()); + auto devices = OSInterface::discoverDevices(*executionEnvironment); + EXPECT_FALSE(executionEnvironment->isDevicePermissionError()); + EXPECT_FALSE(devices.empty()); + EXPECT_NE(0u, SysCalls::openFuncCalled); +} + +TEST(DrmOrWddmTest, GivenInufficientPermissionsForDirectoryWhenDiscoveringDevicesThenDevicePermissionErrorIsNotSet) { + SysCalls::openFuncCalled = 0; + VariableBackup openCounter(&SysCalls::openFuncCalled); + VariableBackup mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + errno = ENOENT; + return -1; + }); + VariableBackup emptyDir(&NEO::returnEmptyFilesVector, true); + VariableBackup errnoNumber(&NEO::setErrno, EPERM); + + auto executionEnvironment = std::make_unique(); + + EXPECT_FALSE(executionEnvironment->isDevicePermissionError()); + auto devices = OSInterface::discoverDevices(*executionEnvironment); + EXPECT_FALSE(executionEnvironment->isDevicePermissionError()); + EXPECT_FALSE(devices.empty()); + EXPECT_NE(0u, SysCalls::openFuncCalled); +} \ No newline at end of file