]>
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 test_suite
* init_unit_test_suite(int, char* [])
183 test_suite
* test
= BOOST_TEST_SUITE("gzip test");
184 test
->add(BOOST_TEST_CASE(&compression_test
));
185 test
->add(BOOST_TEST_CASE(&multiple_member_test
));
186 test
->add(BOOST_TEST_CASE(&array_source_test
));
187 test
->add(BOOST_TEST_CASE(&header_test
));
188 test
->add(BOOST_TEST_CASE(&empty_file_test
));