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++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 static_test_env static_env;
63 std::error_code ec;
64 directory_options opts = directory_options::none;
65 const directory_iterator endIt;
66
67 const path testPaths[] = { static_env.DNE, static_env.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
TEST_CASE(access_denied_test_case)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
TEST_CASE(access_denied_to_file_test_case)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
TEST_CASE(test_open_on_empty_directory_equals_end)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
TEST_CASE(test_open_on_directory_succeeds)170 TEST_CASE(test_open_on_directory_succeeds)
171 {
172 static_test_env static_env;
173 const path testDir = static_env.Dir;
174 std::set<path> dir_contents(static_env.DirIterationList.begin(),
175 static_env.DirIterationList.end());
176 const directory_iterator endIt{};
177
178 {
179 std::error_code ec;
180 directory_iterator it(testDir, ec);
181 TEST_REQUIRE(!ec);
182 TEST_CHECK(it != endIt);
183 TEST_CHECK(dir_contents.count(*it));
184 }
185 {
186 directory_iterator it(testDir);
187 TEST_CHECK(it != endIt);
188 TEST_CHECK(dir_contents.count(*it));
189 }
190 }
191
TEST_CASE(test_open_on_file_fails)192 TEST_CASE(test_open_on_file_fails)
193 {
194 static_test_env static_env;
195 const path testFile = static_env.File;
196 const directory_iterator endIt{};
197 {
198 std::error_code ec;
199 directory_iterator it(testFile, ec);
200 TEST_REQUIRE(ec);
201 TEST_CHECK(it == endIt);
202 }
203 {
204 TEST_CHECK_THROW(filesystem_error, directory_iterator(testFile));
205 }
206 }
207
TEST_CASE(test_open_on_empty_string)208 TEST_CASE(test_open_on_empty_string)
209 {
210 const path testPath = "";
211 const directory_iterator endIt{};
212
213 std::error_code ec;
214 directory_iterator it(testPath, ec);
215 TEST_CHECK(ec);
216 TEST_CHECK(it == endIt);
217 }
218
TEST_CASE(test_open_on_dot_dir)219 TEST_CASE(test_open_on_dot_dir)
220 {
221 const path testPath = ".";
222
223 std::error_code ec;
224 directory_iterator it(testPath, ec);
225 TEST_CHECK(!ec);
226 }
227
TEST_CASE(test_open_on_symlink)228 TEST_CASE(test_open_on_symlink)
229 {
230 static_test_env static_env;
231 const path symlinkToDir = static_env.SymlinkToDir;
232 std::set<path> dir_contents;
233 for (path const& p : static_env.DirIterationList) {
234 dir_contents.insert(p.filename());
235 }
236 const directory_iterator endIt{};
237
238 {
239 std::error_code ec;
240 directory_iterator it(symlinkToDir, ec);
241 TEST_REQUIRE(!ec);
242 TEST_CHECK(it != endIt);
243 path const& entry = *it;
244 TEST_CHECK(dir_contents.count(entry.filename()));
245 }
246 {
247 std::error_code ec;
248 directory_iterator it(symlinkToDir,
249 directory_options::follow_directory_symlink, ec);
250 TEST_REQUIRE(!ec);
251 TEST_CHECK(it != endIt);
252 path const& entry = *it;
253 TEST_CHECK(dir_contents.count(entry.filename()));
254 }
255 }
256
257 TEST_SUITE_END()
258