Resend on http & mqtt DPS transient error

This commit is contained in:
jebrando 2018-06-29 15:24:22 -07:00
Родитель dbaf949247
Коммит 21cd0fe8b8
7 изменённых файлов: 284 добавлений и 39 удалений

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

@ -16,6 +16,20 @@ extern "C" {
#include <stdbool.h>
#endif /* __cplusplus */
#define PROV_STATUS_CODE_TRANSIENT_ERROR 429
#define PROV_DEVICE_TRANSPORT_STATUS_VALUES \
PROV_DEVICE_TRANSPORT_STATUS_CONNECTED, \
PROV_DEVICE_TRANSPORT_STATUS_AUTHENTICATED, \
PROV_DEVICE_TRANSPORT_STATUS_UNASSIGNED, \
PROV_DEVICE_TRANSPORT_STATUS_ASSIGNING, \
PROV_DEVICE_TRANSPORT_STATUS_ASSIGNED, \
PROV_DEVICE_TRANSPORT_STATUS_BLACKLISTED, \
PROV_DEVICE_TRANSPORT_STATUS_TRANSIENT, \
PROV_DEVICE_TRANSPORT_STATUS_ERROR
DEFINE_ENUM(PROV_DEVICE_TRANSPORT_STATUS, PROV_DEVICE_TRANSPORT_STATUS_VALUES);
typedef struct PROV_JSON_INFO_TAG
{
PROV_DEVICE_TRANSPORT_STATUS prov_status;

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

@ -33,17 +33,6 @@ extern "C" {
DEFINE_ENUM(PROV_DEVICE_TRANSPORT_RESULT, PROV_DEVICE_TRANSPORT_RESULT_VALUES);
#define PROV_DEVICE_TRANSPORT_STATUS_VALUES \
PROV_DEVICE_TRANSPORT_STATUS_CONNECTED, \
PROV_DEVICE_TRANSPORT_STATUS_AUTHENTICATED, \
PROV_DEVICE_TRANSPORT_STATUS_UNASSIGNED, \
PROV_DEVICE_TRANSPORT_STATUS_ASSIGNING, \
PROV_DEVICE_TRANSPORT_STATUS_ASSIGNED, \
PROV_DEVICE_TRANSPORT_STATUS_BLACKLISTED, \
PROV_DEVICE_TRANSPORT_STATUS_ERROR
DEFINE_ENUM(PROV_DEVICE_TRANSPORT_STATUS, PROV_DEVICE_TRANSPORT_STATUS_VALUES);
#ifdef __cplusplus
}
#endif /* __cplusplus */

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

@ -494,6 +494,21 @@ static void on_transport_status(PROV_DEVICE_TRANSPORT_STATUS transport_status, v
}
}
break;
case PROV_DEVICE_TRANSPORT_STATUS_TRANSIENT:
if (prov_info->prov_state == CLIENT_STATE_REGISTER_SENT)
{
prov_info->prov_state = CLIENT_STATE_REGISTER_SEND;
}
else if (prov_info->prov_state == CLIENT_STATE_STATUS_SENT)
{
prov_info->prov_state = CLIENT_STATE_STATUS_SEND;
}
else
{
// Ideally this should not happen
LogError("State Error: Transient Error occured in the %d state", (int)transport_status);
}
break;
default:
LogError("Unknown status encountered");
break;

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

@ -19,10 +19,10 @@
#include "azure_uhttp_c/uhttp.h"
#include "parson.h"
#define HTTP_PORT_NUM 443
#define HTTP_STATUS_CODE_OK 200
#define HTTP_STATUS_CODE_OK_MAX 226
#define HTTP_STATUS_CODE_UNAUTHORIZED 401
#define HTTP_PORT_NUM 443
#define HTTP_STATUS_CODE_OK 200
#define HTTP_STATUS_CODE_OK_MAX 226
#define HTTP_STATUS_CODE_UNAUTHORIZED 401
static const char* PROV_REGISTRATION_URI_FMT = "/%s/registrations/%s/register?api-version=%s";
static const char* PROV_OP_STATUS_URI_FMT = "/%s/registrations/%s/operations/%s?api-version=%s";
@ -53,6 +53,8 @@ typedef enum PROV_TRANSPORT_STATE_TAG
TRANSPORT_CLIENT_STATE_STATUS_SENT,
TRANSPORT_CLIENT_STATE_STATUS_RECV,
TRANSPORT_CLIENT_STATE_TRANSIENT,
TRANSPORT_CLIENT_STATE_ERROR
} PROV_TRANSPORT_STATE;
@ -169,6 +171,11 @@ static void on_http_reply_recv(void* callback_ctx, HTTP_CALLBACK_REASON request_
}
}
}
else if (status_code > PROV_STATUS_CODE_TRANSIENT_ERROR)
{
// On transient error reset the transport to send state
http_info->transport_state = TRANSPORT_CLIENT_STATE_TRANSIENT;
}
else
{
LogError("Failure status code sent from the server: %u", status_code);
@ -959,6 +966,14 @@ void prov_transport_http_dowork(PROV_DEVICE_TRANSPORT_HANDLE handle)
break;
}
case TRANSPORT_CLIENT_STATE_TRANSIENT:
if (http_info->status_cb != NULL)
{
http_info->status_cb(PROV_DEVICE_TRANSPORT_STATUS_TRANSIENT, http_info->status_ctx);
}
http_info->transport_state = TRANSPORT_CLIENT_STATE_IDLE;
break;
case TRANSPORT_CLIENT_STATE_ERROR:
/* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_039: [ If the state is Error, prov_transport_http_dowork shall call the registration_data callback with PROV_DEVICE_TRANSPORT_RESULT_ERROR and NULL payload_data. ] */
http_info->register_data_cb(PROV_DEVICE_TRANSPORT_RESULT_ERROR, NULL, NULL, NULL, http_info->user_ctx);

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

