Home | History | Annotate | Download | only in fs.op.symlink_status
      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