diff options
Diffstat (limited to 'libcxx/test/std/experimental/filesystem')
19 files changed, 752 insertions, 270 deletions
diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.itr/iterator.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.itr/iterator.pass.cpp index e5b3c848255..0ea672bdf1e 100644 --- a/libcxx/test/std/experimental/filesystem/class.path/path.itr/iterator.pass.cpp +++ b/libcxx/test/std/experimental/filesystem/class.path/path.itr/iterator.pass.cpp @@ -83,14 +83,14 @@ void checkBeginEndBasic() { } { path p("//root_name//first_dir////second_dir"); - const path expect[] = {"//root_name", "/", "first_dir", "second_dir"}; + const path expect[] = {"/", "root_name", "first_dir", "second_dir"}; assert(checkCollectionsEqual(p.begin(), p.end(), std::begin(expect), std::end(expect))); assert(checkCollectionsEqualBackwards(p.begin(), p.end(), std::begin(expect), std::end(expect))); } { path p("////foo/bar/baz///"); - const path expect[] = {"/", "foo", "bar", "baz", "."}; + const path expect[] = {"/", "foo", "bar", "baz", ""}; assert(checkCollectionsEqual(p.begin(), p.end(), std::begin(expect), std::end(expect))); assert(checkCollectionsEqualBackwards(p.begin(), p.end(), std::begin(expect), std::end(expect))); diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.append.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.append.pass.cpp index ca072d16114..11bc5dd9b86 100644 --- a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.append.pass.cpp +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.append.pass.cpp @@ -31,6 +31,7 @@ #include "test_iterators.h" #include "count_new.hpp" #include "filesystem_test_helper.hpp" +#include "verbose_assert.h" struct AppendOperatorTestcase { @@ -45,13 +46,22 @@ const AppendOperatorTestcase Cases[] = {S(""), S(""), S("")} , {S("p1"), S("p2"), S("p1/p2")} , {S("p1/"), S("p2"), S("p1/p2")} - , {S("p1"), S("/p2"), S("p1/p2")} - , {S("p1/"), S("/p2"), S("p1//p2")} + , {S("p1"), S("/p2"), S("/p2")} + , {S("p1/"), S("/p2"), S("/p2")} , {S("p1"), S("\\p2"), S("p1/\\p2")} , {S("p1\\"), S("p2"), S("p1\\/p2")} , {S("p1\\"), S("\\p2"), S("p1\\/\\p2")} - , {S("p1"), S(""), S("p1")} , {S(""), S("p2"), S("p2")} + , {S("/p1"), S("p2"), S("/p1/p2")} + , {S("/p1"), S("/p2"), S("/p2")} + , {S("/p1/p3"), S("p2"), S("/p1/p3/p2")} + , {S("/p1/p3/"), S("p2"), S("/p1/p3/p2")} + , {S("/p1/"), S("p2"), S("/p1/p2")} + , {S("/p1/p3/"), S("/p2/p4"), S("/p2/p4")} + , {S("/"), S(""), S("/")} + , {S("/p1"), S("/p2/"), S("/p2/")} + , {S("p1"), S(""), S("p1/")} + , {S("p1/"), S(""), S("p1/")} }; @@ -59,7 +69,8 @@ const AppendOperatorTestcase LongLHSCases[] = { {S("p1"), S("p2"), S("p1/p2")} , {S("p1/"), S("p2"), S("p1/p2")} - , {S("p1"), S("/p2"), S("p1/p2")} + , {S("p1"), S("/p2"), S("/p2")} + , {S("/p1"), S("p2"), S("/p1/p2")} }; #undef S @@ -98,7 +109,7 @@ void doAppendSourceAllocTest(AppendOperatorTestcase const& TC) DisableAllocationGuard g; LHS /= RHS; } - assert(LHS == E); + ASSERT_PRED(PathEq, LHS , E); } // basic_string_view { @@ -108,7 +119,7 @@ void doAppendSourceAllocTest(AppendOperatorTestcase const& TC) DisableAllocationGuard g; LHS /= RHS; } - assert(LHS == E); + assert(PathEq(LHS, E)); } // CharT* { @@ -118,7 +129,7 @@ void doAppendSourceAllocTest(AppendOperatorTestcase const& TC) DisableAllocationGuard g; LHS /= RHS; } - assert(LHS == E); + assert(PathEq(LHS, E)); } { path LHS(L); PathReserve(LHS, ReserveSize); @@ -127,7 +138,7 @@ void doAppendSourceAllocTest(AppendOperatorTestcase const& TC) DisableAllocationGuard g; LHS.append(RHS, StrEnd(RHS)); } - assert(LHS == E); + assert(PathEq(LHS, E)); } // input iterator - For non-native char types, appends needs to copy the // iterator range into a contiguous block of memory before it can perform the @@ -143,7 +154,7 @@ void doAppendSourceAllocTest(AppendOperatorTestcase const& TC) if (DisableAllocations) g.requireExactly(0); LHS /= RHS; } - assert(LHS == E); + assert(PathEq(LHS, E)); } { path LHS(L); PathReserve(LHS, ReserveSize); @@ -154,7 +165,7 @@ void doAppendSourceAllocTest(AppendOperatorTestcase const& TC) if (DisableAllocations) g.requireExactly(0); LHS.append(RHS, REnd); } - assert(LHS == E); + assert(PathEq(LHS, E)); } } @@ -171,17 +182,18 @@ void doAppendSourceTest(AppendOperatorTestcase const& TC) const Ptr E = TC.expect; // basic_string { - path LHS(L); + path Result(L); Str RHS(R); - path& Ref = (LHS /= RHS); - assert(LHS == E); - assert(&Ref == &LHS); + path& Ref = (Result /= RHS); + ASSERT_EQ(Result, E) + << DISPLAY(L) << DISPLAY(R); + assert(&Ref == &Result); } { path LHS(L); Str RHS(R); path& Ref = LHS.append(RHS); - assert(LHS == E); + assert(PathEq(LHS, E)); assert(&Ref == &LHS); } // basic_string_view @@ -189,14 +201,14 @@ void doAppendSourceTest(AppendOperatorTestcase const& TC) path LHS(L); StrView RHS(R); path& Ref = (LHS /= RHS); - assert(LHS == E); + assert(PathEq(LHS, E)); assert(&Ref == &LHS); } { path LHS(L); StrView RHS(R); path& Ref = LHS.append(RHS); - assert(LHS == E); + assert(PathEq(LHS, E)); assert(&Ref == &LHS); } // Char* @@ -204,21 +216,22 @@ void doAppendSourceTest(AppendOperatorTestcase const& TC) path LHS(L); Str RHS(R); path& Ref = (LHS /= RHS); - assert(LHS == E); + assert(PathEq(LHS, E)); assert(&Ref == &LHS); } { path LHS(L); Ptr RHS(R); path& Ref = LHS.append(RHS); - assert(LHS == E); + assert(PathEq(LHS, E)); assert(&Ref == &LHS); } { path LHS(L); Ptr RHS(R); path& Ref = LHS.append(RHS, StrEnd(RHS)); - assert(LHS == E); + ASSERT_PRED(PathEq, LHS, E) + << DISPLAY(L) << DISPLAY(R); assert(&Ref == &LHS); } // iterators @@ -226,13 +239,13 @@ void doAppendSourceTest(AppendOperatorTestcase const& TC) path LHS(L); InputIter RHS(R); path& Ref = (LHS /= RHS); - assert(LHS == E); + assert(PathEq(LHS, E)); assert(&Ref == &LHS); } { path LHS(L); InputIter RHS(R); path& Ref = LHS.append(RHS); - assert(LHS == E); + assert(PathEq(LHS, E)); assert(&Ref == &LHS); } { @@ -240,7 +253,7 @@ void doAppendSourceTest(AppendOperatorTestcase const& TC) InputIter RHS(R); InputIter REnd(StrEnd(R)); path& Ref = LHS.append(RHS, REnd); - assert(LHS == E); + assert(PathEq(LHS, E)); assert(&Ref == &LHS); } } @@ -304,11 +317,14 @@ int main() using namespace fs; for (auto const & TC : Cases) { { - path LHS((const char*)TC.lhs); - path RHS((const char*)TC.rhs); - path& Ref = (LHS /= RHS); - assert(LHS == (const char*)TC.expect); - assert(&Ref == &LHS); + const char* LHS_In = TC.lhs; + const char* RHS_In = TC.rhs; + path LHS(LHS_In); + path RHS(RHS_In); + path& Res = (LHS /= RHS); + ASSERT_PRED(PathEq, Res, (const char*)TC.expect) + << DISPLAY(LHS_In) << DISPLAY(RHS_In); + assert(&Res == &LHS); } doAppendSourceTest<char> (TC); doAppendSourceTest<wchar_t> (TC); diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.compare.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.compare.pass.cpp index ea356782678..a2af094128d 100644 --- a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.compare.pass.cpp +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.compare.pass.cpp @@ -26,6 +26,7 @@ // // size_t hash_value(path const&) noexcept; + #include "filesystem_include.hpp" #include <type_traits> #include <vector> @@ -35,7 +36,7 @@ #include "test_iterators.h" #include "count_new.hpp" #include "filesystem_test_helper.hpp" - +#include "verbose_assert.h" struct PathCompareTest { const char* LHS; @@ -57,8 +58,9 @@ const PathCompareTest CompareTestCases[] = {"a/b/c", "b/a/c", -1}, {"a/b", "a/b/c", -1}, {"a/b/c", "a/b", 1}, - {"a/b/", "a/b/.", 0}, - {"a/b//////", "a/b/////.", 0}, + {"a/b/", "a/b/.", -1}, + {"a/b/", "a/b", 1}, + {"a/b//////", "a/b/////.", -1}, {"a/.././b", "a///..//.////b", 0}, {"//foo//bar///baz////", "//foo/bar/baz/", 0}, // duplicate separators {"///foo/bar", "/foo/bar", 0}, // "///" is not a root directory @@ -94,8 +96,13 @@ int main() int ret2 = normalize_ret(p1.compare(R)); int ret3 = normalize_ret(p1.compare(TC.RHS)); int ret4 = normalize_ret(p1.compare(RV)); - assert(ret1 == ret2 && ret1 == ret3 && ret1 == ret4); - assert(ret1 == E); + + g.release(); + ASSERT_EQ(ret1, ret2); + ASSERT_EQ(ret1, ret3); + ASSERT_EQ(ret1, ret4); + ASSERT_EQ(ret1, E) + << DISPLAY(TC.LHS) << DISPLAY(TC.RHS); // check signatures ASSERT_NOEXCEPT(p1.compare(p2)); diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.decompose/empty.fail.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.decompose/empty.fail.cpp index 377b94e52c7..ecc4c0c30a0 100644 --- a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.decompose/empty.fail.cpp +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.decompose/empty.fail.cpp @@ -18,6 +18,7 @@ // UNSUPPORTED: clang-3.3, clang-3.4, clang-3.5, clang-3.6, clang-3.7, clang-3.8 #include "filesystem_include.hpp" + #include "test_macros.h" int main () diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.decompose/path.decompose.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.decompose/path.decompose.pass.cpp index 6dd24b51156..f959e43a304 100644 --- a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.decompose/path.decompose.pass.cpp +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.decompose/path.decompose.pass.cpp @@ -53,6 +53,14 @@ #include "test_iterators.h" #include "count_new.hpp" #include "filesystem_test_helper.hpp" +#include "assert_checkpoint.h" +#include "verbose_assert.h" + +struct ComparePathExact { + bool operator()(std::string const& LHS, std::string const& RHS) const { + return LHS == RHS; + } +}; struct PathDecomposeTestcase { @@ -72,80 +80,89 @@ const PathDecomposeTestcase PathTestCases[] = , {".", {"."}, "", "", "", ".", "", "."} , {"..", {".."}, "", "", "", "..", "", ".."} , {"foo", {"foo"}, "", "", "", "foo", "", "foo"} - , {"/", {"/"}, "/", "", "/", "", "", "/"} + , {"/", {"/"}, "/", "", "/", "", "/", ""} , {"/foo", {"/", "foo"}, "/", "", "/", "foo", "/", "foo"} - , {"foo/", {"foo", "."}, "", "", "", "foo/", "foo", "."} - , {"/foo/", {"/", "foo", "."}, "/", "", "/", "foo/", "/foo", "."} + , {"foo/", {"foo", ""}, "", "", "", "foo/", "foo", ""} + , {"/foo/", {"/", "foo", ""}, "/", "", "/", "foo/", "/foo", ""} , {"foo/bar", {"foo","bar"}, "", "", "", "foo/bar", "foo", "bar"} , {"/foo//bar", {"/","foo","bar"}, "/", "", "/", "foo/bar", "/foo", "bar"} - , {"//net", {"//net"}, "//net", "//net", "", "", "", "//net"} - , {"//net/foo", {"//net", "/", "foo"}, "//net/", "//net", "/", "foo", "//net/", "foo"} - , {"///foo///", {"/", "foo", "."}, "/", "", "/", "foo///", "///foo", "."} + , {"//net", {"/", "net"}, "/", "", "/", "net", "/", "net"} + , {"//net/foo", {"/", "net", "foo"}, "/", "", "/", "net/foo", "/net", "foo"} + , {"///foo///", {"/", "foo", ""}, "/", "", "/", "foo///", "///foo", ""} , {"///foo///bar", {"/", "foo", "bar"}, "/", "", "/", "foo///bar", "///foo", "bar"} , {"/.", {"/", "."}, "/", "", "/", ".", "/", "."} - , {"./", {".", "."}, "", "", "", "./", ".", "."} + , {"./", {".", ""}, "", "", "", "./", ".", ""} , {"/..", {"/", ".."}, "/", "", "/", "..", "/", ".."} - , {"../", {"..", "."}, "", "", "", "../", "..", "."} + , {"../", {"..", ""}, "", "", "", "../", "..", ""} , {"foo/.", {"foo", "."}, "", "", "", "foo/.", "foo", "."} , {"foo/..", {"foo", ".."}, "", "", "", "foo/..", "foo", ".."} - , {"foo/./", {"foo", ".", "."}, "", "", "", "foo/./", "foo/.", "."} + , {"foo/./", {"foo", ".", ""}, "", "", "", "foo/./", "foo/.", ""} , {"foo/./bar", {"foo", ".", "bar"}, "", "", "", "foo/./bar", "foo/.", "bar"} - , {"foo/../", {"foo", "..", "."}, "", "", "", "foo/../", "foo/..", "."} + , {"foo/../", {"foo", "..", ""}, "", "", "", "foo/../", "foo/..", ""} , {"foo/../bar", {"foo", "..", "bar"}, "", "", "", "foo/../bar", "foo/..", "bar"} , {"c:", {"c:"}, "", "", "", "c:", "", "c:"} - , {"c:/", {"c:", "."}, "", "", "", "c:/", "c:", "."} + , {"c:/", {"c:", ""}, "", "", "", "c:/", "c:", ""} , {"c:foo", {"c:foo"}, "", "", "", "c:foo", "", "c:foo"} , {"c:/foo", {"c:", "foo"}, "", "", "", "c:/foo", "c:", "foo"} - , {"c:foo/", {"c:foo", "."}, "", "", "", "c:foo/", "c:foo", "."} - , {"c:/foo/", {"c:", "foo", "."}, "", "", "", "c:/foo/", "c:/foo", "."} + , {"c:foo/", {"c:foo", ""}, "", "", "", "c:foo/", "c:foo", ""} + , {"c:/foo/", {"c:", "foo", ""}, "", "", "", "c:/foo/", "c:/foo", ""} , {"c:/foo/bar", {"c:", "foo", "bar"}, "", "", "", "c:/foo/bar", "c:/foo", "bar"} , {"prn:", {"prn:"}, "", "", "", "prn:", "", "prn:"} , {"c:\\", {"c:\\"}, "", "", "", "c:\\", "", "c:\\"} , {"c:\\foo", {"c:\\foo"}, "", "", "", "c:\\foo", "", "c:\\foo"} , {"c:foo\\", {"c:foo\\"}, "", "", "", "c:foo\\", "", "c:foo\\"} , {"c:\\foo\\", {"c:\\foo\\"}, "", "", "", "c:\\foo\\", "", "c:\\foo\\"} - , {"c:\\foo/", {"c:\\foo", "."}, "", "", "", "c:\\foo/", "c:\\foo", "."} + , {"c:\\foo/", {"c:\\foo", ""}, "", "", "", "c:\\foo/", "c:\\foo", ""} , {"c:/foo\\bar", {"c:", "foo\\bar"}, "", "", "", "c:/foo\\bar", "c:", "foo\\bar"} - , {"//", {"//"}, "//", "//", "", "", "", "//"} + , {"//", {"/"}, "/", "", "/", "", "/", ""} }; void decompPathTest() { using namespace fs; for (auto const & TC : PathTestCases) { - path p(TC.raw); - assert(p == TC.raw); + CHECKPOINT(TC.raw.c_str()); + fs::path p(TC.raw); + ASSERT(p == TC.raw); - assert(p.root_path() == TC.root_path); - assert(p.has_root_path() != TC.root_path.empty()); + ASSERT_EQ(p.root_path(), TC.root_path); + ASSERT_NEQ(p.has_root_path(), TC.root_path.empty()); - assert(p.root_name() == TC.root_name); - assert(p.has_root_name() != TC.root_name.empty()); + ASSERT(p.root_name().native().empty()) + << DISPLAY(p.root_name()); + ASSERT_EQ(p.root_name(),TC.root_name); + ASSERT_NEQ(p.has_root_name(), TC.root_name.empty()); - assert(p.root_directory() == TC.root_directory); - assert(p.has_root_directory() != TC.root_directory.empty()); + ASSERT_EQ(p.root_directory(), TC.root_directory); + ASSERT_NEQ(p.has_root_directory(), TC.root_directory.empty()); - assert(p.relative_path() == TC.relative_path); - assert(p.has_relative_path() != TC.relative_path.empty()); + ASSERT_EQ(p.relative_path(), TC.relative_path); + ASSERT_NEQ(p.has_relative_path(), TC.relative_path.empty()); - assert(p.parent_path() == TC.parent_path); - assert(p.has_parent_path() != TC.parent_path.empty()); + ASSERT_EQ(p.parent_path(), TC.parent_path); + ASSERT_NEQ(p.has_parent_path(), TC.parent_path.empty()); - assert(p.filename() == TC.filename); - assert(p.has_filename() != TC.filename.empty()); + ASSERT_EQ(p.filename(), TC.filename); + ASSERT_NEQ(p.has_filename(), TC.filename.empty()); - assert(p.is_absolute() == p.has_root_directory()); - assert(p.is_relative() != p.is_absolute()); + ASSERT_EQ(p.is_absolute(), p.has_root_directory()); + ASSERT_NEQ(p.is_relative(), p.is_absolute()); + if (p.empty()) + ASSERT(p.is_relative()); - assert(checkCollectionsEqual(p.begin(), p.end(), - TC.elements.begin(), TC.elements.end())); + ASSERT_COLLECTION_EQ_COMP( + p.begin(), p.end(), + TC.elements.begin(), TC.elements.end(), + ComparePathExact() + ); // check backwards std::vector<fs::path> Parts; for (auto it = p.end(); it != p.begin(); ) Parts.push_back(*--it); - assert(checkCollectionsEqual(Parts.begin(), Parts.end(), - TC.elements.rbegin(), TC.elements.rend())); + ASSERT_COLLECTION_EQ_COMP(Parts.begin(), Parts.end(), + TC.elements.rbegin(), TC.elements.rend(), + ComparePathExact()); } } @@ -163,10 +180,12 @@ const FilenameDecompTestcase FilenameTestCases[] = {"", "", "", ""} , {".", ".", ".", ""} , {"..", "..", "..", ""} - , {"/", "/", "/", ""} + , {"/", "", "", ""} , {"foo", "foo", "foo", ""} , {"/foo/bar.txt", "bar.txt", "bar", ".txt"} , {"foo..txt", "foo..txt", "foo.", ".txt"} + , {".profile", ".profile", ".profile", ""} + , {".profile.txt", ".profile.txt", ".profile", ".txt"} }; @@ -174,18 +193,19 @@ void decompFilenameTest() { using namespace fs; for (auto const & TC : FilenameTestCases) { - path p(TC.raw); - assert(p == TC.raw); + CHECKPOINT(TC.raw.c_str()); + fs::path p(TC.raw); + ASSERT_EQ(p, TC.raw); ASSERT_NOEXCEPT(p.empty()); - assert(p.filename() == TC.filename); - assert(p.has_filename() != TC.filename.empty()); + ASSERT_EQ(p.filename(), TC.filename); + ASSERT_NEQ(p.has_filename(), TC.filename.empty()); - assert(p.stem() == TC.stem); - assert(p.has_stem() != TC.stem.empty()); + ASSERT_EQ(p.stem(), TC.stem); + ASSERT_NEQ(p.has_stem(), TC.stem.empty()); - assert(p.extension() == TC.extension); - assert(p.has_extension() != TC.extension.empty()); + ASSERT_EQ(p.extension(), TC.extension); + ASSERT_NEQ(p.has_extension(), TC.extension.empty()); } } diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.gen/lexically_normal.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.gen/lexically_normal.pass.cpp new file mode 100644 index 00000000000..c897ab60f73 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.gen/lexically_normal.pass.cpp @@ -0,0 +1,142 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// class path + +// path lexically_normal() const; + +#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[] = { + {"", ""}, + {"/a/b/c", "/a/b/c"}, + {"/a/b//c", "/a/b/c"}, + {"foo/./bar/..", "foo/"}, + {"foo/.///bar/../", "foo/"}, + {"/a/b/", "/a/b/"}, + {"a/b", "a/b"}, + {"a/b/.", "a/b/"}, + {"a/b/./", "a/b/"}, + {"a/..", "."}, + {".", "."}, + {"./", "."}, + {"./.", "."}, + {"./..", ".."}, + {"..", ".."}, + {"../..", "../.."}, + {"/../", "/"}, + {"/../..", "/"}, + {"/../../", "/"}, + {"..", ".."}, + {"../", ".."}, + {"/a/b/c/../", "/a/b/"}, + {"/a/b/./", "/a/b/"}, + {"/a/b/c/../d", "/a/b/d"}, + {"/a/b/c/../d/", "/a/b/d/"}, + {"//a/", "/a/"}, + {"//a/b/", "/a/b/"}, + {"//a/b/.", "/a/b/"}, + {"//a/..", "/"}, + ///===---------------------------------------------------------------===// + /// Tests specifically for the clauses under [fs.path.generic]p6 + ///===---------------------------------------------------------------===// + // p1: If the path is empty, stop. + {"", ""}, + // p2: Replace each slash character in the root-name with a preferred + // separator. + {"NO_ROOT_NAME_ON_LINUX", "NO_ROOT_NAME_ON_LINUX"}, + // p3: Replace each directory-separator with a preferred-separator. + // [ Note: The generic pathname grammar ([fs.path.generic]) defines + // directory-separator as one or more slashes and preferred-separators. + // — end note ] + {"/", "/"}, + {"//", "/"}, + {"///", "/"}, + {"a/b", "a/b"}, + {"a//b", "a/b"}, + {"a///b", "a/b"}, + {"a/b/", "a/b/"}, + {"a/b//", "a/b/"}, + {"a/b///", "a/b/"}, + {"///a////b//////", "/a/b/"}, + // p4: Remove each dot filename and any immediately following directory + // separators + {"foo/.", "foo/"}, + {"foo/./bar/.", "foo/bar/"}, + {"./foo/././bar/./", "foo/bar/"}, + {".///foo//.////./bar/.///", "foo/bar/"}, + // p5: As long as any appear, remove a non-dot-dot filename immediately + // followed by a directory-separator and a dot-dot filename, along with + // any immediately following directory separator. + {"foo/..", "."}, + {"foo/../", "."}, + {"foo/bar/..", "foo/"}, + {"foo/bar/../", "foo/"}, + {"foo/bar/../..", "."}, + {"foo/bar/../../", "."}, + {"foo/bar/baz/../..", "foo/"}, + {"foo/bar/baz/../../", "foo/"}, + {"foo/bar/./..", "foo/"}, + {"foo/bar/./../", "foo/"}, + // p6: If there is a root-directory, remove all dot-dot filenames and any + // directory-separators immediately following them. [ Note: These dot-dot + // filenames attempt to refer to nonexistent parent directories. — end note ] + {"/..", "/"}, + {"/../", "/"}, + {"/foo/../..", "/"}, + {"/../foo", "/foo"}, + {"/../foo/../..", "/"}, + // p7: If the last filename is dot-dot, remove any trailing + // directory-separator. + {"../", ".."}, + {"../../", "../.."}, + {"foo/../bar/../..///", ".."}, + {"foo/../bar/..//..///../", "../.."}, + // p8: If the path is empty, add a dot + {".", "."}, + {"./", "."}, + {"foo/..", "."} + }; + // clang-format on + int ID = 0; + bool Failed = false; + for (auto& TC : TestCases) { + ++ID; + fs::path p(TC.input); + const fs::path output = p.lexically_normal(); + 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; +} diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.gen/lexically_relative_and_proximate.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.gen/lexically_relative_and_proximate.pass.cpp new file mode 100644 index 00000000000..8b56a19b716 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.gen/lexically_relative_and_proximate.pass.cpp @@ -0,0 +1,89 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// class path + +// path lexically_relative(const path& p) const; +// path lexically_proximate(const path& p) const; + +#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 base; + std::string expect; + } TestCases[] = { + {"", "", "."}, + {"/", "a", ""}, + {"a", "/", ""}, + {"//net", "a", ""}, + {"a", "//net", ""}, + {"//net/", "//net", ""}, + {"//net", "//net/", ".."}, + {"//base", "a", ""}, + {"a", "a", "."}, + {"a/b", "a/b", "."}, + {"a/b/c/", "a/b/c/", "."}, + {"//net", "//net", "."}, + {"//net/", "//net/", "."}, + {"//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; + bool Failed = false; + for (auto& TC : TestCases) { + ++ID; + const fs::path p(TC.input); + const fs::path output = p.lexically_relative(TC.base); + auto ReportErr = [&](const char* Testing, fs::path const& Output, + fs::path const& Expected) { + Failed = true; + std::cerr << "TEST CASE #" << ID << " FAILED: \n"; + std::cerr << " Testing: " << Testing << "\n"; + std::cerr << " Input: '" << TC.input << "'\n"; + std::cerr << " Base: '" << TC.base << "'\n"; + std::cerr << " Expected: '" << Expected << "'\n"; + std::cerr << " Output: '" << Output.native() << "'"; + std::cerr << std::endl; + }; + if (!PathEq(output, TC.expect)) + ReportErr("path::lexically_relative", output, TC.expect); + const fs::path proximate_output = p.lexically_proximate(TC.base); + // [path.gen] lexically_proximate + // Returns: If the value of lexically_relative(base) is not an empty path, + // return it.Otherwise return *this. + const fs::path proximate_expected = output.native().empty() ? p + : output; + if (!PathEq(proximate_expected, proximate_output)) + ReportErr("path::lexically_proximate", proximate_output, proximate_expected); + } + return Failed; +} diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.generic.obs/generic_string_alloc.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.generic.obs/generic_string_alloc.pass.cpp index 7e329376c93..a757cbb88fd 100644 --- a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.generic.obs/generic_string_alloc.pass.cpp +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.generic.obs/generic_string_alloc.pass.cpp @@ -28,7 +28,6 @@ #include "min_allocator.h" #include "filesystem_test_helper.hpp" - MultiStringType longString = MKSTR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/123456789/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.generic.obs/named_overloads.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.generic.obs/named_overloads.pass.cpp index d3df09ed97e..56b2787fbb6 100644 --- a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.generic.obs/named_overloads.pass.cpp +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.generic.obs/named_overloads.pass.cpp @@ -30,7 +30,6 @@ #include "min_allocator.h" #include "filesystem_test_helper.hpp" - MultiStringType longString = MKSTR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/123456789/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); int main() diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.modifiers/remove_filename.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.modifiers/remove_filename.pass.cpp index 84cdd521429..ec885f15c8c 100644 --- a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.modifiers/remove_filename.pass.cpp +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.modifiers/remove_filename.pass.cpp @@ -23,7 +23,7 @@ #include "test_iterators.h" #include "count_new.hpp" #include "filesystem_test_helper.hpp" - +#include "verbose_assert.h" struct RemoveFilenameTestcase { const char* value; @@ -33,27 +33,29 @@ struct RemoveFilenameTestcase { const RemoveFilenameTestcase TestCases[] = { {"", ""} - , {"/", ""} - , {"//", ""} - , {"///", ""} + , {"/", "/"} + , {"//", "//"} + , {"///", "///"} , {"\\", ""} , {".", ""} , {"..", ""} , {"/foo", "/"} - , {"//foo", ""} - , {"//foo/", ""} - , {"//foo///", ""} - , {"///foo", "/"} - , {"///foo/", "///foo"} - , {"/foo/", "/foo"} - , {"/foo/.", "/foo"} - , {"/foo/..", "/foo"} - , {"/foo/////", "/foo"} + , {"foo/bar", "foo/"} + , {"foo/", "foo/"} + , {"//foo", "//"} + , {"//foo/", "//foo/"} + , {"//foo///", "//foo///"} + , {"///foo", "///"} + , {"///foo/", "///foo/"} + , {"/foo/", "/foo/"} + , {"/foo/.", "/foo/"} + , {"/foo/..", "/foo/"} + , {"/foo/////", "/foo/////"} , {"/foo\\\\", "/"} - , {"/foo//\\/", "/foo//\\"} - , {"///foo", "/"} + , {"/foo//\\/", "/foo//\\/"} + , {"///foo", "///"} , {"file.txt", ""} - , {"bar/../baz/./file.txt", "bar/../baz/."} + , {"bar/../baz/./file.txt", "bar/../baz/./"} }; int main() @@ -64,16 +66,8 @@ int main() path p(p_orig); assert(p == TC.value); path& Ref = (p.remove_filename()); - assert(p == TC.expect); + ASSERT_EQ(p, TC.expect) << DISPLAY(p_orig); assert(&Ref == &p); - { - const path parentp = p_orig.parent_path(); - if (parentp == p_orig.root_name()) { - - assert(p.empty()); - } else { - assert(p == parentp); - } - } + assert(!p.has_filename()); } } diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.modifiers/replace_filename.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.modifiers/replace_filename.pass.cpp index fb7741110cc..bfb3b6a19cd 100644 --- a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.modifiers/replace_filename.pass.cpp +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.modifiers/replace_filename.pass.cpp @@ -23,7 +23,8 @@ #include "test_iterators.h" #include "count_new.hpp" #include "filesystem_test_helper.hpp" - +#include "assert_checkpoint.h" +#include "verbose_assert.h" struct ReplaceFilenameTestcase { const char* value; @@ -36,9 +37,9 @@ const ReplaceFilenameTestcase TestCases[] = {"/foo", "/bar", "bar"} , {"/foo", "/", ""} , {"foo", "bar", "bar"} - , {"/", "bar", "bar"} + , {"/", "/bar", "bar"} , {"\\", "bar", "bar"} - , {"///", "bar", "bar"} + , {"///", "///bar", "bar"} , {"\\\\", "bar", "bar"} , {"\\/\\", "\\/bar", "bar"} , {".", "bar", "bar"} @@ -52,9 +53,11 @@ int main() using namespace fs; for (auto const & TC : TestCases) { path p(TC.value); - assert(p == TC.value); + ASSERT_EQ(p, TC.value); path& Ref = (p.replace_filename(TC.filename)); - assert(p == TC.expect); + ASSERT_EQ(p, TC.expect) + << DISPLAY(TC.value) + << DISPLAY(TC.filename); assert(&Ref == &p); // Tests Effects "as-if": remove_filename() append(filename) { @@ -62,7 +65,7 @@ int main() path replace(TC.filename); p2.remove_filename(); p2 /= replace; - assert(p2 == p); + ASSERT_EQ(p, p2); } } } diff --git a/libcxx/test/std/experimental/filesystem/fs.enum/enum.perm_options.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.enum/enum.perm_options.pass.cpp new file mode 100644 index 00000000000..c1066b63ba3 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.enum/enum.perm_options.pass.cpp @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// enum class perm_options; + +#include "filesystem_include.hpp" +#include <type_traits> +#include <cassert> +#include <sys/stat.h> + +#include "test_macros.h" +#include "check_bitmask_types.hpp" + + +constexpr fs::perm_options ME(int val) { + return static_cast<fs::perm_options>(val); +} + +int main() { + typedef fs::perm_options E; + static_assert(std::is_enum<E>::value, ""); + + // Check that E is a scoped enum by checking for conversions. + typedef std::underlying_type<E>::type UT; + static_assert(!std::is_convertible<E, UT>::value, ""); + + static_assert(std::is_same<UT, unsigned char >::value, ""); // Implementation detail + + typedef check_bitmask_type<E, E::replace, E::nofollow> BitmaskTester; + assert(BitmaskTester::check()); + + static_assert( + E::replace == ME(1) && + E::add == ME(2) && + E::remove == ME(4) && + E::nofollow == ME(8), + "Expected enumeration values do not match"); +} 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; +} |