brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.2 KiB · 1d405a8 Raw
216 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// REQUIRES: can-create-symlinks10// UNSUPPORTED: c++03, c++11, c++1411// UNSUPPORTED: no-filesystem12 13// Starting in Android N (API 24), SELinux policy prevents the shell user from14// creating a FIFO file.15// XFAIL: LIBCXX-ANDROID-FIXME && !android-device-api={{21|22|23}}16 17// <filesystem>18 19// file_status symlink_status(const path& p);20// file_status symlink_status(const path& p, error_code& ec) noexcept;21 22#include <filesystem>23 24#include "assert_macros.h"25#include "test_macros.h"26#include "filesystem_test_helper.h"27namespace fs = std::filesystem;28using namespace fs;29 30static void signature_test()31{32    const path p; ((void)p);33    std::error_code ec; ((void)ec);34    ASSERT_NOT_NOEXCEPT(symlink_status(p));35    ASSERT_NOEXCEPT(symlink_status(p, ec));36}37 38static void test_symlink_status_not_found()39{40    static_test_env static_env;41    const std::errc expect_errc = std::errc::no_such_file_or_directory;42    const path cases[] {43        static_env.DNE44    };45    for (auto& p : cases) {46        std::error_code ec = std::make_error_code(std::errc::address_in_use);47        // test non-throwing overload.48        file_status st = symlink_status(p, ec);49        assert(ErrorIs(ec, expect_errc));50        assert(st.type() == file_type::not_found);51        assert(st.permissions() == perms::unknown);52        // test throwing overload. It should not throw even though it reports53        // that the file was not found.54        TEST_DOES_NOT_THROW(st = status(p));55        assert(st.type() == file_type::not_found);56        assert(st.permissions() == perms::unknown);57    }58}59 60// Windows doesn't support setting perms::none to trigger failures61// reading directories. Imaginary files under GetWindowsInaccessibleDir()62// produce no_such_file_or_directory, not the error codes this test checks63// for. Finally, status() for a too long file name doesn't return errors64// on windows.65#ifndef TEST_WIN_NO_FILESYSTEM_PERMS_NONE66static void test_symlink_status_cannot_resolve()67{68    scoped_test_env env;69    const path dir = env.create_dir("dir");70    const path file_in_dir = env.create_file("dir/file", 42);71    const path sym_in_dir = env.create_symlink("dir/file", "dir/bad_sym");72    const path sym_points_in_dir = env.create_symlink("dir/file", "sym");73    permissions(dir, perms::none);74 75    const std::errc set_errc = std::errc::address_in_use;76    const std::errc expect_errc = std::errc::permission_denied;77 78    const path fail_cases[] = {79        file_in_dir, sym_in_dir80    };81    for (auto& p : fail_cases)82    {83        { // test non-throwing case84            std::error_code ec = std::make_error_code(set_errc);85            file_status st = symlink_status(p, ec);86            assert(ErrorIs(ec, expect_errc));87            assert(st.type() == file_type::none);88            assert(st.permissions() == perms::unknown);89        }90#ifndef TEST_HAS_NO_EXCEPTIONS91        { // test throwing case92            try {93                (void)symlink_status(p);94            } catch (filesystem_error const& err) {95                assert(err.path1() == p);96                assert(err.path2() == "");97                assert(ErrorIs(err.code(), expect_errc));98            }99        }100#endif101    }102    // Test that a symlink that points into a directory without read perms103    // can be stat-ed using symlink_status104    {105        std::error_code ec = std::make_error_code(set_errc);106        file_status st = symlink_status(sym_points_in_dir, ec);107        assert(!ec);108        assert(st.type() == file_type::symlink);109        assert(st.permissions() != perms::unknown);110        // test non-throwing version111        TEST_DOES_NOT_THROW(st = symlink_status(sym_points_in_dir));112        assert(st.type() == file_type::symlink);113        assert(st.permissions() != perms::unknown);114    }115}116#endif // TEST_WIN_NO_FILESYSTEM_PERMS_NONE117 118 119static void symlink_status_file_types_test()120{121    static_test_env static_env;122    scoped_test_env env;123    struct TestCase {124      path p;125      file_type expect_type;126    } cases[] = {127        {static_env.BadSymlink, file_type::symlink},128        {static_env.File, file_type::regular},129        {static_env.SymlinkToFile, file_type::symlink},130        {static_env.Dir, file_type::directory},131        {static_env.SymlinkToDir, file_type::symlink},132        // file_type::block files tested elsewhere133#ifndef _WIN32134        {static_env.CharFile, file_type::character},135#endif136#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(_WIN32) // No support for domain sockets137        {env.create_socket("socket"), file_type::socket},138#endif139#ifndef _WIN32140        {env.create_fifo("fifo"), file_type::fifo}141#endif142    };143    for (const auto& TC : cases) {144        // test non-throwing case145        std::error_code ec = std::make_error_code(std::errc::address_in_use);146        file_status st = symlink_status(TC.p, ec);147        assert(!ec);148        assert(st.type() == TC.expect_type);149        assert(st.permissions() != perms::unknown);150        // test throwing case151        TEST_DOES_NOT_THROW(st = symlink_status(TC.p));152        assert(st.type() == TC.expect_type);153        assert(st.permissions() != perms::unknown);154    }155}156 157static void test_block_file()158{159    const path possible_paths[] = {160        "/dev/drive0", // Apple161        "/dev/sda",    // Linux162        "/dev/loop0"   // Linux163        // No FreeBSD files known164    };165    path p;166    for (const path& possible_p : possible_paths) {167        std::error_code ec;168        if (exists(possible_p, ec)) {169            p = possible_p;170            break;171        }172    }173    if (p == path{}) {174        // No possible path found.175        return;176    }177    scoped_test_env env;178    { // test block file179        // test non-throwing case180        std::error_code ec = std::make_error_code(std::errc::address_in_use);181        file_status st = symlink_status(p, ec);182        assert(!ec);183        assert(st.type() == file_type::block);184        assert(st.permissions() != perms::unknown);185        // test throwing case186        TEST_DOES_NOT_THROW(st = symlink_status(p));187        assert(st.type() == file_type::block);188        assert(st.permissions() != perms::unknown);189    }190    const path sym = env.make_env_path("sym");191    create_symlink(p, sym);192    { // test symlink to block file193        // test non-throwing case194        std::error_code ec = std::make_error_code(std::errc::address_in_use);195        file_status st = symlink_status(sym, ec);196        assert(!ec);197        assert(st.type() == file_type::symlink);198        assert(st.permissions() != perms::unknown);199        // test throwing case200        TEST_DOES_NOT_THROW(st = symlink_status(sym));201        assert(st.type() == file_type::symlink);202        assert(st.permissions() != perms::unknown);203    }204}205 206int main(int, char**) {207    signature_test();208    test_symlink_status_not_found();209#ifndef TEST_WIN_NO_FILESYSTEM_PERMS_NONE210    test_symlink_status_cannot_resolve();211#endif212    symlink_status_file_types_test();213    test_block_file();214    return 0;215}216