Bugfix/bacapp deprecation fixes (#578)
* Secured bacapp_decode_application_data_safe(), bacapp_decode_application_data_len(), bacapp_decode_context_data(), bacapp_decode_known_property() for timestamp, bacapp_decode_context_data_len(), and bacapp_data_len() functions. * Fixed Command, Credential Data Input, and Schedule objects unit test
This commit is contained in:
@@ -27,6 +27,7 @@ add_compile_definitions(
|
||||
|
||||
include_directories(
|
||||
${SRC_DIR}
|
||||
${TST_DIR}/bacnet/basic/object
|
||||
${TST_DIR}/ztest/include
|
||||
)
|
||||
|
||||
@@ -49,6 +50,7 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/indtext.c
|
||||
${SRC_DIR}/bacnet/hostnport.c
|
||||
${SRC_DIR}/bacnet/lighting.c
|
||||
${SRC_DIR}/bacnet/proplist.c
|
||||
${SRC_DIR}/bacnet/timestamp.c
|
||||
${SRC_DIR}/bacnet/wp.c
|
||||
${SRC_DIR}/bacnet/weeklyschedule.c
|
||||
@@ -58,6 +60,7 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/special_event.c
|
||||
# Test and test library files
|
||||
./src/main.c
|
||||
${TST_DIR}/bacnet/basic/object/property_test.c
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
${ZTST_DIR}/ztest.c
|
||||
)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
#include <zephyr/ztest.h>
|
||||
#include <bacnet/basic/object/command.h>
|
||||
#include <bacnet/bactext.h>
|
||||
#include <property_test.h>
|
||||
|
||||
/**
|
||||
* @addtogroup bacnet_tests
|
||||
@@ -24,83 +24,34 @@ ZTEST(tests_object_command, test_object_command)
|
||||
static void test_object_command(void)
|
||||
#endif
|
||||
{
|
||||
uint8_t apdu[MAX_APDU] = { 0 };
|
||||
int len = 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;
|
||||
bool status = false;
|
||||
unsigned count = 0;
|
||||
uint32_t object_instance = 0;
|
||||
const int skip_fail_property_list[] = { PROP_ACTION, -1 };
|
||||
|
||||
Command_Init();
|
||||
count = Command_Count();
|
||||
zassert_true(count > 0, NULL);
|
||||
object_instance = Command_Index_To_Instance(0);
|
||||
rpdata.application_data = &apdu[0];
|
||||
rpdata.application_data_len = sizeof(apdu);
|
||||
rpdata.object_type = OBJECT_COMMAND;
|
||||
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);
|
||||
if (len != test_len) {
|
||||
printf("property '%s': failed to decode!\n",
|
||||
bactext_property_name(rpdata.object_property));
|
||||
}
|
||||
if (rpdata.object_property == PROP_PRIORITY_ARRAY) {
|
||||
/* FIXME: known fail to decode */
|
||||
len = test_len;
|
||||
}
|
||||
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);
|
||||
if (len != test_len) {
|
||||
printf("property '%s': failed to decode!\n",
|
||||
bactext_property_name(rpdata.object_property));
|
||||
}
|
||||
if (rpdata.object_property == PROP_PRIORITY_ARRAY) {
|
||||
/* FIXME: known fail to decode */
|
||||
len = test_len;
|
||||
}
|
||||
zassert_true(test_len >= 0, NULL);
|
||||
}
|
||||
pOptional++;
|
||||
}
|
||||
|
||||
return;
|
||||
bacnet_object_properties_read_write_test(
|
||||
OBJECT_COMMAND,
|
||||
object_instance,
|
||||
Command_Property_Lists,
|
||||
Command_Read_Property,
|
||||
Command_Write_Property,
|
||||
skip_fail_property_list);
|
||||
}
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
#if defined(CONFIG_ZTEST_NEW_API)
|
||||
ZTEST_SUITE(tests_object_command, NULL, NULL, NULL, NULL, NULL);
|
||||
#else
|
||||
void test_main(void)
|
||||
{
|
||||
ztest_test_suite(tests_object_command,
|
||||
ztest_unit_test(test_object_command)
|
||||
);
|
||||
ztest_test_suite(
|
||||
tests_object_command, ztest_unit_test(test_object_command));
|
||||
|
||||
ztest_run_test_suite(tests_object_command);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ add_compile_definitions(
|
||||
|
||||
include_directories(
|
||||
${SRC_DIR}
|
||||
${TST_DIR}/bacnet/basic/object
|
||||
${TST_DIR}/ztest/include
|
||||
)
|
||||
|
||||
@@ -52,6 +53,7 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/indtext.c
|
||||
${SRC_DIR}/bacnet/hostnport.c
|
||||
${SRC_DIR}/bacnet/lighting.c
|
||||
${SRC_DIR}/bacnet/proplist.c
|
||||
${SRC_DIR}/bacnet/timestamp.c
|
||||
${SRC_DIR}/bacnet/wp.c
|
||||
${SRC_DIR}/bacnet/weeklyschedule.c
|
||||
@@ -61,6 +63,7 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/special_event.c
|
||||
# Test and test library files
|
||||
./src/main.c
|
||||
${TST_DIR}/bacnet/basic/object/property_test.c
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
${ZTST_DIR}/ztest.c
|
||||
)
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Legrand North America, LLC.
|
||||
/**
|
||||
* @file
|
||||
* @brief Unit test for object
|
||||
* @author Steve Karg <skarg@users.sourceforge.net>
|
||||
* @date February 2024
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
/* @file
|
||||
* @brief test BACnet integer encode/decode APIs
|
||||
*/
|
||||
|
||||
#include <zephyr/ztest.h>
|
||||
#include <bacnet/basic/object/credential_data_input.h>
|
||||
#include <bacnet/bactext.h>
|
||||
#include <property_test.h>
|
||||
|
||||
/**
|
||||
* @addtogroup bacnet_tests
|
||||
@@ -26,65 +25,25 @@ ZTEST(credential_data_input_tests, testCredentialDataInput)
|
||||
static void testCredentialDataInput(void)
|
||||
#endif
|
||||
{
|
||||
uint8_t apdu[MAX_APDU] = { 0 };
|
||||
int len = 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;
|
||||
const int skip_fail_property_list[] = {
|
||||
PROP_PRESENT_VALUE,
|
||||
PROP_UPDATE_TIME,
|
||||
PROP_SUPPORTED_FORMATS,
|
||||
-1 };
|
||||
|
||||
Credential_Data_Input_Init();
|
||||
count = Credential_Data_Input_Count();
|
||||
zassert_true(count > 0, NULL);
|
||||
object_instance = Credential_Data_Input_Index_To_Instance(0);
|
||||
rpdata.application_data = &apdu[0];
|
||||
rpdata.application_data_len = sizeof(apdu);
|
||||
rpdata.object_type = OBJECT_CREDENTIAL_DATA_INPUT;
|
||||
rpdata.object_instance = object_instance;
|
||||
Credential_Data_Input_Property_Lists(&pRequired, &pOptional, &pProprietary);
|
||||
while ((*pRequired) != -1) {
|
||||
rpdata.object_property = *pRequired;
|
||||
rpdata.array_index = BACNET_ARRAY_ALL;
|
||||
len = Credential_Data_Input_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);
|
||||
if (len != test_len) {
|
||||
printf("property '%s': failed to decode!\n",
|
||||
bactext_property_name(rpdata.object_property));
|
||||
}
|
||||
if (rpdata.object_property == PROP_PRIORITY_ARRAY) {
|
||||
/* FIXME: known fail to decode */
|
||||
len = test_len;
|
||||
}
|
||||
zassert_true(test_len >= 0, NULL);
|
||||
} else {
|
||||
printf("property '%s': failed to read!\n",
|
||||
bactext_property_name(rpdata.object_property));
|
||||
}
|
||||
pRequired++;
|
||||
}
|
||||
while ((*pOptional) != -1) {
|
||||
rpdata.object_property = *pOptional;
|
||||
rpdata.array_index = BACNET_ARRAY_ALL;
|
||||
len = Credential_Data_Input_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);
|
||||
} else {
|
||||
printf("property '%s': failed to read!\n",
|
||||
bactext_property_name(rpdata.object_property));
|
||||
}
|
||||
pOptional++;
|
||||
}
|
||||
bacnet_object_properties_read_write_test(
|
||||
OBJECT_CREDENTIAL_DATA_INPUT,
|
||||
object_instance,
|
||||
Credential_Data_Input_Property_Lists,
|
||||
Credential_Data_Input_Read_Property,
|
||||
Credential_Data_Input_Write_Property,
|
||||
skip_fail_property_list);
|
||||
}
|
||||
/**
|
||||
* @}
|
||||
|
||||
@@ -27,6 +27,7 @@ add_compile_definitions(
|
||||
|
||||
include_directories(
|
||||
${SRC_DIR}
|
||||
${TST_DIR}/bacnet/basic/object
|
||||
${TST_DIR}/ztest/include
|
||||
)
|
||||
|
||||
@@ -61,6 +62,7 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/special_event.c
|
||||
# Test and test library files
|
||||
./src/main.c
|
||||
${TST_DIR}/bacnet/basic/object/property_test.c
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
${ZTST_DIR}/ztest.c
|
||||
)
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Legrand North America, LLC.
|
||||
/**
|
||||
* @file
|
||||
* @brief Unit test for object
|
||||
* @author Steve Karg <skarg@users.sourceforge.net>
|
||||
* @date February 2024
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
/* @file
|
||||
* @brief test BACnet integer encode/decode APIs
|
||||
*/
|
||||
|
||||
#include <zephyr/ztest.h>
|
||||
#include <bacnet/readrange.h>
|
||||
#include <bacnet/basic/object/netport.h>
|
||||
#include <property_test.h>
|
||||
|
||||
/**
|
||||
* @addtogroup bacnet_tests
|
||||
@@ -26,23 +25,18 @@ ZTEST(netport_tests, test_network_port)
|
||||
static void test_network_port(void)
|
||||
#endif
|
||||
{
|
||||
uint8_t apdu[MAX_APDU] = { 0 };
|
||||
int len = 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;
|
||||
bool status = false;
|
||||
unsigned count = 0;
|
||||
uint32_t object_instance = 0;
|
||||
bool status = false;
|
||||
uint8_t port_type[] = { PORT_TYPE_ETHERNET, PORT_TYPE_ARCNET,
|
||||
PORT_TYPE_MSTP, PORT_TYPE_PTP, PORT_TYPE_LONTALK, PORT_TYPE_BIP,
|
||||
PORT_TYPE_ZIGBEE, PORT_TYPE_VIRTUAL, PORT_TYPE_NON_BACNET,
|
||||
PORT_TYPE_BIP6, PORT_TYPE_MAX };
|
||||
const int known_fail_property_list[] = { PROP_IP_DNS_SERVER,
|
||||
PROP_BBMD_BROADCAST_DISTRIBUTION_TABLE,
|
||||
PROP_BBMD_FOREIGN_DEVICE_TABLE, PROP_FD_BBMD_ADDRESS,
|
||||
PROP_IPV6_DNS_SERVER, -1 };
|
||||
|
||||
while (port_type[port] != PORT_TYPE_MAX) {
|
||||
object_instance = 1234;
|
||||
@@ -53,43 +47,13 @@ static void test_network_port(void)
|
||||
Network_Port_Init();
|
||||
count = Network_Port_Count();
|
||||
zassert_true(count > 0, NULL);
|
||||
rpdata.application_data = &apdu[0];
|
||||
rpdata.application_data_len = sizeof(apdu);
|
||||
rpdata.object_type = OBJECT_NETWORK_PORT;
|
||||
rpdata.object_instance = object_instance;
|
||||
Network_Port_Property_Lists(&pRequired, &pOptional, &pProprietary);
|
||||
while ((*pRequired) != -1) {
|
||||
rpdata.object_property = *pRequired;
|
||||
rpdata.array_index = BACNET_ARRAY_ALL;
|
||||
len = Network_Port_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);
|
||||
if (test_len < 0) {
|
||||
printf("<decode failed!>\n");
|
||||
}
|
||||
}
|
||||
pRequired++;
|
||||
}
|
||||
while ((*pOptional) != -1) {
|
||||
rpdata.object_property = *pOptional;
|
||||
rpdata.array_index = BACNET_ARRAY_ALL;
|
||||
len = Network_Port_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);
|
||||
if (test_len < 0) {
|
||||
printf("<decode failed!>\n");
|
||||
}
|
||||
}
|
||||
pOptional++;
|
||||
}
|
||||
bacnet_object_properties_read_write_test(
|
||||
OBJECT_NETWORK_PORT,
|
||||
object_instance,
|
||||
Network_Port_Property_Lists,
|
||||
Network_Port_Read_Property,
|
||||
Network_Port_Write_Property,
|
||||
known_fail_property_list);
|
||||
port++;
|
||||
}
|
||||
|
||||
@@ -99,15 +63,12 @@ static void test_network_port(void)
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
#if defined(CONFIG_ZTEST_NEW_API)
|
||||
ZTEST_SUITE(netport_tests, NULL, NULL, NULL, NULL, NULL);
|
||||
#else
|
||||
void test_main(void)
|
||||
{
|
||||
ztest_test_suite(netport_tests,
|
||||
ztest_unit_test(test_network_port)
|
||||
);
|
||||
ztest_test_suite(netport_tests, ztest_unit_test(test_network_port));
|
||||
|
||||
ztest_run_test_suite(netport_tests);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Unit test for object property read/write
|
||||
* @author Steve Karg <skarg@users.sourceforge.net>
|
||||
* @date February 2024
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include <zephyr/ztest.h>
|
||||
#include <bacnet/bactext.h>
|
||||
#include <bacnet/rp.h>
|
||||
#include <bacnet/rpm.h>
|
||||
#include <bacnet/wp.h>
|
||||
|
||||
/**
|
||||
* @brief Perform a read/write test on a property
|
||||
* @param rpdata [in,out] The structure to hold the read property request
|
||||
* @param read_property [in] The function to read the property
|
||||
* @param write_property [in] The function to write the property
|
||||
* @param skip_fail_property_list [in] The list of properties that
|
||||
* are known to fail to decode after reading
|
||||
* @return true if the property was written successfully, false if not
|
||||
*/
|
||||
bool bacnet_object_property_write_test(BACNET_WRITE_PROPERTY_DATA *wpdata,
|
||||
write_property_function write_property,
|
||||
const int *skip_fail_property_list)
|
||||
{
|
||||
bool status = false;
|
||||
int len = 0;
|
||||
int test_len = 0;
|
||||
|
||||
(void)skip_fail_property_list;
|
||||
if (wpdata && write_property) {
|
||||
status = write_property(wpdata);
|
||||
if (!status) {
|
||||
/* verify WriteProperty property is known */
|
||||
zassert_not_equal(wpdata->error_code, ERROR_CODE_UNKNOWN_PROPERTY,
|
||||
"property '%s': WriteProperty Unknown!\n",
|
||||
bactext_property_name(wpdata->object_property));
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the write property parameter structure data from the
|
||||
* read property parameter structure data and the length of the property value
|
||||
* @param wpdata [in,out] The structure to hold the write property request
|
||||
* @param rpdata [in] The structure to hold the read property request
|
||||
*/
|
||||
void bacnet_object_property_write_parameter_init(
|
||||
BACNET_WRITE_PROPERTY_DATA *wpdata,
|
||||
BACNET_READ_PROPERTY_DATA *rpdata,
|
||||
int len)
|
||||
{
|
||||
if (wpdata && rpdata) {
|
||||
/* WriteProperty parameters */
|
||||
wpdata->object_type = rpdata->object_type;
|
||||
wpdata->object_instance = rpdata->object_instance;
|
||||
wpdata->object_property = rpdata->object_property;
|
||||
wpdata->array_index = rpdata->array_index;
|
||||
memcpy(&wpdata->application_data, rpdata->application_data, MAX_APDU);
|
||||
wpdata->application_data_len = len;
|
||||
wpdata->error_code = ERROR_CODE_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Perform a read/write test on a property
|
||||
* @param rpdata [in,out] The structure to hold the read property request
|
||||
* @param read_property [in] The function to read the property
|
||||
* @param write_property [in] The function to write the property
|
||||
* @param skip_fail_property_list [in] The list of properties that
|
||||
* are known to fail to decode after reading
|
||||
* @return length of the property value that was read
|
||||
*/
|
||||
int bacnet_object_property_read_test(BACNET_READ_PROPERTY_DATA *rpdata,
|
||||
read_property_function read_property,
|
||||
const int *skip_fail_property_list)
|
||||
{
|
||||
bool status = false;
|
||||
int len = 0;
|
||||
int test_len = 0;
|
||||
int apdu_len = 0;
|
||||
int read_len = 0;
|
||||
uint8_t *apdu;
|
||||
BACNET_ARRAY_INDEX array_index = 0;
|
||||
BACNET_WRITE_PROPERTY_DATA wpdata = { 0 };
|
||||
BACNET_APPLICATION_DATA_VALUE value = { 0 };
|
||||
|
||||
read_len = read_property(rpdata);
|
||||
if ((read_len == BACNET_STATUS_ERROR) &&
|
||||
(rpdata->error_class == ERROR_CLASS_PROPERTY) &&
|
||||
(rpdata->error_code == ERROR_CODE_READ_ACCESS_DENIED)) {
|
||||
/* read-only is a valid response for some properties */
|
||||
} else if (read_len > 0) {
|
||||
/* validate the data from the read request */
|
||||
apdu = rpdata->application_data;
|
||||
apdu_len = read_len;
|
||||
while (apdu_len) {
|
||||
len = bacapp_decode_known_property(apdu, apdu_len, &value,
|
||||
rpdata->object_type, rpdata->object_property);
|
||||
if (len > 0) {
|
||||
test_len += len;
|
||||
if ((len < apdu_len) &&
|
||||
(rpdata->array_index == BACNET_ARRAY_ALL)) {
|
||||
/* more data, therefore, this is an array */
|
||||
array_index = 1;
|
||||
}
|
||||
if (array_index > 0) {
|
||||
apdu += len;
|
||||
apdu_len -= len;
|
||||
array_index++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
printf("property '%s': failed to decode! len=%d\n",
|
||||
bactext_property_name(rpdata->object_property),
|
||||
len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (read_len != test_len) {
|
||||
printf("property '%s': failed to decode! %d!=%d\n",
|
||||
bactext_property_name(rpdata->object_property), test_len,
|
||||
read_len);
|
||||
}
|
||||
if (property_list_member(
|
||||
skip_fail_property_list, rpdata->object_property)) {
|
||||
/* FIXME: known fail to decode */
|
||||
test_len = read_len;
|
||||
}
|
||||
zassert_true(test_len == read_len, NULL);
|
||||
} else if (read_len == 0) {
|
||||
/* empty response is valid for some properties */
|
||||
} else {
|
||||
zassert_not_equal(len, BACNET_STATUS_ERROR,
|
||||
"property '%s': failed to read!\n",
|
||||
bactext_property_name(rpdata->object_property));
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test all the properties of an object for read/write
|
||||
*
|
||||
* @param object_type The type of object to test
|
||||
* @param object_instance The instance number of the object to test
|
||||
* @param property_list The function to get the list of properties
|
||||
* @param read_property The function to read the property
|
||||
* @param write_property The function to write the property
|
||||
* @param skip_fail_property_list The list of properties that
|
||||
* are known to fail to decode after reading
|
||||
*/
|
||||
void bacnet_object_properties_read_write_test(BACNET_OBJECT_TYPE object_type,
|
||||
uint32_t object_instance,
|
||||
rpm_property_lists_function property_list,
|
||||
read_property_function read_property,
|
||||
write_property_function write_property,
|
||||
const int *skip_fail_property_list)
|
||||
{
|
||||
uint8_t apdu[MAX_APDU] = { 0 };
|
||||
BACNET_READ_PROPERTY_DATA rpdata = { 0 };
|
||||
BACNET_WRITE_PROPERTY_DATA wpdata = { 0 };
|
||||
const int *pRequired = NULL;
|
||||
const int *pOptional = NULL;
|
||||
const int *pProprietary = NULL;
|
||||
unsigned count = 0;
|
||||
int len = 0;
|
||||
|
||||
/* ReadProperty parameters */
|
||||
rpdata.application_data = &apdu[0];
|
||||
rpdata.application_data_len = sizeof(apdu);
|
||||
rpdata.object_type = object_type;
|
||||
rpdata.object_instance = object_instance;
|
||||
property_list(&pRequired, &pOptional, &pProprietary);
|
||||
while ((*pRequired) != -1) {
|
||||
rpdata.object_property = *pRequired;
|
||||
rpdata.array_index = BACNET_ARRAY_ALL;
|
||||
len = bacnet_object_property_read_test(
|
||||
&rpdata, read_property, skip_fail_property_list);
|
||||
bacnet_object_property_write_parameter_init(&wpdata, &rpdata, len);
|
||||
bacnet_object_property_write_test(
|
||||
&wpdata, write_property, skip_fail_property_list);
|
||||
pRequired++;
|
||||
}
|
||||
while ((*pOptional) != -1) {
|
||||
rpdata.object_property = *pOptional;
|
||||
rpdata.array_index = BACNET_ARRAY_ALL;
|
||||
bacnet_object_property_read_test(
|
||||
&rpdata, read_property, skip_fail_property_list);
|
||||
bacnet_object_property_write_parameter_init(&wpdata, &rpdata, len);
|
||||
bacnet_object_property_write_test(
|
||||
&wpdata, write_property, skip_fail_property_list);
|
||||
pOptional++;
|
||||
}
|
||||
while ((*pProprietary) != -1) {
|
||||
rpdata.object_property = *pProprietary;
|
||||
rpdata.array_index = BACNET_ARRAY_ALL;
|
||||
bacnet_object_property_read_test(
|
||||
&rpdata, read_property, skip_fail_property_list);
|
||||
bacnet_object_property_write_parameter_init(&wpdata, &rpdata, len);
|
||||
bacnet_object_property_write_test(
|
||||
&wpdata, write_property, skip_fail_property_list);
|
||||
pProprietary++;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Unit test for object property read/write
|
||||
* @author Steve Karg <skarg@users.sourceforge.net>
|
||||
* @date February 2024
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#ifndef _BACNET_PROPERTY_TEST_H_
|
||||
#define _BACNET_PROPERTY_TEST_H_
|
||||
#include <stdint.h>
|
||||
#include <bacnet/rp.h>
|
||||
#include <bacnet/rpm.h>
|
||||
#include <bacnet/wp.h>
|
||||
|
||||
void bacnet_object_properties_read_write_test(
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
uint32_t object_instance,
|
||||
rpm_property_lists_function property_list,
|
||||
read_property_function read_property,
|
||||
write_property_function write_property,
|
||||
const int *skip_fail_property_list);
|
||||
|
||||
int bacnet_object_property_read_test(
|
||||
BACNET_READ_PROPERTY_DATA *rpdata,
|
||||
read_property_function read_property,
|
||||
const int *skip_fail_property_list);
|
||||
|
||||
bool bacnet_object_property_write_test(
|
||||
BACNET_WRITE_PROPERTY_DATA *wpdata,
|
||||
write_property_function write_property,
|
||||
const int *skip_fail_property_list);
|
||||
|
||||
void bacnet_object_property_write_parameter_init(
|
||||
BACNET_WRITE_PROPERTY_DATA *wpdata,
|
||||
BACNET_READ_PROPERTY_DATA *rpdata,
|
||||
int len);
|
||||
|
||||
#endif
|
||||
@@ -27,6 +27,7 @@ add_compile_definitions(
|
||||
|
||||
include_directories(
|
||||
${SRC_DIR}
|
||||
${TST_DIR}/bacnet/basic/object
|
||||
${TST_DIR}/ztest/include
|
||||
)
|
||||
|
||||
@@ -50,6 +51,7 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/indtext.c
|
||||
${SRC_DIR}/bacnet/hostnport.c
|
||||
${SRC_DIR}/bacnet/lighting.c
|
||||
${SRC_DIR}/bacnet/proplist.c
|
||||
${SRC_DIR}/bacnet/timestamp.c
|
||||
${SRC_DIR}/bacnet/wp.c
|
||||
${SRC_DIR}/bacnet/weeklyschedule.c
|
||||
@@ -58,6 +60,7 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/special_event.c
|
||||
# Test and test library files
|
||||
./src/main.c
|
||||
${TST_DIR}/bacnet/basic/object/property_test.c
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
${ZTST_DIR}/ztest.c
|
||||
)
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include <zephyr/ztest.h>
|
||||
#include <bacnet/basic/object/schedule.h>
|
||||
#include <bacnet/bactext.h>
|
||||
#include <property_test.h>
|
||||
|
||||
/**
|
||||
* @addtogroup bacnet_tests
|
||||
@@ -25,70 +25,22 @@ ZTEST(schedule_tests, testSchedule)
|
||||
static void testSchedule(void)
|
||||
#endif
|
||||
{
|
||||
uint8_t apdu[MAX_APDU] = { 0 };
|
||||
int len = 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;
|
||||
bool status = false;
|
||||
uint32_t object_instance = 0;
|
||||
const int skip_fail_property_list[] = {
|
||||
PROP_LIST_OF_OBJECT_PROPERTY_REFERENCES, -1 };
|
||||
|
||||
Schedule_Init();
|
||||
count = Schedule_Count();
|
||||
zassert_true(count > 0, NULL);
|
||||
rpdata.application_data = &apdu[0];
|
||||
rpdata.application_data_len = sizeof(apdu);
|
||||
rpdata.object_type = OBJECT_SCHEDULE;
|
||||
rpdata.object_instance = Schedule_Index_To_Instance(0);;
|
||||
status = Schedule_Valid_Instance(rpdata.object_instance);
|
||||
zassert_true(status, NULL);
|
||||
Schedule_Property_Lists(&pRequired, &pOptional, &pProprietary);
|
||||
while ((*pRequired) != -1) {
|
||||
rpdata.object_property = *pRequired;
|
||||
rpdata.array_index = BACNET_ARRAY_ALL;
|
||||
len = Schedule_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);
|
||||
if (len != test_len) {
|
||||
printf("property '%s': failed to decode!\n",
|
||||
bactext_property_name(rpdata.object_property));
|
||||
}
|
||||
if (rpdata.object_property == PROP_PRIORITY_ARRAY) {
|
||||
/* FIXME: known fail to decode */
|
||||
len = test_len;
|
||||
}
|
||||
zassert_true(test_len >= 0, NULL);
|
||||
} else {
|
||||
printf("property '%s': failed to read!\n",
|
||||
bactext_property_name(rpdata.object_property));
|
||||
}
|
||||
pRequired++;
|
||||
}
|
||||
while ((*pOptional) != -1) {
|
||||
rpdata.object_property = *pOptional;
|
||||
rpdata.array_index = BACNET_ARRAY_ALL;
|
||||
len = Schedule_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);
|
||||
if (len != test_len) {
|
||||
printf("property '%s': failed to decode!\n",
|
||||
bactext_property_name(rpdata.object_property));
|
||||
}
|
||||
zassert_true(test_len >= 0, NULL);
|
||||
} else {
|
||||
printf("property '%s': failed to read!\n",
|
||||
bactext_property_name(rpdata.object_property));
|
||||
}
|
||||
pOptional++;
|
||||
}
|
||||
object_instance = Schedule_Index_To_Instance(0);
|
||||
bacnet_object_properties_read_write_test(
|
||||
OBJECT_SCHEDULE,
|
||||
object_instance,
|
||||
Schedule_Property_Lists,
|
||||
Schedule_Read_Property,
|
||||
Schedule_Write_Property,
|
||||
skip_fail_property_list);
|
||||
}
|
||||
/**
|
||||
* @}
|
||||
|
||||
@@ -27,6 +27,7 @@ add_compile_definitions(
|
||||
|
||||
include_directories(
|
||||
${SRC_DIR}
|
||||
${TST_DIR}/bacnet/basic/object
|
||||
${TST_DIR}/ztest/include
|
||||
)
|
||||
|
||||
@@ -50,6 +51,7 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/indtext.c
|
||||
${SRC_DIR}/bacnet/hostnport.c
|
||||
${SRC_DIR}/bacnet/lighting.c
|
||||
${SRC_DIR}/bacnet/proplist.c
|
||||
${SRC_DIR}/bacnet/timestamp.c
|
||||
${SRC_DIR}/bacnet/wp.c
|
||||
${SRC_DIR}/bacnet/weeklyschedule.c
|
||||
@@ -59,6 +61,7 @@ add_executable(${PROJECT_NAME}
|
||||
# Test and test library files
|
||||
./src/main.c
|
||||
../mock/device_mock.c
|
||||
${TST_DIR}/bacnet/basic/object/property_test.c
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
${ZTST_DIR}/ztest.c
|
||||
)
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include <zephyr/ztest.h>
|
||||
#include <bacnet/basic/object/trendlog.h>
|
||||
#include <bacnet/bactext.h>
|
||||
#include <property_test.h>
|
||||
|
||||
/**
|
||||
* @addtogroup bacnet_tests
|
||||
@@ -21,70 +21,24 @@
|
||||
*/
|
||||
static void test_Trend_Log_ReadProperty(void)
|
||||
{
|
||||
uint8_t apdu[MAX_APDU] = { 0 };
|
||||
int len = 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;
|
||||
bool status = false;
|
||||
const int known_fail_property_list[] = { -1 };
|
||||
|
||||
Trend_Log_Init();
|
||||
count = Trend_Log_Count();
|
||||
zassert_true(count > 0, NULL);
|
||||
rpdata.application_data = &apdu[0];
|
||||
rpdata.application_data_len = sizeof(apdu);
|
||||
rpdata.object_type = OBJECT_TRENDLOG;
|
||||
rpdata.object_instance = Trend_Log_Index_To_Instance(0);;
|
||||
status = Trend_Log_Valid_Instance(rpdata.object_instance);
|
||||
object_instance = Trend_Log_Index_To_Instance(0);
|
||||
status = Trend_Log_Valid_Instance(object_instance);
|
||||
zassert_true(status, NULL);
|
||||
Trend_Log_Property_Lists(&pRequired, &pOptional, &pProprietary);
|
||||
while ((*pRequired) != -1) {
|
||||
rpdata.object_property = *pRequired;
|
||||
rpdata.array_index = BACNET_ARRAY_ALL;
|
||||
len = Trend_Log_Read_Property(&rpdata);
|
||||
if (len > 0) {
|
||||
zassert_not_equal(len, BACNET_STATUS_ERROR, NULL);
|
||||
test_len = bacapp_decode_application_data(rpdata.application_data,
|
||||
(uint8_t)rpdata.application_data_len, &value);
|
||||
if (len != test_len) {
|
||||
printf("property '%s': failed to decode!\n",
|
||||
bactext_property_name(rpdata.object_property));
|
||||
}
|
||||
if (rpdata.object_property == PROP_PRIORITY_ARRAY) {
|
||||
/* FIXME: known fail to decode */
|
||||
len = test_len;
|
||||
}
|
||||
zassert_true(test_len >= 0, NULL);
|
||||
} else {
|
||||
printf("property '%s': failed to read!\n",
|
||||
bactext_property_name(rpdata.object_property));
|
||||
}
|
||||
pRequired++;
|
||||
}
|
||||
while ((*pOptional) != -1) {
|
||||
rpdata.object_property = *pOptional;
|
||||
rpdata.array_index = BACNET_ARRAY_ALL;
|
||||
len = Trend_Log_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);
|
||||
if (len != test_len) {
|
||||
printf("property '%s': failed to decode!\n",
|
||||
bactext_property_name(rpdata.object_property));
|
||||
}
|
||||
zassert_true(test_len >= 0, NULL);
|
||||
} else {
|
||||
printf("property '%s': failed to read!\n",
|
||||
bactext_property_name(rpdata.object_property));
|
||||
}
|
||||
pOptional++;
|
||||
}
|
||||
bacnet_object_properties_read_write_test(
|
||||
OBJECT_TRENDLOG,
|
||||
object_instance,
|
||||
Trend_Log_Property_Lists,
|
||||
Trend_Log_Read_Property,
|
||||
Trend_Log_Write_Property,
|
||||
known_fail_property_list);
|
||||
}
|
||||
/**
|
||||
* @}
|
||||
|
||||
Reference in New Issue
Block a user