• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // void permissions(const path& p, perms prms);
15 // void permissions(const path& p, perms prms, std::error_code& ec) noexcept;
16 
17 
18 #include <experimental/filesystem>
19 
20 #include "test_macros.h"
21 #include "rapid-cxx-test.hpp"
22 #include "filesystem_test_helper.hpp"
23 
24 using namespace std::experimental::filesystem;
25 namespace fs = std::experimental::filesystem;
26 
27 using PR = fs::perms;
28 
29 TEST_SUITE(filesystem_permissions_test_suite)
30 
TEST_CASE(test_signatures)31 TEST_CASE(test_signatures)
32 {
33     const path p; ((void)p);
34     const perms opts{}; ((void)opts);
35     std::error_code ec; ((void)ec);
36     ASSERT_NOT_NOEXCEPT(fs::permissions(p, opts));
37     // Not noexcept because of narrow contract
38     LIBCPP_ONLY(
39         ASSERT_NOT_NOEXCEPT(fs::permissions(p, opts, ec)));
40 }
41 
TEST_CASE(test_error_reporting)42 TEST_CASE(test_error_reporting)
43 {
44     auto checkThrow = [](path const& f, fs::perms opts, const std::error_code& ec)
45     {
46 #ifndef TEST_HAS_NO_EXCEPTIONS
47         try {
48             fs::permissions(f, opts);
49             return false;
50         } catch (filesystem_error const& err) {
51             return err.path1() == f
52                 && err.path2() == ""
53                 && err.code() == ec;
54         }
55 #else
56         ((void)f); ((void)opts); ((void)ec);
57         return true;
58 #endif
59     };
60 
61     scoped_test_env env;
62     const path dne = env.make_env_path("dne");
63     const path dne_sym = env.create_symlink(dne, "dne_sym");
64     { // !exists
65         std::error_code ec;
66         fs::permissions(dne, fs::perms{}, ec);
67         TEST_REQUIRE(ec);
68         TEST_CHECK(checkThrow(dne, fs::perms{}, ec));
69     }
70     {
71         std::error_code ec;
72         fs::permissions(dne_sym, fs::perms{}, ec);
73         TEST_REQUIRE(ec);
74         TEST_CHECK(checkThrow(dne_sym, fs::perms{}, ec));
75     }
76 }
77 
TEST_CASE(basic_permissions_test)78 TEST_CASE(basic_permissions_test)
79 {
80     scoped_test_env env;
81     const path file = env.create_file("file1", 42);
82     const path dir = env.create_dir("dir1");
83     const path file_for_sym = env.create_file("file2", 42);
84     const path sym = env.create_symlink(file_for_sym, "sym");
85     const perms AP = perms::add_perms;
86     const perms RP = perms::remove_perms;
87     const perms NF = perms::symlink_nofollow;
88     struct TestCase {
89       path p;
90       perms set_perms;
91       perms expected;
92     } cases[] = {
93         // test file
94         {file, perms::none, perms::none},
95         {file, perms::owner_all, perms::owner_all},
96         {file, perms::group_all | AP, perms::owner_all | perms::group_all},
97         {file, perms::group_all | RP, perms::owner_all},
98         // test directory
99         {dir, perms::none, perms::none},
100         {dir, perms::owner_all, perms::owner_all},
101         {dir, perms::group_all | AP, perms::owner_all | perms::group_all},
102         {dir, perms::group_all | RP, perms::owner_all},
103         // test symlink without symlink_nofollow
104         {sym, perms::none, perms::none},
105         {sym, perms::owner_all, perms::owner_all},
106         {sym, perms::group_all | AP, perms::owner_all | perms::group_all},
107         {sym, perms::group_all | RP , perms::owner_all},
108         // test non-symlink with symlink_nofollow. The last test on file/dir
109         // will have set their permissions to perms::owner_all
110         {file, perms::group_all | AP | NF, perms::owner_all | perms::group_all},
111         {dir,  perms::group_all | AP | NF, perms::owner_all | perms::group_all}
112     };
113     for (auto const& TC : cases) {
114         TEST_CHECK(status(TC.p).permissions() != TC.expected);
115         // Set the error code to ensure it's cleared.
116         std::error_code ec = std::make_error_code(std::errc::bad_address);
117         permissions(TC.p, TC.set_perms, ec);
118         TEST_CHECK(!ec);
119         auto pp = status(TC.p).permissions();
120         TEST_CHECK(pp == TC.expected);
121     }
122 }
123 
TEST_CASE(test_no_resolve_symlink_on_symlink)124 TEST_CASE(test_no_resolve_symlink_on_symlink)
125 {
126     scoped_test_env env;
127     const path file = env.create_file("file", 42);
128     const path sym = env.create_symlink(file, "sym");
129     const auto file_perms = status(file).permissions();
130 
131     struct TestCase {
132         perms set_perms;
133         perms expected; // only expected on platform that support symlink perms.
134     } cases[] = {
135         {perms::owner_all, perms::owner_all},
136         {perms::group_all | perms::add_perms, perms::owner_all | perms::group_all},
137         {perms::owner_all | perms::remove_perms, perms::group_all},
138     };
139     for (auto const& TC : cases) {
140 #if defined(__APPLE__) || defined(__FreeBSD__)
141         // On OS X symlink permissions are supported. We should get an empty
142         // error code and the expected permissions.
143         const auto expected_link_perms = TC.expected;
144         std::error_code expected_ec;
145 #else
146         // On linux symlink permissions are not supported. The error code should
147         // be 'operation_not_supported' and the symlink permissions should be
148         // unchanged.
149         const auto expected_link_perms = symlink_status(sym).permissions();
150         std::error_code expected_ec = std::make_error_code(std::errc::operation_not_supported);
151 #endif
152         std::error_code ec = std::make_error_code(std::errc::bad_address);
153         permissions(sym, TC.set_perms | perms::symlink_nofollow, ec);
154         TEST_CHECK(ec == expected_ec);
155         TEST_CHECK(status(file).permissions() == file_perms);
156         TEST_CHECK(symlink_status(sym).permissions() == expected_link_perms);
157     }
158 }
159 
160 TEST_SUITE_END()
161