1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 // REQUIRES: can-create-symlinks
10 // UNSUPPORTED: c++03, c++11, c++14
11
12 // <filesystem>
13
14 // class directory_entry
15
16 // explicit directory_entry(const path);
17 // directory_entry(const path&, error_code& ec);
18
19 #include <filesystem>
20 #include <type_traits>
21 #include <cassert>
22
23 #include "assert_macros.h"
24 #include "test_macros.h"
25 #include "filesystem_test_helper.h"
26 #include "test_convertible.h"
27 namespace fs = std::filesystem;
28
path_ctor()29 static void path_ctor() {
30 using namespace fs;
31 {
32 static_assert(std::is_constructible<directory_entry, const path&>::value,
33 "directory_entry must be constructible from path");
34 static_assert(
35 !std::is_nothrow_constructible<directory_entry, const path&>::value,
36 "directory_entry constructor should not be noexcept");
37 static_assert(!std::is_convertible<path const&, directory_entry>::value,
38 "directory_entry constructor should be explicit");
39 }
40 {
41 const path p("foo/bar/baz");
42 const directory_entry e(p);
43 assert(e.path() == p);
44 }
45 }
46
path_ec_ctor()47 static void path_ec_ctor() {
48 static_test_env static_env;
49 using namespace fs;
50 {
51 static_assert(
52 std::is_constructible<directory_entry, const path&,
53 std::error_code&>::value,
54 "directory_entry must be constructible from path and error_code");
55 static_assert(!std::is_nothrow_constructible<directory_entry, const path&,
56 std::error_code&>::value,
57 "directory_entry constructor should not be noexcept");
58 static_assert(
59 test_convertible<directory_entry, const path&, std::error_code&>(),
60 "directory_entry constructor should not be explicit");
61 }
62 {
63 std::error_code ec = GetTestEC();
64 const directory_entry e(static_env.File, ec);
65 assert(e.path() == static_env.File);
66 assert(!ec);
67 }
68 {
69 const path p("foo/bar/baz");
70 std::error_code ec = GetTestEC();
71 const directory_entry e(p, ec);
72 assert(e.path() == p);
73 assert(ErrorIs(ec, std::errc::no_such_file_or_directory));
74 }
75 }
76
path_ctor_calls_refresh()77 static void path_ctor_calls_refresh() {
78 using namespace fs;
79 scoped_test_env env;
80 const path dir = env.create_dir("dir");
81 const path file = env.create_file("dir/file", 42);
82 const path sym = env.create_symlink("dir/file", "sym");
83
84 {
85 directory_entry ent(file);
86 std::error_code ec = GetTestEC();
87 directory_entry ent_ec(file, ec);
88 assert(!ec);
89
90 LIBCPP_ONLY(remove(file));
91
92 assert(ent.exists());
93 assert(ent_ec.exists());
94
95 assert(ent.file_size() == 42);
96 assert(ent_ec.file_size() == 42);
97 }
98
99 env.create_file("dir/file", 101);
100
101 {
102 directory_entry ent(sym);
103 std::error_code ec = GetTestEC();
104 directory_entry ent_ec(sym, ec);
105 assert(!ec);
106
107 LIBCPP_ONLY(remove(file));
108 LIBCPP_ONLY(remove(sym));
109
110 assert(ent.is_symlink());
111 assert(ent_ec.is_symlink());
112
113 assert(ent.is_regular_file());
114 assert(ent_ec.is_regular_file());
115
116 assert(ent.file_size() == 101);
117 assert(ent_ec.file_size() == 101);
118 }
119 }
120
path_ctor_dne()121 static void path_ctor_dne() {
122 using namespace fs;
123
124 static_test_env static_env;
125
126 {
127 std::error_code ec = GetTestEC();
128 directory_entry ent(static_env.DNE, ec);
129 assert(ErrorIs(ec, std::errc::no_such_file_or_directory));
130 assert(ent.path() == static_env.DNE);
131 }
132 // don't report dead symlinks as an error.
133 {
134 std::error_code ec = GetTestEC();
135 directory_entry ent(static_env.BadSymlink, ec);
136 assert(!ec);
137 assert(ent.path() == static_env.BadSymlink);
138 }
139 // DNE does not cause the constructor to throw
140 {
141 directory_entry ent(static_env.DNE);
142 assert(ent.path() == static_env.DNE);
143
144 directory_entry ent_two(static_env.BadSymlink);
145 assert(ent_two.path() == static_env.BadSymlink);
146 }
147 }
148
path_ctor_cannot_resolve()149 static void path_ctor_cannot_resolve() {
150 using namespace fs;
151 #ifdef _WIN32
152 // Windows doesn't support setting perms::none to trigger failures
153 // reading directories; test using a special inaccessible directory
154 // instead.
155 const path dir = GetWindowsInaccessibleDir();
156 if (dir.empty())
157 return;
158 const path file = dir / "file";
159 {
160 std::error_code ec = GetTestEC();
161 directory_entry ent(file, ec);
162 assert(ErrorIs(ec, std::errc::no_such_file_or_directory));
163 assert(ent.path() == file);
164 }
165 {
166 TEST_DOES_NOT_THROW(directory_entry(file));
167 }
168 #else
169 scoped_test_env env;
170 const path dir = env.create_dir("dir");
171 const path file = env.create_file("dir/file", 42);
172 const path file_out_of_dir = env.create_file("file1", 101);
173 const path sym_out_of_dir = env.create_symlink("dir/file", "sym");
174 const path sym_in_dir = env.create_symlink("dir/file1", "dir/sym2");
175 permissions(dir, perms::none);
176
177 {
178 std::error_code ec = GetTestEC();
179 directory_entry ent(file, ec);
180 assert(ErrorIs(ec, std::errc::permission_denied));
181 assert(ent.path() == file);
182 }
183 {
184 std::error_code ec = GetTestEC();
185 directory_entry ent(sym_in_dir, ec);
186 assert(ErrorIs(ec, std::errc::permission_denied));
187 assert(ent.path() == sym_in_dir);
188 }
189 {
190 std::error_code ec = GetTestEC();
191 directory_entry ent(sym_out_of_dir, ec);
192 assert(!ec);
193 assert(ent.path() == sym_out_of_dir);
194 }
195 {
196 TEST_DOES_NOT_THROW(directory_entry(file));
197 TEST_DOES_NOT_THROW(directory_entry(sym_in_dir));
198 TEST_DOES_NOT_THROW(directory_entry(sym_out_of_dir));
199 }
200 #endif
201 }
202
main(int,char **)203 int main(int, char**) {
204 path_ctor();
205 path_ec_ctor();
206 path_ctor_calls_refresh();
207 path_ctor_dne();
208 path_ctor_cannot_resolve();
209
210 return 0;
211 }
212