]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/iostreams/test/gzip_test.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / iostreams / test / gzip_test.cpp
1 // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
2 // (C) Copyright 2004-2007 Jonathan Turkanis
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 #include <cstddef>
9 #include <string>
10 #include <boost/iostreams/copy.hpp>
11 #include <boost/iostreams/device/array.hpp>
12 #include <boost/iostreams/device/back_inserter.hpp>
13 #include <boost/iostreams/filter/gzip.hpp>
14 #include <boost/iostreams/filter/test.hpp>
15 #include <boost/iostreams/filtering_stream.hpp>
16 #include <boost/ref.hpp>
17 #include <boost/range/iterator_range.hpp>
18 #include <boost/test/test_tools.hpp>
19 #include <boost/test/unit_test.hpp>
20 #include "detail/sequence.hpp"
21 #include "detail/verification.hpp"
22
23 using namespace boost;
24 using namespace boost::iostreams;
25 using namespace boost::iostreams::test;
26 namespace io = boost::iostreams;
27 using boost::unit_test::test_suite;
28
29 struct gzip_alloc : std::allocator<char> {
30 gzip_alloc() { }
31 gzip_alloc(const gzip_alloc& other) { }
32 template<typename T>
33 gzip_alloc(const std::allocator<T>& other) { }
34 };
35
36 void compression_test()
37 {
38 text_sequence data;
39
40 // Test compression and decompression with metadata
41 for (int i = 0; i < 4; ++i) {
42 gzip_params params;
43 if (i & 1) {
44 params.file_name = "original file name";
45 }
46 if (i & 2) {
47 params.comment = "detailed file description";
48 }
49 gzip_compressor out(params);
50 gzip_decompressor in;
51 BOOST_CHECK(
52 test_filter_pair( boost::ref(out),
53 boost::ref(in),
54 std::string(data.begin(), data.end()) )
55 );
56 BOOST_CHECK(in.file_name() == params.file_name);
57 BOOST_CHECK(in.comment() == params.comment);
58 }
59
60 // Test compression and decompression with custom allocator
61 BOOST_CHECK(
62 test_filter_pair( basic_gzip_compressor<gzip_alloc>(),
63 basic_gzip_decompressor<gzip_alloc>(),
64 std::string(data.begin(), data.end()) )
65 );
66 }
67
68 void multiple_member_test()
69 {
70 text_sequence data;
71 std::vector<char> temp, dest;
72
73 // Write compressed data to temp, twice in succession
74 filtering_ostream out;
75 out.push(gzip_compressor());
76 out.push(io::back_inserter(temp));
77 io::copy(make_iterator_range(data), out);
78 out.push(io::back_inserter(temp));
79 io::copy(make_iterator_range(data), out);
80
81 // Read compressed data from temp into dest
82 filtering_istream in;
83 in.push(gzip_decompressor());
84 in.push(array_source(&temp[0], temp.size()));
85 io::copy(in, io::back_inserter(dest));
86
87 // Check that dest consists of two copies of data
88 BOOST_REQUIRE_EQUAL(data.size() * 2, dest.size());
89 BOOST_CHECK(std::equal(data.begin(), data.end(), dest.begin()));
90 BOOST_CHECK(std::equal(data.begin(), data.end(), dest.begin() + dest.size() / 2));
91
92 dest.clear();
93 io::copy(
94 array_source(&temp[0], temp.size()),
95 io::compose(gzip_decompressor(), io::back_inserter(dest)));
96
97 // Check that dest consists of two copies of data
98 BOOST_REQUIRE_EQUAL(data.size() * 2, dest.size());
99 BOOST_CHECK(std::equal(data.begin(), data.end(), dest.begin()));
100 BOOST_CHECK(std::equal(data.begin(), data.end(), dest.begin() + dest.size() / 2));
101 }
102
103 void array_source_test()
104 {
105 std::string data = "simple test string.";
106 std::string encoded;
107
108 filtering_ostream out;
109 out.push(gzip_compressor());
110 out.push(io::back_inserter(encoded));
111 io::copy(make_iterator_range(data), out);
112
113 std::string res;
114 io::array_source src(encoded.data(),encoded.length());
115 io::copy(io::compose(io::gzip_decompressor(), src), io::back_inserter(res));
116
117 BOOST_CHECK_EQUAL(data, res);
118 }
119
120 #if defined(BOOST_MSVC)
121 # pragma warning(push)
122 # pragma warning(disable:4309) // Truncation of constant value
123 #endif
124
125 void header_test()
126 {
127 // This test is in response to https://svn.boost.org/trac/boost/ticket/5908
128 // which describes a problem parsing gzip headers with extra fields as
129 // defined in RFC 1952 (http://www.ietf.org/rfc/rfc1952.txt).
130 // The extra field data used here is characteristic of the tabix file
131 // format (http://samtools.sourceforge.net/tabix.shtml).
132 const char header_bytes[] = {
133 static_cast<char>(gzip::magic::id1),
134 static_cast<char>(gzip::magic::id2),
135 gzip::method::deflate, // Compression Method: deflate
136 gzip::flags::extra | gzip::flags::name | gzip::flags::comment, // flags
137 '\x22', '\x9c', '\xf3', '\x4e', // 4 byte modification time (little endian)
138 gzip::extra_flags::best_compression, // XFL
139 gzip::os_unix, // OS
140 6, 0, // 2 byte length of extra field (little endian, 6 bytes)
141 'B', 'C', 2, 0, 0, 0, // 6 bytes worth of extra field data
142 'a', 'b', 'c', 0, // original filename, null terminated
143 'n', 'o', ' ', 'c', 'o', 'm', 'm', 'e', 'n', 't', 0, // comment
144 };
145 size_t sz = sizeof(header_bytes)/sizeof(header_bytes[0]);
146
147 boost::iostreams::detail::gzip_header hdr;
148 for (size_t i = 0; i < sz; ++i) {
149 hdr.process(header_bytes[i]);
150
151 // Require that we are done at the last byte, not before.
152 if (i == sz-1)
153 BOOST_REQUIRE(hdr.done());
154 else
155 BOOST_REQUIRE(!hdr.done());
156 }
157
158 BOOST_CHECK_EQUAL("abc", hdr.file_name());
159 BOOST_CHECK_EQUAL("no comment", hdr.comment());
160 BOOST_CHECK_EQUAL(0x4ef39c22, hdr.mtime());
161 BOOST_CHECK_EQUAL(gzip::os_unix, hdr.os());
162 }
163
164 #if defined(BOOST_MSVC)
165 # pragma warning(pop)
166 #endif
167
168 void empty_file_test()
169 {
170 // This test is in response to https://svn.boost.org/trac/boost/ticket/5237
171 // The previous implementation of gzip_compressor only wrote the gzip file
172 // header when the first bytes of uncompressed input were processed, causing
173 // incorrect behavior for empty files
174 BOOST_CHECK(
175 test_filter_pair( gzip_compressor(),
176 gzip_decompressor(),
177 std::string() )
178 );
179 }
180
181 void multipart_test()
182 {
183 // This test verifies that the gzip_decompressor properly handles a file
184 // that was written in multiple parts using Z_FULL_FLUSH, and in particular
185 // handles the CRC properly when one of those parts is empty.
186 const char multipart_file[] = {
187 '\x1f', '\x8b', '\x08', '\x00', '\x00', '\x00', '\x00', '\x00', '\x02', '\xff', '\xf2', '\xc9',
188 '\xcc', '\x4b', '\x55', '\x30', '\xe4', '\xf2', '\x01', '\x51', '\x46', '\x10', '\xca', '\x98',
189 '\x0b', '\x00', '\x00', '\x00', '\xff', '\xff', '\x03', '\x00', '\xdb', '\xa7', '\x83', '\xc9',
190 '\x15', '\x00', '\x00', '\x00', '\x1f', '\x8b', '\x08', '\x00', '\x00', '\x00', '\x00', '\x00',
191 '\x02', '\xff', '\xf2', '\xc9', '\xcc', '\x4b', '\x55', '\x30', '\xe1', '\xf2', '\x01', '\x51',
192 '\xa6', '\x10', '\xca', '\x8c', '\x0b', '\x00', '\x00', '\x00', '\xff', '\xff', '\x03', '\x00',
193 '\x41', '\xe3', '\xcc', '\xaa', '\x15', '\x00', '\x00', '\x00', '\x1f', '\x8b', '\x08', '\x00',
194 '\x00', '\x00', '\x00', '\x00', '\x02', '\xff', '\x02', '\x00', '\x00', '\x00', '\xff', '\xff',
195 '\x03', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x1f', '\x8b',
196 '\x08', '\x00', '\x00', '\x00', '\x00', '\x00', '\x02', '\xff', '\xf2', '\xc9', '\xcc', '\x4b',
197 '\x55', '\x30', '\xe7', '\xf2', '\x01', '\x51', '\x16', '\x10', '\xca', '\x92', '\x0b', '\x00',
198 '\x00', '\x00', '\xff', '\xff', '\x03', '\x00', '\x2b', '\xac', '\xd3', '\xf5', '\x15', '\x00',
199 '\x00', '\x00'
200 };
201
202 filtering_istream in;
203 std::string line;
204
205 in.push(gzip_decompressor());
206 in.push(io::array_source(multipart_file, sizeof(multipart_file)));
207
208 // First part
209 std::getline(in, line);
210 BOOST_CHECK_EQUAL("Line 1", line);
211 std::getline(in, line);
212 BOOST_CHECK_EQUAL("Line 2", line);
213 std::getline(in, line);
214 BOOST_CHECK_EQUAL("Line 3", line);
215
216 // Second part immediately follows
217 std::getline(in, line);
218 BOOST_CHECK_EQUAL("Line 4", line);
219 std::getline(in, line);
220 BOOST_CHECK_EQUAL("Line 5", line);
221 std::getline(in, line);
222 BOOST_CHECK_EQUAL("Line 6", line);
223
224 // Then an empty part, followed by one last 3-line part.
225 std::getline(in, line);
226 BOOST_CHECK_EQUAL("Line 7", line);
227 std::getline(in, line);
228 BOOST_CHECK_EQUAL("Line 8", line);
229 std::getline(in, line);
230 BOOST_CHECK_EQUAL("Line 9", line);
231
232 // Check for gzip errors too.
233 BOOST_CHECK(!in.bad());
234 }
235
236 test_suite* init_unit_test_suite(int, char* [])
237 {
238 test_suite* test = BOOST_TEST_SUITE("gzip test");
239 test->add(BOOST_TEST_CASE(&compression_test));
240 test->add(BOOST_TEST_CASE(&multiple_member_test));
241 test->add(BOOST_TEST_CASE(&array_source_test));
242 test->add(BOOST_TEST_CASE(&header_test));
243 test->add(BOOST_TEST_CASE(&empty_file_test));
244 test->add(BOOST_TEST_CASE(&multipart_test));
245 return test;
246 }