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 | |
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(from: p, to: p)); |
53 | ASSERT_NOT_NOEXCEPT(fs::copy_file(from: p, to: p, option: opts)); |
54 | ASSERT_NOT_NOEXCEPT(fs::copy_file(from: p, to: p, ec&: ec)); |
55 | ASSERT_NOT_NOEXCEPT(fs::copy_file(from: p, to: p, option: opts, ec&: ec)); |
56 | } |
57 | |
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 |
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 | |
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(p: file); |
112 | perms new_perms = perms::owner_read; |
113 | permissions(p: file, prms: 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(p: dest); |
118 | assert(new_st.permissions() == NormalizeExpectedPerms(new_perms)); |
119 | } |
120 | |
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 | |
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(p: dest, prms: perms::all); |
150 | permissions(p: file, |
151 | prms: perms::group_write | perms::owner_write | perms::others_write, |
152 | opts: 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 | |
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 | |