* librz: rename function parameter The function parameter is renamed from _dest to dest. In the body of the function, the identifiers _dest and dest are swapped accordingly. This makes these functions have the same parameter name as all others of the same kind in the header. * librz: add swap macros when builtins missing The rz_swap_ macros are only defined when the compiler builtins are available. We define them in case they are not for uniformity of presence in the preprocessor namespace. * librz: add documentation for rz_endian.h Every function and macro is documented except for the signed swap macros. * librz: return max value in read if parameter is NULL The read functions in rz_endian.h sometimes returned the MAX value when the source parameter was NULL and sometimes didn't. For example, compare rz_read_be16 which doesn't check NULL and rz_read_le16 which does. We fix this by inserting checks for NULL in every integer read function. We also insert these checks for the floating-point read functions. They also too sometimes checked for NULL indirectly by calling the corresponding integer read functions, but the read functions with the offset parameter did not check for NULL. Separately, The NULL checks in rz_read_le8 and rz_read_me8 were removed because they were duplicate; they call rz_read_ble8 which checks for NULL. * librz: add documentation in swap functions for NULL source parameter The case where the source parameter is NULL is documented in all the read functions in rz_endian.h A mistake in the documentation of rz_read_at_ble64 is fixed; it incorrectly mentioned 128-bit instead of 64-bit integers. * librz: add missing 24-bit macros The 24-bit macros for minimum and maximum value are added. * librz: add missing endianness functions For the readers and writers, certain endianness and bit number combinations were missing. Some missing big-endian, little-endian, middle-endian functions as well as helper functions are added. The documentation of some read blue functions is corrected to mention "specified" order instead of "big-endian". * librz: fixing some compiler errors from typos * librz: remove UT24 macros We remove the UT24_ macros due to PR review. * librz: replace UT24_MAX with UT32_MAX It is better to return the maximum value held by the return type instead of returning a max 24-bit value. * test: add more rz_endian tests All the integral endian functions for read and write are ran through some basic tests. * librz: remove unused internal functions The signed rz_swap functions are removed because they are not used anywhere in the source code. They are duplicates of the corresponding unsigned functions. Moreover, the rz_swap_st16 function has an incorrect implementation when the compiler builtin is missing. Instead of fixing, adding documentation, and unit tests, which means we would also need to create an environment with the compiler builtin check undefined, we simply remove them, because they are not used anywhere. * librz: remove unnecessary define macros These macros were added during the PR and were requested to be removed again. * test: fix MSVC complaining on erroneous commas The string literal #__VA_ARGS__ is equal to "" in a conforming implementation when there is an empty list of variadic arguments. On MSVC 2017, it is completely missing, causing an error. These issues appear to have been fixed in VS2019 v16.5 and later using the /Zc:preprocessor compiler switch and in Visual Studio 2017 version 15.8 using /experimental:preprocessor. In any case, we use string concatenating to force an empty string to appear even if #__VA_ARGS__ is missing.
505 lines
17 KiB
C
505 lines
17 KiB
C
// SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
|
|
/** \internal
|
|
* \file
|
|
* \brief Test the functions in rz_endian.h
|
|
*/
|
|
|
|
#include <rz_util.h>
|
|
#include <rz_io.h>
|
|
#include <stdlib.h>
|
|
#include "minunit.h"
|
|
|
|
static const char data_pool[] =
|
|
"\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8"
|
|
"\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8";
|
|
|
|
#undef INPUT
|
|
#undef OFFSET
|
|
#undef ENDIANNESS
|
|
#undef SIZE
|
|
#undef RESULT
|
|
#undef BIG_ENDIAN
|
|
#undef LITTLE_ENDIAN
|
|
#undef MIDDLE_ENDIAN
|
|
#undef BE_TEST
|
|
#undef LE_TEST
|
|
#undef ME_TEST
|
|
#undef BE24_TEST
|
|
#undef LE24_TEST
|
|
#undef IS_be_SIZE
|
|
#undef IS_le_SIZE
|
|
#undef IS_me_SIZE
|
|
#undef IS_ble_SIZE
|
|
#undef MAKE_INTEGRAL_READ_TEST_AUX
|
|
#undef MAKE_INTEGRAL_READ_AT_TEST
|
|
#define INPUT(i) (rz_read_table[i].input)
|
|
#define OFFSET(i) (rz_read_table[i].offset)
|
|
#define ENDIANNESS(i) (rz_read_table[i].endianness)
|
|
#define SIZE(i) (rz_read_table[i].size)
|
|
#define RESULT(i) (rz_read_table[i].result)
|
|
#define BIG_ENDIAN 1
|
|
#define LITTLE_ENDIAN 2
|
|
#define MIDDLE_ENDIAN 3
|
|
|
|
/**
|
|
* \def BE_TEST Create entries in \c rz_read_table for big-endian unit tests.
|
|
*/
|
|
#define BE_TEST(input, offset, size) (&data_pool[input]), offset, BIG_ENDIAN, size, .result.u##size
|
|
/**
|
|
* \def LE_TEST Create entries in \c rz_read_table for little-endian unit tests.
|
|
*/
|
|
#define LE_TEST(input, offset, size) (&data_pool[input]), offset, LITTLE_ENDIAN, size, .result.u##size
|
|
/**
|
|
* \def ME_TEST Create entries in \c rz_read_table for middle-endian unit tests.
|
|
*/
|
|
#define ME_TEST(input, offset, size) (&data_pool[input]), offset, MIDDLE_ENDIAN, size, .result.u##size
|
|
/**
|
|
* \def BE24_TEST Create entries in \c rz_read_table for 24-bit big-endian unit tests.
|
|
*/
|
|
#define BE24_TEST(input, offset) (&data_pool[input]), offset, BIG_ENDIAN, 24, .result.u##32
|
|
/**
|
|
* \def LE24_TEST Create entries in \c rz_read_table for 24-bit little-endian unit tests.
|
|
*/
|
|
#define LE24_TEST(input, offset) (&data_pool[input]), offset, LITTLE_ENDIAN, 24, .result.u##32
|
|
|
|
/**
|
|
* \def IS_be_SIZE Check if entry is big-endian and of given size.
|
|
*/
|
|
#define IS_be_SIZE(i, N) (ENDIANNESS(i) == BIG_ENDIAN && SIZE(i) == N)
|
|
/**
|
|
* \def IS_le_SIZE Check if entry is little-endian and of given size.
|
|
*/
|
|
#define IS_le_SIZE(i, N) (ENDIANNESS(i) == LITTLE_ENDIAN && SIZE(i) == N)
|
|
/**
|
|
* \def IS_me_SIZE Check if entry is middle-endian and of given size.
|
|
*/
|
|
#define IS_me_SIZE(i, N) (ENDIANNESS(i) == MIDDLE_ENDIAN && SIZE(i) == N)
|
|
/**
|
|
* \def IS_ble_SIZE Check if entry is big- or little-endian and of given size.
|
|
*/
|
|
#define IS_ble_SIZE(i, N) ((ENDIANNESS(i) == BIG_ENDIAN || ENDIANNESS(i) == LITTLE_ENDIAN) && SIZE(i) == N)
|
|
|
|
static const struct {
|
|
const char *input; ///< source parameter of read function
|
|
size_t offset; ///< offset parameter of read functions
|
|
int endianness; ///< 1 = be, 2 = le, 3 = me
|
|
int size; ///< 32 for ut32, st32, or float, etc
|
|
union {
|
|
ut8 u8;
|
|
ut16 u16;
|
|
ut32 u32;
|
|
ut64 u64;
|
|
ut128 u128;
|
|
float f;
|
|
double d;
|
|
} result;
|
|
} rz_read_table[] = {
|
|
/* rz_read_be128, rz_read_at_be128 */
|
|
{ BE_TEST(0, 0, 128) = { .High = 0xA1A2A3A4A5A6A7A8, .Low = 0xB1B2B3B4B5B6B7B8 } },
|
|
{ BE_TEST(0, 16, 128) = { .High = 0xC1C2C3C4C5C6C7C8, .Low = 0xD1D2D3D4D5D6D7D8 } },
|
|
{ BE_TEST(8, 0, 128) = { .High = 0xB1B2B3B4B5B6B7B8, .Low = 0xC1C2C3C4C5C6C7C8 } },
|
|
{ BE_TEST(8, 8, 128) = { .High = 0xC1C2C3C4C5C6C7C8, .Low = 0xD1D2D3D4D5D6D7D8 } },
|
|
/* rz_reat_be64, rz_reat_at_be64 */
|
|
{ BE_TEST(0, 0, 64) = 0xA1A2A3A4A5A6A7A8 },
|
|
{ BE_TEST(0, 8, 64) = 0xB1B2B3B4B5B6B7B8 },
|
|
{ BE_TEST(8, 0, 64) = 0xB1B2B3B4B5B6B7B8 },
|
|
{ BE_TEST(8, 8, 64) = 0xC1C2C3C4C5C6C7C8 },
|
|
/* rz_reat_be32, rz_reat_at_be32 */
|
|
{ BE_TEST(0, 0, 32) = 0xA1A2A3A4 },
|
|
{ BE_TEST(0, 8, 32) = 0xB1B2B3B4 },
|
|
{ BE_TEST(8, 0, 32) = 0xB1B2B3B4 },
|
|
{ BE_TEST(8, 8, 32) = 0xC1C2C3C4 },
|
|
/* rz_reat_be24, rz_reat_at_be24 */
|
|
{ BE24_TEST(0, 0) = 0xA1A2A3 },
|
|
{ BE24_TEST(0, 8) = 0xB1B2B3 },
|
|
{ BE24_TEST(8, 0) = 0xB1B2B3 },
|
|
{ BE24_TEST(8, 8) = 0xC1C2C3 },
|
|
/* rz_reat_be16, rz_reat_at_be16 */
|
|
{ BE_TEST(0, 0, 16) = 0xA1A2 },
|
|
{ BE_TEST(0, 8, 16) = 0xB1B2 },
|
|
{ BE_TEST(8, 0, 16) = 0xB1B2 },
|
|
{ BE_TEST(8, 8, 16) = 0xC1C2 },
|
|
/* rz_read_le128, rz_read_at_le128 */
|
|
{ LE_TEST(0, 0, 128) = { .High = 0xB8B7B6B5B4B3B2B1, .Low = 0xA8A7A6A5A4A3A2A1 } },
|
|
{ LE_TEST(0, 16, 128) = { .High = 0xD8D7D6D5D4D3D2D1, .Low = 0xC8C7C6C5C4C3C2C1 } },
|
|
{ LE_TEST(8, 0, 128) = { .High = 0xC8C7C6C5C4C3C2C1, .Low = 0xB8B7B6B5B4B3B2B1 } },
|
|
{ LE_TEST(8, 8, 128) = { .High = 0xD8D7D6D5D4D3D2D1, .Low = 0xC8C7C6C5C4C3C2C1 } },
|
|
/* rz_reat_le64, rz_reat_at_le64 */
|
|
{ LE_TEST(0, 0, 64) = 0xA8A7A6A5A4A3A2A1 },
|
|
{ LE_TEST(0, 8, 64) = 0xB8B7B6B5B4B3B2B1 },
|
|
{ LE_TEST(8, 0, 64) = 0xB8B7B6B5B4B3B2B1 },
|
|
{ LE_TEST(8, 8, 64) = 0xC8C7C6C5C4C3C2C1 },
|
|
/* rz_reat_le32, rz_reat_at_le32 */
|
|
{ LE_TEST(0, 0, 32) = 0xA4A3A2A1 },
|
|
{ LE_TEST(0, 8, 32) = 0xB4B3B2B1 },
|
|
{ LE_TEST(8, 0, 32) = 0xB4B3B2B1 },
|
|
{ LE_TEST(8, 8, 32) = 0xC4C3C2C1 },
|
|
/* rz_reat_le24, rz_reat_at_le24 */
|
|
{ LE24_TEST(0, 0) = 0xA3A2A1 },
|
|
{ LE24_TEST(0, 8) = 0xB3B2B1 },
|
|
{ LE24_TEST(8, 0) = 0xB3B2B1 },
|
|
{ LE24_TEST(8, 8) = 0xC3C2C1 },
|
|
/* rz_reat_le16, rz_reat_at_le16 */
|
|
{ LE_TEST(0, 0, 16) = 0xA2A1 },
|
|
{ LE_TEST(0, 8, 16) = 0xB2B1 },
|
|
{ LE_TEST(8, 0, 16) = 0xB2B1 },
|
|
{ LE_TEST(8, 8, 16) = 0xC2C1 },
|
|
/* rz_reat_me64, rz_reat_at_me64 */
|
|
{ ME_TEST(0, 0, 64) = 0xA7A8A5A6A3A4A1A2 },
|
|
{ ME_TEST(0, 8, 64) = 0xB7B8B5B6B3B4B1B2 },
|
|
{ ME_TEST(8, 0, 64) = 0xB7B8B5B6B3B4B1B2 },
|
|
{ ME_TEST(8, 8, 64) = 0xC7C8C5C6C3C4C1C2 },
|
|
/* rz_reat_me32, rz_reat_at_me32 */
|
|
{ ME_TEST(0, 0, 32) = 0xA3A4A1A2 },
|
|
{ ME_TEST(0, 8, 32) = 0xB3B4B1B2 },
|
|
{ ME_TEST(8, 0, 32) = 0xB3B4B1B2 },
|
|
{ ME_TEST(8, 8, 32) = 0xC3C4C1C2 },
|
|
/* rz_reat_me16, rz_reat_at_me16 */
|
|
{ ME_TEST(0, 0, 16) = 0xA1A2 },
|
|
{ ME_TEST(0, 8, 16) = 0xB1B2 },
|
|
{ ME_TEST(8, 0, 16) = 0xB1B2 },
|
|
{ ME_TEST(8, 8, 16) = 0xC1C2 }
|
|
};
|
|
|
|
/* This is a helper macro, we later abstract away the vararg
|
|
detail.
|
|
*/
|
|
#define MAKE_INTEGRAL_READ_TEST_AUX(ret_type, endianness, size, ...) \
|
|
bool test_rz_read_##__VA_ARGS__##endianness##size() { \
|
|
char dest[1024]; \
|
|
size_t offset = 0; \
|
|
size_t i; \
|
|
ut##ret_type test_result = { 0 }; \
|
|
ut##ret_type actual_result = { 0 }; \
|
|
(void)offset; \
|
|
for (i = 0; i < sizeof rz_read_table / sizeof rz_read_table[0]; i++) { \
|
|
if (IS_##endianness##_SIZE(i, size)) { \
|
|
test_result = rz_read_aux_##endianness##size(1 < sizeof "" #__VA_ARGS__, INPUT(i), OFFSET(i)); \
|
|
actual_result = RESULT(i).u##ret_type; \
|
|
mu_assert_memeq((void *)&test_result, (void *)&actual_result, size / 8, "rz_read_" #__VA_ARGS__ #endianness #size); \
|
|
rz_write_aux_##endianness##size(1 < sizeof "" #__VA_ARGS__, dest, actual_result, OFFSET(i)); \
|
|
mu_assert_memeq((void *)&dest[OFFSET(i)], (void *)(INPUT(i) + OFFSET(i)), size / 8, "rz_write_" #__VA_ARGS__ #endianness #size); \
|
|
} \
|
|
} \
|
|
mu_end; \
|
|
}
|
|
|
|
/**
|
|
* \def MAKE_INTEGRAL_READ_TEST
|
|
* \brief Create an integral read test.
|
|
* \param ret_type The return type of the function.
|
|
* \param endianness The endianness of the function.
|
|
* \param size The read function of this size is called.
|
|
* \attention \p size and \p ret_type are different when calling the
|
|
* 24-bit functions because there is no 24-bit type, instead a \c ut32
|
|
* is returned.
|
|
* \attention The read test also tests the write functions. The name
|
|
* of the function that failed is correctly reported, so there is no
|
|
* confusion.
|
|
* \bug The offset should not be more than 512, otherwise a buffer
|
|
* overflow may occur. This issue can be solved by using malloc for
|
|
* the dest buffer to allocate at least \c offset+sizeof(ut128)
|
|
* bytes.
|
|
*
|
|
* The \p ret_type is one of \c 8, \c 16, \c 32, \c 64, \c 128. The \p
|
|
* size is one of \c 8, \c 16, \c 24, \c 32, \c 64, \c 128. The \p
|
|
* endianness is one of \c be, \c le, \c me.
|
|
*
|
|
* # Example
|
|
*
|
|
* Create two tests, \c test_rz_read_be64 and \c test_rz_read_at_be64.
|
|
* They test from data in \c data_pool and \c rz_read_table.
|
|
*
|
|
* \code{.c}
|
|
* MAKE_INTEGRAL_READ_TEST(64, be, 64)
|
|
* \endcode
|
|
*
|
|
* To create tests for the 24-bit big-endian version, use
|
|
*
|
|
* \code{.c}
|
|
* MAKE_INTEGRAL_READ_TEST(32, be, 24)
|
|
* \endcode
|
|
*
|
|
* The \c 32 here is the size of the return type of \c rz_read_be24,
|
|
* while \c 24 selects the 24-bit variant.
|
|
*/
|
|
#define MAKE_INTEGRAL_READ_TEST(ret_type, endianness, size) \
|
|
/* This helper function decides at runtime which version of the two \
|
|
rz_read functions (with offset and without) to call. The issue \
|
|
cannot be decided at preprocessing time because the number of \
|
|
arguments these functions take are not the same. */ \
|
|
ut##ret_type rz_read_aux_##endianness##size(bool at, const char *src, size_t offset) { \
|
|
if (at) { \
|
|
if (#endianness[2] && #size[1]) { \
|
|
return rz_read_at_ble##size(src, offset, #endianness[0] == 'b'); \
|
|
} else { \
|
|
return rz_read_at_##endianness##size(src, offset); \
|
|
} \
|
|
} else { \
|
|
if (#endianness[2] && #size[1]) { \
|
|
return rz_read_ble##size(&src[offset], #endianness[0] == 'b'); \
|
|
} else { \
|
|
return rz_read_##endianness##size(&src[offset]); \
|
|
} \
|
|
} \
|
|
} \
|
|
/* This helper function decides at runtime which version of the two \
|
|
rz_write functions (with offset and without) to call. The issue \
|
|
cannot be decided at preprocessing time because the number of \
|
|
arguments these functions take are not the same. */ \
|
|
void rz_write_aux_##endianness##size(bool at, char *dest, ut##ret_type val, size_t offset) { \
|
|
if (at) { \
|
|
if (#endianness[2] && #size[1]) { \
|
|
rz_write_at_ble##size(dest, val, #endianness[0] == 'b', offset); \
|
|
} else { \
|
|
rz_write_at_##endianness##size(dest, val, offset); \
|
|
} \
|
|
} else { \
|
|
if (#endianness[2] && #size[1]) { \
|
|
rz_write_ble##size(&dest[offset], val, #endianness[0] == 'b'); \
|
|
} else { \
|
|
rz_write_##endianness##size(&dest[offset], val); \
|
|
} \
|
|
} \
|
|
} \
|
|
MAKE_INTEGRAL_READ_TEST_AUX(ret_type, endianness, size, at_) \
|
|
MAKE_INTEGRAL_READ_TEST_AUX(ret_type, endianness, size)
|
|
|
|
MAKE_INTEGRAL_READ_TEST(128, be, 128)
|
|
MAKE_INTEGRAL_READ_TEST(64, be, 64)
|
|
MAKE_INTEGRAL_READ_TEST(32, be, 32)
|
|
MAKE_INTEGRAL_READ_TEST(32, be, 24)
|
|
MAKE_INTEGRAL_READ_TEST(16, be, 16)
|
|
|
|
MAKE_INTEGRAL_READ_TEST(128, le, 128)
|
|
MAKE_INTEGRAL_READ_TEST(64, le, 64)
|
|
MAKE_INTEGRAL_READ_TEST(32, le, 32)
|
|
MAKE_INTEGRAL_READ_TEST(32, le, 24)
|
|
MAKE_INTEGRAL_READ_TEST(16, le, 16)
|
|
|
|
MAKE_INTEGRAL_READ_TEST(64, me, 64)
|
|
MAKE_INTEGRAL_READ_TEST(32, me, 32)
|
|
MAKE_INTEGRAL_READ_TEST(16, me, 16)
|
|
|
|
/**
|
|
* \brief Test the 8-bit read and write endianness functions.
|
|
* \bug If \c data_pool grows larger than 1024 bytes, there will be a
|
|
* buffer overflow in this function. To fix this if necessary, use
|
|
* malloc to allocate at least \c sizeof(data_pool) bytes in \c buf.
|
|
*/
|
|
bool test_rz_read_8bit(void) {
|
|
ut8 buf[1024];
|
|
ut8 c;
|
|
size_t i;
|
|
for (i = 0; i < sizeof data_pool; i++) {
|
|
c = rz_read_be8(&data_pool[i]);
|
|
mu_assert_memeq((void *)&c, (void *)&data_pool[i], 1, "rz_read_be8");
|
|
rz_write_be8(buf, c);
|
|
mu_assert_memeq((void *)buf, (void *)&data_pool[i], 1, "rz_write_be8");
|
|
|
|
c = rz_read_le8(&data_pool[i]);
|
|
mu_assert_memeq((void *)&c, (void *)&data_pool[i], 1, "rz_read_le8");
|
|
rz_write_le8(buf, c);
|
|
mu_assert_memeq((void *)buf, (void *)&data_pool[i], 1, "rz_write_le8");
|
|
|
|
c = rz_read_me8(&data_pool[i]);
|
|
mu_assert_memeq((void *)&c, (void *)&data_pool[i], 1, "rz_read_me8");
|
|
rz_write_me8(buf, c);
|
|
mu_assert_memeq((void *)buf, (void *)&data_pool[i], 1, "rz_write_me8");
|
|
|
|
c = rz_read_ble8(&data_pool[i]);
|
|
mu_assert_memeq((void *)&c, (void *)&data_pool[i], 1, "rz_read_ble8");
|
|
rz_write_ble8(buf, c);
|
|
mu_assert_memeq((void *)buf, (void *)&data_pool[i], 1, "rz_write_ble8");
|
|
|
|
c = rz_read_at_be8(data_pool, i);
|
|
mu_assert_memeq((void *)&c, (void *)&data_pool[i], 1, "rz_read_at_be8");
|
|
rz_write_at_be8(buf, c, i);
|
|
mu_assert_memeq((void *)&buf[i], (void *)&data_pool[i], 1, "rz_write_at_be8");
|
|
|
|
c = rz_read_at_le8(data_pool, i);
|
|
mu_assert_memeq((void *)&c, (void *)&data_pool[i], 1, "rz_read_at_le8");
|
|
rz_write_at_le8(buf, c, i);
|
|
mu_assert_memeq((void *)&buf[i], (void *)&data_pool[i], 1, "rz_write_at_le8");
|
|
|
|
c = rz_read_at_me8(data_pool, i);
|
|
mu_assert_memeq((void *)&c, (void *)&data_pool[i], 1, "rz_read_at_me8");
|
|
rz_write_at_me8(buf, c, i);
|
|
mu_assert_memeq((void *)&buf[i], (void *)&data_pool[i], 1, "rz_write_at_me8");
|
|
|
|
c = rz_read_at_ble8(data_pool, i);
|
|
mu_assert_memeq((void *)&c, (void *)&data_pool[i], 1, "rz_read_at_ble8");
|
|
rz_write_at_ble8(buf, c, i);
|
|
mu_assert_memeq((void *)&buf[i], (void *)&data_pool[i], 1, "rz_write_at_ble8");
|
|
}
|
|
mu_end;
|
|
}
|
|
|
|
bool test_endian(void) {
|
|
ut8 buf[8];
|
|
rz_write_be16(buf, 0x1122);
|
|
mu_assert_memeq((ut8 *)"\x11\x22", buf, 2, "be16");
|
|
rz_write_le16(buf, 0x1122);
|
|
mu_assert_memeq((ut8 *)"\x22\x11", buf, 2, "le16");
|
|
|
|
rz_write_be32(buf, 0x11223344);
|
|
mu_assert_memeq((ut8 *)"\x11\x22\x33\x44", buf, 4, "be32");
|
|
rz_write_le32(buf, 0x11223344);
|
|
mu_assert_memeq((ut8 *)"\x44\x33\x22\x11", buf, 4, "le32");
|
|
|
|
rz_write_ble(buf, 0x1122, true, 16);
|
|
mu_assert_memeq((ut8 *)"\x11\x22", buf, 2, "ble 16 true");
|
|
rz_write_ble(buf, 0x1122, false, 16);
|
|
mu_assert_memeq((ut8 *)"\x22\x11", buf, 2, "ble 16 false");
|
|
|
|
mu_end;
|
|
}
|
|
|
|
bool test_rz_swap_ut64(void) {
|
|
ut64 a = 0x1122334455667788;
|
|
ut64 b = rz_swap_ut64(a);
|
|
mu_assert_eq(b, 0x8877665544332211, "rz_swap_ut64");
|
|
mu_end;
|
|
}
|
|
|
|
bool test_rz_swap_ut32(void) {
|
|
ut32 a = 0x11223344;
|
|
ut32 b = rz_swap_ut32(a);
|
|
mu_assert_eq(b, 0x44332211, "rz_swap_ut32");
|
|
mu_end;
|
|
}
|
|
|
|
bool test_rz_swap_ut16(void) {
|
|
ut16 a = 0x1122;
|
|
ut16 b = rz_swap_ut16(a);
|
|
mu_assert_eq(b, 0x2211, "rz_swap_ut16");
|
|
mu_end;
|
|
}
|
|
|
|
bool test_be(void) {
|
|
const float f32 = 5.728f;
|
|
const ut8 bf32[4] = { 0x40, 0xb7, 0x4b, 0xc7 };
|
|
const double f64 = 821.3987218732134;
|
|
const ut8 bf64[8] = { 0x40, 0x89, 0xab, 0x30, 0x95, 0x17, 0xed, 0x36 };
|
|
|
|
float val32;
|
|
double val64;
|
|
|
|
ut8 buffer[8] = { 0 };
|
|
|
|
val32 = rz_read_be_float(bf32);
|
|
mu_assert_eqf(val32, f32, "float big endian decoded");
|
|
|
|
val64 = rz_read_be_double(bf64);
|
|
mu_assert_eqf(val64, f64, "double big endian decoded");
|
|
|
|
rz_write_be_float(buffer, f32);
|
|
mu_assert_memeq(buffer, bf32, sizeof(bf32), "float big endian encoded");
|
|
|
|
rz_write_be_double(buffer, f64);
|
|
mu_assert_memeq(buffer, bf64, sizeof(bf64), "double big endian encoded");
|
|
|
|
mu_end;
|
|
}
|
|
|
|
bool test_le(void) {
|
|
const float f32 = 5.728f;
|
|
const ut8 bf32[4] = { 0xc7, 0x4b, 0xb7, 0x40 };
|
|
const double f64 = 821.3987218732134;
|
|
const ut8 bf64[8] = { 0x36, 0xed, 0x17, 0x95, 0x30, 0xab, 0x89, 0x40 };
|
|
|
|
float val32;
|
|
double val64;
|
|
|
|
ut8 buffer[8] = { 0 };
|
|
|
|
val32 = rz_read_le_float(bf32);
|
|
mu_assert_eqf(val32, f32, "float little endian decoded");
|
|
|
|
val64 = rz_read_le_double(bf64);
|
|
mu_assert_eqf(val64, f64, "double little endian decoded");
|
|
|
|
rz_write_le_float(buffer, f32);
|
|
mu_assert_memeq(buffer, bf32, sizeof(bf32), "float little endian encoded");
|
|
|
|
rz_write_le_double(buffer, f64);
|
|
mu_assert_memeq(buffer, bf64, sizeof(bf64), "double little endian encoded");
|
|
|
|
mu_end;
|
|
}
|
|
|
|
bool test_me(void) {
|
|
const float f32 = 5.728f;
|
|
const ut8 bf32[4] = { 0x4b, 0xc7, 0x40, 0xb7 };
|
|
const double f64 = 821.3987218732134;
|
|
const ut8 bf64[8] = { 0xed, 0x36, 0x95, 0x17, 0xab, 0x30, 0x40, 0x89 };
|
|
|
|
float val32;
|
|
double val64;
|
|
|
|
ut8 buffer[8] = { 0 };
|
|
|
|
val32 = rz_read_me_float(bf32);
|
|
mu_assert_eqf(val32, f32, "float middle endian decoded");
|
|
|
|
val64 = rz_read_me_double(bf64);
|
|
mu_assert_eqf(val64, f64, "double middle endian decoded");
|
|
|
|
rz_write_me_float(buffer, f32);
|
|
mu_assert_memeq(buffer, bf32, sizeof(bf32), "float middle endian encoded");
|
|
|
|
rz_write_me_double(buffer, f64);
|
|
mu_assert_memeq(buffer, bf64, sizeof(bf64), "double middle endian encoded");
|
|
|
|
mu_end;
|
|
}
|
|
|
|
int all_tests() {
|
|
/* big-endian read tests */
|
|
mu_run_test(test_rz_read_be128);
|
|
mu_run_test(test_rz_read_at_be128);
|
|
mu_run_test(test_rz_read_be64);
|
|
mu_run_test(test_rz_read_at_be64);
|
|
mu_run_test(test_rz_read_be32);
|
|
mu_run_test(test_rz_read_at_be32);
|
|
mu_run_test(test_rz_read_be24);
|
|
mu_run_test(test_rz_read_at_be24);
|
|
mu_run_test(test_rz_read_be16);
|
|
mu_run_test(test_rz_read_at_be16);
|
|
|
|
/* little-endian read tests */
|
|
mu_run_test(test_rz_read_le128);
|
|
mu_run_test(test_rz_read_at_le128);
|
|
mu_run_test(test_rz_read_le64);
|
|
mu_run_test(test_rz_read_at_le64);
|
|
mu_run_test(test_rz_read_le32);
|
|
mu_run_test(test_rz_read_at_le32);
|
|
mu_run_test(test_rz_read_le24);
|
|
mu_run_test(test_rz_read_at_le24);
|
|
mu_run_test(test_rz_read_le16);
|
|
mu_run_test(test_rz_read_at_le16);
|
|
|
|
/* middle-endian read tests */
|
|
mu_run_test(test_rz_read_me64);
|
|
mu_run_test(test_rz_read_at_me64);
|
|
mu_run_test(test_rz_read_me32);
|
|
mu_run_test(test_rz_read_at_me32);
|
|
mu_run_test(test_rz_read_me16);
|
|
mu_run_test(test_rz_read_at_me16);
|
|
|
|
/* 8-bit read/write tests */
|
|
mu_run_test(test_rz_read_8bit);
|
|
|
|
mu_run_test(test_endian);
|
|
mu_run_test(test_rz_swap_ut64);
|
|
mu_run_test(test_rz_swap_ut32);
|
|
mu_run_test(test_rz_swap_ut16);
|
|
mu_run_test(test_be);
|
|
mu_run_test(test_le);
|
|
mu_run_test(test_me);
|
|
return tests_passed != tests_run;
|
|
}
|
|
|
|
mu_main(all_tests)
|