xref: /llvm-project/libcxx/test/std/input.output/filesystems/class.path/path.member/path.concat.pass.cpp (revision ac8c9f1e39e1a773fd81ce23dbf1c80ea186f226)
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 
9*ac8c9f1eSLouis 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 // path& operator+=(const path& x);
20f7b43230SLouis Dionne // path& operator+=(const string_type& x);
21f7b43230SLouis Dionne // path& operator+=(string_view x);
22f7b43230SLouis Dionne // path& operator+=(const value_type* x);
23f7b43230SLouis Dionne // path& operator+=(value_type x);
24f7b43230SLouis Dionne // template <class Source>
25f7b43230SLouis Dionne //   path& operator+=(const Source& x);
26f7b43230SLouis Dionne // template <class EcharT>
27f7b43230SLouis Dionne //   path& operator+=(EcharT x);
28f7b43230SLouis Dionne // template <class Source>
29f7b43230SLouis Dionne //   path& concat(const Source& x);
30f7b43230SLouis Dionne // template <class InputIterator>
31f7b43230SLouis Dionne //   path& concat(InputIterator first, InputIterator last);
32f7b43230SLouis Dionne 
33*ac8c9f1eSLouis Dionne #include <filesystem>
34f7b43230SLouis Dionne #include <type_traits>
35f7b43230SLouis Dionne #include <string>
36f7b43230SLouis Dionne #include <string_view>
37f7b43230SLouis Dionne #include <cassert>
38f7b43230SLouis Dionne 
39f5f3a598SMartin Storsjö // On Windows, charset conversions cause allocations in the path class in
40f5f3a598SMartin Storsjö // cases where no allocations are done on other platforms.
41f5f3a598SMartin Storsjö 
42c352fa74SLouis Dionne #include "../path_helper.h"
43cc89063bSNico Weber #include "count_new.h"
44c352fa74SLouis Dionne #include "make_string.h"
45c352fa74SLouis Dionne #include "test_iterators.h"
46c352fa74SLouis Dionne #include "test_macros.h"
47*ac8c9f1eSLouis Dionne namespace fs = std::filesystem;
48f7b43230SLouis Dionne 
49f7b43230SLouis Dionne struct ConcatOperatorTestcase {
50f7b43230SLouis Dionne   MultiStringType lhs;
51f7b43230SLouis Dionne   MultiStringType rhs;
52f7b43230SLouis Dionne   MultiStringType expect;
53f7b43230SLouis Dionne };
54f7b43230SLouis Dionne 
55f7b43230SLouis Dionne #define LONGSTR "LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR"
56f7b43230SLouis Dionne #define S(Str) MKSTR(Str)
57f7b43230SLouis Dionne const ConcatOperatorTestcase Cases[] =
58f7b43230SLouis Dionne     {
59f7b43230SLouis Dionne         {S(""),         S(""),                  S("")}
60f7b43230SLouis Dionne       , {S("p1"),       S("p2"),                S("p1p2")}
61f7b43230SLouis Dionne       , {S("p1/"),      S("/p2"),               S("p1//p2")}
62f7b43230SLouis Dionne       , {S(""),         S("\\foo/bar/baz"),     S("\\foo/bar/baz")}
63f7b43230SLouis Dionne       , {S("c:\\foo"),  S(""),                  S("c:\\foo")}
64f7b43230SLouis Dionne       , {S(LONGSTR),    S("foo"),               S(LONGSTR "foo")}
65f7b43230SLouis Dionne       , {S("abcdefghijklmnopqrstuvwxyz/\\"), S("/\\123456789"), S("abcdefghijklmnopqrstuvwxyz/\\/\\123456789")}
66f7b43230SLouis Dionne     };
67f7b43230SLouis Dionne const ConcatOperatorTestcase LongLHSCases[] =
68f7b43230SLouis Dionne     {
69f7b43230SLouis Dionne         {S(""),        S(LONGSTR),     S(LONGSTR)}
70f7b43230SLouis Dionne       , {S("p1/"),     S(LONGSTR),      S("p1/" LONGSTR)}
71f7b43230SLouis Dionne     };
72f7b43230SLouis Dionne const ConcatOperatorTestcase CharTestCases[] =
73f7b43230SLouis Dionne     {
74f7b43230SLouis Dionne         {S(""),       S("P"), S("P")}
75f7b43230SLouis Dionne       , {S("/fooba"), S("r"), S("/foobar")}
76f7b43230SLouis Dionne     };
77f7b43230SLouis Dionne #undef S
78f7b43230SLouis Dionne #undef LONGSTR
79f7b43230SLouis Dionne 
80f7b43230SLouis Dionne // The concat operator may need to allocate a temporary buffer before a code_cvt
81f7b43230SLouis Dionne // conversion. Test if this allocation occurs by:
82f7b43230SLouis Dionne //   1. Create a path, `LHS`, and reserve enough space to append `RHS`.
83f7b43230SLouis Dionne //      This prevents `LHS` from allocating during the actual appending.
84f7b43230SLouis Dionne //   2. Create a `Source` object `RHS`, which represents a "large" string.
85f7b43230SLouis Dionne //      (The string must not trigger the SSO)
86f7b43230SLouis Dionne //   3. Concat `RHS` to `LHS` and check for the expected allocation behavior.
87f7b43230SLouis Dionne template <class CharT>
doConcatSourceAllocTest(ConcatOperatorTestcase const & TC)88f7b43230SLouis Dionne void doConcatSourceAllocTest(ConcatOperatorTestcase const& TC)
89f7b43230SLouis Dionne {
90f7b43230SLouis Dionne   using namespace fs;
91f7b43230SLouis Dionne   using Ptr = CharT const*;
92f7b43230SLouis Dionne   using Str = std::basic_string<CharT>;
93f7b43230SLouis Dionne   using StrView = std::basic_string_view<CharT>;
94773ae441SChristopher Di Bella   using InputIter = cpp17_input_iterator<Ptr>;
95f7b43230SLouis Dionne 
96f7b43230SLouis Dionne   const Ptr L = TC.lhs;
97f7b43230SLouis Dionne   const Ptr R = TC.rhs;
98f7b43230SLouis Dionne   const Ptr E =  TC.expect;
99f7b43230SLouis Dionne   std::size_t ReserveSize = StrLen(E) + 1;
100f7b43230SLouis Dionne   // basic_string
101f7b43230SLouis Dionne   {
102f7b43230SLouis Dionne     path LHS(L); PathReserve(LHS, ReserveSize);
103f7b43230SLouis Dionne     Str  RHS(R);
104f7b43230SLouis Dionne     {
105f5f3a598SMartin Storsjö       TEST_NOT_WIN32(DisableAllocationGuard g);
106f7b43230SLouis Dionne       LHS += RHS;
107f7b43230SLouis Dionne     }
108f7b43230SLouis Dionne     assert(LHS == E);
109f7b43230SLouis Dionne   }
110f7b43230SLouis Dionne   // basic_string_view
111f7b43230SLouis Dionne   {
112f7b43230SLouis Dionne     path LHS(L); PathReserve(LHS, ReserveSize);
113f7b43230SLouis Dionne     StrView  RHS(R);
114f7b43230SLouis Dionne     {
115f5f3a598SMartin Storsjö       TEST_NOT_WIN32(DisableAllocationGuard g);
116f7b43230SLouis Dionne       LHS += RHS;
117f7b43230SLouis Dionne     }
118f7b43230SLouis Dionne     assert(LHS == E);
119f7b43230SLouis Dionne   }
120f7b43230SLouis Dionne   // CharT*
121f7b43230SLouis Dionne   {
122f7b43230SLouis Dionne     path LHS(L); PathReserve(LHS, ReserveSize);
123f7b43230SLouis Dionne     Ptr RHS(R);
124f7b43230SLouis Dionne     {
125f5f3a598SMartin Storsjö       TEST_NOT_WIN32(DisableAllocationGuard g);
126f7b43230SLouis Dionne       LHS += RHS;
127f7b43230SLouis Dionne     }
128f7b43230SLouis Dionne     assert(LHS == E);
129f7b43230SLouis Dionne   }
130f7b43230SLouis Dionne   {
131f7b43230SLouis Dionne     path LHS(L); PathReserve(LHS, ReserveSize);
132f7b43230SLouis Dionne     Ptr RHS(R);
133f7b43230SLouis Dionne     {
134f5f3a598SMartin Storsjö       TEST_NOT_WIN32(DisableAllocationGuard g);
135f7b43230SLouis Dionne       LHS.concat(RHS, StrEnd(RHS));
136f7b43230SLouis Dionne     }
137f7b43230SLouis Dionne     assert(LHS == E);
138f7b43230SLouis Dionne   }
139f7b43230SLouis Dionne   // input iterator - For non-native char types, appends needs to copy the
140f7b43230SLouis Dionne   // iterator range into a contiguous block of memory before it can perform the
141f7b43230SLouis Dionne   // code_cvt conversions.
142f5f3a598SMartin Storsjö   // For the path native type, no allocations will be performed because no
143f5f3a598SMartin Storsjö   // conversion is required.
1440e8f5e4aSMartin Storsjö 
145128b2136SMartin Storsjö #if TEST_SUPPORTS_LIBRARY_INTERNAL_ALLOCATIONS
146128b2136SMartin Storsjö   // Only check allocations if we can pick up allocations done within the
147128b2136SMartin Storsjö   // library implementation.
148128b2136SMartin Storsjö   bool ExpectNoAllocations = std::is_same<CharT, path::value_type>::value;
149128b2136SMartin Storsjö #endif
150f7b43230SLouis Dionne   {
151f7b43230SLouis Dionne     path LHS(L); PathReserve(LHS, ReserveSize);
152f7b43230SLouis Dionne     InputIter RHS(R);
153f7b43230SLouis Dionne     {
154128b2136SMartin Storsjö       RequireAllocationGuard g(0); // require "at least zero" allocations by default
155128b2136SMartin Storsjö #if TEST_SUPPORTS_LIBRARY_INTERNAL_ALLOCATIONS
156128b2136SMartin Storsjö       if (ExpectNoAllocations)
157128b2136SMartin Storsjö         g.requireExactly(0);
158128b2136SMartin Storsjö #endif
159f7b43230SLouis Dionne       LHS += RHS;
160f7b43230SLouis Dionne     }
161f7b43230SLouis Dionne     assert(LHS == E);
162f7b43230SLouis Dionne   }
163f7b43230SLouis Dionne   {
164f7b43230SLouis Dionne     path LHS(L); PathReserve(LHS, ReserveSize);
165f7b43230SLouis Dionne     InputIter RHS(R);
166f7b43230SLouis Dionne     InputIter REnd(StrEnd(R));
167f7b43230SLouis Dionne     {
168128b2136SMartin Storsjö       RequireAllocationGuard g(0); // require "at least zero" allocations by default
169128b2136SMartin Storsjö #if TEST_SUPPORTS_LIBRARY_INTERNAL_ALLOCATIONS
170128b2136SMartin Storsjö       if (ExpectNoAllocations)
171128b2136SMartin Storsjö         g.requireExactly(0);
172128b2136SMartin Storsjö #endif
173f7b43230SLouis Dionne       LHS.concat(RHS, REnd);
174f7b43230SLouis Dionne     }
175f7b43230SLouis Dionne     assert(LHS == E);
176f7b43230SLouis Dionne   }
177f7b43230SLouis Dionne }
178f7b43230SLouis Dionne 
179f7b43230SLouis Dionne template <class CharT>
doConcatSourceTest(ConcatOperatorTestcase const & TC)180f7b43230SLouis Dionne void doConcatSourceTest(ConcatOperatorTestcase const& TC)
181f7b43230SLouis Dionne {
182f7b43230SLouis Dionne   using namespace fs;
183f7b43230SLouis Dionne   using Ptr = CharT const*;
184f7b43230SLouis Dionne   using Str = std::basic_string<CharT>;
185f7b43230SLouis Dionne   using StrView = std::basic_string_view<CharT>;
186773ae441SChristopher Di Bella   using InputIter = cpp17_input_iterator<Ptr>;
187f7b43230SLouis Dionne   const Ptr L = TC.lhs;
188f7b43230SLouis Dionne   const Ptr R = TC.rhs;
189f7b43230SLouis Dionne   const Ptr E = TC.expect;
190f7b43230SLouis Dionne   // basic_string
191f7b43230SLouis Dionne   {
192f7b43230SLouis Dionne     path LHS(L);
193f7b43230SLouis Dionne     Str RHS(R);
194f7b43230SLouis Dionne     path& Ref = (LHS += RHS);
195f7b43230SLouis Dionne     assert(LHS == E);
196f7b43230SLouis Dionne     assert(&Ref == &LHS);
197f7b43230SLouis Dionne   }
198f7b43230SLouis Dionne   {
199f7b43230SLouis Dionne     path LHS(L);
200f7b43230SLouis Dionne     Str RHS(R);
201f7b43230SLouis Dionne     path& Ref = LHS.concat(RHS);
202f7b43230SLouis Dionne     assert(LHS == E);
203f7b43230SLouis Dionne     assert(&Ref == &LHS);
204f7b43230SLouis Dionne   }
205f7b43230SLouis Dionne   // basic_string_view
206f7b43230SLouis Dionne   {
207f7b43230SLouis Dionne     path LHS(L);
208f7b43230SLouis Dionne     StrView RHS(R);
209f7b43230SLouis Dionne     path& Ref = (LHS += RHS);
210f7b43230SLouis Dionne     assert(LHS == E);
211f7b43230SLouis Dionne     assert(&Ref == &LHS);
212f7b43230SLouis Dionne   }
213f7b43230SLouis Dionne   {
214f7b43230SLouis Dionne     path LHS(L);
215f7b43230SLouis Dionne     StrView RHS(R);
216f7b43230SLouis Dionne     path& Ref = LHS.concat(RHS);
217f7b43230SLouis Dionne     assert(LHS == E);
218f7b43230SLouis Dionne     assert(&Ref == &LHS);
219f7b43230SLouis Dionne   }
220f7b43230SLouis Dionne   // Char*
221f7b43230SLouis Dionne   {
222f7b43230SLouis Dionne     path LHS(L);
223f7b43230SLouis Dionne     Str RHS(R);
224f7b43230SLouis Dionne     path& Ref = (LHS += RHS);
225f7b43230SLouis Dionne     assert(LHS == E);
226f7b43230SLouis Dionne     assert(&Ref == &LHS);
227f7b43230SLouis Dionne   }
228f7b43230SLouis Dionne   {
229f7b43230SLouis Dionne     path LHS(L);
230f7b43230SLouis Dionne     Ptr RHS(R);
231f7b43230SLouis Dionne     path& Ref = LHS.concat(RHS);
232f7b43230SLouis Dionne     assert(LHS == E);
233f7b43230SLouis Dionne     assert(&Ref == &LHS);
234f7b43230SLouis Dionne   }
235f7b43230SLouis Dionne   {
236f7b43230SLouis Dionne     path LHS(L);
237f7b43230SLouis Dionne     Ptr RHS(R);
238f7b43230SLouis Dionne     path& Ref = LHS.concat(RHS, StrEnd(RHS));
239f7b43230SLouis Dionne     assert(LHS == E);
240f7b43230SLouis Dionne     assert(&Ref == &LHS);
241f7b43230SLouis Dionne   }
242f7b43230SLouis Dionne   // iterators
243f7b43230SLouis Dionne   {
244f7b43230SLouis Dionne     path LHS(L);
245f7b43230SLouis Dionne     InputIter RHS(R);
246f7b43230SLouis Dionne     path& Ref = (LHS += RHS);
247f7b43230SLouis Dionne     assert(LHS == E);
248f7b43230SLouis Dionne     assert(&Ref == &LHS);
249f7b43230SLouis Dionne   }
250f7b43230SLouis Dionne   {
251f7b43230SLouis Dionne     path LHS(L); InputIter RHS(R);
252f7b43230SLouis Dionne     path& Ref = LHS.concat(RHS);
253f7b43230SLouis Dionne     assert(LHS == E);
254f7b43230SLouis Dionne     assert(&Ref == &LHS);
255f7b43230SLouis Dionne   }
256f7b43230SLouis Dionne   {
257f7b43230SLouis Dionne     path LHS(L);
258f7b43230SLouis Dionne     InputIter RHS(R);
259f7b43230SLouis Dionne     InputIter REnd(StrEnd(R));
260f7b43230SLouis Dionne     path& Ref = LHS.concat(RHS, REnd);
261f7b43230SLouis Dionne     assert(LHS == E);
262f7b43230SLouis Dionne     assert(&Ref == &LHS);
263f7b43230SLouis Dionne   }
264f7b43230SLouis Dionne }
265f7b43230SLouis Dionne 
266f7b43230SLouis Dionne template <class CharT>
doConcatECharTest(ConcatOperatorTestcase const & TC)267f7b43230SLouis Dionne void doConcatECharTest(ConcatOperatorTestcase const& TC)
268f7b43230SLouis Dionne {
269f7b43230SLouis Dionne   using namespace fs;
270f7b43230SLouis Dionne   using Ptr = CharT const*;
271f7b43230SLouis Dionne   const Ptr RStr = TC.rhs;
272f7b43230SLouis Dionne   assert(StrLen(RStr) == 1);
273f7b43230SLouis Dionne   const Ptr L   = TC.lhs;
274f7b43230SLouis Dionne   const CharT R = RStr[0];
275f7b43230SLouis Dionne   const Ptr E   = TC.expect;
276f7b43230SLouis Dionne   {
277f7b43230SLouis Dionne     path LHS(L);
278f7b43230SLouis Dionne     path& Ref = (LHS += R);
279f7b43230SLouis Dionne     assert(LHS == E);
280f7b43230SLouis Dionne     assert(&Ref == &LHS);
281f7b43230SLouis Dionne   }
282f7b43230SLouis Dionne }
283f7b43230SLouis Dionne 
284f7b43230SLouis Dionne 
285f7b43230SLouis Dionne template <class It, class = decltype(fs::path{}.concat(std::declval<It>()))>
has_concat(int)286f7b43230SLouis Dionne constexpr bool has_concat(int) { return true; }
287f7b43230SLouis Dionne template <class It>
has_concat(long)288f7b43230SLouis Dionne constexpr bool has_concat(long) { return false; }
289f7b43230SLouis Dionne 
290f7b43230SLouis Dionne template <class It, class = decltype(fs::path{}.operator+=(std::declval<It>()))>
has_concat_op(int)291f7b43230SLouis Dionne constexpr bool has_concat_op(int) { return true; }
292f7b43230SLouis Dionne template <class It>
has_concat_op(long)293f7b43230SLouis Dionne constexpr bool has_concat_op(long) { return false; }
294f7b43230SLouis Dionne template <class It>
has_concat_op()295f7b43230SLouis Dionne constexpr bool has_concat_op() { return has_concat_op<It>(0); }
296f7b43230SLouis Dionne 
297f7b43230SLouis Dionne template <class It>
has_concat()298f7b43230SLouis Dionne constexpr bool has_concat() {
299f7b43230SLouis Dionne   static_assert(has_concat<It>(0) == has_concat_op<It>(0), "must be same");
300f7b43230SLouis Dionne   return has_concat<It>(0) && has_concat_op<It>(0);
301f7b43230SLouis Dionne }
302f7b43230SLouis Dionne 
test_sfinae()303f7b43230SLouis Dionne void test_sfinae() {
304f7b43230SLouis Dionne   using namespace fs;
305f7b43230SLouis Dionne   {
306f7b43230SLouis Dionne     static_assert(has_concat_op<char>(), "");
307f7b43230SLouis Dionne     static_assert(has_concat_op<const char>(), "");
308f7b43230SLouis Dionne     static_assert(has_concat_op<char16_t>(), "");
309f7b43230SLouis Dionne     static_assert(has_concat_op<const char16_t>(), "");
310f7b43230SLouis Dionne   }
311f7b43230SLouis Dionne   {
312f7b43230SLouis Dionne     using It = const char* const;
313f7b43230SLouis Dionne     static_assert(has_concat<It>(), "");
314f7b43230SLouis Dionne   }
315f7b43230SLouis Dionne   {
316773ae441SChristopher Di Bella     using It = cpp17_input_iterator<const char*>;
317f7b43230SLouis Dionne     static_assert(has_concat<It>(), "");
318f7b43230SLouis Dionne   }
319f7b43230SLouis Dionne   {
320f7b43230SLouis Dionne     struct Traits {
321f7b43230SLouis Dionne       using iterator_category = std::input_iterator_tag;
322f7b43230SLouis Dionne       using value_type = const char;
323f7b43230SLouis Dionne       using pointer = const char*;
324f7b43230SLouis Dionne       using reference = const char&;
325f7b43230SLouis Dionne       using difference_type = std::ptrdiff_t;
326f7b43230SLouis Dionne     };
327773ae441SChristopher Di Bella     using It = cpp17_input_iterator<const char*, Traits>;
328f7b43230SLouis Dionne     static_assert(has_concat<It>(), "");
329f7b43230SLouis Dionne   }
330f7b43230SLouis Dionne   {
3315e97d37bSMark de Wever     using It = cpp17_output_iterator<const char*>;
332f7b43230SLouis Dionne     static_assert(!has_concat<It>(), "");
333f7b43230SLouis Dionne   }
334f7b43230SLouis Dionne   {
335f7b43230SLouis Dionne     static_assert(!has_concat<int>(0), "");
336f7b43230SLouis Dionne     // operator+=(int) is well formed since it converts to operator+=(value_type)
337f7b43230SLouis Dionne     // but concat(int) isn't valid because there is no concat(value_type).
338f7b43230SLouis Dionne     // This should probably be addressed by a LWG issue.
339f7b43230SLouis Dionne     static_assert(has_concat_op<int>(), "");
340f7b43230SLouis Dionne   }
341f7b43230SLouis Dionne   {
342f7b43230SLouis Dionne     static_assert(!has_concat<int*>(), "");
343f7b43230SLouis Dionne   }
344f7b43230SLouis Dionne }
345f7b43230SLouis Dionne 
main(int,char **)346f7b43230SLouis Dionne int main(int, char**)
347f7b43230SLouis Dionne {
348f7b43230SLouis Dionne   using namespace fs;
349f7b43230SLouis Dionne   for (auto const & TC : Cases) {
350f7b43230SLouis Dionne     {
351f7b43230SLouis Dionne       path LHS((const char*)TC.lhs);
352f7b43230SLouis Dionne       path RHS((const char*)TC.rhs);
353f7b43230SLouis Dionne       path& Ref = (LHS += RHS);
354f7b43230SLouis Dionne       assert(LHS == (const char*)TC.expect);
355f7b43230SLouis Dionne       assert(&Ref == &LHS);
356f7b43230SLouis Dionne     }
357f7b43230SLouis Dionne     {
358f7b43230SLouis Dionne       path LHS((const char*)TC.lhs);
359cb2648e6SMartin Storsjö       std::basic_string_view<path::value_type> RHS((const path::value_type*)TC.rhs);
360f7b43230SLouis Dionne       path& Ref = (LHS += RHS);
361f7b43230SLouis Dionne       assert(LHS == (const char*)TC.expect);
362f7b43230SLouis Dionne       assert(&Ref == &LHS);
363f7b43230SLouis Dionne     }
364f7b43230SLouis Dionne     doConcatSourceTest<char>    (TC);
365f4c1258dSLouis Dionne #ifndef TEST_HAS_NO_WIDE_CHARACTERS
366f7b43230SLouis Dionne     doConcatSourceTest<wchar_t> (TC);
367f4c1258dSLouis Dionne #endif
368f7b43230SLouis Dionne     doConcatSourceTest<char16_t>(TC);
369f7b43230SLouis Dionne     doConcatSourceTest<char32_t>(TC);
370f7b43230SLouis Dionne   }
371f7b43230SLouis Dionne   for (auto const & TC : LongLHSCases) {
372f7b43230SLouis Dionne     // Do path test
373f7b43230SLouis Dionne     {
374f7b43230SLouis Dionne       path LHS((const char*)TC.lhs);
375f7b43230SLouis Dionne       path RHS((const char*)TC.rhs);
376f7b43230SLouis Dionne       const char* E = TC.expect;
377f7b43230SLouis Dionne       PathReserve(LHS, StrLen(E) + 5);
378f7b43230SLouis Dionne       {
379afe40b30SMartin Storsjö         LIBCPP_ONLY(DisableAllocationGuard g);
380f7b43230SLouis Dionne         path& Ref = (LHS += RHS);
381f7b43230SLouis Dionne         assert(&Ref == &LHS);
382f7b43230SLouis Dionne       }
383f7b43230SLouis Dionne       assert(LHS == E);
384f7b43230SLouis Dionne     }
385f7b43230SLouis Dionne     {
386f7b43230SLouis Dionne       path LHS((const char*)TC.lhs);
387cb2648e6SMartin Storsjö       std::basic_string_view<path::value_type> RHS((const path::value_type*)TC.rhs);
388f7b43230SLouis Dionne       const char* E = TC.expect;
389f7b43230SLouis Dionne       PathReserve(LHS, StrLen(E) + 5);
390f7b43230SLouis Dionne       {
391afe40b30SMartin Storsjö         LIBCPP_ONLY(DisableAllocationGuard g);
392f7b43230SLouis Dionne         path& Ref = (LHS += RHS);
393f7b43230SLouis Dionne         assert(&Ref == &LHS);
394f7b43230SLouis Dionne       }
395f7b43230SLouis Dionne       assert(LHS == E);
396f7b43230SLouis Dionne     }
397afe40b30SMartin Storsjö     LIBCPP_ONLY(doConcatSourceAllocTest<char>(TC));
398f4c1258dSLouis Dionne #ifndef TEST_HAS_NO_WIDE_CHARACTERS
399afe40b30SMartin Storsjö     LIBCPP_ONLY(doConcatSourceAllocTest<wchar_t>(TC));
400f4c1258dSLouis Dionne #endif
401f7b43230SLouis Dionne   }
402f7b43230SLouis Dionne   for (auto const& TC : CharTestCases) {
403f7b43230SLouis Dionne     doConcatECharTest<char>(TC);
404f4c1258dSLouis Dionne #ifndef TEST_HAS_NO_WIDE_CHARACTERS
405f7b43230SLouis Dionne     doConcatECharTest<wchar_t>(TC);
406f4c1258dSLouis Dionne #endif
407f7b43230SLouis Dionne     doConcatECharTest<char16_t>(TC);
408f7b43230SLouis Dionne     doConcatECharTest<char32_t>(TC);
409f7b43230SLouis Dionne   }
410f7b43230SLouis Dionne   test_sfinae();
411f7b43230SLouis Dionne 
412f7b43230SLouis Dionne   return 0;
413f7b43230SLouis Dionne }
414