1 //===----------------------------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is dual licensed under the MIT and the University of Illinois Open 6 // Source Licenses. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 // UNSUPPORTED: c++98, c++03 11 12 // <filesystem> 13 14 // class directory_iterator 15 16 // explicit directory_iterator(const path& p); 17 // directory_iterator(const path& p, directory_options options); 18 // directory_iterator(const path& p, error_code& ec); 19 // directory_iterator(const path& p, directory_options options, error_code& ec); 20 21 #include "filesystem_include.hpp" 22 #include <type_traits> 23 #include <set> 24 #include <cassert> 25 26 #include "test_macros.h" 27 #include "rapid-cxx-test.hpp" 28 #include "filesystem_test_helper.hpp" 29 30 using namespace fs; 31 32 TEST_SUITE(directory_iterator_constructor_tests) 33 34 TEST_CASE(test_constructor_signatures) 35 { 36 using D = directory_iterator; 37 38 // explicit directory_iterator(path const&); 39 static_assert(!std::is_convertible<path, D>::value, ""); 40 static_assert(std::is_constructible<D, path>::value, ""); 41 static_assert(!std::is_nothrow_constructible<D, path>::value, ""); 42 43 // directory_iterator(path const&, error_code&) 44 static_assert(std::is_constructible<D, path, 45 std::error_code&>::value, ""); 46 static_assert(!std::is_nothrow_constructible<D, path, 47 std::error_code&>::value, ""); 48 49 // directory_iterator(path const&, directory_options); 50 static_assert(std::is_constructible<D, path, directory_options>::value, ""); 51 static_assert(!std::is_nothrow_constructible<D, path, directory_options>::value, ""); 52 53 // directory_iterator(path const&, directory_options, error_code&) 54 static_assert(std::is_constructible<D, path, directory_options, 55 std::error_code&>::value, ""); 56 static_assert(!std::is_nothrow_constructible<D, path, directory_options, 57 std::error_code&>::value, ""); 58 59 } 60 61 TEST_CASE(test_construction_from_bad_path) 62 { 63 std::error_code ec; 64 directory_options opts = directory_options::none; 65 const directory_iterator endIt; 66 67 const path testPaths[] = { StaticEnv::DNE, StaticEnv::BadSymlink }; 68 for (path const& testPath : testPaths) 69 { 70 { 71 directory_iterator it(testPath, ec); 72 TEST_CHECK(ec); 73 TEST_CHECK(it == endIt); 74 } 75 { 76 directory_iterator it(testPath, opts, ec); 77 TEST_CHECK(ec); 78 TEST_CHECK(it == endIt); 79 } 80 { 81 TEST_CHECK_THROW(filesystem_error, directory_iterator(testPath)); 82 TEST_CHECK_THROW(filesystem_error, directory_iterator(testPath, opts)); 83 } 84 } 85 } 86 87 TEST_CASE(access_denied_test_case) 88 { 89 using namespace fs; 90 scoped_test_env env; 91 path const testDir = env.make_env_path("dir1"); 92 path const testFile = testDir / "testFile"; 93 env.create_dir(testDir); 94 env.create_file(testFile, 42); 95 96 // Test that we can iterator over the directory before changing the perms 97 { 98 directory_iterator it(testDir); 99 TEST_REQUIRE(it != directory_iterator{}); 100 } 101 // Change the permissions so we can no longer iterate 102 permissions(testDir, perms::none); 103 104 // Check that the construction fails when skip_permissions_denied is 105 // not given. 106 { 107 std::error_code ec; 108 directory_iterator it(testDir, ec); 109 TEST_REQUIRE(ec); 110 TEST_CHECK(it == directory_iterator{}); 111 } 112 // Check that construction does not report an error when 113 // 'skip_permissions_denied' is given. 114 { 115 std::error_code ec; 116 directory_iterator it(testDir, directory_options::skip_permission_denied, ec); 117 TEST_REQUIRE(!ec); 118 TEST_CHECK(it == directory_iterator{}); 119 } 120 } 121 122 123 TEST_CASE(access_denied_to_file_test_case) 124 { 125 using namespace fs; 126 scoped_test_env env; 127 path const testFile = env.make_env_path("file1"); 128 env.create_file(testFile, 42); 129 130 // Change the permissions so we can no longer iterate 131 permissions(testFile, perms::none); 132 133 // Check that the construction fails when skip_permissions_denied is 134 // not given. 135 { 136 std::error_code ec; 137 directory_iterator it(testFile, ec); 138 TEST_REQUIRE(ec); 139 TEST_CHECK(it == directory_iterator{}); 140 } 141 // Check that construction still fails when 'skip_permissions_denied' is given 142 // because we tried to open a file and not a directory. 143 { 144 std::error_code ec; 145 directory_iterator it(testFile, directory_options::skip_permission_denied, ec); 146 TEST_REQUIRE(ec); 147 TEST_CHECK(it == directory_iterator{}); 148 } 149 } 150 151 TEST_CASE(test_open_on_empty_directory_equals_end) 152 { 153 scoped_test_env env; 154 const path testDir = env.make_env_path("dir1"); 155 env.create_dir(testDir); 156 157 const directory_iterator endIt; 158 { 159 std::error_code ec; 160 directory_iterator it(testDir, ec); 161 TEST_CHECK(!ec); 162 TEST_CHECK(it == endIt); 163 } 164 { 165 directory_iterator it(testDir); 166 TEST_CHECK(it == endIt); 167 } 168 } 169 170 TEST_CASE(test_open_on_directory_succeeds) 171 { 172 const path testDir = StaticEnv::Dir; 173 std::set<path> dir_contents(std::begin(StaticEnv::DirIterationList), 174 std::end( StaticEnv::DirIterationList)); 175 const directory_iterator endIt{}; 176 177 { 178 std::error_code ec; 179 directory_iterator it(testDir, ec); 180 TEST_REQUIRE(!ec); 181 TEST_CHECK(it != endIt); 182 TEST_CHECK(dir_contents.count(*it)); 183 } 184 { 185 directory_iterator it(testDir); 186 TEST_CHECK(it != endIt); 187 TEST_CHECK(dir_contents.count(*it)); 188 } 189 } 190 191 TEST_CASE(test_open_on_file_fails) 192 { 193 const path testFile = StaticEnv::File; 194 const directory_iterator endIt{}; 195 { 196 std::error_code ec; 197 directory_iterator it(testFile, ec); 198 TEST_REQUIRE(ec); 199 TEST_CHECK(it == endIt); 200 } 201 { 202 TEST_CHECK_THROW(filesystem_error, directory_iterator(testFile)); 203 } 204 } 205 206 TEST_CASE(test_open_on_empty_string) 207 { 208 const path testPath = ""; 209 const directory_iterator endIt{}; 210 211 std::error_code ec; 212 directory_iterator it(testPath, ec); 213 TEST_CHECK(ec); 214 TEST_CHECK(it == endIt); 215 } 216 217 TEST_CASE(test_open_on_dot_dir) 218 { 219 const path testPath = "."; 220 221 std::error_code ec; 222 directory_iterator it(testPath, ec); 223 TEST_CHECK(!ec); 224 } 225 226 TEST_CASE(test_open_on_symlink) 227 { 228 const path symlinkToDir = StaticEnv::SymlinkToDir; 229 std::set<path> dir_contents; 230 for (path const& p : StaticEnv::DirIterationList) { 231 dir_contents.insert(p.filename()); 232 } 233 const directory_iterator endIt{}; 234 235 { 236 std::error_code ec; 237 directory_iterator it(symlinkToDir, ec); 238 TEST_REQUIRE(!ec); 239 TEST_CHECK(it != endIt); 240 path const& entry = *it; 241 TEST_CHECK(dir_contents.count(entry.filename())); 242 } 243 { 244 std::error_code ec; 245 directory_iterator it(symlinkToDir, 246 directory_options::follow_directory_symlink, ec); 247 TEST_REQUIRE(!ec); 248 TEST_CHECK(it != endIt); 249 path const& entry = *it; 250 TEST_CHECK(dir_contents.count(entry.filename())); 251 } 252 } 253 254 TEST_SUITE_END() 255