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++98, 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 #include "verbose_assert.h"
39
40 struct PathCompareTest {
41 const char* LHS;
42 const char* RHS;
43 int expect;
44 };
45
46 #define LONGA "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
47 #define LONGB "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
48 #define LONGC "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
49 #define LONGD "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
50 const PathCompareTest CompareTestCases[] =
51 {
52 {"", "", 0},
53 {"a", "", 1},
54 {"", "a", -1},
55 {"a/b/c", "a/b/c", 0},
56 {"b/a/c", "a/b/c", 1},
57 {"a/b/c", "b/a/c", -1},
58 {"a/b", "a/b/c", -1},
59 {"a/b/c", "a/b", 1},
60 {"a/b/", "a/b/.", -1},
61 {"a/b/", "a/b", 1},
62 {"a/b//////", "a/b/////.", -1},
63 {"a/.././b", "a///..//.////b", 0},
64 {"//foo//bar///baz////", "//foo/bar/baz/", 0}, // duplicate separators
65 {"///foo/bar", "/foo/bar", 0}, // "///" is not a root directory
66 {"/foo/bar/", "/foo/bar", 1}, // trailing separator
67 {"foo", "/foo", -1}, // if !this->has_root_directory() and p.has_root_directory(), a value less than 0.
68 {"/foo", "foo", 1}, // if this->has_root_directory() and !p.has_root_directory(), a value greater than 0.
69 {"//" LONGA "////" LONGB "/" LONGC "///" LONGD, "//" LONGA "/" LONGB "/" LONGC "/" LONGD, 0},
70 { LONGA "/" LONGB "/" LONGC, LONGA "/" LONGB "/" LONGB, 1}
71
72 };
73 #undef LONGA
74 #undef LONGB
75 #undef LONGC
76 #undef LONGD
77
normalize_ret(int ret)78 static inline int normalize_ret(int ret)
79 {
80 return ret < 0 ? -1 : (ret > 0 ? 1 : 0);
81 }
82
test_compare_basic()83 void test_compare_basic()
84 {
85 using namespace fs;
86 for (auto const & TC : CompareTestCases) {
87 const path p1(TC.LHS);
88 const path p2(TC.RHS);
89 const std::string R(TC.RHS);
90 const std::string_view RV(TC.RHS);
91 const int E = TC.expect;
92 { // compare(...) functions
93 DisableAllocationGuard g; // none of these operations should allocate
94
95 // check runtime results
96 int ret1 = normalize_ret(p1.compare(p2));
97 int ret2 = normalize_ret(p1.compare(R));
98 int ret3 = normalize_ret(p1.compare(TC.RHS));
99 int ret4 = normalize_ret(p1.compare(RV));
100
101 g.release();
102 ASSERT_EQ(ret1, ret2);
103 ASSERT_EQ(ret1, ret3);
104 ASSERT_EQ(ret1, ret4);
105 ASSERT_EQ(ret1, E)
106 << DISPLAY(TC.LHS) << DISPLAY(TC.RHS);
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
CompareElements(std::vector<std::string> const & LHS,std::vector<std::string> const & RHS)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
test_compare_elements()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
main(int,char **)187 int main(int, char**) {
188 test_compare_basic();
189 test_compare_elements();
190
191 return 0;
192 }
193