xref: /llvm-project/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy_file/copy_file.pass.cpp (revision fa1c077b41ae1335332d65399802f2c68e82ca7b)
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: use_system_cxx_lib && target={{.+}}-apple-macosx10.15
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 "test_macros.h"
29 #include "rapid-cxx-test.h"
30 #include "filesystem_test_helper.h"
31 
32 using namespace fs;
33 
34 using CO = fs::copy_options;
35 
36 TEST_SUITE(filesystem_copy_file_test_suite)
37 
38 TEST_CASE(test_signatures) {
39   const path p;
40   ((void)p);
41   const copy_options opts{};
42   ((void)opts);
43   std::error_code ec;
44   ((void)ec);
45   ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p)), bool);
46   ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p, opts)), bool);
47   ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p, ec)), bool);
48   ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p, opts, ec)), bool);
49   ASSERT_NOT_NOEXCEPT(fs::copy_file(p, p));
50   ASSERT_NOT_NOEXCEPT(fs::copy_file(p, p, opts));
51   ASSERT_NOT_NOEXCEPT(fs::copy_file(p, p, ec));
52   ASSERT_NOT_NOEXCEPT(fs::copy_file(p, p, opts, ec));
53 }
54 
55 TEST_CASE(test_error_reporting) {
56 
57   scoped_test_env env;
58   const path file = env.create_file("file1", 42);
59   const path file2 = env.create_file("file2", 55);
60 
61   { // exists(to) && equivalent(to, from)
62     std::error_code ec;
63     TEST_CHECK(fs::copy_file(file, file, copy_options::overwrite_existing,
64                              ec) == false);
65     TEST_CHECK(ErrorIs(ec, std::errc::file_exists));
66     ExceptionChecker Checker(file, file, std::errc::file_exists, "copy_file");
67     TEST_CHECK_THROW_RESULT(filesystem_error, Checker, copy_file(file, file, copy_options::overwrite_existing));
68 
69   }
70   { // exists(to) && !(skip_existing | overwrite_existing | update_existing)
71     std::error_code ec;
72     TEST_CHECK(fs::copy_file(file, file2, ec) == false);
73     TEST_CHECK(ErrorIs(ec, std::errc::file_exists));
74     ExceptionChecker Checker(file, file, std::errc::file_exists, "copy_file");
75     TEST_CHECK_THROW_RESULT(filesystem_error, Checker, copy_file(file, file, copy_options::overwrite_existing));
76 
77   }
78 }
79 
80 #ifndef _WIN32
81 TEST_CASE(non_regular_file_test) {
82   scoped_test_env env;
83   const path fifo = env.create_fifo("fifo");
84   const path dest = env.make_env_path("dest");
85   const path file = env.create_file("file", 42);
86 
87   {
88     std::error_code ec = GetTestEC();
89     TEST_REQUIRE(fs::copy_file(fifo, dest, ec) == false);
90     TEST_CHECK(ErrorIs(ec, std::errc::not_supported));
91     TEST_CHECK(!exists(dest));
92   }
93   {
94     std::error_code ec = GetTestEC();
95     TEST_REQUIRE(fs::copy_file(file, fifo, copy_options::overwrite_existing,
96                                ec) == false);
97     TEST_CHECK(ErrorIs(ec, std::errc::not_supported));
98     TEST_CHECK(is_fifo(fifo));
99   }
100 
101 }
102 #endif
103 
104 TEST_CASE(test_attributes_get_copied) {
105   scoped_test_env env;
106   const path file = env.create_file("file1", 42);
107   const path dest = env.make_env_path("file2");
108   (void)status(file);
109   perms new_perms = perms::owner_read;
110   permissions(file, new_perms);
111   std::error_code ec = GetTestEC();
112   TEST_REQUIRE(fs::copy_file(file, dest, ec) == true);
113   TEST_CHECK(!ec);
114   auto new_st = status(dest);
115   TEST_CHECK(new_st.permissions() == NormalizeExpectedPerms(new_perms));
116 }
117 
118 TEST_CASE(copy_dir_test) {
119   scoped_test_env env;
120   const path file = env.create_file("file1", 42);
121   const path dest = env.create_dir("dir1");
122   std::error_code ec = GetTestEC();
123   TEST_CHECK(fs::copy_file(file, dest, ec) == false);
124   TEST_CHECK(ec);
125   TEST_CHECK(ec != GetTestEC());
126   ec = GetTestEC();
127   TEST_CHECK(fs::copy_file(dest, file, ec) == false);
128   TEST_CHECK(ec);
129   TEST_CHECK(ec != GetTestEC());
130 }
131 
132 TEST_CASE(copy_file) {
133   scoped_test_env env;
134   const path file = env.create_file("file1", 42);
135 
136   { // !exists(to)
137     const path dest = env.make_env_path("dest1");
138     std::error_code ec = GetTestEC();
139 
140     TEST_REQUIRE(fs::copy_file(file, dest, ec) == true);
141     TEST_CHECK(!ec);
142     TEST_CHECK(file_size(dest) == 42);
143   }
144   { // exists(to) && overwrite_existing
145     const path dest = env.create_file("dest2", 55);
146     permissions(dest, perms::all);
147     permissions(file,
148                 perms::group_write | perms::owner_write | perms::others_write,
149                 perm_options::remove);
150 
151     std::error_code ec = GetTestEC();
152     TEST_REQUIRE(fs::copy_file(file, dest, copy_options::overwrite_existing,
153                                ec) == true);
154     TEST_CHECK(!ec);
155     TEST_CHECK(file_size(dest) == 42);
156     TEST_CHECK(status(dest).permissions() == status(file).permissions());
157   }
158   { // exists(to) && update_existing
159     using Sec = std::chrono::seconds;
160     const path older = env.create_file("older_file", 1);
161 
162     SleepFor(Sec(2));
163     const path from = env.create_file("update_from", 55);
164 
165     SleepFor(Sec(2));
166     const path newer = env.create_file("newer_file", 2);
167 
168     std::error_code ec = GetTestEC();
169     TEST_REQUIRE(
170         fs::copy_file(from, older, copy_options::update_existing, ec) == true);
171     TEST_CHECK(!ec);
172     TEST_CHECK(file_size(older) == 55);
173 
174     TEST_REQUIRE(
175         fs::copy_file(from, newer, copy_options::update_existing, ec) == false);
176     TEST_CHECK(!ec);
177     TEST_CHECK(file_size(newer) == 2);
178   }
179   { // skip_existing
180     const path file2 = env.create_file("file2", 55);
181     std::error_code ec = GetTestEC();
182     TEST_REQUIRE(fs::copy_file(file, file2, copy_options::skip_existing, ec) ==
183                  false);
184     TEST_CHECK(!ec);
185     TEST_CHECK(file_size(file2) == 55);
186   }
187 }
188 
189 
190 TEST_SUITE_END()
191