diff options
Diffstat (limited to 'libcxx/test/std/experimental/filesystem/fs.op.funcs')
7 files changed, 321 insertions, 157 deletions
diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.absolute/absolute.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.absolute/absolute.pass.cpp index 97d168a4a53..9b73aedc8ef 100644 --- a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.absolute/absolute.pass.cpp +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.absolute/absolute.pass.cpp @@ -28,89 +28,30 @@ TEST_SUITE(filesystem_absolute_path_test_suite) TEST_CASE(absolute_signature_test) { const path p; ((void)p); + std::error_code ec; ASSERT_NOT_NOEXCEPT(absolute(p)); - ASSERT_NOT_NOEXCEPT(absolute(p, p)); + ASSERT_NOT_NOEXCEPT(absolute(p, ec)); } -// There are 4 cases is the proposal for absolute path. -// Each scope tests one of the cases. -TEST_CASE(absolute_path_test) -{ - // has_root_name() && has_root_directory() - { - const path p("//net/foo"); - const path base("//net/bar/baz"); - TEST_REQUIRE(p.has_root_name()); - TEST_REQUIRE(p.has_root_directory()); - TEST_CHECK(p.is_absolute()); - path ret = absolute(p, base); - TEST_CHECK(ret.is_absolute()); - TEST_CHECK(ret == p); - } - // !has_root_name() && has_root_directory() - { - const path p("/foo"); - const path base("//net/bar"); - TEST_REQUIRE(not p.has_root_name()); - TEST_REQUIRE(p.has_root_directory()); - TEST_CHECK(p.is_absolute()); - // ensure absolute(base) is not recursively called - TEST_REQUIRE(base.has_root_name()); - TEST_REQUIRE(base.has_root_directory()); - - path ret = absolute(p, base); - TEST_CHECK(ret.is_absolute()); - TEST_CHECK(ret.has_root_name()); - TEST_CHECK(ret.root_name() == path("//net")); - TEST_CHECK(ret.has_root_directory()); - TEST_CHECK(ret.root_directory() == path("/")); - TEST_CHECK(ret == path("//net/foo")); - } - // has_root_name() && !has_root_directory() - { - const path p("//net"); - const path base("//net/foo/bar"); - TEST_REQUIRE(p.has_root_name()); - TEST_REQUIRE(not p.has_root_directory()); - TEST_CHECK(not p.is_absolute()); - // absolute is called recursively on base. The following conditions - // must be true for it to return base unmodified - TEST_REQUIRE(base.has_root_name()); - TEST_REQUIRE(base.has_root_directory()); - path ret = absolute(p, base); - const path expect("//net/foo/bar"); - TEST_CHECK(ret.is_absolute()); - TEST_CHECK(ret == path("//net/foo/bar")); - } - // !has_root_name() && !has_root_directory() - { - const path p("bar/baz"); - const path base("//net/foo"); - TEST_REQUIRE(not p.has_root_name()); - TEST_REQUIRE(not p.has_root_directory()); - TEST_REQUIRE(base.has_root_name()); - TEST_REQUIRE(base.has_root_directory()); - - path ret = absolute(p, base); - TEST_CHECK(ret.is_absolute()); - TEST_CHECK(ret == path("//net/foo/bar/baz")); - } -} -TEST_CASE(absolute_path_with_default_base) +TEST_CASE(basic_test) { - const path testCases[] = { - "//net/foo", // has_root_name() && has_root_directory() - "/foo", // !has_root_name() && has_root_directory() - "//net", // has_root_name() && !has_root_directory() - "bar/baz" // !has_root_name() && !has_root_directory() + const fs::path cwd = fs::current_path(); + const struct { + std::string input; + std::string expect; + } TestCases [] = { + {"", cwd / ""}, + {"foo", cwd / "foo"}, + {"foo/", cwd / "foo/"}, + {"/already_absolute", "/already_absolute"} }; - const path base = current_path(); - for (auto& p : testCases) { - const path ret = absolute(p); - const path expect = absolute(p, base); + for (auto& TC : TestCases) { + std::error_code ec = GetTestEC(); + const path ret = absolute(TC.input, ec); + TEST_CHECK(!ec); TEST_CHECK(ret.is_absolute()); - TEST_CHECK(ret == expect); + TEST_CHECK(PathEq(ret, TC.expect)); } } diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.canonical/canonical.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.canonical/canonical.pass.cpp index 0872b7b30dd..c9c9128aa2a 100644 --- a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.canonical/canonical.pass.cpp +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.canonical/canonical.pass.cpp @@ -11,9 +11,8 @@ // <experimental/filesystem> -// path canonical(const path& p, const path& base = current_path()); +// path canonical(const path& p); // path canonical(const path& p, error_code& ec); -// path canonical(const path& p, const path& base, error_code& ec); #include "filesystem_include.hpp" #include <type_traits> @@ -25,6 +24,15 @@ using namespace fs; +struct CWDGuard { + path OldCWD; + CWDGuard() : OldCWD(fs::current_path()) { } + ~CWDGuard() { fs::current_path(OldCWD); } + + CWDGuard(CWDGuard const&) = delete; + CWDGuard& operator=(CWDGuard const&) = delete; +}; + TEST_SUITE(filesystem_canonical_path_test_suite) TEST_CASE(signature_test) @@ -32,15 +40,14 @@ TEST_CASE(signature_test) const path p; ((void)p); std::error_code ec; ((void)ec); ASSERT_NOT_NOEXCEPT(canonical(p)); - ASSERT_NOT_NOEXCEPT(canonical(p, p)); ASSERT_NOT_NOEXCEPT(canonical(p, ec)); - ASSERT_NOT_NOEXCEPT(canonical(p, p, ec)); } // There are 4 cases is the proposal for absolute path. // Each scope tests one of the cases. TEST_CASE(test_canonical) { + CWDGuard guard; // has_root_name() && has_root_directory() const path Root = StaticEnv::Root; const path RootName = Root.filename(); @@ -65,54 +72,51 @@ TEST_CASE(test_canonical) { SymlinkName, StaticEnv::File, StaticEnv::Root} }; for (auto& TC : testCases) { - std::error_code ec; - const path ret = canonical(TC.p, TC.base, ec); + std::error_code ec = GetTestEC(); + fs::current_path(TC.base); + const path ret = canonical(TC.p, ec); TEST_REQUIRE(!ec); - const path ret2 = canonical(TC.p, TC.base); - TEST_CHECK(ret == TC.expect); - TEST_CHECK(ret == ret2); + const path ret2 = canonical(TC.p); + TEST_CHECK(PathEq(ret, TC.expect)); + TEST_CHECK(PathEq(ret, ret2)); TEST_CHECK(ret.is_absolute()); } } TEST_CASE(test_dne_path) { - std::error_code ec; + std::error_code ec = GetTestEC(); { const path ret = canonical(StaticEnv::DNE, ec); - TEST_REQUIRE(ec); - TEST_CHECK(ret == path{}); - } - ec.clear(); - { - const path ret = canonical(StaticEnv::DNE, StaticEnv::Root, ec); + TEST_CHECK(ec != GetTestEC()); TEST_REQUIRE(ec); TEST_CHECK(ret == path{}); } { TEST_CHECK_THROW(filesystem_error, canonical(StaticEnv::DNE)); - TEST_CHECK_THROW(filesystem_error, canonical(StaticEnv::DNE, StaticEnv::Root)); } } TEST_CASE(test_exception_contains_paths) { #ifndef TEST_HAS_NO_EXCEPTIONS + CWDGuard guard; const path p = "blabla/dne"; - const path base = StaticEnv::Root; try { - canonical(p, base); + canonical(p); TEST_REQUIRE(false); } catch (filesystem_error const& err) { TEST_CHECK(err.path1() == p); - TEST_CHECK(err.path2() == base); + // libc++ provides the current path as the second path in the exception + LIBCPP_ONLY(TEST_CHECK(err.path2() == current_path())); } + fs::current_path(StaticEnv::Dir); try { canonical(p); TEST_REQUIRE(false); } catch (filesystem_error const& err) { TEST_CHECK(err.path1() == p); - TEST_CHECK(err.path2() == current_path()); + LIBCPP_ONLY(TEST_CHECK(err.path2() == StaticEnv::Dir)); } #endif } diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp index b842b4a1896..ce763a6c391 100644 --- a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp @@ -17,7 +17,6 @@ // void last_write_time(const path& p, file_time_type new_type, // std::error_code& ec) noexcept; - #include "filesystem_include.hpp" #include <type_traits> #include <chrono> @@ -33,7 +32,6 @@ using namespace fs; - std::pair<std::time_t, std::time_t> GetTimes(path const& p) { using Clock = file_time_type::clock; struct ::stat st; diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.proximate/proximate.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.proximate/proximate.pass.cpp new file mode 100644 index 00000000000..7b526507f0a --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.proximate/proximate.pass.cpp @@ -0,0 +1,125 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// <experimental/filesystem> + +// path proximate(const path& p, error_code &ec) +// path proximate(const path& p, const path& base = current_path()) +// path proximate(const path& p, const path& base, error_code& ec); + +#include "filesystem_include.hpp" +#include <type_traits> +#include <vector> +#include <iostream> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" +#include "count_new.hpp" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + + +static int count_path_elems(const fs::path& p) { + int count = 0; + for (auto& elem : p) { + if (elem != "/" && elem != "") + ++count; + } + return count; +} + +TEST_SUITE(filesystem_proximate_path_test_suite) + + +TEST_CASE(signature_test) +{ + using fs::path; + const path p; ((void)p); + std::error_code ec; ((void)ec); + ASSERT_NOT_NOEXCEPT(proximate(p)); + ASSERT_NOT_NOEXCEPT(proximate(p, p)); + ASSERT_NOT_NOEXCEPT(proximate(p, ec)); + ASSERT_NOT_NOEXCEPT(proximate(p, p, ec)); +} + +TEST_CASE(basic_test) { + using fs::path; + const path cwd = fs::current_path(); + const path parent_cwd = cwd.parent_path(); + const path curdir = cwd.filename(); + TEST_REQUIRE(!cwd.native().empty()); + int cwd_depth = count_path_elems(cwd); + path dot_dot_to_root; + for (int i=0; i < cwd_depth; ++i) + dot_dot_to_root /= ".."; + path relative_cwd = cwd.native().substr(1); + // clang-format off + struct { + std::string input; + std::string base; + std::string expect; + } TestCases[] = { + {"", "", "."}, + {cwd, "a", ".."}, + {parent_cwd, "a", "../.."}, + {"a", cwd, "a"}, + {"a", parent_cwd, "fs.op.proximate/a"}, + {"/", "a", dot_dot_to_root / ".."}, + {"/", "a/b", dot_dot_to_root / "../.."}, + {"/", "a/b/", dot_dot_to_root / "../../.."}, + {"a", "/", relative_cwd / "a"}, + {"a/b", "/", relative_cwd / "a/b"}, + {"a", "/net", ".." / relative_cwd / "a"}, + {"//net/", "//net", "/net/"}, + {"//net", "//net/", ".."}, + {"//net", "//net", "."}, + {"//net/", "//net/", "."}, + {"//base", "a", dot_dot_to_root / "../base"}, + {"a", "a", "."}, + {"a/b", "a/b", "."}, + {"a/b/c/", "a/b/c/", "."}, + {"//net/a/b", "//net/a/b", "."}, + {"/a/d", "/a/b/c", "../../d"}, + {"/a/b/c", "/a/d", "../b/c"}, + {"a/b/c", "a", "b/c"}, + {"a/b/c", "a/b/c/x/y", "../.."}, + {"a/b/c", "a/b/c", "."}, + {"a/b", "c/d", "../../a/b"} + }; + // clang-format on + int ID = 0; + for (auto& TC : TestCases) { + ++ID; + std::error_code ec = GetTestEC(); + fs::path p(TC.input); + const fs::path output = fs::proximate(p, TC.base, ec); + TEST_CHECK(!ec); + TEST_CHECK(PathEq(output, TC.expect)); + if (!PathEq(output, TC.expect)) { + const path canon_input = fs::weakly_canonical(TC.input); + const path canon_base = fs::weakly_canonical(TC.base); + const path lexically_p = canon_input.lexically_proximate(canon_base); + std::cerr << "TEST CASE #" << ID << " FAILED: \n"; + std::cerr << " Input: '" << TC.input << "'\n"; + std::cerr << " Base: '" << TC.base << "'\n"; + std::cerr << " Expected: '" << TC.expect << "'\n"; + std::cerr << " Output: '" << output.native() << "'\n"; + std::cerr << " Lex Prox: '" << lexically_p.native() << "'\n"; + std::cerr << " Canon Input: " << canon_input << "\n"; + std::cerr << " Canon Base: " << canon_base << "\n"; + + std::cerr << std::endl; + } + } +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.relative/relative.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.relative/relative.pass.cpp new file mode 100644 index 00000000000..62bc32a732b --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.relative/relative.pass.cpp @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// <experimental/filesystem> + +// path proximate(const path& p, error_code &ec) +// path proximate(const path& p, const path& base = current_path()) +// path proximate(const path& p, const path& base, error_code& ec); + +#include "filesystem_include.hpp" +#include <type_traits> +#include <vector> +#include <iostream> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" +#include "count_new.hpp" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + + +TEST_SUITE(filesystem_proximate_path_test_suite) + +TEST_CASE(test_signature) { + +} +int main() { + // clang-format off + struct { + std::string input; + std::string expect; + } TestCases[] = { + {"", fs::current_path()}, + {".", fs::current_path()}, + {StaticEnv::File, StaticEnv::File}, + {StaticEnv::Dir, StaticEnv::Dir}, + {StaticEnv::SymlinkToDir, StaticEnv::Dir}, + {StaticEnv::SymlinkToDir / "dir2/.", StaticEnv::Dir / "dir2"}, + // FIXME? If the trailing separator occurs in a part of the path that exists, + // it is ommitted. Otherwise it is added to the end of the result. + {StaticEnv::SymlinkToDir / "dir2/./", StaticEnv::Dir / "dir2"}, + {StaticEnv::SymlinkToDir / "dir2/DNE/./", StaticEnv::Dir / "dir2/DNE/"}, + {StaticEnv::SymlinkToDir / "dir2", StaticEnv::Dir2}, + {StaticEnv::SymlinkToDir / "dir2/../dir2/DNE/..", StaticEnv::Dir2 / ""}, + {StaticEnv::SymlinkToDir / "dir2/dir3/../DNE/DNE2", StaticEnv::Dir2 / "DNE/DNE2"}, + {StaticEnv::Dir / "../dir1", StaticEnv::Dir}, + {StaticEnv::Dir / "./.", StaticEnv::Dir}, + {StaticEnv::Dir / "DNE/../foo", StaticEnv::Dir / "foo"} + }; + // clang-format on + int ID = 0; + bool Failed = false; + for (auto& TC : TestCases) { + ++ID; + fs::path p(TC.input); + const fs::path output = fs::weakly_canonical(p); + if (output != TC.expect) { + Failed = true; + std::cerr << "TEST CASE #" << ID << " FAILED: \n"; + std::cerr << " Input: '" << TC.input << "'\n"; + std::cerr << " Expected: '" << TC.expect << "'\n"; + std::cerr << " Output: '" << output.native() << "'"; + std::cerr << std::endl; + } + } + return Failed; +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.system_complete/system_complete.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.system_complete/system_complete.pass.cpp deleted file mode 100644 index b4fb1f19af9..00000000000 --- a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.system_complete/system_complete.pass.cpp +++ /dev/null @@ -1,58 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++98, c++03 - -// <experimental/filesystem> - -// path system_complete(const path& p); -// path system_complete(const path& p, error_code& ec); - -// Note: For POSIX based operating systems, 'system_complete(p)' has the -// same semantics as 'absolute(p, current_path())'. - -#include "filesystem_include.hpp" -#include <type_traits> -#include <cassert> - -#include "test_macros.h" -#include "rapid-cxx-test.hpp" -#include "filesystem_test_helper.hpp" - -using namespace fs; - -TEST_SUITE(filesystem_system_complete_test_suite) - -TEST_CASE(signature_test) -{ - const path p; ((void)p); - std::error_code ec; ((void)ec); - ASSERT_NOT_NOEXCEPT(system_complete(p)); - ASSERT_NOT_NOEXCEPT(system_complete(p, ec)); -} - - -TEST_CASE(basic_system_complete_tests) -{ - const path testCases[] = { - "//net/foo", // has_root_name() && has_root_directory() - "/foo", // !has_root_name() && has_root_directory() - "//net", // has_root_name() && !has_root_directory() - "bar/baz" // !has_root_name() && !has_root_directory() - }; - const path base = current_path(); - for (auto& p : testCases) { - const path ret = system_complete(p); - const path expect = absolute(p, base); - TEST_CHECK(ret.is_absolute()); - TEST_CHECK(ret == expect); - } -} - -TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.weakly_canonical/weakly_canonical.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.weakly_canonical/weakly_canonical.pass.cpp new file mode 100644 index 00000000000..b4cb81d5bce --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.weakly_canonical/weakly_canonical.pass.cpp @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// <experimental/filesystem> + +// path weakly_canonical(const path& p); +// path weakly_canonical(const path& p, error_code& ec); + +#include "filesystem_include.hpp" +#include <type_traits> +#include <vector> +#include <iostream> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" +#include "count_new.hpp" +#include "filesystem_test_helper.hpp" + + +int main() { + // clang-format off + struct { + std::string input; + std::string expect; + } TestCases[] = { + {"", fs::current_path()}, + {".", fs::current_path()}, + {"/", "/"}, + {"/foo", "/foo"}, + {"/.", "/"}, + {"/./", "/"}, + {"a/b", fs::current_path() / "a/b"}, + {"a", fs::current_path() / "a"}, + {"a/b/", fs::current_path() / "a/b/"}, + {StaticEnv::File, StaticEnv::File}, + {StaticEnv::Dir, StaticEnv::Dir}, + {StaticEnv::SymlinkToDir, StaticEnv::Dir}, + {StaticEnv::SymlinkToDir / "dir2/.", StaticEnv::Dir / "dir2"}, + // FIXME? If the trailing separator occurs in a part of the path that exists, + // it is ommitted. Otherwise it is added to the end of the result. + {StaticEnv::SymlinkToDir / "dir2/./", StaticEnv::Dir / "dir2"}, + {StaticEnv::SymlinkToDir / "dir2/DNE/./", StaticEnv::Dir / "dir2/DNE/"}, + {StaticEnv::SymlinkToDir / "dir2", StaticEnv::Dir2}, + {StaticEnv::SymlinkToDir / "dir2/../dir2/DNE/..", StaticEnv::Dir2 / ""}, + {StaticEnv::SymlinkToDir / "dir2/dir3/../DNE/DNE2", StaticEnv::Dir2 / "DNE/DNE2"}, + {StaticEnv::Dir / "../dir1", StaticEnv::Dir}, + {StaticEnv::Dir / "./.", StaticEnv::Dir}, + {StaticEnv::Dir / "DNE/../foo", StaticEnv::Dir / "foo"} + }; + // clang-format on + int ID = 0; + bool Failed = false; + for (auto& TC : TestCases) { + ++ID; + fs::path p(TC.input); + const fs::path output = fs::weakly_canonical(p); + if (!PathEq(output, TC.expect)) { + Failed = true; + std::cerr << "TEST CASE #" << ID << " FAILED: \n"; + std::cerr << " Input: '" << TC.input << "'\n"; + std::cerr << " Expected: '" << TC.expect << "'\n"; + std::cerr << " Output: '" << output.native() << "'"; + std::cerr << std::endl; + } + } + return Failed; +} |