Fixed issue where two Paths could compare equal to each other, but hash differently (#4126)
* Fixed issue where two Paths could compare equal to each other, but hash differently This issue is caused by the Path comparison logic using the path separator of the left path in a comparison of two paths(left and right) to determine whether the PathComparison is case-sensitive or not. The logic has been updated to only perform a non-case-sensitive path comparison if both paths are using the WindowsPathSeperator of `\` Also fixed issue with the Hashing algorihtm of the Path class to always hash the root directory as if it is `/`. This allows a path of "C:\foo" and "C:/foo" to hash to the equivalent value. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * MS Build Tools 14.29 workaround around suppressing warnings using the external header feature Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
bd8c53550a
commit
ce72e32cfc
@@ -213,6 +213,82 @@ namespace UnitTest
|
||||
AZStd::tuple<AZStd::string_view, AZStd::string_view>(R"(foO/Bar)", "foo/bar")
|
||||
));
|
||||
|
||||
|
||||
struct PathHashCompareParams
|
||||
{
|
||||
AZ::IO::PathView m_testPath{};
|
||||
::testing::Matcher<AZ::IO::PathView> m_compareMatcher;
|
||||
::testing::Matcher<size_t> m_hashMatcher;
|
||||
};
|
||||
|
||||
class PathHashCompareFixture
|
||||
: public ScopedAllocatorSetupFixture
|
||||
, public ::testing::WithParamInterface<PathHashCompareParams>
|
||||
{};
|
||||
|
||||
// Verifies that two paths that compare equal has their hash value compare equal
|
||||
TEST_P(PathHashCompareFixture, PathsWhichCompareEqual_HashesToSameValue_Succeeds)
|
||||
{
|
||||
auto&& [testPath1, compareMatcher, hashMatcher] = GetParam();
|
||||
|
||||
// Compare path using parameterized Matcher
|
||||
EXPECT_THAT(testPath1, compareMatcher);
|
||||
// Compare hash using parameterized Matcher
|
||||
const size_t testPath1Hash = AZStd::hash<AZ::IO::PathView>{}(testPath1);
|
||||
AZ_PUSH_DISABLE_WARNING(4296, "-Wunknown-warning-option")
|
||||
EXPECT_THAT(testPath1Hash, hashMatcher);
|
||||
AZ_POP_DISABLE_WARNING
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
HashPathCompareValidation,
|
||||
PathHashCompareFixture,
|
||||
::testing::Values(
|
||||
PathHashCompareParams{ AZ::IO::PathView("C:/test/foo", AZ::IO::WindowsPathSeparator),
|
||||
testing::Eq(AZ::IO::PathView(R"(c:\test/foo)", AZ::IO::WindowsPathSeparator)),
|
||||
testing::Eq(AZStd::hash<AZ::IO::PathView>{}(AZ::IO::PathView(R"(c:\test/foo)", AZ::IO::WindowsPathSeparator))) },
|
||||
PathHashCompareParams{ AZ::IO::PathView("/test/foo", AZ::IO::WindowsPathSeparator),
|
||||
testing::Eq(AZ::IO::PathView(R"(/test/FOO)", AZ::IO::WindowsPathSeparator)),
|
||||
testing::Eq(AZStd::hash<AZ::IO::PathView>{}(AZ::IO::PathView(R"(/test/FOO)", AZ::IO::WindowsPathSeparator))) },
|
||||
PathHashCompareParams{ AZ::IO::PathView("C:/test/foo", AZ::IO::WindowsPathSeparator),
|
||||
testing::Eq(AZ::IO::PathView(R"(c:\test/foo)", AZ::IO::WindowsPathSeparator)),
|
||||
testing::Eq(AZStd::hash<AZ::IO::PathView>{}(AZ::IO::PathView(R"(c:\test/foo)", AZ::IO::WindowsPathSeparator))) },
|
||||
PathHashCompareParams{ AZ::IO::PathView("C:/test/foo", AZ::IO::PosixPathSeparator),
|
||||
testing::Ne(AZ::IO::PathView(R"(c:\test/foo)", AZ::IO::WindowsPathSeparator)),
|
||||
testing::Ne(AZStd::hash<AZ::IO::PathView>{}(AZ::IO::PathView(R"(c:\test/foo)", AZ::IO::WindowsPathSeparator))) },
|
||||
PathHashCompareParams{ AZ::IO::PathView(R"(C:\test\foo)", AZ::IO::WindowsPathSeparator),
|
||||
testing::Ne(AZ::IO::PathView(R"(c:/test/foo)", AZ::IO::PosixPathSeparator)),
|
||||
testing::Ne(AZStd::hash<AZ::IO::PathView>{}(AZ::IO::PathView(R"(c:/test/foo)", AZ::IO::PosixPathSeparator))) },
|
||||
PathHashCompareParams{ AZ::IO::PathView("/test/aoo", AZ::IO::WindowsPathSeparator),
|
||||
testing::Eq(AZ::IO::PathView(R"(/test/AOO)", AZ::IO::WindowsPathSeparator)),
|
||||
testing::Eq(AZStd::hash<AZ::IO::PathView>{}(AZ::IO::PathView(R"(/test/AOO)", AZ::IO::WindowsPathSeparator))) },
|
||||
PathHashCompareParams{ AZ::IO::PathView("/test/aoo", AZ::IO::PosixPathSeparator),
|
||||
testing::Gt(AZ::IO::PathView(R"(/test/AOO)", AZ::IO::WindowsPathSeparator)),
|
||||
testing::Eq(AZStd::hash<AZ::IO::PathView>{}(AZ::IO::PathView(R"(/test/AOO)", AZ::IO::WindowsPathSeparator))) },
|
||||
PathHashCompareParams{ AZ::IO::PathView("/test/aoo", AZ::IO::WindowsPathSeparator),
|
||||
testing::Gt(AZ::IO::PathView(R"(/test/AOO)", AZ::IO::PosixPathSeparator)),
|
||||
testing::Ne(AZStd::hash<AZ::IO::PathView>{}(AZ::IO::PathView(R"(/test/AOO)", AZ::IO::PosixPathSeparator))) },
|
||||
PathHashCompareParams{ AZ::IO::PathView("/test/AOO", AZ::IO::PosixPathSeparator),
|
||||
testing::Lt(AZ::IO::PathView(R"(/test/aoo)", AZ::IO::WindowsPathSeparator)),
|
||||
testing::Ne(AZStd::hash<AZ::IO::PathView>{}(AZ::IO::PathView(R"(/test/aoo)", AZ::IO::WindowsPathSeparator))) },
|
||||
PathHashCompareParams{ AZ::IO::PathView("/test/AOO", AZ::IO::WindowsPathSeparator),
|
||||
testing::Lt(AZ::IO::PathView(R"(/test/aoo)", AZ::IO::PosixPathSeparator)),
|
||||
testing::Eq(AZStd::hash<AZ::IO::PathView>{}(AZ::IO::PathView(R"(/test/aoo)", AZ::IO::PosixPathSeparator))) },
|
||||
// Paths with different character values, comparison based on path separator
|
||||
PathHashCompareParams{ AZ::IO::PathView("/test/BOO", AZ::IO::PosixPathSeparator),
|
||||
testing::Le(AZ::IO::PathView(R"(/test/aoo)", AZ::IO::WindowsPathSeparator)),
|
||||
testing::Ne(AZStd::hash<AZ::IO::PathView>{}(AZ::IO::PathView(R"(/test/aoo)", AZ::IO::WindowsPathSeparator))) },
|
||||
PathHashCompareParams{ AZ::IO::PathView("/test/BOO", AZ::IO::WindowsPathSeparator),
|
||||
testing::Ge(AZ::IO::PathView(R"(/test/aoo)", AZ::IO::WindowsPathSeparator)),
|
||||
testing::Ne(AZStd::hash<AZ::IO::PathView>{}(AZ::IO::PathView(R"(/test/aoo)", AZ::IO::WindowsPathSeparator))) },
|
||||
PathHashCompareParams{ AZ::IO::PathView("/test/aoo", AZ::IO::WindowsPathSeparator),
|
||||
testing::Le(AZ::IO::PathView(R"(/test/Boo)", AZ::IO::WindowsPathSeparator)),
|
||||
testing::Ne(AZStd::hash<AZ::IO::PathView>{}(AZ::IO::PathView(R"(/test/Boo)", AZ::IO::WindowsPathSeparator))) },
|
||||
PathHashCompareParams{ AZ::IO::PathView("/test/aoo", AZ::IO::PosixPathSeparator),
|
||||
testing::Ge(AZ::IO::PathView(R"(/test/Boo)", AZ::IO::WindowsPathSeparator)),
|
||||
testing::Ne(AZStd::hash<AZ::IO::PathView>{}(AZ::IO::PathView(R"(/test/Boo)", AZ::IO::WindowsPathSeparator))) }
|
||||
));
|
||||
|
||||
class PathSingleParamFixture
|
||||
: public ScopedAllocatorSetupFixture
|
||||
, public ::testing::WithParamInterface<AZStd::tuple<AZStd::string_view>>
|
||||
|
||||
Reference in New Issue
Block a user