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