1// (C) Copyright Jorge Lodos 2008
2// (C) Copyright Jonathan Turkanis 2004
3// Distributed under the Boost Software License, Version 1.0. (See accompanying
4// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
5
6// See http://www.boost.org/libs/iostreams for documentation.
7
8// This is the original (boost 1.34) boost::iostream test for the mapped files with the
9// following modifications:
10// 1. The namespace for the mapped file was changed to seglib::filemap.
11// 2. Added test for privately mapped files.
12// 3. The test test_writeable was added for mapped files.
13// 4. The test test_resizeable was added for mapped files.
14//
15
16#include <fstream>
17#include <boost/config.hpp>
18#include <boost/detail/workaround.hpp>
19#include <boost/test/unit_test.hpp>
20
21#include <boost/iostreams/stream.hpp>
22#include <boost/iostreams/device/mapped_file.hpp>
23#include <boost/filesystem/path.hpp>
24#include "detail/temp_file.hpp"
25#include "detail/verification.hpp"
26
27// Code generation bugs cause tests to fail with global optimization.
28#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
29# pragma optimize("g", off)
30#endif
31
32namespace boost { namespace iostreams { namespace test {
33
34bool test_writeable(mapped_file& mf)
35{
36 // Test writing
37 for (int i = 0; i < data_reps; ++i) {
38 memcpy(dest: mf.data(), src: narrow_data(), n: chunk_size);
39 char buf[chunk_size];
40 memcpy(dest: buf, src: mf.const_data(), n: chunk_size);
41 if (strncmp(s1: buf, s2: narrow_data(), n: chunk_size) != 0)
42 return false;
43 memset(s: mf.data(), c: 0, n: chunk_size);
44 }
45 return true;
46}
47
48bool test_resizeable(mapped_file& mf)
49{
50 // Test resizing
51 mapped_file::size_type size = mf.size();
52 if (size == 0)
53 return false;
54 mf.resize(new_size: size/2);
55 if (mf.size() != size/2)
56 return false;
57 mf.resize(new_size: size);
58 if (mf.size() != size)
59 return false;
60 return true;
61}
62
63} } } // End namespaces test, iostreams, boost.
64
65void mapped_file_test()
66{
67 using namespace boost::iostreams;
68 BOOST_TEST_MESSAGE("about to begin");
69
70 //--------------Reading from a mapped_file_source-------------------------//
71
72 {
73 // Note: the ifstream second is placed in a nested scope because
74 // closing and reopening a single ifstream failed for CW 9.4 on Windows.
75
76 // Test reading from a stream based on a mapped_file_source,
77 // in chars.
78 boost::iostreams::test::test_file test1, test2;
79 boost::iostreams::stream<mapped_file_source> first(test1.name());
80 {
81 std::ifstream second( test2.name().c_str(),
82 BOOST_IOS::in | BOOST_IOS::binary );
83 BOOST_CHECK_MESSAGE(
84 boost::iostreams::test::compare_streams_in_chars(first, second),
85 "failed reading from stream<mapped_file_source> in chars"
86 );
87
88 BOOST_TEST_MESSAGE(
89 "done reading from stream<mapped_file_source> in chars"
90 );
91 }
92 first.close();
93
94 // Test reading from a stream based on a mapped_file_source,
95 // in chunks. (Also tests reopening the stream.)
96 first.open(t: mapped_file_source(test1.name()));
97 {
98 std::ifstream second( test2.name().c_str(),
99 BOOST_IOS::in | BOOST_IOS::binary );
100 BOOST_CHECK_MESSAGE(
101 boost::iostreams::test::compare_streams_in_chunks(first, second),
102 "failed reading from stream<mapped_file_source> in chunks"
103 );
104
105 BOOST_TEST_MESSAGE(
106 "done reading from stream<mapped_file_source> in chunks"
107 );
108 }
109 }
110
111 //--------------Writing to a mapped_file_sink-----------------------------//
112
113 {
114 // Test writing to a stream based on a mapped_file_sink, in
115 // chars.
116 boost::iostreams::test::uppercase_file first, second; // Will overwrite these.
117 boost::iostreams::test::test_file test;
118
119 boost::iostreams::stream<mapped_file_sink> out;
120 out.open(t: mapped_file_sink(first.name()));
121 boost::iostreams::test::write_data_in_chars(os&: out);
122 out.close();
123 BOOST_CHECK_MESSAGE(
124 boost::iostreams::test::compare_files(first.name(), test.name()),
125 "failed writing to stream<mapped_file_sink> in chars"
126 );
127
128 BOOST_TEST_MESSAGE(
129 "done writing to stream<mapped_file_sink> in chars"
130 );
131
132 // Test writing to a stream based on a mapped_file_sink, in
133 // chunks. (Also tests reopening the stream.)
134 out.open(t: mapped_file_sink(second.name()));
135 boost::iostreams::test::write_data_in_chunks(os&: out);
136 out.close();
137 BOOST_CHECK_MESSAGE(
138 boost::iostreams::test::compare_files(second.name(), test.name()),
139 "failed writing to stream<mapped_file_sink> in chunks"
140 );
141
142 BOOST_TEST_MESSAGE(
143 "done writing to stream<mapped_file_sink> in chunks"
144 );
145 }
146
147 //--------------Writing to a newly created file---------------------------//
148
149 {
150 // Test writing to a newly created mapped file.
151 boost::iostreams::test::temp_file first, second;
152 boost::iostreams::test::test_file test;
153
154 mapped_file_params p(first.name());
155 p.new_file_size = boost::iostreams::test::data_reps * boost::iostreams::test::data_length();
156 boost::iostreams::stream<mapped_file_sink> out;
157 out.open(t: mapped_file_sink(p));
158 boost::iostreams::test::write_data_in_chars(os&: out);
159 out.close();
160 BOOST_CHECK_MESSAGE(
161 boost::iostreams::test::compare_files(first.name(), test.name()),
162 "failed writing to newly created mapped file in chars"
163 );
164
165
166 // Test writing to a newly created mapped file.
167 // (Also tests reopening the stream.)
168 p.path = second.name();
169 out.open(t: mapped_file_sink(p));
170 boost::iostreams::test::write_data_in_chunks(os&: out);
171 out.close();
172 BOOST_CHECK_MESSAGE(
173 boost::iostreams::test::compare_files(second.name(), test.name()),
174 "failed writing to newly created mapped file in chunks"
175 );
176 }
177
178 //--------------Writing to a pre-existing file---------------------------//
179 {
180 // Test for Bug #3953 - writing to a pre-existing mapped file.
181 boost::iostreams::test::test_file first, test;
182
183 mapped_file_params p(first.name());
184 p.new_file_size = boost::iostreams::test::data_reps * boost::iostreams::test::data_length();
185 boost::iostreams::stream<mapped_file_sink> out;
186 out.open(t: mapped_file_sink(p));
187 boost::iostreams::test::write_data_in_chars(os&: out);
188 out.close();
189 BOOST_CHECK_MESSAGE(
190 boost::iostreams::test::compare_files(first.name(), test.name()),
191 "failed writing to pre-existing mapped file in chars"
192 );
193 }
194
195 //--------------Random access with a mapped_file--------------------------//
196
197 {
198 // Test reading, writing and seeking within a stream based on a
199 // mapped_file, in chars.
200 boost::iostreams::test::test_file test;
201 boost::iostreams::stream<mapped_file> io;
202 io.open(t: mapped_file(test.name()));
203 BOOST_CHECK_MESSAGE(
204 boost::iostreams::test::test_seekable_in_chars(io),
205 "failed seeking within stream<mapped_file> in chars"
206 );
207
208 BOOST_TEST_MESSAGE(
209 "done seeking within stream<mapped_file> in chars"
210 );
211
212 io.close();
213
214 // Test reading, writing and seeking within a stream based on a
215 // mapped_file, in chunks. (Also tests reopening the
216 // stream.)
217 io.open(t: mapped_file(test.name()));
218 BOOST_CHECK_MESSAGE(
219 boost::iostreams::test::test_seekable_in_chunks(io),
220 "failed seeking within stream<mapped_file> in chunks"
221 );
222
223 BOOST_TEST_MESSAGE(
224 "done seeking within stream<mapped_file> in chunks"
225 );
226 }
227
228 //--------------Resizing a mapped_file------------------------------------//
229
230 {
231 // Test resizing a mapped_file.
232 boost::iostreams::test::test_file test;
233 mapped_file mf;
234 mf.open(path: test.name());
235 BOOST_CHECK_MESSAGE(
236 boost::iostreams::test::test_resizeable(mf),
237 "failed resizing a mapped_file"
238 );
239
240 BOOST_TEST_MESSAGE(
241 "done resizing a mapped_file"
242 );
243 }
244
245 //--------------Random access with a private mapped_file------------------//
246
247 {
248 // Use 2 copies of the file to compare later
249 boost::iostreams::test::test_file orig, copy;
250
251 // Test reading and writing within a mapped_file.
252 // Since the file is privately mapped, it should remain
253 // unchanged after writing when opened in readonly mode.
254 mapped_file mf;
255 mf.open(path: orig.name(), flags: mapped_file::priv);
256 BOOST_CHECK_MESSAGE(
257 boost::iostreams::test::test_writeable(mf),
258 "failed seeking within private mapped_file"
259 );
260 BOOST_CHECK_MESSAGE(
261 boost::iostreams::test::compare_files(orig.name(), copy.name()),
262 "failed writing to private mapped_file"
263 );
264
265 BOOST_TEST_MESSAGE(
266 "done seeking within private mapped_file"
267 );
268
269 mf.close();
270
271 // Test reopening the mapped file.
272 mf.open(path: orig.name(), flags: mapped_file::priv);
273 BOOST_CHECK_MESSAGE(
274 boost::iostreams::test::test_writeable(mf),
275 "failed reopening private mapped_file"
276 );
277 BOOST_CHECK_MESSAGE(
278 boost::iostreams::test::compare_files(orig.name(), copy.name()),
279 "failed writing to reopened private mapped_file"
280 );
281
282 BOOST_TEST_MESSAGE(
283 "done reopening private mapped_file"
284 );
285 }
286
287 //-------------Check creating opening mapped_file with char*-------------//
288
289 {
290 boost::iostreams::test::test_file orig;
291 char name[50];
292 std::strncpy(dest: name, src: orig.name().c_str(), n: 50);
293
294 mapped_file mf((char*) name);
295
296 BOOST_CHECK_MESSAGE(
297 boost::iostreams::test::test_writeable(mf),
298 "failed seeking within private mapped_file"
299 );
300
301 mf.close();
302 }
303
304 // CYGWIN supports wide paths in boost::filesystem, but uses open() in the
305 // mapped file implementation and it is not configured to handle wide paths
306 // properly. See github issue https://github.com/boostorg/iostreams/issues/61
307#ifndef __CYGWIN__
308 //---------Check creating opening mapped_file with filesystem3 path------//
309 {
310 boost::iostreams::test::test_file orig;
311
312 mapped_file mf(boost::filesystem::path(orig.name()));
313
314 BOOST_CHECK_MESSAGE(
315 boost::iostreams::test::test_writeable(mf),
316 "failed seeking within private mapped_file"
317 );
318
319 mf.close();
320 }
321#endif
322}
323
324#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
325# pragma optimize("", on)
326#endif
327
328boost::unit_test::test_suite* init_unit_test_suite(int, char* [])
329{
330 boost::unit_test::test_suite* test = BOOST_TEST_SUITE("mapped_file test");
331 test->add(BOOST_TEST_CASE(&mapped_file_test));
332 return test;
333}
334

source code of boost/libs/iostreams/test/mapped_file_test.cpp