From a7ce50212e7e757776abeaf7fda230be338cc7ae Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Wed, 18 Mar 2026 20:02:40 +0000 Subject: [PATCH 01/19] static: Introduce STATIC If AIS_TESTING is defined, STATIC dissappears, if AIS_TESTING is not defined STATIC becomes static. This is useful in some testing scenarios. --- src/amd_detail/configuration.cpp | 11 +++-------- src/amd_detail/hip.cpp | 15 +++++---------- src/amd_detail/static.h | 15 +++++++++++++++ 3 files changed, 23 insertions(+), 18 deletions(-) create mode 100644 src/amd_detail/static.h diff --git a/src/amd_detail/configuration.cpp b/src/amd_detail/configuration.cpp index b18340d2..5282f767 100644 --- a/src/amd_detail/configuration.cpp +++ b/src/amd_detail/configuration.cpp @@ -6,6 +6,7 @@ #include "configuration.h" #include "environment.h" #include "hip.h" +#include "static.h" #include @@ -32,14 +33,8 @@ Configuration::Configuration() : m_fastpath(true), m_fallback(true), m_statsLeve bool Configuration::fastpath() const noexcept { -#ifndef AIS_TESTING - static -#endif - bool readExists{!!getHipAmdFileReadPtr()}; -#ifndef AIS_TESTING - static -#endif - bool writeExists{!!getHipAmdFileWritePtr()}; + STATIC bool readExists{!!getHipAmdFileReadPtr()}; + STATIC bool writeExists{!!getHipAmdFileWritePtr()}; return readExists && writeExists && m_fastpath; } diff --git a/src/amd_detail/hip.cpp b/src/amd_detail/hip.cpp index 963495d6..df3e89f7 100644 --- a/src/amd_detail/hip.cpp +++ b/src/amd_detail/hip.cpp @@ -5,6 +5,7 @@ #include "context.h" #include "hip.h" +#include "static.h" #include #include @@ -24,22 +25,16 @@ catch (...) { hipAmdFileRead_t getHipAmdFileReadPtr() { -#ifndef AIS_TESTING - static -#endif - hipAmdFileRead_t hipAmdFileReadPtr{ - reinterpret_cast(hipGetProcAddressHelper("hipAmdFileRead"))}; + STATIC hipAmdFileRead_t hipAmdFileReadPtr{ + reinterpret_cast(hipGetProcAddressHelper("hipAmdFileRead"))}; return hipAmdFileReadPtr; } hipAmdFileWrite_t getHipAmdFileWritePtr() { -#ifndef AIS_TESTING - static -#endif - hipAmdFileWrite_t hipAmdFileWritePtr{ - reinterpret_cast(hipGetProcAddressHelper("hipAmdFileWrite"))}; + STATIC hipAmdFileWrite_t hipAmdFileWritePtr{ + reinterpret_cast(hipGetProcAddressHelper("hipAmdFileWrite"))}; return hipAmdFileWritePtr; } diff --git a/src/amd_detail/static.h b/src/amd_detail/static.h new file mode 100644 index 00000000..dbb2894d --- /dev/null +++ b/src/amd_detail/static.h @@ -0,0 +1,15 @@ +/* Copyright (c) Advanced Micro Devices, Inc. All rights reserved. + * + * SPDX-License-Identifier: MIT + */ + +#pragma once + +// When testing it is sometimes inconvenient if a variable is statically initialized. +// Declaring a variable as STATIC will result in the variable being static only +// when tests are not being built. +#ifdef AIS_TESTING +#define STATIC +#else +#define STATIC static +#endif From 6086baae6255065d1c867ebaebff45d2352cdf9b Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Wed, 18 Mar 2026 21:25:29 +0000 Subject: [PATCH 02/19] configuration: Allow MConfiguration to replace Configuration in Context Previously, when MConfiguration inherited from IConfiguration compilers complained when you tried to do `StrictMock`. This will allow tests to use `StrictMock mcfg` and not worry about side effects of the `Configuration` constructor. --- src/amd_detail/configuration.cpp | 27 ++---- src/amd_detail/configuration.h | 26 ++---- test/amd_detail/configuration.cpp | 149 ++++++++++-------------------- test/amd_detail/mconfiguration.h | 9 +- test/amd_detail/stats.cpp | 7 +- 5 files changed, 71 insertions(+), 147 deletions(-) diff --git a/src/amd_detail/configuration.cpp b/src/amd_detail/configuration.cpp index 5282f767..74548194 100644 --- a/src/amd_detail/configuration.cpp +++ b/src/amd_detail/configuration.cpp @@ -12,40 +12,25 @@ using namespace hipFile; -Configuration::Configuration() : m_fastpath(true), m_fallback(true), m_statsLevel(0) -{ - auto maybe_env_force_compat{Environment::force_compat_mode()}; - if (maybe_env_force_compat && maybe_env_force_compat.value()) { - m_fastpath = false; - } - - auto maybe_env_allow_compat{Environment::allow_compat_mode()}; - if (maybe_env_allow_compat && !maybe_env_allow_compat.value()) { - m_fallback = false; - } - - auto maybe_stats_level{Environment::stats_level()}; - if (maybe_stats_level) { - m_statsLevel = maybe_stats_level.value(); - } -} - bool Configuration::fastpath() const noexcept { + STATIC bool fastpath_env{!Environment::force_compat_mode().value_or(false)}; STATIC bool readExists{!!getHipAmdFileReadPtr()}; STATIC bool writeExists{!!getHipAmdFileWritePtr()}; - return readExists && writeExists && m_fastpath; + return readExists && writeExists && fastpath_env; } bool Configuration::fallback() const noexcept { - return m_fallback; + STATIC bool fallback_env{Environment::allow_compat_mode().value_or(true)}; + return fallback_env; } unsigned int Configuration::statsLevel() const noexcept { - return m_statsLevel; + STATIC unsigned int stats_level_env{Environment::stats_level().value_or(0)}; + return stats_level_env; } diff --git a/src/amd_detail/configuration.h b/src/amd_detail/configuration.h index a556b28d..9bec4ef6 100644 --- a/src/amd_detail/configuration.h +++ b/src/amd_detail/configuration.h @@ -7,36 +7,22 @@ namespace hipFile { -class IConfiguration { +class Configuration { + public: - virtual ~IConfiguration() - { - } + virtual ~Configuration() = default; /// @brief Checks if the fastpath backend is enabled /// @return true if the fastpath backend is enabled, false otherwise - virtual bool fastpath() const noexcept = 0; + virtual bool fastpath() const noexcept; /// @brief Checks if the fallback backend is enabled /// @return true if the fallback backend is enabled, false otherwise - virtual bool fallback() const noexcept = 0; + virtual bool fallback() const noexcept; /// @brief Shows the level of detail for stats collection /// @return 0 if stats collection disabled, higher levels of detail as value increases - virtual unsigned int statsLevel() const noexcept = 0; -}; - -class Configuration : public IConfiguration { - bool m_fastpath; - bool m_fallback; - unsigned int m_statsLevel; - -public: - Configuration(); - - bool fastpath() const noexcept override; - bool fallback() const noexcept override; - unsigned int statsLevel() const noexcept override; + virtual unsigned int statsLevel() const noexcept; }; } diff --git a/test/amd_detail/configuration.cpp b/test/amd_detail/configuration.cpp index 737b10b9..46c1773d 100644 --- a/test/amd_detail/configuration.cpp +++ b/test/amd_detail/configuration.cpp @@ -20,166 +20,111 @@ using namespace std; HIPFILE_WARN_NO_GLOBAL_CTOR_OFF -struct ConfigurationExpectation; - -struct ConfigurationExpectationBuilder { - StrictMock &m_msys; - StrictMock &m_mhip; - std::optional m_env_force_compat_mode; - std::optional m_env_allow_compat_mode; - std::optional m_env_stats_level; - void *m_hip_amd_file_read{reinterpret_cast(0xDEADBEEF)}; - void *m_hip_amd_file_write{reinterpret_cast(0x0BADF00D)}; - bool m_fastpath{false}; - - ConfigurationExpectationBuilder(StrictMock &msys, StrictMock &mhip) - : m_msys(msys), m_mhip(mhip) - { - } - - ConfigurationExpectationBuilder &env_force_compat_mode(const char *value) - { - m_env_force_compat_mode = value; - return *this; - } - - ConfigurationExpectationBuilder &env_allow_compat_mode(const char *value) - { - m_env_allow_compat_mode = value; - return *this; - } - - ConfigurationExpectationBuilder &env_stats_level(const char *value) - { - m_env_stats_level = value; - return *this; - } +struct HipFileConfiguration : public Test { + StrictMock msys; + StrictMock mhip; - ConfigurationExpectationBuilder &hip_amd_file_read(void *value) + void expect_configuration_fastpath(const char *hipfile_force_compat_mode, + void *hipAmdFileRead = reinterpret_cast(0xDEADBEEF), + void *hipAmdFileWrite = reinterpret_cast(0xCAFEBABE)) { - m_hip_amd_file_read = value; - return *this; + EXPECT_CALL(msys, getenv(StrEq(hipFile::Environment::FORCE_COMPAT_MODE))) + .WillOnce(Return(const_cast(hipfile_force_compat_mode))); + EXPECT_CALL(mhip, hipRuntimeGetVersion).Times(2); + EXPECT_CALL(mhip, hipGetProcAddress(StrEq("hipAmdFileRead"), _, _, _)) + .WillOnce(Return(hipAmdFileRead)); + EXPECT_CALL(mhip, hipGetProcAddress(StrEq("hipAmdFileWrite"), _, _, _)) + .WillOnce(Return(hipAmdFileWrite)); } - ConfigurationExpectationBuilder &hip_amd_file_write(void *value) + void expect_configuration_fallback(const char *hipfile_allow_compat_mode) { - m_hip_amd_file_write = value; - return *this; + EXPECT_CALL(msys, getenv(StrEq(hipFile::Environment::ALLOW_COMPAT_MODE))) + .WillOnce(Return(const_cast(hipfile_allow_compat_mode))); } - ConfigurationExpectationBuilder &fastpath() + void expect_configuration_statslevel(const char *hipfile_stats_level) { - m_fastpath = true; - return *this; + EXPECT_CALL(msys, getenv(StrEq(hipFile::Environment::STATS_LEVEL))) + .WillOnce(Return(const_cast(hipfile_stats_level))); } - - ConfigurationExpectation build(); }; -struct ConfigurationExpectation { - ConfigurationExpectation(const ConfigurationExpectationBuilder &builder) - { - if (builder.m_env_force_compat_mode) { - EXPECT_CALL(builder.m_msys, getenv(StrEq(hipFile::Environment::FORCE_COMPAT_MODE))) - .WillOnce(Return(const_cast(builder.m_env_force_compat_mode.value()))); - } - else { - EXPECT_CALL(builder.m_msys, getenv(StrEq(hipFile::Environment::FORCE_COMPAT_MODE))); - } - - if (builder.m_env_allow_compat_mode) { - EXPECT_CALL(builder.m_msys, getenv(StrEq(hipFile::Environment::ALLOW_COMPAT_MODE))) - .WillOnce(Return(const_cast(builder.m_env_allow_compat_mode.value()))); - } - else { - EXPECT_CALL(builder.m_msys, getenv(StrEq(hipFile::Environment::ALLOW_COMPAT_MODE))); - } - - if (builder.m_env_stats_level) { - EXPECT_CALL(builder.m_msys, getenv(StrEq(hipFile::Environment::STATS_LEVEL))) - .WillOnce(Return(const_cast(builder.m_env_stats_level.value()))); - } - else { - EXPECT_CALL(builder.m_msys, getenv(StrEq(hipFile::Environment::STATS_LEVEL))); - } - if (builder.m_fastpath) { - EXPECT_CALL(builder.m_mhip, hipRuntimeGetVersion).Times(2); - EXPECT_CALL(builder.m_mhip, hipGetProcAddress(StrEq("hipAmdFileRead"), _, _, _)) - .WillOnce(Return(builder.m_hip_amd_file_read)); - EXPECT_CALL(builder.m_mhip, hipGetProcAddress(StrEq("hipAmdFileWrite"), _, _, _)) - .WillOnce(Return(builder.m_hip_amd_file_write)); - } - } -}; - -ConfigurationExpectation -ConfigurationExpectationBuilder::build() +TEST_F(HipFileConfiguration, FastpathEnabledIfForceCompatModeEnvironmentVariableIsNotSet) { - return ConfigurationExpectation(*this); + expect_configuration_fastpath(nullptr); + ASSERT_TRUE(Configuration().fastpath()); } -struct HipFileConfiguration : public Test { - StrictMock msys; - StrictMock mhip; -}; - -TEST_F(HipFileConfiguration, FastpathEnabledIfForceCompatModeEnvironmentVariableIsNotSetOrInvalid) +TEST_F(HipFileConfiguration, FastpathEnabledIfForceCompatModeEnvironmentVariableIsInvalid) { - ConfigurationExpectationBuilder{msys, mhip}.fastpath().build(); + expect_configuration_fastpath("not-a-bool"); ASSERT_TRUE(Configuration().fastpath()); } TEST_F(HipFileConfiguration, FastpathEnabledIfForceCompatModeEnvironmentVariableIsFalse) { - ConfigurationExpectationBuilder{msys, mhip}.fastpath().env_force_compat_mode("false").build(); + expect_configuration_fastpath("false"); ASSERT_TRUE(Configuration().fastpath()); } TEST_F(HipFileConfiguration, FastpathDisabledIfForceCompatModeEnvironmentVariableIsTrue) { - ConfigurationExpectationBuilder{msys, mhip}.fastpath().env_force_compat_mode("true").build(); + expect_configuration_fastpath("true"); ASSERT_FALSE(Configuration().fastpath()); } TEST_F(HipFileConfiguration, FastpathDisabledIfHipAmdFileReadIsNotFound) { - ConfigurationExpectationBuilder{msys, mhip}.fastpath().hip_amd_file_read(nullptr).build(); + expect_configuration_fastpath(nullptr, nullptr); ASSERT_FALSE(Configuration().fastpath()); } TEST_F(HipFileConfiguration, FastpathDisabledIfHipAmdFileWriteIsNotFound) { - ConfigurationExpectationBuilder{msys, mhip}.fastpath().hip_amd_file_write(nullptr).build(); + expect_configuration_fastpath(nullptr, reinterpret_cast(0x1), nullptr); ASSERT_FALSE(Configuration().fastpath()); } -TEST_F(HipFileConfiguration, FallbackEnabledIfAllowCompatModeEnvironmentVariableIsNotSetOrInvalid) +TEST_F(HipFileConfiguration, FallbackEnabledIfAllowCompatModeEnvironmentVariableIsNotSet) { - ConfigurationExpectationBuilder{msys, mhip}.build(); + expect_configuration_fallback(nullptr); + ASSERT_TRUE(Configuration().fallback()); +} + +TEST_F(HipFileConfiguration, FallbackEnabledIfAllowCompatModeEnvironmentVariableIsInvalid) +{ + expect_configuration_fallback("not-a-bool"); ASSERT_TRUE(Configuration().fallback()); } TEST_F(HipFileConfiguration, FallbackEnabledIfAllowCompatModeEnvironmentVariableIsTrue) { - ConfigurationExpectationBuilder{msys, mhip}.env_allow_compat_mode("true").build(); + expect_configuration_fallback("true"); ASSERT_TRUE(Configuration().fallback()); } TEST_F(HipFileConfiguration, FallbackDisabledIfAllowCompatModeEnvironmentVariableIsFalse) { - ConfigurationExpectationBuilder{msys, mhip}.env_allow_compat_mode("false").build(); + expect_configuration_fallback("false"); ASSERT_FALSE(Configuration().fallback()); } -TEST_F(HipFileConfiguration, StatsLevelEnvironmentVariableIsNotSetOrInvalid) +TEST_F(HipFileConfiguration, StatsLevelEnvironmentVariableIsNotSet) +{ + expect_configuration_statslevel(nullptr); + ASSERT_EQ(0, Configuration().statsLevel()); +} + +TEST_F(HipFileConfiguration, StatsLevelEnvironmentVariableIsInvalid) { - ConfigurationExpectationBuilder{msys, mhip}.build(); + expect_configuration_statslevel("not-a-number"); ASSERT_EQ(0, Configuration().statsLevel()); } TEST_F(HipFileConfiguration, StatsLevelEnvironmentVariableIsSet) { - ConfigurationExpectationBuilder{msys, mhip}.env_stats_level("1").build(); + expect_configuration_statslevel("1"); ASSERT_EQ(1, Configuration().statsLevel()); } diff --git a/test/amd_detail/mconfiguration.h b/test/amd_detail/mconfiguration.h index a0a75704..d1d06974 100644 --- a/test/amd_detail/mconfiguration.h +++ b/test/amd_detail/mconfiguration.h @@ -6,12 +6,17 @@ #pragma once #include "configuration.h" +#include "context.h" #include -namespace rocFile { +namespace hipFile { -struct MConfiguration : IConfiguration { +struct MConfiguration : Configuration { + ContextOverride co; + MConfiguration() : co{this} + { + } MOCK_METHOD(bool, fastpath, (), (const, noexcept, override)); MOCK_METHOD(bool, fallback, (), (const, noexcept, override)); MOCK_METHOD(unsigned int, statsLevel, (), (const, noexcept, override)); diff --git a/test/amd_detail/stats.cpp b/test/amd_detail/stats.cpp index 304057fe..356cbdb8 100644 --- a/test/amd_detail/stats.cpp +++ b/test/amd_detail/stats.cpp @@ -4,6 +4,7 @@ */ #include "hipfile-test.h" +#include "mconfiguration.h" #include "mstats.h" #include "stats.h" #include "msys.h" @@ -45,8 +46,9 @@ STAT_TEST(FallbackPathWrite) TEST_F(HipFileStats, StatsServerLifetime) { - StrictMock msys{}; - char buff[sizeof(Stats)]; + StrictMock msys{}; + StrictMock mcfg{}; + char buff[sizeof(Stats)]; EXPECT_CALL(msys, memfd_create).WillOnce(testing::Return(10)); EXPECT_CALL(msys, eventfd).WillOnce(testing::Return(11)); EXPECT_CALL(msys, fcntl).WillOnce(testing::Return(0)); @@ -54,6 +56,7 @@ TEST_F(HipFileStats, StatsServerLifetime) EXPECT_CALL(msys, mmap).WillOnce(testing::Return(&buff)); EXPECT_CALL(msys, munmap); EXPECT_CALL(msys, close).Times(2); + EXPECT_CALL(mcfg, statsLevel()).WillOnce(testing::Return(1)); StatsServer srvr{}; } From 81a73c21b28cf44df83b8866705d3512b390e533 Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Wed, 18 Mar 2026 02:32:08 +0000 Subject: [PATCH 03/19] configuration: Allow fastpath enablement to be overridden --- src/amd_detail/configuration.cpp | 8 +++++- src/amd_detail/configuration.h | 10 +++++++ test/amd_detail/configuration.cpp | 44 +++++++++++++++++++++++++++++++ test/amd_detail/mconfiguration.h | 1 + 4 files changed, 62 insertions(+), 1 deletion(-) diff --git a/src/amd_detail/configuration.cpp b/src/amd_detail/configuration.cpp index 74548194..47d494df 100644 --- a/src/amd_detail/configuration.cpp +++ b/src/amd_detail/configuration.cpp @@ -18,7 +18,13 @@ Configuration::fastpath() const noexcept STATIC bool fastpath_env{!Environment::force_compat_mode().value_or(false)}; STATIC bool readExists{!!getHipAmdFileReadPtr()}; STATIC bool writeExists{!!getHipAmdFileWritePtr()}; - return readExists && writeExists && fastpath_env; + return readExists && writeExists && m_fastpath_override.value_or(fastpath_env); +} + +void +Configuration::fastpath(bool enabled) noexcept +{ + m_fastpath_override = enabled; } bool diff --git a/src/amd_detail/configuration.h b/src/amd_detail/configuration.h index 9bec4ef6..ed689422 100644 --- a/src/amd_detail/configuration.h +++ b/src/amd_detail/configuration.h @@ -5,10 +5,14 @@ #pragma once +#include + namespace hipFile { class Configuration { + std::optional m_fastpath_override; + public: virtual ~Configuration() = default; @@ -16,6 +20,12 @@ class Configuration { /// @return true if the fastpath backend is enabled, false otherwise virtual bool fastpath() const noexcept; + /// @brief Override fastpath backend enablement. + /// + /// If hipAmdFileRead/hipAmdFileWrite are not available fastpath() will + /// return false even if fastpath(true) is called. + virtual void fastpath(bool enabled) noexcept; + /// @brief Checks if the fallback backend is enabled /// @return true if the fallback backend is enabled, false otherwise virtual bool fallback() const noexcept; diff --git a/test/amd_detail/configuration.cpp b/test/amd_detail/configuration.cpp index 46c1773d..4da10e10 100644 --- a/test/amd_detail/configuration.cpp +++ b/test/amd_detail/configuration.cpp @@ -68,6 +68,17 @@ TEST_F(HipFileConfiguration, FastpathEnabledIfForceCompatModeEnvironmentVariable ASSERT_TRUE(Configuration().fastpath()); } +TEST_F(HipFileConfiguration, OverrideEnabledFastpathBackend) +{ + Configuration config{}; + expect_configuration_fastpath("false"); + ASSERT_TRUE(config.fastpath()); + + config.fastpath(false); + expect_configuration_fastpath("false"); + ASSERT_FALSE(config.fastpath()); +} + TEST_F(HipFileConfiguration, FastpathDisabledIfForceCompatModeEnvironmentVariableIsTrue) { expect_configuration_fastpath("true"); @@ -86,6 +97,39 @@ TEST_F(HipFileConfiguration, FastpathDisabledIfHipAmdFileWriteIsNotFound) ASSERT_FALSE(Configuration().fastpath()); } +TEST_F(HipFileConfiguration, OverrideDisabledFastpathBackend) +{ + Configuration config{}; + expect_configuration_fastpath("true"); + ASSERT_FALSE(config.fastpath()); + + config.fastpath(true); + expect_configuration_fastpath("true"); + ASSERT_TRUE(config.fastpath()); +} + +TEST_F(HipFileConfiguration, CantOverrideDisabledFastpathBackendIfHipAmdFileReadIsNotAvailable) +{ + Configuration config{}; + expect_configuration_fastpath(nullptr, nullptr); + ASSERT_FALSE(config.fastpath()); + + config.fastpath(true); + expect_configuration_fastpath(nullptr, nullptr); + ASSERT_FALSE(config.fastpath()); +} + +TEST_F(HipFileConfiguration, CantOverrideDisabledFastpathBackendIfHipAmdFileWriteIsNotAvailable) +{ + Configuration config{}; + expect_configuration_fastpath(nullptr, reinterpret_cast(0x1), nullptr); + ASSERT_FALSE(config.fastpath()); + + config.fastpath(true); + expect_configuration_fastpath(nullptr, reinterpret_cast(0x1), nullptr); + ASSERT_FALSE(config.fastpath()); +} + TEST_F(HipFileConfiguration, FallbackEnabledIfAllowCompatModeEnvironmentVariableIsNotSet) { expect_configuration_fallback(nullptr); diff --git a/test/amd_detail/mconfiguration.h b/test/amd_detail/mconfiguration.h index d1d06974..20418d39 100644 --- a/test/amd_detail/mconfiguration.h +++ b/test/amd_detail/mconfiguration.h @@ -18,6 +18,7 @@ struct MConfiguration : Configuration { { } MOCK_METHOD(bool, fastpath, (), (const, noexcept, override)); + MOCK_METHOD(void, fastpath, (bool), (noexcept, override)); MOCK_METHOD(bool, fallback, (), (const, noexcept, override)); MOCK_METHOD(unsigned int, statsLevel, (), (const, noexcept, override)); }; From ad176c39925c84997f604c21e3cff672438211ac Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Wed, 18 Mar 2026 02:32:08 +0000 Subject: [PATCH 04/19] configuration: Allow fallback enablement to be overridden --- src/amd_detail/configuration.cpp | 8 +++++++- src/amd_detail/configuration.h | 4 ++++ test/amd_detail/configuration.cpp | 22 ++++++++++++++++++++++ test/amd_detail/mconfiguration.h | 1 + 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/amd_detail/configuration.cpp b/src/amd_detail/configuration.cpp index 47d494df..7bf89583 100644 --- a/src/amd_detail/configuration.cpp +++ b/src/amd_detail/configuration.cpp @@ -31,7 +31,13 @@ bool Configuration::fallback() const noexcept { STATIC bool fallback_env{Environment::allow_compat_mode().value_or(true)}; - return fallback_env; + return m_fallback_override.value_or(fallback_env); +} + +void +Configuration::fallback(bool enabled) noexcept +{ + m_fallback_override = enabled; } unsigned int diff --git a/src/amd_detail/configuration.h b/src/amd_detail/configuration.h index ed689422..8648a62d 100644 --- a/src/amd_detail/configuration.h +++ b/src/amd_detail/configuration.h @@ -12,6 +12,7 @@ namespace hipFile { class Configuration { std::optional m_fastpath_override; + std::optional m_fallback_override; public: virtual ~Configuration() = default; @@ -30,6 +31,9 @@ class Configuration { /// @return true if the fallback backend is enabled, false otherwise virtual bool fallback() const noexcept; + /// @brief Override fallback backend enablement + virtual void fallback(bool enabled) noexcept; + /// @brief Shows the level of detail for stats collection /// @return 0 if stats collection disabled, higher levels of detail as value increases virtual unsigned int statsLevel() const noexcept; diff --git a/test/amd_detail/configuration.cpp b/test/amd_detail/configuration.cpp index 4da10e10..e465f99f 100644 --- a/test/amd_detail/configuration.cpp +++ b/test/amd_detail/configuration.cpp @@ -148,12 +148,34 @@ TEST_F(HipFileConfiguration, FallbackEnabledIfAllowCompatModeEnvironmentVariable ASSERT_TRUE(Configuration().fallback()); } +TEST_F(HipFileConfiguration, OverrideEnabledFallbackBackend) +{ + Configuration config{}; + expect_configuration_fallback(nullptr); + ASSERT_TRUE(config.fallback()); + + config.fallback(false); + expect_configuration_fallback(nullptr); + ASSERT_FALSE(config.fallback()); +} + TEST_F(HipFileConfiguration, FallbackDisabledIfAllowCompatModeEnvironmentVariableIsFalse) { expect_configuration_fallback("false"); ASSERT_FALSE(Configuration().fallback()); } +TEST_F(HipFileConfiguration, OverrideDisabledFallbackBackend) +{ + Configuration config{}; + expect_configuration_fallback("false"); + ASSERT_FALSE(config.fallback()); + + config.fallback(true); + expect_configuration_fallback("false"); + ASSERT_TRUE(config.fallback()); +} + TEST_F(HipFileConfiguration, StatsLevelEnvironmentVariableIsNotSet) { expect_configuration_statslevel(nullptr); diff --git a/test/amd_detail/mconfiguration.h b/test/amd_detail/mconfiguration.h index 20418d39..fe910247 100644 --- a/test/amd_detail/mconfiguration.h +++ b/test/amd_detail/mconfiguration.h @@ -20,6 +20,7 @@ struct MConfiguration : Configuration { MOCK_METHOD(bool, fastpath, (), (const, noexcept, override)); MOCK_METHOD(void, fastpath, (bool), (noexcept, override)); MOCK_METHOD(bool, fallback, (), (const, noexcept, override)); + MOCK_METHOD(void, fallback, (bool), (noexcept, override)); MOCK_METHOD(unsigned int, statsLevel, (), (const, noexcept, override)); }; From cccbb9d8c742dafddd8a8f9d7792289e3751f437 Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Wed, 18 Mar 2026 02:40:05 +0000 Subject: [PATCH 05/19] backend/fastpath: Check fastpath enablement when scoring IO --- src/amd_detail/backend/fastpath.cpp | 3 +++ test/amd_detail/fastpath.cpp | 42 +++++++++++++++++++++++++---- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/src/amd_detail/backend/fastpath.cpp b/src/amd_detail/backend/fastpath.cpp index aba587c8..047e6a5b 100644 --- a/src/amd_detail/backend/fastpath.cpp +++ b/src/amd_detail/backend/fastpath.cpp @@ -4,6 +4,7 @@ */ #include "buffer.h" +#include "configuration.h" #include "context.h" #include "fastpath.h" #include "file.h" @@ -128,6 +129,8 @@ Fastpath::score(shared_ptr file, shared_ptr buffer, size_t size, { bool accept_io{true}; + accept_io &= Context::get()->fastpath(); + accept_io &= file->getUnbufferedFd().has_value(); accept_io &= buffer->getType() == hipMemoryTypeDevice; diff --git a/test/amd_detail/fastpath.cpp b/test/amd_detail/fastpath.cpp index 258f29d0..ff4e7545 100644 --- a/test/amd_detail/fastpath.cpp +++ b/test/amd_detail/fastpath.cpp @@ -10,6 +10,7 @@ #include "hipfile-warnings.h" #include "io.h" #include "mbuffer.h" +#include "mconfiguration.h" #include "mfile.h" #include "mhip.h" @@ -53,6 +54,7 @@ operator==(const hipAmdFileHandle_t &lhs, const hipAmdFileHandle_t &rhs) // Provide default values for variables used in fastpath tests struct FastpathTestBase { + const bool DEFAULT_ENABLE{true}; const size_t DEFAULT_IO_SIZE{1024 * 1024}; void *const DEFAULT_BUFFER_ADDR{reinterpret_cast(0xABAD'CAFE'0000'0000)}; const off_t DEFAULT_BUFFER_OFFSET{DEFAULT_MEM_ALIGN}; @@ -75,12 +77,15 @@ struct FastpathTestBase { // Buffer and file mocks used to setup expectations shared_ptr> mfile{make_shared>()}; shared_ptr> mbuffer{make_shared>()}; + + StrictMock mcfg{}; }; struct FastpathTest : public FastpathTestBase, public Test {}; TEST_F(FastpathTest, TestDefaults) { + ASSERT_TRUE(DEFAULT_ENABLE); ASSERT_FALSE((DEFAULT_MEM_ALIGN & (DEFAULT_MEM_ALIGN - 1))); ASSERT_TRUE(DEFAULT_MEM_ALIGN > 1); ASSERT_FALSE((DEFAULT_OFFSET_ALIGN & (DEFAULT_OFFSET_ALIGN - 1))); @@ -91,8 +96,9 @@ TEST_F(FastpathTest, TestDefaults) ASSERT_FALSE((DEFAULT_FILE_OFFSET & (DEFAULT_OFFSET_ALIGN - 1))); } -TEST_F(FastpathTest, UnbufferedFdAvailable) +TEST_F(FastpathTest, ScoreAcceptsIoWithDefaults) { + EXPECT_CALL(mcfg, fastpath()).WillOnce(Return(DEFAULT_ENABLE)); EXPECT_CALL(*mfile, getUnbufferedFd).WillOnce(Return(DEFAULT_UNBUFFERED_FD)); EXPECT_CALL(*mbuffer, getType).WillOnce(Return(DEFAULT_BUFFER_TYPE)); #if defined(STATX_DIOALIGN) @@ -104,8 +110,23 @@ TEST_F(FastpathTest, UnbufferedFdAvailable) SCORE_ACCEPT); } -TEST_F(FastpathTest, UnbufferedFdNotAvailable) +TEST_F(FastpathTest, ScoreRejectsIoIfFastpathIsDisabled) +{ + EXPECT_CALL(mcfg, fastpath()).WillOnce(Return(false)); + EXPECT_CALL(*mfile, getUnbufferedFd).WillOnce(Return(DEFAULT_UNBUFFERED_FD)); + EXPECT_CALL(*mbuffer, getType).WillOnce(Return(DEFAULT_BUFFER_TYPE)); +#if defined(STATX_DIOALIGN) + EXPECT_CALL(*mfile, getStatx).WillOnce(ReturnRef(DEFAULT_STATX)); +#endif + EXPECT_CALL(*mbuffer, getBuffer).WillOnce(Return(DEFAULT_BUFFER_ADDR)); + + ASSERT_EQ(Fastpath().score(mfile, mbuffer, DEFAULT_IO_SIZE, DEFAULT_FILE_OFFSET, DEFAULT_BUFFER_OFFSET), + SCORE_REJECT); +} + +TEST_F(FastpathTest, ScoreRejectsIoIfUnbufferedFdNotAvailable) { + EXPECT_CALL(mcfg, fastpath()).WillOnce(Return(DEFAULT_ENABLE)); EXPECT_CALL(*mfile, getUnbufferedFd).WillOnce(Return(nullopt)); EXPECT_CALL(*mbuffer, getType).WillOnce(Return(DEFAULT_BUFFER_TYPE)); #if defined(STATX_DIOALIGN) @@ -117,8 +138,9 @@ TEST_F(FastpathTest, UnbufferedFdNotAvailable) SCORE_REJECT); } -TEST_F(FastpathTest, ScoreRejectsNegativeAlignedFileOffset) +TEST_F(FastpathTest, ScoreRejectsIoWithNegativeAlignedFileOffset) { + EXPECT_CALL(mcfg, fastpath()).WillOnce(Return(DEFAULT_ENABLE)); EXPECT_CALL(*mfile, getUnbufferedFd).WillOnce(Return(DEFAULT_UNBUFFERED_FD)); EXPECT_CALL(*mbuffer, getType).WillOnce(Return(DEFAULT_BUFFER_TYPE)); #if defined(STATX_DIOALIGN) @@ -131,8 +153,9 @@ TEST_F(FastpathTest, ScoreRejectsNegativeAlignedFileOffset) SCORE_REJECT); } -TEST_F(FastpathTest, ScoreRejectsNegativeAlignedBufferOffset) +TEST_F(FastpathTest, ScoreRejectsIoWithNegativeAlignedBufferOffset) { + EXPECT_CALL(mcfg, fastpath()).WillOnce(Return(DEFAULT_ENABLE)); EXPECT_CALL(*mfile, getUnbufferedFd).WillOnce(Return(DEFAULT_UNBUFFERED_FD)); EXPECT_CALL(*mbuffer, getType).WillOnce(Return(DEFAULT_BUFFER_TYPE)); #if defined(STATX_DIOALIGN) @@ -145,8 +168,9 @@ TEST_F(FastpathTest, ScoreRejectsNegativeAlignedBufferOffset) SCORE_REJECT); } -TEST_F(FastpathTest, ScoreRejectsBufferAddressPlusBufferOffsetIsUnaligned) +TEST_F(FastpathTest, ScoreRejectsIoIfBufferAddressPlusBufferOffsetIsUnaligned) { + EXPECT_CALL(mcfg, fastpath()).WillOnce(Return(DEFAULT_ENABLE)); EXPECT_CALL(*mfile, getUnbufferedFd).WillOnce(Return(DEFAULT_UNBUFFERED_FD)); EXPECT_CALL(*mbuffer, getType).WillOnce(Return(DEFAULT_BUFFER_TYPE)); #if defined(STATX_DIOALIGN) @@ -167,6 +191,7 @@ struct FastpathSupportedHipMemoryParam : public FastpathTestBase, public TestWit TEST_P(FastpathSupportedHipMemoryParam, Score) { + EXPECT_CALL(mcfg, fastpath()).WillOnce(Return(DEFAULT_ENABLE)); EXPECT_CALL(*mfile, getUnbufferedFd).WillOnce(Return(DEFAULT_UNBUFFERED_FD)); EXPECT_CALL(*mbuffer, getType).WillOnce(Return(GetParam())); #if defined(STATX_DIOALIGN) @@ -184,6 +209,7 @@ struct FastpathUnsupportedHipMemoryParam : public FastpathTestBase, public TestW TEST_P(FastpathUnsupportedHipMemoryParam, Score) { + EXPECT_CALL(mcfg, fastpath()).WillOnce(Return(DEFAULT_ENABLE)); EXPECT_CALL(*mfile, getUnbufferedFd).WillOnce(Return(DEFAULT_UNBUFFERED_FD)); EXPECT_CALL(*mbuffer, getType).WillOnce(Return(GetParam())); #if defined(STATX_DIOALIGN) @@ -202,6 +228,7 @@ struct FastpathAlignedIoSizesParam : public FastpathTestBase, public TestWithPar TEST_P(FastpathAlignedIoSizesParam, Score) { + EXPECT_CALL(mcfg, fastpath()).WillOnce(Return(DEFAULT_ENABLE)); EXPECT_CALL(*mfile, getUnbufferedFd).WillOnce(Return(DEFAULT_UNBUFFERED_FD)); EXPECT_CALL(*mbuffer, getType).WillOnce(Return(DEFAULT_BUFFER_TYPE)); #if defined(STATX_DIOALIGN) @@ -221,6 +248,7 @@ struct FastpathUnalignedIoSizesParam : public FastpathTestBase, public TestWithP TEST_P(FastpathUnalignedIoSizesParam, Score) { + EXPECT_CALL(mcfg, fastpath()).WillOnce(Return(DEFAULT_ENABLE)); EXPECT_CALL(*mfile, getUnbufferedFd).WillOnce(Return(DEFAULT_UNBUFFERED_FD)); EXPECT_CALL(*mbuffer, getType).WillOnce(Return(DEFAULT_BUFFER_TYPE)); #if defined(STATX_DIOALIGN) @@ -240,6 +268,7 @@ struct FastpathAlignedFileOffsetsParam : public FastpathTestBase, public TestWit TEST_P(FastpathAlignedFileOffsetsParam, Score) { + EXPECT_CALL(mcfg, fastpath()).WillOnce(Return(DEFAULT_ENABLE)); EXPECT_CALL(*mfile, getUnbufferedFd).WillOnce(Return(DEFAULT_UNBUFFERED_FD)); EXPECT_CALL(*mbuffer, getType).WillOnce(Return(DEFAULT_BUFFER_TYPE)); #if defined(STATX_DIOALIGN) @@ -261,6 +290,7 @@ struct FastpathUnalignedFileOffsetsParam : public FastpathTestBase, public TestW TEST_P(FastpathUnalignedFileOffsetsParam, Score) { + EXPECT_CALL(mcfg, fastpath()).WillOnce(Return(DEFAULT_ENABLE)); EXPECT_CALL(*mfile, getUnbufferedFd).WillOnce(Return(DEFAULT_UNBUFFERED_FD)); EXPECT_CALL(*mbuffer, getType).WillOnce(Return(DEFAULT_BUFFER_TYPE)); #if defined(STATX_DIOALIGN) @@ -284,6 +314,7 @@ struct FastpathAlignedBufferOffsetsParam : public FastpathTestBase, public TestW TEST_P(FastpathAlignedBufferOffsetsParam, Score) { + EXPECT_CALL(mcfg, fastpath()).WillOnce(Return(DEFAULT_ENABLE)); EXPECT_CALL(*mfile, getUnbufferedFd).WillOnce(Return(DEFAULT_UNBUFFERED_FD)); EXPECT_CALL(*mbuffer, getType).WillOnce(Return(DEFAULT_BUFFER_TYPE)); #if defined(STATX_DIOALIGN) @@ -306,6 +337,7 @@ struct FastpathUnalignedBufferOffsetsParam : public FastpathTestBase, public Tes TEST_P(FastpathUnalignedBufferOffsetsParam, Score) { + EXPECT_CALL(mcfg, fastpath()).WillOnce(Return(DEFAULT_ENABLE)); EXPECT_CALL(*mfile, getUnbufferedFd).WillOnce(Return(DEFAULT_UNBUFFERED_FD)); EXPECT_CALL(*mbuffer, getType).WillOnce(Return(DEFAULT_BUFFER_TYPE)); #if defined(STATX_DIOALIGN) From 47c4db90a977ac408b1747bf7d8196a427760ac1 Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Wed, 18 Mar 2026 02:40:05 +0000 Subject: [PATCH 06/19] backend/fastpath: Check fastpath enablement when performing IO --- src/amd_detail/backend.h | 7 +++++++ src/amd_detail/backend/fastpath.cpp | 4 ++++ test/amd_detail/fastpath.cpp | 8 ++++++++ test/amd_detail/hipfile-api.cpp | 7 +++++++ 4 files changed, 26 insertions(+) diff --git a/src/amd_detail/backend.h b/src/amd_detail/backend.h index c2e040df..aa7d970e 100644 --- a/src/amd_detail/backend.h +++ b/src/amd_detail/backend.h @@ -22,6 +22,13 @@ namespace hipFile { // write() system call. Mirrors kernel's MAX_RW_COUNT static const size_t MAX_RW_COUNT = 0x7ffff000; +/// @brief Backend is not enabled +struct BackendDisabled : public std::runtime_error { + BackendDisabled() : std::runtime_error("Backend is disabled") + { + } +}; + struct Backend { virtual ~Backend() = default; diff --git a/src/amd_detail/backend/fastpath.cpp b/src/amd_detail/backend/fastpath.cpp index 047e6a5b..972b61b2 100644 --- a/src/amd_detail/backend/fastpath.cpp +++ b/src/amd_detail/backend/fastpath.cpp @@ -161,6 +161,10 @@ ssize_t Fastpath::io(IoType type, shared_ptr file, shared_ptr buffer, size_t size, hoff_t file_offset, hoff_t buffer_offset) { + if (!Context::get()->fastpath()) { + throw BackendDisabled(); + } + void *devptr{reinterpret_cast(reinterpret_cast(buffer->getBuffer()) + buffer_offset)}; hipAmdFileHandle_t handle{}; size_t nbytes{}; diff --git a/test/amd_detail/fastpath.cpp b/test/amd_detail/fastpath.cpp index ff4e7545..25d213e3 100644 --- a/test/amd_detail/fastpath.cpp +++ b/test/amd_detail/fastpath.cpp @@ -361,6 +361,7 @@ struct FastpathIoParam : public FastpathTestBase, public TestWithParam { void expect_io() { + EXPECT_CALL(mcfg, fastpath()).WillOnce(Return(DEFAULT_ENABLE)); EXPECT_CALL(*mbuffer, getBuffer).WillOnce(Return(DEFAULT_BUFFER_ADDR)); EXPECT_CALL(*mbuffer, getLength).WillOnce(Return(DEFAULT_BUFFER_LENGTH)); EXPECT_CALL(*mfile, getUnbufferedFd).WillOnce(Return(DEFAULT_UNBUFFERED_FD)); @@ -368,12 +369,19 @@ struct FastpathIoParam : public FastpathTestBase, public TestWithParam { void expect_io(optional fd, void *bufptr, size_t buflen) { + EXPECT_CALL(mcfg, fastpath()).WillOnce(Return(DEFAULT_ENABLE)); EXPECT_CALL(*mbuffer, getBuffer).WillOnce(Return(bufptr)); EXPECT_CALL(*mbuffer, getLength).WillOnce(Return(buflen)); EXPECT_CALL(*mfile, getUnbufferedFd).WillOnce(Return(fd)); } }; +TEST_P(FastpathIoParam, IoRejectedIfFastpathDisabled) +{ + EXPECT_CALL(mcfg, fastpath()).WillOnce(Return(false)); + ASSERT_THROW(Fastpath().io(GetParam(), mfile, mbuffer, 0, -1, 0), BackendDisabled); +} + TEST_P(FastpathIoParam, IoRejectsNegativeFileOffset) { expect_io(); diff --git a/test/amd_detail/hipfile-api.cpp b/test/amd_detail/hipfile-api.cpp index 73367ffe..af9adc29 100644 --- a/test/amd_detail/hipfile-api.cpp +++ b/test/amd_detail/hipfile-api.cpp @@ -203,6 +203,13 @@ TEST_P(HipFileIoParam, HipFileIoHandlesInvalidArgumentError) ASSERT_EQ(hipFileIo(GetParam(), file_handle, bufptr, buflen, 0, 0, mbackends), -hipFileInvalidValue); } +TEST_P(HipFileIoParam, HipFileIoHandlesBackendDisabled) +{ + EXPECT_CALL(*mbackend, score).WillOnce(Return(1)); + EXPECT_CALL(*mbackend, io).WillOnce(Throw(BackendDisabled())); + ASSERT_EQ(hipFileIo(GetParam(), file_handle, bufptr, buflen, 0, 0, mbackends), -hipFileInternalError); +} + INSTANTIATE_TEST_SUITE_P(HipFileIo, HipFileIoParam, Values(IoType::Read, IoType::Write)); struct HipFileIoBackendSelectionParam : public ::testing::TestWithParam { From 3ae360df9dd57061ce4acd79a33e681db4a1b5dc Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Wed, 18 Mar 2026 15:37:01 +0000 Subject: [PATCH 07/19] backend/fallback: Test cleanup - Rework fallback scoring tests This will make it easier to add tests when fallback scoring is updated to test for fallback enablement. --- test/amd_detail/fallback.cpp | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/test/amd_detail/fallback.cpp b/test/amd_detail/fallback.cpp index dffa530c..88548011 100644 --- a/test/amd_detail/fallback.cpp +++ b/test/amd_detail/fallback.cpp @@ -139,28 +139,24 @@ struct FallbackIo : public HipFileOpened { } }; -TEST(HipFileFallbackBackend, FallbackBackendIsBarelyWillingToHandleDeviceMemory) -{ - auto mfile{std::make_shared>()}; - auto mbuffer{std::make_shared>()}; - size_t io_size{2048}; - hoff_t file_offset{4096}; - hoff_t buffer_offset{1024}; +struct FallbackScoring : public testing::Test { + const size_t io_size{2048}; + const hoff_t file_offset{4096}; + const hoff_t buffer_offset{1024}; + shared_ptr> mfile{make_shared>()}; + shared_ptr> mbuffer{make_shared>()}; +}; +TEST_F(FallbackScoring, ScoreAcceptsIoTargetingDeviceMemory) +{ EXPECT_CALL(*mbuffer, getType).WillOnce(Return(hipMemoryTypeDevice)); ASSERT_EQ(Fallback().score(mfile, mbuffer, io_size, file_offset, buffer_offset), 0); } -TEST(HipFileFallbackBackend, FallbackBackendRejectsUnsupportedHipMemoryTypes) +TEST_F(FallbackScoring, ScoreRejectsIoTargetingUnsupportedMemoryType) { - auto mfile{std::make_shared>()}; - size_t io_size{2048}; - hoff_t file_offset{4096}; - hoff_t buffer_offset{1024}; - for (const auto memoryType : UnsupportedHipMemoryTypes) { - auto mbuffer = std::make_shared>(); EXPECT_CALL(*mbuffer, getType).WillOnce(Return(memoryType)); ASSERT_EQ(Fallback().score(mfile, mbuffer, io_size, file_offset, buffer_offset), -1); } From 9ce6fa71dc55b7af0800f1b5b0a1e110adae9c65 Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Thu, 19 Mar 2026 17:05:33 +0000 Subject: [PATCH 08/19] backend/fallback: Test cleanup - Test names should use camel case --- test/amd_detail/fallback.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/amd_detail/fallback.cpp b/test/amd_detail/fallback.cpp index 88548011..d8255ffc 100644 --- a/test/amd_detail/fallback.cpp +++ b/test/amd_detail/fallback.cpp @@ -205,14 +205,14 @@ struct FallbackParam : ::testing::TestWithParam { IoType io_type; }; -TEST_P(FallbackParam, fallback_io_throws_on_negative_buffer_offset) +TEST_P(FallbackParam, FallbackIoThrowsOnNegativeBufferOffset) { StrictMock mhip; StrictMock msys; ASSERT_THROW(Fallback().io(io_type, file, buffer, 0, 0, -1, 4096), std::invalid_argument); } -TEST_P(FallbackParam, fallback_io_throws_if_buffer_offset_is_out_of_bounds) +TEST_P(FallbackParam, FallbackIoThrowsIfBufferOffsetIsOutOfBounds) { StrictMock mhip; StrictMock msys; @@ -220,7 +220,7 @@ TEST_P(FallbackParam, fallback_io_throws_if_buffer_offset_is_out_of_bounds) ASSERT_THROW(Fallback().io(io_type, file, buffer, 0, 0, buffer_offset, 4096), std::invalid_argument); } -TEST_P(FallbackParam, fallback_io_throws_if_op_could_overrun_buffer) +TEST_P(FallbackParam, FallbackIoThrowsIfOpCouldOverrunBuffer) { StrictMock mhip; StrictMock msys; @@ -229,14 +229,14 @@ TEST_P(FallbackParam, fallback_io_throws_if_op_could_overrun_buffer) ASSERT_THROW(Fallback().io(io_type, file, buffer, size, 0, buffer_offset, 4096), std::invalid_argument); } -TEST_P(FallbackParam, fallback_io_throws_on_negative_file_offset) +TEST_P(FallbackParam, FallbackIoThrowsOnNegativeFileOffset) { StrictMock mhip; StrictMock msys; ASSERT_THROW(Fallback().io(io_type, file, buffer, 0, -1, 0, 4096), std::invalid_argument); } -TEST_P(FallbackParam, fallback_io_truncates_size_to_MAX_RW_COUNT) +TEST_P(FallbackParam, FallbackIoTruncatesSizeToMAX_RW_COUNT) { StrictMock mhip; StrictMock msys; @@ -272,7 +272,7 @@ TEST_P(FallbackParam, fallback_io_truncates_size_to_MAX_RW_COUNT) ASSERT_EQ(MAX_RW_COUNT, Fallback().io(io_type, file, big_buffer, SIZE_MAX, 0, 0, 16 * 1024 * 1024)); } -TEST_P(FallbackParam, fallback_io_throws_on_bounce_buffer_allocation_failure) +TEST_P(FallbackParam, FallbackIoThrowsOnBounceBufferAllocationFailure) { StrictMock mhip; StrictMock msys; @@ -280,7 +280,7 @@ TEST_P(FallbackParam, fallback_io_throws_on_bounce_buffer_allocation_failure) ASSERT_THROW(Fallback().io(io_type, file, buffer, 4096, 0, 0, 4096), std::system_error); } -TEST_P(FallbackParam, fallback_io_allocates_chunk_sized_host_bounce_buffer) +TEST_P(FallbackParam, FallbackIoAllocatesChunkSizedHostBounceBuffer) { StrictMock mhip; StrictMock msys; From ec8c76357452dbc6fa3b6b7272d0f499fa8047fd Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Thu, 19 Mar 2026 16:49:57 +0000 Subject: [PATCH 09/19] backend/fallback: Test cleanup - Test names should use camel case --- test/amd_detail/fallback.cpp | 60 ++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/test/amd_detail/fallback.cpp b/test/amd_detail/fallback.cpp index d8255ffc..4442830d 100644 --- a/test/amd_detail/fallback.cpp +++ b/test/amd_detail/fallback.cpp @@ -355,7 +355,7 @@ struct FallbackWrite : public FallbackIo { void *nonnull_ptr = reinterpret_cast(0x1); }; -TEST_F(FallbackWrite, fallback_write_handles_zero_sized_write) +TEST_F(FallbackWrite, FallbackWriteHandlesZeroSizedWrite) { StrictMock mhip; StrictMock msys; @@ -364,7 +364,7 @@ TEST_F(FallbackWrite, fallback_write_handles_zero_sized_write) ASSERT_EQ(0, Fallback().io(IoType::Write, file, buffer, 0, 0, 0)); } -TEST_F(FallbackWrite, fallback_write_throws_on_pwrite_exception) +TEST_F(FallbackWrite, FallbackWriteThrowsOnPwriteException) { StrictMock mhip; StrictMock msys; @@ -378,7 +378,7 @@ TEST_F(FallbackWrite, fallback_write_throws_on_pwrite_exception) ASSERT_THROW(Fallback().io(IoType::Write, file, buffer, buffer->getLength(), 0, 0), std::system_error); } -TEST_F(FallbackWrite, fallback_write_throws_on_hipmemcpy_failure) +TEST_F(FallbackWrite, FallbackWriteThrowsOnHipmemcpyFailure) { StrictMock mhip; StrictMock msys; @@ -390,7 +390,7 @@ TEST_F(FallbackWrite, fallback_write_throws_on_hipmemcpy_failure) ASSERT_THROW(Fallback().io(IoType::Write, file, buffer, buffer->getLength(), 0, 0), Hip::RuntimeError); } -TEST_F(FallbackWrite, fallback_write_throws_on_hipstreamsynchronize_error) +TEST_F(FallbackWrite, FallbackWriteThrowsOnHipStreamSynchronizeError) { StrictMock mhip; StrictMock msys; @@ -403,7 +403,7 @@ TEST_F(FallbackWrite, fallback_write_throws_on_hipstreamsynchronize_error) ASSERT_THROW(Fallback().io(IoType::Write, file, buffer, buffer->getLength(), 0, 0), Hip::RuntimeError); } -TEST_F(FallbackWrite, fallback_write_to_empty_file) +TEST_F(FallbackWrite, FallbackWriteToEmptyFile) { StrictMock mhip; StrictMock msys; @@ -418,7 +418,7 @@ TEST_F(FallbackWrite, fallback_write_to_empty_file) ASSERT_TRUE(file_contains_expected_data(0, 0, size)); } -TEST_F(FallbackWrite, fallback_write_to_empty_file_at_file_offset) +TEST_F(FallbackWrite, FallbackWriteToEmptyFileAtFileOffset) { StrictMock mhip; StrictMock msys; @@ -434,7 +434,7 @@ TEST_F(FallbackWrite, fallback_write_to_empty_file_at_file_offset) ASSERT_TRUE(file_contains_expected_data(file_offset, 0, size)); } -TEST_F(FallbackWrite, fallback_write_to_empty_file_at_buffer_offset) +TEST_F(FallbackWrite, FallbackWriteToEmptyFileAtBufferOffset) { StrictMock mhip; StrictMock msys; @@ -450,7 +450,7 @@ TEST_F(FallbackWrite, fallback_write_to_empty_file_at_buffer_offset) ASSERT_TRUE(file_contains_expected_data(0, buffer_offset, size)); } -TEST_F(FallbackWrite, fallback_write_to_empty_file_at_buffer_offset_file_offset) +TEST_F(FallbackWrite, FallbackWriteToEmptyFileAtBufferOffsetFileOffset) { StrictMock mhip; StrictMock msys; @@ -467,7 +467,7 @@ TEST_F(FallbackWrite, fallback_write_to_empty_file_at_buffer_offset_file_offset) ASSERT_TRUE(file_contains_expected_data(file_offset, buffer_offset, size)); } -TEST_F(FallbackWrite, fallback_write_overwite_entire_file) +TEST_F(FallbackWrite, FallbackWriteOverwiteEntireFile) { StrictMock mhip; StrictMock msys; @@ -480,7 +480,7 @@ TEST_F(FallbackWrite, fallback_write_overwite_entire_file) ASSERT_TRUE(file_contains_expected_data(0, 0, file_data.size())); } -TEST_F(FallbackWrite, fallback_write_to_file_subregion) +TEST_F(FallbackWrite, FallbackWriteToFileSubregion) { StrictMock mhip; StrictMock msys; @@ -496,7 +496,7 @@ TEST_F(FallbackWrite, fallback_write_to_file_subregion) ASSERT_TRUE(file_contains_expected_data(file_offset, 0, buffer->getLength())); } -TEST_F(FallbackWrite, fallback_write_append_non_empty_small_file) +TEST_F(FallbackWrite, FallbackWriteAppendNonEmptySmallFile) { StrictMock mhip; StrictMock msys; @@ -569,7 +569,7 @@ struct FallbackRead : public FallbackIo { void *nonnull_ptr = reinterpret_cast(0x1); }; -TEST_F(FallbackRead, fallback_read_handles_zero_sized_read) +TEST_F(FallbackRead, FallbackReadHandlesZeroSizedRead) { StrictMock mhip; StrictMock msys; @@ -597,7 +597,7 @@ TEST_F(FallbackRead, ReadFromRegionWithinFile) ASSERT_TRUE(device_buffer_contains_expected_data(file_offset, buffer_offset, size)); } -TEST_F(FallbackRead, fallback_read_throws_on_pread_exception) +TEST_F(FallbackRead, FallbackReadThrowsOnPreadException) { StrictMock mhip; StrictMock msys; @@ -607,7 +607,7 @@ TEST_F(FallbackRead, fallback_read_throws_on_pread_exception) ASSERT_THROW(Fallback().io(IoType::Read, file, buffer, 4096, 0, 0), std::system_error); } -TEST_F(FallbackRead, fallback_read_throws_on_hipmemcpy_failure) +TEST_F(FallbackRead, FallbackReadThrowsOnHipmemcpyFailure) { StrictMock mhip; StrictMock msys; @@ -622,7 +622,7 @@ TEST_F(FallbackRead, fallback_read_throws_on_hipmemcpy_failure) ASSERT_THROW(Fallback().io(IoType::Read, file, buffer, file_length, 0, 0), Hip::RuntimeError); } -TEST_F(FallbackRead, fallback_read_handles_empty_file) +TEST_F(FallbackRead, FallbackReadHandlesEmptyFile) { StrictMock mhip; StrictMock msys; @@ -637,7 +637,7 @@ TEST_F(FallbackRead, fallback_read_handles_empty_file) ASSERT_TRUE(device_buffer_contains_expected_data(0, 0, file_length)); } -TEST_F(FallbackRead, fallback_read_handles_short_preads) +TEST_F(FallbackRead, FallbackReadHandlesShortPreads) { StrictMock mhip; StrictMock msys; @@ -659,7 +659,7 @@ TEST_F(FallbackRead, fallback_read_handles_short_preads) ASSERT_TRUE(device_buffer_contains_expected_data(0, 0, file_length)); } -TEST_F(FallbackRead, fallback_read_handles_interrupted_pread) +TEST_F(FallbackRead, FallbackReadHandlesInterruptedPread) { StrictMock mhip; StrictMock msys; @@ -679,7 +679,7 @@ TEST_F(FallbackRead, fallback_read_handles_interrupted_pread) ASSERT_TRUE(device_buffer_contains_expected_data(0, 0, file_length)); } -TEST_F(FallbackRead, fallback_read_handles_file_smaller_than_buffer) +TEST_F(FallbackRead, FallbackReadHandlesFileSmallerThanBuffer) { StrictMock mhip; StrictMock msys; @@ -692,7 +692,7 @@ TEST_F(FallbackRead, fallback_read_handles_file_smaller_than_buffer) ASSERT_TRUE(device_buffer_contains_expected_data(0, 0, file_length)); } -TEST_F(FallbackRead, fallback_read_handles_file_same_size_as_buffer) +TEST_F(FallbackRead, FallbackReadHandlesFileSameSizeAsBuffer) { StrictMock mhip; StrictMock msys; @@ -705,7 +705,7 @@ TEST_F(FallbackRead, fallback_read_handles_file_same_size_as_buffer) ASSERT_TRUE(device_buffer_contains_expected_data(0, 0, file_length)); } -TEST_F(FallbackRead, fallback_read_handles_file_larger_than_buffer) +TEST_F(FallbackRead, FallbackReadHandlesFileLargerThanBuffer) { StrictMock mhip; StrictMock msys; @@ -718,7 +718,7 @@ TEST_F(FallbackRead, fallback_read_handles_file_larger_than_buffer) ASSERT_TRUE(device_buffer_contains_expected_data(0, 0, buffer->getLength())); } -TEST_F(FallbackRead, fallback_read_handles_file_with_size_multiple_of_chunk_size) +TEST_F(FallbackRead, FallbackReadHandlesFileWithSizeMultipleOfChunkSize) { StrictMock mhip; StrictMock msys; @@ -732,7 +732,7 @@ TEST_F(FallbackRead, fallback_read_handles_file_with_size_multiple_of_chunk_size ASSERT_TRUE(device_buffer_contains_expected_data(0, 0, file_length)); } -TEST_F(FallbackRead, fallback_read_handles_files_with_size_not_multiple_of_chunk_size) +TEST_F(FallbackRead, FallbackReadHandlesFilesWithSizeNotMultipleOfChunkSize) { StrictMock mhip; StrictMock msys; @@ -746,7 +746,7 @@ TEST_F(FallbackRead, fallback_read_handles_files_with_size_not_multiple_of_chunk ASSERT_TRUE(device_buffer_contains_expected_data(0, 0, file_length)); } -TEST_F(FallbackRead, fallback_read_with_non_zero_file_offset) +TEST_F(FallbackRead, FallbackReadWithNonZeroFileOffset) { StrictMock mhip; StrictMock msys; @@ -761,7 +761,7 @@ TEST_F(FallbackRead, fallback_read_with_non_zero_file_offset) ASSERT_TRUE(device_buffer_contains_expected_data(file_offset, 0, buffer->getLength())); } -TEST_F(FallbackRead, fallback_read_to_eof_with_non_zero_file_offset) +TEST_F(FallbackRead, FallbackReadToEofWithNonZeroFileOffset) { StrictMock mhip; StrictMock msys; @@ -776,7 +776,7 @@ TEST_F(FallbackRead, fallback_read_to_eof_with_non_zero_file_offset) ASSERT_TRUE(device_buffer_contains_expected_data(file_offset, 0, buffer->getLength())); } -TEST_F(FallbackRead, fallback_read_past_eof_with_non_zero_file_offset) +TEST_F(FallbackRead, FallbackReadPastEofWithNonZeroFileOffset) { StrictMock mhip; StrictMock msys; @@ -791,7 +791,7 @@ TEST_F(FallbackRead, fallback_read_past_eof_with_non_zero_file_offset) ASSERT_TRUE(device_buffer_contains_expected_data(file_offset, 0, buffer->getLength() - 1)); } -TEST_F(FallbackRead, fallback_read_can_read_single_byte_at_end_of_file) +TEST_F(FallbackRead, FallbackReadCanReadSingleByteAtEndOfFile) { StrictMock mhip; StrictMock msys; @@ -805,7 +805,7 @@ TEST_F(FallbackRead, fallback_read_can_read_single_byte_at_end_of_file) ASSERT_TRUE(device_buffer_contains_expected_data(file_offset, 0, 1)); } -TEST_F(FallbackRead, fallback_read_emtpy_file_with_non_zero_file_offset) +TEST_F(FallbackRead, FallbackReadEmtpyFileWithNonZeroFileOffset) { StrictMock mhip; StrictMock msys; @@ -819,7 +819,7 @@ TEST_F(FallbackRead, fallback_read_emtpy_file_with_non_zero_file_offset) ASSERT_TRUE(device_buffer_contains_expected_data(0, 0, 0)); } -TEST_F(FallbackRead, fallback_read_with_non_zero_buffer_offset) +TEST_F(FallbackRead, FallbackReadWithNonZeroBufferOffset) { StrictMock mhip; StrictMock msys; @@ -834,7 +834,7 @@ TEST_F(FallbackRead, fallback_read_with_non_zero_buffer_offset) ASSERT_TRUE(device_buffer_contains_expected_data(0, buffer_offset, buffer->getLength() - 1)); } -TEST_F(FallbackRead, fallback_read_can_read_into_last_byte_of_buffer) +TEST_F(FallbackRead, FallbackReadCanReadIntoLastByteOfBuffer) { StrictMock mhip; StrictMock msys; @@ -848,7 +848,7 @@ TEST_F(FallbackRead, fallback_read_can_read_into_last_byte_of_buffer) ASSERT_TRUE(device_buffer_contains_expected_data(0, buffer_offset, 1)); } -TEST_F(FallbackRead, fallback_read_with_non_zero_buffer_offset_and_file_offset) +TEST_F(FallbackRead, FallbackReadWithNonZeroBufferOffsetAndFileOffset) { StrictMock mhip; StrictMock msys; From 770050c38c12be28f516a69edc9796ae9e525c56 Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Thu, 19 Mar 2026 17:09:37 +0000 Subject: [PATCH 10/19] backend/fallback: Test cleanup - Move msys, mhip, mlibmounthelper into FallbackParam --- test/amd_detail/fallback.cpp | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/test/amd_detail/fallback.cpp b/test/amd_detail/fallback.cpp index 4442830d..162307f5 100644 --- a/test/amd_detail/fallback.cpp +++ b/test/amd_detail/fallback.cpp @@ -167,11 +167,12 @@ struct FallbackParam : ::testing::TestWithParam { shared_ptr buffer; shared_ptr file; + StrictMock mhip; + StrictMock msys; + StrictMock mlibmounthelper; + FallbackParam() { - StrictMock mhip; - StrictMock msys; - StrictMock mlibmounthelper; assert(hipFileDriverOpen() == HIPFILE_SUCCESS); @@ -207,40 +208,31 @@ struct FallbackParam : ::testing::TestWithParam { TEST_P(FallbackParam, FallbackIoThrowsOnNegativeBufferOffset) { - StrictMock mhip; - StrictMock msys; ASSERT_THROW(Fallback().io(io_type, file, buffer, 0, 0, -1, 4096), std::invalid_argument); } TEST_P(FallbackParam, FallbackIoThrowsIfBufferOffsetIsOutOfBounds) { - StrictMock mhip; - StrictMock msys; - hoff_t buffer_offset = static_cast(buffer->getLength()); + hoff_t buffer_offset = static_cast(buffer->getLength()); + ASSERT_THROW(Fallback().io(io_type, file, buffer, 0, 0, buffer_offset, 4096), std::invalid_argument); } TEST_P(FallbackParam, FallbackIoThrowsIfOpCouldOverrunBuffer) { - StrictMock mhip; - StrictMock msys; - size_t size = 10; - hoff_t buffer_offset = static_cast(buffer->getLength()) - 9; + size_t size = 10; + hoff_t buffer_offset = static_cast(buffer->getLength()) - 9; + ASSERT_THROW(Fallback().io(io_type, file, buffer, size, 0, buffer_offset, 4096), std::invalid_argument); } TEST_P(FallbackParam, FallbackIoThrowsOnNegativeFileOffset) { - StrictMock mhip; - StrictMock msys; ASSERT_THROW(Fallback().io(io_type, file, buffer, 0, -1, 0, 4096), std::invalid_argument); } TEST_P(FallbackParam, FallbackIoTruncatesSizeToMAX_RW_COUNT) { - StrictMock mhip; - StrictMock msys; - expect_buffer_registration(mhip, hipMemoryTypeDevice); auto buf = reinterpret_cast(0xABABABAB); Context::get()->registerBuffer(buf, MAX_RW_COUNT + 1, 0); @@ -274,18 +266,15 @@ TEST_P(FallbackParam, FallbackIoTruncatesSizeToMAX_RW_COUNT) TEST_P(FallbackParam, FallbackIoThrowsOnBounceBufferAllocationFailure) { - StrictMock mhip; - StrictMock msys; EXPECT_CALL(msys, mmap).WillOnce(testing::Throw(std::system_error(ENOMEM, std::generic_category()))); ASSERT_THROW(Fallback().io(io_type, file, buffer, 4096, 0, 0, 4096), std::system_error); } TEST_P(FallbackParam, FallbackIoAllocatesChunkSizedHostBounceBuffer) { - StrictMock mhip; - StrictMock msys; - size_t chunk_size = 1024 * 1024; - auto ptr = reinterpret_cast(0xFEFEFEFE); + size_t chunk_size = 1024 * 1024; + auto ptr = reinterpret_cast(0xFEFEFEFE); + EXPECT_CALL(msys, mmap(testing::_, chunk_size, testing::_, testing::_, testing::_, testing::_)) .WillOnce(testing::Return(ptr)); switch (io_type) { From bfaa66050f96707ff0d7fd312d7232dfafdecae6 Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Thu, 19 Mar 2026 16:52:01 +0000 Subject: [PATCH 11/19] backend/fallback: Test cleanup - Move nonnull_ptr into FallbackIo --- test/amd_detail/fallback.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/test/amd_detail/fallback.cpp b/test/amd_detail/fallback.cpp index 162307f5..e622982d 100644 --- a/test/amd_detail/fallback.cpp +++ b/test/amd_detail/fallback.cpp @@ -110,6 +110,7 @@ struct FallbackIo : public HipFileOpened { std::vector buffer_data; shared_ptr file; std::vector file_data; + void *nonnull_ptr{reinterpret_cast(0x1)}; FallbackIo() : buffer_data(1024 * 1024) { @@ -340,8 +341,6 @@ struct FallbackWrite : public FallbackIo { { rand_fill(buffer_data); } - - void *nonnull_ptr = reinterpret_cast(0x1); }; TEST_F(FallbackWrite, FallbackWriteHandlesZeroSizedWrite) @@ -554,8 +553,6 @@ struct FallbackRead : public FallbackIo { EXPECT_CALL(mhip, hipMemcpy).WillRepeatedly(testing::Invoke(this, &FallbackRead::fake_hipMemcpy)); EXPECT_CALL(msys, munmap).WillOnce(testing::Invoke(::munmap)); } - - void *nonnull_ptr = reinterpret_cast(0x1); }; TEST_F(FallbackRead, FallbackReadHandlesZeroSizedRead) From f13fa3fd2121e94225dadf791051dab343226c6c Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Thu, 19 Mar 2026 16:52:46 +0000 Subject: [PATCH 12/19] backend/fallback: Test cleanup - Move mhip, msys, mlibmounthelper into FallbackIo --- test/amd_detail/fallback.cpp | 148 +++++++---------------------------- 1 file changed, 29 insertions(+), 119 deletions(-) diff --git a/test/amd_detail/fallback.cpp b/test/amd_detail/fallback.cpp index e622982d..52ff5e18 100644 --- a/test/amd_detail/fallback.cpp +++ b/test/amd_detail/fallback.cpp @@ -112,11 +112,12 @@ struct FallbackIo : public HipFileOpened { std::vector file_data; void *nonnull_ptr{reinterpret_cast(0x1)}; + StrictMock mhip; + StrictMock msys; + StrictMock mlibmounthelper; + FallbackIo() : buffer_data(1024 * 1024) { - StrictMock mhip; - StrictMock msys; - StrictMock mlibmounthelper; expect_buffer_registration(mhip, hipMemoryTypeDevice); Context::get()->registerBuffer(buffer_data.data(), buffer_data.size(), 0); @@ -321,7 +322,7 @@ struct FallbackWrite : public FallbackIo { return static_cast(count); } - void expect_fallback_write(MHip &mhip, MSys &msys) + void expect_fallback_write() { EXPECT_CALL(msys, mmap).WillOnce(testing::Invoke(::mmap)); EXPECT_CALL(mhip, hipMemcpy).WillRepeatedly(testing::Invoke(this, &FallbackWrite::fake_hipMemcpy)); @@ -345,18 +346,12 @@ struct FallbackWrite : public FallbackIo { TEST_F(FallbackWrite, FallbackWriteHandlesZeroSizedWrite) { - StrictMock mhip; - StrictMock msys; - - expect_fallback_write(mhip, msys); + expect_fallback_write(); ASSERT_EQ(0, Fallback().io(IoType::Write, file, buffer, 0, 0, 0)); } TEST_F(FallbackWrite, FallbackWriteThrowsOnPwriteException) { - StrictMock mhip; - StrictMock msys; - EXPECT_CALL(msys, mmap).WillOnce(testing::Invoke(::mmap)); EXPECT_CALL(mhip, hipMemcpy); EXPECT_CALL(mhip, hipStreamSynchronize); @@ -368,9 +363,6 @@ TEST_F(FallbackWrite, FallbackWriteThrowsOnPwriteException) TEST_F(FallbackWrite, FallbackWriteThrowsOnHipmemcpyFailure) { - StrictMock mhip; - StrictMock msys; - EXPECT_CALL(msys, mmap).WillOnce(testing::Invoke(::mmap)); EXPECT_CALL(mhip, hipMemcpy).WillOnce(testing::Throw(Hip::RuntimeError(hipErrorUnknown))); EXPECT_CALL(msys, munmap).WillOnce(testing::Invoke(::munmap)); @@ -380,9 +372,6 @@ TEST_F(FallbackWrite, FallbackWriteThrowsOnHipmemcpyFailure) TEST_F(FallbackWrite, FallbackWriteThrowsOnHipStreamSynchronizeError) { - StrictMock mhip; - StrictMock msys; - EXPECT_CALL(msys, mmap).WillOnce(testing::Invoke(::mmap)); EXPECT_CALL(mhip, hipMemcpy); EXPECT_CALL(mhip, hipStreamSynchronize).WillOnce(testing::Throw(Hip::RuntimeError(hipErrorUnknown))); @@ -393,14 +382,11 @@ TEST_F(FallbackWrite, FallbackWriteThrowsOnHipStreamSynchronizeError) TEST_F(FallbackWrite, FallbackWriteToEmptyFile) { - StrictMock mhip; - StrictMock msys; - size_t size = 64 * 1024; size_t chunk_size = 4096; randomize_device_buffer(); - expect_fallback_write(mhip, msys); + expect_fallback_write(); ASSERT_EQ(size, Fallback().io(IoType::Write, file, buffer, size, 0, 0, chunk_size)); ASSERT_TRUE(file_contains_expected_data(0, 0, size)); @@ -408,15 +394,12 @@ TEST_F(FallbackWrite, FallbackWriteToEmptyFile) TEST_F(FallbackWrite, FallbackWriteToEmptyFileAtFileOffset) { - StrictMock mhip; - StrictMock msys; - size_t size = 64 * 1024; size_t chunk_size = 4096; hoff_t file_offset = 1024; randomize_device_buffer(); - expect_fallback_write(mhip, msys); + expect_fallback_write(); ASSERT_EQ(size, Fallback().io(IoType::Write, file, buffer, size, file_offset, 0, chunk_size)); ASSERT_TRUE(file_contains_expected_data(file_offset, 0, size)); @@ -424,15 +407,12 @@ TEST_F(FallbackWrite, FallbackWriteToEmptyFileAtFileOffset) TEST_F(FallbackWrite, FallbackWriteToEmptyFileAtBufferOffset) { - StrictMock mhip; - StrictMock msys; - size_t size = 64 * 1024; size_t chunk_size = 4096; hoff_t buffer_offset = 1024; randomize_device_buffer(); - expect_fallback_write(mhip, msys); + expect_fallback_write(); ASSERT_EQ(size, Fallback().io(IoType::Write, file, buffer, size, 0, buffer_offset, chunk_size)); ASSERT_TRUE(file_contains_expected_data(0, buffer_offset, size)); @@ -440,16 +420,13 @@ TEST_F(FallbackWrite, FallbackWriteToEmptyFileAtBufferOffset) TEST_F(FallbackWrite, FallbackWriteToEmptyFileAtBufferOffsetFileOffset) { - StrictMock mhip; - StrictMock msys; - size_t size = 64 * 1024; size_t chunk_size = 4096; hoff_t buffer_offset = 1024; hoff_t file_offset = 512; randomize_device_buffer(); - expect_fallback_write(mhip, msys); + expect_fallback_write(); ASSERT_EQ(size, Fallback().io(IoType::Write, file, buffer, size, file_offset, buffer_offset, chunk_size)); ASSERT_TRUE(file_contains_expected_data(file_offset, buffer_offset, size)); @@ -457,12 +434,9 @@ TEST_F(FallbackWrite, FallbackWriteToEmptyFileAtBufferOffsetFileOffset) TEST_F(FallbackWrite, FallbackWriteOverwiteEntireFile) { - StrictMock mhip; - StrictMock msys; - file_data.resize(buffer->getLength()); randomize_device_buffer(); - expect_fallback_write(mhip, msys); + expect_fallback_write(); ASSERT_EQ(buffer->getLength(), Fallback().io(IoType::Write, file, buffer, buffer->getLength(), 0, 0)); ASSERT_TRUE(file_contains_expected_data(0, 0, file_data.size())); @@ -470,14 +444,11 @@ TEST_F(FallbackWrite, FallbackWriteOverwiteEntireFile) TEST_F(FallbackWrite, FallbackWriteToFileSubregion) { - StrictMock mhip; - StrictMock msys; - size_t file_length = buffer->getLength() * 2; hoff_t file_offset = buffer->getLength() / 2; file_data.resize(file_length); randomize_device_buffer(); - expect_fallback_write(mhip, msys); + expect_fallback_write(); ASSERT_EQ(buffer->getLength(), Fallback().io(IoType::Write, file, buffer, buffer->getLength(), file_offset, 0)); @@ -486,15 +457,12 @@ TEST_F(FallbackWrite, FallbackWriteToFileSubregion) TEST_F(FallbackWrite, FallbackWriteAppendNonEmptySmallFile) { - StrictMock mhip; - StrictMock msys; - file_data.resize(64); size_t size = 64 * 1024; hoff_t file_offset = 64; randomize_device_buffer(); - expect_fallback_write(mhip, msys); + expect_fallback_write(); ASSERT_EQ(size, Fallback().io(IoType::Write, file, buffer, size, file_offset, 0)); ASSERT_TRUE(file_contains_expected_data(file_offset, 0, size)); @@ -546,7 +514,7 @@ struct FallbackRead : public FallbackIo { return contains_expected_data(buffer_data, buffer_offset, file_data, file_offset, count); } - void expect_fallback_read(MHip &mhip, MSys &msys) + void expect_fallback_read() { EXPECT_CALL(msys, mmap).WillOnce(testing::Invoke(::mmap)); EXPECT_CALL(msys, pread).WillRepeatedly(testing::Invoke(this, &FallbackRead::fake_pread)); @@ -557,9 +525,7 @@ struct FallbackRead : public FallbackIo { TEST_F(FallbackRead, FallbackReadHandlesZeroSizedRead) { - StrictMock mhip; - StrictMock msys; - expect_fallback_read(mhip, msys); + expect_fallback_read(); ASSERT_EQ(0, Fallback().io(IoType::Read, file, buffer, 0, 0, 0)); } @@ -568,9 +534,6 @@ TEST_F(FallbackRead, FallbackReadHandlesZeroSizedRead) /// [SOF.....[....REGION....]....EOF] TEST_F(FallbackRead, ReadFromRegionWithinFile) { - StrictMock mhip; - StrictMock msys; - size_t file_length = buffer->getLength() * 3; init_file(file_length); @@ -578,15 +541,13 @@ TEST_F(FallbackRead, ReadFromRegionWithinFile) hoff_t buffer_offset = buffer->getLength() / 4; hoff_t file_offset = static_cast(buffer->getLength()); - expect_fallback_read(mhip, msys); + expect_fallback_read(); ASSERT_EQ(Fallback().io(IoType::Read, file, buffer, size, file_offset, buffer_offset), size); ASSERT_TRUE(device_buffer_contains_expected_data(file_offset, buffer_offset, size)); } TEST_F(FallbackRead, FallbackReadThrowsOnPreadException) { - StrictMock mhip; - StrictMock msys; EXPECT_CALL(msys, mmap).WillOnce(testing::Invoke(::mmap)); EXPECT_CALL(msys, pread).WillOnce(testing::Throw(std::system_error(EIO, std::generic_category()))); EXPECT_CALL(msys, munmap).WillOnce(testing::Invoke(::munmap)); @@ -595,9 +556,6 @@ TEST_F(FallbackRead, FallbackReadThrowsOnPreadException) TEST_F(FallbackRead, FallbackReadThrowsOnHipmemcpyFailure) { - StrictMock mhip; - StrictMock msys; - size_t file_length = buffer->getLength(); init_file(file_length); @@ -610,9 +568,6 @@ TEST_F(FallbackRead, FallbackReadThrowsOnHipmemcpyFailure) TEST_F(FallbackRead, FallbackReadHandlesEmptyFile) { - StrictMock mhip; - StrictMock msys; - const size_t file_length = 0; init_file(file_length); @@ -625,9 +580,6 @@ TEST_F(FallbackRead, FallbackReadHandlesEmptyFile) TEST_F(FallbackRead, FallbackReadHandlesShortPreads) { - StrictMock mhip; - StrictMock msys; - size_t file_length = buffer->getLength(); init_file(file_length); @@ -647,9 +599,6 @@ TEST_F(FallbackRead, FallbackReadHandlesShortPreads) TEST_F(FallbackRead, FallbackReadHandlesInterruptedPread) { - StrictMock mhip; - StrictMock msys; - size_t file_length = buffer->getLength(); init_file(file_length); @@ -667,81 +616,63 @@ TEST_F(FallbackRead, FallbackReadHandlesInterruptedPread) TEST_F(FallbackRead, FallbackReadHandlesFileSmallerThanBuffer) { - StrictMock mhip; - StrictMock msys; - size_t file_length = buffer->getLength() / 2; init_file(file_length); - expect_fallback_read(mhip, msys); + expect_fallback_read(); ASSERT_EQ(file_length, Fallback().io(IoType::Read, file, buffer, buffer->getLength(), 0, 0)); ASSERT_TRUE(device_buffer_contains_expected_data(0, 0, file_length)); } TEST_F(FallbackRead, FallbackReadHandlesFileSameSizeAsBuffer) { - StrictMock mhip; - StrictMock msys; - size_t file_length = buffer->getLength(); init_file(file_length); - expect_fallback_read(mhip, msys); + expect_fallback_read(); ASSERT_EQ(file_length, Fallback().io(IoType::Read, file, buffer, buffer->getLength(), 0, 0)); ASSERT_TRUE(device_buffer_contains_expected_data(0, 0, file_length)); } TEST_F(FallbackRead, FallbackReadHandlesFileLargerThanBuffer) { - StrictMock mhip; - StrictMock msys; - size_t file_length = buffer->getLength() * 2; init_file(file_length); - expect_fallback_read(mhip, msys); + expect_fallback_read(); ASSERT_EQ(buffer->getLength(), Fallback().io(IoType::Read, file, buffer, buffer->getLength(), 0, 0)); ASSERT_TRUE(device_buffer_contains_expected_data(0, 0, buffer->getLength())); } TEST_F(FallbackRead, FallbackReadHandlesFileWithSizeMultipleOfChunkSize) { - StrictMock mhip; - StrictMock msys; - size_t chunk_size = 4096; size_t file_length = chunk_size; init_file(file_length); - expect_fallback_read(mhip, msys); + expect_fallback_read(); ASSERT_EQ(file_length, Fallback().io(IoType::Read, file, buffer, file_length, 0, 0, chunk_size)); ASSERT_TRUE(device_buffer_contains_expected_data(0, 0, file_length)); } TEST_F(FallbackRead, FallbackReadHandlesFilesWithSizeNotMultipleOfChunkSize) { - StrictMock mhip; - StrictMock msys; - size_t chunk_size = 4096; size_t file_length = chunk_size + 1; init_file(file_length); - expect_fallback_read(mhip, msys); + expect_fallback_read(); ASSERT_EQ(file_length, Fallback().io(IoType::Read, file, buffer, file_length, 0, 0, chunk_size)); ASSERT_TRUE(device_buffer_contains_expected_data(0, 0, file_length)); } TEST_F(FallbackRead, FallbackReadWithNonZeroFileOffset) { - StrictMock mhip; - StrictMock msys; - size_t file_length = buffer->getLength() * 3; init_file(file_length); hoff_t file_offset = static_cast(buffer->getLength()); - expect_fallback_read(mhip, msys); + expect_fallback_read(); ASSERT_EQ(buffer->getLength(), Fallback().io(IoType::Read, file, buffer, buffer->getLength(), file_offset, 0)); ASSERT_TRUE(device_buffer_contains_expected_data(file_offset, 0, buffer->getLength())); @@ -749,14 +680,11 @@ TEST_F(FallbackRead, FallbackReadWithNonZeroFileOffset) TEST_F(FallbackRead, FallbackReadToEofWithNonZeroFileOffset) { - StrictMock mhip; - StrictMock msys; - size_t file_length = buffer->getLength() * 2; init_file(file_length); hoff_t file_offset = static_cast(buffer->getLength()); - expect_fallback_read(mhip, msys); + expect_fallback_read(); ASSERT_EQ(buffer->getLength(), Fallback().io(IoType::Read, file, buffer, buffer->getLength(), file_offset, 0)); ASSERT_TRUE(device_buffer_contains_expected_data(file_offset, 0, buffer->getLength())); @@ -764,14 +692,11 @@ TEST_F(FallbackRead, FallbackReadToEofWithNonZeroFileOffset) TEST_F(FallbackRead, FallbackReadPastEofWithNonZeroFileOffset) { - StrictMock mhip; - StrictMock msys; - size_t file_length = buffer->getLength() * 2; init_file(file_length); hoff_t file_offset = static_cast(buffer->getLength()) + 1; - expect_fallback_read(mhip, msys); + expect_fallback_read(); ASSERT_EQ(buffer->getLength() - 1, Fallback().io(IoType::Read, file, buffer, buffer->getLength(), file_offset, 0)); ASSERT_TRUE(device_buffer_contains_expected_data(file_offset, 0, buffer->getLength() - 1)); @@ -779,42 +704,33 @@ TEST_F(FallbackRead, FallbackReadPastEofWithNonZeroFileOffset) TEST_F(FallbackRead, FallbackReadCanReadSingleByteAtEndOfFile) { - StrictMock mhip; - StrictMock msys; - size_t file_length = buffer->getLength(); init_file(file_length); hoff_t file_offset = static_cast(file_length) - 1; - expect_fallback_read(mhip, msys); + expect_fallback_read(); ASSERT_EQ(1, Fallback().io(IoType::Read, file, buffer, buffer->getLength(), file_offset, 0)); ASSERT_TRUE(device_buffer_contains_expected_data(file_offset, 0, 1)); } TEST_F(FallbackRead, FallbackReadEmtpyFileWithNonZeroFileOffset) { - StrictMock mhip; - StrictMock msys; - size_t file_length = 0; init_file(file_length); hoff_t file_offset = static_cast(buffer->getLength()); - expect_fallback_read(mhip, msys); + expect_fallback_read(); ASSERT_EQ(0, Fallback().io(IoType::Read, file, buffer, buffer->getLength(), file_offset, 0)); ASSERT_TRUE(device_buffer_contains_expected_data(0, 0, 0)); } TEST_F(FallbackRead, FallbackReadWithNonZeroBufferOffset) { - StrictMock mhip; - StrictMock msys; - size_t file_length = buffer->getLength() * 2; init_file(file_length); hoff_t buffer_offset = static_cast(1); - expect_fallback_read(mhip, msys); + expect_fallback_read(); ASSERT_EQ(buffer->getLength() - 1, Fallback().io(IoType::Read, file, buffer, buffer->getLength() - 1, 0, buffer_offset)); ASSERT_TRUE(device_buffer_contains_expected_data(0, buffer_offset, buffer->getLength() - 1)); @@ -822,30 +738,24 @@ TEST_F(FallbackRead, FallbackReadWithNonZeroBufferOffset) TEST_F(FallbackRead, FallbackReadCanReadIntoLastByteOfBuffer) { - StrictMock mhip; - StrictMock msys; - size_t file_length = buffer->getLength(); init_file(file_length); hoff_t buffer_offset = static_cast(buffer->getLength() - 1); - expect_fallback_read(mhip, msys); + expect_fallback_read(); ASSERT_EQ(1, Fallback().io(IoType::Read, file, buffer, 1, 0, buffer_offset)); ASSERT_TRUE(device_buffer_contains_expected_data(0, buffer_offset, 1)); } TEST_F(FallbackRead, FallbackReadWithNonZeroBufferOffsetAndFileOffset) { - StrictMock mhip; - StrictMock msys; - size_t file_length = buffer->getLength(); init_file(file_length); hoff_t file_offset = 74; hoff_t buffer_offset = 97; size_t read_size = buffer->getLength() / 2; - expect_fallback_read(mhip, msys); + expect_fallback_read(); ASSERT_EQ(read_size, Fallback().io(IoType::Read, file, buffer, read_size, file_offset, buffer_offset)); ASSERT_TRUE(device_buffer_contains_expected_data(file_offset, buffer_offset, read_size)); } From d966d1de9bbeddf3ea5b75e0179e69162570a691 Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Thu, 19 Mar 2026 16:47:11 +0000 Subject: [PATCH 13/19] backend/fallback: Test cleanup - Use uniform initialization --- test/amd_detail/fallback.cpp | 147 +++++++++++++++++------------------ 1 file changed, 73 insertions(+), 74 deletions(-) diff --git a/test/amd_detail/fallback.cpp b/test/amd_detail/fallback.cpp index 52ff5e18..cf42cc44 100644 --- a/test/amd_detail/fallback.cpp +++ b/test/amd_detail/fallback.cpp @@ -53,13 +53,13 @@ rand_fill(std::vector &v) { // *Quickly* fill the vector with data. Reading from /dev/urandom is // faster than C++'s prngs and C's rand. - auto fd = open("/dev/urandom", O_RDONLY); + auto fd{open("/dev/urandom", O_RDONLY)}; if (fd == -1) { throw std::runtime_error("Can't open /dev/urandom"); } - size_t total_bytes_read = 0; + size_t total_bytes_read{0}; while (total_bytes_read < v.size()) { - auto bytes_read = read(fd, v.data() + total_bytes_read, v.size() - total_bytes_read); + auto bytes_read{read(fd, v.data() + total_bytes_read, v.size() - total_bytes_read)}; if (bytes_read == -1) { throw std::runtime_error("Can't read from /dev/urandom"); } @@ -85,7 +85,7 @@ contains_expected_data(std::vector &buffer, hoff_t buffer_offset, std:: throw std::invalid_argument("out of bounds: expected"); } - for (hoff_t i = 0; i < buffer_offset; i++) { + for (hoff_t i{0}; i < buffer_offset; i++) { if (buffer.data()[i] != 0) { return false; } @@ -95,7 +95,7 @@ contains_expected_data(std::vector &buffer, hoff_t buffer_offset, std:: return false; } - for (size_t i = static_cast(buffer_offset) + count; i < buffer.size(); i++) { + for (size_t i{static_cast(buffer_offset) + count}; i < buffer.size(); i++) { if (buffer.data()[i] != 0) { return false; } @@ -106,10 +106,10 @@ contains_expected_data(std::vector &buffer, hoff_t buffer_offset, std:: struct FallbackIo : public HipFileOpened { - shared_ptr buffer; - std::vector buffer_data; - shared_ptr file; - std::vector file_data; + shared_ptr buffer{}; + std::vector buffer_data{}; + shared_ptr file{}; + std::vector file_data{}; void *nonnull_ptr{reinterpret_cast(0x1)}; StrictMock mhip; @@ -166,20 +166,19 @@ TEST_F(FallbackScoring, ScoreRejectsIoTargetingUnsupportedMemoryType) struct FallbackParam : ::testing::TestWithParam { - shared_ptr buffer; - shared_ptr file; + shared_ptr buffer{}; + shared_ptr file{}; - StrictMock mhip; - StrictMock msys; - StrictMock mlibmounthelper; + StrictMock mhip{}; + StrictMock msys{}; + StrictMock mlibmounthelper{}; FallbackParam() { - assert(hipFileDriverOpen() == HIPFILE_SUCCESS); expect_buffer_registration(mhip, hipMemoryTypeDevice); - void *buf = reinterpret_cast(0xFEFEFEFE); + void *buf{reinterpret_cast(0xFEFEFEFE)}; Context::get()->registerBuffer(buf, 4096, 0); buffer = Context::get()->getRegisteredBuffer(buf); @@ -215,15 +214,15 @@ TEST_P(FallbackParam, FallbackIoThrowsOnNegativeBufferOffset) TEST_P(FallbackParam, FallbackIoThrowsIfBufferOffsetIsOutOfBounds) { - hoff_t buffer_offset = static_cast(buffer->getLength()); + hoff_t buffer_offset{static_cast(buffer->getLength())}; ASSERT_THROW(Fallback().io(io_type, file, buffer, 0, 0, buffer_offset, 4096), std::invalid_argument); } TEST_P(FallbackParam, FallbackIoThrowsIfOpCouldOverrunBuffer) { - size_t size = 10; - hoff_t buffer_offset = static_cast(buffer->getLength()) - 9; + size_t size{10}; + hoff_t buffer_offset{static_cast(buffer->getLength()) - 9}; ASSERT_THROW(Fallback().io(io_type, file, buffer, size, 0, buffer_offset, 4096), std::invalid_argument); } @@ -236,9 +235,9 @@ TEST_P(FallbackParam, FallbackIoThrowsOnNegativeFileOffset) TEST_P(FallbackParam, FallbackIoTruncatesSizeToMAX_RW_COUNT) { expect_buffer_registration(mhip, hipMemoryTypeDevice); - auto buf = reinterpret_cast(0xABABABAB); + auto buf{reinterpret_cast(0xABABABAB)}; Context::get()->registerBuffer(buf, MAX_RW_COUNT + 1, 0); - auto big_buffer = Context::get()->getRegisteredBuffer(buf); + auto big_buffer{Context::get()->getRegisteredBuffer(buf)}; EXPECT_CALL(msys, mmap).WillOnce(testing::Return(reinterpret_cast(0xFEFEFEFE))); switch (io_type) { @@ -274,8 +273,8 @@ TEST_P(FallbackParam, FallbackIoThrowsOnBounceBufferAllocationFailure) TEST_P(FallbackParam, FallbackIoAllocatesChunkSizedHostBounceBuffer) { - size_t chunk_size = 1024 * 1024; - auto ptr = reinterpret_cast(0xFEFEFEFE); + size_t chunk_size{1024 * 1024}; + auto ptr{reinterpret_cast(0xFEFEFEFE)}; EXPECT_CALL(msys, mmap(testing::_, chunk_size, testing::_, testing::_, testing::_, testing::_)) .WillOnce(testing::Return(ptr)); @@ -312,7 +311,7 @@ struct FallbackWrite : public FallbackIo { return -1; } - auto uoffset = static_cast(offset); + auto uoffset{static_cast(offset)}; if (file_data.size() < uoffset + count) { file_data.resize(uoffset + count); } @@ -382,8 +381,8 @@ TEST_F(FallbackWrite, FallbackWriteThrowsOnHipStreamSynchronizeError) TEST_F(FallbackWrite, FallbackWriteToEmptyFile) { - size_t size = 64 * 1024; - size_t chunk_size = 4096; + size_t size{64 * 1024}; + size_t chunk_size{4096}; randomize_device_buffer(); expect_fallback_write(); @@ -394,9 +393,9 @@ TEST_F(FallbackWrite, FallbackWriteToEmptyFile) TEST_F(FallbackWrite, FallbackWriteToEmptyFileAtFileOffset) { - size_t size = 64 * 1024; - size_t chunk_size = 4096; - hoff_t file_offset = 1024; + size_t size{64 * 1024}; + size_t chunk_size{4096}; + hoff_t file_offset{1024}; randomize_device_buffer(); expect_fallback_write(); @@ -407,9 +406,9 @@ TEST_F(FallbackWrite, FallbackWriteToEmptyFileAtFileOffset) TEST_F(FallbackWrite, FallbackWriteToEmptyFileAtBufferOffset) { - size_t size = 64 * 1024; - size_t chunk_size = 4096; - hoff_t buffer_offset = 1024; + size_t size{64 * 1024}; + size_t chunk_size{4096}; + hoff_t buffer_offset{1024}; randomize_device_buffer(); expect_fallback_write(); @@ -420,10 +419,10 @@ TEST_F(FallbackWrite, FallbackWriteToEmptyFileAtBufferOffset) TEST_F(FallbackWrite, FallbackWriteToEmptyFileAtBufferOffsetFileOffset) { - size_t size = 64 * 1024; - size_t chunk_size = 4096; - hoff_t buffer_offset = 1024; - hoff_t file_offset = 512; + size_t size{64 * 1024}; + size_t chunk_size{4096}; + hoff_t buffer_offset{1024}; + hoff_t file_offset{512}; randomize_device_buffer(); expect_fallback_write(); @@ -444,8 +443,8 @@ TEST_F(FallbackWrite, FallbackWriteOverwiteEntireFile) TEST_F(FallbackWrite, FallbackWriteToFileSubregion) { - size_t file_length = buffer->getLength() * 2; - hoff_t file_offset = buffer->getLength() / 2; + size_t file_length{buffer->getLength() * 2}; + hoff_t file_offset{static_cast(buffer->getLength() / 2)}; file_data.resize(file_length); randomize_device_buffer(); expect_fallback_write(); @@ -458,8 +457,8 @@ TEST_F(FallbackWrite, FallbackWriteToFileSubregion) TEST_F(FallbackWrite, FallbackWriteAppendNonEmptySmallFile) { file_data.resize(64); - size_t size = 64 * 1024; - hoff_t file_offset = 64; + size_t size{64 * 1024}; + hoff_t file_offset{64}; randomize_device_buffer(); expect_fallback_write(); @@ -490,7 +489,7 @@ struct FallbackRead : public FallbackIo { return -1; } - auto uoffset = static_cast(offset); + auto uoffset{static_cast(offset)}; if (count >= static_cast(SSIZE_MAX) + 1) { return -1; @@ -534,12 +533,12 @@ TEST_F(FallbackRead, FallbackReadHandlesZeroSizedRead) /// [SOF.....[....REGION....]....EOF] TEST_F(FallbackRead, ReadFromRegionWithinFile) { - size_t file_length = buffer->getLength() * 3; + size_t file_length{buffer->getLength() * 3}; init_file(file_length); - size_t size = buffer->getLength() / 2; - hoff_t buffer_offset = buffer->getLength() / 4; - hoff_t file_offset = static_cast(buffer->getLength()); + size_t size{buffer->getLength() / 2}; + hoff_t buffer_offset{static_cast(buffer->getLength() / 4)}; + hoff_t file_offset{static_cast(buffer->getLength())}; expect_fallback_read(); ASSERT_EQ(Fallback().io(IoType::Read, file, buffer, size, file_offset, buffer_offset), size); @@ -556,7 +555,7 @@ TEST_F(FallbackRead, FallbackReadThrowsOnPreadException) TEST_F(FallbackRead, FallbackReadThrowsOnHipmemcpyFailure) { - size_t file_length = buffer->getLength(); + size_t file_length{buffer->getLength()}; init_file(file_length); EXPECT_CALL(msys, mmap).WillOnce(testing::Invoke(::mmap)); @@ -568,7 +567,7 @@ TEST_F(FallbackRead, FallbackReadThrowsOnHipmemcpyFailure) TEST_F(FallbackRead, FallbackReadHandlesEmptyFile) { - const size_t file_length = 0; + const size_t file_length{0}; init_file(file_length); EXPECT_CALL(msys, mmap).WillOnce(testing::Invoke(::mmap)); @@ -580,7 +579,7 @@ TEST_F(FallbackRead, FallbackReadHandlesEmptyFile) TEST_F(FallbackRead, FallbackReadHandlesShortPreads) { - size_t file_length = buffer->getLength(); + size_t file_length{buffer->getLength()}; init_file(file_length); EXPECT_CALL(msys, mmap).WillOnce(testing::Invoke(::mmap)); @@ -599,7 +598,7 @@ TEST_F(FallbackRead, FallbackReadHandlesShortPreads) TEST_F(FallbackRead, FallbackReadHandlesInterruptedPread) { - size_t file_length = buffer->getLength(); + size_t file_length{buffer->getLength()}; init_file(file_length); EXPECT_CALL(msys, mmap).WillOnce(testing::Invoke(::mmap)); @@ -616,7 +615,7 @@ TEST_F(FallbackRead, FallbackReadHandlesInterruptedPread) TEST_F(FallbackRead, FallbackReadHandlesFileSmallerThanBuffer) { - size_t file_length = buffer->getLength() / 2; + size_t file_length{buffer->getLength() / 2}; init_file(file_length); expect_fallback_read(); @@ -626,7 +625,7 @@ TEST_F(FallbackRead, FallbackReadHandlesFileSmallerThanBuffer) TEST_F(FallbackRead, FallbackReadHandlesFileSameSizeAsBuffer) { - size_t file_length = buffer->getLength(); + size_t file_length{buffer->getLength()}; init_file(file_length); expect_fallback_read(); @@ -636,7 +635,7 @@ TEST_F(FallbackRead, FallbackReadHandlesFileSameSizeAsBuffer) TEST_F(FallbackRead, FallbackReadHandlesFileLargerThanBuffer) { - size_t file_length = buffer->getLength() * 2; + size_t file_length{buffer->getLength() * 2}; init_file(file_length); expect_fallback_read(); @@ -646,8 +645,8 @@ TEST_F(FallbackRead, FallbackReadHandlesFileLargerThanBuffer) TEST_F(FallbackRead, FallbackReadHandlesFileWithSizeMultipleOfChunkSize) { - size_t chunk_size = 4096; - size_t file_length = chunk_size; + size_t chunk_size{4096}; + size_t file_length{chunk_size}; init_file(file_length); expect_fallback_read(); @@ -657,8 +656,8 @@ TEST_F(FallbackRead, FallbackReadHandlesFileWithSizeMultipleOfChunkSize) TEST_F(FallbackRead, FallbackReadHandlesFilesWithSizeNotMultipleOfChunkSize) { - size_t chunk_size = 4096; - size_t file_length = chunk_size + 1; + size_t chunk_size{4096}; + size_t file_length{chunk_size + 1}; init_file(file_length); expect_fallback_read(); @@ -668,9 +667,9 @@ TEST_F(FallbackRead, FallbackReadHandlesFilesWithSizeNotMultipleOfChunkSize) TEST_F(FallbackRead, FallbackReadWithNonZeroFileOffset) { - size_t file_length = buffer->getLength() * 3; + size_t file_length{buffer->getLength() * 3}; init_file(file_length); - hoff_t file_offset = static_cast(buffer->getLength()); + hoff_t file_offset{static_cast(buffer->getLength())}; expect_fallback_read(); ASSERT_EQ(buffer->getLength(), @@ -680,9 +679,9 @@ TEST_F(FallbackRead, FallbackReadWithNonZeroFileOffset) TEST_F(FallbackRead, FallbackReadToEofWithNonZeroFileOffset) { - size_t file_length = buffer->getLength() * 2; + size_t file_length{buffer->getLength() * 2}; init_file(file_length); - hoff_t file_offset = static_cast(buffer->getLength()); + hoff_t file_offset{static_cast(buffer->getLength())}; expect_fallback_read(); ASSERT_EQ(buffer->getLength(), @@ -692,9 +691,9 @@ TEST_F(FallbackRead, FallbackReadToEofWithNonZeroFileOffset) TEST_F(FallbackRead, FallbackReadPastEofWithNonZeroFileOffset) { - size_t file_length = buffer->getLength() * 2; + size_t file_length{buffer->getLength() * 2}; init_file(file_length); - hoff_t file_offset = static_cast(buffer->getLength()) + 1; + hoff_t file_offset{static_cast(buffer->getLength()) + 1}; expect_fallback_read(); ASSERT_EQ(buffer->getLength() - 1, @@ -704,9 +703,9 @@ TEST_F(FallbackRead, FallbackReadPastEofWithNonZeroFileOffset) TEST_F(FallbackRead, FallbackReadCanReadSingleByteAtEndOfFile) { - size_t file_length = buffer->getLength(); + size_t file_length{buffer->getLength()}; init_file(file_length); - hoff_t file_offset = static_cast(file_length) - 1; + hoff_t file_offset{static_cast(file_length) - 1}; expect_fallback_read(); ASSERT_EQ(1, Fallback().io(IoType::Read, file, buffer, buffer->getLength(), file_offset, 0)); @@ -715,9 +714,9 @@ TEST_F(FallbackRead, FallbackReadCanReadSingleByteAtEndOfFile) TEST_F(FallbackRead, FallbackReadEmtpyFileWithNonZeroFileOffset) { - size_t file_length = 0; + size_t file_length{0}; init_file(file_length); - hoff_t file_offset = static_cast(buffer->getLength()); + hoff_t file_offset{static_cast(buffer->getLength())}; expect_fallback_read(); ASSERT_EQ(0, Fallback().io(IoType::Read, file, buffer, buffer->getLength(), file_offset, 0)); @@ -726,9 +725,9 @@ TEST_F(FallbackRead, FallbackReadEmtpyFileWithNonZeroFileOffset) TEST_F(FallbackRead, FallbackReadWithNonZeroBufferOffset) { - size_t file_length = buffer->getLength() * 2; + size_t file_length{buffer->getLength() * 2}; init_file(file_length); - hoff_t buffer_offset = static_cast(1); + hoff_t buffer_offset{static_cast(1)}; expect_fallback_read(); ASSERT_EQ(buffer->getLength() - 1, @@ -738,9 +737,9 @@ TEST_F(FallbackRead, FallbackReadWithNonZeroBufferOffset) TEST_F(FallbackRead, FallbackReadCanReadIntoLastByteOfBuffer) { - size_t file_length = buffer->getLength(); + size_t file_length{buffer->getLength()}; init_file(file_length); - hoff_t buffer_offset = static_cast(buffer->getLength() - 1); + hoff_t buffer_offset{static_cast(buffer->getLength() - 1)}; expect_fallback_read(); ASSERT_EQ(1, Fallback().io(IoType::Read, file, buffer, 1, 0, buffer_offset)); @@ -749,11 +748,11 @@ TEST_F(FallbackRead, FallbackReadCanReadIntoLastByteOfBuffer) TEST_F(FallbackRead, FallbackReadWithNonZeroBufferOffsetAndFileOffset) { - size_t file_length = buffer->getLength(); + size_t file_length{buffer->getLength()}; init_file(file_length); - hoff_t file_offset = 74; - hoff_t buffer_offset = 97; - size_t read_size = buffer->getLength() / 2; + hoff_t file_offset{74}; + hoff_t buffer_offset{97}; + size_t read_size{buffer->getLength() / 2}; expect_fallback_read(); ASSERT_EQ(read_size, Fallback().io(IoType::Read, file, buffer, read_size, file_offset, buffer_offset)); From b8d939669453e300e1af452f39d667b0527235fe Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Wed, 18 Mar 2026 02:40:05 +0000 Subject: [PATCH 14/19] backend/fallback: Check fallback enablement when scoring IO --- src/amd_detail/backend/fallback.cpp | 4 +++- test/amd_detail/fallback.cpp | 11 +++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/amd_detail/backend/fallback.cpp b/src/amd_detail/backend/fallback.cpp index 1d2caa73..f1d9e081 100644 --- a/src/amd_detail/backend/fallback.cpp +++ b/src/amd_detail/backend/fallback.cpp @@ -8,6 +8,7 @@ #include "buffer.h" #include "backend/asyncop-fallback.h" #include "backend/memcpy-kernel.h" +#include "configuration.h" #include "context.h" #include "fallback.h" #include "file.h" @@ -47,7 +48,8 @@ Fallback::score(std::shared_ptr file, std::shared_ptr buffer, si (void)file; (void)file_offset; (void)size; - return buffer->getType() == hipMemoryTypeDevice ? 0 : -1; + + return Context::get()->fallback() && buffer->getType() == hipMemoryTypeDevice ? 0 : -1; } ssize_t diff --git a/test/amd_detail/fallback.cpp b/test/amd_detail/fallback.cpp index cf42cc44..5cd088b4 100644 --- a/test/amd_detail/fallback.cpp +++ b/test/amd_detail/fallback.cpp @@ -14,6 +14,7 @@ #include "hipfile-warnings.h" #include "io.h" #include "mbuffer.h" +#include "mconfiguration.h" #include "mfile.h" #include "mhip.h" #include "mmountinfo.h" @@ -147,10 +148,13 @@ struct FallbackScoring : public testing::Test { const hoff_t buffer_offset{1024}; shared_ptr> mfile{make_shared>()}; shared_ptr> mbuffer{make_shared>()}; + + StrictMock mcfg; }; TEST_F(FallbackScoring, ScoreAcceptsIoTargetingDeviceMemory) { + EXPECT_CALL(mcfg, fallback()).WillOnce(Return(true)); EXPECT_CALL(*mbuffer, getType).WillOnce(Return(hipMemoryTypeDevice)); ASSERT_EQ(Fallback().score(mfile, mbuffer, io_size, file_offset, buffer_offset), 0); @@ -158,12 +162,19 @@ TEST_F(FallbackScoring, ScoreAcceptsIoTargetingDeviceMemory) TEST_F(FallbackScoring, ScoreRejectsIoTargetingUnsupportedMemoryType) { + EXPECT_CALL(mcfg, fallback()).WillRepeatedly(Return(true)); for (const auto memoryType : UnsupportedHipMemoryTypes) { EXPECT_CALL(*mbuffer, getType).WillOnce(Return(memoryType)); ASSERT_EQ(Fallback().score(mfile, mbuffer, io_size, file_offset, buffer_offset), -1); } } +TEST_F(FallbackScoring, ScoreRejectsIoIfFallbackDisabled) +{ + EXPECT_CALL(mcfg, fallback()).WillOnce(Return(false)); + ASSERT_EQ(Fallback().score(mfile, mbuffer, io_size, file_offset, buffer_offset), -1); +} + struct FallbackParam : ::testing::TestWithParam { shared_ptr buffer{}; From a83d6a3a95d536965931baf328d5f54ff1134ea1 Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Wed, 18 Mar 2026 02:40:05 +0000 Subject: [PATCH 15/19] backend/fallback: Check fallback enablement when performing IO --- src/amd_detail/backend/fallback.cpp | 4 ++++ test/amd_detail/fallback.cpp | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/amd_detail/backend/fallback.cpp b/src/amd_detail/backend/fallback.cpp index f1d9e081..5358eb56 100644 --- a/src/amd_detail/backend/fallback.cpp +++ b/src/amd_detail/backend/fallback.cpp @@ -63,6 +63,10 @@ ssize_t Fallback::io(IoType io_type, shared_ptr file, shared_ptr buffer, size_t size, hoff_t file_offset, hoff_t buffer_offset, size_t chunk_size) { + if (!Context::get()->fallback()) { + throw BackendDisabled(); + } + size = min(size, hipFile::MAX_RW_COUNT); if (!paramsValid(buffer, size, file_offset, buffer_offset)) { diff --git a/test/amd_detail/fallback.cpp b/test/amd_detail/fallback.cpp index 5cd088b4..4b998949 100644 --- a/test/amd_detail/fallback.cpp +++ b/test/amd_detail/fallback.cpp @@ -116,6 +116,7 @@ struct FallbackIo : public HipFileOpened { StrictMock mhip; StrictMock msys; StrictMock mlibmounthelper; + StrictMock mcfg{}; FallbackIo() : buffer_data(1024 * 1024) { @@ -183,6 +184,7 @@ struct FallbackParam : ::testing::TestWithParam { StrictMock mhip{}; StrictMock msys{}; StrictMock mlibmounthelper{}; + StrictMock mcfg{}; FallbackParam() { @@ -218,8 +220,15 @@ struct FallbackParam : ::testing::TestWithParam { IoType io_type; }; +TEST_P(FallbackParam, FallbackIoRejectedIfBackendIsDiabled) +{ + EXPECT_CALL(mcfg, fallback()).WillOnce(Return(false)); + ASSERT_THROW(Fallback().io(io_type, file, buffer, 0, 0, -1, 4096), BackendDisabled); +} + TEST_P(FallbackParam, FallbackIoThrowsOnNegativeBufferOffset) { + EXPECT_CALL(mcfg, fallback()).WillOnce(Return(true)); ASSERT_THROW(Fallback().io(io_type, file, buffer, 0, 0, -1, 4096), std::invalid_argument); } @@ -227,6 +236,7 @@ TEST_P(FallbackParam, FallbackIoThrowsIfBufferOffsetIsOutOfBounds) { hoff_t buffer_offset{static_cast(buffer->getLength())}; + EXPECT_CALL(mcfg, fallback()).WillOnce(Return(true)); ASSERT_THROW(Fallback().io(io_type, file, buffer, 0, 0, buffer_offset, 4096), std::invalid_argument); } @@ -235,11 +245,13 @@ TEST_P(FallbackParam, FallbackIoThrowsIfOpCouldOverrunBuffer) size_t size{10}; hoff_t buffer_offset{static_cast(buffer->getLength()) - 9}; + EXPECT_CALL(mcfg, fallback()).WillOnce(Return(true)); ASSERT_THROW(Fallback().io(io_type, file, buffer, size, 0, buffer_offset, 4096), std::invalid_argument); } TEST_P(FallbackParam, FallbackIoThrowsOnNegativeFileOffset) { + EXPECT_CALL(mcfg, fallback()).WillOnce(Return(true)); ASSERT_THROW(Fallback().io(io_type, file, buffer, 0, -1, 0, 4096), std::invalid_argument); } @@ -250,6 +262,7 @@ TEST_P(FallbackParam, FallbackIoTruncatesSizeToMAX_RW_COUNT) Context::get()->registerBuffer(buf, MAX_RW_COUNT + 1, 0); auto big_buffer{Context::get()->getRegisteredBuffer(buf)}; + EXPECT_CALL(mcfg, fallback()).WillOnce(Return(true)); EXPECT_CALL(msys, mmap).WillOnce(testing::Return(reinterpret_cast(0xFEFEFEFE))); switch (io_type) { case IoType::Read: @@ -278,6 +291,7 @@ TEST_P(FallbackParam, FallbackIoTruncatesSizeToMAX_RW_COUNT) TEST_P(FallbackParam, FallbackIoThrowsOnBounceBufferAllocationFailure) { + EXPECT_CALL(mcfg, fallback()).WillOnce(Return(true)); EXPECT_CALL(msys, mmap).WillOnce(testing::Throw(std::system_error(ENOMEM, std::generic_category()))); ASSERT_THROW(Fallback().io(io_type, file, buffer, 4096, 0, 0, 4096), std::system_error); } @@ -287,6 +301,7 @@ TEST_P(FallbackParam, FallbackIoAllocatesChunkSizedHostBounceBuffer) size_t chunk_size{1024 * 1024}; auto ptr{reinterpret_cast(0xFEFEFEFE)}; + EXPECT_CALL(mcfg, fallback()).WillOnce(Return(true)); EXPECT_CALL(msys, mmap(testing::_, chunk_size, testing::_, testing::_, testing::_, testing::_)) .WillOnce(testing::Return(ptr)); switch (io_type) { @@ -334,6 +349,7 @@ struct FallbackWrite : public FallbackIo { void expect_fallback_write() { + EXPECT_CALL(mcfg, fallback()).WillOnce(testing::Return(true)); EXPECT_CALL(msys, mmap).WillOnce(testing::Invoke(::mmap)); EXPECT_CALL(mhip, hipMemcpy).WillRepeatedly(testing::Invoke(this, &FallbackWrite::fake_hipMemcpy)); EXPECT_CALL(mhip, hipStreamSynchronize).WillRepeatedly(testing::Return()); @@ -362,6 +378,7 @@ TEST_F(FallbackWrite, FallbackWriteHandlesZeroSizedWrite) TEST_F(FallbackWrite, FallbackWriteThrowsOnPwriteException) { + EXPECT_CALL(mcfg, fallback()).WillOnce(testing::Return(true)); EXPECT_CALL(msys, mmap).WillOnce(testing::Invoke(::mmap)); EXPECT_CALL(mhip, hipMemcpy); EXPECT_CALL(mhip, hipStreamSynchronize); @@ -373,6 +390,7 @@ TEST_F(FallbackWrite, FallbackWriteThrowsOnPwriteException) TEST_F(FallbackWrite, FallbackWriteThrowsOnHipmemcpyFailure) { + EXPECT_CALL(mcfg, fallback()).WillOnce(testing::Return(true)); EXPECT_CALL(msys, mmap).WillOnce(testing::Invoke(::mmap)); EXPECT_CALL(mhip, hipMemcpy).WillOnce(testing::Throw(Hip::RuntimeError(hipErrorUnknown))); EXPECT_CALL(msys, munmap).WillOnce(testing::Invoke(::munmap)); @@ -382,6 +400,7 @@ TEST_F(FallbackWrite, FallbackWriteThrowsOnHipmemcpyFailure) TEST_F(FallbackWrite, FallbackWriteThrowsOnHipStreamSynchronizeError) { + EXPECT_CALL(mcfg, fallback()).WillOnce(testing::Return(true)); EXPECT_CALL(msys, mmap).WillOnce(testing::Invoke(::mmap)); EXPECT_CALL(mhip, hipMemcpy); EXPECT_CALL(mhip, hipStreamSynchronize).WillOnce(testing::Throw(Hip::RuntimeError(hipErrorUnknown))); @@ -526,6 +545,7 @@ struct FallbackRead : public FallbackIo { void expect_fallback_read() { + EXPECT_CALL(mcfg, fallback()).WillOnce(testing::Return(true)); EXPECT_CALL(msys, mmap).WillOnce(testing::Invoke(::mmap)); EXPECT_CALL(msys, pread).WillRepeatedly(testing::Invoke(this, &FallbackRead::fake_pread)); EXPECT_CALL(mhip, hipMemcpy).WillRepeatedly(testing::Invoke(this, &FallbackRead::fake_hipMemcpy)); @@ -558,6 +578,7 @@ TEST_F(FallbackRead, ReadFromRegionWithinFile) TEST_F(FallbackRead, FallbackReadThrowsOnPreadException) { + EXPECT_CALL(mcfg, fallback()).WillOnce(testing::Return(true)); EXPECT_CALL(msys, mmap).WillOnce(testing::Invoke(::mmap)); EXPECT_CALL(msys, pread).WillOnce(testing::Throw(std::system_error(EIO, std::generic_category()))); EXPECT_CALL(msys, munmap).WillOnce(testing::Invoke(::munmap)); @@ -569,6 +590,7 @@ TEST_F(FallbackRead, FallbackReadThrowsOnHipmemcpyFailure) size_t file_length{buffer->getLength()}; init_file(file_length); + EXPECT_CALL(mcfg, fallback()).WillOnce(testing::Return(true)); EXPECT_CALL(msys, mmap).WillOnce(testing::Invoke(::mmap)); EXPECT_CALL(msys, pread).WillRepeatedly(testing::Invoke(this, &FallbackRead::fake_pread)); EXPECT_CALL(mhip, hipMemcpy).WillOnce(testing::Throw(Hip::RuntimeError(hipErrorUnknown))); @@ -581,6 +603,7 @@ TEST_F(FallbackRead, FallbackReadHandlesEmptyFile) const size_t file_length{0}; init_file(file_length); + EXPECT_CALL(mcfg, fallback()).WillOnce(testing::Return(true)); EXPECT_CALL(msys, mmap).WillOnce(testing::Invoke(::mmap)); EXPECT_CALL(msys, pread).WillRepeatedly(testing::Invoke(this, &FallbackRead::fake_pread)); EXPECT_CALL(msys, munmap).WillOnce(testing::Invoke(::munmap)); @@ -593,6 +616,7 @@ TEST_F(FallbackRead, FallbackReadHandlesShortPreads) size_t file_length{buffer->getLength()}; init_file(file_length); + EXPECT_CALL(mcfg, fallback()).WillOnce(testing::Return(true)); EXPECT_CALL(msys, mmap).WillOnce(testing::Invoke(::mmap)); EXPECT_CALL(msys, pread) .WillOnce(testing::Invoke([this](int fd, void *buf, size_t count, hoff_t offset) -> ssize_t { @@ -612,6 +636,7 @@ TEST_F(FallbackRead, FallbackReadHandlesInterruptedPread) size_t file_length{buffer->getLength()}; init_file(file_length); + EXPECT_CALL(mcfg, fallback()).WillOnce(testing::Return(true)); EXPECT_CALL(msys, mmap).WillOnce(testing::Invoke(::mmap)); EXPECT_CALL(msys, pread) .WillOnce(testing::Throw(std::system_error(EINTR, std::generic_category()))) From 1e3f70ab8175a6d3c8912719d1ce0e082645d672 Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Wed, 18 Mar 2026 16:00:08 +0000 Subject: [PATCH 16/19] test/system: Test cleanup - Give parameterized tests better names Clone async tests to improve the name of test variants. Before: HipFileIo.ReadToUnregisteredBufferAtOffset/4-byte object <00-00 00-00> HipFileIo.ReadToUnregisteredBufferAtOffset/4-byte object <01-00 00-00> After: HipFileIo.ReadToUnregisteredBufferAtOffset/Fastpath HipFileIo.ReadToUnregisteredBufferAtOffset/Fallback --- test/system/io.cpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/test/system/io.cpp b/test/system/io.cpp index 297a45ed..348e0c33 100644 --- a/test/system/io.cpp +++ b/test/system/io.cpp @@ -9,10 +9,12 @@ #include "test-common.h" #include "test-options.h" +#include #include -#include #include #include +#include +#include extern SystemTestOptions test_env; @@ -23,7 +25,17 @@ enum class IoTestBackend { Fallback, }; -struct HipFileIo : public testing::TestWithParam { +struct IoTestParam { + IoTestBackend backend; + std::string name; +}; + +HIPFILE_WARN_NO_EXIT_DTOR_OFF +static std::array io_test_params{ + {{IoTestBackend::Fastpath, "Fastpath"}, {IoTestBackend::Fallback, "Fallback"}}}; +HIPFILE_WARN_NO_EXIT_DTOR_ON + +struct HipFileIo : public testing::TestWithParam { Tmpfile tmpfile; size_t tmpfile_size; @@ -63,7 +75,7 @@ struct HipFileIo : public testing::TestWithParam { void SetUp() override { - switch (GetParam()) { + switch (GetParam().backend) { case IoTestBackend::Fastpath: enable_fastpath_only(); break; @@ -112,6 +124,9 @@ TEST_P(HipFileIo, ReadToUnregisteredBufferAtOffsetReturnsErrorIfOverflow) hipFileRead(tmpfile_handle, unregistered_device_buffer, io_size, 0, io_buffer_offset)); } -INSTANTIATE_TEST_SUITE_P(, HipFileIo, testing::Values(IoTestBackend::Fastpath, IoTestBackend::Fallback)); +INSTANTIATE_TEST_SUITE_P(, HipFileIo, testing::ValuesIn(io_test_params), + [](const testing::TestParamInfo ¶m_info) { + return param_info.param.name; + }); HIPFILE_WARN_NO_GLOBAL_CTOR_ON From f4139a383e55ff7af6c2fdd5e297c44126ad8172 Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Wed, 18 Mar 2026 16:20:10 +0000 Subject: [PATCH 17/19] test/system: Use backend override functions to enable the desired backend --- test/system/io.cpp | 37 +++++++++++-------------------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/test/system/io.cpp b/test/system/io.cpp index 348e0c33..45200110 100644 --- a/test/system/io.cpp +++ b/test/system/io.cpp @@ -3,6 +3,8 @@ * SPDX-License-Identifier: MIT */ +#include "context.h" +#include "configuration.h" #include "hipfile-warnings.h" #include "hipfile.h" @@ -18,6 +20,8 @@ extern SystemTestOptions test_env; +using namespace hipFile; + HIPFILE_WARN_NO_GLOBAL_CTOR_OFF enum class IoTestBackend { @@ -49,39 +53,20 @@ struct HipFileIo : public testing::TestWithParam { { } - // Must be called before hipfile is initialized. Relies on each test being - // run in a separate process - void enable_fastpath_only() - { - if (unsetenv("HIPFILE_FORCE_COMPAT_MODE")) { - FAIL() << "Could not clear HIPFILE_FORCE_COMPAT_MODE"; - } - if (setenv("HIPFILE_ALLOW_COMPAT_MODE", "false", 1)) { - FAIL() << "Could not set HIPFILE_ALLOW_COMPAT_MODE=false"; - } - } - - // Must be called before hipfile is initialized. Relies on each test being - // run in a separate process - void enable_fallback_only() - { - if (unsetenv("HIPFILE_ALLOW_COMPAT_MODE")) { - FAIL() << "Could not clear HIPFILE_ALLOW_COMPAT_MODE"; - } - if (setenv("HIPFILE_FORCE_COMPAT_MODE", "true", 1)) { - FAIL() << "Could not set HIPFILE_FORCE_COMPAT_MODE=true"; - } - } - void SetUp() override { + // Disable all backends + Context::get()->fastpath(false); + Context::get()->fallback(false); + + // Enable the desired backend switch (GetParam().backend) { case IoTestBackend::Fastpath: - enable_fastpath_only(); + Context::get()->fastpath(true); break; case IoTestBackend::Fallback: - enable_fallback_only(); + Context::get()->fallback(true); break; default: From 69bb16f84f08d7231b16a97f766e4162846e2669 Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Wed, 18 Mar 2026 17:02:26 +0000 Subject: [PATCH 18/19] state: Always instantiate all backends Backends now check for enablement when they score IO. If a backend is disabled it will not accept IO. Backends can be enabled/disabled at runtime. This was done for testing purposes. To fully support this functionality all backends need to be instantiated. --- src/amd_detail/state.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/amd_detail/state.cpp b/src/amd_detail/state.cpp index fd4aacfa..f65c09db 100644 --- a/src/amd_detail/state.cpp +++ b/src/amd_detail/state.cpp @@ -275,12 +275,8 @@ std::vector> DriverState::getBackends() const { static bool once = [&]() { - if (Context::get()->fastpath()) { - backends.emplace_back(new Fastpath{}); - } - if (Context::get()->fallback()) { - backends.emplace_back(new Fallback{}); - } + backends.emplace_back(new Fastpath{}); + backends.emplace_back(new Fallback{}); return true; }(); (void)once; From 3c912b9583bdd7eb9887401b1fef86ec00cb185d Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Thu, 19 Mar 2026 21:20:30 +0000 Subject: [PATCH 19/19] test/system: Move io.cpp to amd/io.cpp The new mechanism for selecting backends does not work when building for NVIDIA. The original mechanism for selecting backends did not work with NVIDIA either. Moving to an AMD specific directory to make it clear that these tests are AMD only (for now). --- test/CMakeLists.txt | 2 +- test/system/{ => amd}/io.cpp | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename test/system/{ => amd}/io.cpp (100%) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0a0869be..ea93bb51 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -24,7 +24,6 @@ set(SYSTEM_TEST_SOURCE_FILES system/buffer.cpp system/config.cpp system/driver.cpp - system/io.cpp system/main.cpp system/version.cpp ) @@ -38,6 +37,7 @@ if(AIS_BUILD_NVIDIA_DETAIL) list(APPEND UNIT_TEST_SOURCE_FILES nvidia_detail/cufile-api-compat.cpp) list(APPEND TEST_SYSINCLS ${HIPFILE_NVIDIA_SOURCE_PATH}) else() + list(APPEND SYSTEM_TEST_SOURCE_FILES system/amd/io.cpp) list(APPEND TEST_SYSINCLS ${HIPFILE_AMD_SOURCE_PATH}) endif() diff --git a/test/system/io.cpp b/test/system/amd/io.cpp similarity index 100% rename from test/system/io.cpp rename to test/system/amd/io.cpp