root/tests/test_filter_flags.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. encode
  2. decode_ret
  3. decode
  4. test_bcj
  5. test_delta
  6. main

///////////////////////////////////////////////////////////////////////////////
//
/// \file       test_filter_flags.c
/// \brief      Tests Filter Flags coders
//
//  Author:     Lasse Collin
//
//  This file has been put into the public domain.
//  You can do whatever you want with this file.
//
///////////////////////////////////////////////////////////////////////////////

#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_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);
        }

        // 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_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

        lzma_end(&strm);

        return 0;
}

/* [<][>][^][v][top][bottom][index][help] */