1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
10 // UNSUPPORTED: no-filesystem
11 // UNSUPPORTED: availability-filesystem-missing
15 // class directory_iterator
18 // explicit recursive_directory_iterator(const path& p);
19 // recursive_directory_iterator(const path& p, directory_options options);
20 // recursive_directory_iterator(const path& p, error_code& ec);
21 // recursive_directory_iterator(const path& p, directory_options options, error_code& ec);
24 #include "filesystem_include.h"
25 #include <type_traits>
29 #include "assert_macros.h"
30 #include "test_macros.h"
31 #include "filesystem_test_helper.h"
35 using RDI
= recursive_directory_iterator
;
37 static void test_constructor_signatures()
39 using D
= recursive_directory_iterator
;
41 // explicit directory_iterator(path const&);
42 static_assert(!std::is_convertible
<path
, D
>::value
, "");
43 static_assert(std::is_constructible
<D
, path
>::value
, "");
44 static_assert(!std::is_nothrow_constructible
<D
, path
>::value
, "");
46 // directory_iterator(path const&, error_code&)
47 static_assert(std::is_constructible
<D
, path
,
48 std::error_code
&>::value
, "");
49 static_assert(!std::is_nothrow_constructible
<D
, path
,
50 std::error_code
&>::value
, "");
52 // directory_iterator(path const&, directory_options);
53 static_assert(std::is_constructible
<D
, path
, directory_options
>::value
, "");
54 static_assert(!std::is_nothrow_constructible
<D
, path
, directory_options
>::value
, "");
56 // directory_iterator(path const&, directory_options, error_code&)
57 static_assert(std::is_constructible
<D
, path
, directory_options
, std::error_code
&>::value
, "");
58 static_assert(!std::is_nothrow_constructible
<D
, path
, directory_options
, std::error_code
&>::value
, "");
61 static void test_construction_from_bad_path()
63 static_test_env static_env
;
65 directory_options opts
= directory_options::none
;
68 const path testPaths
[] = { static_env
.DNE
, static_env
.BadSymlink
};
69 for (path
const& testPath
: testPaths
)
77 RDI
it(testPath
, opts
, ec
);
82 TEST_THROWS_TYPE(filesystem_error
, RDI(testPath
));
83 TEST_THROWS_TYPE(filesystem_error
, RDI(testPath
, opts
));
88 static void access_denied_test_case()
92 // Windows doesn't support setting perms::none to trigger failures
93 // reading directories; test using a special inaccessible directory
95 const path testDir
= GetWindowsInaccessibleDir();
100 path
const testDir
= env
.make_env_path("dir1");
101 path
const testFile
= testDir
/ "testFile";
102 env
.create_dir(testDir
);
103 env
.create_file(testFile
, 42);
105 // Test that we can iterator over the directory before changing the perms
111 // Change the permissions so we can no longer iterate
112 permissions(testDir
, perms::none
);
115 // Check that the construction fails when skip_permissions_denied is
123 // Check that construction does not report an error when
124 // 'skip_permissions_denied' is given.
127 RDI
it(testDir
, directory_options::skip_permission_denied
, ec
);
134 static void access_denied_to_file_test_case()
138 // Windows doesn't support setting perms::none to trigger failures
139 // reading directories; test using a special inaccessible directory
141 const path testDir
= GetWindowsInaccessibleDir();
144 path
const testFile
= testDir
/ "inaccessible_file";
147 path
const testFile
= env
.make_env_path("file1");
148 env
.create_file(testFile
, 42);
150 // Change the permissions so we can no longer iterate
151 permissions(testFile
, perms::none
);
154 // Check that the construction fails when skip_permissions_denied is
158 RDI
it(testFile
, ec
);
162 // Check that construction still fails when 'skip_permissions_denied' is given
163 // because we tried to open a file and not a directory.
166 RDI
it(testFile
, directory_options::skip_permission_denied
, ec
);
172 static void test_open_on_empty_directory_equals_end()
175 const path testDir
= env
.make_env_path("dir1");
176 env
.create_dir(testDir
);
191 static void test_open_on_directory_succeeds()
193 static_test_env static_env
;
194 const path testDir
= static_env
.Dir
;
195 std::set
<path
> dir_contents(static_env
.DirIterationList
.begin(),
196 static_env
.DirIterationList
.end());
204 assert(dir_contents
.count(*it
));
209 assert(dir_contents
.count(*it
));
213 static void test_open_on_file_fails()
215 static_test_env static_env
;
216 const path testFile
= static_env
.File
;
220 RDI
it(testFile
, ec
);
225 TEST_THROWS_TYPE(filesystem_error
, RDI(testFile
));
229 static void test_options_post_conditions()
231 static_test_env static_env
;
232 const path goodDir
= static_env
.Dir
;
233 const path badDir
= static_env
.DNE
;
238 RDI
it1(goodDir
, ec
);
240 assert(it1
.options() == directory_options::none
);
244 assert(it2
== RDI
{});
248 const directory_options opts
= directory_options::skip_permission_denied
;
250 RDI
it1(goodDir
, opts
, ec
);
252 assert(it1
.options() == opts
);
254 RDI
it2(badDir
, opts
, ec
);
256 assert(it2
== RDI
{});
260 assert(it
.options() == directory_options::none
);
263 const directory_options opts
= directory_options::follow_directory_symlink
;
264 RDI
it(goodDir
, opts
);
265 assert(it
.options() == opts
);
269 int main(int, char**) {
270 test_constructor_signatures();
271 test_construction_from_bad_path();
272 access_denied_test_case();
273 access_denied_to_file_test_case();
274 test_open_on_empty_directory_equals_end();
275 test_open_on_directory_succeeds();
276 test_open_on_file_fails();
277 test_options_post_conditions();