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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // UNSUPPORTED: c++03
10 
11 // <filesystem>
12 
13 // space_info space(const path& p);
14 // space_info space(const path& p, error_code& ec) noexcept;
15 
16 #include "filesystem_include.h"
17 
18 #include "test_macros.h"
19 #include "rapid-cxx-test.h"
20 #include "filesystem_test_helper.h"
21 
22 using namespace fs;
23 
EqualDelta(std::uintmax_t x,std::uintmax_t y,std::uintmax_t delta)24 bool EqualDelta(std::uintmax_t x, std::uintmax_t y, std::uintmax_t delta) {
25     if (x >= y) {
26         return (x - y) <= delta;
27     } else {
28         return (y - x) <= delta;
29     }
30 }
31 
32 TEST_SUITE(filesystem_space_test_suite)
33 
TEST_CASE(signature_test)34 TEST_CASE(signature_test)
35 {
36     const path p; ((void)p);
37     std::error_code ec; ((void)ec);
38     ASSERT_SAME_TYPE(decltype(space(p)), space_info);
39     ASSERT_SAME_TYPE(decltype(space(p, ec)), space_info);
40     ASSERT_NOT_NOEXCEPT(space(p));
41     ASSERT_NOEXCEPT(space(p, ec));
42 }
43 
TEST_CASE(test_error_reporting)44 TEST_CASE(test_error_reporting)
45 {
46     static_test_env static_env;
47     auto checkThrow = [](path const& f, const std::error_code& ec)
48     {
49 #ifndef TEST_HAS_NO_EXCEPTIONS
50         try {
51             (void)space(f);
52             return false;
53         } catch (filesystem_error const& err) {
54             return err.path1() == f
55                 && err.path2() == ""
56                 && err.code() == ec;
57         }
58 #else
59         ((void)f); ((void)ec);
60         return true;
61 #endif
62     };
63     const path cases[] = {
64         "",
65         static_env.DNE,
66         static_env.BadSymlink
67     };
68     for (auto& p : cases) {
69         const auto expect = static_cast<std::uintmax_t>(-1);
70         std::error_code ec;
71         space_info info = space(p, ec);
72         TEST_CHECK(ec);
73         TEST_CHECK(info.capacity == expect);
74         TEST_CHECK(info.free == expect);
75         TEST_CHECK(info.available == expect);
76         TEST_CHECK(checkThrow(p, ec));
77     }
78 }
79 
TEST_CASE(basic_space_test)80 TEST_CASE(basic_space_test)
81 {
82     static_test_env static_env;
83 
84     // All the test cases should reside on the same filesystem and therefore
85     // should have the same expected result. Compute this expected result
86     // one and check that it looks semi-sane.
87     const std::uintmax_t bad_value = static_cast<std::uintmax_t>(-1);
88     std::uintmax_t expect_capacity;
89     std::uintmax_t expect_free;
90     std::uintmax_t expect_avail;
91     TEST_REQUIRE(utils::space(static_env.Dir.string(), expect_capacity,
92                               expect_free, expect_avail));
93 
94     // Other processes running on the operating system may have changed
95     // the amount of space available. Check that these are within tolerances.
96     // Currently 5% of capacity
97     const std::uintmax_t delta = expect_capacity / 20;
98     const path cases[] = {
99         static_env.File,
100         static_env.Dir,
101         static_env.Dir2,
102         static_env.SymlinkToFile,
103         static_env.SymlinkToDir
104     };
105     for (auto& p : cases) {
106         std::error_code ec = GetTestEC();
107         space_info info = space(p, ec);
108         TEST_CHECK(!ec);
109         TEST_CHECK(info.capacity != bad_value);
110         TEST_CHECK(expect_capacity == info.capacity);
111         TEST_CHECK(info.free != bad_value);
112         TEST_CHECK(EqualDelta(expect_free, info.free, delta));
113         TEST_CHECK(info.available != bad_value);
114         TEST_CHECK(EqualDelta(expect_avail, info.available, delta));
115     }
116 }
117 
118 TEST_SUITE_END()
119