1//===----------------------------------------------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is dual licensed under the MIT and the University of Illinois Open 6// Source Licenses. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10// UNSUPPORTED: c++98, c++03 11 12// <experimental/filesystem> 13 14// void copy(const path& from, const path& to); 15// void copy(const path& from, const path& to, error_code& ec) noexcept; 16// void copy(const path& from, const path& to, copy_options options); 17// void copy(const path& from, const path& to, copy_options options, 18// error_code& ec) noexcept; 19 20#include <experimental/filesystem> 21#include <type_traits> 22#include <cstddef> 23#include <cassert> 24 25#include "test_macros.h" 26#include "rapid-cxx-test.hpp" 27#include "filesystem_test_helper.hpp" 28 29using namespace std::experimental::filesystem; 30namespace fs = std::experimental::filesystem; 31 32using CO = fs::copy_options; 33 34TEST_SUITE(filesystem_copy_test_suite) 35 36TEST_CASE(signature_test) 37{ 38 const path p; ((void)p); 39 std::error_code ec; ((void)ec); 40 const copy_options opts{}; ((void)opts); 41 ASSERT_NOT_NOEXCEPT(fs::copy(p, p)); 42 ASSERT_NOEXCEPT(fs::copy(p, p, ec)); 43 ASSERT_NOT_NOEXCEPT(copy(p, p, opts)); 44 ASSERT_NOEXCEPT(copy(p, p, opts, ec)); 45} 46 47// There are 4 cases is the proposal for absolute path. 48// Each scope tests one of the cases. 49TEST_CASE(test_error_reporting) 50{ 51 auto checkThrow = [](path const& f, path const& t, const std::error_code& ec) 52 { 53#ifndef TEST_HAS_NO_EXCEPTIONS 54 try { 55 fs::copy(f, t); 56 return false; 57 } catch (filesystem_error const& err) { 58 return err.path1() == f 59 && err.path2() == t 60 && err.code() == ec; 61 } 62#else 63 ((void)f); ((void)t); ((void)ec); 64 return true; 65#endif 66 }; 67 68 scoped_test_env env; 69 const path file = env.create_file("file1", 42); 70 const path dir = env.create_dir("dir"); 71 const path fifo = env.create_fifo("fifo"); 72 TEST_REQUIRE(is_other(fifo)); 73 74 const auto test_ec = GetTestEC(); 75 76 // !exists(f) 77 { 78 std::error_code ec = test_ec; 79 const path f = StaticEnv::DNE; 80 const path t = env.test_root; 81 fs::copy(f, t, ec); 82 TEST_REQUIRE(ec); 83 TEST_REQUIRE(ec != test_ec); 84 TEST_CHECK(checkThrow(f, t, ec)); 85 } 86 { // equivalent(f, t) == true 87 std::error_code ec = test_ec; 88 fs::copy(file, file, ec); 89 TEST_REQUIRE(ec); 90 TEST_REQUIRE(ec != test_ec); 91 TEST_CHECK(checkThrow(file, file, ec)); 92 } 93 { // is_directory(from) && is_file(to) 94 std::error_code ec = test_ec; 95 fs::copy(dir, file, ec); 96 TEST_REQUIRE(ec); 97 TEST_REQUIRE(ec != test_ec); 98 TEST_CHECK(checkThrow(dir, file, ec)); 99 } 100 { // is_other(from) 101 std::error_code ec = test_ec; 102 fs::copy(fifo, dir, ec); 103 TEST_REQUIRE(ec); 104 TEST_REQUIRE(ec != test_ec); 105 TEST_CHECK(checkThrow(fifo, dir, ec)); 106 } 107 { // is_other(to) 108 std::error_code ec = test_ec; 109 fs::copy(file, fifo, ec); 110 TEST_REQUIRE(ec); 111 TEST_REQUIRE(ec != test_ec); 112 TEST_CHECK(checkThrow(file, fifo, ec)); 113 } 114} 115 116TEST_CASE(from_is_symlink) 117{ 118 scoped_test_env env; 119 const path file = env.create_file("file", 42); 120 const path symlink = env.create_symlink(file, "sym"); 121 const path dne = env.make_env_path("dne"); 122 123 { // skip symlinks 124 std::error_code ec = GetTestEC(); 125 fs::copy(symlink, dne, copy_options::skip_symlinks, ec); 126 TEST_CHECK(!ec); 127 TEST_CHECK(!exists(dne)); 128 } 129 { 130 const path dest = env.make_env_path("dest"); 131 std::error_code ec = GetTestEC(); 132 fs::copy(symlink, dest, copy_options::copy_symlinks, ec); 133 TEST_CHECK(!ec); 134 TEST_CHECK(exists(dest)); 135 TEST_CHECK(is_symlink(dest)); 136 } 137 { // copy symlink but target exists 138 std::error_code ec = GetTestEC(); 139 fs::copy(symlink, file, copy_options::copy_symlinks, ec); 140 TEST_CHECK(ec); 141 TEST_CHECK(ec != GetTestEC()); 142 } 143 { // create symlinks but target exists 144 std::error_code ec = GetTestEC(); 145 fs::copy(symlink, file, copy_options::create_symlinks, ec); 146 TEST_CHECK(ec); 147 TEST_CHECK(ec != GetTestEC()); 148 } 149} 150 151TEST_CASE(from_is_regular_file) 152{ 153 scoped_test_env env; 154 const path file = env.create_file("file", 42); 155 const path dir = env.create_dir("dir"); 156 { // skip copy because of directory 157 const path dest = env.make_env_path("dest1"); 158 std::error_code ec = GetTestEC(); 159 fs::copy(file, dest, CO::directories_only, ec); 160 TEST_CHECK(!ec); 161 TEST_CHECK(!exists(dest)); 162 } 163 { // create symlink to file 164 const path dest = env.make_env_path("sym"); 165 std::error_code ec = GetTestEC(); 166 fs::copy(file, dest, CO::create_symlinks, ec); 167 TEST_CHECK(!ec); 168 TEST_CHECK(is_symlink(dest)); 169 TEST_CHECK(equivalent(file, canonical(dest))); 170 } 171 { // create hard link to file 172 const path dest = env.make_env_path("hardlink"); 173 TEST_CHECK(hard_link_count(file) == 1); 174 std::error_code ec = GetTestEC(); 175 fs::copy(file, dest, CO::create_hard_links, ec); 176 TEST_CHECK(!ec); 177 TEST_CHECK(exists(dest)); 178 TEST_CHECK(hard_link_count(file) == 2); 179 } 180 { // is_directory(t) 181 const path dest_dir = env.create_dir("dest_dir"); 182 const path expect_dest = dest_dir / file.filename(); 183 std::error_code ec = GetTestEC(); 184 fs::copy(file, dest_dir, ec); 185 TEST_CHECK(!ec); 186 TEST_CHECK(is_regular_file(expect_dest)); 187 } 188 { // otherwise copy_file(from, to, ...) 189 const path dest = env.make_env_path("file_copy"); 190 std::error_code ec = GetTestEC(); 191 fs::copy(file, dest, ec); 192 TEST_CHECK(!ec); 193 TEST_CHECK(is_regular_file(dest)); 194 } 195} 196 197TEST_CASE(from_is_directory) 198{ 199 struct FileInfo { 200 path filename; 201 std::size_t size; 202 }; 203 const FileInfo files[] = { 204 {"file1", 0}, 205 {"file2", 42}, 206 {"file3", 300} 207 }; 208 scoped_test_env env; 209 const path dir = env.create_dir("dir"); 210 const path nested_dir_name = "dir2"; 211 const path nested_dir = env.create_dir("dir/dir2"); 212 213 for (auto& FI : files) { 214 env.create_file(dir / FI.filename, FI.size); 215 env.create_file(nested_dir / FI.filename, FI.size); 216 } 217 { // test for non-existent directory 218 const path dest = env.make_env_path("dest_dir1"); 219 std::error_code ec = GetTestEC(); 220 fs::copy(dir, dest, ec); 221 TEST_REQUIRE(!ec); 222 TEST_CHECK(is_directory(dest)); 223 for (auto& FI : files) { 224 path created = dest / FI.filename; 225 TEST_CHECK(is_regular_file(created)); 226 TEST_CHECK(file_size(created) == FI.size); 227 } 228 TEST_CHECK(!is_directory(dest / nested_dir_name)); 229 } 230 { // test for existing directory 231 const path dest = env.create_dir("dest_dir2"); 232 std::error_code ec = GetTestEC(); 233 fs::copy(dir, dest, ec); 234 TEST_REQUIRE(!ec); 235 TEST_CHECK(is_directory(dest)); 236 for (auto& FI : files) { 237 path created = dest / FI.filename; 238 TEST_CHECK(is_regular_file(created)); 239 TEST_CHECK(file_size(created) == FI.size); 240 } 241 TEST_CHECK(!is_directory(dest / nested_dir_name)); 242 } 243 { // test recursive copy 244 const path dest = env.make_env_path("dest_dir3"); 245 std::error_code ec = GetTestEC(); 246 fs::copy(dir, dest, CO::recursive, ec); 247 TEST_REQUIRE(!ec); 248 TEST_CHECK(is_directory(dest)); 249 const path nested_dest = dest / nested_dir_name; 250 TEST_REQUIRE(is_directory(nested_dest)); 251 for (auto& FI : files) { 252 path created = dest / FI.filename; 253 path nested_created = nested_dest / FI.filename; 254 TEST_CHECK(is_regular_file(created)); 255 TEST_CHECK(file_size(created) == FI.size); 256 TEST_CHECK(is_regular_file(nested_created)); 257 TEST_CHECK(file_size(nested_created) == FI.size); 258 } 259 } 260} 261 262TEST_CASE(test_copy_symlinks_to_symlink_dir) 263{ 264 scoped_test_env env; 265 const path file1 = env.create_file("file1", 42); 266 const path file2 = env.create_file("file2", 101); 267 const path file2_sym = env.create_symlink(file2, "file2_sym"); 268 const path dir = env.create_dir("dir"); 269 const path dir_sym = env.create_symlink(dir, "dir_sym"); 270 { 271 std::error_code ec = GetTestEC(); 272 fs::copy(file1, dir_sym, copy_options::copy_symlinks, ec); 273 TEST_CHECK(!ec); 274 const path dest = env.make_env_path("dir/file1"); 275 TEST_CHECK(exists(dest)); 276 TEST_CHECK(!is_symlink(dest)); 277 TEST_CHECK(file_size(dest) == 42); 278 } 279} 280 281 282TEST_CASE(test_dir_create_symlink) 283{ 284 scoped_test_env env; 285 const path dir = env.create_dir("dir1"); 286 const path dest = env.make_env_path("dne"); 287 { 288 std::error_code ec = GetTestEC(); 289 fs::copy(dir, dest, copy_options::create_symlinks, ec); 290 TEST_CHECK(ec == std::make_error_code(std::errc::is_a_directory)); 291 TEST_CHECK(!exists(dest)); 292 TEST_CHECK(!is_symlink(dest)); 293 } 294 { 295 std::error_code ec = GetTestEC(); 296 fs::copy(dir, dest, copy_options::create_symlinks|copy_options::recursive, ec); 297 TEST_CHECK(ec == std::make_error_code(std::errc::is_a_directory)); 298 TEST_CHECK(!exists(dest)); 299 TEST_CHECK(!is_symlink(dest)); 300 } 301} 302 303TEST_CASE(test_otherwise_no_effects_clause) 304{ 305 scoped_test_env env; 306 const path dir = env.create_dir("dir1"); 307 { // skip copy because of directory 308 const path dest = env.make_env_path("dest1"); 309 std::error_code ec; 310 fs::copy(dir, dest, CO::directories_only, ec); 311 TEST_CHECK(!ec); 312 TEST_CHECK(!exists(dest)); 313 } 314} 315 316TEST_SUITE_END() 317