diff --git a/docs/doxygen/pages.dox b/docs/doxygen/pages.dox
index fba6ecf2..15cbc69d 100644
--- a/docs/doxygen/pages.dox
+++ b/docs/doxygen/pages.dox
@@ -75,16 +75,16 @@ Some configuration settings are C pre-processor constants, and some are function
/**
@page shadow_functions Functions
@brief Primary functions of the Shadow library:
-@subpage shadow_matchtopic_function
-@subpage shadow_gettopicstring_function
+@subpage shadow_matchtopicstring_function
+@subpage shadow_assembletopicstring_function
-@page shadow_matchtopic_function Shadow_MatchTopic
-@snippet shadow.h declare_shadow_matchtopic
-@copydoc Shadow_MatchTopic
+@page shadow_matchtopicstring_function Shadow_MatchTopicString
+@snippet shadow.h declare_shadow_matchtopicstring
+@copydoc Shadow_MatchTopicString
-@page shadow_gettopicstring_function Shadow_GetTopicString
-@snippet shadow.h declare_shadow_gettopicstring
-@copydoc Shadow_GetTopicString
+@page shadow_assembletopicstring_function Shadow_AssembleTopicString
+@snippet shadow.h declare_shadow_assembletopicstring
+@copydoc Shadow_AssembleTopicString
*/
diff --git a/lexicon.txt b/lexicon.txt
index 6f03e3b4..98a31c59 100644
--- a/lexicon.txt
+++ b/lexicon.txt
@@ -43,6 +43,8 @@ matchtopic
mdash
messagetype
mqtt
+myshadow
+myshadowname
mything
mythingname
noninfringement
@@ -51,11 +53,16 @@ operationlength
os
outlength
param
+pconsumedtopiclength
pmessagetype
png
posix
+pname
+pnamelength
poutlength
pre
+pshadowname
+pshadownamelength
pstring
psubstring
pthingname
@@ -65,6 +72,8 @@ ptopicbuffer
ptopicname
rm
sdk
+shadowname
+shadownamelength
shadowstatus
shadowtopicstringtypedelete
shadowtopicstringtypedeleteaccepted
@@ -87,6 +96,7 @@ sublicense
substringlength
suffixlength
td
+testshadowname
testthingname
thingname
thingnamelength
@@ -97,3 +107,4 @@ topicnamelength
topictype
tr
utest
+un
diff --git a/source/include/shadow.h b/source/include/shadow.h
index eb7175a9..37d3873c 100644
--- a/source/include/shadow.h
+++ b/source/include/shadow.h
@@ -67,7 +67,7 @@ typedef enum ShadowMessageType
* @ingroup shadow_enum_types
* @brief Each of these values describes the type of a shadow topic string.
*
- * These are used for topicType parameter of Shadow_GetTopicString() to tell it
+ * These are used for topicType parameter of Shadow_AssembleTopicString() to tell it
* what topic string to assemble.
*/
typedef enum ShadowTopicStringType
@@ -92,15 +92,17 @@ typedef enum ShadowTopicStringType
*/
typedef enum ShadowStatus
{
- SHADOW_SUCCESS = 0, /**< @brief Shadow function success. */
- SHADOW_FAIL, /**< @brief Shadow function encountered error. */
- SHADOW_BAD_PARAMETER, /**< @brief Input parameter is invalid. */
- SHADOW_BUFFER_TOO_SMALL, /**< @brief The provided buffer is too small. */
- SHADOW_THINGNAME_PARSE_FAILED, /**< @brief Could not parse the thing name. */
- SHADOW_SHADOW_MESSAGE_TYPE_PARSE_FAILED /**< @brief Could not parse the shadow type. */
+ SHADOW_SUCCESS = 0, /**< @brief Shadow function success. */
+ SHADOW_FAIL, /**< @brief Shadow function encountered error. */
+ SHADOW_BAD_PARAMETER, /**< @brief Input parameter is invalid. */
+ SHADOW_BUFFER_TOO_SMALL, /**< @brief The provided buffer is too small. */
+ SHADOW_THINGNAME_PARSE_FAILED, /**< @brief Could not parse the thing name. */
+ SHADOW_MESSAGE_TYPE_PARSE_FAILED, /**< @brief Could not parse the shadow type. */
+ SHADOW_ROOT_PARSE_FAILED, /**< @brief Could not parse the classic or named shadow root. */
+ SHADOW_SHADOWNAME_PARSE_FAILED /**< @brief Could not parse the shadow name (in the case of a named shadow topic). */
} ShadowStatus_t;
-/*------------------------ Shadow library functions -------------------------*/
+/*------------------------ Shadow library constants -------------------------*/
/**
* @ingroup shadow_constants
@@ -115,11 +117,37 @@ typedef enum ShadowStatus
*/
#define SHADOW_PREFIX_LENGTH ( ( uint16_t ) ( sizeof( SHADOW_PREFIX ) - 1U ) )
+/**
+ * @ingroup shadow_constants
+ * @brief The root of all unnamed "Classic" Shadow MQTT topics
+ * from here https://docs.aws.amazon.com/iot/latest/developerguide/device-shadow-mqtt.html.
+ */
+#define SHADOW_CLASSIC_ROOT "/shadow"
+
+/**
+ * @ingroup shadow_constants
+ * @brief The length of #SHADOW_CLASSIC_ROOT.
+ */
+#define SHADOW_CLASSIC_ROOT_LENGTH ( ( uint16_t ) ( sizeof( SHADOW_CLASSIC_ROOT ) - 1U ) )
+
+/**
+ * @ingroup shadow_constants
+ * @brief The common root of all named Shadow MQTT topics
+ * from here https://docs.aws.amazon.com/iot/latest/developerguide/device-shadow-mqtt.html.
+ */
+#define SHADOW_NAMED_ROOT "/shadow/name/"
+
+/**
+ * @ingroup shadow_constants
+ * @brief The length of #SHADOW_NAMED_ROOT.
+ */
+#define SHADOW_NAMED_ROOT_LENGTH ( ( uint16_t ) ( sizeof( SHADOW_NAMED_ROOT ) - 1U ) )
+
/**
* @ingroup shadow_constants
* @brief The string representing a Shadow "DELETE" operation in a Shadow MQTT topic.
*/
-#define SHADOW_OP_DELETE "/shadow/delete"
+#define SHADOW_OP_DELETE "/delete"
/**
* @ingroup shadow_constants
@@ -131,7 +159,7 @@ typedef enum ShadowStatus
* @ingroup shadow_constants
* @brief The string representing a Shadow "GET" operation in a Shadow MQTT topic.
*/
-#define SHADOW_OP_GET "/shadow/get"
+#define SHADOW_OP_GET "/get"
/**
* @ingroup shadow_constants
@@ -143,7 +171,7 @@ typedef enum ShadowStatus
* @ingroup shadow_constants
* @brief The string representing a Shadow "UPDATE" operation in a Shadow MQTT topic.
*/
-#define SHADOW_OP_UPDATE "/shadow/update"
+#define SHADOW_OP_UPDATE "/update"
/**
* @ingroup shadow_constants
@@ -217,119 +245,230 @@ typedef enum ShadowStatus
*/
#define SHADOW_THINGNAME_LENGTH_MAX ( 128U )
+/**
+ * @ingroup shadow_constants
+ * @brief The maximum length of Shadow Name.
+ */
+#define SHADOW_NAME_LENGTH_MAX ( 64U )
+
+/**
+ * @ingroup shadow_constants
+ * @brief The name string for the unnamed "Classic" shadow.
+ */
+#define SHADOW_NAME_CLASSIC ""
+
+/**
+ * @ingroup shadow_constants
+ * @brief The length of #SHADOW_NAME_CLASSIC.
+ */
+#define SHADOW_NAME_CLASSIC_LENGTH ( ( uint16_t ) ( sizeof( SHADOW_NAME_CLASSIC ) - 1U ) )
+
/**
* @ingroup shadow_constants
* @brief Compute shadow topic length.
*
* The format of shadow topic strings is defined at https://docs.aws.amazon.com/iot/latest/developerguide/device-shadow-mqtt.html
*
- * A shadow topic string takes one of the two forms:
+ * A shadow topic string takes one of the two forms, in the case of an unnamed ("Classic") shadow:
* $aws/things/\/shadow/\
* $aws/things/\/shadow/\/\
*
- * The \, \ and \ segments correspond to the three input
- * parameters of this macro. The \ part can be null.
+ * Or as follows, in the case of a named shadow:
+ * $aws/things/\/shadow/name//
+ * $aws/things/\/shadow/name///\
*
- * When thingName is known to be "myThing" at compile time, invoke the macro like this:
+ * The \, \, \ and \ segments correspond to the
+ * four input parameters of this macro. The \ part can be null.
+ *
+ * When thingName and shadow name are known to be "myThing" and "myShadow" at compile time,
+ * invoke the macro like this:
* (In this case, the length is a constant at compile time.)
*
- * SHADOW_TOPIC_LENGTH( SHADOW_OP_UPDATE_LENGTH, SHADOW_SUFFIX_DELTA_LENGTH, 7 )
+ * SHADOW_TOPIC_LEN( SHADOW_OP_UPDATE_LENGTH, SHADOW_SUFFIX_DELTA_LENGTH, 7, 8 )
*
- * When thingName is only known at run time and held in a variable myThingName, invoke
- * the macro like this:
+ * When thingName and shadowName are only known at run time, and held in variables myThingName
+ * and myShadowName, invoke the macro like this:
*
- * SHADOW_TOPIC_LENGTH( SHADOW_OP_UPDATE_LENGTH, SHADOW_SUFFIX_DELTA_LENGTH,
- * strlen( ( const char * ) myThingName ) )
+ * SHADOW_TOPIC_LEN( SHADOW_OP_UPDATE_LENGTH, SHADOW_SUFFIX_DELTA_LENGTH,
+ * strlen( ( const char * ) myThingName ),
+ * strlen( ( const char * ) myShadowName ) )
*
- * @param[operationLength] Can be one of:
- * - #SHADOW_OP_UPDATE_LENGTH
- * - #SHADOW_OP_DELETE_LENGTH
- * - #SHADOW_OP_GET_LENGTH
- * @param[suffixLength] Can be one of:
- * - #SHADOW_SUFFIX_NULL_LENGTH
- * - #SHADOW_SUFFIX_ACCEPTED_LENGTH
- * - #SHADOW_SUFFIX_REJECTED_LENGTH
- * - #SHADOW_SUFFIX_DELTA_LENGTH
- * - #SHADOW_SUFFIX_DOCUMENTS_LENGTH
- * @param[thingNameLength] Length of the thingName excluding the ending NULL.
+ * To compute an unnamed ("Classic") shadow length, the shadowName length passed must be zero.
+ *
+ * @param[in] operationLength Can be one of:
+ * - #SHADOW_OP_UPDATE_LENGTH
+ * - #SHADOW_OP_DELETE_LENGTH
+ * - #SHADOW_OP_GET_LENGTH
+ * @param[in] suffixLength Can be one of:
+ * - #SHADOW_SUFFIX_NULL_LENGTH
+ * - #SHADOW_SUFFIX_ACCEPTED_LENGTH
+ * - #SHADOW_SUFFIX_REJECTED_LENGTH
+ * - #SHADOW_SUFFIX_DELTA_LENGTH
+ * - #SHADOW_SUFFIX_DOCUMENTS_LENGTH
+ * @param[in] thingNameLength Length of the thingName excluding the ending NULL.
+ * @param[in] shadowNameLength Length of the shadowName excluding the ending NULL. Zero for "Classic" shadow.
*
* @return Length of the shadow topic in bytes.
*/
-#define SHADOW_TOPIC_LENGTH( operationLength, suffixLength, thingNameLength ) \
- ( operationLength + suffixLength + thingNameLength + SHADOW_PREFIX_LENGTH )
+#define SHADOW_TOPIC_LEN( operationLength, suffixLength, thingNameLength, shadowNameLength ) \
+ ( operationLength + suffixLength + thingNameLength + shadowNameLength + \
+ SHADOW_PREFIX_LENGTH + \
+ ( ( shadowNameLength > 0 ) ? SHADOW_NAMED_ROOT_LENGTH : SHADOW_CLASSIC_ROOT_LENGTH ) )
/**
- * @brief Compute the length of shadow topic "$aws/things//shadow/update".
+ * @ingroup shadow_constants
+ * @brief Compute the length of shadow topic "$aws/things//shadow/update" or
+ * "$aws/things//shadow/name//update".
+ *
+ * @param[in] thingNameLength Length of the thingName excluding the ending NULL.
+ * @param[in] shadowNameLength Length of the shadowName excluding the ending NULL. Zero for "Classic" shadow.
+ *
+ * @return Length of the shadow topic in bytes.
*/
-#define SHADOW_TOPIC_LENGTH_UPDATE( thingNameLength ) \
- SHADOW_TOPIC_LENGTH( SHADOW_OP_UPDATE_LENGTH, SHADOW_SUFFIX_NULL_LENGTH, thingNameLength )
+#define SHADOW_TOPIC_LEN_UPDATE( thingNameLength, shadowNameLength ) \
+ SHADOW_TOPIC_LEN( SHADOW_OP_UPDATE_LENGTH, SHADOW_SUFFIX_NULL_LENGTH, thingNameLength, shadowNameLength )
/**
- * @brief Compute the length of shadow topic "$aws/things//shadow/update/accepted".
+ * @ingroup shadow_constants
+ * @brief Compute the length of shadow topic "$aws/things//shadow/update/accepted" or
+ * "$aws/things//shadow/name//update/accepted".
+ *
+ * @param[in] thingNameLength Length of the thingName excluding the ending NULL.
+ * @param[in] shadowNameLength Length of the shadowName excluding the ending NULL. Zero for "Classic" shadow.
+ *
+ * @return Length of the shadow topic in bytes.
*/
-#define SHADOW_TOPIC_LENGTH_UPDATE_ACCEPTED( thingNameLength ) \
- SHADOW_TOPIC_LENGTH( SHADOW_OP_UPDATE_LENGTH, SHADOW_SUFFIX_ACCEPTED_LENGTH, thingNameLength )
+#define SHADOW_TOPIC_LEN_UPDATE_ACC( thingNameLength, shadowNameLength ) \
+ SHADOW_TOPIC_LEN( SHADOW_OP_UPDATE_LENGTH, SHADOW_SUFFIX_ACCEPTED_LENGTH, thingNameLength, shadowNameLength )
/**
- * @brief Compute the length of shadow topic "$aws/things//shadow/update/rejected".
+ * @ingroup shadow_constants
+ * @brief Compute the length of shadow topic "$aws/things//shadow/update/rejected" or
+ * "$aws/things//shadow/name//update/rejected".
+ *
+ * @param[in] thingNameLength Length of the thingName excluding the ending NULL.
+ * @param[in] shadowNameLength Length of the shadowName excluding the ending NULL. Zero for "Classic" shadow.
+ *
+ * @return Length of the shadow topic in bytes.
*/
-#define SHADOW_TOPIC_LENGTH_UPDATE_REJECTED( thingNameLength ) \
- SHADOW_TOPIC_LENGTH( SHADOW_OP_UPDATE_LENGTH, SHADOW_SUFFIX_REJECTED_LENGTH, thingNameLength )
+#define SHADOW_TOPIC_LEN_UPDATE_REJ( thingNameLength, shadowNameLength ) \
+ SHADOW_TOPIC_LEN( SHADOW_OP_UPDATE_LENGTH, SHADOW_SUFFIX_REJECTED_LENGTH, thingNameLength, shadowNameLength )
/**
- * @brief Compute the length of shadow topic "$aws/things//shadow/update/documents".
+ * @ingroup shadow_constants
+ * @brief Compute the length of shadow topic "$aws/things//shadow/update/documents" or
+ * "$aws/things//shadow/name//update/documents".
+ *
+ * @param[in] thingNameLength Length of the thingName excluding the ending NULL.
+ * @param[in] shadowNameLength Length of the shadowName excluding the ending NULL. Zero for "Classic" shadow.
+ *
+ * @return Length of the shadow topic in bytes.
*/
-#define SHADOW_TOPIC_LENGTH_UPDATE_DOCUMENTS( thingNameLength ) \
- SHADOW_TOPIC_LENGTH( SHADOW_OP_UPDATE_LENGTH, SHADOW_SUFFIX_DOCUMENTS_LENGTH, thingNameLength )
+#define SHADOW_TOPIC_LEN_UPDATE_DOCS( thingNameLength, shadowNameLength ) \
+ SHADOW_TOPIC_LEN( SHADOW_OP_UPDATE_LENGTH, SHADOW_SUFFIX_DOCUMENTS_LENGTH, thingNameLength, shadowNameLength )
/**
- * @brief Compute the length of shadow topic "$aws/things//shadow/update/delta".
+ * @ingroup shadow_constants
+ * @brief Compute the length of shadow topic "$aws/things//shadow/update/delta" or
+ * "$aws/things//shadow/name//update/delta".
+ *
+ * @param[in] thingNameLength Length of the thingName excluding the ending NULL.
+ * @param[in] shadowNameLength Length of the shadowName excluding the ending NULL. Zero for "Classic" shadow.
+ *
+ * @return Length of the shadow topic in bytes.
*/
-#define SHADOW_TOPIC_LENGTH_UPDATE_DELTA( thingNameLength ) \
- SHADOW_TOPIC_LENGTH( SHADOW_OP_UPDATE_LENGTH, SHADOW_SUFFIX_DELTA_LENGTH, thingNameLength )
+#define SHADOW_TOPIC_LEN_UPDATE_DELTA( thingNameLength, shadowNameLength ) \
+ SHADOW_TOPIC_LEN( SHADOW_OP_UPDATE_LENGTH, SHADOW_SUFFIX_DELTA_LENGTH, thingNameLength, shadowNameLength )
/**
- * @brief Compute the length of shadow topic "$aws/things//shadow/get".
+ * @ingroup shadow_constants
+ * @brief Compute the length of shadow topic "$aws/things//shadow/get" or
+ * "$aws/things//shadow/name//get".
+ *
+ * @param[in] thingNameLength Length of the thingName excluding the ending NULL.
+ * @param[in] shadowNameLength Length of the shadowName excluding the ending NULL. Zero for "Classic" shadow.
+ *
+ * @return Length of the shadow topic in bytes.
*/
-#define SHADOW_TOPIC_LENGTH_GET( thingNameLength ) \
- SHADOW_TOPIC_LENGTH( SHADOW_OP_GET_LENGTH, SHADOW_SUFFIX_NULL_LENGTH, thingNameLength )
+#define SHADOW_TOPIC_LEN_GET( thingNameLength, shadowNameLength ) \
+ SHADOW_TOPIC_LEN( SHADOW_OP_GET_LENGTH, SHADOW_SUFFIX_NULL_LENGTH, thingNameLength, shadowNameLength )
/**
- * @brief Compute the length of shadow topic "$aws/things//shadow/get/accepted".
+ * @ingroup shadow_constants
+ * @brief Compute the length of shadow topic "$aws/things//shadow/get/accepted" or
+ * "$aws/things//shadow/name//get/accepted".
+ *
+ * @param[in] thingNameLength Length of the thingName excluding the ending NULL.
+ * @param[in] shadowNameLength Length of the shadowName excluding the ending NULL. Zero for "Classic" shadow.
+ *
+ * @return Length of the shadow topic in bytes.
*/
-#define SHADOW_TOPIC_LENGTH_GET_ACCEPTED( thingNameLength ) \
- SHADOW_TOPIC_LENGTH( SHADOW_OP_GET_LENGTH, SHADOW_SUFFIX_ACCEPTED_LENGTH, thingNameLength )
+#define SHADOW_TOPIC_LEN_GET_ACC( thingNameLength, shadowNameLength ) \
+ SHADOW_TOPIC_LEN( SHADOW_OP_GET_LENGTH, SHADOW_SUFFIX_ACCEPTED_LENGTH, thingNameLength, shadowNameLength )
/**
- * @brief Compute the length of shadow topic "$aws/things//shadow/get/rejected".
+ * @ingroup shadow_constants
+ * @brief Compute the length of shadow topic "$aws/things//shadow/get/rejected" or
+ * "$aws/things//shadow/name//get/rejected".
+ *
+ * @param[in] thingNameLength Length of the thingName excluding the ending NULL.
+ * @param[in] shadowNameLength Length of the shadowName excluding the ending NULL. Zero for "Classic" shadow.
+ *
+ * @return Length of the shadow topic in bytes.
*/
-#define SHADOW_TOPIC_LENGTH_GET_REJECTED( thingNameLength ) \
- SHADOW_TOPIC_LENGTH( SHADOW_OP_GET_LENGTH, SHADOW_SUFFIX_REJECTED_LENGTH, thingNameLength )
+#define SHADOW_TOPIC_LEN_GET_REJ( thingNameLength, shadowNameLength ) \
+ SHADOW_TOPIC_LEN( SHADOW_OP_GET_LENGTH, SHADOW_SUFFIX_REJECTED_LENGTH, thingNameLength, shadowNameLength )
/**
- * @brief Compute the length of shadow topic "$aws/things//shadow/delete".
+ * @ingroup shadow_constants
+ * @brief Compute the length of shadow topic "$aws/things//shadow/delete" or
+ * "$aws/things//shadow/name//delete".
+ *
+ * @param[in] thingNameLength Length of the thingName excluding the ending NULL.
+ * @param[in] shadowNameLength Length of the shadowName excluding the ending NULL. Zero for "Classic" shadow.
+ *
+ * @return Length of the shadow topic in bytes.
*/
-#define SHADOW_TOPIC_LENGTH_DELETE( thingNameLength ) \
- SHADOW_TOPIC_LENGTH( SHADOW_OP_DELETE_LENGTH, SHADOW_SUFFIX_NULL_LENGTH, thingNameLength )
+#define SHADOW_TOPIC_LEN_DELETE( thingNameLength, shadowNameLength ) \
+ SHADOW_TOPIC_LEN( SHADOW_OP_DELETE_LENGTH, SHADOW_SUFFIX_NULL_LENGTH, thingNameLength, shadowNameLength )
/**
- * @brief Compute the length of shadow topic "$aws/things//shadow/delete/accepted".
+ * @ingroup shadow_constants
+ * @brief Compute the length of shadow topic "$aws/things//shadow/delete/accepted" or
+ * "$aws/things//shadow/name//delete/accepted".
+ *
+ * @param[in] thingNameLength Length of the thingName excluding the ending NULL.
+ * @param[in] shadowNameLength Length of the shadowName excluding the ending NULL. Zero for "Classic" shadow.
+ *
+ * @return Length of the shadow topic in bytes.
*/
-#define SHADOW_TOPIC_LENGTH_DELETE_ACCEPTED( thingNameLength ) \
- SHADOW_TOPIC_LENGTH( SHADOW_OP_DELETE_LENGTH, SHADOW_SUFFIX_ACCEPTED_LENGTH, thingNameLength )
+#define SHADOW_TOPIC_LEN_DELETE_ACC( thingNameLength, shadowNameLength ) \
+ SHADOW_TOPIC_LEN( SHADOW_OP_DELETE_LENGTH, SHADOW_SUFFIX_ACCEPTED_LENGTH, thingNameLength, shadowNameLength )
/**
- * @brief Compute the length of shadow topic "$aws/things//shadow/delete/rejected".
+ * @ingroup shadow_constants
+ * @brief Compute the length of shadow topic "$aws/things//shadow/delete/rejected" or
+ * "$aws/things//shadow/name//delete/rejected".
+ *
+ * @param[in] thingNameLength Length of the thingName excluding the ending NULL.
+ * @param[in] shadowNameLength Length of the shadowName excluding the ending NULL. Zero for "Classic" shadow.
+ *
+ * @return Length of the shadow topic in bytes.
*/
-#define SHADOW_TOPIC_LENGTH_DELETE_REJECTED( thingNameLength ) \
- SHADOW_TOPIC_LENGTH( SHADOW_OP_DELETE_LENGTH, SHADOW_SUFFIX_REJECTED_LENGTH, thingNameLength )
+#define SHADOW_TOPIC_LEN_DELETE_REJ( thingNameLength, shadowNameLength ) \
+ SHADOW_TOPIC_LEN( SHADOW_OP_DELETE_LENGTH, SHADOW_SUFFIX_REJECTED_LENGTH, thingNameLength, shadowNameLength )
/**
* @ingroup shadow_constants
* @brief Compute the length of the longest shadow topic.
+ *
+ * @param[in] thingNameLength Length of the thingName excluding the ending NULL.
+ * @param[in] shadowNameLength Length of the shadowName excluding the ending NULL. Zero for "Classic" shadow.
+ *
+ * @return Length of the shadow topic in bytes.
*/
-#define SHADOW_TOPIC_LENGTH_MAX( thingNameLength ) \
- SHADOW_TOPIC_LENGTH( SHADOW_OP_UPDATE_LENGTH, SHADOW_SUFFIX_DOCUMENTS_LENGTH, thingNameLength )
+#define SHADOW_TOPIC_LEN_MAX( thingNameLength, shadowNameLength ) \
+ SHADOW_TOPIC_LEN( SHADOW_OP_UPDATE_LENGTH, SHADOW_SUFFIX_DOCUMENTS_LENGTH, thingNameLength, shadowNameLength )
/**
* @ingroup shadow_constants
@@ -337,99 +476,181 @@ typedef enum ShadowStatus
*
* When thingName is known to be "myThing" at compile time, invoke the macro like this:
*
- * SHADOW_TOPIC_STRING( SHADOW_OP_UPDATE, SHADOW_SUFFIX_DELTA, "myThing" )
+ * SHADOW_TOPIC_STR( SHADOW_OP_UPDATE, SHADOW_SUFFIX_DELTA, "myThing" )
*
* When thingName is only known at run time, do not use this macro. Use the
* Shadow_GetTopicString() function instead.
*
- * @param[operation] Can be one of:
- * - #SHADOW_OP_UPDATE
- * - #SHADOW_OP_DELETE
- * - #SHADOW_OP_GET
- * @param[suffix] Can be one of:
- * - #SHADOW_SUFFIX_NULL
- * - #SHADOW_SUFFIX_ACCEPTED
- * - #SHADOW_SUFFIX_REJECTED
- * - #SHADOW_SUFFIX_DELTA
- * - #SHADOW_SUFFIX_DOCUMENTS
+ * @param[in] operation Can be one of:
+ * - #SHADOW_OP_UPDATE
+ * - #SHADOW_OP_DELETE
+ * - #SHADOW_OP_GET
+ * @param[in] suffix Can be one of:
+ * - #SHADOW_SUFFIX_NULL
+ * - #SHADOW_SUFFIX_ACCEPTED
+ * - #SHADOW_SUFFIX_REJECTED
+ * - #SHADOW_SUFFIX_DELTA
+ * - #SHADOW_SUFFIX_DOCUMENTS
*
- * @param[thingName] Thing Name.
+ * @param[in] thingName Thing Name.
+ * @param[in] shadowName Shadow Name. Empty string for an unnamed ("Classic") shadow.
*
* @return Topic string.
*/
-#define SHADOW_TOPIC_STRING( thingName, operation, suffix ) \
- ( SHADOW_PREFIX thingName operation suffix )
+#define SHADOW_TOPIC_STR( thingName, shadowName, operation, suffix ) \
+ ( ( sizeof( shadowName ) > 1 ) ? \
+ ( SHADOW_PREFIX thingName SHADOW_NAMED_ROOT shadowName operation suffix ) : \
+ ( SHADOW_PREFIX thingName SHADOW_CLASSIC_ROOT operation suffix ) )
/**
- * @brief Assemble shadow topic string "$aws/things//shadow/update".
+ * @ingroup shadow_constants
+ * @brief Assemble shadow topic string "$aws/things//shadow/update" or
+ * "$aws/things//shadow/name//update".
+ *
+ * @param[in] thingName Thing Name.
+ * @param[in] shadowName Shadow Name. Empty string for an unnamed ("Classic") shadow.
+ *
+ * @return Topic string.
*/
-#define SHADOW_TOPIC_STRING_UPDATE( thingName ) \
- SHADOW_TOPIC_STRING( thingName, SHADOW_OP_UPDATE, SHADOW_SUFFIX_NULL )
+#define SHADOW_TOPIC_STR_UPDATE( thingName, shadowName ) \
+ SHADOW_TOPIC_STR( thingName, shadowName, SHADOW_OP_UPDATE, SHADOW_SUFFIX_NULL )
/**
- * @brief Assemble shadow topic string "$aws/things//shadow/update/accepted".
+ * @ingroup shadow_constants
+ * @brief Assemble shadow topic string "$aws/things//shadow/update/accepted" or
+ * "$aws/things//shadow/name//update/accepted".
+ *
+ * @param[in] thingName Thing Name.
+ * @param[in] shadowName Shadow Name. Empty string for an unnamed ("Classic") shadow.
+ *
+ * @return Topic string.
*/
-#define SHADOW_TOPIC_STRING_UPDATE_ACCEPTED( thingName ) \
- SHADOW_TOPIC_STRING( thingName, SHADOW_OP_UPDATE, SHADOW_SUFFIX_ACCEPTED )
+#define SHADOW_TOPIC_STR_UPDATE_ACC( thingName, shadowName ) \
+ SHADOW_TOPIC_STR( thingName, shadowName, SHADOW_OP_UPDATE, SHADOW_SUFFIX_ACCEPTED )
/**
- * @brief Assemble shadow topic string "$aws/things//shadow/update/rejected".
+ * @ingroup shadow_constants
+ * @brief Assemble shadow topic string "$aws/things//shadow/update/rejected" or
+ * "$aws/things//shadow/name//update/rejected".
+ *
+ * @param[in] thingName Thing Name.
+ * @param[in] shadowName Shadow Name. Empty string for an unnamed ("Classic") shadow.
+ *
+ * @return Topic string.
*/
-#define SHADOW_TOPIC_STRING_UPDATE_REJECTED( thingName ) \
- SHADOW_TOPIC_STRING( thingName, SHADOW_OP_UPDATE, SHADOW_SUFFIX_REJECTED )
+#define SHADOW_TOPIC_STR_UPDATE_REJ( thingName, shadowName ) \
+ SHADOW_TOPIC_STR( thingName, shadowName, SHADOW_OP_UPDATE, SHADOW_SUFFIX_REJECTED )
/**
- * @brief Assemble shadow topic string "$aws/things//shadow/update/documents".
+ * @ingroup shadow_constants
+ * @brief Assemble shadow topic string "$aws/things//shadow/update/documents" or
+ * "$aws/things//shadow/name//update/documents".
+ *
+ * @param[in] thingName Thing Name.
+ * @param[in] shadowName Shadow Name. Empty string for an unnamed ("Classic") shadow.
+ *
+ * @return Topic string.
*/
-#define SHADOW_TOPIC_STRING_UPDATE_DOCUMENTS( thingName ) \
- SHADOW_TOPIC_STRING( thingName, SHADOW_OP_UPDATE, SHADOW_SUFFIX_DOCUMENTS )
+#define SHADOW_TOPIC_STR_UPDATE_DOCS( thingName, shadowName ) \
+ SHADOW_TOPIC_STR( thingName, shadowName, SHADOW_OP_UPDATE, SHADOW_SUFFIX_DOCUMENTS )
/**
- * @brief Assemble shadow topic string "$aws/things//shadow/update/delta".
+ * @ingroup shadow_constants
+ * @brief Assemble shadow topic string "$aws/things//shadow/update/delta" or
+ * "$aws/things//shadow/name//update/delta".
+ *
+ * @param[in] thingName Thing Name.
+ * @param[in] shadowName Shadow Name. Empty string for an unnamed ("Classic") shadow.
+ *
+ * @return Topic string.
*/
-#define SHADOW_TOPIC_STRING_UPDATE_DELTA( thingName ) \
- SHADOW_TOPIC_STRING( thingName, SHADOW_OP_UPDATE, SHADOW_SUFFIX_DELTA )
+#define SHADOW_TOPIC_STR_UPDATE_DELTA( thingName, shadowName ) \
+ SHADOW_TOPIC_STR( thingName, shadowName, SHADOW_OP_UPDATE, SHADOW_SUFFIX_DELTA )
/**
- * @brief Assemble shadow topic string "$aws/things//shadow/get".
+ * @ingroup shadow_constants
+ * @brief Assemble shadow topic string "$aws/things//shadow/get" or
+ * "$aws/things//shadow/name//get".
+ *
+ * @param[in] thingName Thing Name.
+ * @param[in] shadowName Shadow Name. Empty string for an unnamed ("Classic") shadow.
+ *
+ * @return Topic string.
*/
-#define SHADOW_TOPIC_STRING_GET( thingName ) \
- SHADOW_TOPIC_STRING( thingName, SHADOW_OP_GET, SHADOW_SUFFIX_NULL )
+#define SHADOW_TOPIC_STR_GET( thingName, shadowName ) \
+ SHADOW_TOPIC_STR( thingName, shadowName, SHADOW_OP_GET, SHADOW_SUFFIX_NULL )
/**
- * @brief Assemble shadow topic string "$aws/things//shadow/get/accepted".
+ * @ingroup shadow_constants
+ * @brief Assemble shadow topic string "$aws/things//shadow/get/accepted" or
+ * "$aws/things//shadow/name//get/accepted".
+ *
+ * @param[in] thingName Thing Name.
+ * @param[in] shadowName Shadow Name. Empty string for an unnamed ("Classic") shadow.
+ *
+ * @return Topic string.
*/
-#define SHADOW_TOPIC_STRING_GET_ACCEPTED( thingName ) \
- SHADOW_TOPIC_STRING( thingName, SHADOW_OP_GET, SHADOW_SUFFIX_ACCEPTED )
+#define SHADOW_TOPIC_STR_GET_ACC( thingName, shadowName ) \
+ SHADOW_TOPIC_STR( thingName, shadowName, SHADOW_OP_GET, SHADOW_SUFFIX_ACCEPTED )
/**
- * @brief Assemble shadow topic string "$aws/things//shadow/get/rejected".
+ * @ingroup shadow_constants
+ * @brief Assemble shadow topic string "$aws/things//shadow/get/rejected" or
+ * "$aws/things//shadow/name//get/rejected".
+ *
+ * @param[in] thingName Thing Name.
+ * @param[in] shadowName Shadow Name. Empty string for an unnamed ("Classic") shadow.
+ *
+ * @return Topic string.
*/
-#define SHADOW_TOPIC_STRING_GET_REJECTED( thingName ) \
- SHADOW_TOPIC_STRING( thingName, SHADOW_OP_GET, SHADOW_SUFFIX_REJECTED )
+#define SHADOW_TOPIC_STR_GET_REJ( thingName, shadowName ) \
+ SHADOW_TOPIC_STR( thingName, shadowName, SHADOW_OP_GET, SHADOW_SUFFIX_REJECTED )
/**
- * @brief Assemble shadow topic string "$aws/things//shadow/delete".
+ * @ingroup shadow_constants
+ * @brief Assemble shadow topic string "$aws/things//shadow/delete" or
+ * "$aws/things//shadow/name//delete".
+ *
+ * @param[in] thingName Thing Name.
+ * @param[in] shadowName Shadow Name. Empty string for an unnamed ("Classic") shadow.
+ *
+ * @return Topic string.
*/
-#define SHADOW_TOPIC_STRING_DELETE( thingName ) \
- SHADOW_TOPIC_STRING( thingName, SHADOW_OP_DELETE, SHADOW_SUFFIX_NULL )
+#define SHADOW_TOPIC_STR_DELETE( thingName, shadowName ) \
+ SHADOW_TOPIC_STR( thingName, shadowName, SHADOW_OP_DELETE, SHADOW_SUFFIX_NULL )
/**
- * @brief Assemble shadow topic string "$aws/things//shadow/delete/accepted".
+ * @ingroup shadow_constants
+ * @brief Assemble shadow topic string "$aws/things//shadow/delete/accepted" or
+ * "$aws/things//shadow/name//delete/accepted".
+ *
+ * @param[in] thingName Thing Name.
+ * @param[in] shadowName Shadow Name. Empty string for an unnamed ("Classic") shadow.
+ *
+ * @return Topic string.
*/
-#define SHADOW_TOPIC_STRING_DELETE_ACCEPTED( thingName ) \
- SHADOW_TOPIC_STRING( thingName, SHADOW_OP_DELETE, SHADOW_SUFFIX_ACCEPTED )
+#define SHADOW_TOPIC_STR_DELETE_ACC( thingName, shadowName ) \
+ SHADOW_TOPIC_STR( thingName, shadowName, SHADOW_OP_DELETE, SHADOW_SUFFIX_ACCEPTED )
/**
- * @brief Assemble shadow topic string "$aws/things//shadow/delete/rejected".
+ * @ingroup shadow_constants
+ * @brief Assemble shadow topic string "$aws/things//shadow/delete/rejected". or
+ * "$aws/things//shadow/name//delete/rejected".
+ *
+ * @param[in] thingName Thing Name.
+ * @param[in] shadowName Shadow Name. Empty string for an unnamed ("Classic") shadow.
+ *
+ * @return Topic string.
*/
-#define SHADOW_TOPIC_STRING_DELETE_REJECTED( thingName ) \
- SHADOW_TOPIC_STRING( thingName, SHADOW_OP_DELETE, SHADOW_SUFFIX_REJECTED )
+#define SHADOW_TOPIC_STR_DELETE_REJ( thingName, shadowName ) \
+ SHADOW_TOPIC_STR( thingName, shadowName, SHADOW_OP_DELETE, SHADOW_SUFFIX_REJECTED )
+
+/*------------------------ Shadow library functions -------------------------*/
/**
- * @brief Assemble shadow topic string when Thing Name is only known at run time.
- * If the Thing Name is known at compile time, use @link #SHADOW_TOPIC_STRING_UPDATE
- * SHADOW_TOPIC_STRING_* @endlink macros instead.
+ * @brief Assemble shadow topic string when Thing Name or Shadow Name is only known at run time.
+ * If both the Thing Name and Shadow Name are known at compile time, use
+ * @link #SHADOW_TOPIC_STR SHADOW_TOPIC_STR_* @endlink macros instead.
*
* @param[in] topicType Indicates what topic will be written into the buffer pointed to by pTopicBuffer.
* can be one of:
@@ -446,6 +667,8 @@ typedef enum ShadowStatus
* - ShadowTopicStringTypeUpdateDelta
* @param[in] pThingName Thing Name string. No need to be null terminated. Must not be NULL.
* @param[in] thingNameLength Length of Thing Name string pointed to by pThingName. Must not be zero.
+ * @param[in] pShadowName Shadow Name string. No need to be null terminated. Must not be NULL. Empty string for classic shadow.
+ * @param[in] shadowNameLength Length of Shadow Name string pointed to by pShadowName. Zero for classic shadow.
* @param[out] pTopicBuffer Pointer to buffer for returning the topic string.
* Caller is responsible for supplying memory pointed to by pTopicBuffer.
* This function does not fill in the terminating null character. The app
@@ -468,15 +691,19 @@ typedef enum ShadowStatus
* char topicBuffer[ SHADOW_TOPIC_MAX_LENGTH ] = { 0 };
* uint16_t bufferSize = SHADOW_TOPIC_MAX_LENGTH;
* uint16_t outLength = 0;
- * const char * pThingName = "TestThingName";
+ * const char thingName[] = "TestThingName";
* uint16_t thingNameLength = ( sizeof( thingName ) - 1U );
+ * const char shadowName[] = "TestShadowName";
+ * uint16_t shadowNameLength = ( sizeof( shadowName ) - 1U );
*
- * shadowStatus = Shadow_GetTopicString( ShadowTopicStringTypeUpdateDelta,
- * pThingName,
- * thingNameLength,
- * & ( topicBuffer[ 0 ] ),
- * bufferSize,
- * & outLength );
+ * shadowStatus = Shadow_AssembleTopicString( ShadowTopicStringTypeUpdateDelta,
+ * thingName,
+ * thingNameLength,
+ * shadowName,
+ * shadowNameLength,
+ * & ( topicBuffer[ 0 ] ),
+ * bufferSize,
+ * & outLength );
*
* if( shadowStatus == SHADOW_SUCCESS )
* {
@@ -485,26 +712,30 @@ typedef enum ShadowStatus
*
* @endcode
*/
-/* @[declare_shadow_gettopicstring] */
-ShadowStatus_t Shadow_GetTopicString( ShadowTopicStringType_t topicType,
- const char * pThingName,
- uint8_t thingNameLength,
- char * pTopicBuffer,
- uint16_t bufferSize,
- uint16_t * pOutLength );
-/* @[declare_shadow_gettopicstring] */
+/* @[declare_shadow_assembletopicstring] */
+ShadowStatus_t Shadow_AssembleTopicString( ShadowTopicStringType_t topicType,
+ const char * pThingName,
+ uint8_t thingNameLength,
+ const char * pShadowName,
+ uint8_t shadowNameLength,
+ char * pTopicBuffer,
+ uint16_t bufferSize,
+ uint16_t * pOutLength );
+/* @[declare_shadow_assembletopicstring] */
/**
* @brief Given the topic string of an incoming message, determine whether it is
* related to a device shadow; if it is, return information about the type of
- * device shadow message, and a pointer to the Thing Name inside of the topic string.
- * See #ShadowMessageType_t for the list of message types. Those types correspond to
- * Device Shadow Topics.
+ * device shadow message, and pointers to the Thing Name and Shadow Name inside of
+ * the topic string. See #ShadowMessageType_t for the list of message types.
+ * Those types correspond to Device Shadow Topics.
*
* @note When this function returns, the pointer pThingName points at the first character
- * of the \ segment inside of the topic string.
+ * of the \ segment inside of the topic string. Likewise, the pointer pShadowName
+ * points at the first character of the \ segment inside of the topic string
+ * (if the topic is for a named shadow, not the "Classic" shadow.)
* Caller is responsible for keeping the memory holding the topic string around while
- * accessing the Thing Name through pThingName.
+ * accessing the Thing Name through pThingName and the Shadow Name through pShadowName.
*
* @param[in] pTopic Pointer to the MQTT topic string. Does not have to be null-terminated.
* @param[in] topicLength Length of the MQTT topic string.
@@ -513,6 +744,12 @@ ShadowStatus_t Shadow_GetTopicString( ShadowTopicStringType_t topicType,
* null if caller does not need to know the Thing Name contained in the topic string.
* @param[out] pThingNameLength Pointer to caller-supplied memory for returning the length of the Thing Name,
* and can be null if caller does not need to know the Thing Name contained in the topic string.
+ * @param[out] pShadowName Points to the 1st character of Shadow Name inside of the topic string, and can be
+ * null if caller does not need to know the Shadow Name contained in the topic string. Null is
+ * returned if the shadow is Classic.
+ * @param[out] pShadowNameLength Pointer to caller-supplied memory for returning the length of the Shadow Name,
+ * and can be null if caller does not need to know the Shadow Name contained in the topic string.
+ * A value of 0 is returned if the shadow is Classic.
* @return One of the following:
* - #SHADOW_SUCCESS if the message is related to a device shadow;
* - An error code defined in #ShadowStatus_t if the message is not related to a device shadow,
@@ -531,11 +768,13 @@ ShadowStatus_t Shadow_GetTopicString( ShadowTopicStringType_t topicType,
* uint16_t topicNameLength; //usually supplied by MQTT stack
* ShadowMessageType_t messageType;
*
- * shadowStatus = Shadow_MatchTopic( pTopicName,
- * topicNameLength,
- * & messageType,
- * NULL,
- * NULL );
+ * shadowStatus = Shadow_MatchTopicString( pTopicName,
+ * topicNameLength,
+ * &messageType,
+ * NULL,
+ * NULL,
+ * NULL,
+ * NULL );
*
* if( shadowStatus == SHADOW_SUCCESS )
* {
@@ -545,12 +784,272 @@ ShadowStatus_t Shadow_GetTopicString( ShadowTopicStringType_t topicType,
*
* @endcode
*/
+/* @[declare_shadow_matchtopicstring] */
+ShadowStatus_t Shadow_MatchTopicString( const char * pTopic,
+ uint16_t topicLength,
+ ShadowMessageType_t * pMessageType,
+ const char ** pThingName,
+ uint16_t * pThingNameLength,
+ const char ** pShadowName,
+ uint16_t * pShadowNameLength );
+/* @[declare_shadow_matchtopicstring] */
+
+/*------------- Shadow library backwardly-compatible constants -------------*/
+
+/**
+ * @brief Compute unnamed "Classic" shadow topic length.
+ * @deprecated Please use @ref #SHADOW_TOPIC_LEN in new designs.
+ *
+ * See @ref #SHADOW_TOPIC_LEN for documentation of common behavior.
+ */
+#define SHADOW_TOPIC_LENGTH( operationLength, suffixLength, thingNameLength ) \
+ SHADOW_TOPIC_LEN( operationLength, suffixLength, thingNameLength, SHADOW_NAME_CLASSIC_LENGTH )
+
+/**
+ * @brief Compute the length of unnamed "Classic" shadow topic "$aws/things//shadow/update".
+ * @deprecated Please use @ref #SHADOW_TOPIC_LEN_UPDATE in new designs.
+ *
+ * See @ref #SHADOW_TOPIC_LEN_UPDATE for documentation of common behavior.
+ */
+#define SHADOW_TOPIC_LENGTH_UPDATE( thingNameLength ) \
+ SHADOW_TOPIC_LEN_UPDATE( thingNameLength, SHADOW_NAME_CLASSIC_LENGTH )
+
+/**
+ * @brief Compute the length of unnamed "Classic" shadow topic "$aws/things//shadow/update/accepted".
+ * @deprecated Please use @ref #SHADOW_TOPIC_LEN_UPDATE_ACC in new designs.
+ *
+ * See @ref #SHADOW_TOPIC_LEN_UPDATE_ACC for documentation of common behavior.
+ */
+#define SHADOW_TOPIC_LENGTH_UPDATE_ACCEPTED( thingNameLength ) \
+ SHADOW_TOPIC_LEN_UPDATE_ACC( thingNameLength, SHADOW_NAME_CLASSIC_LENGTH )
+
+/**
+ * @brief Compute the length of unnamed "Classic" shadow topic "$aws/things//shadow/update/rejected".
+ * @deprecated Please use @ref #SHADOW_TOPIC_LEN_UPDATE_REJ in new designs.
+ *
+ * See @ref #SHADOW_TOPIC_LEN_UPDATE_REJ for documentation of common behavior.
+ */
+#define SHADOW_TOPIC_LENGTH_UPDATE_REJECTED( thingNameLength ) \
+ SHADOW_TOPIC_LEN_UPDATE_REJ( thingNameLength, SHADOW_NAME_CLASSIC_LENGTH )
+
+/**
+ * @brief Compute the length of unnamed "Classic" shadow topic "$aws/things//shadow/update/documents".
+ * @deprecated Please use @ref #SHADOW_TOPIC_LEN_UPDATE_DOCS in new designs.
+ *
+ * See @ref #SHADOW_TOPIC_LEN_UPDATE_DOCS for documentation of common behavior.
+ */
+#define SHADOW_TOPIC_LENGTH_UPDATE_DOCUMENTS( thingNameLength ) \
+ SHADOW_TOPIC_LEN_UPDATE_DOCS( thingNameLength, SHADOW_NAME_CLASSIC_LENGTH )
+
+/**
+ * @brief Compute the length of unnamed "Classic" shadow topic "$aws/things//shadow/update/delta".
+ * @deprecated Please use @ref #SHADOW_TOPIC_LEN_UPDATE_DELTA in new designs.
+ *
+ * See @ref #SHADOW_TOPIC_LEN_UPDATE_DELTA for documentation of common behavior.
+ */
+#define SHADOW_TOPIC_LENGTH_UPDATE_DELTA( thingNameLength ) \
+ SHADOW_TOPIC_LEN_UPDATE_DELTA( thingNameLength, SHADOW_NAME_CLASSIC_LENGTH )
+
+/**
+ * @brief Compute the length of unnamed "Classic" shadow topic "$aws/things//shadow/get".
+ * @deprecated Please use @ref #SHADOW_TOPIC_LEN_GET in new designs.
+ *
+ * See @ref #SHADOW_TOPIC_LEN_GET for documentation of common behavior.
+ */
+#define SHADOW_TOPIC_LENGTH_GET( thingNameLength ) \
+ SHADOW_TOPIC_LEN_GET( thingNameLength, SHADOW_NAME_CLASSIC_LENGTH )
+
+/**
+ * @brief Compute the length of unnamed "Classic" shadow topic "$aws/things//shadow/get/accepted".
+ * @deprecated Please use @ref #SHADOW_TOPIC_LEN_GET_ACC in new designs.
+ *
+ * See @ref #SHADOW_TOPIC_LEN_GET_ACC for documentation of common behavior.
+ */
+#define SHADOW_TOPIC_LENGTH_GET_ACCEPTED( thingNameLength ) \
+ SHADOW_TOPIC_LEN_GET_ACC( thingNameLength, SHADOW_NAME_CLASSIC_LENGTH )
+
+/**
+ * @brief Compute the length of unnamed "Classic" shadow topic "$aws/things//shadow/get/rejected".
+ * @deprecated Please use @ref #SHADOW_TOPIC_LEN_GET_REJ in new designs.
+ *
+ * See @ref #SHADOW_TOPIC_LEN_GET_REJ for documentation of common behavior.
+ */
+#define SHADOW_TOPIC_LENGTH_GET_REJECTED( thingNameLength ) \
+ SHADOW_TOPIC_LEN_GET_REJ( thingNameLength, SHADOW_NAME_CLASSIC_LENGTH )
+
+/**
+ * @brief Compute the length of unnamed "Classic" shadow topic "$aws/things//shadow/delete".
+ * @deprecated Please use @ref #SHADOW_TOPIC_LEN_DELETE in new designs.
+ *
+ * See @ref #SHADOW_TOPIC_LEN_DELETE for documentation of common behavior.
+ */
+#define SHADOW_TOPIC_LENGTH_DELETE( thingNameLength ) \
+ SHADOW_TOPIC_LEN_DELETE( thingNameLength, SHADOW_NAME_CLASSIC_LENGTH )
+
+/**
+ * @brief Compute the length of unnamed "Classic" shadow topic "$aws/things//shadow/delete/accepted".
+ * @deprecated Please use @ref #SHADOW_TOPIC_LEN_DELETE_ACC in new designs.
+ *
+ * See @ref #SHADOW_TOPIC_LEN_DELETE_ACC for documentation of common behavior.
+ */
+#define SHADOW_TOPIC_LENGTH_DELETE_ACCEPTED( thingNameLength ) \
+ SHADOW_TOPIC_LEN_DELETE_ACC( thingNameLength, SHADOW_NAME_CLASSIC_LENGTH )
+
+/**
+ * @brief Compute the length of unnamed "Classic" shadow topic "$aws/things//shadow/delete/rejected".
+ * @deprecated Please use @ref #SHADOW_TOPIC_LEN_DELETE_REJ in new designs.
+ *
+ * See @ref #SHADOW_TOPIC_LEN_DELETE_REJ for documentation of common behavior.
+ */
+#define SHADOW_TOPIC_LENGTH_DELETE_REJECTED( thingNameLength ) \
+ SHADOW_TOPIC_LEN_DELETE_REJ( thingNameLength, SHADOW_NAME_CLASSIC_LENGTH )
+
+/**
+ * @brief Compute the length of the longest unnamed "Classic" shadow topic.
+ * @deprecated Please use @ref #SHADOW_TOPIC_LEN_MAX in new designs.
+ *
+ * See @ref #SHADOW_TOPIC_LEN for documentation of common behavior.
+ */
+#define SHADOW_TOPIC_LENGTH_MAX( thingNameLength ) \
+ SHADOW_TOPIC_LEN_MAX( thingNameLength, SHADOW_NAME_CLASSIC_LENGTH )
+
+/**
+ * @brief Assemble constant unnamed "Classic" shadow topic strings when Thing Name is known at compile time.
+ * @deprecated Please use @ref #SHADOW_TOPIC_STR in new designs.
+ *
+ * See @ref #SHADOW_TOPIC_STR for documentation of common behavior.
+ */
+#define SHADOW_TOPIC_STRING( thingName, operation, suffix ) \
+ SHADOW_TOPIC_STR( thingName, SHADOW_NAME_CLASSIC, operation, suffix )
+
+/**
+ * @brief Assemble unnamed "Classic" shadow topic string "$aws/things//shadow/update".
+ * @deprecated Please use @ref #SHADOW_TOPIC_STR_UPDATE in new designs.
+ *
+ * See @ref #SHADOW_TOPIC_STR_UPDATE for documentation of common behavior.
+ */
+#define SHADOW_TOPIC_STRING_UPDATE( thingName ) \
+ SHADOW_TOPIC_STR_UPDATE( thingName, SHADOW_NAME_CLASSIC )
+
+/**
+ * @brief Assemble unnamed "Classic" shadow topic string "$aws/things//shadow/update/accepted".
+ * @deprecated Please use @ref #SHADOW_TOPIC_STR_UPDATE_ACC in new designs.
+ *
+ * See @ref #SHADOW_TOPIC_STR_UPDATE_ACC for documentation of common behavior.
+ */
+#define SHADOW_TOPIC_STRING_UPDATE_ACCEPTED( thingName ) \
+ SHADOW_TOPIC_STR_UPDATE_ACC( thingName, SHADOW_NAME_CLASSIC )
+
+/**
+ * @brief Assemble unnamed "Classic" shadow topic string "$aws/things//shadow/update/rejected".
+ * @deprecated Please use @ref #SHADOW_TOPIC_STR_UPDATE_REJ in new designs.
+ *
+ * See @ref #SHADOW_TOPIC_STR_UPDATE_REJ for documentation of common behavior.
+ */
+#define SHADOW_TOPIC_STRING_UPDATE_REJECTED( thingName ) \
+ SHADOW_TOPIC_STR_UPDATE_REJ( thingName, SHADOW_NAME_CLASSIC )
+
+/**
+ * @brief Assemble unnamed "Classic" shadow topic string "$aws/things//shadow/update/documents".
+ * @deprecated Please use @ref #SHADOW_TOPIC_STR_UPDATE_DOCS in new designs.
+ *
+ * See @ref #SHADOW_TOPIC_STR_UPDATE_DOCS for documentation of common behavior.
+ */
+#define SHADOW_TOPIC_STRING_UPDATE_DOCUMENTS( thingName ) \
+ SHADOW_TOPIC_STR_UPDATE_DOCS( thingName, SHADOW_NAME_CLASSIC )
+
+/**
+ * @brief Assemble unnamed "Classic" shadow topic string "$aws/things//shadow/update/delta".
+ * @deprecated Please use @ref #SHADOW_TOPIC_STR_UPDATE_DELTA in new designs.
+ *
+ * See @ref #SHADOW_TOPIC_STR_UPDATE_DELTA for documentation of common behavior.
+ */
+#define SHADOW_TOPIC_STRING_UPDATE_DELTA( thingName ) \
+ SHADOW_TOPIC_STR_UPDATE_DELTA( thingName, SHADOW_NAME_CLASSIC )
+
+/**
+ * @brief Assemble unnamed "Classic" shadow topic string "$aws/things//shadow/get".
+ * @deprecated Please use @ref #SHADOW_TOPIC_STR_GET in new designs.
+ *
+ * See @ref #SHADOW_TOPIC_STR_GET for documentation of common behavior.
+ */
+#define SHADOW_TOPIC_STRING_GET( thingName ) \
+ SHADOW_TOPIC_STR_GET( thingName, SHADOW_NAME_CLASSIC )
+
+/**
+ * @brief Assemble shadow topic string "$aws/things//shadow/get/accepted".
+ * @deprecated Please use @ref #SHADOW_TOPIC_STR_GET_ACC in new designs.
+ *
+ * See @ref #SHADOW_TOPIC_STR_GET_ACC for documentation of common behavior.
+ */
+#define SHADOW_TOPIC_STRING_GET_ACCEPTED( thingName ) \
+ SHADOW_TOPIC_STR_GET_ACC( thingName, SHADOW_NAME_CLASSIC )
+
+/**
+ * @brief Assemble unnamed "Classic" shadow topic string "$aws/things//shadow/get/rejected".
+ * @deprecated Please use @ref #SHADOW_TOPIC_STR_GET_REJ in new designs.
+ *
+ * See @ref #SHADOW_TOPIC_STR_GET_REJ for documentation of common behavior.
+ */
+#define SHADOW_TOPIC_STRING_GET_REJECTED( thingName ) \
+ SHADOW_TOPIC_STR_GET_REJ( thingName, SHADOW_NAME_CLASSIC )
+
+/**
+ * @brief Assemble unnamed "Classic" shadow topic string "$aws/things//shadow/delete".
+ * @deprecated Please use @ref #SHADOW_TOPIC_STR_DELETE in new designs.
+ *
+ * See @ref #SHADOW_TOPIC_STR_DELETE for documentation of common behavior.
+ */
+#define SHADOW_TOPIC_STRING_DELETE( thingName ) \
+ SHADOW_TOPIC_STR_DELETE( thingName, SHADOW_NAME_CLASSIC )
+
+/**
+ * @brief Assemble unnamed "Classic" shadow topic string "$aws/things//shadow/delete/accepted".
+ * @deprecated Please use @ref #SHADOW_TOPIC_STR_DELETE_ACC in new designs.
+ *
+ * See @ref #SHADOW_TOPIC_STR_DELETE_ACC for documentation of common behavior.
+ */
+#define SHADOW_TOPIC_STRING_DELETE_ACCEPTED( thingName ) \
+ SHADOW_TOPIC_STR_DELETE_ACC( thingName, SHADOW_NAME_CLASSIC )
+
+/**
+ * @brief Assemble unnamed "Classic" shadow topic string "$aws/things//shadow/delete/rejected".
+ * @deprecated Please use @ref #SHADOW_TOPIC_STR_DELETE_REJ in new designs.
+ *
+ * See @ref #SHADOW_TOPIC_STR_DELETE_REJ for documentation of common behavior.
+ */
+#define SHADOW_TOPIC_STRING_DELETE_REJECTED( thingName ) \
+ SHADOW_TOPIC_STR_DELETE_REJ( thingName, SHADOW_NAME_CLASSIC )
+
+/**
+ * @brief Assemble unnamed ("Classic") shadow topic string when Thing Name is only known at run time.
+ * If the Thing Name is known at compile time, use
+ * @link #SHADOW_TOPIC_STRING SHADOW_TOPIC_STRING @endlink macro instead.
+ *
+ * @deprecated Please use @ref Shadow_AssembleTopicString in new designs.
+ *
+ * See @ref Shadow_AssembleTopicString for documentation of common behavior.
+ */
+/* @[declare_shadow_gettopicstring] */
+#define Shadow_GetTopicString( topicType, pThingName, thingNameLength, pTopicBuffer, bufferSize, pOutLength ) \
+ Shadow_AssembleTopicString( topicType, pThingName, thingNameLength, SHADOW_NAME_CLASSIC, 0, \
+ pTopicBuffer, bufferSize, pOutLength )
+/* @[declare_shadow_gettopicstring] */
+
+/**
+ * @brief Given the topic string of an incoming message, determine whether it is related to
+ * an unnamed ("Classic") device shadow; if it is, return information about the type
+ * of device shadow message, and a pointers to the Thing Name inside of
+ * the topic string. See #ShadowMessageType_t for the list of message types.
+ * Those types correspond to Device Shadow Topics.
+ *
+ * @deprecated Please use @ref Shadow_MatchTopicString in new designs.
+ *
+ * See @ref Shadow_MatchTopicString for documentation of common behavior.
+ */
/* @[declare_shadow_matchtopic] */
-ShadowStatus_t Shadow_MatchTopic( const char * pTopic,
- uint16_t topicLength,
- ShadowMessageType_t * pMessageType,
- const char ** pThingName,
- uint16_t * pThingNameLength );
+#define Shadow_MatchTopic( pTopic, topicLength, pMessageType, pThingName, pThingNameLength ) \
+ Shadow_MatchTopicString( pTopic, topicLength, pMessageType, pThingName, pThingNameLength, NULL, 0 )
/* @[declare_shadow_matchtopic] */
#endif /* ifndef SHADOW_H_ */
diff --git a/source/shadow.c b/source/shadow.c
index 427d3312..214dbf0a 100644
--- a/source/shadow.c
+++ b/source/shadow.c
@@ -111,6 +111,20 @@
*/
#define SHADOW_OP_DELETE_REJECTED_LENGTH ( SHADOW_OP_DELETE_LENGTH + SHADOW_SUFFIX_REJECTED_LENGTH )
+/**
+ * @brief Check if Shadow_MatchTopicString has valid parameters.
+ *
+ * @param[in] pTopic Pointer to the topic string.
+ * @param[in] topicLength Length of pTopic.
+ * @param[in] pMessageType Pointer to caller-supplied memory for returning the type of the shadow message.
+ *
+ * @return Return SHADOW_SUCCESS if the parameters are valid;
+ * return SHADOW_BAD_PARAMETER if not.
+ */
+static ShadowStatus_t validateMatchTopicParameters( const char * pTopic,
+ uint16_t topicLength,
+ const ShadowMessageType_t * pMessageType );
+
/**
* @brief Determine if the string contains the substring.
*
@@ -128,33 +142,50 @@ static ShadowStatus_t containsSubString( const char * pString,
uint16_t subStringLength );
/**
- * @brief Check if the Thing Name is valid.
+ * @brief Check if the Thing or Shadow Name is valid.
*
- * @param[in] pString Pointer to the starting of thing name.
+ * @param[in] pString Pointer to the starting of a name.
* @param[in] stringLength Length of pString.
- * @param[out] pThingNameLength Pointer to caller-supplied memory for returning the length of the Thing Name.
+ * @param[out] pNameLength Pointer to caller-supplied memory for returning the length of the Thing or Shadow Name.
*
* @return Return SHADOW_SUCCESS if it is valid;
- * return SHADOW_THINGNAME_PARSE_FAILED if it is not.
+ * return SHADOW_FAIL if it is not.
*/
-static ShadowStatus_t validateThingName( const char * pString,
- uint16_t stringLength,
- uint16_t * pThingNameLength );
+static ShadowStatus_t validateName( const char * pString,
+ uint16_t stringLength,
+ uint16_t * pNameLength );
/**
* @brief Extract the Shadow message type from a string.
*
* @param[in] pString Pointer to the string.
* @param[in] stringLength Length of pString.
- * @param[out] pMessageType Pointer to call-supplied memory for returning the type of the shadow message.
+ * @param[out] pMessageType Pointer to caller-supplied memory for returning the type of the shadow message.
*
* @return Return SHADOW_SUCCESS if successfully extracted;
- * return SHADOW_SHADOW_MESSAGE_TYPE_PARSE_FAILED if failed.
+ * return SHADOW_MESSAGE_TYPE_PARSE_FAILED if failed.
*/
static ShadowStatus_t extractShadowMessageType( const char * pString,
uint16_t stringLength,
ShadowMessageType_t * pMessageType );
+/**
+ * @brief Extract the classic shadow root OR the named shadow root and shadow name from a topic string.
+ *
+ * @param[in] pTopic Pointer to the topic string.
+ * @param[in] topicLength Length of pTopic.
+ * @param[out] pConsumedTopicLength Pointer to caller-supplied memory for returning the consumed topic length.
+ * @param[out] pShadowNameLength Pointer to caller-supplied memory for returning the shadow name length.
+ *
+ * @return Return SHADOW_SUCCESS if successfully extracted;
+ * return SHADOW_ROOT_PARSE_FAILED shadow root parsing fails.
+ * return SHADOW_SHADOWNAME_PARSE_FAILED shadow name parsing fails.
+ */
+static ShadowStatus_t extractShadowRootAndName( const char * pTopic,
+ uint16_t topicLength,
+ uint16_t * pConsumedTopicLength,
+ uint16_t * pShadowNameLength );
+
/**
* @brief Get the shadow operation string for a given shadow topic type.
*
@@ -173,6 +204,45 @@ static const char * getShadowOperationString( ShadowTopicStringType_t topicType
*/
static uint16_t getShadowOperationLength( ShadowTopicStringType_t topicType );
+/**
+ * @brief Creates a shadow topic string
+ *
+ * @param[in] topicType The type of shadow topic to be constructed.
+ * @param[in] pThingName Pointer to the Thing name.
+ * @param[in] thingNameLength The length of the Thing name.
+ * @param[in] pShadowName Pointer to the Shadow name.
+ * @param[in] shadowNameLength The length of the Shadow name.
+ * @param[out] pTopicBuffer Pointer to caller-supplied memory for returning the constructed shadow topic string.
+ */
+static void createShadowTopicString( ShadowTopicStringType_t topicType,
+ const char * pThingName,
+ uint8_t thingNameLength,
+ const char * pShadowName,
+ uint8_t shadowNameLength,
+ char * pTopicBuffer );
+
+/*-----------------------------------------------------------*/
+
+static ShadowStatus_t validateMatchTopicParameters( const char * pTopic,
+ uint16_t topicLength,
+ const ShadowMessageType_t * pMessageType )
+{
+ ShadowStatus_t shadowStatus = SHADOW_SUCCESS;
+
+ if( ( pTopic == NULL ) ||
+ ( topicLength == 0U ) ||
+ ( pMessageType == NULL ) )
+ {
+ shadowStatus = SHADOW_BAD_PARAMETER;
+ LogError( ( "Invalid input parameters pTopic: %p, topicLength: %u, pMessageType: %p.",
+ ( void * ) pTopic,
+ ( unsigned int ) topicLength,
+ ( void * ) pMessageType ) );
+ }
+
+ return shadowStatus;
+}
+
/*-----------------------------------------------------------*/
static ShadowStatus_t containsSubString( const char * pString,
@@ -196,38 +266,92 @@ static ShadowStatus_t containsSubString( const char * pString,
return returnStatus;
}
+
/*-----------------------------------------------------------*/
-static ShadowStatus_t validateThingName( const char * pString,
- uint16_t stringLength,
- uint16_t * pThingNameLength )
+static ShadowStatus_t validateName( const char * pString,
+ uint16_t stringLength,
+ uint16_t * pNameLength )
{
uint16_t index = 0U;
- ShadowStatus_t returnStatus = SHADOW_THINGNAME_PARSE_FAILED;
+ ShadowStatus_t returnStatus = SHADOW_FAIL;
for( ; index < stringLength; index++ )
{
+ /* The name should always be terminated by a forward slash */
if( pString[ index ] == ( char ) '/' )
{
+ if( index > 0U )
+ {
+ /* Only accept names of greater than zero length */
+ *pNameLength = index;
+ returnStatus = SHADOW_SUCCESS;
+ }
+
break;
}
}
- /* Zero length thing name is not valid,
- * $"$aws/things//
- * $"$aws/things/"
- * will extract the same thing name result.
- * Only empty thing name string like:
- * "$aws/things/" or "$aws/things" will fail.
- */
- if( index > 0U )
+ return returnStatus;
+}
+
+/*-----------------------------------------------------------*/
+
+static ShadowStatus_t extractShadowRootAndName( const char * pTopic,
+ uint16_t topicLength,
+ uint16_t * pConsumedTopicLength,
+ uint16_t * pShadowNameLength )
+{
+ ShadowStatus_t shadowStatus;
+
+ /* Look for the named shadow root */
+ shadowStatus = containsSubString( &( pTopic[ *pConsumedTopicLength ] ),
+ topicLength - *pConsumedTopicLength,
+ SHADOW_NAMED_ROOT,
+ SHADOW_NAMED_ROOT_LENGTH );
+
+ if( shadowStatus == SHADOW_SUCCESS )
{
- *pThingNameLength = index;
- returnStatus = SHADOW_SUCCESS;
+ /* Topic is a named shadow */
+ *pConsumedTopicLength += SHADOW_NAMED_ROOT_LENGTH;
+
+ /* Extract shadow name. */
+ shadowStatus = validateName( &( pTopic[ *pConsumedTopicLength ] ),
+ topicLength - *pConsumedTopicLength,
+ pShadowNameLength );
+
+ if( shadowStatus == SHADOW_SUCCESS )
+ {
+ *pConsumedTopicLength += *pShadowNameLength;
+ }
+ else
+ {
+ shadowStatus = SHADOW_SHADOWNAME_PARSE_FAILED;
+ LogDebug( ( "Not related to Shadow, failed to parse shadow name in pTopic %s", pTopic ) );
+ }
}
+ else
+ {
+ /* Not a named shadow. Try to match the classic shadow root. */
+ shadowStatus = containsSubString( &( pTopic[ *pConsumedTopicLength ] ),
+ topicLength - *pConsumedTopicLength,
+ SHADOW_CLASSIC_ROOT,
+ SHADOW_CLASSIC_ROOT_LENGTH );
- return returnStatus;
+ if( shadowStatus == SHADOW_SUCCESS )
+ {
+ *pConsumedTopicLength += SHADOW_CLASSIC_ROOT_LENGTH;
+ }
+ else
+ {
+ shadowStatus = SHADOW_ROOT_PARSE_FAILED;
+ LogDebug( ( "Not related to Shadow, failed to parse shadow root in pTopic %s", pTopic ) );
+ }
+ }
+
+ return shadowStatus;
}
+
/*-----------------------------------------------------------*/
static ShadowStatus_t extractShadowMessageType( const char * pString,
@@ -356,7 +480,7 @@ static const char * getShadowOperationString( ShadowTopicStringType_t topicType
break;
case ShadowTopicStringTypeUpdateDelta:
- /* topicType >= ShadowTopicStringTypeMaxNum check is covered at entry of Shadow_GetTopicString. */
+ /* topicType >= ShadowTopicStringTypeMaxNum check is covered at entry of Shadow_AssembleTopicString. */
default:
shadowOperationString = SHADOW_OP_UPDATE_DELTA;
break;
@@ -414,7 +538,7 @@ static uint16_t getShadowOperationLength( ShadowTopicStringType_t topicType )
break;
case ShadowTopicStringTypeUpdateDelta:
- /* topicType >= ShadowTopicStringTypeMaxNum check is covered at entry of Shadow_GetTopicString. */
+ /* topicType >= ShadowTopicStringTypeMaxNum check is covered at entry of Shadow_AssembleTopicString. */
default:
shadowOperationLength = SHADOW_OP_UPDATE_DELTA_LENGTH;
break;
@@ -425,37 +549,93 @@ static uint16_t getShadowOperationLength( ShadowTopicStringType_t topicType )
/*-----------------------------------------------------------*/
+static void createShadowTopicString( ShadowTopicStringType_t topicType,
+ const char * pThingName,
+ uint8_t thingNameLength,
+ const char * pShadowName,
+ uint8_t shadowNameLength,
+ char * pTopicBuffer )
+{
+ uint16_t offset = 0U, operationStringLength = 0U;
+ const char * pShadowPrefix = SHADOW_PREFIX;
+ const char * pOperationString = NULL;
+ const char * pClassicShadowRoot = SHADOW_CLASSIC_ROOT;
+ const char * pNamedShadowRoot = SHADOW_NAMED_ROOT;
+
+ /* Copy the Shadow topic prefix into the topic buffer. */
+ ( void ) memcpy( ( void * ) pTopicBuffer,
+ ( const void * ) pShadowPrefix,
+ ( size_t ) SHADOW_PREFIX_LENGTH );
+ offset = ( uint16_t ) ( offset + SHADOW_PREFIX_LENGTH );
+
+ /* Copy the Thing Name into the topic buffer. */
+ ( void ) memcpy( ( void * ) &( pTopicBuffer[ offset ] ),
+ ( const void * ) pThingName,
+ ( size_t ) thingNameLength );
+ offset = ( uint16_t ) ( offset + thingNameLength );
+
+ /* Are we assembling a named shadow? */
+ if( shadowNameLength > 0U )
+ {
+ /* Copy the named Shadow topic root into the topic buffer. */
+ ( void ) memcpy( ( void * ) &( pTopicBuffer[ offset ] ),
+ ( const void * ) pNamedShadowRoot,
+ ( size_t ) SHADOW_NAMED_ROOT_LENGTH );
+ offset = ( uint16_t ) ( offset + SHADOW_NAMED_ROOT_LENGTH );
+
+ /* Copy the Shadow Name into the topic buffer. */
+ ( void ) memcpy( ( void * ) &( pTopicBuffer[ offset ] ),
+ ( const void * ) pShadowName,
+ ( size_t ) shadowNameLength );
+ offset = ( uint16_t ) ( offset + shadowNameLength );
+ }
+ else
+ {
+ /* Copy the Classic Shadow topic root into the topic buffer. */
+ ( void ) memcpy( ( void * ) &( pTopicBuffer[ offset ] ),
+ ( const void * ) pClassicShadowRoot,
+ ( size_t ) SHADOW_CLASSIC_ROOT_LENGTH );
+ offset = ( uint16_t ) ( offset + SHADOW_CLASSIC_ROOT_LENGTH );
+ }
+
+ pOperationString = getShadowOperationString( topicType );
+ operationStringLength = getShadowOperationLength( topicType );
+ /* Copy the Shadow operation string into the topic buffer. */
+ ( void ) memcpy( ( void * ) &( pTopicBuffer[ offset ] ),
+ ( const void * ) pOperationString,
+ ( size_t ) operationStringLength );
+}
+
/*-----------------------------------------------------------*/
-ShadowStatus_t Shadow_MatchTopic( const char * pTopic,
- uint16_t topicLength,
- ShadowMessageType_t * pMessageType,
- const char ** pThingName,
- uint16_t * pThingNameLength )
+ShadowStatus_t Shadow_MatchTopicString( const char * pTopic,
+ uint16_t topicLength,
+ ShadowMessageType_t * pMessageType,
+ const char ** pThingName,
+ uint16_t * pThingNameLength,
+ const char ** pShadowName,
+ uint16_t * pShadowNameLength )
{
uint16_t consumedTopicLength = 0U;
ShadowStatus_t shadowStatus = SHADOW_SUCCESS;
uint16_t thingNameLength = 0;
+ uint16_t shadowNameLength = 0;
- if( ( pTopic == NULL ) ||
- ( topicLength == 0U ) ||
- ( pMessageType == NULL ) )
- {
- shadowStatus = SHADOW_BAD_PARAMETER;
- LogError( ( "Invalid input parameters pTopic: %p, topicLength: %u, pMessageType: %p.",
- ( void * ) pTopic,
- ( unsigned int ) topicLength,
- ( void * ) pMessageType ) );
- }
+ shadowStatus = validateMatchTopicParameters( pTopic, topicLength, pMessageType );
- /* A shadow topic string takes one of the two forms:
+ /* A shadow topic string takes one of the two forms.
+ * Classic shadow:
* $aws/things//shadow/
* $aws/things//shadow//
+ * Named shadow:
+ * $aws/things//shadow/name//
+ * $aws/things//shadow/name///
*
* We need to match the following things:
* 1. Prefix ($aws/things).
* 2. Thing Name.
- * 3. Shadow operation and suffix.
+ * 3. Classic shadow root (/shadow) OR Named shadow root (/shadow/name) and shadow name
+ * 4. Shadow operation and suffix.
*/
if( shadowStatus == SHADOW_SUCCESS )
{
@@ -464,54 +644,55 @@ ShadowStatus_t Shadow_MatchTopic( const char * pTopic,
topicLength - consumedTopicLength,
SHADOW_PREFIX,
SHADOW_PREFIX_LENGTH );
- }
- if( shadowStatus == SHADOW_SUCCESS )
- {
- consumedTopicLength += SHADOW_PREFIX_LENGTH;
-
- /* If no more topic string is left to parse, fail. */
- if( consumedTopicLength >= topicLength )
+ if( shadowStatus == SHADOW_SUCCESS )
{
- shadowStatus = SHADOW_THINGNAME_PARSE_FAILED;
- LogDebug( ( "Not related to Shadow, thing name is not in pTopic %s, failed to parse thing name.", pTopic ) );
+ consumedTopicLength += SHADOW_PREFIX_LENGTH;
+ }
+ else
+ {
+ LogDebug( ( "Not related to Shadow, failed to parse shadow topic prefix in pTopic %s.", pTopic ) );
}
- }
- else
- {
- LogDebug( ( "Not related to Shadow, failed to parse shadow topic prefix in pTopic %s.", pTopic ) );
}
if( shadowStatus == SHADOW_SUCCESS )
{
/* Extract thing name. */
- shadowStatus = validateThingName( &( pTopic[ consumedTopicLength ] ),
- topicLength - consumedTopicLength,
- &thingNameLength );
+ shadowStatus = validateName( &( pTopic[ consumedTopicLength ] ),
+ topicLength - consumedTopicLength,
+ &thingNameLength );
if( shadowStatus == SHADOW_SUCCESS )
{
consumedTopicLength += thingNameLength;
-
- /* If no more topic string is left to parse, fail. */
- if( consumedTopicLength >= topicLength )
- {
- shadowStatus = SHADOW_SHADOW_MESSAGE_TYPE_PARSE_FAILED;
- LogDebug( ( "Not related to Shadow, shadow message type is not in pTopic %s, failed to parse shadow message type.", pTopic ) );
- }
}
else
{
+ shadowStatus = SHADOW_THINGNAME_PARSE_FAILED;
LogDebug( ( "Not related to Shadow, failed to parse thing name in pTopic %s.", pTopic ) );
}
}
+ if( shadowStatus == SHADOW_SUCCESS )
+ {
+ shadowStatus = extractShadowRootAndName( pTopic,
+ topicLength,
+ &consumedTopicLength,
+ &shadowNameLength );
+ }
+
if( shadowStatus == SHADOW_SUCCESS )
{
/* Extract shadow message type. */
shadowStatus = extractShadowMessageType( &( pTopic[ consumedTopicLength ] ),
topicLength - consumedTopicLength,
pMessageType );
+
+ if( shadowStatus != SHADOW_SUCCESS )
+ {
+ shadowStatus = SHADOW_MESSAGE_TYPE_PARSE_FAILED;
+ LogDebug( ( "Not related to Shadow, shadow message type is not in pTopic %s, failed to parse shadow message type.", pTopic ) );
+ }
}
if( shadowStatus == SHADOW_SUCCESS )
@@ -527,41 +708,59 @@ ShadowStatus_t Shadow_MatchTopic( const char * pTopic,
{
*pThingNameLength = thingNameLength;
}
+
+ if( pShadowName != NULL )
+ {
+ *pShadowName = &( pTopic[ SHADOW_PREFIX_LENGTH + thingNameLength +
+ SHADOW_NAMED_ROOT_LENGTH ] );
+ }
+
+ if( pShadowNameLength != NULL )
+ {
+ *pShadowNameLength = shadowNameLength;
+ }
}
return shadowStatus;
}
/*-----------------------------------------------------------*/
-
-ShadowStatus_t Shadow_GetTopicString( ShadowTopicStringType_t topicType,
- const char * pThingName,
- uint8_t thingNameLength,
- char * pTopicBuffer,
- uint16_t bufferSize,
- uint16_t * pOutLength )
+ShadowStatus_t Shadow_AssembleTopicString( ShadowTopicStringType_t topicType,
+ const char * pThingName,
+ uint8_t thingNameLength,
+ const char * pShadowName,
+ uint8_t shadowNameLength,
+ char * pTopicBuffer,
+ uint16_t bufferSize,
+ uint16_t * pOutLength )
{
- uint16_t offset = 0U, generatedTopicStringLength = 0U, operationStringLength = 0U;
+ uint16_t generatedTopicStringLength = 0U;
ShadowStatus_t shadowStatus = SHADOW_SUCCESS;
- const char * pOperationString = NULL;
- const char * pShadowPrefix = SHADOW_PREFIX;
if( ( pTopicBuffer == NULL ) ||
( pThingName == NULL ) ||
( thingNameLength == 0U ) ||
+ ( ( pShadowName == NULL ) && ( shadowNameLength > 0U ) ) ||
( topicType >= ShadowTopicStringTypeMaxNum ) ||
( pOutLength == NULL ) )
{
shadowStatus = SHADOW_BAD_PARAMETER;
- LogError( ( "Invalid input parameters pTopicBuffer: %p, pThingName: %p, "
- "thingNameLength: %u, topicType: %d, pOutLength: %p.",
- ( void * ) pTopicBuffer, ( void * ) pThingName,
- ( unsigned int ) thingNameLength, topicType,
+ LogError( ( "Invalid input parameters pTopicBuffer: %p, pThingName: %p, thingNameLength: %u,\
+ pShadowName: %p, shadowNameLength: %u, topicType: %d, pOutLength: %p.",
+ ( void * ) pTopicBuffer,
+ ( void * ) pThingName,
+ ( unsigned int ) thingNameLength,
+ ( void * ) pShadowName,
+ ( unsigned int ) shadowNameLength,
+ topicType,
( void * ) pOutLength ) );
}
else
{
- generatedTopicStringLength = SHADOW_PREFIX_LENGTH + /* Prefix ("$aws/things/"). */
- thingNameLength + /* Thing name. */
+ generatedTopicStringLength = SHADOW_PREFIX_LENGTH + /* Prefix ("$aws/things/"). */
+ thingNameLength + /* Thing name. */
+ ( ( shadowNameLength > 0U ) ? /* Handle named or classic shadow */
+ ( SHADOW_NAMED_ROOT_LENGTH + shadowNameLength ) :
+ SHADOW_CLASSIC_ROOT_LENGTH ) +
getShadowOperationLength( topicType ); /* Shadow operation. */
if( bufferSize < generatedTopicStringLength )
@@ -573,24 +772,13 @@ ShadowStatus_t Shadow_GetTopicString( ShadowTopicStringType_t topicType,
}
else
{
- /* Copy the Shadow topic prefix into the topic buffer. */
- ( void ) memcpy( ( void * ) pTopicBuffer,
- ( const void * ) pShadowPrefix,
- ( size_t ) SHADOW_PREFIX_LENGTH );
- offset = ( uint16_t ) ( offset + SHADOW_PREFIX_LENGTH );
-
- /* Copy the Thing Name into the topic buffer. */
- ( void ) memcpy( ( void * ) &( pTopicBuffer[ offset ] ),
- ( const void * ) pThingName,
- ( size_t ) thingNameLength );
- offset = ( uint16_t ) ( offset + thingNameLength );
-
- pOperationString = getShadowOperationString( topicType );
- operationStringLength = getShadowOperationLength( topicType );
- /* Copy the Shadow operation string into the topic buffer. */
- ( void ) memcpy( ( void * ) &( pTopicBuffer[ offset ] ),
- ( const void * ) pOperationString,
- ( size_t ) operationStringLength );
+ /* With everything validated, now create the topic string */
+ createShadowTopicString( topicType,
+ pThingName,
+ thingNameLength,
+ pShadowName,
+ shadowNameLength,
+ pTopicBuffer );
/* Return the generated topic string length to the caller. */
*pOutLength = generatedTopicStringLength;
diff --git a/test/cbmc/proofs/Shadow_GetTopicString/Makefile b/test/cbmc/proofs/Shadow_AssembleTopicString/Makefile
similarity index 94%
rename from test/cbmc/proofs/Shadow_GetTopicString/Makefile
rename to test/cbmc/proofs/Shadow_AssembleTopicString/Makefile
index 1d891407..61d5913a 100644
--- a/test/cbmc/proofs/Shadow_GetTopicString/Makefile
+++ b/test/cbmc/proofs/Shadow_AssembleTopicString/Makefile
@@ -20,8 +20,8 @@
#
HARNESS_ENTRY=harness
-HARNESS_FILE=Shadow_GetTopicString_harness
-PROOF_UID = Shadow_GetTopicString
+HARNESS_FILE=Shadow_AssembleTopicString_harness
+PROOF_UID = Shadow_AssembleTopicString
DEFINES +=
INCLUDES +=
diff --git a/test/cbmc/proofs/Shadow_GetTopicString/README.md b/test/cbmc/proofs/Shadow_AssembleTopicString/README.md
similarity index 61%
rename from test/cbmc/proofs/Shadow_GetTopicString/README.md
rename to test/cbmc/proofs/Shadow_AssembleTopicString/README.md
index d361b5af..90949932 100644
--- a/test/cbmc/proofs/Shadow_GetTopicString/README.md
+++ b/test/cbmc/proofs/Shadow_AssembleTopicString/README.md
@@ -1,7 +1,7 @@
-Shadow_GetTopicString proof
+Shadow_AssembleTopicString proof
==============
-This directory contains a memory safety proof for Shadow_GetTopicString.
+This directory contains a memory safety proof for Shadow_AssembleTopicString.
To run the proof.
* Add cbmc, goto-cc, goto-instrument, goto-analyzer, and cbmc-viewer
diff --git a/test/cbmc/proofs/Shadow_GetTopicString/Shadow_GetTopicString_harness.c b/test/cbmc/proofs/Shadow_AssembleTopicString/Shadow_AssembleTopicString_harness.c
similarity index 72%
rename from test/cbmc/proofs/Shadow_GetTopicString/Shadow_GetTopicString_harness.c
rename to test/cbmc/proofs/Shadow_AssembleTopicString/Shadow_AssembleTopicString_harness.c
index 0628b23f..215fc84f 100644
--- a/test/cbmc/proofs/Shadow_GetTopicString/Shadow_GetTopicString_harness.c
+++ b/test/cbmc/proofs/Shadow_AssembleTopicString/Shadow_AssembleTopicString_harness.c
@@ -21,8 +21,8 @@
*/
/**
- * @file Shadow_GetTopicString_harness.c
- * @brief Implements the proof harness for Shadow_GetTopicString function.
+ * @file Shadow_AssembleTopicString_harness.c
+ * @brief Implements the proof harness for Shadow_AssembleTopicString function.
*/
#include "shadow.h"
@@ -35,16 +35,21 @@ void harness()
uint16_t * pOutLength;
char * pThingName;
uint8_t thingNameLength;
+ char * pShadowName;
+ uint8_t shadowNameLength;
uint8_t topicType;
topicBuffer = mallocCanFail( bufferSize );
pOutLength = mallocCanFail( sizeof( *pOutLength ) );
pThingName = mallocCanFail( thingNameLength );
+ pShadowName = mallocCanFail( shadowNameLength );
- Shadow_GetTopicString( topicType,
- pThingName,
- thingNameLength,
- &( topicBuffer[ 0 ] ),
- bufferSize,
- pOutLength );
+ Shadow_AssembleTopicString( topicType,
+ pThingName,
+ thingNameLength,
+ pShadowName,
+ shadowNameLength,
+ &( topicBuffer[ 0 ] ),
+ bufferSize,
+ pOutLength );
}
diff --git a/test/cbmc/proofs/Shadow_GetTopicString/cbmc-proof.txt b/test/cbmc/proofs/Shadow_AssembleTopicString/cbmc-proof.txt
similarity index 100%
rename from test/cbmc/proofs/Shadow_GetTopicString/cbmc-proof.txt
rename to test/cbmc/proofs/Shadow_AssembleTopicString/cbmc-proof.txt
diff --git a/test/cbmc/proofs/Shadow_GetTopicString/cbmc-viewer.json b/test/cbmc/proofs/Shadow_AssembleTopicString/cbmc-viewer.json
similarity index 62%
rename from test/cbmc/proofs/Shadow_GetTopicString/cbmc-viewer.json
rename to test/cbmc/proofs/Shadow_AssembleTopicString/cbmc-viewer.json
index 0b0688c3..18c1159a 100644
--- a/test/cbmc/proofs/Shadow_GetTopicString/cbmc-viewer.json
+++ b/test/cbmc/proofs/Shadow_AssembleTopicString/cbmc-viewer.json
@@ -2,6 +2,6 @@
[
],
- "proof-name": "Shadow_GetTopicString",
+ "proof-name": "Shadow_AssembleTopicString",
"proof-root": "../cbmc/proofs"
}
diff --git a/test/cbmc/proofs/Shadow_MatchTopic/Makefile b/test/cbmc/proofs/Shadow_MatchTopicString/Makefile
similarity index 69%
rename from test/cbmc/proofs/Shadow_MatchTopic/Makefile
rename to test/cbmc/proofs/Shadow_MatchTopicString/Makefile
index 4def05ee..3cbcd22d 100644
--- a/test/cbmc/proofs/Shadow_MatchTopic/Makefile
+++ b/test/cbmc/proofs/Shadow_MatchTopicString/Makefile
@@ -20,25 +20,25 @@
#
HARNESS_ENTRY=harness
-HARNESS_FILE=Shadow_MatchTopic_harness
-PROOF_UID = Shadow_MatchTopic
+HARNESS_FILE=Shadow_MatchTopicString_harness
+PROOF_UID = Shadow_MatchTopicString
# The topic length is bounded to reduce the proof run time. This length bounds
-# the time to look for the thing name in the topic string. The minimum length
-# of the topic string is the length of the SHADOW_PREFIX ("$aws/things/")
-# plus the maximum Shadow Message Type length ("/shadow/update/documents").
-# Memory safety on the buffer holding the topic string can be proven within
-# a reasonable bound. It adds no value to the proof to input the largest possible
-# topic string accepted by AWS (64KB).
-TOPIC_STRING_LENGTH_MAX=50
+# the time to look for the thing and shadow names in the topic string. It adds
+# no value to the proof to input the largest possible topic string accepted by
+# AWS (64KB). We allow for a the longest named shadow topic, but with only
+# reasonable allowance for typical Thing and Shadow names.
+# $aws/things/thingName/shadow/name/shadowName/update/documents
+TOPIC_STRING_LENGTH_MAX=65
DEFINES += -DTOPIC_STRING_LENGTH_MAX=$(TOPIC_STRING_LENGTH_MAX)
INCLUDES +=
-# The maximum length of the message type ( /shadow/update/documents ) is 24.
-UNWINDSET += strncmp.0:25
+# The maximum length of the message type ( /update/documents ) is 17.
+UNWINDSET += strncmp.0:18
-UNWINDSET += __CPROVER_file_local_shadow_c_validateThingName.0:$(TOPIC_STRING_LENGTH_MAX)
+# Allow for the longest possible Shadow name
+UNWINDSET += __CPROVER_file_local_shadow_c_validateName.0:64
# The number of message types is 8.
UNWINDSET += __CPROVER_file_local_shadow_c_extractShadowMessageType.0:9
diff --git a/test/cbmc/proofs/Shadow_MatchTopic/README.md b/test/cbmc/proofs/Shadow_MatchTopicString/README.md
similarity index 85%
rename from test/cbmc/proofs/Shadow_MatchTopic/README.md
rename to test/cbmc/proofs/Shadow_MatchTopicString/README.md
index d3052f3c..82b4f6f5 100644
--- a/test/cbmc/proofs/Shadow_MatchTopic/README.md
+++ b/test/cbmc/proofs/Shadow_MatchTopicString/README.md
@@ -1,7 +1,7 @@
-Shadow_MatchTopic proof
+Shadow_MatchTopicString proof
==============
-This directory contains a memory safety proof for Shadow_MatchTopic.
+This directory contains a memory safety proof for Shadow_MatchTopicString.
To run the proof.
* Add cbmc, goto-cc, goto-instrument, goto-analyzer, and cbmc-viewer
diff --git a/test/cbmc/proofs/Shadow_MatchTopic/Shadow_MatchTopic_harness.c b/test/cbmc/proofs/Shadow_MatchTopicString/Shadow_MatchTopicString_harness.c
similarity index 73%
rename from test/cbmc/proofs/Shadow_MatchTopic/Shadow_MatchTopic_harness.c
rename to test/cbmc/proofs/Shadow_MatchTopicString/Shadow_MatchTopicString_harness.c
index b3b0dbaa..ab008f62 100644
--- a/test/cbmc/proofs/Shadow_MatchTopic/Shadow_MatchTopic_harness.c
+++ b/test/cbmc/proofs/Shadow_MatchTopicString/Shadow_MatchTopicString_harness.c
@@ -21,8 +21,8 @@
*/
/**
- * @file Shadow_MatchTopic_harness.c
- * @brief Implements the proof harness for Shadow_MatchTopic function.
+ * @file Shadow_MatchTopicString_harness.c
+ * @brief Implements the proof harness for Shadow_MatchTopicString function.
*/
#include "shadow.h"
@@ -35,6 +35,8 @@ void harness()
ShadowMessageType_t * pMessageType;
const char ** pThingName;
uint16_t * pThingNameLength;
+ const char ** pShadowName;
+ uint16_t * pShadowNameLength;
__CPROVER_assume( topicNameLength < TOPIC_STRING_LENGTH_MAX );
pTopicName = mallocCanFail( topicNameLength );
@@ -44,9 +46,14 @@ void harness()
pThingName = mallocCanFail( sizeof( *pThingName ) );
pThingNameLength = mallocCanFail( sizeof( *pThingNameLength ) );
- Shadow_MatchTopic( pTopicName,
- topicNameLength,
- pMessageType,
- pThingName,
- pThingNameLength );
+ pShadowName = mallocCanFail( sizeof( *pShadowName ) );
+ pShadowNameLength = mallocCanFail( sizeof( *pShadowNameLength ) );
+
+ Shadow_MatchTopicString( pTopicName,
+ topicNameLength,
+ pMessageType,
+ pThingName,
+ pThingNameLength,
+ pShadowName,
+ pShadowNameLength );
}
diff --git a/test/cbmc/proofs/Shadow_MatchTopic/cbmc-proof.txt b/test/cbmc/proofs/Shadow_MatchTopicString/cbmc-proof.txt
similarity index 100%
rename from test/cbmc/proofs/Shadow_MatchTopic/cbmc-proof.txt
rename to test/cbmc/proofs/Shadow_MatchTopicString/cbmc-proof.txt
diff --git a/test/cbmc/proofs/Shadow_MatchTopic/cbmc-viewer.json b/test/cbmc/proofs/Shadow_MatchTopicString/cbmc-viewer.json
similarity index 64%
rename from test/cbmc/proofs/Shadow_MatchTopic/cbmc-viewer.json
rename to test/cbmc/proofs/Shadow_MatchTopicString/cbmc-viewer.json
index 084d64b8..6f66bd64 100644
--- a/test/cbmc/proofs/Shadow_MatchTopic/cbmc-viewer.json
+++ b/test/cbmc/proofs/Shadow_MatchTopicString/cbmc-viewer.json
@@ -2,6 +2,6 @@
[
],
- "proof-name": "Shadow_MatchTopic",
+ "proof-name": "Shadow_MatchTopicString",
"proof-root": "../cbmc/proofs"
}
diff --git a/test/unit-test/shadow_utest.c b/test/unit-test/shadow_utest.c
index 6d86942f..03d1b08c 100644
--- a/test/unit-test/shadow_utest.c
+++ b/test/unit-test/shadow_utest.c
@@ -42,198 +42,423 @@
/**
* @brief The Thing Name shared among all the tests.
*/
-#define TEST_THING_NAME "TestThingName"
+#define TEST_THING_NAME "TestThingName"
/**
* @brief The length of #TEST_THING_NAME.
*/
-#define TEST_THING_NAME_LENGTH ( sizeof( TEST_THING_NAME ) - 1 )
+#define TEST_THING_NAME_LENGTH ( sizeof( TEST_THING_NAME ) - 1 )
/**
- * @brief The shadow topic string "update" shared among all test cases.
+ * @brief The shadow topic string "update" shared among all Classic shadow test cases.
*/
-#define TEST_SHADOW_TOPIC_STRING_UPDATE "$aws/things/TestThingName/shadow/update"
+#define TEST_CLASSIC_TOPIC_STRING_UPDATE "$aws/things/TestThingName/shadow/update"
/**
- * @brief The shadow topic string "update/accepted" shared among all test cases.
+ * @brief The shadow topic string "update/accepted" shared among all Classic shadow test cases.
*/
-#define TEST_SHADOW_TOPIC_STRING_UPDATE_ACCEPTED "$aws/things/TestThingName/shadow/update/accepted"
+#define TEST_CLASSIC_TOPIC_STRING_UPDATE_ACCEPTED "$aws/things/TestThingName/shadow/update/accepted"
/**
- * @brief The shadow topic string "update/rejected" shared among all test cases.
+ * @brief The shadow topic string "update/rejected" shared among all Classic shadow test cases.
*/
-#define TEST_SHADOW_TOPIC_STRING_UPDATE_REJECTED "$aws/things/TestThingName/shadow/update/rejected"
+#define TEST_CLASSIC_TOPIC_STRING_UPDATE_REJECTED "$aws/things/TestThingName/shadow/update/rejected"
/**
- * @brief The shadow topic string "update/documents" shared among all test cases.
+ * @brief The shadow topic string "update/documents" shared among all Classic shadow test cases.
*/
-#define TEST_SHADOW_TOPIC_STRING_UPDATE_DOCUMENTS "$aws/things/TestThingName/shadow/update/documents"
+#define TEST_CLASSIC_TOPIC_STRING_UPDATE_DOCUMENTS "$aws/things/TestThingName/shadow/update/documents"
/**
- * @brief The shadow topic string "update/delta" shared among all test cases.
+ * @brief The shadow topic string "update/delta" shared among all Classic shadow test cases.
*/
-#define TEST_SHADOW_TOPIC_STRING_UPDATE_DELTA "$aws/things/TestThingName/shadow/update/delta"
+#define TEST_CLASSIC_TOPIC_STRING_UPDATE_DELTA "$aws/things/TestThingName/shadow/update/delta"
/**
- * @brief The shadow topic string "get" shared among all test cases.
+ * @brief The shadow topic string "get" shared among all Classic shadow test cases.
*/
-#define TEST_SHADOW_TOPIC_STRING_GET "$aws/things/TestThingName/shadow/get"
+#define TEST_CLASSIC_TOPIC_STRING_GET "$aws/things/TestThingName/shadow/get"
/**
- * @brief The shadow topic string "get/accepted" shared among all test cases.
+ * @brief The shadow topic string "get/accepted" shared among all Classic shadow test cases.
*/
-#define TEST_SHADOW_TOPIC_STRING_GET_ACCEPTED "$aws/things/TestThingName/shadow/get/accepted"
+#define TEST_CLASSIC_TOPIC_STRING_GET_ACCEPTED "$aws/things/TestThingName/shadow/get/accepted"
/**
- * @brief The shadow topic string "get/rejected" shared among all test cases.
+ * @brief The shadow topic string "get/rejected" shared among all Classic shadow test cases.
*/
-#define TEST_SHADOW_TOPIC_STRING_GET_REJECTED "$aws/things/TestThingName/shadow/get/rejected"
+#define TEST_CLASSIC_TOPIC_STRING_GET_REJECTED "$aws/things/TestThingName/shadow/get/rejected"
/**
- * @brief The shadow topic string "delete" shared among all test cases.
+ * @brief The shadow topic string "delete" shared among all Classic shadow test cases.
*/
-#define TEST_SHADOW_TOPIC_STRING_DELETE "$aws/things/TestThingName/shadow/delete"
+#define TEST_CLASSIC_TOPIC_STRING_DELETE "$aws/things/TestThingName/shadow/delete"
/**
- * @brief The shadow topic string "delete/accepted" shared among all test cases.
+ * @brief The shadow topic string "delete/accepted" shared among all Classic shadow test cases.
*/
-#define TEST_SHADOW_TOPIC_STRING_DELETE_ACCEPTED "$aws/things/TestThingName/shadow/delete/accepted"
+#define TEST_CLASSIC_TOPIC_STRING_DELETE_ACCEPTED "$aws/things/TestThingName/shadow/delete/accepted"
/**
- * @brief The shadow topic string "delete/rejected" shared among all test cases.
+ * @brief The shadow topic string "delete/rejected" shared among all Classic shadow test cases.
*/
-#define TEST_SHADOW_TOPIC_STRING_DELETE_REJECTED "$aws/things/TestThingName/shadow/delete/rejected"
+#define TEST_CLASSIC_TOPIC_STRING_DELETE_REJECTED "$aws/things/TestThingName/shadow/delete/rejected"
/**
- * @brief The length of #TEST_SHADOW_TOPIC_STRING_UPDATE shared among all test cases.
+ * @brief The length of #TEST_CLASSIC_TOPIC_STRING_UPDATE shared among all Classic shadow test cases.
*/
-#define TEST_SHADOW_TOPIC_LENGTH_UPDATE ( ( uint16_t ) sizeof( TEST_SHADOW_TOPIC_STRING_UPDATE ) - 1U )
+#define TEST_CLASSIC_TOPIC_LENGTH_UPDATE ( ( uint16_t ) sizeof( TEST_CLASSIC_TOPIC_STRING_UPDATE ) - 1U )
/**
- * @brief The length of #TEST_SHADOW_TOPIC_STRING_UPDATE_ACCEPTED shared among all test cases.
+ * @brief The length of #TEST_CLASSIC_TOPIC_STRING_UPDATE_ACCEPTED shared among all Classic shadow test cases.
*/
-#define TEST_SHADOW_TOPIC_LENGTH_UPDATE_ACCEPTED ( ( uint16_t ) sizeof( TEST_SHADOW_TOPIC_STRING_UPDATE_ACCEPTED ) - 1U )
+#define TEST_CLASSIC_TOPIC_LENGTH_UPDATE_ACCEPTED ( ( uint16_t ) sizeof( TEST_CLASSIC_TOPIC_STRING_UPDATE_ACCEPTED ) - 1U )
/**
- * @brief The length of #TEST_SHADOW_TOPIC_STRING_UPDATE_REJECTED shared among all test cases.
+ * @brief The length of #TEST_CLASSIC_TOPIC_STRING_UPDATE_REJECTED shared among all Classic shadow test cases.
*/
-#define TEST_SHADOW_TOPIC_LENGTH_UPDATE_REJECTED ( ( uint16_t ) sizeof( TEST_SHADOW_TOPIC_STRING_UPDATE_REJECTED ) - 1U )
+#define TEST_CLASSIC_TOPIC_LENGTH_UPDATE_REJECTED ( ( uint16_t ) sizeof( TEST_CLASSIC_TOPIC_STRING_UPDATE_REJECTED ) - 1U )
/**
- * @brief The length of #TEST_SHADOW_TOPIC_STRING_UPDATE_DOCUMENTS shared among all test cases.
+ * @brief The length of #TEST_CLASSIC_TOPIC_STRING_UPDATE_DOCUMENTS shared among all Classic shadow test cases.
*/
-#define TEST_SHADOW_TOPIC_LENGTH_UPDATE_DOCUMENTS ( ( uint16_t ) sizeof( TEST_SHADOW_TOPIC_STRING_UPDATE_DOCUMENTS ) - 1U )
+#define TEST_CLASSIC_TOPIC_LENGTH_UPDATE_DOCUMENTS ( ( uint16_t ) sizeof( TEST_CLASSIC_TOPIC_STRING_UPDATE_DOCUMENTS ) - 1U )
/**
- * @brief The length of #TEST_SHADOW_TOPIC_STRING_UPDATE_DELTA shared among all test cases.
+ * @brief The length of #TEST_CLASSIC_TOPIC_STRING_UPDATE_DELTA shared among all Classic shadow test cases.
*/
-#define TEST_SHADOW_TOPIC_LENGTH_UPDATE_DELTA ( ( uint16_t ) sizeof( TEST_SHADOW_TOPIC_STRING_UPDATE_DELTA ) - 1U )
+#define TEST_CLASSIC_TOPIC_LENGTH_UPDATE_DELTA ( ( uint16_t ) sizeof( TEST_CLASSIC_TOPIC_STRING_UPDATE_DELTA ) - 1U )
/**
- * @brief The length of #TEST_SHADOW_TOPIC_STRING_GET shared among all test cases.
+ * @brief The length of #TEST_CLASSIC_TOPIC_STRING_GET shared among all Classic shadow test cases.
*/
-#define TEST_SHADOW_TOPIC_LENGTH_GET ( ( uint16_t ) sizeof( TEST_SHADOW_TOPIC_STRING_GET ) - 1U )
+#define TEST_CLASSIC_TOPIC_LENGTH_GET ( ( uint16_t ) sizeof( TEST_CLASSIC_TOPIC_STRING_GET ) - 1U )
/**
- * @brief The length of #TEST_SHADOW_TOPIC_STRING_GET_ACCEPTED shared among all test cases.
+ * @brief The length of #TEST_CLASSIC_TOPIC_STRING_GET_ACCEPTED shared among all Classic shadow test cases.
*/
-#define TEST_SHADOW_TOPIC_LENGTH_GET_ACCEPTED ( ( uint16_t ) sizeof( TEST_SHADOW_TOPIC_STRING_GET_ACCEPTED ) - 1U )
+#define TEST_CLASSIC_TOPIC_LENGTH_GET_ACCEPTED ( ( uint16_t ) sizeof( TEST_CLASSIC_TOPIC_STRING_GET_ACCEPTED ) - 1U )
/**
- * @brief The length of #TEST_SHADOW_TOPIC_STRING_GET_REJECTED shared among all test cases.
+ * @brief The length of #TEST_CLASSIC_TOPIC_STRING_GET_REJECTED shared among all Classic shadow test cases.
*/
-#define TEST_SHADOW_TOPIC_LENGTH_GET_REJECTED ( ( uint16_t ) sizeof( TEST_SHADOW_TOPIC_STRING_GET_REJECTED ) - 1U )
+#define TEST_CLASSIC_TOPIC_LENGTH_GET_REJECTED ( ( uint16_t ) sizeof( TEST_CLASSIC_TOPIC_STRING_GET_REJECTED ) - 1U )
/**
- * @brief The length of #TEST_SHADOW_TOPIC_STRING_DELETE shared among all test cases.
+ * @brief The length of #TEST_CLASSIC_TOPIC_STRING_DELETE shared among all Classic shadow test cases.
*/
-#define TEST_SHADOW_TOPIC_LENGTH_DELETE ( ( uint16_t ) sizeof( TEST_SHADOW_TOPIC_STRING_DELETE ) - 1U )
+#define TEST_CLASSIC_TOPIC_LENGTH_DELETE ( ( uint16_t ) sizeof( TEST_CLASSIC_TOPIC_STRING_DELETE ) - 1U )
/**
- * @brief The length of #TEST_SHADOW_TOPIC_STRING_DELETE_ACCEPTED shared among all test cases.
+ * @brief The length of #TEST_CLASSIC_TOPIC_STRING_DELETE_ACCEPTED shared among all Classic shadow test cases.
*/
-#define TEST_SHADOW_TOPIC_LENGTH_DELETE_ACCEPTED ( ( uint16_t ) sizeof( TEST_SHADOW_TOPIC_STRING_DELETE_ACCEPTED ) - 1U )
+#define TEST_CLASSIC_TOPIC_LENGTH_DELETE_ACCEPTED ( ( uint16_t ) sizeof( TEST_CLASSIC_TOPIC_STRING_DELETE_ACCEPTED ) - 1U )
/**
- * @brief The length of #TEST_SHADOW_TOPIC_STRING_DELETE_REJECTED shared among all test cases.
+ * @brief The length of #TEST_CLASSIC_TOPIC_STRING_DELETE_REJECTED shared among all Classic shadow test cases.
*/
-#define TEST_SHADOW_TOPIC_LENGTH_DELETE_REJECTED ( ( uint16_t ) sizeof( TEST_SHADOW_TOPIC_STRING_DELETE_REJECTED ) - 1U )
+#define TEST_CLASSIC_TOPIC_LENGTH_DELETE_REJECTED ( ( uint16_t ) sizeof( TEST_CLASSIC_TOPIC_STRING_DELETE_REJECTED ) - 1U )
/**
* @brief A topic string with an empty thing name.
*/
-#define TEST_SHADOW_TOPIC_STRING_EMPTY_THINGNAME "$aws/things/"
+#define TEST_TOPIC_STRING_EMPTY_THINGNAME "$aws/things/"
/**
* @brief A topic string with an invalid thing name.
*/
-#define TEST_SHADOW_TOPIC_STRING_INVALID_THINGNAME "$aws/things//"
+#define TEST_TOPIC_STRING_INVALID_THINGNAME "$aws/things//"
+
+/**
+ * @brief A topic string with an un-terminated thing name
+ */
+#define TEST_TOPIC_STRING_UNTERMINATED_THINGNAME "$aws/things/TestThingName"
+
+/**
+ * @brief A topic string with an empty shadow root.
+ */
+#define TEST_TOPIC_STRING_EMPTY_SHADOW_ROOT "$aws/things/TestThingName/"
+
+/**
+ * @brief A topic string with an invalid shadow root.
+ */
+#define TEST_TOPIC_STRING_INVALID_SHADOW_ROOT "$aws/things/TestThingName/invalid"
/**
* @brief A topic string with an empty shadow message type.
*/
-#define TEST_SHADOW_TOPIC_STRING_EMPTY_SHADOW_MESSAGE_TYPE "$aws/things/TestThingName"
+#define TEST_CLASSIC_TOPIC_STRING_EMPTY_SHADOW_MESSAGE_TYPE "$aws/things/TestThingName/shadow"
/**
* @brief A topic string that is not related to Shadow.
*/
-#define TEST_SHADOW_TOPIC_STRING_INVALID_SHADOW_RESPONSE "$aws/things/TestThingName/shadow/invalid/invalid"
+#define TEST_CLASSIC_TOPIC_STRING_INVALID_SHADOW_RESPONSE "$aws/things/TestThingName/shadow/invalid/invalid"
/**
* @brief A topic string that is not related to Shadow.
*/
-#define TEST_SHADOW_TOPIC_STRING_INVALID_GET_REJECTED "$aws/things/TestThingName/shadow/get/rejected/gibberish"
+#define TEST_CLASSIC_TOPIC_STRING_INVALID_GET_REJECTED "$aws/things/TestThingName/shadow/get/rejected/gibberish"
+
+/**
+ * @brief A topic string that is not related to Shadow.
+ */
+#define TEST_TOPIC_STRING_INVALID_PREFIX "$aws/jobs/TestThingName/shadow/get/rejected"
+
+/**
+ * @brief The length of #TEST_TOPIC_STRING_INVALID_PREFIX shared among all shadow test cases.
+ */
+#define TEST_TOPIC_LENGTH_INVALID_PREFIX ( ( uint16_t ) sizeof( TEST_TOPIC_STRING_INVALID_PREFIX ) - 1U )
+
+/**
+ * @brief The length of #TEST_TOPIC_STRING_EMPTY_THINGNAME shared among all shadow test cases.
+ */
+#define TEST_TOPIC_LENGTH_EMPTY_THINGNAME ( ( uint16_t ) sizeof( TEST_TOPIC_STRING_EMPTY_THINGNAME ) - 1U )
+
+/**
+ * @brief The length of #TEST_TOPIC_STRING_INVALID_THINGNAME shared among all shadow test cases.
+ */
+#define TEST_TOPIC_LENGTH_INVALID_THINGNAME ( ( uint16_t ) sizeof( TEST_TOPIC_STRING_INVALID_THINGNAME ) - 1U )
+
+/**
+ * @brief The length of #TEST_TOPIC_STRING_UNTERMINATED_THINGNAME shared among all shadow test cases.
+ */
+#define TEST_TOPIC_LENGTH_UNTERMINATED_THINGNAME ( ( uint16_t ) sizeof( TEST_TOPIC_STRING_UNTERMINATED_THINGNAME ) - 1U )
+
+/**
+ * @brief The length of #TEST_TOPIC_STRING_EMPTY_SHADOW_ROOT shared among all shadow test cases.
+ */
+#define TEST_TOPIC_LENGTH_EMPTY_SHADOW_ROOT ( ( uint16_t ) sizeof( TEST_TOPIC_STRING_EMPTY_SHADOW_ROOT ) - 1U )
+
+/**
+ * @brief The length of #TEST_TOPIC_STRING_INVALID_SHADOW_ROOT shared among all shadow test cases.
+ */
+#define TEST_TOPIC_LENGTH_INVALID_SHADOW_ROOT ( ( uint16_t ) sizeof( TEST_TOPIC_STRING_INVALID_SHADOW_ROOT ) - 1U )
+
+/**
+ * @brief The length of #TEST_CLASSIC_TOPIC_STRING_EMPTY_SHADOW_MESSAGE_TYPE shared among all Classic shadow test cases.
+ */
+#define TEST_CLASSIC_TOPIC_LENGTH_EMPTY_SHADOW_MESSAGE_TYPE ( ( uint16_t ) sizeof( TEST_CLASSIC_TOPIC_STRING_EMPTY_SHADOW_MESSAGE_TYPE ) - 1U )
+
+/**
+ * @brief The length of #TEST_CLASSIC_TOPIC_STRING_INVALID_SHADOW_RESPONSE shared among all Classic shadow test cases.
+ */
+#define TEST_CLASSIC_TOPIC_LENGTH_INVALID_SHADOW_RESPONSE ( ( uint16_t ) sizeof( TEST_CLASSIC_TOPIC_STRING_INVALID_SHADOW_RESPONSE ) - 1U )
+
+/**
+ * @brief The length of #TEST_CLASSIC_TOPIC_STRING_INVALID_GET_REJECTED shared among all Classic shadow test cases.
+ */
+#define TEST_CLASSIC_TOPIC_LENGTH_INVALID_GET_REJECTED ( ( uint16_t ) sizeof( TEST_CLASSIC_TOPIC_STRING_INVALID_GET_REJECTED ) - 1U )
+
+/**
+ * @brief The init value for a topic buffer.
+ */
+#define TEST_CLASSIC_TOPIC_BUFFER_INITIALIZE "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789abcdefghijklmno"
+
+/**
+ * @brief The init value for a topic buffer.
+ */
+#define TEST_CLASSIC_TOPIC_BUFFER_MODIFIED "$aws/things/TestThingName/shadow/get/acceptedklmno"
+
+/**
+ * @brief The length of #TEST_CLASSIC_TOPIC_STRING_DELETE_REJECTED shared among all Classic shadow test cases.
+ */
+#define TEST_CLASSIC_TOPIC_BUFFER_LENGTH ( ( uint16_t ) sizeof( TEST_CLASSIC_TOPIC_BUFFER_INITIALIZE ) - 1U )
+
+
+/**
+ * @brief The Shadow Name shared among all the named shadow tests.
+ */
+#define TEST_SHADOW_NAME "TestShadowName"
+
+/**
+ * @brief The length of #TEST_SHADOW_NAME.
+ */
+#define TEST_SHADOW_NAME_LENGTH ( sizeof( TEST_SHADOW_NAME ) - 1 )
+
+/**
+ * @brief The shadow topic string "update" shared among all named shadow test cases.
+ */
+#define TEST_NAMED_TOPIC_STRING_UPDATE "$aws/things/TestThingName/shadow/name/TestShadowName/update"
+
+/**
+ * @brief The shadow topic string "update/accepted" shared among all named shadow test cases.
+ */
+#define TEST_NAMED_TOPIC_STRING_UPDATE_ACCEPTED "$aws/things/TestThingName/shadow/name/TestShadowName/update/accepted"
+
+/**
+ * @brief The shadow topic string "update/rejected" shared among all named shadow test cases.
+ */
+#define TEST_NAMED_TOPIC_STRING_UPDATE_REJECTED "$aws/things/TestThingName/shadow/name/TestShadowName/update/rejected"
+
+/**
+ * @brief The shadow topic string "update/documents" shared among all named shadow test cases.
+ */
+#define TEST_NAMED_TOPIC_STRING_UPDATE_DOCUMENTS "$aws/things/TestThingName/shadow/name/TestShadowName/update/documents"
+
+/**
+ * @brief The shadow topic string "update/delta" shared among all named shadow test cases.
+ */
+#define TEST_NAMED_TOPIC_STRING_UPDATE_DELTA "$aws/things/TestThingName/shadow/name/TestShadowName/update/delta"
+
+/**
+ * @brief The shadow topic string "get" shared among all named shadow test cases.
+ */
+#define TEST_NAMED_TOPIC_STRING_GET "$aws/things/TestThingName/shadow/name/TestShadowName/get"
+
+/**
+ * @brief The shadow topic string "get/accepted" shared among all named shadow test cases.
+ */
+#define TEST_NAMED_TOPIC_STRING_GET_ACCEPTED "$aws/things/TestThingName/shadow/name/TestShadowName/get/accepted"
+
+/**
+ * @brief The shadow topic string "get/rejected" shared among all named shadow test cases.
+ */
+#define TEST_NAMED_TOPIC_STRING_GET_REJECTED "$aws/things/TestThingName/shadow/name/TestShadowName/get/rejected"
+
+/**
+ * @brief The shadow topic string "delete" shared among all named shadow test cases.
+ */
+#define TEST_NAMED_TOPIC_STRING_DELETE "$aws/things/TestThingName/shadow/name/TestShadowName/delete"
+
+/**
+ * @brief The shadow topic string "delete/accepted" shared among all named shadow test cases.
+ */
+#define TEST_NAMED_TOPIC_STRING_DELETE_ACCEPTED "$aws/things/TestThingName/shadow/name/TestShadowName/delete/accepted"
+
+/**
+ * @brief The shadow topic string "delete/rejected" shared among all named shadow test cases.
+ */
+#define TEST_NAMED_TOPIC_STRING_DELETE_REJECTED "$aws/things/TestThingName/shadow/name/TestShadowName/delete/rejected"
+
+/**
+ * @brief The length of #TEST_NAMED_TOPIC_STRING_UPDATE shared among all named shadow test cases.
+ */
+#define TEST_NAMED_TOPIC_LENGTH_UPDATE ( ( uint16_t ) sizeof( TEST_NAMED_TOPIC_STRING_UPDATE ) - 1U )
+
+/**
+ * @brief The length of #TEST_NAMED_TOPIC_STRING_UPDATE_ACCEPTED shared among all named shadow test cases.
+ */
+#define TEST_NAMED_TOPIC_LENGTH_UPDATE_ACCEPTED ( ( uint16_t ) sizeof( TEST_NAMED_TOPIC_STRING_UPDATE_ACCEPTED ) - 1U )
+
+/**
+ * @brief The length of #TEST_NAMED_TOPIC_STRING_UPDATE_REJECTED shared among all named shadow test cases.
+ */
+#define TEST_NAMED_TOPIC_LENGTH_UPDATE_REJECTED ( ( uint16_t ) sizeof( TEST_NAMED_TOPIC_STRING_UPDATE_REJECTED ) - 1U )
+
+/**
+ * @brief The length of #TEST_NAMED_TOPIC_STRING_UPDATE_DOCUMENTS shared among all named shadow test cases.
+ */
+#define TEST_NAMED_TOPIC_LENGTH_UPDATE_DOCUMENTS ( ( uint16_t ) sizeof( TEST_NAMED_TOPIC_STRING_UPDATE_DOCUMENTS ) - 1U )
+
+/**
+ * @brief The length of #TEST_NAMED_TOPIC_STRING_UPDATE_DELTA shared among all named shadow test cases.
+ */
+#define TEST_NAMED_TOPIC_LENGTH_UPDATE_DELTA ( ( uint16_t ) sizeof( TEST_NAMED_TOPIC_STRING_UPDATE_DELTA ) - 1U )
+
+/**
+ * @brief The length of #TEST_NAMED_TOPIC_STRING_GET shared among all named shadow test cases.
+ */
+#define TEST_NAMED_TOPIC_LENGTH_GET ( ( uint16_t ) sizeof( TEST_NAMED_TOPIC_STRING_GET ) - 1U )
+
+/**
+ * @brief The length of #TEST_NAMED_TOPIC_STRING_GET_ACCEPTED shared among all named shadow test cases.
+ */
+#define TEST_NAMED_TOPIC_LENGTH_GET_ACCEPTED ( ( uint16_t ) sizeof( TEST_NAMED_TOPIC_STRING_GET_ACCEPTED ) - 1U )
+
+/**
+ * @brief The length of #TEST_NAMED_TOPIC_STRING_GET_REJECTED shared among all named shadow test cases.
+ */
+#define TEST_NAMED_TOPIC_LENGTH_GET_REJECTED ( ( uint16_t ) sizeof( TEST_NAMED_TOPIC_STRING_GET_REJECTED ) - 1U )
+
+/**
+ * @brief The length of #TEST_NAMED_TOPIC_STRING_DELETE shared among all named shadow test cases.
+ */
+#define TEST_NAMED_TOPIC_LENGTH_DELETE ( ( uint16_t ) sizeof( TEST_NAMED_TOPIC_STRING_DELETE ) - 1U )
+
+/**
+ * @brief The length of #TEST_NAMED_TOPIC_STRING_DELETE_ACCEPTED shared among all named shadow test cases.
+ */
+#define TEST_NAMED_TOPIC_LENGTH_DELETE_ACCEPTED ( ( uint16_t ) sizeof( TEST_NAMED_TOPIC_STRING_DELETE_ACCEPTED ) - 1U )
+
+/**
+ * @brief The length of #TEST_NAMED_TOPIC_STRING_DELETE_REJECTED shared among all named shadow test cases.
+ */
+#define TEST_NAMED_TOPIC_LENGTH_DELETE_REJECTED ( ( uint16_t ) sizeof( TEST_NAMED_TOPIC_STRING_DELETE_REJECTED ) - 1U )
+
+/**
+ * @brief A topic string with an empty shadow name.
+ */
+#define TEST_NAMED_TOPIC_STRING_EMPTY_SHADOWNAME "$aws/things/TestThingName/shadow/name/"
+
+/**
+ * @brief A topic string with an invalid shadow name.
+ */
+#define TEST_NAMED_TOPIC_STRING_INVALID_SHADOWNAME "$aws/things/TestThingName/shadow/name//"
+
+/**
+ * @brief A topic string with an un-terminated shadow name
+ */
+#define TEST_NAMED_TOPIC_STRING_UNTERMINATED_SHADOWNAME "$aws/things/TestThingName/shadow/name/TestShadowName"
+
+/**
+ * @brief A topic string with an empty shadow message type.
+ */
+#define TEST_NAMED_TOPIC_STRING_EMPTY_SHADOW_MESSAGE_TYPE "$aws/things/TestThingName/shadow/name/TestShadowName/"
/**
* @brief A topic string that is not related to Shadow.
*/
-#define TEST_SHADOW_TOPIC_STRING_INVALID_PREFIX "$aws/jobs/TestThingName/shadow/get/rejected"
+#define TEST_NAMED_TOPIC_STRING_INVALID_SHADOW_RESPONSE "$aws/things/TestThingName/shadow/name/TestShadowName/invalid/invalid"
/**
- * @brief The length of #TEST_SHADOW_TOPIC_STRING_EMPTY_THINGNAME shared among all test cases.
+ * @brief A topic string that is not related to Shadow.
*/
-#define TEST_SHADOW_TOPIC_LENGTH_EMPTY_THINGNAME ( ( uint16_t ) sizeof( TEST_SHADOW_TOPIC_STRING_EMPTY_THINGNAME ) - 1U )
+#define TEST_NAMED_TOPIC_STRING_INVALID_GET_REJECTED "$aws/things/TestThingName/shadow/name/TestShadowName/get/rejected/gibberish"
/**
- * @brief The length of #TEST_SHADOW_TOPIC_STRING_INVALID_THINGNAME shared among all test cases.
+ * @brief The length of #TEST_NAMED_TOPIC_STRING_EMPTY_SHADOWNAME shared among all named shadow test cases.
*/
-#define TEST_SHADOW_TOPIC_LENGTH_INVALID_THINGNAME ( ( uint16_t ) sizeof( TEST_SHADOW_TOPIC_STRING_INVALID_THINGNAME ) - 1U )
+#define TEST_NAMED_TOPIC_LENGTH_EMPTY_SHADOWNAME ( ( uint16_t ) sizeof( TEST_NAMED_TOPIC_STRING_EMPTY_SHADOWNAME ) - 1U )
+/**
+ * @brief The length of #TEST_NAMED_TOPIC_STRING_INVALID_SHADOWNAME shared among all named shadow test cases.
+ */
+#define TEST_NAMED_TOPIC_LENGTH_INVALID_SHADOWNAME ( ( uint16_t ) sizeof( TEST_NAMED_TOPIC_STRING_INVALID_SHADOWNAME ) - 1U )
/**
- * @brief The length of #TEST_SHADOW_TOPIC_STRING_EMPTY_SHADOW_MESSAGE_TYPE shared among all test cases.
+ * @brief The length of #TEST_NAMED_TOPIC_STRING_UNTERMINATED_SHADOWNAME shared among all named shadow test cases.
*/
-#define TEST_SHADOW_TOPIC_LENGTH_EMPTY_SHADOW_MESSAGE_TYPE ( ( uint16_t ) sizeof( TEST_SHADOW_TOPIC_STRING_EMPTY_SHADOW_MESSAGE_TYPE ) - 1U )
+#define TEST_NAMED_TOPIC_LENGTH_UNTERMINATED_SHADOWNAME ( ( uint16_t ) sizeof( TEST_NAMED_TOPIC_STRING_UNTERMINATED_SHADOWNAME ) - 1U )
/**
- * @brief The length of #TEST_SHADOW_TOPIC_STRING_INVALID_SHADOW_RESPONSE shared among all test cases.
+ * @brief The length of #TEST_NAMED_TOPIC_STRING_EMPTY_SHADOW_MESSAGE_TYPE shared among all named shadow test cases.
*/
-#define TEST_SHADOW_TOPIC_LENGTH_INVALID_SHADOW_RESPONSE ( ( uint16_t ) sizeof( TEST_SHADOW_TOPIC_STRING_INVALID_SHADOW_RESPONSE ) - 1U )
+#define TEST_NAMED_TOPIC_LENGTH_EMPTY_SHADOW_MESSAGE_TYPE ( ( uint16_t ) sizeof( TEST_NAMED_TOPIC_STRING_EMPTY_SHADOW_MESSAGE_TYPE ) - 1U )
/**
- * @brief The length of #TEST_SHADOW_TOPIC_STRING_INVALID_GET_REJECTED shared among all test cases.
+ * @brief The length of #TEST_NAMED_TOPIC_STRING_INVALID_SHADOW_RESPONSE shared among all named shadow test cases.
*/
-#define TEST_SHADOW_TOPIC_LENGTH_INVALID_GET_REJECTED ( ( uint16_t ) sizeof( TEST_SHADOW_TOPIC_STRING_INVALID_GET_REJECTED ) - 1U )
+#define TEST_NAMED_TOPIC_LENGTH_INVALID_SHADOW_RESPONSE ( ( uint16_t ) sizeof( TEST_NAMED_TOPIC_STRING_INVALID_SHADOW_RESPONSE ) - 1U )
/**
- * @brief The length of #TEST_SHADOW_TOPIC_STRING_INVALID_PREFIX shared among all test cases.
+ * @brief The length of #TEST_NAMED_TOPIC_STRING_INVALID_GET_REJECTED shared among all named shadow test cases.
*/
-#define TEST_SHADOW_TOPIC_LENGTH_INVALID_PREFIX ( ( uint16_t ) sizeof( TEST_SHADOW_TOPIC_STRING_INVALID_PREFIX ) - 1U )
+#define TEST_NAMED_TOPIC_LENGTH_INVALID_GET_REJECTED ( ( uint16_t ) sizeof( TEST_NAMED_TOPIC_STRING_INVALID_GET_REJECTED ) - 1U )
/**
* @brief The init value for a topic buffer.
*/
-#define TEST_SHADOW_TOPIC_BUFFER_INITIALZIE "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789abcdefghijklmno"
+#define TEST_NAMED_TOPIC_BUFFER_INITIALIZE "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789abcdefghijklmnopqrstuvwxyz123456789"
/**
* @brief The init value for a topic buffer.
*/
-#define TEST_SHADOW_TOPIC_BUFFER_MODIFIED "$aws/things/TestThingName/shadow/get/acceptedklmno"
+#define TEST_NAMED_TOPIC_BUFFER_MODIFIED "$aws/things/TestThingName/shadow/name/TestShadowName/get/accepted56789"
/**
- * @brief The length of #TEST_SHADOW_TOPIC_STRING_DELETE_REJECTED shared among all test cases.
+ * @brief The length of #TEST_NAMED_TOPIC_STRING_DELETE_REJECTED shared among all named shadow test cases.
*/
-#define TEST_SHADOW_TOPIC_BUFFER_LENGTH ( ( uint16_t ) sizeof( TEST_SHADOW_TOPIC_BUFFER_INITIALZIE ) - 1U )
+#define TEST_NAMED_TOPIC_BUFFER_LENGTH ( ( uint16_t ) sizeof( TEST_NAMED_TOPIC_BUFFER_INITIALIZE ) - 1U )
/*-----------------------------------------------------------*/
@@ -262,90 +487,130 @@ int suiteTearDown( int numFailures )
/*-----------------------------------------------------------*/
/**
- * @brief Tests the macros generates the expected strings.
+ * @brief Tests the macros generate the expected strings for Classic shadows.
*/
-void test_Shadow_MacrosString( void )
+void test_Shadow_Classic_MacrosString( void )
{
- TEST_ASSERT_EQUAL( TEST_SHADOW_TOPIC_STRING_UPDATE, SHADOW_TOPIC_STRING_UPDATE( TEST_THING_NAME ) );
- TEST_ASSERT_EQUAL( TEST_SHADOW_TOPIC_STRING_UPDATE_ACCEPTED, SHADOW_TOPIC_STRING_UPDATE_ACCEPTED( TEST_THING_NAME ) );
- TEST_ASSERT_EQUAL( TEST_SHADOW_TOPIC_STRING_UPDATE_REJECTED, SHADOW_TOPIC_STRING_UPDATE_REJECTED( TEST_THING_NAME ) );
- TEST_ASSERT_EQUAL( TEST_SHADOW_TOPIC_STRING_UPDATE_DOCUMENTS, SHADOW_TOPIC_STRING_UPDATE_DOCUMENTS( TEST_THING_NAME ) );
- TEST_ASSERT_EQUAL( TEST_SHADOW_TOPIC_STRING_UPDATE_DELTA, SHADOW_TOPIC_STRING_UPDATE_DELTA( TEST_THING_NAME ) );
- TEST_ASSERT_EQUAL( TEST_SHADOW_TOPIC_STRING_GET, SHADOW_TOPIC_STRING_GET( TEST_THING_NAME ) );
- TEST_ASSERT_EQUAL( TEST_SHADOW_TOPIC_STRING_GET_ACCEPTED, SHADOW_TOPIC_STRING_GET_ACCEPTED( TEST_THING_NAME ) );
- TEST_ASSERT_EQUAL( TEST_SHADOW_TOPIC_STRING_GET_REJECTED, SHADOW_TOPIC_STRING_GET_REJECTED( TEST_THING_NAME ) );
- TEST_ASSERT_EQUAL( TEST_SHADOW_TOPIC_STRING_DELETE, SHADOW_TOPIC_STRING_DELETE( TEST_THING_NAME ) );
- TEST_ASSERT_EQUAL( TEST_SHADOW_TOPIC_STRING_DELETE_ACCEPTED, SHADOW_TOPIC_STRING_DELETE_ACCEPTED( TEST_THING_NAME ) );
- TEST_ASSERT_EQUAL( TEST_SHADOW_TOPIC_STRING_DELETE_REJECTED, SHADOW_TOPIC_STRING_DELETE_REJECTED( TEST_THING_NAME ) );
+ /* Test Classic shadow topic strings through the deprecated legacy macros, to verify the legacy macros. */
+ TEST_ASSERT_EQUAL( TEST_CLASSIC_TOPIC_STRING_UPDATE, SHADOW_TOPIC_STRING_UPDATE( TEST_THING_NAME ) );
+ TEST_ASSERT_EQUAL( TEST_CLASSIC_TOPIC_STRING_UPDATE_ACCEPTED, SHADOW_TOPIC_STRING_UPDATE_ACCEPTED( TEST_THING_NAME ) );
+ TEST_ASSERT_EQUAL( TEST_CLASSIC_TOPIC_STRING_UPDATE_REJECTED, SHADOW_TOPIC_STRING_UPDATE_REJECTED( TEST_THING_NAME ) );
+ TEST_ASSERT_EQUAL( TEST_CLASSIC_TOPIC_STRING_UPDATE_DOCUMENTS, SHADOW_TOPIC_STRING_UPDATE_DOCUMENTS( TEST_THING_NAME ) );
+ TEST_ASSERT_EQUAL( TEST_CLASSIC_TOPIC_STRING_UPDATE_DELTA, SHADOW_TOPIC_STRING_UPDATE_DELTA( TEST_THING_NAME ) );
+ TEST_ASSERT_EQUAL( TEST_CLASSIC_TOPIC_STRING_GET, SHADOW_TOPIC_STRING_GET( TEST_THING_NAME ) );
+ TEST_ASSERT_EQUAL( TEST_CLASSIC_TOPIC_STRING_GET_ACCEPTED, SHADOW_TOPIC_STRING_GET_ACCEPTED( TEST_THING_NAME ) );
+ TEST_ASSERT_EQUAL( TEST_CLASSIC_TOPIC_STRING_GET_REJECTED, SHADOW_TOPIC_STRING_GET_REJECTED( TEST_THING_NAME ) );
+ TEST_ASSERT_EQUAL( TEST_CLASSIC_TOPIC_STRING_DELETE, SHADOW_TOPIC_STRING_DELETE( TEST_THING_NAME ) );
+ TEST_ASSERT_EQUAL( TEST_CLASSIC_TOPIC_STRING_DELETE_ACCEPTED, SHADOW_TOPIC_STRING_DELETE_ACCEPTED( TEST_THING_NAME ) );
+ TEST_ASSERT_EQUAL( TEST_CLASSIC_TOPIC_STRING_DELETE_REJECTED, SHADOW_TOPIC_STRING_DELETE_REJECTED( TEST_THING_NAME ) );
+}
+
+/**
+ * @brief Tests the macros generate the expected strings for named shadows.
+ */
+void test_Shadow_Named_MacrosString( void )
+{
+ TEST_ASSERT_EQUAL( TEST_NAMED_TOPIC_STRING_UPDATE, SHADOW_TOPIC_STR_UPDATE( TEST_THING_NAME, TEST_SHADOW_NAME ) );
+ TEST_ASSERT_EQUAL( TEST_NAMED_TOPIC_STRING_UPDATE_ACCEPTED, SHADOW_TOPIC_STR_UPDATE_ACC( TEST_THING_NAME, TEST_SHADOW_NAME ) );
+ TEST_ASSERT_EQUAL( TEST_NAMED_TOPIC_STRING_UPDATE_REJECTED, SHADOW_TOPIC_STR_UPDATE_REJ( TEST_THING_NAME, TEST_SHADOW_NAME ) );
+ TEST_ASSERT_EQUAL( TEST_NAMED_TOPIC_STRING_UPDATE_DOCUMENTS, SHADOW_TOPIC_STR_UPDATE_DOCS( TEST_THING_NAME, TEST_SHADOW_NAME ) );
+ TEST_ASSERT_EQUAL( TEST_NAMED_TOPIC_STRING_UPDATE_DELTA, SHADOW_TOPIC_STR_UPDATE_DELTA( TEST_THING_NAME, TEST_SHADOW_NAME ) );
+ TEST_ASSERT_EQUAL( TEST_NAMED_TOPIC_STRING_GET, SHADOW_TOPIC_STR_GET( TEST_THING_NAME, TEST_SHADOW_NAME ) );
+ TEST_ASSERT_EQUAL( TEST_NAMED_TOPIC_STRING_GET_ACCEPTED, SHADOW_TOPIC_STR_GET_ACC( TEST_THING_NAME, TEST_SHADOW_NAME ) );
+ TEST_ASSERT_EQUAL( TEST_NAMED_TOPIC_STRING_GET_REJECTED, SHADOW_TOPIC_STR_GET_REJ( TEST_THING_NAME, TEST_SHADOW_NAME ) );
+ TEST_ASSERT_EQUAL( TEST_NAMED_TOPIC_STRING_DELETE, SHADOW_TOPIC_STR_DELETE( TEST_THING_NAME, TEST_SHADOW_NAME ) );
+ TEST_ASSERT_EQUAL( TEST_NAMED_TOPIC_STRING_DELETE_ACCEPTED, SHADOW_TOPIC_STR_DELETE_ACC( TEST_THING_NAME, TEST_SHADOW_NAME ) );
+ TEST_ASSERT_EQUAL( TEST_NAMED_TOPIC_STRING_DELETE_REJECTED, SHADOW_TOPIC_STR_DELETE_REJ( TEST_THING_NAME, TEST_SHADOW_NAME ) );
}
/*-----------------------------------------------------------*/
/**
- * @brief Tests the macros generates the expected strings length.
+ * @brief Tests the macros generate the expected strings length for Classic shadows.
*/
-void test_Shadow_MacrosLength( void )
+void test_Shadow_Classic_MacrosLength( void )
{
- TEST_ASSERT_EQUAL( TEST_SHADOW_TOPIC_LENGTH_UPDATE, SHADOW_TOPIC_LENGTH_UPDATE( TEST_THING_NAME_LENGTH ) );
- TEST_ASSERT_EQUAL( TEST_SHADOW_TOPIC_LENGTH_UPDATE_ACCEPTED, SHADOW_TOPIC_LENGTH_UPDATE_ACCEPTED( TEST_THING_NAME_LENGTH ) );
- TEST_ASSERT_EQUAL( TEST_SHADOW_TOPIC_LENGTH_UPDATE_REJECTED, SHADOW_TOPIC_LENGTH_UPDATE_REJECTED( TEST_THING_NAME_LENGTH ) );
- TEST_ASSERT_EQUAL( TEST_SHADOW_TOPIC_LENGTH_UPDATE_DOCUMENTS, SHADOW_TOPIC_LENGTH_UPDATE_DOCUMENTS( TEST_THING_NAME_LENGTH ) );
- TEST_ASSERT_EQUAL( TEST_SHADOW_TOPIC_LENGTH_UPDATE_DELTA, SHADOW_TOPIC_LENGTH_UPDATE_DELTA( TEST_THING_NAME_LENGTH ) );
- TEST_ASSERT_EQUAL( TEST_SHADOW_TOPIC_LENGTH_GET, SHADOW_TOPIC_LENGTH_GET( TEST_THING_NAME_LENGTH ) );
- TEST_ASSERT_EQUAL( TEST_SHADOW_TOPIC_LENGTH_GET_ACCEPTED, SHADOW_TOPIC_LENGTH_GET_ACCEPTED( TEST_THING_NAME_LENGTH ) );
- TEST_ASSERT_EQUAL( TEST_SHADOW_TOPIC_LENGTH_GET_REJECTED, SHADOW_TOPIC_LENGTH_GET_REJECTED( TEST_THING_NAME_LENGTH ) );
- TEST_ASSERT_EQUAL( TEST_SHADOW_TOPIC_LENGTH_DELETE, SHADOW_TOPIC_LENGTH_DELETE( TEST_THING_NAME_LENGTH ) );
- TEST_ASSERT_EQUAL( TEST_SHADOW_TOPIC_LENGTH_DELETE_ACCEPTED, SHADOW_TOPIC_LENGTH_DELETE_ACCEPTED( TEST_THING_NAME_LENGTH ) );
- TEST_ASSERT_EQUAL( TEST_SHADOW_TOPIC_LENGTH_DELETE_REJECTED, SHADOW_TOPIC_LENGTH_DELETE_REJECTED( TEST_THING_NAME_LENGTH ) );
+ /* Test Classic shadow topic lengths through the deprecated legacy macros, to verify the legacy macros. */
+ TEST_ASSERT_EQUAL( TEST_CLASSIC_TOPIC_LENGTH_UPDATE, SHADOW_TOPIC_LENGTH_UPDATE( TEST_THING_NAME_LENGTH ) );
+ TEST_ASSERT_EQUAL( TEST_CLASSIC_TOPIC_LENGTH_UPDATE_ACCEPTED, SHADOW_TOPIC_LENGTH_UPDATE_ACCEPTED( TEST_THING_NAME_LENGTH ) );
+ TEST_ASSERT_EQUAL( TEST_CLASSIC_TOPIC_LENGTH_UPDATE_REJECTED, SHADOW_TOPIC_LENGTH_UPDATE_REJECTED( TEST_THING_NAME_LENGTH ) );
+ TEST_ASSERT_EQUAL( TEST_CLASSIC_TOPIC_LENGTH_UPDATE_DOCUMENTS, SHADOW_TOPIC_LENGTH_UPDATE_DOCUMENTS( TEST_THING_NAME_LENGTH ) );
+ TEST_ASSERT_EQUAL( TEST_CLASSIC_TOPIC_LENGTH_UPDATE_DELTA, SHADOW_TOPIC_LENGTH_UPDATE_DELTA( TEST_THING_NAME_LENGTH ) );
+ TEST_ASSERT_EQUAL( TEST_CLASSIC_TOPIC_LENGTH_GET, SHADOW_TOPIC_LENGTH_GET( TEST_THING_NAME_LENGTH ) );
+ TEST_ASSERT_EQUAL( TEST_CLASSIC_TOPIC_LENGTH_GET_ACCEPTED, SHADOW_TOPIC_LENGTH_GET_ACCEPTED( TEST_THING_NAME_LENGTH ) );
+ TEST_ASSERT_EQUAL( TEST_CLASSIC_TOPIC_LENGTH_GET_REJECTED, SHADOW_TOPIC_LENGTH_GET_REJECTED( TEST_THING_NAME_LENGTH ) );
+ TEST_ASSERT_EQUAL( TEST_CLASSIC_TOPIC_LENGTH_DELETE, SHADOW_TOPIC_LENGTH_DELETE( TEST_THING_NAME_LENGTH ) );
+ TEST_ASSERT_EQUAL( TEST_CLASSIC_TOPIC_LENGTH_DELETE_ACCEPTED, SHADOW_TOPIC_LENGTH_DELETE_ACCEPTED( TEST_THING_NAME_LENGTH ) );
+ TEST_ASSERT_EQUAL( TEST_CLASSIC_TOPIC_LENGTH_DELETE_REJECTED, SHADOW_TOPIC_LENGTH_DELETE_REJECTED( TEST_THING_NAME_LENGTH ) );
+}
+
+/**
+ * @brief Tests the macros generate the expected strings length for named shadows.
+ */
+void test_Shadow_Named_MacrosLength( void )
+{
+ TEST_ASSERT_EQUAL( TEST_NAMED_TOPIC_LENGTH_UPDATE, SHADOW_TOPIC_LEN_UPDATE( TEST_THING_NAME_LENGTH, TEST_SHADOW_NAME_LENGTH ) );
+ TEST_ASSERT_EQUAL( TEST_NAMED_TOPIC_LENGTH_UPDATE_ACCEPTED, SHADOW_TOPIC_LEN_UPDATE_ACC( TEST_THING_NAME_LENGTH, TEST_SHADOW_NAME_LENGTH ) );
+ TEST_ASSERT_EQUAL( TEST_NAMED_TOPIC_LENGTH_UPDATE_REJECTED, SHADOW_TOPIC_LEN_UPDATE_REJ( TEST_THING_NAME_LENGTH, TEST_SHADOW_NAME_LENGTH ) );
+ TEST_ASSERT_EQUAL( TEST_NAMED_TOPIC_LENGTH_UPDATE_DOCUMENTS, SHADOW_TOPIC_LEN_UPDATE_DOCS( TEST_THING_NAME_LENGTH, TEST_SHADOW_NAME_LENGTH ) );
+ TEST_ASSERT_EQUAL( TEST_NAMED_TOPIC_LENGTH_UPDATE_DELTA, SHADOW_TOPIC_LEN_UPDATE_DELTA( TEST_THING_NAME_LENGTH, TEST_SHADOW_NAME_LENGTH ) );
+ TEST_ASSERT_EQUAL( TEST_NAMED_TOPIC_LENGTH_GET, SHADOW_TOPIC_LEN_GET( TEST_THING_NAME_LENGTH, TEST_SHADOW_NAME_LENGTH ) );
+ TEST_ASSERT_EQUAL( TEST_NAMED_TOPIC_LENGTH_GET_ACCEPTED, SHADOW_TOPIC_LEN_GET_ACC( TEST_THING_NAME_LENGTH, TEST_SHADOW_NAME_LENGTH ) );
+ TEST_ASSERT_EQUAL( TEST_NAMED_TOPIC_LENGTH_GET_REJECTED, SHADOW_TOPIC_LEN_GET_REJ( TEST_THING_NAME_LENGTH, TEST_SHADOW_NAME_LENGTH ) );
+ TEST_ASSERT_EQUAL( TEST_NAMED_TOPIC_LENGTH_DELETE, SHADOW_TOPIC_LEN_DELETE( TEST_THING_NAME_LENGTH, TEST_SHADOW_NAME_LENGTH ) );
+ TEST_ASSERT_EQUAL( TEST_NAMED_TOPIC_LENGTH_DELETE_ACCEPTED, SHADOW_TOPIC_LEN_DELETE_ACC( TEST_THING_NAME_LENGTH, TEST_SHADOW_NAME_LENGTH ) );
+ TEST_ASSERT_EQUAL( TEST_NAMED_TOPIC_LENGTH_DELETE_REJECTED, SHADOW_TOPIC_LEN_DELETE_REJ( TEST_THING_NAME_LENGTH, TEST_SHADOW_NAME_LENGTH ) );
}
/*-----------------------------------------------------------*/
/**
- * @brief Tests the behavior of Shadow_GetTopicString() with valid parameters.
+ * @brief Tests the behavior of Shadow_AssembleTopicString() for Classic shadows,
+ * with valid parameters. Tests Classic shadows through the deprecated legacy API macro
+ * Shadow_GetTopicString(), to verify the legacy macro.
*/
-void test_Shadow_GetTopicString_Happy_Path( void )
+void test_Shadow_AssembleTopicString_Classic_Happy_Path( void )
{
ShadowStatus_t shadowStatus = SHADOW_SUCCESS;
- uint16_t outLength = 0;
- char topicBufferExceeded[ TEST_SHADOW_TOPIC_BUFFER_LENGTH ] = TEST_SHADOW_TOPIC_BUFFER_INITIALZIE;
- uint16_t bufferSizeExceeded = TEST_SHADOW_TOPIC_BUFFER_LENGTH;
+ uint16_t outLength = 0U;
+ char topicBufferExceeded[ TEST_CLASSIC_TOPIC_BUFFER_LENGTH ] = TEST_CLASSIC_TOPIC_BUFFER_INITIALIZE;
+ uint16_t bufferSizeExceeded = TEST_CLASSIC_TOPIC_BUFFER_LENGTH;
char topicBufferGetAccepted[ SHADOW_TOPIC_LENGTH_GET_ACCEPTED( TEST_THING_NAME_LENGTH ) ] = { 0 };
- uint16_t bufferSizeGetAccepted = TEST_SHADOW_TOPIC_LENGTH_GET_ACCEPTED;
+ uint16_t bufferSizeGetAccepted = TEST_CLASSIC_TOPIC_LENGTH_GET_ACCEPTED;
char topicBuffer[ SHADOW_TOPIC_LENGTH_MAX( TEST_THING_NAME_LENGTH ) ] = { 0 };
uint16_t bufferSize = SHADOW_TOPIC_LENGTH_MAX( TEST_THING_NAME_LENGTH );
- uint16_t index = 0;
+ uint16_t index = 0U;
/* Lookup table for Shadow message string. */
static const uint16_t expectedBuffersSize[ ShadowTopicStringTypeMaxNum ] =
{
- TEST_SHADOW_TOPIC_LENGTH_UPDATE,
- TEST_SHADOW_TOPIC_LENGTH_UPDATE_ACCEPTED,
- TEST_SHADOW_TOPIC_LENGTH_UPDATE_REJECTED,
- TEST_SHADOW_TOPIC_LENGTH_UPDATE_DOCUMENTS,
- TEST_SHADOW_TOPIC_LENGTH_UPDATE_DELTA,
- TEST_SHADOW_TOPIC_LENGTH_GET,
- TEST_SHADOW_TOPIC_LENGTH_GET_ACCEPTED,
- TEST_SHADOW_TOPIC_LENGTH_GET_REJECTED,
- TEST_SHADOW_TOPIC_LENGTH_DELETE,
- TEST_SHADOW_TOPIC_LENGTH_DELETE_ACCEPTED,
- TEST_SHADOW_TOPIC_LENGTH_DELETE_REJECTED
+ TEST_CLASSIC_TOPIC_LENGTH_UPDATE,
+ TEST_CLASSIC_TOPIC_LENGTH_UPDATE_ACCEPTED,
+ TEST_CLASSIC_TOPIC_LENGTH_UPDATE_REJECTED,
+ TEST_CLASSIC_TOPIC_LENGTH_UPDATE_DOCUMENTS,
+ TEST_CLASSIC_TOPIC_LENGTH_UPDATE_DELTA,
+ TEST_CLASSIC_TOPIC_LENGTH_GET,
+ TEST_CLASSIC_TOPIC_LENGTH_GET_ACCEPTED,
+ TEST_CLASSIC_TOPIC_LENGTH_GET_REJECTED,
+ TEST_CLASSIC_TOPIC_LENGTH_DELETE,
+ TEST_CLASSIC_TOPIC_LENGTH_DELETE_ACCEPTED,
+ TEST_CLASSIC_TOPIC_LENGTH_DELETE_REJECTED
};
/* Lookup table for Shadow message string. */
static const char * const expectedBuffers[ ShadowTopicStringTypeMaxNum ] =
{
- TEST_SHADOW_TOPIC_STRING_UPDATE,
- TEST_SHADOW_TOPIC_STRING_UPDATE_ACCEPTED,
- TEST_SHADOW_TOPIC_STRING_UPDATE_REJECTED,
- TEST_SHADOW_TOPIC_STRING_UPDATE_DOCUMENTS,
- TEST_SHADOW_TOPIC_STRING_UPDATE_DELTA,
- TEST_SHADOW_TOPIC_STRING_GET,
- TEST_SHADOW_TOPIC_STRING_GET_ACCEPTED,
- TEST_SHADOW_TOPIC_STRING_GET_REJECTED,
- TEST_SHADOW_TOPIC_STRING_DELETE,
- TEST_SHADOW_TOPIC_STRING_DELETE_ACCEPTED,
- TEST_SHADOW_TOPIC_STRING_DELETE_REJECTED
+ TEST_CLASSIC_TOPIC_STRING_UPDATE,
+ TEST_CLASSIC_TOPIC_STRING_UPDATE_ACCEPTED,
+ TEST_CLASSIC_TOPIC_STRING_UPDATE_REJECTED,
+ TEST_CLASSIC_TOPIC_STRING_UPDATE_DOCUMENTS,
+ TEST_CLASSIC_TOPIC_STRING_UPDATE_DELTA,
+ TEST_CLASSIC_TOPIC_STRING_GET,
+ TEST_CLASSIC_TOPIC_STRING_GET_ACCEPTED,
+ TEST_CLASSIC_TOPIC_STRING_GET_REJECTED,
+ TEST_CLASSIC_TOPIC_STRING_DELETE,
+ TEST_CLASSIC_TOPIC_STRING_DELETE_ACCEPTED,
+ TEST_CLASSIC_TOPIC_STRING_DELETE_REJECTED
};
static const ShadowTopicStringType_t topicTypes[ ShadowTopicStringTypeMaxNum ] =
@@ -372,9 +637,9 @@ void test_Shadow_GetTopicString_Happy_Path( void )
bufferSizeExceeded,
&outLength );
TEST_ASSERT_EQUAL_INT( SHADOW_SUCCESS, shadowStatus );
- TEST_ASSERT_EQUAL_INT( TEST_SHADOW_TOPIC_LENGTH_GET_ACCEPTED, outLength );
+ TEST_ASSERT_EQUAL_INT( TEST_CLASSIC_TOPIC_LENGTH_GET_ACCEPTED, outLength );
TEST_ASSERT_LESS_THAN( bufferSizeExceeded, outLength );
- TEST_ASSERT_EQUAL_STRING_LEN( TEST_SHADOW_TOPIC_BUFFER_MODIFIED,
+ TEST_ASSERT_EQUAL_STRING_LEN( TEST_CLASSIC_TOPIC_BUFFER_MODIFIED,
topicBufferExceeded,
bufferSizeExceeded );
@@ -386,12 +651,12 @@ void test_Shadow_GetTopicString_Happy_Path( void )
&( topicBufferGetAccepted[ 0 ] ),
bufferSizeGetAccepted,
&outLength );
- TEST_ASSERT_EQUAL_INT( TEST_SHADOW_TOPIC_LENGTH_GET_ACCEPTED, outLength );
- TEST_ASSERT_EQUAL_STRING_LEN( TEST_SHADOW_TOPIC_STRING_GET_ACCEPTED,
+ TEST_ASSERT_EQUAL_INT( TEST_CLASSIC_TOPIC_LENGTH_GET_ACCEPTED, outLength );
+ TEST_ASSERT_EQUAL_STRING_LEN( TEST_CLASSIC_TOPIC_STRING_GET_ACCEPTED,
topicBufferGetAccepted,
bufferSizeGetAccepted );
- for( index = 0; index < ShadowTopicStringTypeMaxNum; index++ )
+ for( index = 0U; index < ShadowTopicStringTypeMaxNum; index++ )
{
/* Call Shadow_GetTopicString() with valid parameters with all types of topic string
* and verify result. */
@@ -408,92 +673,241 @@ void test_Shadow_GetTopicString_Happy_Path( void )
}
}
+/**
+ * @brief Tests the behavior of Shadow_AssembleTopicString() for named shadows, with valid parameters.
+ */
+void test_Shadow_AssembleTopicString_Named_Happy_Path( void )
+{
+ ShadowStatus_t shadowStatus = SHADOW_SUCCESS;
+ uint16_t outLength = 0U;
+ char topicBufferExceeded[ TEST_NAMED_TOPIC_BUFFER_LENGTH ] = TEST_NAMED_TOPIC_BUFFER_INITIALIZE;
+ uint16_t bufferSizeExceeded = TEST_NAMED_TOPIC_BUFFER_LENGTH;
+ char topicBufferGetAccepted[ SHADOW_TOPIC_LEN_GET_ACC( TEST_THING_NAME_LENGTH, TEST_SHADOW_NAME_LENGTH ) ] = { 0 };
+ uint16_t bufferSizeGetAccepted = TEST_NAMED_TOPIC_LENGTH_GET_ACCEPTED;
+ char topicBuffer[ SHADOW_TOPIC_LEN_MAX( TEST_THING_NAME_LENGTH, TEST_SHADOW_NAME_LENGTH ) ] = { 0 };
+ uint16_t bufferSize = SHADOW_TOPIC_LEN_MAX( TEST_THING_NAME_LENGTH, TEST_SHADOW_NAME_LENGTH );
+ uint16_t index = 0U;
+
+ /* Lookup table for Shadow message string. */
+ static const uint16_t expectedBuffersSize[ ShadowTopicStringTypeMaxNum ] =
+ {
+ TEST_NAMED_TOPIC_LENGTH_UPDATE,
+ TEST_NAMED_TOPIC_LENGTH_UPDATE_ACCEPTED,
+ TEST_NAMED_TOPIC_LENGTH_UPDATE_REJECTED,
+ TEST_NAMED_TOPIC_LENGTH_UPDATE_DOCUMENTS,
+ TEST_NAMED_TOPIC_LENGTH_UPDATE_DELTA,
+ TEST_NAMED_TOPIC_LENGTH_GET,
+ TEST_NAMED_TOPIC_LENGTH_GET_ACCEPTED,
+ TEST_NAMED_TOPIC_LENGTH_GET_REJECTED,
+ TEST_NAMED_TOPIC_LENGTH_DELETE,
+ TEST_NAMED_TOPIC_LENGTH_DELETE_ACCEPTED,
+ TEST_NAMED_TOPIC_LENGTH_DELETE_REJECTED
+ };
+
+ /* Lookup table for Shadow message string. */
+ static const char * const expectedBuffers[ ShadowTopicStringTypeMaxNum ] =
+ {
+ TEST_NAMED_TOPIC_STRING_UPDATE,
+ TEST_NAMED_TOPIC_STRING_UPDATE_ACCEPTED,
+ TEST_NAMED_TOPIC_STRING_UPDATE_REJECTED,
+ TEST_NAMED_TOPIC_STRING_UPDATE_DOCUMENTS,
+ TEST_NAMED_TOPIC_STRING_UPDATE_DELTA,
+ TEST_NAMED_TOPIC_STRING_GET,
+ TEST_NAMED_TOPIC_STRING_GET_ACCEPTED,
+ TEST_NAMED_TOPIC_STRING_GET_REJECTED,
+ TEST_NAMED_TOPIC_STRING_DELETE,
+ TEST_NAMED_TOPIC_STRING_DELETE_ACCEPTED,
+ TEST_NAMED_TOPIC_STRING_DELETE_REJECTED
+ };
+
+ static const ShadowTopicStringType_t topicTypes[ ShadowTopicStringTypeMaxNum ] =
+ {
+ ShadowTopicStringTypeUpdate,
+ ShadowTopicStringTypeUpdateAccepted,
+ ShadowTopicStringTypeUpdateRejected,
+ ShadowTopicStringTypeUpdateDocuments,
+ ShadowTopicStringTypeUpdateDelta,
+ ShadowTopicStringTypeGet,
+ ShadowTopicStringTypeGetAccepted,
+ ShadowTopicStringTypeGetRejected,
+ ShadowTopicStringTypeDelete,
+ ShadowTopicStringTypeDeleteAccepted,
+ ShadowTopicStringTypeDeleteRejected
+ };
+
+ /* Call Shadow_AssembleTopicString() with valid parameters but bufferSize exceeds topic string length
+ * and verify result. */
+ shadowStatus = Shadow_AssembleTopicString( ShadowTopicStringTypeGetAccepted,
+ TEST_THING_NAME,
+ TEST_THING_NAME_LENGTH,
+ TEST_SHADOW_NAME,
+ TEST_SHADOW_NAME_LENGTH,
+ &( topicBufferExceeded[ 0 ] ),
+ bufferSizeExceeded,
+ &outLength );
+ TEST_ASSERT_EQUAL_INT( SHADOW_SUCCESS, shadowStatus );
+ TEST_ASSERT_EQUAL_INT( TEST_NAMED_TOPIC_LENGTH_GET_ACCEPTED, outLength );
+ TEST_ASSERT_LESS_THAN( bufferSizeExceeded, outLength );
+ TEST_ASSERT_EQUAL_STRING_LEN( TEST_NAMED_TOPIC_BUFFER_MODIFIED,
+ topicBufferExceeded,
+ bufferSizeExceeded );
+
+ /* Call Shadow_AssembleTopicString() with valid parameters, bufferSize = expected outLength
+ * and verify result. */
+ shadowStatus = Shadow_AssembleTopicString( ShadowTopicStringTypeGetAccepted,
+ TEST_THING_NAME,
+ TEST_THING_NAME_LENGTH,
+ TEST_SHADOW_NAME,
+ TEST_SHADOW_NAME_LENGTH,
+ &( topicBufferGetAccepted[ 0 ] ),
+ bufferSizeGetAccepted,
+ &outLength );
+ TEST_ASSERT_EQUAL_INT( TEST_NAMED_TOPIC_LENGTH_GET_ACCEPTED, outLength );
+ TEST_ASSERT_EQUAL_STRING_LEN( TEST_NAMED_TOPIC_STRING_GET_ACCEPTED,
+ topicBufferGetAccepted,
+ bufferSizeGetAccepted );
+
+ for( index = 0U; index < ShadowTopicStringTypeMaxNum; index++ )
+ {
+ /* Call Shadow_AssembleTopicString() with valid parameters with all types of topic string
+ * and verify result. */
+ shadowStatus = Shadow_AssembleTopicString( topicTypes[ index ],
+ TEST_THING_NAME,
+ TEST_THING_NAME_LENGTH,
+ TEST_SHADOW_NAME,
+ TEST_SHADOW_NAME_LENGTH,
+ &( topicBuffer[ 0 ] ),
+ bufferSize,
+ &outLength );
+ TEST_ASSERT_EQUAL_INT( expectedBuffersSize[ index ], outLength );
+ TEST_ASSERT_EQUAL_STRING_LEN( expectedBuffers[ index ],
+ topicBuffer,
+ outLength );
+ }
+}
+
/*-----------------------------------------------------------*/
/**
- * @brief Tests the behavior of Shadow_GetTopicString() with invalid parameters.
+ * @brief Tests the behavior of Shadow_AssembleTopicString() with invalid parameters
*/
-void test_Shadow_GetTopicString_Invalid_Parameters( void )
+void test_Shadow_AssembleTopicString_Invalid_Parameters( void )
{
ShadowStatus_t shadowStatus = SHADOW_SUCCESS;
- uint16_t outLength = 0;
+ uint16_t outLength = 0U;
ShadowTopicStringType_t topicType = ShadowTopicStringTypeGetAccepted;
- char topicBuffer[ TEST_SHADOW_TOPIC_BUFFER_LENGTH ] = TEST_SHADOW_TOPIC_BUFFER_INITIALZIE;
- uint16_t bufferSize = TEST_SHADOW_TOPIC_BUFFER_LENGTH;
+ char classicTopicBuffer[ TEST_CLASSIC_TOPIC_LENGTH_GET_ACCEPTED ];
+ uint16_t classicBufferSize = TEST_CLASSIC_TOPIC_LENGTH_GET_ACCEPTED;
+ char namedTopicBuffer[ TEST_NAMED_TOPIC_LENGTH_GET_ACCEPTED ];
+ uint16_t namedBufferSize = TEST_NAMED_TOPIC_LENGTH_GET_ACCEPTED;
- /* Call Shadow_GetTopicString() with various combinations of
+ /* Call Shadow_AssembleTopicString() with various combinations of
* incorrect parameters. */
- shadowStatus = Shadow_GetTopicString( 0,
- "",
- 0,
- &( topicBuffer[ 0 ] ),
- bufferSize,
- &outLength );
+ shadowStatus = Shadow_AssembleTopicString( 0,
+ "",
+ 0,
+ SHADOW_NAME_CLASSIC,
+ 0,
+ classicTopicBuffer,
+ classicBufferSize,
+ &outLength );
TEST_ASSERT_EQUAL_INT( SHADOW_BAD_PARAMETER, shadowStatus );
- shadowStatus = Shadow_GetTopicString( 0,
- NULL,
- 0,
- &( topicBuffer[ 0 ] ),
- bufferSize,
- &outLength );
+ shadowStatus = Shadow_AssembleTopicString( 0,
+ NULL,
+ 0,
+ SHADOW_NAME_CLASSIC,
+ 0,
+ classicTopicBuffer,
+ classicBufferSize,
+ &outLength );
TEST_ASSERT_EQUAL_INT( SHADOW_BAD_PARAMETER, shadowStatus );
- shadowStatus = Shadow_GetTopicString( topicType,
- TEST_THING_NAME,
- TEST_THING_NAME_LENGTH,
- NULL,
- 0,
- &outLength );
+ shadowStatus = Shadow_AssembleTopicString( topicType,
+ TEST_THING_NAME,
+ TEST_THING_NAME_LENGTH,
+ SHADOW_NAME_CLASSIC,
+ 0,
+ NULL,
+ 0,
+ &outLength );
TEST_ASSERT_EQUAL_INT( SHADOW_BAD_PARAMETER, shadowStatus );
+ shadowStatus = Shadow_AssembleTopicString( ShadowTopicStringTypeMaxNum + 1,
+ TEST_THING_NAME,
+ TEST_THING_NAME_LENGTH,
+ SHADOW_NAME_CLASSIC,
+ 0,
+ classicTopicBuffer,
+ classicBufferSize,
+ &outLength );
+ TEST_ASSERT_EQUAL_INT( SHADOW_BAD_PARAMETER, shadowStatus );
- shadowStatus = Shadow_GetTopicString( ShadowTopicStringTypeMaxNum + 1,
- TEST_THING_NAME,
- TEST_THING_NAME_LENGTH,
- &( topicBuffer[ 0 ] ),
- bufferSize,
- &outLength );
+ shadowStatus = Shadow_AssembleTopicString( topicType,
+ TEST_THING_NAME,
+ TEST_THING_NAME_LENGTH,
+ SHADOW_NAME_CLASSIC,
+ 0,
+ classicTopicBuffer,
+ classicBufferSize,
+ NULL );
TEST_ASSERT_EQUAL_INT( SHADOW_BAD_PARAMETER, shadowStatus );
- shadowStatus = Shadow_GetTopicString( topicType,
- TEST_THING_NAME,
- TEST_THING_NAME_LENGTH,
- &( topicBuffer[ 0 ] ),
- bufferSize,
- NULL );
+ shadowStatus = Shadow_AssembleTopicString( topicType,
+ TEST_THING_NAME,
+ TEST_THING_NAME_LENGTH,
+ NULL,
+ 1,
+ namedTopicBuffer,
+ namedBufferSize,
+ &outLength );
TEST_ASSERT_EQUAL_INT( SHADOW_BAD_PARAMETER, shadowStatus );
- shadowStatus = Shadow_GetTopicString( topicType,
- TEST_THING_NAME,
- TEST_THING_NAME_LENGTH,
- &( topicBuffer[ 0 ] ),
- 0,
- &outLength );
+ shadowStatus = Shadow_AssembleTopicString( topicType,
+ TEST_THING_NAME,
+ TEST_THING_NAME_LENGTH,
+ SHADOW_NAME_CLASSIC,
+ 0,
+ classicTopicBuffer,
+ 0,
+ &outLength );
TEST_ASSERT_EQUAL_INT( SHADOW_BUFFER_TOO_SMALL, shadowStatus );
- shadowStatus = Shadow_GetTopicString( topicType,
- TEST_THING_NAME,
- TEST_THING_NAME_LENGTH,
- &( topicBuffer[ 0 ] ),
- ( bufferSize / 2 ),
- &outLength );
+ shadowStatus = Shadow_AssembleTopicString( topicType,
+ TEST_THING_NAME,
+ TEST_THING_NAME_LENGTH,
+ SHADOW_NAME_CLASSIC,
+ 0,
+ classicTopicBuffer,
+ ( classicBufferSize - 1 ),
+ &outLength );
+ TEST_ASSERT_EQUAL_INT( SHADOW_BUFFER_TOO_SMALL, shadowStatus );
+
+ shadowStatus = Shadow_AssembleTopicString( topicType,
+ TEST_THING_NAME,
+ TEST_THING_NAME_LENGTH,
+ TEST_SHADOW_NAME,
+ TEST_SHADOW_NAME_LENGTH,
+ namedTopicBuffer,
+ ( namedBufferSize - 1 ),
+ &outLength );
TEST_ASSERT_EQUAL_INT( SHADOW_BUFFER_TOO_SMALL, shadowStatus );
}
/*-----------------------------------------------------------*/
/**
- * @brief Tests the behavior of Shadow_MatchTopic() with valid parameters.
+ * @brief Tests the behavior of Shadow_MatchTopicString() for classic shadow with valid parameters. Tests Classic
+ * shadows through the deprecated legacy API macro Shadow_MatchTopic(), to verify the legacy macros.
*/
-void test_Shadow_MatchTopic_Happy_Path( void )
+void test_Shadow_MatchTopicString_Classic_Happy_Path( void )
{
ShadowStatus_t shadowStatus = SHADOW_SUCCESS;
ShadowMessageType_t messageType = ShadowMessageTypeMaxNum;
const char * pThingName = NULL;
- uint16_t thingNameLength = 0;
- const char topicBuffer[ TEST_SHADOW_TOPIC_LENGTH_UPDATE_ACCEPTED ] = TEST_SHADOW_TOPIC_STRING_UPDATE_ACCEPTED;
- uint16_t bufferSize = TEST_SHADOW_TOPIC_LENGTH_UPDATE_ACCEPTED;
+ uint16_t thingNameLength = 0U;
+ const char topicBuffer[ TEST_CLASSIC_TOPIC_LENGTH_UPDATE_ACCEPTED ] = TEST_CLASSIC_TOPIC_STRING_UPDATE_ACCEPTED;
+ uint16_t bufferSize = TEST_CLASSIC_TOPIC_LENGTH_UPDATE_ACCEPTED;
/* Call Shadow_MatchTopic() with valid parameters and verify result. */
shadowStatus = Shadow_MatchTopic( &( topicBuffer[ 0 ] ),
@@ -534,100 +948,293 @@ void test_Shadow_MatchTopic_Happy_Path( void )
TEST_ASSERT_EQUAL_INT( ShadowMessageTypeUpdateAccepted, messageType );
}
+/**
+ * @brief Tests the behavior of Shadow_MatchTopicString() for named shadows with valid parameters.
+ */
+void test_Shadow_MatchTopicString_Named_Happy_Path( void )
+{
+ ShadowStatus_t shadowStatus = SHADOW_SUCCESS;
+ ShadowMessageType_t messageType = ShadowMessageTypeMaxNum;
+ const char * pThingName = NULL;
+ uint16_t thingNameLength = 0U;
+ const char * pShadowName = NULL;
+ uint16_t shadowNameLength = 0U;
+ const char topicBuffer[ TEST_NAMED_TOPIC_LENGTH_UPDATE_ACCEPTED ] = TEST_NAMED_TOPIC_STRING_UPDATE_ACCEPTED;
+ uint16_t bufferSize = TEST_NAMED_TOPIC_LENGTH_UPDATE_ACCEPTED;
+
+ /* Call Shadow_MatchTopicString() with valid parameters and verify result. */
+ shadowStatus = Shadow_MatchTopicString( &( topicBuffer[ 0 ] ),
+ bufferSize,
+ &messageType,
+ &pThingName,
+ &thingNameLength,
+ &pShadowName,
+ &shadowNameLength );
+
+ TEST_ASSERT_EQUAL_INT( SHADOW_SUCCESS, shadowStatus );
+ TEST_ASSERT_EQUAL_INT( TEST_THING_NAME_LENGTH, thingNameLength );
+ TEST_ASSERT_EQUAL_INT( ShadowMessageTypeUpdateAccepted, messageType );
+ TEST_ASSERT_EQUAL_STRING_LEN( TEST_THING_NAME, pThingName, TEST_THING_NAME_LENGTH );
+ TEST_ASSERT_EQUAL_INT( TEST_SHADOW_NAME_LENGTH, shadowNameLength );
+ TEST_ASSERT_EQUAL_STRING_LEN( TEST_SHADOW_NAME, pShadowName, TEST_SHADOW_NAME_LENGTH );
+
+ shadowStatus = Shadow_MatchTopicString( &( topicBuffer[ 0 ] ),
+ bufferSize,
+ &messageType,
+ &pThingName,
+ &thingNameLength,
+ NULL,
+ &shadowNameLength );
+ TEST_ASSERT_EQUAL_INT( SHADOW_SUCCESS, shadowStatus );
+ TEST_ASSERT_EQUAL_INT( TEST_THING_NAME_LENGTH, thingNameLength );
+ TEST_ASSERT_EQUAL_INT( ShadowMessageTypeUpdateAccepted, messageType );
+ TEST_ASSERT_EQUAL_STRING_LEN( TEST_THING_NAME, pThingName, TEST_THING_NAME_LENGTH );
+ TEST_ASSERT_EQUAL_INT( TEST_SHADOW_NAME_LENGTH, shadowNameLength );
+
+ shadowStatus = Shadow_MatchTopicString( &( topicBuffer[ 0 ] ),
+ bufferSize,
+ &messageType,
+ &pThingName,
+ &thingNameLength,
+ &pShadowName,
+ NULL );
+ TEST_ASSERT_EQUAL_INT( SHADOW_SUCCESS, shadowStatus );
+ TEST_ASSERT_EQUAL_INT( TEST_THING_NAME_LENGTH, thingNameLength );
+ TEST_ASSERT_EQUAL_INT( ShadowMessageTypeUpdateAccepted, messageType );
+ TEST_ASSERT_EQUAL_STRING_LEN( TEST_THING_NAME, pThingName, TEST_THING_NAME_LENGTH );
+ TEST_ASSERT_EQUAL_STRING_LEN( TEST_SHADOW_NAME, pShadowName, TEST_SHADOW_NAME_LENGTH );
+
+ shadowStatus = Shadow_MatchTopicString( &( topicBuffer[ 0 ] ),
+ bufferSize,
+ &messageType,
+ &pThingName,
+ &thingNameLength,
+ NULL,
+ NULL );
+ TEST_ASSERT_EQUAL_INT( SHADOW_SUCCESS, shadowStatus );
+ TEST_ASSERT_EQUAL_INT( TEST_THING_NAME_LENGTH, thingNameLength );
+ TEST_ASSERT_EQUAL_INT( ShadowMessageTypeUpdateAccepted, messageType );
+ TEST_ASSERT_EQUAL_STRING_LEN( TEST_THING_NAME, pThingName, TEST_THING_NAME_LENGTH );
+}
+
/*-----------------------------------------------------------*/
/**
- * @brief Tests the behavior of Shadow_MatchTopic() with various
- * invalid parameters.
+ * @brief Tests the behavior of Shadow_MatchTopicString() with various
+ * invalid parameters
*/
-void test_Shadow_MatchTopic_Invalid_Parameters( void )
+void test_Shadow_MatchTopicString_Invalid_Parameters( void )
{
ShadowStatus_t shadowStatus = SHADOW_SUCCESS;
ShadowMessageType_t messageType = ShadowMessageTypeMaxNum;
const char * pThingName = NULL;
- uint16_t thingNameLength = 0;
- const char topicBuffer[ TEST_SHADOW_TOPIC_LENGTH_UPDATE_ACCEPTED ] = TEST_SHADOW_TOPIC_STRING_UPDATE_ACCEPTED;
- uint16_t bufferSize = TEST_SHADOW_TOPIC_LENGTH_UPDATE_ACCEPTED;
-
- /* Call Shadow_MatchTopic() with various combinations of
+ uint16_t thingNameLength = 0U;
+ const char * pShadowName = NULL;
+ uint16_t shadowNameLength = 0U;
+ const char classicTopicBuffer[ TEST_CLASSIC_TOPIC_LENGTH_UPDATE_ACCEPTED ] = TEST_CLASSIC_TOPIC_STRING_UPDATE_ACCEPTED;
+ uint16_t classicBufferSize = TEST_CLASSIC_TOPIC_LENGTH_UPDATE_ACCEPTED;
+ const char namedTopicBuffer[ TEST_NAMED_TOPIC_LENGTH_UPDATE_ACCEPTED ] = TEST_NAMED_TOPIC_STRING_UPDATE_ACCEPTED;
+ uint16_t namedBufferSize = TEST_NAMED_TOPIC_LENGTH_UPDATE_ACCEPTED;
+
+ /* Call Shadow_MatchTopicString() with various combinations of
* incorrect parameters. */
- shadowStatus = Shadow_MatchTopic( NULL,
- bufferSize,
- &messageType,
- &pThingName,
- &thingNameLength );
+ shadowStatus = Shadow_MatchTopicString( NULL,
+ classicBufferSize,
+ &messageType,
+ &pThingName,
+ &thingNameLength,
+ &pShadowName,
+ &shadowNameLength );
TEST_ASSERT_EQUAL_INT( SHADOW_BAD_PARAMETER, shadowStatus );
- shadowStatus = Shadow_MatchTopic( &( topicBuffer[ 0 ] ),
- 0,
- &messageType,
- &pThingName,
- &thingNameLength );
+ shadowStatus = Shadow_MatchTopicString( classicTopicBuffer,
+ 0,
+ &messageType,
+ &pThingName,
+ &thingNameLength,
+ &pShadowName,
+ &shadowNameLength );
TEST_ASSERT_EQUAL_INT( SHADOW_BAD_PARAMETER, shadowStatus );
- shadowStatus = Shadow_MatchTopic( &( topicBuffer[ 0 ] ),
- bufferSize,
- NULL,
- &pThingName,
- &thingNameLength );
-
+ shadowStatus = Shadow_MatchTopicString( classicTopicBuffer,
+ classicBufferSize,
+ NULL,
+ &pThingName,
+ &thingNameLength,
+ &pShadowName,
+ &shadowNameLength );
TEST_ASSERT_EQUAL_INT( SHADOW_BAD_PARAMETER, shadowStatus );
- shadowStatus = Shadow_MatchTopic( TEST_SHADOW_TOPIC_STRING_INVALID_PREFIX,
- TEST_SHADOW_TOPIC_LENGTH_INVALID_PREFIX,
- &messageType,
- &pThingName,
- &thingNameLength );
+ shadowStatus = Shadow_MatchTopicString( TEST_TOPIC_STRING_INVALID_PREFIX,
+ TEST_TOPIC_LENGTH_INVALID_PREFIX,
+ &messageType,
+ &pThingName,
+ &thingNameLength,
+ &pShadowName,
+ &shadowNameLength );
TEST_ASSERT_EQUAL_INT( SHADOW_FAIL, shadowStatus );
- shadowStatus = Shadow_MatchTopic( TEST_SHADOW_TOPIC_STRING_EMPTY_THINGNAME,
- TEST_SHADOW_TOPIC_LENGTH_EMPTY_THINGNAME,
- &messageType,
- &pThingName,
- &thingNameLength );
+ shadowStatus = Shadow_MatchTopicString( TEST_TOPIC_STRING_EMPTY_THINGNAME,
+ TEST_TOPIC_LENGTH_EMPTY_THINGNAME,
+ &messageType,
+ &pThingName,
+ &thingNameLength,
+ &pShadowName,
+ &shadowNameLength );
TEST_ASSERT_EQUAL_INT( SHADOW_THINGNAME_PARSE_FAILED, shadowStatus );
- shadowStatus = Shadow_MatchTopic( TEST_SHADOW_TOPIC_STRING_INVALID_THINGNAME,
- TEST_SHADOW_TOPIC_LENGTH_INVALID_THINGNAME,
- &messageType,
- &pThingName,
- &thingNameLength );
+ shadowStatus = Shadow_MatchTopicString( TEST_TOPIC_STRING_INVALID_THINGNAME,
+ TEST_TOPIC_LENGTH_INVALID_THINGNAME,
+ &messageType,
+ &pThingName,
+ &thingNameLength,
+ &pShadowName,
+ &shadowNameLength );
TEST_ASSERT_EQUAL_INT( SHADOW_THINGNAME_PARSE_FAILED, shadowStatus );
- shadowStatus = Shadow_MatchTopic( TEST_SHADOW_TOPIC_STRING_EMPTY_SHADOW_MESSAGE_TYPE,
- TEST_SHADOW_TOPIC_LENGTH_EMPTY_SHADOW_MESSAGE_TYPE,
- &messageType,
- &pThingName,
- &thingNameLength );
- TEST_ASSERT_EQUAL_INT( SHADOW_SHADOW_MESSAGE_TYPE_PARSE_FAILED, shadowStatus );
-
- shadowStatus = Shadow_MatchTopic( TEST_SHADOW_TOPIC_STRING_INVALID_SHADOW_RESPONSE,
- TEST_SHADOW_TOPIC_LENGTH_INVALID_SHADOW_RESPONSE,
- &messageType,
- &pThingName,
- &thingNameLength );
- TEST_ASSERT_EQUAL_INT( SHADOW_FAIL, shadowStatus );
-
- shadowStatus = Shadow_MatchTopic( TEST_SHADOW_TOPIC_STRING_INVALID_GET_REJECTED,
- TEST_SHADOW_TOPIC_LENGTH_INVALID_GET_REJECTED,
- &messageType,
- &pThingName,
- &thingNameLength );
- TEST_ASSERT_EQUAL_INT( SHADOW_FAIL, shadowStatus );
-
- shadowStatus = Shadow_MatchTopic( &( topicBuffer[ 0 ] ),
- bufferSize / 2,
- &messageType,
- &pThingName,
- &thingNameLength );
- TEST_ASSERT_EQUAL_INT( SHADOW_SHADOW_MESSAGE_TYPE_PARSE_FAILED, shadowStatus );
+ shadowStatus = Shadow_MatchTopicString( TEST_TOPIC_STRING_UNTERMINATED_THINGNAME,
+ TEST_TOPIC_LENGTH_UNTERMINATED_THINGNAME,
+ &messageType,
+ &pThingName,
+ &thingNameLength,
+ &pShadowName,
+ &shadowNameLength );
+ TEST_ASSERT_EQUAL_INT( SHADOW_THINGNAME_PARSE_FAILED, shadowStatus );
- shadowStatus = Shadow_MatchTopic( &( topicBuffer[ 0 ] ),
- bufferSize * 2,
- &messageType,
- &pThingName,
- &thingNameLength );
- TEST_ASSERT_EQUAL_INT( SHADOW_FAIL, shadowStatus );
+ shadowStatus = Shadow_MatchTopicString( TEST_TOPIC_STRING_EMPTY_SHADOW_ROOT,
+ TEST_TOPIC_LENGTH_EMPTY_SHADOW_ROOT,
+ &messageType,
+ &pThingName,
+ &thingNameLength,
+ &pShadowName,
+ &shadowNameLength );
+ TEST_ASSERT_EQUAL_INT( SHADOW_ROOT_PARSE_FAILED, shadowStatus );
+
+ shadowStatus = Shadow_MatchTopicString( TEST_TOPIC_STRING_INVALID_SHADOW_ROOT,
+ TEST_TOPIC_LENGTH_INVALID_SHADOW_ROOT,
+ &messageType,
+ &pThingName,
+ &thingNameLength,
+ &pShadowName,
+ &shadowNameLength );
+ TEST_ASSERT_EQUAL_INT( SHADOW_ROOT_PARSE_FAILED, shadowStatus );
+
+ shadowStatus = Shadow_MatchTopicString( TEST_NAMED_TOPIC_STRING_EMPTY_SHADOWNAME,
+ TEST_NAMED_TOPIC_LENGTH_EMPTY_SHADOWNAME,
+ &messageType,
+ &pThingName,
+ &thingNameLength,
+ &pShadowName,
+ &shadowNameLength );
+ TEST_ASSERT_EQUAL_INT( SHADOW_SHADOWNAME_PARSE_FAILED, shadowStatus );
+
+ shadowStatus = Shadow_MatchTopicString( TEST_NAMED_TOPIC_STRING_INVALID_SHADOWNAME,
+ TEST_NAMED_TOPIC_LENGTH_INVALID_SHADOWNAME,
+ &messageType,
+ &pThingName,
+ &thingNameLength,
+ &pShadowName,
+ &shadowNameLength );
+ TEST_ASSERT_EQUAL_INT( SHADOW_SHADOWNAME_PARSE_FAILED, shadowStatus );
+
+ shadowStatus = Shadow_MatchTopicString( TEST_NAMED_TOPIC_STRING_UNTERMINATED_SHADOWNAME,
+ TEST_NAMED_TOPIC_LENGTH_UNTERMINATED_SHADOWNAME,
+ &messageType,
+ &pThingName,
+ &thingNameLength,
+ &pShadowName,
+ &shadowNameLength );
+ TEST_ASSERT_EQUAL_INT( SHADOW_SHADOWNAME_PARSE_FAILED, shadowStatus );
+
+ shadowStatus = Shadow_MatchTopicString( TEST_CLASSIC_TOPIC_STRING_EMPTY_SHADOW_MESSAGE_TYPE,
+ TEST_CLASSIC_TOPIC_LENGTH_EMPTY_SHADOW_MESSAGE_TYPE,
+ &messageType,
+ &pThingName,
+ &thingNameLength,
+ &pShadowName,
+ &shadowNameLength );
+ TEST_ASSERT_EQUAL_INT( SHADOW_MESSAGE_TYPE_PARSE_FAILED, shadowStatus );
+
+ shadowStatus = Shadow_MatchTopicString( TEST_NAMED_TOPIC_STRING_EMPTY_SHADOW_MESSAGE_TYPE,
+ TEST_NAMED_TOPIC_LENGTH_EMPTY_SHADOW_MESSAGE_TYPE,
+ &messageType,
+ &pThingName,
+ &thingNameLength,
+ &pShadowName,
+ &shadowNameLength );
+ TEST_ASSERT_EQUAL_INT( SHADOW_MESSAGE_TYPE_PARSE_FAILED, shadowStatus );
+
+ shadowStatus = Shadow_MatchTopicString( TEST_CLASSIC_TOPIC_STRING_INVALID_SHADOW_RESPONSE,
+ TEST_CLASSIC_TOPIC_LENGTH_INVALID_SHADOW_RESPONSE,
+ &messageType,
+ &pThingName,
+ &thingNameLength,
+ &pShadowName,
+ &shadowNameLength );
+ TEST_ASSERT_EQUAL_INT( SHADOW_MESSAGE_TYPE_PARSE_FAILED, shadowStatus );
+
+ shadowStatus = Shadow_MatchTopicString( TEST_NAMED_TOPIC_STRING_INVALID_SHADOW_RESPONSE,
+ TEST_NAMED_TOPIC_LENGTH_INVALID_SHADOW_RESPONSE,
+ &messageType,
+ &pThingName,
+ &thingNameLength,
+ &pShadowName,
+ &shadowNameLength );
+ TEST_ASSERT_EQUAL_INT( SHADOW_MESSAGE_TYPE_PARSE_FAILED, shadowStatus );
+
+ shadowStatus = Shadow_MatchTopicString( TEST_CLASSIC_TOPIC_STRING_INVALID_GET_REJECTED,
+ TEST_CLASSIC_TOPIC_LENGTH_INVALID_GET_REJECTED,
+ &messageType,
+ &pThingName,
+ &thingNameLength,
+ &pShadowName,
+ &shadowNameLength );
+ TEST_ASSERT_EQUAL_INT( SHADOW_MESSAGE_TYPE_PARSE_FAILED, shadowStatus );
+
+ shadowStatus = Shadow_MatchTopicString( TEST_NAMED_TOPIC_STRING_INVALID_GET_REJECTED,
+ TEST_NAMED_TOPIC_LENGTH_INVALID_GET_REJECTED,
+ &messageType,
+ &pThingName,
+ &thingNameLength,
+ &pShadowName,
+ &shadowNameLength );
+ TEST_ASSERT_EQUAL_INT( SHADOW_MESSAGE_TYPE_PARSE_FAILED, shadowStatus );
+
+ shadowStatus = Shadow_MatchTopicString( classicTopicBuffer,
+ classicBufferSize - 1,
+ &messageType,
+ &pThingName,
+ &thingNameLength,
+ &pShadowName,
+ &shadowNameLength );
+ TEST_ASSERT_EQUAL_INT( SHADOW_MESSAGE_TYPE_PARSE_FAILED, shadowStatus );
+
+ shadowStatus = Shadow_MatchTopicString( namedTopicBuffer,
+ namedBufferSize - 1,
+ &messageType,
+ &pThingName,
+ &thingNameLength,
+ &pShadowName,
+ &shadowNameLength );
+ TEST_ASSERT_EQUAL_INT( SHADOW_MESSAGE_TYPE_PARSE_FAILED, shadowStatus );
+
+ shadowStatus = Shadow_MatchTopicString( classicTopicBuffer,
+ classicBufferSize + 1,
+ &messageType,
+ &pThingName,
+ &thingNameLength,
+ &pShadowName,
+ &shadowNameLength );
+ TEST_ASSERT_EQUAL_INT( SHADOW_MESSAGE_TYPE_PARSE_FAILED, shadowStatus );
+
+ shadowStatus = Shadow_MatchTopicString( namedTopicBuffer,
+ namedBufferSize + 1,
+ &messageType,
+ &pThingName,
+ &thingNameLength,
+ &pShadowName,
+ &shadowNameLength );
+ TEST_ASSERT_EQUAL_INT( SHADOW_MESSAGE_TYPE_PARSE_FAILED, shadowStatus );
}
/*-----------------------------------------------------------*/