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
normalize_ret(int ret)79 static inline int normalize_ret(int ret)
80 {
81 return ret < 0 ? -1 : (ret > 0 ? 1 : 0);
82 }
83
test_compare_basic()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
CompareElements(std::vector<std::string> const & LHS,std::vector<std::string> const & RHS)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
test_compare_elements()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
main()188 int main() {
189 test_compare_basic();
190 test_compare_elements();
191 }
192