Build: Removes redundant check for LZMA1 filter support.
[xz/debian.git] / tests / test_block_header.c
blob43c7df43615e72485269f13cdf89cd6bd7146ac7
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 #ifdef HAVE_ENCODERS
21 static lzma_filter filters_none[1] = {
23 .id = LZMA_VLI_UNKNOWN,
28 static lzma_filter filters_one[2] = {
30 .id = LZMA_FILTER_LZMA2,
31 .options = &opt_lzma,
32 }, {
33 .id = LZMA_VLI_UNKNOWN,
38 // These filters are only used in test_lzma_block_header_decode()
39 // which only runs if encoders and decoders are configured.
40 #ifdef HAVE_DECODERS
41 static lzma_filter filters_four[5] = {
43 .id = LZMA_FILTER_X86,
44 .options = NULL,
45 }, {
46 .id = LZMA_FILTER_X86,
47 .options = NULL,
48 }, {
49 .id = LZMA_FILTER_X86,
50 .options = NULL,
51 }, {
52 .id = LZMA_FILTER_LZMA2,
53 .options = &opt_lzma,
54 }, {
55 .id = LZMA_VLI_UNKNOWN,
58 #endif
61 static lzma_filter filters_five[6] = {
63 .id = LZMA_FILTER_X86,
64 .options = NULL,
65 }, {
66 .id = LZMA_FILTER_X86,
67 .options = NULL,
68 }, {
69 .id = LZMA_FILTER_X86,
70 .options = NULL,
71 }, {
72 .id = LZMA_FILTER_X86,
73 .options = NULL,
74 }, {
75 .id = LZMA_FILTER_LZMA2,
76 .options = &opt_lzma,
77 }, {
78 .id = LZMA_VLI_UNKNOWN,
81 #endif
84 static void
85 test_lzma_block_header_size(void)
87 #ifndef HAVE_ENCODERS
88 assert_skip("Encoder support disabled");
89 #else
90 if (!lzma_filter_encoder_is_supported(LZMA_FILTER_X86))
91 assert_skip("x86 BCJ encoder is disabled");
93 lzma_block block = {
94 .version = 0,
95 .filters = filters_one,
96 .compressed_size = LZMA_VLI_UNKNOWN,
97 .uncompressed_size = LZMA_VLI_UNKNOWN,
98 .check = LZMA_CHECK_CRC32
101 // Test that all initial options are valid
102 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
103 assert_uint(block.header_size, >=, LZMA_BLOCK_HEADER_SIZE_MIN);
104 assert_uint(block.header_size, <=, LZMA_BLOCK_HEADER_SIZE_MAX);
105 assert_uint_eq(block.header_size % 4, 0);
107 // Test invalid version number
108 for (uint32_t i = 2; i < 20; i++) {
109 block.version = i;
110 assert_lzma_ret(lzma_block_header_size(&block),
111 LZMA_OPTIONS_ERROR);
114 block.version = 1;
116 // Test invalid compressed size
117 block.compressed_size = 0;
118 assert_lzma_ret(lzma_block_header_size(&block), LZMA_PROG_ERROR);
120 block.compressed_size = LZMA_VLI_MAX + 1;
121 assert_lzma_ret(lzma_block_header_size(&block), LZMA_PROG_ERROR);
122 block.compressed_size = LZMA_VLI_UNKNOWN;
124 // Test invalid uncompressed size
125 block.uncompressed_size = LZMA_VLI_MAX + 1;
126 assert_lzma_ret(lzma_block_header_size(&block), LZMA_PROG_ERROR);
127 block.uncompressed_size = LZMA_VLI_MAX;
129 // Test invalid filters
130 block.filters = NULL;
131 assert_lzma_ret(lzma_block_header_size(&block), LZMA_PROG_ERROR);
133 block.filters = filters_none;
134 assert_lzma_ret(lzma_block_header_size(&block), LZMA_PROG_ERROR);
136 block.filters = filters_five;
137 assert_lzma_ret(lzma_block_header_size(&block), LZMA_PROG_ERROR);
139 block.filters = filters_one;
141 // Test setting compressed_size to something valid
142 block.compressed_size = 4096;
143 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
144 assert_uint(block.header_size, >=, LZMA_BLOCK_HEADER_SIZE_MIN);
145 assert_uint(block.header_size, <=, LZMA_BLOCK_HEADER_SIZE_MAX);
146 assert_uint_eq(block.header_size % 4, 0);
148 // Test setting uncompressed_size to something valid
149 block.uncompressed_size = 4096;
150 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
151 assert_uint(block.header_size, >=, LZMA_BLOCK_HEADER_SIZE_MIN);
152 assert_uint(block.header_size, <=, LZMA_BLOCK_HEADER_SIZE_MAX);
153 assert_uint_eq(block.header_size % 4, 0);
155 // This should pass, but header_size will be an invalid value
156 // because the total block size will not be able to fit in a valid
157 // lzma_vli. This way a temporary value can be used to reserve
158 // space for the header and later the actual value can be set.
159 block.compressed_size = LZMA_VLI_MAX;
160 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
161 assert_uint(block.header_size, >=, LZMA_BLOCK_HEADER_SIZE_MIN);
162 assert_uint(block.header_size, <=, LZMA_BLOCK_HEADER_SIZE_MAX);
163 assert_uint_eq(block.header_size % 4, 0);
165 // Use an invalid value for a filter option. This should still pass
166 // because the size of the LZMA2 properties is known by liblzma
167 // without reading any of the options so it doesn't validate them.
168 lzma_options_lzma bad_ops;
169 assert_false(lzma_lzma_preset(&bad_ops, 1));
170 bad_ops.pb = 0x1000;
172 lzma_filter bad_filters[2] = {
174 .id = LZMA_FILTER_LZMA2,
175 .options = &bad_ops
178 .id = LZMA_VLI_UNKNOWN,
179 .options = NULL
183 block.filters = bad_filters;
185 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
186 assert_uint(block.header_size, >=, LZMA_BLOCK_HEADER_SIZE_MIN);
187 assert_uint(block.header_size, <=, LZMA_BLOCK_HEADER_SIZE_MAX);
188 assert_uint_eq(block.header_size % 4, 0);
190 // Use an invalid block option. The check type isn't stored in
191 // the Block Header and so _header_size ignores it.
192 block.check = INVALID_LZMA_CHECK_ID;
193 block.ignore_check = false;
195 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
196 assert_uint(block.header_size, >=, LZMA_BLOCK_HEADER_SIZE_MIN);
197 assert_uint(block.header_size, <=, LZMA_BLOCK_HEADER_SIZE_MAX);
198 assert_uint_eq(block.header_size % 4, 0);
199 #endif
203 static void
204 test_lzma_block_header_encode(void)
206 #if !defined(HAVE_ENCODERS) || !defined(HAVE_DECODERS)
207 assert_skip("Encoder or decoder support disabled");
208 #else
210 if (!lzma_filter_encoder_is_supported(LZMA_FILTER_X86)
211 || !lzma_filter_decoder_is_supported(LZMA_FILTER_X86))
212 assert_skip("x86 BCJ encoder and/or decoder "
213 "is disabled");
215 lzma_block block = {
216 .version = 1,
217 .filters = filters_one,
218 .compressed_size = LZMA_VLI_UNKNOWN,
219 .uncompressed_size = LZMA_VLI_UNKNOWN,
220 .check = LZMA_CHECK_CRC32,
223 // Ensure all block options are valid before changes are tested
224 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
226 uint8_t out[LZMA_BLOCK_HEADER_SIZE_MAX];
228 // Test invalid block version
229 for (uint32_t i = 2; i < 20; i++) {
230 block.version = i;
231 assert_lzma_ret(lzma_block_header_encode(&block, out),
232 LZMA_PROG_ERROR);
235 block.version = 1;
237 // Test invalid header size (< min, > max, % 4 != 0)
238 block.header_size = LZMA_BLOCK_HEADER_SIZE_MIN - 4;
239 assert_lzma_ret(lzma_block_header_encode(&block, out),
240 LZMA_PROG_ERROR);
241 block.header_size = LZMA_BLOCK_HEADER_SIZE_MIN + 2;
242 assert_lzma_ret(lzma_block_header_encode(&block, out),
243 LZMA_PROG_ERROR);
244 block.header_size = LZMA_BLOCK_HEADER_SIZE_MAX + 4;
245 assert_lzma_ret(lzma_block_header_encode(&block, out),
246 LZMA_PROG_ERROR);
247 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
249 // Test invalid compressed_size
250 block.compressed_size = 0;
251 assert_lzma_ret(lzma_block_header_encode(&block, out),
252 LZMA_PROG_ERROR);
253 block.compressed_size = LZMA_VLI_MAX + 1;
254 assert_lzma_ret(lzma_block_header_encode(&block, out),
255 LZMA_PROG_ERROR);
257 // This test passes test_lzma_block_header_size, but should
258 // fail here because there is not enough space to encode the
259 // proper block size because the total size is too big to fit
260 // in an lzma_vli
261 block.compressed_size = LZMA_VLI_MAX;
262 assert_lzma_ret(lzma_block_header_encode(&block, out),
263 LZMA_PROG_ERROR);
264 block.compressed_size = LZMA_VLI_UNKNOWN;
266 // Test invalid uncompressed size
267 block.uncompressed_size = LZMA_VLI_MAX + 1;
268 assert_lzma_ret(lzma_block_header_encode(&block, out),
269 LZMA_PROG_ERROR);
270 block.uncompressed_size = LZMA_VLI_UNKNOWN;
272 // Test invalid block check
273 block.check = INVALID_LZMA_CHECK_ID;
274 block.ignore_check = false;
275 assert_lzma_ret(lzma_block_header_encode(&block, out),
276 LZMA_PROG_ERROR);
277 block.check = LZMA_CHECK_CRC32;
279 // Test invalid filters
280 block.filters = NULL;
281 assert_lzma_ret(lzma_block_header_encode(&block, out),
282 LZMA_PROG_ERROR);
284 block.filters = filters_none;
285 assert_lzma_ret(lzma_block_header_encode(&block, out),
286 LZMA_PROG_ERROR);
288 block.filters = filters_five;
289 block.header_size = LZMA_BLOCK_HEADER_SIZE_MAX - 4;
290 assert_lzma_ret(lzma_block_header_encode(&block, out),
291 LZMA_PROG_ERROR);
293 // Test valid encoding and verify bytes of block header.
294 // More complicated tests for encoding headers are included
295 // in test_lzma_block_header_decode.
296 block.filters = filters_one;
297 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
298 assert_lzma_ret(lzma_block_header_encode(&block, out), LZMA_OK);
300 // First read block header size from out and verify
301 // that it == (encoded size + 1) * 4
302 uint32_t header_size = (out[0] + 1U) * 4;
303 assert_uint_eq(header_size, block.header_size);
305 // Next read block flags
306 uint8_t flags = out[1];
308 // Should have number of filters = 1
309 assert_uint_eq((flags & 0x3) + 1, 1);
311 // Bits 2-7 must be empty not set
312 assert_uint_eq(flags & (0xFF - 0x3), 0);
314 // Verify filter flags
315 // Decode Filter ID
316 lzma_vli filter_id = 0;
317 size_t pos = 2;
318 assert_lzma_ret(lzma_vli_decode(&filter_id, NULL, out,
319 &pos, header_size), LZMA_OK);
320 assert_uint_eq(filter_id, filters_one[0].id);
322 // Decode Size of Properties
323 lzma_vli prop_size = 0;
324 assert_lzma_ret(lzma_vli_decode(&prop_size, NULL, out,
325 &pos, header_size), LZMA_OK);
327 // LZMA2 has 1 byte prop size
328 assert_uint_eq(prop_size, 1);
329 uint8_t expected_filter_props = 0;
330 assert_lzma_ret(lzma_properties_encode(filters_one,
331 &expected_filter_props), LZMA_OK);
332 assert_uint_eq(out[pos], expected_filter_props);
333 pos++;
335 // Check null-padding
336 for (size_t i = pos; i < header_size - 4; i++)
337 assert_uint_eq(out[i], 0);
339 // Check CRC32
340 assert_uint_eq(read32le(&out[header_size - 4]), lzma_crc32(out,
341 header_size - 4, 0));
342 #endif
346 #if defined(HAVE_ENCODERS) && defined(HAVE_DECODERS)
347 // Helper function to compare two lzma_block structures field by field
348 static void
349 compare_blocks(lzma_block *block_expected, lzma_block *block_actual)
351 assert_uint_eq(block_actual->version, block_expected->version);
352 assert_uint_eq(block_actual->compressed_size,
353 block_expected->compressed_size);
354 assert_uint_eq(block_actual->uncompressed_size,
355 block_expected->uncompressed_size);
356 assert_uint_eq(block_actual->check, block_expected->check);
357 assert_uint_eq(block_actual->header_size, block_expected->header_size);
359 // Compare filter IDs
360 assert_true(block_expected->filters && block_actual->filters);
361 lzma_filter expected_filter = block_expected->filters[0];
362 uint32_t filter_count = 0;
363 while (expected_filter.id != LZMA_VLI_UNKNOWN) {
364 assert_uint_eq(block_actual->filters[filter_count].id,
365 expected_filter.id);
366 expected_filter = block_expected->filters[++filter_count];
369 assert_uint_eq(block_actual->filters[filter_count].id,
370 LZMA_VLI_UNKNOWN);
372 #endif
375 static void
376 test_lzma_block_header_decode(void)
378 #if !defined(HAVE_ENCODERS) || !defined(HAVE_DECODERS)
379 assert_skip("Encoder or decoder support disabled");
380 #else
381 if (!lzma_filter_encoder_is_supported(LZMA_FILTER_X86)
382 || !lzma_filter_decoder_is_supported(LZMA_FILTER_X86))
383 assert_skip("x86 BCJ encoder and/or decoder "
384 "is disabled");
386 lzma_block block = {
387 .filters = filters_one,
388 .compressed_size = LZMA_VLI_UNKNOWN,
389 .uncompressed_size = LZMA_VLI_UNKNOWN,
390 .check = LZMA_CHECK_CRC32,
391 .version = 0
394 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
396 // Encode block header with simple options
397 uint8_t out[LZMA_BLOCK_HEADER_SIZE_MAX];
398 assert_lzma_ret(lzma_block_header_encode(&block, out), LZMA_OK);
400 // Decode block header and check that the options match
401 lzma_filter decoded_filters[LZMA_FILTERS_MAX + 1];
402 lzma_block decoded_block = {
403 .version = 0,
404 .filters = decoded_filters,
405 .check = LZMA_CHECK_CRC32
407 decoded_block.header_size = lzma_block_header_size_decode(out[0]);
409 assert_lzma_ret(lzma_block_header_decode(&decoded_block, NULL, out),
410 LZMA_OK);
411 compare_blocks(&block, &decoded_block);
413 // Reset output buffer and decoded_block
414 memzero(out, LZMA_BLOCK_HEADER_SIZE_MAX);
415 memzero(&decoded_block, sizeof(lzma_block));
416 decoded_block.filters = decoded_filters;
417 decoded_block.check = LZMA_CHECK_CRC32;
419 // Test with compressed size set
420 block.compressed_size = 4096;
421 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
422 assert_lzma_ret(lzma_block_header_encode(&block, out), LZMA_OK);
423 decoded_block.header_size = lzma_block_header_size_decode(out[0]);
424 assert_lzma_ret(lzma_block_header_decode(&decoded_block, NULL, out),
425 LZMA_OK);
426 compare_blocks(&block, &decoded_block);
428 memzero(out, LZMA_BLOCK_HEADER_SIZE_MAX);
429 memzero(&decoded_block, sizeof(lzma_block));
430 decoded_block.filters = decoded_filters;
431 decoded_block.check = LZMA_CHECK_CRC32;
433 // Test with uncompressed size set
434 block.uncompressed_size = 4096;
435 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
436 assert_lzma_ret(lzma_block_header_encode(&block, out), LZMA_OK);
437 decoded_block.header_size = lzma_block_header_size_decode(out[0]);
438 assert_lzma_ret(lzma_block_header_decode(&decoded_block, NULL, out),
439 LZMA_OK);
440 compare_blocks(&block, &decoded_block);
442 memzero(out, LZMA_BLOCK_HEADER_SIZE_MAX);
443 memzero(&decoded_block, sizeof(lzma_block));
444 decoded_block.filters = decoded_filters;
445 decoded_block.check = LZMA_CHECK_CRC32;
447 // Test with multiple filters
448 block.filters = filters_four;
449 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
450 assert_lzma_ret(lzma_block_header_encode(&block, out), LZMA_OK);
451 decoded_block.header_size = lzma_block_header_size_decode(out[0]);
452 assert_lzma_ret(lzma_block_header_decode(&decoded_block, NULL, out),
453 LZMA_OK);
454 compare_blocks(&block, &decoded_block);
456 memzero(&decoded_block, sizeof(lzma_block));
457 decoded_block.filters = decoded_filters;
458 decoded_block.check = LZMA_CHECK_CRC32;
459 decoded_block.header_size = lzma_block_header_size_decode(out[0]);
461 // Test with too high version. The decoder will set it to a version
462 // that it supports.
463 decoded_block.version = 2;
464 assert_lzma_ret(lzma_block_header_decode(&decoded_block, NULL, out),
465 LZMA_OK);
466 assert_uint_eq(decoded_block.version, 1);
468 // Test bad check type
469 decoded_block.check = INVALID_LZMA_CHECK_ID;
470 assert_lzma_ret(lzma_block_header_decode(&decoded_block, NULL, out),
471 LZMA_PROG_ERROR);
472 decoded_block.check = LZMA_CHECK_CRC32;
474 // Test bad check value
475 out[decoded_block.header_size - 1] -= 10;
476 assert_lzma_ret(lzma_block_header_decode(&decoded_block, NULL, out),
477 LZMA_DATA_ERROR);
478 out[decoded_block.header_size - 1] += 10;
480 // Test non-NULL padding
481 out[decoded_block.header_size - 5] = 1;
483 // Recompute CRC32
484 write32le(&out[decoded_block.header_size - 4], lzma_crc32(out,
485 decoded_block.header_size - 4, 0));
486 assert_lzma_ret(lzma_block_header_decode(&decoded_block, NULL, out),
487 LZMA_OPTIONS_ERROR);
489 // Test unsupported flags
490 out[1] = 0xFF;
492 // Recompute CRC32
493 write32le(&out[decoded_block.header_size - 4], lzma_crc32(out,
494 decoded_block.header_size - 4, 0));
495 assert_lzma_ret(lzma_block_header_decode(&decoded_block, NULL, out),
496 LZMA_OPTIONS_ERROR);
497 #endif
501 extern int
502 main(int argc, char **argv)
504 tuktest_start(argc, argv);
506 if (lzma_lzma_preset(&opt_lzma, 1))
507 tuktest_error("lzma_lzma_preset() failed");
509 tuktest_run(test_lzma_block_header_size);
510 tuktest_run(test_lzma_block_header_encode);
511 tuktest_run(test_lzma_block_header_decode);
513 return tuktest_end();