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 // UNSUPPORTED: c++03
10
11 // <filesystem>
12
13 // class directory_entry
14
15 // directory_entry& operator=(directory_entry const&) = default;
16 // directory_entry& operator=(directory_entry&&) noexcept = default;
17 // void assign(path const&);
18 // void replace_filename(path const&);
19
20 #include "filesystem_include.h"
21 #include <type_traits>
22 #include <cassert>
23
24 #include "test_macros.h"
25 #include "rapid-cxx-test.h"
26 #include "filesystem_test_helper.h"
27
28 TEST_SUITE(directory_entry_mods_suite)
29
TEST_CASE(test_path_assign_method)30 TEST_CASE(test_path_assign_method) {
31 using namespace fs;
32 const path p("foo/bar/baz");
33 const path p2("abc");
34 directory_entry e(p);
35 {
36 static_assert(std::is_same<decltype(e.assign(p)), void>::value,
37 "return type should be void");
38 static_assert(noexcept(e.assign(p)) == false,
39 "operation must not be noexcept");
40 }
41 {
42 TEST_CHECK(e.path() == p);
43 e.assign(p2);
44 TEST_CHECK(e.path() == p2 && e.path() != p);
45 e.assign(p);
46 TEST_CHECK(e.path() == p && e.path() != p2);
47 }
48 }
49
TEST_CASE(test_path_assign_ec_method)50 TEST_CASE(test_path_assign_ec_method) {
51 using namespace fs;
52 const path p("foo/bar/baz");
53 const path p2("abc");
54 {
55 std::error_code ec;
56 directory_entry e(p);
57 static_assert(std::is_same<decltype(e.assign(p, ec)), void>::value,
58 "return type should be void");
59 static_assert(noexcept(e.assign(p, ec)) == false,
60 "operation must not be noexcept");
61 }
62 {
63 directory_entry ent(p);
64 std::error_code ec = GetTestEC();
65 ent.assign(p2, ec);
66 TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
67 TEST_CHECK(ent.path() == p2);
68 }
69 }
70
TEST_CASE(test_assign_calls_refresh)71 TEST_CASE(test_assign_calls_refresh) {
72 using namespace fs;
73 scoped_test_env env;
74 const path dir = env.create_dir("dir");
75 const path file = env.create_file("dir/file", 42);
76 const path sym = env.create_symlink("dir/file", "sym");
77
78 {
79 directory_entry ent;
80 ent.assign(file);
81
82 // removing the file demonstrates that the values where cached previously.
83 LIBCPP_ONLY(remove(file));
84
85 TEST_CHECK(ent.is_regular_file());
86 }
87 env.create_file("dir/file", 101);
88 {
89 directory_entry ent;
90 ent.assign(sym);
91
92 LIBCPP_ONLY(remove(file));
93 LIBCPP_ONLY(remove(sym));
94
95 TEST_CHECK(ent.is_symlink());
96 TEST_CHECK(ent.is_regular_file());
97 }
98 }
99
TEST_CASE(test_assign_propagates_error)100 TEST_CASE(test_assign_propagates_error) {
101 using namespace fs;
102 scoped_test_env env;
103 #ifdef _WIN32
104 // Windows doesn't support setting perms::none to trigger failures
105 // reading directories; test using a special inaccessible directory
106 // instead.
107 const path dir = GetWindowsInaccessibleDir();
108 if (dir.empty())
109 TEST_UNSUPPORTED();
110 const path file = dir / "inaccessible_file";
111 // We can't create files in the inaccessible directory, so this doesn't
112 // test exactly the same as the code below.
113 const path sym_out_of_dir = env.create_symlink(file, "sym");
114 {
115 directory_entry ent;
116 std::error_code ec = GetTestEC();
117 ent.assign(file, ec);
118 TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
119 }
120 #else
121 const path dir = env.create_dir("dir");
122 const path file = env.create_file("dir/file", 42);
123 const path sym_out_of_dir = env.create_symlink("dir/file", "sym");
124 const path file_out_of_dir = env.create_file("file1");
125 const path sym_in_dir = env.create_symlink("file1", "dir/sym1");
126
127 permissions(dir, perms::none);
128
129 {
130 directory_entry ent;
131 std::error_code ec = GetTestEC();
132 ent.assign(file, ec);
133 TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
134 }
135 {
136 directory_entry ent;
137 std::error_code ec = GetTestEC();
138 ent.assign(sym_in_dir, ec);
139 TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
140 }
141 #endif
142 {
143 directory_entry ent;
144 std::error_code ec = GetTestEC();
145 ent.assign(sym_out_of_dir, ec);
146 TEST_CHECK(!ec);
147 }
148 }
149
150 TEST_SUITE_END()
151