diff --git a/lib/common/byteorder.h b/lib/common/byteorder.h index 4b58a45658958e168b8b0dab51ee21eeba6a5d6a..634e184324ffbac06efd89a41d7f563bbd51b6c5 100644 --- a/lib/common/byteorder.h +++ b/lib/common/byteorder.h @@ -53,16 +53,30 @@ #undef __LITTLE_ENDIAN #endif -#if defined(__sparc__) #ifndef __BIG_ENDIAN -#define __BIG_ENDIAN 4321 -#endif +# if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +# define __BIG_ENDIAN 4321 +# elif defined(__clang__) && __BIG_ENDIAN__ +# define __BIG_ENDIAN 4321 +# elif defined(__sparc__) +# define __BIG_ENDIAN 4321 +# endif #endif -#if defined(__i386__) || defined(__x86_64__) #ifndef __LITTLE_ENDIAN -#define __LITTLE_ENDIAN 1234 +# if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) +# define __LITTLE_ENDIAN 1234 +# elif defined(__clang__) && __LITTLE_ENDIAN__ +# define __LITTLE_ENDIAN 1234 +# elif defined(_MSC_VER) && (_M_AMD64 || _M_IX86) +# define __LITTLE_ENDIAN 1234 +# elif defined(__i386__) || defined(__x86_64__) +# define __LITTLE_ENDIAN 1234 +# endif #endif + +#if defined(__BIG_ENDIAN) == defined(__LITTLE_ENDIAN) +#error "Unknown byte order!" #endif diff --git a/lib/common/cmp_data_types.c b/lib/common/cmp_data_types.c index bba86c89ddf92ea9191cc6f37b004ec8f8a4d19d..f548702fb487d89d68b8f3dae91c63c724afaa02 100644 --- a/lib/common/cmp_data_types.c +++ b/lib/common/cmp_data_types.c @@ -885,7 +885,7 @@ int be_to_cpu_data_type(void *data, uint32_t data_size_byte, enum cmp_data_type } samples = data_size_byte / sample_size; -#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) +#ifdef __LITTLE_ENDIAN switch (data_type) { case DATA_TYPE_IMAGETTE: case DATA_TYPE_IMAGETTE_ADAPTIVE: @@ -949,7 +949,7 @@ int be_to_cpu_data_type(void *data, uint32_t data_size_byte, enum cmp_data_type return -1; /* LCOV_EXCL_STOP */ } -#endif /*__BYTE_ORDER__ */ +#endif /* __LITTLE_ENDIAN */ return 0; } diff --git a/lib/common/cmp_debug.c b/lib/common/cmp_debug.c new file mode 100644 index 0000000000000000000000000000000000000000..db1645d40c8a4bef8d44cb91c91949fa33dded0f --- /dev/null +++ b/lib/common/cmp_debug.c @@ -0,0 +1,87 @@ +/** + * @file cmp_debug.c + * @author Dominik Loidolt (dominik.loidolt@univie.ac.at) + * @date 2024 + * + * @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 compression/decompression debugging printing functions + */ + + +#ifndef ICU_ASW +# include <stdio.h> +#endif +#include <string.h> +#include <stdarg.h> + +#include "cmp_debug.h" +#include "compiler.h" +#include "vsnprintf.h" + + +/** + * @brief outputs a debug string + * + * This function outputs a string for debugging purposes + * + * @param str The string to output + */ + +static void cmp_debug_puts(const char *str) +{ +#ifdef ICU_ASW + /* XXX adapt it to your needs */ + /* asw_puts(str); */ + (void)str; +#else + fputs(str, stderr); + fputs("\n", stderr); +#endif +} + + +/** + * @brief implements debug printing + * + * This function formats a string and prints it for debugging. It uses a static + * buffer to format the string + * + * @param fmt pointer to a null-terminated byte string specifying how to + * interpret the data + * @param ... arguments specifying data to print + */ + +void cmp_debug_print_impl(const char *fmt, ...) +{ + static char print_buffer[PRINT_BUFFER_SIZE]; + int len; + va_list args; + + va_start(args, fmt); + len = my_vsnprintf(print_buffer, sizeof(print_buffer)-1, fmt, args); + va_end(args); + + if (len < 0) { + const char str[] = "my_snprintf is broken"; + + compile_time_assert(sizeof(str) <= sizeof(print_buffer), CMP_DEBUG_PRINT_BUFFER_SIZE_TO_SMALL); + memcpy(print_buffer, str, sizeof(str)); + } + if ((size_t)len >= sizeof(print_buffer)-1) { + const char str[] = "cmp_debug print_buffer too small"; + + compile_time_assert(sizeof(str) <= sizeof(print_buffer), CMP_DEBUG_PRINT_BUFFER_SIZE_TO_SMALL); + memcpy(print_buffer, str, sizeof(str)); + } + + cmp_debug_puts(print_buffer); +} diff --git a/lib/common/cmp_debug.h b/lib/common/cmp_debug.h index f95dc2e96964cef2ba81c41f8d1675740606c42a..df599117bf614d4f09b377e0e8d74c84db94d52d 100644 --- a/lib/common/cmp_debug.h +++ b/lib/common/cmp_debug.h @@ -13,7 +13,7 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * @brief compression/decompression debugging defines + * @brief compression/decompression debugging printing functions */ #ifndef CMP_DEBUG_H @@ -26,17 +26,16 @@ # define DEBUGLEVEL 0 #endif -#if !defined(ICU_ASW) && (defined(DEBUG) || DEBUGLEVEL > 0) - #include <stdio.h> - __extension__ - #define debug_print(...) \ - do { \ - fprintf(stderr, __VA_ARGS__); \ - fprintf(stderr, "\n"); \ - } while (0) + +#define PRINT_BUFFER_SIZE 256 + +__extension__ +#if (defined(DEBUG) || DEBUGLEVEL > 0) +# define debug_print(...) cmp_debug_print_impl(__VA_ARGS__) #else - #define debug_print(...) \ - do {} while (0) +# define debug_print(...) do {} while (0) #endif +void cmp_debug_print_impl(const char *fmt, ...); + #endif /* CMP_DEBUG_H */ diff --git a/lib/common/cmp_entity.c b/lib/common/cmp_entity.c index 46df7e957266a35fa69606ac94a8969527455ec0..73f91679fff990a72c93aa0b34da6c586c8ffac3 100644 --- a/lib/common/cmp_entity.c +++ b/lib/common/cmp_entity.c @@ -1863,23 +1863,7 @@ int cmp_ent_write_cmp_pars(struct cmp_entity *ent, const struct cmp_cfg *cfg, if (cmp_ent_set_ima_golomb_par(ent, cfg->golomb_par)) return -1; break; - case DATA_TYPE_OFFSET: - case DATA_TYPE_F_CAM_OFFSET: - case DATA_TYPE_BACKGROUND: - case DATA_TYPE_F_CAM_BACKGROUND: - case DATA_TYPE_SMEARING: - case DATA_TYPE_S_FX: - case DATA_TYPE_S_FX_EFX: - case DATA_TYPE_S_FX_NCOB: - case DATA_TYPE_S_FX_EFX_NCOB_ECOB: - case DATA_TYPE_L_FX: - case DATA_TYPE_L_FX_EFX: - case DATA_TYPE_L_FX_NCOB: - case DATA_TYPE_L_FX_EFX_NCOB_ECOB: - case DATA_TYPE_F_FX: - case DATA_TYPE_F_FX_EFX: - case DATA_TYPE_F_FX_NCOB: - case DATA_TYPE_F_FX_EFX_NCOB_ECOB: + case DATA_TYPE_CHUNK: if (cmp_ent_set_non_ima_cmp_par1(ent, cfg->cmp_par_1)) return -1; if (cmp_ent_set_non_ima_spill1(ent, cfg->spill_par_1)) @@ -1911,6 +1895,24 @@ int cmp_ent_write_cmp_pars(struct cmp_entity *ent, const struct cmp_cfg *cfg, return -1; break; + /* the compression entity data type field only supports imagette or chunk data types*/ + case DATA_TYPE_OFFSET: + case DATA_TYPE_F_CAM_OFFSET: + case DATA_TYPE_BACKGROUND: + case DATA_TYPE_F_CAM_BACKGROUND: + case DATA_TYPE_SMEARING: + case DATA_TYPE_S_FX: + case DATA_TYPE_S_FX_EFX: + case DATA_TYPE_S_FX_NCOB: + case DATA_TYPE_S_FX_EFX_NCOB_ECOB: + case DATA_TYPE_L_FX: + case DATA_TYPE_L_FX_EFX: + case DATA_TYPE_L_FX_NCOB: + case DATA_TYPE_L_FX_EFX_NCOB_ECOB: + case DATA_TYPE_F_FX: + case DATA_TYPE_F_FX_EFX: + case DATA_TYPE_F_FX_NCOB: + case DATA_TYPE_F_FX_EFX_NCOB_ECOB: case DATA_TYPE_UNKNOWN: default: return -1; diff --git a/lib/common/compiler.h b/lib/common/compiler.h index 983ffa46d046fa6bafbf102a8271387741ea0c6c..dc6e7a90ab577f01f4918d82576bba0144a54ffa 100644 --- a/lib/common/compiler.h +++ b/lib/common/compiler.h @@ -37,13 +37,6 @@ #endif -/** - * Compile time check usable outside of function scope. - * Stolen from Linux (hpi_internal.h) - */ -#define compile_time_assert(cond, msg) typedef char ASSERT_##msg[(cond) ? 1 : -1] - - /** * same with the stuff below */ @@ -127,7 +120,7 @@ * It also tries to prevent the actual use of the "unused" variables. */ -#if GNUC_PREREQ(4, 5) +#if GNUC_PREREQ(4, 5) || defined(__clang__) #define UNUSED __attribute__((unused)) \ __attribute__((deprecated ("parameter declared as UNUSED"))) #elif defined(__GNUC__) @@ -154,4 +147,11 @@ #endif +/** + * Compile time check usable outside of function scope. + * Stolen from Linux (hpi_internal.h) + */ +#define compile_time_assert(cond, msg) UNUSED typedef char ASSERT_##msg[(cond) ? 1 : -1] + + #endif /* COMPILER_H */ diff --git a/lib/common/leon_inttypes.h b/lib/common/leon_inttypes.h index 694af3e1e217129e775ee5d7a5ba5656be2b206a..7374e27465c58a0fae6367cd0a3d21eceb2e6619 100644 --- a/lib/common/leon_inttypes.h +++ b/lib/common/leon_inttypes.h @@ -49,6 +49,8 @@ # define PRIX32 "lX" #endif /*PRIX32*/ +#if 0 +/* sparc-elf-gcc (BCC 4.4.2 release 1.0.50) does not support printf for long long types */ #ifndef PRId64 # define PRId64 "lld" #endif /*PRId64*/ @@ -72,6 +74,7 @@ #ifndef PRIX64 # define PRIX64 "llX" #endif /*PRIX64*/ +#endif #endif /* __sparc__ */ diff --git a/lib/common/meson.build b/lib/common/meson.build index c4d8b68cca24c0148eddfc042604639d236760dd..f24b91bfd2db2b20694b5f6fd2312f2a448e26a9 100644 --- a/lib/common/meson.build +++ b/lib/common/meson.build @@ -1,6 +1,8 @@ common_sources = files([ 'cmp_data_types.c', + 'cmp_debug.c', 'cmp_entity.c', 'cmp_max_used_bits.c', - 'cmp_support.c' + 'cmp_support.c', + 'vsnprintf.c' ]) diff --git a/lib/common/vsnprintf.c b/lib/common/vsnprintf.c new file mode 100644 index 0000000000000000000000000000000000000000..ef5cc57887f13a8a4ae200ea77043c11992efd6d --- /dev/null +++ b/lib/common/vsnprintf.c @@ -0,0 +1,885 @@ +/* + * @author (c) Marco Paland (info@paland.com) + * 2014-2019, PALANDesign Hannover, Germany + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @brief Tiny vsnprintf implementation, optimized for speed on embedded systems + * with a very limited resources. These routines are thread safe and + * reentrant! + */ + +#include <stdbool.h> +#include <stdint.h> +#include <stddef.h> +#include <stdarg.h> +#include <math.h> + +#include "vsnprintf.h" + +#define PRINTF_DISABLE_SUPPORT_EXPONENTIAL + +/* + * define this globally (e.g. gcc -DPRINTF_INCLUDE_CONFIG_H ...) to include the + * printf_config.h header file + * default: undefined + */ +#ifdef PRINTF_INCLUDE_CONFIG_H +#include "printf_config.h" +#endif + + +/* + * 'ntoa' conversion buffer size, this must be big enough to hold one converted + * numeric number including padded zeros (dynamically created on stack) + * default: 32 byte + */ +#ifndef PRINTF_NTOA_BUFFER_SIZE +#define PRINTF_NTOA_BUFFER_SIZE 32U +#endif + +/* + * 'ftoa' conversion buffer size, this must be big enough to hold one converted + * float number including padded zeros (dynamically created on stack) + * default: 32 byte + */ +#ifndef PRINTF_FTOA_BUFFER_SIZE +#define PRINTF_FTOA_BUFFER_SIZE 32U +#endif + +/* + * support for the floating point type (%f) + * default: activated + */ +#ifndef PRINTF_DISABLE_SUPPORT_FLOAT +#define PRINTF_SUPPORT_FLOAT +#endif + +/* + * support for exponential floating point notation (%e/%g) + * default: + */ +#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL +#define PRINTF_SUPPORT_EXPONENTIAL +#endif + +/* + * define the default floating point precision + * default: 6 digits + */ +#ifndef PRINTF_DEFAULT_FLOAT_PRECISION +#define PRINTF_DEFAULT_FLOAT_PRECISION 6U +#endif + +/* + * define the largest float suitable to print with %f + * default: 1e9 + */ +#ifndef PRINTF_MAX_FLOAT +#define PRINTF_MAX_FLOAT 1e9 +#endif + +/* + * support for the long long types (%llu or %p) + * default: activated + */ +#ifndef PRINTF_DISABLE_SUPPORT_LONG_LONG +#define PRINTF_SUPPORT_LONG_LONG +#endif + +/* + * support for the ptrdiff_t type (%t) + * ptrdiff_t is normally defined in <stddef.h> as long or long long type + * default: activated + */ +#ifndef PRINTF_DISABLE_SUPPORT_PTRDIFF_T +#define PRINTF_SUPPORT_PTRDIFF_T +#endif + + +/* internal flag definitions */ +#define FLAGS_ZEROPAD (1U << 0U) +#define FLAGS_LEFT (1U << 1U) +#define FLAGS_PLUS (1U << 2U) +#define FLAGS_SPACE (1U << 3U) +#define FLAGS_HASH (1U << 4U) +#define FLAGS_UPPERCASE (1U << 5U) +#define FLAGS_CHAR (1U << 6U) +#define FLAGS_SHORT (1U << 7U) +#define FLAGS_LONG (1U << 8U) +#define FLAGS_LONG_LONG (1U << 9U) +#define FLAGS_PRECISION (1U << 10U) +#define FLAGS_ADAPT_EXP (1U << 11U) + + +/* import float.h for DBL_MAX */ +#if defined(PRINTF_SUPPORT_FLOAT) +#include <float.h> +#endif + + +/* output function type */ +typedef void (*out_fct_type)(char character, void* buffer, size_t idx, size_t maxlen); + + +/* wrapper (used as buffer) for output function type */ +typedef struct { + void (*fct)(char character, void* arg); + void* arg; +} out_fct_wrap_type; + + +/* internal buffer output */ +static inline void _out_buffer(char character, void* buffer, size_t idx, size_t maxlen) +{ + if (idx < maxlen) { + ((char*)buffer)[idx] = character; + } +} + +/* internal null output */ +static inline void _out_null(char character, void* buffer, size_t idx, size_t maxlen) +{ + (void)character; (void)buffer; (void)idx; (void)maxlen; +} + + +/* + * internal secure strlen + * @returns The length of the string (excluding the terminating 0) limited by 'maxsize' + */ +static inline unsigned int _strnlen_s(const char* str, size_t maxsize) +{ + const char* s; + for (s = str; *s && maxsize--; ++s); + return (unsigned int)(s - str); +} + + +/* + * internal test if char is a digit (0-9) + * @returns true if char is a digit + */ +static inline bool _is_digit(char ch) +{ + return (ch >= '0') && (ch <= '9'); +} + + +/* internal ASCII string to unsigned int conversion */ +static unsigned int _atoi(const char** str) +{ + unsigned int i = 0U; + while (_is_digit(**str)) { + i = i * 10U + (unsigned int)(*((*str)++) - '0'); + } + return i; +} + + +/* output the specified string in reverse, taking care of any zero-padding */ +static size_t _out_rev(out_fct_type out, char* buffer, size_t idx, size_t maxlen, const char* buf, size_t len, unsigned int width, unsigned int flags) +{ + const size_t start_idx = idx; + + /* pad spaces up to given width */ + if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) { + size_t i; + for (i = len; i < width; i++) { + out(' ', buffer, idx++, maxlen); + } + } + + /* reverse string */ + while (len) { + out(buf[--len], buffer, idx++, maxlen); + } + + /* append pad spaces up to given width */ + if (flags & FLAGS_LEFT) { + while (idx - start_idx < width) { + out(' ', buffer, idx++, maxlen); + } + } + + return idx; +} + + +/* internal itoa format */ +static size_t _ntoa_format(out_fct_type out, char* buffer, size_t idx, size_t maxlen, char* buf, size_t len, bool negative, unsigned int base, unsigned int prec, unsigned int width, unsigned int flags) +{ + /* pad leading zeros */ + if (!(flags & FLAGS_LEFT)) { + if (width && (flags & FLAGS_ZEROPAD) && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { + width--; + } + while ((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + while ((flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + } + + /* handle hash */ + if (flags & FLAGS_HASH) { + if (!(flags & FLAGS_PRECISION) && len && ((len == prec) || (len == width))) { + len--; + if (len && (base == 16U)) { + len--; + } + } + if ((base == 16U) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'x'; + } + else if ((base == 16U) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'X'; + } + else if ((base == 2U) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'b'; + } + if (len < PRINTF_NTOA_BUFFER_SIZE) { + buf[len++] = '0'; + } + } + + if (len < PRINTF_NTOA_BUFFER_SIZE) { + if (negative) { + buf[len++] = '-'; + } + else if (flags & FLAGS_PLUS) { + buf[len++] = '+'; /* ignore the space if the '+' exists */ + } + else if (flags & FLAGS_SPACE) { + buf[len++] = ' '; + } + } + + return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags); +} + + +/* internal itoa for 'long' type */ +static size_t _ntoa_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long value, bool negative, unsigned long base, unsigned int prec, unsigned int width, unsigned int flags) +{ + char buf[PRINTF_NTOA_BUFFER_SIZE]; + size_t len = 0U; + + /* no hash for 0 values */ + if (!value) { + flags &= ~FLAGS_HASH; + } + + /* write if precision != 0 and value is != 0 */ + if (!(flags & FLAGS_PRECISION) || value) { + do { + const char digit = (char)(value % base); + buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; + value /= base; + } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); + } + + return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags); +} + + +/* internal itoa for 'long long' type */ +#if defined(PRINTF_SUPPORT_LONG_LONG) +static size_t _ntoa_long_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long long value, bool negative, unsigned long long base, unsigned int prec, unsigned int width, unsigned int flags) +{ + char buf[PRINTF_NTOA_BUFFER_SIZE]; + size_t len = 0U; + + /* no hash for 0 values */ + if (!value) { + flags &= ~FLAGS_HASH; + } + + /* write if precision != 0 and value is != 0 */ + if (!(flags & FLAGS_PRECISION) || value) { + do { + const char digit = (char)(value % base); + buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; + value /= base; + } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); + } + + return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags); +} +#endif /* PRINTF_SUPPORT_LONG_LONG */ + + +#if defined(PRINTF_SUPPORT_FLOAT) + +#if defined(PRINTF_SUPPORT_EXPONENTIAL) +/* forward declaration so that _ftoa can switch to exp notation for values > PRINTF_MAX_FLOAT */ +static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags); +#endif + + +/* internal ftoa for fixed decimal floating point */ +static size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags) +{ + char buf[PRINTF_FTOA_BUFFER_SIZE]; + size_t len = 0U; + double diff = 0.0; + bool negative = false; + int whole; + double tmp; + unsigned long frac; + + /* powers of 10 */ + static const double pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; + + /* test for special values */ + if (isnan(value)) + return _out_rev(out, buffer, idx, maxlen, "nan", 3, width, flags); + if (value < -DBL_MAX) + return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags); + if (value > DBL_MAX) + return _out_rev(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags); + + /* test for very large values */ + /* standard printf behavior is to print EVERY whole number digit -- which could be 100s of characters overflowing your buffers == bad */ + if ((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) { +#if defined(PRINTF_SUPPORT_EXPONENTIAL) + return _etoa(out, buffer, idx, maxlen, value, prec, width, flags); +#else + return 0U; +#endif + } + + /* test for negative */ + if (value < 0) { + negative = true; + value = 0 - value; + } + + /* set default precision, if not set explicitly */ + if (!(flags & FLAGS_PRECISION)) { + prec = PRINTF_DEFAULT_FLOAT_PRECISION; + } + /* limit precision to 9, cause a prec >= 10 can lead to overflow errors */ + while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) { + buf[len++] = '0'; + prec--; + } + + whole = (int)value; + tmp = (value - whole) * pow10[prec]; + frac = (unsigned long)tmp; + diff = tmp - (double)frac; + + if (diff > 0.5) { + ++frac; + /* handle rollover, e.g. case 0.99 with prec 1 is 1.0 */ + if ((double)frac >= pow10[prec]) { + frac = 0; + ++whole; + } + } + else if (diff < 0.5) { + } + else if ((frac == 0U) || (frac & 1U)) { + /* if halfway, round up if odd OR if last digit is 0 */ + ++frac; + } + + if (prec == 0U) { + diff = value - (double)whole; + if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) { + /* exactly 0.5 and ODD, then round up */ + /* 1.5 -> 2, but 2.5 -> 2 */ + ++whole; + } + } + else { + unsigned int count = prec; + /* now do fractional part, as an unsigned number */ + while (len < PRINTF_FTOA_BUFFER_SIZE) { + --count; + buf[len++] = (char)(48U + (frac % 10U)); + if (!(frac /= 10U)) { + break; + } + } + /* add extra 0s */ + while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) { + buf[len++] = '0'; + } + if (len < PRINTF_FTOA_BUFFER_SIZE) { + /* add decimal */ + buf[len++] = '.'; + } + } + + /* do whole part, number is reversed */ + while (len < PRINTF_FTOA_BUFFER_SIZE) { + buf[len++] = (char)(48 + (whole % 10)); + if (!(whole /= 10)) { + break; + } + } + + /* pad leading zeros */ + if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) { + if (width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { + width--; + } + while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + } + + if (len < PRINTF_FTOA_BUFFER_SIZE) { + if (negative) { + buf[len++] = '-'; + } + else if (flags & FLAGS_PLUS) { + buf[len++] = '+'; /* ignore the space if the '+' exists */ + } + else if (flags & FLAGS_SPACE) { + buf[len++] = ' '; + } + } + + return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags); +} + + +#if defined(PRINTF_SUPPORT_EXPONENTIAL) +/* internal ftoa variant for exponential floating-point type, contributed by Martijn Jasperse <m.jasperse@gmail.com> */ +static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags) +{ + const bool negative = value < 0; + union { + uint64_t U; + double F; + } conv; + int exp2, expval; + double z, z2; + unsigned int minwidth, fwidth; + size_t start_idx; + + /* check for NaN and special values */ + if ((value != value || (value > DBL_MAX) || (value < -DBL_MAX)) { + return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags); + } + + /* determine the sign */ + if (value < 0) { + value = -value; + } + + /* default precision */ + if (!(flags & FLAGS_PRECISION)) { + prec = PRINTF_DEFAULT_FLOAT_PRECISION; + } + + /* determine the decimal exponent */ + /* based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c) */ + conv.F = value; + exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023; /* effectively log2 */ + conv.U = (conv.U & ((1ULL << 52U) - 1U)) | (1023ULL << 52U); /* drop the exponent so conv.F is now in [1,2) */ + /* now approximate log10 from the log2 integer part and an expansion of ln around 1.5 */ + expval = (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168); + /* now we want to compute 10^expval but we want to be sure it won't overflow */ + exp2 = (int)(expval * 3.321928094887362 + 0.5); + z = expval * 2.302585092994046 - exp2 * 0.6931471805599453; + z2 = z * z; + conv.U = (uint64_t)(exp2 + 1023) << 52U; + /* compute exp(z) using continued fractions, see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex */ + conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14))))); + /* correct for rounding errors */ + if (value < conv.F) { + expval--; + conv.F /= 10; + } + + /* the exponent format is "%+03d" and largest value is "307", so set aside 4-5 characters */ + minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U; + + /* in "%g" mode, "prec" is the number of *significant figures* not decimals */ + if (flags & FLAGS_ADAPT_EXP) { + /* do we want to fall-back to "%f" mode? */ + if ((value >= 1e-4) && (value < 1e6)) { + if ((int)prec > expval) { + prec = (unsigned)((int)prec - expval - 1); + } + else { + prec = 0; + } + flags |= FLAGS_PRECISION; /* make sure _ftoa respects precision */ + /* no characters in exponent */ + minwidth = 0U; + expval = 0; + } + else { + /* we use one sigfig for the whole part */ + if ((prec > 0) && (flags & FLAGS_PRECISION)) { + --prec; + } + } + } + + /* will everything fit? */ + fwidth = width; + if (width > minwidth) { + /* we didn't fall-back so subtract the characters required for the exponent */ + fwidth -= minwidth; + } else { + /* not enough characters, so go back to default sizing */ + fwidth = 0U; + } + if ((flags & FLAGS_LEFT) && minwidth) { + /* if we're padding on the right, DON'T pad the floating part */ + fwidth = 0U; + } + + /* rescale the float value */ + if (expval) { + value /= conv.F; + } + + /* output the floating part */ + start_idx = idx; + idx = _ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, flags & ~FLAGS_ADAPT_EXP); + + /* output the exponent part */ + if (minwidth) { + /* output the exponential symbol */ + out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen); + /* output the exponent value */ + idx = _ntoa_long(out, buffer, idx, maxlen, (expval < 0) ? -expval : expval, expval < 0, 10, 0, minwidth-1, FLAGS_ZEROPAD | FLAGS_PLUS); + /* might need to right-pad spaces */ + if (flags & FLAGS_LEFT) { + while (idx - start_idx < width) out(' ', buffer, idx++, maxlen); + } + } + return idx; +} +#endif /* PRINTF_SUPPORT_EXPONENTIAL */ +#endif /* PRINTF_SUPPORT_FLOAT */ + + +/* internal vsnprintf */ +static int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const char* format, va_list va) +{ + unsigned int flags, width, precision, n; + size_t idx = 0U; + + if (!buffer) { + /* use null output function */ + out = _out_null; + } + + while (*format) + { + /* format specifier? %[flags][width][.precision][length] */ + if (*format != '%') { + /* no */ + out(*format, buffer, idx++, maxlen); + format++; + continue; + } + else { + /* yes, evaluate it */ + format++; + } + + /* evaluate flags */ + flags = 0U; + do { + switch (*format) { + case '0': flags |= FLAGS_ZEROPAD; format++; n = 1U; break; + case '-': flags |= FLAGS_LEFT; format++; n = 1U; break; + case '+': flags |= FLAGS_PLUS; format++; n = 1U; break; + case ' ': flags |= FLAGS_SPACE; format++; n = 1U; break; + case '#': flags |= FLAGS_HASH; format++; n = 1U; break; + default : n = 0U; break; + } + } while (n); + + /* evaluate width field */ + width = 0U; + if (_is_digit(*format)) { + width = _atoi(&format); + } + else if (*format == '*') { + const int w = va_arg(va, int); + if (w < 0) { + flags |= FLAGS_LEFT; /* reverse padding */ + width = (unsigned int)-w; + } + else { + width = (unsigned int)w; + } + format++; + } + + /* evaluate precision field */ + precision = 0U; + if (*format == '.') { + flags |= FLAGS_PRECISION; + format++; + if (_is_digit(*format)) { + precision = _atoi(&format); + } + else if (*format == '*') { + const int prec = (int)va_arg(va, int); + precision = prec > 0 ? (unsigned int)prec : 0U; + format++; + } + } + + /* evaluate length field */ + switch (*format) { + case 'l' : + flags |= FLAGS_LONG; + format++; + if (*format == 'l') { + flags |= FLAGS_LONG_LONG; + format++; + } + break; + case 'h' : + flags |= FLAGS_SHORT; + format++; + if (*format == 'h') { + flags |= FLAGS_CHAR; + format++; + } + break; +#if defined(PRINTF_SUPPORT_PTRDIFF_T) + case 't' : + flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; +#endif + case 'j' : + flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; + case 'z' : + flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; + default : + break; + } + + /* evaluate specifier */ + switch (*format) { + case 'd' : + case 'i' : + case 'u' : + case 'x' : + case 'X' : + case 'o' : + case 'b' : { + /* set the base */ + unsigned int base; + if (*format == 'x' || *format == 'X') { + base = 16U; + } + else if (*format == 'o') { + base = 8U; + } + else if (*format == 'b') { + base = 2U; + } + else { + base = 10U; + flags &= ~FLAGS_HASH; /* no hash for dec format */ + } + /* uppercase */ + if (*format == 'X') { + flags |= FLAGS_UPPERCASE; + } + + /* no plus or space flag for u, x, X, o, b */ + if ((*format != 'i') && (*format != 'd')) { + flags &= ~(FLAGS_PLUS | FLAGS_SPACE); + } + + /* ignore '0' flag when precision is given */ + if (flags & FLAGS_PRECISION) { + flags &= ~FLAGS_ZEROPAD; + } + + /* convert the integer */ + if ((*format == 'i') || (*format == 'd')) { + /* signed */ + if (flags & FLAGS_LONG_LONG) { +#if defined(PRINTF_SUPPORT_LONG_LONG) + const long long value = va_arg(va, long long); + idx = _ntoa_long_long(out, buffer, idx, maxlen, (unsigned long long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags); +#endif + } + else if (flags & FLAGS_LONG) { + const long value = va_arg(va, long); + idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags); + } + else { + const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int) : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) : va_arg(va, int); + idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned int)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags); + } + } + else { + /* unsigned */ + if (flags & FLAGS_LONG_LONG) { +#if defined(PRINTF_SUPPORT_LONG_LONG) + idx = _ntoa_long_long(out, buffer, idx, maxlen, va_arg(va, unsigned long long), false, base, precision, width, flags); +#endif + } + else if (flags & FLAGS_LONG) { + idx = _ntoa_long(out, buffer, idx, maxlen, va_arg(va, unsigned long), false, base, precision, width, flags); + } + else { + const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned char)va_arg(va, unsigned int) : (flags & FLAGS_SHORT) ? (unsigned short int)va_arg(va, unsigned int) : va_arg(va, unsigned int); + idx = _ntoa_long(out, buffer, idx, maxlen, value, false, base, precision, width, flags); + } + } + format++; + break; + } +#if defined(PRINTF_SUPPORT_FLOAT) + case 'f' : + case 'F' : + if (*format == 'F') flags |= FLAGS_UPPERCASE; + idx = _ftoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags); + format++; + break; +#if defined(PRINTF_SUPPORT_EXPONENTIAL) + case 'e': + case 'E': + case 'g': + case 'G': + if ((*format == 'g')||(*format == 'G')) flags |= FLAGS_ADAPT_EXP; + if ((*format == 'E')||(*format == 'G')) flags |= FLAGS_UPPERCASE; + idx = _etoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags); + format++; + break; +#endif /* PRINTF_SUPPORT_EXPONENTIAL */ +#endif /* PRINTF_SUPPORT_FLOAT */ + case 'c' : { + unsigned int l = 1U; + /* pre padding */ + if (!(flags & FLAGS_LEFT)) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + /* char output */ + out((char)va_arg(va, int), buffer, idx++, maxlen); + /* post padding */ + if (flags & FLAGS_LEFT) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + format++; + break; + } + + case 's' : { + const char* p = va_arg(va, char*); + unsigned int l = _strnlen_s(p, precision ? precision : (size_t)-1); + /* pre padding */ + if (flags & FLAGS_PRECISION) { + l = (l < precision ? l : precision); + } + if (!(flags & FLAGS_LEFT)) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + /* string output */ + while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) { + out(*(p++), buffer, idx++, maxlen); + } + /* post padding */ + if (flags & FLAGS_LEFT) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + format++; + break; + } + + case 'p' : { + width = sizeof(void*) * 2U; + flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE; +#if defined(PRINTF_SUPPORT_LONG_LONG) + if (sizeof(uintptr_t) == sizeof(long long)) { + idx = _ntoa_long_long(out, buffer, idx, maxlen, (uintptr_t)va_arg(va, void*), false, 16U, precision, width, flags); + } + else { +#endif + idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)((uintptr_t)va_arg(va, void*)), false, 16U, precision, width, flags); +#if defined(PRINTF_SUPPORT_LONG_LONG) + } +#endif + format++; + break; + } + + case '%' : + out('%', buffer, idx++, maxlen); + format++; + break; + + default : + out(*format, buffer, idx++, maxlen); + format++; + break; + } + } + + /* termination */ + out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen); + + /* return written chars without terminating \0 */ + return (int)idx; +} + + +/** + * @brief Custom vsnprintf function + * + * This function attempts to write to a buffer with a given size + * It is a wrapper around the a vsnprintf function + * + * @param buffer buffer to write the output + * @param count maximum number of characters to write + * @param format format string + * @param va variable argument list + * + * @return The number of characters written, or a negative value if an error occurs + */ + +int my_vsnprintf(char* buffer, size_t count, const char* format, va_list va) +{ + return _vsnprintf(_out_buffer, buffer, count, format, va); +} + diff --git a/lib/common/vsnprintf.h b/lib/common/vsnprintf.h new file mode 100644 index 0000000000000000000000000000000000000000..8b04ab66f6073027359eb37053a0184a53e5b079 --- /dev/null +++ b/lib/common/vsnprintf.h @@ -0,0 +1,25 @@ +/** + * @file vsnprintf.h + * @author Dominik Loidolt (dominik.loidolt@univie.ac.at) + * @date 2024 + * + * @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 Tiny vsnprintf implementation + */ + + +#ifndef VSNPRINTF_H +#define VSNPRINTF_H + +int my_vsnprintf(char* buffer, size_t count, const char* format, va_list va); + +#endif /* VSNPRINTF_H */ diff --git a/lib/decompress/decmp.c b/lib/decompress/decmp.c index 3c26fbd4ad400e7ebf4641edf3985e5eaa3979f3..e21235043179574e2846210806fee839ba7f486e 100644 --- a/lib/decompress/decmp.c +++ b/lib/decompress/decmp.c @@ -1990,8 +1990,9 @@ static int cmp_ent_read_header(struct cmp_entity *ent, struct cmp_cfg *cfg) return -1; cfg->data_type = cmp_ent_get_data_type(ent); - if (cmp_data_type_is_invalid(cfg->data_type)) { - debug_print("Error: Compression data type not supported."); + /* the compression entity data type field only supports imagette or chunk data types */ + if (cfg->data_type != DATA_TYPE_CHUNK && !rdcu_supported_data_type_is_used(cfg->data_type)) { + debug_print("Error: Compression entity data type not supported."); return -1; } diff --git a/lib/decompress/read_bitstream.h b/lib/decompress/read_bitstream.h index c65090eac4074d12fcd087fa43d193c3c4ade4fa..f46804c1841315a5e7e912aea4da13fccbc84cf6 100644 --- a/lib/decompress/read_bitstream.h +++ b/lib/decompress/read_bitstream.h @@ -106,8 +106,15 @@ static const uint32_t BIT_MASK[] = { static __inline uint64_t bit_read_unaligned_64be(const void *ptr) { +#ifdef __sparc__ + uint64_t v; + memcpy(&v, ptr, sizeof(v)); + return cpu_to_be64(v); + +#else typedef __attribute__((aligned(1))) uint64_t unalign64; return cpu_to_be64(*(const unalign64*)ptr); +#endif } @@ -184,7 +191,6 @@ static __inline size_t bit_init_decoder(struct bit_decoder *dec, const void *buf * * @returns extracted value */ - static __inline uint64_t bit_peek_bits(const struct bit_decoder *dec, unsigned int nb_bits) { /* mask for the shift value register to prevent undefined behaviour */ diff --git a/lib/rdcu_compress/rdcu_ctrl.c b/lib/rdcu_compress/rdcu_ctrl.c index 0c23b5bf7396386f886ff763ada7552f6b454bd7..c5d748e34ceefc27c7c0368df3299f45ec7fd5aa 100644 --- a/lib/rdcu_compress/rdcu_ctrl.c +++ b/lib/rdcu_compress/rdcu_ctrl.c @@ -1653,9 +1653,9 @@ int rdcu_write_sram_16(const uint16_t *buf, uint32_t addr, uint32_t size) if (addr + size > RDCU_SRAM_START + RDCU_SRAM_SIZE) return -1; -#if !(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) +#ifdef __BIG_ENDIAN return rdcu_write_sram(buf, addr, size); -#else +#elif defined(__LITTLE_ENDIAN) { uint32_t i; @@ -1666,7 +1666,9 @@ int rdcu_write_sram_16(const uint16_t *buf, uint32_t addr, uint32_t size) } } return (int)size; /* lol */ -#endif /* __BYTE_ORDER__ */ +#else +#error "Unknown byte order!" +#endif } @@ -1699,9 +1701,9 @@ int rdcu_write_sram_32(const uint32_t *buf, uint32_t addr, uint32_t size) if (addr + size > RDCU_SRAM_START + RDCU_SRAM_SIZE) return -1; -#if !(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) +#ifdef __BIG_ENDIAN return rdcu_write_sram(buf, addr, size); -#else +#elif defined(__LITTLE_ENDIAN) { uint32_t i; @@ -1712,7 +1714,9 @@ int rdcu_write_sram_32(const uint32_t *buf, uint32_t addr, uint32_t size) } } return (int)size; /* lol */ -#endif /* __BYTE_ORDER__ */ +#else +#error "Unknown byte order!" +#endif } diff --git a/lib/rdcu_compress/rdcu_rmap.c b/lib/rdcu_compress/rdcu_rmap.c index 7a740e8c205585a62be58ed05bd0960e89e6b217..dc7c71a5dfd259ce0b43a9d03a79a1bf87bdab90 100644 --- a/lib/rdcu_compress/rdcu_rmap.c +++ b/lib/rdcu_compress/rdcu_rmap.c @@ -292,7 +292,7 @@ static int rdcu_process_rx(void) uint8_t crc8; /* convert endianness in-place if needed */ -#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) +#ifdef __LITTLE_ENDIAN { uint32_t i, tmp; @@ -302,7 +302,7 @@ static int rdcu_process_rx(void) memcpy(&rp->data[i], &tmp, sizeof(tmp)); } } -#endif /* __BYTE_ORDER__ */ +#endif /* __LITTLE_ENDIAN */ crc8 = rmap_crc8(rp->data, rp->data_len); if (crc8 != rp->data_crc) { @@ -471,7 +471,7 @@ int rdcu_sync(int (*fn)(uint16_t trans_id, uint8_t *cmd), } /* convert endianness if needed */ -#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) +#ifdef __LITTLE_ENDIAN if (data_len) { uint32_t i; uint32_t *tmp_buf = alloca(data_len); @@ -482,7 +482,7 @@ int rdcu_sync(int (*fn)(uint16_t trans_id, uint8_t *cmd), addr = tmp_buf; } -#endif /* __BYTE_ORDER__ */ +#endif /* __LITTLE_ENDIAN */ n = rdcu_submit_tx(rmap_cmd, (uint32_t)n, addr, data_len); free(rmap_cmd); diff --git a/lib/rdcu_compress/rmap.h b/lib/rdcu_compress/rmap.h index 3dde00952ef8241ea944406b67f622463d83b562..9c217804b37300e8fa9414af3b6368870436236a 100644 --- a/lib/rdcu_compress/rmap.h +++ b/lib/rdcu_compress/rmap.h @@ -23,6 +23,7 @@ #include <stddef.h> #include "../common/compiler.h" +#include "../common/byteorder.h" /** * valid RMAP command codes, see Table 5-1 of ECSS‐E‐ST‐50‐52C @@ -142,12 +143,12 @@ __extension__ struct rmap_instruction { -#if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +#ifdef __BIG_ENDIAN uint8_t reserved:1; uint8_t cmd_resp:1; uint8_t cmd:4; uint8_t reply_addr_len:2; -#elif (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) +#elif defined (__LITTLE_ENDIAN) uint8_t reply_addr_len:2; uint8_t cmd:4; uint8_t cmd_resp:1; diff --git a/test/cmp_decmp/test_cmp_decmp.c b/test/cmp_decmp/test_cmp_decmp.c index 1331f3de4fb4c775da781436081ffbffa51ca53c..d4959caafe5dfd124cbdc1eab17c3bd900a339db 100644 --- a/test/cmp_decmp/test_cmp_decmp.c +++ b/test/cmp_decmp/test_cmp_decmp.c @@ -15,14 +15,14 @@ * * @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. + * After that we decompress the compression entity and compare the + * decompressed data with the original data. */ #include <string.h> #include <stdlib.h> +#include <stdio.h> #include <unity.h> #include "../test_common/test_common.h" @@ -32,6 +32,7 @@ #include <decmp.h> #include <cmp_data_types.h> #include <leon_inttypes.h> +#include <byteorder.h> #if defined __has_include # if __has_include(<time.h>) @@ -41,13 +42,11 @@ # 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 ROUND_UP_TO_MULTIPLE_OF_4(x) (((x) + 3) & ~3) + /** - * @brief Seeds the pseudo-random number generator used by rand() + * @brief Seeds the pseudo-random number generator */ void setUp(void) @@ -55,28 +54,49 @@ void setUp(void) uint64_t seed; static int n; -#if HAS_TIME_H +#ifdef HAS_TIME_H seed = (uint64_t)(time(NULL) ^ getpid() ^ (intptr_t)&setUp); #else seed = 1; #endif if (!n) { + uint32_t high = seed >> 32; + uint32_t low = seed & 0xFFFFFFFF; n = 1; cmp_rand_seed(seed); - printf("seed: %"PRIu64"\n", seed); + printf("seed: 0x%08"PRIx32"%08"PRIx32"\n", high, low); } } -static size_t gen_ima_data(uint16_t *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) +static size_t gen_ima_data(uint16_t *data, enum cmp_data_type data_type, + uint32_t samples, const struct cmp_max_used_bits *max_used_bits) { uint32_t i; - if (data) + if (data) { + uint32_t max_data_bits; + + switch (data_type) { + case DATA_TYPE_IMAGETTE: + case DATA_TYPE_IMAGETTE_ADAPTIVE: + max_data_bits = max_used_bits->nc_imagette; + break; + case DATA_TYPE_SAT_IMAGETTE: + case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE: + max_data_bits = max_used_bits->saturated_imagette; + break; + case DATA_TYPE_F_CAM_IMAGETTE: + case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE: + max_data_bits = max_used_bits->fc_imagette; + break; + default: + TEST_FAIL(); + } for (i = 0; i < samples; i++) - data[i] = (uint16_t)cmp_rand_nbits(max_used_bits->nc_imagette); + data[i] = (uint16_t)cmp_rand_nbits(max_data_bits); + } return sizeof(*data) * samples; } @@ -365,86 +385,8 @@ static size_t gen_l_fx_efx_ncob_ecob_data(struct l_fx_efx_ncob_ecob *data, uint3 } -static uint8_t get_sst(enum cmp_data_type data_type) -{ - uint8_t sst = 0; - - switch (data_type) { - case DATA_TYPE_IMAGETTE: - case DATA_TYPE_IMAGETTE_ADAPTIVE: - sst = SST_NCxx_S_SCIENCE_IMAGETTE; - break; - case DATA_TYPE_SAT_IMAGETTE: - case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE: - sst = SST_NCxx_S_SCIENCE_SAT_IMAGETTE; - break; - case DATA_TYPE_OFFSET: - sst = SST_NCxx_S_SCIENCE_OFFSET; - break; - case DATA_TYPE_BACKGROUND: - sst = SST_NCxx_S_SCIENCE_BACKGROUND; - break; - case DATA_TYPE_SMEARING: - sst = SST_NCxx_S_SCIENCE_SMEARING; - break; - case DATA_TYPE_S_FX: - sst = SST_NCxx_S_SCIENCE_S_FX; - break; - case DATA_TYPE_S_FX_EFX: - sst = SST_NCxx_S_SCIENCE_S_FX_EFX; - break; - case DATA_TYPE_S_FX_NCOB: - sst = SST_NCxx_S_SCIENCE_S_FX_NCOB; - break; - case DATA_TYPE_S_FX_EFX_NCOB_ECOB: - sst = SST_NCxx_S_SCIENCE_S_FX_EFX_NCOB_ECOB; - break; - case DATA_TYPE_L_FX: - sst = SST_NCxx_S_SCIENCE_L_FX; - break; - case DATA_TYPE_L_FX_EFX: - sst = SST_NCxx_S_SCIENCE_L_FX_EFX; - break; - case DATA_TYPE_L_FX_NCOB: - sst = SST_NCxx_S_SCIENCE_L_FX_NCOB; - break; - case DATA_TYPE_L_FX_EFX_NCOB_ECOB: - sst = SST_NCxx_S_SCIENCE_L_FX_EFX_NCOB_ECOB; - break; - case DATA_TYPE_F_FX: - sst = SST_NCxx_S_SCIENCE_F_FX; - break; - case DATA_TYPE_F_FX_EFX: - sst = SST_NCxx_S_SCIENCE_F_FX_EFX; - break; - case DATA_TYPE_F_FX_NCOB: - sst = SST_NCxx_S_SCIENCE_F_FX_NCOB; - break; - case DATA_TYPE_F_FX_EFX_NCOB_ECOB: - sst = SST_NCxx_S_SCIENCE_F_FX_EFX_NCOB_ECOB; - break; - case DATA_TYPE_F_CAM_IMAGETTE: - case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE: - sst = SST_FCx_S_SCIENCE_IMAGETTE; - break; - case DATA_TYPE_F_CAM_OFFSET: - sst = SST_FCx_S_SCIENCE_OFFSET_VALUES; - break; - case DATA_TYPE_F_CAM_BACKGROUND: - sst = SST_FCx_S_BACKGROUND_VALUES; - break; - default: - case DATA_TYPE_UNKNOWN: - TEST_FAIL(); - /* debug_print("Error: Unknown compression data type!\n"); */ - }; - - return sst; -} - - -size_t generate_random_collection_hdr(struct collection_hdr *col, enum cmp_data_type data_type, - uint32_t samples) +uint32_t generate_random_collection_hdr(struct collection_hdr *col, enum cmp_data_type data_type, + uint32_t samples) { static uint8_t sequence_num; size_t data_size = size_of_a_sample(data_type)*samples; @@ -452,11 +394,15 @@ size_t generate_random_collection_hdr(struct collection_hdr *col, enum cmp_data_ TEST_ASSERT(data_size <= UINT16_MAX); if (col) { +#ifdef HAS_TIME_H TEST_ASSERT_FALSE(cmp_col_set_timestamp(col, cmp_ent_create_timestamp(NULL))); +#else + TEST_ASSERT_FALSE(cmp_col_set_timestamp(col, 0x150D15AB1ED)); +#endif TEST_ASSERT_FALSE(cmp_col_set_configuration_id(col, (uint16_t)cmp_rand32())); TEST_ASSERT_FALSE(cmp_col_set_pkt_type(col, COL_SCI_PKTS_TYPE)); - TEST_ASSERT_FALSE(cmp_col_set_subservice(col, get_sst(data_type))); + TEST_ASSERT_FALSE(cmp_col_set_subservice(col, convert_cmp_data_type_to_subservice(data_type))); TEST_ASSERT_FALSE(cmp_col_set_ccd_id(col, (uint8_t)cmp_rand_between(0, 3))); TEST_ASSERT_FALSE(cmp_col_set_sequence_num(col, sequence_num++)); @@ -467,13 +413,17 @@ size_t generate_random_collection_hdr(struct collection_hdr *col, enum cmp_data_ /** - * @brief generate random test data + * @brief generates a random collection (with header) * - * @param samples number of random test samples - * @param data_type compression data type of the test data - * @param max_used_bits pointer to a max_used_bits structure + * @param col pointer to where the random collection will be stored; + * if NULL, the function will only return the size of the + * random collection + * @param data_type specifies the compression data type of the test data + * @param samples the number of random test data samples to generate + * @param max_used_bits pointer to a structure that tracks the maximum number of + * bits used * - * @returns a pointer to the generated random test data + * @return the size of the generated random collection in bytes */ size_t generate_random_collection(struct collection_hdr *col, enum cmp_data_type data_type, @@ -485,22 +435,17 @@ size_t generate_random_collection(struct collection_hdr *col, enum cmp_data_type if (col) science_data = col->entry; - if (rdcu_supported_data_type_is_used(data_type)) { - /* for the rdcu the header counts as data */ - size_t hdr_in_samples = COLLECTION_HDR_SIZE/size_of_a_sample(data_type); - TEST_ASSERT(samples >= hdr_in_samples); - samples -= hdr_in_samples; - } - size = generate_random_collection_hdr(col, data_type, samples); - /* TDOO remove me */ - int i; - for (i = 0; i < size_of_a_sample(data_type)*samples; ++i) { - if (col){ - col->entry[i] = i; +#if 0 + { int i; + + for (i = 0; i < size_of_a_sample(data_type)*samples; i++) { + if (col) + col->entry[i] = i; } + return size+i; } - return size+i; +#endif switch (data_type) { case DATA_TYPE_IMAGETTE: @@ -509,7 +454,7 @@ size_t generate_random_collection(struct collection_hdr *col, enum cmp_data_type case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE: case DATA_TYPE_F_CAM_IMAGETTE: case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE: - size += gen_ima_data(science_data, samples, max_used_bits); + size += gen_ima_data(science_data, data_type, samples, max_used_bits); break; case DATA_TYPE_OFFSET: size += gen_nc_offset_data(science_data, samples, max_used_bits); @@ -566,6 +511,9 @@ size_t generate_random_collection(struct collection_hdr *col, enum cmp_data_type TEST_FAIL(); } + if (col) + TEST_ASSERT_EQUAL_UINT(size, cmp_col_get_size(col)); + return size; } @@ -575,11 +523,25 @@ struct chunk_def { }; -static size_t generate_random_chunk(void *chunk, struct chunk_def col_array[], size_t array_elements, +/** + * @brief generates a random chunk of collections + * + * @param chunk pointer to where the random chunk will be stored; if + * NULL, the function will only return the size of the + * random chunk + * @param col_array specifies which collections are contained in the chunk + * @param array_elements number of elements in the col_array + * @param max_used_bits pointer to a structure that tracks the maximum number of + * bits used + * + * @return the size of the generated random chunk in bytes + */ + +static uint32_t generate_random_chunk(void *chunk, struct chunk_def col_array[], size_t array_elements, const struct cmp_max_used_bits *max_used_bits) { size_t i; - size_t chunk_size = 0; + uint32_t chunk_size = 0; struct collection_hdr *col = NULL; for (i = 0; i < array_elements; i++) { @@ -599,7 +561,7 @@ static size_t generate_random_chunk(void *chunk, struct chunk_def col_array[], s * @param cfg pointer to a compression configuration */ -void generate_random_cmp_par(struct cmp_cfg *cfg) +void generate_random_cmp_cfg(struct cmp_cfg *cfg) { if (cmp_imagette_data_type_is_used(cfg->data_type)) { cfg->cmp_par_imagette = cmp_rand_between(MIN_IMA_GOLOMB_PAR, MAX_IMA_GOLOMB_PAR); @@ -644,6 +606,56 @@ void generate_random_cmp_par(struct cmp_cfg *cfg) } +/** + * @brief generate random chunk compression parameters + * + * @param par pointer where to store the chunk compression + */ + +void generate_random_cmp_par(struct cmp_par *par) +{ + if (par) { + par->cmp_mode = cmp_rand_between(0, MAX_RDCU_CMP_MODE); + par->model_value = cmp_rand_between(0, MAX_MODEL_VALUE); + par->lossy_par = cmp_rand_between(0, MAX_ICU_ROUND); + + par->nc_imagette = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + + par->s_exp_flags = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->s_fx = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->s_ncob = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->s_efx = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->s_ecob = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + + par->l_exp_flags = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->l_fx = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->l_ncob = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->l_efx = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->l_ecob = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->l_fx_cob_variance = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + + par->saturated_imagette = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + + par->nc_offset_mean = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->nc_offset_variance = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->nc_background_mean = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->nc_background_variance = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->nc_background_outlier_pixels = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + + par->smearing_mean = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->smearing_variance_mean = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->smearing_outlier_pixels = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + + par->fc_imagette = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->fc_offset_mean = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->fc_offset_variance = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->fc_background_mean = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->fc_background_variance = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->fc_background_outlier_pixels = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + } +} + + /** * @brief compress the given configuration and decompress it afterwards; finally * compare the results @@ -673,7 +685,7 @@ void compression_decompression(struct cmp_cfg *cfg) /* create a compression entity */ cmp_data_size = cmp_cal_size_of_data(cfg->buffer_length, cfg->data_type); - cmp_data_size &= ~0x3U; /* the size of the compressed data should be a multiple of 4 */ + /* cmp_data_size &= ~0x3U; /1* the size of the compressed data should be a multiple of 4 *1/ */ TEST_ASSERT_NOT_EQUAL_INT(0, cmp_data_size); cmp_ent_size = cmp_ent_create(NULL, cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW, cmp_data_size); @@ -682,12 +694,13 @@ void compression_decompression(struct cmp_cfg *cfg) cmp_ent_size = cmp_ent_create(ent, cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW, cmp_data_size); TEST_ASSERT_NOT_EQUAL_UINT(0, cmp_ent_size); - /* we put the coompressed data direct into the compression entity */ + /* we put the compressed 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 */ @@ -741,26 +754,27 @@ void compression_decompression(struct cmp_cfg *cfg) } -#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. + * @brief random RDCU like compression decompression test + * + * We generate random imagette 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 */ -#define MB *(1U<<20) -#define MAX_DATA_TO_COMPRESS_SIZE 0x1000B -void test_random_compression_decompression(void) +void test_random_round_trip_like_rdcu_compression(void) { enum cmp_data_type data_type; enum cmp_mode cmp_mode; struct cmp_cfg cfg; uint32_t cmp_buffer_size; + enum { + MAX_DATA_TO_COMPRESS_SIZE = 0x1000B, + CMP_BUFFER_FAKTOR = 3 /* compression data buffer size / data to compress buffer size */ + }; void *data_to_compress1 = malloc(MAX_DATA_TO_COMPRESS_SIZE); void *data_to_compress2 = malloc(MAX_DATA_TO_COMPRESS_SIZE); void *updated_model = calloc(1, MAX_DATA_TO_COMPRESS_SIZE); @@ -768,22 +782,19 @@ void test_random_compression_decompression(void) for (data_type = 1; data_type <= DATA_TYPE_F_CAM_BACKGROUND; data_type++) { /* printf("%s\n", data_type2string(data_type)); */ /* generate random data*/ - /* uint32_t samples = cmp_rand_between(1, 430179/CMP_BUFFER_FAKTOR); */ size_t size; uint32_t samples = cmp_rand_between(1, UINT16_MAX/size_of_a_sample(data_type)); uint32_t model_value = cmp_rand_between(0, MAX_MODEL_VALUE); - /* void *data_to_compress1 = generate_random_test_data(samples, data_type, &MAX_USED_BITS_V1); */ - /* void *data_to_compress2 = generate_random_test_data(samples, data_type, &MAX_USED_BITS_V1); */ - /* void *updated_model = calloc(1, cmp_cal_size_of_data(samples, data_type)); */ - /* memset(updated_model, 0, MAX_DATA_TO_COMPRESS_SIZE); */ - size = generate_random_collection(NULL, data_type, samples, &MAX_USED_BITS_V1); + if (!rdcu_supported_data_type_is_used(data_type)) + continue; + + size = gen_ima_data(NULL, data_type, samples, &MAX_USED_BITS_V1); TEST_ASSERT(size <= MAX_DATA_TO_COMPRESS_SIZE); - size = generate_random_collection(data_to_compress1, data_type, samples, &MAX_USED_BITS_V1); + size = gen_ima_data(data_to_compress1, data_type, samples, &MAX_USED_BITS_V1); TEST_ASSERT(size <= MAX_DATA_TO_COMPRESS_SIZE); - size = generate_random_collection(data_to_compress2, data_type, samples, &MAX_USED_BITS_V1); + size = gen_ima_data(data_to_compress2, data_type, samples, &MAX_USED_BITS_V1); TEST_ASSERT(size <= MAX_DATA_TO_COMPRESS_SIZE); - /* 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); */ @@ -791,14 +802,14 @@ void test_random_compression_decompression(void) CMP_LOSSLESS); TEST_ASSERT_NOT_EQUAL_INT(cfg.data_type, DATA_TYPE_UNKNOWN); - generate_random_cmp_par(&cfg); + generate_random_cmp_cfg(&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); + 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); + samples, data_to_compress1, updated_model, NULL, samples*CMP_BUFFER_FAKTOR); TEST_ASSERT_EQUAL_UINT(cmp_buffer_size, cmp_cal_size_of_data(CMP_BUFFER_FAKTOR*samples, data_type)); @@ -812,8 +823,11 @@ void test_random_compression_decompression(void) } -#define N_SAMPLES 5 -void test_random_compression_decompression2(void) +/** + * @test icu_compress_data + */ + +void test_random_compression_decompress_rdcu_data(void) { struct cmp_cfg cfg; struct cmp_info info = {0}; @@ -821,7 +835,11 @@ void test_random_compression_decompression2(void) int s, i, cmp_size_bits; void *compressed_data; uint16_t *decompressed_data; + enum {N_SAMPLES = 5}; uint16_t data[N_SAMPLES] = {0, UINT16_MAX, INT16_MAX, 42, 23}; + enum { + CMP_BUFFER_FAKTOR = 2 /* compression data buffer size / data to compress buffer size */ + }; 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); @@ -846,173 +864,217 @@ void test_random_compression_decompression2(void) info.rdcu_cmp_adr_used = cfg.rdcu_buffer_adr; s = decompress_rdcu_data(compressed_data, &info, NULL, NULL, NULL); - TEST_ASSERT(s > 0); + TEST_ASSERT_EQUAL(sizeof(data), s); decompressed_data = malloc((size_t)s); s = decompress_rdcu_data(compressed_data, &info, NULL, NULL, decompressed_data); - TEST_ASSERT(s > 0); + TEST_ASSERT_EQUAL(sizeof(data), s); for (i = 0; i < N_SAMPLES; i++) TEST_ASSERT_EQUAL_HEX16(data[i], decompressed_data[i]); - free(compressed_data); free(decompressed_data); } -#if 0 -int icu_compress_chunk(void *chunk, size_t chunk_size, void *model, void *dst, - size_t dst_capacity); -void no_test_chunk(void) + +static int32_t chunk_round_trip(void *data, uint32_t data_size, + void *model, void *up_model, + uint32_t *cmp_data, uint32_t cmp_data_capacity, + struct cmp_par *cmp_par, int use_decmp_buf, int use_decmp_up_model) { - size_t s, i; - struct todo chunk_struct[3]; - uint8_t *buf; - uint8_t *dst; - - cmp_rand_seed(0); - chunk_struct[0].data_type = DATA_TYPE_F_FX; - chunk_struct[0].samples = 10; - - chunk_struct[1].data_type = DATA_TYPE_S_FX; - chunk_struct[1].samples = 3; - - chunk_struct[2].data_type = DATA_TYPE_SMEARING; - chunk_struct[2].samples = 4; - - s = generate_random_chunk(NULL, chunk_struct, ARRAY_SIZE(chunk_struct), &MAX_USED_BITS_V1); - printf("s: %zu\n", s); - - buf = malloc(s); - s = generate_random_chunk(buf, chunk_struct, ARRAY_SIZE(chunk_struct), &MAX_USED_BITS_V1); - printf("data to compress (s: %zu)\n", s); - for (i = 0; i < s; ++i) { - printf("%02X", buf[i]); - if ((i + 1) % 2 == 0) - printf("\n"); + int32_t cmp_size; + void *model_cpy = NULL; + + /* if in-place model update is used (up_model == model), the model + * needed for decompression is destroyed; therefore we make a copy + */ + if (model) { + if (up_model == model) { + model_cpy = TEST_malloc(data_size); + memcpy(model_cpy, model, data_size); + } else { + model_cpy = model; + } } - dst = malloc(s+1000); - s = icu_compress_chunk(buf, s, NULL, dst, s+1000); - printf("\n\ncompressed data (s: %zu)\n", s); - for (i = 0; i < s; ++i) { - printf("%02X", dst[i]); - if ((i + 1) % 2 == 0) - printf("\n"); - } + cmp_size = compress_chunk(data, data_size, model, up_model, + cmp_data, cmp_data_capacity, cmp_par); + TEST_ASSERT(cmp_size != CMP_ERROR_HIGH_VALUE); - free(dst); - free(buf); -} +#if 0 + { /* Compress a second time and check for determinism */ + int32_t cSize2; + void *compressed2 = NULL; + void *up_model2 = NULL; + + if (compressed) + compressed2 = FUZZ_malloc(compressedCapacity); + + if (up_model) + up_model2 = FUZZ_malloc(srcSize); + cSize2 = compress_chunk((void *)src, srcSize, (void *)model, up_model2, + compressed2, compressedCapacity, cmp_par); + FUZZ_ASSERT(cSize == cSize2); + FUZZ_ASSERT_MSG(!FUZZ_memcmp(compressed, compressed2, cSize), "Not deterministic!"); + FUZZ_ASSERT_MSG(!FUZZ_memcmp(up_model, compressed2, cSize), "NO deterministic!"); + free(compressed2); + free(up_model2); + } #endif -#include <byteorder.h> + if (cmp_size >= 0 && cmp_data) { + void *decmp_data = NULL; + void *up_model_decmp = NULL; + int decmp_size; + + decmp_size = decompress_cmp_entiy((struct cmp_entity *)cmp_data, model_cpy, NULL, NULL); + TEST_ASSERT(decmp_size >= 0); + TEST_ASSERT_EQUAL((uint32_t)decmp_size, data_size); + + if (use_decmp_buf) + decmp_data = TEST_malloc(data_size); + if (use_decmp_up_model) + up_model_decmp = TEST_malloc(data_size); + + decmp_size = decompress_cmp_entiy((struct cmp_entity *)cmp_data, model_cpy, + up_model_decmp, decmp_data); + TEST_ASSERT(decmp_size >= 0); + TEST_ASSERT((uint32_t)decmp_size == data_size); + + if (use_decmp_buf) { + TEST_ASSERT_EQUAL_HEX8_ARRAY(data, decmp_data, data_size); + TEST_ASSERT(!memcmp(data, decmp_data, data_size)); + + /* + * the model is only updated when the decompressed_data + * buffer is set + */ + if (up_model && up_model_decmp) + TEST_ASSERT(!memcmp(up_model, up_model_decmp, data_size)); + } -size_t set_cmp_size(uint8_t *p, uint16_t v) -{ - v -= COLLECTION_HDR_SIZE; - memset(p, v >> 8, 1); - memset(p+1, v & 0xFF, 1); - return sizeof(uint16_t); -} + free(decmp_data); + free(up_model_decmp); + } -uint16_t get_cmp_size(uint8_t *p) -{ - return ((uint16_t)p[0]<<8) + p[1]; + if (up_model == model) + free(model_cpy); + + return cmp_size; } -#if 0 -remove this -void no_test_new_format(void) + + +/** + * @brief random compression decompression round trip test + * + * We generate random data and compress them with random parameters. + * We decompress the compression entity and compare the decompressed data with + * the original data. + * + * @test compress_chunk + * @test decompress_cmp_entiy + */ + +void test_random_collection_round_trip(void) { - uint32_t data_size = cmp_cal_size_of_data(3, DATA_TYPE_L_FX_EFX_NCOB_ECOB); - data_size += cmp_cal_size_of_data(2, DATA_TYPE_L_FX_EFX_NCOB_ECOB); - data_size += cmp_cal_size_of_data(5, DATA_TYPE_L_FX); - data_size += cmp_cal_size_of_data(2, DATA_TYPE_L_FX); - data_size += 3*sizeof(uint16_t); - - uint32_t ent_size = cmp_ent_create(NULL, DATA_TYPE_L_FX, 1, data_size); - void *ent = calloc(1, ent_size); - ent_size = cmp_ent_create(ent, DATA_TYPE_L_FX, 1, data_size); - - char *p = cmp_ent_get_data_buf(ent); - p +=2; - uint16_t s = generate_random_collection(p, DATA_TYPE_L_FX, 2, &MAX_USED_BITS_V1); - p += set_cmp_size(p-2, s); - p += s; - s = generate_random_collection(p, DATA_TYPE_L_FX, 5, &MAX_USED_BITS_V1); - p += set_cmp_size(p-2, s); - p += s; - s = generate_random_collection(p, DATA_TYPE_L_FX_EFX_NCOB_ECOB, 2, &MAX_USED_BITS_V1); - p += set_cmp_size(p-2, s); - p += s; - s = generate_random_collection(p, DATA_TYPE_L_FX_EFX_NCOB_ECOB, 2, &MAX_USED_BITS_V1); - p+=s; - - int num_of_coll =4; - - uint8_t *d_p = cmp_ent_get_data_buf(ent); - uint32_t sum =0; - s =0; - for (int c = 1; c <= num_of_coll ; c++) { - uint16_t cmp_col_size; - if (c == num_of_coll) - cmp_col_size = cmp_ent_get_cmp_data_size(ent)- sum; - else{ - cmp_col_size = get_cmp_size(&d_p[s]); - sum += cmp_col_size; - s+=2; - } + enum cmp_data_type data_type; + enum cmp_mode cmp_mode; + enum { MAX_DATA_TO_COMPRESS_SIZE = UINT16_MAX}; + uint32_t cmp_data_capacity = COMPRESS_CHUNK_BOUND(MAX_DATA_TO_COMPRESS_SIZE, 1); +#ifdef __sparc__ + void *data = (void *)0x63000000; + void *model = (void *)0x64000000; + void *updated_model = (void *)0x65000000; + void *cmp_data = (void *)0x66000000; +#else /* assume PC */ + void *data = malloc(CMP_ENTITY_MAX_ORIGINAL_SIZE); + void *model = malloc(MAX_DATA_TO_COMPRESS_SIZE); + void *updated_model = calloc(1, MAX_DATA_TO_COMPRESS_SIZE); + void *cmp_data = malloc(cmp_data_capacity); +#endif - uint16_t col_size = cmp_col_get_data_length(&d_p[s]); - printf("cmp_col_sizel: %X col_size: %X\n", cmp_col_size, col_size); - for (int i = s-2; i < s+col_size +COLLECTION_HDR_SIZE; ++i) { - printf("%02X ",((uint8_t *)d_p)[i]); - if ((i + 1) % 2 == 0) - printf("\n"); + TEST_ASSERT_NOT_NULL(data); + TEST_ASSERT_NOT_NULL(model); + TEST_ASSERT_NOT_NULL(updated_model); + TEST_ASSERT_NOT_NULL(cmp_data); + + for (data_type = 1; data_type <= DATA_TYPE_F_CAM_BACKGROUND; data_type++) { + /* printf("%s\n", data_type2string(data_type)); */ + /* generate random data*/ + size_t size; + uint32_t samples = cmp_rand_between(1, UINT16_MAX/size_of_a_sample(data_type)); + + size = generate_random_collection(NULL, data_type, samples, &MAX_USED_BITS_SAFE); + TEST_ASSERT(size <= MAX_DATA_TO_COMPRESS_SIZE); + size = generate_random_collection(data, data_type, samples, &MAX_USED_BITS_SAFE); + TEST_ASSERT(size <= MAX_DATA_TO_COMPRESS_SIZE); + size = generate_random_collection(model, data_type, samples, &MAX_USED_BITS_SAFE); + TEST_ASSERT(size <= MAX_DATA_TO_COMPRESS_SIZE); + + for (cmp_mode = CMP_MODE_RAW; cmp_mode <= CMP_MODE_DIFF_MULTI; cmp_mode++) { + struct cmp_par par; + int32_t cmp_size; + + generate_random_cmp_par(&par); + par.cmp_mode = cmp_mode; + par.lossy_par = CMP_LOSSLESS; + + cmp_size = chunk_round_trip(data, (uint32_t)size, model, updated_model, + cmp_data, cmp_data_capacity, + &par, 1, model_mode_is_used(par.cmp_mode)); + /* No chunk is defined for fast cadence subservices */ + if (data_type == DATA_TYPE_F_FX || data_type == DATA_TYPE_F_FX_EFX || + data_type == DATA_TYPE_F_FX_NCOB || data_type == DATA_TYPE_F_FX_EFX_NCOB_ECOB) + TEST_ASSERT(cmp_size == -1); + else + TEST_ASSERT(cmp_size > 0); } - TEST_ASSERT(cmp_col_size == col_size); - s+=col_size+COLLECTION_HDR_SIZE; } - -} +#ifndef __sparc__ + free(data); + free(model); + free(updated_model); + free(cmp_data); #endif -#if 0 -/* #include "../../lib/common/byteorder.h" */ -void NOOO_test_cmp_collection_raw(void) +} + + +/** + * @test compress_chunk + * @test decompress_cmp_entiy + */ + +void test_cmp_collection_raw(void) { struct collection_hdr *col = NULL; uint32_t samples = 2; - size_t col_size, dst_capacity = 0; + uint32_t dst_capacity = 0; struct s_fx *data; uint32_t *dst = NULL; - int dst_capacity_used = 0; struct cmp_par par = {0}; - const size_t exp_col_size = COLLECTION_HDR_SIZE+2*sizeof(struct s_fx); - const size_t exp_cmp_size_byte = exp_col_size; + const uint32_t col_size = COLLECTION_HDR_SIZE+2*sizeof(struct s_fx); + const size_t exp_cmp_size_byte = GENERIC_HEADER_SIZE + col_size; + int cmp_size_byte; par.cmp_mode = CMP_MODE_RAW; - col_size = generate_random_collection(col, DATA_TYPE_S_FX, samples, &MAX_USED_BITS_SAFE); - TEST_ASSERT_EQUAL(exp_col_size, col_size); - col = malloc(col_size); - TEST_ASSERT_NOT_NULL(col); - col_size = generate_random_collection(col, DATA_TYPE_S_FX, samples, &MAX_USED_BITS_SAFE); - TEST_ASSERT_EQUAL(exp_col_size, col_size); - + col = malloc(col_size); TEST_ASSERT_NOT_NULL(col); + generate_random_collection_hdr(col, DATA_TYPE_S_FX, samples); data = (struct s_fx *)col->entry; data[0].exp_flags = 0; data[0].fx = 0; data[1].exp_flags = 0xF0; data[1].fx = 0xABCDE0FF; - - dst_capacity = (size_t)cmp_collection(col, NULL, dst, dst_capacity, &par, dst_capacity_used); - TEST_ASSERT_EQUAL_INT(exp_cmp_size_byte, dst_capacity); + cmp_size_byte = compress_chunk(col, col_size, NULL, NULL, dst, dst_capacity, &par); + TEST_ASSERT_EQUAL_INT(exp_cmp_size_byte, cmp_size_byte); + dst_capacity = (uint32_t)cmp_size_byte; dst = malloc(dst_capacity); TEST_ASSERT_NOT_NULL(dst); - dst_capacity_used = cmp_collection(col, NULL, dst, dst_capacity, &par, dst_capacity_used); - TEST_ASSERT_EQUAL_INT(exp_cmp_size_byte, dst_capacity_used); + cmp_size_byte = compress_chunk(col, col_size, NULL, NULL, dst, dst_capacity, &par); + TEST_ASSERT_EQUAL_INT(exp_cmp_size_byte, cmp_size_byte); { - uint8_t *p = (uint8_t *)dst; + uint8_t *p = (uint8_t *)dst+GENERIC_HEADER_SIZE; struct collection_hdr *raw_cmp_col = (struct collection_hdr *)p; struct s_fx *raw_cmp_data = (void *)raw_cmp_col->entry; @@ -1023,62 +1085,69 @@ void NOOO_test_cmp_collection_raw(void) TEST_ASSERT_EQUAL_HEX(data[1].exp_flags, raw_cmp_data[1].exp_flags); TEST_ASSERT_EQUAL_HEX(data[1].fx, be32_to_cpu(raw_cmp_data[1].fx)); } + { /* decompress the data */ + int decmp_size; + uint8_t *decompressed_data; + + decmp_size = decompress_cmp_entiy((struct cmp_entity *)dst, NULL, NULL, NULL); + TEST_ASSERT_EQUAL_INT(col_size, decmp_size); + decompressed_data = malloc((size_t)decmp_size); TEST_ASSERT_TRUE(decompressed_data); + decmp_size = decompress_cmp_entiy((struct cmp_entity *)dst, NULL, NULL, decompressed_data); + TEST_ASSERT_EQUAL_INT(col_size, decmp_size); + TEST_ASSERT_EQUAL_HEX8_ARRAY(col, decompressed_data, decmp_size); + free(decompressed_data); + } - memset(dst, 0, dst_capacity); - + /* error case: buffer for the compressed data is to small */ dst_capacity -= 1; - dst_capacity_used = cmp_collection(col, NULL, dst, dst_capacity, &par, dst_capacity_used); - TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, dst_capacity_used); + TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, compress_chunk(col, col_size, NULL, NULL, dst, dst_capacity, &par)); free(col); free(dst); } -void NOOO_test_cmp_collection_diff(void) +/** + * @test compress_chunk + * @test decompress_cmp_entiy + */ + +void test_cmp_collection_diff(void) { struct collection_hdr *col = NULL; uint32_t *dst = NULL; - size_t dst_capacity = 0; - int dst_capacity_used = 33; + uint32_t dst_capacity = 0; struct cmp_par par = {0}; - const uint16_t cmp_size_byte_exp= 2; + const uint16_t cmp_size_byte_exp = 2; + struct s_fx *data; + const uint32_t samples = 2; + const uint32_t col_size = COLLECTION_HDR_SIZE+samples*sizeof(*data); - { /* generate test data */ - struct s_fx *data; - uint32_t samples = 2; - size_t col_size; - const size_t exp_col_size = COLLECTION_HDR_SIZE+samples*sizeof(*data); + /* generate test data */ + col = malloc(col_size); TEST_ASSERT_NOT_NULL(col); + generate_random_collection_hdr(col, DATA_TYPE_S_FX, samples); + data = (struct s_fx *)col->entry; + data[0].exp_flags = 0; + data[0].fx = 0; + data[1].exp_flags = 1; + data[1].fx = 1; - col_size = generate_random_collection(col, DATA_TYPE_S_FX, samples, &MAX_USED_BITS_SAFE); - TEST_ASSERT_EQUAL(exp_col_size, col_size); - col = malloc(col_size); TEST_ASSERT_NOT_NULL(col); - col_size = generate_random_collection(col, DATA_TYPE_S_FX, samples, &MAX_USED_BITS_SAFE); - TEST_ASSERT_EQUAL(exp_col_size, col_size); - - data = (struct s_fx *)col->entry; - data[0].exp_flags = 0; - data[0].fx = 0; - data[1].exp_flags = 1; - data[1].fx = 1; - } { /* compress data */ int cmp_size_byte; - const int exp_cmp_size_byte = dst_capacity_used + CMP_COLLECTION_FILD_SIZE - + COLLECTION_HDR_SIZE + cmp_size_byte_exp;; + const int exp_cmp_size_byte = NON_IMAGETTE_HEADER_SIZE + CMP_COLLECTION_FILD_SIZE + + COLLECTION_HDR_SIZE + cmp_size_byte_exp; par.cmp_mode = CMP_MODE_DIFF_ZERO; par.s_exp_flags = 1; par.s_fx = 1; - cmp_size_byte = cmp_collection(col, NULL, dst, dst_capacity, &par, dst_capacity_used); + cmp_size_byte = compress_chunk(col, col_size, NULL, NULL, dst, dst_capacity, &par); TEST_ASSERT_EQUAL_INT(exp_cmp_size_byte, cmp_size_byte); - dst_capacity = (size_t)ROUND_UP_TO_MULTIPLE_OF_4(cmp_size_byte); + dst_capacity = (uint32_t)ROUND_UP_TO_MULTIPLE_OF_4(cmp_size_byte); dst = malloc(dst_capacity); TEST_ASSERT_NOT_NULL(dst); - memset(dst, 0xFF, dst_capacity); - cmp_size_byte = cmp_collection(col, NULL, dst, dst_capacity, &par, dst_capacity_used); + cmp_size_byte = compress_chunk(col, col_size, NULL, NULL, dst, dst_capacity, &par); TEST_ASSERT_EQUAL_INT(exp_cmp_size_byte, cmp_size_byte); } @@ -1086,8 +1155,8 @@ void NOOO_test_cmp_collection_diff(void) uint8_t *p = (uint8_t *)dst; uint16_t cmp_collection_size_exp = cpu_to_be16(cmp_size_byte_exp); - TEST_ASSERT_EACH_EQUAL_HEX8(0xFF, p, dst_capacity_used); - p += dst_capacity_used; + /* TODO: check the entity header */ + p += NON_IMAGETTE_HEADER_SIZE; TEST_ASSERT_EQUAL_HEX8_ARRAY(&cmp_collection_size_exp, p, CMP_COLLECTION_FILD_SIZE); p += CMP_COLLECTION_FILD_SIZE; @@ -1097,68 +1166,72 @@ void NOOO_test_cmp_collection_diff(void) TEST_ASSERT_EQUAL_HEX8(0xAE, *p++); TEST_ASSERT_EQUAL_HEX8(0xE0, *p++); - TEST_ASSERT_EQUAL_HEX8(0x00, *p++); - TEST_ASSERT_EQUAL_HEX8(0x00, *p++); - TEST_ASSERT_EQUAL_HEX8(0x00, *p++); TEST_ASSERT_EQUAL_size_t(dst_capacity, p - (uint8_t *)dst); } - + { /* decompress the data */ + int decmp_size; + uint8_t *decompressed_data; + + decmp_size = decompress_cmp_entiy((struct cmp_entity *)dst, NULL, NULL, NULL); + TEST_ASSERT_EQUAL_INT(col_size, decmp_size); + decompressed_data = malloc((size_t)decmp_size); TEST_ASSERT_TRUE(decompressed_data); + decmp_size = decompress_cmp_entiy((struct cmp_entity *)dst, NULL, NULL, decompressed_data); + TEST_ASSERT_EQUAL_INT(col_size, decmp_size); + TEST_ASSERT_EQUAL_HEX8_ARRAY(col, decompressed_data, decmp_size); + free(decompressed_data); + } /* error cases dst buffer to small */ dst_capacity -= 1; - dst_capacity_used = cmp_collection(col, NULL, dst, dst_capacity, &par, dst_capacity_used); - TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, dst_capacity_used); + TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, compress_chunk(col, col_size, NULL, NULL, dst, dst_capacity, &par)); free(col); free(dst); } -void NOOO_test_cmp_collection_worst_case(void) +/** + * @test compress_chunk + * @test decompress_cmp_entiy + */ + +void test_cmp_collection_worst_case(void) { struct collection_hdr *col = NULL; uint32_t *dst = NULL; - size_t dst_capacity = 0; - int dst_capacity_used = 4; + uint32_t dst_capacity = 0; struct cmp_par par = {0}; - const uint16_t cmp_size_byte_exp= 2*sizeof(struct s_fx); + const uint16_t cmp_size_byte_exp = 2*sizeof(struct s_fx); int cmp_size_byte; + struct s_fx *data; + uint32_t samples = 2; + const uint32_t col_size = COLLECTION_HDR_SIZE+samples*sizeof(*data); - { /* generate test data */ - struct s_fx *data; - uint32_t samples = 2; - size_t col_size; - const size_t exp_col_size = COLLECTION_HDR_SIZE+samples*sizeof(*data); + /* generate test data */ + col = malloc(col_size); TEST_ASSERT_NOT_NULL(col); + generate_random_collection_hdr(col, DATA_TYPE_S_FX, samples); + data = (struct s_fx *)col->entry; + data[0].exp_flags = 0x4; + data[0].fx = 0x0000000E; + data[1].exp_flags = 0x4; + data[1].fx = 0x00000016; - col_size = generate_random_collection(col, DATA_TYPE_S_FX, samples, &MAX_USED_BITS_SAFE); - TEST_ASSERT_EQUAL(exp_col_size, col_size); - col = malloc(col_size); TEST_ASSERT_NOT_NULL(col); - col_size = generate_random_collection(col, DATA_TYPE_S_FX, samples, &MAX_USED_BITS_SAFE); - TEST_ASSERT_EQUAL(exp_col_size, col_size); - - data = (struct s_fx *)col->entry; - data[0].exp_flags = 0x4; - data[0].fx = 0x0000000E; - data[1].exp_flags = 0x4; - data[1].fx = 0x00000016; -; - } { /* compress data */ - const int exp_cmp_size_byte = dst_capacity_used + CMP_COLLECTION_FILD_SIZE - + COLLECTION_HDR_SIZE + cmp_size_byte_exp;; + const int exp_cmp_size_byte = NON_IMAGETTE_HEADER_SIZE + CMP_COLLECTION_FILD_SIZE + + COLLECTION_HDR_SIZE + cmp_size_byte_exp; par.cmp_mode = CMP_MODE_DIFF_ZERO; par.s_exp_flags = 1; par.s_fx = 1; - cmp_size_byte = cmp_collection(col, NULL, dst, dst_capacity, &par, dst_capacity_used); + cmp_size_byte = compress_chunk(col, col_size, NULL, NULL, dst, dst_capacity, &par); TEST_ASSERT_EQUAL_INT(exp_cmp_size_byte, cmp_size_byte); - dst_capacity = 1000; + dst_capacity = (uint32_t)cmp_size_byte; dst = malloc(dst_capacity); TEST_ASSERT_NOT_NULL(dst); memset(dst, 0xFF, dst_capacity); - cmp_size_byte = cmp_collection(col, NULL, dst, dst_capacity, &par, dst_capacity_used); + cmp_size_byte = compress_chunk(col, col_size, NULL, NULL, dst, dst_capacity, &par); TEST_ASSERT_EQUAL_INT(exp_cmp_size_byte, cmp_size_byte); } @@ -1166,8 +1239,8 @@ void NOOO_test_cmp_collection_worst_case(void) uint8_t *p = (uint8_t *)dst; uint16_t cmp_collection_size_exp = cpu_to_be16(cmp_size_byte_exp); - TEST_ASSERT_EACH_EQUAL_HEX8(0xFF, p, dst_capacity_used); - p += dst_capacity_used; + /* TODO: check the entity header */ + p += NON_IMAGETTE_HEADER_SIZE; TEST_ASSERT_EQUAL_HEX8_ARRAY(&cmp_collection_size_exp, p, CMP_COLLECTION_FILD_SIZE); p += CMP_COLLECTION_FILD_SIZE; @@ -1188,19 +1261,121 @@ void NOOO_test_cmp_collection_worst_case(void) TEST_ASSERT_EQUAL_size_t(cmp_size_byte, p - (uint8_t *)dst); } + { /* decompress the data */ + int decmp_size; + uint8_t *decompressed_data; + + decmp_size = decompress_cmp_entiy((struct cmp_entity *)dst, NULL, NULL, NULL); + TEST_ASSERT_EQUAL_INT(col_size, decmp_size); + decompressed_data = malloc((size_t)decmp_size); TEST_ASSERT_TRUE(decompressed_data); + decmp_size = decompress_cmp_entiy((struct cmp_entity *)dst, NULL, NULL, decompressed_data); + TEST_ASSERT_EQUAL_INT(col_size, decmp_size); + TEST_ASSERT_EQUAL_HEX8_ARRAY(col, decompressed_data, decmp_size); + free(decompressed_data); + } + free(dst); + free(col); } -#endif -void test_cmp_chunk_raw2(void) +/** + * @test compress_chunk + * @test decompress_cmp_entiy + */ + +void test_cmp_collection_imagette_worst_case(void) +{ + struct collection_hdr *col = NULL; + uint32_t *dst = NULL; + struct cmp_par par = {0}; + uint16_t const cmp_size_byte_exp = 10*sizeof(uint16_t); + int cmp_size_byte; + uint32_t const col_size = COLLECTION_HDR_SIZE + cmp_size_byte_exp; + + { /* generate test data */ + uint16_t *data; + + col = malloc(col_size); TEST_ASSERT_NOT_NULL(col); + generate_random_collection_hdr(col, DATA_TYPE_IMAGETTE, 10); + + data = (void *)col->entry; + data[0] = 0x0102; + data[1] = 0x0304; + data[2] = 0x0506; + data[3] = 0x0708; + data[4] = 0x090A; + data[5] = 0x0B0C; + data[6] = 0x0D0E; + data[7] = 0x0F10; + data[8] = 0x1112; + data[9] = 0x1314; + } + + { /* compress data */ + uint32_t dst_capacity = 0; + const int exp_cmp_size_byte = NON_IMAGETTE_HEADER_SIZE + CMP_COLLECTION_FILD_SIZE + + COLLECTION_HDR_SIZE + cmp_size_byte_exp; + + par.cmp_mode = CMP_MODE_DIFF_MULTI; + par.nc_imagette = 62; + + cmp_size_byte = compress_chunk(col, col_size, NULL, NULL, dst, dst_capacity, &par); + TEST_ASSERT_EQUAL_INT(exp_cmp_size_byte, cmp_size_byte); + dst_capacity = (uint32_t)cmp_size_byte; + dst = malloc(dst_capacity); TEST_ASSERT_NOT_NULL(dst); + memset(dst, 0xFF, dst_capacity); + cmp_size_byte = compress_chunk(col, col_size, NULL, NULL, dst, dst_capacity, &par); + TEST_ASSERT_EQUAL_INT(exp_cmp_size_byte, cmp_size_byte); + } + + { /* check the compressed data */ + uint32_t i; + uint8_t *p = (uint8_t *)dst; + uint16_t cmp_collection_size_exp = cpu_to_be16(cmp_size_byte_exp); + + /* TODO: check the entity header */ + p += NON_IMAGETTE_HEADER_SIZE; + + TEST_ASSERT_EQUAL_HEX8_ARRAY(&cmp_collection_size_exp, p, CMP_COLLECTION_FILD_SIZE); + p += CMP_COLLECTION_FILD_SIZE; + + TEST_ASSERT(memcmp(col, p, COLLECTION_HDR_SIZE) == 0); + p += COLLECTION_HDR_SIZE; + + for (i = 1; i <= col_size-COLLECTION_HDR_SIZE; ++i) + TEST_ASSERT_EQUAL_HEX8(i, *p++); + + TEST_ASSERT_EQUAL_size_t(cmp_size_byte, p - (uint8_t *)dst); + } + { /* decompress the data */ + int decmp_size; + uint8_t *decompressed_data; + + decmp_size = decompress_cmp_entiy((struct cmp_entity *)dst, NULL, NULL, NULL); + TEST_ASSERT_EQUAL_INT(col_size, decmp_size); + decompressed_data = malloc((size_t)decmp_size); TEST_ASSERT_TRUE(decompressed_data); + decmp_size = decompress_cmp_entiy((struct cmp_entity *)dst, NULL, NULL, decompressed_data); + TEST_ASSERT_EQUAL_INT(col_size, decmp_size); + TEST_ASSERT_EQUAL_HEX8_ARRAY(col, decompressed_data, decmp_size); + free(decompressed_data); + } +} + + +/** + * @test compress_chunk + * @test decompress_cmp_entiy + */ + +void test_cmp_decmp_chunk_raw(void) { struct cmp_par par = {0}; struct chunk_def chunk_def[2] = {{DATA_TYPE_S_FX, 2}, {DATA_TYPE_S_FX_EFX_NCOB_ECOB, 3}}; - size_t chunk_size; + uint32_t chunk_size; size_t chunk_size_exp = 2*sizeof(struct s_fx) + 3*sizeof(struct s_fx_efx_ncob_ecob) + 2*COLLECTION_HDR_SIZE; void *chunk = NULL; uint32_t *dst = NULL; - int dst_capacity = 0; + uint32_t dst_capacity = 0; /* generate test data */ chunk_size = generate_random_chunk(chunk, chunk_def, ARRAY_SIZE(chunk_def), &MAX_USED_BITS_SAFE); @@ -1212,37 +1387,33 @@ void test_cmp_chunk_raw2(void) /* "compress" data */ { - size_t cmp_size_byte_exp = GENERIC_HEADER_SIZE + chunk_size_exp; + size_t cmp_size_exp = GENERIC_HEADER_SIZE + chunk_size_exp; + int cmp_size; par.cmp_mode = CMP_MODE_RAW; - dst_capacity = compress_chunk(chunk, chunk_size, NULL, NULL, dst, dst_capacity, &par); - TEST_ASSERT_EQUAL_INT(cmp_size_byte_exp, dst_capacity); - dst = calloc(1, dst_capacity); - TEST_ASSERT_NOT_NULL(dst); - dst_capacity = compress_chunk(chunk, chunk_size, NULL, NULL, dst, dst_capacity, &par); - TEST_ASSERT_EQUAL_INT(cmp_size_byte_exp, dst_capacity); + cmp_size = compress_chunk(chunk, chunk_size, NULL, NULL, dst, dst_capacity, &par); + TEST_ASSERT_EQUAL_INT(cmp_size_exp, cmp_size); + dst_capacity = (uint32_t)cmp_size; + dst = malloc(dst_capacity); TEST_ASSERT_NOT_NULL(dst); + cmp_size = compress_chunk(chunk, chunk_size, NULL, NULL, dst, dst_capacity, &par); + TEST_ASSERT_EQUAL_INT(cmp_size_exp, dst_capacity); } /* check results */ { uint8_t *p = (uint8_t *)dst; - /* uint16_t cmp_collection_size_exp = cpu_to_be16(2*sizeof(struct s_fx)); */ struct collection_hdr *col = (struct collection_hdr *)chunk; struct s_fx *cmp_data_raw_1; struct s_fx *data = (void *)col->entry; int i; - /* TODO: Check header */ - TEST_ASSERT_EQUAL_HEX(chunk_size, cmp_ent_get_original_size(dst)); - TEST_ASSERT_EQUAL_HEX(chunk_size+GENERIC_HEADER_SIZE, cmp_ent_get_size(dst)); + /* TODO: Check entity header */ + TEST_ASSERT_EQUAL_HEX(chunk_size, cmp_ent_get_original_size((struct cmp_entity *)dst)); + TEST_ASSERT_EQUAL_HEX(chunk_size+GENERIC_HEADER_SIZE, cmp_ent_get_size((struct cmp_entity *)dst)); p += GENERIC_HEADER_SIZE; - - /* TEST_ASSERT(memcmp(p, &cmp_collection_size_exp, CMP_COLLECTION_FILD_SIZE) == 0); */ - /* p += CMP_COLLECTION_FILD_SIZE; */ - TEST_ASSERT(memcmp(col, p, COLLECTION_HDR_SIZE) == 0); p += COLLECTION_HDR_SIZE; @@ -1254,10 +1425,6 @@ void test_cmp_chunk_raw2(void) p += 2*sizeof(struct s_fx); /* check 2nd collection */ - /* cmp_collection_size_exp = cpu_to_be16(3*sizeof(struct s_fx_efx_ncob_ecob)); */ - /* TEST_ASSERT(memcmp(p, &cmp_collection_size_exp, CMP_COLLECTION_FILD_SIZE) == 0); */ - /* p += CMP_COLLECTION_FILD_SIZE; */ - col = (struct collection_hdr *) ((char *)col + cmp_col_get_size(col)); TEST_ASSERT(memcmp(col, p, COLLECTION_HDR_SIZE) == 0); p += COLLECTION_HDR_SIZE; @@ -1279,20 +1446,21 @@ void test_cmp_chunk_raw2(void) void *decompressed_data = NULL; int decmp_size = decompress_cmp_entiy((void *)dst, NULL, NULL, decompressed_data); TEST_ASSERT_EQUAL_size_t(chunk_size, decmp_size); + decompressed_data = malloc((size_t)decmp_size); TEST_ASSERT_NOT_NULL(decompressed_data); decmp_size = decompress_cmp_entiy((void *)dst, NULL, NULL, decompressed_data); TEST_ASSERT_EQUAL_INT(chunk_size, decmp_size); TEST_ASSERT_EQUAL_HEX8_ARRAY(chunk, decompressed_data, chunk_size); + free(decompressed_data); } + { /* error case: buffer to small for compressed data */ + int cmp_size; - /* error cases */ - memset(dst, 0, dst_capacity); - - /* buffer to small for compressed data */ - dst_capacity -=1 ; - dst_capacity = compress_chunk(chunk, chunk_size, NULL, NULL, dst, dst_capacity, &par); - TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, dst_capacity); + dst_capacity -= 1; + cmp_size = compress_chunk(chunk, chunk_size, NULL, NULL, dst, dst_capacity, &par); + TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, cmp_size); + } free(chunk); } @@ -1301,23 +1469,32 @@ void test_cmp_chunk_raw2(void) void test_cmp_decmp_chunk_worst_case(void) { struct chunk_def chunk_def[2] = {{DATA_TYPE_S_FX, 2}, {DATA_TYPE_S_FX_EFX_NCOB_ECOB, 3}}; - uint32_t chunk_size; enum {CHUNK_SIZE_EXP = 2*sizeof(struct s_fx) + 3*sizeof(struct s_fx_efx_ncob_ecob) + 2*COLLECTION_HDR_SIZE}; + uint32_t chunk_size = CHUNK_SIZE_EXP; void *chunk = NULL; uint32_t dst[COMPRESS_CHUNK_BOUND(CHUNK_SIZE_EXP, ARRAY_SIZE(chunk_def))/sizeof(uint32_t)]; int cmp_size_byte = 0; struct cmp_par par = {0}; - /* generate test data */ - chunk_size = (uint32_t)generate_random_chunk(chunk, chunk_def, ARRAY_SIZE(chunk_def), &MAX_USED_BITS_SAFE); - TEST_ASSERT_EQUAL_size_t(CHUNK_SIZE_EXP, chunk_size); - chunk = calloc(1, chunk_size); - TEST_ASSERT_NOT_NULL(chunk); - chunk_size = (uint32_t)generate_random_chunk(chunk, chunk_def, ARRAY_SIZE(chunk_def), &MAX_USED_BITS_SAFE); - TEST_ASSERT_EQUAL_size_t(CHUNK_SIZE_EXP, chunk_size); + { /* generate test data */ + uint16_t s; + uint8_t *p, i; - /* "compress" data */ - { + chunk = malloc(chunk_size); TEST_ASSERT_NOT_NULL(chunk); + generate_random_collection_hdr(chunk, DATA_TYPE_S_FX, 2); + p = chunk; + p += COLLECTION_HDR_SIZE; + for (i = 0; i < cmp_col_get_data_length(chunk); i++) + *p++ = i; + generate_random_collection_hdr((struct collection_hdr *)p, DATA_TYPE_S_FX_EFX_NCOB_ECOB, 3); + s = cmp_col_get_data_length((struct collection_hdr *)p); + p += COLLECTION_HDR_SIZE; + for (i = 0; i < s; i++) + *p++ = i; + } + + + { /* "compress" data */ size_t cmp_size_byte_exp = NON_IMAGETTE_HEADER_SIZE + 2*CMP_COLLECTION_FILD_SIZE + CHUNK_SIZE_EXP; par.cmp_mode = CMP_MODE_DIFF_ZERO; @@ -1333,8 +1510,7 @@ void test_cmp_decmp_chunk_worst_case(void) TEST_ASSERT_EQUAL_INT(cmp_size_byte_exp, cmp_size_byte); } - /* check results */ - { + { /* check results */ uint8_t *p = (uint8_t *)dst; uint16_t cmp_collection_size_exp = cpu_to_be16(2*sizeof(struct s_fx)); struct collection_hdr *col = (struct collection_hdr *)chunk; @@ -1342,7 +1518,7 @@ void test_cmp_decmp_chunk_worst_case(void) struct s_fx *data = (void *)col->entry; int i; - /* TODO: Check header */ + /* TODO: Check entity header */ p += NON_IMAGETTE_HEADER_SIZE; TEST_ASSERT_EQUAL_HEX8_ARRAY(&cmp_collection_size_exp, p, CMP_COLLECTION_FILD_SIZE); @@ -1383,18 +1559,17 @@ void test_cmp_decmp_chunk_worst_case(void) { void *decompressed_data = NULL; int decmp_size = decompress_cmp_entiy((void *)dst, NULL, NULL, decompressed_data); + TEST_ASSERT_EQUAL_size_t(chunk_size, decmp_size); decompressed_data = malloc((size_t)decmp_size); TEST_ASSERT_NOT_NULL(decompressed_data); decmp_size = decompress_cmp_entiy((void *)dst, NULL, NULL, decompressed_data); TEST_ASSERT_EQUAL_INT(chunk_size, decmp_size); TEST_ASSERT_EQUAL_HEX8_ARRAY(chunk, decompressed_data, chunk_size); + free(decompressed_data); } - /* error cases */ - memset(dst, 0, sizeof(dst)); - - /* buffer to small for compressed data */ + /* error case: buffer to small for compressed data */ cmp_size_byte = compress_chunk(chunk, chunk_size, NULL, NULL, dst, chunk_size, &par); TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, cmp_size_byte); @@ -1405,13 +1580,11 @@ void test_cmp_decmp_chunk_worst_case(void) void test_cmp_decmp_diff(void) { struct chunk_def chunk_def[2] = {{DATA_TYPE_S_FX, 2}, {DATA_TYPE_S_FX_EFX_NCOB_ECOB, 3}}; - size_t chunk_size; + uint32_t chunk_size; void *chunk = NULL; uint32_t *dst = NULL; - int dst_capacity = 0; - /* generate test data */ - { + { /* generate test data */ struct s_fx *col_data1; struct s_fx_efx_ncob_ecob *col_data2; struct collection_hdr *col; @@ -1456,10 +1629,10 @@ void test_cmp_decmp_diff(void) col_data2[2].ecob_y = 2; } - - /* compress data */ - { + { /* compress data */ struct cmp_par par = {0}; + uint32_t dst_capacity = 0; + int cmp_size; par.cmp_mode = CMP_MODE_DIFF_ZERO; par.s_exp_flags = 1; @@ -1469,13 +1642,13 @@ void test_cmp_decmp_diff(void) par.s_ecob = 5; - dst_capacity = compress_chunk(chunk, chunk_size, NULL, NULL, dst, dst_capacity, &par); - TEST_ASSERT_GREATER_THAN_INT(0, dst_capacity); - /* TODO: */ dst_capacity = ROUND_UP_TO_MULTIPLE_OF_4(dst_capacity); + cmp_size = compress_chunk(chunk, chunk_size, NULL, NULL, dst, dst_capacity, &par); + TEST_ASSERT_GREATER_THAN_INT(0, cmp_size); + dst_capacity = (uint32_t)ROUND_UP_TO_MULTIPLE_OF_4(cmp_size); dst = malloc(dst_capacity); TEST_ASSERT_NOT_NULL(dst); - dst_capacity = compress_chunk(chunk, chunk_size, NULL, NULL, dst, dst_capacity, &par); - TEST_ASSERT_GREATER_THAN_INT(0, dst_capacity); + cmp_size = compress_chunk(chunk, chunk_size, NULL, NULL, dst, dst_capacity, &par); + TEST_ASSERT_GREATER_THAN_INT(0, cmp_size); } { void *decompressed_data = NULL; @@ -1488,5 +1661,7 @@ void test_cmp_decmp_diff(void) TEST_ASSERT_EQUAL_INT(chunk_size, decmp_size); TEST_ASSERT_EQUAL_HEX8_ARRAY(chunk, decompressed_data, chunk_size); + free(decompressed_data); } + free(dst); } diff --git a/test/decmp/test_decmp.c b/test/decmp/test_decmp.c index 8e9fb8720c4d666388e219fe08932d618951d5c2..a1627cb52a17b78e1917b468744c23dff2a55e66 100644 --- a/test/decmp/test_decmp.c +++ b/test/decmp/test_decmp.c @@ -24,12 +24,20 @@ #include <compiler.h> #include <cmp_entity.h> +#include <cmp_data_types.h> #include "../../lib/icu_compress/cmp_icu.c" /* .c file included to test static functions */ #include "../../lib/decompress/decmp.c" /* .c file included to test static functions */ #define MAX_VALID_CW_LEM 32 +/** + * @test bit_init_decoder + * @test bit_read_bits32 + * @test bit_read_bits + * @test bit_refill + */ + void test_bitstream(void) { uint8_t i, data[12]; @@ -68,7 +76,7 @@ void test_bitstream(void) TEST_ASSERT_EQUAL_INT(32, dec.bits_consumed); status = bit_refill(&dec); TEST_ASSERT_EQUAL_INT(BIT_END_OF_BUFFER, status); - TEST_ASSERT_EQUAL_INT(32,dec.bits_consumed); + TEST_ASSERT_EQUAL_INT(32, dec.bits_consumed); TEST_ASSERT_FALSE(bit_end_of_stream(&dec)); read_bits = bit_read_bits32(&dec, 32); @@ -95,8 +103,6 @@ void test_bitstream(void) bit_read_bits(&dec, 57); TEST_ASSERT_EQUAL_INT(BIT_OVERFLOW, status); - - { uint8_t k, j; uint8_t buf[9]; @@ -197,8 +203,8 @@ void test_unary_decoder(void) TEST_ASSERT_EQUAL_INT(32, leading_ones); TEST_ASSERT_EQUAL_INT(BIT_OVERFLOW, bit_refill(&dec)); - { - uint64_t value64 = ~0ULL; + { uint64_t value64 = ~0ULL; + ret = bit_init_decoder(&dec, &value64, sizeof(value64)); TEST_ASSERT_EQUAL_size_t(sizeof(value64), ret); leading_ones = unary_decoder(&dec, unused_1, unused_2); @@ -790,8 +796,7 @@ void test_decode_multi(void) TEST_ASSERT_EQUAL_INT(-1, err); - /* 0xFA -> 16 = spill(8)+8 -> unencoded_len = 17 bits -> larger than - * 16 bit max_used_bits*/ + /* 0xFA -> 16 = spill(8)+8 -> unencoded_len = 17 bits -> larger than 16 bit max_used_bits */ cmp_data[0] = cpu_to_be32(0xFA000000); cmp_data[1] = cpu_to_be32(0x00000000); bit_init_decoder(&dec, cmp_data, sizeof(cmp_data)); @@ -888,6 +893,7 @@ void test_multi_refill_needed(void) TEST_ASSERT_EQUAL_INT(CORRUPTION_DETECTED, err); } + /** * @test re_map_to_pos */ @@ -920,6 +926,7 @@ void test_re_map_to_pos(void) for (j = -16; j < 15; j++) { uint32_t map_val = map_to_pos((uint32_t)j, 16) & 0x3F; + result = re_map_to_pos(map_val); TEST_ASSERT_EQUAL_INT32(j, result); } @@ -980,7 +987,8 @@ size_t icu_compress_data_entity(struct cmp_entity *ent, const struct cmp_cfg *cf return 0; /* XXX overwrite the size of the compression entity with the size of the actual - * size of the compressed data; not all allocated memory is normally used */ + * size of the compressed data; not all allocated memory is normally used + */ s = cmp_ent_create(ent, cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW, cmp_bit_to_byte((unsigned int)cmp_size_bits)); @@ -1065,8 +1073,7 @@ void test_decompress_imagette_model(void) bit_init_decoder(&dec, cfg.icu_output_buf, cfg.buffer_length); - err = decompress_imagette(&cfg, &dec); - /* TEST_ASSERT_EQUAL_INT(15, stream_pos); */ + err = decompress_imagette(&cfg, &dec, RDCU_DECOMPRESSION); TEST_ASSERT_FALSE(err); TEST_ASSERT_EQUAL_HEX(1, data[0]); TEST_ASSERT_EQUAL_HEX(2, data[1]); @@ -1082,189 +1089,6 @@ void test_decompress_imagette_model(void) } -#define DATA_SAMPLES 5 -void test_cmp_decmp_s_fx_diff(void) -{ - size_t s; - int err, decmp_size; - - struct cmp_entity *ent; - const uint32_t MAX_VALUE = ~(~0U << MAX_USED_BITS_V1.s_fx); - struct s_fx data_entry[DATA_SAMPLES]; - uint8_t data_to_compress[COLLECTION_HDR_SIZE + sizeof(data_entry)]; - struct s_fx *decompressed_data = NULL; - uint32_t compressed_data_len_samples = DATA_SAMPLES; - struct cmp_cfg cfg; - - data_entry[0].exp_flags = 0; - data_entry[0].fx = 0; - data_entry[1].exp_flags = 1; - data_entry[1].fx = 23; - data_entry[2].exp_flags = 2; - data_entry[2].fx = 42; - data_entry[3].exp_flags = 3; - data_entry[3].fx = MAX_VALUE; - data_entry[4].exp_flags = 3; - data_entry[4].fx = MAX_VALUE>>1; - - for (s = 0; s < COLLECTION_HDR_SIZE; s++) - data_to_compress[s] = (uint8_t)s; - memcpy(&data_to_compress[COLLECTION_HDR_SIZE], data_entry, sizeof(data_entry)); - - cfg = cmp_cfg_icu_create(DATA_TYPE_S_FX, CMP_MODE_DIFF_MULTI, - CMP_PAR_UNUSED, CMP_LOSSLESS); - TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN); - - s = cmp_cfg_icu_buffers(&cfg, data_to_compress, DATA_SAMPLES, NULL, NULL, - NULL, compressed_data_len_samples); - TEST_ASSERT_TRUE(s); - - err = cmp_cfg_fx_cob(&cfg, 2, 6, 4, 14, CMP_PAR_UNUSED, CMP_PAR_UNUSED, - CMP_PAR_UNUSED, CMP_PAR_UNUSED, CMP_PAR_UNUSED, - CMP_PAR_UNUSED, CMP_PAR_UNUSED, CMP_PAR_UNUSED); - TEST_ASSERT_FALSE(err); - - s = icu_compress_data_entity(NULL, &cfg); - TEST_ASSERT_TRUE(s); - ent = malloc(s); TEST_ASSERT_TRUE(ent); - s = icu_compress_data_entity(ent, &cfg); - TEST_ASSERT_TRUE(s); - - /* now decompress the data */ - decmp_size = decompress_cmp_entiy(ent, NULL, NULL, decompressed_data); - TEST_ASSERT_EQUAL_INT(cmp_cal_size_of_data(cfg.samples, cfg.data_type), decmp_size); - decompressed_data = malloc((size_t)decmp_size); TEST_ASSERT_TRUE(decompressed_data); - decmp_size = decompress_cmp_entiy(ent, NULL, NULL, decompressed_data); - TEST_ASSERT_EQUAL_INT(cmp_cal_size_of_data(cfg.samples, cfg.data_type), decmp_size); - - TEST_ASSERT_EQUAL_HEX8_ARRAY(data_to_compress, decompressed_data, decmp_size); - /* TEST_ASSERT_FALSE(memcmp(data_to_compress, decompressed_data, (size_t)decmp_size)); */ - /* for (i = 0; i < samples; ++i) { */ - /* printf("%u == %u (round: %u)\n", data[i], decompressed_data[i], round); */ - /* uint32_t mask = ~0U << round; */ - /* if ((data[i]&mask) != (decompressed_data[i]&mask)) */ - /* TEST_ASSERT(0); */ - /* if (model_mode_is_used(cmp_mode)) */ - /* if (up_model[i] != de_up_model[i]) */ - /* TEST_ASSERT(0); */ - /* } */ - free(ent); - free(decompressed_data); -} -#undef DATA_SAMPLES - - -void test_s_fx_diff(void) -{ - size_t i; - int s; - uint8_t cmp_entity[88] = { - 0x80, 0x00, 0x00, 0x09, 0x00, 0x00, 0x58, 0x00, 0x00, 0x20, 0x04, 0xEE, 0x21, 0xBD, 0xB0, 0x1C, 0x04, 0xEE, 0x21, 0xBD, 0xB0, 0x41, 0x00, 0x08, 0x02, 0x08, 0xD0, 0x10, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0xAE, 0xDE, 0x00, 0x00, 0x00, 0x73, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00, - }; - - uint8_t result_data[32] = {0}; - struct collection_hdr *hdr = (struct collection_hdr *)result_data; - struct s_fx *data = (struct s_fx *)hdr->entry; - uint8_t *decompressed_data; - - /* put some dummy data in the header*/ - for (i = 0; i < sizeof(*hdr); i++) - result_data[i] = (uint8_t)i; - data[0].exp_flags = 0; - data[0].fx = 0; - data[1].exp_flags = 1; - data[1].fx = 0xFFFFFF; - data[2].exp_flags = 3; - data[2].fx = 0x7FFFFF; - data[3].exp_flags = 0; - data[3].fx = 0; - - s = decompress_cmp_entiy((void *)cmp_entity, NULL, NULL, NULL); - TEST_ASSERT_EQUAL_INT(sizeof(result_data), s); - decompressed_data = malloc((size_t)s); - TEST_ASSERT_TRUE(decompressed_data); - s = decompress_cmp_entiy((void *)cmp_entity, NULL, NULL, decompressed_data); - TEST_ASSERT_EQUAL_INT(sizeof(result_data), s); - for (i = 0; i < (size_t)s; ++i) { - TEST_ASSERT_EQUAL(result_data[i], decompressed_data[i]); - } - free(decompressed_data); -} - - -void test_s_fx_model(void) -{ - size_t i; - int s; - uint8_t compressed_data_buf[92] = { - 0x80, 0x00, 0x00, 0x09, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x20, 0x04, 0xF0, 0xC2, 0xD3, 0x47, 0xE4, 0x04, 0xF0, 0xC2, 0xD3, 0x48, 0x16, 0x00, 0x08, 0x03, 0x08, 0xD0, 0x10, 0x01, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x3B, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0x5B, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0x5D, 0x80, 0x00, 0x00, - }; - struct cmp_entity *cmp_entity = (struct cmp_entity *)compressed_data_buf; - - uint8_t model_buf[32]; - uint8_t decompressed_data[32]; - uint8_t up_model_buf[32]; - uint8_t exp_data_buf[32] = {0}; /* expected uncompressed data */ - uint8_t exp_up_model_buf[32] = {0}; - - struct collection_hdr *model_collection = (struct collection_hdr *)model_buf; - struct s_fx *model_data = (struct s_fx *)model_collection->entry; - - struct collection_hdr *exp_data_collection; - struct s_fx *exp_data; - struct collection_hdr *exp_up_model_collection; - struct s_fx *exp_updated_model_data; - - memset(model_collection, 0xFF, sizeof(*model_collection)); - model_data[0].exp_flags = 0; - model_data[0].fx = 0; - model_data[1].exp_flags = 3; - model_data[1].fx = 0x7FFFFF; - model_data[2].exp_flags = 0; - model_data[2].fx = 0xFFFFFF; - model_data[3].exp_flags = 3; - model_data[3].fx = 0xFFFFFF; - - exp_data_collection = (struct collection_hdr *)exp_data_buf; - exp_data = (struct s_fx *)exp_data_collection->entry; - /* put some dummy data in the header */ - for (i = 0; i < sizeof(*exp_data_collection); i++) - exp_data_buf[i] = (uint8_t)i; - exp_data[0].exp_flags = 0; - exp_data[0].fx = 0; - exp_data[1].exp_flags = 1; - exp_data[1].fx = 0xFFFFFF; - exp_data[2].exp_flags = 3; - exp_data[2].fx = 0x7FFFFF; - exp_data[3].exp_flags = 0; - exp_data[3].fx = 0; - - exp_up_model_collection = (struct collection_hdr *)exp_up_model_buf; - exp_updated_model_data = (struct s_fx *)exp_up_model_collection->entry; - /* put some dummy data in the header*/ - for (i = 0; i < sizeof(*exp_up_model_collection); i++) - exp_up_model_buf[i] = (uint8_t)i; - exp_updated_model_data[0].exp_flags = 0; - exp_updated_model_data[0].fx = 0; - exp_updated_model_data[1].exp_flags = 2; - exp_updated_model_data[1].fx = 0xBFFFFF; - exp_updated_model_data[2].exp_flags = 1; - exp_updated_model_data[2].fx = 0xBFFFFF; - exp_updated_model_data[3].exp_flags = 1; - exp_updated_model_data[3].fx = 0x7FFFFF; - - s = decompress_cmp_entiy(cmp_entity, model_buf, up_model_buf, decompressed_data); - TEST_ASSERT_EQUAL_INT(sizeof(exp_data_buf), s); - - TEST_ASSERT_FALSE(memcmp(exp_data_buf, decompressed_data, sizeof(exp_data_buf))); - TEST_ASSERT_FALSE(memcmp(exp_up_model_buf, up_model_buf, sizeof(exp_up_model_buf))); -} - - /** * @test cmp_ent_write_cmp_pars * @test cmp_ent_read_header @@ -1421,130 +1245,6 @@ void test_cmp_ent_write_cmp_pars(void) memset(&cfg, 0, sizeof(struct cmp_cfg)); memset(&cfg_read, 0, sizeof(struct cmp_cfg)); - /** flux cob data type test **/ - /* create configuration */ - cfg.data_type = DATA_TYPE_S_FX_EFX_NCOB_ECOB; - cfg.cmp_mode = CMP_MODE_MODEL_ZERO; - cfg.model_value = 11; - cfg.round = 2; - cfg.samples = 9; - cfg.spill_exp_flags = 1; - cfg.spill_fx = 2; - cfg.spill_ncob = 3; - cfg.spill_efx = 4; - cfg.spill_ecob = 5; - cfg.spill_fx_cob_variance = 6; - cfg.cmp_par_exp_flags = 7; - cfg.cmp_par_fx = 8; - cfg.cmp_par_ncob = 9; - cfg.cmp_par_efx = 10; - cfg.cmp_par_ecob = 11; - cfg.cmp_par_fx_cob_variance = 12; - cfg.max_used_bits = cmp_max_used_bits_list_get(42); - - /* create a compression entity */ - size = cmp_ent_create(NULL, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, 12); - TEST_ASSERT_NOT_EQUAL_INT(0, size); - ent = malloc(size); TEST_ASSERT_NOT_NULL(ent); - size = cmp_ent_create(ent, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, 12); - TEST_ASSERT_NOT_EQUAL_INT(0, size); - - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_FALSE(error); - - TEST_ASSERT_EQUAL_INT(cfg.data_type, cmp_ent_get_data_type(ent)); - TEST_ASSERT_EQUAL_INT(0, cmp_ent_get_data_type_raw_bit(ent)); - TEST_ASSERT_EQUAL_INT(12, cmp_ent_get_cmp_data_size(ent)); - - TEST_ASSERT_EQUAL_INT(cmp_cal_size_of_data(cfg.samples, cfg.data_type), cmp_ent_get_original_size(ent)); - TEST_ASSERT_EQUAL_INT(cfg.cmp_mode, cmp_ent_get_cmp_mode(ent)); - TEST_ASSERT_EQUAL_INT(cfg.model_value, cmp_ent_get_model_value(ent)); - TEST_ASSERT_EQUAL_INT(max_used_bits.version, cmp_ent_get_max_used_bits_version(ent)); - TEST_ASSERT_EQUAL_INT(cfg.round, cmp_ent_get_lossy_cmp_par(ent)); - - - TEST_ASSERT_EQUAL_INT(cfg.spill_exp_flags, cmp_ent_get_non_ima_spill1(ent)); - TEST_ASSERT_EQUAL_INT(cfg.spill_fx, cmp_ent_get_non_ima_spill2(ent)); - TEST_ASSERT_EQUAL_INT(cfg.spill_ncob, cmp_ent_get_non_ima_spill3(ent)); - TEST_ASSERT_EQUAL_INT(cfg.spill_efx, cmp_ent_get_non_ima_spill4(ent)); - TEST_ASSERT_EQUAL_INT(cfg.spill_ecob, cmp_ent_get_non_ima_spill5(ent)); - TEST_ASSERT_EQUAL_INT(cfg.spill_fx_cob_variance, cmp_ent_get_non_ima_spill6(ent)); - TEST_ASSERT_EQUAL_INT(cfg.cmp_par_exp_flags, cmp_ent_get_non_ima_cmp_par1(ent)); - TEST_ASSERT_EQUAL_INT(cfg.cmp_par_fx, cmp_ent_get_non_ima_cmp_par2(ent)); - TEST_ASSERT_EQUAL_INT(cfg.cmp_par_ncob, cmp_ent_get_non_ima_cmp_par3(ent)); - TEST_ASSERT_EQUAL_INT(cfg.cmp_par_efx, cmp_ent_get_non_ima_cmp_par4(ent)); - TEST_ASSERT_EQUAL_INT(cfg.cmp_par_ecob, cmp_ent_get_non_ima_cmp_par5(ent)); - TEST_ASSERT_EQUAL_INT(cfg.cmp_par_fx_cob_variance, cmp_ent_get_non_ima_cmp_par6(ent)); - - error = cmp_ent_read_header(ent, &cfg_read); - TEST_ASSERT_FALSE(error); - cfg.icu_output_buf = cmp_ent_get_data_buf(ent); /* quick fix that both cfg are equal */ - cfg.buffer_length = 12; /* quick fix that both cfg are equal */ - TEST_ASSERT_EQUAL_MEMORY(&cfg, &cfg_read, sizeof(struct cmp_cfg)); - - free(ent); - memset(&cfg, 0, sizeof(struct cmp_cfg)); - memset(&cfg_read, 0, sizeof(struct cmp_cfg)); - - /** auxiliary data data_type test **/ - /* create configuration */ - cfg.data_type = DATA_TYPE_SMEARING; - cfg.cmp_mode = CMP_MODE_MODEL_ZERO; - cfg.model_value = 11; - cfg.round = 2; - cfg.samples = 9; - cfg.spill_smearing_mean = 1; - cfg.spill_smearing_variance = 2; - cfg.spill_smearing_pixels_error = 3; - cfg.cmp_par_smearing_mean = 7; - cfg.cmp_par_smearing_variance = 8; - cfg.cmp_par_smearing_pixels_error = 9; - cfg.max_used_bits = cmp_max_used_bits_list_get(42); - - /* create a compression entity */ - size = cmp_ent_create(NULL, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, 12); - TEST_ASSERT_NOT_EQUAL_INT(0, size); - ent = malloc(size); TEST_ASSERT_NOT_NULL(ent); - size = cmp_ent_create(ent, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, 12); - TEST_ASSERT_NOT_EQUAL_INT(0, size); - - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_FALSE(error); - - TEST_ASSERT_EQUAL_INT(cfg.data_type, cmp_ent_get_data_type(ent)); - TEST_ASSERT_EQUAL_INT(0, cmp_ent_get_data_type_raw_bit(ent)); - TEST_ASSERT_EQUAL_INT(12, cmp_ent_get_cmp_data_size(ent)); - - TEST_ASSERT_EQUAL_INT(cmp_cal_size_of_data(cfg.samples, cfg.data_type), cmp_ent_get_original_size(ent)); - TEST_ASSERT_EQUAL_INT(cfg.cmp_mode, cmp_ent_get_cmp_mode(ent)); - TEST_ASSERT_EQUAL_INT(cfg.model_value, cmp_ent_get_model_value(ent)); - TEST_ASSERT_EQUAL_INT(max_used_bits.version, cmp_ent_get_max_used_bits_version(ent)); - TEST_ASSERT_EQUAL_INT(cfg.round, cmp_ent_get_lossy_cmp_par(ent)); - - - TEST_ASSERT_EQUAL_INT(0, cmp_ent_get_non_ima_spill1(ent)); - TEST_ASSERT_EQUAL_INT(0, cmp_ent_get_non_ima_spill2(ent)); - TEST_ASSERT_EQUAL_INT(0, cmp_ent_get_non_ima_spill3(ent)); - TEST_ASSERT_EQUAL_INT(cfg.spill_smearing_mean, cmp_ent_get_non_ima_spill4(ent)); - TEST_ASSERT_EQUAL_INT(cfg.spill_smearing_variance, cmp_ent_get_non_ima_spill5(ent)); - TEST_ASSERT_EQUAL_INT(cfg.spill_smearing_pixels_error, cmp_ent_get_non_ima_spill6(ent)); - TEST_ASSERT_EQUAL_INT(0, cmp_ent_get_non_ima_cmp_par1(ent)); - TEST_ASSERT_EQUAL_INT(0, cmp_ent_get_non_ima_cmp_par2(ent)); - TEST_ASSERT_EQUAL_INT(0, cmp_ent_get_non_ima_cmp_par3(ent)); - TEST_ASSERT_EQUAL_INT(cfg.cmp_par_smearing_mean, cmp_ent_get_non_ima_cmp_par4(ent)); - TEST_ASSERT_EQUAL_INT(cfg.cmp_par_smearing_variance, cmp_ent_get_non_ima_cmp_par5(ent)); - TEST_ASSERT_EQUAL_INT(cfg.cmp_par_smearing_pixels_error, cmp_ent_get_non_ima_cmp_par6(ent)); - - error = cmp_ent_read_header(ent, &cfg_read); - TEST_ASSERT_FALSE(error); - cfg.icu_output_buf = cmp_ent_get_data_buf(ent); /* quick fix that both cfg are equal */ - cfg.buffer_length = 12; /* quick fix that both cfg are equal */ - TEST_ASSERT_EQUAL_MEMORY(&cfg, &cfg_read, sizeof(struct cmp_cfg)); - - free(ent); - memset(&cfg, 0, sizeof(struct cmp_cfg)); - memset(&cfg_read, 0, sizeof(struct cmp_cfg)); - /** Error Cases **/ /* create imagette raw mode configuration */ cfg.data_type = DATA_TYPE_IMAGETTE; @@ -1796,8 +1496,8 @@ void test_cmp_ent_write_cmp_pars(void) TEST_ASSERT_TRUE(error); /* test data type = DATA_TYPE_F_CAM_BACKGROUND +1 */ - cmp_ent_set_data_type(ent, DATA_TYPE_F_CAM_BACKGROUND + 1, 0); - cfg.data_type = DATA_TYPE_F_CAM_BACKGROUND + 1; + cmp_ent_set_data_type(ent, DATA_TYPE_F_CAM_BACKGROUND + 10, 0); + cfg.data_type = DATA_TYPE_F_CAM_BACKGROUND + 10; error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); TEST_ASSERT_TRUE(error); free(ent); @@ -2032,6 +1732,56 @@ void test_cmp_ent_read_header_error_cases(void) } +/** + * @test decompress_cmp_entiy + */ + +void test_decompress_imagette_chunk_raw(void) +{ + int decmp_size; + size_t i; + uint16_t data[] = {0, 1, 2, 0x42, (uint16_t)INT16_MIN, INT16_MAX, UINT16_MAX}; + uint8_t *decompressed_data; + struct cmp_entity *ent; + uint32_t ent_size; + uint32_t chunk_size = 2*(COLLECTION_HDR_SIZE + sizeof(data)); + uint8_t *chunk = calloc(1, chunk_size); TEST_ASSERT_TRUE(chunk); + + for (i = 0; i < 2; i++) { + struct collection_hdr *col = (struct collection_hdr *)(chunk+chunk_size/2*i); + + TEST_ASSERT_FALSE(cmp_col_set_subservice(col, SST_NCxx_S_SCIENCE_IMAGETTE)); + TEST_ASSERT_FALSE(cmp_col_set_data_length(col, sizeof(data))); + TEST_ASSERT_FALSE(cmp_col_set_timestamp(col, 0x0102030400607)); + memcpy(col->entry, data, sizeof(data)); + } + + ent_size = cmp_ent_create(NULL, DATA_TYPE_CHUNK, 1, chunk_size); + TEST_ASSERT_EQUAL_INT(GENERIC_HEADER_SIZE+chunk_size, ent_size); + ent = malloc(ent_size); TEST_ASSERT_TRUE(ent); + ent_size = cmp_ent_create(ent, DATA_TYPE_CHUNK, 1, chunk_size); + TEST_ASSERT_EQUAL_INT(GENERIC_HEADER_SIZE+chunk_size, ent_size); + TEST_ASSERT_FALSE(cmp_ent_set_original_size(ent, chunk_size)); + memcpy(cmp_ent_get_data_buf(ent), chunk, chunk_size); + TEST_ASSERT_FALSE(cpu_to_be_chunk(cmp_ent_get_data_buf(ent), chunk_size)); + + decmp_size = decompress_cmp_entiy(ent, NULL, NULL, NULL); + TEST_ASSERT_EQUAL_INT(chunk_size, decmp_size); + decompressed_data = malloc((size_t)decmp_size); + TEST_ASSERT_TRUE(decompressed_data); + decmp_size = decompress_cmp_entiy(ent, NULL, NULL, decompressed_data); + TEST_ASSERT_EQUAL_INT(chunk_size, decmp_size); + + for (i = 0; i < chunk_size; ++i) + TEST_ASSERT_EQUAL_INT(chunk[i], decompressed_data[i]); + + + free(chunk); + free(ent); + free(decompressed_data); +} + + void test_decompression_error_cases(void) { /* TODO: error cases model decompression without a model Buffer */ diff --git a/test/test_common/meson.build b/test/test_common/meson.build index 56d233028906f36724e4d138c6ab98ceb218794a..082ac4c1c8a79e1e30ea3147bf445c513b569da7 100644 --- a/test/test_common/meson.build +++ b/test/test_common/meson.build @@ -4,5 +4,5 @@ pcb_dep = pcg_proj.get_variable('libpcg_basic_dep') test_common_lib = static_library( 'test_common', 'test_common.c', - dependencies: pcb_dep, + dependencies: [pcb_dep, unity_dep] ) diff --git a/test/test_common/test_common.c b/test/test_common/test_common.c index 37644a7f07c820cad0552069460cf8b48e400b89..4f90832be876c6d41c2f386d9911ff5b4034f606 100644 --- a/test/test_common/test_common.c +++ b/test/test_common/test_common.c @@ -1,7 +1,11 @@ -#include <assert.h> +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> #include "pcg_basic.h" +#include <unity.h> void cmp_rand_seed(uint64_t seed) { @@ -27,7 +31,7 @@ uint32_t cmp_rand32(void) uint32_t cmp_rand_between(uint32_t min, uint32_t max) { - assert(min < max); + TEST_ASSERT(min < max); return min + pcg32_boundedrand(max-min+1); } @@ -35,7 +39,26 @@ uint32_t cmp_rand_between(uint32_t min, uint32_t max) uint32_t cmp_rand_nbits(unsigned int nbits) { - assert(nbits > 0); + TEST_ASSERT(nbits > 0); return cmp_rand32() >> (32 - nbits); } + + +/** + * @brief allocates memory safely for tests + * + * @param size The size of memory to allocate. + * + * @returns a pointer to the allocated memory, or NULL if allocation fails + */ + +void* TEST_malloc(size_t size) +{ + if (size > 0) { + void* const mem = malloc(size); + TEST_ASSERT(mem); + return mem; + } + return NULL; +} diff --git a/test/test_common/test_common.h b/test/test_common/test_common.h index f0fd84aea743cf4d2f6b3239949977c61b472943..e27d68a860bd17083712c94e05d9476da3fd61bf 100644 --- a/test/test_common/test_common.h +++ b/test/test_common/test_common.h @@ -2,6 +2,7 @@ #define TEST_COMMON_H #include <stdint.h> +#include <stddef.h> void cmp_rand_seed(uint64_t seed); @@ -11,4 +12,6 @@ uint32_t cmp_rand_between(uint32_t min, uint32_t max); uint32_t cmp_rand_nbits(unsigned int nbits); +void* TEST_malloc(size_t size); + #endif /* TEST_COMMON_H */