]>
Commit | Line | Data |
---|---|---|
b32b8144 FG |
1 | // (C) COPYRIGHT 2017 ARM Limited |
2 | // Based on gzip_test.cpp by: | |
3 | // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) | |
4 | // (C) Copyright 2004-2007 Jonathan Turkanis | |
5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.) | |
7 | ||
8 | // See http://www.boost.org/libs/iostreams for documentation. | |
9 | ||
10 | // Note: basically a copy-paste of the gzip test | |
11 | ||
12 | #include <cstddef> | |
13 | #include <string> | |
14 | #include <boost/iostreams/copy.hpp> | |
15 | #include <boost/iostreams/device/array.hpp> | |
16 | #include <boost/iostreams/device/back_inserter.hpp> | |
17 | #include <boost/iostreams/filter/lzma.hpp> | |
18 | #include <boost/iostreams/filter/test.hpp> | |
19 | #include <boost/iostreams/filtering_stream.hpp> | |
20 | #include <boost/ref.hpp> | |
21 | #include <boost/range/iterator_range.hpp> | |
22 | #include <boost/test/test_tools.hpp> | |
23 | #include <boost/test/unit_test.hpp> | |
24 | #include "detail/sequence.hpp" | |
25 | #include "detail/verification.hpp" | |
26 | ||
27 | using namespace boost; | |
28 | using namespace boost::iostreams; | |
29 | using namespace boost::iostreams::test; | |
30 | namespace io = boost::iostreams; | |
31 | using boost::unit_test::test_suite; | |
32 | ||
33 | struct lzma_alloc : std::allocator<char> { | |
34 | lzma_alloc() { } | |
35 | lzma_alloc(const lzma_alloc& other) { } | |
36 | template<typename T> | |
37 | lzma_alloc(const std::allocator<T>& other) { } | |
38 | }; | |
39 | ||
40 | void compression_test() | |
41 | { | |
42 | text_sequence data; | |
43 | ||
44 | // Test compression and decompression with custom allocator | |
45 | BOOST_CHECK( | |
46 | test_filter_pair( basic_lzma_compressor<lzma_alloc>(), | |
47 | basic_lzma_decompressor<lzma_alloc>(), | |
48 | std::string(data.begin(), data.end()) ) | |
49 | ); | |
50 | } | |
51 | ||
52 | void multiple_member_test() | |
53 | { | |
54 | text_sequence data; | |
55 | std::vector<char> temp, dest; | |
56 | ||
57 | // Write compressed data to temp, twice in succession | |
58 | filtering_ostream out; | |
59 | out.push(lzma_compressor()); | |
60 | out.push(io::back_inserter(temp)); | |
61 | io::copy(make_iterator_range(data), out); | |
62 | out.push(io::back_inserter(temp)); | |
63 | io::copy(make_iterator_range(data), out); | |
64 | ||
65 | // Read compressed data from temp into dest | |
66 | filtering_istream in; | |
67 | in.push(lzma_decompressor()); | |
68 | in.push(array_source(&temp[0], temp.size())); | |
69 | io::copy(in, io::back_inserter(dest)); | |
70 | ||
71 | // Check that dest consists of two copies of data | |
72 | BOOST_REQUIRE_EQUAL(data.size() * 2, dest.size()); | |
73 | BOOST_CHECK(std::equal(data.begin(), data.end(), dest.begin())); | |
74 | BOOST_CHECK(std::equal(data.begin(), data.end(), dest.begin() + dest.size() / 2)); | |
75 | ||
76 | dest.clear(); | |
77 | io::copy( | |
78 | array_source(&temp[0], temp.size()), | |
79 | io::compose(lzma_decompressor(), io::back_inserter(dest))); | |
80 | ||
81 | // Check that dest consists of two copies of data | |
82 | BOOST_REQUIRE_EQUAL(data.size() * 2, dest.size()); | |
83 | BOOST_CHECK(std::equal(data.begin(), data.end(), dest.begin())); | |
84 | BOOST_CHECK(std::equal(data.begin(), data.end(), dest.begin() + dest.size() / 2)); | |
85 | } | |
86 | ||
87 | void array_source_test() | |
88 | { | |
89 | std::string data = "simple test string."; | |
90 | std::string encoded; | |
91 | ||
92 | filtering_ostream out; | |
93 | out.push(lzma_compressor()); | |
94 | out.push(io::back_inserter(encoded)); | |
95 | io::copy(make_iterator_range(data), out); | |
96 | ||
97 | std::string res; | |
98 | io::array_source src(encoded.data(),encoded.length()); | |
99 | io::copy(io::compose(io::lzma_decompressor(), src), io::back_inserter(res)); | |
100 | ||
101 | BOOST_CHECK_EQUAL(data, res); | |
102 | } | |
103 | ||
104 | void empty_file_test() | |
105 | { | |
106 | // This test is in response to https://svn.boost.org/trac/boost/ticket/5237 | |
107 | // The previous implementation of gzip_compressor only wrote the gzip file | |
108 | // header when the first bytes of uncompressed input were processed, causing | |
109 | // incorrect behavior for empty files | |
110 | BOOST_CHECK( | |
111 | test_filter_pair( lzma_compressor(), | |
112 | lzma_decompressor(), | |
113 | std::string() ) | |
114 | ); | |
115 | } | |
116 | ||
117 | void multipart_test() | |
118 | { | |
119 | // This test verifies that the lzma_decompressor properly handles a file | |
120 | // that consists of multiple concatenated files (matches unxz behaviour) | |
121 | static const char multipart_file[] = { | |
122 | '\xfd', '\x37', '\x7a', '\x58', '\x5a', '\x00', '\x00', '\x04', '\xe6', '\xd6', '\xb4', '\x46', | |
123 | '\x02', '\x00', '\x21', '\x01', '\x1c', '\x00', '\x00', '\x00', '\x10', '\xcf', '\x58', '\xcc', | |
124 | '\xe0', '\x00', '\x14', '\x00', '\x11', '\x5d', '\x00', '\x26', '\x1a', '\x49', '\xc6', '\x67', | |
125 | '\x41', '\x3f', '\x96', '\x8c', '\x25', '\x02', '\xb3', '\x4d', '\x16', '\xa8', '\xb4', '\x40', | |
126 | '\x00', '\x00', '\x00', '\x00', '\xeb', '\xad', '\x3f', '\xbf', '\x8c', '\x8c', '\x72', '\x25', | |
127 | '\x00', '\x01', '\x2d', '\x15', '\x2f', '\x0b', '\x71', '\x6d', '\x1f', '\xb6', '\xf3', '\x7d', | |
128 | '\x01', '\x00', '\x00', '\x00', '\x00', '\x04', '\x59', '\x5a', '\xfd', '\x37', '\x7a', '\x58', | |
129 | '\x5a', '\x00', '\x00', '\x04', '\xe6', '\xd6', '\xb4', '\x46', '\x02', '\x00', '\x21', '\x01', | |
130 | '\x1c', '\x00', '\x00', '\x00', '\x10', '\xcf', '\x58', '\xcc', '\xe0', '\x00', '\x14', '\x00', | |
131 | '\x11', '\x5d', '\x00', '\x26', '\x1a', '\x49', '\xc6', '\x67', '\x41', '\x4d', '\x84', '\x0c', | |
132 | '\x25', '\x1f', '\x5e', '\x1d', '\x4a', '\x91', '\x61', '\xa0', '\x00', '\x00', '\x00', '\x00', | |
133 | '\x56', '\x76', '\x71', '\xf0', '\x54', '\x21', '\xa2', '\x5b', '\x00', '\x01', '\x2d', '\x15', | |
134 | '\x2f', '\x0b', '\x71', '\x6d', '\x1f', '\xb6', '\xf3', '\x7d', '\x01', '\x00', '\x00', '\x00', | |
135 | '\x00', '\x04', '\x59', '\x5a', '\xfd', '\x37', '\x7a', '\x58', '\x5a', '\x00', '\x00', '\x04', | |
136 | '\xe6', '\xd6', '\xb4', '\x46', '\x00', '\x00', '\x00', '\x00', '\x1c', '\xdf', '\x44', '\x21', | |
137 | '\x1f', '\xb6', '\xf3', '\x7d', '\x01', '\x00', '\x00', '\x00', '\x00', '\x04', '\x59', '\x5a', | |
138 | '\xfd', '\x37', '\x7a', '\x58', '\x5a', '\x00', '\x00', '\x04', '\xe6', '\xd6', '\xb4', '\x46', | |
139 | '\x02', '\x00', '\x21', '\x01', '\x1c', '\x00', '\x00', '\x00', '\x10', '\xcf', '\x58', '\xcc', | |
140 | '\xe0', '\x00', '\x14', '\x00', '\x11', '\x5d', '\x00', '\x26', '\x1a', '\x49', '\xc6', '\x67', | |
141 | '\x41', '\x5b', '\x71', '\x8c', '\x25', '\x3c', '\x08', '\xec', '\x79', '\xa7', '\x7b', '\x60', | |
142 | '\x00', '\x00', '\x00', '\x00', '\xc7', '\x62', '\xbb', '\xaa', '\x59', '\x96', '\x2b', '\xa4', | |
143 | '\x00', '\x01', '\x2d', '\x15', '\x2f', '\x0b', '\x71', '\x6d', '\x1f', '\xb6', '\xf3', '\x7d', | |
144 | '\x01', '\x00', '\x00', '\x00', '\x00', '\x04', '\x59', '\x5a' | |
145 | }; | |
146 | ||
147 | filtering_istream in; | |
148 | std::string line; | |
149 | ||
150 | in.push(lzma_decompressor()); | |
151 | in.push(io::array_source(multipart_file, sizeof(multipart_file))); | |
152 | ||
153 | // First part | |
154 | std::getline(in, line); | |
155 | BOOST_CHECK_EQUAL("Line 1", line); | |
156 | std::getline(in, line); | |
157 | BOOST_CHECK_EQUAL("Line 2", line); | |
158 | std::getline(in, line); | |
159 | BOOST_CHECK_EQUAL("Line 3", line); | |
160 | ||
161 | // Second part immediately follows | |
162 | std::getline(in, line); | |
163 | BOOST_CHECK_EQUAL("Line 4", line); | |
164 | std::getline(in, line); | |
165 | BOOST_CHECK_EQUAL("Line 5", line); | |
166 | std::getline(in, line); | |
167 | BOOST_CHECK_EQUAL("Line 6", line); | |
168 | ||
169 | // Then an empty part, followed by one last 3-line part. | |
170 | std::getline(in, line); | |
171 | BOOST_CHECK_EQUAL("Line 7", line); | |
172 | std::getline(in, line); | |
173 | BOOST_CHECK_EQUAL("Line 8", line); | |
174 | std::getline(in, line); | |
175 | BOOST_CHECK_EQUAL("Line 9", line); | |
176 | ||
177 | // Check for lzma errors too. | |
178 | BOOST_CHECK(!in.bad()); | |
179 | } | |
180 | ||
92f5a8d4 TL |
181 | void multithreaded_test() |
182 | { | |
183 | text_sequence data; | |
184 | ||
185 | // Get correct compressed string at level 2. | |
186 | // Tests legacy capability of providing a single integer to the | |
187 | // lzma_compressor constructor to be used as the "level" to initialize | |
188 | // lzma_params. | |
189 | std::string correct_level_2; | |
190 | { | |
191 | filtering_ostream out; | |
192 | out.push(lzma_compressor(2)); | |
193 | out.push(io::back_inserter(correct_level_2)); | |
194 | io::copy(make_iterator_range(data), out); | |
195 | } | |
196 | ||
197 | // Tests omitting the threads parameters and arriving at same compressed data. | |
198 | BOOST_CHECK( | |
199 | test_output_filter( lzma_compressor(lzma_params(2)), | |
200 | std::string(data.begin(), data.end()), | |
201 | correct_level_2 ) | |
202 | ); | |
203 | ||
204 | // Test specifying a single thread and arriving at same compressed data. | |
205 | BOOST_CHECK( | |
206 | test_output_filter( lzma_compressor(lzma_params(2, 1)), | |
207 | std::string(data.begin(), data.end()), | |
208 | correct_level_2 ) | |
209 | ); | |
210 | ||
211 | // Test specifying multiple threads and arriving at same compressed data. | |
212 | BOOST_CHECK( | |
213 | test_output_filter( lzma_compressor(lzma_params(2, 4)), | |
214 | std::string(data.begin(), data.end()), | |
215 | correct_level_2 ) | |
216 | ); | |
217 | ||
218 | // Test specifying "0" threads, which is interpreted as | |
219 | // using all cores, or 1 thread if such capability is missing. | |
220 | BOOST_CHECK( | |
221 | test_output_filter( lzma_compressor(lzma_params(2, 0)), | |
222 | std::string(data.begin(), data.end()), | |
223 | correct_level_2 ) | |
224 | ); | |
225 | ||
226 | // Test that decompressor works to decompress the output with various thread values. | |
227 | // Threading shouldn't affect the decompression and, in fact, isn't | |
228 | // threaded in current implementation of liblzma. Both the level and | |
229 | // threads options are ignored by the decompressor. | |
230 | BOOST_CHECK( | |
231 | test_input_filter( lzma_decompressor(lzma_params(2, 1)), | |
232 | correct_level_2, | |
233 | std::string(data.begin(), data.end()) ) | |
234 | ); | |
235 | BOOST_CHECK( | |
236 | test_input_filter( lzma_decompressor(lzma_params(2, 4)), | |
237 | correct_level_2, | |
238 | std::string(data.begin(), data.end()) ) | |
239 | ); | |
240 | BOOST_CHECK( | |
241 | test_input_filter( lzma_decompressor(lzma_params(2, 0)), | |
242 | correct_level_2, | |
243 | std::string(data.begin(), data.end()) ) | |
244 | ); | |
245 | ||
246 | } | |
247 | ||
b32b8144 FG |
248 | test_suite* init_unit_test_suite(int, char* []) |
249 | { | |
250 | test_suite* test = BOOST_TEST_SUITE("lzma test"); | |
251 | test->add(BOOST_TEST_CASE(&compression_test)); | |
252 | test->add(BOOST_TEST_CASE(&multiple_member_test)); | |
253 | test->add(BOOST_TEST_CASE(&array_source_test)); | |
254 | test->add(BOOST_TEST_CASE(&empty_file_test)); | |
255 | test->add(BOOST_TEST_CASE(&multipart_test)); | |
92f5a8d4 | 256 | test->add(BOOST_TEST_CASE(&multithreaded_test)); |
b32b8144 FG |
257 | return test; |
258 | } |