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