summaryrefslogtreecommitdiff
path: root/test/std
diff options
context:
space:
mode:
authorEric Fiselier <eric@efcs.ca>2017-10-30 18:43:21 +0000
committerEric Fiselier <eric@efcs.ca>2017-10-30 18:43:21 +0000
commitfba9cd8c9e50509aceaef0944899cbf89b395b64 (patch)
tree735d4bfb928a7fd70a780443745307e4a1f59518 /test/std
parent3b8f03d964f47d4ca71bbf1d47f11a494c646488 (diff)
Fix PR35078 - recursive directory iterator's increment method throws incorrectly.
The guts of the increment method for recursive_directory_iterator was failing to pass an error code object to calls to status/symlink_status, which can throw under certain conditions. This patch fixes the issues by correctly propagating the error codes. However the noexcept still needs to be removed from the signature, as mentioned in LWG 3014, but that change will be made in a separate commit. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@316939 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/std')
-rw-r--r--test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp246
1 files changed, 246 insertions, 0 deletions
diff --git a/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp b/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp
index 26fc3ca28..e91bd50f2 100644
--- a/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp
+++ b/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp
@@ -237,4 +237,250 @@ TEST_CASE(access_denied_on_recursion_test_case)
}
}
+// See llvm.org/PR35078
+TEST_CASE(test_PR35078)
+{
+ using namespace std::experimental::filesystem;
+ scoped_test_env env;
+ const path testFiles[] = {
+ env.create_dir("dir1"),
+ env.create_dir("dir1/dir2"),
+ env.create_dir("dir1/dir2/dir3"),
+ env.create_file("dir1/file1"),
+ env.create_file("dir1/dir2/dir3/file2")
+ };
+ const path startDir = testFiles[0];
+ const path permDeniedDir = testFiles[1];
+ const path nestedDir = testFiles[2];
+ const path nestedFile = testFiles[3];
+
+ // Change the permissions so we can no longer iterate
+ permissions(permDeniedDir,
+ perms::remove_perms|perms::group_exec
+ |perms::owner_exec|perms::others_exec);
+
+ const std::error_code eacess_ec =
+ std::make_error_code(std::errc::permission_denied);
+ std::error_code ec = GetTestEC();
+
+ const recursive_directory_iterator endIt;
+
+ auto SetupState = [&](bool AllowEAccess, bool& SeenFile3) {
+ SeenFile3 = false;
+ auto Opts = AllowEAccess ? directory_options::skip_permission_denied
+ : directory_options::none;
+ recursive_directory_iterator it(startDir, Opts, ec);
+ while (!ec && it != endIt && *it != nestedDir) {
+ if (*it == nestedFile)
+ SeenFile3 = true;
+ it.increment(ec);
+ }
+ return it;
+ };
+
+ {
+ bool SeenNestedFile = false;
+ recursive_directory_iterator it = SetupState(false, SeenNestedFile);
+ TEST_REQUIRE(it != endIt);
+ TEST_REQUIRE(*it == nestedDir);
+ ec = GetTestEC();
+ it.increment(ec);
+ TEST_CHECK(ec);
+ TEST_CHECK(ec == eacess_ec);
+ TEST_CHECK(it == endIt);
+ }
+ {
+ bool SeenNestedFile = false;
+ recursive_directory_iterator it = SetupState(true, SeenNestedFile);
+ TEST_REQUIRE(it != endIt);
+ TEST_REQUIRE(*it == nestedDir);
+ ec = GetTestEC();
+ it.increment(ec);
+ TEST_CHECK(!ec);
+ if (SeenNestedFile) {
+ TEST_CHECK(it == endIt);
+ } else {
+ TEST_REQUIRE(it != endIt);
+ TEST_CHECK(*it == nestedFile);
+ }
+ }
+}
+
+
+// See llvm.org/PR35078
+TEST_CASE(test_PR35078_with_symlink)
+{
+ using namespace std::experimental::filesystem;
+ scoped_test_env env;
+ const path testFiles[] = {
+ env.create_dir("dir1"),
+ env.create_file("dir1/file1"),
+ env.create_dir("sym_dir"),
+ env.create_dir("sym_dir/nested_sym_dir"),
+ env.create_symlink("sym_dir/nested_sym_dir", "dir1/dir2"),
+ env.create_dir("sym_dir/dir1"),
+ env.create_dir("sym_dir/dir1/dir2"),
+
+ };
+ // const unsigned TestFilesSize = sizeof(testFiles) / sizeof(testFiles[0]);
+ const path startDir = testFiles[0];
+ const path nestedFile = testFiles[1];
+ const path permDeniedDir = testFiles[2];
+ const path symDir = testFiles[4];
+
+ // Change the permissions so we can no longer iterate
+ permissions(permDeniedDir,
+ perms::remove_perms|perms::group_exec
+ |perms::owner_exec|perms::others_exec);
+
+ const std::error_code eacess_ec =
+ std::make_error_code(std::errc::permission_denied);
+ std::error_code ec = GetTestEC();
+
+ const recursive_directory_iterator endIt;
+
+ auto SetupState = [&](bool AllowEAccess, bool FollowSym, bool& SeenFile3) {
+ SeenFile3 = false;
+ auto Opts = AllowEAccess ? directory_options::skip_permission_denied
+ : directory_options::none;
+ if (FollowSym)
+ Opts |= directory_options::follow_directory_symlink;
+ recursive_directory_iterator it(startDir, Opts, ec);
+ while (!ec && it != endIt && *it != symDir) {
+ std::cout << *it << std::endl;
+ if (*it == nestedFile)
+ SeenFile3 = true;
+ it.increment(ec);
+ }
+ return it;
+ };
+
+ struct {
+ bool SkipPermDenied;
+ bool FollowSymlinks;
+ bool ExpectSuccess;
+ } TestCases[] = {
+ // Passing cases
+ {false, false, true}, {true, true, true}, {true, false, true},
+ // Failing cases
+ {false, true, false}
+ };
+ for (auto TC : TestCases) {
+ bool SeenNestedFile = false;
+ recursive_directory_iterator it = SetupState(TC.SkipPermDenied,
+ TC.FollowSymlinks,
+ SeenNestedFile);
+ TEST_REQUIRE(!ec);
+ TEST_REQUIRE(it != endIt);
+ TEST_REQUIRE(*it == symDir);
+ ec = GetTestEC();
+ it.increment(ec);
+ if (TC.ExpectSuccess) {
+ TEST_CHECK(!ec);
+ if (SeenNestedFile) {
+ TEST_CHECK(it == endIt);
+ } else {
+ TEST_REQUIRE(it != endIt);
+ TEST_CHECK(*it == nestedFile);
+ }
+ } else {
+ TEST_CHECK(ec);
+ TEST_CHECK(ec == eacess_ec);
+ TEST_CHECK(it == endIt);
+ }
+ }
+}
+
+
+// See llvm.org/PR35078
+TEST_CASE(test_PR35078_with_symlink_file)
+{
+ using namespace std::experimental::filesystem;
+ scoped_test_env env;
+ const path testFiles[] = {
+ env.create_dir("dir1"),
+ env.create_dir("dir1/dir2"),
+ env.create_file("dir1/file2"),
+ env.create_dir("sym_dir"),
+ env.create_dir("sym_dir/sdir1"),
+ env.create_file("sym_dir/sdir1/sfile1"),
+ env.create_symlink("sym_dir/sdir1/sfile1", "dir1/dir2/file1")
+ };
+ const unsigned TestFilesSize = sizeof(testFiles) / sizeof(testFiles[0]);
+ const path startDir = testFiles[0];
+ const path nestedDir = testFiles[1];
+ const path nestedFile = testFiles[2];
+ const path permDeniedDir = testFiles[3];
+ const path symFile = testFiles[TestFilesSize - 1];
+
+ // Change the permissions so we can no longer iterate
+ permissions(permDeniedDir,
+ perms::remove_perms|perms::group_exec
+ |perms::owner_exec|perms::others_exec);
+
+ const std::error_code eacess_ec =
+ std::make_error_code(std::errc::permission_denied);
+ std::error_code ec = GetTestEC();
+
+ const recursive_directory_iterator EndIt;
+
+ auto SetupState = [&](bool AllowEAccess, bool FollowSym, bool& SeenNestedFile) {
+ SeenNestedFile = false;
+ auto Opts = AllowEAccess ? directory_options::skip_permission_denied
+ : directory_options::none;
+ if (FollowSym)
+ Opts |= directory_options::follow_directory_symlink;
+ recursive_directory_iterator it(startDir, Opts, ec);
+ while (!ec && it != EndIt && *it != nestedDir) {
+ if (*it == nestedFile)
+ SeenNestedFile = true;
+ it.increment(ec);
+ }
+ return it;
+ };
+
+ struct {
+ bool SkipPermDenied;
+ bool FollowSymlinks;
+ bool ExpectSuccess;
+ } TestCases[] = {
+ // Passing cases
+ {false, false, true}, {true, true, true}, {true, false, true},
+ // Failing cases
+ {false, true, false}
+ };
+ for (auto TC : TestCases){
+ bool SeenNestedFile = false;
+ recursive_directory_iterator it = SetupState(TC.SkipPermDenied,
+ TC.FollowSymlinks,
+ SeenNestedFile);
+ TEST_REQUIRE(!ec);
+ TEST_REQUIRE(it != EndIt);
+ TEST_REQUIRE(*it == nestedDir);
+ ec = GetTestEC();
+ it.increment(ec);
+ TEST_REQUIRE(it != EndIt);
+ TEST_CHECK(!ec);
+ TEST_CHECK(*it == symFile);
+ ec = GetTestEC();
+ it.increment(ec);
+ if (TC.ExpectSuccess) {
+ if (!SeenNestedFile) {
+ TEST_CHECK(!ec);
+ TEST_REQUIRE(it != EndIt);
+ TEST_CHECK(*it == nestedFile);
+ ec = GetTestEC();
+ it.increment(ec);
+ }
+ TEST_CHECK(!ec);
+ TEST_CHECK(it == EndIt);
+ } else {
+ TEST_CHECK(ec);
+ TEST_CHECK(ec == eacess_ec);
+ TEST_CHECK(it == EndIt);
+ }
+ }
+}
+
+
TEST_SUITE_END()