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