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"
36namespace fs = std::filesystem;
37using namespace fs;
38
39using CO = fs::copy_options;
40
41static 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
58static 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
84static 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
107static 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
121static 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
135static 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
192int 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

source code of libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy_file/copy_file.pass.cpp