diff --git a/scripts/templates/ze_loader_internal.h.mako b/scripts/templates/ze_loader_internal.h.mako index 0f96fbee..29b601d0 100644 --- a/scripts/templates/ze_loader_internal.h.mako +++ b/scripts/templates/ze_loader_internal.h.mako @@ -47,6 +47,7 @@ namespace loader ZEL_DRIVER_TYPE_INTEGRATED_GPU = 2, ///< The driver has Integrated GPUs only ZEL_DRIVER_TYPE_MIXED = 3, ///< The driver has Heterogenous driver types not limited to GPU or NPU. ZEL_DRIVER_TYPE_OTHER = 4, ///< The driver has No GPU Devices and has other device types only + ZEL_DRIVER_TYPE_NPU = 5, ///< The driver has NPU devices only ZEL_DRIVER_TYPE_FORCE_UINT32 = 0x7fffffff } zel_driver_type_t; @@ -114,6 +115,7 @@ namespace loader ze_result_t init_driver(driver_t &driver, ze_init_flags_t flags, ze_init_driver_type_desc_t* desc, ze_global_dditable_t *globalInitStored, zes_global_dditable_t *sysmanGlobalInitStored, bool sysmanOnly); void add_loader_version(); bool driverSorting(driver_vector_t *drivers, ze_init_driver_type_desc_t* desc, bool sysmanOnly); + void driverOrdering(driver_vector_t *drivers); ~context_t(); bool intercept_enabled = false; bool debugTraceEnabled = false; diff --git a/source/loader/ze_loader.cpp b/source/loader/ze_loader.cpp index 9ffd2714..fae2bcaa 100644 --- a/source/loader/ze_loader.cpp +++ b/source/loader/ze_loader.cpp @@ -5,7 +5,7 @@ * SPDX-License-Identifier: MIT * */ -#include "ze_loader_internal.h" +#include "ze_loader_utils.h" #include "driver_discovery.h" #include @@ -72,6 +72,179 @@ namespace loader return a.driverType < b.driverType; } + void context_t::driverOrdering(driver_vector_t *drivers) { + std::string orderStr = getenv_string("ZEL_DRIVERS_ORDER"); + if (orderStr.empty()) { + return; // No ordering specified + } + + std::vector specs = parseDriverOrder(orderStr); + + if (specs.empty()) { + if (debugTraceEnabled) { + std::string message = "driverOrdering: ZEL_DRIVERS_ORDER parsing failed or empty: " + orderStr; + debug_trace_message(message, ""); + } + return; + } + + if (debugTraceEnabled) { + std::string message = "driverOrdering:ZEL_DRIVERS_ORDER parsing successful: " + orderStr + ", specs count: " + std::to_string(specs.size()); + debug_trace_message(message, ""); + } + + // Create a copy of the original driver vector for reference + driver_vector_t originalDrivers = *drivers; + + driver_vector_t discreteGPUDrivers; + driver_vector_t integratedGPUDrivers; + driver_vector_t npuDrivers; + driver_vector_t gpuDrivers; + + std::vector discreteGPUIndices; + std::vector integratedGPUIndices; + std::vector npuIndices; + std::vector gpuIndices; + + // Group drivers by type and track their original indices + for (uint32_t i = 0; i < originalDrivers.size(); ++i) { + const auto& driver = originalDrivers[i]; + switch (driver.driverType) { + case ZEL_DRIVER_TYPE_DISCRETE_GPU: + discreteGPUDrivers.push_back(driver); + discreteGPUIndices.push_back(i); + break; + case ZEL_DRIVER_TYPE_INTEGRATED_GPU: + integratedGPUDrivers.push_back(driver); + integratedGPUIndices.push_back(i); + break; + case ZEL_DRIVER_TYPE_GPU: + gpuDrivers.push_back(driver); + gpuIndices.push_back(i); + break; + case ZEL_DRIVER_TYPE_NPU: + npuDrivers.push_back(driver); + npuIndices.push_back(i); + break; + case ZEL_DRIVER_TYPE_OTHER: + npuDrivers.push_back(driver); + npuIndices.push_back(i); + break; + case ZEL_DRIVER_TYPE_MIXED: + // Mixed drivers go to gpuDrivers + gpuDrivers.push_back(driver); + gpuIndices.push_back(i); + break; + default: + break; + } + } + + // Create new ordered driver vector + driver_vector_t orderedDrivers; + std::set usedGlobalIndices; + std::set> usedTypeIndices; + + // Apply ordering specifications + for (const auto& spec : specs) { + switch (spec.type) { + case DriverOrderSpecType::BY_GLOBAL_INDEX: + if (spec.globalIndex < originalDrivers.size() && + usedGlobalIndices.find(spec.globalIndex) == usedGlobalIndices.end()) { + orderedDrivers.push_back(originalDrivers[spec.globalIndex]); + usedGlobalIndices.insert(spec.globalIndex); + } + break; + + case DriverOrderSpecType::BY_TYPE: + // Add all drivers of this type that haven't been used + { + std::vector* typeIndices = nullptr; + switch (spec.driverType) { + case ZEL_DRIVER_TYPE_DISCRETE_GPU: + typeIndices = &discreteGPUIndices; + break; + case ZEL_DRIVER_TYPE_INTEGRATED_GPU: + typeIndices = &integratedGPUIndices; + break; + case ZEL_DRIVER_TYPE_GPU: + typeIndices = &gpuIndices; + break; + case ZEL_DRIVER_TYPE_NPU: + case ZEL_DRIVER_TYPE_OTHER: + typeIndices = &npuIndices; + break; + default: + break; + } + + if (typeIndices) { + for (uint32_t globalIdx : *typeIndices) { + if (usedGlobalIndices.find(globalIdx) == usedGlobalIndices.end()) { + orderedDrivers.push_back(originalDrivers[globalIdx]); + usedGlobalIndices.insert(globalIdx); + } + } + } + } + break; + + case DriverOrderSpecType::BY_TYPE_AND_INDEX: + { + std::vector* typeIndices = nullptr; + switch (spec.driverType) { + case ZEL_DRIVER_TYPE_DISCRETE_GPU: + typeIndices = &discreteGPUIndices; + break; + case ZEL_DRIVER_TYPE_INTEGRATED_GPU: + typeIndices = &integratedGPUIndices; + break; + case ZEL_DRIVER_TYPE_GPU: + typeIndices = &gpuIndices; + break; + case ZEL_DRIVER_TYPE_NPU: + case ZEL_DRIVER_TYPE_OTHER: + typeIndices = &npuIndices; + break; + default: + break; + } + + if (typeIndices && spec.typeIndex < typeIndices->size()) { + auto typeIndexPair = std::make_pair(spec.driverType, spec.typeIndex); + if (usedTypeIndices.find(typeIndexPair) == usedTypeIndices.end()) { + uint32_t globalIdx = (*typeIndices)[spec.typeIndex]; + if (usedGlobalIndices.find(globalIdx) == usedGlobalIndices.end()) { + orderedDrivers.push_back(originalDrivers[globalIdx]); + usedGlobalIndices.insert(globalIdx); + usedTypeIndices.insert(typeIndexPair); + } + } + } + } + break; + } + } + + // Add remaining drivers in their original order + for (uint32_t i = 0; i < originalDrivers.size(); ++i) { + if (usedGlobalIndices.find(i) == usedGlobalIndices.end()) { + orderedDrivers.push_back(originalDrivers[i]); + } + } + + // Replace the original driver vector with the ordered one + *drivers = orderedDrivers; + + if (debugTraceEnabled) { + std::string message = "driverOrdering: Drivers after ZEL_DRIVERS_ORDER:"; + for (uint32_t i = 0; i < drivers->size(); ++i) { + message += "\n[" + std::to_string(i) + "] Driver Type: " + std::to_string((*drivers)[i].driverType) + " Driver Name: " + (*drivers)[i].name; + } + debug_trace_message(message, ""); + } + } + bool context_t::driverSorting(driver_vector_t *drivers, ze_init_driver_type_desc_t* desc, bool sysmanOnly) { ze_init_driver_type_desc_t permissiveDesc = {}; permissiveDesc.stype = ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC; @@ -246,6 +419,10 @@ namespace loader } debug_trace_message(message, ""); } + + // Apply driver ordering based on ZEL_DRIVERS_ORDER environment variable + driverOrdering(drivers); + return true; } @@ -577,7 +754,7 @@ namespace loader GET_FUNCTION_PTR(validationLayer, "zelLoaderGetVersion")); zel_component_version_t compVersion; if(getVersion && ZE_RESULT_SUCCESS == getVersion(&compVersion)) - { + { compVersions.push_back(compVersion); } } else if (debugTraceEnabled) { @@ -602,7 +779,7 @@ namespace loader GET_FUNCTION_PTR(tracingLayer, "zelLoaderGetVersion")); zel_component_version_t compVersion; if(getVersion && ZE_RESULT_SUCCESS == getVersion(&compVersion)) - { + { compVersions.push_back(compVersion); } } else if (debugTraceEnabled) { diff --git a/source/loader/ze_loader_internal.h b/source/loader/ze_loader_internal.h index 1ce407f2..12f66fc1 100644 --- a/source/loader/ze_loader_internal.h +++ b/source/loader/ze_loader_internal.h @@ -38,6 +38,7 @@ namespace loader ZEL_DRIVER_TYPE_INTEGRATED_GPU = 2, ///< The driver has Integrated GPUs only ZEL_DRIVER_TYPE_MIXED = 3, ///< The driver has Heterogenous driver types not limited to GPU or NPU. ZEL_DRIVER_TYPE_OTHER = 4, ///< The driver has No GPU Devices and has other device types only + ZEL_DRIVER_TYPE_NPU = 5, ///< The driver has NPU devices only ZEL_DRIVER_TYPE_FORCE_UINT32 = 0x7fffffff } zel_driver_type_t; @@ -150,6 +151,7 @@ namespace loader ze_result_t init_driver(driver_t &driver, ze_init_flags_t flags, ze_init_driver_type_desc_t* desc, ze_global_dditable_t *globalInitStored, zes_global_dditable_t *sysmanGlobalInitStored, bool sysmanOnly); void add_loader_version(); bool driverSorting(driver_vector_t *drivers, ze_init_driver_type_desc_t* desc, bool sysmanOnly); + void driverOrdering(driver_vector_t *drivers); ~context_t(); bool intercept_enabled = false; bool debugTraceEnabled = false; diff --git a/source/loader/ze_loader_utils.h b/source/loader/ze_loader_utils.h new file mode 100644 index 00000000..6f6eb9d7 --- /dev/null +++ b/source/loader/ze_loader_utils.h @@ -0,0 +1,108 @@ +/* + * + * Copyright (C) 2025 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ +#pragma once +#include "ze_loader_internal.h" +#include +#include +#include +#include +#include +#include +#include + + +namespace loader +{ + // Helper function to map driver type string to enum + inline zel_driver_type_t stringToDriverType(const std::string& typeStr) { + if (typeStr == "DISCRETE_GPU_ONLY") { + return ZEL_DRIVER_TYPE_DISCRETE_GPU; + } else if (typeStr == "GPU") { + return ZEL_DRIVER_TYPE_GPU; + } else if (typeStr == "INTEGRATED_GPU_ONLY") { + return ZEL_DRIVER_TYPE_INTEGRATED_GPU; + } else if (typeStr == "NPU") { + return ZEL_DRIVER_TYPE_NPU; + } + return ZEL_DRIVER_TYPE_FORCE_UINT32; // Invalid + } + + // Helper function to trim whitespace + inline std::string trim(const std::string& str) { + const std::string whitespace = " \t\n\r\f\v"; + size_t start = str.find_first_not_of(whitespace); + if (start == std::string::npos) return ""; + size_t end = str.find_last_not_of(whitespace); + return str.substr(start, end - start + 1); + } + + enum DriverOrderSpecType { BY_GLOBAL_INDEX, BY_TYPE, BY_TYPE_AND_INDEX }; + + // Structure to hold parsed ordering instructions + struct DriverOrderSpec { + DriverOrderSpecType type; + uint32_t globalIndex = 0; + zel_driver_type_t driverType = ZEL_DRIVER_TYPE_FORCE_UINT32; + uint32_t typeIndex = 0; + }; + + // Parse ZEL_DRIVERS_ORDER environment variable + inline std::vector parseDriverOrder(const std::string& orderStr) { + std::vector specs; + + // Split by comma + std::vector tokens; + std::stringstream ss(orderStr); + std::string token; + + while (std::getline(ss, token, ',')) { + token = trim(token); + if (token.empty()) continue; + + DriverOrderSpec spec; + + // Check if it contains a colon (type:index format) + size_t colonPos = token.find(':'); + if (colonPos != std::string::npos) { + // Format: : + std::string typeStr = trim(token.substr(0, colonPos)); + std::string indexStr = trim(token.substr(colonPos + 1)); + + spec.driverType = stringToDriverType(typeStr); + if (spec.driverType == ZEL_DRIVER_TYPE_FORCE_UINT32) { + continue; // Invalid driver type, skip + } + + try { + spec.typeIndex = std::stoul(indexStr); + spec.type = DriverOrderSpecType::BY_TYPE_AND_INDEX; + specs.push_back(spec); + } catch (const std::exception&) { + // Invalid index, skip + continue; + } + } else { + // Check if it's a pure number (global index) or driver type + try { + spec.globalIndex = std::stoul(token); + spec.type = DriverOrderSpecType::BY_GLOBAL_INDEX; + specs.push_back(spec); + } catch (const std::exception&) { + // Not a number, try as driver type + spec.driverType = stringToDriverType(token); + if (spec.driverType != ZEL_DRIVER_TYPE_FORCE_UINT32) { + spec.type = DriverOrderSpecType::BY_TYPE; + specs.push_back(spec); + } + } + } + } + + return specs; + } +} // namespace loader \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d6fc1dba..6683b030 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -5,14 +5,68 @@ add_executable( tests loader_api.cpp loader_validation_layer.cpp + driver_ordering_helper_tests.cpp ) -target_include_directories(tests PRIVATE ${CMAKE_SOURCE_DIR}/include) + +# Only include driver_ordering_unit_tests for static builds or non-Windows platforms +# as it requires internal loader symbols that are not exported in Windows DLLs +if(BUILD_STATIC OR NOT WIN32) + target_sources(tests PRIVATE driver_ordering_unit_tests.cpp) +endif() + +# For static builds, we need to include the loader source files directly +# since they are not built into the library when BUILD_STATIC=1 +if(BUILD_STATIC) + target_sources(tests PRIVATE + ${CMAKE_SOURCE_DIR}/source/loader/ze_loader.cpp + ${CMAKE_SOURCE_DIR}/source/loader/ze_loader_api.cpp + ${CMAKE_SOURCE_DIR}/source/loader/ze_ldrddi.cpp + ${CMAKE_SOURCE_DIR}/source/loader/ze_ldrddi_driver_ddi.cpp + ${CMAKE_SOURCE_DIR}/source/loader/zet_ldrddi.cpp + ${CMAKE_SOURCE_DIR}/source/loader/zet_ldrddi_driver_ddi.cpp + ${CMAKE_SOURCE_DIR}/source/loader/zes_ldrddi.cpp + ${CMAKE_SOURCE_DIR}/source/loader/zes_ldrddi_driver_ddi.cpp + ${CMAKE_SOURCE_DIR}/source/loader/zel_tracing_ldrddi.cpp + ) + + # Platform-specific source files + if(WIN32) + target_sources(tests PRIVATE + ${CMAKE_SOURCE_DIR}/source/loader/windows/driver_discovery_win.cpp + ${CMAKE_SOURCE_DIR}/source/loader/windows/loader_init.cpp + ) + else() + target_sources(tests PRIVATE + ${CMAKE_SOURCE_DIR}/source/loader/linux/driver_discovery_lin.cpp + ${CMAKE_SOURCE_DIR}/source/loader/linux/loader_init.cpp + ) + endif() + + # Add the same definitions as the source CMakeLists.txt + target_compile_definitions(tests PRIVATE + L0_LOADER_VERSION="${PROJECT_VERSION_MAJOR}" + L0_VALIDATION_LAYER_SUPPORTED_VERSION="${PROJECT_VERSION_MAJOR}" + L0_STATIC_LOADER_BUILD="1" + ) +endif() + +target_include_directories(tests PRIVATE ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/source/inc) target_link_libraries( tests + PRIVATE GTest::gtest_main ${TARGET_LOADER_NAME} + level_zero_utils ) +# For static builds, we need additional system libraries +if(BUILD_STATIC) + target_link_libraries(tests PRIVATE ${CMAKE_DL_LIBS}) + if(UNIX AND NOT APPLE) + target_link_libraries(tests PRIVATE pthread) + endif() +endif() + add_test(NAME tests_api COMMAND tests --gtest_filter=*GivenLevelZeroLoaderPresentWhenCallingzeGetLoaderVersionsAPIThenValidVersionIsReturned*) set_property(TEST tests_api PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1") add_test(NAME tests_init_gpu_all COMMAND tests --gtest_filter=*GivenLevelZeroLoaderPresentWhenCallingZeInitDriversWithGPUTypeThenExpectPassWithGPUorAllOnly*) @@ -335,6 +389,213 @@ else() set_property(TEST tests_multi_driver_sysman_vf_management_api APPEND PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/lib/libze_null_test1.so,${CMAKE_BINARY_DIR}/lib/libze_null_test2.so") endif() +# Driver ordering tests - each test added individually +add_test(NAME tests_driver_ordering_specific_type_and_index COMMAND tests --gtest_filter=*GivenZelDriversOrderWithSpecificTypeAndIndexWhenCallingZeInitDriversThenDriversAreOrderedCorrectly) +if (MSVC) + set_property(TEST tests_driver_ordering_specific_type_and_index PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/bin/$/ze_null_test1.dll,${CMAKE_BINARY_DIR}/bin/$/ze_null_test2.dll") +else() + set_property(TEST tests_driver_ordering_specific_type_and_index PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/lib/libze_null_test1.so,${CMAKE_BINARY_DIR}/lib/libze_null_test2.so") +endif() + +add_test(NAME tests_driver_ordering_gpu_type_and_index COMMAND tests --gtest_filter=*GivenZelDriversOrderWithGpuTypeAndIndexWhenCallingZeInitDriversThenDriversAreOrderedCorrectly) +if (MSVC) + set_property(TEST tests_driver_ordering_gpu_type_and_index PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/bin/$/ze_null_test1.dll,${CMAKE_BINARY_DIR}/bin/$/ze_null_test2.dll") +else() + set_property(TEST tests_driver_ordering_gpu_type_and_index PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/lib/libze_null_test1.so,${CMAKE_BINARY_DIR}/lib/libze_null_test2.so") +endif() + +add_test(NAME tests_driver_ordering_integrated_gpu_type_and_index COMMAND tests --gtest_filter=*GivenZelDriversOrderWithIntegratedGpuTypeAndIndexWhenCallingZeInitDriversThenDriversAreOrderedCorrectly) +if (MSVC) + set_property(TEST tests_driver_ordering_integrated_gpu_type_and_index PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/bin/$/ze_null_test1.dll,${CMAKE_BINARY_DIR}/bin/$/ze_null_test2.dll") +else() + set_property(TEST tests_driver_ordering_integrated_gpu_type_and_index PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/lib/libze_null_test1.so,${CMAKE_BINARY_DIR}/lib/libze_null_test2.so") +endif() + +add_test(NAME tests_driver_ordering_npu_type_and_index COMMAND tests --gtest_filter=*GivenZelDriversOrderWithNpuTypeAndIndexWhenCallingZeInitDriversThenDriversAreOrderedCorrectly) +if (MSVC) + set_property(TEST tests_driver_ordering_npu_type_and_index PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/bin/$/ze_null_test1.dll,${CMAKE_BINARY_DIR}/bin/$/ze_null_test2.dll") +else() + set_property(TEST tests_driver_ordering_npu_type_and_index PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/lib/libze_null_test1.so,${CMAKE_BINARY_DIR}/lib/libze_null_test2.so") +endif() + +add_test(NAME tests_driver_ordering_specific_type_only COMMAND tests --gtest_filter=*GivenZelDriversOrderWithSpecificTypeOnlyWhenCallingZeInitDriversThenDriversAreOrderedCorrectly) +if (MSVC) + set_property(TEST tests_driver_ordering_specific_type_only PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/bin/$/ze_null_test1.dll,${CMAKE_BINARY_DIR}/bin/$/ze_null_test2.dll") +else() + set_property(TEST tests_driver_ordering_specific_type_only PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/lib/libze_null_test1.so,${CMAKE_BINARY_DIR}/lib/libze_null_test2.so") +endif() + +add_test(NAME tests_driver_ordering_gpu_type_only COMMAND tests --gtest_filter=*GivenZelDriversOrderWithGpuTypeOnlyWhenCallingZeInitDriversThenDriversAreOrderedCorrectly) +if (MSVC) + set_property(TEST tests_driver_ordering_gpu_type_only PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/bin/$/ze_null_test1.dll,${CMAKE_BINARY_DIR}/bin/$/ze_null_test2.dll") +else() + set_property(TEST tests_driver_ordering_gpu_type_only PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/lib/libze_null_test1.so,${CMAKE_BINARY_DIR}/lib/libze_null_test2.so") +endif() + +add_test(NAME tests_driver_ordering_integrated_gpu_type_only COMMAND tests --gtest_filter=*GivenZelDriversOrderWithIntegratedGpuTypeOnlyWhenCallingZeInitDriversThenDriversAreOrderedCorrectly) +if (MSVC) + set_property(TEST tests_driver_ordering_integrated_gpu_type_only PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/bin/$/ze_null_test1.dll,${CMAKE_BINARY_DIR}/bin/$/ze_null_test2.dll") +else() + set_property(TEST tests_driver_ordering_integrated_gpu_type_only PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/lib/libze_null_test1.so,${CMAKE_BINARY_DIR}/lib/libze_null_test2.so") +endif() + +add_test(NAME tests_driver_ordering_single_npu_type COMMAND tests --gtest_filter=*GivenZelDriversOrderWithSingleNpuTypeWhenCallingZeInitDriversThenDriversAreOrderedCorrectly) +if (MSVC) + set_property(TEST tests_driver_ordering_single_npu_type PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/bin/$/ze_null_test1.dll,${CMAKE_BINARY_DIR}/bin/$/ze_null_test2.dll") +else() + set_property(TEST tests_driver_ordering_single_npu_type PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/lib/libze_null_test1.so,${CMAKE_BINARY_DIR}/lib/libze_null_test2.so") +endif() + +add_test(NAME tests_driver_ordering_global_index_only COMMAND tests --gtest_filter=*GivenZelDriversOrderWithGlobalIndexOnlyWhenCallingZeInitDriversThenDriversAreOrderedCorrectly) +if (MSVC) + set_property(TEST tests_driver_ordering_global_index_only PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/bin/$/ze_null_test1.dll,${CMAKE_BINARY_DIR}/bin/$/ze_null_test2.dll") +else() + set_property(TEST tests_driver_ordering_global_index_only PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/lib/libze_null_test1.so,${CMAKE_BINARY_DIR}/lib/libze_null_test2.so") +endif() + +add_test(NAME tests_driver_ordering_single_global_index COMMAND tests --gtest_filter=*GivenZelDriversOrderWithSingleGlobalIndexWhenCallingZeInitDriversThenDriversAreOrderedCorrectly) +if (MSVC) + set_property(TEST tests_driver_ordering_single_global_index PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/bin/$/ze_null_test1.dll,${CMAKE_BINARY_DIR}/bin/$/ze_null_test2.dll") +else() + set_property(TEST tests_driver_ordering_single_global_index PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/lib/libze_null_test1.so,${CMAKE_BINARY_DIR}/lib/libze_null_test2.so") +endif() + +add_test(NAME tests_driver_ordering_multiple_global_indices COMMAND tests --gtest_filter=*GivenZelDriversOrderWithMultipleGlobalIndicesWhenCallingZeInitDriversThenDriversAreOrderedCorrectly) +if (MSVC) + set_property(TEST tests_driver_ordering_multiple_global_indices PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/bin/$/ze_null_test1.dll,${CMAKE_BINARY_DIR}/bin/$/ze_null_test2.dll") +else() + set_property(TEST tests_driver_ordering_multiple_global_indices PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/lib/libze_null_test1.so,${CMAKE_BINARY_DIR}/lib/libze_null_test2.so") +endif() + +add_test(NAME tests_driver_ordering_mixed_syntax COMMAND tests --gtest_filter=*GivenZelDriversOrderWithMixedSyntaxWhenCallingZeInitDriversThenDriversAreOrderedCorrectly) +if (MSVC) + set_property(TEST tests_driver_ordering_mixed_syntax PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/bin/$/ze_null_test1.dll,${CMAKE_BINARY_DIR}/bin/$/ze_null_test2.dll") +else() + set_property(TEST tests_driver_ordering_mixed_syntax PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/lib/libze_null_test1.so,${CMAKE_BINARY_DIR}/lib/libze_null_test2.so") +endif() + +add_test(NAME tests_driver_ordering_mixed_type_and_index_syntax COMMAND tests --gtest_filter=*GivenZelDriversOrderWithMixedTypeAndIndexSyntaxWhenCallingZeInitDriversThenDriversAreOrderedCorrectly) +if (MSVC) + set_property(TEST tests_driver_ordering_mixed_type_and_index_syntax PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/bin/$/ze_null_test1.dll,${CMAKE_BINARY_DIR}/bin/$/ze_null_test2.dll") +else() + set_property(TEST tests_driver_ordering_mixed_type_and_index_syntax PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/lib/libze_null_test1.so,${CMAKE_BINARY_DIR}/lib/libze_null_test2.so") +endif() + +add_test(NAME tests_driver_ordering_invalid_driver_type COMMAND tests --gtest_filter=*GivenZelDriversOrderWithInvalidDriverTypeWhenCallingZeInitDriversThenDriversStillInitialize) +if (MSVC) + set_property(TEST tests_driver_ordering_invalid_driver_type PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/bin/$/ze_null_test1.dll,${CMAKE_BINARY_DIR}/bin/$/ze_null_test2.dll") +else() + set_property(TEST tests_driver_ordering_invalid_driver_type PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/lib/libze_null_test1.so,${CMAKE_BINARY_DIR}/lib/libze_null_test2.so") +endif() + +add_test(NAME tests_driver_ordering_invalid_index COMMAND tests --gtest_filter=*GivenZelDriversOrderWithInvalidIndexWhenCallingZeInitDriversThenDriversStillInitialize) +if (MSVC) + set_property(TEST tests_driver_ordering_invalid_index PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/bin/$/ze_null_test1.dll,${CMAKE_BINARY_DIR}/bin/$/ze_null_test2.dll") +else() + set_property(TEST tests_driver_ordering_invalid_index PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/lib/libze_null_test1.so,${CMAKE_BINARY_DIR}/lib/libze_null_test2.so") +endif() + +add_test(NAME tests_driver_ordering_empty_string COMMAND tests --gtest_filter=*GivenZelDriversOrderWithEmptyStringWhenCallingZeInitDriversThenDriversUseDefaultOrder) +if (MSVC) + set_property(TEST tests_driver_ordering_empty_string PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/bin/$/ze_null_test1.dll,${CMAKE_BINARY_DIR}/bin/$/ze_null_test2.dll") +else() + set_property(TEST tests_driver_ordering_empty_string PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/lib/libze_null_test1.so,${CMAKE_BINARY_DIR}/lib/libze_null_test2.so") +endif() + +add_test(NAME tests_driver_ordering_whitespace_and_commas COMMAND tests --gtest_filter=*GivenZelDriversOrderWithWhitespaceAndCommasWhenCallingZeInitDriversThenDriversAreOrderedCorrectly) +if (MSVC) + set_property(TEST tests_driver_ordering_whitespace_and_commas PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/bin/$/ze_null_test1.dll,${CMAKE_BINARY_DIR}/bin/$/ze_null_test2.dll") +else() + set_property(TEST tests_driver_ordering_whitespace_and_commas PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/lib/libze_null_test1.so,${CMAKE_BINARY_DIR}/lib/libze_null_test2.so") +endif() + +add_test(NAME tests_driver_ordering_duplicate_entries COMMAND tests --gtest_filter=*GivenZelDriversOrderWithDuplicateEntriesWhenCallingZeInitDriversThenDriversAreOrderedCorrectly) +if (MSVC) + set_property(TEST tests_driver_ordering_duplicate_entries PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/bin/$/ze_null_test1.dll,${CMAKE_BINARY_DIR}/bin/$/ze_null_test2.dll") +else() + set_property(TEST tests_driver_ordering_duplicate_entries PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/lib/libze_null_test1.so,${CMAKE_BINARY_DIR}/lib/libze_null_test2.so") +endif() + +add_test(NAME tests_driver_ordering_zeinit_compatibility COMMAND tests --gtest_filter=*GivenZelDriversOrderWithzeInitWhenCallingzeInitThenDriversAreOrderedCorrectly) +if (MSVC) + set_property(TEST tests_driver_ordering_zeinit_compatibility PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/bin/$/ze_null_test1.dll,${CMAKE_BINARY_DIR}/bin/$/ze_null_test2.dll") +else() + set_property(TEST tests_driver_ordering_zeinit_compatibility PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/lib/libze_null_test1.so,${CMAKE_BINARY_DIR}/lib/libze_null_test2.so") +endif() + +add_test(NAME tests_driver_ordering_zeinit_and_zeinitdrivers COMMAND tests --gtest_filter=*GivenZelDriversOrderWithzeInitAndzeInitDriversWhenCallingBothThenDriversAreOrderedCorrectly) +if (MSVC) + set_property(TEST tests_driver_ordering_zeinit_and_zeinitdrivers PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/bin/$/ze_null_test1.dll,${CMAKE_BINARY_DIR}/bin/$/ze_null_test2.dll") +else() + set_property(TEST tests_driver_ordering_zeinit_and_zeinitdrivers PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/lib/libze_null_test1.so,${CMAKE_BINARY_DIR}/lib/libze_null_test2.so") +endif() + +add_test(NAME tests_driver_ordering_complex_scenario_example1 COMMAND tests --gtest_filter=*GivenZelDriversOrderWithComplexScenarioLikeDocumentationExample1WhenCallingZeInitDriversThenDriversAreOrderedCorrectly) +if (MSVC) + set_property(TEST tests_driver_ordering_complex_scenario_example1 PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/bin/$/ze_null_test1.dll,${CMAKE_BINARY_DIR}/bin/$/ze_null_test2.dll") +else() + set_property(TEST tests_driver_ordering_complex_scenario_example1 PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/lib/libze_null_test1.so,${CMAKE_BINARY_DIR}/lib/libze_null_test2.so") +endif() + +add_test(NAME tests_driver_ordering_complex_scenario_example3 COMMAND tests --gtest_filter=*GivenZelDriversOrderWithComplexScenarioLikeDocumentationExample3WhenCallingZeInitDriversThenDriversAreOrderedCorrectly) +if (MSVC) + set_property(TEST tests_driver_ordering_complex_scenario_example3 PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/bin/$/ze_null_test1.dll,${CMAKE_BINARY_DIR}/bin/$/ze_null_test2.dll") +else() + set_property(TEST tests_driver_ordering_complex_scenario_example3 PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/lib/libze_null_test1.so,${CMAKE_BINARY_DIR}/lib/libze_null_test2.so") +endif() + +add_test(NAME tests_driver_ordering_all_supported_driver_types COMMAND tests --gtest_filter=*GivenZelDriversOrderWithAllSupportedDriverTypesWhenCallingZeInitDriversThenDriversAreOrderedCorrectly) +if (MSVC) + set_property(TEST tests_driver_ordering_all_supported_driver_types PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/bin/$/ze_null_test1.dll,${CMAKE_BINARY_DIR}/bin/$/ze_null_test2.dll") +else() + set_property(TEST tests_driver_ordering_all_supported_driver_types PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_ALT_DRIVERS=${CMAKE_BINARY_DIR}/lib/libze_null_test1.so,${CMAKE_BINARY_DIR}/lib/libze_null_test2.so") +endif() + +# Driver Ordering Unit Tests +add_test(NAME driver_ordering_unit_tests COMMAND tests --gtest_filter=DriverOrderingUnitTest.*) +set_property(TEST driver_ordering_unit_tests PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1") + +# Individual Driver Ordering Unit Tests for better granular reporting +add_test(NAME driver_ordering_no_env COMMAND tests --gtest_filter=DriverOrderingUnitTest.NoEnvironmentVariable_ShouldNotChangeOrder) +set_property(TEST driver_ordering_no_env PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1") + +add_test(NAME driver_ordering_empty_env COMMAND tests --gtest_filter=DriverOrderingUnitTest.EmptyEnvironmentVariable_ShouldNotChangeOrder) +set_property(TEST driver_ordering_empty_env PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1") + +add_test(NAME driver_ordering_global_index COMMAND tests --gtest_filter=DriverOrderingUnitTest.GlobalIndex_*) +set_property(TEST driver_ordering_global_index PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1") + +add_test(NAME driver_ordering_driver_type COMMAND tests --gtest_filter=DriverOrderingUnitTest.DriverType_*) +set_property(TEST driver_ordering_driver_type PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1") + +add_test(NAME driver_ordering_type_and_index COMMAND tests --gtest_filter=DriverOrderingUnitTest.DriverTypeAndIndex_*) +set_property(TEST driver_ordering_type_and_index PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1") + +add_test(NAME driver_ordering_mixed_syntax COMMAND tests --gtest_filter=DriverOrderingUnitTest.MixedSyntax_*) +set_property(TEST driver_ordering_mixed_syntax PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1") + +add_test(NAME driver_ordering_edge_cases COMMAND tests --gtest_filter=DriverOrderingUnitTest.*Edge*|DriverOrderingUnitTest.*Invalid*|DriverOrderingUnitTest.*Error*) +set_property(TEST driver_ordering_edge_cases PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1") + +add_test(NAME driver_ordering_boundary_conditions COMMAND tests --gtest_filter=DriverOrderingUnitTest.*Boundary*|DriverOrderingUnitTest.*Single*|DriverOrderingUnitTest.*Max*) +set_property(TEST driver_ordering_boundary_conditions PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1") + +# Driver Ordering Helper Function Tests +add_test(NAME driver_ordering_helper_functions COMMAND tests --gtest_filter=DriverOrderingHelperFunctionsTest.*) +set_property(TEST driver_ordering_helper_functions PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1") + +# Individual Helper Function Tests for better granular reporting +add_test(NAME driver_ordering_string_to_driver_type COMMAND tests --gtest_filter=DriverOrderingHelperFunctionsTest.StringToDriverType_*) +set_property(TEST driver_ordering_string_to_driver_type PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1") + +add_test(NAME driver_ordering_trim_function COMMAND tests --gtest_filter=DriverOrderingHelperFunctionsTest.Trim_*) +set_property(TEST driver_ordering_trim_function PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1") + +add_test(NAME driver_ordering_parse_driver_order COMMAND tests --gtest_filter=DriverOrderingHelperFunctionsTest.ParseDriverOrder_*) +set_property(TEST driver_ordering_parse_driver_order PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1") + + + # These tests are currently not supported on Windows. The reason is that the std::cerr is not being redirected to a pipe in Windows to be then checked against the expected output. if(NOT MSVC) add_test(NAME tests_event_deadlock COMMAND tests --gtest_filter=*GivenLevelZeroLoaderPresentWhenCallingzeCommandListAppendMemoryCopyWithCircularDependencyOnEventsThenValidationLayerPrintsWarningOfDeadlock*) diff --git a/test/driver_ordering_helper_tests.cpp b/test/driver_ordering_helper_tests.cpp new file mode 100644 index 00000000..b9aa9654 --- /dev/null +++ b/test/driver_ordering_helper_tests.cpp @@ -0,0 +1,314 @@ +/* + * + * Copyright (C) 2025 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "gtest/gtest.h" + +// To test internal functions, we need to include the implementation +// In a real scenario, these functions might need to be exposed via a test interface +// or moved to a separate testable module + +#include +#include + +// Include the loader types we need +#include "source/loader/ze_loader_internal.h" +#include "source/loader/ze_loader_utils.h" + +/////////////////////////////////////////////////////////////////////////////// +// Unit tests for helper functions +/////////////////////////////////////////////////////////////////////////////// + +class DriverOrderingHelperFunctionsTest : public ::testing::Test { +protected: + void SetUp() override { + // No setup needed for these pure function tests + } + + void TearDown() override { + // No cleanup needed + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// Tests for stringToDriverType function +/////////////////////////////////////////////////////////////////////////////// + +TEST_F(DriverOrderingHelperFunctionsTest, StringToDriverType_ValidTypes_ShouldReturnCorrectEnum) { + // Test all valid driver type strings + EXPECT_EQ(loader::stringToDriverType("DISCRETE_GPU_ONLY"), loader::ZEL_DRIVER_TYPE_DISCRETE_GPU); + EXPECT_EQ(loader::stringToDriverType("GPU"), loader::ZEL_DRIVER_TYPE_GPU); + EXPECT_EQ(loader::stringToDriverType("INTEGRATED_GPU_ONLY"), loader::ZEL_DRIVER_TYPE_INTEGRATED_GPU); + EXPECT_EQ(loader::stringToDriverType("NPU"), loader::ZEL_DRIVER_TYPE_NPU); +} + +TEST_F(DriverOrderingHelperFunctionsTest, StringToDriverType_InvalidTypes_ShouldReturnForceUint32) { + // Test invalid driver type strings + EXPECT_EQ(loader::stringToDriverType("INVALID_TYPE"), loader::ZEL_DRIVER_TYPE_FORCE_UINT32); + EXPECT_EQ(loader::stringToDriverType(""), loader::ZEL_DRIVER_TYPE_FORCE_UINT32); + EXPECT_EQ(loader::stringToDriverType("gpu"), loader::ZEL_DRIVER_TYPE_FORCE_UINT32); // lowercase + EXPECT_EQ(loader::stringToDriverType("discrete_gpu"), loader::ZEL_DRIVER_TYPE_FORCE_UINT32); // wrong format + EXPECT_EQ(loader::stringToDriverType("GPU_ONLY"), loader::ZEL_DRIVER_TYPE_FORCE_UINT32); // wrong suffix +} + +TEST_F(DriverOrderingHelperFunctionsTest, StringToDriverType_CaseSensitivity_ShouldBeStrict) { + // Test case sensitivity + EXPECT_EQ(loader::stringToDriverType("npu"), loader::ZEL_DRIVER_TYPE_FORCE_UINT32); + EXPECT_EQ(loader::stringToDriverType("Npu"), loader::ZEL_DRIVER_TYPE_FORCE_UINT32); + EXPECT_EQ(loader::stringToDriverType("NPu"), loader::ZEL_DRIVER_TYPE_FORCE_UINT32); + EXPECT_EQ(loader::stringToDriverType("discrete_gpu_only"), loader::ZEL_DRIVER_TYPE_FORCE_UINT32); +} + +/////////////////////////////////////////////////////////////////////////////// +// Tests for trim function +/////////////////////////////////////////////////////////////////////////////// + +TEST_F(DriverOrderingHelperFunctionsTest, Trim_NoWhitespace_ShouldReturnOriginal) { + EXPECT_EQ(loader::trim("NPU"), "NPU"); + EXPECT_EQ(loader::trim("DISCRETE_GPU_ONLY"), "DISCRETE_GPU_ONLY"); + EXPECT_EQ(loader::trim("123"), "123"); +} + +TEST_F(DriverOrderingHelperFunctionsTest, Trim_LeadingWhitespace_ShouldRemove) { + EXPECT_EQ(loader::trim(" NPU"), "NPU"); + EXPECT_EQ(loader::trim(" NPU"), "NPU"); + EXPECT_EQ(loader::trim("\tNPU"), "NPU"); + EXPECT_EQ(loader::trim("\nNPU"), "NPU"); + EXPECT_EQ(loader::trim("\r\n NPU"), "NPU"); +} + +TEST_F(DriverOrderingHelperFunctionsTest, Trim_TrailingWhitespace_ShouldRemove) { + EXPECT_EQ(loader::trim("NPU "), "NPU"); + EXPECT_EQ(loader::trim("NPU "), "NPU"); + EXPECT_EQ(loader::trim("NPU\t"), "NPU"); + EXPECT_EQ(loader::trim("NPU\n"), "NPU"); + EXPECT_EQ(loader::trim("NPU \r\n"), "NPU"); +} + +TEST_F(DriverOrderingHelperFunctionsTest, Trim_BothSidesWhitespace_ShouldRemove) { + EXPECT_EQ(loader::trim(" NPU "), "NPU"); + EXPECT_EQ(loader::trim(" NPU "), "NPU"); + EXPECT_EQ(loader::trim("\t NPU \t"), "NPU"); + EXPECT_EQ(loader::trim("\n\r NPU \r\n"), "NPU"); +} + +TEST_F(DriverOrderingHelperFunctionsTest, Trim_OnlyWhitespace_ShouldReturnEmpty) { + EXPECT_EQ(loader::trim(""), ""); + EXPECT_EQ(loader::trim(" "), ""); + EXPECT_EQ(loader::trim(" "), ""); + EXPECT_EQ(loader::trim("\t"), ""); + EXPECT_EQ(loader::trim("\n"), ""); + EXPECT_EQ(loader::trim("\r\n\t "), ""); +} + +TEST_F(DriverOrderingHelperFunctionsTest, Trim_MiddleWhitespace_ShouldKeep) { + EXPECT_EQ(loader::trim("DISCRETE GPU ONLY"), "DISCRETE GPU ONLY"); + EXPECT_EQ(loader::trim(" DISCRETE GPU ONLY "), "DISCRETE GPU ONLY"); +} + +/////////////////////////////////////////////////////////////////////////////// +// Tests for parseDriverOrder function +/////////////////////////////////////////////////////////////////////////////// + +TEST_F(DriverOrderingHelperFunctionsTest, ParseDriverOrder_EmptyString_ShouldReturnEmpty) { + auto specs = loader::parseDriverOrder(""); + EXPECT_TRUE(specs.empty()); +} + +TEST_F(DriverOrderingHelperFunctionsTest, ParseDriverOrder_SingleGlobalIndex_ShouldParseCorrectly) { + auto specs = loader::parseDriverOrder("2"); + ASSERT_EQ(specs.size(), 1); + EXPECT_EQ(specs[0].type, loader::BY_GLOBAL_INDEX); + EXPECT_EQ(specs[0].globalIndex, 2); +} + +TEST_F(DriverOrderingHelperFunctionsTest, ParseDriverOrder_MultipleGlobalIndices_ShouldParseCorrectly) { + auto specs = loader::parseDriverOrder("2,0,1"); + ASSERT_EQ(specs.size(), 3); + + EXPECT_EQ(specs[0].type, loader::BY_GLOBAL_INDEX); + EXPECT_EQ(specs[0].globalIndex, 2); + + EXPECT_EQ(specs[1].type, loader::BY_GLOBAL_INDEX); + EXPECT_EQ(specs[1].globalIndex, 0); + + EXPECT_EQ(specs[2].type, loader::BY_GLOBAL_INDEX); + EXPECT_EQ(specs[2].globalIndex, 1); +} + +TEST_F(DriverOrderingHelperFunctionsTest, ParseDriverOrder_SingleDriverType_ShouldParseCorrectly) { + auto specs = loader::parseDriverOrder("NPU"); + ASSERT_EQ(specs.size(), 1); + EXPECT_EQ(specs[0].type, loader::BY_TYPE); + EXPECT_EQ(specs[0].driverType, loader::ZEL_DRIVER_TYPE_NPU); +} + +TEST_F(DriverOrderingHelperFunctionsTest, ParseDriverOrder_MultipleDriverTypes_ShouldParseCorrectly) { + auto specs = loader::parseDriverOrder("NPU,DISCRETE_GPU_ONLY,GPU"); + ASSERT_EQ(specs.size(), 3); + + EXPECT_EQ(specs[0].type, loader::BY_TYPE); + EXPECT_EQ(specs[0].driverType, loader::ZEL_DRIVER_TYPE_NPU); + + EXPECT_EQ(specs[1].type, loader::BY_TYPE); + EXPECT_EQ(specs[1].driverType, loader::ZEL_DRIVER_TYPE_DISCRETE_GPU); + + EXPECT_EQ(specs[2].type, loader::BY_TYPE); + EXPECT_EQ(specs[2].driverType, loader::ZEL_DRIVER_TYPE_GPU); +} + +TEST_F(DriverOrderingHelperFunctionsTest, ParseDriverOrder_DriverTypeWithIndex_ShouldParseCorrectly) { + auto specs = loader::parseDriverOrder("NPU:1"); + ASSERT_EQ(specs.size(), 1); + EXPECT_EQ(specs[0].type, loader::BY_TYPE_AND_INDEX); + EXPECT_EQ(specs[0].driverType, loader::ZEL_DRIVER_TYPE_NPU); + EXPECT_EQ(specs[0].typeIndex, 1); +} + +TEST_F(DriverOrderingHelperFunctionsTest, ParseDriverOrder_MultipleDriverTypesWithIndices_ShouldParseCorrectly) { + auto specs = loader::parseDriverOrder("NPU:1,DISCRETE_GPU_ONLY:0,GPU:2"); + ASSERT_EQ(specs.size(), 3); + + EXPECT_EQ(specs[0].type, loader::BY_TYPE_AND_INDEX); + EXPECT_EQ(specs[0].driverType, loader::ZEL_DRIVER_TYPE_NPU); + EXPECT_EQ(specs[0].typeIndex, 1); + + EXPECT_EQ(specs[1].type, loader::BY_TYPE_AND_INDEX); + EXPECT_EQ(specs[1].driverType, loader::ZEL_DRIVER_TYPE_DISCRETE_GPU); + EXPECT_EQ(specs[1].typeIndex, 0); + + EXPECT_EQ(specs[2].type, loader::BY_TYPE_AND_INDEX); + EXPECT_EQ(specs[2].driverType, loader::ZEL_DRIVER_TYPE_GPU); + EXPECT_EQ(specs[2].typeIndex, 2); +} + +TEST_F(DriverOrderingHelperFunctionsTest, ParseDriverOrder_MixedSyntax_ShouldParseCorrectly) { + auto specs = loader::parseDriverOrder("NPU:1,2,GPU,0"); + ASSERT_EQ(specs.size(), 4); + + EXPECT_EQ(specs[0].type, loader::BY_TYPE_AND_INDEX); + EXPECT_EQ(specs[0].driverType, loader::ZEL_DRIVER_TYPE_NPU); + EXPECT_EQ(specs[0].typeIndex, 1); + + EXPECT_EQ(specs[1].type, loader::BY_GLOBAL_INDEX); + EXPECT_EQ(specs[1].globalIndex, 2); + + EXPECT_EQ(specs[2].type, loader::BY_TYPE); + EXPECT_EQ(specs[2].driverType, loader::ZEL_DRIVER_TYPE_GPU); + + EXPECT_EQ(specs[3].type, loader::BY_GLOBAL_INDEX); + EXPECT_EQ(specs[3].globalIndex, 0); +} + +TEST_F(DriverOrderingHelperFunctionsTest, ParseDriverOrder_WithWhitespace_ShouldTrimAndParseCorrectly) { + auto specs = loader::parseDriverOrder(" NPU : 1 , 2 , GPU "); + ASSERT_EQ(specs.size(), 3); + + EXPECT_EQ(specs[0].type, loader::BY_TYPE_AND_INDEX); + EXPECT_EQ(specs[0].driverType, loader::ZEL_DRIVER_TYPE_NPU); + EXPECT_EQ(specs[0].typeIndex, 1); + + EXPECT_EQ(specs[1].type, loader::BY_GLOBAL_INDEX); + EXPECT_EQ(specs[1].globalIndex, 2); + + EXPECT_EQ(specs[2].type, loader::BY_TYPE); + EXPECT_EQ(specs[2].driverType, loader::ZEL_DRIVER_TYPE_GPU); +} + +TEST_F(DriverOrderingHelperFunctionsTest, ParseDriverOrder_InvalidEntries_ShouldSkipInvalid) { + auto specs = loader::parseDriverOrder("NPU:1,INVALID_TYPE,abc,GPU:xyz,2"); + ASSERT_EQ(specs.size(), 2); + + EXPECT_EQ(specs[0].type, loader::BY_TYPE_AND_INDEX); + EXPECT_EQ(specs[0].driverType, loader::ZEL_DRIVER_TYPE_NPU); + EXPECT_EQ(specs[0].typeIndex, 1); + + EXPECT_EQ(specs[1].type, loader::BY_GLOBAL_INDEX); + EXPECT_EQ(specs[1].globalIndex, 2); +} + +TEST_F(DriverOrderingHelperFunctionsTest, ParseDriverOrder_EmptyTokens_ShouldSkipEmpty) { + auto specs = loader::parseDriverOrder("NPU,,2,,,GPU"); + ASSERT_EQ(specs.size(), 3); + + EXPECT_EQ(specs[0].type, loader::BY_TYPE); + EXPECT_EQ(specs[0].driverType, loader::ZEL_DRIVER_TYPE_NPU); + + EXPECT_EQ(specs[1].type, loader::BY_GLOBAL_INDEX); + EXPECT_EQ(specs[1].globalIndex, 2); + + EXPECT_EQ(specs[2].type, loader::BY_TYPE); + EXPECT_EQ(specs[2].driverType, loader::ZEL_DRIVER_TYPE_GPU); +} + +TEST_F(DriverOrderingHelperFunctionsTest, ParseDriverOrder_ColonWithoutIndex_ShouldSkip) { + auto specs = loader::parseDriverOrder("NPU:,GPU:"); + EXPECT_TRUE(specs.empty()); +} + +TEST_F(DriverOrderingHelperFunctionsTest, ParseDriverOrder_OnlyCommas_ShouldReturnEmpty) { + auto specs = loader::parseDriverOrder(",,,,"); + EXPECT_TRUE(specs.empty()); +} + +TEST_F(DriverOrderingHelperFunctionsTest, ParseDriverOrder_InvalidIndexes_ShouldSkipInvalidOnes) { + auto specs = loader::parseDriverOrder("NPU:0,GPU:abc,DISCRETE_GPU_ONLY:999999999999999999999"); + ASSERT_EQ(specs.size(), 1); // Only NPU:0 should be valid + + EXPECT_EQ(specs[0].type, loader::BY_TYPE_AND_INDEX); + EXPECT_EQ(specs[0].driverType, loader::ZEL_DRIVER_TYPE_NPU); + EXPECT_EQ(specs[0].typeIndex, 0); +} + +TEST_F(DriverOrderingHelperFunctionsTest, ParseDriverOrder_LargeValidIndex_ShouldParseCorrectly) { + auto specs = loader::parseDriverOrder("NPU:4294967295"); // Max uint32_t + ASSERT_EQ(specs.size(), 1); + + EXPECT_EQ(specs[0].type, loader::BY_TYPE_AND_INDEX); + EXPECT_EQ(specs[0].driverType, loader::ZEL_DRIVER_TYPE_NPU); + EXPECT_EQ(specs[0].typeIndex, 4294967295u); +} + +/////////////////////////////////////////////////////////////////////////////// +// Integration tests for the parsing functionality +/////////////////////////////////////////////////////////////////////////////// + +TEST_F(DriverOrderingHelperFunctionsTest, ParseDriverOrder_RealWorldExamples_ShouldParseCorrectly) { + // Documentation Example 1: DISCRETE_GPU_ONLY:1,NPU + auto specs = loader::parseDriverOrder("DISCRETE_GPU_ONLY:1,NPU"); + ASSERT_EQ(specs.size(), 2); + + EXPECT_EQ(specs[0].type, loader::BY_TYPE_AND_INDEX); + EXPECT_EQ(specs[0].driverType, loader::ZEL_DRIVER_TYPE_DISCRETE_GPU); + EXPECT_EQ(specs[0].typeIndex, 1); + + EXPECT_EQ(specs[1].type, loader::BY_TYPE); + EXPECT_EQ(specs[1].driverType, loader::ZEL_DRIVER_TYPE_NPU); +} + +TEST_F(DriverOrderingHelperFunctionsTest, ParseDriverOrder_ComplexScenario_ShouldParseCorrectly) { + // Complex example: "NPU:0,2,GPU,0,DISCRETE_GPU_ONLY:1" + auto specs = loader::parseDriverOrder("NPU:0,2,GPU,0,DISCRETE_GPU_ONLY:1"); + ASSERT_EQ(specs.size(), 5); + + EXPECT_EQ(specs[0].type, loader::BY_TYPE_AND_INDEX); + EXPECT_EQ(specs[0].driverType, loader::ZEL_DRIVER_TYPE_NPU); + EXPECT_EQ(specs[0].typeIndex, 0); + + EXPECT_EQ(specs[1].type, loader::BY_GLOBAL_INDEX); + EXPECT_EQ(specs[1].globalIndex, 2); + + EXPECT_EQ(specs[2].type, loader::BY_TYPE); + EXPECT_EQ(specs[2].driverType, loader::ZEL_DRIVER_TYPE_GPU); + + EXPECT_EQ(specs[3].type, loader::BY_GLOBAL_INDEX); + EXPECT_EQ(specs[3].globalIndex, 0); + + EXPECT_EQ(specs[4].type, loader::BY_TYPE_AND_INDEX); + EXPECT_EQ(specs[4].driverType, loader::ZEL_DRIVER_TYPE_DISCRETE_GPU); + EXPECT_EQ(specs[4].typeIndex, 1); +} diff --git a/test/driver_ordering_unit_tests.cpp b/test/driver_ordering_unit_tests.cpp new file mode 100644 index 00000000..ff5152c4 --- /dev/null +++ b/test/driver_ordering_unit_tests.cpp @@ -0,0 +1,579 @@ +/* + * + * Copyright (C) 2025 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "gtest/gtest.h" + +#include "source/loader/ze_loader_internal.h" +#include "ze_api.h" + +#include +#include +#include + +#if defined(_WIN32) + #include + #include + #include + #include + #define putenv_safe _putenv +#else + #include + #include + #include + #define putenv_safe putenv +#endif + +namespace { + +// Helper function to create a mock driver with specific type +loader::driver_t createMockDriver(const std::string& name, loader::zel_driver_type_t type) { + loader::driver_t driver; + driver.name = name; + driver.driverType = type; + driver.handle = nullptr; // Mock handle + driver.initStatus = ZE_RESULT_SUCCESS; + driver.driverInuse = false; + return driver; +} + +// Helper function to clear ZEL_DRIVERS_ORDER environment variable +void clearDriverOrderEnv() { + putenv_safe(const_cast("ZEL_DRIVERS_ORDER=")); +} + +// Helper function to set ZEL_DRIVERS_ORDER environment variable +void setDriverOrderEnv(const std::string& order) { + static std::string env_var_storage; + env_var_storage = "ZEL_DRIVERS_ORDER=" + order; + putenv_safe(const_cast(env_var_storage.c_str())); +} + +// Test fixture for direct unit testing of driver ordering functionality +class DriverOrderingUnitTest : public ::testing::Test { +protected: + void SetUp() override { + // Clear any existing environment variables + clearDriverOrderEnv(); + + // Initialize a test context if needed + if (!loader::context) { + loader::context = new loader::context_t(); + loader::context->debugTraceEnabled = false; // Disable debug trace for cleaner tests + } + } + + void TearDown() override { + // Clean up environment variables + clearDriverOrderEnv(); + } + + // Helper to create a standard test driver setup + loader::driver_vector_t createStandardDriverSetup() { + loader::driver_vector_t drivers; + drivers.push_back(createMockDriver("discrete_gpu_0", loader::ZEL_DRIVER_TYPE_DISCRETE_GPU)); + drivers.push_back(createMockDriver("discrete_gpu_1", loader::ZEL_DRIVER_TYPE_DISCRETE_GPU)); + drivers.push_back(createMockDriver("integrated_gpu_0", loader::ZEL_DRIVER_TYPE_INTEGRATED_GPU)); + drivers.push_back(createMockDriver("gpu_mixed_0", loader::ZEL_DRIVER_TYPE_GPU)); + drivers.push_back(createMockDriver("npu_0", loader::ZEL_DRIVER_TYPE_NPU)); + drivers.push_back(createMockDriver("other_0", loader::ZEL_DRIVER_TYPE_OTHER)); + return drivers; + } + + // Helper to verify driver order by names + void verifyDriverOrder(const loader::driver_vector_t& drivers, const std::vector& expectedOrder) { + ASSERT_EQ(drivers.size(), expectedOrder.size()) << "Driver count mismatch"; + for (size_t i = 0; i < drivers.size(); ++i) { + EXPECT_EQ(drivers[i].name, expectedOrder[i]) << "Driver order mismatch at index " << i; + } + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// Tests for basic driver ordering functionality +/////////////////////////////////////////////////////////////////////////////// + +TEST_F(DriverOrderingUnitTest, NoEnvironmentVariable_ShouldNotChangeOrder) { + // Arrange + auto drivers = createStandardDriverSetup(); + auto originalOrder = drivers; + + // Act + loader::context->driverOrdering(&drivers); + + // Assert - order should remain unchanged + ASSERT_EQ(drivers.size(), originalOrder.size()); + for (size_t i = 0; i < drivers.size(); ++i) { + EXPECT_EQ(drivers[i].name, originalOrder[i].name); + EXPECT_EQ(drivers[i].driverType, originalOrder[i].driverType); + } +} + +TEST_F(DriverOrderingUnitTest, EmptyEnvironmentVariable_ShouldNotChangeOrder) { + // Arrange + setDriverOrderEnv(""); + auto drivers = createStandardDriverSetup(); + auto originalOrder = drivers; + + // Act + loader::context->driverOrdering(&drivers); + + // Assert - order should remain unchanged + ASSERT_EQ(drivers.size(), originalOrder.size()); + for (size_t i = 0; i < drivers.size(); ++i) { + EXPECT_EQ(drivers[i].name, originalOrder[i].name); + EXPECT_EQ(drivers[i].driverType, originalOrder[i].driverType); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Tests for global index ordering (Syntax 3) +/////////////////////////////////////////////////////////////////////////////// + +TEST_F(DriverOrderingUnitTest, GlobalIndex_SingleIndex_ShouldMoveToFront) { + // Arrange + setDriverOrderEnv("2"); + auto drivers = createStandardDriverSetup(); + + // Act + loader::context->driverOrdering(&drivers); + + // Assert - driver at index 2 should move to front + std::vector expectedOrder = { + "integrated_gpu_0", // was at index 2 + "discrete_gpu_0", // was at index 0 + "discrete_gpu_1", // was at index 1 + "gpu_mixed_0", // was at index 3 + "npu_0", // was at index 4 + "other_0" // was at index 5 + }; + verifyDriverOrder(drivers, expectedOrder); +} + +TEST_F(DriverOrderingUnitTest, GlobalIndex_MultipleIndices_ShouldReorderAccordingly) { + // Arrange + setDriverOrderEnv("4,1,0"); + auto drivers = createStandardDriverSetup(); + + // Act + loader::context->driverOrdering(&drivers); + + // Assert + std::vector expectedOrder = { + "npu_0", // was at index 4 + "discrete_gpu_1", // was at index 1 + "discrete_gpu_0", // was at index 0 + "integrated_gpu_0", // was at index 2 + "gpu_mixed_0", // was at index 3 + "other_0" // was at index 5 + }; + verifyDriverOrder(drivers, expectedOrder); +} + +TEST_F(DriverOrderingUnitTest, GlobalIndex_OutOfBounds_ShouldIgnoreInvalidIndices) { + // Arrange + setDriverOrderEnv("999,2,1000"); + auto drivers = createStandardDriverSetup(); + + // Act + loader::context->driverOrdering(&drivers); + + // Assert - only valid index 2 should be moved + std::vector expectedOrder = { + "integrated_gpu_0", // was at index 2 + "discrete_gpu_0", // was at index 0 + "discrete_gpu_1", // was at index 1 + "gpu_mixed_0", // was at index 3 + "npu_0", // was at index 4 + "other_0" // was at index 5 + }; + verifyDriverOrder(drivers, expectedOrder); +} + +/////////////////////////////////////////////////////////////////////////////// +// Tests for driver type ordering (Syntax 2) +/////////////////////////////////////////////////////////////////////////////// + +TEST_F(DriverOrderingUnitTest, DriverType_NPU_ShouldMoveAllNPUDriversToFront) { + // Arrange + setDriverOrderEnv("NPU"); + auto drivers = createStandardDriverSetup(); + + // Act + loader::context->driverOrdering(&drivers); + + // Assert - NPU drivers should come first, and OTHER drivers are also moved because + // they're stored in the same npuIndices vector + std::vector expectedOrder = { + "npu_0", // NPU driver moved to front + "other_0", // OTHER drivers are also moved with NPU + "discrete_gpu_0", // remaining drivers in original order + "discrete_gpu_1", + "integrated_gpu_0", + "gpu_mixed_0" + }; + verifyDriverOrder(drivers, expectedOrder); +} + +TEST_F(DriverOrderingUnitTest, DriverType_DiscreteGPU_ShouldMoveAllDiscreteGPUDriversToFront) { + // Arrange + setDriverOrderEnv("DISCRETE_GPU_ONLY"); + auto drivers = createStandardDriverSetup(); + + // Act + loader::context->driverOrdering(&drivers); + + // Assert + std::vector expectedOrder = { + "discrete_gpu_0", // discrete GPU drivers moved to front + "discrete_gpu_1", + "integrated_gpu_0", // remaining drivers in original order + "gpu_mixed_0", + "npu_0", + "other_0" + }; + verifyDriverOrder(drivers, expectedOrder); +} + +TEST_F(DriverOrderingUnitTest, DriverType_MultipleTypes_ShouldRespectOrder) { + // Arrange + setDriverOrderEnv("NPU,DISCRETE_GPU_ONLY,GPU"); + auto drivers = createStandardDriverSetup(); + + // Act + loader::context->driverOrdering(&drivers); + + // Assert + std::vector expectedOrder = { + "npu_0", // NPU first + "other_0", // OTHER also moved with NPU request + "discrete_gpu_0", // DISCRETE_GPU_ONLY second + "discrete_gpu_1", + "gpu_mixed_0", // GPU third + "integrated_gpu_0" // remaining drivers + }; + verifyDriverOrder(drivers, expectedOrder); +} + +/////////////////////////////////////////////////////////////////////////////// +// Tests for driver type and index ordering (Syntax 1) +/////////////////////////////////////////////////////////////////////////////// + +TEST_F(DriverOrderingUnitTest, DriverTypeAndIndex_ValidTypeAndIndex_ShouldMoveSpecificDriver) { + // Arrange + setDriverOrderEnv("DISCRETE_GPU_ONLY:1"); + auto drivers = createStandardDriverSetup(); + + // Act + loader::context->driverOrdering(&drivers); + + // Assert - second discrete GPU driver should move to front + std::vector expectedOrder = { + "discrete_gpu_1", // DISCRETE_GPU_ONLY index 1 + "discrete_gpu_0", // remaining drivers + "integrated_gpu_0", + "gpu_mixed_0", + "npu_0", + "other_0" + }; + verifyDriverOrder(drivers, expectedOrder); +} + +TEST_F(DriverOrderingUnitTest, DriverTypeAndIndex_NPUWithIndex_ShouldMoveSpecificNPUDriver) { + // Arrange: In the standard setup, we have npu_0 at index 4 and other_0 at index 5 + // Both are stored in npuIndices, so NPU:0 = npu_0, NPU:1 = other_0 + auto drivers = createStandardDriverSetup(); + + setDriverOrderEnv("NPU:1"); + + // Act + loader::context->driverOrdering(&drivers); + + // Assert - NPU index 1 should be the OTHER driver (other_0) since both NPU and OTHER + // are stored in the npuIndices vector + EXPECT_EQ(drivers[0].name, "other_0"); + EXPECT_EQ(drivers[0].driverType, loader::ZEL_DRIVER_TYPE_OTHER); +} + +TEST_F(DriverOrderingUnitTest, DriverTypeAndIndex_OutOfBoundsIndex_ShouldIgnore) { + // Arrange + setDriverOrderEnv("DISCRETE_GPU_ONLY:999"); + auto drivers = createStandardDriverSetup(); + auto originalOrder = drivers; + + // Act + loader::context->driverOrdering(&drivers); + + // Assert - order should remain unchanged due to invalid index + ASSERT_EQ(drivers.size(), originalOrder.size()); + for (size_t i = 0; i < drivers.size(); ++i) { + EXPECT_EQ(drivers[i].name, originalOrder[i].name); + } +} + +TEST_F(DriverOrderingUnitTest, DriverTypeAndIndex_InvalidDriverType_ShouldIgnore) { + // Arrange + setDriverOrderEnv("INVALID_TYPE:0"); + auto drivers = createStandardDriverSetup(); + auto originalOrder = drivers; + + // Act + loader::context->driverOrdering(&drivers); + + // Assert - order should remain unchanged due to invalid type + ASSERT_EQ(drivers.size(), originalOrder.size()); + for (size_t i = 0; i < drivers.size(); ++i) { + EXPECT_EQ(drivers[i].name, originalOrder[i].name); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Tests for mixed syntax combinations +/////////////////////////////////////////////////////////////////////////////// + +TEST_F(DriverOrderingUnitTest, MixedSyntax_GlobalIndexAndType_ShouldRespectOrder) { + // Arrange + setDriverOrderEnv("2,NPU,0"); + auto drivers = createStandardDriverSetup(); + + // Act + loader::context->driverOrdering(&drivers); + + // Assert + std::vector expectedOrder = { + "integrated_gpu_0", // global index 2 + "npu_0", // NPU type + "other_0", // OTHER treated as NPU + "discrete_gpu_0", // global index 0 + "discrete_gpu_1", // remaining + "gpu_mixed_0" + }; + verifyDriverOrder(drivers, expectedOrder); +} + +TEST_F(DriverOrderingUnitTest, MixedSyntax_TypeIndexAndGlobal_ShouldRespectOrder) { + // Arrange + setDriverOrderEnv("DISCRETE_GPU_ONLY:1,3,NPU:0"); + auto drivers = createStandardDriverSetup(); + + // Act + loader::context->driverOrdering(&drivers); + + // Assert + std::vector expectedOrder = { + "discrete_gpu_1", // DISCRETE_GPU_ONLY:1 + "gpu_mixed_0", // global index 3 + "npu_0", // NPU:0 + "discrete_gpu_0", // remaining + "integrated_gpu_0", + "other_0" + }; + verifyDriverOrder(drivers, expectedOrder); +} + +/////////////////////////////////////////////////////////////////////////////// +// Tests for edge cases and error handling +/////////////////////////////////////////////////////////////////////////////// + +TEST_F(DriverOrderingUnitTest, EmptyDriverVector_ShouldNotCrash) { + // Arrange + setDriverOrderEnv("NPU,GPU,0"); + loader::driver_vector_t drivers; // empty vector + + // Act & Assert - should not crash + EXPECT_NO_THROW(loader::context->driverOrdering(&drivers)); + EXPECT_EQ(drivers.size(), 0); +} + +TEST_F(DriverOrderingUnitTest, WhitespaceInEnvironmentVariable_ShouldTrimCorrectly) { + // Arrange + setDriverOrderEnv(" NPU : 0 , GPU , 1 "); + auto drivers = createStandardDriverSetup(); + + // Act + loader::context->driverOrdering(&drivers); + + // Assert - should handle whitespace correctly + // NPU:0 = npu_0, GPU type = gpu_mixed_0, global index 1 = discrete_gpu_1 + EXPECT_EQ(drivers[0].name, "npu_0"); // NPU:0 + EXPECT_EQ(drivers[1].name, "gpu_mixed_0"); // GPU type + EXPECT_EQ(drivers[2].name, "discrete_gpu_1"); // global index 1 +} + +TEST_F(DriverOrderingUnitTest, DuplicateSpecifications_ShouldUseFirstOccurrence) { + // Arrange + setDriverOrderEnv("NPU:0,NPU:0,1,1"); + auto drivers = createStandardDriverSetup(); + + // Act + loader::context->driverOrdering(&drivers); + + // Assert - duplicates should be ignored + std::vector expectedOrder = { + "npu_0", // NPU:0 (first occurrence) + "discrete_gpu_1", // global index 1 (first occurrence) + "discrete_gpu_0", // remaining + "integrated_gpu_0", + "gpu_mixed_0", + "other_0" + }; + verifyDriverOrder(drivers, expectedOrder); +} + +TEST_F(DriverOrderingUnitTest, InvalidSyntax_ShouldIgnoreInvalidEntries) { + // Arrange + setDriverOrderEnv("NPU:,GPU:abc,::,INVALID:SYNTAX,2"); + auto drivers = createStandardDriverSetup(); + + // Act + loader::context->driverOrdering(&drivers); + + // Assert - only valid entries should be processed + // In this case, only "2" should be processed as a valid global index + // Expected: integrated_gpu_0 (global index 2) should move to front + std::vector expectedOrder = { + "integrated_gpu_0", // valid global index 2 + "discrete_gpu_0", // remaining drivers + "discrete_gpu_1", + "gpu_mixed_0", + "npu_0", + "other_0" + }; + verifyDriverOrder(drivers, expectedOrder); +} + +TEST_F(DriverOrderingUnitTest, ColonWithoutIndex_ShouldIgnore) { + // Arrange + setDriverOrderEnv("NPU:,GPU:"); + auto drivers = createStandardDriverSetup(); + auto originalOrder = drivers; + + // Act + loader::context->driverOrdering(&drivers); + + // Assert - should ignore invalid syntax and maintain original order + ASSERT_EQ(drivers.size(), originalOrder.size()); + for (size_t i = 0; i < drivers.size(); ++i) { + EXPECT_EQ(drivers[i].name, originalOrder[i].name); + } +} + +TEST_F(DriverOrderingUnitTest, OnlyCommas_ShouldIgnore) { + // Arrange + setDriverOrderEnv(",,,,"); + auto drivers = createStandardDriverSetup(); + auto originalOrder = drivers; + + // Act + loader::context->driverOrdering(&drivers); + + // Assert - should maintain original order + ASSERT_EQ(drivers.size(), originalOrder.size()); + for (size_t i = 0; i < drivers.size(); ++i) { + EXPECT_EQ(drivers[i].name, originalOrder[i].name); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Tests for all supported driver types +/////////////////////////////////////////////////////////////////////////////// + +TEST_F(DriverOrderingUnitTest, AllSupportedDriverTypes_ShouldHandleCorrectly) { + // Arrange: Create drivers of all types + loader::driver_vector_t drivers; + drivers.push_back(createMockDriver("discrete_0", loader::ZEL_DRIVER_TYPE_DISCRETE_GPU)); + drivers.push_back(createMockDriver("integrated_0", loader::ZEL_DRIVER_TYPE_INTEGRATED_GPU)); + drivers.push_back(createMockDriver("gpu_mixed_0", loader::ZEL_DRIVER_TYPE_GPU)); + drivers.push_back(createMockDriver("mixed_0", loader::ZEL_DRIVER_TYPE_MIXED)); + drivers.push_back(createMockDriver("other_0", loader::ZEL_DRIVER_TYPE_OTHER)); + drivers.push_back(createMockDriver("npu_0", loader::ZEL_DRIVER_TYPE_NPU)); + + setDriverOrderEnv("NPU,INTEGRATED_GPU_ONLY,DISCRETE_GPU_ONLY,GPU"); + + // Act + loader::context->driverOrdering(&drivers); + + // Assert + std::vector expectedOrder = { + "other_0", // OTHER (moved with NPU request, comes first due to lower original index) + "npu_0", // NPU (moved with NPU request, comes second due to higher original index) + "integrated_0", // INTEGRATED_GPU_ONLY + "discrete_0", // DISCRETE_GPU_ONLY + "gpu_mixed_0", // GPU + "mixed_0" // remaining (MIXED) + }; + verifyDriverOrder(drivers, expectedOrder); +} + +TEST_F(DriverOrderingUnitTest, ComplexRealWorldScenario_ShouldHandleCorrectly) { + // Arrange: Simulate a complex real-world system + loader::driver_vector_t drivers; + drivers.push_back(createMockDriver("intel_discrete_0", loader::ZEL_DRIVER_TYPE_DISCRETE_GPU)); + drivers.push_back(createMockDriver("intel_discrete_1", loader::ZEL_DRIVER_TYPE_DISCRETE_GPU)); + drivers.push_back(createMockDriver("intel_integrated_0", loader::ZEL_DRIVER_TYPE_INTEGRATED_GPU)); + drivers.push_back(createMockDriver("intel_npu_0", loader::ZEL_DRIVER_TYPE_NPU)); + drivers.push_back(createMockDriver("other_vendor_gpu", loader::ZEL_DRIVER_TYPE_GPU)); + + // Test complex ordering: specific discrete GPU, then all NPUs, then specific global index + setDriverOrderEnv("DISCRETE_GPU_ONLY:1,NPU,2"); + + // Act + loader::context->driverOrdering(&drivers); + + // Assert + std::vector expectedOrder = { + "intel_discrete_1", // DISCRETE_GPU_ONLY:1 (second discrete GPU) + "intel_npu_0", // NPU (all NPU drivers) + "intel_integrated_0", // global index 2 + "intel_discrete_0", // remaining drivers + "other_vendor_gpu" + }; + verifyDriverOrder(drivers, expectedOrder); +} + +/////////////////////////////////////////////////////////////////////////////// +// Tests for boundary conditions +/////////////////////////////////////////////////////////////////////////////// + +TEST_F(DriverOrderingUnitTest, SingleDriver_ShouldHandleCorrectly) { + // Arrange + loader::driver_vector_t drivers; + drivers.push_back(createMockDriver("single_driver", loader::ZEL_DRIVER_TYPE_DISCRETE_GPU)); + + setDriverOrderEnv("DISCRETE_GPU_ONLY:0,NPU,1"); + + // Act + loader::context->driverOrdering(&drivers); + + // Assert - single driver should remain + ASSERT_EQ(drivers.size(), 1); + EXPECT_EQ(drivers[0].name, "single_driver"); +} + +TEST_F(DriverOrderingUnitTest, MaxOrderSpecifications_ShouldHandleCorrectly) { + // Arrange: Test with many order specifications + auto drivers = createStandardDriverSetup(); + + // Create a long ordering string + setDriverOrderEnv("5,4,3,2,1,0,NPU,GPU,DISCRETE_GPU_ONLY,INTEGRATED_GPU_ONLY"); + + // Act + loader::context->driverOrdering(&drivers); + + // Assert - should process all valid specifications + std::vector expectedOrder = { + "other_0", // global index 5 + "npu_0", // global index 4 + "gpu_mixed_0", // global index 3 + "integrated_gpu_0", // global index 2 + "discrete_gpu_1", // global index 1 + "discrete_gpu_0" // global index 0 + }; + verifyDriverOrder(drivers, expectedOrder); +} + +} // namespace diff --git a/test/loader_api.cpp b/test/loader_api.cpp index 470bd132..965fb91e 100644 --- a/test/loader_api.cpp +++ b/test/loader_api.cpp @@ -421,7 +421,7 @@ class CaptureOutput { enum { Stdout = 1, Stderr = 2 }; CaptureOutput(int stream_) : stream(stream_) { - original_fd = _dup(stream); + original_fd = _dup(stream); #if defined(__linux__) fd = mkstemp(filename); #elif defined(_WIN32) @@ -469,7 +469,7 @@ TEST( CaptureOutput capture(CaptureOutput::Stdout); EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pInitDriversCount, nullptr, &desc)); - + std::string output = capture.GetOutput(); EXPECT_TRUE(output.empty()); } @@ -1610,6 +1610,8 @@ EXPECT_EQ(translatedHandle, devices[0]); } + + TEST( SysManApiLoaderDriverInteraction, GivenLevelZeroLoaderPresentWhenCallingSysManVfApisThenExpectNullDriverIsReachedSuccessfully) @@ -1662,4 +1664,627 @@ TEST( EXPECT_TRUE(compare_env("zesVFManagementGetVFCapabilitiesExp2", std::to_string(i + 1))); } } + +// Helper function to clear ZEL_DRIVERS_ORDER environment variable +void clearDriverOrderEnv() { + putenv_safe(const_cast("ZEL_DRIVERS_ORDER=")); +} + +// Helper function to set ZEL_DRIVERS_ORDER environment variable +void setDriverOrderEnv(const std::string& order) { + // Use static storage to ensure the string persists after the function returns + // This is necessary because putenv() stores a pointer to the string, not a copy + static std::string env_var_storage; + env_var_storage = "ZEL_DRIVERS_ORDER=" + order; + putenv_safe(const_cast(env_var_storage.c_str())); +} + +// Test Class for Driver Ordering Tests +class DriverOrderingTest : public ::testing::Test { +protected: + void SetUp() override { + // Clear any existing environment variables + clearDriverOrderEnv(); + putenv_safe(const_cast("ZEL_TEST_NULL_DRIVER_TYPE=ALL")); + putenv_safe(const_cast("ZE_ENABLE_LOADER_INTERCEPT=1")); + } + + void TearDown() override { + // Clean up environment variables + clearDriverOrderEnv(); + putenv_safe(const_cast("ZEL_TEST_NULL_DRIVER_TYPE=")); + putenv_safe(const_cast("ZE_ENABLE_LOADER_INTERCEPT=")); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// Tests for ZEL_DRIVERS_ORDER: Syntax 1 - Specific type and index within that type +/////////////////////////////////////////////////////////////////////////////// + +TEST_F(DriverOrderingTest, + GivenZelDriversOrderWithSpecificTypeAndIndexWhenCallingZeInitDriversThenSuccessfulReturn) { + + // Test case: DISCRETE_GPU_ONLY:1,NPU + setDriverOrderEnv("DISCRETE_GPU_ONLY:1,NPU"); + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + EXPECT_GT(pCount, 0); + + std::vector drivers(pCount); + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, drivers.data(), &desc)); + + // Verify that we got drivers back + EXPECT_GT(pCount, 0); + for (uint32_t i = 0; i < pCount; ++i) { + EXPECT_NE(drivers[i], nullptr); + } +} + +TEST_F(DriverOrderingTest, + GivenZelDriversOrderWithGpuTypeAndIndexWhenCallingZeInitDriversThenSuccessfulReturn) { + + // Test case: GPU:1,NPU:0 + setDriverOrderEnv("GPU:1,NPU:0"); + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + EXPECT_GT(pCount, 0); + + std::vector drivers(pCount); + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, drivers.data(), &desc)); + + // Verify that we got drivers back + EXPECT_GT(pCount, 0); + for (uint32_t i = 0; i < pCount; ++i) { + EXPECT_NE(drivers[i], nullptr); + } +} + +TEST_F(DriverOrderingTest, + GivenZelDriversOrderWithIntegratedGpuTypeAndIndexWhenCallingZeInitDriversThenSuccessfulReturn) { + + // Test case: INTEGRATED_GPU_ONLY:0,DISCRETE_GPU_ONLY:0 + setDriverOrderEnv("INTEGRATED_GPU_ONLY:0,DISCRETE_GPU_ONLY:0"); + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + EXPECT_GT(pCount, 0); + + std::vector drivers(pCount); + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, drivers.data(), &desc)); + + // Verify that we got drivers back + EXPECT_GT(pCount, 0); + for (uint32_t i = 0; i < pCount; ++i) { + EXPECT_NE(drivers[i], nullptr); + } +} + +TEST_F(DriverOrderingTest, + GivenZelDriversOrderWithNpuTypeAndIndexWhenCallingZeInitDriversThenSuccessfulReturn) { + + // Test case: NPU:0,GPU:0 + setDriverOrderEnv("NPU:0,GPU:0"); + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + EXPECT_GT(pCount, 0); + + std::vector drivers(pCount); + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, drivers.data(), &desc)); + + // Verify that we got drivers back + EXPECT_GT(pCount, 0); + for (uint32_t i = 0; i < pCount; ++i) { + EXPECT_NE(drivers[i], nullptr); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Tests for ZEL_DRIVERS_ORDER: Syntax 2 - Specific type only +/////////////////////////////////////////////////////////////////////////////// + +TEST_F(DriverOrderingTest, + GivenZelDriversOrderWithSpecificTypeOnlyWhenCallingZeInitDriversThenSuccessfulReturn) { + + // Test case: NPU,DISCRETE_GPU_ONLY + setDriverOrderEnv("NPU,DISCRETE_GPU_ONLY"); + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + EXPECT_GT(pCount, 0); + + std::vector drivers(pCount); + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, drivers.data(), &desc)); + + // Verify that we got drivers back + EXPECT_GT(pCount, 0); + for (uint32_t i = 0; i < pCount; ++i) { + EXPECT_NE(drivers[i], nullptr); + } +} + +TEST_F(DriverOrderingTest, + GivenZelDriversOrderWithGpuTypeOnlyWhenCallingZeInitDriversThenSuccessfulReturn) { + + // Test case: GPU,NPU + setDriverOrderEnv("GPU,NPU"); + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + EXPECT_GT(pCount, 0); + + std::vector drivers(pCount); + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, drivers.data(), &desc)); + + // Verify that we got drivers back + EXPECT_GT(pCount, 0); + for (uint32_t i = 0; i < pCount; ++i) { + EXPECT_NE(drivers[i], nullptr); + } +} + +TEST_F(DriverOrderingTest, + GivenZelDriversOrderWithIntegratedGpuTypeOnlyWhenCallingZeInitDriversThenSuccessfulReturn) { + + // Test case: INTEGRATED_GPU_ONLY,DISCRETE_GPU_ONLY,NPU + setDriverOrderEnv("INTEGRATED_GPU_ONLY,DISCRETE_GPU_ONLY,NPU"); + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + EXPECT_GT(pCount, 0); + + std::vector drivers(pCount); + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, drivers.data(), &desc)); + + // Verify that we got drivers back + EXPECT_GT(pCount, 0); + for (uint32_t i = 0; i < pCount; ++i) { + EXPECT_NE(drivers[i], nullptr); + } +} + +TEST_F(DriverOrderingTest, + GivenZelDriversOrderWithSingleNpuTypeWhenCallingZeInitDriversThenSuccessfulReturn) { + + // Test case: NPU (equivalent to example 4 in documentation) + setDriverOrderEnv("NPU"); + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + EXPECT_GT(pCount, 0); + + std::vector drivers(pCount); + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, drivers.data(), &desc)); + + // Verify that we got drivers back + EXPECT_GT(pCount, 0); + for (uint32_t i = 0; i < pCount; ++i) { + EXPECT_NE(drivers[i], nullptr); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Tests for ZEL_DRIVERS_ORDER: Syntax 3 - Global driver index only +/////////////////////////////////////////////////////////////////////////////// + +TEST_F(DriverOrderingTest, + GivenZelDriversOrderWithGlobalIndexOnlyWhenCallingZeInitDriversThenSuccessfulReturn) { + + // Test case: 2,0 (equivalent to example 2 in documentation) + setDriverOrderEnv("2,0"); + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + EXPECT_GT(pCount, 0); + + std::vector drivers(pCount); + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, drivers.data(), &desc)); + + // Verify that we got drivers back + EXPECT_GT(pCount, 0); + for (uint32_t i = 0; i < pCount; ++i) { + EXPECT_NE(drivers[i], nullptr); + } +} + +TEST_F(DriverOrderingTest, + GivenZelDriversOrderWithSingleGlobalIndexWhenCallingZeInitDriversThenSuccessfulReturn) { + + // Test case: 1 + setDriverOrderEnv("1"); + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + EXPECT_GT(pCount, 0); + + std::vector drivers(pCount); + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, drivers.data(), &desc)); + + // Verify that we got drivers back + EXPECT_GT(pCount, 0); + for (uint32_t i = 0; i < pCount; ++i) { + EXPECT_NE(drivers[i], nullptr); + } +} + +TEST_F(DriverOrderingTest, + GivenZelDriversOrderWithMultipleGlobalIndicesWhenCallingZeInitDriversThenSuccessfulReturn) { + + // Test case: 1,2,0 + setDriverOrderEnv("1,2,0"); + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + EXPECT_GT(pCount, 0); + + std::vector drivers(pCount); + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, drivers.data(), &desc)); + + // Verify that we got drivers back + EXPECT_GT(pCount, 0); + for (uint32_t i = 0; i < pCount; ++i) { + EXPECT_NE(drivers[i], nullptr); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Tests for ZEL_DRIVERS_ORDER: Mixed syntax combinations +/////////////////////////////////////////////////////////////////////////////// + +TEST_F(DriverOrderingTest, + GivenZelDriversOrderWithMixedSyntaxWhenCallingZeInitDriversThenSuccessfulReturn) { + + // Test case: NPU:0,2,GPU,0 (mixed syntax) + setDriverOrderEnv("NPU:0,2,GPU,0"); + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + EXPECT_GT(pCount, 0); + + std::vector drivers(pCount); + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, drivers.data(), &desc)); + + // Verify that we got drivers back + EXPECT_GT(pCount, 0); + for (uint32_t i = 0; i < pCount; ++i) { + EXPECT_NE(drivers[i], nullptr); + } +} + +TEST_F(DriverOrderingTest, + GivenZelDriversOrderWithMixedTypeAndIndexSyntaxWhenCallingZeInitDriversThenSuccessfulReturn) { + + // Test case: DISCRETE_GPU_ONLY:1,1,INTEGRATED_GPU_ONLY (type:index, global index, type) + setDriverOrderEnv("DISCRETE_GPU_ONLY:1,1,INTEGRATED_GPU_ONLY"); + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + EXPECT_GT(pCount, 0); + + std::vector drivers(pCount); + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, drivers.data(), &desc)); + + // Verify that we got drivers back + EXPECT_GT(pCount, 0); + for (uint32_t i = 0; i < pCount; ++i) { + EXPECT_NE(drivers[i], nullptr); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Tests for ZEL_DRIVERS_ORDER: Edge cases and error handling +/////////////////////////////////////////////////////////////////////////////// + +TEST_F(DriverOrderingTest, + GivenZelDriversOrderWithInvalidDriverTypeWhenCallingZeInitDriversThenDriversStillInitialize) { + + // Test case: INVALID_TYPE,NPU + setDriverOrderEnv("INVALID_TYPE,NPU"); + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + EXPECT_GT(pCount, 0); + + std::vector drivers(pCount); + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, drivers.data(), &desc)); + + // Should still get drivers back despite invalid type + EXPECT_GT(pCount, 0); + for (uint32_t i = 0; i < pCount; ++i) { + EXPECT_NE(drivers[i], nullptr); + } +} + +TEST_F(DriverOrderingTest, + GivenZelDriversOrderWithInvalidIndexWhenCallingZeInitDriversThenDriversStillInitialize) { + + // Test case: NPU:999,GPU:abc + setDriverOrderEnv("NPU:999,GPU:abc"); + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + EXPECT_GT(pCount, 0); + + std::vector drivers(pCount); + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, drivers.data(), &desc)); + + // Should still get drivers back despite invalid indices + EXPECT_GT(pCount, 0); + for (uint32_t i = 0; i < pCount; ++i) { + EXPECT_NE(drivers[i], nullptr); + } +} + +TEST_F(DriverOrderingTest, + GivenZelDriversOrderWithEmptyStringWhenCallingZeInitDriversThenDriversUseDefaultOrder) { + + // Test case: empty string + setDriverOrderEnv(""); + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + EXPECT_GT(pCount, 0); + + std::vector drivers(pCount); + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, drivers.data(), &desc)); + + // Should get drivers back in default order + EXPECT_GT(pCount, 0); + for (uint32_t i = 0; i < pCount; ++i) { + EXPECT_NE(drivers[i], nullptr); + } +} + +TEST_F(DriverOrderingTest, + GivenZelDriversOrderWithWhitespaceAndCommasWhenCallingZeInitDriversThenSuccessfulReturn) { + + // Test case: " NPU : 0 , GPU , 1 " (whitespace handling) + setDriverOrderEnv(" NPU : 0 , GPU , 1 "); + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + EXPECT_GT(pCount, 0); + + std::vector drivers(pCount); + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, drivers.data(), &desc)); + + // Should handle whitespace correctly + EXPECT_GT(pCount, 0); + for (uint32_t i = 0; i < pCount; ++i) { + EXPECT_NE(drivers[i], nullptr); + } +} + +TEST_F(DriverOrderingTest, + GivenZelDriversOrderWithDuplicateEntriesWhenCallingZeInitDriversThenSuccessfulReturn) { + + // Test case: GPU,GPU,NPU,NPU (duplicates) + setDriverOrderEnv("GPU,GPU,NPU,NPU"); + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + EXPECT_GT(pCount, 0); + + std::vector drivers(pCount); + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, drivers.data(), &desc)); + + // Should handle duplicates gracefully + EXPECT_GT(pCount, 0); + for (uint32_t i = 0; i < pCount; ++i) { + EXPECT_NE(drivers[i], nullptr); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Tests for ZEL_DRIVERS_ORDER: Compatibility with zeInit +/////////////////////////////////////////////////////////////////////////////// + +TEST_F(DriverOrderingTest, + GivenZelDriversOrderWithzeInitWhenCallingzeInitThenSuccessfulReturn) { + + // Test ZEL_DRIVERS_ORDER compatibility with zeInit + setDriverOrderEnv("NPU,GPU"); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInit(0)); + + uint32_t pDriverGetCount = 0; + EXPECT_EQ(ZE_RESULT_SUCCESS, zeDriverGet(&pDriverGetCount, nullptr)); + EXPECT_GT(pDriverGetCount, 0); + + std::vector drivers(pDriverGetCount); + EXPECT_EQ(ZE_RESULT_SUCCESS, zeDriverGet(&pDriverGetCount, drivers.data())); + + // Verify that we got drivers back + EXPECT_GT(pDriverGetCount, 0); + for (uint32_t i = 0; i < pDriverGetCount; ++i) { + EXPECT_NE(drivers[i], nullptr); + } +} + +TEST_F(DriverOrderingTest, + GivenZelDriversOrderWithzeInitAndzeInitDriversWhenCallingBothThenSuccessfulReturn) { + + // Test ZEL_DRIVERS_ORDER compatibility with both zeInit and zeInitDrivers + setDriverOrderEnv("DISCRETE_GPU_ONLY:0,NPU:0"); + + uint32_t pInitDriversCount = 0; + uint32_t pDriverGetCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pInitDriversCount, nullptr, &desc)); + EXPECT_GT(pInitDriversCount, 0); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInit(0)); + EXPECT_EQ(ZE_RESULT_SUCCESS, zeDriverGet(&pDriverGetCount, nullptr)); + EXPECT_GT(pDriverGetCount, 0); + + std::vector drivers(pDriverGetCount); + EXPECT_EQ(ZE_RESULT_SUCCESS, zeDriverGet(&pDriverGetCount, drivers.data())); + + // Verify that both calls succeed and drivers are available + EXPECT_GT(pDriverGetCount, 0); + for (uint32_t i = 0; i < pDriverGetCount; ++i) { + EXPECT_NE(drivers[i], nullptr); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Tests for ZEL_DRIVERS_ORDER: Complex real-world scenarios +/////////////////////////////////////////////////////////////////////////////// + +TEST_F(DriverOrderingTest, + GivenZelDriversOrderWithComplexScenarioLikeDocumentationExample1WhenCallingZeInitDriversThenSuccessfulReturn) { + + // Documentation Example 1: DISCRETE_GPU_ONLY:1,NPU + // On a system with 2 GPU Drivers (discrete:0, discrete:1) and 1 NPU Driver + // Default order: Discrete:0, Discrete:1, NPU + // Expected order: Discrete:1, NPU:0, Discrete:0 + setDriverOrderEnv("DISCRETE_GPU_ONLY:1,NPU"); + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + EXPECT_GT(pCount, 0); + + std::vector drivers(pCount); + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, drivers.data(), &desc)); + + // Verify that we got drivers back + EXPECT_GT(pCount, 0); + for (uint32_t i = 0; i < pCount; ++i) { + EXPECT_NE(drivers[i], nullptr); + } +} + +TEST_F(DriverOrderingTest, + GivenZelDriversOrderWithComplexScenarioLikeDocumentationExample3WhenCallingZeInitDriversThenSuccessfulReturn) { + + // Documentation Example 3: GPU:1,NPU:0 + // On a system with 2 GPU Drivers (discrete, integrated) and 1 NPU Driver + // Default order: Discrete, Integrated, NPU + // GPU indexes: Discrete(0), Integrated(1); NPU indexes: NPU(0) + // Expected order: Integrated, NPU, Discrete + setDriverOrderEnv("GPU:1,NPU:0"); + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + EXPECT_GT(pCount, 0); + + std::vector drivers(pCount); + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, drivers.data(), &desc)); + + // Verify that we got drivers back + EXPECT_GT(pCount, 0); + for (uint32_t i = 0; i < pCount; ++i) { + EXPECT_NE(drivers[i], nullptr); + } +} + +TEST_F(DriverOrderingTest, + GivenZelDriversOrderWithAllSupportedDriverTypesWhenCallingZeInitDriversThenSuccessfulReturn) { + + // Test all supported driver types in one ordering + setDriverOrderEnv("NPU,INTEGRATED_GPU_ONLY,DISCRETE_GPU_ONLY,GPU"); + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + EXPECT_GT(pCount, 0); + + std::vector drivers(pCount); + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, drivers.data(), &desc)); + + // Verify that we got drivers back + EXPECT_GT(pCount, 0); + for (uint32_t i = 0; i < pCount; ++i) { + EXPECT_NE(drivers[i], nullptr); + } +} + } // namespace