/** * @file * @brief Unit test for BACnetSpecialEvent. This test also indirectly tests * BACnetCalendarEntry, BACnetDailySchedule, and BACnetTimeValue. * @author Ondřej Hruška * @date Aug 2023 * @copyright SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include "bacnet/bactimevalue.h" #include "bacnet/special_event.h" #include "bacnet/calendar_entry.h" #include "bacnet/datetime.h" #include "bacnet/bacapp.h" /** * @addtogroup bacnet_tests * @{ */ /** * @brief Test encode/decode API */ #if defined(CONFIG_ZTEST_NEW_API) ZTEST(BACnetSpecialEvent_tests, test_BACnetSpecialEvent_CalendarRef) #else static void test_BACnetSpecialEvent_CalendarRef(void) #endif { int len, apdu_len, null_len; uint8_t apdu[MAX_APDU] = { 0 }; BACNET_SPECIAL_EVENT in = { 0 }; BACNET_SPECIAL_EVENT out = { 0 }; in.periodTag = BACNET_SPECIAL_EVENT_PERIOD_CALENDAR_REFERENCE; in.period.calendarReference.instance = 5; in.period.calendarReference.type = OBJECT_CALENDAR; in.timeValues.TV_Count = 2; in.timeValues.Time_Values[0].Time.hour = 12; in.timeValues.Time_Values[0].Time.min = 30; in.timeValues.Time_Values[0].Time.sec = 15; in.timeValues.Time_Values[0].Time.hundredths = 5; in.timeValues.Time_Values[0].Value.tag = BACNET_APPLICATION_TAG_UNSIGNED_INT; in.timeValues.Time_Values[0].Value.type.Unsigned_Int = 15; in.timeValues.Time_Values[1].Time.hour = 16; in.timeValues.Time_Values[1].Time.min = 1; in.timeValues.Time_Values[1].Time.sec = 2; in.timeValues.Time_Values[1].Time.hundredths = 3; in.timeValues.Time_Values[1].Value.tag = BACNET_APPLICATION_TAG_UNSIGNED_INT; in.timeValues.Time_Values[1].Value.type.Unsigned_Int = 0; in.priority = 5; len = bacnet_special_event_encode(apdu, &in); null_len = bacnet_special_event_encode(NULL, &in); zassert_equal(len, null_len, NULL); apdu_len = bacnet_special_event_decode(apdu, len, &out); zassert_equal(len, apdu_len, NULL); zassert_equal(in.periodTag, out.periodTag, NULL); zassert_equal( in.period.calendarReference.instance, out.period.calendarReference.instance, NULL); zassert_equal( in.period.calendarReference.type, out.period.calendarReference.type, NULL); zassert_equal(in.timeValues.TV_Count, out.timeValues.TV_Count, NULL); zassert_equal( in.timeValues.Time_Values[0].Time.hour, out.timeValues.Time_Values[0].Time.hour, NULL); zassert_equal( in.timeValues.Time_Values[0].Time.min, out.timeValues.Time_Values[0].Time.min, NULL); zassert_equal( in.timeValues.Time_Values[0].Time.sec, out.timeValues.Time_Values[0].Time.sec, NULL); zassert_equal( in.timeValues.Time_Values[0].Time.hundredths, out.timeValues.Time_Values[0].Time.hundredths, NULL); zassert_equal( in.timeValues.Time_Values[0].Value.tag, out.timeValues.Time_Values[0].Value.tag, NULL); zassert_equal( in.timeValues.Time_Values[0].Value.type.Unsigned_Int, out.timeValues.Time_Values[0].Value.type.Unsigned_Int, NULL); zassert_equal( in.timeValues.Time_Values[1].Time.hour, out.timeValues.Time_Values[1].Time.hour, NULL); zassert_equal( in.timeValues.Time_Values[1].Time.min, out.timeValues.Time_Values[1].Time.min, NULL); zassert_equal( in.timeValues.Time_Values[1].Time.sec, out.timeValues.Time_Values[1].Time.sec, NULL); zassert_equal( in.timeValues.Time_Values[1].Time.hundredths, out.timeValues.Time_Values[1].Time.hundredths, NULL); zassert_equal( in.timeValues.Time_Values[1].Value.tag, out.timeValues.Time_Values[1].Value.tag, NULL); zassert_equal( in.timeValues.Time_Values[1].Value.type.Unsigned_Int, out.timeValues.Time_Values[1].Value.type.Unsigned_Int, NULL); zassert_equal(in.priority, out.priority, NULL); } /** * @brief Test encode/decode API with Calendar Entry (Date variant) */ #if defined(CONFIG_ZTEST_NEW_API) ZTEST(BACnetSpecialEvent_tests, test_BACnetSpecialEvent_Date) #else static void test_BACnetSpecialEvent_Date(void) #endif { int len, apdu_len, null_len; uint8_t apdu[MAX_APDU] = { 0 }; BACNET_SPECIAL_EVENT in = { 0 }; BACNET_SPECIAL_EVENT out = { 0 }; in.periodTag = BACNET_SPECIAL_EVENT_PERIOD_CALENDAR_ENTRY; in.period.calendarEntry.tag = BACNET_CALENDAR_DATE; in.period.calendarEntry.type.Date.year = 2155; in.period.calendarEntry.type.Date.month = 10; in.period.calendarEntry.type.Date.day = 0xff; in.period.calendarEntry.type.Date.wday = 0xff; in.timeValues.TV_Count = 0; in.priority = 16; len = bacnet_special_event_encode(apdu, &in); null_len = bacnet_special_event_encode(NULL, &in); zassert_equal(len, null_len, NULL); apdu_len = bacnet_special_event_decode(apdu, len, &out); zassert_equal(len, apdu_len, NULL); zassert_equal(in.periodTag, out.periodTag, NULL); zassert_equal( in.period.calendarEntry.tag, out.period.calendarEntry.tag, NULL); zassert_equal( in.period.calendarEntry.type.Date.wday, out.period.calendarEntry.type.Date.wday, NULL); zassert_equal( in.period.calendarEntry.type.Date.year, out.period.calendarEntry.type.Date.year, NULL); zassert_equal( in.period.calendarEntry.type.Date.month, out.period.calendarEntry.type.Date.month, NULL); zassert_equal( in.period.calendarEntry.type.Date.day, out.period.calendarEntry.type.Date.day, NULL); zassert_equal(in.timeValues.TV_Count, out.timeValues.TV_Count, NULL); zassert_equal(in.priority, out.priority, NULL); } /** * @brief Test encode/decode API with Calendar Entry (DateRange variant) */ #if defined(CONFIG_ZTEST_NEW_API) ZTEST(BACnetSpecialEvent_tests, test_BACnetSpecialEvent_DateRange) #else static void test_BACnetSpecialEvent_DateRange(void) #endif { int len, apdu_len, null_len; uint8_t apdu[MAX_APDU] = { 0 }; BACNET_SPECIAL_EVENT in = { 0 }; BACNET_SPECIAL_EVENT out = { 0 }; in.periodTag = BACNET_SPECIAL_EVENT_PERIOD_CALENDAR_ENTRY; in.period.calendarEntry.tag = BACNET_CALENDAR_DATE_RANGE; in.period.calendarEntry.type.DateRange.startdate.year = 2155; in.period.calendarEntry.type.DateRange.startdate.month = 12; in.period.calendarEntry.type.DateRange.startdate.day = 1; in.period.calendarEntry.type.DateRange.startdate.wday = 0xff; in.period.calendarEntry.type.DateRange.enddate.year = 2155; in.period.calendarEntry.type.DateRange.enddate.month = 12; in.period.calendarEntry.type.DateRange.enddate.day = 31; in.period.calendarEntry.type.DateRange.enddate.wday = 0xff; in.timeValues.TV_Count = 0; in.priority = 0; len = bacnet_special_event_encode(apdu, &in); null_len = bacnet_special_event_encode(NULL, &in); zassert_equal(len, null_len, NULL); apdu_len = bacnet_special_event_decode(apdu, len, &out); zassert_equal(len, apdu_len, "apdu_len %d != len %d", apdu_len, len); zassert_equal(in.periodTag, out.periodTag, NULL); zassert_equal( in.period.calendarEntry.tag, out.period.calendarEntry.tag, NULL); zassert_equal( in.period.calendarEntry.type.DateRange.startdate.wday, out.period.calendarEntry.type.DateRange.startdate.wday, NULL); zassert_equal( in.period.calendarEntry.type.DateRange.startdate.year, out.period.calendarEntry.type.DateRange.startdate.year, NULL); zassert_equal( in.period.calendarEntry.type.DateRange.startdate.month, out.period.calendarEntry.type.DateRange.startdate.month, NULL); zassert_equal( in.period.calendarEntry.type.DateRange.startdate.day, out.period.calendarEntry.type.DateRange.startdate.day, NULL); zassert_equal( in.period.calendarEntry.type.DateRange.enddate.wday, out.period.calendarEntry.type.DateRange.enddate.wday, NULL); zassert_equal( in.period.calendarEntry.type.DateRange.enddate.year, out.period.calendarEntry.type.DateRange.enddate.year, NULL); zassert_equal( in.period.calendarEntry.type.DateRange.enddate.month, out.period.calendarEntry.type.DateRange.enddate.month, NULL); zassert_equal( in.period.calendarEntry.type.DateRange.enddate.day, out.period.calendarEntry.type.DateRange.enddate.day, NULL); zassert_equal(in.timeValues.TV_Count, out.timeValues.TV_Count, NULL); zassert_equal(in.priority, out.priority, NULL); } /** * @brief Test encode/decode API with Calendar Entry (Date variant) */ #if defined(CONFIG_ZTEST_NEW_API) ZTEST(BACnetSpecialEvent_tests, test_BACnetSpecialEvent_WeekNDate) #else static void test_BACnetSpecialEvent_WeekNDate(void) #endif { int len, apdu_len, null_len; uint8_t apdu[MAX_APDU] = { 0 }; BACNET_SPECIAL_EVENT in = { 0 }; BACNET_SPECIAL_EVENT out = { 0 }; in.periodTag = BACNET_SPECIAL_EVENT_PERIOD_CALENDAR_ENTRY; in.period.calendarEntry.tag = BACNET_CALENDAR_WEEK_N_DAY; in.period.calendarEntry.type.WeekNDay.month = 0xff; in.period.calendarEntry.type.WeekNDay.dayofweek = 1; /* mondays */ in.period.calendarEntry.type.WeekNDay.weekofmonth = 0xff; in.timeValues.TV_Count = 0; in.priority = 16; len = bacnet_special_event_encode(apdu, &in); null_len = bacnet_special_event_encode(NULL, &in); zassert_equal(len, null_len, NULL); apdu_len = bacnet_special_event_decode(apdu, len, &out); zassert_equal(len, apdu_len, NULL); zassert_equal(in.periodTag, out.periodTag, NULL); zassert_equal( in.period.calendarEntry.tag, out.period.calendarEntry.tag, NULL); zassert_equal( in.period.calendarEntry.type.WeekNDay.month, out.period.calendarEntry.type.WeekNDay.month, NULL); zassert_equal( in.period.calendarEntry.type.WeekNDay.dayofweek, out.period.calendarEntry.type.WeekNDay.dayofweek, NULL); zassert_equal( in.period.calendarEntry.type.WeekNDay.weekofmonth, out.period.calendarEntry.type.WeekNDay.weekofmonth, NULL); zassert_equal(in.timeValues.TV_Count, out.timeValues.TV_Count, NULL); zassert_equal(in.priority, out.priority, NULL); } /** @brief try decoding a real sample from Siemens, captured with wireshark */ #if defined(CONFIG_ZTEST_NEW_API) ZTEST(BACnetSpecialEvent_tests, test_BACnetSpecialEvent_DecodeRealAPDU) #else static void test_BACnetSpecialEvent_DecodeRealAPDU(void) #endif { int apdu_len; BACNET_SPECIAL_EVENT out = { 0 }; uint8_t sample[18] = { 0x0e, 0x0c, 0xff, 0x0a, 0x1c, 0xff, 0x0f, 0x2e, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x91, 0x00, 0x2f, 0x39, 0x10 }; apdu_len = bacnet_special_event_decode(sample, sizeof(sample), &out); zassert_equal(sizeof(sample), apdu_len, NULL); zassert_equal( out.periodTag, BACNET_SPECIAL_EVENT_PERIOD_CALENDAR_ENTRY, NULL); zassert_equal(out.period.calendarEntry.tag, BACNET_CALENDAR_DATE, NULL); zassert_equal(out.period.calendarEntry.type.Date.day, 28, NULL); zassert_equal(out.period.calendarEntry.type.Date.month, 10, NULL); zassert_equal( out.period.calendarEntry.type.Date.year, 2155 /* any */, NULL); zassert_equal( out.period.calendarEntry.type.Date.wday, 0xff /* any */, NULL); zassert_equal(out.timeValues.TV_Count, 1, NULL); zassert_equal(out.timeValues.Time_Values[0].Time.hour, 0, NULL); zassert_equal(out.timeValues.Time_Values[0].Time.min, 0, NULL); zassert_equal(out.timeValues.Time_Values[0].Time.sec, 0, NULL); zassert_equal(out.timeValues.Time_Values[0].Time.hundredths, 0, NULL); zassert_equal( out.timeValues.Time_Values[0].Value.tag, BACNET_APPLICATION_TAG_ENUMERATED, NULL); zassert_equal( out.timeValues.Time_Values[0].Value.type.Unsigned_Int, 0, NULL); zassert_equal(out.priority, 16, NULL); } /** * @} */ #if defined(CONFIG_ZTEST_NEW_API) ZTEST_SUITE(BACnetSpecialEvent_tests, NULL, NULL, NULL, NULL, NULL); #else void test_main(void) { ztest_test_suite( BACnetSpecialEvent_tests, ztest_unit_test(test_BACnetSpecialEvent_CalendarRef), ztest_unit_test(test_BACnetSpecialEvent_Date), ztest_unit_test(test_BACnetSpecialEvent_DateRange), ztest_unit_test(test_BACnetSpecialEvent_WeekNDate), ztest_unit_test(test_BACnetSpecialEvent_DecodeRealAPDU)); ztest_run_test_suite(BACnetSpecialEvent_tests); } #endif