diff --git a/docs/doxygen/include/size_table.md b/docs/doxygen/include/size_table.md
index 67eb14c..04fbe51 100644
--- a/docs/doxygen/include/size_table.md
+++ b/docs/doxygen/include/size_table.md
@@ -9,8 +9,8 @@
jobs.c |
- 2.8K |
- 2.5K |
+ 2.9K |
+ 2.7K |
job_parser.c |
@@ -29,7 +29,7 @@
Total estimates |
- 6.8K |
- 6.0K |
+ 6.9K |
+ 6.2K |
diff --git a/source/include/jobs.h b/source/include/jobs.h
index adeb223..5fbb292 100644
--- a/source/include/jobs.h
+++ b/source/include/jobs.h
@@ -150,6 +150,9 @@
#define JOBS_API_EXPECTED_VERSION "\",\"expectedVersion\":\""
#define JOBS_API_EXPECTED_VERSION_LENGTH ( sizeof( JOBS_API_EXPECTED_VERSION ) - 1U )
+#define JOBS_API_STATUS_DETAILS "\",\"statusDetails\":\""
+#define JOBS_API_STATUS_DETAILS_LENGTH ( sizeof( JOBS_API_STATUS_DETAILS ) - 1U )
+
#define JOBS_API_COMMON_LENGTH( thingNameLength ) \
( JOBS_API_PREFIX_LENGTH + ( thingNameLength ) + JOBS_API_BRIDGE_LENGTH )
@@ -314,6 +317,32 @@ typedef enum
JobsMaxTopic
} JobsTopic_t;
+/**
+ * @ingroup jobs_struct_types
+ * @brief Structure for Jobs_UpdateMsg request parameters.
+ *
+ * @note For optional fields setting a pointer to NULL or
+ * the length to 0U will disable this field from being used
+ *
+ *
+ * @note Optional fields include:
+ * * expectedVersion
+ * * expectedVersionLength
+ * * statusDetails
+ * * statusDetailsLength
+ *
+ * @note The status details must be a JSON formatted key-value
+ * paid.
+ */
+typedef struct
+{
+ JobCurrentStatus_t status; /**< Status to update the job to */
+ const char * expectedVersion; /**< Expected version, optional */
+ size_t expectedVersionLength; /**< Expected version length, optional */
+ const char * statusDetails; /**< JSON key-value pair, optional */
+ size_t statusDetailsLength; /**< JSON key-value pair length, optional */
+} JobsUpdateRequest_t;
+
/*-----------------------------------------------------------*/
/**
@@ -838,9 +867,7 @@ JobsStatus_t Jobs_Update( char * buffer,
/**
* @brief Populate a message string for an UpdateJobExecution request.
*
- * @param status Current status of the job
- * @param expectedVersion The version that is expected, NULL if no version is expected
- * @param expectedVersionLength The length of the expectedVersion string, 0U if no version is expected
+ * @param request A jobs update request structure
* @param buffer The buffer to be written to
* @param bufferSize the size of the buffer
*
@@ -855,14 +882,18 @@ JobsStatus_t Jobs_Update( char * buffer,
* // of the AWS IoT Jobs Service
*
* const char * expectedVersion = "2";
- * size_t expectedVersionLength = ( sizeof(expectedVersion ) - 1U );
- * JobCurrentStatus_t status = Succeeded;
+ * const chat * statusDetails = "{\"key\":\"value\"}";
* char messageBuffer[ UPDATE_JOB_MSG_LENGTH ] = {0};
* size_t messageLength = 0U;
*
- * messageLength = Jobs_UpdateMsg( status,
- * expectedVersion,
- * expectedVersionLength,
+ * JobsUpdateRequest_t request;
+ * request.status = Succeeded;
+ * request.expectedVersion = expectedVersion;
+ * request.expectedVersionLength = ( sizeof( expectedVersion ) - 1U );
+ * request.statusDetails = statusDetails;
+ * request.statusDetailsLength = ( sizeof( statusDetails ) - 1U );
+ *
+ * messageLength = Jobs_UpdateMsg( request
* messageBuffer,
* UPDATE_JOB_MSG_LENGTH );
*
@@ -876,9 +907,7 @@ JobsStatus_t Jobs_Update( char * buffer,
* @endcode
*/
/* @[declare_jobs_updatemsg] */
-size_t Jobs_UpdateMsg( JobCurrentStatus_t status,
- const char * expectedVersion,
- size_t expectedVersionLength,
+size_t Jobs_UpdateMsg( JobsUpdateRequest_t request,
char * buffer,
size_t bufferSize );
/* @[declare_jobs_updatemsg] */
diff --git a/source/jobs.c b/source/jobs.c
index e66755d..5ab04a0 100644
--- a/source/jobs.c
+++ b/source/jobs.c
@@ -82,6 +82,24 @@ static const size_t apiTopicLength[] =
JOBS_API_UPDATE_LENGTH + JOBS_API_FAILURE_LENGTH,
};
+static const char * const jobStatusString[] =
+{
+ "QUEUED",
+ "IN_PROGRESS",
+ "FAILED",
+ "SUCCEEDED",
+ "REJECTED"
+};
+
+static const size_t jobStatusStringLengths[] =
+{
+ CONST_STRLEN( "QUEUED" ),
+ CONST_STRLEN( "IN_PROGRESS" ),
+ CONST_STRLEN( "FAILED" ),
+ CONST_STRLEN( "SUCCEEDED" ),
+ CONST_STRLEN( "REJECTED" )
+};
+
/**
* @brief Predicate returns true for a valid thing name or job ID character.
*
@@ -813,53 +831,91 @@ JobsStatus_t Jobs_Update( char * buffer,
return ret;
}
-size_t Jobs_UpdateMsg( JobCurrentStatus_t status,
- const char * expectedVersion,
- size_t expectedVersionLength,
- char * buffer,
- size_t bufferSize )
+/**
+ * @brief Get the total length of optional fields provided for
+ * the Jobs_UpdateMsg. These optional fields, if provided, require
+ * additional buffer space.
+ *
+ * @param request A JobsUpdateRequest_t containing the optional fields
+ * @return size_t The buffer space required for the optional fields
+ */
+static size_t getOptionalFieldsLength( JobsUpdateRequest_t request )
{
- static const char * const jobStatusString[] =
+ size_t minimumOptionalFieldsBufferSize = 0U;
+
+ if( ( request.expectedVersion != NULL ) && ( request.expectedVersionLength > 0U ) )
{
- "QUEUED",
- "IN_PROGRESS",
- "FAILED",
- "SUCCEEDED",
- "REJECTED"
- };
+ minimumOptionalFieldsBufferSize += JOBS_API_EXPECTED_VERSION_LENGTH + request.expectedVersionLength;
+ }
- static const size_t jobStatusStringLengths[] =
+ if( ( request.statusDetails != NULL ) && ( request.statusDetailsLength ) )
{
- CONST_STRLEN( "QUEUED" ),
- CONST_STRLEN( "IN_PROGRESS" ),
- CONST_STRLEN( "FAILED" ),
- CONST_STRLEN( "SUCCEEDED" ),
- CONST_STRLEN( "REJECTED" )
- };
+ minimumOptionalFieldsBufferSize += JOBS_API_STATUS_DETAILS_LENGTH + request.statusDetailsLength;
+ }
- assert( ( ( size_t ) status ) < ARRAY_LENGTH( jobStatusString ) );
+ return minimumOptionalFieldsBufferSize;
+}
- size_t start = 0U;
- size_t minimumBufferSize = JOBS_API_STATUS_LENGTH + jobStatusStringLengths[ status ] + CONST_STRLEN( "\"}" );
+/**
+ * @brief Get the total length of the required fields in the
+ * Jobs_UpdateMsg request.
+ *
+ * @param request A JobsUpdateRequest_t containing the optional fields
+ * @return size_t The buffer space required for the optional fields
+ */
+static size_t getRequiredFieldsLength( JobsUpdateRequest_t request )
+{
+ return JOBS_API_STATUS_LENGTH + jobStatusStringLengths[ request.status ] + CONST_STRLEN( "\"}" );
+}
+
+/**
+ * @brief Check non-null optional fields in the Jobs_UpdateMsg request
+ * for validity.
+ *
+ * @param request A JobsUpdateRequest_t containing the optional fields
+ * @return true Optional fields appear valid
+ * @return false Optional fields are invalid
+ */
+static bool areOptionalFieldsValid( JobsUpdateRequest_t request )
+{
+ bool optionalFieldsValid = true;
- if( ( expectedVersion != NULL ) && ( expectedVersionLength > 0U ) )
+ if( ( request.statusDetails != NULL ) && ( request.statusDetailsLength ) )
{
- minimumBufferSize += JOBS_API_EXPECTED_VERSION_LENGTH + expectedVersionLength;
+ optionalFieldsValid &= ( JSONSuccess == JSON_Validate( request.statusDetails, request.statusDetailsLength ) );
}
- bool writeFailed = bufferSize < minimumBufferSize;
+ return optionalFieldsValid;
+}
+
+size_t Jobs_UpdateMsg( JobsUpdateRequest_t request,
+ char * buffer,
+ size_t bufferSize )
+{
+ assert( ( ( size_t ) request.status ) < ARRAY_LENGTH( jobStatusString ) );
+
+ size_t start = 0U;
+ size_t minimumBufferSize = getRequiredFieldsLength( request ) + getOptionalFieldsLength( request );
+ bool writeFailed = bufferSize < minimumBufferSize || !areOptionalFieldsValid( request );
- if( !writeFailed && ( jobStatusString[ status ] != NULL ) )
+ if( !writeFailed )
{
( void ) strnAppend( buffer, &start, bufferSize, JOBS_API_STATUS, JOBS_API_STATUS_LENGTH );
- ( void ) strnAppend( buffer, &start, bufferSize, jobStatusString[ status ], jobStatusStringLengths[ status ] );
+ ( void ) strnAppend( buffer, &start, bufferSize, jobStatusString[ request.status ], jobStatusStringLengths[ request.status ] );
}
/* This is an optional field so do not fail if expected version is missing */
- if( !writeFailed && ( expectedVersion != NULL ) && ( expectedVersionLength > 0U ) )
+ if( !writeFailed && ( request.expectedVersion != NULL ) && ( request.expectedVersionLength > 0U ) )
{
( void ) strnAppend( buffer, &start, bufferSize, JOBS_API_EXPECTED_VERSION, JOBS_API_EXPECTED_VERSION_LENGTH );
- ( void ) strnAppend( buffer, &start, bufferSize, expectedVersion, expectedVersionLength );
+ ( void ) strnAppend( buffer, &start, bufferSize, request.expectedVersion, request.expectedVersionLength );
+ }
+
+ /* This is an optional field so do not fail if expected version is missing */
+ if( !writeFailed && ( request.statusDetails != NULL ) && ( request.statusDetailsLength > 0U ) )
+ {
+ ( void ) strnAppend( buffer, &start, bufferSize, JOBS_API_STATUS_DETAILS, JOBS_API_STATUS_DETAILS_LENGTH );
+ ( void ) strnAppend( buffer, &start, bufferSize, request.statusDetails, request.statusDetailsLength );
}
if( !writeFailed )
diff --git a/test/unit-test/jobs_utest.c b/test/unit-test/jobs_utest.c
index cf11ae7..8f995c8 100644
--- a/test/unit-test/jobs_utest.c
+++ b/test/unit-test/jobs_utest.c
@@ -878,65 +878,155 @@ void test_getStartNextPendingJobExecutionMsg_hasValidParameters( void )
/*Tests for getUpdateJobExecutionMsg */
void test_getUpdateJobExecutionMsg_hasNullExpectedVersion( void )
{
- JobCurrentStatus_t status = Queued;
char buffer[ TOPIC_BUFFER_SIZE + 1 ] = { 0 };
- size_t result = Jobs_UpdateMsg( status, NULL, 1U, buffer, TOPIC_BUFFER_SIZE );
+ JobsUpdateRequest_t request =
+ {
+ Queued,
+ NULL,
+ 1,
+ "{\"key\": \"value\"}",
+ strlen( "{\"key\": \"value\"}" )
+ };
- TEST_ASSERT_EQUAL( 19U, result );
+ size_t result = Jobs_UpdateMsg( request, buffer, TOPIC_BUFFER_SIZE );
+
+ TEST_ASSERT_EQUAL( 54U, result );
}
void test_getUpdateJobExecutionMsg_hasZeroLengthExpectedVersion( void )
{
- char * version = "1.0.1";
- JobCurrentStatus_t status = Queued;
char buffer[ TOPIC_BUFFER_SIZE + 1 ] = { 0 };
+ JobsUpdateRequest_t request =
+ {
+ Queued,
+ "1.0.1",
+ 0,
+ "{\"key\": \"value\"}",
+ strlen( "{\"key\": \"value\"}" )
+ };
+
+ size_t result = Jobs_UpdateMsg( request, buffer, TOPIC_BUFFER_SIZE );
+
+ TEST_ASSERT_EQUAL( 54U, result );
+}
+
+void test_getUpdateJobExecutionMsg_hasNullStatusDetails( void )
+{
+ char buffer[ TOPIC_BUFFER_SIZE + 1 ] = { 0 };
+ JobsUpdateRequest_t request =
+ {
+ Queued,
+ "1.0.1",
+ strlen( "1.0.1" ),
+ NULL,
+ strlen( "{\"key\": \"value\"}" )
+ };
+
+ size_t result = Jobs_UpdateMsg( request, buffer, TOPIC_BUFFER_SIZE );
+
+ TEST_ASSERT_EQUAL( 45U, result );
+}
+
+void test_getUpdateJobExecutionMsg_hasZeroLengthStatusDetails( void )
+{
+ char buffer[ TOPIC_BUFFER_SIZE + 1 ] = { 0 };
+ JobsUpdateRequest_t request =
+ {
+ Queued,
+ "1.0.1",
+ strlen( "1.0.1" ),
+ "{\"key\": \"value\"}",
+ 0
+ };
+
+ size_t result = Jobs_UpdateMsg( request, buffer, TOPIC_BUFFER_SIZE );
- size_t result = Jobs_UpdateMsg( status, version, 0U, buffer, TOPIC_BUFFER_SIZE );
+ TEST_ASSERT_EQUAL( 45U, result );
+}
+
+void test_getUpdateJobExecutionMsg_hasMalformedStatusDetails( void )
+{
+ char buffer[ TOPIC_BUFFER_SIZE + 1 ] = { 0 };
+ JobsUpdateRequest_t request =
+ {
+ Queued,
+ "1.0.1",
+ strlen( "1.0.1" ),
+ "malformed-details",
+ strlen( "malformed-details" )
+ };
+
+ size_t result = Jobs_UpdateMsg( request, buffer, TOPIC_BUFFER_SIZE );
TEST_ASSERT_EQUAL( 19U, result );
}
void test_getUpdateJobExecutionMsg_hasTooSmallBufferSizeForRequiredParameters( void )
{
- JobCurrentStatus_t status = Queued;
char buffer[ 2 ] = { 0 };
+ JobsUpdateRequest_t request =
+ {
+ Queued,
+ NULL,
+ 0,
+ NULL,
+ 0
+ };
- size_t result = Jobs_UpdateMsg( status, NULL, 0U, buffer, 1 );
+ size_t result = Jobs_UpdateMsg( request, buffer, 1 );
TEST_ASSERT_EQUAL( 0U, result );
}
void test_getUpdateJobExecutionMsg_hasTooSmallBufferSizeForAllParameters( void )
{
- char * version = "1.0.1";
- size_t versionLength = strlen( version );
- JobCurrentStatus_t status = Queued;
- char buffer[ 25 ] = { 0 };
+ char buffer[ 38 ] = { 0 };
+
+ JobsUpdateRequest_t request =
+ {
+ Queued,
+ "1.0.1",
+ strlen( "1.0.1" ),
+ "{\"key\": \"value\"}",
+ strlen( "{\"key\": \"value\"}" )
+ };
- size_t result = Jobs_UpdateMsg( status, version, versionLength, buffer, 1 );
+ size_t result = Jobs_UpdateMsg( request, buffer, 38 );
TEST_ASSERT_EQUAL( 0U, result );
}
void test_getUpdateJobExecutionMsg_hasAllValidParameters( void )
{
- char * version = "1.0.1";
- size_t versionLength = strlen( version );
- JobCurrentStatus_t status = Queued;
char buffer[ TOPIC_BUFFER_SIZE + 1 ] = { 0 };
+ JobsUpdateRequest_t request =
+ {
+ Queued,
+ "1.0.1",
+ strlen( "1.0.1" ),
+ "{\"key\": \"value\"}",
+ strlen( "{\"key\": \"value\"}" )
+ };
- size_t result = Jobs_UpdateMsg( status, version, versionLength, buffer, TOPIC_BUFFER_SIZE );
+ size_t result = Jobs_UpdateMsg( request, buffer, TOPIC_BUFFER_SIZE );
- TEST_ASSERT_EQUAL( 45U, result );
+ TEST_ASSERT_EQUAL( 80U, result );
}
void test_getUpdateJobExecutionMsg_hasRequiredValidParameters( void )
{
- JobCurrentStatus_t status = Queued;
char buffer[ TOPIC_BUFFER_SIZE + 1 ] = { 0 };
-
- size_t result = Jobs_UpdateMsg( status, NULL, 0U, buffer, TOPIC_BUFFER_SIZE );
+ JobsUpdateRequest_t request =
+ {
+ Queued,
+ NULL,
+ 0,
+ NULL,
+ 0
+ };
+
+ size_t result = Jobs_UpdateMsg( request, buffer, TOPIC_BUFFER_SIZE );
TEST_ASSERT_EQUAL( 19U, result );
}