From 81df45d8964fc4aa042b0fdd3c31ebf5fd423d72 Mon Sep 17 00:00:00 2001 From: Alysa Liu Date: Tue, 2 Dec 2025 10:15:03 -0500 Subject: [PATCH] rocrtst: Add test for filter ROCR_VISIBLE_DEVICES (#2016) Improve test coverage for amd_filter_device.cpp. --- .../suites/functional/filter_devices.cc | 171 ++++++++++++++++++ .../suites/functional/filter_devices.h | 43 +++++ .../rocrtst/suites/test_common/main.cc | 10 + 3 files changed, 224 insertions(+) create mode 100644 projects/rocr-runtime/rocrtst/suites/functional/filter_devices.cc create mode 100644 projects/rocr-runtime/rocrtst/suites/functional/filter_devices.h diff --git a/projects/rocr-runtime/rocrtst/suites/functional/filter_devices.cc b/projects/rocr-runtime/rocrtst/suites/functional/filter_devices.cc new file mode 100644 index 0000000000..985467b2b2 --- /dev/null +++ b/projects/rocr-runtime/rocrtst/suites/functional/filter_devices.cc @@ -0,0 +1,171 @@ +/* +* Copyright © Advanced Micro Devices, Inc., or its affiliates. +* +* SPDX-License-Identifier: MIT +*/ +#include +#include +#include +#include +#include +#include + +#include "suites/functional/filter_devices.h" +#include "common/base_rocr_utils.h" +#include "common/common.h" +#include "common/helper_funcs.h" +#include "common/os.h" +#include "gtest/gtest.h" +#include "hsa/hsa.h" + +static const char kSubTestSeparator[] = " **************************"; + +static void PrintFilterSubtestHeader(const char *header) { + std::cout << " *** Filter Devices Subtest: " << header << " ***" << std::endl; +} + +FilterDevicesTest::FilterDevicesTest(void) : TestBase() { + set_num_iteration(1); + set_title("RocR Filter Devices Tests"); + set_description("This series of tests check ROCR_VISIBLE_DEVICES " + "environment variable functionality for filtering GPU devices."); + initial_gpu_count_ = 0; +} + +FilterDevicesTest::~FilterDevicesTest(void) {} + +void FilterDevicesTest::SetUp(void) { + TestBase::SetUp(); +} + +void FilterDevicesTest::Run(void) { + if (!rocrtst::CheckProfile(this)) { + return; + } + + TestBase::Run(); +} + +void FilterDevicesTest::DisplayTestInfo(void) { + TestBase::DisplayTestInfo(); +} + +void FilterDevicesTest::DisplayResults(void) const { + if (!rocrtst::CheckProfile(this)) { + return; + } + return; +} + +void FilterDevicesTest::Close() { + TestBase::Close(); +} + +void FilterDevicesTest::TestRocrVisibleDevicesFiltering() { + PrintFilterSubtestHeader("ROCR_VISIBLE_DEVICES Comprehensive Test"); + + const char* rvd_env = std::getenv("ROCR_VISIBLE_DEVICES"); + if (rvd_env != nullptr) { + if (verbosity() > 0) { + std::cout << "ROCR_VISIBLE_DEVICES is already set to: " + << rvd_env << ", Skipping." << std::endl; + std::cout << kSubTestSeparator << std::endl; + } + return; + } + + ASSERT_SUCCESS(hsa_iterate_agents(rocrtst::IterateGPUAgents, &available_gpus_)); + initial_gpu_count_ = available_gpus_.size(); + + if (initial_gpu_count_ < 2) { + if (verbosity() > 0) { + std::cout << "Test requires at least 2 GPUs. Skipping." << std::endl; + std::cout << kSubTestSeparator << std::endl; + } + return; + } + + std::vector gpu_uuids; + for (const auto& gpu : available_gpus_) { + char uuid[64] = {0}; + ASSERT_SUCCESS(hsa_agent_get_info(gpu, static_cast(HSA_AMD_AGENT_INFO_UUID), uuid)); + gpu_uuids.push_back(std::string(uuid)); + } + + // ROCR_VISIBLE_DEVICES=0 (single GPU) + if (verbosity() > 0) { + std::cout << "Testing with single device index." << std::endl; + } + rocrtst::SetEnv("ROCR_VISIBLE_DEVICES", "0"); + ASSERT_SUCCESS(hsa_shut_down()); + ASSERT_SUCCESS(hsa_init()); + + std::vector filtered_gpus; + ASSERT_SUCCESS(hsa_iterate_agents(rocrtst::IterateGPUAgents, &filtered_gpus)); + ASSERT_EQ(filtered_gpus.size(), 1) << "Expected 1 GPU, found " << filtered_gpus.size(); + + // ROCR_VISIBLE_DEVICES > number of physical devices + if (verbosity() > 0) { + std::cout << "Testing with invalid device index." << std::endl; + } + std::string invalid_index = std::to_string(initial_gpu_count_ + 5); + rocrtst::SetEnv("ROCR_VISIBLE_DEVICES", invalid_index.c_str()); + ASSERT_SUCCESS(hsa_shut_down()); + ASSERT_SUCCESS(hsa_init()); + + filtered_gpus.clear(); + ASSERT_SUCCESS(hsa_iterate_agents(rocrtst::IterateGPUAgents, &filtered_gpus)); + ASSERT_EQ(filtered_gpus.size(), 0) << "Expected 0 GPUs for invalid index, found " << filtered_gpus.size(); + + // ROCR_VISIBLE_DEVICES=1,0 (swapped indices) + if (verbosity() > 0) { + std::cout << "Testing with swapped device indices." << std::endl; + } + rocrtst::SetEnv("ROCR_VISIBLE_DEVICES", "1,0"); + ASSERT_SUCCESS(hsa_shut_down()); + ASSERT_SUCCESS(hsa_init()); + + filtered_gpus.clear(); + ASSERT_SUCCESS(hsa_iterate_agents(rocrtst::IterateGPUAgents, &filtered_gpus)); + ASSERT_EQ(filtered_gpus.size(), 2) << "Expected 2 GPUs, found " << filtered_gpus.size(); + + if (gpu_uuids.size() >= 2) { + char new_uuid_0[64] = {0}; + char new_uuid_1[64] = {0}; + + ASSERT_SUCCESS(hsa_agent_get_info(filtered_gpus[0], static_cast(HSA_AMD_AGENT_INFO_UUID), new_uuid_0)); + ASSERT_SUCCESS(hsa_agent_get_info(filtered_gpus[1], static_cast(HSA_AMD_AGENT_INFO_UUID), new_uuid_1)); + + ASSERT_EQ(std::string(new_uuid_0), gpu_uuids[1]) << "GPU 0 UUID should be swapped"; + ASSERT_EQ(std::string(new_uuid_1), gpu_uuids[0]) << "GPU 1 UUID should be swapped"; + } + + // ROCR_VISIBLE_DEVICES=GPU-XX (UUID selection) + if (verbosity() > 0) { + std::cout << "Testing with UUID filters." << std::endl; + } + if (!gpu_uuids.empty()) { + std::string uuid_filter = gpu_uuids[0]; + rocrtst::SetEnv("ROCR_VISIBLE_DEVICES", uuid_filter.c_str()); + ASSERT_SUCCESS(hsa_shut_down()); + ASSERT_SUCCESS(hsa_init()); + + filtered_gpus.clear(); + ASSERT_SUCCESS(hsa_iterate_agents(rocrtst::IterateGPUAgents, &filtered_gpus)); + ASSERT_EQ(filtered_gpus.size(), 1) << "Expected 1 GPU for UUID filter, found " << filtered_gpus.size(); + + char selected_uuid[64] = {0}; + ASSERT_SUCCESS(hsa_agent_get_info(filtered_gpus[0], static_cast(HSA_AMD_AGENT_INFO_UUID), selected_uuid)); + ASSERT_EQ(std::string(selected_uuid), gpu_uuids[0]) << "Selected GPU UUID should match"; + } + + // Clean up + unsetenv("ROCR_VISIBLE_DEVICES"); + ASSERT_SUCCESS(hsa_shut_down()); + ASSERT_SUCCESS(hsa_init()); + + if (verbosity() > 0) { + std::cout << "\nAll subtests passed" << std::endl; + std::cout << kSubTestSeparator << std::endl; + } +} \ No newline at end of file diff --git a/projects/rocr-runtime/rocrtst/suites/functional/filter_devices.h b/projects/rocr-runtime/rocrtst/suites/functional/filter_devices.h new file mode 100644 index 0000000000..0426c83f3e --- /dev/null +++ b/projects/rocr-runtime/rocrtst/suites/functional/filter_devices.h @@ -0,0 +1,43 @@ +/* +* Copyright © Advanced Micro Devices, Inc., or its affiliates. +* +* SPDX-License-Identifier: MIT +*/ +#ifndef ROCRTST_SUITES_FUNCTIONAL_FILTER_DEVICES_H_ +#define ROCRTST_SUITES_FUNCTIONAL_FILTER_DEVICES_H_ + +#include "common/base_rocr.h" +#include "hsa/hsa.h" +#include "suites/test_common/test_base.h" + +class FilterDevicesTest : public TestBase { + public: + FilterDevicesTest(); + + // @Brief: Destructor for test case of FilterDevicesTest + virtual ~FilterDevicesTest(); + + // @Brief: Setup the environment for FilterDevicesTest + virtual void SetUp(); + + // @Brief: Core test execution + virtual void Run(); + + // @Brief: Clean up and retrive the resource + virtual void Close(); + + // @Brief: Display results + virtual void DisplayResults() const; + + // @Brief: Display information about what this test does + virtual void DisplayTestInfo(void); + + // @Brief: Test ROCR_VISIBLE_DEVICES filtering functionality + void TestRocrVisibleDevicesFiltering(); + + private: + uint32_t initial_gpu_count_; + std::vector available_gpus_; +}; + +#endif // ROCRTST_SUITES_FUNCTIONAL_FILTER_DEVICES_H_ \ No newline at end of file diff --git a/projects/rocr-runtime/rocrtst/suites/test_common/main.cc b/projects/rocr-runtime/rocrtst/suites/test_common/main.cc index 4590959b82..457538f5ff 100644 --- a/projects/rocr-runtime/rocrtst/suites/test_common/main.cc +++ b/projects/rocr-runtime/rocrtst/suites/test_common/main.cc @@ -79,6 +79,7 @@ #include "suites/functional/aql_barrier_bit.h" #include "suites/functional/signal_kernel.h" #include "suites/functional/cu_masking.h" +#include "suites/functional/filter_devices.h" #include "amd_smi/amdsmi.h" #include "common/common.h" @@ -480,6 +481,15 @@ TEST(rocrtstFunc, VirtMemory_Interprocess_Test) { ); } +TEST(rocrtstFunc, Filter_Devices_Test) { + RUN_IF_NOT_EMU_MODE( + FilterDevicesTest fd; + RunCustomTestProlog(&fd); + fd.TestRocrVisibleDevicesFiltering(); + RunCustomTestEpilog(&fd); + ); +} + TEST(rocrtstNeg, Memory_Negative_Tests) { RUN_IF_NOT_EMU_MODE( MemoryAllocateNegativeTest mt;