1f7b43230SLouis Dionne //===----------------------------------------------------------------------===//
2f7b43230SLouis Dionne //
3f7b43230SLouis Dionne // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4f7b43230SLouis Dionne // See https://llvm.org/LICENSE.txt for license information.
5f7b43230SLouis Dionne // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f7b43230SLouis Dionne //
7f7b43230SLouis Dionne //===----------------------------------------------------------------------===//
8f7b43230SLouis Dionne
9ac8c9f1eSLouis Dionne // UNSUPPORTED: c++03, c++11, c++14
10c352fa74SLouis Dionne // UNSUPPORTED: availability-filesystem-missing
11f7b43230SLouis Dionne
1288ffc727SLouis Dionne // These tests require locale for non-char paths
13a7f9895cSLouis Dionne // UNSUPPORTED: no-localization
1488ffc727SLouis Dionne
15f7b43230SLouis Dionne // <filesystem>
16f7b43230SLouis Dionne
17f7b43230SLouis Dionne // class path
18f7b43230SLouis Dionne
19f7b43230SLouis Dionne // template <class Source>
20f7b43230SLouis Dionne // path& operator=(Source const&);
21f7b43230SLouis Dionne // path& operator=(string_type&&);
22f7b43230SLouis Dionne // template <class Source>
23f7b43230SLouis Dionne // path& assign(Source const&);
24f7b43230SLouis Dionne // template <class InputIterator>
25f7b43230SLouis Dionne // path& assign(InputIterator first, InputIterator last);
26f7b43230SLouis Dionne
27ac8c9f1eSLouis Dionne #include <filesystem>
28f7b43230SLouis Dionne #include <type_traits>
29f7b43230SLouis Dionne #include <string_view>
30f7b43230SLouis Dionne #include <cassert>
31f7b43230SLouis Dionne
32f5f3a598SMartin Storsjö // On Windows, charset conversions cause allocations in the path class in
33f5f3a598SMartin Storsjö // cases where no allocations are done on other platforms.
34f5f3a598SMartin Storsjö
35c352fa74SLouis Dionne #include "../../path_helper.h"
36cc89063bSNico Weber #include "count_new.h"
37c352fa74SLouis Dionne #include "make_string.h"
38c352fa74SLouis Dionne #include "test_iterators.h"
39c352fa74SLouis Dionne #include "test_macros.h"
40ac8c9f1eSLouis Dionne namespace fs = std::filesystem;
41f7b43230SLouis Dionne
42f7b43230SLouis Dionne template <class CharT>
RunTestCase(MultiStringType const & MS)43f7b43230SLouis Dionne void RunTestCase(MultiStringType const& MS) {
44f7b43230SLouis Dionne using namespace fs;
4581db3c31SMartin Storsjö const fs::path::value_type* Expect = MS;
46f7b43230SLouis Dionne const CharT* TestPath = MS;
47f7b43230SLouis Dionne const CharT* TestPathEnd = StrEnd(TestPath);
48f7b43230SLouis Dionne const std::size_t Size = TestPathEnd - TestPath;
49f7b43230SLouis Dionne const std::size_t SSize = StrEnd(Expect) - Expect;
50f7b43230SLouis Dionne assert(Size == SSize);
51f7b43230SLouis Dionne //////////////////////////////////////////////////////////////////////////////
52f7b43230SLouis Dionne // basic_string<Char, Traits, Alloc>
53f7b43230SLouis Dionne {
54f7b43230SLouis Dionne const std::basic_string<CharT> S(TestPath);
55f7b43230SLouis Dionne path p; PathReserve(p, S.length() + 1);
56f7b43230SLouis Dionne {
57f7b43230SLouis Dionne // string provides a contiguous iterator. No allocation needed.
58f5f3a598SMartin Storsjö TEST_NOT_WIN32(DisableAllocationGuard g);
59f7b43230SLouis Dionne path& pref = (p = S);
60f7b43230SLouis Dionne assert(&pref == &p);
61f7b43230SLouis Dionne }
62f7b43230SLouis Dionne assert(p.native() == Expect);
63f7b43230SLouis Dionne assert(p.string<CharT>() == TestPath);
64f7b43230SLouis Dionne assert(p.string<CharT>() == S);
65f7b43230SLouis Dionne }
66f7b43230SLouis Dionne {
67f7b43230SLouis Dionne const std::basic_string<CharT> S(TestPath);
68f7b43230SLouis Dionne path p; PathReserve(p, S.length() + 1);
69f7b43230SLouis Dionne {
70f5f3a598SMartin Storsjö TEST_NOT_WIN32(DisableAllocationGuard g);
71f7b43230SLouis Dionne path& pref = p.assign(S);
72f7b43230SLouis Dionne assert(&pref == &p);
73f7b43230SLouis Dionne }
74f7b43230SLouis Dionne assert(p.native() == Expect);
75f7b43230SLouis Dionne assert(p.string<CharT>() == TestPath);
76f7b43230SLouis Dionne assert(p.string<CharT>() == S);
77f7b43230SLouis Dionne }
78f7b43230SLouis Dionne // basic_string<Char, Traits, Alloc>
79f7b43230SLouis Dionne {
80f7b43230SLouis Dionne const std::basic_string_view<CharT> S(TestPath);
81f7b43230SLouis Dionne path p; PathReserve(p, S.length() + 1);
82f7b43230SLouis Dionne {
83f7b43230SLouis Dionne // string provides a contiguous iterator. No allocation needed.
84f5f3a598SMartin Storsjö TEST_NOT_WIN32(DisableAllocationGuard g);
85f7b43230SLouis Dionne path& pref = (p = S);
86f7b43230SLouis Dionne assert(&pref == &p);
87f7b43230SLouis Dionne }
88f7b43230SLouis Dionne assert(p.native() == Expect);
89f7b43230SLouis Dionne assert(p.string<CharT>() == TestPath);
90f7b43230SLouis Dionne assert(p.string<CharT>() == S);
91f7b43230SLouis Dionne }
92f7b43230SLouis Dionne {
93f7b43230SLouis Dionne const std::basic_string_view<CharT> S(TestPath);
94f7b43230SLouis Dionne path p; PathReserve(p, S.length() + 1);
95f7b43230SLouis Dionne {
96f5f3a598SMartin Storsjö TEST_NOT_WIN32(DisableAllocationGuard g);
97f7b43230SLouis Dionne path& pref = p.assign(S);
98f7b43230SLouis Dionne assert(&pref == &p);
99f7b43230SLouis Dionne }
100f7b43230SLouis Dionne assert(p.native() == Expect);
101f7b43230SLouis Dionne assert(p.string<CharT>() == TestPath);
102f7b43230SLouis Dionne assert(p.string<CharT>() == S);
103f7b43230SLouis Dionne }
104f7b43230SLouis Dionne //////////////////////////////////////////////////////////////////////////////
105f7b43230SLouis Dionne // Char* pointers
106f7b43230SLouis Dionne {
107f7b43230SLouis Dionne path p; PathReserve(p, Size + 1);
108f7b43230SLouis Dionne {
109f7b43230SLouis Dionne // char* pointers are contiguous and can be used with code_cvt directly.
110f7b43230SLouis Dionne // no allocations needed.
111f5f3a598SMartin Storsjö TEST_NOT_WIN32(DisableAllocationGuard g);
112f7b43230SLouis Dionne path& pref = (p = TestPath);
113f7b43230SLouis Dionne assert(&pref == &p);
114f7b43230SLouis Dionne }
115f7b43230SLouis Dionne assert(p.native() == Expect);
116f7b43230SLouis Dionne assert(p.string<CharT>() == TestPath);
117f7b43230SLouis Dionne }
118f7b43230SLouis Dionne {
119f7b43230SLouis Dionne path p; PathReserve(p, Size + 1);
120f7b43230SLouis Dionne {
121f5f3a598SMartin Storsjö TEST_NOT_WIN32(DisableAllocationGuard g);
122f7b43230SLouis Dionne path& pref = p.assign(TestPath);
123f7b43230SLouis Dionne assert(&pref == &p);
124f7b43230SLouis Dionne }
125f7b43230SLouis Dionne assert(p.native() == Expect);
126f7b43230SLouis Dionne assert(p.string<CharT>() == TestPath);
127f7b43230SLouis Dionne }
128f7b43230SLouis Dionne {
129f7b43230SLouis Dionne path p; PathReserve(p, Size + 1);
130f7b43230SLouis Dionne {
131f5f3a598SMartin Storsjö TEST_NOT_WIN32(DisableAllocationGuard g);
132f7b43230SLouis Dionne path& pref = p.assign(TestPath, TestPathEnd);
133f7b43230SLouis Dionne assert(&pref == &p);
134f7b43230SLouis Dionne }
135f7b43230SLouis Dionne assert(p.native() == Expect);
136f7b43230SLouis Dionne assert(p.string<CharT>() == TestPath);
137f7b43230SLouis Dionne }
138f7b43230SLouis Dionne //////////////////////////////////////////////////////////////////////////////
139f7b43230SLouis Dionne // Iterators
140f7b43230SLouis Dionne {
141773ae441SChristopher Di Bella using It = cpp17_input_iterator<const CharT*>;
142f7b43230SLouis Dionne path p; PathReserve(p, Size + 1);
143f7b43230SLouis Dionne It it(TestPath);
144f7b43230SLouis Dionne {
145f7b43230SLouis Dionne // Iterators cannot be used with code_cvt directly. This assignment
146f7b43230SLouis Dionne // may allocate if it's larger than a "short-string".
147f7b43230SLouis Dionne path& pref = (p = it);
148f7b43230SLouis Dionne assert(&pref == &p);
149f7b43230SLouis Dionne }
150f7b43230SLouis Dionne assert(p.native() == Expect);
151f7b43230SLouis Dionne assert(p.string<CharT>() == TestPath);
152f7b43230SLouis Dionne }
153f7b43230SLouis Dionne {
154773ae441SChristopher Di Bella using It = cpp17_input_iterator<const CharT*>;
155f7b43230SLouis Dionne path p; PathReserve(p, Size + 1);
156f7b43230SLouis Dionne It it(TestPath);
157f7b43230SLouis Dionne {
158f7b43230SLouis Dionne path& pref = p.assign(it);
159f7b43230SLouis Dionne assert(&pref == &p);
160f7b43230SLouis Dionne }
161f7b43230SLouis Dionne assert(p.native() == Expect);
162f7b43230SLouis Dionne assert(p.string<CharT>() == TestPath);
163f7b43230SLouis Dionne }
164f7b43230SLouis Dionne {
165773ae441SChristopher Di Bella using It = cpp17_input_iterator<const CharT*>;
166f7b43230SLouis Dionne path p; PathReserve(p, Size + 1);
167f7b43230SLouis Dionne It it(TestPath);
168f7b43230SLouis Dionne It e(TestPathEnd);
169f7b43230SLouis Dionne {
170f7b43230SLouis Dionne path& pref = p.assign(it, e);
171f7b43230SLouis Dionne assert(&pref == &p);
172f7b43230SLouis Dionne }
173f7b43230SLouis Dionne assert(p.native() == Expect);
174f7b43230SLouis Dionne assert(p.string<CharT>() == TestPath);
175f7b43230SLouis Dionne }
176f7b43230SLouis Dionne }
177f7b43230SLouis Dionne
178f7b43230SLouis Dionne template <class It, class = decltype(fs::path{}.assign(std::declval<It>()))>
has_assign(int)179f7b43230SLouis Dionne constexpr bool has_assign(int) { return true; }
180f7b43230SLouis Dionne template <class It>
has_assign(long)181f7b43230SLouis Dionne constexpr bool has_assign(long) { return false; }
182f7b43230SLouis Dionne template <class It>
has_assign()183f7b43230SLouis Dionne constexpr bool has_assign() { return has_assign<It>(0); }
184f7b43230SLouis Dionne
test_sfinae()185f7b43230SLouis Dionne void test_sfinae() {
186f7b43230SLouis Dionne using namespace fs;
187f7b43230SLouis Dionne {
188f7b43230SLouis Dionne using It = const char* const;
189f7b43230SLouis Dionne static_assert(std::is_assignable<path, It>::value, "");
190f7b43230SLouis Dionne static_assert(has_assign<It>(), "");
191f7b43230SLouis Dionne }
192f7b43230SLouis Dionne {
193773ae441SChristopher Di Bella using It = cpp17_input_iterator<const char*>;
194f7b43230SLouis Dionne static_assert(std::is_assignable<path, It>::value, "");
195f7b43230SLouis Dionne static_assert(has_assign<It>(), "");
196f7b43230SLouis Dionne }
197f7b43230SLouis Dionne {
198f7b43230SLouis Dionne struct Traits {
199f7b43230SLouis Dionne using iterator_category = std::input_iterator_tag;
200f7b43230SLouis Dionne using value_type = const char;
201f7b43230SLouis Dionne using pointer = const char*;
202f7b43230SLouis Dionne using reference = const char&;
203f7b43230SLouis Dionne using difference_type = std::ptrdiff_t;
204f7b43230SLouis Dionne };
205773ae441SChristopher Di Bella using It = cpp17_input_iterator<const char*, Traits>;
206f7b43230SLouis Dionne static_assert(std::is_assignable<path, It>::value, "");
207f7b43230SLouis Dionne static_assert(has_assign<It>(), "");
208f7b43230SLouis Dionne }
209f7b43230SLouis Dionne {
2105e97d37bSMark de Wever using It = cpp17_output_iterator<const char*>;
211f7b43230SLouis Dionne static_assert(!std::is_assignable<path, It>::value, "");
212f7b43230SLouis Dionne static_assert(!has_assign<It>(), "");
213f7b43230SLouis Dionne
214f7b43230SLouis Dionne }
215f7b43230SLouis Dionne {
216f7b43230SLouis Dionne static_assert(!std::is_assignable<path, int*>::value, "");
217f7b43230SLouis Dionne static_assert(!has_assign<int*>(), "");
218f7b43230SLouis Dionne }
219f7b43230SLouis Dionne }
220f7b43230SLouis Dionne
RunStringMoveTest(const fs::path::value_type * Expect)22181db3c31SMartin Storsjö void RunStringMoveTest(const fs::path::value_type* Expect) {
222f7b43230SLouis Dionne using namespace fs;
22381db3c31SMartin Storsjö fs::path::string_type ss(Expect);
224f7b43230SLouis Dionne path p;
225f7b43230SLouis Dionne {
226f7b43230SLouis Dionne DisableAllocationGuard g; ((void)g);
227f7b43230SLouis Dionne path& pr = (p = std::move(ss));
228f7b43230SLouis Dionne assert(&pr == &p);
229f7b43230SLouis Dionne }
230f7b43230SLouis Dionne assert(p == Expect);
231f7b43230SLouis Dionne {
232f7b43230SLouis Dionne // Signature test
233*fde04e61SStephan T. Lavavej LIBCPP_ASSERT_NOEXCEPT(p = std::move(ss));
234f7b43230SLouis Dionne }
235f7b43230SLouis Dionne }
236f7b43230SLouis Dionne
main(int,char **)237f7b43230SLouis Dionne int main(int, char**) {
238f7b43230SLouis Dionne for (auto const& MS : PathList) {
239f7b43230SLouis Dionne RunTestCase<char>(MS);
240f4c1258dSLouis Dionne #ifndef TEST_HAS_NO_WIDE_CHARACTERS
241f7b43230SLouis Dionne RunTestCase<wchar_t>(MS);
242f4c1258dSLouis Dionne #endif
243f7b43230SLouis Dionne RunTestCase<char16_t>(MS);
244f7b43230SLouis Dionne RunTestCase<char32_t>(MS);
245f7b43230SLouis Dionne RunStringMoveTest(MS);
246f7b43230SLouis Dionne }
247f7b43230SLouis Dionne test_sfinae();
248f7b43230SLouis Dionne
249f7b43230SLouis Dionne return 0;
250f7b43230SLouis Dionne }
251