path.compare.pass.cpp 5.8 KB

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