xref: /llvm-project/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.proximate/proximate.pass.cpp (revision 4f7fa06a666a2ff2107892c6a4737a82062e1feb)
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 
9 // UNSUPPORTED: c++03
10 
11 // XFAIL: LIBCXX-WINDOWS-FIXME
12 
13 // <filesystem>
14 
15 // path proximate(const path& p, error_code &ec)
16 // path proximate(const path& p, const path& base = current_path())
17 // path proximate(const path& p, const path& base, error_code& ec);
18 
19 #include "filesystem_include.h"
20 #include <cassert>
21 #include <cstdio>
22 
23 #include "test_macros.h"
24 #include "count_new.h"
25 #include "rapid-cxx-test.h"
26 #include "filesystem_test_helper.h"
27 
28 
29 static int count_path_elems(const fs::path& p) {
30   int count = 0;
31   for (auto& elem : p) {
32     if (elem != "/" && elem != "")
33       ++count;
34   }
35   return count;
36 }
37 
38 TEST_SUITE(filesystem_proximate_path_test_suite)
39 
40 
41 TEST_CASE(signature_test)
42 {
43     using fs::path;
44     const path p; ((void)p);
45     std::error_code ec; ((void)ec);
46     ASSERT_NOT_NOEXCEPT(proximate(p));
47     ASSERT_NOT_NOEXCEPT(proximate(p, p));
48     ASSERT_NOT_NOEXCEPT(proximate(p, ec));
49     ASSERT_NOT_NOEXCEPT(proximate(p, p, ec));
50 }
51 
52 TEST_CASE(basic_test) {
53   using fs::path;
54   const path cwd = fs::current_path();
55   const path parent_cwd = cwd.parent_path();
56   const path curdir = cwd.filename();
57   TEST_REQUIRE(!cwd.native().empty());
58   int cwd_depth = count_path_elems(cwd);
59   path dot_dot_to_root;
60   for (int i=0; i < cwd_depth; ++i)
61     dot_dot_to_root /= "..";
62   path relative_cwd = cwd.native().substr(1);
63   // clang-format off
64   struct {
65     fs::path input;
66     fs::path base;
67     fs::path expect;
68   } TestCases[] = {
69       {"", "", "."},
70       {cwd, "a", ".."},
71       {parent_cwd, "a", "../.."},
72       {"a", cwd, "a"},
73       {"a", parent_cwd, curdir / "a"},
74       {"/", "a", dot_dot_to_root / ".."},
75       {"/", "a/b", dot_dot_to_root / "../.."},
76       {"/", "a/b/", dot_dot_to_root / "../.."},
77       {"a", "/", relative_cwd / "a"},
78       {"a/b", "/", relative_cwd / "a/b"},
79       {"a", "/net", ".." / relative_cwd / "a"},
80       {"//foo/", "//foo", "."},
81       {"//foo", "//foo/", "."},
82       {"//foo", "//foo", "."},
83       {"//foo/", "//foo/", "."},
84       {"//base", "a", dot_dot_to_root / "../base"},
85       {"a", "a", "."},
86       {"a/b", "a/b", "."},
87       {"a/b/c/", "a/b/c/", "."},
88       {"//foo/a/b", "//foo/a/b", "."},
89       {"/a/d", "/a/b/c", "../../d"},
90       {"/a/b/c", "/a/d", "../b/c"},
91       {"a/b/c", "a", "b/c"},
92       {"a/b/c", "a/b/c/x/y", "../.."},
93       {"a/b/c", "a/b/c", "."},
94       {"a/b", "c/d", "../../a/b"}
95   };
96   // clang-format on
97   int ID = 0;
98   for (auto& TC : TestCases) {
99     ++ID;
100     std::error_code ec = GetTestEC();
101     fs::path p(TC.input);
102     const fs::path output = fs::proximate(p, TC.base, ec);
103     if (ec) {
104       TEST_CHECK(!ec);
105       std::fprintf(stderr, "TEST CASE #%d FAILED:\n"
106                   "  Input: '%s'\n"
107                   "  Base: '%s'\n"
108                   "  Expected: '%s'\n",
109         ID, TC.input.string().c_str(), TC.base.string().c_str(),
110         TC.expect.string().c_str());
111     } else if (!PathEq(output, TC.expect)) {
112       TEST_CHECK(PathEq(output, TC.expect));
113 
114       const path canon_input = fs::weakly_canonical(TC.input);
115       const path canon_base = fs::weakly_canonical(TC.base);
116       const path lexically_p = canon_input.lexically_proximate(canon_base);
117       std::fprintf(stderr, "TEST CASE #%d FAILED:\n"
118                   "  Input: '%s'\n"
119                   "  Base: '%s'\n"
120                   "  Expected: '%s'\n"
121                   "  Output: '%s'\n"
122                   "  Lex Prox: '%s'\n"
123                   "  Canon Input: '%s'\n"
124                   "  Canon Base: '%s'\n",
125         ID, TC.input.string().c_str(), TC.base.string().c_str(),
126         TC.expect.string().c_str(), output.string().c_str(),
127         lexically_p.string().c_str(), canon_input.string().c_str(),
128         canon_base.string().c_str());
129     }
130   }
131 }
132 
133 TEST_SUITE_END()
134