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