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