diff options
Diffstat (limited to 'test/std/experimental/filesystem')
29 files changed, 505 insertions, 90 deletions
diff --git a/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/ctor.pass.cpp b/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/ctor.pass.cpp index a6becb1bafaa..830e8123150a 100644 --- a/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/ctor.pass.cpp +++ b/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/ctor.pass.cpp @@ -87,9 +87,10 @@ TEST_CASE(access_denied_test_case) env.create_file(testFile, 42); // Test that we can iterator over the directory before changing the perms - directory_iterator it(testDir); - TEST_REQUIRE(it != directory_iterator{}); - + { + directory_iterator it(testDir); + TEST_REQUIRE(it != directory_iterator{}); + } // Change the permissions so we can no longer iterate permissions(testDir, perms::none); diff --git a/test/std/experimental/filesystem/class.path/path.member/path.append.pass.cpp b/test/std/experimental/filesystem/class.path/path.member/path.append.pass.cpp index 1118497e06a8..f344e1153071 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.append.pass.cpp +++ b/test/std/experimental/filesystem/class.path/path.member/path.append.pass.cpp @@ -24,6 +24,7 @@ #include <experimental/filesystem> #include <type_traits> +#include <string_view> #include <cassert> #include "test_macros.h" @@ -77,6 +78,7 @@ void doAppendSourceAllocTest(AppendOperatorTestcase const& TC) using namespace fs; using Ptr = CharT const*; using Str = std::basic_string<CharT>; + using StrView = std::basic_string_view<CharT>; using InputIter = input_iterator<Ptr>; const Ptr L = TC.lhs; @@ -99,6 +101,16 @@ void doAppendSourceAllocTest(AppendOperatorTestcase const& TC) } assert(LHS == E); } + // basic_string_view + { + path LHS(L); PathReserve(LHS, ReserveSize); + StrView RHS(R); + { + DisableAllocationGuard g; + LHS /= RHS; + } + assert(LHS == E); + } // CharT* { path LHS(L); PathReserve(LHS, ReserveSize); @@ -153,6 +165,7 @@ void doAppendSourceTest(AppendOperatorTestcase const& TC) using namespace fs; using Ptr = CharT const*; using Str = std::basic_string<CharT>; + using StrView = std::basic_string_view<CharT>; using InputIter = input_iterator<Ptr>; const Ptr L = TC.lhs; const Ptr R = TC.rhs; @@ -172,6 +185,21 @@ void doAppendSourceTest(AppendOperatorTestcase const& TC) assert(LHS == E); assert(&Ref == &LHS); } + // basic_string_view + { + path LHS(L); + StrView RHS(R); + path& Ref = (LHS /= RHS); + assert(LHS == E); + assert(&Ref == &LHS); + } + { + path LHS(L); + StrView RHS(R); + path& Ref = LHS.append(RHS); + assert(LHS == E); + assert(&Ref == &LHS); + } // Char* { path LHS(L); @@ -218,6 +246,60 @@ void doAppendSourceTest(AppendOperatorTestcase const& TC) } } + + +template <class It, class = decltype(fs::path{}.append(std::declval<It>()))> +constexpr bool has_append(int) { return true; } +template <class It> +constexpr bool has_append(long) { return false; } + +template <class It, class = decltype(fs::path{}.operator/=(std::declval<It>()))> +constexpr bool has_append_op(int) { return true; } +template <class It> +constexpr bool has_append_op(long) { return false; } + +template <class It> +constexpr bool has_append() { + static_assert(has_append<It>(0) == has_append_op<It>(0), "must be same"); + return has_append<It>(0) && has_append_op<It>(0); +} + +void test_sfinae() +{ + using namespace fs; + { + using It = const char* const; + static_assert(has_append<It>(), ""); + } + { + using It = input_iterator<const char*>; + static_assert(has_append<It>(), ""); + } + { + struct Traits { + using iterator_category = std::input_iterator_tag; + using value_type = const char; + using pointer = const char*; + using reference = const char&; + using difference_type = std::ptrdiff_t; + }; + using It = input_iterator<const char*, Traits>; + static_assert(has_append<It>(), ""); + } + { + using It = output_iterator<const char*>; + static_assert(!has_append<It>(), ""); + + } + { + static_assert(!has_append<int*>(), ""); + } + { + static_assert(!has_append<char>(), ""); + static_assert(!has_append<const char>(), ""); + } +} + int main() { using namespace fs; @@ -238,4 +320,5 @@ int main() doAppendSourceAllocTest<char>(TC); doAppendSourceAllocTest<wchar_t>(TC); } + test_sfinae(); } diff --git a/test/std/experimental/filesystem/class.path/path.member/path.assign/source.pass.cpp b/test/std/experimental/filesystem/class.path/path.member/path.assign/source.pass.cpp index 4c2d5112d10b..9e48cbf1e7f2 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.assign/source.pass.cpp +++ b/test/std/experimental/filesystem/class.path/path.member/path.assign/source.pass.cpp @@ -23,6 +23,7 @@ #include <experimental/filesystem> #include <type_traits> +#include <string_view> #include <cassert> #include "test_macros.h" @@ -69,6 +70,32 @@ void RunTestCase(MultiStringType const& MS) { assert(p.string<CharT>() == TestPath); assert(p.string<CharT>() == S); } + // basic_string<Char, Traits, Alloc> + { + const std::basic_string_view<CharT> S(TestPath); + path p; PathReserve(p, S.length() + 1); + { + // string provides a contigious iterator. No allocation needed. + DisableAllocationGuard g; + path& pref = (p = S); + assert(&pref == &p); + } + assert(p.native() == Expect); + assert(p.string<CharT>() == TestPath); + assert(p.string<CharT>() == S); + } + { + const std::basic_string_view<CharT> S(TestPath); + path p; PathReserve(p, S.length() + 1); + { + DisableAllocationGuard g; + path& pref = p.assign(S); + assert(&pref == &p); + } + assert(p.native() == Expect); + assert(p.string<CharT>() == TestPath); + assert(p.string<CharT>() == S); + } ////////////////////////////////////////////////////////////////////////////// // Char* pointers { @@ -143,6 +170,49 @@ void RunTestCase(MultiStringType const& MS) { } } +template <class It, class = decltype(fs::path{}.assign(std::declval<It>()))> +constexpr bool has_assign(int) { return true; } +template <class It> +constexpr bool has_assign(long) { return false; } +template <class It> +constexpr bool has_assign() { return has_assign<It>(0); } + +void test_sfinae() { + using namespace fs; + { + using It = const char* const; + static_assert(std::is_assignable<path, It>::value, ""); + static_assert(has_assign<It>(), ""); + } + { + using It = input_iterator<const char*>; + static_assert(std::is_assignable<path, It>::value, ""); + static_assert(has_assign<It>(), ""); + } + { + struct Traits { + using iterator_category = std::input_iterator_tag; + using value_type = const char; + using pointer = const char*; + using reference = const char&; + using difference_type = std::ptrdiff_t; + }; + using It = input_iterator<const char*, Traits>; + static_assert(std::is_assignable<path, It>::value, ""); + static_assert(has_assign<It>(), ""); + } + { + using It = output_iterator<const char*>; + static_assert(!std::is_assignable<path, It>::value, ""); + static_assert(!has_assign<It>(), ""); + + } + { + static_assert(!std::is_assignable<path, int*>::value, ""); + static_assert(!has_assign<int*>(), ""); + } +} + int main() { for (auto const& MS : PathList) { RunTestCase<char>(MS); @@ -150,4 +220,5 @@ int main() { RunTestCase<char16_t>(MS); RunTestCase<char32_t>(MS); } + test_sfinae(); } diff --git a/test/std/experimental/filesystem/class.path/path.member/path.compare.pass.cpp b/test/std/experimental/filesystem/class.path/path.member/path.compare.pass.cpp index 557c1b24d88f..69d08e6eb49a 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.compare.pass.cpp +++ b/test/std/experimental/filesystem/class.path/path.member/path.compare.pass.cpp @@ -73,6 +73,11 @@ const PathCompareTest CompareTestCases[] = #undef LONGC #undef LONGD +static inline int normalize_ret(int ret) +{ + return ret < 0 ? -1 : (ret > 0 ? 1 : 0); +} + int main() { using namespace fs; @@ -80,17 +85,18 @@ int main() const path p1(TC.LHS); const path p2(TC.RHS); const std::string R(TC.RHS); + const std::string_view RV(TC.RHS); const int E = TC.expect; { // compare(...) functions DisableAllocationGuard g; // none of these operations should allocate // check runtime results - int ret1 = p1.compare(p2); - int ret2 = p1.compare(R); - int ret3 = p1.compare(TC.RHS); - assert(ret1 == ret2 && ret1 == ret3); - int normalized_ret = ret1 < 0 ? -1 : (ret1 > 0 ? 1 : 0); - assert(normalized_ret == E); + int ret1 = normalize_ret(p1.compare(p2)); + 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); // check signatures ASSERT_NOEXCEPT(p1.compare(p2)); diff --git a/test/std/experimental/filesystem/class.path/path.member/path.concat.pass.cpp b/test/std/experimental/filesystem/class.path/path.member/path.concat.pass.cpp index 6e00afe0b49c..89269362d06f 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.concat.pass.cpp +++ b/test/std/experimental/filesystem/class.path/path.member/path.concat.pass.cpp @@ -14,8 +14,9 @@ // class path // path& operator+=(const path& x); -// path& operator+=(const string_type& x); // Implemented as Source template -// path& operator+=(const value_type* x); // Implemented as Source template +// path& operator+=(const string_type& x); +// path& operator+=(string_view x); +// path& operator+=(const value_type* x); // path& operator+=(value_type x); // template <class Source> // path& operator+=(const Source& x); @@ -29,6 +30,8 @@ #include <experimental/filesystem> #include <type_traits> +#include <string> +#include <string_view> #include <cassert> #include "test_macros.h" @@ -82,6 +85,7 @@ void doConcatSourceAllocTest(ConcatOperatorTestcase const& TC) using namespace fs; using Ptr = CharT const*; using Str = std::basic_string<CharT>; + using StrView = std::basic_string_view<CharT>; using InputIter = input_iterator<Ptr>; const Ptr L = TC.lhs; @@ -98,6 +102,16 @@ void doConcatSourceAllocTest(ConcatOperatorTestcase const& TC) } assert(LHS == E); } + // basic_string_view + { + path LHS(L); PathReserve(LHS, ReserveSize); + StrView RHS(R); + { + DisableAllocationGuard g; + LHS += RHS; + } + assert(LHS == E); + } // CharT* { path LHS(L); PathReserve(LHS, ReserveSize); @@ -152,6 +166,7 @@ void doConcatSourceTest(ConcatOperatorTestcase const& TC) using namespace fs; using Ptr = CharT const*; using Str = std::basic_string<CharT>; + using StrView = std::basic_string_view<CharT>; using InputIter = input_iterator<Ptr>; const Ptr L = TC.lhs; const Ptr R = TC.rhs; @@ -171,6 +186,21 @@ void doConcatSourceTest(ConcatOperatorTestcase const& TC) assert(LHS == E); assert(&Ref == &LHS); } + // basic_string_view + { + path LHS(L); + StrView RHS(R); + path& Ref = (LHS += RHS); + assert(LHS == E); + assert(&Ref == &LHS); + } + { + path LHS(L); + StrView RHS(R); + path& Ref = LHS.concat(RHS); + assert(LHS == E); + assert(&Ref == &LHS); + } // Char* { path LHS(L); @@ -235,6 +265,68 @@ void doConcatECharTest(ConcatOperatorTestcase const& TC) } } + +template <class It, class = decltype(fs::path{}.concat(std::declval<It>()))> +constexpr bool has_concat(int) { return true; } +template <class It> +constexpr bool has_concat(long) { return false; } + +template <class It, class = decltype(fs::path{}.operator+=(std::declval<It>()))> +constexpr bool has_concat_op(int) { return true; } +template <class It> +constexpr bool has_concat_op(long) { return false; } +template <class It> +constexpr bool has_concat_op() { return has_concat_op<It>(0); } + +template <class It> +constexpr bool has_concat() { + static_assert(has_concat<It>(0) == has_concat_op<It>(0), "must be same"); + return has_concat<It>(0) && has_concat_op<It>(0); +} + +void test_sfinae() { + using namespace fs; + { + static_assert(has_concat_op<char>(), ""); + static_assert(has_concat_op<const char>(), ""); + static_assert(has_concat_op<char16_t>(), ""); + static_assert(has_concat_op<const char16_t>(), ""); + } + { + using It = const char* const; + static_assert(has_concat<It>(), ""); + } + { + using It = input_iterator<const char*>; + static_assert(has_concat<It>(), ""); + } + { + struct Traits { + using iterator_category = std::input_iterator_tag; + using value_type = const char; + using pointer = const char*; + using reference = const char&; + using difference_type = std::ptrdiff_t; + }; + using It = input_iterator<const char*, Traits>; + static_assert(has_concat<It>(), ""); + } + { + using It = output_iterator<const char*>; + static_assert(!has_concat<It>(), ""); + } + { + static_assert(!has_concat<int>(0), ""); + // operator+=(int) is well formed since it converts to operator+=(value_type) + // but concat(int) isn't valid because there is no concat(value_type). + // This should probably be addressed by a LWG issue. + static_assert(has_concat_op<int>(), ""); + } + { + static_assert(!has_concat<int*>(), ""); + } +} + int main() { using namespace fs; @@ -246,6 +338,13 @@ int main() assert(LHS == (const char*)TC.expect); assert(&Ref == &LHS); } + { + path LHS((const char*)TC.lhs); + std::string_view RHS((const char*)TC.rhs); + path& Ref = (LHS += RHS); + assert(LHS == (const char*)TC.expect); + assert(&Ref == &LHS); + } doConcatSourceTest<char> (TC); doConcatSourceTest<wchar_t> (TC); doConcatSourceTest<char16_t>(TC); @@ -265,6 +364,18 @@ int main() } assert(LHS == E); } + { + path LHS((const char*)TC.lhs); + std::string_view RHS((const char*)TC.rhs); + const char* E = TC.expect; + PathReserve(LHS, StrLen(E) + 5); + { + DisableAllocationGuard g; + path& Ref = (LHS += RHS); + assert(&Ref == &LHS); + } + assert(LHS == E); + } doConcatSourceAllocTest<char>(TC); doConcatSourceAllocTest<wchar_t>(TC); } @@ -274,4 +385,5 @@ int main() doConcatECharTest<char16_t>(TC); doConcatECharTest<char32_t>(TC); } + test_sfinae(); } diff --git a/test/std/experimental/filesystem/class.path/path.member/path.construct/source.pass.cpp b/test/std/experimental/filesystem/class.path/path.member/path.construct/source.pass.cpp index d89e7c815efb..a04f35af5780 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.construct/source.pass.cpp +++ b/test/std/experimental/filesystem/class.path/path.member/path.construct/source.pass.cpp @@ -47,6 +47,13 @@ void RunTestCase(MultiStringType const& MS) { assert(p.string<CharT>() == TestPath); assert(p.string<CharT>() == S); } + { + const std::basic_string_view<CharT> S(TestPath); + path p(S); + assert(p.native() == Expect); + assert(p.string<CharT>() == TestPath); + assert(p.string<CharT>() == S); + } // Char* pointers { path p(TestPath); @@ -73,6 +80,37 @@ void RunTestCase(MultiStringType const& MS) { } } +void test_sfinae() { + using namespace fs; + { + using It = const char* const; + static_assert(std::is_constructible<path, It>::value, ""); + } + { + using It = input_iterator<const char*>; + static_assert(std::is_constructible<path, It>::value, ""); + } + { + struct Traits { + using iterator_category = std::input_iterator_tag; + using value_type = const char; + using pointer = const char*; + using reference = const char&; + using difference_type = std::ptrdiff_t; + }; + using It = input_iterator<const char*, Traits>; + static_assert(std::is_constructible<path, It>::value, ""); + } + { + using It = output_iterator<const char*>; + static_assert(!std::is_constructible<path, It>::value, ""); + + } + { + static_assert(!std::is_constructible<path, int*>::value, ""); + } +} + int main() { for (auto const& MS : PathList) { RunTestCase<char>(MS); @@ -80,4 +118,5 @@ int main() { RunTestCase<char16_t>(MS); RunTestCase<char32_t>(MS); } + test_sfinae(); } diff --git a/test/std/experimental/filesystem/class.path/path.member/path.modifiers/clear.pass.cpp b/test/std/experimental/filesystem/class.path/path.member/path.modifiers/clear.pass.cpp index 5be934968c46..7881c9700d6e 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.modifiers/clear.pass.cpp +++ b/test/std/experimental/filesystem/class.path/path.member/path.modifiers/clear.pass.cpp @@ -28,7 +28,6 @@ namespace fs = std::experimental::filesystem; int main() { using namespace fs; - const path p("/foo/bar/baz"); { path p; ASSERT_NOEXCEPT(p.clear()); @@ -37,6 +36,7 @@ int main() { assert(p.empty()); } { + const path p("/foo/bar/baz"); path p2(p); assert(p == p2); p2.clear(); diff --git a/test/std/experimental/filesystem/class.path/path.member/path.modifiers/remove_filename.pass.cpp b/test/std/experimental/filesystem/class.path/path.member/path.modifiers/remove_filename.pass.cpp index 4ad9084dbf81..e414202bf8ff 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.modifiers/remove_filename.pass.cpp +++ b/test/std/experimental/filesystem/class.path/path.member/path.modifiers/remove_filename.pass.cpp @@ -35,16 +35,24 @@ const RemoveFilenameTestcase TestCases[] = { {"", ""} , {"/", ""} + , {"//", ""} + , {"///", ""} , {"\\", ""} , {".", ""} , {"..", ""} , {"/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/."} }; diff --git a/test/std/experimental/filesystem/class.path/path.member/path.native.obs/c_str.pass.cpp b/test/std/experimental/filesystem/class.path/path.member/path.native.obs/c_str.pass.cpp index 7cf3564bb9b1..796609432727 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.native.obs/c_str.pass.cpp +++ b/test/std/experimental/filesystem/class.path/path.member/path.native.obs/c_str.pass.cpp @@ -30,8 +30,8 @@ int main() using namespace fs; const char* const value = "hello world"; const std::string str_value = value; - path p(value); { // Check signature + path p(value); ASSERT_SAME_TYPE(path::value_type const*, decltype(p.c_str())); ASSERT_NOEXCEPT(p.c_str()); } diff --git a/test/std/experimental/filesystem/class.path/path.member/path.native.obs/native.pass.cpp b/test/std/experimental/filesystem/class.path/path.member/path.native.obs/native.pass.cpp index 7f8df27faf0a..db1326483776 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.native.obs/native.pass.cpp +++ b/test/std/experimental/filesystem/class.path/path.member/path.native.obs/native.pass.cpp @@ -28,8 +28,8 @@ int main() { using namespace fs; const char* const value = "hello world"; - path p(value); { // Check signature + path p(value); ASSERT_SAME_TYPE(path::string_type const&, decltype(p.native())); ASSERT_NOEXCEPT(p.native()); } diff --git a/test/std/experimental/filesystem/class.path/path.member/path.native.obs/operator_string.pass.cpp b/test/std/experimental/filesystem/class.path/path.member/path.native.obs/operator_string.pass.cpp index 9ef83f989aa5..013d26cdb7f6 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.native.obs/operator_string.pass.cpp +++ b/test/std/experimental/filesystem/class.path/path.member/path.native.obs/operator_string.pass.cpp @@ -30,8 +30,8 @@ int main() using namespace fs; using string_type = path::string_type; const char* const value = "hello world"; - path p(value); { // Check signature + path p(value); static_assert(std::is_convertible<path, string_type>::value, ""); static_assert(std::is_constructible<string_type, path>::value, ""); ASSERT_SAME_TYPE(string_type, decltype(p.operator string_type())); diff --git a/test/std/experimental/filesystem/class.path/path.nonmember/path.io.pass.cpp b/test/std/experimental/filesystem/class.path/path.nonmember/path.io.pass.cpp index e8d150f1e39d..4b7ad735c7f8 100644 --- a/test/std/experimental/filesystem/class.path/path.nonmember/path.io.pass.cpp +++ b/test/std/experimental/filesystem/class.path/path.nonmember/path.io.pass.cpp @@ -40,7 +40,6 @@ void doIOTest() { using namespace fs; using Ptr = const CharT*; using StrStream = std::basic_stringstream<CharT>; - const char* const InCStr = InStr; const Ptr E = OutStr; const path p((const char*)InStr); StrStream ss; diff --git a/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/ctor.pass.cpp b/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/ctor.pass.cpp index 1cddccd0d724..8f6009d399c1 100644 --- a/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/ctor.pass.cpp +++ b/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/ctor.pass.cpp @@ -91,8 +91,10 @@ TEST_CASE(access_denied_test_case) env.create_file(testFile, 42); // Test that we can iterator over the directory before changing the perms - RDI it(testDir); - TEST_REQUIRE(it != RDI{}); + { + RDI it(testDir); + TEST_REQUIRE(it != RDI{}); + } // Change the permissions so we can no longer iterate permissions(testDir, perms::none); diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy/copy.pass.cpp b/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy/copy.pass.cpp index 7d318719f740..c9b42b3596ad 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy/copy.pass.cpp +++ b/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy/copy.pass.cpp @@ -19,6 +19,7 @@ #include <experimental/filesystem> #include <type_traits> +#include <cstddef> #include <cassert> #include "test_macros.h" @@ -59,6 +60,7 @@ TEST_CASE(test_error_reporting) && err.code() == ec; } #else + ((void)f); ((void)t); ((void)ec); return true; #endif }; @@ -69,37 +71,44 @@ TEST_CASE(test_error_reporting) const path fifo = env.create_fifo("fifo"); TEST_REQUIRE(is_other(fifo)); + const auto test_ec = GetTestEC(); + // !exists(f) { - std::error_code ec; + std::error_code ec = test_ec; const path f = StaticEnv::DNE; const path t = env.test_root; fs::copy(f, t, ec); TEST_REQUIRE(ec); + TEST_REQUIRE(ec != test_ec); TEST_CHECK(checkThrow(f, t, ec)); } { // equivalent(f, t) == true - std::error_code ec; + std::error_code ec = test_ec; fs::copy(file, file, ec); TEST_REQUIRE(ec); + TEST_REQUIRE(ec != test_ec); TEST_CHECK(checkThrow(file, file, ec)); } { // is_directory(from) && is_file(to) - std::error_code ec; + std::error_code ec = test_ec; fs::copy(dir, file, ec); TEST_REQUIRE(ec); + TEST_REQUIRE(ec != test_ec); TEST_CHECK(checkThrow(dir, file, ec)); } { // is_other(from) - std::error_code ec; + std::error_code ec = test_ec; fs::copy(fifo, dir, ec); TEST_REQUIRE(ec); + TEST_REQUIRE(ec != test_ec); TEST_CHECK(checkThrow(fifo, dir, ec)); } { // is_other(to) - std::error_code ec; + std::error_code ec = test_ec; fs::copy(file, fifo, ec); TEST_REQUIRE(ec); + TEST_REQUIRE(ec != test_ec); TEST_CHECK(checkThrow(file, fifo, ec)); } } @@ -129,11 +138,13 @@ TEST_CASE(from_is_symlink) std::error_code ec = GetTestEC(); fs::copy(symlink, file, copy_options::copy_symlinks, ec); TEST_CHECK(ec); + TEST_CHECK(ec != GetTestEC()); } { // create symlinks but target exists std::error_code ec = GetTestEC(); fs::copy(symlink, file, copy_options::create_symlinks, ec); TEST_CHECK(ec); + TEST_CHECK(ec != GetTestEC()); } } @@ -187,7 +198,7 @@ TEST_CASE(from_is_directory) { struct FileInfo { path filename; - int size; + std::size_t size; }; const FileInfo files[] = { {"file1", 0}, @@ -246,6 +257,60 @@ TEST_CASE(from_is_directory) TEST_CHECK(file_size(nested_created) == FI.size); } } +} +TEST_CASE(test_copy_symlinks_to_symlink_dir) +{ + scoped_test_env env; + const path file1 = env.create_file("file1", 42); + const path file2 = env.create_file("file2", 101); + const path file2_sym = env.create_symlink(file2, "file2_sym"); + const path dir = env.create_dir("dir"); + const path dir_sym = env.create_symlink(dir, "dir_sym"); + { + std::error_code ec = GetTestEC(); + fs::copy(file1, dir_sym, copy_options::copy_symlinks, ec); + TEST_CHECK(!ec); + const path dest = env.make_env_path("dir/file1"); + TEST_CHECK(exists(dest)); + TEST_CHECK(!is_symlink(dest)); + TEST_CHECK(file_size(dest) == 42); + } } + + +TEST_CASE(test_dir_create_symlink) +{ + scoped_test_env env; + const path dir = env.create_dir("dir1"); + const path dest = env.make_env_path("dne"); + { + std::error_code ec = GetTestEC(); + fs::copy(dir, dest, copy_options::create_symlinks, ec); + TEST_CHECK(ec == std::make_error_code(std::errc::is_a_directory)); + TEST_CHECK(!exists(dest)); + TEST_CHECK(!is_symlink(dest)); + } + { + std::error_code ec = GetTestEC(); + fs::copy(dir, dest, copy_options::create_symlinks|copy_options::recursive, ec); + TEST_CHECK(ec == std::make_error_code(std::errc::is_a_directory)); + TEST_CHECK(!exists(dest)); + TEST_CHECK(!is_symlink(dest)); + } +} + +TEST_CASE(test_otherwise_no_effects_clause) +{ + scoped_test_env env; + const path dir = env.create_dir("dir1"); + { // skip copy because of directory + const path dest = env.make_env_path("dest1"); + std::error_code ec; + fs::copy(dir, dest, CO::directories_only, ec); + TEST_CHECK(!ec); + TEST_CHECK(!exists(dest)); + } +} + TEST_SUITE_END() diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_file/copy_file.pass.cpp b/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_file/copy_file.pass.cpp index ac9877bbd9ce..8c5241c71af8 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_file/copy_file.pass.cpp +++ b/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_file/copy_file.pass.cpp @@ -62,6 +62,7 @@ TEST_CASE(test_error_reporting) && err.code() == ec; } #else + ((void)f); ((void)t); ((void)ec); return true; #endif }; @@ -138,7 +139,6 @@ TEST_CASE(test_attributes_get_copied) const path file = env.create_file("file1", 42); const path dest = env.make_env_path("file2"); auto st = status(file); - perms default_perms = st.permissions(); perms new_perms = perms::owner_read; permissions(file, new_perms); std::error_code ec; @@ -153,12 +153,36 @@ TEST_CASE(copy_dir_test) scoped_test_env env; const path file = env.create_file("file1", 42); const path dest = env.create_dir("dir1"); - std::error_code ec; + std::error_code ec = GetTestEC(); TEST_CHECK(fs::copy_file(file, dest, ec) == false); TEST_CHECK(ec); - ec.clear(); + TEST_CHECK(ec != GetTestEC()); + ec = GetTestEC(); TEST_CHECK(fs::copy_file(dest, file, ec) == false); TEST_CHECK(ec); + TEST_CHECK(ec != GetTestEC()); +} + +TEST_CASE(non_regular_file_test) +{ + scoped_test_env env; + const path fifo = env.create_fifo("fifo"); + const path dest = env.make_env_path("dest"); + const path file = env.create_file("file", 42); + { + std::error_code ec = GetTestEC(); + TEST_REQUIRE(fs::copy_file(fifo, dest, ec) == false); + TEST_CHECK(ec); + TEST_CHECK(ec != GetTestEC()); + TEST_CHECK(!exists(dest)); + } + { + std::error_code ec = GetTestEC(); + TEST_REQUIRE(fs::copy_file(file, fifo, copy_options::overwrite_existing, ec) == false); + TEST_CHECK(ec); + TEST_CHECK(ec != GetTestEC()); + TEST_CHECK(is_fifo(fifo)); + } } TEST_SUITE_END() diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_symlink/copy_symlink.pass.cpp b/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_symlink/copy_symlink.pass.cpp index 6fae11195206..fe4729806772 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_symlink/copy_symlink.pass.cpp +++ b/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_symlink/copy_symlink.pass.cpp @@ -50,6 +50,7 @@ TEST_CASE(test_error_reporting) && err.code() == ec; } #else + ((void)f); ((void)t); ((void)ec); return true; #endif }; diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directory_symlink/create_directory_symlink.pass.cpp b/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directory_symlink/create_directory_symlink.pass.cpp index e0473754cc88..85a3b6cb3465 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directory_symlink/create_directory_symlink.pass.cpp +++ b/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directory_symlink/create_directory_symlink.pass.cpp @@ -37,21 +37,6 @@ TEST_CASE(test_signatures) TEST_CASE(test_error_reporting) { - auto checkThrow = [](path const& f, path const& t, const std::error_code& ec) - { -#ifndef TEST_HAS_NO_EXCEPTIONS - try { - fs::create_directory_symlink(f, t); - return true; - } catch (filesystem_error const& err) { - return err.path1() == f - && err.code() == ec; - } -#else - return true; -#endif - }; - scoped_test_env env; const path file = env.create_file("file1", 42); const path file2 = env.create_file("file2", 55); diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_hard_link/create_hard_link.pass.cpp b/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_hard_link/create_hard_link.pass.cpp index 4a865fdee7e8..7aefece46a4a 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_hard_link/create_hard_link.pass.cpp +++ b/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_hard_link/create_hard_link.pass.cpp @@ -36,21 +36,6 @@ TEST_CASE(test_signatures) TEST_CASE(test_error_reporting) { - auto checkThrow = [](path const& f, path const& t, const std::error_code& ec) - { -#ifndef TEST_HAS_NO_EXCEPTIONS - try { - fs::create_hard_link(f, t); - return true; - } catch (filesystem_error const& err) { - return err.path1() == f - && err.code() == ec; - } -#else - return true; -#endif - }; - scoped_test_env env; const path file = env.create_file("file1", 42); const path file2 = env.create_file("file2", 55); diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_symlink/create_symlink.pass.cpp b/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_symlink/create_symlink.pass.cpp index 35ba57f3ab46..d261d987a1ee 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_symlink/create_symlink.pass.cpp +++ b/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_symlink/create_symlink.pass.cpp @@ -37,21 +37,6 @@ TEST_CASE(test_signatures) TEST_CASE(test_error_reporting) { - auto checkThrow = [](path const& f, path const& t, const std::error_code& ec) - { -#ifndef TEST_HAS_NO_EXCEPTIONS - try { - fs::create_symlink(f, t); - return true; - } catch (filesystem_error const& err) { - return err.path1() == f - && err.code() == ec; - } -#else - return true; -#endif - }; - scoped_test_env env; const path file = env.create_file("file1", 42); const path file2 = env.create_file("file2", 55); diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.hard_lk_ct/hard_link_count.pass.cpp b/test/std/experimental/filesystem/fs.op.funcs/fs.op.hard_lk_ct/hard_link_count.pass.cpp index abc50e9c6a41..7537ac20c757 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.hard_lk_ct/hard_link_count.pass.cpp +++ b/test/std/experimental/filesystem/fs.op.funcs/fs.op.hard_lk_ct/hard_link_count.pass.cpp @@ -45,18 +45,27 @@ TEST_CASE(hard_link_count_for_file) TEST_CASE(hard_link_count_for_directory) { - uintmax_t DirExpect = 3; - uintmax_t Dir3Expect = 2; + uintmax_t DirExpect = 3; // hard link from . .. and Dir2 + uintmax_t Dir3Expect = 2; // hard link from . .. + uintmax_t DirExpectAlt = DirExpect; + uintmax_t Dir3ExpectAlt = Dir3Expect; #if defined(__APPLE__) - DirExpect += 2; - Dir3Expect += 1; + // Filesystems formatted with case sensitive hfs+ behave unixish as + // expected. Normal hfs+ filesystems report the number of directory + // entries instead. + DirExpectAlt = 5; // . .. Dir2 file1 file2 + Dir3Expect = 3; // . .. file5 #endif - TEST_CHECK(hard_link_count(StaticEnv::Dir) == DirExpect); - TEST_CHECK(hard_link_count(StaticEnv::Dir3) == Dir3Expect); + TEST_CHECK(hard_link_count(StaticEnv::Dir) == DirExpect || + hard_link_count(StaticEnv::Dir) == DirExpectAlt); + TEST_CHECK(hard_link_count(StaticEnv::Dir3) == Dir3Expect || + hard_link_count(StaticEnv::Dir3) == Dir3ExpectAlt); std::error_code ec; - TEST_CHECK(hard_link_count(StaticEnv::Dir, ec) == DirExpect); - TEST_CHECK(hard_link_count(StaticEnv::Dir3, ec) == Dir3Expect); + TEST_CHECK(hard_link_count(StaticEnv::Dir, ec) == DirExpect || + hard_link_count(StaticEnv::Dir, ec) == DirExpectAlt); + TEST_CHECK(hard_link_count(StaticEnv::Dir3, ec) == Dir3Expect || + hard_link_count(StaticEnv::Dir3, ec) == Dir3ExpectAlt); } TEST_CASE(hard_link_count_increments_test) { diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_empty/is_empty.pass.cpp b/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_empty/is_empty.pass.cpp index ba07d09d10d9..bc62086c2cff 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_empty/is_empty.pass.cpp +++ b/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_empty/is_empty.pass.cpp @@ -77,4 +77,33 @@ TEST_CASE(test_is_empty_fails) TEST_CHECK_THROW(filesystem_error, is_empty(dir2)); } +TEST_CASE(test_directory_access_denied) +{ + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path file1 = env.create_file("dir/file", 42); + permissions(dir, perms::none); + + std::error_code ec = GetTestEC(); + TEST_CHECK(is_empty(dir, ec) == false); + TEST_CHECK(ec); + TEST_CHECK(ec != GetTestEC()); + + TEST_CHECK_THROW(filesystem_error, is_empty(dir)); +} + + +TEST_CASE(test_fifo_fails) +{ + scoped_test_env env; + const path fifo = env.create_fifo("fifo"); + + std::error_code ec = GetTestEC(); + TEST_CHECK(is_empty(fifo, ec) == false); + TEST_CHECK(ec); + TEST_CHECK(ec != GetTestEC()); + + TEST_CHECK_THROW(filesystem_error, is_empty(fifo)); +} + TEST_SUITE_END() diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.permissions/permissions.pass.cpp b/test/std/experimental/filesystem/fs.op.funcs/fs.op.permissions/permissions.pass.cpp index b177693c09bd..4177392141e5 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.permissions/permissions.pass.cpp +++ b/test/std/experimental/filesystem/fs.op.funcs/fs.op.permissions/permissions.pass.cpp @@ -35,7 +35,8 @@ TEST_CASE(test_signatures) std::error_code ec; ((void)ec); ASSERT_NOT_NOEXCEPT(fs::permissions(p, opts)); // Not noexcept because of narrow contract - ASSERT_NOT_NOEXCEPT(fs::permissions(p, opts, ec)); + LIBCPP_ONLY( + ASSERT_NOT_NOEXCEPT(fs::permissions(p, opts, ec))); } TEST_CASE(test_error_reporting) @@ -52,6 +53,7 @@ TEST_CASE(test_error_reporting) && err.code() == ec; } #else + ((void)f); ((void)opts); ((void)ec); return true; #endif }; @@ -115,7 +117,7 @@ TEST_CASE(basic_permissions_test) permissions(TC.p, TC.set_perms, ec); TEST_CHECK(!ec); auto pp = status(TC.p).permissions(); - TEST_CHECK(status(TC.p).permissions() == TC.expected); + TEST_CHECK(pp == TC.expected); } } diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.read_symlink/read_symlink.pass.cpp b/test/std/experimental/filesystem/fs.op.funcs/fs.op.read_symlink/read_symlink.pass.cpp index 00581cbe8bcc..d69e95ce5d5c 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.read_symlink/read_symlink.pass.cpp +++ b/test/std/experimental/filesystem/fs.op.funcs/fs.op.read_symlink/read_symlink.pass.cpp @@ -51,6 +51,7 @@ TEST_CASE(test_error_reporting) && err.code() == ec; } #else + ((void)f); ((void)ec); return true; #endif }; diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.remove/remove.pass.cpp b/test/std/experimental/filesystem/fs.op.funcs/fs.op.remove/remove.pass.cpp index edb0c4fc76c9..f7ce8a30e64e 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.remove/remove.pass.cpp +++ b/test/std/experimental/filesystem/fs.op.funcs/fs.op.remove/remove.pass.cpp @@ -50,6 +50,7 @@ TEST_CASE(test_error_reporting) && err.code() == ec; } #else + ((void)f); ((void)ec); return true; #endif }; diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp b/test/std/experimental/filesystem/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp index aecfce7885e9..b84c18c1da06 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp +++ b/test/std/experimental/filesystem/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp @@ -50,6 +50,7 @@ TEST_CASE(test_error_reporting) && err.code() == ec; } #else + ((void)f); ((void)ec); return true; #endif }; diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.rename/rename.pass.cpp b/test/std/experimental/filesystem/fs.op.funcs/fs.op.rename/rename.pass.cpp index c2ae854c0bf6..e265c7af6b10 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.rename/rename.pass.cpp +++ b/test/std/experimental/filesystem/fs.op.funcs/fs.op.rename/rename.pass.cpp @@ -50,6 +50,7 @@ TEST_CASE(test_error_reporting) && err.code() == ec; } #else + ((void)f); ((void)t); ((void)ec); return true; #endif }; diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.resize_file/resize_file.pass.cpp b/test/std/experimental/filesystem/fs.op.funcs/fs.op.resize_file/resize_file.pass.cpp index 8a6aa09b14c7..f7c2ee14e83a 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.resize_file/resize_file.pass.cpp +++ b/test/std/experimental/filesystem/fs.op.funcs/fs.op.resize_file/resize_file.pass.cpp @@ -52,6 +52,7 @@ TEST_CASE(test_error_reporting) && err.code() == ec; } #else + ((void)f); ((void)s); ((void)ec); return true; #endif }; diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.space/space.pass.cpp b/test/std/experimental/filesystem/fs.op.funcs/fs.op.space/space.pass.cpp index 865191520be3..8f241810fc7d 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.space/space.pass.cpp +++ b/test/std/experimental/filesystem/fs.op.funcs/fs.op.space/space.pass.cpp @@ -57,6 +57,7 @@ TEST_CASE(test_error_reporting) && err.code() == ec; } #else + ((void)f); ((void)ec); return true; #endif }; diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.temp_dir_path/temp_directory_path.pass.cpp b/test/std/experimental/filesystem/fs.op.funcs/fs.op.temp_dir_path/temp_directory_path.pass.cpp index 215c35a33f30..148564e61961 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.temp_dir_path/temp_directory_path.pass.cpp +++ b/test/std/experimental/filesystem/fs.op.funcs/fs.op.temp_dir_path/temp_directory_path.pass.cpp @@ -51,7 +51,6 @@ TEST_CASE(basic_tests) const path dir_perms = env.create_dir("bad_perms_dir"); const path nested_dir = env.create_dir("bad_perms_dir/nested"); permissions(dir_perms, perms::none); - const std::error_code set_ec = std::make_error_code(std::errc::address_in_use); const std::error_code expect_ec = std::make_error_code(std::errc::not_a_directory); struct TestCase { std::string name; @@ -66,7 +65,7 @@ TEST_CASE(basic_tests) PutEnv(TC.name, TC.p); } for (auto& TC : cases) { - std::error_code ec = set_ec; + std::error_code ec = GetTestEC(); path ret = temp_directory_path(ec); TEST_CHECK(!ec); TEST_CHECK(ret == TC.p); @@ -75,21 +74,25 @@ TEST_CASE(basic_tests) // Set the env variable to a path that does not exist and check // that it fails. PutEnv(TC.name, dne); - ec = set_ec; + ec = GetTestEC(); ret = temp_directory_path(ec); - TEST_CHECK(ec == expect_ec); + LIBCPP_ONLY(TEST_CHECK(ec == expect_ec)); + TEST_CHECK(ec != GetTestEC()); + TEST_CHECK(ec); TEST_CHECK(ret == ""); // Set the env variable to point to a file and check that it fails. PutEnv(TC.name, file); - ec = set_ec; + ec = GetTestEC(); ret = temp_directory_path(ec); - TEST_CHECK(ec == expect_ec); + LIBCPP_ONLY(TEST_CHECK(ec == expect_ec)); + TEST_CHECK(ec != GetTestEC()); + TEST_CHECK(ec); TEST_CHECK(ret == ""); // Set the env variable to point to a dir we can't access PutEnv(TC.name, nested_dir); - ec = set_ec; + ec = GetTestEC(); ret = temp_directory_path(ec); TEST_CHECK(ec == std::make_error_code(std::errc::permission_denied)); TEST_CHECK(ret == ""); @@ -99,7 +102,7 @@ TEST_CASE(basic_tests) } // No env variables are defined { - std::error_code ec = set_ec; + std::error_code ec = GetTestEC(); path ret = temp_directory_path(ec); TEST_CHECK(!ec); TEST_CHECK(ret == "/tmp"); |