lexically_normal.pass.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. //===----------------------------------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. // UNSUPPORTED: c++98, c++03
  9. // <filesystem>
  10. // class path
  11. // path lexically_normal() const;
  12. #include "filesystem_include.hpp"
  13. #include <type_traits>
  14. #include <vector>
  15. #include <iostream>
  16. #include <cassert>
  17. #include "test_macros.h"
  18. #include "test_iterators.h"
  19. #include "count_new.hpp"
  20. #include "filesystem_test_helper.hpp"
  21. int main(int, char**) {
  22. // clang-format off
  23. struct {
  24. std::string input;
  25. std::string expect;
  26. } TestCases[] = {
  27. {"", ""},
  28. {"/a/b/c", "/a/b/c"},
  29. {"/a/b//c", "/a/b/c"},
  30. {"foo/./bar/..", "foo/"},
  31. {"foo/.///bar/../", "foo/"},
  32. {"/a/b/", "/a/b/"},
  33. {"a/b", "a/b"},
  34. {"a/b/.", "a/b/"},
  35. {"a/b/./", "a/b/"},
  36. {"a/..", "."},
  37. {".", "."},
  38. {"./", "."},
  39. {"./.", "."},
  40. {"./..", ".."},
  41. {"..", ".."},
  42. {"../..", "../.."},
  43. {"/../", "/"},
  44. {"/../..", "/"},
  45. {"/../../", "/"},
  46. {"..", ".."},
  47. {"../", ".."},
  48. {"/a/b/c/../", "/a/b/"},
  49. {"/a/b/./", "/a/b/"},
  50. {"/a/b/c/../d", "/a/b/d"},
  51. {"/a/b/c/../d/", "/a/b/d/"},
  52. {"//a/", "/a/"},
  53. {"//a/b/", "/a/b/"},
  54. {"//a/b/.", "/a/b/"},
  55. {"//a/..", "/"},
  56. ///===---------------------------------------------------------------===//
  57. /// Tests specifically for the clauses under [fs.path.generic]p6
  58. ///===---------------------------------------------------------------===//
  59. // p1: If the path is empty, stop.
  60. {"", ""},
  61. // p2: Replace each slash character in the root-name with a preferred
  62. // separator.
  63. {"NO_ROOT_NAME_ON_LINUX", "NO_ROOT_NAME_ON_LINUX"},
  64. // p3: Replace each directory-separator with a preferred-separator.
  65. // [ Note: The generic pathname grammar ([fs.path.generic]) defines
  66. // directory-separator as one or more slashes and preferred-separators.
  67. // — end note ]
  68. {"/", "/"},
  69. {"//", "/"},
  70. {"///", "/"},
  71. {"a/b", "a/b"},
  72. {"a//b", "a/b"},
  73. {"a///b", "a/b"},
  74. {"a/b/", "a/b/"},
  75. {"a/b//", "a/b/"},
  76. {"a/b///", "a/b/"},
  77. {"///a////b//////", "/a/b/"},
  78. // p4: Remove each dot filename and any immediately following directory
  79. // separators
  80. {"foo/.", "foo/"},
  81. {"foo/./bar/.", "foo/bar/"},
  82. {"./foo/././bar/./", "foo/bar/"},
  83. {".///foo//.////./bar/.///", "foo/bar/"},
  84. // p5: As long as any appear, remove a non-dot-dot filename immediately
  85. // followed by a directory-separator and a dot-dot filename, along with
  86. // any immediately following directory separator.
  87. {"foo/..", "."},
  88. {"foo/../", "."},
  89. {"foo/bar/..", "foo/"},
  90. {"foo/bar/../", "foo/"},
  91. {"foo/bar/../..", "."},
  92. {"foo/bar/../../", "."},
  93. {"foo/bar/baz/../..", "foo/"},
  94. {"foo/bar/baz/../../", "foo/"},
  95. {"foo/bar/./..", "foo/"},
  96. {"foo/bar/./../", "foo/"},
  97. // p6: If there is a root-directory, remove all dot-dot filenames and any
  98. // directory-separators immediately following them. [ Note: These dot-dot
  99. // filenames attempt to refer to nonexistent parent directories. — end note ]
  100. {"/..", "/"},
  101. {"/../", "/"},
  102. {"/foo/../..", "/"},
  103. {"/../foo", "/foo"},
  104. {"/../foo/../..", "/"},
  105. // p7: If the last filename is dot-dot, remove any trailing
  106. // directory-separator.
  107. {"../", ".."},
  108. {"../../", "../.."},
  109. {"foo/../bar/../..///", ".."},
  110. {"foo/../bar/..//..///../", "../.."},
  111. // p8: If the path is empty, add a dot
  112. {".", "."},
  113. {"./", "."},
  114. {"foo/..", "."}
  115. };
  116. // clang-format on
  117. int ID = 0;
  118. bool Failed = false;
  119. for (auto& TC : TestCases) {
  120. ++ID;
  121. fs::path p(TC.input);
  122. const fs::path output = p.lexically_normal();
  123. if (!PathEq(output, TC.expect)) {
  124. Failed = true;
  125. std::cerr << "TEST CASE #" << ID << " FAILED: \n";
  126. std::cerr << " Input: '" << TC.input << "'\n";
  127. std::cerr << " Expected: '" << TC.expect << "'\n";
  128. std::cerr << " Output: '" << output.native() << "'";
  129. std::cerr << std::endl;
  130. }
  131. }
  132. return Failed;
  133. }