Added BACnetRecipient and BACnetAddressBinding codecs for EPICS application (#1163)

* Added BACnetRecipient and BACnetAddressBinding encoding, decoding, ASCII conversion, comparison, and copy functions.

*  Added library specific string manipulation utilities including strcmp, strncmp, stptok, and snprintf with offset functions.

* Added test/README about verification and validation testing.
This commit is contained in:
Steve Karg
2025-11-27 23:12:39 -06:00
committed by GitHub
parent 21626d1ac5
commit ca9836b099
28 changed files with 1875 additions and 207 deletions
+211 -2
View File
@@ -31,6 +31,10 @@ static void test_BACNET_ADDRESS(void)
zassert_false(status, NULL);
status = bacnet_address_same(NULL, NULL);
zassert_false(status, NULL);
bacnet_address_copy(&dest, NULL);
bacnet_address_copy(&src, NULL);
status = bacnet_address_same(&dest, &src);
zassert_true(status, NULL);
/* happy day cases */
status = bacnet_address_same(&dest, &dest);
@@ -44,6 +48,42 @@ static void test_BACNET_ADDRESS(void)
zassert_true(status, NULL);
status = bacnet_address_same(&dest, &src);
zassert_true(status, NULL);
mac.len = 1;
mac.adr[0] = 3;
adr.len = 1;
adr.adr[0] = 4;
dnet = 1234;
status = bacnet_address_init(&src, &mac, dnet, &adr);
zassert_true(status, NULL);
bacnet_address_copy(&dest, &src);
zassert_true(status, NULL);
status = bacnet_address_net_same(&dest, &src);
zassert_true(status, NULL);
dnet = 0;
status = bacnet_address_init(&src, &mac, dnet, &adr);
zassert_true(status, NULL);
bacnet_address_copy(&dest, &src);
zassert_true(status, NULL);
status = bacnet_address_net_same(&dest, &src);
zassert_true(status, NULL);
/* net + adr */
dnet = 1;
status = bacnet_address_init(&src, NULL, dnet, &adr);
status = bacnet_address_net_same(&dest, &src);
zassert_false(status, NULL);
/* net=0, mac */
dnet = 1;
status = bacnet_address_init(&dest, NULL, dnet, &adr);
zassert_true(status, NULL);
dnet = 0;
status = bacnet_address_init(&src, &mac, dnet, NULL);
zassert_true(status, NULL);
status = bacnet_address_net_same(&dest, &src);
zassert_false(status, NULL);
status = bacnet_address_net_same(NULL, &src);
zassert_false(status, NULL);
status = bacnet_address_net_same(&dest, NULL);
zassert_false(status, NULL);
/* remote dnet is non-zero */
dnet = 1;
status = bacnet_address_init(&dest, &mac, dnet, &adr);
@@ -105,6 +145,11 @@ static void test_BACNET_ADDRESS(void)
zassert_true(status, NULL);
status = bacnet_address_same(&dest, &src);
zassert_true(status, NULL);
/* initialize using copy */
bacnet_address_copy(&dest, NULL);
zassert_equal(dest.mac_len, 0, NULL);
zassert_equal(dest.len, 0, NULL);
zassert_equal(dest.net, 0, NULL);
}
#if defined(CONFIG_ZTEST_NEW_API)
@@ -215,8 +260,36 @@ static void test_BACnetAddress_Codec(void)
zassert_equal(value.net, test_value.net, NULL);
zassert_equal(value.mac_len, test_value.mac_len, NULL);
zassert_equal(value.mac_len, 6, NULL);
/* test deprecated function */
test_len = decode_bacnet_address(apdu, &test_value);
zassert_equal(len, test_len, NULL);
zassert_equal(value.net, test_value.net, NULL);
zassert_equal(value.mac_len, test_value.mac_len, NULL);
zassert_equal(value.mac_len, 6, NULL);
/* negative tests - NULL value */
test_len = bacnet_address_decode(apdu, sizeof(apdu), NULL);
zassert_equal(len, test_len, NULL);
/* network address */
value.net = 1;
value.len = 3;
value.adr[0] = 1;
value.adr[1] = 2;
value.adr[2] = 3;
len = encode_bacnet_address(NULL, &value);
test_len = encode_bacnet_address(apdu, &value);
zassert_true(len > 0, NULL);
zassert_true(test_len > 0, NULL);
zassert_equal(len, test_len, "len=%d test_len=%d", len, test_len);
test_len = bacnet_address_decode(apdu, sizeof(apdu), &test_value);
zassert_equal(len, test_len, NULL);
zassert_equal(value.net, test_value.net, NULL);
zassert_equal(value.mac_len, test_value.mac_len, NULL);
zassert_equal(value.len, test_value.len, NULL);
zassert_equal(value.len, 3, NULL);
zassert_equal(value.adr[0], test_value.adr[0], NULL);
zassert_equal(value.adr[1], test_value.adr[1], NULL);
zassert_equal(value.adr[2], test_value.adr[2], NULL);
/* context tagged */
tag_number = 1;
len = encode_context_bacnet_address(NULL, tag_number, &value);
test_len = encode_context_bacnet_address(apdu, tag_number, &value);
@@ -229,6 +302,12 @@ static void test_BACnetAddress_Codec(void)
zassert_equal(value.net, test_value.net, NULL);
zassert_equal(value.mac_len, test_value.mac_len, NULL);
zassert_equal(value.mac_len, 6, NULL);
/* validate deprecated function */
test_len = decode_context_bacnet_address(apdu, tag_number, &test_value);
zassert_equal(len, test_len, NULL);
zassert_equal(value.net, test_value.net, NULL);
zassert_equal(value.mac_len, test_value.mac_len, NULL);
zassert_equal(value.mac_len, 6, NULL);
test_len = bacnet_address_context_decode(
apdu, sizeof(apdu), tag_number, &test_value);
/* negative tests - NULL value */
@@ -256,9 +335,18 @@ static void test_bacnet_vmac_entry_codec(void)
{
uint8_t apdu[MAX_APDU];
BACNET_VMAC_ENTRY value = { 0 }, test_value = { 0 };
BACNET_ADDRESS test_addr = { 0 };
int test_len = 0, apdu_len = 0, null_len = 0;
bool status = false;
unsigned i;
status = bacnet_vmac_address_set(NULL, 0);
zassert_false(status, NULL);
status = bacnet_vmac_address_set(&test_addr, 12345);
zassert_true(status, NULL);
zassert_equal(test_addr.mac_len, 3, NULL);
zassert_equal(test_addr.net, 0, NULL);
/* VMAC */
value.virtual_mac_address.adr[0] = 1;
value.virtual_mac_address.adr[1] = 2;
value.virtual_mac_address.adr[2] = 3;
@@ -268,6 +356,8 @@ static void test_bacnet_vmac_entry_codec(void)
value.native_mac_address[2] = 6;
value.native_mac_address[3] = 7;
value.native_mac_address_len = 4;
null_len = bacnet_vmac_entry_encode(NULL, sizeof(apdu), NULL);
zassert_equal(null_len, 0, NULL);
null_len = bacnet_vmac_entry_encode(NULL, sizeof(apdu), &value);
apdu_len = bacnet_vmac_entry_encode(apdu, sizeof(apdu), &value);
zassert_true(apdu_len > 0, NULL);
@@ -302,6 +392,124 @@ static void test_bacnet_vmac_entry_codec(void)
}
}
#if defined(CONFIG_ZTEST_NEW_API)
ZTEST(bacnet_address_tests, test_bacnet_address_ascii)
#else
static void test_bacnet_address_ascii(void)
#endif
{
char ascii_mac_net_adr[80] = "{ff:00:ff:01:ff:02,1,7f}";
char ascii_mac_net[80] = "{192.168.1.1:47808,0}";
BACNET_ADDRESS value = { 0 };
bool status;
status = bacnet_address_from_ascii(NULL, NULL);
zassert_false(status, NULL);
status = bacnet_address_from_ascii(&value, NULL);
zassert_false(status, NULL);
status = bacnet_address_from_ascii(NULL, ascii_mac_net_adr);
zassert_false(status, NULL);
status = bacnet_address_from_ascii(&value, ascii_mac_net_adr);
zassert_true(status, NULL);
zassert_equal(value.mac_len, 6, NULL);
zassert_equal(value.mac[0], 0xff, NULL);
zassert_equal(value.mac[1], 0x00, NULL);
zassert_equal(value.mac[2], 0xff, NULL);
zassert_equal(value.mac[3], 0x01, NULL);
zassert_equal(value.mac[4], 0xff, NULL);
zassert_equal(value.mac[5], 0x02, NULL);
zassert_equal(value.net, 1, NULL);
zassert_equal(value.len, 1, NULL);
zassert_equal(value.adr[0], 0x7f, NULL);
status = bacnet_address_from_ascii(&value, ascii_mac_net);
zassert_true(status, NULL);
zassert_equal(value.mac_len, 6, NULL);
zassert_equal(value.mac[0], 192, NULL);
zassert_equal(value.mac[1], 168, NULL);
zassert_equal(value.mac[2], 1, NULL);
zassert_equal(value.mac[3], 1, NULL);
zassert_equal(value.net, 0, NULL);
zassert_equal(value.len, 0, NULL);
}
#if defined(CONFIG_ZTEST_NEW_API)
ZTEST(bacnet_address_tests, test_BACNET_ADDRESS_BINDING)
#else
static void test_BACNET_ADDRESS_BINDING(void)
#endif
{
uint8_t apdu[MAX_APDU] = { 0 };
BACNET_ADDRESS addr = {
.mac_len = 1, .mac[0] = 0x01, .net = 0, .adr[0] = 0, .len = 0
};
BACNET_ADDRESS_BINDING binding = { 0 }, test_binding = { 0 };
bool status = false;
int len, test_len, apdu_len, null_len;
char str[80] = "";
null_len = bacnet_address_binding_type_encode(NULL, NULL);
zassert_equal(null_len, 0, NULL);
status = bacnet_address_binding_init(&binding, 12345, &addr);
len = bacnet_address_binding_type_encode(NULL, &binding);
null_len = bacnet_address_binding_type_encode(NULL, &binding);
zassert_not_equal(null_len, 0, NULL);
apdu_len = bacnet_address_binding_type_encode(apdu, &binding);
zassert_not_equal(null_len, 0, NULL);
zassert_equal(null_len, apdu_len, NULL);
test_len = bacnet_address_binding_decode(apdu, apdu_len, &test_binding);
zassert_equal(apdu_len, test_len, NULL);
status = bacnet_address_same(
&binding.device_address, &test_binding.device_address);
zassert_true(status, NULL);
status = bacnet_address_binding_same(&binding, &test_binding);
zassert_true(status, NULL);
null_len = bacnet_address_binding_encode(NULL, 0, &binding);
zassert_equal(null_len, 0, NULL);
null_len = bacnet_address_binding_encode(NULL, 0, NULL);
zassert_equal(null_len, 0, NULL);
null_len = bacnet_address_binding_encode(NULL, sizeof(apdu), &binding);
zassert_not_equal(null_len, 0, NULL);
apdu_len = bacnet_address_binding_encode(apdu, sizeof(apdu), &binding);
zassert_equal(null_len, apdu_len, NULL);
/* shrink the apdu size for decoding test */
while (apdu_len) {
apdu_len--;
test_len = bacnet_address_binding_decode(apdu, apdu_len, &test_binding);
zassert_equal(test_len, BACNET_STATUS_ERROR, NULL);
}
/* negative tests - NULL value */
apdu_len = bacnet_address_binding_encode(apdu, sizeof(apdu), &binding);
zassert_equal(null_len, apdu_len, NULL);
test_len = bacnet_address_binding_decode(apdu, sizeof(apdu), NULL);
zassert_equal(apdu_len, test_len, NULL);
test_len = bacnet_address_binding_decode(NULL, 0, NULL);
zassert_equal(test_len, BACNET_STATUS_ERROR, NULL);
status = bacnet_address_binding_copy(&test_binding, &binding);
zassert_true(status, NULL);
status = bacnet_address_binding_same(&test_binding, &binding);
zassert_true(status, NULL);
/* ASCII */
len = bacnet_address_binding_to_ascii(&binding, str, sizeof(str));
zassert_true(len > 0, NULL);
status = bacnet_address_binding_from_ascii(&test_binding, str);
zassert_true(status, NULL);
status = bacnet_address_binding_same(&test_binding, &binding);
zassert_true(status, NULL);
/* negative tests - NULL value */
status = bacnet_address_binding_same(NULL, &binding);
zassert_false(status, NULL);
status = bacnet_address_binding_same(&test_binding, NULL);
zassert_false(status, NULL);
status = bacnet_address_binding_copy(NULL, &binding);
zassert_false(status, NULL);
status = bacnet_address_binding_copy(&test_binding, NULL);
zassert_false(status, NULL);
status = bacnet_address_binding_init(NULL, 0, &addr);
zassert_false(status, NULL);
len = bacnet_address_binding_to_ascii(NULL, str, sizeof(str));
zassert_equal(len, 0, NULL);
}
/**
* @}
*/
@@ -314,8 +522,9 @@ void test_main(void)
bacnet_address_tests, ztest_unit_test(test_BACNET_ADDRESS),
ztest_unit_test(test_BACNET_MAC_ADDRESS),
ztest_unit_test(test_BACnetAddress_Codec),
ztest_unit_test(test_bacnet_vmac_entry_codec));
ztest_unit_test(test_bacnet_vmac_entry_codec),
ztest_unit_test(test_bacnet_address_ascii),
ztest_unit_test(test_BACNET_ADDRESS_BINDING));
ztest_run_test_suite(bacnet_address_tests);
}
#endif