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 // 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 Source> 20 // path& operator=(Source const&); 21 // path& operator=(string_type&&); 22 // template <class Source> 23 // path& assign(Source const&); 24 // template <class InputIterator> 25 // path& assign(InputIterator first, InputIterator last); 26 27 28 #include "filesystem_include.h" 29 #include <type_traits> 30 #include <string_view> 31 #include <cassert> 32 33 // On Windows, charset conversions cause allocations in the path class in 34 // cases where no allocations are done on other platforms. 35 36 #include "../../path_helper.h" 37 #include "count_new.h" 38 #include "make_string.h" 39 #include "test_iterators.h" 40 #include "test_macros.h" 41 42 43 template <class CharT> 44 void RunTestCase(MultiStringType const& MS) { 45 using namespace fs; 46 const fs::path::value_type* Expect = MS; 47 const CharT* TestPath = MS; 48 const CharT* TestPathEnd = StrEnd(TestPath); 49 const std::size_t Size = TestPathEnd - TestPath; 50 const std::size_t SSize = StrEnd(Expect) - Expect; 51 assert(Size == SSize); 52 ////////////////////////////////////////////////////////////////////////////// 53 // basic_string<Char, Traits, Alloc> 54 { 55 const std::basic_string<CharT> S(TestPath); 56 path p; PathReserve(p, S.length() + 1); 57 { 58 // string provides a contiguous iterator. No allocation needed. 59 TEST_NOT_WIN32(DisableAllocationGuard g); 60 path& pref = (p = S); 61 assert(&pref == &p); 62 } 63 assert(p.native() == Expect); 64 assert(p.string<CharT>() == TestPath); 65 assert(p.string<CharT>() == S); 66 } 67 { 68 const std::basic_string<CharT> S(TestPath); 69 path p; PathReserve(p, S.length() + 1); 70 { 71 TEST_NOT_WIN32(DisableAllocationGuard g); 72 path& pref = p.assign(S); 73 assert(&pref == &p); 74 } 75 assert(p.native() == Expect); 76 assert(p.string<CharT>() == TestPath); 77 assert(p.string<CharT>() == S); 78 } 79 // basic_string<Char, Traits, Alloc> 80 { 81 const std::basic_string_view<CharT> S(TestPath); 82 path p; PathReserve(p, S.length() + 1); 83 { 84 // string provides a contiguous iterator. No allocation needed. 85 TEST_NOT_WIN32(DisableAllocationGuard g); 86 path& pref = (p = S); 87 assert(&pref == &p); 88 } 89 assert(p.native() == Expect); 90 assert(p.string<CharT>() == TestPath); 91 assert(p.string<CharT>() == S); 92 } 93 { 94 const std::basic_string_view<CharT> S(TestPath); 95 path p; PathReserve(p, S.length() + 1); 96 { 97 TEST_NOT_WIN32(DisableAllocationGuard g); 98 path& pref = p.assign(S); 99 assert(&pref == &p); 100 } 101 assert(p.native() == Expect); 102 assert(p.string<CharT>() == TestPath); 103 assert(p.string<CharT>() == S); 104 } 105 ////////////////////////////////////////////////////////////////////////////// 106 // Char* pointers 107 { 108 path p; PathReserve(p, Size + 1); 109 { 110 // char* pointers are contiguous and can be used with code_cvt directly. 111 // no allocations needed. 112 TEST_NOT_WIN32(DisableAllocationGuard g); 113 path& pref = (p = TestPath); 114 assert(&pref == &p); 115 } 116 assert(p.native() == Expect); 117 assert(p.string<CharT>() == TestPath); 118 } 119 { 120 path p; PathReserve(p, Size + 1); 121 { 122 TEST_NOT_WIN32(DisableAllocationGuard g); 123 path& pref = p.assign(TestPath); 124 assert(&pref == &p); 125 } 126 assert(p.native() == Expect); 127 assert(p.string<CharT>() == TestPath); 128 } 129 { 130 path p; PathReserve(p, Size + 1); 131 { 132 TEST_NOT_WIN32(DisableAllocationGuard g); 133 path& pref = p.assign(TestPath, TestPathEnd); 134 assert(&pref == &p); 135 } 136 assert(p.native() == Expect); 137 assert(p.string<CharT>() == TestPath); 138 } 139 ////////////////////////////////////////////////////////////////////////////// 140 // Iterators 141 { 142 using It = cpp17_input_iterator<const CharT*>; 143 path p; PathReserve(p, Size + 1); 144 It it(TestPath); 145 { 146 // Iterators cannot be used with code_cvt directly. This assignment 147 // may allocate if it's larger than a "short-string". 148 path& pref = (p = it); 149 assert(&pref == &p); 150 } 151 assert(p.native() == Expect); 152 assert(p.string<CharT>() == TestPath); 153 } 154 { 155 using It = cpp17_input_iterator<const CharT*>; 156 path p; PathReserve(p, Size + 1); 157 It it(TestPath); 158 { 159 path& pref = p.assign(it); 160 assert(&pref == &p); 161 } 162 assert(p.native() == Expect); 163 assert(p.string<CharT>() == TestPath); 164 } 165 { 166 using It = cpp17_input_iterator<const CharT*>; 167 path p; PathReserve(p, Size + 1); 168 It it(TestPath); 169 It e(TestPathEnd); 170 { 171 path& pref = p.assign(it, e); 172 assert(&pref == &p); 173 } 174 assert(p.native() == Expect); 175 assert(p.string<CharT>() == TestPath); 176 } 177 } 178 179 template <class It, class = decltype(fs::path{}.assign(std::declval<It>()))> 180 constexpr bool has_assign(int) { return true; } 181 template <class It> 182 constexpr bool has_assign(long) { return false; } 183 template <class It> 184 constexpr bool has_assign() { return has_assign<It>(0); } 185 186 void test_sfinae() { 187 using namespace fs; 188 { 189 using It = const char* const; 190 static_assert(std::is_assignable<path, It>::value, ""); 191 static_assert(has_assign<It>(), ""); 192 } 193 { 194 using It = cpp17_input_iterator<const char*>; 195 static_assert(std::is_assignable<path, It>::value, ""); 196 static_assert(has_assign<It>(), ""); 197 } 198 { 199 struct Traits { 200 using iterator_category = std::input_iterator_tag; 201 using value_type = const char; 202 using pointer = const char*; 203 using reference = const char&; 204 using difference_type = std::ptrdiff_t; 205 }; 206 using It = cpp17_input_iterator<const char*, Traits>; 207 static_assert(std::is_assignable<path, It>::value, ""); 208 static_assert(has_assign<It>(), ""); 209 } 210 { 211 using It = cpp17_output_iterator<const char*>; 212 static_assert(!std::is_assignable<path, It>::value, ""); 213 static_assert(!has_assign<It>(), ""); 214 215 } 216 { 217 static_assert(!std::is_assignable<path, int*>::value, ""); 218 static_assert(!has_assign<int*>(), ""); 219 } 220 } 221 222 void RunStringMoveTest(const fs::path::value_type* Expect) { 223 using namespace fs; 224 fs::path::string_type ss(Expect); 225 path p; 226 { 227 DisableAllocationGuard g; ((void)g); 228 path& pr = (p = std::move(ss)); 229 assert(&pr == &p); 230 } 231 assert(p == Expect); 232 { 233 // Signature test 234 LIBCPP_ONLY(ASSERT_NOEXCEPT(p = std::move(ss))); 235 } 236 } 237 238 int main(int, char**) { 239 for (auto const& MS : PathList) { 240 RunTestCase<char>(MS); 241 #ifndef TEST_HAS_NO_WIDE_CHARACTERS 242 RunTestCase<wchar_t>(MS); 243 #endif 244 RunTestCase<char16_t>(MS); 245 RunTestCase<char32_t>(MS); 246 RunStringMoveTest(MS); 247 } 248 test_sfinae(); 249 250 return 0; 251 } 252