thrust / dependencies /libcudacxx /libcxx /test /std /input.output /filesystems /class.path /path.member /path.compare.pass.cpp
| //===----------------------------------------------------------------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // UNSUPPORTED: c++98, c++03 | |
| // <filesystem> | |
| // class path | |
| // int compare(path const&) const noexcept; | |
| // int compare(string_type const&) const; | |
| // int compare(value_type const*) const; | |
| // | |
| // bool operator==(path const&, path const&) noexcept; | |
| // bool operator!=(path const&, path const&) noexcept; | |
| // bool operator< (path const&, path const&) noexcept; | |
| // bool operator<=(path const&, path const&) noexcept; | |
| // bool operator> (path const&, path const&) noexcept; | |
| // bool operator>=(path const&, path const&) noexcept; | |
| // | |
| // size_t hash_value(path const&) noexcept; | |
| struct PathCompareTest { | |
| const char* LHS; | |
| const char* RHS; | |
| int expect; | |
| }; | |
| const PathCompareTest CompareTestCases[] = | |
| { | |
| {"", "", 0}, | |
| {"a", "", 1}, | |
| {"", "a", -1}, | |
| {"a/b/c", "a/b/c", 0}, | |
| {"b/a/c", "a/b/c", 1}, | |
| {"a/b/c", "b/a/c", -1}, | |
| {"a/b", "a/b/c", -1}, | |
| {"a/b/c", "a/b", 1}, | |
| {"a/b/", "a/b/.", -1}, | |
| {"a/b/", "a/b", 1}, | |
| {"a/b//////", "a/b/////.", -1}, | |
| {"a/.././b", "a///..//.////b", 0}, | |
| {"//foo//bar///baz////", "//foo/bar/baz/", 0}, // duplicate separators | |
| {"///foo/bar", "/foo/bar", 0}, // "///" is not a root directory | |
| {"/foo/bar/", "/foo/bar", 1}, // trailing separator | |
| {"foo", "/foo", -1}, // if !this->has_root_directory() and p.has_root_directory(), a value less than 0. | |
| {"/foo", "foo", 1}, // if this->has_root_directory() and !p.has_root_directory(), a value greater than 0. | |
| {"//" LONGA "////" LONGB "/" LONGC "///" LONGD, "//" LONGA "/" LONGB "/" LONGC "/" LONGD, 0}, | |
| { LONGA "/" LONGB "/" LONGC, LONGA "/" LONGB "/" LONGB, 1} | |
| }; | |
| static inline int normalize_ret(int ret) | |
| { | |
| return ret < 0 ? -1 : (ret > 0 ? 1 : 0); | |
| } | |
| void test_compare_basic() | |
| { | |
| using namespace fs; | |
| for (auto const & TC : CompareTestCases) { | |
| const path p1(TC.LHS); | |
| const path p2(TC.RHS); | |
| const std::string R(TC.RHS); | |
| const std::string_view RV(TC.RHS); | |
| const int E = TC.expect; | |
| { // compare(...) functions | |
| DisableAllocationGuard g; // none of these operations should allocate | |
| // check runtime results | |
| int ret1 = normalize_ret(p1.compare(p2)); | |
| int ret2 = normalize_ret(p1.compare(R)); | |
| int ret3 = normalize_ret(p1.compare(TC.RHS)); | |
| int ret4 = normalize_ret(p1.compare(RV)); | |
| g.release(); | |
| ASSERT_EQ(ret1, ret2); | |
| ASSERT_EQ(ret1, ret3); | |
| ASSERT_EQ(ret1, ret4); | |
| ASSERT_EQ(ret1, E) | |
| << DISPLAY(TC.LHS) << DISPLAY(TC.RHS); | |
| // check signatures | |
| ASSERT_NOEXCEPT(p1.compare(p2)); | |
| } | |
| { // comparison operators | |
| DisableAllocationGuard g; // none of these operations should allocate | |
| // Check runtime result | |
| assert((p1 == p2) == (E == 0)); | |
| assert((p1 != p2) == (E != 0)); | |
| assert((p1 < p2) == (E < 0)); | |
| assert((p1 <= p2) == (E <= 0)); | |
| assert((p1 > p2) == (E > 0)); | |
| assert((p1 >= p2) == (E >= 0)); | |
| // Check signatures | |
| ASSERT_NOEXCEPT(p1 == p2); | |
| ASSERT_NOEXCEPT(p1 != p2); | |
| ASSERT_NOEXCEPT(p1 < p2); | |
| ASSERT_NOEXCEPT(p1 <= p2); | |
| ASSERT_NOEXCEPT(p1 > p2); | |
| ASSERT_NOEXCEPT(p1 >= p2); | |
| } | |
| { // check hash values | |
| auto h1 = hash_value(p1); | |
| auto h2 = hash_value(p2); | |
| assert((h1 == h2) == (p1 == p2)); | |
| // check signature | |
| ASSERT_SAME_TYPE(size_t, decltype(hash_value(p1))); | |
| ASSERT_NOEXCEPT(hash_value(p1)); | |
| } | |
| } | |
| } | |
| int CompareElements(std::vector<std::string> const& LHS, std::vector<std::string> const& RHS) { | |
| bool IsLess = std::lexicographical_compare(LHS.begin(), LHS.end(), RHS.begin(), RHS.end()); | |
| if (IsLess) | |
| return -1; | |
| bool IsGreater = std::lexicographical_compare(RHS.begin(), RHS.end(), LHS.begin(), LHS.end()); | |
| if (IsGreater) | |
| return 1; | |
| return 0; | |
| } | |
| void test_compare_elements() { | |
| struct { | |
| std::vector<std::string> LHSElements; | |
| std::vector<std::string> RHSElements; | |
| int Expect; | |
| } TestCases[] = { | |
| {{"a"}, {"a"}, 0}, | |
| {{"a"}, {"b"}, -1}, | |
| {{"b"}, {"a"}, 1}, | |
| {{"a", "b", "c"}, {"a", "b", "c"}, 0}, | |
| {{"a", "b", "c"}, {"a", "b", "d"}, -1}, | |
| {{"a", "b", "d"}, {"a", "b", "c"}, 1}, | |
| {{"a", "b"}, {"a", "b", "c"}, -1}, | |
| {{"a", "b", "c"}, {"a", "b"}, 1}, | |
| }; | |
| auto BuildPath = [](std::vector<std::string> const& Elems) { | |
| fs::path p; | |
| for (auto &E : Elems) | |
| p /= E; | |
| return p; | |
| }; | |
| for (auto &TC : TestCases) { | |
| fs::path LHS = BuildPath(TC.LHSElements); | |
| fs::path RHS = BuildPath(TC.RHSElements); | |
| const int ExpectCmp = CompareElements(TC.LHSElements, TC.RHSElements); | |
| assert(ExpectCmp == TC.Expect); | |
| const int GotCmp = normalize_ret(LHS.compare(RHS)); | |
| assert(GotCmp == TC.Expect); | |
| } | |
| } | |
| int main(int, char**) { | |
| test_compare_basic(); | |
| test_compare_elements(); | |
| return 0; | |
| } | |