]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/filesystem/test/copy_test.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / filesystem / test / copy_test.cpp
CommitLineData
20effc67
TL
1// Copyright Andrey Semashev 2020.
2
3// Distributed under the Boost Software License, Version 1.0.
4// See http://www.boost.org/LICENSE_1_0.txt
5
6// Library home page: http://www.boost.org/libs/filesystem
7
8// This test verifies copy operation behavior.
9
10#include <boost/filesystem/operations.hpp>
11#include <boost/filesystem/path.hpp>
12#include <boost/filesystem/directory.hpp>
13#include <boost/filesystem/exception.hpp>
1e59de90 14#include <boost/filesystem/fstream.hpp> // for BOOST_FILESYSTEM_C_STR
20effc67
TL
15#include <boost/system/error_code.hpp>
16
17#include <set>
18#include <string>
19#include <fstream>
20#include <iostream>
21#include <stdexcept>
22
23#include <boost/throw_exception.hpp>
24#include <boost/exception/diagnostic_information.hpp>
25#include <boost/core/lightweight_test.hpp>
26
20effc67
TL
27namespace fs = boost::filesystem;
28
29namespace {
30
31void create_file(fs::path const& ph, std::string const& contents = std::string())
32{
1e59de90 33 std::ofstream f(BOOST_FILESYSTEM_C_STR(ph), std::ios_base::out | std::ios_base::trunc);
20effc67
TL
34 if (!f)
35 BOOST_THROW_EXCEPTION(std::runtime_error("Failed to create file: " + ph.string()));
36 if (!contents.empty())
37 f << contents;
38}
39
40void verify_file(fs::path const& ph, std::string const& expected)
41{
1e59de90 42 std::ifstream f(BOOST_FILESYSTEM_C_STR(ph));
20effc67
TL
43 if (!f)
44 BOOST_THROW_EXCEPTION(std::runtime_error("Failed to open file: " + ph.string()));
45 std::string contents;
46 f >> contents;
47 BOOST_TEST_EQ(contents, expected);
48 if (contents != expected)
49 {
1e59de90 50 BOOST_THROW_EXCEPTION(std::runtime_error("verify_file failed: contents \"" + contents + "\" != \"" + expected + "\" in " + ph.string()));
20effc67
TL
51 }
52}
53
54fs::path create_tree()
55{
56 fs::path root_dir = fs::unique_path();
57
58 fs::create_directory(root_dir);
59 create_file(root_dir / "f1", "f1");
60 create_file(root_dir / "f2", "f2");
61
62 fs::create_directory(root_dir / "d1");
63 create_file(root_dir / "d1/f1", "d1f1");
64
65 fs::create_directory(root_dir / "d1/d1");
66 create_file(root_dir / "d1/d1/f1", "d1d1f1");
67
68 fs::create_directory(root_dir / "d1/d2");
69
70 fs::create_directory(root_dir / "d2");
71 create_file(root_dir / "d2/f1", "d2f1");
72
73 return root_dir;
74}
75
76typedef std::set< fs::path > directory_tree;
77
78directory_tree collect_directory_tree(fs::path const& root_dir)
79{
80 std::cout << "Collecting directory tree in: " << root_dir << '\n';
81
82 directory_tree tree;
1e59de90
TL
83 fs::recursive_directory_iterator it(root_dir, fs::directory_options::skip_permission_denied |
84 fs::directory_options::follow_directory_symlink | fs::directory_options::skip_dangling_symlinks);
85 fs::recursive_directory_iterator end;
20effc67
TL
86 while (it != end)
87 {
88 fs::path p = fs::relative(it->path(), root_dir);
89 std::cout << p << '\n';
90 tree.insert(p);
91 ++it;
92 }
93
94 std::cout << "done." << std::endl;
95
96 return tree;
97}
98
99void test_copy_file_default(fs::path const& root_dir)
100{
101 std::cout << "test_copy_file_default" << std::endl;
102
103 fs::path target_dir = fs::unique_path();
104 fs::create_directory(target_dir);
105
106 fs::copy(root_dir / "f1", target_dir);
107 fs::copy(root_dir / "f2", target_dir / "f3");
108
109 directory_tree tree = collect_directory_tree(target_dir);
110
111 BOOST_TEST_EQ(tree.size(), 2u);
112 BOOST_TEST(tree.find("f1") != tree.end());
113 BOOST_TEST(tree.find("f3") != tree.end());
114
115 verify_file(target_dir / "f1", "f1");
116 verify_file(target_dir / "f3", "f2");
117
118 fs::remove_all(target_dir);
119}
120
121void test_copy_dir_default(fs::path const& root_dir, bool with_symlinks)
122{
123 std::cout << "test_copy_dir_default" << std::endl;
124
125 fs::path target_dir = fs::unique_path();
126
127 fs::copy(root_dir, target_dir);
128
129 directory_tree tree = collect_directory_tree(target_dir);
130
131 BOOST_TEST_EQ(tree.size(), 4u + with_symlinks);
132 BOOST_TEST(tree.find("f1") != tree.end());
133 BOOST_TEST(tree.find("f2") != tree.end());
134 BOOST_TEST(tree.find("d1") != tree.end());
135 BOOST_TEST(tree.find("d2") != tree.end());
136 if (with_symlinks)
137 {
138 BOOST_TEST(tree.find("s1") != tree.end());
139 }
140
141 verify_file(target_dir / "f1", "f1");
142 verify_file(target_dir / "f2", "f2");
143
144 fs::remove_all(target_dir);
145}
146
147void test_copy_dir_default_ec(fs::path const& root_dir, bool with_symlinks)
148{
149 // This test is similar to test_copy_dir_default, but uses an error_code overload of the operation.
150 // Tests for https://github.com/boostorg/filesystem/issues/152 fix.
151
152 std::cout << "test_copy_dir_default_ec" << std::endl;
153
154 fs::path target_dir = fs::unique_path();
155
156 boost::system::error_code ec;
157 fs::copy(root_dir, target_dir, ec);
158 BOOST_TEST(!ec);
159
160 directory_tree tree = collect_directory_tree(target_dir);
161
162 BOOST_TEST_EQ(tree.size(), 4u + with_symlinks);
163 BOOST_TEST(tree.find("f1") != tree.end());
164 BOOST_TEST(tree.find("f2") != tree.end());
165 BOOST_TEST(tree.find("d1") != tree.end());
166 BOOST_TEST(tree.find("d2") != tree.end());
167 if (with_symlinks)
168 {
169 BOOST_TEST(tree.find("s1") != tree.end());
170 }
171
172 verify_file(target_dir / "f1", "f1");
173 verify_file(target_dir / "f2", "f2");
174
175 fs::remove_all(target_dir);
176}
177
178void test_copy_dir_recursive(fs::path const& root_dir)
179{
180 std::cout << "test_copy_dir_recursive" << std::endl;
181
182 fs::path target_dir = fs::unique_path();
183
184 fs::copy(root_dir, target_dir, fs::copy_options::recursive);
185
186 directory_tree tree = collect_directory_tree(target_dir);
187
188 BOOST_TEST_EQ(tree.size(), 9u);
189 BOOST_TEST(tree.find("f1") != tree.end());
190 BOOST_TEST(tree.find("f2") != tree.end());
191 BOOST_TEST(tree.find("d1") != tree.end());
192 BOOST_TEST(tree.find(fs::path("d1") / "f1") != tree.end());
193 BOOST_TEST(tree.find(fs::path("d1") / "d1") != tree.end());
194 BOOST_TEST(tree.find(fs::path("d1") / "d1" / "f1") != tree.end());
195 BOOST_TEST(tree.find(fs::path("d1") / "d2") != tree.end());
196 BOOST_TEST(tree.find("d2") != tree.end());
197 BOOST_TEST(tree.find(fs::path("d2") / "f1") != tree.end());
198
199 verify_file(target_dir / "f1", "f1");
200 verify_file(target_dir / "f2", "f2");
201 verify_file(target_dir / "d1/f1", "d1f1");
202 verify_file(target_dir / "d1/d1/f1", "d1d1f1");
203 verify_file(target_dir / "d2/f1", "d2f1");
204
205 fs::remove_all(target_dir);
206}
207
208void test_copy_dir_recursive_tree(fs::path const& root_dir)
209{
210 std::cout << "test_copy_dir_recursive_tree" << std::endl;
211
212 fs::path target_dir = fs::unique_path();
213
214 fs::copy(root_dir, target_dir, fs::copy_options::recursive | fs::copy_options::directories_only);
215
216 directory_tree tree = collect_directory_tree(target_dir);
217
218 BOOST_TEST_EQ(tree.size(), 4u);
219 BOOST_TEST(tree.find("d1") != tree.end());
220 BOOST_TEST(tree.find(fs::path("d1") / "d1") != tree.end());
221 BOOST_TEST(tree.find(fs::path("d1") / "d2") != tree.end());
222 BOOST_TEST(tree.find("d2") != tree.end());
223
224 fs::remove_all(target_dir);
225}
226
227void test_copy_file_symlinks(fs::path const& root_dir)
228{
229 std::cout << "test_copy_file_symlinks" << std::endl;
230
231 fs::path target_dir = fs::unique_path();
232 fs::create_directory(target_dir);
233
234 fs::copy(root_dir / "f1", target_dir);
235
236 fs::path prev_cur_dir = fs::current_path();
237 fs::current_path(target_dir);
238 fs::copy(".." / root_dir / "f2", "f2", fs::copy_options::create_symlinks);
239 fs::current_path(prev_cur_dir);
240
241 // Copying from a relative path with copy_options::create_symlinks to a directory other than current directory is a non-standard extension
242 fs::copy(target_dir / "f1", target_dir / "f3", fs::copy_options::create_symlinks);
243
244 verify_file(target_dir / "f1", "f1");
245
246 fs::path link_target = fs::read_symlink(target_dir / "f2");
247 if (link_target != (".." / root_dir / "f2"))
248 {
249 BOOST_ERROR("Incorrect f2 symlink in test_copy_file_symlinks");
250 std::cout << (target_dir / "f2") << " => " << link_target << std::endl;
251 }
252
253 link_target = fs::read_symlink(target_dir / "f3");
254 if (link_target != "f1" && link_target != (fs::path(".") / "f1"))
255 {
256 BOOST_ERROR("Incorrect f3 symlink in test_copy_file_symlinks");
257 std::cout << (target_dir / "f3") << " => " << link_target << std::endl;
258 }
259
260 fs::remove_all(target_dir);
261}
262
263void test_copy_errors(fs::path const& root_dir, bool symlinks_supported)
264{
265 std::cout << "test_copy_errors" << std::endl;
266
267 fs::path target_dir = fs::unique_path();
268 fs::create_directory(target_dir);
269
270 BOOST_TEST_THROWS(fs::copy(root_dir / "non-existing", target_dir), fs::filesystem_error);
271
272 create_file(target_dir / "f1");
273
274 BOOST_TEST_THROWS(fs::copy(root_dir / "f1", target_dir), fs::filesystem_error);
275 BOOST_TEST_THROWS(fs::copy(root_dir / "f1", target_dir / "f1"), fs::filesystem_error);
276 BOOST_TEST_THROWS(fs::copy(root_dir / "d1", target_dir / "f1"), fs::filesystem_error);
277
278 BOOST_TEST_THROWS(fs::copy(target_dir, target_dir), fs::filesystem_error);
279 BOOST_TEST_THROWS(fs::copy(target_dir / "f1", target_dir / "f1"), fs::filesystem_error);
280
281 if (symlinks_supported)
282 {
283 // Should fail with is_a_directory error code
284 BOOST_TEST_THROWS(fs::copy(root_dir, target_dir, fs::copy_options::create_symlinks), fs::filesystem_error);
285 }
286
287 fs::remove_all(target_dir);
288}
289
290} // namespace
291
292int main()
293{
294 try
295 {
296 fs::path root_dir = create_tree();
297
298 test_copy_file_default(root_dir);
299 test_copy_dir_default(root_dir, false);
300 test_copy_dir_default_ec(root_dir, false);
301 test_copy_dir_recursive(root_dir);
302 test_copy_dir_recursive_tree(root_dir);
303
304 bool symlinks_supported = false;
305 try
306 {
307 fs::create_symlink("f1", root_dir / "s1");
308 symlinks_supported = true;
1e59de90
TL
309 std::cout << " *** For information only ***\n"
310 " create_symlink() attempt succeeded"
311 << std::endl;
20effc67
TL
312 }
313 catch (fs::filesystem_error& e)
314 {
1e59de90
TL
315 std::cout << " *** For information only ***\n"
316 " create_symlink() attempt failed\n"
317 " filesystem_error.what() reports: "
318 << e.what() << "\n"
319 " create_symlink() may not be supported on this operating system or file system"
320 << std::endl;
20effc67
TL
321 }
322
323 if (symlinks_supported)
324 {
325 test_copy_dir_default(root_dir, true);
326 test_copy_file_symlinks(root_dir);
327 }
328
329 test_copy_errors(root_dir, symlinks_supported);
330
331 fs::remove_all(root_dir);
332
333 return boost::report_errors();
334 }
335 catch (std::exception& e)
336 {
337 std::cout << "FAIL, exception caught: " << boost::diagnostic_information(e) << std::endl;
338 return 1;
339 }
340}