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
32 namespace boost { namespace iostreams { namespace test {
33
test_writeable(mapped_file & mf)34 bool test_writeable(mapped_file& mf)
35 {
36 // Test writing
37 for (int i = 0; i < data_reps; ++i) {
38 memcpy(mf.data(), narrow_data(), chunk_size);
39 char buf[chunk_size];
40 memcpy(buf, mf.const_data(), chunk_size);
41 if (strncmp(buf, narrow_data(), chunk_size) != 0)
42 return false;
43 memset(mf.data(), 0, chunk_size);
44 }
45 return true;
46 }
47
test_resizeable(mapped_file & mf)48 bool 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(size/2);
55 if (mf.size() != size/2)
56 return false;
57 mf.resize(size);
58 if (mf.size() != size)
59 return false;
60 return true;
61 }
62
63 } } } // End namespaces test, iostreams, boost.
64
mapped_file_test()65 void 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(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(mapped_file_sink(first.name()));
121 boost::iostreams::test::write_data_in_chars(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(mapped_file_sink(second.name()));
135 boost::iostreams::test::write_data_in_chunks(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(mapped_file_sink(p));
158 boost::iostreams::test::write_data_in_chars(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(mapped_file_sink(p));
170 boost::iostreams::test::write_data_in_chunks(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(mapped_file_sink(p));
187 boost::iostreams::test::write_data_in_chars(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(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(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(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(orig.name(), 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(orig.name(), 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(name, orig.name().c_str(), 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
init_unit_test_suite(int,char * [])328 boost::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