testCMFilesystemPath.cxx 21 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #include <algorithm>
  4. #include <iostream>
  5. #include <sstream>
  6. #include <string>
  7. #include <vector>
  8. #include <cm/filesystem>
  9. #include <cm/iomanip>
  10. namespace {
  11. namespace fs = cm::filesystem;
  12. void checkResult(bool success)
  13. {
  14. if (!success) {
  15. std::cout << " => failed";
  16. }
  17. std::cout << std::endl;
  18. }
  19. bool testConstructors()
  20. {
  21. std::cout << "testConstructors()";
  22. bool result = true;
  23. {
  24. fs::path p;
  25. if (p != fs::path()) {
  26. result = false;
  27. }
  28. }
  29. {
  30. fs::path p1("/a/b/c");
  31. fs::path p2("/a/b/c");
  32. if (p1 != p2) {
  33. result = false;
  34. }
  35. if (p1.string() != p2.string()) {
  36. result = false;
  37. }
  38. if (p1.string() != "/a/b/c") {
  39. result = false;
  40. }
  41. }
  42. {
  43. std::string s("/a/b/c");
  44. fs::path p1(s);
  45. fs::path p2(s.begin(), s.end());
  46. if (p1 != p2) {
  47. result = false;
  48. }
  49. if (p1.string() != s || p2.string() != s) {
  50. result = false;
  51. }
  52. #if CM_FILESYSTEM_SOURCE_TRAITS_ITERATOR
  53. std::string s2(s);
  54. s2 += '\0';
  55. fs::path p3(s2.begin());
  56. if (p1 != p3 || p3.string() != s) {
  57. result = false;
  58. }
  59. #endif
  60. }
  61. {
  62. std::wstring s(L"/a/b/c");
  63. fs::path p1(s);
  64. fs::path p2(s.begin(), s.end());
  65. if (p1 != p2) {
  66. result = false;
  67. }
  68. if (p1.wstring() != s || p2.wstring() != s) {
  69. result = false;
  70. }
  71. #if CM_FILESYSTEM_SOURCE_TRAITS_ITERATOR
  72. std::wstring s2(s);
  73. s2 += L'\0';
  74. fs::path p3(s2.begin());
  75. if (p1 != p3 || p3.wstring() != s) {
  76. result = false;
  77. }
  78. #endif
  79. }
  80. {
  81. std::string s("/a/b/c");
  82. fs::path::string_type ws;
  83. for (auto c : s) {
  84. ws += fs::path::value_type(c);
  85. }
  86. fs::path p1(ws);
  87. fs::path p2(ws.begin(), ws.end());
  88. if (p1 != p2) {
  89. result = false;
  90. }
  91. if (p1.native() != ws || p2.native() != ws) {
  92. result = false;
  93. }
  94. #if CM_FILESYSTEM_SOURCE_TRAITS_ITERATOR
  95. fs::path::string_type ws2(ws);
  96. ws2 += fs::path::value_type('\0');
  97. fs::path p3(ws2.begin());
  98. if (p1 != p3 || p3.native() != ws) {
  99. result = false;
  100. }
  101. #endif
  102. }
  103. checkResult(result);
  104. return result;
  105. }
  106. bool testConcatenation()
  107. {
  108. std::cout << "testConcatenation()";
  109. bool result = true;
  110. {
  111. fs::path p("/a/b");
  112. p /= "c";
  113. if (!(p.string() == "/a/b/c" || p.string() == "/a/b\\c")) {
  114. result = false;
  115. }
  116. p += "d";
  117. if (!(p.string() == "/a/b/cd" || p.string() == "/a/b\\cd")) {
  118. result = false;
  119. }
  120. fs::path p2("x/y");
  121. p /= p2;
  122. if (!(p.string() == "/a/b/cd/x/y" || p.string() == "/a/b\\cd\\x/y")) {
  123. result = false;
  124. }
  125. p = p / p2;
  126. if (!(p.string() == "/a/b/cd/x/y/x/y" ||
  127. p.string() == "/a/b\\cd\\x/y\\x/y")) {
  128. result = false;
  129. }
  130. }
  131. {
  132. fs::path p("a");
  133. p /= "";
  134. if (!(p.string() == "a/" || p.string() == "a\\")) {
  135. result = false;
  136. }
  137. p /= "/b";
  138. if (p.string() != "/b") {
  139. result = false;
  140. }
  141. }
  142. #if defined(_WIN32)
  143. {
  144. fs::path p("a");
  145. p /= "c:/b";
  146. if (p.string() != "c:/b") {
  147. result = false;
  148. }
  149. p = fs::path("a") / "c:";
  150. if (p.string() != "c:") {
  151. result = false;
  152. }
  153. p = fs::path("c:") / "";
  154. if (p.string() != "c:") {
  155. result = false;
  156. }
  157. p = fs::path("c:a") / "/b";
  158. if (p.string() != "c:/b") {
  159. result = false;
  160. }
  161. p = fs::path("c:a") / "c:b";
  162. if (p.string() != "c:a\\b") {
  163. result = false;
  164. }
  165. p = fs::path("//host") / "b";
  166. if (p.string() != "//host\\b") {
  167. result = false;
  168. }
  169. p = fs::path("//host/") / "b";
  170. if (p.string() != "//host/b") {
  171. result = false;
  172. }
  173. }
  174. #endif
  175. checkResult(result);
  176. return result;
  177. }
  178. bool testModifiers()
  179. {
  180. std::cout << "testModifiers()";
  181. bool result = true;
  182. {
  183. std::string s("a///b/");
  184. fs::path p(s);
  185. std::replace(
  186. s.begin(), s.end(), '/',
  187. static_cast<std::string::value_type>(fs::path::preferred_separator));
  188. p.make_preferred();
  189. if (p.string() != s) {
  190. result = false;
  191. }
  192. }
  193. {
  194. fs::path p("a/b/c.e.f");
  195. p.remove_filename();
  196. if (p.string() != "a/b/") {
  197. result = false;
  198. }
  199. p.remove_filename();
  200. if (p.string() != "a/b/") {
  201. result = false;
  202. }
  203. }
  204. {
  205. fs::path p("a/b/c.e.f");
  206. p.replace_filename("x.y");
  207. if (p.string() != "a/b/x.y") {
  208. result = false;
  209. }
  210. }
  211. {
  212. fs::path p("a/b/c.e.f");
  213. p.replace_extension(".x");
  214. if (p.string() != "a/b/c.e.x") {
  215. result = false;
  216. }
  217. p.replace_extension(".y");
  218. if (p.string() != "a/b/c.e.y") {
  219. result = false;
  220. }
  221. p.replace_extension();
  222. if (p.string() != "a/b/c.e") {
  223. result = false;
  224. }
  225. p = "/a/b";
  226. p.replace_extension(".x");
  227. if (p.string() != "/a/b.x") {
  228. result = false;
  229. }
  230. p = "/a/b/";
  231. p.replace_extension(".x");
  232. if (p.string() != "/a/b/.x") {
  233. result = false;
  234. }
  235. }
  236. checkResult(result);
  237. return result;
  238. }
  239. bool testObservers()
  240. {
  241. std::cout << "testObservers()";
  242. bool result = true;
  243. {
  244. std::string s("a/b/c");
  245. fs::path p(s);
  246. fs::path::string_type st;
  247. for (auto c : s) {
  248. st += static_cast<fs::path::value_type>(c);
  249. }
  250. if (p.native() != st || static_cast<fs::path::string_type>(p) != st ||
  251. p.c_str() != st) {
  252. result = false;
  253. }
  254. }
  255. {
  256. std::string s("a//b//c");
  257. std::wstring ws(L"a//b//c");
  258. fs::path p(s);
  259. if (p.string() != s || p.wstring() != ws) {
  260. result = false;
  261. }
  262. }
  263. {
  264. std::string s("a/b/c");
  265. std::wstring ws;
  266. for (auto c : s) {
  267. ws += static_cast<std::wstring::value_type>(c);
  268. }
  269. std::string ns(s);
  270. std::replace(
  271. ns.begin(), ns.end(), '/',
  272. static_cast<std::string::value_type>(fs::path::preferred_separator));
  273. fs::path p(ns);
  274. if (p.generic_string() != s || p.generic_wstring() != ws) {
  275. result = false;
  276. }
  277. }
  278. checkResult(result);
  279. return result;
  280. }
  281. bool testCompare()
  282. {
  283. std::cout << "testCompare()";
  284. bool result = true;
  285. {
  286. std::string s("a/b/c");
  287. fs::path p1(s);
  288. fs::path p2(s);
  289. if (p1.compare(p2) != 0) {
  290. result = false;
  291. }
  292. p2 = "a/b";
  293. if (p1.compare(p2) <= 0) {
  294. result = false;
  295. }
  296. p2 = "a/d";
  297. if (p1.compare(p2) >= 0) {
  298. result = false;
  299. }
  300. p2 = "a/b/d";
  301. if (p1.compare(p2) >= 0) {
  302. result = false;
  303. }
  304. p2 = "a/b/a";
  305. if (p1.compare(p2) <= 0) {
  306. result = false;
  307. }
  308. p2 = "a/b/c/d";
  309. if (p1.compare(p2) >= 0) {
  310. result = false;
  311. }
  312. p1 = "a";
  313. p2 = "b";
  314. if (p1.compare(p2) == 0) {
  315. result = false;
  316. }
  317. }
  318. {
  319. // LWG 3096 (https://cplusplus.github.io/LWG/issue3096)
  320. // fs::path p1("/a/");
  321. // fs::path p2("/a/.");
  322. // if (p1.compare(p2) != 0) {
  323. // result = false;
  324. // }
  325. }
  326. checkResult(result);
  327. return result;
  328. }
  329. bool testGeneration()
  330. {
  331. std::cout << "testGeneration()";
  332. bool result = true;
  333. {
  334. fs::path p("a/./b/..");
  335. if (p.lexically_normal().generic_string() != "a/") {
  336. result = false;
  337. }
  338. p = "a/.///b/../";
  339. if (p.lexically_normal().generic_string() != "a/") {
  340. result = false;
  341. }
  342. }
  343. #if defined(_WIN32)
  344. {
  345. fs::path p("//host/./b/..");
  346. if (p.lexically_normal().string() != "\\\\host\\") {
  347. result = false;
  348. }
  349. p = "//host/.///b/../";
  350. if (p.lexically_normal().string() != "\\\\host\\") {
  351. result = false;
  352. }
  353. p = "c://a/.///b/../";
  354. if (p.lexically_normal().string() != "c:\\a\\") {
  355. result = false;
  356. }
  357. }
  358. #endif
  359. {
  360. if (fs::path("/a//d").lexically_relative("/a/b/c") != "../../d") {
  361. result = false;
  362. }
  363. if (fs::path("/a//b///c").lexically_relative("/a/d") != "../b/c") {
  364. result = false;
  365. }
  366. if (fs::path("a/b/c").lexically_relative("a") != "b/c") {
  367. result = false;
  368. }
  369. if (fs::path("a/b/c").lexically_relative("a/b/c/x/y") != "../..") {
  370. result = false;
  371. }
  372. if (fs::path("a/b/c").lexically_relative("a/b/c") != ".") {
  373. result = false;
  374. }
  375. if (fs::path("a/b").lexically_relative("c/d") != "../../a/b") {
  376. result = false;
  377. }
  378. }
  379. {
  380. #if defined(_WIN32)
  381. if (fs::path("/a/d").lexically_relative("e/d/c") != "/a/d") {
  382. result = false;
  383. }
  384. if (!fs::path("c:/a/d").lexically_relative("e/d/c").empty()) {
  385. result = false;
  386. }
  387. #else
  388. if (!fs::path("/a/d").lexically_relative("e/d/c").empty()) {
  389. result = false;
  390. }
  391. #endif
  392. }
  393. {
  394. #if defined(_WIN32)
  395. if (fs::path("c:/a/d").lexically_proximate("e/d/c") != "c:/a/d") {
  396. result = false;
  397. }
  398. #else
  399. if (fs::path("/a/d").lexically_proximate("e/d/c") != "/a/d") {
  400. result = false;
  401. }
  402. #endif
  403. if (fs::path("/a/d").lexically_proximate("/a/b/c") != "../../d") {
  404. result = false;
  405. }
  406. }
  407. // LWG 3070
  408. {
  409. #if defined(_WIN32)
  410. if (!fs::path("/a:/b:").lexically_relative("/a:/c:").empty()) {
  411. result = false;
  412. }
  413. if (fs::path("c:/a/b").lexically_relative("c:/a/d") != "../b") {
  414. result = false;
  415. }
  416. if (!fs::path("c:/a/b:").lexically_relative("c:/a/d").empty()) {
  417. result = false;
  418. }
  419. if (!fs::path("c:/a/b").lexically_relative("c:/a/d:").empty()) {
  420. result = false;
  421. }
  422. #else
  423. if (fs::path("/a:/b:").lexically_relative("/a:/c:") != "../b:") {
  424. result = false;
  425. }
  426. #endif
  427. }
  428. // LWG 3096
  429. {
  430. if (fs::path("/a").lexically_relative("/a/.") != ".") {
  431. result = false;
  432. }
  433. if (fs::path("/a").lexically_relative("/a/") != ".") {
  434. result = false;
  435. }
  436. if (fs::path("a/b/c").lexically_relative("a/b/c") != ".") {
  437. result = false;
  438. }
  439. if (fs::path("a/b/c").lexically_relative("a/b/c/") != ".") {
  440. result = false;
  441. }
  442. if (fs::path("a/b/c").lexically_relative("a/b/c/.") != ".") {
  443. result = false;
  444. }
  445. if (fs::path("a/b/c/").lexically_relative("a/b/c") != ".") {
  446. result = false;
  447. }
  448. if (fs::path("a/b/c/.").lexically_relative("a/b/c") != ".") {
  449. result = false;
  450. }
  451. if (fs::path("a/b/c/.").lexically_relative("a/b/c/") != ".") {
  452. result = false;
  453. }
  454. }
  455. checkResult(result);
  456. return result;
  457. }
  458. bool testDecomposition()
  459. {
  460. std::cout << "testDecomposition()";
  461. bool result = true;
  462. {
  463. if (!fs::path("/a/b").root_name().empty()) {
  464. result = false;
  465. }
  466. #if defined(_WIN32)
  467. if (fs::path("c:/a/b").root_name() != "c:") {
  468. result = false;
  469. }
  470. if (fs::path("c:a/b").root_name() != "c:") {
  471. result = false;
  472. }
  473. if (fs::path("c:").root_name() != "c:") {
  474. result = false;
  475. }
  476. if (fs::path("//host/b").root_name() != "//host") {
  477. result = false;
  478. }
  479. if (fs::path("//host").root_name() != "//host") {
  480. result = false;
  481. }
  482. #endif
  483. }
  484. {
  485. if (!fs::path("a/b").root_directory().empty()) {
  486. result = false;
  487. }
  488. if (fs::path("/a/b").root_directory() != "/") {
  489. result = false;
  490. }
  491. #if defined(_WIN32)
  492. if (!fs::path("c:a/b").root_directory().empty()) {
  493. result = false;
  494. }
  495. if (fs::path("/a/b").root_directory() != "/") {
  496. result = false;
  497. }
  498. if (fs::path("c:/a/b").root_directory() != "/") {
  499. result = false;
  500. }
  501. if (fs::path("//host/b").root_directory() != "/") {
  502. result = false;
  503. }
  504. #endif
  505. }
  506. {
  507. if (!fs::path("a/b").root_path().empty()) {
  508. result = false;
  509. }
  510. if (fs::path("/a/b").root_path() != "/") {
  511. result = false;
  512. }
  513. #if defined(_WIN32)
  514. if (fs::path("c:a/b").root_path() != "c:") {
  515. result = false;
  516. }
  517. if (fs::path("/a/b").root_path() != "/") {
  518. result = false;
  519. }
  520. if (fs::path("c:/a/b").root_path() != "c:/") {
  521. result = false;
  522. }
  523. if (fs::path("//host/b").root_path() != "//host/") {
  524. result = false;
  525. }
  526. #endif
  527. }
  528. {
  529. if (!fs::path("/").relative_path().empty()) {
  530. result = false;
  531. }
  532. if (fs::path("a/b").relative_path() != "a/b") {
  533. result = false;
  534. }
  535. if (fs::path("/a/b").relative_path() != "a/b") {
  536. result = false;
  537. }
  538. #if defined(_WIN32)
  539. if (fs::path("c:a/b").relative_path() != "a/b") {
  540. result = false;
  541. }
  542. if (fs::path("/a/b").relative_path() != "a/b") {
  543. result = false;
  544. }
  545. if (fs::path("c:/a/b").relative_path() != "a/b") {
  546. result = false;
  547. }
  548. if (fs::path("//host/b").relative_path() != "b") {
  549. result = false;
  550. }
  551. #endif
  552. }
  553. {
  554. if (fs::path("/a/b").parent_path() != "/a") {
  555. result = false;
  556. }
  557. if (fs::path("/a/b/").parent_path() != "/a/b") {
  558. result = false;
  559. }
  560. if (fs::path("/a/b/.").parent_path() != "/a/b") {
  561. result = false;
  562. }
  563. if (fs::path("/").parent_path() != "/") {
  564. result = false;
  565. }
  566. #if defined(_WIN32)
  567. if (fs::path("c:/a/b").parent_path() != "c:/a") {
  568. result = false;
  569. }
  570. if (fs::path("c:/").parent_path() != "c:/") {
  571. result = false;
  572. }
  573. if (fs::path("c:").parent_path() != "c:") {
  574. result = false;
  575. }
  576. if (fs::path("//host/").parent_path() != "//host/") {
  577. result = false;
  578. }
  579. if (fs::path("//host").parent_path() != "//host") {
  580. result = false;
  581. }
  582. #endif
  583. }
  584. {
  585. if (fs::path("/a/b.txt").filename() != "b.txt") {
  586. result = false;
  587. }
  588. if (fs::path("/a/.b").filename() != ".b") {
  589. result = false;
  590. }
  591. if (fs::path("/foo/bar/").filename() != "") {
  592. result = false;
  593. }
  594. if (fs::path("/foo/.").filename() != ".") {
  595. result = false;
  596. }
  597. if (fs::path("/foo/..").filename() != "..") {
  598. result = false;
  599. }
  600. if (fs::path(".").filename() != ".") {
  601. result = false;
  602. }
  603. if (fs::path("..").filename() != "..") {
  604. result = false;
  605. }
  606. if (!fs::path("/").filename().empty()) {
  607. result = false;
  608. }
  609. #if defined(_WIN32)
  610. if (fs::path("c:a").filename() != "a") {
  611. result = false;
  612. }
  613. if (fs::path("c:/a").filename() != "a") {
  614. result = false;
  615. }
  616. if (!fs::path("c:").filename().empty()) {
  617. result = false;
  618. }
  619. if (!fs::path("c:/").filename().empty()) {
  620. result = false;
  621. }
  622. if (!fs::path("//host").filename().empty()) {
  623. result = false;
  624. }
  625. #endif
  626. }
  627. {
  628. if (fs::path("/a/b.txt").stem() != "b") {
  629. result = false;
  630. }
  631. if (fs::path("/a/b.c.txt").stem() != "b.c") {
  632. result = false;
  633. }
  634. if (fs::path("/a/.b").stem() != ".b") {
  635. result = false;
  636. }
  637. if (fs::path("/a/b").stem() != "b") {
  638. result = false;
  639. }
  640. if (fs::path("/a/b/.").stem() != ".") {
  641. result = false;
  642. }
  643. if (fs::path("/a/b/..").stem() != "..") {
  644. result = false;
  645. }
  646. if (!fs::path("/a/b/").stem().empty()) {
  647. result = false;
  648. }
  649. #if defined(_WIN32)
  650. if (!fs::path("c:/a/b/").stem().empty()) {
  651. result = false;
  652. }
  653. if (!fs::path("c:/").stem().empty()) {
  654. result = false;
  655. }
  656. if (!fs::path("c:").stem().empty()) {
  657. result = false;
  658. }
  659. if (!fs::path("//host/").stem().empty()) {
  660. result = false;
  661. }
  662. if (!fs::path("//host").stem().empty()) {
  663. result = false;
  664. }
  665. #endif
  666. }
  667. {
  668. if (fs::path("/a/b.txt").extension() != ".txt") {
  669. result = false;
  670. }
  671. if (fs::path("/a/b.").extension() != ".") {
  672. result = false;
  673. }
  674. if (!fs::path("/a/b").extension().empty()) {
  675. result = false;
  676. }
  677. if (fs::path("/a/b.txt/b.cc").extension() != ".cc") {
  678. result = false;
  679. }
  680. if (fs::path("/a/b.txt/b.").extension() != ".") {
  681. result = false;
  682. }
  683. if (!fs::path("/a/b.txt/b").extension().empty()) {
  684. result = false;
  685. }
  686. if (!fs::path("/a/.").extension().empty()) {
  687. result = false;
  688. }
  689. if (!fs::path("/a/..").extension().empty()) {
  690. result = false;
  691. }
  692. if (!fs::path("/a/.hidden").extension().empty()) {
  693. result = false;
  694. }
  695. if (fs::path("/a/..b").extension() != ".b") {
  696. result = false;
  697. }
  698. }
  699. checkResult(result);
  700. return result;
  701. }
  702. bool testQueries()
  703. {
  704. std::cout << "testQueries()";
  705. bool result = true;
  706. {
  707. if (fs::path("/a/b").has_root_name()) {
  708. result = false;
  709. }
  710. fs::path p("/a/b");
  711. if (!p.has_root_directory() || !p.has_root_path()) {
  712. result = false;
  713. }
  714. if (!fs::path("/a/b").has_root_path() || fs::path("a/b").has_root_path()) {
  715. result = false;
  716. }
  717. if (!fs::path("/a/b").has_relative_path() ||
  718. fs::path("/").has_relative_path()) {
  719. result = false;
  720. }
  721. if (!fs::path("/a/b").has_parent_path() ||
  722. !fs::path("/").has_parent_path() || fs::path("a").has_parent_path()) {
  723. result = false;
  724. }
  725. if (!fs::path("/a/b").has_filename() || !fs::path("a.b").has_filename() ||
  726. fs::path("/a/").has_filename() || fs::path("/").has_filename()) {
  727. result = false;
  728. }
  729. if (!fs::path("/a/b").has_stem() || !fs::path("a.b").has_stem() ||
  730. !fs::path("/.a").has_stem() || fs::path("/a/").has_stem() ||
  731. fs::path("/").has_stem()) {
  732. result = false;
  733. }
  734. if (!fs::path("/a/b.c").has_extension() ||
  735. !fs::path("a.b").has_extension() || fs::path("/.a").has_extension() ||
  736. fs::path("/a/").has_extension() || fs::path("/").has_extension()) {
  737. result = false;
  738. }
  739. #if defined(_WIN32)
  740. p = "c:/a/b";
  741. if (!fs::path("c:/a/b").has_root_name() || !p.has_root_directory() ||
  742. !p.has_root_path()) {
  743. result = false;
  744. }
  745. p = "c:a/b";
  746. if (!p.has_root_name() || p.has_root_directory() || !p.has_root_path()) {
  747. result = false;
  748. }
  749. p = "//host/b";
  750. if (!p.has_root_name() || !p.has_root_directory() || !p.has_root_path()) {
  751. result = false;
  752. }
  753. p = "//host";
  754. if (!p.has_root_name() || p.has_root_directory() || !p.has_root_path()) {
  755. result = false;
  756. }
  757. if (!fs::path("c:/a/b").has_relative_path() ||
  758. !fs::path("c:a/b").has_relative_path() ||
  759. !fs::path("//host/b").has_relative_path()) {
  760. result = false;
  761. }
  762. if (!fs::path("c:/a/b").has_parent_path() ||
  763. !fs::path("c:/").has_parent_path() ||
  764. !fs::path("c:").has_parent_path() ||
  765. !fs::path("//host/").has_parent_path() ||
  766. !fs::path("//host").has_parent_path()) {
  767. result = false;
  768. }
  769. #endif
  770. }
  771. {
  772. #if defined(_WIN32)
  773. fs::path p("c:/a");
  774. #else
  775. fs::path p("/a");
  776. #endif
  777. if (!p.is_absolute() || p.is_relative()) {
  778. result = false;
  779. }
  780. p = "a/b";
  781. if (p.is_absolute() || !p.is_relative()) {
  782. result = false;
  783. }
  784. #if defined(_WIN32)
  785. p = "c:/a/b";
  786. if (!p.is_absolute() || p.is_relative()) {
  787. result = false;
  788. }
  789. p = "//host/b";
  790. if (!p.is_absolute() || p.is_relative()) {
  791. result = false;
  792. }
  793. p = "/a";
  794. if (p.is_absolute() || !p.is_relative()) {
  795. result = false;
  796. }
  797. p = "c:a";
  798. if (p.is_absolute() || !p.is_relative()) {
  799. result = false;
  800. }
  801. #endif
  802. }
  803. checkResult(result);
  804. return result;
  805. }
  806. bool testIterators()
  807. {
  808. std::cout << "testIterators()";
  809. bool result = true;
  810. {
  811. fs::path p("/a/b/");
  812. #if defined(_WIN32)
  813. std::vector<fs::path::string_type> ref{ L"/", L"a", L"b", L"" };
  814. #else
  815. std::vector<fs::path::string_type> ref{ "/", "a", "b", "" };
  816. #endif
  817. std::vector<fs::path::string_type> res;
  818. for (auto i = p.begin(), e = p.end(); i != e; ++i) {
  819. res.push_back(*i);
  820. }
  821. if (res != ref) {
  822. result = false;
  823. }
  824. res.clear();
  825. for (const auto& e : p) {
  826. res.push_back(e);
  827. }
  828. if (res != ref) {
  829. result = false;
  830. }
  831. }
  832. {
  833. fs::path p("/a/b/");
  834. #if defined(_WIN32)
  835. std::vector<fs::path::string_type> ref{ L"", L"b", L"a", L"/" };
  836. #else
  837. std::vector<fs::path::string_type> ref{ "", "b", "a", "/" };
  838. #endif
  839. std::vector<fs::path::string_type> res;
  840. auto i = p.end(), b = p.begin();
  841. do {
  842. res.push_back(*--i);
  843. } while (i != b);
  844. if (res != ref) {
  845. result = false;
  846. }
  847. }
  848. checkResult(result);
  849. return result;
  850. }
  851. bool testNonMemberFunctions()
  852. {
  853. std::cout << "testNonMemberFunctions()";
  854. bool result = true;
  855. {
  856. fs::path p1("/a/b/");
  857. fs::path p2("/c/d");
  858. fs::swap(p1, p2);
  859. if (p1.string() != "/c/d" || p2.string() != "/a/b/")
  860. result = false;
  861. }
  862. {
  863. auto h1 = fs::hash_value(fs::path("/a//b//"));
  864. auto h2 = fs::hash_value(fs::path("/a/b/"));
  865. if (h1 != h2)
  866. result = false;
  867. }
  868. {
  869. fs::path p1("/a/b/");
  870. fs::path p2("/c/d");
  871. if (p1 == p2)
  872. result = false;
  873. p1 = "/a//b//";
  874. p2 = "/a/b/";
  875. if (p1 != p2)
  876. result = false;
  877. }
  878. {
  879. fs::path p = "/a";
  880. p = p / "b" / "c";
  881. if (p.generic_string() != "/a/b/c") {
  882. result = false;
  883. }
  884. fs::path::string_type ref;
  885. ref += fs::path::value_type('/');
  886. ref += fs::path::value_type('a');
  887. ref += fs::path::preferred_separator;
  888. ref += fs::path::value_type('b');
  889. ref += fs::path::preferred_separator;
  890. ref += fs::path::value_type('c');
  891. if (p.native() != ref) {
  892. result = false;
  893. }
  894. }
  895. {
  896. fs::path p("/a b\\c/");
  897. std::ostringstream oss;
  898. oss << p;
  899. if (oss.str() != "\"/a b\\\\c/\"") {
  900. result = false;
  901. }
  902. std::istringstream iss(oss.str());
  903. fs::path p2;
  904. iss >> p2;
  905. if (p2 != p) {
  906. result = false;
  907. }
  908. }
  909. checkResult(result);
  910. return result;
  911. }
  912. }
  913. int testCMFilesystemPath(int /*unused*/, char* /*unused*/ [])
  914. {
  915. int result = 0;
  916. if (!testConstructors()) {
  917. result = 1;
  918. }
  919. if (!testConcatenation()) {
  920. result = 1;
  921. }
  922. if (!testModifiers()) {
  923. result = 1;
  924. }
  925. if (!testObservers()) {
  926. result = 1;
  927. }
  928. if (!testCompare()) {
  929. result = 1;
  930. }
  931. if (!testGeneration()) {
  932. result = 1;
  933. }
  934. if (!testDecomposition()) {
  935. result = 1;
  936. }
  937. if (!testQueries()) {
  938. result = 1;
  939. }
  940. if (!testIterators()) {
  941. result = 1;
  942. }
  943. if (!testNonMemberFunctions()) {
  944. result = 1;
  945. }
  946. return result;
  947. }