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"
27namespace fs = std::filesystem;
28
29int main(int, char**) {
30 // clang-format off
31 struct {
32 std::string input;
33 std::string base;
34 std::string expect;
35 } TestCases[] = {
36 {.input: "", .base: "", .expect: "."},
37 {.input: "/", .base: "a", .expect: ""},
38 {.input: "a", .base: "/", .expect: ""},
39 {.input: "//net", .base: "a", .expect: ""},
40 {.input: "a", .base: "//net", .expect: ""},
41#ifdef _WIN32
42 {"//net/", "//net", ""},
43 {"//net", "//net/", ""},
44 {"C:\\a\\b", "C:/a", "b"},
45#else
46 {.input: "//net/", .base: "//net", .expect: "."},
47 {.input: "//net", .base: "//net/", .expect: "."},
48 {.input: "C:\\a\\b", .base: "C:/a", .expect: "../../C:\\a\\b"},
49#endif
50 {.input: "//base", .base: "a", .expect: ""},
51 {.input: "a", .base: "a", .expect: "."},
52 {.input: "a/b", .base: "a/b", .expect: "."},
53 {.input: "a/b/c/", .base: "a/b/c/", .expect: "."},
54 {.input: "//net", .base: "//net", .expect: "."},
55 {.input: "//net/", .base: "//net/", .expect: "."},
56 {.input: "//net/a/b", .base: "//net/a/b", .expect: "."},
57 {.input: "/a/d", .base: "/a/b/c", .expect: "../../d"},
58 {.input: "/a/b/c", .base: "/a/d", .expect: "../b/c"},
59 {.input: "a/b/c", .base: "a", .expect: "b/c"},
60 {.input: "a/b/c", .base: "a/b/c/x/y", .expect: "../.."},
61 {.input: "a/b/c", .base: "a/b/c", .expect: "."},
62 {.input: "a/b", .base: "c/d", .expect: "../../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(base: TC.base);
68 fs::path expect(TC.expect);
69 expect.make_preferred();
70
71 // clang-format off
72 TEST_REQUIRE(
73 PathEq(LHS: output, RHS: 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(base: 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(LHS: proximate_output, RHS: 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

source code of libcxx/test/std/input.output/filesystems/class.path/path.member/path.gen/lexically_relative_and_proximate.pass.cpp