From 0dfc30fdd8f2c5a3db92e2b12ac2366fbba9a9fd Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Tue, 19 Aug 2025 12:21:46 -0700 Subject: [PATCH] APITests: Adds extendedvolatile --- unittests/APITests/CMakeLists.txt | 1 + .../APITests/ExtendedVolatileMetadata.cpp | 158 ++++++++++++++++++ 2 files changed, 159 insertions(+) create mode 100644 unittests/APITests/ExtendedVolatileMetadata.cpp diff --git a/unittests/APITests/CMakeLists.txt b/unittests/APITests/CMakeLists.txt index 071bb0a3f..260f1be47 100644 --- a/unittests/APITests/CMakeLists.txt +++ b/unittests/APITests/CMakeLists.txt @@ -5,6 +5,7 @@ set (TESTS Filesystem StringUtils fextl_function + ExtendedVolatileMetadata ) list(APPEND LIBS Common FEXCore JemallocLibs) diff --git a/unittests/APITests/ExtendedVolatileMetadata.cpp b/unittests/APITests/ExtendedVolatileMetadata.cpp new file mode 100644 index 000000000..4c0654828 --- /dev/null +++ b/unittests/APITests/ExtendedVolatileMetadata.cpp @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: MIT +#include +#include "Common/VolatileMetadata.h" + +TEST_CASE("Basic - Empty") { + const auto String = ""; + const auto Result = FEX::VolatileMetadata::ParseExtendedVolatileMetadata(String); + REQUIRE(Result.empty()); +} + +TEST_CASE("Basic - Empty - modules") { + const auto String = ":::::"; + const auto Result = FEX::VolatileMetadata::ParseExtendedVolatileMetadata(String); + REQUIRE(Result.empty()); +} + +TEST_CASE("Basic - Single") { + const auto String = "hl2_linux"; + const auto Result = FEX::VolatileMetadata::ParseExtendedVolatileMetadata(String); + REQUIRE(Result.size() == 1); + + REQUIRE(Result.contains("hl2_linux")); + CHECK(Result.at("hl2_linux").ModuleTSODisabled == true); + CHECK(Result.at("hl2_linux").VolatileInstructions.empty()); + CHECK(Result.at("hl2_linux").VolatileValidRanges.Empty()); +} + +TEST_CASE("Basic - Multiple") { + const auto String = "hl2_linux:DeckJob"; + const auto Result = FEX::VolatileMetadata::ParseExtendedVolatileMetadata(String); + REQUIRE(Result.size() == 2); + + REQUIRE(Result.contains("hl2_linux")); + CHECK(Result.at("hl2_linux").ModuleTSODisabled == true); + CHECK(Result.at("hl2_linux").VolatileInstructions.empty()); + CHECK(Result.at("hl2_linux").VolatileValidRanges.Empty()); + + REQUIRE(Result.contains("DeckJob")); + CHECK(Result.at("DeckJob").ModuleTSODisabled == true); + CHECK(Result.at("DeckJob").VolatileInstructions.empty()); + CHECK(Result.at("DeckJob").VolatileValidRanges.Empty()); +} + +TEST_CASE("Basic - Single plus empty") { + const auto String = "hl2_linux:::::"; + const auto Result = FEX::VolatileMetadata::ParseExtendedVolatileMetadata(String); + REQUIRE(Result.size() == 1); + REQUIRE(Result.contains("hl2_linux")); + CHECK(Result.at("hl2_linux").ModuleTSODisabled == true); + CHECK(Result.at("hl2_linux").VolatileInstructions.empty()); + CHECK(Result.at("hl2_linux").VolatileValidRanges.Empty()); +} + +static inline bool ContainsRange(std::pair Range, const std::vector>& ValidRanges) { + return std::ranges::find(ValidRanges, Range) != ValidRanges.end(); +} + +TEST_CASE("Basic - Single - offset") { + const auto String = "hl2_linux;0x0-0x1000"; + const auto Result = FEX::VolatileMetadata::ParseExtendedVolatileMetadata(String); + REQUIRE(Result.size() == 1); + + REQUIRE(Result.contains("hl2_linux")); + CHECK(Result.at("hl2_linux").ModuleTSODisabled == false); + CHECK(Result.at("hl2_linux").VolatileInstructions.empty()); + CHECK(Result.at("hl2_linux").VolatileValidRanges.Empty() == false); + + const std::vector> ValidRanges = { + {0, 0x1000}, + }; + + for (auto it : Result.at("hl2_linux").VolatileValidRanges) { + CHECK(ContainsRange(std::make_pair(it.Offset, it.End), ValidRanges)); + } +} + +TEST_CASE("Basic - Single - offset x2") { + const auto String = "hl2_linux;0x0-0x1000,0x2000-0x3000"; + const auto Result = FEX::VolatileMetadata::ParseExtendedVolatileMetadata(String); + REQUIRE(Result.size() == 1); + REQUIRE(Result.contains("hl2_linux")); + CHECK(Result.at("hl2_linux").ModuleTSODisabled == false); + CHECK(Result.at("hl2_linux").VolatileInstructions.empty()); + CHECK(Result.at("hl2_linux").VolatileValidRanges.Empty() == false); + + const std::vector> ValidRanges = { + {0, 0x1000}, + {0x2000, 0x3000}, + }; + + for (auto it : Result.at("hl2_linux").VolatileValidRanges) { + CHECK(ContainsRange(std::make_pair(it.Offset, it.End), ValidRanges)); + } +} + +TEST_CASE("Basic - Single - offset plus instruction") { + const auto String = "hl2_linux;0x0-0x1000;0x1,0x2,0x3"; + const auto Result = FEX::VolatileMetadata::ParseExtendedVolatileMetadata(String); + REQUIRE(Result.size() == 1); + REQUIRE(Result.contains("hl2_linux")); + CHECK(Result.at("hl2_linux").ModuleTSODisabled == false); + CHECK(Result.at("hl2_linux").VolatileInstructions.empty() == false); + CHECK(Result.at("hl2_linux").VolatileValidRanges.Empty() == false); + + const std::vector> ValidRanges = { + {0, 0x1000}, + }; + + const std::vector ValidInsts = { + 1, + 2, + 3, + }; + + for (auto it : Result.at("hl2_linux").VolatileValidRanges) { + CHECK(ContainsRange(std::make_pair(it.Offset, it.End), ValidRanges)); + } + + for (auto it : Result.at("hl2_linux").VolatileInstructions) { + CHECK_THAT(ValidInsts, Catch::Matchers::Contains(it)); + } +} + +TEST_CASE("Basic - Double - offset") { + const auto String = "hl2_linux;0x0-0x1000:DeckJob;0x2000-0x3000"; + const auto Result = FEX::VolatileMetadata::ParseExtendedVolatileMetadata(String); + REQUIRE(Result.size() == 2); + + { + REQUIRE(Result.contains("hl2_linux")); + CHECK(Result.at("hl2_linux").ModuleTSODisabled == false); + CHECK(Result.at("hl2_linux").VolatileInstructions.empty()); + CHECK(Result.at("hl2_linux").VolatileValidRanges.Empty() == false); + + const std::vector> ValidRanges = { + {0, 0x1000}, + }; + + for (auto it : Result.at("hl2_linux").VolatileValidRanges) { + CHECK(ContainsRange(std::make_pair(it.Offset, it.End), ValidRanges)); + } + } + + { + REQUIRE(Result.contains("DeckJob")); + CHECK(Result.at("DeckJob").ModuleTSODisabled == false); + CHECK(Result.at("DeckJob").VolatileInstructions.empty()); + CHECK(Result.at("DeckJob").VolatileValidRanges.Empty() == false); + + const std::vector> ValidRanges = { + {0x2000, 0x3000}, + }; + + for (auto it : Result.at("DeckJob").VolatileValidRanges) { + CHECK(ContainsRange(std::make_pair(it.Offset, it.End), ValidRanges)); + } + } +}