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