From a1df42cc347b3e46c1ef662ab557b81ede40a939 Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Wed, 18 Mar 2026 20:02:40 +0000 Subject: [PATCH 01/21] 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 9396eda2..66196817 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 8201ca7949746b87b0555f675a466896fad9a9fc Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Wed, 18 Mar 2026 21:25:29 +0000 Subject: [PATCH 02/21] 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 84f94274574e8deccec1397d56a13ad229ee04f2 Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Wed, 18 Mar 2026 02:32:08 +0000 Subject: [PATCH 03/21] 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 4f0fe42bc92504e2e0dea1f9fcb41da92cbdb5f0 Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Wed, 18 Mar 2026 02:32:08 +0000 Subject: [PATCH 04/21] 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 2163b527e27cc5265647fcd05f188fbbb6009cac Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Wed, 18 Mar 2026 02:40:05 +0000 Subject: [PATCH 05/21] 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 70bf39af..af748ec6 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 47b05d6b..220c8871 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 0c0023ea0ad66bd006ccbd8455e6472a8d70d8ce Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Wed, 18 Mar 2026 02:40:05 +0000 Subject: [PATCH 06/21] 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 af748ec6..35652363 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 220c8871..06098b70 100644 --- a/test/amd_detail/fastpath.cpp +++ b/test/amd_detail/fastpath.cpp @@ -364,6 +364,7 @@ struct FastpathIoParam : public FastpathTestBase, public TestWithParam { // Setup expectations on the mocks called to validate IO arguments void expect_validate() { + 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)); @@ -380,6 +381,7 @@ struct FastpathIoParam : public FastpathTestBase, public TestWithParam { // Setup expectations on the mocks called to validate IO arguments void expect_validate(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)); @@ -394,6 +396,12 @@ struct FastpathIoParam : public FastpathTestBase, public TestWithParam { } }; +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_validate(); 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 1fdd6cdfaa65c449480fdfce21b5c073977ed531 Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Wed, 18 Mar 2026 15:37:01 +0000 Subject: [PATCH 07/21] 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 ae9c4fc020ed03313fa016cc852c4a72f5aedb4b Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Thu, 19 Mar 2026 17:05:33 +0000 Subject: [PATCH 08/21] 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 d9018da559ec4a6fd49b480723fd8b0e943167dc Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Thu, 19 Mar 2026 16:49:57 +0000 Subject: [PATCH 09/21] 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 b2befbf3150af2fa4a7363531c1b8923eceb3f5a Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Thu, 19 Mar 2026 17:09:37 +0000 Subject: [PATCH 10/21] 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 eb17eb7355343c11efdea1b96720af4cc2c825e7 Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Thu, 19 Mar 2026 16:52:01 +0000 Subject: [PATCH 11/21] 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 c8d3b6536ef065a38823a0f2670762b307fc1805 Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Thu, 19 Mar 2026 16:52:46 +0000 Subject: [PATCH 12/21] 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 75a56c442affe522216661f0d14ab5db40fd1f6c Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Thu, 19 Mar 2026 16:47:11 +0000 Subject: [PATCH 13/21] 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 be682752223f1c318a39fa3e36c4d180ccee02c4 Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Wed, 18 Mar 2026 02:40:05 +0000 Subject: [PATCH 14/21] 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 cf2acf03530eebdc3bdea7e6c6b30c9ddf5c1592 Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Wed, 18 Mar 2026 02:40:05 +0000 Subject: [PATCH 15/21] 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 b247f5eadb464f475f24a5f706c802eb68aac9bf Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Wed, 18 Mar 2026 16:00:08 +0000 Subject: [PATCH 16/21] 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 997e283996b43185ffa200bb34db4fd7d88bc109 Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Wed, 18 Mar 2026 16:20:10 +0000 Subject: [PATCH 17/21] 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 a5788677411cb9bef58c7d3a575f9af292c4beb9 Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Wed, 18 Mar 2026 17:02:26 +0000 Subject: [PATCH 18/21] 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 2bc8468bff3efdef5e38af97558397ccab9234d1 Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Thu, 19 Mar 2026 21:20:30 +0000 Subject: [PATCH 19/21] 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 d851bb77..780cef48 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 From a6053d153e75d688769388083e346796087a8d07 Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Mon, 23 Mar 2026 15:31:45 +0000 Subject: [PATCH 20/21] review: Rename STATIC -> HIPFILE_STATIC --- src/amd_detail/configuration.cpp | 10 +++++----- src/amd_detail/hip.cpp | 4 ++-- src/amd_detail/static.h | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/amd_detail/configuration.cpp b/src/amd_detail/configuration.cpp index 7bf89583..97b88e19 100644 --- a/src/amd_detail/configuration.cpp +++ b/src/amd_detail/configuration.cpp @@ -15,9 +15,9 @@ using namespace hipFile; bool Configuration::fastpath() const noexcept { - STATIC bool fastpath_env{!Environment::force_compat_mode().value_or(false)}; - STATIC bool readExists{!!getHipAmdFileReadPtr()}; - STATIC bool writeExists{!!getHipAmdFileWritePtr()}; + HIPFILE_STATIC bool fastpath_env{!Environment::force_compat_mode().value_or(false)}; + HIPFILE_STATIC bool readExists{!!getHipAmdFileReadPtr()}; + HIPFILE_STATIC bool writeExists{!!getHipAmdFileWritePtr()}; return readExists && writeExists && m_fastpath_override.value_or(fastpath_env); } @@ -30,7 +30,7 @@ Configuration::fastpath(bool enabled) noexcept bool Configuration::fallback() const noexcept { - STATIC bool fallback_env{Environment::allow_compat_mode().value_or(true)}; + HIPFILE_STATIC bool fallback_env{Environment::allow_compat_mode().value_or(true)}; return m_fallback_override.value_or(fallback_env); } @@ -43,6 +43,6 @@ Configuration::fallback(bool enabled) noexcept unsigned int Configuration::statsLevel() const noexcept { - STATIC unsigned int stats_level_env{Environment::stats_level().value_or(0)}; + HIPFILE_STATIC unsigned int stats_level_env{Environment::stats_level().value_or(0)}; return stats_level_env; } diff --git a/src/amd_detail/hip.cpp b/src/amd_detail/hip.cpp index 66196817..66a9f149 100644 --- a/src/amd_detail/hip.cpp +++ b/src/amd_detail/hip.cpp @@ -25,7 +25,7 @@ catch (...) { hipAmdFileRead_t getHipAmdFileReadPtr() { - STATIC hipAmdFileRead_t hipAmdFileReadPtr{ + HIPFILE_STATIC hipAmdFileRead_t hipAmdFileReadPtr{ reinterpret_cast(hipGetProcAddressHelper("hipAmdFileRead"))}; return hipAmdFileReadPtr; } @@ -33,7 +33,7 @@ getHipAmdFileReadPtr() hipAmdFileWrite_t getHipAmdFileWritePtr() { - STATIC hipAmdFileWrite_t hipAmdFileWritePtr{ + HIPFILE_STATIC hipAmdFileWrite_t hipAmdFileWritePtr{ reinterpret_cast(hipGetProcAddressHelper("hipAmdFileWrite"))}; return hipAmdFileWritePtr; } diff --git a/src/amd_detail/static.h b/src/amd_detail/static.h index dbb2894d..ca0b14d6 100644 --- a/src/amd_detail/static.h +++ b/src/amd_detail/static.h @@ -9,7 +9,7 @@ // Declaring a variable as STATIC will result in the variable being static only // when tests are not being built. #ifdef AIS_TESTING -#define STATIC +#define HIPFILE_STATIC #else -#define STATIC static +#define HIPFILE_STATIC static #endif From a45a49e298d9fde53fa4147aa04abcc7bfd764d7 Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Mon, 23 Mar 2026 15:33:48 +0000 Subject: [PATCH 21/21] review: Fix typos --- test/amd_detail/fallback.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/amd_detail/fallback.cpp b/test/amd_detail/fallback.cpp index 4b998949..f257727a 100644 --- a/test/amd_detail/fallback.cpp +++ b/test/amd_detail/fallback.cpp @@ -220,7 +220,7 @@ struct FallbackParam : ::testing::TestWithParam { IoType io_type; }; -TEST_P(FallbackParam, FallbackIoRejectedIfBackendIsDiabled) +TEST_P(FallbackParam, FallbackIoRejectedIfBackendIsDisabled) { EXPECT_CALL(mcfg, fallback()).WillOnce(Return(false)); ASSERT_THROW(Fallback().io(io_type, file, buffer, 0, 0, -1, 4096), BackendDisabled); @@ -461,7 +461,7 @@ TEST_F(FallbackWrite, FallbackWriteToEmptyFileAtBufferOffsetFileOffset) ASSERT_TRUE(file_contains_expected_data(file_offset, buffer_offset, size)); } -TEST_F(FallbackWrite, FallbackWriteOverwiteEntireFile) +TEST_F(FallbackWrite, FallbackWriteOverwriteEntireFile) { file_data.resize(buffer->getLength()); randomize_device_buffer(); @@ -748,7 +748,7 @@ TEST_F(FallbackRead, FallbackReadCanReadSingleByteAtEndOfFile) ASSERT_TRUE(device_buffer_contains_expected_data(file_offset, 0, 1)); } -TEST_F(FallbackRead, FallbackReadEmtpyFileWithNonZeroFileOffset) +TEST_F(FallbackRead, FallbackReadEmptyFileWithNonZeroFileOffset) { size_t file_length{0}; init_file(file_length);