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 // recursive_directory_iterator& operator=(recursive_directory_iterator 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 
createInterestingIterator(const static_test_env & static_env)30 recursive_directory_iterator createInterestingIterator(const static_test_env &static_env)
31     // Create an "interesting" iterator where all fields are
32     // in a non-default state. The returned 'it' is in a
33     // state such that:
34     //   it.options() == directory_options::skip_permission_denied
35     //   it.depth() == 1
36     //   it.recursion_pending() == true
37 {
38     const path testDir = static_env.Dir;
39     const recursive_directory_iterator endIt;
40     recursive_directory_iterator it(testDir,
41                                     directory_options::skip_permission_denied);
42     assert(it != endIt);
43     while (it.depth() != 1) {
44         ++it;
45         assert(it != endIt);
46     }
47     assert(it.depth() == 1);
48     it.disable_recursion_pending();
49     return it;
50 }
51 
52 
createDifferentInterestingIterator(const static_test_env & static_env)53 recursive_directory_iterator createDifferentInterestingIterator(const static_test_env &static_env)
54     // Create an "interesting" iterator where all fields are
55     // in a non-default state. The returned 'it' is in a
56     // state such that:
57     //   it.options() == directory_options::follow_directory_symlink
58     //   it.depth() == 2
59     //   it.recursion_pending() == false
60 {
61     const path testDir = static_env.Dir;
62     const recursive_directory_iterator endIt;
63     recursive_directory_iterator it(testDir,
64                                     directory_options::follow_directory_symlink);
65     assert(it != endIt);
66     while (it.depth() != 2) {
67         ++it;
68         assert(it != endIt);
69     }
70     assert(it.depth() == 2);
71     return it;
72 }
73 
test_assignment_signature()74 static void test_assignment_signature() {
75     using D = recursive_directory_iterator;
76     static_assert(std::is_copy_assignable<D>::value, "");
77 }
78 
test_copy_to_end_iterator()79 static void test_copy_to_end_iterator()
80 {
81     static_test_env static_env;
82     const recursive_directory_iterator endIt;
83 
84     const recursive_directory_iterator from = createInterestingIterator(static_env);
85     const path entry = *from;
86 
87     recursive_directory_iterator to;
88     to = from;
89     assert(to == from);
90     assert(*to == entry);
91     assert(to.options() == from.options());
92     assert(to.depth() == from.depth());
93     assert(to.recursion_pending() == from.recursion_pending());
94 }
95 
96 
test_copy_from_end_iterator()97 static void test_copy_from_end_iterator()
98 {
99     static_test_env static_env;
100     const recursive_directory_iterator from;
101     recursive_directory_iterator to = createInterestingIterator(static_env);
102 
103     to = from;
104     assert(to == from);
105     assert(to == recursive_directory_iterator{});
106 }
107 
test_copy_valid_iterator()108 static void test_copy_valid_iterator()
109 {
110     static_test_env static_env;
111     const recursive_directory_iterator endIt;
112 
113     const recursive_directory_iterator it = createInterestingIterator(static_env);
114     const path entry = *it;
115 
116     recursive_directory_iterator it2 = createDifferentInterestingIterator(static_env);
117     assert(it2                   != it);
118     assert(it2.options()           != it.options());
119     assert(it2.depth()             != it.depth());
120     assert(it2.recursion_pending() != it.recursion_pending());
121     assert(*it2                    != entry);
122 
123     it2 = it;
124     assert(it2                   == it);
125     assert(it2.options()           == it.options());
126     assert(it2.depth()             == it.depth());
127     assert(it2.recursion_pending() == it.recursion_pending());
128     assert(*it2                    == entry);
129 }
130 
test_returns_reference_to_self()131 static void test_returns_reference_to_self()
132 {
133     const recursive_directory_iterator it;
134     recursive_directory_iterator it2;
135     recursive_directory_iterator& ref = (it2 = it);
136     assert(&ref == &it2);
137 }
138 
test_self_copy()139 static void test_self_copy()
140 {
141     static_test_env static_env;
142     // Create two non-equal iterators that have exactly the same state.
143     recursive_directory_iterator it = createInterestingIterator(static_env);
144     recursive_directory_iterator it2 = createInterestingIterator(static_env);
145     assert(it != it2);
146     assert(it2.options()           == it.options());
147     assert(it2.depth()             == it.depth());
148     assert(it2.recursion_pending() == it.recursion_pending());
149     assert(*it2 == *it);
150 
151     // perform a self-copy and check that the state still matches the
152     // other unmodified iterator.
153     recursive_directory_iterator const& cit = it;
154     it = cit;
155     assert(it2.options()           == it.options());
156     assert(it2.depth()             == it.depth());
157     assert(it2.recursion_pending() == it.recursion_pending());
158     assert(*it2 == *it);
159 }
160 
main(int,char **)161 int main(int, char**) {
162     test_assignment_signature();
163     test_copy_to_end_iterator();
164     test_copy_from_end_iterator();
165     test_copy_valid_iterator();
166     test_returns_reference_to_self();
167     test_self_copy();
168 
169     return 0;
170 }
171