diff --git a/tests/test_filter_flags.c b/tests/test_filter_flags.c index ccd9ae98..4ddffa7f 100644 --- a/tests/test_filter_flags.c +++ b/tests/test_filter_flags.c @@ -3,7 +3,8 @@ /// \file test_filter_flags.c /// \brief Tests Filter Flags coders // -// Author: Lasse Collin +// Authors: Jia Tan +// Lasse Collin // // This file has been put into the public domain. // You can do whatever you want with this file. @@ -11,248 +12,506 @@ /////////////////////////////////////////////////////////////////////////////// #include "tests.h" +// Including the internal header file for access to the +// LZMA_FILTER_RESERVED_START macro +#include "common/common.h" -static uint8_t buffer[4096]; -static lzma_filter known_flags; -static lzma_filter decoded_flags; -static lzma_stream strm = LZMA_STREAM_INIT; +// Used to create filters and easily to set id and options +#define INIT_FILTER(_id, _options) {\ + .id = _id, \ + .options = _options \ +} -static bool -encode(uint32_t known_size) +#if defined(HAVE_ENCODERS) +// No tests are run without encoders, so init the global filters +// only when the encoders are enabled. +static lzma_filter lzma1_filter = INIT_FILTER(LZMA_FILTER_LZMA1, NULL); +static lzma_filter lzma2_filter = INIT_FILTER(LZMA_FILTER_LZMA2, NULL); +static lzma_filter delta_filter = INIT_FILTER(LZMA_FILTER_DELTA, NULL); + +static lzma_filter bcj_filters_encoders[] = { +#ifdef HAVE_ENCODER_X86 + INIT_FILTER(LZMA_FILTER_X86, NULL), +#endif +#ifdef HAVE_ENCODER_POWERPC + INIT_FILTER(LZMA_FILTER_POWERPC, NULL), +#endif +#ifdef HAVE_ENCODER_IA64 + INIT_FILTER(LZMA_FILTER_IA64, NULL), +#endif +#ifdef HAVE_ENCODER_ARM + INIT_FILTER(LZMA_FILTER_ARM, NULL), +#endif +#ifdef HAVE_ENCODER_ARM64 + INIT_FILTER(LZMA_FILTER_ARM64, NULL), +#endif +#ifdef HAVE_ENCODER_ARMTHUMB + INIT_FILTER(LZMA_FILTER_ARMTHUMB, NULL), +#endif +#ifdef HAVE_ENCODER_SPARC + INIT_FILTER(LZMA_FILTER_SPARC, NULL), +#endif +}; + +// HAVE_ENCODERS ifdef not termianted here because decoders are +// only used if encoders are, but encoders can still be used +// even if decoders are not. + +#ifdef HAVE_DECODERS +static lzma_filter bcj_filters_decoders[] = { +#ifdef HAVE_DECODER_X86 + INIT_FILTER(LZMA_FILTER_X86, NULL), +#endif +#ifdef HAVE_DECODER_POWERPC + INIT_FILTER(LZMA_FILTER_POWERPC, NULL), +#endif +#ifdef HAVE_DECODER_IA64 + INIT_FILTER(LZMA_FILTER_IA64, NULL), +#endif +#ifdef HAVE_DECODER_ARM + INIT_FILTER(LZMA_FILTER_ARM, NULL), +#endif +#ifdef HAVE_DECODER_ARM64 + INIT_FILTER(LZMA_FILTER_ARM64, NULL), +#endif +#ifdef HAVE_DECODER_ARMTHUMB + INIT_FILTER(LZMA_FILTER_ARMTHUMB, NULL), +#endif +#ifdef HAVE_DECODER_SPARC + INIT_FILTER(LZMA_FILTER_SPARC, NULL), +#endif +}; +#endif +#endif + + +static void +test_lzma_filter_flags_size(void) { - memcrap(buffer, sizeof(buffer)); +#ifndef HAVE_ENCODERS + assert_skip("Encoder support disabled"); +#else + // For each supported filter, test that the size can be calculated + // and that the size calculated is reasonable. A reasonable size + // must be greater than 0, but less than the maximum size for the + // block header. + uint32_t size = 0; + if (lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA1)) { + assert_lzma_ret(lzma_filter_flags_size(&size, + &lzma1_filter), LZMA_PROG_ERROR); + } - uint32_t tmp; - if (lzma_filter_flags_size(&tmp, &known_flags) != LZMA_OK) - return true; + if (lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA2)) { + assert_lzma_ret(lzma_filter_flags_size(&size, + &lzma2_filter), LZMA_OK); + assert_true(size != 0 && size < LZMA_BLOCK_HEADER_SIZE_MAX); + } - if (tmp != known_size) - return true; + for (uint32_t i = 0; i < ARRAY_SIZE(bcj_filters_encoders); i++) { + assert_lzma_ret(lzma_filter_flags_size(&size, + &bcj_filters_encoders[i]), LZMA_OK); + assert_true(size != 0 && size < LZMA_BLOCK_HEADER_SIZE_MAX); + } + if (lzma_filter_encoder_is_supported(LZMA_FILTER_DELTA)) { + assert_lzma_ret(lzma_filter_flags_size(&size, + &delta_filter), LZMA_OK); + assert_true(size != 0 && size < LZMA_BLOCK_HEADER_SIZE_MAX); + } + + // Test invalid filter ids + lzma_filter bad_filter = INIT_FILTER(2, NULL); + + assert_lzma_ret(lzma_filter_flags_size(&size, &bad_filter), + LZMA_OPTIONS_ERROR); + bad_filter.id = LZMA_VLI_MAX; + assert_lzma_ret(lzma_filter_flags_size(&size, &bad_filter), + LZMA_PROG_ERROR); + bad_filter.id = LZMA_FILTER_RESERVED_START; + assert_lzma_ret(lzma_filter_flags_size(&size, &bad_filter), + LZMA_PROG_ERROR); +#endif +} + + +// Helper function for test_lzma_filter_flags_encode. +// The should_encode parameter represents if the encoding operation +// is expected to fail. +// Avoid data -> encode -> decode -> compare to data. +// Instead create expected encoding and compare to result from +// lzma_filter_flags_encode. +// Filter flags for xz are encoded as: +// |Filter ID (VLI)|Size of Properties (VLI)|Filter Properties| +#if defined(HAVE_ENCODERS) && defined(HAVE_DECODERS) +static void +verify_filter_flags_encode(lzma_filter *filter, bool should_encode) +{ + uint32_t size = 0; + // First calculate the size of filter flags to know how much + // memory to allocate to hold the filter flags encoded + assert_lzma_ret(lzma_filter_flags_size(&size, filter), LZMA_OK); + uint8_t *encoded_out = tuktest_malloc(size * sizeof(uint8_t)); size_t out_pos = 0; - if (lzma_filter_flags_encode(&known_flags, - buffer, &out_pos, known_size) != LZMA_OK) - return true; - - if (out_pos != known_size) - return true; - - return false; -} - - -static bool -decode_ret(uint32_t known_size, lzma_ret expected_ret) -{ - memcrap(&decoded_flags, sizeof(decoded_flags)); - - size_t pos = 0; - if (lzma_filter_flags_decode(&decoded_flags, NULL, - buffer, &pos, known_size) != expected_ret - || pos != known_size) - return true; - - return false; -} - - -static bool -decode(uint32_t known_size) -{ - if (decode_ret(known_size, LZMA_OK)) - return true; - - if (known_flags.id != decoded_flags.id) - return true; - - return false; -} - - -#if defined(HAVE_ENCODER_X86) && defined(HAVE_DECODER_X86) -static void -test_bcj(void) -{ - // Test 1 - known_flags.id = LZMA_FILTER_X86; - known_flags.options = NULL; - - expect(!encode(2)); - expect(!decode(2)); - expect(decoded_flags.options == NULL); - - // Test 2 - lzma_options_bcj options; - options.start_offset = 0; - known_flags.options = &options; - expect(!encode(2)); - expect(!decode(2)); - expect(decoded_flags.options == NULL); - - // Test 3 - options.start_offset = 123456; - known_flags.options = &options; - expect(!encode(6)); - expect(!decode(6)); - expect(decoded_flags.options != NULL); - - lzma_options_bcj *decoded = decoded_flags.options; - expect(decoded->start_offset == options.start_offset); - - free(decoded); -} -#endif - - -#if defined(HAVE_ENCODER_DELTA) && defined(HAVE_DECODER_DELTA) -static void -test_delta(void) -{ - // Test 1 - known_flags.id = LZMA_FILTER_DELTA; - known_flags.options = NULL; - expect(encode(99)); - - // Test 2 - lzma_options_delta options = { - .type = LZMA_DELTA_TYPE_BYTE, - .dist = 0 - }; - known_flags.options = &options; - expect(encode(99)); - - // Test 3 - options.dist = LZMA_DELTA_DIST_MIN; - expect(!encode(3)); - expect(!decode(3)); - expect(((lzma_options_delta *)(decoded_flags.options))->dist - == options.dist); - - free(decoded_flags.options); - - // Test 4 - options.dist = LZMA_DELTA_DIST_MAX; - expect(!encode(3)); - expect(!decode(3)); - expect(((lzma_options_delta *)(decoded_flags.options))->dist - == options.dist); - - free(decoded_flags.options); - - // Test 5 - options.dist = LZMA_DELTA_DIST_MAX + 1; - expect(encode(99)); -} -#endif - -/* -#ifdef HAVE_FILTER_LZMA -static void -validate_lzma(void) -{ - const lzma_options_lzma *known = known_flags.options; - const lzma_options_lzma *decoded = decoded_flags.options; - - expect(known->dictionary_size <= decoded->dictionary_size); - - if (known->dictionary_size == 1) - expect(decoded->dictionary_size == 1); - else - expect(known->dictionary_size + known->dictionary_size / 2 - > decoded->dictionary_size); - - expect(known->literal_context_bits == decoded->literal_context_bits); - expect(known->literal_pos_bits == decoded->literal_pos_bits); - expect(known->pos_bits == decoded->pos_bits); -} - - -static void -test_lzma(void) -{ - // Test 1 - known_flags.id = LZMA_FILTER_LZMA1; - known_flags.options = NULL; - expect(encode(99)); - - // Test 2 - lzma_options_lzma options = { - .dictionary_size = 0, - .literal_context_bits = 0, - .literal_pos_bits = 0, - .pos_bits = 0, - .preset_dictionary = NULL, - .preset_dictionary_size = 0, - .mode = LZMA_MODE_INVALID, - .fast_bytes = 0, - .match_finder = LZMA_MF_INVALID, - .match_finder_cycles = 0, - }; - - // Test 3 (empty dictionary not allowed) - known_flags.options = &options; - expect(encode(99)); - - // Test 4 (brute-force test some valid dictionary sizes) - options.dictionary_size = LZMA_DICTIONARY_SIZE_MIN; - while (options.dictionary_size != LZMA_DICTIONARY_SIZE_MAX) { - if (++options.dictionary_size == 5000) - options.dictionary_size = LZMA_DICTIONARY_SIZE_MAX - 5; - - expect(!encode(4)); - expect(!decode(4)); - validate_lzma(); - - free(decoded_flags.options); + if(!should_encode) { + assert_false(lzma_filter_flags_encode(filter, encoded_out, + &out_pos, size) == LZMA_OK); + return; } - // Test 5 (too big dictionary size) - options.dictionary_size = LZMA_DICTIONARY_SIZE_MAX + 1; - expect(encode(99)); + // Next encode the filter flags for the provided filter + assert_lzma_ret(lzma_filter_flags_encode(filter, encoded_out, + &out_pos, size), LZMA_OK); + assert_uint_eq(size, out_pos); + // Next decode the vli for the filter ID and verify it matches + // the expected filter id + size_t filter_id_vli_size = 0; + lzma_vli filter_id = 0; + assert_lzma_ret(lzma_vli_decode(&filter_id, NULL, encoded_out, + &filter_id_vli_size, size), LZMA_OK); + assert_uint_eq(filter->id, filter_id); - // Test 6 (brute-force test lc/lp/pb) - options.dictionary_size = LZMA_DICTIONARY_SIZE_MIN; - for (uint32_t lc = LZMA_LITERAL_CONTEXT_BITS_MIN; - lc <= LZMA_LITERAL_CONTEXT_BITS_MAX; ++lc) { - for (uint32_t lp = LZMA_LITERAL_POS_BITS_MIN; - lp <= LZMA_LITERAL_POS_BITS_MAX; ++lp) { - for (uint32_t pb = LZMA_POS_BITS_MIN; - pb <= LZMA_POS_BITS_MAX; ++pb) { - if (lc + lp > LZMA_LITERAL_BITS_MAX) - continue; + // Next decode the size of properites and ensure it equals + // the expected size + // Expected size should be: + // total filter flag length - size of filter id VLI + size of + // property size VLI + // Not verifying the contents of Filter Properties since + // that belongs in a different test + size_t size_of_properties_vli_size = 0; + lzma_vli size_of_properties = 0; + assert_lzma_ret(lzma_vli_decode(&size_of_properties, NULL, + encoded_out + filter_id_vli_size, + &size_of_properties_vli_size, size), LZMA_OK); + assert_uint_eq(size - (size_of_properties_vli_size + + filter_id_vli_size), size_of_properties); +} +#endif - options.literal_context_bits = lc; - options.literal_pos_bits = lp; - options.pos_bits = pb; - expect(!encode(4)); - expect(!decode(4)); - validate_lzma(); +static void +test_lzma_filter_flags_encode(void) +{ +#if !defined(HAVE_ENCODERS) || !defined(HAVE_DECODERS) + assert_skip("Encoder or decoder support disabled"); +#else + // No test for LZMA1 since the xz format does not support LZMA1 + // and so the flags cannot be encoded for that filter + if (lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA2)) { + // Test with NULL options that should fail + lzma_options_lzma *options = lzma2_filter.options; + lzma2_filter.options = NULL; + verify_filter_flags_encode(&lzma2_filter, false); + // Place options back in the filter, and test should pass + lzma2_filter.options = options; + verify_filter_flags_encode(&lzma2_filter, true); + } - free(decoded_flags.options); - } + lzma_options_bcj bcj_options = { + .start_offset = 200 + }; + + for (uint32_t i = 0; i < ARRAY_SIZE(bcj_filters_encoders); i++) { + // NULL options should pass for bcj filters + verify_filter_flags_encode(&bcj_filters_encoders[i], true); + lzma_filter bcj_with_options = INIT_FILTER( + bcj_filters_encoders[i].id, &bcj_options); + verify_filter_flags_encode(&bcj_with_options, true); + } + + if (lzma_filter_encoder_is_supported(LZMA_FILTER_DELTA)) { + lzma_options_delta delta_ops_below_min = { + .type = LZMA_DELTA_TYPE_BYTE, + .dist = LZMA_DELTA_DIST_MIN - 1 + }; + + lzma_options_delta delta_ops_above_max = { + .type = LZMA_DELTA_TYPE_BYTE, + .dist = LZMA_DELTA_DIST_MAX + 1 + }; + + verify_filter_flags_encode(&delta_filter, true); + + lzma_filter delta_filter_bad_options = INIT_FILTER( + LZMA_FILTER_DELTA, &delta_ops_below_min); + + // Next test error case using minimum - 1 delta distance + verify_filter_flags_encode(&delta_filter_bad_options, false); + + // Next test error case using maximum + 1 delta distance + delta_filter_bad_options.options = &delta_ops_above_max; + verify_filter_flags_encode(&delta_filter_bad_options, false); + + // Next test null case + delta_filter_bad_options.options = NULL; + verify_filter_flags_encode(&delta_filter_bad_options, false); + } + + // Test expected failing cases + lzma_filter bad_filter = INIT_FILTER(LZMA_FILTER_RESERVED_START, + NULL); + size_t out_pos = 0; + size_t out_size = LZMA_BLOCK_HEADER_SIZE_MAX; + uint8_t out[LZMA_BLOCK_HEADER_SIZE_MAX]; + + + // Filter id outside of valid range + assert_lzma_ret(lzma_filter_flags_encode(&bad_filter, out, &out_pos, + out_size), LZMA_PROG_ERROR); + out_pos = 0; + bad_filter.id = LZMA_VLI_MAX + 1; + assert_lzma_ret(lzma_filter_flags_encode(&bad_filter, out, &out_pos, + out_size), LZMA_PROG_ERROR); + out_pos = 0; + + // Invalid filter id + bad_filter.id = 2; + assert_lzma_ret(lzma_filter_flags_encode(&bad_filter, out, &out_pos, + out_size), LZMA_OPTIONS_ERROR); + out_pos = 0; + + // Out size too small + if (lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA2)) { + uint32_t bad_size = 0; + + // First test with 0 output size + assert_lzma_ret(lzma_filter_flags_encode( + &lzma2_filter, out, &out_pos, 0), + LZMA_PROG_ERROR); + + // Next calculate the size needed to encode and + // use less than that + assert_lzma_ret(lzma_filter_flags_size(&bad_size, + &lzma2_filter), LZMA_OK); + + assert_lzma_ret(lzma_filter_flags_encode( + &lzma2_filter, out, &out_pos, + bad_size - 1), LZMA_PROG_ERROR); + out_pos = 0; + } + + // Invalid options + if (lzma_filter_encoder_is_supported(LZMA_FILTER_DELTA)) { + bad_filter.id = LZMA_FILTER_DELTA; + // First test with NULL options + assert_lzma_ret(lzma_filter_flags_encode(&bad_filter, out, + &out_pos, out_size), LZMA_PROG_ERROR); + out_pos = 0; + + // Next test with invalid options + lzma_options_delta bad_options = { + .dist = LZMA_DELTA_DIST_MAX + 1, + .type = LZMA_DELTA_TYPE_BYTE + }; + bad_filter.options = &bad_options; + + assert_lzma_ret(lzma_filter_flags_encode(&bad_filter, out, + &out_pos, out_size), LZMA_PROG_ERROR); + } +#endif +} + + +// Helper function for test_lzma_filter_flags_decode. +// Encodes the filter_in without using lzma_filter_flags_encode. +// Leaves the specific assertions of filter_out options to the caller +// because it is agnostic to the type of options used in the call +#if defined(HAVE_ENCODERS) && defined(HAVE_DECODERS) +static void +verify_filter_flags_decode(lzma_filter *filter_in, lzma_filter *filter_out) +{ + uint32_t total_size = 0; + + assert_lzma_ret(lzma_filter_flags_size(&total_size, filter_in), + LZMA_OK); + uint8_t *filter_flag_buffer = tuktest_malloc(total_size); + + uint32_t properties_size = 0; + size_t out_pos = 0, in_pos = 0; + assert_lzma_ret(lzma_properties_size(&properties_size, filter_in), + LZMA_OK); + assert_lzma_ret(lzma_vli_encode(filter_in->id, NULL, + filter_flag_buffer, &out_pos, total_size), LZMA_OK); + assert_lzma_ret(lzma_vli_encode(properties_size, NULL, + filter_flag_buffer, &out_pos, total_size), + LZMA_OK); + assert_lzma_ret(lzma_properties_encode(filter_in, + filter_flag_buffer + out_pos), LZMA_OK); + assert_lzma_ret(lzma_filter_flags_decode(filter_out, NULL, + filter_flag_buffer, &in_pos, total_size), + LZMA_OK); + assert_uint_eq(filter_in->id, filter_out->id); +} +#endif + + +static void +test_lzma_filter_flags_decode(void) +{ +#if !defined(HAVE_ENCODERS) || !defined(HAVE_DECODERS) + assert_skip("Encoder or decoder support disabled"); +#else + // For each filter, only run the decoder test if both the encoder + // and decoder is enabled. This is because verify_filter_flags_decode + // uses lzma_filter_flags_size, which requires the encoder. + if (lzma_filter_decoder_is_supported(LZMA_FILTER_LZMA2) && + lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA2)) { + lzma_filter lzma2_decoded = INIT_FILTER(LZMA_FILTER_LZMA2, + NULL); + + verify_filter_flags_decode(&lzma2_filter, &lzma2_decoded); + + lzma_options_lzma *expected = lzma2_filter.options; + lzma_options_lzma *decoded = lzma2_decoded.options; + + // Only the dictionary size is encoded and decoded + // so only compare those + assert_uint_eq(decoded->dict_size, expected->dict_size); + + // The decoded options must be freed by the caller + free(decoded); + } + + for (uint32_t i = 0; i < ARRAY_SIZE(bcj_filters_decoders); i++) { + if (lzma_filter_encoder_is_supported( + bcj_filters_decoders[i].id)) { + lzma_filter bcj_decoded = INIT_FILTER( + bcj_filters_decoders[i].id, NULL); + + lzma_filter bcj_encoded = INIT_FILTER( + bcj_filters_decoders[i].id, NULL); + + // First test without options + verify_filter_flags_decode(&bcj_encoded, + &bcj_decoded); + assert_true(bcj_decoded.options == NULL); + + // Next test with offset + lzma_options_bcj options = { + .start_offset = 200 + }; + + bcj_encoded.options = &options; + verify_filter_flags_decode(&bcj_encoded, + &bcj_decoded); + lzma_options_bcj *decoded_ops = bcj_decoded.options; + assert_uint_eq(decoded_ops->start_offset, + options.start_offset); + free(decoded_ops); } + } -} -#endif -*/ -int -main(void) + if (lzma_filter_decoder_is_supported(LZMA_FILTER_DELTA) && + lzma_filter_encoder_is_supported(LZMA_FILTER_DELTA)) { + lzma_filter delta_decoded = INIT_FILTER(LZMA_FILTER_DELTA, + NULL); + + verify_filter_flags_decode(&delta_filter, &delta_decoded); + lzma_options_delta *expected = delta_filter.options; + lzma_options_delta *decoded = delta_decoded.options; + assert_uint_eq(expected->dist, decoded->dist); + assert_uint_eq(expected->type, decoded->type); + + free(decoded); + } + + // Test expected failing cases + uint8_t bad_encoded_filter[LZMA_BLOCK_HEADER_SIZE_MAX]; + lzma_filter bad_filter; + + // Filter outside of valid range + lzma_vli bad_filter_id = LZMA_FILTER_RESERVED_START; + size_t bad_encoded_out_pos = 0; + size_t in_pos = 0; + + assert_lzma_ret(lzma_vli_encode(bad_filter_id, NULL, + bad_encoded_filter, &bad_encoded_out_pos, + LZMA_BLOCK_HEADER_SIZE_MAX), LZMA_OK); + + assert_lzma_ret(lzma_filter_flags_decode(&bad_filter, NULL, + bad_encoded_filter, &in_pos, + LZMA_BLOCK_HEADER_SIZE_MAX), LZMA_DATA_ERROR); + + bad_encoded_out_pos = 0; + in_pos = 0; + + // Invalid filter Id + bad_filter_id = 2; + bad_encoded_out_pos = 0; + in_pos = 0; + + assert_lzma_ret(lzma_vli_encode(bad_filter_id, NULL, + bad_encoded_filter, &bad_encoded_out_pos, + LZMA_BLOCK_HEADER_SIZE_MAX), LZMA_OK); + + // Next encode propery size of 0 + assert_lzma_ret(lzma_vli_encode(0, NULL, + bad_encoded_filter, &bad_encoded_out_pos, + LZMA_BLOCK_HEADER_SIZE_MAX), LZMA_OK); + // Decode should fail on bad filter id + assert_lzma_ret(lzma_filter_flags_decode(&bad_filter, NULL, + bad_encoded_filter, &in_pos, + LZMA_BLOCK_HEADER_SIZE_MAX), LZMA_OPTIONS_ERROR); + bad_encoded_out_pos = 0; + in_pos = 0; + + // Outsize too small + // Encode the lzma2 filter normally, but then set + // the out size when decoding as too small + if (lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA2) && + lzma_filter_decoder_is_supported(LZMA_FILTER_LZMA2)) { + uint32_t filter_flag_size = 0; + assert_lzma_ret(lzma_filter_flags_size(&filter_flag_size, + &lzma2_filter), LZMA_OK); + + assert_lzma_ret(lzma_filter_flags_encode(&lzma2_filter, + bad_encoded_filter, &bad_encoded_out_pos, + LZMA_BLOCK_HEADER_SIZE_MAX), LZMA_OK); + + assert_lzma_ret(lzma_filter_flags_decode(&bad_filter, NULL, + bad_encoded_filter, &in_pos, + filter_flag_size - 1), LZMA_DATA_ERROR); + } +#endif +} + + +extern int +main(int argc, char **argv) { -#if defined(HAVE_ENCODER_X86) && defined(HAVE_DECODER_X86) - test_bcj(); -#endif -#if defined(HAVE_ENCODER_DELTA) && defined(HAVE_DECODER_DELTA) - test_delta(); -#endif -// #ifdef HAVE_FILTER_LZMA -// test_lzma(); -// #endif + tuktest_start(argc, argv); - lzma_end(&strm); +#ifdef HAVE_ENCODERS + // Only init filter options if encoder is supported because decoder + // tests requires encoder support, so the decoder tests will only + // run if for a given filter both the encoder and decoder are enabled. + if (lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA1)) { + lzma_options_lzma *options = tuktest_malloc( + sizeof(lzma_options_lzma)); + lzma_lzma_preset(options, LZMA_PRESET_DEFAULT); + lzma1_filter.options = options; + } - return 0; + if (lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA2)) { + lzma_options_lzma *options = tuktest_malloc( + sizeof(lzma_options_lzma)); + lzma_lzma_preset(options, LZMA_PRESET_DEFAULT); + lzma2_filter.options = options; + } + + if (lzma_filter_encoder_is_supported(LZMA_FILTER_DELTA)) { + lzma_options_delta *options = tuktest_malloc( + sizeof(lzma_options_delta)); + options->dist = LZMA_DELTA_DIST_MIN; + options->type = LZMA_DELTA_TYPE_BYTE; + delta_filter.options = options; + } +#endif + + tuktest_run(test_lzma_filter_flags_size); + tuktest_run(test_lzma_filter_flags_encode); + tuktest_run(test_lzma_filter_flags_decode); + return tuktest_end(); }