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