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