1 ///////////////////////////////////////////////////////////////////////////////
3 /// \file test_filter_flags.c
4 /// \brief Tests Filter Flags coders
9 // This file has been put into the public domain.
10 // You can do whatever you want with this file.
12 ///////////////////////////////////////////////////////////////////////////////
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
},
33 #ifdef HAVE_ENCODER_POWERPC
34 { LZMA_FILTER_POWERPC
, NULL
},
36 #ifdef HAVE_ENCODER_IA64
37 { LZMA_FILTER_IA64
, NULL
},
39 #ifdef HAVE_ENCODER_ARM
40 { LZMA_FILTER_ARM
, NULL
},
42 #ifdef HAVE_ENCODER_ARM64
43 { LZMA_FILTER_ARM64
, NULL
},
45 #ifdef HAVE_ENCODER_ARMTHUMB
46 { LZMA_FILTER_ARMTHUMB
, NULL
},
48 #ifdef HAVE_ENCODER_SPARC
49 { LZMA_FILTER_SPARC
, NULL
},
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.
58 static lzma_filter bcj_filters_decoders
[] = {
59 #ifdef HAVE_DECODER_X86
60 { LZMA_FILTER_X86
, NULL
},
62 #ifdef HAVE_DECODER_POWERPC
63 { LZMA_FILTER_POWERPC
, NULL
},
65 #ifdef HAVE_DECODER_IA64
66 { LZMA_FILTER_IA64
, NULL
},
68 #ifdef HAVE_DECODER_ARM
69 { LZMA_FILTER_ARM
, NULL
},
71 #ifdef HAVE_DECODER_ARM64
72 { LZMA_FILTER_ARM64
, NULL
},
74 #ifdef HAVE_DECODER_ARMTHUMB
75 { LZMA_FILTER_ARMTHUMB
, NULL
},
77 #ifdef HAVE_DECODER_SPARC
78 { LZMA_FILTER_SPARC
, NULL
},
86 test_lzma_filter_flags_size(void)
89 assert_skip("Encoder support disabled");
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
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
),
129 bad_filter
.id
= LZMA_VLI_MAX
;
130 assert_lzma_ret(lzma_filter_flags_size(&size
, &bad_filter
),
132 bad_filter
.id
= LZMA_FILTER_RESERVED_START
;
133 assert_lzma_ret(lzma_filter_flags_size(&size
, &bad_filter
),
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)
149 verify_filter_flags_encode(lzma_filter
*filter
, bool should_encode
)
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));
158 if (!should_encode
) {
159 assert_false(lzma_filter_flags_encode(filter
, encoded_out
,
160 &out_pos
, size
) == LZMA_OK
);
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
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
);
196 test_lzma_filter_flags_encode(void)
198 #if !defined(HAVE_ENCODERS) || !defined(HAVE_DECODERS)
199 assert_skip("Encoder or decoder support disabled");
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
= {
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
};
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
);
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
);
278 assert_lzma_ret(lzma_filter_flags_encode(&bad_filter
, out
, &out_pos
,
279 out_size
), LZMA_OPTIONS_ERROR
);
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),
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
);
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
);
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
);
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)
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
),
337 assert_uint(total_size
, >, 0);
338 uint8_t *filter_flag_buffer
= tuktest_malloc(total_size
);
340 uint32_t properties_size
= 0;
343 assert_lzma_ret(lzma_properties_size(&properties_size
, filter_in
),
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
),
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
),
355 assert_uint_eq(filter_in
->id
, filter_out
->id
);
361 test_lzma_filter_flags_decode(void)
363 #if !defined(HAVE_ENCODERS) || !defined(HAVE_DECODERS)
364 assert_skip("Encoder or decoder support disabled");
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
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
,
399 assert_true(bcj_decoded
.options
== NULL
);
401 // Next test with offset
402 lzma_options_bcj options
= {
406 bcj_encoded
.options
= &options
;
407 verify_filter_flags_decode(&bcj_encoded
,
409 lzma_options_bcj
*decoded_opts
= bcj_decoded
.options
;
410 assert_uint_eq(decoded_opts
->start_offset
,
411 options
.start_offset
);
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
);
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;
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;
451 bad_encoded_out_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;
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
);
492 main(int argc
, char **argv
)
494 tuktest_start(argc
, argv
);
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
;
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();