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