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 // void pop();
19 // void pop(error_code& ec);
20 
21 #include <filesystem>
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 
signature_tests()30 static void signature_tests()
31 {
32     recursive_directory_iterator it{}; ((void)it);
33     std::error_code ec; ((void)ec);
34     ASSERT_NOT_NOEXCEPT(it.pop());
35     ASSERT_NOT_NOEXCEPT(it.pop(ec)); // may require allocation or other things
36 }
37 
38 // NOTE: Since the order of iteration is unspecified we use a list of
39 // seen files at each depth to determine the new depth after a 'pop()' operation.
test_depth()40 static void test_depth()
41 {
42     static_test_env static_env;
43     const recursive_directory_iterator endIt{};
44 
45     auto& DE0 = static_env.DirIterationList;
46     std::set<path> notSeenDepth0(DE0.begin(), DE0.end());
47 
48     auto& DE1 = static_env.DirIterationListDepth1;
49     std::set<path> notSeenDepth1(DE1.begin(), DE1.end());
50 
51     std::error_code ec;
52     recursive_directory_iterator it(static_env.Dir, ec);
53     assert(it != endIt);
54     assert(it.depth() == 0);
55 
56     while (it.depth() != 2) {
57         if (it.depth() == 0)
58             notSeenDepth0.erase(it->path());
59         else
60             notSeenDepth1.erase(it->path());
61         ++it;
62         assert(it != endIt);
63     }
64 
65     while (true) {
66         auto set_ec = std::make_error_code(std::errc::address_in_use);
67         it.pop(set_ec);
68         assert(!set_ec);
69 
70         if (it == endIt) {
71             // We must have seen every entry at depth 0 and 1.
72             assert(notSeenDepth0.empty() && notSeenDepth1.empty());
73             break;
74         }
75         else if (it.depth() == 1) {
76             // If we popped to depth 1 then there must be unseen entries
77             // at this level.
78             assert(!notSeenDepth1.empty());
79             assert(notSeenDepth1.count(it->path()));
80             notSeenDepth1.clear();
81         }
82         else if (it.depth() == 0) {
83             // If we popped to depth 0 there must be unseen entries at this
84             // level. There should also be no unseen entries at depth 1.
85             assert(!notSeenDepth0.empty());
86             assert(notSeenDepth1.empty());
87             assert(notSeenDepth0.count(it->path()));
88             notSeenDepth0.clear();
89         }
90     }
91 }
92 
main(int,char **)93 int main(int, char**) {
94     signature_tests();
95     test_depth();
96 
97     return 0;
98 }
99