From 125731315179ab44a4b0108911a88992631acc74 Mon Sep 17 00:00:00 2001 From: Ewerton Scaboro da Silva Date: Fri, 30 Jun 2023 15:50:42 -0700 Subject: [PATCH 01/27] Add more granular upload-to-blob functions, refactor u2b code --- iothub_client/inc/internal/blob.h | 52 +- .../internal/iothub_client_ll_uploadtoblob.h | 17 +- iothub_client/inc/iothub_client_core.h | 4 + iothub_client/inc/iothub_client_core_ll.h | 6 + iothub_client/inc/iothub_device_client.h | 83 +- iothub_client/inc/iothub_device_client_ll.h | 82 + iothub_client/samples/CMakeLists.txt | 1 + .../CMakeLists.txt | 46 + ...thub_client_sample_upload_to_blob_custom.c | 129 ++ .../linux/CMakeLists.txt | 29 + .../iothub_client_sample_upload_to_blob.sln | 28 + ...othub_client_sample_upload_to_blob.vcxproj | 172 +++ .../iothub_client_sample_upload_to_blob_mb.c | 5 + iothub_client/src/blob.c | 422 +++--- iothub_client/src/iothub_client_core.c | 36 + iothub_client/src/iothub_client_core_ll.c | 135 +- .../src/iothub_client_ll_uploadtoblob.c | 1316 ++++++++++------- iothub_client/src/iothub_device_client.c | 21 + iothub_client/src/iothub_device_client_ll.c | 19 + .../iothubclient_uploadtoblob_e2e.c | 6 +- 20 files changed, 1818 insertions(+), 791 deletions(-) create mode 100644 iothub_client/samples/iothub_client_sample_upload_to_blob_custom/CMakeLists.txt create mode 100644 iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c create mode 100644 iothub_client/samples/iothub_client_sample_upload_to_blob_custom/linux/CMakeLists.txt create mode 100644 iothub_client/samples/iothub_client_sample_upload_to_blob_custom/windows/iothub_client_sample_upload_to_blob.sln create mode 100644 iothub_client/samples/iothub_client_sample_upload_to_blob_custom/windows/iothub_client_sample_upload_to_blob.vcxproj diff --git a/iothub_client/inc/internal/blob.h b/iothub_client/inc/internal/blob.h index bdc149bbc1..d6c7c9caaf 100644 --- a/iothub_client/inc/internal/blob.h +++ b/iothub_client/inc/internal/blob.h @@ -17,6 +17,7 @@ #include "azure_c_shared_utility/buffer_.h" #include "azure_c_shared_utility/strings_types.h" #include "azure_c_shared_utility/httpapiex.h" +#include "azure_c_shared_utility/singlylinkedlist.h" #include "iothub_client_core_ll.h" #include "azure_c_shared_utility/shared_util_options.h" @@ -46,36 +47,47 @@ extern "C" MU_DEFINE_ENUM_WITHOUT_INVALID(BLOB_RESULT, BLOB_RESULT_VALUES) +MOCKABLE_FUNCTION(, HTTPAPIEX_HANDLE, Blob_CreateHttpConnection, const char*, blobStorageHostname, const char*, certificates, HTTP_PROXY_OPTIONS*, proxyOptions, const char*, networkInterface, const size_t, timeoutInMilliseconds); + +MOCKABLE_FUNCTION(, void, Blob_DestroyHttpConnection, HTTPAPIEX_HANDLE, httpApiExHandle); + +MOCKABLE_FUNCTION(, void, Blob_ClearBlockIdList, SINGLYLINKEDLIST_HANDLE, blockIdList); + /** -* @brief Synchronously uploads a byte array to blob storage -* -* @param SASURI The URI to use to upload data -* @param getDataCallbackEx A callback to be invoked to acquire the file chunks to be uploaded, as well as to indicate the status of the upload of the previous block. -* @param context Any data provided by the user to serve as context on getDataCallback. -* @param httpStatus A pointer to an out argument receiving the HTTP status (available only when the return value is BLOB_OK) -* @param httpResponse A BUFFER_HANDLE that receives the HTTP response from the server (available only when the return value is BLOB_OK) -* @param certificates A null terminated string containing CA certificates to be used -* @param proxyOptions A structure that contains optional web proxy information -* @param networkInterface An optional null terminated string containing the network interface -* @param timeoutInMilliseconds The maximum time in ms allowed for a blob transfer. A value of 0 uses the default timeout for the underlying transport. +* @brief Synchronously uploads a byte array as a new block to blob storage (put block operation) * -* @return A @c BLOB_RESULT. BLOB_OK means the blob has been uploaded successfully. Any other value indicates an error +* @param httpApiExHandle The HTTP connection handle +* @param relativePath The destination path within the storage +* @param blockID The block id (from 00000 to 49999) +* @param blockData The data to upload +* @param blockIDList The list where to store the block IDs +* @param httpStatus A pointer to an out argument receiving the HTTP status (available only when the return value is BLOB_OK) +* @param httpResponse A BUFFER_HANDLE that receives the HTTP response from the server (available only when the return value is BLOB_OK) */ -MOCKABLE_FUNCTION(, BLOB_RESULT, Blob_UploadMultipleBlocksFromSasUri, const char*, SASURI, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context, unsigned int*, httpStatus, BUFFER_HANDLE, httpResponse, const char*, certificates, HTTP_PROXY_OPTIONS*, proxyOptions, const char*, networkInterface, const size_t, timeoutInMilliseconds) +MOCKABLE_FUNCTION(, BLOB_RESULT, Blob_PutBlock, + HTTPAPIEX_HANDLE, httpApiExHandle, + const char*, relativePath, + unsigned int, blockID, + BUFFER_HANDLE, blockData, + SINGLYLINKEDLIST_HANDLE, blockIDList, + unsigned int*, httpStatus, + BUFFER_HANDLE, httpResponse) /** -* @brief Synchronously uploads a byte array as a new block to blob storage +* @brief Synchronously sends a put block list request to Azure Storage * -* @param requestContent The data to upload -* @param blockId The block id (from 00000 to 49999) -* @param xml The XML file containing the blockId list +* @param httpApiExHandle The HTTP connection handle * @param relativePath The destination path within the storage -* @param httpApiExHandle The connection handle +* @param blockIDList The list containing the block IDs to report * @param httpStatus A pointer to an out argument receiving the HTTP status (available only when the return value is BLOB_OK) * @param httpResponse A BUFFER_HANDLE that receives the HTTP response from the server (available only when the return value is BLOB_OK) */ -//MOCKABLE_FUNCTION(, BLOB_RESULT, Blob_UploadNextBlock, BUFFER_HANDLE, requestContent, unsigned int, blockID, STRING_HANDLE, xml, const char*, relativePath, HTTPAPIEX_HANDLE, httpApiExHandle, unsigned int*, httpStatus, BUFFER_HANDLE, httpResponse) -MOCKABLE_FUNCTION(, BLOB_RESULT, Blob_UploadBlock, HTTPAPIEX_HANDLE, httpApiExHandle, const char*, relativePath, BUFFER_HANDLE, requestContent, unsigned int, blockID, STRING_HANDLE, blockIDList, unsigned int*, httpStatus, BUFFER_HANDLE, httpResponse) +MOCKABLE_FUNCTION(, BLOB_RESULT, Blob_PutBlockList, + HTTPAPIEX_HANDLE, httpApiExHandle, + const char*, relativePath, + SINGLYLINKEDLIST_HANDLE, blockIDList, + unsigned int*, httpStatus, + BUFFER_HANDLE, httpResponse) #ifdef __cplusplus } #endif diff --git a/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h b/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h index 7798d6a641..a73e20d879 100644 --- a/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h +++ b/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h @@ -40,10 +40,23 @@ extern "C" #define BLOCK_SIZE (100*1024*1024) typedef struct IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE; + typedef struct IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_STRUCT* IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE; MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, IoTHubClient_LL_UploadToBlob_Create, const IOTHUB_CLIENT_CONFIG*, config, IOTHUB_AUTHORIZATION_HANDLE, auth_handle); - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_Impl, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, handle, const char*, destinationFileName, const unsigned char*, source, size_t, size); - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, handle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context); + + /* + * @remark This is a function left in this module for legacy compatibility with the exposed public API for + * upload to blob in iothub_(device|module)_client(_ll) that allowed passing a callback for obtaining the + * blob blocks data. Since there was quite a lot of (specific) logic put into this function that it + * better reside in this API module. + */ + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context); + + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, IoTHubClient_LL_UploadToBlob_CreateContext, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, handle, const char*, destinationFileName); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_UploadBlock, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContext, uint32_t, blockNumber, const uint8_t*, dataPtr, size_t, dataSize); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_Complete, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContext, bool, isSuccess, int, responseCode, const char*, responseMessage); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_DestroyContext, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContext); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_SetOption, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, handle, const char*, optionName, const void*, value); MOCKABLE_FUNCTION(, void, IoTHubClient_LL_UploadToBlob_Destroy, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, handle); diff --git a/iothub_client/inc/iothub_client_core.h b/iothub_client/inc/iothub_client_core.h index 8ac8f1443a..859208d11f 100644 --- a/iothub_client/inc/iothub_client_core.h +++ b/iothub_client/inc/iothub_client_core.h @@ -52,6 +52,10 @@ extern "C" #ifndef DONT_USE_UPLOADTOBLOB MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_UploadToBlobAsync, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, const char*, destinationFileName, const unsigned char*, source, size_t, size, IOTHUB_CLIENT_FILE_UPLOAD_CALLBACK, iotHubClientFileUploadCallback, void*, context); MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_UploadMultipleBlocksToBlobAsync, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK, getDataCallback, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, IoTHubClientCore_CreateUploadContext, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, const char*, destinationFileName); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_UploadBlockToBlob, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle, uint32_t, blockNumber, const uint8_t*, dataPtr, size_t, dataSize); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_CompleteUploadToBlob, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle, bool, isSuccess, int, responseCode, const char*, responseMessage); + MOCKABLE_FUNCTION(, void, IoTHubClientCore_DestroyUploadContext, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle); #endif /* DONT_USE_UPLOADTOBLOB */ MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_SendEventToOutputAsync, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, IOTHUB_MESSAGE_HANDLE, eventMessageHandle, const char*, outputName, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK, eventConfirmationCallback, void*, userContextCallback); diff --git a/iothub_client/inc/iothub_client_core_ll.h b/iothub_client/inc/iothub_client_core_ll.h index 36c1801132..18c9bd2afb 100644 --- a/iothub_client/inc/iothub_client_core_ll.h +++ b/iothub_client/inc/iothub_client_core_ll.h @@ -1,3 +1,4 @@ + // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. @@ -18,6 +19,7 @@ typedef struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA_TAG* IOTHUB_CLIENT_CORE_LL_HAND #include "umock_c/umock_c_prod.h" #include "iothub_transport_ll.h" #include "iothub_client_core_common.h" +#include "internal/iothub_client_ll_uploadtoblob.h" #ifdef __cplusplus extern "C" @@ -52,6 +54,10 @@ extern "C" MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_UploadToBlob, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, const unsigned char*, source, size_t, size); MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_UploadMultipleBlocksToBlob, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK, getDataCallback, void*, context); MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, IoTHubClientCore_LL_CreateUploadContext, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_UploadBlockToBlob, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle, uint32_t, blockNumber, const uint8_t*, dataPtr, size_t, dataSize); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_CompleteUploadToBlob, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle, bool, isSuccess, int, responseCode, const char*, responseMessage); + MOCKABLE_FUNCTION(, void, IoTHubClientCore_LL_DestroyUploadContext, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle); #endif /*DONT_USE_UPLOADTOBLOB*/ #ifdef USE_EDGE_MODULES diff --git a/iothub_client/inc/iothub_device_client.h b/iothub_client/inc/iothub_device_client.h index 23cac8ca5b..4385259e84 100644 --- a/iothub_client/inc/iothub_device_client.h +++ b/iothub_client/inc/iothub_device_client.h @@ -24,7 +24,6 @@ #include "iothub_client_core.h" #include "iothub_device_client_ll.h" - #ifndef IOTHUB_DEVICE_CLIENT_INSTANCE_TYPE /** * @brief Handle corresponding to a convenience layer device client instance. @@ -349,6 +348,88 @@ extern "C" */ MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync, IOTHUB_DEVICE_CLIENT_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context); + /** + * @brief This API creates a context for a new blob upload to Azure Storage. + * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. + * This function is expected to be used along with: + * `IoTHubDeviceClient_CreateUploadContext` + * `IoTHubDeviceClient_UploadBlockToBlob` + * `IoTHubDeviceClient_DestroyUploadContext` + * For the standard less-granular uploads to blob please use either + * `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`. + * + * @param iotHubClientHandle The handle created by a call to the create function. + * @param destinationFileName name of the file. + * + * @warning This is a synchronous/blocking function. + * + * @return A `IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE` on success or NULL if the function fails. + */ + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, IoTHubDeviceClient_CreateUploadContext, IOTHUB_DEVICE_CLIENT_HANDLE, iotHubClientHandle, const char*, destinationFileName); + + /** + * @brief This API upload a single blob block to Azure Storage (performs a PUT BLOCK operation). + * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. + * This function is expected to be used along with: + * `IoTHubDeviceClient_CreateUploadContext` + * `IoTHubDeviceClient_UploadBlockToBlob` + * `IoTHubDeviceClient_DestroyUploadContext` + * For the standard less-granular uploads to blob please use either + * `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`. + * + * @param uploadContextHandle The handle created with `IoTHubDeviceClient_CreateUploadContext`. + * @param blockNumber Number of the block being uploaded. + * @param dataPtr Pointer to the block data to be uploaded to Azure Storage blob. + * @param dataSize Size of the block data pointed by `dataPtr`. + * + * @warning This is a synchronous/blocking function. + * + * @return IOTHUB_CLIENT_OK upon success or an error code upon failure. + */ + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_UploadBlockToBlob, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle, uint32_t, blockNumber, const uint8_t*, dataPtr, size_t, dataSize); + + /** + * @brief This API performs an Azure Storage PUT BLOCK LIST operation and + * notifies Azure IoT Hub of the upload completion. + * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. + * This function is expected to be used along with: + * `IoTHubDeviceClient_CreateUploadContext` + * `IoTHubDeviceClient_UploadBlockToBlob` + * `IoTHubDeviceClient_DestroyUploadContext` + * For the standard less-granular uploads to blob please use either + * `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`. + * If this function fails (due to any HTTP error to either Azure Storage or Azure IoT Hub) it can + * be run again for a discretionary number of times in an attempt to succeed after, for example, + * an internet connectivity disruption is over. + * + * @param uploadContextHandle The handle created with `IoTHubDeviceClient_CreateUploadContext`. + * @param isSuccess A boolean value indicating if the call(s) to `IoTHubDeviceClient_UploadBlockToBlob` succeeded. + * @param responseCode An user-defined code to signal the status of the upload (e.g., 200 for success, or -1 for abort). + * @param responseMessage An user-defined status message to go along with `responseCode` on the notification to Azure IoT Hub. + * + * @warning This is a synchronous/blocking function. + * + * @return IOTHUB_CLIENT_OK upon success or an error code upon failure. + */ + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_CompleteUploadToBlob, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle, bool, isSuccess, int, responseCode, const char*, responseMessage); + + /** + * @brief This API destroy a blob upload context previously created with `IoTHubDeviceClient_CreateUploadContext`. + * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. + * This function is expected to be used along with: + * `IoTHubDeviceClient_CreateUploadContext` + * `IoTHubDeviceClient_UploadBlockToBlob` + * `IoTHubDeviceClient_CompleteUploadToBlob` + * For the standard less-granular uploads to blob please use either + * `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`. + * + * @param uploadContextHandle The handle created with `IoTHubDeviceClient_CreateUploadContext`. + * + * @warning This is a synchronous/blocking function. + * + * @return Nothing. + */ + MOCKABLE_FUNCTION(, void, IoTHubDeviceClient_DestroyUploadContext, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle); #endif /* DONT_USE_UPLOADTOBLOB */ /** diff --git a/iothub_client/inc/iothub_device_client_ll.h b/iothub_client/inc/iothub_device_client_ll.h index 028f7cdd0a..dda3ece9d0 100644 --- a/iothub_client/inc/iothub_device_client_ll.h +++ b/iothub_client/inc/iothub_device_client_ll.h @@ -378,6 +378,88 @@ typedef struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA_TAG* IOTHUB_DEVICE_CLIENT_LL_HA */ MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context); + /** + * @brief This API creates a context for a new blob upload to Azure Storage. + * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. + * This function is expected to be used along with: + * `IoTHubDeviceClient_LL_UploadBlockToBlob` + * `IoTHubDeviceClient_LL_CompleteUploadToBlob` + * `IoTHubDeviceClient_LL_DestroyUploadContext` + * For the standard less-granular uploads to blob please use either + * `IoTHubDeviceClient_LL_UploadToBlob` or `IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob`. + * + * @param iotHubClientHandle The handle created by a call to the create function. + * @param destinationFileName name of the file. + * + * @warning This is a synchronous/blocking function. + * + * @return A `IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE` on success or NULL if the function fails. + */ + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, IoTHubDeviceClient_LL_CreateUploadContext, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName); + + /** + * @brief This API upload a single blob block to Azure Storage (performs a PUT BLOCK operation). + * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. + * This function is expected to be used along with: + * `IoTHubDeviceClient_LL_CreateUploadContext` + * `IoTHubDeviceClient_LL_CompleteUploadToBlob` + * `IoTHubDeviceClient_LL_DestroyUploadContext` + * For the standard less-granular uploads to blob please use either + * `IoTHubDeviceClient_LL_UploadToBlob` or `IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob`. + * + * @param uploadContextHandle The handle created with `IoTHubDeviceClient_LL_CreateUploadContext`. + * @param blockNumber Number of the block being uploaded. + * @param dataPtr Pointer to the block data to be uploaded to Azure Storage blob. + * @param dataSize Size of the block data pointed by `dataPtr`. + * + * @warning This is a synchronous/blocking function. + * + * @return IOTHUB_CLIENT_OK upon success or an error code upon failure. + */ + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_UploadBlockToBlob, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle, uint32_t, blockNumber, const uint8_t*, dataPtr, size_t, dataSize); + + /** + * @brief This API performs an Azure Storage PUT BLOCK LIST operation and + * notifies Azure IoT Hub of the upload completion. + * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. + * This function is expected to be used along with: + * `IoTHubDeviceClient_LL_CreateUploadContext` + * `IoTHubDeviceClient_LL_UploadBlockToBlob` + * `IoTHubDeviceClient_LL_DestroyUploadContext` + * For the standard less-granular uploads to blob please use either + * `IoTHubDeviceClient_LL_UploadToBlob` or `IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob`. + * If this function fails (due to any HTTP error to either Azure Storage or Azure IoT Hub) it can + * be run again for a discretionary number of times in an attempt to succeed after, for example, + * an internet connectivity disruption is over. + * + * @param uploadContextHandle The handle created with `IoTHubDeviceClient_LL_CreateUploadContext`. + * @param isSuccess A boolean value indicating if the call(s) to `IoTHubDeviceClient_LL_UploadBlockToBlob` succeeded. + * @param responseCode An user-defined code to signal the status of the upload (e.g., 200 for success, or -1 for abort). + * @param responseMessage An user-defined status message to go along with `responseCode` on the notification to Azure IoT Hub. + * + * @warning This is a synchronous/blocking function. + * + * @return IOTHUB_CLIENT_OK upon success or an error code upon failure. + */ + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_CompleteUploadToBlob, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle, bool, isSuccess, int, responseCode, const char*, responseMessage); + + /** + * @brief This API destroy a blob upload context previously created with `IoTHubDeviceClient_LL_CreateUploadContext` . + * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. + * This function is expected to be used along with: + * `IoTHubDeviceClient_LL_CreateUploadContext` + * `IoTHubDeviceClient_LL_UploadBlockToBlob` + * `IoTHubDeviceClient_LL_CompleteUploadToBlob` + * For the standard less-granular uploads to blob please use either + * `IoTHubDeviceClient_LL_UploadToBlob` or `IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob`. + * + * @param uploadContextHandle The handle created with `IoTHubDeviceClient_LL_CreateUploadContext`. + * + * @warning This is a synchronous/blocking function. + * + * @return Nothing. + */ + MOCKABLE_FUNCTION(, void, IoTHubDeviceClient_LL_DestroyUploadContext, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle); #endif /*DONT_USE_UPLOADTOBLOB*/ /** diff --git a/iothub_client/samples/CMakeLists.txt b/iothub_client/samples/CMakeLists.txt index 04f00ba8b2..b23dea6bdf 100644 --- a/iothub_client/samples/CMakeLists.txt +++ b/iothub_client/samples/CMakeLists.txt @@ -24,6 +24,7 @@ if(${use_http}) if(NOT ${dont_use_uploadtoblob}) add_sample_directory(iothub_client_sample_upload_to_blob) add_sample_directory(iothub_client_sample_upload_to_blob_mb) + add_sample_directory(iothub_client_sample_upload_to_blob_custom) endif() if (${use_edge_modules}) add_sample_directory(iothub_client_sample_module_method_invoke) diff --git a/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/CMakeLists.txt b/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/CMakeLists.txt new file mode 100644 index 0000000000..db966715e9 --- /dev/null +++ b/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/CMakeLists.txt @@ -0,0 +1,46 @@ +#Copyright (c) Microsoft. All rights reserved. +#Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#this is CMakeLists.txt for iothub_client_sample_upload_to_blob + +compileAsC99() + +if(NOT ${use_http}) + message(FATAL_ERROR "iothub_client_sample_upload_to_blob_custom being generated without HTTP support") +endif() + +set(iothub_client_sample_upload_to_blob_custom_c_files + iothub_client_sample_upload_to_blob_custom.c +) + +set(iothub_client_sample_upload_to_blob_custom_h_files +) + +#Conditionally use the SDK trusted certs in the samples +if(${use_sample_trusted_cert}) + add_definitions(-DSET_TRUSTED_CERT_IN_SAMPLES) + include_directories(${PROJECT_SOURCE_DIR}/certs) + set(iothub_client_sample_upload_to_blob_custom_c_files ${iothub_client_sample_upload_to_blob_custom_c_files} ${PROJECT_SOURCE_DIR}/certs/certs.c) +endif() + +IF(WIN32) + #windows needs this define + add_definitions(-D_CRT_SECURE_NO_WARNINGS) + add_definitions(-DGB_MEASURE_MEMORY_FOR_THIS -DGB_DEBUG_ALLOC) +ENDIF(WIN32) + +include_directories(.) + +add_executable( + iothub_client_sample_upload_to_blob_custom + ${iothub_client_sample_upload_to_blob_custom_c_files} + ${iothub_client_sample_upload_to_blob_custom_h_files} +) + +target_link_libraries(iothub_client_sample_upload_to_blob_custom + iothub_client + iothub_client_http_transport +) + +linkSharedUtil(iothub_client_sample_upload_to_blob_custom) +linkHttp(iothub_client_sample_upload_to_blob_custom) diff --git a/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c b/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c new file mode 100644 index 0000000000..8531e3da6d --- /dev/null +++ b/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c @@ -0,0 +1,129 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +// CAVEAT: This sample is to demonstrate azure IoT client concepts only and is not a guide design principles or style +// Checking of return codes and error values shall be omitted for brevity. Please practice sound engineering practices +// when writing production code. + +#ifndef DONT_USE_UPLOADTOBLOB + +#include +#include + +/* This sample uses the _LL APIs of iothub_client for example purposes. +That does not mean that HTTP only works with the _LL APIs. +Simply changing the using the convenience layer (functions not having _LL) +and removing calls to _DoWork will yield the same results. */ + +#include "iothub.h" +#include "iothub_device_client.h" + +#include "azure_c_shared_utility/shared_util_options.h" +#include "iothub_message.h" +#include "iothubtransportmqtt.h" + +#ifdef SET_TRUSTED_CERT_IN_SAMPLES +#include "certs.h" +#endif // SET_TRUSTED_CERT_IN_SAMPLES + +/*String containing Hostname, Device Id & Device Key in the format: */ +/* "HostName=;DeviceId=;SharedAccessKey=" */ +/* "HostName=;DeviceId=;SharedAccessSignature=" */ +static const char* connectionString = "[device connection string]"; + +/*Optional string with http proxy host and integer for http proxy port (Linux only) */ +static const char* proxyHost = NULL; +static int proxyPort = 0; + +static const char* data_to_upload_format = "Hello World from iothub_client_sample_upload_to_blob_custom: %d\n"; +static char data_to_upload[128]; + +int main(void) +{ + IOTHUB_DEVICE_CLIENT_LL_HANDLE device_ll_handle; + + // Used to initialize IoTHub SDK subsystem + (void)IoTHub_Init(); + (void)printf("Starting the IoTHub client sample upload to blob...\r\n"); + + device_ll_handle = IoTHubDeviceClient_LL_CreateFromConnectionString(connectionString, MQTT_Protocol); + if (device_ll_handle == NULL) + { + (void)printf("Failure creating IotHub device. Hint: Check your connection string.\r\n"); + } + else + { +#ifndef WIN32 + size_t log = 1; + (void)IoTHubDeviceClient_LL_SetOption(device_ll_handle, OPTION_CURL_VERBOSE, &log); +#endif // !WIN32 + +#ifdef SET_TRUSTED_CERT_IN_SAMPLES + // Setting the Trusted Certificate. This is only necessary on systems without + // built in certificate stores. + IoTHubDeviceClient_LL_SetOption(device_ll_handle, OPTION_TRUSTED_CERT, certificates); +#endif // SET_TRUSTED_CERT_IN_SAMPLES + + HTTP_PROXY_OPTIONS http_proxy_options = { 0 }; + http_proxy_options.host_address = proxyHost; + http_proxy_options.port = proxyPort; + + if (proxyHost != NULL && IoTHubDeviceClient_LL_SetOption(device_ll_handle, OPTION_HTTP_PROXY, &http_proxy_options) != IOTHUB_CLIENT_OK) + { + (void)printf("failure to set proxy\n"); + } + else + { + IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle = IoTHubDeviceClient_LL_CreateUploadContext(device_ll_handle, "subdir/hello_world_custom_mb.txt"); + + if (uploadContextHandle == NULL) + { + (void)printf("hello world failed to create upload context\n"); + } + else + { + bool uploadSuccessful = true; + int uploadResultCode = 200; + + for (uint32_t block_number = 0; block_number < 100; block_number++) + { + int data_size = snprintf(data_to_upload, sizeof(data_to_upload), data_to_upload_format, block_number); + + if (IoTHubDeviceClient_LL_UploadBlockToBlob( + uploadContextHandle, block_number, (const uint8_t*)data_to_upload, data_size) != IOTHUB_CLIENT_OK) + { + (void)printf("Failed uploading block number %u to blob. Aborting upload.\n", block_number); + uploadSuccessful = false; + uploadResultCode = 300; + break; + } + } + + // Hint: here if there is a failure (e.g., in HTTP transport) + // this function can be called again in a retry loop if desired. + if (IoTHubDeviceClient_LL_CompleteUploadToBlob( + uploadContextHandle, uploadSuccessful, uploadResultCode, uploadSuccessful ? "OK" : "Aborted") + != IOTHUB_CLIENT_OK) + { + (void)printf("Failed notifying Azure IoT Hub of upload completion.\n"); + } + else + { + (void)printf("hello world has been created\n"); + } + + IoTHubDeviceClient_LL_DestroyUploadContext(uploadContextHandle); + } + } + // Clean up the iothub sdk handle + IoTHubDeviceClient_LL_Destroy(device_ll_handle); + } + // Free all the sdk subsystem + IoTHub_Deinit(); + + printf("Press any key to continue"); + (void)getchar(); + + return 0; +} +#endif /*DONT_USE_UPLOADTOBLOB*/ diff --git a/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/linux/CMakeLists.txt b/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/linux/CMakeLists.txt new file mode 100644 index 0000000000..0ee7c49a9a --- /dev/null +++ b/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/linux/CMakeLists.txt @@ -0,0 +1,29 @@ +#Copyright (c) Microsoft. All rights reserved. +#Licensed under the MIT license. See LICENSE file in the project root for full license information. + +cmake_minimum_required(VERSION 3.5) + +cmake_policy(SET CMP0074 NEW) +cmake_policy(SET CMP0012 NEW) + +project(iothub_client_sample_upload_to_blob_custom) + +if(WIN32) + message(FATAL_ERROR "This CMake file only supports Linux builds!") +endif() + +find_package(azure_iot_sdks REQUIRED) + +add_definitions(-DSET_TRUSTED_CERT_IN_SAMPLES) +include_directories("../../../../certs") + +set(iothub_client_sample_upload_to_blob_custom_c_files + ../iothub_client_sample_upload_to_blob_custom.c + ../../../../certs/certs.c +) + +add_executable(iothub_client_sample_upload_to_blob_custom ${iothub_client_sample_upload_to_blob_custom_c_files}) + +target_link_libraries(iothub_client_sample_upload_to_blob_custom + iothub_client +) diff --git a/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/windows/iothub_client_sample_upload_to_blob.sln b/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/windows/iothub_client_sample_upload_to_blob.sln new file mode 100644 index 0000000000..6868d80a76 --- /dev/null +++ b/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/windows/iothub_client_sample_upload_to_blob.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.23107.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "iothub_client_sample_upload_to_blob", "iothub_client_sample_upload_to_blob.vcxproj", "{8BE6464E-75F3-4748-B33D-85598A74B18B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8BE6464E-75F3-4748-B33D-85598A74B18B}.Debug|Win32.ActiveCfg = Debug|Win32 + {8BE6464E-75F3-4748-B33D-85598A74B18B}.Debug|Win32.Build.0 = Debug|Win32 + {8BE6464E-75F3-4748-B33D-85598A74B18B}.Debug|x64.ActiveCfg = Debug|x64 + {8BE6464E-75F3-4748-B33D-85598A74B18B}.Debug|x64.Build.0 = Debug|x64 + {8BE6464E-75F3-4748-B33D-85598A74B18B}.Release|Win32.ActiveCfg = Release|Win32 + {8BE6464E-75F3-4748-B33D-85598A74B18B}.Release|Win32.Build.0 = Release|Win32 + {8BE6464E-75F3-4748-B33D-85598A74B18B}.Release|x64.ActiveCfg = Release|x64 + {8BE6464E-75F3-4748-B33D-85598A74B18B}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/windows/iothub_client_sample_upload_to_blob.vcxproj b/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/windows/iothub_client_sample_upload_to_blob.vcxproj new file mode 100644 index 0000000000..2640902a4b --- /dev/null +++ b/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/windows/iothub_client_sample_upload_to_blob.vcxproj @@ -0,0 +1,172 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {8BE6464E-75F3-4748-B33D-85598A74B18B} + Win32Proj + iothub_client_sample_upload_to_blob + + + + Application + true + v141 + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + ..\..\..\..\certs;$(IncludePath) + + + true + ..\..\..\..\certs;$(IncludePath) + + + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + ..\..\..\..\certs;$(IncludePath) + + + false + ..\..\..\..\certs;$(IncludePath) + + + + + + Level3 + Disabled + GB_MEASURE_MEMORY_FOR_THIS;GB_DEBUG_ALLOC;WIN32;_CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\;$(VcpkgRoot)\installed\$(VcpkgTriplet)\include\azureiot; + + + Console + true + rpcrt4.lib;ncrypt.lib;crypt32.lib;winhttp.lib;secur32.lib;ws2_32.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + GB_MEASURE_MEMORY_FOR_THIS;GB_DEBUG_ALLOC;WIN32;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\;$(VcpkgRoot)\installed\$(VcpkgTriplet)\include\azureiot; + + + Console + true + rpcrt4.lib;ncrypt.lib;crypt32.lib;winhttp.lib;secur32.lib;ws2_32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + ..\;$(VcpkgRoot)\installed\$(VcpkgTriplet)\include\azureiot; + + + Console + true + true + true + rpcrt4.lib;ncrypt.lib;crypt32.lib;winhttp.lib;secur32.lib;ws2_32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\;$(VcpkgRoot)\installed\$(VcpkgTriplet)\include\azureiot; + + + Console + true + true + true + rpcrt4.lib;ncrypt.lib;crypt32.lib;winhttp.lib;secur32.lib;ws2_32.lib;%(AdditionalDependencies) + + + + + + + + + + + + + This project references Vcpkg package(s) that are missing on this computer. For more information, see https://github.com/Azure/azure-iot-sdk-c/tree/main/doc/setting_up_vcpkg.md. The missing file is {0}. + + + + diff --git a/iothub_client/samples/iothub_client_sample_upload_to_blob_mb/iothub_client_sample_upload_to_blob_mb.c b/iothub_client/samples/iothub_client_sample_upload_to_blob_mb/iothub_client_sample_upload_to_blob_mb.c index e7151b7867..f73db9719d 100644 --- a/iothub_client/samples/iothub_client_sample_upload_to_blob_mb/iothub_client_sample_upload_to_blob_mb.c +++ b/iothub_client/samples/iothub_client_sample_upload_to_blob_mb/iothub_client_sample_upload_to_blob_mb.c @@ -103,6 +103,11 @@ int main(void) } else { +#ifndef WIN32 + size_t log = 1; + (void)IoTHubDeviceClient_LL_SetOption(device_ll_handle, OPTION_CURL_VERBOSE, &log); +#endif // !WIN32 + #ifdef SET_TRUSTED_CERT_IN_SAMPLES // Setting the Trusted Certificate. This is only necessary on systems without // built in certificate stores. diff --git a/iothub_client/src/blob.c b/iothub_client/src/blob.c index 9aba0cd7ed..2ed82e22db 100644 --- a/iothub_client/src/blob.c +++ b/iothub_client/src/blob.c @@ -13,32 +13,132 @@ #include "azure_c_shared_utility/azure_base64.h" #include "azure_c_shared_utility/shared_util_options.h" -#define HTTP_STATUS_CODE_OK 200 -#define IS_HTTP_STATUS_CODE_SUCCESS(x) ((x) >= 100 && (x) < 300) - static const char blockListXmlBegin[] = "\r\n"; static const char blockListXmlEnd[] = ""; static const char blockListUriMarker[] = "&comp=blocklist"; +static const char blockListLatestTagXmlBegin[] = ""; +static const char blockListLatestTagXmlEnd[] = ""; + +static STRING_HANDLE createBlockIdListXml(SINGLYLINKEDLIST_HANDLE blockIDList) +{ + STRING_HANDLE blockIdListXml; + + if ((blockIdListXml = STRING_construct(blockListXmlBegin)) == NULL) + { + LogError("failed opening Block ID List XML"); + } + else + { + LIST_ITEM_HANDLE listNode = singlylinkedlist_get_head_item(blockIDList); + + while (listNode != NULL) + { + STRING_HANDLE blockIdEncodedString = (STRING_HANDLE)singlylinkedlist_item_get_value(listNode); + + if (!( + (STRING_concat(blockIdListXml, blockListLatestTagXmlBegin) == 0) && + (STRING_concat_with_STRING(blockIdListXml, blockIdEncodedString) == 0) && + (STRING_concat(blockIdListXml, blockListLatestTagXmlEnd) == 0) + )) + { + LogError("failed to concatenate Block ID to XML"); + STRING_delete(blockIdListXml); + blockIdListXml = NULL; + break; + } + + listNode = singlylinkedlist_get_next_item(listNode); + } + + if (blockIdListXml != NULL && + STRING_concat(blockIdListXml, blockListXmlEnd) != 0) + { + LogError("failed closing Block ID List XML"); + STRING_delete(blockIdListXml); + blockIdListXml = NULL; + } + } + + return blockIdListXml; +} + +static bool removeAndDestroyBlockIdsInList(const void* item, const void* match_context, bool* continue_processing) +{ + (void)match_context; + STRING_HANDLE blockId = (STRING_HANDLE)item; + STRING_delete(blockId); + *continue_processing = true; + return true; +} + +HTTPAPIEX_HANDLE Blob_CreateHttpConnection(const char* blobStorageHostname, const char* certificates, HTTP_PROXY_OPTIONS *proxyOptions, const char* networkInterface, const size_t timeoutInMilliseconds) +{ + HTTPAPIEX_HANDLE httpApiExHandle; + + if ((blobStorageHostname == NULL)) + { + LogError("One or more required values is NULL, blobStorageHostname=%p", blobStorageHostname); + httpApiExHandle = NULL; + } + else + { + if ((httpApiExHandle = HTTPAPIEX_Create(blobStorageHostname)) == NULL) + { + LogError("unable to create a HTTPAPIEX_HANDLE"); + } + else if ((timeoutInMilliseconds != 0) && (HTTPAPIEX_SetOption(httpApiExHandle, OPTION_HTTP_TIMEOUT, &timeoutInMilliseconds) == HTTPAPIEX_ERROR)) + { + LogError("unable to set blob transfer timeout"); + HTTPAPIEX_Destroy(httpApiExHandle); + httpApiExHandle = NULL; + } + else if ((certificates != NULL) && (HTTPAPIEX_SetOption(httpApiExHandle, OPTION_TRUSTED_CERT, certificates) == HTTPAPIEX_ERROR)) + { + LogError("failure in setting trusted certificates"); + HTTPAPIEX_Destroy(httpApiExHandle); + httpApiExHandle = NULL; + } + else if ((proxyOptions != NULL && proxyOptions->host_address != NULL) && HTTPAPIEX_SetOption(httpApiExHandle, OPTION_HTTP_PROXY, proxyOptions) == HTTPAPIEX_ERROR) + { + LogError("failure in setting proxy options"); + HTTPAPIEX_Destroy(httpApiExHandle); + httpApiExHandle = NULL; + } + else if ((networkInterface != NULL) && HTTPAPIEX_SetOption(httpApiExHandle, OPTION_CURL_INTERFACE, networkInterface) == HTTPAPIEX_ERROR) + { + LogError("failure in setting network interface"); + HTTPAPIEX_Destroy(httpApiExHandle); + httpApiExHandle = NULL; + } + } + + return httpApiExHandle; +} -BLOB_RESULT Blob_UploadBlock( +void Blob_DestroyHttpConnection(HTTPAPIEX_HANDLE httpApiExHandle) +{ + if (httpApiExHandle != NULL) + { + HTTPAPIEX_Destroy(httpApiExHandle); + } +} + +BLOB_RESULT Blob_PutBlock( HTTPAPIEX_HANDLE httpApiExHandle, const char* relativePath, - BUFFER_HANDLE requestContent, unsigned int blockID, - STRING_HANDLE blockIDList, + BUFFER_HANDLE blockData, + SINGLYLINKEDLIST_HANDLE blockIDList, unsigned int* httpStatus, BUFFER_HANDLE httpResponse) { BLOB_RESULT result; - if (requestContent == NULL || + if (blockData == NULL || blockIDList == NULL || - relativePath == NULL || - httpApiExHandle == NULL || - httpStatus == NULL || - httpResponse == NULL) + httpApiExHandle == NULL) { - LogError("invalid argument detected requestContent=%p blockIDList=%p relativePath=%p httpApiExHandle=%p httpStatus=%p httpResponse=%p", requestContent, blockIDList, relativePath, httpApiExHandle, httpStatus, httpResponse); + LogError("invalid argument detected blockData=%p blockIDList=%p relativePath=%p httpApiExHandle=%p", blockData, blockIDList, relativePath, httpApiExHandle); result = BLOB_ERROR; } else if (blockID > 49999) /*outside the expected range of 000000... 049999*/ @@ -48,15 +148,15 @@ BLOB_RESULT Blob_UploadBlock( } else { - char temp[7]; /*this will contain 000000... 049999*/ - if (sprintf(temp, "%6u", (unsigned int)blockID) != 6) /*produces 000000... 049999*/ + char blockIdString[7]; /*this will contain 000000... 049999*/ + if (sprintf(blockIdString, "%6u", (unsigned int)blockID) != 6) /*produces 000000... 049999*/ { LogError("failed to sprintf"); result = BLOB_ERROR; } else { - STRING_HANDLE blockIdString = Azure_Base64_Encode_Bytes((const unsigned char*)temp, 6); + STRING_HANDLE blockIdEncodedString = Azure_Base64_Encode_Bytes((const unsigned char*)blockIdString, 6); if (blockIdString == NULL) { LogError("unable to Azure_Base64_Encode_Bytes"); @@ -64,32 +164,36 @@ BLOB_RESULT Blob_UploadBlock( } else { + LIST_ITEM_HANDLE newListItem = singlylinkedlist_add(blockIDList, blockIdEncodedString); + /*add the blockId base64 encoded to the XML*/ - if (!( - (STRING_concat(blockIDList, "") == 0) && - (STRING_concat_with_STRING(blockIDList, blockIdString) == 0) && - (STRING_concat(blockIDList, "") == 0) - )) + if (newListItem == NULL) { - LogError("unable to STRING_concat"); + LogError("unable to store block ID"); + STRING_delete(blockIdEncodedString); result = BLOB_ERROR; } else { STRING_HANDLE newRelativePath = STRING_construct(relativePath); + if (newRelativePath == NULL) { LogError("unable to STRING_construct"); + (void)singlylinkedlist_remove(blockIDList, newListItem); + STRING_delete(blockIdEncodedString); result = BLOB_ERROR; } else { if (!( (STRING_concat(newRelativePath, "&comp=block&blockid=") == 0) && - (STRING_concat_with_STRING(newRelativePath, blockIdString) == 0) + (STRING_concat_with_STRING(newRelativePath, blockIdEncodedString) == 0) )) { LogError("unable to STRING concatenate"); + (void)singlylinkedlist_remove(blockIDList, newListItem); + STRING_delete(blockIdEncodedString); result = BLOB_ERROR; } else @@ -99,277 +203,129 @@ BLOB_RESULT Blob_UploadBlock( HTTPAPI_REQUEST_PUT, STRING_c_str(newRelativePath), NULL, - requestContent, + blockData, httpStatus, NULL, httpResponse) != HTTPAPIEX_OK ) { LogError("unable to HTTPAPIEX_ExecuteRequest"); + (void)singlylinkedlist_remove(blockIDList, newListItem); + STRING_delete(blockIdEncodedString); result = BLOB_HTTP_ERROR; } - else if (!IS_HTTP_STATUS_CODE_SUCCESS(*httpStatus)) - { - LogError("HTTP status from storage does not indicate success (%d)", (int)*httpStatus); - result = BLOB_OK; - } else { result = BLOB_OK; } } + STRING_delete(newRelativePath); } } - STRING_delete(blockIdString); } } } return result; } - -// InvokeUserCallbackAndSendBlobs invokes the application's getDataCallbackEx as many time as callback requests and, for each call, -// sends the blob contents to the server. -static BLOB_RESULT InvokeUserCallbackAndSendBlobs(HTTPAPIEX_HANDLE httpApiExHandle, const char* relativePath, STRING_HANDLE blockIDList, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX getDataCallbackEx, void* context, unsigned int* httpStatus, BUFFER_HANDLE httpResponse) +void Blob_ClearBlockIdList(SINGLYLINKEDLIST_HANDLE blockIdList) { - BLOB_RESULT result; - - unsigned int blockID = 0; /* incremented for each new block */ - unsigned int isError = 0; /* set to 1 if a block upload fails or if getDataCallbackEx returns incorrect blocks to upload */ - unsigned int uploadOneMoreBlock = 1; /* set to 1 while getDataCallbackEx returns correct blocks to upload */ - unsigned char const * source = NULL; /* data set by getDataCallbackEx */ - size_t size = 0; /* source size set by getDataCallbackEx */ - IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT getDataReturnValue; - - do + if (blockIdList != NULL) { - getDataReturnValue = getDataCallbackEx(FILE_UPLOAD_OK, &source, &size, context); - if (getDataReturnValue == IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_ABORT) + if (singlylinkedlist_remove_if(blockIdList, removeAndDestroyBlockIdsInList, NULL) != 0) { - LogInfo("Upload to blob has been aborted by the user"); - uploadOneMoreBlock = 0; - result = BLOB_ABORTED; - } - else if (source == NULL || size == 0) - { - uploadOneMoreBlock = 0; - result = BLOB_OK; - *httpStatus = HTTP_STATUS_CODE_OK; - } - else - { - if (size > BLOCK_SIZE) - { - LogError("tried to upload block of size %lu, max allowed size is %d", (unsigned long)size, BLOCK_SIZE); - result = BLOB_INVALID_ARG; - isError = 1; - } - else if (blockID >= MAX_BLOCK_COUNT) - { - LogError("unable to upload more than %lu blocks in one blob", (unsigned long)MAX_BLOCK_COUNT); - result = BLOB_INVALID_ARG; - isError = 1; - } - else - { - BUFFER_HANDLE requestContent = BUFFER_create(source, size); - if (requestContent == NULL) - { - LogError("unable to BUFFER_create"); - result = BLOB_ERROR; - isError = 1; - } - else - { - result = Blob_UploadBlock( - httpApiExHandle, - relativePath, - requestContent, - blockID, - blockIDList, - httpStatus, - httpResponse); - - BUFFER_delete(requestContent); - } - - if (result != BLOB_OK) - { - LogError("unable to Blob_UploadBlock. Returned value=%d", result); - isError = 1; - } - else if (!IS_HTTP_STATUS_CODE_SUCCESS(*httpStatus)) - { - LogError("unable to Blob_UploadBlock. Returned httpStatus=%u", (unsigned int)*httpStatus); - isError = 1; - } - } - blockID++; + LogError("Failed clearing block ID list"); } } - while(uploadOneMoreBlock && !isError); - - return result; } -// SendBlockIdList to send an XML of uploaded blockIds to the server after the application's payload block(s) have been transferred. -static BLOB_RESULT SendBlockIdList(HTTPAPIEX_HANDLE httpApiExHandle, const char* relativePath, STRING_HANDLE blockIDList, unsigned int* httpStatus, BUFFER_HANDLE httpResponse) +// Blob_PutBlockList to send an XML of uploaded blockIds to the server after the application's payload block(s) have been transferred. +BLOB_RESULT Blob_PutBlockList( + HTTPAPIEX_HANDLE httpApiExHandle, + const char* relativePath, + SINGLYLINKEDLIST_HANDLE blockIDList, + unsigned int* httpStatus, + BUFFER_HANDLE httpResponse) { BLOB_RESULT result; - - /*complete the XML*/ - if (STRING_concat(blockIDList, blockListXmlEnd) != 0) + + if (httpApiExHandle == NULL || relativePath == NULL || blockIDList == NULL || httpStatus == NULL) { - LogError("failed to STRING_concat"); - result = BLOB_ERROR; + LogError("Invalid argument (httpApiExHandle=%p, relativePath=%p, blockIDList=%p, httpStatus=%p)", + httpApiExHandle, relativePath, blockIDList, httpStatus); + result = BLOB_INVALID_ARG; + } + else if (singlylinkedlist_get_head_item(blockIDList) == NULL) + { + // Block ID List is empty, there is nothing to be be sent to Azure Blob Storage. + result = BLOB_OK; } else { - STRING_HANDLE newRelativePath = STRING_construct(relativePath); - if (newRelativePath == NULL) + STRING_HANDLE blockIdListXml = createBlockIdListXml(blockIDList); + + /*complete the XML*/ + if (blockIdListXml == NULL) { - LogError("failed to STRING_construct"); + LogError("failed creating Block ID list XML"); result = BLOB_ERROR; } else { - if (STRING_concat(newRelativePath, blockListUriMarker) != 0) + STRING_HANDLE newRelativePath = STRING_construct(relativePath); + + if (newRelativePath == NULL) { - LogError("failed to STRING_concat"); + LogError("failed to STRING_construct"); result = BLOB_ERROR; } else { - const char* s = STRING_c_str(blockIDList); - BUFFER_HANDLE blockIDListAsBuffer = BUFFER_create((const unsigned char*)s, strlen(s)); - if (blockIDListAsBuffer == NULL) + if (STRING_concat(newRelativePath, blockListUriMarker) != 0) { - LogError("failed to BUFFER_create"); + LogError("failed to STRING_concat"); result = BLOB_ERROR; } else { - if (HTTPAPIEX_ExecuteRequest( - httpApiExHandle, - HTTPAPI_REQUEST_PUT, - STRING_c_str(newRelativePath), - NULL, - blockIDListAsBuffer, - httpStatus, - NULL, - httpResponse - ) != HTTPAPIEX_OK) + const char* s = STRING_c_str(blockIdListXml); + BUFFER_HANDLE blockIDListAsBuffer = BUFFER_create((const unsigned char*)s, strlen(s)); + if (blockIDListAsBuffer == NULL) { - LogError("unable to HTTPAPIEX_ExecuteRequest"); - result = BLOB_HTTP_ERROR; + LogError("failed to BUFFER_create"); + result = BLOB_ERROR; } else { - result = BLOB_OK; + if (HTTPAPIEX_ExecuteRequest( + httpApiExHandle, + HTTPAPI_REQUEST_PUT, + STRING_c_str(newRelativePath), + NULL, + blockIDListAsBuffer, + httpStatus, + NULL, + httpResponse + ) != HTTPAPIEX_OK) + { + LogError("unable to HTTPAPIEX_ExecuteRequest"); + result = BLOB_HTTP_ERROR; + } + else + { + (void)singlylinkedlist_remove_if(blockIDList, removeAndDestroyBlockIdsInList, NULL); + result = BLOB_OK; + } + BUFFER_delete(blockIDListAsBuffer); } - BUFFER_delete(blockIDListAsBuffer); } + STRING_delete(newRelativePath); } - STRING_delete(newRelativePath); - } - } - return result; -} - - -BLOB_RESULT Blob_UploadMultipleBlocksFromSasUri(const char* SASURI, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX getDataCallbackEx, void* context, unsigned int* httpStatus, BUFFER_HANDLE httpResponse, const char* certificates, HTTP_PROXY_OPTIONS *proxyOptions, const char* networkInterface, const size_t timeoutInMilliseconds) -{ - BLOB_RESULT result; - const char* hostnameBegin; - STRING_HANDLE blockIDList = NULL; - HTTPAPIEX_HANDLE httpApiExHandle = NULL; - char* hostname = NULL; - - if ((SASURI == NULL) || (getDataCallbackEx == NULL)) - { - LogError("One or more required values is NULL, SASURI=%p, getDataCallbackEx=%p", SASURI, getDataCallbackEx); - result = BLOB_INVALID_ARG; - } - /*to find the hostname, the following logic is applied:*/ - /*the hostname starts at the first character after "://"*/ - /*the hostname ends at the first character before the next "/" after "://"*/ - else if ((hostnameBegin = strstr(SASURI, "://")) == NULL) - { - LogError("hostname cannot be determined"); - result = BLOB_INVALID_ARG; - } - else - { - hostnameBegin += 3; /*have to skip 3 characters which are "://"*/ - const char* relativePath = strchr(hostnameBegin, '/'); - if (relativePath == NULL) - { - LogError("hostname cannot be determined"); - result = BLOB_INVALID_ARG; - } - else - { - size_t hostnameSize = relativePath - hostnameBegin; - if ((hostname = (char*)malloc(hostnameSize + 1)) == NULL) - { - LogError("oom - out of memory"); - result = BLOB_ERROR; - } - else - { - (void)memcpy(hostname, hostnameBegin, hostnameSize); - hostname[hostnameSize] = '\0'; - - httpApiExHandle = HTTPAPIEX_Create(hostname); - if (httpApiExHandle == NULL) - { - LogError("unable to create a HTTPAPIEX_HANDLE"); - result = BLOB_ERROR; - } - else if ((timeoutInMilliseconds != 0) && (HTTPAPIEX_SetOption(httpApiExHandle, OPTION_HTTP_TIMEOUT, &timeoutInMilliseconds) == HTTPAPIEX_ERROR)) - { - LogError("unable to set blob transfer timeout"); - result = BLOB_ERROR; - } - else if ((certificates != NULL) && (HTTPAPIEX_SetOption(httpApiExHandle, OPTION_TRUSTED_CERT, certificates) == HTTPAPIEX_ERROR)) - { - LogError("failure in setting trusted certificates"); - result = BLOB_ERROR; - } - else if ((proxyOptions != NULL && proxyOptions->host_address != NULL) && HTTPAPIEX_SetOption(httpApiExHandle, OPTION_HTTP_PROXY, proxyOptions) == HTTPAPIEX_ERROR) - { - LogError("failure in setting proxy options"); - result = BLOB_ERROR; - } - else if ((networkInterface != NULL) && HTTPAPIEX_SetOption(httpApiExHandle, OPTION_CURL_INTERFACE, networkInterface) == HTTPAPIEX_ERROR) - { - LogError("failure in setting network interface"); - result = BLOB_ERROR; - } - else if ((blockIDList = STRING_construct(blockListXmlBegin)) == NULL) - { - LogError("failed to STRING_construct"); - result = BLOB_HTTP_ERROR; - } - else if ((result = InvokeUserCallbackAndSendBlobs(httpApiExHandle, relativePath, blockIDList, getDataCallbackEx, context, httpStatus, httpResponse)) != BLOB_OK) - { - LogError("Failed in invoking callback/sending blob step"); - } - else if (IS_HTTP_STATUS_CODE_SUCCESS(*httpStatus)) - { - // Per SRS_BLOB_02_026, it possible for us to have a result=BLOB_OK AND a non-success HTTP status code. - // In order to maintain back-compat with existing code, we will return the BLOB_OK to the caller but NOT invoke this final step. - result = SendBlockIdList(httpApiExHandle, relativePath, blockIDList, httpStatus, httpResponse); - } - } + STRING_delete(blockIdListXml); } } - HTTPAPIEX_Destroy(httpApiExHandle); - STRING_delete(blockIDList); - free(hostname); - return result; } diff --git a/iothub_client/src/iothub_client_core.c b/iothub_client/src/iothub_client_core.c index 49b6b5c335..d8d137a552 100644 --- a/iothub_client/src/iothub_client_core.c +++ b/iothub_client/src/iothub_client_core.c @@ -2486,6 +2486,42 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_UploadMultipleBlocksToBlobAsync(IOTHUB_CLI return result; } +IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubClientCore_CreateUploadContext(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, const char* destinationFileName) +{ + IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE result; + + if ( + (iotHubClientHandle == NULL) || + (destinationFileName == NULL)) + { + LogError("invalid parameters iotHubClientHandle = %p , destinationFileName = %p", + iotHubClientHandle, + destinationFileName + ); + result = NULL; + } + else + { + result = IoTHubClientCore_LL_CreateUploadContext(iotHubClientHandle->IoTHubClientLLHandle, destinationFileName); + } + + return result; +} + +IOTHUB_CLIENT_RESULT IoTHubClientCore_UploadBlockToBlob(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle, uint32_t blockNumber, const uint8_t* dataPtr, size_t dataSize) +{ + return IoTHubClientCore_LL_UploadBlockToBlob(uploadContextHandle, blockNumber, dataPtr, dataSize); +} + +IOTHUB_CLIENT_RESULT IoTHubClientCore_CompleteUploadToBlob(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle, bool isSuccess, int responseCode, const char* responseMessage) +{ + return IoTHubClientCore_LL_CompleteUploadToBlob(uploadContextHandle, isSuccess, responseCode, responseMessage); +} + +void IoTHubClientCore_DestroyUploadContext(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle) +{ + IoTHubClientCore_LL_DestroyUploadContext(uploadContextHandle); +} #endif /*DONT_USE_UPLOADTOBLOB*/ IOTHUB_CLIENT_RESULT IoTHubClientCore_SendEventToOutputAsync(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, IOTHUB_MESSAGE_HANDLE eventMessageHandle, const char* outputName, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK eventConfirmationCallback, void* userContextCallback) diff --git a/iothub_client/src/iothub_client_core_ll.c b/iothub_client/src/iothub_client_core_ll.c index b166a5fbd9..d26325857e 100755 --- a/iothub_client/src/iothub_client_core_ll.c +++ b/iothub_client/src/iothub_client_core_ll.c @@ -2711,8 +2711,38 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_UploadToBlob(IOTHUB_CLIENT_CORE_LL_HAND } else { - result = IoTHubClient_LL_UploadToBlob_Impl(iotHubClientHandle->uploadToBlobHandle, destinationFileName, source, size); + IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext = IoTHubClient_LL_UploadToBlob_CreateContext(iotHubClientHandle->uploadToBlobHandle, destinationFileName); + + if (uploadContext == NULL) + { + LogError("Failed creating upload to blob context"); + result = IOTHUB_CLIENT_ERROR; + } + else + { + bool uploadSucceeded = true; + + if (IoTHubClient_LL_UploadToBlob_UploadBlock(uploadContext, 0, source, size) != IOTHUB_CLIENT_OK) + { + LogError("Failed uploading block to Azure Blob Storage"); + uploadSucceeded = false; + } + + if (IoTHubClient_LL_UploadToBlob_Complete( + uploadContext, uploadSucceeded, (uploadSucceeded ? 200 : 400), NULL) != IOTHUB_CLIENT_OK) + { + LogError("Failed completing upload to blob."); + result = IOTHUB_CLIENT_ERROR; + } + else + { + result = (uploadSucceeded ? IOTHUB_CLIENT_OK : IOTHUB_CLIENT_ERROR); + } + + IoTHubClient_LL_UploadToBlob_DestroyContext(uploadContext); + } } + return result; } @@ -2744,12 +2774,25 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_UploadMultipleBlocksToBlob(IOTHUB_CLIEN } else { - UPLOAD_MULTIPLE_BLOCKS_WRAPPER_CONTEXT uploadMultipleBlocksWrapperContext; - uploadMultipleBlocksWrapperContext.getDataCallback = getDataCallback; - uploadMultipleBlocksWrapperContext.context = context; + IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle = IoTHubClient_LL_UploadToBlob_CreateContext(iotHubClientHandle->uploadToBlobHandle, destinationFileName); - result = IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl(iotHubClientHandle->uploadToBlobHandle, destinationFileName, uploadMultipleBlocksCallbackWrapper, &uploadMultipleBlocksWrapperContext); + if (uploadContextHandle == NULL) + { + LogError("Failed creating upload to blob context"); + result = IOTHUB_CLIENT_ERROR; + } + else + { + UPLOAD_MULTIPLE_BLOCKS_WRAPPER_CONTEXT uploadMultipleBlocksWrapperContext; + uploadMultipleBlocksWrapperContext.getDataCallback = getDataCallback; + uploadMultipleBlocksWrapperContext.context = context; + + result = IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(uploadContextHandle, uploadMultipleBlocksCallbackWrapper, &uploadMultipleBlocksWrapperContext); + + IoTHubClient_LL_UploadToBlob_DestroyContext(uploadContextHandle); + } } + return result; } @@ -2767,10 +2810,90 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx(IOTHUB_CLI } else { - result = IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl(iotHubClientHandle->uploadToBlobHandle, destinationFileName, getDataCallbackEx, context); + IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle = IoTHubClient_LL_UploadToBlob_CreateContext(iotHubClientHandle->uploadToBlobHandle, destinationFileName); + + if (uploadContextHandle == NULL) + { + LogError("Failed creating upload to blob context"); + result = IOTHUB_CLIENT_ERROR; + } + else + { + result = IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(uploadContextHandle, getDataCallbackEx, context); + + IoTHubClient_LL_UploadToBlob_DestroyContext(uploadContextHandle); + } } + return result; } + +IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubClientCore_LL_CreateUploadContext(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, const char* destinationFileName) +{ + IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE result; + if ( + (iotHubClientHandle == NULL) || + (destinationFileName == NULL) + ) + { + LogError("invalid parameters IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle=%p, destinationFileName=%p", iotHubClientHandle, destinationFileName); + result = NULL; + } + else + { + result = IoTHubClient_LL_UploadToBlob_CreateContext(iotHubClientHandle->uploadToBlobHandle, destinationFileName); + } + + return result; +} + +IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_UploadBlockToBlob(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle, uint32_t blockNumber, const uint8_t* dataPtr, size_t dataSize) +{ + IOTHUB_CLIENT_RESULT result; + + if ( + (uploadContextHandle == NULL) || + (dataPtr == NULL) || + (dataSize == 0) + ) + { + LogError("invalid parameters uploadContextHandle=%p, dataPtr=%p, dataSize=%zu", uploadContextHandle, dataPtr, dataSize); + result = IOTHUB_CLIENT_INVALID_ARG; + } + else + { + result = IoTHubClient_LL_UploadToBlob_UploadBlock(uploadContextHandle, blockNumber, dataPtr, dataSize); + } + + return result; +} + +IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_CompleteUploadToBlob(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle, bool isSuccess, int responseCode, const char* responseMessage) +{ + IOTHUB_CLIENT_RESULT result; + + if ( + (uploadContextHandle == NULL) + ) + { + LogError("invalid parameters uploadContextHandle=%p", uploadContextHandle); + result = IOTHUB_CLIENT_INVALID_ARG; + } + else + { + result = IoTHubClient_LL_UploadToBlob_Complete(uploadContextHandle, isSuccess, responseCode, responseMessage); + } + + return result; +} + +void IoTHubClientCore_LL_DestroyUploadContext(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle) +{ + if (uploadContextHandle != NULL) + { + IoTHubClient_LL_UploadToBlob_DestroyContext(uploadContextHandle); + } +} #endif // DONT_USE_UPLOADTOBLOB IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SendEventToOutputAsync(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, IOTHUB_MESSAGE_HANDLE eventMessageHandle, const char* outputName, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK eventConfirmationCallback, void* userContextCallback) diff --git a/iothub_client/src/iothub_client_ll_uploadtoblob.c b/iothub_client/src/iothub_client_ll_uploadtoblob.c index 1c5719fd92..2cd093da15 100644 --- a/iothub_client/src/iothub_client_ll_uploadtoblob.c +++ b/iothub_client/src/iothub_client_ll_uploadtoblob.c @@ -29,8 +29,11 @@ static const char* const RESPONSE_BODY_FORMAT = "{\"correlationId\":\"%s\", \"isSuccess\":%s, \"statusCode\":%d, \"statusDescription\":\"%s\"}"; static const char* const RESPONSE_BODY_ABORTED_MESSAGE = "file upload aborted"; -static const char* const RESPONSE_BODY_FAILED_MESSAGE = "client not able to connect with the server"; +static const char* const RESPONSE_BODY_BLOCK_SIZE_EXCEEDED_MESSAGE = "block data size exceeded"; +static const char* const RESPONSE_BODY_BLOCK_COUNT_EXCEEDED_MESSAGE = "block count exceeded"; +static const char* const RESPONSE_BODY_UPLOAD_FAILED_MESSAGE = "block upload failed"; static const int RESPONSE_BODY_ERROR_RETURN_CODE = -1; +static const char* const RESPONSE_BODY_SUCCESS_BOOLEAN_STRING = "true"; static const char* const RESPONSE_BODY_ERROR_BOOLEAN_STRING = "false"; #define INDEFINITE_TIME ((time_t)-1) @@ -39,6 +42,10 @@ static const char* const EMPTY_STRING = ""; static const char* const HEADER_AUTHORIZATION = "Authorization"; static const char* const HEADER_APP_JSON = "application/json"; +#define HTTP_STATUS_CODE_OK 200 +#define HTTP_STATUS_CODE_BAD_REQUEST 400 +#define IS_HTTP_STATUS_CODE_SUCCESS(x) ((x) >= 100 && (x) < 300) + typedef struct UPLOADTOBLOB_X509_CREDENTIALS_TAG { char* x509certificate; @@ -69,10 +76,10 @@ typedef struct IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA_TAG char* certificates; HTTP_PROXY_OPTIONS http_proxy_options; UPLOADTOBLOB_CURL_VERBOSITY curl_verbosity_level; - size_t blob_upload_timeout_secs; + size_t blob_upload_timeout_millisecs; const char* networkInterface; bool tls_renegotiation; -}IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA; +} IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA; typedef struct BLOB_UPLOAD_CONTEXT_TAG { @@ -81,36 +88,65 @@ typedef struct BLOB_UPLOAD_CONTEXT_TAG size_t remainingSizeToUpload; /* size not yet uploaded */ } BLOB_UPLOAD_CONTEXT; -static int send_http_sas_request(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_client, const char* uri_resource, HTTPAPIEX_HANDLE http_api_handle, const char* relative_path, HTTP_HEADERS_HANDLE request_header, BUFFER_HANDLE blobBuffer, BUFFER_HANDLE response_buff) +typedef struct IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_STRUCT +{ + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* u2bClientData; + + /* ID of the upload as provided by the Azure IoT Hub */ + STRING_HANDLE correlationId; + char* blobStorageHostname; + char* blobStorageRelativePath; + SINGLYLINKEDLIST_HANDLE blockIdList; + + HTTPAPIEX_HANDLE blobHttpApiHandle; +} IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT; + +static int send_http_sas_request(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_client, HTTPAPIEX_HANDLE http_api_handle, const char* relative_path, HTTP_HEADERS_HANDLE request_header, BUFFER_HANDLE blobBuffer, BUFFER_HANDLE response_buff) { int result; - unsigned int statusCode; + STRING_HANDLE uri_resource = STRING_construct_sprintf("%s/devices/%s", upload_client->hostname, upload_client->deviceId); - HTTPAPIEX_SAS_HANDLE http_sas_handle = HTTPAPIEX_SAS_Create_From_String(IoTHubClient_Auth_Get_DeviceKey(upload_client->authorization_module), uri_resource, EMPTY_STRING); - if (http_sas_handle == NULL) + if (uri_resource == NULL) { - LogError("unable to HTTPAPIEX_SAS_Create"); + LogError("Failure constructing uri string"); result = MU_FAILURE; } else { - if (HTTPAPIEX_SAS_ExecuteRequest(http_sas_handle, http_api_handle, HTTPAPI_REQUEST_POST, relative_path, request_header, - blobBuffer, &statusCode, NULL, response_buff) != HTTPAPIEX_OK) - { - result = MU_FAILURE; - LogError("unable to HTTPAPIEX_ExecuteRequest"); - } - else if (statusCode >= 300) + HTTPAPIEX_SAS_HANDLE http_sas_handle = HTTPAPIEX_SAS_Create_From_String(IoTHubClient_Auth_Get_DeviceKey(upload_client->authorization_module), STRING_c_str(uri_resource), EMPTY_STRING); + + if (http_sas_handle == NULL) { + LogError("unable to HTTPAPIEX_SAS_Create"); result = MU_FAILURE; - LogError("HTTP code was %u", statusCode); } else { - result = 0; + unsigned int statusCode; + + if (HTTPAPIEX_SAS_ExecuteRequest( + http_sas_handle, http_api_handle, HTTPAPI_REQUEST_POST, relative_path, request_header, + blobBuffer, &statusCode, NULL, response_buff) != HTTPAPIEX_OK) + { + LogError("unable to HTTPAPIEX_ExecuteRequest"); + result = MU_FAILURE; + } + else if (!IS_HTTP_STATUS_CODE_SUCCESS(statusCode)) + { + LogError("HTTP response code was %u", statusCode); + result = MU_FAILURE; + } + else + { + result = 0; + } + + HTTPAPIEX_SAS_Destroy(http_sas_handle); } - HTTPAPIEX_SAS_Destroy(http_sas_handle); + + STRING_delete(uri_resource); } + return result; } @@ -121,22 +157,23 @@ static int send_http_request(HTTPAPIEX_HANDLE http_api_handle, const char* relat if (HTTPAPIEX_ExecuteRequest(http_api_handle, HTTPAPI_REQUEST_POST, relative_path, request_header, blobBuffer, &statusCode, NULL, response_buff) != HTTPAPIEX_OK) { - result = MU_FAILURE; LogError("unable to HTTPAPIEX_ExecuteRequest"); + result = MU_FAILURE; } - else if (statusCode >= 300) + else if (!IS_HTTP_STATUS_CODE_SUCCESS(statusCode)) { - result = MU_FAILURE; LogError("HTTP code was %u", statusCode); + result = MU_FAILURE; } else { result = 0; } + return result; } -static int parse_result_json(const char* json_response, STRING_HANDLE correlation_id, STRING_HANDLE sas_uri) +static int parseResultFromIoTHub(const char* json_response, STRING_HANDLE correlation_id, STRING_HANDLE sas_uri) { int result; @@ -202,19 +239,549 @@ static int parse_result_json(const char* json_response, STRING_HANDLE correlatio } else if (STRING_copy(correlation_id, json_corr_id) != 0) { - LogError("unable to copy correlation Id"); + LogError("unable to copy correlation Id"); + result = MU_FAILURE; + STRING_empty(sas_uri); + } + else + { + result = 0; + } + STRING_delete(filename); + } + } + json_value_free(json); + } + return result; +} + + +static HTTP_HEADERS_HANDLE createIotHubRequestHttpHeaders(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_data) +{ + HTTP_HEADERS_HANDLE iotHubRequestHttpHeaders; + + if ((iotHubRequestHttpHeaders = HTTPHeaders_Alloc()) == NULL) + { + LogError("Failed to allocate HTTP headers for IoT Hub connection"); + } + else + { + bool isError; + + if ((HTTPHeaders_AddHeaderNameValuePair(iotHubRequestHttpHeaders, "Content-Type", HEADER_APP_JSON) != HTTP_HEADERS_OK) || + (HTTPHeaders_AddHeaderNameValuePair(iotHubRequestHttpHeaders, "Accept", HEADER_APP_JSON) != HTTP_HEADERS_OK) || + (HTTPHeaders_AddHeaderNameValuePair(iotHubRequestHttpHeaders, "User-Agent", "iothubclient/" IOTHUB_SDK_VERSION) != HTTP_HEADERS_OK)) + { + LogError("unable to HTTPHeaders_AddHeaderNameValuePair"); + isError = true; + } + else + { + switch (upload_data->cred_type) + { + default: + { + LogError("Internal Error: unexpected value in auth schema = %d", upload_data->cred_type); + isError = true; + break; + } + case IOTHUB_CREDENTIAL_TYPE_X509_ECC: + case IOTHUB_CREDENTIAL_TYPE_X509: + { + isError = false; + break; + } + case IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY: + { + // This is the scenario that uses `send_http_sas_request`. + // Believe it or not, HTTPAPIEX_SAS_ExecuteRequest requires the headers to have + // an empty Authorization header so it can replace it with the authorization value. + + if (HTTPHeaders_AddHeaderNameValuePair(iotHubRequestHttpHeaders, HEADER_AUTHORIZATION, EMPTY_STRING) != HTTP_HEADERS_OK) + { + LogError("unable to add authorization header"); + isError = true; + } + else + { + isError = false; + } + break; + } + case IOTHUB_CREDENTIAL_TYPE_DEVICE_AUTH: + { + STRING_HANDLE uri_resource = STRING_construct_sprintf("%s/devices/%s", upload_data->hostname, upload_data->deviceId); + + if (uri_resource == NULL) + { + LogError("Failure constructing uri string"); + isError = true; + } + else + { + time_t curr_time; + if ((curr_time = get_time(NULL)) == INDEFINITE_TIME) + { + LogError("failure retrieving time"); + isError = true; + } + else + { + uint64_t expiry = (uint64_t)(difftime(curr_time, 0) + 3600); + char* sas_token = IoTHubClient_Auth_Get_SasToken(upload_data->authorization_module, STRING_c_str(uri_resource), expiry, EMPTY_STRING); + + if (sas_token == NULL) + { + LogError("unable to retrieve sas token"); + isError = true; + } + else + { + if (HTTPHeaders_AddHeaderNameValuePair(iotHubRequestHttpHeaders, HEADER_AUTHORIZATION, sas_token) != HTTP_HEADERS_OK) + { + LogError("unable to HTTPHeaders_AddHeaderNameValuePair"); + isError = true; + } + else + { + isError = false; + } + + free(sas_token); + } + } + + STRING_delete(uri_resource); + } + + break; + } + case IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN: + { + if (HTTPHeaders_AddHeaderNameValuePair(iotHubRequestHttpHeaders, HEADER_AUTHORIZATION, upload_data->credentials.supplied_sas_token) != HTTP_HEADERS_OK) + { + LogError("unable to add authorization header"); + isError = true; + } + else + { + isError = false; + } + break; + } + } + } + + if (isError) + { + HTTPHeaders_Free(iotHubRequestHttpHeaders); + iotHubRequestHttpHeaders = NULL; + } + } + + return iotHubRequestHttpHeaders; +} + +static HTTPAPIEX_HANDLE createIotHubHttpApiExHandle(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* u2bLLClientData) +{ + HTTPAPIEX_HANDLE iotHubHttpApiExHandle = HTTPAPIEX_Create(u2bLLClientData->hostname); + + if (iotHubHttpApiExHandle == NULL) + { + LogError("unable to HTTPAPIEX_Create"); + } + else if (u2bLLClientData->blob_upload_timeout_millisecs != 0 && + HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_HTTP_TIMEOUT, &u2bLLClientData->blob_upload_timeout_millisecs) != HTTPAPIEX_OK) + { + LogError("unable to set blob transfer timeout"); + HTTPAPIEX_Destroy(iotHubHttpApiExHandle); + iotHubHttpApiExHandle = NULL; + } + else + { + if (u2bLLClientData->curl_verbosity_level != UPLOADTOBLOB_CURL_VERBOSITY_UNSET) + { + size_t curl_verbose = (u2bLLClientData->curl_verbosity_level == UPLOADTOBLOB_CURL_VERBOSITY_ON); + (void)HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_CURL_VERBOSE, &curl_verbose); + } + + if ((u2bLLClientData->networkInterface) != NULL && + (HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_CURL_INTERFACE, u2bLLClientData->networkInterface) != HTTPAPIEX_OK)) + { + LogError("unable to set networkInteface!"); + HTTPAPIEX_Destroy(iotHubHttpApiExHandle); + iotHubHttpApiExHandle = NULL; + } + else + { + /*transmit the x509certificate and x509privatekey*/ + if ((u2bLLClientData->cred_type == IOTHUB_CREDENTIAL_TYPE_X509 || u2bLLClientData->cred_type == IOTHUB_CREDENTIAL_TYPE_X509_ECC) && + (((u2bLLClientData->tls_renegotiation == true) && (HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_SET_TLS_RENEGOTIATION, &u2bLLClientData->tls_renegotiation) != HTTPAPIEX_OK)) || + (HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_X509_CERT, u2bLLClientData->credentials.x509_credentials.x509certificate) != HTTPAPIEX_OK) || + (HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_X509_PRIVATE_KEY, u2bLLClientData->credentials.x509_credentials.x509privatekey) != HTTPAPIEX_OK) || + ((u2bLLClientData->credentials.x509_credentials.x509privatekeyType != NULL) && (HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_OPENSSL_PRIVATE_KEY_TYPE, u2bLLClientData->credentials.x509_credentials.x509privatekeyType) != HTTPAPIEX_OK)) || + ((u2bLLClientData->credentials.x509_credentials.engine != NULL) && (HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_OPENSSL_ENGINE, u2bLLClientData->credentials.x509_credentials.engine) != HTTPAPIEX_OK)))) + { + LogError("unable to HTTPAPIEX_SetOption for x509 certificate"); + HTTPAPIEX_Destroy(iotHubHttpApiExHandle); + iotHubHttpApiExHandle = NULL; + } + else if ((u2bLLClientData->certificates != NULL) && + (HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_TRUSTED_CERT, u2bLLClientData->certificates) != HTTPAPIEX_OK)) + { + LogError("unable to set TrustedCerts!"); + HTTPAPIEX_Destroy(iotHubHttpApiExHandle); + iotHubHttpApiExHandle = NULL; + } + else if ((u2bLLClientData->http_proxy_options.host_address != NULL) && + (HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_HTTP_PROXY, &(u2bLLClientData->http_proxy_options)) != HTTPAPIEX_OK)) + { + LogError("unable to set http proxy!"); + HTTPAPIEX_Destroy(iotHubHttpApiExHandle); + iotHubHttpApiExHandle = NULL; + } + } + } + + return iotHubHttpApiExHandle; +} + +static int IoTHubClient_LL_UploadToBlob_GetBlobCredentialsFromIoTHub(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_data, const char* destinationFileName, STRING_HANDLE correlationId, STRING_HANDLE sasUri) +{ + int result; + STRING_HANDLE relativePath = STRING_construct_sprintf("/devices/%s/files/%s", upload_data->deviceId, API_VERSION); + + if (relativePath == NULL) + { + LogError("Failure constructing string"); + result = MU_FAILURE; + } + else + { + STRING_HANDLE blobName = STRING_construct_sprintf("{ \"blobName\": \"%s\" }", destinationFileName); + + if (blobName == NULL) + { + LogError("Failure constructing string"); + result = MU_FAILURE; + } + else + { + BUFFER_HANDLE blobBuffer = BUFFER_create( + (const unsigned char *)STRING_c_str(blobName), STRING_length(blobName)); + + if (blobBuffer == NULL) + { + LogError("unable to create BUFFER"); + result = MU_FAILURE; + } + else + { + BUFFER_HANDLE responseContent; + + if ((responseContent = BUFFER_new()) == NULL) + { + result = MU_FAILURE; + LogError("unable to BUFFER_new"); + } + else + { + HTTPAPIEX_HANDLE iotHubHttpApiExHandle = createIotHubHttpApiExHandle(upload_data); + + if (iotHubHttpApiExHandle == NULL) + { + LogError("Failed to create the HTTPAPIEX_HANDLE for Azure IoT Hub"); + result = MU_FAILURE; + } + else + { + HTTP_HEADERS_HANDLE iotHubRequestHttpHeaders; + + if ((iotHubRequestHttpHeaders = createIotHubRequestHttpHeaders(upload_data)) == NULL) + { + LogError("Failed to allocate HTTP headers for IoT Hub connection"); + result = MU_FAILURE; + } + else + { + bool wasIoTHubRequestSuccess = false; + + switch (upload_data->cred_type) + { + default: + { + LogError("Internal Error: unexpected value in auth schema = %d", upload_data->cred_type); + break; + } + case IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN: + case IOTHUB_CREDENTIAL_TYPE_DEVICE_AUTH: + case IOTHUB_CREDENTIAL_TYPE_X509_ECC: + case IOTHUB_CREDENTIAL_TYPE_X509: + { + if (send_http_request(iotHubHttpApiExHandle, STRING_c_str(relativePath), iotHubRequestHttpHeaders, blobBuffer, responseContent) != 0) + { + LogError("unable to HTTPAPIEX_ExecuteRequest"); + } + else + { + wasIoTHubRequestSuccess = true; + } + break; + } + case IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY: + { + if (send_http_sas_request(upload_data, iotHubHttpApiExHandle, STRING_c_str(relativePath), iotHubRequestHttpHeaders, blobBuffer, responseContent) != 0) + { + LogError("unable to HTTPAPIEX_ExecuteRequest"); + } + else + { + wasIoTHubRequestSuccess = true; + } + + break; + } + } + + if (wasIoTHubRequestSuccess) + { + const unsigned char* responseContent_u_char = BUFFER_u_char(responseContent); + size_t responseContent_length = BUFFER_length(responseContent); + STRING_HANDLE responseAsString = STRING_from_byte_array(responseContent_u_char, responseContent_length); + if (responseAsString == NULL) + { + LogError("unable to get the response as string"); + result = MU_FAILURE; + } + else + { + if (parseResultFromIoTHub(STRING_c_str(responseAsString), correlationId, sasUri) != 0) + { + LogError("unable to parse json result"); + result = MU_FAILURE; + } + else + { + result = 0; + } + + STRING_delete(responseAsString); + } + } + else + { + result = MU_FAILURE; + } + + HTTPHeaders_Free(iotHubRequestHttpHeaders); + } + + HTTPAPIEX_Destroy(iotHubHttpApiExHandle); + } + + BUFFER_delete(responseContent); + } + + BUFFER_delete(blobBuffer); + } + + STRING_delete(blobName); + } + + STRING_delete(relativePath); + } + + return result; +} + +static int IoTHubClient_LL_UploadToBlob_NotifyIoTHubOfUploadCompletion(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_data, BUFFER_HANDLE messageBody) +{ + int result; + STRING_HANDLE relativePathNotification = STRING_construct_sprintf("/devices/%s/files/notifications/%s", upload_data->deviceId, API_VERSION); + + if (relativePathNotification == NULL) + { + LogError("Failure constructing relative path string"); + result = MU_FAILURE; + } + else + { + HTTPAPIEX_HANDLE iotHubHttpApiExHandle = createIotHubHttpApiExHandle(upload_data); + + if (iotHubHttpApiExHandle == NULL) + { + LogError("Failed to create the HTTPAPIEX_HANDLE for Azure IoT Hub"); + result = MU_FAILURE; + } + else + { + HTTP_HEADERS_HANDLE iotHubRequestHttpHeaders; + + if ((iotHubRequestHttpHeaders = createIotHubRequestHttpHeaders(upload_data)) == NULL) + { + LogError("Failed to allocate HTTP headers for IoT Hub connection"); + result = MU_FAILURE; + } + else + { + switch (upload_data->cred_type) + { + default: + { + LogError("internal error: unknown authorization Scheme"); + result = MU_FAILURE; + break; + } + case IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN: + case IOTHUB_CREDENTIAL_TYPE_X509: + case IOTHUB_CREDENTIAL_TYPE_X509_ECC: + case IOTHUB_CREDENTIAL_TYPE_DEVICE_AUTH: + { + if (send_http_request(iotHubHttpApiExHandle, STRING_c_str(relativePathNotification), iotHubRequestHttpHeaders, messageBody, NULL) != 0) + { + LogError("unable to execute HTTPAPIEX_ExecuteRequest"); + result = MU_FAILURE; + } + else + { + result = 0; + } + break; + } + case IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY: + { + if (send_http_sas_request(upload_data, iotHubHttpApiExHandle, STRING_c_str(relativePathNotification), iotHubRequestHttpHeaders, messageBody, NULL) != 0) + { + LogError("unable to execute HTTPAPIEX_ExecuteRequest"); + result = MU_FAILURE; + } + else + { + result = 0; + } + break; + } + } + + HTTPHeaders_Free(iotHubRequestHttpHeaders); + } + + HTTPAPIEX_Destroy(iotHubHttpApiExHandle); + } + + STRING_delete(relativePathNotification); + } + + return result; +} + +static IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT* createUploadToBlobContextInstance() +{ + IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT* result; + + if ((result = malloc(sizeof(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT))) == NULL) + { + LogError("Failed allocating IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT"); + } + else + { + (void)memset(result, 0, sizeof(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT)); + + if ((result->blockIdList = singlylinkedlist_create()) == NULL) + { + LogError("Failed allocating list for blockIds"); + free(result); + result = NULL; + } + else if ((result->correlationId = STRING_new()) == NULL) + { + LogError("unable to STRING_new"); + singlylinkedlist_destroy(result->blockIdList); + free(result); + result = NULL; + } + } + + return result; +} + +static void destroyUploadToBlobContextInstance(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT* uploadContext) +{ + if (uploadContext != NULL) + { + HTTPAPIEX_Destroy(uploadContext->blobHttpApiHandle); + + if (uploadContext->blockIdList != NULL) + { + Blob_ClearBlockIdList(uploadContext->blockIdList); + singlylinkedlist_destroy(uploadContext->blockIdList); + } + + STRING_delete(uploadContext->correlationId); + free(uploadContext->blobStorageHostname); + free(uploadContext->blobStorageRelativePath); + free(uploadContext); + } +} + +static int parseAzureBlobSasUri(STRING_HANDLE sasUri, char** blobStorageHostname, char** blobStorageRelativePath) +{ + int result; + const char* hostnameBegin; + char* hostname = NULL; + char* relativePath = NULL; + + /*to find the hostname, the following logic is applied:*/ + /*the hostname starts at the first character after "://"*/ + /*the hostname ends at the first character before the next "/" after "://"*/ + if ((hostnameBegin = strstr(STRING_c_str(sasUri), "://")) == NULL) + { + LogError("hostname cannot be determined"); + result = MU_FAILURE; + } + else + { + hostnameBegin += 3; /*have to skip 3 characters which are "://"*/ + const char* relativePathBegin = strchr(hostnameBegin, '/'); + + if (relativePathBegin == NULL) + { + LogError("relative path cannot be determined"); + result = MU_FAILURE; + } + else + { + size_t hostnameSize = relativePathBegin - hostnameBegin; + + if ((hostname = malloc(hostnameSize + 1)) == NULL) + { + LogError("failed to allocate memory for blob storage hostname"); + result = MU_FAILURE; + } + else + { + (void)memcpy(hostname, hostnameBegin, hostnameSize); + hostname[hostnameSize] = '\0'; + size_t relativePathSize = STRING_length(sasUri) - (relativePathBegin - STRING_c_str(sasUri)); + + if ((relativePath = malloc(relativePathSize + 1)) == NULL) + { + LogError("failed to allocate memory for blob storage relative path"); + free(hostname); result = MU_FAILURE; - STRING_empty(sas_uri); } else { + (void)memcpy(relativePath, relativePathBegin, relativePathSize); + relativePath[relativePathSize] = '\0'; + *blobStorageHostname = hostname; + *blobStorageRelativePath = relativePath; result = 0; } - STRING_delete(filename); } } - json_value_free(json); } + return result; } @@ -302,602 +869,297 @@ IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE IoTHubClient_LL_UploadToBlob_Create(const I } } } - return (IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE)upload_data; + return (IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE)upload_data; } -/*returns 0 when correlationId, sasUri contain data*/ -static int IoTHubClient_LL_UploadToBlob_step1and2(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_data, HTTPAPIEX_HANDLE iotHubHttpApiExHandle, HTTP_HEADERS_HANDLE requestHttpHeaders, const char* destinationFileName, STRING_HANDLE correlationId, STRING_HANDLE sasUri) +IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubClient_LL_UploadToBlob_CreateContext(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE handle, const char* destinationFileName) { - int result; + IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT* result; - STRING_HANDLE relativePath = STRING_construct_sprintf("/devices/%s/files/%s", upload_data->deviceId, API_VERSION); - if (relativePath == NULL) + if (handle == NULL || destinationFileName == NULL) { - LogError("Failure constructing string"); - result = MU_FAILURE; + LogError("invalid argument detected handle=%p destinationFileName=%p", handle, destinationFileName); + result = NULL; + } + else if ((result = createUploadToBlobContextInstance()) == NULL) + { + LogError("Failed creating Upload to Blob context"); } else { - STRING_HANDLE blobName = STRING_construct_sprintf("{ \"blobName\": \"%s\" }", destinationFileName); - if (blobName == NULL) + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_data = (IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA*)handle; + STRING_HANDLE sasUri; + + if ((sasUri = STRING_new()) == NULL) { - LogError("Failure constructing string"); - result = MU_FAILURE; + LogError("Failed to allocate STRING_HANDLE for SAS URI"); + destroyUploadToBlobContextInstance(result); + result = NULL; } else { - BUFFER_HANDLE responseContent; - size_t len = STRING_length(blobName); - BUFFER_HANDLE blobBuffer = BUFFER_create((const unsigned char *)STRING_c_str(blobName), len); - if (blobBuffer == NULL) + /*do step 1*/ + if (IoTHubClient_LL_UploadToBlob_GetBlobCredentialsFromIoTHub( + upload_data, destinationFileName, result->correlationId, sasUri) != 0) { - LogError("unable to create BUFFER"); - result = MU_FAILURE; + LogError("error in IoTHubClient_LL_UploadToBlob_GetBlobCredentialsFromIoTHub"); + destroyUploadToBlobContextInstance(result); + result = NULL; + } + else if (parseAzureBlobSasUri(sasUri, &result->blobStorageHostname, &result->blobStorageRelativePath) != 0) + { + LogError("failed parsing Blob Storage SAS URI"); + destroyUploadToBlobContextInstance(result); + result = NULL; } else { - if ((responseContent = BUFFER_new()) == NULL) - { - result = MU_FAILURE; - LogError("unable to BUFFER_new"); - } - else + result->u2bClientData = upload_data; + + result->blobHttpApiHandle = Blob_CreateHttpConnection( + result->blobStorageHostname, + result->u2bClientData->certificates, + &(result->u2bClientData->http_proxy_options), + result->u2bClientData->networkInterface, + result->u2bClientData->blob_upload_timeout_millisecs); + + if (result->blobHttpApiHandle == NULL) { - if (!( - (HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, "Content-Type", HEADER_APP_JSON) == HTTP_HEADERS_OK) && - (HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, "Accept", HEADER_APP_JSON) == HTTP_HEADERS_OK) && - (HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, "User-Agent", "iothubclient/" IOTHUB_SDK_VERSION) == HTTP_HEADERS_OK) && - ((upload_data->cred_type == IOTHUB_CREDENTIAL_TYPE_X509 || upload_data->cred_type == IOTHUB_CREDENTIAL_TYPE_X509_ECC) || - (HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, HEADER_AUTHORIZATION, EMPTY_STRING) == HTTP_HEADERS_OK)) - )) - { - LogError("unable to HTTPHeaders_AddHeaderNameValuePair"); - result = MU_FAILURE; - } - else - { - int wasIoTHubRequestSuccess = 0; /*!=0 means responseContent has a buffer that should be parsed by parson after executing the below switch*/ - /* set the result to error by default */ - result = MU_FAILURE; - switch (upload_data->cred_type) - { - default: - { - /*wasIoTHubRequestSuccess takes care of the return value*/ - LogError("Internal Error: unexpected value in auth schema = %d", upload_data->cred_type); - result = MU_FAILURE; - break; - } - case IOTHUB_CREDENTIAL_TYPE_X509_ECC: - case IOTHUB_CREDENTIAL_TYPE_X509: - { - if (send_http_request(iotHubHttpApiExHandle, STRING_c_str(relativePath), requestHttpHeaders, blobBuffer, responseContent) != 0) - { - result = MU_FAILURE; - LogError("unable to HTTPAPIEX_ExecuteRequest"); - } - else - { - wasIoTHubRequestSuccess = 1; - } - break; - } - case IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY: - case IOTHUB_CREDENTIAL_TYPE_DEVICE_AUTH: - { - STRING_HANDLE uri_resource = STRING_construct_sprintf("%s/devices/%s", upload_data->hostname, upload_data->deviceId); - if (uri_resource == NULL) - { - result = MU_FAILURE; - LogError("Failure constructing string"); - } - else - { - if (upload_data->cred_type == IOTHUB_CREDENTIAL_TYPE_DEVICE_AUTH) - { - time_t curr_time; - if ((curr_time = get_time(NULL)) == INDEFINITE_TIME) - { - result = MU_FAILURE; - LogError("failure retrieving time"); - } - else - { - uint64_t expiry = (uint64_t)(difftime(curr_time, 0) + 3600); - char* sas_token = IoTHubClient_Auth_Get_SasToken(upload_data->authorization_module, STRING_c_str(uri_resource), expiry, EMPTY_STRING); - if (sas_token == NULL) - { - result = MU_FAILURE; - LogError("unable to retrieve sas token"); - } - else - { - if (HTTPHeaders_ReplaceHeaderNameValuePair(requestHttpHeaders, HEADER_AUTHORIZATION, sas_token) != HTTP_HEADERS_OK) - { - result = MU_FAILURE; - LogError("unable to HTTPHeaders_AddHeaderNameValuePair"); - } - else if (send_http_request(iotHubHttpApiExHandle, STRING_c_str(relativePath), requestHttpHeaders, blobBuffer, responseContent) != 0) - { - result = MU_FAILURE; - LogError("unable to HTTPAPIEX_ExecuteRequest"); - } - else - { - wasIoTHubRequestSuccess = 1; - } - } - free(sas_token); - } - } - else - { - if (send_http_sas_request(upload_data, STRING_c_str(uri_resource), iotHubHttpApiExHandle, STRING_c_str(relativePath), requestHttpHeaders, blobBuffer, responseContent) != 0) - { - result = MU_FAILURE; - LogError("unable to HTTPAPIEX_ExecuteRequest"); - } - else - { - wasIoTHubRequestSuccess = 1; - } - } - STRING_delete(uri_resource); - } - break; - } - case IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN: - { - if (HTTPHeaders_ReplaceHeaderNameValuePair(requestHttpHeaders, HEADER_AUTHORIZATION, upload_data->credentials.supplied_sas_token) != HTTP_HEADERS_OK) - { - result = MU_FAILURE; - LogError("unable to HTTPHeaders_AddHeaderNameValuePair"); - } - else if (send_http_request(iotHubHttpApiExHandle, STRING_c_str(relativePath), requestHttpHeaders, blobBuffer, responseContent) != 0) - { - result = MU_FAILURE; - LogError("unable to HTTPAPIEX_ExecuteRequest"); - } - else - { - wasIoTHubRequestSuccess = 1; - } - break; - } - } - if (wasIoTHubRequestSuccess == 1) - { - const unsigned char*responseContent_u_char = BUFFER_u_char(responseContent); - size_t responseContent_length = BUFFER_length(responseContent); - STRING_HANDLE responseAsString = STRING_from_byte_array(responseContent_u_char, responseContent_length); - if (responseAsString == NULL) - { - result = MU_FAILURE; - LogError("unable to get the response as string"); - } - else - { - if (parse_result_json(STRING_c_str(responseAsString), correlationId, sasUri) != 0) - { - LogError("unable to parse json result"); - result = MU_FAILURE; - } - else - { - result = 0; - } - STRING_delete(responseAsString); - } - } - } - BUFFER_delete(responseContent); + LogError("Failed creating HTTP connection to Azure Blob"); + destroyUploadToBlobContextInstance(result); + result = NULL; } - BUFFER_delete(blobBuffer); } - STRING_delete(blobName); + + STRING_delete(sasUri); } - STRING_delete(relativePath); } + return result; } -/*returns 0 when the IoTHub has been informed about the file upload status*/ -static int IoTHubClient_LL_UploadToBlob_step3(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_data, HTTPAPIEX_HANDLE iotHubHttpApiExHandle, HTTP_HEADERS_HANDLE requestHttpHeaders, BUFFER_HANDLE messageBody) +IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_DestroyContext(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext) { - int result; - /*here is step 3. depending on the outcome of step 2 it needs to inform IoTHub about the file upload status*/ - /*if step 1 failed, there's nothing that step 3 needs to report.*/ - /*this POST "tries" to happen*/ + IOTHUB_CLIENT_RESULT result; - STRING_HANDLE relativePathNotification = STRING_construct_sprintf("/devices/%s/files/notifications/%s", upload_data->deviceId, API_VERSION); - if (relativePathNotification == NULL) + if (uploadContext == NULL) { - result = MU_FAILURE; - LogError("Failure constructing string"); + LogError("invalid argument detected uploadContext=%p", uploadContext); + result = IOTHUB_CLIENT_INVALID_ARG; } else { - switch (upload_data->cred_type) - { - default: - { - LogError("internal error: unknown authorization Scheme"); - result = MU_FAILURE; - break; - } - case IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN: - case IOTHUB_CREDENTIAL_TYPE_X509: - case IOTHUB_CREDENTIAL_TYPE_X509_ECC: - case IOTHUB_CREDENTIAL_TYPE_DEVICE_AUTH: - { - if (send_http_request(iotHubHttpApiExHandle, STRING_c_str(relativePathNotification), requestHttpHeaders, messageBody, NULL) != 0) - { - LogError("unable to execute HTTPAPIEX_ExecuteRequest"); - result = MU_FAILURE; - } - else - { - result = 0; - } - break; - } - case IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY: - { - STRING_HANDLE uriResource = STRING_construct_sprintf("%s/devices/%s/files/notifications", upload_data->hostname, upload_data->deviceId); - if (uriResource == NULL) - { - LogError("Failure constructing string"); - result = MU_FAILURE; - } - else - { - if (send_http_sas_request(upload_data, STRING_c_str(uriResource), iotHubHttpApiExHandle, STRING_c_str(relativePathNotification), requestHttpHeaders, messageBody, NULL) != 0) - { - LogError("unable to execute HTTPAPIEX_ExecuteRequest"); - result = MU_FAILURE; - } - else - { - result = 0; - } - STRING_delete(uriResource); - } - break; - } - } - STRING_delete(relativePathNotification); + destroyUploadToBlobContextInstance(uploadContext); + result = IOTHUB_CLIENT_OK; } + return result; } -// this callback splits the source data into blocks to be fed to IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex)_Impl -static IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT FileUpload_GetData_Callback(IOTHUB_CLIENT_FILE_UPLOAD_RESULT result, unsigned char const ** data, size_t* size, void* context) +IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_UploadBlock(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext, uint32_t blockNumber, const uint8_t* dataPtr, size_t dataSize) { - BLOB_UPLOAD_CONTEXT* uploadContext = (BLOB_UPLOAD_CONTEXT*) context; + IOTHUB_CLIENT_RESULT result; - if (data == NULL || size == NULL) - { - // This is the last call, nothing to do - } - else if (result != FILE_UPLOAD_OK) + if (uploadContext == NULL || dataPtr == NULL || dataSize == 0) { - // Last call failed - *data = NULL; - *size = 0; - } - else if (uploadContext->remainingSizeToUpload == 0) - { - // Everything has been uploaded - *data = NULL; - *size = 0; + LogError("invalid argument detected uploadContext=%p, dataPtr=%p, dataSize=%zu", uploadContext, dataPtr, dataSize); + result = IOTHUB_CLIENT_INVALID_ARG; } else { - // Upload next block - size_t thisBlockSize = (uploadContext->remainingSizeToUpload > BLOCK_SIZE) ? BLOCK_SIZE : uploadContext->remainingSizeToUpload; - *data = (unsigned char*)uploadContext->blobSource + (uploadContext->blobSourceSize - uploadContext->remainingSizeToUpload); - *size = thisBlockSize; - uploadContext->remainingSizeToUpload -= thisBlockSize; - } + BUFFER_HANDLE blockData; - return IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_OK; -} + if ((blockData = BUFFER_create(dataPtr, dataSize)) == NULL) + { + LogError("Failed allocating buffer for Blob block data"); + result = IOTHUB_CLIENT_ERROR; + } + else + { + unsigned int httpResponseStatus; -static HTTPAPIEX_RESULT set_transfer_timeout(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_data, HTTPAPIEX_HANDLE iotHubHttpApiExHandle) -{ - HTTPAPIEX_RESULT result; - if (upload_data->blob_upload_timeout_secs != 0) - { - // Convert the timeout to milliseconds for curl - long http_timeout = (long)upload_data->blob_upload_timeout_secs * 1000; - result = HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_HTTP_TIMEOUT, &http_timeout); - } - else - { - result = HTTPAPIEX_OK; + if (Blob_PutBlock( + uploadContext->blobHttpApiHandle, + uploadContext->blobStorageRelativePath, + blockNumber, blockData, + uploadContext->blockIdList, + &httpResponseStatus, NULL) != BLOB_OK) + { + LogError("Failed uploading Blob block data"); + result = IOTHUB_CLIENT_ERROR; + } + else + { + result = IOTHUB_CLIENT_OK; + } + + BUFFER_delete(blockData); + } } + return result; } -IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE handle, const char* destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX getDataCallbackEx, void* context) +IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_Complete(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext, bool isSuccess, int responseCode, const char* responseMessage) { IOTHUB_CLIENT_RESULT result; - - if (handle == NULL || destinationFileName == NULL || getDataCallbackEx == NULL) + if (uploadContext == NULL) { - LogError("invalid argument detected handle=%p destinationFileName=%p getDataCallbackEx=%p", handle, destinationFileName, getDataCallbackEx); + LogError("invalid argument detected uploadContext=%p", uploadContext); result = IOTHUB_CLIENT_INVALID_ARG; } else { - IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_data = (IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA*)handle; + unsigned int putBlockListHttpStatus; - HTTPAPIEX_HANDLE iotHubHttpApiExHandle = HTTPAPIEX_Create(upload_data->hostname); - if (iotHubHttpApiExHandle == NULL) - { - LogError("unable to HTTPAPIEX_Create"); - result = IOTHUB_CLIENT_ERROR; - } - else if (set_transfer_timeout(upload_data, iotHubHttpApiExHandle) != HTTPAPIEX_OK) + // Do not PUT BLOCK LIST if result is not success (isSuccess == false) + // Otherwise we could corrupt a blob with a partial update. + if (isSuccess && Blob_PutBlockList( + uploadContext->blobHttpApiHandle, + uploadContext->blobStorageRelativePath, + uploadContext->blockIdList, &putBlockListHttpStatus, NULL) != BLOB_OK) { - LogError("unable to set blob transfer timeout"); + LogError("Failed sending block ID list to Blob Storage (%u)", putBlockListHttpStatus); result = IOTHUB_CLIENT_ERROR; } else { - if (upload_data->curl_verbosity_level != UPLOADTOBLOB_CURL_VERBOSITY_UNSET) - { - size_t curl_verbose = (upload_data->curl_verbosity_level == UPLOADTOBLOB_CURL_VERBOSITY_ON); - (void)HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_CURL_VERBOSE, &curl_verbose); - } + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_data = (IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA*)uploadContext->u2bClientData; - if ((upload_data->networkInterface) != NULL && (HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_CURL_INTERFACE, upload_data->networkInterface) != HTTPAPIEX_OK)) + STRING_HANDLE response = STRING_construct_sprintf(RESPONSE_BODY_FORMAT, + STRING_c_str(uploadContext->correlationId), + isSuccess ? RESPONSE_BODY_SUCCESS_BOOLEAN_STRING : RESPONSE_BODY_ERROR_BOOLEAN_STRING, + responseCode, + responseMessage); + + if(response == NULL) { - LogError("unable to set networkInteface!"); + LogError("STRING_construct_sprintf failed"); result = IOTHUB_CLIENT_ERROR; } else { - /*transmit the x509certificate and x509privatekey*/ - if ((upload_data->cred_type == IOTHUB_CREDENTIAL_TYPE_X509 || upload_data->cred_type == IOTHUB_CREDENTIAL_TYPE_X509_ECC) && - (((upload_data->tls_renegotiation == true) && (HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_SET_TLS_RENEGOTIATION, &upload_data->tls_renegotiation) != HTTPAPIEX_OK)) || - (HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_X509_CERT, upload_data->credentials.x509_credentials.x509certificate) != HTTPAPIEX_OK) || - (HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_X509_PRIVATE_KEY, upload_data->credentials.x509_credentials.x509privatekey) != HTTPAPIEX_OK) || - ((upload_data->credentials.x509_credentials.x509privatekeyType != NULL) && (HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_OPENSSL_PRIVATE_KEY_TYPE, upload_data->credentials.x509_credentials.x509privatekeyType) != HTTPAPIEX_OK)) || - ((upload_data->credentials.x509_credentials.engine != NULL) && (HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_OPENSSL_ENGINE, upload_data->credentials.x509_credentials.engine) != HTTPAPIEX_OK)))) + size_t response_length = STRING_length(response); + BUFFER_HANDLE responseToIoTHub = BUFFER_new(); + + if (responseToIoTHub == NULL) { - LogError("unable to HTTPAPIEX_SetOption for x509 certificate"); + LogError("BUFFER_new failed"); result = IOTHUB_CLIENT_ERROR; } else { - if ((upload_data->certificates != NULL) && (HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_TRUSTED_CERT, upload_data->certificates) != HTTPAPIEX_OK)) - { - LogError("unable to set TrustedCerts!"); - result = IOTHUB_CLIENT_ERROR; - } - else + if (BUFFER_build(responseToIoTHub, (const unsigned char*)STRING_c_str(response), response_length) == 0) { - - if (upload_data->http_proxy_options.host_address != NULL) + if (IoTHubClient_LL_UploadToBlob_NotifyIoTHubOfUploadCompletion(upload_data, responseToIoTHub) != 0) { - HTTP_PROXY_OPTIONS proxy_options; - proxy_options = upload_data->http_proxy_options; - - if (HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_HTTP_PROXY, &proxy_options) != HTTPAPIEX_OK) - { - LogError("unable to set http proxy!"); - result = IOTHUB_CLIENT_ERROR; - } - else - { - result = IOTHUB_CLIENT_OK; - } + LogError("IoTHubClient_LL_UploadToBlob_NotifyIoTHubOfUploadCompletion failed"); + result = IOTHUB_CLIENT_ERROR; } else { result = IOTHUB_CLIENT_OK; } - - if (result != IOTHUB_CLIENT_ERROR) - { - STRING_HANDLE sasUri; - STRING_HANDLE correlationId; - if ((correlationId = STRING_new()) == NULL) - { - LogError("unable to STRING_new"); - result = IOTHUB_CLIENT_ERROR; - } - else if ((sasUri = STRING_new()) == NULL) - { - LogError("unable to create sas uri"); - result = IOTHUB_CLIENT_ERROR; - STRING_delete(correlationId); - } - else - { - HTTP_HEADERS_HANDLE requestHttpHeaders = HTTPHeaders_Alloc(); /*these are build by step 1 and used by step 3 too*/ - if (requestHttpHeaders == NULL) - { - LogError("unable to HTTPHeaders_Alloc"); - result = IOTHUB_CLIENT_ERROR; - } - else - { - /*do step 1*/ - if (IoTHubClient_LL_UploadToBlob_step1and2(upload_data, iotHubHttpApiExHandle, requestHttpHeaders, destinationFileName, correlationId, sasUri) != 0) - { - LogError("error in IoTHubClient_LL_UploadToBlob_step1"); - result = IOTHUB_CLIENT_ERROR; - } - else - { - /*do step 2.*/ - - unsigned int httpResponse; - BUFFER_HANDLE responseToIoTHub = BUFFER_new(); - if (responseToIoTHub == NULL) - { - result = IOTHUB_CLIENT_ERROR; - LogError("unable to BUFFER_new"); - } - else - { - const size_t timeoutInMilliseconds = (upload_data->blob_upload_timeout_secs * 1000); - BLOB_RESULT uploadMultipleBlocksResult = Blob_UploadMultipleBlocksFromSasUri(STRING_c_str(sasUri), getDataCallbackEx, context, &httpResponse, responseToIoTHub, upload_data->certificates, &(upload_data->http_proxy_options), upload_data->networkInterface, timeoutInMilliseconds); - if (uploadMultipleBlocksResult == BLOB_ABORTED) - { - LogInfo("Blob_UploadFromSasUri aborted file upload"); - - STRING_HANDLE aborted_response = STRING_construct_sprintf(RESPONSE_BODY_FORMAT, - STRING_c_str(correlationId), - RESPONSE_BODY_ERROR_BOOLEAN_STRING, - RESPONSE_BODY_ERROR_RETURN_CODE, - RESPONSE_BODY_ABORTED_MESSAGE); - if(aborted_response == NULL) - { - LogError("STRING_construct_sprintf failed"); - result = IOTHUB_CLIENT_ERROR; - } - else - { - size_t response_length = STRING_length(aborted_response); - if (BUFFER_build(responseToIoTHub, (const unsigned char*)STRING_c_str(aborted_response), response_length) == 0) - { - if (IoTHubClient_LL_UploadToBlob_step3(upload_data, iotHubHttpApiExHandle, requestHttpHeaders, responseToIoTHub) != 0) - { - LogError("IoTHubClient_LL_UploadToBlob_step3 failed"); - result = IOTHUB_CLIENT_ERROR; - } - else - { - result = IOTHUB_CLIENT_OK; - } - } - else - { - LogError("Unable to BUFFER_build, can't perform IoTHubClient_LL_UploadToBlob_step3"); - result = IOTHUB_CLIENT_ERROR; - } - STRING_delete(aborted_response); - } - } - else if (uploadMultipleBlocksResult != BLOB_OK) - { - LogError("unable to Blob_UploadFromSasUri"); - - /*do step 3*/ /*try*/ - STRING_HANDLE failed_response = STRING_construct_sprintf(RESPONSE_BODY_FORMAT, - STRING_c_str(correlationId), - RESPONSE_BODY_ERROR_BOOLEAN_STRING, - RESPONSE_BODY_ERROR_RETURN_CODE, - RESPONSE_BODY_FAILED_MESSAGE); - if(failed_response == NULL) - { - LogError("STRING_construct_sprintf failed"); - result = IOTHUB_CLIENT_ERROR; - } - else - { - size_t response_length = STRING_length(failed_response); - if (BUFFER_build(responseToIoTHub, (const unsigned char*)STRING_c_str(failed_response), response_length) == 0) - { - if (IoTHubClient_LL_UploadToBlob_step3(upload_data, iotHubHttpApiExHandle, requestHttpHeaders, responseToIoTHub) != 0) - { - LogError("IoTHubClient_LL_UploadToBlob_step3 failed"); - } - } - STRING_delete(failed_response); - result = IOTHUB_CLIENT_ERROR; - } - } - else - { - /*must make a json*/ - unsigned char * response = BUFFER_u_char(responseToIoTHub); - STRING_HANDLE req_string; - req_string = STRING_construct_sprintf(RESPONSE_BODY_FORMAT, - STRING_c_str(correlationId), - ((httpResponse < 300) ? "true" : "false"), - httpResponse, - (response == NULL ? (const unsigned char*)"" : response)); - if (req_string == NULL) - { - LogError("Failure constructing string"); - result = IOTHUB_CLIENT_ERROR; - } - else - { - /*do again snprintf*/ - BUFFER_HANDLE toBeTransmitted = NULL; - size_t req_string_len = STRING_length(req_string); - const char* required_string = STRING_c_str(req_string); - if ((toBeTransmitted = BUFFER_create((const unsigned char*)required_string, req_string_len)) == NULL) - { - LogError("unable to BUFFER_create"); - result = IOTHUB_CLIENT_ERROR; - } - else - { - if (IoTHubClient_LL_UploadToBlob_step3(upload_data, iotHubHttpApiExHandle, requestHttpHeaders, toBeTransmitted) != 0) - { - LogError("IoTHubClient_LL_UploadToBlob_step3 failed"); - result = IOTHUB_CLIENT_ERROR; - } - else - { - result = (httpResponse < 300) ? IOTHUB_CLIENT_OK : IOTHUB_CLIENT_ERROR; - } - BUFFER_delete(toBeTransmitted); - } - STRING_delete(req_string); - } - } - BUFFER_delete(responseToIoTHub); - } - } - HTTPHeaders_Free(requestHttpHeaders); - } - STRING_delete(sasUri); - STRING_delete(correlationId); - } - } } + else + { + LogError("Unable to BUFFER_build, can't perform IoTHubClient_LL_UploadToBlob_NotifyIoTHubOfUploadCompletion"); + result = IOTHUB_CLIENT_ERROR; + } + + BUFFER_delete(responseToIoTHub); } + + STRING_delete(response); } - HTTPAPIEX_Destroy(iotHubHttpApiExHandle); } - - (void)getDataCallbackEx(result == IOTHUB_CLIENT_OK ? FILE_UPLOAD_OK : FILE_UPLOAD_ERROR, NULL, NULL, context); } + return result; } -IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_Impl(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE handle, const char* destinationFileName, const unsigned char* source, size_t size) +IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX getDataCallbackEx, void* context) { IOTHUB_CLIENT_RESULT result; - if (handle == NULL || destinationFileName == NULL) - { - LogError("Invalid parameter handle:%p destinationFileName:%p", handle, destinationFileName); - result = IOTHUB_CLIENT_INVALID_ARG; - } - else if (source == NULL && size > 0) + if (uploadContextHandle == NULL || getDataCallbackEx == NULL) { - LogError("Invalid source and size combination: source=%p size=%lu", source, (unsigned long)size); + LogError("invalid argument detected uploadContextHandle=%p getDataCallbackEx=%p", uploadContextHandle, getDataCallbackEx); result = IOTHUB_CLIENT_INVALID_ARG; } else { - BLOB_UPLOAD_CONTEXT context; - context.blobSource = source; - context.blobSourceSize = size; - context.remainingSizeToUpload = size; + unsigned int blockID = 0; + unsigned int uploadHttpStatus; + const char* responseToIoTHub = RESPONSE_BODY_ABORTED_MESSAGE; + unsigned char const * blockDataPtr = NULL; + size_t blockDataSize = 0; + IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT getDataReturnValue; + + do + { + getDataReturnValue = getDataCallbackEx(FILE_UPLOAD_OK, &blockDataPtr, &blockDataSize, context); + + if (getDataReturnValue == IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_ABORT) + { + LogInfo("Upload to blob has been aborted by the user"); + uploadHttpStatus = HTTP_STATUS_CODE_BAD_REQUEST; + responseToIoTHub = RESPONSE_BODY_ABORTED_MESSAGE; + break; + } + else if (blockDataPtr == NULL || blockDataSize == 0) + { + // This is how the user indicates that there is no more data to be uploaded, + // and the function can end with success result. + uploadHttpStatus = HTTP_STATUS_CODE_OK; + responseToIoTHub = EMPTY_STRING; + break; + } + else + { + if (blockDataSize > BLOCK_SIZE) + { + LogError("tried to upload block of size %lu, max allowed size is %d", (unsigned long)blockDataSize, BLOCK_SIZE); + uploadHttpStatus = HTTP_STATUS_CODE_BAD_REQUEST; + responseToIoTHub = RESPONSE_BODY_BLOCK_SIZE_EXCEEDED_MESSAGE; + break; + } + else if (blockID >= MAX_BLOCK_COUNT) + { + LogError("unable to upload more than %lu blocks in one blob", (unsigned long)MAX_BLOCK_COUNT); + uploadHttpStatus = HTTP_STATUS_CODE_BAD_REQUEST; + responseToIoTHub = RESPONSE_BODY_BLOCK_COUNT_EXCEEDED_MESSAGE; + break; + } + else if (IoTHubClient_LL_UploadToBlob_UploadBlock(uploadContextHandle, blockID, blockDataPtr, blockDataSize) != IOTHUB_CLIENT_OK) + { + LogError("failed uploading block to blob"); + uploadHttpStatus = HTTP_STATUS_CODE_BAD_REQUEST; + responseToIoTHub = RESPONSE_BODY_UPLOAD_FAILED_MESSAGE; + break; + } + + blockID++; + } + } + while(true); - result = IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl(handle, destinationFileName, FileUpload_GetData_Callback, &context); + if (IoTHubClient_LL_UploadToBlob_Complete( + uploadContextHandle, IS_HTTP_STATUS_CODE_SUCCESS(uploadHttpStatus), uploadHttpStatus, responseToIoTHub) != IOTHUB_CLIENT_OK) + { + LogError("Failed notifying IoT Hub of upload completion"); + (void)getDataCallbackEx(FILE_UPLOAD_ERROR, NULL, NULL, context); + result = IOTHUB_CLIENT_ERROR; + } + else + { + (void)getDataCallbackEx(FILE_UPLOAD_OK, NULL, NULL, context); + result = IOTHUB_CLIENT_OK; + } } + return result; } @@ -1161,7 +1423,7 @@ IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_SetOption(IOTHUB_CLIENT_LL_UPL } else if (strcmp(optionName, OPTION_BLOB_UPLOAD_TIMEOUT_SECS) == 0) { - upload_data->blob_upload_timeout_secs = *(size_t*)value; + upload_data->blob_upload_timeout_millisecs = 1000 * (*(size_t*)value); result = IOTHUB_CLIENT_OK; } else if (strcmp(optionName, OPTION_NETWORK_INTERFACE_UPLOAD_TO_BLOB) == 0) @@ -1204,5 +1466,3 @@ IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_SetOption(IOTHUB_CLIENT_LL_UPL } #endif /*DONT_USE_UPLOADTOBLOB*/ - - diff --git a/iothub_client/src/iothub_device_client.c b/iothub_client/src/iothub_device_client.c index abb584bb36..35408e50e6 100644 --- a/iothub_client/src/iothub_device_client.c +++ b/iothub_client/src/iothub_device_client.c @@ -114,6 +114,27 @@ IOTHUB_CLIENT_RESULT IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync(IOTHUB_D { return IoTHubClientCore_UploadMultipleBlocksToBlobAsync((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, destinationFileName, NULL, getDataCallbackEx, context); } + +IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubDeviceClient_CreateUploadContext(IOTHUB_DEVICE_CLIENT_HANDLE iotHubClientHandle, const char* destinationFileName) +{ + return IoTHubClientCore_CreateUploadContext((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, destinationFileName); +} + +IOTHUB_CLIENT_RESULT IoTHubDeviceClient_UploadBlockToBlob(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle, uint32_t blockNumber, const uint8_t* dataPtr, size_t dataSize) +{ + return IoTHubClientCore_LL_UploadBlockToBlob(uploadContextHandle, blockNumber, dataPtr, dataSize); +} + +IOTHUB_CLIENT_RESULT IoTHubDeviceClient_CompleteUploadToBlob(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle, bool isSuccess, int responseCode, const char* responseMessage) +{ + return IoTHubClientCore_CompleteUploadToBlob(uploadContextHandle, isSuccess, responseCode, responseMessage); +} + +void IoTHubDeviceClient_DestroyUploadContext(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle) +{ + IoTHubClientCore_LL_DestroyUploadContext(uploadContextHandle); +} + #endif /*DONT_USE_UPLOADTOBLOB*/ IOTHUB_CLIENT_RESULT IoTHubDeviceClient_SendTelemetryAsync(IOTHUB_DEVICE_CLIENT_HANDLE iotHubClientHandle, IOTHUB_MESSAGE_HANDLE telemetryMessageHandle, IOTHUB_CLIENT_TELEMETRY_CALLBACK telemetryConfirmationCallback, void* userContextCallback) diff --git a/iothub_client/src/iothub_device_client_ll.c b/iothub_client/src/iothub_device_client_ll.c index fdb7dec0d6..f4712833c1 100644 --- a/iothub_client/src/iothub_device_client_ll.c +++ b/iothub_client/src/iothub_device_client_ll.c @@ -137,6 +137,25 @@ IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob(IOTHUB_DEV return IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, destinationFileName, getDataCallbackEx, context); } +IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubDeviceClient_LL_CreateUploadContext(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, const char* destinationFileName) +{ + return IoTHubClientCore_LL_CreateUploadContext((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, destinationFileName); +} + +IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_UploadBlockToBlob(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle, uint32_t blockNumber, const uint8_t* dataPtr, size_t dataSize) +{ + return IoTHubClientCore_LL_UploadBlockToBlob(uploadContextHandle, blockNumber, dataPtr, dataSize); +} + +IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_CompleteUploadToBlob(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle, bool isSuccess, int responseCode, const char* responseMessage) +{ + return IoTHubClientCore_LL_CompleteUploadToBlob(uploadContextHandle, isSuccess, responseCode, responseMessage); +} + +void IoTHubDeviceClient_LL_DestroyUploadContext(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle) +{ + IoTHubClientCore_LL_DestroyUploadContext(uploadContextHandle); +} #endif IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_SendTelemetryAsync(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, IOTHUB_MESSAGE_HANDLE telemetryMessageHandle, IOTHUB_CLIENT_TELEMETRY_CALLBACK telemetryConfirmationCallback, void* userContextCallback) diff --git a/iothub_client/tests/iothubclient_uploadtoblob_e2e/iothubclient_uploadtoblob_e2e.c b/iothub_client/tests/iothubclient_uploadtoblob_e2e/iothubclient_uploadtoblob_e2e.c index cb6f3311be..bd2f1e7f97 100644 --- a/iothub_client/tests/iothubclient_uploadtoblob_e2e/iothubclient_uploadtoblob_e2e.c +++ b/iothub_client/tests/iothubclient_uploadtoblob_e2e/iothubclient_uploadtoblob_e2e.c @@ -501,6 +501,7 @@ TEST_FUNCTION_INITIALIZE(TestMethodInitialize) } #ifdef TEST_MQTT + TEST_FUNCTION(IoTHub_MQTT_UploadMultipleBlocksToBlobEx) { e2e_uploadtoblob_multiblock_test(MQTT_Protocol, true, false, false); @@ -525,7 +526,10 @@ TEST_FUNCTION(IoTHub_MQTT_UploadToBlob_x509) TEST_FUNCTION(IoTHub_MQTT_UploadCloseHandle_Before_WorkersComplete) { - e2e_uploadtoblob_close_handle_with_active_thread(MQTT_Protocol); + for (int i = 0; i < 100; i++) + { + e2e_uploadtoblob_close_handle_with_active_thread(MQTT_Protocol); + } } #endif // TEST_MQTT From c49c3d1a39e61836e2ec406d07c664ffa1a55d75 Mon Sep 17 00:00:00 2001 From: Ewerton Scaboro da Silva Date: Fri, 7 Jul 2023 18:05:17 -0700 Subject: [PATCH 02/27] [ACR] Expose upload-to-blob correlation ID and SAS URI in new API functions --- .../internal/iothub_client_ll_uploadtoblob.h | 9 +- iothub_client/inc/iothub_client_core.h | 8 +- iothub_client/inc/iothub_client_core_ll.h | 8 +- iothub_client/inc/iothub_device_client.h | 75 ++++-- iothub_client/inc/iothub_device_client_ll.h | 78 ++++-- ...thub_client_sample_upload_to_blob_custom.c | 77 ++++-- iothub_client/src/iothub_client_core.c | 45 +++- iothub_client/src/iothub_client_core_ll.c | 207 ++++++++++++--- .../src/iothub_client_ll_uploadtoblob.c | 249 +++++++++++------- iothub_client/src/iothub_device_client.c | 24 +- iothub_client/src/iothub_device_client_ll.c | 22 +- 11 files changed, 576 insertions(+), 226 deletions(-) diff --git a/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h b/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h index a73e20d879..fbf263fe0e 100644 --- a/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h +++ b/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h @@ -52,10 +52,13 @@ extern "C" */ MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context); - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, IoTHubClient_LL_UploadToBlob_CreateContext, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, handle, const char*, destinationFileName); - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_UploadBlock, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContext, uint32_t, blockNumber, const uint8_t*, dataPtr, size_t, dataSize); - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_Complete, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContext, bool, isSuccess, int, responseCode, const char*, responseMessage); + + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_InitializeUpload, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, handle, const char*, destinationFileName, char**, uploadCorrelationId, char**, azureBlobSasUri); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, IoTHubClient_LL_UploadToBlob_CreateContext, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, handle, const char*, azureBlobSasUri); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_PutBlock, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContext, uint32_t, blockNumber, const uint8_t*, dataPtr, size_t, dataSize); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_PutBlockList, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContext); MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_DestroyContext, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContext); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_NotifyCompletion, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, handle, const char*, uploadCorrelationId, bool, isSuccess, int, responseCode, const char*, responseMessage); MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_SetOption, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, handle, const char*, optionName, const void*, value); MOCKABLE_FUNCTION(, void, IoTHubClient_LL_UploadToBlob_Destroy, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, handle); diff --git a/iothub_client/inc/iothub_client_core.h b/iothub_client/inc/iothub_client_core.h index 859208d11f..3d8a7ed270 100644 --- a/iothub_client/inc/iothub_client_core.h +++ b/iothub_client/inc/iothub_client_core.h @@ -52,10 +52,12 @@ extern "C" #ifndef DONT_USE_UPLOADTOBLOB MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_UploadToBlobAsync, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, const char*, destinationFileName, const unsigned char*, source, size_t, size, IOTHUB_CLIENT_FILE_UPLOAD_CALLBACK, iotHubClientFileUploadCallback, void*, context); MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_UploadMultipleBlocksToBlobAsync, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK, getDataCallback, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context); - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, IoTHubClientCore_CreateUploadContext, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, const char*, destinationFileName); - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_UploadBlockToBlob, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle, uint32_t, blockNumber, const uint8_t*, dataPtr, size_t, dataSize); - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_CompleteUploadToBlob, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle, bool, isSuccess, int, responseCode, const char*, responseMessage); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_InitializeUpload, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, const char*, destinationFileName, char**, uploadCorrelationId, char**, azureBlobSasUri); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, IoTHubClientCore_CreateUploadContext, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, const char*, azureBlobSasUri); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_AzureStoragePutBlock, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle, uint32_t, blockNumber, const uint8_t*, dataPtr, size_t, dataSize); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_AzureStoragePutBlockList, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle); MOCKABLE_FUNCTION(, void, IoTHubClientCore_DestroyUploadContext, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_NotifyUploadCompletion, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, const char*, uploadCorrelationId, bool, isSuccess, int, responseCode, const char*, responseMessage); #endif /* DONT_USE_UPLOADTOBLOB */ MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_SendEventToOutputAsync, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, IOTHUB_MESSAGE_HANDLE, eventMessageHandle, const char*, outputName, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK, eventConfirmationCallback, void*, userContextCallback); diff --git a/iothub_client/inc/iothub_client_core_ll.h b/iothub_client/inc/iothub_client_core_ll.h index 18c9bd2afb..53d3920c4b 100644 --- a/iothub_client/inc/iothub_client_core_ll.h +++ b/iothub_client/inc/iothub_client_core_ll.h @@ -54,10 +54,12 @@ extern "C" MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_UploadToBlob, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, const unsigned char*, source, size_t, size); MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_UploadMultipleBlocksToBlob, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK, getDataCallback, void*, context); MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context); - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, IoTHubClientCore_LL_CreateUploadContext, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName); - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_UploadBlockToBlob, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle, uint32_t, blockNumber, const uint8_t*, dataPtr, size_t, dataSize); - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_CompleteUploadToBlob, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle, bool, isSuccess, int, responseCode, const char*, responseMessage); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_InitializeUpload, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, char**, uploadCorrelationId, char**, azureBlobSasUri); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, IoTHubClientCore_LL_CreateUploadContext, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const char*, azureBlobSasUri); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_AzureStoragePutBlock, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle, uint32_t, blockNumber, const uint8_t*, dataPtr, size_t, dataSize); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_AzureStoragePutBlockList, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle); MOCKABLE_FUNCTION(, void, IoTHubClientCore_LL_DestroyUploadContext, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_NotifyUploadCompletion, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const char*, uploadCorrelationId, bool, isSuccess, int, responseCode, const char*, responseMessage); #endif /*DONT_USE_UPLOADTOBLOB*/ #ifdef USE_EDGE_MODULES diff --git a/iothub_client/inc/iothub_device_client.h b/iothub_client/inc/iothub_device_client.h index 4385259e84..3acb33499b 100644 --- a/iothub_client/inc/iothub_device_client.h +++ b/iothub_client/inc/iothub_device_client.h @@ -348,31 +348,55 @@ extern "C" */ MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync, IOTHUB_DEVICE_CLIENT_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context); + /** + * @brief This API creates a new upload within Azure IoT Hub, getting back a correlation-id and a + * SAS URI for the Blob upload to the Azure Storage associated with the Azure IoT Hub. + * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. + * This function is expected to be used along with: + * `IoTHubDeviceClient_CreateUploadContext` + * `IoTHubDeviceClient_AzureStoragePutBlock` + * `IoTHubDeviceClient_DestroyUploadContext` + * For the standard less-granular uploads to blob please use either + * `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`. + * + * @param iotHubClientHandle The handle created by a call to the create function. + * @param destinationFileName Name of the file in blob storage. + * @param uploadCorrelationId Variable where to store the correlation-id of the new upload. + * @param azureBlobSasUri Variable where to store the Azure Storage SAS URI for the new upload. + * + * @warning This is a synchronous/blocking function. + * `uploadCorrelationId` and `azureBlobSasUri` must be freed by the calling application + * after the blob upload process is done (e.g., after calling `IoTHubDeviceClient_NotifyUploadCompletion`). + * + * @return An IOTHUB_CLIENT_RESULT value indicating the success or failure of the API call. + */ + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_InitializeUpload, IOTHUB_DEVICE_CLIENT_HANDLE, iotHubClientHandle, const char*, destinationFileName, char**, uploadCorrelationId, char**, azureBlobSasUri); + /** * @brief This API creates a context for a new blob upload to Azure Storage. * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. * This function is expected to be used along with: * `IoTHubDeviceClient_CreateUploadContext` - * `IoTHubDeviceClient_UploadBlockToBlob` + * `IoTHubDeviceClient_AzureStoragePutBlock` * `IoTHubDeviceClient_DestroyUploadContext` * For the standard less-granular uploads to blob please use either * `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`. * * @param iotHubClientHandle The handle created by a call to the create function. - * @param destinationFileName name of the file. + * @param azureBlobSasUri The Azure Storage Blob SAS uri obtained with `IoTHubDeviceClient_InitializeUpload`. * * @warning This is a synchronous/blocking function. * * @return A `IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE` on success or NULL if the function fails. */ - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, IoTHubDeviceClient_CreateUploadContext, IOTHUB_DEVICE_CLIENT_HANDLE, iotHubClientHandle, const char*, destinationFileName); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, IoTHubDeviceClient_CreateUploadContext, IOTHUB_DEVICE_CLIENT_HANDLE, iotHubClientHandle, const char*, azureBlobSasUri); /** * @brief This API upload a single blob block to Azure Storage (performs a PUT BLOCK operation). * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. * This function is expected to be used along with: * `IoTHubDeviceClient_CreateUploadContext` - * `IoTHubDeviceClient_UploadBlockToBlob` + * `IoTHubDeviceClient_AzureStoragePutBlock` * `IoTHubDeviceClient_DestroyUploadContext` * For the standard less-granular uploads to blob please use either * `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`. @@ -386,40 +410,36 @@ extern "C" * * @return IOTHUB_CLIENT_OK upon success or an error code upon failure. */ - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_UploadBlockToBlob, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle, uint32_t, blockNumber, const uint8_t*, dataPtr, size_t, dataSize); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_AzureStoragePutBlock, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle, uint32_t, blockNumber, const uint8_t*, dataPtr, size_t, dataSize); /** - * @brief This API performs an Azure Storage PUT BLOCK LIST operation and - * notifies Azure IoT Hub of the upload completion. + * @brief This API performs an Azure Storage PUT BLOCK LIST operation. * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. * This function is expected to be used along with: * `IoTHubDeviceClient_CreateUploadContext` - * `IoTHubDeviceClient_UploadBlockToBlob` + * `IoTHubDeviceClient_AzureStoragePutBlock` * `IoTHubDeviceClient_DestroyUploadContext` * For the standard less-granular uploads to blob please use either * `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`. - * If this function fails (due to any HTTP error to either Azure Storage or Azure IoT Hub) it can + * If this function fails (due to any HTTP error to Azure Storage) it can * be run again for a discretionary number of times in an attempt to succeed after, for example, * an internet connectivity disruption is over. * * @param uploadContextHandle The handle created with `IoTHubDeviceClient_CreateUploadContext`. - * @param isSuccess A boolean value indicating if the call(s) to `IoTHubDeviceClient_UploadBlockToBlob` succeeded. - * @param responseCode An user-defined code to signal the status of the upload (e.g., 200 for success, or -1 for abort). - * @param responseMessage An user-defined status message to go along with `responseCode` on the notification to Azure IoT Hub. * * @warning This is a synchronous/blocking function. * * @return IOTHUB_CLIENT_OK upon success or an error code upon failure. */ - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_CompleteUploadToBlob, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle, bool, isSuccess, int, responseCode, const char*, responseMessage); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_AzureStoragePutBlockList, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle); /** * @brief This API destroy a blob upload context previously created with `IoTHubDeviceClient_CreateUploadContext`. * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. * This function is expected to be used along with: * `IoTHubDeviceClient_CreateUploadContext` - * `IoTHubDeviceClient_UploadBlockToBlob` - * `IoTHubDeviceClient_CompleteUploadToBlob` + * `IoTHubDeviceClient_AzureStoragePutBlock` + * `IoTHubDeviceClient_NotifyUploadCompletion` * For the standard less-granular uploads to blob please use either * `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`. * @@ -430,6 +450,31 @@ extern "C" * @return Nothing. */ MOCKABLE_FUNCTION(, void, IoTHubDeviceClient_DestroyUploadContext, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle); + + /** + * @brief This API notifies Azure IoT Hub of the upload completion. + * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. + * This function is expected to be used along with: + * `IoTHubDeviceClient_CreateUploadContext` + * `IoTHubDeviceClient_AzureStoragePutBlock` + * `IoTHubDeviceClient_DestroyUploadContext` + * For the standard less-granular uploads to blob please use either + * `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`. + * If this function fails (due to any HTTP error to either Azure Storage or Azure IoT Hub) it can + * be run again for a discretionary number of times in an attempt to succeed after, for example, + * an internet connectivity disruption is over. + * + * @param uploadContextHandle The handle created with `IoTHubDeviceClient_CreateUploadContext`. + * @param uploadCorrelationId Upload correlation-id obtained with `IoTHubDeviceClient_InitializeUpload`. + * @param isSuccess A boolean value indicating if the call(s) to `IoTHubDeviceClient_AzureStoragePutBlock` succeeded. + * @param responseCode An user-defined code to signal the status of the upload (e.g., 200 for success, or -1 for abort). + * @param responseMessage An user-defined status message to go along with `responseCode` on the notification to Azure IoT Hub. + * + * @warning This is a synchronous/blocking function. + * + * @return IOTHUB_CLIENT_OK upon success or an error code upon failure. + */ + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_NotifyUploadCompletion, IOTHUB_DEVICE_CLIENT_HANDLE, iotHubClientHandle, const char*, uploadCorrelationId, bool, isSuccess, int, responseCode, const char*, responseMessage); #endif /* DONT_USE_UPLOADTOBLOB */ /** diff --git a/iothub_client/inc/iothub_device_client_ll.h b/iothub_client/inc/iothub_device_client_ll.h index dda3ece9d0..2e55c98f08 100644 --- a/iothub_client/inc/iothub_device_client_ll.h +++ b/iothub_client/inc/iothub_device_client_ll.h @@ -378,31 +378,55 @@ typedef struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA_TAG* IOTHUB_DEVICE_CLIENT_LL_HA */ MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context); + /** + * @brief This API creates a new upload within Azure IoT Hub, getting back a correlation-id and a + * SAS URI for the Blob upload to the Azure Storage associated with the Azure IoT Hub. + * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. + * This function is expected to be used along with: + * `IoTHubDeviceClient_LL_AzureStoragePutBlock` + * `IoTHubDeviceClient_LL_NotifyUploadCompletion` + * `IoTHubDeviceClient_LL_DestroyUploadContext` + * For the standard less-granular uploads to blob please use either + * `IoTHubDeviceClient_LL_UploadToBlob` or `IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob`. + * + * @param iotHubClientHandle The handle created by a call to the create function. + * @param destinationFileName Name of the file in blob storage. + * @param uploadCorrelationId Variable where to store the correlation-id of the new upload. + * @param azureBlobSasUri Variable where to store the Azure Storage SAS URI for the new upload. + * + * @warning This is a synchronous/blocking function. + * `uploadCorrelationId` and `azureBlobSasUri` must be freed by the calling application + * after the blob upload process is done (e.g., after calling `IoTHubDeviceClient_LL_NotifyUploadCompletion`). + * + * @return An IOTHUB_CLIENT_RESULT value indicating the success or failure of the API call. + */ + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_InitializeUpload, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, char**, uploadCorrelationId, char**, azureBlobSasUri); + /** * @brief This API creates a context for a new blob upload to Azure Storage. * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. * This function is expected to be used along with: - * `IoTHubDeviceClient_LL_UploadBlockToBlob` - * `IoTHubDeviceClient_LL_CompleteUploadToBlob` + * `IoTHubDeviceClient_LL_AzureStoragePutBlock` + * `IoTHubDeviceClient_LL_NotifyUploadCompletion` * `IoTHubDeviceClient_LL_DestroyUploadContext` * For the standard less-granular uploads to blob please use either * `IoTHubDeviceClient_LL_UploadToBlob` or `IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob`. * * @param iotHubClientHandle The handle created by a call to the create function. - * @param destinationFileName name of the file. + * @param azureBlobSasUri The Azure Storage Blob SAS uri obtained with `IoTHubDeviceClient_InitializeUpload`. * * @warning This is a synchronous/blocking function. * * @return A `IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE` on success or NULL if the function fails. */ - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, IoTHubDeviceClient_LL_CreateUploadContext, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, IoTHubDeviceClient_LL_CreateUploadContext, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, azureBlobSasUri); /** * @brief This API upload a single blob block to Azure Storage (performs a PUT BLOCK operation). * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. * This function is expected to be used along with: * `IoTHubDeviceClient_LL_CreateUploadContext` - * `IoTHubDeviceClient_LL_CompleteUploadToBlob` + * `IoTHubDeviceClient_LL_NotifyUploadCompletion` * `IoTHubDeviceClient_LL_DestroyUploadContext` * For the standard less-granular uploads to blob please use either * `IoTHubDeviceClient_LL_UploadToBlob` or `IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob`. @@ -416,40 +440,33 @@ typedef struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA_TAG* IOTHUB_DEVICE_CLIENT_LL_HA * * @return IOTHUB_CLIENT_OK upon success or an error code upon failure. */ - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_UploadBlockToBlob, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle, uint32_t, blockNumber, const uint8_t*, dataPtr, size_t, dataSize); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_AzureStoragePutBlock, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle, uint32_t, blockNumber, const uint8_t*, dataPtr, size_t, dataSize); /** - * @brief This API performs an Azure Storage PUT BLOCK LIST operation and - * notifies Azure IoT Hub of the upload completion. + * @brief This API performs an Azure Storage PUT BLOCK LIST operation. * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. * This function is expected to be used along with: * `IoTHubDeviceClient_LL_CreateUploadContext` - * `IoTHubDeviceClient_LL_UploadBlockToBlob` + * `IoTHubDeviceClient_LL_NotifyUploadCompletion` * `IoTHubDeviceClient_LL_DestroyUploadContext` * For the standard less-granular uploads to blob please use either * `IoTHubDeviceClient_LL_UploadToBlob` or `IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob`. - * If this function fails (due to any HTTP error to either Azure Storage or Azure IoT Hub) it can - * be run again for a discretionary number of times in an attempt to succeed after, for example, - * an internet connectivity disruption is over. * * @param uploadContextHandle The handle created with `IoTHubDeviceClient_LL_CreateUploadContext`. - * @param isSuccess A boolean value indicating if the call(s) to `IoTHubDeviceClient_LL_UploadBlockToBlob` succeeded. - * @param responseCode An user-defined code to signal the status of the upload (e.g., 200 for success, or -1 for abort). - * @param responseMessage An user-defined status message to go along with `responseCode` on the notification to Azure IoT Hub. * * @warning This is a synchronous/blocking function. * * @return IOTHUB_CLIENT_OK upon success or an error code upon failure. */ - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_CompleteUploadToBlob, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle, bool, isSuccess, int, responseCode, const char*, responseMessage); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_AzureStoragePutBlockList, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle); /** * @brief This API destroy a blob upload context previously created with `IoTHubDeviceClient_LL_CreateUploadContext` . * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. * This function is expected to be used along with: * `IoTHubDeviceClient_LL_CreateUploadContext` - * `IoTHubDeviceClient_LL_UploadBlockToBlob` - * `IoTHubDeviceClient_LL_CompleteUploadToBlob` + * `IoTHubDeviceClient_LL_AzureStoragePutBlock` + * `IoTHubDeviceClient_LL_NotifyUploadCompletion` * For the standard less-granular uploads to blob please use either * `IoTHubDeviceClient_LL_UploadToBlob` or `IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob`. * @@ -460,6 +477,31 @@ typedef struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA_TAG* IOTHUB_DEVICE_CLIENT_LL_HA * @return Nothing. */ MOCKABLE_FUNCTION(, void, IoTHubDeviceClient_LL_DestroyUploadContext, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle); + + /** + * @brief This API notifies Azure IoT Hub of the upload completion. + * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. + * This function is expected to be used along with: + * `IoTHubDeviceClient_LL_CreateUploadContext` + * `IoTHubDeviceClient_LL_AzureStoragePutBlock` + * `IoTHubDeviceClient_LL_DestroyUploadContext` + * For the standard less-granular uploads to blob please use either + * `IoTHubDeviceClient_LL_UploadToBlob` or `IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob`. + * If this function fails (due to any HTTP error to either Azure Storage or Azure IoT Hub) it can + * be run again for a discretionary number of times in an attempt to succeed after, for example, + * an internet connectivity disruption is over. + * + * @param uploadContextHandle The handle created with `IoTHubDeviceClient_LL_CreateUploadContext`. + * @param uploadCorrelationId Upload correlation-id obtained with `IoTHubDeviceClient_LL_InitializeUpload`. + * @param isSuccess A boolean value indicating if the call(s) to `IoTHubDeviceClient_LL_AzureStoragePutBlock` succeeded. + * @param responseCode An user-defined code to signal the status of the upload (e.g., 200 for success, or -1 for abort). + * @param responseMessage An user-defined status message to go along with `responseCode` on the notification to Azure IoT Hub. + * + * @warning This is a synchronous/blocking function. + * + * @return IOTHUB_CLIENT_OK upon success or an error code upon failure. + */ + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_NotifyUploadCompletion, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, uploadCorrelationId, bool, isSuccess, int, responseCode, const char*, responseMessage); #endif /*DONT_USE_UPLOADTOBLOB*/ /** diff --git a/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c b/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c index 8531e3da6d..2d8b31c325 100644 --- a/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c +++ b/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c @@ -74,45 +74,70 @@ int main(void) } else { - IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle = IoTHubDeviceClient_LL_CreateUploadContext(device_ll_handle, "subdir/hello_world_custom_mb.txt"); + char* uploadCorrelationId; + char* azureBlobSasUri; + const char* bla = "subdir/hello_world_custom_mb.txt"; - if (uploadContextHandle == NULL) + if (IoTHubDeviceClient_LL_InitializeUpload( + device_ll_handle, bla, &uploadCorrelationId, &azureBlobSasUri) != IOTHUB_CLIENT_OK) { - (void)printf("hello world failed to create upload context\n"); + printf("failed initializing upload in IoT Hub\n"); } else { - bool uploadSuccessful = true; - int uploadResultCode = 200; + IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle = IoTHubDeviceClient_LL_CreateUploadContext(device_ll_handle, azureBlobSasUri); - for (uint32_t block_number = 0; block_number < 100; block_number++) + if (uploadContextHandle == NULL) { - int data_size = snprintf(data_to_upload, sizeof(data_to_upload), data_to_upload_format, block_number); + (void)printf("failed to create upload context\n"); + } + else + { + bool uploadSuccessful = true; + int uploadResultCode = 200; - if (IoTHubDeviceClient_LL_UploadBlockToBlob( - uploadContextHandle, block_number, (const uint8_t*)data_to_upload, data_size) != IOTHUB_CLIENT_OK) + for (uint32_t block_number = 0; block_number < 100; block_number++) { - (void)printf("Failed uploading block number %u to blob. Aborting upload.\n", block_number); - uploadSuccessful = false; - uploadResultCode = 300; - break; + int data_size = snprintf(data_to_upload, sizeof(data_to_upload), data_to_upload_format, block_number); + + if (IoTHubDeviceClient_LL_AzureStoragePutBlock( + uploadContextHandle, block_number, (const uint8_t*)data_to_upload, data_size) != IOTHUB_CLIENT_OK) + { + (void)printf("Failed uploading block number %u to blob. Aborting upload.\n", block_number); + uploadSuccessful = false; + uploadResultCode = 300; + break; + } } - } - // Hint: here if there is a failure (e.g., in HTTP transport) - // this function can be called again in a retry loop if desired. - if (IoTHubDeviceClient_LL_CompleteUploadToBlob( - uploadContextHandle, uploadSuccessful, uploadResultCode, uploadSuccessful ? "OK" : "Aborted") - != IOTHUB_CLIENT_OK) - { - (void)printf("Failed notifying Azure IoT Hub of upload completion.\n"); - } - else - { - (void)printf("hello world has been created\n"); + if (uploadSuccessful) + { + if (IoTHubDeviceClient_LL_AzureStoragePutBlockList(uploadContextHandle) != IOTHUB_CLIENT_OK) + { + (void)printf("failed performing Azure Storage Put Blob List.\n"); + uploadSuccessful = false; + uploadResultCode = 400; + } + } + + IoTHubDeviceClient_LL_DestroyUploadContext(uploadContextHandle); + + // Hint: here if there is a failure (e.g., in HTTP transport) + // this function can be called again in a retry loop if desired. + if (IoTHubDeviceClient_LL_NotifyUploadCompletion( + device_ll_handle, uploadCorrelationId, uploadSuccessful, uploadResultCode, uploadSuccessful ? "OK" : "Aborted") + != IOTHUB_CLIENT_OK) + { + (void)printf("Failed notifying Azure IoT Hub of upload completion.\n"); + } + else + { + (void)printf("hello world has been created\n"); + } } - IoTHubDeviceClient_LL_DestroyUploadContext(uploadContextHandle); + free(uploadCorrelationId); + free(azureBlobSasUri); } } // Clean up the iothub sdk handle diff --git a/iothub_client/src/iothub_client_core.c b/iothub_client/src/iothub_client_core.c index d8d137a552..39f0b28a87 100644 --- a/iothub_client/src/iothub_client_core.c +++ b/iothub_client/src/iothub_client_core.c @@ -2486,42 +2486,63 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_UploadMultipleBlocksToBlobAsync(IOTHUB_CLI return result; } -IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubClientCore_CreateUploadContext(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, const char* destinationFileName) +IOTHUB_CLIENT_RESULT IoTHubClientCore_InitializeUpload(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, const char* destinationFileName, char** uploadCorrelationId, char** azureBlobSasUri) +{ + IOTHUB_CLIENT_RESULT result; + + if ( + (iotHubClientHandle == NULL) + ) + { + LogError("invalid parameters iotHubClientHandle = %p", iotHubClientHandle); + result = IOTHUB_CLIENT_INVALID_ARG; + } + else + { + result = IoTHubClientCore_LL_InitializeUpload(iotHubClientHandle->IoTHubClientLLHandle, destinationFileName, uploadCorrelationId, azureBlobSasUri); + } + + return result; +} + +IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubClientCore_CreateUploadContext(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, const char* azureBlobSasUri) { IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE result; if ( - (iotHubClientHandle == NULL) || - (destinationFileName == NULL)) + (iotHubClientHandle == NULL) + ) { - LogError("invalid parameters iotHubClientHandle = %p , destinationFileName = %p", - iotHubClientHandle, - destinationFileName - ); + LogError("invalid parameters iotHubClientHandle = %p", iotHubClientHandle); result = NULL; } else { - result = IoTHubClientCore_LL_CreateUploadContext(iotHubClientHandle->IoTHubClientLLHandle, destinationFileName); + result = IoTHubClientCore_LL_CreateUploadContext(iotHubClientHandle->IoTHubClientLLHandle, azureBlobSasUri); } return result; } -IOTHUB_CLIENT_RESULT IoTHubClientCore_UploadBlockToBlob(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle, uint32_t blockNumber, const uint8_t* dataPtr, size_t dataSize) +IOTHUB_CLIENT_RESULT IoTHubClientCore_AzureStoragePutBlock(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle, uint32_t blockNumber, const uint8_t* dataPtr, size_t dataSize) { - return IoTHubClientCore_LL_UploadBlockToBlob(uploadContextHandle, blockNumber, dataPtr, dataSize); + return IoTHubClientCore_LL_AzureStoragePutBlock(uploadContextHandle, blockNumber, dataPtr, dataSize); } -IOTHUB_CLIENT_RESULT IoTHubClientCore_CompleteUploadToBlob(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle, bool isSuccess, int responseCode, const char* responseMessage) +IOTHUB_CLIENT_RESULT IoTHubClientCore_AzureStoragePutBlockList(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle) { - return IoTHubClientCore_LL_CompleteUploadToBlob(uploadContextHandle, isSuccess, responseCode, responseMessage); + return IoTHubClientCore_LL_AzureStoragePutBlockList(uploadContextHandle); } void IoTHubClientCore_DestroyUploadContext(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle) { IoTHubClientCore_LL_DestroyUploadContext(uploadContextHandle); } + +IOTHUB_CLIENT_RESULT IoTHubClientCore_NotifyUploadCompletion(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, const char* uploadCorrelationId, bool isSuccess, int responseCode, const char* responseMessage) +{ + return IoTHubClientCore_LL_NotifyUploadCompletion(iotHubClientHandle->IoTHubClientLLHandle, uploadCorrelationId, isSuccess, responseCode, responseMessage); +} #endif /*DONT_USE_UPLOADTOBLOB*/ IOTHUB_CLIENT_RESULT IoTHubClientCore_SendEventToOutputAsync(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, IOTHUB_MESSAGE_HANDLE eventMessageHandle, const char* outputName, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK eventConfirmationCallback, void* userContextCallback) diff --git a/iothub_client/src/iothub_client_core_ll.c b/iothub_client/src/iothub_client_core_ll.c index d26325857e..34fa8d376c 100755 --- a/iothub_client/src/iothub_client_core_ll.c +++ b/iothub_client/src/iothub_client_core_ll.c @@ -2706,30 +2706,54 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_UploadToBlob(IOTHUB_CLIENT_CORE_LL_HAND ((source == NULL) && (size >0)) ) { - LogError("invalid parameters IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle=%p, const char* destinationFileName=%s, const unsigned char* source=%p, size_t size=%lu", iotHubClientHandle, destinationFileName, source, (unsigned long)size); + LogError("invalid parameters IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle=%p, const char* destinationFileName=%s, const unsigned char* source=%p, size_t size=%lu", + iotHubClientHandle, destinationFileName, source, (unsigned long)size); result = IOTHUB_CLIENT_INVALID_ARG; } else { - IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext = IoTHubClient_LL_UploadToBlob_CreateContext(iotHubClientHandle->uploadToBlobHandle, destinationFileName); + char* uploadCorrelationId; + char* azureBlobSasUri; - if (uploadContext == NULL) + if (IoTHubClient_LL_UploadToBlob_InitializeUpload( + iotHubClientHandle->uploadToBlobHandle, destinationFileName, &uploadCorrelationId, &azureBlobSasUri) != IOTHUB_CLIENT_OK) { - LogError("Failed creating upload to blob context"); + LogError("Failed initializing upload in IoT Hub"); result = IOTHUB_CLIENT_ERROR; } else { - bool uploadSucceeded = true; + bool uploadSucceeded; + IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext = IoTHubClient_LL_UploadToBlob_CreateContext(iotHubClientHandle->uploadToBlobHandle, azureBlobSasUri); - if (IoTHubClient_LL_UploadToBlob_UploadBlock(uploadContext, 0, source, size) != IOTHUB_CLIENT_OK) + if (uploadContext == NULL) { - LogError("Failed uploading block to Azure Blob Storage"); + LogError("Failed creating upload to blob context"); uploadSucceeded = false; } + else + { + if (IoTHubClient_LL_UploadToBlob_PutBlock(uploadContext, 0, source, size) != IOTHUB_CLIENT_OK) + { + LogError("Failed uploading block to Azure Blob Storage"); + uploadSucceeded = false; + } + else if (IoTHubClient_LL_UploadToBlob_PutBlockList(uploadContext) != IOTHUB_CLIENT_OK) + { + LogError("Failed completing upload to blob."); + uploadSucceeded = false; + } + else + { + uploadSucceeded = true; + } - if (IoTHubClient_LL_UploadToBlob_Complete( - uploadContext, uploadSucceeded, (uploadSucceeded ? 200 : 400), NULL) != IOTHUB_CLIENT_OK) + IoTHubClient_LL_UploadToBlob_DestroyContext(uploadContext); + } + + // TODO (ewertons): fix the http error status below. + if (IoTHubClient_LL_UploadToBlob_NotifyCompletion( + iotHubClientHandle->uploadToBlobHandle, uploadCorrelationId, uploadSucceeded, 400, NULL) != IOTHUB_CLIENT_OK) { LogError("Failed completing upload to blob."); result = IOTHUB_CLIENT_ERROR; @@ -2739,7 +2763,8 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_UploadToBlob(IOTHUB_CLIENT_CORE_LL_HAND result = (uploadSucceeded ? IOTHUB_CLIENT_OK : IOTHUB_CLIENT_ERROR); } - IoTHubClient_LL_UploadToBlob_DestroyContext(uploadContext); + free(uploadCorrelationId); + free(azureBlobSasUri); } } @@ -2774,22 +2799,59 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_UploadMultipleBlocksToBlob(IOTHUB_CLIEN } else { - IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle = IoTHubClient_LL_UploadToBlob_CreateContext(iotHubClientHandle->uploadToBlobHandle, destinationFileName); + char* uploadCorrelationId; + char* azureBlobSasUri; - if (uploadContextHandle == NULL) + if (IoTHubClient_LL_UploadToBlob_InitializeUpload( + iotHubClientHandle->uploadToBlobHandle, destinationFileName, &uploadCorrelationId, &azureBlobSasUri) != IOTHUB_CLIENT_OK) { - LogError("Failed creating upload to blob context"); + LogError("Failed initializing upload in IoT Hub"); result = IOTHUB_CLIENT_ERROR; } else { - UPLOAD_MULTIPLE_BLOCKS_WRAPPER_CONTEXT uploadMultipleBlocksWrapperContext; - uploadMultipleBlocksWrapperContext.getDataCallback = getDataCallback; - uploadMultipleBlocksWrapperContext.context = context; + bool uploadSucceeded; + IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext = IoTHubClient_LL_UploadToBlob_CreateContext(iotHubClientHandle->uploadToBlobHandle, azureBlobSasUri); + + if (uploadContext == NULL) + { + LogError("Failed creating upload to blob context"); + uploadSucceeded = false; + } + else + { + UPLOAD_MULTIPLE_BLOCKS_WRAPPER_CONTEXT uploadMultipleBlocksWrapperContext; + uploadMultipleBlocksWrapperContext.getDataCallback = getDataCallback; + uploadMultipleBlocksWrapperContext.context = context; + + if (IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks( + uploadContext, uploadMultipleBlocksCallbackWrapper, &uploadMultipleBlocksWrapperContext) != IOTHUB_CLIENT_OK) + { + LogError("Failed to upload multiple blocks to Azure blob"); + uploadSucceeded = false; + } + else + { + uploadSucceeded = false; + } - result = IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(uploadContextHandle, uploadMultipleBlocksCallbackWrapper, &uploadMultipleBlocksWrapperContext); + IoTHubClient_LL_UploadToBlob_DestroyContext(uploadContext); + } + + // TODO (ewertons): fix the http error status below. + if (IoTHubClient_LL_UploadToBlob_NotifyCompletion( + iotHubClientHandle->uploadToBlobHandle, uploadCorrelationId, uploadSucceeded, 400, NULL) != IOTHUB_CLIENT_OK) + { + LogError("Failed completing upload to blob."); + result = IOTHUB_CLIENT_ERROR; + } + else + { + result = (uploadSucceeded ? IOTHUB_CLIENT_OK : IOTHUB_CLIENT_ERROR); + } - IoTHubClient_LL_UploadToBlob_DestroyContext(uploadContextHandle); + free(uploadCorrelationId); + free(azureBlobSasUri); } } @@ -2810,44 +2872,108 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx(IOTHUB_CLI } else { - IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle = IoTHubClient_LL_UploadToBlob_CreateContext(iotHubClientHandle->uploadToBlobHandle, destinationFileName); + char* uploadCorrelationId; + char* azureBlobSasUri; - if (uploadContextHandle == NULL) + if (IoTHubClient_LL_UploadToBlob_InitializeUpload( + iotHubClientHandle->uploadToBlobHandle, destinationFileName, &uploadCorrelationId, &azureBlobSasUri) != IOTHUB_CLIENT_OK) { - LogError("Failed creating upload to blob context"); + LogError("Failed initializing upload in IoT Hub"); result = IOTHUB_CLIENT_ERROR; } else { - result = IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(uploadContextHandle, getDataCallbackEx, context); + bool uploadSucceeded; + IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext = IoTHubClient_LL_UploadToBlob_CreateContext(iotHubClientHandle->uploadToBlobHandle, azureBlobSasUri); + + if (uploadContext == NULL) + { + LogError("Failed creating upload to blob context"); + uploadSucceeded = false; + } + else + { + if (IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(uploadContext, getDataCallbackEx, context) != IOTHUB_CLIENT_OK) + { + LogError("Failed to upload multiple blocks to Azure blob"); + uploadSucceeded = false; + } + else + { + uploadSucceeded = false; + } + + IoTHubClient_LL_UploadToBlob_DestroyContext(uploadContext); + } - IoTHubClient_LL_UploadToBlob_DestroyContext(uploadContextHandle); + // TODO (ewertons): fix the http error status below. + if (IoTHubClient_LL_UploadToBlob_NotifyCompletion( + iotHubClientHandle->uploadToBlobHandle, uploadCorrelationId, uploadSucceeded, 400, NULL) != IOTHUB_CLIENT_OK) + { + LogError("Failed completing upload to blob."); + result = IOTHUB_CLIENT_ERROR; + } + else + { + result = (uploadSucceeded ? IOTHUB_CLIENT_OK : IOTHUB_CLIENT_ERROR); + } + + free(uploadCorrelationId); + free(azureBlobSasUri); + } + } + + return result; +} + +IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_InitializeUpload(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, const char* destinationFileName, char** uploadCorrelationId, char** azureBlobSasUri) +{ + IOTHUB_CLIENT_RESULT result; + + if ( + (iotHubClientHandle == NULL) + ) + { + LogError("invalid parameters IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle=%p", iotHubClientHandle); + result = IOTHUB_CLIENT_INVALID_ARG; + } + else + { + if (IoTHubClient_LL_UploadToBlob_InitializeUpload( + iotHubClientHandle->uploadToBlobHandle, destinationFileName, uploadCorrelationId, azureBlobSasUri) != IOTHUB_CLIENT_OK) + { + LogError("Failed initializing upload in IoT Hub"); + result = IOTHUB_CLIENT_ERROR; + } + else + { + result = IOTHUB_CLIENT_OK; } } return result; } -IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubClientCore_LL_CreateUploadContext(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, const char* destinationFileName) +IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubClientCore_LL_CreateUploadContext(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, const char* azureBlobSasUri) { IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE result; if ( (iotHubClientHandle == NULL) || - (destinationFileName == NULL) + (azureBlobSasUri == NULL) ) { - LogError("invalid parameters IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle=%p, destinationFileName=%p", iotHubClientHandle, destinationFileName); + LogError("invalid parameters IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle=%p, azureBlobSasUri=%p", iotHubClientHandle, azureBlobSasUri); result = NULL; } else { - result = IoTHubClient_LL_UploadToBlob_CreateContext(iotHubClientHandle->uploadToBlobHandle, destinationFileName); + result = IoTHubClient_LL_UploadToBlob_CreateContext(iotHubClientHandle->uploadToBlobHandle, azureBlobSasUri); } return result; } -IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_UploadBlockToBlob(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle, uint32_t blockNumber, const uint8_t* dataPtr, size_t dataSize) +IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_AzureStoragePutBlock(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle, uint32_t blockNumber, const uint8_t* dataPtr, size_t dataSize) { IOTHUB_CLIENT_RESULT result; @@ -2862,13 +2988,13 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_UploadBlockToBlob(IOTHUB_CLIENT_LL_UPLO } else { - result = IoTHubClient_LL_UploadToBlob_UploadBlock(uploadContextHandle, blockNumber, dataPtr, dataSize); + result = IoTHubClient_LL_UploadToBlob_PutBlock(uploadContextHandle, blockNumber, dataPtr, dataSize); } return result; } -IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_CompleteUploadToBlob(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle, bool isSuccess, int responseCode, const char* responseMessage) +IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_AzureStoragePutBlockList(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle) { IOTHUB_CLIENT_RESULT result; @@ -2881,7 +3007,26 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_CompleteUploadToBlob(IOTHUB_CLIENT_LL_U } else { - result = IoTHubClient_LL_UploadToBlob_Complete(uploadContextHandle, isSuccess, responseCode, responseMessage); + result = IoTHubClient_LL_UploadToBlob_PutBlockList(uploadContextHandle); + } + + return result; +} + +IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_NotifyUploadCompletion(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, const char* uploadCorrelationId, bool isSuccess, int responseCode, const char* responseMessage) +{ + IOTHUB_CLIENT_RESULT result; + + if ( + (iotHubClientHandle == NULL) + ) + { + LogError("invalid parameters iotHubClientHandle=%p", iotHubClientHandle); + result = IOTHUB_CLIENT_INVALID_ARG; + } + else + { + result = IoTHubClient_LL_UploadToBlob_NotifyCompletion(iotHubClientHandle->uploadToBlobHandle, uploadCorrelationId, isSuccess, responseCode, responseMessage); } return result; diff --git a/iothub_client/src/iothub_client_ll_uploadtoblob.c b/iothub_client/src/iothub_client_ll_uploadtoblob.c index 2cd093da15..d7754c22e6 100644 --- a/iothub_client/src/iothub_client_ll_uploadtoblob.c +++ b/iothub_client/src/iothub_client_ll_uploadtoblob.c @@ -31,7 +31,8 @@ static const char* const RESPONSE_BODY_FORMAT = "{\"correlationId\":\"%s\", \"is static const char* const RESPONSE_BODY_ABORTED_MESSAGE = "file upload aborted"; static const char* const RESPONSE_BODY_BLOCK_SIZE_EXCEEDED_MESSAGE = "block data size exceeded"; static const char* const RESPONSE_BODY_BLOCK_COUNT_EXCEEDED_MESSAGE = "block count exceeded"; -static const char* const RESPONSE_BODY_UPLOAD_FAILED_MESSAGE = "block upload failed"; +static const char* const RESPONSE_BODY_PUT_BLOCK_FAILED_MESSAGE = "put block failed"; +static const char* const RESPONSE_BODY_PUT_BLOCK_LIST_FAILED_MESSAGE = "put block list failed"; static const int RESPONSE_BODY_ERROR_RETURN_CODE = -1; static const char* const RESPONSE_BODY_SUCCESS_BOOLEAN_STRING = "true"; static const char* const RESPONSE_BODY_ERROR_BOOLEAN_STRING = "false"; @@ -92,8 +93,6 @@ typedef struct IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_STRUCT { IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* u2bClientData; - /* ID of the upload as provided by the Azure IoT Hub */ - STRING_HANDLE correlationId; char* blobStorageHostname; char* blobStorageRelativePath; SINGLYLINKEDLIST_HANDLE blockIdList; @@ -173,12 +172,12 @@ static int send_http_request(HTTPAPIEX_HANDLE http_api_handle, const char* relat return result; } -static int parseResultFromIoTHub(const char* json_response, STRING_HANDLE correlation_id, STRING_HANDLE sas_uri) +static int parseResultFromIoTHub(const char* json_response, char** uploadCorrelationId, char** azureBlobSasUri) { int result; - JSON_Object* json_obj; JSON_Value* json = json_parse_string(json_response); + if (json == NULL) { LogError("unable to json_parse_string"); @@ -200,6 +199,7 @@ static int parseResultFromIoTHub(const char* json_response, STRING_HANDLE correl const char* json_blob_name; const char* json_sas_token; STRING_HANDLE filename; + if ((json_corr_id = json_object_get_string(json_obj, "correlationId")) == NULL) { LogError("unable to retrieve correlation Id from json"); @@ -232,26 +232,47 @@ static int parseResultFromIoTHub(const char* json_response, STRING_HANDLE correl } else { - if (STRING_sprintf(sas_uri, "https://%s/%s/%s%s", json_hostname, json_container_name, STRING_c_str(filename), json_sas_token) != 0) - { - LogError("unable to construct uri string"); - result = MU_FAILURE; - } - else if (STRING_copy(correlation_id, json_corr_id) != 0) + STRING_HANDLE sas_uri; + + if ((sas_uri = STRING_new()) == NULL) { - LogError("unable to copy correlation Id"); + LogError("Failed to allocate SAS URI STRING_HANDLE"); result = MU_FAILURE; - STRING_empty(sas_uri); } else { - result = 0; + if (STRING_sprintf(sas_uri, "https://%s/%s/%s%s", json_hostname, json_container_name, STRING_c_str(filename), json_sas_token) != 0) + { + LogError("unable to construct uri string"); + result = MU_FAILURE; + } + else if (mallocAndStrcpy_s(uploadCorrelationId, json_corr_id) != 0) + { + LogError("unable to copy correlation Id"); + result = MU_FAILURE; + } + else if (mallocAndStrcpy_s(azureBlobSasUri, STRING_c_str(sas_uri)) != 0) + { + LogError("unable to copy Sas URI"); + free(*uploadCorrelationId); + *uploadCorrelationId = NULL; + result = MU_FAILURE; + } + else + { + result = 0; + } + + STRING_delete(sas_uri); } + STRING_delete(filename); } } + json_value_free(json); } + return result; } @@ -446,7 +467,8 @@ static HTTPAPIEX_HANDLE createIotHubHttpApiExHandle(IOTHUB_CLIENT_LL_UPLOADTOBLO return iotHubHttpApiExHandle; } -static int IoTHubClient_LL_UploadToBlob_GetBlobCredentialsFromIoTHub(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_data, const char* destinationFileName, STRING_HANDLE correlationId, STRING_HANDLE sasUri) +static int IoTHubClient_LL_UploadToBlob_GetBlobCredentialsFromIoTHub( + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_data, const char* destinationFileName, char** correlationId, char** sasUri) { int result; STRING_HANDLE relativePath = STRING_construct_sprintf("/devices/%s/files/%s", upload_data->deviceId, API_VERSION); @@ -693,13 +715,6 @@ static IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT* createUploadToBlobContextInstance( free(result); result = NULL; } - else if ((result->correlationId = STRING_new()) == NULL) - { - LogError("unable to STRING_new"); - singlylinkedlist_destroy(result->blockIdList); - free(result); - result = NULL; - } } return result; @@ -717,24 +732,24 @@ static void destroyUploadToBlobContextInstance(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CON singlylinkedlist_destroy(uploadContext->blockIdList); } - STRING_delete(uploadContext->correlationId); free(uploadContext->blobStorageHostname); free(uploadContext->blobStorageRelativePath); free(uploadContext); } } -static int parseAzureBlobSasUri(STRING_HANDLE sasUri, char** blobStorageHostname, char** blobStorageRelativePath) +static int parseAzureBlobSasUri(const char* sasUri, char** blobStorageHostname, char** blobStorageRelativePath) { int result; const char* hostnameBegin; char* hostname = NULL; char* relativePath = NULL; + int sasUriLength = strlen(sasUri); /*to find the hostname, the following logic is applied:*/ /*the hostname starts at the first character after "://"*/ /*the hostname ends at the first character before the next "/" after "://"*/ - if ((hostnameBegin = strstr(STRING_c_str(sasUri), "://")) == NULL) + if ((hostnameBegin = strstr(sasUri, "://")) == NULL) { LogError("hostname cannot be determined"); result = MU_FAILURE; @@ -762,7 +777,7 @@ static int parseAzureBlobSasUri(STRING_HANDLE sasUri, char** blobStorageHostname { (void)memcpy(hostname, hostnameBegin, hostnameSize); hostname[hostnameSize] = '\0'; - size_t relativePathSize = STRING_length(sasUri) - (relativePathBegin - STRING_c_str(sasUri)); + size_t relativePathSize = sasUriLength - (relativePathBegin - sasUri); if ((relativePath = malloc(relativePathSize + 1)) == NULL) { @@ -873,13 +888,42 @@ IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE IoTHubClient_LL_UploadToBlob_Create(const I return (IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE)upload_data; } -IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubClient_LL_UploadToBlob_CreateContext(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE handle, const char* destinationFileName) +IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_InitializeUpload(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE handle, const char* destinationFileName, char** uploadCorrelationId, char** azureBlobSasUri) +{ + IOTHUB_CLIENT_RESULT result; + + if (handle == NULL || destinationFileName == NULL || uploadCorrelationId == NULL) + { + LogError("invalid argument detected handle=%p destinationFileName=%p uploadCorrelationId=%p azureBlobSasUri=%p", + handle, destinationFileName, uploadCorrelationId, azureBlobSasUri); + result = IOTHUB_CLIENT_INVALID_ARG; + } + else + { + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_data = (IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA*)handle; + + if (IoTHubClient_LL_UploadToBlob_GetBlobCredentialsFromIoTHub( + upload_data, destinationFileName, uploadCorrelationId, azureBlobSasUri) != 0) + { + LogError("error in IoTHubClient_LL_UploadToBlob_GetBlobCredentialsFromIoTHub"); + result = IOTHUB_CLIENT_ERROR; + } + else + { + result = IOTHUB_CLIENT_OK; + } + } + + return result; +} + +IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubClient_LL_UploadToBlob_CreateContext(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE handle, const char* azureBlobSasUri) { IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT* result; - if (handle == NULL || destinationFileName == NULL) + if (handle == NULL || azureBlobSasUri == NULL) { - LogError("invalid argument detected handle=%p destinationFileName=%p", handle, destinationFileName); + LogError("invalid argument detected handle=%p azureBlobSasUri=%p", handle, azureBlobSasUri); result = NULL; } else if ((result = createUploadToBlobContextInstance()) == NULL) @@ -889,50 +933,30 @@ IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubClient_LL_UploadToBlob_Create else { IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_data = (IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA*)handle; - STRING_HANDLE sasUri; - if ((sasUri = STRING_new()) == NULL) + if (parseAzureBlobSasUri(azureBlobSasUri, &result->blobStorageHostname, &result->blobStorageRelativePath) != 0) { - LogError("Failed to allocate STRING_HANDLE for SAS URI"); + LogError("failed parsing Blob Storage SAS URI"); destroyUploadToBlobContextInstance(result); result = NULL; } else { - /*do step 1*/ - if (IoTHubClient_LL_UploadToBlob_GetBlobCredentialsFromIoTHub( - upload_data, destinationFileName, result->correlationId, sasUri) != 0) - { - LogError("error in IoTHubClient_LL_UploadToBlob_GetBlobCredentialsFromIoTHub"); - destroyUploadToBlobContextInstance(result); - result = NULL; - } - else if (parseAzureBlobSasUri(sasUri, &result->blobStorageHostname, &result->blobStorageRelativePath) != 0) + result->u2bClientData = upload_data; + + result->blobHttpApiHandle = Blob_CreateHttpConnection( + result->blobStorageHostname, + result->u2bClientData->certificates, + &(result->u2bClientData->http_proxy_options), + result->u2bClientData->networkInterface, + result->u2bClientData->blob_upload_timeout_millisecs); + + if (result->blobHttpApiHandle == NULL) { - LogError("failed parsing Blob Storage SAS URI"); + LogError("Failed creating HTTP connection to Azure Blob"); destroyUploadToBlobContextInstance(result); result = NULL; } - else - { - result->u2bClientData = upload_data; - - result->blobHttpApiHandle = Blob_CreateHttpConnection( - result->blobStorageHostname, - result->u2bClientData->certificates, - &(result->u2bClientData->http_proxy_options), - result->u2bClientData->networkInterface, - result->u2bClientData->blob_upload_timeout_millisecs); - - if (result->blobHttpApiHandle == NULL) - { - LogError("Failed creating HTTP connection to Azure Blob"); - destroyUploadToBlobContextInstance(result); - result = NULL; - } - } - - STRING_delete(sasUri); } } @@ -957,7 +981,7 @@ IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_DestroyContext(IOTHUB_CLIENT_L return result; } -IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_UploadBlock(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext, uint32_t blockNumber, const uint8_t* dataPtr, size_t dataSize) +IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_PutBlock(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext, uint32_t blockNumber, const uint8_t* dataPtr, size_t dataSize) { IOTHUB_CLIENT_RESULT result; @@ -1001,7 +1025,7 @@ IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_UploadBlock(IOTHUB_CLIENT_LL_U return result; } -IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_Complete(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext, bool isSuccess, int responseCode, const char* responseMessage) +IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_PutBlockList(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext) { IOTHUB_CLIENT_RESULT result; @@ -1016,7 +1040,7 @@ IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_Complete(IOTHUB_CLIENT_LL_UPLO // Do not PUT BLOCK LIST if result is not success (isSuccess == false) // Otherwise we could corrupt a blob with a partial update. - if (isSuccess && Blob_PutBlockList( + if (Blob_PutBlockList( uploadContext->blobHttpApiHandle, uploadContext->blobStorageRelativePath, uploadContext->blockIdList, &putBlockListHttpStatus, NULL) != BLOB_OK) @@ -1026,54 +1050,71 @@ IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_Complete(IOTHUB_CLIENT_LL_UPLO } else { - IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_data = (IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA*)uploadContext->u2bClientData; + result = IOTHUB_CLIENT_OK; + } + } - STRING_HANDLE response = STRING_construct_sprintf(RESPONSE_BODY_FORMAT, - STRING_c_str(uploadContext->correlationId), - isSuccess ? RESPONSE_BODY_SUCCESS_BOOLEAN_STRING : RESPONSE_BODY_ERROR_BOOLEAN_STRING, - responseCode, - responseMessage); + return result; +} - if(response == NULL) +IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_NotifyCompletion(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE handle, const char* uploadCorrelationId, bool isSuccess, int responseCode, const char* responseMessage) +{ + IOTHUB_CLIENT_RESULT result; + + if (handle == NULL || uploadCorrelationId == NULL) + { + LogError("invalid argument detected handle=%p uploadCorrelationId=%p", handle, uploadCorrelationId); + result = IOTHUB_CLIENT_INVALID_ARG; + } + else + { + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_data = (IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA*)handle; + + STRING_HANDLE response = STRING_construct_sprintf(RESPONSE_BODY_FORMAT, + uploadCorrelationId, + isSuccess ? RESPONSE_BODY_SUCCESS_BOOLEAN_STRING : RESPONSE_BODY_ERROR_BOOLEAN_STRING, + responseCode, + responseMessage); + + if(response == NULL) + { + LogError("STRING_construct_sprintf failed"); + result = IOTHUB_CLIENT_ERROR; + } + else + { + size_t response_length = STRING_length(response); + BUFFER_HANDLE responseToIoTHub = BUFFER_new(); + + if (responseToIoTHub == NULL) { - LogError("STRING_construct_sprintf failed"); + LogError("BUFFER_new failed"); result = IOTHUB_CLIENT_ERROR; } else { - size_t response_length = STRING_length(response); - BUFFER_HANDLE responseToIoTHub = BUFFER_new(); - - if (responseToIoTHub == NULL) + if (BUFFER_build(responseToIoTHub, (const unsigned char*)STRING_c_str(response), response_length) == 0) { - LogError("BUFFER_new failed"); - result = IOTHUB_CLIENT_ERROR; - } - else - { - if (BUFFER_build(responseToIoTHub, (const unsigned char*)STRING_c_str(response), response_length) == 0) + if (IoTHubClient_LL_UploadToBlob_NotifyIoTHubOfUploadCompletion(upload_data, responseToIoTHub) != 0) { - if (IoTHubClient_LL_UploadToBlob_NotifyIoTHubOfUploadCompletion(upload_data, responseToIoTHub) != 0) - { - LogError("IoTHubClient_LL_UploadToBlob_NotifyIoTHubOfUploadCompletion failed"); - result = IOTHUB_CLIENT_ERROR; - } - else - { - result = IOTHUB_CLIENT_OK; - } + LogError("IoTHubClient_LL_UploadToBlob_NotifyIoTHubOfUploadCompletion failed"); + result = IOTHUB_CLIENT_ERROR; } else { - LogError("Unable to BUFFER_build, can't perform IoTHubClient_LL_UploadToBlob_NotifyIoTHubOfUploadCompletion"); - result = IOTHUB_CLIENT_ERROR; + result = IOTHUB_CLIENT_OK; } - - BUFFER_delete(responseToIoTHub); + } + else + { + LogError("Unable to BUFFER_build, can't perform IoTHubClient_LL_UploadToBlob_NotifyIoTHubOfUploadCompletion"); + result = IOTHUB_CLIENT_ERROR; } - STRING_delete(response); + BUFFER_delete(responseToIoTHub); } + + STRING_delete(response); } } @@ -1133,11 +1174,11 @@ IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(IOTHUB_CL responseToIoTHub = RESPONSE_BODY_BLOCK_COUNT_EXCEEDED_MESSAGE; break; } - else if (IoTHubClient_LL_UploadToBlob_UploadBlock(uploadContextHandle, blockID, blockDataPtr, blockDataSize) != IOTHUB_CLIENT_OK) + else if (IoTHubClient_LL_UploadToBlob_PutBlock(uploadContextHandle, blockID, blockDataPtr, blockDataSize) != IOTHUB_CLIENT_OK) { LogError("failed uploading block to blob"); uploadHttpStatus = HTTP_STATUS_CODE_BAD_REQUEST; - responseToIoTHub = RESPONSE_BODY_UPLOAD_FAILED_MESSAGE; + responseToIoTHub = RESPONSE_BODY_PUT_BLOCK_FAILED_MESSAGE; break; } @@ -1146,10 +1187,14 @@ IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(IOTHUB_CL } while(true); - if (IoTHubClient_LL_UploadToBlob_Complete( - uploadContextHandle, IS_HTTP_STATUS_CODE_SUCCESS(uploadHttpStatus), uploadHttpStatus, responseToIoTHub) != IOTHUB_CLIENT_OK) + if (!IS_HTTP_STATUS_CODE_SUCCESS(uploadHttpStatus)) + { + (void)getDataCallbackEx(FILE_UPLOAD_ERROR, NULL, NULL, context); + result = IOTHUB_CLIENT_ERROR; + } + else if (IoTHubClient_LL_UploadToBlob_PutBlockList(uploadContextHandle) != IOTHUB_CLIENT_OK) { - LogError("Failed notifying IoT Hub of upload completion"); + LogError("Failed to perform Azure Blob Put Block List operation"); (void)getDataCallbackEx(FILE_UPLOAD_ERROR, NULL, NULL, context); result = IOTHUB_CLIENT_ERROR; } diff --git a/iothub_client/src/iothub_device_client.c b/iothub_client/src/iothub_device_client.c index 35408e50e6..25f4ee8a3c 100644 --- a/iothub_client/src/iothub_device_client.c +++ b/iothub_client/src/iothub_device_client.c @@ -115,24 +115,34 @@ IOTHUB_CLIENT_RESULT IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync(IOTHUB_D return IoTHubClientCore_UploadMultipleBlocksToBlobAsync((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, destinationFileName, NULL, getDataCallbackEx, context); } -IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubDeviceClient_CreateUploadContext(IOTHUB_DEVICE_CLIENT_HANDLE iotHubClientHandle, const char* destinationFileName) +IOTHUB_CLIENT_RESULT IoTHubDeviceClient_InitializeUpload(IOTHUB_DEVICE_CLIENT_HANDLE iotHubClientHandle, const char* destinationFileName, char** uploadCorrelationId, char** azureBlobSasUri) { - return IoTHubClientCore_CreateUploadContext((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, destinationFileName); + return IoTHubClientCore_InitializeUpload((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, destinationFileName, uploadCorrelationId, azureBlobSasUri); } -IOTHUB_CLIENT_RESULT IoTHubDeviceClient_UploadBlockToBlob(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle, uint32_t blockNumber, const uint8_t* dataPtr, size_t dataSize) +IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubDeviceClient_CreateUploadContext(IOTHUB_DEVICE_CLIENT_HANDLE iotHubClientHandle, const char* azureBlobSasUri) { - return IoTHubClientCore_LL_UploadBlockToBlob(uploadContextHandle, blockNumber, dataPtr, dataSize); + return IoTHubClientCore_CreateUploadContext((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, azureBlobSasUri); } -IOTHUB_CLIENT_RESULT IoTHubDeviceClient_CompleteUploadToBlob(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle, bool isSuccess, int responseCode, const char* responseMessage) +IOTHUB_CLIENT_RESULT IoTHubDeviceClient_AzureStoragePutBlock(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle, uint32_t blockNumber, const uint8_t* dataPtr, size_t dataSize) { - return IoTHubClientCore_CompleteUploadToBlob(uploadContextHandle, isSuccess, responseCode, responseMessage); + return IoTHubClientCore_AzureStoragePutBlock(uploadContextHandle, blockNumber, dataPtr, dataSize); +} + +IOTHUB_CLIENT_RESULT IoTHubDeviceClient_AzureStoragePutBlockList(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle) +{ + return IoTHubClientCore_AzureStoragePutBlockList(uploadContextHandle); } void IoTHubDeviceClient_DestroyUploadContext(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle) { - IoTHubClientCore_LL_DestroyUploadContext(uploadContextHandle); + IoTHubClientCore_DestroyUploadContext(uploadContextHandle); +} + +IOTHUB_CLIENT_RESULT IoTHubDeviceClient_NotifyUploadCompletion(IOTHUB_DEVICE_CLIENT_HANDLE iotHubClientHandle, const char* uploadCorrelationId, bool isSuccess, int responseCode, const char* responseMessage) +{ + return IoTHubClientCore_NotifyUploadCompletion((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, uploadCorrelationId, isSuccess, responseCode, responseMessage); } #endif /*DONT_USE_UPLOADTOBLOB*/ diff --git a/iothub_client/src/iothub_device_client_ll.c b/iothub_client/src/iothub_device_client_ll.c index f4712833c1..e2f87fd2b4 100644 --- a/iothub_client/src/iothub_device_client_ll.c +++ b/iothub_client/src/iothub_device_client_ll.c @@ -137,25 +137,35 @@ IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob(IOTHUB_DEV return IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, destinationFileName, getDataCallbackEx, context); } -IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubDeviceClient_LL_CreateUploadContext(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, const char* destinationFileName) +IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_InitializeUpload(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, const char* destinationFileName, char** uploadCorrelationId, char** azureBlobSasUri) { - return IoTHubClientCore_LL_CreateUploadContext((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, destinationFileName); + return IoTHubClientCore_LL_InitializeUpload((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, destinationFileName, uploadCorrelationId, azureBlobSasUri); } -IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_UploadBlockToBlob(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle, uint32_t blockNumber, const uint8_t* dataPtr, size_t dataSize) +IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubDeviceClient_LL_CreateUploadContext(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, const char* azureBlobSasUri) { - return IoTHubClientCore_LL_UploadBlockToBlob(uploadContextHandle, blockNumber, dataPtr, dataSize); + return IoTHubClientCore_LL_CreateUploadContext((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, azureBlobSasUri); } -IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_CompleteUploadToBlob(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle, bool isSuccess, int responseCode, const char* responseMessage) +IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_AzureStoragePutBlock(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle, uint32_t blockNumber, const uint8_t* dataPtr, size_t dataSize) { - return IoTHubClientCore_LL_CompleteUploadToBlob(uploadContextHandle, isSuccess, responseCode, responseMessage); + return IoTHubClientCore_LL_AzureStoragePutBlock(uploadContextHandle, blockNumber, dataPtr, dataSize); +} + +IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_AzureStoragePutBlockList(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle) +{ + return IoTHubClientCore_LL_AzureStoragePutBlockList(uploadContextHandle); } void IoTHubDeviceClient_LL_DestroyUploadContext(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle) { IoTHubClientCore_LL_DestroyUploadContext(uploadContextHandle); } + +IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_NotifyUploadCompletion(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, const char* uploadCorrelationId, bool isSuccess, int responseCode, const char* responseMessage) +{ + return IoTHubClientCore_LL_NotifyUploadCompletion((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, uploadCorrelationId, isSuccess, responseCode, responseMessage); +} #endif IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_SendTelemetryAsync(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, IOTHUB_MESSAGE_HANDLE telemetryMessageHandle, IOTHUB_CLIENT_TELEMETRY_CALLBACK telemetryConfirmationCallback, void* userContextCallback) From e176cef5c48ba6cc35aa50ab98bfb9099ea86db1 Mon Sep 17 00:00:00 2001 From: Ewerton Scaboro da Silva Date: Mon, 10 Jul 2023 21:30:57 -0700 Subject: [PATCH 03/27] Address code review comments (2) --- .../internal/iothub_client_ll_uploadtoblob.h | 15 ++++++++--- iothub_client/inc/iothub_client_core_ll.h | 1 - iothub_client/inc/iothub_device_client.h | 26 +++++++++++++++++-- iothub_client/inc/iothub_device_client_ll.h | 16 ++++++++++-- .../iothub_client_sample_upload_to_blob.c | 3 ++- ...thub_client_sample_upload_to_blob_custom.c | 4 +-- .../iothub_client_sample_upload_to_blob_mb.c | 3 ++- iothub_client/src/blob.c | 14 +++++++--- iothub_client/src/iothub_client_core.c | 4 +-- 9 files changed, 68 insertions(+), 18 deletions(-) diff --git a/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h b/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h index fbf263fe0e..ee599dbe20 100644 --- a/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h +++ b/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h @@ -40,15 +40,24 @@ extern "C" #define BLOCK_SIZE (100*1024*1024) typedef struct IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE; + + /* + * @remark `struct IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_STRUCT` contains information specifically + * related to an individual upload request currently active in Azure IoT Hub, mainly + * the correlation-id and Azure Blob SAS URI provided by the Azure IoT Hub when a new + * upload is started. The `struct IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA` on the other hand + * holds common information (independent from individual upload requests) that is used for + * upload-to-blob Rest API calls to Azure IoT Hub. + */ typedef struct IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_STRUCT* IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE; MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, IoTHubClient_LL_UploadToBlob_Create, const IOTHUB_CLIENT_CONFIG*, config, IOTHUB_AUTHORIZATION_HANDLE, auth_handle); /* - * @remark This is a function left in this module for legacy compatibility with the exposed public API for + * @remark This is a legacy function that provides compatibility with the exposed public API for * upload to blob in iothub_(device|module)_client(_ll) that allowed passing a callback for obtaining the - * blob blocks data. Since there was quite a lot of (specific) logic put into this function that it - * better reside in this API module. + * blob blocks data. Since there was quite a lot of (specific) logic put into this function, it + * better remain in this API module. */ MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context); diff --git a/iothub_client/inc/iothub_client_core_ll.h b/iothub_client/inc/iothub_client_core_ll.h index 53d3920c4b..9cb2ea29ba 100644 --- a/iothub_client/inc/iothub_client_core_ll.h +++ b/iothub_client/inc/iothub_client_core_ll.h @@ -1,4 +1,3 @@ - // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. diff --git a/iothub_client/inc/iothub_device_client.h b/iothub_client/inc/iothub_device_client.h index 3acb33499b..d6637386d9 100644 --- a/iothub_client/inc/iothub_device_client.h +++ b/iothub_client/inc/iothub_device_client.h @@ -355,7 +355,10 @@ extern "C" * This function is expected to be used along with: * `IoTHubDeviceClient_CreateUploadContext` * `IoTHubDeviceClient_AzureStoragePutBlock` + * `IoTHubDeviceClient_AzureStoragePutBlockList` * `IoTHubDeviceClient_DestroyUploadContext` + * `IoTHubDeviceClient_InitializeUpload` + * `IoTHubDeviceClient_NotifyUploadCompletion` * For the standard less-granular uploads to blob please use either * `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`. * @@ -378,7 +381,10 @@ extern "C" * This function is expected to be used along with: * `IoTHubDeviceClient_CreateUploadContext` * `IoTHubDeviceClient_AzureStoragePutBlock` + * `IoTHubDeviceClient_AzureStoragePutBlockList` * `IoTHubDeviceClient_DestroyUploadContext` + * `IoTHubDeviceClient_InitializeUpload` + * `IoTHubDeviceClient_NotifyUploadCompletion` * For the standard less-granular uploads to blob please use either * `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`. * @@ -392,14 +398,19 @@ extern "C" MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, IoTHubDeviceClient_CreateUploadContext, IOTHUB_DEVICE_CLIENT_HANDLE, iotHubClientHandle, const char*, azureBlobSasUri); /** - * @brief This API upload a single blob block to Azure Storage (performs a PUT BLOCK operation). + * @brief This API uploads a single blob block to Azure Storage (performs a PUT BLOCK operation). * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. * This function is expected to be used along with: * `IoTHubDeviceClient_CreateUploadContext` * `IoTHubDeviceClient_AzureStoragePutBlock` + * `IoTHubDeviceClient_AzureStoragePutBlockList` * `IoTHubDeviceClient_DestroyUploadContext` + * `IoTHubDeviceClient_InitializeUpload` + * `IoTHubDeviceClient_NotifyUploadCompletion` * For the standard less-granular uploads to blob please use either * `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`. + * For more information about Azure Storage PUT BLOCK, its parameters and behavior, please refer to + * https://learn.microsoft.com/en-us/rest/api/storageservices/put-block * * @param uploadContextHandle The handle created with `IoTHubDeviceClient_CreateUploadContext`. * @param blockNumber Number of the block being uploaded. @@ -418,12 +429,17 @@ extern "C" * This function is expected to be used along with: * `IoTHubDeviceClient_CreateUploadContext` * `IoTHubDeviceClient_AzureStoragePutBlock` + * `IoTHubDeviceClient_AzureStoragePutBlockList` * `IoTHubDeviceClient_DestroyUploadContext` + * `IoTHubDeviceClient_InitializeUpload` + * `IoTHubDeviceClient_NotifyUploadCompletion` * For the standard less-granular uploads to blob please use either * `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`. * If this function fails (due to any HTTP error to Azure Storage) it can * be run again for a discretionary number of times in an attempt to succeed after, for example, - * an internet connectivity disruption is over. + * an internet connectivity disruption is over. + * For more information about Azure Storage PUT BLOCK LIST, please refer to + * https://learn.microsoft.com/en-us/rest/api/storageservices/put-block-list * * @param uploadContextHandle The handle created with `IoTHubDeviceClient_CreateUploadContext`. * @@ -439,6 +455,9 @@ extern "C" * This function is expected to be used along with: * `IoTHubDeviceClient_CreateUploadContext` * `IoTHubDeviceClient_AzureStoragePutBlock` + * `IoTHubDeviceClient_AzureStoragePutBlockList` + * `IoTHubDeviceClient_DestroyUploadContext` + * `IoTHubDeviceClient_InitializeUpload` * `IoTHubDeviceClient_NotifyUploadCompletion` * For the standard less-granular uploads to blob please use either * `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`. @@ -457,7 +476,10 @@ extern "C" * This function is expected to be used along with: * `IoTHubDeviceClient_CreateUploadContext` * `IoTHubDeviceClient_AzureStoragePutBlock` + * `IoTHubDeviceClient_AzureStoragePutBlockList` * `IoTHubDeviceClient_DestroyUploadContext` + * `IoTHubDeviceClient_InitializeUpload` + * `IoTHubDeviceClient_NotifyUploadCompletion` * For the standard less-granular uploads to blob please use either * `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`. * If this function fails (due to any HTTP error to either Azure Storage or Azure IoT Hub) it can diff --git a/iothub_client/inc/iothub_device_client_ll.h b/iothub_client/inc/iothub_device_client_ll.h index 2e55c98f08..df29e92bce 100644 --- a/iothub_client/inc/iothub_device_client_ll.h +++ b/iothub_client/inc/iothub_device_client_ll.h @@ -395,6 +395,8 @@ typedef struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA_TAG* IOTHUB_DEVICE_CLIENT_LL_HA * @param azureBlobSasUri Variable where to store the Azure Storage SAS URI for the new upload. * * @warning This is a synchronous/blocking function. + * This function only attempts to send HTTP requests once, it does not retry in case of failure. + * Any retries must be explicitly implemented by the calling application. * `uploadCorrelationId` and `azureBlobSasUri` must be freed by the calling application * after the blob upload process is done (e.g., after calling `IoTHubDeviceClient_LL_NotifyUploadCompletion`). * @@ -422,7 +424,7 @@ typedef struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA_TAG* IOTHUB_DEVICE_CLIENT_LL_HA MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, IoTHubDeviceClient_LL_CreateUploadContext, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, azureBlobSasUri); /** - * @brief This API upload a single blob block to Azure Storage (performs a PUT BLOCK operation). + * @brief This API uploads a single blob block to Azure Storage (performs a PUT BLOCK operation). * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. * This function is expected to be used along with: * `IoTHubDeviceClient_LL_CreateUploadContext` @@ -430,6 +432,8 @@ typedef struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA_TAG* IOTHUB_DEVICE_CLIENT_LL_HA * `IoTHubDeviceClient_LL_DestroyUploadContext` * For the standard less-granular uploads to blob please use either * `IoTHubDeviceClient_LL_UploadToBlob` or `IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob`. + * For more information about Azure Storage PUT BLOCK, its parameters and behavior, please refer to + * https://learn.microsoft.com/en-us/rest/api/storageservices/put-block * * @param uploadContextHandle The handle created with `IoTHubDeviceClient_LL_CreateUploadContext`. * @param blockNumber Number of the block being uploaded. @@ -437,6 +441,8 @@ typedef struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA_TAG* IOTHUB_DEVICE_CLIENT_LL_HA * @param dataSize Size of the block data pointed by `dataPtr`. * * @warning This is a synchronous/blocking function. + * This function only attempts to send HTTP requests once, it does not retry in case of failure. + * Any retries must be explicitly implemented by the calling application. * * @return IOTHUB_CLIENT_OK upon success or an error code upon failure. */ @@ -451,10 +457,14 @@ typedef struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA_TAG* IOTHUB_DEVICE_CLIENT_LL_HA * `IoTHubDeviceClient_LL_DestroyUploadContext` * For the standard less-granular uploads to blob please use either * `IoTHubDeviceClient_LL_UploadToBlob` or `IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob`. + * For more information about Azure Storage PUT BLOCK LIST, please refer to + * https://learn.microsoft.com/en-us/rest/api/storageservices/put-block-list * * @param uploadContextHandle The handle created with `IoTHubDeviceClient_LL_CreateUploadContext`. * * @warning This is a synchronous/blocking function. + * This function only attempts to send HTTP requests once, it does not retry in case of failure. + * Any retries must be explicitly implemented by the calling application. * * @return IOTHUB_CLIENT_OK upon success or an error code upon failure. */ @@ -498,7 +508,9 @@ typedef struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA_TAG* IOTHUB_DEVICE_CLIENT_LL_HA * @param responseMessage An user-defined status message to go along with `responseCode` on the notification to Azure IoT Hub. * * @warning This is a synchronous/blocking function. - * + * This function only attempts to send HTTP requests once, it does not retry in case of failure. + * Any retries must be explicitly implemented by the calling application. + * * @return IOTHUB_CLIENT_OK upon success or an error code upon failure. */ MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_NotifyUploadCompletion, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, uploadCorrelationId, bool, isSuccess, int, responseCode, const char*, responseMessage); diff --git a/iothub_client/samples/iothub_client_sample_upload_to_blob/iothub_client_sample_upload_to_blob.c b/iothub_client/samples/iothub_client_sample_upload_to_blob/iothub_client_sample_upload_to_blob.c index 7857afb683..df000a9537 100644 --- a/iothub_client/samples/iothub_client_sample_upload_to_blob/iothub_client_sample_upload_to_blob.c +++ b/iothub_client/samples/iothub_client_sample_upload_to_blob/iothub_client_sample_upload_to_blob.c @@ -35,6 +35,7 @@ static const char* connectionString = "[device connection string]"; static const char* proxyHost = NULL; static int proxyPort = 0; +static const char* azureStorageBlobPath = "subdir/hello_world.txt"; #define HELLO_WORLD "Hello World from IoTHubDeviceClient_LL_UploadToBlob" int main(void) @@ -73,7 +74,7 @@ int main(void) } else { - if (IoTHubDeviceClient_LL_UploadToBlob(device_ll_handle, "subdir/hello_world.txt", (const unsigned char*)HELLO_WORLD, sizeof(HELLO_WORLD) - 1) != IOTHUB_CLIENT_OK) + if (IoTHubDeviceClient_LL_UploadToBlob(device_ll_handle, azureStorageBlobPath, (const unsigned char*)HELLO_WORLD, sizeof(HELLO_WORLD) - 1) != IOTHUB_CLIENT_OK) { (void)printf("hello world failed to upload\n"); } diff --git a/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c b/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c index 2d8b31c325..3f967bbfc8 100644 --- a/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c +++ b/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c @@ -35,6 +35,7 @@ static const char* connectionString = "[device connection string]"; static const char* proxyHost = NULL; static int proxyPort = 0; +static const char* azureStorageBlobPath = "subdir/hello_world_custom_mb.txt"; static const char* data_to_upload_format = "Hello World from iothub_client_sample_upload_to_blob_custom: %d\n"; static char data_to_upload[128]; @@ -76,10 +77,9 @@ int main(void) { char* uploadCorrelationId; char* azureBlobSasUri; - const char* bla = "subdir/hello_world_custom_mb.txt"; if (IoTHubDeviceClient_LL_InitializeUpload( - device_ll_handle, bla, &uploadCorrelationId, &azureBlobSasUri) != IOTHUB_CLIENT_OK) + device_ll_handle, azureStorageBlobPath, &uploadCorrelationId, &azureBlobSasUri) != IOTHUB_CLIENT_OK) { printf("failed initializing upload in IoT Hub\n"); } diff --git a/iothub_client/samples/iothub_client_sample_upload_to_blob_mb/iothub_client_sample_upload_to_blob_mb.c b/iothub_client/samples/iothub_client_sample_upload_to_blob_mb/iothub_client_sample_upload_to_blob_mb.c index f73db9719d..c351745521 100644 --- a/iothub_client/samples/iothub_client_sample_upload_to_blob_mb/iothub_client_sample_upload_to_blob_mb.c +++ b/iothub_client/samples/iothub_client_sample_upload_to_blob_mb/iothub_client_sample_upload_to_blob_mb.c @@ -33,6 +33,7 @@ static const char* connectionString = "[device connection string]"; /*Optional string with http proxy host and integer for http proxy port (Linux only) */ static const char* proxyHost = NULL; static int proxyPort = 0; +static const char* azureStorageBlobPath = "subdir/hello_world_mb.txt"; static const char* data_to_upload_format = "Hello World from IoTHubDeviceClient_LL_UploadToBlob block: %d\n"; static char data_to_upload[128]; static int block_count = 0; @@ -124,7 +125,7 @@ int main(void) } else { - if (IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob(device_ll_handle, "subdir/hello_world_mb.txt", getDataCallback, NULL) != IOTHUB_CLIENT_OK) + if (IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob(device_ll_handle, azureStorageBlobPath, getDataCallback, NULL) != IOTHUB_CLIENT_OK) { (void)printf("hello world failed to upload\n"); } diff --git a/iothub_client/src/blob.c b/iothub_client/src/blob.c index 2ed82e22db..5f19768059 100644 --- a/iothub_client/src/blob.c +++ b/iothub_client/src/blob.c @@ -19,6 +19,14 @@ static const char blockListUriMarker[] = "&comp=blocklist"; static const char blockListLatestTagXmlBegin[] = ""; static const char blockListLatestTagXmlEnd[] = ""; +// Size of the string containing an Azure Blob Block ID. +// For more details please see +// https://learn.microsoft.com/en-us/rest/api/storageservices/put-block?tabs=azure-ad#uri-parameters +#define AZURE_BLOB_BLOCK_ID_SIZE 7 + +// Length of the string representation of an Azure Blob Block ID (enough to represent "049999"). +#define AZURE_BLOB_BLOCK_ID_LENGTH 6 + static STRING_HANDLE createBlockIdListXml(SINGLYLINKEDLIST_HANDLE blockIDList) { STRING_HANDLE blockIdListXml; @@ -147,9 +155,9 @@ BLOB_RESULT Blob_PutBlock( result = BLOB_ERROR; } else - { - char blockIdString[7]; /*this will contain 000000... 049999*/ - if (sprintf(blockIdString, "%6u", (unsigned int)blockID) != 6) /*produces 000000... 049999*/ + { + char blockIdString[AZURE_BLOB_BLOCK_ID_SIZE]; /*this will contain 000000... 049999*/ + if (sprintf(blockIdString, "%6u", (unsigned int)blockID) != AZURE_BLOB_BLOCK_ID_LENGTH) /*produces 000000... 049999*/ { LogError("failed to sprintf"); result = BLOB_ERROR; diff --git a/iothub_client/src/iothub_client_core.c b/iothub_client/src/iothub_client_core.c index 39f0b28a87..b014aefaf9 100644 --- a/iothub_client/src/iothub_client_core.c +++ b/iothub_client/src/iothub_client_core.c @@ -2509,9 +2509,7 @@ IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubClientCore_CreateUploadContex { IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE result; - if ( - (iotHubClientHandle == NULL) - ) + if (iotHubClientHandle == NULL) { LogError("invalid parameters iotHubClientHandle = %p", iotHubClientHandle); result = NULL; From 161463ca07c9d2df43292f40ce4751e0b25ce0ee Mon Sep 17 00:00:00 2001 From: Ewerton Scaboro da Silva Date: Tue, 11 Jul 2023 23:07:34 -0700 Subject: [PATCH 04/27] Update unit tests for blob.c --- iothub_client/inc/internal/blob.h | 2 +- iothub_client/src/blob.c | 25 +- iothub_client/tests/blob_ut/blob_ut.c | 1353 +++++++++---------------- 3 files changed, 492 insertions(+), 888 deletions(-) diff --git a/iothub_client/inc/internal/blob.h b/iothub_client/inc/internal/blob.h index d6c7c9caaf..2505ea9c5e 100644 --- a/iothub_client/inc/internal/blob.h +++ b/iothub_client/inc/internal/blob.h @@ -47,7 +47,7 @@ extern "C" MU_DEFINE_ENUM_WITHOUT_INVALID(BLOB_RESULT, BLOB_RESULT_VALUES) -MOCKABLE_FUNCTION(, HTTPAPIEX_HANDLE, Blob_CreateHttpConnection, const char*, blobStorageHostname, const char*, certificates, HTTP_PROXY_OPTIONS*, proxyOptions, const char*, networkInterface, const size_t, timeoutInMilliseconds); +MOCKABLE_FUNCTION(, HTTPAPIEX_HANDLE, Blob_CreateHttpConnection, const char*, blobStorageHostname, const char*, certificates, const HTTP_PROXY_OPTIONS*, proxyOptions, const char*, networkInterface, const size_t, timeoutInMilliseconds); MOCKABLE_FUNCTION(, void, Blob_DestroyHttpConnection, HTTPAPIEX_HANDLE, httpApiExHandle); diff --git a/iothub_client/src/blob.c b/iothub_client/src/blob.c index 5f19768059..ad0c8b8c72 100644 --- a/iothub_client/src/blob.c +++ b/iothub_client/src/blob.c @@ -79,7 +79,7 @@ static bool removeAndDestroyBlockIdsInList(const void* item, const void* match_c return true; } -HTTPAPIEX_HANDLE Blob_CreateHttpConnection(const char* blobStorageHostname, const char* certificates, HTTP_PROXY_OPTIONS *proxyOptions, const char* networkInterface, const size_t timeoutInMilliseconds) +HTTPAPIEX_HANDLE Blob_CreateHttpConnection(const char* blobStorageHostname, const char* certificates, const HTTP_PROXY_OPTIONS *proxyOptions, const char* networkInterface, const size_t timeoutInMilliseconds) { HTTPAPIEX_HANDLE httpApiExHandle; @@ -142,9 +142,10 @@ BLOB_RESULT Blob_PutBlock( { BLOB_RESULT result; - if (blockData == NULL || - blockIDList == NULL || - httpApiExHandle == NULL) + if (httpApiExHandle == NULL || + relativePath == NULL || + blockData == NULL || + blockIDList == NULL) { LogError("invalid argument detected blockData=%p blockIDList=%p relativePath=%p httpApiExHandle=%p", blockData, blockIDList, relativePath, httpApiExHandle); result = BLOB_ERROR; @@ -164,8 +165,9 @@ BLOB_RESULT Blob_PutBlock( } else { - STRING_HANDLE blockIdEncodedString = Azure_Base64_Encode_Bytes((const unsigned char*)blockIdString, 6); - if (blockIdString == NULL) + STRING_HANDLE blockIdEncodedString = Azure_Base64_Encode_Bytes((const unsigned char*)blockIdString, AZURE_BLOB_BLOCK_ID_LENGTH); + + if (blockIdEncodedString == NULL) { LogError("unable to Azure_Base64_Encode_Bytes"); result = BLOB_ERROR; @@ -267,7 +269,10 @@ BLOB_RESULT Blob_PutBlockList( else if (singlylinkedlist_get_head_item(blockIDList) == NULL) { // Block ID List is empty, there is nothing to be be sent to Azure Blob Storage. - result = BLOB_OK; + // In this case we better return error, forcing the caller to call this function only + // if at least one call to Blob_PutBlock() succeeds. + LogError("Block ID list is empty"); + result = BLOB_ERROR; } else { @@ -297,8 +302,10 @@ BLOB_RESULT Blob_PutBlockList( } else { - const char* s = STRING_c_str(blockIdListXml); - BUFFER_HANDLE blockIDListAsBuffer = BUFFER_create((const unsigned char*)s, strlen(s)); + const char* blockIdListXmlCharPtr = STRING_c_str(blockIdListXml); + size_t blockIdListXmlLength = STRING_length(blockIdListXml); + BUFFER_HANDLE blockIDListAsBuffer = BUFFER_create((const unsigned char*)blockIdListXmlCharPtr, blockIdListXmlLength); + if (blockIDListAsBuffer == NULL) { LogError("failed to BUFFER_create"); diff --git a/iothub_client/tests/blob_ut/blob_ut.c b/iothub_client/tests/blob_ut/blob_ut.c index cf36fafe22..0388feca00 100644 --- a/iothub_client/tests/blob_ut/blob_ut.c +++ b/iothub_client/tests/blob_ut/blob_ut.c @@ -26,6 +26,7 @@ static void my_gballoc_free(void* s) #include "azure_c_shared_utility/httpapiex.h" #include "azure_c_shared_utility/buffer_.h" #include "azure_c_shared_utility/strings.h" +#include "azure_c_shared_utility/singlylinkedlist.h" #include "azure_c_shared_utility/azure_base64.h" #include "azure_c_shared_utility/httpheaders.h" #include "azure_c_shared_utility/gballoc.h" @@ -47,7 +48,11 @@ static void my_gballoc_free(void* s) #undef malloc #endif -#define TEST_HTTPAPIEX_HANDLE (HTTPAPIEX_HANDLE)0x4343; +#define TEST_HTTPAPIEX_HANDLE (HTTPAPIEX_HANDLE)0x4343 +#define TEST_SINGLYLINKEDLIST_HANDLE (SINGLYLINKEDLIST_HANDLE)0x4444 +#define TEST_BUFFER_HANDLE (BUFFER_HANDLE)0x4445 +#define TEST_LIST_ITEM_HANDLE (LIST_ITEM_HANDLE)0x4446 +#define TEST_STRING_HANDLE (STRING_HANDLE)0x4447 #define HTTP_OK 200 #define HTTP_NOT_FOUND 404 @@ -60,17 +65,6 @@ IMPLEMENT_UMOCK_C_ENUM_TYPE(HTTPAPIEX_RESULT, HTTPAPIEX_RESULT_VALUES); TEST_DEFINE_ENUM_TYPE(HTTP_HEADERS_RESULT, HTTP_HEADERS_RESULT_VALUES); IMPLEMENT_UMOCK_C_ENUM_TYPE(HTTP_HEADERS_RESULT, HTTP_HEADERS_RESULT_VALUES); -static HTTPAPIEX_HANDLE my_HTTPAPIEX_Create(const char* hostName) -{ - (void)hostName; - return (HTTPAPIEX_HANDLE)my_gballoc_malloc(1); -} - -static void my_HTTPAPIEX_Destroy(HTTPAPIEX_HANDLE handle) -{ - my_gballoc_free(handle); -} - static BUFFER_HANDLE my_BUFFER_create(const unsigned char* source, size_t size) { (void)source; @@ -93,36 +87,21 @@ static void my_HTTPHeaders_Free(HTTP_HEADERS_HANDLE h) my_gballoc_free(h); } -static STRING_HANDLE my_STRING_construct(const char* psz) -{ - char* temp = (char*)my_gballoc_malloc(strlen(psz) + 1); - ASSERT_IS_NOT_NULL(temp); - (void)memcpy(temp, psz, strlen(psz) + 1); - return (STRING_HANDLE)temp; -} - -static void my_STRING_delete(STRING_HANDLE h) -{ - my_gballoc_free((void*)h); -} - -static STRING_HANDLE my_Azure_Base64_Encode_Bytes(const unsigned char* source, size_t size) -{ - (void)source; - (void)size; - return (STRING_HANDLE)my_gballoc_malloc(1); -} - TEST_DEFINE_ENUM_TYPE(BLOB_RESULT, BLOB_RESULT_VALUES); #define TEST_HTTPCOLONBACKSLASHBACKSLACH "http://" -#define TEST_HOSTNAME_1 "host.name" #define TEST_RELATIVE_PATH_1 "/here/follows/something?param1=value1¶m2=value2" #define TEST_VALID_SASURI_1 TEST_HTTPCOLONBACKSLASHBACKSLACH TEST_HOSTNAME_1 TEST_RELATIVE_PATH_1 #define X_MS_BLOB_TYPE "x-ms-blob-type" #define BLOCK_BLOB "BlockBlob" +const char* TEST_BLOB_STORAGE_HOSTNAME = "host.name"; +const char* TEST_TRUSTED_CERTIFICATE = "my certificate"; +const HTTP_PROXY_OPTIONS TEST_PROXY_OPTIONS = { "a", 8888, NULL, NULL }; +const char* TEST_NETWORK_INTERFACE = "eth0"; +const size_t TEST_TIMEOUT_MILLISECONDS = 5000; + MU_DEFINE_ENUM_STRINGS(UMOCK_C_ERROR_CODE, UMOCK_C_ERROR_CODE_VALUES) static void on_umock_c_error(UMOCK_C_ERROR_CODE error_code) @@ -144,106 +123,6 @@ static unsigned char * testUploadToBlobContent; // test to verify that large buffers are properly chunked end up with this. static const size_t testUploadToBlobContentMaxSize = 256 * 1024 * 1024; -/** - * BLOB_UPLOAD_CONTEXT and FileUpload_GetData_Callback - * allow to simulate a user who wants to upload - * a source of size "size". - */ -typedef struct BLOB_UPLOAD_CONTEXT_TAG -{ - const unsigned char* source; /* source to upload */ - size_t size; /* size of the source */ - size_t toUpload; /* size not yet uploaded */ -}BLOB_UPLOAD_CONTEXT; - -BLOB_UPLOAD_CONTEXT context; - -static IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT FileUpload_GetData_Callback(IOTHUB_CLIENT_FILE_UPLOAD_RESULT result, unsigned char const ** data, size_t* size, void* _uploadContext) -{ - BLOB_UPLOAD_CONTEXT* uploadContext = (BLOB_UPLOAD_CONTEXT*) _uploadContext; - - if (data == NULL || size == NULL) - { - // This is the last call - } - else if (result != FILE_UPLOAD_OK) - { - // Last call failed - *data = NULL; - *size = 0; - } - else if (uploadContext->toUpload == 0) - { - // Everything has been uploaded - *data = NULL; - *size = 0; - } - else - { - // Upload next block - size_t thisBlockSize = (uploadContext->toUpload > BLOCK_SIZE) ? BLOCK_SIZE : uploadContext->toUpload; - *data = (unsigned char*)uploadContext->source + (uploadContext->size - uploadContext->toUpload); - *size = thisBlockSize; - uploadContext->toUpload -= thisBlockSize; - } - - return IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_OK; -} - -/** - * BLOB_UPLOAD_CONTEXT_FAKE and FileUpload_GetFakeData_Callback - * allow to simulate a user who wants to sent - * blocksCount blocks of size blockSize - */ -typedef struct BLOB_UPLOAD_CONTEXT_FAKE_TAG -{ - unsigned char* fakeData; /* fake data allocated */ - size_t blockSize; /* size of the block */ - unsigned int blocksCount; /* number of block wanted */ - unsigned int blockSent; /* number block already sent */ - int abortOnBlockNumber; /* the callback shall abort if the block asked is equal to this value */ -}BLOB_UPLOAD_CONTEXT_FAKE; - -static IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT FileUpload_GetFakeData_Callback(IOTHUB_CLIENT_FILE_UPLOAD_RESULT result, unsigned char const ** data, size_t* size, void* _uploadContext) -{ - BLOB_UPLOAD_CONTEXT_FAKE* uploadContext = (BLOB_UPLOAD_CONTEXT_FAKE*) _uploadContext; - - if (uploadContext->fakeData == NULL) - { - // Allocate the fake data exactly once (actual LL layer just reads through existing buffer) - uploadContext->fakeData = (unsigned char*)gballoc_malloc(uploadContext->blockSize); - } - - if (data == NULL || size == NULL) - { - // This is the last call - } - else if (result != FILE_UPLOAD_OK) - { - // Last call failed - *data = NULL; - *size = 0; - } - else if (uploadContext->blockSent >= uploadContext->blocksCount) - { - // Everything has been uploaded - *data = NULL; - *size = 0; - } - else - { - // Upload next block - uploadContext->blockSent++; - *data = uploadContext->fakeData; - *size = (uploadContext->fakeData != NULL) ? uploadContext->blockSize : 0; - } - - if (uploadContext->abortOnBlockNumber + 1 == (int)uploadContext->blockSent) - return IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_ABORT; - - return IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_OK; -} - BEGIN_TEST_SUITE(blob_ut) TEST_SUITE_INITIALIZE(TestSuiteInitialize) @@ -256,10 +135,9 @@ TEST_SUITE_INITIALIZE(TestSuiteInitialize) REGISTER_GLOBAL_MOCK_FAIL_RETURN(gballoc_malloc, NULL); REGISTER_GLOBAL_MOCK_HOOK(gballoc_free, my_gballoc_free); - REGISTER_GLOBAL_MOCK_HOOK(HTTPAPIEX_Create, my_HTTPAPIEX_Create); + REGISTER_GLOBAL_MOCK_RETURN(HTTPAPIEX_Create, TEST_HTTPAPIEX_HANDLE); REGISTER_GLOBAL_MOCK_FAIL_RETURN(HTTPAPIEX_Create, NULL); REGISTER_GLOBAL_MOCK_FAIL_RETURN(HTTPAPIEX_ExecuteRequest, HTTPAPIEX_ERROR); - REGISTER_GLOBAL_MOCK_HOOK(HTTPAPIEX_Destroy, my_HTTPAPIEX_Destroy); REGISTER_GLOBAL_MOCK_HOOK(BUFFER_create, my_BUFFER_create); REGISTER_GLOBAL_MOCK_FAIL_RETURN(BUFFER_create, NULL); @@ -268,26 +146,31 @@ TEST_SUITE_INITIALIZE(TestSuiteInitialize) REGISTER_GLOBAL_MOCK_HOOK(HTTPHeaders_Alloc, my_HTTPHeaders_Alloc); REGISTER_GLOBAL_MOCK_HOOK(HTTPHeaders_Free, my_HTTPHeaders_Free); - REGISTER_GLOBAL_MOCK_HOOK(STRING_construct, my_STRING_construct); + REGISTER_GLOBAL_MOCK_RETURN(STRING_construct, TEST_STRING_HANDLE); REGISTER_GLOBAL_MOCK_FAIL_RETURN(STRING_construct, NULL); - REGISTER_GLOBAL_MOCK_HOOK(Azure_Base64_Encode_Bytes, my_Azure_Base64_Encode_Bytes); + REGISTER_GLOBAL_MOCK_RETURN(Azure_Base64_Encode_Bytes, TEST_STRING_HANDLE); REGISTER_GLOBAL_MOCK_FAIL_RETURN(Azure_Base64_Encode_Bytes, NULL); REGISTER_GLOBAL_MOCK_FAIL_RETURN(STRING_concat, MU_FAILURE); REGISTER_GLOBAL_MOCK_FAIL_RETURN(STRING_concat_with_STRING, MU_FAILURE); - REGISTER_GLOBAL_MOCK_RETURNS(HTTPAPIEX_SetOption, HTTPAPIEX_OK, HTTPAPIEX_ERROR); + REGISTER_GLOBAL_MOCK_RETURNS(singlylinkedlist_add, TEST_LIST_ITEM_HANDLE, NULL); + REGISTER_GLOBAL_MOCK_RETURNS(singlylinkedlist_get_head_item, TEST_LIST_ITEM_HANDLE, NULL); + REGISTER_GLOBAL_MOCK_RETURNS(singlylinkedlist_get_next_item, TEST_LIST_ITEM_HANDLE, NULL); + REGISTER_GLOBAL_MOCK_RETURNS(HTTPAPIEX_SetOption, HTTPAPIEX_OK, HTTPAPIEX_ERROR); REGISTER_GLOBAL_MOCK_RETURNS(HTTPAPIEX_ExecuteRequest, HTTPAPIEX_OK, HTTPAPIEX_ERROR); REGISTER_GLOBAL_MOCK_RETURN(STRING_c_str, "a"); - REGISTER_GLOBAL_MOCK_HOOK(STRING_delete, my_STRING_delete); REGISTER_UMOCK_ALIAS_TYPE(HTTP_HEADERS_HANDLE, void*); REGISTER_UMOCK_ALIAS_TYPE(HTTPAPIEX_HANDLE, void*); REGISTER_UMOCK_ALIAS_TYPE(BUFFER_HANDLE, void*); REGISTER_UMOCK_ALIAS_TYPE(STRING_HANDLE, void*); + REGISTER_UMOCK_ALIAS_TYPE(SINGLYLINKEDLIST_HANDLE, void*); + REGISTER_UMOCK_ALIAS_TYPE(LIST_CONDITION_FUNCTION, void*); + REGISTER_UMOCK_ALIAS_TYPE(LIST_ITEM_HANDLE, void*); REGISTER_TYPE(HTTPAPI_REQUEST_TYPE, HTTPAPI_REQUEST_TYPE); REGISTER_TYPE(HTTPAPIEX_RESULT, HTTPAPIEX_RESULT); @@ -313,17 +196,6 @@ TEST_SUITE_CLEANUP(TestClassCleanup) static void reset_test_data() { - memset(&context, 0, sizeof(context)); -} - -static void set_expected_calls_for_Blob_UploadMultipleBlocksFromSasUri_cleanup() -{ - STRICT_EXPECTED_CALL(HTTPAPIEX_Destroy(IGNORED_PTR_ARG)) /*this is the HTTPAPIEX handle*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG))/*this is the XML string used for Put Block List operation*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)) /*this is freeing the copy of hte hostname*/ - .IgnoreArgument_ptr(); } TEST_FUNCTION_INITIALIZE(Setup) @@ -337,984 +209,709 @@ TEST_FUNCTION_CLEANUP(Cleanup) reset_test_data(); } -TEST_FUNCTION(Blob_UploadMultipleBlocksFromSasUri_with_NULL_SasUri_fails) +TEST_FUNCTION(Blob_CreateHttpConnection_with_NULL_hostname_fails) { ///arrange - unsigned int httpResponse = HTTP_OK; ///act - BLOB_RESULT result = Blob_UploadMultipleBlocksFromSasUri(NULL, FileUpload_GetData_Callback, &context, &httpResponse, testValidBufferHandle, NULL, NULL, NULL, 0); + HTTPAPIEX_HANDLE result = Blob_CreateHttpConnection(NULL, NULL, NULL, NULL, 0); ///assert - ASSERT_ARE_EQUAL(BLOB_RESULT, BLOB_INVALID_ARG, result); + ASSERT_ARE_EQUAL(void_ptr, NULL, result); ///cleanup - } -TEST_FUNCTION(Blob_UploadMultipleBlocksFromSasUri_with_NULL_getDataCallBack_and_non_NULL_context_fails) +TEST_FUNCTION(Blob_CreateHttpConnection_happy_path_no_options_succeeds) { ///arrange - unsigned int httpResponse = HTTP_OK; + umock_c_reset_all_calls(); + STRICT_EXPECTED_CALL(HTTPAPIEX_Create(TEST_BLOB_STORAGE_HOSTNAME)); ///act - BLOB_RESULT result = Blob_UploadMultipleBlocksFromSasUri(TEST_VALID_SASURI_1, NULL, &context, &httpResponse, testValidBufferHandle, NULL, NULL, NULL, 0); + HTTPAPIEX_HANDLE result = Blob_CreateHttpConnection(TEST_BLOB_STORAGE_HOSTNAME, NULL, NULL, NULL, 0); ///assert - ASSERT_ARE_EQUAL(BLOB_RESULT, BLOB_INVALID_ARG, result); + ASSERT_ARE_EQUAL(void_ptr, TEST_HTTPAPIEX_HANDLE, result); ///cleanup - } -TEST_FUNCTION(Blob_UploadMultipleBlocksFromSasUri_succeeds_when_HTTP_status_code_is_404) +TEST_FUNCTION(Blob_CreateHttpConnection_happy_path_succeeds) { ///arrange - unsigned int httpResponse = HTTP_OK; - unsigned char c = '3'; - size_t size = 1; - context.size = size; - context.source = &c; - context.toUpload = context.size; - - STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)) /*this is creating a copy of the hostname */ - .IgnoreArgument_size(); - - STRICT_EXPECTED_CALL(HTTPAPIEX_Create("host.name")); /*this is creating the httpapiex handle to storage (it is always the same host)*/ - STRICT_EXPECTED_CALL(STRING_construct("\r\n")); /*this is starting to build the XML used in Put Block List operation*/ - - /*uploading blocks (Put Block)*/ - for (size_t blockNumber = 0;blockNumber < (size - 1) / (100 * 1024 * 1024) + 1;blockNumber++) - { - STRICT_EXPECTED_CALL(BUFFER_create(&c + blockNumber * 100 * 1024 * 1024, - (blockNumber != (size - 1) / (100 * 1024 * 1024)) ? 100 * 1024 * 1024 : (size - 1) % (100 * 1024 * 1024) + 1 /*condition to take care of "the size of the last block*/ - )); /*this is the content to be uploaded by this call*/ - - /*here some sprintf happens and that produces a string in the form: 000000...049999*/ - STRICT_EXPECTED_CALL(Azure_Base64_Encode_Bytes(IGNORED_PTR_ARG, 6)) /*this is converting the produced blockID string to a base64 representation*/ - .IgnoreArgument_source(); - - STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, "")) /*this is building the XML*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_concat_with_STRING(IGNORED_PTR_ARG, IGNORED_PTR_ARG)) /*this is building the XML*/ - .IgnoreArgument_s1() - .IgnoreArgument_s2(); - STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, "")) /*this is building the XML*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_construct("/here/follows/something?param1=value1¶m2=value2")); /*this is building the relativePath*/ - - STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, "&comp=block&blockid=")) /*this is building the relativePath*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_concat_with_STRING(IGNORED_PTR_ARG, IGNORED_PTR_ARG)) /*this is building the relativePath by adding the blockId (base64 encoded_*/ - .IgnoreArgument_s1() - .IgnoreArgument_s2(); - - STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) /*this is getting the relative path as const char* */ - .IgnoreArgument_handle(); - - int responseCode = HTTP_NOT_FOUND; /*not found*/ - STRICT_EXPECTED_CALL(HTTPAPIEX_ExecuteRequest(IGNORED_PTR_ARG, HTTPAPI_REQUEST_PUT, IGNORED_PTR_ARG, NULL, IGNORED_PTR_ARG, &httpResponse, NULL, testValidBufferHandle)) - .IgnoreArgument_handle() - .IgnoreArgument_relativePath() - .IgnoreArgument_requestContent() - .CopyOutArgumentBuffer_statusCode(&responseCode, sizeof(responseCode)); - - STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)) /*this is unbuilding the relativePath*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)) /*this is unbuilding the blockID string to a base64 representation*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG)) /*this was the content to be uploaded*/ - .IgnoreArgument_handle(); - } - - set_expected_calls_for_Blob_UploadMultipleBlocksFromSasUri_cleanup(); + umock_c_reset_all_calls(); + STRICT_EXPECTED_CALL(HTTPAPIEX_Create(TEST_BLOB_STORAGE_HOSTNAME)); + STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(TEST_HTTPAPIEX_HANDLE, OPTION_HTTP_TIMEOUT, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(TEST_HTTPAPIEX_HANDLE, OPTION_TRUSTED_CERT, TEST_TRUSTED_CERTIFICATE)); + STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(TEST_HTTPAPIEX_HANDLE, OPTION_HTTP_PROXY, &TEST_PROXY_OPTIONS)); + STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(TEST_HTTPAPIEX_HANDLE, OPTION_CURL_INTERFACE, TEST_NETWORK_INTERFACE)); ///act - BLOB_RESULT result = Blob_UploadMultipleBlocksFromSasUri(TEST_VALID_SASURI_1, FileUpload_GetData_Callback, &context, &httpResponse, testValidBufferHandle, NULL, NULL, NULL, 0); + HTTPAPIEX_HANDLE result = Blob_CreateHttpConnection( + TEST_BLOB_STORAGE_HOSTNAME, TEST_TRUSTED_CERTIFICATE, &TEST_PROXY_OPTIONS, TEST_NETWORK_INTERFACE, TEST_TIMEOUT_MILLISECONDS); ///assert - ASSERT_ARE_EQUAL(BLOB_RESULT, BLOB_OK, result); - ASSERT_ARE_EQUAL(int, HTTP_NOT_FOUND, httpResponse); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(void_ptr, TEST_HTTPAPIEX_HANDLE, result); ///cleanup } -TEST_FUNCTION(Blob_UploadMultipleBlocksFromSasUri_fails_when_HTTPAPIEX_ExecuteRequest_fails) +TEST_FUNCTION(Blob_CreateHttpConnection_failure_checks) { ///arrange - unsigned int httpResponse = HTTP_OK; - unsigned char c = '3'; - size_t size = 1; - context.size = size; - context.source = &c; - context.toUpload = context.size; - - STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)) /*this is creating a copy of the hostname */ - .IgnoreArgument_size(); + ASSERT_ARE_EQUAL(int, 0, umock_c_negative_tests_init()); - STRICT_EXPECTED_CALL(HTTPAPIEX_Create("host.name")); /*this is creating the httpapiex handle to storage (it is always the same host)*/ - STRICT_EXPECTED_CALL(STRING_construct("\r\n")); /*this is starting to build the XML used in Put Block List operation*/ + umock_c_reset_all_calls(); + STRICT_EXPECTED_CALL(HTTPAPIEX_Create(TEST_BLOB_STORAGE_HOSTNAME)); + STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(TEST_HTTPAPIEX_HANDLE, OPTION_HTTP_TIMEOUT, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(TEST_HTTPAPIEX_HANDLE, OPTION_TRUSTED_CERT, TEST_TRUSTED_CERTIFICATE)); + STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(TEST_HTTPAPIEX_HANDLE, OPTION_HTTP_PROXY, &TEST_PROXY_OPTIONS)); + STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(TEST_HTTPAPIEX_HANDLE, OPTION_CURL_INTERFACE, TEST_NETWORK_INTERFACE)); + umock_c_negative_tests_snapshot(); - /*uploading blocks (Put Block)*/ - for (size_t blockNumber = 0;blockNumber < (size - 1) / (100 * 1024 * 1024) + 1;blockNumber++) + // act + for (int i = 0; i < umock_c_negative_tests_call_count(); i++) { - STRICT_EXPECTED_CALL(BUFFER_create(&c + blockNumber * 100 * 1024 * 1024, - (blockNumber != (size - 1) / (100 * 1024 * 1024)) ? 100 * 1024 * 1024 : (size - 1) % (100 * 1024 * 1024) + 1 /*condition to take care of "the size of the last block*/ - )); /*this is the content to be uploaded by this call*/ - - /*here some sprintf happens and that produces a string in the form: 000000...049999*/ - STRICT_EXPECTED_CALL(Azure_Base64_Encode_Bytes(IGNORED_PTR_ARG, 6)) /*this is converting the produced blockID string to a base64 representation*/ - .IgnoreArgument_source(); - - STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, "")) /*this is building the XML*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_concat_with_STRING(IGNORED_PTR_ARG, IGNORED_PTR_ARG)) /*this is building the XML*/ - .IgnoreArgument_s1() - .IgnoreArgument_s2(); - STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, "")) /*this is building the XML*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_construct("/here/follows/something?param1=value1¶m2=value2")); /*this is building the relativePath*/ - - STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, "&comp=block&blockid=")) /*this is building the relativePath*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_concat_with_STRING(IGNORED_PTR_ARG, IGNORED_PTR_ARG)) /*this is building the relativePath by adding the blockId (base64 encoded_*/ - .IgnoreArgument_s1() - .IgnoreArgument_s2(); - - STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) /*this is getting the relative path as const char* */ - .IgnoreArgument_handle(); - - int responseCode = HTTP_OK; /*ok*/ - STRICT_EXPECTED_CALL(HTTPAPIEX_ExecuteRequest(IGNORED_PTR_ARG, HTTPAPI_REQUEST_PUT, IGNORED_PTR_ARG, NULL, IGNORED_PTR_ARG, &httpResponse, NULL, testValidBufferHandle)) - .IgnoreArgument_handle() - .IgnoreArgument_relativePath() - .IgnoreArgument_requestContent() - .CopyOutArgumentBuffer_statusCode(&responseCode, sizeof(responseCode)) - .SetReturn(HTTPAPIEX_ERROR); - - STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)) /*this is unbuilding the relativePath*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)) /*this is unbuilding the blockID string to a base64 representation*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG)) /*this was the content to be uploaded*/ - .IgnoreArgument_handle(); + umock_c_negative_tests_reset(); + + if (umock_c_negative_tests_can_call_fail(i)) + { + // arrange + char error_msg[64]; + HTTPAPIEX_HANDLE result; + + umock_c_negative_tests_reset(); + umock_c_negative_tests_fail_call(i); + + // act + result = Blob_CreateHttpConnection( + TEST_BLOB_STORAGE_HOSTNAME, TEST_TRUSTED_CERTIFICATE, &TEST_PROXY_OPTIONS, TEST_NETWORK_INTERFACE, TEST_TIMEOUT_MILLISECONDS); + + ///assert + sprintf(error_msg, "On failed call %lu", (unsigned long)i); + ASSERT_IS_NULL(result, error_msg); + } } - set_expected_calls_for_Blob_UploadMultipleBlocksFromSasUri_cleanup(); + // cleanup + umock_c_negative_tests_deinit(); +} + +TEST_FUNCTION(Blob_DestroyHttpConnection_happy_path_succeeds) +{ + ///arrange + umock_c_reset_all_calls(); + STRICT_EXPECTED_CALL(HTTPAPIEX_Destroy(TEST_HTTPAPIEX_HANDLE)); ///act - BLOB_RESULT result = Blob_UploadMultipleBlocksFromSasUri(TEST_VALID_SASURI_1, FileUpload_GetData_Callback, &context, &httpResponse, testValidBufferHandle, NULL, NULL, NULL, 0); + Blob_DestroyHttpConnection(TEST_HTTPAPIEX_HANDLE); ///assert - ASSERT_ARE_EQUAL(BLOB_RESULT, BLOB_HTTP_ERROR, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ///cleanup } - -TEST_FUNCTION(Blob_UploadMultipleBlocksFromSasUri_fails_when_BUFFER_create_fails) +TEST_FUNCTION(Blob_DestroyHttpConnection_NULL_handle_fails) { ///arrange - unsigned int httpResponse = HTTP_OK; - unsigned char c = '3'; - context.size = 1; - context.source = &c; - context.toUpload = context.size; + umock_c_reset_all_calls(); - STRICT_EXPECTED_CALL(gballoc_malloc(strlen(TEST_HOSTNAME_1) + 1)); - { - STRICT_EXPECTED_CALL(HTTPAPIEX_Create(TEST_HOSTNAME_1)); - { - STRICT_EXPECTED_CALL(STRING_construct("\r\n")); /*this is starting to build the XML used in Put Block List operation*/ + ///act + Blob_DestroyHttpConnection(NULL); - STRICT_EXPECTED_CALL(BUFFER_create(&c, 1)) - .SetReturn(NULL); + ///assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); - } - set_expected_calls_for_Blob_UploadMultipleBlocksFromSasUri_cleanup(); - } + ///cleanup +} + +TEST_FUNCTION(Blob_ClearBlockIdList_happy_path_succeeds) +{ + ///arrange + umock_c_reset_all_calls(); + STRICT_EXPECTED_CALL(singlylinkedlist_remove_if(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); ///act - BLOB_RESULT result = Blob_UploadMultipleBlocksFromSasUri(TEST_VALID_SASURI_1, FileUpload_GetData_Callback, &context, &httpResponse, testValidBufferHandle, NULL, NULL, NULL, 0); + Blob_ClearBlockIdList(TEST_SINGLYLINKEDLIST_HANDLE); ///assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); - ASSERT_ARE_EQUAL(BLOB_RESULT, BLOB_ERROR, result); ///cleanup } -TEST_FUNCTION(Blob_UploadMultipleBlocksFromSasUri_fails_when_HTTPAPIEX_Create_fails) +TEST_FUNCTION(Blob_ClearBlockIdList_NULL_handle_fails) { ///arrange - unsigned int httpResponse = HTTP_OK; - unsigned char c = '3'; - context.size = 1; - context.source = &c; - context.toUpload = context.size; - - STRICT_EXPECTED_CALL(gballoc_malloc(strlen(TEST_HOSTNAME_1) + 1)); - { - STRICT_EXPECTED_CALL(HTTPAPIEX_Create(TEST_HOSTNAME_1)) - .SetReturn(NULL) - ; - } - - set_expected_calls_for_Blob_UploadMultipleBlocksFromSasUri_cleanup(); + umock_c_reset_all_calls(); ///act - BLOB_RESULT result = Blob_UploadMultipleBlocksFromSasUri(TEST_VALID_SASURI_1, FileUpload_GetData_Callback, &context, &httpResponse, testValidBufferHandle, NULL, NULL, NULL, 0); + Blob_ClearBlockIdList(NULL); ///assert - ASSERT_ARE_EQUAL(BLOB_RESULT, BLOB_ERROR, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ///cleanup } -TEST_FUNCTION(Blob_UploadMultipleBlocksFromSasUri_fails_when_malloc_fails) +TEST_FUNCTION(Blob_PutBlock_happy_path_succeeds) { ///arrange - unsigned int httpResponse = HTTP_OK; - unsigned char c = '3'; - context.size = 1; - context.source = &c; - context.toUpload = context.size; - - STRICT_EXPECTED_CALL(gballoc_malloc(strlen(TEST_HOSTNAME_1) + 1)) - .SetReturn(NULL) - ; + unsigned int blockId = 0; + BUFFER_HANDLE blockData = TEST_BUFFER_HANDLE; + SINGLYLINKEDLIST_HANDLE blockIdList = TEST_SINGLYLINKEDLIST_HANDLE; + unsigned int responseHttpStatus = 0; + BUFFER_HANDLE responseContent = TEST_BUFFER_HANDLE; - set_expected_calls_for_Blob_UploadMultipleBlocksFromSasUri_cleanup(); + umock_c_reset_all_calls(); + STRICT_EXPECTED_CALL(Azure_Base64_Encode_Bytes(IGNORED_PTR_ARG, 6)); + STRICT_EXPECTED_CALL(singlylinkedlist_add(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_construct(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_concat_with_STRING(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) + .CallCannotFail(); + STRICT_EXPECTED_CALL(HTTPAPIEX_ExecuteRequest( + TEST_HTTPAPIEX_HANDLE, HTTPAPI_REQUEST_PUT, IGNORED_PTR_ARG, IGNORED_PTR_ARG, blockData, &responseHttpStatus, IGNORED_PTR_ARG, responseContent)); + STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); ///act - BLOB_RESULT result = Blob_UploadMultipleBlocksFromSasUri(TEST_VALID_SASURI_1, FileUpload_GetData_Callback, &context, &httpResponse, testValidBufferHandle, NULL, NULL, NULL, 0); + BLOB_RESULT result = Blob_PutBlock( + TEST_HTTPAPIEX_HANDLE, TEST_RELATIVE_PATH_1, blockId, blockData, blockIdList, &responseHttpStatus, responseContent); ///assert - ASSERT_ARE_EQUAL(BLOB_RESULT, BLOB_ERROR, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(int, BLOB_OK, result); ///cleanup } -TEST_FUNCTION(Blob_UploadMultipleBlocksFromSasUri_when_SasUri_is_wrong_fails_1) +TEST_FUNCTION(Blob_PutBlock_NULL_HTTPAPI_HANDLE_fails) { ///arrange - unsigned int httpResponse = HTTP_OK; - unsigned char c = '3'; - context.size = 1; - context.source = &c; - context.toUpload = context.size; + unsigned int blockId = 0; + BUFFER_HANDLE blockData = TEST_BUFFER_HANDLE; + SINGLYLINKEDLIST_HANDLE blockIdList = TEST_SINGLYLINKEDLIST_HANDLE; + unsigned int responseHttpStatus = 0; + BUFFER_HANDLE responseContent = TEST_BUFFER_HANDLE; - set_expected_calls_for_Blob_UploadMultipleBlocksFromSasUri_cleanup(); + umock_c_reset_all_calls(); ///act - BLOB_RESULT result = Blob_UploadMultipleBlocksFromSasUri("https:/h.h/doms", FileUpload_GetData_Callback, &context, &httpResponse, testValidBufferHandle, NULL, NULL, NULL, 0); /*wrong format for protocol, notice it is actually http:\h.h\doms (missing a \ from http)*/ + BLOB_RESULT result = Blob_PutBlock( + NULL, TEST_RELATIVE_PATH_1, blockId, blockData, blockIdList, &responseHttpStatus, responseContent); ///assert - ASSERT_ARE_EQUAL(BLOB_RESULT, BLOB_INVALID_ARG, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_NOT_EQUAL(int, BLOB_OK, result); ///cleanup } -TEST_FUNCTION(Blob_UploadMultipleBlocksFromSasUri_when_SasUri_is_wrong_fails_2) +TEST_FUNCTION(Blob_PutBlock_NULL_relative_path_fails) { ///arrange - unsigned int httpResponse = HTTP_OK; - unsigned char c = '3'; - context.size = 1; - context.source = &c; - context.toUpload = context.size; + unsigned int blockId = 0; + BUFFER_HANDLE blockData = TEST_BUFFER_HANDLE; + SINGLYLINKEDLIST_HANDLE blockIdList = TEST_SINGLYLINKEDLIST_HANDLE; + unsigned int responseHttpStatus = 0; + BUFFER_HANDLE responseContent = TEST_BUFFER_HANDLE; - set_expected_calls_for_Blob_UploadMultipleBlocksFromSasUri_cleanup(); + umock_c_reset_all_calls(); ///act - BLOB_RESULT result = Blob_UploadMultipleBlocksFromSasUri("https://h.h", FileUpload_GetData_Callback, &context, &httpResponse, testValidBufferHandle, NULL, NULL, NULL, 0); /*there's no relative path here*/ + BLOB_RESULT result = Blob_PutBlock( + TEST_HTTPAPIEX_HANDLE, NULL, blockId, blockData, blockIdList, &responseHttpStatus, responseContent); ///assert - ASSERT_ARE_EQUAL(BLOB_RESULT, BLOB_INVALID_ARG, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_NOT_EQUAL(int, BLOB_OK, result); ///cleanup } -static void Blob_UploadMultipleBlocksFromSasUri_various_sizes_happy_path_Impl(HTTP_PROXY_OPTIONS *proxyOptions, const char * networkInterface, const char* certificate, size_t* blockSizesToTest, size_t numberBlockSizesToTest, const size_t timeoutInMilliseconds) +TEST_FUNCTION(Blob_PutBlock_NULL_blockData_fails) { - unsigned int httpResponse = HTTP_OK; - for (size_t iSize = 0; iSize < numberBlockSizesToTest; iSize++) - { - umock_c_reset_all_calls(); - ///arrange - umock_c_reset_all_calls(); - - memset(testUploadToBlobContent, '3', blockSizesToTest[iSize]); - testUploadToBlobContent[0] = '0'; - testUploadToBlobContent[blockSizesToTest[iSize] - 1] = '4'; - context.size = blockSizesToTest[iSize]; - context.source = testUploadToBlobContent; - context.toUpload = context.size; + ///arrange + unsigned int blockId = 0; + BUFFER_HANDLE blockData = NULL; + SINGLYLINKEDLIST_HANDLE blockIdList = TEST_SINGLYLINKEDLIST_HANDLE; + unsigned int responseHttpStatus = 0; + BUFFER_HANDLE responseContent = TEST_BUFFER_HANDLE; - STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)) /*this is creating a copy of the hostname */ - .IgnoreArgument_size(); + umock_c_reset_all_calls(); - STRICT_EXPECTED_CALL(HTTPAPIEX_Create("h.h")); /*this is creating the httpapiex handle to storage (it is always the same host)*/ + ///act + BLOB_RESULT result = Blob_PutBlock( + TEST_HTTPAPIEX_HANDLE, TEST_RELATIVE_PATH_1, blockId, blockData, blockIdList, &responseHttpStatus, responseContent); - if (timeoutInMilliseconds != 0) - { - STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(IGNORED_PTR_ARG, OPTION_HTTP_TIMEOUT, IGNORED_PTR_ARG)); - } + ///assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_NOT_EQUAL(int, BLOB_OK, result); - if (certificate != NULL) - { - STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(IGNORED_PTR_ARG, "TrustedCerts", IGNORED_PTR_ARG)); - } - - if (proxyOptions != NULL) - { - STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(IGNORED_PTR_ARG, OPTION_HTTP_PROXY, proxyOptions)); - } + ///cleanup +} - if (networkInterface != NULL) - { - STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(IGNORED_PTR_ARG, OPTION_CURL_INTERFACE, networkInterface)); - } - STRICT_EXPECTED_CALL(STRING_construct("\r\n")); /*this is starting to build the XML used in Put Block List operation*/ +TEST_FUNCTION(Blob_PutBlock_NULL_blockIdList_fails) +{ + ///arrange + unsigned int blockId = 0; + BUFFER_HANDLE blockData = TEST_BUFFER_HANDLE; + SINGLYLINKEDLIST_HANDLE blockIdList = NULL; + unsigned int responseHttpStatus = 0; + BUFFER_HANDLE responseContent = TEST_BUFFER_HANDLE; - /*uploading blocks (Put Block)*/ - for (size_t blockNumber = 0; blockNumber < (blockSizesToTest[iSize] - 1) / (100 * 1024 * 1024) + 1;blockNumber++) - { - STRICT_EXPECTED_CALL(BUFFER_create(testUploadToBlobContent + blockNumber * 100 * 1024 * 1024, - (blockNumber != (blockSizesToTest[iSize] - 1) / (100 * 1024 * 1024)) ? 100 * 1024 * 1024 : (blockSizesToTest[iSize] - 1) % (100 * 1024 * 1024) + 1 /*condition to take care of "the size of the last block*/ - )); /*this is the content to be uploaded by this call*/ - - /*here some sprintf happens and that produces a string in the form: 000000...049999*/ - STRICT_EXPECTED_CALL(Azure_Base64_Encode_Bytes(IGNORED_PTR_ARG, 6)) /*this is converting the produced blockID string to a base64 representation*/ - .IgnoreArgument_source(); - - STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, "")) /*this is building the XML*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_concat_with_STRING(IGNORED_PTR_ARG, IGNORED_PTR_ARG)) /*this is building the XML*/ - .IgnoreArgument_s1() - .IgnoreArgument_s2(); - STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, "")) /*this is building the XML*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_construct("/something?a=b")); /*this is building the relativePath*/ - - STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, "&comp=block&blockid=")) /*this is building the relativePath*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_concat_with_STRING(IGNORED_PTR_ARG, IGNORED_PTR_ARG)) /*this is building the relativePath by adding the blockId (base64 encoded_*/ - .IgnoreArgument_s1() - .IgnoreArgument_s2(); - - STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) /*this is getting the relative path as const char* */ - .IgnoreArgument_handle(); - - STRICT_EXPECTED_CALL(HTTPAPIEX_ExecuteRequest(IGNORED_PTR_ARG, HTTPAPI_REQUEST_PUT, IGNORED_PTR_ARG, NULL, IGNORED_PTR_ARG, &httpResponse, NULL, testValidBufferHandle)) - .IgnoreArgument_handle() - .IgnoreArgument_relativePath() - .IgnoreArgument_requestContent(); - - STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)) /*this is unbuilding the relativePath*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)) /*this is unbuilding the blockID string to a base64 representation*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG)) /*this was the content to be uploaded*/ - .IgnoreArgument_handle(); - } + umock_c_reset_all_calls(); - /*this part is Put Block list*/ - STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, "")) /*This is closing the XML*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_construct("/something?a=b")); /*this is building the relative path for the Put BLock list*/ - - STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, "&comp=blocklist")) /*This is still building relative path for Put Block list*/ - .IgnoreArgument_handle(); - - STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) /*this is getting the XML as const char* so it can be passed to _ExecuteRequest*/ - .IgnoreArgument_handle(); - - STRICT_EXPECTED_CALL(BUFFER_create(IGNORED_PTR_ARG, IGNORED_NUM_ARG)) /*this is creating the XML body as BUFFER_HANDLE*/ - .IgnoreAllArguments(); - - STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) /*this is getting the relative path*/ - .IgnoreArgument_handle(); - - STRICT_EXPECTED_CALL(HTTPAPIEX_ExecuteRequest( - IGNORED_PTR_ARG, - HTTPAPI_REQUEST_PUT, - IGNORED_PTR_ARG, - NULL, - IGNORED_PTR_ARG, - &httpResponse, - NULL, - testValidBufferHandle - )) - .IgnoreArgument_handle() - .IgnoreArgument_relativePath() - .IgnoreArgument_requestContent() - .CopyOutArgumentBuffer_statusCode(&TwoHundred, sizeof(TwoHundred)) - ; - - STRICT_EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG)) /*This is the XML as BUFFER_HANDLE*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)) /*this is destroying the relative path for Put Block List*/ - .IgnoreArgument_handle(); - set_expected_calls_for_Blob_UploadMultipleBlocksFromSasUri_cleanup(); - - ///act - BLOB_RESULT result = Blob_UploadMultipleBlocksFromSasUri("https://h.h/something?a=b", FileUpload_GetData_Callback, &context, &httpResponse, testValidBufferHandle, certificate, proxyOptions, networkInterface, timeoutInMilliseconds); - - ///assert - ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); - ASSERT_ARE_EQUAL(BLOB_RESULT, BLOB_OK, result); - ASSERT_ARE_EQUAL(int, HTTP_OK, httpResponse); - } + ///act + BLOB_RESULT result = Blob_PutBlock( + TEST_HTTPAPIEX_HANDLE, TEST_RELATIVE_PATH_1, blockId, blockData, blockIdList, &responseHttpStatus, responseContent); + ///assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_NOT_EQUAL(int, BLOB_OK, result); + ///cleanup } - -TEST_FUNCTION(Blob_UploadFromSasUri_with_proxy_happy_path) +TEST_FUNCTION(Blob_PutBlock_NULL_response_status_succeeds) { - HTTP_PROXY_OPTIONS proxyOptions = { "a", 8888, NULL, NULL }; - size_t blockSizesToTest[] = { 100 * 1024 * 1024 }; - Blob_UploadMultipleBlocksFromSasUri_various_sizes_happy_path_Impl(&proxyOptions, NULL, NULL, blockSizesToTest, sizeof(blockSizesToTest) / sizeof(blockSizesToTest[0]), 0); -} + ///arrange + unsigned int blockId = 0; + BUFFER_HANDLE blockData = TEST_BUFFER_HANDLE; + SINGLYLINKEDLIST_HANDLE blockIdList = TEST_SINGLYLINKEDLIST_HANDLE; + BUFFER_HANDLE responseContent = TEST_BUFFER_HANDLE; -TEST_FUNCTION(Blob_UploadFromSasUri_with_network_interface) -{ - const char* networkInterface = "eth0"; - size_t blockSizesToTest[] = { 100 * 1024 * 1024 }; - Blob_UploadMultipleBlocksFromSasUri_various_sizes_happy_path_Impl(NULL, networkInterface, NULL, blockSizesToTest, sizeof(blockSizesToTest) / sizeof(blockSizesToTest[0]), 0); -} + umock_c_reset_all_calls(); + STRICT_EXPECTED_CALL(Azure_Base64_Encode_Bytes(IGNORED_PTR_ARG, 6)); + STRICT_EXPECTED_CALL(singlylinkedlist_add(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_construct(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_concat_with_STRING(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) + .CallCannotFail(); + STRICT_EXPECTED_CALL(HTTPAPIEX_ExecuteRequest( + TEST_HTTPAPIEX_HANDLE, HTTPAPI_REQUEST_PUT, IGNORED_PTR_ARG, IGNORED_PTR_ARG, blockData, NULL, IGNORED_PTR_ARG, responseContent)); + STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); -TEST_FUNCTION(Blob_UploadMultipleBlocksFromSasUri_various_sizes_with_certificates_happy_path) -{ - const char* certificate = "testCertificate"; - size_t blockSizesToTest[] = { 100 * 1024 * 1024 }; - Blob_UploadMultipleBlocksFromSasUri_various_sizes_happy_path_Impl(NULL, NULL, certificate, blockSizesToTest, sizeof(blockSizesToTest) / sizeof(blockSizesToTest[0]), 0); -} + ///act + BLOB_RESULT result = Blob_PutBlock( + TEST_HTTPAPIEX_HANDLE, TEST_RELATIVE_PATH_1, blockId, blockData, blockIdList, NULL, responseContent); -TEST_FUNCTION(Blob_UploadMultipleBlocksFromSasUri_various_sizes_with_timeout_happy_path) -{ - const size_t timeoutInMilliseconds = 5000; - size_t blockSizesToTest[] = { 100 * 1024 * 1024 }; - Blob_UploadMultipleBlocksFromSasUri_various_sizes_happy_path_Impl(NULL, NULL, NULL, blockSizesToTest, sizeof(blockSizesToTest) / sizeof(blockSizesToTest[0]), timeoutInMilliseconds); -} + ///assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(int, BLOB_OK, result); -TEST_FUNCTION(Blob_UploadMultipleBlocksFromSasUri_various_sizes_happy_path) -{ - size_t blockSizesToTest[] = { - 1, - 100 * 1024 * 1024 - 1, - 100 * 1024 * 1024, - 100 * 1024 * 1024 + 1, - 256 * 1024 * 1024 - 1, - }; - Blob_UploadMultipleBlocksFromSasUri_various_sizes_happy_path_Impl(NULL, NULL, NULL, blockSizesToTest, sizeof(blockSizesToTest) / sizeof(blockSizesToTest[0]), 0); + ///cleanup } -TEST_FUNCTION(Blob_UploadMultipleBlocksFromSasUri_64MB_unhappy_paths) +TEST_FUNCTION(Blob_PutBlock_NULL_response_content_succeeds) { - unsigned int httpResponse = HTTP_OK; - (void)umock_c_negative_tests_init(); - - umock_c_reset_all_calls(); ///arrange - umock_c_reset_all_calls(); - - memset(testUploadToBlobContent, '3', testUploadToBlobContentMaxSize); - testUploadToBlobContent[0] = '0'; - testUploadToBlobContent[testUploadToBlobContentMaxSize - 1] = '4'; - context.size = testUploadToBlobContentMaxSize; - context.source = testUploadToBlobContent; - context.toUpload = context.size; + unsigned int blockId = 0; + BUFFER_HANDLE blockData = TEST_BUFFER_HANDLE; + SINGLYLINKEDLIST_HANDLE blockIdList = TEST_SINGLYLINKEDLIST_HANDLE; + unsigned int responseHttpStatus = 0; + BUFFER_HANDLE responseContent = NULL; - STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)) /*this is creating a copy of the hostname */ - .IgnoreArgument_size(); - - STRICT_EXPECTED_CALL(HTTPAPIEX_Create("h.h")); /*this is creating the httpapiex handle to storage (it is always the same host)*/ - STRICT_EXPECTED_CALL(STRING_construct("\r\n")); /*this is starting to build the XML used in Put Block List operation*/ + umock_c_reset_all_calls(); + STRICT_EXPECTED_CALL(Azure_Base64_Encode_Bytes(IGNORED_PTR_ARG, 6)); + STRICT_EXPECTED_CALL(singlylinkedlist_add(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_construct(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_concat_with_STRING(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) + .CallCannotFail(); + STRICT_EXPECTED_CALL(HTTPAPIEX_ExecuteRequest( + TEST_HTTPAPIEX_HANDLE, HTTPAPI_REQUEST_PUT, IGNORED_PTR_ARG, IGNORED_PTR_ARG, blockData, &responseHttpStatus, IGNORED_PTR_ARG, responseContent)); + STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); - /*uploading blocks (Put Block)*/ - for (size_t blockNumber = 0;blockNumber < (testUploadToBlobContentMaxSize - 1) / (100 * 1024 * 1024) + 1;blockNumber++) - { - STRICT_EXPECTED_CALL(BUFFER_create(testUploadToBlobContent + blockNumber * 100 * 1024 * 1024, - (blockNumber != (testUploadToBlobContentMaxSize - 1) / (100 * 1024 * 1024)) ? 100 * 1024 * 1024 : (testUploadToBlobContentMaxSize - 1) % (100 * 1024 * 1024) + 1 /*condition to take care of "the size of the last block*/ - )); /*this is the content to be uploaded by this call*/ - - /*here some sprintf happens and that produces a string in the form: 000000...049999*/ - STRICT_EXPECTED_CALL(Azure_Base64_Encode_Bytes(IGNORED_PTR_ARG, 6)) /*this is converting the produced blockID string to a base64 representation*/ /*3, 16, 29... (16 numbers)*/ - .IgnoreArgument_source(); - - STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, "")) /*this is building the XML*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_concat_with_STRING(IGNORED_PTR_ARG, IGNORED_PTR_ARG)) /*this is building the XML*/ - .IgnoreArgument_s1() - .IgnoreArgument_s2(); - STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, "")) /*this is building the XML*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_construct("/something?a=b")); /*this is building the relativePath*/ - - STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, "&comp=block&blockid=")) /*this is building the relativePath*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_concat_with_STRING(IGNORED_PTR_ARG, IGNORED_PTR_ARG)) /*this is building the relativePath by adding the blockId (base64 encoded_*/ - .IgnoreArgument_s1() - .IgnoreArgument_s2(); - - STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) /*this is getting the relative path as const char* */ /*11, 24, 27...*/ - .IgnoreArgument_handle() - .CallCannotFail(); - - STRICT_EXPECTED_CALL(HTTPAPIEX_ExecuteRequest(IGNORED_PTR_ARG, HTTPAPI_REQUEST_PUT, IGNORED_PTR_ARG, NULL, IGNORED_PTR_ARG, &httpResponse, NULL, testValidBufferHandle)) - .IgnoreArgument_handle() - .IgnoreArgument_relativePath() - .IgnoreArgument_requestContent() - .CopyOutArgumentBuffer_statusCode(&TwoHundred, sizeof(TwoHundred)) - ; - - STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)) /*this is unbuilding the relativePath*/ /*13, 26, 39...*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)) /*this is unbuilding the blockID string to a base64 representation*/ /*14, 27, 40...*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG)) /*this was the content to be uploaded*/ /*15, 28, 41...210 (16 numbers)*/ - .IgnoreArgument_handle(); - } + ///act + BLOB_RESULT result = Blob_PutBlock( + TEST_HTTPAPIEX_HANDLE, TEST_RELATIVE_PATH_1, blockId, blockData, blockIdList, &responseHttpStatus, responseContent); - /*this part is Put Block list*/ - STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, "")) /*This is closing the XML*/ /*211*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_construct("/something?a=b")); /*this is building the relative path for the Put BLock list*/ + ///assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(int, BLOB_OK, result); - STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, "&comp=blocklist")) /*This is still building relative path for Put Block list*/ - .IgnoreArgument_handle(); + ///cleanup +} - STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) /*this is getting the XML as const char* so it can be passed to _ExecuteRequest*/ - .IgnoreArgument_handle() - .CallCannotFail(); +TEST_FUNCTION(Blob_PutBlock_failure_checks) +{ + ///arrange + unsigned int blockId = 0; + BUFFER_HANDLE blockData = TEST_BUFFER_HANDLE; + SINGLYLINKEDLIST_HANDLE blockIdList = TEST_SINGLYLINKEDLIST_HANDLE; + unsigned int responseHttpStatus = 0; + BUFFER_HANDLE responseContent = TEST_BUFFER_HANDLE; - STRICT_EXPECTED_CALL(BUFFER_create(IGNORED_PTR_ARG, IGNORED_NUM_ARG)) /*this is creating the XML body as BUFFER_HANDLE*/ - .IgnoreAllArguments(); + ASSERT_ARE_EQUAL(int, 0, umock_c_negative_tests_init()); - STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) /*this is getting the relative path*/ - .IgnoreArgument_handle() + umock_c_reset_all_calls(); + STRICT_EXPECTED_CALL(Azure_Base64_Encode_Bytes(IGNORED_PTR_ARG, 6)); + STRICT_EXPECTED_CALL(singlylinkedlist_add(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_construct(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_concat_with_STRING(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) .CallCannotFail(); - STRICT_EXPECTED_CALL(HTTPAPIEX_ExecuteRequest( - IGNORED_PTR_ARG, - HTTPAPI_REQUEST_PUT, - IGNORED_PTR_ARG, - NULL, - IGNORED_PTR_ARG, - &httpResponse, - NULL, - testValidBufferHandle - )) - .IgnoreArgument_handle() - .IgnoreArgument_relativePath() - .IgnoreArgument_requestContent() - .CopyOutArgumentBuffer_statusCode(&TwoHundred, sizeof(TwoHundred)) - ; - - STRICT_EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG)) /*This is the XML as BUFFER_HANDLE*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)) /*this is destroying the relative path for Put Block List*/ - .IgnoreArgument_handle(); - set_expected_calls_for_Blob_UploadMultipleBlocksFromSasUri_cleanup(); - + TEST_HTTPAPIEX_HANDLE, HTTPAPI_REQUEST_PUT, IGNORED_PTR_ARG, IGNORED_PTR_ARG, blockData, &responseHttpStatus, IGNORED_PTR_ARG, responseContent)); + STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); umock_c_negative_tests_snapshot(); - for (size_t i = 0; i < umock_c_negative_tests_call_count(); i++) + // act + for (int i = 0; i < umock_c_negative_tests_call_count(); i++) { umock_c_negative_tests_reset(); if (umock_c_negative_tests_can_call_fail(i)) { - + umock_c_negative_tests_reset(); umock_c_negative_tests_fail_call(i); - char temp_str[128]; - sprintf(temp_str, "On failed call %lu", (unsigned long)i); - ///act - context.toUpload = context.size; /* Reinit context */ - BLOB_RESULT result = Blob_UploadMultipleBlocksFromSasUri("https://h.h/something?a=b", FileUpload_GetData_Callback, &context, &httpResponse, testValidBufferHandle, NULL, NULL, NULL, 0); + // arrange + char error_msg[64]; + + // act + BLOB_RESULT result = Blob_PutBlock( + TEST_HTTPAPIEX_HANDLE, TEST_RELATIVE_PATH_1, blockId, blockData, blockIdList, &responseHttpStatus, responseContent); ///assert - ASSERT_ARE_NOT_EQUAL(BLOB_RESULT, BLOB_OK, result, temp_str); - ASSERT_ARE_EQUAL(int, HTTP_OK, httpResponse); + sprintf(error_msg, "On failed call %lu", (unsigned long)i); + ASSERT_ARE_NOT_EQUAL(int, BLOB_OK, result, error_msg); } } + // cleanup umock_c_negative_tests_deinit(); } -TEST_FUNCTION(Blob_UploadMultipleBlocksFromSasUri_64MB_with_certificate_and_network_interface_unhappy_paths) +TEST_FUNCTION(Blob_PutBlock_blockId_max_succeeds) { - unsigned int httpResponse = HTTP_OK; - - (void)umock_c_negative_tests_init(); + ///arrange + unsigned int blockId = 49999; // Maximum + BUFFER_HANDLE blockData = TEST_BUFFER_HANDLE; + SINGLYLINKEDLIST_HANDLE blockIdList = TEST_SINGLYLINKEDLIST_HANDLE; + unsigned int responseHttpStatus = 0; + BUFFER_HANDLE responseContent = TEST_BUFFER_HANDLE; umock_c_reset_all_calls(); + STRICT_EXPECTED_CALL(Azure_Base64_Encode_Bytes(IGNORED_PTR_ARG, 6)); + STRICT_EXPECTED_CALL(singlylinkedlist_add(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_construct(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_concat_with_STRING(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) + .CallCannotFail(); + STRICT_EXPECTED_CALL(HTTPAPIEX_ExecuteRequest( + TEST_HTTPAPIEX_HANDLE, HTTPAPI_REQUEST_PUT, IGNORED_PTR_ARG, IGNORED_PTR_ARG, blockData, &responseHttpStatus, IGNORED_PTR_ARG, responseContent)); + STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); + + ///act + BLOB_RESULT result = Blob_PutBlock( + TEST_HTTPAPIEX_HANDLE, TEST_RELATIVE_PATH_1, blockId, blockData, blockIdList, &responseHttpStatus, responseContent); + + ///assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(int, BLOB_OK, result); + + ///cleanup +} + +TEST_FUNCTION(Blob_PutBlock_blockId_above_max_fails) +{ ///arrange + unsigned int blockId = 50000; // Maximum + BUFFER_HANDLE blockData = TEST_BUFFER_HANDLE; + SINGLYLINKEDLIST_HANDLE blockIdList = TEST_SINGLYLINKEDLIST_HANDLE; + unsigned int responseHttpStatus = 0; + BUFFER_HANDLE responseContent = TEST_BUFFER_HANDLE; + umock_c_reset_all_calls(); - memset(testUploadToBlobContent, '3', testUploadToBlobContentMaxSize); - testUploadToBlobContent[0] = '0'; - testUploadToBlobContent[testUploadToBlobContentMaxSize - 1] = '4'; - context.size = testUploadToBlobContentMaxSize; - context.source = testUploadToBlobContent; - context.toUpload = context.size; + ///act + BLOB_RESULT result = Blob_PutBlock( + TEST_HTTPAPIEX_HANDLE, TEST_RELATIVE_PATH_1, blockId, blockData, blockIdList, &responseHttpStatus, responseContent); - STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)) /*this is creating a copy of the hostname */ - .IgnoreArgument_size(); + ///assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(int, BLOB_ERROR, result); - STRICT_EXPECTED_CALL(HTTPAPIEX_Create("h.h")); /*this is creating the httpapiex handle to storage (it is always the same host)*/ - STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(IGNORED_PTR_ARG, "TrustedCerts", IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(IGNORED_PTR_ARG, OPTION_CURL_INTERFACE, IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(STRING_construct("\r\n")); /*this is starting to build the XML used in Put Block List operation*/ + ///cleanup +} - /*uploading blocks (Put Block)*/ - for (size_t blockNumber = 0;blockNumber < (testUploadToBlobContentMaxSize - 1) / (100 * 1024 * 1024) + 1;blockNumber++) - { - STRICT_EXPECTED_CALL(BUFFER_create(testUploadToBlobContent + blockNumber * 100 * 1024 * 1024, - (blockNumber != (testUploadToBlobContentMaxSize - 1) / (100 * 1024 * 1024)) ? 100 * 1024 * 1024 : (testUploadToBlobContentMaxSize - 1) % (100 * 1024 * 1024) + 1 /*condition to take care of "the size of the last block*/ - )); /*this is the content to be uploaded by this call*/ - - /*here some sprintf happens and that produces a string in the form: 000000...049999*/ - STRICT_EXPECTED_CALL(Azure_Base64_Encode_Bytes(IGNORED_PTR_ARG, 6)) /*this is converting the produced blockID string to a base64 representation*/ /*3, 16, 29... (16 numbers)*/ - .IgnoreArgument_source(); /* 5 */ - - STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, "")) /*this is building the XML*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_concat_with_STRING(IGNORED_PTR_ARG, IGNORED_PTR_ARG)) /*this is building the XML*/ - .IgnoreArgument_s1() - .IgnoreArgument_s2(); - STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, "")) /*this is building the XML*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_construct("/something?a=b")); /*this is building the relativePath*/ - - STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, "&comp=block&blockid=")) /*this is building the relativePath*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_concat_with_STRING(IGNORED_PTR_ARG, IGNORED_PTR_ARG)) /*this is building the relativePath by adding the blockId (base64 encoded_*/ - .IgnoreArgument_s1() - .IgnoreArgument_s2(); - - STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) /*this is getting the relative path as const char* */ /*12, 25, 38...*/ - .IgnoreArgument_handle() - .CallCannotFail(); - - STRICT_EXPECTED_CALL(HTTPAPIEX_ExecuteRequest(IGNORED_PTR_ARG, HTTPAPI_REQUEST_PUT, IGNORED_PTR_ARG, NULL, IGNORED_PTR_ARG, &httpResponse, NULL, testValidBufferHandle)) - .IgnoreArgument_handle() - .IgnoreArgument_relativePath() - .IgnoreArgument_requestContent() - .CopyOutArgumentBuffer_statusCode(&TwoHundred, sizeof(TwoHundred)) - ; /* 13 */ - - STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)) /*this is unbuilding the relativePath*/ /*14, 27, 40...*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)) /*this is unbuilding the blockID string to a base64 representation*/ /*15, 28, 41... */ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG)) /*this was the content to be uploaded*/ /*16, 29, 42...211 (16 numbers)*/ - .IgnoreArgument_handle(); - } +TEST_FUNCTION(Blob_PutBlockList_happy_path_succeeds) +{ + ///arrange + SINGLYLINKEDLIST_HANDLE blockIdList = TEST_SINGLYLINKEDLIST_HANDLE; + unsigned int responseHttpStatus = 0; + BUFFER_HANDLE responseContent = TEST_BUFFER_HANDLE; - /*this part is Put Block list*/ - STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, "")) /*This is closing the XML*/ /*212*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_construct("/something?a=b")); /*this is building the relative path for the Put BLock list*/ + umock_c_reset_all_calls(); + STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); + // createBlockIdListXml(1 block) + STRICT_EXPECTED_CALL(STRING_construct(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(singlylinkedlist_item_get_value(IGNORED_PTR_ARG)) + .CallCannotFail() + .SetReturn(TEST_STRING_HANDLE); + STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_concat_with_STRING(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(singlylinkedlist_get_next_item(IGNORED_PTR_ARG)) + .CallCannotFail() + .SetReturn(NULL); + STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + // Back to Blob_PutBlockList + STRICT_EXPECTED_CALL(STRING_construct(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_length(IGNORED_PTR_ARG)) + .CallCannotFail() + .SetReturn(100); + STRICT_EXPECTED_CALL(BUFFER_create(IGNORED_PTR_ARG, IGNORED_NUM_ARG)); + STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(HTTPAPIEX_ExecuteRequest( + TEST_HTTPAPIEX_HANDLE, HTTPAPI_REQUEST_PUT, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, &responseHttpStatus, IGNORED_PTR_ARG, responseContent)); + STRICT_EXPECTED_CALL(singlylinkedlist_remove_if(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, "&comp=blocklist")) /*This is still building relative path for Put Block list*/ - .IgnoreArgument_handle(); + ///act + BLOB_RESULT result = Blob_PutBlockList( + TEST_HTTPAPIEX_HANDLE, TEST_RELATIVE_PATH_1, blockIdList, &responseHttpStatus, responseContent); - STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) /*this is getting the XML as const char* so it can be passed to _ExecuteRequest*/ - .IgnoreArgument_handle() - .CallCannotFail(); + ///assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(int, BLOB_OK, result); - STRICT_EXPECTED_CALL(BUFFER_create(IGNORED_PTR_ARG, IGNORED_NUM_ARG)) /*this is creating the XML body as BUFFER_HANDLE*/ - .IgnoreAllArguments(); + ///cleanup +} - STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) /*this is getting the relative path*/ - .IgnoreArgument_handle() - .CallCannotFail(); +TEST_FUNCTION(Blob_PutBlockList_failure_checks) +{ + ///arrange + SINGLYLINKEDLIST_HANDLE blockIdList = TEST_SINGLYLINKEDLIST_HANDLE; + unsigned int responseHttpStatus = 0; + BUFFER_HANDLE responseContent = TEST_BUFFER_HANDLE; + ASSERT_ARE_EQUAL(int, 0, umock_c_negative_tests_init()); + umock_c_reset_all_calls(); + STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)) + .CallCannotFail(); + // createBlockIdListXml(1 block) + STRICT_EXPECTED_CALL(STRING_construct(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)) + .CallCannotFail(); + STRICT_EXPECTED_CALL(singlylinkedlist_item_get_value(IGNORED_PTR_ARG)) + .CallCannotFail() + .SetReturn(TEST_STRING_HANDLE); + STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_concat_with_STRING(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(singlylinkedlist_get_next_item(IGNORED_PTR_ARG)) + .CallCannotFail() + .SetReturn(NULL); + STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + // Back to Blob_PutBlockList + STRICT_EXPECTED_CALL(STRING_construct(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) + .CallCannotFail(); + STRICT_EXPECTED_CALL(STRING_length(IGNORED_PTR_ARG)) + .CallCannotFail() + .SetReturn(100); + STRICT_EXPECTED_CALL(BUFFER_create(IGNORED_PTR_ARG, IGNORED_NUM_ARG)); + STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) + .CallCannotFail(); STRICT_EXPECTED_CALL(HTTPAPIEX_ExecuteRequest( - IGNORED_PTR_ARG, - HTTPAPI_REQUEST_PUT, - IGNORED_PTR_ARG, - NULL, - IGNORED_PTR_ARG, - &httpResponse, - NULL, - testValidBufferHandle - )) - .IgnoreArgument_handle() - .IgnoreArgument_relativePath() - .IgnoreArgument_requestContent() - .CopyOutArgumentBuffer_statusCode(&TwoHundred, sizeof(TwoHundred)) - ; - - STRICT_EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG)) /*This is the XML as BUFFER_HANDLE*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)) /*this is destroying the relative path for Put Block List*/ - .IgnoreArgument_handle(); - set_expected_calls_for_Blob_UploadMultipleBlocksFromSasUri_cleanup(); - + TEST_HTTPAPIEX_HANDLE, HTTPAPI_REQUEST_PUT, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, &responseHttpStatus, IGNORED_PTR_ARG, responseContent)); + STRICT_EXPECTED_CALL(singlylinkedlist_remove_if(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)) + .CallCannotFail(); + STRICT_EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); umock_c_negative_tests_snapshot(); - for (size_t i = 0; i < umock_c_negative_tests_call_count(); i++) + // act + for (int i = 0; i < umock_c_negative_tests_call_count(); i++) { umock_c_negative_tests_reset(); if (umock_c_negative_tests_can_call_fail(i)) { + // arrange + char error_msg[64]; + umock_c_negative_tests_reset(); umock_c_negative_tests_fail_call(i); - const char* interfaceName = "eth0"; - char temp_str[128]; - sprintf(temp_str, "On failed call %lu", (unsigned long)i); - ///act - context.toUpload = context.size; /* Reinit context */ - BLOB_RESULT result = Blob_UploadMultipleBlocksFromSasUri("https://h.h/something?a=b", FileUpload_GetData_Callback, &context, &httpResponse, testValidBufferHandle, "a", NULL, interfaceName, 0); + // act + BLOB_RESULT result = Blob_PutBlockList( + TEST_HTTPAPIEX_HANDLE, TEST_RELATIVE_PATH_1, blockIdList, &responseHttpStatus, responseContent); ///assert - ASSERT_ARE_NOT_EQUAL(BLOB_RESULT, BLOB_OK, result, temp_str); - ASSERT_ARE_EQUAL(int, HTTP_OK, httpResponse); + sprintf(error_msg, "On failed call %lu", (unsigned long)i); + ASSERT_ARE_NOT_EQUAL(BLOB_RESULT, BLOB_OK, result, error_msg); } } + // cleanup umock_c_negative_tests_deinit(); } -TEST_FUNCTION(Blob_UploadFromSasUri_when_http_code_is_404_it_immediately_succeeds) +TEST_FUNCTION(Blob_PutBlockList_empty_blockIDList_fails) { ///arrange - unsigned int httpResponse = HTTP_OK; - umock_c_reset_all_calls(); + SINGLYLINKEDLIST_HANDLE blockIdList = TEST_SINGLYLINKEDLIST_HANDLE; + unsigned int responseHttpStatus = 0; + BUFFER_HANDLE responseContent = TEST_BUFFER_HANDLE; - memset(testUploadToBlobContent, '3', testUploadToBlobContentMaxSize); - testUploadToBlobContent[0] = '0'; - testUploadToBlobContent[testUploadToBlobContentMaxSize - 1] = '4'; - context.size = testUploadToBlobContentMaxSize; - context.source = testUploadToBlobContent; - context.toUpload = context.size; - - STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)) /*this is creating a copy of the hostname */ - .IgnoreArgument_size(); - - STRICT_EXPECTED_CALL(HTTPAPIEX_Create("h.h")); /*this is creating the httpapiex handle to storage (it is always the same host)*/ - STRICT_EXPECTED_CALL(STRING_construct("\r\n")); /*this is starting to build the XML used in Put Block List operation*/ - - /*uploading blocks (Put Block)*/ /*this simply fails first block*/ - size_t blockNumber = 0; - { - STRICT_EXPECTED_CALL(BUFFER_create(testUploadToBlobContent + blockNumber * 100 * 1024 * 1024, - (blockNumber != (testUploadToBlobContentMaxSize - 1) / (100 * 1024 * 1024)) ? 100 * 1024 * 1024 : (testUploadToBlobContentMaxSize - 1) % (100 * 1024 * 1024) + 1 /*condition to take care of "the size of the last block*/ - )); /*this is the content to be uploaded by this call*/ - - /*here some sprintf happens and that produces a string in the form: 000000...049999*/ - STRICT_EXPECTED_CALL(Azure_Base64_Encode_Bytes(IGNORED_PTR_ARG, 6)) /*this is converting the produced blockID string to a base64 representation*/ - .IgnoreArgument_source(); - - STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, "")) /*this is building the XML*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_concat_with_STRING(IGNORED_PTR_ARG, IGNORED_PTR_ARG)) /*this is building the XML*/ - .IgnoreArgument_s1() - .IgnoreArgument_s2(); - STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, "")) /*this is building the XML*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_construct("/something?a=b")); /*this is building the relativePath*/ - - STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, "&comp=block&blockid=")) /*this is building the relativePath*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_concat_with_STRING(IGNORED_PTR_ARG, IGNORED_PTR_ARG)) /*this is building the relativePath by adding the blockId (base64 encoded_*/ - .IgnoreArgument_s1() - .IgnoreArgument_s2(); - - STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) /*this is getting the relative path as const char* */ - .IgnoreArgument_handle(); - - STRICT_EXPECTED_CALL(HTTPAPIEX_ExecuteRequest(IGNORED_PTR_ARG, HTTPAPI_REQUEST_PUT, IGNORED_PTR_ARG, NULL, IGNORED_PTR_ARG, &httpResponse, NULL, testValidBufferHandle)) - .IgnoreArgument_handle() - .IgnoreArgument_relativePath() - .IgnoreArgument_requestContent() - .CopyOutArgumentBuffer_statusCode(&FourHundredFour, sizeof(FourHundredFour)) - ; - - STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)) /*this is unbuilding the relativePath*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)) /*this is unbuilding the blockID string to a base64 representation*/ - .IgnoreArgument_handle(); - STRICT_EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG)) /*this was the content to be uploaded*/ - .IgnoreArgument_handle(); - } - - /*this part is Put Block list*/ /*notice: no op because it failed before with 404*/ - - set_expected_calls_for_Blob_UploadMultipleBlocksFromSasUri_cleanup(); + umock_c_reset_all_calls(); + STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)) + .SetReturn(NULL); ///act - BLOB_RESULT result = Blob_UploadMultipleBlocksFromSasUri("https://h.h/something?a=b", FileUpload_GetData_Callback, &context, &httpResponse, testValidBufferHandle, NULL, NULL, NULL, 0); + BLOB_RESULT result = Blob_PutBlockList( + TEST_HTTPAPIEX_HANDLE, TEST_RELATIVE_PATH_1, blockIdList, &responseHttpStatus, responseContent); ///assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); - ASSERT_ARE_EQUAL(BLOB_RESULT, BLOB_OK, result); - ASSERT_ARE_EQUAL(int, HTTP_NOT_FOUND, httpResponse); -} - -TEST_FUNCTION(Blob_UploadMultipleBlocksFromSasUri_when_blockSize_too_big_fails) -{ - ///arrange - unsigned int httpResponse = HTTP_OK; - BLOB_UPLOAD_CONTEXT_FAKE fakeContext; - fakeContext.blockSent = 0; - fakeContext.blockSize = BLOCK_SIZE + 1; - fakeContext.blocksCount = 1; - fakeContext.fakeData = NULL; - fakeContext.abortOnBlockNumber = -1; - - ///act - BLOB_RESULT result = Blob_UploadMultipleBlocksFromSasUri("https://h.h/something?a=b", FileUpload_GetFakeData_Callback, &fakeContext, &httpResponse, testValidBufferHandle, NULL, NULL, NULL, 0); - - ///assert - ASSERT_ARE_EQUAL(BLOB_RESULT, BLOB_INVALID_ARG, result); - ASSERT_ARE_EQUAL(int, HTTP_OK, httpResponse); + ASSERT_ARE_EQUAL(int, BLOB_ERROR, result); ///cleanup - gballoc_free(fakeContext.fakeData); } -TEST_FUNCTION(Blob_UploadMultipleBlocksFromSasUri_when_blockSize_is_4MB_succeeds) +TEST_FUNCTION(Blob_PutBlockList_NULL_HTTPAPIEX_HANDLE_fails) { ///arrange - unsigned int httpResponse = HTTP_OK; - BLOB_UPLOAD_CONTEXT_FAKE fakeContext; - fakeContext.blockSent = 0; - fakeContext.blockSize = BLOCK_SIZE; - fakeContext.blocksCount = 1; - fakeContext.fakeData = NULL; - fakeContext.abortOnBlockNumber = -1; + SINGLYLINKEDLIST_HANDLE blockIdList = TEST_SINGLYLINKEDLIST_HANDLE; + unsigned int responseHttpStatus = 0; + BUFFER_HANDLE responseContent = TEST_BUFFER_HANDLE; - ///act - BLOB_RESULT result = Blob_UploadMultipleBlocksFromSasUri("https://h.h/something?a=b", FileUpload_GetFakeData_Callback, &fakeContext, &httpResponse, testValidBufferHandle, NULL, NULL, NULL, 0); - - ///assert - ASSERT_ARE_EQUAL(BLOB_RESULT, BLOB_OK, result); - ASSERT_ARE_EQUAL(int, HTTP_OK, httpResponse); - - ///cleanup - gballoc_free(fakeContext.fakeData); -} - -TEST_FUNCTION(Blob_UploadMultipleBlocksFromSasUri_when_blockCount_is_maximum_succeeds) -{ - ///arrange - unsigned int httpResponse = HTTP_OK; - BLOB_UPLOAD_CONTEXT_FAKE fakeContext; - fakeContext.blockSent = 0; - fakeContext.blockSize = 1; - fakeContext.blocksCount = MAX_BLOCK_COUNT; - fakeContext.fakeData = NULL; - fakeContext.abortOnBlockNumber = -1; + umock_c_reset_all_calls(); ///act - BLOB_RESULT result = Blob_UploadMultipleBlocksFromSasUri("https://h.h/something?a=b", FileUpload_GetFakeData_Callback, &fakeContext, &httpResponse, testValidBufferHandle, NULL, NULL, NULL, 0); + BLOB_RESULT result = Blob_PutBlockList( + NULL, TEST_RELATIVE_PATH_1, blockIdList, &responseHttpStatus, responseContent); ///assert - ASSERT_ARE_EQUAL(BLOB_RESULT, BLOB_OK, result); - ASSERT_ARE_EQUAL(int, HTTP_OK, httpResponse); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(int, BLOB_INVALID_ARG, result); ///cleanup - gballoc_free(fakeContext.fakeData); } -TEST_FUNCTION(Blob_UploadMultipleBlocksFromSasUri_when_blockCount_is_one_over_maximum_fails) +TEST_FUNCTION(Blob_PutBlockList_NULL_blockIdList_fails) { ///arrange - unsigned int httpResponse = HTTP_OK; - BLOB_UPLOAD_CONTEXT_FAKE fakeContext; - fakeContext.blockSent = 0; - fakeContext.blockSize = 1; - fakeContext.blocksCount = MAX_BLOCK_COUNT + 1; - fakeContext.fakeData = NULL; - fakeContext.abortOnBlockNumber = -1; + unsigned int responseHttpStatus = 0; + BUFFER_HANDLE responseContent = TEST_BUFFER_HANDLE; + + umock_c_reset_all_calls(); ///act - BLOB_RESULT result = Blob_UploadMultipleBlocksFromSasUri("https://h.h/something?a=b", FileUpload_GetFakeData_Callback, &fakeContext, &httpResponse, testValidBufferHandle, NULL, NULL, NULL, 0); + BLOB_RESULT result = Blob_PutBlockList( + TEST_HTTPAPIEX_HANDLE, TEST_RELATIVE_PATH_1, NULL, &responseHttpStatus, responseContent); ///assert - ASSERT_ARE_EQUAL(BLOB_RESULT, BLOB_INVALID_ARG, result); - ASSERT_ARE_EQUAL(int, HTTP_OK, httpResponse); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(int, BLOB_INVALID_ARG, result); ///cleanup - gballoc_free(fakeContext.fakeData); } -TEST_FUNCTION(Blob_UploadMultipleBlocksFromSasUri_returns_BLOB_ABORTED_when_callback_aborts_immediately) +TEST_FUNCTION(Blob_PutBlockList_NULL_relative_path_fails) { ///arrange - unsigned int httpResponse = HTTP_OK; - BLOB_UPLOAD_CONTEXT_FAKE fakeContext; - fakeContext.blockSent = 0; - fakeContext.blockSize = 1; - fakeContext.blocksCount = 10; - fakeContext.fakeData = NULL; - fakeContext.abortOnBlockNumber = 0; + SINGLYLINKEDLIST_HANDLE blockIdList = TEST_SINGLYLINKEDLIST_HANDLE; + unsigned int responseHttpStatus = 0; + BUFFER_HANDLE responseContent = TEST_BUFFER_HANDLE; + + umock_c_reset_all_calls(); ///act - BLOB_RESULT result = Blob_UploadMultipleBlocksFromSasUri("https://h.h/something?a=b", FileUpload_GetFakeData_Callback, &fakeContext, &httpResponse, testValidBufferHandle, NULL, NULL, NULL, 0); + BLOB_RESULT result = Blob_PutBlockList( + TEST_HTTPAPIEX_HANDLE, NULL, blockIdList, &responseHttpStatus, responseContent); ///assert - ASSERT_ARE_EQUAL(BLOB_RESULT, BLOB_ABORTED, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(int, BLOB_INVALID_ARG, result); ///cleanup - gballoc_free(fakeContext.fakeData); } -TEST_FUNCTION(Blob_UploadMultipleBlocksFromSasUri_returns_BLOB_ABORTED_when_callback_aborts_after_5_blocks) +TEST_FUNCTION(Blob_PutBlockList_NULL_http_status_fails) { ///arrange - unsigned int httpResponse = HTTP_OK; - BLOB_UPLOAD_CONTEXT_FAKE fakeContext; - fakeContext.blockSent = 0; - fakeContext.blockSize = 1; - fakeContext.blocksCount = 10; - fakeContext.fakeData = NULL; - fakeContext.abortOnBlockNumber = 5; + SINGLYLINKEDLIST_HANDLE blockIdList = TEST_SINGLYLINKEDLIST_HANDLE; + BUFFER_HANDLE responseContent = TEST_BUFFER_HANDLE; + + umock_c_reset_all_calls(); ///act - BLOB_RESULT result = Blob_UploadMultipleBlocksFromSasUri("https://h.h/something?a=b", FileUpload_GetFakeData_Callback, &fakeContext, &httpResponse, testValidBufferHandle, NULL, NULL, NULL, 0); + BLOB_RESULT result = Blob_PutBlockList( + TEST_HTTPAPIEX_HANDLE, TEST_RELATIVE_PATH_1, blockIdList, NULL, responseContent); ///assert - ASSERT_ARE_EQUAL(BLOB_RESULT, BLOB_ABORTED, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(int, BLOB_INVALID_ARG, result); ///cleanup - gballoc_free(fakeContext.fakeData); } -TEST_FUNCTION(Blob_UploadMultipleBlocksFromSasUri_with_empty_payload) +TEST_FUNCTION(Blob_PutBlockList_no_response_content_succeeds) { ///arrange - unsigned int httpResponse = HTTP_OK; - BLOB_UPLOAD_CONTEXT_FAKE fakeContext; - fakeContext.blockSent = 0; - fakeContext.blockSize = 1; - fakeContext.blocksCount = 0; - fakeContext.fakeData = NULL; - fakeContext.abortOnBlockNumber = 5; + SINGLYLINKEDLIST_HANDLE blockIdList = TEST_SINGLYLINKEDLIST_HANDLE; + unsigned int responseHttpStatus = 0; + + umock_c_reset_all_calls(); + STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); + // createBlockIdListXml(1 block) + STRICT_EXPECTED_CALL(STRING_construct(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(singlylinkedlist_item_get_value(IGNORED_PTR_ARG)) + .CallCannotFail() + .SetReturn(TEST_STRING_HANDLE); + STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_concat_with_STRING(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(singlylinkedlist_get_next_item(IGNORED_PTR_ARG)) + .CallCannotFail() + .SetReturn(NULL); + STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + // Back to Blob_PutBlockList + STRICT_EXPECTED_CALL(STRING_construct(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_length(IGNORED_PTR_ARG)) + .CallCannotFail() + .SetReturn(100); + STRICT_EXPECTED_CALL(BUFFER_create(IGNORED_PTR_ARG, IGNORED_NUM_ARG)); + STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(HTTPAPIEX_ExecuteRequest( + TEST_HTTPAPIEX_HANDLE, HTTPAPI_REQUEST_PUT, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, &responseHttpStatus, IGNORED_PTR_ARG, NULL)); + STRICT_EXPECTED_CALL(singlylinkedlist_remove_if(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); ///act - BLOB_RESULT result = Blob_UploadMultipleBlocksFromSasUri("https://h.h/something?a=b", FileUpload_GetFakeData_Callback, &fakeContext, &httpResponse, testValidBufferHandle, NULL, NULL, NULL, 0); + BLOB_RESULT result = Blob_PutBlockList( + TEST_HTTPAPIEX_HANDLE, TEST_RELATIVE_PATH_1, blockIdList, &responseHttpStatus, NULL); ///assert - ASSERT_ARE_EQUAL(BLOB_RESULT, BLOB_OK, result); - ASSERT_ARE_EQUAL(int, HTTP_OK, httpResponse); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(int, BLOB_OK, result); ///cleanup - gballoc_free(fakeContext.fakeData); } END_TEST_SUITE(blob_ut); From 136911a45deefd4907019b4db5496fe6c2f0ad81 Mon Sep 17 00:00:00 2001 From: Ewerton Scaboro da Silva Date: Wed, 12 Jul 2023 15:27:22 -0700 Subject: [PATCH 05/27] Update iothub_client_ll_u2b_ut --- .../internal/iothub_client_ll_uploadtoblob.h | 1 - .../iothub_client_ll_u2b_ut.c | 301 ++++-------------- 2 files changed, 60 insertions(+), 242 deletions(-) diff --git a/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h b/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h index ee599dbe20..5b963a599d 100644 --- a/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h +++ b/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h @@ -61,7 +61,6 @@ extern "C" */ MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context); - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_InitializeUpload, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, handle, const char*, destinationFileName, char**, uploadCorrelationId, char**, azureBlobSasUri); MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, IoTHubClient_LL_UploadToBlob_CreateContext, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, handle, const char*, azureBlobSasUri); MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_PutBlock, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContext, uint32_t, blockNumber, const uint8_t*, dataPtr, size_t, dataSize); diff --git a/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c b/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c index d64d22b8d8..a03dd53b51 100644 --- a/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c +++ b/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c @@ -74,6 +74,9 @@ MOCKABLE_FUNCTION(, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT, TestMultiBlockUpl #define TEST_API_VERSION "?api-version=2016-11-14" #define TEST_IOTHUB_SDK_VERSION "1.11.0" +#define TEST_HTTPAPIEX_HANDLE (HTTPAPIEX_HANDLE)0x4444 +#define TEST_U2B_CONTEXT_HANDLE (IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE)0x4445 + static const char* const testUploadtrustedCertificates = "some certificates"; static const char* const TEST_SAS_TOKEN = "test_sas_token"; static const char* const TEST_PRIVATE = "test_private"; @@ -490,6 +493,30 @@ typedef struct UPLOADTOBLOB_TEST_UT_CONTEXT_TAG static UPLOADTOBLOB_TEST_UT_CONTEXT uploadtoblobTest_Context; +static void setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE cred_type) +{ + STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); + STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); + STRICT_EXPECTED_CALL(IoTHubClient_Auth_Get_DeviceId(TEST_AUTH_HANDLE)); + STRICT_EXPECTED_CALL(IoTHubClient_Auth_Get_Credential_Type(TEST_AUTH_HANDLE)) + .SetReturn(cred_type) + .CallCannotFail(); + + if (cred_type == IOTHUB_CREDENTIAL_TYPE_X509_ECC) + { + STRICT_EXPECTED_CALL(IoTHubClient_Auth_Get_x509_info(TEST_AUTH_HANDLE, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + } + else if (cred_type == IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN) + { + STRICT_EXPECTED_CALL(IoTHubClient_Auth_Get_SasToken(TEST_AUTH_HANDLE, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG)); + } +} + +static void reset_test_data() +{ + memset(&blobUploadContext, 0, sizeof(blobUploadContext)); +} + BEGIN_TEST_SUITE(iothubclient_ll_uploadtoblob_ut) TEST_SUITE_INITIALIZE(TestClassInitialize) @@ -592,8 +619,9 @@ TEST_SUITE_INITIALIZE(TestClassInitialize) REGISTER_GLOBAL_MOCK_RETURN(HTTPAPIEX_SetOption, HTTPAPIEX_OK); REGISTER_GLOBAL_MOCK_FAIL_RETURN(HTTPAPIEX_SetOption, HTTPAPIEX_ERROR); - REGISTER_GLOBAL_MOCK_RETURN(Blob_UploadMultipleBlocksFromSasUri, BLOB_OK); - REGISTER_GLOBAL_MOCK_FAIL_RETURN(Blob_UploadMultipleBlocksFromSasUri, BLOB_ERROR); + REGISTER_GLOBAL_MOCK_RETURNS(Blob_CreateHttpConnection, TEST_HTTPAPIEX_HANDLE, NULL); + REGISTER_GLOBAL_MOCK_RETURNS(Blob_PutBlock, BLOB_OK, BLOB_ERROR); + REGISTER_GLOBAL_MOCK_RETURNS(Blob_PutBlockList, BLOB_OK, BLOB_ERROR); REGISTER_GLOBAL_MOCK_FAIL_RETURN(mallocAndStrcpy_s, MU_FAILURE); REGISTER_GLOBAL_MOCK_HOOK(mallocAndStrcpy_s, my_mallocAndStrcpy_s); @@ -606,11 +634,6 @@ TEST_SUITE_CLEANUP(TestClassCleanup) TEST_MUTEX_DESTROY(g_testByTest); } -static void reset_test_data() -{ - memset(&blobUploadContext, 0, sizeof(blobUploadContext)); -} - TEST_FUNCTION_INITIALIZE(TestMethodInitialize) { if (TEST_MUTEX_ACQUIRE(g_testByTest)) @@ -628,214 +651,10 @@ TEST_FUNCTION_CLEANUP(TestMethodCleanup) TEST_MUTEX_RELEASE(g_testByTest); } -static void setup_uploadtoblob_create_mocks(IOTHUB_CREDENTIAL_TYPE cred_type) -{ - STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); - STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); - STRICT_EXPECTED_CALL(IoTHubClient_Auth_Get_DeviceId(TEST_AUTH_HANDLE)); - STRICT_EXPECTED_CALL(IoTHubClient_Auth_Get_Credential_Type(TEST_AUTH_HANDLE)) - .SetReturn(cred_type) - .CallCannotFail(); - if (cred_type == IOTHUB_CREDENTIAL_TYPE_X509_ECC) - { - STRICT_EXPECTED_CALL(IoTHubClient_Auth_Get_x509_info(TEST_AUTH_HANDLE, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); - } - else if (cred_type == IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN) - { - STRICT_EXPECTED_CALL(IoTHubClient_Auth_Get_SasToken(TEST_AUTH_HANDLE, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG)); - } -} - -static void setup_steps_1_and_2_mocks(IOTHUB_CREDENTIAL_TYPE cred_type) -{ - int status_code = 200; - - // Step 1 - STRICT_EXPECTED_CALL(STRING_length(IGNORED_PTR_ARG)).CallCannotFail(); - STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)).CallCannotFail(); - STRICT_EXPECTED_CALL(BUFFER_create(IGNORED_PTR_ARG, IGNORED_NUM_ARG)); - STRICT_EXPECTED_CALL(BUFFER_new()); - - STRICT_EXPECTED_CALL(HTTPHeaders_AddHeaderNameValuePair(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(HTTPHeaders_AddHeaderNameValuePair(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(HTTPHeaders_AddHeaderNameValuePair(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); // 11 - if (cred_type == IOTHUB_CREDENTIAL_TYPE_X509_ECC || cred_type == IOTHUB_CREDENTIAL_TYPE_X509) - { - STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)).CallCannotFail(); - STRICT_EXPECTED_CALL(HTTPAPIEX_ExecuteRequest(IGNORED_PTR_ARG, HTTPAPI_REQUEST_POST, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, NULL, IGNORED_PTR_ARG)) - .CopyOutArgumentBuffer_statusCode(&status_code, sizeof(status_code)); - } - else if (cred_type == IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY) - { - STRICT_EXPECTED_CALL(HTTPHeaders_AddHeaderNameValuePair(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)).CallCannotFail(); - STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)).CallCannotFail(); - STRICT_EXPECTED_CALL(IoTHubClient_Auth_Get_DeviceKey(TEST_AUTH_HANDLE)).CallCannotFail(); - STRICT_EXPECTED_CALL(HTTPAPIEX_SAS_Create_From_String(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); - - STRICT_EXPECTED_CALL(HTTPAPIEX_SAS_ExecuteRequest(IGNORED_PTR_ARG, IGNORED_PTR_ARG, HTTPAPI_REQUEST_POST, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, NULL, IGNORED_PTR_ARG)) - .CopyOutArgumentBuffer_statusCode(&status_code, sizeof(status_code)); - STRICT_EXPECTED_CALL(HTTPAPIEX_SAS_Destroy(IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); - } - else if (cred_type == IOTHUB_CREDENTIAL_TYPE_DEVICE_AUTH) - { - STRICT_EXPECTED_CALL(HTTPHeaders_AddHeaderNameValuePair(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(get_time(NULL)).CallCannotFail(); - STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)).CallCannotFail(); - STRICT_EXPECTED_CALL(IoTHubClient_Auth_Get_SasToken(TEST_AUTH_HANDLE, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(HTTPHeaders_ReplaceHeaderNameValuePair(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)).CallCannotFail(); - STRICT_EXPECTED_CALL(HTTPAPIEX_ExecuteRequest(IGNORED_PTR_ARG, HTTPAPI_REQUEST_POST, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, NULL, IGNORED_PTR_ARG)) - .CopyOutArgumentBuffer_statusCode(&status_code, sizeof(status_code)); - STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); - } - else if (cred_type == IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN) - { - STRICT_EXPECTED_CALL(HTTPHeaders_AddHeaderNameValuePair(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(HTTPHeaders_ReplaceHeaderNameValuePair(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)).CallCannotFail(); - STRICT_EXPECTED_CALL(HTTPAPIEX_ExecuteRequest(IGNORED_PTR_ARG, HTTPAPI_REQUEST_POST, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, NULL, IGNORED_PTR_ARG)) - .CopyOutArgumentBuffer_statusCode(&status_code, sizeof(status_code)); - } - STRICT_EXPECTED_CALL(BUFFER_u_char(IGNORED_PTR_ARG)).CallCannotFail(); - STRICT_EXPECTED_CALL(BUFFER_length(IGNORED_PTR_ARG)).CallCannotFail(); - STRICT_EXPECTED_CALL(STRING_from_byte_array(IGNORED_PTR_ARG, IGNORED_NUM_ARG)); - STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)).CallCannotFail(); - - STRICT_EXPECTED_CALL(json_parse_string(IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(json_value_get_object(IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(json_object_get_string(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(json_object_get_string(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(json_object_get_string(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(json_object_get_string(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(json_object_get_string(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(URL_EncodeString(IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)).CallCannotFail(); - STRICT_EXPECTED_CALL(STRING_copy(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(json_value_free(IGNORED_PTR_ARG)); - - STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); -} - -static void setup_steps_3(IOTHUB_CREDENTIAL_TYPE cred_type) -{ - int status_code = 200; - - if (cred_type == IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY) - { - STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)).CallCannotFail(); - STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)).CallCannotFail(); - STRICT_EXPECTED_CALL(IoTHubClient_Auth_Get_DeviceKey(TEST_AUTH_HANDLE)).CallCannotFail(); - STRICT_EXPECTED_CALL(HTTPAPIEX_SAS_Create_From_String(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(HTTPAPIEX_SAS_ExecuteRequest(IGNORED_PTR_ARG, IGNORED_PTR_ARG, HTTPAPI_REQUEST_POST, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, NULL, IGNORED_PTR_ARG)) - .CopyOutArgumentBuffer_statusCode(&status_code, sizeof(status_code)); - STRICT_EXPECTED_CALL(HTTPAPIEX_SAS_Destroy(IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); - } - else - { - STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)).CallCannotFail(); - STRICT_EXPECTED_CALL(HTTPAPIEX_ExecuteRequest(IGNORED_PTR_ARG, HTTPAPI_REQUEST_POST, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, NULL, IGNORED_PTR_ARG)) - .CopyOutArgumentBuffer_statusCode(&status_code, sizeof(status_code)); - } - STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); -} - -static void setup_Blob_UploadMultipleBlocksFromSasUri_mocks(IOTHUB_CREDENTIAL_TYPE cred_type, BLOB_RESULT blob_result, bool null_buffer) -{ - STRICT_EXPECTED_CALL(BUFFER_new()); - STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)).CallCannotFail(); - - unsigned int status_code; - if (BLOB_OK != blob_result) - { - status_code = 404; - STRICT_EXPECTED_CALL(Blob_UploadMultipleBlocksFromSasUri(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG)) - .CopyOutArgumentBuffer_httpStatus(&status_code, sizeof(status_code)) - .SetReturn(blob_result); - STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(STRING_length(IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(BUFFER_build(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG)); - - setup_steps_3(cred_type); - STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); - } - else - { - status_code = 200; - STRICT_EXPECTED_CALL(Blob_UploadMultipleBlocksFromSasUri(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG)) - .CopyOutArgumentBuffer_httpStatus(&status_code, sizeof(status_code)).CallCannotFail(); - - if (null_buffer) - { - STRICT_EXPECTED_CALL(BUFFER_u_char(IGNORED_PTR_ARG)).SetReturn(NULL); - } - else - { - STRICT_EXPECTED_CALL(BUFFER_u_char(IGNORED_PTR_ARG)).CallCannotFail(); - } - STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)).CallCannotFail(); - STRICT_EXPECTED_CALL(STRING_length(IGNORED_PTR_ARG)).CallCannotFail(); - STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)).CallCannotFail(); - STRICT_EXPECTED_CALL(BUFFER_create(IGNORED_PTR_ARG, IGNORED_NUM_ARG)); - - setup_steps_3(cred_type); - STRICT_EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); - } -} - -static void setup_upload_blocks_mocks(IOTHUB_CREDENTIAL_TYPE cred_type, bool proxy, bool set_timeout, bool trusted_cert, BLOB_RESULT blob_result, bool null_buffer, bool set_tls_renego) -{ - STRICT_EXPECTED_CALL(HTTPAPIEX_Create(IGNORED_PTR_ARG)); - if (set_timeout) - { - STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(IGNORED_PTR_ARG, OPTION_HTTP_TIMEOUT, IGNORED_PTR_ARG)); - } - if (cred_type == IOTHUB_CREDENTIAL_TYPE_X509_ECC || cred_type == IOTHUB_CREDENTIAL_TYPE_X509) - { - if (set_tls_renego) - { - STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(IGNORED_PTR_ARG, OPTION_SET_TLS_RENEGOTIATION, IGNORED_PTR_ARG)); - } - STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(IGNORED_PTR_ARG, OPTION_X509_CERT, IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(IGNORED_PTR_ARG, OPTION_X509_PRIVATE_KEY, IGNORED_PTR_ARG)); - } - if (trusted_cert) - { - STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(IGNORED_PTR_ARG, OPTION_TRUSTED_CERT, IGNORED_PTR_ARG)); - } - if (proxy) - { - STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(IGNORED_PTR_ARG, OPTION_HTTP_PROXY, IGNORED_PTR_ARG)); - } - - STRICT_EXPECTED_CALL(STRING_new()); - STRICT_EXPECTED_CALL(STRING_new()); - STRICT_EXPECTED_CALL(HTTPHeaders_Alloc()); - - setup_steps_1_and_2_mocks(cred_type); - - setup_Blob_UploadMultipleBlocksFromSasUri_mocks(cred_type, blob_result, null_buffer); - - STRICT_EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(HTTPHeaders_Free(IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(HTTPAPIEX_Destroy(IGNORED_PTR_ARG)); -} TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Create_sas_token_succeeds) { //arrange - setup_uploadtoblob_create_mocks(IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN); + setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN); //act IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); @@ -851,7 +670,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Create_sas_token_succeeds) TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Create_x509_succeeds) { //arrange - setup_uploadtoblob_create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); + setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); //act IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); @@ -867,7 +686,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Create_x509_succeeds) TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Create_x509_ecc_succeeds) { //arrange - setup_uploadtoblob_create_mocks(IOTHUB_CREDENTIAL_TYPE_X509_ECC); + setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509_ECC); //act IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); @@ -916,7 +735,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Create_fails) int result = umock_c_negative_tests_init(); ASSERT_ARE_EQUAL(int, 0, result); - setup_uploadtoblob_create_mocks(IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY); + setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY); umock_c_negative_tests_snapshot(); @@ -997,29 +816,29 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Destroy_handle_x509_succeeds) //cleanup } -TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Impl_handle_NULL_fails) +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks_handle_NULL_fails) { //arrange umock_c_reset_all_calls(); //act - IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_Impl(NULL, TEST_DESTINATION_FILENAME, TEST_SOURCE, TEST_SOURCE_LENGTH); - + IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(NULL, FileUpload_GetData_Callback, &blobUploadContext); + //assert - ASSERT_ARE_NOT_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_INVALID_ARG, result); //cleanup } -TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Impl_source_NULL_fails) +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks_NULL_callback_fails) { //arrange - IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); umock_c_reset_all_calls(); + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); //act - IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_Impl(h, TEST_DESTINATION_FILENAME, NULL, TEST_SOURCE_LENGTH); + IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(TEST_U2B_CONTEXT_HANDLE, NULL, &blobUploadContext); //assert ASSERT_ARE_NOT_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); @@ -1029,7 +848,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Impl_source_NULL_fails) IoTHubClient_LL_UploadToBlob_Destroy(h); } -TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Impl_with_proxy_succeeds) +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks_succeeds) { //arrange HTTP_PROXY_OPTIONS proxy_options = { 0 }; @@ -1099,7 +918,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Impl_succeeds) TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Impl_device_key_succeeds) { //arrange - setup_uploadtoblob_create_mocks(IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY); + setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); umock_c_reset_all_calls(); @@ -1120,7 +939,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Impl_x509_succeeds) { //arrange - setup_uploadtoblob_create_mocks(IOTHUB_CREDENTIAL_TYPE_X509_ECC); + setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509_ECC); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); umock_c_reset_all_calls(); @@ -1141,7 +960,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Impl_x509_with_tls_renegotiation_set_ { //arrange - setup_uploadtoblob_create_mocks(IOTHUB_CREDENTIAL_TYPE_X509_ECC); + setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509_ECC); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); bool set_tls_renegotiaton = false; ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_BLOB_UPLOAD_TLS_RENEGOTIATION, &set_tls_renegotiaton)); @@ -1166,7 +985,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Impl_x509_with_tls_renegotiation_set_ { //arrange - setup_uploadtoblob_create_mocks(IOTHUB_CREDENTIAL_TYPE_X509_ECC); + setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509_ECC); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); bool set_tls_renegotiaton = true; ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_BLOB_UPLOAD_TLS_RENEGOTIATION, &set_tls_renegotiaton)); @@ -1190,7 +1009,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Impl_x509_with_tls_renegotiation_set_ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Impl_device_auth_succeeds) { //arrange - setup_uploadtoblob_create_mocks(IOTHUB_CREDENTIAL_TYPE_DEVICE_AUTH); + setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_DEVICE_AUTH); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); umock_c_reset_all_calls(); @@ -1245,7 +1064,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Impl_dev_key_fails) //arrange ASSERT_ARE_EQUAL(int, 0, umock_c_negative_tests_init()); - setup_uploadtoblob_create_mocks(IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY); + setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); umock_c_reset_all_calls(); @@ -1279,7 +1098,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Impl_dev_auth_fails) //arrange ASSERT_ARE_EQUAL(int, 0, umock_c_negative_tests_init()); - setup_uploadtoblob_create_mocks(IOTHUB_CREDENTIAL_TYPE_DEVICE_AUTH); + setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_DEVICE_AUTH); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); umock_c_reset_all_calls(); @@ -1402,7 +1221,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_verbose_succeeds) TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_x509_cert_succeeds) { //arrange - setup_uploadtoblob_create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); + setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); umock_c_reset_all_calls(); @@ -1423,7 +1242,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_openssl_private_key_type_su { int privateKeyType = 1; //arrange - setup_uploadtoblob_create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); + setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); umock_c_reset_all_calls(); @@ -1443,7 +1262,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_openssl_engine_type_succeed { const char* engine = "pkcs11"; //arrange - setup_uploadtoblob_create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); + setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); umock_c_reset_all_calls(); @@ -1462,7 +1281,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_openssl_engine_type_succeed TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_Network_Interface) { //arrange - setup_uploadtoblob_create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); + setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); umock_c_reset_all_calls(); @@ -1483,7 +1302,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_Network_Interface) TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_x509_cert_twice_succeeds) { //arrange - setup_uploadtoblob_create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); + setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_X509_CERT, TEST_CERT); umock_c_reset_all_calls(); @@ -1505,7 +1324,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_x509_cert_twice_succeeds) TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_x509_key_succeeds) { //arrange - setup_uploadtoblob_create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); + setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); umock_c_reset_all_calls(); @@ -1525,7 +1344,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_x509_key_succeeds) TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_x509_trusted_cert_succeeds) { //arrange - setup_uploadtoblob_create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); + setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); umock_c_reset_all_calls(); @@ -1564,7 +1383,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_x509_timeout_succeeds) //arrange size_t timeout = 10; - setup_uploadtoblob_create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); + setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); umock_c_reset_all_calls(); @@ -1584,7 +1403,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_tls_renegotiation_succeeds) //arrange bool set_tls_renegotiaton = true; - setup_uploadtoblob_create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); + setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); umock_c_reset_all_calls(); @@ -1606,7 +1425,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl_succeeds) //arrange REGISTER_GLOBAL_MOCK_HOOK(TestMultiBlockUploadCallback, TestUploadMultiBlockTestSucceeds); - setup_uploadtoblob_create_mocks(IOTHUB_CREDENTIAL_TYPE_X509_ECC); + setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509_ECC); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); umock_c_reset_all_calls(); @@ -1630,7 +1449,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl_fails) //arrange REGISTER_GLOBAL_MOCK_HOOK(TestMultiBlockUploadCallback, TestUploadMultiBlockTestFails); - setup_uploadtoblob_create_mocks(IOTHUB_CREDENTIAL_TYPE_X509_ECC); + setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509_ECC); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); umock_c_reset_all_calls(); From 969f6b75f2f2fd2ffc4282ad70fc2e54a45de87a Mon Sep 17 00:00:00 2001 From: Ewerton Scaboro da Silva Date: Thu, 13 Jul 2023 22:45:23 -0700 Subject: [PATCH 06/27] Update iothub_client_ll_u2b_ut (continued) and other fixes --- iothub_client/inc/internal/blob.h | 1 - .../internal/iothub_client_ll_uploadtoblob.h | 4 +- iothub_client/src/blob.c | 2 - .../src/iothub_client_ll_uploadtoblob.c | 1 + iothub_client/tests/blob_ut/blob_ut.c | 4 - .../iothub_client_ll_u2b_ut.c | 444 ++---------------- 6 files changed, 30 insertions(+), 426 deletions(-) diff --git a/iothub_client/inc/internal/blob.h b/iothub_client/inc/internal/blob.h index 2505ea9c5e..3200841a14 100644 --- a/iothub_client/inc/internal/blob.h +++ b/iothub_client/inc/internal/blob.h @@ -18,7 +18,6 @@ #include "azure_c_shared_utility/strings_types.h" #include "azure_c_shared_utility/httpapiex.h" #include "azure_c_shared_utility/singlylinkedlist.h" -#include "iothub_client_core_ll.h" #include "azure_c_shared_utility/shared_util_options.h" #ifdef __cplusplus diff --git a/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h b/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h index 5b963a599d..0a16b01f6a 100644 --- a/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h +++ b/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h @@ -25,10 +25,10 @@ #ifndef IOTHUB_CLIENT_LL_UPLOADTOBLOB_H #define IOTHUB_CLIENT_LL_UPLOADTOBLOB_H -#include "iothub_client_core_ll.h" +#include "iothub_client_core_common.h" #include "internal/iothub_client_authorization.h" - #include "umock_c/umock_c_prod.h" + #ifdef __cplusplus #include extern "C" diff --git a/iothub_client/src/blob.c b/iothub_client/src/blob.c index ad0c8b8c72..c622d7330d 100644 --- a/iothub_client/src/blob.c +++ b/iothub_client/src/blob.c @@ -6,8 +6,6 @@ #include "azure_c_shared_utility/gballoc.h" #include "internal/blob.h" -#include "internal/iothub_client_ll_uploadtoblob.h" - #include "azure_c_shared_utility/httpapiex.h" #include "azure_c_shared_utility/xlogging.h" #include "azure_c_shared_utility/azure_base64.h" diff --git a/iothub_client/src/iothub_client_ll_uploadtoblob.c b/iothub_client/src/iothub_client_ll_uploadtoblob.c index d7754c22e6..1cae0aa1e5 100644 --- a/iothub_client/src/iothub_client_ll_uploadtoblob.c +++ b/iothub_client/src/iothub_client_ll_uploadtoblob.c @@ -14,6 +14,7 @@ #include "azure_c_shared_utility/httpapiexsas.h" #include "azure_c_shared_utility/shared_util_options.h" #include "azure_c_shared_utility/urlencode.h" +#include "azure_c_shared_utility/crt_abstractions.h" #include "iothub_client_core_ll.h" #include "iothub_client_options.h" diff --git a/iothub_client/tests/blob_ut/blob_ut.c b/iothub_client/tests/blob_ut/blob_ut.c index 0388feca00..3effca8d7a 100644 --- a/iothub_client/tests/blob_ut/blob_ut.c +++ b/iothub_client/tests/blob_ut/blob_ut.c @@ -39,10 +39,6 @@ static void my_gballoc_free(void* s) #include "umock_c/umocktypes_charptr.h" #include "umock_c/umock_c_negative_tests.h" -#define ENABLE_MOCKS -#include "internal/iothub_client_ll_uploadtoblob.h" -#undef ENABLE_MOCKS - /*helps when enums are not matched*/ #ifdef malloc #undef malloc diff --git a/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c b/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c index a03dd53b51..612e595ebf 100644 --- a/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c +++ b/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c @@ -37,7 +37,6 @@ static void* my_gballoc_calloc(size_t nmemb, size_t size) #include "iothub_client_options.h" #define ENABLE_MOCKS - #include "azure_c_shared_utility/agenttime.h" #include "azure_c_shared_utility/httpapiex.h" #include "azure_c_shared_utility/httpapiexsas.h" @@ -45,20 +44,23 @@ static void* my_gballoc_calloc(size_t nmemb, size_t size) #include "azure_c_shared_utility/urlencode.h" #include "azure_c_shared_utility/crt_abstractions.h" #include "azure_c_shared_utility/shared_util_options.h" - +#include "azure_c_shared_utility/gballoc.h" #include "internal/blob.h" #include "internal/iothub_client_authorization.h" - #include "parson.h" -#define BLOCK_SIZE (100*1024*1024) - MOCKABLE_FUNCTION(, JSON_Value*, json_parse_string, const char *, string); MOCKABLE_FUNCTION(, const char*, json_object_get_string, const JSON_Object *, object, const char *, name); MOCKABLE_FUNCTION(, void, json_value_free, JSON_Value *, value); MOCKABLE_FUNCTION(, JSON_Object*, json_value_get_object, const JSON_Value *, value); +#undef ENABLE_MOCKS + +#include "internal/iothub_client_ll_uploadtoblob.h" + +#define BLOCK_SIZE (100*1024*1024) -MOCKABLE_FUNCTION(, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT, TestMultiBlockUploadCallback, IOTHUB_CLIENT_FILE_UPLOAD_RESULT, result, unsigned char const **, data, size_t*, size, void*, context); +// TODO: remove this? +// MOCKABLE_FUNCTION(, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT, TestMultiBlockUploadCallback, IOTHUB_CLIENT_FILE_UPLOAD_RESULT, result, unsigned char const **, data, size_t*, size, void*, context); #define TEST_DEVICE_ID "theidofTheDevice" #define TEST_DEVICE_KEY "theKeyoftheDevice" @@ -76,12 +78,13 @@ MOCKABLE_FUNCTION(, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT, TestMultiBlockUpl #define TEST_HTTPAPIEX_HANDLE (HTTPAPIEX_HANDLE)0x4444 #define TEST_U2B_CONTEXT_HANDLE (IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE)0x4445 +#define TEST_JSON_VALUE (JSON_Value*)0x4446 + static const char* const testUploadtrustedCertificates = "some certificates"; static const char* const TEST_SAS_TOKEN = "test_sas_token"; static const char* const TEST_PRIVATE = "test_private"; static const char* const TEST_CERT = "test_cert"; - static const unsigned char* TEST_SOURCE = (const unsigned char*)0x3; static const size_t TEST_SOURCE_LENGTH = 3; static const char* const TEST_DESTINATION_FILENAME = "text.txt"; @@ -222,17 +225,6 @@ static void my_HTTPAPIEX_SAS_Destroy(HTTPAPIEX_SAS_HANDLE handle) my_gballoc_free(handle); } -static JSON_Value * my_json_parse_string(const char *string) -{ - (void)string; - return (JSON_Value *)my_gballoc_malloc(1); -} - -static void my_json_value_free(JSON_Value *value) -{ - my_gballoc_free(value); -} - static HTTPAPIEX_RESULT my_HTTPAPIEX_ExecuteRequest(HTTPAPIEX_HANDLE handle, HTTPAPI_REQUEST_TYPE requestType, const char* relativePath, HTTP_HEADERS_HANDLE requestHttpHeadersHandle, BUFFER_HANDLE requestContent, unsigned int* statusCode, HTTP_HEADERS_HANDLE responseHttpHeadersHandle, BUFFER_HANDLE responseContent) @@ -356,12 +348,6 @@ static IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT FileUpload_GetData_Callback(IOT return IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_OK; } -#include "azure_c_shared_utility/gballoc.h" - -#undef ENABLE_MOCKS - -#include "internal/iothub_client_ll_uploadtoblob.h" - TEST_DEFINE_ENUM_TYPE (HTTPAPI_RESULT, HTTPAPI_RESULT_VALUES); IMPLEMENT_UMOCK_C_ENUM_TYPE (HTTPAPI_RESULT, HTTPAPI_RESULT_VALUES); TEST_DEFINE_ENUM_TYPE (HTTPAPIEX_RESULT, HTTPAPIEX_RESULT_VALUES); @@ -549,6 +535,8 @@ TEST_SUITE_INITIALIZE(TestClassInitialize) REGISTER_UMOCK_ALIAS_TYPE(const size_t, size_t); REGISTER_UMOCK_ALIAS_TYPE(IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK, void*); REGISTER_UMOCK_ALIAS_TYPE(IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, void*); + REGISTER_UMOCK_ALIAS_TYPE(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, void*); + REGISTER_UMOCK_ALIAS_TYPE(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, void*); REGISTER_UMOCK_ALIAS_TYPE(IOTHUB_AUTHORIZATION_HANDLE, void*); REGISTER_GLOBAL_MOCK_HOOK(gballoc_malloc, my_gballoc_malloc); @@ -591,11 +579,9 @@ TEST_SUITE_INITIALIZE(TestClassInitialize) REGISTER_GLOBAL_MOCK_HOOK(BUFFER_delete, my_BUFFER_delete); REGISTER_GLOBAL_MOCK_HOOK(BUFFER_build, my_BUFFER_build); REGISTER_GLOBAL_MOCK_FAIL_RETURN(BUFFER_build, 1); - - REGISTER_GLOBAL_MOCK_HOOK(json_parse_string, my_json_parse_string); + REGISTER_GLOBAL_MOCK_RETURNS(json_parse_string, TEST_JSON_VALUE, NULL); REGISTER_GLOBAL_MOCK_RETURN(json_value_get_object, (JSON_Object*)1); REGISTER_GLOBAL_MOCK_RETURN(json_object_get_string, "a"); - REGISTER_GLOBAL_MOCK_HOOK(json_value_free, my_json_value_free); REGISTER_GLOBAL_MOCK_RETURN(IoTHubClient_Auth_Get_Credential_Type, IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN); REGISTER_GLOBAL_MOCK_FAIL_RETURN(IoTHubClient_Auth_Get_Credential_Type, IOTHUB_CREDENTIAL_TYPE_UNKNOWN); @@ -835,350 +821,15 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks_NULL_callback_fa { //arrange umock_c_reset_all_calls(); + setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); //act IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(TEST_U2B_CONTEXT_HANDLE, NULL, &blobUploadContext); //assert - ASSERT_ARE_NOT_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); - ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); - - //cleanup - IoTHubClient_LL_UploadToBlob_Destroy(h); -} - -TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks_succeeds) -{ - //arrange - HTTP_PROXY_OPTIONS proxy_options = { 0 }; - proxy_options.host_address = "127.0.0.1"; - proxy_options.port = 8888; - - IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); - (void)IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_HTTP_PROXY, &proxy_options); - umock_c_reset_all_calls(); - - setup_upload_blocks_mocks(IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN, true, false, false, BLOB_OK, false, false); - - //act - IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_Impl(h, TEST_DESTINATION_FILENAME, TEST_SOURCE, TEST_SOURCE_LENGTH); - - //assert - (void)result; - //ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); - ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); - - //cleanup - IoTHubClient_LL_UploadToBlob_Destroy(h); -} - -TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Impl_with_timeout_succeeds) -{ - //arrange - size_t timeout = 500; - - IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); - (void)IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_BLOB_UPLOAD_TIMEOUT_SECS, &timeout); - umock_c_reset_all_calls(); - - setup_upload_blocks_mocks(IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN, false, true, false, BLOB_OK, false, false); - - //act - IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_Impl(h, TEST_DESTINATION_FILENAME, TEST_SOURCE, TEST_SOURCE_LENGTH); - - //assert - ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); - ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); - - //cleanup - IoTHubClient_LL_UploadToBlob_Destroy(h); -} - -TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Impl_succeeds) -{ - //arrange - IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); - (void)IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_TRUSTED_CERT, TEST_CERT); - umock_c_reset_all_calls(); - - setup_upload_blocks_mocks(IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN, false, false, true, BLOB_OK, false, false); - - //act - IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_Impl(h, TEST_DESTINATION_FILENAME, TEST_SOURCE, TEST_SOURCE_LENGTH); - - //assert - ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); - ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); - - //cleanup - IoTHubClient_LL_UploadToBlob_Destroy(h); -} - -TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Impl_device_key_succeeds) -{ - //arrange - setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY); - IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); - umock_c_reset_all_calls(); - - setup_upload_blocks_mocks(IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY, false, false, false, BLOB_OK, false, false); - - //act - IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_Impl(h, TEST_DESTINATION_FILENAME, TEST_SOURCE, TEST_SOURCE_LENGTH); - - //assert - ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); - ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); - - //cleanup - IoTHubClient_LL_UploadToBlob_Destroy(h); -} - -TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Impl_x509_succeeds) -{ - //arrange - - setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509_ECC); - IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); - umock_c_reset_all_calls(); - - setup_upload_blocks_mocks(IOTHUB_CREDENTIAL_TYPE_X509, false, false, false, BLOB_OK, false, false); - - //act - IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_Impl(h, TEST_DESTINATION_FILENAME, TEST_SOURCE, TEST_SOURCE_LENGTH); - - //assert - ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); - ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); - - //cleanup - IoTHubClient_LL_UploadToBlob_Destroy(h); -} - -TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Impl_x509_with_tls_renegotiation_set_false_succeeds) -{ - //arrange - - setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509_ECC); - IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); - bool set_tls_renegotiaton = false; - ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_BLOB_UPLOAD_TLS_RENEGOTIATION, &set_tls_renegotiaton)); - - umock_c_reset_all_calls(); - - setup_upload_blocks_mocks(IOTHUB_CREDENTIAL_TYPE_X509, false, false, false, BLOB_OK, false, false); - - //act - IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_Impl(h, TEST_DESTINATION_FILENAME, TEST_SOURCE, TEST_SOURCE_LENGTH); - - //assert - ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); - ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); - - //cleanup - IoTHubClient_LL_UploadToBlob_Destroy(h); -} - - -TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Impl_x509_with_tls_renegotiation_set_true_succeeds) -{ - //arrange - - setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509_ECC); - IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); - bool set_tls_renegotiaton = true; - ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_BLOB_UPLOAD_TLS_RENEGOTIATION, &set_tls_renegotiaton)); - - umock_c_reset_all_calls(); - - setup_upload_blocks_mocks(IOTHUB_CREDENTIAL_TYPE_X509, false, false, false, BLOB_OK, false, true); - - //act - IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_Impl(h, TEST_DESTINATION_FILENAME, TEST_SOURCE, TEST_SOURCE_LENGTH); - - //assert - ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); - ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); - - //cleanup - IoTHubClient_LL_UploadToBlob_Destroy(h); -} - - -TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Impl_device_auth_succeeds) -{ - //arrange - setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_DEVICE_AUTH); - IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); - umock_c_reset_all_calls(); - - setup_upload_blocks_mocks(IOTHUB_CREDENTIAL_TYPE_DEVICE_AUTH, false, false, false, BLOB_OK, false, false); - - //act - IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_Impl(h, TEST_DESTINATION_FILENAME, TEST_SOURCE, TEST_SOURCE_LENGTH); - - //assert - ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); - ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); - - //cleanup - IoTHubClient_LL_UploadToBlob_Destroy(h); -} - -TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Impl_fails) -{ - //arrange - ASSERT_ARE_EQUAL(int, 0, umock_c_negative_tests_init()); - - IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); - umock_c_reset_all_calls(); - - setup_upload_blocks_mocks(IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN, false, false, false, BLOB_OK, false, false); - - umock_c_negative_tests_snapshot(); - - //act - size_t count = umock_c_negative_tests_call_count(); - for (size_t index = 0; index < count; index++) - { - if (umock_c_negative_tests_can_call_fail(index)) - { - umock_c_negative_tests_reset(); - umock_c_negative_tests_fail_call(index); - - IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_Impl(h, TEST_DESTINATION_FILENAME, TEST_SOURCE, TEST_SOURCE_LENGTH); - - //assert - ASSERT_ARE_NOT_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result, "IoTHubClient_LL_UploadToBlob_Impl failure in test %lu/%lu", (unsigned long)index, (unsigned long)count); - } - } - - //cleanup - IoTHubClient_LL_UploadToBlob_Destroy(h); - umock_c_negative_tests_deinit(); -} - -TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Impl_dev_key_fails) -{ - //arrange - ASSERT_ARE_EQUAL(int, 0, umock_c_negative_tests_init()); - - setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY); - IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); - umock_c_reset_all_calls(); - - setup_upload_blocks_mocks(IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY, false, false, false, BLOB_OK, false, false); - - umock_c_negative_tests_snapshot(); - - //act - size_t count = umock_c_negative_tests_call_count(); - for (size_t index = 0; index < count; index++) - { - if (umock_c_negative_tests_can_call_fail(index)) - { - umock_c_negative_tests_reset(); - umock_c_negative_tests_fail_call(index); - - IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_Impl(h, TEST_DESTINATION_FILENAME, TEST_SOURCE, TEST_SOURCE_LENGTH); - - //assert - ASSERT_ARE_NOT_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result, "IoTHubClient_LL_UploadToBlob_Impl failure in test %lu/%lu", (unsigned long)index, (unsigned long)count); - } - } - - //cleanup - IoTHubClient_LL_UploadToBlob_Destroy(h); - umock_c_negative_tests_deinit(); -} - -TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Impl_dev_auth_fails) -{ - //arrange - ASSERT_ARE_EQUAL(int, 0, umock_c_negative_tests_init()); - - setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_DEVICE_AUTH); - IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); - umock_c_reset_all_calls(); - - setup_upload_blocks_mocks(IOTHUB_CREDENTIAL_TYPE_DEVICE_AUTH, false, false, false, BLOB_OK, false, false); - - umock_c_negative_tests_snapshot(); - - //act - size_t count = umock_c_negative_tests_call_count(); - for (size_t index = 0; index < count; index++) - { - if (umock_c_negative_tests_can_call_fail(index)) - { - umock_c_negative_tests_reset(); - umock_c_negative_tests_fail_call(index); - - IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_Impl(h, TEST_DESTINATION_FILENAME, TEST_SOURCE, TEST_SOURCE_LENGTH); - - //assert - ASSERT_ARE_NOT_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result, "IoTHubClient_LL_UploadToBlob_Impl failure in test %lu/%lu", (unsigned long)index, (unsigned long)count); - } - } - - //cleanup - IoTHubClient_LL_UploadToBlob_Destroy(h); - umock_c_negative_tests_deinit(); -} - -TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Impl_blob_aborted_succeeds) -{ - //arrange - IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); - umock_c_reset_all_calls(); - - setup_upload_blocks_mocks(IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN, false, false, false, BLOB_ABORTED, false, false); - - //act - IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_Impl(h, TEST_DESTINATION_FILENAME, TEST_SOURCE, TEST_SOURCE_LENGTH); - - //assert - ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); - ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); - - //cleanup - IoTHubClient_LL_UploadToBlob_Destroy(h); -} - -TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Impl_blob_error_fails) -{ - //arrange - IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); - umock_c_reset_all_calls(); - - setup_upload_blocks_mocks(IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN, false, false, false, BLOB_ERROR, false, false); - - //act - IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_Impl(h, TEST_DESTINATION_FILENAME, TEST_SOURCE, TEST_SOURCE_LENGTH); - - //assert - ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_ERROR, result); - ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); - - //cleanup - IoTHubClient_LL_UploadToBlob_Destroy(h); -} - -TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Impl_null_response_succeeds) -{ - //arrange - IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); - umock_c_reset_all_calls(); - - setup_upload_blocks_mocks(IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN, false, false, false, BLOB_OK, true, false); - - //act - IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_Impl(h, TEST_DESTINATION_FILENAME, TEST_SOURCE, TEST_SOURCE_LENGTH); - - //assert - ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_NOT_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); //cleanup IoTHubClient_LL_UploadToBlob_Destroy(h); @@ -1226,6 +877,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_x509_cert_succeeds) umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, TEST_CERT)); + STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); // Within mallocAndStrcpy_s hook. //act IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_X509_CERT, TEST_CERT); @@ -1264,10 +916,12 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_openssl_engine_type_succeed //arrange setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); + umock_c_reset_all_calls(); + STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, engine)); + STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); // Within mallocAndStrcpy_s hook. //act - STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, engine)); IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_OPENSSL_ENGINE, engine); //assert @@ -1283,11 +937,12 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_Network_Interface) //arrange setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); - umock_c_reset_all_calls(); - + umock_c_reset_all_calls(); const char* networkInterface = "eth0"; STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, networkInterface)); + STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); // Within mallocAndStrcpy_s hook. + //act IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_NETWORK_INTERFACE_UPLOAD_TO_BLOB, networkInterface); @@ -1308,6 +963,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_x509_cert_twice_succeeds) umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, TEST_CERT)); + STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); // Within mallocAndStrcpy_s hook. STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); //act @@ -1326,9 +982,10 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_x509_key_succeeds) //arrange setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); - umock_c_reset_all_calls(); + umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, TEST_PRIVATE)); + STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); // Within mallocAndStrcpy_s hook. //act IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_X509_PRIVATE_KEY, TEST_PRIVATE); @@ -1346,9 +1003,10 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_x509_trusted_cert_succeeds) //arrange setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); - umock_c_reset_all_calls(); + umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, TEST_CERT)); + STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); // Within mallocAndStrcpy_s hook. //act IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_TRUSTED_CERT, TEST_CERT); @@ -1418,52 +1076,4 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_tls_renegotiation_succeeds) IoTHubClient_LL_UploadToBlob_Destroy(h); } -// Test that when calling IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl, the final callback to the application indicating success or failure -// is invoked. We don't test the individual per-upload calls in this UT because that layer is handled in blob_ut. -TEST_FUNCTION(IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl_succeeds) -{ - //arrange - REGISTER_GLOBAL_MOCK_HOOK(TestMultiBlockUploadCallback, TestUploadMultiBlockTestSucceeds); - - setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509_ECC); - IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); - umock_c_reset_all_calls(); - - setup_upload_blocks_mocks(IOTHUB_CREDENTIAL_TYPE_X509, false, false, false, BLOB_OK, false, false); - - //act - IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl(h, TEST_DESTINATION_FILENAME, TestUploadMultiBlockTestSucceeds, uploadCallbackTestContext); - - //assert - ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); - ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); - - //cleanup - IoTHubClient_LL_UploadToBlob_Destroy(h); -} - -// Analogous to IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl_succeeds test, but tests when the Blob layer returns failure that the failure -// makes it to the callback correctly. -TEST_FUNCTION(IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl_fails) -{ - //arrange - REGISTER_GLOBAL_MOCK_HOOK(TestMultiBlockUploadCallback, TestUploadMultiBlockTestFails); - - setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509_ECC); - IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); - umock_c_reset_all_calls(); - - setup_upload_blocks_mocks(IOTHUB_CREDENTIAL_TYPE_X509, false, false, false, BLOB_ERROR, false, false); - - //act - IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl(h, TEST_DESTINATION_FILENAME, TestUploadMultiBlockTestFails, uploadCallbackTestContext); - - //assert - ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_ERROR, result); - ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); - - //cleanup - IoTHubClient_LL_UploadToBlob_Destroy(h); -} - END_TEST_SUITE(iothubclient_ll_uploadtoblob_ut) From 184ced45ffb2c3ff4b3f095dd37e55f8a5f032bf Mon Sep 17 00:00:00 2001 From: Ewerton Scaboro da Silva Date: Fri, 14 Jul 2023 23:34:56 -0700 Subject: [PATCH 07/27] Update iothub_client_ll_u2b_ut (continued 2) --- .../src/iothub_client_ll_uploadtoblob.c | 17 +- .../iothub_client_ll_u2b_ut.c | 487 ++++++++++++++---- 2 files changed, 396 insertions(+), 108 deletions(-) diff --git a/iothub_client/src/iothub_client_ll_uploadtoblob.c b/iothub_client/src/iothub_client_ll_uploadtoblob.c index 1cae0aa1e5..52fe4214ad 100644 --- a/iothub_client/src/iothub_client_ll_uploadtoblob.c +++ b/iothub_client/src/iothub_client_ll_uploadtoblob.c @@ -113,7 +113,8 @@ static int send_http_sas_request(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* uplo } else { - HTTPAPIEX_SAS_HANDLE http_sas_handle = HTTPAPIEX_SAS_Create_From_String(IoTHubClient_Auth_Get_DeviceKey(upload_client->authorization_module), STRING_c_str(uri_resource), EMPTY_STRING); + const char* uriResourceCharPtr = STRING_c_str(uri_resource); + HTTPAPIEX_SAS_HANDLE http_sas_handle = HTTPAPIEX_SAS_Create_From_String(IoTHubClient_Auth_Get_DeviceKey(upload_client->authorization_module), uriResourceCharPtr, EMPTY_STRING); if (http_sas_handle == NULL) { @@ -122,13 +123,13 @@ static int send_http_sas_request(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* uplo } else { - unsigned int statusCode; + unsigned int statusCode = 0; if (HTTPAPIEX_SAS_ExecuteRequest( http_sas_handle, http_api_handle, HTTPAPI_REQUEST_POST, relative_path, request_header, blobBuffer, &statusCode, NULL, response_buff) != HTTPAPIEX_OK) { - LogError("unable to HTTPAPIEX_ExecuteRequest"); + LogError("unable to HTTPAPIEX_SAS_ExecuteRequest"); result = MU_FAILURE; } else if (!IS_HTTP_STATUS_CODE_SUCCESS(statusCode)) @@ -153,7 +154,7 @@ static int send_http_sas_request(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* uplo static int send_http_request(HTTPAPIEX_HANDLE http_api_handle, const char* relative_path, HTTP_HEADERS_HANDLE request_header, BUFFER_HANDLE blobBuffer, BUFFER_HANDLE response_buff) { int result; - unsigned int statusCode; + unsigned int statusCode = 0; if (HTTPAPIEX_ExecuteRequest(http_api_handle, HTTPAPI_REQUEST_POST, relative_path, request_header, blobBuffer, &statusCode, NULL, response_buff) != HTTPAPIEX_OK) { @@ -462,6 +463,7 @@ static HTTPAPIEX_HANDLE createIotHubHttpApiExHandle(IOTHUB_CLIENT_LL_UPLOADTOBLO HTTPAPIEX_Destroy(iotHubHttpApiExHandle); iotHubHttpApiExHandle = NULL; } + // TODO: proxy username and password can be set through SetOption, but are not used (it was the previous behavior as well). Bug? } } @@ -490,8 +492,11 @@ static int IoTHubClient_LL_UploadToBlob_GetBlobCredentialsFromIoTHub( } else { + // Keep STRING_length separate in an separate call to avoid messing up with unit tests. + // For details, see function parameter evaluation order (C99 6.5.2.2p10). + size_t blobNameLength = STRING_length(blobName); BUFFER_HANDLE blobBuffer = BUFFER_create( - (const unsigned char *)STRING_c_str(blobName), STRING_length(blobName)); + (const unsigned char *)STRING_c_str(blobName), blobNameLength); if (blobBuffer == NULL) { @@ -555,7 +560,7 @@ static int IoTHubClient_LL_UploadToBlob_GetBlobCredentialsFromIoTHub( { if (send_http_sas_request(upload_data, iotHubHttpApiExHandle, STRING_c_str(relativePath), iotHubRequestHttpHeaders, blobBuffer, responseContent) != 0) { - LogError("unable to HTTPAPIEX_ExecuteRequest"); + LogError("unable to HTTPAPIEX_SAS_ExecuteRequest"); } else { diff --git a/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c b/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c index 612e595ebf..7f1562000a 100644 --- a/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c +++ b/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c @@ -76,10 +76,11 @@ MOCKABLE_FUNCTION(, JSON_Object*, json_value_get_object, const JSON_Value *, val #define TEST_API_VERSION "?api-version=2016-11-14" #define TEST_IOTHUB_SDK_VERSION "1.11.0" +#define TEST_HTTP_HEADERS_HANDLE (HTTP_HEADERS_HANDLE)0x4443 #define TEST_HTTPAPIEX_HANDLE (HTTPAPIEX_HANDLE)0x4444 -#define TEST_U2B_CONTEXT_HANDLE (IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE)0x4445 -#define TEST_JSON_VALUE (JSON_Value*)0x4446 - +#define TEST_HTTPAPIEX_SAS_HANDLE (HTTPAPIEX_SAS_HANDLE)0x4445 +#define TEST_U2B_CONTEXT_HANDLE (IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE)0x4446 +#define TEST_JSON_VALUE (JSON_Value*)0x4447 static const char* const testUploadtrustedCertificates = "some certificates"; static const char* const TEST_SAS_TOKEN = "test_sas_token"; @@ -88,6 +89,7 @@ static const char* const TEST_CERT = "test_cert"; static const unsigned char* TEST_SOURCE = (const unsigned char*)0x3; static const size_t TEST_SOURCE_LENGTH = 3; static const char* const TEST_DESTINATION_FILENAME = "text.txt"; +static const char* const TEST_BLOB_NAME_CHAR_PTR = "{ \"blobName\": \"text.txt\" }"; #ifdef __cplusplus extern "C" @@ -158,16 +160,6 @@ static STRING_HANDLE my_URL_EncodeString(const char* textEncode) return (STRING_HANDLE)my_gballoc_malloc(1); } -static HTTP_HEADERS_HANDLE my_HTTPHeaders_Alloc(void) -{ - return (HTTP_HEADERS_HANDLE)my_gballoc_malloc(1); -} - -static void my_HTTPHeaders_Free(HTTP_HEADERS_HANDLE h) -{ - my_gballoc_free(h); -} - static int my_BUFFER_build(BUFFER_HANDLE handle, const unsigned char* source, size_t size) { (void)handle; @@ -193,73 +185,6 @@ static void my_BUFFER_delete(BUFFER_HANDLE handle) my_gballoc_free(handle); } -static HTTPAPIEX_HANDLE my_HTTPAPIEX_Create(const char* hostName) -{ - (void)hostName; - return (HTTPAPIEX_HANDLE)my_gballoc_malloc(1); -} - -static void my_HTTPAPIEX_Destroy(HTTPAPIEX_HANDLE handle) -{ - my_gballoc_free(handle); -} - -static HTTPAPIEX_SAS_HANDLE my_HTTPAPIEX_SAS_Create(STRING_HANDLE key, STRING_HANDLE uriResource, STRING_HANDLE keyName) -{ - (void)key; - (void)uriResource; - (void)keyName; - return (HTTPAPIEX_SAS_HANDLE)my_gballoc_malloc(1); -} - -static HTTPAPIEX_SAS_HANDLE my_HTTPAPIEX_SAS_Create_From_String(const char* key, const char* uriResource, const char* keyName) -{ - (void)key; - (void)uriResource; - (void)keyName; - return (HTTPAPIEX_SAS_HANDLE)my_gballoc_malloc(1); -} - -static void my_HTTPAPIEX_SAS_Destroy(HTTPAPIEX_SAS_HANDLE handle) -{ - my_gballoc_free(handle); -} - -static HTTPAPIEX_RESULT my_HTTPAPIEX_ExecuteRequest(HTTPAPIEX_HANDLE handle, HTTPAPI_REQUEST_TYPE requestType, const char* relativePath, - HTTP_HEADERS_HANDLE requestHttpHeadersHandle, BUFFER_HANDLE requestContent, unsigned int* statusCode, - HTTP_HEADERS_HANDLE responseHttpHeadersHandle, BUFFER_HANDLE responseContent) -{ - (void)handle; - (void)requestType; - (void)relativePath; - (void)requestHttpHeadersHandle; - (void)requestContent; - (void)responseHttpHeadersHandle; - (void)responseContent; - if (statusCode != NULL) - { - *statusCode = 200; /*success*/ - } - return HTTPAPIEX_OK; -} - -static HTTPAPIEX_RESULT my_HTTPAPIEX_SAS_ExecuteRequest(HTTPAPIEX_SAS_HANDLE sasHandle, HTTPAPIEX_HANDLE handle, HTTPAPI_REQUEST_TYPE requestType, const char* relativePath, HTTP_HEADERS_HANDLE requestHttpHeadersHandle, BUFFER_HANDLE requestContent, unsigned int* statusCode, HTTP_HEADERS_HANDLE responseHeadersHandle, BUFFER_HANDLE responseContent) -{ - (void)sasHandle; - (void)handle; - (void)requestType; - (void)relativePath; - (void)requestHttpHeadersHandle; - (void)requestContent; - (void)responseHeadersHandle; - (void)responseContent; - if (statusCode != NULL) - { - *statusCode = 200;/*success*/ - } - return HTTPAPIEX_OK; -} - static int my_mallocAndStrcpy_s(char** destination, const char* source) { size_t l = strlen(source); @@ -498,6 +423,200 @@ static void setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TY } } + +static void setCreateIotHubHttpApiExHandleExpectedCalls( + IOTHUB_CREDENTIAL_TYPE credentialType, + size_t blobUploadTimeoutMillisecs, + bool curlEnableVerboseLogging, + const char* networkInterface, + bool useTlsRenegotiation, + int x509privatekeyType, + const char* openSslEngine, + const char* trustedCertificates, + HTTP_PROXY_OPTIONS* proxyOptions) +{ + STRICT_EXPECTED_CALL(HTTPAPIEX_Create(IGNORED_PTR_ARG)); + + if (blobUploadTimeoutMillisecs != 0) + { + STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(TEST_HTTPAPIEX_HANDLE, OPTION_HTTP_TIMEOUT, IGNORED_PTR_ARG)); + } + + if (curlEnableVerboseLogging) + { + STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(TEST_HTTPAPIEX_HANDLE, OPTION_CURL_VERBOSE, IGNORED_PTR_ARG)) + .CallCannotFail(); + } + + if (networkInterface != NULL) + { + STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(TEST_HTTPAPIEX_HANDLE, OPTION_CURL_INTERFACE, IGNORED_PTR_ARG)); + } + + if (credentialType == IOTHUB_CREDENTIAL_TYPE_X509 || credentialType == IOTHUB_CREDENTIAL_TYPE_X509_ECC) + { + if (useTlsRenegotiation) + { + STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(TEST_HTTPAPIEX_HANDLE, OPTION_SET_TLS_RENEGOTIATION, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(TEST_HTTPAPIEX_HANDLE, OPTION_X509_CERT, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(TEST_HTTPAPIEX_HANDLE, OPTION_X509_PRIVATE_KEY, IGNORED_PTR_ARG)); + + if (x509privatekeyType != 0) + { + STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(TEST_HTTPAPIEX_HANDLE, OPTION_OPENSSL_PRIVATE_KEY_TYPE, IGNORED_PTR_ARG)); + } + + if (openSslEngine != NULL) + { + STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(TEST_HTTPAPIEX_HANDLE, OPTION_OPENSSL_ENGINE, IGNORED_PTR_ARG)); + } + } + } + + if (trustedCertificates != NULL) + { + STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(TEST_HTTPAPIEX_HANDLE, OPTION_TRUSTED_CERT, IGNORED_PTR_ARG)); + } + + if (proxyOptions != NULL) + { + if (proxyOptions->host_address != NULL) + { + STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(TEST_HTTPAPIEX_HANDLE, OPTION_HTTP_PROXY, IGNORED_PTR_ARG)); + } + // TODO: username and password are not used... add to test if this is fixed. + } +} + +static void setCreateIotHubRequestHttpHeadersCalls(IOTHUB_CREDENTIAL_TYPE credentialType) +{ + STRICT_EXPECTED_CALL(HTTPHeaders_Alloc()); + // Content-Type + STRICT_EXPECTED_CALL(HTTPHeaders_AddHeaderNameValuePair(TEST_HTTP_HEADERS_HANDLE, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + // Accept + STRICT_EXPECTED_CALL(HTTPHeaders_AddHeaderNameValuePair(TEST_HTTP_HEADERS_HANDLE, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + // User-Agent + STRICT_EXPECTED_CALL(HTTPHeaders_AddHeaderNameValuePair(TEST_HTTP_HEADERS_HANDLE, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + + if (credentialType == IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY) + { + // Empty Authorization + STRICT_EXPECTED_CALL(HTTPHeaders_AddHeaderNameValuePair(TEST_HTTP_HEADERS_HANDLE, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + } + else if (credentialType == IOTHUB_CREDENTIAL_TYPE_DEVICE_AUTH) + { + STRICT_EXPECTED_CALL(IoTHubClient_Auth_Get_SasToken(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(HTTPHeaders_AddHeaderNameValuePair(TEST_HTTP_HEADERS_HANDLE, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); + } + else if (credentialType == IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN) + { + STRICT_EXPECTED_CALL(HTTPHeaders_AddHeaderNameValuePair(TEST_HTTP_HEADERS_HANDLE, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + } +} + +static void setParseResultFromIoTHubCalls() +{ + STRICT_EXPECTED_CALL(json_parse_string(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(json_value_get_object(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(json_object_get_string(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(json_object_get_string(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(json_object_get_string(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(json_object_get_string(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(json_object_get_string(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(URL_EncodeString(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_new()); + STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) + .CallCannotFail(); + // STRING_sprintf + STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)) // due to mallocAndStrcpy_s mock + .CallCannotFail(); + STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) + .CallCannotFail(); + STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)) // due to mallocAndStrcpy_s mock + .CallCannotFail(); + STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(json_value_free(IGNORED_PTR_ARG)); +} + +static void setIoTHubClient_LL_UploadToBlob_InitializeUploadCalls( + IOTHUB_CREDENTIAL_TYPE credentialType, + size_t blobUploadTimeoutMillisecs, + bool curlEnableVerboseLogging, + const char* networkInterface, + bool useTlsRenegotiation, + int x509privatekeyType, + const char* openSslEngine, + const char* trustedCertificates, + HTTP_PROXY_OPTIONS* proxyOptions) +{ + // STRICT_EXPECTED_CALL(STRING_construct_sprintf(...)); // Not mocked. + // STRICT_EXPECTED_CALL(STRING_construct_sprintf(...)); // Not mocked. + STRICT_EXPECTED_CALL(STRING_length(IGNORED_PTR_ARG)) + .SetReturn(strlen(TEST_BLOB_NAME_CHAR_PTR)) + .CallCannotFail(); + STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) + .SetReturn(TEST_BLOB_NAME_CHAR_PTR) + .CallCannotFail(); + STRICT_EXPECTED_CALL(BUFFER_create(IGNORED_PTR_ARG, strlen(TEST_BLOB_NAME_CHAR_PTR))); + STRICT_EXPECTED_CALL(BUFFER_new()); + + setCreateIotHubHttpApiExHandleExpectedCalls( + credentialType, blobUploadTimeoutMillisecs, curlEnableVerboseLogging, networkInterface, + useTlsRenegotiation, x509privatekeyType, openSslEngine, trustedCertificates, proxyOptions); + setCreateIotHubRequestHttpHeadersCalls(credentialType); + + if (credentialType == IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY) + { + // send_http_sas_request + const unsigned int httpStatusCode = 200; + + STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) + .CallCannotFail(); + STRICT_EXPECTED_CALL(IoTHubClient_Auth_Get_DeviceKey(IGNORED_PTR_ARG)) + .CallCannotFail(); + STRICT_EXPECTED_CALL(HTTPAPIEX_SAS_Create_From_String(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(HTTPAPIEX_SAS_ExecuteRequest( + IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG, + IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)) + .CopyOutArgumentBuffer_statusCode(&httpStatusCode, sizeof(httpStatusCode)); + STRICT_EXPECTED_CALL(HTTPAPIEX_SAS_Destroy(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); + } + else + { + // send_http_request + const unsigned int httpStatusCode = 200; + + STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) + .CallCannotFail(); + STRICT_EXPECTED_CALL(HTTPAPIEX_ExecuteRequest( + IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, + IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)) + .CopyOutArgumentBuffer_statusCode(&httpStatusCode, sizeof(httpStatusCode)); + } + + STRICT_EXPECTED_CALL(BUFFER_u_char(IGNORED_PTR_ARG)) + .CallCannotFail(); + STRICT_EXPECTED_CALL(BUFFER_length(IGNORED_PTR_ARG)) + .CallCannotFail(); + STRICT_EXPECTED_CALL(STRING_from_byte_array(IGNORED_PTR_ARG, IGNORED_NUM_ARG)); + STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) + .CallCannotFail(); + setParseResultFromIoTHubCalls(); + + STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); // responseAsString + STRICT_EXPECTED_CALL(HTTPHeaders_Free(IGNORED_PTR_ARG)); // iotHubRequestHttpHeaders + STRICT_EXPECTED_CALL(HTTPAPIEX_Destroy(IGNORED_PTR_ARG)); // iotHubHttpApiExHandle + STRICT_EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG)); // responseContent + STRICT_EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG)); // blobBuffer + STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); // blobName + STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); // relativePath +} + static void reset_test_data() { memset(&blobUploadContext, 0, sizeof(blobUploadContext)); @@ -557,18 +676,13 @@ TEST_SUITE_INITIALIZE(TestClassInitialize) REGISTER_GLOBAL_MOCK_HOOK(STRING_delete, my_STRING_delete); REGISTER_GLOBAL_MOCK_HOOK(URL_EncodeString, my_URL_EncodeString); - REGISTER_GLOBAL_MOCK_HOOK(HTTPHeaders_Alloc, my_HTTPHeaders_Alloc); - REGISTER_GLOBAL_MOCK_HOOK(HTTPHeaders_Free, my_HTTPHeaders_Free); - - REGISTER_GLOBAL_MOCK_HOOK(HTTPAPIEX_Create, my_HTTPAPIEX_Create); - REGISTER_GLOBAL_MOCK_FAIL_RETURN(HTTPAPIEX_Create, NULL); - REGISTER_GLOBAL_MOCK_HOOK(HTTPAPIEX_Destroy, my_HTTPAPIEX_Destroy); + REGISTER_GLOBAL_MOCK_RETURNS(HTTPHeaders_Alloc, TEST_HTTP_HEADERS_HANDLE, NULL); - REGISTER_GLOBAL_MOCK_HOOK(HTTPAPIEX_SAS_Create, my_HTTPAPIEX_SAS_Create); - REGISTER_GLOBAL_MOCK_FAIL_RETURN(HTTPAPIEX_SAS_ExecuteRequest, HTTPAPIEX_ERROR); - REGISTER_GLOBAL_MOCK_HOOK(HTTPAPIEX_SAS_ExecuteRequest, my_HTTPAPIEX_SAS_ExecuteRequest) - REGISTER_GLOBAL_MOCK_HOOK(HTTPAPIEX_SAS_Destroy, my_HTTPAPIEX_SAS_Destroy); - REGISTER_GLOBAL_MOCK_HOOK(HTTPAPIEX_SAS_Create_From_String, my_HTTPAPIEX_SAS_Create_From_String); + REGISTER_GLOBAL_MOCK_RETURNS(HTTPAPIEX_Create, TEST_HTTPAPIEX_HANDLE, NULL); + REGISTER_GLOBAL_MOCK_RETURNS(HTTPAPIEX_SAS_Create, TEST_HTTPAPIEX_SAS_HANDLE, NULL); + REGISTER_GLOBAL_MOCK_RETURNS(HTTPAPIEX_SAS_Create_From_String, TEST_HTTPAPIEX_SAS_HANDLE, NULL); + REGISTER_GLOBAL_MOCK_RETURNS(HTTPAPIEX_SAS_ExecuteRequest, HTTPAPIEX_OK, HTTPAPIEX_ERROR); + REGISTER_GLOBAL_MOCK_RETURNS(HTTPAPIEX_ExecuteRequest, HTTPAPIEX_OK, HTTPAPIEX_ERROR); REGISTER_GLOBAL_MOCK_HOOK(BUFFER_new, my_BUFFER_new); REGISTER_GLOBAL_MOCK_FAIL_RETURN(BUFFER_new, NULL); @@ -593,17 +707,12 @@ TEST_SUITE_INITIALIZE(TestClassInitialize) REGISTER_GLOBAL_MOCK_RETURN(IoTHubClient_Auth_Get_DeviceId, TEST_DEVICE_ID); REGISTER_GLOBAL_MOCK_FAIL_RETURN(IoTHubClient_Auth_Get_DeviceId, NULL); - REGISTER_GLOBAL_MOCK_RETURN(HTTPHeaders_AddHeaderNameValuePair, HTTP_HEADERS_OK); - REGISTER_GLOBAL_MOCK_FAIL_RETURN(HTTPHeaders_AddHeaderNameValuePair, HTTP_HEADERS_ERROR); + REGISTER_GLOBAL_MOCK_RETURNS(HTTPHeaders_AddHeaderNameValuePair, HTTP_HEADERS_OK, HTTP_HEADERS_ERROR); + REGISTER_GLOBAL_MOCK_RETURNS(HTTPHeaders_ReplaceHeaderNameValuePair, HTTP_HEADERS_OK, HTTP_HEADERS_ERROR); - REGISTER_GLOBAL_MOCK_RETURN(HTTPHeaders_ReplaceHeaderNameValuePair, HTTP_HEADERS_OK); - REGISTER_GLOBAL_MOCK_FAIL_RETURN(HTTPHeaders_ReplaceHeaderNameValuePair, HTTP_HEADERS_ERROR); - REGISTER_GLOBAL_MOCK_HOOK(HTTPAPIEX_ExecuteRequest, my_HTTPAPIEX_ExecuteRequest) - REGISTER_GLOBAL_MOCK_RETURN(HTTPAPIEX_ExecuteRequest, HTTPAPIEX_OK); - - REGISTER_GLOBAL_MOCK_FAIL_RETURN(HTTPAPIEX_ExecuteRequest, HTTPAPIEX_ERROR); - REGISTER_GLOBAL_MOCK_RETURN(HTTPAPIEX_SetOption, HTTPAPIEX_OK); - REGISTER_GLOBAL_MOCK_FAIL_RETURN(HTTPAPIEX_SetOption, HTTPAPIEX_ERROR); + REGISTER_GLOBAL_MOCK_RETURNS(HTTPAPIEX_ExecuteRequest, HTTPAPIEX_OK, HTTPAPIEX_ERROR); + REGISTER_GLOBAL_MOCK_RETURNS(HTTPAPIEX_SAS_ExecuteRequest, HTTPAPIEX_OK, HTTPAPIEX_ERROR); + REGISTER_GLOBAL_MOCK_RETURNS(HTTPAPIEX_SetOption, HTTPAPIEX_OK, HTTPAPIEX_ERROR); REGISTER_GLOBAL_MOCK_RETURNS(Blob_CreateHttpConnection, TEST_HTTPAPIEX_HANDLE, NULL); REGISTER_GLOBAL_MOCK_RETURNS(Blob_PutBlock, BLOB_OK, BLOB_ERROR); @@ -820,10 +929,11 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks_handle_NULL_fail TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks_NULL_callback_fails) { //arrange - umock_c_reset_all_calls(); setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); + umock_c_reset_all_calls(); + //act IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(TEST_U2B_CONTEXT_HANDLE, NULL, &blobUploadContext); @@ -835,6 +945,179 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks_NULL_callback_fa IoTHubClient_LL_UploadToBlob_Destroy(h); } +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_succeeds) +{ + //arrange + char* uploadCorrelationId; + char* azureBlobSasUri; + + IOTHUB_CREDENTIAL_TYPE credentialType = IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN; + size_t blobUploadTimeoutMillisecs = 0; + bool curlEnableVerboseLogging = false; + char* networkInterface = NULL; + bool useTlsRenegotiation = false; + int x509privatekeyType = 1; + char* openSslEngine = "pkcs11"; + char* trustedCertificates = NULL; + HTTP_PROXY_OPTIONS* proxyOptions = NULL; + + setup_IoTHubClient_LL_UploadToBlob_Create_mocks(credentialType); + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); + + umock_c_reset_all_calls(); + setIoTHubClient_LL_UploadToBlob_InitializeUploadCalls( + credentialType, blobUploadTimeoutMillisecs, curlEnableVerboseLogging, networkInterface, + useTlsRenegotiation, x509privatekeyType, openSslEngine, trustedCertificates, proxyOptions); + + //act + IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_InitializeUpload(h, TEST_DESTINATION_FILENAME, &uploadCorrelationId, &azureBlobSasUri); + + //assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); + + //cleanup + IoTHubClient_LL_UploadToBlob_Destroy(h); +} + +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_ALL_OPTIONS_succeeds) +{ + //arrange + char* uploadCorrelationId; + char* azureBlobSasUri; + + IOTHUB_CREDENTIAL_TYPE credentialType = IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN; + size_t blobUploadTimeoutSecs = 5; + bool curlEnableVerboseLogging = true; + const char* networkInterface = "eth0"; + bool useTlsRenegotiation = true; + int x509privatekeyType = 1; + const char* openSslEngine = "pkcs11"; + const char* trustedCertificates = "test cert"; + HTTP_PROXY_OPTIONS proxyOptions; + proxyOptions.host_address = "proxy.address.com"; + proxyOptions.username = "proxyusername"; + proxyOptions.password = "proxypassword"; + + setup_IoTHubClient_LL_UploadToBlob_Create_mocks(credentialType); + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); + (void)IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_BLOB_UPLOAD_TIMEOUT_SECS, &blobUploadTimeoutSecs); + (void)IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_CURL_VERBOSE, &curlEnableVerboseLogging); + (void)IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_BLOB_UPLOAD_TLS_RENEGOTIATION, &useTlsRenegotiation); + (void)IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_OPENSSL_PRIVATE_KEY_TYPE, &x509privatekeyType); + (void)IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_OPENSSL_ENGINE, openSslEngine); + (void)IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_TRUSTED_CERT, trustedCertificates); + (void)IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_NETWORK_INTERFACE_UPLOAD_TO_BLOB, networkInterface); + (void)IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_HTTP_PROXY, &proxyOptions); + + umock_c_reset_all_calls(); + setIoTHubClient_LL_UploadToBlob_InitializeUploadCalls( + credentialType, blobUploadTimeoutSecs, curlEnableVerboseLogging, networkInterface, + useTlsRenegotiation, x509privatekeyType, openSslEngine, trustedCertificates, &proxyOptions); + + //act + IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_InitializeUpload(h, TEST_DESTINATION_FILENAME, &uploadCorrelationId, &azureBlobSasUri); + + //assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); + + //cleanup + IoTHubClient_LL_UploadToBlob_Destroy(h); +} + +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_failure_checks) +{ + //arrange + char* uploadCorrelationId; + char* azureBlobSasUri; + + IOTHUB_CREDENTIAL_TYPE credentialType = IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN; + size_t blobUploadTimeoutSecs = 5; + bool curlEnableVerboseLogging = true; + const char* networkInterface = "eth0"; + bool useTlsRenegotiation = true; + int x509privatekeyType = 1; + const char* openSslEngine = "pkcs11"; + const char* trustedCertificates = "test cert"; + HTTP_PROXY_OPTIONS proxyOptions; + proxyOptions.host_address = "proxy.address.com"; + proxyOptions.username = "proxyusername"; + proxyOptions.password = "proxypassword"; + + setup_IoTHubClient_LL_UploadToBlob_Create_mocks(credentialType); + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); + (void)IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_BLOB_UPLOAD_TIMEOUT_SECS, &blobUploadTimeoutSecs); + (void)IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_CURL_VERBOSE, &curlEnableVerboseLogging); + (void)IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_BLOB_UPLOAD_TLS_RENEGOTIATION, &useTlsRenegotiation); + (void)IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_OPENSSL_PRIVATE_KEY_TYPE, &x509privatekeyType); + (void)IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_OPENSSL_ENGINE, openSslEngine); + (void)IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_TRUSTED_CERT, trustedCertificates); + (void)IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_NETWORK_INTERFACE_UPLOAD_TO_BLOB, networkInterface); + (void)IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_HTTP_PROXY, &proxyOptions); + + ASSERT_ARE_EQUAL(int, 0, umock_c_negative_tests_init()); + umock_c_reset_all_calls(); + setIoTHubClient_LL_UploadToBlob_InitializeUploadCalls( + credentialType, blobUploadTimeoutSecs, curlEnableVerboseLogging, networkInterface, + useTlsRenegotiation, x509privatekeyType, openSslEngine, trustedCertificates, &proxyOptions); + umock_c_negative_tests_snapshot(); + + // act + for (int i = 0; i < umock_c_negative_tests_call_count(); i++) + { + umock_c_negative_tests_reset(); + + if (umock_c_negative_tests_can_call_fail(i)) + { + umock_c_negative_tests_reset(); + umock_c_negative_tests_fail_call(i); + + // arrange + char error_msg[64]; + + umock_c_negative_tests_reset(); + umock_c_negative_tests_fail_call(i); + + // act + IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_InitializeUpload( + h, TEST_DESTINATION_FILENAME, &uploadCorrelationId, &azureBlobSasUri); + + ///assert + sprintf(error_msg, "On failed call %lu (%s)", (unsigned long)i, umockcall_stringify(umock_c_get_last_expected_call())); + ASSERT_ARE_NOT_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result, error_msg); + } + } + + // cleanup + umock_c_negative_tests_deinit(); + IoTHubClient_LL_UploadToBlob_Destroy(h); +} + + + +// TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks_succeeds) +// { +// //arrange +// setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN); +// IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); + + +// IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext = IoTHubClient_LL_UploadToBlob_CreateContext(h, azureBlobSasUri); + +// umock_c_reset_all_calls(); + +// //act +// IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(TEST_U2B_CONTEXT_HANDLE, FileUpload_GetData_Callback, &blobUploadContext); + +// //assert +// ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); +// ASSERT_ARE_NOT_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); + +// //cleanup +// IoTHubClient_LL_UploadToBlob_Destroy(h); +// } + TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_handle_NULL_fails) { bool curlVerbosity = true; From 824652ae19b1835c41b9f74629eab1fdec78c3da Mon Sep 17 00:00:00 2001 From: Ewerton Scaboro da Silva Date: Sat, 15 Jul 2023 23:14:10 -0700 Subject: [PATCH 08/27] Update iothub_client_ll_u2b_ut (continued 3) --- .../internal/iothub_client_ll_uploadtoblob.h | 2 +- .../src/iothub_client_ll_uploadtoblob.c | 19 +- .../iothub_client_ll_u2b_ut.c | 408 ++++++++++++++++-- 3 files changed, 376 insertions(+), 53 deletions(-) diff --git a/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h b/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h index 0a16b01f6a..247a9f7943 100644 --- a/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h +++ b/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h @@ -65,7 +65,7 @@ extern "C" MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, IoTHubClient_LL_UploadToBlob_CreateContext, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, handle, const char*, azureBlobSasUri); MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_PutBlock, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContext, uint32_t, blockNumber, const uint8_t*, dataPtr, size_t, dataSize); MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_PutBlockList, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContext); - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_DestroyContext, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContext); + MOCKABLE_FUNCTION(, void, IoTHubClient_LL_UploadToBlob_DestroyContext, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContext); MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_NotifyCompletion, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, handle, const char*, uploadCorrelationId, bool, isSuccess, int, responseCode, const char*, responseMessage); MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_SetOption, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, handle, const char*, optionName, const void*, value); diff --git a/iothub_client/src/iothub_client_ll_uploadtoblob.c b/iothub_client/src/iothub_client_ll_uploadtoblob.c index 52fe4214ad..980c3c5b18 100644 --- a/iothub_client/src/iothub_client_ll_uploadtoblob.c +++ b/iothub_client/src/iothub_client_ll_uploadtoblob.c @@ -898,7 +898,7 @@ IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_InitializeUpload(IOTHUB_CLIENT { IOTHUB_CLIENT_RESULT result; - if (handle == NULL || destinationFileName == NULL || uploadCorrelationId == NULL) + if (handle == NULL || destinationFileName == NULL || uploadCorrelationId == NULL || azureBlobSasUri == NULL) { LogError("invalid argument detected handle=%p destinationFileName=%p uploadCorrelationId=%p azureBlobSasUri=%p", handle, destinationFileName, uploadCorrelationId, azureBlobSasUri); @@ -969,22 +969,9 @@ IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubClient_LL_UploadToBlob_Create return result; } -IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_DestroyContext(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext) +void IoTHubClient_LL_UploadToBlob_DestroyContext(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext) { - IOTHUB_CLIENT_RESULT result; - - if (uploadContext == NULL) - { - LogError("invalid argument detected uploadContext=%p", uploadContext); - result = IOTHUB_CLIENT_INVALID_ARG; - } - else - { - destroyUploadToBlobContextInstance(uploadContext); - result = IOTHUB_CLIENT_OK; - } - - return result; + destroyUploadToBlobContextInstance(uploadContext); } IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_PutBlock(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext, uint32_t blockNumber, const uint8_t* dataPtr, size_t dataSize) diff --git a/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c b/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c index 7f1562000a..c8517c2ae5 100644 --- a/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c +++ b/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c @@ -41,6 +41,7 @@ static void* my_gballoc_calloc(size_t nmemb, size_t size) #include "azure_c_shared_utility/httpapiex.h" #include "azure_c_shared_utility/httpapiexsas.h" #include "azure_c_shared_utility/strings.h" +#include "azure_c_shared_utility/singlylinkedlist.h" #include "azure_c_shared_utility/urlencode.h" #include "azure_c_shared_utility/crt_abstractions.h" #include "azure_c_shared_utility/shared_util_options.h" @@ -76,20 +77,23 @@ MOCKABLE_FUNCTION(, JSON_Object*, json_value_get_object, const JSON_Value *, val #define TEST_API_VERSION "?api-version=2016-11-14" #define TEST_IOTHUB_SDK_VERSION "1.11.0" -#define TEST_HTTP_HEADERS_HANDLE (HTTP_HEADERS_HANDLE)0x4443 -#define TEST_HTTPAPIEX_HANDLE (HTTPAPIEX_HANDLE)0x4444 -#define TEST_HTTPAPIEX_SAS_HANDLE (HTTPAPIEX_SAS_HANDLE)0x4445 -#define TEST_U2B_CONTEXT_HANDLE (IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE)0x4446 -#define TEST_JSON_VALUE (JSON_Value*)0x4447 +#define TEST_HTTP_HEADERS_HANDLE (HTTP_HEADERS_HANDLE)0x4443 +#define TEST_HTTPAPIEX_HANDLE (HTTPAPIEX_HANDLE)0x4444 +#define TEST_HTTPAPIEX_SAS_HANDLE (HTTPAPIEX_SAS_HANDLE)0x4445 +#define TEST_U2B_CONTEXT_HANDLE (IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE)0x4446 +#define TEST_JSON_VALUE (JSON_Value*)0x4447 +#define TEST_SINGLYLINKEDLIST_HANDLE (SINGLYLINKEDLIST_HANDLE)0x4448 static const char* const testUploadtrustedCertificates = "some certificates"; -static const char* const TEST_SAS_TOKEN = "test_sas_token"; +static const char* const TEST_IOTHUB_SAS_TOKEN = "test_sas_token"; static const char* const TEST_PRIVATE = "test_private"; static const char* const TEST_CERT = "test_cert"; static const unsigned char* TEST_SOURCE = (const unsigned char*)0x3; static const size_t TEST_SOURCE_LENGTH = 3; static const char* const TEST_DESTINATION_FILENAME = "text.txt"; static const char* const TEST_BLOB_NAME_CHAR_PTR = "{ \"blobName\": \"text.txt\" }"; +static const char* const TEST_BLOB_SAS_URI = "https://mystorageaccount.blob.core.windows.net/uploadcontainer01/myDeviceId%2fsubdir%text.txt?sv=2018-03-28&sr=b&sig=BuvkhxiMqrFJDYoS4UCZq%2FMkS4rb47doCPvfdgx1iwM%3D&se=2023-07-16T05%3A31%3A08Z&sp=rw"; +static const char* const TEST_UPLOAD_CORRELATION_ID = "MjAyMzA3MTYwNTQxXzVjMzg5NzMzLTlhZTgtNDVmZC1iNjQ0LTIzZDUzMDc5YzgyMF9zdWJkaXIvaGVsbG9fd29ybGRfY3VzdG9tX21iLnR4dF92ZXIyLjA="; #ifdef __cplusplus extern "C" @@ -199,9 +203,9 @@ static char* my_IoTHubClient_Auth_Get_SasToken(IOTHUB_AUTHORIZATION_HANDLE handl (void)scope; (void)expiry_time_relative_seconds; (void)key_name; - size_t l = strlen(TEST_SAS_TOKEN); + size_t l = strlen(TEST_IOTHUB_SAS_TOKEN); char* result = (char*)my_gballoc_malloc(l+1); - strcpy(result, TEST_SAS_TOKEN); + strcpy(result, TEST_IOTHUB_SAS_TOKEN); return result; } @@ -404,7 +408,7 @@ typedef struct UPLOADTOBLOB_TEST_UT_CONTEXT_TAG static UPLOADTOBLOB_TEST_UT_CONTEXT uploadtoblobTest_Context; -static void setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE cred_type) +static void setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(IOTHUB_CREDENTIAL_TYPE cred_type) { STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); @@ -519,7 +523,8 @@ static void setParseResultFromIoTHubCalls() { STRICT_EXPECTED_CALL(json_parse_string(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(json_value_get_object(IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(json_object_get_string(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(json_object_get_string(IGNORED_PTR_ARG, IGNORED_PTR_ARG)) + .SetReturn(TEST_UPLOAD_CORRELATION_ID); STRICT_EXPECTED_CALL(json_object_get_string(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(json_object_get_string(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(json_object_get_string(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); @@ -533,7 +538,8 @@ static void setParseResultFromIoTHubCalls() STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)) // due to mallocAndStrcpy_s mock .CallCannotFail(); STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) - .CallCannotFail(); + .CallCannotFail() + .SetReturn(TEST_BLOB_SAS_URI); STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)) // due to mallocAndStrcpy_s mock .CallCannotFail(); @@ -542,7 +548,7 @@ static void setParseResultFromIoTHubCalls() STRICT_EXPECTED_CALL(json_value_free(IGNORED_PTR_ARG)); } -static void setIoTHubClient_LL_UploadToBlob_InitializeUploadCalls( +static void setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_InitializeUpload( IOTHUB_CREDENTIAL_TYPE credentialType, size_t blobUploadTimeoutMillisecs, bool curlEnableVerboseLogging, @@ -646,6 +652,7 @@ TEST_SUITE_INITIALIZE(TestClassInitialize) REGISTER_UMOCK_ALIAS_TYPE(BUFFER_HANDLE, void*); REGISTER_UMOCK_ALIAS_TYPE(char **, void*); REGISTER_UMOCK_ALIAS_TYPE(STRING_HANDLE, void*); + REGISTER_UMOCK_ALIAS_TYPE(SINGLYLINKEDLIST_HANDLE, void*); REGISTER_UMOCK_ALIAS_TYPE(HTTP_HEADERS_HANDLE, void*); REGISTER_UMOCK_ALIAS_TYPE(HTTP_HANDLE, void*); REGISTER_UMOCK_ALIAS_TYPE(HTTPAPIEX_HANDLE, void*); @@ -676,6 +683,8 @@ TEST_SUITE_INITIALIZE(TestClassInitialize) REGISTER_GLOBAL_MOCK_HOOK(STRING_delete, my_STRING_delete); REGISTER_GLOBAL_MOCK_HOOK(URL_EncodeString, my_URL_EncodeString); + REGISTER_GLOBAL_MOCK_RETURNS(singlylinkedlist_create, TEST_SINGLYLINKEDLIST_HANDLE, NULL); + REGISTER_GLOBAL_MOCK_RETURNS(HTTPHeaders_Alloc, TEST_HTTP_HEADERS_HANDLE, NULL); REGISTER_GLOBAL_MOCK_RETURNS(HTTPAPIEX_Create, TEST_HTTPAPIEX_HANDLE, NULL); @@ -749,7 +758,7 @@ TEST_FUNCTION_CLEANUP(TestMethodCleanup) TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Create_sas_token_succeeds) { //arrange - setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN); //act IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); @@ -765,7 +774,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Create_sas_token_succeeds) TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Create_x509_succeeds) { //arrange - setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(IOTHUB_CREDENTIAL_TYPE_X509); //act IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); @@ -781,7 +790,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Create_x509_succeeds) TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Create_x509_ecc_succeeds) { //arrange - setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509_ECC); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(IOTHUB_CREDENTIAL_TYPE_X509_ECC); //act IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); @@ -830,7 +839,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Create_fails) int result = umock_c_negative_tests_init(); ASSERT_ARE_EQUAL(int, 0, result); - setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY); umock_c_negative_tests_snapshot(); @@ -929,7 +938,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks_handle_NULL_fail TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks_NULL_callback_fails) { //arrange - setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); umock_c_reset_all_calls(); @@ -945,7 +954,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks_NULL_callback_fa IoTHubClient_LL_UploadToBlob_Destroy(h); } -TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_succeeds) +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_SAS_succeeds) { //arrange char* uploadCorrelationId; @@ -961,11 +970,11 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_succeeds) char* trustedCertificates = NULL; HTTP_PROXY_OPTIONS* proxyOptions = NULL; - setup_IoTHubClient_LL_UploadToBlob_Create_mocks(credentialType); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(credentialType); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); umock_c_reset_all_calls(); - setIoTHubClient_LL_UploadToBlob_InitializeUploadCalls( + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_InitializeUpload( credentialType, blobUploadTimeoutMillisecs, curlEnableVerboseLogging, networkInterface, useTlsRenegotiation, x509privatekeyType, openSslEngine, trustedCertificates, proxyOptions); @@ -980,7 +989,42 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_succeeds) IoTHubClient_LL_UploadToBlob_Destroy(h); } -TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_ALL_OPTIONS_succeeds) +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_X509_succeeds) +{ + //arrange + char* uploadCorrelationId; + char* azureBlobSasUri; + + IOTHUB_CREDENTIAL_TYPE credentialType = IOTHUB_CREDENTIAL_TYPE_X509; + size_t blobUploadTimeoutMillisecs = 0; + bool curlEnableVerboseLogging = false; + char* networkInterface = NULL; + bool useTlsRenegotiation = false; + int x509privatekeyType = 1; + char* openSslEngine = "pkcs11"; + char* trustedCertificates = NULL; + HTTP_PROXY_OPTIONS* proxyOptions = NULL; + + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(credentialType); + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); + + umock_c_reset_all_calls(); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_InitializeUpload( + credentialType, blobUploadTimeoutMillisecs, curlEnableVerboseLogging, networkInterface, + useTlsRenegotiation, x509privatekeyType, openSslEngine, trustedCertificates, proxyOptions); + + //act + IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_InitializeUpload(h, TEST_DESTINATION_FILENAME, &uploadCorrelationId, &azureBlobSasUri); + + //assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); + + //cleanup + IoTHubClient_LL_UploadToBlob_Destroy(h); +} + +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_SAS_ALL_OPTIONS_succeeds) { //arrange char* uploadCorrelationId; @@ -999,7 +1043,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_ALL_OPTIONS_succeeds proxyOptions.username = "proxyusername"; proxyOptions.password = "proxypassword"; - setup_IoTHubClient_LL_UploadToBlob_Create_mocks(credentialType); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(credentialType); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); (void)IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_BLOB_UPLOAD_TIMEOUT_SECS, &blobUploadTimeoutSecs); (void)IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_CURL_VERBOSE, &curlEnableVerboseLogging); @@ -1011,7 +1055,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_ALL_OPTIONS_succeeds (void)IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_HTTP_PROXY, &proxyOptions); umock_c_reset_all_calls(); - setIoTHubClient_LL_UploadToBlob_InitializeUploadCalls( + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_InitializeUpload( credentialType, blobUploadTimeoutSecs, curlEnableVerboseLogging, networkInterface, useTlsRenegotiation, x509privatekeyType, openSslEngine, trustedCertificates, &proxyOptions); @@ -1026,7 +1070,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_ALL_OPTIONS_succeeds IoTHubClient_LL_UploadToBlob_Destroy(h); } -TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_failure_checks) +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_SAS_failure_checks) { //arrange char* uploadCorrelationId; @@ -1045,7 +1089,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_failure_checks) proxyOptions.username = "proxyusername"; proxyOptions.password = "proxypassword"; - setup_IoTHubClient_LL_UploadToBlob_Create_mocks(credentialType); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(credentialType); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); (void)IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_BLOB_UPLOAD_TIMEOUT_SECS, &blobUploadTimeoutSecs); (void)IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_CURL_VERBOSE, &curlEnableVerboseLogging); @@ -1058,7 +1102,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_failure_checks) ASSERT_ARE_EQUAL(int, 0, umock_c_negative_tests_init()); umock_c_reset_all_calls(); - setIoTHubClient_LL_UploadToBlob_InitializeUploadCalls( + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_InitializeUpload( credentialType, blobUploadTimeoutSecs, curlEnableVerboseLogging, networkInterface, useTlsRenegotiation, x509privatekeyType, openSslEngine, trustedCertificates, &proxyOptions); umock_c_negative_tests_snapshot(); @@ -1094,12 +1138,304 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_failure_checks) IoTHubClient_LL_UploadToBlob_Destroy(h); } +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_NULL_handle_fails) +{ + //arrange + char* uploadCorrelationId; + char* azureBlobSasUri; + IOTHUB_CREDENTIAL_TYPE credentialType = IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN; + + umock_c_reset_all_calls(); + + //act + IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_InitializeUpload(NULL, TEST_DESTINATION_FILENAME, &uploadCorrelationId, &azureBlobSasUri); + + //assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_NOT_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); + + //cleanup +} + +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_NULL_destination_file_fails) +{ + //arrange + char* uploadCorrelationId; + char* azureBlobSasUri; + IOTHUB_CREDENTIAL_TYPE credentialType = IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN; + + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(credentialType); + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); + + umock_c_reset_all_calls(); + + //act + IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_InitializeUpload(h, NULL, &uploadCorrelationId, &azureBlobSasUri); + + //assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_NOT_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); + + //cleanup + IoTHubClient_LL_UploadToBlob_Destroy(h); +} + +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_NULL_correlation_arg_fails) +{ + //arrange + char* azureBlobSasUri; + IOTHUB_CREDENTIAL_TYPE credentialType = IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN; + + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(credentialType); + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); + + umock_c_reset_all_calls(); + + //act + IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_InitializeUpload(h, TEST_DESTINATION_FILENAME, NULL, &azureBlobSasUri); + + //assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_NOT_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); + + //cleanup + IoTHubClient_LL_UploadToBlob_Destroy(h); +} + +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_NULL_SAS_URI_arg_fails) +{ + //arrange + char* uploadCorrelationId; + IOTHUB_CREDENTIAL_TYPE credentialType = IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN; + + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(credentialType); + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); + + umock_c_reset_all_calls(); + + //act + IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_InitializeUpload(h, TEST_DESTINATION_FILENAME, &uploadCorrelationId, NULL); + + //assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_NOT_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); + + //cleanup + IoTHubClient_LL_UploadToBlob_Destroy(h); +} + + +static void setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_CreateContext() +{ + // createUploadToBlobContextInstance + STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); + STRICT_EXPECTED_CALL(singlylinkedlist_create()); + // parseAzureBlobSasUri + STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); + STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); + STRICT_EXPECTED_CALL(Blob_CreateHttpConnection(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG)); +} + +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_CreateContext_succeeds) +{ + //arrange + char* uploadCorrelationId; + char* azureBlobSasUri; + + IOTHUB_CREDENTIAL_TYPE credentialType = IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN; + size_t blobUploadTimeoutMillisecs = 0; + bool curlEnableVerboseLogging = false; + char* networkInterface = NULL; + bool useTlsRenegotiation = false; + int x509privatekeyType = 1; + char* openSslEngine = "pkcs11"; + char* trustedCertificates = NULL; + HTTP_PROXY_OPTIONS* proxyOptions = NULL; + + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(credentialType); + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); + + umock_c_reset_all_calls(); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_InitializeUpload( + credentialType, blobUploadTimeoutMillisecs, curlEnableVerboseLogging, networkInterface, + useTlsRenegotiation, x509privatekeyType, openSslEngine, trustedCertificates, proxyOptions); + IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_InitializeUpload(h, TEST_DESTINATION_FILENAME, &uploadCorrelationId, &azureBlobSasUri); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); + + umock_c_reset_all_calls(); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_CreateContext(); + + //act + IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext = IoTHubClient_LL_UploadToBlob_CreateContext(h, azureBlobSasUri); + + //assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_IS_NOT_NULL(uploadContext); + + //cleanup + IoTHubClient_LL_UploadToBlob_DestroyContext(uploadContext); + IoTHubClient_LL_UploadToBlob_Destroy(h); +} + +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_CreateContext_failure_checks) +{ + //arrange + char* uploadCorrelationId; + char* azureBlobSasUri; + + IOTHUB_CREDENTIAL_TYPE credentialType = IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN; + size_t blobUploadTimeoutMillisecs = 0; + bool curlEnableVerboseLogging = false; + char* networkInterface = NULL; + bool useTlsRenegotiation = false; + int x509privatekeyType = 0; + char* openSslEngine = NULL; + char* trustedCertificates = NULL; + HTTP_PROXY_OPTIONS* proxyOptions = NULL; + + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(credentialType); + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); + + umock_c_reset_all_calls(); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_InitializeUpload( + credentialType, blobUploadTimeoutMillisecs, curlEnableVerboseLogging, networkInterface, + useTlsRenegotiation, x509privatekeyType, openSslEngine, trustedCertificates, proxyOptions); + IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_InitializeUpload(h, TEST_DESTINATION_FILENAME, &uploadCorrelationId, &azureBlobSasUri); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); + + ASSERT_ARE_EQUAL(int, 0, umock_c_negative_tests_init()); + umock_c_reset_all_calls(); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_CreateContext(); + umock_c_negative_tests_snapshot(); + + // act + for (int i = 0; i < umock_c_negative_tests_call_count(); i++) + { + umock_c_negative_tests_reset(); + + if (umock_c_negative_tests_can_call_fail(i)) + { + umock_c_negative_tests_reset(); + umock_c_negative_tests_fail_call(i); + + // arrange + char error_msg[64]; + + umock_c_negative_tests_reset(); + umock_c_negative_tests_fail_call(i); + + // act + IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext = + IoTHubClient_LL_UploadToBlob_CreateContext(h, azureBlobSasUri); + + ///assert + sprintf(error_msg, "On failed call %lu (%s)", (unsigned long)i, umockcall_stringify(umock_c_get_last_expected_call())); + ASSERT_IS_NULL(uploadContext, error_msg); + } + } + + //cleanup + umock_c_negative_tests_deinit(); + IoTHubClient_LL_UploadToBlob_Destroy(h); +} + +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_CreateContext_NULL_handle_fails) +{ + //arrange + umock_c_reset_all_calls(); + + //act + IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext = IoTHubClient_LL_UploadToBlob_CreateContext(NULL, TEST_BLOB_SAS_URI); + + //assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_IS_NULL(uploadContext); + + //cleanup +} + +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_CreateContext_NULL_SAS_URI_fails) +{ + //arrange + umock_c_reset_all_calls(); + + //act + IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext = + IoTHubClient_LL_UploadToBlob_CreateContext((IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE)0x4567, NULL); + + //assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_IS_NULL(uploadContext); + + //cleanup +} + +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_DestroyContext_succeeds) +{ + //arrange + char* uploadCorrelationId; + char* azureBlobSasUri; + + IOTHUB_CREDENTIAL_TYPE credentialType = IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN; + size_t blobUploadTimeoutMillisecs = 0; + bool curlEnableVerboseLogging = false; + char* networkInterface = NULL; + bool useTlsRenegotiation = false; + int x509privatekeyType = 1; + char* openSslEngine = "pkcs11"; + char* trustedCertificates = NULL; + HTTP_PROXY_OPTIONS* proxyOptions = NULL; + + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(credentialType); + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); + + umock_c_reset_all_calls(); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_InitializeUpload( + credentialType, blobUploadTimeoutMillisecs, curlEnableVerboseLogging, networkInterface, + useTlsRenegotiation, x509privatekeyType, openSslEngine, trustedCertificates, proxyOptions); + IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_InitializeUpload(h, TEST_DESTINATION_FILENAME, &uploadCorrelationId, &azureBlobSasUri); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); + + umock_c_reset_all_calls(); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_CreateContext(); + IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext = IoTHubClient_LL_UploadToBlob_CreateContext(h, azureBlobSasUri); + + umock_c_reset_all_calls(); + STRICT_EXPECTED_CALL(HTTPAPIEX_Destroy(TEST_HTTPAPIEX_HANDLE)); + STRICT_EXPECTED_CALL(Blob_ClearBlockIdList(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(singlylinkedlist_destroy(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); + + //act + IoTHubClient_LL_UploadToBlob_DestroyContext(uploadContext); + + //assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + //cleanup + IoTHubClient_LL_UploadToBlob_Destroy(h); +} + +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_DestroyContext_NULL_handle_fails) +{ + //arrange + umock_c_reset_all_calls(); + + //act + IoTHubClient_LL_UploadToBlob_DestroyContext(NULL); + + //assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + //cleanup +} // TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks_succeeds) // { // //arrange -// setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN); +// setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN); // IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); @@ -1155,7 +1491,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_verbose_succeeds) TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_x509_cert_succeeds) { //arrange - setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(IOTHUB_CREDENTIAL_TYPE_X509); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); umock_c_reset_all_calls(); @@ -1177,7 +1513,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_openssl_private_key_type_su { int privateKeyType = 1; //arrange - setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(IOTHUB_CREDENTIAL_TYPE_X509); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); umock_c_reset_all_calls(); @@ -1197,7 +1533,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_openssl_engine_type_succeed { const char* engine = "pkcs11"; //arrange - setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(IOTHUB_CREDENTIAL_TYPE_X509); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); umock_c_reset_all_calls(); @@ -1218,7 +1554,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_openssl_engine_type_succeed TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_Network_Interface) { //arrange - setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(IOTHUB_CREDENTIAL_TYPE_X509); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); umock_c_reset_all_calls(); @@ -1240,7 +1576,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_Network_Interface) TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_x509_cert_twice_succeeds) { //arrange - setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(IOTHUB_CREDENTIAL_TYPE_X509); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_X509_CERT, TEST_CERT); umock_c_reset_all_calls(); @@ -1263,7 +1599,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_x509_cert_twice_succeeds) TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_x509_key_succeeds) { //arrange - setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(IOTHUB_CREDENTIAL_TYPE_X509); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); umock_c_reset_all_calls(); @@ -1284,7 +1620,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_x509_key_succeeds) TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_x509_trusted_cert_succeeds) { //arrange - setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(IOTHUB_CREDENTIAL_TYPE_X509); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); umock_c_reset_all_calls(); @@ -1324,7 +1660,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_x509_timeout_succeeds) //arrange size_t timeout = 10; - setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(IOTHUB_CREDENTIAL_TYPE_X509); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); umock_c_reset_all_calls(); @@ -1344,7 +1680,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_tls_renegotiation_succeeds) //arrange bool set_tls_renegotiaton = true; - setup_IoTHubClient_LL_UploadToBlob_Create_mocks(IOTHUB_CREDENTIAL_TYPE_X509); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(IOTHUB_CREDENTIAL_TYPE_X509); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); umock_c_reset_all_calls(); From 381471373d9cf4c88400f741626ce1cf0c6703a3 Mon Sep 17 00:00:00 2001 From: Ewerton Scaboro da Silva Date: Sun, 16 Jul 2023 23:44:05 -0700 Subject: [PATCH 09/27] Update iothub_client_ll_u2b_ut (continued 4) --- .../iothub_client_ll_u2b_ut.c | 968 +++++++++++++++--- 1 file changed, 846 insertions(+), 122 deletions(-) diff --git a/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c b/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c index c8517c2ae5..f370bee585 100644 --- a/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c +++ b/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c @@ -58,11 +58,6 @@ MOCKABLE_FUNCTION(, JSON_Object*, json_value_get_object, const JSON_Value *, val #include "internal/iothub_client_ll_uploadtoblob.h" -#define BLOCK_SIZE (100*1024*1024) - -// TODO: remove this? -// MOCKABLE_FUNCTION(, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT, TestMultiBlockUploadCallback, IOTHUB_CLIENT_FILE_UPLOAD_RESULT, result, unsigned char const **, data, size_t*, size, void*, context); - #define TEST_DEVICE_ID "theidofTheDevice" #define TEST_DEVICE_KEY "theKeyoftheDevice" #define TEST_DEVICE_SAS "theSasOfTheDevice" @@ -83,6 +78,7 @@ MOCKABLE_FUNCTION(, JSON_Object*, json_value_get_object, const JSON_Value *, val #define TEST_U2B_CONTEXT_HANDLE (IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE)0x4446 #define TEST_JSON_VALUE (JSON_Value*)0x4447 #define TEST_SINGLYLINKEDLIST_HANDLE (SINGLYLINKEDLIST_HANDLE)0x4448 +#define TEST_BUFFER_HANDLE (BUFFER_HANDLE)0x4449 static const char* const testUploadtrustedCertificates = "some certificates"; static const char* const TEST_IOTHUB_SAS_TOKEN = "test_sas_token"; @@ -164,31 +160,6 @@ static STRING_HANDLE my_URL_EncodeString(const char* textEncode) return (STRING_HANDLE)my_gballoc_malloc(1); } -static int my_BUFFER_build(BUFFER_HANDLE handle, const unsigned char* source, size_t size) -{ - (void)handle; - (void)source; - (void)size; - return 0; -} - -static BUFFER_HANDLE my_BUFFER_new(void) -{ - return (BUFFER_HANDLE)my_gballoc_malloc(1); -} - -static BUFFER_HANDLE my_BUFFER_create(const unsigned char* source, size_t size) -{ - (void)source; - (void)size; - return (BUFFER_HANDLE)my_gballoc_malloc(1); -} - -static void my_BUFFER_delete(BUFFER_HANDLE handle) -{ - my_gballoc_free(handle); -} - static int my_mallocAndStrcpy_s(char** destination, const char* source) { size_t l = strlen(source); @@ -238,14 +209,21 @@ typedef struct BLOB_UPLOAD_CONTEXT_TAG IOTHUB_CLIENT_FILE_UPLOAD_RESULT lastResult; /* last result received */ unsigned char const ** lastData; size_t* lastSize; + size_t maxBlockSize; + size_t callbackCount; + size_t abortOnCount; }BLOB_UPLOAD_CONTEXT; +// By setting a very high block number below we guarantee +// our tests will never get to it and do not abort the uploads. +#define DO_NOT_ABORT_UPLOAD 1999999 BLOB_UPLOAD_CONTEXT blobUploadContext; static IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT FileUpload_GetData_Callback(IOTHUB_CLIENT_FILE_UPLOAD_RESULT result, unsigned char const ** data, size_t* size, void* _uploadContext) { BLOB_UPLOAD_CONTEXT* uploadContext = (BLOB_UPLOAD_CONTEXT*) _uploadContext; + uploadContext->callbackCount++; uploadContext->lastResult = result; uploadContext->lastData = data; uploadContext->lastSize = size; @@ -265,16 +243,20 @@ static IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT FileUpload_GetData_Callback(IOT *data = NULL; *size = 0; } + else if (uploadContext->callbackCount == uploadContext->abortOnCount) + { + return IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_ABORT; + } else { // Upload next block - size_t thisBlockSize = (uploadContext->toUpload > BLOCK_SIZE) ? BLOCK_SIZE : uploadContext->toUpload; + size_t thisBlockSize = (uploadContext->toUpload > uploadContext->maxBlockSize) ? uploadContext->maxBlockSize : uploadContext->toUpload; *data = (unsigned char*)uploadContext->source + (uploadContext->size - uploadContext->toUpload); *size = thisBlockSize; uploadContext->toUpload -= thisBlockSize; - } - return IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_OK; + return IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_OK; + } } TEST_DEFINE_ENUM_TYPE (HTTPAPI_RESULT, HTTPAPI_RESULT_VALUES); @@ -462,18 +444,19 @@ static void setCreateIotHubHttpApiExHandleExpectedCalls( if (useTlsRenegotiation) { STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(TEST_HTTPAPIEX_HANDLE, OPTION_SET_TLS_RENEGOTIATION, IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(TEST_HTTPAPIEX_HANDLE, OPTION_X509_CERT, IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(TEST_HTTPAPIEX_HANDLE, OPTION_X509_PRIVATE_KEY, IGNORED_PTR_ARG)); - - if (x509privatekeyType != 0) - { - STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(TEST_HTTPAPIEX_HANDLE, OPTION_OPENSSL_PRIVATE_KEY_TYPE, IGNORED_PTR_ARG)); - } - - if (openSslEngine != NULL) - { - STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(TEST_HTTPAPIEX_HANDLE, OPTION_OPENSSL_ENGINE, IGNORED_PTR_ARG)); - } + } + + STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(TEST_HTTPAPIEX_HANDLE, OPTION_X509_CERT, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(TEST_HTTPAPIEX_HANDLE, OPTION_X509_PRIVATE_KEY, IGNORED_PTR_ARG)); + + if (x509privatekeyType != 0) + { + STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(TEST_HTTPAPIEX_HANDLE, OPTION_OPENSSL_PRIVATE_KEY_TYPE, IGNORED_PTR_ARG)); + } + + if (openSslEngine != NULL) + { + STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(TEST_HTTPAPIEX_HANDLE, OPTION_OPENSSL_ENGINE, IGNORED_PTR_ARG)); } } @@ -623,6 +606,78 @@ static void setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_InitializeUpload( STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); // relativePath } +static void setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_NotifyCompletion( + IOTHUB_CREDENTIAL_TYPE credentialType, + size_t blobUploadTimeoutMillisecs, + bool curlEnableVerboseLogging, + const char* networkInterface, + bool useTlsRenegotiation, + int x509privatekeyType, + const char* openSslEngine, + const char* trustedCertificates, + HTTP_PROXY_OPTIONS* proxyOptions) +{ + STRICT_EXPECTED_CALL(STRING_length(IGNORED_PTR_ARG)) + .CallCannotFail(); + STRICT_EXPECTED_CALL(BUFFER_new()); + STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) + .CallCannotFail(); + STRICT_EXPECTED_CALL(BUFFER_build(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG)); + + setCreateIotHubHttpApiExHandleExpectedCalls( + credentialType, blobUploadTimeoutMillisecs, curlEnableVerboseLogging, networkInterface, + useTlsRenegotiation, x509privatekeyType, openSslEngine, trustedCertificates, proxyOptions); + setCreateIotHubRequestHttpHeadersCalls(credentialType); + + if (credentialType == IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY) + { + // send_http_sas_request + const unsigned int httpStatusCode = 200; + + STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) + .CallCannotFail(); + STRICT_EXPECTED_CALL(IoTHubClient_Auth_Get_DeviceKey(IGNORED_PTR_ARG)) + .CallCannotFail(); + STRICT_EXPECTED_CALL(HTTPAPIEX_SAS_Create_From_String(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(HTTPAPIEX_SAS_ExecuteRequest( + IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG, + IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)) + .CopyOutArgumentBuffer_statusCode(&httpStatusCode, sizeof(httpStatusCode)); + STRICT_EXPECTED_CALL(HTTPAPIEX_SAS_Destroy(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); + } + else + { + // send_http_request + const unsigned int httpStatusCode = 200; + + STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) + .CallCannotFail(); + STRICT_EXPECTED_CALL(HTTPAPIEX_ExecuteRequest( + IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, + IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)) + .CopyOutArgumentBuffer_statusCode(&httpStatusCode, sizeof(httpStatusCode)); + } + + STRICT_EXPECTED_CALL(HTTPHeaders_Free(IGNORED_PTR_ARG)); // iotHubRequestHttpHeaders + STRICT_EXPECTED_CALL(HTTPAPIEX_Destroy(IGNORED_PTR_ARG)); // iotHubHttpApiExHandle + STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); // relativePathNotification + + STRICT_EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG)); // responseToIoTHub + STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); // response +} + +static void setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_CreateContext() +{ + // createUploadToBlobContextInstance + STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); + STRICT_EXPECTED_CALL(singlylinkedlist_create()); + // parseAzureBlobSasUri + STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); + STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); + STRICT_EXPECTED_CALL(Blob_CreateHttpConnection(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG)); +} + static void reset_test_data() { memset(&blobUploadContext, 0, sizeof(blobUploadContext)); @@ -693,15 +748,10 @@ TEST_SUITE_INITIALIZE(TestClassInitialize) REGISTER_GLOBAL_MOCK_RETURNS(HTTPAPIEX_SAS_ExecuteRequest, HTTPAPIEX_OK, HTTPAPIEX_ERROR); REGISTER_GLOBAL_MOCK_RETURNS(HTTPAPIEX_ExecuteRequest, HTTPAPIEX_OK, HTTPAPIEX_ERROR); - REGISTER_GLOBAL_MOCK_HOOK(BUFFER_new, my_BUFFER_new); - REGISTER_GLOBAL_MOCK_FAIL_RETURN(BUFFER_new, NULL); + REGISTER_GLOBAL_MOCK_RETURNS(BUFFER_new, TEST_BUFFER_HANDLE, NULL); + REGISTER_GLOBAL_MOCK_RETURNS(BUFFER_create, TEST_BUFFER_HANDLE, NULL); + REGISTER_GLOBAL_MOCK_RETURNS(BUFFER_build, 0, 1); - REGISTER_GLOBAL_MOCK_HOOK(BUFFER_create, my_BUFFER_create); - REGISTER_GLOBAL_MOCK_FAIL_RETURN(BUFFER_create, NULL); - - REGISTER_GLOBAL_MOCK_HOOK(BUFFER_delete, my_BUFFER_delete); - REGISTER_GLOBAL_MOCK_HOOK(BUFFER_build, my_BUFFER_build); - REGISTER_GLOBAL_MOCK_FAIL_RETURN(BUFFER_build, 1); REGISTER_GLOBAL_MOCK_RETURNS(json_parse_string, TEST_JSON_VALUE, NULL); REGISTER_GLOBAL_MOCK_RETURN(json_value_get_object, (JSON_Object*)1); REGISTER_GLOBAL_MOCK_RETURN(json_object_get_string, "a"); @@ -920,40 +970,6 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_Destroy_handle_x509_succeeds) //cleanup } -TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks_handle_NULL_fails) -{ - //arrange - umock_c_reset_all_calls(); - - //act - IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(NULL, FileUpload_GetData_Callback, &blobUploadContext); - - //assert - ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); - ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_INVALID_ARG, result); - - //cleanup -} - -TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks_NULL_callback_fails) -{ - //arrange - setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN); - IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); - - umock_c_reset_all_calls(); - - //act - IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(TEST_U2B_CONTEXT_HANDLE, NULL, &blobUploadContext); - - //assert - ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); - ASSERT_ARE_NOT_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); - - //cleanup - IoTHubClient_LL_UploadToBlob_Destroy(h); -} - TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_SAS_succeeds) { //arrange @@ -1000,13 +1016,13 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_X509_succeeds) bool curlEnableVerboseLogging = false; char* networkInterface = NULL; bool useTlsRenegotiation = false; - int x509privatekeyType = 1; - char* openSslEngine = "pkcs11"; + int x509privatekeyType = 0; + char* openSslEngine = NULL; char* trustedCertificates = NULL; HTTP_PROXY_OPTIONS* proxyOptions = NULL; setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(credentialType); - IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_X509, TEST_AUTH_HANDLE); umock_c_reset_all_calls(); setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_InitializeUpload( @@ -1024,13 +1040,13 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_X509_succeeds) IoTHubClient_LL_UploadToBlob_Destroy(h); } -TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_SAS_ALL_OPTIONS_succeeds) +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_X509_ALL_OPTIONS_succeeds) { //arrange char* uploadCorrelationId; char* azureBlobSasUri; - IOTHUB_CREDENTIAL_TYPE credentialType = IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN; + IOTHUB_CREDENTIAL_TYPE credentialType = IOTHUB_CREDENTIAL_TYPE_X509; size_t blobUploadTimeoutSecs = 5; bool curlEnableVerboseLogging = true; const char* networkInterface = "eth0"; @@ -1044,7 +1060,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_SAS_ALL_OPTIONS_succ proxyOptions.password = "proxypassword"; setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(credentialType); - IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_X509, TEST_AUTH_HANDLE); (void)IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_BLOB_UPLOAD_TIMEOUT_SECS, &blobUploadTimeoutSecs); (void)IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_CURL_VERBOSE, &curlEnableVerboseLogging); (void)IoTHubClient_LL_UploadToBlob_SetOption(h, OPTION_BLOB_UPLOAD_TLS_RENEGOTIATION, &useTlsRenegotiation); @@ -1224,18 +1240,6 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_NULL_SAS_URI_arg_fai IoTHubClient_LL_UploadToBlob_Destroy(h); } - -static void setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_CreateContext() -{ - // createUploadToBlobContextInstance - STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); - STRICT_EXPECTED_CALL(singlylinkedlist_create()); - // parseAzureBlobSasUri - STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); - STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); - STRICT_EXPECTED_CALL(Blob_CreateHttpConnection(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG)); -} - TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_CreateContext_succeeds) { //arrange @@ -1381,8 +1385,8 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_DestroyContext_succeeds) bool curlEnableVerboseLogging = false; char* networkInterface = NULL; bool useTlsRenegotiation = false; - int x509privatekeyType = 1; - char* openSslEngine = "pkcs11"; + int x509privatekeyType = 0; + char* openSslEngine = NULL; char* trustedCertificates = NULL; HTTP_PROXY_OPTIONS* proxyOptions = NULL; @@ -1432,27 +1436,747 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_DestroyContext_NULL_handle_fails) //cleanup } -// TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks_succeeds) -// { -// //arrange -// setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN); -// IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_NotifyCompletion_SAS_Success_succeeds) +{ + //arrange + char* uploadCorrelationId; + char* azureBlobSasUri; + + IOTHUB_CREDENTIAL_TYPE credentialType = IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN; + size_t blobUploadTimeoutMillisecs = 0; + bool curlEnableVerboseLogging = false; + char* networkInterface = NULL; + bool useTlsRenegotiation = false; + int x509privatekeyType = 0; + char* openSslEngine = NULL; + char* trustedCertificates = NULL; + HTTP_PROXY_OPTIONS* proxyOptions = NULL; + + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(credentialType); + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); + + umock_c_reset_all_calls(); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_InitializeUpload( + credentialType, blobUploadTimeoutMillisecs, curlEnableVerboseLogging, networkInterface, + useTlsRenegotiation, x509privatekeyType, openSslEngine, trustedCertificates, proxyOptions); + IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_InitializeUpload(h, TEST_DESTINATION_FILENAME, &uploadCorrelationId, &azureBlobSasUri); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); + + umock_c_reset_all_calls(); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_NotifyCompletion( + credentialType, blobUploadTimeoutMillisecs, curlEnableVerboseLogging, networkInterface, + useTlsRenegotiation, x509privatekeyType, openSslEngine, trustedCertificates, proxyOptions); + + //act + result = IoTHubClient_LL_UploadToBlob_NotifyCompletion(h, uploadCorrelationId, true, 200, "All good"); + + //assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); + + //cleanup + IoTHubClient_LL_UploadToBlob_Destroy(h); +} + +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_NotifyCompletion_X509_Success_succeeds) +{ + //arrange + char* uploadCorrelationId; + char* azureBlobSasUri; + + IOTHUB_CREDENTIAL_TYPE credentialType = IOTHUB_CREDENTIAL_TYPE_X509; + size_t blobUploadTimeoutMillisecs = 0; + bool curlEnableVerboseLogging = false; + char* networkInterface = NULL; + bool useTlsRenegotiation = false; + int x509privatekeyType = 0; + char* openSslEngine = NULL; + char* trustedCertificates = NULL; + HTTP_PROXY_OPTIONS* proxyOptions = NULL; + + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(credentialType); + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_X509, TEST_AUTH_HANDLE); + + umock_c_reset_all_calls(); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_InitializeUpload( + credentialType, blobUploadTimeoutMillisecs, curlEnableVerboseLogging, networkInterface, + useTlsRenegotiation, x509privatekeyType, openSslEngine, trustedCertificates, proxyOptions); + IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_InitializeUpload(h, TEST_DESTINATION_FILENAME, &uploadCorrelationId, &azureBlobSasUri); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); + + umock_c_reset_all_calls(); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_NotifyCompletion( + credentialType, blobUploadTimeoutMillisecs, curlEnableVerboseLogging, networkInterface, + useTlsRenegotiation, x509privatekeyType, openSslEngine, trustedCertificates, proxyOptions); + + //act + result = IoTHubClient_LL_UploadToBlob_NotifyCompletion(h, uploadCorrelationId, true, 200, "All good"); + + //assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); + //cleanup + IoTHubClient_LL_UploadToBlob_Destroy(h); +} -// IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext = IoTHubClient_LL_UploadToBlob_CreateContext(h, azureBlobSasUri); +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_NotifyCompletion_NULL_responseContent_succeeds) +{ + //arrange + char* uploadCorrelationId; + char* azureBlobSasUri; -// umock_c_reset_all_calls(); + IOTHUB_CREDENTIAL_TYPE credentialType = IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN; + size_t blobUploadTimeoutMillisecs = 0; + bool curlEnableVerboseLogging = false; + char* networkInterface = NULL; + bool useTlsRenegotiation = false; + int x509privatekeyType = 0; + char* openSslEngine = NULL; + char* trustedCertificates = NULL; + HTTP_PROXY_OPTIONS* proxyOptions = NULL; -// //act -// IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(TEST_U2B_CONTEXT_HANDLE, FileUpload_GetData_Callback, &blobUploadContext); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(credentialType); + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); -// //assert -// ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); -// ASSERT_ARE_NOT_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); + umock_c_reset_all_calls(); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_InitializeUpload( + credentialType, blobUploadTimeoutMillisecs, curlEnableVerboseLogging, networkInterface, + useTlsRenegotiation, x509privatekeyType, openSslEngine, trustedCertificates, proxyOptions); + IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_InitializeUpload(h, TEST_DESTINATION_FILENAME, &uploadCorrelationId, &azureBlobSasUri); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); -// //cleanup -// IoTHubClient_LL_UploadToBlob_Destroy(h); -// } + umock_c_reset_all_calls(); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_NotifyCompletion( + credentialType, blobUploadTimeoutMillisecs, curlEnableVerboseLogging, networkInterface, + useTlsRenegotiation, x509privatekeyType, openSslEngine, trustedCertificates, proxyOptions); + + //act + result = IoTHubClient_LL_UploadToBlob_NotifyCompletion(h, uploadCorrelationId, true, 200, NULL); + + //assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); + + //cleanup + IoTHubClient_LL_UploadToBlob_Destroy(h); +} + +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_NotifyCompletion_failure_checks) +{ + //arrange + char* uploadCorrelationId; + char* azureBlobSasUri; + + IOTHUB_CREDENTIAL_TYPE credentialType = IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN; + size_t blobUploadTimeoutMillisecs = 0; + bool curlEnableVerboseLogging = false; + char* networkInterface = NULL; + bool useTlsRenegotiation = false; + int x509privatekeyType = 0; + char* openSslEngine = NULL; + char* trustedCertificates = NULL; + HTTP_PROXY_OPTIONS* proxyOptions = NULL; + + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(credentialType); + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); + + umock_c_reset_all_calls(); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_InitializeUpload( + credentialType, blobUploadTimeoutMillisecs, curlEnableVerboseLogging, networkInterface, + useTlsRenegotiation, x509privatekeyType, openSslEngine, trustedCertificates, proxyOptions); + IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_InitializeUpload(h, TEST_DESTINATION_FILENAME, &uploadCorrelationId, &azureBlobSasUri); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); + + ASSERT_ARE_EQUAL(int, 0, umock_c_negative_tests_init()); + umock_c_reset_all_calls(); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_NotifyCompletion( + credentialType, blobUploadTimeoutMillisecs, curlEnableVerboseLogging, networkInterface, + useTlsRenegotiation, x509privatekeyType, openSslEngine, trustedCertificates, proxyOptions); + umock_c_negative_tests_snapshot(); + + // act + for (int i = 0; i < umock_c_negative_tests_call_count(); i++) + { + umock_c_negative_tests_reset(); + + if (umock_c_negative_tests_can_call_fail(i)) + { + umock_c_negative_tests_reset(); + umock_c_negative_tests_fail_call(i); + + // arrange + char error_msg[64]; + + umock_c_negative_tests_reset(); + umock_c_negative_tests_fail_call(i); + + // act + IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_NotifyCompletion(h, uploadCorrelationId, true, 200, "All good"); + + ///assert + sprintf(error_msg, "On failed call %lu (%s)", (unsigned long)i, umockcall_stringify(umock_c_get_last_expected_call())); + ASSERT_ARE_NOT_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result, error_msg); + } + } + + //cleanup + umock_c_negative_tests_deinit(); + IoTHubClient_LL_UploadToBlob_Destroy(h); +} + +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_NotifyCompletion_NULL_handle_fails) +{ + //arrange + const char* uploadCorrelationId = "correlationid"; + + umock_c_reset_all_calls(); + + //act + IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_NotifyCompletion(NULL, uploadCorrelationId, true, 200, "All good"); + + //assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_INVALID_ARG, result); + + //cleanup +} + +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_NotifyCompletion_NULL_correlation_id_fails) +{ + //arrange + umock_c_reset_all_calls(); + + //act + IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_NotifyCompletion( + (IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE)0x4567, NULL, true, 200, "All good"); + + //assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_INVALID_ARG, result); + + //cleanup +} + +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_PutBlock_succeeds) +{ + //arrange + char* uploadCorrelationId; + char* azureBlobSasUri; + IOTHUB_CLIENT_RESULT result; + IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext; + + #define blockDataSize 6 + const uint8_t blockData[blockDataSize] = { 'a', 'b', 'c', 'd', 'e', 'f' }; + + IOTHUB_CREDENTIAL_TYPE credentialType = IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN; + size_t blobUploadTimeoutMillisecs = 0; + bool curlEnableVerboseLogging = false; + char* networkInterface = NULL; + bool useTlsRenegotiation = false; + int x509privatekeyType = 0; + char* openSslEngine = NULL; + char* trustedCertificates = NULL; + HTTP_PROXY_OPTIONS* proxyOptions = NULL; + + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(credentialType); + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); + + umock_c_reset_all_calls(); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_InitializeUpload( + credentialType, blobUploadTimeoutMillisecs, curlEnableVerboseLogging, networkInterface, + useTlsRenegotiation, x509privatekeyType, openSslEngine, trustedCertificates, proxyOptions); + result = IoTHubClient_LL_UploadToBlob_InitializeUpload(h, TEST_DESTINATION_FILENAME, &uploadCorrelationId, &azureBlobSasUri); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); + + umock_c_reset_all_calls(); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_CreateContext(); + uploadContext = IoTHubClient_LL_UploadToBlob_CreateContext(h, azureBlobSasUri); + ASSERT_IS_NOT_NULL(uploadContext); + + umock_c_reset_all_calls(); + STRICT_EXPECTED_CALL(BUFFER_create(blockData, blockDataSize)); + STRICT_EXPECTED_CALL(Blob_PutBlock( + TEST_HTTPAPIEX_HANDLE, IGNORED_PTR_ARG, 0, IGNORED_PTR_ARG, TEST_SINGLYLINKEDLIST_HANDLE, IGNORED_PTR_ARG, NULL)); + STRICT_EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG)); + + + //act + result = IoTHubClient_LL_UploadToBlob_PutBlock(uploadContext, 0 /* block number*/, blockData, blockDataSize); + + //assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); + + //cleanup + IoTHubClient_LL_UploadToBlob_DestroyContext(uploadContext); + IoTHubClient_LL_UploadToBlob_Destroy(h); +} + +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_PutBlock_failure_checks) +{ + //arrange + char* uploadCorrelationId; + char* azureBlobSasUri; + IOTHUB_CLIENT_RESULT result; + IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext; + + #define blockDataSize 6 + const uint8_t blockData[blockDataSize] = { 'a', 'b', 'c', 'd', 'e', 'f' }; + + IOTHUB_CREDENTIAL_TYPE credentialType = IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN; + size_t blobUploadTimeoutMillisecs = 0; + bool curlEnableVerboseLogging = false; + char* networkInterface = NULL; + bool useTlsRenegotiation = false; + int x509privatekeyType = 0; + char* openSslEngine = NULL; + char* trustedCertificates = NULL; + HTTP_PROXY_OPTIONS* proxyOptions = NULL; + + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(credentialType); + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); + + umock_c_reset_all_calls(); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_InitializeUpload( + credentialType, blobUploadTimeoutMillisecs, curlEnableVerboseLogging, networkInterface, + useTlsRenegotiation, x509privatekeyType, openSslEngine, trustedCertificates, proxyOptions); + result = IoTHubClient_LL_UploadToBlob_InitializeUpload(h, TEST_DESTINATION_FILENAME, &uploadCorrelationId, &azureBlobSasUri); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); + + umock_c_reset_all_calls(); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_CreateContext(); + uploadContext = IoTHubClient_LL_UploadToBlob_CreateContext(h, azureBlobSasUri); + ASSERT_IS_NOT_NULL(uploadContext); + + ASSERT_ARE_EQUAL(int, 0, umock_c_negative_tests_init()); + umock_c_reset_all_calls(); + STRICT_EXPECTED_CALL(BUFFER_create(blockData, blockDataSize)); + STRICT_EXPECTED_CALL(Blob_PutBlock( + TEST_HTTPAPIEX_HANDLE, IGNORED_PTR_ARG, 0, IGNORED_PTR_ARG, TEST_SINGLYLINKEDLIST_HANDLE, IGNORED_PTR_ARG, NULL)); + STRICT_EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG)); + umock_c_negative_tests_snapshot(); + + // act + for (int i = 0; i < umock_c_negative_tests_call_count(); i++) + { + umock_c_negative_tests_reset(); + + if (umock_c_negative_tests_can_call_fail(i)) + { + umock_c_negative_tests_reset(); + umock_c_negative_tests_fail_call(i); + + // arrange + char error_msg[64]; + + umock_c_negative_tests_reset(); + umock_c_negative_tests_fail_call(i); + + // act + result = IoTHubClient_LL_UploadToBlob_PutBlock(uploadContext, 0 /* block number*/, blockData, blockDataSize); + + ///assert + sprintf(error_msg, "On failed call %lu (%s)", (unsigned long)i, umockcall_stringify(umock_c_get_last_expected_call())); + ASSERT_ARE_NOT_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result, error_msg); + } + } + + //cleanup + umock_c_negative_tests_deinit(); + IoTHubClient_LL_UploadToBlob_DestroyContext(uploadContext); + IoTHubClient_LL_UploadToBlob_Destroy(h); +} + +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_PutBlock_NULL_handle_fails) +{ + //arrange + IOTHUB_CLIENT_RESULT result; + + #define blockDataSize 6 + const uint8_t blockData[blockDataSize] = { 'a', 'b', 'c', 'd', 'e', 'f' }; + + umock_c_reset_all_calls(); + + //act + result = IoTHubClient_LL_UploadToBlob_PutBlock(NULL, 0 /* block number*/, blockData, blockDataSize); + + //assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_INVALID_ARG, result); + + //cleanup +} + +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_PutBlock_NULL_data_fails) +{ + //arrange + IOTHUB_CLIENT_RESULT result; + IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext = (IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE)0x4567; + + #define blockDataSize 6 + + umock_c_reset_all_calls(); + + //act + result = IoTHubClient_LL_UploadToBlob_PutBlock(uploadContext, 0 /* block number*/, NULL, blockDataSize); + + //assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_INVALID_ARG, result); + + //cleanup +} + +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_PutBlock_zero_dataSize_fails) +{ + //arrange + IOTHUB_CLIENT_RESULT result; + IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext = (IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE)0x4567; + + #define blockDataSize 6 + const uint8_t blockData[blockDataSize] = { 'a', 'b', 'c', 'd', 'e', 'f' }; + + umock_c_reset_all_calls(); + + //act + result = IoTHubClient_LL_UploadToBlob_PutBlock(uploadContext, 0 /* block number*/, blockData, 0); + + //assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_INVALID_ARG, result); + + //cleanup +} + +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_PutBlockList_succeeds) +{ + //arrange + char* uploadCorrelationId; + char* azureBlobSasUri; + IOTHUB_CLIENT_RESULT result; + IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext; + + #define blockDataSize 6 + const uint8_t blockData[blockDataSize] = { 'a', 'b', 'c', 'd', 'e', 'f' }; + + IOTHUB_CREDENTIAL_TYPE credentialType = IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN; + size_t blobUploadTimeoutMillisecs = 0; + bool curlEnableVerboseLogging = false; + char* networkInterface = NULL; + bool useTlsRenegotiation = false; + int x509privatekeyType = 0; + char* openSslEngine = NULL; + char* trustedCertificates = NULL; + HTTP_PROXY_OPTIONS* proxyOptions = NULL; + + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(credentialType); + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); + + umock_c_reset_all_calls(); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_InitializeUpload( + credentialType, blobUploadTimeoutMillisecs, curlEnableVerboseLogging, networkInterface, + useTlsRenegotiation, x509privatekeyType, openSslEngine, trustedCertificates, proxyOptions); + result = IoTHubClient_LL_UploadToBlob_InitializeUpload(h, TEST_DESTINATION_FILENAME, &uploadCorrelationId, &azureBlobSasUri); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); + + umock_c_reset_all_calls(); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_CreateContext(); + uploadContext = IoTHubClient_LL_UploadToBlob_CreateContext(h, azureBlobSasUri); + ASSERT_IS_NOT_NULL(uploadContext); + + umock_c_reset_all_calls(); + STRICT_EXPECTED_CALL(BUFFER_create(blockData, blockDataSize)); + STRICT_EXPECTED_CALL(Blob_PutBlock( + TEST_HTTPAPIEX_HANDLE, IGNORED_PTR_ARG, 0, IGNORED_PTR_ARG, TEST_SINGLYLINKEDLIST_HANDLE, IGNORED_PTR_ARG, NULL)); + STRICT_EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG)); + result = IoTHubClient_LL_UploadToBlob_PutBlock(uploadContext, 0 /* block number*/, blockData, blockDataSize); + + umock_c_reset_all_calls(); + STRICT_EXPECTED_CALL(Blob_PutBlockList( + TEST_HTTPAPIEX_HANDLE, IGNORED_PTR_ARG, TEST_SINGLYLINKEDLIST_HANDLE, IGNORED_PTR_ARG, NULL)); + + //act + result = IoTHubClient_LL_UploadToBlob_PutBlockList(uploadContext); + + //assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); + + //cleanup + IoTHubClient_LL_UploadToBlob_DestroyContext(uploadContext); + IoTHubClient_LL_UploadToBlob_Destroy(h); +} + +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_PutBlockList_failure_checks) +{ + //arrange + char* uploadCorrelationId; + char* azureBlobSasUri; + IOTHUB_CLIENT_RESULT result; + IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext; + + #define blockDataSize 6 + const uint8_t blockData[blockDataSize] = { 'a', 'b', 'c', 'd', 'e', 'f' }; + + IOTHUB_CREDENTIAL_TYPE credentialType = IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN; + size_t blobUploadTimeoutMillisecs = 0; + bool curlEnableVerboseLogging = false; + char* networkInterface = NULL; + bool useTlsRenegotiation = false; + int x509privatekeyType = 0; + char* openSslEngine = NULL; + char* trustedCertificates = NULL; + HTTP_PROXY_OPTIONS* proxyOptions = NULL; + + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(credentialType); + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); + + umock_c_reset_all_calls(); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_InitializeUpload( + credentialType, blobUploadTimeoutMillisecs, curlEnableVerboseLogging, networkInterface, + useTlsRenegotiation, x509privatekeyType, openSslEngine, trustedCertificates, proxyOptions); + result = IoTHubClient_LL_UploadToBlob_InitializeUpload(h, TEST_DESTINATION_FILENAME, &uploadCorrelationId, &azureBlobSasUri); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); + + umock_c_reset_all_calls(); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_CreateContext(); + uploadContext = IoTHubClient_LL_UploadToBlob_CreateContext(h, azureBlobSasUri); + ASSERT_IS_NOT_NULL(uploadContext); + + umock_c_reset_all_calls(); + STRICT_EXPECTED_CALL(BUFFER_create(blockData, blockDataSize)); + STRICT_EXPECTED_CALL(Blob_PutBlock( + TEST_HTTPAPIEX_HANDLE, IGNORED_PTR_ARG, 0, IGNORED_PTR_ARG, TEST_SINGLYLINKEDLIST_HANDLE, IGNORED_PTR_ARG, NULL)); + STRICT_EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG)); + result = IoTHubClient_LL_UploadToBlob_PutBlock(uploadContext, 0 /* block number*/, blockData, blockDataSize); + + ASSERT_ARE_EQUAL(int, 0, umock_c_negative_tests_init()); + umock_c_reset_all_calls(); + STRICT_EXPECTED_CALL(Blob_PutBlockList( + TEST_HTTPAPIEX_HANDLE, IGNORED_PTR_ARG, TEST_SINGLYLINKEDLIST_HANDLE, IGNORED_PTR_ARG, NULL)); + umock_c_negative_tests_snapshot(); + + // act + for (int i = 0; i < umock_c_negative_tests_call_count(); i++) + { + umock_c_negative_tests_reset(); + + if (umock_c_negative_tests_can_call_fail(i)) + { + umock_c_negative_tests_reset(); + umock_c_negative_tests_fail_call(i); + + // arrange + char error_msg[64]; + + umock_c_negative_tests_reset(); + umock_c_negative_tests_fail_call(i); + + // act + result = IoTHubClient_LL_UploadToBlob_PutBlockList(uploadContext); + + ///assert + sprintf(error_msg, "On failed call %lu (%s)", (unsigned long)i, umockcall_stringify(umock_c_get_last_expected_call())); + ASSERT_ARE_NOT_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result, error_msg); + } + } + + //cleanup + umock_c_negative_tests_deinit(); + IoTHubClient_LL_UploadToBlob_DestroyContext(uploadContext); + IoTHubClient_LL_UploadToBlob_Destroy(h); +} + +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_PutBlockList_NULL_handle_fails) +{ + //arrange + umock_c_reset_all_calls(); + + //act + IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_PutBlockList(NULL); + + //assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_INVALID_ARG, result); + + //cleanup +} + +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks_handle_NULL_fails) +{ + //arrange + umock_c_reset_all_calls(); + + //act + IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(NULL, FileUpload_GetData_Callback, &blobUploadContext); + + //assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_INVALID_ARG, result); + + //cleanup +} + +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks_NULL_callback_fails) +{ + //arrange + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN); + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); + + umock_c_reset_all_calls(); + + //act + IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(TEST_U2B_CONTEXT_HANDLE, NULL, &blobUploadContext); + + //assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_NOT_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); + + //cleanup + IoTHubClient_LL_UploadToBlob_Destroy(h); +} + +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks_20x_succeeds) +{ + //arrange + char* uploadCorrelationId; + char* azureBlobSasUri; + IOTHUB_CLIENT_RESULT result; + IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext; + + #define numberOfUploads 20 + #define blockSize 10 + #define dataSize (numberOfUploads * blockSize) + uint8_t data[dataSize]; + (void)memset(data, 1, dataSize); + + blobUploadContext.source = data; + blobUploadContext.size = dataSize; + blobUploadContext.toUpload = dataSize; + blobUploadContext.maxBlockSize = blockSize; + blobUploadContext.abortOnCount = DO_NOT_ABORT_UPLOAD; + + IOTHUB_CREDENTIAL_TYPE credentialType = IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN; + size_t blobUploadTimeoutMillisecs = 0; + bool curlEnableVerboseLogging = false; + char* networkInterface = NULL; + bool useTlsRenegotiation = false; + int x509privatekeyType = 0; + char* openSslEngine = NULL; + char* trustedCertificates = NULL; + HTTP_PROXY_OPTIONS* proxyOptions = NULL; + + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(credentialType); + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); + + umock_c_reset_all_calls(); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_InitializeUpload( + credentialType, blobUploadTimeoutMillisecs, curlEnableVerboseLogging, networkInterface, + useTlsRenegotiation, x509privatekeyType, openSslEngine, trustedCertificates, proxyOptions); + result = IoTHubClient_LL_UploadToBlob_InitializeUpload(h, TEST_DESTINATION_FILENAME, &uploadCorrelationId, &azureBlobSasUri); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); + + umock_c_reset_all_calls(); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_CreateContext(); + uploadContext = IoTHubClient_LL_UploadToBlob_CreateContext(h, azureBlobSasUri); + ASSERT_IS_NOT_NULL(uploadContext); + + umock_c_reset_all_calls(); + for (size_t i = 0; i < numberOfUploads; i++) + { + STRICT_EXPECTED_CALL(BUFFER_create(IGNORED_PTR_ARG, IGNORED_NUM_ARG)); + STRICT_EXPECTED_CALL(Blob_PutBlock( + TEST_HTTPAPIEX_HANDLE, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG, TEST_SINGLYLINKEDLIST_HANDLE, IGNORED_PTR_ARG, NULL)); + STRICT_EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG)); + } + + STRICT_EXPECTED_CALL(Blob_PutBlockList( + TEST_HTTPAPIEX_HANDLE, IGNORED_PTR_ARG, TEST_SINGLYLINKEDLIST_HANDLE, IGNORED_PTR_ARG, NULL)); + + //act + result = IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(uploadContext, FileUpload_GetData_Callback, &blobUploadContext); + + //assert + #undef numberOfUploads + #undef blockSize + #undef dataSize + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); + + //cleanup + IoTHubClient_LL_UploadToBlob_DestroyContext(uploadContext); + IoTHubClient_LL_UploadToBlob_Destroy(h); +} + +TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks_abort_on_2nd_fails) +{ + //arrange + char* uploadCorrelationId; + char* azureBlobSasUri; + IOTHUB_CLIENT_RESULT result; + IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext; + + #define numberOfUploads 3 + #define blockSize 10 + #define dataSize (numberOfUploads * blockSize) + uint8_t data[dataSize]; + (void)memset(data, 1, dataSize); + + blobUploadContext.source = data; + blobUploadContext.size = dataSize; + blobUploadContext.toUpload = dataSize; + blobUploadContext.maxBlockSize = blockSize; + blobUploadContext.abortOnCount = 2; + + IOTHUB_CREDENTIAL_TYPE credentialType = IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN; + size_t blobUploadTimeoutMillisecs = 0; + bool curlEnableVerboseLogging = false; + char* networkInterface = NULL; + bool useTlsRenegotiation = false; + int x509privatekeyType = 0; + char* openSslEngine = NULL; + char* trustedCertificates = NULL; + HTTP_PROXY_OPTIONS* proxyOptions = NULL; + + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(credentialType); + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); + + umock_c_reset_all_calls(); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_InitializeUpload( + credentialType, blobUploadTimeoutMillisecs, curlEnableVerboseLogging, networkInterface, + useTlsRenegotiation, x509privatekeyType, openSslEngine, trustedCertificates, proxyOptions); + result = IoTHubClient_LL_UploadToBlob_InitializeUpload(h, TEST_DESTINATION_FILENAME, &uploadCorrelationId, &azureBlobSasUri); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); + + umock_c_reset_all_calls(); + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_CreateContext(); + uploadContext = IoTHubClient_LL_UploadToBlob_CreateContext(h, azureBlobSasUri); + ASSERT_IS_NOT_NULL(uploadContext); + + umock_c_reset_all_calls(); + for (size_t count = 1; count < blobUploadContext.abortOnCount; count++) + { + STRICT_EXPECTED_CALL(BUFFER_create(IGNORED_PTR_ARG, IGNORED_NUM_ARG)); + STRICT_EXPECTED_CALL(Blob_PutBlock( + TEST_HTTPAPIEX_HANDLE, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG, TEST_SINGLYLINKEDLIST_HANDLE, IGNORED_PTR_ARG, NULL)); + STRICT_EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG)); + } + + //act + result = IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(uploadContext, FileUpload_GetData_Callback, &blobUploadContext); + + //assert + #undef numberOfUploads + #undef blockSize + #undef dataSize + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_ERROR, result); + + //cleanup + IoTHubClient_LL_UploadToBlob_DestroyContext(uploadContext); + IoTHubClient_LL_UploadToBlob_Destroy(h); +} TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_handle_NULL_fails) { From e2ea53d159d0ff47c3875b35570465380466b3d7 Mon Sep 17 00:00:00 2001 From: Ewerton Scaboro da Silva Date: Mon, 17 Jul 2023 20:51:07 -0700 Subject: [PATCH 10/27] Updates to iothub_client_core_ll_ut --- .../iothub_client_core_ll_ut.c | 64 +++++++++++-------- 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/iothub_client/tests/iothubclientcore_ll_ut/iothub_client_core_ll_ut.c b/iothub_client/tests/iothubclientcore_ll_ut/iothub_client_core_ll_ut.c index be8be7e831..f5faec0826 100644 --- a/iothub_client/tests/iothubclientcore_ll_ut/iothub_client_core_ll_ut.c +++ b/iothub_client/tests/iothubclientcore_ll_ut/iothub_client_core_ll_ut.c @@ -50,6 +50,7 @@ void* my_gballoc_realloc(void* ptr, size_t size) #include "iothub_message.h" #include "internal/iothub_client_authorization.h" #include "internal/iothub_client_diagnostic.h" +#include "internal/iothub_client_ll_uploadtoblob.h" #ifdef USE_EDGE_MODULES #include "internal/iothub_client_edge.h" @@ -226,7 +227,9 @@ static const char* TEST_STRING_VALUE = "Test string value"; #define TEST_RETRY_TIMEOUT_SECS 60 #define TEST_METHOD_ID (METHOD_HANDLE)0x61 -#define TEST_IOTHUB_AUTH_HANDLE (IOTHUB_AUTHORIZATION_HANDLE)0x62 +#define TEST_IOTHUB_AUTH_HANDLE (IOTHUB_AUTHORIZATION_HANDLE)0x62 + +#define TEST_U2B_HANDLE (IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE)0x4243 static const char* TEST_PROV_URI = "global.azure-devices-provisioning.net"; @@ -477,20 +480,6 @@ static void my_CONSTBUFFER_DecRef(CONSTBUFFER_HANDLE constbufferHandle) my_gballoc_free(constbufferHandle); } -#ifndef DONT_USE_UPLOADTOBLOB -static IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE my_IoTHubClient_LL_UploadToBlob_Create(const IOTHUB_CLIENT_CONFIG* config, IOTHUB_AUTHORIZATION_HANDLE auth_handle) -{ - (void)config; - (void)auth_handle; - return (IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE)my_gballoc_malloc(1); -} - -static void my_IoTHubClient_LL_UploadToBlob_Destroy(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE handle) -{ - my_gballoc_free(handle); -} -#endif - #ifdef USE_EDGE_MODULES static IOTHUB_CLIENT_EDGE_HANDLE my_IoTHubModuleClient_LL_MethodHandle_Create(const IOTHUB_CLIENT_CONFIG* config, IOTHUB_AUTHORIZATION_HANDLE authorizationHandle, const char* moduleId) { @@ -858,10 +847,8 @@ TEST_SUITE_INITIALIZE(suite_init) REGISTER_GLOBAL_MOCK_FAIL_RETURN(FAKE_IoTHubTransport_DeviceMethod_Response, MU_FAILURE); #ifndef DONT_USE_UPLOADTOBLOB - REGISTER_GLOBAL_MOCK_HOOK(IoTHubClient_LL_UploadToBlob_Create, my_IoTHubClient_LL_UploadToBlob_Create); - REGISTER_GLOBAL_MOCK_FAIL_RETURN(IoTHubClient_LL_UploadToBlob_Create, NULL); - REGISTER_GLOBAL_MOCK_HOOK(IoTHubClient_LL_UploadToBlob_Destroy, my_IoTHubClient_LL_UploadToBlob_Destroy); - REGISTER_GLOBAL_MOCK_RETURN(IoTHubClient_LL_UploadToBlob_SetOption, IOTHUB_CLIENT_OK); + REGISTER_GLOBAL_MOCK_RETURNS(IoTHubClient_LL_UploadToBlob_Create, TEST_U2B_HANDLE, NULL); + REGISTER_GLOBAL_MOCK_RETURNS(IoTHubClient_LL_UploadToBlob_SetOption, IOTHUB_CLIENT_OK, IOTHUB_CLIENT_ERROR); #endif #ifdef USE_EDGE_MODULES @@ -971,9 +958,6 @@ TEST_SUITE_INITIALIZE(suite_init) REGISTER_GLOBAL_MOCK_HOOK(singlylinkedlist_find, real_singlylinkedlist_find); REGISTER_GLOBAL_MOCK_HOOK(singlylinkedlist_foreach, real_singlylinkedlist_foreach); REGISTER_GLOBAL_MOCK_HOOK(singlylinkedlist_remove_if, real_singlylinkedlist_remove_if); - - REGISTER_GLOBAL_MOCK_RETURN(IoTHubClient_LL_UploadToBlob_Impl, IOTHUB_CLIENT_OK); - REGISTER_GLOBAL_MOCK_RETURN(IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl, IOTHUB_CLIENT_OK); } TEST_SUITE_CLEANUP(suite_cleanup) @@ -4054,7 +4038,14 @@ TEST_FUNCTION(IoTHubClientCore_LL_UploadToBlob_OK) IOTHUB_CLIENT_CORE_LL_HANDLE h = IoTHubClientCore_LL_Create(&TEST_CONFIG); umock_c_reset_all_calls(); - STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_Impl(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG)); + STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_InitializeUpload(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_CreateContext(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_PutBlock(IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG)); + STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_PutBlockList(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_DestroyContext(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_NotifyCompletion(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); //act IOTHUB_CLIENT_RESULT result = IoTHubClientCore_LL_UploadToBlob(h, "irrelevantFileName", (const unsigned char*)"a", 1); @@ -4073,7 +4064,15 @@ TEST_FUNCTION(IoTHubClientCore_LL_UploadToBlob_fails) IOTHUB_CLIENT_CORE_LL_HANDLE h = IoTHubClientCore_LL_Create(&TEST_CONFIG); umock_c_reset_all_calls(); - STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_Impl(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG)).SetReturn(IOTHUB_CLIENT_ERROR); + STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_InitializeUpload(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_CreateContext(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_PutBlock(IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG)) + .SetReturn(IOTHUB_CLIENT_ERROR); + STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_PutBlockList(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_DestroyContext(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_NotifyCompletion(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); //act IOTHUB_CLIENT_RESULT result = IoTHubClientCore_LL_UploadToBlob(h, "irrelevantFileName", (const unsigned char*)"a", 1); @@ -4189,7 +4188,13 @@ TEST_FUNCTION(IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx_succeeds) IOTHUB_CLIENT_CORE_LL_HANDLE h = IoTHubClientCore_LL_Create(&TEST_CONFIG); umock_c_reset_all_calls(); - STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_InitializeUpload(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_CreateContext(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_DestroyContext(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_NotifyCompletion(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); //act IOTHUB_CLIENT_RESULT result = IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx(h, "irrelevantFileName", my_FileUpload_GetData_CallbackEx, &context); @@ -4208,7 +4213,14 @@ TEST_FUNCTION(IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx_fails) IOTHUB_CLIENT_CORE_LL_HANDLE h = IoTHubClientCore_LL_Create(&TEST_CONFIG); umock_c_reset_all_calls(); - STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)).SetReturn(IOTHUB_CLIENT_ERROR); + STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_InitializeUpload(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_CreateContext(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)) + .SetReturn(IOTHUB_CLIENT_ERROR); + STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_DestroyContext(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_NotifyCompletion(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); //act IOTHUB_CLIENT_RESULT result = IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx(h, "irrelevantFileName", my_FileUpload_GetData_CallbackEx, &context); From 5c000b05e069d54e138398889d04ed9ed51dc2ce Mon Sep 17 00:00:00 2001 From: Ewerton Scaboro da Silva Date: Mon, 17 Jul 2023 22:00:17 -0700 Subject: [PATCH 11/27] Updates to iothub_client_core_ll_ut (continued) --- iothub_client/src/iothub_client_core_ll.c | 10 +-- .../iothub_client_core_ll_ut.c | 66 +++++++++++++++---- 2 files changed, 60 insertions(+), 16 deletions(-) diff --git a/iothub_client/src/iothub_client_core_ll.c b/iothub_client/src/iothub_client_core_ll.c index 34fa8d376c..a721c6c36a 100755 --- a/iothub_client/src/iothub_client_core_ll.c +++ b/iothub_client/src/iothub_client_core_ll.c @@ -2872,8 +2872,8 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx(IOTHUB_CLI } else { - char* uploadCorrelationId; - char* azureBlobSasUri; + char* uploadCorrelationId = NULL; + char* azureBlobSasUri = NULL; if (IoTHubClient_LL_UploadToBlob_InitializeUpload( iotHubClientHandle->uploadToBlobHandle, destinationFileName, &uploadCorrelationId, &azureBlobSasUri) != IOTHUB_CLIENT_OK) @@ -2900,15 +2900,15 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx(IOTHUB_CLI } else { - uploadSucceeded = false; + uploadSucceeded = true; } IoTHubClient_LL_UploadToBlob_DestroyContext(uploadContext); } - // TODO (ewertons): fix the http error status below. if (IoTHubClient_LL_UploadToBlob_NotifyCompletion( - iotHubClientHandle->uploadToBlobHandle, uploadCorrelationId, uploadSucceeded, 400, NULL) != IOTHUB_CLIENT_OK) + iotHubClientHandle->uploadToBlobHandle, uploadCorrelationId, uploadSucceeded, + uploadSucceeded ? 200 : 400, NULL) != IOTHUB_CLIENT_OK) { LogError("Failed completing upload to blob."); result = IOTHUB_CLIENT_ERROR; diff --git a/iothub_client/tests/iothubclientcore_ll_ut/iothub_client_core_ll_ut.c b/iothub_client/tests/iothubclientcore_ll_ut/iothub_client_core_ll_ut.c index f5faec0826..9717d77101 100644 --- a/iothub_client/tests/iothubclientcore_ll_ut/iothub_client_core_ll_ut.c +++ b/iothub_client/tests/iothubclientcore_ll_ut/iothub_client_core_ll_ut.c @@ -229,8 +229,6 @@ static const char* TEST_STRING_VALUE = "Test string value"; #define TEST_METHOD_ID (METHOD_HANDLE)0x61 #define TEST_IOTHUB_AUTH_HANDLE (IOTHUB_AUTHORIZATION_HANDLE)0x62 -#define TEST_U2B_HANDLE (IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE)0x4243 - static const char* TEST_PROV_URI = "global.azure-devices-provisioning.net"; #define TEST_METHOD_NAME "method_name" @@ -259,6 +257,13 @@ static const char* TEST_VAR_EDGEHOSTNAME = "testEdgeHost.host"; static const char* TEST_VAR_EDGEGATEWAYHOST = "testEdgeGatewayHost"; static const char* TEST_VAR_MODULEID = "testModuleId"; +#ifndef DONT_USE_UPLOADTOBLOB +#define TEST_U2B_HANDLE (IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE)0x4243 +#define TEST_U2B_CONTEXT_HANDLE (IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE)0x4244 +static const char* const TEST_BLOB_SAS_URI = "https://mystorageaccount.blob.core.windows.net/uploadcontainer01/myDeviceId%2fsubdir%text.txt?sv=2018-03-28&sr=b&sig=BuvkhxiMqrFJDYoS4UCZq%2FMkS4rb47doCPvfdgx1iwM%3D&se=2023-07-16T05%3A31%3A08Z&sp=rw"; +static const char* const TEST_UPLOAD_CORRELATION_ID = "MjAyMzA3MTYwNTQxXzVjMzg5NzMzLTlhZTgtNDVmZC1iNjQ0LTIzZDUzMDc5YzgyMF9zdWJkaXIvaGVsbG9fd29ybGRfY3VzdG9tX21iLnR4dF92ZXIyLjA="; +#endif // DONT_USE_UPLOADTOBLOB + static SINGLYLINKEDLIST_HANDLE test_singlylinkedlist_handle = (SINGLYLINKEDLIST_HANDLE)0x4243; static LIST_ITEM_HANDLE find_item_handle = (LIST_ITEM_HANDLE)0x4244; static LIST_ITEM_HANDLE add_item_handle = (LIST_ITEM_HANDLE)0x4245; @@ -794,6 +799,7 @@ TEST_SUITE_INITIALIZE(suite_init) #ifndef DONT_USE_UPLOADTOBLOB REGISTER_UMOCK_ALIAS_TYPE(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, void*); + REGISTER_UMOCK_ALIAS_TYPE(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, void*); REGISTER_UMOCK_ALIAS_TYPE(IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, void*); #endif // DONT_USE_UPLOADTOBLOB @@ -849,6 +855,13 @@ TEST_SUITE_INITIALIZE(suite_init) #ifndef DONT_USE_UPLOADTOBLOB REGISTER_GLOBAL_MOCK_RETURNS(IoTHubClient_LL_UploadToBlob_Create, TEST_U2B_HANDLE, NULL); REGISTER_GLOBAL_MOCK_RETURNS(IoTHubClient_LL_UploadToBlob_SetOption, IOTHUB_CLIENT_OK, IOTHUB_CLIENT_ERROR); + REGISTER_GLOBAL_MOCK_RETURNS(IoTHubClient_LL_UploadToBlob_InitializeUpload, IOTHUB_CLIENT_OK, IOTHUB_CLIENT_ERROR); + REGISTER_GLOBAL_MOCK_RETURNS(IoTHubClient_LL_UploadToBlob_NotifyCompletion, IOTHUB_CLIENT_OK, IOTHUB_CLIENT_ERROR); + REGISTER_GLOBAL_MOCK_RETURNS(IoTHubClient_LL_UploadToBlob_CreateContext, TEST_U2B_CONTEXT_HANDLE, NULL); + REGISTER_GLOBAL_MOCK_RETURNS(IoTHubClient_LL_UploadToBlob_PutBlock, IOTHUB_CLIENT_OK, IOTHUB_CLIENT_ERROR); + REGISTER_GLOBAL_MOCK_RETURNS(IoTHubClient_LL_UploadToBlob_PutBlockList, IOTHUB_CLIENT_OK, IOTHUB_CLIENT_ERROR); + REGISTER_GLOBAL_MOCK_RETURNS(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks, IOTHUB_CLIENT_OK, IOTHUB_CLIENT_ERROR); + #endif #ifdef USE_EDGE_MODULES @@ -4035,10 +4048,16 @@ TEST_FUNCTION(IoTHubClientCore_LL_SetOption_messageTimeout_when_tickcounter_fail TEST_FUNCTION(IoTHubClientCore_LL_UploadToBlob_OK) { //arrange + char* uploadCorrelationId; + char* azureBlobSasUri; + (void)my_mallocAndStrcpy_s(&uploadCorrelationId, TEST_UPLOAD_CORRELATION_ID); + (void)my_mallocAndStrcpy_s(&azureBlobSasUri, TEST_BLOB_SAS_URI); IOTHUB_CLIENT_CORE_LL_HANDLE h = IoTHubClientCore_LL_Create(&TEST_CONFIG); umock_c_reset_all_calls(); - STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_InitializeUpload(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_InitializeUpload(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)) + .CopyOutArgumentBuffer_uploadCorrelationId(&uploadCorrelationId, sizeof(char*)) + .CopyOutArgumentBuffer_azureBlobSasUri(&azureBlobSasUri, sizeof(char*)); STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_CreateContext(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_PutBlock(IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG)); STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_PutBlockList(IGNORED_PTR_ARG)); @@ -4051,8 +4070,8 @@ TEST_FUNCTION(IoTHubClientCore_LL_UploadToBlob_OK) IOTHUB_CLIENT_RESULT result = IoTHubClientCore_LL_UploadToBlob(h, "irrelevantFileName", (const unsigned char*)"a", 1); ///assert - ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); ///cleanup IoTHubClientCore_LL_Destroy(h); @@ -4061,14 +4080,19 @@ TEST_FUNCTION(IoTHubClientCore_LL_UploadToBlob_OK) TEST_FUNCTION(IoTHubClientCore_LL_UploadToBlob_fails) { //arrange + char* uploadCorrelationId; + char* azureBlobSasUri; + (void)my_mallocAndStrcpy_s(&uploadCorrelationId, TEST_UPLOAD_CORRELATION_ID); + (void)my_mallocAndStrcpy_s(&azureBlobSasUri, TEST_BLOB_SAS_URI); IOTHUB_CLIENT_CORE_LL_HANDLE h = IoTHubClientCore_LL_Create(&TEST_CONFIG); umock_c_reset_all_calls(); - STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_InitializeUpload(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_InitializeUpload(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)) + .CopyOutArgumentBuffer_uploadCorrelationId(&uploadCorrelationId, sizeof(char*)) + .CopyOutArgumentBuffer_azureBlobSasUri(&azureBlobSasUri, sizeof(char*)); STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_CreateContext(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_PutBlock(IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG)) .SetReturn(IOTHUB_CLIENT_ERROR); - STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_PutBlockList(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_DestroyContext(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_NotifyCompletion(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); @@ -4078,8 +4102,8 @@ TEST_FUNCTION(IoTHubClientCore_LL_UploadToBlob_fails) IOTHUB_CLIENT_RESULT result = IoTHubClientCore_LL_UploadToBlob(h, "irrelevantFileName", (const unsigned char*)"a", 1); ///assert - ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_ERROR, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_ERROR, result); ///cleanup IoTHubClientCore_LL_Destroy(h); @@ -4089,11 +4113,13 @@ TEST_FUNCTION(IoTHubClientCore_LL_UploadToBlob_fails) TEST_FUNCTION(IoTHubClientCore_LL_UploadToBlob_with_NULL_handle_fails) { //arrange + umock_c_reset_all_calls(); //act IOTHUB_CLIENT_RESULT result = IoTHubClientCore_LL_UploadToBlob(NULL, "irrelevantFileName", (const unsigned char*)"a", 1); ///assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_INVALID_ARG, result); ///cleanup @@ -4109,8 +4135,8 @@ TEST_FUNCTION(IoTHubClientCore_LL_UploadToBlob_with_NULL_fileName_fails) IOTHUB_CLIENT_RESULT result = IoTHubClientCore_LL_UploadToBlob(h, NULL, (const unsigned char*)"a", 1); ///assert - ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_INVALID_ARG, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_INVALID_ARG, result); ///cleanup IoTHubClientCore_LL_Destroy(h); @@ -4126,8 +4152,8 @@ TEST_FUNCTION(IoTHubClientCore_LL_UploadToBlob_with_NULL_source_and_size_greater IOTHUB_CLIENT_RESULT result = IoTHubClientCore_LL_UploadToBlob(h, "someFileName.txt", NULL, 1); ///assert - ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_INVALID_ARG, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_INVALID_ARG, result); ///cleanup IoTHubClientCore_LL_Destroy(h); @@ -4142,6 +4168,7 @@ TEST_FUNCTION(IoTHubClientCore_LL_UploadMultipleBlocksToBlob_with_NULL_handle_fa IOTHUB_CLIENT_RESULT result = IoTHubClientCore_LL_UploadMultipleBlocksToBlob(NULL, "irrelevantFileName", my_FileUpload_GetData_Callback, &context); ///assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_INVALID_ARG, result); ///cleanup @@ -4158,6 +4185,7 @@ TEST_FUNCTION(IoTHubClientCore_LL_UploadMultipleBlocksToBlob_with_NULL_filename_ IOTHUB_CLIENT_RESULT result = IoTHubClientCore_LL_UploadMultipleBlocksToBlob(h, NULL, my_FileUpload_GetData_Callback, &context); ///assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_INVALID_ARG, result); ///cleanup @@ -4175,6 +4203,7 @@ TEST_FUNCTION(IoTHubClientCore_LL_UploadMultipleBlocksToBlob_with_NULL_callback_ IOTHUB_CLIENT_RESULT result = IoTHubClientCore_LL_UploadMultipleBlocksToBlob(h, "irrelevantFileName", NULL, &context); ///assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_INVALID_ARG, result); ///cleanup @@ -4185,10 +4214,16 @@ TEST_FUNCTION(IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx_succeeds) { //arrange unsigned int context = 1; + char* uploadCorrelationId; + char* azureBlobSasUri; + (void)my_mallocAndStrcpy_s(&uploadCorrelationId, TEST_UPLOAD_CORRELATION_ID); + (void)my_mallocAndStrcpy_s(&azureBlobSasUri, TEST_BLOB_SAS_URI); IOTHUB_CLIENT_CORE_LL_HANDLE h = IoTHubClientCore_LL_Create(&TEST_CONFIG); umock_c_reset_all_calls(); - STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_InitializeUpload(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_InitializeUpload(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)) + .CopyOutArgumentBuffer_uploadCorrelationId(&uploadCorrelationId, sizeof(char*)) + .CopyOutArgumentBuffer_azureBlobSasUri(&azureBlobSasUri, sizeof(char*)); STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_CreateContext(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_DestroyContext(IGNORED_PTR_ARG)); @@ -4200,6 +4235,7 @@ TEST_FUNCTION(IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx_succeeds) IOTHUB_CLIENT_RESULT result = IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx(h, "irrelevantFileName", my_FileUpload_GetData_CallbackEx, &context); ///assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); ///cleanup @@ -4210,10 +4246,17 @@ TEST_FUNCTION(IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx_fails) { //arrange unsigned int context = 1; + char* uploadCorrelationId; + char* azureBlobSasUri; + (void)my_mallocAndStrcpy_s(&uploadCorrelationId, TEST_UPLOAD_CORRELATION_ID); + (void)my_mallocAndStrcpy_s(&azureBlobSasUri, TEST_BLOB_SAS_URI); + IOTHUB_CLIENT_CORE_LL_HANDLE h = IoTHubClientCore_LL_Create(&TEST_CONFIG); umock_c_reset_all_calls(); - STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_InitializeUpload(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_InitializeUpload(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)) + .CopyOutArgumentBuffer_uploadCorrelationId(&uploadCorrelationId, sizeof(char*)) + .CopyOutArgumentBuffer_azureBlobSasUri(&azureBlobSasUri, sizeof(char*)); STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_CreateContext(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)) .SetReturn(IOTHUB_CLIENT_ERROR); @@ -4226,6 +4269,7 @@ TEST_FUNCTION(IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx_fails) IOTHUB_CLIENT_RESULT result = IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx(h, "irrelevantFileName", my_FileUpload_GetData_CallbackEx, &context); ///assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_ERROR, result); ///cleanup From 561dd8a74dcf9ac941cba58eb3a7e36accf299d2 Mon Sep 17 00:00:00 2001 From: Ewerton Scaboro da Silva Date: Tue, 18 Jul 2023 14:22:13 -0700 Subject: [PATCH 12/27] Additional unit test fixes --- .../src/iothub_client_ll_uploadtoblob.c | 8 ++- .../iothub_client_ll_u2b_ut.c | 52 +++++++++++++++++-- .../iothubclient_uploadtoblob_e2e.c | 1 - 3 files changed, 53 insertions(+), 8 deletions(-) diff --git a/iothub_client/src/iothub_client_ll_uploadtoblob.c b/iothub_client/src/iothub_client_ll_uploadtoblob.c index 980c3c5b18..01c48ee50b 100644 --- a/iothub_client/src/iothub_client_ll_uploadtoblob.c +++ b/iothub_client/src/iothub_client_ll_uploadtoblob.c @@ -1029,7 +1029,7 @@ IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_PutBlockList(IOTHUB_CLIENT_LL_ } else { - unsigned int putBlockListHttpStatus; + unsigned int putBlockListHttpStatus = 0; // Do not PUT BLOCK LIST if result is not success (isSuccess == false) // Otherwise we could corrupt a blob with a partial update. @@ -1185,7 +1185,11 @@ IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(IOTHUB_CL (void)getDataCallbackEx(FILE_UPLOAD_ERROR, NULL, NULL, context); result = IOTHUB_CLIENT_ERROR; } - else if (IoTHubClient_LL_UploadToBlob_PutBlockList(uploadContextHandle) != IOTHUB_CLIENT_OK) + // Checking if blockID is greater than 0 guarantees that PUT BLOCK LIST will only + // be attempted if at least one block has indeed been uploaded to Azure Storage. + // This behavior follows the behavior of the original implementation of + // Upload-to-Blob in azure-iot-sdk-c. + else if (blockID > 0 && IoTHubClient_LL_UploadToBlob_PutBlockList(uploadContextHandle) != IOTHUB_CLIENT_OK) { LogError("Failed to perform Azure Blob Put Block List operation"); (void)getDataCallbackEx(FILE_UPLOAD_ERROR, NULL, NULL, context); diff --git a/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c b/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c index f370bee585..f4a81bb513 100644 --- a/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c +++ b/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c @@ -1003,6 +1003,8 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_SAS_succeeds) //cleanup IoTHubClient_LL_UploadToBlob_Destroy(h); + my_gballoc_free(uploadCorrelationId); + my_gballoc_free(azureBlobSasUri); } TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_X509_succeeds) @@ -1038,6 +1040,8 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_X509_succeeds) //cleanup IoTHubClient_LL_UploadToBlob_Destroy(h); + my_gballoc_free(uploadCorrelationId); + my_gballoc_free(azureBlobSasUri); } TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_X509_ALL_OPTIONS_succeeds) @@ -1084,6 +1088,8 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_X509_ALL_OPTIONS_suc //cleanup IoTHubClient_LL_UploadToBlob_Destroy(h); + my_gballoc_free(uploadCorrelationId); + my_gballoc_free(azureBlobSasUri); } TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_SAS_failure_checks) @@ -1144,7 +1150,9 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_SAS_failure_checks) h, TEST_DESTINATION_FILENAME, &uploadCorrelationId, &azureBlobSasUri); ///assert - sprintf(error_msg, "On failed call %lu (%s)", (unsigned long)i, umockcall_stringify(umock_c_get_last_expected_call())); + char* umock_last_call = umockcall_stringify(umock_c_get_last_expected_call()); + sprintf(error_msg, "On failed call %lu (%s)", (unsigned long)i, umock_last_call); + my_gballoc_free(umock_last_call); ASSERT_ARE_NOT_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result, error_msg); } } @@ -1279,6 +1287,8 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_CreateContext_succeeds) //cleanup IoTHubClient_LL_UploadToBlob_DestroyContext(uploadContext); IoTHubClient_LL_UploadToBlob_Destroy(h); + my_gballoc_free(uploadCorrelationId); + my_gballoc_free(azureBlobSasUri); } TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_CreateContext_failure_checks) @@ -1333,7 +1343,9 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_CreateContext_failure_checks) IoTHubClient_LL_UploadToBlob_CreateContext(h, azureBlobSasUri); ///assert - sprintf(error_msg, "On failed call %lu (%s)", (unsigned long)i, umockcall_stringify(umock_c_get_last_expected_call())); + char* umock_last_call = umockcall_stringify(umock_c_get_last_expected_call()); + sprintf(error_msg, "On failed call %lu (%s)", (unsigned long)i, umock_last_call); + my_gballoc_free(umock_last_call); ASSERT_IS_NULL(uploadContext, error_msg); } } @@ -1341,6 +1353,8 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_CreateContext_failure_checks) //cleanup umock_c_negative_tests_deinit(); IoTHubClient_LL_UploadToBlob_Destroy(h); + my_gballoc_free(uploadCorrelationId); + my_gballoc_free(azureBlobSasUri); } TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_CreateContext_NULL_handle_fails) @@ -1420,6 +1434,8 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_DestroyContext_succeeds) //cleanup IoTHubClient_LL_UploadToBlob_Destroy(h); + my_gballoc_free(uploadCorrelationId); + my_gballoc_free(azureBlobSasUri); } TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_DestroyContext_NULL_handle_fails) @@ -1476,6 +1492,8 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_NotifyCompletion_SAS_Success_succeeds //cleanup IoTHubClient_LL_UploadToBlob_Destroy(h); + my_gballoc_free(uploadCorrelationId); + my_gballoc_free(azureBlobSasUri); } TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_NotifyCompletion_X509_Success_succeeds) @@ -1518,6 +1536,8 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_NotifyCompletion_X509_Success_succeed //cleanup IoTHubClient_LL_UploadToBlob_Destroy(h); + my_gballoc_free(uploadCorrelationId); + my_gballoc_free(azureBlobSasUri); } TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_NotifyCompletion_NULL_responseContent_succeeds) @@ -1560,6 +1580,8 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_NotifyCompletion_NULL_responseContent //cleanup IoTHubClient_LL_UploadToBlob_Destroy(h); + my_gballoc_free(uploadCorrelationId); + my_gballoc_free(azureBlobSasUri); } TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_NotifyCompletion_failure_checks) @@ -1615,7 +1637,9 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_NotifyCompletion_failure_checks) IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_NotifyCompletion(h, uploadCorrelationId, true, 200, "All good"); ///assert - sprintf(error_msg, "On failed call %lu (%s)", (unsigned long)i, umockcall_stringify(umock_c_get_last_expected_call())); + char* umock_last_call = umockcall_stringify(umock_c_get_last_expected_call()); + sprintf(error_msg, "On failed call %lu (%s)", (unsigned long)i, umock_last_call); + my_gballoc_free(umock_last_call); ASSERT_ARE_NOT_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result, error_msg); } } @@ -1623,6 +1647,8 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_NotifyCompletion_failure_checks) //cleanup umock_c_negative_tests_deinit(); IoTHubClient_LL_UploadToBlob_Destroy(h); + my_gballoc_free(uploadCorrelationId); + my_gballoc_free(azureBlobSasUri); } TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_NotifyCompletion_NULL_handle_fails) @@ -1711,6 +1737,8 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_PutBlock_succeeds) //cleanup IoTHubClient_LL_UploadToBlob_DestroyContext(uploadContext); IoTHubClient_LL_UploadToBlob_Destroy(h); + my_gballoc_free(uploadCorrelationId); + my_gballoc_free(azureBlobSasUri); } TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_PutBlock_failure_checks) @@ -1777,7 +1805,9 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_PutBlock_failure_checks) result = IoTHubClient_LL_UploadToBlob_PutBlock(uploadContext, 0 /* block number*/, blockData, blockDataSize); ///assert - sprintf(error_msg, "On failed call %lu (%s)", (unsigned long)i, umockcall_stringify(umock_c_get_last_expected_call())); + char* umock_last_call = umockcall_stringify(umock_c_get_last_expected_call()); + sprintf(error_msg, "On failed call %lu (%s)", (unsigned long)i, umock_last_call); + my_gballoc_free(umock_last_call); ASSERT_ARE_NOT_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result, error_msg); } } @@ -1786,6 +1816,8 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_PutBlock_failure_checks) umock_c_negative_tests_deinit(); IoTHubClient_LL_UploadToBlob_DestroyContext(uploadContext); IoTHubClient_LL_UploadToBlob_Destroy(h); + my_gballoc_free(uploadCorrelationId); + my_gballoc_free(azureBlobSasUri); } TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_PutBlock_NULL_handle_fails) @@ -1906,6 +1938,8 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_PutBlockList_succeeds) //cleanup IoTHubClient_LL_UploadToBlob_DestroyContext(uploadContext); IoTHubClient_LL_UploadToBlob_Destroy(h); + my_gballoc_free(uploadCorrelationId); + my_gballoc_free(azureBlobSasUri); } TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_PutBlockList_failure_checks) @@ -1977,7 +2011,9 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_PutBlockList_failure_checks) result = IoTHubClient_LL_UploadToBlob_PutBlockList(uploadContext); ///assert - sprintf(error_msg, "On failed call %lu (%s)", (unsigned long)i, umockcall_stringify(umock_c_get_last_expected_call())); + char* umock_last_call = umockcall_stringify(umock_c_get_last_expected_call()); + sprintf(error_msg, "On failed call %lu (%s)", (unsigned long)i, umock_last_call); + my_gballoc_free(umock_last_call); ASSERT_ARE_NOT_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result, error_msg); } } @@ -1986,6 +2022,8 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_PutBlockList_failure_checks) umock_c_negative_tests_deinit(); IoTHubClient_LL_UploadToBlob_DestroyContext(uploadContext); IoTHubClient_LL_UploadToBlob_Destroy(h); + my_gballoc_free(uploadCorrelationId); + my_gballoc_free(azureBlobSasUri); } TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_PutBlockList_NULL_handle_fails) @@ -2107,6 +2145,8 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks_20x_succeeds) //cleanup IoTHubClient_LL_UploadToBlob_DestroyContext(uploadContext); IoTHubClient_LL_UploadToBlob_Destroy(h); + my_gballoc_free(uploadCorrelationId); + my_gballoc_free(azureBlobSasUri); } TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks_abort_on_2nd_fails) @@ -2176,6 +2216,8 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks_abort_on_2nd_fai //cleanup IoTHubClient_LL_UploadToBlob_DestroyContext(uploadContext); IoTHubClient_LL_UploadToBlob_Destroy(h); + my_gballoc_free(uploadCorrelationId); + my_gballoc_free(azureBlobSasUri); } TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_SetOption_handle_NULL_fails) diff --git a/iothub_client/tests/iothubclient_uploadtoblob_e2e/iothubclient_uploadtoblob_e2e.c b/iothub_client/tests/iothubclient_uploadtoblob_e2e/iothubclient_uploadtoblob_e2e.c index bd2f1e7f97..3c2929d120 100644 --- a/iothub_client/tests/iothubclient_uploadtoblob_e2e/iothubclient_uploadtoblob_e2e.c +++ b/iothub_client/tests/iothubclient_uploadtoblob_e2e/iothubclient_uploadtoblob_e2e.c @@ -534,4 +534,3 @@ TEST_FUNCTION(IoTHub_MQTT_UploadCloseHandle_Before_WorkersComplete) #endif // TEST_MQTT END_TEST_SUITE(iothubclient_uploadtoblob_e2e) - From 8cae13171fca17a3c0fa51307b2a672b4c81c534 Mon Sep 17 00:00:00 2001 From: Ewerton Scaboro da Silva Date: Tue, 18 Jul 2023 14:41:08 -0700 Subject: [PATCH 13/27] Fix return of blob result in iothubclient_ll_u2b_ut --- .../tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c b/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c index f4a81bb513..2ccca10183 100644 --- a/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c +++ b/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c @@ -254,9 +254,9 @@ static IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT FileUpload_GetData_Callback(IOT *data = (unsigned char*)uploadContext->source + (uploadContext->size - uploadContext->toUpload); *size = thisBlockSize; uploadContext->toUpload -= thisBlockSize; - - return IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_OK; } + + return IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_OK; } TEST_DEFINE_ENUM_TYPE (HTTPAPI_RESULT, HTTPAPI_RESULT_VALUES); From 297cfb56f8a74b962f33c5bb0462fe3a696e5b5c Mon Sep 17 00:00:00 2001 From: Ewerton Scaboro da Silva Date: Tue, 18 Jul 2023 14:43:13 -0700 Subject: [PATCH 14/27] Fix size_t to int conversion in iothub_client_ll_uploadtoblob.c --- iothub_client/src/iothub_client_ll_uploadtoblob.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iothub_client/src/iothub_client_ll_uploadtoblob.c b/iothub_client/src/iothub_client_ll_uploadtoblob.c index 01c48ee50b..99e64af58c 100644 --- a/iothub_client/src/iothub_client_ll_uploadtoblob.c +++ b/iothub_client/src/iothub_client_ll_uploadtoblob.c @@ -750,7 +750,7 @@ static int parseAzureBlobSasUri(const char* sasUri, char** blobStorageHostname, const char* hostnameBegin; char* hostname = NULL; char* relativePath = NULL; - int sasUriLength = strlen(sasUri); + size_t sasUriLength = strlen(sasUri); /*to find the hostname, the following logic is applied:*/ /*the hostname starts at the first character after "://"*/ From 2bce60fa35fc6873b46843bd4574b6d9bb764944 Mon Sep 17 00:00:00 2001 From: Ewerton Scaboro da Silva Date: Tue, 18 Jul 2023 15:07:40 -0700 Subject: [PATCH 15/27] Add fixes for clang build --- iothub_client/src/blob.c | 2 +- iothub_client/src/iothub_client_core_ll.c | 12 +++--------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/iothub_client/src/blob.c b/iothub_client/src/blob.c index c622d7330d..fb157ebe28 100644 --- a/iothub_client/src/blob.c +++ b/iothub_client/src/blob.c @@ -81,7 +81,7 @@ HTTPAPIEX_HANDLE Blob_CreateHttpConnection(const char* blobStorageHostname, cons { HTTPAPIEX_HANDLE httpApiExHandle; - if ((blobStorageHostname == NULL)) + if (blobStorageHostname == NULL) { LogError("One or more required values is NULL, blobStorageHostname=%p", blobStorageHostname); httpApiExHandle = NULL; diff --git a/iothub_client/src/iothub_client_core_ll.c b/iothub_client/src/iothub_client_core_ll.c index a721c6c36a..bf249539e3 100755 --- a/iothub_client/src/iothub_client_core_ll.c +++ b/iothub_client/src/iothub_client_core_ll.c @@ -2930,9 +2930,7 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_InitializeUpload(IOTHUB_CLIENT_CORE_LL_ { IOTHUB_CLIENT_RESULT result; - if ( - (iotHubClientHandle == NULL) - ) + if (iotHubClientHandle == NULL) { LogError("invalid parameters IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle=%p", iotHubClientHandle); result = IOTHUB_CLIENT_INVALID_ARG; @@ -2998,9 +2996,7 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_AzureStoragePutBlockList(IOTHUB_CLIENT_ { IOTHUB_CLIENT_RESULT result; - if ( - (uploadContextHandle == NULL) - ) + if (uploadContextHandle == NULL) { LogError("invalid parameters uploadContextHandle=%p", uploadContextHandle); result = IOTHUB_CLIENT_INVALID_ARG; @@ -3017,9 +3013,7 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_NotifyUploadCompletion(IOTHUB_CLIENT_CO { IOTHUB_CLIENT_RESULT result; - if ( - (iotHubClientHandle == NULL) - ) + if (iotHubClientHandle == NULL) { LogError("invalid parameters iotHubClientHandle=%p", iotHubClientHandle); result = IOTHUB_CLIENT_INVALID_ARG; From 20065e6075708d1fe096a605ab6711e3bd51a643 Mon Sep 17 00:00:00 2001 From: Ewerton Scaboro da Silva Date: Tue, 18 Jul 2023 17:16:40 -0700 Subject: [PATCH 16/27] More fixes for clang and windows builds --- iothub_client/src/iothub_client_core.c | 4 +--- .../iothubclientcore_ll_ut/iothub_client_core_ll_ut.c | 8 ++++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/iothub_client/src/iothub_client_core.c b/iothub_client/src/iothub_client_core.c index b014aefaf9..587ecc5117 100644 --- a/iothub_client/src/iothub_client_core.c +++ b/iothub_client/src/iothub_client_core.c @@ -2490,9 +2490,7 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_InitializeUpload(IOTHUB_CLIENT_CORE_HANDLE { IOTHUB_CLIENT_RESULT result; - if ( - (iotHubClientHandle == NULL) - ) + if (iotHubClientHandle == NULL) { LogError("invalid parameters iotHubClientHandle = %p", iotHubClientHandle); result = IOTHUB_CLIENT_INVALID_ARG; diff --git a/iothub_client/tests/iothubclientcore_ll_ut/iothub_client_core_ll_ut.c b/iothub_client/tests/iothubclientcore_ll_ut/iothub_client_core_ll_ut.c index 9717d77101..3737567d5f 100644 --- a/iothub_client/tests/iothubclientcore_ll_ut/iothub_client_core_ll_ut.c +++ b/iothub_client/tests/iothubclientcore_ll_ut/iothub_client_core_ll_ut.c @@ -4062,7 +4062,7 @@ TEST_FUNCTION(IoTHubClientCore_LL_UploadToBlob_OK) STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_PutBlock(IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG)); STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_PutBlockList(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_DestroyContext(IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_NotifyCompletion(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_NotifyCompletion(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); @@ -4094,7 +4094,7 @@ TEST_FUNCTION(IoTHubClientCore_LL_UploadToBlob_fails) STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_PutBlock(IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG)) .SetReturn(IOTHUB_CLIENT_ERROR); STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_DestroyContext(IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_NotifyCompletion(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_NotifyCompletion(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); @@ -4227,7 +4227,7 @@ TEST_FUNCTION(IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx_succeeds) STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_CreateContext(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_DestroyContext(IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_NotifyCompletion(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_NotifyCompletion(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); @@ -4261,7 +4261,7 @@ TEST_FUNCTION(IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx_fails) STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)) .SetReturn(IOTHUB_CLIENT_ERROR); STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_DestroyContext(IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_NotifyCompletion(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_NotifyCompletion(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); From 8bec9adee14996e0d7f0fb4ee8d3576a8932cf36 Mon Sep 17 00:00:00 2001 From: Ewerton Scaboro da Silva Date: Tue, 18 Jul 2023 17:51:57 -0700 Subject: [PATCH 17/27] Fix DONT_USE_UPLOADTOBLOB guards in code --- iothub_client/inc/iothub_client_core_ll.h | 2 ++ iothub_client/src/iothub_client_ll.c | 2 +- .../tests/iothubclientcore_ll_ut/iothub_client_core_ll_ut.c | 3 +++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/iothub_client/inc/iothub_client_core_ll.h b/iothub_client/inc/iothub_client_core_ll.h index 9cb2ea29ba..d67b837c46 100644 --- a/iothub_client/inc/iothub_client_core_ll.h +++ b/iothub_client/inc/iothub_client_core_ll.h @@ -18,7 +18,9 @@ typedef struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA_TAG* IOTHUB_CLIENT_CORE_LL_HAND #include "umock_c/umock_c_prod.h" #include "iothub_transport_ll.h" #include "iothub_client_core_common.h" +#ifndef DONT_USE_UPLOADTOBLOB #include "internal/iothub_client_ll_uploadtoblob.h" +#endif #ifdef __cplusplus extern "C" diff --git a/iothub_client/src/iothub_client_ll.c b/iothub_client/src/iothub_client_ll.c index 8bc7c9c62e..9ae71f157a 100644 --- a/iothub_client/src/iothub_client_ll.c +++ b/iothub_client/src/iothub_client_ll.c @@ -24,7 +24,7 @@ #ifndef DONT_USE_UPLOADTOBLOB #include "internal/iothub_client_ll_uploadtoblob.h" -#endif +#endif // DONT_USE_UPLOADTOBLOB IOTHUB_CLIENT_LL_HANDLE IoTHubClient_LL_CreateFromConnectionString(const char* connectionString, IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol) { diff --git a/iothub_client/tests/iothubclientcore_ll_ut/iothub_client_core_ll_ut.c b/iothub_client/tests/iothubclientcore_ll_ut/iothub_client_core_ll_ut.c index 3737567d5f..242a11a731 100644 --- a/iothub_client/tests/iothubclientcore_ll_ut/iothub_client_core_ll_ut.c +++ b/iothub_client/tests/iothubclientcore_ll_ut/iothub_client_core_ll_ut.c @@ -50,7 +50,10 @@ void* my_gballoc_realloc(void* ptr, size_t size) #include "iothub_message.h" #include "internal/iothub_client_authorization.h" #include "internal/iothub_client_diagnostic.h" + +#ifndef DONT_USE_UPLOADTOBLOB #include "internal/iothub_client_ll_uploadtoblob.h" +#endif // DONT_USE_UPLOADTOBLOB #ifdef USE_EDGE_MODULES #include "internal/iothub_client_edge.h" From 21eb23eca77f14ce0e4ebb06a2fcec0397cce14d Mon Sep 17 00:00:00 2001 From: Ewerton Scaboro da Silva Date: Tue, 18 Jul 2023 21:30:48 -0700 Subject: [PATCH 18/27] More build and test fixes --- .../src/iothub_client_ll_uploadtoblob.c | 2 +- iothub_client/tests/blob_ut/blob_ut.c | 6 +++--- .../iothub_client_ll_u2b_ut.c | 17 +++++++++-------- .../iothubclient_uploadtoblob_e2e.c | 2 +- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/iothub_client/src/iothub_client_ll_uploadtoblob.c b/iothub_client/src/iothub_client_ll_uploadtoblob.c index 99e64af58c..27a10fbb50 100644 --- a/iothub_client/src/iothub_client_ll_uploadtoblob.c +++ b/iothub_client/src/iothub_client_ll_uploadtoblob.c @@ -703,7 +703,7 @@ static int IoTHubClient_LL_UploadToBlob_NotifyIoTHubOfUploadCompletion(IOTHUB_CL return result; } -static IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT* createUploadToBlobContextInstance() +static IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT* createUploadToBlobContextInstance(void) { IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT* result; diff --git a/iothub_client/tests/blob_ut/blob_ut.c b/iothub_client/tests/blob_ut/blob_ut.c index 3effca8d7a..cccec68e83 100644 --- a/iothub_client/tests/blob_ut/blob_ut.c +++ b/iothub_client/tests/blob_ut/blob_ut.c @@ -268,7 +268,7 @@ TEST_FUNCTION(Blob_CreateHttpConnection_failure_checks) umock_c_negative_tests_snapshot(); // act - for (int i = 0; i < umock_c_negative_tests_call_count(); i++) + for (size_t i = 0; i < umock_c_negative_tests_call_count(); i++) { umock_c_negative_tests_reset(); @@ -561,7 +561,7 @@ TEST_FUNCTION(Blob_PutBlock_failure_checks) umock_c_negative_tests_snapshot(); // act - for (int i = 0; i < umock_c_negative_tests_call_count(); i++) + for (size_t i = 0; i < umock_c_negative_tests_call_count(); i++) { umock_c_negative_tests_reset(); @@ -736,7 +736,7 @@ TEST_FUNCTION(Blob_PutBlockList_failure_checks) umock_c_negative_tests_snapshot(); // act - for (int i = 0; i < umock_c_negative_tests_call_count(); i++) + for (size_t i = 0; i < umock_c_negative_tests_call_count(); i++) { umock_c_negative_tests_reset(); diff --git a/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c b/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c index 2ccca10183..c6c15792a9 100644 --- a/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c +++ b/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c @@ -1130,7 +1130,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_SAS_failure_checks) umock_c_negative_tests_snapshot(); // act - for (int i = 0; i < umock_c_negative_tests_call_count(); i++) + for (size_t i = 0; i < umock_c_negative_tests_call_count(); i++) { umock_c_negative_tests_reset(); @@ -1167,7 +1167,6 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_NULL_handle_fails) //arrange char* uploadCorrelationId; char* azureBlobSasUri; - IOTHUB_CREDENTIAL_TYPE credentialType = IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN; umock_c_reset_all_calls(); @@ -1323,7 +1322,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_CreateContext_failure_checks) umock_c_negative_tests_snapshot(); // act - for (int i = 0; i < umock_c_negative_tests_call_count(); i++) + for (size_t i = 0; i < umock_c_negative_tests_call_count(); i++) { umock_c_negative_tests_reset(); @@ -1600,6 +1599,8 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_NotifyCompletion_failure_checks) char* trustedCertificates = NULL; HTTP_PROXY_OPTIONS* proxyOptions = NULL; + IOTHUB_CLIENT_RESULT result; + setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_Create(credentialType); IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE h = IoTHubClient_LL_UploadToBlob_Create(&TEST_CONFIG_SAS, TEST_AUTH_HANDLE); @@ -1607,7 +1608,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_NotifyCompletion_failure_checks) setExpectedCallsFor_IoTHubClient_LL_UploadToBlob_InitializeUpload( credentialType, blobUploadTimeoutMillisecs, curlEnableVerboseLogging, networkInterface, useTlsRenegotiation, x509privatekeyType, openSslEngine, trustedCertificates, proxyOptions); - IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_InitializeUpload(h, TEST_DESTINATION_FILENAME, &uploadCorrelationId, &azureBlobSasUri); + result = IoTHubClient_LL_UploadToBlob_InitializeUpload(h, TEST_DESTINATION_FILENAME, &uploadCorrelationId, &azureBlobSasUri); ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); ASSERT_ARE_EQUAL(int, 0, umock_c_negative_tests_init()); @@ -1618,7 +1619,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_NotifyCompletion_failure_checks) umock_c_negative_tests_snapshot(); // act - for (int i = 0; i < umock_c_negative_tests_call_count(); i++) + for (size_t i = 0; i < umock_c_negative_tests_call_count(); i++) { umock_c_negative_tests_reset(); @@ -1634,7 +1635,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_NotifyCompletion_failure_checks) umock_c_negative_tests_fail_call(i); // act - IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_UploadToBlob_NotifyCompletion(h, uploadCorrelationId, true, 200, "All good"); + result = IoTHubClient_LL_UploadToBlob_NotifyCompletion(h, uploadCorrelationId, true, 200, "All good"); ///assert char* umock_last_call = umockcall_stringify(umock_c_get_last_expected_call()); @@ -1786,7 +1787,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_PutBlock_failure_checks) umock_c_negative_tests_snapshot(); // act - for (int i = 0; i < umock_c_negative_tests_call_count(); i++) + for (size_t i = 0; i < umock_c_negative_tests_call_count(); i++) { umock_c_negative_tests_reset(); @@ -1992,7 +1993,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_PutBlockList_failure_checks) umock_c_negative_tests_snapshot(); // act - for (int i = 0; i < umock_c_negative_tests_call_count(); i++) + for (size_t i = 0; i < umock_c_negative_tests_call_count(); i++) { umock_c_negative_tests_reset(); diff --git a/iothub_client/tests/iothubclient_uploadtoblob_e2e/iothubclient_uploadtoblob_e2e.c b/iothub_client/tests/iothubclient_uploadtoblob_e2e/iothubclient_uploadtoblob_e2e.c index 3c2929d120..4a3ee56c97 100644 --- a/iothub_client/tests/iothubclient_uploadtoblob_e2e/iothubclient_uploadtoblob_e2e.c +++ b/iothub_client/tests/iothubclient_uploadtoblob_e2e/iothubclient_uploadtoblob_e2e.c @@ -526,7 +526,7 @@ TEST_FUNCTION(IoTHub_MQTT_UploadToBlob_x509) TEST_FUNCTION(IoTHub_MQTT_UploadCloseHandle_Before_WorkersComplete) { - for (int i = 0; i < 100; i++) + for (int i = 0; i < 10; i++) { e2e_uploadtoblob_close_handle_with_active_thread(MQTT_Protocol); } From 391e27a5bf3cd3ea1f66d03f3be68fcf93fa41dc Mon Sep 17 00:00:00 2001 From: Ewerton Scaboro da Silva Date: Tue, 18 Jul 2023 22:06:24 -0700 Subject: [PATCH 19/27] More build fixes --- .../src/iothub_client_ll_uploadtoblob.c | 26 +++++-------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/iothub_client/src/iothub_client_ll_uploadtoblob.c b/iothub_client/src/iothub_client_ll_uploadtoblob.c index 27a10fbb50..86692e9a71 100644 --- a/iothub_client/src/iothub_client_ll_uploadtoblob.c +++ b/iothub_client/src/iothub_client_ll_uploadtoblob.c @@ -29,12 +29,6 @@ #define API_VERSION "?api-version=2016-11-14" static const char* const RESPONSE_BODY_FORMAT = "{\"correlationId\":\"%s\", \"isSuccess\":%s, \"statusCode\":%d, \"statusDescription\":\"%s\"}"; -static const char* const RESPONSE_BODY_ABORTED_MESSAGE = "file upload aborted"; -static const char* const RESPONSE_BODY_BLOCK_SIZE_EXCEEDED_MESSAGE = "block data size exceeded"; -static const char* const RESPONSE_BODY_BLOCK_COUNT_EXCEEDED_MESSAGE = "block count exceeded"; -static const char* const RESPONSE_BODY_PUT_BLOCK_FAILED_MESSAGE = "put block failed"; -static const char* const RESPONSE_BODY_PUT_BLOCK_LIST_FAILED_MESSAGE = "put block list failed"; -static const int RESPONSE_BODY_ERROR_RETURN_CODE = -1; static const char* const RESPONSE_BODY_SUCCESS_BOOLEAN_STRING = "true"; static const char* const RESPONSE_BODY_ERROR_BOOLEAN_STRING = "false"; @@ -1126,8 +1120,7 @@ IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(IOTHUB_CL else { unsigned int blockID = 0; - unsigned int uploadHttpStatus; - const char* responseToIoTHub = RESPONSE_BODY_ABORTED_MESSAGE; + bool isError; unsigned char const * blockDataPtr = NULL; size_t blockDataSize = 0; IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT getDataReturnValue; @@ -1139,16 +1132,14 @@ IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(IOTHUB_CL if (getDataReturnValue == IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_ABORT) { LogInfo("Upload to blob has been aborted by the user"); - uploadHttpStatus = HTTP_STATUS_CODE_BAD_REQUEST; - responseToIoTHub = RESPONSE_BODY_ABORTED_MESSAGE; + isError = true; break; } else if (blockDataPtr == NULL || blockDataSize == 0) { // This is how the user indicates that there is no more data to be uploaded, // and the function can end with success result. - uploadHttpStatus = HTTP_STATUS_CODE_OK; - responseToIoTHub = EMPTY_STRING; + isError = false; break; } else @@ -1156,22 +1147,19 @@ IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(IOTHUB_CL if (blockDataSize > BLOCK_SIZE) { LogError("tried to upload block of size %lu, max allowed size is %d", (unsigned long)blockDataSize, BLOCK_SIZE); - uploadHttpStatus = HTTP_STATUS_CODE_BAD_REQUEST; - responseToIoTHub = RESPONSE_BODY_BLOCK_SIZE_EXCEEDED_MESSAGE; + isError = true; break; } else if (blockID >= MAX_BLOCK_COUNT) { LogError("unable to upload more than %lu blocks in one blob", (unsigned long)MAX_BLOCK_COUNT); - uploadHttpStatus = HTTP_STATUS_CODE_BAD_REQUEST; - responseToIoTHub = RESPONSE_BODY_BLOCK_COUNT_EXCEEDED_MESSAGE; + isError = true; break; } else if (IoTHubClient_LL_UploadToBlob_PutBlock(uploadContextHandle, blockID, blockDataPtr, blockDataSize) != IOTHUB_CLIENT_OK) { LogError("failed uploading block to blob"); - uploadHttpStatus = HTTP_STATUS_CODE_BAD_REQUEST; - responseToIoTHub = RESPONSE_BODY_PUT_BLOCK_FAILED_MESSAGE; + isError = true; break; } @@ -1180,7 +1168,7 @@ IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(IOTHUB_CL } while(true); - if (!IS_HTTP_STATUS_CODE_SUCCESS(uploadHttpStatus)) + if (isError) { (void)getDataCallbackEx(FILE_UPLOAD_ERROR, NULL, NULL, context); result = IOTHUB_CLIENT_ERROR; From 3ef5d8821db6f13d6216fb9f878d0ffb2efbbb8e Mon Sep 17 00:00:00 2001 From: Ewerton Scaboro da Silva Date: Tue, 18 Jul 2023 22:45:42 -0700 Subject: [PATCH 20/27] More test fixes in iothub_client_ll_u2b_ut for OSX pipeline --- .../iothub_client_ll_u2b_ut.c | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c b/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c index c6c15792a9..aa54179e3a 100644 --- a/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c +++ b/iothub_client/tests/iothubclient_ll_u2b_ut/iothub_client_ll_u2b_ut.c @@ -1150,9 +1150,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_InitializeUpload_SAS_failure_checks) h, TEST_DESTINATION_FILENAME, &uploadCorrelationId, &azureBlobSasUri); ///assert - char* umock_last_call = umockcall_stringify(umock_c_get_last_expected_call()); - sprintf(error_msg, "On failed call %lu (%s)", (unsigned long)i, umock_last_call); - my_gballoc_free(umock_last_call); + sprintf(error_msg, "On failed call %lu", (unsigned long)i); ASSERT_ARE_NOT_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result, error_msg); } } @@ -1342,9 +1340,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_CreateContext_failure_checks) IoTHubClient_LL_UploadToBlob_CreateContext(h, azureBlobSasUri); ///assert - char* umock_last_call = umockcall_stringify(umock_c_get_last_expected_call()); - sprintf(error_msg, "On failed call %lu (%s)", (unsigned long)i, umock_last_call); - my_gballoc_free(umock_last_call); + sprintf(error_msg, "On failed call %lu", (unsigned long)i); ASSERT_IS_NULL(uploadContext, error_msg); } } @@ -1638,9 +1634,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_NotifyCompletion_failure_checks) result = IoTHubClient_LL_UploadToBlob_NotifyCompletion(h, uploadCorrelationId, true, 200, "All good"); ///assert - char* umock_last_call = umockcall_stringify(umock_c_get_last_expected_call()); - sprintf(error_msg, "On failed call %lu (%s)", (unsigned long)i, umock_last_call); - my_gballoc_free(umock_last_call); + sprintf(error_msg, "On failed call %lu", (unsigned long)i); ASSERT_ARE_NOT_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result, error_msg); } } @@ -1806,9 +1800,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_PutBlock_failure_checks) result = IoTHubClient_LL_UploadToBlob_PutBlock(uploadContext, 0 /* block number*/, blockData, blockDataSize); ///assert - char* umock_last_call = umockcall_stringify(umock_c_get_last_expected_call()); - sprintf(error_msg, "On failed call %lu (%s)", (unsigned long)i, umock_last_call); - my_gballoc_free(umock_last_call); + sprintf(error_msg, "On failed call %lu", (unsigned long)i); ASSERT_ARE_NOT_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result, error_msg); } } @@ -2012,9 +2004,7 @@ TEST_FUNCTION(IoTHubClient_LL_UploadToBlob_PutBlockList_failure_checks) result = IoTHubClient_LL_UploadToBlob_PutBlockList(uploadContext); ///assert - char* umock_last_call = umockcall_stringify(umock_c_get_last_expected_call()); - sprintf(error_msg, "On failed call %lu (%s)", (unsigned long)i, umock_last_call); - my_gballoc_free(umock_last_call); + sprintf(error_msg, "On failed call %lu", (unsigned long)i); ASSERT_ARE_NOT_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result, error_msg); } } From 76c3aec21ed5853b5394301c42cb6bc6f413d552 Mon Sep 17 00:00:00 2001 From: Ewerton Scaboro da Silva Date: Tue, 18 Jul 2023 23:32:52 -0700 Subject: [PATCH 21/27] Reduce number of iterations of IoTHub_MQTT_UploadCloseHandle_Before_WorkersComplete --- .../iothubclient_uploadtoblob_e2e.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/iothub_client/tests/iothubclient_uploadtoblob_e2e/iothubclient_uploadtoblob_e2e.c b/iothub_client/tests/iothubclient_uploadtoblob_e2e/iothubclient_uploadtoblob_e2e.c index 4a3ee56c97..e71fc8add1 100644 --- a/iothub_client/tests/iothubclient_uploadtoblob_e2e/iothubclient_uploadtoblob_e2e.c +++ b/iothub_client/tests/iothubclient_uploadtoblob_e2e/iothubclient_uploadtoblob_e2e.c @@ -526,7 +526,8 @@ TEST_FUNCTION(IoTHub_MQTT_UploadToBlob_x509) TEST_FUNCTION(IoTHub_MQTT_UploadCloseHandle_Before_WorkersComplete) { - for (int i = 0; i < 10; i++) + // Running this for lots of iterations can cause e2e test failures. + for (int i = 0; i < 1; i++) { e2e_uploadtoblob_close_handle_with_active_thread(MQTT_Protocol); } From 276e03d0252351f3be2cf300ac2a464ce497d944 Mon Sep 17 00:00:00 2001 From: Ewerton Scaboro da Silva Date: Wed, 19 Jul 2023 13:36:16 -0700 Subject: [PATCH 22/27] Address CR comments from Eric --- iothub_client/inc/iothub_device_client_ll.h | 2 +- .../CMakeLists.txt | 2 +- .../iothub_client_sample_upload_to_blob_custom.c | 8 ++++---- .../iothub_client_sample_upload_to_blob_mb.c | 2 +- iothub_client/src/blob.c | 8 ++++---- iothub_client/src/iothub_client_core.c | 4 ++-- iothub_client/src/iothub_client_core_ll.c | 10 +++++----- iothub_client/src/iothub_client_ll_uploadtoblob.c | 14 +++++++------- 8 files changed, 25 insertions(+), 25 deletions(-) diff --git a/iothub_client/inc/iothub_device_client_ll.h b/iothub_client/inc/iothub_device_client_ll.h index df29e92bce..cf80365224 100644 --- a/iothub_client/inc/iothub_device_client_ll.h +++ b/iothub_client/inc/iothub_device_client_ll.h @@ -380,7 +380,7 @@ typedef struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA_TAG* IOTHUB_DEVICE_CLIENT_LL_HA /** * @brief This API creates a new upload within Azure IoT Hub, getting back a correlation-id and a - * SAS URI for the Blob upload to the Azure Storage associated with the Azure IoT Hub. + * SAS URI for the Blob access to the Azure Storage associated with the Azure IoT Hub. * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. * This function is expected to be used along with: * `IoTHubDeviceClient_LL_AzureStoragePutBlock` diff --git a/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/CMakeLists.txt b/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/CMakeLists.txt index db966715e9..3243edd4d3 100644 --- a/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/CMakeLists.txt +++ b/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/CMakeLists.txt @@ -1,7 +1,7 @@ #Copyright (c) Microsoft. All rights reserved. #Licensed under the MIT license. See LICENSE file in the project root for full license information. -#this is CMakeLists.txt for iothub_client_sample_upload_to_blob +#this is CMakeLists.txt for iothub_client_sample_upload_to_blob_custom compileAsC99() diff --git a/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c b/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c index 3f967bbfc8..7f7547b189 100644 --- a/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c +++ b/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c @@ -96,7 +96,7 @@ int main(void) bool uploadSuccessful = true; int uploadResultCode = 200; - for (uint32_t block_number = 0; block_number < 100; block_number++) + for (uint32_t block_number = 0; block_number < 10; block_number++) { int data_size = snprintf(data_to_upload, sizeof(data_to_upload), data_to_upload_format, block_number); @@ -114,7 +114,7 @@ int main(void) { if (IoTHubDeviceClient_LL_AzureStoragePutBlockList(uploadContextHandle) != IOTHUB_CLIENT_OK) { - (void)printf("failed performing Azure Storage Put Blob List.\n"); + (void)printf("Failed performing Azure Storage Put Blob List.\n"); uploadSuccessful = false; uploadResultCode = 400; } @@ -123,7 +123,7 @@ int main(void) IoTHubDeviceClient_LL_DestroyUploadContext(uploadContextHandle); // Hint: here if there is a failure (e.g., in HTTP transport) - // this function can be called again in a retry loop if desired. + // this function should be retried. if (IoTHubDeviceClient_LL_NotifyUploadCompletion( device_ll_handle, uploadCorrelationId, uploadSuccessful, uploadResultCode, uploadSuccessful ? "OK" : "Aborted") != IOTHUB_CLIENT_OK) @@ -132,7 +132,7 @@ int main(void) } else { - (void)printf("hello world has been created\n"); + (void)printf("hello world blob has been created\n"); } } diff --git a/iothub_client/samples/iothub_client_sample_upload_to_blob_mb/iothub_client_sample_upload_to_blob_mb.c b/iothub_client/samples/iothub_client_sample_upload_to_blob_mb/iothub_client_sample_upload_to_blob_mb.c index c351745521..2d1fc64e46 100644 --- a/iothub_client/samples/iothub_client_sample_upload_to_blob_mb/iothub_client_sample_upload_to_blob_mb.c +++ b/iothub_client/samples/iothub_client_sample_upload_to_blob_mb/iothub_client_sample_upload_to_blob_mb.c @@ -49,7 +49,7 @@ static IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT getDataCallback(IOTHUB_CLIENT_F // Note that the IoT SDK caller does NOT free(*data), as a typical use case the buffer returned // to the IoT layer may be part of a larger buffer that this callback is chunking up for network sends. - if (block_count < 100) + if (block_count < 10) { int len = snprintf(data_to_upload, sizeof(data_to_upload), data_to_upload_format, block_count); if (len < 0 || len >= sizeof(data_to_upload)) diff --git a/iothub_client/src/blob.c b/iothub_client/src/blob.c index fb157ebe28..1a8fd470c1 100644 --- a/iothub_client/src/blob.c +++ b/iothub_client/src/blob.c @@ -68,7 +68,7 @@ static STRING_HANDLE createBlockIdListXml(SINGLYLINKEDLIST_HANDLE blockIDList) return blockIdListXml; } -static bool removeAndDestroyBlockIdsInList(const void* item, const void* match_context, bool* continue_processing) +static bool removeAndDestroyBlockIdInList(const void* item, const void* match_context, bool* continue_processing) { (void)match_context; STRING_HANDLE blockId = (STRING_HANDLE)item; @@ -83,7 +83,7 @@ HTTPAPIEX_HANDLE Blob_CreateHttpConnection(const char* blobStorageHostname, cons if (blobStorageHostname == NULL) { - LogError("One or more required values is NULL, blobStorageHostname=%p", blobStorageHostname); + LogError("Required storage hostname is NULL, blobStorageHostname=%p", blobStorageHostname); httpApiExHandle = NULL; } else @@ -241,7 +241,7 @@ void Blob_ClearBlockIdList(SINGLYLINKEDLIST_HANDLE blockIdList) { if (blockIdList != NULL) { - if (singlylinkedlist_remove_if(blockIdList, removeAndDestroyBlockIdsInList, NULL) != 0) + if (singlylinkedlist_remove_if(blockIdList, removeAndDestroyBlockIdInList, NULL) != 0) { LogError("Failed clearing block ID list"); } @@ -327,7 +327,7 @@ BLOB_RESULT Blob_PutBlockList( } else { - (void)singlylinkedlist_remove_if(blockIDList, removeAndDestroyBlockIdsInList, NULL); + (void)singlylinkedlist_remove_if(blockIDList, removeAndDestroyBlockIdInList, NULL); result = BLOB_OK; } BUFFER_delete(blockIDListAsBuffer); diff --git a/iothub_client/src/iothub_client_core.c b/iothub_client/src/iothub_client_core.c index 587ecc5117..3d04f0daf8 100644 --- a/iothub_client/src/iothub_client_core.c +++ b/iothub_client/src/iothub_client_core.c @@ -2492,7 +2492,7 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_InitializeUpload(IOTHUB_CLIENT_CORE_HANDLE if (iotHubClientHandle == NULL) { - LogError("invalid parameters iotHubClientHandle = %p", iotHubClientHandle); + LogError("invalid parameter iotHubClientHandle = %p", iotHubClientHandle); result = IOTHUB_CLIENT_INVALID_ARG; } else @@ -2509,7 +2509,7 @@ IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubClientCore_CreateUploadContex if (iotHubClientHandle == NULL) { - LogError("invalid parameters iotHubClientHandle = %p", iotHubClientHandle); + LogError("invalid parameter iotHubClientHandle = %p", iotHubClientHandle); result = NULL; } else diff --git a/iothub_client/src/iothub_client_core_ll.c b/iothub_client/src/iothub_client_core_ll.c index bf249539e3..2c2baae07d 100755 --- a/iothub_client/src/iothub_client_core_ll.c +++ b/iothub_client/src/iothub_client_core_ll.c @@ -2706,7 +2706,7 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_UploadToBlob(IOTHUB_CLIENT_CORE_LL_HAND ((source == NULL) && (size >0)) ) { - LogError("invalid parameters IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle=%p, const char* destinationFileName=%s, const unsigned char* source=%p, size_t size=%lu", + LogError("invalid parameters iotHubClientHandle=%p, const char* destinationFileName=%s, const unsigned char* source=%p, size_t size=%lu", iotHubClientHandle, destinationFileName, source, (unsigned long)size); result = IOTHUB_CLIENT_INVALID_ARG; } @@ -2932,7 +2932,7 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_InitializeUpload(IOTHUB_CLIENT_CORE_LL_ if (iotHubClientHandle == NULL) { - LogError("invalid parameters IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle=%p", iotHubClientHandle); + LogError("invalid parameter iotHubClientHandle=%p", iotHubClientHandle); result = IOTHUB_CLIENT_INVALID_ARG; } else @@ -2960,7 +2960,7 @@ IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubClientCore_LL_CreateUploadCon (azureBlobSasUri == NULL) ) { - LogError("invalid parameters IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle=%p, azureBlobSasUri=%p", iotHubClientHandle, azureBlobSasUri); + LogError("invalid parameters iotHubClientHandle=%p, azureBlobSasUri=%p", iotHubClientHandle, azureBlobSasUri); result = NULL; } else @@ -2998,7 +2998,7 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_AzureStoragePutBlockList(IOTHUB_CLIENT_ if (uploadContextHandle == NULL) { - LogError("invalid parameters uploadContextHandle=%p", uploadContextHandle); + LogError("invalid parameter uploadContextHandle=%p", uploadContextHandle); result = IOTHUB_CLIENT_INVALID_ARG; } else @@ -3015,7 +3015,7 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_NotifyUploadCompletion(IOTHUB_CLIENT_CO if (iotHubClientHandle == NULL) { - LogError("invalid parameters iotHubClientHandle=%p", iotHubClientHandle); + LogError("invalid parameter iotHubClientHandle=%p", iotHubClientHandle); result = IOTHUB_CLIENT_INVALID_ARG; } else diff --git a/iothub_client/src/iothub_client_ll_uploadtoblob.c b/iothub_client/src/iothub_client_ll_uploadtoblob.c index 86692e9a71..b47a20f00a 100644 --- a/iothub_client/src/iothub_client_ll_uploadtoblob.c +++ b/iothub_client/src/iothub_client_ll_uploadtoblob.c @@ -128,7 +128,7 @@ static int send_http_sas_request(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* uplo } else if (!IS_HTTP_STATUS_CODE_SUCCESS(statusCode)) { - LogError("HTTP response code was %u", statusCode); + LogError("HTTP failed response code was %u", statusCode); result = MU_FAILURE; } else @@ -249,7 +249,7 @@ static int parseResultFromIoTHub(const char* json_response, char** uploadCorrela } else if (mallocAndStrcpy_s(azureBlobSasUri, STRING_c_str(sas_uri)) != 0) { - LogError("unable to copy Sas URI"); + LogError("unable to copy SAS URI"); free(*uploadCorrelationId); *uploadCorrelationId = NULL; result = MU_FAILURE; @@ -289,7 +289,7 @@ static HTTP_HEADERS_HANDLE createIotHubRequestHttpHeaders(IOTHUB_CLIENT_LL_UPLOA (HTTPHeaders_AddHeaderNameValuePair(iotHubRequestHttpHeaders, "Accept", HEADER_APP_JSON) != HTTP_HEADERS_OK) || (HTTPHeaders_AddHeaderNameValuePair(iotHubRequestHttpHeaders, "User-Agent", "iothubclient/" IOTHUB_SDK_VERSION) != HTTP_HEADERS_OK)) { - LogError("unable to HTTPHeaders_AddHeaderNameValuePair"); + LogError("unable to add HTTP headers"); isError = true; } else @@ -661,7 +661,7 @@ static int IoTHubClient_LL_UploadToBlob_NotifyIoTHubOfUploadCompletion(IOTHUB_CL { if (send_http_request(iotHubHttpApiExHandle, STRING_c_str(relativePathNotification), iotHubRequestHttpHeaders, messageBody, NULL) != 0) { - LogError("unable to execute HTTPAPIEX_ExecuteRequest"); + LogError("unable to execute send_http_request"); result = MU_FAILURE; } else @@ -674,7 +674,7 @@ static int IoTHubClient_LL_UploadToBlob_NotifyIoTHubOfUploadCompletion(IOTHUB_CL { if (send_http_sas_request(upload_data, iotHubHttpApiExHandle, STRING_c_str(relativePathNotification), iotHubRequestHttpHeaders, messageBody, NULL) != 0) { - LogError("unable to execute HTTPAPIEX_ExecuteRequest"); + LogError("unable to execute send_http_sas_request"); result = MU_FAILURE; } else @@ -974,7 +974,7 @@ IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_PutBlock(IOTHUB_CLIENT_LL_UPLO if (uploadContext == NULL || dataPtr == NULL || dataSize == 0) { - LogError("invalid argument detected uploadContext=%p, dataPtr=%p, dataSize=%zu", uploadContext, dataPtr, dataSize); + LogError("invalid argument uploadContext=%p, dataPtr=%p, dataSize=%zu", uploadContext, dataPtr, dataSize); result = IOTHUB_CLIENT_INVALID_ARG; } else @@ -1018,7 +1018,7 @@ IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_PutBlockList(IOTHUB_CLIENT_LL_ if (uploadContext == NULL) { - LogError("invalid argument detected uploadContext=%p", uploadContext); + LogError("invalid argument uploadContext=%p", uploadContext); result = IOTHUB_CLIENT_INVALID_ARG; } else From e01a280c3f93ab5f8b1f028c5677d8994830f0b0 Mon Sep 17 00:00:00 2001 From: Ewerton Scaboro da Silva Date: Wed, 19 Jul 2023 14:21:42 -0700 Subject: [PATCH 23/27] Add retry logic to iothub_client_sample_upload_to_blob_custom --- ...thub_client_sample_upload_to_blob_custom.c | 78 +++++++++++++++---- 1 file changed, 61 insertions(+), 17 deletions(-) diff --git a/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c b/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c index 7f7547b189..013387e920 100644 --- a/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c +++ b/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c @@ -19,6 +19,7 @@ and removing calls to _DoWork will yield the same results. */ #include "iothub_device_client.h" #include "azure_c_shared_utility/shared_util_options.h" +#include "azure_c_shared_utility/threadapi.h" #include "iothub_message.h" #include "iothubtransportmqtt.h" @@ -39,6 +40,9 @@ static const char* azureStorageBlobPath = "subdir/hello_world_custom_mb.txt"; static const char* data_to_upload_format = "Hello World from iothub_client_sample_upload_to_blob_custom: %d\n"; static char data_to_upload[128]; +#define SAMPLE_MAX_RETRY_COUNT 3 +#define SAMPLE_RETRY_DELAY_MILLISECS 2000 + int main(void) { IOTHUB_DEVICE_CLIENT_LL_HANDLE device_ll_handle; @@ -95,18 +99,39 @@ int main(void) { bool uploadSuccessful = true; int uploadResultCode = 200; + int attemptCount; - for (uint32_t block_number = 0; block_number < 10; block_number++) + for (uint32_t block_number = 0; block_number < 10 && uploadSuccessful; block_number++) { int data_size = snprintf(data_to_upload, sizeof(data_to_upload), data_to_upload_format, block_number); - if (IoTHubDeviceClient_LL_AzureStoragePutBlock( - uploadContextHandle, block_number, (const uint8_t*)data_to_upload, data_size) != IOTHUB_CLIENT_OK) + attemptCount = 1; + + while (true) { - (void)printf("Failed uploading block number %u to blob. Aborting upload.\n", block_number); - uploadSuccessful = false; - uploadResultCode = 300; - break; + if (IoTHubDeviceClient_LL_AzureStoragePutBlock( + uploadContextHandle, block_number, (const uint8_t*)data_to_upload, data_size) == IOTHUB_CLIENT_OK) + { + // Block upload succeeded. Continuing with next block. + break; + } + else + { + if (attemptCount >= SAMPLE_MAX_RETRY_COUNT) + { + (void)printf("Failed uploading block number %u to blob (exhausted all retries).\n", block_number); + uploadSuccessful = false; + uploadResultCode = 300; + break; + } + else + { + (void)printf("Failed uploading block number %u. Retrying in %u seconds...\n", block_number, SAMPLE_RETRY_DELAY_MILLISECS / 1000); + ThreadAPI_Sleep(SAMPLE_RETRY_DELAY_MILLISECS); + } + } + + attemptCount++; } } @@ -122,17 +147,36 @@ int main(void) IoTHubDeviceClient_LL_DestroyUploadContext(uploadContextHandle); - // Hint: here if there is a failure (e.g., in HTTP transport) - // this function should be retried. - if (IoTHubDeviceClient_LL_NotifyUploadCompletion( - device_ll_handle, uploadCorrelationId, uploadSuccessful, uploadResultCode, uploadSuccessful ? "OK" : "Aborted") - != IOTHUB_CLIENT_OK) - { - (void)printf("Failed notifying Azure IoT Hub of upload completion.\n"); - } - else + attemptCount = 1; + + while (true) { - (void)printf("hello world blob has been created\n"); + if (IoTHubDeviceClient_LL_NotifyUploadCompletion( + device_ll_handle, uploadCorrelationId, uploadSuccessful, uploadResultCode, uploadSuccessful ? "OK" : "Aborted") + == IOTHUB_CLIENT_OK) + { + // Notification succeeded. + if (uploadSuccessful) + { + (void)printf("hello world blob has been created\n"); + } + break; + } + else + { + if (attemptCount >= SAMPLE_MAX_RETRY_COUNT) + { + (void)printf("Failed notifying Azure IoT Hub of upload completion (exhausted all retries).\n"); + break; + } + else + { + (void)printf("Failed notifying Azure IoT Hub of upload completion. Retrying in %u seconds...\n", SAMPLE_RETRY_DELAY_MILLISECS / 1000); + ThreadAPI_Sleep(SAMPLE_RETRY_DELAY_MILLISECS); + } + } + + attemptCount++; } } From 2129550afb9646e4cc87a76cf9a4553d5a9dc055 Mon Sep 17 00:00:00 2001 From: Ewerton Scaboro da Silva Date: Wed, 19 Jul 2023 18:51:06 -0700 Subject: [PATCH 24/27] Address code review comments (function renaming) --- .../internal/iothub_client_ll_uploadtoblob.h | 2 +- iothub_client/inc/iothub_client_core.h | 8 +-- iothub_client/inc/iothub_client_core_ll.h | 8 +-- iothub_client/inc/iothub_device_client.h | 64 ++++++++++--------- iothub_client/inc/iothub_device_client_ll.h | 60 +++++++++-------- ...thub_client_sample_upload_to_blob_custom.c | 14 ++-- iothub_client/src/iothub_client_core.c | 16 ++--- iothub_client/src/iothub_client_core_ll.c | 24 +++---- .../src/iothub_client_ll_uploadtoblob.c | 10 +-- iothub_client/src/iothub_device_client.c | 16 ++--- iothub_client/src/iothub_device_client_ll.c | 16 ++--- 11 files changed, 125 insertions(+), 113 deletions(-) diff --git a/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h b/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h index 247a9f7943..c3bff63a97 100644 --- a/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h +++ b/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h @@ -59,7 +59,7 @@ extern "C" * blob blocks data. Since there was quite a lot of (specific) logic put into this function, it * better remain in this API module. */ - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, azureStorageClientHandle, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context); MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_InitializeUpload, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, handle, const char*, destinationFileName, char**, uploadCorrelationId, char**, azureBlobSasUri); MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, IoTHubClient_LL_UploadToBlob_CreateContext, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, handle, const char*, azureBlobSasUri); diff --git a/iothub_client/inc/iothub_client_core.h b/iothub_client/inc/iothub_client_core.h index 3d8a7ed270..341ef92281 100644 --- a/iothub_client/inc/iothub_client_core.h +++ b/iothub_client/inc/iothub_client_core.h @@ -53,10 +53,10 @@ extern "C" MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_UploadToBlobAsync, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, const char*, destinationFileName, const unsigned char*, source, size_t, size, IOTHUB_CLIENT_FILE_UPLOAD_CALLBACK, iotHubClientFileUploadCallback, void*, context); MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_UploadMultipleBlocksToBlobAsync, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK, getDataCallback, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context); MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_InitializeUpload, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, const char*, destinationFileName, char**, uploadCorrelationId, char**, azureBlobSasUri); - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, IoTHubClientCore_CreateUploadContext, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, const char*, azureBlobSasUri); - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_AzureStoragePutBlock, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle, uint32_t, blockNumber, const uint8_t*, dataPtr, size_t, dataSize); - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_AzureStoragePutBlockList, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle); - MOCKABLE_FUNCTION(, void, IoTHubClientCore_DestroyUploadContext, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, IoTHubClientCore_AzureStorageCreateClient, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, const char*, azureBlobSasUri); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_AzureStoragePutBlock, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, azureStorageClientHandle, uint32_t, blockNumber, const uint8_t*, dataPtr, size_t, dataSize); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_AzureStoragePutBlockList, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, azureStorageClientHandle); + MOCKABLE_FUNCTION(, void, IoTHubClientCore_AzureStorageDestroyClient, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, azureStorageClientHandle); MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_NotifyUploadCompletion, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, const char*, uploadCorrelationId, bool, isSuccess, int, responseCode, const char*, responseMessage); #endif /* DONT_USE_UPLOADTOBLOB */ diff --git a/iothub_client/inc/iothub_client_core_ll.h b/iothub_client/inc/iothub_client_core_ll.h index d67b837c46..befe5364af 100644 --- a/iothub_client/inc/iothub_client_core_ll.h +++ b/iothub_client/inc/iothub_client_core_ll.h @@ -56,10 +56,10 @@ extern "C" MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_UploadMultipleBlocksToBlob, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK, getDataCallback, void*, context); MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context); MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_InitializeUpload, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, char**, uploadCorrelationId, char**, azureBlobSasUri); - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, IoTHubClientCore_LL_CreateUploadContext, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const char*, azureBlobSasUri); - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_AzureStoragePutBlock, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle, uint32_t, blockNumber, const uint8_t*, dataPtr, size_t, dataSize); - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_AzureStoragePutBlockList, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle); - MOCKABLE_FUNCTION(, void, IoTHubClientCore_LL_DestroyUploadContext, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, IoTHubClientCore_LL_AzureStorageCreateClient, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const char*, azureBlobSasUri); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_AzureStoragePutBlock, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, azureStorageClientHandle, uint32_t, blockNumber, const uint8_t*, dataPtr, size_t, dataSize); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_AzureStoragePutBlockList, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, azureStorageClientHandle); + MOCKABLE_FUNCTION(, void, IoTHubClientCore_LL_AzureStorageDestroyClient, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, azureStorageClientHandle); MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_NotifyUploadCompletion, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const char*, uploadCorrelationId, bool, isSuccess, int, responseCode, const char*, responseMessage); #endif /*DONT_USE_UPLOADTOBLOB*/ diff --git a/iothub_client/inc/iothub_device_client.h b/iothub_client/inc/iothub_device_client.h index d6637386d9..56423b73be 100644 --- a/iothub_client/inc/iothub_device_client.h +++ b/iothub_client/inc/iothub_device_client.h @@ -34,6 +34,12 @@ typedef IOTHUB_CLIENT_CORE_HANDLE IOTHUB_DEVICE_CLIENT_HANDLE; #define IOTHUB_DEVICE_CLIENT_INSTANCE_TYPE #endif // IOTHUB_CLIENT_INSTANCE +#ifndef DONT_USE_UPLOADTOBLOB +/** +* @brief Handle for Upload-to-Blob API Functions. +*/ +typedef IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IOTHUB_CLIENT_AZURE_STORAGE_CLIENT_HANDLE; +#endif // DONT_USE_UPLOADTOBLOB #ifdef __cplusplus extern "C" @@ -353,13 +359,13 @@ extern "C" * SAS URI for the Blob upload to the Azure Storage associated with the Azure IoT Hub. * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. * This function is expected to be used along with: - * `IoTHubDeviceClient_CreateUploadContext` + * `IoTHubDeviceClient_AzureStorageCreateClient` * `IoTHubDeviceClient_AzureStoragePutBlock` * `IoTHubDeviceClient_AzureStoragePutBlockList` - * `IoTHubDeviceClient_DestroyUploadContext` + * `IoTHubDeviceClient_AzureStorageDestroyClient` * `IoTHubDeviceClient_InitializeUpload` * `IoTHubDeviceClient_NotifyUploadCompletion` - * For the standard less-granular uploads to blob please use either + * For simpler/less-granular control of uploads to Azure blob storage please use either * `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`. * * @param iotHubClientHandle The handle created by a call to the create function. @@ -376,16 +382,16 @@ extern "C" MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_InitializeUpload, IOTHUB_DEVICE_CLIENT_HANDLE, iotHubClientHandle, const char*, destinationFileName, char**, uploadCorrelationId, char**, azureBlobSasUri); /** - * @brief This API creates a context for a new blob upload to Azure Storage. + * @brief This API creates a client for a new blob upload to Azure Storage. * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. * This function is expected to be used along with: - * `IoTHubDeviceClient_CreateUploadContext` + * `IoTHubDeviceClient_AzureStorageCreateClient` * `IoTHubDeviceClient_AzureStoragePutBlock` * `IoTHubDeviceClient_AzureStoragePutBlockList` - * `IoTHubDeviceClient_DestroyUploadContext` + * `IoTHubDeviceClient_AzureStorageDestroyClient` * `IoTHubDeviceClient_InitializeUpload` * `IoTHubDeviceClient_NotifyUploadCompletion` - * For the standard less-granular uploads to blob please use either + * For simpler/less-granular control of uploads to Azure blob storage please use either * `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`. * * @param iotHubClientHandle The handle created by a call to the create function. @@ -393,26 +399,26 @@ extern "C" * * @warning This is a synchronous/blocking function. * - * @return A `IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE` on success or NULL if the function fails. + * @return A `IOTHUB_CLIENT_AZURE_STORAGE_CLIENT_HANDLE` on success or NULL if the function fails. */ - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, IoTHubDeviceClient_CreateUploadContext, IOTHUB_DEVICE_CLIENT_HANDLE, iotHubClientHandle, const char*, azureBlobSasUri); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_AZURE_STORAGE_CLIENT_HANDLE, IoTHubDeviceClient_AzureStorageCreateClient, IOTHUB_DEVICE_CLIENT_HANDLE, iotHubClientHandle, const char*, azureBlobSasUri); /** * @brief This API uploads a single blob block to Azure Storage (performs a PUT BLOCK operation). * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. * This function is expected to be used along with: - * `IoTHubDeviceClient_CreateUploadContext` + * `IoTHubDeviceClient_AzureStorageCreateClient` * `IoTHubDeviceClient_AzureStoragePutBlock` * `IoTHubDeviceClient_AzureStoragePutBlockList` - * `IoTHubDeviceClient_DestroyUploadContext` + * `IoTHubDeviceClient_AzureStorageDestroyClient` * `IoTHubDeviceClient_InitializeUpload` * `IoTHubDeviceClient_NotifyUploadCompletion` - * For the standard less-granular uploads to blob please use either + * For simpler/less-granular control of uploads to Azure blob storage please use either * `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`. * For more information about Azure Storage PUT BLOCK, its parameters and behavior, please refer to * https://learn.microsoft.com/en-us/rest/api/storageservices/put-block * - * @param uploadContextHandle The handle created with `IoTHubDeviceClient_CreateUploadContext`. + * @param azureStorageClientHandle The handle created with `IoTHubDeviceClient_AzureStorageCreateClient`. * @param blockNumber Number of the block being uploaded. * @param dataPtr Pointer to the block data to be uploaded to Azure Storage blob. * @param dataSize Size of the block data pointed by `dataPtr`. @@ -421,19 +427,19 @@ extern "C" * * @return IOTHUB_CLIENT_OK upon success or an error code upon failure. */ - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_AzureStoragePutBlock, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle, uint32_t, blockNumber, const uint8_t*, dataPtr, size_t, dataSize); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_AzureStoragePutBlock, IOTHUB_CLIENT_AZURE_STORAGE_CLIENT_HANDLE, azureStorageClientHandle, uint32_t, blockNumber, const uint8_t*, dataPtr, size_t, dataSize); /** * @brief This API performs an Azure Storage PUT BLOCK LIST operation. * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. * This function is expected to be used along with: - * `IoTHubDeviceClient_CreateUploadContext` + * `IoTHubDeviceClient_AzureStorageCreateClient` * `IoTHubDeviceClient_AzureStoragePutBlock` * `IoTHubDeviceClient_AzureStoragePutBlockList` - * `IoTHubDeviceClient_DestroyUploadContext` + * `IoTHubDeviceClient_AzureStorageDestroyClient` * `IoTHubDeviceClient_InitializeUpload` * `IoTHubDeviceClient_NotifyUploadCompletion` - * For the standard less-granular uploads to blob please use either + * For simpler/less-granular control of uploads to Azure blob storage please use either * `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`. * If this function fails (due to any HTTP error to Azure Storage) it can * be run again for a discretionary number of times in an attempt to succeed after, for example, @@ -441,52 +447,52 @@ extern "C" * For more information about Azure Storage PUT BLOCK LIST, please refer to * https://learn.microsoft.com/en-us/rest/api/storageservices/put-block-list * - * @param uploadContextHandle The handle created with `IoTHubDeviceClient_CreateUploadContext`. + * @param azureStorageClientHandle The handle created with `IoTHubDeviceClient_AzureStorageCreateClient`. * * @warning This is a synchronous/blocking function. * * @return IOTHUB_CLIENT_OK upon success or an error code upon failure. */ - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_AzureStoragePutBlockList, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_AzureStoragePutBlockList, IOTHUB_CLIENT_AZURE_STORAGE_CLIENT_HANDLE, azureStorageClientHandle); /** - * @brief This API destroy a blob upload context previously created with `IoTHubDeviceClient_CreateUploadContext`. + * @brief This API destroys an instance previously created with `IoTHubDeviceClient_AzureStorageCreateClient`. * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. * This function is expected to be used along with: - * `IoTHubDeviceClient_CreateUploadContext` + * `IoTHubDeviceClient_AzureStorageCreateClient` * `IoTHubDeviceClient_AzureStoragePutBlock` * `IoTHubDeviceClient_AzureStoragePutBlockList` - * `IoTHubDeviceClient_DestroyUploadContext` + * `IoTHubDeviceClient_AzureStorageDestroyClient` * `IoTHubDeviceClient_InitializeUpload` * `IoTHubDeviceClient_NotifyUploadCompletion` - * For the standard less-granular uploads to blob please use either + * For simpler/less-granular control of uploads to Azure blob storage please use either * `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`. * - * @param uploadContextHandle The handle created with `IoTHubDeviceClient_CreateUploadContext`. + * @param azureStorageClientHandle The handle created with `IoTHubDeviceClient_AzureStorageCreateClient`. * * @warning This is a synchronous/blocking function. * * @return Nothing. */ - MOCKABLE_FUNCTION(, void, IoTHubDeviceClient_DestroyUploadContext, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle); + MOCKABLE_FUNCTION(, void, IoTHubDeviceClient_AzureStorageDestroyClient, IOTHUB_CLIENT_AZURE_STORAGE_CLIENT_HANDLE, azureStorageClientHandle); /** * @brief This API notifies Azure IoT Hub of the upload completion. * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. * This function is expected to be used along with: - * `IoTHubDeviceClient_CreateUploadContext` + * `IoTHubDeviceClient_AzureStorageCreateClient` * `IoTHubDeviceClient_AzureStoragePutBlock` * `IoTHubDeviceClient_AzureStoragePutBlockList` - * `IoTHubDeviceClient_DestroyUploadContext` + * `IoTHubDeviceClient_AzureStorageDestroyClient` * `IoTHubDeviceClient_InitializeUpload` * `IoTHubDeviceClient_NotifyUploadCompletion` - * For the standard less-granular uploads to blob please use either + * For simpler/less-granular control of uploads to Azure blob storage please use either * `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`. * If this function fails (due to any HTTP error to either Azure Storage or Azure IoT Hub) it can * be run again for a discretionary number of times in an attempt to succeed after, for example, * an internet connectivity disruption is over. * - * @param uploadContextHandle The handle created with `IoTHubDeviceClient_CreateUploadContext`. + * @param azureStorageClientHandle The handle created with `IoTHubDeviceClient_AzureStorageCreateClient`. * @param uploadCorrelationId Upload correlation-id obtained with `IoTHubDeviceClient_InitializeUpload`. * @param isSuccess A boolean value indicating if the call(s) to `IoTHubDeviceClient_AzureStoragePutBlock` succeeded. * @param responseCode An user-defined code to signal the status of the upload (e.g., 200 for success, or -1 for abort). diff --git a/iothub_client/inc/iothub_device_client_ll.h b/iothub_client/inc/iothub_device_client_ll.h index cf80365224..c843c03d4f 100644 --- a/iothub_client/inc/iothub_device_client_ll.h +++ b/iothub_client/inc/iothub_device_client_ll.h @@ -48,6 +48,14 @@ extern "C" */ typedef struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA_TAG* IOTHUB_DEVICE_CLIENT_LL_HANDLE; +#ifndef DONT_USE_UPLOADTOBLOB +/** +* @brief Handle for Upload-to-Blob API Functions. +*/ +typedef IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IOTHUB_CLIENT_LL_AZURE_STORAGE_CLIENT_HANDLE; +#endif // DONT_USE_UPLOADTOBLOB + + /** * @brief Creates a IoT Hub client for communication with an existing @@ -385,8 +393,8 @@ typedef struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA_TAG* IOTHUB_DEVICE_CLIENT_LL_HA * This function is expected to be used along with: * `IoTHubDeviceClient_LL_AzureStoragePutBlock` * `IoTHubDeviceClient_LL_NotifyUploadCompletion` - * `IoTHubDeviceClient_LL_DestroyUploadContext` - * For the standard less-granular uploads to blob please use either + * `IoTHubDeviceClient_LL_AzureStorageDestroyClient` + * For simpler/less-granular control of uploads to Azure blob storage please use either * `IoTHubDeviceClient_LL_UploadToBlob` or `IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob`. * * @param iotHubClientHandle The handle created by a call to the create function. @@ -405,13 +413,13 @@ typedef struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA_TAG* IOTHUB_DEVICE_CLIENT_LL_HA MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_InitializeUpload, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, char**, uploadCorrelationId, char**, azureBlobSasUri); /** - * @brief This API creates a context for a new blob upload to Azure Storage. + * @brief This API creates a client for a new blob upload to Azure Storage. * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. * This function is expected to be used along with: * `IoTHubDeviceClient_LL_AzureStoragePutBlock` * `IoTHubDeviceClient_LL_NotifyUploadCompletion` - * `IoTHubDeviceClient_LL_DestroyUploadContext` - * For the standard less-granular uploads to blob please use either + * `IoTHubDeviceClient_LL_AzureStorageDestroyClient` + * For simpler/less-granular control of uploads to Azure blob storage please use either * `IoTHubDeviceClient_LL_UploadToBlob` or `IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob`. * * @param iotHubClientHandle The handle created by a call to the create function. @@ -419,23 +427,23 @@ typedef struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA_TAG* IOTHUB_DEVICE_CLIENT_LL_HA * * @warning This is a synchronous/blocking function. * - * @return A `IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE` on success or NULL if the function fails. + * @return A `IOTHUB_CLIENT_LL_AZURE_STORAGE_CLIENT_HANDLE` on success or NULL if the function fails. */ - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, IoTHubDeviceClient_LL_CreateUploadContext, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, azureBlobSasUri); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_AZURE_STORAGE_CLIENT_HANDLE, IoTHubDeviceClient_LL_AzureStorageCreateClient, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, azureBlobSasUri); /** * @brief This API uploads a single blob block to Azure Storage (performs a PUT BLOCK operation). * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. * This function is expected to be used along with: - * `IoTHubDeviceClient_LL_CreateUploadContext` + * `IoTHubDeviceClient_LL_AzureStorageCreateClient` * `IoTHubDeviceClient_LL_NotifyUploadCompletion` - * `IoTHubDeviceClient_LL_DestroyUploadContext` - * For the standard less-granular uploads to blob please use either + * `IoTHubDeviceClient_LL_AzureStorageDestroyClient` + * For simpler/less-granular control of uploads to Azure blob storage please use either * `IoTHubDeviceClient_LL_UploadToBlob` or `IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob`. * For more information about Azure Storage PUT BLOCK, its parameters and behavior, please refer to * https://learn.microsoft.com/en-us/rest/api/storageservices/put-block * - * @param uploadContextHandle The handle created with `IoTHubDeviceClient_LL_CreateUploadContext`. + * @param azureStorageClientHandle The handle created with `IoTHubDeviceClient_LL_AzureStorageCreateClient`. * @param blockNumber Number of the block being uploaded. * @param dataPtr Pointer to the block data to be uploaded to Azure Storage blob. * @param dataSize Size of the block data pointed by `dataPtr`. @@ -446,21 +454,21 @@ typedef struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA_TAG* IOTHUB_DEVICE_CLIENT_LL_HA * * @return IOTHUB_CLIENT_OK upon success or an error code upon failure. */ - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_AzureStoragePutBlock, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle, uint32_t, blockNumber, const uint8_t*, dataPtr, size_t, dataSize); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_AzureStoragePutBlock, IOTHUB_CLIENT_LL_AZURE_STORAGE_CLIENT_HANDLE, azureStorageClientHandle, uint32_t, blockNumber, const uint8_t*, dataPtr, size_t, dataSize); /** * @brief This API performs an Azure Storage PUT BLOCK LIST operation. * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. * This function is expected to be used along with: - * `IoTHubDeviceClient_LL_CreateUploadContext` + * `IoTHubDeviceClient_LL_AzureStorageCreateClient` * `IoTHubDeviceClient_LL_NotifyUploadCompletion` - * `IoTHubDeviceClient_LL_DestroyUploadContext` - * For the standard less-granular uploads to blob please use either + * `IoTHubDeviceClient_LL_AzureStorageDestroyClient` + * For simpler/less-granular control of uploads to Azure blob storage please use either * `IoTHubDeviceClient_LL_UploadToBlob` or `IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob`. * For more information about Azure Storage PUT BLOCK LIST, please refer to * https://learn.microsoft.com/en-us/rest/api/storageservices/put-block-list * - * @param uploadContextHandle The handle created with `IoTHubDeviceClient_LL_CreateUploadContext`. + * @param azureStorageClientHandle The handle created with `IoTHubDeviceClient_LL_AzureStorageCreateClient`. * * @warning This is a synchronous/blocking function. * This function only attempts to send HTTP requests once, it does not retry in case of failure. @@ -468,40 +476,40 @@ typedef struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA_TAG* IOTHUB_DEVICE_CLIENT_LL_HA * * @return IOTHUB_CLIENT_OK upon success or an error code upon failure. */ - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_AzureStoragePutBlockList, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_AzureStoragePutBlockList, IOTHUB_CLIENT_LL_AZURE_STORAGE_CLIENT_HANDLE, azureStorageClientHandle); /** - * @brief This API destroy a blob upload context previously created with `IoTHubDeviceClient_LL_CreateUploadContext` . + * @brief This API destroys an instance previously created with `IoTHubDeviceClient_LL_AzureStorageCreateClient` . * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. * This function is expected to be used along with: - * `IoTHubDeviceClient_LL_CreateUploadContext` + * `IoTHubDeviceClient_LL_AzureStorageCreateClient` * `IoTHubDeviceClient_LL_AzureStoragePutBlock` * `IoTHubDeviceClient_LL_NotifyUploadCompletion` - * For the standard less-granular uploads to blob please use either + * For simpler/less-granular control of uploads to Azure blob storage please use either * `IoTHubDeviceClient_LL_UploadToBlob` or `IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob`. * - * @param uploadContextHandle The handle created with `IoTHubDeviceClient_LL_CreateUploadContext`. + * @param azureStorageClientHandle The handle created with `IoTHubDeviceClient_LL_AzureStorageCreateClient`. * * @warning This is a synchronous/blocking function. * * @return Nothing. */ - MOCKABLE_FUNCTION(, void, IoTHubDeviceClient_LL_DestroyUploadContext, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContextHandle); + MOCKABLE_FUNCTION(, void, IoTHubDeviceClient_LL_AzureStorageDestroyClient, IOTHUB_CLIENT_LL_AZURE_STORAGE_CLIENT_HANDLE, azureStorageClientHandle); /** * @brief This API notifies Azure IoT Hub of the upload completion. * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. * This function is expected to be used along with: - * `IoTHubDeviceClient_LL_CreateUploadContext` + * `IoTHubDeviceClient_LL_AzureStorageCreateClient` * `IoTHubDeviceClient_LL_AzureStoragePutBlock` - * `IoTHubDeviceClient_LL_DestroyUploadContext` - * For the standard less-granular uploads to blob please use either + * `IoTHubDeviceClient_LL_AzureStorageDestroyClient` + * For simpler/less-granular control of uploads to Azure blob storage please use either * `IoTHubDeviceClient_LL_UploadToBlob` or `IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob`. * If this function fails (due to any HTTP error to either Azure Storage or Azure IoT Hub) it can * be run again for a discretionary number of times in an attempt to succeed after, for example, * an internet connectivity disruption is over. * - * @param uploadContextHandle The handle created with `IoTHubDeviceClient_LL_CreateUploadContext`. + * @param azureStorageClientHandle The handle created with `IoTHubDeviceClient_LL_AzureStorageCreateClient`. * @param uploadCorrelationId Upload correlation-id obtained with `IoTHubDeviceClient_LL_InitializeUpload`. * @param isSuccess A boolean value indicating if the call(s) to `IoTHubDeviceClient_LL_AzureStoragePutBlock` succeeded. * @param responseCode An user-defined code to signal the status of the upload (e.g., 200 for success, or -1 for abort). diff --git a/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c b/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c index 013387e920..377d59ff90 100644 --- a/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c +++ b/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c @@ -5,8 +5,6 @@ // Checking of return codes and error values shall be omitted for brevity. Please practice sound engineering practices // when writing production code. -#ifndef DONT_USE_UPLOADTOBLOB - #include #include @@ -89,9 +87,9 @@ int main(void) } else { - IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle = IoTHubDeviceClient_LL_CreateUploadContext(device_ll_handle, azureBlobSasUri); + IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE azureStorageClientHandle = IoTHubDeviceClient_LL_AzureStorageCreateClient(device_ll_handle, azureBlobSasUri); - if (uploadContextHandle == NULL) + if (azureStorageClientHandle == NULL) { (void)printf("failed to create upload context\n"); } @@ -110,7 +108,7 @@ int main(void) while (true) { if (IoTHubDeviceClient_LL_AzureStoragePutBlock( - uploadContextHandle, block_number, (const uint8_t*)data_to_upload, data_size) == IOTHUB_CLIENT_OK) + azureStorageClientHandle, block_number, (const uint8_t*)data_to_upload, data_size) == IOTHUB_CLIENT_OK) { // Block upload succeeded. Continuing with next block. break; @@ -137,7 +135,7 @@ int main(void) if (uploadSuccessful) { - if (IoTHubDeviceClient_LL_AzureStoragePutBlockList(uploadContextHandle) != IOTHUB_CLIENT_OK) + if (IoTHubDeviceClient_LL_AzureStoragePutBlockList(azureStorageClientHandle) != IOTHUB_CLIENT_OK) { (void)printf("Failed performing Azure Storage Put Blob List.\n"); uploadSuccessful = false; @@ -145,7 +143,7 @@ int main(void) } } - IoTHubDeviceClient_LL_DestroyUploadContext(uploadContextHandle); + IoTHubDeviceClient_LL_AzureStorageDestroyClient(azureStorageClientHandle); attemptCount = 1; @@ -195,4 +193,4 @@ int main(void) return 0; } -#endif /*DONT_USE_UPLOADTOBLOB*/ + diff --git a/iothub_client/src/iothub_client_core.c b/iothub_client/src/iothub_client_core.c index 3d04f0daf8..6da8b7216e 100644 --- a/iothub_client/src/iothub_client_core.c +++ b/iothub_client/src/iothub_client_core.c @@ -2503,7 +2503,7 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_InitializeUpload(IOTHUB_CLIENT_CORE_HANDLE return result; } -IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubClientCore_CreateUploadContext(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, const char* azureBlobSasUri) +IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubClientCore_AzureStorageCreateClient(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, const char* azureBlobSasUri) { IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE result; @@ -2514,25 +2514,25 @@ IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubClientCore_CreateUploadContex } else { - result = IoTHubClientCore_LL_CreateUploadContext(iotHubClientHandle->IoTHubClientLLHandle, azureBlobSasUri); + result = IoTHubClientCore_LL_AzureStorageCreateClient(iotHubClientHandle->IoTHubClientLLHandle, azureBlobSasUri); } return result; } -IOTHUB_CLIENT_RESULT IoTHubClientCore_AzureStoragePutBlock(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle, uint32_t blockNumber, const uint8_t* dataPtr, size_t dataSize) +IOTHUB_CLIENT_RESULT IoTHubClientCore_AzureStoragePutBlock(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE azureStorageClientHandle, uint32_t blockNumber, const uint8_t* dataPtr, size_t dataSize) { - return IoTHubClientCore_LL_AzureStoragePutBlock(uploadContextHandle, blockNumber, dataPtr, dataSize); + return IoTHubClientCore_LL_AzureStoragePutBlock(azureStorageClientHandle, blockNumber, dataPtr, dataSize); } -IOTHUB_CLIENT_RESULT IoTHubClientCore_AzureStoragePutBlockList(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle) +IOTHUB_CLIENT_RESULT IoTHubClientCore_AzureStoragePutBlockList(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE azureStorageClientHandle) { - return IoTHubClientCore_LL_AzureStoragePutBlockList(uploadContextHandle); + return IoTHubClientCore_LL_AzureStoragePutBlockList(azureStorageClientHandle); } -void IoTHubClientCore_DestroyUploadContext(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle) +void IoTHubClientCore_AzureStorageDestroyClient(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE azureStorageClientHandle) { - IoTHubClientCore_LL_DestroyUploadContext(uploadContextHandle); + IoTHubClientCore_LL_AzureStorageDestroyClient(azureStorageClientHandle); } IOTHUB_CLIENT_RESULT IoTHubClientCore_NotifyUploadCompletion(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, const char* uploadCorrelationId, bool isSuccess, int responseCode, const char* responseMessage) diff --git a/iothub_client/src/iothub_client_core_ll.c b/iothub_client/src/iothub_client_core_ll.c index 2c2baae07d..e8ed0ab526 100755 --- a/iothub_client/src/iothub_client_core_ll.c +++ b/iothub_client/src/iothub_client_core_ll.c @@ -2952,7 +2952,7 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_InitializeUpload(IOTHUB_CLIENT_CORE_LL_ return result; } -IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubClientCore_LL_CreateUploadContext(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, const char* azureBlobSasUri) +IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubClientCore_LL_AzureStorageCreateClient(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, const char* azureBlobSasUri) { IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE result; if ( @@ -2971,39 +2971,39 @@ IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubClientCore_LL_CreateUploadCon return result; } -IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_AzureStoragePutBlock(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle, uint32_t blockNumber, const uint8_t* dataPtr, size_t dataSize) +IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_AzureStoragePutBlock(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE azureStorageClientHandle, uint32_t blockNumber, const uint8_t* dataPtr, size_t dataSize) { IOTHUB_CLIENT_RESULT result; if ( - (uploadContextHandle == NULL) || + (azureStorageClientHandle == NULL) || (dataPtr == NULL) || (dataSize == 0) ) { - LogError("invalid parameters uploadContextHandle=%p, dataPtr=%p, dataSize=%zu", uploadContextHandle, dataPtr, dataSize); + LogError("invalid parameters azureStorageClientHandle=%p, dataPtr=%p, dataSize=%zu", azureStorageClientHandle, dataPtr, dataSize); result = IOTHUB_CLIENT_INVALID_ARG; } else { - result = IoTHubClient_LL_UploadToBlob_PutBlock(uploadContextHandle, blockNumber, dataPtr, dataSize); + result = IoTHubClient_LL_UploadToBlob_PutBlock(azureStorageClientHandle, blockNumber, dataPtr, dataSize); } return result; } -IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_AzureStoragePutBlockList(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle) +IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_AzureStoragePutBlockList(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE azureStorageClientHandle) { IOTHUB_CLIENT_RESULT result; - if (uploadContextHandle == NULL) + if (azureStorageClientHandle == NULL) { - LogError("invalid parameter uploadContextHandle=%p", uploadContextHandle); + LogError("invalid parameter azureStorageClientHandle=%p", azureStorageClientHandle); result = IOTHUB_CLIENT_INVALID_ARG; } else { - result = IoTHubClient_LL_UploadToBlob_PutBlockList(uploadContextHandle); + result = IoTHubClient_LL_UploadToBlob_PutBlockList(azureStorageClientHandle); } return result; @@ -3026,11 +3026,11 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_NotifyUploadCompletion(IOTHUB_CLIENT_CO return result; } -void IoTHubClientCore_LL_DestroyUploadContext(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle) +void IoTHubClientCore_LL_AzureStorageDestroyClient(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE azureStorageClientHandle) { - if (uploadContextHandle != NULL) + if (azureStorageClientHandle != NULL) { - IoTHubClient_LL_UploadToBlob_DestroyContext(uploadContextHandle); + IoTHubClient_LL_UploadToBlob_DestroyContext(azureStorageClientHandle); } } #endif // DONT_USE_UPLOADTOBLOB diff --git a/iothub_client/src/iothub_client_ll_uploadtoblob.c b/iothub_client/src/iothub_client_ll_uploadtoblob.c index b47a20f00a..31d3786cf5 100644 --- a/iothub_client/src/iothub_client_ll_uploadtoblob.c +++ b/iothub_client/src/iothub_client_ll_uploadtoblob.c @@ -1108,13 +1108,13 @@ IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_NotifyCompletion(IOTHUB_CLIENT return result; } -IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX getDataCallbackEx, void* context) +IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE azureStorageClientHandle, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX getDataCallbackEx, void* context) { IOTHUB_CLIENT_RESULT result; - if (uploadContextHandle == NULL || getDataCallbackEx == NULL) + if (azureStorageClientHandle == NULL || getDataCallbackEx == NULL) { - LogError("invalid argument detected uploadContextHandle=%p getDataCallbackEx=%p", uploadContextHandle, getDataCallbackEx); + LogError("invalid argument detected azureStorageClientHandle=%p getDataCallbackEx=%p", azureStorageClientHandle, getDataCallbackEx); result = IOTHUB_CLIENT_INVALID_ARG; } else @@ -1156,7 +1156,7 @@ IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(IOTHUB_CL isError = true; break; } - else if (IoTHubClient_LL_UploadToBlob_PutBlock(uploadContextHandle, blockID, blockDataPtr, blockDataSize) != IOTHUB_CLIENT_OK) + else if (IoTHubClient_LL_UploadToBlob_PutBlock(azureStorageClientHandle, blockID, blockDataPtr, blockDataSize) != IOTHUB_CLIENT_OK) { LogError("failed uploading block to blob"); isError = true; @@ -1177,7 +1177,7 @@ IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(IOTHUB_CL // be attempted if at least one block has indeed been uploaded to Azure Storage. // This behavior follows the behavior of the original implementation of // Upload-to-Blob in azure-iot-sdk-c. - else if (blockID > 0 && IoTHubClient_LL_UploadToBlob_PutBlockList(uploadContextHandle) != IOTHUB_CLIENT_OK) + else if (blockID > 0 && IoTHubClient_LL_UploadToBlob_PutBlockList(azureStorageClientHandle) != IOTHUB_CLIENT_OK) { LogError("Failed to perform Azure Blob Put Block List operation"); (void)getDataCallbackEx(FILE_UPLOAD_ERROR, NULL, NULL, context); diff --git a/iothub_client/src/iothub_device_client.c b/iothub_client/src/iothub_device_client.c index 25f4ee8a3c..d92e69d293 100644 --- a/iothub_client/src/iothub_device_client.c +++ b/iothub_client/src/iothub_device_client.c @@ -120,24 +120,24 @@ IOTHUB_CLIENT_RESULT IoTHubDeviceClient_InitializeUpload(IOTHUB_DEVICE_CLIENT_HA return IoTHubClientCore_InitializeUpload((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, destinationFileName, uploadCorrelationId, azureBlobSasUri); } -IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubDeviceClient_CreateUploadContext(IOTHUB_DEVICE_CLIENT_HANDLE iotHubClientHandle, const char* azureBlobSasUri) +IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubDeviceClient_AzureStorageCreateClient(IOTHUB_DEVICE_CLIENT_HANDLE iotHubClientHandle, const char* azureBlobSasUri) { - return IoTHubClientCore_CreateUploadContext((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, azureBlobSasUri); + return IoTHubClientCore_AzureStorageCreateClient((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, azureBlobSasUri); } -IOTHUB_CLIENT_RESULT IoTHubDeviceClient_AzureStoragePutBlock(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle, uint32_t blockNumber, const uint8_t* dataPtr, size_t dataSize) +IOTHUB_CLIENT_RESULT IoTHubDeviceClient_AzureStoragePutBlock(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE azureStorageClientHandle, uint32_t blockNumber, const uint8_t* dataPtr, size_t dataSize) { - return IoTHubClientCore_AzureStoragePutBlock(uploadContextHandle, blockNumber, dataPtr, dataSize); + return IoTHubClientCore_AzureStoragePutBlock(azureStorageClientHandle, blockNumber, dataPtr, dataSize); } -IOTHUB_CLIENT_RESULT IoTHubDeviceClient_AzureStoragePutBlockList(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle) +IOTHUB_CLIENT_RESULT IoTHubDeviceClient_AzureStoragePutBlockList(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE azureStorageClientHandle) { - return IoTHubClientCore_AzureStoragePutBlockList(uploadContextHandle); + return IoTHubClientCore_AzureStoragePutBlockList(azureStorageClientHandle); } -void IoTHubDeviceClient_DestroyUploadContext(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle) +void IoTHubDeviceClient_AzureStorageDestroyClient(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE azureStorageClientHandle) { - IoTHubClientCore_DestroyUploadContext(uploadContextHandle); + IoTHubClientCore_AzureStorageDestroyClient(azureStorageClientHandle); } IOTHUB_CLIENT_RESULT IoTHubDeviceClient_NotifyUploadCompletion(IOTHUB_DEVICE_CLIENT_HANDLE iotHubClientHandle, const char* uploadCorrelationId, bool isSuccess, int responseCode, const char* responseMessage) diff --git a/iothub_client/src/iothub_device_client_ll.c b/iothub_client/src/iothub_device_client_ll.c index e2f87fd2b4..1b6dcda8bf 100644 --- a/iothub_client/src/iothub_device_client_ll.c +++ b/iothub_client/src/iothub_device_client_ll.c @@ -142,24 +142,24 @@ IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_InitializeUpload(IOTHUB_DEVICE_CLIENT return IoTHubClientCore_LL_InitializeUpload((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, destinationFileName, uploadCorrelationId, azureBlobSasUri); } -IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubDeviceClient_LL_CreateUploadContext(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, const char* azureBlobSasUri) +IOTHUB_CLIENT_LL_AZURE_STORAGE_CLIENT_HANDLE IoTHubDeviceClient_LL_AzureStorageCreateClient(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, const char* azureBlobSasUri) { - return IoTHubClientCore_LL_CreateUploadContext((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, azureBlobSasUri); + return IoTHubClientCore_LL_AzureStorageCreateClient((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, azureBlobSasUri); } -IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_AzureStoragePutBlock(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle, uint32_t blockNumber, const uint8_t* dataPtr, size_t dataSize) +IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_AzureStoragePutBlock(IOTHUB_CLIENT_LL_AZURE_STORAGE_CLIENT_HANDLE azureStorageClientHandle, uint32_t blockNumber, const uint8_t* dataPtr, size_t dataSize) { - return IoTHubClientCore_LL_AzureStoragePutBlock(uploadContextHandle, blockNumber, dataPtr, dataSize); + return IoTHubClientCore_LL_AzureStoragePutBlock(azureStorageClientHandle, blockNumber, dataPtr, dataSize); } -IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_AzureStoragePutBlockList(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle) +IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_AzureStoragePutBlockList(IOTHUB_CLIENT_LL_AZURE_STORAGE_CLIENT_HANDLE azureStorageClientHandle) { - return IoTHubClientCore_LL_AzureStoragePutBlockList(uploadContextHandle); + return IoTHubClientCore_LL_AzureStoragePutBlockList(azureStorageClientHandle); } -void IoTHubDeviceClient_LL_DestroyUploadContext(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContextHandle) +void IoTHubDeviceClient_LL_AzureStorageDestroyClient(IOTHUB_CLIENT_LL_AZURE_STORAGE_CLIENT_HANDLE azureStorageClientHandle) { - IoTHubClientCore_LL_DestroyUploadContext(uploadContextHandle); + IoTHubClientCore_LL_AzureStorageDestroyClient(azureStorageClientHandle); } IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_NotifyUploadCompletion(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, const char* uploadCorrelationId, bool isSuccess, int responseCode, const char* responseMessage) From 48e7fceb2b34423104b02c644eefe55a3b05904a Mon Sep 17 00:00:00 2001 From: Ewerton Scaboro da Silva Date: Wed, 19 Jul 2023 22:32:55 -0700 Subject: [PATCH 25/27] Verify and log http response status code in u2b functions --- ...thub_client_sample_upload_to_blob_custom.c | 1 + iothub_client/src/blob.c | 58 ++++++++++++------- .../src/iothub_client_ll_uploadtoblob.c | 2 +- 3 files changed, 40 insertions(+), 21 deletions(-) diff --git a/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c b/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c index 377d59ff90..dbe38e472f 100644 --- a/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c +++ b/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c @@ -135,6 +135,7 @@ int main(void) if (uploadSuccessful) { + // This function can also be retried if any errors occur. if (IoTHubDeviceClient_LL_AzureStoragePutBlockList(azureStorageClientHandle) != IOTHUB_CLIENT_OK) { (void)printf("Failed performing Azure Storage Put Blob List.\n"); diff --git a/iothub_client/src/blob.c b/iothub_client/src/blob.c index 1a8fd470c1..7ac5735c28 100644 --- a/iothub_client/src/blob.c +++ b/iothub_client/src/blob.c @@ -25,6 +25,9 @@ static const char blockListLatestTagXmlEnd[] = ""; // Length of the string representation of an Azure Blob Block ID (enough to represent "049999"). #define AZURE_BLOB_BLOCK_ID_LENGTH 6 +#define IS_HTTP_STATUS_CODE_SUCCESS(x) ((x) >= 100 && (x) < 300) + + static STRING_HANDLE createBlockIdListXml(SINGLYLINKEDLIST_HANDLE blockIDList) { STRING_HANDLE blockIdListXml; @@ -206,18 +209,20 @@ BLOB_RESULT Blob_PutBlock( } else { + unsigned int httpResponseStatusCode = 0; + if (HTTPAPIEX_ExecuteRequest( - httpApiExHandle, - HTTPAPI_REQUEST_PUT, - STRING_c_str(newRelativePath), - NULL, - blockData, - httpStatus, - NULL, - httpResponse) != HTTPAPIEX_OK - ) + httpApiExHandle, + HTTPAPI_REQUEST_PUT, + STRING_c_str(newRelativePath), + NULL, + blockData, + &httpResponseStatusCode, + NULL, + httpResponse) != HTTPAPIEX_OK || + !IS_HTTP_STATUS_CODE_SUCCESS(httpResponseStatusCode)) { - LogError("unable to HTTPAPIEX_ExecuteRequest"); + LogError("unable to HTTPAPIEX_ExecuteRequest (HTTP response status %u)", httpResponseStatusCode); (void)singlylinkedlist_remove(blockIDList, newListItem); STRING_delete(blockIdEncodedString); result = BLOB_HTTP_ERROR; @@ -226,6 +231,11 @@ BLOB_RESULT Blob_PutBlock( { result = BLOB_OK; } + + if (httpStatus != NULL) + { + *httpStatus = httpResponseStatusCode; + } } STRING_delete(newRelativePath); @@ -311,18 +321,20 @@ BLOB_RESULT Blob_PutBlockList( } else { + unsigned int httpResponseStatusCode = 0; + if (HTTPAPIEX_ExecuteRequest( - httpApiExHandle, - HTTPAPI_REQUEST_PUT, - STRING_c_str(newRelativePath), - NULL, - blockIDListAsBuffer, - httpStatus, - NULL, - httpResponse - ) != HTTPAPIEX_OK) + httpApiExHandle, + HTTPAPI_REQUEST_PUT, + STRING_c_str(newRelativePath), + NULL, + blockIDListAsBuffer, + &httpResponseStatusCode, + NULL, + httpResponse) != HTTPAPIEX_OK || + !IS_HTTP_STATUS_CODE_SUCCESS(httpResponseStatusCode)) { - LogError("unable to HTTPAPIEX_ExecuteRequest"); + LogError("unable to HTTPAPIEX_ExecuteRequest (HTTP response status %u)", httpResponseStatusCode); result = BLOB_HTTP_ERROR; } else @@ -330,6 +342,12 @@ BLOB_RESULT Blob_PutBlockList( (void)singlylinkedlist_remove_if(blockIDList, removeAndDestroyBlockIdInList, NULL); result = BLOB_OK; } + + if (httpStatus != NULL) + { + *httpStatus = httpResponseStatusCode; + } + BUFFER_delete(blockIDListAsBuffer); } } diff --git a/iothub_client/src/iothub_client_ll_uploadtoblob.c b/iothub_client/src/iothub_client_ll_uploadtoblob.c index 31d3786cf5..03a3d7fe22 100644 --- a/iothub_client/src/iothub_client_ll_uploadtoblob.c +++ b/iothub_client/src/iothub_client_ll_uploadtoblob.c @@ -157,7 +157,7 @@ static int send_http_request(HTTPAPIEX_HANDLE http_api_handle, const char* relat } else if (!IS_HTTP_STATUS_CODE_SUCCESS(statusCode)) { - LogError("HTTP code was %u", statusCode); + LogError("HTTP failed response code was %u", statusCode); result = MU_FAILURE; } else From a31dacb8f8d5307944cc69d3c4ee6ef2c7bc7f07 Mon Sep 17 00:00:00 2001 From: Ewerton Scaboro da Silva Date: Wed, 19 Jul 2023 23:26:29 -0700 Subject: [PATCH 26/27] Update blob_ut --- iothub_client/tests/blob_ut/blob_ut.c | 118 ++++++++++++++++++++++---- 1 file changed, 102 insertions(+), 16 deletions(-) diff --git a/iothub_client/tests/blob_ut/blob_ut.c b/iothub_client/tests/blob_ut/blob_ut.c index cccec68e83..533efde228 100644 --- a/iothub_client/tests/blob_ut/blob_ut.c +++ b/iothub_client/tests/blob_ut/blob_ut.c @@ -50,7 +50,10 @@ static void my_gballoc_free(void* s) #define TEST_LIST_ITEM_HANDLE (LIST_ITEM_HANDLE)0x4446 #define TEST_STRING_HANDLE (STRING_HANDLE)0x4447 #define HTTP_OK 200 -#define HTTP_NOT_FOUND 404 +#define HTTP_UNAUTHORIZED 401 + +const unsigned int HTTP_STATUS_200 = HTTP_OK; +const unsigned int HTTP_STATUS_401 = HTTP_UNAUTHORIZED; TEST_DEFINE_ENUM_TYPE(HTTPAPI_REQUEST_TYPE, HTTPAPI_REQUEST_TYPE_VALUES); IMPLEMENT_UMOCK_C_ENUM_TYPE(HTTPAPI_REQUEST_TYPE, HTTPAPI_REQUEST_TYPE_VALUES); @@ -107,10 +110,6 @@ static void on_umock_c_error(UMOCK_C_ERROR_CODE error_code) ASSERT_FAIL(temp_str); } -static BUFFER_HANDLE testValidBufferHandle; /*assigned in TEST_SUITE_INITIALIZE*/ -static const unsigned int TwoHundred = HTTP_OK; -static const unsigned int FourHundredFour = HTTP_NOT_FOUND; - // Allocate test content during initial test setup only. This buffer is very large, // which means significant performance degradation on Valgrind tests if we were to // allocate and free it per individual test-case. @@ -172,9 +171,6 @@ TEST_SUITE_INITIALIZE(TestSuiteInitialize) REGISTER_TYPE(HTTPAPIEX_RESULT, HTTPAPIEX_RESULT); REGISTER_TYPE(HTTP_HEADERS_RESULT, HTTP_HEADERS_RESULT); - testValidBufferHandle = BUFFER_create((const unsigned char*)"a", 1); - ASSERT_IS_NOT_NULL(testValidBufferHandle); - testUploadToBlobContent = gballoc_malloc(testUploadToBlobContentMaxSize); ASSERT_IS_NOT_NULL(testUploadToBlobContent); @@ -183,8 +179,6 @@ TEST_SUITE_INITIALIZE(TestSuiteInitialize) TEST_SUITE_CLEANUP(TestClassCleanup) { - - BUFFER_delete(testValidBufferHandle); gballoc_free(testUploadToBlobContent); umock_c_deinit(); @@ -371,7 +365,8 @@ TEST_FUNCTION(Blob_PutBlock_happy_path_succeeds) STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) .CallCannotFail(); STRICT_EXPECTED_CALL(HTTPAPIEX_ExecuteRequest( - TEST_HTTPAPIEX_HANDLE, HTTPAPI_REQUEST_PUT, IGNORED_PTR_ARG, IGNORED_PTR_ARG, blockData, &responseHttpStatus, IGNORED_PTR_ARG, responseContent)); + TEST_HTTPAPIEX_HANDLE, HTTPAPI_REQUEST_PUT, IGNORED_PTR_ARG, IGNORED_PTR_ARG, blockData, IGNORED_PTR_ARG, IGNORED_PTR_ARG, responseContent)) + .CopyOutArgumentBuffer_statusCode(&HTTP_STATUS_200, sizeof(unsigned int)); STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); ///act @@ -385,6 +380,42 @@ TEST_FUNCTION(Blob_PutBlock_happy_path_succeeds) ///cleanup } +TEST_FUNCTION(Blob_PutBlock_401_fails) +{ + ///arrange + unsigned int blockId = 0; + BUFFER_HANDLE blockData = TEST_BUFFER_HANDLE; + SINGLYLINKEDLIST_HANDLE blockIdList = TEST_SINGLYLINKEDLIST_HANDLE; + unsigned int responseHttpStatus = 0; + BUFFER_HANDLE responseContent = TEST_BUFFER_HANDLE; + + umock_c_reset_all_calls(); + STRICT_EXPECTED_CALL(Azure_Base64_Encode_Bytes(IGNORED_PTR_ARG, 6)); + STRICT_EXPECTED_CALL(singlylinkedlist_add(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_construct(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_concat_with_STRING(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) + .CallCannotFail(); + STRICT_EXPECTED_CALL(HTTPAPIEX_ExecuteRequest( + TEST_HTTPAPIEX_HANDLE, HTTPAPI_REQUEST_PUT, IGNORED_PTR_ARG, IGNORED_PTR_ARG, blockData, IGNORED_PTR_ARG, IGNORED_PTR_ARG, responseContent)) + .CopyOutArgumentBuffer_statusCode(&HTTP_STATUS_401, sizeof(unsigned int)); + STRICT_EXPECTED_CALL(singlylinkedlist_remove(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); + + ///act + BLOB_RESULT result = Blob_PutBlock( + TEST_HTTPAPIEX_HANDLE, TEST_RELATIVE_PATH_1, blockId, blockData, blockIdList, &responseHttpStatus, responseContent); + + ///assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(int, BLOB_HTTP_ERROR, result); + ASSERT_ARE_EQUAL(int, HTTP_STATUS_401, responseHttpStatus); + + ///cleanup +} + TEST_FUNCTION(Blob_PutBlock_NULL_HTTPAPI_HANDLE_fails) { ///arrange @@ -490,7 +521,8 @@ TEST_FUNCTION(Blob_PutBlock_NULL_response_status_succeeds) STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) .CallCannotFail(); STRICT_EXPECTED_CALL(HTTPAPIEX_ExecuteRequest( - TEST_HTTPAPIEX_HANDLE, HTTPAPI_REQUEST_PUT, IGNORED_PTR_ARG, IGNORED_PTR_ARG, blockData, NULL, IGNORED_PTR_ARG, responseContent)); + TEST_HTTPAPIEX_HANDLE, HTTPAPI_REQUEST_PUT, IGNORED_PTR_ARG, IGNORED_PTR_ARG, blockData, NULL, IGNORED_PTR_ARG, responseContent)) + .CopyOutArgumentBuffer_statusCode(&HTTP_STATUS_200, sizeof(unsigned int)); STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); ///act @@ -522,7 +554,8 @@ TEST_FUNCTION(Blob_PutBlock_NULL_response_content_succeeds) STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) .CallCannotFail(); STRICT_EXPECTED_CALL(HTTPAPIEX_ExecuteRequest( - TEST_HTTPAPIEX_HANDLE, HTTPAPI_REQUEST_PUT, IGNORED_PTR_ARG, IGNORED_PTR_ARG, blockData, &responseHttpStatus, IGNORED_PTR_ARG, responseContent)); + TEST_HTTPAPIEX_HANDLE, HTTPAPI_REQUEST_PUT, IGNORED_PTR_ARG, IGNORED_PTR_ARG, blockData, IGNORED_PTR_ARG, IGNORED_PTR_ARG, responseContent)) + .CopyOutArgumentBuffer_statusCode(&HTTP_STATUS_200, sizeof(unsigned int)); STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); ///act @@ -605,7 +638,8 @@ TEST_FUNCTION(Blob_PutBlock_blockId_max_succeeds) STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)) .CallCannotFail(); STRICT_EXPECTED_CALL(HTTPAPIEX_ExecuteRequest( - TEST_HTTPAPIEX_HANDLE, HTTPAPI_REQUEST_PUT, IGNORED_PTR_ARG, IGNORED_PTR_ARG, blockData, &responseHttpStatus, IGNORED_PTR_ARG, responseContent)); + TEST_HTTPAPIEX_HANDLE, HTTPAPI_REQUEST_PUT, IGNORED_PTR_ARG, IGNORED_PTR_ARG, blockData, IGNORED_PTR_ARG, IGNORED_PTR_ARG, responseContent)) + .CopyOutArgumentBuffer_statusCode(&HTTP_STATUS_200, sizeof(unsigned int)); STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); ///act @@ -673,7 +707,8 @@ TEST_FUNCTION(Blob_PutBlockList_happy_path_succeeds) STRICT_EXPECTED_CALL(BUFFER_create(IGNORED_PTR_ARG, IGNORED_NUM_ARG)); STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(HTTPAPIEX_ExecuteRequest( - TEST_HTTPAPIEX_HANDLE, HTTPAPI_REQUEST_PUT, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, &responseHttpStatus, IGNORED_PTR_ARG, responseContent)); + TEST_HTTPAPIEX_HANDLE, HTTPAPI_REQUEST_PUT, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, responseContent)) + .CopyOutArgumentBuffer_statusCode(&HTTP_STATUS_200, sizeof(unsigned int)); STRICT_EXPECTED_CALL(singlylinkedlist_remove_if(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); @@ -690,6 +725,56 @@ TEST_FUNCTION(Blob_PutBlockList_happy_path_succeeds) ///cleanup } +TEST_FUNCTION(Blob_PutBlockList_401_fails) +{ + ///arrange + SINGLYLINKEDLIST_HANDLE blockIdList = TEST_SINGLYLINKEDLIST_HANDLE; + unsigned int responseHttpStatus = 0; + BUFFER_HANDLE responseContent = TEST_BUFFER_HANDLE; + + umock_c_reset_all_calls(); + STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); + // createBlockIdListXml(1 block) + STRICT_EXPECTED_CALL(STRING_construct(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(singlylinkedlist_item_get_value(IGNORED_PTR_ARG)) + .CallCannotFail() + .SetReturn(TEST_STRING_HANDLE); + STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_concat_with_STRING(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(singlylinkedlist_get_next_item(IGNORED_PTR_ARG)) + .CallCannotFail() + .SetReturn(NULL); + STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + // Back to Blob_PutBlockList + STRICT_EXPECTED_CALL(STRING_construct(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_concat(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_length(IGNORED_PTR_ARG)) + .CallCannotFail() + .SetReturn(100); + STRICT_EXPECTED_CALL(BUFFER_create(IGNORED_PTR_ARG, IGNORED_NUM_ARG)); + STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(HTTPAPIEX_ExecuteRequest( + TEST_HTTPAPIEX_HANDLE, HTTPAPI_REQUEST_PUT, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, responseContent)) + .CopyOutArgumentBuffer_statusCode(&HTTP_STATUS_401, sizeof(unsigned int)); + STRICT_EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); + + ///act + BLOB_RESULT result = Blob_PutBlockList( + TEST_HTTPAPIEX_HANDLE, TEST_RELATIVE_PATH_1, blockIdList, &responseHttpStatus, responseContent); + + ///assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_ARE_EQUAL(int, BLOB_HTTP_ERROR, result); + ASSERT_ARE_EQUAL(int, HTTP_STATUS_401, responseHttpStatus); + + ///cleanup +} + TEST_FUNCTION(Blob_PutBlockList_failure_checks) { ///arrange @@ -893,7 +978,8 @@ TEST_FUNCTION(Blob_PutBlockList_no_response_content_succeeds) STRICT_EXPECTED_CALL(BUFFER_create(IGNORED_PTR_ARG, IGNORED_NUM_ARG)); STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(HTTPAPIEX_ExecuteRequest( - TEST_HTTPAPIEX_HANDLE, HTTPAPI_REQUEST_PUT, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, &responseHttpStatus, IGNORED_PTR_ARG, NULL)); + TEST_HTTPAPIEX_HANDLE, HTTPAPI_REQUEST_PUT, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, NULL)) + .CopyOutArgumentBuffer_statusCode(&HTTP_STATUS_200, sizeof(unsigned int)); STRICT_EXPECTED_CALL(singlylinkedlist_remove_if(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); From 2db1cb9a15b69173eb6634a17fca6fc24c23b2e7 Mon Sep 17 00:00:00 2001 From: Ewerton Scaboro da Silva Date: Thu, 20 Jul 2023 11:57:30 -0700 Subject: [PATCH 27/27] Address final CR comments --- iothub_client/inc/iothub_device_client.h | 34 +++++++------- iothub_client/inc/iothub_device_client_ll.h | 20 ++++---- iothub_client/samples/CMakeLists.txt | 2 +- .../CMakeLists.txt | 46 ------------------- .../CMakeLists.txt | 46 +++++++++++++++++++ ...client_sample_upload_to_blob_with_retry.c} | 18 ++++++-- .../linux/CMakeLists.txt | 10 ++-- .../iothub_client_sample_upload_to_blob.sln | 0 ...othub_client_sample_upload_to_blob.vcxproj | 0 iothub_client/src/iothub_device_client.c | 4 +- iothub_client/src/iothub_device_client_ll.c | 4 +- .../iothubclient_uploadtoblob_e2e.c | 6 +-- 12 files changed, 98 insertions(+), 92 deletions(-) delete mode 100644 iothub_client/samples/iothub_client_sample_upload_to_blob_custom/CMakeLists.txt create mode 100644 iothub_client/samples/iothub_client_sample_upload_to_blob_with_retry/CMakeLists.txt rename iothub_client/samples/{iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c => iothub_client_sample_upload_to_blob_with_retry/iothub_client_sample_upload_to_blob_with_retry.c} (90%) rename iothub_client/samples/{iothub_client_sample_upload_to_blob_custom => iothub_client_sample_upload_to_blob_with_retry}/linux/CMakeLists.txt (58%) rename iothub_client/samples/{iothub_client_sample_upload_to_blob_custom => iothub_client_sample_upload_to_blob_with_retry}/windows/iothub_client_sample_upload_to_blob.sln (100%) rename iothub_client/samples/{iothub_client_sample_upload_to_blob_custom => iothub_client_sample_upload_to_blob_with_retry}/windows/iothub_client_sample_upload_to_blob.vcxproj (100%) diff --git a/iothub_client/inc/iothub_device_client.h b/iothub_client/inc/iothub_device_client.h index 56423b73be..9468ae4028 100644 --- a/iothub_client/inc/iothub_device_client.h +++ b/iothub_client/inc/iothub_device_client.h @@ -363,8 +363,8 @@ extern "C" * `IoTHubDeviceClient_AzureStoragePutBlock` * `IoTHubDeviceClient_AzureStoragePutBlockList` * `IoTHubDeviceClient_AzureStorageDestroyClient` - * `IoTHubDeviceClient_InitializeUpload` - * `IoTHubDeviceClient_NotifyUploadCompletion` + * `IoTHubDeviceClient_AzureStorageInitializeBlobUpload` + * `IoTHubDeviceClient_AzureStorageNotifyBlobUploadCompletion` * For simpler/less-granular control of uploads to Azure blob storage please use either * `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`. * @@ -375,11 +375,11 @@ extern "C" * * @warning This is a synchronous/blocking function. * `uploadCorrelationId` and `azureBlobSasUri` must be freed by the calling application - * after the blob upload process is done (e.g., after calling `IoTHubDeviceClient_NotifyUploadCompletion`). + * after the blob upload process is done (e.g., after calling `IoTHubDeviceClient_AzureStorageNotifyBlobUploadCompletion`). * * @return An IOTHUB_CLIENT_RESULT value indicating the success or failure of the API call. */ - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_InitializeUpload, IOTHUB_DEVICE_CLIENT_HANDLE, iotHubClientHandle, const char*, destinationFileName, char**, uploadCorrelationId, char**, azureBlobSasUri); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_AzureStorageInitializeBlobUpload, IOTHUB_DEVICE_CLIENT_HANDLE, iotHubClientHandle, const char*, destinationFileName, char**, uploadCorrelationId, char**, azureBlobSasUri); /** * @brief This API creates a client for a new blob upload to Azure Storage. @@ -389,13 +389,13 @@ extern "C" * `IoTHubDeviceClient_AzureStoragePutBlock` * `IoTHubDeviceClient_AzureStoragePutBlockList` * `IoTHubDeviceClient_AzureStorageDestroyClient` - * `IoTHubDeviceClient_InitializeUpload` - * `IoTHubDeviceClient_NotifyUploadCompletion` + * `IoTHubDeviceClient_AzureStorageInitializeBlobUpload` + * `IoTHubDeviceClient_AzureStorageNotifyBlobUploadCompletion` * For simpler/less-granular control of uploads to Azure blob storage please use either * `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`. * * @param iotHubClientHandle The handle created by a call to the create function. - * @param azureBlobSasUri The Azure Storage Blob SAS uri obtained with `IoTHubDeviceClient_InitializeUpload`. + * @param azureBlobSasUri The Azure Storage Blob SAS uri obtained with `IoTHubDeviceClient_AzureStorageInitializeBlobUpload`. * * @warning This is a synchronous/blocking function. * @@ -411,8 +411,8 @@ extern "C" * `IoTHubDeviceClient_AzureStoragePutBlock` * `IoTHubDeviceClient_AzureStoragePutBlockList` * `IoTHubDeviceClient_AzureStorageDestroyClient` - * `IoTHubDeviceClient_InitializeUpload` - * `IoTHubDeviceClient_NotifyUploadCompletion` + * `IoTHubDeviceClient_AzureStorageInitializeBlobUpload` + * `IoTHubDeviceClient_AzureStorageNotifyBlobUploadCompletion` * For simpler/less-granular control of uploads to Azure blob storage please use either * `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`. * For more information about Azure Storage PUT BLOCK, its parameters and behavior, please refer to @@ -437,8 +437,8 @@ extern "C" * `IoTHubDeviceClient_AzureStoragePutBlock` * `IoTHubDeviceClient_AzureStoragePutBlockList` * `IoTHubDeviceClient_AzureStorageDestroyClient` - * `IoTHubDeviceClient_InitializeUpload` - * `IoTHubDeviceClient_NotifyUploadCompletion` + * `IoTHubDeviceClient_AzureStorageInitializeBlobUpload` + * `IoTHubDeviceClient_AzureStorageNotifyBlobUploadCompletion` * For simpler/less-granular control of uploads to Azure blob storage please use either * `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`. * If this function fails (due to any HTTP error to Azure Storage) it can @@ -463,8 +463,8 @@ extern "C" * `IoTHubDeviceClient_AzureStoragePutBlock` * `IoTHubDeviceClient_AzureStoragePutBlockList` * `IoTHubDeviceClient_AzureStorageDestroyClient` - * `IoTHubDeviceClient_InitializeUpload` - * `IoTHubDeviceClient_NotifyUploadCompletion` + * `IoTHubDeviceClient_AzureStorageInitializeBlobUpload` + * `IoTHubDeviceClient_AzureStorageNotifyBlobUploadCompletion` * For simpler/less-granular control of uploads to Azure blob storage please use either * `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`. * @@ -484,8 +484,8 @@ extern "C" * `IoTHubDeviceClient_AzureStoragePutBlock` * `IoTHubDeviceClient_AzureStoragePutBlockList` * `IoTHubDeviceClient_AzureStorageDestroyClient` - * `IoTHubDeviceClient_InitializeUpload` - * `IoTHubDeviceClient_NotifyUploadCompletion` + * `IoTHubDeviceClient_AzureStorageInitializeBlobUpload` + * `IoTHubDeviceClient_AzureStorageNotifyBlobUploadCompletion` * For simpler/less-granular control of uploads to Azure blob storage please use either * `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`. * If this function fails (due to any HTTP error to either Azure Storage or Azure IoT Hub) it can @@ -493,7 +493,7 @@ extern "C" * an internet connectivity disruption is over. * * @param azureStorageClientHandle The handle created with `IoTHubDeviceClient_AzureStorageCreateClient`. - * @param uploadCorrelationId Upload correlation-id obtained with `IoTHubDeviceClient_InitializeUpload`. + * @param uploadCorrelationId Upload correlation-id obtained with `IoTHubDeviceClient_AzureStorageInitializeBlobUpload`. * @param isSuccess A boolean value indicating if the call(s) to `IoTHubDeviceClient_AzureStoragePutBlock` succeeded. * @param responseCode An user-defined code to signal the status of the upload (e.g., 200 for success, or -1 for abort). * @param responseMessage An user-defined status message to go along with `responseCode` on the notification to Azure IoT Hub. @@ -502,7 +502,7 @@ extern "C" * * @return IOTHUB_CLIENT_OK upon success or an error code upon failure. */ - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_NotifyUploadCompletion, IOTHUB_DEVICE_CLIENT_HANDLE, iotHubClientHandle, const char*, uploadCorrelationId, bool, isSuccess, int, responseCode, const char*, responseMessage); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_AzureStorageNotifyBlobUploadCompletion, IOTHUB_DEVICE_CLIENT_HANDLE, iotHubClientHandle, const char*, uploadCorrelationId, bool, isSuccess, int, responseCode, const char*, responseMessage); #endif /* DONT_USE_UPLOADTOBLOB */ /** diff --git a/iothub_client/inc/iothub_device_client_ll.h b/iothub_client/inc/iothub_device_client_ll.h index c843c03d4f..a2bf326fff 100644 --- a/iothub_client/inc/iothub_device_client_ll.h +++ b/iothub_client/inc/iothub_device_client_ll.h @@ -392,7 +392,7 @@ typedef IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IOTHUB_CLIENT_LL_AZURE_STOR * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. * This function is expected to be used along with: * `IoTHubDeviceClient_LL_AzureStoragePutBlock` - * `IoTHubDeviceClient_LL_NotifyUploadCompletion` + * `IoTHubDeviceClient_LL_AzureStorageNotifyBlobUploadCompletion` * `IoTHubDeviceClient_LL_AzureStorageDestroyClient` * For simpler/less-granular control of uploads to Azure blob storage please use either * `IoTHubDeviceClient_LL_UploadToBlob` or `IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob`. @@ -406,24 +406,24 @@ typedef IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IOTHUB_CLIENT_LL_AZURE_STOR * This function only attempts to send HTTP requests once, it does not retry in case of failure. * Any retries must be explicitly implemented by the calling application. * `uploadCorrelationId` and `azureBlobSasUri` must be freed by the calling application - * after the blob upload process is done (e.g., after calling `IoTHubDeviceClient_LL_NotifyUploadCompletion`). + * after the blob upload process is done (e.g., after calling `IoTHubDeviceClient_LL_AzureStorageNotifyBlobUploadCompletion`). * * @return An IOTHUB_CLIENT_RESULT value indicating the success or failure of the API call. */ - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_InitializeUpload, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, char**, uploadCorrelationId, char**, azureBlobSasUri); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_AzureStorageInitializeBlobUpload, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, char**, uploadCorrelationId, char**, azureBlobSasUri); /** * @brief This API creates a client for a new blob upload to Azure Storage. * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. * This function is expected to be used along with: * `IoTHubDeviceClient_LL_AzureStoragePutBlock` - * `IoTHubDeviceClient_LL_NotifyUploadCompletion` + * `IoTHubDeviceClient_LL_AzureStorageNotifyBlobUploadCompletion` * `IoTHubDeviceClient_LL_AzureStorageDestroyClient` * For simpler/less-granular control of uploads to Azure blob storage please use either * `IoTHubDeviceClient_LL_UploadToBlob` or `IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob`. * * @param iotHubClientHandle The handle created by a call to the create function. - * @param azureBlobSasUri The Azure Storage Blob SAS uri obtained with `IoTHubDeviceClient_InitializeUpload`. + * @param azureBlobSasUri The Azure Storage Blob SAS uri obtained with `IoTHubDeviceClient_LL_AzureStorageInitializeBlobUpload`. * * @warning This is a synchronous/blocking function. * @@ -436,7 +436,7 @@ typedef IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IOTHUB_CLIENT_LL_AZURE_STOR * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. * This function is expected to be used along with: * `IoTHubDeviceClient_LL_AzureStorageCreateClient` - * `IoTHubDeviceClient_LL_NotifyUploadCompletion` + * `IoTHubDeviceClient_LL_AzureStorageNotifyBlobUploadCompletion` * `IoTHubDeviceClient_LL_AzureStorageDestroyClient` * For simpler/less-granular control of uploads to Azure blob storage please use either * `IoTHubDeviceClient_LL_UploadToBlob` or `IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob`. @@ -461,7 +461,7 @@ typedef IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IOTHUB_CLIENT_LL_AZURE_STOR * @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads. * This function is expected to be used along with: * `IoTHubDeviceClient_LL_AzureStorageCreateClient` - * `IoTHubDeviceClient_LL_NotifyUploadCompletion` + * `IoTHubDeviceClient_LL_AzureStorageNotifyBlobUploadCompletion` * `IoTHubDeviceClient_LL_AzureStorageDestroyClient` * For simpler/less-granular control of uploads to Azure blob storage please use either * `IoTHubDeviceClient_LL_UploadToBlob` or `IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob`. @@ -484,7 +484,7 @@ typedef IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IOTHUB_CLIENT_LL_AZURE_STOR * This function is expected to be used along with: * `IoTHubDeviceClient_LL_AzureStorageCreateClient` * `IoTHubDeviceClient_LL_AzureStoragePutBlock` - * `IoTHubDeviceClient_LL_NotifyUploadCompletion` + * `IoTHubDeviceClient_LL_AzureStorageNotifyBlobUploadCompletion` * For simpler/less-granular control of uploads to Azure blob storage please use either * `IoTHubDeviceClient_LL_UploadToBlob` or `IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob`. * @@ -510,7 +510,7 @@ typedef IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IOTHUB_CLIENT_LL_AZURE_STOR * an internet connectivity disruption is over. * * @param azureStorageClientHandle The handle created with `IoTHubDeviceClient_LL_AzureStorageCreateClient`. - * @param uploadCorrelationId Upload correlation-id obtained with `IoTHubDeviceClient_LL_InitializeUpload`. + * @param uploadCorrelationId Upload correlation-id obtained with `IoTHubDeviceClient_LL_AzureStorageInitializeBlobUpload`. * @param isSuccess A boolean value indicating if the call(s) to `IoTHubDeviceClient_LL_AzureStoragePutBlock` succeeded. * @param responseCode An user-defined code to signal the status of the upload (e.g., 200 for success, or -1 for abort). * @param responseMessage An user-defined status message to go along with `responseCode` on the notification to Azure IoT Hub. @@ -521,7 +521,7 @@ typedef IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IOTHUB_CLIENT_LL_AZURE_STOR * * @return IOTHUB_CLIENT_OK upon success or an error code upon failure. */ - MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_NotifyUploadCompletion, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, uploadCorrelationId, bool, isSuccess, int, responseCode, const char*, responseMessage); + MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_AzureStorageNotifyBlobUploadCompletion, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, uploadCorrelationId, bool, isSuccess, int, responseCode, const char*, responseMessage); #endif /*DONT_USE_UPLOADTOBLOB*/ /** diff --git a/iothub_client/samples/CMakeLists.txt b/iothub_client/samples/CMakeLists.txt index b23dea6bdf..9cae40f585 100644 --- a/iothub_client/samples/CMakeLists.txt +++ b/iothub_client/samples/CMakeLists.txt @@ -24,7 +24,7 @@ if(${use_http}) if(NOT ${dont_use_uploadtoblob}) add_sample_directory(iothub_client_sample_upload_to_blob) add_sample_directory(iothub_client_sample_upload_to_blob_mb) - add_sample_directory(iothub_client_sample_upload_to_blob_custom) + add_sample_directory(iothub_client_sample_upload_to_blob_with_retry) endif() if (${use_edge_modules}) add_sample_directory(iothub_client_sample_module_method_invoke) diff --git a/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/CMakeLists.txt b/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/CMakeLists.txt deleted file mode 100644 index 3243edd4d3..0000000000 --- a/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/CMakeLists.txt +++ /dev/null @@ -1,46 +0,0 @@ -#Copyright (c) Microsoft. All rights reserved. -#Licensed under the MIT license. See LICENSE file in the project root for full license information. - -#this is CMakeLists.txt for iothub_client_sample_upload_to_blob_custom - -compileAsC99() - -if(NOT ${use_http}) - message(FATAL_ERROR "iothub_client_sample_upload_to_blob_custom being generated without HTTP support") -endif() - -set(iothub_client_sample_upload_to_blob_custom_c_files - iothub_client_sample_upload_to_blob_custom.c -) - -set(iothub_client_sample_upload_to_blob_custom_h_files -) - -#Conditionally use the SDK trusted certs in the samples -if(${use_sample_trusted_cert}) - add_definitions(-DSET_TRUSTED_CERT_IN_SAMPLES) - include_directories(${PROJECT_SOURCE_DIR}/certs) - set(iothub_client_sample_upload_to_blob_custom_c_files ${iothub_client_sample_upload_to_blob_custom_c_files} ${PROJECT_SOURCE_DIR}/certs/certs.c) -endif() - -IF(WIN32) - #windows needs this define - add_definitions(-D_CRT_SECURE_NO_WARNINGS) - add_definitions(-DGB_MEASURE_MEMORY_FOR_THIS -DGB_DEBUG_ALLOC) -ENDIF(WIN32) - -include_directories(.) - -add_executable( - iothub_client_sample_upload_to_blob_custom - ${iothub_client_sample_upload_to_blob_custom_c_files} - ${iothub_client_sample_upload_to_blob_custom_h_files} -) - -target_link_libraries(iothub_client_sample_upload_to_blob_custom - iothub_client - iothub_client_http_transport -) - -linkSharedUtil(iothub_client_sample_upload_to_blob_custom) -linkHttp(iothub_client_sample_upload_to_blob_custom) diff --git a/iothub_client/samples/iothub_client_sample_upload_to_blob_with_retry/CMakeLists.txt b/iothub_client/samples/iothub_client_sample_upload_to_blob_with_retry/CMakeLists.txt new file mode 100644 index 0000000000..40b80ca884 --- /dev/null +++ b/iothub_client/samples/iothub_client_sample_upload_to_blob_with_retry/CMakeLists.txt @@ -0,0 +1,46 @@ +#Copyright (c) Microsoft. All rights reserved. +#Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#this is CMakeLists.txt for iothub_client_sample_upload_to_blob_with_retry + +compileAsC99() + +if(NOT ${use_http}) + message(FATAL_ERROR "iothub_client_sample_upload_to_blob_with_retry being generated without HTTP support") +endif() + +set(iothub_client_sample_upload_to_blob_with_retry_c_files + iothub_client_sample_upload_to_blob_with_retry.c +) + +set(iothub_client_sample_upload_to_blob_with_retry_h_files +) + +#Conditionally use the SDK trusted certs in the samples +if(${use_sample_trusted_cert}) + add_definitions(-DSET_TRUSTED_CERT_IN_SAMPLES) + include_directories(${PROJECT_SOURCE_DIR}/certs) + set(iothub_client_sample_upload_to_blob_with_retry_c_files ${iothub_client_sample_upload_to_blob_with_retry_c_files} ${PROJECT_SOURCE_DIR}/certs/certs.c) +endif() + +IF(WIN32) + #windows needs this define + add_definitions(-D_CRT_SECURE_NO_WARNINGS) + add_definitions(-DGB_MEASURE_MEMORY_FOR_THIS -DGB_DEBUG_ALLOC) +ENDIF(WIN32) + +include_directories(.) + +add_executable( + iothub_client_sample_upload_to_blob_with_retry + ${iothub_client_sample_upload_to_blob_with_retry_c_files} + ${iothub_client_sample_upload_to_blob_with_retry_h_files} +) + +target_link_libraries(iothub_client_sample_upload_to_blob_with_retry + iothub_client + iothub_client_http_transport +) + +linkSharedUtil(iothub_client_sample_upload_to_blob_with_retry) +linkHttp(iothub_client_sample_upload_to_blob_with_retry) diff --git a/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c b/iothub_client/samples/iothub_client_sample_upload_to_blob_with_retry/iothub_client_sample_upload_to_blob_with_retry.c similarity index 90% rename from iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c rename to iothub_client/samples/iothub_client_sample_upload_to_blob_with_retry/iothub_client_sample_upload_to_blob_with_retry.c index dbe38e472f..5c9a456eef 100644 --- a/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/iothub_client_sample_upload_to_blob_custom.c +++ b/iothub_client/samples/iothub_client_sample_upload_to_blob_with_retry/iothub_client_sample_upload_to_blob_with_retry.c @@ -5,6 +5,12 @@ // Checking of return codes and error values shall be omitted for brevity. Please practice sound engineering practices // when writing production code. +// This sample is also uses a much more improved API for performing +// Azure IoT Hub-backed Azure Storage Blob uploads by: +// Explicitly getting a SAS token for the Blob storage (usable by external tools such as az_copy). +// Using the the built-in Azure Storage Blob new upload client. +// Showing how to retry blob upload per block (as opposed to the entire file). + #include #include @@ -34,8 +40,8 @@ static const char* connectionString = "[device connection string]"; static const char* proxyHost = NULL; static int proxyPort = 0; -static const char* azureStorageBlobPath = "subdir/hello_world_custom_mb.txt"; -static const char* data_to_upload_format = "Hello World from iothub_client_sample_upload_to_blob_custom: %d\n"; +static const char* azureStorageBlobPath = "subdir/hello_world_mb_with_retry.txt"; +static const char* data_to_upload_format = "Hello World from iothub_client_sample_upload_to_blob_with_retry: %d\n"; static char data_to_upload[128]; #define SAMPLE_MAX_RETRY_COUNT 3 @@ -80,13 +86,17 @@ int main(void) char* uploadCorrelationId; char* azureBlobSasUri; - if (IoTHubDeviceClient_LL_InitializeUpload( + if (IoTHubDeviceClient_LL_AzureStorageInitializeBlobUpload( device_ll_handle, azureStorageBlobPath, &uploadCorrelationId, &azureBlobSasUri) != IOTHUB_CLIENT_OK) { printf("failed initializing upload in IoT Hub\n"); } else { + // The SAS URI obtained above (azureBlobSasUri) can be used with other tools + // like az_copy or Azure Storage SDK instead of the API functions + // built-in this SDK shown below. + IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE azureStorageClientHandle = IoTHubDeviceClient_LL_AzureStorageCreateClient(device_ll_handle, azureBlobSasUri); if (azureStorageClientHandle == NULL) @@ -150,7 +160,7 @@ int main(void) while (true) { - if (IoTHubDeviceClient_LL_NotifyUploadCompletion( + if (IoTHubDeviceClient_LL_AzureStorageNotifyBlobUploadCompletion( device_ll_handle, uploadCorrelationId, uploadSuccessful, uploadResultCode, uploadSuccessful ? "OK" : "Aborted") == IOTHUB_CLIENT_OK) { diff --git a/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/linux/CMakeLists.txt b/iothub_client/samples/iothub_client_sample_upload_to_blob_with_retry/linux/CMakeLists.txt similarity index 58% rename from iothub_client/samples/iothub_client_sample_upload_to_blob_custom/linux/CMakeLists.txt rename to iothub_client/samples/iothub_client_sample_upload_to_blob_with_retry/linux/CMakeLists.txt index 0ee7c49a9a..0a64c19c97 100644 --- a/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/linux/CMakeLists.txt +++ b/iothub_client/samples/iothub_client_sample_upload_to_blob_with_retry/linux/CMakeLists.txt @@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.5) cmake_policy(SET CMP0074 NEW) cmake_policy(SET CMP0012 NEW) -project(iothub_client_sample_upload_to_blob_custom) +project(iothub_client_sample_upload_to_blob_with_retry) if(WIN32) message(FATAL_ERROR "This CMake file only supports Linux builds!") @@ -17,13 +17,13 @@ find_package(azure_iot_sdks REQUIRED) add_definitions(-DSET_TRUSTED_CERT_IN_SAMPLES) include_directories("../../../../certs") -set(iothub_client_sample_upload_to_blob_custom_c_files - ../iothub_client_sample_upload_to_blob_custom.c +set(iothub_client_sample_upload_to_blob_with_retry_c_files + ../iothub_client_sample_upload_to_blob_with_retry.c ../../../../certs/certs.c ) -add_executable(iothub_client_sample_upload_to_blob_custom ${iothub_client_sample_upload_to_blob_custom_c_files}) +add_executable(iothub_client_sample_upload_to_blob_with_retry ${iothub_client_sample_upload_to_blob_with_retry_c_files}) -target_link_libraries(iothub_client_sample_upload_to_blob_custom +target_link_libraries(iothub_client_sample_upload_to_blob_with_retry iothub_client ) diff --git a/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/windows/iothub_client_sample_upload_to_blob.sln b/iothub_client/samples/iothub_client_sample_upload_to_blob_with_retry/windows/iothub_client_sample_upload_to_blob.sln similarity index 100% rename from iothub_client/samples/iothub_client_sample_upload_to_blob_custom/windows/iothub_client_sample_upload_to_blob.sln rename to iothub_client/samples/iothub_client_sample_upload_to_blob_with_retry/windows/iothub_client_sample_upload_to_blob.sln diff --git a/iothub_client/samples/iothub_client_sample_upload_to_blob_custom/windows/iothub_client_sample_upload_to_blob.vcxproj b/iothub_client/samples/iothub_client_sample_upload_to_blob_with_retry/windows/iothub_client_sample_upload_to_blob.vcxproj similarity index 100% rename from iothub_client/samples/iothub_client_sample_upload_to_blob_custom/windows/iothub_client_sample_upload_to_blob.vcxproj rename to iothub_client/samples/iothub_client_sample_upload_to_blob_with_retry/windows/iothub_client_sample_upload_to_blob.vcxproj diff --git a/iothub_client/src/iothub_device_client.c b/iothub_client/src/iothub_device_client.c index d92e69d293..eaabf51037 100644 --- a/iothub_client/src/iothub_device_client.c +++ b/iothub_client/src/iothub_device_client.c @@ -115,7 +115,7 @@ IOTHUB_CLIENT_RESULT IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync(IOTHUB_D return IoTHubClientCore_UploadMultipleBlocksToBlobAsync((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, destinationFileName, NULL, getDataCallbackEx, context); } -IOTHUB_CLIENT_RESULT IoTHubDeviceClient_InitializeUpload(IOTHUB_DEVICE_CLIENT_HANDLE iotHubClientHandle, const char* destinationFileName, char** uploadCorrelationId, char** azureBlobSasUri) +IOTHUB_CLIENT_RESULT IoTHubDeviceClient_AzureStorageInitializeBlobUpload(IOTHUB_DEVICE_CLIENT_HANDLE iotHubClientHandle, const char* destinationFileName, char** uploadCorrelationId, char** azureBlobSasUri) { return IoTHubClientCore_InitializeUpload((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, destinationFileName, uploadCorrelationId, azureBlobSasUri); } @@ -140,7 +140,7 @@ void IoTHubDeviceClient_AzureStorageDestroyClient(IOTHUB_CLIENT_LL_UPLOADTOBLOB_ IoTHubClientCore_AzureStorageDestroyClient(azureStorageClientHandle); } -IOTHUB_CLIENT_RESULT IoTHubDeviceClient_NotifyUploadCompletion(IOTHUB_DEVICE_CLIENT_HANDLE iotHubClientHandle, const char* uploadCorrelationId, bool isSuccess, int responseCode, const char* responseMessage) +IOTHUB_CLIENT_RESULT IoTHubDeviceClient_AzureStorageNotifyBlobUploadCompletion(IOTHUB_DEVICE_CLIENT_HANDLE iotHubClientHandle, const char* uploadCorrelationId, bool isSuccess, int responseCode, const char* responseMessage) { return IoTHubClientCore_NotifyUploadCompletion((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, uploadCorrelationId, isSuccess, responseCode, responseMessage); } diff --git a/iothub_client/src/iothub_device_client_ll.c b/iothub_client/src/iothub_device_client_ll.c index 1b6dcda8bf..6b7aea86c1 100644 --- a/iothub_client/src/iothub_device_client_ll.c +++ b/iothub_client/src/iothub_device_client_ll.c @@ -137,7 +137,7 @@ IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob(IOTHUB_DEV return IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, destinationFileName, getDataCallbackEx, context); } -IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_InitializeUpload(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, const char* destinationFileName, char** uploadCorrelationId, char** azureBlobSasUri) +IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_AzureStorageInitializeBlobUpload(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, const char* destinationFileName, char** uploadCorrelationId, char** azureBlobSasUri) { return IoTHubClientCore_LL_InitializeUpload((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, destinationFileName, uploadCorrelationId, azureBlobSasUri); } @@ -162,7 +162,7 @@ void IoTHubDeviceClient_LL_AzureStorageDestroyClient(IOTHUB_CLIENT_LL_AZURE_STOR IoTHubClientCore_LL_AzureStorageDestroyClient(azureStorageClientHandle); } -IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_NotifyUploadCompletion(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, const char* uploadCorrelationId, bool isSuccess, int responseCode, const char* responseMessage) +IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_AzureStorageNotifyBlobUploadCompletion(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, const char* uploadCorrelationId, bool isSuccess, int responseCode, const char* responseMessage) { return IoTHubClientCore_LL_NotifyUploadCompletion((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, uploadCorrelationId, isSuccess, responseCode, responseMessage); } diff --git a/iothub_client/tests/iothubclient_uploadtoblob_e2e/iothubclient_uploadtoblob_e2e.c b/iothub_client/tests/iothubclient_uploadtoblob_e2e/iothubclient_uploadtoblob_e2e.c index e71fc8add1..bdbf490e90 100644 --- a/iothub_client/tests/iothubclient_uploadtoblob_e2e/iothubclient_uploadtoblob_e2e.c +++ b/iothub_client/tests/iothubclient_uploadtoblob_e2e/iothubclient_uploadtoblob_e2e.c @@ -526,11 +526,7 @@ TEST_FUNCTION(IoTHub_MQTT_UploadToBlob_x509) TEST_FUNCTION(IoTHub_MQTT_UploadCloseHandle_Before_WorkersComplete) { - // Running this for lots of iterations can cause e2e test failures. - for (int i = 0; i < 1; i++) - { - e2e_uploadtoblob_close_handle_with_active_thread(MQTT_Protocol); - } + e2e_uploadtoblob_close_handle_with_active_thread(MQTT_Protocol); } #endif // TEST_MQTT