xref: /llvm-project/libcxx/test/std/input.output/filesystems/class.path/path.member/path.append.pass.cpp (revision 49173ca4db21e4d1576c2440b79ebff48c6c4156)
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 
931cbe0f2SLouis Dionne // UNSUPPORTED: c++03
10f7b43230SLouis Dionne 
1188ffc727SLouis Dionne // These tests require locale for non-char paths
1288ffc727SLouis Dionne // UNSUPPORTED: libcpp-has-no-localization
1388ffc727SLouis Dionne 
14f7b43230SLouis Dionne // <filesystem>
15f7b43230SLouis Dionne 
16f7b43230SLouis Dionne // class path
17f7b43230SLouis Dionne 
18f7b43230SLouis Dionne // path& operator/=(path const&)
19f7b43230SLouis Dionne // template <class Source>
20f7b43230SLouis Dionne //      path& operator/=(Source const&);
21f7b43230SLouis Dionne // template <class Source>
22f7b43230SLouis Dionne //      path& append(Source const&);
23f7b43230SLouis Dionne // template <class InputIterator>
24f7b43230SLouis Dionne //      path& append(InputIterator first, InputIterator last);
25f7b43230SLouis Dionne 
26f7b43230SLouis Dionne 
27cc89063bSNico Weber #include "filesystem_include.h"
28f7b43230SLouis Dionne #include <type_traits>
29f7b43230SLouis Dionne #include <string_view>
30f7b43230SLouis Dionne #include <cassert>
31f7b43230SLouis Dionne 
32f7b43230SLouis Dionne #include "test_macros.h"
33f7b43230SLouis Dionne #include "test_iterators.h"
34cc89063bSNico Weber #include "count_new.h"
35cc89063bSNico Weber #include "filesystem_test_helper.h"
36f7b43230SLouis Dionne 
37f7b43230SLouis Dionne 
38f7b43230SLouis Dionne struct AppendOperatorTestcase {
39f7b43230SLouis Dionne   MultiStringType lhs;
40f7b43230SLouis Dionne   MultiStringType rhs;
4153d7c636SMartin Storsjö   MultiStringType expect_posix;
4253d7c636SMartin Storsjö   MultiStringType expect_windows;
4353d7c636SMartin Storsjö 
4453d7c636SMartin Storsjö   MultiStringType const& expected_result() const {
4553d7c636SMartin Storsjö #ifdef _WIN32
4653d7c636SMartin Storsjö     return expect_windows;
4753d7c636SMartin Storsjö #else
4853d7c636SMartin Storsjö     return expect_posix;
4953d7c636SMartin Storsjö #endif
5053d7c636SMartin Storsjö   }
51f7b43230SLouis Dionne };
52f7b43230SLouis Dionne 
53f7b43230SLouis Dionne #define S(Str) MKSTR(Str)
54f7b43230SLouis Dionne const AppendOperatorTestcase Cases[] =
55f7b43230SLouis Dionne     {
5653d7c636SMartin Storsjö         {S(""),        S(""),         S(""),              S("")}
5753d7c636SMartin Storsjö       , {S("p1"),      S("p2"),       S("p1/p2"),         S("p1\\p2")}
5853d7c636SMartin Storsjö       , {S("p1/"),     S("p2"),       S("p1/p2"),         S("p1/p2")}
5953d7c636SMartin Storsjö       , {S("p1"),      S("/p2"),      S("/p2"),           S("/p2")}
6053d7c636SMartin Storsjö       , {S("p1/"),     S("/p2"),      S("/p2"),           S("/p2")}
6153d7c636SMartin Storsjö       , {S("p1"),      S("\\p2"),     S("p1/\\p2"),       S("\\p2")}
6253d7c636SMartin Storsjö       , {S("p1\\"),    S("p2"),       S("p1\\/p2"),       S("p1\\p2")}
6353d7c636SMartin Storsjö       , {S("p1\\"),    S("\\p2"),     S("p1\\/\\p2"),     S("\\p2")}
6453d7c636SMartin Storsjö       , {S(""),        S("p2"),       S("p2"),            S("p2")}
6553d7c636SMartin Storsjö       , {S("/p1"),     S("p2"),       S("/p1/p2"),        S("/p1\\p2")}
6653d7c636SMartin Storsjö       , {S("/p1"),     S("/p2"),      S("/p2"),           S("/p2")}
6753d7c636SMartin Storsjö       , {S("/p1/p3"),  S("p2"),       S("/p1/p3/p2"),     S("/p1/p3\\p2")}
6853d7c636SMartin Storsjö       , {S("/p1/p3/"), S("p2"),       S("/p1/p3/p2"),     S("/p1/p3/p2")}
6953d7c636SMartin Storsjö       , {S("/p1/"),    S("p2"),       S("/p1/p2"),        S("/p1/p2")}
7053d7c636SMartin Storsjö       , {S("/p1/p3/"), S("/p2/p4"),   S("/p2/p4"),        S("/p2/p4")}
7153d7c636SMartin Storsjö       , {S("/"),       S(""),         S("/"),             S("/")}
7253d7c636SMartin Storsjö       , {S("/p1"),     S("/p2/"),     S("/p2/"),          S("/p2/")}
7353d7c636SMartin Storsjö       , {S("p1"),      S(""),         S("p1/"),           S("p1\\")}
7453d7c636SMartin Storsjö       , {S("p1/"),     S(""),         S("p1/"),           S("p1/")}
7578d693faSMartin Storsjö 
7653d7c636SMartin Storsjö       , {S("//host"),  S("foo"),      S("//host/foo"),    S("//host\\foo")}
7753d7c636SMartin Storsjö       , {S("//host/"), S("foo"),      S("//host/foo"),    S("//host/foo")}
7853d7c636SMartin Storsjö       , {S("//host"),  S(""),         S("//host/"),       S("//host\\")}
7978d693faSMartin Storsjö 
8053d7c636SMartin Storsjö       , {S("foo"),     S("C:/bar"),   S("foo/C:/bar"),    S("C:/bar")}
8153d7c636SMartin Storsjö       , {S("foo"),     S("C:"),       S("foo/C:"),        S("C:")}
8278d693faSMartin Storsjö 
8353d7c636SMartin Storsjö       , {S("C:"),      S(""),         S("C:/"),           S("C:")}
8453d7c636SMartin Storsjö       , {S("C:foo"),   S("/bar"),     S("/bar"),          S("C:/bar")}
8553d7c636SMartin Storsjö       , {S("C:foo"),   S("bar"),      S("C:foo/bar"),     S("C:foo\\bar")}
8653d7c636SMartin Storsjö       , {S("C:/foo"),  S("bar"),      S("C:/foo/bar"),    S("C:/foo\\bar")}
8753d7c636SMartin Storsjö       , {S("C:/foo"),  S("/bar"),     S("/bar"),          S("C:/bar")}
8878d693faSMartin Storsjö 
8953d7c636SMartin Storsjö       , {S("C:foo"),   S("C:/bar"),   S("C:foo/C:/bar"),  S("C:/bar")}
9053d7c636SMartin Storsjö       , {S("C:foo"),   S("C:bar"),    S("C:foo/C:bar"),   S("C:foo\\bar")}
9153d7c636SMartin Storsjö       , {S("C:/foo"),  S("C:/bar"),   S("C:/foo/C:/bar"), S("C:/bar")}
9253d7c636SMartin Storsjö       , {S("C:/foo"),  S("C:bar"),    S("C:/foo/C:bar"),  S("C:/foo\\bar")}
9378d693faSMartin Storsjö 
9453d7c636SMartin Storsjö       , {S("C:foo"),   S("c:/bar"),   S("C:foo/c:/bar"),  S("c:/bar")}
9553d7c636SMartin Storsjö       , {S("C:foo"),   S("c:bar"),    S("C:foo/c:bar"),   S("c:bar")}
9653d7c636SMartin Storsjö       , {S("C:/foo"),  S("c:/bar"),   S("C:/foo/c:/bar"), S("c:/bar")}
9753d7c636SMartin Storsjö       , {S("C:/foo"),  S("c:bar"),    S("C:/foo/c:bar"),  S("c:bar")}
9878d693faSMartin Storsjö 
9953d7c636SMartin Storsjö       , {S("C:/foo"),  S("D:bar"),    S("C:/foo/D:bar"),  S("D:bar")}
100f7b43230SLouis Dionne     };
101f7b43230SLouis Dionne 
102f7b43230SLouis Dionne 
103f7b43230SLouis Dionne const AppendOperatorTestcase LongLHSCases[] =
104f7b43230SLouis Dionne     {
10553d7c636SMartin Storsjö         {S("p1"),   S("p2"),    S("p1/p2"),  S("p1\\p2")}
10653d7c636SMartin Storsjö       , {S("p1/"),  S("p2"),    S("p1/p2"),  S("p1/p2")}
10753d7c636SMartin Storsjö       , {S("p1"),   S("/p2"),   S("/p2"),    S("/p2")}
10853d7c636SMartin Storsjö       , {S("/p1"),  S("p2"),    S("/p1/p2"), S("/p1\\p2")}
109f7b43230SLouis Dionne     };
110f7b43230SLouis Dionne #undef S
111f7b43230SLouis Dionne 
112f7b43230SLouis Dionne 
113f7b43230SLouis Dionne // The append operator may need to allocate a temporary buffer before a code_cvt
114f7b43230SLouis Dionne // conversion. Test if this allocation occurs by:
115f7b43230SLouis Dionne //   1. Create a path, `LHS`, and reserve enough space to append `RHS`.
116f7b43230SLouis Dionne //      This prevents `LHS` from allocating during the actual appending.
117f7b43230SLouis Dionne //   2. Create a `Source` object `RHS`, which represents a "large" string.
118f7b43230SLouis Dionne //      (The string must not trigger the SSO)
119f7b43230SLouis Dionne //   3. Append `RHS` to `LHS` and check for the expected allocation behavior.
120f7b43230SLouis Dionne template <class CharT>
121f7b43230SLouis Dionne void doAppendSourceAllocTest(AppendOperatorTestcase const& TC)
122f7b43230SLouis Dionne {
123f7b43230SLouis Dionne   using namespace fs;
124f7b43230SLouis Dionne   using Ptr = CharT const*;
125f7b43230SLouis Dionne   using Str = std::basic_string<CharT>;
126f7b43230SLouis Dionne   using StrView = std::basic_string_view<CharT>;
127f7b43230SLouis Dionne   using InputIter = input_iterator<Ptr>;
128f7b43230SLouis Dionne 
129f7b43230SLouis Dionne   const Ptr L = TC.lhs;
130f7b43230SLouis Dionne   Str RShort = (Ptr)TC.rhs;
13153d7c636SMartin Storsjö   Str EShort = (Ptr)TC.expected_result();
132f7b43230SLouis Dionne   assert(RShort.size() >= 2);
133f7b43230SLouis Dionne   CharT c = RShort.back();
134f7b43230SLouis Dionne   RShort.append(100, c);
135f7b43230SLouis Dionne   EShort.append(100, c);
136f7b43230SLouis Dionne   const Ptr R = RShort.data();
137f7b43230SLouis Dionne   const Str& E = EShort;
138f7b43230SLouis Dionne   std::size_t ReserveSize = E.size() + 3;
139f7b43230SLouis Dionne   // basic_string
140f7b43230SLouis Dionne   {
141f7b43230SLouis Dionne     path LHS(L); PathReserve(LHS, ReserveSize);
142f7b43230SLouis Dionne     Str  RHS(R);
143f7b43230SLouis Dionne     {
144f7b43230SLouis Dionne       DisableAllocationGuard g;
145f7b43230SLouis Dionne       LHS /= RHS;
146f7b43230SLouis Dionne     }
147e557b6a6SLouis Dionne     assert(PathEq(LHS, E));
148f7b43230SLouis Dionne   }
149f7b43230SLouis Dionne   // basic_string_view
150f7b43230SLouis Dionne   {
151f7b43230SLouis Dionne     path LHS(L); PathReserve(LHS, ReserveSize);
152f7b43230SLouis Dionne     StrView  RHS(R);
153f7b43230SLouis Dionne     {
154f7b43230SLouis Dionne       DisableAllocationGuard g;
155f7b43230SLouis Dionne       LHS /= RHS;
156f7b43230SLouis Dionne     }
157f7b43230SLouis Dionne     assert(PathEq(LHS, E));
158f7b43230SLouis Dionne   }
159f7b43230SLouis Dionne   // CharT*
160f7b43230SLouis Dionne   {
161f7b43230SLouis Dionne     path LHS(L); PathReserve(LHS, ReserveSize);
162f7b43230SLouis Dionne     Ptr RHS(R);
163f7b43230SLouis Dionne     {
164f7b43230SLouis Dionne       DisableAllocationGuard g;
165f7b43230SLouis Dionne       LHS /= RHS;
166f7b43230SLouis Dionne     }
167f7b43230SLouis Dionne     assert(PathEq(LHS, E));
168f7b43230SLouis Dionne   }
169f7b43230SLouis Dionne   {
170f7b43230SLouis Dionne     path LHS(L); PathReserve(LHS, ReserveSize);
171f7b43230SLouis Dionne     Ptr RHS(R);
172f7b43230SLouis Dionne     {
173f7b43230SLouis Dionne       DisableAllocationGuard g;
174f7b43230SLouis Dionne       LHS.append(RHS, StrEnd(RHS));
175f7b43230SLouis Dionne     }
176f7b43230SLouis Dionne     assert(PathEq(LHS, E));
177f7b43230SLouis Dionne   }
178*49173ca4SMartin Storsjö   {
179*49173ca4SMartin Storsjö     path LHS(L); PathReserve(LHS, ReserveSize);
180*49173ca4SMartin Storsjö     path RHS(R);
181*49173ca4SMartin Storsjö     {
182*49173ca4SMartin Storsjö       DisableAllocationGuard g;
183*49173ca4SMartin Storsjö       LHS /= RHS;
184*49173ca4SMartin Storsjö     }
185*49173ca4SMartin Storsjö     assert(PathEq(LHS, E));
186*49173ca4SMartin Storsjö   }
187f7b43230SLouis Dionne   // input iterator - For non-native char types, appends needs to copy the
188f7b43230SLouis Dionne   // iterator range into a contiguous block of memory before it can perform the
189f7b43230SLouis Dionne   // code_cvt conversions.
190f7b43230SLouis Dionne   // For "char" no allocations will be performed because no conversion is
191f7b43230SLouis Dionne   // required.
192f7b43230SLouis Dionne   bool DisableAllocations = std::is_same<CharT, char>::value;
193f7b43230SLouis Dionne   {
194f7b43230SLouis Dionne     path LHS(L); PathReserve(LHS, ReserveSize);
195f7b43230SLouis Dionne     InputIter RHS(R);
196f7b43230SLouis Dionne     {
197f7b43230SLouis Dionne       RequireAllocationGuard  g; // requires 1 or more allocations occur by default
198f7b43230SLouis Dionne       if (DisableAllocations) g.requireExactly(0);
199f7b43230SLouis Dionne       LHS /= RHS;
200f7b43230SLouis Dionne     }
201f7b43230SLouis Dionne     assert(PathEq(LHS, E));
202f7b43230SLouis Dionne   }
203f7b43230SLouis Dionne   {
204f7b43230SLouis Dionne     path LHS(L); PathReserve(LHS, ReserveSize);
205f7b43230SLouis Dionne     InputIter RHS(R);
206f7b43230SLouis Dionne     InputIter REnd(StrEnd(R));
207f7b43230SLouis Dionne     {
208f7b43230SLouis Dionne       RequireAllocationGuard g;
209f7b43230SLouis Dionne       if (DisableAllocations) g.requireExactly(0);
210f7b43230SLouis Dionne       LHS.append(RHS, REnd);
211f7b43230SLouis Dionne     }
212f7b43230SLouis Dionne     assert(PathEq(LHS, E));
213f7b43230SLouis Dionne   }
214f7b43230SLouis Dionne }
215f7b43230SLouis Dionne 
216f7b43230SLouis Dionne template <class CharT>
217f7b43230SLouis Dionne void doAppendSourceTest(AppendOperatorTestcase const& TC)
218f7b43230SLouis Dionne {
219f7b43230SLouis Dionne   using namespace fs;
220f7b43230SLouis Dionne   using Ptr = CharT const*;
221f7b43230SLouis Dionne   using Str = std::basic_string<CharT>;
222f7b43230SLouis Dionne   using StrView = std::basic_string_view<CharT>;
223f7b43230SLouis Dionne   using InputIter = input_iterator<Ptr>;
224f7b43230SLouis Dionne   const Ptr L = TC.lhs;
225f7b43230SLouis Dionne   const Ptr R = TC.rhs;
22653d7c636SMartin Storsjö   const Ptr E = TC.expected_result();
227f7b43230SLouis Dionne   // basic_string
228f7b43230SLouis Dionne   {
229f7b43230SLouis Dionne     path Result(L);
230f7b43230SLouis Dionne     Str RHS(R);
231f7b43230SLouis Dionne     path& Ref = (Result /= RHS);
232e557b6a6SLouis Dionne     assert(Result == E);
233f7b43230SLouis Dionne     assert(&Ref == &Result);
234f7b43230SLouis Dionne   }
235f7b43230SLouis Dionne   {
236f7b43230SLouis Dionne     path LHS(L);
237f7b43230SLouis Dionne     Str RHS(R);
238f7b43230SLouis Dionne     path& Ref = LHS.append(RHS);
239f7b43230SLouis Dionne     assert(PathEq(LHS, E));
240f7b43230SLouis Dionne     assert(&Ref == &LHS);
241f7b43230SLouis Dionne   }
242f7b43230SLouis Dionne   // basic_string_view
243f7b43230SLouis Dionne   {
244f7b43230SLouis Dionne     path LHS(L);
245f7b43230SLouis Dionne     StrView RHS(R);
246f7b43230SLouis Dionne     path& Ref = (LHS /= RHS);
247f7b43230SLouis Dionne     assert(PathEq(LHS, E));
248f7b43230SLouis Dionne     assert(&Ref == &LHS);
249f7b43230SLouis Dionne   }
250f7b43230SLouis Dionne   {
251f7b43230SLouis Dionne     path LHS(L);
252f7b43230SLouis Dionne     StrView RHS(R);
253f7b43230SLouis Dionne     path& Ref = LHS.append(RHS);
254f7b43230SLouis Dionne     assert(PathEq(LHS, E));
255f7b43230SLouis Dionne     assert(&Ref == &LHS);
256f7b43230SLouis Dionne   }
257f7b43230SLouis Dionne   // Char*
258f7b43230SLouis Dionne   {
259f7b43230SLouis Dionne     path LHS(L);
260f7b43230SLouis Dionne     Str RHS(R);
261f7b43230SLouis Dionne     path& Ref = (LHS /= RHS);
262f7b43230SLouis Dionne     assert(PathEq(LHS, E));
263f7b43230SLouis Dionne     assert(&Ref == &LHS);
264f7b43230SLouis Dionne   }
265f7b43230SLouis Dionne   {
266f7b43230SLouis Dionne     path LHS(L);
267f7b43230SLouis Dionne     Ptr RHS(R);
268f7b43230SLouis Dionne     path& Ref = LHS.append(RHS);
269f7b43230SLouis Dionne     assert(PathEq(LHS, E));
270f7b43230SLouis Dionne     assert(&Ref == &LHS);
271f7b43230SLouis Dionne   }
272f7b43230SLouis Dionne   {
273f7b43230SLouis Dionne     path LHS(L);
274f7b43230SLouis Dionne     Ptr RHS(R);
275f7b43230SLouis Dionne     path& Ref = LHS.append(RHS, StrEnd(RHS));
276e557b6a6SLouis Dionne     assert(PathEq(LHS, E));
277f7b43230SLouis Dionne     assert(&Ref == &LHS);
278f7b43230SLouis Dionne   }
279f7b43230SLouis Dionne   // iterators
280f7b43230SLouis Dionne   {
281f7b43230SLouis Dionne     path LHS(L);
282f7b43230SLouis Dionne     InputIter RHS(R);
283f7b43230SLouis Dionne     path& Ref = (LHS /= RHS);
284f7b43230SLouis Dionne     assert(PathEq(LHS, E));
285f7b43230SLouis Dionne     assert(&Ref == &LHS);
286f7b43230SLouis Dionne   }
287f7b43230SLouis Dionne   {
288f7b43230SLouis Dionne     path LHS(L); InputIter RHS(R);
289f7b43230SLouis Dionne     path& Ref = LHS.append(RHS);
290f7b43230SLouis Dionne     assert(PathEq(LHS, E));
291f7b43230SLouis Dionne     assert(&Ref == &LHS);
292f7b43230SLouis Dionne   }
293f7b43230SLouis Dionne   {
294f7b43230SLouis Dionne     path LHS(L);
295f7b43230SLouis Dionne     InputIter RHS(R);
296f7b43230SLouis Dionne     InputIter REnd(StrEnd(R));
297f7b43230SLouis Dionne     path& Ref = LHS.append(RHS, REnd);
298f7b43230SLouis Dionne     assert(PathEq(LHS, E));
299f7b43230SLouis Dionne     assert(&Ref == &LHS);
300f7b43230SLouis Dionne   }
301f7b43230SLouis Dionne }
302f7b43230SLouis Dionne 
303f7b43230SLouis Dionne 
304f7b43230SLouis Dionne 
305f7b43230SLouis Dionne template <class It, class = decltype(fs::path{}.append(std::declval<It>()))>
306f7b43230SLouis Dionne constexpr bool has_append(int) { return true; }
307f7b43230SLouis Dionne template <class It>
308f7b43230SLouis Dionne constexpr bool has_append(long) { return false; }
309f7b43230SLouis Dionne 
310f7b43230SLouis Dionne template <class It, class = decltype(fs::path{}.operator/=(std::declval<It>()))>
311f7b43230SLouis Dionne constexpr bool has_append_op(int) { return true; }
312f7b43230SLouis Dionne template <class It>
313f7b43230SLouis Dionne constexpr bool has_append_op(long) { return false; }
314f7b43230SLouis Dionne 
315f7b43230SLouis Dionne template <class It>
316f7b43230SLouis Dionne constexpr bool has_append() {
317f7b43230SLouis Dionne   static_assert(has_append<It>(0) == has_append_op<It>(0), "must be same");
318f7b43230SLouis Dionne   return has_append<It>(0) && has_append_op<It>(0);
319f7b43230SLouis Dionne }
320f7b43230SLouis Dionne 
321f7b43230SLouis Dionne void test_sfinae()
322f7b43230SLouis Dionne {
323f7b43230SLouis Dionne   using namespace fs;
324f7b43230SLouis Dionne   {
325f7b43230SLouis Dionne     using It = const char* const;
326f7b43230SLouis Dionne     static_assert(has_append<It>(), "");
327f7b43230SLouis Dionne   }
328f7b43230SLouis Dionne   {
329f7b43230SLouis Dionne     using It = input_iterator<const char*>;
330f7b43230SLouis Dionne     static_assert(has_append<It>(), "");
331f7b43230SLouis Dionne   }
332f7b43230SLouis Dionne   {
333f7b43230SLouis Dionne     struct Traits {
334f7b43230SLouis Dionne       using iterator_category = std::input_iterator_tag;
335f7b43230SLouis Dionne       using value_type = const char;
336f7b43230SLouis Dionne       using pointer = const char*;
337f7b43230SLouis Dionne       using reference = const char&;
338f7b43230SLouis Dionne       using difference_type = std::ptrdiff_t;
339f7b43230SLouis Dionne     };
340f7b43230SLouis Dionne     using It = input_iterator<const char*, Traits>;
341f7b43230SLouis Dionne     static_assert(has_append<It>(), "");
342f7b43230SLouis Dionne   }
343f7b43230SLouis Dionne   {
344f7b43230SLouis Dionne     using It = output_iterator<const char*>;
345f7b43230SLouis Dionne     static_assert(!has_append<It>(), "");
346f7b43230SLouis Dionne 
347f7b43230SLouis Dionne   }
348f7b43230SLouis Dionne   {
349f7b43230SLouis Dionne     static_assert(!has_append<int*>(), "");
350f7b43230SLouis Dionne   }
351f7b43230SLouis Dionne   {
352f7b43230SLouis Dionne     static_assert(!has_append<char>(), "");
353f7b43230SLouis Dionne     static_assert(!has_append<const char>(), "");
354f7b43230SLouis Dionne   }
355f7b43230SLouis Dionne }
356f7b43230SLouis Dionne 
357f7b43230SLouis Dionne int main(int, char**)
358f7b43230SLouis Dionne {
359f7b43230SLouis Dionne   using namespace fs;
360f7b43230SLouis Dionne   for (auto const & TC : Cases) {
361f7b43230SLouis Dionne     {
362f7b43230SLouis Dionne       const char* LHS_In = TC.lhs;
363f7b43230SLouis Dionne       const char* RHS_In = TC.rhs;
364f7b43230SLouis Dionne       path LHS(LHS_In);
365f7b43230SLouis Dionne       path RHS(RHS_In);
366f7b43230SLouis Dionne       path& Res = (LHS /= RHS);
36753d7c636SMartin Storsjö       assert(PathEq(Res, (const char*)TC.expected_result()));
368f7b43230SLouis Dionne       assert(&Res == &LHS);
369f7b43230SLouis Dionne     }
370f7b43230SLouis Dionne     doAppendSourceTest<char>    (TC);
371f7b43230SLouis Dionne     doAppendSourceTest<wchar_t> (TC);
372f7b43230SLouis Dionne     doAppendSourceTest<char16_t>(TC);
373f7b43230SLouis Dionne     doAppendSourceTest<char32_t>(TC);
374f7b43230SLouis Dionne   }
375f7b43230SLouis Dionne   for (auto const & TC : LongLHSCases) {
37622e5ee0eSMartin Storsjö     (void)TC;
377afe40b30SMartin Storsjö     LIBCPP_ONLY(doAppendSourceAllocTest<char>(TC));
378afe40b30SMartin Storsjö     LIBCPP_ONLY(doAppendSourceAllocTest<wchar_t>(TC));
379f7b43230SLouis Dionne   }
380f7b43230SLouis Dionne   test_sfinae();
381f7b43230SLouis Dionne 
382f7b43230SLouis Dionne   return 0;
383f7b43230SLouis Dionne }
384