From d7918bb2ea8c26e7a684925d9542ca999953ccdf Mon Sep 17 00:00:00 2001 From: Steve Karg Date: Sat, 11 Apr 2020 22:58:07 -0500 Subject: [PATCH] Feature/add bbmd unit tests (#65) * Added som BBMD IPv4 and IPv6 unit tests Co-authored-by: Steve Karg --- Makefile | 8 + src/bacnet/basic/bbmd/h_bbmd.c | 148 +-------- src/bacnet/basic/bbmd/h_bbmd.h | 13 + src/bacnet/basic/bbmd6/h_bbmd6.c | 165 ++------- src/bacnet/basic/bbmd6/h_bbmd6.h | 16 +- src/bacnet/datalink/bvlc.c | 4 +- test/Makefile | 13 +- .../bacnet/basic/bbmd/Makefile | 13 +- test/bacnet/basic/bbmd/main.c | 267 +++++++++++++++ test/bacnet/basic/bbmd6/Makefile | 52 +++ test/bacnet/basic/bbmd6/main.c | 312 ++++++++++++++++++ 11 files changed, 715 insertions(+), 296 deletions(-) rename src/bacnet/basic/bbmd/h_bbmd.mak => test/bacnet/basic/bbmd/Makefile (75%) create mode 100644 test/bacnet/basic/bbmd/main.c create mode 100644 test/bacnet/basic/bbmd6/Makefile create mode 100644 test/bacnet/basic/bbmd6/main.c diff --git a/Makefile b/Makefile index 10453aed..f3b8f46e 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,14 @@ mstpwin32: mstp: $(MAKE) BACDL=mstp -C apps all +.PHONY: bip6-win32 +bip6-win32: + $(MAKE) BACDL=bip6 BACNET_PORT=win32 -C apps all + +.PHONY: bip6 +bip6: + $(MAKE) BACDL=bip6 -C apps all + .PHONY: apps apps: $(MAKE) -s -C apps all diff --git a/src/bacnet/basic/bbmd/h_bbmd.c b/src/bacnet/basic/bbmd/h_bbmd.c index c6fe0ff7..51449aa6 100644 --- a/src/bacnet/basic/bbmd/h_bbmd.c +++ b/src/bacnet/basic/bbmd/h_bbmd.c @@ -639,7 +639,6 @@ static int bvlc_send_result(BACNET_IP_ADDRESS *dest_addr, uint16_t result_code) return bip_send_mpdu(dest_addr, mtu, mtu_len); } -#if ((!BBMD_ENABLED) || (TEST)) /** * Use this handler when you are not a BBMD. * Sets the BVLC_Function_Code in case it is needed later. @@ -651,7 +650,7 @@ static int bvlc_send_result(BACNET_IP_ADDRESS *dest_addr, uint16_t result_code) * * @return number of bytes offset into the NPDU for APDU, or 0 if handled */ -static int handler_bbmd_for_non_bbmd(BACNET_IP_ADDRESS *addr, +int bvlc_bbmd_disabled_handler(BACNET_IP_ADDRESS *addr, BACNET_ADDRESS *src, uint8_t *mtu, uint16_t mtu_len) @@ -785,7 +784,6 @@ static int handler_bbmd_for_non_bbmd(BACNET_IP_ADDRESS *addr, return offset; } -#endif #if BBMD_ENABLED /** @@ -799,7 +797,7 @@ static int handler_bbmd_for_non_bbmd(BACNET_IP_ADDRESS *addr, * * @return number of bytes offset into the NPDU for APDU, or 0 if handled */ -static int handler_bbmd_for_bbmd(BACNET_IP_ADDRESS *addr, +int bvlc_bbmd_enabled_handler(BACNET_IP_ADDRESS *addr, BACNET_ADDRESS *src, uint8_t *mtu, uint16_t mtu_len) @@ -1111,10 +1109,10 @@ int bvlc_handler(BACNET_IP_ADDRESS *addr, { #if BBMD_ENABLED debug_print_bip("Received BVLC (BBMD Enabled)", addr); - return handler_bbmd_for_bbmd(addr, src, npdu, npdu_len); + return bvlc_bbmd_enabled_handler(addr, src, npdu, npdu_len); #else debug_print_bip("Received BVLC (BBMD Disabled)", addr); - return handler_bbmd_for_non_bbmd(addr, src, npdu, npdu_len); + return bvlc_bbmd_disabled_handler(addr, src, npdu, npdu_len); #endif } @@ -1254,141 +1252,3 @@ void bvlc_init(void) bvlc_foreign_device_table_link_array(&FD_Table[0], MAX_FD_ENTRIES); #endif } - -#ifdef TEST -#include -#include -#include "ctest.h" -static uint32_t Device_ID = 0; -static BACNET_IP_ADDRESS BIP_Addr; -static BACNET_IP_ADDRESS BIP_Broadcast_Addr; - -/* network stub functions */ -/** - * BACnet/IP Datalink Receive handler. - * - * @param src - returns the source address - * @param npdu - returns the NPDU buffer - * @param max_npdu -maximum size of the NPDU buffer - * @param timeout - number of milliseconds to wait for a packet - * - * @return Number of bytes received, or 0 if none or timeout. - */ -uint16_t bip_receive( - BACNET_ADDRESS *src, uint8_t *npdu, uint16_t max_npdu, unsigned timeout) -{ - return 0; -} - -/** - * The send function for BACnet/IPv4 driver layer - * - * @param dest - Points to a BACNET_IP_ADDRESS structure containing the - * destination address. - * @param mtu - the bytes of data to send - * @param mtu_len - the number of bytes of data to send - * - * @return Upon successful completion, returns the number of bytes sent. - * Otherwise, -1 shall be returned and errno set to indicate the error. - */ -int bip_send_mpdu(BACNET_IP_ADDRESS *dest, uint8_t *mtu, uint16_t mtu_len) -{ - return 0; -} - -/** Return the Object Instance number for our (single) Device Object. - * This is a key function, widely invoked by the handler code, since - * it provides "our" (ie, local) address. - * - * @return The Instance number used in the BACNET_OBJECT_ID for the Device. - */ -uint32_t Device_Object_Instance_Number(void) -{ - return Device_ID; -} - -/** - * Get the BACnet/IP address - * - * @return BACnet/IP address - */ -bool bip_get_addr(BACNET_IP_ADDRESS *addr) -{ - return bvlc_address_copy(addr, &BIP_Addr); -} - -/** - * Get the BACnet/IP address - * - * @return BACnet/IP address - */ -bool bip_get_broadcast_addr(BACNET_IP_ADDRESS *addr) -{ - return bvlc_address_copy(addr, &BIP_Broadcast_Addr); -} - -static void test_BBMD_Result(Test *pTest) -{ - int result = 0; - uint16_t result_code[] = { BVLC_RESULT_SUCCESSFUL_COMPLETION, - BVLC_RESULT_WRITE_BROADCAST_DISTRIBUTION_TABLE_NAK, - BVLC_RESULT_READ_BROADCAST_DISTRIBUTION_TABLE_NAK, - BVLC_RESULT_REGISTER_FOREIGN_DEVICE_NAK, - BVLC_RESULT_READ_FOREIGN_DEVICE_TABLE_NAK, - BVLC_RESULT_DELETE_FOREIGN_DEVICE_TABLE_ENTRY_NAK, - BVLC_RESULT_DISTRIBUTE_BROADCAST_TO_NETWORK_NAK }; - size_t result_code_max = sizeof(result_code) / sizeof(result_code[0]); - uint16_t test_result_code = 0; - uint8_t test_function_code = 0; - BACNET_IP_ADDRESS addr; - BACNET_ADDRESS src; - unsigned int i = 0; - uint8_t mtu[MAX_MPDU] = { 0 }; - uint16_t mtu_len = 0; - - bvlc_address_port_from_ascii(&addr, "192.168.0.1", "0xBAC0"); - for (i = 0; i < result_code_max; i++) { - mtu_len = bvlc_encode_result(&mtu[0], sizeof(mtu), result_code[i]); - result = handler_bbmd_for_non_bbmd(&addr, &src, &mtu[0], mtu_len); - /* validate that the result is handled (0) */ - ct_test(pTest, result == 0); - test_result_code = bvlc_get_last_result(); - ct_test(pTest, test_result_code == result_code[i]); - test_function_code = bvlc_get_function_code(); - ct_test(pTest, test_function_code == BVLC_RESULT); - result = handler_bbmd_for_bbmd(&addr, &src, &mtu[0], mtu_len); - /* validate that the result is handled (0) */ - ct_test(pTest, result == 0); - test_result_code = bvlc_get_last_result(); - ct_test(pTest, test_result_code == result_code[i]); - test_function_code = bvlc_get_function_code(); - ct_test(pTest, test_function_code == BVLC_RESULT); - } -} - -static void test_BBMD_Handler(Test *pTest) -{ - bool rc; - - /* individual tests */ - rc = ct_addTestFunction(pTest, test_BBMD_Result); - assert(rc); -} - -#ifdef TEST_BBMD_HANDLER -int main(void) -{ - Test *pTest; - - pTest = ct_create("BACnet Broadcast Management Device Handler", NULL); - test_BBMD_Handler(pTest); - /* configure output */ - ct_setStream(pTest, stdout); - ct_run(pTest); - (void)ct_report(pTest); - ct_destroy(pTest); - - return 0; -} -#endif -#endif diff --git a/src/bacnet/basic/bbmd/h_bbmd.h b/src/bacnet/basic/bbmd/h_bbmd.h index ac0d4531..73feeb69 100644 --- a/src/bacnet/basic/bbmd/h_bbmd.h +++ b/src/bacnet/basic/bbmd/h_bbmd.h @@ -47,6 +47,19 @@ int bvlc_handler(BACNET_IP_ADDRESS *addr, uint8_t *npdu, uint16_t npdu_len); +BACNET_STACK_EXPORT +int bvlc_bbmd_enabled_handler(BACNET_IP_ADDRESS *addr, + BACNET_ADDRESS *src, + uint8_t *mtu, + uint16_t mtu_len); + +BACNET_STACK_EXPORT +int bvlc_bbmd_disabled_handler(BACNET_IP_ADDRESS *addr, + BACNET_ADDRESS *src, + uint8_t *mtu, + uint16_t mtu_len); + + BACNET_STACK_EXPORT int bvlc_send_pdu(BACNET_ADDRESS *dest, BACNET_NPDU_DATA *npdu_data, diff --git a/src/bacnet/basic/bbmd6/h_bbmd6.c b/src/bacnet/basic/bbmd6/h_bbmd6.c index a04d7b9b..0bb6f5f8 100644 --- a/src/bacnet/basic/bbmd6/h_bbmd6.c +++ b/src/bacnet/basic/bbmd6/h_bbmd6.c @@ -42,9 +42,6 @@ #include "bacnet/basic/sys/debug.h" #include "bacnet/basic/object/device.h" #include "bacnet/basic/bbmd6/vmac.h" -#ifndef TEST -#include "bacport.h" -#endif /** result from a client request */ static uint16_t BVLC6_Result_Code = BVLC6_RESULT_SUCCESSFUL_COMPLETION; @@ -603,7 +600,7 @@ static void bbmd6_address_resolution_ack_handler( * * @return number of bytes offset into the NPDU for APDU, or 0 if handled */ -static int handler_bbmd6_for_non_bbmd(BACNET_IP6_ADDRESS *addr, +int bvlc6_bbmd_disabled_handler(BACNET_IP6_ADDRESS *addr, BACNET_ADDRESS *src, uint8_t *mtu, uint16_t mtu_len) @@ -770,7 +767,7 @@ static int handler_bbmd6_for_non_bbmd(BACNET_IP6_ADDRESS *addr, * * @return number of bytes offset into the NPDU for APDU, or 0 if handled */ -static int handler_bbmd6_for_bbmd(BACNET_IP6_ADDRESS *addr, +int bvlc6_bbmd_enabled_handler(BACNET_IP6_ADDRESS *addr, BACNET_ADDRESS *src, uint8_t *mtu, uint16_t mtu_len) @@ -960,9 +957,9 @@ int bvlc6_handler(BACNET_IP6_ADDRESS *addr, uint16_t npdu_len) { #if defined(BACDL_BIP6) && BBMD6_ENABLED - return handler_bbmd6_for_bbmd(addr, src, npdu, npdu_len); + return bvlc6_bbmd_enabled_handler(addr, src, npdu, npdu_len); #else - return handler_bbmd6_for_non_bbmd(addr, src, npdu, npdu_len); + return bvlc6_bbmd_disabled_handler(addr, src, npdu, npdu_len); #endif } @@ -1013,144 +1010,26 @@ uint8_t bvlc6_get_function_code(void) return BVLC6_Function_Code; } +/** + * Cleanup any memory usage + */ +void bvlc6_cleanup(void) +{ + VMAC_Cleanup(); +} + +/** + * Initialize any tables or other memory + */ void bvlc6_init(void) { VMAC_Init(); -} - -#ifdef TEST -#include -#include -#include "ctest.h" -static uint32_t Device_ID = 0; -static uint32_t Test_Device_ID = 12345; -static BACNET_IP6_ADDRESS BIP6_Addr; -static BACNET_IP6_ADDRESS Test_BIP6_Addr; -static BACNET_IP6_ADDRESS BIP6_Broadcast_Addr; -static uint8_t BIP6_MTU_Buffer[MAX_MPDU]; - -/* network stub functions */ -/** - * BACnet/IP Datalink Receive handler. - * - * @param src - returns the source address - * @param npdu - returns the NPDU buffer - * @param max_npdu -maximum size of the NPDU buffer - * @param timeout - number of milliseconds to wait for a packet - * - * @return Number of bytes received, or 0 if none or timeout. - */ -uint16_t bip6_receive( - BACNET_ADDRESS *src, uint8_t *npdu, uint16_t max_npdu, unsigned timeout) -{ - return 0; -} - -/** - * The send function for BACnet/IPv6 driver layer - * - * @param dest - Points to a BACNET_IP6_ADDRESS structure containing the - * destination address. - * @param mtu - the bytes of data to send - * @param mtu_len - the number of bytes of data to send - * - * @return Upon successful completion, returns the number of bytes sent. - * Otherwise, -1 shall be returned and errno set to indicate the error. - */ -int bip6_send_mpdu(BACNET_IP6_ADDRESS *dest, uint8_t *mtu, uint16_t mtu_len) -{ - return 0; -} - -/** Return the Object Instance number for our (single) Device Object. - * This is a key function, widely invoked by the handler code, since - * it provides "our" (ie, local) address. - * - * @return The Instance number used in the BACNET_OBJECT_ID for the Device. - */ -uint32_t Device_Object_Instance_Number(void) -{ - return Device_ID; -} - -/** - * Get the BACnet/IP address - * - * @return BACnet/IP address - */ -bool bip6_get_addr(BACNET_IP6_ADDRESS *addr) -{ - return bvlc6_address_copy(addr, &BIP6_Addr); -} - -/** - * Get the BACnet/IP address - * - * @return BACnet/IP address - */ -bool bip6_get_broadcast_addr(BACNET_IP6_ADDRESS *addr) -{ - return bvlc6_address_copy(addr, &BIP6_Broadcast_Addr); -} - -static void test_BBMD_Result(Test *pTest) -{ - int result = 0; - uint32_t vmac_src = 0x1234; - uint16_t result_code[6] = { BVLC6_RESULT_SUCCESSFUL_COMPLETION, - BVLC6_RESULT_ADDRESS_RESOLUTION_NAK, - BVLC6_RESULT_VIRTUAL_ADDRESS_RESOLUTION_NAK, - BVLC6_RESULT_REGISTER_FOREIGN_DEVICE_NAK, - BVLC6_RESULT_DELETE_FOREIGN_DEVICE_NAK, - BVLC6_RESULT_DISTRIBUTE_BROADCAST_TO_NETWORK_NAK }; - uint16_t test_result_code = 0; - uint8_t test_function_code = 0; - BACNET_IP6_ADDRESS addr; - BACNET_ADDRESS src; - unsigned int i = 0; - uint8_t mtu[MAX_MPDU] = { 0 }; - uint16_t mtu_len = 0; - - bvlc6_address_set(&addr, BIP6_MULTICAST_LINK_LOCAL, 0, 0, 0, 0, 0, 0, + BVLC6_Result_Code = BVLC6_RESULT_SUCCESSFUL_COMPLETION; + BVLC6_Function_Code = BVLC6_RESULT; + bvlc6_address_set(&Remote_BBMD, 0, 0, 0, 0, 0, 0, 0, BIP6_MULTICAST_GROUP_ID); - addr.port = 0xBAC0U; - bvlc6_vmac_address_set(&src, vmac_src); - for (i = 0; i < 6; i++) { - mtu_len = - bvlc6_encode_result(&mtu[0], sizeof(mtu), vmac_src, result_code[i]); - result = handler_bbmd6_for_non_bbmd(&addr, &src, &mtu[0], mtu_len); - /* validate that the result is handled (0) */ - ct_test(pTest, result == 0); - test_result_code = bvlc6_get_last_result(); - ct_test(pTest, test_result_code == result_code[i]); - test_function_code = bvlc6_get_function_code(); - ct_test(pTest, test_function_code == BVLC6_RESULT); - } -} - -static void test_BBMD6(Test *pTest) -{ - bool rc; - - /* individual tests */ - rc = ct_addTestFunction(pTest, test_BBMD_Result); - assert(rc); -} - -#ifdef TEST_BBMD6 -int main(void) -{ - Test *pTest; - - pTest = ct_create("BACnet Broadcast Management Device IP/v6", NULL); - test_BBMD6(pTest); - /* configure output */ - ct_setStream(pTest, stdout); - ct_run(pTest); - (void)ct_report(pTest); - ct_destroy(pTest); - - return 0; -} -#endif +#if defined(BACDL_BIP6) && BBMD6_ENABLED + memset(&BBMD_Table, 0, sizeof(BBMD_Table)); + memset(&FD_Table, 0, sizeof(FD_Table)); #endif +} diff --git a/src/bacnet/basic/bbmd6/h_bbmd6.h b/src/bacnet/basic/bbmd6/h_bbmd6.h index c909b3d5..33341807 100644 --- a/src/bacnet/basic/bbmd6/h_bbmd6.h +++ b/src/bacnet/basic/bbmd6/h_bbmd6.h @@ -48,6 +48,18 @@ extern "C" { uint8_t * npdu, uint16_t npdu_len); + BACNET_STACK_EXPORT + int bvlc6_bbmd_enabled_handler(BACNET_IP6_ADDRESS *addr, + BACNET_ADDRESS *src, + uint8_t *mtu, + uint16_t mtu_len); + + BACNET_STACK_EXPORT + int bvlc6_bbmd_disabled_handler(BACNET_IP6_ADDRESS *addr, + BACNET_ADDRESS *src, + uint8_t *mtu, + uint16_t mtu_len); + BACNET_STACK_EXPORT int bvlc6_send_pdu(BACNET_ADDRESS *dest, BACNET_NPDU_DATA *npdu_data, @@ -73,8 +85,10 @@ extern "C" { uint16_t seconds); BACNET_STACK_EXPORT - void bvlc6_init(void); + void bvlc6_cleanup(void); + BACNET_STACK_EXPORT + void bvlc6_init(void); #ifdef __cplusplus } diff --git a/src/bacnet/datalink/bvlc.c b/src/bacnet/datalink/bvlc.c index be45c37f..448c125a 100644 --- a/src/bacnet/datalink/bvlc.c +++ b/src/bacnet/datalink/bvlc.c @@ -1464,7 +1464,7 @@ int bvlc_decode_original_unicast(uint8_t *pdu, int bytes_consumed = 0; uint16_t i = 0; - if (pdu_len >= npdu_size) { + if (pdu_len <= npdu_size) { if (pdu && npdu) { for (i = 0; i < pdu_len; i++) { npdu[i] = pdu[i]; @@ -1541,7 +1541,7 @@ int bvlc_decode_original_broadcast(uint8_t *pdu, int bytes_consumed = 0; uint16_t i = 0; - if (pdu_len >= npdu_size) { + if (pdu_len <= npdu_size) { if (pdu && npdu) { for (i = 0; i < pdu_len; i++) { npdu[i] = pdu[i]; diff --git a/test/Makefile b/test/Makefile index 62f7fccf..5da6a689 100644 --- a/test/Makefile +++ b/test/Makefile @@ -2,10 +2,11 @@ LOGFILE = test.log -all: abort address arf awf bvlc6 bacapp bacdcode bacerror bacint bacstr \ +all: abort address arf awf bvlc bvlc6 bacapp bacdcode bacerror bacint bacstr \ cov crc datetime dcc event filename fifo getevent iam ihave \ indtext keylist key lighting lso memcopy npdu proplist ptransfer \ rd reject ringbuf rp rpm sbuf timesync vmac \ + bbmd bbmd6 \ whohas whois wp clean: logfile @@ -70,11 +71,21 @@ bvlc: logfile bvlc.mak ( ./bvlc >> ${LOGFILE} ) $(MAKE) -s -f bvlc.mak clean +bbmd: logfile bacnet/basic/bbmd/Makefile + $(MAKE) -s -C bacnet/basic/bbmd/ clean all + ( ./bacnet/basic/bbmd/unittest >> ${LOGFILE} ) + $(MAKE) -s -C bacnet/basic/bbmd/ clean + bvlc6: logfile bvlc6.mak $(MAKE) -s -f bvlc6.mak clean all ( ./bvlc6 >> ${LOGFILE} ) $(MAKE) -s -f bvlc6.mak clean +bbmd6: logfile bacnet/basic/bbmd6/Makefile + $(MAKE) -s -C bacnet/basic/bbmd6/ clean all + ( ./bacnet/basic/bbmd6/unittest >> ${LOGFILE} ) + $(MAKE) -s -C bacnet/basic/bbmd6/ clean + cov: logfile cov.mak $(MAKE) -s -f cov.mak clean all ( ./cov >> ${LOGFILE} ) diff --git a/src/bacnet/basic/bbmd/h_bbmd.mak b/test/bacnet/basic/bbmd/Makefile similarity index 75% rename from src/bacnet/basic/bbmd/h_bbmd.mak rename to test/bacnet/basic/bbmd/Makefile index ee5081ee..dea1623f 100644 --- a/src/bacnet/basic/bbmd/h_bbmd.mak +++ b/test/bacnet/basic/bbmd/Makefile @@ -1,22 +1,25 @@ #Makefile to build test case CC = gcc SRC_DIR = ../../../../src -TEST_DIR = ../../../../test +TEST_DIR = ../../.. INCLUDES = -I$(SRC_DIR) -I$(TEST_DIR) -DEFINES = -DBIG_ENDIAN=0 -DBACDL_BIP -DBBMD_ENABLED=1 -DTEST -DTEST_BBMD_HANDLER +DEFINES = -DBIG_ENDIAN=0 -DDEBUG_ENABLED=0 CFLAGS = -Wall $(INCLUDES) $(DEFINES) -g -SRCS = $(SRC_DIR)/bacnet/basic/bbmd/h_bbmd.c \ +SRCS = main.c \ + $(SRC_DIR)/bacnet/basic/bbmd/h_bbmd.c \ $(SRC_DIR)/bacnet/bacdcode.c \ $(SRC_DIR)/bacnet/bacint.c \ $(SRC_DIR)/bacnet/bacstr.c \ $(SRC_DIR)/bacnet/bacreal.c \ + $(SRC_DIR)/bacnet/iam.c \ + $(SRC_DIR)/bacnet/npdu.c \ $(SRC_DIR)/bacnet/datalink/bvlc.c \ $(SRC_DIR)/bacnet/basic/sys/debug.c \ $(TEST_DIR)/ctest.c -TARGET_NAME = bbmd +TARGET_NAME = unittest ifeq ($(OS),Windows_NT) TARGET_EXT = .exe else @@ -39,7 +42,7 @@ depend: ${CC} -MM ${CFLAGS} *.c >> .depend clean: - rm -rf core ${TARGET} $(OBJS) *.bak *.1 *.ini + rm -rf ${TARGET} $(OBJS) test: ${TARGET} ./${TARGET} diff --git a/test/bacnet/basic/bbmd/main.c b/test/bacnet/basic/bbmd/main.c new file mode 100644 index 00000000..e677f9d0 --- /dev/null +++ b/test/bacnet/basic/bbmd/main.c @@ -0,0 +1,267 @@ +/** + * @file + * @author Steve Karg + * @date April 2020 + * @brief Test file for a basic BBMD for BVLC IPv4 handler + * + * @section LICENSE + * + * 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. + */ +#include /* for standard i/o, like printing */ +#include /* for standard integer types uint8_t etc. */ +#include /* for the standard bool type. */ +#include /* for memcpy */ +#include +#include +#include "bacnet/bacdcode.h" +#include "bacnet/iam.h" +#include "bacnet/npdu.h" +#include "bacnet/datalink/bip.h" +#include "bacnet/datalink/bvlc.h" +#include "bacnet/basic/sys/debug.h" +#include "bacnet/basic/object/device.h" +#include "bacnet/basic/bbmd/h_bbmd.h" +#include "ctest.h" + +struct device_info_t { + uint32_t Device_ID; + BACNET_IP_ADDRESS BIP_Addr; + BACNET_IP_ADDRESS BIP_Broadcast_Addr; + BACNET_ADDRESS BACnet_Address; +}; +static struct device_info_t TD; +static struct device_info_t IUT; + +/* for the reply sent from the handler */ +static uint8_t Test_Sent_Message_Type; +static uint8_t Test_Sent_Message_Length; +static uint8_t Test_Sent_Message_Buffer[MAX_MPDU]; +static uint16_t Test_Sent_Message_Buffer_Length; +static BACNET_IP_ADDRESS Test_Sent_Message_Dest; + +/* network stub functions */ +/** + * BACnet/IP Datalink Receive handler. + * + * @param src - returns the source address + * @param npdu - returns the NPDU buffer + * @param max_npdu -maximum size of the NPDU buffer + * @param timeout - number of milliseconds to wait for a packet + * + * @return Number of bytes received, or 0 if none or timeout. + */ +uint16_t bip_receive( + BACNET_ADDRESS *src, uint8_t *npdu, uint16_t max_npdu, unsigned timeout) +{ + return 0; +} + +/** + * The send function for BACnet/IPv6 driver layer + * + * @param dest - Points to a BACNET_IP_ADDRESS structure containing the + * destination address. + * @param mtu - the bytes of data to send + * @param mtu_len - the number of bytes of data to send + * + * @return Upon successful completion, returns the number of bytes sent. + * Otherwise, -1 shall be returned and errno set to indicate the error. + */ +int bip_send_mpdu(BACNET_IP_ADDRESS *dest, uint8_t *mtu, uint16_t mtu_len) +{ + uint8_t message_type = 0; + uint16_t message_length = 0; + int header_len = 0; + + header_len = + bvlc_decode_header(mtu, mtu_len, &message_type, &message_length); + Test_Sent_Message_Type = message_type; + Test_Sent_Message_Length = message_length; + bvlc_address_copy(&Test_Sent_Message_Dest, dest); + if ((header_len == 4) && (mtu_len >= 4)) { + memcpy(&Test_Sent_Message_Buffer[0], &mtu[4], mtu_len-4); + Test_Sent_Message_Buffer_Length = mtu_len - 4; + } else { + Test_Sent_Message_Buffer_Length = 0; + } + + return 0; +} + +/** Return the Object Instance number for our (single) Device Object. + * This is a key function, widely invoked by the handler code, since + * it provides "our" (ie, local) address. + * + * @return The Instance number used in the BACNET_OBJECT_ID for the Device. + */ +uint32_t Device_Object_Instance_Number(void) +{ + return IUT.Device_ID; +} + +/** + * Get the BACnet/IP address + * + * @return BACnet/IP address + */ +bool bip_get_addr(BACNET_IP_ADDRESS *addr) +{ + return bvlc_address_copy(addr, &IUT.BIP_Addr); +} + +/** + * Get the BACnet/IP address + * + * @return BACnet/IP address + */ +bool bip_get_broadcast_addr(BACNET_IP_ADDRESS *addr) +{ + return bvlc_address_copy(addr, &IUT.BIP_Broadcast_Addr); +} + +static void test_setup(void) +{ + bvlc_init(); + bvlc_address_set(&TD.BIP_Broadcast_Addr, 255, 255, 255, 255); + bvlc_address_set(&TD.BIP_Addr, 192, 168, 1, 100); + TD.Device_ID = 12345; + + bvlc_address_set(&IUT.BIP_Broadcast_Addr, 255, 255, 255, 255); + bvlc_address_set(&IUT.BIP_Addr, 192, 168, 1, 10); + IUT.Device_ID = 54321; +} + +static void test_cleanup(void) +{ + +} + +/** + * @brief Test 15.2.1.1 Initiate Original-Broadcast-NPDU + */ +static void test_Initiate_Original_Broadcast_NPDU(Test *pTest) +{ + uint8_t pdu[MAX_MPDU] = {0}; + int npdu_len = 0; + int apdu_len = 0; + int pdu_len = 0; + BACNET_ADDRESS dest = {0}; + BACNET_NPDU_DATA npdu_data = {0}; + uint8_t test_pdu[MAX_MPDU] = {0}; + uint16_t test_pdu_len = 0; + int function_len = 0; + + test_setup(); + /* MAKE(the IUT send a broadcast) */ + dest.net = BACNET_BROADCAST_NETWORK; + npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL); + npdu_len = npdu_encode_pdu(&pdu[0], &dest, &IUT.BACnet_Address, &npdu_data); + apdu_len = iam_encode_apdu(&pdu[npdu_len], IUT.Device_ID, MAX_APDU, + SEGMENTATION_NONE, BACNET_VENDOR_ID); + pdu_len = npdu_len + apdu_len; + bvlc_send_pdu(&dest, &npdu_data, pdu, pdu_len); + /* DA=Link Local Multicast Address */ + ct_test(pTest, !bvlc_address_different(&TD.BIP_Broadcast_Addr, + &Test_Sent_Message_Dest)); + /* SA = IUT - done in port layer */ + /* Original-Broadcast-NPDU */ + ct_test(pTest, Test_Sent_Message_Type == + BVLC_ORIGINAL_BROADCAST_NPDU); + if (Test_Sent_Message_Type == BVLC_ORIGINAL_BROADCAST_NPDU) { + function_len = bvlc_decode_original_broadcast( + Test_Sent_Message_Buffer, Test_Sent_Message_Buffer_Length, + test_pdu, sizeof(test_pdu), &test_pdu_len); + printf("len=%u pdu[%u] test_pdu[%u]\n", + (unsigned)function_len, + (unsigned)Test_Sent_Message_Buffer_Length, + (unsigned)sizeof(test_pdu)); + ct_test(pTest, function_len > 0); + /* (any valid BACnet-Unconfirmed-Request-PDU, + with any valid broadcast network options */ + ct_test(pTest, test_pdu_len == pdu_len); + } + test_cleanup(); +} + +static void test_BBMD_Result(Test *pTest) +{ + int result = 0; + uint16_t result_code[] = { BVLC_RESULT_SUCCESSFUL_COMPLETION, + BVLC_RESULT_WRITE_BROADCAST_DISTRIBUTION_TABLE_NAK, + BVLC_RESULT_READ_BROADCAST_DISTRIBUTION_TABLE_NAK, + BVLC_RESULT_REGISTER_FOREIGN_DEVICE_NAK, + BVLC_RESULT_READ_FOREIGN_DEVICE_TABLE_NAK, + BVLC_RESULT_DELETE_FOREIGN_DEVICE_TABLE_ENTRY_NAK, + BVLC_RESULT_DISTRIBUTE_BROADCAST_TO_NETWORK_NAK }; + size_t result_code_max = sizeof(result_code) / sizeof(result_code[0]); + uint16_t test_result_code = 0; + uint8_t test_function_code = 0; + BACNET_IP_ADDRESS addr; + BACNET_ADDRESS src; + unsigned int i = 0; + uint8_t mtu[MAX_MPDU] = { 0 }; + uint16_t mtu_len = 0; + + bvlc_address_port_from_ascii(&addr, "192.168.0.1", "0xBAC0"); + for (i = 0; i < result_code_max; i++) { + mtu_len = bvlc_encode_result(&mtu[0], sizeof(mtu), result_code[i]); + result = bvlc_bbmd_disabled_handler(&addr, &src, &mtu[0], mtu_len); + /* validate that the result is handled (0) */ + ct_test(pTest, result == 0); + test_result_code = bvlc_get_last_result(); + ct_test(pTest, test_result_code == result_code[i]); + test_function_code = bvlc_get_function_code(); + ct_test(pTest, test_function_code == BVLC_RESULT); + result = bvlc_bbmd_enabled_handler(&addr, &src, &mtu[0], mtu_len); + /* validate that the result is handled (0) */ + ct_test(pTest, result == 0); + test_result_code = bvlc_get_last_result(); + ct_test(pTest, test_result_code == result_code[i]); + test_function_code = bvlc_get_function_code(); + ct_test(pTest, test_function_code == BVLC_RESULT); + } +} + +static void test_BBMD_Handler(Test *pTest) +{ + bool rc; + + /* individual tests */ + rc = ct_addTestFunction(pTest, test_BBMD_Result); + assert(rc); + rc = ct_addTestFunction(pTest, test_Initiate_Original_Broadcast_NPDU); + assert(rc); +} + +int main(void) +{ + Test *pTest; + + pTest = ct_create("BACnet Broadcast Management Device IP/v4", NULL); + test_BBMD_Handler(pTest); + /* configure output */ + ct_setStream(pTest, stdout); + ct_run(pTest); + (void)ct_report(pTest); + ct_destroy(pTest); + + return 0; +} diff --git a/test/bacnet/basic/bbmd6/Makefile b/test/bacnet/basic/bbmd6/Makefile new file mode 100644 index 00000000..dd8a3d3d --- /dev/null +++ b/test/bacnet/basic/bbmd6/Makefile @@ -0,0 +1,52 @@ +#Makefile to build test case +CC = gcc +SRC_DIR = ../../../../src +TEST_DIR = ../../.. +INCLUDES = -I$(SRC_DIR) -I$(TEST_DIR) +DEFINES = -DBIG_ENDIAN=0 -DDEBUG_ENABLED=0 + +CFLAGS = -Wall $(INCLUDES) $(DEFINES) -g + +SRCS = main.c \ + $(SRC_DIR)/bacnet/bacdcode.c \ + $(SRC_DIR)/bacnet/bacint.c \ + $(SRC_DIR)/bacnet/bacstr.c \ + $(SRC_DIR)/bacnet/bacreal.c \ + $(SRC_DIR)/bacnet/iam.c \ + $(SRC_DIR)/bacnet/npdu.c \ + $(SRC_DIR)/bacnet/basic/sys/keylist.c \ + $(SRC_DIR)/bacnet/basic/bbmd6/h_bbmd6.c \ + $(SRC_DIR)/bacnet/basic/bbmd6/vmac.c \ + $(SRC_DIR)/bacnet/datalink/bvlc6.c \ + $(SRC_DIR)/bacnet/basic/sys/debug.c \ + $(TEST_DIR)/ctest.c + +TARGET_NAME = unittest +ifeq ($(OS),Windows_NT) +TARGET_EXT = .exe +else +TARGET_EXT = +endif +TARGET = $(TARGET_NAME)$(TARGET_EXT) + +all: ${TARGET} + +OBJS = ${SRCS:.c=.o} + +${TARGET}: ${OBJS} + ${CC} -o $@ ${OBJS} + +.c.o: + ${CC} -c ${CFLAGS} $*.c -o $@ + +depend: + rm -f .depend + ${CC} -MM ${CFLAGS} *.c >> .depend + +clean: + rm -rf ${TARGET} $(OBJS) + +test: ${TARGET} + ./${TARGET} + +include: .depend diff --git a/test/bacnet/basic/bbmd6/main.c b/test/bacnet/basic/bbmd6/main.c new file mode 100644 index 00000000..3b4d6e6a --- /dev/null +++ b/test/bacnet/basic/bbmd6/main.c @@ -0,0 +1,312 @@ +/** + * @file + * @author Steve Karg + * @date April 2020 + * @brief Test file for a basic BBMD for BVLC IPv6 handler + * + * @section LICENSE + * + * 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. + */ +#include /* for standard i/o, like printing */ +#include /* for standard integer types uint8_t etc. */ +#include /* for the standard bool type. */ +#include /* for memcpy */ +#include +#include +#include "bacnet/bacdcode.h" +#include "bacnet/iam.h" +#include "bacnet/npdu.h" +#include "bacnet/datalink/bip6.h" +#include "bacnet/datalink/bvlc6.h" +#include "bacnet/basic/sys/debug.h" +#include "bacnet/basic/object/device.h" +#include "bacnet/basic/bbmd6/h_bbmd6.h" +#include "bacnet/basic/bbmd6/vmac.h" +#include "ctest.h" + +struct device_info_t { + uint32_t Device_ID; + BACNET_IP6_ADDRESS BIP6_Addr; + BACNET_IP6_ADDRESS BIP6_Broadcast_Addr; + BACNET_ADDRESS BACnet_Address; +}; +static struct device_info_t TD; +static struct device_info_t IUT; + +/* for the reply sent from the handler */ +static uint8_t Test_Sent_Message_Type; +static uint8_t Test_Sent_Message_Length; +static uint8_t Test_Sent_Message_Buffer[MAX_MPDU]; +static uint16_t Test_Sent_Message_Buffer_Length; +static BACNET_IP6_ADDRESS Test_Sent_Message_Dest; + +/* network stub functions */ +/** + * BACnet/IP Datalink Receive handler. + * + * @param src - returns the source address + * @param npdu - returns the NPDU buffer + * @param max_npdu -maximum size of the NPDU buffer + * @param timeout - number of milliseconds to wait for a packet + * + * @return Number of bytes received, or 0 if none or timeout. + */ +uint16_t bip6_receive( + BACNET_ADDRESS *src, uint8_t *npdu, uint16_t max_npdu, unsigned timeout) +{ + return 0; +} + +/** + * The send function for BACnet/IPv6 driver layer + * + * @param dest - Points to a BACNET_IP6_ADDRESS structure containing the + * destination address. + * @param mtu - the bytes of data to send + * @param mtu_len - the number of bytes of data to send + * + * @return Upon successful completion, returns the number of bytes sent. + * Otherwise, -1 shall be returned and errno set to indicate the error. + */ +int bip6_send_mpdu(BACNET_IP6_ADDRESS *dest, uint8_t *mtu, uint16_t mtu_len) +{ + uint8_t message_type = 0; + uint16_t message_length = 0; + int header_len = 0; + + header_len = + bvlc6_decode_header(mtu, mtu_len, &message_type, &message_length); + Test_Sent_Message_Type = message_type; + Test_Sent_Message_Length = message_length; + bvlc6_address_copy(&Test_Sent_Message_Dest, dest); + if ((header_len == 4) && (mtu_len >= 4)) { + memcpy(&Test_Sent_Message_Buffer[0], &mtu[4], mtu_len-4); + Test_Sent_Message_Buffer_Length = mtu_len - 4; + } else { + Test_Sent_Message_Buffer_Length = 0; + } + + return 0; +} + +/** Return the Object Instance number for our (single) Device Object. + * This is a key function, widely invoked by the handler code, since + * it provides "our" (ie, local) address. + * + * @return The Instance number used in the BACNET_OBJECT_ID for the Device. + */ +uint32_t Device_Object_Instance_Number(void) +{ + return IUT.Device_ID; +} + +/** + * Get the BACnet/IP address + * + * @return BACnet/IP address + */ +bool bip6_get_addr(BACNET_IP6_ADDRESS *addr) +{ + return bvlc6_address_copy(addr, &IUT.BIP6_Addr); +} + +/** + * Get the BACnet/IP address + * + * @return BACnet/IP address + */ +bool bip6_get_broadcast_addr(BACNET_IP6_ADDRESS *addr) +{ + return bvlc6_address_copy(addr, &IUT.BIP6_Broadcast_Addr); +} + +static void test_setup(void) +{ + bvlc6_init(); + /* BACnet_IPv6_Multicast_Address is FF02::BAC0 */ + bvlc6_address_set(&TD.BIP6_Broadcast_Addr, + BIP6_MULTICAST_LINK_LOCAL, 0, 0, 0, 0, 0, 0, + BIP6_MULTICAST_GROUP_ID); + bvlc6_address_set(&TD.BIP6_Addr, + 0x2001, 0x0DBB, 0xAC10, 0xFE01, 0, 0, 0, + BIP6_MULTICAST_GROUP_ID); + TD.Device_ID = 12345; + bvlc6_vmac_address_set(&TD.BACnet_Address, TD.Device_ID); + + + /* BACnet_IPv6_Multicast_Address is FF02::BAC0 */ + bvlc6_address_set(&IUT.BIP6_Broadcast_Addr, + BIP6_MULTICAST_LINK_LOCAL, 0, 0, 0, 0, 0, 0, + BIP6_MULTICAST_GROUP_ID); + bvlc6_address_set(&IUT.BIP6_Addr, + 0x2001, 0x0DBB, 0xAC10, 0xFE01, 0, 0, 1, + BIP6_MULTICAST_GROUP_ID); + IUT.Device_ID = 54321; + bvlc6_vmac_address_set(&IUT.BACnet_Address, IUT.Device_ID); +} + +static void test_cleanup(void) +{ + bvlc6_cleanup(); +} + +/** + * @brief Test 15.2.1.1 Initiate Original-Broadcast-NPDU + */ +static void test_Initiate_Original_Broadcast_NPDU(Test *pTest) +{ + uint8_t pdu[MAX_MPDU] = {0}; + int npdu_len = 0; + int apdu_len = 0; + int pdu_len = 0; + BACNET_ADDRESS dest = {0}; + BACNET_NPDU_DATA npdu_data = {0}; + uint8_t test_pdu[MAX_MPDU] = {0}; + uint16_t test_pdu_len = 0; + uint32_t test_vmac_src = 0; + int function_len = 0; + + test_setup(); + /* MAKE(the IUT send a broadcast) */ + dest.net = BACNET_BROADCAST_NETWORK; + npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL); + npdu_len = npdu_encode_pdu(&pdu[0], &dest, &IUT.BACnet_Address, &npdu_data); + apdu_len = iam_encode_apdu(&pdu[npdu_len], IUT.Device_ID, MAX_APDU, + SEGMENTATION_NONE, BACNET_VENDOR_ID); + pdu_len = npdu_len + apdu_len; + bvlc6_send_pdu(&dest, &npdu_data, pdu, pdu_len); + /* DA=Link Local Multicast Address */ + ct_test(pTest, !bvlc6_address_different(&TD.BIP6_Broadcast_Addr, + &Test_Sent_Message_Dest)); + /* SA = IUT - done in port layer */ + /* Original-Broadcast-NPDU */ + ct_test(pTest, Test_Sent_Message_Type == + BVLC6_ORIGINAL_BROADCAST_NPDU); + if (Test_Sent_Message_Type == BVLC6_ORIGINAL_BROADCAST_NPDU) { + function_len = bvlc6_decode_original_broadcast( + Test_Sent_Message_Buffer, Test_Sent_Message_Buffer_Length, + &test_vmac_src, test_pdu, sizeof(test_pdu), &test_pdu_len); + ct_test(pTest, function_len > 0); + /* Source-Virtual-Address = IUT */ + ct_test(pTest, test_vmac_src == IUT.Device_ID); + /* (any valid BACnet-Unconfirmed-Request-PDU, + with any valid broadcast network options */ + ct_test(pTest, test_pdu_len == pdu_len); + } + test_cleanup(); +} + +/** + * @brief Test 15.1.2 Execute Virtual-Address-Resolution + */ +static void test_Execute_Virtual_Address_Resolution(Test *pTest) +{ + uint8_t mtu[MAX_MPDU] = {0}; + uint16_t mtu_len = 0; + uint32_t test_vmac_src = 0; + uint32_t test_vmac_dst = 0; + int result = 0; + int function_len = 0; + + test_setup(); + mtu_len = bvlc6_encode_virtual_address_resolution( + &mtu[0], sizeof(mtu), TD.Device_ID); + result = bvlc6_bbmd_disabled_handler(&TD.BIP6_Addr, &TD.BACnet_Address, + &mtu[0], mtu_len); + ct_test(pTest, result == 0); + ct_test(pTest, bvlc6_get_function_code() == + BVLC6_VIRTUAL_ADDRESS_RESOLUTION); + ct_test(pTest, Test_Sent_Message_Type == + BVLC6_VIRTUAL_ADDRESS_RESOLUTION_ACK); + ct_test(pTest, VMAC_Find_By_Key(TD.Device_ID) != NULL); + if (Test_Sent_Message_Type == BVLC6_VIRTUAL_ADDRESS_RESOLUTION_ACK) { + function_len = bvlc6_decode_virtual_address_resolution_ack( + Test_Sent_Message_Buffer, Test_Sent_Message_Buffer_Length, + &test_vmac_src, &test_vmac_dst); + ct_test(pTest, function_len > 0); + ct_test(pTest, test_vmac_src == IUT.Device_ID); + ct_test(pTest, test_vmac_dst == TD.Device_ID); + } + test_cleanup(); +} + +static void test_BBMD_Result(Test *pTest) +{ + int result = 0; + uint32_t vmac_src = 0x1234; + uint16_t result_code[6] = { BVLC6_RESULT_SUCCESSFUL_COMPLETION, + BVLC6_RESULT_ADDRESS_RESOLUTION_NAK, + BVLC6_RESULT_VIRTUAL_ADDRESS_RESOLUTION_NAK, + BVLC6_RESULT_REGISTER_FOREIGN_DEVICE_NAK, + BVLC6_RESULT_DELETE_FOREIGN_DEVICE_NAK, + BVLC6_RESULT_DISTRIBUTE_BROADCAST_TO_NETWORK_NAK }; + uint16_t test_result_code = 0; + uint8_t test_function_code = 0; + BACNET_IP6_ADDRESS addr; + BACNET_ADDRESS src; + unsigned int i = 0; + uint8_t mtu[MAX_MPDU] = { 0 }; + uint16_t mtu_len = 0; + + bvlc6_address_set(&addr, BIP6_MULTICAST_LINK_LOCAL, 0, 0, 0, 0, 0, 0, + BIP6_MULTICAST_GROUP_ID); + addr.port = 0xBAC0U; + bvlc6_vmac_address_set(&src, vmac_src); + for (i = 0; i < 6; i++) { + mtu_len = + bvlc6_encode_result(&mtu[0], sizeof(mtu), vmac_src, result_code[i]); + result = bvlc6_bbmd_disabled_handler(&addr, &src, &mtu[0], mtu_len); + /* validate that the result is handled (0) */ + ct_test(pTest, result == 0); + test_result_code = bvlc6_get_last_result(); + ct_test(pTest, test_result_code == result_code[i]); + test_function_code = bvlc6_get_function_code(); + ct_test(pTest, test_function_code == BVLC6_RESULT); + } +} + +static void test_BBMD6(Test *pTest) +{ + bool rc; + + /* individual tests */ + rc = ct_addTestFunction(pTest, test_BBMD_Result); + assert(rc); + rc = ct_addTestFunction(pTest, test_Execute_Virtual_Address_Resolution); + assert(rc); + rc = ct_addTestFunction(pTest, test_Initiate_Original_Broadcast_NPDU); + assert(rc); +} + +int main(void) +{ + Test *pTest; + + pTest = ct_create("BACnet Broadcast Management Device IP/v6", NULL); + test_BBMD6(pTest); + /* configure output */ + ct_setStream(pTest, stdout); + ct_run(pTest); + (void)ct_report(pTest); + ct_destroy(pTest); + + return 0; +}