@ -30,6 +30,8 @@ static const char* MQTT_USERNAME_FMT = "%s/registrations/%s/api-version=%s&Clien
static const char* MQTT_REGISTER_MESSAGE_FMT = "$dps/registrations/PUT/iotdps-register/?$rid=%d";
static const char* MQTT_STATUS_MESSAGE_FMT = "$dps/registrations/GET/iotdps-get-operationstatus/?$rid=%d&operationId=%s";
static const char* MQTT_TOPIC_STATUS_PREFIX = "$dps/registrations/res/";
typedef enum MQTT_TRANSPORT_STATE_TAG
{
MQTT_STATE_IDLE,
@ -55,6 +57,7 @@ typedef enum PROV_TRANSPORT_STATE_TAG
TRANSPORT_CLIENT_STATE_STATUS_SENT,
TRANSPORT_CLIENT_STATE_STATUS_RECV,
TRANSPORT_CLIENT_STATE_TRANSIENT,
TRANSPORT_CLIENT_STATE_ERROR
} PROV_TRANSPORT_STATE;
@ -265,41 +268,69 @@ static void mqtt_notification_callback(MQTT_MESSAGE_HANDLE handle, void* user_ct
{
PROV_TRANSPORT_MQTT_INFO* mqtt_info = (PROV_TRANSPORT_MQTT_INFO*)user_ctx;
const APP_PAYLOAD* payload = mqttmessage_getApplicationMsg(handle);
if (payload != NULL)
bool is_transient_error = false;
const char* topic_resp = mqttmessage_getTopicName(handle);
if (topic_resp != NULL)
{
if (mqtt_info->payload_data != NULL)
// Extract the registration status
size_t status_pos = strlen(MQTT_TOPIC_STATUS_PREFIX);
if (memcmp(MQTT_TOPIC_STATUS_PREFIX, topic_resp, status_pos) == 0)
{
free(mqtt_info->payload_data);
mqtt_info->payload_data = NULL;
}
if ((mqtt_info->payload_data = malloc(payload->length + 1)) == NULL)
{
LogError("failure allocating payload data");
mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
mqtt_info->mqtt_state = MQTT_STATE_ERROR;
}
else
{
memset(mqtt_info->payload_data, 0, payload->length + 1);
memcpy(mqtt_info->payload_data, payload->message, payload->length);
if (mqtt_info->transport_state == TRANSPORT_CLIENT_STATE_REG_SENT)
// If the status code is > 429 then this is a transient error
long status_code = atol(topic_resp + status_pos);
if (status_code > PROV_STATUS_CODE_TRANSIENT_ERROR)
{
mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_REG_RECV;
}
else
{
mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_STATUS_RECV;
// On transient error reset the transport to send state
mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_TRANSIENT;
is_transient_error = true;
}
}
}
else
{
LogError("failure NULL message encountered from umqtt");
LogError("failure topic name is NULL");
mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
mqtt_info->mqtt_state = MQTT_STATE_ERROR;
}
if (!is_transient_error)
{
const APP_PAYLOAD* payload = mqttmessage_getApplicationMsg(handle);
if (payload != NULL)
{
if (mqtt_info->payload_data != NULL)
{
free(mqtt_info->payload_data);
mqtt_info->payload_data = NULL;
}
if ((mqtt_info->payload_data = malloc(payload->length + 1)) == NULL)
{
LogError("failure allocating payload data");
mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
mqtt_info->mqtt_state = MQTT_STATE_ERROR;
}
else
{
memset(mqtt_info->payload_data, 0, payload->length + 1);
memcpy(mqtt_info->payload_data, payload->message, payload->length);
if (mqtt_info->transport_state == TRANSPORT_CLIENT_STATE_REG_SENT)
{
mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_REG_RECV;
}
else
{
mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_STATUS_RECV;
}
}
}
else
{
LogError("failure NULL message encountered from umqtt");
mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
mqtt_info->mqtt_state = MQTT_STATE_ERROR;
}
}
}
else
{
@ -935,6 +966,8 @@ void prov_transport_common_mqtt_dowork(PROV_DEVICE_TRANSPORT_HANDLE handle)
mqtt_info->register_data_cb(PROV_DEVICE_TRANSPORT_RESULT_OK, parse_info->authorization_key, parse_info->iothub_uri, parse_info->device_id, mqtt_info->user_ctx);
mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_IDLE;
break;
case PROV_DEVICE_TRANSPORT_STATUS_TRANSIENT:
break;
case PROV_DEVICE_TRANSPORT_STATUS_ERROR:
default:
/* Tests_PROV_TRANSPORT_MQTT_COMMON_07_049: [ If any error is encountered prov_transport_common_mqtt_dowork shall set the mqtt_state to MQTT_STATE_ERROR and the transport_state to TRANSPORT_CLIENT_STATE_ERROR. ] */
@ -948,6 +981,13 @@ void prov_transport_common_mqtt_dowork(PROV_DEVICE_TRANSPORT_HANDLE handle)
}
break;
}
case TRANSPORT_CLIENT_STATE_TRANSIENT:
if (mqtt_info->status_cb != NULL)
{
mqtt_info->status_cb(PROV_DEVICE_TRANSPORT_STATUS_TRANSIENT, mqtt_info->status_ctx);
}
mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_IDLE;
break;
case TRANSPORT_CLIENT_STATE_ERROR:
/* Codes_PROV_TRANSPORT_MQTT_COMMON_07_057: [ If transport_state is set to TRANSPORT_CLIENT_STATE_ERROR, prov_transport_common_mqtt_dowork shall call the register_data_cb function with PROV_DEVICE_TRANSPORT_RESULT_ERROR setting the transport_state to TRANSPORT_CLIENT_STATE_IDLE ] */

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

