1 /*-
2 * Copyright (c) 2014 Michihiro NAKAJIMA
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer
10 * in this position and unchanged.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #include "test.h"
28
29 /*
30 * A basic exercise of lz4 reading and writing.
31 */
32
DEFINE_TEST(test_write_filter_lz4)33 DEFINE_TEST(test_write_filter_lz4)
34 {
35 struct archive_entry *ae;
36 struct archive* a;
37 char *buff, *data;
38 size_t buffsize, datasize;
39 char path[16];
40 size_t used1, used2;
41 int i, r, use_prog = 0, filecount;
42
43 assert((a = archive_write_new()) != NULL);
44 r = archive_write_add_filter_lz4(a);
45 if (archive_liblz4_version() == NULL) {
46 if (!canLz4()) {
47 skipping("lz4 writing not supported on this platform");
48 assertEqualInt(ARCHIVE_WARN, r);
49 assertEqualInt(ARCHIVE_OK, archive_write_free(a));
50 return;
51 } else {
52 assertEqualInt(ARCHIVE_WARN, r);
53 use_prog = 1;
54 }
55 } else {
56 assertEqualInt(ARCHIVE_OK, r);
57 }
58 assertEqualInt(ARCHIVE_OK, archive_write_free(a));
59
60 buffsize = 2000000;
61 assert(NULL != (buff = malloc(buffsize)));
62
63 datasize = 10000;
64 assert(NULL != (data = calloc(datasize, 1)));
65 filecount = 10;
66
67 /*
68 * Write a filecount files and read them all back.
69 */
70 assert((a = archive_write_new()) != NULL);
71 assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
72 assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK,
73 archive_write_add_filter_lz4(a));
74 assertEqualIntA(a, ARCHIVE_OK,
75 archive_write_set_bytes_per_block(a, 1024));
76 assertEqualIntA(a, ARCHIVE_OK,
77 archive_write_set_bytes_in_last_block(a, 1024));
78 assertEqualInt(ARCHIVE_FILTER_LZ4, archive_filter_code(a, 0));
79 assertEqualString("lz4", archive_filter_name(a, 0));
80 assertEqualIntA(a, ARCHIVE_OK,
81 archive_write_open_memory(a, buff, buffsize, &used1));
82 assert((ae = archive_entry_new()) != NULL);
83 archive_entry_set_filetype(ae, AE_IFREG);
84 archive_entry_set_size(ae, datasize);
85 for (i = 0; i < filecount; i++) {
86 snprintf(path, sizeof(path), "file%03d", i);
87 archive_entry_copy_pathname(ae, path);
88 assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
89 assertA(datasize
90 == (size_t)archive_write_data(a, data, datasize));
91 }
92 archive_entry_free(ae);
93 assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
94 assertEqualInt(ARCHIVE_OK, archive_write_free(a));
95
96 assert((a = archive_read_new()) != NULL);
97 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
98 r = archive_read_support_filter_lz4(a);
99 if (r == ARCHIVE_WARN) {
100 skipping("Can't verify lz4 writing by reading back;"
101 " lz4 reading not fully supported on this platform");
102 assertEqualInt(ARCHIVE_OK, archive_read_free(a));
103 return;
104 }
105
106 assertEqualIntA(a, ARCHIVE_OK,
107 archive_read_open_memory(a, buff, used1));
108 for (i = 0; i < filecount; i++) {
109 snprintf(path, sizeof(path), "file%03d", i);
110 if (!assertEqualInt(ARCHIVE_OK,
111 archive_read_next_header(a, &ae)))
112 break;
113 assertEqualString(path, archive_entry_pathname(ae));
114 assertEqualInt((int)datasize, archive_entry_size(ae));
115 }
116 assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
117 assertEqualInt(ARCHIVE_OK, archive_read_free(a));
118
119 /*
120 * Repeat the cycle again, this time setting some compression
121 * options.
122 */
123 assert((a = archive_write_new()) != NULL);
124 assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
125 assertEqualIntA(a, ARCHIVE_OK,
126 archive_write_set_bytes_per_block(a, 10));
127 assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK,
128 archive_write_add_filter_lz4(a));
129 assertEqualIntA(a, ARCHIVE_FAILED,
130 archive_write_set_options(a, "lz4:nonexistent-option=0"));
131 assertEqualIntA(a, ARCHIVE_OK,
132 archive_write_set_options(a, "lz4:compression-level=1"));
133 assertEqualIntA(a, ARCHIVE_OK,
134 archive_write_set_filter_option(a, NULL, "compression-level", "9"));
135 assertEqualIntA(a, ARCHIVE_FAILED,
136 archive_write_set_filter_option(a, NULL, "compression-level", "abc"));
137 assertEqualIntA(a, ARCHIVE_FAILED,
138 archive_write_set_filter_option(a, NULL, "compression-level", "99"));
139 assertEqualIntA(a, ARCHIVE_OK,
140 archive_write_set_options(a, "lz4:compression-level=9"));
141 assertEqualIntA(a, ARCHIVE_OK,
142 archive_write_open_memory(a, buff, buffsize, &used2));
143 for (i = 0; i < filecount; i++) {
144 snprintf(path, sizeof(path), "file%03d", i);
145 assert((ae = archive_entry_new()) != NULL);
146 archive_entry_copy_pathname(ae, path);
147 archive_entry_set_size(ae, datasize);
148 archive_entry_set_filetype(ae, AE_IFREG);
149 assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
150 assertA(datasize == (size_t)archive_write_data(
151 a, data, datasize));
152 archive_entry_free(ae);
153 }
154 assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
155 assertEqualInt(ARCHIVE_OK, archive_write_free(a));
156
157 failure("compression-level=9 wrote %d bytes, default wrote %d bytes",
158 (int)used2, (int)used1);
159 assert(used2 < used1);
160
161 assert((a = archive_read_new()) != NULL);
162 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
163 r = archive_read_support_filter_lz4(a);
164 if (r != ARCHIVE_OK && !use_prog) {
165 skipping("lz4 reading not fully supported on this platform");
166 } else {
167 assertEqualIntA(a, ARCHIVE_OK,
168 archive_read_support_filter_all(a));
169 assertEqualIntA(a, ARCHIVE_OK,
170 archive_read_open_memory(a, buff, used2));
171 for (i = 0; i < filecount; i++) {
172 snprintf(path, sizeof(path), "file%03d", i);
173 if (!assertEqualInt(ARCHIVE_OK,
174 archive_read_next_header(a, &ae)))
175 break;
176 assertEqualString(path, archive_entry_pathname(ae));
177 assertEqualInt((int)datasize, archive_entry_size(ae));
178 }
179 assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
180 }
181 assertEqualInt(ARCHIVE_OK, archive_read_free(a));
182
183 /*
184 * Repeat again, with much lower compression.
185 */
186 assert((a = archive_write_new()) != NULL);
187 assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
188 assertEqualIntA(a, ARCHIVE_OK,
189 archive_write_set_bytes_per_block(a, 10));
190 assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK,
191 archive_write_add_filter_lz4(a));
192 assertEqualIntA(a, ARCHIVE_OK,
193 archive_write_set_filter_option(a, NULL, "compression-level", "1"));
194 assertEqualIntA(a, ARCHIVE_OK,
195 archive_write_open_memory(a, buff, buffsize, &used2));
196 for (i = 0; i < filecount; i++) {
197 snprintf(path, sizeof(path), "file%03d", i);
198 assert((ae = archive_entry_new()) != NULL);
199 archive_entry_copy_pathname(ae, path);
200 archive_entry_set_size(ae, datasize);
201 archive_entry_set_filetype(ae, AE_IFREG);
202 assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
203 failure("Writing file %s", path);
204 assertEqualIntA(a, datasize,
205 (size_t)archive_write_data(a, data, datasize));
206 archive_entry_free(ae);
207 }
208 assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
209 assertEqualInt(ARCHIVE_OK, archive_write_free(a));
210
211 #if 0
212 failure("Compression-level=1 wrote %d bytes; default wrote %d bytes",
213 (int)used2, (int)used1);
214 assert(used2 > used1);
215 #endif
216
217 assert((a = archive_read_new()) != NULL);
218 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
219 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
220 r = archive_read_support_filter_lz4(a);
221 if (r == ARCHIVE_WARN) {
222 skipping("lz4 reading not fully supported on this platform");
223 } else {
224 assertEqualIntA(a, ARCHIVE_OK,
225 archive_read_open_memory(a, buff, used2));
226 for (i = 0; i < filecount; i++) {
227 snprintf(path, sizeof(path), "file%03d", i);
228 if (!assertEqualInt(ARCHIVE_OK,
229 archive_read_next_header(a, &ae)))
230 break;
231 assertEqualString(path, archive_entry_pathname(ae));
232 assertEqualInt((int)datasize, archive_entry_size(ae));
233 }
234 assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
235 }
236 assertEqualInt(ARCHIVE_OK, archive_read_free(a));
237
238 /*
239 * Test various premature shutdown scenarios to make sure we
240 * don't crash or leak memory.
241 */
242 assert((a = archive_write_new()) != NULL);
243 assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK,
244 archive_write_add_filter_lz4(a));
245 assertEqualInt(ARCHIVE_OK, archive_write_free(a));
246
247 assert((a = archive_write_new()) != NULL);
248 assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK,
249 archive_write_add_filter_lz4(a));
250 assertEqualInt(ARCHIVE_OK, archive_write_close(a));
251 assertEqualInt(ARCHIVE_OK, archive_write_free(a));
252
253 assert((a = archive_write_new()) != NULL);
254 assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
255 assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK,
256 archive_write_add_filter_lz4(a));
257 assertEqualInt(ARCHIVE_OK, archive_write_close(a));
258 assertEqualInt(ARCHIVE_OK, archive_write_free(a));
259
260 assert((a = archive_write_new()) != NULL);
261 assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
262 assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK,
263 archive_write_add_filter_lz4(a));
264 assertEqualIntA(a, ARCHIVE_OK,
265 archive_write_open_memory(a, buff, buffsize, &used2));
266 assertEqualInt(ARCHIVE_OK, archive_write_close(a));
267 assertEqualInt(ARCHIVE_OK, archive_write_free(a));
268
269 /*
270 * Clean up.
271 */
272 free(data);
273 free(buff);
274 }
275
276 static void
test_options(const char * options)277 test_options(const char *options)
278 {
279 struct archive_entry *ae;
280 struct archive* a;
281 char *buff, *data;
282 size_t buffsize, datasize;
283 char path[16];
284 size_t used1;
285 int i, r, use_prog = 0, filecount;
286
287 assert((a = archive_write_new()) != NULL);
288 r = archive_write_add_filter_lz4(a);
289 if (archive_liblz4_version() == NULL) {
290 if (!canLz4()) {
291 skipping("lz4 writing not supported on this platform");
292 assertEqualInt(ARCHIVE_WARN, r);
293 assertEqualInt(ARCHIVE_OK, archive_write_free(a));
294 return;
295 } else {
296 assertEqualInt(ARCHIVE_WARN, r);
297 use_prog = 1;
298 }
299 } else {
300 assertEqualInt(ARCHIVE_OK, r);
301 }
302 assertEqualInt(ARCHIVE_OK, archive_write_free(a));
303
304 buffsize = 2000000;
305 assert(NULL != (buff = malloc(buffsize)));
306
307 datasize = 10000;
308 assert(NULL != (data = calloc(datasize, 1)));
309 filecount = 10;
310
311 /*
312 * Write a filecount files and read them all back.
313 */
314 assert((a = archive_write_new()) != NULL);
315 assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
316 assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK,
317 archive_write_add_filter_lz4(a));
318 assertEqualIntA(a, ARCHIVE_OK,
319 archive_write_set_options(a, options));
320 assertEqualIntA(a, ARCHIVE_OK,
321 archive_write_set_bytes_per_block(a, 1024));
322 assertEqualIntA(a, ARCHIVE_OK,
323 archive_write_set_bytes_in_last_block(a, 1024));
324 assertEqualInt(ARCHIVE_FILTER_LZ4, archive_filter_code(a, 0));
325 assertEqualString("lz4", archive_filter_name(a, 0));
326 assertEqualIntA(a, ARCHIVE_OK,
327 archive_write_open_memory(a, buff, buffsize, &used1));
328 assert((ae = archive_entry_new()) != NULL);
329 archive_entry_set_filetype(ae, AE_IFREG);
330 archive_entry_set_size(ae, datasize);
331 for (i = 0; i < filecount; i++) {
332 snprintf(path, sizeof(path), "file%03d", i);
333 archive_entry_copy_pathname(ae, path);
334 assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
335 assertA(datasize
336 == (size_t)archive_write_data(a, data, datasize));
337 }
338 archive_entry_free(ae);
339 assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
340 assertEqualInt(ARCHIVE_OK, archive_write_free(a));
341
342 assert((a = archive_read_new()) != NULL);
343 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
344 r = archive_read_support_filter_lz4(a);
345 if (r == ARCHIVE_WARN) {
346 skipping("Can't verify lz4 writing by reading back;"
347 " lz4 reading not fully supported on this platform");
348 } else {
349 assertEqualIntA(a, ARCHIVE_OK,
350 archive_read_open_memory(a, buff, used1));
351 for (i = 0; i < filecount; i++) {
352 snprintf(path, sizeof(path), "file%03d", i);
353 if (!assertEqualInt(ARCHIVE_OK,
354 archive_read_next_header(a, &ae)))
355 break;
356 assertEqualString(path, archive_entry_pathname(ae));
357 assertEqualInt((int)datasize, archive_entry_size(ae));
358 }
359 assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
360 }
361 assertEqualInt(ARCHIVE_OK, archive_read_free(a));
362
363 /*
364 * Clean up.
365 */
366 free(data);
367 free(buff);
368 }
369
DEFINE_TEST(test_write_filter_lz4_disable_stream_checksum)370 DEFINE_TEST(test_write_filter_lz4_disable_stream_checksum)
371 {
372 test_options("lz4:!stream-checksum");
373 }
374
DEFINE_TEST(test_write_filter_lz4_enable_block_checksum)375 DEFINE_TEST(test_write_filter_lz4_enable_block_checksum)
376 {
377 test_options("lz4:block-checksum");
378 }
379
DEFINE_TEST(test_write_filter_lz4_block_size_4)380 DEFINE_TEST(test_write_filter_lz4_block_size_4)
381 {
382 test_options("lz4:block-size=4");
383 }
384
DEFINE_TEST(test_write_filter_lz4_block_size_5)385 DEFINE_TEST(test_write_filter_lz4_block_size_5)
386 {
387 test_options("lz4:block-size=5");
388 }
389
DEFINE_TEST(test_write_filter_lz4_block_size_6)390 DEFINE_TEST(test_write_filter_lz4_block_size_6)
391 {
392 test_options("lz4:block-size=6");
393 }
394
DEFINE_TEST(test_write_filter_lz4_block_dependence)395 DEFINE_TEST(test_write_filter_lz4_block_dependence)
396 {
397 test_options("lz4:block-dependence");
398 }
399
400 /*
401 * TODO: Figure out how to correctly handle this.
402 *
403 * This option simply fails on some versions of the LZ4 libraries.
404 */
405 /*
406 XXXDEFINE_TEST(test_write_filter_lz4_block_dependence_hc)
407 {
408 test_options("lz4:block-dependence,lz4:compression-level=9");
409 }
410 */
411