Eric Fiselier | 1e34c76 | 2018-04-02 23:03:41 +0000 | [diff] [blame^] | 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 | // <experimental/filesystem> |
| 13 | |
| 14 | // path proximate(const path& p, error_code &ec) |
| 15 | // path proximate(const path& p, const path& base = current_path()) |
| 16 | // path proximate(const path& p, const path& base, error_code& ec); |
| 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 "rapid-cxx-test.hpp" |
| 28 | #include "filesystem_test_helper.hpp" |
| 29 | |
| 30 | |
| 31 | static int count_path_elems(const fs::path& p) { |
| 32 | int count = 0; |
| 33 | for (auto& elem : p) { |
| 34 | if (elem != "/" && elem != "") |
| 35 | ++count; |
| 36 | } |
| 37 | return count; |
| 38 | } |
| 39 | |
| 40 | TEST_SUITE(filesystem_proximate_path_test_suite) |
| 41 | |
| 42 | |
| 43 | TEST_CASE(signature_test) |
| 44 | { |
| 45 | using fs::path; |
| 46 | const path p; ((void)p); |
| 47 | std::error_code ec; ((void)ec); |
| 48 | ASSERT_NOT_NOEXCEPT(proximate(p)); |
| 49 | ASSERT_NOT_NOEXCEPT(proximate(p, p)); |
| 50 | ASSERT_NOT_NOEXCEPT(proximate(p, ec)); |
| 51 | ASSERT_NOT_NOEXCEPT(proximate(p, p, ec)); |
| 52 | } |
| 53 | |
| 54 | TEST_CASE(basic_test) { |
| 55 | using fs::path; |
| 56 | const path cwd = fs::current_path(); |
| 57 | const path parent_cwd = cwd.parent_path(); |
| 58 | const path curdir = cwd.filename(); |
| 59 | TEST_REQUIRE(!cwd.native().empty()); |
| 60 | int cwd_depth = count_path_elems(cwd); |
| 61 | path dot_dot_to_root; |
| 62 | for (int i=0; i < cwd_depth; ++i) |
| 63 | dot_dot_to_root /= ".."; |
| 64 | path relative_cwd = cwd.native().substr(1); |
| 65 | // clang-format off |
| 66 | struct { |
| 67 | std::string input; |
| 68 | std::string base; |
| 69 | std::string expect; |
| 70 | } TestCases[] = { |
| 71 | {"", "", "."}, |
| 72 | {cwd, "a", ".."}, |
| 73 | {parent_cwd, "a", "../.."}, |
| 74 | {"a", cwd, "a"}, |
| 75 | {"a", parent_cwd, "fs.op.proximate/a"}, |
| 76 | {"/", "a", dot_dot_to_root / ".."}, |
| 77 | {"/", "a/b", dot_dot_to_root / "../.."}, |
| 78 | {"/", "a/b/", dot_dot_to_root / "../../.."}, |
| 79 | {"a", "/", relative_cwd / "a"}, |
| 80 | {"a/b", "/", relative_cwd / "a/b"}, |
| 81 | {"a", "/net", ".." / relative_cwd / "a"}, |
| 82 | {"//net/", "//net", "/net/"}, |
| 83 | {"//net", "//net/", ".."}, |
| 84 | {"//net", "//net", "."}, |
| 85 | {"//net/", "//net/", "."}, |
| 86 | {"//base", "a", dot_dot_to_root / "../base"}, |
| 87 | {"a", "a", "."}, |
| 88 | {"a/b", "a/b", "."}, |
| 89 | {"a/b/c/", "a/b/c/", "."}, |
| 90 | {"//net/a/b", "//net/a/b", "."}, |
| 91 | {"/a/d", "/a/b/c", "../../d"}, |
| 92 | {"/a/b/c", "/a/d", "../b/c"}, |
| 93 | {"a/b/c", "a", "b/c"}, |
| 94 | {"a/b/c", "a/b/c/x/y", "../.."}, |
| 95 | {"a/b/c", "a/b/c", "."}, |
| 96 | {"a/b", "c/d", "../../a/b"} |
| 97 | }; |
| 98 | // clang-format on |
| 99 | int ID = 0; |
| 100 | for (auto& TC : TestCases) { |
| 101 | ++ID; |
| 102 | std::error_code ec = GetTestEC(); |
| 103 | fs::path p(TC.input); |
| 104 | const fs::path output = fs::proximate(p, TC.base, ec); |
| 105 | TEST_CHECK(!ec); |
| 106 | TEST_CHECK(PathEq(output, TC.expect)); |
| 107 | if (!PathEq(output, TC.expect)) { |
| 108 | const path canon_input = fs::weakly_canonical(TC.input); |
| 109 | const path canon_base = fs::weakly_canonical(TC.base); |
| 110 | const path lexically_p = canon_input.lexically_proximate(canon_base); |
| 111 | std::cerr << "TEST CASE #" << ID << " FAILED: \n"; |
| 112 | std::cerr << " Input: '" << TC.input << "'\n"; |
| 113 | std::cerr << " Base: '" << TC.base << "'\n"; |
| 114 | std::cerr << " Expected: '" << TC.expect << "'\n"; |
| 115 | std::cerr << " Output: '" << output.native() << "'\n"; |
| 116 | std::cerr << " Lex Prox: '" << lexically_p.native() << "'\n"; |
| 117 | std::cerr << " Canon Input: " << canon_input << "\n"; |
| 118 | std::cerr << " Canon Base: " << canon_base << "\n"; |
| 119 | |
| 120 | std::cerr << std::endl; |
| 121 | } |
| 122 | } |
| 123 | } |
| 124 | |
| 125 | TEST_SUITE_END() |