Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/filesystem/test/operations_test.cpp @ 47

Last change on this file since 47 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 26.2 KB
Line 
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>
20namespace 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>
26using 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
56namespace
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
132int 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
Note: See TracBrowser for help on using the repository browser.