/////////////////////////////////////////////////////////////////////////////// // /// \file test_filter_flags.c /// \brief Tests Filter Flags coders // // Copyright (C) 2007 Lasse Collin // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // /////////////////////////////////////////////////////////////////////////////// #include "tests.h" static uint8_t buffer[4096]; static lzma_filter known_flags; static lzma_filter decoded_flags; static lzma_stream strm = LZMA_STREAM_INIT; static bool encode(uint32_t known_size) { memcrap(buffer, sizeof(buffer)); uint32_t tmp; if (lzma_filter_flags_size(&tmp, &known_flags) != LZMA_OK) return true; if (tmp != known_size) return true; 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_SUBBLOCK) && defined(HAVE_DECODER_SUBBLOCK) static void test_subblock(void) { // Test 1 known_flags.id = LZMA_FILTER_SUBBLOCK; known_flags.options = NULL; expect(!encode(2)); expect(!decode(2)); expect(decoded_flags.options == NULL); // Test 2 buffer[0] = LZMA_FILTER_SUBBLOCK; buffer[1] = 1; buffer[2] = 0; expect(!decode_ret(3, LZMA_OPTIONS_ERROR)); } #endif #if defined(HAVE_ENCODER_X86) && defined(HAVE_DECODER_X86) static void test_simple(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_simple 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_simple *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); } // Test 5 (too big dictionary size) options.dictionary_size = LZMA_DICTIONARY_SIZE_MAX + 1; expect(encode(99)); // 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; options.literal_context_bits = lc; options.literal_pos_bits = lp; options.pos_bits = pb; expect(!encode(4)); expect(!decode(4)); validate_lzma(); free(decoded_flags.options); } } } } #endif */ int main(void) { #if defined(HAVE_ENCODER_SUBBLOCK) && defined(HAVE_DECODER_SUBBLOCK) test_subblock(); #endif #if defined(HAVE_ENCODER_X86) && defined(HAVE_DECODER_X86) test_simple(); #endif #if defined(HAVE_ENCODER_DELTA) && defined(HAVE_DECODER_DELTA) test_delta(); #endif // #ifdef HAVE_FILTER_LZMA // test_lzma(); // #endif lzma_end(&strm); return 0; }