ustream_forward: a lightweight smart-pointer for fast and efficient data transfer (#76)

Interfaces:

* flush(): copy data from source to destination directly
* read(): copy data from source to destination indirectly utilizing a user-provided local-buffer
* get_size(): get total length of data source
* dispose(): free all resources associated with ustream_forward smart-pointer

Note: does not yet support infinite streams.
This commit is contained in:
Spencer McDonough 2021-08-18 11:36:22 -07:00 коммит произвёл GitHub
Родитель 2518399f69
Коммит c25479057f
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
30 изменённых файлов: 1994 добавлений и 65 удалений

Просмотреть файл

@ -98,6 +98,7 @@ ulib_add_standards()
add_library(azure_ulib_c
${CMAKE_CURRENT_LIST_DIR}/src/az_ulib_ustream/az_ulib_ustream_aux.c
${CMAKE_CURRENT_LIST_DIR}/src/az_ulib_ustream/az_ulib_ustream.c
${CMAKE_CURRENT_LIST_DIR}/src/az_ulib_ustream_forward/az_ulib_ustream_forward.c
${CMAKE_CURRENT_LIST_DIR}/src/az_ulib_ipc/az_ulib_ipc.c
${CMAKE_CURRENT_LIST_DIR}/src/az_ulib_ipc/az_ulib_ipc_query_interface.c
${CMAKE_CURRENT_LIST_DIR}/src/az_ulib_ipc/az_ulib_ipc_interface_manager_interface.c

Просмотреть файл

@ -12,6 +12,7 @@
#define AZ_ULIB_BASE_H
#ifndef __cplusplus
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#else
@ -47,6 +48,27 @@ typedef uint32_t az_ulib_version;
*/
#define AZ_ULIB_STRINGIFIED_VERSION_SIZE 12
/**
* @brief Define offset_t with the same size as size_t.
*/
typedef size_t offset_t;
/**
* @brief Context that uniquely identifies the callback.
*
* The callback context is the way that the capability's caller associates the call to its answer.
* It can have any value that is meaningful for the caller.
*/
typedef void* az_ulib_callback_context;
/**
* @brief Signature of the function to release memory passed to the ustream
*
* @param[in] release_pointer void pointer to memory that needs to be free'd
*
*/
typedef void (*az_ulib_release_callback)(void* release_pointer);
#include "azure/core/_az_cfg_suffix.h"
#endif // AZ_ULIB_BASE_H

Просмотреть файл

@ -101,14 +101,6 @@ typedef az_result (*az_ulib_capability)(az_ulib_model_in model_in, az_ulib_model
typedef az_result (
*az_ulib_capability_span_wrapper)(az_span model_in_span, az_span* model_out_span);
/**
* @brief Context that uniquely identifies the callback.
*
* The callback context is the way that the capability's caller associates the call to its answer.
* It can have any value that is meaningful for the caller.
*/
typedef void* az_ulib_callback_context;
/**
* @brief Telemetry callback signature.
*

Просмотреть файл

@ -326,6 +326,7 @@
* point. In this case, the consumer can call the API az_ulib_ustream_reset().
*/
#include "az_ulib_base.h"
#include "az_ulib_config.h"
#include "az_ulib_pal_os.h"
#include "az_ulib_result.h"
@ -340,11 +341,6 @@
#include "azure/core/_az_cfg_prefix.h"
/**
* @brief Define offset_t with the same size as size_t.
*/
typedef size_t offset_t;
/**
* @brief Forward declaration of az_ulib_ustream. See #az_ulib_ustream_tag for struct members.
*/
@ -393,14 +389,6 @@ typedef struct az_ulib_ustream_interface_tag
} az_ulib_ustream_interface;
/**
* @brief Signature of the function to release memory passed to the ustream
*
* @param[in] release_pointer void pointer to memory that needs to be free'd
*
*/
typedef void (*az_ulib_release_callback)(void* release_pointer);
/**
* @brief Pointer to the data from which to read
*

Просмотреть файл

@ -0,0 +1,359 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
/**
* @file az_ulib_ustream_forward.h
*
* @brief The ustream_forward interfaces and accompanying APIs.
*/
#ifndef AZ_ULIB_USTREAM_FORWARD_H
#define AZ_ULIB_USTREAM_FORWARD_H
#include "az_ulib_base.h"
#include "az_ulib_result.h"
#include "azure/az_core.h"
#ifdef __cplusplus
#include <cstddef>
#include <cstdint>
#else
#include <stddef.h>
#include <stdint.h>
#endif /* __cplusplus */
#include "azure/core/_az_cfg_prefix.h"
/**
* @brief Forward declaration of az_ulib_ustream_forward. See #az_ulib_ustream_forward_tag for
* struct members.
*/
typedef struct az_ulib_ustream_forward_tag az_ulib_ustream_forward;
/**
* @brief Signature of the function to be invoked by the `az_ulib_ustream_forward_flush`
* operation when the `const uint8_t* const` to the buffer has been created.
*
* @param[in] buffer The `const uint8_t* const` buffer to be handled by the
* implementation of this callback.
* @param[in] size The number of `uint8_t` bytes in the
* `const uint8_t* const` buffer.
* @param[in] flush_callback_context The #az_ulib_callback_context contract held between the
* owner of this callback and the caller of
* `az_ulib_ustream_forward_flush`.
*/
typedef void (*az_ulib_flush_callback)(
const uint8_t* const buffer,
size_t size,
az_ulib_callback_context flush_callback_context);
/**
* @brief vTable with the ustream_forward APIs.
*
* Any module that exposes the ustream_forward shall implement the functions on this vTable.
*
* Any code that will use an exposed ustream_forward shall call the APIs using the
* `az_ulib_ustream_forward_...` inline functions.
*/
typedef struct az_ulib_ustream_forward_interface_tag
{
/** Concrete `flush` implementation. */
az_result (*flush)(
az_ulib_ustream_forward* ustream_forward,
az_ulib_flush_callback flush_callback,
az_ulib_callback_context flush_callback_context);
/** Concrete `read` implementation. */
az_result (*read)(
az_ulib_ustream_forward* ustream_forward,
uint8_t* const buffer,
size_t buffer_length,
size_t* const size);
/** Concrete `get_size` implementation. */
size_t (*get_size)(az_ulib_ustream_forward* ustream_forward);
/** Concrete `dispose` implementation. */
az_result (*dispose)(az_ulib_ustream_forward* ustream_forward);
} az_ulib_ustream_forward_interface;
/**
* @brief Pointer to the data from which to read
*
* void pointer to memory where the data is located or any needed controls to access the data.
* The content of the memory to which this points is up to the ustream_forward implementation.
*
*/
typedef void* az_ulib_ustream_forward_data;
/**
* @brief Structure for the ustream_forward control block
*
* For any given ustream_forward that is created, one control block is created and initialized.
*
* @note This structure should be viewed and used as internal to the implementation of the
* ustream_forward. Users should therefore not act on it directly and only allocate the
* memory necessary for it to be passed to the ustream_forward.
*
*/
struct az_ulib_ustream_forward_tag
{
struct
{
/** The #az_ulib_ustream_forward_interface* for this ustream_forward instance type. */
const az_ulib_ustream_forward_interface* api;
/** The #az_ulib_ustream_forward_data* pointing to the data to read. It can be anything that a
* give ustream_forward implementation needs to access the data, whether it be a memory address
* to a buffer, another struct with more controls, etc */
const az_ulib_ustream_forward_data* ptr;
/** The #az_ulib_release_callback to call to release `ptr` */
az_ulib_release_callback data_release;
/** The #az_ulib_release_callback to call to release the #az_ulib_ustream_forward. */
az_ulib_release_callback ustream_forward_release;
/** The #offset_t used to keep track of the current position (next returned position). */
offset_t inner_current_position;
/** The number of `uint8_t` bytes of data in the control_block. */
size_t length;
} _internal;
};
/**
* @brief Check if a handle is the same type of the API.
*
* It will return true if the handle is valid and it is the same type of the API. It will
* return false if the handle is `NULL` or not the correct type.
*/
#define AZ_ULIB_USTREAM_FORWARD_IS_TYPE_OF(handle, type_api) \
(!((handle == NULL) || (handle->_internal.api == NULL) || (handle->_internal.api != &type_api)))
/**
* @brief Provide data from the source to the #az_ulib_flush_callback.
*
* The `az_ulib_ustream_forward_flush` API will forward the data directly from the
* source (provider) to be handled by the `#az_ulib_flush_callback* flush_callback`.
*
* In the event that the source (provider) memory is not immediately available without a call
* to an external API (e.g. an HTTP connection to a blob storage provider), the flush operation
* will call this external API (e.g. http_response_body_get) in a loop, invoking the
* `flush_callback` each pass of the loop.
*
* The `az_ulib_ustream_forward_flush` API will provide the consumer a pointer to the memory
* associated with the ustream_forward in the form of a `const uint8_t* const` buffer,
* to be handled in the `#az_ulib_flush_callback* flush_callback` function implemented by the
* consumer.
*
* The `az_ulib_ustream_forward_flush` API shall meet the following minimum requirements:
* - The flush operation creates a `const uint8_t* const` from the `Data Source` and hands it
* off to the `flush_callback`
* - If the totality of `Data Source` is not available in the provided memory location,
* the API shall request the next portion of the data using the appropriate external API.
* This process shall be repeated in a loop until the totality of the `Data Source` has been
* copied.
* - The API shall satisfy all of the precondition requirements laid forth below.
*
* @param[in] ustream_forward The #az_ulib_ustream_forward* with the interface of
* the ustream_forward.
* @param[out] flush_callback The #az_ulib_flush_callback* for the consumer to
* handle the incoming data.
* @param[out] flush_callback_context The #az_ulib_callback_context contract between the
* caller and flush_callback.
*
* @pre \p ustream_forward shall not be `NULL`.
* @pre \p ustream_forward shall be a valid ustream_forward that is the
* implemented ustream_forward type.
* @pre \p flush_callback shall not be `NULL`.
*
* @return The #az_result with the result of the flush operation
* @retval #AZ_OK If the flush operation succeeded in pushing the
* entire stream content to `flush_callback`.
* @retval #AZ_ERROR_ULIB_BUSY If the resource necessary to get the next portion of
* data is busy.
* @retval #AZ_ERROR_CANCELED If any one of the flush operation's dependent
* external calls is canceled.
* @retval #AZ_ERROR_NOT_ENOUGH_SPACE If there is not enough memory to finish copying the
* data from source to destination.
* @retval #AZ_ERROR_ULIB_SECURITY If any one of the flush operation's dependent
* external calls returns an error for security reasons.
* @retval #AZ_ERROR_ULIB_SYSTEM If any one of the flush operation's dependent
* fails at the system level.
*/
AZ_NODISCARD AZ_INLINE az_result az_ulib_ustream_forward_flush(
az_ulib_ustream_forward* ustream_forward,
az_ulib_flush_callback flush_callback,
az_ulib_callback_context flush_callback_context)
{
return ustream_forward->_internal.api->flush(
ustream_forward, flush_callback, flush_callback_context);
}
/**
* @brief Gets the next portion of the ustream_forward.
*
* The `az_ulib_ustream_forward_read` API will copy the contents of the `Data Source` to the local
* buffer starting at the offset set by the previous call to `az_ulib_ustream_forward_read`.
* This position will be the beginning of the stream (offset of 0) the first time this API is
* called. The local buffer is the one referenced by the parameter `buffer`, and with the
* maximum size `buffer_length`.
*
* The buffer is defined as a `uint8_t*` and can represent any sequence of data. Pay
* special attention, if the data is a string, the buffer will still copy it as a sequence of
* `uint8_t`, and will <b>NOT</b> put any terminator at the end of the string. The size of
* the content copied in the local buffer will be returned in the parameter `size`.
*
* The `az_ulib_ustream_forward_read` API shall follow the following minimum requirements:
* - The read shall copy the contents of the `Data Source` to the provided local buffer.
* - If the contents of the `Data Source` is bigger than the `buffer_length`, the read shall
* limit the copy size up to the buffer_length.
* - The read shall return the number of valid `uint8_t` values in the local buffer in
* the provided `size`.
* - If there is no more content to return, the read shall return
* #AZ_ULIB_EOF, size shall be set to 0, and will not change the contents
* of the local buffer.
* - The API shall satisfy all of the precondition requirements laid forth below.
*
* @param[in] ustream_forward The #az_ulib_ustream_forward* with the interface of the
* ustream_forward.
* @param[out] buffer The `uint8_t* const` that points to the local buffer.
* @param[in] buffer_length The `size_t` with the size of the local buffer.
* @param[out] size The `size_t* const` that points to the place where the
* read shall store the number of valid `uint8_t` values
* returned in the local buffer.
*
* @pre \p ustream_forward shall not be `NULL`.
* @pre \p ustream_forward shall be a valid ustream_forward that is the implemented
* ustream_forward type.
* @pre \p buffer shall not be `NULL`.
* @pre \p buffer_length shall not be bigger than 0.
* @pre \p size shall not be `NULL`.
*
* @return The #az_result with the result of the read operation.
* @retval #AZ_OK If the ustream_forward copied the content of the
* `Data Source` to the local buffer with success.
* @retval #AZ_ERROR_ULIB_BUSY If the resource necessary to read the ustream_forward
* content is busy.
* @retval #AZ_ERROR_CANCELED If the read of the content was cancelled.
* @retval #AZ_ULIB_EOF If there are no more `uint8_t` values in the `Data
* Source` to read.
* @retval #AZ_ERROR_NOT_ENOUGH_SPACE If there is not enough memory to execute the read.
* @retval #AZ_ERROR_ULIB_SECURITY If the read was denied for security reasons.
* @retval #AZ_ERROR_ULIB_SYSTEM If the read operation failed on the system level.
*/
AZ_NODISCARD AZ_INLINE az_result az_ulib_ustream_forward_read(
az_ulib_ustream_forward* ustream_forward,
uint8_t* const buffer,
size_t buffer_length,
size_t* const size)
{
return ustream_forward->_internal.api->read(ustream_forward, buffer, buffer_length, size);
}
/**
* @brief Returns the size of the ustream_forward.
*
* This API returns the number of bytes in the ustream_forward.
*
* The `az_ulib_ustream_forward_get_size` API shall follow the following minimum requirements:
* - The API shall return the number of bytes in the ustream_forward.
* - The API shall satisfy all of the precondition requirements laid forth below.
*
* @param[in] ustream_forward The #az_ulib_ustream_forward* with the interface of the
* ustream_forward.
*
* @pre \p ustream_forward shall not be `NULL`.
* @pre \p ustream_forward shall be a valid ustream_forward that is the implemented
* ustream_forward type.
*
* @return The `size_t` of the ustream_forward
*/
AZ_NODISCARD AZ_INLINE size_t
az_ulib_ustream_forward_get_size(az_ulib_ustream_forward* ustream_forward)
{
return ustream_forward->_internal.api->get_size(ustream_forward);
}
/**
* @brief Release all the resources allocated to the ustream_forward.
*
* The `az_ulib_ustream_forward_dispose` API shall follow the following minimum requirements:
* - The `dispose` shall release all resources allocated to the ustream_forward.
* - The API shall satisfy all of the precondition requirements laid forth below.
*
* @param[in] ustream_forward The #az_ulib_ustream_forward* with the interface of the
* ustream_forward.
*
* @pre \p ustream_forward shall not be `NULL`.
* @pre \p ustream_forward shall be a valid ustream_forward that is the implemented
* ustream_forward type.
*
* @return The #az_result with the result of the `dispose` operation.
* @retval #AZ_OK If the instance of the ustream_forward was disposed
* with success.
*
* @note: While the simplest implementation of this API returns only #AZ_OK, other implementations
* may return errors.
*/
AZ_NODISCARD AZ_INLINE az_result
az_ulib_ustream_forward_dispose(az_ulib_ustream_forward* ustream_forward)
{
return ustream_forward->_internal.api->dispose(ustream_forward);
}
/**
* @brief Factory to initialize a new ustream_forward.
*
* This factory initializes a ustream_forward that handles the content of the provided buffer. As a
* result, it will return an #az_ulib_ustream_forward* with this content. The initialized
* ustream_forward takes ownership of the passed memory and will release the memory with the
* passed #az_ulib_release_callback function when the caller goes out of scope.
*
* @param[out] ustream_forward The pointer to the allocated
* #az_ulib_ustream_forward struct.
* @param[in] ustream_forward_release The #az_ulib_release_callback function that will be
* called to release the ustream_forward block (the
* passed `ustream_forward` parameter). If `NULL` is
* passed, the `az_ulib_ustream_forward_dispose` will
* not release the memory associated with
* `ustream_forward`, so it will be the caller's
* responsibility to do so. For example, developers
* may use the stdlib `free` to release malloc'd
* memory.
* @param[in] data_buffer The `const uint8_t* const` that points to a memory
* position where the buffer starts.
* @param[in] data_buffer_length The `size_t` with the number of `uint8_t` in the
* provided buffer.
* @param[in] data_buffer_release The #az_ulib_release_callback function that will be
* called to release the data. If `NULL` is passed,
* the `az_ulib_ustream_forward_dispose` will not
* release the memory associated with
* `ustream_forward`, so it will be the caller's
* responsibility to do so. For example, developers
* may use the stdlib `free` to release malloc'd
* memory.
*
* @pre \p ustream_forward shall not be `NULL`.
* @pre \p data_buffer shall not be `NULL`.
* @pre \p data_buffer_length shall be greater than `0`.
*
* @return The #az_result with result of the initialization.
* @retval #AZ_OK If the #az_ulib_ustream_forward* is successfully
* initialized.
*
* @note: While the simplest implementation of this API returns only #AZ_OK, other implementations
* may return errors.
*/
AZ_NODISCARD az_result az_ulib_ustream_forward_init(
az_ulib_ustream_forward* ustream_forward,
az_ulib_release_callback ustream_forward_release,
const uint8_t* const data_buffer,
size_t data_buffer_length,
az_ulib_release_callback data_buffer_release);
#include "azure/core/_az_cfg_suffix.h"
#endif /* AZ_ULIB_USTREAM_FORWARD_H */

Просмотреть файл

@ -7,4 +7,5 @@ add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/ipc_call_interface)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/ipc_hardware_update)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/ipc_telemetry)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/ustream_basic)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/ustream_forward_basic)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/ustream_split)

