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