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