mapped_file_test.cpp 11 KB

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