Welcome to mirror list, hosted at ThFree Co, Russian Federation.

runner.cpp « map_handle_create_close « tests « test - github.com/windirstat/llfio.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 2198e7b80f3357529478824044c17e8e0af0995f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/* Integration test kernel for map_handle create and close
(C) 2016-2017 Niall Douglas <http://www.nedproductions.biz/> (8 commits)
File Created: Aug 2016


Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.


Distributed under the Boost Software License, Version 1.0.
    (See accompanying file Licence.txt or copy at
          http://www.boost.org/LICENSE_1_0.txt)
*/

#include "kernel_map_handle.cpp.hpp"

template <class U> inline void map_handle_create_close_(U &&f)
{
  using namespace KERNELTEST_V1_NAMESPACE;
  using LLFIO_V2_NAMESPACE::result;
  using LLFIO_V2_NAMESPACE::file_handle;
  using LLFIO_V2_NAMESPACE::section_handle;
  using LLFIO_V2_NAMESPACE::map_handle;

  // Create a temporary file and put some text into it
  file_handle temph;
  auto boundf = [&](auto... pars) { return f(temph, pars...); };

  // clang-format off
  static const auto permuter(st_permute_parameters<
    result<void>,                               
    parameters<                              
      typename map_handle::size_type,
      typename section_handle::flag
    >,
    precondition::filesystem_setup_parameters,
    postcondition::custom_parameters<bool>
  >(
    {
      { success(),{ 4096, section_handle::flag::none },{ "_" },{ false } },
      { success(),{ 4096, section_handle::flag::read },{ "_" },{ false } },
      { success(),{ 4096, section_handle::flag::write },{ "_" },{ false } },
      { success(),{ 4096, section_handle::flag::cow },{ "_" },{ false } },
      //{ success(),{ 4096, section_handle::flag::execute },{ "_" },{ false } },
      { success(),{ 4096, section_handle::flag::write|section_handle::flag::nocommit },{ "_" },{ false } },
      { success(),{ 4096, section_handle::flag::write|section_handle::flag::prefault },{ "_" },{ false } },
      //{ success(),{ 4096, section_handle::flag::write|section_handle::flag::executable },{ "_" },{ false } },

      { success(),{ 0, section_handle::flag::none },{ "_" },{ true } },
      { success(),{ 0, section_handle::flag::read },{ "_" },{ true } },
      { success(),{ 0, section_handle::flag::write },{ "_" },{ true } },
      { success(),{ 0, section_handle::flag::cow },{ "_" },{ true } },
      //{ success(),{ 0, section_handle::flag::execute },{ "_" },{ true } },
      { success(),{ 0, section_handle::flag::write | section_handle::flag::nocommit },{ "_" },{ true } },
      { success(),{ 0, section_handle::flag::write | section_handle::flag::prefault },{ "_" },{ true } },
      //{ success(),{ 0, section_handle::flag::write|section_handle::flag::executable },{ "_" },{ true } },
  },
    precondition::filesystem_setup(),
    postcondition::custom(
      [&](auto &permuter, auto &testreturn, size_t idx, int use_file_backing) {
        if (use_file_backing)
        {
          // Create a temporary backing file
          temph = file_handle::file({}, "tempfile", file_handle::mode::write, file_handle::creation::if_needed).value();
          temph.write(0, { {reinterpret_cast<const LLFIO_V2_NAMESPACE::byte *>("I am some file data"), 19} }).value();
        }
        else
        {
          // Use the page file
          temph = file_handle();
	      }
        return std::make_tuple(std::ref(permuter), std::ref(testreturn), idx, use_file_backing);
      },
      [&](auto tuplestate) {
        auto &permuter = std::get<0>(tuplestate);
        auto &testreturn = *std::get<1>(tuplestate);
        size_t idx = std::get<2>(tuplestate);
        int use_file_backing = std::get<3>(tuplestate);
        map_handle maph;
        if (testreturn)
        {
          maph = std::move(testreturn.value());
        }
        // Need to close the map and any backing file as otherwise filesystem_setup won't be able to clear up the working dir on Windows
        auto onexit = LLFIO_V2_NAMESPACE::undoer([&]{
          (void) maph.close();
          (void) temph.close();
        });
//#undef KERNELTEST_CHECK
//#define KERNELTEST_CHECK(a, ...) BOOST_CHECK(__VA_ARGS__)
        if (testreturn)
        {
          LLFIO_V2_NAMESPACE::byte *addr = maph.address();
          section_handle::flag flags = std::get<1>(std::get<1>(permuter[idx]));
          KERNELTEST_CHECK(testreturn, maph.length() > 0);
          KERNELTEST_CHECK(testreturn, addr != nullptr);
          if (!(flags & section_handle::flag::nocommit) && addr != nullptr)
          {
            LLFIO_V2_NAMESPACE::byte buffer[64];
            // Make sure the backing file is appearing in the map
            if (use_file_backing && maph.is_readable())
            {
              KERNELTEST_CHECK(testreturn, !memcmp(addr, "I am some file data", 19));
            }
            // Make sure maph's read() does what it is supposed to
            if (use_file_backing)
            {
              auto b = maph.read(0, { {nullptr, 20} }).value();
              KERNELTEST_CHECK(testreturn, b[0].data() == addr);
              KERNELTEST_CHECK(testreturn, b[0].size() == 19);  // reads do not read more than the backing length
            }
            else
            {
              auto b = maph.read(5, { {nullptr, 5000} }).value();
              KERNELTEST_CHECK(testreturn, b[0].data() == addr+5); // NOLINT
              KERNELTEST_CHECK(testreturn, b[0].size() == 4091);
            }
            // If we are writable, write straight into the map
            if (maph.is_writable() && addr)
            {
              memcpy(addr, "NIALL was here", 14);
              // Make sure maph's write() works
              maph.write(1, { {reinterpret_cast<const LLFIO_V2_NAMESPACE::byte *>("iall"), 4} });
              // Make sure data written to the map turns up in the file
              if (use_file_backing)
              {
                temph.read(0, { {buffer, 64} });  // NOLINT
                if (flags & section_handle::flag::cow)
                {
                  KERNELTEST_CHECK(testreturn, !memcmp(buffer, "I am some file data", 19));  // NOLINT
                }
                else
                {
                  KERNELTEST_CHECK(testreturn, !memcmp(buffer, "Niall was here data", 19));  // NOLINT
                }
              }
            }
            // The OS should not auto expand storage to 4Kb
            if (use_file_backing)
            {
              KERNELTEST_CHECK(testreturn, temph.maximum_extent().value() == 19);
            }
          }
        }
      },
    "check mmap")
  ));
  // clang-format on

  auto results = permuter(boundf);
  check_results_with_boost_test(permuter, results);
}

KERNELTEST_TEST_KERNEL(unit, llfio, map_handle_create_close, map_handle, "Tests that llfio::map_handle's creation parameters work as expected", map_handle_create_close_(map_handle_create_close::test_kernel_map_handle))