190 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 status(const path& p);20// file_status 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(status(p));35 ASSERT_NOEXCEPT(status(p, ec));36}37 38static void test_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.DNE,44 static_env.BadSymlink45 };46 for (auto& p : cases) {47 std::error_code ec = std::make_error_code(std::errc::address_in_use);48 // test non-throwing overload.49 file_status st = status(p, ec);50 assert(ErrorIs(ec, expect_errc));51 assert(st.type() == file_type::not_found);52 assert(st.permissions() == perms::unknown);53 // test throwing overload. It should not throw even though it reports54 // that the file was not found.55 TEST_DOES_NOT_THROW(st = status(p));56 assert(st.type() == file_type::not_found);57 assert(st.permissions() == perms::unknown);58 }59}60 61// Windows doesn't support setting perms::none to trigger failures62// reading directories. Imaginary files under GetWindowsInaccessibleDir()63// produce no_such_file_or_directory, not the error codes this test checks64// for. Finally, status() for a too long file name doesn't return errors65// on windows.66#ifndef TEST_WIN_NO_FILESYSTEM_PERMS_NONE67static void test_status_cannot_resolve()68{69 scoped_test_env env;70 const path dir = env.create_dir("dir");71 const path file = env.create_file("dir/file", 42);72 const path sym = 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 perm_errc = std::errc::permission_denied;77 const std::errc name_too_long_errc = std::errc::filename_too_long;78 79 struct TestCase {80 path p;81 std::errc expect_errc;82 } const TestCases[] = {83 {file, perm_errc},84 {sym, perm_errc},85 {path(std::string(2500, 'a')), name_too_long_errc}86 };87 for (auto& TC : TestCases)88 {89 { // test non-throwing case90 std::error_code ec = std::make_error_code(set_errc);91 file_status st = status(TC.p, ec);92 assert(ErrorIs(ec, TC.expect_errc));93 assert(st.type() == file_type::none);94 assert(st.permissions() == perms::unknown);95 }96#ifndef TEST_HAS_NO_EXCEPTIONS97 { // test throwing case98 try {99 status(TC.p);100 } catch (filesystem_error const& err) {101 assert(err.path1() == TC.p);102 assert(err.path2() == "");103 assert(ErrorIs(err.code(), TC.expect_errc));104 }105 }106#endif107 }108}109#endif // TEST_WIN_NO_FILESYSTEM_PERMS_NONE110 111static void status_file_types_test()112{113 static_test_env static_env;114 scoped_test_env env;115 struct TestCase {116 path p;117 file_type expect_type;118 } cases[] = {119 {static_env.File, file_type::regular},120 {static_env.SymlinkToFile, file_type::regular},121 {static_env.Dir, file_type::directory},122 {static_env.SymlinkToDir, file_type::directory},123 // file_type::block files tested elsewhere124#ifndef _WIN32125 {static_env.CharFile, file_type::character},126#endif127#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(_WIN32) // No support for domain sockets128 {env.create_socket("socket"), file_type::socket},129#endif130#ifndef _WIN32131 {env.create_fifo("fifo"), file_type::fifo}132#endif133 };134 for (const auto& TC : cases) {135 // test non-throwing case136 std::error_code ec = std::make_error_code(std::errc::address_in_use);137 file_status st = status(TC.p, ec);138 assert(!ec);139 assert(st.type() == TC.expect_type);140 assert(st.permissions() != perms::unknown);141 // test throwing case142 TEST_DOES_NOT_THROW(st = status(TC.p));143 assert(st.type() == TC.expect_type);144 assert(st.permissions() != perms::unknown);145 }146}147 148static void test_block_file()149{150 const path possible_paths[] = {151 "/dev/drive0", // Apple152 "/dev/sda",153 "/dev/loop0"154 };155 path p;156 for (const path& possible_p : possible_paths) {157 std::error_code ec;158 if (exists(possible_p, ec)) {159 p = possible_p;160 break;161 }162 }163 if (p == path{}) {164 // No possible path found.165 return;166 }167 // test non-throwing case168 std::error_code ec = std::make_error_code(std::errc::address_in_use);169 file_status st = status(p, ec);170 assert(!ec);171 assert(st.type() == file_type::block);172 assert(st.permissions() != perms::unknown);173 // test throwing case174 TEST_DOES_NOT_THROW(st = status(p));175 assert(st.type() == file_type::block);176 assert(st.permissions() != perms::unknown);177}178 179int main(int, char**) {180 signature_test();181 test_status_not_found();182#ifndef TEST_WIN_NO_FILESYSTEM_PERMS_NONE183 test_status_cannot_resolve();184#endif185 status_file_types_test();186 test_block_file();187 188 return 0;189}190