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, c++11, c++14
10 // UNSUPPORTED: availability-filesystem-missing
11 
12 // <filesystem>
13 
14 // class path
15 
16 // path lexically_relative(const path& p) const;
17 // path lexically_proximate(const path& p) const;
18 
19 #include <filesystem>
20 #include <string>
21 
22 #include "../../path_helper.h"
23 #include "assert_macros.h"
24 #include "concat_macros.h"
25 #include "count_new.h"
26 #include "test_macros.h"
27 namespace fs = std::filesystem;
28 
29 int main(int, char**) {
30   // clang-format off
31   struct {
32     std::string input;
33     std::string base;
34     std::string expect;
35   } TestCases[] = {
36       {"", "", "."},
37       {"/", "a", ""},
38       {"a", "/", ""},
39       {"//net", "a", ""},
40       {"a", "//net", ""},
41 #ifdef _WIN32
42       {"//net/", "//net", ""},
43       {"//net", "//net/", ""},
44       {"C:\\a\\b", "C:/a", "b"},
45 #else
46       {"//net/", "//net", "."},
47       {"//net", "//net/", "."},
48       {"C:\\a\\b", "C:/a", "../../C:\\a\\b"},
49 #endif
50       {"//base", "a", ""},
51       {"a", "a", "."},
52       {"a/b", "a/b", "."},
53       {"a/b/c/", "a/b/c/", "."},
54       {"//net", "//net", "."},
55       {"//net/", "//net/", "."},
56       {"//net/a/b", "//net/a/b", "."},
57       {"/a/d", "/a/b/c", "../../d"},
58       {"/a/b/c", "/a/d", "../b/c"},
59       {"a/b/c", "a", "b/c"},
60       {"a/b/c", "a/b/c/x/y", "../.."},
61       {"a/b/c", "a/b/c", "."},
62       {"a/b", "c/d", "../../a/b"}
63   };
64   // clang-format on
65   for (auto& TC : TestCases) {
66     const fs::path p(TC.input);
67     const fs::path output = p.lexically_relative(TC.base);
68     fs::path expect(TC.expect);
69     expect.make_preferred();
70 
71     // clang-format off
72     TEST_REQUIRE(
73         PathEq(output, expect),
74         TEST_WRITE_CONCATENATED(
75             "path::lexically_relative test case failed",
76             "\nInput: ", TC.input,
77             "\nBase: ", TC.base,
78             "\nExpected: ", expect,
79             "\nOutput: ", output));
80     // clang-format on
81 
82     const fs::path proximate_output = p.lexically_proximate(TC.base);
83     // [path.gen] lexically_proximate
84     // Returns: If the value of lexically_relative(base) is not an empty path,
85     // return it. Otherwise return *this.
86     const fs::path proximate_expect = expect.empty() ? p : expect;
87 
88     // clang-format off
89     TEST_REQUIRE(
90         PathEq(proximate_output, proximate_expect),
91         TEST_WRITE_CONCATENATED(
92             "path::lexically_proximate test case failed",
93             "\nInput: ", TC.input,
94             "\nBase: ", TC.base,
95             "\nExpected: ", proximate_expect,
96             "\nOutput: ", proximate_output));
97     // clang-format on
98   }
99 
100   return 0;
101 }
102