From 001b69cbd8806590d5ca31649b6bcd29f85006f7 Mon Sep 17 00:00:00 2001 From: Steve Karg Date: Mon, 2 Dec 2024 07:32:57 -0600 Subject: [PATCH] Fixed dlmstp ringbuffer initialization corruption (#865) * Added ringbuf API for testing. * Fixed basic ms/tp datalink packet ringbuffer initialization buffer overrun. * Added basic ms/tp datalink unit test * Added Ringbuf_Initialize() API with buffer size checking. * Changed examples to use Ringbuf_Initialize() API for buffer size checking. --- src/bacnet/basic/client/bac-rw.c | 5 +- src/bacnet/basic/sys/ringbuf.c | 45 +++- src/bacnet/basic/sys/ringbuf.h | 9 + src/bacnet/datalink/dlmstp.c | 8 +- test/CMakeLists.txt | 1 + test/bacnet/basic/sys/ringbuf/src/main.c | 20 +- test/bacnet/datalink/dlmstp/CMakeLists.txt | 52 +++++ test/bacnet/datalink/dlmstp/src/main.c | 234 +++++++++++++++++++++ test/bacnet/datalink/test/mstp-mock.c | 93 ++++++++ test/bacnet/datalink/test/mstp-rs485.c | 51 +++++ test/bacnet/datalink/test/mstp-rs485.h | 22 ++ 11 files changed, 526 insertions(+), 14 deletions(-) create mode 100644 test/bacnet/datalink/dlmstp/CMakeLists.txt create mode 100644 test/bacnet/datalink/dlmstp/src/main.c create mode 100644 test/bacnet/datalink/test/mstp-mock.c create mode 100644 test/bacnet/datalink/test/mstp-rs485.c create mode 100644 test/bacnet/datalink/test/mstp-rs485.h diff --git a/src/bacnet/basic/client/bac-rw.c b/src/bacnet/basic/client/bac-rw.c index 8abe4b48..8f4e50fc 100644 --- a/src/bacnet/basic/client/bac-rw.c +++ b/src/bacnet/basic/client/bac-rw.c @@ -896,9 +896,10 @@ uint16_t bacnet_read_write_vendor_id_filter(void) */ void bacnet_read_write_init(void) { - Ringbuf_Init( + Ringbuf_Initialize( &Target_Data_Queue, (uint8_t *)&Target_Data_Buffer, - TARGET_DATA_QUEUE_SIZE, TARGET_DATA_QUEUE_COUNT); + sizeof(Target_Data_Buffer), TARGET_DATA_QUEUE_SIZE, + TARGET_DATA_QUEUE_COUNT); /* handle i-am to support binding to other devices */ apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, My_I_Am_Bind); /* handle the data coming back from confirmed requests */ diff --git a/src/bacnet/basic/sys/ringbuf.c b/src/bacnet/basic/sys/ringbuf.c index 13a55fde..c792557f 100644 --- a/src/bacnet/basic/sys/ringbuf.c +++ b/src/bacnet/basic/sys/ringbuf.c @@ -374,6 +374,23 @@ bool Ringbuf_Data_Put(RING_BUFFER *b, const volatile uint8_t *data_element) return status; } +/** + * Gets the data size of each element in the ring buffer + * + * @param b - pointer to RING_BUFFER structure + * @return size of each element in the ring buffer + */ +unsigned Ringbuf_Data_Size(RING_BUFFER const *b) +{ + unsigned size = 0; + + if (b) { + size = b->element_size; + } + + return size; +} + /** * Test that the parameter is a power of two. * @@ -395,8 +412,8 @@ static bool isPowerOfTwo(unsigned int x) * @param buffer - pointer to a data buffer that is used to store the ring data * @param element_size - size of one element in the data block * @param element_count - number elements in the data block - * * @return true if ring buffer was initialized + * @deprecated Use Ringbuf_Initialize() instead */ bool Ringbuf_Init( RING_BUFFER *b, @@ -419,3 +436,29 @@ bool Ringbuf_Init( return status; } + +/** + * Configures the ring buffer data buffer. Note that the element_count + * parameter must be a power of two. + * + * @param b - pointer to RING_BUFFER structure + * @param buffer - pointer to a data buffer that is used to store the ring data + * @param buffer_size - size of the data buffer + * @param element_size - size of one element in the data block + * @param element_count - number elements in the data block + * + * @return true if ring buffer was initialized + */ +bool Ringbuf_Initialize( + RING_BUFFER *b, + volatile uint8_t *buffer, + unsigned buffer_size, + unsigned element_size, + unsigned element_count) +{ + if ((element_size * element_count) <= buffer_size) { + return Ringbuf_Init(b, buffer, element_size, element_count); + } + + return false; +} diff --git a/src/bacnet/basic/sys/ringbuf.h b/src/bacnet/basic/sys/ringbuf.h index d163210d..53f4bb45 100644 --- a/src/bacnet/basic/sys/ringbuf.h +++ b/src/bacnet/basic/sys/ringbuf.h @@ -89,6 +89,8 @@ volatile void * Ringbuf_Peek_Next(RING_BUFFER const *b, const uint8_t *data_element); BACNET_STACK_EXPORT bool Ringbuf_Data_Put(RING_BUFFER *b, const volatile uint8_t *data_element); +BACNET_STACK_EXPORT +unsigned Ringbuf_Data_Size(RING_BUFFER const *b); /* Note: element_count must be a power of two */ BACNET_STACK_EXPORT bool Ringbuf_Init( @@ -96,6 +98,13 @@ bool Ringbuf_Init( volatile uint8_t *buffer, unsigned element_size, unsigned element_count); +BACNET_STACK_EXPORT +bool Ringbuf_Initialize( + RING_BUFFER *b, + volatile uint8_t *buffer, + unsigned buffer_size, + unsigned element_size, + unsigned element_count); #ifdef __cplusplus } diff --git a/src/bacnet/datalink/dlmstp.c b/src/bacnet/datalink/dlmstp.c index 9d4698f5..9a5b58e9 100644 --- a/src/bacnet/datalink/dlmstp.c +++ b/src/bacnet/datalink/dlmstp.c @@ -92,6 +92,7 @@ uint16_t MSTP_Get_Send(struct mstp_port_struct_t *mstp_port, unsigned timeout) struct dlmstp_packet *pkt; struct dlmstp_user_data_t *user; + (void)timeout; if (!mstp_port) { return 0; } @@ -250,6 +251,7 @@ uint16_t MSTP_Get_Reply(struct mstp_port_struct_t *mstp_port, unsigned timeout) struct dlmstp_user_data_t *user = NULL; struct dlmstp_packet *pkt; + (void)timeout; if (!mstp_port) { return 0; } @@ -346,6 +348,7 @@ uint16_t dlmstp_receive( uint16_t i; uint32_t milliseconds; + (void)timeout; if (!MSTP_Port) { return 0; } @@ -993,9 +996,10 @@ bool dlmstp_init(char *ifname) MSTP_Port->SilenceTimerReset = dlmstp_silence_reset; user = (struct dlmstp_user_data_t *)MSTP_Port->UserData; if (user && !user->Initialized) { - Ringbuf_Init( + Ringbuf_Initialize( &user->PDU_Queue, (volatile uint8_t *)user->PDU_Buffer, - sizeof(user->PDU_Buffer), DLMSTP_MAX_INFO_FRAMES); + sizeof(user->PDU_Buffer), sizeof(struct dlmstp_packet), + DLMSTP_MAX_INFO_FRAMES); MSTP_Init(MSTP_Port); user->Initialized = true; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 09392691..b39b572f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -188,6 +188,7 @@ list(APPEND testdirs bacnet/datalink/crc bacnet/datalink/bvlc bacnet/datalink/mstp + bacnet/datalink/dlmstp ) # ports tests diff --git a/test/bacnet/basic/sys/ringbuf/src/main.c b/test/bacnet/basic/sys/ringbuf/src/main.c index d708e45a..c0cd2925 100644 --- a/test/bacnet/basic/sys/ringbuf/src/main.c +++ b/test/bacnet/basic/sys/ringbuf/src/main.c @@ -79,6 +79,7 @@ static void testRingAroundBuffer( */ static void testRingBuf( uint8_t *data_store, + unsigned data_store_size, uint8_t *data_element, unsigned element_size, unsigned element_count) @@ -89,8 +90,8 @@ static void testRingBuf( unsigned data_index; bool status; - status = - Ringbuf_Init(&test_buffer, data_store, element_size, element_count); + status = Ringbuf_Initialize( + &test_buffer, data_store, data_store_size, element_size, element_count); if (!status) { return; } @@ -176,7 +177,7 @@ static void testRingBufSizeSmall(void) uint8_t data_store[sizeof(data_element) * NEXT_POWER_OF_2(16)]; testRingBuf( - data_store, data_element, sizeof(data_element), + data_store, sizeof(data_store), data_element, sizeof(data_element), sizeof(data_store) / sizeof(data_element)); } @@ -193,7 +194,7 @@ static void testRingBufSizeLarge(void) uint8_t data_store[sizeof(data_element) * NEXT_POWER_OF_2(99)]; testRingBuf( - data_store, data_element, sizeof(data_element), + data_store, sizeof(data_store), data_element, sizeof(data_element), sizeof(data_store) / sizeof(data_element)); } @@ -211,8 +212,8 @@ static void testRingBufSizeInvalid(void) uint8_t data_store[sizeof(data_element) * 99]; zassert_false( - Ringbuf_Init( - &test_buffer, data_store, sizeof(data_element), + Ringbuf_Initialize( + &test_buffer, data_store, sizeof(data_store), sizeof(data_element), sizeof(data_store) / sizeof(data_element)), NULL); } @@ -242,6 +243,7 @@ static void testRingBufPowerOfTwo(void) */ static bool testRingBufNextElement( uint8_t *data_store, + unsigned data_store_size, uint8_t *data_element, unsigned element_size, unsigned element_count) @@ -251,8 +253,8 @@ static bool testRingBufNextElement( unsigned index; unsigned data_index; bool status; - status = - Ringbuf_Init(&test_buffer, data_store, element_size, element_count); + status = Ringbuf_Initialize( + &test_buffer, data_store, data_store_size, element_size, element_count); if (!status) { return false; } @@ -348,7 +350,7 @@ static void testRingBufNextElementSizeSmall(void) uint8_t data_store[sizeof(data_element) * NEXT_POWER_OF_2(16)]; status = testRingBufNextElement( - data_store, data_element, sizeof(data_element), + data_store, sizeof(data_store), data_element, sizeof(data_element), sizeof(data_store) / sizeof(data_element)); zassert_true(status, NULL); } diff --git a/test/bacnet/datalink/dlmstp/CMakeLists.txt b/test/bacnet/datalink/dlmstp/CMakeLists.txt new file mode 100644 index 00000000..5c196455 --- /dev/null +++ b/test/bacnet/datalink/dlmstp/CMakeLists.txt @@ -0,0 +1,52 @@ +# 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 + ${TST_DIR}/bacnet/datalink/test + ) + +add_executable(${PROJECT_NAME} + # File(s) under test + ${SRC_DIR}/bacnet/datalink/dlmstp.c + # Support files and stubs (pathname alphabetical) + ${SRC_DIR}/bacnet/bacaddr.c + ${SRC_DIR}/bacnet/bacdcode.c + ${SRC_DIR}/bacnet/bacint.c + ${SRC_DIR}/bacnet/bacreal.c + ${SRC_DIR}/bacnet/bacstr.c + ${SRC_DIR}/bacnet/basic/sys/ringbuf.c + ${SRC_DIR}/bacnet/basic/sys/days.c + ${SRC_DIR}/bacnet/npdu.c + # Test and test library files + ./src/main.c + ${TST_DIR}/bacnet/datalink/test/mstp-mock.c + ${TST_DIR}/bacnet/datalink/test/mstp-rs485.c + ${ZTST_DIR}/ztest_mock.c + ${ZTST_DIR}/ztest.c + ) diff --git a/test/bacnet/datalink/dlmstp/src/main.c b/test/bacnet/datalink/dlmstp/src/main.c new file mode 100644 index 00000000..e98e4100 --- /dev/null +++ b/test/bacnet/datalink/dlmstp/src/main.c @@ -0,0 +1,234 @@ +/** + * @file + * @brief Unit test for a basic BACnet MS/TP Datalink + * @author Steve Karg + * @date November 2024 + * @copyright SPDX-License-Identifier: MIT + */ +#include +#include +#include +#include +#include + +/** + * @addtogroup bacnet_tests + * @{ + */ +static uint8_t RS485_Rx_Buffer[512]; +static uint8_t RS485_Tx_Buffer[512]; +static struct mstp_port_struct_t MSTP_Port; +static struct dlmstp_user_data_t MSTP_User; +static struct dlmstp_rs485_driver MSTP_RS485_Driver = { + .init = MSTP_RS485_Init, + .send = MSTP_RS485_Send, + .read = MSTP_RS485_Read, + .transmitting = MSTP_RS485_Transmitting, + .baud_rate = MSTP_RS485_Baud_Rate, + .baud_rate_set = MSTP_RS485_Baud_Rate_Set, + .silence_milliseconds = MSTP_RS485_Silence_Milliseconds, + .silence_reset = MSTP_RS485_Silence_Reset +}; + +/** + * @brief Test the basic operation of the MS/TP Datalink + */ +#if defined(CONFIG_ZTEST_NEW_API) +ZTEST(dlsmtp_tests, test_MSTP_Datalink) +#else +static void test_MSTP_Datalink(void) +#endif +{ + bool status = false; + struct dlmstp_statistics test_stats; + uint32_t test_baudrate; + uint8_t test_mac_address; + BACNET_ADDRESS test_address; + uint8_t test_frames; + uint16_t test_length; + uint8_t test_data[10] = { PDU_TYPE_ABORT, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + BACNET_NPDU_DATA test_npdu_data = { 0 }; + + /* error handling before port is initialized */ + test_length = dlmstp_send_pdu(NULL, NULL, 0, 0); + test_length = MSTP_Get_Send(NULL, 0); + zassert_equal(test_length, 0, NULL); + test_length = MSTP_Get_Reply(NULL, 0); + zassert_equal(test_length, 0, NULL); + MSTP_Send_Frame(NULL, NULL, 0); + test_length = dlmstp_receive(&test_address, NULL, 0, 0); + zassert_equal(test_length, 0, NULL); + test_mac_address = dlmstp_mac_address(); + zassert_equal(test_mac_address, 0, NULL); + test_frames = dlmstp_max_info_frames(); + zassert_equal(test_frames, 0, NULL); + test_mac_address = dlmstp_max_master(); + zassert_equal(test_mac_address, 0, NULL); + status = dlmstp_sole_master(); + zassert_equal(status, false, NULL); + status = dlmstp_slave_mode_enabled_set(true); + zassert_equal(status, false, NULL); + status = dlmstp_slave_mode_enabled(); + zassert_equal(status, false, NULL); + status = dlmstp_zero_config_enabled(); + zassert_equal(status, false, NULL); + test_mac_address = dlmstp_zero_config_preferred_station(); + zassert_equal(test_mac_address, 0, NULL); + dlmstp_zero_config_preferred_station_set(0); + dlmstp_set_baud_rate(38400); + test_baudrate = dlmstp_baud_rate(); + zassert_equal(test_baudrate, 0, NULL); + dlmstp_set_frame_rx_complete_callback(NULL); + dlmstp_set_invalid_frame_rx_complete_callback(NULL); + dlmstp_set_frame_rx_start_callback(NULL); + dlmstp_fill_statistics(NULL); + dlmstp_reset_statistics(); + /* initialize */ + MSTP_User.RS485_Driver = &MSTP_RS485_Driver; + MSTP_Port.UserData = &MSTP_User; + MSTP_Port.InputBuffer = RS485_Rx_Buffer; + MSTP_Port.InputBufferSize = sizeof(RS485_Rx_Buffer); + MSTP_Port.OutputBuffer = RS485_Tx_Buffer; + MSTP_Port.OutputBufferSize = sizeof(RS485_Tx_Buffer); + ztest_expect_value(MSTP_Init, mstp_port, &MSTP_Port); + status = dlmstp_init((char *)&MSTP_Port); + zassert_true(status, NULL); + zassert_true(MSTP_User.Initialized, NULL); + zassert_equal( + Ringbuf_Size(&MSTP_User.PDU_Queue), DLMSTP_MAX_INFO_FRAMES, NULL); + zassert_equal( + Ringbuf_Data_Size(&MSTP_User.PDU_Queue), sizeof(struct dlmstp_packet), + NULL); + zassert_equal(dlmstp_send_pdu_queue_empty(), true, NULL); + zassert_equal(dlmstp_send_pdu_queue_full(), false, NULL); + ztest_returns_value(MSTP_RS485_Silence_Milliseconds, 0); + zassert_equal(dlmstp_silence_milliseconds(&MSTP_Port), 0, NULL); + dlmstp_silence_reset(&MSTP_Port); + ztest_returns_value(MSTP_RS485_Silence_Milliseconds, 0); + zassert_equal(dlmstp_silence_milliseconds(&MSTP_Port), 0, NULL); + zassert_equal(dlmstp_max_master_limit(), DLMSTP_MAX_MASTER, NULL); + zassert_equal(dlmstp_max_info_frames_limit(), DLMSTP_MAX_INFO_FRAMES, NULL); + dlmstp_fill_statistics(NULL); + dlmstp_fill_statistics(&test_stats); + zassert_equal( + test_stats.transmit_frame_counter, + MSTP_User.Statistics.transmit_frame_counter, NULL); + zassert_equal( + test_stats.receive_valid_frame_counter, + MSTP_User.Statistics.receive_valid_frame_counter, NULL); + zassert_equal( + test_stats.receive_invalid_frame_counter, + MSTP_User.Statistics.receive_invalid_frame_counter, NULL); + zassert_equal( + test_stats.transmit_pdu_counter, + MSTP_User.Statistics.transmit_pdu_counter, NULL); + zassert_equal( + test_stats.receive_pdu_counter, + MSTP_User.Statistics.receive_pdu_counter, NULL); + dlmstp_reset_statistics(); + dlmstp_set_frame_rx_complete_callback(NULL); + dlmstp_set_invalid_frame_rx_complete_callback(NULL); + dlmstp_set_frame_rx_start_callback(NULL); + dlmstp_get_broadcast_address(&test_address); + zassert_equal(test_address.mac_len, 1, NULL); + zassert_equal(test_address.mac[0], MSTP_BROADCAST_ADDRESS, NULL); + zassert_equal(test_address.net, BACNET_BROADCAST_NETWORK, NULL); + zassert_equal(test_address.len, 0, NULL); + dlmstp_get_my_address(&test_address); + zassert_equal(test_address.mac_len, 1, NULL); + zassert_equal(test_address.mac[0], MSTP_Port.This_Station, NULL); + zassert_equal(test_address.net, 0, NULL); + zassert_equal(test_address.len, 0, NULL); + test_mac_address = dlmstp_max_master(); + zassert_equal(test_mac_address, MSTP_Port.Nmax_master, NULL); + dlmstp_set_max_master(10); + test_mac_address = dlmstp_max_master(); + zassert_equal(test_mac_address, 10, NULL); + test_frames = dlmstp_max_info_frames(); + zassert_equal(test_frames, MSTP_Port.Nmax_info_frames, NULL); + dlmstp_set_max_info_frames(10); + test_frames = dlmstp_max_info_frames(); + zassert_equal(test_frames, 10, NULL); + test_mac_address = dlmstp_mac_address(); + zassert_equal(test_mac_address, MSTP_Port.This_Station, NULL); + dlmstp_set_mac_address(10); + test_mac_address = dlmstp_mac_address(); + zassert_equal(test_mac_address, 10, NULL); + dlmstp_fill_bacnet_address(&test_address, 10); + zassert_equal(test_address.mac_len, 1, NULL); + zassert_equal(test_address.mac[0], 10, NULL); + zassert_equal(test_address.net, 0, NULL); + zassert_equal(test_address.len, 0, NULL); + dlmstp_fill_bacnet_address(&test_address, MSTP_BROADCAST_ADDRESS); + zassert_equal(test_address.mac_len, 0, NULL); + zassert_equal(test_address.mac[0], 0, NULL); + zassert_equal(test_address.net, 0, NULL); + zassert_equal(test_address.len, 0, NULL); + ztest_returns_value(MSTP_RS485_Baud_Rate, 38400); + test_baudrate = dlmstp_baud_rate(); + zassert_equal(test_baudrate, 38400, NULL); + ztest_expect_value(MSTP_RS485_Baud_Rate_Set, baud, 19200); + ztest_returns_value(MSTP_RS485_Baud_Rate_Set, true); + dlmstp_set_baud_rate(19200); + dlmstp_zero_config_preferred_station_set(65); + test_mac_address = dlmstp_zero_config_preferred_station(); + zassert_equal(test_mac_address, 65, NULL); + dlmstp_zero_config_enabled_set(true); + status = dlmstp_zero_config_enabled(); + zassert_equal(status, true, NULL); + status = dlmstp_slave_mode_enabled_set(true); + zassert_equal(status, true, NULL); + status = dlmstp_slave_mode_enabled(); + zassert_equal(status, true, NULL); + status = dlmstp_sole_master(); + zassert_equal(status, MSTP_Port.SoleMaster, NULL); + /* various test cases */ + ztest_returns_value(MSTP_RS485_Transmitting, true); + test_length = dlmstp_receive(&test_address, NULL, 0, 0); + zassert_equal(test_length, 0, NULL); + /* fixme: dlmstp_receive() calls driver with local var pointer + and zmock does not seem to have a way to test that. */ + test_length = MSTP_Put_Receive(&MSTP_Port); + zassert_equal(test_length, MSTP_Port.DataLength, NULL); + zassert_equal(MSTP_User.ReceivePacketPending, true, NULL); + ztest_expect_data(MSTP_RS485_Send, payload, test_data); + MSTP_Send_Frame(&MSTP_Port, test_data, sizeof(test_data)); + zassert_equal(MSTP_User.Statistics.transmit_frame_counter, 1, NULL); + test_length = MSTP_Get_Reply(&MSTP_Port, 0); + zassert_equal(test_length, 0, NULL); + test_npdu_data.data_expecting_reply = false; + test_length = dlmstp_send_pdu( + &test_address, &test_npdu_data, test_data, sizeof(test_data)); + zassert_equal( + test_length, sizeof(test_data), "dlmstp_send_pdu() length=%d", + test_length); + ztest_expect_value(MSTP_Create_Frame, buffer, &MSTP_Port.OutputBuffer[0]); + ztest_expect_value( + MSTP_Create_Frame, buffer_len, MSTP_Port.OutputBufferSize); + ztest_expect_value( + MSTP_Create_Frame, frame_type, + FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY); + ztest_expect_value(MSTP_Create_Frame, destination, MSTP_BROADCAST_ADDRESS); + ztest_expect_value(MSTP_Create_Frame, source, MSTP_Port.This_Station); + ztest_expect_data(MSTP_Create_Frame, data, test_data); + ztest_returns_value( + MSTP_Create_Frame, sizeof(test_data) + DLMSTP_HEADER_MAX); + test_length = MSTP_Get_Send(&MSTP_Port, 0); + zassert_equal( + test_length, sizeof(test_data) + DLMSTP_HEADER_MAX, + "MSTP_Get_Send() length=%d", test_length); +} +/** + * @} + */ + +#if defined(CONFIG_ZTEST_NEW_API) +ZTEST_SUITE(dlmstp_tests, NULL, NULL, NULL, NULL, NULL); +#else +void test_main(void) +{ + ztest_test_suite(dlmstp_tests, ztest_unit_test(test_MSTP_Datalink)); + + ztest_run_test_suite(dlmstp_tests); +} +#endif diff --git a/test/bacnet/datalink/test/mstp-mock.c b/test/bacnet/datalink/test/mstp-mock.c new file mode 100644 index 00000000..0fe6745e --- /dev/null +++ b/test/bacnet/datalink/test/mstp-mock.c @@ -0,0 +1,93 @@ +/** + * @file + * @brief Mock for BACnet MS/TP API + * @author Steve Karg + * @date November 2024 + * @copyright SPDX-License-Identifier: MIT + */ +#include +#include +#include +#include "bacnet/datalink/mstp.h" + +void MSTP_Init(struct mstp_port_struct_t *mstp_port) +{ + ztest_check_expected_value(mstp_port); +} + +void MSTP_Receive_Frame_FSM(struct mstp_port_struct_t *mstp_port) +{ + ztest_check_expected_value(mstp_port); +} + +bool MSTP_Master_Node_FSM(struct mstp_port_struct_t *mstp_port) +{ + ztest_check_expected_value(mstp_port); + return ztest_get_return_value(); +} + +void MSTP_Slave_Node_FSM(struct mstp_port_struct_t *mstp_port) +{ + ztest_check_expected_value(mstp_port); +} + +bool MSTP_Line_Active(const struct mstp_port_struct_t *mstp_port) +{ + ztest_check_expected_value(mstp_port); + return ztest_get_return_value(); +} + +uint16_t MSTP_Create_Frame( + uint8_t *buffer, + uint16_t buffer_len, + uint8_t frame_type, + uint8_t destination, + uint8_t source, + const uint8_t *data, + uint16_t data_len) +{ + ztest_check_expected_value(buffer); + ztest_check_expected_value(buffer_len); + ztest_check_expected_value(frame_type); + ztest_check_expected_value(destination); + ztest_check_expected_value(source); + ztest_check_expected_data(data, data_len); + return ztest_get_return_value(); +} + +void MSTP_Create_And_Send_Frame( + struct mstp_port_struct_t *mstp_port, + uint8_t frame_type, + uint8_t destination, + uint8_t source, + const uint8_t *data, + uint16_t data_len) +{ + ztest_check_expected_value(mstp_port); + ztest_check_expected_value(frame_type); + ztest_check_expected_value(destination); + ztest_check_expected_value(source); + ztest_check_expected_data(data, data_len); +} + +void MSTP_Fill_BACnet_Address(BACNET_ADDRESS *src, uint8_t mstp_address) +{ + ztest_check_expected_value(src); + ztest_check_expected_value(mstp_address); +} + +void MSTP_Zero_Config_UUID_Init(struct mstp_port_struct_t *mstp_port) +{ + ztest_check_expected_value(mstp_port); +} + +unsigned MSTP_Zero_Config_Station_Increment(unsigned station) +{ + ztest_check_expected_value(station); + return ztest_get_return_value(); +} + +void MSTP_Zero_Config_FSM(struct mstp_port_struct_t *mstp_port) +{ + ztest_check_expected_value(mstp_port); +} diff --git a/test/bacnet/datalink/test/mstp-rs485.c b/test/bacnet/datalink/test/mstp-rs485.c new file mode 100644 index 00000000..2677e0e2 --- /dev/null +++ b/test/bacnet/datalink/test/mstp-rs485.c @@ -0,0 +1,51 @@ +/** + * @file + * @brief Mock for RS485 driver API + * @author Steve Karg + * @date November 2024 + * @copyright SPDX-License-Identifier: MIT + */ +#include +#include +#include +#include "bacnet/datalink/dlmstp.h" + +void MSTP_RS485_Init(void) +{ +} + +void MSTP_RS485_Send(const uint8_t *payload, uint16_t payload_len) +{ + ztest_check_expected_data(payload, payload_len); +} + +bool MSTP_RS485_Read(uint8_t *buf) +{ + ztest_check_expected_value(buf); + return ztest_get_return_value(); +} + +bool MSTP_RS485_Transmitting(void) +{ + return ztest_get_return_value(); +} + +uint32_t MSTP_RS485_Baud_Rate(void) +{ + return ztest_get_return_value(); +} + +bool MSTP_RS485_Baud_Rate_Set(uint32_t baud) +{ + ztest_check_expected_value(baud); + return ztest_get_return_value(); +} + +uint32_t MSTP_RS485_Silence_Milliseconds(void) +{ + return ztest_get_return_value(); +} + +void MSTP_RS485_Silence_Reset(void) +{ +} diff --git a/test/bacnet/datalink/test/mstp-rs485.h b/test/bacnet/datalink/test/mstp-rs485.h new file mode 100644 index 00000000..c962fc15 --- /dev/null +++ b/test/bacnet/datalink/test/mstp-rs485.h @@ -0,0 +1,22 @@ +/** + * @file + * @brief Mock for MS/TP RS485 driver API + * @author Steve Karg + * @date November 2024 + * @copyright SPDX-License-Identifier: MIT + */ +#ifndef MSTP_RS485_H +#define MSTP_RS485_H +#include +#include + +void MSTP_RS485_Init(void); +void MSTP_RS485_Send(const uint8_t *payload, uint16_t payload_len); +bool MSTP_RS485_Read(uint8_t *buf); +bool MSTP_RS485_Transmitting(void); +uint32_t MSTP_RS485_Baud_Rate(void); +bool MSTP_RS485_Baud_Rate_Set(uint32_t baud); +uint32_t MSTP_RS485_Silence_Milliseconds(void); +void MSTP_RS485_Silence_Reset(void); + +#endif