@ -1065,6 +1065,27 @@ BEGIN_TEST_SUITE(prov_transport_http_client_ut)
prov_dev_http_transport_destroy(handle);
}
TEST_FUNCTION(prov_transport_http_reply_recv_transient_error_succeed)
{
//arrange
PROV_DEVICE_TRANSPORT_HANDLE handle = prov_dev_http_transport_create(TEST_URI_VALUE, TRANSPORT_HSM_TYPE_TPM, TEST_SCOPE_ID_VALUE, TEST_DPS_API_VALUE);
(void)prov_dev_http_transport_open(handle, TEST_REGISTRATION_ID_VALUE, TEST_BUFFER_VALUE, TEST_BUFFER_VALUE, on_transport_register_data_cb, NULL, on_transport_status_cb, NULL);
(void)prov_dev_http_transport_register_device(handle, on_transport_challenge_callback, NULL, on_transport_json_parse, NULL);
g_on_http_open(g_http_open_ctx, HTTP_CALLBACK_REASON_OK);
prov_dev_http_transport_dowork(handle);
umock_c_reset_all_calls();
//act
g_on_http_reply_recv(g_http_execute_ctx, HTTP_CALLBACK_REASON_OK, (const unsigned char*)TEST_JSON_CONTENT, TEST_JSON_CONTENT_LEN, TEST_FAILURE_STATUS_CODE, TEST_HTTP_HANDLE_VALUE);
//assert
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
//cleanup
(void)prov_dev_http_transport_close(handle);
prov_dev_http_transport_destroy(handle);
}
/* Tests_PROV_TRANSPORT_HTTP_CLIENT_07_029: [ If the argument handle, or operation_id is NULL, prov_transport_http_get_operation_status shall return a non-zero value. ] */
TEST_FUNCTION(prov_transport_http_get_operation_status_handle_NULL_fail)
{

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

@ -1218,6 +1218,7 @@ BEGIN_TEST_SUITE(prov_transport_mqtt_common_ut)
umock_c_reset_all_calls();
//arrange
STRICT_EXPECTED_CALL(mqttmessage_getTopicName(IGNORED_PTR_ARG));
STRICT_EXPECTED_CALL(mqttmessage_getApplicationMsg(IGNORED_PTR_ARG));
STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG));
@ -1232,6 +1233,114 @@ BEGIN_TEST_SUITE(prov_transport_mqtt_common_ut)
prov_transport_common_mqtt_destroy(handle);
}
TEST_FUNCTION(prov_transport_common_mqtt_dowork_register_recv_app_msg_NULL_fail)
{
CONNECT_ACK connack = { true, CONNECTION_ACCEPTED };
QOS_VALUE QosValue[] = { DELIVER_AT_LEAST_ONCE };
SUBSCRIBE_ACK suback;
suback.packetId = 1234;
suback.qosCount = 1;
suback.qosReturn = QosValue;
PROV_DEVICE_TRANSPORT_HANDLE handle = prov_transport_common_mqtt_create(TEST_URI_VALUE, TRANSPORT_HSM_TYPE_X509, TEST_SCOPE_ID_VALUE, TEST_DPS_API_VALUE, on_mqtt_transport_io);
(void)prov_transport_common_mqtt_x509_cert(handle, TEST_X509_CERT_VALUE, TEST_PRIVATE_KEY_VALUE);
(void)prov_transport_common_mqtt_open(handle, TEST_REGISTRATION_ID_VALUE, TEST_BUFFER_VALUE, TEST_BUFFER_VALUE, on_transport_register_data_cb, NULL, on_transport_status_cb, NULL);
(void)prov_transport_common_mqtt_register_device(handle, on_transport_challenge_callback, NULL, on_transport_json_parse, NULL);
prov_transport_common_mqtt_dowork(handle);
g_operation_cb(TEST_MQTT_CLIENT_HANDLE, MQTT_CLIENT_ON_CONNACK, &connack, g_msg_recv_callback_context);
prov_transport_common_mqtt_dowork(handle);
g_operation_cb(TEST_MQTT_CLIENT_HANDLE, MQTT_CLIENT_ON_SUBSCRIBE_ACK, &suback, g_msg_recv_callback_context);
prov_transport_common_mqtt_dowork(handle);
umock_c_reset_all_calls();
//arrange
STRICT_EXPECTED_CALL(mqttmessage_getTopicName(IGNORED_PTR_ARG));
STRICT_EXPECTED_CALL(mqttmessage_getApplicationMsg(IGNORED_PTR_ARG)).SetReturn(NULL);
//act
g_on_msg_recv(TEST_MQTT_MESSAGE, g_msg_recv_callback_context);
//assert
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
//cleanup
prov_transport_common_mqtt_close(handle);
prov_transport_common_mqtt_destroy(handle);
}
TEST_FUNCTION(prov_transport_common_mqtt_dowork_register_recv_malloc_NULL_fail)
{
CONNECT_ACK connack = { true, CONNECTION_ACCEPTED };
QOS_VALUE QosValue[] = { DELIVER_AT_LEAST_ONCE };
SUBSCRIBE_ACK suback;
suback.packetId = 1234;
suback.qosCount = 1;
suback.qosReturn = QosValue;
PROV_DEVICE_TRANSPORT_HANDLE handle = prov_transport_common_mqtt_create(TEST_URI_VALUE, TRANSPORT_HSM_TYPE_X509, TEST_SCOPE_ID_VALUE, TEST_DPS_API_VALUE, on_mqtt_transport_io);
(void)prov_transport_common_mqtt_x509_cert(handle, TEST_X509_CERT_VALUE, TEST_PRIVATE_KEY_VALUE);
(void)prov_transport_common_mqtt_open(handle, TEST_REGISTRATION_ID_VALUE, TEST_BUFFER_VALUE, TEST_BUFFER_VALUE, on_transport_register_data_cb, NULL, on_transport_status_cb, NULL);
(void)prov_transport_common_mqtt_register_device(handle, on_transport_challenge_callback, NULL, on_transport_json_parse, NULL);
prov_transport_common_mqtt_dowork(handle);
g_operation_cb(TEST_MQTT_CLIENT_HANDLE, MQTT_CLIENT_ON_CONNACK, &connack, g_msg_recv_callback_context);
prov_transport_common_mqtt_dowork(handle);
g_operation_cb(TEST_MQTT_CLIENT_HANDLE, MQTT_CLIENT_ON_SUBSCRIBE_ACK, &suback, g_msg_recv_callback_context);
prov_transport_common_mqtt_dowork(handle);
umock_c_reset_all_calls();
//arrange
STRICT_EXPECTED_CALL(mqttmessage_getTopicName(IGNORED_PTR_ARG));
STRICT_EXPECTED_CALL(mqttmessage_getApplicationMsg(IGNORED_PTR_ARG));
STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)).SetReturn(NULL);
//act
g_on_msg_recv(TEST_MQTT_MESSAGE, g_msg_recv_callback_context);
//assert
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
//cleanup
prov_transport_common_mqtt_close(handle);
prov_transport_common_mqtt_destroy(handle);
}
TEST_FUNCTION(prov_transport_common_mqtt_dowork_register_recv_transient_error_succeed)
{
CONNECT_ACK connack = { true, CONNECTION_ACCEPTED };
QOS_VALUE QosValue[] = { DELIVER_AT_LEAST_ONCE };
SUBSCRIBE_ACK suback;
suback.packetId = 1234;
suback.qosCount = 1;
suback.qosReturn = QosValue;
PROV_DEVICE_TRANSPORT_HANDLE handle = prov_transport_common_mqtt_create(TEST_URI_VALUE, TRANSPORT_HSM_TYPE_X509, TEST_SCOPE_ID_VALUE, TEST_DPS_API_VALUE, on_mqtt_transport_io);
(void)prov_transport_common_mqtt_x509_cert(handle, TEST_X509_CERT_VALUE, TEST_PRIVATE_KEY_VALUE);
(void)prov_transport_common_mqtt_open(handle, TEST_REGISTRATION_ID_VALUE, TEST_BUFFER_VALUE, TEST_BUFFER_VALUE, on_transport_register_data_cb, NULL, on_transport_status_cb, NULL);
(void)prov_transport_common_mqtt_register_device(handle, on_transport_challenge_callback, NULL, on_transport_json_parse, NULL);
prov_transport_common_mqtt_dowork(handle);
g_operation_cb(TEST_MQTT_CLIENT_HANDLE, MQTT_CLIENT_ON_CONNACK, &connack, g_msg_recv_callback_context);
prov_transport_common_mqtt_dowork(handle);
g_operation_cb(TEST_MQTT_CLIENT_HANDLE, MQTT_CLIENT_ON_SUBSCRIBE_ACK, &suback, g_msg_recv_callback_context);
prov_transport_common_mqtt_dowork(handle);
umock_c_reset_all_calls();
//arrange
STRICT_EXPECTED_CALL(mqttmessage_getTopicName(IGNORED_PTR_ARG)).SetReturn("$dps/registrations/res/500/?$rid=1");
STRICT_EXPECTED_CALL(mqtt_client_dowork(IGNORED_PTR_ARG));
STRICT_EXPECTED_CALL(on_transport_status_cb(PROV_DEVICE_TRANSPORT_STATUS_TRANSIENT, IGNORED_PTR_ARG));
//act
g_on_msg_recv(TEST_MQTT_MESSAGE, g_msg_recv_callback_context);
prov_transport_common_mqtt_dowork(handle);
//assert
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
//cleanup
prov_transport_common_mqtt_close(handle);
prov_transport_common_mqtt_destroy(handle);
}
/* Tests_PROV_TRANSPORT_MQTT_COMMON_07_054: [ Upon successful sending of a TRANSPORT_CLIENT_STATE_REG_SEND message, prov_transport_common_mqtt_dowork shall set the transport_state to TRANSPORT_CLIENT_STATE_REG_SENT ] */
TEST_FUNCTION(prov_transport_common_mqtt_dowork_register_recv_assigned_succeed)
{
@ -1312,6 +1421,48 @@ BEGIN_TEST_SUITE(prov_transport_mqtt_common_ut)
prov_transport_common_mqtt_destroy(handle);
}
TEST_FUNCTION(prov_transport_common_mqtt_dowork_send_status_transient_error_succeed)
{
PROV_DEVICE_TRANSPORT_HANDLE handle;
CONNECT_ACK connack = { true, CONNECTION_ACCEPTED };
QOS_VALUE QosValue[] = { DELIVER_AT_LEAST_ONCE };
SUBSCRIBE_ACK suback;
suback.packetId = 1234;
suback.qosCount = 1;
suback.qosReturn = QosValue;
handle = prov_transport_common_mqtt_create(TEST_URI_VALUE, TRANSPORT_HSM_TYPE_X509, TEST_SCOPE_ID_VALUE, TEST_DPS_API_VALUE, on_mqtt_transport_io);
(void)prov_transport_common_mqtt_x509_cert(handle, TEST_X509_CERT_VALUE, TEST_PRIVATE_KEY_VALUE);
(void)prov_transport_common_mqtt_open(handle, TEST_REGISTRATION_ID_VALUE, TEST_BUFFER_VALUE, TEST_BUFFER_VALUE, on_transport_register_data_cb, NULL, on_transport_status_cb, NULL);
(void)prov_transport_common_mqtt_register_device(handle, on_transport_challenge_callback, NULL, on_transport_json_parse, NULL);
prov_transport_common_mqtt_dowork(handle);
g_operation_cb(TEST_MQTT_CLIENT_HANDLE, MQTT_CLIENT_ON_CONNACK, &connack, g_msg_recv_callback_context);
prov_transport_common_mqtt_dowork(handle);
g_operation_cb(TEST_MQTT_CLIENT_HANDLE, MQTT_CLIENT_ON_SUBSCRIBE_ACK, &suback, g_msg_recv_callback_context);
prov_transport_common_mqtt_dowork(handle);
g_on_msg_recv(TEST_MQTT_MESSAGE, g_msg_recv_callback_context);
g_target_transport_status = PROV_DEVICE_TRANSPORT_STATUS_ASSIGNING;
prov_transport_common_mqtt_dowork(handle);
(void)prov_transport_common_mqtt_get_operation_status(handle);
umock_c_reset_all_calls();
//arrange
STRICT_EXPECTED_CALL(mqttmessage_getTopicName(IGNORED_PTR_ARG)).SetReturn("$dps/registrations/res/500/?$rid=1");
STRICT_EXPECTED_CALL(mqtt_client_dowork(IGNORED_PTR_ARG));
STRICT_EXPECTED_CALL(on_transport_status_cb(PROV_DEVICE_TRANSPORT_STATUS_TRANSIENT, IGNORED_PTR_ARG));
//act
g_on_msg_recv(TEST_MQTT_MESSAGE, g_msg_recv_callback_context);
prov_transport_common_mqtt_dowork(handle);
//assert
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
//cleanup
prov_transport_common_mqtt_close(handle);
prov_transport_common_mqtt_destroy(handle);
}
/* Tests_PROV_TRANSPORT_MQTT_COMMON_07_023: [ If handle is NULL, prov_transport_common_mqtt_set_trace shall return a non-zero value. ] */
TEST_FUNCTION(prov_transport_common_mqtt_set_trace_handle_NULL_fail)
{