Skip to content
Snippets Groups Projects
Select Git revision
  • 1c99e79c91011f9ca4decd1904d66f7bce505e53
  • master default protected
  • cmp_tool-improvement
  • v0.15
  • v0.14
  • v0.13
  • v0.12
  • v0.11
  • v0.09
  • v0.08
  • v0.07
  • v0.06
  • v0.05
13 results

test_cmp_decmp.c

Blame
  • test_cmp_decmp.c 21.58 KiB
    /**
     * @file   test_cmp_decmp.c
     * @author Dominik Loidolt (dominik.loidolt@univie.ac.at),
     * @date   2022
     *
     * @copyright GPLv2
     * This program is free software; you can redistribute it and/or modify it
     * under the terms and conditions of the GNU General Public License,
     * version 2, as published by the Free Software Foundation.
     *
     * This program is distributed in the hope it will be useful, but WITHOUT
     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     * more details.
     *
     * @brief random compression decompression tests
     * @details We generate random data and compress them with random parameters.
     *	After that we put the data in a compression entity. We decompress the
     *	compression entity and compare the decompressed data with the original
     *	data.
     */
    
    
    #include <string.h>
    #include <stdlib.h>
    
    #include <unity.h>
    
    #include <cmp_icu.h>
    #include <decmp.h>
    #include <cmp_data_types.h>
    
    #if defined __has_include
    #  if __has_include(<time.h>)
    #    include <time.h>
    #    include <unistd.h>
    #    define HAS_TIME_H 1
    #  endif
    #endif
    
    #define IMAX_BITS(m) ((m)/((m)%255+1) / 255%255*8 + 7-86/((m)%255+12))
    #define RAND_MAX_WIDTH IMAX_BITS(RAND_MAX)
    
    #define set_n_bits(n)  (n != 32 ? ~(~0UL << (n)):0xFFFFFFFF)
    
    
    /**
     * @brief  Seeds the pseudo-random number generator used by rand()
     */
    
    void setUp(void)
    {
    	unsigned int seed;
    	static int n;
    
    #if HAS_TIME_H
    	seed = time(NULL) * getpid();
    #else
    	seed = 1;
    #endif
    
    	if (!n) {
    		n = 1;
    		srand(seed);
    		printf("seed: %u\n", seed);
    	}
    }
    
    
    /**
     * @brief generate a uint32_t random number
     *
     * @return a "random" uint32_t value
     * @see https://stackoverflow.com/a/33021408
     */
    
    uint32_t rand32(void)
    {
    	int i;
    	uint32_t r = 0;
    
    	for (i = 0; i < 32; i += RAND_MAX_WIDTH) {
    		r <<= RAND_MAX_WIDTH;
    		r ^= (unsigned int) rand();
    	}
    	return r;
    }
    
    
    /**
     * @brief generate a random number in a range
     *
     * @param min minimum value (inclusive)
     * @param max maximum value (inclusive)
     *
     * @returns "random" numbers in the range [min, max]
     *
     * @see https://c-faq.com/lib/randrange.html
     */
    
    uint32_t random_between(unsigned int min, unsigned int max)
    {
    	TEST_ASSERT(min < max);
    	if (max-min < RAND_MAX)
    		return min + rand() / (RAND_MAX / (max - min + 1ULL) + 1);
    	else
    		return min + rand32() / (UINT32_MAX / (max - min + 1ULL) + 1);
    }
    
    
    static void gen_ima_data(uint16_t *data, uint32_t samples)
    {
    	uint32_t i;
    	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
    
    	for (i = 0; i < samples; i++)
    		data[i] = random_between(0, set_n_bits(max_used_bits.nc_imagette));
    }
    
    
    static void gen_offset_data(struct nc_offset *data, uint32_t samples)
    {
    	uint32_t i;
    	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
    
    	for (i = 0; i < samples; i++) {
    		data[i].mean = random_between(0, set_n_bits(max_used_bits.nc_offset_mean));
    		data[i].variance = random_between(0, set_n_bits(max_used_bits.nc_offset_variance));
    	}
    }
    
    
    static void gen_background_data(struct nc_background *data, uint32_t samples)
    {
    	uint32_t i;
    	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
    
    	for (i = 0; i < samples; i++) {
    		data[i].mean = random_between(0, set_n_bits(max_used_bits.nc_background_mean));
    		data[i].variance = random_between(0, set_n_bits(max_used_bits.nc_background_variance));
    		data[i].outlier_pixels = random_between(0, set_n_bits(max_used_bits.nc_background_outlier_pixels));
    	}
    }
    
    
    static void gen_smearing_data(struct smearing *data, uint32_t samples)
    {
    	uint32_t i;
    	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
    
    	for (i = 0; i < samples; i++) {
    		data[i].mean = random_between(0, set_n_bits(max_used_bits.smearing_mean));
    		data[i].variance_mean = random_between(0, set_n_bits(max_used_bits.smearing_variance_mean));
    		data[i].outlier_pixels = random_between(0, set_n_bits(max_used_bits.smearing_outlier_pixels));
    	}
    }
    
    
    static void gen_s_fx_data(struct s_fx *data, uint32_t samples)
    {
    	uint32_t i;
    	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
    
    	for (i = 0; i < samples; i++) {
    		data[i].exp_flags = random_between(0, set_n_bits(max_used_bits.s_exp_flags));
    		data[i].fx = random_between(0, set_n_bits(max_used_bits.s_fx));
    	}
    }
    
    
    static void gen_s_fx_efx_data(struct s_fx_efx *data, uint32_t samples)
    {
    	uint32_t i;
    	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
    
    	for (i = 0; i < samples; i++) {
    		data[i].exp_flags = random_between(0, set_n_bits(max_used_bits.s_exp_flags));
    		data[i].fx = random_between(0, set_n_bits(max_used_bits.s_fx));
    		data[i].efx = random_between(0, set_n_bits(max_used_bits.s_efx));
    	}
    }
    
    
    static void gen_s_fx_ncob_data(struct s_fx_ncob *data, uint32_t samples)
    {
    	uint32_t i;
    	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
    
    	for (i = 0; i < samples; i++) {
    		data[i].exp_flags = random_between(0, set_n_bits(max_used_bits.s_exp_flags));
    		data[i].fx = random_between(0, set_n_bits(max_used_bits.s_fx));
    		data[i].ncob_x = random_between(0, set_n_bits(max_used_bits.s_ncob));
    		data[i].ncob_y = random_between(0, set_n_bits(max_used_bits.s_ncob));
    	}
    }
    
    
    static void gen_s_fx_efx_ncob_ecob_data(struct s_fx_efx_ncob_ecob *data, uint32_t samples)
    {
    	uint32_t i;
    	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
    
    	for (i = 0; i < samples; i++) {
    		data[i].exp_flags = random_between(0, set_n_bits(max_used_bits.s_exp_flags));
    		data[i].fx = random_between(0, set_n_bits(max_used_bits.s_fx));
    		data[i].ncob_x = random_between(0, set_n_bits(max_used_bits.s_ncob));
    		data[i].ncob_y = random_between(0, set_n_bits(max_used_bits.s_ncob));
    		data[i].efx = random_between(0, set_n_bits(max_used_bits.s_efx));
    		data[i].ecob_x = random_between(0, set_n_bits(max_used_bits.s_ecob));
    		data[i].ecob_y = random_between(0, set_n_bits(max_used_bits.s_ecob));
    	}
    }
    
    
    static void gen_f_fx_data(struct f_fx *data, uint32_t samples)
    {
    	uint32_t i;
    	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
    
    	for (i = 0; i < samples; i++)
    		data[i].fx = random_between(0, set_n_bits(max_used_bits.f_fx));
    }
    
    
    static void gen_f_fx_efx_data(struct f_fx_efx *data, uint32_t samples)
    {
    	uint32_t i;
    	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
    
    	for (i = 0; i < samples; i++) {
    		data[i].fx = random_between(0, set_n_bits(max_used_bits.f_fx));
    		data[i].efx = random_between(0, set_n_bits(max_used_bits.f_efx));
    	}
    }
    
    
    static void gen_f_fx_ncob_data(struct f_fx_ncob *data, uint32_t samples)
    {
    	uint32_t i;
    	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
    
    	for (i = 0; i < samples; i++) {
    		data[i].fx = random_between(0, set_n_bits(max_used_bits.f_fx));
    		data[i].ncob_x = random_between(0, set_n_bits(max_used_bits.f_ncob));
    		data[i].ncob_y = random_between(0, set_n_bits(max_used_bits.f_ncob));
    	}
    }
    
    
    static void gen_f_fx_efx_ncob_ecob_data(struct f_fx_efx_ncob_ecob *data, uint32_t samples)
    {
    	uint32_t i;
    	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
    
    	for (i = 0; i < samples; i++) {
    		data[i].fx = random_between(0, set_n_bits(max_used_bits.f_fx));
    		data[i].ncob_x = random_between(0, set_n_bits(max_used_bits.f_ncob));
    		data[i].ncob_y = random_between(0, set_n_bits(max_used_bits.f_ncob));
    		data[i].efx = random_between(0, set_n_bits(max_used_bits.f_efx));
    		data[i].ecob_x = random_between(0, set_n_bits(max_used_bits.f_ecob));
    		data[i].ecob_y = random_between(0, set_n_bits(max_used_bits.f_ecob));
    	}
    }
    
    
    static void gen_l_fx_data(struct l_fx *data, uint32_t samples)
    {
    	uint32_t i;
    	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
    
    	for (i = 0; i < samples; i++) {
    		data[i].exp_flags = random_between(0, set_n_bits(max_used_bits.l_exp_flags));
    		data[i].fx = random_between(0, set_n_bits(max_used_bits.l_fx));
    		data[i].fx_variance = random_between(0, set_n_bits(max_used_bits.l_fx_variance));
    	}
    }
    
    
    static void gen_l_fx_efx_data(struct l_fx_efx *data, uint32_t samples)
    {
    	uint32_t i;
    	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
    
    	for (i = 0; i < samples; i++) {
    		data[i].exp_flags = random_between(0, set_n_bits(max_used_bits.l_exp_flags));
    		data[i].fx = random_between(0, set_n_bits(max_used_bits.l_fx));
    		data[i].efx = random_between(0, set_n_bits(max_used_bits.l_efx));
    		data[i].fx_variance = random_between(0, set_n_bits(max_used_bits.l_fx_variance));
    	}
    }
    
    
    static void gen_l_fx_ncob_data(struct l_fx_ncob *data, uint32_t samples)
    {
    	uint32_t i;
    	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
    
    	for (i = 0; i < samples; i++) {
    		data[i].exp_flags = random_between(0, set_n_bits(max_used_bits.l_exp_flags));
    		data[i].fx = random_between(0, set_n_bits(max_used_bits.l_fx));
    		data[i].ncob_x = random_between(0, set_n_bits(max_used_bits.l_ncob));
    		data[i].ncob_y = random_between(0, set_n_bits(max_used_bits.l_ncob));
    		data[i].fx_variance = random_between(0, set_n_bits(max_used_bits.l_fx_variance));
    		data[i].cob_x_variance = random_between(0, set_n_bits(max_used_bits.l_cob_variance));
    		data[i].cob_y_variance = random_between(0, set_n_bits(max_used_bits.l_cob_variance));
    	}
    }
    
    
    static void gen_l_fx_efx_ncob_ecob_data(struct l_fx_efx_ncob_ecob *data, uint32_t samples)
    {
    	uint32_t i;
    	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
    
    	for (i = 0; i < samples; i++) {
    		data[i].exp_flags = random_between(0, set_n_bits(max_used_bits.l_exp_flags));
    		data[i].fx = random_between(0, set_n_bits(max_used_bits.l_fx));
    		data[i].ncob_x = random_between(0, set_n_bits(max_used_bits.l_ncob));
    		data[i].ncob_y = random_between(0, set_n_bits(max_used_bits.l_ncob));
    		data[i].efx = random_between(0, set_n_bits(max_used_bits.l_efx));
    		data[i].ecob_x = random_between(0, set_n_bits(max_used_bits.l_ecob));
    		data[i].ecob_y = random_between(0, set_n_bits(max_used_bits.l_ecob));
    		data[i].fx_variance = random_between(0, set_n_bits(max_used_bits.l_fx_variance));
    		data[i].cob_x_variance = random_between(0, set_n_bits(max_used_bits.l_cob_variance));
    		data[i].cob_y_variance = random_between(0, set_n_bits(max_used_bits.l_cob_variance));
    	}
    }
    
    
    /**
     * @brief generate random test data
     *
     * @param samples	number of random test samples
     * @param data_type	compression data type of the test data
     *
     * @returns a pointer to the generated random test data
     */
    
    void *generate_random_test_data(uint32_t samples, enum cmp_data_type data_type)
    {
    	size_t data_size = cmp_cal_size_of_data(samples, data_type);
    	void *data = malloc(data_size);
    	void *data_cpy = data;
    	uint8_t *p = data;
    
    	TEST_ASSERT_NOT_EQUAL_INT(data_size, 0);
    	TEST_ASSERT(data_size < (CMP_ENTITY_MAX_SIZE - NON_IMAGETTE_HEADER_SIZE));
    	TEST_ASSERT_NOT_NULL(data);
    
    	if (!rdcu_supported_data_type_is_used(data_type)) {
    		int i;
    
    		TEST_ASSERT(data_size > MULTI_ENTRY_HDR_SIZE);
    		for (i = 0; i < MULTI_ENTRY_HDR_SIZE; ++i)
    			*p++ = random_between(0, UINT8_MAX);
    		data = p;
    	}
    
    	switch (data_type) {
    	case DATA_TYPE_IMAGETTE:
    	case DATA_TYPE_IMAGETTE_ADAPTIVE:
    	case DATA_TYPE_SAT_IMAGETTE:
    	case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE:
    	case DATA_TYPE_F_CAM_IMAGETTE:
    	case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE:
    		gen_ima_data(data, samples);
    		break;
    	case DATA_TYPE_OFFSET:
    		gen_offset_data(data, samples);
    		break;
    	case DATA_TYPE_BACKGROUND:
    		gen_background_data(data, samples);
    		break;
    	case DATA_TYPE_SMEARING:
    		gen_smearing_data(data, samples);
    		break;
    	case DATA_TYPE_S_FX:
    		gen_s_fx_data(data, samples);
    		break;
    	case DATA_TYPE_S_FX_EFX:
    		gen_s_fx_efx_data(data, samples);
    		break;
    	case DATA_TYPE_S_FX_NCOB:
    		gen_s_fx_ncob_data(data, samples);
    		break;
    	case DATA_TYPE_S_FX_EFX_NCOB_ECOB:
    		gen_s_fx_efx_ncob_ecob_data(data, samples);
    		break;
    	case DATA_TYPE_L_FX:
    		gen_l_fx_data(data, samples);
    		break;
    	case DATA_TYPE_L_FX_EFX:
    		gen_l_fx_efx_data(data, samples);
    		break;
    	case DATA_TYPE_L_FX_NCOB:
    		gen_l_fx_ncob_data(data, samples);
    		break;
    	case DATA_TYPE_L_FX_EFX_NCOB_ECOB:
    		gen_l_fx_efx_ncob_ecob_data(data, samples);
    		break;
    	case DATA_TYPE_F_FX:
    		gen_f_fx_data(data, samples);
    		break;
    	case DATA_TYPE_F_FX_EFX:
    		gen_f_fx_efx_data(data, samples);
    		break;
    	case DATA_TYPE_F_FX_NCOB:
    		gen_f_fx_ncob_data(data, samples);
    		break;
    	case DATA_TYPE_F_FX_EFX_NCOB_ECOB:
    		gen_f_fx_efx_ncob_ecob_data(data, samples);
    		break;
    	case DATA_TYPE_F_CAM_OFFSET: /* TODO: implement this */
    	case DATA_TYPE_F_CAM_BACKGROUND: /* TODO: implement this */
    	default:
    		TEST_FAIL();
    	}
    
    	return data_cpy;
    }
    
    
    /**
     * @brief generate random compression configuration
     *
     * @param cfg	pointer to a compression configuration
     *
     */
    
    void generate_random_cmp_par(struct cmp_cfg *cfg)
    {
    	cfg->golomb_par = random_between(MIN_IMA_GOLOMB_PAR, MAX_IMA_GOLOMB_PAR);
    	cfg->ap1_golomb_par = random_between(MIN_IMA_GOLOMB_PAR, MAX_IMA_GOLOMB_PAR);
    	cfg->ap2_golomb_par = random_between(MIN_IMA_GOLOMB_PAR, MAX_IMA_GOLOMB_PAR);
    
    	cfg->cmp_par_exp_flags = random_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR);
    	cfg->cmp_par_fx = random_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR);
    	cfg->cmp_par_ncob = random_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR);
    	cfg->cmp_par_efx = random_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR);
    	cfg->cmp_par_ecob = random_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR);
    	cfg->cmp_par_fx_cob_variance = random_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR);
    	cfg->cmp_par_mean = random_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR);
    	cfg->cmp_par_variance = random_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR);
    	cfg->cmp_par_pixels_error = random_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR);
    
    
    	cfg->spill = random_between(MIN_IMA_SPILL, cmp_ima_max_spill(cfg->golomb_par));
    	cfg->ap1_spill = random_between(MIN_IMA_SPILL, cmp_ima_max_spill(cfg->ap1_golomb_par));
    	cfg->ap2_spill = random_between(MIN_IMA_SPILL, cmp_ima_max_spill(cfg->ap2_golomb_par));
    
    	cfg->spill_exp_flags = random_between(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg->cmp_par_exp_flags));
    	cfg->spill_fx = random_between(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg->cmp_par_fx));
    	cfg->spill_ncob = random_between(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg->cmp_par_ncob));
    	cfg->spill_efx = random_between(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg->cmp_par_efx));
    	cfg->spill_ecob = random_between(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg->cmp_par_ecob));
    	cfg->spill_fx_cob_variance = random_between(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg->cmp_par_fx_cob_variance));
    	cfg->spill_mean = random_between(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg->cmp_par_mean));
    	cfg->spill_variance = random_between(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg->cmp_par_variance));
    	cfg->spill_pixels_error = random_between(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg->cmp_par_pixels_error));
    #if 0
    	if (cfg->cmp_mode == CMP_MODE_STUFF) {
    		/* cfg->golomb_par = random_between(16, MAX_STUFF_CMP_PAR); */
    		cfg->golomb_par = 16;
    		cfg->ap1_golomb_par = random_between(0, MAX_STUFF_CMP_PAR);
    		cfg->ap2_golomb_par = random_between(0, MAX_STUFF_CMP_PAR);
    		cfg->cmp_par_exp_flags = random_between(0, MAX_STUFF_CMP_PAR);
    		cfg->cmp_par_fx = random_between(0, MAX_STUFF_CMP_PAR);
    		cfg->cmp_par_ncob = random_between(0, MAX_STUFF_CMP_PAR);
    		cfg->cmp_par_efx = random_between(0, MAX_STUFF_CMP_PAR);
    		cfg->cmp_par_ecob = random_between(0, MAX_STUFF_CMP_PAR);
    		cfg->cmp_par_fx_cob_variance = random_between(0, MAX_STUFF_CMP_PAR);
    		cfg->cmp_par_mean = random_between(0, MAX_STUFF_CMP_PAR);
    		cfg->cmp_par_variance = random_between(0, MAX_STUFF_CMP_PAR);
    		cfg->cmp_par_pixels_error = random_between(0, MAX_STUFF_CMP_PAR);
    		return;
    	}
    #endif
    }
    
    
    /**
     * @brief compress the given configuration and decompress it afterwards; finally
     *	compare the results
     *
     * @param cfg	pointer to a compression configuration
     */
    
    void compression_decompression(struct cmp_cfg *cfg)
    {
    	int cmp_size_bits, s, error;
    	int data_size, cmp_data_size;
    	struct cmp_entity *ent;
    	void *decompressed_data;
    	static void *model_of_data;
    	void *updated_model = NULL;
    
    	if (!cfg) {
    		free(model_of_data);
    		return;
    	}
    
    	TEST_ASSERT_NOT_NULL(cfg);
    
    	TEST_ASSERT_NULL(cfg->icu_output_buf);
    
    	data_size = cmp_cal_size_of_data(cfg->samples, cfg->data_type);
    
    	/* create a compression entity */
    	cmp_data_size = cmp_cal_size_of_data(cfg->buffer_length, cfg->data_type);
    	cmp_data_size &= ~0x3; /* the size of the compressed data should be a multiple of 4 */
    	TEST_ASSERT_NOT_EQUAL_INT(0, cmp_data_size);
    
    	s = cmp_ent_create(NULL, cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW, cmp_data_size);
    	TEST_ASSERT_NOT_EQUAL_INT(0, s);
    	ent = malloc(s); TEST_ASSERT_TRUE(ent);
    	s = cmp_ent_create(ent, cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW, cmp_data_size);
    	TEST_ASSERT_NOT_EQUAL_INT(0, s);
    
    	/* we put the coompressed data direct into the compression entity */
    	cfg->icu_output_buf = cmp_ent_get_data_buf(ent);
    	TEST_ASSERT_NOT_NULL(cfg->icu_output_buf);
    
    	/* now compress the data */
    	cmp_size_bits = icu_compress_data(cfg);
    	TEST_ASSERT(cmp_size_bits > 0);
    
    	/* put the compression parameters in the entity header */
    	error = cmp_ent_write_cmp_pars(ent, cfg, cmp_size_bits);
    	TEST_ASSERT_FALSE(error);
    
    	/* allocate the buffers for decompression */
    	TEST_ASSERT_NOT_EQUAL_INT(0, data_size);
    	s = decompress_cmp_entiy(ent, model_of_data, NULL, NULL);
    	decompressed_data = malloc(s); TEST_ASSERT_NOT_NULL(decompressed_data);
    
    	if (model_mode_is_used(cfg->cmp_mode)) {
    		updated_model = malloc(data_size);
    		TEST_ASSERT_NOT_NULL(updated_model);
    	}
    
    	/* now we try to decompress the data */
    	s = decompress_cmp_entiy(ent, model_of_data, updated_model, decompressed_data);
    	TEST_ASSERT_EQUAL_INT(data_size, s);
    	TEST_ASSERT_FALSE(memcmp(decompressed_data, cfg->input_buf, data_size));
    
    	if (model_mode_is_used(cfg->cmp_mode)) {
    		TEST_ASSERT_NOT_NULL(updated_model);
    		TEST_ASSERT_NOT_NULL(model_of_data);
    		TEST_ASSERT_FALSE(memcmp(updated_model, cfg->icu_new_model_buf, data_size));
    		memcpy(model_of_data, updated_model, data_size);
    	} else { /* non-model mode */
    		/* reset model */
    		free(model_of_data);
    		model_of_data = malloc(data_size);
    		memcpy(model_of_data, decompressed_data, data_size);
    	}
    
    	cfg->icu_output_buf = NULL;
    	free(ent);
    	free(decompressed_data);
    	free(updated_model);
    }
    
    
    #define CMP_BUFFER_FAKTOR 3 /* compression data buffer size / data to compress buffer size */
    
    /**
     * @brief random compression decompression test
     * @details We generate random data and compress them with random parameters.
     *	After that we put the data in a compression entity. We decompress the
     *	compression entity and compare the decompressed data with the original
     *	data.
     * @test icu_compress_data
     * @test decompress_cmp_entiy
     */
    
    void test_random_compression_decompression(void)
    {
    	enum cmp_data_type data_type;
    	enum cmp_mode cmp_mode;
    	struct cmp_cfg cfg;
    	int cmp_buffer_size;
    
    	/* TODO: extend test for DATA_TYPE_F_CAM_BACKGROUND, DATA_TYPE_F_CAM_OFFSET  */
    	for (data_type = 1; data_type <= DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE; data_type++) {
    		/* printf("%s\n", data_type2string(data_type)); */
    		/* generate random data*/
    		uint32_t samples = random_between(1, 430179/CMP_BUFFER_FAKTOR);
    		uint32_t model_value = random_between(0, MAX_MODEL_VALUE);
    		void *data_to_compress1 = generate_random_test_data(samples, data_type);
    		void *data_to_compress2 = generate_random_test_data(samples, data_type);
    		void *updated_model = calloc(1, cmp_cal_size_of_data(samples, data_type));
    		/* for (cmp_mode = CMP_MODE_RAW; cmp_mode <= CMP_MODE_STUFF; cmp_mode++) { */
    		for (cmp_mode = CMP_MODE_RAW; cmp_mode <= CMP_MODE_DIFF_MULTI; cmp_mode++) {
    			/* printf("cmp_mode: %i\n", cmp_mode); */
    			cfg = cmp_cfg_icu_create(data_type, cmp_mode, model_value,
    						 CMP_LOSSLESS);
    			TEST_ASSERT_NOT_EQUAL_INT(cfg.data_type, DATA_TYPE_UNKNOWN);
    
    			generate_random_cmp_par(&cfg);
    
    			if (!model_mode_is_used(cmp_mode))
    				cmp_buffer_size = cmp_cfg_icu_buffers(&cfg, data_to_compress1,
    					samples, NULL, NULL, NULL, samples*CMP_BUFFER_FAKTOR);
    			else
    				cmp_buffer_size = cmp_cfg_icu_buffers(&cfg, data_to_compress2,
    					samples, data_to_compress1, updated_model, NULL, samples*CMP_BUFFER_FAKTOR);
    
    			TEST_ASSERT_EQUAL_INT(cmp_buffer_size, cmp_cal_size_of_data(CMP_BUFFER_FAKTOR*samples, data_type));
    
    			compression_decompression(&cfg);
    		}
    		free(data_to_compress1);
    		free(data_to_compress2);
    		free(updated_model);
    	}
    	compression_decompression(NULL);
    }
    
    #define N_SAMPLES 5
    
    void test_random_compression_decompression2(void)
    {
    	struct cmp_cfg cfg;
    	struct cmp_info info = {0};
    	uint32_t cmp_buffer_size;
    	int s, i, cmp_size_bits;
    	void *compressed_data;
    	uint16_t *decompressed_data;
    	uint16_t data[N_SAMPLES] = {0, UINT16_MAX, INT16_MAX, 42, 23};
    
    	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_RAW, 8, CMP_LOSSLESS);
    	TEST_ASSERT_NOT_EQUAL_INT(cfg.data_type, DATA_TYPE_UNKNOWN);
    
    	cmp_buffer_size = cmp_cfg_icu_buffers(&cfg, data, N_SAMPLES, NULL, NULL,
    					      NULL, N_SAMPLES*CMP_BUFFER_FAKTOR);
    	compressed_data = malloc(cmp_buffer_size);
    	cmp_buffer_size = cmp_cfg_icu_buffers(&cfg, data, N_SAMPLES, NULL, NULL,
    					      compressed_data, N_SAMPLES*CMP_BUFFER_FAKTOR);
    	TEST_ASSERT_EQUAL_INT(cmp_buffer_size, cmp_cal_size_of_data(CMP_BUFFER_FAKTOR*N_SAMPLES, DATA_TYPE_IMAGETTE));
    
    	cmp_size_bits = icu_compress_data(&cfg);
    	TEST_ASSERT(cmp_size_bits > 0);
    	info.cmp_size = cmp_size_bits;
    	info.cmp_mode_used = (uint8_t)cfg.cmp_mode;
    	info.model_value_used = (uint8_t)cfg.model_value;
    	info.round_used = (uint8_t)cfg.round;
    	info.spill_used = cfg.spill;
    	info.golomb_par_used = cfg.golomb_par;
    	info.samples_used = cfg.samples;
    	info.rdcu_new_model_adr_used = cfg.rdcu_new_model_adr;
    	info.rdcu_cmp_adr_used = cfg.rdcu_buffer_adr;
    
    	s = decompress_rdcu_data(compressed_data, &info, NULL, NULL, NULL);
    	TEST_ASSERT(s > 0);
    	decompressed_data = malloc(s);
    	s = decompress_rdcu_data(compressed_data, &info, NULL, NULL, decompressed_data);
    	TEST_ASSERT(s > 0);
    
    	for (i = 0; i < N_SAMPLES; i++)
    		TEST_ASSERT_EQUAL_HEX16(data[i], decompressed_data[i]);
    
    
    	free(compressed_data);
    	free(decompressed_data);
    }