Translations: Update the German man page translations.
[xz.git] / tests / test_block_header.c
blob6b42df22c5f4b4b1a37c9b288886f1364d2b83b7
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 static lzma_filter filters_four[5] = {
40 .id = LZMA_FILTER_X86,
41 .options = NULL,
42 }, {
43 .id = LZMA_FILTER_X86,
44 .options = NULL,
45 }, {
46 .id = LZMA_FILTER_X86,
47 .options = NULL,
48 }, {
49 .id = LZMA_FILTER_LZMA2,
50 .options = &opt_lzma,
51 }, {
52 .id = LZMA_VLI_UNKNOWN,
57 static lzma_filter filters_five[6] = {
59 .id = LZMA_FILTER_X86,
60 .options = NULL,
61 }, {
62 .id = LZMA_FILTER_X86,
63 .options = NULL,
64 }, {
65 .id = LZMA_FILTER_X86,
66 .options = NULL,
67 }, {
68 .id = LZMA_FILTER_X86,
69 .options = NULL,
70 }, {
71 .id = LZMA_FILTER_LZMA2,
72 .options = &opt_lzma,
73 }, {
74 .id = LZMA_VLI_UNKNOWN,
77 #endif
80 static void
81 test_lzma_block_header_size(void)
83 #ifndef HAVE_ENCODERS
84 assert_skip("Encoder support disabled");
85 #else
86 if (!lzma_filter_encoder_is_supported(LZMA_FILTER_X86))
87 assert_skip("x86 BCJ encoder is disabled");
89 lzma_block block = {
90 .version = 0,
91 .filters = filters_one,
92 .compressed_size = LZMA_VLI_UNKNOWN,
93 .uncompressed_size = LZMA_VLI_UNKNOWN,
94 .check = LZMA_CHECK_CRC32
97 // Test that all initial options are valid
98 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
99 assert_uint(block.header_size, >=, LZMA_BLOCK_HEADER_SIZE_MIN);
100 assert_uint(block.header_size, <=, LZMA_BLOCK_HEADER_SIZE_MAX);
101 assert_uint_eq(block.header_size % 4, 0);
103 // Test invalid version number
104 for (uint32_t i = 2; i < 20; i++) {
105 block.version = i;
106 assert_lzma_ret(lzma_block_header_size(&block),
107 LZMA_OPTIONS_ERROR);
110 block.version = 1;
112 // Test invalid compressed size
113 block.compressed_size = 0;
114 assert_lzma_ret(lzma_block_header_size(&block), LZMA_PROG_ERROR);
116 block.compressed_size = LZMA_VLI_MAX + 1;
117 assert_lzma_ret(lzma_block_header_size(&block), LZMA_PROG_ERROR);
118 block.compressed_size = LZMA_VLI_UNKNOWN;
120 // Test invalid uncompressed size
121 block.uncompressed_size = LZMA_VLI_MAX + 1;
122 assert_lzma_ret(lzma_block_header_size(&block), LZMA_PROG_ERROR);
123 block.uncompressed_size = LZMA_VLI_MAX;
125 // Test invalid filters
126 block.filters = NULL;
127 assert_lzma_ret(lzma_block_header_size(&block), LZMA_PROG_ERROR);
129 block.filters = filters_none;
130 assert_lzma_ret(lzma_block_header_size(&block), LZMA_PROG_ERROR);
132 block.filters = filters_five;
133 assert_lzma_ret(lzma_block_header_size(&block), LZMA_PROG_ERROR);
135 block.filters = filters_one;
137 // Test setting compressed_size to something valid
138 block.compressed_size = 4096;
139 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
140 assert_uint(block.header_size, >=, LZMA_BLOCK_HEADER_SIZE_MIN);
141 assert_uint(block.header_size, <=, LZMA_BLOCK_HEADER_SIZE_MAX);
142 assert_uint_eq(block.header_size % 4, 0);
144 // Test setting uncompressed_size to something valid
145 block.uncompressed_size = 4096;
146 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
147 assert_uint(block.header_size, >=, LZMA_BLOCK_HEADER_SIZE_MIN);
148 assert_uint(block.header_size, <=, LZMA_BLOCK_HEADER_SIZE_MAX);
149 assert_uint_eq(block.header_size % 4, 0);
151 // This should pass, but header_size will be an invalid value
152 // because the total block size will not be able to fit in a valid
153 // lzma_vli. This way a temporary value can be used to reserve
154 // space for the header and later the actual value can be set.
155 block.compressed_size = LZMA_VLI_MAX;
156 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
157 assert_uint(block.header_size, >=, LZMA_BLOCK_HEADER_SIZE_MIN);
158 assert_uint(block.header_size, <=, LZMA_BLOCK_HEADER_SIZE_MAX);
159 assert_uint_eq(block.header_size % 4, 0);
161 // Use an invalid value for a filter option. This should still pass
162 // because the size of the LZMA2 properties is known by liblzma
163 // without reading any of the options so it doesn't validate them.
164 lzma_options_lzma bad_ops;
165 assert_false(lzma_lzma_preset(&bad_ops, 1));
166 bad_ops.pb = 0x1000;
168 lzma_filter bad_filters[2] = {
170 .id = LZMA_FILTER_LZMA2,
171 .options = &bad_ops
174 .id = LZMA_VLI_UNKNOWN,
175 .options = NULL
179 block.filters = bad_filters;
181 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
182 assert_uint(block.header_size, >=, LZMA_BLOCK_HEADER_SIZE_MIN);
183 assert_uint(block.header_size, <=, LZMA_BLOCK_HEADER_SIZE_MAX);
184 assert_uint_eq(block.header_size % 4, 0);
186 // Use an invalid block option. The check type isn't stored in
187 // the Block Header and so _header_size ignores it.
188 block.check = 0x1000;
189 block.ignore_check = false;
191 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
192 assert_uint(block.header_size, >=, LZMA_BLOCK_HEADER_SIZE_MIN);
193 assert_uint(block.header_size, <=, LZMA_BLOCK_HEADER_SIZE_MAX);
194 assert_uint_eq(block.header_size % 4, 0);
195 #endif
199 static void
200 test_lzma_block_header_encode(void)
202 #if !defined(HAVE_ENCODERS) || !defined(HAVE_DECODERS)
203 assert_skip("Encoder or decoder support disabled");
204 #else
206 if (!lzma_filter_encoder_is_supported(LZMA_FILTER_X86)
207 || !lzma_filter_decoder_is_supported(LZMA_FILTER_X86))
208 assert_skip("x86 BCJ encoder and/or decoder "
209 "is disabled");
211 lzma_block block = {
212 .version = 1,
213 .filters = filters_one,
214 .compressed_size = LZMA_VLI_UNKNOWN,
215 .uncompressed_size = LZMA_VLI_UNKNOWN,
216 .check = LZMA_CHECK_CRC32,
219 // Ensure all block options are valid before changes are tested
220 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
222 uint8_t out[LZMA_BLOCK_HEADER_SIZE_MAX];
224 // Test invalid block version
225 for (uint32_t i = 2; i < 20; i++) {
226 block.version = i;
227 assert_lzma_ret(lzma_block_header_encode(&block, out),
228 LZMA_PROG_ERROR);
231 block.version = 1;
233 // Test invalid header size (< min, > max, % 4 != 0)
234 block.header_size = LZMA_BLOCK_HEADER_SIZE_MIN - 4;
235 assert_lzma_ret(lzma_block_header_encode(&block, out),
236 LZMA_PROG_ERROR);
237 block.header_size = LZMA_BLOCK_HEADER_SIZE_MIN + 2;
238 assert_lzma_ret(lzma_block_header_encode(&block, out),
239 LZMA_PROG_ERROR);
240 block.header_size = LZMA_BLOCK_HEADER_SIZE_MAX + 4;
241 assert_lzma_ret(lzma_block_header_encode(&block, out),
242 LZMA_PROG_ERROR);
243 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
245 // Test invalid compressed_size
246 block.compressed_size = 0;
247 assert_lzma_ret(lzma_block_header_encode(&block, out),
248 LZMA_PROG_ERROR);
249 block.compressed_size = LZMA_VLI_MAX + 1;
250 assert_lzma_ret(lzma_block_header_encode(&block, out),
251 LZMA_PROG_ERROR);
253 // This test passes test_lzma_block_header_size, but should
254 // fail here because there is not enough space to encode the
255 // proper block size because the total size is too big to fit
256 // in an lzma_vli
257 block.compressed_size = LZMA_VLI_MAX;
258 assert_lzma_ret(lzma_block_header_encode(&block, out),
259 LZMA_PROG_ERROR);
260 block.compressed_size = LZMA_VLI_UNKNOWN;
262 // Test invalid uncompressed size
263 block.uncompressed_size = LZMA_VLI_MAX + 1;
264 assert_lzma_ret(lzma_block_header_encode(&block, out),
265 LZMA_PROG_ERROR);
266 block.uncompressed_size = LZMA_VLI_UNKNOWN;
268 // Test invalid block check
269 block.check = 0x1000;
270 block.ignore_check = false;
271 assert_lzma_ret(lzma_block_header_encode(&block, out),
272 LZMA_PROG_ERROR);
273 block.check = LZMA_CHECK_CRC32;
275 // Test invalid filters
276 block.filters = NULL;
277 assert_lzma_ret(lzma_block_header_encode(&block, out),
278 LZMA_PROG_ERROR);
280 block.filters = filters_none;
281 assert_lzma_ret(lzma_block_header_encode(&block, out),
282 LZMA_PROG_ERROR);
284 block.filters = filters_five;
285 block.header_size = LZMA_BLOCK_HEADER_SIZE_MAX - 4;
286 assert_lzma_ret(lzma_block_header_encode(&block, out),
287 LZMA_PROG_ERROR);
289 // Test valid encoding and verify bytes of block header.
290 // More complicated tests for encoding headers are included
291 // in test_lzma_block_header_decode.
292 block.filters = filters_one;
293 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
294 assert_lzma_ret(lzma_block_header_encode(&block, out), LZMA_OK);
296 // First read block header size from out and verify
297 // that it == (encoded size + 1) * 4
298 uint32_t header_size = (out[0] + 1U) * 4;
299 assert_uint_eq(header_size, block.header_size);
301 // Next read block flags
302 uint8_t flags = out[1];
304 // Should have number of filters = 1
305 assert_uint_eq((flags & 0x3) + 1, 1);
307 // Bits 2-7 must be empty not set
308 assert_uint_eq(flags & (0xFF - 0x3), 0);
310 // Verify filter flags
311 // Decode Filter ID
312 lzma_vli filter_id = 0;
313 size_t pos = 2;
314 assert_lzma_ret(lzma_vli_decode(&filter_id, NULL, out,
315 &pos, header_size), LZMA_OK);
316 assert_uint_eq(filter_id, filters_one[0].id);
318 // Decode Size of Properties
319 lzma_vli prop_size = 0;
320 assert_lzma_ret(lzma_vli_decode(&prop_size, NULL, out,
321 &pos, header_size), LZMA_OK);
323 // LZMA2 has 1 byte prop size
324 assert_uint_eq(prop_size, 1);
325 uint8_t expected_filter_props = 0;
326 assert_lzma_ret(lzma_properties_encode(filters_one,
327 &expected_filter_props), LZMA_OK);
328 assert_uint_eq(out[pos], expected_filter_props);
329 pos++;
331 // Check null-padding
332 for (size_t i = pos; i < header_size - 4; i++)
333 assert_uint_eq(out[i], 0);
335 // Check CRC32
336 assert_uint_eq(read32le(&out[header_size - 4]), lzma_crc32(out,
337 header_size - 4, 0));
338 #endif
342 #if defined(HAVE_ENCODERS) && defined(HAVE_DECODERS)
343 // Helper function to compare two lzma_block structures field by field
344 static void
345 compare_blocks(lzma_block *block_expected, lzma_block *block_actual)
347 assert_uint_eq(block_actual->version, block_expected->version);
348 assert_uint_eq(block_actual->compressed_size,
349 block_expected->compressed_size);
350 assert_uint_eq(block_actual->uncompressed_size,
351 block_expected->uncompressed_size);
352 assert_uint_eq(block_actual->check, block_expected->check);
353 assert_uint_eq(block_actual->header_size, block_expected->header_size);
355 // Compare filter IDs
356 assert_true(block_expected->filters && block_actual->filters);
357 lzma_filter expected_filter = block_expected->filters[0];
358 uint32_t filter_count = 0;
359 while (expected_filter.id != LZMA_VLI_UNKNOWN) {
360 assert_uint_eq(block_actual->filters[filter_count].id,
361 expected_filter.id);
362 expected_filter = block_expected->filters[++filter_count];
365 assert_uint_eq(block_actual->filters[filter_count].id,
366 LZMA_VLI_UNKNOWN);
368 #endif
371 static void
372 test_lzma_block_header_decode(void)
374 #if !defined(HAVE_ENCODERS) || !defined(HAVE_DECODERS)
375 assert_skip("Encoder or decoder support disabled");
376 #else
377 if (!lzma_filter_encoder_is_supported(LZMA_FILTER_X86)
378 || !lzma_filter_decoder_is_supported(LZMA_FILTER_X86))
379 assert_skip("x86 BCJ encoder and/or decoder "
380 "is disabled");
382 lzma_block block = {
383 .filters = filters_one,
384 .compressed_size = LZMA_VLI_UNKNOWN,
385 .uncompressed_size = LZMA_VLI_UNKNOWN,
386 .check = LZMA_CHECK_CRC32,
387 .version = 0
390 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
392 // Encode block header with simple options
393 uint8_t out[LZMA_BLOCK_HEADER_SIZE_MAX];
394 assert_lzma_ret(lzma_block_header_encode(&block, out), LZMA_OK);
396 // Decode block header and check that the options match
397 lzma_filter decoded_filters[LZMA_FILTERS_MAX + 1];
398 lzma_block decoded_block = {
399 .version = 0,
400 .filters = decoded_filters,
401 .check = LZMA_CHECK_CRC32
403 decoded_block.header_size = lzma_block_header_size_decode(out[0]);
405 assert_lzma_ret(lzma_block_header_decode(&decoded_block, NULL, out),
406 LZMA_OK);
407 compare_blocks(&block, &decoded_block);
409 // Reset output buffer and decoded_block
410 memzero(out, LZMA_BLOCK_HEADER_SIZE_MAX);
411 memzero(&decoded_block, sizeof(lzma_block));
412 decoded_block.filters = decoded_filters;
413 decoded_block.check = LZMA_CHECK_CRC32;
415 // Test with compressed size set
416 block.compressed_size = 4096;
417 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
418 assert_lzma_ret(lzma_block_header_encode(&block, out), LZMA_OK);
419 decoded_block.header_size = lzma_block_header_size_decode(out[0]);
420 assert_lzma_ret(lzma_block_header_decode(&decoded_block, NULL, out),
421 LZMA_OK);
422 compare_blocks(&block, &decoded_block);
424 memzero(out, LZMA_BLOCK_HEADER_SIZE_MAX);
425 memzero(&decoded_block, sizeof(lzma_block));
426 decoded_block.filters = decoded_filters;
427 decoded_block.check = LZMA_CHECK_CRC32;
429 // Test with uncompressed size set
430 block.uncompressed_size = 4096;
431 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
432 assert_lzma_ret(lzma_block_header_encode(&block, out), LZMA_OK);
433 decoded_block.header_size = lzma_block_header_size_decode(out[0]);
434 assert_lzma_ret(lzma_block_header_decode(&decoded_block, NULL, out),
435 LZMA_OK);
436 compare_blocks(&block, &decoded_block);
438 memzero(out, LZMA_BLOCK_HEADER_SIZE_MAX);
439 memzero(&decoded_block, sizeof(lzma_block));
440 decoded_block.filters = decoded_filters;
441 decoded_block.check = LZMA_CHECK_CRC32;
443 // Test with multiple filters
444 block.filters = filters_four;
445 assert_lzma_ret(lzma_block_header_size(&block), LZMA_OK);
446 assert_lzma_ret(lzma_block_header_encode(&block, out), LZMA_OK);
447 decoded_block.header_size = lzma_block_header_size_decode(out[0]);
448 assert_lzma_ret(lzma_block_header_decode(&decoded_block, NULL, out),
449 LZMA_OK);
450 compare_blocks(&block, &decoded_block);
452 memzero(&decoded_block, sizeof(lzma_block));
453 decoded_block.filters = decoded_filters;
454 decoded_block.check = LZMA_CHECK_CRC32;
455 decoded_block.header_size = lzma_block_header_size_decode(out[0]);
457 // Test with too high version. The decoder will set it to a version
458 // that it supports.
459 decoded_block.version = 2;
460 assert_lzma_ret(lzma_block_header_decode(&decoded_block, NULL, out),
461 LZMA_OK);
462 assert_uint_eq(decoded_block.version, 1);
464 // Test bad check type
465 decoded_block.check = LZMA_CHECK_ID_MAX + 1;
466 assert_lzma_ret(lzma_block_header_decode(&decoded_block, NULL, out),
467 LZMA_PROG_ERROR);
468 decoded_block.check = LZMA_CHECK_CRC32;
470 // Test bad check value
471 out[decoded_block.header_size - 1] -= 10;
472 assert_lzma_ret(lzma_block_header_decode(&decoded_block, NULL, out),
473 LZMA_DATA_ERROR);
474 out[decoded_block.header_size - 1] += 10;
476 // Test non-NULL padding
477 out[decoded_block.header_size - 5] = 1;
479 // Recompute CRC32
480 write32le(&out[decoded_block.header_size - 4], lzma_crc32(out,
481 decoded_block.header_size - 4, 0));
482 assert_lzma_ret(lzma_block_header_decode(&decoded_block, NULL, out),
483 LZMA_OPTIONS_ERROR);
485 // Test unsupported flags
486 out[1] = 0xFF;
488 // Recompute CRC32
489 write32le(&out[decoded_block.header_size - 4], lzma_crc32(out,
490 decoded_block.header_size - 4, 0));
491 assert_lzma_ret(lzma_block_header_decode(&decoded_block, NULL, out),
492 LZMA_OPTIONS_ERROR);
493 #endif
497 extern int
498 main(int argc, char **argv)
500 tuktest_start(argc, argv);
502 if (lzma_lzma_preset(&opt_lzma, 1))
503 tuktest_error("lzma_lzma_preset() failed");
505 tuktest_run(test_lzma_block_header_size);
506 tuktest_run(test_lzma_block_header_encode);
507 tuktest_run(test_lzma_block_header_decode);
509 return tuktest_end();