Просмотреть файл

@ -0,0 +1,10 @@
#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.10)
add_executable(ustream_forward_basic
${CMAKE_CURRENT_LIST_DIR}/src/main.c
)
ulib_populate_sample_target(ustream_forward_basic)

Просмотреть файл

@ -0,0 +1,78 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
#include "az_ulib_result.h"
#include "az_ulib_ustream_forward.h"
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define START_MEMORY_OFFSET 0
static const char ustream_forward_producer_buf[] = "Hello World!\r\n";
typedef struct ustream_forward_basic_context
{
offset_t offset;
char buffer[100];
} consumer_context;
static void flush_callback(
const uint8_t* const buffer,
size_t size,
az_ulib_callback_context flush_callback_context)
{
// handle buffer
consumer_context* flush_context = (consumer_context*)flush_callback_context;
(void)snprintf(
flush_context->buffer + flush_context->offset,
sizeof(flush_context->buffer) / sizeof(char),
"%s", buffer);
// adjust offset
flush_context->offset += size;
}
static az_result my_consumer(void)
{
AZ_ULIB_TRY
{
// initialize ustream_forward with producer data
az_ulib_ustream_forward ustream_forward_instance;
AZ_ULIB_THROW_IF_AZ_ERROR(az_ulib_ustream_forward_init(
&ustream_forward_instance,
NULL,
(const uint8_t*)ustream_forward_producer_buf,
sizeof(ustream_forward_producer_buf),
NULL));
// initialize context
consumer_context my_consumer_context = { 0 };
(void)printf("my_consumer_context.buffer = %s\r\n", my_consumer_context.buffer);
// flush from producer to consumer buffer
(void)printf("----- FLUSH ----\r\n");
AZ_ULIB_THROW_IF_AZ_ERROR(
az_ulib_ustream_forward_flush(&ustream_forward_instance, flush_callback, &my_consumer_context));
(void)printf("my_consumer_context.buffer = %s\r\n", my_consumer_context.buffer);
}
AZ_ULIB_CATCH(...) {}
return AZ_ULIB_TRY_RESULT;
}
int main(void)
{
az_result result;
if ((result = my_consumer()) != AZ_OK)
{
printf("my_consumer() failed\r\n");
}
return 0;
}

