From 8b8ef8f338e52a0758eb498a189afff21b9be490 Mon Sep 17 00:00:00 2001 From: Greg Shue <32416235+gregshue@users.noreply.github.com> Date: Mon, 16 Aug 2021 15:29:40 -0700 Subject: [PATCH] Issue 187 enable skipped ztest suites (#189) * Fix some ztests that were skipped * Expose bacapp_same_value() * Fix bacapp, ptransfer tests * Fix bugs in Load_Control object & tests * refactor days functions from datetime module * fix legacy ctests * Add bacnet/basic/sys/days.[ch] to Zephyr build * Update ztest to match from Zephyr v2.6.0; update ringbuf, datetime to build * Fixup ztest test for object/acc * Fix bvlc_address_from_ascii; enable/fix bvlc test * Comment cleanup * test/bacnet/basic/object/lc partially enabled * Fix bacapp_decode_data_len return status on erroneous input * fix ztest include fatal error * fix ztest strsignal reference fatal error * fix zassert_mem_equal reference syntax error * fix zassert_mem_equal reference syntax error Co-authored-by: Gregory Shue Co-authored-by: Steve Karg --- CMakeLists.txt | 59 +- Makefile | 1 + README.md | 9 + ports/zephyr/bip-init.c | 11 +- src/bacnet/bacapp.c | 29 +- src/bacnet/bacapp.h | 11 - src/bacnet/basic/object/lc.c | 38 +- src/bacnet/basic/object/objects.c | 7 +- src/bacnet/basic/object/objects.h | 2 +- src/bacnet/basic/sys/days.c | 296 +++++++++ src/bacnet/basic/sys/days.h | 58 ++ src/bacnet/datalink/bvlc.c | 8 +- src/bacnet/datetime.c | 288 +++++---- src/bacnet/datetime.h | 498 +++++++-------- src/bacnet/lighting.c | 8 +- src/bacnet/timesync.c | 6 +- test/address.mak | 1 + test/bacapp.mak | 1 + test/bacdevobjpropref.mak | 1 + test/bacnet/alarm_ack/CMakeLists.txt | 1 + test/bacnet/bacapp/CMakeLists.txt | 1 + test/bacnet/bacapp/src/main.c | 528 ++++++++++++---- test/bacnet/bacdevobjpropref/CMakeLists.txt | 1 + .../basic/binding/address/CMakeLists.txt | 1 + test/bacnet/basic/binding/address/src/main.c | 25 +- test/bacnet/basic/object/acc/CMakeLists.txt | 1 + test/bacnet/basic/object/acc/src/main.c | 3 +- .../object/access_credential/CMakeLists.txt | 1 + .../basic/object/access_credential/src/main.c | 2 +- .../basic/object/access_door/CMakeLists.txt | 1 + .../basic/object/access_door/src/main.c | 80 ++- .../basic/object/access_point/CMakeLists.txt | 1 + .../basic/object/access_rights/CMakeLists.txt | 1 + .../basic/object/access_user/CMakeLists.txt | 1 + .../basic/object/access_zone/CMakeLists.txt | 1 + test/bacnet/basic/object/ai/CMakeLists.txt | 1 + test/bacnet/basic/object/ao/CMakeLists.txt | 1 + test/bacnet/basic/object/av/CMakeLists.txt | 1 + test/bacnet/basic/object/bi/CMakeLists.txt | 1 + test/bacnet/basic/object/bo/CMakeLists.txt | 1 + test/bacnet/basic/object/bv/CMakeLists.txt | 1 + .../basic/object/command/CMakeLists.txt | 1 + test/bacnet/basic/object/command/src/main.c | 103 ++- .../credential_data_input/CMakeLists.txt | 1 + .../bacnet/basic/object/device/CMakeLists.txt | 1 + test/bacnet/basic/object/lc/CMakeLists.txt | 1 + test/bacnet/basic/object/lc/src/main.c | 593 ++++++++++++++---- test/bacnet/basic/object/lo/CMakeLists.txt | 1 + test/bacnet/basic/object/lsp/CMakeLists.txt | 1 + .../basic/object/ms-input/CMakeLists.txt | 1 + test/bacnet/basic/object/mso/CMakeLists.txt | 1 + test/bacnet/basic/object/msv/CMakeLists.txt | 1 + .../basic/object/netport/CMakeLists.txt | 1 + test/bacnet/basic/object/objects/main.c | 4 +- test/bacnet/basic/object/objects/src/main.c | 29 +- test/bacnet/basic/object/osv/CMakeLists.txt | 1 + test/bacnet/basic/object/piv/CMakeLists.txt | 1 + .../basic/object/schedule/CMakeLists.txt | 1 + test/bacnet/basic/sys/days/CMakeLists.txt | 41 ++ test/bacnet/basic/sys/days/src/main.c | 161 +++++ test/bacnet/basic/sys/ringbuf/src/main.c | 23 +- test/bacnet/cov/CMakeLists.txt | 1 + test/bacnet/cov/src/main.c | 2 - test/bacnet/datalink/bvlc/CMakeLists.txt | 1 + test/bacnet/datalink/bvlc/src/main.c | 84 +-- test/bacnet/datetime/CMakeLists.txt | 1 + test/bacnet/datetime/src/main.c | 26 +- test/bacnet/event/CMakeLists.txt | 1 + test/bacnet/getevent/CMakeLists.txt | 1 + test/bacnet/lso/CMakeLists.txt | 27 +- test/bacnet/ptransfer/CMakeLists.txt | 1 + test/bacnet/ptransfer/src/main.c | 8 - test/bacnet/rpm/CMakeLists.txt | 1 + test/bacnet/rpm/src/main.c | 115 ---- test/bacnet/timestamp/CMakeLists.txt | 1 + test/bacnet/timesync/CMakeLists.txt | 1 + test/bacnet/timesync/src/main.c | 31 +- test/bacnet/wp/CMakeLists.txt | 1 + test/cov.mak | 1 + test/datetime.mak | 3 +- test/event.mak | 1 + test/getevent.mak | 1 + test/lso.mak | 1 + test/proplist.mak | 1 + test/ptransfer.mak | 1 + test/rpm.mak | 1 + test/timesync.mak | 1 + test/wp.mak | 1 + test/ztest/include/tc_util.h | 69 +- test/ztest/include/test_utils.h | 14 +- test/ztest/include/ztest.h | 30 +- test/ztest/include/ztest_assert.h | 45 +- test/ztest/include/ztest_error_hook.h | 75 +++ test/ztest/include/ztest_mock.h | 95 ++- test/ztest/include/ztest_test.h | 53 +- test/ztest/src/ztest.c | 356 ++++++++++- test/ztest/src/ztest_error_hook.c | 147 +++++ test/ztest/src/ztest_mock.c | 197 +++++- zephyr/CMakeLists.txt | 7 +- zephyr/Kconfig | 5 + .../bacnet/basic/binding/address/prj.conf | 1 + zephyr/tests/bacnet/datalink/bvlc/prj.conf | 23 + 102 files changed, 3178 insertions(+), 1208 deletions(-) create mode 100644 src/bacnet/basic/sys/days.c create mode 100644 src/bacnet/basic/sys/days.h create mode 100644 test/bacnet/basic/sys/days/CMakeLists.txt create mode 100644 test/bacnet/basic/sys/days/src/main.c create mode 100644 test/ztest/include/ztest_error_hook.h create mode 100644 test/ztest/src/ztest_error_hook.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 0cb94532..0cfb42c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -305,6 +305,8 @@ add_library(${PROJECT_NAME} src/bacnet/basic/services.h src/bacnet/basic/sys/bigend.c src/bacnet/basic/sys/bigend.h + src/bacnet/basic/sys/days.c + src/bacnet/basic/sys/days.h src/bacnet/basic/sys/debug.c src/bacnet/basic/sys/debug.h src/bacnet/basic/sys/fifo.c @@ -460,7 +462,7 @@ list(APPEND testdirs test/bacnet/bacreal test/bacnet/bacstr test/bacnet/cov - #test/bacnet/datetime #Tests skipped, redesign to use only API + test/bacnet/datetime test/bacnet/dcc test/bacnet/event test/bacnet/getevent @@ -489,34 +491,35 @@ list(APPEND testdirs # basic/object/binding test/bacnet/basic/binding/address # basic/object - #test/bacnet/basic/object/acc #Tests skipped, redesign to use only API - test/bacnet/basic/object/access_credential # Build failed - test/bacnet/basic/object/access_door # Build failed - test/bacnet/basic/object/access_point # Build failed - test/bacnet/basic/object/access_rights # Build failed - test/bacnet/basic/object/access_user # Build failed - test/bacnet/basic/object/access_zone # Build failed - test/bacnet/basic/object/ai # Build failed - test/bacnet/basic/object/ao # Build failed - test/bacnet/basic/object/av # Build failed - test/bacnet/basic/object/bi # Build failed - test/bacnet/basic/object/bo # Build failed - test/bacnet/basic/object/bv # Build failed - #test/bacnet/basic/object/command #Tests skipped, redesign to use only API - test/bacnet/basic/object/credential_data_input # Build failed - test/bacnet/basic/object/device # Build failed + test/bacnet/basic/object/acc + test/bacnet/basic/object/access_credential + test/bacnet/basic/object/access_door + test/bacnet/basic/object/access_point + test/bacnet/basic/object/access_rights + test/bacnet/basic/object/access_user + test/bacnet/basic/object/access_zone + test/bacnet/basic/object/ai + test/bacnet/basic/object/ao + test/bacnet/basic/object/av + test/bacnet/basic/object/bi + test/bacnet/basic/object/bo + test/bacnet/basic/object/bv + test/bacnet/basic/object/command + test/bacnet/basic/object/credential_data_input + test/bacnet/basic/object/device #test/bacnet/basic/object/lc #Tests skipped, redesign to use only API - test/bacnet/basic/object/lo # Build failed - test/bacnet/basic/object/lsp # Build failed - test/bacnet/basic/object/ms-input # Build failed - test/bacnet/basic/object/mso # Build failed - test/bacnet/basic/object/msv # Build failed - test/bacnet/basic/object/netport # Build failed - #test/bacnet/basic/object/objects #Tests skipped, redesign to use only API - test/bacnet/basic/object/osv # Build failed - test/bacnet/basic/object/piv # Build failed - test/bacnet/basic/object/schedule # Build failed + test/bacnet/basic/object/lo + test/bacnet/basic/object/lsp + test/bacnet/basic/object/ms-input + test/bacnet/basic/object/mso + test/bacnet/basic/object/msv + test/bacnet/basic/object/netport + test/bacnet/basic/object/objects + test/bacnet/basic/object/osv + test/bacnet/basic/object/piv + test/bacnet/basic/object/schedule # basic/sys + test/bacnet/basic/sys/days test/bacnet/basic/sys/fifo test/bacnet/basic/sys/filename test/bacnet/basic/sys/key @@ -529,7 +532,7 @@ list(APPEND testdirs list(APPEND testdirs test/bacnet/datalink/cobs test/bacnet/datalink/crc - #test/bacnet/datalink/bvlc #All tests skipped, needing development + test/bacnet/datalink/bvlc ) enable_testing() diff --git a/Makefile b/Makefile index 8310ce7c..eb075cff 100644 --- a/Makefile +++ b/Makefile @@ -206,6 +206,7 @@ clean: $(MAKE) -s -C apps/router-mstp clean $(MAKE) -s -C apps/gateway clean $(MAKE) -s -C test clean + rm -rf ./build .PHONY: test test: diff --git a/README.md b/README.md index 782ac56f..76af59d1 100644 --- a/README.md +++ b/README.md @@ -112,6 +112,15 @@ to generate a Code::Blocks project: c:\> cd build/ c:\> cmake .. -G"CodeBlocks - MinGW Makefiles" + +The the available tests may be run with the command sequence: + + $ make clean + $ make cmake + $ cd build + $ CTEST_OUTPUT_ON_FAILURE=1 make test + $ cd .. + The demo applications are all client applications that provide one main BACnet service, except the one server application and one gateway application, a couple router applications, and a couple of MS/TP specific applications. diff --git a/ports/zephyr/bip-init.c b/ports/zephyr/bip-init.c index 46b35ff7..1c7e8aec 100644 --- a/ports/zephyr/bip-init.c +++ b/ports/zephyr/bip-init.c @@ -82,17 +82,12 @@ static char ipv4_addr_str[]=""; */ char* inet_ntoa(struct in_addr *a) { - #if CONFIG_BACNETSTACK_LOG_LEVEL + if (IS_ENABLED(CONFIG_BACNETSTACK_LOG_LEVEL)) { - /* Avoid overwhelming the logging system */ - while(log_buffered_cnt()) - { - k_sleep(K_MSEC(1)); + snprintf(ipv4_addr_str, sizeof(ipv4_addr_str), "%d.%d.%d.%d", + a->s4_addr[0],a->s4_addr[1],a->s4_addr[2],a->s4_addr[3]); } - snprintf(ipv4_addr_str, sizeof(ipv4_addr_str), "%d.%d.%d.%d", - a->s4_addr[0],a->s4_addr[1],a->s4_addr[2],a->s4_addr[3]); - #endif return &ipv4_addr_str[0]; } diff --git a/src/bacnet/bacapp.c b/src/bacnet/bacapp.c index ee881591..76f8141b 100644 --- a/src/bacnet/bacapp.c +++ b/src/bacnet/bacapp.c @@ -437,7 +437,10 @@ int bacapp_decode_data_len( case BACNET_APPLICATION_TAG_DATE: case BACNET_APPLICATION_TAG_TIME: case BACNET_APPLICATION_TAG_OBJECT_ID: - len = (int)len_value_type; + len = (int) (~0U >> 1); + if ( len_value_type < (uint32_t) len) { + len = (int)len_value_type; + } break; default: break; @@ -835,9 +838,10 @@ int bacapp_encode_data(uint8_t *apdu, BACNET_APPLICATION_DATA_VALUE *value) bool bacapp_copy(BACNET_APPLICATION_DATA_VALUE *dest_value, BACNET_APPLICATION_DATA_VALUE *src_value) { - bool status = true; /*return value */ + bool status = false; /* return value, assume failure */ if (dest_value && src_value) { + status = true; /* assume successful for now */ dest_value->tag = src_value->tag; switch (src_value->tag) { #if defined(BACAPP_NULL) @@ -1686,13 +1690,6 @@ void bacapp_property_value_list_init(BACNET_PROPERTY_VALUE *value, size_t count) } } -#ifdef BAC_TEST -#include -#include -#include "ctest.h" - -#include - /* generic - can be used by other unit tests returns true if matching or same, false if different */ bool bacapp_same_value(BACNET_APPLICATION_DATA_VALUE *value, @@ -1701,6 +1698,9 @@ bool bacapp_same_value(BACNET_APPLICATION_DATA_VALUE *value, bool status = false; /*return value */ /* does the tag match? */ + if ((value == NULL) || (test_value == NULL)) { + return false; + } if (test_value->tag == value->tag) status = true; if (status) { @@ -1805,7 +1805,14 @@ bool bacapp_same_value(BACNET_APPLICATION_DATA_VALUE *value, return status; } -void testBACnetApplicationData_Safe(Test *pTest) +#ifdef TEST_BACNET_APPLICATION_DATA +#include +#include +#include "ctest.h" + +#include + +static void testBACnetApplicationData_Safe(Test *pTest) { int i; uint8_t apdu[MAX_APDU]; @@ -2292,7 +2299,6 @@ void testBACnetApplicationData(Test *pTest) return; } -#ifdef TEST_BACNET_APPLICATION_DATA int main(void) { Test *pTest; @@ -2315,4 +2321,3 @@ int main(void) return 0; } #endif /* TEST_BACNET_APPLICATION_DATA */ -#endif /* BAC_TEST */ diff --git a/src/bacnet/bacapp.h b/src/bacnet/bacapp.h index 68e69ba5..86f3330c 100644 --- a/src/bacnet/bacapp.h +++ b/src/bacnet/bacapp.h @@ -256,22 +256,11 @@ extern "C" { #define bacapp_print_value(x,y) false #endif -#ifdef BAC_TEST -#include "ctest.h" -#include "bacnet/datetime.h" BACNET_STACK_EXPORT bool bacapp_same_value( BACNET_APPLICATION_DATA_VALUE * value, BACNET_APPLICATION_DATA_VALUE * test_value); - BACNET_STACK_EXPORT - void testBACnetApplicationDataLength( - Test * pTest); - BACNET_STACK_EXPORT - void testBACnetApplicationData( - Test * pTest); -#endif - #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/bacnet/basic/object/lc.c b/src/bacnet/basic/object/lc.c index a420b34b..7e005496 100644 --- a/src/bacnet/basic/object/lc.c +++ b/src/bacnet/basic/object/lc.c @@ -40,6 +40,16 @@ #include "bacnet/wp.h" #include "bacnet/basic/services.h" +#ifndef LOAD_CONTROL_DEBUG +#define LOAD_CONTROL_DEBUG 0 +#endif +#if LOAD_CONTROL_DEBUG +#include +#define PRINTF(...) printk(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + /* number of demo objects */ #ifndef MAX_LOAD_CONTROLS #define MAX_LOAD_CONTROLS 4 @@ -212,7 +222,10 @@ unsigned Load_Control_Count(void) /* that correlates to the correct index */ uint32_t Load_Control_Index_To_Instance(unsigned index) { - return index; + if (index < MAX_LOAD_CONTROLS) { + return index; + } + return MAX_LOAD_CONTROLS; } /* we simply have 0-n object instances. Yours might be */ @@ -857,11 +870,25 @@ bool Load_Control_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) BACNET_DATE TempDate; /* build here in case of error in time half of datetime */ + PRINTF("Load_Control_Write_Property(wp_data=%p)\n", wp_data); + if (wp_data == NULL) { + PRINTF("Load_Control_Write_Property() failure detected point A\n"); + return false; + } + if (wp_data->application_data_len < 0) { + PRINTF("Load_Control_Write_Property() failure detected point A.2\n"); + /* error while decoding - a smaller larger than we can handle */ + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; + return false; + } + /* decode the some of the request */ len = bacapp_decode_application_data( wp_data->application_data, wp_data->application_data_len, &value); /* FIXME: len < application_data_len: more data? */ if (len < 0) { + PRINTF("Load_Control_Write_Property() failure detected point B\n"); /* error while decoding - a value larger than we can handle */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; @@ -870,6 +897,7 @@ bool Load_Control_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) /* only array properties can have array options */ if ((wp_data->object_property != PROP_SHED_LEVELS) && (wp_data->array_index != BACNET_ARRAY_ALL)) { + PRINTF("Load_Control_Write_Property() failure detected point C\n"); wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; return false; @@ -881,6 +909,7 @@ bool Load_Control_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) wp_data->application_data_len, &value, PROP_REQUESTED_SHED_LEVEL); if (len == BACNET_STATUS_ERROR) { + PRINTF("Load_Control_Write_Property() failure detected point D\n"); /* error! */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; @@ -906,6 +935,7 @@ bool Load_Control_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) value.type.Real; status = true; } else { + PRINTF("Load_Control_Write_Property() failure detected point E\n"); /* error! */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; @@ -919,6 +949,7 @@ bool Load_Control_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) status = write_property_type_valid(wp_data, &value, BACNET_APPLICATION_TAG_DATE); if (!status) { + PRINTF("Load_Control_Write_Property() failure detected point F\n"); /* don't continue if we don't have a valid date */ break; } @@ -937,6 +968,7 @@ bool Load_Control_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) Start_Time_Property_Written[object_index] = true; } } else { + PRINTF("Load_Control_Write_Property() failure detected point G\n"); status = false; wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; @@ -949,6 +981,8 @@ bool Load_Control_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) if (status) { Shed_Duration[object_index] = value.type.Unsigned_Int; Load_Control_Request_Written[object_index] = true; + } else { + PRINTF("Load_Control_Write_Property() failure detected point H\n"); } break; @@ -993,11 +1027,13 @@ bool Load_Control_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) } break; default: + PRINTF("Load_Control_Write_Property() failure detected point Z\n"); wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; break; } + PRINTF("Load_Control_Write_Property() returning status=%d\n", status); return status; } diff --git a/src/bacnet/basic/object/objects.c b/src/bacnet/basic/object/objects.c index a755302c..3f2263ba 100644 --- a/src/bacnet/basic/object/objects.c +++ b/src/bacnet/basic/object/objects.c @@ -32,6 +32,7 @@ ------------------------------------------- ####COPYRIGHTEND####*/ +#include #include #include #include @@ -100,8 +101,9 @@ OBJECT_DEVICE_T *objects_device_new(uint32_t device_instance) return pDevice; } -OBJECT_DEVICE_T *objects_device_delete(int index) +bool objects_device_delete(int index) { + bool result = false; OBJECT_DEVICE_T *pDevice = NULL; BACNET_OBJECT_ID *pObject; @@ -121,7 +123,8 @@ OBJECT_DEVICE_T *objects_device_delete(int index) Keylist_Delete(pDevice->Object_List); } free(pDevice); + result = true; } } - return pDevice; + return result; } diff --git a/src/bacnet/basic/object/objects.h b/src/bacnet/basic/object/objects.h index 01d763a8..0a079399 100644 --- a/src/bacnet/basic/object/objects.h +++ b/src/bacnet/basic/object/objects.h @@ -61,7 +61,7 @@ extern "C" { #endif /* __cplusplus */ BACNET_STACK_EXPORT - OBJECT_DEVICE_T *objects_device_delete(int index); + bool objects_device_delete(int index); BACNET_STACK_EXPORT OBJECT_DEVICE_T *objects_device_new(uint32_t device_instance); diff --git a/src/bacnet/basic/sys/days.c b/src/bacnet/basic/sys/days.c new file mode 100644 index 00000000..12a2496b --- /dev/null +++ b/src/bacnet/basic/sys/days.c @@ -0,0 +1,296 @@ +/** + * @file + * @author Steve Karg + * @date 1997 + * @brief computes days from date, days of the week, days in a month, + * days in a year + * + * @section LICENSE + * + * Public domain algorithms from ACM + * + */ +#include +#include +#include "bacnet/basic/sys/days.h" + +/** + * Determines if a year is a leap year using Gregorian algorithm + * + * @param year - years after Christ birth (0..9999 AD) + * @return true if leap year + */ +bool days_is_leap_year(uint16_t year) +{ + if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0)) + return true; + + return (false); +} + +/** + * Determines the number of days in given month and year + * + * @param year - years after Christ birth (0..9999 AD) + * @param month - months (1=Jan...12=Dec) + * @return number of days in a given month and year, or 0 on error + */ +uint8_t days_per_month(uint16_t year, uint8_t month) +{ + /* note: start with a zero in the first element to save us from a + month - 1 calculation in the lookup */ + uint8_t month_days[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, + 31 }; + + if ((month == 2) && days_is_leap_year(year)) + return (29); + else if (month >= 1 && month <= 12) + return (month_days[month]); + + return 0; +} + +/** + * Determines the number of days in given year + * + * @param year - years after Christ birth (0..9999 AD) + * @return number of days in a given year + */ +uint32_t days_per_year(uint16_t year) +{ + uint32_t days = 365; + + if (days_is_leap_year(year)) { + days++; + } + + return days; +} + +/** + * Determines the number of days (1..365) for a given date + * + * @param year - years after Christ birth (0..9999 AD) + * @param month - months (1=Jan...12=Dec) + * @param day - day of month (1-31) + * @param days - number of days of the year (1..365) + */ +uint16_t days_of_year(uint16_t year, uint8_t month, uint8_t day) +{ + uint16_t days = 0; /* return value */ + uint8_t mm = 0; /* months counter */ + + for (mm = 1; mm < month; mm++) { + days += days_per_month(year, mm); + } + days += day; + + return days; +} + +/** + * Determines the number of days remaining in the year for a given date + * + * @param year - years after Christ birth (0..9999 AD) + * @param month - months (1=Jan...12=Dec) + * @param day - day of month (1-31) + * @param days - number of days of the year (1..365) + */ +uint16_t days_of_year_remaining(uint16_t year, uint8_t month, uint8_t day) +{ + uint16_t days = 0; /* return value */ + uint8_t mm = 0; /* months counter */ + + days = days_per_month(year, month) - day; + for (mm = 12; mm > month; mm--) { + days += days_per_month(year, mm); + } + + return days; +} + +/** + * Converts days of year into date (year, month, day) + * + * @param days - number of days of the year (1..365) + * @param year - years after Christ birth (0..9999 AD) + * @param pMonth - months (1=Jan...12=Dec) + * @param pDay - day of month (1-31) + */ +void days_of_year_to_month_day( + uint32_t days, uint16_t year, uint8_t *pMonth, uint8_t *pDay) +{ + uint8_t month = 1; + uint8_t day = 0; + + while (days > (uint32_t)days_per_month(year, month)) { + days -= days_per_month(year, month); + month++; + } + day = (uint8_t)(day + days); + + if (pMonth) { + *pMonth = month; + } + if (pDay) { + *pDay = day; + } + + return; +} + +/** + * Counts days apart between two dates + * + * @param year1 - years after Christ birth (0..9999 AD) + * @param month1 - months (1=Jan...12=Dec) + * @param day1 - day of month (1-31) + * @return number of days apart, or 0 if same dates + */ +uint32_t days_apart(uint16_t year1, + uint8_t month1, + uint8_t day1, + uint16_t year2, + uint8_t month2, + uint8_t day2) +{ + uint32_t days = 0; /* return value */ + uint32_t days1 = 0; + uint32_t days2 = 0; + uint16_t yy = 0; /* year */ + + if (year2 > year1) { + days = days_of_year_remaining(year1, month1, day1); + for (yy = year1 + 1; yy < year2; yy++) { + days += 365; + if (days_is_leap_year(yy)) { + days++; + } + } + days += days_of_year(year2, month2, day2); + } else if (year2 < year1) { + days = days_of_year_remaining(year2, month2, day2); + for (yy = year2 + 1; yy < year1; yy++) { + days += 365; + if (days_is_leap_year(yy)) { + days++; + } + } + days += days_of_year(year1, month1, day1); + } else { + days1 = days_of_year(year1, month1, day1); + days2 = days_of_year(year2, month2, day2); + if (days2 > days1) { + days = days2 - days1; + } else { + days = days1 - days2; + } + } + + return days; +} + +/** + * Converts date to days since epoch (Jan 0, epoch year) + * + * @param year - years after Christ birth (0..9999 AD) + * @param month - months (1=Jan...12=Dec) + * @param day - day of month (1-31) + * @return number of days since epoch, or 0 if out of range + */ +uint32_t days_since_epoch(uint16_t epoch_year, + uint16_t year, + uint8_t month, + uint8_t day) +{ + uint32_t days = 0; /* return value */ + uint16_t yy = 0; /* year */ + uint8_t mm = 0; /* months counter */ + uint8_t monthdays = 0; /* days in a month */ + + /* validate the date conforms to our range */ + monthdays = days_per_month(year, month); + if ((year >= epoch_year) && (year <= 9999) && + (monthdays > 0) && (day >= 1) && (day <= monthdays)) { + for (yy = epoch_year; yy < year; yy++) { + days += 365; + if (days_is_leap_year(yy)) { + days++; + } + } + for (mm = 1; mm < month; mm++) { + days += days_per_month(year, mm); + } + days += day; + } + + return (days); +} + +/** + * Converts epoch days into date (year, month, day) + * + * @param days - number of days since epoch + * @param pYear - years after Christ birth (2000..9999 AD) + * @param pMonth - months (1=Jan...12=Dec) + * @param pDay - day of month (1-31) + * @return nothing + */ +void days_since_epoch_to_date( + uint16_t epoch_year, + uint32_t days, + uint16_t * pYear, + uint8_t * pMonth, + uint8_t * pDay) +{ + uint8_t month = 1; + uint8_t day = 0; + uint16_t year; + + year = epoch_year; + while (days > days_per_year(year)) { + days -= days_per_year(year); + year++; + } + while (days > days_per_month(year, month)) { + days -= days_per_month(year, month); + month++; + } + day += days; + /* load values into the pointers */ + if (pYear) { + *pYear = year; + } + if (pMonth) { + *pMonth = month; + } + if (pDay) { + *pDay = day; + } + + return; +} + +/** + * Determines if a given date is valid + * + * @param year - years after Christ birth (0..9999 AD) + * @param month - months (1=Jan...12=Dec) + * @param day - day of month (1-31) + * @return true if the date is valid + */ +bool days_date_is_valid(uint16_t year, + uint8_t month, + uint8_t day) +{ + uint8_t month_days = 0; + bool valid = false; /* return value */ + + /* get the number of days in the month, and check for valid month too */ + month_days = days_per_month(year, month); + if ((month_days > 0) && (day > 0) && (day <= month_days)) { + valid = true; + } + + return (valid); +} diff --git a/src/bacnet/basic/sys/days.h b/src/bacnet/basic/sys/days.h new file mode 100644 index 00000000..6782642b --- /dev/null +++ b/src/bacnet/basic/sys/days.h @@ -0,0 +1,58 @@ +/** + * @file + * @author Steve Karg + * @date 1997 + * @brief This file contains the function prototypes for the days calculations + */ +#ifndef DAYS_H +#define DAYS_H +#include +#include +#include "bacnet/bacnet_stack_exports.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +BACNET_STACK_EXPORT +bool days_is_leap_year(uint16_t year); +BACNET_STACK_EXPORT +uint8_t days_per_month(uint16_t year, uint8_t month); +BACNET_STACK_EXPORT +uint32_t days_per_year(uint16_t year); +BACNET_STACK_EXPORT +uint16_t days_of_year(uint16_t year, uint8_t month, uint8_t day); +BACNET_STACK_EXPORT +uint16_t days_of_year_remaining(uint16_t year, uint8_t month, uint8_t day); +BACNET_STACK_EXPORT +void days_of_year_to_month_day( + uint32_t days, uint16_t year, uint8_t *pMonth, uint8_t *pDay); +BACNET_STACK_EXPORT +uint32_t days_apart(uint16_t year1, + uint8_t month1, + uint8_t day1, + uint16_t year2, + uint8_t month2, + uint8_t day2); +BACNET_STACK_EXPORT +uint32_t days_since_epoch(uint16_t epoch_year, + uint16_t year, + uint8_t month, + uint8_t day); +BACNET_STACK_EXPORT +void days_since_epoch_to_date( + uint16_t epoch_year, + uint32_t days, + uint16_t * pYear, + uint8_t * pMonth, + uint8_t * pDay); + +BACNET_STACK_EXPORT +bool days_date_is_valid(uint16_t year, + uint8_t month, + uint8_t day); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif diff --git a/src/bacnet/datalink/bvlc.c b/src/bacnet/datalink/bvlc.c index 792d5d5d..128e971d 100644 --- a/src/bacnet/datalink/bvlc.c +++ b/src/bacnet/datalink/bvlc.c @@ -2140,7 +2140,7 @@ bool bvlc_address_get(BACNET_IP_ADDRESS *addr, */ bool bvlc_address_from_ascii(BACNET_IP_ADDRESS *addr, const char *addrstr) { - unsigned char tmp = 0; + uint16_t tmp = 0; char c = 0; unsigned char i = 0, j = 0; uint8_t charsread = 0; @@ -2151,6 +2151,7 @@ bool bvlc_address_from_ascii(BACNET_IP_ADDRESS *addr, const char *addrstr) if (!addrstr) { return false; } + for (i = 0; i < 4; ++i) { j = 0; do { @@ -2160,10 +2161,13 @@ bool bvlc_address_from_ascii(BACNET_IP_ADDRESS *addr, const char *addrstr) return false; } if ((c == '.') || (c == 0) || (c == ' ')) { - addr->address[i] = tmp; + addr->address[i] = (uint8_t) tmp; tmp = 0; } else if ((c >= '0') && (c <= '9')) { tmp = (tmp * 10) + (c - '0'); + if (tmp > UINT8_MAX) { + return false; + } } else { return false; } diff --git a/src/bacnet/datetime.c b/src/bacnet/datetime.c index 5f97330b..f8cea54b 100644 --- a/src/bacnet/datetime.c +++ b/src/bacnet/datetime.c @@ -37,18 +37,14 @@ #include #include #include +#include "bacnet/basic/sys/days.h" #include "bacnet/datetime.h" #include "bacnet/bacdcode.h" /** @file datetime.c Manipulate BACnet Date and Time values */ -/* define our epic beginnings */ -#define BACNET_EPOCH_YEAR 1900 -/* 1/1/1900 is a Monday */ -#define BACNET_EPOCH_DOW BACNET_WEEKDAY_MONDAY - /* BACnet Date */ -/* year = years since 1900 */ +/* year = years since 1900 through 2155 */ /* month 1=Jan */ /* day = day of month 1..31 */ /* wday 1=Monday...7=Sunday */ @@ -60,40 +56,21 @@ time or date may be interpreted as "any" or "don't care" */ -bool datetime_is_leap_year(uint16_t year) -{ - if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0)) { - return (true); - } else { - return (false); - } -} - -uint8_t datetime_month_days(uint16_t year, uint8_t month) -{ - /* note: start with a zero in the first element to save us from a - month - 1 calculation in the lookup */ - int month_days[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - /* return value */ - uint8_t days = 0; - - /* February */ - if ((month == 2) && datetime_is_leap_year(year)) { - days = 29; - } else if (month >= 1 && month <= 12) { - days = (uint8_t)month_days[month]; - } - - return days; -} - +/** + * Determines if a given date is valid + * + * @param year - years after Christ birth (1900..2155 AD) + * @param month - months (1=Jan...12=Dec) + * @param day - day of month (1-31) + * @return true if the date is valid + */ bool datetime_ymd_is_valid(uint16_t year, uint8_t month, uint8_t day) { bool status = false; /* true if value date */ uint8_t monthdays = 0; /* days in a month */ - monthdays = datetime_month_days(year, month); - if ((year >= BACNET_EPOCH_YEAR) && (monthdays > 0) && (day >= 1) && + monthdays = days_per_month(year, month); + if ((year >= BACNET_DATE_YEAR_EPOCH) && (monthdays > 0) && (day >= 1) && (day <= monthdays)) { status = true; } @@ -101,6 +78,12 @@ bool datetime_ymd_is_valid(uint16_t year, uint8_t month, uint8_t day) return status; } +/** + * Determines if a given date is valid + * + * @param bdate - BACnet date structure + * @return true if the date is valid + */ bool datetime_date_is_valid(BACNET_DATE *bdate) { bool status = false; /* true if value date */ @@ -112,14 +95,22 @@ bool datetime_date_is_valid(BACNET_DATE *bdate) return status; } -static uint32_t day_of_year(uint16_t year, uint8_t month, uint8_t day) +/** + * Converts date to day of the year + * + * @param year - years after Christ birth (1900..2155 AD) + * @param month - months (1=Jan...12=Dec) + * @param day - day of month (1-31) + * @return number of days since Jan 1 (inclusive) of the given year + */ +uint32_t datetime_ymd_day_of_year(uint16_t year, uint8_t month, uint8_t day) { uint32_t days = 0; /* return value */ uint8_t months = 0; /* loop counter for months */ if (datetime_ymd_is_valid(year, month, day)) { for (months = 1; months < month; months++) { - days += datetime_month_days(year, months); + days += days_per_month(year, months); } days += day; } @@ -127,63 +118,62 @@ static uint32_t day_of_year(uint16_t year, uint8_t month, uint8_t day) return (days); } -static void day_of_year_into_md( - uint32_t days, uint16_t year, uint8_t *pMonth, uint8_t *pDay) -{ - uint8_t month = 1; - uint8_t day = 0; - - while (days > (uint32_t)datetime_month_days(year, month)) { - days -= datetime_month_days(year, month); - month++; - } - - day = (uint8_t)(day + days); - - if (pMonth) { - *pMonth = month; - } - if (pDay) { - *pDay = day; - } - - return; -} - +/** + * Converts date to day of the year + * + * @param days - number of days since Jan 1 (inclusive) of the given year + * @param year - years after Christ birth (1900..2155 AD) + * @param bdate - BACnet date structure + */ void datetime_day_of_year_into_date( uint32_t days, uint16_t year, BACNET_DATE *bdate) { uint8_t month = 0; uint8_t day = 0; - day_of_year_into_md(days, year, &month, &day); + days_of_year_to_month_day(days, year, &month, &day); datetime_set_date(bdate, year, month, day); } +/** + * Converts date to day of the year + * + * @param bdate - BACnet date structure + * @return number of days since Jan 1 (inclusive) of the given year + */ uint32_t datetime_day_of_year(BACNET_DATE *bdate) { uint32_t days = 0; if (bdate) { - days = day_of_year(bdate->year, bdate->month, bdate->day); + days = datetime_ymd_day_of_year(bdate->year, bdate->month, bdate->day); } return days; } -static uint32_t days_since_epoch(uint16_t year, uint8_t month, uint8_t day) +/** + * Converts days since BACnet epoch + * + * @param year - years after Christ birth (1900..2155 AD) + * @param month - months (1=Jan...12=Dec) + * @param day - day of month (1-31) + * @return number of days since epoch, or 0 if out of range + */ +uint32_t datetime_ymd_to_days_since_epoch( + uint16_t year, uint8_t month, uint8_t day) { uint32_t days = 0; /* return value */ uint16_t years = 0; /* loop counter for years */ if (datetime_ymd_is_valid(year, month, day)) { - for (years = BACNET_EPOCH_YEAR; years < year; years++) { + for (years = BACNET_DATE_YEAR_EPOCH; years < year; years++) { days += 365; - if (datetime_is_leap_year(years)) { + if (days_is_leap_year(years)) { days++; } } - days += day_of_year(year, month, day); + days += datetime_ymd_day_of_year(year, month, day); /* 'days since' is one less */ days -= 1; } @@ -191,37 +181,52 @@ static uint32_t days_since_epoch(uint16_t year, uint8_t month, uint8_t day) return (days); } +/** + * Converts date to days since BACnet epoch + * + * @param bdate - BACnet date structure + * @return number of days since epoch, or 0 if out of range + */ uint32_t datetime_days_since_epoch(BACNET_DATE *bdate) { uint32_t days = 0; if (bdate) { - days = days_since_epoch(bdate->year, bdate->month, bdate->day); + days = datetime_ymd_to_days_since_epoch( + bdate->year, bdate->month, bdate->day); } return days; } -static void days_since_epoch_into_ymd( +/** + * Converts days since BACnet epoch to YMD date + * + * @param days - number of days since epoch, or 0 if out of range + * @param pYear - [out] years after Christ birth (1900..2155 AD) + * @param pMonth - [out] months (1=Jan...12=Dec) + * @param pDay - [out] day of month (1-31) + */ +void datetime_ymd_from_days_since_epoch( uint32_t days, uint16_t *pYear, uint8_t *pMonth, uint8_t *pDay) { - uint16_t year = BACNET_EPOCH_YEAR; + uint16_t year = BACNET_DATE_YEAR_EPOCH; uint8_t month = 1; uint8_t day = 1; while (days >= 365) { - if ((datetime_is_leap_year(year)) && (days == 365)) { + if ((days_is_leap_year(year)) && (days == 365)) { break; } days -= 365; - if (datetime_is_leap_year(year)) { + if (days_is_leap_year(year)) { --days; } year++; } - while (days >= (uint32_t)datetime_month_days(year, month)) { - days -= datetime_month_days(year, month); + while (days >= (uint32_t)days_per_month(year, month)) { + days -= days_per_month(year, month); month++; } @@ -240,27 +245,45 @@ static void days_since_epoch_into_ymd( return; } +/** + * Converts days since BACnet epoch to date + * + * @param days - number of days since epoch, or 0 if out of range + * @param bdate - BACnet date structure + */ void datetime_days_since_epoch_into_date(uint32_t days, BACNET_DATE *bdate) { uint16_t year = 0; uint8_t month = 0; uint8_t day = 0; - days_since_epoch_into_ymd(days, &year, &month, &day); + datetime_ymd_from_days_since_epoch(days, &year, &month, &day); datetime_set_date(bdate, year, month, day); } -/* Jan 1, 1900 is a Monday */ -/* wday 1=Monday...7=Sunday */ +/** + * Determines the day of week based on BACnet epoch: Jan 1, 1900 was a Monday + * + * @param year - years after Christ birth (1900..2155 AD) + * @param month - months (1=Jan...12=Dec) + * @param day - day of month (1-31) + * @return BACnet day of week where 1=Monday...7=Sunday + */ uint8_t datetime_day_of_week(uint16_t year, uint8_t month, uint8_t day) { - uint8_t dow = (uint8_t)BACNET_EPOCH_DOW; + uint8_t dow = (uint8_t)BACNET_DAY_OF_WEEK_EPOCH; - dow += (days_since_epoch(year, month, day) % 7); + dow += (datetime_ymd_to_days_since_epoch(year, month, day) % 7); return dow; } +/** + * Determines if a given time is valid + * + * @param btime - pointer to a BACNET_TIME structure + * @return true if the time is valid + */ bool datetime_time_is_valid(BACNET_TIME *btime) { bool status = false; @@ -522,18 +545,18 @@ void datetime_set_values(BACNET_DATE_TIME *bdatetime, } } -static uint32_t seconds_since_midnight( +uint32_t datetime_hms_to_seconds_since_midnight( uint8_t hours, uint8_t minutes, uint8_t seconds) { return ((hours * 60 * 60) + (minutes * 60) + seconds); } -static uint16_t minutes_since_midnight(uint8_t hours, uint8_t minutes) +uint16_t datetime_hm_to_minutes_since_midnight(uint8_t hours, uint8_t minutes) { return ((hours * 60) + minutes); } -static void seconds_since_midnight_into_hms( +void datetime_hms_from_seconds_since_midnight( uint32_t seconds, uint8_t *pHours, uint8_t *pMinutes, uint8_t *pSeconds) { uint8_t hour = 0; @@ -564,7 +587,7 @@ void datetime_seconds_since_midnight_into_time( uint32_t seconds, BACNET_TIME *btime) { if (btime) { - seconds_since_midnight_into_hms( + datetime_hms_from_seconds_since_midnight( seconds, &btime->hour, &btime->min, &btime->sec); btime->hundredths = 0; } @@ -581,7 +604,8 @@ uint32_t datetime_seconds_since_midnight(BACNET_TIME *btime) uint32_t seconds = 0; if (btime) { - seconds = seconds_since_midnight(btime->hour, btime->min, btime->sec); + seconds = datetime_hms_to_seconds_since_midnight( + btime->hour, btime->min, btime->sec); } return seconds; @@ -598,7 +622,8 @@ uint16_t datetime_minutes_since_midnight(BACNET_TIME *btime) uint32_t minutes = 0; if (btime) { - minutes = minutes_since_midnight(btime->hour, btime->min); + minutes = + datetime_hm_to_minutes_since_midnight(btime->hour, btime->min); } return minutes; @@ -616,8 +641,9 @@ void datetime_add_minutes(BACNET_DATE_TIME *bdatetime, int32_t minutes) int32_t days = 0; /* convert bdatetime to seconds and days */ - bdatetime_minutes = seconds_since_midnight(bdatetime->time.hour, - bdatetime->time.min, bdatetime->time.sec) / + bdatetime_minutes = + datetime_hms_to_seconds_since_midnight( + bdatetime->time.hour, bdatetime->time.min, bdatetime->time.sec) / 60; bdatetime_days = datetime_days_since_epoch(&bdatetime->date); @@ -648,7 +674,7 @@ void datetime_add_minutes(BACNET_DATE_TIME *bdatetime, int32_t minutes) } /* convert bdatetime from seconds and days */ - seconds_since_midnight_into_hms(bdatetime_minutes * 60, + datetime_hms_from_seconds_since_midnight(bdatetime_minutes * 60, &bdatetime->time.hour, &bdatetime->time.min, NULL); datetime_days_since_epoch_into_date(bdatetime_days, &bdatetime->date); } @@ -666,7 +692,7 @@ uint64_t datetime_seconds_since_epoch(BACNET_DATE_TIME *bdatetime) if (bdatetime) { days = datetime_days_since_epoch(&bdatetime->date); - seconds = seconds_since_midnight(24, 0, 0); + seconds = datetime_hms_to_seconds_since_midnight(24, 0, 0); seconds *= days; seconds += datetime_seconds_since_midnight(&bdatetime->time); } @@ -688,7 +714,7 @@ void datetime_since_epoch_seconds(BACNET_DATE_TIME *bdatetime, uint64_t seconds) uint32_t day_seconds = 0; if (bdatetime) { - day_seconds = seconds_since_midnight(24, 0, 0); + day_seconds = datetime_hms_to_seconds_since_midnight(24, 0, 0); days = seconds / day_seconds; seconds_after_midnight = seconds - (days * day_seconds); datetime_seconds_since_midnight_into_time( @@ -704,7 +730,7 @@ bool datetime_wildcard_year(BACNET_DATE *bdate) bool wildcard_present = false; if (bdate) { - if (bdate->year == (BACNET_EPOCH_YEAR + 0xFF)) { + if (bdate->year == (BACNET_DATE_YEAR_EPOCH + 0xFF)) { wildcard_present = true; } } @@ -716,7 +742,7 @@ bool datetime_wildcard_year(BACNET_DATE *bdate) void datetime_wildcard_year_set(BACNET_DATE *bdate) { if (bdate) { - bdate->year = BACNET_EPOCH_YEAR + 0xFF; + bdate->year = BACNET_DATE_YEAR_EPOCH + 0xFF; } } @@ -919,7 +945,7 @@ bool datetime_wildcard_present(BACNET_DATE_TIME *bdatetime) void datetime_date_wildcard_set(BACNET_DATE *bdate) { if (bdate) { - bdate->year = BACNET_EPOCH_YEAR + 0xFF; + bdate->year = BACNET_DATE_YEAR_EPOCH + 0xFF; bdate->month = 0xFF; bdate->day = 0xFF; bdate->wday = 0xFF; @@ -1101,8 +1127,7 @@ bool datetime_date_init_ascii(BACNET_DATE *bdate, const char *ascii) int year, month, day, wday; int count = 0; - count = - sscanf(ascii, "%4d/%3d/%3d:%3d", &year, &month, &day, &wday); + count = sscanf(ascii, "%4d/%3d/%3d:%3d", &year, &month, &day, &wday); if (count == 3) { datetime_set_date(bdate, (uint16_t)year, (uint8_t)month, (uint8_t)day); status = true; @@ -1132,8 +1157,7 @@ bool datetime_time_init_ascii(BACNET_TIME *btime, const char *ascii) int hour, min, sec, hundredths; int count = 0; - count = sscanf( - ascii, "%3d:%3d:%3d.%3d", &hour, &min, &sec, &hundredths); + count = sscanf(ascii, "%3d:%3d:%3d.%3d", &hour, &min, &sec, &hundredths); if (count == 4) { btime->hour = (uint8_t)hour; btime->min = (uint8_t)min; @@ -1177,7 +1201,7 @@ static void testBACnetDateTimeWildcard(Test *pTest) BACNET_DATE_TIME bdatetime; bool status = false; - datetime_set_values(&bdatetime, BACNET_EPOCH_YEAR, 1, 1, 0, 0, 0, 0); + datetime_set_values(&bdatetime, BACNET_DATE_YEAR_EPOCH, 1, 1, 0, 0, 0, 0); status = datetime_wildcard(&bdatetime); ct_test(pTest, status == false); @@ -1192,27 +1216,30 @@ static void testBACnetDateTimeAdd(Test *pTest) uint32_t minutes = 0; int diff = 0; - datetime_set_values(&bdatetime, BACNET_EPOCH_YEAR, 1, 1, 0, 0, 0, 0); + datetime_set_values(&bdatetime, BACNET_DATE_YEAR_EPOCH, 1, 1, 0, 0, 0, 0); datetime_copy(&test_bdatetime, &bdatetime); datetime_add_minutes(&bdatetime, minutes); diff = datetime_compare(&test_bdatetime, &bdatetime); ct_test(pTest, diff == 0); - datetime_set_values(&bdatetime, BACNET_EPOCH_YEAR, 1, 1, 0, 0, 0, 0); + datetime_set_values(&bdatetime, BACNET_DATE_YEAR_EPOCH, 1, 1, 0, 0, 0, 0); datetime_add_minutes(&bdatetime, 60); - datetime_set_values(&test_bdatetime, BACNET_EPOCH_YEAR, 1, 1, 1, 0, 0, 0); + datetime_set_values( + &test_bdatetime, BACNET_DATE_YEAR_EPOCH, 1, 1, 1, 0, 0, 0); diff = datetime_compare(&test_bdatetime, &bdatetime); ct_test(pTest, diff == 0); - datetime_set_values(&bdatetime, BACNET_EPOCH_YEAR, 1, 1, 0, 0, 0, 0); + datetime_set_values(&bdatetime, BACNET_DATE_YEAR_EPOCH, 1, 1, 0, 0, 0, 0); datetime_add_minutes(&bdatetime, (24 * 60)); - datetime_set_values(&test_bdatetime, BACNET_EPOCH_YEAR, 1, 2, 0, 0, 0, 0); + datetime_set_values( + &test_bdatetime, BACNET_DATE_YEAR_EPOCH, 1, 2, 0, 0, 0, 0); diff = datetime_compare(&test_bdatetime, &bdatetime); ct_test(pTest, diff == 0); - datetime_set_values(&bdatetime, BACNET_EPOCH_YEAR, 1, 1, 0, 0, 0, 0); + datetime_set_values(&bdatetime, BACNET_DATE_YEAR_EPOCH, 1, 1, 0, 0, 0, 0); datetime_add_minutes(&bdatetime, (31 * 24 * 60)); - datetime_set_values(&test_bdatetime, BACNET_EPOCH_YEAR, 2, 1, 0, 0, 0, 0); + datetime_set_values( + &test_bdatetime, BACNET_DATE_YEAR_EPOCH, 2, 1, 0, 0, 0, 0); diff = datetime_compare(&test_bdatetime, &bdatetime); ct_test(pTest, diff == 0); @@ -1238,11 +1265,12 @@ static void testBACnetDateTimeSeconds(Test *pTest) for (hour = 0; hour < 24; hour++) { for (minute = 0; minute < 60; minute += 3) { for (second = 0; second < 60; second += 17) { - seconds = seconds_since_midnight(hour, minute, second); - seconds_since_midnight_into_hms( + seconds = datetime_hms_to_seconds_since_midnight( + hour, minute, second); + datetime_hms_from_seconds_since_midnight( seconds, &test_hour, &test_minute, &test_second); - test_seconds = - seconds_since_midnight(test_hour, test_minute, test_second); + test_seconds = datetime_hms_to_seconds_since_midnight( + test_hour, test_minute, test_second); ct_test(pTest, seconds == test_seconds); } } @@ -1254,14 +1282,14 @@ static void testBACnetDate(Test *pTest) BACNET_DATE bdate1, bdate2; int diff = 0; - datetime_set_date(&bdate1, BACNET_EPOCH_YEAR, 1, 1); + datetime_set_date(&bdate1, BACNET_DATE_YEAR_EPOCH, 1, 1); datetime_copy_date(&bdate2, &bdate1); diff = datetime_compare_date(&bdate1, &bdate2); ct_test(pTest, diff == 0); - datetime_set_date(&bdate2, BACNET_EPOCH_YEAR, 1, 2); + datetime_set_date(&bdate2, BACNET_DATE_YEAR_EPOCH, 1, 2); diff = datetime_compare_date(&bdate1, &bdate2); ct_test(pTest, diff < 0); - datetime_set_date(&bdate2, BACNET_EPOCH_YEAR, 2, 1); + datetime_set_date(&bdate2, BACNET_DATE_YEAR_EPOCH, 2, 1); diff = datetime_compare_date(&bdate1, &bdate2); ct_test(pTest, diff < 0); datetime_set_date(&bdate2, 1901, 1, 1); @@ -1297,7 +1325,7 @@ static void testBACnetDate(Test *pTest) datetime_set_date(&bdate2, 2006, 7, 15); diff = datetime_compare_date(&bdate1, &bdate2); ct_test(pTest, diff > 0); - datetime_set_date(&bdate2, BACNET_EPOCH_YEAR, 7, 15); + datetime_set_date(&bdate2, BACNET_DATE_YEAR_EPOCH, 7, 15); diff = datetime_compare_date(&bdate1, &bdate2); ct_test(pTest, diff > 0); datetime_set_date(&bdate2, 2008, 7, 15); @@ -1366,12 +1394,12 @@ static void testBACnetDateTime(Test *pTest) BACNET_TIME btime; int diff = 0; - datetime_set_values(&bdatetime1, BACNET_EPOCH_YEAR, 1, 1, 0, 0, 0, 0); + datetime_set_values(&bdatetime1, BACNET_DATE_YEAR_EPOCH, 1, 1, 0, 0, 0, 0); datetime_copy(&bdatetime2, &bdatetime1); diff = datetime_compare(&bdatetime1, &bdatetime2); ct_test(pTest, diff == 0); datetime_set_time(&btime, 0, 0, 0, 0); - datetime_set_date(&bdate, BACNET_EPOCH_YEAR, 1, 1); + datetime_set_date(&bdate, BACNET_DATE_YEAR_EPOCH, 1, 1); datetime_set(&bdatetime1, &bdate, &btime); diff = datetime_compare(&bdatetime1, &bdatetime2); ct_test(pTest, diff == 0); @@ -1456,17 +1484,17 @@ static void testDayOfYear(Test *pTest) BACNET_DATE bdate; BACNET_DATE test_bdate; - days = day_of_year(1900, 1, 1); + days = datetime_ymd_day_of_year(1900, 1, 1); ct_test(pTest, days == 1); - day_of_year_into_md(days, 1900, &month, &day); + days_of_year_to_month_day(days, 1900, &month, &day); ct_test(pTest, month == 1); ct_test(pTest, day == 1); for (year = 1900; year <= 2154; year++) { for (month = 1; month <= 12; month++) { - for (day = 1; day <= datetime_month_days(year, month); day++) { - days = day_of_year(year, month, day); - day_of_year_into_md(days, year, &test_month, &test_day); + for (day = 1; day <= days_per_month(year, month); day++) { + days = datetime_ymd_day_of_year(year, month, day); + days_of_year_to_month_day(days, year, &test_month, &test_day); ct_test(pTest, month == test_month); ct_test(pTest, day == test_day); } @@ -1474,7 +1502,7 @@ static void testDayOfYear(Test *pTest) } for (year = 1900; year <= 2154; year++) { for (month = 1; month <= 12; month++) { - for (day = 1; day <= datetime_month_days(year, month); day++) { + for (day = 1; day <= days_per_month(year, month); day++) { datetime_set_date(&bdate, year, month, day); days = datetime_day_of_year(&bdate); datetime_day_of_year_into_date(days, year, &test_bdate); @@ -1513,12 +1541,13 @@ static void testDateEpochConversionCompare(Test *pTest, static void testDateEpochConversion(Test *pTest) { /* min */ - testDateEpochConversionCompare(pTest, BACNET_EPOCH_YEAR, 1, 1, 0, 0, 0, 0); + testDateEpochConversionCompare( + pTest, BACNET_DATE_YEAR_EPOCH, 1, 1, 0, 0, 0, 0); /* middle */ testDateEpochConversionCompare(pTest, 2020, 6, 26, 12, 30, 30, 0); /* max */ testDateEpochConversionCompare( - pTest, BACNET_EPOCH_YEAR + 0xFF - 1, 12, 31, 23, 59, 59, 0); + pTest, BACNET_DATE_YEAR_EPOCH + 0xFF - 1, 12, 31, 23, 59, 59, 0); } static void testDateEpoch(Test *pTest) @@ -1528,18 +1557,19 @@ static void testDateEpoch(Test *pTest) uint8_t month = 0, test_month = 0; uint8_t day = 0, test_day = 0; - days = days_since_epoch(BACNET_EPOCH_YEAR, 1, 1); + days = datetime_ymd_to_days_since_epoch(BACNET_DATE_YEAR_EPOCH, 1, 1); ct_test(pTest, days == 0); - days_since_epoch_into_ymd(days, &year, &month, &day); - ct_test(pTest, year == BACNET_EPOCH_YEAR); + datetime_ymd_from_days_since_epoch(days, &year, &month, &day); + ct_test(pTest, year == BACNET_DATE_YEAR_EPOCH); ct_test(pTest, month == 1); ct_test(pTest, day == 1); - for (year = BACNET_EPOCH_YEAR; year < (BACNET_EPOCH_YEAR + 0xFF); year++) { + for (year = BACNET_DATE_YEAR_EPOCH; year < (BACNET_DATE_YEAR_EPOCH + 0xFF); + year++) { for (month = 1; month <= 12; month++) { - for (day = 1; day <= datetime_month_days(year, month); day++) { - days = days_since_epoch(year, month, day); - days_since_epoch_into_ymd( + for (day = 1; day <= days_per_month(year, month); day++) { + days = datetime_ymd_to_days_since_epoch(year, month, day); + datetime_ymd_from_days_since_epoch( days, &test_year, &test_month, &test_day); ct_test(pTest, year == test_year); ct_test(pTest, month == test_month); diff --git a/src/bacnet/datetime.h b/src/bacnet/datetime.h index 7d67ccc1..c3cadb30 100644 --- a/src/bacnet/datetime.h +++ b/src/bacnet/datetime.h @@ -1,26 +1,26 @@ /************************************************************************** -* -* Copyright (C) 2012 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. -*********************************************************************/ + * + * Copyright (C) 2012 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. + *********************************************************************/ #ifndef DATE_TIME_H #define DATE_TIME_H @@ -28,6 +28,11 @@ #include #include "bacnet/bacnet_stack_exports.h" +/* define our epic beginnings */ +#define BACNET_DATE_YEAR_EPOCH 1900 +/* 1/1/1900 is a Monday */ +#define BACNET_DAY_OF_WEEK_EPOCH BACNET_WEEKDAY_MONDAY + typedef enum BACnet_Weekday { BACNET_WEEKDAY_MONDAY = 1, BACNET_WEEKDAY_TUESDAY = 2, @@ -40,10 +45,10 @@ typedef enum BACnet_Weekday { /* date */ typedef struct BACnet_Date { - uint16_t year; /* AD */ - uint8_t month; /* 1=Jan */ - uint8_t day; /* 1..31 */ - uint8_t wday; /* 1=Monday-7=Sunday */ + uint16_t year; /* AD */ + uint8_t month; /* 1=Jan */ + uint8_t day; /* 1..31 */ + uint8_t wday; /* 1=Monday-7=Sunday */ } BACNET_DATE; /* time */ @@ -67,284 +72,215 @@ typedef struct BACnet_Date_Range { /* week and days */ typedef struct BACnet_Weeknday { - uint8_t month; /* 1=Jan 13=odd 14=even FF=any */ - uint8_t weekofmonth; /* 1=days 1-7, 2=days 8-14, 3=days 15-21, 4=days 22-28, 5=days 29-31, 6=last 7 days, FF=any week */ - uint8_t dayofweek; /* 1=Monday-7=Sunday, FF=any */ + uint8_t month; /* 1=Jan 13=odd 14=even FF=any */ + uint8_t weekofmonth; /* 1=days 1-7, 2=days 8-14, 3=days 15-21, 4=days 22-28, + 5=days 29-31, 6=last 7 days, FF=any week */ + uint8_t dayofweek; /* 1=Monday-7=Sunday, FF=any */ } BACNET_WEEKNDAY; #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ - /* utility initialization functions */ - BACNET_STACK_EXPORT - void datetime_set_date( - BACNET_DATE * bdate, - uint16_t year, - uint8_t month, - uint8_t day); - BACNET_STACK_EXPORT - void datetime_set_time( - BACNET_TIME * btime, - uint8_t hour, - uint8_t minute, - uint8_t seconds, - uint8_t hundredths); - BACNET_STACK_EXPORT - void datetime_set( - BACNET_DATE_TIME * bdatetime, - BACNET_DATE * bdate, - BACNET_TIME * btime); - BACNET_STACK_EXPORT - void datetime_set_values( - BACNET_DATE_TIME * bdatetime, - uint16_t year, - uint8_t month, - uint8_t day, - uint8_t hour, - uint8_t minute, - uint8_t seconds, - uint8_t hundredths); - /* utility test for validity */ - BACNET_STACK_EXPORT - bool datetime_is_valid( - BACNET_DATE * bdate, - BACNET_TIME * btime); - BACNET_STACK_EXPORT - bool datetime_time_is_valid( - BACNET_TIME * btime); - BACNET_STACK_EXPORT - bool datetime_date_is_valid( - BACNET_DATE * bdate); - BACNET_STACK_EXPORT - /* date and time calculations and summaries */ - uint32_t datetime_days_since_epoch( - BACNET_DATE * bdate); - BACNET_STACK_EXPORT - void datetime_days_since_epoch_into_date( - uint32_t days, - BACNET_DATE * bdate); - BACNET_STACK_EXPORT - uint32_t datetime_day_of_year( - BACNET_DATE *bdate); - BACNET_STACK_EXPORT - void datetime_day_of_year_into_date( - uint32_t days, - uint16_t year, - BACNET_DATE *bdate); - BACNET_STACK_EXPORT - bool datetime_is_leap_year( - uint16_t year); - BACNET_STACK_EXPORT - uint8_t datetime_month_days( - uint16_t year, - uint8_t month); - BACNET_STACK_EXPORT - uint8_t datetime_day_of_week( - uint16_t year, - uint8_t month, - uint8_t day); - BACNET_STACK_EXPORT - bool datetime_ymd_is_valid( - uint16_t year, - uint8_t month, - uint8_t day); +/* utility initialization functions */ +BACNET_STACK_EXPORT +void datetime_set_date( + BACNET_DATE *bdate, uint16_t year, uint8_t month, uint8_t day); +BACNET_STACK_EXPORT +void datetime_set_time(BACNET_TIME *btime, + uint8_t hour, + uint8_t minute, + uint8_t seconds, + uint8_t hundredths); +BACNET_STACK_EXPORT +void datetime_set( + BACNET_DATE_TIME *bdatetime, BACNET_DATE *bdate, BACNET_TIME *btime); +BACNET_STACK_EXPORT +void datetime_set_values(BACNET_DATE_TIME *bdatetime, + uint16_t year, + uint8_t month, + uint8_t day, + uint8_t hour, + uint8_t minute, + uint8_t seconds, + uint8_t hundredths); +BACNET_STACK_EXPORT +uint32_t datetime_hms_to_seconds_since_midnight( + uint8_t hours, uint8_t minutes, uint8_t seconds); +BACNET_STACK_EXPORT +uint16_t datetime_hm_to_minutes_since_midnight(uint8_t hours, uint8_t minutes); +BACNET_STACK_EXPORT +void datetime_hms_from_seconds_since_midnight( + uint32_t seconds, uint8_t *pHours, uint8_t *pMinutes, uint8_t *pSeconds); +/* utility test for validity */ +BACNET_STACK_EXPORT +bool datetime_is_valid(BACNET_DATE *bdate, BACNET_TIME *btime); +BACNET_STACK_EXPORT +bool datetime_time_is_valid(BACNET_TIME *btime); +BACNET_STACK_EXPORT +bool datetime_date_is_valid(BACNET_DATE *bdate); +/* date and time calculations and summaries */ +BACNET_STACK_EXPORT +void datetime_ymd_from_days_since_epoch( + uint32_t days, uint16_t *pYear, uint8_t *pMonth, uint8_t *pDay); +BACNET_STACK_EXPORT +uint32_t datetime_days_since_epoch(BACNET_DATE *bdate); +BACNET_STACK_EXPORT +void datetime_days_since_epoch_into_date(uint32_t days, BACNET_DATE *bdate); +BACNET_STACK_EXPORT +uint32_t datetime_day_of_year(BACNET_DATE *bdate); +BACNET_STACK_EXPORT +uint32_t datetime_ymd_to_days_since_epoch( + uint16_t year, uint8_t month, uint8_t day); +BACNET_STACK_EXPORT +void datetime_day_of_year_into_date( + uint32_t days, uint16_t year, BACNET_DATE *bdate); +BACNET_STACK_EXPORT +bool datetime_is_leap_year(uint16_t year); +BACNET_STACK_EXPORT +uint8_t datetime_month_days(uint16_t year, uint8_t month); +BACNET_STACK_EXPORT +uint8_t datetime_day_of_week(uint16_t year, uint8_t month, uint8_t day); +BACNET_STACK_EXPORT +bool datetime_ymd_is_valid(uint16_t year, uint8_t month, uint8_t day); +BACNET_STACK_EXPORT +uint32_t datetime_ymd_day_of_year(uint16_t year, uint8_t month, uint8_t day); - BACNET_STACK_EXPORT - void datetime_seconds_since_midnight_into_time( - uint32_t seconds, - BACNET_TIME *btime); - BACNET_STACK_EXPORT - uint32_t datetime_seconds_since_midnight( - BACNET_TIME * btime); - BACNET_STACK_EXPORT - uint16_t datetime_minutes_since_midnight( - BACNET_TIME * btime); +BACNET_STACK_EXPORT +void datetime_seconds_since_midnight_into_time( + uint32_t seconds, BACNET_TIME *btime); +BACNET_STACK_EXPORT +uint32_t datetime_seconds_since_midnight(BACNET_TIME *btime); +BACNET_STACK_EXPORT +uint16_t datetime_minutes_since_midnight(BACNET_TIME *btime); - /* utility comparison functions: - if the date/times are the same, return is 0 - if date1 is before date2, returns negative - if date1 is after date2, returns positive */ - BACNET_STACK_EXPORT - int datetime_compare_date( - BACNET_DATE * date1, - BACNET_DATE * date2); - BACNET_STACK_EXPORT - int datetime_compare_time( - BACNET_TIME * time1, - BACNET_TIME * time2); - BACNET_STACK_EXPORT - int datetime_compare( - BACNET_DATE_TIME * datetime1, - BACNET_DATE_TIME * datetime2); +/* utility comparison functions: + if the date/times are the same, return is 0 + if date1 is before date2, returns negative + if date1 is after date2, returns positive */ +BACNET_STACK_EXPORT +int datetime_compare_date(BACNET_DATE *date1, BACNET_DATE *date2); +BACNET_STACK_EXPORT +int datetime_compare_time(BACNET_TIME *time1, BACNET_TIME *time2); +BACNET_STACK_EXPORT +int datetime_compare(BACNET_DATE_TIME *datetime1, BACNET_DATE_TIME *datetime2); - /* full comparison functions: - * taking into account FF fields in date and time structures, - * do a full comparison of two values */ - int datetime_wildcard_compare_date( - BACNET_DATE * date1, - BACNET_DATE * date2); - BACNET_STACK_EXPORT - int datetime_wildcard_compare_time( - BACNET_TIME * time1, - BACNET_TIME * time2); - BACNET_STACK_EXPORT - int datetime_wildcard_compare( - BACNET_DATE_TIME * datetime1, - BACNET_DATE_TIME * datetime2); +/* full comparison functions: + * taking into account FF fields in date and time structures, + * do a full comparison of two values */ +BACNET_STACK_EXPORT +int datetime_wildcard_compare_date(BACNET_DATE *date1, BACNET_DATE *date2); +BACNET_STACK_EXPORT +int datetime_wildcard_compare_time(BACNET_TIME *time1, BACNET_TIME *time2); +BACNET_STACK_EXPORT +int datetime_wildcard_compare( + BACNET_DATE_TIME *datetime1, BACNET_DATE_TIME *datetime2); - /* utility copy functions */ - BACNET_STACK_EXPORT - void datetime_copy_date( - BACNET_DATE * dest, - BACNET_DATE * src); - BACNET_STACK_EXPORT - void datetime_copy_time( - BACNET_TIME * dest, - BACNET_TIME * src); - BACNET_STACK_EXPORT - void datetime_copy( - BACNET_DATE_TIME * dest, - BACNET_DATE_TIME * src); +/* utility copy functions */ +BACNET_STACK_EXPORT +void datetime_copy_date(BACNET_DATE *dest, BACNET_DATE *src); +BACNET_STACK_EXPORT +void datetime_copy_time(BACNET_TIME *dest, BACNET_TIME *src); +BACNET_STACK_EXPORT +void datetime_copy(BACNET_DATE_TIME *dest, BACNET_DATE_TIME *src); - /* utility add or subtract minutes function */ - BACNET_STACK_EXPORT - void datetime_add_minutes( - BACNET_DATE_TIME * bdatetime, - int32_t minutes); +/* utility add or subtract minutes function */ +BACNET_STACK_EXPORT +void datetime_add_minutes(BACNET_DATE_TIME *bdatetime, int32_t minutes); - BACNET_STACK_EXPORT - uint64_t datetime_seconds_since_epoch( - BACNET_DATE_TIME * bdatetime); - BACNET_STACK_EXPORT - void datetime_since_epoch_seconds( - BACNET_DATE_TIME * bdatetime, - uint64_t seconds); +BACNET_STACK_EXPORT +uint64_t datetime_seconds_since_epoch(BACNET_DATE_TIME *bdatetime); +BACNET_STACK_EXPORT +void datetime_since_epoch_seconds( + BACNET_DATE_TIME *bdatetime, uint64_t seconds); - /* date and time wildcards */ - BACNET_STACK_EXPORT - bool datetime_wildcard_year( - BACNET_DATE *bdate); - BACNET_STACK_EXPORT - void datetime_wildcard_year_set( - BACNET_DATE *bdate); - BACNET_STACK_EXPORT - bool datetime_wildcard_month( - BACNET_DATE *bdate); - BACNET_STACK_EXPORT - void datetime_wildcard_month_set( - BACNET_DATE *bdate); - BACNET_STACK_EXPORT - bool datetime_wildcard_day( - BACNET_DATE *bdate); - BACNET_STACK_EXPORT - void datetime_wildcard_day_set( - BACNET_DATE *bdate); - BACNET_STACK_EXPORT - bool datetime_wildcard_weekday( - BACNET_DATE *bdate); - BACNET_STACK_EXPORT - void datetime_wildcard_weekday_set( - BACNET_DATE *bdate); - BACNET_STACK_EXPORT - bool datetime_wildcard_hour( - BACNET_TIME *btime); - BACNET_STACK_EXPORT - void datetime_wildcard_hour_set( - BACNET_TIME *btime); - BACNET_STACK_EXPORT - bool datetime_wildcard_minute( - BACNET_TIME *btime); - BACNET_STACK_EXPORT - void datetime_wildcard_minute_set( - BACNET_TIME *btime); - BACNET_STACK_EXPORT - bool datetime_wildcard_second( - BACNET_TIME *btime); - BACNET_STACK_EXPORT - void datetime_wildcard_second_set( - BACNET_TIME *btime); - BACNET_STACK_EXPORT - bool datetime_wildcard_hundredths( - BACNET_TIME *btime); - BACNET_STACK_EXPORT - void datetime_wildcard_hundredths_set( - BACNET_TIME *btime); - BACNET_STACK_EXPORT - bool datetime_wildcard( - BACNET_DATE_TIME * bdatetime); - BACNET_STACK_EXPORT - bool datetime_wildcard_present( - BACNET_DATE_TIME * bdatetime); - BACNET_STACK_EXPORT - void datetime_wildcard_set( - BACNET_DATE_TIME * bdatetime); - BACNET_STACK_EXPORT - void datetime_date_wildcard_set( - BACNET_DATE * bdate); - BACNET_STACK_EXPORT - void datetime_time_wildcard_set( - BACNET_TIME * btime); +/* date and time wildcards */ +BACNET_STACK_EXPORT +bool datetime_wildcard_year(BACNET_DATE *bdate); +BACNET_STACK_EXPORT +void datetime_wildcard_year_set(BACNET_DATE *bdate); +BACNET_STACK_EXPORT +bool datetime_wildcard_month(BACNET_DATE *bdate); +BACNET_STACK_EXPORT +void datetime_wildcard_month_set(BACNET_DATE *bdate); +BACNET_STACK_EXPORT +bool datetime_wildcard_day(BACNET_DATE *bdate); +BACNET_STACK_EXPORT +void datetime_wildcard_day_set(BACNET_DATE *bdate); +BACNET_STACK_EXPORT +bool datetime_wildcard_weekday(BACNET_DATE *bdate); +BACNET_STACK_EXPORT +void datetime_wildcard_weekday_set(BACNET_DATE *bdate); +BACNET_STACK_EXPORT +bool datetime_wildcard_hour(BACNET_TIME *btime); +BACNET_STACK_EXPORT +void datetime_wildcard_hour_set(BACNET_TIME *btime); +BACNET_STACK_EXPORT +bool datetime_wildcard_minute(BACNET_TIME *btime); +BACNET_STACK_EXPORT +void datetime_wildcard_minute_set(BACNET_TIME *btime); +BACNET_STACK_EXPORT +bool datetime_wildcard_second(BACNET_TIME *btime); +BACNET_STACK_EXPORT +void datetime_wildcard_second_set(BACNET_TIME *btime); +BACNET_STACK_EXPORT +bool datetime_wildcard_hundredths(BACNET_TIME *btime); +BACNET_STACK_EXPORT +void datetime_wildcard_hundredths_set(BACNET_TIME *btime); +BACNET_STACK_EXPORT +bool datetime_wildcard(BACNET_DATE_TIME *bdatetime); +BACNET_STACK_EXPORT +bool datetime_wildcard_present(BACNET_DATE_TIME *bdatetime); +BACNET_STACK_EXPORT +void datetime_wildcard_set(BACNET_DATE_TIME *bdatetime); +BACNET_STACK_EXPORT +void datetime_date_wildcard_set(BACNET_DATE *bdate); +BACNET_STACK_EXPORT +void datetime_time_wildcard_set(BACNET_TIME *btime); - BACNET_STACK_EXPORT - bool datetime_local_to_utc( - BACNET_DATE_TIME * utc_time, - BACNET_DATE_TIME * local_time, - int16_t utc_offset_minutes, - int8_t dst_adjust_minutes); - BACNET_STACK_EXPORT - bool datetime_utc_to_local( - BACNET_DATE_TIME * local_time, - BACNET_DATE_TIME * utc_time, - int16_t utc_offset_minutes, - int8_t dst_adjust_minutes); +BACNET_STACK_EXPORT +bool datetime_local_to_utc(BACNET_DATE_TIME *utc_time, + BACNET_DATE_TIME *local_time, + int16_t utc_offset_minutes, + int8_t dst_adjust_minutes); +BACNET_STACK_EXPORT +bool datetime_utc_to_local(BACNET_DATE_TIME *local_time, + BACNET_DATE_TIME *utc_time, + int16_t utc_offset_minutes, + int8_t dst_adjust_minutes); - BACNET_STACK_EXPORT - bool datetime_date_init_ascii( - BACNET_DATE *bdate, - const char *ascii); - BACNET_STACK_EXPORT - bool datetime_time_init_ascii( - BACNET_TIME *btime, - const char *ascii); +BACNET_STACK_EXPORT +bool datetime_date_init_ascii(BACNET_DATE *bdate, const char *ascii); +BACNET_STACK_EXPORT +bool datetime_time_init_ascii(BACNET_TIME *btime, const char *ascii); - BACNET_STACK_EXPORT - int bacapp_encode_datetime( - uint8_t * apdu, - BACNET_DATE_TIME * value); +BACNET_STACK_EXPORT +int bacapp_encode_datetime(uint8_t *apdu, BACNET_DATE_TIME *value); - BACNET_STACK_EXPORT - int bacapp_encode_context_datetime( - uint8_t * apdu, - uint8_t tag_number, - BACNET_DATE_TIME * value); +BACNET_STACK_EXPORT +int bacapp_encode_context_datetime( + uint8_t *apdu, uint8_t tag_number, BACNET_DATE_TIME *value); - BACNET_STACK_EXPORT - int bacapp_decode_datetime( - uint8_t * apdu, - BACNET_DATE_TIME * value); +BACNET_STACK_EXPORT +int bacapp_decode_datetime(uint8_t *apdu, BACNET_DATE_TIME *value); - BACNET_STACK_EXPORT - int bacapp_decode_context_datetime( - uint8_t * apdu, - uint8_t tag_number, - BACNET_DATE_TIME * value); +BACNET_STACK_EXPORT +int bacapp_decode_context_datetime( + uint8_t *apdu, uint8_t tag_number, BACNET_DATE_TIME *value); - /* implementation agnostic functions - create your own! */ - BACNET_STACK_EXPORT - bool datetime_local( - BACNET_DATE * bdate, - BACNET_TIME * btime, - int16_t * utc_offset_minutes, - bool * dst_active); - BACNET_STACK_EXPORT - void datetime_init(void); +/* implementation agnostic functions - create your own! */ +BACNET_STACK_EXPORT +bool datetime_local(BACNET_DATE *bdate, + BACNET_TIME *btime, + int16_t *utc_offset_minutes, + bool *dst_active); +BACNET_STACK_EXPORT +void datetime_init(void); #ifdef BAC_TEST #include "ctest.h" - BACNET_STACK_EXPORT - void testDateTime( - Test * pTest); +BACNET_STACK_EXPORT +void testDateTime(Test *pTest); #endif #ifdef __cplusplus diff --git a/src/bacnet/lighting.c b/src/bacnet/lighting.c index a18be707..9cc45dbc 100644 --- a/src/bacnet/lighting.c +++ b/src/bacnet/lighting.c @@ -293,12 +293,12 @@ bool lighting_command_same( return status; } -#ifdef BAC_TEST +#ifdef TEST_LIGHTING_COMMAND #include #include #include "ctest.h" -void testBACnetLightingCommand(Test *pTest, BACNET_LIGHTING_COMMAND *data) +static void testBACnetLightingCommand(Test *pTest, BACNET_LIGHTING_COMMAND *data) { bool status = false; BACNET_LIGHTING_COMMAND test_data; @@ -320,7 +320,7 @@ void testBACnetLightingCommand(Test *pTest, BACNET_LIGHTING_COMMAND *data) status = lighting_command_same(&test_data, data); } -void testBACnetLightingCommandAll(Test *pTest) +static void testBACnetLightingCommandAll(Test *pTest) { BACNET_LIGHTING_COMMAND data; @@ -345,7 +345,6 @@ void testBACnetLightingCommandAll(Test *pTest) testBACnetLightingCommand(pTest, &data); } -#ifdef TEST_LIGHTING_COMMAND int main(void) { Test *pTest; @@ -365,4 +364,3 @@ int main(void) } #endif -#endif /* BAC_TEST */ diff --git a/src/bacnet/timesync.c b/src/bacnet/timesync.c index 748f8e24..f6b56d69 100644 --- a/src/bacnet/timesync.c +++ b/src/bacnet/timesync.c @@ -295,7 +295,7 @@ int timesync_decode_timesync_recipients( return BACNET_STATUS_ABORT; } apdu_len += len; - } else if (decode_is_context_tag(&apdu[apdu_len], 1)) { + } else if (decode_is_opening_tag_number(&apdu[apdu_len], 1)) { apdu_len += 1; pRecipient->tag = 1; /* network-number Unsigned16 */ @@ -339,6 +339,10 @@ int timesync_decode_timesync_recipients( octetstring_copy_value(&pRecipient->type.address.mac[0], sizeof(pRecipient->type.address.mac), &octet_string); } + if (!decode_is_closing_tag_number(&apdu[apdu_len], 1)) { + return BACNET_STATUS_ABORT; + } + apdu_len += 1; } else { return BACNET_STATUS_ABORT; } diff --git a/test/address.mak b/test/address.mak index 15af4175..eb861cbf 100644 --- a/test/address.mak +++ b/test/address.mak @@ -18,6 +18,7 @@ SRCS = $(SRC_DIR)/bacnet/basic/binding/address.c \ $(SRC_DIR)/bacnet/lighting.c \ $(SRC_DIR)/bacnet/bactext.c \ $(SRC_DIR)/bacnet/indtext.c \ + $(SRC_DIR)/bacnet/basic/sys/days.c \ ctest.c OBJS = ${SRCS:.c=.o} diff --git a/test/bacapp.mak b/test/bacapp.mak index 4333112a..7e85e608 100644 --- a/test/bacapp.mak +++ b/test/bacapp.mak @@ -16,6 +16,7 @@ SRCS = $(SRC_DIR)/bacnet/bacdcode.c \ $(SRC_DIR)/bacnet/bactext.c \ $(SRC_DIR)/bacnet/lighting.c \ $(SRC_DIR)/bacnet/indtext.c \ + $(SRC_DIR)/bacnet/basic/sys/days.c \ ctest.c OBJS = ${SRCS:.c=.o} diff --git a/test/bacdevobjpropref.mak b/test/bacdevobjpropref.mak index 7e15eec6..594e339f 100644 --- a/test/bacdevobjpropref.mak +++ b/test/bacdevobjpropref.mak @@ -16,6 +16,7 @@ SRCS = $(SRC_DIR)/bacnet/bacdcode.c \ $(SRC_DIR)/bacnet/bactext.c \ $(SRC_DIR)/bacnet/lighting.c \ $(SRC_DIR)/bacnet/indtext.c \ + $(SRC_DIR)/bacnet/basic/sys/days.c \ ctest.c OBJS = ${SRCS:.c=.o} diff --git a/test/bacnet/alarm_ack/CMakeLists.txt b/test/bacnet/alarm_ack/CMakeLists.txt index a4d3d85e..b650c288 100644 --- a/test/bacnet/alarm_ack/CMakeLists.txt +++ b/test/bacnet/alarm_ack/CMakeLists.txt @@ -40,6 +40,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bacstr.c ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/timestamp.c # Test and test library files ./src/main.c diff --git a/test/bacnet/bacapp/CMakeLists.txt b/test/bacnet/bacapp/CMakeLists.txt index b69a1396..fcbecd22 100644 --- a/test/bacnet/bacapp/CMakeLists.txt +++ b/test/bacnet/bacapp/CMakeLists.txt @@ -43,6 +43,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bactext.c ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/lighting.c ${SRC_DIR}/bacnet/indtext.c # Test and test library files diff --git a/test/bacnet/bacapp/src/main.c b/test/bacnet/bacapp/src/main.c index 3e2d7ad8..6674c8a4 100644 --- a/test/bacnet/bacapp/src/main.c +++ b/test/bacnet/bacapp/src/main.c @@ -8,6 +8,8 @@ * @brief test BACnet integer encode/decode APIs */ +#include +#include #include #include #include @@ -17,123 +19,421 @@ * @{ */ -/** - * @brief Test - */ -/* generic - can be used by other unit tests - returns true if matching or same, false if different */ -static bool bacapp_same_value(BACNET_APPLICATION_DATA_VALUE *value, - BACNET_APPLICATION_DATA_VALUE *test_value) +static void test_bacapp_decode_application_data(void) { - bool status = false; /*return value */ + uint8_t apdu[128] = { 0 }; + //unsigned max_apdu_len = sizeof(apdu); + BACNET_APPLICATION_DATA_VALUE value = { 0 }; - /* does the tag match? */ - if (test_value->tag == value->tag) - status = true; - if (status) { - /* second test for same-ness */ - status = false; - /* does the value match? */ - switch (test_value->tag) { -#if defined(BACAPP_NULL) - case BACNET_APPLICATION_TAG_NULL: - status = true; - break; -#endif -#if defined(BACAPP_BOOLEAN) - case BACNET_APPLICATION_TAG_BOOLEAN: - if (test_value->type.Boolean == value->type.Boolean) - status = true; - break; -#endif -#if defined(BACAPP_UNSIGNED) - case BACNET_APPLICATION_TAG_UNSIGNED_INT: - if (test_value->type.Unsigned_Int == value->type.Unsigned_Int) - status = true; - break; -#endif -#if defined(BACAPP_SIGNED) - case BACNET_APPLICATION_TAG_SIGNED_INT: - if (test_value->type.Signed_Int == value->type.Signed_Int) - status = true; - break; -#endif -#if defined(BACAPP_REAL) - case BACNET_APPLICATION_TAG_REAL: - if (test_value->type.Real == value->type.Real) - status = true; - break; -#endif -#if defined(BACAPP_DOUBLE) - case BACNET_APPLICATION_TAG_DOUBLE: - if (test_value->type.Double == value->type.Double) - status = true; - break; -#endif -#if defined(BACAPP_ENUMERATED) - case BACNET_APPLICATION_TAG_ENUMERATED: - if (test_value->type.Enumerated == value->type.Enumerated) - status = true; - break; -#endif -#if defined(BACAPP_DATE) - case BACNET_APPLICATION_TAG_DATE: - if (datetime_compare_date( - &test_value->type.Date, &value->type.Date) == 0) - status = true; - break; -#endif -#if defined(BACAPP_TIME) - case BACNET_APPLICATION_TAG_TIME: - if (datetime_compare_time( - &test_value->type.Time, &value->type.Time) == 0) - status = true; - break; -#endif -#if defined(BACAPP_OBJECT_ID) - case BACNET_APPLICATION_TAG_OBJECT_ID: - if ((test_value->type.Object_Id.type == - value->type.Object_Id.type) && - (test_value->type.Object_Id.instance == - value->type.Object_Id.instance)) { - status = true; - } - break; -#endif -#if defined(BACAPP_CHARACTER_STRING) - case BACNET_APPLICATION_TAG_CHARACTER_STRING: - status = characterstring_same(&value->type.Character_String, - &test_value->type.Character_String); - break; -#endif -#if defined(BACAPP_OCTET_STRING) - case BACNET_APPLICATION_TAG_OCTET_STRING: - status = octetstring_value_same( - &value->type.Octet_String, &test_value->type.Octet_String); - break; -#endif -#if defined(BACAPP_BIT_STRING) - case BACNET_APPLICATION_TAG_BIT_STRING: - status = bitstring_same( - &value->type.Bit_String, &test_value->type.Bit_String); - break; -#endif -#if 0 /*TODO: Enable when lighting.c builds cleanly */ -#if defined(BACAPP_LIGHTING_COMMAND) - case BACNET_APPLICATION_TAG_LIGHTING_COMMAND: - status = lighting_command_same(&value->type.Lighting_Command, - &test_value->type.Lighting_Command); - break; -#endif -#endif /*TODO: */ - default: - status = false; - break; + zassert_equal(bacapp_decode_application_data(NULL, sizeof(apdu), &value), 0, NULL); + zassert_equal(bacapp_decode_application_data(apdu, 0, &value), 0, NULL); + zassert_equal(bacapp_decode_application_data(apdu, sizeof(apdu), NULL), 0, NULL); +} + + +static void test_bacapp_decode_data_len(void) +{ + uint8_t apdu[3] = { 0 }; + uint32_t len_value_type = 0; + int expected_value = 0; + + zassert_equal(bacapp_decode_data_len(NULL, BACNET_APPLICATION_TAG_NULL, sizeof(apdu)), 0, NULL); + zassert_equal(bacapp_decode_data_len(apdu, UINT8_MAX, sizeof(apdu)), 0, NULL); + + expected_value = (int) (~0U >> 1); /* INT_MAX is not universally defined */ + zassert_equal(bacapp_decode_data_len(apdu, BACNET_APPLICATION_TAG_UNSIGNED_INT, UINT32_MAX), expected_value, NULL); + + zassert_equal(bacapp_decode_data_len(apdu, BACNET_APPLICATION_TAG_NULL, sizeof(apdu)), 0, NULL); + zassert_equal(bacapp_decode_data_len(apdu, BACNET_APPLICATION_TAG_BOOLEAN, sizeof(apdu)), 0, NULL); + + len_value_type = INT32_MAX - 1; + expected_value = (int) len_value_type; + zassert_equal(bacapp_decode_data_len(apdu, BACNET_APPLICATION_TAG_UNSIGNED_INT, len_value_type), expected_value, NULL); + + len_value_type = INT32_MAX - 2; + expected_value = (int) len_value_type; + zassert_equal(bacapp_decode_data_len(apdu, BACNET_APPLICATION_TAG_SIGNED_INT, len_value_type), expected_value, NULL); + + len_value_type = INT32_MAX - 5; + expected_value = (int) len_value_type; + zassert_equal(bacapp_decode_data_len(apdu, BACNET_APPLICATION_TAG_REAL, len_value_type), expected_value, NULL); + + len_value_type = INT32_MAX - 9; + expected_value = (int) len_value_type; + zassert_equal(bacapp_decode_data_len(apdu, BACNET_APPLICATION_TAG_DOUBLE, len_value_type), expected_value, NULL); + + len_value_type = INT32_MAX - 13; + expected_value = (int) len_value_type; + zassert_equal(bacapp_decode_data_len(apdu, BACNET_APPLICATION_TAG_OCTET_STRING, len_value_type), expected_value, NULL); + + len_value_type = INT32_MAX - 17; + expected_value = (int) len_value_type; + zassert_equal(bacapp_decode_data_len(apdu, BACNET_APPLICATION_TAG_CHARACTER_STRING, len_value_type), expected_value, NULL); + + len_value_type = INT32_MAX - 19; + expected_value = (int) len_value_type; + zassert_equal(bacapp_decode_data_len(apdu, BACNET_APPLICATION_TAG_BIT_STRING, len_value_type), expected_value, NULL); + + len_value_type = INT32_MAX - 23; + expected_value = (int) len_value_type; + zassert_equal(bacapp_decode_data_len(apdu, BACNET_APPLICATION_TAG_ENUMERATED, len_value_type), expected_value, NULL); + + len_value_type = INT32_MAX - 29; + expected_value = (int) len_value_type; + zassert_equal(bacapp_decode_data_len(apdu, BACNET_APPLICATION_TAG_DATE, len_value_type), expected_value, NULL); + + len_value_type = INT32_MAX - 31; + expected_value = (int) len_value_type; + zassert_equal(bacapp_decode_data_len(apdu, BACNET_APPLICATION_TAG_TIME, len_value_type), expected_value, NULL); + + len_value_type = INT32_MAX - 37; + expected_value = (int) len_value_type; + zassert_equal(bacapp_decode_data_len(apdu, BACNET_APPLICATION_TAG_OBJECT_ID, len_value_type), expected_value, NULL); +} + +static void test_bacapp_copy(void) +{ + int i = 0; + + BACNET_APPLICATION_DATA_VALUE src_value = { 0 }; + BACNET_APPLICATION_DATA_VALUE dest_value = { 0 }; + + zassert_false(bacapp_copy(NULL, &src_value), NULL); + zassert_false(bacapp_copy(&dest_value, NULL), NULL); + + memset(&src_value, 0xAA, sizeof(src_value)); + memset(&dest_value, 0, sizeof(dest_value)); + zassert_false(bacapp_copy(&dest_value, &src_value), NULL); + zassert_equal(dest_value.tag, src_value.tag, NULL); + zassert_equal(dest_value.next, src_value.next, NULL); + + const BACNET_APPLICATION_TAG tags[] = { + BACNET_APPLICATION_TAG_NULL, + #if defined(BACAPP_BOOLEAN) + BACNET_APPLICATION_TAG_BOOLEAN, + #endif + #if defined(BACAPP_UNSIGNED) + BACNET_APPLICATION_TAG_UNSIGNED_INT, + #endif + #if defined(BACAPP_SIGNED) + BACNET_APPLICATION_TAG_SIGNED_INT, + #endif + #if defined(BACAPP_REAL) + BACNET_APPLICATION_TAG_REAL, + #endif + #if defined(BACAPP_DOUBLE) + BACNET_APPLICATION_TAG_DOUBLE, + #endif + #if defined(BACAPP_OCTET_STRING) + BACNET_APPLICATION_TAG_OCTET_STRING, + #endif + #if defined(BACAPP_CHARACTER_STRING) + BACNET_APPLICATION_TAG_CHARACTER_STRING, + #endif + #if defined(BACAPP_BIT_STRING) + BACNET_APPLICATION_TAG_BIT_STRING, + #endif + #if defined(BACAPP_ENUMERATED) + BACNET_APPLICATION_TAG_ENUMERATED, + #endif + #if defined(BACAPP_DATE) + BACNET_APPLICATION_TAG_DATE, + #endif + #if defined(BACAPP_TIME) + BACNET_APPLICATION_TAG_TIME, + #endif + #if defined(BACAPP_OBJECT_ID) + BACNET_APPLICATION_TAG_OBJECT_ID, + #endif + #if defined(BACAPP_LIGHTING_COMMAND) + BACNET_APPLICATION_TAG_LIGHTING_COMMAND, + #endif + }; + for (i = 0; i < sizeof(tags)/sizeof(tags[0]); ++i) { + BACNET_APPLICATION_TAG tag = tags[i]; + bool expected_result = true; + + #if ! defined(BACAPP_NULL) + if (tag == BACNET_APPLICATION_TAG_NULL) { + expected_result = false; + } + #endif + + memset(&src_value, 0, sizeof(src_value)); + memset(&dest_value, 0xBB, sizeof(dest_value)); + src_value.tag = tag; + src_value.next = (struct BACnet_Application_Data_Value *)(((uint32_t)tags[i]) << 8); + zassert_equal(bacapp_copy(&dest_value, &src_value), expected_result, NULL); + zassert_true(bacapp_same_value(&dest_value, &src_value), NULL); + zassert_equal(dest_value.next, src_value.next, NULL); + } +} + +static void test_bacapp_value_list_init(void) +{ + BACNET_APPLICATION_DATA_VALUE value[2] = { { 0 } }; + size_t max_count = 0; + size_t count = 0; + + /* Verify NULL ptr is properly handled */ + bacapp_value_list_init(NULL, 1); + + /* Verify zero length is properly handled */ + value[0] = value[1]; /* Struct copy */ + bacapp_value_list_init(&value[0], 0); + zassert_equal(memcmp(&value[0], &value[1], sizeof(value[1])), 0, NULL); + /* Verify one structure is initialized correctly */ + for (max_count = 1; max_count < sizeof(value)/sizeof(value[0]); ++max_count) { + memset(value, 0, sizeof(value)); + max_count = 1; + bacapp_value_list_init(&value[0], max_count); + + for (count = 0; count < max_count; ++count) { + zassert_equal(value[count].tag, BACNET_APPLICATION_TAG_NULL, NULL); + zassert_equal(value[count].context_specific, 0, NULL); + zassert_equal(value[count].context_tag, 0, NULL); + zassert_equal(value[count].next, ((count + 1 >= max_count) ? NULL : &value[count + 1]), NULL); } } - return status; } +static void test_bacapp_property_value_list_init(void) +{ + BACNET_PROPERTY_VALUE value[2] = { { 0 } }; + size_t max_count = 0; + size_t count = 0; + + /* Verify NULL ptr is properly handled */ + bacapp_property_value_list_init(NULL, 1); + + /* Verify zero length is properly handled */ + value[0] = value[1]; /* Struct copy */ + bacapp_property_value_list_init(&value[0], 0); + zassert_equal(memcmp(&value[0], &value[1], sizeof(value[1])), 0, NULL); + + /* Verify one structure is initialized correctly */ + for (max_count = 1; max_count < sizeof(value)/sizeof(value[0]); ++max_count) { + memset(value, 0, sizeof(value)); + max_count = 1; + bacapp_property_value_list_init(&value[0], max_count); + + for (count = 0; count < max_count; ++count) { + zassert_equal(value[count].propertyIdentifier, MAX_BACNET_PROPERTY_ID, NULL); + zassert_equal(value[count].propertyArrayIndex, BACNET_ARRAY_ALL, NULL); + zassert_equal(value[count].priority, BACNET_NO_PRIORITY, NULL); + zassert_equal(value[count].next, ((count + 1 >= max_count) ? NULL : &value[count + 1]), NULL); + } + } +} + +static void test_bacapp_same_value(void) +{ + BACNET_APPLICATION_DATA_VALUE value = { 0 }; + BACNET_APPLICATION_DATA_VALUE test_value = { 0 }; + + zassert_false(bacapp_same_value(NULL, &test_value), NULL); + zassert_false(bacapp_same_value(&value, NULL), NULL); + + value.tag = ~test_value.tag; + zassert_false(bacapp_same_value(&value, &test_value), NULL); + + test_value.tag = BACNET_APPLICATION_TAG_NULL; + value.tag = test_value.tag; +#if defined(BACAPP_NULL) + zassert_true(bacapp_same_value(&value, &test_value), NULL); +#else + zassert_false(bacapp_same_value(&value, &test_value), NULL); +#endif + + + test_value.tag = BACNET_APPLICATION_TAG_BOOLEAN; + value.tag = test_value.tag; +#if defined(BACAPP_BOOLEAN) + zassert_true(bacapp_same_value(&value, &test_value), NULL); +#else + zassert_false(bacapp_same_value(&value, &test_value), NULL); +#endif + value.type.Boolean = !test_value.type.Boolean; + zassert_false(bacapp_same_value(&value, &test_value), NULL); + + + memset(&test_value, 0, sizeof(test_value)); + test_value.tag = BACNET_APPLICATION_TAG_UNSIGNED_INT; + value = test_value; /* Struct copy */ +#if defined(BACAPP_UNSIGNED) + zassert_true(bacapp_same_value(&value, &test_value), NULL); +#else + zassert_false(bacapp_same_value(&value, &test_value), NULL); +#endif + value.type.Unsigned_Int = ~test_value.type.Unsigned_Int; + zassert_false(bacapp_same_value(&value, &test_value), NULL); + + + memset(&test_value, 0, sizeof(test_value)); + test_value.tag = BACNET_APPLICATION_TAG_SIGNED_INT; + value = test_value; /* Struct copy */ +#if defined(BACAPP_SIGNED) + zassert_true(bacapp_same_value(&value, &test_value), NULL); +#else + zassert_false(bacapp_same_value(&value, &test_value), NULL); +#endif + value.type.Signed_Int = test_value.type.Signed_Int + 1; + zassert_false(bacapp_same_value(&value, &test_value), NULL); + + + memset(&test_value, 0, sizeof(test_value)); + test_value.tag = BACNET_APPLICATION_TAG_REAL; + value = test_value; /* Struct copy */ +#if defined(BACAPP_REAL) + zassert_true(bacapp_same_value(&value, &test_value), NULL); +#else + zassert_false(bacapp_same_value(&value, &test_value), NULL); +#endif + value.type.Real = test_value.type.Real + 1.0f; + zassert_false(bacapp_same_value(&value, &test_value), NULL); + + + memset(&test_value, 0, sizeof(test_value)); + test_value.tag = BACNET_APPLICATION_TAG_DOUBLE; + value = test_value; /* Struct copy */ +#if defined(BACAPP_DOUBLE) + zassert_true(bacapp_same_value(&value, &test_value), NULL); +#else + zassert_false(bacapp_same_value(&value, &test_value), NULL); +#endif + value.type.Double = test_value.type.Double + 1.0; + zassert_false(bacapp_same_value(&value, &test_value), NULL); + + + memset(&test_value, 0, sizeof(test_value)); + test_value.tag = BACNET_APPLICATION_TAG_ENUMERATED; + value = test_value; /* Struct copy */ +#if defined(BACAPP_ENUMERATED) + zassert_true(bacapp_same_value(&value, &test_value), NULL); +#else + zassert_false(bacapp_same_value(&value, &test_value), NULL); +#endif + value.type.Enumerated = test_value.type.Enumerated + 1; + zassert_false(bacapp_same_value(&value, &test_value), NULL); + + + memset(&test_value, 0, sizeof(test_value)); + test_value.tag = BACNET_APPLICATION_TAG_DATE; + value = test_value; /* Struct copy */ +#if defined(BACAPP_DATE) + zassert_true(bacapp_same_value(&value, &test_value), NULL); +#else + zassert_false(bacapp_same_value(&value, &test_value), NULL); +#endif + + value = test_value; /* Struct copy */ + value.type.Date.day = test_value.type.Date.day + 1; + zassert_false(bacapp_same_value(&value, &test_value), NULL); + +#if 0 /*REVISIT: wday is not compared! */ + value = test_value; /* Struct copy */ + value.type.Date.wday = test_value.type.Date.wday + 1; + zassert_false(bacapp_same_value(&value, &test_value), NULL); +#endif + + value = test_value; /* Struct copy */ + value.type.Date.month = test_value.type.Date.month + 1; + zassert_false(bacapp_same_value(&value, &test_value), NULL); + + value = test_value; /* Struct copy */ + value.type.Date.year = test_value.type.Date.year + 1; + zassert_false(bacapp_same_value(&value, &test_value), NULL); + + + memset(&test_value, 0, sizeof(test_value)); + test_value.tag = BACNET_APPLICATION_TAG_TIME; + value = test_value; /* Struct copy */ +#if defined(BACAPP_TIME) + zassert_true(bacapp_same_value(&value, &test_value), NULL); +#else + zassert_false(bacapp_same_value(&value, &test_value), NULL); +#endif + + value = test_value; /* Struct copy */ + value.type.Time.hour = test_value.type.Time.hour + 1; + zassert_false(bacapp_same_value(&value, &test_value), NULL); + + value = test_value; /* Struct copy */ + value.type.Time.min = test_value.type.Time.min + 1; + zassert_false(bacapp_same_value(&value, &test_value), NULL); + + value = test_value; /* Struct copy */ + value.type.Time.sec = test_value.type.Time.sec + 1; + zassert_false(bacapp_same_value(&value, &test_value), NULL); + + value = test_value; /* Struct copy */ + value.type.Time.hundredths = test_value.type.Time.hundredths + 1; + zassert_false(bacapp_same_value(&value, &test_value), NULL); + + + memset(&test_value, 0, sizeof(test_value)); + test_value.tag = BACNET_APPLICATION_TAG_OBJECT_ID; + value = test_value; /* Struct copy */ +#if defined(BACAPP_OBJECT_ID) + zassert_true(bacapp_same_value(&value, &test_value), NULL); +#else + zassert_false(bacapp_same_value(&value, &test_value), NULL); +#endif + + value = test_value; /* Struct copy */ + value.type.Object_Id.type = test_value.type.Object_Id.type + 1; + zassert_false(bacapp_same_value(&value, &test_value), NULL); + + value = test_value; /* Struct copy */ + value.type.Object_Id.instance = test_value.type.Object_Id.instance + 1; + zassert_false(bacapp_same_value(&value, &test_value), NULL); + + + memset(&test_value, 0, sizeof(test_value)); + test_value.tag = BACNET_APPLICATION_TAG_CHARACTER_STRING; + value = test_value; /* Struct copy */ +#if defined(BACAPP_CHARACTER_STRING) + zassert_true(bacapp_same_value(&value, &test_value), NULL); +#else + zassert_false(bacapp_same_value(&value, &test_value), NULL); +#endif + //TODO: Verify .type.Character_String value compared + + + memset(&test_value, 0, sizeof(test_value)); + test_value.tag = BACNET_APPLICATION_TAG_OCTET_STRING; + value = test_value; /* Struct copy */ +#if defined(BACAPP_OCTET_STRING) + zassert_true(bacapp_same_value(&value, &test_value), NULL); +#else + zassert_false(bacapp_same_value(&value, &test_value), NULL); +#endif + //TODO: Verify .type.Octet_String value compared + + + memset(&test_value, 0, sizeof(test_value)); + test_value.tag = BACNET_APPLICATION_TAG_BIT_STRING; + value = test_value; /* Struct copy */ +#if defined(BACAPP_BIT_STRING) + zassert_true(bacapp_same_value(&value, &test_value), NULL); +#else + zassert_false(bacapp_same_value(&value, &test_value), NULL); +#endif + //TODO: Verify .type.Bit_String value compared + + + memset(&test_value, 0, sizeof(test_value)); + test_value.tag = BACNET_APPLICATION_TAG_LIGHTING_COMMAND; + value = test_value; /* Struct copy */ +#if defined(BACAPP_LIGHTING_COMMAND) + zassert_true(bacapp_same_value(&value, &test_value), NULL); +#else + zassert_false(bacapp_same_value(&value, &test_value), NULL); +#endif + //TODO: Verify .type.Lighting_Command value compared +} + + /** * @brief Test */ @@ -640,6 +940,12 @@ static void testBACnetApplicationData(void) void test_main(void) { ztest_test_suite(bacapp_tests, + ztest_unit_test(test_bacapp_decode_application_data), + ztest_unit_test(test_bacapp_decode_data_len), + ztest_unit_test(test_bacapp_copy), + ztest_unit_test(test_bacapp_value_list_init), + ztest_unit_test(test_bacapp_property_value_list_init), + ztest_unit_test(test_bacapp_same_value), ztest_unit_test(testBACnetApplicationData), ztest_unit_test(testBACnetApplicationDataLength), ztest_unit_test(testBACnetApplicationData_Safe) diff --git a/test/bacnet/bacdevobjpropref/CMakeLists.txt b/test/bacnet/bacdevobjpropref/CMakeLists.txt index 83613d97..d34bb035 100644 --- a/test/bacnet/bacdevobjpropref/CMakeLists.txt +++ b/test/bacnet/bacdevobjpropref/CMakeLists.txt @@ -43,6 +43,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bactext.c ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c # Test and test library files diff --git a/test/bacnet/basic/binding/address/CMakeLists.txt b/test/bacnet/basic/binding/address/CMakeLists.txt index 5eab762d..f4fcaedc 100644 --- a/test/bacnet/basic/binding/address/CMakeLists.txt +++ b/test/bacnet/basic/binding/address/CMakeLists.txt @@ -44,6 +44,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bactext.c ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c # Test and test library files diff --git a/test/bacnet/basic/binding/address/src/main.c b/test/bacnet/basic/binding/address/src/main.c index 24cb2615..56057557 100644 --- a/test/bacnet/basic/binding/address/src/main.c +++ b/test/bacnet/basic/binding/address/src/main.c @@ -24,6 +24,8 @@ * @{ */ +static const char *Address_Cache_Filename = "address_cache"; + /** * @brief Test */ @@ -42,7 +44,6 @@ static void set_address(unsigned index, BACNET_ADDRESS *dest) } } -#if 0 /* Not used */ static void set_file_address(const char *pFilename, uint32_t device_id, BACNET_ADDRESS *dest, @@ -76,18 +77,18 @@ static void set_file_address(const char *pFilename, fclose(pFile); } } -#endif #ifdef BACNET_ADDRESS_CACHE_FILE +/* Validate that the address data in the file */ static void testAddressFile(void) { -#if 0 /* Skip file as Address_Cache_Filename is an internal data structure */ BACNET_ADDRESS src = { 0 }; uint32_t device_id = 0; unsigned max_apdu = 480; BACNET_ADDRESS test_address = { 0 }; unsigned test_max_apdu = 0; + /* Create known data */ /* create a fake address */ device_id = 55555; src.mac_len = 1; @@ -97,12 +98,19 @@ static void testAddressFile(void) max_apdu = 50; set_file_address(Address_Cache_Filename, device_id, &src, max_apdu); /* retrieve it from the file, and see if we can find it */ - address_file_init(Address_Cache_Filename); + address_init(); + + /* Verify */ zassert_true( address_get_by_device(device_id, &test_max_apdu, &test_address), NULL); zassert_equal(test_max_apdu, max_apdu, NULL); zassert_true(bacnet_address_same(&test_address, &src), NULL); + zassert_equal(address_count(), 1, NULL); + address_remove_device(device_id); + zassert_equal(address_count(), 0, NULL); + + /* create a fake address */ device_id = 55555; src.mac_len = 6; @@ -118,14 +126,15 @@ static void testAddressFile(void) max_apdu = 50; set_file_address(Address_Cache_Filename, device_id, &src, max_apdu); /* retrieve it from the file, and see if we can find it */ - address_file_init(Address_Cache_Filename); + address_init(); zassert_true( address_get_by_device(device_id, &test_max_apdu, &test_address), NULL); zassert_equal(test_max_apdu, max_apdu, NULL); zassert_true(bacnet_address_same(&test_address, &src), NULL); -#else - ztest_test_skip(); -#endif + + zassert_equal(address_count(), 1, NULL); + address_remove_device(device_id); + zassert_equal(address_count(), 0, NULL); } #endif diff --git a/test/bacnet/basic/object/acc/CMakeLists.txt b/test/bacnet/basic/object/acc/CMakeLists.txt index de197ac2..56a1dadf 100644 --- a/test/bacnet/basic/object/acc/CMakeLists.txt +++ b/test/bacnet/basic/object/acc/CMakeLists.txt @@ -45,6 +45,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/datetime.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c + ${SRC_DIR}/bacnet/basic/sys/days.c # Test and test library files ./src/main.c ${ZTST_DIR}/ztest_mock.c diff --git a/test/bacnet/basic/object/acc/src/main.c b/test/bacnet/basic/object/acc/src/main.c index 15cdbdaa..bf0ea093 100644 --- a/test/bacnet/basic/object/acc/src/main.c +++ b/test/bacnet/basic/object/acc/src/main.c @@ -10,6 +10,7 @@ #include #include +#include /** * @addtogroup bacnet_tests @@ -26,7 +27,7 @@ static void test_Accumulator(void) int test_len = 0; BACNET_READ_PROPERTY_DATA rpdata = {0}; BACNET_APPLICATION_DATA_VALUE value = {0}; - int *required_property = NULL; + const int *required_property = NULL; BACNET_UNSIGNED_INTEGER unsigned_value = 1; Accumulator_Init(); diff --git a/test/bacnet/basic/object/access_credential/CMakeLists.txt b/test/bacnet/basic/object/access_credential/CMakeLists.txt index 32f31499..82c44fce 100644 --- a/test/bacnet/basic/object/access_credential/CMakeLists.txt +++ b/test/bacnet/basic/object/access_credential/CMakeLists.txt @@ -46,6 +46,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/credential_authentication_factor.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c ${SRC_DIR}/bacnet/wp.c diff --git a/test/bacnet/basic/object/access_credential/src/main.c b/test/bacnet/basic/object/access_credential/src/main.c index dddbf6be..6286dc6e 100644 --- a/test/bacnet/basic/object/access_credential/src/main.c +++ b/test/bacnet/basic/object/access_credential/src/main.c @@ -27,7 +27,7 @@ static void testAccessCredential(void) BACNET_READ_PROPERTY_DATA rpdata = {0}; BACNET_APPLICATION_DATA_VALUE value = {0}; BACNET_APPLICATION_DATA_VALUE value2 = {0}; - int *required_property = NULL; + const int *required_property = NULL; BACNET_UNSIGNED_INTEGER unsigned_value = 1; Access_Credential_Init(); diff --git a/test/bacnet/basic/object/access_door/CMakeLists.txt b/test/bacnet/basic/object/access_door/CMakeLists.txt index 27a66987..e5583c3c 100644 --- a/test/bacnet/basic/object/access_door/CMakeLists.txt +++ b/test/bacnet/basic/object/access_door/CMakeLists.txt @@ -43,6 +43,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bactext.c ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c ${SRC_DIR}/bacnet/wp.c diff --git a/test/bacnet/basic/object/access_door/src/main.c b/test/bacnet/basic/object/access_door/src/main.c index e9bb25ab..92e26e9a 100644 --- a/test/bacnet/basic/object/access_door/src/main.c +++ b/test/bacnet/basic/object/access_door/src/main.c @@ -5,7 +5,7 @@ */ /* @file - * @brief test BACnet integer encode/decode APIs + * @brief test BACnet access_door object APIs */ #include @@ -19,45 +19,57 @@ /** * @brief Test */ -#if 0 -bool WPValidateArgType(BACNET_APPLICATION_DATA_VALUE *pValue, - uint8_t ucExpectedTag, - BACNET_ERROR_CLASS *pErrorClass, - BACNET_ERROR_CODE *pErrorCode) -{ - pValue = pValue; - ucExpectedTag = ucExpectedTag; - pErrorClass = pErrorClass; - pErrorCode = pErrorCode; - - return false; -} -#endif - -static void testAccessDoor(void) +static void test_object_access_door(void) { uint8_t apdu[MAX_APDU] = { 0 }; int len = 0; - uint32_t len_value = 0; - uint8_t tag_number = 0; - uint32_t decoded_instance = 0; - BACNET_OBJECT_TYPE decoded_type = 0; + int test_len = 0; BACNET_READ_PROPERTY_DATA rpdata; + /* for decode value data */ + BACNET_APPLICATION_DATA_VALUE value; + const int *pRequired = NULL; + const int *pOptional = NULL; + const int *pProprietary = NULL; + unsigned port = 0; + unsigned count = 0; + uint32_t object_instance = 0; + object_instance = Access_Door_Index_To_Instance(0); Access_Door_Init(); + count = Access_Door_Count(); + zassert_true(count > 0, NULL); rpdata.application_data = &apdu[0]; rpdata.application_data_len = sizeof(apdu); rpdata.object_type = OBJECT_ACCESS_DOOR; - rpdata.object_instance = 1; - rpdata.object_property = PROP_OBJECT_IDENTIFIER; - rpdata.array_index = BACNET_ARRAY_ALL; - len = Access_Door_Read_Property(&rpdata); - zassert_not_equal(len, 0, NULL); - len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value); - zassert_equal(tag_number, BACNET_APPLICATION_TAG_OBJECT_ID, NULL); - len = decode_object_id(&apdu[len], &decoded_type, &decoded_instance); - zassert_equal(decoded_type, rpdata.object_type, NULL); - zassert_equal(decoded_instance, rpdata.object_instance, NULL); + rpdata.object_instance = object_instance; + Access_Door_Property_Lists(&pRequired, &pOptional, &pProprietary); + while ((*pRequired) != -1) { + rpdata.object_property = *pRequired; + rpdata.array_index = BACNET_ARRAY_ALL; + len = Access_Door_Read_Property(&rpdata); + zassert_not_equal(len, BACNET_STATUS_ERROR, NULL); + if (len > 0) { + test_len = bacapp_decode_application_data( + rpdata.application_data, + (uint8_t)rpdata.application_data_len, &value); + zassert_true(test_len >= 0, NULL); + } + pRequired++; + } + while ((*pOptional) != -1) { + rpdata.object_property = *pOptional; + rpdata.array_index = BACNET_ARRAY_ALL; + len = Access_Door_Read_Property(&rpdata); + zassert_not_equal(len, BACNET_STATUS_ERROR, NULL); + if (len > 0) { + test_len = bacapp_decode_application_data( + rpdata.application_data, + (uint8_t)rpdata.application_data_len, &value); + zassert_true(test_len >= 0, NULL); + } + pOptional++; + } + port++; return; } @@ -68,9 +80,9 @@ static void testAccessDoor(void) void test_main(void) { - ztest_test_suite(access_door_tests, - ztest_unit_test(testAccessDoor) + ztest_test_suite(tests_object_access_door, + ztest_unit_test(test_object_access_door) ); - ztest_run_test_suite(access_door_tests); + ztest_run_test_suite(tests_object_access_door); } diff --git a/test/bacnet/basic/object/access_point/CMakeLists.txt b/test/bacnet/basic/object/access_point/CMakeLists.txt index dee7d0d3..b1cf0fce 100644 --- a/test/bacnet/basic/object/access_point/CMakeLists.txt +++ b/test/bacnet/basic/object/access_point/CMakeLists.txt @@ -43,6 +43,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bactext.c ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c ${SRC_DIR}/bacnet/timestamp.c diff --git a/test/bacnet/basic/object/access_rights/CMakeLists.txt b/test/bacnet/basic/object/access_rights/CMakeLists.txt index 6ae6ec20..003c43b1 100644 --- a/test/bacnet/basic/object/access_rights/CMakeLists.txt +++ b/test/bacnet/basic/object/access_rights/CMakeLists.txt @@ -44,6 +44,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bactext.c ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c ${SRC_DIR}/bacnet/wp.c diff --git a/test/bacnet/basic/object/access_user/CMakeLists.txt b/test/bacnet/basic/object/access_user/CMakeLists.txt index 52d6fc98..6357dbde 100644 --- a/test/bacnet/basic/object/access_user/CMakeLists.txt +++ b/test/bacnet/basic/object/access_user/CMakeLists.txt @@ -43,6 +43,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bactext.c ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c ${SRC_DIR}/bacnet/wp.c diff --git a/test/bacnet/basic/object/access_zone/CMakeLists.txt b/test/bacnet/basic/object/access_zone/CMakeLists.txt index 7ee422d0..9d51081f 100644 --- a/test/bacnet/basic/object/access_zone/CMakeLists.txt +++ b/test/bacnet/basic/object/access_zone/CMakeLists.txt @@ -47,6 +47,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/credential_authentication_factor.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c ${SRC_DIR}/bacnet/wp.c diff --git a/test/bacnet/basic/object/ai/CMakeLists.txt b/test/bacnet/basic/object/ai/CMakeLists.txt index baa97684..c364385b 100644 --- a/test/bacnet/basic/object/ai/CMakeLists.txt +++ b/test/bacnet/basic/object/ai/CMakeLists.txt @@ -44,6 +44,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/cov.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c ${SRC_DIR}/bacnet/memcopy.c diff --git a/test/bacnet/basic/object/ao/CMakeLists.txt b/test/bacnet/basic/object/ao/CMakeLists.txt index 4b3568ce..2fe0378c 100644 --- a/test/bacnet/basic/object/ao/CMakeLists.txt +++ b/test/bacnet/basic/object/ao/CMakeLists.txt @@ -43,6 +43,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bactext.c ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c ${SRC_DIR}/bacnet/wp.c diff --git a/test/bacnet/basic/object/av/CMakeLists.txt b/test/bacnet/basic/object/av/CMakeLists.txt index 3b053065..215ebcb5 100644 --- a/test/bacnet/basic/object/av/CMakeLists.txt +++ b/test/bacnet/basic/object/av/CMakeLists.txt @@ -44,6 +44,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/cov.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c ${SRC_DIR}/bacnet/memcopy.c diff --git a/test/bacnet/basic/object/bi/CMakeLists.txt b/test/bacnet/basic/object/bi/CMakeLists.txt index 1c9ab197..abbe8e57 100644 --- a/test/bacnet/basic/object/bi/CMakeLists.txt +++ b/test/bacnet/basic/object/bi/CMakeLists.txt @@ -44,6 +44,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/cov.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c ${SRC_DIR}/bacnet/memcopy.c diff --git a/test/bacnet/basic/object/bo/CMakeLists.txt b/test/bacnet/basic/object/bo/CMakeLists.txt index 165cd632..02ffe1f5 100644 --- a/test/bacnet/basic/object/bo/CMakeLists.txt +++ b/test/bacnet/basic/object/bo/CMakeLists.txt @@ -43,6 +43,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bactext.c ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c ${SRC_DIR}/bacnet/wp.c diff --git a/test/bacnet/basic/object/bv/CMakeLists.txt b/test/bacnet/basic/object/bv/CMakeLists.txt index 6671f4a7..fffd35b2 100644 --- a/test/bacnet/basic/object/bv/CMakeLists.txt +++ b/test/bacnet/basic/object/bv/CMakeLists.txt @@ -43,6 +43,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bactext.c ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c ${SRC_DIR}/bacnet/wp.c diff --git a/test/bacnet/basic/object/command/CMakeLists.txt b/test/bacnet/basic/object/command/CMakeLists.txt index 4664f6cc..45b871ac 100644 --- a/test/bacnet/basic/object/command/CMakeLists.txt +++ b/test/bacnet/basic/object/command/CMakeLists.txt @@ -43,6 +43,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bactext.c ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c ${SRC_DIR}/bacnet/wp.c diff --git a/test/bacnet/basic/object/command/src/main.c b/test/bacnet/basic/object/command/src/main.c index fc91e818..fa8a3cb0 100644 --- a/test/bacnet/basic/object/command/src/main.c +++ b/test/bacnet/basic/object/command/src/main.c @@ -5,7 +5,7 @@ */ /* @file - * @brief test BACnet integer encode/decode APIs + * @brief test BACnet command object APIs */ #include @@ -19,66 +19,59 @@ /** * @brief Test */ -static void testCommand(void) +static void test_object_command(void) { -#if 0 /*TODO: Test does not pass */ uint8_t apdu[MAX_APDU] = { 0 }; int len = 0; - uint32_t len_value = 0; - uint8_t tag_number = 0; - uint32_t decoded_instance = 0; - BACNET_OBJECT_TYPE decoded_type = 0; + int test_len = 0; BACNET_READ_PROPERTY_DATA rpdata; - BACNET_ACTION_LIST clist, clist_test; + /* for decode value data */ + BACNET_APPLICATION_DATA_VALUE value; + const int *pRequired = NULL; + const int *pOptional = NULL; + const int *pProprietary = NULL; + unsigned port = 0; + unsigned count = 0; + uint32_t object_instance = 0; + + object_instance = Command_Index_To_Instance(0); Command_Init(); + count = Command_Count(); + zassert_true(count > 0, NULL); rpdata.application_data = &apdu[0]; rpdata.application_data_len = sizeof(apdu); rpdata.object_type = OBJECT_COMMAND; - rpdata.object_instance = 1; - rpdata.object_property = PROP_OBJECT_IDENTIFIER; - rpdata.array_index = BACNET_ARRAY_ALL; - len = Command_Read_Property(&rpdata); - zassert_not_equal(len, 0, NULL); - len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value); - zassert_equal(tag_number, BACNET_APPLICATION_TAG_OBJECT_ID, NULL); - len = decode_object_id(&apdu[len], &decoded_type, &decoded_instance); - zassert_equal(decoded_type, rpdata.object_type, NULL); - zassert_equal(decoded_instance, rpdata.object_instance, NULL); - memset(&clist, 0, sizeof(BACNET_ACTION_LIST)); - memset(&clist_test, 0, sizeof(BACNET_ACTION_LIST)); - clist.Device_Id.type = OBJECT_DEVICE; - clist.Device_Id.instance = 3389; - clist.Object_Id.type = OBJECT_ANALOG_VALUE; - clist.Object_Id.instance = 42; - clist.Property_Identifier = PROP_PRESENT_VALUE; - clist.Property_Array_Index = BACNET_ARRAY_ALL; - clist.Value.tag = BACNET_APPLICATION_TAG_REAL; - clist.Value.type.Real = 39.0f; - clist.Priority = 4; - clist.Post_Delay = 0xFFFFFFFFU; - clist.Quit_On_Failure = true; - clist.Write_Successful = false; - clist.next = NULL; - len = cl_encode_apdu(apdu, &clist); - zassert_true(len > 0, NULL); - len = cl_decode_apdu(apdu, len, BACNET_APPLICATION_TAG_REAL, &clist_test); - zassert_true(len > 0, NULL); - zassert_equal(clist.Device_Id.type, clist_test.Device_Id.type, NULL); - zassert_equal(clist.Device_Id.instance, clist_test.Device_Id.instance, NULL); - zassert_equal(clist.Object_Id.type, clist_test.Object_Id.type, NULL); - zassert_equal(clist.Object_Id.instance, clist_test.Object_Id.instance, NULL); - zassert_equal(clist.Property_Identifier, clist_test.Property_Identifier, NULL); - zassert_equal(clist.Property_Array_Index, clist_test.Property_Array_Index, NULL); - zassert_equal(clist.Value.tag, clist_test.Value.tag, NULL); - zassert_equal(clist.Value.type.Real, clist_test.Value.type.Real, NULL); - zassert_equal(clist.Priority, clist_test.Priority, NULL); - zassert_equal(clist.Post_Delay, clist_test.Post_Delay, NULL); - zassert_equal(clist.Quit_On_Failure, clist_test.Quit_On_Failure, NULL); - zassert_equal(clist.Write_Successful, clist_test.Write_Successful, NULL); + rpdata.object_instance = object_instance; + Command_Property_Lists(&pRequired, &pOptional, &pProprietary); + while ((*pRequired) != -1) { + rpdata.object_property = *pRequired; + rpdata.array_index = BACNET_ARRAY_ALL; + len = Command_Read_Property(&rpdata); + zassert_not_equal(len, BACNET_STATUS_ERROR, NULL); + if (len > 0) { + test_len = bacapp_decode_application_data( + rpdata.application_data, + (uint8_t)rpdata.application_data_len, &value); + zassert_true(test_len >= 0, NULL); + } + pRequired++; + } + while ((*pOptional) != -1) { + rpdata.object_property = *pOptional; + rpdata.array_index = BACNET_ARRAY_ALL; + len = Command_Read_Property(&rpdata); + zassert_not_equal(len, BACNET_STATUS_ERROR, NULL); + if (len > 0) { + test_len = bacapp_decode_application_data( + rpdata.application_data, + (uint8_t)rpdata.application_data_len, &value); + zassert_true(test_len >= 0, NULL); + } + pOptional++; + } + port++; + return; -#else - ztest_test_skip(); -#endif } /** * @} @@ -87,9 +80,9 @@ static void testCommand(void) void test_main(void) { - ztest_test_suite(command_tests, - ztest_unit_test(testCommand) + ztest_test_suite(tests_object_command, + ztest_unit_test(test_object_command) ); - ztest_run_test_suite(command_tests); + ztest_run_test_suite(tests_object_command); } diff --git a/test/bacnet/basic/object/credential_data_input/CMakeLists.txt b/test/bacnet/basic/object/credential_data_input/CMakeLists.txt index f037a713..e0f4b435 100644 --- a/test/bacnet/basic/object/credential_data_input/CMakeLists.txt +++ b/test/bacnet/basic/object/credential_data_input/CMakeLists.txt @@ -46,6 +46,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/credential_authentication_factor.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c ${SRC_DIR}/bacnet/timestamp.c diff --git a/test/bacnet/basic/object/device/CMakeLists.txt b/test/bacnet/basic/object/device/CMakeLists.txt index d7a03434..ea6c349c 100644 --- a/test/bacnet/basic/object/device/CMakeLists.txt +++ b/test/bacnet/basic/object/device/CMakeLists.txt @@ -76,6 +76,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/datalink/bvlc.c ${SRC_DIR}/bacnet/cov.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/dcc.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c diff --git a/test/bacnet/basic/object/lc/CMakeLists.txt b/test/bacnet/basic/object/lc/CMakeLists.txt index cda4b2f1..cb4fd269 100644 --- a/test/bacnet/basic/object/lc/CMakeLists.txt +++ b/test/bacnet/basic/object/lc/CMakeLists.txt @@ -45,6 +45,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/basic/object/ao.c ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c ${SRC_DIR}/bacnet/wp.c diff --git a/test/bacnet/basic/object/lc/src/main.c b/test/bacnet/basic/object/lc/src/main.c index adda6bd2..2d983d8b 100644 --- a/test/bacnet/basic/object/lc/src/main.c +++ b/test/bacnet/basic/object/lc/src/main.c @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -26,10 +27,198 @@ * @{ */ +#if 0 +/* Mocks */ + +void bacapp_value_list_init( + BACNET_APPLICATION_DATA_VALUE *value, + size_t count) +{ +} + +void bacapp_property_value_list_init( + BACNET_PROPERTY_VALUE *value, + size_t count) +{ +} + + +int bacapp_encode_data( + uint8_t * apdu, + BACNET_APPLICATION_DATA_VALUE * value) +{ + return -1; +} + +int bacapp_decode_data( + uint8_t * apdu, + uint8_t tag_data_type, + uint32_t len_value_type, + BACNET_APPLICATION_DATA_VALUE * value) +{ + return -1; +} + + +int bacapp_decode_application_data( + uint8_t * apdu, + unsigned max_apdu_len, + BACNET_APPLICATION_DATA_VALUE * value) +{ + return -1; +} + + +bool bacapp_decode_application_data_safe( + uint8_t * new_apdu, + uint32_t new_apdu_len, + BACNET_APPLICATION_DATA_VALUE * value) +{ + return false; +} + + +int bacapp_encode_application_data( + uint8_t * apdu, + BACNET_APPLICATION_DATA_VALUE * value) +{ + return -1; +} + + +int bacapp_decode_context_data( + uint8_t * apdu, + unsigned max_apdu_len, + BACNET_APPLICATION_DATA_VALUE * value, + BACNET_PROPERTY_ID property) +{ + return -1; +} + + +int bacapp_encode_context_data( + uint8_t * apdu, + BACNET_APPLICATION_DATA_VALUE * value, + BACNET_PROPERTY_ID property) +{ + return -1; +} + + +int bacapp_encode_context_data_value( + uint8_t * apdu, + uint8_t context_tag_number, + BACNET_APPLICATION_DATA_VALUE * value) +{ + return -1; +} + + +BACNET_APPLICATION_TAG bacapp_context_tag_type( + BACNET_PROPERTY_ID property, + uint8_t tag_number) +{ + return MAX_BACNET_APPLICATION_TAG; +} + + +bool bacapp_copy( + BACNET_APPLICATION_DATA_VALUE * dest_value, + BACNET_APPLICATION_DATA_VALUE * src_value) +{ + return false; +} + + +int bacapp_data_len( + uint8_t * apdu, + unsigned max_apdu_len, + BACNET_PROPERTY_ID property) +{ + return -1; +} + +int bacapp_decode_data_len( + uint8_t * apdu, + uint8_t tag_data_type, + uint32_t len_value_type) +{ + return -1; +} + +int bacapp_decode_application_data_len( + uint8_t * apdu, + unsigned max_apdu_len) +{ + return -1; +} + +int bacapp_decode_context_data_len( + uint8_t * apdu, + unsigned max_apdu_len, + BACNET_PROPERTY_ID property) +{ + return -1; +} + +int bacapp_snprintf_value( + char *str, + size_t str_len, + BACNET_OBJECT_PROPERTY_VALUE * object_value) +{ + return -1; +} + + +#ifdef BACAPP_PRINT_ENABLED +bool bacapp_parse_application_data( + BACNET_APPLICATION_TAG tag_number, + const char *argv, + BACNET_APPLICATION_DATA_VALUE * value) +{ + return false; +} + +bool bacapp_print_value( + FILE * stream, + BACNET_OBJECT_PROPERTY_VALUE * value) +{ + return false; +} + +#endif + +bool bacapp_same_value( + BACNET_APPLICATION_DATA_VALUE * value, + BACNET_APPLICATION_DATA_VALUE * test_value) +{ + return false; +} +#endif + + + /** * @brief Test */ -#if 0 /* TODO: How should this get exposed? */ + +static void test_Load_Control_Count(void) +{ + /* Verify the same value is returned on successive calls without init */ + zassert_equal(Load_Control_Count(), MAX_LOAD_CONTROLS, NULL); + zassert_equal(Load_Control_Count(), MAX_LOAD_CONTROLS, NULL); + + /* Verify the same value is returned on successive calls with init */ + Load_Control_Init(); + zassert_equal(Load_Control_Count(), MAX_LOAD_CONTROLS, NULL); + zassert_equal(Load_Control_Count(), MAX_LOAD_CONTROLS, NULL); + + /* Verify the same value is returned on successive calls with re-init */ + Load_Control_Init(); + zassert_equal(Load_Control_Count(), MAX_LOAD_CONTROLS, NULL); + zassert_equal(Load_Control_Count(), MAX_LOAD_CONTROLS, NULL); +} + static void Load_Control_WriteProperty_Request_Shed_Level( int instance, unsigned level) { @@ -52,9 +241,7 @@ static void Load_Control_WriteProperty_Request_Shed_Level( status = Load_Control_Write_Property(&wp_data); zassert_true(status, NULL); } -#endif -#if 0 /* TODO: How should this get exposed? */ static void Load_Control_WriteProperty_Enable( int instance, bool enable) { @@ -78,9 +265,7 @@ static void Load_Control_WriteProperty_Enable( status = Load_Control_Write_Property(&wp_data); zassert_true(status, NULL); } -#endif -#if 0 /* TODO: How should this get exposed? */ static void Load_Control_WriteProperty_Shed_Duration( int instance, unsigned duration) { @@ -103,9 +288,7 @@ static void Load_Control_WriteProperty_Shed_Duration( status = Load_Control_Write_Property(&wp_data); zassert_true(status, NULL); } -#endif -#if 0 /* TODO: How should this get exposed? */ static void Load_Control_WriteProperty_Duty_Window( int instance, unsigned duration) { @@ -128,9 +311,7 @@ static void Load_Control_WriteProperty_Duty_Window( status = Load_Control_Write_Property(&wp_data); zassert_true(status, NULL); } -#endif -#if 0 /* TODO: How should this get exposed? */ static void Load_Control_WriteProperty_Start_Time_Wildcards( int instance) { @@ -161,9 +342,7 @@ static void Load_Control_WriteProperty_Start_Time_Wildcards( status = Load_Control_Write_Property(&wp_data); zassert_true(status, NULL); } -#endif -#if 0 /* TODO: How should this get exposed? */ static void Load_Control_WriteProperty_Start_Time( int instance, uint16_t year, @@ -201,179 +380,355 @@ static void Load_Control_WriteProperty_Start_Time( status = Load_Control_Write_Property(&wp_data); zassert_true(status, NULL); } -#endif static void testLoadControlStateMachine(void) { -#if 0 /*TODO: Need visiblity inside LoadControlStateMachine */ - unsigned i = 0, j = 0; +//TODO: unsigned i = 0, j = 0; uint8_t level = 0; Load_Control_Init(); - /* validate the triggers for each state change */ - for (j = 0; j < 20; j++) { - Load_Control_State_Machine(0); - for (i = 0; i < MAX_LOAD_CONTROLS; i++) { - zassert_equal(Load_Control_State[i], SHED_INACTIVE, NULL); - } - } + +//TODO: /* validate the triggers for each state change */ +//TODO: for (j = 0; j < 20; j++) { +//TODO: Load_Control_State_Machine(0); +//TODO: for (i = 0; i < MAX_LOAD_CONTROLS; i++) { +//TODO: zassert_equal(Load_Control_State[i], SHED_INACTIVE, NULL); +//TODO: } +//TODO: } + /* SHED_REQUEST_PENDING */ /* CancelShed - Start time has wildcards */ - Load_Control_WriteProperty_Enable(pTest, 0, true); - Load_Control_WriteProperty_Shed_Duration(pTest, 0, 60); - Load_Control_WriteProperty_Start_Time_Wildcards(pTest, 0); + Load_Control_WriteProperty_Enable(0, true); + Load_Control_WriteProperty_Shed_Duration(0, 60); + Load_Control_WriteProperty_Start_Time_Wildcards(0); Load_Control_State_Machine(0); - zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); +//TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); Load_Control_State_Machine(0); - zassert_equal(Load_Control_State[0], SHED_INACTIVE, NULL); +//TODO: zassert_equal(Load_Control_State[0], SHED_INACTIVE, NULL); /* CancelShed - Requested_Shed_Level equal to default value */ Load_Control_Init(); - Load_Control_WriteProperty_Request_Shed_Level(pTest, 0, 0); - Load_Control_WriteProperty_Start_Time(pTest, 0, 2007, 2, 27, 15, 0, 0, 0); - Load_Control_WriteProperty_Shed_Duration(pTest, 0, 5); - datetime_set_values(&Current_Time, 2007, 2, 27, 15, 0, 0, 0); + Load_Control_WriteProperty_Request_Shed_Level(0, 0); + Load_Control_WriteProperty_Start_Time(0, 2007, 2, 27, 15, 0, 0, 0); + Load_Control_WriteProperty_Shed_Duration(0, 5); +//TODO: datetime_set_values(&Current_Time, 2007, 2, 27, 15, 0, 0, 0); Load_Control_State_Machine(0); - zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); +//TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); Load_Control_State_Machine(0); - zassert_equal(Load_Control_State[0], SHED_INACTIVE, NULL); +//TODO: zassert_equal(Load_Control_State[0], SHED_INACTIVE, NULL); /* CancelShed - Non-default values, but Start time is passed */ Load_Control_Init(); - Load_Control_WriteProperty_Enable(pTest, 0, true); - Load_Control_WriteProperty_Request_Shed_Level(pTest, 0, 1); - Load_Control_WriteProperty_Shed_Duration(pTest, 0, 5); - Load_Control_WriteProperty_Start_Time(pTest, 0, 2007, 2, 27, 15, 0, 0, 0); - datetime_set_values(&Current_Time, 2007, 2, 28, 15, 0, 0, 0); + Load_Control_WriteProperty_Enable(0, true); + Load_Control_WriteProperty_Request_Shed_Level(0, 1); + Load_Control_WriteProperty_Shed_Duration(0, 5); + Load_Control_WriteProperty_Start_Time(0, 2007, 2, 27, 15, 0, 0, 0); +//TODO: datetime_set_values(&Current_Time, 2007, 2, 28, 15, 0, 0, 0); Load_Control_State_Machine(0); - zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); +//TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); Load_Control_State_Machine(0); - zassert_equal(Load_Control_State[0], SHED_INACTIVE, NULL); +//TODO: zassert_equal(Load_Control_State[0], SHED_INACTIVE, NULL); /* ReconfigurePending - new write received while pending */ Load_Control_Init(); - Load_Control_WriteProperty_Enable(pTest, 0, true); - Load_Control_WriteProperty_Request_Shed_Level(pTest, 0, 1); - Load_Control_WriteProperty_Shed_Duration(pTest, 0, 5); - Load_Control_WriteProperty_Start_Time(pTest, 0, 2007, 2, 27, 15, 0, 0, 0); - datetime_set_values(&Current_Time, 2007, 2, 27, 5, 0, 0, 0); + Load_Control_WriteProperty_Enable(0, true); + Load_Control_WriteProperty_Request_Shed_Level(0, 1); + Load_Control_WriteProperty_Shed_Duration(0, 5); + Load_Control_WriteProperty_Start_Time(0, 2007, 2, 27, 15, 0, 0, 0); +//TODO: datetime_set_values(&Current_Time, 2007, 2, 27, 5, 0, 0, 0); Load_Control_State_Machine(0); - zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); +//TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); Load_Control_State_Machine(0); - zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); - Load_Control_WriteProperty_Request_Shed_Level(pTest, 0, 2); +//TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); + Load_Control_WriteProperty_Request_Shed_Level(0, 2); Load_Control_State_Machine(0); - zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); - Load_Control_WriteProperty_Shed_Duration(pTest, 0, 6); +//TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); + Load_Control_WriteProperty_Shed_Duration(0, 6); Load_Control_State_Machine(0); - zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); - Load_Control_WriteProperty_Duty_Window(pTest, 0, 60); +//TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); + Load_Control_WriteProperty_Duty_Window(0, 60); Load_Control_State_Machine(0); - zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); - Load_Control_WriteProperty_Start_Time(pTest, 0, 2007, 2, 27, 15, 0, 0, 1); +//TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); + Load_Control_WriteProperty_Start_Time(0, 2007, 2, 27, 15, 0, 0, 1); Load_Control_State_Machine(0); - zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); +//TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); Load_Control_State_Machine(0); - zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); +//TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); Load_Control_State_Machine(0); - zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); +//TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); /* CannotMeetShed -> FinishedUnsuccessfulShed */ Load_Control_Init(); - Load_Control_WriteProperty_Enable(pTest, 0, true); - Load_Control_WriteProperty_Request_Shed_Level(pTest, 0, 1); - Load_Control_WriteProperty_Shed_Duration(pTest, 0, 120); - Load_Control_WriteProperty_Start_Time(pTest, 0, 2007, 2, 27, 15, 0, 0, 0); - datetime_set_values(&Current_Time, 2007, 2, 27, 5, 0, 0, 0); + Load_Control_WriteProperty_Enable(0, true); + Load_Control_WriteProperty_Request_Shed_Level(0, 1); + Load_Control_WriteProperty_Shed_Duration(0, 120); + Load_Control_WriteProperty_Start_Time(0, 2007, 2, 27, 15, 0, 0, 0); +//TODO: datetime_set_values(&Current_Time, 2007, 2, 27, 5, 0, 0, 0); Load_Control_State_Machine(0); - zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); +//TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); Load_Control_State_Machine(0); - zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); +//TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); /* set to lowest value so we cannot meet the shed level */ - datetime_set_values(&Current_Time, 2007, 2, 27, 16, 0, 0, 0); +//TODO: datetime_set_values(&Current_Time, 2007, 2, 27, 16, 0, 0, 0); Analog_Output_Present_Value_Set(0, 0, 16); Load_Control_State_Machine(0); - zassert_equal(Load_Control_State[0], SHED_NON_COMPLIANT, NULL); +//TODO: zassert_equal(Load_Control_State[0], SHED_NON_COMPLIANT, NULL); Load_Control_State_Machine(0); - zassert_equal(Load_Control_State[0], SHED_NON_COMPLIANT, NULL); +//TODO: zassert_equal(Load_Control_State[0], SHED_NON_COMPLIANT, NULL); /* FinishedUnsuccessfulShed */ - datetime_set_values(&Current_Time, 2007, 2, 27, 23, 0, 0, 0); +//TODO: datetime_set_values(&Current_Time, 2007, 2, 27, 23, 0, 0, 0); Load_Control_State_Machine(0); - zassert_equal(Load_Control_State[0], SHED_INACTIVE, NULL); +//TODO: zassert_equal(Load_Control_State[0], SHED_INACTIVE, NULL); /* CannotMeetShed -> UnsuccessfulShedReconfigured */ Load_Control_Init(); - Load_Control_WriteProperty_Enable(pTest, 0, true); - Load_Control_WriteProperty_Request_Shed_Level(pTest, 0, 1); - Load_Control_WriteProperty_Shed_Duration(pTest, 0, 120); - Load_Control_WriteProperty_Start_Time(pTest, 0, 2007, 2, 27, 15, 0, 0, 0); - datetime_set_values(&Current_Time, 2007, 2, 27, 5, 0, 0, 0); + Load_Control_WriteProperty_Enable(0, true); + Load_Control_WriteProperty_Request_Shed_Level(0, 1); + Load_Control_WriteProperty_Shed_Duration(0, 120); + Load_Control_WriteProperty_Start_Time(0, 2007, 2, 27, 15, 0, 0, 0); +//TODO: datetime_set_values(&Current_Time, 2007, 2, 27, 5, 0, 0, 0); Load_Control_State_Machine(0); - zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); +//TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); Load_Control_State_Machine(0); - zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); +//TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); /* set to lowest value so we cannot meet the shed level */ - datetime_set_values(&Current_Time, 2007, 2, 27, 16, 0, 0, 0); +//TODO: datetime_set_values(&Current_Time, 2007, 2, 27, 16, 0, 0, 0); Analog_Output_Present_Value_Set(0, 0, 16); Load_Control_State_Machine(0); - zassert_equal(Load_Control_State[0], SHED_NON_COMPLIANT, NULL); +//TODO: zassert_equal(Load_Control_State[0], SHED_NON_COMPLIANT, NULL); Load_Control_State_Machine(0); - zassert_equal(Load_Control_State[0], SHED_NON_COMPLIANT, NULL); +//TODO: zassert_equal(Load_Control_State[0], SHED_NON_COMPLIANT, NULL); /* FinishedUnsuccessfulShed */ - Load_Control_WriteProperty_Start_Time(pTest, 0, 2007, 2, 27, 16, 0, 0, 0); + Load_Control_WriteProperty_Start_Time(0, 2007, 2, 27, 16, 0, 0, 0); Load_Control_State_Machine(0); - zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); +//TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); Load_Control_State_Machine(0); - zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); - datetime_set_values(&Current_Time, 2007, 2, 27, 16, 0, 1, 0); +//TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, NULL); +//TODO: datetime_set_values(&Current_Time, 2007, 2, 27, 16, 0, 1, 0); Load_Control_State_Machine(0); - zassert_equal(Load_Control_State[0], SHED_NON_COMPLIANT, NULL); +//TODO: zassert_equal(Load_Control_State[0], SHED_NON_COMPLIANT, NULL); /* CanNowComplyWithShed */ Analog_Output_Present_Value_Set(0, 100, 16); - datetime_set_values(&Current_Time, 2007, 2, 27, 16, 0, 2, 0); +//TODO: datetime_set_values(&Current_Time, 2007, 2, 27, 16, 0, 2, 0); Load_Control_State_Machine(0); - zassert_equal(Load_Control_State[0], SHED_COMPLIANT, NULL); +//TODO: zassert_equal(Load_Control_State[0], SHED_COMPLIANT, NULL); level = Analog_Output_Present_Value(0); - zassert_equal(level, 90, NULL); +//TODO: Fails: zassert_equal(level, 90, NULL); /* FinishedSuccessfulShed */ - datetime_set_values(&Current_Time, 2007, 2, 27, 23, 0, 0, 0); +//TODO: datetime_set_values(&Current_Time, 2007, 2, 27, 23, 0, 0, 0); Load_Control_State_Machine(0); - zassert_equal(Load_Control_State[0], SHED_INACTIVE, NULL); +//TODO: zassert_equal(Load_Control_State[0], SHED_INACTIVE, NULL); level = Analog_Output_Present_Value(0); - zassert_equal(level, 100, NULL); -#else - ztest_test_skip(); -#endif +//TODO: Fails: zassert_equal(level, 100, NULL); } -static void testLoadControl(void) + +#ifndef MAX_LOAD_CONTROLS +#define MAX_LOAD_CONTROLS (4) +#endif + +static void test_api_stubs(void) +{ + BACNET_CHARACTER_STRING object_name_st = { 0 }; + + zassert_equal(Load_Control_Count(), MAX_LOAD_CONTROLS, NULL); + + zassert_false(Load_Control_Valid_Instance(MAX_LOAD_CONTROLS), NULL); + zassert_equal(Load_Control_Index_To_Instance(MAX_LOAD_CONTROLS), Load_Control_Count(), NULL); + zassert_equal(Load_Control_Instance_To_Index(MAX_LOAD_CONTROLS), Load_Control_Count(), NULL); + + zassert_false(Load_Control_Valid_Instance(UINT32_MAX), NULL); + zassert_equal(Load_Control_Index_To_Instance(UINT32_MAX), Load_Control_Count(), NULL); + zassert_equal(Load_Control_Instance_To_Index(UINT32_MAX), Load_Control_Count(), NULL); + + zassert_true(Load_Control_Valid_Instance(0), NULL); + zassert_equal(Load_Control_Index_To_Instance(0), 0, NULL); + zassert_equal(Load_Control_Instance_To_Index(0), 0, NULL); + + zassert_false(Load_Control_Object_Name(0, NULL), NULL); + zassert_false(Load_Control_Object_Name(UINT32_MAX, &object_name_st), NULL); + + + zassert_true(Load_Control_Object_Name(0, &object_name_st), NULL); + zassert_true(characterstring_valid(&object_name_st), NULL); + zassert_true(characterstring_printable(&object_name_st), NULL); +} + +static void test_Load_Control_Read_Write_Property(void) { uint8_t apdu[MAX_APDU] = { 0 }; int len = 0; - uint32_t len_value = 0; - uint8_t tag_number = 0; - BACNET_OBJECT_TYPE decoded_type = 0; - uint32_t decoded_instance = 0; + int test_len = 0; BACNET_READ_PROPERTY_DATA rpdata; + /* for decode value data */ + BACNET_APPLICATION_DATA_VALUE value; + const int *pRequired = NULL; + const int *pOptional = NULL; + const int *pProprietary = NULL; + unsigned count = 0; + uint32_t object_instance = 0; - Analog_Output_Init(); + + zassert_equal(Load_Control_Read_Property(NULL), 0, NULL); + zassert_false(Load_Control_Write_Property(NULL), NULL); + + object_instance = Load_Control_Index_To_Instance(0); Load_Control_Init(); + count = Load_Control_Count(); + zassert_true(count > 0, NULL); rpdata.application_data = &apdu[0]; rpdata.application_data_len = sizeof(apdu); rpdata.object_type = OBJECT_LOAD_CONTROL; - rpdata.object_instance = 1; - rpdata.object_property = PROP_OBJECT_IDENTIFIER; - rpdata.array_index = BACNET_ARRAY_ALL; - len = Load_Control_Read_Property(&rpdata); - zassert_true(len != 0, NULL); - len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value); - zassert_equal(tag_number, BACNET_APPLICATION_TAG_OBJECT_ID, NULL); - len = decode_object_id(&apdu[len], &decoded_type, &decoded_instance); - zassert_equal(decoded_type, rpdata.object_type, NULL); - zassert_equal(decoded_instance, rpdata.object_instance, NULL); - - return; + rpdata.object_instance = object_instance; + Load_Control_Property_Lists(&pRequired, &pOptional, &pProprietary); + while ((*pRequired) != -1) { + rpdata.object_property = *pRequired; + rpdata.array_index = BACNET_ARRAY_ALL; + len = Load_Control_Read_Property(&rpdata); + zassert_not_equal(len, BACNET_STATUS_ERROR, NULL); + if (len > 0) { + test_len = bacapp_decode_application_data( + rpdata.application_data, + (uint8_t)rpdata.application_data_len, &value); + zassert_true(test_len >= 0, NULL); + } + pRequired++; + } + while ((*pOptional) != -1) { + rpdata.object_property = *pOptional; + rpdata.array_index = BACNET_ARRAY_ALL; + len = Load_Control_Read_Property(&rpdata); + zassert_not_equal(len, BACNET_STATUS_ERROR, NULL); + if (len > 0) { + test_len = bacapp_decode_application_data( + rpdata.application_data, + (uint8_t)rpdata.application_data_len, &value); + zassert_true(test_len >= 0, NULL); + } + pOptional++; + } } + +static bool init_wp_data_and_value( + BACNET_WRITE_PROPERTY_DATA *wp_data, + BACNET_APPLICATION_DATA_VALUE * value) +{ + bool status = false; + if ((wp_data != NULL) && (value != NULL)) + { + memset(&value, 0, sizeof(value)); + memset(&wp_data, 0, sizeof(wp_data)); + + wp_data->object_type = OBJECT_LOAD_CONTROL; + wp_data->object_instance = 0; + wp_data->array_index = BACNET_ARRAY_ALL; + wp_data->priority = BACNET_NO_PRIORITY; + wp_data->object_property = PROP_SHED_DURATION; + value->context_specific = false; + value->context_tag = 0; + value->tag = BACNET_APPLICATION_TAG_UNSIGNED_INT; + value->type.Unsigned_Int = 0; /* duration */ + wp_data->application_data_len = bacapp_encode_application_data(&wp_data->application_data[0], value); + zassert_true(wp_data->application_data_len >= 0, NULL); + zassert_equal(wp_data->error_class, 0, NULL); + zassert_equal(wp_data->error_code, 0, NULL); + + status = true; + } + + return status; +} + +static void test_ShedInactive_gets_RcvShedRequests(void) +{ + BACNET_APPLICATION_DATA_VALUE value = { 0 }; + BACNET_WRITE_PROPERTY_DATA wp_data = { 0 }; + + /* Verify invalid parameters cause failure */ + zassert_false(Load_Control_Write_Property(NULL), NULL); + + /* Verify invalid parameter value of application_data_len cause failure */ + zassert_true(init_wp_data_and_value(&wp_data, &value), NULL); + wp_data.application_data_len = -1; + + zassert_false(Load_Control_Write_Property(&wp_data), NULL); + zassert_equal(wp_data.error_class, ERROR_CLASS_PROPERTY, NULL); + zassert_equal(wp_data.error_code, ERROR_CODE_VALUE_OUT_OF_RANGE, NULL); + + /* Verify invalid parameter value of application_data_len cause failure */ + zassert_true(init_wp_data_and_value(&wp_data, &value), NULL); + wp_data.application_data_len = -1; + + zassert_false(Load_Control_Write_Property(&wp_data), NULL); + zassert_equal(wp_data.error_class, ERROR_CLASS_PROPERTY, NULL); + zassert_equal(wp_data.error_code, ERROR_CODE_VALUE_OUT_OF_RANGE, NULL); + + + /* Verify calls to dependencies are properly made */ + // object_property == PROP_REQUESTED_SHED_LEVEL calls bacapp_decode_context_data() + // object_property == PROP_START_TIME calls bacapp_decode_application_data() + // object_property == PROP_SHED_DURATION calls nothing + // object_property == PROP_DUTY_WINDOW calls nothing + // object_property == PROP_SHED_LEVELS calls nothing + // object_property == PROP_ENABLE calls nothing + // default returns error +} + +static void test_ShedReqPending_gets_ReconfigPending(void) +{ + ztest_test_skip(); +} + +static void test_ShedReqPending_gets_CancelShed(void) +{ + ztest_test_skip(); +} + +static void test_ShedReqPending_gets_CannotMeetShed(void) +{ + ztest_test_skip(); +} + +static void test_ShedReqPending_gets_PrepareToShed(void) +{ + ztest_test_skip(); +} + +static void test_ShedReqPending_gets_AbleToMeetShed(void) +{ + ztest_test_skip(); +} + +static void test_ShedNonCommpliant_gets_UnsuccessfulShedReconfig(void) +{ + ztest_test_skip(); +} + +static void test_ShedNonCommpliant_gets_FinishedUnsuccessfulShed(void) +{ + ztest_test_skip(); +} + +static void test_ShedNonCommpliant_gets_CanNowComplyWithShed(void) +{ + ztest_test_skip(); +} + +static void test_ShedCommpliant_gets_FinishedSuccessfulShed(void) +{ + ztest_test_skip(); +} + +static void test_ShedCommpliant_gets_SuccessfulShedReconfig(void) +{ + ztest_test_skip(); +} + +static void test_ShedCommpliant_gets_CanNoLongerComplyWithShed(void) +{ + ztest_test_skip(); +} + /** * @} */ @@ -382,8 +737,22 @@ static void testLoadControl(void) void test_main(void) { ztest_test_suite(lc_tests, - ztest_unit_test(testLoadControl), - ztest_unit_test(testLoadControlStateMachine) + ztest_unit_test(test_api_stubs), + ztest_unit_test(test_Load_Control_Count), + ztest_unit_test(test_Load_Control_Read_Write_Property), + ztest_unit_test(testLoadControlStateMachine), + ztest_unit_test(test_ShedInactive_gets_RcvShedRequests), + ztest_unit_test(test_ShedReqPending_gets_ReconfigPending), + ztest_unit_test(test_ShedReqPending_gets_CancelShed), + ztest_unit_test(test_ShedReqPending_gets_CannotMeetShed), + ztest_unit_test(test_ShedReqPending_gets_PrepareToShed), + ztest_unit_test(test_ShedReqPending_gets_AbleToMeetShed), + ztest_unit_test(test_ShedNonCommpliant_gets_UnsuccessfulShedReconfig), + ztest_unit_test(test_ShedNonCommpliant_gets_FinishedUnsuccessfulShed), + ztest_unit_test(test_ShedNonCommpliant_gets_CanNowComplyWithShed), + ztest_unit_test(test_ShedCommpliant_gets_FinishedSuccessfulShed), + ztest_unit_test(test_ShedCommpliant_gets_SuccessfulShedReconfig), + ztest_unit_test(test_ShedCommpliant_gets_CanNoLongerComplyWithShed) ); ztest_run_test_suite(lc_tests); diff --git a/test/bacnet/basic/object/lo/CMakeLists.txt b/test/bacnet/basic/object/lo/CMakeLists.txt index e36ce9ab..31dcbdef 100644 --- a/test/bacnet/basic/object/lo/CMakeLists.txt +++ b/test/bacnet/basic/object/lo/CMakeLists.txt @@ -45,6 +45,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/basic/object/ao.c ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c ${SRC_DIR}/bacnet/wp.c diff --git a/test/bacnet/basic/object/lsp/CMakeLists.txt b/test/bacnet/basic/object/lsp/CMakeLists.txt index 7e275d4a..0cd9307c 100644 --- a/test/bacnet/basic/object/lsp/CMakeLists.txt +++ b/test/bacnet/basic/object/lsp/CMakeLists.txt @@ -44,6 +44,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bactext.c ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c ${SRC_DIR}/bacnet/wp.c diff --git a/test/bacnet/basic/object/ms-input/CMakeLists.txt b/test/bacnet/basic/object/ms-input/CMakeLists.txt index 1d63c9cf..0ee0150d 100644 --- a/test/bacnet/basic/object/ms-input/CMakeLists.txt +++ b/test/bacnet/basic/object/ms-input/CMakeLists.txt @@ -43,6 +43,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bactext.c ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c ${SRC_DIR}/bacnet/wp.c diff --git a/test/bacnet/basic/object/mso/CMakeLists.txt b/test/bacnet/basic/object/mso/CMakeLists.txt index 3b379b39..9a61505a 100644 --- a/test/bacnet/basic/object/mso/CMakeLists.txt +++ b/test/bacnet/basic/object/mso/CMakeLists.txt @@ -43,6 +43,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bactext.c ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c ${SRC_DIR}/bacnet/wp.c diff --git a/test/bacnet/basic/object/msv/CMakeLists.txt b/test/bacnet/basic/object/msv/CMakeLists.txt index 9d30c260..5f849dea 100644 --- a/test/bacnet/basic/object/msv/CMakeLists.txt +++ b/test/bacnet/basic/object/msv/CMakeLists.txt @@ -44,6 +44,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/cov.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c ${SRC_DIR}/bacnet/memcopy.c diff --git a/test/bacnet/basic/object/netport/CMakeLists.txt b/test/bacnet/basic/object/netport/CMakeLists.txt index 717af062..dd1c1788 100644 --- a/test/bacnet/basic/object/netport/CMakeLists.txt +++ b/test/bacnet/basic/object/netport/CMakeLists.txt @@ -45,6 +45,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/datalink/bvlc.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c ${SRC_DIR}/bacnet/proplist.c diff --git a/test/bacnet/basic/object/objects/main.c b/test/bacnet/basic/object/objects/main.c index 1f302c78..d73f83aa 100644 --- a/test/bacnet/basic/object/objects/main.c +++ b/test/bacnet/basic/object/objects/main.c @@ -53,6 +53,7 @@ void testBACnetObjects(Test *pTest) unsigned test_point = 0; const unsigned max_test_points = 20; OBJECT_DEVICE_T *pDevice; + bool status = false; for (test_point = 0; test_point < max_test_points; test_point++) { device_id = test_point * (BACNET_MAX_INSTANCE / max_test_points); @@ -74,7 +75,8 @@ void testBACnetObjects(Test *pTest) pTest, pDevice, objects_device_id(test_point)); } for (test_point = 0; test_point < max_test_points; test_point++) { - pDevice = objects_device_delete(0); + status = objects_device_delete(0); + ct_test(pTest, status); } } diff --git a/test/bacnet/basic/object/objects/src/main.c b/test/bacnet/basic/object/objects/src/main.c index 3e34f3f2..6d478884 100644 --- a/test/bacnet/basic/object/objects/src/main.c +++ b/test/bacnet/basic/object/objects/src/main.c @@ -20,53 +20,60 @@ /** * @brief Test */ -#if 0 /*TODO: Change to use external methods */ static void testBACnetObjectsCompare( - OBJECT_DEVICE_T *pDevice, uint32_t device_id) + OBJECT_DEVICE_T *pDevice, uint32_t expected_device_id) { zassert_not_null(pDevice, NULL); if (pDevice) { zassert_not_null(pDevice->Object_List, NULL); - zassert_equal(pDevice->Object_Identifier.instance, device_id, NULL); + zassert_equal(pDevice->Object_Identifier.instance, expected_device_id, NULL); zassert_equal(pDevice->Object_Identifier.type, OBJECT_DEVICE, NULL); zassert_equal(pDevice->Object_Type, OBJECT_DEVICE, NULL); } } -#endif static void testBACnetObjects(void) { -#if 0 /*TODO: Change to use external methods */ uint32_t device_id = 0; unsigned test_point = 0; const unsigned max_test_points = 20; OBJECT_DEVICE_T *pDevice; + + /* Verify deleting a non-existant object returns the correct value */ + zassert_false(objects_device_delete(0), NULL); + + /* Create devices */ for (test_point = 0; test_point < max_test_points; test_point++) { device_id = test_point * (BACNET_MAX_INSTANCE / max_test_points); pDevice = objects_device_new(device_id); testBACnetObjectsCompare(pDevice, device_id); + + /* Verify the last created device can be fetched by ID */ pDevice = objects_device_by_instance(device_id); testBACnetObjectsCompare(pDevice, device_id); } zassert_equal(max_test_points, objects_device_count(), NULL); + + /* Verify each of the expected IDs can be fetched by ID */ for (test_point = 0; test_point < max_test_points; test_point++) { device_id = test_point * (BACNET_MAX_INSTANCE / max_test_points); pDevice = objects_device_by_instance(device_id); testBACnetObjectsCompare(pDevice, device_id); } + /* Verify each of the expected IDs can be fetched by index */ for (test_point = 0; test_point < max_test_points; test_point++) { device_id = test_point * (BACNET_MAX_INSTANCE / max_test_points); pDevice = objects_device_data(test_point); - testBACnetObjectsCompare( - pDevice, Keylist_Key(Device_List, test_point)); + testBACnetObjectsCompare(pDevice, device_id); } + /* Delete every object */ for (test_point = 0; test_point < max_test_points; test_point++) { - pDevice = objects_device_delete(0); + device_id = test_point * (BACNET_MAX_INSTANCE / max_test_points); + zassert_true(objects_device_delete(0), NULL); + zassert_equal(objects_device_by_instance(device_id), NULL, NULL); } -#else - ztest_test_skip(); -#endif + zassert_false(objects_device_delete(0), NULL); } /** * @} diff --git a/test/bacnet/basic/object/osv/CMakeLists.txt b/test/bacnet/basic/object/osv/CMakeLists.txt index 1b350cf1..f3e34069 100644 --- a/test/bacnet/basic/object/osv/CMakeLists.txt +++ b/test/bacnet/basic/object/osv/CMakeLists.txt @@ -43,6 +43,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bactext.c ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c ${SRC_DIR}/bacnet/wp.c diff --git a/test/bacnet/basic/object/piv/CMakeLists.txt b/test/bacnet/basic/object/piv/CMakeLists.txt index 3e13bbf3..fee6de14 100644 --- a/test/bacnet/basic/object/piv/CMakeLists.txt +++ b/test/bacnet/basic/object/piv/CMakeLists.txt @@ -43,6 +43,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bactext.c ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c ${SRC_DIR}/bacnet/wp.c diff --git a/test/bacnet/basic/object/schedule/CMakeLists.txt b/test/bacnet/basic/object/schedule/CMakeLists.txt index 9c6d6190..133b53cc 100644 --- a/test/bacnet/basic/object/schedule/CMakeLists.txt +++ b/test/bacnet/basic/object/schedule/CMakeLists.txt @@ -44,6 +44,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bactimevalue.c ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c ${SRC_DIR}/bacnet/wp.c diff --git a/test/bacnet/basic/sys/days/CMakeLists.txt b/test/bacnet/basic/sys/days/CMakeLists.txt new file mode 100644 index 00000000..7f68b11a --- /dev/null +++ b/test/bacnet/basic/sys/days/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/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/basic/sys/days.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/basic/sys/days/src/main.c b/test/bacnet/basic/sys/days/src/main.c new file mode 100644 index 00000000..3fd938c0 --- /dev/null +++ b/test/bacnet/basic/sys/days/src/main.c @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2021 Steve Karg + * + * SPDX-License-Identifier: MIT + */ + +/* @file + * @brief test BACnet integer encode/decode APIs + */ + +#include +#include + +/** + * @addtogroup bacnet_tests + * @{ + */ + +/** +* Unit Test for the days, checking the epoch conversion +*/ +static void test_epoch_conversion_date( + uint16_t epoch_year, + uint16_t year, + uint8_t month, + uint8_t day) +{ + uint32_t days; + uint16_t test_year; + uint8_t test_month; + uint8_t test_day; + + /* conversions of day and date */ + days = days_since_epoch(epoch_year, year, month, day); + days_since_epoch_to_date(epoch_year, days, &test_year, &test_month, + &test_day); + zassert_equal(year, test_year, NULL); + zassert_equal(month, test_month, NULL); + zassert_equal(day, test_day, NULL); +} + +/** + * Unit Test for the epoch + */ +static void test_days_epoch_conversion(void) +{ + const uint16_t epoch_year = 2000; + + test_epoch_conversion_date(epoch_year, 2000, 1, 1); + test_epoch_conversion_date(epoch_year, 2048, 2, 28); + test_epoch_conversion_date(epoch_year, 2048, 2, 29); + test_epoch_conversion_date(epoch_year, 2038, 6, 15); + test_epoch_conversion_date(epoch_year, 9999, 12, 31); +} + +/** + * Unit Test for the days and year to month date year + */ +static void test_days_of_year_to_month_day_date( + uint16_t year, + uint16_t days, + uint8_t month, + uint8_t day) +{ + uint8_t test_month = 0; + uint8_t test_day = 0; + /* conversions of days and year */ + days_of_year_to_month_day(days , year, &test_month, &test_day); + zassert_equal(month, test_month, NULL); + zassert_equal(day, test_day, NULL); +} + +/** + * Unit Test for the days and year to month date year + */ +static void test_days_of_year_to_md(void) +{ + test_days_of_year_to_month_day_date(2029, 145, 5, 25); + test_days_of_year_to_month_day_date(2000, 260, 9, 16); + test_days_of_year_to_month_day_date(1995, 67, 3, 8); + test_days_of_year_to_month_day_date(2092, 366, 12, 31); + test_days_of_year_to_month_day_date(2070, 105, 4, 15); +} + +/** +* Unit Test for the days, checking the date to see if it is a valid day +*/ +static void test_date_is_valid_day( + uint16_t year, + uint8_t month) +{ + uint8_t last_day = days_per_month(year, month); + + zassert_equal(days_date_is_valid(year, month, 0), false, NULL); + zassert_equal(days_date_is_valid(year, month, 1), true, NULL); + zassert_equal(days_date_is_valid(year, month, 15), true, NULL); + zassert_equal(days_date_is_valid(year, month, last_day), true, NULL); + zassert_equal(days_date_is_valid(year, month, 32), false, NULL); +} + +/** +* Unit Test for the days, checking the date to see if it is a valid date +*/ +static void test_days_date_is_valid(void) +{ + /* first month */ + test_date_is_valid_day(0, 1); + test_date_is_valid_day(2012, 1); + test_date_is_valid_day(9999, 1); + /* middle month */ + test_date_is_valid_day(0, 6); + test_date_is_valid_day(2012, 6); + test_date_is_valid_day(9999, 6); + /* last month */ + test_date_is_valid_day(0, 12); + test_date_is_valid_day(2012, 12); + test_date_is_valid_day(9999, 12); + /* february */ + test_date_is_valid_day(0, 2); + test_date_is_valid_day(2000, 2); + test_date_is_valid_day(2001, 2); + test_date_is_valid_day(2002, 2); + test_date_is_valid_day(2003, 2); + test_date_is_valid_day(2004, 2); + test_date_is_valid_day(9999, 2); + /* invalid months */ + zassert_equal(days_per_month(0, 0), 0, NULL); + zassert_equal(days_per_month(0, 13), 0, NULL); + zassert_equal(days_per_month(0, 99), 0, NULL); + zassert_equal(days_per_month(0, 0), 0, NULL); +} + +/** +* Unit Test for days apart, checking the dates to see how many days apart +*/ +static void test_days_apart(void) +{ + zassert_equal(days_apart(2000, 1, 1, 2000, 1, 1), 0, NULL); + zassert_equal(days_apart(2000, 1, 1, 2000, 1, 2), 1, NULL); + zassert_equal(days_apart(2000, 1, 1, 2000, 2, 1), 31, NULL); + zassert_equal(days_apart(2000, 1, 1, 2000, 12, 31), 365, NULL); + zassert_equal(days_apart(2000, 1, 1, 2001, 1, 1), 366, NULL); + zassert_equal(days_apart(2001, 1, 1, 2000, 1, 1), 366, NULL); +} + +/** + * @} + */ + + +void test_main(void) +{ + ztest_test_suite(days_tests, + ztest_unit_test(test_days_epoch_conversion), + ztest_unit_test(test_days_of_year_to_md), + ztest_unit_test(test_days_date_is_valid), + ztest_unit_test(test_days_apart) + ); + + ztest_run_test_suite(days_tests); +} diff --git a/test/bacnet/basic/sys/ringbuf/src/main.c b/test/bacnet/basic/sys/ringbuf/src/main.c index 29153456..5304e8d4 100644 --- a/test/bacnet/basic/sys/ringbuf/src/main.c +++ b/test/bacnet/basic/sys/ringbuf/src/main.c @@ -77,7 +77,7 @@ static void testRingAroundBuffer( * @param element_size - size of one data element * @param element_count - number of data elements in the store */ -static bool testRingBuf( +static void testRingBuf( uint8_t *data_store, uint8_t *data_element, unsigned element_size, @@ -92,7 +92,7 @@ static bool testRingBuf( status = Ringbuf_Init(&test_buffer, data_store, element_size, element_count); if (!status) { - return false; + return; } zassert_true(Ringbuf_Empty(&test_buffer), NULL); zassert_equal(Ringbuf_Depth(&test_buffer), 0, NULL); @@ -161,8 +161,6 @@ static bool testRingBuf( testRingAroundBuffer( &test_buffer, data_element, element_size, element_count); - - return true; } /** @@ -170,13 +168,11 @@ static bool testRingBuf( */ static void testRingBufSizeSmall(void) { - bool status; uint8_t data_element[5]; uint8_t data_store[sizeof(data_element) * NEXT_POWER_OF_2(16)]; - status = testRingBuf(data_store, data_element, sizeof(data_element), + testRingBuf(data_store, data_element, sizeof(data_element), sizeof(data_store) / sizeof(data_element)); - zassert_true(status, NULL); } /** @@ -184,13 +180,11 @@ static void testRingBufSizeSmall(void) */ static void testRingBufSizeLarge(void) { - bool status; uint8_t data_element[16]; uint8_t data_store[sizeof(data_element) * NEXT_POWER_OF_2(99)]; - status = testRingBuf(data_store, data_element, sizeof(data_element), + testRingBuf(data_store, data_element, sizeof(data_element), sizeof(data_store) / sizeof(data_element)); - zassert_true(status, NULL); } /** @@ -198,13 +192,14 @@ static void testRingBufSizeLarge(void) */ static void testRingBufSizeInvalid(void) { - bool status; + RING_BUFFER test_buffer; uint8_t data_element[16]; uint8_t data_store[sizeof(data_element) * 99]; - status = testRingBuf(data_store, data_element, sizeof(data_element), - sizeof(data_store) / sizeof(data_element)); - zassert_false(status, NULL); + zassert_false(Ringbuf_Init(&test_buffer, + data_store, sizeof(data_element), + sizeof(data_store) / sizeof(data_element)), + NULL); } static void testRingBufPowerOfTwo(void) diff --git a/test/bacnet/cov/CMakeLists.txt b/test/bacnet/cov/CMakeLists.txt index 57da666a..03c9a59d 100644 --- a/test/bacnet/cov/CMakeLists.txt +++ b/test/bacnet/cov/CMakeLists.txt @@ -43,6 +43,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bactext.c ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c ${SRC_DIR}/bacnet/memcopy.c diff --git a/test/bacnet/cov/src/main.c b/test/bacnet/cov/src/main.c index b1697412..c14d58aa 100644 --- a/test/bacnet/cov/src/main.c +++ b/test/bacnet/cov/src/main.c @@ -157,10 +157,8 @@ static void testCOVNotifyData( zassert_equal( test_value->propertyArrayIndex, value->propertyArrayIndex, NULL); zassert_equal(test_value->priority, value->priority, NULL); -#if 0 /*TODO: Need to expose bacapp_same_value hidden under TEST conditional */ zassert_true( bacapp_same_value(&test_value->value, &value->value), NULL); -#endif test_value = test_value->next; } value = value->next; diff --git a/test/bacnet/datalink/bvlc/CMakeLists.txt b/test/bacnet/datalink/bvlc/CMakeLists.txt index d16fc704..ee70e162 100644 --- a/test/bacnet/datalink/bvlc/CMakeLists.txt +++ b/test/bacnet/datalink/bvlc/CMakeLists.txt @@ -39,6 +39,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bacreal.c ${SRC_DIR}/bacnet/bacstr.c ${SRC_DIR}/bacnet/basic/sys/bigend.c + ${SRC_DIR}/bacnet/basic/sys/days.c # Test and test library files ./src/main.c ${ZTST_DIR}/ztest_mock.c diff --git a/test/bacnet/datalink/bvlc/src/main.c b/test/bacnet/datalink/bvlc/src/main.c index 439b77bc..eb8cb2c1 100644 --- a/test/bacnet/datalink/bvlc/src/main.c +++ b/test/bacnet/datalink/bvlc/src/main.c @@ -20,16 +20,13 @@ /** * @brief Test */ -#if 0 /*TODO: Expose test_BVLC_Header */ static void test_BVLC_Address( BACNET_IP_ADDRESS *bip_address_1, BACNET_IP_ADDRESS *bip_address_2) { zassert_false(bvlc_address_different(bip_address_1, bip_address_2), NULL); } -#endif -#if 0 /*TODO: Expose test_BVLC_Header */ static void test_BVLC_Broadcast_Distribution_Mask( BACNET_IP_BROADCAST_DISTRIBUTION_MASK *bd_mask_1, BACNET_IP_BROADCAST_DISTRIBUTION_MASK *bd_mask_2) @@ -37,9 +34,7 @@ static void test_BVLC_Broadcast_Distribution_Mask( zassert_false( bvlc_broadcast_distribution_mask_different(bd_mask_1, bd_mask_2), NULL); } -#endif -#if 0 /*TODO: Expose test_BVLC_Header */ static void test_BVLC_Broadcast_Distribution_Table_Entry( BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_entry_1, BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_entry_2) @@ -54,9 +49,7 @@ static void test_BVLC_Broadcast_Distribution_Table_Entry( return; } -#endif -#if 0 /*TODO: Expose test_BVLC_Header */ static void test_BVLC_Foreign_Device_Table_Entry( BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *fdt_entry_1, BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *fdt_entry_2) @@ -73,9 +66,7 @@ static void test_BVLC_Foreign_Device_Table_Entry( return; } -#endif -#if 0 /*TODO: Expose test_BVLC_Header */ static int test_BVLC_Header( uint8_t *pdu, uint16_t pdu_len, @@ -94,9 +85,7 @@ static int test_BVLC_Header( return bytes_consumed; } -#endif -#if 0 /*TODO: Expose test_BVLC_Header */ static void test_BVLC_Result_Code(uint16_t result_code) { uint8_t pdu[50] = { 0 }; @@ -115,11 +104,9 @@ static void test_BVLC_Result_Code(uint16_t result_code) zassert_equal(len, test_len, NULL); zassert_equal(result_code, test_result_code, NULL); } -#endif static void test_BVLC_Result(void) { -#if 0 /*TODO: refactor */ uint16_t result_code[] = { BVLC_RESULT_SUCCESSFUL_COMPLETION, BVLC_RESULT_WRITE_BROADCAST_DISTRIBUTION_TABLE_NAK, BVLC_RESULT_READ_BROADCAST_DISTRIBUTION_TABLE_NAK, @@ -133,12 +120,8 @@ static void test_BVLC_Result(void) for (i = 0; i < result_code_max; i++) { test_BVLC_Result_Code(result_code[i]); } -#else - ztest_test_skip(); -#endif } -#if 0 /*TODO: Expose test_BVLC_Header */ static void test_BVLC_Original_Unicast_NPDU_Message( uint8_t *npdu, uint16_t npdu_len) { @@ -166,11 +149,9 @@ static void test_BVLC_Original_Unicast_NPDU_Message( zassert_equal(npdu[i], test_npdu[i], NULL); } } -#endif static void test_BVLC_Original_Unicast_NPDU(void) { -#if 0 /*TODO: Expose test_BVLC_Header */ uint8_t npdu[50] = { 0 }; uint16_t npdu_len = 0; uint16_t i = 0; @@ -182,12 +163,8 @@ static void test_BVLC_Original_Unicast_NPDU(void) } npdu_len = sizeof(npdu); test_BVLC_Original_Unicast_NPDU_Message(npdu, npdu_len); -#else - ztest_test_skip(); -#endif } -#if 0 /*TODO: Expose test_BVLC_Header */ static void test_BVLC_Original_Broadcast_NPDU_Message( uint8_t *npdu, uint16_t npdu_len) { @@ -215,11 +192,9 @@ static void test_BVLC_Original_Broadcast_NPDU_Message( zassert_equal(npdu[i], test_npdu[i], NULL); } } -#endif static void test_BVLC_Original_Broadcast_NPDU(void) { -#if 0 /*TODO: Expose test_BVLC_Header */ uint8_t npdu[50] = { 0 }; uint16_t npdu_len = 0; uint16_t i = 0; @@ -231,12 +206,8 @@ static void test_BVLC_Original_Broadcast_NPDU(void) } npdu_len = sizeof(npdu); test_BVLC_Original_Broadcast_NPDU_Message(npdu, npdu_len); -#else - ztest_test_skip(); -#endif } -#if 0 /*TODO: Expose test_BVLC_Header */ static void test_BVLC_Forwarded_NPDU_Message( uint8_t *npdu, uint16_t npdu_len, @@ -269,11 +240,9 @@ static void test_BVLC_Forwarded_NPDU_Message( zassert_equal(npdu[i], test_npdu[i], NULL); } } -#endif static void test_BVLC_Forwarded_NPDU(void) { -#if 0 /*TODO: Expose test_BVLC_Header */ uint8_t npdu[50] = { 0 }; BACNET_IP_ADDRESS bip_address = { 0 }; uint16_t npdu_len = 0; @@ -290,12 +259,8 @@ static void test_BVLC_Forwarded_NPDU(void) } npdu_len = sizeof(npdu); test_BVLC_Forwarded_NPDU_Message(npdu, npdu_len, &bip_address); -#else - ztest_test_skip(); -#endif } -#if 0 /*TODO: Expose test_BVLC_Header */ static void test_BVLC_Register_Foreign_Device_Message( uint16_t ttl_seconds) { @@ -318,22 +283,16 @@ static void test_BVLC_Register_Foreign_Device_Message( zassert_equal(msg_len, test_len, NULL); zassert_equal(ttl_seconds, test_ttl_seconds, NULL); } -#endif static void test_BVLC_Register_Foreign_Device(void) { -#if 0 /*TODO: Expose test_BVLC_Header */ uint16_t ttl_seconds = 0; test_BVLC_Register_Foreign_Device_Message(ttl_seconds); ttl_seconds = 600; test_BVLC_Register_Foreign_Device_Message(ttl_seconds); -#else - ztest_test_skip(); -#endif } -#if 0 /*TODO: Expose test_BVLC_Header */ static void test_BVLC_Delete_Foreign_Device_Message( BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *fdt_entry) { @@ -361,11 +320,9 @@ static void test_BVLC_Delete_Foreign_Device_Message( test_BVLC_Address( &fdt_entry->dest_address, &test_fdt_entry.dest_address); } -#endif static void test_BVLC_Delete_Foreign_Device(void) { -#if 0 /*TODO: Expose test_BVLC_Header */ BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY fdt_entry = { 0 }; unsigned int i = 0; @@ -380,12 +337,8 @@ static void test_BVLC_Delete_Foreign_Device(void) fdt_entry.ttl_seconds_remaining = 42; fdt_entry.next = NULL; test_BVLC_Delete_Foreign_Device_Message(&fdt_entry); -#else - ztest_test_skip(); -#endif } -#if 0 /*TODO: Expose test_BVLC_Header */ static void test_BVLC_Secure_BVLL_Message( uint8_t *sbuf, uint16_t sbuf_len) { @@ -413,11 +366,9 @@ static void test_BVLC_Secure_BVLL_Message( zassert_equal(sbuf[i], test_sbuf[i], NULL); } } -#endif static void test_BVLC_Secure_BVLL(void) { -#if 0 /*TODO: Expose test_BVLC_Header */ uint8_t sbuf[50] = { 0 }; uint16_t sbuf_len = 0; uint16_t i = 0; @@ -429,14 +380,10 @@ static void test_BVLC_Secure_BVLL(void) } sbuf_len = sizeof(sbuf); test_BVLC_Secure_BVLL_Message(sbuf, sbuf_len); -#else - ztest_test_skip(); -#endif } static void test_BVLC_Read_Broadcast_Distribution_Table_Message(void) { -#if 0 /*TODO: Expose test_BVLC_Header */ uint8_t pdu[60] = { 0 }; uint8_t message_type = 0; uint16_t length = 0; @@ -449,12 +396,8 @@ static void test_BVLC_Read_Broadcast_Distribution_Table_Message(void) zassert_equal(test_len, 4, NULL); zassert_equal(message_type, BVLC_READ_BROADCAST_DIST_TABLE, NULL); zassert_equal(length, msg_len, NULL); -#else - ztest_test_skip(); -#endif } -#if 0 /*TODO: Expose test_BVLC_Header */ static void test_BVLC_Distribute_Broadcast_To_Network_Message( uint8_t *npdu, uint16_t npdu_len) { @@ -483,11 +426,9 @@ static void test_BVLC_Distribute_Broadcast_To_Network_Message( zassert_equal(npdu[i], test_npdu[i], NULL); } } -#endif static void test_BVLC_Distribute_Broadcast_To_Network(void) { -#if 0 /*TODO: Expose test_BVLC_Header */ uint8_t npdu[50] = { 0 }; uint16_t npdu_len = 0; uint16_t i = 0; @@ -499,9 +440,6 @@ static void test_BVLC_Distribute_Broadcast_To_Network(void) } npdu_len = sizeof(npdu); test_BVLC_Distribute_Broadcast_To_Network_Message(npdu, npdu_len); -#else - ztest_test_skip(); -#endif } static void test_BVLC_Broadcast_Distribution_Table_Encode(void) @@ -561,7 +499,6 @@ static void test_BVLC_Broadcast_Distribution_Table_Encode(void) } } -#if 0 /*TODO: Expose test_BVLC_Header */ static void test_BVLC_Write_Broadcast_Distribution_Table_Message( uint8_t *npdu, uint16_t npdu_len, @@ -596,11 +533,9 @@ static void test_BVLC_Write_Broadcast_Distribution_Table_Message( &bdt_list[i], &test_bdt_list[i]); } } -#endif static void test_BVLC_Write_Broadcast_Distribution_Table(void) { -#if 0 /*TODO: Expose test_BVLC_Header */ uint8_t npdu[480] = { 0 }; uint16_t npdu_len = 0; uint16_t i = 0; @@ -652,12 +587,8 @@ static void test_BVLC_Write_Broadcast_Distribution_Table(void) npdu_len = sizeof(npdu); test_BVLC_Write_Broadcast_Distribution_Table_Message( npdu, npdu_len, &bdt_list[0]); -#else - ztest_test_skip(); -#endif } -#if 0 /*TODO: Expose test_BVLC_Header */ static void test_BVLC_Read_Foreign_Device_Table_Ack_Message( uint8_t *npdu, uint16_t npdu_len, @@ -690,11 +621,9 @@ static void test_BVLC_Read_Foreign_Device_Table_Ack_Message( &fdt_list[i], &test_fdt_list[i]); } } -#endif static void test_BVLC_Read_Foreign_Device_Table_Ack(void) { -#if 0 /*TODO: Expose test_BVLC_Header */ uint8_t npdu[480] = { 0 }; uint16_t npdu_len = 0; uint16_t i = 0; @@ -745,14 +674,10 @@ static void test_BVLC_Read_Foreign_Device_Table_Ack(void) } test_count = bvlc_foreign_device_table_valid_count(fdt_list); zassert_equal(test_count, 0, NULL); -#else - ztest_test_skip(); -#endif } static void test_BVLC_Address_Copy(void) { -#if 0 /*TODO: Expose test_BVLC_Header */ unsigned int i = 0; BACNET_IP_ADDRESS src = { 0 }; BACNET_IP_ADDRESS dst = { 0 }; @@ -784,14 +709,10 @@ static void test_BVLC_Address_Copy(void) zassert_true(status, NULL); dst.address[i] = 1 + i; } -#else - ztest_test_skip(); -#endif } static void test_BVLC_Address_Get_Set(void) { -#if 0 /*TODO: Expose test_BVLC_Header */ uint16_t i = 0; BACNET_ADDRESS bsrc = { 0 }; BACNET_IP_ADDRESS src = { 0 }; @@ -893,10 +814,8 @@ static void test_BVLC_Address_Get_Set(void) zassert_equal(octet1, test_octet1, NULL); zassert_equal(octet2, test_octet2, NULL); zassert_equal(octet3, test_octet3, NULL); -#else - ztest_test_skip(); -#endif } + /** * @} */ @@ -913,6 +832,7 @@ void test_main(void) ztest_unit_test(test_BVLC_Read_Foreign_Device_Table_Ack), ztest_unit_test(test_BVLC_Delete_Foreign_Device), ztest_unit_test(test_BVLC_Distribute_Broadcast_To_Network), + ztest_unit_test(test_BVLC_Broadcast_Distribution_Table_Encode), ztest_unit_test(test_BVLC_Original_Unicast_NPDU), ztest_unit_test(test_BVLC_Original_Broadcast_NPDU), ztest_unit_test(test_BVLC_Secure_BVLL), diff --git a/test/bacnet/datetime/CMakeLists.txt b/test/bacnet/datetime/CMakeLists.txt index 85f897c0..ff12def0 100644 --- a/test/bacnet/datetime/CMakeLists.txt +++ b/test/bacnet/datetime/CMakeLists.txt @@ -40,6 +40,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bacreal.c ${SRC_DIR}/bacnet/bacstr.c ${SRC_DIR}/bacnet/basic/sys/bigend.c + ${SRC_DIR}/bacnet/basic/sys/days.c # Test and test library files ./src/main.c ${ZTST_DIR}/ztest_mock.c diff --git a/test/bacnet/datetime/src/main.c b/test/bacnet/datetime/src/main.c index 7adbea71..5ac336e1 100644 --- a/test/bacnet/datetime/src/main.c +++ b/test/bacnet/datetime/src/main.c @@ -132,9 +132,9 @@ static void testBACnetDateTimeAdd(void) zassert_equal(diff, 0, NULL); } +#if 0 /*TODO: Change to use external methods */ static void testBACnetDateTimeSeconds(void) { -#if 0 /*TODO: Change to use external methods */ uint8_t hour = 0, minute = 0, second = 0; uint8_t test_hour = 0, test_minute = 0, test_second = 0; uint32_t seconds = 0, test_seconds; @@ -151,10 +151,8 @@ static void testBACnetDateTimeSeconds(void) } } } -#else - ztest_test_skip(); -#endif } +#endif static void testBACnetDate(void) { @@ -354,9 +352,9 @@ static void testWildcardDateTime(void) return; } +#if 0 /*TODO: Change to use external methods */ static void testDayOfYear(void) { -#if 0 /*TODO: Change to use external methods */ uint32_t days = 0; uint8_t month = 0, test_month = 0; uint8_t day = 0, test_day = 0; @@ -390,10 +388,8 @@ static void testDayOfYear(void) } } } -#else - ztest_test_skip(); -#endif } +#endif static void testDateEpochConversionCompare( uint16_t year, uint8_t month, uint8_t day, @@ -431,9 +427,9 @@ static void testDateEpochConversion(void) BACNET_EPOCH_YEAR + 0xFF - 1, 12, 31, 23, 59, 59, 0); } +#if 0 /*TODO: Change to use external methods */ static void testDateEpoch(void) { -#if 0 /*TODO: Change to use external methods */ uint32_t days = 0; uint16_t year = 0, test_year = 0; uint8_t month = 0, test_month = 0; @@ -458,10 +454,8 @@ static void testDateEpoch(void) } } } -#else - ztest_test_skip(); -#endif } +#endif static void testBACnetDayOfWeek(void) { @@ -586,18 +580,20 @@ static void testDatetimeConvertUTC(void) void test_main(void) { +#if 0 + ztest_unit_test(testDateEpoch), + ztest_unit_test(testBACnetDateTimeSeconds), + ztest_unit_test(testDayOfYear), +#endif ztest_test_suite(wp_tests, ztest_unit_test(testBACnetDate), ztest_unit_test(testBACnetTime), ztest_unit_test(testBACnetDateTime), ztest_unit_test(testBACnetDayOfWeek), - ztest_unit_test(testDateEpoch), ztest_unit_test(testDateEpochConversion), - ztest_unit_test(testBACnetDateTimeSeconds), ztest_unit_test(testBACnetDateTimeAdd), ztest_unit_test(testBACnetDateTimeWildcard), ztest_unit_test(testDatetimeCodec), - ztest_unit_test(testDayOfYear), ztest_unit_test(testWildcardDateTime) ); diff --git a/test/bacnet/event/CMakeLists.txt b/test/bacnet/event/CMakeLists.txt index b1792732..cc703706 100644 --- a/test/bacnet/event/CMakeLists.txt +++ b/test/bacnet/event/CMakeLists.txt @@ -43,6 +43,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bacdevobjpropref.c ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/timestamp.c # Test and test library files ./src/main.c diff --git a/test/bacnet/getevent/CMakeLists.txt b/test/bacnet/getevent/CMakeLists.txt index 23010271..e03f9b07 100644 --- a/test/bacnet/getevent/CMakeLists.txt +++ b/test/bacnet/getevent/CMakeLists.txt @@ -44,6 +44,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bacpropstates.c ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/lighting.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/timestamp.c diff --git a/test/bacnet/lso/CMakeLists.txt b/test/bacnet/lso/CMakeLists.txt index fc7b168e..2e9f23f7 100644 --- a/test/bacnet/lso/CMakeLists.txt +++ b/test/bacnet/lso/CMakeLists.txt @@ -32,21 +32,22 @@ include_directories( add_executable(${PROJECT_NAME} # File(s) under test - ${SRC_DIR}/bacnet/lso.c + ${SRC_DIR}/bacnet/lso.c # Support files and stubs (pathname alphabetical) - ${SRC_DIR}/bacnet/bacapp.c - ${SRC_DIR}/bacnet/bacdcode.c - ${SRC_DIR}/bacnet/bacdevobjpropref.c - ${SRC_DIR}/bacnet/bacerror.c - ${SRC_DIR}/bacnet/bacint.c - ${SRC_DIR}/bacnet/bacreal.c - ${SRC_DIR}/bacnet/bacstr.c - ${SRC_DIR}/bacnet/bactext.c + ${SRC_DIR}/bacnet/bacapp.c + ${SRC_DIR}/bacnet/bacdcode.c + ${SRC_DIR}/bacnet/bacdevobjpropref.c + ${SRC_DIR}/bacnet/bacerror.c + ${SRC_DIR}/bacnet/bacint.c + ${SRC_DIR}/bacnet/bacreal.c + ${SRC_DIR}/bacnet/bacstr.c + ${SRC_DIR}/bacnet/bactext.c ${SRC_DIR}/bacnet/basic/sys/bigend.c - ${SRC_DIR}/bacnet/datetime.c - ${SRC_DIR}/bacnet/indtext.c - ${SRC_DIR}/bacnet/lighting.c - ${SRC_DIR}/bacnet/memcopy.c + ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c + ${SRC_DIR}/bacnet/indtext.c + ${SRC_DIR}/bacnet/lighting.c + ${SRC_DIR}/bacnet/memcopy.c # Test and test library files ./src/main.c ${ZTST_DIR}/ztest_mock.c diff --git a/test/bacnet/ptransfer/CMakeLists.txt b/test/bacnet/ptransfer/CMakeLists.txt index 8cc5045b..10c5c57e 100644 --- a/test/bacnet/ptransfer/CMakeLists.txt +++ b/test/bacnet/ptransfer/CMakeLists.txt @@ -44,6 +44,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bactext.c ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c # Test and test library files diff --git a/test/bacnet/ptransfer/src/main.c b/test/bacnet/ptransfer/src/main.c index c98c7559..c1885028 100644 --- a/test/bacnet/ptransfer/src/main.c +++ b/test/bacnet/ptransfer/src/main.c @@ -169,9 +169,7 @@ static void test_Private_Transfer_Ack(void) test_data.serviceParametersLen, private_data.serviceParametersLen, NULL); len = bacapp_decode_application_data(test_data.serviceParameters, test_data.serviceParametersLen, &test_data_value); -#if 0 /*TODO: Need to expose bacapp_same_value hidden under TEST conditional */ zassert_true(bacapp_same_value(&data_value, &test_data_value), NULL); -#endif } static void test_Private_Transfer_Error(void) @@ -222,9 +220,7 @@ static void test_Private_Transfer_Error(void) test_data.serviceParametersLen, private_data.serviceParametersLen, NULL); len = bacapp_decode_application_data(test_data.serviceParameters, test_data.serviceParametersLen, &test_data_value); -#if 0 /*TODO: Need to expose bacapp_same_value hidden under TEST conditional */ zassert_true(bacapp_same_value(&data_value, &test_data_value), NULL); -#endif } static void test_Private_Transfer_Request(void) @@ -266,9 +262,7 @@ static void test_Private_Transfer_Request(void) test_data.serviceParametersLen, private_data.serviceParametersLen, NULL); len = bacapp_decode_application_data(test_data.serviceParameters, test_data.serviceParametersLen, &test_data_value); -#if 0 /*TODO: Need to expose bacapp_same_value hidden under TEST conditional */ zassert_true(bacapp_same_value(&data_value, &test_data_value), NULL); -#endif return; } @@ -310,9 +304,7 @@ static void test_Unconfirmed_Private_Transfer_Request(void) test_data.serviceParametersLen, private_data.serviceParametersLen, NULL); len = bacapp_decode_application_data(test_data.serviceParameters, test_data.serviceParametersLen, &test_data_value); -#if 0 /*TODO: Need to expose bacapp_same_value hidden under TEST conditional */ zassert_true(bacapp_same_value(&data_value, &test_data_value), NULL); -#endif return; } diff --git a/test/bacnet/rpm/CMakeLists.txt b/test/bacnet/rpm/CMakeLists.txt index e0527422..ece3f7b7 100644 --- a/test/bacnet/rpm/CMakeLists.txt +++ b/test/bacnet/rpm/CMakeLists.txt @@ -45,6 +45,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bactext.c ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c ${SRC_DIR}/bacnet/memcopy.c diff --git a/test/bacnet/rpm/src/main.c b/test/bacnet/rpm/src/main.c index 58eef523..599da415 100644 --- a/test/bacnet/rpm/src/main.c +++ b/test/bacnet/rpm/src/main.c @@ -13,121 +13,6 @@ #include #include -/* TODO: Refactor from bacapp.c (when TEST is defined) */ -/* generic - can be used by other unit tests - returns true if matching or same, false if different */ -static bool bacapp_same_value(BACNET_APPLICATION_DATA_VALUE *value, - BACNET_APPLICATION_DATA_VALUE *test_value) -{ - bool status = false; /*return value */ - - /* does the tag match? */ - if (test_value->tag == value->tag) - status = true; - if (status) { - /* second test for same-ness */ - status = false; - /* does the value match? */ - switch (test_value->tag) { -#if defined(BACAPP_NULL) - case BACNET_APPLICATION_TAG_NULL: - status = true; - break; -#endif -#if defined(BACAPP_BOOLEAN) - case BACNET_APPLICATION_TAG_BOOLEAN: - if (test_value->type.Boolean == value->type.Boolean) - status = true; - break; -#endif -#if defined(BACAPP_UNSIGNED) - case BACNET_APPLICATION_TAG_UNSIGNED_INT: - if (test_value->type.Unsigned_Int == value->type.Unsigned_Int) - status = true; - break; -#endif -#if defined(BACAPP_SIGNED) - case BACNET_APPLICATION_TAG_SIGNED_INT: - if (test_value->type.Signed_Int == value->type.Signed_Int) - status = true; - break; -#endif -#if defined(BACAPP_REAL) - case BACNET_APPLICATION_TAG_REAL: - if (test_value->type.Real == value->type.Real) - status = true; - break; -#endif -#if defined(BACAPP_DOUBLE) - case BACNET_APPLICATION_TAG_DOUBLE: - if (test_value->type.Double == value->type.Double) - status = true; - break; -#endif -#if defined(BACAPP_ENUMERATED) - case BACNET_APPLICATION_TAG_ENUMERATED: - if (test_value->type.Enumerated == value->type.Enumerated) - status = true; - break; -#endif -#if defined(BACAPP_DATE) - case BACNET_APPLICATION_TAG_DATE: - if (datetime_compare_date( - &test_value->type.Date, &value->type.Date) == 0) - status = true; - break; -#endif -#if defined(BACAPP_TIME) - case BACNET_APPLICATION_TAG_TIME: - if (datetime_compare_time( - &test_value->type.Time, &value->type.Time) == 0) - status = true; - break; -#endif -#if defined(BACAPP_OBJECT_ID) - case BACNET_APPLICATION_TAG_OBJECT_ID: - if ((test_value->type.Object_Id.type == - value->type.Object_Id.type) && - (test_value->type.Object_Id.instance == - value->type.Object_Id.instance)) { - status = true; - } - break; -#endif -#if defined(BACAPP_CHARACTER_STRING) - case BACNET_APPLICATION_TAG_CHARACTER_STRING: - status = characterstring_same(&value->type.Character_String, - &test_value->type.Character_String); - break; -#endif -#if defined(BACAPP_OCTET_STRING) - case BACNET_APPLICATION_TAG_OCTET_STRING: - status = octetstring_value_same( - &value->type.Octet_String, &test_value->type.Octet_String); - break; -#endif -#if defined(BACAPP_BIT_STRING) - case BACNET_APPLICATION_TAG_BIT_STRING: - status = bitstring_same( - &value->type.Bit_String, &test_value->type.Bit_String); - break; -#endif -#if 0 /*TODO: Enable when lighting.c builds cleanly */ -#if defined(BACAPP_LIGHTING_COMMAND) - case BACNET_APPLICATION_TAG_LIGHTING_COMMAND: - status = lighting_command_same(&value->type.Lighting_Command, - &test_value->type.Lighting_Command); - break; -#endif -#endif /*TODO: */ - default: - status = false; - break; - } - } - return status; -} - /** * @addtogroup bacnet_tests * @{ diff --git a/test/bacnet/timestamp/CMakeLists.txt b/test/bacnet/timestamp/CMakeLists.txt index 7eb14cdc..80269ebc 100644 --- a/test/bacnet/timestamp/CMakeLists.txt +++ b/test/bacnet/timestamp/CMakeLists.txt @@ -41,6 +41,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bacstr.c ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c # Test and test library files ./src/main.c ${ZTST_DIR}/ztest_mock.c diff --git a/test/bacnet/timesync/CMakeLists.txt b/test/bacnet/timesync/CMakeLists.txt index 42a9017b..3092837d 100644 --- a/test/bacnet/timesync/CMakeLists.txt +++ b/test/bacnet/timesync/CMakeLists.txt @@ -45,6 +45,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bactext.c ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c # Test and test library files diff --git a/test/bacnet/timesync/src/main.c b/test/bacnet/timesync/src/main.c index de424efd..43e6fa6a 100644 --- a/test/bacnet/timesync/src/main.c +++ b/test/bacnet/timesync/src/main.c @@ -20,7 +20,6 @@ /** * @brief Test */ -#if 0 /* Not used */ static void testTimeSyncRecipientData( BACNET_RECIPIENT_LIST *recipient1, BACNET_RECIPIENT_LIST *recipient2) @@ -66,15 +65,13 @@ static void testTimeSyncRecipientData( } } } -#endif -#if 0 /* Not used */ static void testTimeSyncRecipient(void) { uint8_t apdu[480] = { 0 }; int len = 0; - BACNET_RECIPIENT_LIST recipient[4]; - BACNET_RECIPIENT_LIST test_recipient[4]; + BACNET_RECIPIENT_LIST recipient[4] = { 0 }; + BACNET_RECIPIENT_LIST test_recipient[4] = { 0 }; /* link the recipient list */ recipient[0].next = &recipient[1]; @@ -94,21 +91,21 @@ static void testTimeSyncRecipient(void) /* network = broadcast */ recipient[1].tag = 1; recipient[1].type.address.net = BACNET_BROADCAST_NETWORK; - recipient[2].type.address.mac_len = 0; + recipient[1].type.address.mac_len = 0; /* network = non-zero */ - recipient[1].tag = 1; + recipient[2].tag = 1; recipient[2].type.address.net = 4201; recipient[2].type.address.adr[0] = 127; recipient[2].type.address.len = 1; /* network = zero */ - recipient[2].type.address.net = 0; - recipient[2].type.address.mac[0] = 10; - recipient[2].type.address.mac[1] = 1; - recipient[2].type.address.mac[2] = 0; - recipient[2].type.address.mac[3] = 86; - recipient[2].type.address.mac[4] = 0xBA; - recipient[2].type.address.mac[5] = 0xC1; - recipient[2].type.address.mac_len = 6; + recipient[3].type.address.net = 0; + recipient[3].type.address.mac[0] = 10; + recipient[3].type.address.mac[1] = 1; + recipient[3].type.address.mac[2] = 0; + recipient[3].type.address.mac[3] = 86; + recipient[3].type.address.mac[4] = 0xBA; + recipient[3].type.address.mac[5] = 0xC1; + recipient[3].type.address.mac_len = 6; /* perform positive test */ len = timesync_encode_timesync_recipients( &apdu[0], sizeof(apdu), &recipient[0]); @@ -120,7 +117,6 @@ static void testTimeSyncRecipient(void) zassert_true(len > 0, NULL); testTimeSyncRecipientData(&recipient[0], &test_recipient[0]); } -#endif static int timesync_decode_apdu_service(uint8_t *apdu, BACNET_UNCONFIRMED_SERVICE service, @@ -215,7 +211,8 @@ static void testTimeSync(void) void test_main(void) { ztest_test_suite(timesync_tests, - ztest_unit_test(testTimeSync) + ztest_unit_test(testTimeSync), + ztest_unit_test(testTimeSyncRecipient) ); ztest_run_test_suite(timesync_tests); diff --git a/test/bacnet/wp/CMakeLists.txt b/test/bacnet/wp/CMakeLists.txt index 063856fe..3a244a07 100644 --- a/test/bacnet/wp/CMakeLists.txt +++ b/test/bacnet/wp/CMakeLists.txt @@ -44,6 +44,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bactext.c ${SRC_DIR}/bacnet/basic/sys/bigend.c ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/days.c ${SRC_DIR}/bacnet/lighting.c ${SRC_DIR}/bacnet/indtext.c # Test and test library files diff --git a/test/cov.mak b/test/cov.mak index c01986a9..cc035245 100644 --- a/test/cov.mak +++ b/test/cov.mak @@ -18,6 +18,7 @@ SRCS = $(SRC_DIR)/bacnet/bacdcode.c \ $(SRC_DIR)/bacnet/memcopy.c \ $(SRC_DIR)/bacnet/bactext.c \ $(SRC_DIR)/bacnet/cov.c \ + $(SRC_DIR)/bacnet/basic/sys/days.c \ ctest.c OBJS = ${SRCS:.c=.o} diff --git a/test/datetime.mak b/test/datetime.mak index 7ce9bc00..58d36d02 100644 --- a/test/datetime.mak +++ b/test/datetime.mak @@ -4,7 +4,7 @@ SRC_DIR = ../src INCLUDES = -I$(SRC_DIR) -I. DEFINES = -DBIG_ENDIAN=0 -DBAC_TEST -DTEST_DATE_TIME -CFLAGS = -Wall $(INCLUDES) $(DEFINES) -g +CFLAGS = -Wall $(INCLUDES) $(DEFINES) -g -Wmissing-prototypes SRCS = $(SRC_DIR)/bacnet/datetime.c \ $(SRC_DIR)/bacnet/bacdcode.c \ @@ -16,6 +16,7 @@ SRCS = $(SRC_DIR)/bacnet/datetime.c \ $(SRC_DIR)/bacnet/lighting.c \ $(SRC_DIR)/bacnet/bactext.c \ $(SRC_DIR)/bacnet/indtext.c \ + $(SRC_DIR)/bacnet/basic/sys/days.c \ ctest.c OBJS = ${SRCS:.c=.o} diff --git a/test/event.mak b/test/event.mak index 14b2f495..f58dd383 100644 --- a/test/event.mak +++ b/test/event.mak @@ -22,6 +22,7 @@ SRCS = $(SRC_DIR)/bacnet/bacdcode.c \ $(SRC_DIR)/bacnet/bacdevobjpropref.c \ $(SRC_DIR)/bacnet/event.c \ $(SRC_DIR)/bacnet/authentication_factor.c \ + $(SRC_DIR)/bacnet/basic/sys/days.c \ ctest.c TARGET_NAME = event diff --git a/test/getevent.mak b/test/getevent.mak index c5d09c1d..723c7ca7 100644 --- a/test/getevent.mak +++ b/test/getevent.mak @@ -18,6 +18,7 @@ SRCS = $(SRC_DIR)/bacnet/bacdcode.c \ $(SRC_DIR)/bacnet/indtext.c \ $(SRC_DIR)/bacnet/timestamp.c \ $(SRC_DIR)/bacnet/getevent.c \ + $(SRC_DIR)/bacnet/basic/sys/days.c \ ctest.c TARGET_NAME = getevent diff --git a/test/lso.mak b/test/lso.mak index d742398e..6c306478 100644 --- a/test/lso.mak +++ b/test/lso.mak @@ -19,6 +19,7 @@ SRCS = $(SRC_DIR)/bacnet/bacdcode.c \ $(SRC_DIR)/bacnet/lighting.c \ $(SRC_DIR)/bacnet/memcopy.c \ $(SRC_DIR)/bacnet/lso.c \ + $(SRC_DIR)/bacnet/basic/sys/days.c \ ctest.c TARGET_NAME = lso diff --git a/test/proplist.mak b/test/proplist.mak index 6852f4ca..a152d8b9 100644 --- a/test/proplist.mak +++ b/test/proplist.mak @@ -15,6 +15,7 @@ SRCS = $(SRC_DIR)/bacnet/proplist.c \ $(SRC_DIR)/bacnet/bacstr.c \ $(SRC_DIR)/bacnet/datetime.c \ $(SRC_DIR)/bacnet/lighting.c \ + $(SRC_DIR)/bacnet/basic/sys/days.c \ ctest.c TARGET_NAME = proplist diff --git a/test/ptransfer.mak b/test/ptransfer.mak index 68c03974..a982df83 100644 --- a/test/ptransfer.mak +++ b/test/ptransfer.mak @@ -17,6 +17,7 @@ SRCS = $(SRC_DIR)/bacnet/bacdcode.c \ $(SRC_DIR)/bacnet/datetime.c \ $(SRC_DIR)/bacnet/lighting.c \ $(SRC_DIR)/bacnet/ptransfer.c \ + $(SRC_DIR)/bacnet/basic/sys/days.c \ ctest.c TARGET_NAME = ptransfer diff --git a/test/rpm.mak b/test/rpm.mak index 4b4d500c..236cf54d 100644 --- a/test/rpm.mak +++ b/test/rpm.mak @@ -19,6 +19,7 @@ SRCS = $(SRC_DIR)/bacnet/bacdcode.c \ $(SRC_DIR)/bacnet/lighting.c \ $(SRC_DIR)/bacnet/memcopy.c \ $(SRC_DIR)/bacnet/rpm.c \ + $(SRC_DIR)/bacnet/basic/sys/days.c \ ctest.c TARGET_NAME = rpm diff --git a/test/timesync.mak b/test/timesync.mak index 83ea9223..d30fb606 100644 --- a/test/timesync.mak +++ b/test/timesync.mak @@ -36,6 +36,7 @@ SRCS := $(SRC_DIR)/bacnet/bacdcode.c \ $(SRC_DIR)/bacnet/datetime.c \ $(SRC_DIR)/bacnet/lighting.c \ $(SRC_DIR)/bacnet/timesync.c \ + $(SRC_DIR)/bacnet/basic/sys/days.c \ ctest.c OBJS := ${SRCS:.c=.o} diff --git a/test/wp.mak b/test/wp.mak index 9939ac6f..5eecad59 100644 --- a/test/wp.mak +++ b/test/wp.mak @@ -17,6 +17,7 @@ SRCS = $(SRC_DIR)/bacnet/bacdcode.c \ $(SRC_DIR)/bacnet/bactext.c \ $(SRC_DIR)/bacnet/indtext.c \ $(SRC_DIR)/bacnet/wp.c \ + $(SRC_DIR)/bacnet/basic/sys/days.c \ ctest.c TARGET_NAME = wp diff --git a/test/ztest/include/tc_util.h b/test/ztest/include/tc_util.h index 68efef04..cec47d15 100644 --- a/test/ztest/include/tc_util.h +++ b/test/ztest/include/tc_util.h @@ -6,8 +6,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef __TC_UTIL_H__ -#define __TC_UTIL_H__ +#ifndef ZEPHYR_TESTSUITE_INCLUDE_TC_UTIL_H_ +#define ZEPHYR_TESTSUITE_INCLUDE_TC_UTIL_H_ #include @@ -92,6 +92,31 @@ static inline const char *TC_RESULT_TO_STR(int result) } } +static uint32_t tc_start_time; +static uint32_t tc_spend_time; + +static inline void get_start_time_cyc(void) +{ + /* Besides the ztest framework, some testcase will also call + * TC_START() in their code. But the caller thread cannot be + * in userspace. + */ +#if 0 + if (!k_is_user_context()) { + tc_start_time = k_cycle_get_32(); + } +#endif +} + +static inline void test_time_ms(void) +{ +#if 0 + uint32_t spend_cycle = k_cycle_get_32() - tc_start_time; + + tc_spend_time = k_cyc_to_ms_ceil32(spend_cycle); +#endif +} + #ifndef TC_ERROR #define TC_ERROR(fmt, ...) \ do { \ @@ -105,7 +130,11 @@ static inline const char *TC_RESULT_TO_STR(int result) #endif #ifndef TC_START -#define TC_START(name) PRINT_DATA("starting test - %s\n", name) +#define TC_START(name) \ + do { \ + PRINT_DATA("START - %s\n", name); \ + get_start_time_cyc(); \ + } while (0) #endif #ifndef TC_END @@ -114,10 +143,13 @@ static inline const char *TC_RESULT_TO_STR(int result) #ifndef Z_TC_END_RESULT /* prints result and the function name */ -#define Z_TC_END_RESULT(result, func) \ - do { \ - TC_END(result, "%s - %s\n", TC_RESULT_TO_STR(result), func); \ - PRINT_LINE; \ +#define Z_TC_END_RESULT(result, func) \ + do { \ + test_time_ms(); \ + TC_END(result, " %s - %s in %u.%u seconds\n", \ + TC_RESULT_TO_STR(result), func, tc_spend_time/1000, \ + tc_spend_time%1000); \ + PRINT_LINE; \ } while (0) #endif @@ -126,6 +158,25 @@ static inline const char *TC_RESULT_TO_STR(int result) Z_TC_END_RESULT((result), __func__) #endif +#ifndef TC_SUITE_START +#define TC_SUITE_START(name) \ + do { \ + TC_PRINT("Running test suite %s\n", name); \ + PRINT_LINE; \ + } while (0) +#endif + +#ifndef TC_SUITE_END +#define TC_SUITE_END(name, result) \ + do { \ + if (result == TC_PASS) { \ + TC_PRINT("Test suite %s succeeded\n", name); \ + } else { \ + TC_PRINT("Test suite %s failed.\n", name); \ + } \ + } while (0) +#endif + #if defined(CONFIG_ARCH_POSIX) #define TC_END_POST(result) posix_exit(result) #else @@ -157,7 +208,7 @@ static inline const char *TC_RESULT_TO_STR(int result) #define TC_CMD_ITEM(name) cmd_##name #else #define TC_CMD_DEFINE(name) \ - int cmd_##name(int argc, char *argv[]) \ + int cmd_##name(int argc, char *argv[]) \ { \ TC_START(__func__); \ name(); \ @@ -167,4 +218,4 @@ static inline const char *TC_RESULT_TO_STR(int result) #define TC_CMD_ITEM(name) {STRINGIFY(name), cmd_##name, "none"} #endif -#endif /* __TC_UTIL_H__ */ +#endif /* ZEPHYR_TESTSUITE_INCLUDE_TC_UTIL_H_ */ diff --git a/test/ztest/include/test_utils.h b/test/ztest/include/test_utils.h index 98209e92..20ecff82 100644 --- a/test/ztest/include/test_utils.h +++ b/test/ztest/include/test_utils.h @@ -35,19 +35,19 @@ #include #include -static inline void show_str(const char *label, const u8_t *s, size_t len) +static inline void show_str(const char *label, const uint8_t *s, size_t len) { - u32_t i; + uint32_t i; TC_PRINT("%s = ", label); - for (i = 0U; i < (u32_t)len; ++i) { + for (i = 0U; i < (uint32_t)len; ++i) { TC_PRINT("%02x", s[i]); } TC_PRINT("\n"); } static inline -void fatal(u32_t testnum, const void *expected, size_t expectedlen, +void fatal(uint32_t testnum, const void *expected, size_t expectedlen, const void *computed, size_t computedlen) { TC_ERROR("\tTest #%d Failed!\n", testnum); @@ -57,11 +57,11 @@ void fatal(u32_t testnum, const void *expected, size_t expectedlen, } static inline -u32_t check_result(u32_t testnum, const void *expected, +uint32_t check_result(uint32_t testnum, const void *expected, size_t expectedlen, const void *computed, - size_t computedlen, u32_t verbose) + size_t computedlen, uint32_t verbose) { - u32_t result = TC_PASS; + uint32_t result = TC_PASS; ARG_UNUSED(verbose); diff --git a/test/ztest/include/ztest.h b/test/ztest/include/ztest.h index 94940fd6..b412ff40 100644 --- a/test/ztest/include/ztest.h +++ b/test/ztest/include/ztest.h @@ -2,34 +2,29 @@ * Copyright (c) 2016 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 - * - * Modified from zephyr_v2.2.0 subsys/testsuite/ztest/include/ztest.h - * because: - * 1. This port will never be run in the Zephyr kernel. - * This repository is extended to be a Zephyr module for that. - * 2. This port will not support multiple CPUs or toolchains. - * - * Modifications: - * a. Code conditionally compiled on the following CPP symbols were deleted - * (as they were kernel-specific): - * KERNEL */ /** * @file * - * @brief Zephyr testing suite + * @brief Zephyr Testsuite + * + * From zephyr_v2.6.0 subsys/testsuite/ztest/include/ztest.h + * Note: + * 1. This port will never be run in the Zephyr kernel. + * This repository is extended to be a Zephyr module for that. + * 2. This port will not support multiple CPUs or toolchains. */ /** - * @brief Zephyr Tests + * @brief Zephyr Tests (ZTest) * @defgroup all_tests Zephyr Tests * @{ * @} */ -#ifndef __ZTEST_H__ -#define __ZTEST_H__ +#ifndef ZEPHYR_TESTSUITE_INCLUDE_ZTEST_H_ +#define ZEPHYR_TESTSUITE_INCLUDE_ZTEST_H_ /** * @defgroup ztest Zephyr testing suite @@ -39,6 +34,7 @@ #error "You need to add CONFIG_ZTEST to your config file." #endif +#ifndef KERNEL #define CONFIG_STDOUT_CONSOLE 1 #define CONFIG_ZTEST_ASSERT_VERBOSE 1 #define CONFIG_ZTEST_MOCKING @@ -48,6 +44,7 @@ #define CONFIG_MP_NUM_CPUS 1 #define CONFIG_SYS_CLOCK_TICKS_PER_SEC 100 #define CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC 10000000 +#define ARCH_STACK_PTR_ALIGN 8 /* FIXME: Properly integrate with Zephyr's arch specific code */ #define CONFIG_X86 1 #define CONFIG_PRINTK 1 @@ -59,6 +56,7 @@ typedef struct esf z_arch_esf_t; #ifdef __cplusplus } #endif +#endif /* KERNEL */ #include #define PRINT printk @@ -80,4 +78,4 @@ void test_main(void); } #endif -#endif /* __ZTEST_H__ */ +#endif /* ZEPHYR_TESTSUITE_INCLUDE_ZTEST_H_ */ diff --git a/test/ztest/include/ztest_assert.h b/test/ztest/include/ztest_assert.h index 69cda736..1b5e22fa 100644 --- a/test/ztest/include/ztest_assert.h +++ b/test/ztest/include/ztest_assert.h @@ -10,8 +10,8 @@ * @brief Zephyr testing framework assertion macros */ -#ifndef __ZTEST_ASSERT_H__ -#define __ZTEST_ASSERT_H__ +#ifndef ZEPHYR_TESTSUITE_ZTEST_ASSERT_H_ +#define ZEPHYR_TESTSUITE_ZTEST_ASSERT_H_ #include #include @@ -23,16 +23,20 @@ extern "C" { #endif +const char *ztest_relative_filename(const char *file); void ztest_test_fail(void); #if CONFIG_ZTEST_ASSERT_VERBOSE == 0 -static inline void z_zassert_(bool cond, const char *file, int line) +static inline bool z_zassert_(bool cond, const char *file, int line) { if (cond == false) { PRINT("\n Assertion failed at %s:%d\n", - file, line); + ztest_relative_filename(file), line); ztest_test_fail(); + return false; } + + return true; } #define z_zassert(cond, default_msg, file, line, func, msg, ...) \ @@ -40,7 +44,7 @@ static inline void z_zassert_(bool cond, const char *file, int line) #else /* CONFIG_ZTEST_ASSERT_VERBOSE != 0 */ -static inline void z_zassert(bool cond, +static inline bool z_zassert(bool cond, const char *default_msg, const char *file, int line, const char *func, @@ -51,18 +55,20 @@ static inline void z_zassert(bool cond, va_start(vargs, msg); PRINT("\n Assertion failed at %s:%d: %s: %s\n", - file, line, func, default_msg); + ztest_relative_filename(file), line, func, default_msg); vprintk(msg, vargs); printk("\n"); va_end(vargs); ztest_test_fail(); + return false; } #if CONFIG_ZTEST_ASSERT_VERBOSE == 2 else { PRINT("\n Assertion succeeded at %s:%d (%s)\n", - file, line, func); + ztest_relative_filename(file), line, func); } #endif + return true; } #endif /* CONFIG_ZTEST_ASSERT_VERBOSE */ @@ -83,14 +89,19 @@ static inline void z_zassert(bool cond, * You probably don't need to call this macro directly. You should * instead use zassert_{condition} macros below. * + * Note that when CONFIG_MULTITHREADING=n macro returns from the function. It is + * then expected that in that case ztest asserts will be used only in the + * context of the test function. + * * @param cond Condition to check * @param msg Optional, can be NULL. Message to print if @a cond is false. * @param default_msg Message to print if @a cond is false */ - -#define zassert(cond, default_msg, msg, ...) \ - z_zassert(cond, msg ? ("(" default_msg ")") : (default_msg), \ - __FILE__, __LINE__, __func__, msg ? msg : "", ##__VA_ARGS__) +#define zassert(cond, default_msg, msg, ...) do { \ + bool _ret = z_zassert(cond, msg ? ("(" default_msg ")") : (default_msg), \ + __FILE__, __LINE__, __func__, \ + msg ? msg : "", ##__VA_ARGS__); \ +} while (0) /** * @brief Assert that this function call won't be reached @@ -115,6 +126,14 @@ static inline void z_zassert(bool cond, #define zassert_false(cond, msg, ...) zassert(!(cond), #cond " is true", \ msg, ##__VA_ARGS__) +/** + * @brief Assert that @a cond is 0 (success) + * @param cond Condition to check + * @param msg Optional message to print if the assertion fails + */ +#define zassert_ok(cond, msg, ...) zassert(!(cond), #cond " is non-zero", \ + msg, ##__VA_ARGS__) + /** * @brief Assert that @a ptr is NULL * @param ptr Pointer to compare @@ -181,7 +200,7 @@ static inline void z_zassert(bool cond, * @param msg Optional message to print if the assertion fails */ #define zassert_within(a, b, d, msg, ...) \ - zassert(((a) > ((b) - (d))) && ((a) < ((b) + (d))), \ + zassert(((a) >= ((b) - (d))) && ((a) <= ((b) + (d))), \ #a " not within " #b " +/- " #d, \ msg, ##__VA_ARGS__) @@ -222,4 +241,4 @@ static inline void z_zassert(bool cond, } #endif -#endif /* __ZTEST_ASSERT_H__ */ +#endif /* ZEPHYR_TESTSUITE_ZTEST_ASSERT_H_ */ diff --git a/test/ztest/include/ztest_error_hook.h b/test/ztest/include/ztest_error_hook.h new file mode 100644 index 00000000..3c0b984f --- /dev/null +++ b/test/ztest/include/ztest_error_hook.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ZTEST_FATAL_HOOK_H_ +#define ZEPHYR_INCLUDE_ZTEST_FATAL_HOOK_H_ + +#include + + +#if defined(CONFIG_ZTEST_FATAL_HOOK) +/** + * @brief Set the flag that treat fatal error happened as expected + * + * @details This is used for negative test cases which triggers a fatal + * error. Set the param true will still pass the test case when expected + * fatal error happened. For normal test case, set it false makes it back + * to normal behavior. + * + * @param valid flag indicate fault is expected + */ +__syscall void ztest_set_fault_valid(bool valid); + +/* @brief A hook after fatal error handler + * + * @details This is a test case hook that can run code from test case, in + * order to deal with some special case when catching the expected fatal + * error. + * + * Usage: Define your own hook function in your test case code, and do what + * you want to do after fatal error handler. + * + * By default, it will do nothing before leaving error handler. + */ +void ztest_post_fatal_error_hook(unsigned int reason, + const z_arch_esf_t *pEsf); + +#endif + + +#if defined(CONFIG_ZTEST_ASSERT_HOOK) +/** + * @brief Set the flag that treat assert fail happened as expected + * + * @details This is used for negative test cases which triggers a assert + * fail. Set the param true will still pass the test case when expected + * assert fail happened. For normal test case, set it false make it back + * to normal behavior. + * + * @param valid flag indicate assert is expected + */ +__syscall void ztest_set_assert_valid(bool valid); + +/* @brief A hook after assert fault handler + * + * @details This is a test case hook that can run code from test case, in + * order to deal with some special case when catching the expected assert + * failed. + * + * Usage: Define your own hook function in your test case code, and do what + * you want to do after assert handler. + * + * By default, it will abort the thread which assert failed. + */ +void ztest_post_assert_fail_hook(void); + +#endif + +#if defined(CONFIG_ZTEST_FATAL_HOOK) || defined(CONFIG_ZTEST_ASSERT_HOOK) +#include +#endif + +#endif /* ZEPHYR_INCLUDE_ZTEST_FATAL_HOOK_H_ */ diff --git a/test/ztest/include/ztest_mock.h b/test/ztest/include/ztest_mock.h index 8e4ac8fc..d4a6d159 100644 --- a/test/ztest/include/ztest_mock.h +++ b/test/ztest/include/ztest_mock.h @@ -10,8 +10,8 @@ * @brief Ztest mocking support */ -#ifndef __ZTEST_MOCK_H__ -#define __ZTEST_MOCK_H__ +#ifndef ZEPHYR_TESTSUITE_ZTEST_MOCK_H_ +#define ZEPHYR_TESTSUITE_ZTEST_MOCK_H_ /** * @defgroup ztest_mock Ztest mocking support @@ -33,9 +33,9 @@ * @param param Parameter for which the value should be set * @param value Value for @a param */ -#define ztest_expect_value(func, param, value) \ - z_ztest_expect_value(STRINGIFY(func), STRINGIFY(param), \ - (uintptr_t)(value)) +#define ztest_expect_value(func, param, value) \ + z_ztest_expect_value(STRINGIFY(func), STRINGIFY(param), \ + (uintptr_t)(value)) /** * @brief If @a param doesn't match the value set by ztest_expect_value(), @@ -48,17 +48,75 @@ * * @param param Parameter to check */ -#define ztest_check_expected_value(param) \ - z_ztest_check_expected_value(__func__, STRINGIFY(param), \ - (uintptr_t)(param)) +#define ztest_check_expected_value(param) \ + z_ztest_check_expected_value(__func__, STRINGIFY(param), \ + (uintptr_t)(param)) +/** + * @brief Tell function @a func to expect the data @a data for @a param + * + * When using ztest_check_expected_data(), the data pointed to by + * @a param should be same @a data in this function. Only data pointer is stored + * by this function, so it must still be valid when ztest_check_expected_data is + * called. + * + * @param func Function in question + * @param param Parameter for which the data should be set + * @param data pointer for the data for parameter @a param + */ +#define ztest_expect_data(func, param, data) \ + z_ztest_expect_data(STRINGIFY(func), STRINGIFY(param), (void *)(data)) + +/** + * @brief If data pointed by @a param don't match the data set by + * ztest_expect_data(), fail the test + * + * This will first check that @a param is expected to be null or non-null and + * then check whether the data pointed by parameter is equal to expected data. + * If either of these checks fail, the current test will fail. This + * must be called from the called function. + * + * @param param Parameter to check + * @param length Length of the data to compare + */ +#define ztest_check_expected_data(param, length) \ + z_ztest_check_expected_data(__func__, STRINGIFY(param), \ + (void *)(param), (length)) + +/** + * @brief Tell function @a func to return the data @a data for @a param + * + * When using ztest_return_data(), the data pointed to by @a param should be + * same @a data in this function. Only data pointer is stored by this function, + * so it must still be valid when ztest_copy_return_data is called. + * + * @param func Function in question + * @param param Parameter for which the data should be set + * @param data pointer for the data for parameter @a param + */ +#define ztest_return_data(func, param, data) \ + z_ztest_return_data(STRINGIFY(func), STRINGIFY(param), (void *)(data)) + +/** + * @brief Copy the data set by ztest_return_data to the memory pointed by + * @a param + * + * This will first check that @a param is not null and then copy the data. + * This must be called from the called function. + * + * @param param Parameter to return data for + * @param length Length of the data to return + */ +#define ztest_copy_return_data(param, length) \ + z_ztest_copy_return_data(__func__, STRINGIFY(param), \ + (void *)(param), (length)) /** * @brief Tell @a func that it should return @a value * * @param func Function that should return @a value * @param value Value to return from @a func */ -#define ztest_returns_value(func, value) \ +#define ztest_returns_value(func, value) \ z_ztest_returns_value(STRINGIFY(func), (uintptr_t)(value)) /** @@ -69,8 +127,7 @@ * * @returns The value the current function should return */ -#define ztest_get_return_value() \ - z_ztest_get_return_value(__func__) +#define ztest_get_return_value() z_ztest_get_return_value(__func__) /** * @brief Get the return value as a pointer for current function @@ -80,7 +137,7 @@ * * @returns The value the current function should return as a `void *` */ -#define ztest_get_return_value_ptr() \ +#define ztest_get_return_value_ptr() \ ((void *)z_ztest_get_return_value(__func__)) /** @@ -100,7 +157,15 @@ int z_cleanup_mock(void); void z_ztest_expect_value(const char *fn, const char *name, uintptr_t value); void z_ztest_check_expected_value(const char *fn, const char *param, - uintptr_t value); + uintptr_t value); + +void z_ztest_expect_data(const char *fn, const char *name, void *val); +void z_ztest_check_expected_data(const char *fn, const char *name, void *data, + uint32_t length); + +void z_ztest_return_data(const char *fn, const char *name, void *val); +void z_ztest_copy_return_data(const char *fn, const char *name, void *data, + uint32_t length); void z_ztest_returns_value(const char *fn, uintptr_t value); uintptr_t z_ztest_get_return_value(const char *fn); @@ -114,6 +179,6 @@ uintptr_t z_ztest_get_return_value(const char *fn); #define z_init_mock() #define z_cleanup_mock() 0 -#endif /* CONFIG_ZTEST_MOCKING */ +#endif /* CONFIG_ZTEST_MOCKING */ -#endif /* __ZTEST_H__ */ +#endif /* ZEPHYR_TESTSUITE_ZTEST_MOCK_H_ */ diff --git a/test/ztest/include/ztest_test.h b/test/ztest/include/ztest_test.h index 4aba87d2..efb91b5e 100644 --- a/test/ztest/include/ztest_test.h +++ b/test/ztest/include/ztest_test.h @@ -9,26 +9,24 @@ * * @brief Zephyr testing framework _test. * - * Modified from zephyr_v2.2.0 subsys/testsuite/ztest/src/ztest.c - * because: + * From zephyr_v2.6.0 subsys/testsuite/ztest/src/ztest.c + * Note: * 1. This port will never be run in the Zephyr kernel. * This repository is extended to be a Zephyr module for that. * 2. This port will not support multiple CPUs or toolchains. * * Modifications: - * a. Code conditionally compiled on the following CPP symbols were deleted - * (as they were kernel-specific): - * CONFIG_USERSPACE - * CONFIG_SMP - * KERNEL - * b. Inclusion of The following header files were removed as irrelevant. - * - * c. syscall declarations and inclusions. + * 1. Added __ZEPHYR__ conditionals around: + * a. #include + * b. syscall declarations and inclusions. */ -#ifndef __ZTEST_TEST_H__ -#define __ZTEST_TEST_H__ +#ifndef ZEPHYR_TESTSUITE_ZTEST_TEST_H_ +#define ZEPHYR_TESTSUITE_ZTEST_TEST_H_ +#if 0 /* __ZEPHYR__ */ +#include +#endif /* __ZEPHYR__ */ #ifdef __cplusplus extern "C" { @@ -39,7 +37,7 @@ struct unit_test { void (*test)(void); void (*setup)(void); void (*teardown)(void); - u32_t thread_options; + uint32_t thread_options; }; void z_ztest_run_test_suite(const char *name, struct unit_test *suite); @@ -145,6 +143,11 @@ static inline void unit_test_noop(void) #define ztest_user_unit_test(fn) \ ztest_user_unit_test_setup_teardown(fn, unit_test_noop, unit_test_noop) +#if 0 /* __ZEPHYR__ */ +__syscall void z_test_1cpu_start(void); +__syscall void z_test_1cpu_stop(void); +#endif /* __ZEPHYR__ */ + /** * @brief Define a SMP-unsafe test function * @@ -153,7 +156,12 @@ static inline void unit_test_noop(void) * * @param fn Test function */ +#ifdef CONFIG_SMP +#define ztest_1cpu_unit_test(fn) \ + ztest_unit_test_setup_teardown(fn, z_test_1cpu_start, z_test_1cpu_stop) +#else #define ztest_1cpu_unit_test(fn) ztest_unit_test(fn) +#endif /** * @brief Define a SMP-unsafe test function that should run as a user thread @@ -163,12 +171,24 @@ static inline void unit_test_noop(void) * * @param fn Test function */ +#ifdef CONFIG_SMP +#define ztest_1cpu_user_unit_test(fn) \ + ztest_user_unit_test_setup_teardown(fn, z_test_1cpu_start, z_test_1cpu_stop) +#else #define ztest_1cpu_user_unit_test(fn) ztest_user_unit_test(fn) +#endif /* definitions for use with testing application shared memory */ +#ifdef CONFIG_USERSPACE +#define ZTEST_DMEM K_APP_DMEM(ztest_mem_partition) +#define ZTEST_BMEM K_APP_BMEM(ztest_mem_partition) +#define ZTEST_SECTION K_APP_DMEM_SECTION(ztest_mem_partition) +extern struct k_mem_partition ztest_mem_partition; +#else #define ZTEST_DMEM #define ZTEST_BMEM #define ZTEST_SECTION .data +#endif /** * @brief Define a test suite @@ -200,9 +220,14 @@ static inline void unit_test_noop(void) /** * @} */ +#ifndef ZTEST_UNITTEST +#if 0 /* __ZEPHYR__ */ +#include +#endif /* _ZEPHYR__ */ +#endif #ifdef __cplusplus } #endif -#endif /* __ZTEST_ASSERT_H__ */ +#endif /* ZEPHYR_TESTSUITE_ZTEST_TEST_H_ */ diff --git a/test/ztest/src/ztest.c b/test/ztest/src/ztest.c index 2bdbd3aa..f500bc8b 100644 --- a/test/ztest/src/ztest.c +++ b/test/ztest/src/ztest.c @@ -2,26 +2,26 @@ * Copyright (c) 2016 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 - * - * Modified from zephyr_v2.2.0 subsys/testsuite/ztest/src/ztest.c - * because: - * 1. This port will never be run in the Zephyr kernel. - * This repository is extended to be a Zephyr module for that. - * 2. This port will not support multiple CPUs or toolchains. - * - * Modifications: - * a. Deleted code conditionally compiled on the following CPP symbols: - * (as they were kernel-specific): - * CONFIG_USERSPACE - * KERNEL - * b. Removed irrelevant inclusion of the following header files: - * - * - * c. Addition of test_skip functionality missing from non-kernel paths. */ #include #include +#include +#if 0 +#include +#ifdef CONFIG_USERSPACE +#include +#endif +#endif + +#ifdef KERNEL +#include +static struct k_thread ztest_thread; +#endif + +#ifdef CONFIG_ARCH_POSIX +#include +#endif /* ZTEST_DMEM and ZTEST_BMEM are used for the application shared memory test */ @@ -34,6 +34,31 @@ ZTEST_DMEM enum { static ZTEST_BMEM int test_status; +/** + * @brief Try to shorten a filename by removing the current directory + * + * This helps to reduce the very long filenames in assertion failures. It + * removes the current directory from the filename and returns the rest. + * This makes assertions a lot more readable, and sometimes they fit on one + * line. + * + * @param file Filename to check + * @returns Shortened filename, or @file if it could not be shortened + */ +const char *ztest_relative_filename(const char *file) +{ +#ifdef CONFIG_ARCH_POSIX + const char *cwd; + char buf[200]; + + cwd = getcwd(buf, sizeof(buf)); + if (cwd && strlen(file) > strlen(cwd) && + !strncmp(file, cwd, strlen(cwd))) + return file + strlen(cwd) + 1; /* move past the trailing '/' */ +#endif + return file; +} + static int cleanup_test(struct unit_test *test) { int ret = TC_PASS; @@ -41,6 +66,16 @@ static int cleanup_test(struct unit_test *test) mock_status = z_cleanup_mock(); +#ifdef KERNEL + /* we need to remove the ztest_thread information from the timeout_q. + * Because we reuse the same k_thread structure this would + * causes some problems. + */ + if (IS_ENABLED(CONFIG_MULTITHREADING)) { + k_thread_abort(&ztest_thread); + } +#endif + if (!ret && mock_status == 1) { PRINT("Test %s failed: Unused mock parameter values\n", test->name); @@ -49,11 +84,123 @@ static int cleanup_test(struct unit_test *test) PRINT("Test %s failed: Unused mock return values\n", test->name); ret = TC_FAIL; + } else { + ; } return ret; } +#ifdef KERNEL +#ifdef CONFIG_SMP +#define NUM_CPUHOLD (CONFIG_MP_NUM_CPUS - 1) +#else +#define NUM_CPUHOLD 0 +#endif +#define CPUHOLD_STACK_SZ (512 + CONFIG_TEST_EXTRA_STACKSIZE) + +static struct k_thread cpuhold_threads[NUM_CPUHOLD]; +K_KERNEL_STACK_ARRAY_DEFINE(cpuhold_stacks, NUM_CPUHOLD, CPUHOLD_STACK_SZ); +static struct k_sem cpuhold_sem; +volatile int cpuhold_active; + +/* "Holds" a CPU for use with the "1cpu" test cases. Note that we + * can't use tools like the cpumask feature because we have tests that + * may need to control that configuration themselves. We do this at + * the lowest level, but locking interrupts directly and spinning. + */ +static void cpu_hold(void *arg1, void *arg2, void *arg3) +{ + ARG_UNUSED(arg1); + ARG_UNUSED(arg2); + ARG_UNUSED(arg3); + unsigned int key = arch_irq_lock(); + uint32_t dt, start_ms = k_uptime_get_32(); + + k_sem_give(&cpuhold_sem); + +#if defined(CONFIG_ARM64) && defined(CONFIG_FPU_SHARING) + /* + * We'll be spinning with IRQs disabled. The flush-your-FPU request + * IPI will never be serviced during that time. Therefore we flush + * the FPU preemptively here to prevent any other CPU waiting after + * this CPU forever and deadlock the system. + */ + extern void z_arm64_flush_local_fpu(void); + z_arm64_flush_local_fpu(); +#endif + + while (cpuhold_active) { + k_busy_wait(1000); + } + + /* Holding the CPU via spinning is expensive, and abusing this + * for long-running test cases tends to overload the CI system + * (qemu runs separate CPUs in different threads, but the CI + * logic views it as one "job") and cause other test failures. + */ + dt = k_uptime_get_32() - start_ms; + zassert_true(dt < 3000, + "1cpu test took too long (%d ms)", dt); + arch_irq_unlock(key); +} + +void z_impl_z_test_1cpu_start(void) +{ + cpuhold_active = 1; +#ifdef CONFIG_THREAD_NAME + char tname[CONFIG_THREAD_MAX_NAME_LEN]; +#endif + k_sem_init(&cpuhold_sem, 0, 999); + + /* Spawn N-1 threads to "hold" the other CPUs, waiting for + * each to signal us that it's locked and spinning. + * + * Note that NUM_CPUHOLD can be a value that causes coverity + * to flag the following loop as DEADCODE so suppress the warning. + */ + /* coverity[DEADCODE] */ + for (int i = 0; i < NUM_CPUHOLD; i++) { + k_thread_create(&cpuhold_threads[i], + cpuhold_stacks[i], CPUHOLD_STACK_SZ, + (k_thread_entry_t) cpu_hold, NULL, NULL, NULL, + K_HIGHEST_THREAD_PRIO, 0, K_NO_WAIT); +#ifdef CONFIG_THREAD_NAME + snprintk(tname, CONFIG_THREAD_MAX_NAME_LEN, "cpuhold%02d", i); + k_thread_name_set(&cpuhold_threads[i], tname); +#endif + k_sem_take(&cpuhold_sem, K_FOREVER); + } +} + +void z_impl_z_test_1cpu_stop(void) +{ + cpuhold_active = 0; + + /* Note that NUM_CPUHOLD can be a value that causes coverity + * to flag the following loop as DEADCODE so suppress the warning. + */ + /* coverity[DEADCODE] */ + for (int i = 0; i < NUM_CPUHOLD; i++) { + k_thread_abort(&cpuhold_threads[i]); + } +} + +#ifdef CONFIG_USERSPACE +void z_vrfy_z_test_1cpu_start(void) +{ + z_impl_z_test_1cpu_start(); +} +#include + +void z_vrfy_z_test_1cpu_stop(void) +{ + z_impl_z_test_1cpu_stop(); +} +#include +#endif /* CONFIG_USERSPACE */ +#endif + static void run_test_functions(struct unit_test *test) { phase = TEST_PHASE_SETUP; @@ -62,6 +209,7 @@ static void run_test_functions(struct unit_test *test) test->test(); } +#ifndef KERNEL #include #include #include @@ -71,7 +219,6 @@ static void run_test_functions(struct unit_test *test) static jmp_buf test_fail; static jmp_buf test_pass; -static jmp_buf test_skip; static jmp_buf stack_fail; void ztest_test_fail(void) @@ -84,11 +231,6 @@ void ztest_test_pass(void) longjmp(test_pass, 1); } -void ztest_test_skip(void) -{ - longjmp(test_skip, 1); -} - static void handle_signal(int sig) { static const char *const phase_str[] = { @@ -141,11 +283,6 @@ static int run_test(struct unit_test *test) goto out; } - if (setjmp(test_skip)) { - ret = TC_SKIP; - goto out; - } - run_test_functions(test); out: ret |= cleanup_test(test); @@ -154,6 +291,112 @@ out: return ret; } + +#else /* KERNEL */ + +/* Zephyr's probably going to cause all tests to fail if one test fails, so + * skip the rest of tests if one of them fails + */ +#ifdef CONFIG_ZTEST_FAIL_FAST +#define FAIL_FAST 1 +#else +#define FAIL_FAST 0 +#endif + +K_THREAD_STACK_DEFINE(ztest_thread_stack, CONFIG_ZTEST_STACKSIZE + + CONFIG_TEST_EXTRA_STACKSIZE); +static ZTEST_BMEM int test_result; + +static void test_finalize(void) +{ + if (IS_ENABLED(CONFIG_MULTITHREADING)) { + k_thread_abort(&ztest_thread); + k_thread_abort(k_current_get()); + } +} + +void ztest_test_fail(void) +{ + test_result = -1; + test_finalize(); +} + +void ztest_test_pass(void) +{ + test_result = 0; + test_finalize(); +} + +void ztest_test_skip(void) +{ + test_result = -2; + test_finalize(); +} + +static void init_testing(void) +{ + k_object_access_all_grant(&ztest_thread); +} + +static void test_cb(void *a, void *dummy2, void *dummy) +{ + struct unit_test *test = (struct unit_test *)a; + + ARG_UNUSED(dummy2); + ARG_UNUSED(dummy); + + test_result = 1; + run_test_functions(test); + test_result = 0; +} + +static int run_test(struct unit_test *test) +{ + int ret = TC_PASS; + + TC_START(test->name); + + if (IS_ENABLED(CONFIG_MULTITHREADING)) { + k_thread_create(&ztest_thread, ztest_thread_stack, + K_THREAD_STACK_SIZEOF(ztest_thread_stack), + (k_thread_entry_t) test_cb, (struct unit_test *)test, + NULL, NULL, CONFIG_ZTEST_THREAD_PRIORITY, + test->thread_options | K_INHERIT_PERMS, + K_FOREVER); + + if (test->name != NULL) { + k_thread_name_set(&ztest_thread, test->name); + } + k_thread_start(&ztest_thread); + k_thread_join(&ztest_thread, K_FOREVER); + } else { + test_result = 1; + run_test_functions(test); + } + + phase = TEST_PHASE_TEARDOWN; + test->teardown(); + phase = TEST_PHASE_FRAMEWORK; + + if (test_result == -1) { + ret = TC_FAIL; + } + + if (!test_result || !FAIL_FAST) { + ret |= cleanup_test(test); + } + + if (test_result == -2) { + Z_TC_END_RESULT(TC_SKIP, test->name); + } else { + Z_TC_END_RESULT(ret, test->name); + } + + return ret; +} + +#endif /* !KERNEL */ + void z_ztest_run_test_suite(const char *name, struct unit_test *suite) { int fail = 0; @@ -164,8 +407,7 @@ void z_ztest_run_test_suite(const char *name, struct unit_test *suite) init_testing(); - PRINT("Running test suite %s\n", name); - PRINT_LINE; + TC_SUITE_START(name); while (suite->test) { fail += run_test(suite); suite++; @@ -174,11 +416,7 @@ void z_ztest_run_test_suite(const char *name, struct unit_test *suite) break; } } - if (fail) { - TC_PRINT("Test suite %s failed.\n", name); - } else { - TC_PRINT("Test suite %s succeeded\n", name); - } + TC_SUITE_END(name, (fail > 0 ? TC_FAIL : TC_PASS)); test_status = (test_status || fail) ? 1 : 0; } @@ -192,6 +430,11 @@ void end_report(void) } } +#ifdef CONFIG_USERSPACE +K_APPMEM_PARTITION_DEFINE(ztest_mem_partition); +#endif + +#ifndef KERNEL int main(void) { z_init_mock(); @@ -200,3 +443,48 @@ int main(void) return test_status; } +#else +void main(void) +{ +#ifdef CONFIG_USERSPACE + /* Partition containing globals tagged with ZTEST_DMEM and ZTEST_BMEM + * macros. Any variables that user code may reference need to be + * placed in this partition if no other memory domain configuration + * is made. + */ + k_mem_domain_add_partition(&k_mem_domain_default, + &ztest_mem_partition); +#ifdef Z_MALLOC_PARTITION_EXISTS + /* Allow access to malloc() memory */ + k_mem_domain_add_partition(&k_mem_domain_default, + &z_malloc_partition); +#endif +#endif /* CONFIG_USERSPACE */ + + z_init_mock(); + test_main(); + end_report(); + if (IS_ENABLED(CONFIG_ZTEST_RETEST_IF_PASSED)) { + static __noinit struct { + uint32_t magic; + uint32_t boots; + } state; + const uint32_t magic = 0x152ac523; + + if (state.magic != magic) { + state.magic = magic; + state.boots = 0; + } + state.boots += 1; + if (test_status == 0) { + PRINT("Reset board #%u to test again\n", + state.boots); + k_msleep(10); + sys_reboot(SYS_REBOOT_COLD); + } else { + PRINT("Failed after %u attempts\n", state.boots); + state.boots = 0; + } + } +} +#endif diff --git a/test/ztest/src/ztest_error_hook.c b/test/ztest/src/ztest_error_hook.c new file mode 100644 index 00000000..0c3a9733 --- /dev/null +++ b/test/ztest/src/ztest_error_hook.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include + + +#if defined(CONFIG_ZTEST_FATAL_HOOK) +/* This is a flag indicate if treating fatal error as expected, then take + * action dealing with it. It's SMP-safe. + */ +ZTEST_BMEM volatile bool fault_in_isr; +ZTEST_BMEM volatile k_tid_t valid_fault_tid; + +static inline void reset_stored_fault_status(void) +{ + valid_fault_tid = NULL; + fault_in_isr = false; +} + +void z_impl_ztest_set_fault_valid(bool valid) +{ + if (valid) { + if (k_is_in_isr()) { + fault_in_isr = true; + } else { + valid_fault_tid = k_current_get(); + } + } else { + reset_stored_fault_status(); + } +} + +#if defined(CONFIG_USERSPACE) +static inline void z_vrfy_ztest_set_fault_valid(bool valid) +{ + z_impl_ztest_set_fault_valid(valid); +} +#include +#endif + +__weak void ztest_post_fatal_error_hook(unsigned int reason, + const z_arch_esf_t *pEsf) +{ +} + +void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *pEsf) +{ + k_tid_t curr_tid = k_current_get(); + bool valid_fault = (curr_tid == valid_fault_tid) || fault_in_isr; + + printk("Caught system error -- reason %d %d\n", reason, valid_fault); + + if (valid_fault) { + printk("Fatal error expected as part of test case.\n"); + + /* reset back to normal */ + reset_stored_fault_status(); + + /* do some action after expected fatal error happened */ + ztest_post_fatal_error_hook(reason, pEsf); + } else { + printk("Fatal error was unexpected, aborting...\n"); + k_fatal_halt(reason); + } +} +#endif + + +#if defined(CONFIG_ZTEST_ASSERT_HOOK) +/* This is a flag indicate if treating assert fail as expected, then take + * action dealing with it. It's SMP-safe. + */ +ZTEST_BMEM volatile bool assert_in_isr; +ZTEST_BMEM volatile k_tid_t valid_assert_tid; + +static inline void reset_stored_assert_status(void) +{ + valid_assert_tid = NULL; + assert_in_isr = 0; +} + +void z_impl_ztest_set_assert_valid(bool valid) +{ + if (valid) { + if (k_is_in_isr()) { + assert_in_isr = true; + } else { + valid_assert_tid = k_current_get(); + } + } else { + reset_stored_assert_status(); + } +} + +#if defined(CONFIG_USERSPACE) +static inline void z_vrfy_ztest_set_assert_valid(bool valid) +{ + z_impl_ztest_set_assert_valid(valid); +} +#include +#endif + +__weak void ztest_post_assert_fail_hook(void) +{ + k_thread_abort(k_current_get()); +} + +#ifdef CONFIG_ASSERT_NO_FILE_INFO +void assert_post_action(void) +#else +void assert_post_action(const char *file, unsigned int line) +#endif +{ +#ifndef CONFIG_ASSERT_NO_FILE_INFO + ARG_UNUSED(file); + ARG_UNUSED(line); +#endif + + printk("Caught assert failed\n"); + + if ((k_current_get() == valid_assert_tid) || assert_in_isr) { + printk("Assert error expected as part of test case.\n"); + + /* reset back to normal */ + reset_stored_assert_status(); + + /* It won't go back to caller when assert failed, and it + * will terminate the thread. + */ + ztest_post_assert_fail_hook(); + } else { + printk("Assert failed was unexpected, aborting...\n"); +#ifdef CONFIG_USERSPACE + /* User threads aren't allowed to induce kernel panics; generate + * an oops instead. + */ + if (k_is_user_context()) { + k_oops(); + } +#endif + k_panic(); + } +} +#endif diff --git a/test/ztest/src/ztest_mock.c b/test/ztest/src/ztest_mock.c index 6a860cfe..09e2a567 100644 --- a/test/ztest/src/ztest_mock.c +++ b/test/ztest/src/ztest_mock.c @@ -3,22 +3,32 @@ * * SPDX-License-Identifier: Apache-2.0 * - * Modified from zephyr_v2.2.0 subsys/testsuite/ztest/src/ztest_mock.c - * because: + * From zephyr_v2.6.0 subsys/testsuite/ztest/src/ztest_mock.c + * NOTE: * 1. This port will never be run in the Zephyr kernel. * This repository is extended to be a Zephyr module for that. * 2. This port will not support multiple CPUs or toolchains. - * - * Modifications: - * a. Code conditionally compiled on the following CPP symbols were deleted - * (as they were kernel-specific): - * KERNEL */ +#ifdef KERNEL +#error Why is KERNEL defined by hered? +#endif #include +#ifdef KERNEL +#error Why is KERNEL defined by hered? +#endif #include +#ifdef KERNEL +#error Why is KERNEL defined by hered? +#endif #include +#ifdef KERNEL +#error Why is KERNEL defined by hered? +#endif #include +#ifdef KERNEL +#error Why is KERNEL defined by hered? +#endif struct parameter { struct parameter *next; @@ -27,6 +37,8 @@ struct parameter { uintptr_t value; }; +#ifndef KERNEL + #include #include @@ -50,7 +62,6 @@ static struct parameter *alloc_parameter(void) void z_init_mock(void) { - } void printk(const char *fmt, ...) @@ -66,10 +77,89 @@ void vprintk(const char *fmt, va_list ap) { vprintf(fmt, ap); } +#else + +/* + * FIXME: move to sys_io.h once the argument signature for bitmap has + * been fixed to void* or similar GH-2825 + */ +#define BITS_PER_UL (8 * sizeof(unsigned long int)) +#define DEFINE_BITFIELD(name, bits) \ + unsigned long int(name)[((bits) + BITS_PER_UL - 1) / BITS_PER_UL] + +static inline int sys_bitfield_find_first_clear(const unsigned long *bitmap, + const unsigned int bits) +{ + const size_t words = (bits + BITS_PER_UL - 1) / BITS_PER_UL; + size_t cnt; + unsigned int long neg_bitmap; + + /* + * By bitwise negating the bitmap, we are actually implementing + * ffc (find first clear) using ffs (find first set). + */ + for (cnt = 0; cnt < words; cnt++) { + neg_bitmap = ~bitmap[cnt]; + if (neg_bitmap == 0) { + /* All full. Try next word. */ + continue; + } else if (neg_bitmap == ~0UL) { + /* First bit is free */ + return cnt * BITS_PER_UL; + } else { + const unsigned int bit = (cnt * BITS_PER_UL) + + __builtin_ffsl(neg_bitmap) - 1; + /* Ensure first free bit is within total bits count */ + if (bit < bits) { + return bit; + } else { + return -1; + } + } + } + return -1; +} + +static DEFINE_BITFIELD(params_allocation, CONFIG_ZTEST_PARAMETER_COUNT); +static struct parameter params[CONFIG_ZTEST_PARAMETER_COUNT]; + +static void free_parameter(struct parameter *param) +{ + unsigned int allocation_index = param - params; + + if (param == NULL) + return; + __ASSERT(allocation_index < CONFIG_ZTEST_PARAMETER_COUNT, + "param %p given to free is not in the static buffer %p:%u", + param, params, CONFIG_ZTEST_PARAMETER_COUNT); + sys_bitfield_clear_bit((mem_addr_t)params_allocation, allocation_index); +} + +static struct parameter *alloc_parameter(void) +{ + int allocation_index; + struct parameter *param; + + allocation_index = sys_bitfield_find_first_clear( + params_allocation, CONFIG_ZTEST_PARAMETER_COUNT); + if (allocation_index == -1) { + printk("No more mock parameters available for allocation\n"); + ztest_test_fail(); + } + sys_bitfield_set_bit((mem_addr_t)params_allocation, allocation_index); + param = params + allocation_index; + (void)memset(param, 0, sizeof(*param)); + return param; +} + +void z_init_mock(void) +{ +} + +#endif static struct parameter *find_and_delete_value(struct parameter *param, - const char *fn, - const char *name) + const char *fn, const char *name) { struct parameter *value; @@ -117,7 +207,7 @@ void z_ztest_expect_value(const char *fn, const char *name, uintptr_t val) } void z_ztest_check_expected_value(const char *fn, const char *name, - uintptr_t val) + uintptr_t val) { struct parameter *param; uintptr_t expected; @@ -135,23 +225,91 @@ void z_ztest_check_expected_value(const char *fn, const char *name, /* We need to cast these values since the toolchain doesn't * provide inttypes.h */ - PRINT("%s received wrong value: Got %lu, expected %lu\n", - fn, (unsigned long)val, (unsigned long)expected); + PRINT("%s:%s received wrong value: Got %lu, expected %lu\n", fn, + name, (unsigned long)val, (unsigned long)expected); ztest_test_fail(); } } -void z_ztest_returns_value(const char *fn, uintptr_t value) +void z_ztest_expect_data(const char *fn, const char *name, void *val) +{ + insert_value(¶meter_list, fn, name, (uintptr_t)val); +} + +void z_ztest_check_expected_data(const char *fn, const char *name, void *data, + uint32_t length) +{ + struct parameter *param; + void *expected; + + param = find_and_delete_value(¶meter_list, fn, name); + if (!param) { + PRINT("Failed to find parameter %s for %s\n", name, fn); + /* No return from this function but for coverity reasons + * put a return after to avoid the warning of a null + * dereference of param below. + */ + ztest_test_fail(); + return; + } + + expected = (void *)param->value; + free_parameter(param); + + if (expected == NULL && data != NULL) { + PRINT("%s:%s received null pointer\n", fn, name); + ztest_test_fail(); + } else if (data == NULL && expected != NULL) { + PRINT("%s:%s received data while expected null pointer\n", fn, + name); + ztest_test_fail(); + } else if (data != NULL) { + if (memcmp(data, expected, length) != 0) { + PRINT("%s:%s data provided don't match\n", fn, name); + ztest_test_fail(); + } + } +} + +void z_ztest_return_data(const char *fn, const char *name, void *val) +{ + insert_value(¶meter_list, fn, name, (uintptr_t)val); +} + +void z_ztest_copy_return_data(const char *fn, const char *name, void *data, + uint32_t length) +{ + struct parameter *param; + void *return_data; + + if (data == NULL) { + PRINT("%s:%s received null pointer\n", fn, name); + ztest_test_fail(); + return; + } + + param = find_and_delete_value(¶meter_list, fn, name); + if (!param) { + PRINT("Failed to find parameter %s for %s\n", name, fn); + memset(data, 0, length); + ztest_test_fail(); + } else { + return_data = (void *)param->value; + free_parameter(param); + memcpy(data, return_data, length); + } +} + +void z_ztest_returns_value(const char *fn, uintptr_t value) { insert_value(&return_value_list, fn, "", value); } - uintptr_t z_ztest_get_return_value(const char *fn) { uintptr_t value; - struct parameter *param = find_and_delete_value(&return_value_list, - fn, ""); + struct parameter *param = + find_and_delete_value(&return_value_list, fn, ""); if (!param) { PRINT("Failed to find return value for function %s\n", fn); @@ -180,9 +338,14 @@ int z_cleanup_mock(void) int fail = 0; if (parameter_list.next) { + PRINT("Parameter not used by mock: %s:%s\n", + parameter_list.next->fn, + parameter_list.next->name); fail = 1; } if (return_value_list.next) { + PRINT("Return value no used by mock: %s\n", + return_value_list.next->fn); fail = 2; } diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 7df5a276..c4faaa5e 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -29,6 +29,7 @@ message(STATUS "BACNETSTACK: BACDL_ARCNET \"${CONFIG_BACDL_ARCNET}\"") message(STATUS "BACNETSTACK: BACDL_MSTP \"${CONFIG_BACDL_MSTP}\"") message(STATUS "BACNETSTACK: BACDL_ETHERNET \"${CONFIG_BACDL_ETHERNET}\"") message(STATUS "BACNETSTACK: BACDL_NONE \"${CONFIG_BACDL_NONE}\"") +message(STATUS "BACNETSTACK: BACNET_ADDRESS_CACHE_FILE \"${CONFIG_BACNET_ADDRESS_CACHE_FILE}\"") #Do not allow in source builds set(CMAKE_DISABLE_SOURCE_CHANGES ON) @@ -205,6 +206,8 @@ set(BACNETSTACK_SRCS ${BACNETSTACK_SRC}/bacnet/basic/services.h ${BACNETSTACK_SRC}/bacnet/basic/sys/bigend.c ${BACNETSTACK_SRC}/bacnet/basic/sys/bigend.h + ${BACNETSTACK_SRC}/bacnet/basic/sys/days.c + ${BACNETSTACK_SRC}/bacnet/basic/sys/days.h ${BACNETSTACK_SRC}/bacnet/basic/sys/debug.c ${BACNETSTACK_SRC}/bacnet/basic/sys/debug.h ${BACNETSTACK_SRC}/bacnet/basic/sys/fifo.c @@ -316,7 +319,7 @@ set(BACNETSTACK_BASIC_SRCS ${BACNETSTACK_SRC}/bacnet/basic/object/access_zone.c ${BACNETSTACK_SRC}/bacnet/basic/object/acc.c ${BACNETSTACK_SRC}/bacnet/basic/object/ao.c - ${BACNETSTACK_SRC}/bacnet/basic/object/bacfile.c # Build error: fseek not supported in Zephyr + ${BACNETSTACK_SRC}/bacnet/basic/object/bacfile.c ${BACNETSTACK_SRC}/bacnet/basic/object/bi.c ${BACNETSTACK_SRC}/bacnet/basic/object/bo.c ${BACNETSTACK_SRC}/bacnet/basic/object/bv.c @@ -424,6 +427,7 @@ zephyr_library_compile_definitions( $<$:BACNET_ROUTING> $<$:BACAPP_PRINT_ENABLED=1> $<$:BACAPP_SNPRINTF_ENABLED=1> + $<$:BACNET_ADDRESS_CACHE_FILE=1> ) zephyr_library_sources( @@ -448,6 +452,7 @@ target_compile_definitions( $<$:BACNET_ROUTING> $<$:BACAPP_PRINT_ENABLED=1> $<$:BACAPP_SNPRINTF_ENABLED=1> + $<$:BACNET_ADDRESS_CACHE_FILE=1> BACNET_STACK_STATIC_DEFINE PRINT_ENABLED=1 ) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 0b7a4786..74a555b0 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -101,6 +101,11 @@ config BACDL_BIP6_PORT help UDP port to listen on (default=47808) +config BACNET_ADDRESS_CACHE_FILE + bool "BACnet Address Cache file functionality" + help + BACnet Address Cache file functionality + rsource "subsys/Kconfig" endif # BACNETSTACK diff --git a/zephyr/tests/bacnet/basic/binding/address/prj.conf b/zephyr/tests/bacnet/basic/binding/address/prj.conf index 7c43f2ec..79faee88 100644 --- a/zephyr/tests/bacnet/basic/binding/address/prj.conf +++ b/zephyr/tests/bacnet/basic/binding/address/prj.conf @@ -1,2 +1,3 @@ CONFIG_ZTEST=y CONFIG_BACNETSTACK=y +CONFIG_BACNET_ADDRESS_CACHE_FILE=y diff --git a/zephyr/tests/bacnet/datalink/bvlc/prj.conf b/zephyr/tests/bacnet/datalink/bvlc/prj.conf index 7c43f2ec..ca120096 100644 --- a/zephyr/tests/bacnet/datalink/bvlc/prj.conf +++ b/zephyr/tests/bacnet/datalink/bvlc/prj.conf @@ -1,2 +1,25 @@ CONFIG_ZTEST=y CONFIG_BACNETSTACK=y + +# BIP Options +CONFIG_BACDL_BIP=y +CONFIG_BACDL_BIP_PORT=47808 +CONFIG_BACDL_BIP_ADDRESS_INDEX=0 + +# pthreads +CONFIG_POSIX_API=y +CONFIG_PTHREAD_IPC=y +CONFIG_POSIX_MQUEUE=y + +# networking +CONFIG_NETWORKING=y +CONFIG_NET_IPV4=y +CONFIG_NET_ARP=y +CONFIG_NET_TCP=y +CONFIG_NET_UDP=y +CONFIG_NET_DHCPV4=y + +CONFIG_NET_MGMT=y +CONFIG_NET_MGMT_EVENT=y + +CONFIG_LOG=y