diff --git a/src/bacnet/bacint.c b/src/bacnet/bacint.c index e3856426..df5d7a2c 100644 --- a/src/bacnet/bacint.c +++ b/src/bacnet/bacint.c @@ -424,7 +424,7 @@ int encode_signed32(uint8_t *apdu, int32_t value) int decode_signed32(uint8_t *apdu, int32_t *value) { - if (value) { + if (apdu && value) { *value = ((int32_t)((((int32_t)apdu[0]) << 24) & 0xff000000)); *value |= ((int32_t)((((int32_t)apdu[1]) << 16) & 0x00ff0000)); *value |= ((int32_t)((((int32_t)apdu[2]) << 8) & 0x0000ff00)); @@ -448,7 +448,7 @@ int bacnet_signed_length(int32_t value) len = 1; } else if ((value >= -32768) && (value < 32768)) { len = 2; - } else if ((value > -8388608) && (value < 8388608)) { + } else if ((value >= -8388608) && (value < 8388608)) { len = 3; } else { len = 4; diff --git a/test/unit/bacnet/bacint/CMakeLists.txt b/test/unit/bacnet/bacint/CMakeLists.txt new file mode 100644 index 00000000..be820026 --- /dev/null +++ b/test/unit/bacnet/bacint/CMakeLists.txt @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: MIT + +cmake_minimum_required(VERSION 3.10 FATAL_ERROR) + +get_filename_component(basename ${CMAKE_CURRENT_SOURCE_DIR} NAME) +project(test_${basename} + VERSION 1.0.0 + LANGUAGES C) + + +string(REGEX REPLACE + "/test/unit/bacnet/[a-zA-Z_/-]*$" + "/src" + SRC_DIR + ${CMAKE_CURRENT_SOURCE_DIR}) +string(REGEX REPLACE + "/test/unit/bacnet/[a-zA-Z_/-]*$" + "/test" + TST_DIR + ${CMAKE_CURRENT_SOURCE_DIR}) +set(ZTST_DIR "${TST_DIR}/ztest/src") + +add_compile_definitions( + BIG_ENDIAN=0 + CONFIG_ZTEST=1 + ) + +include_directories( + ${SRC_DIR} + ${TST_DIR}/ztest/include + ) + +add_executable(${PROJECT_NAME} + # File(s) under test + # NOTE: bits.h contains the complete implementation of the API. + # Support files and stubs (pathname alphabetical) + # Test and test library files + ./src/main.c + ${ZTST_DIR}/ztest_mock.c + ${ZTST_DIR}/ztest.c + ) diff --git a/test/unit/bacnet/bacint/src/main.c b/test/unit/bacnet/bacint/src/main.c new file mode 100644 index 00000000..157d3842 --- /dev/null +++ b/test/unit/bacnet/bacint/src/main.c @@ -0,0 +1,1021 @@ +/* + * Copyright (c) 2023 Legrand North America, LLC. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bacnet/bacint.c" + +#include +#include // for memset(), memcpy +#include + +static void test_unsigned16(void) +{ + uint8_t apdu[8] = { 0 }; + uint8_t test_apdu[8] = { 0 }; + uint16_t test_value = 0x1234U; + uint16_t value = 0; + + /* + * Verify invalid parameter detection and handling + */ + zassert_equal(2, encode_unsigned16(NULL, 0U), NULL); + zassert_equal(2, decode_unsigned16(NULL, NULL), NULL); + + value = 42; + zassert_equal(2, decode_unsigned16(NULL, &value), NULL); + zassert_equal(42, value, NULL); + + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + zassert_equal(2, decode_unsigned16(&apdu[2], NULL), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + + memset(test_apdu, 0xA5U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + zassert_equal(2, decode_unsigned16(&apdu[3], NULL), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + + /* + * Verify multi-byte write in correct order + */ + + /* Verify aligned access with no extra bytes written */ + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[2] = (uint8_t) (test_value >> 8); + test_apdu[3] = (uint8_t) (test_value >> 0); + zassert_equal(2, encode_unsigned16(&apdu[2], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(2, decode_unsigned16(&apdu[2], &value), NULL); + zassert_equal(test_value, value, NULL); + + memset(test_apdu, 0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[2] = (uint8_t) (test_value >> 8); + test_apdu[3] = (uint8_t) (test_value >> 0); + zassert_equal(2, encode_unsigned16(&apdu[2], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(2, decode_unsigned16(&apdu[2], &value), NULL); + zassert_equal(test_value, value, NULL); + + /* Verify unaligned access with no extra bytes written */ + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[3] = (uint8_t) (test_value >> 8); + test_apdu[4] = (uint8_t) (test_value >> 0); + zassert_equal(2, encode_unsigned16(&apdu[3], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(2, decode_unsigned16(&apdu[3], &value), NULL); + zassert_equal(test_value, value, NULL); + + memset(test_apdu, 0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[3] = (uint8_t) (test_value >> 8); + test_apdu[4] = (uint8_t) (test_value >> 0); + zassert_equal(2, encode_unsigned16(&apdu[3], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(2, decode_unsigned16(&apdu[3], &value), NULL); + zassert_equal(test_value, value, NULL); +} + +static void test_unsigned24(void) +{ + uint8_t apdu[8] = { 0 }; + uint8_t test_apdu[8] = { 0 }; + uint32_t test_value = 0x123456UL; + uint32_t value = 0; + + /* + * Verify invalid parameter detection and handling + */ + zassert_equal(3, encode_unsigned24(NULL, 0U), NULL); + zassert_equal(3, decode_unsigned24(NULL, NULL), NULL); + + value = 42; + zassert_equal(3, decode_unsigned24(NULL, &value), NULL); + zassert_equal(42, value, NULL); + + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + zassert_equal(3, decode_unsigned24(&apdu[2], NULL), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + + memset(test_apdu, 0xA5U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + zassert_equal(3, decode_unsigned24(&apdu[3], NULL), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + + /* + * Verify multi-byte write in correct order + */ + + /* Verify aligned access with no extra bytes written */ + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[2] = (uint8_t) (test_value >>16); + test_apdu[3] = (uint8_t) (test_value >> 8); + test_apdu[4] = (uint8_t) (test_value >> 0); + zassert_equal(3, encode_unsigned24(&apdu[2], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(3, decode_unsigned24(&apdu[2], &value), NULL); + zassert_equal(test_value, value, NULL); + + memset(test_apdu, 0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[2] = (uint8_t) (test_value >>16); + test_apdu[3] = (uint8_t) (test_value >> 8); + test_apdu[4] = (uint8_t) (test_value >> 0); + zassert_equal(3, encode_unsigned24(&apdu[2], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(3, decode_unsigned24(&apdu[2], &value), NULL); + zassert_equal(test_value, value, NULL); + + /* Verify unaligned access with no extra bytes written */ + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[3] = (uint8_t) (test_value >>16); + test_apdu[4] = (uint8_t) (test_value >> 8); + test_apdu[5] = (uint8_t) (test_value >> 0); + zassert_equal(3, encode_unsigned24(&apdu[3], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(3, decode_unsigned24(&apdu[3], &value), NULL); + zassert_equal(test_value, value, NULL); + + memset(test_apdu, 0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[3] = (uint8_t) (test_value >>16); + test_apdu[4] = (uint8_t) (test_value >> 8); + test_apdu[5] = (uint8_t) (test_value >> 0); + zassert_equal(3, encode_unsigned24(&apdu[3], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(3, decode_unsigned24(&apdu[3], &value), NULL); + zassert_equal(test_value, value, NULL); +} + +static void test_unsigned32(void) +{ + uint8_t apdu[8] = { 0 }; + uint8_t test_apdu[8] = { 0 }; + uint32_t test_value = 0x12345678UL; + uint32_t value = 0; + + /* + * Verify invalid parameter detection and handling + */ + zassert_equal(4, encode_unsigned32(NULL, 0U), NULL); + zassert_equal(4, decode_unsigned32(NULL, NULL), NULL); + + value = 42; + zassert_equal(4, decode_unsigned32(NULL, &value), NULL); + zassert_equal(42, value, NULL); + + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + zassert_equal(4, decode_unsigned32(&apdu[2], NULL), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + + memset(test_apdu, 0xA5U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + zassert_equal(4, decode_unsigned32(&apdu[3], NULL), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + + /* + * Verify multi-byte write in correct order + */ + + /* Verify aligned access with no extra bytes written */ + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[2] = (uint8_t) (test_value >>24); + test_apdu[3] = (uint8_t) (test_value >>16); + test_apdu[4] = (uint8_t) (test_value >> 8); + test_apdu[5] = (uint8_t) (test_value >> 0); + zassert_equal(4, encode_unsigned32(&apdu[2], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(4, decode_unsigned32(&apdu[2], &value), NULL); + zassert_equal(test_value, value, NULL); + + memset(test_apdu, 0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[2] = (uint8_t) (test_value >>24); + test_apdu[3] = (uint8_t) (test_value >>16); + test_apdu[4] = (uint8_t) (test_value >> 8); + test_apdu[5] = (uint8_t) (test_value >> 0); + zassert_equal(4, encode_unsigned32(&apdu[2], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(4, decode_unsigned32(&apdu[2], &value), NULL); + zassert_equal(test_value, value, NULL); + + /* Verify unaligned access with no extra bytes written */ + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[3] = (uint8_t) (test_value >>24); + test_apdu[4] = (uint8_t) (test_value >>16); + test_apdu[5] = (uint8_t) (test_value >> 8); + test_apdu[6] = (uint8_t) (test_value >> 0); + zassert_equal(4, encode_unsigned32(&apdu[3], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(4, decode_unsigned32(&apdu[3], &value), NULL); + zassert_equal(test_value, value, NULL); + + memset(test_apdu, 0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[3] = (uint8_t) (test_value >>24); + test_apdu[4] = (uint8_t) (test_value >>16); + test_apdu[5] = (uint8_t) (test_value >> 8); + test_apdu[6] = (uint8_t) (test_value >> 0); + zassert_equal(4, encode_unsigned32(&apdu[3], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(4, decode_unsigned32(&apdu[3], &value), NULL); + zassert_equal(test_value, value, NULL); +} + +static void test_unsigned40(void) +{ +#ifdef UINT64_MAX + uint8_t apdu[12] = { 0 }; + uint8_t test_apdu[12] = { 0 }; + uint64_t test_value = 0x123456789AULL; + uint64_t value = 0; + + /* + * Verify invalid parameter detection and handling + */ + zassert_equal(5, encode_unsigned40(NULL, 0U), NULL); + zassert_equal(5, decode_unsigned40(NULL, NULL), NULL); + + value = 42; + zassert_equal(5, decode_unsigned40(NULL, &value), NULL); + zassert_equal(42, value, NULL); + + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + zassert_equal(5, decode_unsigned40(&apdu[2], NULL), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + + memset(test_apdu, 0xA5U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + zassert_equal(5, decode_unsigned40(&apdu[3], NULL), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + + /* + * Verify multi-byte write in correct order + */ + + /* Verify aligned access with no extra bytes written */ + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[2] = (uint8_t) (test_value >>32); + test_apdu[3] = (uint8_t) (test_value >>24); + test_apdu[4] = (uint8_t) (test_value >>16); + test_apdu[5] = (uint8_t) (test_value >> 8); + test_apdu[6] = (uint8_t) (test_value >> 0); + zassert_equal(5, encode_unsigned40(&apdu[2], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(5, decode_unsigned40(&apdu[2], &value), NULL); + zassert_equal(test_value, value, NULL); + + memset(test_apdu, 0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[2] = (uint8_t) (test_value >>32); + test_apdu[3] = (uint8_t) (test_value >>24); + test_apdu[4] = (uint8_t) (test_value >>16); + test_apdu[5] = (uint8_t) (test_value >> 8); + test_apdu[6] = (uint8_t) (test_value >> 0); + zassert_equal(5, encode_unsigned40(&apdu[2], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(5, decode_unsigned40(&apdu[2], &value), NULL); + zassert_equal(test_value, value, NULL); + + /* Verify unaligned access with no extra bytes written */ + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[3] = (uint8_t) (test_value >>32); + test_apdu[4] = (uint8_t) (test_value >>24); + test_apdu[5] = (uint8_t) (test_value >>16); + test_apdu[6] = (uint8_t) (test_value >> 8); + test_apdu[7] = (uint8_t) (test_value >> 0); + zassert_equal(5, encode_unsigned40(&apdu[3], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(5, decode_unsigned40(&apdu[3], &value), NULL); + zassert_equal(test_value, value, NULL); + + memset(test_apdu, 0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[3] = (uint8_t) (test_value >>32); + test_apdu[4] = (uint8_t) (test_value >>24); + test_apdu[5] = (uint8_t) (test_value >>16); + test_apdu[6] = (uint8_t) (test_value >> 8); + test_apdu[7] = (uint8_t) (test_value >> 0); + zassert_equal(5, encode_unsigned40(&apdu[3], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(5, decode_unsigned40(&apdu[3], &value), NULL); + zassert_equal(test_value, value, NULL); +#else +#if (defined(__ZEPHYR__) && defined(KERNEL)) + ztest_test_skip(); +#else + ztest_test_pass(); +#endif +#endif /* defined(UINT64_MAX) */ +} + +static void test_unsigned48(void) +{ +#ifdef UINT64_MAX + uint8_t apdu[12] = { 0 }; + uint8_t test_apdu[12] = { 0 }; + uint64_t test_value = 0x123456789ABCULL; + uint64_t value = 0; + + /* + * Verify invalid parameter detection and handling + */ + zassert_equal(6, encode_unsigned48(NULL, 0U), NULL); + zassert_equal(6, decode_unsigned48(NULL, NULL), NULL); + + value = 42; + zassert_equal(6, decode_unsigned48(NULL, &value), NULL); + zassert_equal(42, value, NULL); + + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + zassert_equal(6, decode_unsigned48(&apdu[2], NULL), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + + memset(test_apdu, 0xA5U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + zassert_equal(6, decode_unsigned48(&apdu[3], NULL), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + + /* + * Verify multi-byte write in correct order + */ + + /* Verify aligned access with no extra bytes written */ + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[2] = (uint8_t) (test_value >>40); + test_apdu[3] = (uint8_t) (test_value >>32); + test_apdu[4] = (uint8_t) (test_value >>24); + test_apdu[5] = (uint8_t) (test_value >>16); + test_apdu[6] = (uint8_t) (test_value >> 8); + test_apdu[7] = (uint8_t) (test_value >> 0); + zassert_equal(6, encode_unsigned48(&apdu[2], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(6, decode_unsigned48(&apdu[2], &value), NULL); + zassert_equal(test_value, value, NULL); + + memset(test_apdu, 0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[2] = (uint8_t) (test_value >>40); + test_apdu[3] = (uint8_t) (test_value >>32); + test_apdu[4] = (uint8_t) (test_value >>24); + test_apdu[5] = (uint8_t) (test_value >>16); + test_apdu[6] = (uint8_t) (test_value >> 8); + test_apdu[7] = (uint8_t) (test_value >> 0); + zassert_equal(6, encode_unsigned48(&apdu[2], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(6, decode_unsigned48(&apdu[2], &value), NULL); + zassert_equal(test_value, value, NULL); + + /* Verify unaligned access with no extra bytes written */ + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[3] = (uint8_t) (test_value >>40); + test_apdu[4] = (uint8_t) (test_value >>32); + test_apdu[5] = (uint8_t) (test_value >>24); + test_apdu[6] = (uint8_t) (test_value >>16); + test_apdu[7] = (uint8_t) (test_value >> 8); + test_apdu[8] = (uint8_t) (test_value >> 0); + zassert_equal(6, encode_unsigned48(&apdu[3], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(6, decode_unsigned48(&apdu[3], &value), NULL); + zassert_equal(test_value, value, NULL); + + memset(test_apdu, 0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[3] = (uint8_t) (test_value >>40); + test_apdu[4] = (uint8_t) (test_value >>32); + test_apdu[5] = (uint8_t) (test_value >>24); + test_apdu[6] = (uint8_t) (test_value >>16); + test_apdu[7] = (uint8_t) (test_value >> 8); + test_apdu[8] = (uint8_t) (test_value >> 0); + zassert_equal(6, encode_unsigned48(&apdu[3], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(6, decode_unsigned48(&apdu[3], &value), NULL); + zassert_equal(test_value, value, NULL); +#else +#if (defined(__ZEPHYR__) && defined(KERNEL)) + ztest_test_skip(); +#else + ztest_test_pass(); +#endif +#endif /* defined(UINT64_MAX) */ +} + +static void test_unsigned56(void) +{ +#ifdef UINT64_MAX + uint8_t apdu[12] = { 0 }; + uint8_t test_apdu[12] = { 0 }; + uint64_t test_value = 0x123456789ABCDEULL; + uint64_t value = 0; + + /* + * Verify invalid parameter detection and handling + */ + zassert_equal(7, encode_unsigned56(NULL, 0U), NULL); + zassert_equal(7, decode_unsigned56(NULL, NULL), NULL); + + value = 42; + zassert_equal(7, decode_unsigned56(NULL, &value), NULL); + zassert_equal(42, value, NULL); + + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + zassert_equal(7, decode_unsigned56(&apdu[2], NULL), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + + memset(test_apdu, 0xA5U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + zassert_equal(7, decode_unsigned56(&apdu[3], NULL), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + + /* + * Verify multi-byte write in correct order + */ + + /* Verify aligned access with no extra bytes written */ + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[2] = (uint8_t) (test_value >>48); + test_apdu[3] = (uint8_t) (test_value >>40); + test_apdu[4] = (uint8_t) (test_value >>32); + test_apdu[5] = (uint8_t) (test_value >>24); + test_apdu[6] = (uint8_t) (test_value >>16); + test_apdu[7] = (uint8_t) (test_value >> 8); + test_apdu[8] = (uint8_t) (test_value >> 0); + zassert_equal(7, encode_unsigned56(&apdu[2], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(7, decode_unsigned56(&apdu[2], &value), NULL); + zassert_equal(test_value, value, NULL); + + memset(test_apdu, 0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[2] = (uint8_t) (test_value >>48); + test_apdu[3] = (uint8_t) (test_value >>40); + test_apdu[4] = (uint8_t) (test_value >>32); + test_apdu[5] = (uint8_t) (test_value >>24); + test_apdu[6] = (uint8_t) (test_value >>16); + test_apdu[7] = (uint8_t) (test_value >> 8); + test_apdu[8] = (uint8_t) (test_value >> 0); + zassert_equal(7, encode_unsigned56(&apdu[2], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(7, decode_unsigned56(&apdu[2], &value), NULL); + zassert_equal(test_value, value, NULL); + + /* Verify unaligned access with no extra bytes written */ + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[3] = (uint8_t) (test_value >>48); + test_apdu[4] = (uint8_t) (test_value >>40); + test_apdu[5] = (uint8_t) (test_value >>32); + test_apdu[6] = (uint8_t) (test_value >>24); + test_apdu[7] = (uint8_t) (test_value >>16); + test_apdu[8] = (uint8_t) (test_value >> 8); + test_apdu[9] = (uint8_t) (test_value >> 0); + zassert_equal(7, encode_unsigned56(&apdu[3], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(7, decode_unsigned56(&apdu[3], &value), NULL); + zassert_equal(test_value, value, NULL); + + memset(test_apdu, 0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[3] = (uint8_t) (test_value >>48); + test_apdu[4] = (uint8_t) (test_value >>40); + test_apdu[5] = (uint8_t) (test_value >>32); + test_apdu[6] = (uint8_t) (test_value >>24); + test_apdu[7] = (uint8_t) (test_value >>16); + test_apdu[8] = (uint8_t) (test_value >> 8); + test_apdu[9] = (uint8_t) (test_value >> 0); + zassert_equal(7, encode_unsigned56(&apdu[3], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(7, decode_unsigned56(&apdu[3], &value), NULL); + zassert_equal(test_value, value, NULL); +#else +#if (defined(__ZEPHYR__) && defined(KERNEL)) + ztest_test_skip(); +#else + ztest_test_pass(); +#endif +#endif /* defined(UINT64_MAX) */ +} + +static void test_unsigned64(void) +{ +#ifdef UINT64_MAX + uint8_t apdu[12] = { 0 }; + uint8_t test_apdu[12] = { 0 }; + uint64_t test_value = 0x123456789ABCDEF0ULL; + uint64_t value = 0; + + /* + * Verify invalid parameter detection and handling + */ + zassert_equal(8, encode_unsigned64(NULL, 0U), NULL); + zassert_equal(8, decode_unsigned64(NULL, NULL), NULL); + + value = 42; + zassert_equal(8, decode_unsigned64(NULL, &value), NULL); + zassert_equal(42, value, NULL); + + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + zassert_equal(8, decode_unsigned64(&apdu[2], NULL), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + + memset(test_apdu, 0xA5U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + zassert_equal(8, decode_unsigned64(&apdu[3], NULL), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + + /* + * Verify multi-byte write in correct order + */ + + /* Verify aligned access with no extra bytes written */ + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[2] = (uint8_t) (test_value >>56); + test_apdu[3] = (uint8_t) (test_value >>48); + test_apdu[4] = (uint8_t) (test_value >>40); + test_apdu[5] = (uint8_t) (test_value >>32); + test_apdu[6] = (uint8_t) (test_value >>24); + test_apdu[7] = (uint8_t) (test_value >>16); + test_apdu[8] = (uint8_t) (test_value >> 8); + test_apdu[9] = (uint8_t) (test_value >> 0); + zassert_equal(8, encode_unsigned64(&apdu[2], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(8, decode_unsigned64(&apdu[2], &value), NULL); + zassert_equal(test_value, value, NULL); + + memset(test_apdu, 0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[2] = (uint8_t) (test_value >>56); + test_apdu[3] = (uint8_t) (test_value >>48); + test_apdu[4] = (uint8_t) (test_value >>40); + test_apdu[5] = (uint8_t) (test_value >>32); + test_apdu[6] = (uint8_t) (test_value >>24); + test_apdu[7] = (uint8_t) (test_value >>16); + test_apdu[8] = (uint8_t) (test_value >> 8); + test_apdu[9] = (uint8_t) (test_value >> 0); + zassert_equal(8, encode_unsigned64(&apdu[2], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(8, decode_unsigned64(&apdu[2], &value), NULL); + zassert_equal(test_value, value, NULL); + + /* Verify unaligned access with no extra bytes written */ + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[3] = (uint8_t) (test_value >>56); + test_apdu[4] = (uint8_t) (test_value >>48); + test_apdu[5] = (uint8_t) (test_value >>40); + test_apdu[6] = (uint8_t) (test_value >>32); + test_apdu[7] = (uint8_t) (test_value >>24); + test_apdu[8] = (uint8_t) (test_value >>16); + test_apdu[9] = (uint8_t) (test_value >> 8); + test_apdu[10] = (uint8_t) (test_value >> 0); + zassert_equal(8, encode_unsigned64(&apdu[3], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(8, decode_unsigned64(&apdu[3], &value), NULL); + zassert_equal(test_value, value, NULL); + + memset(test_apdu, 0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[3] = (uint8_t) (test_value >>56); + test_apdu[4] = (uint8_t) (test_value >>48); + test_apdu[5] = (uint8_t) (test_value >>40); + test_apdu[6] = (uint8_t) (test_value >>32); + test_apdu[7] = (uint8_t) (test_value >>24); + test_apdu[8] = (uint8_t) (test_value >>16); + test_apdu[9] = (uint8_t) (test_value >> 8); + test_apdu[10] = (uint8_t) (test_value >> 0); + zassert_equal(8, encode_unsigned64(&apdu[3], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(8, decode_unsigned64(&apdu[3], &value), NULL); + zassert_equal(test_value, value, NULL); +#else +#if (defined(__ZEPHYR__) && defined(KERNEL)) + ztest_test_skip(); +#else + ztest_test_pass(); +#endif +#endif /* defined(UINT64_MAX) */ +} + +static void test_unsigned_length(void) +{ + zassert_equal(1, bacnet_unsigned_length(0), NULL); + zassert_equal(1, bacnet_unsigned_length(0x7EUL), NULL); + zassert_equal(1, bacnet_unsigned_length(0xFFUL), NULL); + + zassert_equal(2, bacnet_unsigned_length(1UL << 8), NULL); + zassert_equal(2, bacnet_unsigned_length(0x7DUL << 8), NULL); + zassert_equal(2, bacnet_unsigned_length(0xFFUL << 8), NULL); + zassert_equal(2, bacnet_unsigned_length(0xFFFFUL), NULL); + + zassert_equal(3, bacnet_unsigned_length(1UL <<16), NULL); + zassert_equal(3, bacnet_unsigned_length(0x7DUL <<16), NULL); + zassert_equal(3, bacnet_unsigned_length(0xFFUL <<16), NULL); + zassert_equal(3, bacnet_unsigned_length(0xFFFFFFUL), NULL); + + zassert_equal(4, bacnet_unsigned_length(1UL <<24), NULL); + zassert_equal(4, bacnet_unsigned_length(0x7DUL <<24), NULL); + zassert_equal(4, bacnet_unsigned_length(0xFFUL <<24), NULL); + zassert_equal(4, bacnet_unsigned_length(0xFFFFFFFFUL), NULL); + +#ifdef UINT64_MAX + zassert_equal(5, bacnet_unsigned_length(1ULL <<32), NULL); + zassert_equal(5, bacnet_unsigned_length(0x7DULL <<32), NULL); + zassert_equal(5, bacnet_unsigned_length(0xFFULL <<32), NULL); + zassert_equal(5, bacnet_unsigned_length(0xFFFFFFFFFFULL), NULL); + + zassert_equal(6, bacnet_unsigned_length(1ULL <<40), NULL); + zassert_equal(6, bacnet_unsigned_length(0x7DULL <<40), NULL); + zassert_equal(6, bacnet_unsigned_length(0xFFULL <<40), NULL); + zassert_equal(6, bacnet_unsigned_length(0xFFFFFFFFFFFFULL), NULL); + + zassert_equal(7, bacnet_unsigned_length(1ULL <<48), NULL); + zassert_equal(7, bacnet_unsigned_length(0x7DULL <<48), NULL); + zassert_equal(7, bacnet_unsigned_length(0xFFULL <<48), NULL); + zassert_equal(7, bacnet_unsigned_length(0xFFFFFFFFFFFFFFULL), NULL); + + zassert_equal(8, bacnet_unsigned_length(1ULL <<56), NULL); + zassert_equal(8, bacnet_unsigned_length(0x7DULL <<56), NULL); + zassert_equal(8, bacnet_unsigned_length(0xFFULL <<56), NULL); + zassert_equal(8, bacnet_unsigned_length(0xFFFFFFFFFFFFFFFFULL), NULL); +#endif +} + +static void test_signed8(void) +{ +#if BACNET_USE_SIGNED + uint8_t apdu[8] = { 0 }; + uint8_t test_apdu[8] = { 0 }; + int8_t test_value = 0x21; + int32_t value = 0; + + /* + * Verify invalid parameter detection and handling + */ + zassert_equal(1, encode_signed8(NULL, 0), NULL); + zassert_equal(1, decode_signed8(NULL, NULL), NULL); + + value = 42; + zassert_equal(1, decode_signed8(NULL, &value), NULL); + zassert_equal(42, value, NULL); + + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + zassert_equal(1, decode_signed8(&apdu[2], NULL), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + + memset(test_apdu, 0xA5U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + zassert_equal(1, decode_signed8(&apdu[3], NULL), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + + /* + * Verify multi-byte write in correct order + */ + + /* Verify aligned access with no extra bytes written */ + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[2] = (uint8_t) (test_value >> 0); + zassert_equal(1, encode_signed8(&apdu[2], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(1, decode_signed8(&apdu[2], &value), NULL); + zassert_equal(test_value, value, NULL); + + memset(test_apdu, 0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[2] = (uint8_t) (test_value >> 0); + zassert_equal(1, encode_signed8(&apdu[2], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(1, decode_signed8(&apdu[2], &value), NULL); + zassert_equal(test_value, value, NULL); + + /* Verify unaligned access with no extra bytes written */ + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[3] = (uint8_t) (test_value >> 0); + zassert_equal(1, encode_signed8(&apdu[3], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(1, decode_signed8(&apdu[3], &value), NULL); + zassert_equal(test_value, value, NULL); + + memset(test_apdu, 0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[3] = (uint8_t) (test_value >> 0); + zassert_equal(1, encode_signed8(&apdu[3], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(1, decode_signed8(&apdu[3], &value), NULL); + zassert_equal(test_value, value, NULL); +#else +#if (defined(__ZEPHYR__) && defined(KERNEL)) + ztest_test_skip(); +#else + ztest_test_pass(); +#endif +#endif /* BACNET_USE_SIGNED */ +} + +static void test_signed16(void) +{ +#if BACNET_USE_SIGNED + uint8_t apdu[8] = { 0 }; + uint8_t test_apdu[8] = { 0 }; + int16_t test_value = 0x4321; + int32_t value = 0; + + /* + * Verify invalid parameter detection and handling + */ + zassert_equal(2, encode_signed16(NULL, 0U), NULL); + zassert_equal(2, decode_signed16(NULL, NULL), NULL); + + value = 42; + zassert_equal(2, decode_signed16(NULL, &value), NULL); + zassert_equal(42, value, NULL); + + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + zassert_equal(2, decode_signed16(&apdu[2], NULL), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + + memset(test_apdu, 0xA5U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + zassert_equal(2, decode_signed16(&apdu[3], NULL), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + + /* + * Verify multi-byte write in correct order + */ + + /* Verify aligned access with no extra bytes written */ + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[2] = (uint8_t) (test_value >> 8); + test_apdu[3] = (uint8_t) (test_value >> 0); + zassert_equal(2, encode_signed16(&apdu[2], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(2, decode_signed16(&apdu[2], &value), NULL); + zassert_equal(test_value, value, NULL); + + memset(test_apdu, 0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[2] = (uint8_t) (test_value >> 8); + test_apdu[3] = (uint8_t) (test_value >> 0); + zassert_equal(2, encode_signed16(&apdu[2], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(2, decode_signed16(&apdu[2], &value), NULL); + zassert_equal(test_value, value, NULL); + + /* Verify unaligned access with no extra bytes written */ + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[3] = (uint8_t) (test_value >> 8); + test_apdu[4] = (uint8_t) (test_value >> 0); + zassert_equal(2, encode_signed16(&apdu[3], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(2, decode_signed16(&apdu[3], &value), NULL); + zassert_equal(test_value, value, NULL); + + memset(test_apdu, 0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[3] = (uint8_t) (test_value >> 8); + test_apdu[4] = (uint8_t) (test_value >> 0); + zassert_equal(2, encode_signed16(&apdu[3], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(2, decode_signed16(&apdu[3], &value), NULL); + zassert_equal(test_value, value, NULL); +#else + ztest_test_skip(); +#endif /* BACNET_USE_SIGNED */ +} + +static void test_signed24(void) +{ +#if BACNET_USE_SIGNED + uint8_t apdu[8] = { 0 }; + uint8_t test_apdu[8] = { 0 }; + int32_t test_value = 0x123456L; + int32_t value = 0; + + /* + * Verify invalid parameter detection and handling + */ + zassert_equal(3, encode_signed24(NULL, 0U), NULL); + zassert_equal(3, decode_signed24(NULL, NULL), NULL); + + value = 42; + zassert_equal(3, decode_signed24(NULL, &value), NULL); + zassert_equal(42, value, NULL); + + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + zassert_equal(3, decode_signed24(&apdu[2], NULL), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + + memset(test_apdu, 0xA5U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + zassert_equal(3, decode_signed24(&apdu[3], NULL), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + + /* + * Verify multi-byte write in correct order + */ + + /* Verify aligned access with no extra bytes written */ + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[2] = (uint8_t) (test_value >>16); + test_apdu[3] = (uint8_t) (test_value >> 8); + test_apdu[4] = (uint8_t) (test_value >> 0); + zassert_equal(3, encode_signed24(&apdu[2], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(3, decode_signed24(&apdu[2], &value), NULL); + zassert_equal(test_value, value, NULL); + + memset(test_apdu, 0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[2] = (uint8_t) (test_value >>16); + test_apdu[3] = (uint8_t) (test_value >> 8); + test_apdu[4] = (uint8_t) (test_value >> 0); + zassert_equal(3, encode_signed24(&apdu[2], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(3, decode_signed24(&apdu[2], &value), NULL); + zassert_equal(test_value, value, NULL); + + /* Verify unaligned access with no extra bytes written */ + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[3] = (uint8_t) (test_value >>16); + test_apdu[4] = (uint8_t) (test_value >> 8); + test_apdu[5] = (uint8_t) (test_value >> 0); + zassert_equal(3, encode_signed24(&apdu[3], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(3, decode_signed24(&apdu[3], &value), NULL); + zassert_equal(test_value, value, NULL); + + memset(test_apdu, 0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[3] = (uint8_t) (test_value >>16); + test_apdu[4] = (uint8_t) (test_value >> 8); + test_apdu[5] = (uint8_t) (test_value >> 0); + zassert_equal(3, encode_signed24(&apdu[3], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(3, decode_signed24(&apdu[3], &value), NULL); + zassert_equal(test_value, value, NULL); +#else + ztest_test_skip(); +#endif /* BACNET_USE_SIGNED */ +} + +static void test_signed32(void) +{ +#if BACNET_USE_SIGNED + uint8_t apdu[8] = { 0 }; + uint8_t test_apdu[8] = { 0 }; + int32_t test_value = 0x12345678L; + int32_t value = 0; + + /* + * Verify invalid parameter detection and handling + */ + zassert_equal(4, encode_signed32(NULL, 0U), NULL); + zassert_equal(4, decode_signed32(NULL, NULL), NULL); + + value = 42; + zassert_equal(4, decode_signed32(NULL, &value), NULL); + zassert_equal(42, value, NULL); + + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + zassert_equal(4, decode_signed32(&apdu[2], NULL), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + + memset(test_apdu, 0xA5U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + zassert_equal(4, decode_signed32(&apdu[3], NULL), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + + /* + * Verify multi-byte write in correct order + */ + + /* Verify aligned access with no extra bytes written */ + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[2] = (uint8_t) (test_value >>24); + test_apdu[3] = (uint8_t) (test_value >>16); + test_apdu[4] = (uint8_t) (test_value >> 8); + test_apdu[5] = (uint8_t) (test_value >> 0); + zassert_equal(4, encode_signed32(&apdu[2], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(4, decode_signed32(&apdu[2], &value), NULL); + zassert_equal(test_value, value, NULL); + + memset(test_apdu, 0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[2] = (uint8_t) (test_value >>24); + test_apdu[3] = (uint8_t) (test_value >>16); + test_apdu[4] = (uint8_t) (test_value >> 8); + test_apdu[5] = (uint8_t) (test_value >> 0); + zassert_equal(4, encode_signed32(&apdu[2], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(4, decode_signed32(&apdu[2], &value), NULL); + zassert_equal(test_value, value, NULL); + + /* Verify unaligned access with no extra bytes written */ + memset(test_apdu, ~0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[3] = (uint8_t) (test_value >>24); + test_apdu[4] = (uint8_t) (test_value >>16); + test_apdu[5] = (uint8_t) (test_value >> 8); + test_apdu[6] = (uint8_t) (test_value >> 0); + zassert_equal(4, encode_signed32(&apdu[3], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(4, decode_signed32(&apdu[3], &value), NULL); + zassert_equal(test_value, value, NULL); + + memset(test_apdu, 0U, sizeof(test_apdu)); + memcpy(apdu, test_apdu, sizeof(test_apdu)); + test_apdu[3] = (uint8_t) (test_value >>24); + test_apdu[4] = (uint8_t) (test_value >>16); + test_apdu[5] = (uint8_t) (test_value >> 8); + test_apdu[6] = (uint8_t) (test_value >> 0); + zassert_equal(4, encode_signed32(&apdu[3], test_value), NULL); + zassert_mem_equal(test_apdu, apdu, sizeof(test_apdu), NULL); + zassert_equal(4, decode_signed32(&apdu[3], &value), NULL); + zassert_equal(test_value, value, NULL); +#else + ztest_test_skip(); +#endif /* BACNET_USE_SIGNED */ +} + +static void test_signed_length(void) +{ +#if BACNET_USE_SIGNED + const int32_t sint24_max = 0x7FFFFFL; + const int32_t sint24_min = -sint24_max - 1L; + + zassert_equal(1, bacnet_signed_length(CHAR_MIN), NULL); + zassert_equal(1, bacnet_signed_length(-1), NULL); + zassert_equal(1, bacnet_signed_length(0), NULL); + zassert_equal(1, bacnet_signed_length(1), NULL); + zassert_equal(1, bacnet_signed_length(CHAR_MAX), NULL); + + zassert_equal(2, bacnet_signed_length(SHRT_MIN), NULL); + zassert_equal(2, bacnet_signed_length(CHAR_MIN - 1L), NULL); + zassert_equal(2, bacnet_signed_length(CHAR_MAX + 1L), NULL); + zassert_equal(2, bacnet_signed_length(SHRT_MAX), NULL); + + zassert_equal(3, bacnet_signed_length(sint24_min), NULL); + zassert_equal(3, bacnet_signed_length(SHRT_MIN - 1L), NULL); + zassert_equal(3, bacnet_signed_length(SHRT_MAX + 1L), NULL); + zassert_equal(3, bacnet_signed_length(sint24_max), NULL); + + zassert_equal(4, bacnet_signed_length(INT_MIN), NULL); + zassert_equal(4, bacnet_signed_length(sint24_min - 1L), NULL); + zassert_equal(4, bacnet_signed_length(sint24_max + 1L), NULL); + zassert_equal(4, bacnet_signed_length(INT_MAX), NULL); +#else + ztest_test_skip(); +#endif /* BACNET_USE_SIGNED */ +} + + +void test_main(void) +{ + ztest_test_suite(bacnet_bacint, + ztest_unit_test(test_unsigned16), + ztest_unit_test(test_unsigned24), + ztest_unit_test(test_unsigned32), + ztest_unit_test(test_unsigned40), + ztest_unit_test(test_unsigned48), + ztest_unit_test(test_unsigned56), + ztest_unit_test(test_unsigned64), + ztest_unit_test(test_unsigned_length), + ztest_unit_test(test_signed8), + ztest_unit_test(test_signed16), + ztest_unit_test(test_signed24), + ztest_unit_test(test_signed32), + ztest_unit_test(test_signed_length) + ); + ztest_run_test_suite(bacnet_bacint); +} diff --git a/zephyr/tests/unit/bacnet/bacint/CMakeLists.txt b/zephyr/tests/unit/bacnet/bacint/CMakeLists.txt new file mode 100644 index 00000000..f9408d10 --- /dev/null +++ b/zephyr/tests/unit/bacnet/bacint/CMakeLists.txt @@ -0,0 +1,26 @@ +# Copyright (c) 2022 Legrand North America, LLC. +# +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +if(NOT ZEPHYR_CURRENT_MODULE_DIR) + string(REGEX REPLACE "/zephyr/tests/[a-zA-Z_/-]*$" "" + ZEPHYR_CURRENT_MODULE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +endif() + +set(SOURCES + ${ZEPHYR_CURRENT_MODULE_DIR}/test/unit/bacnet/bacint/src/main.c + ) + +project(bacnet_bacint) +find_package(Zephyr COMPONENTS unittest REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +# NOTE for Zephyr >= v3.2.0: +# - Zephyr unittest builds for target 'testbinary' instead of 'app'. +# - Zephyr unittest does not generate ZEPHYR__MODULE_DIR. +# So we have to use relative paths to get to the source. + +target_include_directories(testbinary PRIVATE + ${ZEPHYR_CURRENT_MODULE_DIR}/src + ) diff --git a/zephyr/tests/unit/bacnet/bacint/prj.conf b/zephyr/tests/unit/bacnet/bacint/prj.conf new file mode 100644 index 00000000..d41d3a24 --- /dev/null +++ b/zephyr/tests/unit/bacnet/bacint/prj.conf @@ -0,0 +1 @@ +# This file is intentionally empty diff --git a/zephyr/tests/unit/bacnet/bacint/testcase.yaml b/zephyr/tests/unit/bacnet/bacint/testcase.yaml new file mode 100644 index 00000000..d9619773 --- /dev/null +++ b/zephyr/tests/unit/bacnet/bacint/testcase.yaml @@ -0,0 +1,3 @@ +tests: + bacnet.bacint.unit: + type: unit