summaryrefslogtreecommitdiffstats
path: root/libcxx/test/std/experimental/filesystem
diff options
context:
space:
mode:
Diffstat (limited to 'libcxx/test/std/experimental/filesystem')
-rw-r--r--libcxx/test/std/experimental/filesystem/class.path/path.itr/iterator.pass.cpp4
-rw-r--r--libcxx/test/std/experimental/filesystem/class.path/path.member/path.append.pass.cpp72
-rw-r--r--libcxx/test/std/experimental/filesystem/class.path/path.member/path.compare.pass.cpp17
-rw-r--r--libcxx/test/std/experimental/filesystem/class.path/path.member/path.decompose/empty.fail.cpp1
-rw-r--r--libcxx/test/std/experimental/filesystem/class.path/path.member/path.decompose/path.decompose.pass.cpp108
-rw-r--r--libcxx/test/std/experimental/filesystem/class.path/path.member/path.gen/lexically_normal.pass.cpp142
-rw-r--r--libcxx/test/std/experimental/filesystem/class.path/path.member/path.gen/lexically_relative_and_proximate.pass.cpp89
-rw-r--r--libcxx/test/std/experimental/filesystem/class.path/path.member/path.generic.obs/generic_string_alloc.pass.cpp1
-rw-r--r--libcxx/test/std/experimental/filesystem/class.path/path.member/path.generic.obs/named_overloads.pass.cpp1
-rw-r--r--libcxx/test/std/experimental/filesystem/class.path/path.member/path.modifiers/remove_filename.pass.cpp46
-rw-r--r--libcxx/test/std/experimental/filesystem/class.path/path.member/path.modifiers/replace_filename.pass.cpp15
-rw-r--r--libcxx/test/std/experimental/filesystem/fs.enum/enum.perm_options.pass.cpp48
-rw-r--r--libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.absolute/absolute.pass.cpp93
-rw-r--r--libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.canonical/canonical.pass.cpp46
-rw-r--r--libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp2
-rw-r--r--libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.proximate/proximate.pass.cpp125
-rw-r--r--libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.relative/relative.pass.cpp78
-rw-r--r--libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.system_complete/system_complete.pass.cpp58
-rw-r--r--libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.weakly_canonical/weakly_canonical.pass.cpp76
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;
+}
OpenPOWER on IntegriCloud