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 status(const path& p);
15// file_status 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
23using namespace std::experimental::filesystem;
24
25TEST_SUITE(filesystem_status_test_suite)
26
27TEST_CASE(signature_test)
28{
29    const path p; ((void)p);
30    std::error_code ec; ((void)ec);
31    ASSERT_NOT_NOEXCEPT(status(p));
32    ASSERT_NOEXCEPT(status(p, ec));
33}
34
35TEST_CASE(test_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        StaticEnv::BadSymlink
42    };
43    for (auto& p : cases) {
44        std::error_code ec = std::make_error_code(std::errc::address_in_use);
45        // test non-throwing overload.
46        file_status st = status(p, ec);
47        TEST_CHECK(ec == expect_ec);
48        TEST_CHECK(st.type() == file_type::not_found);
49        TEST_CHECK(st.permissions() == perms::unknown);
50        // test throwing overload. It should not throw even though it reports
51        // that the file was not found.
52        TEST_CHECK_NO_THROW(st = status(p));
53        TEST_CHECK(st.type() == file_type::not_found);
54        TEST_CHECK(st.permissions() == perms::unknown);
55    }
56}
57
58TEST_CASE(test_status_cannot_resolve)
59{
60    scoped_test_env env;
61    const path dir = env.create_dir("dir");
62    const path file = env.create_file("dir/file", 42);
63    const path sym = 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 perm_ec =
69        std::make_error_code(std::errc::permission_denied);
70    const std::error_code name_too_long_ec =
71        std::make_error_code(std::errc::filename_too_long);
72
73    struct TestCase {
74      path p;
75      std::error_code expect_ec;
76    } const TestCases[] = {
77      {file, perm_ec},
78      {sym, perm_ec},
79      {path(std::string(2500, 'a')), name_too_long_ec}
80    };
81    for (auto& TC : TestCases)
82    {
83        { // test non-throwing case
84            std::error_code ec = set_ec;
85            file_status st = status(TC.p, ec);
86            TEST_CHECK(ec == TC.expect_ec);
87            TEST_CHECK(st.type() == file_type::none);
88            TEST_CHECK(st.permissions() == perms::unknown);
89        }
90#ifndef TEST_HAS_NO_EXCEPTIONS
91        { // test throwing case
92            try {
93                status(TC.p);
94            } catch (filesystem_error const& err) {
95                TEST_CHECK(err.path1() == TC.p);
96                TEST_CHECK(err.path2() == "");
97                TEST_CHECK(err.code() == TC.expect_ec);
98            }
99        }
100#endif
101    }
102}
103
104TEST_CASE(status_file_types_test)
105{
106    scoped_test_env env;
107    struct TestCase {
108      path p;
109      file_type expect_type;
110    } cases[] = {
111        {StaticEnv::File, file_type::regular},
112        {StaticEnv::SymlinkToFile, file_type::regular},
113        {StaticEnv::Dir, file_type::directory},
114        {StaticEnv::SymlinkToDir, file_type::directory},
115        // Block files tested elsewhere
116        {StaticEnv::CharFile, file_type::character},
117#if !defined(__APPLE__) && !defined(__FreeBSD__) // No support for domain sockets
118        {env.create_socket("socket"), file_type::socket},
119#endif
120        {env.create_fifo("fifo"), file_type::fifo}
121    };
122    for (const auto& TC : cases) {
123        // test non-throwing case
124        std::error_code ec = std::make_error_code(std::errc::address_in_use);
125        file_status st = status(TC.p, ec);
126        TEST_CHECK(!ec);
127        TEST_CHECK(st.type() == TC.expect_type);
128        TEST_CHECK(st.permissions() != perms::unknown);
129        // test throwing case
130        TEST_REQUIRE_NO_THROW(st = status(TC.p));
131        TEST_CHECK(st.type() == TC.expect_type);
132        TEST_CHECK(st.permissions() != perms::unknown);
133    }
134}
135
136TEST_CASE(test_block_file)
137{
138    const path possible_paths[] = {
139        "/dev/drive0", // Apple
140        "/dev/sda",
141        "/dev/loop0"
142    };
143    path p;
144    for (const path& possible_p : possible_paths) {
145        std::error_code ec;
146        if (exists(possible_p, ec)) {
147            p = possible_p;
148            break;
149        }
150    }
151    if (p == path{}) {
152        TEST_UNSUPPORTED();
153    }
154    // test non-throwing case
155    std::error_code ec = std::make_error_code(std::errc::address_in_use);
156    file_status st = status(p, ec);
157    TEST_CHECK(!ec);
158    TEST_CHECK(st.type() == file_type::block);
159    TEST_CHECK(st.permissions() != perms::unknown);
160    // test throwing case
161    TEST_REQUIRE_NO_THROW(st = status(p));
162    TEST_CHECK(st.type() == file_type::block);
163    TEST_CHECK(st.permissions() != perms::unknown);
164}
165
166TEST_SUITE_END()
167