Home | History | Annotate | Download | only in fs.op.copy
      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);
     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);
     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 
     29 using namespace std::experimental::filesystem;
     30 namespace fs = std::experimental::filesystem;
     31 
     32 using CO = fs::copy_options;
     33 
     34 TEST_SUITE(filesystem_copy_test_suite)
     35 
     36 TEST_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_NOT_NOEXCEPT(fs::copy(p, p, ec));
     43     ASSERT_NOT_NOEXCEPT(copy(p, p, opts));
     44     ASSERT_NOT_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.
     49 TEST_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 
    116 TEST_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 
    151 TEST_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 
    197 TEST_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 
    262 TEST_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 
    282 TEST_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 
    303 TEST_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 
    316 TEST_SUITE_END()
    317