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