CMake: Keep existing options in LIBS when adding -lrt
[xz/debian.git] / tests / test_filter_flags.c
blob9dfc16e69b75003a7fb40dccaec980d61284c656
1 // SPDX-License-Identifier: 0BSD
3 ///////////////////////////////////////////////////////////////////////////////
4 //
5 /// \file test_filter_flags.c
6 /// \brief Tests Filter Flags coders
7 //
8 // Authors: Jia Tan
9 // Lasse Collin
11 ///////////////////////////////////////////////////////////////////////////////
13 #include "tests.h"
15 // FIXME: This is from src/liblzma/common/common.h but it cannot be
16 // included here. This constant is needed in only a few files, perhaps
17 // move it to some other internal header or create a new one?
18 #define LZMA_FILTER_RESERVED_START (LZMA_VLI_C(1) << 62)
21 #if defined(HAVE_ENCODERS)
22 // No tests are run without encoders, so init the global filters
23 // only when the encoders are enabled.
24 static lzma_filter lzma1_filter = { LZMA_FILTER_LZMA1, NULL };
25 static lzma_filter lzma2_filter = { LZMA_FILTER_LZMA2, NULL };
26 static lzma_filter delta_filter = { LZMA_FILTER_DELTA, NULL };
28 static lzma_filter bcj_filters_encoders[] = {
29 #ifdef HAVE_ENCODER_X86
30 { LZMA_FILTER_X86, NULL },
31 #endif
32 #ifdef HAVE_ENCODER_POWERPC
33 { LZMA_FILTER_POWERPC, NULL },
34 #endif
35 #ifdef HAVE_ENCODER_IA64
36 { LZMA_FILTER_IA64, NULL },
37 #endif
38 #ifdef HAVE_ENCODER_ARM
39 { LZMA_FILTER_ARM, NULL },
40 #endif
41 #ifdef HAVE_ENCODER_ARM64
42 { LZMA_FILTER_ARM64, NULL },
43 #endif
44 #ifdef HAVE_ENCODER_ARMTHUMB
45 { LZMA_FILTER_ARMTHUMB, NULL },
46 #endif
47 #ifdef HAVE_ENCODER_SPARC
48 { LZMA_FILTER_SPARC, NULL },
49 #endif
50 #ifdef HAVE_ENCODER_RISCV
51 { LZMA_FILTER_RISCV, NULL },
52 #endif
53 { LZMA_VLI_UNKNOWN, NULL }
56 // HAVE_ENCODERS ifdef not terminated here because decoders are
57 // only used if encoders are, but encoders can still be used
58 // even if decoders are not.
60 #ifdef HAVE_DECODERS
61 static lzma_filter bcj_filters_decoders[] = {
62 #ifdef HAVE_DECODER_X86
63 { LZMA_FILTER_X86, NULL },
64 #endif
65 #ifdef HAVE_DECODER_POWERPC
66 { LZMA_FILTER_POWERPC, NULL },
67 #endif
68 #ifdef HAVE_DECODER_IA64
69 { LZMA_FILTER_IA64, NULL },
70 #endif
71 #ifdef HAVE_DECODER_ARM
72 { LZMA_FILTER_ARM, NULL },
73 #endif
74 #ifdef HAVE_DECODER_ARM64
75 { LZMA_FILTER_ARM64, NULL },
76 #endif
77 #ifdef HAVE_DECODER_ARMTHUMB
78 { LZMA_FILTER_ARMTHUMB, NULL },
79 #endif
80 #ifdef HAVE_DECODER_SPARC
81 { LZMA_FILTER_SPARC, NULL },
82 #endif
83 #ifdef HAVE_DECODER_RISCV
84 { LZMA_FILTER_RISCV, NULL },
85 #endif
86 { LZMA_VLI_UNKNOWN, NULL }
88 #endif
89 #endif
92 static void
93 test_lzma_filter_flags_size(void)
95 #ifndef HAVE_ENCODERS
96 assert_skip("Encoder support disabled");
97 #else
98 // For each supported filter, test that the size can be calculated
99 // and that the size calculated is reasonable. A reasonable size
100 // must be greater than 0, but less than the maximum size for the
101 // block header.
102 uint32_t size = 0;
103 if (lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA1)) {
104 // LZMA1 isn't supported in .xz so we get LZMA_PROG_ERROR.
105 assert_lzma_ret(lzma_filter_flags_size(&size,
106 &lzma1_filter), LZMA_PROG_ERROR);
109 if (lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA2)) {
110 assert_lzma_ret(lzma_filter_flags_size(&size,
111 &lzma2_filter), LZMA_OK);
112 assert_true(size != 0 && size < LZMA_BLOCK_HEADER_SIZE_MAX);
115 for (size_t i = 0; bcj_filters_encoders[i].id != LZMA_VLI_UNKNOWN;
116 ++i) {
117 assert_lzma_ret(lzma_filter_flags_size(&size,
118 &bcj_filters_encoders[i]), LZMA_OK);
119 assert_true(size != 0 && size < LZMA_BLOCK_HEADER_SIZE_MAX);
122 if (lzma_filter_encoder_is_supported(LZMA_FILTER_DELTA)) {
123 assert_lzma_ret(lzma_filter_flags_size(&size,
124 &delta_filter), LZMA_OK);
125 assert_true(size != 0 && size < LZMA_BLOCK_HEADER_SIZE_MAX);
128 // Test invalid Filter IDs
129 lzma_filter bad_filter = { 2, NULL };
131 assert_lzma_ret(lzma_filter_flags_size(&size, &bad_filter),
132 LZMA_OPTIONS_ERROR);
133 bad_filter.id = LZMA_VLI_MAX;
134 assert_lzma_ret(lzma_filter_flags_size(&size, &bad_filter),
135 LZMA_PROG_ERROR);
136 bad_filter.id = LZMA_FILTER_RESERVED_START;
137 assert_lzma_ret(lzma_filter_flags_size(&size, &bad_filter),
138 LZMA_PROG_ERROR);
139 #endif
143 // Helper function for test_lzma_filter_flags_encode.
144 // The should_encode parameter represents if the encoding operation
145 // is expected to fail.
146 // Avoid data -> encode -> decode -> compare to data.
147 // Instead create expected encoding and compare to result from
148 // lzma_filter_flags_encode.
149 // Filter Flags in .xz are encoded as:
150 // |Filter ID (VLI)|Size of Properties (VLI)|Filter Properties|
151 #if defined(HAVE_ENCODERS) && defined(HAVE_DECODERS)
152 static void
153 verify_filter_flags_encode(lzma_filter *filter, bool should_encode)
155 uint32_t size = 0;
157 // First calculate the size of Filter Flags to know how much
158 // memory to allocate to hold the encoded Filter Flags
159 assert_lzma_ret(lzma_filter_flags_size(&size, filter), LZMA_OK);
160 uint8_t *encoded_out = tuktest_malloc(size);
161 size_t out_pos = 0;
162 if (!should_encode) {
163 assert_false(lzma_filter_flags_encode(filter, encoded_out,
164 &out_pos, size) == LZMA_OK);
165 return;
168 // Next encode the Filter Flags for the provided filter
169 assert_lzma_ret(lzma_filter_flags_encode(filter, encoded_out,
170 &out_pos, size), LZMA_OK);
171 assert_uint_eq(size, out_pos);
173 // Next decode the VLI for the Filter ID and verify it matches
174 // the expected Filter ID
175 size_t filter_id_vli_size = 0;
176 lzma_vli filter_id = 0;
177 assert_lzma_ret(lzma_vli_decode(&filter_id, NULL, encoded_out,
178 &filter_id_vli_size, size), LZMA_OK);
179 assert_uint_eq(filter->id, filter_id);
181 // Next decode the Size of Properties and ensure it equals
182 // the expected size.
183 // Expected size should be:
184 // total filter flag length - size of filter id VLI + size of
185 // property size VLI
186 // Not verifying the contents of Filter Properties since
187 // that belongs in a different test
188 size_t size_of_properties_vli_size = 0;
189 lzma_vli size_of_properties = 0;
190 assert_lzma_ret(lzma_vli_decode(&size_of_properties, NULL,
191 encoded_out + filter_id_vli_size,
192 &size_of_properties_vli_size, size), LZMA_OK);
193 assert_uint_eq(size - (size_of_properties_vli_size +
194 filter_id_vli_size), size_of_properties);
196 #endif
199 static void
200 test_lzma_filter_flags_encode(void)
202 #if !defined(HAVE_ENCODERS) || !defined(HAVE_DECODERS)
203 assert_skip("Encoder or decoder support disabled");
204 #else
205 // No test for LZMA1 since the .xz format does not support LZMA1
206 // and so the flags cannot be encoded for that filter
207 if (lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA2)) {
208 // Test with NULL options that should fail
209 lzma_options_lzma *options = lzma2_filter.options;
210 lzma2_filter.options = NULL;
211 verify_filter_flags_encode(&lzma2_filter, false);
213 // Place options back in the filter, and test should pass
214 lzma2_filter.options = options;
215 verify_filter_flags_encode(&lzma2_filter, true);
218 // NOTE: Many BCJ filters require that start_offset is a multiple
219 // of some power of two. The Filter Flags encoder and decoder don't
220 // completely validate the options and thus 257 passes the tests
221 // with all BCJ filters. It would be caught when initializing
222 // a filter chain encoder or decoder.
223 lzma_options_bcj bcj_options = {
224 .start_offset = 257
227 for (size_t i = 0; bcj_filters_encoders[i].id != LZMA_VLI_UNKNOWN;
228 ++i) {
229 // NULL options should pass for bcj filters
230 verify_filter_flags_encode(&bcj_filters_encoders[i], true);
231 lzma_filter bcj_with_options = {
232 bcj_filters_encoders[i].id, &bcj_options };
233 verify_filter_flags_encode(&bcj_with_options, true);
236 if (lzma_filter_encoder_is_supported(LZMA_FILTER_DELTA)) {
237 lzma_options_delta delta_opts_below_min = {
238 .type = LZMA_DELTA_TYPE_BYTE,
239 .dist = LZMA_DELTA_DIST_MIN - 1
242 lzma_options_delta delta_opts_above_max = {
243 .type = LZMA_DELTA_TYPE_BYTE,
244 .dist = LZMA_DELTA_DIST_MAX + 1
247 verify_filter_flags_encode(&delta_filter, true);
249 lzma_filter delta_filter_bad_options = {
250 LZMA_FILTER_DELTA, &delta_opts_below_min };
252 // Next test error case using minimum - 1 delta distance
253 verify_filter_flags_encode(&delta_filter_bad_options, false);
255 // Next test error case using maximum + 1 delta distance
256 delta_filter_bad_options.options = &delta_opts_above_max;
257 verify_filter_flags_encode(&delta_filter_bad_options, false);
259 // Next test NULL case
260 delta_filter_bad_options.options = NULL;
261 verify_filter_flags_encode(&delta_filter_bad_options, false);
264 // Test expected failing cases
265 lzma_filter bad_filter = { LZMA_FILTER_RESERVED_START, NULL };
266 size_t out_pos = 0;
267 size_t out_size = LZMA_BLOCK_HEADER_SIZE_MAX;
268 uint8_t out[LZMA_BLOCK_HEADER_SIZE_MAX];
270 // Filter ID outside of valid range
271 assert_lzma_ret(lzma_filter_flags_encode(&bad_filter, out, &out_pos,
272 out_size), LZMA_PROG_ERROR);
273 out_pos = 0;
274 bad_filter.id = LZMA_VLI_MAX + 1;
275 assert_lzma_ret(lzma_filter_flags_encode(&bad_filter, out, &out_pos,
276 out_size), LZMA_PROG_ERROR);
277 out_pos = 0;
279 // Invalid Filter ID
280 bad_filter.id = 2;
281 assert_lzma_ret(lzma_filter_flags_encode(&bad_filter, out, &out_pos,
282 out_size), LZMA_OPTIONS_ERROR);
283 out_pos = 0;
285 // Out size too small
286 if (lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA2)) {
287 uint32_t bad_size = 0;
289 // First test with 0 output size
290 assert_lzma_ret(lzma_filter_flags_encode(
291 &lzma2_filter, out, &out_pos, 0),
292 LZMA_PROG_ERROR);
294 // Next calculate the size needed to encode and
295 // use less than that
296 assert_lzma_ret(lzma_filter_flags_size(&bad_size,
297 &lzma2_filter), LZMA_OK);
299 assert_lzma_ret(lzma_filter_flags_encode(
300 &lzma2_filter, out, &out_pos,
301 bad_size - 1), LZMA_PROG_ERROR);
302 out_pos = 0;
305 // Invalid options
306 if (lzma_filter_encoder_is_supported(LZMA_FILTER_DELTA)) {
307 bad_filter.id = LZMA_FILTER_DELTA;
309 // First test with NULL options
310 assert_lzma_ret(lzma_filter_flags_encode(&bad_filter, out,
311 &out_pos, out_size), LZMA_PROG_ERROR);
312 out_pos = 0;
314 // Next test with invalid options
315 lzma_options_delta bad_options = {
316 .dist = LZMA_DELTA_DIST_MAX + 1,
317 .type = LZMA_DELTA_TYPE_BYTE
319 bad_filter.options = &bad_options;
321 assert_lzma_ret(lzma_filter_flags_encode(&bad_filter, out,
322 &out_pos, out_size), LZMA_PROG_ERROR);
324 #endif
328 // Helper function for test_lzma_filter_flags_decode.
329 // Encodes the filter_in without using lzma_filter_flags_encode.
330 // Leaves the specific assertions of filter_out options to the caller
331 // because it is agnostic to the type of options used in the call
332 #if defined(HAVE_ENCODERS) && defined(HAVE_DECODERS)
333 static void
334 verify_filter_flags_decode(const lzma_filter *filter_in,
335 lzma_filter *filter_out)
337 uint32_t total_size = 0;
339 assert_lzma_ret(lzma_filter_flags_size(&total_size, filter_in),
340 LZMA_OK);
341 assert_uint(total_size, >, 0);
342 uint8_t *filter_flag_buffer = tuktest_malloc(total_size);
344 uint32_t properties_size = 0;
345 size_t out_pos = 0;
346 size_t in_pos = 0;
347 assert_lzma_ret(lzma_properties_size(&properties_size, filter_in),
348 LZMA_OK);
349 assert_lzma_ret(lzma_vli_encode(filter_in->id, NULL,
350 filter_flag_buffer, &out_pos, total_size), LZMA_OK);
351 assert_lzma_ret(lzma_vli_encode(properties_size, NULL,
352 filter_flag_buffer, &out_pos, total_size),
353 LZMA_OK);
354 assert_lzma_ret(lzma_properties_encode(filter_in,
355 filter_flag_buffer + out_pos), LZMA_OK);
356 assert_lzma_ret(lzma_filter_flags_decode(filter_out, NULL,
357 filter_flag_buffer, &in_pos, total_size),
358 LZMA_OK);
359 assert_uint_eq(filter_in->id, filter_out->id);
361 #endif
364 static void
365 test_lzma_filter_flags_decode(void)
367 #if !defined(HAVE_ENCODERS) || !defined(HAVE_DECODERS)
368 assert_skip("Encoder or decoder support disabled");
369 #else
370 // For each filter, only run the decoder test if both the encoder
371 // and decoder are enabled. This is because verify_filter_flags_decode
372 // uses lzma_filter_flags_size which requires the encoder.
373 if (lzma_filter_decoder_is_supported(LZMA_FILTER_LZMA2) &&
374 lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA2)) {
375 lzma_filter lzma2_decoded = { LZMA_FILTER_LZMA2, NULL };
377 verify_filter_flags_decode(&lzma2_filter, &lzma2_decoded);
379 lzma_options_lzma *expected = lzma2_filter.options;
380 lzma_options_lzma *decoded = lzma2_decoded.options;
382 // Only the dictionary size is encoded and decoded
383 // so only compare those
384 assert_uint_eq(decoded->dict_size, expected->dict_size);
386 // The decoded options must be freed by the caller
387 free(decoded);
390 for (size_t i = 0; bcj_filters_decoders[i].id != LZMA_VLI_UNKNOWN;
391 ++i) {
392 if (lzma_filter_encoder_is_supported(
393 bcj_filters_decoders[i].id)) {
394 lzma_filter bcj_decoded = {
395 bcj_filters_decoders[i].id, NULL };
397 lzma_filter bcj_encoded = {
398 bcj_filters_decoders[i].id, NULL };
400 // First test without options
401 verify_filter_flags_decode(&bcj_encoded,
402 &bcj_decoded);
403 assert_true(bcj_decoded.options == NULL);
405 // Next test with start_offset.
407 // NOTE: The encoder and decoder don't verify if
408 // the start_offset is valid for the filter. Only
409 // the encoder or decoder initialization does.
410 lzma_options_bcj options = {
411 .start_offset = 257
414 bcj_encoded.options = &options;
415 verify_filter_flags_decode(&bcj_encoded,
416 &bcj_decoded);
417 lzma_options_bcj *decoded_opts = bcj_decoded.options;
418 assert_uint_eq(decoded_opts->start_offset,
419 options.start_offset);
420 free(decoded_opts);
424 if (lzma_filter_decoder_is_supported(LZMA_FILTER_DELTA) &&
425 lzma_filter_encoder_is_supported(LZMA_FILTER_DELTA)) {
426 lzma_filter delta_decoded = { LZMA_FILTER_DELTA, NULL };
428 verify_filter_flags_decode(&delta_filter, &delta_decoded);
429 lzma_options_delta *expected = delta_filter.options;
430 lzma_options_delta *decoded = delta_decoded.options;
431 assert_uint_eq(expected->dist, decoded->dist);
432 assert_uint_eq(expected->type, decoded->type);
434 free(decoded);
437 // Test expected failing cases
438 uint8_t bad_encoded_filter[LZMA_BLOCK_HEADER_SIZE_MAX];
439 lzma_filter bad_filter;
441 // Filter ID outside of valid range
442 lzma_vli bad_filter_id = LZMA_FILTER_RESERVED_START;
443 size_t bad_encoded_out_pos = 0;
444 size_t in_pos = 0;
446 assert_lzma_ret(lzma_vli_encode(bad_filter_id, NULL,
447 bad_encoded_filter, &bad_encoded_out_pos,
448 LZMA_BLOCK_HEADER_SIZE_MAX), LZMA_OK);
450 assert_lzma_ret(lzma_filter_flags_decode(&bad_filter, NULL,
451 bad_encoded_filter, &in_pos,
452 LZMA_BLOCK_HEADER_SIZE_MAX), LZMA_DATA_ERROR);
454 bad_encoded_out_pos = 0;
455 in_pos = 0;
457 // Invalid Filter ID
458 bad_filter_id = 2;
459 bad_encoded_out_pos = 0;
460 in_pos = 0;
462 assert_lzma_ret(lzma_vli_encode(bad_filter_id, NULL,
463 bad_encoded_filter, &bad_encoded_out_pos,
464 LZMA_BLOCK_HEADER_SIZE_MAX), LZMA_OK);
466 // Next encode Size of Properties with the value of 0
467 assert_lzma_ret(lzma_vli_encode(0, NULL,
468 bad_encoded_filter, &bad_encoded_out_pos,
469 LZMA_BLOCK_HEADER_SIZE_MAX), LZMA_OK);
471 // Decode should fail on bad Filter ID
472 assert_lzma_ret(lzma_filter_flags_decode(&bad_filter, NULL,
473 bad_encoded_filter, &in_pos,
474 LZMA_BLOCK_HEADER_SIZE_MAX), LZMA_OPTIONS_ERROR);
475 bad_encoded_out_pos = 0;
476 in_pos = 0;
478 // Outsize too small
479 // Encode the LZMA2 filter normally, but then set
480 // the out size when decoding as too small
481 if (lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA2) &&
482 lzma_filter_decoder_is_supported(LZMA_FILTER_LZMA2)) {
483 uint32_t filter_flag_size = 0;
484 assert_lzma_ret(lzma_filter_flags_size(&filter_flag_size,
485 &lzma2_filter), LZMA_OK);
487 assert_lzma_ret(lzma_filter_flags_encode(&lzma2_filter,
488 bad_encoded_filter, &bad_encoded_out_pos,
489 LZMA_BLOCK_HEADER_SIZE_MAX), LZMA_OK);
491 assert_lzma_ret(lzma_filter_flags_decode(&bad_filter, NULL,
492 bad_encoded_filter, &in_pos,
493 filter_flag_size - 1), LZMA_DATA_ERROR);
495 #endif
499 extern int
500 main(int argc, char **argv)
502 tuktest_start(argc, argv);
504 #ifdef HAVE_ENCODERS
505 // Only init filter options if encoder is supported because decoder
506 // tests requires encoder support, so the decoder tests will only
507 // run if for a given filter both the encoder and decoder are enabled.
508 if (lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA1)) {
509 lzma_options_lzma *options = tuktest_malloc(
510 sizeof(lzma_options_lzma));
511 lzma_lzma_preset(options, LZMA_PRESET_DEFAULT);
512 lzma1_filter.options = options;
515 if (lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA2)) {
516 lzma_options_lzma *options = tuktest_malloc(
517 sizeof(lzma_options_lzma));
518 lzma_lzma_preset(options, LZMA_PRESET_DEFAULT);
519 lzma2_filter.options = options;
522 if (lzma_filter_encoder_is_supported(LZMA_FILTER_DELTA)) {
523 lzma_options_delta *options = tuktest_malloc(
524 sizeof(lzma_options_delta));
525 options->dist = LZMA_DELTA_DIST_MIN;
526 options->type = LZMA_DELTA_TYPE_BYTE;
527 delta_filter.options = options;
529 #endif
531 tuktest_run(test_lzma_filter_flags_size);
532 tuktest_run(test_lzma_filter_flags_encode);
533 tuktest_run(test_lzma_filter_flags_decode);
534 return tuktest_end();