1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // UNSUPPORTED: c++03 10 11 // <filesystem> 12 13 // class path 14 15 // int compare(path const&) const noexcept; 16 // int compare(string_type const&) const; 17 // int compare(value_type const*) const; 18 // 19 // bool operator==(path const&, path const&) noexcept; 20 // bool operator!=(path const&, path const&) noexcept; 21 // bool operator< (path const&, path const&) noexcept; 22 // bool operator<=(path const&, path const&) noexcept; 23 // bool operator> (path const&, path const&) noexcept; 24 // bool operator>=(path const&, path const&) noexcept; 25 // 26 // size_t hash_value(path const&) noexcept; 27 28 29 #include "filesystem_include.h" 30 #include <type_traits> 31 #include <vector> 32 #include <cassert> 33 34 #include "test_macros.h" 35 #include "test_iterators.h" 36 #include "count_new.h" 37 #include "filesystem_test_helper.h" 38 39 struct PathCompareTest { 40 const char* LHS; 41 const char* RHS; 42 int expect; 43 }; 44 45 #define LONGA "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 46 #define LONGB "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" 47 #define LONGC "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC" 48 #define LONGD "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD" 49 const PathCompareTest CompareTestCases[] = 50 { 51 {"", "", 0}, 52 {"a", "", 1}, 53 {"", "a", -1}, 54 {"a/b/c", "a/b/c", 0}, 55 {"b/a/c", "a/b/c", 1}, 56 {"a/b/c", "b/a/c", -1}, 57 {"a/b", "a/b/c", -1}, 58 {"a/b/c", "a/b", 1}, 59 {"a/b/", "a/b/.", -1}, 60 {"a/b/", "a/b", 1}, 61 {"a/b//////", "a/b/////.", -1}, 62 {"a/.././b", "a///..//.////b", 0}, 63 {"//foo//bar///baz////", "//foo/bar/baz/", 0}, // duplicate separators 64 {"///foo/bar", "/foo/bar", 0}, // "///" is not a root directory 65 {"/foo/bar/", "/foo/bar", 1}, // trailing separator 66 {"foo", "/foo", -1}, // if !this->has_root_directory() and p.has_root_directory(), a value less than 0. 67 {"/foo", "foo", 1}, // if this->has_root_directory() and !p.has_root_directory(), a value greater than 0. 68 {("//" LONGA "////" LONGB "/" LONGC "///" LONGD), ("//" LONGA "/" LONGB "/" LONGC "/" LONGD), 0}, 69 {(LONGA "/" LONGB "/" LONGC), (LONGA "/" LONGB "/" LONGB), 1} 70 71 }; 72 #undef LONGA 73 #undef LONGB 74 #undef LONGC 75 #undef LONGD 76 77 static inline int normalize_ret(int ret) 78 { 79 return ret < 0 ? -1 : (ret > 0 ? 1 : 0); 80 } 81 82 void test_compare_basic() 83 { 84 using namespace fs; 85 for (auto const & TC : CompareTestCases) { 86 const path p1(TC.LHS); 87 const path p2(TC.RHS); 88 std::string RHS(TC.RHS); 89 const path::string_type R(RHS.begin(), RHS.end()); 90 const std::basic_string_view<path::value_type> RV(R); 91 const path::value_type *Ptr = R.c_str(); 92 const int E = TC.expect; 93 { // compare(...) functions 94 DisableAllocationGuard g; // none of these operations should allocate 95 96 // check runtime results 97 int ret1 = normalize_ret(p1.compare(p2)); 98 int ret2 = normalize_ret(p1.compare(R)); 99 int ret3 = normalize_ret(p1.compare(Ptr)); 100 int ret4 = normalize_ret(p1.compare(RV)); 101 102 g.release(); 103 assert(ret1 == ret2); 104 assert(ret1 == ret3); 105 assert(ret1 == ret4); 106 assert(ret1 == E); 107 108 // check signatures 109 ASSERT_NOEXCEPT(p1.compare(p2)); 110 } 111 { // comparison operators 112 DisableAllocationGuard g; // none of these operations should allocate 113 114 // Check runtime result 115 assert((p1 == p2) == (E == 0)); 116 assert((p1 != p2) == (E != 0)); 117 assert((p1 < p2) == (E < 0)); 118 assert((p1 <= p2) == (E <= 0)); 119 assert((p1 > p2) == (E > 0)); 120 assert((p1 >= p2) == (E >= 0)); 121 122 // Check signatures 123 ASSERT_NOEXCEPT(p1 == p2); 124 ASSERT_NOEXCEPT(p1 != p2); 125 ASSERT_NOEXCEPT(p1 < p2); 126 ASSERT_NOEXCEPT(p1 <= p2); 127 ASSERT_NOEXCEPT(p1 > p2); 128 ASSERT_NOEXCEPT(p1 >= p2); 129 } 130 { // check hash values 131 auto h1 = hash_value(p1); 132 auto h2 = hash_value(p2); 133 assert((h1 == h2) == (p1 == p2)); 134 // check signature 135 ASSERT_SAME_TYPE(size_t, decltype(hash_value(p1))); 136 ASSERT_NOEXCEPT(hash_value(p1)); 137 } 138 } 139 } 140 141 int CompareElements(std::vector<std::string> const& LHS, std::vector<std::string> const& RHS) { 142 bool IsLess = std::lexicographical_compare(LHS.begin(), LHS.end(), RHS.begin(), RHS.end()); 143 if (IsLess) 144 return -1; 145 146 bool IsGreater = std::lexicographical_compare(RHS.begin(), RHS.end(), LHS.begin(), LHS.end()); 147 if (IsGreater) 148 return 1; 149 150 return 0; 151 } 152 153 void test_compare_elements() { 154 struct { 155 std::vector<std::string> LHSElements; 156 std::vector<std::string> RHSElements; 157 int Expect; 158 } TestCases[] = { 159 {{"a"}, {"a"}, 0}, 160 {{"a"}, {"b"}, -1}, 161 {{"b"}, {"a"}, 1}, 162 {{"a", "b", "c"}, {"a", "b", "c"}, 0}, 163 {{"a", "b", "c"}, {"a", "b", "d"}, -1}, 164 {{"a", "b", "d"}, {"a", "b", "c"}, 1}, 165 {{"a", "b"}, {"a", "b", "c"}, -1}, 166 {{"a", "b", "c"}, {"a", "b"}, 1}, 167 168 }; 169 170 auto BuildPath = [](std::vector<std::string> const& Elems) { 171 fs::path p; 172 for (auto &E : Elems) 173 p /= E; 174 return p; 175 }; 176 177 for (auto &TC : TestCases) { 178 fs::path LHS = BuildPath(TC.LHSElements); 179 fs::path RHS = BuildPath(TC.RHSElements); 180 const int ExpectCmp = CompareElements(TC.LHSElements, TC.RHSElements); 181 assert(ExpectCmp == TC.Expect); 182 const int GotCmp = normalize_ret(LHS.compare(RHS)); 183 assert(GotCmp == TC.Expect); 184 } 185 } 186 187 int main(int, char**) { 188 test_compare_basic(); 189 test_compare_elements(); 190 191 return 0; 192 } 193