xref: /llvm-project/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy_file/copy_file.pass.cpp (revision 3497500946c9b6a1b2e1452312a24c41ee412b34)
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // UNSUPPORTED: c++03, c++11, c++14
10 // UNSUPPORTED: no-filesystem
11 // UNSUPPORTED: availability-filesystem-missing
12 
13 // The string reported on errors changed, which makes those tests fail when run
14 // against a built library that doesn't contain 0aa637b2037d.
15 // XFAIL: using-built-library-before-llvm-13
16 
17 // Starting in Android N (API 24), SELinux policy prevents the shell user from
18 // creating a FIFO file.
19 // XFAIL: LIBCXX-ANDROID-FIXME && !android-device-api={{21|22|23}}
20 
21 // <filesystem>
22 
23 // bool copy_file(const path& from, const path& to);
24 // bool copy_file(const path& from, const path& to, error_code& ec) noexcept;
25 // bool copy_file(const path& from, const path& to, copy_options options);
26 // bool copy_file(const path& from, const path& to, copy_options options, error_code& ec) noexcept;
27 
28 #include <filesystem>
29 #include <type_traits>
30 #include <chrono>
31 #include <cassert>
32 
33 #include "assert_macros.h"
34 #include "test_macros.h"
35 #include "filesystem_test_helper.h"
36 namespace fs = std::filesystem;
37 using namespace fs;
38 
39 using CO = fs::copy_options;
40 
test_signatures()41 static void test_signatures() {
42   const path p;
43   ((void)p);
44   const copy_options opts{};
45   ((void)opts);
46   std::error_code ec;
47   ((void)ec);
48   ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p)), bool);
49   ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p, opts)), bool);
50   ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p, ec)), bool);
51   ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p, opts, ec)), bool);
52   ASSERT_NOT_NOEXCEPT(fs::copy_file(p, p));
53   ASSERT_NOT_NOEXCEPT(fs::copy_file(p, p, opts));
54   ASSERT_NOT_NOEXCEPT(fs::copy_file(p, p, ec));
55   ASSERT_NOT_NOEXCEPT(fs::copy_file(p, p, opts, ec));
56 }
57 
test_error_reporting()58 static void test_error_reporting() {
59 
60   scoped_test_env env;
61   const path file = env.create_file("file1", 42);
62   const path file2 = env.create_file("file2", 55);
63 
64   { // exists(to) && equivalent(to, from)
65     std::error_code ec;
66     assert(fs::copy_file(file, file, copy_options::overwrite_existing,
67                              ec) == false);
68     assert(ErrorIs(ec, std::errc::file_exists));
69     ExceptionChecker Checker(file, file, std::errc::file_exists, "copy_file");
70     TEST_VALIDATE_EXCEPTION(filesystem_error, Checker, copy_file(file, file, copy_options::overwrite_existing));
71 
72   }
73   { // exists(to) && !(skip_existing | overwrite_existing | update_existing)
74     std::error_code ec;
75     assert(fs::copy_file(file, file2, ec) == false);
76     assert(ErrorIs(ec, std::errc::file_exists));
77     ExceptionChecker Checker(file, file, std::errc::file_exists, "copy_file");
78     TEST_VALIDATE_EXCEPTION(filesystem_error, Checker, copy_file(file, file, copy_options::overwrite_existing));
79 
80   }
81 }
82 
83 #ifndef _WIN32
non_regular_file_test()84 static void non_regular_file_test() {
85   scoped_test_env env;
86   const path fifo = env.create_fifo("fifo");
87   const path dest = env.make_env_path("dest");
88   const path file = env.create_file("file", 42);
89 
90   {
91     std::error_code ec = GetTestEC();
92     assert(fs::copy_file(fifo, dest, ec) == false);
93     assert(ErrorIs(ec, std::errc::not_supported));
94     assert(!exists(dest));
95   }
96   {
97     std::error_code ec = GetTestEC();
98     assert(fs::copy_file(file, fifo, copy_options::overwrite_existing,
99                                ec) == false);
100     assert(ErrorIs(ec, std::errc::not_supported));
101     assert(is_fifo(fifo));
102   }
103 
104 }
105 #endif // _WIN32
106 
test_attributes_get_copied()107 static void test_attributes_get_copied() {
108   scoped_test_env env;
109   const path file = env.create_file("file1", 42);
110   const path dest = env.make_env_path("file2");
111   (void)status(file);
112   perms new_perms = perms::owner_read;
113   permissions(file, new_perms);
114   std::error_code ec = GetTestEC();
115   assert(fs::copy_file(file, dest, ec) == true);
116   assert(!ec);
117   auto new_st = status(dest);
118   assert(new_st.permissions() == NormalizeExpectedPerms(new_perms));
119 }
120 
copy_dir_test()121 static void copy_dir_test() {
122   scoped_test_env env;
123   const path file = env.create_file("file1", 42);
124   const path dest = env.create_dir("dir1");
125   std::error_code ec = GetTestEC();
126   assert(fs::copy_file(file, dest, ec) == false);
127   assert(ec);
128   assert(ec != GetTestEC());
129   ec = GetTestEC();
130   assert(fs::copy_file(dest, file, ec) == false);
131   assert(ec);
132   assert(ec != GetTestEC());
133 }
134 
copy_file()135 static void copy_file() {
136   scoped_test_env env;
137   const path file = env.create_file("file1", 42);
138 
139   { // !exists(to)
140     const path dest = env.make_env_path("dest1");
141     std::error_code ec = GetTestEC();
142 
143     assert(fs::copy_file(file, dest, ec) == true);
144     assert(!ec);
145     assert(file_size(dest) == 42);
146   }
147   { // exists(to) && overwrite_existing
148     const path dest = env.create_file("dest2", 55);
149     permissions(dest, perms::all);
150     permissions(file,
151                 perms::group_write | perms::owner_write | perms::others_write,
152                 perm_options::remove);
153 
154     std::error_code ec = GetTestEC();
155     assert(fs::copy_file(file, dest, copy_options::overwrite_existing,
156                                ec) == true);
157     assert(!ec);
158     assert(file_size(dest) == 42);
159     assert(status(dest).permissions() == status(file).permissions());
160   }
161   { // exists(to) && update_existing
162     using Sec = std::chrono::seconds;
163     const path older = env.create_file("older_file", 1);
164 
165     SleepFor(Sec(2));
166     const path from = env.create_file("update_from", 55);
167 
168     SleepFor(Sec(2));
169     const path newer = env.create_file("newer_file", 2);
170 
171     std::error_code ec = GetTestEC();
172     assert(
173         fs::copy_file(from, older, copy_options::update_existing, ec) == true);
174     assert(!ec);
175     assert(file_size(older) == 55);
176 
177     assert(
178         fs::copy_file(from, newer, copy_options::update_existing, ec) == false);
179     assert(!ec);
180     assert(file_size(newer) == 2);
181   }
182   { // skip_existing
183     const path file2 = env.create_file("file2", 55);
184     std::error_code ec = GetTestEC();
185     assert(fs::copy_file(file, file2, copy_options::skip_existing, ec) ==
186                  false);
187     assert(!ec);
188     assert(file_size(file2) == 55);
189   }
190 }
191 
main(int,char **)192 int main(int, char**) {
193   test_signatures();
194   test_error_reporting();
195 #ifndef _WIN32
196   non_regular_file_test();
197 #endif
198   test_attributes_get_copied();
199   copy_dir_test();
200   copy_file();
201 
202   return 0;
203 }
204