1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
10 // UNSUPPORTED: no-filesystem
11 // UNSUPPORTED: availability-filesystem-missing
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);
19 #include "filesystem_include.h"
22 #include "assert_macros.h"
23 #include "concat_macros.h"
24 #include "test_macros.h"
25 #include "count_new.h"
26 #include "filesystem_test_helper.h"
27 #include "../../class.path/path_helper.h"
29 static int count_path_elems(const fs::path
& p
) {
31 for (auto&& elem
: p
) {
32 if (elem
!= p
.root_name() && elem
!= "/" && elem
!= "")
38 static void signature_test() {
44 ASSERT_NOT_NOEXCEPT(proximate(p
));
45 ASSERT_NOT_NOEXCEPT(proximate(p
, p
));
46 ASSERT_NOT_NOEXCEPT(proximate(p
, ec
));
47 ASSERT_NOT_NOEXCEPT(proximate(p
, p
, ec
));
50 static void basic_test() {
52 const path cwd
= fs::current_path();
53 const path parent_cwd
= cwd
.parent_path();
54 const path curdir
= cwd
.filename();
55 assert(!cwd
.native().empty());
56 int cwd_depth
= count_path_elems(cwd
);
58 for (int i
= 0; i
< cwd_depth
; ++i
)
59 dot_dot_to_root
/= "..";
60 path relative_cwd
= cwd
.native().substr(cwd
.root_path().native().size());
69 {parent_cwd
, "a", "../.."},
71 {"a", parent_cwd
, curdir
/ "a"},
72 {"/", "a", dot_dot_to_root
/ ".."},
73 {"/", "a/b", dot_dot_to_root
/ "../.."},
74 {"/", "a/b/", dot_dot_to_root
/ "../.."},
75 {"a", "/", relative_cwd
/ "a"},
76 {"a/b", "/", relative_cwd
/ "a/b"},
77 {"a", "/net", ".." / relative_cwd
/ "a"},
79 {"//foo/", "//foo", "//foo/"},
80 {"//foo", "//foo/", "//foo"},
82 {"//foo/", "//foo", "."},
83 {"//foo", "//foo/", "."},
85 {"//foo", "//foo", "."},
86 {"//foo/", "//foo/", "."},
88 {"//foo", "a", "//foo"},
89 {"//foo/a", "//bar", "//foo/a"},
90 {"//foo/a", "//bar/", "//foo/a"},
91 {"//foo/a", "b", "//foo/a"},
92 {"//foo/a", "/b", "//foo/a"},
93 {"//foo/a", "//bar/b", "//foo/a"},
94 // Using X: instead of C: to avoid influence from the CWD being under C:
95 {"X:/a", "X:/b", "../a"},
96 {"X:/a", "X:b", "X:/a"},
97 {"X:/a", "Y:/a", "X:/a"},
98 {"X:/a", "Y:/b", "X:/a"},
99 {"X:/a", "Y:b", "X:/a"},
100 {"X:a", "X:/b", "X:a"},
101 {"X:a", "X:b", "../a"},
102 {"X:a", "Y:/a", "X:a"},
103 {"X:a", "Y:/b", "X:a"},
104 {"X:a", "Y:b", "X:a"},
106 {"//foo", "a", dot_dot_to_root
/ "../foo"},
107 {"//foo/a", "//bar", "../foo/a"},
108 {"//foo/a", "//bar/", "../foo/a"},
109 {"//foo/a", "b", dot_dot_to_root
/ "../foo/a"},
110 {"//foo/a", "/b", "../foo/a"},
111 {"//foo/a", "//bar/b", "../../foo/a"},
112 {"X:/a", "X:/b", "../a"},
113 {"X:/a", "X:b", "../X:/a"},
114 {"X:/a", "Y:/a", "../../X:/a"},
115 {"X:/a", "Y:/b", "../../X:/a"},
116 {"X:/a", "Y:b", "../X:/a"},
117 {"X:a", "X:/b", "../../X:a"},
118 {"X:a", "X:b", "../X:a"},
119 {"X:a", "Y:/a", "../../X:a"},
120 {"X:a", "Y:/b", "../../X:a"},
121 {"X:a", "Y:b", "../X:a"},
125 {"a/b/c/", "a/b/c/", "."},
126 {"//foo/a/b", "//foo/a/b", "."},
127 {"/a/d", "/a/b/c", "../../d"},
128 {"/a/b/c", "/a/d", "../b/c"},
129 {"a/b/c", "a", "b/c"},
130 {"a/b/c", "a/b/c/x/y", "../.."},
131 {"a/b/c", "a/b/c", "."},
132 {"a/b", "c/d", "../../a/b"}
135 for (auto& TC
: TestCases
) {
136 std::error_code ec
= GetTestEC();
137 fs::path p
= TC
.input
;
138 const fs::path output
= fs::proximate(p
, TC
.base
, ec
);
139 fs::path expect
= TC
.expect
;
140 expect
.make_preferred();
142 TEST_WRITE_CONCATENATED(
143 "Input: ", TC
.input
.string(), "\nBase: ", TC
.base
.string(), "\nExpected: ", expect
.string()));
145 const path canon_input
= fs::weakly_canonical(TC
.input
);
146 const path canon_base
= fs::weakly_canonical(TC
.base
);
147 const path lexically_p
= canon_input
.lexically_proximate(canon_base
);
149 PathEq(output
, expect
),
150 TEST_WRITE_CONCATENATED(
160 lexically_p
.string(),
162 canon_input
.string(),
164 canon_base
.string()));
168 int main(int, char**) {