From 587e3c5a1161bf0aee460e80107c8ce2410d82a8 Mon Sep 17 00:00:00 2001 From: Steve Karg Date: Fri, 12 Jan 2024 16:14:24 -0600 Subject: [PATCH] Chore/refactor automac unit test (#557) * move ports automac module into bacnet/datalink and add unit test. --- ports/stm32f10x/Makefile | 2 +- ports/stm32f10x/bacnet.ewp | 2 +- ports/stm32f10x/dlmstp.c | 2 +- .../bacnet/datalink}/automac.c | 163 +++--------------- .../bacnet/datalink}/automac.h | 6 + test/CMakeLists.txt | 1 + test/bacnet/datalink/automac/CMakeLists.txt | 40 +++++ test/bacnet/datalink/automac/src/main.c | 99 +++++++++++ 8 files changed, 172 insertions(+), 143 deletions(-) rename {ports/stm32f10x => src/bacnet/datalink}/automac.c (63%) rename {ports/stm32f10x => src/bacnet/datalink}/automac.h (92%) create mode 100644 test/bacnet/datalink/automac/CMakeLists.txt create mode 100644 test/bacnet/datalink/automac/src/main.c diff --git a/ports/stm32f10x/Makefile b/ports/stm32f10x/Makefile index 4fc94b09..a0477622 100644 --- a/ports/stm32f10x/Makefile +++ b/ports/stm32f10x/Makefile @@ -20,7 +20,6 @@ INCLUDES += -I$(BACNET_INCLUDE) PLATFORM_SRC = \ $(PLATFORM_DIR)/main.c \ - $(PLATFORM_DIR)/automac.c \ $(PLATFORM_DIR)/bacnet.c \ $(PLATFORM_DIR)/bo.c \ $(PLATFORM_DIR)/device.c \ @@ -62,6 +61,7 @@ BACNET_SRC = \ $(BACNET_CORE)/bacint.c \ $(BACNET_CORE)/bacreal.c \ $(BACNET_CORE)/bacstr.c \ + $(BACNET_CORE)/datalink/automac.c \ $(BACNET_CORE)/datalink/crc.c \ $(BACNET_CORE)/datetime.c \ $(BACNET_CORE)/dcc.c \ diff --git a/ports/stm32f10x/bacnet.ewp b/ports/stm32f10x/bacnet.ewp index 8c8f4c50..a390a08e 100644 --- a/ports/stm32f10x/bacnet.ewp +++ b/ports/stm32f10x/bacnet.ewp @@ -1130,7 +1130,7 @@ BACnet-Datalink - $PROJ_DIR$\automac.c + $PROJ_DIR$\..\..\src\bacnet\datalink\automac.c $PROJ_DIR$\..\..\src\bacnet\datalink\crc.c diff --git a/ports/stm32f10x/dlmstp.c b/ports/stm32f10x/dlmstp.c index a0b8b056..53a1b1e5 100644 --- a/ports/stm32f10x/dlmstp.c +++ b/ports/stm32f10x/dlmstp.c @@ -46,7 +46,7 @@ #include "bacnet/basic/sys/ringbuf.h" #include "bacnet/datalink/crc.h" #include "bacnet/datalink/mstpdef.h" -#include "automac.h" +#include "bacnet/datalink/automac.h" #include "bacnet/basic/object/device.h" /* This file has been customized for use with small microprocessors */ diff --git a/ports/stm32f10x/automac.c b/src/bacnet/datalink/automac.c similarity index 63% rename from ports/stm32f10x/automac.c rename to src/bacnet/datalink/automac.c index b1aba26b..35e2ed13 100644 --- a/ports/stm32f10x/automac.c +++ b/src/bacnet/datalink/automac.c @@ -1,27 +1,11 @@ -/************************************************************************** +/** + * @file + * @brief BACnet MSTP zero-config auto MAC address + * @author Steve Karg + * @date 2010 * - * Copyright (C) 2010 Steve Karg - * - * 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. - * - *********************************************************************/ + * SPDX-License-Identifier: MIT + */ #include #include #include @@ -30,7 +14,7 @@ #include "bacnet/bacenum.h" #include "bacnet/config.h" #include "bacnet/datalink/mstpdef.h" -#include "automac.h" +#include "bacnet/datalink/automac.h" /* MS/TP Auto MAC address functionality */ @@ -46,11 +30,7 @@ typedef struct { /* reserve some slots for fixed addresses */ bool reserved : 1; } AUTO_MAC_DATA; -/* starting number available for AutoMAC */ -#define MAC_SLOTS_OFFSET 32 -/* total number of slots */ -#define MAC_SLOTS_MAX 128 -static AUTO_MAC_DATA Auto_MAC_Data[MAC_SLOTS_MAX]; +static AUTO_MAC_DATA Auto_MAC_Data[MSTP_MAC_SLOTS_MAX]; /* my automatic MAC address */ static uint8_t My_MAC_Address; /* my no-token silence timer time slot in milliseconds */ @@ -99,7 +79,7 @@ static bool automac_address_used(uint8_t mac) { bool status = false; - if (mac < MAC_SLOTS_MAX) { + if (mac < MSTP_MAC_SLOTS_MAX) { if ((Auto_MAC_Data[mac].emitter) || (Auto_MAC_Data[mac].reserved) || (Auto_MAC_Data[mac].token)) { status = true; @@ -118,7 +98,7 @@ bool automac_free_address_valid(uint8_t mac) { bool status = false; - if (mac < MAC_SLOTS_MAX) { + if (mac < MSTP_MAC_SLOTS_MAX) { if ((Auto_MAC_Data[mac].pfm) && (!automac_address_used(mac))) { status = true; } @@ -139,12 +119,12 @@ uint8_t automac_next_station(uint8_t mac) uint8_t test_station = 0; /* station number to test for token */ test_station = (mac + 1) % 128; - for (i = 0; i < MAC_SLOTS_MAX; i++) { + for (i = 0; i < MSTP_MAC_SLOTS_MAX; i++) { if (Auto_MAC_Data[test_station].token) { next_station = test_station; break; } - test_station = (test_station + 1) % MAC_SLOTS_MAX; + test_station = (test_station + 1) % MSTP_MAC_SLOTS_MAX; } return next_station; @@ -160,7 +140,7 @@ uint8_t automac_free_address_count(void) uint8_t i = 0; uint8_t slots = 0; - for (i = 0; i < MAC_SLOTS_MAX; i++) { + for (i = 0; i < MSTP_MAC_SLOTS_MAX; i++) { if (automac_free_address_valid(i)) { slots++; } @@ -180,7 +160,7 @@ uint8_t automac_free_address_mac(uint8_t count) uint8_t slots = 0; uint8_t mac = 255; - for (i = 0; i < MAC_SLOTS_MAX; i++) { + for (i = 0; i < MSTP_MAC_SLOTS_MAX; i++) { if (automac_free_address_valid(i)) { if (slots == count) { mac = i; @@ -250,10 +230,10 @@ uint16_t automac_time_slot(void) *****************************************************************************/ void automac_address_init(void) { - My_MAC_Address = - MAC_SLOTS_OFFSET + rand() % (MAC_SLOTS_MAX - MAC_SLOTS_OFFSET); + My_MAC_Address = MSTP_MAC_SLOTS_OFFSET + + rand() % (MSTP_MAC_SLOTS_MAX - MSTP_MAC_SLOTS_OFFSET); /* at least as long as a dropped token - worst case */ - My_Time_Slot = Tno_token + (MAC_SLOTS_MAX * Tslot); + My_Time_Slot = Tno_token + (MSTP_MAC_SLOTS_MAX * Tslot); My_Time_Slot += (uint16_t)My_MAC_Address * Tslot; } @@ -264,7 +244,7 @@ void automac_address_init(void) *****************************************************************************/ void automac_pfm_set(uint8_t mac) { - if (mac < MAC_SLOTS_MAX) { + if (mac < MSTP_MAC_SLOTS_MAX) { if (Auto_MAC_Data[mac].pfm) { /* indicate that we have completed enough PFM to continue */ if (automac_free_address_count() > 0) { @@ -282,7 +262,7 @@ void automac_pfm_set(uint8_t mac) *****************************************************************************/ void automac_token_set(uint8_t mac) { - if (mac < MAC_SLOTS_MAX) { + if (mac < MSTP_MAC_SLOTS_MAX) { Auto_MAC_Data[mac].token = true; } } @@ -294,7 +274,7 @@ void automac_token_set(uint8_t mac) *****************************************************************************/ void automac_emitter_set(uint8_t mac) { - if (mac < MAC_SLOTS_MAX) { + if (mac < MSTP_MAC_SLOTS_MAX) { Auto_MAC_Data[mac].emitter = true; } } @@ -308,11 +288,11 @@ void automac_init(void) { uint8_t i = 0; - for (i = 0; i < MAC_SLOTS_MAX; i++) { + for (i = 0; i < MSTP_MAC_SLOTS_MAX; i++) { Auto_MAC_Data[i].token = false; Auto_MAC_Data[i].emitter = false; Auto_MAC_Data[i].pfm = false; - if (i < MAC_SLOTS_OFFSET) { + if (i < MSTP_MAC_SLOTS_OFFSET) { Auto_MAC_Data[i].reserved = true; } else { Auto_MAC_Data[i].reserved = false; @@ -321,100 +301,3 @@ void automac_init(void) automac_address_init(); PFM_Cycle_Complete = false; } - -#ifdef BAC_TEST -#include -#include -#include -#include "ctest.h" - -/* test the ring buffer */ -void test_Auto_MAC(Test *pTest) -{ - uint8_t mac = 255; - - automac_init(); - ct_test(pTest, automac_free_address_count() == 0); - mac = automac_free_address_mac(0); - ct_test(pTest, mac == 255); - automac_pfm_set(MAC_SLOTS_OFFSET); - mac = automac_free_address_mac(0); - ct_test(pTest, mac == MAC_SLOTS_OFFSET); - ct_test(pTest, automac_free_address_count() == 1); - automac_token_set(MAC_SLOTS_OFFSET); - mac = automac_free_address_mac(0); - ct_test(pTest, mac == 255); - ct_test(pTest, automac_free_address_count() == 0); - automac_pfm_set(127); - mac = automac_free_address_mac(0); - ct_test(pTest, mac == 127); - ct_test(pTest, automac_free_address_count() == 1); - automac_token_set(127); - mac = automac_free_address_mac(0); - ct_test(pTest, mac == 255); - ct_test(pTest, automac_free_address_count() == 0); - /* the ANSI rand() uses consistent sequence based on seed */ - srand(42); - mac = automac_free_address_random(); - ct_test(pTest, mac == 255); - automac_pfm_set(MAC_SLOTS_OFFSET + 1); - mac = automac_free_address_mac(0); - ct_test(pTest, mac == (MAC_SLOTS_OFFSET + 1)); - mac = automac_free_address_random(); - ct_test(pTest, mac == (MAC_SLOTS_OFFSET + 1)); - /* test 2 free addresses */ - automac_pfm_set(MAC_SLOTS_OFFSET + 2); - mac = automac_free_address_mac(0); - ct_test(pTest, mac == (MAC_SLOTS_OFFSET + 1)); - mac = automac_free_address_mac(1); - ct_test(pTest, mac == (MAC_SLOTS_OFFSET + 2)); - mac = automac_free_address_random(); - ct_test(pTest, - (mac == (MAC_SLOTS_OFFSET + 1)) || (mac == (MAC_SLOTS_OFFSET + 2))); - /* test 3 free addresses */ - automac_pfm_set(126); - mac = automac_free_address_mac(0); - ct_test(pTest, mac == (MAC_SLOTS_OFFSET + 1)); - mac = automac_free_address_mac(1); - ct_test(pTest, mac == (MAC_SLOTS_OFFSET + 2)); - mac = automac_free_address_mac(2); - ct_test(pTest, mac == 126); - mac = automac_free_address_random(); - ct_test(pTest, - (mac == (MAC_SLOTS_OFFSET + 1)) || (mac == (MAC_SLOTS_OFFSET + 2)) || - (mac == 126)); - /* test the stored address */ - mac = automac_address(); - ct_test(pTest, mac < MAC_SLOTS_MAX); - automac_address_set(MAC_SLOTS_OFFSET); - mac = automac_address(); - ct_test(pTest, mac == MAC_SLOTS_OFFSET); - - automac_init(); - automac_token_set(0x6B); - mac = automac_next_station(0x25); - ct_test(pTest, mac == 0x6B); -} - -#ifdef TEST_AUTOMAC -int main(void) -{ - Test *pTest; - bool rc; - - pTest = ct_create("Auto MAC", NULL); - - /* individual tests */ - rc = ct_addTestFunction(pTest, test_Auto_MAC); - assert(rc); - - ct_setStream(pTest, stdout); - ct_run(pTest); - (void)ct_report(pTest); - - ct_destroy(pTest); - - return 0; -} -#endif -#endif diff --git a/ports/stm32f10x/automac.h b/src/bacnet/datalink/automac.h similarity index 92% rename from ports/stm32f10x/automac.h rename to src/bacnet/datalink/automac.h index fcfd7d4b..23822bb1 100644 --- a/ports/stm32f10x/automac.h +++ b/src/bacnet/datalink/automac.h @@ -27,8 +27,14 @@ #include #include +#include +#include /* MS/TP Auto MAC address functionality */ +/* starting number available for AutoMAC */ +#define MSTP_MAC_SLOTS_OFFSET 32 +/* total number of slots */ +#define MSTP_MAC_SLOTS_MAX 128 #ifdef __cplusplus extern "C" { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7d611590..10aa75e2 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -149,6 +149,7 @@ list(APPEND testdirs # bacnet/datalink/* list(APPEND testdirs + bacnet/datalink/automac bacnet/datalink/cobs bacnet/datalink/crc bacnet/datalink/bvlc diff --git a/test/bacnet/datalink/automac/CMakeLists.txt b/test/bacnet/datalink/automac/CMakeLists.txt new file mode 100644 index 00000000..9dd3e19d --- /dev/null +++ b/test/bacnet/datalink/automac/CMakeLists.txt @@ -0,0 +1,40 @@ +# 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/bacnet/[a-zA-Z_/-]*$" + "/src" + SRC_DIR + ${CMAKE_CURRENT_SOURCE_DIR}) +string(REGEX REPLACE + "/test/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 + ${SRC_DIR}/bacnet/datalink/automac.c + # 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/bacnet/datalink/automac/src/main.c b/test/bacnet/datalink/automac/src/main.c new file mode 100644 index 00000000..e9fd5937 --- /dev/null +++ b/test/bacnet/datalink/automac/src/main.c @@ -0,0 +1,99 @@ +/** + * @file + * @brief test BACnet MSTP zero-config auto MAC address + * @author Steve Karg + * @date 2023-June + * + * SPDX-License-Identifier: MIT + */ +#include +#include +#include + +/** + * @addtogroup bacnet_tests + * @{ + */ + +/** + * @brief Test Auto-MAC initialization + */ +static void test_automac_init(void) +{ + uint8_t mac = 255; + bool options; + + automac_init(); + zassert_equal(automac_free_address_count(), 0, NULL); + mac = automac_free_address_mac(0); + zassert_equal(mac, 255, NULL); + automac_pfm_set(MSTP_MAC_SLOTS_OFFSET); + mac = automac_free_address_mac(0); + zassert_equal(mac, MSTP_MAC_SLOTS_OFFSET, NULL); + zassert_equal(automac_free_address_count(), 1, NULL); + automac_token_set(MSTP_MAC_SLOTS_OFFSET); + mac = automac_free_address_mac(0); + zassert_equal(mac, 255, NULL); + zassert_equal(automac_free_address_count(), 0, NULL); + automac_pfm_set(127); + mac = automac_free_address_mac(0); + zassert_equal(mac, 127, NULL); + zassert_equal(automac_free_address_count(), 1, NULL); + automac_token_set(127); + mac = automac_free_address_mac(0); + zassert_equal(mac, 255, NULL); + zassert_equal(automac_free_address_count(), 0, NULL); + /* the ANSI rand() uses consistent sequence based on seed */ + srand(42); + mac = automac_free_address_random(); + zassert_equal(mac, 255, NULL); + automac_pfm_set(MSTP_MAC_SLOTS_OFFSET + 1); + mac = automac_free_address_mac(0); + zassert_equal(mac, (MSTP_MAC_SLOTS_OFFSET + 1), NULL); + mac = automac_free_address_random(); + zassert_equal(mac, (MSTP_MAC_SLOTS_OFFSET + 1), NULL); + /* test 2 free addresses */ + automac_pfm_set(MSTP_MAC_SLOTS_OFFSET + 2); + mac = automac_free_address_mac(0); + zassert_equal(mac, (MSTP_MAC_SLOTS_OFFSET + 1), NULL); + mac = automac_free_address_mac(1); + zassert_equal(mac, (MSTP_MAC_SLOTS_OFFSET + 2), NULL); + mac = automac_free_address_random(); + options = (mac == (MSTP_MAC_SLOTS_OFFSET + 1)) || + (mac == (MSTP_MAC_SLOTS_OFFSET + 2)); + zassert_true(options, NULL); + /* test 3 free addresses */ + automac_pfm_set(126); + mac = automac_free_address_mac(0); + zassert_equal(mac, (MSTP_MAC_SLOTS_OFFSET + 1), NULL); + mac = automac_free_address_mac(1); + zassert_equal(mac, (MSTP_MAC_SLOTS_OFFSET + 2), NULL); + mac = automac_free_address_mac(2); + zassert_equal(mac, 126, NULL); + mac = automac_free_address_random(); + options = (mac == (MSTP_MAC_SLOTS_OFFSET + 1)) || + (mac == (MSTP_MAC_SLOTS_OFFSET + 2)) || + (mac == 126); + zassert_true(options, NULL); + /* test the stored address */ + mac = automac_address(); + zassert_true(mac < MSTP_MAC_SLOTS_MAX, NULL); + automac_address_set(MSTP_MAC_SLOTS_OFFSET); + mac = automac_address(); + zassert_equal(mac, MSTP_MAC_SLOTS_OFFSET, NULL); + + automac_init(); + automac_token_set(0x6B); + mac = automac_next_station(0x25); + zassert_equal(mac, 0x6B, NULL); +} + +/** + * @} + */ +void test_main(void) +{ + ztest_test_suite(automac_tests, ztest_unit_test(test_automac_init)); + + ztest_run_test_suite(automac_tests); +}