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/fallback.cpp b/src/amd_detail/backend/fallback.cpp index 1d2caa73..5358eb56 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 @@ -61,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/src/amd_detail/backend/fastpath.cpp b/src/amd_detail/backend/fastpath.cpp index aba587c8..972b61b2 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; @@ -158,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/src/amd_detail/configuration.cpp b/src/amd_detail/configuration.cpp index b18340d2..7bf89583 100644 --- a/src/amd_detail/configuration.cpp +++ b/src/amd_detail/configuration.cpp @@ -6,51 +6,43 @@ #include "configuration.h" #include "environment.h" #include "hip.h" +#include "static.h" #include using namespace hipFile; -Configuration::Configuration() : m_fastpath(true), m_fallback(true), m_statsLevel(0) +bool +Configuration::fastpath() const noexcept { - 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(); - } + STATIC bool fastpath_env{!Environment::force_compat_mode().value_or(false)}; + STATIC bool readExists{!!getHipAmdFileReadPtr()}; + STATIC bool writeExists{!!getHipAmdFileWritePtr()}; + return readExists && writeExists && m_fastpath_override.value_or(fastpath_env); } -bool -Configuration::fastpath() const noexcept +void +Configuration::fastpath(bool enabled) noexcept { -#ifndef AIS_TESTING - static -#endif - bool readExists{!!getHipAmdFileReadPtr()}; -#ifndef AIS_TESTING - static -#endif - bool writeExists{!!getHipAmdFileWritePtr()}; - return readExists && writeExists && m_fastpath; + m_fastpath_override = enabled; } bool Configuration::fallback() const noexcept { - return m_fallback; + STATIC bool fallback_env{Environment::allow_compat_mode().value_or(true)}; + return m_fallback_override.value_or(fallback_env); +} + +void +Configuration::fallback(bool enabled) noexcept +{ + m_fallback_override = enabled; } 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..8648a62d 100644 --- a/src/amd_detail/configuration.h +++ b/src/amd_detail/configuration.h @@ -5,38 +5,38 @@ #pragma once +#include + namespace hipFile { -class IConfiguration { +class Configuration { + + std::optional m_fastpath_override; + std::optional m_fallback_override; + 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 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 = 0; + 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 = 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/src/amd_detail/hip.cpp b/src/amd_detail/hip.cpp index 963495d6..df3e89f7 100644 --- a/src/amd_detail/hip.cpp +++ b/src/amd_detail/hip.cpp @@ -5,6 +5,7 @@ #include "context.h" #include "hip.h" +#include "static.h" #include #include @@ -24,22 +25,16 @@ catch (...) { hipAmdFileRead_t getHipAmdFileReadPtr() { -#ifndef AIS_TESTING - static -#endif - hipAmdFileRead_t hipAmdFileReadPtr{ - reinterpret_cast(hipGetProcAddressHelper("hipAmdFileRead"))}; + STATIC hipAmdFileRead_t hipAmdFileReadPtr{ + reinterpret_cast(hipGetProcAddressHelper("hipAmdFileRead"))}; return hipAmdFileReadPtr; } hipAmdFileWrite_t getHipAmdFileWritePtr() { -#ifndef AIS_TESTING - static -#endif - hipAmdFileWrite_t hipAmdFileWritePtr{ - reinterpret_cast(hipGetProcAddressHelper("hipAmdFileWrite"))}; + STATIC hipAmdFileWrite_t hipAmdFileWritePtr{ + reinterpret_cast(hipGetProcAddressHelper("hipAmdFileWrite"))}; return hipAmdFileWritePtr; } diff --git a/src/amd_detail/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; 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 diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0a0869be..ea93bb51 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -24,7 +24,6 @@ set(SYSTEM_TEST_SOURCE_FILES system/buffer.cpp system/config.cpp system/driver.cpp - system/io.cpp system/main.cpp system/version.cpp ) @@ -38,6 +37,7 @@ if(AIS_BUILD_NVIDIA_DETAIL) list(APPEND UNIT_TEST_SOURCE_FILES nvidia_detail/cufile-api-compat.cpp) list(APPEND TEST_SYSINCLS ${HIPFILE_NVIDIA_SOURCE_PATH}) else() + list(APPEND SYSTEM_TEST_SOURCE_FILES system/amd/io.cpp) list(APPEND TEST_SYSINCLS ${HIPFILE_AMD_SOURCE_PATH}) endif() diff --git a/test/amd_detail/configuration.cpp b/test/amd_detail/configuration.cpp index 737b10b9..e465f99f 100644 --- a/test/amd_detail/configuration.cpp +++ b/test/amd_detail/configuration.cpp @@ -20,166 +20,177 @@ 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; - } - - ConfigurationExpectationBuilder &hip_amd_file_read(void *value) - { - m_hip_amd_file_read = value; - return *this; - } +struct HipFileConfiguration : public Test { + StrictMock msys; + StrictMock mhip; - ConfigurationExpectationBuilder &hip_amd_file_write(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_write = 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 &fastpath() + void expect_configuration_fallback(const char *hipfile_allow_compat_mode) { - m_fastpath = true; - return *this; + EXPECT_CALL(msys, getenv(StrEq(hipFile::Environment::ALLOW_COMPAT_MODE))) + .WillOnce(Return(const_cast(hipfile_allow_compat_mode))); } - ConfigurationExpectation build(); -}; - -struct ConfigurationExpectation { - ConfigurationExpectation(const ConfigurationExpectationBuilder &builder) + void expect_configuration_statslevel(const char *hipfile_stats_level) { - 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)); - } + EXPECT_CALL(msys, getenv(StrEq(hipFile::Environment::STATS_LEVEL))) + .WillOnce(Return(const_cast(hipfile_stats_level))); } }; -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, 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) { - 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, OverrideDisabledFastpathBackend) { - ConfigurationExpectationBuilder{msys, mhip}.build(); + 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); + 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, 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) { - ConfigurationExpectationBuilder{msys, mhip}.env_allow_compat_mode("false").build(); + expect_configuration_fallback("false"); ASSERT_FALSE(Configuration().fallback()); } -TEST_F(HipFileConfiguration, StatsLevelEnvironmentVariableIsNotSetOrInvalid) +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); + 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/fallback.cpp b/test/amd_detail/fallback.cpp index dffa530c..4b998949 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" @@ -53,13 +54,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 +86,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 +96,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,16 +107,19 @@ 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; + StrictMock msys; + StrictMock mlibmounthelper; + StrictMock mcfg{}; 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); @@ -139,48 +143,55 @@ 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>()}; + 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); } -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}; - + EXPECT_CALL(mcfg, fallback()).WillRepeatedly(Return(true)); 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); } } +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; - shared_ptr file; + shared_ptr buffer{}; + shared_ptr file{}; + + StrictMock mhip{}; + StrictMock msys{}; + StrictMock mlibmounthelper{}; + StrictMock mcfg{}; FallbackParam() { - StrictMock mhip; - StrictMock msys; - StrictMock mlibmounthelper; - 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); @@ -209,47 +220,49 @@ struct FallbackParam : ::testing::TestWithParam { IoType io_type; }; -TEST_P(FallbackParam, fallback_io_throws_on_negative_buffer_offset) +TEST_P(FallbackParam, FallbackIoRejectedIfBackendIsDiabled) { - StrictMock mhip; - StrictMock msys; + 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); } -TEST_P(FallbackParam, fallback_io_throws_if_buffer_offset_is_out_of_bounds) +TEST_P(FallbackParam, FallbackIoThrowsIfBufferOffsetIsOutOfBounds) { - StrictMock mhip; - StrictMock msys; - hoff_t buffer_offset = static_cast(buffer->getLength()); + 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); } -TEST_P(FallbackParam, fallback_io_throws_if_op_could_overrun_buffer) +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}; + + 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, fallback_io_throws_on_negative_file_offset) +TEST_P(FallbackParam, FallbackIoThrowsOnNegativeFileOffset) { - StrictMock mhip; - StrictMock msys; + EXPECT_CALL(mcfg, fallback()).WillOnce(Return(true)); 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; - 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(mcfg, fallback()).WillOnce(Return(true)); EXPECT_CALL(msys, mmap).WillOnce(testing::Return(reinterpret_cast(0xFEFEFEFE))); switch (io_type) { case IoType::Read: @@ -276,20 +289,19 @@ 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; + 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); } -TEST_P(FallbackParam, fallback_io_allocates_chunk_sized_host_bounce_buffer) +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(mcfg, fallback()).WillOnce(Return(true)); EXPECT_CALL(msys, mmap(testing::_, chunk_size, testing::_, testing::_, testing::_, testing::_)) .WillOnce(testing::Return(ptr)); switch (io_type) { @@ -325,7 +337,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); } @@ -335,8 +347,9 @@ struct FallbackWrite : public FallbackIo { return static_cast(count); } - void expect_fallback_write(MHip &mhip, MSys &msys) + 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()); @@ -355,24 +368,17 @@ struct FallbackWrite : public FallbackIo { { rand_fill(buffer_data); } - - void *nonnull_ptr = reinterpret_cast(0x1); }; -TEST_F(FallbackWrite, fallback_write_handles_zero_sized_write) +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, fallback_write_throws_on_pwrite_exception) +TEST_F(FallbackWrite, FallbackWriteThrowsOnPwriteException) { - StrictMock mhip; - StrictMock msys; - + EXPECT_CALL(mcfg, fallback()).WillOnce(testing::Return(true)); EXPECT_CALL(msys, mmap).WillOnce(testing::Invoke(::mmap)); EXPECT_CALL(mhip, hipMemcpy); EXPECT_CALL(mhip, hipStreamSynchronize); @@ -382,11 +388,9 @@ 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; - + 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)); @@ -394,11 +398,9 @@ 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; - + 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))); @@ -407,110 +409,89 @@ 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; - - 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(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)); } -TEST_F(FallbackWrite, fallback_write_to_empty_file_at_file_offset) +TEST_F(FallbackWrite, FallbackWriteToEmptyFileAtFileOffset) { - StrictMock mhip; - StrictMock msys; - - 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(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)); } -TEST_F(FallbackWrite, fallback_write_to_empty_file_at_buffer_offset) +TEST_F(FallbackWrite, FallbackWriteToEmptyFileAtBufferOffset) { - StrictMock mhip; - StrictMock msys; - - 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(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)); } -TEST_F(FallbackWrite, fallback_write_to_empty_file_at_buffer_offset_file_offset) +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; + 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)); } -TEST_F(FallbackWrite, fallback_write_overwite_entire_file) +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())); } -TEST_F(FallbackWrite, fallback_write_to_file_subregion) +TEST_F(FallbackWrite, FallbackWriteToFileSubregion) { - StrictMock mhip; - StrictMock msys; - - 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(mhip, msys); + expect_fallback_write(); ASSERT_EQ(buffer->getLength(), Fallback().io(IoType::Write, file, buffer, buffer->getLength(), file_offset, 0)); 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; - 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(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)); @@ -538,7 +519,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; @@ -562,22 +543,19 @@ 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(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)); EXPECT_CALL(msys, munmap).WillOnce(testing::Invoke(::munmap)); } - - void *nonnull_ptr = reinterpret_cast(0x1); }; -TEST_F(FallbackRead, fallback_read_handles_zero_sized_read) +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)); } @@ -586,39 +564,33 @@ TEST_F(FallbackRead, fallback_read_handles_zero_sized_read) /// [SOF.....[....REGION....]....EOF] TEST_F(FallbackRead, ReadFromRegionWithinFile) { - StrictMock mhip; - StrictMock msys; - - 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(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, fallback_read_throws_on_pread_exception) +TEST_F(FallbackRead, FallbackReadThrowsOnPreadException) { - StrictMock mhip; - StrictMock msys; + 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)); 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; - - size_t file_length = buffer->getLength(); + 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))); @@ -626,14 +598,12 @@ 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; - - const size_t file_length = 0; + 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)); @@ -641,14 +611,12 @@ 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; - - size_t file_length = buffer->getLength(); + 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 { @@ -663,14 +631,12 @@ 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; - - size_t file_length = buffer->getLength(); + 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()))) @@ -683,187 +649,148 @@ 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; - - size_t file_length = buffer->getLength() / 2; + 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, fallback_read_handles_file_same_size_as_buffer) +TEST_F(FallbackRead, FallbackReadHandlesFileSameSizeAsBuffer) { - StrictMock mhip; - StrictMock msys; - - size_t file_length = buffer->getLength(); + 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, fallback_read_handles_file_larger_than_buffer) +TEST_F(FallbackRead, FallbackReadHandlesFileLargerThanBuffer) { - StrictMock mhip; - StrictMock msys; - - size_t file_length = buffer->getLength() * 2; + 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, fallback_read_handles_file_with_size_multiple_of_chunk_size) +TEST_F(FallbackRead, FallbackReadHandlesFileWithSizeMultipleOfChunkSize) { - StrictMock mhip; - StrictMock msys; - - 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(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, fallback_read_handles_files_with_size_not_multiple_of_chunk_size) +TEST_F(FallbackRead, FallbackReadHandlesFilesWithSizeNotMultipleOfChunkSize) { - StrictMock mhip; - StrictMock msys; - - 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(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, fallback_read_with_non_zero_file_offset) +TEST_F(FallbackRead, FallbackReadWithNonZeroFileOffset) { - StrictMock mhip; - StrictMock msys; - - 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(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())); } -TEST_F(FallbackRead, fallback_read_to_eof_with_non_zero_file_offset) +TEST_F(FallbackRead, FallbackReadToEofWithNonZeroFileOffset) { - StrictMock mhip; - StrictMock msys; - - 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(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())); } -TEST_F(FallbackRead, fallback_read_past_eof_with_non_zero_file_offset) +TEST_F(FallbackRead, FallbackReadPastEofWithNonZeroFileOffset) { - StrictMock mhip; - StrictMock msys; - - 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(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)); } -TEST_F(FallbackRead, fallback_read_can_read_single_byte_at_end_of_file) +TEST_F(FallbackRead, FallbackReadCanReadSingleByteAtEndOfFile) { - StrictMock mhip; - StrictMock msys; - - 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(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, fallback_read_emtpy_file_with_non_zero_file_offset) +TEST_F(FallbackRead, FallbackReadEmtpyFileWithNonZeroFileOffset) { - StrictMock mhip; - StrictMock msys; - - 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(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, fallback_read_with_non_zero_buffer_offset) +TEST_F(FallbackRead, FallbackReadWithNonZeroBufferOffset) { - StrictMock mhip; - StrictMock msys; - - 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(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)); } -TEST_F(FallbackRead, fallback_read_can_read_into_last_byte_of_buffer) +TEST_F(FallbackRead, FallbackReadCanReadIntoLastByteOfBuffer) { - StrictMock mhip; - StrictMock msys; - - 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(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, fallback_read_with_non_zero_buffer_offset_and_file_offset) +TEST_F(FallbackRead, FallbackReadWithNonZeroBufferOffsetAndFileOffset) { - StrictMock mhip; - StrictMock msys; - - 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(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)); } diff --git a/test/amd_detail/fastpath.cpp b/test/amd_detail/fastpath.cpp index 258f29d0..25d213e3 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) @@ -329,6 +361,7 @@ struct FastpathIoParam : public FastpathTestBase, public TestWithParam { void expect_io() { + EXPECT_CALL(mcfg, fastpath()).WillOnce(Return(DEFAULT_ENABLE)); EXPECT_CALL(*mbuffer, getBuffer).WillOnce(Return(DEFAULT_BUFFER_ADDR)); EXPECT_CALL(*mbuffer, getLength).WillOnce(Return(DEFAULT_BUFFER_LENGTH)); EXPECT_CALL(*mfile, getUnbufferedFd).WillOnce(Return(DEFAULT_UNBUFFERED_FD)); @@ -336,12 +369,19 @@ struct FastpathIoParam : public FastpathTestBase, public TestWithParam { void expect_io(optional fd, void *bufptr, size_t buflen) { + EXPECT_CALL(mcfg, fastpath()).WillOnce(Return(DEFAULT_ENABLE)); EXPECT_CALL(*mbuffer, getBuffer).WillOnce(Return(bufptr)); EXPECT_CALL(*mbuffer, getLength).WillOnce(Return(buflen)); EXPECT_CALL(*mfile, getUnbufferedFd).WillOnce(Return(fd)); } }; +TEST_P(FastpathIoParam, IoRejectedIfFastpathDisabled) +{ + EXPECT_CALL(mcfg, fastpath()).WillOnce(Return(false)); + ASSERT_THROW(Fastpath().io(GetParam(), mfile, mbuffer, 0, -1, 0), BackendDisabled); +} + TEST_P(FastpathIoParam, IoRejectsNegativeFileOffset) { expect_io(); diff --git a/test/amd_detail/hipfile-api.cpp b/test/amd_detail/hipfile-api.cpp index 73367ffe..af9adc29 100644 --- a/test/amd_detail/hipfile-api.cpp +++ b/test/amd_detail/hipfile-api.cpp @@ -203,6 +203,13 @@ TEST_P(HipFileIoParam, HipFileIoHandlesInvalidArgumentError) ASSERT_EQ(hipFileIo(GetParam(), file_handle, bufptr, buflen, 0, 0, mbackends), -hipFileInvalidValue); } +TEST_P(HipFileIoParam, HipFileIoHandlesBackendDisabled) +{ + EXPECT_CALL(*mbackend, score).WillOnce(Return(1)); + EXPECT_CALL(*mbackend, io).WillOnce(Throw(BackendDisabled())); + ASSERT_EQ(hipFileIo(GetParam(), file_handle, bufptr, buflen, 0, 0, mbackends), -hipFileInternalError); +} + INSTANTIATE_TEST_SUITE_P(HipFileIo, HipFileIoParam, Values(IoType::Read, IoType::Write)); struct HipFileIoBackendSelectionParam : public ::testing::TestWithParam { diff --git a/test/amd_detail/mconfiguration.h b/test/amd_detail/mconfiguration.h index a0a75704..fe910247 100644 --- a/test/amd_detail/mconfiguration.h +++ b/test/amd_detail/mconfiguration.h @@ -6,14 +6,21 @@ #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(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)); }; 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{}; } diff --git a/test/system/io.cpp b/test/system/amd/io.cpp similarity index 66% rename from test/system/io.cpp rename to test/system/amd/io.cpp index 297a45ed..45200110 100644 --- a/test/system/io.cpp +++ b/test/system/amd/io.cpp @@ -3,19 +3,25 @@ * SPDX-License-Identifier: MIT */ +#include "context.h" +#include "configuration.h" #include "hipfile-warnings.h" #include "hipfile.h" #include "test-common.h" #include "test-options.h" +#include #include -#include #include #include +#include +#include extern SystemTestOptions test_env; +using namespace hipFile; + HIPFILE_WARN_NO_GLOBAL_CTOR_OFF enum class IoTestBackend { @@ -23,7 +29,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; @@ -37,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 { - switch (GetParam()) { + // 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: @@ -112,6 +109,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