| //===----------------------------------------------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| // UNSUPPORTED: c++03 |
| |
| // <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); |
| // recursive_directory_iterator(const path& p, directory_options options, error_code& ec); |
| |
| |
| #include "filesystem_include.h" |
| #include <type_traits> |
| #include <set> |
| #include <cassert> |
| |
| #include "assert_macros.h" |
| #include "test_macros.h" |
| #include "filesystem_test_helper.h" |
| |
| using namespace fs; |
| |
| using RDI = recursive_directory_iterator; |
| |
| static void 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&) |
| static_assert(std::is_constructible<D, path, |
| std::error_code&>::value, ""); |
| 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&) |
| static_assert(std::is_constructible<D, path, directory_options, std::error_code&>::value, ""); |
| static_assert(!std::is_nothrow_constructible<D, path, directory_options, std::error_code&>::value, ""); |
| } |
| |
| static void test_construction_from_bad_path() |
| { |
| static_test_env static_env; |
| std::error_code ec; |
| directory_options opts = directory_options::none; |
| const RDI endIt; |
| |
| const path testPaths[] = { static_env.DNE, static_env.BadSymlink }; |
| for (path const& testPath : testPaths) |
| { |
| { |
| RDI it(testPath, ec); |
| assert(ec); |
| assert(it == endIt); |
| } |
| { |
| RDI it(testPath, opts, ec); |
| assert(ec); |
| assert(it == endIt); |
| } |
| { |
| TEST_THROWS_TYPE(filesystem_error, RDI(testPath)); |
| TEST_THROWS_TYPE(filesystem_error, RDI(testPath, opts)); |
| } |
| } |
| } |
| |
| static void access_denied_test_case() |
| { |
| using namespace fs; |
| #ifdef _WIN32 |
| // Windows doesn't support setting perms::none to trigger failures |
| // reading directories; test using a special inaccessible directory |
| // instead. |
| const path testDir = GetWindowsInaccessibleDir(); |
| if (testDir.empty()) |
| return; |
| #else |
| 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); |
| assert(it != RDI{}); |
| } |
| |
| // Change the permissions so we can no longer iterate |
| permissions(testDir, perms::none); |
| #endif |
| |
| // Check that the construction fails when skip_permissions_denied is |
| // not given. |
| { |
| std::error_code ec; |
| RDI it(testDir, ec); |
| assert(ec); |
| assert(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); |
| assert(!ec); |
| assert(it == RDI{}); |
| } |
| } |
| |
| |
| static void access_denied_to_file_test_case() |
| { |
| using namespace fs; |
| #ifdef _WIN32 |
| // Windows doesn't support setting perms::none to trigger failures |
| // reading directories; test using a special inaccessible directory |
| // instead. |
| const path testDir = GetWindowsInaccessibleDir(); |
| if (testDir.empty()) |
| return; |
| path const testFile = testDir / "inaccessible_file"; |
| #else |
| 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); |
| #endif |
| |
| // Check that the construction fails when skip_permissions_denied is |
| // not given. |
| { |
| std::error_code ec; |
| RDI it(testFile, ec); |
| assert(ec); |
| assert(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); |
| assert(ec); |
| assert(it == RDI{}); |
| } |
| } |
| |
| static void 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); |
| assert(!ec); |
| assert(it == endIt); |
| } |
| { |
| RDI it(testDir); |
| assert(it == endIt); |
| } |
| } |
| |
| static void test_open_on_directory_succeeds() |
| { |
| static_test_env static_env; |
| const path testDir = static_env.Dir; |
| std::set<path> dir_contents(static_env.DirIterationList.begin(), |
| static_env.DirIterationList.end()); |
| const RDI endIt{}; |
| |
| { |
| std::error_code ec; |
| RDI it(testDir, ec); |
| assert(!ec); |
| assert(it != endIt); |
| assert(dir_contents.count(*it)); |
| } |
| { |
| RDI it(testDir); |
| assert(it != endIt); |
| assert(dir_contents.count(*it)); |
| } |
| } |
| |
| static void test_open_on_file_fails() |
| { |
| static_test_env static_env; |
| const path testFile = static_env.File; |
| const RDI endIt{}; |
| { |
| std::error_code ec; |
| RDI it(testFile, ec); |
| assert(ec); |
| assert(it == endIt); |
| } |
| { |
| TEST_THROWS_TYPE(filesystem_error, RDI(testFile)); |
| } |
| } |
| |
| static void test_options_post_conditions() |
| { |
| static_test_env static_env; |
| const path goodDir = static_env.Dir; |
| const path badDir = static_env.DNE; |
| |
| { |
| std::error_code ec; |
| |
| RDI it1(goodDir, ec); |
| assert(!ec); |
| assert(it1.options() == directory_options::none); |
| |
| RDI it2(badDir, ec); |
| assert(ec); |
| assert(it2 == RDI{}); |
| } |
| { |
| std::error_code ec; |
| const directory_options opts = directory_options::skip_permission_denied; |
| |
| RDI it1(goodDir, opts, ec); |
| assert(!ec); |
| assert(it1.options() == opts); |
| |
| RDI it2(badDir, opts, ec); |
| assert(ec); |
| assert(it2 == RDI{}); |
| } |
| { |
| RDI it(goodDir); |
| assert(it.options() == directory_options::none); |
| } |
| { |
| const directory_options opts = directory_options::follow_directory_symlink; |
| RDI it(goodDir, opts); |
| assert(it.options() == opts); |
| } |
| } |
| |
| int main(int, char**) { |
| test_constructor_signatures(); |
| test_construction_from_bad_path(); |
| access_denied_test_case(); |
| access_denied_to_file_test_case(); |
| test_open_on_empty_directory_equals_end(); |
| test_open_on_directory_succeeds(); |
| test_open_on_file_fails(); |
| test_options_post_conditions(); |
| |
| return 0; |
| } |