Просмотреть файл

@ -0,0 +1,165 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "az_ulib_port.h"
#include "az_ulib_result.h"
#include "az_ulib_ustream_forward.h"
#include "azure/core/az_span.h"
#include <azure/core/internal/az_precondition_internal.h>
#ifdef __clang__
#define IGNORE_POINTER_TYPE_QUALIFICATION \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wincompatible-pointer-types-discards-qualifiers\"")
#define IGNORE_MEMCPY_TO_NULL _Pragma("GCC diagnostic push")
#define RESUME_WARNINGS _Pragma("clang diagnostic pop")
#elif defined(__GNUC__)
#define IGNORE_POINTER_TYPE_QUALIFICATION \
_Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wdiscarded-qualifiers\"")
#define IGNORE_MEMCPY_TO_NULL _Pragma("GCC diagnostic push")
#define RESUME_WARNINGS _Pragma("GCC diagnostic pop")
#else
#define IGNORE_POINTER_TYPE_QUALIFICATION __pragma(warning(push));
#define IGNORE_MEMCPY_TO_NULL \
__pragma(warning(push)); \
__pragma(warning(suppress : 6387));
#define RESUME_WARNINGS __pragma(warning(pop));
#endif // __clang__
static az_result concrete_flush(
az_ulib_ustream_forward* ustream_forward,
az_ulib_flush_callback flush_callback,
az_ulib_callback_context flush_callback_context);
static az_result concrete_read(
az_ulib_ustream_forward* ustream_forward,
uint8_t* const buffer,
size_t buffer_length,
size_t* const size);
static size_t concrete_get_size(az_ulib_ustream_forward* ustream_forward);
static az_result concrete_dispose(az_ulib_ustream_forward* ustream_forward);
static const az_ulib_ustream_forward_interface api
= { concrete_flush, concrete_read, concrete_get_size, concrete_dispose };
static az_result concrete_flush(
az_ulib_ustream_forward* ustream_forward,
az_ulib_flush_callback flush_callback,
az_ulib_callback_context flush_callback_context)
{
// precondition checks
_az_PRECONDITION_NOT_NULL(ustream_forward);
_az_PRECONDITION(AZ_ULIB_USTREAM_FORWARD_IS_TYPE_OF(ustream_forward, api));
_az_PRECONDITION_NOT_NULL(flush_callback);
// get size of data
size_t buffer_size = concrete_get_size(ustream_forward);
// point to data
const uint8_t* buffer = (const uint8_t*)ustream_forward->_internal.ptr
+ ustream_forward->_internal.inner_current_position;
// invoke callback
(*flush_callback)(buffer, buffer_size, flush_callback_context);
return AZ_OK;
}
static az_result concrete_read(
az_ulib_ustream_forward* ustream_forward,
uint8_t* const buffer,
size_t buffer_length,
size_t* const size)
{
_az_PRECONDITION(AZ_ULIB_USTREAM_FORWARD_IS_TYPE_OF(ustream_forward, api));
_az_PRECONDITION_NOT_NULL(buffer);
_az_PRECONDITION(buffer_length > 0);
_az_PRECONDITION_NOT_NULL(size);
az_result result;
if (ustream_forward->_internal.inner_current_position >= ustream_forward->_internal.length)
{
*size = 0;
result = AZ_ULIB_EOF;
}
else
{
size_t remain_size = ustream_forward->_internal.length
- (size_t)ustream_forward->_internal.inner_current_position;
*size = (buffer_length < remain_size) ? buffer_length : remain_size;
/**
* Since pre-conditions can be disabled by the user, compilers throw a warning for a potential
* memcpy to `NULL`. We disable this warning knowing that it is the user's responsibility to
* assure `buffer` is a valid pointer when pre-conditions are disabled for release mode.
* See \ref Pre-conditions "https://azure.github.io/azure-sdk/clang_design.html#pre-conditions"
* for more details.
*/
IGNORE_MEMCPY_TO_NULL
memcpy(
buffer,
(const uint8_t*)ustream_forward->_internal.ptr
+ ustream_forward->_internal.inner_current_position,
*size);
RESUME_WARNINGS
ustream_forward->_internal.inner_current_position += *size;
result = AZ_OK;
}
return result;
}
static size_t concrete_get_size(az_ulib_ustream_forward* ustream_forward)
{
_az_PRECONDITION(AZ_ULIB_USTREAM_FORWARD_IS_TYPE_OF(ustream_forward, api));
return ustream_forward->_internal.length - ustream_forward->_internal.inner_current_position;
}
static az_result concrete_dispose(az_ulib_ustream_forward* ustream_forward)
{
_az_PRECONDITION(AZ_ULIB_USTREAM_FORWARD_IS_TYPE_OF(ustream_forward, api));
if (ustream_forward->_internal.data_release)
{
/* If `data_relese` was provided is because `ptr` is not `const`. So, we have an Warning
* exception here to remove the `const` qualification of the `ptr`. */
IGNORE_POINTER_TYPE_QUALIFICATION
ustream_forward->_internal.data_release(ustream_forward->_internal.ptr);
RESUME_WARNINGS
}
if (ustream_forward->_internal.ustream_forward_release)
{
ustream_forward->_internal.ustream_forward_release(ustream_forward);
}
return AZ_OK;
}
AZ_NODISCARD az_result az_ulib_ustream_forward_init(
az_ulib_ustream_forward* ustream_forward,
az_ulib_release_callback ustream_forward_release,
const uint8_t* const data_buffer,
size_t data_buffer_length,
az_ulib_release_callback data_buffer_release)
{
_az_PRECONDITION_NOT_NULL(ustream_forward);
_az_PRECONDITION_NOT_NULL(data_buffer);
_az_PRECONDITION(data_buffer_length > 0);
ustream_forward->_internal.api = &api;
ustream_forward->_internal.ptr = (const az_ulib_ustream_forward_data*)data_buffer;
ustream_forward->_internal.data_release = data_buffer_release;
ustream_forward->_internal.ustream_forward_release = ustream_forward_release;
ustream_forward->_internal.inner_current_position = 0;
ustream_forward->_internal.length = data_buffer_length;
return AZ_OK;
}

Просмотреть файл

@ -9,7 +9,9 @@ ulib_use_permissive_rules_for_samples_and_tests()
if(${UNIT_TESTING})
add_subdirectory(tests_ut/az_ulib_ipc_ut)
add_subdirectory(tests_ut/az_ulib_ustream_ut)
add_subdirectory(tests_ut/az_ulib_ustream_forward_ut)
add_subdirectory(tests_e2e/az_ulib_ipc_e2e)
add_subdirectory(tests_e2e/az_ulib_ustream_e2e)
add_subdirectory(tests_e2e/az_ulib_ustream_forward_e2e)
endif()

Просмотреть файл

@ -1,40 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
#ifndef AZ_ULIB_CTEST_AUX_H
#define AZ_ULIB_CTEST_AUX_H
#include <stdint.h>
#include "az_ulib_ustream_base.h"
#include "cmocka.h"
/**
* Check buffer
*/
static void check_buffer(
az_ulib_ustream* ustream_instance,
uint8_t offset,
const uint8_t* const expected_content,
uint8_t expected_content_length)
{
uint8_t buf_result[256];
size_t size_result;
if (offset < expected_content_length)
{
assert_int_equal(az_ulib_ustream_read(ustream_instance, buf_result, 256, &size_result), AZ_OK);
assert_int_equal(size_result, expected_content_length - offset);
assert_memory_equal((const uint8_t* const)(expected_content + offset), buf_result, size_result);
}
size_result = 10;
assert_int_equal(
az_ulib_ustream_read(ustream_instance, buf_result, 256, &size_result), AZ_ULIB_EOF);
assert_int_equal(size_result, 0);
}
#endif /* AZ_ULIB_CTEST_AUX_H */

Просмотреть файл

