]>
git.proxmox.com Git - ceph.git/blob - 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.)
6 // See http://www.boost.org/libs/iostreams for documentation.
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"
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
;
29 struct gzip_alloc
: std::allocator
<char> {
31 gzip_alloc(const gzip_alloc
& other
) { }
33 gzip_alloc(const std::allocator
<T
>& other
) { }
36 void compression_test()
40 // Test compression and decompression with metadata
41 for (int i
= 0; i
< 4; ++i
) {
44 params
.file_name
= "original file name";
47 params
.comment
= "detailed file description";
49 gzip_compressor
out(params
);
52 test_filter_pair( boost::ref(out
),
54 std::string(data
.begin(), data
.end()) )
56 BOOST_CHECK(in
.file_name() == params
.file_name
);
57 BOOST_CHECK(in
.comment() == params
.comment
);
60 // Test compression and decompression with custom allocator
62 test_filter_pair( basic_gzip_compressor
<gzip_alloc
>(),
63 basic_gzip_decompressor
<gzip_alloc
>(),
64 std::string(data
.begin(), data
.end()) )
68 void multiple_member_test()
71 std::vector
<char> temp
, dest
;
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
);
81 // Read compressed data from temp into dest
83 in
.push(gzip_decompressor());
84 in
.push(array_source(&temp
[0], temp
.size()));
85 io::copy(in
, io::back_inserter(dest
));
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));
94 array_source(&temp
[0], temp
.size()),
95 io::compose(gzip_decompressor(), io::back_inserter(dest
)));
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));
103 void array_source_test()
105 std::string data
= "simple test string.";
108 filtering_ostream out
;
109 out
.push(gzip_compressor());
110 out
.push(io::back_inserter(encoded
));
111 io::copy(make_iterator_range(data
), out
);
114 io::array_source
src(encoded
.data(),encoded
.length());
115 io::copy(io::compose(io::gzip_decompressor(), src
), io::back_inserter(res
));
117 BOOST_CHECK_EQUAL(data
, res
);
120 #if defined(BOOST_MSVC)
121 # pragma warning(push)
122 # pragma warning(disable:4309) // Truncation of constant value
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
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
145 size_t sz
= sizeof(header_bytes
)/sizeof(header_bytes
[0]);
147 boost::iostreams::detail::gzip_header hdr
;
148 for (size_t i
= 0; i
< sz
; ++i
) {
149 hdr
.process(header_bytes
[i
]);
151 // Require that we are done at the last byte, not before.
153 BOOST_REQUIRE(hdr
.done());
155 BOOST_REQUIRE(!hdr
.done());
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());
164 #if defined(BOOST_MSVC)
165 # pragma warning(pop)
168 void empty_file_test()
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
175 test_filter_pair( gzip_compressor(),
181 void multipart_test()
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',
202 filtering_istream in
;
205 in
.push(gzip_decompressor());
206 in
.push(io::array_source(multipart_file
, sizeof(multipart_file
)));
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
);
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
);
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
);
232 // Check for gzip errors too.
233 BOOST_CHECK(!in
.bad());
236 test_suite
* init_unit_test_suite(int, char* [])
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
));