]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/27_io/filesystem/operations/copy.cc
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / 27_io / filesystem / operations / copy.cc
1 // { dg-do run { target c++17 } }
2 // { dg-require-filesystem-ts "" }
3
4 // Copyright (C) 2014-2023 Free Software Foundation, Inc.
5 //
6 // This file is part of the GNU ISO C++ Library. This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 3, or (at your option)
10 // any later version.
11
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16
17 // You should have received a copy of the GNU General Public License along
18 // with this library; see the file COPYING3. If not see
19 // <http://www.gnu.org/licenses/>.
20
21 // 15.3 Copy [fs.op.copy]
22
23 #include <filesystem>
24 #include <testsuite_fs.h>
25 #include <testsuite_hooks.h>
26
27 namespace fs = std::filesystem;
28
29 // Test error conditions.
30 void
31 test01()
32 {
33 auto p = __gnu_test::nonexistent_path();
34 std::error_code ec;
35
36 VERIFY( !fs::exists(p) );
37 fs::copy(p, ".", fs::copy_options::none, ec);
38 VERIFY( ec );
39
40 ec.clear();
41 fs::copy(".", ".", fs::copy_options::none, ec);
42 VERIFY( ec );
43
44 __gnu_test::scoped_file f(p);
45 VERIFY( fs::is_directory(".") );
46 VERIFY( fs::is_regular_file(p) );
47 ec.clear();
48 fs::copy(".", p, fs::copy_options::none, ec);
49 VERIFY( ec );
50
51 auto to = __gnu_test::nonexistent_path();
52 ec.clear();
53 auto opts = fs::copy_options::create_symlinks;
54 fs::copy("/", to, opts, ec);
55 VERIFY( ec == std::make_error_code(std::errc::is_a_directory) );
56 VERIFY( !exists(to) );
57
58 ec.clear();
59 opts |= fs::copy_options::recursive;
60 fs::copy("/", to, opts, ec);
61 VERIFY( ec == std::make_error_code(std::errc::is_a_directory) );
62 VERIFY( !exists(to) );
63 }
64
65 // Test is_symlink(f) case.
66 void
67 test02()
68 {
69 #ifndef NO_SYMLINKS
70 const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
71 auto from = __gnu_test::nonexistent_path();
72 std::error_code ec;
73
74 ec = bad_ec;
75 fs::create_symlink(".", from, ec);
76 VERIFY( !ec );
77 VERIFY( fs::exists(from) );
78
79 auto to = __gnu_test::nonexistent_path();
80 ec = bad_ec;
81 fs::copy(from, to, fs::copy_options::skip_symlinks, ec);
82 VERIFY( !ec );
83 VERIFY( !fs::exists(to) );
84
85 ec = bad_ec;
86 fs::copy(from, to, fs::copy_options::skip_symlinks, ec);
87 VERIFY( !ec );
88 VERIFY( !fs::exists(to) );
89
90 ec = bad_ec;
91 fs::copy(from, to,
92 fs::copy_options::skip_symlinks|fs::copy_options::copy_symlinks,
93 ec);
94 VERIFY( !ec );
95 VERIFY( !fs::exists(to) );
96
97 ec = bad_ec;
98 fs::copy(from, to, fs::copy_options::copy_symlinks, ec);
99 VERIFY( !ec );
100 VERIFY( fs::exists(to) );
101 VERIFY( is_symlink(to) );
102
103 ec.clear();
104 fs::copy(from, to, fs::copy_options::copy_symlinks, ec);
105 VERIFY( ec );
106
107 remove(from, ec);
108 remove(to, ec);
109 #endif
110 }
111
112 // Test is_regular_file(f) case.
113 void
114 test03()
115 {
116 auto from = __gnu_test::nonexistent_path();
117
118 // test empty file
119 std::ofstream{from};
120 VERIFY( fs::exists(from) );
121 VERIFY( fs::file_size(from) == 0 );
122
123 auto to = __gnu_test::nonexistent_path();
124 fs::copy(from, to);
125 VERIFY( fs::exists(to) );
126 VERIFY( fs::file_size(to) == 0 );
127
128 remove(to);
129 VERIFY( !fs::exists(to) );
130 std::ofstream{from} << "Hello, filesystem!";
131 VERIFY( fs::file_size(from) != 0 );
132 fs::copy(from, to);
133 VERIFY( fs::exists(to) );
134 VERIFY( fs::file_size(to) == fs::file_size(from) );
135
136 remove(from);
137 remove(to);
138 }
139
140 // Test is_directory(f) case.
141 void
142 test04()
143 {
144 const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
145 auto from = __gnu_test::nonexistent_path();
146 std::error_code ec;
147
148 create_directories(from/"a/b/c");
149
150 auto to = __gnu_test::nonexistent_path();
151 {
152 __gnu_test::scoped_file f(to);
153 copy(from, to, ec);
154 VERIFY( ec );
155 }
156
157 __gnu_test::scoped_file f1(from/"a/f1");
158 std::ofstream{f1.path} << "file one";
159 __gnu_test::scoped_file f2(from/"a/b/f2");
160 std::ofstream{f2.path} << "file two";
161
162 copy(from, to, ec);
163 VERIFY( !ec );
164 VERIFY( exists(to) && is_empty(to) );
165 remove(to);
166
167 ec = bad_ec;
168 copy(from, to, fs::copy_options::recursive, ec);
169 VERIFY( !ec );
170 VERIFY( exists(to) && !is_empty(to) );
171 VERIFY( is_regular_file(to/"a/f1") && !is_empty(to/"a/f1") );
172 VERIFY( file_size(from/"a/f1") == file_size(to/"a/f1") );
173 VERIFY( is_regular_file(to/"a/b/f2") && !is_empty(to/"a/b/f2") );
174 VERIFY( file_size(from/"a/b/f2") == file_size(to/"a/b/f2") );
175 VERIFY( is_directory(to/"a/b/c") && is_empty(to/"a/b/c") );
176
177 f1.path.clear();
178 f2.path.clear();
179 remove_all(from, ec);
180 remove_all(to, ec);
181 }
182
183 // Test no-op cases.
184 void
185 test05()
186 {
187 auto to = __gnu_test::nonexistent_path();
188 std::error_code ec = std::make_error_code(std::errc::invalid_argument);
189
190 fs::copy("/", to, fs::copy_options::copy_symlinks, ec);
191 VERIFY( !ec ); // Previous value should be cleared (LWG 2683)
192 }
193
194 void
195 test_pr99290()
196 {
197 auto dir = __gnu_test::nonexistent_path();
198 auto source = dir/"source";
199 auto dest = dir/"dest";
200 create_directories(source/"emptydir");
201 create_directories(dest/"emptydir");
202 std::ofstream{source/"file"} << 'a';
203 std::ofstream{dest/"file"} << 'b';
204 // PR libstdc++/99290
205 // std::filesystem::copy does not always report errors for recursion
206 std::error_code ec;
207 copy(source, dest, ec);
208 VERIFY( ec == std::errc::file_exists );
209
210 #if __cpp_exceptions
211 try {
212 copy(source, dest);
213 VERIFY( false );
214 } catch (const fs::filesystem_error& e) {
215 VERIFY( e.code() == std::errc::file_exists );
216 }
217 #endif
218
219 remove_all(dir);
220 }
221
222 int
223 main()
224 {
225 test01();
226 test02();
227 test03();
228 test04();
229 test05();
230 test_pr99290();
231 }