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 // <filesystem>
12 
13 // path canonical(const path& p);
14 // path canonical(const path& p, error_code& ec);
15 
16 #include "filesystem_include.h"
17 #include <type_traits>
18 #include <cassert>
19 
20 #include "test_macros.h"
21 #include "rapid-cxx-test.h"
22 #include "filesystem_test_helper.h"
23 
24 using namespace fs;
25 
26 TEST_SUITE(filesystem_canonical_path_test_suite)
27 
TEST_CASE(signature_test)28 TEST_CASE(signature_test)
29 {
30     const path p; ((void)p);
31     std::error_code ec; ((void)ec);
32     ASSERT_NOT_NOEXCEPT(canonical(p));
33     ASSERT_NOT_NOEXCEPT(canonical(p, ec));
34 }
35 
36 // There are 4 cases is the proposal for absolute path.
37 // Each scope tests one of the cases.
TEST_CASE(test_canonical)38 TEST_CASE(test_canonical)
39 {
40     static_test_env static_env;
41     CWDGuard guard;
42     // has_root_name() && has_root_directory()
43     const path Root = static_env.Root;
44     const path RootName = Root.filename();
45     const path DirName = static_env.Dir.filename();
46     const path SymlinkName = static_env.SymlinkToFile.filename();
47     struct TestCase {
48         path p;
49         path expect;
50         path base;
51         TestCase(path p1, path e, path b)
52             : p(p1), expect(e), base(b) {}
53     };
54     const TestCase testCases[] = {
55         { ".", Root, Root },
56         { DirName / ".." / "." / DirName, static_env.Dir, Root },
57         { static_env.Dir2 / "..",    static_env.Dir, Root },
58         { static_env.Dir3 / "../..", static_env.Dir, Root },
59         { static_env.Dir / ".",      static_env.Dir, Root },
60         { Root / "." / DirName / ".." / DirName, static_env.Dir, Root },
61         { path("..") / "." / RootName / DirName / ".." / DirName,
62           static_env.Dir,
63           Root },
64         { static_env.SymlinkToFile,  static_env.File, Root },
65         { SymlinkName, static_env.File, Root}
66     };
67     for (auto& TC : testCases) {
68         std::error_code ec = GetTestEC();
69         fs::current_path(TC.base);
70         const path ret = canonical(TC.p, ec);
71         TEST_REQUIRE(!ec);
72         const path ret2 = canonical(TC.p);
73         TEST_CHECK(PathEq(ret, TC.expect));
74         TEST_CHECK(PathEq(ret, ret2));
75         TEST_CHECK(ret.is_absolute());
76     }
77 }
78 
TEST_CASE(test_dne_path)79 TEST_CASE(test_dne_path)
80 {
81     static_test_env static_env;
82     std::error_code ec = GetTestEC();
83     {
84         const path ret = canonical(static_env.DNE, ec);
85         TEST_CHECK(ec != GetTestEC());
86         TEST_REQUIRE(ec);
87         TEST_CHECK(ret == path{});
88     }
89     {
90         TEST_CHECK_THROW(filesystem_error, canonical(static_env.DNE));
91     }
92 }
93 
TEST_CASE(test_exception_contains_paths)94 TEST_CASE(test_exception_contains_paths)
95 {
96 #ifndef TEST_HAS_NO_EXCEPTIONS
97     static_test_env static_env;
98     CWDGuard guard;
99     const path p = "blabla/dne";
100     try {
101         (void)canonical(p);
102         TEST_REQUIRE(false);
103     } catch (filesystem_error const& err) {
104         TEST_CHECK(err.path1() == p);
105         // libc++ provides the current path as the second path in the exception
106         LIBCPP_ONLY(TEST_CHECK(err.path2() == current_path()));
107     }
108     fs::current_path(static_env.Dir);
109     try {
110         (void)canonical(p);
111         TEST_REQUIRE(false);
112     } catch (filesystem_error const& err) {
113         TEST_CHECK(err.path1() == p);
114         LIBCPP_ONLY(TEST_CHECK(err.path2() == static_env.Dir));
115     }
116 #endif
117 }
118 
119 TEST_SUITE_END()
120