/** * @file * @brief BACnet Application encoding and decoding API testing * @author Steve Karg * @date 2007 * @copyright SPDX-License-Identifier: MIT */ #include #include #include #include #include #include static const BACNET_APPLICATION_TAG tag_list[] = { /* primitive tags */ BACNET_APPLICATION_TAG_NULL, BACNET_APPLICATION_TAG_BOOLEAN, BACNET_APPLICATION_TAG_UNSIGNED_INT, BACNET_APPLICATION_TAG_SIGNED_INT, BACNET_APPLICATION_TAG_REAL, BACNET_APPLICATION_TAG_DOUBLE, BACNET_APPLICATION_TAG_OCTET_STRING, BACNET_APPLICATION_TAG_CHARACTER_STRING, BACNET_APPLICATION_TAG_BIT_STRING, BACNET_APPLICATION_TAG_ENUMERATED, BACNET_APPLICATION_TAG_DATE, BACNET_APPLICATION_TAG_TIME, BACNET_APPLICATION_TAG_OBJECT_ID, /* non-primitive tags */ BACNET_APPLICATION_TAG_EMPTYLIST, /* BACnetWeeknday */ /* BACNET_APPLICATION_TAG_WEEKNDAY, --> not implemented! */ /* BACnetDateRange */ BACNET_APPLICATION_TAG_DATERANGE, /* BACnetDateTime */ BACNET_APPLICATION_TAG_DATETIME, /* BACnetTimeStamp */ BACNET_APPLICATION_TAG_TIMESTAMP, /* Error Class, Error Code */ /* BACNET_APPLICATION_TAG_ERROR, --> not implemented! */ /* BACnetDeviceObjectPropertyReference */ BACNET_APPLICATION_TAG_DEVICE_OBJECT_PROPERTY_REFERENCE, /* BACnetDeviceObjectReference */ BACNET_APPLICATION_TAG_DEVICE_OBJECT_REFERENCE, /* BACnetObjectPropertyReference */ BACNET_APPLICATION_TAG_OBJECT_PROPERTY_REFERENCE, /* BACnetDestination (Recipient_List) */ BACNET_APPLICATION_TAG_DESTINATION, /* BACnetRecipient */ /* BACNET_APPLICATION_TAG_RECIPIENT, --> not implemented! */ /* BACnetCOVSubscription */ /* BACNET_APPLICATION_TAG_COV_SUBSCRIPTION, --> not implemented! */ /* BACnetCalendarEntry */ BACNET_APPLICATION_TAG_CALENDAR_ENTRY, /* BACnetWeeklySchedule */ BACNET_APPLICATION_TAG_WEEKLY_SCHEDULE, /* BACnetSpecialEvent */ BACNET_APPLICATION_TAG_SPECIAL_EVENT, /* BACnetReadAccessSpecification */ /* BACNET_APPLICATION_TAG_READ_ACCESS_SPECIFICATION, --> not implemented! */ /* BACnetLightingCommand */ BACNET_APPLICATION_TAG_LIGHTING_COMMAND, /* BACnetHostNPort */ BACNET_APPLICATION_TAG_HOST_N_PORT, /* BACnetxyColor */ BACNET_APPLICATION_TAG_XY_COLOR, /* BACnetColorCommand */ BACNET_APPLICATION_TAG_COLOR_COMMAND, /* BACnetBDTEntry */ BACNET_APPLICATION_TAG_BDT_ENTRY, /* BACnetFDTEntry */ BACNET_APPLICATION_TAG_FDT_ENTRY, /* BACnetActionCommand */ BACNET_APPLICATION_TAG_ACTION_COMMAND, /* BACnetScale */ BACNET_APPLICATION_TAG_SCALE, /* BACnetShedLevel */ BACNET_APPLICATION_TAG_SHED_LEVEL, /* BACnetAccessRule */ BACNET_APPLICATION_TAG_ACCESS_RULE }; /** * @addtogroup bacnet_tests * @{ */ #if defined(CONFIG_ZTEST_NEW_API) ZTEST(bacapp_tests, test_bacapp_decode_application_data) #else static void test_bacapp_decode_application_data(void) #endif { uint8_t apdu[128] = { 0 }; // unsigned max_apdu_len = sizeof(apdu); BACNET_APPLICATION_DATA_VALUE value = { 0 }; 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); } #if defined(CONFIG_ZTEST_NEW_API) ZTEST(bacapp_tests, test_bacapp_decode_data_len) #else static void test_bacapp_decode_data_len(void) #endif { 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_MAX; 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); } #if defined(CONFIG_ZTEST_NEW_API) ZTEST(bacapp_tests, test_bacapp_copy) #else static void test_bacapp_copy(void) #endif { 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_true(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); for (i = 0; i < ARRAY_SIZE(tag_list); ++i) { BACNET_APPLICATION_TAG tag = tag_list[i]; bool result; 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)); src_value.next = NULL; memset(&dest_value, 0xBB, sizeof(dest_value)); dest_value.next = NULL; src_value.tag = tag; result = bacapp_copy(&dest_value, &src_value); zassert_equal(result, expected_result, NULL); result = bacapp_same_value(&dest_value, &src_value); if (!result) { printf( "bacapp: same-value of tag=%s[%u]\n", bactext_application_tag_name(tag), tag); } zassert_true(result, NULL); zassert_equal(dest_value.next, src_value.next, NULL); } } #if defined(CONFIG_ZTEST_NEW_API) ZTEST(bacapp_tests, test_bacapp_value_list_init) #else static void test_bacapp_value_list_init(void) #endif { 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); } } } #if defined(CONFIG_ZTEST_NEW_API) ZTEST(bacapp_tests, test_bacapp_property_value_list) #else static void test_bacapp_property_value_list(void) #endif { BACNET_PROPERTY_VALUE value[2] = { { 0 } }; size_t max_count = 0; size_t count = 0; int len, test_len; uint8_t apdu[480]; bool status; /* 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 < ARRAY_SIZE(value); ++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); } } bacapp_property_value_list_link(value, ARRAY_SIZE(value)); value[0].propertyIdentifier = 1; value[0].propertyArrayIndex = 1; value[0].priority = 1; status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_UNSIGNED_INT, "1", &value[0].value); zassert_true(status, NULL); test_len = bacapp_property_value_encode(NULL, &value[0]); zassert_true(test_len > 0, NULL); len = bacapp_property_value_encode(apdu, &value[0]); zassert_true(len > 0, NULL); test_len = bacapp_property_value_decode(apdu, sizeof(apdu), &value[1]); zassert_equal(len, test_len, "len=%d test_len=%d", len, test_len); test_len = bacapp_property_value_decode(apdu, sizeof(apdu), NULL); zassert_equal(len, test_len, "len=%d test_len=%d", len, test_len); while (len) { len--; test_len = bacapp_property_value_decode(apdu, len, &value[1]); if (test_len != BACNET_STATUS_ERROR) { /* shorter packet leaves off the OPTIONAL priority */ zassert_equal(len, test_len, "len=%d test_len=%d", len, test_len); zassert_equal( value[1].priority, BACNET_NO_PRIORITY, "priority=%u", (unsigned)value[1].priority); } else { zassert_equal( test_len, BACNET_STATUS_ERROR, "len=%d test_len=%d", len, test_len); test_len = bacapp_property_value_decode(apdu, len, NULL); zassert_equal( test_len, BACNET_STATUS_ERROR, "len=%d test_len=%d", len, test_len); } } } #if defined(CONFIG_ZTEST_NEW_API) ZTEST(bacapp_tests, test_bacapp_same_value) #else static void test_bacapp_same_value(void) #endif { 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); value.type.Boolean = !test_value.type.Boolean; zassert_false(bacapp_same_value(&value, &test_value), NULL); #else zassert_false(bacapp_same_value(&value, &test_value), NULL); #endif 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); value.type.Unsigned_Int = ~test_value.type.Unsigned_Int; zassert_false(bacapp_same_value(&value, &test_value), NULL); #else zassert_false(bacapp_same_value(&value, &test_value), NULL); #endif 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); value.type.Signed_Int = test_value.type.Signed_Int + 1; zassert_false(bacapp_same_value(&value, &test_value), NULL); #else zassert_false(bacapp_same_value(&value, &test_value), NULL); #endif 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); value.type.Real = test_value.type.Real + 1.0f; zassert_false(bacapp_same_value(&value, &test_value), NULL); #else zassert_false(bacapp_same_value(&value, &test_value), NULL); #endif 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); value.type.Double = test_value.type.Double + 1.0; zassert_false(bacapp_same_value(&value, &test_value), NULL); #else zassert_false(bacapp_same_value(&value, &test_value), NULL); #endif 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); value.type.Enumerated = test_value.type.Enumerated + 1; zassert_false(bacapp_same_value(&value, &test_value), NULL); #else zassert_false(bacapp_same_value(&value, &test_value), NULL); #endif 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); value.type.Date.day = test_value.type.Date.day + 1; zassert_false(bacapp_same_value(&value, &test_value), NULL); 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); #else zassert_false(bacapp_same_value(&value, &test_value), NULL); #endif #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 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); 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); #else zassert_false(bacapp_same_value(&value, &test_value), NULL); #endif 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); 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); #else zassert_false(bacapp_same_value(&value, &test_value), NULL); #endif 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 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 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 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 } /** * @brief Test */ #if defined(CONFIG_ZTEST_NEW_API) ZTEST(bacapp_tests, testBACnetApplicationData_Safe) #else static void testBACnetApplicationData_Safe(void) #endif { int i; uint8_t apdu[MAX_APDU]; int len = 0; int apdu_len; BACNET_APPLICATION_DATA_VALUE input_value[13]; uint32_t len_segment[13]; uint32_t single_length_segment; BACNET_APPLICATION_DATA_VALUE value = { 0 }; for (i = 0; i < 13; i++) { input_value[i].tag = (BACNET_APPLICATION_TAG)i; input_value[i].context_specific = 0; input_value[i].context_tag = 0; input_value[i].next = NULL; switch (input_value[i].tag) { case BACNET_APPLICATION_TAG_NULL: /* NULL: no data */ break; case BACNET_APPLICATION_TAG_BOOLEAN: input_value[i].type.Boolean = true; break; case BACNET_APPLICATION_TAG_UNSIGNED_INT: input_value[i].type.Unsigned_Int = 0xDEADBEEF; break; case BACNET_APPLICATION_TAG_SIGNED_INT: input_value[i].type.Signed_Int = 0x00C0FFEE; break; case BACNET_APPLICATION_TAG_REAL: input_value[i].type.Real = 3.141592654f; break; case BACNET_APPLICATION_TAG_DOUBLE: input_value[i].type.Double = 2.32323232323; break; case BACNET_APPLICATION_TAG_OCTET_STRING: { uint8_t test_octet[5] = { "Karg" }; octetstring_init( &input_value[i].type.Octet_String, test_octet, sizeof(test_octet)); } break; case BACNET_APPLICATION_TAG_CHARACTER_STRING: characterstring_init_ansi( &input_value[i].type.Character_String, "Hello There!"); break; case BACNET_APPLICATION_TAG_BIT_STRING: bitstring_init(&input_value[i].type.Bit_String); bitstring_set_bit(&input_value[i].type.Bit_String, 0, true); bitstring_set_bit(&input_value[i].type.Bit_String, 1, false); bitstring_set_bit(&input_value[i].type.Bit_String, 2, false); bitstring_set_bit(&input_value[i].type.Bit_String, 3, true); bitstring_set_bit(&input_value[i].type.Bit_String, 4, false); bitstring_set_bit(&input_value[i].type.Bit_String, 5, true); bitstring_set_bit(&input_value[i].type.Bit_String, 6, true); break; case BACNET_APPLICATION_TAG_ENUMERATED: input_value[i].type.Enumerated = 0x0BADF00D; break; case BACNET_APPLICATION_TAG_DATE: input_value[i].type.Date.day = 10; input_value[i].type.Date.month = 9; input_value[i].type.Date.wday = 3; input_value[i].type.Date.year = 1998; break; case BACNET_APPLICATION_TAG_TIME: input_value[i].type.Time.hour = 12; input_value[i].type.Time.hundredths = 56; input_value[i].type.Time.min = 20; input_value[i].type.Time.sec = 41; break; case BACNET_APPLICATION_TAG_OBJECT_ID: input_value[i].type.Object_Id.instance = 1234; input_value[i].type.Object_Id.type = 12; break; default: break; } single_length_segment = bacapp_encode_data(&apdu[len], &input_value[i]); zassert_true(single_length_segment > 0, NULL); /* len_segment is accumulated length */ if (i == 0) { len_segment[i] = single_length_segment; } else { len_segment[i] = single_length_segment + len_segment[i - 1]; } len = len_segment[i]; } /* ** Start processing packets at processivly truncated lengths */ for (apdu_len = len; apdu_len >= 0; apdu_len--) { bool status; bool expected_status; for (i = 0; i < 14; i++) { if (i == 13) { expected_status = false; } else { if (apdu_len < len_segment[i]) { expected_status = false; } else { expected_status = true; } } status = bacapp_decode_application_data_safe( i == 0 ? apdu : NULL, apdu_len, &value); zassert_equal(status, expected_status, NULL); if (status) { zassert_equal(value.tag, i, NULL); zassert_true(bacapp_same_value(&input_value[i], &value), NULL); zassert_true(!value.context_specific, NULL); zassert_is_null(value.next, NULL); } else { break; } } } } /** * @brief Test */ #if defined(CONFIG_ZTEST_NEW_API) ZTEST(bacapp_tests, testBACnetApplicationDataLength) #else static void testBACnetApplicationDataLength(void) #endif { int apdu_len = 0; /* total length of the apdu, return value */ int len = 0; /* total length of the apdu, return value */ int test_len = 0; /* length of the data */ uint8_t apdu[480] = { 0 }; BACNET_TIME local_time; BACNET_DATE local_date; /* create some constructed data */ /* 1. zero elements */ test_len = 0; apdu_len = 0; len = encode_opening_tag(&apdu[apdu_len], 3); apdu_len += len; len = encode_closing_tag(&apdu[apdu_len], 3); apdu_len += len; /* verify the length of the data inside the opening/closing tags */ len = bacnet_enclosed_data_length(&apdu[0], apdu_len); zassert_equal(test_len, len, NULL); /* 2. application tagged data, one element */ test_len = 0; apdu_len = 0; len = encode_opening_tag(&apdu[apdu_len], 3); apdu_len += len; len = encode_application_unsigned(&apdu[apdu_len], 4194303); test_len += len; apdu_len += len; len = encode_closing_tag(&apdu[apdu_len], 3); apdu_len += len; /* verify the length of the data inside the opening/closing tags */ len = bacnet_enclosed_data_length(&apdu[0], apdu_len); zassert_equal(test_len, len, NULL); /* 3. application tagged data, multiple elements */ test_len = 0; apdu_len = 0; len = encode_opening_tag(&apdu[apdu_len], 3); apdu_len += len; len = encode_application_null(&apdu[apdu_len]); test_len += len; apdu_len += len; len = encode_application_null(&apdu[apdu_len]); test_len += len; apdu_len += len; len = encode_application_unsigned(&apdu[apdu_len], 1); test_len += len; apdu_len += len; len = encode_application_unsigned(&apdu[apdu_len], 42); test_len += len; apdu_len += len; len = encode_application_unsigned(&apdu[apdu_len], 91); test_len += len; apdu_len += len; len = encode_application_null(&apdu[apdu_len]); test_len += len; apdu_len += len; len = encode_application_null(&apdu[apdu_len]); test_len += len; apdu_len += len; len = encode_application_null(&apdu[apdu_len]); test_len += len; apdu_len += len; len = encode_application_null(&apdu[apdu_len]); test_len += len; apdu_len += len; len = encode_application_null(&apdu[apdu_len]); test_len += len; apdu_len += len; len = encode_application_null(&apdu[apdu_len]); test_len += len; apdu_len += len; len = encode_application_null(&apdu[apdu_len]); test_len += len; apdu_len += len; len = encode_application_null(&apdu[apdu_len]); test_len += len; apdu_len += len; len = encode_application_null(&apdu[apdu_len]); test_len += len; apdu_len += len; len = encode_application_null(&apdu[apdu_len]); test_len += len; apdu_len += len; len = encode_application_null(&apdu[apdu_len]); test_len += len; apdu_len += len; len = encode_closing_tag(&apdu[apdu_len], 3); apdu_len += len; /* verify the length of the data inside the opening/closing tags */ len = bacnet_enclosed_data_length(&apdu[0], apdu_len); zassert_equal(test_len, len, NULL); /* 4. complex datatype - one element */ test_len = 0; apdu_len = 0; len = encode_opening_tag(&apdu[apdu_len], 3); apdu_len += len; len = encode_opening_tag(&apdu[apdu_len], 3); test_len += len; apdu_len += len; local_date.year = 2006; /* AD */ local_date.month = 4; /* 1=Jan */ local_date.day = 1; /* 1..31 */ local_date.wday = 6; /* 1=Monday */ len = encode_application_date(&apdu[apdu_len], &local_date); test_len += len; apdu_len += len; local_time.hour = 7; local_time.min = 0; local_time.sec = 3; local_time.hundredths = 1; len = encode_application_time(&apdu[apdu_len], &local_time); test_len += len; apdu_len += len; len = encode_closing_tag(&apdu[apdu_len], 3); test_len += len; apdu_len += len; len = encode_closing_tag(&apdu[apdu_len], 3); apdu_len += len; /* verify the length of the data inside the opening/closing tags */ len = bacnet_enclosed_data_length(&apdu[0], apdu_len); zassert_equal(test_len, len, NULL); /* 5. complex datatype - multiple elements */ /* 6. context tagged data, one element */ test_len = 0; apdu_len = 0; len = encode_opening_tag(&apdu[apdu_len], 3); apdu_len += len; len = encode_context_unsigned(&apdu[apdu_len], 1, 91); test_len += len; apdu_len += len; len = encode_closing_tag(&apdu[apdu_len], 3); apdu_len += len; /* verify the length of the data inside the opening/closing tags */ len = bacnet_enclosed_data_length(&apdu[0], apdu_len); zassert_equal(test_len, len, NULL); /* 7. context opening & closing tag */ test_len = 0; apdu_len = 0; len = encode_opening_tag(&apdu[apdu_len], 3); apdu_len += len; len = encode_opening_tag(&apdu[apdu_len], 0); apdu_len += len; test_len += len; len = encode_closing_tag(&apdu[apdu_len], 0); apdu_len += len; test_len += len; len = encode_closing_tag(&apdu[apdu_len], 3); apdu_len += len; /* verify the length of the data inside the opening/closing tags */ len = bacnet_enclosed_data_length(&apdu[0], apdu_len); zassert_equal(test_len, len, NULL); } /** * @brief Test */ static bool verifyBACnetApplicationDataValue(const BACNET_APPLICATION_DATA_VALUE *value) { uint8_t apdu[480] = { 0 }; int apdu_len = 0; int null_len = 0; int test_len = 0; int len = 0; bool status = false; BACNET_APPLICATION_DATA_VALUE test_value = { 0 }; /* 1. test that encode length matches NULL */ apdu_len = bacapp_encode_application_data(&apdu[0], value); zassert_true(apdu_len > 0, NULL); null_len = bacapp_encode_application_data(NULL, value); zassert_equal(apdu_len, null_len, NULL); /* 2. test that value decoded from buffer matches incoming value */ test_len = bacapp_decode_application_data(&apdu[0], apdu_len, &test_value); zassert_true(test_len != BACNET_STATUS_ERROR, NULL); status = bacapp_same_value(value, &test_value); /* 3. test that decoded buffer matches encoded buffer */ while (apdu_len) { apdu_len--; test_len = bacapp_decode_application_data(&apdu[0], apdu_len, &test_value); if (apdu_len == 0) { zassert_equal( test_len, 0, "tag=%u apdu_len=%d test_len=%d\n", value->tag, apdu_len, test_len); } else { zassert_equal( test_len, BACNET_STATUS_ERROR, "tag=%u apdu_len=%d test_len=%d null_len=%d\n", value->tag, apdu_len, test_len, null_len); } } /* 4. test bacnet_enclosed_data_length() matches APDU buffer length */ apdu_len = 0; test_len = 0; len = encode_opening_tag(&apdu[0], 3); apdu_len += len; len = bacapp_encode_application_data(&apdu[apdu_len], value); test_len += len; apdu_len += len; len = encode_closing_tag(&apdu[apdu_len], 3); apdu_len += len; /* verify the length of the data inside the opening/closing tags */ len = bacnet_enclosed_data_length(&apdu[0], apdu_len); zassert_equal(test_len, len, NULL); zassert_equal(null_len, len, NULL); return status; } /** * @brief Test */ static void verifyBACnetComplexDataValue( const BACNET_APPLICATION_DATA_VALUE *value, BACNET_OBJECT_TYPE object_type, BACNET_PROPERTY_ID prop) { uint8_t apdu[480] = { 0 }; int apdu_len = 0; int null_len = 0; int test_len = 0; int len = 0; BACNET_APPLICATION_DATA_VALUE test_value = { 0 }; bool status = false; /* 1. test that encode length matches NULL */ apdu_len = bacapp_encode_application_data(&apdu[0], value); zassert_true(apdu_len > 0, NULL); null_len = bacapp_encode_application_data(NULL, value); zassert_equal(apdu_len, null_len, "encoded length=%d", apdu_len); /* 2. test that value decoded from buffer matches incoming value */ apdu_len = bacapp_decode_known_property( &apdu[0], apdu_len, &test_value, object_type, prop); zassert_true( apdu_len != BACNET_STATUS_ERROR, "decoded length=%d", apdu_len); zassert_true(apdu_len > 0, "decoded length=%d", apdu_len); status = bacapp_same_value(value, &test_value); if (!status) { null_len = 0; } zassert_true( status, "bacapp: same-value of tag=%s[%u]\n", bactext_application_tag_name(value->tag), value->tag); /* 3. test bacnet_enclosed_data_length() matches APDU buffer length */ apdu_len = 0; test_len = 0; len = encode_opening_tag(&apdu[0], 3); apdu_len += len; len = bacapp_encode_application_data(&apdu[apdu_len], value); test_len += len; apdu_len += len; len = encode_closing_tag(&apdu[apdu_len], 3); apdu_len += len; /* verify the length of the data inside the opening/closing tags */ len = bacnet_enclosed_data_length(&apdu[0], apdu_len); zassert_equal(test_len, len, NULL); zassert_equal(null_len, len, NULL); } /** * @brief Test */ #if defined(CONFIG_ZTEST_NEW_API) ZTEST(bacapp_tests, testBACnetApplicationData) #else static void testBACnetApplicationData(void) #endif { BACNET_APPLICATION_DATA_VALUE value = { 0 }; bool status = false; status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_NULL, NULL, &value); zassert_true(status, NULL); status = verifyBACnetApplicationDataValue(&value); zassert_true(status, NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_BOOLEAN, "1", &value); zassert_true(status, NULL); zassert_true(value.type.Boolean, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_BOOLEAN, "0", &value); zassert_true(status, NULL); zassert_false(value.type.Boolean, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_UNSIGNED_INT, "0", &value); zassert_true(status, NULL); zassert_equal(value.type.Unsigned_Int, 0, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_UNSIGNED_INT, "0xFFFF", &value); zassert_true(status, NULL); zassert_equal(value.type.Unsigned_Int, 0xFFFF, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_UNSIGNED_INT, "0xFFFFFFFF", &value); zassert_true(status, NULL); zassert_equal(value.type.Unsigned_Int, 0xFFFFFFFF, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_SIGNED_INT, "0", &value); zassert_true(status, NULL); zassert_equal(value.type.Signed_Int, 0, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_SIGNED_INT, "-1", &value); zassert_true(status, NULL); zassert_equal(value.type.Signed_Int, -1, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_SIGNED_INT, "32768", &value); zassert_true(status, NULL); zassert_equal(value.type.Signed_Int, 32768, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_SIGNED_INT, "-32768", &value); zassert_true(status, NULL); zassert_equal(value.type.Signed_Int, -32768, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_REAL, "0.0", &value); zassert_true(status, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_REAL, "-1.0", &value); zassert_true(status, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_REAL, "1.0", &value); zassert_true(status, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_REAL, "3.14159", &value); zassert_true(status, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_REAL, "-3.14159", &value); zassert_true(status, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_DOUBLE, "0.0", &value); zassert_true(status, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_DOUBLE, "-1.0", &value); zassert_true(status, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_DOUBLE, "1.0", &value); zassert_true(status, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_DOUBLE, "3.14159", &value); zassert_true(status, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_DOUBLE, "-3.14159", &value); zassert_true(status, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_OCTET_STRING, "1234567890ABCDEF", &value); zassert_true(status, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_OCTET_STRING, "12-34-56-78-90-AB-CD-EF", &value); zassert_true(status, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_OCTET_STRING, "12 34 56 78 90 AB CD EF", &value); zassert_true(status, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); /* test empty string */ status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_OCTET_STRING, "", &value); zassert_true(status, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_CHARACTER_STRING, "Karg!", &value); zassert_true(status, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); /* test empty string */ status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_CHARACTER_STRING, "", &value); zassert_true(status, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_BIT_STRING, "1011010010011111", &value); zassert_true(status, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_BIT_STRING, "111100001111", &value); zassert_true(status, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_ENUMERATED, "0", &value); zassert_true(status, NULL); zassert_equal(value.type.Enumerated, 0, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_ENUMERATED, "0xFFFF", &value); zassert_true(status, NULL); zassert_equal(value.type.Enumerated, 0xFFFF, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_ENUMERATED, "0xFFFFFFFF", &value); zassert_true(status, NULL); zassert_equal(value.type.Enumerated, 0xFFFFFFFF, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_DATE, "2005/5/22:1", &value); zassert_true(status, NULL); zassert_equal(value.type.Date.year, 2005, NULL); zassert_equal(value.type.Date.month, 5, NULL); zassert_equal(value.type.Date.day, 22, NULL); zassert_equal(value.type.Date.wday, 1, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); /* Happy Valentines Day! */ status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_DATE, "2007/2/14", &value); zassert_true(status, NULL); zassert_equal(value.type.Date.year, 2007, NULL); zassert_equal(value.type.Date.month, 2, NULL); zassert_equal(value.type.Date.day, 14, NULL); zassert_equal(value.type.Date.wday, BACNET_WEEKDAY_WEDNESDAY, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); /* Wildcard Values */ status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_DATE, "2155/255/255:255", &value); zassert_true(status, NULL); zassert_equal(value.type.Date.year, 2155, NULL); zassert_equal(value.type.Date.month, 255, NULL); zassert_equal(value.type.Date.day, 255, NULL); zassert_equal(value.type.Date.wday, 255, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_TIME, "23:59:59.12", &value); zassert_true(status, NULL); zassert_equal(value.type.Time.hour, 23, NULL); zassert_equal(value.type.Time.min, 59, NULL); zassert_equal(value.type.Time.sec, 59, NULL); zassert_equal(value.type.Time.hundredths, 12, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_TIME, "23:59:59", &value); zassert_true(status, NULL); zassert_equal(value.type.Time.hour, 23, NULL); zassert_equal(value.type.Time.min, 59, NULL); zassert_equal(value.type.Time.sec, 59, NULL); zassert_equal(value.type.Time.hundredths, 0, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_TIME, "23:59", &value); zassert_true(status, NULL); zassert_equal(value.type.Time.hour, 23, NULL); zassert_equal(value.type.Time.min, 59, NULL); zassert_equal(value.type.Time.sec, 0, NULL); zassert_equal(value.type.Time.hundredths, 0, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); /* Wildcard Values */ status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_TIME, "255:255:255.255", &value); zassert_true(status, NULL); zassert_equal(value.type.Time.hour, 255, NULL); zassert_equal(value.type.Time.min, 255, NULL); zassert_equal(value.type.Time.sec, 255, NULL); zassert_equal(value.type.Time.hundredths, 255, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_OBJECT_ID, "0:100", &value); zassert_true(status, NULL); zassert_equal(value.type.Object_Id.type, 0, NULL); zassert_equal(value.type.Object_Id.instance, 100, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_OBJECT_ID, "8:4194303", &value); zassert_true(status, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_OBJECT_ID, "0:0", &value); zassert_true(status, NULL); zassert_true(verifyBACnetApplicationDataValue(&value), NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_HOST_N_PORT, "192", &value); zassert_false(status, NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_HOST_N_PORT, "192.168.1.1", &value); zassert_true(status, NULL); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_HOST_N_PORT, "192.168.1.1:47808", &value); zassert_true(status, NULL); verifyBACnetComplexDataValue( &value, OBJECT_NETWORK_PORT, PROP_FD_BBMD_ADDRESS); verifyBACnetComplexDataValue( &value, OBJECT_NETWORK_PORT, PROP_BACNET_IP_GLOBAL_ADDRESS); status = bacapp_parse_application_data( BACNET_APPLICATION_TAG_BDT_ENTRY, "192.168.1.1:47808,255.255.255.255", &value); zassert_true(status, NULL); verifyBACnetComplexDataValue( &value, OBJECT_NETWORK_PORT, PROP_BBMD_BROADCAST_DISTRIBUTION_TABLE); return; } /** * @brief Test */ #if defined(CONFIG_ZTEST_NEW_API) ZTEST(bacapp_tests, test_bacapp_data) #else static void test_bacapp_data(void) #endif { uint8_t apdu[480] = { 0 }; BACNET_APPLICATION_DATA_VALUE value = { 0 }; int apdu_len, null_len, test_len, len; unsigned i = 0; for (i = 0; i < ARRAY_SIZE(tag_list); i++) { /* 1. test encoding matches for NULL and APDU buffer */ BACNET_APPLICATION_TAG tag = tag_list[i]; value.tag = tag; null_len = bacapp_encode_application_data(NULL, &value); apdu_len = bacapp_encode_application_data(apdu, &value); if (apdu_len != null_len) { printf( "bacapp: NULL len=%d != APDU len=%d for tag=%s", null_len, apdu_len, bactext_application_tag_name(tag)); } zassert_equal(apdu_len, null_len, NULL); /* 2. test bacnet_enclosed_data_length() matches APDU buffer or NULL */ apdu_len = 0; test_len = 0; len = encode_opening_tag(apdu, 3); apdu_len += len; len = bacapp_encode_application_data(&apdu[apdu_len], &value); test_len += len; apdu_len += len; len = encode_closing_tag(&apdu[apdu_len], 3); apdu_len += len; /* verify the length of the data inside the opening/closing tags */ len = bacnet_enclosed_data_length(apdu, apdu_len); zassert_equal(test_len, len, NULL); zassert_equal(null_len, len, NULL); /* 3. application tagged */ null_len = bacapp_encode_application_data(NULL, &value); apdu_len = bacapp_encode_application_data(apdu, &value); if (apdu_len != null_len) { printf( "bacapp: NULL len=%d != APDU len=%d for tag=%s", null_len, apdu_len, bactext_application_tag_name(tag)); } zassert_equal(apdu_len, null_len, NULL); /* 4. test bacnet_enclosed_data_length() matches APDU buffer or NULL */ apdu_len = 0; test_len = 0; len = encode_opening_tag(apdu, 3); apdu_len += len; len = bacapp_encode_application_data(&apdu[apdu_len], &value); test_len += len; apdu_len += len; len = encode_closing_tag(&apdu[apdu_len], 3); apdu_len += len; /* verify the length of the data inside the opening/closing tags */ len = bacnet_enclosed_data_length(apdu, apdu_len); zassert_equal(test_len, len, NULL); zassert_equal(null_len, len, NULL); } } /** * @brief Helper function to test bacapp_snprintf_value() * @param tag_number [in] The BACnet application tag to test * @param argv [in] The string to parse into a BACNET_APPLICATION_DATA_VALUE * @param expected [in] The expected string output from bacapp_snprintf_value() */ void test_bacapp_snprintf( BACNET_APPLICATION_TAG tag_number, char *argv, const char *expected) { BACNET_APPLICATION_DATA_VALUE value = { 0 }; BACNET_OBJECT_PROPERTY_VALUE object_value = { 0 }; bool status = false; int str_len = 0, len, test_len; /* object property value is only needed to snprintf ENUMERATED type */ object_value.object_type = OBJECT_DEVICE; object_value.object_instance = 0; object_value.object_property = PROP_SEGMENTATION_SUPPORTED; object_value.array_index = BACNET_ARRAY_ALL; object_value.value = &value; status = bacapp_parse_application_data(tag_number, argv, &value); zassert_true(status, NULL); str_len = bacapp_snprintf_value(NULL, 0, &object_value); if (str_len >= 0) { char str[str_len + 1]; str[0] = '\0'; /* normal case */ len = bacapp_snprintf_value(str, str_len + 1, &object_value); zassert_mem_equal( str, expected, str_len, "str='%s' expected='%s'", str, expected); zassert_equal(len, str_len, NULL); /* test when buffer is too small the behavior matches snprintf(). */ test_len = len; while (test_len >= 0) { len = bacapp_snprintf_value(str, test_len, &object_value); zassert_equal(len, str_len, "len=%d str_len=%d", len, str_len); zassert_equal( str[test_len], '\0', "tag=%u '%s':str[%d]=%02X not NULL", tag_number, argv, test_len, str[test_len]); test_len--; } } } /** * @brief Test */ #if defined(CONFIG_ZTEST_NEW_API) ZTEST(bacapp_tests, test_bacapp_sprintf_epics) #else static void test_bacapp_sprintf_epics(void) #endif { test_bacapp_snprintf(BACNET_APPLICATION_TAG_NULL, NULL, "Null"); test_bacapp_snprintf(BACNET_APPLICATION_TAG_BOOLEAN, "true", "TRUE"); test_bacapp_snprintf(BACNET_APPLICATION_TAG_BOOLEAN, "false", "FALSE"); test_bacapp_snprintf(BACNET_APPLICATION_TAG_UNSIGNED_INT, "0", "0"); test_bacapp_snprintf(BACNET_APPLICATION_TAG_UNSIGNED_INT, "42", "42"); test_bacapp_snprintf( BACNET_APPLICATION_TAG_UNSIGNED_INT, "4294967295", "4294967295"); test_bacapp_snprintf(BACNET_APPLICATION_TAG_SIGNED_INT, "0", "0"); test_bacapp_snprintf(BACNET_APPLICATION_TAG_SIGNED_INT, "-42", "-42"); test_bacapp_snprintf( BACNET_APPLICATION_TAG_SIGNED_INT, "2147483647", "2147483647"); test_bacapp_snprintf( BACNET_APPLICATION_TAG_SIGNED_INT, "-2147483648", "-2147483648"); test_bacapp_snprintf(BACNET_APPLICATION_TAG_REAL, "0.0", "0.000000"); test_bacapp_snprintf(BACNET_APPLICATION_TAG_REAL, "3.14159", "3.141590"); test_bacapp_snprintf(BACNET_APPLICATION_TAG_REAL, "-3.14159", "-3.141590"); test_bacapp_snprintf(BACNET_APPLICATION_TAG_DOUBLE, "0.0", "0.000000"); test_bacapp_snprintf(BACNET_APPLICATION_TAG_DOUBLE, "3.14159", "3.141590"); test_bacapp_snprintf( BACNET_APPLICATION_TAG_DOUBLE, "-3.14159", "-3.141590"); test_bacapp_snprintf( BACNET_APPLICATION_TAG_OCTET_STRING, "1234567890ABCDEF", "1234567890ABCDEF"); test_bacapp_snprintf( BACNET_APPLICATION_TAG_OCTET_STRING, "12-34-56-78-90-AB-CD-EF", "1234567890ABCDEF"); test_bacapp_snprintf( BACNET_APPLICATION_TAG_OCTET_STRING, "12 34 56 78 90 AB CD EF", "1234567890ABCDEF"); test_bacapp_snprintf(BACNET_APPLICATION_TAG_OCTET_STRING, "", ""); test_bacapp_snprintf( BACNET_APPLICATION_TAG_CHARACTER_STRING, "Karg!", "\"Karg!\""); test_bacapp_snprintf(BACNET_APPLICATION_TAG_CHARACTER_STRING, "", "\"\""); test_bacapp_snprintf( BACNET_APPLICATION_TAG_BIT_STRING, "1011010010011111", "{true,false,true,true,false,true,false,false,true,false,false,true," "true,true,true,true}"); test_bacapp_snprintf( BACNET_APPLICATION_TAG_BIT_STRING, "111100001111", "{true,true,true,true,false,false,false,false,true,true,true,true}"); /* note to tester: enumerated test relies on BACNET_OBJECT_PROPERTY_VALUE initialized in test_bacapp_snprintf() as PROP_SEGMENTATION_SUPPORTED */ test_bacapp_snprintf( BACNET_APPLICATION_TAG_ENUMERATED, "0", "segmented-both"); test_bacapp_snprintf( BACNET_APPLICATION_TAG_ENUMERATED, "1", "segmented-transmit"); test_bacapp_snprintf( BACNET_APPLICATION_TAG_ENUMERATED, "2", "segmented-receive"); test_bacapp_snprintf( BACNET_APPLICATION_TAG_ENUMERATED, "3", "no-segmentation"); test_bacapp_snprintf( BACNET_APPLICATION_TAG_ENUMERATED, "42", "Reserved for Use by ASHRAE"); test_bacapp_snprintf( BACNET_APPLICATION_TAG_DATE, "2005/5/22:1", "Monday, May 22, 2005"); test_bacapp_snprintf( BACNET_APPLICATION_TAG_DATE, "2007/2/14", "Wednesday, February 14, 2007"); test_bacapp_snprintf( BACNET_APPLICATION_TAG_DATE, "2155/255/255:255", "any day of week, Any Month (unspecified), (unspecified)"); test_bacapp_snprintf( BACNET_APPLICATION_TAG_TIME, "23:59:59.12", "23:59:59.12"); test_bacapp_snprintf( BACNET_APPLICATION_TAG_TIME, "23:59:59", "23:59:59.00"); test_bacapp_snprintf(BACNET_APPLICATION_TAG_TIME, "23:59", "23:59:00.00"); test_bacapp_snprintf( BACNET_APPLICATION_TAG_TIME, "255:255:255.255", "**:**:**.**"); test_bacapp_snprintf( BACNET_APPLICATION_TAG_OBJECT_ID, "0:100", "(analog-input, 100)"); test_bacapp_snprintf( BACNET_APPLICATION_TAG_OBJECT_ID, "8:4194303", "(device, 4194303)"); test_bacapp_snprintf( BACNET_APPLICATION_TAG_OBJECT_ID, "0:0", "(analog-input, 0)"); } /** * @} */ #if defined(CONFIG_ZTEST_NEW_API) ZTEST_SUITE(bacapp_tests, NULL, NULL, NULL, NULL, NULL); #else 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), ztest_unit_test(test_bacapp_same_value), ztest_unit_test(testBACnetApplicationData), ztest_unit_test(testBACnetApplicationDataLength), ztest_unit_test(testBACnetApplicationData_Safe), ztest_unit_test(test_bacapp_data), ztest_unit_test(test_bacapp_sprintf_epics)); ztest_run_test_suite(bacapp_tests); } #endif