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