280 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// REQUIRES: can-create-symlinks10// UNSUPPORTED: c++03, c++11, c++1411// UNSUPPORTED: no-filesystem12 13// <filesystem>14 15// class directory_iterator16 17//18// explicit recursive_directory_iterator(const path& p);19// recursive_directory_iterator(const path& p, directory_options options);20// recursive_directory_iterator(const path& p, error_code& ec);21// recursive_directory_iterator(const path& p, directory_options options, error_code& ec);22 23#include <filesystem>24#include <type_traits>25#include <set>26#include <cassert>27 28#include "assert_macros.h"29#include "test_macros.h"30#include "filesystem_test_helper.h"31namespace fs = std::filesystem;32using namespace fs;33 34using RDI = recursive_directory_iterator;35 36static void test_constructor_signatures()37{38 using D = recursive_directory_iterator;39 40 // explicit directory_iterator(path const&);41 static_assert(!std::is_convertible<path, D>::value, "");42 static_assert(std::is_constructible<D, path>::value, "");43 static_assert(!std::is_nothrow_constructible<D, path>::value, "");44 45 // directory_iterator(path const&, error_code&)46 static_assert(std::is_constructible<D, path,47 std::error_code&>::value, "");48 static_assert(!std::is_nothrow_constructible<D, path,49 std::error_code&>::value, "");50 51 // directory_iterator(path const&, directory_options);52 static_assert(std::is_constructible<D, path, directory_options>::value, "");53 static_assert(!std::is_nothrow_constructible<D, path, directory_options>::value, "");54 55 // directory_iterator(path const&, directory_options, error_code&)56 static_assert(std::is_constructible<D, path, directory_options, std::error_code&>::value, "");57 static_assert(!std::is_nothrow_constructible<D, path, directory_options, std::error_code&>::value, "");58}59 60static void test_construction_from_bad_path()61{62 static_test_env static_env;63 std::error_code ec;64 directory_options opts = directory_options::none;65 const RDI endIt;66 67 const path testPaths[] = { static_env.DNE, static_env.BadSymlink };68 for (path const& testPath : testPaths)69 {70 {71 RDI it(testPath, ec);72 assert(ec);73 assert(it == endIt);74 }75 {76 RDI it(testPath, opts, ec);77 assert(ec);78 assert(it == endIt);79 }80 {81 TEST_THROWS_TYPE(filesystem_error, RDI(testPath));82 TEST_THROWS_TYPE(filesystem_error, RDI(testPath, opts));83 }84 }85}86 87static void access_denied_test_case()88{89 using namespace fs;90#ifdef _WIN3291 // Windows doesn't support setting perms::none to trigger failures92 // reading directories; test using a special inaccessible directory93 // instead.94 const path testDir = GetWindowsInaccessibleDir();95 if (testDir.empty())96 return;97#else98 scoped_test_env env;99 path const testDir = env.make_env_path("dir1");100 path const testFile = testDir / "testFile";101 env.create_dir(testDir);102 env.create_file(testFile, 42);103 104 // Test that we can iterator over the directory before changing the perms105 {106 RDI it(testDir);107 assert(it != RDI{});108 }109 110 // Change the permissions so we can no longer iterate111 permissions(testDir, perms::none);112#endif113 114 // Check that the construction fails when skip_permissions_denied is115 // not given.116 {117 std::error_code ec;118 RDI it(testDir, ec);119 assert(ec);120 assert(it == RDI{});121 }122 // Check that construction does not report an error when123 // 'skip_permissions_denied' is given.124 {125 std::error_code ec;126 RDI it(testDir, directory_options::skip_permission_denied, ec);127 assert(!ec);128 assert(it == RDI{});129 }130}131 132 133static void access_denied_to_file_test_case()134{135 using namespace fs;136#ifdef _WIN32137 // Windows doesn't support setting perms::none to trigger failures138 // reading directories; test using a special inaccessible directory139 // instead.140 const path testDir = GetWindowsInaccessibleDir();141 if (testDir.empty())142 return;143 path const testFile = testDir / "inaccessible_file";144#else145 scoped_test_env env;146 path const testFile = env.make_env_path("file1");147 env.create_file(testFile, 42);148 149 // Change the permissions so we can no longer iterate150 permissions(testFile, perms::none);151#endif152 153 // Check that the construction fails when skip_permissions_denied is154 // not given.155 {156 std::error_code ec;157 RDI it(testFile, ec);158 assert(ec);159 assert(it == RDI{});160 }161 // Check that construction still fails when 'skip_permissions_denied' is given162 // because we tried to open a file and not a directory.163 {164 std::error_code ec;165 RDI it(testFile, directory_options::skip_permission_denied, ec);166 assert(ec);167 assert(it == RDI{});168 }169}170 171static void test_open_on_empty_directory_equals_end()172{173 scoped_test_env env;174 const path testDir = env.make_env_path("dir1");175 env.create_dir(testDir);176 177 const RDI endIt;178 {179 std::error_code ec;180 RDI it(testDir, ec);181 assert(!ec);182 assert(it == endIt);183 }184 {185 RDI it(testDir);186 assert(it == endIt);187 }188}189 190static void test_open_on_directory_succeeds()191{192 static_test_env static_env;193 const path testDir = static_env.Dir;194 std::set<path> dir_contents(static_env.DirIterationList.begin(),195 static_env.DirIterationList.end());196 const RDI endIt{};197 198 {199 std::error_code ec;200 RDI it(testDir, ec);201 assert(!ec);202 assert(it != endIt);203 assert(dir_contents.count(*it));204 }205 {206 RDI it(testDir);207 assert(it != endIt);208 assert(dir_contents.count(*it));209 }210}211 212static void test_open_on_file_fails()213{214 static_test_env static_env;215 const path testFile = static_env.File;216 const RDI endIt{};217 {218 std::error_code ec;219 RDI it(testFile, ec);220 assert(ec);221 assert(it == endIt);222 }223 {224 TEST_THROWS_TYPE(filesystem_error, RDI(testFile));225 }226}227 228static void test_options_post_conditions()229{230 static_test_env static_env;231 const path goodDir = static_env.Dir;232 const path badDir = static_env.DNE;233 234 {235 std::error_code ec;236 237 RDI it1(goodDir, ec);238 assert(!ec);239 assert(it1.options() == directory_options::none);240 241 RDI it2(badDir, ec);242 assert(ec);243 assert(it2 == RDI{});244 }245 {246 std::error_code ec;247 const directory_options opts = directory_options::skip_permission_denied;248 249 RDI it1(goodDir, opts, ec);250 assert(!ec);251 assert(it1.options() == opts);252 253 RDI it2(badDir, opts, ec);254 assert(ec);255 assert(it2 == RDI{});256 }257 {258 RDI it(goodDir);259 assert(it.options() == directory_options::none);260 }261 {262 const directory_options opts = directory_options::follow_directory_symlink;263 RDI it(goodDir, opts);264 assert(it.options() == opts);265 }266}267 268int main(int, char**) {269 test_constructor_signatures();270 test_construction_from_bad_path();271 access_denied_test_case();272 access_denied_to_file_test_case();273 test_open_on_empty_directory_equals_end();274 test_open_on_directory_succeeds();275 test_open_on_file_fails();276 test_options_post_conditions();277 278 return 0;279}280