1 // Boost operations_test.cpp ---------------------------------------------------------//
2
3 // Copyright Beman Dawes 2002, 2009.
4
5 // Distributed under the Boost Software License, Version 1.0.
6 // See http://www.boost.org/LICENSE_1_0.txt
7
8 // Library home page: http://www.boost.org/libs/filesystem
9
10 #include <boost/config/warning_disable.hpp>
11
12 // See deprecated_test for tests of deprecated features
13 #ifndef BOOST_FILESYSTEM_NO_DEPRECATED
14 # define BOOST_FILESYSTEM_NO_DEPRECATED
15 #endif
16 #ifndef BOOST_SYSTEM_NO_DEPRECATED
17 # define BOOST_SYSTEM_NO_DEPRECATED
18 #endif
19
20 #include <boost/filesystem/operations.hpp>
21 #include <boost/filesystem/directory.hpp>
22 #include <boost/filesystem/exception.hpp>
23 #include <boost/filesystem/file_status.hpp>
24
25 #include <boost/config.hpp>
26 # if defined( BOOST_NO_STD_WSTRING )
27 # error Configuration not supported: Boost.Filesystem V3 and later requires std::wstring support
28 # endif
29
30 #include <boost/cerrno.hpp>
31 #include <boost/system/error_code.hpp>
32 #include <boost/core/lightweight_test.hpp>
33 #include <boost/detail/lightweight_main.hpp>
34
35 namespace fs = boost::filesystem;
36 using boost::system::error_code;
37 using boost::system::system_category;
38 using boost::system::system_error;
39
40 #include <fstream>
41 #include <iostream>
42
43 using std::cout;
44 using std::endl;
45
46 #include <string>
47 #include <vector>
48 #include <algorithm>
49 #include <cstring> // for strncmp, etc.
50 #include <ctime>
51 #include <cstdlib> // for system(), getenv(), etc.
52
53 #ifdef BOOST_WINDOWS_API
54 # include <windows.h>
55
convert(const char * c)56 inline std::wstring convert(const char* c)
57 {
58 std::string s(c);
59
60 return std::wstring(s.begin(), s.end());
61 }
62
63 // Note: these three setenv* functions are not general solutions for the missing
64 // setenv* problem on VC++. See Microsoft's _putenv for that need, and ticker #7018
65 // for discussion and rationale for returning void for this test program, which needs
66 // to work for both the MSVC Runtime and the Windows Runtime (which does not support
67 // _putenv).
68
setenv_(const char * name,const fs::path::value_type * val,int)69 inline void setenv_(const char* name, const fs::path::value_type* val, int)
70 {
71 SetEnvironmentVariableW(convert(name).c_str(), val);
72 }
73
setenv_(const char * name,const char * val,int)74 inline void setenv_(const char* name, const char* val, int)
75 {
76 SetEnvironmentVariableW(convert(name).c_str(), convert(val).c_str());
77 }
78
unsetenv_(const char * name)79 inline void unsetenv_(const char* name)
80 {
81 SetEnvironmentVariableW(convert(name).c_str(), 0);
82 }
83
84 #else
85
86 #include <unistd.h> // sleep
87 #include <stdlib.h> // allow unqualifed calls to env funcs on SunOS
88
setenv_(const char * name,const char * val,int ovw)89 inline void setenv_(const char* name, const char* val, int ovw)
90 {
91 setenv(name, val, ovw);
92 }
93
unsetenv_(const char * name)94 inline void unsetenv_(const char* name)
95 {
96 unsetenv(name);
97 }
98
99 #endif
100
101 // on Windows, except for standard libaries known to have wchar_t overloads for
102 // file stream I/O, use path::string() to get a narrow character c_str()
103 #if defined(BOOST_WINDOWS_API) \
104 && (!defined(_CPPLIB_VER) || _CPPLIB_VER < 405) // not Dinkumware || no wide overloads
105 # define BOOST_FILESYSTEM_C_STR string().c_str() // use narrow, since wide not available
106 #else // use the native c_str, which will be narrow on POSIX, wide on Windows
107 # define BOOST_FILESYSTEM_C_STR c_str()
108 #endif
109
110 #define CHECK_EXCEPTION(Functor,Expect) throws_fs_error(Functor,Expect,__LINE__)
111
112 namespace
113 {
114 typedef int errno_t;
115 std::string platform(BOOST_PLATFORM);
116 bool report_throws = false;
117 bool cleanup = true;
118 bool skip_long_windows_tests = false;
119
120 fs::directory_iterator end_itr;
121 fs::path dir;
122 fs::path d1;
123 fs::path d2;
124 fs::path f0;
125 fs::path f1;
126 fs::path d1f1;
127
128 bool create_symlink_ok(true);
129
130 fs::path ng(" no-way, Jose");
131
132 unsigned short language_id; // 0 except for Windows
133
134 const fs::path temp_dir(fs::unique_path("op-test-%%%%-%%%%"));
135
create_file(const fs::path & ph,const std::string & contents=std::string ())136 void create_file(const fs::path & ph, const std::string & contents = std::string())
137 {
138 std::ofstream f(ph.BOOST_FILESYSTEM_C_STR);
139 if (!f)
140 throw fs::filesystem_error("operations_test create_file",
141 ph, error_code(errno, system_category()));
142 if (!contents.empty()) f << contents;
143 }
144
verify_file(const fs::path & ph,const std::string & expected)145 void verify_file(const fs::path & ph, const std::string & expected)
146 {
147 std::ifstream f(ph.BOOST_FILESYSTEM_C_STR);
148 if (!f)
149 throw fs::filesystem_error("operations_test verify_file",
150 ph, error_code(errno, system_category()));
151 std::string contents;
152 f >> contents;
153 if (contents != expected)
154 throw fs::filesystem_error("operations_test verify_file contents \""
155 + contents + "\" != \"" + expected + "\"", ph, error_code());
156 }
157
158 template< typename F >
throws_fs_error(F func,errno_t en,int line)159 bool throws_fs_error(F func, errno_t en, int line)
160 {
161 try { func(); }
162
163 catch (const fs::filesystem_error & ex)
164 {
165 if (report_throws)
166 {
167 // use the what() convenience function to display exceptions
168 cout << "\n" << ex.what() << "\n";
169 }
170 if (en == 0
171 || en == ex.code().default_error_condition().value()) return true;
172 cout
173 << "\nWarning: line " << line
174 << " exception reports default_error_condition().value() "
175 << ex.code().default_error_condition().value()
176 << ", should be " << en
177 << "\n value() is " << ex.code().value()
178 << endl;
179 return true;
180 }
181 return false;
182 }
183
184 struct poison_category_impl: public boost::system::error_category
185 {
name__anone45b62480111::poison_category_impl186 char const * name() const BOOST_NOEXCEPT { return "poison"; }
message__anone45b62480111::poison_category_impl187 std::string message( int ) const { return "poison_category::message"; }
188 };
189
poison_category()190 boost::system::error_category& poison_category()
191 {
192 static poison_category_impl instance;
193 return instance;
194 }
195
196 // compile-only two argument "do-the-right-thing" tests
197 // verifies that all overload combinations compile without error
do_the_right_thing_tests(bool call_=false)198 void do_the_right_thing_tests(bool call_ = false)
199 {
200 if (call_)
201 {
202 fs::path p;
203 std::string s;
204 const char* a = 0;
205 fs::copy_file(p, p);
206 fs::copy_file(s, p);
207 fs::copy_file(a, p);
208 fs::copy_file(p, s);
209 fs::copy_file(p, a);
210 fs::copy_file(s, s);
211 fs::copy_file(a, s);
212 fs::copy_file(s, a);
213 fs::copy_file(a, a);
214 }
215 }
216
bad_file_size()217 void bad_file_size()
218 {
219 fs::file_size(" No way, Jose");
220 }
221
bad_directory_size()222 void bad_directory_size()
223 {
224 fs::file_size(fs::current_path());
225 }
226
227 fs::path bad_create_directory_path;
bad_create_directory()228 void bad_create_directory()
229 {
230 fs::create_directory(bad_create_directory_path);
231 }
232
bad_equivalent()233 void bad_equivalent()
234 {
235 fs::equivalent("no-such-path", "another-not-present-path");
236 }
237
238 fs::path bad_remove_dir;
bad_remove()239 void bad_remove()
240 {
241 fs::remove(bad_remove_dir);
242 }
243
244 class renamer
245 {
246 public:
renamer(const fs::path & p1,const fs::path & p2)247 renamer(const fs::path & p1, const fs::path & p2)
248 : from(p1), to(p2) {}
operator ()()249 void operator()()
250 {
251 fs::rename(from, to);
252 }
253 private:
254 fs::path from;
255 fs::path to;
256 };
257
258 //------------------------------ debugging aids --------------------------------------//
259
260 //std::ostream& operator<<(std::ostream& os, const fs::file_status& s)
261 //{
262 // if (s.type() == fs::status_error) { os << "status_error"; }
263 // else if (s.type() == fs::file_not_found) { os << "file_not_found"; }
264 // else if (s.type() == fs::regular_file) { os << "regular_file"; }
265 // else if (s.type() == fs::directory_file) { os << "directory_file"; }
266 // else if (s.type() == fs::symlink_file) { os << "symlink_file"; }
267 // else if (s.type() == fs::block_file) { os << "block_file"; }
268 // else if (s.type() == fs::character_file) { os << "character_file"; }
269 // else if (s.type() == fs::fifo_file) { os << "fifo_file"; }
270 // else if (s.type() == fs::socket_file) { os << "socket_file"; }
271 // else if (s.type() == fs::reparse_file) { os << "reparse_file"; }
272 // else if (s.type() == fs::type_unknown) { os << "type_unknown"; }
273 // else { os << "_detail_directory_symlink"; }
274 // return os;
275 //}
276
277 //void dump_tree(const fs::path & root)
278 //{
279 // cout << "dumping tree rooted at " << root << endl;
280 // for (fs::recursive_directory_iterator it (root, fs::directory_options::follow_directory_symlink);
281 // it != fs::recursive_directory_iterator();
282 // ++it)
283 // {
284 // for (int i = 0; i <= it.level(); ++i)
285 // cout << " ";
286
287 // cout << it->path();
288 // if (fs::is_symlink(it->path()))
289 // {
290 // cout << " [symlink]" << endl;
291 // }
292 // else
293 // cout << endl;
294 // }
295 //}
296
297 // exception_tests() ---------------------------------------------------------------//
298
299 #if defined(BOOST_GCC) && BOOST_GCC >= 80000
300 #pragma GCC diagnostic push
301 // catching polymorphic type "X" by value - that's the intention of the test
302 #pragma GCC diagnostic ignored "-Wcatch-value"
303 #endif
304
exception_tests()305 void exception_tests()
306 {
307 cout << "exception_tests..." << endl;
308 bool exception_thrown;
309
310 // catch runtime_error by value
311
312 cout << " catch runtime_error by value" << endl;
313 exception_thrown = false;
314 try
315 {
316 fs::create_directory("no-such-dir/foo/bar");
317 }
318 catch (std::runtime_error x)
319 {
320 exception_thrown = true;
321 if (report_throws) cout << x.what() << endl;
322 if (platform == "Windows" && language_id == 0x0409) // English (United States)
323 // the stdcxx standard library apparently appends additional info
324 // to what(), so check only the initial portion:
325 BOOST_TEST(std::strncmp(x.what(),
326 "boost::filesystem::create_directory",
327 sizeof("boost::filesystem::create_directory")-1) == 0);
328 }
329 BOOST_TEST(exception_thrown);
330
331 // catch system_error by value
332
333 cout << " catch system_error by value" << endl;
334 exception_thrown = false;
335 try
336 {
337 fs::create_directory("no-such-dir/foo/bar");
338 }
339 catch (system_error x)
340 {
341 exception_thrown = true;
342 if (report_throws) cout << x.what() << endl;
343 if (platform == "Windows" && language_id == 0x0409) // English (United States)
344 BOOST_TEST(std::strcmp(x.what(),
345 "boost::filesystem::create_directory: The system cannot find the path specified") == 0);
346 }
347 BOOST_TEST(exception_thrown);
348
349 // catch filesystem_error by value
350
351 cout << " catch filesystem_error by value" << endl;
352 exception_thrown = false;
353 try
354 {
355 fs::create_directory("no-such-dir/foo/bar");
356 }
357 catch (fs::filesystem_error x)
358 {
359 exception_thrown = true;
360 if (report_throws) cout << x.what() << endl;
361 if (platform == "Windows" && language_id == 0x0409) // English (United States)
362 {
363 bool ok (std::strcmp(x.what(),
364 "boost::filesystem::create_directory: The system cannot find the path specified: \"no-such-dir/foo/bar\"") == 0);
365 BOOST_TEST(ok);
366 if (!ok)
367 {
368 cout << "what returns \"" << x.what() << "\"" << endl;
369 }
370 }
371 }
372 BOOST_TEST(exception_thrown);
373
374 // catch filesystem_error by const reference
375
376 cout << " catch filesystem_error by const reference" << endl;
377 exception_thrown = false;
378 try
379 {
380 fs::create_directory("no-such-dir/foo/bar");
381 }
382 catch (const fs::filesystem_error& x)
383 {
384 exception_thrown = true;
385 if (report_throws) cout << x.what() << endl;
386 if (platform == "Windows" && language_id == 0x0409) // English (United States)
387 {
388 bool ok (std::strcmp(x.what(),
389 "boost::filesystem::create_directory: The system cannot find the path specified: \"no-such-dir/foo/bar\"") == 0);
390 BOOST_TEST(ok);
391 if (!ok)
392 {
393 cout << "what returns \"" << x.what() << "\"" << endl;
394 }
395 }
396 }
397 BOOST_TEST(exception_thrown);
398
399 // the bound functions should throw, so CHECK_EXCEPTION() should return true
400
401 BOOST_TEST(CHECK_EXCEPTION(bad_file_size, ENOENT));
402
403 if (platform == "Windows")
404 BOOST_TEST(CHECK_EXCEPTION(bad_directory_size, ENOENT));
405 else
406 BOOST_TEST(CHECK_EXCEPTION(bad_directory_size, 0));
407
408 // test path::exception members
409 try
410 {
411 fs::file_size(ng); // will throw
412 }
413 catch (fs::filesystem_error& ex)
414 {
415 BOOST_TEST(ex.path1().string() == " no-way, Jose");
416 }
417
418 cout << " exception_tests complete" << endl;
419 }
420
421 #if defined(BOOST_GCC) && BOOST_GCC >= 80000
422 #pragma GCC diagnostic pop
423 #endif
424
425 // create a directory tree that can be used by subsequent tests ---------------------//
426 //
427 // dir
428 // d1
429 // d1f1 // an empty file
430 // f0 // an empty file
431 // f1 // a file containing "file-f1"
432
create_tree()433 void create_tree()
434 {
435 cout << "creating test directories and files in " << dir << endl;
436
437 // create directory d1
438 BOOST_TEST(!fs::create_directory(dir));
439 BOOST_TEST(!fs::is_symlink(dir));
440 BOOST_TEST(!fs::is_symlink("nosuchfileordirectory"));
441 d1 = dir / "d1";
442 BOOST_TEST(fs::create_directory(d1));
443 BOOST_TEST(fs::exists(d1));
444 BOOST_TEST(fs::is_directory(d1));
445 BOOST_TEST(fs::is_empty(d1));
446
447 // create an empty file named "d1f1"
448 d1f1 = d1 / "d1f1";
449 create_file(d1f1, "");
450 BOOST_TEST(fs::exists(d1f1));
451 BOOST_TEST(!fs::is_directory(d1f1));
452 BOOST_TEST(fs::is_regular_file(d1f1));
453 BOOST_TEST(fs::is_empty(d1f1));
454 BOOST_TEST(fs::file_size(d1f1) == 0);
455 BOOST_TEST(fs::hard_link_count(d1f1) == 1);
456
457 // create an empty file named "f0"
458 f0 = dir / "f0";
459 create_file(f0, "");
460 BOOST_TEST(fs::exists(f0));
461 BOOST_TEST(!fs::is_directory(f0));
462 BOOST_TEST(fs::is_regular_file(f0));
463 BOOST_TEST(fs::is_empty(f0));
464 BOOST_TEST(fs::file_size(f0) == 0);
465 BOOST_TEST(fs::hard_link_count(f0) == 1);
466
467 // create a file named "f1"
468 f1 = dir / "f1";
469 create_file(f1, "file-f1");
470 BOOST_TEST(fs::exists(f1));
471 BOOST_TEST(!fs::is_directory(f1));
472 BOOST_TEST(fs::is_regular_file(f1));
473 BOOST_TEST(fs::file_size(f1) == 7);
474 verify_file(f1, "file-f1");
475 }
476
477 // directory_iterator_tests --------------------------------------------------------//
478
directory_iterator_tests()479 void directory_iterator_tests()
480 {
481 cout << "directory_iterator_tests..." << endl;
482
483 bool dir_itr_exception(false);
484 try { fs::directory_iterator it(""); }
485 catch (const fs::filesystem_error &) { dir_itr_exception = true; }
486 BOOST_TEST(dir_itr_exception);
487
488 error_code ec;
489
490 BOOST_TEST(!ec);
491 fs::directory_iterator it("", ec);
492 BOOST_TEST(ec);
493
494 dir_itr_exception = false;
495 try { fs::directory_iterator itx("nosuchdirectory"); }
496 catch (const fs::filesystem_error &) { dir_itr_exception = true; }
497 BOOST_TEST(dir_itr_exception);
498
499 ec.clear();
500 fs::directory_iterator it2x("nosuchdirectory", ec);
501 BOOST_TEST(ec);
502
503 dir_itr_exception = false;
504 try
505 {
506 error_code ecx;
507 fs::directory_iterator itx("nosuchdirectory", ecx);
508 BOOST_TEST(ecx);
509 BOOST_TEST(ecx == boost::system::errc::no_such_file_or_directory);
510 }
511 catch (const fs::filesystem_error &) { dir_itr_exception = true; }
512 BOOST_TEST(!dir_itr_exception);
513
514 // create a second directory named d2
515 d2 = dir / "d2";
516 fs::create_directory(d2);
517 BOOST_TEST(fs::exists(d2));
518 BOOST_TEST(fs::is_directory(d2));
519
520 // test the basic operation of directory_iterators, and test that
521 // stepping one iterator doesn't affect a different iterator.
522 {
523 typedef std::vector<fs::directory_entry> vec_type;
524 vec_type vec;
525
526 fs::directory_iterator it1(dir);
527 BOOST_TEST(it1 != fs::directory_iterator());
528 BOOST_TEST(fs::exists(it1->status()));
529 vec.push_back(*it1);
530 BOOST_TEST(*it1 == vec[0]);
531
532 fs::directory_iterator it2(dir);
533 BOOST_TEST(it2 != fs::directory_iterator());
534 BOOST_TEST(*it1 == *it2);
535
536 ++it1;
537 BOOST_TEST(it1 != fs::directory_iterator());
538 BOOST_TEST(fs::exists(it1->status()));
539 BOOST_TEST(it1 != it2);
540 BOOST_TEST(*it1 != vec[0]);
541 BOOST_TEST(*it2 == vec[0]);
542 vec.push_back(*it1);
543
544 ++it1;
545 BOOST_TEST(it1 != fs::directory_iterator());
546 BOOST_TEST(fs::exists(it1->status()));
547 BOOST_TEST(it1 != it2);
548 BOOST_TEST(*it2 == vec[0]);
549 vec.push_back(*it1);
550
551 ++it1;
552 BOOST_TEST(it1 != fs::directory_iterator());
553 BOOST_TEST(fs::exists(it1->status()));
554 BOOST_TEST(it1 != it2);
555 BOOST_TEST(*it2 == vec[0]);
556 vec.push_back(*it1);
557
558 ++it1;
559 BOOST_TEST(it1 == fs::directory_iterator());
560
561 BOOST_TEST(*it2 == vec[0]);
562 ec.clear();
563 it2.increment(ec);
564 BOOST_TEST(!ec);
565 BOOST_TEST(it2 != fs::directory_iterator());
566 BOOST_TEST(it1 == fs::directory_iterator());
567 BOOST_TEST(*it2 == vec[1]);
568 ++it2;
569 BOOST_TEST(*it2 == vec[2]);
570 BOOST_TEST(it1 == fs::directory_iterator());
571 ++it2;
572 BOOST_TEST(*it2 == vec[3]);
573 ++it2;
574 BOOST_TEST(it1 == fs::directory_iterator());
575 BOOST_TEST(it2 == fs::directory_iterator());
576
577 // sort vec and check that the right directory entries were found
578 std::sort(vec.begin(), vec.end());
579
580 BOOST_TEST_EQ(vec[0].path().filename().string(), std::string("d1"));
581 BOOST_TEST_EQ(vec[1].path().filename().string(), std::string("d2"));
582 BOOST_TEST_EQ(vec[2].path().filename().string(), std::string("f0"));
583 BOOST_TEST_EQ(vec[3].path().filename().string(), std::string("f1"));
584 }
585
586 { // *i++ must meet the standard's InputIterator requirements
587 fs::directory_iterator dir_itr(dir);
588 BOOST_TEST(dir_itr != fs::directory_iterator());
589 fs::path p = dir_itr->path();
590 BOOST_TEST((*dir_itr++).path() == p);
591 BOOST_TEST(dir_itr != fs::directory_iterator());
592 BOOST_TEST(dir_itr->path() != p);
593
594 // test case reported in comment to SourceForge bug tracker [937606]
595 // augmented to test single pass semantics of a copied iterator [#12578]
596 fs::directory_iterator itx(dir);
597 fs::directory_iterator itx2(itx);
598 BOOST_TEST(itx == itx2);
599 const fs::path p1 = (*itx++).path();
600 BOOST_TEST(itx == itx2);
601 BOOST_TEST(itx != fs::directory_iterator());
602 const fs::path p2 = (*itx++).path();
603 BOOST_TEST(itx == itx2);
604 BOOST_TEST(p1 != p2);
605 ++itx;
606 BOOST_TEST(itx == itx2);
607 ++itx;
608 BOOST_TEST(itx == itx2);
609 BOOST_TEST(itx == fs::directory_iterator());
610 BOOST_TEST(itx2 == fs::directory_iterator());
611 }
612
613 // Windows has a tricky special case when just the root-name is given,
614 // causing the rest of the path to default to the current directory.
615 // Reported as S/F bug [ 1259176 ]
616 if (platform == "Windows")
617 {
618 fs::path root_name_path(fs::current_path().root_name());
619 fs::directory_iterator itx(root_name_path);
620 BOOST_TEST(itx != fs::directory_iterator());
621 // BOOST_TEST(fs::exists((*itx).path()));
622 BOOST_TEST(fs::exists(itx->path()));
623 BOOST_TEST(itx->path().parent_path() == root_name_path);
624 bool found(false);
625 do
626 {
627 if (itx->path().filename() == temp_dir.filename())
628 found = true;
629 } while (++itx != fs::directory_iterator());
630 BOOST_TEST(found);
631 }
632
633 // there was an inital bug in directory_iterator that caused premature
634 // close of an OS handle. This block will detect regression.
635 {
636 fs::directory_iterator di;
637 {
638 di = fs::directory_iterator(dir);
639 }
640 BOOST_TEST(++di != fs::directory_iterator());
641 }
642
643 cout << " directory_iterator_tests complete" << endl;
644 }
645
646 // recursive_directory_iterator_tests ----------------------------------------------//
647
walk_tree(bool recursive)648 int walk_tree(bool recursive)
649 {
650 //cout << " walk_tree" << endl;
651 error_code ec;
652 int d1f1_count = 0;
653 for (fs::recursive_directory_iterator it (dir,
654 recursive ? (fs::directory_options::follow_directory_symlink | fs::directory_options::skip_dangling_symlinks) : fs::directory_options::none);
655 it != fs::recursive_directory_iterator();
656 it.increment(ec))
657 {
658 //cout << " " << it->path() << " : " << ec << endl;
659 if (it->path().filename() == "d1f1")
660 ++d1f1_count;
661 }
662 //cout << " last error : " << ec << endl;
663 return d1f1_count;
664 }
665
recursive_directory_iterator_tests()666 void recursive_directory_iterator_tests()
667 {
668 cout << "recursive_directory_iterator_tests..." << endl;
669 BOOST_TEST_EQ(walk_tree(false), 1);
670 if (create_symlink_ok)
671 BOOST_TEST(walk_tree(true) > 1);
672
673 // test iterator increment with error_code argument
674 cout << " with error_code argument" << endl;
675 boost::system::error_code ec;
676 int d1f1_count = 0;
677 fs::recursive_directory_iterator it(dir, fs::directory_options::none);
678 fs::recursive_directory_iterator it2(it); // test single pass shallow copy semantics
679 for (;
680 it != fs::recursive_directory_iterator();
681 it.increment(ec))
682 {
683 if (it->path().filename() == "d1f1")
684 ++d1f1_count;
685 BOOST_TEST(it == it2); // verify single pass shallow copy semantics
686 }
687 BOOST_TEST(!ec);
688 BOOST_TEST_EQ(d1f1_count, 1);
689 BOOST_TEST(it == it2); // verify single pass shallow copy semantics
690
691 cout << " recursive_directory_iterator_tests complete" << endl;
692 }
693
694 // iterator_status_tests -----------------------------------------------------------//
695
iterator_status_tests()696 void iterator_status_tests()
697 {
698 cout << "iterator_status_tests..." << endl;
699
700 error_code ec;
701 // harmless if these fail:
702 fs::create_symlink(dir/"f0", dir/"f0_symlink", ec);
703 fs::create_symlink(dir/"no such file", dir/"dangling_symlink", ec);
704 fs::create_directory_symlink(dir/"d1", dir/"d1_symlink", ec);
705 fs::create_directory_symlink(dir/"no such directory",
706 dir/"dangling_directory_symlink", ec);
707
708 for (fs::directory_iterator it(dir);
709 it != fs::directory_iterator(); ++it)
710 {
711 BOOST_TEST(fs::status(it->path()).type() == it->status().type());
712 BOOST_TEST(fs::symlink_status(it->path()).type() == it->symlink_status().type());
713 if (it->path().filename() == "d1")
714 {
715 BOOST_TEST(fs::is_directory(it->status()));
716 BOOST_TEST(fs::is_directory(it->symlink_status()));
717 }
718 else if (it->path().filename() == "d2")
719 {
720 BOOST_TEST(fs::is_directory(it->status()));
721 BOOST_TEST(fs::is_directory(it->symlink_status()));
722 }
723 else if (it->path().filename() == "f0")
724 {
725 BOOST_TEST(fs::is_regular_file(it->status()));
726 BOOST_TEST(fs::is_regular_file(it->symlink_status()));
727 }
728 else if (it->path().filename() == "f1")
729 {
730 BOOST_TEST(fs::is_regular_file(it->status()));
731 BOOST_TEST(fs::is_regular_file(it->symlink_status()));
732 }
733 else if (it->path().filename() == "f0_symlink")
734 {
735 BOOST_TEST(fs::is_regular_file(it->status()));
736 BOOST_TEST(fs::is_symlink(it->symlink_status()));
737 BOOST_TEST(fs::is_symlink(*it));
738 }
739 else if (it->path().filename() == "dangling_symlink")
740 {
741 BOOST_TEST(it->status().type() == fs::file_not_found);
742 BOOST_TEST(fs::is_symlink(it->symlink_status()));
743 }
744 else if (it->path().filename() == "d1_symlink")
745 {
746 BOOST_TEST(fs::is_directory(it->status()));
747 BOOST_TEST(fs::is_symlink(it->symlink_status()));
748 }
749 else if (it->path().filename() == "dangling_directory_symlink")
750 {
751 BOOST_TEST(it->status().type() == fs::file_not_found);
752 BOOST_TEST(fs::is_symlink(it->symlink_status()));
753 }
754 //else
755 // cout << " Note: unexpected directory entry " << it->path().filename() << endl;
756 }
757 }
758
759 // recursive_iterator_status_tests -------------------------------------------------//
760
recursive_iterator_status_tests()761 void recursive_iterator_status_tests()
762 {
763 cout << "recursive_iterator_status_tests..." << endl;
764 for (fs::recursive_directory_iterator it (dir);
765 it != fs::recursive_directory_iterator();
766 ++it)
767 {
768 BOOST_TEST(fs::status(it->path()).type() == it->status().type());
769 BOOST_TEST(fs::symlink_status(it->path()).type() == it->symlink_status().type());
770 }
771 }
772
773 // create_hard_link_tests ----------------------------------------------------------//
774
create_hard_link_tests()775 void create_hard_link_tests()
776 {
777 cout << "create_hard_link_tests..." << endl;
778
779 fs::path from_ph(dir / "f3");
780 fs::path f1x(dir / "f1");
781
782 BOOST_TEST(!fs::exists(from_ph));
783 BOOST_TEST(fs::exists(f1x));
784 bool create_hard_link_ok(true);
785 try { fs::create_hard_link(f1x, from_ph); }
786 catch (const fs::filesystem_error & ex)
787 {
788 create_hard_link_ok = false;
789 cout
790 << " *** For information only ***\n"
791 " create_hard_link() attempt failed\n"
792 " filesystem_error.what() reports: " << ex.what() << "\n"
793 " create_hard_link() may not be supported on this file system\n";
794 }
795
796 if (create_hard_link_ok)
797 {
798 cout
799 << " *** For information only ***\n"
800 " create_hard_link() succeeded\n";
801 BOOST_TEST(fs::exists(from_ph));
802 BOOST_TEST(fs::exists(f1x));
803 BOOST_TEST(fs::equivalent(from_ph, f1x));
804 BOOST_TEST(fs::hard_link_count(from_ph) == 2);
805 BOOST_TEST(fs::hard_link_count(f1x) == 2);
806 }
807
808 // Although tests may be running on a FAT or other file system that does
809 // not support hard links, that is unusual enough that it is considered
810 // a test failure.
811 BOOST_TEST(create_hard_link_ok);
812
813 error_code ec;
814 fs::create_hard_link(fs::path("doesnotexist"),
815 fs::path("shouldnotwork"), ec);
816 BOOST_TEST(ec);
817 }
818
819 // create_symlink_tests ------------------------------------------------------------//
820
create_symlink_tests()821 void create_symlink_tests()
822 {
823 cout << "create_symlink_tests..." << endl;
824
825 fs::path from_ph(dir / "f4");
826 fs::path f1x(dir / "f1");
827 BOOST_TEST(!fs::exists(from_ph));
828 BOOST_TEST(fs::exists(f1x));
829 try { fs::create_symlink(f1x, from_ph); }
830 catch (const fs::filesystem_error & ex)
831 {
832 create_symlink_ok = false;
833 cout
834 << " *** For information only ***\n"
835 " create_symlink() attempt failed\n"
836 " filesystem_error.what() reports: " << ex.what() << "\n"
837 " create_symlink() may not be supported on this operating system or file system\n";
838 }
839
840 if (create_symlink_ok)
841 {
842 cout
843 << " *** For information only ***\n"
844 " create_symlink() succeeded\n";
845 BOOST_TEST(fs::exists(from_ph));
846 BOOST_TEST(fs::is_symlink(from_ph));
847 BOOST_TEST(fs::exists(f1x));
848 BOOST_TEST(fs::equivalent(from_ph, f1x));
849 BOOST_TEST(fs::read_symlink(from_ph) == f1x);
850
851 fs::file_status stat = fs::symlink_status(from_ph);
852 BOOST_TEST(fs::exists(stat));
853 BOOST_TEST(!fs::is_directory(stat));
854 BOOST_TEST(!fs::is_regular_file(stat));
855 BOOST_TEST(!fs::is_other(stat));
856 BOOST_TEST(fs::is_symlink(stat));
857
858 stat = fs::status(from_ph);
859 BOOST_TEST(fs::exists(stat));
860 BOOST_TEST(!fs::is_directory(stat));
861 BOOST_TEST(fs::is_regular_file(stat));
862 BOOST_TEST(!fs::is_other(stat));
863 BOOST_TEST(!fs::is_symlink(stat));
864
865 // since create_symlink worked, copy_symlink should also work
866 fs::path symlink2_ph(dir / "symlink2");
867 fs::copy_symlink(from_ph, symlink2_ph);
868 stat = fs::symlink_status(symlink2_ph);
869 BOOST_TEST(fs::is_symlink(stat));
870 BOOST_TEST(fs::exists(stat));
871 BOOST_TEST(!fs::is_directory(stat));
872 BOOST_TEST(!fs::is_regular_file(stat));
873 BOOST_TEST(!fs::is_other(stat));
874 }
875
876 error_code ec = error_code();
877 fs::create_symlink("doesnotexist", "", ec);
878 BOOST_TEST(ec);
879 }
880
881 // permissions_tests ---------------------------------------------------------------//
882
permissions_tests()883 void permissions_tests()
884 {
885 cout << "permissions_tests..." << endl;
886
887 fs::path p(dir / "permissions.txt");
888 create_file(p);
889
890 if (platform == "POSIX")
891 {
892 cout << " fs::status(p).permissions() " << std::oct << fs::status(p).permissions()
893 << std::dec << endl;
894 BOOST_TEST((fs::status(p).permissions() & 0600) == 0600); // 0644, 0664 sometimes returned
895
896 fs::permissions(p, fs::owner_all);
897 BOOST_TEST(fs::status(p).permissions() == fs::owner_all);
898
899 fs::permissions(p, fs::add_perms | fs::group_all);
900 BOOST_TEST(fs::status(p).permissions() == (fs::owner_all | fs::group_all));
901
902 fs::permissions(p, fs::remove_perms | fs::group_all);
903 BOOST_TEST(fs::status(p).permissions() == fs::owner_all);
904
905 // some POSIX platforms cache permissions during directory iteration, some don't
906 // so test that iteration finds the correct permissions
907 for (fs::directory_iterator itr(dir); itr != fs::directory_iterator(); ++itr)
908 if (itr->path().filename() == fs::path("permissions.txt"))
909 BOOST_TEST(itr->status().permissions() == fs::owner_all);
910
911 if (create_symlink_ok) // only if symlinks supported
912 {
913 BOOST_TEST(fs::status(p).permissions() == fs::owner_all);
914 fs::path p2(dir / "permissions-symlink.txt");
915 fs::create_symlink(p, p2);
916 cout << std::oct;
917 cout << " status(p).permissions() " << fs::status(p).permissions() << endl;
918 cout << " status(p2).permissions() " << fs::status(p).permissions() << endl;
919 fs::permissions(p2, fs::add_perms | fs::others_read);
920 cout << " status(p).permissions(): " << fs::status(p).permissions() << endl;
921 cout << " status(p2).permissions(): " << fs::status(p2).permissions() << endl;
922 cout << std::dec;
923 }
924
925 }
926 else // Windows
927 {
928 BOOST_TEST(fs::status(p).permissions() == 0666);
929 fs::permissions(p, fs::remove_perms | fs::group_write);
930 BOOST_TEST(fs::status(p).permissions() == 0444);
931 fs::permissions(p, fs::add_perms | fs::group_write);
932 BOOST_TEST(fs::status(p).permissions() == 0666);
933 }
934 }
935
936 // rename_tests --------------------------------------------------------------------//
937
rename_tests()938 void rename_tests()
939 {
940 cout << "rename_tests..." << endl;
941
942 fs::path f1x(dir / "f1");
943 BOOST_TEST(fs::exists(f1x));
944
945 // error: rename a non-existent old file
946 BOOST_TEST(!fs::exists(d1 / "f99"));
947 BOOST_TEST(!fs::exists(d1 / "f98"));
948 renamer n1a(d1 / "f99", d1 / "f98");
949 BOOST_TEST(CHECK_EXCEPTION(n1a, ENOENT));
950 renamer n1b(fs::path(""), d1 / "f98");
951 BOOST_TEST(CHECK_EXCEPTION(n1b, ENOENT));
952
953 // error: rename an existing file to ""
954 renamer n2(f1x, "");
955 BOOST_TEST(CHECK_EXCEPTION(n2, ENOENT));
956
957 // rename an existing file to an existent file
958 create_file(dir / "ff1", "ff1");
959 create_file(dir / "ff2", "ff2");
960 fs::rename(dir / "ff2", dir / "ff1");
961 BOOST_TEST(fs::exists(dir / "ff1"));
962 verify_file(dir / "ff1", "ff2");
963 BOOST_TEST(!fs::exists(dir / "ff2"));
964
965 // rename an existing file to itself
966 BOOST_TEST(fs::exists(dir / "f1"));
967 fs::rename(dir / "f1", dir / "f1");
968 BOOST_TEST(fs::exists(dir / "f1"));
969
970 // error: rename an existing directory to an existing non-empty directory
971 BOOST_TEST(fs::exists(dir / "f1"));
972 BOOST_TEST(fs::exists(d1 / "f2"));
973 // several POSIX implementations (cygwin, openBSD) report ENOENT instead of EEXIST,
974 // so we don't verify error type on the following test.
975 renamer n3b(dir, d1);
976 BOOST_TEST(CHECK_EXCEPTION(n3b, 0));
977
978 // error: move existing file to a nonexistent parent directory
979 BOOST_TEST(!fs::is_directory(dir / "f1"));
980 BOOST_TEST(!fs::exists(dir / "d3/f3"));
981 renamer n4a(dir / "f1", dir / "d3/f3");
982 BOOST_TEST(CHECK_EXCEPTION(n4a, ENOENT));
983
984 // rename existing file in same directory
985 BOOST_TEST(fs::exists(d1 / "f2"));
986 BOOST_TEST(!fs::exists(d1 / "f50"));
987 fs::rename(d1 / "f2", d1 / "f50");
988 BOOST_TEST(!fs::exists(d1 / "f2"));
989 BOOST_TEST(fs::exists(d1 / "f50"));
990 fs::rename(d1 / "f50", d1 / "f2");
991 BOOST_TEST(fs::exists(d1 / "f2"));
992 BOOST_TEST(!fs::exists(d1 / "f50"));
993
994 // move and rename an existing file to a different directory
995 fs::rename(d1 / "f2", d2 / "f3");
996 BOOST_TEST(!fs::exists(d1 / "f2"));
997 BOOST_TEST(!fs::exists(d2 / "f2"));
998 BOOST_TEST(fs::exists(d2 / "f3"));
999 BOOST_TEST(!fs::is_directory(d2 / "f3"));
1000 verify_file(d2 / "f3", "file-f1");
1001 fs::rename(d2 / "f3", d1 / "f2");
1002 BOOST_TEST(fs::exists(d1 / "f2"));
1003
1004 // error: move existing directory to nonexistent parent directory
1005 BOOST_TEST(fs::exists(d1));
1006 BOOST_TEST(!fs::exists(dir / "d3/d5"));
1007 BOOST_TEST(!fs::exists(dir / "d3"));
1008 renamer n5a(d1, dir / "d3/d5");
1009 BOOST_TEST(CHECK_EXCEPTION(n5a, ENOENT));
1010
1011 // rename existing directory
1012 fs::path d3(dir / "d3");
1013 BOOST_TEST(fs::exists(d1));
1014 BOOST_TEST(fs::exists(d1 / "f2"));
1015 BOOST_TEST(!fs::exists(d3));
1016 fs::rename(d1, d3);
1017 BOOST_TEST(!fs::exists(d1));
1018 BOOST_TEST(fs::exists(d3));
1019 BOOST_TEST(fs::is_directory(d3));
1020 BOOST_TEST(!fs::exists(d1 / "f2"));
1021 BOOST_TEST(fs::exists(d3 / "f2"));
1022 fs::rename(d3, d1);
1023 BOOST_TEST(fs::exists(d1));
1024 BOOST_TEST(fs::exists(d1 / "f2"));
1025 BOOST_TEST(!fs::exists(d3));
1026
1027 // rename and move d1 to d2 / "d20"
1028 BOOST_TEST(fs::exists(d1));
1029 BOOST_TEST(!fs::exists(d2 / "d20"));
1030 BOOST_TEST(fs::exists(d1 / "f2"));
1031 fs::rename(d1, d2 / "d20");
1032 BOOST_TEST(!fs::exists(d1));
1033 BOOST_TEST(fs::exists(d2 / "d20"));
1034 BOOST_TEST(fs::exists(d2 / "d20" / "f2"));
1035 fs::rename(d2 / "d20", d1);
1036 BOOST_TEST(fs::exists(d1));
1037 BOOST_TEST(!fs::exists(d2 / "d20"));
1038 BOOST_TEST(fs::exists(d1 / "f2"));
1039 }
1040
1041 // predicate_and_status_tests ------------------------------------------------------//
1042
predicate_and_status_tests()1043 void predicate_and_status_tests()
1044 {
1045 cout << "predicate_and_status_tests..." << endl;
1046
1047 BOOST_TEST(!fs::exists(ng));
1048 BOOST_TEST(!fs::is_directory(ng));
1049 BOOST_TEST(!fs::is_regular_file(ng));
1050 BOOST_TEST(!fs::is_symlink(ng));
1051 fs::file_status stat(fs::status(ng));
1052 BOOST_TEST(fs::type_present(stat));
1053 BOOST_TEST(fs::permissions_present(stat));
1054 BOOST_TEST(fs::status_known(stat));
1055 BOOST_TEST(!fs::exists(stat));
1056 BOOST_TEST(!fs::is_directory(stat));
1057 BOOST_TEST(!fs::is_regular_file(stat));
1058 BOOST_TEST(!fs::is_other(stat));
1059 BOOST_TEST(!fs::is_symlink(stat));
1060 stat = fs::status("");
1061 BOOST_TEST(fs::type_present(stat));
1062 BOOST_TEST(fs::permissions_present(stat));
1063 BOOST_TEST(fs::status_known(stat));
1064 BOOST_TEST(!fs::exists(stat));
1065 BOOST_TEST(!fs::is_directory(stat));
1066 BOOST_TEST(!fs::is_regular_file(stat));
1067 BOOST_TEST(!fs::is_other(stat));
1068 BOOST_TEST(!fs::is_symlink(stat));
1069 }
1070
1071 // create_directory_tests ----------------------------------------------------------//
1072
create_directory_tests()1073 void create_directory_tests()
1074 {
1075 cout << "create_directory_tests..." << endl;
1076
1077 error_code ec;
1078 BOOST_TEST(!fs::create_directory("", ec));
1079 BOOST_TEST(ec);
1080
1081 #ifdef BOOST_WINDOWS_API
1082 ec.clear();
1083 BOOST_TEST(!fs::create_directory(" ", ec)); // OK on Linux
1084 BOOST_TEST(ec);
1085 #endif
1086
1087 ec.clear();
1088 BOOST_TEST(!fs::create_directory("/", ec));
1089 BOOST_TEST(!ec);
1090 BOOST_TEST(fs::is_directory("/")); // this is a post-condition
1091
1092 ec.clear();
1093 BOOST_TEST(!fs::create_directory(".", ec));
1094 BOOST_TEST(!ec);
1095
1096 ec.clear();
1097 BOOST_TEST(!fs::create_directory("..", ec));
1098 BOOST_TEST(!ec);
1099
1100 // create a directory, then check it for consistency
1101 // take extra care to report problems, since if this fails
1102 // many subsequent tests will fail
1103 try
1104 {
1105 fs::create_directory(dir);
1106 }
1107
1108 catch (const fs::filesystem_error & x)
1109 {
1110 cout << x.what() << "\n\n"
1111 "***** Creating directory " << dir << " failed. *****\n"
1112 "***** This is a serious error that will prevent further tests *****\n"
1113 "***** from returning useful results. Further testing is aborted. *****\n\n";
1114 std::exit(1);
1115 }
1116
1117 catch (...)
1118 {
1119 cout << "\n\n"
1120 "***** Creating directory " << dir << " failed. *****\n"
1121 "***** This is a serious error that will prevent further tests *****\n"
1122 "***** from returning useful results. Further testing is aborted. *****\n\n";
1123 std::exit(1);
1124 }
1125
1126 BOOST_TEST(fs::exists(dir));
1127 BOOST_TEST(fs::is_empty(dir));
1128 BOOST_TEST(fs::is_directory(dir));
1129 BOOST_TEST(!fs::is_regular_file(dir));
1130 BOOST_TEST(!fs::is_other(dir));
1131 BOOST_TEST(!fs::is_symlink(dir));
1132 fs::file_status stat = fs::status(dir);
1133 BOOST_TEST(fs::exists(stat));
1134 BOOST_TEST(fs::is_directory(stat));
1135 BOOST_TEST(!fs::is_regular_file(stat));
1136 BOOST_TEST(!fs::is_other(stat));
1137 BOOST_TEST(!fs::is_symlink(stat));
1138
1139 cout << " create_directory_tests complete" << endl;
1140 }
1141
1142 // current_directory_tests ---------------------------------------------------------//
1143
current_directory_tests()1144 void current_directory_tests()
1145 {
1146 cout << "current_directory_tests..." << endl;
1147
1148 // set the current directory, then check it for consistency
1149 fs::path original_dir = fs::current_path();
1150 BOOST_TEST(dir != original_dir);
1151 fs::current_path(dir);
1152 BOOST_TEST(fs::current_path() == dir);
1153 BOOST_TEST(fs::current_path() != original_dir);
1154 fs::current_path(original_dir);
1155 BOOST_TEST(fs::current_path() == original_dir);
1156 BOOST_TEST(fs::current_path() != dir);
1157
1158 // make sure the overloads work
1159 fs::current_path(dir.c_str());
1160 BOOST_TEST(fs::current_path() == dir);
1161 BOOST_TEST(fs::current_path() != original_dir);
1162 fs::current_path(original_dir.string());
1163 BOOST_TEST(fs::current_path() == original_dir);
1164 BOOST_TEST(fs::current_path() != dir);
1165 }
1166
1167 // create_directories_tests --------------------------------------------------------//
1168
create_directories_tests()1169 void create_directories_tests()
1170 {
1171 cout << "create_directories_tests..." << endl;
1172
1173 error_code ec;
1174 BOOST_TEST(!fs::create_directories("", ec));
1175 BOOST_TEST(ec);
1176
1177 #ifdef BOOST_WINDOWS_API
1178 // Windows only test, since " " is OK on Linux as a directory name
1179 ec.clear();
1180 BOOST_TEST(!fs::create_directories(" ", ec));
1181 BOOST_TEST(ec);
1182 #endif
1183
1184 ec.clear();
1185 BOOST_TEST(!fs::create_directories("/", ec));
1186 BOOST_TEST(!ec);
1187
1188 ec.clear();
1189 BOOST_TEST(!fs::create_directories(".", ec));
1190 BOOST_TEST(ec);
1191
1192 ec.clear();
1193 BOOST_TEST(!fs::create_directories("..", ec));
1194 BOOST_TEST(ec);
1195
1196 #ifdef BOOST_POSIX_API
1197 ec.clear();
1198 BOOST_TEST(!fs::create_directories("/foo", ec)); // may be OK on Windows
1199 // but unlikely to be OK on POSIX
1200 BOOST_TEST(ec);
1201 #endif
1202
1203 fs::path p = dir / "level1/." / "level2/./.." / "level3/";
1204 // trailing "/.", "/./..", and "/" in the above elements test ticket #7258 and
1205 // related issues
1206
1207 cout << " p is " << p << endl;
1208 BOOST_TEST(!fs::exists(p));
1209 BOOST_TEST(fs::create_directories(p));
1210 BOOST_TEST(fs::exists(p));
1211 BOOST_TEST(fs::is_directory(p));
1212
1213 if (fs::exists("/permissions_test"))
1214 {
1215 BOOST_TEST(!fs::create_directories("/permissions_test", ec));
1216 BOOST_TEST(!fs::create_directories("/permissions_test/another_directory", ec));
1217 BOOST_TEST(ec);
1218 }
1219 }
1220
1221 // resize_file_tests ---------------------------------------------------------------//
1222
resize_file_tests()1223 void resize_file_tests()
1224 {
1225 cout << "resize_file_tests..." << endl;
1226
1227 fs::path p(dir / "resize_file_test.txt");
1228
1229 fs::remove(p);
1230 create_file(p, "1234567890");
1231
1232 BOOST_TEST(fs::exists(p));
1233 BOOST_TEST_EQ(fs::file_size(p), 10U);
1234 fs::resize_file(p, 5);
1235 BOOST_TEST(fs::exists(p));
1236 BOOST_TEST_EQ(fs::file_size(p), 5U);
1237 fs::resize_file(p, 15);
1238 BOOST_TEST(fs::exists(p));
1239 BOOST_TEST_EQ(fs::file_size(p), 15U);
1240
1241 error_code ec;
1242 fs::resize_file("no such file", 15, ec);
1243 BOOST_TEST(ec);
1244 }
1245
1246 // status_of_nonexistent_tests -----------------------------------------------------//
1247
status_of_nonexistent_tests()1248 void status_of_nonexistent_tests()
1249 {
1250 cout << "status_of_nonexistent_tests..." << endl;
1251 fs::path p ("nosuch");
1252 BOOST_TEST(!fs::exists(p));
1253 BOOST_TEST(!fs::is_regular_file(p));
1254 BOOST_TEST(!fs::is_directory(p));
1255 BOOST_TEST(!fs::is_symlink(p));
1256 BOOST_TEST(!fs::is_other(p));
1257
1258 fs::file_status s = fs::status(p);
1259 BOOST_TEST(!fs::exists(s));
1260 BOOST_TEST_EQ(s.type(), fs::file_not_found);
1261 BOOST_TEST(fs::type_present(s));
1262 BOOST_TEST(!fs::is_regular_file(s));
1263 BOOST_TEST(!fs::is_directory(s));
1264 BOOST_TEST(!fs::is_symlink(s));
1265 BOOST_TEST(!fs::is_other(s));
1266
1267 // ticket #12574 was just user confusion, but are the tests are worth keeping
1268 error_code ec;
1269 BOOST_TEST(!fs::is_directory(dir / "no-such-directory", ec));
1270 BOOST_TEST(ec);
1271 //cout << "error_code value: " << ec.value() << endl;
1272 ec.clear();
1273 BOOST_TEST(!fs::is_directory(dir / "no-such-directory" / "bar", ec));
1274 BOOST_TEST(ec);
1275 //cout << "error_code value: " << ec.value() << endl;
1276 }
1277
1278 // status_error_reporting_tests ----------------------------------------------------//
1279
status_error_reporting_tests()1280 void status_error_reporting_tests()
1281 {
1282 cout << "status_error_reporting_tests..." << endl;
1283
1284 error_code ec;
1285
1286 // test status, ec, for existing file
1287 ec.assign(-1,poison_category());
1288 BOOST_TEST(ec.value() == -1);
1289 BOOST_TEST(&ec.category() == &poison_category());
1290 fs::file_status s = fs::status(".",ec);
1291 BOOST_TEST(ec.value() == 0);
1292 BOOST_TEST(ec.category() == system_category());
1293 BOOST_TEST(fs::exists(s));
1294 BOOST_TEST(fs::is_directory(s));
1295
1296 // test status, ec, for non-existing file
1297 fs::path p ("nosuch");
1298 ec.assign(-1,poison_category());
1299 s = fs::status(p,ec);
1300 BOOST_TEST(ec.value() != 0);
1301 BOOST_TEST(ec.category() == system_category());
1302
1303 BOOST_TEST(!fs::exists(s));
1304 BOOST_TEST_EQ(s.type(), fs::file_not_found);
1305 BOOST_TEST(fs::type_present(s));
1306 BOOST_TEST(!fs::is_regular_file(s));
1307 BOOST_TEST(!fs::is_directory(s));
1308 BOOST_TEST(!fs::is_symlink(s));
1309 BOOST_TEST(!fs::is_other(s));
1310
1311 // test queries, ec, for existing file
1312 ec.assign(-1,poison_category());
1313 BOOST_TEST(fs::exists(".", ec));
1314 BOOST_TEST(ec.value() == 0);
1315 BOOST_TEST(ec.category() == system_category());
1316 ec.assign(-1,poison_category());
1317 BOOST_TEST(!fs::is_regular_file(".", ec));
1318 BOOST_TEST(ec.value() == 0);
1319 BOOST_TEST(ec.category() == system_category());
1320 ec.assign(-1,poison_category());
1321 BOOST_TEST(fs::is_directory(".", ec));
1322 BOOST_TEST(ec.value() == 0);
1323 BOOST_TEST(ec.category() == system_category());
1324
1325 // test queries, ec, for non-existing file
1326 ec.assign(-1,poison_category());
1327 BOOST_TEST(!fs::exists(p, ec));
1328 BOOST_TEST(ec.value() != 0);
1329 BOOST_TEST(ec.category() == system_category());
1330 ec.assign(-1,poison_category());
1331 BOOST_TEST(!fs::is_regular_file(p, ec));
1332 BOOST_TEST(ec.value() != 0);
1333 BOOST_TEST(ec.category() == system_category());
1334 ec.assign(-1,poison_category());
1335 BOOST_TEST(!fs::is_directory(p, ec));
1336 BOOST_TEST(ec.value() != 0);
1337 BOOST_TEST(ec.category() == system_category());
1338 }
1339
1340 // remove_tests --------------------------------------------------------------------//
1341
remove_tests(const fs::path & dirx)1342 void remove_tests(const fs::path& dirx)
1343 {
1344 cout << "remove_tests..." << endl;
1345
1346 // remove() file
1347 fs::path f1x = dirx / "shortlife";
1348 BOOST_TEST(!fs::exists(f1x));
1349 create_file(f1x, "");
1350 BOOST_TEST(fs::exists(f1x));
1351 BOOST_TEST(!fs::is_directory(f1x));
1352 BOOST_TEST(fs::remove(f1x));
1353 BOOST_TEST(!fs::exists(f1x));
1354 BOOST_TEST(!fs::remove("no-such-file"));
1355 BOOST_TEST(!fs::remove("no-such-directory/no-such-file"));
1356
1357 // remove() directory
1358 fs::path d1x = dirx / "shortlife_dir";
1359 BOOST_TEST(!fs::exists(d1x));
1360 fs::create_directory(d1x);
1361 BOOST_TEST(fs::exists(d1x));
1362 BOOST_TEST(fs::is_directory(d1x));
1363 BOOST_TEST(fs::is_empty(d1x));
1364 bad_remove_dir = dirx;
1365 BOOST_TEST(CHECK_EXCEPTION(bad_remove, ENOTEMPTY));
1366 BOOST_TEST(fs::remove(d1x));
1367 BOOST_TEST(!fs::exists(d1x));
1368 }
1369
1370 // remove_symlink_tests ------------------------------------------------------------//
1371
remove_symlink_tests()1372 void remove_symlink_tests()
1373 {
1374 cout << "remove_symlink_tests..." << endl;
1375
1376 // remove() dangling symbolic link
1377 fs::path link("dangling_link");
1378 fs::remove(link); // remove any residue from past tests
1379 BOOST_TEST(!fs::is_symlink(link));
1380 BOOST_TEST(!fs::exists(link));
1381 fs::create_symlink("nowhere", link);
1382 BOOST_TEST(!fs::exists(link));
1383 BOOST_TEST(fs::is_symlink(link));
1384 BOOST_TEST(fs::remove(link));
1385 BOOST_TEST(!fs::is_symlink(link));
1386
1387 // remove() self-refering symbolic link
1388 link = "link_to_self";
1389 fs::remove(link); // remove any residue from past tests
1390 BOOST_TEST(!fs::is_symlink(link));
1391 BOOST_TEST(!fs::exists(link));
1392 fs::create_symlink(link, link);
1393 BOOST_TEST(fs::remove(link));
1394 BOOST_TEST(!fs::exists(link));
1395 BOOST_TEST(!fs::is_symlink(link));
1396
1397 // remove() cyclic symbolic link
1398 link = "link_to_a";
1399 fs::path link2("link_to_b");
1400 fs::remove(link); // remove any residue from past tests
1401 fs::remove(link2); // remove any residue from past tests
1402 BOOST_TEST(!fs::is_symlink(link));
1403 BOOST_TEST(!fs::exists(link));
1404 fs::create_symlink(link, link2);
1405 fs::create_symlink(link2, link);
1406 BOOST_TEST(fs::remove(link));
1407 BOOST_TEST(fs::remove(link2));
1408 BOOST_TEST(!fs::exists(link));
1409 BOOST_TEST(!fs::exists(link2));
1410 BOOST_TEST(!fs::is_symlink(link));
1411
1412 // remove() symbolic link to file
1413 fs::path f1x = "link_target";
1414 fs::remove(f1x); // remove any residue from past tests
1415 BOOST_TEST(!fs::exists(f1x));
1416 create_file(f1x, "");
1417 BOOST_TEST(fs::exists(f1x));
1418 BOOST_TEST(!fs::is_directory(f1x));
1419 BOOST_TEST(fs::is_regular_file(f1x));
1420 link = "non_dangling_link";
1421 fs::create_symlink(f1x, link);
1422 BOOST_TEST(fs::exists(link));
1423 BOOST_TEST(!fs::is_directory(link));
1424 BOOST_TEST(fs::is_regular_file(link));
1425 BOOST_TEST(fs::is_symlink(link));
1426 BOOST_TEST(fs::remove(link));
1427 BOOST_TEST(fs::exists(f1x));
1428 BOOST_TEST(!fs::exists(link));
1429 BOOST_TEST(!fs::is_symlink(link));
1430 BOOST_TEST(fs::remove(f1x));
1431 BOOST_TEST(!fs::exists(f1x));
1432 }
1433
1434 // absolute_tests -----------------------------------------------------------------//
1435
absolute_tests()1436 void absolute_tests()
1437 {
1438 cout << "absolute_tests..." << endl;
1439
1440 BOOST_TEST_EQ(fs::absolute(""), fs::current_path() );
1441 BOOST_TEST_EQ(fs::absolute("", ""), fs::current_path() );
1442 BOOST_TEST_EQ(fs::absolute(fs::current_path() / "foo/bar"), fs::current_path() / "foo/bar");
1443 BOOST_TEST_EQ(fs::absolute("foo"), fs::current_path() / "foo");
1444 BOOST_TEST_EQ(fs::absolute("foo", fs::current_path()), fs::current_path() / "foo");
1445 BOOST_TEST_EQ(fs::absolute("bar", "foo"), fs::current_path() / "foo" / "bar");
1446 BOOST_TEST_EQ(fs::absolute("/foo"), fs::current_path().root_path().string() + "foo");
1447
1448 # ifdef BOOST_WINDOWS_API
1449 BOOST_TEST_EQ(fs::absolute("a:foo", "b:/bar"), "a:/bar/foo");
1450 # endif
1451
1452 // these tests were moved from elsewhere, so may duplicate some of the above tests
1453
1454 // p.empty()
1455 BOOST_TEST_EQ(fs::absolute(fs::path(), "//foo/bar"), "//foo/bar");
1456 if (platform == "Windows")
1457 {
1458 BOOST_TEST_EQ(fs::absolute(fs::path(), "a:/bar"), "a:/bar");
1459 }
1460
1461 // p.has_root_name()
1462 // p.has_root_directory()
1463 BOOST_TEST_EQ(fs::absolute(fs::path("//foo/bar"), "//uvw/xyz"), "//foo/bar");
1464 if (platform == "Windows")
1465 {
1466 BOOST_TEST_EQ(fs::absolute(fs::path("a:/bar"), "b:/xyz"), "a:/bar");
1467 }
1468 // !p.has_root_directory()
1469 BOOST_TEST_EQ(fs::absolute(fs::path("//net"), "//xyz/"), "//net/");
1470 BOOST_TEST_EQ(fs::absolute(fs::path("//net"), "//xyz/abc"), "//net/abc");
1471 BOOST_TEST_EQ(fs::absolute(fs::path("//net"), "//xyz/abc/def"), "//net/abc/def");
1472 if (platform == "Windows")
1473 {
1474 BOOST_TEST_EQ(fs::absolute(fs::path("a:"), "b:/"), "a:/");
1475 BOOST_TEST_EQ(fs::absolute(fs::path("a:"),"b:/abc"), "a:/abc");
1476 BOOST_TEST_EQ(fs::absolute(fs::path("a:"),"b:/abc/def"), "a:/abc/def");
1477 BOOST_TEST_EQ(fs::absolute(fs::path("a:foo"), "b:/"), "a:/foo");
1478 BOOST_TEST_EQ(fs::absolute(fs::path("a:foo"), "b:/abc"), "a:/abc/foo");
1479 BOOST_TEST_EQ(fs::absolute(fs::path("a:foo"), "b:/abc/def"), "a:/abc/def/foo");
1480 BOOST_TEST_EQ(fs::absolute(fs::path("a:foo/bar"), "b:/"), "a:/foo/bar");
1481 BOOST_TEST_EQ(fs::absolute(fs::path("a:foo/bar"), "b:/abc"), "a:/abc/foo/bar");
1482 BOOST_TEST_EQ(fs::absolute(fs::path("a:foo/bar"), "b:/abc/def"), "a:/abc/def/foo/bar");
1483 }
1484 // !p.has_root_name()
1485 // p.has_root_directory()
1486 BOOST_TEST_EQ(fs::absolute(fs::path("/"), "//xyz/"), "//xyz/");
1487 BOOST_TEST_EQ(fs::absolute(fs::path("/"), "//xyz/abc"), "//xyz/");
1488 BOOST_TEST_EQ(fs::absolute(fs::path("/foo"), "//xyz/"), "//xyz/foo");
1489 BOOST_TEST_EQ(fs::absolute(fs::path("/foo"), "//xyz/abc"), "//xyz/foo");
1490 // !p.has_root_directory()
1491 BOOST_TEST_EQ(fs::absolute(fs::path("foo"), "//xyz/abc"), "//xyz/abc/foo");
1492 BOOST_TEST_EQ(fs::absolute(fs::path("foo/bar"), "//xyz/abc"), "//xyz/abc/foo/bar");
1493 BOOST_TEST_EQ(fs::absolute(fs::path("."), "//xyz/abc"), "//xyz/abc/.");
1494 BOOST_TEST_EQ(fs::absolute(fs::path(".."), "//xyz/abc"), "//xyz/abc/..");
1495 BOOST_TEST_EQ(fs::absolute(fs::path("./foo"), "//xyz/abc"), "//xyz/abc/./foo");
1496 BOOST_TEST_EQ(fs::absolute(fs::path("../foo"), "//xyz/abc"), "//xyz/abc/../foo");
1497 if (platform == "POSIX")
1498 {
1499 BOOST_TEST_EQ(fs::absolute(fs::path("foo"), "/abc"), "/abc/foo");
1500 BOOST_TEST_EQ(fs::absolute(fs::path("foo/bar"), "/abc"), "/abc/foo/bar");
1501 BOOST_TEST_EQ(fs::absolute(fs::path("."), "/abc"), "/abc/.");
1502 BOOST_TEST_EQ(fs::absolute(fs::path(".."), "/abc"), "/abc/..");
1503 BOOST_TEST_EQ(fs::absolute(fs::path("./foo"), "/abc"), "/abc/./foo");
1504 BOOST_TEST_EQ(fs::absolute(fs::path("../foo"), "/abc"), "/abc/../foo");
1505 }
1506
1507 }
1508
1509 // canonical_basic_tests -----------------------------------------------------------//
1510
canonical_basic_tests()1511 void canonical_basic_tests()
1512 {
1513 cout << "canonical_basic_tests..." << endl;
1514
1515 // error handling
1516 error_code ec;
1517 ec.clear();
1518 fs::canonical("no-such-file", ec);
1519 BOOST_TEST(ec);
1520 ec.clear();
1521 fs::canonical("no-such-file", "x", ec);
1522 BOOST_TEST(ec);
1523 bool ok(false);
1524 try { fs::canonical("no-such-file"); }
1525 catch (const fs::filesystem_error&) { ok = true; }
1526 BOOST_TEST(ok);
1527
1528 // non-symlink tests; also see canonical_symlink_tests()
1529 BOOST_TEST_EQ(fs::canonical(""), fs::current_path());
1530 BOOST_TEST_EQ(fs::canonical("", fs::current_path()), fs::current_path());
1531 BOOST_TEST_EQ(fs::canonical("", ""), fs::current_path());
1532 BOOST_TEST_EQ(fs::canonical(fs::current_path()), fs::current_path());
1533 BOOST_TEST_EQ(fs::canonical(fs::current_path(), ""), fs::current_path());
1534 BOOST_TEST_EQ(fs::canonical(fs::current_path(), "no-such-file"), fs::current_path());
1535
1536 BOOST_TEST_EQ(fs::canonical("."), fs::current_path());
1537 BOOST_TEST_EQ(fs::canonical(".."), fs::current_path().parent_path());
1538 BOOST_TEST_EQ(fs::canonical("/"), fs::current_path().root_path());
1539
1540 fs::path relative_dir(dir.filename());
1541 BOOST_TEST_EQ(fs::canonical(dir), dir);
1542 BOOST_TEST_EQ(fs::canonical(relative_dir), dir);
1543 BOOST_TEST_EQ(fs::canonical(dir / "f0"), dir / "f0");
1544 BOOST_TEST_EQ(fs::canonical(relative_dir / "f0"), dir / "f0");
1545 BOOST_TEST_EQ(fs::canonical(relative_dir / "./f0"), dir / "f0");
1546 BOOST_TEST_EQ(fs::canonical(relative_dir / "d1/../f0"), dir / "f0");
1547
1548 // treat parent of root as itself on both POSIX and Windows
1549 fs::path init(fs::initial_path());
1550 fs::path root(init.root_path());
1551 fs::path::const_iterator it(init.begin());
1552 fs::path first; // relative first non-root directory
1553 # ifdef BOOST_WINDOWS_API
1554 if (!init.empty())
1555 ++it;
1556 # endif
1557 if (++it != init.end())
1558 first = *it;
1559 fs::path expected(root/first);
1560
1561 cout << " init: " << init << endl;
1562 cout << " root: " << root << endl;
1563 cout << " first: " << first << endl;
1564 cout << " expected: " << expected << endl;
1565
1566 // ticket 10187 tests
1567 BOOST_TEST_EQ(fs::canonical(root / "../.." / first), expected);
1568 BOOST_TEST_EQ(fs::canonical(fs::path("../..") / first, root), expected);
1569 BOOST_TEST_EQ(fs::canonical(fs::path("/../..") / first, fs::current_path().root_name()), expected);
1570
1571 // ticket 9683 test
1572 BOOST_TEST_EQ(fs::canonical(root / first / "../../../../.."), root);
1573 }
1574
1575 // canonical_symlink_tests -----------------------------------------------------------//
1576
canonical_symlink_tests()1577 void canonical_symlink_tests()
1578 {
1579 cout << "canonical_symlink_tests..." << endl;
1580
1581 fs::path relative_dir(dir.filename());
1582 BOOST_TEST_EQ(fs::canonical(dir / "sym-d1/f2"), d1 / "f2");
1583 BOOST_TEST_EQ(fs::canonical(relative_dir / "sym-d1/f2"), d1 / "f2");
1584 }
1585
1586 // copy_file_tests ------------------------------------------------------------------//
1587
copy_file_tests(const fs::path & f1x,const fs::path & d1x)1588 void copy_file_tests(const fs::path& f1x, const fs::path& d1x)
1589 {
1590 cout << "copy_file_tests..." << endl;
1591
1592 BOOST_TEST(fs::exists(f1x));
1593 fs::remove(d1x / "f2"); // remove possible residue from prior testing
1594 BOOST_TEST(fs::exists(d1x));
1595 BOOST_TEST(!fs::exists(d1x / "f2"));
1596 cout << " copy " << f1x << " to " << d1x / "f2" << endl;
1597 bool file_copied = fs::copy_file(f1x, d1x / "f2");
1598 cout << " copy complete" << endl;
1599 BOOST_TEST(file_copied);
1600 BOOST_TEST(fs::exists(f1x));
1601 BOOST_TEST(fs::exists(d1x / "f2"));
1602 BOOST_TEST(!fs::is_directory(d1x / "f2"));
1603 verify_file(d1x / "f2", "file-f1");
1604
1605 bool copy_ex_ok = false;
1606 file_copied = false;
1607 try { file_copied = fs::copy_file(f1x, d1x / "f2"); }
1608 catch (const fs::filesystem_error &) { copy_ex_ok = true; }
1609 BOOST_TEST(copy_ex_ok);
1610 BOOST_TEST(!file_copied);
1611
1612 file_copied = false;
1613 copy_ex_ok = false;
1614 try { file_copied = fs::copy_file(f1x, d1x / "f2", fs::copy_options::none); }
1615 catch (const fs::filesystem_error &) { copy_ex_ok = true; }
1616 BOOST_TEST(copy_ex_ok);
1617 BOOST_TEST(!file_copied);
1618
1619 fs::remove(d1x / "f2");
1620 create_file(d1x / "f2", "1234567890");
1621 BOOST_TEST_EQ(fs::file_size(d1x / "f2"), 10U);
1622 file_copied = false;
1623 copy_ex_ok = true;
1624 try { file_copied = fs::copy_file(f1x, d1x / "f2", fs::copy_options::skip_existing); }
1625 catch (const fs::filesystem_error &) { copy_ex_ok = false; }
1626 BOOST_TEST(copy_ex_ok);
1627 BOOST_TEST(!file_copied);
1628 BOOST_TEST_EQ(fs::file_size(d1x / "f2"), 10U);
1629 verify_file(d1x / "f2", "1234567890");
1630
1631 file_copied = false;
1632 copy_ex_ok = true;
1633 try { file_copied = fs::copy_file(f1x, d1x / "f2-non-existing", fs::copy_options::skip_existing); }
1634 catch (const fs::filesystem_error &) { copy_ex_ok = false; }
1635 BOOST_TEST(copy_ex_ok);
1636 BOOST_TEST(file_copied);
1637 BOOST_TEST_EQ(fs::file_size(d1x / "f2-non-existing"), 7U);
1638 verify_file(d1x / "f2-non-existing", "file-f1");
1639 fs::remove(d1x / "f2-non-existing");
1640
1641 file_copied = false;
1642 copy_ex_ok = true;
1643 try { file_copied = fs::copy_file(f1x, d1x / "f2", fs::copy_options::update_existing); }
1644 catch (const fs::filesystem_error &) { copy_ex_ok = false; }
1645 BOOST_TEST(copy_ex_ok);
1646 BOOST_TEST(!file_copied);
1647 BOOST_TEST_EQ(fs::file_size(d1x / "f2"), 10U);
1648 verify_file(d1x / "f2", "1234567890");
1649
1650 // Sleep for a while so that the last modify time is more recent for new files
1651 #if defined(BOOST_POSIX_API)
1652 sleep(2);
1653 #else
1654 Sleep(2000);
1655 #endif
1656
1657 create_file(d1x / "f2-more-recent", "x");
1658 BOOST_TEST_EQ(fs::file_size(d1x / "f2-more-recent"), 1U);
1659 file_copied = false;
1660 copy_ex_ok = true;
1661 try { file_copied = fs::copy_file(d1x / "f2-more-recent", d1x / "f2", fs::copy_options::update_existing); }
1662 catch (const fs::filesystem_error &) { copy_ex_ok = false; }
1663 BOOST_TEST(copy_ex_ok);
1664 BOOST_TEST(file_copied);
1665 BOOST_TEST_EQ(fs::file_size(d1x / "f2"), 1U);
1666 verify_file(d1x / "f2", "x");
1667 fs::remove(d1x / "f2-more-recent");
1668
1669 fs::remove(d1x / "f2");
1670 create_file(d1x / "f2", "1234567890");
1671 BOOST_TEST_EQ(fs::file_size(d1x / "f2"), 10U);
1672 file_copied = false;
1673 copy_ex_ok = true;
1674 try { file_copied = fs::copy_file(f1x, d1x / "f2", fs::copy_options::overwrite_existing); }
1675 catch (const fs::filesystem_error &) { copy_ex_ok = false; }
1676 BOOST_TEST(copy_ex_ok);
1677 BOOST_TEST(file_copied);
1678 BOOST_TEST_EQ(fs::file_size(d1x / "f2"), 7U);
1679 verify_file(d1x / "f2", "file-f1");
1680 }
1681
1682 // symlink_status_tests -------------------------------------------------------------//
1683
symlink_status_tests()1684 void symlink_status_tests()
1685 {
1686 cout << "symlink_status_tests..." << endl;
1687
1688 boost::system::error_code ec;
1689
1690 fs::path dangling_sym(dir / "dangling-sym");
1691 fs::path dangling_directory_sym(dir / "dangling-directory-sym");
1692 fs::path sym_d1(dir / "sym-d1");
1693 fs::path symsym_d1(dir / "symsym-d1");
1694 fs::path sym_f1(dir / "sym-f1");
1695 fs::path symsym_f1(dir / "symsym-f1");
1696 fs::create_symlink("does not exist", dangling_sym);
1697 fs::create_directory_symlink("does not exist", dangling_directory_sym);
1698 fs::create_directory_symlink(d1, sym_d1);
1699 fs::create_directory_symlink(sym_d1, symsym_d1);
1700 fs::create_symlink(f1, sym_f1);
1701 fs::create_symlink(sym_f1, symsym_f1);
1702
1703 // verify all cases detected as symlinks
1704 BOOST_TEST_EQ(fs::symlink_status(dangling_sym, ec).type(), fs::symlink_file);
1705 BOOST_TEST_EQ(fs::symlink_status(dangling_directory_sym, ec).type(), fs::symlink_file);
1706 BOOST_TEST_EQ(fs::symlink_status(sym_d1, ec).type(), fs::symlink_file);
1707 BOOST_TEST_EQ(fs::symlink_status(symsym_d1, ec).type(), fs::symlink_file);
1708 BOOST_TEST_EQ(fs::symlink_status(sym_f1, ec).type(), fs::symlink_file);
1709 BOOST_TEST_EQ(fs::symlink_status(symsym_f1, ec).type(), fs::symlink_file);
1710
1711 // verify all cases resolve to the (possibly recursive) symlink target
1712 BOOST_TEST_EQ(fs::status(dangling_sym, ec).type(), fs::file_not_found);
1713 BOOST_TEST_EQ(fs::status(dangling_directory_sym, ec).type(), fs::file_not_found);
1714
1715 BOOST_TEST_EQ(fs::status(sym_d1, ec).type(), fs::directory_file);
1716 BOOST_TEST_EQ(fs::status(sym_d1 / "d1f1", ec).type(), fs::regular_file);
1717 BOOST_TEST_EQ(fs::status(symsym_d1, ec).type(), fs::directory_file);
1718 BOOST_TEST_EQ(fs::status(symsym_d1 / "d1f1", ec).type(), fs::regular_file);
1719 BOOST_TEST_EQ(fs::status(sym_f1, ec).type(), fs::regular_file);
1720 BOOST_TEST_EQ(fs::status(symsym_f1, ec).type(), fs::regular_file);
1721
1722 #ifdef BOOST_WINDOWS_API
1723
1724 // On Windows, telling if a filesystem entry is a symlink (or junction which is
1725 // treated as a symlink), rather than some other kind of reparse point, requires some
1726 // baroque code. See ticket #4663, filesystem objects falsely identified as symlinks.
1727 // This test checks two directory entries created by Windows itself to verify
1728 // is_symlink() works correctly. Try "dir /A %HOMEPATH%\.." from the command line to
1729 // verify this test is valid on your version of Windows. It only works on Vista and
1730 // later.
1731
1732 fs::path users(getenv("HOMEDRIVE"));
1733 BOOST_TEST(!users.empty());
1734 users /= "\\Users";
1735 BOOST_TEST(fs::exists(users));
1736 BOOST_TEST(fs::exists(users/"All Users"));
1737 BOOST_TEST(fs::exists(users/"Default User"));
1738 BOOST_TEST(fs::is_symlink(users/"All Users")); // dir /A reports <SYMLINKD>
1739 BOOST_TEST(fs::is_symlink(users/"Default User")); // dir /A reports <JUNCTION>
1740
1741 #endif
1742 }
1743
1744 // copy_symlink_tests ---------------------------------------------------------------//
1745
copy_symlink_tests(const fs::path & f1x,const fs::path & d1x)1746 void copy_symlink_tests(const fs::path& f1x, const fs::path& d1x)
1747 {
1748 cout << "copy_symlink_tests..." << endl;
1749
1750 BOOST_TEST(fs::exists(f1x));
1751 BOOST_TEST(fs::exists(d1x));
1752 fs::path sym1(d1x / "symlink1");
1753 fs::remove(sym1); // remove possible residue from prior testing
1754 fs::create_symlink(f1x, sym1);
1755 BOOST_TEST(fs::exists(sym1));
1756 BOOST_TEST(fs::is_symlink(sym1));
1757 fs::path sym2(d1x / "symlink2");
1758 fs::copy_symlink(sym1, sym2);
1759 BOOST_TEST(fs::exists(sym2));
1760 BOOST_TEST(fs::is_symlink(sym2));
1761 //fs::path sym3(d1x / "symlink3");
1762 //fs::copy(sym1, sym3);
1763 //BOOST_TEST(fs::exists(sym3));
1764 //BOOST_TEST(fs::is_symlink(sym3));
1765
1766 bool copy_ex_ok = false;
1767 try { fs::copy_symlink("no-such-file", "new-symlink1"); }
1768 catch (const fs::filesystem_error &) { copy_ex_ok = true; }
1769 BOOST_TEST(copy_ex_ok);
1770
1771 copy_ex_ok = false;
1772 try { fs::copy_symlink(f1x, "new-symlink2"); } // should fail; f1x not symlink
1773 catch (const fs::filesystem_error &) { copy_ex_ok = true; }
1774 BOOST_TEST(copy_ex_ok);
1775 }
1776
1777 // write_time_tests ----------------------------------------------------------------//
1778
write_time_tests(const fs::path & dirx)1779 void write_time_tests(const fs::path& dirx)
1780 {
1781 cout << "write_time_tests..." << endl;
1782
1783 fs::path f1x = dirx / "foobar2";
1784 create_file(f1x, "foobar2");
1785 BOOST_TEST(fs::exists(f1x));
1786 BOOST_TEST(!fs::is_directory(f1x));
1787 BOOST_TEST(fs::is_regular_file(f1x));
1788 BOOST_TEST(fs::file_size(f1x) == 7);
1789 verify_file(f1x, "foobar2");
1790
1791 // Some file system report last write time as local (FAT), while
1792 // others (NTFS) report it as UTC. The C standard does not specify
1793 // if time_t is local or UTC.
1794
1795 std::time_t ft = fs::last_write_time(f1x);
1796 cout << "\n UTC last_write_time() for a file just created is "
1797 << std::asctime(std::gmtime(&ft)) << endl;
1798
1799 std::tm * tmp = std::localtime(&ft);
1800 cout << "\n Year is " << tmp->tm_year << endl;
1801 --tmp->tm_year;
1802 cout << " Change year to " << tmp->tm_year << endl;
1803 fs::last_write_time(f1x, std::mktime(tmp));
1804 std::time_t ft2 = fs::last_write_time(f1x);
1805 cout << " last_write_time() for the file is now "
1806 << std::asctime(std::gmtime(&ft2)) << endl;
1807 BOOST_TEST(ft != fs::last_write_time(f1x));
1808
1809 cout << "\n Reset to current time" << endl;
1810 fs::last_write_time(f1x, ft);
1811 double time_diff = std::difftime(ft, fs::last_write_time(f1x));
1812 cout
1813 << " original last_write_time() - current last_write_time() is "
1814 << time_diff << " seconds" << endl;
1815 BOOST_TEST(time_diff >= -60.0 && time_diff <= 60.0);
1816 }
1817
1818 // platform_specific_tests ---------------------------------------------------------//
1819
platform_specific_tests()1820 void platform_specific_tests()
1821 {
1822 // Windows only tests
1823 if (platform == "Windows")
1824 {
1825 cout << "Windows specific tests..." << endl;
1826 if (!skip_long_windows_tests)
1827 {
1828 cout << " (may take several seconds)"<< endl;
1829
1830 BOOST_TEST(!fs::exists(fs::path("//share-not")));
1831 BOOST_TEST(!fs::exists(fs::path("//share-not/")));
1832 BOOST_TEST(!fs::exists(fs::path("//share-not/foo")));
1833 }
1834 cout << endl;
1835
1836 BOOST_TEST(!fs::exists("tools/jam/src/:sys:stat.h")); // !exists() if ERROR_INVALID_NAME
1837 BOOST_TEST(!fs::exists(":sys:stat.h")); // !exists() if ERROR_INVALID_PARAMETER
1838 BOOST_TEST(dir.string().size() > 1
1839 && dir.string()[1] == ':'); // verify path includes drive
1840
1841 BOOST_TEST(fs::system_complete("").empty());
1842 BOOST_TEST(fs::system_complete("/") == fs::initial_path().root_path());
1843 BOOST_TEST(fs::system_complete("foo")
1844 == fs::initial_path() / "foo");
1845
1846 fs::path p1(fs::system_complete("/foo"));
1847 BOOST_TEST_EQ(p1.string().size(), 6U); // this failed during v3 development due to bug
1848 std::string s1(p1.string() );
1849 std::string s2(fs::initial_path().root_path().string()+"foo");
1850 BOOST_TEST_EQ(s1, s2);
1851
1852 BOOST_TEST(fs::system_complete(fs::path(fs::initial_path().root_name()))
1853 == fs::initial_path());
1854 BOOST_TEST(fs::system_complete(fs::path(fs::initial_path().root_name().string()
1855 + "foo")).string() == fs::initial_path() / "foo");
1856 BOOST_TEST(fs::system_complete(fs::path("c:/")).generic_string()
1857 == "c:/");
1858 BOOST_TEST(fs::system_complete(fs::path("c:/foo")).generic_string()
1859 == "c:/foo");
1860 BOOST_TEST(fs::system_complete(fs::path("//share")).generic_string()
1861 == "//share");
1862
1863 #if defined(BOOST_FILESYSTEM_HAS_MKLINK)
1864 // Issue 9016 asked that NTFS directory junctions be recognized as directories.
1865 // That is equivalent to recognizing them as symlinks, and then the normal symlink
1866 // mechanism takes care of recognizing them as directories.
1867 //
1868 // Directory junctions are very similar to symlinks, but have some performance
1869 // and other advantages over symlinks. They can be created from the command line
1870 // with "mklink /j junction-name target-path".
1871
1872 {
1873 cout << " directory junction tests..." << endl;
1874 BOOST_TEST(fs::exists(dir));
1875 BOOST_TEST(fs::exists(dir / "d1/d1f1"));
1876 fs::path junc(dir / "junc");
1877 if (fs::exists(junc))
1878 fs::remove(junc);
1879 fs::path new_junc(dir / "new-junc");
1880 if (fs::exists(new_junc))
1881 fs::remove(new_junc);
1882
1883 //cout << " dir is " << dir << endl;
1884 //cout << " junc is " << junc << endl;
1885 //cout << " new_junc is " << new_junc << endl;
1886 //cout << " current_path() is " << fs::current_path() << endl;
1887
1888 fs::path cur_path(fs::current_path());
1889 fs::current_path(dir);
1890 //cout << " current_path() is " << fs::current_path() << endl;
1891 BOOST_TEST(std::system("mklink /j junc d1") == 0);
1892 //std::system("dir");
1893 fs::current_path(cur_path);
1894 //cout << " current_path() is " << fs::current_path() << endl;
1895
1896 BOOST_TEST(fs::exists(junc));
1897 BOOST_TEST(fs::is_symlink(junc));
1898 BOOST_TEST(fs::is_directory(junc));
1899 BOOST_TEST(!fs::is_regular_file(junc));
1900 BOOST_TEST(fs::exists(junc / "d1f1"));
1901 BOOST_TEST(fs::is_regular_file(junc / "d1f1"));
1902
1903 int count = 0;
1904 for (fs::directory_iterator itr(junc); itr != fs::directory_iterator(); ++itr)
1905 {
1906 //cout << itr->path() << endl;
1907 ++count;
1908 }
1909 cout << " iteration count is " << count << endl;
1910 BOOST_TEST(count > 0);
1911
1912 fs::rename(junc, new_junc);
1913 BOOST_TEST(!fs::exists(junc));
1914 BOOST_TEST(fs::exists(new_junc));
1915 BOOST_TEST(fs::is_symlink(new_junc));
1916 BOOST_TEST(fs::is_directory(new_junc));
1917 BOOST_TEST(!fs::is_regular_file(new_junc));
1918 BOOST_TEST(fs::exists(new_junc / "d1f1"));
1919 BOOST_TEST(fs::is_regular_file(new_junc / "d1f1"));
1920
1921 fs::remove(new_junc);
1922 BOOST_TEST(!fs::exists(new_junc / "d1f1"));
1923 BOOST_TEST(!fs::exists(new_junc));
1924 BOOST_TEST(fs::exists(dir));
1925 BOOST_TEST(fs::exists(dir / "d1/d1f1"));
1926 }
1927 #endif // defined(BOOST_FILESYSTEM_HAS_MKLINK)
1928 } // Windows
1929
1930 else if (platform == "POSIX")
1931 {
1932 cout << "POSIX specific tests..." << endl;
1933 BOOST_TEST(fs::system_complete("").empty());
1934 BOOST_TEST(fs::initial_path().root_path().string() == "/");
1935 BOOST_TEST(fs::system_complete("/").string() == "/");
1936 BOOST_TEST(fs::system_complete("foo").string()
1937 == fs::initial_path().string()+"/foo");
1938 BOOST_TEST(fs::system_complete("/foo").string()
1939 == fs::initial_path().root_path().string()+"foo");
1940 } // POSIX
1941 }
1942
1943 // initial_tests -------------------------------------------------------------------//
1944
initial_tests()1945 void initial_tests()
1946 {
1947 cout << "initial_tests..." << endl;
1948
1949 cout << " current_path().string() is\n \""
1950 << fs::initial_path().string()
1951 << "\"\n\n";
1952 BOOST_TEST(fs::initial_path() == fs::current_path());
1953 BOOST_TEST(fs::initial_path().is_absolute());
1954 BOOST_TEST(fs::current_path().is_absolute());
1955 BOOST_TEST(fs::initial_path().string()
1956 == fs::current_path().string());
1957 }
1958
1959 // space_tests ---------------------------------------------------------------------//
1960
space_tests()1961 void space_tests()
1962 {
1963 cout << "space_tests..." << endl;
1964
1965 // make some reasonable assuptions for testing purposes
1966 fs::space_info spi(fs::space(dir));
1967 BOOST_TEST(spi.capacity > 1000000);
1968 BOOST_TEST(spi.free > 1000);
1969 BOOST_TEST(spi.capacity > spi.free);
1970 BOOST_TEST(spi.free >= spi.available);
1971
1972 // it is convenient to display space, but older VC++ versions choke
1973 # if !defined(BOOST_MSVC) || _MSC_VER >= 1300 // 1300 == VC++ 7.0
1974 cout << " capacity = " << spi.capacity << '\n';
1975 cout << " free = " << spi.free << '\n';
1976 cout << " available = " << spi.available << '\n';
1977 # endif
1978
1979 // Test that we can specify path to file
1980 fs::path file = dir / "file";
1981 create_file(file);
1982
1983 fs::space_info spi_file(fs::space(file));
1984 BOOST_TEST_EQ(spi_file.capacity, spi.capacity);
1985
1986 fs::remove(file);
1987 }
1988
1989 // equivalent_tests ----------------------------------------------------------------//
1990
equivalent_tests(const fs::path & f1x)1991 void equivalent_tests(const fs::path& f1x)
1992 {
1993 cout << "equivalent_tests..." << endl;
1994
1995 BOOST_TEST(CHECK_EXCEPTION(bad_equivalent, ENOENT));
1996 BOOST_TEST(fs::equivalent(f1x, dir / "f1"));
1997 BOOST_TEST(fs::equivalent(dir, d1 / ".."));
1998 BOOST_TEST(!fs::equivalent(f1x, dir));
1999 BOOST_TEST(!fs::equivalent(dir, f1x));
2000 BOOST_TEST(!fs::equivalent(d1, d2));
2001 BOOST_TEST(!fs::equivalent(dir, ng));
2002 BOOST_TEST(!fs::equivalent(ng, dir));
2003 BOOST_TEST(!fs::equivalent(f1x, ng));
2004 BOOST_TEST(!fs::equivalent(ng, f1x));
2005 }
2006
2007 // temp_directory_path_tests -------------------------------------------------------//
2008 // contributed by Jeff Flinn
2009
2010 struct guarded_env_var
2011 {
2012 struct previous_value
2013 {
2014 std::string m_name;
2015 std::string m_string;
2016 bool m_empty;
2017
previous_value__anone45b62480111::guarded_env_var::previous_value2018 previous_value(const char* name)
2019 : m_name(name)
2020 , m_empty (true)
2021 {
2022 if(const char* value = getenv(name))
2023 {
2024 m_string.assign(value);
2025 m_empty = false;
2026 }
2027 else
2028 {
2029 m_empty = true;
2030 }
2031 }
~previous_value__anone45b62480111::guarded_env_var::previous_value2032 ~previous_value()
2033 {
2034 m_empty? unsetenv_(m_name.c_str())
2035 : setenv_(m_name.c_str(), m_string.c_str(), 1);
2036 }
2037 };
2038
2039 previous_value m_previous_value;
2040
guarded_env_var__anone45b62480111::guarded_env_var2041 guarded_env_var(const char* name, const char* value)
2042 : m_previous_value(name)
2043 {
2044 // std::cout << name << " old value is \"" << getenv(name) << "\"" << std::endl;
2045 value ? setenv_(name, value, 1) : unsetenv_(name);
2046 // std::cout << name << " new value is \"" << getenv(name) << "\"" << std::endl;
2047 }
2048 };
2049
temp_directory_path_tests()2050 void temp_directory_path_tests()
2051 {
2052 {
2053 cout << "temp_directory_path_tests..." << endl;
2054 cout << " temp_directory_path() is " << fs::temp_directory_path() << endl;
2055
2056 #if defined(BOOST_WINDOWS_API)
2057
2058 //**************************************************************************************//
2059 // Bug in GCC 4.9 getenv() when !defined(__GXX_EXPERIMENTAL_CXX0X__) makes these
2060 // tests meaningless, so skip them
2061 //**************************************************************************************//
2062
2063 #if defined(__CYGWIN__) && !defined(__GXX_EXPERIMENTAL_CXX0X__) && __GNUC__ == 4
2064 cout << "Bug in GCC 4.9 getenv() when !defined(__GXX_EXPERIMENTAL_CXX0X__) makes these"
2065 "tests meaningless, so skip them" << endl;
2066 return;
2067 #endif
2068 // Test ticket #5300, temp_directory_path failure on Windows with path length > 130.
2069 // (This test failed prior to the fix being applied.)
2070 {
2071 const wchar_t long_name[] =
2072 L"12345678901234567890123456789012345678901234567890"
2073 L"12345678901234567890123456789012345678901234567890"
2074 L"12345678901234567890123456789012345678901234567890#" // total 151 chars
2075 ;
2076 fs::path p (temp_dir);
2077 p /= long_name;
2078 fs::create_directory(p);
2079
2080 guarded_env_var tmp_guard("TMP", p.string().c_str());
2081 error_code ec;
2082 fs::path tmp_path = fs::temp_directory_path(ec);
2083 BOOST_TEST(!ec);
2084 BOOST_TEST_EQ(p, tmp_path);
2085 fs::remove(p);
2086 }
2087
2088 // Test ticket #10388, null character at end of filesystem::temp_directory_path path
2089 {
2090 guarded_env_var tmp_guard("TMP", fs::initial_path().string().c_str());
2091
2092 error_code ec;
2093 fs::path tmp_path = fs::temp_directory_path(ec);
2094 BOOST_TEST_EQ(tmp_path, fs::initial_path());
2095 }
2096
2097 #endif
2098 BOOST_TEST(!fs::temp_directory_path().empty());
2099 BOOST_TEST(exists(fs::temp_directory_path()));
2100 fs::path ph = fs::temp_directory_path() / fs::unique_path("temp_directory_path_test_%%%%_%%%%.txt");
2101 {
2102 if(exists(ph)) remove(ph);
2103 std::ofstream f(ph.BOOST_FILESYSTEM_C_STR);
2104 f << "passed";
2105 }
2106 BOOST_TEST(exists(ph));
2107 {
2108 std::ifstream f(ph.BOOST_FILESYSTEM_C_STR);
2109 std::string s;
2110 f >> s;
2111 BOOST_TEST(s == "passed");
2112 }
2113 remove(ph);
2114 BOOST_TEST(!exists(ph));
2115 }
2116
2117 fs::path test_temp_dir = temp_dir;
2118
2119 #if defined(BOOST_POSIX_API)
2120 {
2121 struct guarded_tmp_vars
2122 {
2123 guarded_env_var m_tmpdir ;
2124 guarded_env_var m_tmp ;
2125 guarded_env_var m_temp ;
2126 guarded_env_var m_tempdir;
2127
2128 guarded_tmp_vars
2129 ( const fs::path::value_type* tmpdir
2130 , const fs::path::value_type* tmp
2131 , const fs::path::value_type* temp
2132 , const fs::path::value_type* tempdir
2133 )
2134 : m_tmpdir ("TMPDIR" , tmpdir )
2135 , m_tmp ("TMP" , tmp )
2136 , m_temp ("TEMP" , temp )
2137 , m_tempdir("TEMPDIR", tempdir)
2138 {}
2139 };
2140
2141 {
2142 guarded_tmp_vars vars(test_temp_dir.c_str(), 0, 0, 0);
2143 fs::path ph = fs::temp_directory_path();
2144 BOOST_TEST(equivalent(test_temp_dir, ph));
2145 }
2146 {
2147 guarded_tmp_vars vars(0, test_temp_dir.c_str(), 0, 0);
2148 fs::path ph = fs::temp_directory_path();
2149 BOOST_TEST(equivalent(test_temp_dir, ph));
2150 }
2151 {
2152 guarded_tmp_vars vars(0, 0, test_temp_dir.c_str(), 0);
2153 fs::path ph = fs::temp_directory_path();
2154 BOOST_TEST(equivalent(test_temp_dir, ph));
2155 }
2156 {
2157 guarded_tmp_vars vars(0, 0, 0, test_temp_dir.c_str());
2158 fs::path ph = fs::temp_directory_path();
2159 BOOST_TEST(equivalent(test_temp_dir, ph));
2160 }
2161 }
2162 #endif
2163
2164 #if defined(BOOST_WINDOWS_API)
2165
2166 struct guarded_tmp_vars
2167 {
2168 guarded_env_var m_tmp ;
2169 guarded_env_var m_temp ;
2170 guarded_env_var m_localappdata;
2171 guarded_env_var m_userprofile;
2172
2173 guarded_tmp_vars
2174 ( const char* tmp
2175 , const char* temp
2176 , const char* localappdata
2177 , const char* userprofile
2178 )
2179 : m_tmp ("TMP" , tmp )
2180 , m_temp ("TEMP" , temp )
2181 , m_localappdata ("LOCALAPPDATA" , localappdata)
2182 , m_userprofile ("USERPROFILE" , userprofile )
2183 {}
2184 };
2185
2186 // test the GetWindowsDirectoryW()/Temp fallback
2187 {
2188 guarded_tmp_vars vars(0, 0, 0, 0);
2189 error_code ec;
2190 fs::path ph = fs::temp_directory_path(ec);
2191 BOOST_TEST(!ec);
2192 cout << "Fallback test, temp_directory_path() returned " << ph << endl;
2193 }
2194
2195 {
2196 guarded_tmp_vars vars(test_temp_dir.string().c_str(), 0, 0, 0);
2197 fs::path ph = fs::temp_directory_path();
2198 BOOST_TEST(equivalent(test_temp_dir, ph));
2199 }
2200 {
2201 guarded_tmp_vars vars(0, test_temp_dir.string().c_str(), 0, 0);
2202 fs::path ph = fs::temp_directory_path();
2203 BOOST_TEST(equivalent(test_temp_dir, ph));
2204 }
2205
2206 fs::create_directory(test_temp_dir / L"Temp");
2207 {
2208 guarded_tmp_vars vars(0, 0, test_temp_dir.string().c_str(), 0);
2209 fs::path ph = fs::temp_directory_path();
2210 BOOST_TEST(equivalent(test_temp_dir/L"Temp", ph));
2211 cout << "temp_directory_path() returned " << ph << endl;
2212 }
2213 {
2214 guarded_tmp_vars vars(0, 0, 0, test_temp_dir.string().c_str());
2215 fs::path ph = fs::temp_directory_path();
2216 BOOST_TEST(equivalent(test_temp_dir/L"Temp", ph));
2217 cout << "temp_directory_path() returned " << ph << endl;
2218 }
2219 #endif
2220 }
2221
2222 // weakly_canonical_tests ----------------------------------------------------------//
2223
weakly_canonical_tests()2224 void weakly_canonical_tests()
2225 {
2226 cout << "weakly_canonical_tests..." << endl;
2227 cout << " dir is " << dir << endl;
2228
2229 BOOST_TEST_EQ(fs::weakly_canonical("no-such/foo/bar"), "no-such/foo/bar");
2230 BOOST_TEST_EQ(fs::weakly_canonical("no-such/foo/../bar"), "no-such/bar");
2231 BOOST_TEST_EQ(fs::weakly_canonical(dir), dir);
2232 BOOST_TEST_EQ(fs::weakly_canonical(dir/"no-such/foo/bar"), dir/"no-such/foo/bar");
2233 BOOST_TEST_EQ(fs::weakly_canonical(dir/"no-such/foo/../bar"), dir/"no-such/bar");
2234 BOOST_TEST_EQ(fs::weakly_canonical(dir/"../no-such/foo/../bar"),
2235 dir.parent_path()/"no-such/bar");
2236 BOOST_TEST_EQ(fs::weakly_canonical("c:/no-such/foo/bar"), "c:/no-such/foo/bar");
2237
2238 fs::create_directory_symlink(dir / "d1", dir / "sld1");
2239 BOOST_TEST_EQ(fs::weakly_canonical(dir / "sld1/foo/bar"), dir / "d1/foo/bar");
2240
2241 BOOST_TEST_EQ(relative(dir / "sld1/foo/bar/baz", dir / "d1/foo"), "bar/baz");
2242 }
2243
2244 // _tests --------------------------------------------------------------------------//
2245
2246 //void _tests()
2247 //{
2248 // cout << "_tests..." << endl;
2249 //}
2250
2251 } // unnamed namespace
2252
2253 //------------------------------------------------------------------------------------//
2254 // //
2255 // main //
2256 // //
2257 //------------------------------------------------------------------------------------//
2258
cpp_main(int argc,char * argv[])2259 int cpp_main(int argc, char* argv[])
2260 {
2261 // document state of critical macros
2262 #ifdef BOOST_POSIX_API
2263 cout << "BOOST_POSIX_API is defined\n";
2264 #endif
2265 #ifdef BOOST_WINDOWS_API
2266 cout << "BOOST_WINDOWS_API is defined\n";
2267 #endif
2268
2269 for (; argc > 1; --argc, ++argv)
2270 {
2271 if (*argv[1]=='-' && *(argv[1]+1)=='t')
2272 report_throws = true;
2273 else if (*argv[1]=='-' && *(argv[1]+1)=='x')
2274 cleanup = false;
2275 else if (*argv[1]=='-' && *(argv[1]+1)=='w')
2276 skip_long_windows_tests = true;
2277 }
2278
2279 // The choice of platform to test is made at runtime rather than compile-time
2280 // so that compile errors for all platforms will be detected even though
2281 // only the current platform is runtime tested.
2282 # if defined(BOOST_POSIX_API)
2283 platform = "POSIX";
2284 # elif defined(BOOST_WINDOWS_API)
2285 platform = "Windows";
2286 language_id = ::GetUserDefaultUILanguage();
2287 # else
2288 # error neither BOOST_POSIX_API nor BOOST_WINDOWS_API is defined. See boost/system/api_config.hpp
2289 # endif
2290 cout << "API is " << platform << endl;
2291 cout << "initial_path() is " << fs::initial_path() << endl;
2292 fs::path ip = fs::initial_path();
2293 do_the_right_thing_tests(); // compile-only tests, but call anyhow to suppress warnings
2294
2295 for (fs::path::const_iterator it = ip.begin(); it != ip.end(); ++it)
2296 {
2297 if (it != ip.begin())
2298 cout << ", ";
2299 cout << *it;
2300 }
2301 cout << endl;
2302
2303 dir = fs::initial_path() / temp_dir;
2304
2305 if (fs::exists(dir))
2306 {
2307 cout << "remove residue from prior failed tests..." << endl;
2308 fs::remove_all(dir);
2309 }
2310 BOOST_TEST(!fs::exists(dir));
2311
2312 // several functions give unreasonable results if uintmax_t isn't 64-bits
2313 cout << "sizeof(boost::uintmax_t) = " << sizeof(boost::uintmax_t) << '\n';
2314 BOOST_TEST(sizeof(boost::uintmax_t) >= 8);
2315
2316 initial_tests();
2317 predicate_and_status_tests();
2318 exception_tests();
2319 create_directory_tests();
2320 current_directory_tests();
2321 space_tests();
2322
2323 // create a directory tree that can be used by subsequent tests
2324 //
2325 // dir
2326 // d1
2327 // d1f1 // an empty file
2328 // f0 // an empty file
2329 // f1 // a file containing "file f1"
2330 //
2331 create_tree();
2332
2333 status_of_nonexistent_tests();
2334 status_error_reporting_tests();
2335 directory_iterator_tests();
2336 create_directories_tests(); // must run AFTER directory_iterator_tests
2337
2338 bad_create_directory_path = f1;
2339 BOOST_TEST(CHECK_EXCEPTION(bad_create_directory, EEXIST));
2340 fs::file_status stat = fs::status(f1);
2341 BOOST_TEST(fs::status_known(stat));
2342 BOOST_TEST(fs::exists(stat));
2343 BOOST_TEST(!fs::is_directory(stat));
2344 BOOST_TEST(fs::is_regular_file(stat));
2345 BOOST_TEST(!fs::is_other(stat));
2346 BOOST_TEST(!fs::is_symlink(stat));
2347
2348 equivalent_tests(f1);
2349 create_hard_link_tests();
2350 create_symlink_tests();
2351 resize_file_tests();
2352 absolute_tests();
2353 canonical_basic_tests();
2354 permissions_tests();
2355 copy_file_tests(f1, d1);
2356 if (create_symlink_ok) // only if symlinks supported
2357 {
2358 symlink_status_tests();
2359 copy_symlink_tests(f1, d1);
2360 canonical_symlink_tests();
2361 weakly_canonical_tests();
2362 }
2363 iterator_status_tests(); // lots of cases by now, so a good time to test
2364 // dump_tree(dir);
2365 recursive_directory_iterator_tests();
2366 recursive_iterator_status_tests(); // lots of cases by now, so a good time to test
2367 rename_tests();
2368 remove_tests(dir);
2369 if (create_symlink_ok) // only if symlinks supported
2370 remove_symlink_tests();
2371 write_time_tests(dir);
2372 temp_directory_path_tests();
2373
2374 platform_specific_tests(); // do these last since they take a lot of time on Windows,
2375 // and that's a pain during manual testing
2376
2377 cout << "testing complete" << endl;
2378
2379 // post-test cleanup
2380 if (cleanup)
2381 {
2382 cout << "post-test removal of " << dir << endl;
2383 BOOST_TEST(fs::remove_all(dir) != 0);
2384 // above was added just to simplify testing, but it ended up detecting
2385 // a bug (failure to close an internal search handle).
2386 cout << "post-test removal complete" << endl;
2387 // BOOST_TEST(!fs::exists(dir)); // nice test, but doesn't play well with TortoiseGit cache
2388 }
2389
2390 cout << "returning from main()" << endl;
2391 return ::boost::report_errors();
2392 } // main
2393