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_source> 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_source> 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::strcpy(name, orig.name().c_str());
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     //---------Check creating opening mapped_file with filesystem3 path------//
305     {
306         boost::iostreams::test::test_file orig;
307 
308         mapped_file mf(boost::filesystem::path(orig.name()));
309 
310         BOOST_CHECK_MESSAGE(
311             boost::iostreams::test::test_writeable(mf),
312             "failed seeking within private mapped_file"
313         );
314 
315         mf.close();
316     }
317 }
318 
319 #if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
320 # pragma optimize("", on)
321 #endif
322 
init_unit_test_suite(int,char * [])323 boost::unit_test::test_suite* init_unit_test_suite(int, char* [])
324 {
325     boost::unit_test::test_suite* test = BOOST_TEST_SUITE("mapped_file test");
326     test->add(BOOST_TEST_CASE(&mapped_file_test));
327     return test;
328 }
329