• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 recursive_directory_iterator
15 
16 // recursive_directory_iterator& operator++();
17 // recursive_directory_iterator& increment(error_code& ec) noexcept;
18 
19 #include <experimental/filesystem>
20 #include <type_traits>
21 #include <set>
22 #include <cassert>
23 
24 #include "test_macros.h"
25 #include "rapid-cxx-test.hpp"
26 #include "filesystem_test_helper.hpp"
27 #include <iostream>
28 
29 using namespace std::experimental::filesystem;
30 
31 TEST_SUITE(recursive_directory_iterator_increment_tests)
32 
TEST_CASE(test_increment_signatures)33 TEST_CASE(test_increment_signatures)
34 {
35     using D = recursive_directory_iterator;
36     recursive_directory_iterator d; ((void)d);
37     std::error_code ec; ((void)ec);
38 
39     ASSERT_SAME_TYPE(decltype(++d), recursive_directory_iterator&);
40     ASSERT_NOT_NOEXCEPT(++d);
41 
42     ASSERT_SAME_TYPE(decltype(d.increment(ec)), recursive_directory_iterator&);
43     ASSERT_NOEXCEPT(d.increment(ec));
44 }
45 
TEST_CASE(test_prefix_increment)46 TEST_CASE(test_prefix_increment)
47 {
48     const path testDir = StaticEnv::Dir;
49     const std::set<path> dir_contents(std::begin(StaticEnv::RecDirIterationList),
50                                       std::end(  StaticEnv::RecDirIterationList));
51     const recursive_directory_iterator endIt{};
52 
53     std::error_code ec;
54     recursive_directory_iterator it(testDir, ec);
55     TEST_REQUIRE(!ec);
56 
57     std::set<path> unseen_entries = dir_contents;
58     while (!unseen_entries.empty()) {
59         TEST_REQUIRE(it != endIt);
60         const path entry = *it;
61         TEST_REQUIRE(unseen_entries.erase(entry) == 1);
62         recursive_directory_iterator& it_ref = ++it;
63         TEST_CHECK(&it_ref == &it);
64     }
65 
66     TEST_CHECK(it == endIt);
67 }
68 
TEST_CASE(test_postfix_increment)69 TEST_CASE(test_postfix_increment)
70 {
71     const path testDir = StaticEnv::Dir;
72     const std::set<path> dir_contents(std::begin(StaticEnv::RecDirIterationList),
73                                       std::end(  StaticEnv::RecDirIterationList));
74     const recursive_directory_iterator endIt{};
75 
76     std::error_code ec;
77     recursive_directory_iterator it(testDir, ec);
78     TEST_REQUIRE(!ec);
79 
80     std::set<path> unseen_entries = dir_contents;
81     while (!unseen_entries.empty()) {
82         TEST_REQUIRE(it != endIt);
83         const path entry = *it;
84         TEST_REQUIRE(unseen_entries.erase(entry) == 1);
85         const path entry2 = *it++;
86         TEST_CHECK(entry2 == entry);
87     }
88     TEST_CHECK(it == endIt);
89 }
90 
91 
TEST_CASE(test_increment_method)92 TEST_CASE(test_increment_method)
93 {
94     const path testDir = StaticEnv::Dir;
95     const std::set<path> dir_contents(std::begin(StaticEnv::RecDirIterationList),
96                                       std::end(  StaticEnv::RecDirIterationList));
97     const recursive_directory_iterator endIt{};
98 
99     std::error_code ec;
100     recursive_directory_iterator it(testDir, ec);
101     TEST_REQUIRE(!ec);
102 
103     std::set<path> unseen_entries = dir_contents;
104     while (!unseen_entries.empty()) {
105         TEST_REQUIRE(it != endIt);
106         const path entry = *it;
107         TEST_REQUIRE(unseen_entries.erase(entry) == 1);
108         recursive_directory_iterator& it_ref = it.increment(ec);
109         TEST_REQUIRE(!ec);
110         TEST_CHECK(&it_ref == &it);
111     }
112 
113     TEST_CHECK(it == endIt);
114 }
115 
TEST_CASE(test_follow_symlinks)116 TEST_CASE(test_follow_symlinks)
117 {
118     const path testDir = StaticEnv::Dir;
119     auto const& IterList = StaticEnv::RecDirFollowSymlinksIterationList;
120 
121     const std::set<path> dir_contents(std::begin(IterList), std::end(IterList));
122     const recursive_directory_iterator endIt{};
123 
124     std::error_code ec;
125     recursive_directory_iterator it(testDir,
126                               directory_options::follow_directory_symlink, ec);
127     TEST_REQUIRE(!ec);
128 
129     std::set<path> unseen_entries = dir_contents;
130     while (!unseen_entries.empty()) {
131         TEST_REQUIRE(it != endIt);
132         const path entry = *it;
133 
134         TEST_REQUIRE(unseen_entries.erase(entry) == 1);
135         recursive_directory_iterator& it_ref = it.increment(ec);
136         TEST_REQUIRE(!ec);
137         TEST_CHECK(&it_ref == &it);
138     }
139     TEST_CHECK(it == endIt);
140 }
141 
TEST_CASE(access_denied_on_recursion_test_case)142 TEST_CASE(access_denied_on_recursion_test_case)
143 {
144     using namespace std::experimental::filesystem;
145     scoped_test_env env;
146     const path testFiles[] = {
147         env.create_dir("dir1"),
148         env.create_dir("dir1/dir2"),
149         env.create_file("dir1/dir2/file1"),
150         env.create_file("dir1/file2")
151     };
152     const path startDir = testFiles[0];
153     const path permDeniedDir = testFiles[1];
154     const path otherFile = testFiles[3];
155     auto SkipEPerm = directory_options::skip_permission_denied;
156 
157     // Change the permissions so we can no longer iterate
158     permissions(permDeniedDir, perms::none);
159 
160     const recursive_directory_iterator endIt;
161 
162     // Test that recursion resulting in a "EACCESS" error is not ignored
163     // by default.
164     {
165         std::error_code ec = GetTestEC();
166         recursive_directory_iterator it(startDir, ec);
167         TEST_REQUIRE(ec != GetTestEC());
168         TEST_REQUIRE(!ec);
169         while (it != endIt && it->path() != permDeniedDir)
170             ++it;
171         TEST_REQUIRE(it != endIt);
172         TEST_REQUIRE(*it == permDeniedDir);
173 
174         it.increment(ec);
175         TEST_CHECK(ec);
176         TEST_CHECK(it == endIt);
177     }
178     // Same as above but test operator++().
179     {
180         std::error_code ec = GetTestEC();
181         recursive_directory_iterator it(startDir, ec);
182         TEST_REQUIRE(!ec);
183         while (it != endIt && it->path() != permDeniedDir)
184             ++it;
185         TEST_REQUIRE(it != endIt);
186         TEST_REQUIRE(*it == permDeniedDir);
187 
188         TEST_REQUIRE_THROW(filesystem_error, ++it);
189     }
190     // Test that recursion resulting in a "EACCESS" error is ignored when the
191     // correct options are given to the constructor.
192     {
193         std::error_code ec = GetTestEC();
194         recursive_directory_iterator it(startDir, SkipEPerm, ec);
195         TEST_REQUIRE(!ec);
196         TEST_REQUIRE(it != endIt);
197 
198         bool seenOtherFile = false;
199         if (*it == otherFile) {
200             ++it;
201             seenOtherFile = true;
202             TEST_REQUIRE (it != endIt);
203         }
204         TEST_REQUIRE(*it == permDeniedDir);
205 
206         ec = GetTestEC();
207         it.increment(ec);
208         TEST_REQUIRE(!ec);
209 
210         if (seenOtherFile) {
211             TEST_CHECK(it == endIt);
212         } else {
213             TEST_CHECK(it != endIt);
214             TEST_CHECK(*it == otherFile);
215         }
216     }
217     // Test that construction resulting in a "EACCESS" error is not ignored
218     // by default.
219     {
220         std::error_code ec;
221         recursive_directory_iterator it(permDeniedDir, ec);
222         TEST_REQUIRE(ec);
223         TEST_REQUIRE(it == endIt);
224     }
225     // Same as above but testing the throwing constructors
226     {
227         TEST_REQUIRE_THROW(filesystem_error,
228                            recursive_directory_iterator(permDeniedDir));
229     }
230     // Test that construction resulting in a "EACCESS" error constructs the
231     // end iterator when the correct options are given.
232     {
233         std::error_code ec = GetTestEC();
234         recursive_directory_iterator it(permDeniedDir, SkipEPerm, ec);
235         TEST_REQUIRE(!ec);
236         TEST_REQUIRE(it == endIt);
237     }
238 }
239 
240 TEST_SUITE_END()
241