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 // REQUIRES: can-create-symlinks
10 // UNSUPPORTED: c++03, c++11, c++14
11 // UNSUPPORTED: no-filesystem
12 // UNSUPPORTED: availability-filesystem-missing
13 
14 // <filesystem>
15 
16 // class recursive_directory_iterator
17 
18 // bool recursion_pending() const;
19 
20 #include <filesystem>
21 #include <type_traits>
22 #include <set>
23 #include <cassert>
24 
25 #include "test_macros.h"
26 #include "filesystem_test_helper.h"
27 namespace fs = std::filesystem;
28 using namespace fs;
29 
initial_value_test()30 static void initial_value_test()
31 {
32     static_test_env static_env;
33     recursive_directory_iterator it(static_env.Dir);
34     assert(it.recursion_pending() == true);
35 }
36 
value_after_copy_construction_and_assignment_test()37 static void value_after_copy_construction_and_assignment_test()
38 {
39     static_test_env static_env;
40     recursive_directory_iterator rec_pending_it(static_env.Dir);
41     recursive_directory_iterator no_rec_pending_it(static_env.Dir);
42     no_rec_pending_it.disable_recursion_pending();
43 
44     { // copy construction
45         recursive_directory_iterator it(rec_pending_it);
46         assert(it.recursion_pending() == true);
47         it.disable_recursion_pending();
48         assert(rec_pending_it.recursion_pending() == true);
49 
50         recursive_directory_iterator it2(no_rec_pending_it);
51         assert(it2.recursion_pending() == false);
52     }
53     { // copy assignment
54         recursive_directory_iterator it(static_env.Dir);
55         it.disable_recursion_pending();
56         it = rec_pending_it;
57         assert(it.recursion_pending() == true);
58         it.disable_recursion_pending();
59         assert(rec_pending_it.recursion_pending() == true);
60 
61         recursive_directory_iterator it2(static_env.Dir);
62         it2 = no_rec_pending_it;
63         assert(it2.recursion_pending() == false);
64     }
65     assert(rec_pending_it.recursion_pending() == true);
66     assert(no_rec_pending_it.recursion_pending() == false);
67 }
68 
69 
value_after_move_construction_and_assignment_test()70 static void value_after_move_construction_and_assignment_test()
71 {
72     static_test_env static_env;
73     recursive_directory_iterator rec_pending_it(static_env.Dir);
74     recursive_directory_iterator no_rec_pending_it(static_env.Dir);
75     no_rec_pending_it.disable_recursion_pending();
76 
77     { // move construction
78         recursive_directory_iterator it_cp(rec_pending_it);
79         recursive_directory_iterator it(std::move(it_cp));
80         assert(it.recursion_pending() == true);
81 
82         recursive_directory_iterator it_cp2(no_rec_pending_it);
83         recursive_directory_iterator it2(std::move(it_cp2));
84         assert(it2.recursion_pending() == false);
85     }
86     { // copy assignment
87         recursive_directory_iterator it(static_env.Dir);
88         it.disable_recursion_pending();
89         recursive_directory_iterator it_cp(rec_pending_it);
90         it = std::move(it_cp);
91         assert(it.recursion_pending() == true);
92 
93         recursive_directory_iterator it2(static_env.Dir);
94         recursive_directory_iterator it_cp2(no_rec_pending_it);
95         it2 = std::move(it_cp2);
96         assert(it2.recursion_pending() == false);
97     }
98     assert(rec_pending_it.recursion_pending() == true);
99     assert(no_rec_pending_it.recursion_pending() == false);
100 }
101 
increment_resets_value()102 static void increment_resets_value()
103 {
104     static_test_env static_env;
105     const recursive_directory_iterator endIt;
106     {
107         recursive_directory_iterator it(static_env.Dir);
108         it.disable_recursion_pending();
109         assert(it.recursion_pending() == false);
110         ++it;
111         assert(it.recursion_pending() == true);
112         assert(it.depth() == 0);
113     }
114     {
115         recursive_directory_iterator it(static_env.Dir);
116         it.disable_recursion_pending();
117         assert(it.recursion_pending() == false);
118         it++;
119         assert(it.recursion_pending() == true);
120         assert(it.depth() == 0);
121     }
122     {
123         recursive_directory_iterator it(static_env.Dir);
124         it.disable_recursion_pending();
125         assert(it.recursion_pending() == false);
126         std::error_code ec;
127         it.increment(ec);
128         assert(it.recursion_pending() == true);
129         assert(it.depth() == 0);
130     }
131 }
132 
pop_does_not_reset_value()133 static void pop_does_not_reset_value()
134 {
135     static_test_env static_env;
136     const recursive_directory_iterator endIt;
137 
138     auto& DE0 = static_env.DirIterationList;
139     std::set<path> notSeenDepth0(DE0.begin(), DE0.end());
140 
141     recursive_directory_iterator it(static_env.Dir);
142     assert(it != endIt);
143 
144     while (it.depth() == 0) {
145         notSeenDepth0.erase(it->path());
146         ++it;
147         assert(it != endIt);
148     }
149     assert(it.depth() == 1);
150     it.disable_recursion_pending();
151     it.pop();
152     // Since the order of iteration is unspecified the pop() could result
153     // in the end iterator. When this is the case it is undefined behavior
154     // to call recursion_pending().
155     if (it == endIt) {
156         assert(notSeenDepth0.empty());
157 #if defined(_LIBCPP_VERSION)
158         assert(it.recursion_pending() == false);
159 #endif
160     } else {
161         assert(! notSeenDepth0.empty());
162         assert(it.recursion_pending() == false);
163     }
164 }
165 
main(int,char **)166 int main(int, char**) {
167     initial_value_test();
168     value_after_copy_construction_and_assignment_test();
169     value_after_move_construction_and_assignment_test();
170     increment_resets_value();
171     pop_does_not_reset_value();
172 
173     return 0;
174 }
175