xref: /llvm-project/libcxx/test/std/input.output/filesystems/class.path/path.member/path.assign/source.pass.cpp (revision fde04e61cb7393f0ca982d7fc905a17767d93e6e)
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