@ -0,0 +1,40 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
#ifndef AZ_ULIB_TEST_HELPERS_H
#define AZ_ULIB_TEST_HELPERS_H
#include "az_ulib_ustream_base.h"
#include "az_ulib_ustream_forward.h"
#ifdef __cplusplus
#include <cstdint>
extern "C"
{
#else
#include <stdint.h>
#endif /* __cplusplus */
/**
* Check buffer
*/
void check_buffer(
az_ulib_ustream* ustream_instance,
uint8_t offset,
const uint8_t* const expected_content,
uint8_t expected_content_length);
/**
* Check buffer
*/
void check_ustream_forward_buffer(
az_ulib_ustream_forward* ustream_forward,
uint8_t offset,
const uint8_t* const expected_content,
uint8_t expected_content_length);
#ifdef __cplusplus
{
#endif /* __cplusplus */
#endif /* AZ_ULIB_TEST_HELPERS_H */

Просмотреть файл

@ -5,7 +5,7 @@
#ifndef AZ_ULIB_USTREAM_COMPLIANCE_UT_H
#define AZ_ULIB_USTREAM_COMPLIANCE_UT_H
#include "az_ulib_ctest_aux.h"
#include "az_ulib_test_helpers.h"
#include "az_ulib_test_precondition.h"
#include "az_ulib_ustream_mock_buffer.h"

Просмотреть файл

@ -0,0 +1,119 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
#ifndef AZ_ULIB_USTREAM_FORWARD_COMPLIANCE_E2E_H
#define AZ_ULIB_USTREAM_FORWARD_COMPLIANCE_E2E_H
#include "az_ulib_ustream_mock_buffer.h"
#include "cmocka.h"
#ifdef __cplusplus
#include <cstdio>
extern "C"
{
#else
#include <stdio.h>
#endif /* __cplusplus */
/* check for test artifacts. */
#ifndef USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH
#error "USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH not defined"
#endif
#ifndef USTREAM_FORWARD_COMPLIANCE_TARGET_FACTORY
#error "USTREAM_FORWARD_COMPLIANCE_TARGET_FACTORY not defined"
#endif
#if (USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH / 20 == 0)
#error "USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH must be at least 20 uint8_t long"
#endif
/* split the content in 2 parts. */
#define USTREAM_FORWARD_COMPLIANCE_LENGTH_1 (USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH / 2)
#define USTREAM_FORWARD_COMPLIANCE_LENGTH_2 \
(USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH - USTREAM_FORWARD_COMPLIANCE_LENGTH_1)
/* create local buffer with enough size to handle the full content. */
#define USTREAM_FORWARD_COMPLIANCE_TEMP_BUFFER_LENGTH \
(USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH / 2)
static const uint8_t* const compliance_expected_content
= (const uint8_t*)USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT;
/**
* @brief E2e test flush callback.
*/
typedef struct ustream_forward_basic_context
{
offset_t offset;
char buffer[100];
} consumer_context;
static void flush_callback(
const uint8_t* const buffer,
size_t size,
az_ulib_callback_context flush_callback_context)
{
// handle buffer
consumer_context* flush_context = (consumer_context*)flush_callback_context;
(void)snprintf(
flush_context->buffer + flush_context->offset,
sizeof(flush_context->buffer) / sizeof(char),
"%s",
buffer);
// adjust offset
flush_context->offset += size;
}
/**
* Start compliance tests.
*/
/**
* In the event that read does not completely traverse the buffer, flush shall pick up where read
* left off and successfully hand off the remaining buffer to the flush callback.
*/
static void az_ulib_ustream_forward_e2e_compliance_read_flush_succeed(void** state)
{
/// arrange
(void)state;
az_ulib_ustream_forward* ustream_forward;
USTREAM_FORWARD_COMPLIANCE_TARGET_FACTORY(&ustream_forward);
uint8_t buf_result[USTREAM_FORWARD_COMPLIANCE_TEMP_BUFFER_LENGTH];
size_t size_result;
consumer_context test_consumer_context = { 0 };
/// act
az_result result_read = az_ulib_ustream_forward_read(
ustream_forward, buf_result, USTREAM_FORWARD_COMPLIANCE_TEMP_BUFFER_LENGTH, &size_result);
az_result result_flush
= az_ulib_ustream_forward_flush(ustream_forward, flush_callback, &test_consumer_context);
/// assert
assert_int_equal(result_read, AZ_OK);
assert_int_equal(size_result, USTREAM_FORWARD_COMPLIANCE_LENGTH_1);
assert_memory_equal(USTREAM_FORWARD_COMPLIANCE_LOCAL_EXPECTED_CONTENT, buf_result, size_result);
assert_int_equal(result_flush, AZ_OK);
assert_int_equal(test_consumer_context.offset, USTREAM_FORWARD_COMPLIANCE_LENGTH_2);
assert_memory_equal(
(const uint8_t* const)(
USTREAM_FORWARD_COMPLIANCE_LOCAL_EXPECTED_CONTENT + USTREAM_FORWARD_COMPLIANCE_LENGTH_1),
test_consumer_context.buffer,
size_result);
/// cleanup
az_result result = az_ulib_ustream_forward_dispose(ustream_forward);
(void)result;
}
#define AZ_ULIB_USTREAM_FORWARD_COMPLIANCE_E2E_LIST \
cmocka_unit_test(az_ulib_ustream_forward_e2e_compliance_read_flush_succeed)
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* AZ_ULIB_USTREAM_FORWARD_COMPLIANCE_E2E_H */

Просмотреть файл

@ -0,0 +1,614 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
#ifndef AZ_ULIB_USTREAM_FORWARD_COMPLIANCE_UT_H
#define AZ_ULIB_USTREAM_FORWARD_COMPLIANCE_UT_H
#include "az_ulib_test_helpers.h"
#include "az_ulib_test_precondition.h"
#include "az_ulib_ustream_forward_mock_buffer.h"
#include "cmocka.h"
/* check for test artifacts. */
#ifndef USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH
#error "USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH not defined"
#endif
#ifndef USTREAM_FORWARD_COMPLIANCE_TARGET_FACTORY
#error "USTREAM_FORWARD_COMPLIANCE_TARGET_FACTORY not defined"
#endif
#if (USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH / 20 == 0)
#error "USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH must be at least 20 uint8_t long"
#endif
/* split the content in 4 parts. */
#define USTREAM_FORWARD_COMPLIANCE_LENGTH_1 \
(USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH >> 2)
#define USTREAM_FORWARD_COMPLIANCE_LENGTH_2 \
(USTREAM_FORWARD_COMPLIANCE_LENGTH_1 + USTREAM_FORWARD_COMPLIANCE_LENGTH_1)
#define USTREAM_FORWARD_COMPLIANCE_LENGTH_3 \
(USTREAM_FORWARD_COMPLIANCE_LENGTH_2 + USTREAM_FORWARD_COMPLIANCE_LENGTH_1)
/* create local buffer with enough size to handle the full content. */
#define USTREAM_FORWARD_COMPLIANCE_TEMP_BUFFER_LENGTH \
(USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH + 2)
// flush callback global variables
static uint8_t* flush_callback_buffer_check[USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH]
= { 0 };
static size_t flush_callback_size_check = 0;
static az_ulib_callback_context flush_callback_context_check;
// mock callback function
static void mock_flush_callback(
const uint8_t* const buffer,
size_t size,
az_ulib_callback_context flush_callback_context)
{
(void)memcpy(flush_callback_buffer_check, buffer, size);
flush_callback_size_check = size;
flush_callback_context_check = flush_callback_context;
}
/*
* Start compliance tests:
*/
#ifndef AZ_NO_PRECONDITION_CHECKING
/* If the provided handle is NULL, the dispose shall fail with precondition. */
static void az_ulib_ustream_forward_dispose_compliance_null_buffer_failed(void** state)
{
/// arrange
(void)state;
az_ulib_ustream_forward* ustream_forward;
USTREAM_FORWARD_COMPLIANCE_TARGET_FACTORY(&ustream_forward);
/// act
/// assert
AZ_ULIB_ASSERT_PRECONDITION_CHECKED((ustream_forward)->_internal.api->dispose(NULL));
/// cleanup
az_result result = az_ulib_ustream_forward_dispose(ustream_forward);
(void)result;
}
/* If the provided handle is not the implemented buffer type, the dispose shall fail with
* precondition. */
static void az_ulib_ustream_forward_dispose_compliance_buffer_is_not_type_of_buffer_failed(
void** state)
{
/// arrange
(void)state;
az_ulib_ustream_forward* ustream_forward;
USTREAM_FORWARD_COMPLIANCE_TARGET_FACTORY(&ustream_forward);
/// act
/// assert
AZ_ULIB_ASSERT_PRECONDITION_CHECKED(
ustream_forward->_internal.api->dispose(ustream_forward_mock_create()));
/// cleanup
az_result result = az_ulib_ustream_forward_dispose(ustream_forward);
(void)result;
}
/* If the provided handle is NULL, the get_size shall fail with precondition. */
static void az_ulib_ustream_forward_get_size_compliance_null_buffer_failed(void** state)
{
/// arrange
(void)state;
az_ulib_ustream_forward* ustream_forward;
USTREAM_FORWARD_COMPLIANCE_TARGET_FACTORY(&ustream_forward);
/// act
/// assert
AZ_ULIB_ASSERT_PRECONDITION_CHECKED(ustream_forward->_internal.api->get_size(NULL));
/// cleanup
az_result result = az_ulib_ustream_forward_dispose(ustream_forward);
(void)result;
}
/* If the provided handle is not properly initialized, the get_size shall fail with precondition. */
static void az_ulib_ustream_forward_get_size_compliance_buffer_is_not_type_of_buffer_failed(
void** state)
{
/// arrange
(void)state;
az_ulib_ustream_forward* ustream_forward;
USTREAM_FORWARD_COMPLIANCE_TARGET_FACTORY(&ustream_forward);
/// act
/// assert
AZ_ULIB_ASSERT_PRECONDITION_CHECKED(
ustream_forward->_internal.api->get_size(ustream_forward_mock_create()));
/// cleanup
az_result result = az_ulib_ustream_forward_dispose(ustream_forward);
(void)result;
}
/* If the provided handle is NULL, the flush shall fail with precondition. */
static void az_ulib_ustream_forward_flush_compliance_null_handle_failed(void** state)
{
/// arrange
(void)state;
az_ulib_ustream_forward* ustream_forward;
USTREAM_FORWARD_COMPLIANCE_TARGET_FACTORY(&ustream_forward);
az_ulib_callback_context callback_context = { 0 };
/// act
/// assert
AZ_ULIB_ASSERT_PRECONDITION_CHECKED(
ustream_forward->_internal.api->flush(NULL, mock_flush_callback, callback_context));
/// cleanup
az_result result = az_ulib_ustream_forward_dispose(ustream_forward);
(void)result;
}
/* If the provided handle is not the implemented ustream_forward type, the flush shall fail with
* precondition.
*/
static void az_ulib_ustream_forward_flush_compliance_non_type_of_ustream_forward_api_failed(
void** state)
{
/// arrange
(void)state;
az_ulib_ustream_forward* ustream_forward;
USTREAM_FORWARD_COMPLIANCE_TARGET_FACTORY(&ustream_forward);
az_ulib_callback_context callback_context = { 0 };
/// act
/// assert
AZ_ULIB_ASSERT_PRECONDITION_CHECKED(ustream_forward->_internal.api->flush(
ustream_forward_mock_create(), mock_flush_callback, callback_context));
/// cleanup
az_result result = az_ulib_ustream_forward_dispose(ustream_forward);
(void)result;
}
/* If the provided flush_callback is NULL, the flush shall fail with precondition. */
static void az_ulib_ustream_forward_flush_compliance_null_flush_callback_failed(void** state)
{
/// arrange
(void)state;
az_ulib_ustream_forward* ustream_forward;
USTREAM_FORWARD_COMPLIANCE_TARGET_FACTORY(&ustream_forward);
az_ulib_callback_context callback_context = { 0 };
/// act
/// assert
AZ_ULIB_ASSERT_PRECONDITION_CHECKED(
ustream_forward->_internal.api->flush(ustream_forward, NULL, callback_context));
/// cleanup
az_result result = az_ulib_ustream_forward_dispose(ustream_forward);
(void)result;
}
static void az_ulib_ustream_forward_flush_compliance_single_buffer_succeed(void** state)
{
/// arrange
(void)state;
az_ulib_ustream_forward* ustream_forward;
USTREAM_FORWARD_COMPLIANCE_TARGET_FACTORY(&ustream_forward);
struct _test_context
{
uint8_t test_value;
} test_context = { 0 };
az_ulib_callback_context callback_context = (az_ulib_callback_context)&test_context;
/// act
az_result result
= az_ulib_ustream_forward_flush(ustream_forward, mock_flush_callback, callback_context);
/// assert
assert_int_equal(result, AZ_OK);
assert_int_equal(flush_callback_size_check, USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH);
assert_int_equal(flush_callback_context_check, callback_context);
assert_memory_equal(
USTREAM_FORWARD_COMPLIANCE_LOCAL_EXPECTED_CONTENT,
flush_callback_buffer_check,
flush_callback_size_check);
/// cleanup
result = az_ulib_ustream_forward_dispose(ustream_forward);
(void)result;
}
/* If the provided handle is NULL, the read shall fail with precondition. */
static void az_ulib_ustream_forward_read_compliance_null_handle_failed(void** state)
{
/// arrange
(void)state;
az_ulib_ustream_forward* ustream_forward;
USTREAM_FORWARD_COMPLIANCE_TARGET_FACTORY(&ustream_forward);
uint8_t buf_result[USTREAM_FORWARD_COMPLIANCE_TEMP_BUFFER_LENGTH];
size_t size_result;
/// act
/// assert
AZ_ULIB_ASSERT_PRECONDITION_CHECKED(ustream_forward->_internal.api->read(
NULL, buf_result, USTREAM_FORWARD_COMPLIANCE_TEMP_BUFFER_LENGTH, &size_result));
/// cleanup
az_result result = az_ulib_ustream_forward_dispose(ustream_forward);
(void)result;
}
/* If the provided handle is not the implemented buffer type, the read shall fail with precondition.
*/
static void az_ulib_ustream_forward_read_compliance_non_type_of_buffer_api_failed(void** state)
{
/// arrange
(void)state;
az_ulib_ustream_forward* ustream_forward;
USTREAM_FORWARD_COMPLIANCE_TARGET_FACTORY(&ustream_forward);
uint8_t buf_result[USTREAM_FORWARD_COMPLIANCE_TEMP_BUFFER_LENGTH];
size_t size_result;
/// act
/// assert
AZ_ULIB_ASSERT_PRECONDITION_CHECKED(ustream_forward->_internal.api->read(
ustream_forward_mock_create(),
buf_result,
USTREAM_FORWARD_COMPLIANCE_TEMP_BUFFER_LENGTH,
&size_result));
/// cleanup
az_result result = az_ulib_ustream_forward_dispose(ustream_forward);
(void)result;
}
/* If the provided buffer_length is zero, the read shall fail with precondition. */
static void az_ulib_ustream_forward_read_compliance_buffer_with_zero_size_failed(void** state)
{
/// arrange
(void)state;
az_ulib_ustream_forward* ustream_forward;
USTREAM_FORWARD_COMPLIANCE_TARGET_FACTORY(&ustream_forward);
uint8_t buf_result[USTREAM_FORWARD_COMPLIANCE_TEMP_BUFFER_LENGTH];
size_t size_result;
/// act
/// assert
AZ_ULIB_ASSERT_PRECONDITION_CHECKED(
az_ulib_ustream_forward_read(ustream_forward, buf_result, 0, &size_result));
/// cleanup
az_result result = az_ulib_ustream_forward_dispose(ustream_forward);
(void)result;
}
/* If the provided handle is NULL, the read shall fail with precondition. */
static void az_ulib_ustream_forward_read_compliance_null_return_buffer_failed(void** state)
{
/// arrange
(void)state;
az_ulib_ustream_forward* ustream_forward;
USTREAM_FORWARD_COMPLIANCE_TARGET_FACTORY(&ustream_forward);
size_t size_result;
/// act
/// assert
AZ_ULIB_ASSERT_PRECONDITION_CHECKED(az_ulib_ustream_forward_read(
ustream_forward, NULL, USTREAM_FORWARD_COMPLIANCE_TEMP_BUFFER_LENGTH, &size_result));
/// cleanup
az_result result = az_ulib_ustream_forward_dispose(ustream_forward);
(void)result;
}
/* If the provided return size pointer is NULL, the read shall fail with precondition. */
static void az_ulib_ustream_forward_read_compliance_null_return_size_failed(void** state)
{
/// arrange
(void)state;
az_ulib_ustream_forward* ustream_forward;
USTREAM_FORWARD_COMPLIANCE_TARGET_FACTORY(&ustream_forward);
uint8_t buf_result[USTREAM_FORWARD_COMPLIANCE_TEMP_BUFFER_LENGTH];
/// act
/// assert
AZ_ULIB_ASSERT_PRECONDITION_CHECKED(az_ulib_ustream_forward_read(
ustream_forward, buf_result, USTREAM_FORWARD_COMPLIANCE_TEMP_BUFFER_LENGTH, NULL));
/// cleanup
az_result result = az_ulib_ustream_forward_dispose(ustream_forward);
(void)result;
}
#endif // AZ_NO_PRECONDITION_CHECKING
/* The dispose shall release all allocated resources to control the buffer. */
static void az_ulib_ustream_forward_dispose_compliance_single_instance_succeed(void** state)
{
/// arrange
(void)state;
az_ulib_ustream_forward* ustream_forward;
USTREAM_FORWARD_COMPLIANCE_TARGET_FACTORY(&ustream_forward);
/// act
az_result result = az_ulib_ustream_forward_dispose(ustream_forward);
/// assert
assert_int_equal(result, AZ_OK);
/// cleanup
(void)result;
}
/* The get_size shall return the number of bytes between the current position and the end
* of the buffer. */
static void az_ulib_ustream_forward_get_size_compliance_new_buffer_succeed(void** state)
{
/// arrange
(void)state;
az_ulib_ustream_forward* ustream_forward;
USTREAM_FORWARD_COMPLIANCE_TARGET_FACTORY(&ustream_forward);
/// act
size_t size = az_ulib_ustream_forward_get_size(ustream_forward);
/// assert
assert_int_equal(size, USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH);
/// cleanup
az_result result = az_ulib_ustream_forward_dispose(ustream_forward);
(void)result;
}
/* [1]The read shall copy the content in the provided buffer and return the number of valid
* <tt>uint8_t</tt> values in the local buffer in the provided `size`. */
/* [2]If the length of the content is bigger than the `buffer_length`, the read shall limit the copy
* size to the buffer_length.*/
/* [3]If there is no more content to return, the read shall return AZ_ERROR_ITEM_NOT_FOUND,
* size shall receive 0, and do not change the content of the local buffer. */
static void az_ulib_ustream_forward_read_compliance_get_from_original_buffer_succeed(void** state)
{
/// arrange
(void)state;
az_ulib_ustream_forward* ustream_forward;
USTREAM_FORWARD_COMPLIANCE_TARGET_FACTORY(&ustream_forward);
uint8_t buf_result1[USTREAM_FORWARD_COMPLIANCE_TEMP_BUFFER_LENGTH];
uint8_t buf_result2[USTREAM_FORWARD_COMPLIANCE_TEMP_BUFFER_LENGTH];
uint8_t buf_result3[USTREAM_FORWARD_COMPLIANCE_TEMP_BUFFER_LENGTH];
size_t size_result1;
size_t size_result2;
size_t size_result3;
/// act
az_result result1 = az_ulib_ustream_forward_read(
ustream_forward, buf_result1, USTREAM_FORWARD_COMPLIANCE_LENGTH_1, &size_result1);
az_result result2 = az_ulib_ustream_forward_read(
ustream_forward, buf_result2, USTREAM_FORWARD_COMPLIANCE_TEMP_BUFFER_LENGTH, &size_result2);
az_result result3 = az_ulib_ustream_forward_read(
ustream_forward, buf_result3, USTREAM_FORWARD_COMPLIANCE_TEMP_BUFFER_LENGTH, &size_result3);
/// assert
assert_int_equal(result1, AZ_OK);
assert_int_equal(size_result1, USTREAM_FORWARD_COMPLIANCE_LENGTH_1);
assert_memory_equal(USTREAM_FORWARD_COMPLIANCE_LOCAL_EXPECTED_CONTENT, buf_result1, size_result1);
assert_int_equal(result2, AZ_OK);
assert_int_equal(
size_result2,
USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH - USTREAM_FORWARD_COMPLIANCE_LENGTH_1);
assert_memory_equal(
(const uint8_t* const)(
USTREAM_FORWARD_COMPLIANCE_LOCAL_EXPECTED_CONTENT + USTREAM_FORWARD_COMPLIANCE_LENGTH_1),
buf_result2,
size_result2);
assert_int_equal(result3, AZ_ULIB_EOF);
/// cleanup
az_result result = az_ulib_ustream_forward_dispose(ustream_forward);
(void)result;
}
static void az_ulib_ustream_forward_read_compliance_single_buffer_succeed(void** state)
{
/// arrange
(void)state;
az_ulib_ustream_forward* ustream_forward;
USTREAM_FORWARD_COMPLIANCE_TARGET_FACTORY(&ustream_forward);
uint8_t buf_result[USTREAM_FORWARD_COMPLIANCE_TEMP_BUFFER_LENGTH];
size_t size_result;
/// act
az_result result = az_ulib_ustream_forward_read(
ustream_forward, buf_result, USTREAM_FORWARD_COMPLIANCE_TEMP_BUFFER_LENGTH, &size_result);
/// assert
assert_int_equal(result, AZ_OK);
assert_int_equal(size_result, USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH);
assert_memory_equal(USTREAM_FORWARD_COMPLIANCE_LOCAL_EXPECTED_CONTENT, buf_result, size_result);
/// cleanup
result = az_ulib_ustream_forward_dispose(ustream_forward);
(void)result;
}
static void az_ulib_ustream_forward_read_compliance_right_boundary_condition_succeed(void** state)
{
/// arrange
(void)state;
az_ulib_ustream_forward* ustream_forward;
USTREAM_FORWARD_COMPLIANCE_TARGET_FACTORY(&ustream_forward);
uint8_t buf_result[USTREAM_FORWARD_COMPLIANCE_TEMP_BUFFER_LENGTH];
size_t size_result;
/// act
az_result result = az_ulib_ustream_forward_read(
ustream_forward,
buf_result,
USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH - 1,
&size_result);
/// assert
assert_int_equal(result, AZ_OK);
assert_int_equal(size_result, USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH - 1);
assert_memory_equal(USTREAM_FORWARD_COMPLIANCE_LOCAL_EXPECTED_CONTENT, buf_result, size_result);
assert_int_equal(
az_ulib_ustream_forward_read(
ustream_forward, buf_result, USTREAM_FORWARD_COMPLIANCE_TEMP_BUFFER_LENGTH, &size_result),
AZ_OK);
assert_int_equal(size_result, 1);
assert_memory_equal(
(const uint8_t* const)(
USTREAM_FORWARD_COMPLIANCE_LOCAL_EXPECTED_CONTENT
+ USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH - 1),
buf_result,
size_result);
assert_int_equal(
az_ulib_ustream_forward_read(
ustream_forward, buf_result, USTREAM_FORWARD_COMPLIANCE_TEMP_BUFFER_LENGTH, &size_result),
AZ_ULIB_EOF);
/// cleanup
result = az_ulib_ustream_forward_dispose(ustream_forward);
(void)result;
}
static void az_ulib_ustream_forward_read_compliance_boundary_condition_succeed(void** state)
{
/// arrange
(void)state;
az_ulib_ustream_forward* ustream_forward;
USTREAM_FORWARD_COMPLIANCE_TARGET_FACTORY(&ustream_forward);
uint8_t buf_result[USTREAM_FORWARD_COMPLIANCE_TEMP_BUFFER_LENGTH];
size_t size_result;
/// act
az_result result = az_ulib_ustream_forward_read(
ustream_forward,
buf_result,
USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH,
&size_result);
/// assert
assert_int_equal(result, AZ_OK);
assert_int_equal(size_result, USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH);
assert_memory_equal(USTREAM_FORWARD_COMPLIANCE_LOCAL_EXPECTED_CONTENT, buf_result, size_result);
assert_int_equal(
az_ulib_ustream_forward_read(
ustream_forward, buf_result, USTREAM_FORWARD_COMPLIANCE_TEMP_BUFFER_LENGTH, &size_result),
AZ_ULIB_EOF);
/// cleanup
result = az_ulib_ustream_forward_dispose(ustream_forward);
(void)result;
}
static void az_ulib_ustream_forward_read_compliance_left_boundary_condition_succeed(void** state)
{
/// arrange
(void)state;
az_ulib_ustream_forward* ustream_forward;
USTREAM_FORWARD_COMPLIANCE_TARGET_FACTORY(&ustream_forward);
uint8_t buf_result[USTREAM_FORWARD_COMPLIANCE_TEMP_BUFFER_LENGTH];
size_t size_result;
/// act
az_result result = az_ulib_ustream_forward_read(
ustream_forward,
buf_result,
USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH + 1,
&size_result);
/// assert
assert_int_equal(result, AZ_OK);
assert_int_equal(size_result, USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH);
assert_memory_equal(USTREAM_FORWARD_COMPLIANCE_LOCAL_EXPECTED_CONTENT, buf_result, size_result);
assert_int_equal(
az_ulib_ustream_forward_read(
ustream_forward, buf_result, USTREAM_FORWARD_COMPLIANCE_TEMP_BUFFER_LENGTH, &size_result),
AZ_ULIB_EOF);
/// cleanup
result = az_ulib_ustream_forward_dispose(ustream_forward);
(void)result;
}
static void az_ulib_ustream_forward_read_compliance_single_byte_succeed(void** state)
{
/// arrange
(void)state;
az_ulib_ustream_forward* ustream_forward;
USTREAM_FORWARD_COMPLIANCE_TARGET_FACTORY(&ustream_forward);
uint8_t buf_result[USTREAM_FORWARD_COMPLIANCE_TEMP_BUFFER_LENGTH];
size_t size_result;
/// act
az_result result = az_ulib_ustream_forward_read(ustream_forward, buf_result, 1, &size_result);
/// assert
assert_int_equal(result, AZ_OK);
assert_int_equal(size_result, 1);
assert_memory_equal(USTREAM_FORWARD_COMPLIANCE_LOCAL_EXPECTED_CONTENT, buf_result, size_result);
check_ustream_forward_buffer(
ustream_forward,
1,
USTREAM_FORWARD_COMPLIANCE_LOCAL_EXPECTED_CONTENT,
USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH);
/// cleanup
result = az_ulib_ustream_forward_dispose(ustream_forward);
(void)result;
}
#define AZ_ULIB_USTREAM_FORWARD_PRECONDITION_COMPLIANCE_UT_LIST \
cmocka_unit_test(az_ulib_ustream_forward_dispose_compliance_null_buffer_failed), \
cmocka_unit_test( \
az_ulib_ustream_forward_dispose_compliance_buffer_is_not_type_of_buffer_failed), \
cmocka_unit_test(az_ulib_ustream_forward_get_size_compliance_null_buffer_failed), \
cmocka_unit_test( \
az_ulib_ustream_forward_get_size_compliance_buffer_is_not_type_of_buffer_failed), \
cmocka_unit_test(az_ulib_ustream_forward_flush_compliance_null_handle_failed), \
cmocka_unit_test( \
az_ulib_ustream_forward_flush_compliance_non_type_of_ustream_forward_api_failed), \
cmocka_unit_test(az_ulib_ustream_forward_flush_compliance_null_flush_callback_failed), \
cmocka_unit_test(az_ulib_ustream_forward_read_compliance_null_handle_failed), \
cmocka_unit_test(az_ulib_ustream_forward_read_compliance_non_type_of_buffer_api_failed), \
cmocka_unit_test(az_ulib_ustream_forward_read_compliance_buffer_with_zero_size_failed), \
cmocka_unit_test(az_ulib_ustream_forward_read_compliance_null_return_buffer_failed), \
cmocka_unit_test(az_ulib_ustream_forward_read_compliance_null_return_size_failed),
#define AZ_ULIB_USTREAM_FORWARD_COMPLIANCE_UT_LIST \
cmocka_unit_test_setup_teardown( \
az_ulib_ustream_forward_dispose_compliance_single_instance_succeed, setup, teardown), \
cmocka_unit_test_setup_teardown( \
az_ulib_ustream_forward_get_size_compliance_new_buffer_succeed, setup, teardown), \
cmocka_unit_test_setup_teardown( \
az_ulib_ustream_forward_flush_compliance_single_buffer_succeed, setup, teardown), \
cmocka_unit_test_setup_teardown( \
az_ulib_ustream_forward_read_compliance_get_from_original_buffer_succeed, \
setup, \
teardown), \
cmocka_unit_test_setup_teardown( \
az_ulib_ustream_forward_read_compliance_single_buffer_succeed, setup, teardown), \
cmocka_unit_test_setup_teardown( \
az_ulib_ustream_forward_read_compliance_right_boundary_condition_succeed, \
setup, \
teardown), \
cmocka_unit_test_setup_teardown( \
az_ulib_ustream_forward_read_compliance_boundary_condition_succeed, setup, teardown), \
cmocka_unit_test_setup_teardown( \
az_ulib_ustream_forward_read_compliance_left_boundary_condition_succeed, \
setup, \
teardown), \
cmocka_unit_test_setup_teardown( \
az_ulib_ustream_forward_read_compliance_single_byte_succeed, setup, teardown),
#endif /* AZ_ULIB_USTREAM_FORWARD_COMPLIANCE_UT_H */

Просмотреть файл

@ -0,0 +1,30 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
#ifndef AZ_ULIB_USTREAM_FORWARD_MOCK_BUFFER_H
#define AZ_ULIB_USTREAM_FORWARD_MOCK_BUFFER_H
#include "az_ulib_ustream_forward.h"
#include <stdint.h>
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
az_ulib_ustream_forward* ustream_forward_mock_create(void);
void reset_mock_buffer(void);
void set_concurrency_ustream_forward(void);
void set_delay_return_value(uint32_t delay);
void set_flush_result(az_result result);
void set_read_result(az_result result);
void set_dispose_result(az_result result);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* AZ_ULIB_USTREAM_FORWARD_MOCK_BUFFER_H */

Просмотреть файл

@ -6,11 +6,13 @@
#define AZ_ULIB_USTREAM_MOCK_BUFFER_H
#include "az_ulib_ustream_base.h"
#include <stdbool.h>
#ifdef __cplusplus
#include <cstdint>
extern "C"
{
#else
#include <stdint.h>
#endif /* __cplusplus */
az_ulib_ustream* ustream_mock_create(void);

Просмотреть файл

@ -0,0 +1,60 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
#include <setjmp.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "az_ulib_test_helpers.h"
#include "cmocka.h"
void check_buffer(
az_ulib_ustream* ustream_instance,
uint8_t offset,
const uint8_t* const expected_content,
uint8_t expected_content_length)
{
uint8_t buf_result[256];
size_t size_result;
if (offset < expected_content_length)
{
assert_int_equal(az_ulib_ustream_read(ustream_instance, buf_result, 256, &size_result), AZ_OK);
assert_int_equal(size_result, expected_content_length - offset);
assert_memory_equal((const uint8_t* const)(expected_content + offset), buf_result, size_result);
}
size_result = 10;
assert_int_equal(
az_ulib_ustream_read(ustream_instance, buf_result, 256, &size_result), AZ_ULIB_EOF);
assert_int_equal(size_result, 0);
}
void check_ustream_forward_buffer(
az_ulib_ustream_forward* ustream_forward,
uint8_t offset,
const uint8_t* const expected_content,
uint8_t expected_content_length)
{
uint8_t buf_result[256];
size_t size_result;
if (offset < expected_content_length)
{
assert_int_equal(az_ulib_ustream_forward_read(ustream_forward, buf_result, 256, &size_result), AZ_OK);
assert_int_equal(size_result, expected_content_length - offset);
assert_memory_equal((const uint8_t* const)(expected_content + offset), buf_result, size_result);
}
size_result = 10;
assert_int_equal(
az_ulib_ustream_forward_read(ustream_forward, buf_result, 256, &size_result), AZ_ULIB_EOF);
assert_int_equal(size_result, 0);
}

Просмотреть файл

@ -0,0 +1,105 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
#include "az_ulib_result.h"
#include "az_ulib_test_thread.h"
#include "az_ulib_ustream_base.h"
#include "az_ulib_ustream_forward_mock_buffer.h"
#include <stdbool.h>
static az_result _concrete_flush_result = AZ_OK;
static az_result _concrete_read_result = AZ_OK;
static az_result _concrete_dispose_result = AZ_OK;
static offset_t current_position = 0;
static bool concurrency_ustream_forward = false;
static uint32_t delay_return_value = 0;
void reset_mock_buffer(void)
{
current_position = 0;
concurrency_ustream_forward = false;
delay_return_value = 0;
}
void set_concurrency_ustream_forward(void) { concurrency_ustream_forward = true; }
void set_delay_return_value(uint32_t delay) { delay_return_value = delay; }
static az_result concrete_flush(
az_ulib_ustream_forward* ustream_forward,
az_ulib_flush_callback flush_callback,
az_ulib_callback_context flush_callback_context)
{
(void)ustream_forward;
(void)flush_callback;
(void)flush_callback_context;
az_result result = _concrete_flush_result;
_concrete_flush_result = AZ_OK;
return result;
}
static az_result concrete_read(
az_ulib_ustream_forward* ustream_forward,
uint8_t* const buffer,
size_t buffer_length,
size_t* const size)
{
(void)ustream_forward;
(void)buffer;
(void)size;
current_position += buffer_length;
*size = buffer_length;
az_result result = _concrete_read_result;
_concrete_read_result = AZ_OK;
return result;
}
static size_t concrete_get_size(az_ulib_ustream_forward* ustream_forward)
{
(void)ustream_forward;
return 10;
}
static az_result concrete_dispose(az_ulib_ustream_forward* ustream_forward)
{
(void)ustream_forward;
az_result result = _concrete_dispose_result;
_concrete_dispose_result = AZ_OK;
return result;
}
static const az_ulib_ustream_forward_interface api
= { concrete_flush, concrete_read, concrete_get_size, concrete_dispose };
static az_ulib_ustream_forward USTREAM_FORWARD_COMPLIANCE_MOCK_BUFFER
= { ._internal.api = (const az_ulib_ustream_forward_interface*)&api,
._internal.ptr = NULL,
._internal.data_release = NULL,
._internal.ustream_forward_release = NULL,
._internal.inner_current_position = 0,
._internal.length = 10 };
az_ulib_ustream_forward* ustream_forward_mock_create(void)
{
_concrete_flush_result = AZ_OK;
_concrete_read_result = AZ_OK;
_concrete_dispose_result = AZ_OK;
return &USTREAM_FORWARD_COMPLIANCE_MOCK_BUFFER;
}
void set_flush_result(az_result result) { _concrete_flush_result = result; }
void set_read_result(az_result result) { _concrete_read_result = result; }
void set_dispose_result(az_result result) { _concrete_dispose_result = result; }

Просмотреть файл

@ -2,9 +2,10 @@
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
#include "az_ulib_ustream_mock_buffer.h"
#include "az_ulib_result.h"
#include "az_ulib_test_thread.h"
#include "az_ulib_ustream_base.h"
#include "az_ulib_ustream_mock_buffer.h"
#include <stdbool.h>
static az_result _concrete_set_position_result = AZ_OK;

Просмотреть файл

@ -0,0 +1,22 @@
#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.10)
project(az_ulib_ustream_forward_e2e)
include(AddCMockaTest)
add_cmocka_test(az_ulib_ustream_forward_e2e SOURCES
main.c
az_ulib_ustream_forward_e2e.c
${TEST_DIRECTORY}/src/az_ulib_ustream_forward_mock_buffer.c
COMPILE_OPTIONS ${DEFAULT_C_COMPILE_FLAGS} ${NO_CLOBBERED_WARNING}
LINK_LIBRARIES ${CMOCKA_LIBRARIES} azure_ulib_c ${PAL} az::cmocka
LINK_OPTIONS ${WRAP_FUNCTIONS}
# include cmoka headers and private folder headers
INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}/deps/cmocka/include ${CMAKE_SOURCE_DIR}/inc/ ${CMAKE_SOURCE_DIR}/tests/inc/
)
add_cmocka_test_environment(az_ulib_ustream_forward_e2e)

Просмотреть файл

@ -0,0 +1,59 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
#include <setjmp.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "az_ulib_ustream_forward.h"
#include "az_ulib_ustream_forward_e2e.h"
#include "az_ulib_ustream_forward_mock_buffer.h"
#include "cmocka.h"
/* define constants for the compliance test */
#define USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT \
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
#define USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH 62
static const uint8_t* const USTREAM_FORWARD_COMPLIANCE_LOCAL_EXPECTED_CONTENT
= (const uint8_t* const)USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT;
static void ustream_forward_factory(az_ulib_ustream_forward** ustream_forward)
{
*ustream_forward = (az_ulib_ustream_forward*)malloc(sizeof(az_ulib_ustream_forward));
uint8_t* buf
= (uint8_t*)malloc(sizeof(uint8_t) * USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH);
assert_non_null(buf);
(void)memcpy(
buf,
USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT,
USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH);
assert_int_equal(
az_ulib_ustream_forward_init(
*ustream_forward, free, buf, USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH, free),
AZ_OK);
}
#define USTREAM_FORWARD_COMPLIANCE_TARGET_FACTORY(ustream_forward) \
ustream_forward_factory(ustream_forward)
#define TEST_CONST_BUFFER_LENGTH (USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH + 2)
#define TEST_CONST_MAX_BUFFER_SIZE (TEST_CONST_BUFFER_LENGTH - 1)
/**
* Beginning of the e2e for ustream_forward.c on ownership model.
*/
// Run e2e compliance tests for ustream_forward
#include "az_ulib_ustream_forward_compliance_e2e.h"
int az_ulib_ustream_forward_e2e()
{
const struct CMUnitTest tests[] = { AZ_ULIB_USTREAM_FORWARD_COMPLIANCE_E2E_LIST };
return cmocka_run_group_tests_name("az_ulib_ustream_forward_e2e", tests, NULL, NULL);
}

Просмотреть файл

@ -0,0 +1,19 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
#ifndef AZ_ULIB_USTREAM_FORWARD_E2E_H
#define AZ_ULIB_USTREAM_FORWARD_E2E_H
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
int az_ulib_ustream_forward_e2e();
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* AZ_ULIB_USTREAM_FORWARD_E2E_H */

Просмотреть файл

@ -0,0 +1,17 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
#include <stdio.h>
#include "az_ulib_ustream_forward_e2e.h"
int main(void)
{
int result = 0;
(void)printf("[==========]\r\n[ STARTING ] Running az_ulib_ustream_forward_e2e.\r\n");
result += az_ulib_ustream_forward_e2e();
return result;
}

Просмотреть файл

@ -0,0 +1,23 @@
#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.10)
project(az_ulib_ustream_forward_ut)
include(AddCMockaTest)
add_cmocka_test(az_ulib_ustream_forward_ut SOURCES
main.c
az_ulib_ustream_forward_ut.c
${TEST_DIRECTORY}/src/az_ulib_test_helpers.c
${TEST_DIRECTORY}/src/az_ulib_ustream_forward_mock_buffer.c
COMPILE_OPTIONS ${DEFAULT_C_COMPILE_FLAGS} ${NO_CLOBBERED_WARNING}
LINK_LIBRARIES ${CMOCKA_LIBRARIES} azure_ulib_c ${PAL} az::cmocka
LINK_OPTIONS ${WRAP_FUNCTIONS}
# include cmoka headers and private folder headers
INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}/deps/cmocka/include ${CMAKE_SOURCE_DIR}/inc/ ${CMAKE_SOURCE_DIR}/tests/inc/
)
add_cmocka_test_environment(az_ulib_ustream_forward_ut)

Просмотреть файл

@ -0,0 +1,203 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
#include <setjmp.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "az_ulib_ustream_forward.h"
#include "az_ulib_ustream_forward_ut.h"
#include "az_ulib_ustream_forward_mock_buffer.h"
#include "az_ulib_test_precondition.h"
#include "azure/core/az_precondition.h"
#include "cmocka.h"
/* define constants for the compliance test */
#define USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT \
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
#define USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH 62
static const uint8_t* const USTREAM_FORWARD_COMPLIANCE_LOCAL_EXPECTED_CONTENT
= (const uint8_t* const)USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT;
static az_ulib_ustream_forward test_ustream_forward;
static void ustream_forward_factory(az_ulib_ustream_forward** ustream_forward)
{
*ustream_forward = (az_ulib_ustream_forward*)malloc(sizeof(az_ulib_ustream_forward));
uint8_t* buf
= (uint8_t*)malloc(sizeof(uint8_t) * USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH);
assert_non_null(buf);
(void)memcpy(
buf,
USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT,
USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH);
assert_int_equal(
az_ulib_ustream_forward_init(
*ustream_forward, free, buf, USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH, free),
AZ_OK);
}
#define USTREAM_FORWARD_COMPLIANCE_TARGET_FACTORY(ustream_forward) \
ustream_forward_factory(ustream_forward)
#define TEST_CONST_BUFFER_LENGTH (USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH + 2)
#define TEST_CONST_MAX_BUFFER_SIZE (TEST_CONST_BUFFER_LENGTH - 1)
#ifndef AZ_NO_PRECONDITION_CHECKING
AZ_ULIB_ENABLE_PRECONDITION_CHECK_TESTS()
#endif // AZ_NO_PRECONDITION_CHECKING
/**
* Beginning of the UT for ustream_forward.c on ownership model.
*/
static int setup(void** state)
{
(void)state;
memset(&test_ustream_forward, 0, sizeof(az_ulib_ustream_forward));
return 0;
}
static int teardown(void** state)
{
(void)state;
reset_mock_buffer();
return 0;
}
#ifndef AZ_NO_PRECONDITION_CHECKING
/* az_ulib_ustream_forward_init shall fail with precondition if the provided buffer is NULL. */
static void az_ulib_ustream_forward_init_null_buffer_failed(void** state)
{
/// arrange
(void)state;
az_ulib_ustream_forward ustream_forward;
/// act
/// assert
AZ_ULIB_ASSERT_PRECONDITION_CHECKED(az_ulib_ustream_forward_init(
&ustream_forward, NULL, NULL, USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH, NULL));
/// cleanup
}
/* az_ulib_ustream_forward_init shall fail with precondition if the provided buffer length is zero.
*/
static void az_ulib_ustream_forward_init_zero_length_failed(void** state)
{
/// arrange
(void)state;
az_ulib_ustream_forward ustream_forward;
/// act
/// assert
AZ_ULIB_ASSERT_PRECONDITION_CHECKED(az_ulib_ustream_forward_init(
&ustream_forward, NULL, USTREAM_FORWARD_COMPLIANCE_LOCAL_EXPECTED_CONTENT, 0, NULL));
/// cleanup
}
/* az_ulib_ustream_forward_init shall fail with precondition if the provided ustream_forward
is NULL. */
static void az_ulib_ustream_forward_init_NULL_ustream_forward_instance_failed(void** state)
{
/// arrange
(void)state;
/// act
/// assert
AZ_ULIB_ASSERT_PRECONDITION_CHECKED(az_ulib_ustream_forward_init(
NULL,
NULL,
USTREAM_FORWARD_COMPLIANCE_LOCAL_EXPECTED_CONTENT,
USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH,
NULL));
/// cleanup
}
#endif // AZ_NO_PRECONDITION_CHECKING
/* az_ulib_ustream_forward_init shall create an instance of the ustream_forward and initialize the
* instance. */
static void az_ulib_ustream_forward_init_const_succeed(void** state)
{
/// arrange
(void)state;
az_ulib_ustream_forward ustream_forward;
/// act
az_result result = az_ulib_ustream_forward_init(
&ustream_forward,
NULL,
USTREAM_FORWARD_COMPLIANCE_LOCAL_EXPECTED_CONTENT,
USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH,
NULL);
/// assert
assert_int_equal(result, AZ_OK);
/// cleanup
result = az_ulib_ustream_forward_dispose(&ustream_forward);
(void)result;
}
/* az_ulib_ustream_forward_init shall create an instance of the ustream_forward and initialize the
* instance. */
static void az_ulib_ustream_forward_init_succeed(void** state)
{
/// arrange
(void)state;
uint8_t* buf
= (uint8_t*)malloc(sizeof(uint8_t) * USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH);
assert_non_null(buf);
(void)memcpy(
buf,
USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT,
USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH);
az_ulib_ustream_forward ustream_forward;
/// act
az_result result = az_ulib_ustream_forward_init(
&ustream_forward, NULL, buf, USTREAM_FORWARD_COMPLIANCE_EXPECTED_CONTENT_LENGTH, free);
/// assert
assert_int_equal(result, AZ_OK);
/// cleanup
result = az_ulib_ustream_forward_dispose(&ustream_forward);
(void)result;
}
#include "az_ulib_ustream_forward_compliance_ut.h"
int az_ulib_ustream_forward_ut()
{
#ifndef AZ_NO_PRECONDITION_CHECKING
AZ_ULIB_SETUP_PRECONDITION_CHECK_TESTS();
#endif // AZ_NO_PRECONDITION_CHECKING
const struct CMUnitTest tests[] = {
#ifndef AZ_NO_PRECONDITION_CHECKING
cmocka_unit_test(az_ulib_ustream_forward_init_null_buffer_failed),
cmocka_unit_test(az_ulib_ustream_forward_init_zero_length_failed),
cmocka_unit_test(az_ulib_ustream_forward_init_NULL_ustream_forward_instance_failed),
#endif // AZ_NO_PRECONDITION_CHECKING
cmocka_unit_test_setup_teardown(az_ulib_ustream_forward_init_const_succeed, setup, teardown),
cmocka_unit_test_setup_teardown(az_ulib_ustream_forward_init_succeed, setup, teardown),
#ifndef AZ_NO_PRECONDITION_CHECKING
AZ_ULIB_USTREAM_FORWARD_PRECONDITION_COMPLIANCE_UT_LIST
#endif // AZ_NO_PRECONDITION_CHECKING
AZ_ULIB_USTREAM_FORWARD_COMPLIANCE_UT_LIST
};
return cmocka_run_group_tests_name("az_ulib_ustream_forward_ut", tests, NULL, NULL);
}

Просмотреть файл

@ -0,0 +1,19 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
#ifndef AZ_ULIB_USTREAM_FORWARD_UT_H
#define AZ_ULIB_USTREAM_FORWARD_UT_H
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
int az_ulib_ustream_forward_ut();
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* AZ_ULIB_USTREAM_FORWARD_UT_H */

Просмотреть файл

@ -0,0 +1,17 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
#include <stdio.h>
#include "az_ulib_ustream_forward_ut.h"
int main(void)
{
int result = 0;
(void)printf("[==========]\r\n[ STARTING ] Running az_ulib_ustream_ut.\r\n");
result += az_ulib_ustream_forward_ut();
return result;
}

Просмотреть файл

@ -12,6 +12,7 @@ add_cmocka_test(az_ulib_ustream_ut SOURCES
main.c
az_ulib_ustream_ut.c
az_ulib_ustream_aux_ut.c
${TEST_DIRECTORY}/src/az_ulib_test_helpers.c
${TEST_DIRECTORY}/src/az_ulib_ustream_mock_buffer.c
${TEST_DIRECTORY}/src/${ULIB_PAL_OS_DIRECTORY}/az_ulib_test_thread.c
COMPILE_OPTIONS ${DEFAULT_C_COMPILE_FLAGS} ${NO_CLOBBERED_WARNING}

Просмотреть файл

@ -12,7 +12,7 @@
#include "az_ulib_ustream.h"
#include "az_ulib_ustream_ut.h"
#include "az_ulib_ctest_aux.h"
#include "az_ulib_test_helpers.h"
#include "az_ulib_ustream_mock_buffer.h"
#include "az_ulib_test_precondition.h"