liblzma: Prevent warning for MSYS2 Windows build.
[xz/debian.git] / tests / test_filter_flags.c
blob5cfccea9165490f6932e8b3124b1b425fcdd215c
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 /// \file test_filter_flags.c
4 /// \brief Tests Filter Flags coders
5 //
6 // Authors: Jia Tan
7 // Lasse Collin
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"
16 // FIXME: This is from src/liblzma/common/common.h but it cannot be
17 // included here. This constant is needed in only a few files, perhaps
18 // move it to some other internal header or create a new one?
19 #define LZMA_FILTER_RESERVED_START (LZMA_VLI_C(1) << 62)
22 #if defined(HAVE_ENCODERS)
23 // No tests are run without encoders, so init the global filters
24 // only when the encoders are enabled.
25 static lzma_filter lzma1_filter = { LZMA_FILTER_LZMA1, NULL };
26 static lzma_filter lzma2_filter = { LZMA_FILTER_LZMA2, NULL };
27 static lzma_filter delta_filter = { LZMA_FILTER_DELTA, NULL };
29 static lzma_filter bcj_filters_encoders[] = {
30 #ifdef HAVE_ENCODER_X86
31 { LZMA_FILTER_X86, NULL },
32 #endif
33 #ifdef HAVE_ENCODER_POWERPC
34 { LZMA_FILTER_POWERPC, NULL },
35 #endif
36 #ifdef HAVE_ENCODER_IA64
37 { LZMA_FILTER_IA64, NULL },
38 #endif
39 #ifdef HAVE_ENCODER_ARM
40 { LZMA_FILTER_ARM, NULL },
41 #endif
42 #ifdef HAVE_ENCODER_ARM64
43 { LZMA_FILTER_ARM64, NULL },
44 #endif
45 #ifdef HAVE_ENCODER_ARMTHUMB
46 { LZMA_FILTER_ARMTHUMB, NULL },
47 #endif
48 #ifdef HAVE_ENCODER_SPARC
49 { LZMA_FILTER_SPARC, NULL },
50 #endif
53 // HAVE_ENCODERS ifdef not termianted here because decoders are
54 // only used if encoders are, but encoders can still be used
55 // even if decoders are not.
57 #ifdef HAVE_DECODERS
58 static lzma_filter bcj_filters_decoders[] = {
59 #ifdef HAVE_DECODER_X86
60 { LZMA_FILTER_X86, NULL },
61 #endif
62 #ifdef HAVE_DECODER_POWERPC
63 { LZMA_FILTER_POWERPC, NULL },
64 #endif
65 #ifdef HAVE_DECODER_IA64
66 { LZMA_FILTER_IA64, NULL },
67 #endif
68 #ifdef HAVE_DECODER_ARM
69 { LZMA_FILTER_ARM, NULL },
70 #endif
71 #ifdef HAVE_DECODER_ARM64
72 { LZMA_FILTER_ARM64, NULL },
73 #endif
74 #ifdef HAVE_DECODER_ARMTHUMB
75 { LZMA_FILTER_ARMTHUMB, NULL },
76 #endif
77 #ifdef HAVE_DECODER_SPARC
78 { LZMA_FILTER_SPARC, NULL },
79 #endif
81 #endif
82 #endif
85 static void
86 test_lzma_filter_flags_size(void)
88 #ifndef HAVE_ENCODERS
89 assert_skip("Encoder support disabled");
90 #else
91 // For each supported filter, test that the size can be calculated
92 // and that the size calculated is reasonable. A reasonable size
93 // must be greater than 0, but less than the maximum size for the
94 // block header.
95 uint32_t size = 0;
96 if (lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA1)) {
97 assert_lzma_ret(lzma_filter_flags_size(&size,
98 &lzma1_filter), LZMA_PROG_ERROR);
101 if (lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA2)) {
102 assert_lzma_ret(lzma_filter_flags_size(&size,
103 &lzma2_filter), LZMA_OK);
104 assert_true(size != 0 && size < LZMA_BLOCK_HEADER_SIZE_MAX);
107 // Do not use macro ARRAY_SIZE() in the for loop condition directly.
108 // If the BCJ filters are not configured and built, then ARRAY_SIZE()
109 // will return 0 and cause a warning because the for loop will never
110 // execute since any unsigned number cannot be < 0 (-Werror=type-limits).
111 const uint32_t bcj_array_size = ARRAY_SIZE(bcj_filters_encoders);
112 for (uint32_t i = 0; i < bcj_array_size; i++) {
113 assert_lzma_ret(lzma_filter_flags_size(&size,
114 &bcj_filters_encoders[i]), LZMA_OK);
115 assert_true(size != 0 && size < LZMA_BLOCK_HEADER_SIZE_MAX);
118 if (lzma_filter_encoder_is_supported(LZMA_FILTER_DELTA)) {
119 assert_lzma_ret(lzma_filter_flags_size(&size,
120 &delta_filter), LZMA_OK);
121 assert_true(size != 0 && size < LZMA_BLOCK_HEADER_SIZE_MAX);
124 // Test invalid Filter IDs
125 lzma_filter bad_filter = { 2, NULL };
127 assert_lzma_ret(lzma_filter_flags_size(&size, &bad_filter),
128 LZMA_OPTIONS_ERROR);
129 bad_filter.id = LZMA_VLI_MAX;
130 assert_lzma_ret(lzma_filter_flags_size(&size, &bad_filter),
131 LZMA_PROG_ERROR);
132 bad_filter.id = LZMA_FILTER_RESERVED_START;
133 assert_lzma_ret(lzma_filter_flags_size(&size, &bad_filter),
134 LZMA_PROG_ERROR);
135 #endif
139 // Helper function for test_lzma_filter_flags_encode.
140 // The should_encode parameter represents if the encoding operation
141 // is expected to fail.
142 // Avoid data -> encode -> decode -> compare to data.
143 // Instead create expected encoding and compare to result from
144 // lzma_filter_flags_encode.
145 // Filter Flags in .xz are encoded as:
146 // |Filter ID (VLI)|Size of Properties (VLI)|Filter Properties|
147 #if defined(HAVE_ENCODERS) && defined(HAVE_DECODERS)
148 static void
149 verify_filter_flags_encode(lzma_filter *filter, bool should_encode)
151 uint32_t size = 0;
153 // First calculate the size of Filter Flags to know how much
154 // memory to allocate to hold the encoded Filter Flags
155 assert_lzma_ret(lzma_filter_flags_size(&size, filter), LZMA_OK);
156 uint8_t *encoded_out = tuktest_malloc(size * sizeof(uint8_t));
157 size_t out_pos = 0;
158 if (!should_encode) {
159 assert_false(lzma_filter_flags_encode(filter, encoded_out,
160 &out_pos, size) == LZMA_OK);
161 return;
164 // Next encode the Filter Flags for the provided filter
165 assert_lzma_ret(lzma_filter_flags_encode(filter, encoded_out,
166 &out_pos, size), LZMA_OK);
167 assert_uint_eq(size, out_pos);
169 // Next decode the VLI for the Filter ID and verify it matches
170 // the expected Filter ID
171 size_t filter_id_vli_size = 0;
172 lzma_vli filter_id = 0;
173 assert_lzma_ret(lzma_vli_decode(&filter_id, NULL, encoded_out,
174 &filter_id_vli_size, size), LZMA_OK);
175 assert_uint_eq(filter->id, filter_id);
177 // Next decode the Size of Properites and ensure it equals
178 // the expected size.
179 // Expected size should be:
180 // total filter flag length - size of filter id VLI + size of
181 // property size VLI
182 // Not verifying the contents of Filter Properties since
183 // that belongs in a different test
184 size_t size_of_properties_vli_size = 0;
185 lzma_vli size_of_properties = 0;
186 assert_lzma_ret(lzma_vli_decode(&size_of_properties, NULL,
187 encoded_out + filter_id_vli_size,
188 &size_of_properties_vli_size, size), LZMA_OK);
189 assert_uint_eq(size - (size_of_properties_vli_size +
190 filter_id_vli_size), size_of_properties);
192 #endif
195 static void
196 test_lzma_filter_flags_encode(void)
198 #if !defined(HAVE_ENCODERS) || !defined(HAVE_DECODERS)
199 assert_skip("Encoder or decoder support disabled");
200 #else
201 // No test for LZMA1 since the .xz format does not support LZMA1
202 // and so the flags cannot be encoded for that filter
203 if (lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA2)) {
204 // Test with NULL options that should fail
205 lzma_options_lzma *options = lzma2_filter.options;
206 lzma2_filter.options = NULL;
207 verify_filter_flags_encode(&lzma2_filter, false);
209 // Place options back in the filter, and test should pass
210 lzma2_filter.options = options;
211 verify_filter_flags_encode(&lzma2_filter, true);
214 // NOTE: Many BCJ filters require that start_offset is a multiple
215 // of some power of two. The Filter Flags encoder and decoder don't
216 // completely validate the options and thus 257 passes the tests
217 // with all BCJ filters. It would be caught when initializing
218 // a filter chain encoder or decoder.
219 lzma_options_bcj bcj_options = {
220 .start_offset = 257
223 const uint32_t bcj_array_size = ARRAY_SIZE(bcj_filters_encoders);
224 for (uint32_t i = 0; i < bcj_array_size; i++) {
225 // NULL options should pass for bcj filters
226 verify_filter_flags_encode(&bcj_filters_encoders[i], true);
227 lzma_filter bcj_with_options = {
228 bcj_filters_encoders[i].id, &bcj_options };
229 verify_filter_flags_encode(&bcj_with_options, true);
232 if (lzma_filter_encoder_is_supported(LZMA_FILTER_DELTA)) {
233 lzma_options_delta delta_opts_below_min = {
234 .type = LZMA_DELTA_TYPE_BYTE,
235 .dist = LZMA_DELTA_DIST_MIN - 1
238 lzma_options_delta delta_opts_above_max = {
239 .type = LZMA_DELTA_TYPE_BYTE,
240 .dist = LZMA_DELTA_DIST_MAX + 1
243 verify_filter_flags_encode(&delta_filter, true);
245 lzma_filter delta_filter_bad_options = {
246 LZMA_FILTER_DELTA, &delta_opts_below_min };
248 // Next test error case using minimum - 1 delta distance
249 verify_filter_flags_encode(&delta_filter_bad_options, false);
251 // Next test error case using maximum + 1 delta distance
252 delta_filter_bad_options.options = &delta_opts_above_max;
253 verify_filter_flags_encode(&delta_filter_bad_options, false);
255 // Next test NULL case
256 delta_filter_bad_options.options = NULL;
257 verify_filter_flags_encode(&delta_filter_bad_options, false);
260 // Test expected failing cases
261 lzma_filter bad_filter = { LZMA_FILTER_RESERVED_START, NULL };
262 size_t out_pos = 0;
263 size_t out_size = LZMA_BLOCK_HEADER_SIZE_MAX;
264 uint8_t out[LZMA_BLOCK_HEADER_SIZE_MAX];
267 // Filter ID outside of valid range
268 assert_lzma_ret(lzma_filter_flags_encode(&bad_filter, out, &out_pos,
269 out_size), LZMA_PROG_ERROR);
270 out_pos = 0;
271 bad_filter.id = LZMA_VLI_MAX + 1;
272 assert_lzma_ret(lzma_filter_flags_encode(&bad_filter, out, &out_pos,
273 out_size), LZMA_PROG_ERROR);
274 out_pos = 0;
276 // Invalid Filter ID
277 bad_filter.id = 2;
278 assert_lzma_ret(lzma_filter_flags_encode(&bad_filter, out, &out_pos,
279 out_size), LZMA_OPTIONS_ERROR);
280 out_pos = 0;
282 // Out size too small
283 if (lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA2)) {
284 uint32_t bad_size = 0;
286 // First test with 0 output size
287 assert_lzma_ret(lzma_filter_flags_encode(
288 &lzma2_filter, out, &out_pos, 0),
289 LZMA_PROG_ERROR);
291 // Next calculate the size needed to encode and
292 // use less than that
293 assert_lzma_ret(lzma_filter_flags_size(&bad_size,
294 &lzma2_filter), LZMA_OK);
296 assert_lzma_ret(lzma_filter_flags_encode(
297 &lzma2_filter, out, &out_pos,
298 bad_size - 1), LZMA_PROG_ERROR);
299 out_pos = 0;
302 // Invalid options
303 if (lzma_filter_encoder_is_supported(LZMA_FILTER_DELTA)) {
304 bad_filter.id = LZMA_FILTER_DELTA;
306 // First test with NULL options
307 assert_lzma_ret(lzma_filter_flags_encode(&bad_filter, out,
308 &out_pos, out_size), LZMA_PROG_ERROR);
309 out_pos = 0;
311 // Next test with invalid options
312 lzma_options_delta bad_options = {
313 .dist = LZMA_DELTA_DIST_MAX + 1,
314 .type = LZMA_DELTA_TYPE_BYTE
316 bad_filter.options = &bad_options;
318 assert_lzma_ret(lzma_filter_flags_encode(&bad_filter, out,
319 &out_pos, out_size), LZMA_PROG_ERROR);
321 #endif
325 // Helper function for test_lzma_filter_flags_decode.
326 // Encodes the filter_in without using lzma_filter_flags_encode.
327 // Leaves the specific assertions of filter_out options to the caller
328 // because it is agnostic to the type of options used in the call
329 #if defined(HAVE_ENCODERS) && defined(HAVE_DECODERS)
330 static void
331 verify_filter_flags_decode(lzma_filter *filter_in, lzma_filter *filter_out)
333 uint32_t total_size = 0;
335 assert_lzma_ret(lzma_filter_flags_size(&total_size, filter_in),
336 LZMA_OK);
337 assert_uint(total_size, >, 0);
338 uint8_t *filter_flag_buffer = tuktest_malloc(total_size);
340 uint32_t properties_size = 0;
341 size_t out_pos = 0;
342 size_t in_pos = 0;
343 assert_lzma_ret(lzma_properties_size(&properties_size, filter_in),
344 LZMA_OK);
345 assert_lzma_ret(lzma_vli_encode(filter_in->id, NULL,
346 filter_flag_buffer, &out_pos, total_size), LZMA_OK);
347 assert_lzma_ret(lzma_vli_encode(properties_size, NULL,
348 filter_flag_buffer, &out_pos, total_size),
349 LZMA_OK);
350 assert_lzma_ret(lzma_properties_encode(filter_in,
351 filter_flag_buffer + out_pos), LZMA_OK);
352 assert_lzma_ret(lzma_filter_flags_decode(filter_out, NULL,
353 filter_flag_buffer, &in_pos, total_size),
354 LZMA_OK);
355 assert_uint_eq(filter_in->id, filter_out->id);
357 #endif
360 static void
361 test_lzma_filter_flags_decode(void)
363 #if !defined(HAVE_ENCODERS) || !defined(HAVE_DECODERS)
364 assert_skip("Encoder or decoder support disabled");
365 #else
366 // For each filter, only run the decoder test if both the encoder
367 // and decoder are enabled. This is because verify_filter_flags_decode
368 // uses lzma_filter_flags_size which requires the encoder.
369 if (lzma_filter_decoder_is_supported(LZMA_FILTER_LZMA2) &&
370 lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA2)) {
371 lzma_filter lzma2_decoded = { LZMA_FILTER_LZMA2, NULL };
373 verify_filter_flags_decode(&lzma2_filter, &lzma2_decoded);
375 lzma_options_lzma *expected = lzma2_filter.options;
376 lzma_options_lzma *decoded = lzma2_decoded.options;
378 // Only the dictionary size is encoded and decoded
379 // so only compare those
380 assert_uint_eq(decoded->dict_size, expected->dict_size);
382 // The decoded options must be freed by the caller
383 free(decoded);
386 const uint32_t bcj_array_size = ARRAY_SIZE(bcj_filters_decoders);
387 for (uint32_t i = 0; i < bcj_array_size; i++) {
388 if (lzma_filter_encoder_is_supported(
389 bcj_filters_decoders[i].id)) {
390 lzma_filter bcj_decoded = {
391 bcj_filters_decoders[i].id, NULL };
393 lzma_filter bcj_encoded = {
394 bcj_filters_decoders[i].id, NULL };
396 // First test without options
397 verify_filter_flags_decode(&bcj_encoded,
398 &bcj_decoded);
399 assert_true(bcj_decoded.options == NULL);
401 // Next test with offset
402 lzma_options_bcj options = {
403 .start_offset = 257
406 bcj_encoded.options = &options;
407 verify_filter_flags_decode(&bcj_encoded,
408 &bcj_decoded);
409 lzma_options_bcj *decoded_opts = bcj_decoded.options;
410 assert_uint_eq(decoded_opts->start_offset,
411 options.start_offset);
412 free(decoded_opts);
416 if (lzma_filter_decoder_is_supported(LZMA_FILTER_DELTA) &&
417 lzma_filter_encoder_is_supported(LZMA_FILTER_DELTA)) {
418 lzma_filter delta_decoded = { LZMA_FILTER_DELTA, NULL };
420 verify_filter_flags_decode(&delta_filter, &delta_decoded);
421 lzma_options_delta *expected = delta_filter.options;
422 lzma_options_delta *decoded = delta_decoded.options;
423 assert_uint_eq(expected->dist, decoded->dist);
424 assert_uint_eq(expected->type, decoded->type);
426 free(decoded);
429 // Test expected failing cases
430 uint8_t bad_encoded_filter[LZMA_BLOCK_HEADER_SIZE_MAX];
431 lzma_filter bad_filter;
433 // Filter ID outside of valid range
434 lzma_vli bad_filter_id = LZMA_FILTER_RESERVED_START;
435 size_t bad_encoded_out_pos = 0;
436 size_t in_pos = 0;
438 assert_lzma_ret(lzma_vli_encode(bad_filter_id, NULL,
439 bad_encoded_filter, &bad_encoded_out_pos,
440 LZMA_BLOCK_HEADER_SIZE_MAX), LZMA_OK);
442 assert_lzma_ret(lzma_filter_flags_decode(&bad_filter, NULL,
443 bad_encoded_filter, &in_pos,
444 LZMA_BLOCK_HEADER_SIZE_MAX), LZMA_DATA_ERROR);
446 bad_encoded_out_pos = 0;
447 in_pos = 0;
449 // Invalid Filter ID
450 bad_filter_id = 2;
451 bad_encoded_out_pos = 0;
452 in_pos = 0;
454 assert_lzma_ret(lzma_vli_encode(bad_filter_id, NULL,
455 bad_encoded_filter, &bad_encoded_out_pos,
456 LZMA_BLOCK_HEADER_SIZE_MAX), LZMA_OK);
458 // Next encode Size of Properties with the value of 0
459 assert_lzma_ret(lzma_vli_encode(0, NULL,
460 bad_encoded_filter, &bad_encoded_out_pos,
461 LZMA_BLOCK_HEADER_SIZE_MAX), LZMA_OK);
463 // Decode should fail on bad Filter ID
464 assert_lzma_ret(lzma_filter_flags_decode(&bad_filter, NULL,
465 bad_encoded_filter, &in_pos,
466 LZMA_BLOCK_HEADER_SIZE_MAX), LZMA_OPTIONS_ERROR);
467 bad_encoded_out_pos = 0;
468 in_pos = 0;
470 // Outsize too small
471 // Encode the LZMA2 filter normally, but then set
472 // the out size when decoding as too small
473 if (lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA2) &&
474 lzma_filter_decoder_is_supported(LZMA_FILTER_LZMA2)) {
475 uint32_t filter_flag_size = 0;
476 assert_lzma_ret(lzma_filter_flags_size(&filter_flag_size,
477 &lzma2_filter), LZMA_OK);
479 assert_lzma_ret(lzma_filter_flags_encode(&lzma2_filter,
480 bad_encoded_filter, &bad_encoded_out_pos,
481 LZMA_BLOCK_HEADER_SIZE_MAX), LZMA_OK);
483 assert_lzma_ret(lzma_filter_flags_decode(&bad_filter, NULL,
484 bad_encoded_filter, &in_pos,
485 filter_flag_size - 1), LZMA_DATA_ERROR);
487 #endif
491 extern int
492 main(int argc, char **argv)
494 tuktest_start(argc, argv);
496 #ifdef HAVE_ENCODERS
497 // Only init filter options if encoder is supported because decoder
498 // tests requires encoder support, so the decoder tests will only
499 // run if for a given filter both the encoder and decoder are enabled.
500 if (lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA1)) {
501 lzma_options_lzma *options = tuktest_malloc(
502 sizeof(lzma_options_lzma));
503 lzma_lzma_preset(options, LZMA_PRESET_DEFAULT);
504 lzma1_filter.options = options;
507 if (lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA2)) {
508 lzma_options_lzma *options = tuktest_malloc(
509 sizeof(lzma_options_lzma));
510 lzma_lzma_preset(options, LZMA_PRESET_DEFAULT);
511 lzma2_filter.options = options;
514 if (lzma_filter_encoder_is_supported(LZMA_FILTER_DELTA)) {
515 lzma_options_delta *options = tuktest_malloc(
516 sizeof(lzma_options_delta));
517 options->dist = LZMA_DELTA_DIST_MIN;
518 options->type = LZMA_DELTA_TYPE_BYTE;
519 delta_filter.options = options;
521 #endif
523 tuktest_run(test_lzma_filter_flags_size);
524 tuktest_run(test_lzma_filter_flags_encode);
525 tuktest_run(test_lzma_filter_flags_decode);
526 return tuktest_end();