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