1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // REQUIRES: can-create-symlinks
10 // UNSUPPORTED: c++03, c++11, c++14
11 // UNSUPPORTED: no-filesystem
12 // UNSUPPORTED: availability-filesystem-missing
16 // path canonical(const path& p);
17 // path canonical(const path& p, error_code& ec);
20 #include <type_traits>
23 #include "assert_macros.h"
24 #include "test_macros.h"
25 #include "filesystem_test_helper.h"
26 #include "../../class.path/path_helper.h"
27 namespace fs
= std::filesystem
;
30 static void signature_test()
32 const path p
; ((void)p
);
33 std::error_code ec
; ((void)ec
);
34 ASSERT_NOT_NOEXCEPT(canonical(p
));
35 ASSERT_NOT_NOEXCEPT(canonical(p
, ec
));
38 // There are 4 cases is the proposal for absolute path.
39 // Each scope tests one of the cases.
40 static void test_canonical()
42 static_test_env static_env
;
44 // has_root_name() && has_root_directory()
45 const path Root
= static_env
.Root
;
46 const path RootName
= Root
.filename();
47 const path DirName
= static_env
.Dir
.filename();
48 const path SymlinkName
= static_env
.SymlinkToFile
.filename();
53 TestCase(path p1
, path e
, path b
)
54 : p(p1
), expect(e
), base(b
) {}
56 const TestCase testCases
[] = {
58 { DirName
/ ".." / "." / DirName
, static_env
.Dir
, Root
},
59 { static_env
.Dir2
/ "..", static_env
.Dir
, Root
},
60 { static_env
.Dir3
/ "../..", static_env
.Dir
, Root
},
61 { static_env
.Dir
/ ".", static_env
.Dir
, Root
},
62 { Root
/ "." / DirName
/ ".." / DirName
, static_env
.Dir
, Root
},
63 { path("..") / "." / RootName
/ DirName
/ ".." / DirName
,
66 { static_env
.SymlinkToFile
, static_env
.File
, Root
},
67 { SymlinkName
, static_env
.File
, Root
}
69 for (auto& TC
: testCases
) {
70 std::error_code ec
= GetTestEC();
71 fs::current_path(TC
.base
);
72 const path ret
= canonical(TC
.p
, ec
);
74 const path ret2
= canonical(TC
.p
);
75 assert(PathEq(ret
, TC
.expect
));
76 assert(PathEq(ret
, ret2
));
77 assert(ret
.is_absolute());
81 static void test_dne_path()
83 static_test_env static_env
;
84 std::error_code ec
= GetTestEC();
86 const path ret
= canonical(static_env
.DNE
, ec
);
87 assert(ec
!= GetTestEC());
89 assert(ret
== path
{});
92 TEST_THROWS_TYPE(filesystem_error
, canonical(static_env
.DNE
));
96 static void test_exception_contains_paths()
98 #ifndef TEST_HAS_NO_EXCEPTIONS
99 static_test_env static_env
;
101 const path p
= "blabla/dne";
105 } catch (filesystem_error
const& err
) {
106 assert(err
.path1() == p
);
107 // libc++ provides the current path as the second path in the exception
108 LIBCPP_ASSERT(err
.path2() == current_path());
110 fs::current_path(static_env
.Dir
);
114 } catch (filesystem_error
const& err
) {
115 assert(err
.path1() == p
);
116 LIBCPP_ASSERT(err
.path2() == static_env
.Dir
);
121 int main(int, char**) {
125 test_exception_contains_paths();