libstdc++: Implement std::formatter<std::thread::id> without <sstream> [PR115099]
[official-gcc.git] / libstdc++-v3 / testsuite / 27_io / filesystem / iterators / recursive_directory_iterator.cc
blob5aedf1e2925252821fb1599a53b6f1b76f186116
1 // Copyright (C) 2015-2024 Free Software Foundation, Inc.
2 //
3 // This file is part of the GNU ISO C++ Library. This library is free
4 // software; you can redistribute it and/or modify it under the
5 // terms of the GNU General Public License as published by the
6 // Free Software Foundation; either version 3, or (at your option)
7 // any later version.
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License along
15 // with this library; see the file COPYING3. If not see
16 // <http://www.gnu.org/licenses/>.
18 // { dg-do run { target c++17 } }
19 // { dg-require-filesystem-ts "" }
21 #include <filesystem>
22 #include <testsuite_hooks.h>
23 #include <testsuite_fs.h>
25 namespace fs = std::filesystem;
27 void
28 test01()
30 const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
31 std::error_code ec;
33 // Test non-existent path.
34 const auto p = __gnu_test::nonexistent_path();
35 fs::recursive_directory_iterator iter(p, ec);
36 VERIFY( ec );
37 VERIFY( iter == end(iter) );
39 // Test empty directory.
40 ec = bad_ec;
41 create_directory(p, fs::current_path(), ec);
42 VERIFY( !ec );
43 ec = bad_ec;
44 iter = fs::recursive_directory_iterator(p, ec);
45 VERIFY( !ec );
46 VERIFY( iter == end(iter) );
48 // Test non-empty directory.
49 ec = bad_ec;
50 create_directories(p / "d1/d2", ec);
51 VERIFY( !ec );
52 ec = bad_ec;
53 iter = fs::recursive_directory_iterator(p, ec);
54 VERIFY( !ec );
55 VERIFY( iter != end(iter) );
56 VERIFY( iter->path() == p/"d1" );
57 ++iter;
58 VERIFY( iter->path() == p/"d1/d2" );
59 ++iter;
60 VERIFY( iter == end(iter) );
62 if (__gnu_test::permissions_are_testable())
64 // Test inaccessible directory.
65 ec = bad_ec;
66 permissions(p, fs::perms::none, ec);
67 VERIFY( !ec );
68 iter = fs::recursive_directory_iterator(p, ec);
69 VERIFY( ec );
70 VERIFY( iter == end(iter) );
72 // Test inaccessible directory, skipping permission denied.
73 const auto opts = fs::directory_options::skip_permission_denied;
74 iter = fs::recursive_directory_iterator(p, opts, ec);
75 VERIFY( !ec );
76 VERIFY( iter == end(iter) );
78 // Test inaccessible sub-directory.
79 ec = bad_ec;
80 permissions(p, fs::perms::owner_all, ec);
81 VERIFY( !ec );
82 ec = bad_ec;
83 permissions(p/"d1/d2", fs::perms::none, ec);
84 VERIFY( !ec );
85 ec = bad_ec;
86 iter = fs::recursive_directory_iterator(p, ec);
87 VERIFY( !ec );
88 VERIFY( iter != end(iter) );
89 VERIFY( iter->path() == p/"d1" );
90 ++iter; // should recurse into d1
91 VERIFY( iter != end(iter) );
92 VERIFY( iter->path() == p/"d1/d2" );
93 iter.increment(ec); // should fail to recurse into p/d1/d2
94 VERIFY( ec );
95 VERIFY( iter == end(iter) );
97 // Test inaccessible sub-directory, skipping permission denied.
98 ec = bad_ec;
99 iter = fs::recursive_directory_iterator(p, opts, ec);
100 VERIFY( !ec );
101 VERIFY( iter != end(iter) );
102 VERIFY( iter->path() == p/"d1" );
103 ++iter; // should recurse into d1
104 VERIFY( iter != end(iter) );
105 VERIFY( iter->path() == p/"d1/d2" );
106 ec = bad_ec;
107 iter.increment(ec); // should fail to recurse into p/d1/d2, so skip it
108 VERIFY( !ec );
109 VERIFY( iter == end(iter) );
112 permissions(p/"d1/d2", fs::perms::owner_all, ec);
113 remove_all(p, ec);
116 void
117 test02()
119 const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
120 std::error_code ec;
121 const auto p = __gnu_test::nonexistent_path();
122 ec = bad_ec;
123 create_directories(p / "d1/d2", ec);
124 VERIFY( !ec );
126 // Test post-increment (libstdc++/71005)
127 ec = bad_ec;
128 auto iter = fs::recursive_directory_iterator(p, ec);
129 VERIFY( !ec );
130 VERIFY( iter != end(iter) );
131 const auto entry1 = *iter;
132 const auto entry2 = *iter++;
133 VERIFY( entry1 == entry2 );
134 VERIFY( entry1.path() == p/"d1" );
135 const auto entry3 = *iter;
136 const auto entry4 = *iter++;
137 VERIFY( entry3 == entry4 );
138 VERIFY( entry3.path() == p/"d1/d2" );
139 VERIFY( iter == end(iter) );
141 remove_all(p, ec);
144 void
145 test03()
147 const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
148 std::error_code ec;
149 const auto p = __gnu_test::nonexistent_path();
150 ec = bad_ec;
151 create_directories(p / "longer_than_small_string_buffer", ec);
152 VERIFY( !ec );
154 // Test for no reallocation on each dereference (this is a GNU extension)
155 auto iter = fs::recursive_directory_iterator(p, ec);
156 const auto* s1 = iter->path().c_str();
157 const auto* s2 = iter->path().c_str();
158 VERIFY( s1 == s2 );
160 remove_all(p, ec);
163 void
164 test04()
166 // libstdc++/71004
167 const fs::recursive_directory_iterator it;
168 VERIFY( it == end(it) );
171 void
172 test05()
174 auto p = __gnu_test::nonexistent_path();
175 create_directory(p);
176 create_directory(p / "x");
177 fs::recursive_directory_iterator it(p), endit;
178 VERIFY( begin(it) == it );
179 static_assert( noexcept(begin(it)), "begin is noexcept" );
180 VERIFY( end(it) == endit );
181 static_assert( noexcept(end(it)), "end is noexcept" );
183 std::error_code ec;
184 remove_all(p, ec);
187 void
188 test06()
190 #ifndef NO_SYMLINKS
191 auto p = __gnu_test::nonexistent_path();
192 create_directories(p/"d1/d2");
193 create_directory_symlink("d1", p/"link");
194 fs::recursive_directory_iterator it(p), endit;
195 VERIFY( std::distance(it, endit) == 3 ); // d1 and d2 and link
197 it = fs::recursive_directory_iterator(p, fs::directory_options::follow_directory_symlink);
198 VERIFY( std::distance(it, endit) == 4 ); // d1 and d1/d2 and link and link/d2
200 std::error_code ec;
201 remove_all(p, ec);
202 #endif
206 main()
208 test01();
209 test02();
210 test03();
211 test04();
212 test05();
213 test06();