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 // file_status symlink_status(const path& p); 15 // file_status symlink_status(const path& p, error_code& ec) noexcept; 16 17 #include <experimental/filesystem> 18 19 #include "test_macros.h" 20 #include "rapid-cxx-test.hpp" 21 #include "filesystem_test_helper.hpp" 22 23 using namespace std::experimental::filesystem; 24 25 TEST_SUITE(filesystem_symlink_status_test_suite) 26 27 TEST_CASE(signature_test) 28 { 29 const path p; ((void)p); 30 std::error_code ec; ((void)ec); 31 ASSERT_NOT_NOEXCEPT(symlink_status(p)); 32 ASSERT_NOEXCEPT(symlink_status(p, ec)); 33 } 34 35 TEST_CASE(test_symlink_status_not_found) 36 { 37 const std::error_code expect_ec = 38 std::make_error_code(std::errc::no_such_file_or_directory); 39 const path cases[] { 40 StaticEnv::DNE 41 }; 42 for (auto& p : cases) { 43 std::error_code ec = std::make_error_code(std::errc::address_in_use); 44 // test non-throwing overload. 45 file_status st = symlink_status(p, ec); 46 TEST_CHECK(ec == expect_ec); 47 TEST_CHECK(st.type() == file_type::not_found); 48 TEST_CHECK(st.permissions() == perms::unknown); 49 // test throwing overload. It should not throw even though it reports 50 // that the file was not found. 51 TEST_CHECK_NO_THROW(st = status(p)); 52 TEST_CHECK(st.type() == file_type::not_found); 53 TEST_CHECK(st.permissions() == perms::unknown); 54 } 55 } 56 57 TEST_CASE(test_symlink_status_cannot_resolve) 58 { 59 scoped_test_env env; 60 const path dir = env.create_dir("dir"); 61 const path file_in_dir = env.create_file("dir/file", 42); 62 const path sym_in_dir = env.create_symlink("dir/file", "dir/bad_sym"); 63 const path sym_points_in_dir = env.create_symlink("dir/file", "sym"); 64 permissions(dir, perms::none); 65 66 const std::error_code set_ec = 67 std::make_error_code(std::errc::address_in_use); 68 const std::error_code expect_ec = 69 std::make_error_code(std::errc::permission_denied); 70 71 const path fail_cases[] = { 72 file_in_dir, sym_in_dir 73 }; 74 for (auto& p : fail_cases) 75 { 76 { // test non-throwing case 77 std::error_code ec = set_ec; 78 file_status st = symlink_status(p, ec); 79 TEST_CHECK(ec == expect_ec); 80 TEST_CHECK(st.type() == file_type::none); 81 TEST_CHECK(st.permissions() == perms::unknown); 82 } 83 #ifndef TEST_HAS_NO_EXCEPTIONS 84 { // test throwing case 85 try { 86 symlink_status(p); 87 } catch (filesystem_error const& err) { 88 TEST_CHECK(err.path1() == p); 89 TEST_CHECK(err.path2() == ""); 90 TEST_CHECK(err.code() == expect_ec); 91 } 92 } 93 #endif 94 } 95 // Test that a symlink that points into a directory without read perms 96 // can be stat-ed using symlink_status 97 { 98 std::error_code ec = set_ec; 99 file_status st = symlink_status(sym_points_in_dir, ec); 100 TEST_CHECK(!ec); 101 TEST_CHECK(st.type() == file_type::symlink); 102 TEST_CHECK(st.permissions() != perms::unknown); 103 // test non-throwing version 104 TEST_REQUIRE_NO_THROW(st = symlink_status(sym_points_in_dir)); 105 TEST_CHECK(st.type() == file_type::symlink); 106 TEST_CHECK(st.permissions() != perms::unknown); 107 } 108 } 109 110 111 TEST_CASE(symlink_status_file_types_test) 112 { 113 scoped_test_env env; 114 struct TestCase { 115 path p; 116 file_type expect_type; 117 } cases[] = { 118 {StaticEnv::BadSymlink, file_type::symlink}, 119 {StaticEnv::File, file_type::regular}, 120 {StaticEnv::SymlinkToFile, file_type::symlink}, 121 {StaticEnv::Dir, file_type::directory}, 122 {StaticEnv::SymlinkToDir, file_type::symlink}, 123 // Block files tested elsewhere 124 {StaticEnv::CharFile, file_type::character}, 125 #if !defined(__APPLE__) && !defined(__FreeBSD__) // No support for domain sockets 126 {env.create_socket("socket"), file_type::socket}, 127 #endif 128 {env.create_fifo("fifo"), file_type::fifo} 129 }; 130 for (const auto& TC : cases) { 131 // test non-throwing case 132 std::error_code ec = std::make_error_code(std::errc::address_in_use); 133 file_status st = symlink_status(TC.p, ec); 134 TEST_CHECK(!ec); 135 TEST_CHECK(st.type() == TC.expect_type); 136 TEST_CHECK(st.permissions() != perms::unknown); 137 // test throwing case 138 TEST_REQUIRE_NO_THROW(st = symlink_status(TC.p)); 139 TEST_CHECK(st.type() == TC.expect_type); 140 TEST_CHECK(st.permissions() != perms::unknown); 141 } 142 } 143 144 TEST_CASE(test_block_file) 145 { 146 const path possible_paths[] = { 147 "/dev/drive0", // Apple 148 "/dev/sda", // Linux 149 "/dev/loop0" // Linux 150 // No FreeBSD files known 151 }; 152 path p; 153 for (const path& possible_p : possible_paths) { 154 std::error_code ec; 155 if (exists(possible_p, ec)) { 156 p = possible_p; 157 break; 158 } 159 } 160 if (p == path{}) { 161 TEST_UNSUPPORTED(); 162 } 163 scoped_test_env env; 164 { // test block file 165 // test non-throwing case 166 std::error_code ec = std::make_error_code(std::errc::address_in_use); 167 file_status st = symlink_status(p, ec); 168 TEST_CHECK(!ec); 169 TEST_CHECK(st.type() == file_type::block); 170 TEST_CHECK(st.permissions() != perms::unknown); 171 // test throwing case 172 TEST_REQUIRE_NO_THROW(st = symlink_status(p)); 173 TEST_CHECK(st.type() == file_type::block); 174 TEST_CHECK(st.permissions() != perms::unknown); 175 } 176 const path sym = env.make_env_path("sym"); 177 create_symlink(p, sym); 178 { // test symlink to block file 179 // test non-throwing case 180 std::error_code ec = std::make_error_code(std::errc::address_in_use); 181 file_status st = symlink_status(sym, ec); 182 TEST_CHECK(!ec); 183 TEST_CHECK(st.type() == file_type::symlink); 184 TEST_CHECK(st.permissions() != perms::unknown); 185 // test throwing case 186 TEST_REQUIRE_NO_THROW(st = symlink_status(sym)); 187 TEST_CHECK(st.type() == file_type::symlink); 188 TEST_CHECK(st.permissions() != perms::unknown); 189 } 190 } 191 192 TEST_SUITE_END() 193