Skip to content

Commit

Permalink
Add MQTT downloader unit tests (#38)
Browse files Browse the repository at this point in the history
Add unit tests for MQTT library
component.
  • Loading branch information
kstribrnAmzn authored Sep 11, 2023
1 parent e9ecc5d commit 8b46603
Show file tree
Hide file tree
Showing 7 changed files with 1,446 additions and 24 deletions.
10 changes: 4 additions & 6 deletions lib/iot-core-mqtt-file-downloader/source/MQTTFileDownloader.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ static uint16_t createTopic( char * topicBuffer,
return topicLen;
}

/* TODO - Defend agains NULL streamName or thingName and 0 lengths*/
uint8_t mqttDownloader_init( MqttFileDownloaderContext_t * context,
char * streamName,
size_t streamNameLength,
Expand Down Expand Up @@ -262,8 +263,7 @@ uint8_t mqttDownloader_requestDataBlock( MqttFileDownloaderContext_t * context,
{
requestStatus = MQTTFileDownloaderBadParameter;
}

if( ( context->topicStreamDataLength == 0 ) ||
else if( ( context->topicStreamDataLength == 0 ) ||
( context->topicGetStreamLength == 0 ) )
{
requestStatus = MQTTFileDownloaderNotInitialized;
Expand All @@ -286,7 +286,6 @@ uint8_t mqttDownloader_requestDataBlock( MqttFileDownloaderContext_t * context,
"\"l\": %u,"
"\"o\": %u,"
"\"n\": %u"

"}",
fileId,
blockSize,
Expand Down Expand Up @@ -342,8 +341,6 @@ static uint8_t handleCborMessage( uint8_t * decodedData,
size_t payloadSize = mqttFileDownloader_CONFIG_BLOCK_SIZE;
uint8_t handleStatus = MQTTFileDownloaderSuccess;

memset( decodedData, '\0', mqttFileDownloader_CONFIG_BLOCK_SIZE );

cborDecodeRet = CBOR_Decode_GetStreamResponseMessage( message,
messageLength,
&fileId,
Expand Down Expand Up @@ -411,13 +408,14 @@ static uint8_t handleJsonMessage( uint8_t * decodedData,
return handleStatus;
}

/* TODO - Handle NULL topic or zero topic length */
bool mqttDownloader_isDataBlockReceived( MqttFileDownloaderContext_t * context,
char * topic,
size_t topicLength )
{
bool handled = false;

if( ( topicLength == strlen( context->topicStreamData ) ) &&
if( ( topicLength == context->topicStreamDataLength ) &&
( 0 == strncmp( context->topicStreamData, topic, topicLength ) ) )
{
handled = true;
Expand Down
2 changes: 1 addition & 1 deletion lib/iot-core-mqtt-file-downloader/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -135,5 +135,5 @@ add_custom_target(
coverage
COMMAND ${CMAKE_COMMAND} -DCMOCK_DIR=${cmock_SOURCE_DIR} -P
${MODULE_ROOT_DIR}/tools/cmock/coverage.cmake
DEPENDS cmock unity tinycbor mqtt_file_downloader_utest
DEPENDS cmock unity tinycbor mqtt_file_downloader_utest mqtt_file_downloader_base64_utest mqtt_file_downloader_cbor_utest
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
58 changes: 46 additions & 12 deletions lib/iot-core-mqtt-file-downloader/test/unit-test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,13 @@ include(${MODULE_ROOT_DIR}/mqttFileDownloaderFilePaths.cmake)
include("${corejson_SOURCE_DIR}/jsonFilePaths.cmake")
include("${coremqtt_SOURCE_DIR}/mqttFilePaths.cmake")

# ==================== Define your project name (edit) ========================
set(project_name "mqtt_file_downloader")

# ===================== Create your mock here (edit) ========================

# list the files to mock here
list(APPEND mock_list
"${MODULE_ROOT_DIR}/test/unit-test/dependencies/mqtt_wrapper.h")

# list the directories your mocks need
list(APPEND mock_include_list
"${MODULE_ROOT_DIR}/source/include"
"${MODULE_ROOT_DIR}/test/unit-test/dependencies/coreMQTT/"
"${tinycbor_SOURCE_DIR}/src/"
${MQTT_INCLUDE_PUBLIC_DIRS}
)

Expand All @@ -47,7 +41,6 @@ list(APPEND real_include_directories .
${MQTT_FILE_DOWNLOADER_INCLUDES}
${JSON_INCLUDE_PUBLIC_DIRS}
${MQTT_INCLUDE_PUBLIC_DIRS}
"${tinycbor_SOURCE_DIR}/src"
"${MODULE_ROOT_DIR}/test/unit-test/dependencies/"
"${MODULE_ROOT_DIR}/test/unit-test/dependencies/coreMQTT/"
)
Expand All @@ -59,17 +52,58 @@ list(APPEND test_include_directories . ${MQTT_FILE_DOWNLOADER_INCLUDES})

# ============================= (end edit) ===================================

# Create core_jobs unit test
set(real_name "mqtt_file_downloader_real")
# Create MQTTFileDownloader_cbor unit test
set(utest_name "mqtt_file_downloader_cbor_utest")
set(utest_source "downloader_cbor_utest.c")
set(mock_name "mqtt_file_downloader_cbor_mock")
set(real_name "mqtt_file_downloader_cbor_real")

list(APPEND cbor_mock_list
"${MODULE_ROOT_DIR}/test/unit-test/dependencies/cbor.h")

create_mock_list(
${mock_name} "${cbor_mock_list}" "${MODULE_ROOT_DIR}/tools/cmock/project.yml"
"${mock_include_list}" "${mock_define_list}")

create_real_library(${real_name} "${real_source_files}"
"${real_include_directories}" "${mock_define_list}")

list(APPEND cbor_downloader_link_list -l${mock_name} lib${real_name}.a)

list(APPEND cbor_downloader_dep_list ${real_name})

create_test(${utest_name} ${utest_source} "${cbor_downloader_link_list}"
"${cbor_downloader_dep_list}" "${test_include_directories}")

# Create MQTTFileDownloader unit test
set(utest_name "mqtt_file_downloader_utest")
set(utest_source "downloader_utest.c")
set(mock_name "${project_name}_mock")
set(real_name "${project_name}_real")
set(mock_name "mqtt_file_downloader_mock")
set(real_name "mqtt_file_downloader_real")

list(APPEND mock_list
"${MODULE_ROOT_DIR}/test/unit-test/dependencies/mqtt_wrapper.h"
"${MODULE_ROOT_DIR}/source/include/MQTTFileDownloader_cbor.h")

create_mock_list(
${mock_name} "${mock_list}" "${MODULE_ROOT_DIR}/tools/cmock/project.yml"
"${mock_include_list}" "${mock_define_list}")

create_real_library(${real_name} "${real_source_files}"
"${real_include_directories}" "${mock_define_list}")

list(APPEND file_downloader_list -l${mock_name} lib${real_name}.a)

list(APPEND file_downloader_dep_list ${real_name})

create_test(${utest_name} ${utest_source} "${file_downloader_list}"
"${file_downloader_dep_list}" "${test_include_directories}")

# Create MQTTFileDownloader_base64 unit test
set(real_name "mqtt_file_downloader_base64_real")
set(utest_name "mqtt_file_downloader_base64_utest")
set(utest_source "downloader_base64_utest.c")

create_real_library(${real_name} "${real_source_files}"
"${real_include_directories}" "${mock_define_list}")

Expand Down
138 changes: 138 additions & 0 deletions lib/iot-core-mqtt-file-downloader/test/unit-test/dependencies/cbor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/*
* Copyright Amazon.com, Inc. and its affiliates. All Rights Reserved.
* SPDX-License-Identifier: MIT
*
* Licensed under the MIT License. See the LICENSE accompanying this file
* for the specific language governing permissions and limitations under
* the License.
*/

/* This file is a simplified and stripped down version of the tinycbor main header file for mocking */
#ifndef assert
#include <assert.h>
#endif
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>


typedef enum CborType {
CborIntegerType = 0x00,
CborByteStringType = 0x40,
CborTextStringType = 0x60,
CborArrayType = 0x80,
CborMapType = 0xa0,
CborTagType = 0xc0,
CborSimpleType = 0xe0,
CborBooleanType = 0xf5,
CborNullType = 0xf6,
CborUndefinedType = 0xf7,
CborHalfFloatType = 0xf9,
CborFloatType = 0xfa,
CborDoubleType = 0xfb,

CborInvalidType = 0xff /* equivalent to the break byte, so it will never be used */
} CborType;

/* Error API */
typedef enum CborError {
CborNoError = 0,

/* errors in all modes */
CborUnknownError,
CborErrorUnknownLength, /* request for length in array, map, or string with indeterminate length */
CborErrorAdvancePastEOF,
CborErrorIO,

/* parser errors streaming errors */
CborErrorGarbageAtEnd = 256,
CborErrorUnexpectedEOF,
CborErrorUnexpectedBreak,
CborErrorUnknownType, /* can only happen in major type 7 */
CborErrorIllegalType, /* type not allowed here */
CborErrorIllegalNumber,
CborErrorIllegalSimpleType, /* types of value less than 32 encoded in two bytes */

/* parser errors in strict mode parsing only */
CborErrorUnknownSimpleType = 512,
CborErrorUnknownTag,
CborErrorInappropriateTagForType,
CborErrorDuplicateObjectKeys,
CborErrorInvalidUtf8TextString,
CborErrorExcludedType,
CborErrorExcludedValue,
CborErrorImproperValue,
CborErrorOverlongEncoding,
CborErrorMapKeyNotString,
CborErrorMapNotSorted,
CborErrorMapKeysNotUnique,

/* encoder errors */
CborErrorTooManyItems = 768,
CborErrorTooFewItems,

/* internal implementation errors */
CborErrorDataTooLarge = 1024,
CborErrorNestingTooDeep,
CborErrorUnsupportedType,

/* errors in converting to JSON */
CborErrorJsonObjectKeyIsAggregate = 1280,
CborErrorJsonObjectKeyNotString,
CborErrorJsonNotImplemented,

CborErrorOutOfMemory = (int) (~0U / 2 + 1),
CborErrorInternalError = (int) (~0U / 2) /* INT_MAX on two's complement machines */
} CborError;


struct CborParser
{
const uint8_t *end;
uint32_t flags;
};
typedef struct CborParser CborParser;

struct CborEncoder
{
union {
uint8_t *ptr;
ptrdiff_t bytes_needed;
} data;
const uint8_t *end;
size_t remaining;
int flags;
};
typedef struct CborEncoder CborEncoder;

struct CborValue
{
const CborParser *parser;
const uint8_t *ptr;
uint32_t remaining;
uint16_t extra;
uint8_t type;
uint8_t flags;
};
typedef struct CborValue CborValue;


CborError cbor_parser_init(const uint8_t *buffer, size_t size, uint32_t flags, CborParser *parser, CborValue *it);
bool cbor_value_is_map(const CborValue *value);
CborError cbor_value_map_find_value(const CborValue *map, const char *string, CborValue *element);
CborError cbor_value_get_int64(const CborValue *value, int64_t *result);
CborError cbor_value_get_int(const CborValue *value, int *result);
CborError cbor_value_calculate_string_length(const CborValue *value, size_t *length);
CborError cbor_value_copy_byte_string(const CborValue *value, uint8_t *buffer, size_t *buflen, CborValue *next);

void cbor_encoder_init(CborEncoder *encoder, uint8_t *buffer, size_t size, int flags);
CborError cbor_encoder_create_map(CborEncoder *encoder, CborEncoder *mapEncoder, size_t length);
CborError cbor_encode_byte_string(CborEncoder *encoder, const uint8_t *string, size_t length);
CborError cbor_encode_text_stringz(CborEncoder *encoder, const char *string);
CborError cbor_encode_int(CborEncoder *encoder, int64_t value);
CborError cbor_encoder_close_container_checked(CborEncoder *encoder, const CborEncoder *containerEncoder);
size_t cbor_encoder_get_buffer_size(const CborEncoder *encoder, const uint8_t *buffer);

CborType cbor_value_get_type(const CborValue *value);
Loading

0 comments on commit 8b46603

Please sign in to comment.