diff options
Diffstat (limited to 'libcxx/test/std/experimental/filesystem')
123 files changed, 10116 insertions, 0 deletions
diff --git a/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/bad_symlink b/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/bad_symlink new file mode 120000 index 00000000000..76646beed5e --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/bad_symlink @@ -0,0 +1 @@ +dne
\ No newline at end of file diff --git a/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/dir1/dir2/afile3 b/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/dir1/dir2/afile3 new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/dir1/dir2/afile3 diff --git a/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/dir1/dir2/dir3/file5 b/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/dir1/dir2/dir3/file5 new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/dir1/dir2/dir3/file5 diff --git a/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/dir1/dir2/file4 b/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/dir1/dir2/file4 new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/dir1/dir2/file4 diff --git a/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/dir1/dir2/symlink_to_dir3 b/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/dir1/dir2/symlink_to_dir3 new file mode 120000 index 00000000000..39791395262 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/dir1/dir2/symlink_to_dir3 @@ -0,0 +1 @@ +dir3
\ No newline at end of file diff --git a/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/dir1/file1 b/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/dir1/file1 new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/dir1/file1 diff --git a/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/dir1/file2 b/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/dir1/file2 new file mode 100644 index 00000000000..44834e58673 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/dir1/file2 @@ -0,0 +1 @@ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
\ No newline at end of file diff --git a/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/empty_file b/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/empty_file new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/empty_file diff --git a/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/non_empty_file b/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/non_empty_file new file mode 100644 index 00000000000..44834e58673 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/non_empty_file @@ -0,0 +1 @@ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
\ No newline at end of file diff --git a/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/symlink_to_dir b/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/symlink_to_dir new file mode 120000 index 00000000000..df490f837a8 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/symlink_to_dir @@ -0,0 +1 @@ +dir1
\ No newline at end of file diff --git a/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/symlink_to_empty_file b/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/symlink_to_empty_file new file mode 120000 index 00000000000..b79b689fc85 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/Inputs/static_test_env/symlink_to_empty_file @@ -0,0 +1 @@ +empty_file
\ No newline at end of file diff --git a/libcxx/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons.pass.cpp b/libcxx/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons.pass.cpp new file mode 100644 index 00000000000..9a92f0698ba --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons.pass.cpp @@ -0,0 +1,97 @@ +//===----------------------------------------------------------------------===// +// +// 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 directory_entry + +// directory_entry() noexcept = default; +// directory_entry(const directory_entry&) = default; +// directory_entry(directory_entry&&) noexcept = default; +// explicit directory_entry(const path); + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +namespace fs = std::experimental::filesystem; + +void test_default_ctor() +{ + using namespace fs; + // Default + { + static_assert(std::is_nothrow_default_constructible<directory_entry>::value, + "directory_entry must have a nothrow default constructor"); + directory_entry e; + assert(e.path() == path()); + } +} + + +void test_copy_ctor() +{ + using namespace fs; + // Copy + { + static_assert(std::is_copy_constructible<directory_entry>::value, + "directory_entry must be copy constructible"); + static_assert(!std::is_nothrow_copy_constructible<directory_entry>::value, + "directory_entry's copy constructor cannot be noexcept"); + const path p("foo/bar/baz"); + const directory_entry e(p); + assert(e.path() == p); + directory_entry e2(e); + assert(e.path() == p); + assert(e2.path() == p); + } + +} + +void test_move_ctor() +{ + using namespace fs; + // Move + { + static_assert(std::is_nothrow_move_constructible<directory_entry>::value, + "directory_entry must be nothrow move constructible"); + const path p("foo/bar/baz"); + directory_entry e(p); + assert(e.path() == p); + directory_entry e2(std::move(e)); + assert(e2.path() == p); + assert(e.path() != p); // Testing moved from state. + } +} + +void test_path_ctor() { + using namespace fs; + { + static_assert(std::is_constructible<directory_entry, const path&>::value, + "directory_entry must be constructible from path"); + static_assert(!std::is_nothrow_constructible<directory_entry, const path&>::value, + "directory_entry constructor should not be noexcept"); + static_assert(!std::is_convertible<path const&, directory_entry>::value, + "directory_entry constructor should be explicit"); + } + { + const path p("foo/bar/baz"); + const directory_entry e(p); + assert(p == e.path()); + } +} + +int main() { + test_default_ctor(); + test_copy_ctor(); + test_move_ctor(); + test_path_ctor(); +} diff --git a/libcxx/test/std/experimental/filesystem/class.directory_entry/directory_entry.mods.pass.cpp b/libcxx/test/std/experimental/filesystem/class.directory_entry/directory_entry.mods.pass.cpp new file mode 100644 index 00000000000..97ecbefac42 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.directory_entry/directory_entry.mods.pass.cpp @@ -0,0 +1,113 @@ +//===----------------------------------------------------------------------===// +// +// 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 directory_entry + +// directory_entry& operator=(directory_entry const&) = default; +// directory_entry& operator=(directory_entry&&) noexcept = default; +// void assign(path const&); +// void replace_filename(path const&); + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +namespace fs = std::experimental::filesystem; + +void test_copy_assign_operator() +{ + using namespace fs; + // Copy + { + static_assert(std::is_copy_assignable<directory_entry>::value, + "directory_entry must be copy assignable"); + static_assert(!std::is_nothrow_copy_assignable<directory_entry>::value, + "directory_entry's copy assignment cannot be noexcept"); + const path p("foo/bar/baz"); + const path p2("abc"); + const directory_entry e(p); + directory_entry e2; + assert(e.path() == p && e2.path() == path()); + e2 = e; + assert(e.path() == p && e2.path() == p); + directory_entry e3(p2); + e2 = e3; + assert(e2.path() == p2 && e3.path() == p2); + } +} + + +void test_move_assign_operator() +{ + using namespace fs; + // Copy + { + static_assert(std::is_nothrow_move_assignable<directory_entry>::value, + "directory_entry is noexcept move assignable"); + const path p("foo/bar/baz"); + const path p2("abc"); + directory_entry e(p); + directory_entry e2(p2); + assert(e.path() == p && e2.path() == p2); + e2 = std::move(e); + assert(e2.path() == p); + assert(e.path() != p); // testing moved from state + } +} + +void test_path_assign_method() +{ + using namespace fs; + const path p("foo/bar/baz"); + const path p2("abc"); + directory_entry e(p); + { + static_assert(std::is_same<decltype(e.assign(p)), void>::value, + "return type should be void"); + static_assert(noexcept(e.assign(p)) == false, "operation must not be noexcept"); + } + { + assert(e.path() == p); + e.assign(p2); + assert(e.path() == p2 && e.path() != p); + e.assign(p); + assert(e.path() == p && e.path() != p2); + } +} + +void test_replace_filename_method() +{ + using namespace fs; + const path p("/path/to/foo.exe"); + const path replace("bar.out"); + const path expect("/path/to/bar.out"); + directory_entry e(p); + { + static_assert(noexcept(e.replace_filename(replace)) == false, + "operation cannot be noexcept"); + static_assert(std::is_same<decltype(e.replace_filename(replace)), void>::value, + "operation must return void"); + } + { + assert(e.path() == p); + e.replace_filename(replace); + assert(e.path() == expect); + } +} + +int main() { + test_copy_assign_operator(); + test_move_assign_operator(); + test_path_assign_method(); + test_replace_filename_method(); +} diff --git a/libcxx/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/comparisons.pass.cpp b/libcxx/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/comparisons.pass.cpp new file mode 100644 index 00000000000..96e50930022 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/comparisons.pass.cpp @@ -0,0 +1,82 @@ +//===----------------------------------------------------------------------===// +// +// 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 directory_entry + +// bool operator==(directory_entry const&) const noexcept; +// bool operator!=(directory_entry const&) const noexcept; +// bool operator< (directory_entry const&) const noexcept; +// bool operator<=(directory_entry const&) const noexcept; +// bool operator> (directory_entry const&) const noexcept; +// bool operator>=(directory_entry const&) const noexcept; + + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +namespace fs = std::experimental::filesystem; + +#define CHECK_OP(Op) \ + static_assert(std::is_same<decltype(ce. operator Op (ce)), bool>::value, ""); \ + static_assert(noexcept(ce.operator Op (ce)), "Operation must be noexcept" ) + +void test_comparison_signatures() { + using namespace fs; + path const p("foo/bar/baz"); + // Check that the operators are member functions with the correct signatures. + { + directory_entry const ce(p); + CHECK_OP(==); + CHECK_OP(!=); + CHECK_OP(< ); + CHECK_OP(<=); + CHECK_OP(> ); + CHECK_OP(>=); + } +} +#undef CHECK_OP + +// The actual semantics of the comparisons are testing via paths operators. +void test_comparisons_simple() { + using namespace fs; + typedef std::pair<path, path> TestType; + TestType TestCases[] = + { + {"", ""}, + {"", "a"}, + {"a", "a"}, + {"a", "b"}, + {"foo/bar/baz", "foo/bar/baz/"} + }; + auto TestFn = [](path const& LHS, const directory_entry& LHSE, + path const& RHS, const directory_entry& RHSE) { + assert((LHS == RHS) == (LHSE == RHSE)); + assert((LHS != RHS) == (LHSE != RHSE)); + assert((LHS < RHS) == (LHSE < RHSE)); + assert((LHS <= RHS) == (LHSE <= RHSE)); + assert((LHS > RHS) == (LHSE > RHSE)); + assert((LHS >= RHS) == (LHSE >= RHSE)); + }; + for (auto const& TC : TestCases) { + const directory_entry L(TC.first); + const directory_entry R(TC.second); + TestFn(TC.first, L, TC.second, R); + TestFn(TC.second, R, TC.first, L); + } +} + +int main() { + test_comparison_signatures(); + test_comparisons_simple(); +} diff --git a/libcxx/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/path.pass.cpp b/libcxx/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/path.pass.cpp new file mode 100644 index 00000000000..d228a3d9264 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/path.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 directory_entry + +// const path& path() const noexcept; +// operator const path&() const noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +namespace fs = std::experimental::filesystem; + +void test_path_method() { + using namespace fs; + const path p("foo/bar/baz.exe"); + const path p2("abc"); + { + directory_entry nce; + const directory_entry e(""); + static_assert(std::is_same<decltype(e.path()), const path&>::value, ""); + static_assert(std::is_same<decltype(nce.path()), const path&>::value, ""); + static_assert(noexcept(e.path()) && noexcept(nce.path()), ""); + } + { + directory_entry e(p); + path const& pref = e.path(); + assert(pref == p); + assert(&pref == &e.path()); + e.assign(p2); + assert(pref == p2); + assert(&pref == &e.path()); + } +} + +void test_path_conversion() { + using namespace fs; + const path p("foo/bar/baz.exe"); + const path p2("abc"); + { + directory_entry nce; + const directory_entry e(""); + // Check conversions exist + static_assert(std::is_convertible<directory_entry&, path const&>::value, ""); + static_assert(std::is_convertible<directory_entry const&, path const&>::value, ""); + static_assert(std::is_convertible<directory_entry &&, path const&>::value, ""); + static_assert(std::is_convertible<directory_entry const&&, path const&>::value, ""); + // Not convertible to non-const + static_assert(!std::is_convertible<directory_entry&, path&>::value, ""); + static_assert(!std::is_convertible<directory_entry const&, path&>::value, ""); + static_assert(!std::is_convertible<directory_entry &&, path&>::value, ""); + static_assert(!std::is_convertible<directory_entry const&&, path&>::value, ""); + // conversions are noexcept + static_assert(noexcept(e.operator fs::path const&()) && + noexcept(e.operator fs::path const&()), ""); + } + // const + { + directory_entry const e(p); + path const& pref = e; + assert(&pref == &e.path()); + } + // non-const + { + directory_entry e(p); + path const& pref = e; + assert(&pref == &e.path()); + + e.assign(p2); + assert(pref == p2); + assert(&pref == &e.path()); + } +} + +int main() { + test_path_method(); + test_path_conversion(); +} diff --git a/libcxx/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/status.pass.cpp b/libcxx/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/status.pass.cpp new file mode 100644 index 00000000000..54c5172ebce --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/status.pass.cpp @@ -0,0 +1,51 @@ +//===----------------------------------------------------------------------===// +// +// 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 directory_entry + +// file_status status() const; +// file_status status(error_code const&) const noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "filesystem_test_helper.hpp" + +int main() +{ + using namespace fs; + { + const directory_entry e("foo"); + std::error_code ec; + static_assert(std::is_same<decltype(e.status()), file_status>::value, ""); + static_assert(std::is_same<decltype(e.status(ec)), file_status>::value, ""); + static_assert(noexcept(e.status()) == false, ""); + static_assert(noexcept(e.status(ec)) == true, ""); + } + auto TestFn = [](path const& p) { + const directory_entry e(p); + std::error_code pec, eec; + file_status ps = fs::status(p, pec); + file_status es = e.status(eec); + assert(ps.type() == es.type()); + assert(ps.permissions() == es.permissions()); + assert(pec == eec); + }; + { + TestFn(StaticEnv::File); + TestFn(StaticEnv::Dir); + TestFn(StaticEnv::SymlinkToFile); + TestFn(StaticEnv::DNE); + } +} diff --git a/libcxx/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/symlink_status.pass.cpp b/libcxx/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/symlink_status.pass.cpp new file mode 100644 index 00000000000..3a99eb671b4 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/symlink_status.pass.cpp @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// 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 directory_entry + +// file_status symlink_status() const; +// file_status symlink_status(error_code&) const noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "filesystem_test_helper.hpp" + +int main() { + using namespace fs; + { + const directory_entry e("foo"); + std::error_code ec; + static_assert(std::is_same<decltype(e.symlink_status()), file_status>::value, ""); + static_assert(std::is_same<decltype(e.symlink_status(ec)), file_status>::value, ""); + static_assert(noexcept(e.symlink_status()) == false, ""); + static_assert(noexcept(e.symlink_status(ec)) == true, ""); + } + auto TestFn = [](path const& p) { + const directory_entry e(p); + std::error_code pec, eec; + file_status ps = fs::symlink_status(p, pec); + file_status es = e.symlink_status(eec); + assert(ps.type() == es.type()); + assert(ps.permissions() == es.permissions()); + assert(pec == eec); + }; + { + TestFn(StaticEnv::File); + TestFn(StaticEnv::Dir); + TestFn(StaticEnv::SymlinkToFile); + TestFn(StaticEnv::DNE); + } +} diff --git a/libcxx/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/copy.pass.cpp b/libcxx/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/copy.pass.cpp new file mode 100644 index 00000000000..5c4583391e7 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/copy.pass.cpp @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// 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 directory_iterator + +// directory_iterator(directory_iterator const&); + +#include <experimental/filesystem> +#include <type_traits> +#include <set> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(directory_iterator_copy_construct_tests) + +TEST_CASE(test_constructor_signature) +{ + using D = directory_iterator; + static_assert(std::is_copy_constructible<D>::value, ""); +} + +TEST_CASE(test_copy_end_iterator) +{ + const directory_iterator endIt; + directory_iterator it(endIt); + TEST_CHECK(it == endIt); +} + +TEST_CASE(test_copy_valid_iterator) +{ + const path testDir = StaticEnv::Dir; + const directory_iterator endIt{}; + + const directory_iterator it(testDir); + TEST_REQUIRE(it != endIt); + const path entry = *it; + + const directory_iterator it2(it); + TEST_REQUIRE(it2 == it); + TEST_CHECK(*it2 == entry); + TEST_CHECK(*it == entry); +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/copy_assign.pass.cpp b/libcxx/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/copy_assign.pass.cpp new file mode 100644 index 00000000000..0d5ebf3ebe9 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/copy_assign.pass.cpp @@ -0,0 +1,98 @@ +//===----------------------------------------------------------------------===// +// +// 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 directory_iterator + +// directory_iterator& operator=(directory_iterator const&); + +#include <experimental/filesystem> +#include <type_traits> +#include <set> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(directory_iterator_copy_assign_tests) + +TEST_CASE(test_assignment_signature) +{ + using D = directory_iterator; + static_assert(std::is_copy_assignable<D>::value, ""); +} + +TEST_CASE(test_copy_to_end_iterator) +{ + const path testDir = StaticEnv::Dir; + + const directory_iterator from(testDir); + TEST_REQUIRE(from != directory_iterator{}); + const path entry = *from; + + directory_iterator to{}; + to = from; + TEST_REQUIRE(to == from); + TEST_CHECK(*to == entry); + TEST_CHECK(*from == entry); +} + + +TEST_CASE(test_copy_from_end_iterator) +{ + const path testDir = StaticEnv::Dir; + + const directory_iterator from{}; + + directory_iterator to(testDir); + TEST_REQUIRE(to != directory_iterator{}); + + to = from; + TEST_REQUIRE(to == from); + TEST_CHECK(to == directory_iterator{}); +} + +TEST_CASE(test_copy_valid_iterator) +{ + const path testDir = StaticEnv::Dir; + const directory_iterator endIt{}; + + directory_iterator it_obj(testDir); + const directory_iterator& it = it_obj; + TEST_REQUIRE(it != endIt); + ++it_obj; + TEST_REQUIRE(it != endIt); + const path entry = *it; + + directory_iterator it2(testDir); + TEST_REQUIRE(it2 != it); + const path entry2 = *it2; + TEST_CHECK(entry2 != entry); + + it2 = it; + TEST_REQUIRE(it2 == it); + TEST_CHECK(*it2 == entry); +} + +TEST_CASE(test_returns_reference_to_self) +{ + const directory_iterator it; + directory_iterator it2; + directory_iterator& ref = (it2 = it); + TEST_CHECK(&ref == &it2); +} + + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/ctor.pass.cpp b/libcxx/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/ctor.pass.cpp new file mode 100644 index 00000000000..a6becb1bafa --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/ctor.pass.cpp @@ -0,0 +1,246 @@ +//===----------------------------------------------------------------------===// +// +// 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 directory_iterator + +// explicit directory_iterator(const path& p); +// directory_iterator(const path& p, directory_options options); +// directory_iterator(const path& p, error_code& ec) noexcept; +// directory_iterator(const path& p, directory_options options, error_code& ec) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <set> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(directory_iterator_constructor_tests) + +TEST_CASE(test_constructor_signatures) +{ + using D = directory_iterator; + + // explicit directory_iterator(path const&); + static_assert(!std::is_convertible<path, D>::value, ""); + static_assert(std::is_constructible<D, path>::value, ""); + static_assert(!std::is_nothrow_constructible<D, path>::value, ""); + + // directory_iterator(path const&, error_code&) noexcept + static_assert(std::is_nothrow_constructible<D, path, std::error_code&>::value, ""); + + // directory_iterator(path const&, directory_options); + static_assert(std::is_constructible<D, path, directory_options>::value, ""); + static_assert(!std::is_nothrow_constructible<D, path, directory_options>::value, ""); + + // directory_iterator(path const&, directory_options, error_code&) noexcept + static_assert(std::is_nothrow_constructible<D, path, directory_options, std::error_code&>::value, ""); +} + +TEST_CASE(test_construction_from_bad_path) +{ + std::error_code ec; + directory_options opts = directory_options::none; + const directory_iterator endIt; + + const path testPaths[] = { StaticEnv::DNE, StaticEnv::BadSymlink }; + for (path const& testPath : testPaths) + { + { + directory_iterator it(testPath, ec); + TEST_CHECK(ec); + TEST_CHECK(it == endIt); + } + { + directory_iterator it(testPath, opts, ec); + TEST_CHECK(ec); + TEST_CHECK(it == endIt); + } + { + TEST_CHECK_THROW(filesystem_error, directory_iterator(testPath)); + TEST_CHECK_THROW(filesystem_error, directory_iterator(testPath, opts)); + } + } +} + +TEST_CASE(access_denied_test_case) +{ + using namespace std::experimental::filesystem; + scoped_test_env env; + path const testDir = env.make_env_path("dir1"); + path const testFile = testDir / "testFile"; + env.create_dir(testDir); + 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{}); + + // Change the permissions so we can no longer iterate + permissions(testDir, perms::none); + + // Check that the construction fails when skip_permissions_denied is + // not given. + { + std::error_code ec; + directory_iterator it(testDir, ec); + TEST_REQUIRE(ec); + TEST_CHECK(it == directory_iterator{}); + } + // Check that construction does not report an error when + // 'skip_permissions_denied' is given. + { + std::error_code ec; + directory_iterator it(testDir, directory_options::skip_permission_denied, ec); + TEST_REQUIRE(!ec); + TEST_CHECK(it == directory_iterator{}); + } +} + + +TEST_CASE(access_denied_to_file_test_case) +{ + using namespace std::experimental::filesystem; + scoped_test_env env; + path const testFile = env.make_env_path("file1"); + env.create_file(testFile, 42); + + // Change the permissions so we can no longer iterate + permissions(testFile, perms::none); + + // Check that the construction fails when skip_permissions_denied is + // not given. + { + std::error_code ec; + directory_iterator it(testFile, ec); + TEST_REQUIRE(ec); + TEST_CHECK(it == directory_iterator{}); + } + // Check that construction still fails when 'skip_permissions_denied' is given + // because we tried to open a file and not a directory. + { + std::error_code ec; + directory_iterator it(testFile, directory_options::skip_permission_denied, ec); + TEST_REQUIRE(ec); + TEST_CHECK(it == directory_iterator{}); + } +} + +TEST_CASE(test_open_on_empty_directory_equals_end) +{ + scoped_test_env env; + const path testDir = env.make_env_path("dir1"); + env.create_dir(testDir); + + const directory_iterator endIt; + { + std::error_code ec; + directory_iterator it(testDir, ec); + TEST_CHECK(!ec); + TEST_CHECK(it == endIt); + } + { + directory_iterator it(testDir); + TEST_CHECK(it == endIt); + } +} + +TEST_CASE(test_open_on_directory_succeeds) +{ + const path testDir = StaticEnv::Dir; + std::set<path> dir_contents(std::begin(StaticEnv::DirIterationList), + std::end( StaticEnv::DirIterationList)); + const directory_iterator endIt{}; + + { + std::error_code ec; + directory_iterator it(testDir, ec); + TEST_REQUIRE(!ec); + TEST_CHECK(it != endIt); + TEST_CHECK(dir_contents.count(*it)); + } + { + directory_iterator it(testDir); + TEST_CHECK(it != endIt); + TEST_CHECK(dir_contents.count(*it)); + } +} + +TEST_CASE(test_open_on_file_fails) +{ + const path testFile = StaticEnv::File; + const directory_iterator endIt{}; + { + std::error_code ec; + directory_iterator it(testFile, ec); + TEST_REQUIRE(ec); + TEST_CHECK(it == endIt); + } + { + TEST_CHECK_THROW(filesystem_error, directory_iterator(testFile)); + } +} + +TEST_CASE(test_open_on_empty_string) +{ + const path testPath = ""; + const directory_iterator endIt{}; + + std::error_code ec; + directory_iterator it(testPath, ec); + TEST_CHECK(ec); + TEST_CHECK(it == endIt); +} + +TEST_CASE(test_open_on_dot_dir) +{ + const path testPath = "."; + + std::error_code ec; + directory_iterator it(testPath, ec); + TEST_CHECK(!ec); +} + +TEST_CASE(test_open_on_symlink) +{ + const path symlinkToDir = StaticEnv::SymlinkToDir; + std::set<path> dir_contents; + for (path const& p : StaticEnv::DirIterationList) { + dir_contents.insert(p.filename()); + } + const directory_iterator endIt{}; + + { + std::error_code ec; + directory_iterator it(symlinkToDir, ec); + TEST_REQUIRE(!ec); + TEST_CHECK(it != endIt); + path const& entry = *it; + TEST_CHECK(dir_contents.count(entry.filename())); + } + { + std::error_code ec; + directory_iterator it(symlinkToDir, + directory_options::follow_directory_symlink, ec); + TEST_REQUIRE(!ec); + TEST_CHECK(it != endIt); + path const& entry = *it; + TEST_CHECK(dir_contents.count(entry.filename())); + } +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/default_ctor.pass.cpp b/libcxx/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/default_ctor.pass.cpp new file mode 100644 index 00000000000..94ace185a6a --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/default_ctor.pass.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// 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 directory_iterator + +// directory_iterator::directory_iterator() noexcept + + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +namespace fs = std::experimental::filesystem; + +int main() { + { + static_assert(std::is_nothrow_default_constructible<fs::directory_iterator>::value, ""); + } + { + fs::directory_iterator d1; + const fs::directory_iterator d2; + assert(d1 == d2); + } +} diff --git a/libcxx/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/increment.pass.cpp b/libcxx/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/increment.pass.cpp new file mode 100644 index 00000000000..589b4eca7ef --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/increment.pass.cpp @@ -0,0 +1,117 @@ +//===----------------------------------------------------------------------===// +// +// 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 directory_iterator + +// directory_iterator& operator++(); +// directory_iterator& increment(error_code& ec) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <set> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" +#include <iostream> + +using namespace std::experimental::filesystem; + +TEST_SUITE(directory_iterator_increment_tests) + +TEST_CASE(test_increment_signatures) +{ + using D = directory_iterator; + directory_iterator d; ((void)d); + std::error_code ec; ((void)ec); + + ASSERT_SAME_TYPE(decltype(++d), directory_iterator&); + ASSERT_NOT_NOEXCEPT(++d); + + ASSERT_SAME_TYPE(decltype(d.increment(ec)), directory_iterator&); + ASSERT_NOEXCEPT(d.increment(ec)); +} + +TEST_CASE(test_prefix_increment) +{ + const path testDir = StaticEnv::Dir; + const std::set<path> dir_contents(std::begin(StaticEnv::DirIterationList), + std::end( StaticEnv::DirIterationList)); + const directory_iterator endIt{}; + + std::error_code ec; + directory_iterator it(testDir, ec); + TEST_REQUIRE(!ec); + + std::set<path> unseen_entries = dir_contents; + while (!unseen_entries.empty()) { + TEST_REQUIRE(it != endIt); + const path entry = *it; + TEST_REQUIRE(unseen_entries.erase(entry) == 1); + directory_iterator& it_ref = ++it; + TEST_CHECK(&it_ref == &it); + } + + TEST_CHECK(it == endIt); +} + +TEST_CASE(test_postfix_increment) +{ + const path testDir = StaticEnv::Dir; + const std::set<path> dir_contents(std::begin(StaticEnv::DirIterationList), + std::end( StaticEnv::DirIterationList)); + const directory_iterator endIt{}; + + std::error_code ec; + directory_iterator it(testDir, ec); + TEST_REQUIRE(!ec); + + std::set<path> unseen_entries = dir_contents; + while (!unseen_entries.empty()) { + TEST_REQUIRE(it != endIt); + const path entry = *it; + TEST_REQUIRE(unseen_entries.erase(entry) == 1); + const path entry2 = *it++; + TEST_CHECK(entry2 == entry); + } + + TEST_CHECK(it == endIt); +} + + +TEST_CASE(test_increment_method) +{ + const path testDir = StaticEnv::Dir; + const std::set<path> dir_contents(std::begin(StaticEnv::DirIterationList), + std::end( StaticEnv::DirIterationList)); + const directory_iterator endIt{}; + + std::error_code ec; + directory_iterator it(testDir, ec); + TEST_REQUIRE(!ec); + + std::set<path> unseen_entries = dir_contents; + while (!unseen_entries.empty()) { + TEST_REQUIRE(it != endIt); + const path entry = *it; + TEST_REQUIRE(unseen_entries.erase(entry) == 1); + directory_iterator& it_ref = it.increment(ec); + TEST_REQUIRE(!ec); + TEST_CHECK(&it_ref == &it); + } + + TEST_CHECK(it == endIt); +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/move.pass.cpp b/libcxx/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/move.pass.cpp new file mode 100644 index 00000000000..f6c94e18eb0 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/move.pass.cpp @@ -0,0 +1,62 @@ +//===----------------------------------------------------------------------===// +// +// 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 directory_iterator + +// directory_iterator(directory_iterator&&) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <set> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(directory_iterator_move_construct_tests) + +TEST_CASE(test_constructor_signature) +{ + using D = directory_iterator; + static_assert(std::is_nothrow_move_constructible<D>::value, ""); +} + +TEST_CASE(test_move_end_iterator) +{ + const directory_iterator endIt; + directory_iterator endIt2{}; + + directory_iterator it(std::move(endIt2)); + TEST_CHECK(it == endIt); + TEST_CHECK(endIt2 == endIt); +} + +TEST_CASE(test_move_valid_iterator) +{ + const path testDir = StaticEnv::Dir; + const directory_iterator endIt{}; + + directory_iterator it(testDir); + TEST_REQUIRE(it != endIt); + const path entry = *it; + + const directory_iterator it2(std::move(it)); + TEST_CHECK(*it2 == entry); + + TEST_CHECK(it == it2 || it == endIt); +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/move_assign.pass.cpp b/libcxx/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/move_assign.pass.cpp new file mode 100644 index 00000000000..6c766ef2e24 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/move_assign.pass.cpp @@ -0,0 +1,110 @@ +//===----------------------------------------------------------------------===// +// +// 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 directory_iterator + +// directory_iterator& operator=(directory_iterator const&); + +#include <experimental/filesystem> +#include <type_traits> +#include <set> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(directory_iterator_move_assign_tests) + +TEST_CASE(test_assignment_signature) +{ + using D = directory_iterator; + static_assert(std::is_nothrow_move_assignable<D>::value, ""); +} + +TEST_CASE(test_move_to_end_iterator) +{ + const path testDir = StaticEnv::Dir; + + directory_iterator from(testDir); + TEST_REQUIRE(from != directory_iterator{}); + const path entry = *from; + + directory_iterator to{}; + to = std::move(from); + TEST_REQUIRE(to != directory_iterator{}); + TEST_CHECK(*to == entry); +} + + +TEST_CASE(test_move_from_end_iterator) +{ + const path testDir = StaticEnv::Dir; + + directory_iterator from{}; + + directory_iterator to(testDir); + TEST_REQUIRE(to != from); + + to = std::move(from); + TEST_REQUIRE(to == directory_iterator{}); + TEST_REQUIRE(from == directory_iterator{}); +} + +TEST_CASE(test_move_valid_iterator) +{ + const path testDir = StaticEnv::Dir; + const directory_iterator endIt{}; + + directory_iterator it(testDir); + TEST_REQUIRE(it != endIt); + ++it; + TEST_REQUIRE(it != endIt); + const path entry = *it; + + directory_iterator it2(testDir); + TEST_REQUIRE(it2 != it); + const path entry2 = *it2; + TEST_CHECK(entry2 != entry); + + it2 = std::move(it); + TEST_REQUIRE(it2 != directory_iterator{}); + TEST_CHECK(*it2 == entry); +} + +TEST_CASE(test_returns_reference_to_self) +{ + directory_iterator it; + directory_iterator it2; + directory_iterator& ref = (it2 = it); + TEST_CHECK(&ref == &it2); +} + + +TEST_CASE(test_self_move) +{ + // Create two non-equal iterators that have exactly the same state. + directory_iterator it(StaticEnv::Dir); + directory_iterator it2(StaticEnv::Dir); + ++it; ++it2; + TEST_CHECK(it != it2); + TEST_CHECK(*it2 == *it); + + it = std::move(it); + TEST_CHECK(*it2 == *it); +} + + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.nonmembers/begin_end.pass.cpp b/libcxx/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.nonmembers/begin_end.pass.cpp new file mode 100644 index 00000000000..f93a1845218 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.nonmembers/begin_end.pass.cpp @@ -0,0 +1,61 @@ +//===----------------------------------------------------------------------===// +// +// 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 directory_iterator + +// directory_iterator begin(directory_iterator iter) noexcept; +// directory_iterator end(directory_iterator iter) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <set> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" +#include <iostream> + +using namespace std::experimental::filesystem; + +TEST_SUITE(directory_iterator_begin_end_tests) + +TEST_CASE(test_function_signatures) +{ + using D = directory_iterator; + directory_iterator d; ((void)d); + + ASSERT_SAME_TYPE(decltype(begin(d)), directory_iterator); + ASSERT_NOEXCEPT(begin(std::move(d))); + + ASSERT_SAME_TYPE(decltype(end(d)), directory_iterator); + ASSERT_NOEXCEPT(end(std::move(d))); +} + +TEST_CASE(test_ranged_for_loop) +{ + const path testDir = StaticEnv::Dir; + std::set<path> dir_contents(std::begin(StaticEnv::DirIterationList), + std::end( StaticEnv::DirIterationList)); + + std::error_code ec; + directory_iterator it(testDir, ec); + TEST_REQUIRE(!ec); + + for (auto& elem : it) { + TEST_CHECK(dir_contents.erase(elem) == 1); + } + TEST_CHECK(dir_contents.empty()); +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/class.directory_iterator/types.pass.cpp b/libcxx/test/std/experimental/filesystem/class.directory_iterator/types.pass.cpp new file mode 100644 index 00000000000..dad278f43d7 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.directory_iterator/types.pass.cpp @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// 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 directory_iterator + +// typedef ... value_type; +// typedef ... difference_type; +// typedef ... pointer; +// typedef ... reference; +// typedef ... iterator_category + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +namespace fs = std::experimental::filesystem; + +int main() { + using namespace fs; + using D = directory_iterator; + ASSERT_SAME_TYPE(D::value_type, directory_entry); + ASSERT_SAME_TYPE(D::difference_type, std::ptrdiff_t); + ASSERT_SAME_TYPE(D::pointer, const directory_entry*); + ASSERT_SAME_TYPE(D::reference, const directory_entry&); + ASSERT_SAME_TYPE(D::iterator_category, std::input_iterator_tag); +} diff --git a/libcxx/test/std/experimental/filesystem/class.file_status/file_status.cons.pass.cpp b/libcxx/test/std/experimental/filesystem/class.file_status/file_status.cons.pass.cpp new file mode 100644 index 00000000000..585b0bb1dd5 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.file_status/file_status.cons.pass.cpp @@ -0,0 +1,61 @@ +//===----------------------------------------------------------------------===// +// +// 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 file_status + +// explicit file_status() noexcept; +// explicit file_status(file_type, perms prms = perms::unknown) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_convertible.hpp" + +namespace fs = std::experimental::filesystem; + +int main() { + using namespace fs; + // Default ctor + { + static_assert(std::is_nothrow_default_constructible<file_status>::value, + "The default constructor must be noexcept"); + static_assert(!test_convertible<file_status>(), + "The default constructor must be explicit"); + const file_status f; + assert(f.type() == file_type::none); + assert(f.permissions() == perms::unknown); + } + + // Unary ctor + { + static_assert(std::is_nothrow_constructible<file_status, file_type>::value, + "This constructor must be noexcept"); + static_assert(!test_convertible<file_status, file_type>(), + "This constructor must be explicit"); + + const file_status f(file_type::not_found); + assert(f.type() == file_type::not_found); + assert(f.permissions() == perms::unknown); + } + // Binary ctor + { + static_assert(std::is_nothrow_constructible<file_status, file_type, perms>::value, + "This constructor must be noexcept"); + static_assert(!test_convertible<file_status, file_type, perms>(), + "This constructor must b explicit"); + const file_status f(file_type::regular, perms::owner_read); + assert(f.type() == file_type::regular); + assert(f.permissions() == perms::owner_read); + } +} diff --git a/libcxx/test/std/experimental/filesystem/class.file_status/file_status.mods.pass.cpp b/libcxx/test/std/experimental/filesystem/class.file_status/file_status.mods.pass.cpp new file mode 100644 index 00000000000..8681b2dc50d --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.file_status/file_status.mods.pass.cpp @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// 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 file_status + +// void type(file_type) noexcept; +// void permissions(perms) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +namespace fs = std::experimental::filesystem; + +int main() { + using namespace fs; + + file_status st; + + // type test + { + static_assert(noexcept(st.type(file_type::regular)), + "operation must be noexcept"); + static_assert(std::is_same<decltype(st.type(file_type::regular)), void>::value, + "operation must return void"); + assert(st.type() != file_type::regular); + st.type(file_type::regular); + assert(st.type() == file_type::regular); + } + // permissions test + { + static_assert(noexcept(st.permissions(perms::owner_read)), + "operation must be noexcept"); + static_assert(std::is_same<decltype(st.permissions(perms::owner_read)), void>::value, + "operation must return void"); + assert(st.permissions() != perms::owner_read); + st.permissions(perms::owner_read); + assert(st.permissions() == perms::owner_read); + } +} diff --git a/libcxx/test/std/experimental/filesystem/class.file_status/file_status.obs.pass.cpp b/libcxx/test/std/experimental/filesystem/class.file_status/file_status.obs.pass.cpp new file mode 100644 index 00000000000..4113dee453d --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.file_status/file_status.obs.pass.cpp @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// +// 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 file_status + +// file_type type() const noexcept; +// perms permissions(p) const noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +namespace fs = std::experimental::filesystem; + +int main() { + using namespace fs; + + const file_status st(file_type::regular, perms::owner_read); + + // type test + { + static_assert(noexcept(st.type()), + "operation must be noexcept"); + static_assert(std::is_same<decltype(st.type()), file_type>::value, + "operation must return file_type"); + assert(st.type() == file_type::regular); + } + // permissions test + { + static_assert(noexcept(st.permissions()), + "operation must be noexcept"); + static_assert(std::is_same<decltype(st.permissions()), perms>::value, + "operation must return perms"); + assert(st.permissions() == perms::owner_read); + } +} diff --git a/libcxx/test/std/experimental/filesystem/class.filesystem_error/filesystem_error.members.pass.cpp b/libcxx/test/std/experimental/filesystem/class.filesystem_error/filesystem_error.members.pass.cpp new file mode 100644 index 00000000000..68b67ed7280 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.filesystem_error/filesystem_error.members.pass.cpp @@ -0,0 +1,103 @@ +//===----------------------------------------------------------------------===// +// +// 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 filesystem_error + +// filesystem_error(const string& what_arg, error_code ec); +// filesystem_error(const string& what_arg, const path& p1, error_code ec); +// filesystem_error(const string& what_arg, const path& p1, const path& p2, error_code ec); +// const std::error_code& code() const; +// const char* what() const noexcept; +// const path& path1() const noexcept; +// const path& path2() const noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +namespace fs = std::experimental::filesystem; + +void test_constructors() { + using namespace fs; + + // The string returned by "filesystem_error::what() must contain runtime_error::what() + const std::string what_arg = "Hello World"; + const std::string what_contains = std::runtime_error(what_arg).what(); + assert(what_contains.find(what_arg) != std::string::npos); + auto CheckWhat = [what_contains](filesystem_error const& e) { + std::string s = e.what(); + assert(s.find(what_contains) != std::string::npos); + }; + + std::error_code ec = std::make_error_code(std::errc::file_exists); + const path p1("foo"); + const path p2("bar"); + + // filesystem_error(const string& what_arg, error_code ec); + { + ASSERT_NOT_NOEXCEPT(filesystem_error(what_arg, ec)); + filesystem_error e(what_arg, ec); + CheckWhat(e); + assert(e.code() == ec); + assert(e.path1().empty() && e.path2().empty()); + } + // filesystem_error(const string& what_arg, const path&, error_code ec); + { + ASSERT_NOT_NOEXCEPT(filesystem_error(what_arg, p1, ec)); + filesystem_error e(what_arg, p1, ec); + CheckWhat(e); + assert(e.code() == ec); + assert(e.path1() == p1); + assert(e.path2().empty()); + } + // filesystem_error(const string& what_arg, const path&, const path&, error_code ec); + { + ASSERT_NOT_NOEXCEPT(filesystem_error(what_arg, p1, p2, ec)); + filesystem_error e(what_arg, p1, p2, ec); + CheckWhat(e); + assert(e.code() == ec); + assert(e.path1() == p1); + assert(e.path2() == p2); + } +} + +void test_signatures() +{ + using namespace fs; + const path p; + std::error_code ec; + const filesystem_error e("lala", ec); + // const path& path1() const noexcept; + { + ASSERT_SAME_TYPE(path const&, decltype(e.path1())); + ASSERT_NOEXCEPT(e.path1()); + } + // const path& path2() const noexcept + { + ASSERT_SAME_TYPE(path const&, decltype(e.path2())); + ASSERT_NOEXCEPT(e.path2()); + } + // const char* what() const noexcept + { + ASSERT_SAME_TYPE(const char*, decltype(e.what())); + ASSERT_NOEXCEPT(e.what()); + } +} + +int main() { + static_assert(std::is_base_of<std::system_error, fs::filesystem_error>::value, ""); + test_constructors(); + test_signatures(); +} 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 new file mode 100644 index 00000000000..4aa8ebc25d5 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.itr/iterator.pass.cpp @@ -0,0 +1,104 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// template <class Source> +// path(const Source& source); +// template <class InputIterator> +// path(InputIterator first, InputIterator last); + + +#include <experimental/filesystem> +#include <iterator> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "filesystem_test_helper.hpp" + +namespace fs = std::experimental::filesystem; + + +template <class It> +std::reverse_iterator<It> mkRev(It it) { + return std::reverse_iterator<It>(it); +} + + +void checkIteratorConcepts() { + using namespace fs; + using It = path::iterator; + using Traits = std::iterator_traits<It>; + ASSERT_SAME_TYPE(Traits::iterator_category, std::bidirectional_iterator_tag); + ASSERT_SAME_TYPE(Traits::value_type, path); + ASSERT_SAME_TYPE(Traits::pointer, path const*); + ASSERT_SAME_TYPE(Traits::reference, path const&); + { + It it; + ASSERT_SAME_TYPE(It&, decltype(++it)); + ASSERT_SAME_TYPE(It, decltype(it++)); + ASSERT_SAME_TYPE(It&, decltype(--it)); + ASSERT_SAME_TYPE(It, decltype(it--)); + ASSERT_SAME_TYPE(Traits::reference, decltype(*it)); + ASSERT_SAME_TYPE(Traits::pointer, decltype(it.operator->())); + ASSERT_SAME_TYPE(std::string const&, decltype(it->native())); + ASSERT_SAME_TYPE(bool, decltype(it == it)); + ASSERT_SAME_TYPE(bool, decltype(it != it)); + } + { + path const p; + ASSERT_SAME_TYPE(It, decltype(p.begin())); + ASSERT_SAME_TYPE(It, decltype(p.end())); + assert(p.begin() == p.end()); + } +} + +void checkBeginEndBasic() { + using namespace fs; + using It = path::iterator; + { + path const p; + ASSERT_SAME_TYPE(It, decltype(p.begin())); + ASSERT_SAME_TYPE(It, decltype(p.end())); + assert(p.begin() == p.end()); + } + { + path const p("foo"); + It default_constructed; + default_constructed = p.begin(); + assert(default_constructed == p.begin()); + assert(default_constructed != p.end()); + default_constructed = p.end(); + assert(default_constructed == p.end()); + assert(default_constructed != p.begin()); + } + { + path p("//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(checkCollectionsEqual(mkRev(p.end()), mkRev(p.begin()), mkRev(std::end(expect)), mkRev(std::begin(expect)))); + } + { + path p("////foo/bar/baz///"); + const path expect[] = {"/", "foo", "bar", "baz", "."}; + assert(checkCollectionsEqual(p.begin(), p.end(), std::begin(expect), std::end(expect))); + assert(checkCollectionsEqual(mkRev(p.end()), mkRev(p.begin()), mkRev(std::end(expect)), mkRev(std::begin(expect)))); + } +} + +int main() { + using namespace fs; + checkIteratorConcepts(); + checkBeginEndBasic(); // See path.decompose.pass.cpp for more tests. +} 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 new file mode 100644 index 00000000000..1118497e06a --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.append.pass.cpp @@ -0,0 +1,241 @@ +//===----------------------------------------------------------------------===// +// +// 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& operator/=(path const&) +// template <class Source> +// path& operator/=(Source const&); +// template <class Source> +// path& append(Source const&); +// template <class InputIterator> +// path& append(InputIterator first, InputIterator last); + + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" +#include "count_new.hpp" +#include "filesystem_test_helper.hpp" + +namespace fs = std::experimental::filesystem; + +struct AppendOperatorTestcase { + MultiStringType lhs; + MultiStringType rhs; + MultiStringType expect; +}; + +#define S(Str) MKSTR(Str) +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("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")} + }; + + +const AppendOperatorTestcase LongLHSCases[] = + { + {S("p1"), S("p2"), S("p1/p2")} + , {S("p1/"), S("p2"), S("p1/p2")} + , {S("p1"), S("/p2"), S("p1/p2")} + }; +#undef S + + +// The append operator may need to allocate a temporary buffer before a code_cvt +// conversion. Test if this allocation occurs by: +// 1. Create a path, `LHS`, and reserve enough space to append `RHS`. +// This prevents `LHS` from allocating during the actual appending. +// 2. Create a `Source` object `RHS`, which represents a "large" string. +// (The string must not trigger the SSO) +// 3. Append `RHS` to `LHS` and check for the expected allocation behavior. +template <class CharT> +void doAppendSourceAllocTest(AppendOperatorTestcase const& TC) +{ + using namespace fs; + using Ptr = CharT const*; + using Str = std::basic_string<CharT>; + using InputIter = input_iterator<Ptr>; + + const Ptr L = TC.lhs; + Str RShort = (Ptr)TC.rhs; + Str EShort = (Ptr)TC.expect; + assert(RShort.size() >= 2); + CharT c = RShort.back(); + RShort.append(100, c); + EShort.append(100, c); + const Ptr R = RShort.data(); + const Str& E = EShort; + std::size_t ReserveSize = E.size() + 3; + // basic_string + { + path LHS(L); PathReserve(LHS, ReserveSize); + Str RHS(R); + { + DisableAllocationGuard g; + LHS /= RHS; + } + assert(LHS == E); + } + // CharT* + { + path LHS(L); PathReserve(LHS, ReserveSize); + Ptr RHS(R); + { + DisableAllocationGuard g; + LHS /= RHS; + } + assert(LHS == E); + } + { + path LHS(L); PathReserve(LHS, ReserveSize); + Ptr RHS(R); + { + DisableAllocationGuard g; + LHS.append(RHS, StrEnd(RHS)); + } + assert(LHS == E); + } + // input iterator - For non-native char types, appends needs to copy the + // iterator range into a contigious block of memory before it can perform the + // code_cvt conversions. + // For "char" no allocations will be performed because no conversion is + // required. + bool DisableAllocations = std::is_same<CharT, char>::value; + { + path LHS(L); PathReserve(LHS, ReserveSize); + InputIter RHS(R); + { + RequireAllocationGuard g; // requires 1 or more allocations occur by default + if (DisableAllocations) g.requireExactly(0); + LHS /= RHS; + } + assert(LHS == E); + } + { + path LHS(L); PathReserve(LHS, ReserveSize); + InputIter RHS(R); + InputIter REnd(StrEnd(R)); + { + RequireAllocationGuard g; + if (DisableAllocations) g.requireExactly(0); + LHS.append(RHS, REnd); + } + assert(LHS == E); + } +} + +template <class CharT> +void doAppendSourceTest(AppendOperatorTestcase const& TC) +{ + using namespace fs; + using Ptr = CharT const*; + using Str = std::basic_string<CharT>; + using InputIter = input_iterator<Ptr>; + const Ptr L = TC.lhs; + const Ptr R = TC.rhs; + const Ptr E = TC.expect; + // basic_string + { + path LHS(L); + Str RHS(R); + path& Ref = (LHS /= RHS); + assert(LHS == E); + assert(&Ref == &LHS); + } + { + path LHS(L); + Str RHS(R); + path& Ref = LHS.append(RHS); + assert(LHS == E); + assert(&Ref == &LHS); + } + // Char* + { + path LHS(L); + Str RHS(R); + path& Ref = (LHS /= RHS); + assert(LHS == E); + assert(&Ref == &LHS); + } + { + path LHS(L); + Ptr RHS(R); + path& Ref = LHS.append(RHS); + assert(LHS == E); + assert(&Ref == &LHS); + } + { + path LHS(L); + Ptr RHS(R); + path& Ref = LHS.append(RHS, StrEnd(RHS)); + assert(LHS == E); + assert(&Ref == &LHS); + } + // iterators + { + path LHS(L); + InputIter RHS(R); + path& Ref = (LHS /= RHS); + assert(LHS == E); + assert(&Ref == &LHS); + } + { + path LHS(L); InputIter RHS(R); + path& Ref = LHS.append(RHS); + assert(LHS == E); + assert(&Ref == &LHS); + } + { + path LHS(L); + InputIter RHS(R); + InputIter REnd(StrEnd(R)); + path& Ref = LHS.append(RHS, REnd); + assert(LHS == E); + assert(&Ref == &LHS); + } +} + +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); + } + doAppendSourceTest<char> (TC); + doAppendSourceTest<wchar_t> (TC); + doAppendSourceTest<char16_t>(TC); + doAppendSourceTest<char32_t>(TC); + } + for (auto const & TC : LongLHSCases) { + doAppendSourceAllocTest<char>(TC); + doAppendSourceAllocTest<wchar_t>(TC); + } +} diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.assign/copy.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.assign/copy.pass.cpp new file mode 100644 index 00000000000..5c26f8464c1 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.assign/copy.pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// 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& operator=(path const&); + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +namespace fs = std::experimental::filesystem; + +int main() { + using namespace fs; + static_assert(std::is_copy_assignable<path>::value, ""); + static_assert(!std::is_nothrow_copy_assignable<path>::value, "should not be noexcept"); + const std::string s("foo"); + const path p(s); + path p2; + path& pref = (p2 = p); + assert(p.native() == s); + assert(p2.native() == s); + assert(&pref == &p2); +} diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.assign/move.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.assign/move.pass.cpp new file mode 100644 index 00000000000..7263424ad25 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.assign/move.pass.cpp @@ -0,0 +1,43 @@ +//===----------------------------------------------------------------------===// +// +// 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& operator=(path&&) noexcept + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "count_new.hpp" + +namespace fs = std::experimental::filesystem; + +int main() { + using namespace fs; + static_assert(std::is_nothrow_move_assignable<path>::value, ""); + assert(globalMemCounter.checkOutstandingNewEq(0)); + const std::string s("we really really really really really really really " + "really really long string so that we allocate"); + assert(globalMemCounter.checkOutstandingNewEq(1)); + path p(s); + { + DisableAllocationGuard g; + path p2; + path& pref = (p2 = std::move(p)); + assert(p2.native() == s); + assert(p.native() != s); // Testing moved from state + assert(&pref == &p2); + } +} diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.assign/source.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.assign/source.pass.cpp new file mode 100644 index 00000000000..4c2d5112d10 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.assign/source.pass.cpp @@ -0,0 +1,153 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// template <class Source> +// path& operator=(Source const&); +// template <class Source> +// path& assign(Source const&); +// template <class InputIterator> +// path& assign(InputIterator first, InputIterator last); + + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" +#include "count_new.hpp" +#include "filesystem_test_helper.hpp" +#include <iostream> + +namespace fs = std::experimental::filesystem; + +template <class CharT> +void RunTestCase(MultiStringType const& MS) { + using namespace fs; + const char* Expect = MS; + const CharT* TestPath = MS; + const CharT* TestPathEnd = StrEnd(TestPath); + const std::size_t Size = TestPathEnd - TestPath; + const std::size_t SSize = StrEnd(Expect) - Expect; + assert(Size == SSize); + ////////////////////////////////////////////////////////////////////////////// + // basic_string<Char, Traits, Alloc> + { + const std::basic_string<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<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 + { + path p; PathReserve(p, Size + 1); + { + // char* pointers are contigious and can be used with code_cvt directly. + // no allocations needed. + DisableAllocationGuard g; + path& pref = (p = TestPath); + assert(&pref == &p); + } + assert(p.native() == Expect); + assert(p.string<CharT>() == TestPath); + } + { + path p; PathReserve(p, Size + 1); + { + DisableAllocationGuard g; + path& pref = p.assign(TestPath); + assert(&pref == &p); + } + assert(p.native() == Expect); + assert(p.string<CharT>() == TestPath); + } + { + path p; PathReserve(p, Size + 1); + { + DisableAllocationGuard g; + path& pref = p.assign(TestPath, TestPathEnd); + assert(&pref == &p); + } + assert(p.native() == Expect); + assert(p.string<CharT>() == TestPath); + } + ////////////////////////////////////////////////////////////////////////////// + // Iterators + { + using It = input_iterator<const CharT*>; + path p; PathReserve(p, Size + 1); + It it(TestPath); + { + // Iterators cannot be used with code_cvt directly. This assignment + // may allocate if it's larger than a "short-string". + path& pref = (p = it); + assert(&pref == &p); + } + assert(p.native() == Expect); + assert(p.string<CharT>() == TestPath); + } + { + using It = input_iterator<const CharT*>; + path p; PathReserve(p, Size + 1); + It it(TestPath); + { + path& pref = p.assign(it); + assert(&pref == &p); + } + assert(p.native() == Expect); + assert(p.string<CharT>() == TestPath); + } + { + using It = input_iterator<const CharT*>; + path p; PathReserve(p, Size + 1); + It it(TestPath); + It e(TestPathEnd); + { + path& pref = p.assign(it, e); + assert(&pref == &p); + } + assert(p.native() == Expect); + assert(p.string<CharT>() == TestPath); + } +} + +int main() { + for (auto const& MS : PathList) { + RunTestCase<char>(MS); + RunTestCase<wchar_t>(MS); + RunTestCase<char16_t>(MS); + RunTestCase<char32_t>(MS); + } +} 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 new file mode 100644 index 00000000000..557c1b24d88 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.compare.pass.cpp @@ -0,0 +1,126 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// int compare(path const&) const noexcept; +// int compare(string_type const&) const; +// int compare(value_type const*) const; +// +// bool operator==(path const&, path const&) noexcept; +// bool operator!=(path const&, path const&) noexcept; +// bool operator< (path const&, path const&) noexcept; +// bool operator<=(path const&, path const&) noexcept; +// bool operator> (path const&, path const&) noexcept; +// bool operator>=(path const&, path const&) noexcept; +// +// size_t hash_value(path const&) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <vector> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" +#include "count_new.hpp" +#include "filesystem_test_helper.hpp" + +namespace fs = std::experimental::filesystem; + +struct PathCompareTest { + const char* LHS; + const char* RHS; + int expect; +}; + +#define LONGA "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +#define LONGB "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" +#define LONGC "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC" +#define LONGD "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD" +const PathCompareTest CompareTestCases[] = +{ + {"", "", 0}, + {"a", "", 1}, + {"", "a", -1}, + {"a/b/c", "a/b/c", 0}, + {"b/a/c", "a/b/c", 1}, + {"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", 0}, + {"//foo//bar///baz////", "//foo/bar/baz/", 0}, // duplicate separators + {"///foo/bar", "/foo/bar", 0}, // "///" is not a root directory + {"/foo/bar/", "/foo/bar", 1}, // trailing separator + {"//" LONGA "////" LONGB "/" LONGC "///" LONGD, "//" LONGA "/" LONGB "/" LONGC "/" LONGD, 0}, + { LONGA "/" LONGB "/" LONGC, LONGA "/" LONGB "/" LONGB, 1} + +}; +#undef LONGA +#undef LONGB +#undef LONGC +#undef LONGD + +int main() +{ + using namespace fs; + for (auto const & TC : CompareTestCases) { + const path p1(TC.LHS); + const path p2(TC.RHS); + const std::string R(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); + + // check signatures + ASSERT_NOEXCEPT(p1.compare(p2)); + } + { // comparison operators + DisableAllocationGuard g; // none of these operations should allocate + + // Check runtime result + assert((p1 == p2) == (E == 0)); + assert((p1 != p2) == (E != 0)); + assert((p1 < p2) == (E < 0)); + assert((p1 <= p2) == (E <= 0)); + assert((p1 > p2) == (E > 0)); + assert((p1 >= p2) == (E >= 0)); + + // Check signatures + ASSERT_NOEXCEPT(p1 == p2); + ASSERT_NOEXCEPT(p1 != p2); + ASSERT_NOEXCEPT(p1 < p2); + ASSERT_NOEXCEPT(p1 <= p2); + ASSERT_NOEXCEPT(p1 > p2); + ASSERT_NOEXCEPT(p1 >= p2); + } + { // check hash values + auto h1 = hash_value(p1); + auto h2 = hash_value(p2); + assert((h1 == h2) == (p1 == p2)); + // check signature + ASSERT_SAME_TYPE(size_t, decltype(hash_value(p1))); + ASSERT_NOEXCEPT(hash_value(p1)); + } + } +} diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.concat.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.concat.pass.cpp new file mode 100644 index 00000000000..6e00afe0b49 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.concat.pass.cpp @@ -0,0 +1,277 @@ +//===----------------------------------------------------------------------===// +// +// 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& 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+=(value_type x); +// template <class Source> +// path& operator+=(const Source& x); +// template <class EcharT> +// path& operator+=(EcharT x); +// template <class Source> +// path& concat(const Source& x); +// template <class InputIterator> +// path& concat(InputIterator first, InputIterator last); + + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" +#include "count_new.hpp" +#include "filesystem_test_helper.hpp" + +namespace fs = std::experimental::filesystem; + +struct ConcatOperatorTestcase { + MultiStringType lhs; + MultiStringType rhs; + MultiStringType expect; +}; + +#define LONGSTR "LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR" +#define S(Str) MKSTR(Str) +const ConcatOperatorTestcase Cases[] = + { + {S(""), S(""), S("")} + , {S("p1"), S("p2"), S("p1p2")} + , {S("p1/"), S("/p2"), S("p1//p2")} + , {S(""), S("\\foo/bar/baz"), S("\\foo/bar/baz")} + , {S("c:\\foo"), S(""), S("c:\\foo")} + , {S(LONGSTR), S("foo"), S(LONGSTR "foo")} + , {S("abcdefghijklmnopqrstuvwxyz/\\"), S("/\\123456789"), S("abcdefghijklmnopqrstuvwxyz/\\/\\123456789")} + }; +const ConcatOperatorTestcase LongLHSCases[] = + { + {S(""), S(LONGSTR), S(LONGSTR)} + , {S("p1/"), S(LONGSTR), S("p1/" LONGSTR)} + }; +const ConcatOperatorTestcase CharTestCases[] = + { + {S(""), S("P"), S("P")} + , {S("/fooba"), S("r"), S("/foobar")} + }; +#undef S +#undef LONGSTR + +// The concat operator may need to allocate a temporary buffer before a code_cvt +// conversion. Test if this allocation occurs by: +// 1. Create a path, `LHS`, and reserve enough space to append `RHS`. +// This prevents `LHS` from allocating during the actual appending. +// 2. Create a `Source` object `RHS`, which represents a "large" string. +// (The string must not trigger the SSO) +// 3. Concat `RHS` to `LHS` and check for the expected allocation behavior. +template <class CharT> +void doConcatSourceAllocTest(ConcatOperatorTestcase const& TC) +{ + using namespace fs; + using Ptr = CharT const*; + using Str = std::basic_string<CharT>; + using InputIter = input_iterator<Ptr>; + + const Ptr L = TC.lhs; + const Ptr R = TC.rhs; + const Ptr E = TC.expect; + std::size_t ReserveSize = StrLen(E) + 1; + // basic_string + { + path LHS(L); PathReserve(LHS, ReserveSize); + Str RHS(R); + { + DisableAllocationGuard g; + LHS += RHS; + } + assert(LHS == E); + } + // CharT* + { + path LHS(L); PathReserve(LHS, ReserveSize); + Ptr RHS(R); + { + DisableAllocationGuard g; + LHS += RHS; + } + assert(LHS == E); + } + { + path LHS(L); PathReserve(LHS, ReserveSize); + Ptr RHS(R); + { + DisableAllocationGuard g; + LHS.concat(RHS, StrEnd(RHS)); + } + assert(LHS == E); + } + // input iterator - For non-native char types, appends needs to copy the + // iterator range into a contigious block of memory before it can perform the + // code_cvt conversions. + // For "char" no allocations will be performed because no conversion is + // required. + bool DisableAllocations = std::is_same<CharT, char>::value; + { + path LHS(L); PathReserve(LHS, ReserveSize); + InputIter RHS(R); + { + RequireAllocationGuard g; // requires 1 or more allocations occur by default + if (DisableAllocations) g.requireExactly(0); + LHS += RHS; + } + assert(LHS == E); + } + { + path LHS(L); PathReserve(LHS, ReserveSize); + InputIter RHS(R); + InputIter REnd(StrEnd(R)); + { + RequireAllocationGuard g; + if (DisableAllocations) g.requireExactly(0); + LHS.concat(RHS, REnd); + } + assert(LHS == E); + } +} + +template <class CharT> +void doConcatSourceTest(ConcatOperatorTestcase const& TC) +{ + using namespace fs; + using Ptr = CharT const*; + using Str = std::basic_string<CharT>; + using InputIter = input_iterator<Ptr>; + const Ptr L = TC.lhs; + const Ptr R = TC.rhs; + const Ptr E = TC.expect; + // basic_string + { + path LHS(L); + Str RHS(R); + path& Ref = (LHS += RHS); + assert(LHS == E); + assert(&Ref == &LHS); + } + { + path LHS(L); + Str RHS(R); + path& Ref = LHS.concat(RHS); + assert(LHS == E); + assert(&Ref == &LHS); + } + // Char* + { + path LHS(L); + Str RHS(R); + path& Ref = (LHS += RHS); + assert(LHS == E); + assert(&Ref == &LHS); + } + { + path LHS(L); + Ptr RHS(R); + path& Ref = LHS.concat(RHS); + assert(LHS == E); + assert(&Ref == &LHS); + } + { + path LHS(L); + Ptr RHS(R); + path& Ref = LHS.concat(RHS, StrEnd(RHS)); + assert(LHS == E); + assert(&Ref == &LHS); + } + // iterators + { + path LHS(L); + InputIter RHS(R); + path& Ref = (LHS += RHS); + assert(LHS == E); + assert(&Ref == &LHS); + } + { + path LHS(L); InputIter RHS(R); + path& Ref = LHS.concat(RHS); + assert(LHS == E); + assert(&Ref == &LHS); + } + { + path LHS(L); + InputIter RHS(R); + InputIter REnd(StrEnd(R)); + path& Ref = LHS.concat(RHS, REnd); + assert(LHS == E); + assert(&Ref == &LHS); + } +} + +template <class CharT> +void doConcatECharTest(ConcatOperatorTestcase const& TC) +{ + using namespace fs; + using Ptr = CharT const*; + const Ptr RStr = TC.rhs; + assert(StrLen(RStr) == 1); + const Ptr L = TC.lhs; + const CharT R = RStr[0]; + const Ptr E = TC.expect; + { + path LHS(L); + path& Ref = (LHS += R); + assert(LHS == E); + assert(&Ref == &LHS); + } +} + +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); + } + doConcatSourceTest<char> (TC); + doConcatSourceTest<wchar_t> (TC); + doConcatSourceTest<char16_t>(TC); + doConcatSourceTest<char32_t>(TC); + } + for (auto const & TC : LongLHSCases) { + // Do path test + { + path LHS((const char*)TC.lhs); + path 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); + } + for (auto const& TC : CharTestCases) { + doConcatECharTest<char>(TC); + doConcatECharTest<wchar_t>(TC); + doConcatECharTest<char16_t>(TC); + doConcatECharTest<char32_t>(TC); + } +} diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.construct/copy.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.construct/copy.pass.cpp new file mode 100644 index 00000000000..67b8a04049e --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.construct/copy.pass.cpp @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// 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(path const&) + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +namespace fs = std::experimental::filesystem; + +int main() { + using namespace fs; + static_assert(std::is_copy_constructible<path>::value, ""); + static_assert(!std::is_nothrow_copy_constructible<path>::value, "should not be noexcept"); + const std::string s("foo"); + const path p(s); + path p2(p); + assert(p.native() == s); + assert(p2.native() == s); +} diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.construct/default.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.construct/default.pass.cpp new file mode 100644 index 00000000000..f26504616d5 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.construct/default.pass.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// 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() noexcept + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +namespace fs = std::experimental::filesystem; + +int main() { + using namespace fs; + static_assert(std::is_nothrow_default_constructible<path>::value, ""); + const path p; + assert(p.empty()); +} diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.construct/move.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.construct/move.pass.cpp new file mode 100644 index 00000000000..b8ac4b30700 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.construct/move.pass.cpp @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// 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(path&&) noexcept + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "count_new.hpp" + +namespace fs = std::experimental::filesystem; + +int main() { + using namespace fs; + static_assert(std::is_nothrow_move_constructible<path>::value, ""); + assert(globalMemCounter.checkOutstandingNewEq(0)); + const std::string s("we really really really really really really really " + "really really long string so that we allocate"); + assert(globalMemCounter.checkOutstandingNewEq(1)); + path p(s); + { + DisableAllocationGuard g; + path p2(std::move(p)); + assert(p2.native() == s); + assert(p.native() != s); // Testing moved from state + } +} diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.construct/source.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.construct/source.pass.cpp new file mode 100644 index 00000000000..d89e7c815ef --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.construct/source.pass.cpp @@ -0,0 +1,83 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// template <class Source> +// path(const Source& source); +// template <class InputIterator> +// path(InputIterator first, InputIterator last); + + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" +#include "min_allocator.h" +#include "filesystem_test_helper.hpp" + +namespace fs = std::experimental::filesystem; + +template <class CharT> +void RunTestCase(MultiStringType const& MS) { + using namespace fs; + const char* Expect = MS; + const CharT* TestPath = MS; + const CharT* TestPathEnd = StrEnd(TestPath); + const std::size_t Size = TestPathEnd - TestPath; + const std::size_t SSize = StrEnd(Expect) - Expect; + assert(Size == SSize); + // StringTypes + { + const std::basic_string<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); + assert(p.native() == Expect); + assert(p.string<CharT>() == TestPath); + } + { + path p(TestPath, TestPathEnd); + assert(p.native() == Expect); + assert(p.string<CharT>() == TestPath); + } + // Iterators + { + using It = input_iterator<const CharT*>; + path p(It{TestPath}); + assert(p.native() == Expect); + assert(p.string<CharT>() == TestPath); + } + { + using It = input_iterator<const CharT*>; + path p(It{TestPath}, It{TestPathEnd}); + assert(p.native() == Expect); + assert(p.string<CharT>() == TestPath); + } +} + +int main() { + for (auto const& MS : PathList) { + RunTestCase<char>(MS); + RunTestCase<wchar_t>(MS); + RunTestCase<char16_t>(MS); + RunTestCase<char32_t>(MS); + } +} 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 new file mode 100644 index 00000000000..4c83481aaf2 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.decompose/path.decompose.pass.cpp @@ -0,0 +1,198 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// 8.4.9 path decomposition [path.decompose] +//------------------------------------------ +// path root_name() const; +// path root_directory() const; +// path root_path() const; +// path relative_path() const; +// path parent_path() const; +// path filename() const; +// path stem() const; +// path extension() const; +//------------------------------- +// 8.4.10 path query [path.query] +//------------------------------- +// bool empty() const noexcept; +// bool has_root_path() const; +// bool has_root_name() const; +// bool has_root_directory() const; +// bool has_relative_path() const; +// bool has_parent_path() const; +// bool has_filename() const; +// bool has_stem() const; +// bool has_extension() const; +// bool is_absolute() const; +// bool is_relative() const; +//------------------------------- +// 8.5 path iterators [path.itr] +//------------------------------- +// iterator begin() const; +// iterator end() const; + + +#include <experimental/filesystem> +#include <type_traits> +#include <vector> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" +#include "count_new.hpp" +#include "filesystem_test_helper.hpp" + +template <class It> +std::reverse_iterator<It> mkRev(It it) { + return std::reverse_iterator<It>(it); +} + + +namespace fs = std::experimental::filesystem; +struct PathDecomposeTestcase +{ + std::string raw; + std::vector<std::string> elements; + std::string root_path; + std::string root_name; + std::string root_directory; + std::string relative_path; + std::string parent_path; + std::string filename; +}; + +const PathDecomposeTestcase PathTestCases[] = + { + {"", {}, "", "", "", "", "", ""} + , {".", {"."}, "", "", "", ".", "", "."} + , {"..", {".."}, "", "", "", "..", "", ".."} + , {"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", "."} + , {"///foo///bar", {"/", "foo", "bar"}, "/", "", "/", "foo///bar", "///foo", "bar"} + , {"/.", {"/", "."}, "/", "", "/", ".", "/", "."} + , {"./", {".", "."}, "", "", "", "./", ".", "."} + , {"/..", {"/", ".."}, "/", "", "/", "..", "/", ".."} + , {"../", {"..", "."}, "", "", "", "../", "..", "."} + , {"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/../bar", {"foo", "..", "bar"}, "", "", "", "foo/../bar", "foo/..", "bar"} + , {"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/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\\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); + + assert(p.root_path() == TC.root_path); + assert(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_directory() == TC.root_directory); + assert(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(p.parent_path() == TC.parent_path); + assert(p.has_parent_path() != TC.parent_path.empty()); + + assert(p.filename() == TC.filename); + assert(p.has_filename() != TC.filename.empty()); + + assert(p.is_absolute() == p.has_root_directory()); + assert(p.is_relative() != p.is_absolute()); + + assert(checkCollectionsEqual(p.begin(), p.end(), + TC.elements.begin(), TC.elements.end())); + // check backwards + assert(checkCollectionsEqual(mkRev(p.end()), mkRev(p.begin()), + TC.elements.rbegin(), TC.elements.rend())); + } +} + + +struct FilenameDecompTestcase +{ + std::string raw; + std::string filename; + std::string stem; + std::string extension; +}; + +const FilenameDecompTestcase FilenameTestCases[] = +{ + {"", "", "", ""} + , {".", ".", ".", ""} + , {"..", "..", "..", ""} + , {"/", "/", "/", ""} + , {"foo", "foo", "foo", ""} + , {"/foo/bar.txt", "bar.txt", "bar", ".txt"} + , {"foo..txt", "foo..txt", "foo.", ".txt"} +}; + + +void decompFilenameTest() +{ + using namespace fs; + for (auto const & TC : FilenameTestCases) { + path p(TC.raw); + assert(p == TC.raw); + + assert(p.filename() == TC.filename); + assert(p.has_filename() != TC.filename.empty()); + + assert(p.stem() == TC.stem); + assert(p.has_stem() != TC.stem.empty()); + + assert(p.extension() == TC.extension); + assert(p.has_extension() != TC.extension.empty()); + } +} + +int main() +{ + decompPathTest(); + decompFilenameTest(); +} 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 new file mode 100644 index 00000000000..47e94c9a213 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.generic.obs/generic_string_alloc.pass.cpp @@ -0,0 +1,57 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// template <class ECharT, class Traits = char_traits<ECharT>, +// class Allocator = allocator<ECharT>> +// basic_string<ECharT, Traits, Allocator> +// generic_string(const Allocator& a = Allocator()) const; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" +#include "count_new.hpp" +#include "min_allocator.h" +#include "filesystem_test_helper.hpp" + +namespace fs = std::experimental::filesystem; + +MultiStringType longString = MKSTR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/123456789/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); + + +// generic_string<C, T, A> forwards to string<C, T, A>. Tests for +// string<C, T, A>() are in "path.native.op/string_alloc.pass.cpp". +// generic_string is minimally tested here. +int main() +{ + using namespace fs; + using CharT = wchar_t; + using Traits = std::char_traits<CharT>; + using Alloc = malloc_allocator<CharT>; + using Str = std::basic_string<CharT, Traits, Alloc>; + const wchar_t* expect = longString; + const path p((const char*)longString); + { + DisableAllocationGuard g; + Alloc a; + Alloc::disable_default_constructor = true; + Str s = p.generic_string<wchar_t, Traits, Alloc>(a); + assert(s == expect); + assert(Alloc::alloc_count > 0); + assert(Alloc::outstanding_alloc() == 1); + } +} 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 new file mode 100644 index 00000000000..81d06843640 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.generic.obs/named_overloads.pass.cpp @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// std::string generic_string() const; +// std::wstring generic_wstring() const; +// std::u8string generic_u8string() const; +// std::u16string generic_u16string() const; +// std::u32string generic_u32string() const; + + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" +#include "count_new.hpp" +#include "min_allocator.h" +#include "filesystem_test_helper.hpp" + +namespace fs = std::experimental::filesystem; + +MultiStringType longString = MKSTR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/123456789/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); + +int main() +{ + using namespace fs; + auto const& MS = longString; + const char* value = longString; + const path p(value); + { + std::string s = p.generic_string(); + assert(s == value); + } + { + std::string s = p.generic_u8string(); + assert(s == (const char*)MS); + } + { + std::wstring s = p.generic_wstring(); + assert(s == (const wchar_t*)MS); + } + { + std::u16string s = p.generic_u16string(); + assert(s == (const char16_t*)MS); + } + { + std::u32string s = p.generic_u32string(); + assert(s == (const char32_t*)MS); + } +} diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.modifiers/clear.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.modifiers/clear.pass.cpp new file mode 100644 index 00000000000..5be934968c4 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.modifiers/clear.pass.cpp @@ -0,0 +1,45 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// void clear() noexcept + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" +#include "count_new.hpp" +#include "filesystem_test_helper.hpp" + +namespace fs = std::experimental::filesystem; + +int main() { + using namespace fs; + const path p("/foo/bar/baz"); + { + path p; + ASSERT_NOEXCEPT(p.clear()); + ASSERT_SAME_TYPE(void, decltype(p.clear())); + p.clear(); + assert(p.empty()); + } + { + path p2(p); + assert(p == p2); + p2.clear(); + assert(p2.empty()); + } +} diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.modifiers/make_preferred.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.modifiers/make_preferred.pass.cpp new file mode 100644 index 00000000000..559538cf0ec --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.modifiers/make_preferred.pass.cpp @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// 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& make_preferred() + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" +#include "count_new.hpp" +#include "filesystem_test_helper.hpp" + +namespace fs = std::experimental::filesystem; + +struct MakePreferredTestcase { + const char* value; +}; + +const MakePreferredTestcase TestCases[] = + { + {""} + , {"hello_world"} + , {"/"} + , {"/foo/bar/baz/"} + , {"\\"} + , {"\\foo\\bar\\baz\\"} + , {"\\foo\\/bar\\/baz\\"} + }; + +int main() +{ + // This operation is an identity operation on linux. + using namespace fs; + for (auto const & TC : TestCases) { + path p(TC.value); + assert(p == TC.value); + path& Ref = (p.make_preferred()); + assert(p.native() == TC.value); + assert(&Ref == &p); + } +} 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 new file mode 100644 index 00000000000..4ad9084dbf8 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.modifiers/remove_filename.pass.cpp @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// 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& remove_filename() + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" +#include "count_new.hpp" +#include "filesystem_test_helper.hpp" + +namespace fs = std::experimental::filesystem; + +struct RemoveFilenameTestcase { + const char* value; + const char* expect; +}; + +const RemoveFilenameTestcase TestCases[] = + { + {"", ""} + , {"/", ""} + , {"\\", ""} + , {".", ""} + , {"..", ""} + , {"/foo", "/"} + , {"/foo/", "/foo"} + , {"/foo/.", "/foo"} + , {"/foo/..", "/foo"} + , {"/foo/////", "/foo"} + , {"/foo\\\\", "/"} + , {"/foo//\\/", "/foo//\\"} + , {"file.txt", ""} + , {"bar/../baz/./file.txt", "bar/../baz/."} + }; + +int main() +{ + using namespace fs; + for (auto const & TC : TestCases) { + path const p_orig(TC.value); + path p(p_orig); + assert(p == TC.value); + path& Ref = (p.remove_filename()); + assert(p == TC.expect); + assert(&Ref == &p); + { + const path parentp = p_orig.parent_path(); + if (parentp == p_orig.root_name()) { + + assert(p.empty()); + } else { + assert(p == parentp); + } + } + } +} diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.modifiers/replace_extension.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.modifiers/replace_extension.pass.cpp new file mode 100644 index 00000000000..3dd218411c0 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.modifiers/replace_extension.pass.cpp @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// 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& replace_extension(path const& p = path()) + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" +#include "count_new.hpp" +#include "filesystem_test_helper.hpp" + +namespace fs = std::experimental::filesystem; + +struct ReplaceExtensionTestcase { + const char* value; + const char* expect; + const char* extension; +}; + +const ReplaceExtensionTestcase TestCases[] = + { + {"", "", ""} + , {"foo.cpp", "foo", ""} + , {"foo.cpp", "foo.", "."} + , {"foo..cpp", "foo..txt", "txt"} + , {"", ".txt", "txt"} + , {"", ".txt", ".txt"} + , {"/foo", "/foo.txt", ".txt"} + , {"/foo", "/foo.txt", "txt"} + , {"/foo.cpp", "/foo.txt", ".txt"} + , {"/foo.cpp", "/foo.txt", "txt"} + }; +const ReplaceExtensionTestcase NoArgCases[] = + { + {"", ""} + , {"foo", "foo"} + , {"foo.cpp", "foo"} + , {"foo..cpp", "foo."} +}; + +int main() +{ + using namespace fs; + for (auto const & TC : TestCases) { + path p(TC.value); + assert(p == TC.value); + path& Ref = (p.replace_extension(TC.extension)); + assert(p == TC.expect); + assert(&Ref == &p); + } + for (auto const& TC : NoArgCases) { + path p(TC.value); + assert(p == TC.value); + path& Ref = (p.replace_extension()); + assert(p == TC.expect); + assert(&Ref == &p); + } +} 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 new file mode 100644 index 00000000000..66c97218c83 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.modifiers/replace_filename.pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// 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& replace_filename() + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" +#include "count_new.hpp" +#include "filesystem_test_helper.hpp" + +namespace fs = std::experimental::filesystem; + +struct ReplaceFilenameTestcase { + const char* value; + const char* expect; + const char* filename; +}; + +const ReplaceFilenameTestcase TestCases[] = + { + {"/foo", "/bar", "bar"} + , {"/foo", "/", ""} + , {"foo", "bar", "bar"} + , {"/", "bar", "bar"} + , {"\\", "bar", "bar"} + , {"///", "bar", "bar"} + , {"\\\\", "bar", "bar"} + , {"\\/\\", "\\/bar", "bar"} + , {".", "bar", "bar"} + , {"..", "bar", "bar"} + , {"/foo\\baz/bong/", "/foo\\baz/bong/bar", "bar"} + , {"/foo\\baz/bong", "/foo\\baz/bar", "bar"} + }; + +int main() +{ + using namespace fs; + for (auto const & TC : TestCases) { + path p(TC.value); + assert(p == TC.value); + path& Ref = (p.replace_filename(TC.filename)); + assert(p == TC.expect); + assert(&Ref == &p); + // Tests Effects "as-if": remove_filename() append(filename) + { + path p2(TC.value); + path replace(TC.filename); + p2.remove_filename(); + p2 /= replace; + assert(p2 == p); + } + } +} diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.modifiers/swap.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.modifiers/swap.pass.cpp new file mode 100644 index 00000000000..04bbe3751a5 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.modifiers/swap.pass.cpp @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// void swap(path& rhs) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" +#include "count_new.hpp" +#include "filesystem_test_helper.hpp" + +namespace fs = std::experimental::filesystem; + +struct SwapTestcase { + const char* value1; + const char* value2; +}; + +#define LONG_STR1 "_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG" +#define LONG_STR2 "_THIS_IS_LONG2_THIS_IS_LONG2_THIS_IS_LONG2_THIS_IS_LONG2_THIS_IS_LONG2_THIS_IS_LONG2_THIS_IS_LONG2" +const SwapTestcase TestCases[] = + { + {"", ""} + , {"shortstr", LONG_STR1} + , {LONG_STR1, "shortstr"} + , {LONG_STR1, LONG_STR2} + }; +#undef LONG_STR1 +#undef LONG_STR2 + +int main() +{ + using namespace fs; + { + path p; + ASSERT_NOEXCEPT(p.swap(p)); + ASSERT_SAME_TYPE(void, decltype(p.swap(p))); + } + for (auto const & TC : TestCases) { + path p1(TC.value1); + path p2(TC.value2); + { + DisableAllocationGuard g; + p1.swap(p2); + } + assert(p1 == TC.value2); + assert(p2 == TC.value1); + { + DisableAllocationGuard g; + p1.swap(p2); + } + assert(p1 == TC.value1); + assert(p2 == TC.value2); + } + // self-swap + { + const char* Val = "aoeuaoeuaoeuaoeuaoeuaoeuaoeuaoeuaoeu"; + path p1(Val); + assert(p1 == Val); + { + DisableAllocationGuard g; + p1.swap(p1); + } + assert(p1 == Val); + } +} diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.native.obs/c_str.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.native.obs/c_str.pass.cpp new file mode 100644 index 00000000000..7cf3564bb9b --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.native.obs/c_str.pass.cpp @@ -0,0 +1,43 @@ + +//===----------------------------------------------------------------------===// +// +// 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 + +// const value_type* c_str() const noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "filesystem_test_helper.hpp" + +namespace fs = std::experimental::filesystem; + +int main() +{ + using namespace fs; + const char* const value = "hello world"; + const std::string str_value = value; + path p(value); + { // Check signature + ASSERT_SAME_TYPE(path::value_type const*, decltype(p.c_str())); + ASSERT_NOEXCEPT(p.c_str()); + } + { + path p(value); + assert(p.c_str() == str_value); + assert(p.native().c_str() == p.c_str()); + } +} diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.native.obs/named_overloads.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.native.obs/named_overloads.pass.cpp new file mode 100644 index 00000000000..2a83fef9f9e --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.native.obs/named_overloads.pass.cpp @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// std::string string() const; +// std::wstring wstring() const; +// std::u8string u8string() const; +// std::u16string u16string() const; +// std::u32string u32string() const; + + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" +#include "count_new.hpp" +#include "min_allocator.h" +#include "filesystem_test_helper.hpp" + +namespace fs = std::experimental::filesystem; + +MultiStringType longString = MKSTR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/123456789/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); + +int main() +{ + using namespace fs; + auto const& MS = longString; + const char* value = longString; + const path p(value); + { + std::string s = p.string(); + assert(s == value); + } + { + std::string s = p.u8string(); + assert(s == (const char*)MS); + } + { + std::wstring s = p.wstring(); + assert(s == (const wchar_t*)MS); + } + { + std::u16string s = p.u16string(); + assert(s == (const char16_t*)MS); + } + { + std::u32string s = p.u32string(); + assert(s == (const char32_t*)MS); + } +} diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.native.obs/native.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.native.obs/native.pass.cpp new file mode 100644 index 00000000000..7f8df27faf0 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.native.obs/native.pass.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// const string_type& native() const noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "filesystem_test_helper.hpp" + +namespace fs = std::experimental::filesystem; + +int main() +{ + using namespace fs; + const char* const value = "hello world"; + path p(value); + { // Check signature + ASSERT_SAME_TYPE(path::string_type const&, decltype(p.native())); + ASSERT_NOEXCEPT(p.native()); + } + { // native() is tested elsewhere + path p(value); + assert(p.native() == value); + } +} diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.native.obs/operator_string.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.native.obs/operator_string.pass.cpp new file mode 100644 index 00000000000..9ef83f989aa --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.native.obs/operator_string.pass.cpp @@ -0,0 +1,47 @@ + +//===----------------------------------------------------------------------===// +// +// 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 + +// operator string_type() const; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "filesystem_test_helper.hpp" + +namespace fs = std::experimental::filesystem; + +int main() +{ + using namespace fs; + using string_type = path::string_type; + const char* const value = "hello world"; + path p(value); + { // Check signature + 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())); + ASSERT_NOT_NOEXCEPT(p.operator string_type()); + } + { + path p(value); + assert(p.native() == value); + string_type s = p; + assert(s == value); + assert(p == value); + } +} diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.native.obs/string_alloc.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.native.obs/string_alloc.pass.cpp new file mode 100644 index 00000000000..e5fe89670bd --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.native.obs/string_alloc.pass.cpp @@ -0,0 +1,113 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// template <class ECharT, class Traits = char_traits<ECharT>, +// class Allocator = allocator<ECharT>> +// basic_string<ECharT, Traits, Allocator> +// string(const Allocator& a = Allocator()) const; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" +#include "count_new.hpp" +#include "min_allocator.h" +#include "filesystem_test_helper.hpp" + +namespace fs = std::experimental::filesystem; + +MultiStringType shortString = MKSTR("abc"); +MultiStringType longString = MKSTR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/123456789/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); + +template <class CharT> +void doShortStringTest(MultiStringType const& MS) { + using namespace fs; + using Ptr = CharT const*; + using Str = std::basic_string<CharT>; + using Alloc = std::allocator<CharT>; + Ptr value = MS; + const path p((const char*)MS); + { + DisableAllocationGuard g; // should not allocate + Str s = p.string<CharT>(); + assert(s == value); + Str s2 = p.string<CharT>(Alloc{}); + assert(s2 == value); + } +} + +template <class CharT> +void doLongStringTest(MultiStringType const& MS) { + using namespace fs; + using Ptr = CharT const*; + using Str = std::basic_string<CharT>; + Ptr value = MS; + const path p((const char*)MS); + { // Default allocator + using Alloc = std::allocator<CharT>; + RequireAllocationGuard g; // should not allocate because + Str s = p.string<CharT>(); + assert(s == value); + Str s2 = p.string<CharT>(Alloc{}); + assert(s2 == value); + } + using MAlloc = malloc_allocator<CharT>; + MAlloc::reset(); + { // Other allocator - default construct + using Traits = std::char_traits<CharT>; + using AStr = std::basic_string<CharT, Traits, MAlloc>; + DisableAllocationGuard g; + AStr s = p.string<CharT, Traits, MAlloc>(); + assert(s == value); + assert(MAlloc::alloc_count > 0); + assert(MAlloc::outstanding_alloc() == 1); + } + MAlloc::reset(); + { // Other allocator - provided copy + using Traits = std::char_traits<CharT>; + using AStr = std::basic_string<CharT, Traits, MAlloc>; + DisableAllocationGuard g; + MAlloc a; + // don't allow another allocator to be default constructed. + MAlloc::disable_default_constructor = true; + AStr s = p.string<CharT, Traits, MAlloc>(a); + assert(s == value); + assert(MAlloc::alloc_count > 0); + assert(MAlloc::outstanding_alloc() == 1); + } + MAlloc::reset(); + ///////////////////////////////////////////////////////////////////////////// +} + +int main() +{ + using namespace fs; + { + auto const& S = shortString; + doShortStringTest<char>(S); + doShortStringTest<wchar_t>(S); + doShortStringTest<char16_t>(S); + doShortStringTest<char32_t>(S); + } + { + auto const& S = longString; + doLongStringTest<char>(S); + doLongStringTest<wchar_t>(S); + doLongStringTest<char16_t>(S); + doLongStringTest<char32_t>(S); + } +} diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.member/path.query/tested_in_path_decompose.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.query/tested_in_path_decompose.pass.cpp new file mode 100644 index 00000000000..9cf37d4cd53 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.member/path.query/tested_in_path_decompose.pass.cpp @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +//------------------------------- +// 8.4.10 path query [path.query] +//------------------------------- +// bool empty() const noexcept; +// bool has_root_path() const; +// bool has_root_name() const; +// bool has_root_directory() const; +// bool has_relative_path() const; +// bool has_parent_path() const; +// bool has_filename() const; +// bool has_stem() const; +// bool has_extension() const; +// bool is_absolute() const; +// bool is_relative() const; + +// tested in path.decompose +int main() {} diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.nonmember/append_op.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.nonmember/append_op.pass.cpp new file mode 100644 index 00000000000..58983778446 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.nonmember/append_op.pass.cpp @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// 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 operator/(path const&, path const&); + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "filesystem_test_helper.hpp" + +namespace fs = std::experimental::filesystem; + +// This is mainly tested via the member append functions. +int main() +{ + using namespace fs; + path p1("abc"); + path p2("def"); + path p3 = p1 / p2; + assert(p3 == "abc/def"); +} diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.nonmember/comparison_ops_tested_elsewhere.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.nonmember/comparison_ops_tested_elsewhere.pass.cpp new file mode 100644 index 00000000000..28867432c61 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.nonmember/comparison_ops_tested_elsewhere.pass.cpp @@ -0,0 +1,14 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// The comparison operators are tested as part of [path.compare] +// in class.path/path.members/path.compare.pass.cpp +int main() {} diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.nonmember/hash_value_tested_elswhere.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.nonmember/hash_value_tested_elswhere.pass.cpp new file mode 100644 index 00000000000..b03b8008b62 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.nonmember/hash_value_tested_elswhere.pass.cpp @@ -0,0 +1,14 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// The "hash_value" function is tested as part of [path.compare] +// in class.path/path.members/path.compare.pass.cpp +int main() {} diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.nonmember/path.factory.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.nonmember/path.factory.pass.cpp new file mode 100644 index 00000000000..4853994b495 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.nonmember/path.factory.pass.cpp @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class Source> +// path u8path(Source const&); +// template <class InputIter> +// path u8path(InputIter, InputIter); + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" +#include "count_new.hpp" +#include "filesystem_test_helper.hpp" + +namespace fs = std::experimental::filesystem; + +int main() +{ + using namespace fs; + const char* In1 = "abcd/efg"; + const std::string In2(In1); + const auto In3 = In2.begin(); + const auto In3End = In2.end(); + { + path p = fs::u8path(In1); + assert(p == In1); + } + { + path p = fs::u8path(In2); + assert(p == In1); + } + { + path p = fs::u8path(In3); + assert(p == In1); + } + { + path p = fs::u8path(In3, In3End); + assert(p == In1); + } +} diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.nonmember/path.io.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.nonmember/path.io.pass.cpp new file mode 100644 index 00000000000..e8d150f1e39 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.nonmember/path.io.pass.cpp @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// template <class charT, class traits> +// basic_ostream<charT, traits>& +// operator<<(basic_ostream<charT, traits>& os, const path& p); +// +// template <class charT, class traits> +// basic_istream<charT, traits>& +// operator>>(basic_istream<charT, traits>& is, path& p) +// + +#include <experimental/filesystem> +#include <type_traits> +#include <sstream> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" +#include "count_new.hpp" +#include "filesystem_test_helper.hpp" + +MultiStringType InStr = MKSTR("abcdefg/\"hijklmnop\"/qrstuvwxyz/123456789"); +MultiStringType OutStr = MKSTR("\"abcdefg/\\\"hijklmnop\\\"/qrstuvwxyz/123456789\""); + +template <class CharT> +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; + { // test output + auto& ret = (ss << p); + assert(ss.str() == E); + assert(&ret == &ss); + } + { // test input + path p_in; + auto& ret = ss >> p_in; + assert(p_in.native() == (const char*)InStr); + assert(&ret == &ss); + } +} + + +int main() { + doIOTest<char>(); + doIOTest<wchar_t>(); + //doIOTest<char16_t>(); + //doIOTest<char32_t>(); +} diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.nonmember/path.io.unicode_bug.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.nonmember/path.io.unicode_bug.pass.cpp new file mode 100644 index 00000000000..3a9b48b2669 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.nonmember/path.io.unicode_bug.pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// template <class charT, class traits> +// basic_ostream<charT, traits>& +// operator<<(basic_ostream<charT, traits>& os, const path& p); +// +// template <class charT, class traits> +// basic_istream<charT, traits>& +// operator>>(basic_istream<charT, traits>& is, path& p) +// + +// TODO(EricWF) This test fails because "std::quoted" fails to compile +// for char16_t and char32_t types. Combine with path.io.pass.cpp when this +// passes. +// XFAIL: * + +#include <experimental/filesystem> +#include <type_traits> +#include <sstream> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" +#include "count_new.hpp" +#include "filesystem_test_helper.hpp" + +MultiStringType InStr = MKSTR("abcdefg/\"hijklmnop\"/qrstuvwxyz/123456789"); +MultiStringType OutStr = MKSTR("\"abcdefg/\\\"hijklmnop\\\"/qrstuvwxyz/123456789\""); + +template <class CharT> +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; + { // test output + auto& ret = (ss << p); + assert(ss.str() == E); + assert(&ret == &ss); + } + { // test input + path p_in; + auto& ret = ss >> p_in; + assert(p_in.native() == (const char*)InStr); + assert(&ret == &ss); + } +} + + +int main() { + doIOTest<char16_t>(); + doIOTest<char32_t>(); +} diff --git a/libcxx/test/std/experimental/filesystem/class.path/path.nonmember/swap.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/path.nonmember/swap.pass.cpp new file mode 100644 index 00000000000..8d180463a57 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/path.nonmember/swap.pass.cpp @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// void swap(path& lhs, path& rhs) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "count_new.hpp" +#include "filesystem_test_helper.hpp" + +namespace fs = std::experimental::filesystem; + +// NOTE: this is tested in path.members/path.modifiers via the member swap. +int main() +{ + using namespace fs; + const char* value1 = "foo/bar/baz"; + const char* value2 = "_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG"; + path p1(value1); + path p2(value2); + { + using namespace std; using namespace fs; + ASSERT_NOEXCEPT(swap(p1, p2)); + ASSERT_SAME_TYPE(void, decltype(swap(p1, p2))); + } + { + DisableAllocationGuard g; + using namespace std; + using namespace fs; + swap(p1, p2); + assert(p1.native() == value2); + assert(p2.native() == value1); + swap(p1, p2); + assert(p1.native() == value1); + assert(p2.native() == value2); + } +} diff --git a/libcxx/test/std/experimental/filesystem/class.path/synop.pass.cpp b/libcxx/test/std/experimental/filesystem/class.path/synop.pass.cpp new file mode 100644 index 00000000000..b0a7b5cd65e --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.path/synop.pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// typedef ... value_type; +// typedef basic_string<value_type> string_type; +// static constexpr value_type preferred_separator = ...; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +namespace fs = std::experimental::filesystem; + +int main() { + using namespace fs; + ASSERT_SAME_TYPE(path::value_type, char); + ASSERT_SAME_TYPE(path::string_type, std::basic_string<path::value_type>); + { + ASSERT_SAME_TYPE(const path::value_type, decltype(path::preferred_separator)); + static_assert(path::preferred_separator == '/', ""); + // Make preferred_separator ODR used by taking it's address. + const char* dummy = &path::preferred_separator; + ((void)dummy); + } +} diff --git a/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/copy.pass.cpp b/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/copy.pass.cpp new file mode 100644 index 00000000000..4dbd599e543 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/copy.pass.cpp @@ -0,0 +1,79 @@ +//===----------------------------------------------------------------------===// +// +// 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 recursive_directory_iterator + +// recursive_recursive_directory_iterator(recursive_recursive_directory_iterator const&); + +#include <experimental/filesystem> +#include <type_traits> +#include <set> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(recursive_directory_iterator_copy_construct_tests) + +TEST_CASE(test_constructor_signature) +{ + using D = recursive_directory_iterator; + static_assert(std::is_copy_constructible<D>::value, ""); + //static_assert(!std::is_nothrow_copy_constructible<D>::value, ""); +} + +TEST_CASE(test_copy_end_iterator) +{ + const recursive_directory_iterator endIt; + recursive_directory_iterator it(endIt); + TEST_CHECK(it == endIt); +} + +TEST_CASE(test_copy_valid_iterator) +{ + const path testDir = StaticEnv::Dir; + const recursive_directory_iterator endIt{}; + + // build 'it' up with "interesting" non-default state so we can test + // that it gets copied. We want to get 'it' into a state such that: + // it.options() != directory_options::none + // it.depth() != 0 + // it.recursion_pending() != true + const directory_options opts = directory_options::skip_permission_denied; + recursive_directory_iterator it(testDir, opts); + TEST_REQUIRE(it != endIt); + while (it.depth() == 0) { + ++it; + TEST_REQUIRE(it != endIt); + } + it.disable_recursion_pending(); + TEST_CHECK(it.options() == opts); + TEST_CHECK(it.depth() == 1); + TEST_CHECK(it.recursion_pending() == false); + const path entry = *it; + + // OPERATION UNDER TEST // + const recursive_directory_iterator it2(it); + // ------------------- // + + TEST_REQUIRE(it2 == it); + TEST_CHECK(*it2 == entry); + TEST_CHECK(it2.depth() == 1); + TEST_CHECK(it2.recursion_pending() == false); + TEST_CHECK(it != endIt); +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/copy_assign.pass.cpp b/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/copy_assign.pass.cpp new file mode 100644 index 00000000000..3e9257eac8f --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/copy_assign.pass.cpp @@ -0,0 +1,158 @@ +//===----------------------------------------------------------------------===// +// +// 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 recursive_directory_iterator + +// recursive_directory_iterator& operator=(recursive_directory_iterator const&); + +#include <experimental/filesystem> +#include <type_traits> +#include <set> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(recursive_directory_iterator_copy_assign_tests) + +recursive_directory_iterator createInterestingIterator() + // Create an "interesting" iterator where all fields are + // in a non-default state. The returned 'it' is in a + // state such that: + // it.options() == directory_options::skip_permission_denied + // it.depth() == 1 + // it.recursion_pending() == true +{ + const path testDir = StaticEnv::Dir; + const recursive_directory_iterator endIt; + recursive_directory_iterator it(testDir, + directory_options::skip_permission_denied); + TEST_ASSERT(it != endIt); + while (it.depth() != 1) { + ++it; + TEST_ASSERT(it != endIt); + } + TEST_ASSERT(it.depth() == 1); + it.disable_recursion_pending(); + return it; +} + + +recursive_directory_iterator createDifferentInterestingIterator() + // Create an "interesting" iterator where all fields are + // in a non-default state. The returned 'it' is in a + // state such that: + // it.options() == directory_options::follow_directory_symlink + // it.depth() == 2 + // it.recursion_pending() == false +{ + const path testDir = StaticEnv::Dir; + const recursive_directory_iterator endIt; + recursive_directory_iterator it(testDir, + directory_options::follow_directory_symlink); + TEST_ASSERT(it != endIt); + while (it.depth() != 2) { + ++it; + TEST_ASSERT(it != endIt); + } + TEST_ASSERT(it.depth() == 2); + return it; +} + +TEST_CASE(test_assignment_signature) { + using D = recursive_directory_iterator; + static_assert(std::is_copy_assignable<D>::value, ""); +} + +TEST_CASE(test_copy_to_end_iterator) +{ + const recursive_directory_iterator endIt; + + const recursive_directory_iterator from = createInterestingIterator(); + const path entry = *from; + + recursive_directory_iterator to; + to = from; + TEST_REQUIRE(to == from); + TEST_CHECK(*to == entry); + TEST_CHECK(to.options() == from.options()); + TEST_CHECK(to.depth() == from.depth()); + TEST_CHECK(to.recursion_pending() == from.recursion_pending()); +} + + +TEST_CASE(test_copy_from_end_iterator) +{ + const recursive_directory_iterator from; + recursive_directory_iterator to = createInterestingIterator(); + + to = from; + TEST_REQUIRE(to == from); + TEST_CHECK(to == recursive_directory_iterator{}); +} + +TEST_CASE(test_copy_valid_iterator) +{ + const recursive_directory_iterator endIt; + + const recursive_directory_iterator it = createInterestingIterator(); + const path entry = *it; + + recursive_directory_iterator it2 = createDifferentInterestingIterator(); + TEST_REQUIRE(it2 != it); + TEST_CHECK(it2.options() != it.options()); + TEST_CHECK(it2.depth() != it.depth()); + TEST_CHECK(it2.recursion_pending() != it.recursion_pending()); + TEST_CHECK(*it2 != entry); + + it2 = it; + TEST_REQUIRE(it2 == it); + TEST_CHECK(it2.options() == it.options()); + TEST_CHECK(it2.depth() == it.depth()); + TEST_CHECK(it2.recursion_pending() == it.recursion_pending()); + TEST_CHECK(*it2 == entry); +} + +TEST_CASE(test_returns_reference_to_self) +{ + const recursive_directory_iterator it; + recursive_directory_iterator it2; + recursive_directory_iterator& ref = (it2 = it); + TEST_CHECK(&ref == &it2); +} + +TEST_CASE(test_self_copy) +{ + // Create two non-equal iterators that have exactly the same state. + recursive_directory_iterator it = createInterestingIterator(); + recursive_directory_iterator it2 = createInterestingIterator(); + TEST_CHECK(it != it2); + TEST_CHECK(it2.options() == it.options()); + TEST_CHECK(it2.depth() == it.depth()); + TEST_CHECK(it2.recursion_pending() == it.recursion_pending()); + TEST_CHECK(*it2 == *it); + + // perform a self-copy and check that the state still matches the + // other unmodified iterator. + recursive_directory_iterator const& cit = it; + it = cit; + TEST_CHECK(it2.options() == it.options()); + TEST_CHECK(it2.depth() == it.depth()); + TEST_CHECK(it2.recursion_pending() == it.recursion_pending()); + TEST_CHECK(*it2 == *it); +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/ctor.pass.cpp b/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/ctor.pass.cpp new file mode 100644 index 00000000000..1cddccd0d72 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/ctor.pass.cpp @@ -0,0 +1,240 @@ +//===----------------------------------------------------------------------===// +// +// 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 directory_iterator + +// +// explicit recursive_directory_iterator(const path& p); +// recursive_directory_iterator(const path& p, directory_options options); +// recursive_directory_iterator(const path& p, error_code& ec) noexcept; +// recursive_directory_iterator(const path& p, directory_options options, error_code& ec) noexcept; + + +#include <experimental/filesystem> +#include <type_traits> +#include <set> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +using RDI = recursive_directory_iterator; + +TEST_SUITE(recursive_directory_iterator_constructor_tests) + +TEST_CASE(test_constructor_signatures) +{ + using D = recursive_directory_iterator; + + // explicit directory_iterator(path const&); + static_assert(!std::is_convertible<path, D>::value, ""); + static_assert(std::is_constructible<D, path>::value, ""); + static_assert(!std::is_nothrow_constructible<D, path>::value, ""); + + // directory_iterator(path const&, error_code&) noexcept + static_assert(std::is_nothrow_constructible<D, path, std::error_code&>::value, ""); + + // directory_iterator(path const&, directory_options); + static_assert(std::is_constructible<D, path, directory_options>::value, ""); + static_assert(!std::is_nothrow_constructible<D, path, directory_options>::value, ""); + + // directory_iterator(path const&, directory_options, error_code&) noexcept + static_assert(std::is_nothrow_constructible<D, path, directory_options, std::error_code&>::value, ""); +} + +TEST_CASE(test_construction_from_bad_path) +{ + std::error_code ec; + directory_options opts = directory_options::none; + const RDI endIt; + + const path testPaths[] = { StaticEnv::DNE, StaticEnv::BadSymlink }; + for (path const& testPath : testPaths) + { + { + RDI it(testPath, ec); + TEST_CHECK(ec); + TEST_CHECK(it == endIt); + } + { + RDI it(testPath, opts, ec); + TEST_CHECK(ec); + TEST_CHECK(it == endIt); + } + { + TEST_CHECK_THROW(filesystem_error, RDI(testPath)); + TEST_CHECK_THROW(filesystem_error, RDI(testPath, opts)); + } + } +} + +TEST_CASE(access_denied_test_case) +{ + using namespace std::experimental::filesystem; + scoped_test_env env; + path const testDir = env.make_env_path("dir1"); + path const testFile = testDir / "testFile"; + env.create_dir(testDir); + env.create_file(testFile, 42); + + // Test that we can iterator over the directory before changing the perms + RDI it(testDir); + TEST_REQUIRE(it != RDI{}); + + // Change the permissions so we can no longer iterate + permissions(testDir, perms::none); + + // Check that the construction fails when skip_permissions_denied is + // not given. + { + std::error_code ec; + RDI it(testDir, ec); + TEST_REQUIRE(ec); + TEST_CHECK(it == RDI{}); + } + // Check that construction does not report an error when + // 'skip_permissions_denied' is given. + { + std::error_code ec; + RDI it(testDir, directory_options::skip_permission_denied, ec); + TEST_REQUIRE(!ec); + TEST_CHECK(it == RDI{}); + } +} + + +TEST_CASE(access_denied_to_file_test_case) +{ + using namespace std::experimental::filesystem; + scoped_test_env env; + path const testFile = env.make_env_path("file1"); + env.create_file(testFile, 42); + + // Change the permissions so we can no longer iterate + permissions(testFile, perms::none); + + // Check that the construction fails when skip_permissions_denied is + // not given. + { + std::error_code ec; + RDI it(testFile, ec); + TEST_REQUIRE(ec); + TEST_CHECK(it == RDI{}); + } + // Check that construction still fails when 'skip_permissions_denied' is given + // because we tried to open a file and not a directory. + { + std::error_code ec; + RDI it(testFile, directory_options::skip_permission_denied, ec); + TEST_REQUIRE(ec); + TEST_CHECK(it == RDI{}); + } +} + +TEST_CASE(test_open_on_empty_directory_equals_end) +{ + scoped_test_env env; + const path testDir = env.make_env_path("dir1"); + env.create_dir(testDir); + + const RDI endIt; + { + std::error_code ec; + RDI it(testDir, ec); + TEST_CHECK(!ec); + TEST_CHECK(it == endIt); + } + { + RDI it(testDir); + TEST_CHECK(it == endIt); + } +} + +TEST_CASE(test_open_on_directory_succeeds) +{ + const path testDir = StaticEnv::Dir; + std::set<path> dir_contents(std::begin(StaticEnv::DirIterationList), + std::end( StaticEnv::DirIterationList)); + const RDI endIt{}; + + { + std::error_code ec; + RDI it(testDir, ec); + TEST_REQUIRE(!ec); + TEST_CHECK(it != endIt); + TEST_CHECK(dir_contents.count(*it)); + } + { + RDI it(testDir); + TEST_CHECK(it != endIt); + TEST_CHECK(dir_contents.count(*it)); + } +} + +TEST_CASE(test_open_on_file_fails) +{ + const path testFile = StaticEnv::File; + const RDI endIt{}; + { + std::error_code ec; + RDI it(testFile, ec); + TEST_REQUIRE(ec); + TEST_CHECK(it == endIt); + } + { + TEST_CHECK_THROW(filesystem_error, RDI(testFile)); + } +} + +TEST_CASE(test_options_post_conditions) +{ + const path goodDir = StaticEnv::Dir; + const path badDir = StaticEnv::DNE; + + { + std::error_code ec; + + RDI it1(goodDir, ec); + TEST_REQUIRE(!ec); + TEST_CHECK(it1.options() == directory_options::none); + + RDI it2(badDir, ec); + TEST_REQUIRE(ec); + TEST_REQUIRE(it2 == RDI{}); + } + { + std::error_code ec; + const directory_options opts = directory_options::skip_permission_denied; + + RDI it1(goodDir, opts, ec); + TEST_REQUIRE(!ec); + TEST_CHECK(it1.options() == opts); + + RDI it2(badDir, opts, ec); + TEST_REQUIRE(ec); + TEST_REQUIRE(it2 == RDI{}); + } + { + RDI it(goodDir); + TEST_CHECK(it.options() == directory_options::none); + } + { + const directory_options opts = directory_options::follow_directory_symlink; + RDI it(goodDir, opts); + TEST_CHECK(it.options() == opts); + } +} +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/depth.pass.cpp b/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/depth.pass.cpp new file mode 100644 index 00000000000..676e6f27c88 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/depth.pass.cpp @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// 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 recursive_directory_iterator + +// int depth() const + +#include <experimental/filesystem> +#include <type_traits> +#include <set> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(recursive_directory_iterator_depth_tests) + +TEST_CASE(test_depth) +{ + const path testDir = StaticEnv::Dir; + const path DirDepth1 = StaticEnv::Dir2; + const path DirDepth2 = StaticEnv::Dir3; + const recursive_directory_iterator endIt{}; + + std::error_code ec; + recursive_directory_iterator it(testDir, ec); + TEST_REQUIRE(!ec); + TEST_CHECK(it.depth() == 0); + + bool seen_d1, seen_d2; + seen_d1 = seen_d2 = false; + + while (it != endIt) { + const path entry = *it; + const path parent = entry.parent_path(); + if (parent == testDir) { + TEST_CHECK(it.depth() == 0); + } else if (parent == DirDepth1) { + TEST_CHECK(it.depth() == 1); + seen_d1 = true; + } else if (parent == DirDepth2) { + TEST_CHECK(it.depth() == 2); + seen_d2 = true; + } else { + TEST_CHECK(!"Unexpected depth while iterating over static env"); + } + ++it; + } + TEST_REQUIRE(seen_d1 && seen_d2); + TEST_CHECK(it == endIt); +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/disable_recursion_pending.pass.cpp b/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/disable_recursion_pending.pass.cpp new file mode 100644 index 00000000000..387c6145b6a --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/disable_recursion_pending.pass.cpp @@ -0,0 +1,43 @@ +//===----------------------------------------------------------------------===// +// +// 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 recursive_directory_iterator + +// void disable_recursion_pending(); + +#include <experimental/filesystem> +#include <type_traits> +#include <set> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(recursive_directory_iterator_disable_recursion_pending_tests) + +// NOTE: The main semantics of disable_recursion_pending are tested +// in the 'recursion_pending()' tests. +TEST_CASE(basic_test) +{ + recursive_directory_iterator it(StaticEnv::Dir); + TEST_REQUIRE(it.recursion_pending() == true); + it.disable_recursion_pending(); + TEST_CHECK(it.recursion_pending() == false); + it.disable_recursion_pending(); + TEST_CHECK(it.recursion_pending() == false); +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp b/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp new file mode 100644 index 00000000000..874e7dcf63c --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp @@ -0,0 +1,228 @@ +//===----------------------------------------------------------------------===// +// +// 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 recursive_directory_iterator + +// recursive_directory_iterator& operator++(); +// recursive_directory_iterator& increment(error_code& ec) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <set> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" +#include <iostream> + +using namespace std::experimental::filesystem; + +TEST_SUITE(recursive_directory_iterator_increment_tests) + +TEST_CASE(test_increment_signatures) +{ + using D = recursive_directory_iterator; + recursive_directory_iterator d; ((void)d); + std::error_code ec; ((void)ec); + + ASSERT_SAME_TYPE(decltype(++d), recursive_directory_iterator&); + ASSERT_NOT_NOEXCEPT(++d); + + ASSERT_SAME_TYPE(decltype(d.increment(ec)), recursive_directory_iterator&); + ASSERT_NOEXCEPT(d.increment(ec)); +} + +TEST_CASE(test_prefix_increment) +{ + const path testDir = StaticEnv::Dir; + const std::set<path> dir_contents(std::begin(StaticEnv::RecDirIterationList), + std::end( StaticEnv::RecDirIterationList)); + const recursive_directory_iterator endIt{}; + + std::error_code ec; + recursive_directory_iterator it(testDir, ec); + TEST_REQUIRE(!ec); + + std::set<path> unseen_entries = dir_contents; + while (!unseen_entries.empty()) { + TEST_REQUIRE(it != endIt); + const path entry = *it; + TEST_REQUIRE(unseen_entries.erase(entry) == 1); + recursive_directory_iterator& it_ref = ++it; + TEST_CHECK(&it_ref == &it); + } + + TEST_CHECK(it == endIt); +} + +TEST_CASE(test_postfix_increment) +{ + const path testDir = StaticEnv::Dir; + const std::set<path> dir_contents(std::begin(StaticEnv::RecDirIterationList), + std::end( StaticEnv::RecDirIterationList)); + const recursive_directory_iterator endIt{}; + + std::error_code ec; + recursive_directory_iterator it(testDir, ec); + TEST_REQUIRE(!ec); + + std::set<path> unseen_entries = dir_contents; + while (!unseen_entries.empty()) { + TEST_REQUIRE(it != endIt); + const path entry = *it; + TEST_REQUIRE(unseen_entries.erase(entry) == 1); + const path entry2 = *it++; + TEST_CHECK(entry2 == entry); + } + TEST_CHECK(it == endIt); +} + + +TEST_CASE(test_increment_method) +{ + const path testDir = StaticEnv::Dir; + const std::set<path> dir_contents(std::begin(StaticEnv::RecDirIterationList), + std::end( StaticEnv::RecDirIterationList)); + const recursive_directory_iterator endIt{}; + + std::error_code ec; + recursive_directory_iterator it(testDir, ec); + TEST_REQUIRE(!ec); + + std::set<path> unseen_entries = dir_contents; + while (!unseen_entries.empty()) { + TEST_REQUIRE(it != endIt); + const path entry = *it; + TEST_REQUIRE(unseen_entries.erase(entry) == 1); + recursive_directory_iterator& it_ref = it.increment(ec); + TEST_REQUIRE(!ec); + TEST_CHECK(&it_ref == &it); + } + + TEST_CHECK(it == endIt); +} + +TEST_CASE(test_follow_symlinks) +{ + const path testDir = StaticEnv::Dir; + auto const& IterList = StaticEnv::RecDirFollowSymlinksIterationList; + + const std::set<path> dir_contents(std::begin(IterList), std::end(IterList)); + const recursive_directory_iterator endIt{}; + + std::error_code ec; + recursive_directory_iterator it(testDir, + directory_options::follow_directory_symlink, ec); + TEST_REQUIRE(!ec); + + std::set<path> unseen_entries = dir_contents; + while (!unseen_entries.empty()) { + TEST_REQUIRE(it != endIt); + const path entry = *it; + + TEST_REQUIRE(unseen_entries.erase(entry) == 1); + recursive_directory_iterator& it_ref = it.increment(ec); + TEST_REQUIRE(!ec); + TEST_CHECK(&it_ref == &it); + } + TEST_CHECK(it == endIt); +} + +TEST_CASE(access_denied_on_recursion_test_case) +{ + using namespace std::experimental::filesystem; + scoped_test_env env; + const path testFiles[] = { + env.create_dir("dir1"), + env.create_dir("dir1/dir2"), + env.create_file("dir1/dir2/file1"), + env.create_file("dir1/file2") + }; + const path startDir = testFiles[0]; + const path permDeniedDir = testFiles[1]; + const path otherFile = testFiles[3]; + + // Change the permissions so we can no longer iterate + permissions(permDeniedDir, perms::none); + + const recursive_directory_iterator endIt; + + // Test that recursion resulting in a "EACCESS" error is not ignored + // by default. + { + std::error_code ec; + recursive_directory_iterator it(startDir, ec); + TEST_REQUIRE(!ec); + TEST_REQUIRE(it != endIt); + const path elem = *it; + TEST_REQUIRE(elem == permDeniedDir); + + it.increment(ec); + TEST_REQUIRE(ec); + TEST_REQUIRE(it == endIt); + } + // Same as obove but test operator++(). + { + std::error_code ec; + recursive_directory_iterator it(startDir, ec); + TEST_REQUIRE(!ec); + TEST_REQUIRE(it != endIt); + const path elem = *it; + TEST_REQUIRE(elem == permDeniedDir); + + TEST_REQUIRE_THROW(filesystem_error, ++it); + } + // Test that recursion resulting in a "EACCESS" error is ignored when the + // correct options are given to the constructor. + { + std::error_code ec; + recursive_directory_iterator it( + startDir,directory_options::skip_permission_denied, + ec); + TEST_REQUIRE(!ec); + TEST_REQUIRE(it != endIt); + const path elem = *it; + TEST_REQUIRE(elem == permDeniedDir); + + it.increment(ec); + TEST_REQUIRE(!ec); + TEST_REQUIRE(it != endIt); + TEST_CHECK(*it == otherFile); + } + // Test that construction resulting in a "EACCESS" error is not ignored + // by default. + { + std::error_code ec; + recursive_directory_iterator it(permDeniedDir, ec); + TEST_REQUIRE(ec); + TEST_REQUIRE(it == endIt); + } + // Same as obove but testing the throwing constructors + { + TEST_REQUIRE_THROW(filesystem_error, + recursive_directory_iterator(permDeniedDir)); + } + // Test that construction resulting in a "EACCESS" error constructs the + // end iterator when the correct options are given. + { + std::error_code ec; + recursive_directory_iterator it(permDeniedDir, + directory_options::skip_permission_denied, + ec); + TEST_REQUIRE(!ec); + TEST_REQUIRE(it == endIt); + } +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/move.pass.cpp b/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/move.pass.cpp new file mode 100644 index 00000000000..16dde66d216 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/move.pass.cpp @@ -0,0 +1,80 @@ +//===----------------------------------------------------------------------===// +// +// 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 recursive_directory_iterator + +// recursive_directory_iterator(recursive_directory_iterator&&) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <set> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(recursive_directory_iterator_move_construct_tests) + +TEST_CASE(test_constructor_signature) +{ + using D = recursive_directory_iterator; + static_assert(std::is_nothrow_move_constructible<D>::value, ""); +} + +TEST_CASE(test_move_end_iterator) +{ + const recursive_directory_iterator endIt; + recursive_directory_iterator endIt2{}; + + recursive_directory_iterator it(std::move(endIt2)); + TEST_CHECK(it == endIt); + TEST_CHECK(endIt2 == endIt); +} + +TEST_CASE(test_move_valid_iterator) +{ + const path testDir = StaticEnv::Dir; + const recursive_directory_iterator endIt{}; + + // build 'it' up with "interesting" non-default state so we can test + // that it gets copied. We want to get 'it' into a state such that: + // it.options() != directory_options::none + // it.depth() != 0 + // it.recursion_pending() != true + const directory_options opts = directory_options::skip_permission_denied; + recursive_directory_iterator it(testDir, opts); + TEST_REQUIRE(it != endIt); + while (it.depth() == 0) { + ++it; + TEST_REQUIRE(it != endIt); + } + it.disable_recursion_pending(); + TEST_CHECK(it.options() == opts); + TEST_CHECK(it.depth() == 1); + TEST_CHECK(it.recursion_pending() == false); + const path entry = *it; + + // OPERATION UNDER TEST // + const recursive_directory_iterator it2(std::move(it)); + // ------------------- // + + TEST_REQUIRE(it2 != endIt); + TEST_CHECK(*it2 == entry); + TEST_CHECK(it2.depth() == 1); + TEST_CHECK(it2.recursion_pending() == false); +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/move_assign.pass.cpp b/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/move_assign.pass.cpp new file mode 100644 index 00000000000..a2dd03f5bd8 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/move_assign.pass.cpp @@ -0,0 +1,163 @@ +//===----------------------------------------------------------------------===// +// +// 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 recursive_directory_iterator + +// recursive_directory_iterator& operator=(recursive_directory_iterator const&); + +#include <experimental/filesystem> +#include <type_traits> +#include <set> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(recursive_directory_iterator_move_assign_tests) + +recursive_directory_iterator createInterestingIterator() + // Create an "interesting" iterator where all fields are + // in a non-default state. The returned 'it' is in a + // state such that: + // it.options() == directory_options::skip_permission_denied + // it.depth() == 1 + // it.recursion_pending() == true +{ + const path testDir = StaticEnv::Dir; + const recursive_directory_iterator endIt; + recursive_directory_iterator it(testDir, + directory_options::skip_permission_denied); + TEST_ASSERT(it != endIt); + while (it.depth() != 1) { + ++it; + TEST_ASSERT(it != endIt); + } + TEST_ASSERT(it.depth() == 1); + it.disable_recursion_pending(); + return it; +} + +recursive_directory_iterator createDifferentInterestingIterator() + // Create an "interesting" iterator where all fields are + // in a non-default state. The returned 'it' is in a + // state such that: + // it.options() == directory_options::follow_directory_symlink + // it.depth() == 2 + // it.recursion_pending() == false +{ + const path testDir = StaticEnv::Dir; + const recursive_directory_iterator endIt; + recursive_directory_iterator it(testDir, + directory_options::follow_directory_symlink); + TEST_ASSERT(it != endIt); + while (it.depth() != 2) { + ++it; + TEST_ASSERT(it != endIt); + } + TEST_ASSERT(it.depth() == 2); + return it; +} + + +TEST_CASE(test_assignment_signature) +{ + using D = recursive_directory_iterator; + static_assert(std::is_nothrow_move_assignable<D>::value, ""); +} + + +TEST_CASE(test_move_to_end_iterator) +{ + const recursive_directory_iterator endIt; + + recursive_directory_iterator from = createInterestingIterator(); + const recursive_directory_iterator from_copy(from); + const path entry = *from; + + recursive_directory_iterator to; + to = std::move(from); + TEST_REQUIRE(to != endIt); + TEST_CHECK(*to == entry); + TEST_CHECK(to.options() == from_copy.options()); + TEST_CHECK(to.depth() == from_copy.depth()); + TEST_CHECK(to.recursion_pending() == from_copy.recursion_pending()); + TEST_CHECK(from == endIt || from == to); +} + + +TEST_CASE(test_move_from_end_iterator) +{ + recursive_directory_iterator from; + recursive_directory_iterator to = createInterestingIterator(); + + to = std::move(from); + TEST_REQUIRE(to == from); + TEST_CHECK(to == recursive_directory_iterator{}); +} + +TEST_CASE(test_move_valid_iterator) +{ + const recursive_directory_iterator endIt; + + recursive_directory_iterator it = createInterestingIterator(); + const recursive_directory_iterator it_copy(it); + const path entry = *it; + + recursive_directory_iterator it2 = createDifferentInterestingIterator(); + const recursive_directory_iterator it2_copy(it2); + TEST_REQUIRE(it2 != it); + TEST_CHECK(it2.options() != it.options()); + TEST_CHECK(it2.depth() != it.depth()); + TEST_CHECK(it2.recursion_pending() != it.recursion_pending()); + TEST_CHECK(*it2 != entry); + + it2 = std::move(it); + TEST_REQUIRE(it2 != it2_copy && it2 != endIt); + TEST_CHECK(it2.options() == it_copy.options()); + TEST_CHECK(it2.depth() == it_copy.depth()); + TEST_CHECK(it2.recursion_pending() == it_copy.recursion_pending()); + TEST_CHECK(*it2 == entry); + TEST_CHECK(it == endIt || it == it2); +} + +TEST_CASE(test_returns_reference_to_self) +{ + recursive_directory_iterator it; + recursive_directory_iterator it2; + recursive_directory_iterator& ref = (it2 = std::move(it)); + TEST_CHECK(&ref == &it2); +} + +TEST_CASE(test_self_move) +{ + // Create two non-equal iterators that have exactly the same state. + recursive_directory_iterator it = createInterestingIterator(); + recursive_directory_iterator it2 = createInterestingIterator(); + TEST_CHECK(it != it2); + TEST_CHECK(it2.options() == it.options()); + TEST_CHECK(it2.depth() == it.depth()); + TEST_CHECK(it2.recursion_pending() == it.recursion_pending()); + TEST_CHECK(*it2 == *it); + + it = std::move(it); + TEST_CHECK(it2.options() == it.options()); + TEST_CHECK(it2.depth() == it.depth()); + TEST_CHECK(it2.recursion_pending() == it.recursion_pending()); + TEST_CHECK(*it2 == *it); +} + + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/pop.pass.cpp b/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/pop.pass.cpp new file mode 100644 index 00000000000..befa30484c0 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/pop.pass.cpp @@ -0,0 +1,93 @@ +//===----------------------------------------------------------------------===// +// +// 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 recursive_directory_iterator + +// void pop(); +// void pop(error_code& ec); + +#include <experimental/filesystem> +#include <set> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(recursive_directory_iterator_pop_tests) + +TEST_CASE(signature_tests) +{ + recursive_directory_iterator it{}; ((void)it); + std::error_code ec; ((void)ec); + ASSERT_NOT_NOEXCEPT(it.pop()); + ASSERT_NOT_NOEXCEPT(it.pop(ec)); // may require allocation or other things +} + +// NOTE: Since the order of iteration is unspecified we use a list of +// seen files at each depth to determine the new depth after a 'pop()' operation. +TEST_CASE(test_depth) +{ + const recursive_directory_iterator endIt{}; + + auto& DE0 = StaticEnv::DirIterationList; + std::set<path> notSeenDepth0(std::begin(DE0), std::end(DE0)); + + auto& DE1 = StaticEnv::DirIterationListDepth1; + std::set<path> notSeenDepth1(std::begin(DE1), std::end(DE1)); + + std::error_code ec; + recursive_directory_iterator it(StaticEnv::Dir, ec); + TEST_REQUIRE(it != endIt); + TEST_CHECK(it.depth() == 0); + + while (it.depth() != 2) { + if (it.depth() == 0) + notSeenDepth0.erase(it->path()); + else + notSeenDepth1.erase(it->path()); + ++it; + TEST_REQUIRE(it != endIt); + } + + while (true) { + auto set_ec = std::make_error_code(std::errc::address_in_use); + it.pop(set_ec); + TEST_REQUIRE(!set_ec); + + if (it == endIt) { + // We must have seen every entry at depth 0 and 1. + TEST_REQUIRE(notSeenDepth0.empty() && notSeenDepth1.empty()); + break; + } + else if (it.depth() == 1) { + // If we popped to depth 1 then there must be unseen entries + // at this level. + TEST_REQUIRE(!notSeenDepth1.empty()); + TEST_CHECK(notSeenDepth1.count(it->path())); + notSeenDepth1.clear(); + } + else if (it.depth() == 0) { + // If we popped to depth 0 there must be unseen entries at this + // level. There should also be no unseen entries at depth 1. + TEST_REQUIRE(!notSeenDepth0.empty()); + TEST_REQUIRE(notSeenDepth1.empty()); + TEST_CHECK(notSeenDepth0.count(it->path())); + notSeenDepth0.clear(); + } + } +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/recursion_pending.pass.cpp b/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/recursion_pending.pass.cpp new file mode 100644 index 00000000000..833e6203430 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/recursion_pending.pass.cpp @@ -0,0 +1,145 @@ +//===----------------------------------------------------------------------===// +// +// 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 recursive_directory_iterator + +// bool recursion_pending() const; + +#include <experimental/filesystem> +#include <type_traits> +#include <set> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(recursive_directory_iterator_recursion_pending_tests) + +TEST_CASE(initial_value_test) +{ + recursive_directory_iterator it(StaticEnv::Dir); + TEST_REQUIRE(it.recursion_pending() == true); +} + +TEST_CASE(value_after_copy_construction_and_assignment_test) +{ + recursive_directory_iterator rec_pending_it(StaticEnv::Dir); + recursive_directory_iterator no_rec_pending_it(StaticEnv::Dir); + no_rec_pending_it.disable_recursion_pending(); + + { // copy construction + recursive_directory_iterator it(rec_pending_it); + TEST_CHECK(it.recursion_pending() == true); + it.disable_recursion_pending(); + TEST_REQUIRE(rec_pending_it.recursion_pending() == true); + + recursive_directory_iterator it2(no_rec_pending_it); + TEST_CHECK(it2.recursion_pending() == false); + } + { // copy assignment + recursive_directory_iterator it(StaticEnv::Dir); + it.disable_recursion_pending(); + it = rec_pending_it; + TEST_CHECK(it.recursion_pending() == true); + it.disable_recursion_pending(); + TEST_REQUIRE(rec_pending_it.recursion_pending() == true); + + recursive_directory_iterator it2(StaticEnv::Dir); + it2 = no_rec_pending_it; + TEST_CHECK(it2.recursion_pending() == false); + } + TEST_CHECK(rec_pending_it.recursion_pending() == true); + TEST_CHECK(no_rec_pending_it.recursion_pending() == false); +} + + +TEST_CASE(value_after_move_construction_and_assignment_test) +{ + recursive_directory_iterator rec_pending_it(StaticEnv::Dir); + recursive_directory_iterator no_rec_pending_it(StaticEnv::Dir); + no_rec_pending_it.disable_recursion_pending(); + + { // move construction + recursive_directory_iterator it_cp(rec_pending_it); + recursive_directory_iterator it(std::move(it_cp)); + TEST_CHECK(it.recursion_pending() == true); + + recursive_directory_iterator it_cp2(no_rec_pending_it); + recursive_directory_iterator it2(std::move(it_cp2)); + TEST_CHECK(it2.recursion_pending() == false); + } + { // copy assignment + recursive_directory_iterator it(StaticEnv::Dir); + it.disable_recursion_pending(); + recursive_directory_iterator it_cp(rec_pending_it); + it = std::move(it_cp); + TEST_CHECK(it.recursion_pending() == true); + + recursive_directory_iterator it2(StaticEnv::Dir); + recursive_directory_iterator it_cp2(no_rec_pending_it); + it2 = std::move(it_cp2); + TEST_CHECK(it2.recursion_pending() == false); + } + TEST_CHECK(rec_pending_it.recursion_pending() == true); + TEST_CHECK(no_rec_pending_it.recursion_pending() == false); +} + +TEST_CASE(increment_resets_value) +{ + const recursive_directory_iterator endIt; + { + recursive_directory_iterator it(StaticEnv::Dir); + it.disable_recursion_pending(); + TEST_CHECK(it.recursion_pending() == false); + ++it; + TEST_CHECK(it.recursion_pending() == true); + TEST_CHECK(it.depth() == 0); + } + { + recursive_directory_iterator it(StaticEnv::Dir); + it.disable_recursion_pending(); + TEST_CHECK(it.recursion_pending() == false); + it++; + TEST_CHECK(it.recursion_pending() == true); + TEST_CHECK(it.depth() == 0); + } + { + recursive_directory_iterator it(StaticEnv::Dir); + it.disable_recursion_pending(); + TEST_CHECK(it.recursion_pending() == false); + std::error_code ec; + it.increment(ec); + TEST_CHECK(it.recursion_pending() == true); + TEST_CHECK(it.depth() == 0); + } +} + +TEST_CASE(pop_does_not_reset_value) +{ + const recursive_directory_iterator endIt; + recursive_directory_iterator it(StaticEnv::Dir); + + while (it.depth() == 0) { + ++it; + TEST_REQUIRE(it != endIt); + } + it.disable_recursion_pending(); + it.pop(); + TEST_REQUIRE(it != endIt); + TEST_CHECK(it.recursion_pending() == false); +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.nonmembers/begin_end.pass.cpp b/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.nonmembers/begin_end.pass.cpp new file mode 100644 index 00000000000..ca5117f0e32 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.nonmembers/begin_end.pass.cpp @@ -0,0 +1,61 @@ +//===----------------------------------------------------------------------===// +// +// 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 recursive_directory_iterator + +// recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept; +// recursive_directory_iterator end(recursive_directory_iterator iter) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <set> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" +#include <iostream> + +using namespace std::experimental::filesystem; + +TEST_SUITE(recursive_directory_iterator_begin_end_tests) + +TEST_CASE(test_function_signatures) +{ + using D = recursive_directory_iterator; + recursive_directory_iterator d; ((void)d); + + ASSERT_SAME_TYPE(decltype(begin(d)), recursive_directory_iterator); + ASSERT_NOEXCEPT(begin(std::move(d))); + + ASSERT_SAME_TYPE(decltype(end(d)), recursive_directory_iterator); + ASSERT_NOEXCEPT(end(std::move(d))); +} + +TEST_CASE(test_ranged_for_loop) +{ + const path testDir = StaticEnv::Dir; + std::set<path> dir_contents(std::begin(StaticEnv::RecDirIterationList), + std::end( StaticEnv::RecDirIterationList)); + + std::error_code ec; + recursive_directory_iterator it(testDir, ec); + TEST_REQUIRE(!ec); + + for (auto& elem : it) { + TEST_CHECK(dir_contents.erase(elem) == 1); + } + TEST_CHECK(dir_contents.empty()); +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.enum/check_bitmask_types.hpp b/libcxx/test/std/experimental/filesystem/fs.enum/check_bitmask_types.hpp new file mode 100644 index 00000000000..0ad882f24b6 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.enum/check_bitmask_types.hpp @@ -0,0 +1,75 @@ +#ifndef TEST_BITMASK_TYPE_HPP +#define TEST_BITMASK_TYPE_HPP + +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + + +template <class EnumType, EnumType Val1, EnumType Val2, + class UT = typename std::underlying_type<EnumType>::type, + UT UVal1 = static_cast<UT>(Val1), + UT UVal2 = static_cast<UT>(Val2), + UT UZero = static_cast<UT>(0), + EnumType Zero = static_cast<EnumType>(0) + > +struct check_bitmask_type { + + static constexpr UT dcast(EnumType e) { return static_cast<UT>(e); } + static constexpr UT unpromote(decltype(~UZero) promoted) { return static_cast<UT>(promoted); } + // We need two values that are non-zero and share at least one bit. + static_assert(Val1 != Zero && Val2 != Zero, ""); + static_assert(Val1 != Val2, ""); + static_assert((UVal1 & UVal2) == 0, ""); + + + static bool check() + { + { + EnumType ValRef = Val1; + ASSERT_SAME_TYPE(EnumType, decltype(Val1 & Val2)); + ASSERT_SAME_TYPE(EnumType, decltype(Val1 | Val2)); + ASSERT_SAME_TYPE(EnumType, decltype(Val1 ^ Val2)); + ASSERT_SAME_TYPE(EnumType, decltype(~Val1)); + ASSERT_SAME_TYPE(EnumType&, decltype(ValRef &= Val2)); + ASSERT_SAME_TYPE(EnumType&, decltype(ValRef |= Val2)); + ASSERT_SAME_TYPE(EnumType&, decltype(ValRef ^= Val2)); + } + + static_assert((Val1 & Zero) == Zero, ""); + static_assert((Val1 & Val1) == Val1, ""); + static_assert(dcast(Val1 & Val2) == (UVal1 & UVal2), ""); + + static_assert((Val1 | Zero) == Val1, ""); + static_assert(dcast(Val1 | Val2) == (UVal1 | UVal2), ""); + + static_assert((Val1 ^ Zero) == Val1, ""); + static_assert(dcast(Val1 ^ Val2) == (UVal1 ^ UVal2), ""); + + static_assert(dcast(~Zero) == unpromote(~UZero), ""); + static_assert(dcast(~Val1) == unpromote(~UVal1), ""); + + { + EnumType e = Val1; + EnumType& eref = (e &= Val2); + assert(&eref == &e); + assert(dcast(eref) == (UVal1 & UVal2)); + } + { + EnumType e = Val1; + EnumType& eref = (e |= Val2); + assert(&eref == &e); + assert(dcast(eref) == (UVal1 | UVal2)); + } + { + EnumType e = Val1; + EnumType& eref = (e ^= Val2); + assert(&eref == &e); + assert(dcast(eref) == (UVal1 ^ UVal2)); + } + return true; + } +}; + +#endif // TEST_BITMASK_TYPE diff --git a/libcxx/test/std/experimental/filesystem/fs.enum/enum.copy_options.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.enum/enum.copy_options.pass.cpp new file mode 100644 index 00000000000..22f0cb845a7 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.enum/enum.copy_options.pass.cpp @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// 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 copy_options; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "check_bitmask_types.hpp" +#include "test_macros.h" + +namespace fs = std::experimental::filesystem; + +constexpr fs::copy_options ME(int val) { return static_cast<fs::copy_options>(val); } + +int main() { + typedef fs::copy_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 short>::value, ""); // Implementation detail + + typedef check_bitmask_type<E, E::skip_existing, E::update_existing> BitmaskTester; + assert(BitmaskTester::check()); + + static_assert( + E::none == ME(0), + "Expected enumeration values do not match"); + // Option group for copy_file + static_assert( + E::skip_existing == ME(1) && + E::overwrite_existing == ME(2) && + E::update_existing == ME(4), + "Expected enumeration values do not match"); + // Option group for copy on directories + static_assert( + E::recursive == ME(8), + "Expected enumeration values do not match"); + // Option group for copy on symlinks + static_assert( + E::copy_symlinks == ME(16) && + E::skip_symlinks == ME(32), + "Expected enumeration values do not match"); + // Option group for changing form of copy + static_assert( + E::directories_only == ME(64) && + E::create_symlinks == ME(128) && + E::create_hard_links == ME(256), + "Expected enumeration values do not match"); +} diff --git a/libcxx/test/std/experimental/filesystem/fs.enum/enum.directory_options.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.enum/enum.directory_options.pass.cpp new file mode 100644 index 00000000000..7dbf7b2887e --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.enum/enum.directory_options.pass.cpp @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// +// 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 directory_options; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> +#include <sys/stat.h> + +#include "test_macros.h" +#include "check_bitmask_types.hpp" + +namespace fs = std::experimental::filesystem; + +constexpr fs::directory_options ME(int val) { return static_cast<fs::directory_options>(val); } + +int main() { + typedef fs::directory_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, ""); + + typedef check_bitmask_type<E, E::follow_directory_symlink, E::skip_permission_denied> BitmaskTester; + assert(BitmaskTester::check()); + + static_assert( + E::none == ME(0) && + E::follow_directory_symlink == ME(1) && + E::skip_permission_denied == ME(2), + "Expected enumeration values do not match"); + +} diff --git a/libcxx/test/std/experimental/filesystem/fs.enum/enum.file_type.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.enum/enum.file_type.pass.cpp new file mode 100644 index 00000000000..ab94ad2877a --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.enum/enum.file_type.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 file_type; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +namespace fs = std::experimental::filesystem; + +constexpr fs::file_type ME(int val) { return static_cast<fs::file_type>(val); } + +int main() { + typedef fs::file_type 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, signed char>::value, ""); // Implementation detail + + static_assert( + E::none == ME(0) && + E::not_found == ME(-1) && + E::regular == ME(1) && + E::directory == ME(2) && + E::symlink == ME(3) && + E::block == ME(4) && + E::character == ME(5) && + E::fifo == ME(6) && + E::socket == ME(7) && + E::unknown == ME(8), + "Expected enumeration values do not match"); +} diff --git a/libcxx/test/std/experimental/filesystem/fs.enum/enum.perms.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.enum/enum.perms.pass.cpp new file mode 100644 index 00000000000..a3589eb291f --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.enum/enum.perms.pass.cpp @@ -0,0 +1,68 @@ +//===----------------------------------------------------------------------===// +// +// 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 perms; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> +#include <sys/stat.h> + +#include "test_macros.h" +#include "check_bitmask_types.hpp" + +namespace fs = std::experimental::filesystem; + +constexpr fs::perms ME(int val) { return static_cast<fs::perms>(val); } + +int main() { + typedef fs::perms 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 >::value, ""); // Implementation detail + + typedef check_bitmask_type<E, E::group_all, E::owner_all> BitmaskTester; + assert(BitmaskTester::check()); + + static_assert( + E::none == ME(0) && + + E::owner_read == ME(0400) && + E::owner_write == ME(0200) && + E::owner_exec == ME(0100) && + E::owner_all == ME(0700) && + + E::group_read == ME(040) && + E::group_write == ME(020) && + E::group_exec == ME(010) && + E::group_all == ME(070) && + + E::others_read == ME(04) && + E::others_write == ME(02) && + E::others_exec == ME(01) && + E::others_all == ME(07) && + E::all == ME(0777) && + E::set_uid == ME(04000) && + E::set_gid == ME(02000) && + E::sticky_bit == ME(01000) && + E::mask == ME(07777) && + E::unknown == ME(0xFFFF) && + E::add_perms == ME(0x10000) && + E::remove_perms == ME(0x20000) && + E::resolve_symlinks == ME(0x40000), + "Expected enumeration values do not match"); +} diff --git a/libcxx/test/std/experimental/filesystem/fs.error.report/tested_elsewhere.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.error.report/tested_elsewhere.pass.cpp new file mode 100644 index 00000000000..b58f5c55b64 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.error.report/tested_elsewhere.pass.cpp @@ -0,0 +1,12 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +int main() +{ +} diff --git a/libcxx/test/std/experimental/filesystem/fs.filesystem.synopsis/file_time_type.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.filesystem.synopsis/file_time_type.pass.cpp new file mode 100644 index 00000000000..d8d92c5888a --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.filesystem.synopsis/file_time_type.pass.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// typedef TrivialClock file_time_type; + +#include <experimental/filesystem> +#include <chrono> +#include <type_traits> + +// system_clock is used because it meets the requirements of TrivialClock, +// and it's resolution and range of system_clock should match the operating +// systems file time type. +typedef std::chrono::system_clock ExpectedClock; +typedef std::chrono::time_point<ExpectedClock> ExpectedTimePoint; + +int main() { + static_assert(std::is_same< + std::experimental::filesystem::file_time_type, + ExpectedTimePoint + >::value, ""); +} 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 new file mode 100644 index 00000000000..4d59235c722 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.absolute/absolute.pass.cpp @@ -0,0 +1,117 @@ +//===----------------------------------------------------------------------===// +// +// 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 absolute(const path& p, const path& base=current_path()); + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(filesystem_absolute_path_test_suite) + +TEST_CASE(absolute_signature_test) +{ + const path p; ((void)p); + ASSERT_NOT_NOEXCEPT(absolute(p)); + ASSERT_NOT_NOEXCEPT(absolute(p, p)); +} + +// 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 recursivly 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 recursivly 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) +{ + 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 = absolute(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.canonical/canonical.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.canonical/canonical.pass.cpp new file mode 100644 index 00000000000..6b114d0e40a --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.canonical/canonical.pass.cpp @@ -0,0 +1,118 @@ +//===----------------------------------------------------------------------===// +// +// 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 canonical(const path& p, const path& base = current_path()); +// path canonical(const path& p, error_code& ec); +// path canonical(const path& p, const path& base, error_code& ec); + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(filesystem_canonical_path_test_suite) + +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) +{ + // has_root_name() && has_root_directory() + const path Root = StaticEnv::Root; + const path RootName = Root.filename(); + const path DirName = StaticEnv::Dir.filename(); + const path SymlinkName = StaticEnv::SymlinkToFile.filename(); + struct TestCase { + path p; + path expect; + path base = StaticEnv::Root; + }; + const TestCase testCases[] = { + { ".", Root, Root}, + { DirName / ".." / "." / DirName, StaticEnv::Dir, Root}, + { StaticEnv::Dir2 / "..", StaticEnv::Dir }, + { StaticEnv::Dir3 / "../..", StaticEnv::Dir }, + { StaticEnv::Dir / ".", StaticEnv::Dir }, + { Root / "." / DirName / ".." / DirName, StaticEnv::Dir}, + { path("..") / "." / RootName / DirName / ".." / DirName, StaticEnv::Dir, Root}, + { StaticEnv::SymlinkToFile, StaticEnv::File }, + { SymlinkName, StaticEnv::File, StaticEnv::Root} + }; + for (auto& TC : testCases) { + std::error_code ec; + const path ret = canonical(TC.p, TC.base, ec); + TEST_REQUIRE(!ec); + const path ret2 = canonical(TC.p, TC.base); + TEST_CHECK(ret == TC.expect); + TEST_CHECK(ret == ret2); + TEST_CHECK(ret.is_absolute()); + } +} + +TEST_CASE(test_dne_path) +{ + std::error_code ec; + { + 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_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 + const path p = "blabla/dne"; + const path base = StaticEnv::Root; + try { + canonical(p, base); + TEST_REQUIRE(false); + } catch (filesystem_error const& err) { + TEST_CHECK(err.path1() == p); + TEST_CHECK(err.path2() == base); + } + try { + canonical(p); + TEST_REQUIRE(false); + } catch (filesystem_error const& err) { + TEST_CHECK(err.path1() == p); + TEST_CHECK(err.path2() == current_path()); + } +#endif +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy/copy.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy/copy.pass.cpp new file mode 100644 index 00000000000..8e55aec3489 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy/copy.pass.cpp @@ -0,0 +1,251 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// void copy(const path& from, const path& to); +// void copy(const path& from, const path& to, error_code& ec) noexcept; +// void copy(const path& from, const path& to, copy_options options); +// void copy(const path& from, const path& to, copy_options options, +// error_code& ec) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; +namespace fs = std::experimental::filesystem; + +using CO = fs::copy_options; + +TEST_SUITE(filesystem_copy_test_suite) + +TEST_CASE(signature_test) +{ + const path p; ((void)p); + std::error_code ec; ((void)ec); + const copy_options opts{}; ((void)opts); + ASSERT_NOT_NOEXCEPT(fs::copy(p, p)); + ASSERT_NOEXCEPT(fs::copy(p, p, ec)); + ASSERT_NOT_NOEXCEPT(copy(p, p, opts)); + ASSERT_NOEXCEPT(copy(p, p, opts, ec)); +} + +// There are 4 cases is the proposal for absolute path. +// Each scope tests one of the cases. +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::copy(f, t); + return false; + } catch (filesystem_error const& err) { + return err.path1() == f + && err.path2() == t + && err.code() == ec; + } +#else + return true; +#endif + }; + + scoped_test_env env; + const path file = env.create_file("file1", 42); + const path dir = env.create_dir("dir"); + const path fifo = env.create_fifo("fifo"); + TEST_REQUIRE(is_other(fifo)); + + // !exists(f) + { + std::error_code ec; + const path f = StaticEnv::DNE; + const path t = env.test_root; + fs::copy(f, t, ec); + TEST_REQUIRE(ec); + TEST_CHECK(checkThrow(f, t, ec)); + } + { // equivalent(f, t) == true + std::error_code ec; + fs::copy(file, file, ec); + TEST_REQUIRE(ec); + TEST_CHECK(checkThrow(file, file, ec)); + } + { // is_directory(from) && is_file(to) + std::error_code ec; + fs::copy(dir, file, ec); + TEST_REQUIRE(ec); + TEST_CHECK(checkThrow(dir, file, ec)); + } + { // is_other(from) + std::error_code ec; + fs::copy(fifo, dir, ec); + TEST_REQUIRE(ec); + TEST_CHECK(checkThrow(fifo, dir, ec)); + } + { // is_other(to) + std::error_code ec; + fs::copy(file, fifo, ec); + TEST_REQUIRE(ec); + TEST_CHECK(checkThrow(file, fifo, ec)); + } +} + +TEST_CASE(from_is_symlink) +{ + scoped_test_env env; + const path file = env.create_file("file", 42); + const path symlink = env.create_symlink(file, "sym"); + const path dne = env.make_env_path("dne"); + + { // skip symlinks + std::error_code ec; + fs::copy(symlink, dne, copy_options::skip_symlinks, ec); + TEST_CHECK(!ec); + TEST_CHECK(!exists(dne)); + } + { + const path dest = env.make_env_path("dest"); + std::error_code ec; + fs::copy(symlink, dest, copy_options::copy_symlinks, ec); + TEST_CHECK(!ec); + TEST_CHECK(exists(dest)); + TEST_CHECK(is_symlink(dest)); + } + { // copy symlink but target exists + std::error_code ec; + fs::copy(symlink, file, copy_options::copy_symlinks, ec); + TEST_CHECK(ec); + } + { // create symlinks but target exists + std::error_code ec; + fs::copy(symlink, file, copy_options::create_symlinks, ec); + TEST_CHECK(ec); + } +} + +TEST_CASE(from_is_regular_file) +{ + scoped_test_env env; + const path file = env.create_file("file", 42); + const path dir = env.create_dir("dir"); + { // skip copy because of directory + const path dest = env.make_env_path("dest1"); + std::error_code ec; + fs::copy(file, dest, CO::directories_only, ec); + TEST_CHECK(!ec); + TEST_CHECK(!exists(dest)); + } + { // create symlink to file + const path dest = env.make_env_path("sym"); + std::error_code ec; + fs::copy(file, dest, CO::create_symlinks, ec); + TEST_CHECK(!ec); + TEST_CHECK(is_symlink(dest)); + TEST_CHECK(equivalent(file, canonical(dest))); + } + { // create hard link to file + const path dest = env.make_env_path("hardlink"); + TEST_CHECK(hard_link_count(file) == 1); + std::error_code ec; + fs::copy(file, dest, CO::create_hard_links, ec); + TEST_CHECK(!ec); + TEST_CHECK(exists(dest)); + TEST_CHECK(hard_link_count(file) == 2); + } + { // is_directory(t) + const path dest_dir = env.create_dir("dest_dir"); + const path expect_dest = dest_dir / file.filename(); + std::error_code ec; + fs::copy(file, dest_dir, ec); + TEST_CHECK(!ec); + TEST_CHECK(is_regular_file(expect_dest)); + } + { // otherwise copy_file(from, to, ...) + const path dest = env.make_env_path("file_copy"); + std::error_code ec; + fs::copy(file, dest, ec); + TEST_CHECK(!ec); + TEST_CHECK(is_regular_file(dest)); + } +} + +TEST_CASE(from_is_directory) +{ + struct FileInfo { + path filename; + int size; + }; + const FileInfo files[] = { + {"file1", 0}, + {"file2", 42}, + {"file3", 300} + }; + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path nested_dir_name = "dir2"; + const path nested_dir = env.create_dir("dir/dir2"); + + for (auto& FI : files) { + env.create_file(dir / FI.filename, FI.size); + env.create_file(nested_dir / FI.filename, FI.size); + } + { // test for non-existant directory + const path dest = env.make_env_path("dest_dir1"); + std::error_code ec; + fs::copy(dir, dest, ec); + TEST_REQUIRE(!ec); + TEST_CHECK(is_directory(dest)); + for (auto& FI : files) { + path created = dest / FI.filename; + TEST_CHECK(is_regular_file(created)); + TEST_CHECK(file_size(created) == FI.size); + } + TEST_CHECK(!is_directory(dest / nested_dir_name)); + } + { // test for existing directory + const path dest = env.create_dir("dest_dir2"); + std::error_code ec; + fs::copy(dir, dest, ec); + TEST_REQUIRE(!ec); + TEST_CHECK(is_directory(dest)); + for (auto& FI : files) { + path created = dest / FI.filename; + TEST_CHECK(is_regular_file(created)); + TEST_CHECK(file_size(created) == FI.size); + } + TEST_CHECK(!is_directory(dest / nested_dir_name)); + } + { // test recursive copy + const path dest = env.make_env_path("dest_dir3"); + std::error_code ec; + fs::copy(dir, dest, CO::recursive, ec); + TEST_REQUIRE(!ec); + TEST_CHECK(is_directory(dest)); + const path nested_dest = dest / nested_dir_name; + TEST_REQUIRE(is_directory(nested_dest)); + for (auto& FI : files) { + path created = dest / FI.filename; + path nested_created = nested_dest / FI.filename; + TEST_CHECK(is_regular_file(created)); + TEST_CHECK(file_size(created) == FI.size); + TEST_CHECK(is_regular_file(nested_created)); + TEST_CHECK(file_size(nested_created) == FI.size); + } + } + +} +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_file/copy_file.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_file/copy_file.pass.cpp new file mode 100644 index 00000000000..0f43901f851 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_file/copy_file.pass.cpp @@ -0,0 +1,165 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// bool copy_file(const path& from, const path& to); +// bool copy_file(const path& from, const path& to, error_code& ec) noexcept; +// bool copy_file(const path& from, const path& to, copy_options options); +// bool copy_file(const path& from, const path& to, copy_options options, +// error_code& ec) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <chrono> +#include <thread> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; +namespace fs = std::experimental::filesystem; + +using CO = fs::copy_options; + +TEST_SUITE(filesystem_copy_file_test_suite) + +TEST_CASE(test_signatures) +{ + const path p; ((void)p); + const copy_options opts{}; ((void)opts); + std::error_code ec; ((void)ec); + ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p)), bool); + ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p, opts)), bool); + ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p, ec)), bool); + ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p, opts, ec)), bool); + ASSERT_NOT_NOEXCEPT(fs::copy_file(p, p)); + ASSERT_NOT_NOEXCEPT(fs::copy_file(p, p, opts)); + ASSERT_NOEXCEPT(fs::copy_file(p, p, ec)); + ASSERT_NOEXCEPT(fs::copy_file(p, p, opts, ec)); +} + +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::copy_file(f, t); + return false; + } catch (filesystem_error const& err) { + return err.path1() == f + && err.path2() == t + && 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); + const path dne = env.make_env_path("dne"); + { // exists(to) && equivalent(to, from) + std::error_code ec; + TEST_CHECK(fs::copy_file(file, file, ec) == false); + TEST_REQUIRE(ec); + TEST_CHECK(checkThrow(file, file, ec)); + } + { // exists(to) && !(skip_existing | overwrite_existing | update_existing) + std::error_code ec; + TEST_CHECK(fs::copy_file(file, file2, ec) == false); + TEST_REQUIRE(ec); + TEST_CHECK(checkThrow(file, file2, ec)); + } +} + +TEST_CASE(copy_file) +{ + scoped_test_env env; + const path file = env.create_file("file1", 42); + + { // !exists(to) + const path dest = env.make_env_path("dest1"); + std::error_code ec; + TEST_REQUIRE(fs::copy_file(file, dest, ec) == true); + TEST_CHECK(!ec); + TEST_CHECK(file_size(dest) == 42); + } + { // exists(to) && overwrite_existing + const path dest = env.create_file("dest2", 55); + std::error_code ec; + TEST_REQUIRE(fs::copy_file(file, dest, + copy_options::overwrite_existing, ec) == true); + TEST_CHECK(!ec); + TEST_CHECK(file_size(dest) == 42); + } + { // exists(to) && update_existing + using Sec = std::chrono::seconds; + const path older = env.create_file("older_file", 1); + + std::this_thread::sleep_for(Sec(2)); + const path from = env.create_file("update_from", 55); + + std::this_thread::sleep_for(Sec(2)); + const path newer = env.create_file("newer_file", 2); + + std::error_code ec; + TEST_REQUIRE(fs::copy_file(from, older, copy_options::update_existing, ec) == true); + TEST_CHECK(!ec); + TEST_CHECK(file_size(older) == 55); + + TEST_REQUIRE(fs::copy_file(from, newer, copy_options::update_existing, ec) == false); + TEST_CHECK(!ec); + TEST_CHECK(file_size(newer) == 2); + } + { // skip_existing + const path file2 = env.create_file("file2", 55); + std::error_code ec; + TEST_REQUIRE(fs::copy_file(file, file2, copy_options::skip_existing, ec) == false); + TEST_CHECK(!ec); + TEST_CHECK(file_size(file2) == 55); + } +} + +TEST_CASE(test_attributes_get_copied) +{ + scoped_test_env env; + 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; + TEST_REQUIRE(fs::copy_file(file, dest, ec) == true); + TEST_CHECK(!ec); + auto new_st = status(dest); + TEST_CHECK(new_st.permissions() == new_perms); +} + +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; + TEST_CHECK(fs::copy_file(file, dest, ec) == false); + TEST_CHECK(ec); + ec.clear(); + TEST_CHECK(fs::copy_file(dest, file, ec) == false); + TEST_CHECK(ec); +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_symlink/copy_symlink.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_symlink/copy_symlink.pass.cpp new file mode 100644 index 00000000000..a95f6e334d8 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_symlink/copy_symlink.pass.cpp @@ -0,0 +1,110 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// void copy_symlink(const path& existing_symlink, const path& new_symlink); +// void copy_symlink(const path& existing_symlink, const path& new_symlink, +// error_code& ec) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <chrono> +#include <thread> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; +namespace fs = std::experimental::filesystem; + +TEST_SUITE(filesystem_copy_symlink_test_suite) + +TEST_CASE(test_signatures) +{ + const path p; ((void)p); + std::error_code ec; ((void)ec); + ASSERT_NOT_NOEXCEPT(fs::copy_symlink(p, p)); + ASSERT_NOEXCEPT(fs::copy_symlink(p, p, ec)); +} + + +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::copy_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); + const path sym = env.create_symlink(file, "sym"); + const path dir = env.create_dir("dir"); + const path dne = env.make_env_path("dne"); + { // from is a file, not a symlink + std::error_code ec; + fs::copy_symlink(file, dne, ec); + TEST_REQUIRE(ec); + TEST_CHECK(checkThrow(file, dne, ec)); + } + { // from is a file, not a symlink + std::error_code ec; + fs::copy_symlink(dir, dne, ec); + TEST_REQUIRE(ec); + TEST_CHECK(checkThrow(dir, dne, ec)); + } + { // destination exists + std::error_code ec; + fs::copy_symlink(sym, file2, ec); + TEST_REQUIRE(ec); + } +} + +TEST_CASE(copy_symlink_basic) +{ + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path dir_sym = env.create_symlink(dir, "dir_sym"); + const path file = env.create_file("file", 42); + const path file_sym = env.create_symlink(file, "file_sym"); + { // test for directory symlinks + const path dest = env.make_env_path("dest1"); + std::error_code ec; + fs::copy_symlink(dir_sym, dest, ec); + TEST_REQUIRE(!ec); + TEST_CHECK(is_symlink(dest)); + TEST_CHECK(equivalent(dest, dir)); + } + { // test for file symlinks + const path dest = env.make_env_path("dest2"); + std::error_code ec; + fs::copy_symlink(file_sym, dest, ec); + TEST_REQUIRE(!ec); + TEST_CHECK(is_symlink(dest)); + TEST_CHECK(equivalent(dest, file)); + } +} + + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directories/create_directories.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directories/create_directories.pass.cpp new file mode 100644 index 00000000000..7507042aec6 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directories/create_directories.pass.cpp @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// bool create_directories(const path& p); +// bool create_directories(const path& p, error_code& ec) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <chrono> +#include <thread> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; +namespace fs = std::experimental::filesystem; + +TEST_SUITE(filesystem_create_directories_test_suite) + +TEST_CASE(test_signatures) +{ + const path p; ((void)p); + std::error_code ec; ((void)ec); + ASSERT_SAME_TYPE(decltype(fs::create_directories(p)), bool); + ASSERT_SAME_TYPE(decltype(fs::create_directories(p, ec)), bool); + ASSERT_NOT_NOEXCEPT(fs::create_directories(p)); + ASSERT_NOEXCEPT(fs::create_directories(p, ec)); +} + +TEST_CASE(create_existing_directory) +{ + scoped_test_env env; + const path dir = env.create_dir("dir1"); + std::error_code ec; + TEST_CHECK(fs::create_directories(dir, ec) == false); + TEST_CHECK(!ec); + TEST_CHECK(is_directory(dir)); +} + +TEST_CASE(create_directory_one_level) +{ + scoped_test_env env; + const path dir = env.make_env_path("dir1"); + std::error_code ec; + TEST_CHECK(fs::create_directories(dir, ec) == true); + TEST_CHECK(!ec); + TEST_CHECK(is_directory(dir)); +} + +TEST_CASE(create_directories_multi_level) +{ + scoped_test_env env; + const path dir = env.make_env_path("dir1/dir2/dir3"); + std::error_code ec; + TEST_CHECK(fs::create_directories(dir, ec) == true); + TEST_CHECK(!ec); + TEST_CHECK(is_directory(dir)); +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directory/create_directory.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directory/create_directory.pass.cpp new file mode 100644 index 00000000000..6a7b8453801 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directory/create_directory.pass.cpp @@ -0,0 +1,104 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// bool create_directory(const path& p); +// bool create_directory(const path& p, error_code& ec) noexcept; +// bool create_directory(const path& p, const path& attr); +// bool create_directory(const path& p, const path& attr, error_code& ec) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <chrono> +#include <thread> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; +namespace fs = std::experimental::filesystem; + +TEST_SUITE(filesystem_create_directory_test_suite) + +TEST_CASE(test_signatures) +{ + const path p; ((void)p); + std::error_code ec; ((void)ec); + ASSERT_SAME_TYPE(decltype(fs::create_directory(p)), bool); + ASSERT_SAME_TYPE(decltype(fs::create_directory(p, ec)), bool); + ASSERT_SAME_TYPE(decltype(fs::create_directory(p, p)), bool); + ASSERT_SAME_TYPE(decltype(fs::create_directory(p, p, ec)), bool); + ASSERT_NOT_NOEXCEPT(fs::create_directory(p)); + ASSERT_NOEXCEPT(fs::create_directory(p, ec)); + ASSERT_NOT_NOEXCEPT(fs::create_directory(p, p)); + ASSERT_NOEXCEPT(fs::create_directory(p, p, ec)); +} + + +TEST_CASE(create_existing_directory) +{ + scoped_test_env env; + const path dir = env.create_dir("dir1"); + std::error_code ec; + TEST_CHECK(fs::create_directory(dir, ec) == false); + TEST_CHECK(!ec); + TEST_CHECK(is_directory(dir)); + // Test throwing version + TEST_CHECK(fs::create_directory(dir) == false); +} + +TEST_CASE(create_directory_one_level) +{ + scoped_test_env env; + const path dir = env.make_env_path("dir1"); + std::error_code ec; + TEST_CHECK(fs::create_directory(dir, ec) == true); + TEST_CHECK(!ec); + TEST_CHECK(is_directory(dir)); + + auto st = status(dir); + perms owner_perms = perms::owner_all; + perms gperms = perms::group_all; + perms other_perms = perms::others_read | perms::others_exec; +#if defined(__APPLE__) || defined(__FreeBSD__) + gperms = perms::group_read | perms::group_exec; +#endif + TEST_CHECK((st.permissions() & perms::owner_all) == owner_perms); + TEST_CHECK((st.permissions() & perms::group_all) == gperms); + TEST_CHECK((st.permissions() & perms::others_all) == other_perms); +} + +TEST_CASE(create_directory_multi_level) +{ + scoped_test_env env; + const path dir = env.make_env_path("dir1/dir2"); + const path dir1 = env.make_env_path("dir1"); + std::error_code ec; + TEST_CHECK(fs::create_directory(dir, ec) == false); + TEST_CHECK(ec); + TEST_CHECK(!is_directory(dir)); + TEST_CHECK(!is_directory(dir1)); +} + +TEST_CASE(dest_is_file) +{ + scoped_test_env env; + const path file = env.create_file("file", 42); + std::error_code ec; + TEST_CHECK(fs::create_directory(file, ec) == false); + TEST_CHECK(ec); + TEST_CHECK(is_regular_file(file)); +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directory/create_directory_with_attributes.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directory/create_directory_with_attributes.pass.cpp new file mode 100644 index 00000000000..638fca23636 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directory/create_directory_with_attributes.pass.cpp @@ -0,0 +1,103 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// bool create_directory(const path& p, const path& attr); +// bool create_directory(const path& p, const path& attr, error_code& ec) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <chrono> +#include <thread> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; +namespace fs = std::experimental::filesystem; + +TEST_SUITE(filesystem_create_directory_test_suite) + +TEST_CASE(test_signatures) +{ + const path p; ((void)p); + std::error_code ec; ((void)ec); + ASSERT_SAME_TYPE(decltype(fs::create_directory(p, p)), bool); + ASSERT_SAME_TYPE(decltype(fs::create_directory(p, p, ec)), bool); + ASSERT_NOT_NOEXCEPT(fs::create_directory(p, p)); + ASSERT_NOEXCEPT(fs::create_directory(p, p, ec)); +} + +TEST_CASE(create_existing_directory) +{ + scoped_test_env env; + const path dir = env.create_dir("dir1"); + const path dir2 = env.create_dir("dir2"); + + const perms orig_p = status(dir).permissions(); + permissions(dir2, perms::none); + + std::error_code ec; + TEST_CHECK(fs::create_directory(dir, dir2, ec) == false); + TEST_CHECK(!ec); + + // Check that the permissions were unchanged + TEST_CHECK(orig_p == status(dir).permissions()); + + // Test throwing version + TEST_CHECK(fs::create_directory(dir, dir2) == false); +} + +TEST_CASE(create_directory_one_level) +{ + scoped_test_env env; + const path dir = env.make_env_path("dir1"); + const path attr_dir = env.create_dir("dir2"); + permissions(attr_dir, perms::none); + + std::error_code ec; + TEST_CHECK(fs::create_directory(dir, attr_dir, ec) == true); + TEST_CHECK(!ec); + TEST_CHECK(is_directory(dir)); + + // Check that the new directory has the same permissions as attr_dir + auto st = status(dir); + TEST_CHECK(st.permissions() == perms::none); +} + +TEST_CASE(create_directory_multi_level) +{ + scoped_test_env env; + const path dir = env.make_env_path("dir1/dir2"); + const path dir1 = env.make_env_path("dir1"); + const path attr_dir = env.create_dir("attr_dir"); + std::error_code ec; + TEST_CHECK(fs::create_directory(dir, attr_dir, ec) == false); + TEST_CHECK(ec); + TEST_CHECK(!is_directory(dir)); + TEST_CHECK(!is_directory(dir1)); +} + +TEST_CASE(dest_is_file) +{ + scoped_test_env env; + const path file = env.create_file("file", 42); + const path attr_dir = env.create_dir("attr_dir"); + std::error_code ec; + TEST_CHECK(fs::create_directory(file, attr_dir, ec) == false); + TEST_CHECK(ec); + TEST_CHECK(is_regular_file(file)); +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directory_symlink/create_directory_symlink.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directory_symlink/create_directory_symlink.pass.cpp new file mode 100644 index 00000000000..e0473754cc8 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directory_symlink/create_directory_symlink.pass.cpp @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// void create_directory_symlink(const path& existing_symlink, const path& new_symlink); +// void create_directory_symlink(const path& existing_symlink, const path& new_symlink, +// error_code& ec) noexcept; + +#include <experimental/filesystem> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; +namespace fs = std::experimental::filesystem; + +TEST_SUITE(filesystem_create_directory_symlink_test_suite) + +TEST_CASE(test_signatures) +{ + const path p; ((void)p); + std::error_code ec; ((void)ec); + ASSERT_NOT_NOEXCEPT(fs::create_directory_symlink(p, p)); + ASSERT_NOEXCEPT(fs::create_directory_symlink(p, p, ec)); +} + +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); + const path sym = env.create_symlink(file, "sym"); + { // destination exists + std::error_code ec; + fs::create_directory_symlink(sym, file2, ec); + TEST_REQUIRE(ec); + } +} + +TEST_CASE(create_directory_symlink_basic) +{ + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path dir_sym = env.create_symlink(dir, "dir_sym"); + + const path dest = env.make_env_path("dest1"); + std::error_code ec; + fs::create_directory_symlink(dir_sym, dest, ec); + TEST_REQUIRE(!ec); + TEST_CHECK(is_symlink(dest)); + TEST_CHECK(equivalent(dest, dir)); +} + + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_hard_link/create_hard_link.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_hard_link/create_hard_link.pass.cpp new file mode 100644 index 00000000000..4a865fdee7e --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_hard_link/create_hard_link.pass.cpp @@ -0,0 +1,90 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// void create_hard_link(const path& existing_symlink, const path& new_symlink); +// void create_hard_link(const path& existing_symlink, const path& new_symlink, +// error_code& ec) noexcept; + +#include <experimental/filesystem> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; +namespace fs = std::experimental::filesystem; + +TEST_SUITE(filesystem_create_hard_link_test_suite) + +TEST_CASE(test_signatures) +{ + const path p; ((void)p); + std::error_code ec; ((void)ec); + ASSERT_NOT_NOEXCEPT(fs::create_hard_link(p, p)); + ASSERT_NOEXCEPT(fs::create_hard_link(p, p, ec)); +} + +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); + const path sym = env.create_symlink(file, "sym"); + { // destination exists + std::error_code ec; + fs::create_hard_link(sym, file2, ec); + TEST_REQUIRE(ec); + } +} + +TEST_CASE(create_file_hard_link) +{ + scoped_test_env env; + const path file = env.create_file("file"); + const path dest = env.make_env_path("dest1"); + std::error_code ec; + TEST_CHECK(hard_link_count(file) == 1); + fs::create_hard_link(file, dest, ec); + TEST_REQUIRE(!ec); + TEST_CHECK(exists(dest)); + TEST_CHECK(equivalent(dest, file)); + TEST_CHECK(hard_link_count(file) == 2); +} + +TEST_CASE(create_directory_hard_link_fails) +{ + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path dest = env.make_env_path("dest2"); + std::error_code ec; + + fs::create_hard_link(dir, dest, ec); + TEST_REQUIRE(ec); +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_symlink/create_symlink.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_symlink/create_symlink.pass.cpp new file mode 100644 index 00000000000..35ba57f3ab4 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_symlink/create_symlink.pass.cpp @@ -0,0 +1,92 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// void create_symlink(const path& existing_symlink, const path& new_symlink); +// void create_symlink(const path& existing_symlink, const path& new_symlink, +// error_code& ec) noexcept; + +#include <experimental/filesystem> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; +namespace fs = std::experimental::filesystem; + +TEST_SUITE(filesystem_create_symlink_test_suite) + +TEST_CASE(test_signatures) +{ + const path p; ((void)p); + std::error_code ec; ((void)ec); + ASSERT_NOT_NOEXCEPT(fs::create_symlink(p, p)); + ASSERT_NOEXCEPT(fs::create_symlink(p, p, ec)); +} + +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); + const path sym = env.create_symlink(file, "sym"); + { // destination exists + std::error_code ec; + fs::create_symlink(sym, file2, ec); + TEST_REQUIRE(ec); + } +} + +TEST_CASE(create_symlink_basic) +{ + scoped_test_env env; + const path file = env.create_file("file", 42); + const path file_sym = env.create_symlink(file, "file_sym"); + const path dir = env.create_dir("dir"); + const path dir_sym = env.create_symlink(dir, "dir_sym"); + { + const path dest = env.make_env_path("dest1"); + std::error_code ec; + fs::create_symlink(file_sym, dest, ec); + TEST_REQUIRE(!ec); + TEST_CHECK(is_symlink(dest)); + TEST_CHECK(equivalent(dest, file)); + } + { + const path dest = env.make_env_path("dest2"); + std::error_code ec; + fs::create_symlink(dir_sym, dest, ec); + TEST_REQUIRE(!ec); + TEST_CHECK(is_symlink(dest)); + TEST_CHECK(equivalent(dest, dir)); + } +} + + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.current_path/current_path.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.current_path/current_path.pass.cpp new file mode 100644 index 00000000000..9d004ab854c --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.current_path/current_path.pass.cpp @@ -0,0 +1,93 @@ +//===----------------------------------------------------------------------===// +// +// 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 current_path(); +// path current_path(error_code& ec); +// void current_path(path const&); +// void current_path(path const&, std::error_code& ec) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(filesystem_current_path_path_test_suite) + +TEST_CASE(current_path_signature_test) +{ + const path p; ((void)p); + std::error_code ec; ((void)ec); + ASSERT_NOT_NOEXCEPT(current_path()); + ASSERT_NOT_NOEXCEPT(current_path(ec)); + ASSERT_NOT_NOEXCEPT(current_path(p)); + ASSERT_NOEXCEPT(current_path(p, ec)); +} + +TEST_CASE(current_path_test) +{ + std::error_code ec; + const path p = current_path(ec); + TEST_REQUIRE(!ec); + TEST_CHECK(p.is_absolute()); + TEST_CHECK(is_directory(p)); + + const path p2 = current_path(); + TEST_CHECK(p2 == p); +} + +TEST_CASE(current_path_after_change_test) +{ + const path new_path = StaticEnv::Dir; + current_path(new_path); + TEST_CHECK(current_path() == new_path); +} + +TEST_CASE(current_path_is_file_test) +{ + const path p = StaticEnv::File; + std::error_code ec; + const path old_p = current_path(); + current_path(p, ec); + TEST_CHECK(ec); + TEST_CHECK(old_p == current_path()); +} + +TEST_CASE(set_to_non_absolute_path) +{ + const path base = StaticEnv::Dir; + current_path(base); + const path p = StaticEnv::Dir2.filename(); + std::error_code ec; + current_path(p, ec); + TEST_CHECK(!ec); + const path new_cwd = current_path(); + TEST_CHECK(new_cwd == StaticEnv::Dir2); + TEST_CHECK(new_cwd.is_absolute()); +} + +TEST_CASE(set_to_empty) +{ + const path p = ""; + std::error_code ec; + const path old_p = current_path(); + current_path(p, ec); + TEST_CHECK(ec); + TEST_CHECK(old_p == current_path()); +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.equivalent/equivalent.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.equivalent/equivalent.pass.cpp new file mode 100644 index 00000000000..621ff8305fc --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.equivalent/equivalent.pass.cpp @@ -0,0 +1,88 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// bool equivalent(path const& lhs, path const& rhs); +// bool equivalent(path const& lhs, path const& rhs, std::error_code& ec) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(equivalent_test_suite) + +TEST_CASE(signature_test) +{ + const path p; ((void)p); + std::error_code ec; ((void)ec); + ASSERT_NOEXCEPT(equivalent(p, p, ec)); + ASSERT_NOT_NOEXCEPT(equivalent(p, p)); +} + +TEST_CASE(equivalent_test) +{ + struct TestCase { + path lhs; + path rhs; + bool expect; + }; + const TestCase testCases[] = { + {StaticEnv::Dir, StaticEnv::Dir, true}, + {StaticEnv::File, StaticEnv::Dir, false}, + {StaticEnv::Dir, StaticEnv::SymlinkToDir, true}, + {StaticEnv::Dir, StaticEnv::SymlinkToFile, false}, + {StaticEnv::File, StaticEnv::File, true}, + {StaticEnv::File, StaticEnv::SymlinkToFile, true}, + }; + for (auto& TC : testCases) { + std::error_code ec; + TEST_CHECK(equivalent(TC.lhs, TC.rhs, ec) == TC.expect); + TEST_CHECK(!ec); + } +} + +TEST_CASE(equivalent_reports_double_dne) +{ + const path E = StaticEnv::File; + const path DNE = StaticEnv::DNE; + { // Test that no exception is thrown if one of the paths exists + TEST_CHECK(equivalent(E, DNE) == false); + TEST_CHECK(equivalent(DNE, E) == false); + } + { // Test that an exception is thrown if both paths do not exist. + TEST_CHECK_THROW(filesystem_error, equivalent(DNE, DNE)); + } + { + std::error_code ec; + TEST_CHECK(equivalent(DNE, DNE, ec) == false); + TEST_CHECK(ec); + } +} + +TEST_CASE(equivalent_is_other_succeeds) +{ + scoped_test_env env; + path const file = env.create_file("file", 42); + const path hl1 = env.create_hardlink(file, "hl1"); + const path hl2 = env.create_hardlink(file, "hl2"); + TEST_CHECK(equivalent(file, hl1)); + TEST_CHECK(equivalent(file, hl2)); + TEST_CHECK(equivalent(hl1, hl2)); +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.exists/exists.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.exists/exists.pass.cpp new file mode 100644 index 00000000000..460b8be6b12 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.exists/exists.pass.cpp @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// bool exists(file_status s) noexcept +// bool exists(path const& p); +// bool exists(path const& p, std::error_code& ec) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(exists_test_suite) + +TEST_CASE(signature_test) +{ + file_status s; ((void)s); + const path p; ((void)p); + std::error_code ec; ((void)ec); + ASSERT_NOEXCEPT(exists(s)); + ASSERT_NOEXCEPT(exists(p, ec)); + ASSERT_NOT_NOEXCEPT(exists(p)); +} + +TEST_CASE(exists_status_test) +{ + struct TestCase { + file_type type; + bool expect; + }; + const TestCase testCases[] = { + {file_type::none, false}, + {file_type::not_found, false}, + {file_type::regular, true}, + {file_type::directory, true}, + {file_type::symlink, true}, + {file_type::block, true}, + {file_type::character, true}, + {file_type::fifo, true}, + {file_type::socket, true}, + {file_type::unknown, true} + }; + for (auto& TC : testCases) { + file_status s(TC.type); + TEST_CHECK(exists(s) == TC.expect); + } +} + +TEST_CASE(test_exist_not_found) +{ + const path p = StaticEnv::DNE; + TEST_CHECK(exists(p) == false); +} + +TEST_CASE(test_exists_fails) +{ + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path file = env.create_file("dir/file", 42); + permissions(dir, perms::none); + + std::error_code ec; + TEST_CHECK(exists(file, ec) == false); + TEST_CHECK(ec); + + TEST_CHECK_THROW(filesystem_error, exists(file)); +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.file_size/file_size.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.file_size/file_size.pass.cpp new file mode 100644 index 00000000000..460e42dd1c3 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.file_size/file_size.pass.cpp @@ -0,0 +1,79 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// uintmax_t file_size(const path& p); +// uintmax_t file_size(const path& p, std::error_code& ec) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(file_size_test_suite) + +TEST_CASE(signature_test) +{ + const path p; ((void)p); + std::error_code ec; ((void)ec); + ASSERT_SAME_TYPE(decltype(file_size(p)), uintmax_t); + ASSERT_SAME_TYPE(decltype(file_size(p, ec)), uintmax_t); + ASSERT_NOT_NOEXCEPT(file_size(p)); + ASSERT_NOEXCEPT(file_size(p, ec)); +} + +TEST_CASE(file_size_empty_test) +{ + const path p = StaticEnv::EmptyFile; + TEST_CHECK(file_size(p) == 0); + std::error_code ec; + TEST_CHECK(file_size(p, ec) == 0); +} + +TEST_CASE(file_size_non_empty) +{ + scoped_test_env env; + const path p = env.create_file("file", 42); + TEST_CHECK(file_size(p) == 42); + std::error_code ec; + TEST_CHECK(file_size(p, ec) == 42); +} + +TEST_CASE(symlink_test_case) +{ + const path p = StaticEnv::File; + const path p2 = StaticEnv::SymlinkToFile; + TEST_CHECK(file_size(p) == file_size(p2)); +} + +TEST_CASE(file_size_error_cases) +{ + const path testCases[] = { + StaticEnv::Dir, + StaticEnv::SymlinkToDir, + StaticEnv::BadSymlink, + StaticEnv::DNE + }; + const uintmax_t expect = static_cast<uintmax_t>(-1); + for (auto& TC : testCases) { + std::error_code ec; + TEST_CHECK(file_size(TC, ec) == expect); + TEST_CHECK(ec); + } +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.hard_lk_ct/hard_link_count.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.hard_lk_ct/hard_link_count.pass.cpp new file mode 100644 index 00000000000..abc50e9c6a4 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.hard_lk_ct/hard_link_count.pass.cpp @@ -0,0 +1,86 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// uintmax_t hard_link_count(const path& p); +// uintmax_t hard_link_count(const path& p, std::error_code& ec) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(hard_link_count_test_suite) + +TEST_CASE(signature_test) +{ + const path p; ((void)p); + std::error_code ec; ((void)ec); + ASSERT_SAME_TYPE(decltype(hard_link_count(p)), uintmax_t); + ASSERT_SAME_TYPE(decltype(hard_link_count(p, ec)), uintmax_t); + ASSERT_NOT_NOEXCEPT(hard_link_count(p)); + ASSERT_NOEXCEPT(hard_link_count(p, ec)); +} + +TEST_CASE(hard_link_count_for_file) +{ + TEST_CHECK(hard_link_count(StaticEnv::File) == 1); + std::error_code ec; + TEST_CHECK(hard_link_count(StaticEnv::File, ec) == 1); +} + +TEST_CASE(hard_link_count_for_directory) +{ + uintmax_t DirExpect = 3; + uintmax_t Dir3Expect = 2; +#if defined(__APPLE__) + DirExpect += 2; + Dir3Expect += 1; +#endif + TEST_CHECK(hard_link_count(StaticEnv::Dir) == DirExpect); + TEST_CHECK(hard_link_count(StaticEnv::Dir3) == Dir3Expect); + + std::error_code ec; + TEST_CHECK(hard_link_count(StaticEnv::Dir, ec) == DirExpect); + TEST_CHECK(hard_link_count(StaticEnv::Dir3, ec) == Dir3Expect); +} +TEST_CASE(hard_link_count_increments_test) +{ + scoped_test_env env; + const path file = env.create_file("file", 42); + TEST_CHECK(hard_link_count(file) == 1); + + env.create_hardlink(file, "file_hl"); + TEST_CHECK(hard_link_count(file) == 2); +} + + +TEST_CASE(hard_link_count_error_cases) +{ + const path testCases[] = { + StaticEnv::BadSymlink, + StaticEnv::DNE + }; + const uintmax_t expect = static_cast<uintmax_t>(-1); + for (auto& TC : testCases) { + std::error_code ec; + TEST_CHECK(hard_link_count(TC, ec) == expect); + TEST_CHECK(ec); + } +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_block_file/is_block_file.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_block_file/is_block_file.pass.cpp new file mode 100644 index 00000000000..dee28aa5be6 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_block_file/is_block_file.pass.cpp @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// bool is_block_file(file_status s) noexcept +// bool is_block_file(path const& p); +// bool is_block_file(path const& p, std::error_code& ec) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(is_block_file_test_suite) + +TEST_CASE(signature_test) +{ + file_status s; ((void)s); + const path p; ((void)p); + std::error_code ec; ((void)ec); + ASSERT_NOEXCEPT(is_block_file(s)); + ASSERT_NOEXCEPT(is_block_file(p, ec)); + ASSERT_NOT_NOEXCEPT(is_block_file(p)); +} + +TEST_CASE(is_block_file_status_test) +{ + struct TestCase { + file_type type; + bool expect; + }; + const TestCase testCases[] = { + {file_type::none, false}, + {file_type::not_found, false}, + {file_type::regular, false}, + {file_type::directory, false}, + {file_type::symlink, false}, + {file_type::block, true}, + {file_type::character, false}, + {file_type::fifo, false}, + {file_type::socket, false}, + {file_type::unknown, false} + }; + for (auto& TC : testCases) { + file_status s(TC.type); + TEST_CHECK(is_block_file(s) == TC.expect); + } +} + +TEST_CASE(test_exist_not_found) +{ + const path p = StaticEnv::DNE; + TEST_CHECK(is_block_file(p) == false); +} + +TEST_CASE(test_is_block_file_fails) +{ + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path file = env.create_file("dir/file", 42); + permissions(dir, perms::none); + + std::error_code ec; + TEST_CHECK(is_block_file(file, ec) == false); + TEST_CHECK(ec); + + TEST_CHECK_THROW(filesystem_error, is_block_file(file)); +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_char_file/is_character_file.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_char_file/is_character_file.pass.cpp new file mode 100644 index 00000000000..2de42bf2097 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_char_file/is_character_file.pass.cpp @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// bool is_character_file(file_status s) noexcept +// bool is_character_file(path const& p); +// bool is_character_file(path const& p, std::error_code& ec) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(is_character_file_test_suite) + +TEST_CASE(signature_test) +{ + file_status s; ((void)s); + const path p; ((void)p); + std::error_code ec; ((void)ec); + ASSERT_NOEXCEPT(is_character_file(s)); + ASSERT_NOEXCEPT(is_character_file(p, ec)); + ASSERT_NOT_NOEXCEPT(is_character_file(p)); +} + +TEST_CASE(is_character_file_status_test) +{ + struct TestCase { + file_type type; + bool expect; + }; + const TestCase testCases[] = { + {file_type::none, false}, + {file_type::not_found, false}, + {file_type::regular, false}, + {file_type::directory, false}, + {file_type::symlink, false}, + {file_type::block, false}, + {file_type::character, true}, + {file_type::fifo, false}, + {file_type::socket, false}, + {file_type::unknown, false} + }; + for (auto& TC : testCases) { + file_status s(TC.type); + TEST_CHECK(is_character_file(s) == TC.expect); + } +} + +TEST_CASE(test_exist_not_found) +{ + const path p = StaticEnv::DNE; + TEST_CHECK(is_character_file(p) == false); +} + +TEST_CASE(test_is_character_file_fails) +{ + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path file = env.create_file("dir/file", 42); + permissions(dir, perms::none); + + std::error_code ec; + TEST_CHECK(is_character_file(file, ec) == false); + TEST_CHECK(ec); + + TEST_CHECK_THROW(filesystem_error, is_character_file(file)); +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_directory/is_directory.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_directory/is_directory.pass.cpp new file mode 100644 index 00000000000..d6ecb1a1e68 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_directory/is_directory.pass.cpp @@ -0,0 +1,91 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// bool is_directory(file_status s) noexcept +// bool is_directory(path const& p); +// bool is_directory(path const& p, std::error_code& ec) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(is_directory_test_suite) + +TEST_CASE(signature_test) +{ + file_status s; ((void)s); + const path p; ((void)p); + std::error_code ec; ((void)ec); + ASSERT_NOEXCEPT(is_directory(s)); + ASSERT_NOEXCEPT(is_directory(p, ec)); + ASSERT_NOT_NOEXCEPT(is_directory(p)); +} + +TEST_CASE(is_directory_status_test) +{ + struct TestCase { + file_type type; + bool expect; + }; + const TestCase testCases[] = { + {file_type::none, false}, + {file_type::not_found, false}, + {file_type::regular, false}, + {file_type::directory, true}, + {file_type::symlink, false}, + {file_type::block, false}, + {file_type::character, false}, + {file_type::fifo, false}, + {file_type::socket, false}, + {file_type::unknown, false} + }; + for (auto& TC : testCases) { + file_status s(TC.type); + TEST_CHECK(is_directory(s) == TC.expect); + } +} + +TEST_CASE(test_exist_not_found) +{ + const path p = StaticEnv::DNE; + TEST_CHECK(is_directory(p) == false); +} + +TEST_CASE(static_env_test) +{ + TEST_CHECK(is_directory(StaticEnv::Dir)); + TEST_CHECK(is_directory(StaticEnv::SymlinkToDir)); + TEST_CHECK(!is_directory(StaticEnv::File)); +} + +TEST_CASE(test_is_directory_fails) +{ + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path dir2 = env.create_dir("dir/dir2"); + permissions(dir, perms::none); + + std::error_code ec; + TEST_CHECK(is_directory(dir2, ec) == false); + TEST_CHECK(ec); + + TEST_CHECK_THROW(filesystem_error, is_directory(dir2)); +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_empty/is_empty.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_empty/is_empty.pass.cpp new file mode 100644 index 00000000000..ba07d09d10d --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_empty/is_empty.pass.cpp @@ -0,0 +1,80 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// bool is_empty(path const& p); +// bool is_empty(path const& p, std::error_code& ec) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(is_empty_test_suite) + +TEST_CASE(signature_test) +{ + const path p; ((void)p); + std::error_code ec; ((void)ec); + ASSERT_NOEXCEPT(is_empty(p, ec)); + ASSERT_NOT_NOEXCEPT(is_empty(p)); +} + +TEST_CASE(test_exist_not_found) +{ + const path p = StaticEnv::DNE; + std::error_code ec; + TEST_CHECK(is_empty(p, ec) == false); + TEST_CHECK(ec); + TEST_CHECK_THROW(filesystem_error, is_empty(p)); +} + +TEST_CASE(test_is_empty_directory) +{ + TEST_CHECK(!is_empty(StaticEnv::Dir)); + TEST_CHECK(!is_empty(StaticEnv::SymlinkToDir)); +} + +TEST_CASE(test_is_empty_directory_dynamic) +{ + scoped_test_env env; + TEST_CHECK(is_empty(env.test_root)); + env.create_file("foo", 42); + TEST_CHECK(!is_empty(env.test_root)); +} + +TEST_CASE(test_is_empty_file) +{ + TEST_CHECK(is_empty(StaticEnv::EmptyFile)); + TEST_CHECK(!is_empty(StaticEnv::NonEmptyFile)); +} + +TEST_CASE(test_is_empty_fails) +{ + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path dir2 = env.create_dir("dir/dir2"); + permissions(dir, perms::none); + + std::error_code ec; + TEST_CHECK(is_empty(dir2, ec) == false); + TEST_CHECK(ec); + + TEST_CHECK_THROW(filesystem_error, is_empty(dir2)); +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_fifo/is_fifo.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_fifo/is_fifo.pass.cpp new file mode 100644 index 00000000000..44892f65d86 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_fifo/is_fifo.pass.cpp @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// bool is_fifo(file_status s) noexcept +// bool is_fifo(path const& p); +// bool is_fifo(path const& p, std::error_code& ec) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(is_fifo_test_suite) + +TEST_CASE(signature_test) +{ + file_status s; ((void)s); + const path p; ((void)p); + std::error_code ec; ((void)ec); + ASSERT_NOEXCEPT(is_fifo(s)); + ASSERT_NOEXCEPT(is_fifo(p, ec)); + ASSERT_NOT_NOEXCEPT(is_fifo(p)); +} + +TEST_CASE(is_fifo_status_test) +{ + struct TestCase { + file_type type; + bool expect; + }; + const TestCase testCases[] = { + {file_type::none, false}, + {file_type::not_found, false}, + {file_type::regular, false}, + {file_type::directory, false}, + {file_type::symlink, false}, + {file_type::block, false}, + {file_type::character, false}, + {file_type::fifo, true}, + {file_type::socket, false}, + {file_type::unknown, false} + }; + for (auto& TC : testCases) { + file_status s(TC.type); + TEST_CHECK(is_fifo(s) == TC.expect); + } +} + +TEST_CASE(test_exist_not_found) +{ + const path p = StaticEnv::DNE; + TEST_CHECK(is_fifo(p) == false); +} + +TEST_CASE(test_is_fifo_fails) +{ + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path file = env.create_file("dir/file", 42); + permissions(dir, perms::none); + + std::error_code ec; + TEST_CHECK(is_fifo(file, ec) == false); + TEST_CHECK(ec); + + TEST_CHECK_THROW(filesystem_error, is_fifo(file)); +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_other/is_other.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_other/is_other.pass.cpp new file mode 100644 index 00000000000..e86b66b4ea6 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_other/is_other.pass.cpp @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// bool is_other(file_status s) noexcept +// bool is_other(path const& p); +// bool is_other(path const& p, std::error_code& ec) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(is_other_test_suite) + +TEST_CASE(signature_test) +{ + file_status s; ((void)s); + const path p; ((void)p); + std::error_code ec; ((void)ec); + ASSERT_NOEXCEPT(is_other(s)); + ASSERT_NOEXCEPT(is_other(p, ec)); + ASSERT_NOT_NOEXCEPT(is_other(p)); +} + +TEST_CASE(is_other_status_test) +{ + struct TestCase { + file_type type; + bool expect; + }; + const TestCase testCases[] = { + {file_type::none, false}, + {file_type::not_found, false}, + {file_type::regular, false}, + {file_type::directory, false}, + {file_type::symlink, false}, + {file_type::block, true}, + {file_type::character, true}, + {file_type::fifo, true}, + {file_type::socket, true}, + {file_type::unknown, true} + }; + for (auto& TC : testCases) { + file_status s(TC.type); + TEST_CHECK(is_other(s) == TC.expect); + } +} + +TEST_CASE(test_exist_not_found) +{ + const path p = StaticEnv::DNE; + TEST_CHECK(is_other(p) == false); +} + +TEST_CASE(test_is_other_fails) +{ + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path file = env.create_file("dir/file", 42); + permissions(dir, perms::none); + + std::error_code ec; + TEST_CHECK(is_other(file, ec) == false); + TEST_CHECK(ec); + + TEST_CHECK_THROW(filesystem_error, is_other(file)); +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_regular_file/is_regular_file.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_regular_file/is_regular_file.pass.cpp new file mode 100644 index 00000000000..be68dcfc35d --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_regular_file/is_regular_file.pass.cpp @@ -0,0 +1,87 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// bool is_regular_file(file_status s) noexcept +// bool is_regular_file(path const& p); +// bool is_regular_file(path const& p, std::error_code& ec) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(is_regular_file_test_suite) + +TEST_CASE(signature_test) +{ + file_status s; ((void)s); + const path p; ((void)p); + std::error_code ec; ((void)ec); + ASSERT_NOEXCEPT(is_regular_file(s)); + ASSERT_NOEXCEPT(is_regular_file(p, ec)); + ASSERT_NOT_NOEXCEPT(is_regular_file(p)); +} + +TEST_CASE(is_regular_file_status_test) +{ + struct TestCase { + file_type type; + bool expect; + }; + const TestCase testCases[] = { + {file_type::none, false}, + {file_type::not_found, false}, + {file_type::regular, true}, + {file_type::directory, false}, + {file_type::symlink, false}, + {file_type::block, false}, + {file_type::character, false}, + {file_type::fifo, false}, + {file_type::socket, false}, + {file_type::unknown, false} + }; + for (auto& TC : testCases) { + file_status s(TC.type); + TEST_CHECK(is_regular_file(s) == TC.expect); + } +} + +TEST_CASE(test_exist_not_found) +{ + const path p = StaticEnv::DNE; + TEST_CHECK(is_regular_file(p) == false); + std::error_code ec; + TEST_CHECK(is_regular_file(p, ec) == false); + TEST_CHECK(ec); +} + +TEST_CASE(test_is_regular_file_fails) +{ + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path file = env.create_file("dir/file", 42); + permissions(dir, perms::none); + + std::error_code ec; + TEST_CHECK(is_regular_file(file, ec) == false); + TEST_CHECK(ec); + + TEST_CHECK_THROW(filesystem_error, is_regular_file(file)); +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_socket/is_socket.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_socket/is_socket.pass.cpp new file mode 100644 index 00000000000..49fd402eb54 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_socket/is_socket.pass.cpp @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// bool is_socket(file_status s) noexcept +// bool is_socket(path const& p); +// bool is_socket(path const& p, std::error_code& ec) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(is_socket_test_suite) + +TEST_CASE(signature_test) +{ + file_status s; ((void)s); + const path p; ((void)p); + std::error_code ec; ((void)ec); + ASSERT_NOEXCEPT(is_socket(s)); + ASSERT_NOEXCEPT(is_socket(p, ec)); + ASSERT_NOT_NOEXCEPT(is_socket(p)); +} + +TEST_CASE(is_socket_status_test) +{ + struct TestCase { + file_type type; + bool expect; + }; + const TestCase testCases[] = { + {file_type::none, false}, + {file_type::not_found, false}, + {file_type::regular, false}, + {file_type::directory, false}, + {file_type::symlink, false}, + {file_type::block, false}, + {file_type::character, false}, + {file_type::fifo, false}, + {file_type::socket, true}, + {file_type::unknown, false} + }; + for (auto& TC : testCases) { + file_status s(TC.type); + TEST_CHECK(is_socket(s) == TC.expect); + } +} + +TEST_CASE(test_exist_not_found) +{ + const path p = StaticEnv::DNE; + TEST_CHECK(is_socket(p) == false); +} + +TEST_CASE(test_is_socket_fails) +{ + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path file = env.create_file("dir/file", 42); + permissions(dir, perms::none); + + std::error_code ec; + TEST_CHECK(is_socket(file, ec) == false); + TEST_CHECK(ec); + + TEST_CHECK_THROW(filesystem_error, is_socket(file)); +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_symlink/is_symlink.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_symlink/is_symlink.pass.cpp new file mode 100644 index 00000000000..3de00297868 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_symlink/is_symlink.pass.cpp @@ -0,0 +1,105 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// bool is_symlink(file_status s) noexcept +// bool is_symlink(path const& p); +// bool is_symlink(path const& p, std::error_code& ec) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(is_symlink_test_suite) + +TEST_CASE(signature_test) +{ + file_status s; ((void)s); + const path p; ((void)p); + std::error_code ec; ((void)ec); + ASSERT_NOEXCEPT(is_symlink(s)); + ASSERT_NOEXCEPT(is_symlink(p, ec)); + ASSERT_NOT_NOEXCEPT(is_symlink(p)); +} + +TEST_CASE(is_symlink_status_test) +{ + struct TestCase { + file_type type; + bool expect; + }; + const TestCase testCases[] = { + {file_type::none, false}, + {file_type::not_found, false}, + {file_type::regular, false}, + {file_type::directory, false}, + {file_type::symlink, true}, + {file_type::block, false}, + {file_type::character, false}, + {file_type::fifo, false}, + {file_type::socket, false}, + {file_type::unknown, false} + }; + for (auto& TC : testCases) { + file_status s(TC.type); + TEST_CHECK(is_symlink(s) == TC.expect); + } +} + +TEST_CASE(static_env_test) +{ + struct TestCase { + path p; + bool expect; + }; + const TestCase testCases[] = { + {StaticEnv::File, false}, + {StaticEnv::Dir, false}, + {StaticEnv::SymlinkToFile, true}, + {StaticEnv::SymlinkToDir, true}, + {StaticEnv::BadSymlink, true} + }; + for (auto& TC : testCases) { + TEST_CHECK(is_symlink(TC.p) == TC.expect); + } +} + +TEST_CASE(test_exist_not_found) +{ + const path p = StaticEnv::DNE; + TEST_CHECK(is_symlink(p) == false); + std::error_code ec; + TEST_CHECK(is_symlink(p, ec) == false); + TEST_CHECK(ec); +} + +TEST_CASE(test_is_symlink_fails) +{ + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path file = env.create_file("dir/file", 42); + permissions(dir, perms::none); + + std::error_code ec; + TEST_CHECK(is_symlink(file, ec) == false); + TEST_CHECK(ec); + + TEST_CHECK_THROW(filesystem_error, is_symlink(file)); +} + +TEST_SUITE_END() 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 new file mode 100644 index 00000000000..bcba502f417 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp @@ -0,0 +1,297 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// file_time_type last_write_time(const path& p); +// file_time_type last_write_time(const path& p, std::error_code& ec) noexcept; +// void last_write_time(const path& p, file_time_type new_time); +// void last_write_time(const path& p, file_time_type new_type, +// std::error_code& ec) noexcept; + + +#include <experimental/filesystem> +#include <type_traits> +#include <chrono> +#include <thread> +#include <fstream> +#include <iostream> +#include <cstdlib> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +#include <sys/stat.h> + +using namespace std::experimental::filesystem; + + +std::pair<std::time_t, std::time_t> GetTimes(path const& p) { + using Clock = file_time_type::clock; + struct ::stat st; + if (::stat(p.c_str(), &st) == -1) { + std::error_code ec(errno, std::generic_category()); +#ifndef TEST_HAS_NO_EXCEPTIONS + throw ec; +#else + std::cerr << ec.message() << std::endl; + std::exit(EXIT_FAILURE); +#endif + } + return {st.st_atime, st.st_mtime}; +} + +std::time_t LastAccessTime(path const& p) { + return GetTimes(p).first; +} + +std::time_t LastWriteTime(path const& p) { + return GetTimes(p).second; +} + +std::pair<std::time_t, std::time_t> GetSymlinkTimes(path const& p) { + using Clock = file_time_type::clock; + struct ::stat st; + if (::lstat(p.c_str(), &st) == -1) { + std::error_code ec(errno, std::generic_category()); +#ifndef TEST_HAS_NO_EXCEPTIONS + throw ec; +#else + std::cerr << ec.message() << std::endl; + std::exit(EXIT_FAILURE); +#endif + } + return {st.st_atime, st.st_mtime}; +} + + +TEST_SUITE(exists_test_suite) + +TEST_CASE(signature_test) +{ + const file_time_type t; + const path p; ((void)p); + std::error_code ec; ((void)ec); + ASSERT_SAME_TYPE(decltype(last_write_time(p)), file_time_type); + ASSERT_SAME_TYPE(decltype(last_write_time(p, ec)), file_time_type); + ASSERT_SAME_TYPE(decltype(last_write_time(p, t)), void); + ASSERT_SAME_TYPE(decltype(last_write_time(p, t, ec)), void); + ASSERT_NOT_NOEXCEPT(last_write_time(p)); + ASSERT_NOT_NOEXCEPT(last_write_time(p, t)); + ASSERT_NOEXCEPT(last_write_time(p, ec)); + ASSERT_NOEXCEPT(last_write_time(p, t, ec)); +} + +TEST_CASE(read_last_write_time_static_env_test) +{ + using C = file_time_type::clock; + file_time_type min = file_time_type::min(); + { + file_time_type ret = last_write_time(StaticEnv::File); + TEST_CHECK(ret != min); + TEST_CHECK(ret < C::now()); + TEST_CHECK(C::to_time_t(ret) == LastWriteTime(StaticEnv::File)); + + file_time_type ret2 = last_write_time(StaticEnv::SymlinkToFile); + TEST_CHECK(ret == ret2); + TEST_CHECK(C::to_time_t(ret2) == LastWriteTime(StaticEnv::SymlinkToFile)); + } + { + file_time_type ret = last_write_time(StaticEnv::Dir); + TEST_CHECK(ret != min); + TEST_CHECK(ret < C::now()); + TEST_CHECK(C::to_time_t(ret) == LastWriteTime(StaticEnv::Dir)); + + file_time_type ret2 = last_write_time(StaticEnv::SymlinkToDir); + TEST_CHECK(ret == ret2); + TEST_CHECK(C::to_time_t(ret2) == LastWriteTime(StaticEnv::SymlinkToDir)); + } +} + +TEST_CASE(get_last_write_time_dynamic_env_test) +{ + using Clock = file_time_type::clock; + using Sec = std::chrono::seconds; + scoped_test_env env; + + const path file = env.create_file("file", 42); + const path dir = env.create_dir("dir"); + + const auto file_times = GetTimes(file); + const std::time_t file_access_time = file_times.first; + const std::time_t file_write_time = file_times.second; + const auto dir_times = GetTimes(dir); + const std::time_t dir_access_time = dir_times.first; + const std::time_t dir_write_time = dir_times.second; + + file_time_type ftime = last_write_time(file); + TEST_CHECK(Clock::to_time_t(ftime) == file_write_time); + + file_time_type dtime = last_write_time(dir); + TEST_CHECK(Clock::to_time_t(dtime) == dir_write_time); + + std::this_thread::sleep_for(Sec(2)); + + // update file and add a file to the directory. Make sure the times increase. + std::ofstream of(file, std::ofstream::app); + of << "hello"; + of.close(); + env.create_file("dir/file1", 1); + + file_time_type ftime2 = last_write_time(file); + file_time_type dtime2 = last_write_time(dir); + + TEST_CHECK(ftime2 > ftime); + TEST_CHECK(dtime2 > dtime); + TEST_CHECK(LastAccessTime(file) == file_access_time); + TEST_CHECK(LastAccessTime(dir) == dir_access_time); +} + + +TEST_CASE(set_last_write_time_dynamic_env_test) +{ + using Clock = file_time_type::clock; + using Sec = std::chrono::seconds; + using Hours = std::chrono::hours; + using Minutes = std::chrono::minutes; + + scoped_test_env env; + + const path file = env.create_file("file", 42); + const path dir = env.create_dir("dir"); + + const file_time_type future_time = Clock::now() + Hours(3); + const file_time_type past_time = Clock::now() - Minutes(3); + + struct TestCase { + path p; + file_time_type new_time; + } cases[] = { + {file, future_time}, + {dir, future_time}, + {file, past_time}, + {dir, past_time} + }; + for (const auto& TC : cases) { + const auto old_times = GetTimes(TC.p); + + std::error_code ec = GetTestEC(); + last_write_time(TC.p, TC.new_time, ec); + TEST_CHECK(!ec); + + const std::time_t new_time_t = Clock::to_time_t(TC.new_time); + file_time_type got_time = last_write_time(TC.p); + std::time_t got_time_t = Clock::to_time_t(got_time); + + TEST_CHECK(got_time_t != old_times.second); + TEST_CHECK(got_time_t == new_time_t); + TEST_CHECK(LastAccessTime(TC.p) == old_times.first); + } +} + +TEST_CASE(last_write_time_symlink_test) +{ + using Clock = file_time_type::clock; + using Sec = std::chrono::seconds; + using Hours = std::chrono::hours; + using Minutes = std::chrono::minutes; + + scoped_test_env env; + + const path file = env.create_file("file", 42); + const path sym = env.create_symlink("file", "sym"); + + const file_time_type new_time = Clock::now() + Hours(3); + + const auto old_times = GetTimes(sym); + const auto old_sym_times = GetSymlinkTimes(sym); + + std::error_code ec = GetTestEC(); + last_write_time(sym, new_time, ec); + TEST_CHECK(!ec); + + const std::time_t new_time_t = Clock::to_time_t(new_time); + file_time_type got_time = last_write_time(sym); + std::time_t got_time_t = Clock::to_time_t(got_time); + + TEST_CHECK(got_time_t != old_times.second); + TEST_CHECK(got_time_t == new_time_t); + TEST_CHECK(LastWriteTime(file) == new_time_t); + TEST_CHECK(LastAccessTime(sym) == old_times.first); + TEST_CHECK(GetSymlinkTimes(sym) == old_sym_times); +} + +TEST_CASE(test_write_min_max_time) +{ + using Clock = file_time_type::clock; + using Sec = std::chrono::seconds; + using Hours = std::chrono::hours; + scoped_test_env env; + const path p = env.create_file("file", 42); + + file_time_type last_time = last_write_time(p); + + file_time_type new_time = file_time_type::min(); + std::error_code ec = GetTestEC(); + last_write_time(p, new_time, ec); + file_time_type tt = last_write_time(p); + if (ec) { + TEST_CHECK(ec != GetTestEC()); + TEST_CHECK(tt == last_time); + } else { + file_time_type max_allowed = new_time + Sec(1); + TEST_CHECK(tt >= new_time); + TEST_CHECK(tt < max_allowed); + } + + last_time = tt; + new_time = file_time_type::max(); + ec = GetTestEC(); + last_write_time(p, new_time, ec); + + tt = last_write_time(p); + if (ec) { + TEST_CHECK(ec != GetTestEC()); + TEST_CHECK(tt == last_time); + } else { + file_time_type min_allowed = new_time - Sec(1); + TEST_CHECK(tt > min_allowed); + TEST_CHECK(tt <= new_time); + } +} + +TEST_CASE(test_value_on_failure) +{ + const path p = StaticEnv::DNE; + std::error_code ec = GetTestEC(); + TEST_CHECK(last_write_time(p, ec) == file_time_type::min()); + TEST_CHECK(ec); + TEST_CHECK(ec != GetTestEC()); +} + +TEST_CASE(test_exists_fails) +{ + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path file = env.create_file("dir/file", 42); + permissions(dir, perms::none); + + std::error_code ec = GetTestEC(); + TEST_CHECK(last_write_time(file, ec) == file_time_type::min()); + TEST_CHECK(ec); + TEST_CHECK(ec != GetTestEC()); + + TEST_CHECK_THROW(filesystem_error, last_write_time(file)); +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.permissions/permissions.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.permissions/permissions.pass.cpp new file mode 100644 index 00000000000..74977c4eaca --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.permissions/permissions.pass.cpp @@ -0,0 +1,154 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// void permissions(const path& p, perms prms); +// void permissions(const path& p, perms prms, std::error_code& ec) noexcept; + + +#include <experimental/filesystem> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; +namespace fs = std::experimental::filesystem; + +using PR = fs::perms; + +TEST_SUITE(filesystem_permissions_test_suite) + +TEST_CASE(test_signatures) +{ + const path p; ((void)p); + const perms opts{}; ((void)opts); + 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)); +} + +TEST_CASE(test_error_reporting) +{ + auto checkThrow = [](path const& f, fs::perms opts, const std::error_code& ec) + { +#ifndef TEST_HAS_NO_EXCEPTIONS + try { + fs::permissions(f, opts); + return false; + } catch (filesystem_error const& err) { + return err.path1() == f + && err.path2() == "" + && err.code() == ec; + } +#else + return true; +#endif + }; + + scoped_test_env env; + const path dne = env.make_env_path("dne"); + const path dne_sym = env.create_symlink(dne, "dne_sym"); + { // !exists + std::error_code ec; + fs::permissions(dne, fs::perms{}, ec); + TEST_REQUIRE(ec); + TEST_CHECK(checkThrow(dne, fs::perms{}, ec)); + } + { + std::error_code ec; + fs::permissions(dne_sym, perms::resolve_symlinks, ec); + TEST_REQUIRE(ec); + TEST_CHECK(checkThrow(dne_sym, perms::resolve_symlinks, ec)); + } +} + +TEST_CASE(basic_permissions_test) +{ + scoped_test_env env; + const path file = env.create_file("file1", 42); + const path dir = env.create_dir("dir1"); + const path file_for_sym = env.create_file("file2", 42); + const path sym = env.create_symlink(file_for_sym, "sym"); + const perms AP = perms::add_perms; + const perms RP = perms::remove_perms; + const perms RS = perms::resolve_symlinks; + struct TestCase { + path p; + perms set_perms; + perms expected; + } cases[] = { + // test file + {file, perms::owner_all, perms::owner_all}, + {file, perms::group_all | AP, perms::owner_all | perms::group_all}, + {file, perms::group_all | RP, perms::owner_all}, + {file, perms::none, perms::none}, + // test directory + {dir, perms::owner_all, perms::owner_all}, + {dir, perms::group_all | AP, perms::owner_all | perms::group_all}, + {dir, perms::group_all | RP, perms::owner_all}, + {dir, perms::none, perms::none}, + // test symlink with resolve symlinks on symlink + {sym, perms::owner_all | RS, perms::owner_all}, + {sym, perms::group_all | AP | RS, perms::owner_all | perms::group_all}, + {sym, perms::group_all | RP | RS, perms::owner_all}, + {sym, perms::none | RS, perms::none} + }; + for (auto const& TC : cases) { + TEST_CHECK(status(TC.p).permissions() != TC.expected); + // Set the error code to ensure it's cleared. + std::error_code ec = std::make_error_code(std::errc::bad_address); + 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_CASE(test_no_resolve_symlink_on_symlink) +{ + scoped_test_env env; + const path file = env.create_file("file", 42); + const path sym = env.create_symlink(file, "sym"); + const auto file_perms = status(file).permissions(); + + struct TestCase { + perms set_perms; + perms expected; // only expected on platform that support symlink perms. + } cases[] = { + {perms::owner_all, perms::owner_all}, + {perms::group_all | perms::add_perms, perms::owner_all | perms::group_all}, + {perms::owner_all | perms::remove_perms, perms::group_all}, + }; + for (auto const& TC : cases) { +#if defined(__APPLE__) || defined(__FreeBSD__) + // On OS X symlink permissions are supported. We should get an empty + // error code and the expected permissions. + const auto expected_link_perms = TC.expected; + std::error_code expected_ec; +#else + // On linux symlink permissions are not supported. The error code should + // be 'operation_not_supported' and the sylink permissions should be + // unchanged. + const auto expected_link_perms = symlink_status(sym).permissions(); + std::error_code expected_ec = std::make_error_code(std::errc::operation_not_supported); +#endif + std::error_code ec = std::make_error_code(std::errc::bad_address); + permissions(sym, TC.set_perms, ec); + TEST_CHECK(ec == expected_ec); + TEST_CHECK(status(file).permissions() == file_perms); + TEST_CHECK(symlink_status(sym).permissions() == expected_link_perms); + } +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.read_symlink/read_symlink.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.read_symlink/read_symlink.pass.cpp new file mode 100644 index 00000000000..00581cbe8bc --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.read_symlink/read_symlink.pass.cpp @@ -0,0 +1,100 @@ +//===----------------------------------------------------------------------===// +// +// 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 read_symlink(const path& p); +// path read_symlink(const path& p, error_code& ec); + +#include <experimental/filesystem> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; +namespace fs = std::experimental::filesystem; + +TEST_SUITE(filesystem_read_symlink_test_suite) + +TEST_CASE(test_signatures) +{ + const path p; ((void)p); + std::error_code ec; ((void)ec); + ASSERT_SAME_TYPE(decltype(fs::read_symlink(p)), fs::path); + ASSERT_SAME_TYPE(decltype(fs::read_symlink(p, ec)), fs::path); + + ASSERT_NOT_NOEXCEPT(fs::read_symlink(p)); + // Not noexcept because of narrow contract + ASSERT_NOT_NOEXCEPT(fs::read_symlink(p, ec)); +} + +TEST_CASE(test_error_reporting) +{ + auto checkThrow = [](path const& f, const std::error_code& ec) + { +#ifndef TEST_HAS_NO_EXCEPTIONS + try { + fs::read_symlink(f); + return false; + } catch (filesystem_error const& err) { + return err.path1() == f + && err.path2() == "" + && err.code() == ec; + } +#else + return true; +#endif + }; + + scoped_test_env env; + const path cases[] = { + env.make_env_path("dne"), + env.create_file("file", 42), + env.create_dir("dir") + }; + for (path const& p : cases) { + std::error_code ec; + const path ret = fs::read_symlink(p, ec); + TEST_REQUIRE(ec); + TEST_CHECK(ret == path{}); + TEST_CHECK(checkThrow(p, ec)); + } + +} + +TEST_CASE(basic_symlink_test) +{ + scoped_test_env env; + const path dne = env.make_env_path("dne"); + const path file = env.create_file("file", 42); + const path dir = env.create_dir("dir"); + const path link = env.create_symlink(dne, "link"); + const path nested_link = env.make_env_path("nested_link"); + create_symlink(link, nested_link); + struct TestCase { + path symlink; + path expected; + } testCases[] = { + {env.create_symlink(dne, "dne_link"), dne}, + {env.create_symlink(file, "file_link"), file}, + {env.create_symlink(dir, "dir_link"), dir}, + {nested_link, link} + }; + for (auto& TC : testCases) { + std::error_code ec = std::make_error_code(std::errc::address_in_use); + const path ret = read_symlink(TC.symlink, ec); + TEST_CHECK(!ec); + TEST_CHECK(ret == TC.expected); + } +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.remove/remove.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.remove/remove.pass.cpp new file mode 100644 index 00000000000..edb0c4fc76c --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.remove/remove.pass.cpp @@ -0,0 +1,97 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// bool remove(const path& p); +// bool remove(const path& p, error_code& ec) noexcept; + +#include <experimental/filesystem> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; +namespace fs = std::experimental::filesystem; + +TEST_SUITE(filesystem_remove_test_suite) + +TEST_CASE(test_signatures) +{ + const path p; ((void)p); + std::error_code ec; ((void)ec); + ASSERT_SAME_TYPE(decltype(fs::remove(p)), bool); + ASSERT_SAME_TYPE(decltype(fs::remove(p, ec)), bool); + + ASSERT_NOT_NOEXCEPT(fs::remove(p)); + ASSERT_NOEXCEPT(fs::remove(p, ec)); +} + +TEST_CASE(test_error_reporting) +{ + auto checkThrow = [](path const& f, const std::error_code& ec) + { +#ifndef TEST_HAS_NO_EXCEPTIONS + try { + fs::remove(f); + return false; + } catch (filesystem_error const& err) { + return err.path1() == f + && err.path2() == "" + && err.code() == ec; + } +#else + return true; +#endif + }; + scoped_test_env env; + const path non_empty_dir = env.create_dir("dir"); + env.create_file(non_empty_dir / "file1", 42); + const path bad_perms_dir = env.create_dir("bad_dir"); + const path file_in_bad_dir = env.create_file(bad_perms_dir / "file", 42); + permissions(bad_perms_dir, perms::none); + const path testCases[] = { + "", + env.make_env_path("dne"), + non_empty_dir, + file_in_bad_dir, + }; + for (auto& p : testCases) { + std::error_code ec; + TEST_CHECK(!fs::remove(p, ec)); + TEST_CHECK(ec); + TEST_CHECK(checkThrow(p, ec)); + } +} + +TEST_CASE(basic_remove_test) +{ + scoped_test_env env; + const path dne = env.make_env_path("dne"); + const path link = env.create_symlink(dne, "link"); + const path nested_link = env.make_env_path("nested_link"); + create_symlink(link, nested_link); + const path testCases[] = { + env.create_file("file", 42), + env.create_dir("empty_dir"), + nested_link, + link + }; + for (auto& p : testCases) { + std::error_code ec = std::make_error_code(std::errc::address_in_use); + TEST_CHECK(remove(p, ec)); + TEST_CHECK(!ec); + TEST_CHECK(!exists(symlink_status(p))); + } +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp new file mode 100644 index 00000000000..aecfce7885e --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp @@ -0,0 +1,141 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// uintmax_t remove_all(const path& p); +// uintmax_t remove_all(const path& p, error_code& ec) noexcept; + +#include <experimental/filesystem> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; +namespace fs = std::experimental::filesystem; + +TEST_SUITE(filesystem_remove_all_test_suite) + +TEST_CASE(test_signatures) +{ + const path p; ((void)p); + std::error_code ec; ((void)ec); + ASSERT_SAME_TYPE(decltype(fs::remove_all(p)), std::uintmax_t); + ASSERT_SAME_TYPE(decltype(fs::remove_all(p, ec)), std::uintmax_t); + + ASSERT_NOT_NOEXCEPT(fs::remove_all(p)); + ASSERT_NOEXCEPT(fs::remove_all(p, ec)); +} + +TEST_CASE(test_error_reporting) +{ + auto checkThrow = [](path const& f, const std::error_code& ec) + { +#ifndef TEST_HAS_NO_EXCEPTIONS + try { + fs::remove_all(f); + return false; + } catch (filesystem_error const& err) { + return err.path1() == f + && err.path2() == "" + && err.code() == ec; + } +#else + return true; +#endif + }; + scoped_test_env env; + const path non_empty_dir = env.create_dir("dir"); + env.create_file(non_empty_dir / "file1", 42); + const path bad_perms_dir = env.create_dir("bad_dir"); + const path file_in_bad_dir = env.create_file(bad_perms_dir / "file", 42); + permissions(bad_perms_dir, perms::none); + const path bad_perms_file = env.create_file("file2", 42); + permissions(bad_perms_file, perms::none); + + const path testCases[] = { + env.make_env_path("dne"), + file_in_bad_dir + }; + const auto BadRet = static_cast<std::uintmax_t>(-1); + for (auto& p : testCases) { + std::error_code ec; + TEST_CHECK(fs::remove_all(p, ec) == BadRet); + TEST_CHECK(ec); + TEST_CHECK(checkThrow(p, ec)); + } +} + +TEST_CASE(basic_remove_all_test) +{ + scoped_test_env env; + const path dne = env.make_env_path("dne"); + const path link = env.create_symlink(dne, "link"); + const path nested_link = env.make_env_path("nested_link"); + create_symlink(link, nested_link); + const path testCases[] = { + env.create_file("file", 42), + env.create_dir("empty_dir"), + nested_link, + link + }; + for (auto& p : testCases) { + std::error_code ec = std::make_error_code(std::errc::address_in_use); + TEST_CHECK(remove(p, ec)); + TEST_CHECK(!ec); + TEST_CHECK(!exists(symlink_status(p))); + } +} + +TEST_CASE(symlink_to_dir) +{ + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path file = env.create_file(dir / "file", 42); + const path link = env.create_symlink(dir, "sym"); + + { + std::error_code ec = std::make_error_code(std::errc::address_in_use); + TEST_CHECK(remove_all(link, ec) == 1); + TEST_CHECK(!ec); + TEST_CHECK(!exists(symlink_status(link))); + TEST_CHECK(exists(dir)); + TEST_CHECK(exists(file)); + } +} + + +TEST_CASE(nested_dir) +{ + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path dir1 = env.create_dir(dir / "dir1"); + const path out_of_dir_file = env.create_file("file1", 42); + const path all_files[] = { + dir, dir1, + env.create_file(dir / "file1", 42), + env.create_symlink(out_of_dir_file, dir / "sym1"), + env.create_file(dir1 / "file2", 42), + env.create_symlink(dir, dir1 / "sym2") + }; + const std::size_t expected_count = sizeof(all_files) / sizeof(all_files[0]); + + std::error_code ec = std::make_error_code(std::errc::address_in_use); + TEST_CHECK(remove_all(dir, ec) == expected_count); + TEST_CHECK(!ec); + for (auto const& p : all_files) { + TEST_CHECK(!exists(symlink_status(p))); + } + TEST_CHECK(exists(out_of_dir_file)); +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.rename/rename.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.rename/rename.pass.cpp new file mode 100644 index 00000000000..c2ae854c0bf --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.rename/rename.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> + +// void rename(const path& old_p, const path& new_p); +// void rename(const path& old_p, const path& new_p, error_code& ec) noexcept; + +#include <experimental/filesystem> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; +namespace fs = std::experimental::filesystem; + +TEST_SUITE(filesystem_rename_test_suite) + +TEST_CASE(test_signatures) +{ + const path p; ((void)p); + std::error_code ec; ((void)ec); + ASSERT_SAME_TYPE(decltype(fs::rename(p, p)), void); + ASSERT_SAME_TYPE(decltype(fs::rename(p, p, ec)), void); + + ASSERT_NOT_NOEXCEPT(fs::rename(p, p)); + ASSERT_NOEXCEPT(fs::rename(p, p, ec)); +} + +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::rename(f, t); + return false; + } catch (filesystem_error const& err) { + return err.path1() == f + && err.path2() == t + && err.code() == ec; + } +#else + return true; +#endif + }; + scoped_test_env env; + const path dne = env.make_env_path("dne"); + const path file = env.create_file("file1", 42); + const path dir = env.create_dir("dir1"); + struct TestCase { + path from; + path to; + } cases[] = { + {dne, dne}, + {file, dir}, + {dir, file} + }; + for (auto& TC : cases) { + auto from_before = status(TC.from); + auto to_before = status(TC.to); + std::error_code ec; + rename(TC.from, TC.to, ec); + TEST_REQUIRE(ec); + TEST_CHECK(from_before.type() == status(TC.from).type()); + TEST_CHECK(to_before.type() == status(TC.to).type()); + TEST_CHECK(checkThrow(TC.from, TC.to, ec)); + } +} + +TEST_CASE(basic_rename_test) +{ + scoped_test_env env; + + const std::error_code set_ec = std::make_error_code(std::errc::address_in_use); + const path file = env.create_file("file1", 42); + { // same file + std::error_code ec = set_ec; + rename(file, file, ec); + TEST_CHECK(!ec); + TEST_CHECK(is_regular_file(file)); + TEST_CHECK(file_size(file) == 42); + } + const path sym = env.create_symlink(file, "sym"); + { // file -> symlink + std::error_code ec = set_ec; + rename(file, sym, ec); + TEST_CHECK(!ec); + TEST_CHECK(!exists(file)); + TEST_CHECK(is_regular_file(symlink_status(sym))); + TEST_CHECK(file_size(sym) == 42); + } + const path file2 = env.create_file("file2", 42); + const path file3 = env.create_file("file3", 100); + { // file -> file + std::error_code ec = set_ec; + rename(file2, file3, ec); + TEST_CHECK(!ec); + TEST_CHECK(!exists(file2)); + TEST_CHECK(is_regular_file(file3)); + TEST_CHECK(file_size(file3) == 42); + } + const path dne = env.make_env_path("dne"); + const path bad_sym = env.create_symlink(dne, "bad_sym"); + const path bad_sym_dest = env.make_env_path("bad_sym2"); + { // bad-symlink + std::error_code ec = set_ec; + rename(bad_sym, bad_sym_dest, ec); + TEST_CHECK(!ec); + TEST_CHECK(!exists(symlink_status(bad_sym))); + TEST_CHECK(is_symlink(bad_sym_dest)); + TEST_CHECK(read_symlink(bad_sym_dest) == dne); + } +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.resize_file/resize_file.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.resize_file/resize_file.pass.cpp new file mode 100644 index 00000000000..8a6aa09b14c --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.resize_file/resize_file.pass.cpp @@ -0,0 +1,109 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// void resize_file(const path& p, uintmax_t new_size); +// void resize_file(const path& p, uintmax_t new_size, error_code& ec) noexcept; + +#include <experimental/filesystem> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; +namespace fs = std::experimental::filesystem; + +TEST_SUITE(filesystem_resize_file_test_suite) + +TEST_CASE(test_signatures) +{ + const path p; ((void)p); + std::uintmax_t i; ((void)i); + std::error_code ec; ((void)ec); + + ASSERT_SAME_TYPE(decltype(fs::resize_file(p, i)), void); + ASSERT_SAME_TYPE(decltype(fs::resize_file(p, i, ec)), void); + + ASSERT_NOT_NOEXCEPT(fs::resize_file(p, i)); + ASSERT_NOEXCEPT(fs::resize_file(p, i, ec)); +} + +TEST_CASE(test_error_reporting) +{ + auto checkThrow = [](path const& f, std::uintmax_t s, const std::error_code& ec) + { +#ifndef TEST_HAS_NO_EXCEPTIONS + try { + fs::resize_file(f, s); + return false; + } catch (filesystem_error const& err) { + return err.path1() == f + && err.path2() == "" + && err.code() == ec; + } +#else + return true; +#endif + }; + scoped_test_env env; + const path dne = env.make_env_path("dne"); + const path bad_sym = env.create_symlink(dne, "sym"); + const path dir = env.create_dir("dir1"); + const path cases[] = { + dne, bad_sym, dir + }; + for (auto& p : cases) { + std::error_code ec; + resize_file(p, 42, ec); + TEST_REQUIRE(ec); + TEST_CHECK(checkThrow(p, 42, ec)); + } +} + +TEST_CASE(basic_resize_file_test) +{ + scoped_test_env env; + const path file1 = env.create_file("file1", 42); + const auto set_ec = std::make_error_code(std::errc::address_in_use); + { // grow file + const std::uintmax_t new_s = 100; + std::error_code ec = set_ec; + resize_file(file1, new_s, ec); + TEST_CHECK(!ec); + TEST_CHECK(file_size(file1) == new_s); + } + { // shrink file + const std::uintmax_t new_s = 1; + std::error_code ec = set_ec; + resize_file(file1, new_s, ec); + TEST_CHECK(!ec); + TEST_CHECK(file_size(file1) == new_s); + } + { // shrink file to zero + const std::uintmax_t new_s = 0; + std::error_code ec = set_ec; + resize_file(file1, new_s, ec); + TEST_CHECK(!ec); + TEST_CHECK(file_size(file1) == new_s); + } + const path sym = env.create_symlink(file1, "sym"); + { // grow file via symlink + const std::uintmax_t new_s = 1024; + std::error_code ec = set_ec; + resize_file(sym, new_s, ec); + TEST_CHECK(!ec); + TEST_CHECK(file_size(file1) == new_s); + } +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.space/space.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.space/space.pass.cpp new file mode 100644 index 00000000000..7082c9d121b --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.space/space.pass.cpp @@ -0,0 +1,113 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// space_info space(const path& p); +// space_info space(const path& p, error_code& ec) noexcept; + +#include <experimental/filesystem> +#include <sys/statvfs.h> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +bool EqualDelta(std::uintmax_t x, std::uintmax_t y, std::uintmax_t delta) { + if (x >= y) { + return (x - y) <= delta; + } else { + return (y - x) <= delta; + } +} + +TEST_SUITE(filesystem_space_test_suite) + +TEST_CASE(signature_test) +{ + const path p; ((void)p); + std::error_code ec; ((void)ec); + ASSERT_SAME_TYPE(decltype(space(p)), space_info); + ASSERT_SAME_TYPE(decltype(space(p, ec)), space_info); + ASSERT_NOT_NOEXCEPT(space(p)); + ASSERT_NOEXCEPT(space(p, ec)); +} + +TEST_CASE(test_error_reporting) +{ + auto checkThrow = [](path const& f, const std::error_code& ec) + { +#ifndef TEST_HAS_NO_EXCEPTIONS + try { + space(f); + return false; + } catch (filesystem_error const& err) { + return err.path1() == f + && err.path2() == "" + && err.code() == ec; + } +#else + return true; +#endif + }; + const path cases[] = { + "", + StaticEnv::DNE, + StaticEnv::BadSymlink + }; + for (auto& p : cases) { + const auto expect = static_cast<std::uintmax_t>(-1); + std::error_code ec; + space_info info = space(p, ec); + TEST_CHECK(ec); + TEST_CHECK(info.capacity == expect); + TEST_CHECK(info.free == expect); + TEST_CHECK(info.available == expect); + TEST_CHECK(checkThrow(p, ec)); + } +} + +TEST_CASE(basic_space_test) +{ + // All the test cases should reside on the same filesystem and therefore + // should have the same expected result. Compute this expected result + // one and check that it looks semi-sane. + struct statvfs expect; + TEST_REQUIRE(::statvfs(StaticEnv::Dir.c_str(), &expect) != -1); + TEST_CHECK(expect.f_bavail > 0); + TEST_CHECK(expect.f_bfree > 0); + TEST_CHECK(expect.f_bsize > 0); + TEST_CHECK(expect.f_blocks > 0); + const std::uintmax_t expect_cap = expect.f_blocks * expect.f_frsize; + // Other processes running on the operating system may have changed + // the amount of space available. Check that these are within tolerances. + // Currently 5% of capacity + const std::uintmax_t delta = expect_cap / 20; + const path cases[] = { + StaticEnv::File, + StaticEnv::Dir, + StaticEnv::Dir2, + StaticEnv::SymlinkToFile, + StaticEnv::SymlinkToDir + }; + for (auto& p : cases) { + std::error_code ec = std::make_error_code(std::errc::address_in_use); + space_info info = space(p, ec); + TEST_CHECK(!ec); + TEST_CHECK((expect.f_blocks * expect.f_frsize) == info.capacity); + TEST_CHECK(EqualDelta((expect.f_bfree * expect.f_frsize), info.free, delta)); + TEST_CHECK(EqualDelta((expect.f_bavail * expect.f_frsize), info.available, delta)); + } +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.status/status.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.status/status.pass.cpp new file mode 100644 index 00000000000..2c76caf74c8 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.status/status.pass.cpp @@ -0,0 +1,159 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// file_status status(const path& p); +// file_status status(const path& p, error_code& ec) noexcept; + +#include <experimental/filesystem> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(filesystem_status_test_suite) + +TEST_CASE(signature_test) +{ + const path p; ((void)p); + std::error_code ec; ((void)ec); + ASSERT_NOT_NOEXCEPT(status(p)); + ASSERT_NOEXCEPT(status(p, ec)); +} + +TEST_CASE(test_status_not_found) +{ + const std::error_code expect_ec = + std::make_error_code(std::errc::no_such_file_or_directory); + const path cases[] { + StaticEnv::DNE, + StaticEnv::BadSymlink + }; + for (auto& p : cases) { + std::error_code ec = std::make_error_code(std::errc::address_in_use); + // test non-throwing overload. + file_status st = status(p, ec); + TEST_CHECK(ec == expect_ec); + TEST_CHECK(st.type() == file_type::not_found); + TEST_CHECK(st.permissions() == perms::unknown); + // test throwing overload. It should not throw even though it reports + // that the file was not found. + TEST_CHECK_NO_THROW(st = status(p)); + TEST_CHECK(st.type() == file_type::not_found); + TEST_CHECK(st.permissions() == perms::unknown); + } +} + +TEST_CASE(test_status_cannot_resolve) +{ + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path file = env.create_file("dir/file", 42); + const path sym = env.create_symlink("dir/file", "sym"); + permissions(dir, 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::permission_denied); + + const path cases[] = { + file, sym + }; + for (auto& p : cases) + { + { // test non-throwing case + std::error_code ec = set_ec; + file_status st = status(p, ec); + TEST_CHECK(ec == expect_ec); + TEST_CHECK(st.type() == file_type::none); + TEST_CHECK(st.permissions() == perms::unknown); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { // test throwing case + try { + status(p); + } catch (filesystem_error const& err) { + TEST_CHECK(err.path1() == p); + TEST_CHECK(err.path2() == ""); + TEST_CHECK(err.code() == expect_ec); + } + } +#endif + } +} + +TEST_CASE(status_file_types_test) +{ + scoped_test_env env; + struct TestCase { + path p; + file_type expect_type; + } cases[] = { + {StaticEnv::File, file_type::regular}, + {StaticEnv::SymlinkToFile, file_type::regular}, + {StaticEnv::Dir, file_type::directory}, + {StaticEnv::SymlinkToDir, file_type::directory}, + // Block files tested elsewhere + {StaticEnv::CharFile, file_type::character}, +#if !defined(__APPLE__) && !defined(__FreeBSD__) // No support for domain sockets + {env.create_socket("socket"), file_type::socket}, +#endif + {env.create_fifo("fifo"), file_type::fifo} + }; + for (const auto& TC : cases) { + // test non-throwing case + std::error_code ec = std::make_error_code(std::errc::address_in_use); + file_status st = status(TC.p, ec); + TEST_CHECK(!ec); + TEST_CHECK(st.type() == TC.expect_type); + TEST_CHECK(st.permissions() != perms::unknown); + // test throwing case + TEST_REQUIRE_NO_THROW(st = status(TC.p)); + TEST_CHECK(st.type() == TC.expect_type); + TEST_CHECK(st.permissions() != perms::unknown); + } +} + +TEST_CASE(test_block_file) +{ + const path possible_paths[] = { + "/dev/drive0", // Apple + "/dev/sda", + "/dev/loop0" + }; + path p; + for (const path& possible_p : possible_paths) { + std::error_code ec; + if (exists(possible_p, ec)) { + p = possible_p; + break; + } + } + if (p == path{}) { + TEST_UNSUPPORTED(); + } + // test non-throwing case + std::error_code ec = std::make_error_code(std::errc::address_in_use); + file_status st = status(p, ec); + TEST_CHECK(!ec); + TEST_CHECK(st.type() == file_type::block); + TEST_CHECK(st.permissions() != perms::unknown); + // test throwing case + TEST_REQUIRE_NO_THROW(st = status(p)); + TEST_CHECK(st.type() == file_type::block); + TEST_CHECK(st.permissions() != perms::unknown); +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.status_known/status_known.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.status_known/status_known.pass.cpp new file mode 100644 index 00000000000..169c5be9d9a --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.status_known/status_known.pass.cpp @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// bool status_known(file_status s) noexcept; + +#include <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(status_known_test_suite) + +TEST_CASE(signature_test) +{ + file_status s; ((void)s); + ASSERT_SAME_TYPE(decltype(status_known(s)), bool); + ASSERT_NOEXCEPT(status_known(s)); +} + +TEST_CASE(status_known_test) +{ + struct TestCase { + file_type type; + bool expect; + }; + const TestCase testCases[] = { + {file_type::none, false}, + {file_type::not_found, true}, + {file_type::regular, true}, + {file_type::directory, true}, + {file_type::symlink, true}, + {file_type::block, true}, + {file_type::character, true}, + {file_type::fifo, true}, + {file_type::socket, true}, + {file_type::unknown, true} + }; + for (auto& TC : testCases) { + file_status s(TC.type); + TEST_CHECK(status_known(s) == TC.expect); + } +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.symlink_status/symlink_status.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.symlink_status/symlink_status.pass.cpp new file mode 100644 index 00000000000..647504f6e1a --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.symlink_status/symlink_status.pass.cpp @@ -0,0 +1,192 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// file_status symlink_status(const path& p); +// file_status symlink_status(const path& p, error_code& ec) noexcept; + +#include <experimental/filesystem> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +TEST_SUITE(filesystem_symlink_status_test_suite) + +TEST_CASE(signature_test) +{ + const path p; ((void)p); + std::error_code ec; ((void)ec); + ASSERT_NOT_NOEXCEPT(symlink_status(p)); + ASSERT_NOEXCEPT(symlink_status(p, ec)); +} + +TEST_CASE(test_symlink_status_not_found) +{ + const std::error_code expect_ec = + std::make_error_code(std::errc::no_such_file_or_directory); + const path cases[] { + StaticEnv::DNE + }; + for (auto& p : cases) { + std::error_code ec = std::make_error_code(std::errc::address_in_use); + // test non-throwing overload. + file_status st = symlink_status(p, ec); + TEST_CHECK(ec == expect_ec); + TEST_CHECK(st.type() == file_type::not_found); + TEST_CHECK(st.permissions() == perms::unknown); + // test throwing overload. It should not throw even though it reports + // that the file was not found. + TEST_CHECK_NO_THROW(st = status(p)); + TEST_CHECK(st.type() == file_type::not_found); + TEST_CHECK(st.permissions() == perms::unknown); + } +} + +TEST_CASE(test_symlink_status_cannot_resolve) +{ + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path file_in_dir = env.create_file("dir/file", 42); + const path sym_in_dir = env.create_symlink("dir/file", "dir/bad_sym"); + const path sym_points_in_dir = env.create_symlink("dir/file", "sym"); + permissions(dir, 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::permission_denied); + + const path fail_cases[] = { + file_in_dir, sym_in_dir + }; + for (auto& p : fail_cases) + { + { // test non-throwing case + std::error_code ec = set_ec; + file_status st = symlink_status(p, ec); + TEST_CHECK(ec == expect_ec); + TEST_CHECK(st.type() == file_type::none); + TEST_CHECK(st.permissions() == perms::unknown); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { // test throwing case + try { + symlink_status(p); + } catch (filesystem_error const& err) { + TEST_CHECK(err.path1() == p); + TEST_CHECK(err.path2() == ""); + TEST_CHECK(err.code() == expect_ec); + } + } +#endif + } + // Test that a symlink that points into a directory without read perms + // can be stat-ed using symlink_status + { + std::error_code ec = set_ec; + file_status st = symlink_status(sym_points_in_dir, ec); + TEST_CHECK(!ec); + TEST_CHECK(st.type() == file_type::symlink); + TEST_CHECK(st.permissions() != perms::unknown); + // test non-throwing version + TEST_REQUIRE_NO_THROW(st = symlink_status(sym_points_in_dir)); + TEST_CHECK(st.type() == file_type::symlink); + TEST_CHECK(st.permissions() != perms::unknown); + } +} + + +TEST_CASE(symlink_status_file_types_test) +{ + scoped_test_env env; + struct TestCase { + path p; + file_type expect_type; + } cases[] = { + {StaticEnv::BadSymlink, file_type::symlink}, + {StaticEnv::File, file_type::regular}, + {StaticEnv::SymlinkToFile, file_type::symlink}, + {StaticEnv::Dir, file_type::directory}, + {StaticEnv::SymlinkToDir, file_type::symlink}, + // Block files tested elsewhere + {StaticEnv::CharFile, file_type::character}, +#if !defined(__APPLE__) && !defined(__FreeBSD__) // No support for domain sockets + {env.create_socket("socket"), file_type::socket}, +#endif + {env.create_fifo("fifo"), file_type::fifo} + }; + for (const auto& TC : cases) { + // test non-throwing case + std::error_code ec = std::make_error_code(std::errc::address_in_use); + file_status st = symlink_status(TC.p, ec); + TEST_CHECK(!ec); + TEST_CHECK(st.type() == TC.expect_type); + TEST_CHECK(st.permissions() != perms::unknown); + // test throwing case + TEST_REQUIRE_NO_THROW(st = symlink_status(TC.p)); + TEST_CHECK(st.type() == TC.expect_type); + TEST_CHECK(st.permissions() != perms::unknown); + } +} + +TEST_CASE(test_block_file) +{ + const path possible_paths[] = { + "/dev/drive0", // Apple + "/dev/sda", // Linux + "/dev/loop0" // Linux + // No FreeBSD files known + }; + path p; + for (const path& possible_p : possible_paths) { + std::error_code ec; + if (exists(possible_p, ec)) { + p = possible_p; + break; + } + } + if (p == path{}) { + TEST_UNSUPPORTED(); + } + scoped_test_env env; + { // test block file + // test non-throwing case + std::error_code ec = std::make_error_code(std::errc::address_in_use); + file_status st = symlink_status(p, ec); + TEST_CHECK(!ec); + TEST_CHECK(st.type() == file_type::block); + TEST_CHECK(st.permissions() != perms::unknown); + // test throwing case + TEST_REQUIRE_NO_THROW(st = symlink_status(p)); + TEST_CHECK(st.type() == file_type::block); + TEST_CHECK(st.permissions() != perms::unknown); + } + const path sym = env.make_env_path("sym"); + create_symlink(p, sym); + { // test symlink to block file + // test non-throwing case + std::error_code ec = std::make_error_code(std::errc::address_in_use); + file_status st = symlink_status(sym, ec); + TEST_CHECK(!ec); + TEST_CHECK(st.type() == file_type::symlink); + TEST_CHECK(st.permissions() != perms::unknown); + // test throwing case + TEST_REQUIRE_NO_THROW(st = symlink_status(sym)); + TEST_CHECK(st.type() == file_type::symlink); + TEST_CHECK(st.permissions() != perms::unknown); + } +} + +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 new file mode 100644 index 00000000000..634184e24e6 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.system_complete/system_complete.pass.cpp @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// 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 <experimental/filesystem> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +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.temp_dir_path/temp_directory_path.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.temp_dir_path/temp_directory_path.pass.cpp new file mode 100644 index 00000000000..215c35a33f3 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.temp_dir_path/temp_directory_path.pass.cpp @@ -0,0 +1,110 @@ +//===----------------------------------------------------------------------===// +// +// 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 temp_directory_path(); +// path temp_directory_path(error_code& ec); + +#include <experimental/filesystem> +#include <memory> +#include <cstdlib> +#include <cstring> +#include <cassert> + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace std::experimental::filesystem; + +void PutEnv(std::string var, std::string value) { + assert(::setenv(var.c_str(), value.c_str(), /* overwrite */ 1) == 0); +} + +void UnsetEnv(std::string var) { + assert(::unsetenv(var.c_str()) == 0); +} + +TEST_SUITE(filesystem_temp_directory_path_test_suite) + +TEST_CASE(signature_test) +{ + std::error_code ec; ((void)ec); + ASSERT_NOT_NOEXCEPT(temp_directory_path()); + ASSERT_NOT_NOEXCEPT(temp_directory_path(ec)); +} + +TEST_CASE(basic_tests) +{ + scoped_test_env env; + const path dne = env.make_env_path("dne"); + const path file = env.create_file("file", 42); + 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; + path p; + } cases[] = { + {"TMPDIR", env.create_dir("dir1")}, + {"TMP", env.create_dir("dir2")}, + {"TEMP", env.create_dir("dir3")}, + {"TEMPDIR", env.create_dir("dir4")} + }; + for (auto& TC : cases) { + PutEnv(TC.name, TC.p); + } + for (auto& TC : cases) { + std::error_code ec = set_ec; + path ret = temp_directory_path(ec); + TEST_CHECK(!ec); + TEST_CHECK(ret == TC.p); + TEST_CHECK(is_directory(ret)); + + // Set the env variable to a path that does not exist and check + // that it fails. + PutEnv(TC.name, dne); + ec = set_ec; + ret = temp_directory_path(ec); + TEST_CHECK(ec == expect_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; + ret = temp_directory_path(ec); + TEST_CHECK(ec == expect_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; + ret = temp_directory_path(ec); + TEST_CHECK(ec == std::make_error_code(std::errc::permission_denied)); + TEST_CHECK(ret == ""); + + // Finally erase this env variable + UnsetEnv(TC.name); + } + // No env variables are defined + { + std::error_code ec = set_ec; + path ret = temp_directory_path(ec); + TEST_CHECK(!ec); + TEST_CHECK(ret == "/tmp"); + TEST_CHECK(is_directory(ret)); + } +} + +TEST_SUITE_END() diff --git a/libcxx/test/std/experimental/filesystem/fs.req.macros/feature_macro.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.req.macros/feature_macro.pass.cpp new file mode 100644 index 00000000000..d57dff4a7b7 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.req.macros/feature_macro.pass.cpp @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// #define __cpp_lib_experimental_filesystem 201406L + +#include <experimental/filesystem> + +#ifndef __cpp_lib_experimental_filesystem +#error Filesystem feature test macro is not defined (__cpp_lib_experimental_filesystem) +#elif __cpp_lib_experimental_filesystem != 201406L +#error Filesystem feature test macro has an incorrect value (__cpp_lib_experimental_filesystem) +#endif + +int main() { } diff --git a/libcxx/test/std/experimental/filesystem/fs.req.namespace/namespace.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.req.namespace/namespace.pass.cpp new file mode 100644 index 00000000000..77ae7b0989b --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/fs.req.namespace/namespace.pass.cpp @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// namespace std::experimental::filesystem::v1 + +#include <experimental/filesystem> +#include <type_traits> + +int main() { + static_assert(std::is_same< + std::experimental::filesystem::path, + std::experimental::filesystem::v1::path + >::value, ""); +} diff --git a/libcxx/test/std/experimental/filesystem/lit.local.cfg b/libcxx/test/std/experimental/filesystem/lit.local.cfg new file mode 100644 index 00000000000..3d9360431f4 --- /dev/null +++ b/libcxx/test/std/experimental/filesystem/lit.local.cfg @@ -0,0 +1,3 @@ +# Disable all of the filesystem tests if the correct feature is not available. +if 'c++filesystem' not in config.available_features: + config.unsupported = True |