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