1
0
mirror of https://github.com/FreeRTOS/coreMQTT synced 2025-07-03 10:20:18 +08:00
coreMQTT/test/unit/iot_tests_mqtt_validate.c
Muneeb Ahmed 94887b2f35 Reduce complexity in MQTT serialize and API (#701)
* Refactor Wait and PublishAsync API functions

* Refactor _IotMqtt_DeserializePublish

* Move publish setup checks to iot_mqtt_validate.c
2020-01-09 11:23:42 -08:00

427 lines
18 KiB
C

/*
* IoT MQTT V2.1.0
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file iot_tests_mqtt_validate.c
* @brief Tests for the functions in iot_mqtt_validate.c
*/
/* The config header is always included first. */
#include "iot_config.h"
/* Standard includes. */
#include <string.h>
/* SDK initialization include. */
#include "iot_init.h"
/* MQTT internal include. */
#include "private/iot_mqtt_internal.h"
/* Test framework includes. */
#include "unity_fixture.h"
/*-----------------------------------------------------------*/
/**
* @brief Determine which MQTT server mode to test (AWS IoT or Mosquitto).
*/
#if !defined( IOT_TEST_MQTT_MOSQUITTO ) || IOT_TEST_MQTT_MOSQUITTO == 0
#define AWS_IOT_MQTT_SERVER true
#else
#define AWS_IOT_MQTT_SERVER false
#endif
/**
* @brief Length of the subscription array used in
* #TEST_MQTT_Unit_Validate_ValidateSubscriptionList_.
*/
#define SUBSCRIPTION_COUNT ( AWS_IOT_MQTT_SERVER_MAX_TOPIC_FILTERS_PER_SUBSCRIBE )
/**
* @brief A non-NULL function pointer.
*/
#define FUNCTION_POINTER \
( ( void ( * )( void *, \
IotMqttCallbackParam_t * ) ) 0x1 )
/*-----------------------------------------------------------*/
/**
* @brief Test group for MQTT validate tests.
*/
TEST_GROUP( MQTT_Unit_Validate );
/*-----------------------------------------------------------*/
/**
* @brief Test setup for MQTT validate tests.
*/
TEST_SETUP( MQTT_Unit_Validate )
{
TEST_ASSERT_EQUAL_INT( true, IotSdk_Init() );
}
/*-----------------------------------------------------------*/
/**
* @brief Test tear down for MQTT validate tests.
*/
TEST_TEAR_DOWN( MQTT_Unit_Validate )
{
IotSdk_Cleanup();
}
/*-----------------------------------------------------------*/
/**
* @brief Test group runner for MQTT validate tests.
*/
TEST_GROUP_RUNNER( MQTT_Unit_Validate )
{
RUN_TEST_CASE( MQTT_Unit_Validate, ValidateConnectInfo );
RUN_TEST_CASE( MQTT_Unit_Validate, ValidatePublish );
RUN_TEST_CASE( MQTT_Unit_Validate, ValidateOperation );
RUN_TEST_CASE( MQTT_Unit_Validate, ValidateSubscriptionList );
}
/*-----------------------------------------------------------*/
/**
* @brief Test validation of an #IotMqttConnectInfo_t.
*/
TEST( MQTT_Unit_Validate, ValidateConnectInfo )
{
bool validateStatus = false;
IotMqttConnectInfo_t connectInfo = IOT_MQTT_CONNECT_INFO_INITIALIZER;
connectInfo.awsIotMqttMode = AWS_IOT_MQTT_SERVER;
/* NULL parameter. */
validateStatus = _IotMqtt_ValidateConnect( NULL );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
/* Uninitialized parameter. */
validateStatus = _IotMqtt_ValidateConnect( &connectInfo );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
/* Zero-length client identifier with clean session. */
connectInfo.cleanSession = true;
connectInfo.pClientIdentifier = "";
connectInfo.clientIdentifierLength = 0;
validateStatus = _IotMqtt_ValidateConnect( &connectInfo );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
/* Client identifier longer than the MQTT 3.1.1 recommended maximum length. */
connectInfo.pClientIdentifier = "longlongclientidentifier";
connectInfo.clientIdentifierLength = ( uint16_t ) strlen( connectInfo.pClientIdentifier );
validateStatus = _IotMqtt_ValidateConnect( &connectInfo );
TEST_ASSERT_EQUAL_INT( true, validateStatus );
/* AWS IoT MQTT service limit tests. */
#if AWS_IOT_MQTT_SERVER == true
/* Client identifier too long. */
connectInfo.clientIdentifierLength = AWS_IOT_MQTT_SERVER_MAX_CLIENTID_LENGTH + 1;
validateStatus = _IotMqtt_ValidateConnect( &connectInfo );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
connectInfo.clientIdentifierLength = 24;
#endif /* if AWS_IOT_MQTT_SERVER == true */
}
/*-----------------------------------------------------------*/
/**
* @brief Test validation of an #IotMqttPublishInfo_t.
*/
TEST( MQTT_Unit_Validate, ValidatePublish )
{
bool validateStatus = false;
IotMqttPublishInfo_t publishInfo = IOT_MQTT_PUBLISH_INFO_INITIALIZER;
IotMqttCallbackInfo_t callbackInfo = IOT_MQTT_CALLBACK_INFO_INITIALIZER;
IotMqttOperation_t operation = IOT_MQTT_OPERATION_INITIALIZER;
/* NULL parameter. */
validateStatus = _IotMqtt_ValidatePublish( false, NULL, 0, NULL, NULL );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
/* Zero-length topic name. */
publishInfo.pTopicName = "";
publishInfo.topicNameLength = 0;
validateStatus = _IotMqtt_ValidatePublish( false, &publishInfo, 0, NULL, NULL );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
publishInfo.pTopicName = "/test";
publishInfo.topicNameLength = 5;
/* Zero-length/NULL payload. */
publishInfo.pPayload = NULL;
publishInfo.payloadLength = 0;
validateStatus = _IotMqtt_ValidatePublish( false, &publishInfo, 0, NULL, NULL );
TEST_ASSERT_EQUAL_INT( true, validateStatus );
/* NULL payload only allowed with length 0. */
publishInfo.pPayload = NULL;
publishInfo.payloadLength = 1;
validateStatus = _IotMqtt_ValidatePublish( false, &publishInfo, 0, NULL, NULL );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
publishInfo.payloadLength = 0;
/* Negative QoS or QoS > 2. */
publishInfo.qos = ( IotMqttQos_t ) -1;
validateStatus = _IotMqtt_ValidatePublish( false, &publishInfo, 0, NULL, NULL );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
publishInfo.qos = ( IotMqttQos_t ) 3;
validateStatus = _IotMqtt_ValidatePublish( false, &publishInfo, 0, NULL, NULL );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
publishInfo.qos = IOT_MQTT_QOS_0;
/* Positive retry limit with no period. */
publishInfo.retryLimit = 1;
publishInfo.retryMs = 0;
validateStatus = _IotMqtt_ValidatePublish( false, &publishInfo, 0, NULL, NULL );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
/* Positive retry limit with positive period. */
publishInfo.retryLimit = 1;
publishInfo.retryMs = 1;
validateStatus = _IotMqtt_ValidatePublish( false, &publishInfo, 0, NULL, NULL );
TEST_ASSERT_EQUAL_INT( true, validateStatus );
/* Retry limit 0. */
publishInfo.retryLimit = 0;
validateStatus = _IotMqtt_ValidatePublish( false, &publishInfo, 0, NULL, NULL );
TEST_ASSERT_EQUAL_INT( true, validateStatus );
/* Invalid flags. */
validateStatus = _IotMqtt_ValidatePublish( false, &publishInfo, IOT_MQTT_FLAG_WAITABLE, NULL, &operation );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
/* Invalid callback. */
validateStatus = _IotMqtt_ValidatePublish( false, &publishInfo, 0, &callbackInfo, NULL );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
/* Invalid operation. */
publishInfo.qos = IOT_MQTT_QOS_1;
validateStatus = _IotMqtt_ValidatePublish( false, &publishInfo, IOT_MQTT_FLAG_WAITABLE, &callbackInfo, NULL );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
/* Valid flags, callback, and operation. */
validateStatus = _IotMqtt_ValidatePublish( false, &publishInfo, IOT_MQTT_FLAG_WAITABLE, &callbackInfo, &operation );
TEST_ASSERT_EQUAL_INT( true, validateStatus );
/* AWS IoT MQTT service limit tests. */
#if AWS_IOT_MQTT_SERVER == true
/* QoS 2. */
publishInfo.qos = IOT_MQTT_QOS_2;
validateStatus = _IotMqtt_ValidatePublish( true, &publishInfo, 0, NULL, NULL );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
publishInfo.qos = IOT_MQTT_QOS_0;
/* Retained message. */
publishInfo.retain = true;
validateStatus = _IotMqtt_ValidatePublish( true, &publishInfo, 0, NULL, NULL );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
publishInfo.retain = false;
/* Topic name too long. */
publishInfo.topicNameLength = AWS_IOT_MQTT_SERVER_MAX_TOPIC_LENGTH + 1;
validateStatus = _IotMqtt_ValidatePublish( true, &publishInfo, 0, NULL, NULL );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
#endif /* if AWS_IOT_MQTT_SERVER == true */
}
/*-----------------------------------------------------------*/
/**
* @brief Test validation of an #IotMqttOperation_t.
*/
TEST( MQTT_Unit_Validate, ValidateOperation )
{
bool validateStatus = false;
IotMqttOperation_t operation = IotMqtt_MallocOperation( sizeof( _mqttOperation_t ) );
TEST_ASSERT_NOT_NULL( operation );
if( TEST_PROTECT() )
{
( void ) memset( operation, 0x00, sizeof( _mqttOperation_t ) );
/* NULL parameter. */
validateStatus = _IotMqtt_ValidateOperation( NULL );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
/* Non-waitable reference. */
operation->u.operation.flags = 0;
validateStatus = _IotMqtt_ValidateOperation( operation );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
/* Waitable (valid) reference. */
operation->u.operation.flags = IOT_MQTT_FLAG_WAITABLE;
validateStatus = _IotMqtt_ValidateOperation( operation );
TEST_ASSERT_EQUAL_INT( true, validateStatus );
}
IotMqtt_FreeOperation( operation );
}
/*-----------------------------------------------------------*/
/**
* @brief Test validation of a list of #IotMqttSubscription_t.
*/
TEST( MQTT_Unit_Validate, ValidateSubscriptionList )
{
size_t i = 0;
bool validateStatus = false;
IotMqttSubscription_t pSubscriptions[ SUBSCRIPTION_COUNT ] = { IOT_MQTT_SUBSCRIPTION_INITIALIZER };
/* NULL parameter. */
validateStatus = _IotMqtt_ValidateSubscriptionList( IOT_MQTT_SUBSCRIBE, false, NULL, 1 );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
/* Zero parameter. */
validateStatus = _IotMqtt_ValidateSubscriptionList( IOT_MQTT_SUBSCRIBE, false, pSubscriptions, 0 );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
/* Uninitialized subscriptions. */
validateStatus = _IotMqtt_ValidateSubscriptionList( IOT_MQTT_SUBSCRIBE, false, pSubscriptions, SUBSCRIPTION_COUNT );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
/* Initialize all subscriptions to valid values. */
for( i = 0; i < SUBSCRIPTION_COUNT; i++ )
{
pSubscriptions[ i ].pTopicFilter = "/test";
pSubscriptions[ i ].topicFilterLength = 5;
pSubscriptions[ i ].callback.function = FUNCTION_POINTER;
}
validateStatus = _IotMqtt_ValidateSubscriptionList( IOT_MQTT_SUBSCRIBE, false, pSubscriptions, SUBSCRIPTION_COUNT );
TEST_ASSERT_EQUAL_INT( true, validateStatus );
/* One subscription with invalid QoS. */
pSubscriptions[ SUBSCRIPTION_COUNT - 1 ].qos = ( IotMqttQos_t ) -1;
validateStatus = _IotMqtt_ValidateSubscriptionList( IOT_MQTT_SUBSCRIBE, false, pSubscriptions, SUBSCRIPTION_COUNT );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
pSubscriptions[ SUBSCRIPTION_COUNT - 1 ].qos = ( IotMqttQos_t ) 3;
validateStatus = _IotMqtt_ValidateSubscriptionList( IOT_MQTT_SUBSCRIBE, false, pSubscriptions, SUBSCRIPTION_COUNT );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
/* QoS is not validated for UNSUBSCRIBE. */
validateStatus = _IotMqtt_ValidateSubscriptionList( IOT_MQTT_UNSUBSCRIBE, false, pSubscriptions, SUBSCRIPTION_COUNT );
TEST_ASSERT_EQUAL_INT( true, validateStatus );
pSubscriptions[ SUBSCRIPTION_COUNT - 1 ].qos = IOT_MQTT_QOS_0;
/* One subscription with no callback. */
pSubscriptions[ SUBSCRIPTION_COUNT - 1 ].callback.function = NULL;
validateStatus = _IotMqtt_ValidateSubscriptionList( IOT_MQTT_SUBSCRIBE, false, pSubscriptions, SUBSCRIPTION_COUNT );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
/* Callback is not validated for UNSUBSCRIBE. */
validateStatus = _IotMqtt_ValidateSubscriptionList( IOT_MQTT_UNSUBSCRIBE, false, pSubscriptions, SUBSCRIPTION_COUNT );
TEST_ASSERT_EQUAL_INT( true, validateStatus );
pSubscriptions[ SUBSCRIPTION_COUNT - 1 ].callback.function = FUNCTION_POINTER;
/* Valid subscription filters. */
pSubscriptions[ SUBSCRIPTION_COUNT - 1 ].pTopicFilter = "#";
pSubscriptions[ SUBSCRIPTION_COUNT - 1 ].topicFilterLength = 1;
validateStatus = _IotMqtt_ValidateSubscriptionList( IOT_MQTT_SUBSCRIBE, false, pSubscriptions, SUBSCRIPTION_COUNT );
TEST_ASSERT_EQUAL_INT( true, validateStatus );
pSubscriptions[ SUBSCRIPTION_COUNT - 1 ].pTopicFilter = "/#";
pSubscriptions[ SUBSCRIPTION_COUNT - 1 ].topicFilterLength = 2;
validateStatus = _IotMqtt_ValidateSubscriptionList( IOT_MQTT_SUBSCRIBE, false, pSubscriptions, SUBSCRIPTION_COUNT );
TEST_ASSERT_EQUAL_INT( true, validateStatus );
pSubscriptions[ SUBSCRIPTION_COUNT - 1 ].pTopicFilter = "/+/";
pSubscriptions[ SUBSCRIPTION_COUNT - 1 ].topicFilterLength = 3;
validateStatus = _IotMqtt_ValidateSubscriptionList( IOT_MQTT_SUBSCRIBE, false, pSubscriptions, SUBSCRIPTION_COUNT );
TEST_ASSERT_EQUAL_INT( true, validateStatus );
pSubscriptions[ SUBSCRIPTION_COUNT - 1 ].pTopicFilter = "+/";
pSubscriptions[ SUBSCRIPTION_COUNT - 1 ].topicFilterLength = 2;
validateStatus = _IotMqtt_ValidateSubscriptionList( IOT_MQTT_SUBSCRIBE, false, pSubscriptions, SUBSCRIPTION_COUNT );
TEST_ASSERT_EQUAL_INT( true, validateStatus );
pSubscriptions[ SUBSCRIPTION_COUNT - 1 ].pTopicFilter = "/+";
pSubscriptions[ SUBSCRIPTION_COUNT - 1 ].topicFilterLength = 2;
validateStatus = _IotMqtt_ValidateSubscriptionList( IOT_MQTT_SUBSCRIBE, false, pSubscriptions, SUBSCRIPTION_COUNT );
TEST_ASSERT_EQUAL_INT( true, validateStatus );
pSubscriptions[ SUBSCRIPTION_COUNT - 1 ].pTopicFilter = "+/+/+/+";
pSubscriptions[ SUBSCRIPTION_COUNT - 1 ].topicFilterLength = 7;
validateStatus = _IotMqtt_ValidateSubscriptionList( IOT_MQTT_SUBSCRIBE, false, pSubscriptions, SUBSCRIPTION_COUNT );
TEST_ASSERT_EQUAL_INT( true, validateStatus );
/* Invalid subscription filters. */
pSubscriptions[ SUBSCRIPTION_COUNT - 1 ].pTopicFilter = "#/";
pSubscriptions[ SUBSCRIPTION_COUNT - 1 ].topicFilterLength = 2;
validateStatus = _IotMqtt_ValidateSubscriptionList( IOT_MQTT_SUBSCRIBE, false, pSubscriptions, SUBSCRIPTION_COUNT );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
pSubscriptions[ SUBSCRIPTION_COUNT - 1 ].pTopicFilter = "#/#";
pSubscriptions[ SUBSCRIPTION_COUNT - 1 ].topicFilterLength = 3;
validateStatus = _IotMqtt_ValidateSubscriptionList( IOT_MQTT_SUBSCRIBE, false, pSubscriptions, SUBSCRIPTION_COUNT );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
pSubscriptions[ SUBSCRIPTION_COUNT - 1 ].pTopicFilter = "a#";
pSubscriptions[ SUBSCRIPTION_COUNT - 1 ].topicFilterLength = 2;
validateStatus = _IotMqtt_ValidateSubscriptionList( IOT_MQTT_SUBSCRIBE, false, pSubscriptions, SUBSCRIPTION_COUNT );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
pSubscriptions[ SUBSCRIPTION_COUNT - 1 ].pTopicFilter = "a+";
pSubscriptions[ SUBSCRIPTION_COUNT - 1 ].topicFilterLength = 2;
validateStatus = _IotMqtt_ValidateSubscriptionList( IOT_MQTT_SUBSCRIBE, false, pSubscriptions, SUBSCRIPTION_COUNT );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
pSubscriptions[ SUBSCRIPTION_COUNT - 1 ].pTopicFilter = "+a";
pSubscriptions[ SUBSCRIPTION_COUNT - 1 ].topicFilterLength = 2;
validateStatus = _IotMqtt_ValidateSubscriptionList( IOT_MQTT_SUBSCRIBE, false, pSubscriptions, SUBSCRIPTION_COUNT );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
/* AWS IoT MQTT service limit tests. */
#if AWS_IOT_MQTT_SERVER == true
/* Too many subscriptions. */
validateStatus = _IotMqtt_ValidateSubscriptionList( IOT_MQTT_SUBSCRIBE,
true,
pSubscriptions,
AWS_IOT_MQTT_SERVER_MAX_TOPIC_FILTERS_PER_SUBSCRIBE + 1 );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
/* QoS 2. */
pSubscriptions[ 0 ].qos = IOT_MQTT_QOS_2;
validateStatus = _IotMqtt_ValidateSubscriptionList( IOT_MQTT_SUBSCRIBE,
true,
pSubscriptions,
SUBSCRIPTION_COUNT );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
pSubscriptions[ 0 ].qos = IOT_MQTT_QOS_0;
/* Topic filter too long. */
pSubscriptions[ 0 ].topicFilterLength = AWS_IOT_MQTT_SERVER_MAX_TOPIC_LENGTH + 1;
validateStatus = _IotMqtt_ValidateSubscriptionList( IOT_MQTT_SUBSCRIBE,
true,
pSubscriptions,
SUBSCRIPTION_COUNT );
TEST_ASSERT_EQUAL_INT( false, validateStatus );
#endif /* if AWS_IOT_MQTT_SERVER == true */
}
/*-----------------------------------------------------------*/