1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // UNSUPPORTED: c++03
10 
11 // These tests require locale for non-char paths
12 // UNSUPPORTED: libcpp-has-no-localization
13 
14 // <filesystem>
15 
16 // class path
17 
18 // template <class ECharT, class Traits = char_traits<ECharT>,
19 //           class Allocator = allocator<ECharT>>
20 // basic_string<ECharT, Traits, Allocator>
21 // string(const Allocator& a = Allocator()) const;
22 
23 #include "filesystem_include.h"
24 #include <type_traits>
25 #include <cassert>
26 
27 #include "test_macros.h"
28 #include "test_iterators.h"
29 #include "count_new.h"
30 #include "min_allocator.h"
31 #include "filesystem_test_helper.h"
32 
33 
34 // the SSO is always triggered for strings of size 2.
35 MultiStringType shortString = MKSTR("a");
36 MultiStringType longString = MKSTR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/123456789/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
37 
38 template <class CharT>
doShortStringTest(MultiStringType const & MS)39 void doShortStringTest(MultiStringType const& MS) {
40   using namespace fs;
41   using Ptr = CharT const*;
42   using Str = std::basic_string<CharT>;
43   using Alloc = std::allocator<CharT>;
44   Ptr value = MS;
45   const path p((const char*)MS);
46 #ifdef _WIN32
47   // On Windows, charset conversions cause allocations outside of the
48   // provided allocator, but accessing the native type should work without
49   // extra allocations.
50   bool DisableAllocations = std::is_same<CharT, path::value_type>::value;
51 #else
52   // On other platforms, these methods only use the provided allocator, and
53   // no extra allocations should be done.
54   bool DisableAllocations = true;
55 #endif
56   {
57       DisableAllocationGuard g(DisableAllocations);
58       Str s = p.string<CharT>();
59       assert(s == value);
60       Str s2 = p.string<CharT>(Alloc{});
61       assert(s2 == value);
62   }
63   using MAlloc = malloc_allocator<CharT>;
64   MAlloc::reset();
65   {
66       using Traits = std::char_traits<CharT>;
67       using AStr = std::basic_string<CharT, Traits, MAlloc>;
68       DisableAllocationGuard g(DisableAllocations);
69       AStr s = p.string<CharT, Traits, MAlloc>();
70       assert(s == value);
71       assert(MAlloc::alloc_count == 0);
72       assert(MAlloc::outstanding_alloc() == 0);
73   }
74   MAlloc::reset();
75   { // Other allocator - provided copy
76       using Traits = std::char_traits<CharT>;
77       using AStr = std::basic_string<CharT, Traits, MAlloc>;
78       DisableAllocationGuard g(DisableAllocations);
79       MAlloc a;
80       // don't allow another allocator to be default constructed.
81       MAlloc::disable_default_constructor = true;
82       AStr s = p.string<CharT, Traits, MAlloc>(a);
83       assert(s == value);
84       assert(MAlloc::alloc_count == 0);
85       assert(MAlloc::outstanding_alloc() == 0);
86   }
87   MAlloc::reset();
88 }
89 
90 template <class CharT>
doLongStringTest(MultiStringType const & MS)91 void doLongStringTest(MultiStringType const& MS) {
92   using namespace fs;
93   using Ptr = CharT const*;
94   using Str = std::basic_string<CharT>;
95   Ptr value = MS;
96   const path p((const char*)MS);
97   { // Default allocator
98       using Alloc = std::allocator<CharT>;
99       Str s = p.string<CharT>();
100       assert(s == value);
101       Str s2 = p.string<CharT>(Alloc{});
102       assert(s2 == value);
103   }
104   using MAlloc = malloc_allocator<CharT>;
105   MAlloc::reset();
106 #ifdef _WIN32
107   // On Windows, charset conversions cause allocations outside of the
108   // provided allocator, but accessing the native type should work without
109   // extra allocations.
110   bool DisableAllocations = std::is_same<CharT, path::value_type>::value;
111 #else
112   // On other platforms, these methods only use the provided allocator, and
113   // no extra allocations should be done.
114   bool DisableAllocations = true;
115 #endif
116 
117   { // Other allocator - default construct
118       using Traits = std::char_traits<CharT>;
119       using AStr = std::basic_string<CharT, Traits, MAlloc>;
120       DisableAllocationGuard g(DisableAllocations);
121       AStr s = p.string<CharT, Traits, MAlloc>();
122       assert(s == value);
123       assert(MAlloc::alloc_count > 0);
124       assert(MAlloc::outstanding_alloc() == 1);
125   }
126   MAlloc::reset();
127   { // Other allocator - provided copy
128       using Traits = std::char_traits<CharT>;
129       using AStr = std::basic_string<CharT, Traits, MAlloc>;
130       DisableAllocationGuard g(DisableAllocations);
131       MAlloc a;
132       // don't allow another allocator to be default constructed.
133       MAlloc::disable_default_constructor = true;
134       AStr s = p.string<CharT, Traits, MAlloc>(a);
135       assert(s == value);
136       assert(MAlloc::alloc_count > 0);
137       assert(MAlloc::outstanding_alloc() == 1);
138   }
139   MAlloc::reset();
140   /////////////////////////////////////////////////////////////////////////////
141 }
142 
main(int,char **)143 int main(int, char**)
144 {
145   using namespace fs;
146   {
147     auto const& S = shortString;
148     doShortStringTest<char>(S);
149 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
150     doShortStringTest<wchar_t>(S);
151 #endif
152     doShortStringTest<char16_t>(S);
153     doShortStringTest<char32_t>(S);
154 #if TEST_STD_VER > 17 && defined(__cpp_lib_char8_t)
155     doShortStringTest<char8_t>(S);
156 #endif
157   }
158   {
159     auto const& S = longString;
160     doLongStringTest<char>(S);
161 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
162     doLongStringTest<wchar_t>(S);
163 #endif
164     doLongStringTest<char16_t>(S);
165     doLongStringTest<char32_t>(S);
166 #if TEST_STD_VER > 17 && defined(__cpp_lib_char8_t)
167     doLongStringTest<char8_t>(S);
168 #endif
169   }
170 
171   return 0;
172 }
173