//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // // path canonical(const path& p); // path canonical(const path& p, error_code& ec); #include #include #include #include "assert_macros.h" #include "test_macros.h" #include "filesystem_test_helper.h" #include "../../class.path/path_helper.h" namespace fs = std::filesystem; using namespace fs; static void signature_test() { const path p; ((void)p); std::error_code ec; ((void)ec); ASSERT_NOT_NOEXCEPT(canonical(p)); ASSERT_NOT_NOEXCEPT(canonical(p, ec)); } // There are 4 cases is the proposal for absolute path. // Each scope tests one of the cases. static void test_canonical() { static_test_env static_env; CWDGuard guard; // has_root_name() && has_root_directory() const path Root = static_env.Root; const path RootName = Root.filename(); const path DirName = static_env.Dir.filename(); const path SymlinkName = static_env.SymlinkToFile.filename(); struct TestCase { path p; path expect; path base; TestCase(path p1, path e, path b) : p(p1), expect(e), base(b) {} }; const TestCase testCases[] = { { ".", Root, Root }, { DirName / ".." / "." / DirName, static_env.Dir, Root }, { static_env.Dir2 / "..", static_env.Dir, Root }, { static_env.Dir3 / "../..", static_env.Dir, Root }, { static_env.Dir / ".", static_env.Dir, Root }, { Root / "." / DirName / ".." / DirName, static_env.Dir, Root }, { path("..") / "." / RootName / DirName / ".." / DirName, static_env.Dir, Root }, { static_env.SymlinkToFile, static_env.File, Root }, { SymlinkName, static_env.File, Root} }; for (auto& TC : testCases) { std::error_code ec = GetTestEC(); fs::current_path(TC.base); const path ret = canonical(TC.p, ec); assert(!ec); const path ret2 = canonical(TC.p); assert(PathEq(ret, TC.expect)); assert(PathEq(ret, ret2)); assert(ret.is_absolute()); } } static void test_dne_path() { static_test_env static_env; std::error_code ec = GetTestEC(); { const path ret = canonical(static_env.DNE, ec); assert(ec != GetTestEC()); assert(ec); assert(ret == path{}); } { TEST_THROWS_TYPE(filesystem_error, canonical(static_env.DNE)); } } static void test_exception_contains_paths() { #ifndef TEST_HAS_NO_EXCEPTIONS static_test_env static_env; CWDGuard guard; const path p = "blabla/dne"; try { (void)canonical(p); assert(false); } catch (filesystem_error const& err) { assert(err.path1() == p); // libc++ provides the current path as the second path in the exception LIBCPP_ASSERT(err.path2() == current_path()); } fs::current_path(static_env.Dir); try { (void)canonical(p); assert(false); } catch (filesystem_error const& err) { assert(err.path1() == p); LIBCPP_ASSERT(err.path2() == static_env.Dir); } #endif } int main(int, char**) { signature_test(); test_canonical(); test_dne_path(); test_exception_contains_paths(); return 0; }