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: no-filesystem 11 // UNSUPPORTED: availability-filesystem-missing 12 13 // The string reported on errors changed, which makes those tests fail when run 14 // against already-released libc++'s. 15 // XFAIL: stdlib=system && target={{.+}}-apple-macosx{{10.15|11.0}} 16 17 // Starting in Android N (API 24), SELinux policy prevents the shell user from 18 // creating a FIFO file. 19 // XFAIL: LIBCXX-ANDROID-FIXME && !android-device-api={{21|22|23}} 20 21 // <filesystem> 22 23 // bool copy_file(const path& from, const path& to); 24 // bool copy_file(const path& from, const path& to, error_code& ec) noexcept; 25 // bool copy_file(const path& from, const path& to, copy_options options); 26 // bool copy_file(const path& from, const path& to, copy_options options, error_code& ec) noexcept; 27 28 #include <filesystem> 29 #include <type_traits> 30 #include <chrono> 31 #include <cassert> 32 33 #include "assert_macros.h" 34 #include "test_macros.h" 35 #include "filesystem_test_helper.h" 36 namespace fs = std::filesystem; 37 using namespace fs; 38 39 using CO = fs::copy_options; 40 41 static void test_signatures() { 42 const path p; 43 ((void)p); 44 const copy_options opts{}; 45 ((void)opts); 46 std::error_code ec; 47 ((void)ec); 48 ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p)), bool); 49 ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p, opts)), bool); 50 ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p, ec)), bool); 51 ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p, opts, ec)), bool); 52 ASSERT_NOT_NOEXCEPT(fs::copy_file(p, p)); 53 ASSERT_NOT_NOEXCEPT(fs::copy_file(p, p, opts)); 54 ASSERT_NOT_NOEXCEPT(fs::copy_file(p, p, ec)); 55 ASSERT_NOT_NOEXCEPT(fs::copy_file(p, p, opts, ec)); 56 } 57 58 static void test_error_reporting() { 59 60 scoped_test_env env; 61 const path file = env.create_file("file1", 42); 62 const path file2 = env.create_file("file2", 55); 63 64 { // exists(to) && equivalent(to, from) 65 std::error_code ec; 66 assert(fs::copy_file(file, file, copy_options::overwrite_existing, 67 ec) == false); 68 assert(ErrorIs(ec, std::errc::file_exists)); 69 ExceptionChecker Checker(file, file, std::errc::file_exists, "copy_file"); 70 TEST_VALIDATE_EXCEPTION(filesystem_error, Checker, copy_file(file, file, copy_options::overwrite_existing)); 71 72 } 73 { // exists(to) && !(skip_existing | overwrite_existing | update_existing) 74 std::error_code ec; 75 assert(fs::copy_file(file, file2, ec) == false); 76 assert(ErrorIs(ec, std::errc::file_exists)); 77 ExceptionChecker Checker(file, file, std::errc::file_exists, "copy_file"); 78 TEST_VALIDATE_EXCEPTION(filesystem_error, Checker, copy_file(file, file, copy_options::overwrite_existing)); 79 80 } 81 } 82 83 #ifndef _WIN32 84 static void non_regular_file_test() { 85 scoped_test_env env; 86 const path fifo = env.create_fifo("fifo"); 87 const path dest = env.make_env_path("dest"); 88 const path file = env.create_file("file", 42); 89 90 { 91 std::error_code ec = GetTestEC(); 92 assert(fs::copy_file(fifo, dest, ec) == false); 93 assert(ErrorIs(ec, std::errc::not_supported)); 94 assert(!exists(dest)); 95 } 96 { 97 std::error_code ec = GetTestEC(); 98 assert(fs::copy_file(file, fifo, copy_options::overwrite_existing, 99 ec) == false); 100 assert(ErrorIs(ec, std::errc::not_supported)); 101 assert(is_fifo(fifo)); 102 } 103 104 } 105 #endif // _WIN32 106 107 static void test_attributes_get_copied() { 108 scoped_test_env env; 109 const path file = env.create_file("file1", 42); 110 const path dest = env.make_env_path("file2"); 111 (void)status(file); 112 perms new_perms = perms::owner_read; 113 permissions(file, new_perms); 114 std::error_code ec = GetTestEC(); 115 assert(fs::copy_file(file, dest, ec) == true); 116 assert(!ec); 117 auto new_st = status(dest); 118 assert(new_st.permissions() == NormalizeExpectedPerms(new_perms)); 119 } 120 121 static void copy_dir_test() { 122 scoped_test_env env; 123 const path file = env.create_file("file1", 42); 124 const path dest = env.create_dir("dir1"); 125 std::error_code ec = GetTestEC(); 126 assert(fs::copy_file(file, dest, ec) == false); 127 assert(ec); 128 assert(ec != GetTestEC()); 129 ec = GetTestEC(); 130 assert(fs::copy_file(dest, file, ec) == false); 131 assert(ec); 132 assert(ec != GetTestEC()); 133 } 134 135 static void copy_file() { 136 scoped_test_env env; 137 const path file = env.create_file("file1", 42); 138 139 { // !exists(to) 140 const path dest = env.make_env_path("dest1"); 141 std::error_code ec = GetTestEC(); 142 143 assert(fs::copy_file(file, dest, ec) == true); 144 assert(!ec); 145 assert(file_size(dest) == 42); 146 } 147 { // exists(to) && overwrite_existing 148 const path dest = env.create_file("dest2", 55); 149 permissions(dest, perms::all); 150 permissions(file, 151 perms::group_write | perms::owner_write | perms::others_write, 152 perm_options::remove); 153 154 std::error_code ec = GetTestEC(); 155 assert(fs::copy_file(file, dest, copy_options::overwrite_existing, 156 ec) == true); 157 assert(!ec); 158 assert(file_size(dest) == 42); 159 assert(status(dest).permissions() == status(file).permissions()); 160 } 161 { // exists(to) && update_existing 162 using Sec = std::chrono::seconds; 163 const path older = env.create_file("older_file", 1); 164 165 SleepFor(Sec(2)); 166 const path from = env.create_file("update_from", 55); 167 168 SleepFor(Sec(2)); 169 const path newer = env.create_file("newer_file", 2); 170 171 std::error_code ec = GetTestEC(); 172 assert( 173 fs::copy_file(from, older, copy_options::update_existing, ec) == true); 174 assert(!ec); 175 assert(file_size(older) == 55); 176 177 assert( 178 fs::copy_file(from, newer, copy_options::update_existing, ec) == false); 179 assert(!ec); 180 assert(file_size(newer) == 2); 181 } 182 { // skip_existing 183 const path file2 = env.create_file("file2", 55); 184 std::error_code ec = GetTestEC(); 185 assert(fs::copy_file(file, file2, copy_options::skip_existing, ec) == 186 false); 187 assert(!ec); 188 assert(file_size(file2) == 55); 189 } 190 } 191 192 int main(int, char**) { 193 test_signatures(); 194 test_error_reporting(); 195 #ifndef _WIN32 196 non_regular_file_test(); 197 #endif 198 test_attributes_get_copied(); 199 copy_dir_test(); 200 copy_file(); 201 202 return 0; 203 } 204