lib/getopt*.c: Include <config.h> only HAVE_CONFIG_H is defined.
[xz.git] / tests / test_block_header.c
blobb3101355bf8e180d6f0345b3d0ecb2eb54298344
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 /// \file test_block_header.c
4 /// \brief Tests Block Header coders
5 //
6 // Authors: Lasse Collin
7 // Jia Tan
8 //
9 // This file has been put into the public domain.
10 // You can do whatever you want with this file.
12 ///////////////////////////////////////////////////////////////////////////////
14 #include "tests.h"
17 static lzma_options_lzma opt_lzma;
20 // Used in test_lzma_block_header_decode() between tests to ensure
21 // no artifacts are leftover in the block struct that could influence
22 // later tests.
23 #define RESET_BLOCK(block, buf) \
24 do { \
25 lzma_filter *filters_ = (block).filters; \
26 lzma_filters_free(filters_, NULL); \
27 memzero((buf), sizeof((buf))); \
28 memzero(&(block), sizeof(lzma_block)); \
29 (block).filters = filters_; \
30 (block).check = LZMA_CHECK_CRC32; \
31 } while (0);
34 #ifdef HAVE_ENCODERS
35 static lzma_filter filters_none[1] = {
37 .id = LZMA_VLI_UNKNOWN,
42 static lzma_filter filters_one[2] = {
44 .id = LZMA_FILTER_LZMA2,
45 .options = &opt_lzma,
46 }, {
47 .id = LZMA_VLI_UNKNOWN,
52 // These filters are only used in test_lzma_block_header_decode()
53 // which only runs if encoders and decoders are configured.
54 #ifdef HAVE_DECODERS
55 static lzma_filter filters_four[5] = {
57 .id = LZMA_FILTER_X86,
58 .options = NULL,
59 }, {
60 .id = LZMA_FILTER_X86,
61 .options = NULL,
62 }, {
63 .id = LZMA_FILTER_X86,
64 .options = NULL,
65 }, {
66 .id = LZMA_FILTER_LZMA2,
67 .options = &opt_lzma,
68 }, {
69 .id = LZMA_VLI_UNKNOWN,
72 #endif
75 static lzma_filter filters_five[6] = {
77 .id = LZMA_FILTER_X86,
78 .options = NULL,
79 }, {
80 .id = LZMA_FILTER_X86,
81 .options = NULL,
82 }, {
83 .id = LZMA_FILTER_X86,
84 .options = NULL,
85 }, {
86 .id = LZMA_FILTER_X86,
87 .options = NULL,
88 }, {
89 .id = LZMA_FILTER_LZMA2,
90 .options = &opt_lzma,
91 }, {
92 .id = LZMA_VLI_UNKNOWN,
95 #endif
98 static void
99 test_lzma_block_header_size(void)
101 #ifndef HAVE_ENCODERS
102 assert_skip("Encoder support disabled");
103 #else
104 if (!lzma_filter_encoder_is_supported(LZMA_FILTER_X86))
105 assert_skip("x86 BCJ encoder is disabled");
107 lzma_block block = {
108 .version = 0,
109 .filters = filters_one,
110 .compressed_size = LZMA_VLI_UNKNOWN,
111 .uncompressed_size = LZMA_VLI_UNKNOWN,
112 .check = LZMA_CHECK_CRC32
115 // Test that all initial options are valid
116 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
117 assert_uint(block.header_size, >=, LZMA_BLOCK_HEADER_SIZE_MIN);
118 assert_uint(block.header_size, <=, LZMA_BLOCK_HEADER_SIZE_MAX);
119 assert_uint_eq(block.header_size % 4, 0);
121 // Test invalid version number
122 for (uint32_t i = 2; i < 20; i++) {
123 block.version = i;
124 assert_lzma_ret(lzma_block_header_size(&block),
125 LZMA_OPTIONS_ERROR);
128 block.version = 1;
130 // Test invalid compressed size
131 block.compressed_size = 0;
132 assert_lzma_ret(lzma_block_header_size(&block), LZMA_PROG_ERROR);
134 block.compressed_size = LZMA_VLI_MAX + 1;
135 assert_lzma_ret(lzma_block_header_size(&block), LZMA_PROG_ERROR);
136 block.compressed_size = LZMA_VLI_UNKNOWN;
138 // Test invalid uncompressed size
139 block.uncompressed_size = LZMA_VLI_MAX + 1;
140 assert_lzma_ret(lzma_block_header_size(&block), LZMA_PROG_ERROR);
141 block.uncompressed_size = LZMA_VLI_MAX;
143 // Test invalid filters
144 block.filters = NULL;
145 assert_lzma_ret(lzma_block_header_size(&block), LZMA_PROG_ERROR);
147 block.filters = filters_none;
148 assert_lzma_ret(lzma_block_header_size(&block), LZMA_PROG_ERROR);
150 block.filters = filters_five;
151 assert_lzma_ret(lzma_block_header_size(&block), LZMA_PROG_ERROR);
153 block.filters = filters_one;
155 // Test setting compressed_size to something valid
156 block.compressed_size = 4096;
157 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
158 assert_uint(block.header_size, >=, LZMA_BLOCK_HEADER_SIZE_MIN);
159 assert_uint(block.header_size, <=, LZMA_BLOCK_HEADER_SIZE_MAX);
160 assert_uint_eq(block.header_size % 4, 0);
162 // Test setting uncompressed_size to something valid
163 block.uncompressed_size = 4096;
164 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
165 assert_uint(block.header_size, >=, LZMA_BLOCK_HEADER_SIZE_MIN);
166 assert_uint(block.header_size, <=, LZMA_BLOCK_HEADER_SIZE_MAX);
167 assert_uint_eq(block.header_size % 4, 0);
169 // This should pass, but header_size will be an invalid value
170 // because the total block size will not be able to fit in a valid
171 // lzma_vli. This way a temporary value can be used to reserve
172 // space for the header and later the actual value can be set.
173 block.compressed_size = LZMA_VLI_MAX;
174 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
175 assert_uint(block.header_size, >=, LZMA_BLOCK_HEADER_SIZE_MIN);
176 assert_uint(block.header_size, <=, LZMA_BLOCK_HEADER_SIZE_MAX);
177 assert_uint_eq(block.header_size % 4, 0);
179 // Use an invalid value for a filter option. This should still pass
180 // because the size of the LZMA2 properties is known by liblzma
181 // without reading any of the options so it doesn't validate them.
182 lzma_options_lzma bad_ops;
183 assert_false(lzma_lzma_preset(&bad_ops, 1));
184 bad_ops.pb = 0x1000;
186 lzma_filter bad_filters[2] = {
188 .id = LZMA_FILTER_LZMA2,
189 .options = &bad_ops
192 .id = LZMA_VLI_UNKNOWN,
193 .options = NULL
197 block.filters = bad_filters;
199 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
200 assert_uint(block.header_size, >=, LZMA_BLOCK_HEADER_SIZE_MIN);
201 assert_uint(block.header_size, <=, LZMA_BLOCK_HEADER_SIZE_MAX);
202 assert_uint_eq(block.header_size % 4, 0);
204 // Use an invalid block option. The check type isn't stored in
205 // the Block Header and so _header_size ignores it.
206 block.check = INVALID_LZMA_CHECK_ID;
207 block.ignore_check = false;
209 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
210 assert_uint(block.header_size, >=, LZMA_BLOCK_HEADER_SIZE_MIN);
211 assert_uint(block.header_size, <=, LZMA_BLOCK_HEADER_SIZE_MAX);
212 assert_uint_eq(block.header_size % 4, 0);
213 #endif
217 static void
218 test_lzma_block_header_encode(void)
220 #if !defined(HAVE_ENCODERS) || !defined(HAVE_DECODERS)
221 assert_skip("Encoder or decoder support disabled");
222 #else
224 if (!lzma_filter_encoder_is_supported(LZMA_FILTER_X86)
225 || !lzma_filter_decoder_is_supported(LZMA_FILTER_X86))
226 assert_skip("x86 BCJ encoder and/or decoder "
227 "is disabled");
229 lzma_block block = {
230 .version = 1,
231 .filters = filters_one,
232 .compressed_size = LZMA_VLI_UNKNOWN,
233 .uncompressed_size = LZMA_VLI_UNKNOWN,
234 .check = LZMA_CHECK_CRC32,
237 // Ensure all block options are valid before changes are tested
238 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
240 uint8_t out[LZMA_BLOCK_HEADER_SIZE_MAX];
242 // Test invalid block version
243 for (uint32_t i = 2; i < 20; i++) {
244 block.version = i;
245 assert_lzma_ret(lzma_block_header_encode(&block, out),
246 LZMA_PROG_ERROR);
249 block.version = 1;
251 // Test invalid header size (< min, > max, % 4 != 0)
252 block.header_size = LZMA_BLOCK_HEADER_SIZE_MIN - 4;
253 assert_lzma_ret(lzma_block_header_encode(&block, out),
254 LZMA_PROG_ERROR);
255 block.header_size = LZMA_BLOCK_HEADER_SIZE_MIN + 2;
256 assert_lzma_ret(lzma_block_header_encode(&block, out),
257 LZMA_PROG_ERROR);
258 block.header_size = LZMA_BLOCK_HEADER_SIZE_MAX + 4;
259 assert_lzma_ret(lzma_block_header_encode(&block, out),
260 LZMA_PROG_ERROR);
261 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
263 // Test invalid compressed_size
264 block.compressed_size = 0;
265 assert_lzma_ret(lzma_block_header_encode(&block, out),
266 LZMA_PROG_ERROR);
267 block.compressed_size = LZMA_VLI_MAX + 1;
268 assert_lzma_ret(lzma_block_header_encode(&block, out),
269 LZMA_PROG_ERROR);
271 // This test passes test_lzma_block_header_size, but should
272 // fail here because there is not enough space to encode the
273 // proper block size because the total size is too big to fit
274 // in an lzma_vli
275 block.compressed_size = LZMA_VLI_MAX;
276 assert_lzma_ret(lzma_block_header_encode(&block, out),
277 LZMA_PROG_ERROR);
278 block.compressed_size = LZMA_VLI_UNKNOWN;
280 // Test invalid uncompressed size
281 block.uncompressed_size = LZMA_VLI_MAX + 1;
282 assert_lzma_ret(lzma_block_header_encode(&block, out),
283 LZMA_PROG_ERROR);
284 block.uncompressed_size = LZMA_VLI_UNKNOWN;
286 // Test invalid block check
287 block.check = INVALID_LZMA_CHECK_ID;
288 block.ignore_check = false;
289 assert_lzma_ret(lzma_block_header_encode(&block, out),
290 LZMA_PROG_ERROR);
291 block.check = LZMA_CHECK_CRC32;
293 // Test invalid filters
294 block.filters = NULL;
295 assert_lzma_ret(lzma_block_header_encode(&block, out),
296 LZMA_PROG_ERROR);
298 block.filters = filters_none;
299 assert_lzma_ret(lzma_block_header_encode(&block, out),
300 LZMA_PROG_ERROR);
302 block.filters = filters_five;
303 block.header_size = LZMA_BLOCK_HEADER_SIZE_MAX - 4;
304 assert_lzma_ret(lzma_block_header_encode(&block, out),
305 LZMA_PROG_ERROR);
307 // Test valid encoding and verify bytes of block header.
308 // More complicated tests for encoding headers are included
309 // in test_lzma_block_header_decode.
310 block.filters = filters_one;
311 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
312 assert_lzma_ret(lzma_block_header_encode(&block, out), LZMA_OK);
314 // First read block header size from out and verify
315 // that it == (encoded size + 1) * 4
316 uint32_t header_size = (out[0] + 1U) * 4;
317 assert_uint_eq(header_size, block.header_size);
319 // Next read block flags
320 uint8_t flags = out[1];
322 // Should have number of filters = 1
323 assert_uint_eq((flags & 0x3) + 1, 1);
325 // Bits 2-7 must be empty not set
326 assert_uint_eq(flags & (0xFF - 0x3), 0);
328 // Verify filter flags
329 // Decode Filter ID
330 lzma_vli filter_id = 0;
331 size_t pos = 2;
332 assert_lzma_ret(lzma_vli_decode(&filter_id, NULL, out,
333 &pos, header_size), LZMA_OK);
334 assert_uint_eq(filter_id, filters_one[0].id);
336 // Decode Size of Properties
337 lzma_vli prop_size = 0;
338 assert_lzma_ret(lzma_vli_decode(&prop_size, NULL, out,
339 &pos, header_size), LZMA_OK);
341 // LZMA2 has 1 byte prop size
342 assert_uint_eq(prop_size, 1);
343 uint8_t expected_filter_props = 0;
344 assert_lzma_ret(lzma_properties_encode(filters_one,
345 &expected_filter_props), LZMA_OK);
346 assert_uint_eq(out[pos], expected_filter_props);
347 pos++;
349 // Check null-padding
350 for (size_t i = pos; i < header_size - 4; i++)
351 assert_uint_eq(out[i], 0);
353 // Check CRC32
354 assert_uint_eq(read32le(&out[header_size - 4]), lzma_crc32(out,
355 header_size - 4, 0));
356 #endif
360 #if defined(HAVE_ENCODERS) && defined(HAVE_DECODERS)
361 // Helper function to compare two lzma_block structures field by field
362 static void
363 compare_blocks(lzma_block *block_expected, lzma_block *block_actual)
365 assert_uint_eq(block_actual->version, block_expected->version);
366 assert_uint_eq(block_actual->compressed_size,
367 block_expected->compressed_size);
368 assert_uint_eq(block_actual->uncompressed_size,
369 block_expected->uncompressed_size);
370 assert_uint_eq(block_actual->check, block_expected->check);
371 assert_uint_eq(block_actual->header_size, block_expected->header_size);
373 // Compare filter IDs
374 assert_true(block_expected->filters && block_actual->filters);
375 lzma_filter expected_filter = block_expected->filters[0];
376 uint32_t filter_count = 0;
377 while (expected_filter.id != LZMA_VLI_UNKNOWN) {
378 assert_uint_eq(block_actual->filters[filter_count].id,
379 expected_filter.id);
380 expected_filter = block_expected->filters[++filter_count];
383 assert_uint_eq(block_actual->filters[filter_count].id,
384 LZMA_VLI_UNKNOWN);
386 #endif
389 static void
390 test_lzma_block_header_decode(void)
392 #if !defined(HAVE_ENCODERS) || !defined(HAVE_DECODERS)
393 assert_skip("Encoder or decoder support disabled");
394 #else
395 if (!lzma_filter_encoder_is_supported(LZMA_FILTER_X86)
396 || !lzma_filter_decoder_is_supported(LZMA_FILTER_X86))
397 assert_skip("x86 BCJ encoder and/or decoder "
398 "is disabled");
400 lzma_block block = {
401 .filters = filters_one,
402 .compressed_size = LZMA_VLI_UNKNOWN,
403 .uncompressed_size = LZMA_VLI_UNKNOWN,
404 .check = LZMA_CHECK_CRC32,
405 .version = 0
408 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
410 // Encode block header with simple options
411 uint8_t out[LZMA_BLOCK_HEADER_SIZE_MAX];
412 assert_lzma_ret(lzma_block_header_encode(&block, out), LZMA_OK);
414 // Decode block header and check that the options match
415 lzma_filter decoded_filters[LZMA_FILTERS_MAX + 1];
416 lzma_block decoded_block = {
417 .version = 0,
418 .filters = decoded_filters,
419 .check = LZMA_CHECK_CRC32
421 decoded_block.header_size = lzma_block_header_size_decode(out[0]);
423 assert_lzma_ret(lzma_block_header_decode(&decoded_block, NULL, out),
424 LZMA_OK);
425 compare_blocks(&block, &decoded_block);
427 // Reset output buffer and decoded_block
428 RESET_BLOCK(decoded_block, out);
430 // Test with compressed size set
431 block.compressed_size = 4096;
432 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
433 assert_lzma_ret(lzma_block_header_encode(&block, out), LZMA_OK);
434 decoded_block.header_size = lzma_block_header_size_decode(out[0]);
435 assert_lzma_ret(lzma_block_header_decode(&decoded_block, NULL, out),
436 LZMA_OK);
437 compare_blocks(&block, &decoded_block);
439 RESET_BLOCK(decoded_block, out);
441 // Test with uncompressed size set
442 block.uncompressed_size = 4096;
443 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
444 assert_lzma_ret(lzma_block_header_encode(&block, out), LZMA_OK);
445 decoded_block.header_size = lzma_block_header_size_decode(out[0]);
446 assert_lzma_ret(lzma_block_header_decode(&decoded_block, NULL, out),
447 LZMA_OK);
448 compare_blocks(&block, &decoded_block);
450 RESET_BLOCK(decoded_block, out);
452 // Test with multiple filters
453 block.filters = filters_four;
454 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
455 assert_lzma_ret(lzma_block_header_encode(&block, out), LZMA_OK);
456 decoded_block.header_size = lzma_block_header_size_decode(out[0]);
457 assert_lzma_ret(lzma_block_header_decode(&decoded_block, NULL, out),
458 LZMA_OK);
459 compare_blocks(&block, &decoded_block);
461 lzma_filters_free(decoded_filters, NULL);
463 // Test with too high version. The decoder will set it to a version
464 // that it supports.
465 decoded_block.version = 2;
466 assert_lzma_ret(lzma_block_header_decode(&decoded_block, NULL, out),
467 LZMA_OK);
468 assert_uint_eq(decoded_block.version, 1);
470 // Free the filters for the last time since all other cases should
471 // result in an error.
472 lzma_filters_free(decoded_filters, NULL);
474 // Test bad check type
475 decoded_block.check = INVALID_LZMA_CHECK_ID;
476 assert_lzma_ret(lzma_block_header_decode(&decoded_block, NULL, out),
477 LZMA_PROG_ERROR);
478 decoded_block.check = LZMA_CHECK_CRC32;
480 // Test bad check value
481 out[decoded_block.header_size - 1] -= 10;
482 assert_lzma_ret(lzma_block_header_decode(&decoded_block, NULL, out),
483 LZMA_DATA_ERROR);
484 out[decoded_block.header_size - 1] += 10;
486 // Test non-NULL padding
487 out[decoded_block.header_size - 5] = 1;
489 // Recompute CRC32
490 write32le(&out[decoded_block.header_size - 4], lzma_crc32(out,
491 decoded_block.header_size - 4, 0));
492 assert_lzma_ret(lzma_block_header_decode(&decoded_block, NULL, out),
493 LZMA_OPTIONS_ERROR);
495 // Test unsupported flags
496 out[1] = 0xFF;
498 // Recompute CRC32
499 write32le(&out[decoded_block.header_size - 4], lzma_crc32(out,
500 decoded_block.header_size - 4, 0));
501 assert_lzma_ret(lzma_block_header_decode(&decoded_block, NULL, out),
502 LZMA_OPTIONS_ERROR);
503 #endif
507 extern int
508 main(int argc, char **argv)
510 tuktest_start(argc, argv);
512 if (lzma_lzma_preset(&opt_lzma, 1))
513 tuktest_error("lzma_lzma_preset() failed");
515 tuktest_run(test_lzma_block_header_size);
516 tuktest_run(test_lzma_block_header_encode);
517 tuktest_run(test_lzma_block_header_decode);
519 return tuktest_end();