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