250 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++1410 11// These tests require locale for non-char paths12// UNSUPPORTED: no-localization13 14// <filesystem>15 16// class path17 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#include <filesystem>27#include <type_traits>28#include <string_view>29#include <cassert>30 31// On Windows, charset conversions cause allocations in the path class in32// cases where no allocations are done on other platforms.33 34#include "../../path_helper.h"35#include "count_new.h"36#include "make_string.h"37#include "test_iterators.h"38#include "test_macros.h"39namespace fs = std::filesystem;40 41template <class CharT>42void 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* pointers105 {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 // Iterators139 {140 using It = cpp17_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 assignment145 // 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 = cpp17_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 = cpp17_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 177template <class It, class = decltype(fs::path{}.assign(std::declval<It>()))>178constexpr bool has_assign(int) { return true; }179template <class It>180constexpr bool has_assign(long) { return false; }181template <class It>182constexpr bool has_assign() { return has_assign<It>(0); }183 184void 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 = cpp17_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 = cpp17_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 = cpp17_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 220void 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 test232 LIBCPP_ASSERT_NOEXCEPT(p = std::move(ss));233 }234}235 236int main(int, char**) {237 for (auto const& MS : PathList) {238 RunTestCase<char>(MS);239#ifndef TEST_HAS_NO_WIDE_CHARACTERS240 RunTestCase<wchar_t>(MS);241#endif242 RunTestCase<char16_t>(MS);243 RunTestCase<char32_t>(MS);244 RunStringMoveTest(MS);245 }246 test_sfinae();247 248 return 0;249}250