Home | History | Annotate | Download | only in rec.dir.itr.members
      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 // <experimental/filesystem>
     13 
     14 // class recursive_directory_iterator
     15 
     16 // recursive_directory_iterator& operator++();
     17 // recursive_directory_iterator& increment(error_code& ec) noexcept;
     18 
     19 #include <experimental/filesystem>
     20 #include <type_traits>
     21 #include <set>
     22 #include <cassert>
     23 
     24 #include "test_macros.h"
     25 #include "rapid-cxx-test.hpp"
     26 #include "filesystem_test_helper.hpp"
     27 #include <iostream>
     28 
     29 using namespace std::experimental::filesystem;
     30 
     31 TEST_SUITE(recursive_directory_iterator_increment_tests)
     32 
     33 TEST_CASE(test_increment_signatures)
     34 {
     35     using D = recursive_directory_iterator;
     36     recursive_directory_iterator d; ((void)d);
     37     std::error_code ec; ((void)ec);
     38 
     39     ASSERT_SAME_TYPE(decltype(++d), recursive_directory_iterator&);
     40     ASSERT_NOT_NOEXCEPT(++d);
     41 
     42     ASSERT_SAME_TYPE(decltype(d.increment(ec)), recursive_directory_iterator&);
     43     ASSERT_NOEXCEPT(d.increment(ec));
     44 }
     45 
     46 TEST_CASE(test_prefix_increment)
     47 {
     48     const path testDir = StaticEnv::Dir;
     49     const std::set<path> dir_contents(std::begin(StaticEnv::RecDirIterationList),
     50                                       std::end(  StaticEnv::RecDirIterationList));
     51     const recursive_directory_iterator endIt{};
     52 
     53     std::error_code ec;
     54     recursive_directory_iterator it(testDir, ec);
     55     TEST_REQUIRE(!ec);
     56 
     57     std::set<path> unseen_entries = dir_contents;
     58     while (!unseen_entries.empty()) {
     59         TEST_REQUIRE(it != endIt);
     60         const path entry = *it;
     61         TEST_REQUIRE(unseen_entries.erase(entry) == 1);
     62         recursive_directory_iterator& it_ref = ++it;
     63         TEST_CHECK(&it_ref == &it);
     64     }
     65 
     66     TEST_CHECK(it == endIt);
     67 }
     68 
     69 TEST_CASE(test_postfix_increment)
     70 {
     71     const path testDir = StaticEnv::Dir;
     72     const std::set<path> dir_contents(std::begin(StaticEnv::RecDirIterationList),
     73                                       std::end(  StaticEnv::RecDirIterationList));
     74     const recursive_directory_iterator endIt{};
     75 
     76     std::error_code ec;
     77     recursive_directory_iterator it(testDir, ec);
     78     TEST_REQUIRE(!ec);
     79 
     80     std::set<path> unseen_entries = dir_contents;
     81     while (!unseen_entries.empty()) {
     82         TEST_REQUIRE(it != endIt);
     83         const path entry = *it;
     84         TEST_REQUIRE(unseen_entries.erase(entry) == 1);
     85         const path entry2 = *it++;
     86         TEST_CHECK(entry2 == entry);
     87     }
     88     TEST_CHECK(it == endIt);
     89 }
     90 
     91 
     92 TEST_CASE(test_increment_method)
     93 {
     94     const path testDir = StaticEnv::Dir;
     95     const std::set<path> dir_contents(std::begin(StaticEnv::RecDirIterationList),
     96                                       std::end(  StaticEnv::RecDirIterationList));
     97     const recursive_directory_iterator endIt{};
     98 
     99     std::error_code ec;
    100     recursive_directory_iterator it(testDir, ec);
    101     TEST_REQUIRE(!ec);
    102 
    103     std::set<path> unseen_entries = dir_contents;
    104     while (!unseen_entries.empty()) {
    105         TEST_REQUIRE(it != endIt);
    106         const path entry = *it;
    107         TEST_REQUIRE(unseen_entries.erase(entry) == 1);
    108         recursive_directory_iterator& it_ref = it.increment(ec);
    109         TEST_REQUIRE(!ec);
    110         TEST_CHECK(&it_ref == &it);
    111     }
    112 
    113     TEST_CHECK(it == endIt);
    114 }
    115 
    116 TEST_CASE(test_follow_symlinks)
    117 {
    118     const path testDir = StaticEnv::Dir;
    119     auto const& IterList = StaticEnv::RecDirFollowSymlinksIterationList;
    120 
    121     const std::set<path> dir_contents(std::begin(IterList), std::end(IterList));
    122     const recursive_directory_iterator endIt{};
    123 
    124     std::error_code ec;
    125     recursive_directory_iterator it(testDir,
    126                               directory_options::follow_directory_symlink, ec);
    127     TEST_REQUIRE(!ec);
    128 
    129     std::set<path> unseen_entries = dir_contents;
    130     while (!unseen_entries.empty()) {
    131         TEST_REQUIRE(it != endIt);
    132         const path entry = *it;
    133 
    134         TEST_REQUIRE(unseen_entries.erase(entry) == 1);
    135         recursive_directory_iterator& it_ref = it.increment(ec);
    136         TEST_REQUIRE(!ec);
    137         TEST_CHECK(&it_ref == &it);
    138     }
    139     TEST_CHECK(it == endIt);
    140 }
    141 
    142 TEST_CASE(access_denied_on_recursion_test_case)
    143 {
    144     using namespace std::experimental::filesystem;
    145     scoped_test_env env;
    146     const path testFiles[] = {
    147         env.create_dir("dir1"),
    148         env.create_dir("dir1/dir2"),
    149         env.create_file("dir1/dir2/file1"),
    150         env.create_file("dir1/file2")
    151     };
    152     const path startDir = testFiles[0];
    153     const path permDeniedDir = testFiles[1];
    154     const path otherFile = testFiles[3];
    155     auto SkipEPerm = directory_options::skip_permission_denied;
    156 
    157     // Change the permissions so we can no longer iterate
    158     permissions(permDeniedDir, perms::none);
    159 
    160     const recursive_directory_iterator endIt;
    161 
    162     // Test that recursion resulting in a "EACCESS" error is not ignored
    163     // by default.
    164     {
    165         std::error_code ec = GetTestEC();
    166         recursive_directory_iterator it(startDir, ec);
    167         TEST_REQUIRE(ec != GetTestEC());
    168         TEST_REQUIRE(!ec);
    169         while (it != endIt && it->path() != permDeniedDir)
    170             ++it;
    171         TEST_REQUIRE(it != endIt);
    172         TEST_REQUIRE(*it == permDeniedDir);
    173 
    174         it.increment(ec);
    175         TEST_CHECK(ec);
    176         TEST_CHECK(it == endIt);
    177     }
    178     // Same as above but test operator++().
    179     {
    180         std::error_code ec = GetTestEC();
    181         recursive_directory_iterator it(startDir, ec);
    182         TEST_REQUIRE(!ec);
    183         while (it != endIt && it->path() != permDeniedDir)
    184             ++it;
    185         TEST_REQUIRE(it != endIt);
    186         TEST_REQUIRE(*it == permDeniedDir);
    187 
    188         TEST_REQUIRE_THROW(filesystem_error, ++it);
    189     }
    190     // Test that recursion resulting in a "EACCESS" error is ignored when the
    191     // correct options are given to the constructor.
    192     {
    193         std::error_code ec = GetTestEC();
    194         recursive_directory_iterator it(startDir, SkipEPerm, ec);
    195         TEST_REQUIRE(!ec);
    196         TEST_REQUIRE(it != endIt);
    197 
    198         bool seenOtherFile = false;
    199         if (*it == otherFile) {
    200             ++it;
    201             seenOtherFile = true;
    202             TEST_REQUIRE (it != endIt);
    203         }
    204         TEST_REQUIRE(*it == permDeniedDir);
    205 
    206         ec = GetTestEC();
    207         it.increment(ec);
    208         TEST_REQUIRE(!ec);
    209 
    210         if (seenOtherFile) {
    211             TEST_CHECK(it == endIt);
    212         } else {
    213             TEST_CHECK(it != endIt);
    214             TEST_CHECK(*it == otherFile);
    215         }
    216     }
    217     // Test that construction resulting in a "EACCESS" error is not ignored
    218     // by default.
    219     {
    220         std::error_code ec;
    221         recursive_directory_iterator it(permDeniedDir, ec);
    222         TEST_REQUIRE(ec);
    223         TEST_REQUIRE(it == endIt);
    224     }
    225     // Same as above but testing the throwing constructors
    226     {
    227         TEST_REQUIRE_THROW(filesystem_error,
    228                            recursive_directory_iterator(permDeniedDir));
    229     }
    230     // Test that construction resulting in a "EACCESS" error constructs the
    231     // end iterator when the correct options are given.
    232     {
    233         std::error_code ec = GetTestEC();
    234         recursive_directory_iterator it(permDeniedDir, SkipEPerm, ec);
    235         TEST_REQUIRE(!ec);
    236         TEST_REQUIRE(it == endIt);
    237     }
    238 }
    239 
    240 TEST_SUITE_END()
    241