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