1 //===----------------------------------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 // UNSUPPORTED: c++98, c++03
11 
12 // <filesystem>
13 
14 // class recursive_directory_iterator
15 
16 // void pop();
17 // void pop(error_code& ec);
18 
19 #include "filesystem_include.hpp"
20 #include <set>
21 #include <cassert>
22 
23 #include "test_macros.h"
24 #include "rapid-cxx-test.hpp"
25 #include "filesystem_test_helper.hpp"
26 
27 using namespace fs;
28 
29 TEST_SUITE(recursive_directory_iterator_pop_tests)
30 
TEST_CASE(signature_tests)31 TEST_CASE(signature_tests)
32 {
33     recursive_directory_iterator it{}; ((void)it);
34     std::error_code ec; ((void)ec);
35     ASSERT_NOT_NOEXCEPT(it.pop());
36     ASSERT_NOT_NOEXCEPT(it.pop(ec)); // may require allocation or other things
37 }
38 
39 // NOTE: Since the order of iteration is unspecified we use a list of
40 // seen files at each depth to determine the new depth after a 'pop()' operation.
TEST_CASE(test_depth)41 TEST_CASE(test_depth)
42 {
43     const recursive_directory_iterator endIt{};
44 
45     auto& DE0 = StaticEnv::DirIterationList;
46     std::set<path> notSeenDepth0(std::begin(DE0), std::end(DE0));
47 
48     auto& DE1 = StaticEnv::DirIterationListDepth1;
49     std::set<path> notSeenDepth1(std::begin(DE1), std::end(DE1));
50 
51     std::error_code ec;
52     recursive_directory_iterator it(StaticEnv::Dir, ec);
53     TEST_REQUIRE(it != endIt);
54     TEST_CHECK(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         TEST_REQUIRE(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         TEST_REQUIRE(!set_ec);
69 
70         if (it == endIt) {
71             // We must have seen every entry at depth 0 and 1.
72             TEST_REQUIRE(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             TEST_REQUIRE(!notSeenDepth1.empty());
79             TEST_CHECK(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             TEST_REQUIRE(!notSeenDepth0.empty());
86             TEST_REQUIRE(notSeenDepth1.empty());
87             TEST_CHECK(notSeenDepth0.count(it->path()));
88             notSeenDepth0.clear();
89         }
90     }
91 }
92 
93 TEST_SUITE_END()
94