operations_test.cpp 78 KB

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