1 | // Boost operations_test.cpp -----------------------------------------------// |
---|
2 | |
---|
3 | // Copyright Beman Dawes 2002. |
---|
4 | // Use, modification, and distribution is subject to the Boost Software |
---|
5 | // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
---|
6 | // http://www.boost.org/LICENSE_1_0.txt) |
---|
7 | |
---|
8 | // See library home page at http://www.boost.org/libs/filesystem |
---|
9 | |
---|
10 | #include <boost/filesystem/operations.hpp> |
---|
11 | #include <boost/filesystem/exception.hpp> |
---|
12 | namespace fs = boost::filesystem; |
---|
13 | |
---|
14 | #include <boost/config.hpp> |
---|
15 | #include <boost/test/minimal.hpp> |
---|
16 | #include <boost/concept_check.hpp> |
---|
17 | #include <boost/bind.hpp> |
---|
18 | using boost::bind; |
---|
19 | |
---|
20 | #include <fstream> |
---|
21 | #include <iostream> |
---|
22 | #include <string> |
---|
23 | #include <cerrno> |
---|
24 | #include <ctime> |
---|
25 | |
---|
26 | # ifdef BOOST_NO_STDC_NAMESPACE |
---|
27 | namespace std { using ::asctime; using ::gmtime; using ::localtime; |
---|
28 | using ::difftime; using ::time; using ::tm; using ::mktime; } |
---|
29 | # endif |
---|
30 | |
---|
31 | namespace |
---|
32 | { |
---|
33 | bool report_throws; |
---|
34 | fs::directory_iterator end_itr; |
---|
35 | |
---|
36 | void create_file( const fs::path & ph, const std::string & contents ) |
---|
37 | { |
---|
38 | std::ofstream f( ph.native_file_string().c_str() ); |
---|
39 | if ( !f ) |
---|
40 | throw fs::filesystem_error( "operations_test create_file", |
---|
41 | ph, errno ); |
---|
42 | if ( !contents.empty() ) f << contents; |
---|
43 | } |
---|
44 | |
---|
45 | void verify_file( const fs::path & ph, const std::string & expected ) |
---|
46 | { |
---|
47 | std::ifstream f( ph.native_file_string().c_str() ); |
---|
48 | if ( !f ) |
---|
49 | throw fs::filesystem_error( "operations_test verify_file", |
---|
50 | ph, errno ); |
---|
51 | std::string contents; |
---|
52 | f >> contents; |
---|
53 | if ( contents != expected ) |
---|
54 | throw fs::filesystem_error( "operations_test verify_file", |
---|
55 | ph, " contents \"" + contents |
---|
56 | + "\" != \"" + expected + "\"" ); |
---|
57 | } |
---|
58 | |
---|
59 | template< typename F > |
---|
60 | bool throws_fs_error( F func, fs::error_code ec = |
---|
61 | ::boost::filesystem::no_error ) // VC++ 7.1 build 2292 won't accept fs:: |
---|
62 | { |
---|
63 | try { func(); } |
---|
64 | |
---|
65 | catch ( const fs::filesystem_error & ex ) |
---|
66 | { |
---|
67 | if ( report_throws ) std::cout << ex.what() << "\n"; |
---|
68 | if ( ec == fs::no_error || ec == ex.error() ) return true; |
---|
69 | std::cout << "filesystem_error::error() reports " << ex.error() |
---|
70 | << ", should be " << ec |
---|
71 | << "\n native_error() is " << ex.native_error() |
---|
72 | << std::endl; |
---|
73 | } |
---|
74 | return false; |
---|
75 | } |
---|
76 | |
---|
77 | } // unnamed namespace |
---|
78 | |
---|
79 | // test_main ---------------------------------------------------------------// |
---|
80 | |
---|
81 | int test_main( int argc, char * argv[] ) |
---|
82 | { |
---|
83 | if ( argc > 1 && *argv[1]=='-' && *(argv[1]+1)=='t' ) report_throws = true; |
---|
84 | |
---|
85 | std::string platform( BOOST_PLATFORM ); |
---|
86 | |
---|
87 | // The choice of platform is make at runtime rather than compile-time |
---|
88 | // so that compile errors for all platforms will be detected even though |
---|
89 | // only the current platform is runtime tested. |
---|
90 | # if defined( BOOST_POSIX ) |
---|
91 | platform = "POSIX"; |
---|
92 | # elif defined( BOOST_WINDOWS ) |
---|
93 | platform = "Windows"; |
---|
94 | # else |
---|
95 | platform = ( platform == "Win32" || platform == "Win64" || platform == "Cygwin" ) |
---|
96 | ? "Windows" |
---|
97 | : "POSIX"; |
---|
98 | # endif |
---|
99 | std::cout << "Platform is " << platform << '\n'; |
---|
100 | |
---|
101 | std::cout << "initial_path().string() is\n \"" |
---|
102 | << fs::initial_path().string() |
---|
103 | << "\"\n"; |
---|
104 | std::cout << "initial_path().native_file_string() is\n \"" |
---|
105 | << fs::initial_path().native_file_string() |
---|
106 | << "\"\n"; |
---|
107 | |
---|
108 | BOOST_CHECK( fs::initial_path().is_complete() ); |
---|
109 | BOOST_CHECK( fs::current_path().is_complete() ); |
---|
110 | BOOST_CHECK( fs::initial_path().string() == fs::current_path().string() ); |
---|
111 | |
---|
112 | BOOST_CHECK( fs::complete( "" ).empty() ); |
---|
113 | BOOST_CHECK( fs::complete( "/" ).string() |
---|
114 | == fs::initial_path().root_path().string() ); |
---|
115 | BOOST_CHECK( fs::complete( "foo" ).string() |
---|
116 | == fs::initial_path().string()+"/foo" ); |
---|
117 | BOOST_CHECK( fs::complete( "/foo" ).string() |
---|
118 | == fs::initial_path().root_path().string()+"foo" ); |
---|
119 | |
---|
120 | fs::path dir( fs::initial_path() / "temp_fs_test_directory" ); |
---|
121 | |
---|
122 | // Windows only tests |
---|
123 | if ( platform == "Windows" ) |
---|
124 | { |
---|
125 | BOOST_CHECK( !fs::exists( fs::path( "//share-not/foo", fs::native ) ) ); |
---|
126 | BOOST_CHECK( dir.string().size() > 1 |
---|
127 | && dir.string()[1] == ':' ); // verify path includes drive |
---|
128 | |
---|
129 | BOOST_CHECK( fs::system_complete( "" ).empty() ); |
---|
130 | BOOST_CHECK( fs::system_complete( "/" ).string() |
---|
131 | == fs::initial_path().root_path().string() ); |
---|
132 | BOOST_CHECK( fs::system_complete( "foo" ).string() |
---|
133 | == fs::initial_path().string()+"/foo" ); |
---|
134 | BOOST_CHECK( fs::system_complete( "/foo" ).string() |
---|
135 | == fs::initial_path().root_path().string()+"foo" ); |
---|
136 | |
---|
137 | // BOOST_CHECK( fs::complete( fs::path( "c:", fs::native ) ).string() |
---|
138 | // == fs::initial_path().string() ); |
---|
139 | // BOOST_CHECK( fs::complete( fs::path( "c:foo", fs::native ) ).string() |
---|
140 | // == fs::initial_path().string()+"/foo" ); |
---|
141 | BOOST_CHECK( fs::complete( fs::path( "c:/", fs::native ) ).string() |
---|
142 | == "c:/" ); |
---|
143 | BOOST_CHECK( fs::complete( fs::path( "c:/foo", fs::native ) ).string() |
---|
144 | == "c:/foo" ); |
---|
145 | BOOST_CHECK( fs::complete( fs::path( "//share", fs::native ) ).string() |
---|
146 | == "//share" ); |
---|
147 | |
---|
148 | BOOST_CHECK( fs::system_complete( fs::path( fs::initial_path().root_name(), |
---|
149 | fs::native ) ).string() == fs::initial_path().string() ); |
---|
150 | BOOST_CHECK( fs::system_complete( fs::path( fs::initial_path().root_name() |
---|
151 | + "foo", fs::native ) ).string() == fs::initial_path().string()+"/foo" ); |
---|
152 | BOOST_CHECK( fs::system_complete( fs::path( "c:/", fs::native ) ).string() |
---|
153 | == "c:/" ); |
---|
154 | BOOST_CHECK( fs::system_complete( fs::path( "c:/foo", fs::native ) ).string() |
---|
155 | == "c:/foo" ); |
---|
156 | BOOST_CHECK( fs::system_complete( fs::path( "//share", fs::native ) ).string() |
---|
157 | == "//share" ); |
---|
158 | } |
---|
159 | |
---|
160 | else if ( platform == "POSIX" ) |
---|
161 | { |
---|
162 | BOOST_CHECK( fs::system_complete( "" ).empty() ); |
---|
163 | BOOST_CHECK( fs::initial_path().root_path().string() == "/" ); |
---|
164 | BOOST_CHECK( fs::system_complete( "/" ).string() == "/" ); |
---|
165 | BOOST_CHECK( fs::system_complete( "foo" ).string() |
---|
166 | == fs::initial_path().string()+"/foo" ); |
---|
167 | BOOST_CHECK( fs::system_complete( "/foo" ).string() |
---|
168 | == fs::initial_path().root_path().string()+"foo" ); |
---|
169 | } |
---|
170 | |
---|
171 | fs::path ng( " no-way, Jose", fs::native ); |
---|
172 | |
---|
173 | fs::remove_all( dir ); // in case residue from prior failed tests |
---|
174 | BOOST_CHECK( !fs::exists( dir ) ); |
---|
175 | |
---|
176 | // the bound functions should throw, so throws_fs_error() should return true |
---|
177 | BOOST_CHECK( throws_fs_error( bind( fs::is_directory, ng ), fs::not_found_error ) ); |
---|
178 | BOOST_CHECK( throws_fs_error( bind( fs::file_size, ng ), fs::not_found_error ) ); |
---|
179 | BOOST_CHECK( throws_fs_error( bind( fs::is_directory, dir ) ) ); |
---|
180 | BOOST_CHECK( throws_fs_error( bind( fs::_is_empty, dir ) ) ); |
---|
181 | |
---|
182 | // test path::exception members |
---|
183 | try { fs::is_directory( ng ); } // will throw |
---|
184 | |
---|
185 | catch ( const fs::filesystem_error & ex ) |
---|
186 | { |
---|
187 | BOOST_CHECK( ex.who() == "boost::filesystem::is_directory" ); |
---|
188 | BOOST_CHECK( ex.path1().string() == " no-way, Jose" ); |
---|
189 | } |
---|
190 | |
---|
191 | BOOST_CHECK( fs::create_directory( dir ) ); |
---|
192 | |
---|
193 | BOOST_CHECK( fs::exists( dir ) ); |
---|
194 | BOOST_CHECK( fs::_is_empty( dir ) ); |
---|
195 | BOOST_CHECK( fs::is_directory( dir ) ); |
---|
196 | BOOST_CHECK( throws_fs_error( bind( fs::file_size, dir ), |
---|
197 | fs::is_directory_error ) ); |
---|
198 | BOOST_CHECK( !fs::create_directory( dir ) ); |
---|
199 | |
---|
200 | BOOST_CHECK( !fs::symbolic_link_exists( dir ) ); |
---|
201 | BOOST_CHECK( !fs::symbolic_link_exists( "nosuchfileordirectory" ) ); |
---|
202 | |
---|
203 | fs::path d1( dir / "d1" ); |
---|
204 | BOOST_CHECK( fs::create_directory( d1 ) ); |
---|
205 | BOOST_CHECK( fs::exists( d1 ) ); |
---|
206 | BOOST_CHECK( fs::is_directory( d1 ) ); |
---|
207 | BOOST_CHECK( fs::_is_empty( d1 ) ); |
---|
208 | |
---|
209 | boost::function_requires< boost::InputIteratorConcept< fs::directory_iterator > >(); |
---|
210 | |
---|
211 | { |
---|
212 | fs::directory_iterator dir_itr( dir ); |
---|
213 | BOOST_CHECK( dir_itr->leaf() == "d1" ); |
---|
214 | } |
---|
215 | |
---|
216 | // create a second directory named d2 |
---|
217 | fs::path d2( dir / "d2" ); |
---|
218 | fs::create_directory(d2 ); |
---|
219 | BOOST_CHECK( fs::exists( d2 ) ); |
---|
220 | BOOST_CHECK( fs::is_directory( d2 ) ); |
---|
221 | |
---|
222 | // test the basic operation of directory_iterators, and test that |
---|
223 | // stepping one iterator doesn't affect a different iterator. |
---|
224 | { |
---|
225 | fs::directory_iterator dir_itr( dir ); |
---|
226 | fs::directory_iterator dir_itr2( dir ); |
---|
227 | BOOST_CHECK( dir_itr->leaf() == "d1" || dir_itr->leaf() == "d2" ); |
---|
228 | BOOST_CHECK( dir_itr2->leaf() == "d1" || dir_itr2->leaf() == "d2" ); |
---|
229 | if ( dir_itr->leaf() == "d1" ) |
---|
230 | { |
---|
231 | BOOST_CHECK( (++dir_itr)->leaf() == "d2" ); |
---|
232 | BOOST_CHECK( dir_itr2->leaf() == "d1" ); |
---|
233 | BOOST_CHECK( (++dir_itr2)->leaf() == "d2" ); |
---|
234 | } |
---|
235 | else |
---|
236 | { |
---|
237 | BOOST_CHECK( (dir_itr)->leaf() == "d2" ); |
---|
238 | BOOST_CHECK( (++dir_itr)->leaf() == "d1" ); |
---|
239 | BOOST_CHECK( dir_itr2->leaf() == "d2" ); |
---|
240 | BOOST_CHECK( (++dir_itr2)->leaf() == "d1" ); |
---|
241 | } |
---|
242 | BOOST_CHECK( ++dir_itr == fs::directory_iterator() ); |
---|
243 | BOOST_CHECK( dir_itr2 != fs::directory_iterator() ); |
---|
244 | BOOST_CHECK( ++dir_itr2 == fs::directory_iterator() ); |
---|
245 | } |
---|
246 | |
---|
247 | { // *i++ must work to meet the standard's InputIterator requirements |
---|
248 | fs::directory_iterator dir_itr( dir ); |
---|
249 | BOOST_CHECK( dir_itr->leaf() == "d1" || dir_itr->leaf() == "d2" ); |
---|
250 | if ( dir_itr->leaf() == "d1" ) |
---|
251 | { |
---|
252 | BOOST_CHECK( (*dir_itr++).leaf() == "d1" ); |
---|
253 | BOOST_CHECK( dir_itr->leaf() == "d2" ); |
---|
254 | } |
---|
255 | else |
---|
256 | { |
---|
257 | // Check C++98 input iterator requirements |
---|
258 | BOOST_CHECK( (*dir_itr++).leaf() == "d2" ); |
---|
259 | // input iterator requirements in the current WP would require this check: |
---|
260 | // BOOST_CHECK( implicit_cast<std::string const&>(*dir_itr++).leaf() == "d1" ); |
---|
261 | |
---|
262 | BOOST_CHECK( dir_itr->leaf() == "d1" ); |
---|
263 | } |
---|
264 | } |
---|
265 | |
---|
266 | // create an empty file named "f0" |
---|
267 | fs::path file_ph( dir / "f0"); |
---|
268 | create_file( file_ph, "" ); |
---|
269 | BOOST_CHECK( fs::exists( file_ph ) ); |
---|
270 | BOOST_CHECK( !fs::is_directory( file_ph ) ); |
---|
271 | BOOST_CHECK( fs::_is_empty( file_ph ) ); |
---|
272 | BOOST_CHECK( fs::file_size( file_ph ) == 0 ); |
---|
273 | BOOST_CHECK( throws_fs_error( bind( fs::create_directory, file_ph ), |
---|
274 | fs::not_directory_error ) ); |
---|
275 | |
---|
276 | // create a file named "f1" |
---|
277 | file_ph = dir / "f1"; |
---|
278 | create_file( file_ph, "foobar1" ); |
---|
279 | |
---|
280 | // equivalence tests |
---|
281 | fs::path ng2("does_not_exist2"); |
---|
282 | BOOST_CHECK( throws_fs_error( bind( fs::equivalent, ng, ng2 ) ) ); |
---|
283 | BOOST_CHECK( fs::equivalent( file_ph, dir / "f1" ) ); |
---|
284 | BOOST_CHECK( fs::equivalent( dir, d1 / ".." ) ); |
---|
285 | BOOST_CHECK( !fs::equivalent( file_ph, dir ) ); |
---|
286 | BOOST_CHECK( !fs::equivalent( dir, file_ph ) ); |
---|
287 | BOOST_CHECK( !fs::equivalent( d1, d2 ) ); |
---|
288 | BOOST_CHECK( !fs::equivalent( dir, ng ) ); |
---|
289 | BOOST_CHECK( !fs::equivalent( ng, dir ) ); |
---|
290 | BOOST_CHECK( !fs::equivalent( file_ph, ng ) ); |
---|
291 | BOOST_CHECK( !fs::equivalent( ng, file_ph ) ); |
---|
292 | |
---|
293 | std::time_t ft = fs::last_write_time( file_ph ); |
---|
294 | std::cout << "UTC should currently be about " << std::asctime(std::gmtime(&ft)) << "\n"; |
---|
295 | std::cout << "Local time should currently be about " << std::asctime(std::localtime(&ft)) << std::endl; |
---|
296 | |
---|
297 | // hard to test time exactly, but except under the most unusual circumstances, |
---|
298 | // time since file creation should be no more than one minute, I'm hoping. |
---|
299 | double time_diff = std::difftime( std::time(0), fs::last_write_time( file_ph ) ); |
---|
300 | BOOST_CHECK( time_diff > -60.0 && time_diff < 60.0 ); |
---|
301 | |
---|
302 | BOOST_CHECK( fs::exists( file_ph ) ); |
---|
303 | BOOST_CHECK( !fs::is_directory( file_ph ) ); |
---|
304 | BOOST_CHECK( fs::file_size( file_ph ) == 7 ); |
---|
305 | verify_file( file_ph, "foobar1" ); |
---|
306 | |
---|
307 | std::tm * tmp = std::localtime( &ft ); |
---|
308 | std::cout << "Year is " << tmp->tm_year << std::endl; |
---|
309 | --tmp->tm_year; |
---|
310 | std::cout << "Change year to " << tmp->tm_year << std::endl; |
---|
311 | fs::last_write_time( file_ph, std::mktime( tmp ) ); |
---|
312 | std::cout << "Get new value" << std::endl; |
---|
313 | ft = fs::last_write_time( file_ph ); |
---|
314 | std::cout << "Local time one year ago should currently be about " << std::asctime(std::localtime(&ft)) << "\n"; |
---|
315 | std::cout << "Now get time difference" << std::endl; |
---|
316 | time_diff = std::difftime( std::time(0), fs::last_write_time( file_ph ) ); |
---|
317 | time_diff -= 365*24*3600.0; |
---|
318 | std::cout << "Time difference is : " << time_diff << std::endl; |
---|
319 | BOOST_CHECK( time_diff >= -60.0 && time_diff <= 60.0 ); |
---|
320 | std::cout << "Reset to current time" << std::endl; |
---|
321 | fs::last_write_time( file_ph, std::time(0) ); |
---|
322 | std::cout << "And check that" << std::endl; |
---|
323 | time_diff = std::difftime( std::time(0), fs::last_write_time( file_ph ) ); |
---|
324 | BOOST_CHECK( time_diff >= -60.0 && time_diff <= 60.0 ); |
---|
325 | ft = fs::last_write_time( file_ph ); |
---|
326 | std::cout << "Local time should currently be about " << std::asctime(std::localtime(&ft)) << "\n"; |
---|
327 | |
---|
328 | // there was an inital bug in directory_iterator that caused premature |
---|
329 | // close of an OS handle. This block will detect regression. |
---|
330 | { |
---|
331 | fs::directory_iterator di; |
---|
332 | { di = fs::directory_iterator( dir ); } |
---|
333 | BOOST_CHECK( ++di != fs::directory_iterator() ); |
---|
334 | } |
---|
335 | |
---|
336 | // copy_file() tests |
---|
337 | std::cout << "begin copy_file test..." << std::endl; |
---|
338 | fs::copy_file( file_ph, d1 / "f2" ); |
---|
339 | std::cout << "copying complete" << std::endl; |
---|
340 | BOOST_CHECK( fs::exists( file_ph ) ); |
---|
341 | BOOST_CHECK( fs::exists( d1 / "f2" ) ); |
---|
342 | BOOST_CHECK( !fs::is_directory( d1 / "f2" ) ); |
---|
343 | verify_file( d1 / "f2", "foobar1" ); |
---|
344 | std::cout << "copy_file test complete" << std::endl; |
---|
345 | |
---|
346 | // rename() test case numbers refer to operations.htm#rename table |
---|
347 | |
---|
348 | // [case 1] make sure can't rename() a non-existent file |
---|
349 | BOOST_CHECK( !fs::exists( d1 / "f99" ) ); |
---|
350 | BOOST_CHECK( !fs::exists( d1 / "f98" ) ); |
---|
351 | BOOST_CHECK( throws_fs_error( bind( fs::rename, d1 / "f99", d1 / "f98" ), |
---|
352 | fs::not_found_error ) ); |
---|
353 | BOOST_CHECK( throws_fs_error( bind( fs::rename, fs::path(""), d1 / "f98" ), |
---|
354 | fs::not_found_error ) ); |
---|
355 | |
---|
356 | // [case 2] rename() target.empty() |
---|
357 | BOOST_CHECK( throws_fs_error( bind( fs::rename, file_ph, "" ), |
---|
358 | fs::not_found_error ) ); |
---|
359 | |
---|
360 | // [case 3] make sure can't rename() to an existent file or directory |
---|
361 | BOOST_CHECK( fs::exists( dir / "f1" ) ); |
---|
362 | BOOST_CHECK( fs::exists( d1 / "f2" ) ); |
---|
363 | BOOST_CHECK( throws_fs_error( bind( fs::rename, dir / "f1", d1 / "f2" ) ) ); |
---|
364 | // several POSIX implementations (cygwin, openBSD) report ENOENT instead of EEXIST, |
---|
365 | // so we don't verify error type on the above test. |
---|
366 | BOOST_CHECK( throws_fs_error( bind( fs::rename, dir, d1 ) ) ); |
---|
367 | |
---|
368 | // [case 4A] can't rename() file to a nonexistent parent directory |
---|
369 | BOOST_CHECK( !fs::is_directory( dir / "f1" ) ); |
---|
370 | BOOST_CHECK( !fs::exists( dir / "d3/f3" ) ); |
---|
371 | BOOST_CHECK( throws_fs_error( bind( fs::rename, dir / "f1", dir / "d3/f3" ), |
---|
372 | fs::not_found_error ) ); |
---|
373 | |
---|
374 | // [case 4B] rename() file in same directory |
---|
375 | BOOST_CHECK( fs::exists( d1 / "f2" ) ); |
---|
376 | BOOST_CHECK( !fs::exists( d1 / "f50" ) ); |
---|
377 | fs::rename( d1 / "f2", d1 / "f50" ); |
---|
378 | BOOST_CHECK( !fs::exists( d1 / "f2" ) ); |
---|
379 | BOOST_CHECK( fs::exists( d1 / "f50" ) ); |
---|
380 | fs::rename( d1 / "f50", d1 / "f2" ); |
---|
381 | BOOST_CHECK( fs::exists( d1 / "f2" ) ); |
---|
382 | BOOST_CHECK( !fs::exists( d1 / "f50" ) ); |
---|
383 | |
---|
384 | // [case 4C] rename() file d1/f2 to d2/f3 |
---|
385 | fs::rename( d1 / "f2", d2 / "f3" ); |
---|
386 | BOOST_CHECK( !fs::exists( d1 / "f2" ) ); |
---|
387 | BOOST_CHECK( !fs::exists( d2 / "f2" ) ); |
---|
388 | BOOST_CHECK( fs::exists( d2 / "f3" ) ); |
---|
389 | BOOST_CHECK( !fs::is_directory( d2 / "f3" ) ); |
---|
390 | verify_file( d2 / "f3", "foobar1" ); |
---|
391 | fs::rename( d2 / "f3", d1 / "f2" ); |
---|
392 | BOOST_CHECK( fs::exists( d1 / "f2" ) ); |
---|
393 | |
---|
394 | // [case 5A] rename() directory to nonexistent parent directory |
---|
395 | BOOST_CHECK( fs::exists( d1 ) ); |
---|
396 | BOOST_CHECK( !fs::exists( dir / "d3/d5" ) ); |
---|
397 | BOOST_CHECK( !fs::exists( dir / "d3" ) ); |
---|
398 | BOOST_CHECK( throws_fs_error( bind( fs::rename, d1, dir / "d3/d5" ), |
---|
399 | fs::not_found_error ) ); |
---|
400 | |
---|
401 | // [case 5B] rename() on directory |
---|
402 | fs::path d3( dir / "d3" ); |
---|
403 | BOOST_CHECK( fs::exists( d1 ) ); |
---|
404 | BOOST_CHECK( fs::exists( d1 / "f2" ) ); |
---|
405 | BOOST_CHECK( !fs::exists( d3 ) ); |
---|
406 | fs::rename( d1, d3 ); |
---|
407 | BOOST_CHECK( !fs::exists( d1 ) ); |
---|
408 | BOOST_CHECK( fs::exists( d3 ) ); |
---|
409 | BOOST_CHECK( fs::is_directory( d3 ) ); |
---|
410 | BOOST_CHECK( !fs::exists( d1 / "f2" ) ); |
---|
411 | BOOST_CHECK( fs::exists( d3 / "f2" ) ); |
---|
412 | fs::rename( d3, d1 ); |
---|
413 | BOOST_CHECK( fs::exists( d1 ) ); |
---|
414 | BOOST_CHECK( fs::exists( d1 / "f2" ) ); |
---|
415 | BOOST_CHECK( !fs::exists( d3 ) ); |
---|
416 | |
---|
417 | // [case 5C] rename() rename and move d1 to d2 / "d20" |
---|
418 | BOOST_CHECK( fs::exists( d1 ) ); |
---|
419 | BOOST_CHECK( !fs::exists( d2 / "d20" ) ); |
---|
420 | BOOST_CHECK( fs::exists( d1 / "f2" ) ); |
---|
421 | fs::rename( d1, d2 / "d20" ); |
---|
422 | BOOST_CHECK( !fs::exists( d1 ) ); |
---|
423 | BOOST_CHECK( fs::exists( d2 / "d20" ) ); |
---|
424 | BOOST_CHECK( fs::exists( d2 / "d20" / "f2" ) ); |
---|
425 | fs::rename( d2 / "d20", d1 ); |
---|
426 | BOOST_CHECK( fs::exists( d1 ) ); |
---|
427 | BOOST_CHECK( !fs::exists( d2 / "d20" ) ); |
---|
428 | BOOST_CHECK( fs::exists( d1 / "f2" ) ); |
---|
429 | |
---|
430 | // remove() tests on file |
---|
431 | file_ph = dir / "shortlife"; |
---|
432 | BOOST_CHECK( !fs::exists( file_ph ) ); |
---|
433 | create_file( file_ph, "" ); |
---|
434 | BOOST_CHECK( fs::exists( file_ph ) ); |
---|
435 | BOOST_CHECK( !fs::is_directory( file_ph ) ); |
---|
436 | BOOST_CHECK( fs::remove( file_ph ) ); |
---|
437 | BOOST_CHECK( !fs::exists( file_ph ) ); |
---|
438 | BOOST_CHECK( !fs::remove( "no-such-file" ) ); |
---|
439 | BOOST_CHECK( !fs::remove( "no-such-directory/no-such-file" ) ); |
---|
440 | |
---|
441 | // remove() test on directory |
---|
442 | d1 = dir / "shortlife_dir"; |
---|
443 | BOOST_CHECK( !fs::exists( d1 ) ); |
---|
444 | fs::create_directory( d1 ); |
---|
445 | BOOST_CHECK( fs::exists( d1 ) ); |
---|
446 | BOOST_CHECK( fs::is_directory( d1 ) ); |
---|
447 | BOOST_CHECK( fs::_is_empty( d1 ) ); |
---|
448 | BOOST_CHECK( throws_fs_error( bind( fs::remove, dir ), fs::not_empty_error ) ); |
---|
449 | BOOST_CHECK( fs::remove( d1 ) ); |
---|
450 | BOOST_CHECK( !fs::exists( d1 ) ); |
---|
451 | |
---|
452 | // STLPort is allergic to std::system, so don't use runtime platform test |
---|
453 | # ifdef BOOST_POSIX |
---|
454 | // remove() test on dangling symbolic link |
---|
455 | fs::path link( "dangling_link" ); |
---|
456 | fs::remove( link ); |
---|
457 | BOOST_CHECK( !fs::symbolic_link_exists( link ) ); |
---|
458 | BOOST_CHECK( !fs::exists( link ) ); |
---|
459 | std::system("ln -s nowhere dangling_link"); |
---|
460 | BOOST_CHECK( !fs::exists( link ) ); |
---|
461 | BOOST_CHECK( fs::symbolic_link_exists( link ) ); |
---|
462 | BOOST_CHECK( fs::remove( link ) ); |
---|
463 | BOOST_CHECK( !fs::symbolic_link_exists( link ) ); |
---|
464 | |
---|
465 | // remove() test on symbolic link to a file |
---|
466 | file_ph = "link_target"; |
---|
467 | fs::remove( file_ph ); |
---|
468 | BOOST_CHECK( !fs::exists( file_ph ) ); |
---|
469 | create_file( file_ph, "" ); |
---|
470 | BOOST_CHECK( fs::exists( file_ph ) ); |
---|
471 | BOOST_CHECK( !fs::is_directory( file_ph ) ); |
---|
472 | std::system("ln -s link_target non_dangling_link"); |
---|
473 | link = "non_dangling_link"; |
---|
474 | BOOST_CHECK( fs::exists( link ) ); |
---|
475 | BOOST_CHECK( !fs::is_directory( link ) ); |
---|
476 | BOOST_CHECK( fs::symbolic_link_exists( link ) ); |
---|
477 | BOOST_CHECK( fs::remove( link ) ); |
---|
478 | BOOST_CHECK( fs::exists( file_ph ) ); |
---|
479 | BOOST_CHECK( !fs::exists( link ) ); |
---|
480 | BOOST_CHECK( !fs::symbolic_link_exists( link ) ); |
---|
481 | BOOST_CHECK( fs::remove( file_ph ) ); |
---|
482 | BOOST_CHECK( !fs::exists( file_ph ) ); |
---|
483 | } |
---|
484 | # endif |
---|
485 | |
---|
486 | // post-test cleanup |
---|
487 | BOOST_CHECK( fs::remove_all( dir ) != 0 ); |
---|
488 | // above was added just to simplify testing, but it ended up detecting |
---|
489 | // a bug (failure to close an internal search handle). |
---|
490 | BOOST_CHECK( !fs::exists( dir ) ); |
---|
491 | BOOST_CHECK( fs::remove_all( dir ) == 0 ); |
---|
492 | |
---|
493 | return 0; |
---|
494 | } // main |
---|
495 | |
---|