| 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 | // VC++ 8.0 warns on various less-than-safe practices. |
|---|
| 11 | // See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx |
|---|
| 12 | // But at least in VC++ 8.0 betas, their own libraries use the problem |
|---|
| 13 | // practices. So turn off the warnings. |
|---|
| 14 | #define _CRT_SECURE_NO_DEPRECATE |
|---|
| 15 | #define _SCL_SECURE_NO_DEPRECATE |
|---|
| 16 | |
|---|
| 17 | #include <boost/filesystem/operations.hpp> |
|---|
| 18 | #include <boost/filesystem/convenience.hpp> |
|---|
| 19 | #include <boost/filesystem/cerrno.hpp> |
|---|
| 20 | namespace fs = boost::filesystem; |
|---|
| 21 | |
|---|
| 22 | #include <boost/config.hpp> |
|---|
| 23 | #include <boost/test/minimal.hpp> |
|---|
| 24 | #include <boost/concept_check.hpp> |
|---|
| 25 | #include <boost/bind.hpp> |
|---|
| 26 | using boost::bind; |
|---|
| 27 | |
|---|
| 28 | #include <fstream> |
|---|
| 29 | #include <iostream> |
|---|
| 30 | #include <string> |
|---|
| 31 | #include <ctime> |
|---|
| 32 | #include <cstdlib> // for system() |
|---|
| 33 | |
|---|
| 34 | #ifndef BOOST_FILESYSTEM_NARROW_ONLY |
|---|
| 35 | # define BOOST_BND(BOOST_FUNC_TO_DO) BOOST_FUNC_TO_DO<fs::path> |
|---|
| 36 | #else |
|---|
| 37 | # define BOOST_BND(BOOST_FUNC_TO_DO) BOOST_FUNC_TO_DO |
|---|
| 38 | #endif |
|---|
| 39 | |
|---|
| 40 | // VC++ 7.0 and earlier has a serious namespace bug that causes a clash |
|---|
| 41 | // between boost::filesystem::is_empty and the unrelated type trait |
|---|
| 42 | // boost::is_empty. |
|---|
| 43 | #if !defined( BOOST_MSVC ) || BOOST_MSVC > 1300 |
|---|
| 44 | # define BOOST_FS_IS_EMPTY fs::is_empty |
|---|
| 45 | #else |
|---|
| 46 | # define BOOST_FS_IS_EMPTY fs::_is_empty |
|---|
| 47 | #endif |
|---|
| 48 | |
|---|
| 49 | # ifdef BOOST_NO_STDC_NAMESPACE |
|---|
| 50 | namespace std { using ::asctime; using ::gmtime; using ::localtime; |
|---|
| 51 | using ::difftime; using ::time; using ::tm; using ::mktime; using ::system; } |
|---|
| 52 | # endif |
|---|
| 53 | |
|---|
| 54 | #define CHECK_EXCEPTION(b,e) throws_fs_error(b,e,__LINE__) |
|---|
| 55 | |
|---|
| 56 | namespace |
|---|
| 57 | { |
|---|
| 58 | bool report_throws; |
|---|
| 59 | fs::directory_iterator end_itr; |
|---|
| 60 | |
|---|
| 61 | const char * temp_dir_name = "temp_fs_test_dir"; |
|---|
| 62 | |
|---|
| 63 | void create_file( const fs::path & ph, const std::string & contents ) |
|---|
| 64 | { |
|---|
| 65 | std::ofstream f( ph.file_string().c_str() ); |
|---|
| 66 | if ( !f ) |
|---|
| 67 | throw fs::filesystem_path_error( "operations_test create_file", |
|---|
| 68 | ph, errno ); |
|---|
| 69 | if ( !contents.empty() ) f << contents; |
|---|
| 70 | } |
|---|
| 71 | |
|---|
| 72 | void verify_file( const fs::path & ph, const std::string & expected ) |
|---|
| 73 | { |
|---|
| 74 | std::ifstream f( ph.file_string().c_str() ); |
|---|
| 75 | if ( !f ) |
|---|
| 76 | throw fs::filesystem_path_error( "operations_test verify_file", |
|---|
| 77 | ph, errno ); |
|---|
| 78 | std::string contents; |
|---|
| 79 | f >> contents; |
|---|
| 80 | if ( contents != expected ) |
|---|
| 81 | throw fs::filesystem_path_error( "operations_test verify_file contents \"" |
|---|
| 82 | + contents + "\" != \"" + expected + "\"", ph, 0 ); |
|---|
| 83 | } |
|---|
| 84 | |
|---|
| 85 | template< typename F > |
|---|
| 86 | bool throws_fs_error( F func, fs::errno_type ec, int line ) |
|---|
| 87 | { |
|---|
| 88 | try { func(); } |
|---|
| 89 | |
|---|
| 90 | catch ( const fs::filesystem_path_error & ex ) |
|---|
| 91 | { |
|---|
| 92 | if ( report_throws ) |
|---|
| 93 | { |
|---|
| 94 | // use the what() convenience function to display exceptions |
|---|
| 95 | std::cout << fs::what(ex) << "\n"; |
|---|
| 96 | } |
|---|
| 97 | if ( ec == 0 |
|---|
| 98 | || ec == fs::lookup_error_code(ex.system_error()) ) return true; |
|---|
| 99 | std::cout |
|---|
| 100 | << "\nWarning: line " << line |
|---|
| 101 | << " exception reports " << fs::lookup_error_code(ex.system_error()) |
|---|
| 102 | << ", should be " << ec |
|---|
| 103 | << "\n system_error() is " << ex.system_error() |
|---|
| 104 | << std::endl; |
|---|
| 105 | return true; |
|---|
| 106 | } |
|---|
| 107 | return false; |
|---|
| 108 | } |
|---|
| 109 | |
|---|
| 110 | // compile-only two argument "do-the-right-thing" tests |
|---|
| 111 | // verifies that all overload combinations compile without error |
|---|
| 112 | void do_not_call() |
|---|
| 113 | { |
|---|
| 114 | fs::path p; |
|---|
| 115 | std::string s; |
|---|
| 116 | const char * a = 0; |
|---|
| 117 | fs::copy_file( p, p ); |
|---|
| 118 | fs::copy_file( s, p ); |
|---|
| 119 | fs::copy_file( a, p ); |
|---|
| 120 | fs::copy_file( p, s ); |
|---|
| 121 | fs::copy_file( p, a ); |
|---|
| 122 | fs::copy_file( s, s ); |
|---|
| 123 | fs::copy_file( a, s ); |
|---|
| 124 | fs::copy_file( s, a ); |
|---|
| 125 | fs::copy_file( a, a ); |
|---|
| 126 | } |
|---|
| 127 | |
|---|
| 128 | } // unnamed namespace |
|---|
| 129 | |
|---|
| 130 | // test_main ---------------------------------------------------------------// |
|---|
| 131 | |
|---|
| 132 | int test_main( int argc, char * argv[] ) |
|---|
| 133 | { |
|---|
| 134 | if ( argc > 1 && *argv[1]=='-' && *(argv[1]+1)=='t' ) report_throws = true; |
|---|
| 135 | |
|---|
| 136 | std::string platform( BOOST_PLATFORM ); |
|---|
| 137 | |
|---|
| 138 | // The choice of platform is make at runtime rather than compile-time |
|---|
| 139 | // so that compile errors for all platforms will be detected even though |
|---|
| 140 | // only the current platform is runtime tested. |
|---|
| 141 | # if defined( BOOST_POSIX_API ) |
|---|
| 142 | platform = "POSIX"; |
|---|
| 143 | # elif defined( BOOST_WINDOWS_API ) |
|---|
| 144 | platform = "Windows"; |
|---|
| 145 | # else |
|---|
| 146 | platform = ( platform == "Win32" || platform == "Win64" || platform == "Cygwin" ) |
|---|
| 147 | ? "Windows" |
|---|
| 148 | : "POSIX"; |
|---|
| 149 | # endif |
|---|
| 150 | std::cout << "API is " << platform << '\n'; |
|---|
| 151 | |
|---|
| 152 | std::cout << "\ninitial_path<path>().string() is\n \"" |
|---|
| 153 | << fs::initial_path<fs::path>().string() |
|---|
| 154 | << "\"\n"; |
|---|
| 155 | std::cout << "\ninitial_path<fs::path>().file_string() is\n \"" |
|---|
| 156 | << fs::initial_path<fs::path>().file_string() |
|---|
| 157 | << "\"\n\n"; |
|---|
| 158 | BOOST_CHECK( fs::initial_path<fs::path>().is_complete() ); |
|---|
| 159 | BOOST_CHECK( fs::current_path<fs::path>().is_complete() ); |
|---|
| 160 | BOOST_CHECK( fs::initial_path<fs::path>().string() |
|---|
| 161 | == fs::current_path<fs::path>().string() ); |
|---|
| 162 | |
|---|
| 163 | BOOST_CHECK( fs::complete( "" ).empty() ); |
|---|
| 164 | BOOST_CHECK( fs::complete( "/" ).string() == fs::initial_path<fs::path>().root_path().string() ); |
|---|
| 165 | BOOST_CHECK( fs::complete( "foo" ).string() == fs::initial_path<fs::path>().string()+"/foo" ); |
|---|
| 166 | BOOST_CHECK( fs::complete( "/foo" ).string() == fs::initial_path<fs::path>().root_path().string()+"foo" ); |
|---|
| 167 | BOOST_CHECK( fs::complete( "foo", fs::path( "//net/bar" ) ).string() |
|---|
| 168 | == "//net/bar/foo" ); |
|---|
| 169 | |
|---|
| 170 | // predicate and status tests |
|---|
| 171 | fs::path ng( " no-way, Jose" ); |
|---|
| 172 | BOOST_CHECK( !fs::exists( ng ) ); |
|---|
| 173 | BOOST_CHECK( !fs::is_directory( ng ) ); |
|---|
| 174 | BOOST_CHECK( !fs::is_regular( ng ) ); |
|---|
| 175 | BOOST_CHECK( !fs::is_symlink( ng ) ); |
|---|
| 176 | fs::file_status stat( fs::status( ng ) ); |
|---|
| 177 | BOOST_CHECK( fs::status_known( stat ) ); |
|---|
| 178 | BOOST_CHECK( !fs::exists( stat ) ); |
|---|
| 179 | BOOST_CHECK( !fs::is_directory( stat ) ); |
|---|
| 180 | BOOST_CHECK( !fs::is_regular( stat ) ); |
|---|
| 181 | BOOST_CHECK( !fs::is_other( stat ) ); |
|---|
| 182 | BOOST_CHECK( !fs::is_symlink( stat ) ); |
|---|
| 183 | stat = fs::status( "" ); |
|---|
| 184 | BOOST_CHECK( fs::status_known( stat ) ); |
|---|
| 185 | BOOST_CHECK( !fs::exists( stat ) ); |
|---|
| 186 | BOOST_CHECK( !fs::is_directory( stat ) ); |
|---|
| 187 | BOOST_CHECK( !fs::is_regular( stat ) ); |
|---|
| 188 | BOOST_CHECK( !fs::is_other( stat ) ); |
|---|
| 189 | BOOST_CHECK( !fs::is_symlink( stat ) ); |
|---|
| 190 | |
|---|
| 191 | fs::path dir( fs::initial_path<fs::path>() / temp_dir_name ); |
|---|
| 192 | |
|---|
| 193 | // Windows only tests |
|---|
| 194 | if ( platform == "Windows" ) |
|---|
| 195 | { |
|---|
| 196 | BOOST_CHECK( !fs::exists( fs::path( "//share-not" ) ) ); |
|---|
| 197 | BOOST_CHECK( !fs::exists( fs::path( "//share-not/" ) ) ); |
|---|
| 198 | BOOST_CHECK( !fs::exists( fs::path( "//share-not/foo" ) ) ); |
|---|
| 199 | BOOST_CHECK( !fs::exists( "tools/jam/src/:sys:stat.h" ) ); // !exists() if ERROR_INVALID_NAME |
|---|
| 200 | BOOST_CHECK( !fs::exists( ":sys:stat.h" ) ); // !exists() if ERROR_INVALID_PARAMETER |
|---|
| 201 | BOOST_CHECK( dir.string().size() > 1 |
|---|
| 202 | && dir.string()[1] == ':' ); // verify path includes drive |
|---|
| 203 | |
|---|
| 204 | BOOST_CHECK( fs::system_complete( "" ).empty() ); |
|---|
| 205 | BOOST_CHECK( fs::system_complete( "/" ).string() |
|---|
| 206 | == fs::initial_path<fs::path>().root_path().string() ); |
|---|
| 207 | BOOST_CHECK( fs::system_complete( "foo" ).string() |
|---|
| 208 | == fs::initial_path<fs::path>().string()+"/foo" ); |
|---|
| 209 | BOOST_CHECK( fs::system_complete( "/foo" ).string() |
|---|
| 210 | == fs::initial_path<fs::path>().root_path().string()+"foo" ); |
|---|
| 211 | BOOST_CHECK( fs::complete( fs::path( "c:/" ) ).string() |
|---|
| 212 | == "c:/" ); |
|---|
| 213 | BOOST_CHECK( fs::complete( fs::path( "c:/foo" ) ).string() |
|---|
| 214 | == "c:/foo" ); |
|---|
| 215 | |
|---|
| 216 | BOOST_CHECK( fs::system_complete( fs::path( fs::initial_path<fs::path>().root_name() ) ).string() == fs::initial_path<fs::path>().string() ); |
|---|
| 217 | BOOST_CHECK( fs::system_complete( fs::path( fs::initial_path<fs::path>().root_name() |
|---|
| 218 | + "foo" ) ).string() == fs::initial_path<fs::path>().string()+"/foo" ); |
|---|
| 219 | BOOST_CHECK( fs::system_complete( fs::path( "c:/" ) ).string() |
|---|
| 220 | == "c:/" ); |
|---|
| 221 | BOOST_CHECK( fs::system_complete( fs::path( "c:/foo" ) ).string() |
|---|
| 222 | == "c:/foo" ); |
|---|
| 223 | BOOST_CHECK( fs::system_complete( fs::path( "//share" ) ).string() |
|---|
| 224 | == "//share" ); |
|---|
| 225 | } // Windows |
|---|
| 226 | |
|---|
| 227 | else if ( platform == "POSIX" ) |
|---|
| 228 | { |
|---|
| 229 | BOOST_CHECK( fs::system_complete( "" ).empty() ); |
|---|
| 230 | BOOST_CHECK( fs::initial_path<fs::path>().root_path().string() == "/" ); |
|---|
| 231 | BOOST_CHECK( fs::system_complete( "/" ).string() == "/" ); |
|---|
| 232 | BOOST_CHECK( fs::system_complete( "foo" ).string() |
|---|
| 233 | == fs::initial_path<fs::path>().string()+"/foo" ); |
|---|
| 234 | BOOST_CHECK( fs::system_complete( "/foo" ).string() |
|---|
| 235 | == fs::initial_path<fs::path>().root_path().string()+"foo" ); |
|---|
| 236 | } // POSIX |
|---|
| 237 | |
|---|
| 238 | fs::remove_all( dir ); // in case residue from prior failed tests |
|---|
| 239 | BOOST_CHECK( !fs::exists( dir ) ); |
|---|
| 240 | |
|---|
| 241 | // the bound functions should throw, so CHECK_EXCEPTION() should return true |
|---|
| 242 | BOOST_CHECK( CHECK_EXCEPTION( bind( BOOST_BND(fs::file_size), ng ), ENOENT ) ); |
|---|
| 243 | |
|---|
| 244 | // test path::exception members |
|---|
| 245 | try { fs::file_size( ng ); } // will throw |
|---|
| 246 | |
|---|
| 247 | catch ( const fs::filesystem_path_error & ex ) |
|---|
| 248 | { |
|---|
| 249 | BOOST_CHECK( ex.path1().string() == " no-way, Jose" ); |
|---|
| 250 | } |
|---|
| 251 | |
|---|
| 252 | BOOST_CHECK( fs::create_directory( dir ) ); |
|---|
| 253 | |
|---|
| 254 | // several functions give unreasonable results if uintmax_t isn't 64-bits |
|---|
| 255 | std::cout << "sizeof(boost::uintmax_t) = " << sizeof(boost::uintmax_t) << '\n'; |
|---|
| 256 | BOOST_CHECK( sizeof( boost::uintmax_t ) >= 8 ); |
|---|
| 257 | |
|---|
| 258 | // make some reasonable assuptions for testing purposes |
|---|
| 259 | fs::space_info spi( fs::space( dir ) ); |
|---|
| 260 | BOOST_CHECK( spi.capacity > 1000000 ); |
|---|
| 261 | BOOST_CHECK( spi.free > 1000 ); |
|---|
| 262 | BOOST_CHECK( spi.capacity > spi.free ); |
|---|
| 263 | BOOST_CHECK( spi.free >= spi.available ); |
|---|
| 264 | |
|---|
| 265 | // it is convenient to display space, but older VC++ versions choke |
|---|
| 266 | # if !defined(BOOST_MSVC) || _MSC_VER >= 1300 // 1300 == VC++ 7.0 |
|---|
| 267 | std::cout << " capacity = " << spi.capacity << '\n'; |
|---|
| 268 | std::cout << " free = " << spi.free << '\n'; |
|---|
| 269 | std::cout << "available = " << spi.available << '\n'; |
|---|
| 270 | # endif |
|---|
| 271 | |
|---|
| 272 | BOOST_CHECK( fs::exists( dir ) ); |
|---|
| 273 | BOOST_CHECK( BOOST_FS_IS_EMPTY( dir ) ); |
|---|
| 274 | BOOST_CHECK( fs::is_directory( dir ) ); |
|---|
| 275 | BOOST_CHECK( !fs::is_regular( dir ) ); |
|---|
| 276 | BOOST_CHECK( !fs::is_other( dir ) ); |
|---|
| 277 | BOOST_CHECK( !fs::is_symlink( dir ) ); |
|---|
| 278 | stat = fs::status( dir ); |
|---|
| 279 | BOOST_CHECK( fs::exists( stat ) ); |
|---|
| 280 | BOOST_CHECK( fs::is_directory( stat ) ); |
|---|
| 281 | BOOST_CHECK( !fs::is_regular( stat ) ); |
|---|
| 282 | BOOST_CHECK( !fs::is_other( stat ) ); |
|---|
| 283 | BOOST_CHECK( !fs::is_symlink( stat ) ); |
|---|
| 284 | |
|---|
| 285 | if ( platform == "Windows" ) |
|---|
| 286 | BOOST_CHECK( CHECK_EXCEPTION( bind( BOOST_BND(fs::file_size), dir ), |
|---|
| 287 | ENOENT ) ); |
|---|
| 288 | else |
|---|
| 289 | BOOST_CHECK( CHECK_EXCEPTION( bind( BOOST_BND(fs::file_size), dir ), 0 ) ); |
|---|
| 290 | BOOST_CHECK( !fs::create_directory( dir ) ); |
|---|
| 291 | |
|---|
| 292 | BOOST_CHECK( !fs::is_symlink( dir ) ); |
|---|
| 293 | BOOST_CHECK( !fs::is_symlink( "nosuchfileordirectory" ) ); |
|---|
| 294 | |
|---|
| 295 | BOOST_CHECK( !fs::symbolic_link_exists( dir ) ); |
|---|
| 296 | BOOST_CHECK( !fs::symbolic_link_exists( "nosuchfileordirectory" ) ); |
|---|
| 297 | |
|---|
| 298 | fs::path d1( dir / "d1" ); |
|---|
| 299 | BOOST_CHECK( fs::create_directory( d1 ) ); |
|---|
| 300 | BOOST_CHECK( fs::exists( d1 ) ); |
|---|
| 301 | BOOST_CHECK( fs::is_directory( d1 ) ); |
|---|
| 302 | BOOST_CHECK( BOOST_FS_IS_EMPTY( d1 ) ); |
|---|
| 303 | |
|---|
| 304 | boost::function_requires< boost::InputIteratorConcept< fs::directory_iterator > >(); |
|---|
| 305 | |
|---|
| 306 | bool dir_itr_exception(false); |
|---|
| 307 | try { fs::directory_iterator it( "" ); } |
|---|
| 308 | catch ( const fs::filesystem_error & ) { dir_itr_exception = true; } |
|---|
| 309 | BOOST_CHECK( dir_itr_exception ); |
|---|
| 310 | |
|---|
| 311 | dir_itr_exception = false; |
|---|
| 312 | try { fs::directory_iterator it( "nosuchdirectory" ); } |
|---|
| 313 | catch ( const fs::filesystem_error & ) { dir_itr_exception = true; } |
|---|
| 314 | BOOST_CHECK( dir_itr_exception ); |
|---|
| 315 | |
|---|
| 316 | dir_itr_exception = false; |
|---|
| 317 | try |
|---|
| 318 | { |
|---|
| 319 | fs::system_error_type ec(0); |
|---|
| 320 | fs::directory_iterator it( "nosuchdirectory", ec ); |
|---|
| 321 | BOOST_CHECK( ec != 0 ); |
|---|
| 322 | BOOST_CHECK( ec == fs::detail::not_found_error ); |
|---|
| 323 | } |
|---|
| 324 | catch ( const fs::filesystem_error & ) { dir_itr_exception = true; } |
|---|
| 325 | BOOST_CHECK( !dir_itr_exception ); |
|---|
| 326 | |
|---|
| 327 | { |
|---|
| 328 | // probe query function overloads |
|---|
| 329 | fs::directory_iterator dir_itr( dir ); |
|---|
| 330 | BOOST_CHECK( fs::is_directory( *dir_itr ) ); |
|---|
| 331 | BOOST_CHECK( fs::is_directory( dir_itr->status() ) ); |
|---|
| 332 | BOOST_CHECK( fs::is_directory( fs::symlink_status(*dir_itr) ) ); |
|---|
| 333 | BOOST_CHECK( fs::is_directory( dir_itr->symlink_status() ) ); |
|---|
| 334 | BOOST_CHECK( dir_itr->leaf() == "d1" ); |
|---|
| 335 | } |
|---|
| 336 | |
|---|
| 337 | // create a second directory named d2 |
|---|
| 338 | fs::path d2( dir / "d2" ); |
|---|
| 339 | fs::create_directory(d2 ); |
|---|
| 340 | BOOST_CHECK( fs::exists( d2 ) ); |
|---|
| 341 | BOOST_CHECK( fs::is_directory( d2 ) ); |
|---|
| 342 | |
|---|
| 343 | // test the basic operation of directory_iterators, and test that |
|---|
| 344 | // stepping one iterator doesn't affect a different iterator. |
|---|
| 345 | { |
|---|
| 346 | fs::directory_iterator dir_itr( dir ); |
|---|
| 347 | BOOST_CHECK( fs::exists(dir_itr->status()) ); |
|---|
| 348 | BOOST_CHECK( fs::is_directory(dir_itr->status()) ); |
|---|
| 349 | BOOST_CHECK( !fs::is_regular(dir_itr->status()) ); |
|---|
| 350 | BOOST_CHECK( !fs::is_other(dir_itr->status()) ); |
|---|
| 351 | BOOST_CHECK( !fs::is_symlink(dir_itr->status()) ); |
|---|
| 352 | |
|---|
| 353 | fs::directory_iterator dir_itr2( dir ); |
|---|
| 354 | BOOST_CHECK( dir_itr->leaf() == "d1" |
|---|
| 355 | || dir_itr->leaf() == "d2" ); |
|---|
| 356 | BOOST_CHECK( dir_itr2->leaf() == "d1" || dir_itr2->leaf() == "d2" ); |
|---|
| 357 | if ( dir_itr->leaf() == "d1" ) |
|---|
| 358 | { |
|---|
| 359 | BOOST_CHECK( (++dir_itr)->leaf() == "d2" ); |
|---|
| 360 | BOOST_CHECK( dir_itr2->leaf() == "d1" ); |
|---|
| 361 | BOOST_CHECK( (++dir_itr2)->leaf() == "d2" ); |
|---|
| 362 | } |
|---|
| 363 | else |
|---|
| 364 | { |
|---|
| 365 | BOOST_CHECK( dir_itr->leaf() == "d2" ); |
|---|
| 366 | BOOST_CHECK( (++dir_itr)->leaf() == "d1" ); |
|---|
| 367 | BOOST_CHECK( (dir_itr2)->leaf() == "d2" ); |
|---|
| 368 | BOOST_CHECK( (++dir_itr2)->leaf() == "d1" ); |
|---|
| 369 | } |
|---|
| 370 | BOOST_CHECK( ++dir_itr == fs::directory_iterator() ); |
|---|
| 371 | BOOST_CHECK( dir_itr2 != fs::directory_iterator() ); |
|---|
| 372 | BOOST_CHECK( ++dir_itr2 == fs::directory_iterator() ); |
|---|
| 373 | } |
|---|
| 374 | |
|---|
| 375 | { // *i++ must work to meet the standard's InputIterator requirements |
|---|
| 376 | fs::directory_iterator dir_itr( dir ); |
|---|
| 377 | BOOST_CHECK( dir_itr->leaf() == "d1" |
|---|
| 378 | || dir_itr->leaf() == "d2" ); |
|---|
| 379 | if ( dir_itr->leaf() == "d1" ) |
|---|
| 380 | { |
|---|
| 381 | BOOST_CHECK( (*dir_itr++).leaf() == "d1" ); |
|---|
| 382 | BOOST_CHECK( dir_itr->leaf() == "d2" ); |
|---|
| 383 | } |
|---|
| 384 | else |
|---|
| 385 | { |
|---|
| 386 | // Check C++98 input iterator requirements |
|---|
| 387 | BOOST_CHECK( (*dir_itr++).leaf() == "d2" ); |
|---|
| 388 | // input iterator requirements in the current WP would require this check: |
|---|
| 389 | // BOOST_CHECK( implicit_cast<std::string const&>(*dir_itr++).leaf() == "d1" ); |
|---|
| 390 | |
|---|
| 391 | BOOST_CHECK( dir_itr->leaf() == "d1" ); |
|---|
| 392 | } |
|---|
| 393 | |
|---|
| 394 | // test case reported in comment to SourceForge bug tracker [937606] |
|---|
| 395 | fs::directory_iterator it( dir ); |
|---|
| 396 | const fs::path p1 = *it++; |
|---|
| 397 | BOOST_CHECK( it != fs::directory_iterator() ); |
|---|
| 398 | const fs::path p2 = *it++; |
|---|
| 399 | BOOST_CHECK( p1 != p2 ); |
|---|
| 400 | BOOST_CHECK( it == fs::directory_iterator() ); |
|---|
| 401 | } |
|---|
| 402 | |
|---|
| 403 | // Windows has a tricky special case when just the root-name is given, |
|---|
| 404 | // causing the rest of the path to default to the current directory. |
|---|
| 405 | // Reported as S/F bug [ 1259176 ] |
|---|
| 406 | if ( platform == "Windows" ) |
|---|
| 407 | { |
|---|
| 408 | fs::path root_name_path( fs::current_path<fs::path>().root_name() ); |
|---|
| 409 | fs::directory_iterator it( root_name_path ); |
|---|
| 410 | BOOST_CHECK( it != fs::directory_iterator() ); |
|---|
| 411 | BOOST_CHECK( fs::exists( *it ) ); |
|---|
| 412 | BOOST_CHECK( it->path().branch_path() == root_name_path ); |
|---|
| 413 | bool found(false); |
|---|
| 414 | do |
|---|
| 415 | { |
|---|
| 416 | if ( it->leaf() == temp_dir_name ) found = true; |
|---|
| 417 | } while ( ++it != fs::directory_iterator() ); |
|---|
| 418 | BOOST_CHECK( found ); |
|---|
| 419 | } |
|---|
| 420 | |
|---|
| 421 | // create an empty file named "f0" |
|---|
| 422 | fs::path file_ph( dir / "f0"); |
|---|
| 423 | create_file( file_ph, "" ); |
|---|
| 424 | BOOST_CHECK( fs::exists( file_ph ) ); |
|---|
| 425 | BOOST_CHECK( !fs::is_directory( file_ph ) ); |
|---|
| 426 | BOOST_CHECK( fs::is_regular( file_ph ) ); |
|---|
| 427 | BOOST_CHECK( BOOST_FS_IS_EMPTY( file_ph ) ); |
|---|
| 428 | BOOST_CHECK( fs::file_size( file_ph ) == 0 ); |
|---|
| 429 | BOOST_CHECK( CHECK_EXCEPTION( bind( BOOST_BND(fs::create_directory), |
|---|
| 430 | file_ph ), EEXIST ) ); |
|---|
| 431 | stat = fs::status( file_ph ); |
|---|
| 432 | BOOST_CHECK( fs::status_known( stat ) ); |
|---|
| 433 | BOOST_CHECK( fs::exists( stat ) ); |
|---|
| 434 | BOOST_CHECK( !fs::is_directory( stat ) ); |
|---|
| 435 | BOOST_CHECK( fs::is_regular( stat ) ); |
|---|
| 436 | BOOST_CHECK( !fs::is_other( stat ) ); |
|---|
| 437 | BOOST_CHECK( !fs::is_symlink( stat ) ); |
|---|
| 438 | |
|---|
| 439 | // create a file named "f1" |
|---|
| 440 | file_ph = dir / "f1"; |
|---|
| 441 | create_file( file_ph, "foobar1" ); |
|---|
| 442 | |
|---|
| 443 | BOOST_CHECK( fs::exists( file_ph ) ); |
|---|
| 444 | BOOST_CHECK( !fs::is_directory( file_ph ) ); |
|---|
| 445 | BOOST_CHECK( fs::is_regular( file_ph ) ); |
|---|
| 446 | BOOST_CHECK( fs::file_size( file_ph ) == 7 ); |
|---|
| 447 | verify_file( file_ph, "foobar1" ); |
|---|
| 448 | |
|---|
| 449 | // equivalence tests |
|---|
| 450 | fs::path ng2("does_not_exist2"); |
|---|
| 451 | BOOST_CHECK( CHECK_EXCEPTION( |
|---|
| 452 | bind( BOOST_BND(fs::equivalent), ng, ng2 ), ENOENT ) ); |
|---|
| 453 | BOOST_CHECK( fs::equivalent( file_ph, dir / "f1" ) ); |
|---|
| 454 | BOOST_CHECK( fs::equivalent( dir, d1 / ".." ) ); |
|---|
| 455 | BOOST_CHECK( !fs::equivalent( file_ph, dir ) ); |
|---|
| 456 | BOOST_CHECK( !fs::equivalent( dir, file_ph ) ); |
|---|
| 457 | BOOST_CHECK( !fs::equivalent( d1, d2 ) ); |
|---|
| 458 | BOOST_CHECK( !fs::equivalent( dir, ng ) ); |
|---|
| 459 | BOOST_CHECK( !fs::equivalent( ng, dir ) ); |
|---|
| 460 | BOOST_CHECK( !fs::equivalent( file_ph, ng ) ); |
|---|
| 461 | BOOST_CHECK( !fs::equivalent( ng, file_ph ) ); |
|---|
| 462 | |
|---|
| 463 | // hard link tests |
|---|
| 464 | fs::path from_ph( dir / "f3" ); |
|---|
| 465 | BOOST_CHECK( !fs::exists( from_ph ) ); |
|---|
| 466 | BOOST_CHECK( fs::exists( file_ph ) ); |
|---|
| 467 | bool create_hard_link_ok(true); |
|---|
| 468 | try { fs::create_hard_link( file_ph, from_ph ); } |
|---|
| 469 | catch ( const fs::filesystem_error & ex ) |
|---|
| 470 | { |
|---|
| 471 | create_hard_link_ok = false; |
|---|
| 472 | std::cout |
|---|
| 473 | << "create_hard_link() attempt failed\n" |
|---|
| 474 | << "filesystem_error.what() reports: " << ex.what() << '\n' |
|---|
| 475 | << "create_hard_link() may not be supported on this file system\n"; |
|---|
| 476 | } |
|---|
| 477 | |
|---|
| 478 | if ( create_hard_link_ok ) |
|---|
| 479 | { |
|---|
| 480 | std::cout << "create_hard_link() succeeded\n"; |
|---|
| 481 | BOOST_CHECK( fs::exists( from_ph ) ); |
|---|
| 482 | BOOST_CHECK( fs::exists( file_ph ) ); |
|---|
| 483 | BOOST_CHECK( fs::equivalent( from_ph, file_ph ) ); |
|---|
| 484 | } |
|---|
| 485 | |
|---|
| 486 | fs::system_error_type ec(0); |
|---|
| 487 | BOOST_CHECK( fs::create_hard_link( fs::path("doesnotexist"), |
|---|
| 488 | fs::path("shouldnotwork"), ec ) != 0 ); |
|---|
| 489 | BOOST_CHECK( ec != 0 ); |
|---|
| 490 | |
|---|
| 491 | // symbolic link tests |
|---|
| 492 | from_ph = dir / "f4"; |
|---|
| 493 | BOOST_CHECK( !fs::exists( from_ph ) ); |
|---|
| 494 | BOOST_CHECK( fs::exists( file_ph ) ); |
|---|
| 495 | bool create_symlink_ok(true); |
|---|
| 496 | try { fs::create_symlink( file_ph, from_ph ); } |
|---|
| 497 | catch ( const fs::filesystem_error & ex ) |
|---|
| 498 | { |
|---|
| 499 | create_symlink_ok = false; |
|---|
| 500 | std::cout |
|---|
| 501 | << "create_symlink() attempt failed\n" |
|---|
| 502 | << "filesystem_error.what() reports: " << ex.what() << '\n' |
|---|
| 503 | << "create_symlink() may not be supported on this file system\n"; |
|---|
| 504 | } |
|---|
| 505 | |
|---|
| 506 | if ( create_symlink_ok ) |
|---|
| 507 | { |
|---|
| 508 | std::cout << "create_symlink() succeeded\n"; |
|---|
| 509 | BOOST_CHECK( fs::exists( from_ph ) ); |
|---|
| 510 | BOOST_CHECK( fs::is_symlink( from_ph ) ); |
|---|
| 511 | BOOST_CHECK( fs::exists( file_ph ) ); |
|---|
| 512 | BOOST_CHECK( fs::equivalent( from_ph, file_ph ) ); |
|---|
| 513 | stat = fs::symlink_status( from_ph ); |
|---|
| 514 | BOOST_CHECK( fs::exists( stat ) ); |
|---|
| 515 | BOOST_CHECK( !fs::is_directory( stat ) ); |
|---|
| 516 | BOOST_CHECK( !fs::is_regular( stat ) ); |
|---|
| 517 | BOOST_CHECK( !fs::is_other( stat ) ); |
|---|
| 518 | BOOST_CHECK( fs::is_symlink( stat ) ); |
|---|
| 519 | } |
|---|
| 520 | |
|---|
| 521 | ec = 0; |
|---|
| 522 | BOOST_CHECK( fs::create_symlink( "doesnotexist", "", ec ) != 0 ); |
|---|
| 523 | BOOST_CHECK( ec != 0 ); |
|---|
| 524 | |
|---|
| 525 | // there was an inital bug in directory_iterator that caused premature |
|---|
| 526 | // close of an OS handle. This block will detect regression. |
|---|
| 527 | { |
|---|
| 528 | fs::directory_iterator di; |
|---|
| 529 | { di = fs::directory_iterator( dir ); } |
|---|
| 530 | BOOST_CHECK( ++di != fs::directory_iterator() ); |
|---|
| 531 | } |
|---|
| 532 | |
|---|
| 533 | // copy_file() tests |
|---|
| 534 | std::cout << "begin copy_file test..." << std::endl; |
|---|
| 535 | fs::copy_file( file_ph, d1 / "f2" ); |
|---|
| 536 | std::cout << "copying complete" << std::endl; |
|---|
| 537 | BOOST_CHECK( fs::exists( file_ph ) ); |
|---|
| 538 | BOOST_CHECK( fs::exists( d1 / "f2" ) ); |
|---|
| 539 | BOOST_CHECK( !fs::is_directory( d1 / "f2" ) ); |
|---|
| 540 | verify_file( d1 / "f2", "foobar1" ); |
|---|
| 541 | std::cout << "copy_file test complete" << std::endl; |
|---|
| 542 | |
|---|
| 543 | // rename() test case numbers refer to operations.htm#rename table |
|---|
| 544 | |
|---|
| 545 | // [case 1] make sure can't rename() a non-existent file |
|---|
| 546 | BOOST_CHECK( !fs::exists( d1 / "f99" ) ); |
|---|
| 547 | BOOST_CHECK( !fs::exists( d1 / "f98" ) ); |
|---|
| 548 | BOOST_CHECK( CHECK_EXCEPTION( bind( BOOST_BND(fs::rename), d1 / "f99", d1 / "f98" ), |
|---|
| 549 | ENOENT ) ); |
|---|
| 550 | BOOST_CHECK( CHECK_EXCEPTION( bind( BOOST_BND(fs::rename), fs::path(""), d1 / "f98" ), |
|---|
| 551 | ENOENT ) ); |
|---|
| 552 | |
|---|
| 553 | // [case 2] rename() target.empty() |
|---|
| 554 | BOOST_CHECK( CHECK_EXCEPTION( bind( BOOST_BND(fs::rename), file_ph, "" ), |
|---|
| 555 | ENOENT ) ); |
|---|
| 556 | |
|---|
| 557 | // [case 3] make sure can't rename() to an existent file or directory |
|---|
| 558 | BOOST_CHECK( fs::exists( dir / "f1" ) ); |
|---|
| 559 | BOOST_CHECK( fs::exists( d1 / "f2" ) ); |
|---|
| 560 | BOOST_CHECK( CHECK_EXCEPTION( bind( BOOST_BND(fs::rename), |
|---|
| 561 | dir / "f1", d1 / "f2" ), EEXIST ) ); |
|---|
| 562 | // several POSIX implementations (cygwin, openBSD) report ENOENT instead of EEXIST, |
|---|
| 563 | // so we don't verify error type on the above test. |
|---|
| 564 | BOOST_CHECK( CHECK_EXCEPTION( bind( BOOST_BND(fs::rename), dir, d1 ), 0 ) ); |
|---|
| 565 | |
|---|
| 566 | // [case 4A] can't rename() file to a nonexistent parent directory |
|---|
| 567 | BOOST_CHECK( !fs::is_directory( dir / "f1" ) ); |
|---|
| 568 | BOOST_CHECK( !fs::exists( dir / "d3/f3" ) ); |
|---|
| 569 | BOOST_CHECK( CHECK_EXCEPTION( bind( BOOST_BND(fs::rename), dir / "f1", dir / "d3/f3" ), |
|---|
| 570 | ENOENT ) ); |
|---|
| 571 | |
|---|
| 572 | // [case 4B] rename() file in same directory |
|---|
| 573 | BOOST_CHECK( fs::exists( d1 / "f2" ) ); |
|---|
| 574 | BOOST_CHECK( !fs::exists( d1 / "f50" ) ); |
|---|
| 575 | fs::rename( d1 / "f2", d1 / "f50" ); |
|---|
| 576 | BOOST_CHECK( !fs::exists( d1 / "f2" ) ); |
|---|
| 577 | BOOST_CHECK( fs::exists( d1 / "f50" ) ); |
|---|
| 578 | fs::rename( d1 / "f50", d1 / "f2" ); |
|---|
| 579 | BOOST_CHECK( fs::exists( d1 / "f2" ) ); |
|---|
| 580 | BOOST_CHECK( !fs::exists( d1 / "f50" ) ); |
|---|
| 581 | |
|---|
| 582 | // [case 4C] rename() file d1/f2 to d2/f3 |
|---|
| 583 | fs::rename( d1 / "f2", d2 / "f3" ); |
|---|
| 584 | BOOST_CHECK( !fs::exists( d1 / "f2" ) ); |
|---|
| 585 | BOOST_CHECK( !fs::exists( d2 / "f2" ) ); |
|---|
| 586 | BOOST_CHECK( fs::exists( d2 / "f3" ) ); |
|---|
| 587 | BOOST_CHECK( !fs::is_directory( d2 / "f3" ) ); |
|---|
| 588 | verify_file( d2 / "f3", "foobar1" ); |
|---|
| 589 | fs::rename( d2 / "f3", d1 / "f2" ); |
|---|
| 590 | BOOST_CHECK( fs::exists( d1 / "f2" ) ); |
|---|
| 591 | |
|---|
| 592 | // [case 5A] rename() directory to nonexistent parent directory |
|---|
| 593 | BOOST_CHECK( fs::exists( d1 ) ); |
|---|
| 594 | BOOST_CHECK( !fs::exists( dir / "d3/d5" ) ); |
|---|
| 595 | BOOST_CHECK( !fs::exists( dir / "d3" ) ); |
|---|
| 596 | BOOST_CHECK( CHECK_EXCEPTION( bind( BOOST_BND(fs::rename), d1, dir / "d3/d5" ), |
|---|
| 597 | ENOENT ) ); |
|---|
| 598 | |
|---|
| 599 | // [case 5B] rename() on directory |
|---|
| 600 | fs::path d3( dir / "d3" ); |
|---|
| 601 | BOOST_CHECK( fs::exists( d1 ) ); |
|---|
| 602 | BOOST_CHECK( fs::exists( d1 / "f2" ) ); |
|---|
| 603 | BOOST_CHECK( !fs::exists( d3 ) ); |
|---|
| 604 | fs::rename( d1, d3 ); |
|---|
| 605 | BOOST_CHECK( !fs::exists( d1 ) ); |
|---|
| 606 | BOOST_CHECK( fs::exists( d3 ) ); |
|---|
| 607 | BOOST_CHECK( fs::is_directory( d3 ) ); |
|---|
| 608 | BOOST_CHECK( !fs::exists( d1 / "f2" ) ); |
|---|
| 609 | BOOST_CHECK( fs::exists( d3 / "f2" ) ); |
|---|
| 610 | fs::rename( d3, d1 ); |
|---|
| 611 | BOOST_CHECK( fs::exists( d1 ) ); |
|---|
| 612 | BOOST_CHECK( fs::exists( d1 / "f2" ) ); |
|---|
| 613 | BOOST_CHECK( !fs::exists( d3 ) ); |
|---|
| 614 | |
|---|
| 615 | // [case 5C] rename() rename and move d1 to d2 / "d20" |
|---|
| 616 | BOOST_CHECK( fs::exists( d1 ) ); |
|---|
| 617 | BOOST_CHECK( !fs::exists( d2 / "d20" ) ); |
|---|
| 618 | BOOST_CHECK( fs::exists( d1 / "f2" ) ); |
|---|
| 619 | fs::rename( d1, d2 / "d20" ); |
|---|
| 620 | BOOST_CHECK( !fs::exists( d1 ) ); |
|---|
| 621 | BOOST_CHECK( fs::exists( d2 / "d20" ) ); |
|---|
| 622 | BOOST_CHECK( fs::exists( d2 / "d20" / "f2" ) ); |
|---|
| 623 | fs::rename( d2 / "d20", d1 ); |
|---|
| 624 | BOOST_CHECK( fs::exists( d1 ) ); |
|---|
| 625 | BOOST_CHECK( !fs::exists( d2 / "d20" ) ); |
|---|
| 626 | BOOST_CHECK( fs::exists( d1 / "f2" ) ); |
|---|
| 627 | |
|---|
| 628 | // remove() tests on file |
|---|
| 629 | file_ph = dir / "shortlife"; |
|---|
| 630 | BOOST_CHECK( !fs::exists( file_ph ) ); |
|---|
| 631 | create_file( file_ph, "" ); |
|---|
| 632 | BOOST_CHECK( fs::exists( file_ph ) ); |
|---|
| 633 | BOOST_CHECK( !fs::is_directory( file_ph ) ); |
|---|
| 634 | BOOST_CHECK( fs::remove( file_ph ) ); |
|---|
| 635 | BOOST_CHECK( !fs::exists( file_ph ) ); |
|---|
| 636 | BOOST_CHECK( !fs::remove( "no-such-file" ) ); |
|---|
| 637 | BOOST_CHECK( !fs::remove( "no-such-directory/no-such-file" ) ); |
|---|
| 638 | |
|---|
| 639 | // remove() test on directory |
|---|
| 640 | d1 = dir / "shortlife_dir"; |
|---|
| 641 | BOOST_CHECK( !fs::exists( d1 ) ); |
|---|
| 642 | fs::create_directory( d1 ); |
|---|
| 643 | BOOST_CHECK( fs::exists( d1 ) ); |
|---|
| 644 | BOOST_CHECK( fs::is_directory( d1 ) ); |
|---|
| 645 | BOOST_CHECK( BOOST_FS_IS_EMPTY( d1 ) ); |
|---|
| 646 | BOOST_CHECK( CHECK_EXCEPTION( bind( BOOST_BND(fs::remove), dir ), ENOTEMPTY ) ); |
|---|
| 647 | BOOST_CHECK( fs::remove( d1 ) ); |
|---|
| 648 | BOOST_CHECK( !fs::exists( d1 ) ); |
|---|
| 649 | |
|---|
| 650 | // STLport is allergic to std::system, so don't use runtime platform test |
|---|
| 651 | # ifdef BOOST_POSIX |
|---|
| 652 | |
|---|
| 653 | // remove() test on dangling symbolic link |
|---|
| 654 | fs::path link( "dangling_link" ); |
|---|
| 655 | fs::remove( link ); |
|---|
| 656 | BOOST_CHECK( !fs::is_symlink( link ) ); |
|---|
| 657 | BOOST_CHECK( !fs::exists( link ) ); |
|---|
| 658 | std::system("ln -s nowhere dangling_link"); |
|---|
| 659 | BOOST_CHECK( !fs::exists( link ) ); |
|---|
| 660 | BOOST_CHECK( fs::is_symlink( link ) ); |
|---|
| 661 | BOOST_CHECK( fs::remove( link ) ); |
|---|
| 662 | BOOST_CHECK( !fs::is_symlink( link ) ); |
|---|
| 663 | |
|---|
| 664 | // remove() test on symbolic link to a file |
|---|
| 665 | file_ph = "link_target"; |
|---|
| 666 | fs::remove( file_ph ); |
|---|
| 667 | BOOST_CHECK( !fs::exists( file_ph ) ); |
|---|
| 668 | create_file( file_ph, "" ); |
|---|
| 669 | BOOST_CHECK( fs::exists( file_ph ) ); |
|---|
| 670 | BOOST_CHECK( !fs::is_directory( file_ph ) ); |
|---|
| 671 | BOOST_CHECK( fs::is_regular( file_ph ) ); |
|---|
| 672 | std::system("ln -s link_target non_dangling_link"); |
|---|
| 673 | link = "non_dangling_link"; |
|---|
| 674 | BOOST_CHECK( fs::exists( link ) ); |
|---|
| 675 | BOOST_CHECK( !fs::is_directory( link ) ); |
|---|
| 676 | BOOST_CHECK( fs::is_regular( link ) ); |
|---|
| 677 | BOOST_CHECK( fs::is_symlink( link ) ); |
|---|
| 678 | BOOST_CHECK( fs::remove( link ) ); |
|---|
| 679 | BOOST_CHECK( fs::exists( file_ph ) ); |
|---|
| 680 | BOOST_CHECK( !fs::exists( link ) ); |
|---|
| 681 | BOOST_CHECK( !fs::is_symlink( link ) ); |
|---|
| 682 | BOOST_CHECK( fs::remove( file_ph ) ); |
|---|
| 683 | BOOST_CHECK( !fs::exists( file_ph ) ); |
|---|
| 684 | # endif |
|---|
| 685 | |
|---|
| 686 | // write time tests |
|---|
| 687 | |
|---|
| 688 | file_ph = dir / "foobar2"; |
|---|
| 689 | create_file( file_ph, "foobar2" ); |
|---|
| 690 | BOOST_CHECK( fs::exists( file_ph ) ); |
|---|
| 691 | BOOST_CHECK( !fs::is_directory( file_ph ) ); |
|---|
| 692 | BOOST_CHECK( fs::is_regular( file_ph ) ); |
|---|
| 693 | BOOST_CHECK( fs::file_size( file_ph ) == 7 ); |
|---|
| 694 | verify_file( file_ph, "foobar2" ); |
|---|
| 695 | |
|---|
| 696 | // Some file system report last write time as local (FAT), while |
|---|
| 697 | // others (NTFS) report it as UTC. The C standard does not specify |
|---|
| 698 | // if time_t is local or UTC. |
|---|
| 699 | |
|---|
| 700 | std::time_t ft = fs::last_write_time( file_ph ); |
|---|
| 701 | std::cout << "\nUTC last_write_time() for a file just created is " |
|---|
| 702 | << std::asctime(std::gmtime(&ft)) << std::endl; |
|---|
| 703 | |
|---|
| 704 | std::tm * tmp = std::localtime( &ft ); |
|---|
| 705 | std::cout << "\nYear is " << tmp->tm_year << std::endl; |
|---|
| 706 | --tmp->tm_year; |
|---|
| 707 | std::cout << "Change year to " << tmp->tm_year << std::endl; |
|---|
| 708 | fs::last_write_time( file_ph, std::mktime( tmp ) ); |
|---|
| 709 | std::time_t ft2 = fs::last_write_time( file_ph ); |
|---|
| 710 | std::cout << "last_write_time() for the file is now " |
|---|
| 711 | << std::asctime(std::gmtime(&ft2)) << std::endl; |
|---|
| 712 | BOOST_CHECK( ft != fs::last_write_time( file_ph ) ); |
|---|
| 713 | |
|---|
| 714 | |
|---|
| 715 | std::cout << "\nReset to current time" << std::endl; |
|---|
| 716 | fs::last_write_time( file_ph, ft ); |
|---|
| 717 | double time_diff = std::difftime( ft, fs::last_write_time( file_ph ) ); |
|---|
| 718 | std::cout |
|---|
| 719 | << "original last_write_time() - current last_write_time() is " |
|---|
| 720 | << time_diff << " seconds" << std::endl; |
|---|
| 721 | BOOST_CHECK( time_diff >= -60.0 && time_diff <= 60.0 ); |
|---|
| 722 | |
|---|
| 723 | // post-test cleanup |
|---|
| 724 | BOOST_CHECK( fs::remove_all( dir ) != 0 ); |
|---|
| 725 | // above was added just to simplify testing, but it ended up detecting |
|---|
| 726 | // a bug (failure to close an internal search handle). |
|---|
| 727 | BOOST_CHECK( !fs::exists( dir ) ); |
|---|
| 728 | BOOST_CHECK( fs::remove_all( dir ) == 0 ); |
|---|
| 729 | return 0; |
|---|
| 730 | } // main |
|---|
| 731 | |
|---|