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 // file_status symlink_status(const path& p);
15 // file_status symlink_status(const path& p, error_code& ec) noexcept;
16
17 #include "filesystem_include.hpp"
18
19 #include "test_macros.h"
20 #include "rapid-cxx-test.hpp"
21 #include "filesystem_test_helper.hpp"
22
23 using namespace fs;
24
25 TEST_SUITE(filesystem_symlink_status_test_suite)
26
TEST_CASE(signature_test)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
TEST_CASE(test_symlink_status_not_found)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
TEST_CASE(test_symlink_status_cannot_resolve)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
TEST_CASE(symlink_status_file_types_test)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
TEST_CASE(test_block_file)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